Implement liveness analysis
This commit is contained in:
parent
bbacc928ae
commit
2f9d42d4ad
1 changed files with 141 additions and 0 deletions
|
|
@ -0,0 +1,141 @@
|
|||
package edu.kit.kastel.vads.compiler.backend.x86asm;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import edu.kit.kastel.vads.compiler.backend.regalloc.Register;
|
||||
import edu.kit.kastel.vads.compiler.backend.regalloc.RegisterAllocator;
|
||||
import edu.kit.kastel.vads.compiler.ir.IrGraph;
|
||||
import edu.kit.kastel.vads.compiler.ir.node.BinaryOperationNode;
|
||||
import edu.kit.kastel.vads.compiler.ir.node.Block;
|
||||
import edu.kit.kastel.vads.compiler.ir.node.ConstIntNode;
|
||||
import edu.kit.kastel.vads.compiler.ir.node.Node;
|
||||
import edu.kit.kastel.vads.compiler.ir.node.ProjNode;
|
||||
import edu.kit.kastel.vads.compiler.ir.node.ReturnNode;
|
||||
import edu.kit.kastel.vads.compiler.ir.node.StartNode;
|
||||
|
||||
public class X68RegisterAllocator implements RegisterAllocator {
|
||||
|
||||
private class InterferenceGraph {
|
||||
|
||||
}
|
||||
|
||||
private final Map<Node, Set<Node>> temps;
|
||||
private int nextTemp;
|
||||
|
||||
public X68RegisterAllocator() {
|
||||
temps = new HashMap<>();
|
||||
nextTemp = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Node, Register> allocateRegisters(IrGraph graph) {
|
||||
analyseLive(graph);
|
||||
|
||||
System.out.println("=====");
|
||||
printTemps();
|
||||
throw new UnsupportedOperationException();
|
||||
//InterferenceGraph interference = buildInterferenceGraph(temps);
|
||||
//return allocateRegisters(interference);
|
||||
}
|
||||
|
||||
private void analyseLive(IrGraph graph) {
|
||||
boolean change = false;
|
||||
do {
|
||||
change = analyseLiveSinglePass(graph.endBlock(), new HashSet<>());
|
||||
} while (change);
|
||||
}
|
||||
|
||||
private boolean analyseLiveSinglePass(Node node, Set<Node> visited) {
|
||||
boolean changed = false;
|
||||
|
||||
if (needsRegister(node)) {
|
||||
// Get Live Out of node
|
||||
Set<Node> liveOut = temps.getOrDefault(node, Set.of());
|
||||
|
||||
Set<Node> kill = getKillOf(node);
|
||||
Set<Node> gen = getGenOf(node);
|
||||
|
||||
Set<Node> liveIn = new HashSet<>(liveOut);
|
||||
liveIn.removeAll(kill);
|
||||
liveIn.addAll(gen);
|
||||
|
||||
Set<Node> old = temps.put(node, liveIn);
|
||||
changed |= old == null || !old.equals(liveIn);
|
||||
|
||||
//if (changed) {
|
||||
System.out.println("Node " + node);
|
||||
System.out.println("Out: " + Arrays.toString(liveOut.toArray()));
|
||||
System.out.println("Kill: " + Arrays.toString(kill.toArray()));
|
||||
System.out.println("Gen: " + Arrays.toString(gen.toArray()));
|
||||
System.out.println("In: " + Arrays.toString(liveIn.toArray()));
|
||||
System.out.println();
|
||||
//printTemps();
|
||||
//System.out.println();
|
||||
//}
|
||||
|
||||
}
|
||||
|
||||
for (Node predecessor : node.predecessors()) {
|
||||
if (visited.add(predecessor)) {
|
||||
changed |= analyseLiveSinglePass(predecessor, visited);
|
||||
}
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
private Set<Node> getSuccessors(Node node) {
|
||||
return node.graph().successors(node);
|
||||
}
|
||||
|
||||
private InterferenceGraph buildInterferenceGraph(Map<Node, Set<Node>> temps) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'buildInterferenceGraph'");
|
||||
}
|
||||
|
||||
private Map<Node, Register> allocateRegisters(InterferenceGraph graph) {
|
||||
// TODO Auto-generated method stub
|
||||
throw new UnsupportedOperationException("Unimplemented method 'allocateRegisters'");
|
||||
}
|
||||
|
||||
private static boolean needsRegister(Node node) {
|
||||
return !(node instanceof ProjNode || node instanceof StartNode || node instanceof Block);
|
||||
}
|
||||
|
||||
private Set<Node> getKillOf(Node node) {
|
||||
return switch (node) {
|
||||
case BinaryOperationNode bin -> Set.of(bin);
|
||||
case ConstIntNode c -> Set.of(c);
|
||||
case ReturnNode _ -> Set.of();
|
||||
default -> throw new UnsupportedOperationException("No 'kill' set for " + node + "implemented.");
|
||||
};
|
||||
}
|
||||
|
||||
private Set<Node> getGenOf(Node node) {
|
||||
return switch (node) {
|
||||
// TODO special case div/mod
|
||||
case BinaryOperationNode bin -> Set.of(bin.predecessor(BinaryOperationNode.LEFT), bin.predecessor(BinaryOperationNode.RIGHT));
|
||||
case ConstIntNode _ -> Set.of();
|
||||
case ReturnNode ret -> Set.of(ret.predecessor(ReturnNode.RESULT));
|
||||
default -> throw new UnsupportedOperationException("No 'kill' set for " + node + "implemented.");
|
||||
};
|
||||
}
|
||||
|
||||
private void printTemps() {
|
||||
|
||||
for (Entry<Node, Set<Node>> e : temps.entrySet()) {
|
||||
//System.out.println(e.getValue().size());
|
||||
System.out.println(e.getKey() + ": " + e.getValue().stream().map(r -> String.valueOf(r.hashCode())).collect(Collectors.joining(", ")));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue