Skip to content

Commit e1efd56

Browse files
committed
Working on DFS / Scheduling
1 parent 7f4c44e commit e1efd56

17 files changed

Lines changed: 282 additions & 104 deletions

src/main/java/de/mirkosertic/metair/ir/ControlFlowUse.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
public class ControlFlowUse extends Use {
44

5-
public final ControlType type;
5+
public final FlowType type;
66

7-
ControlFlowUse(final ControlType type) {
7+
ControlFlowUse(final FlowType type) {
88
this.type = type;
99
}
1010
}

src/main/java/de/mirkosertic/metair/ir/DFS.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public DFS(final Node startNode) {
2525
for (final Node user : currentNode.usedBy) {
2626
for (final Node.UseEdge edge : user.uses) {
2727
if (edge.node() == currentNode) {
28-
if (edge.use() instanceof final ControlFlowUse cfu && cfu.type == ControlType.FORWARD) {
28+
if (edge.use() instanceof final ControlFlowUse cfu && cfu.type == FlowType.FORWARD) {
2929
final Set<Node> preds = predecessorsOf(user);
3030
if (marked.containsAll(preds)) {
3131
//System.out.println("All predecessors of node " + currentNode + " visited, continuing");
@@ -93,7 +93,7 @@ private Set<Node> predecessorsOf(final Node node) {
9393
final Set<Node> predecessors = new HashSet<>();
9494
for (final Node.UseEdge edge : node.uses) {
9595
if (edge.use() instanceof final ControlFlowUse cfu) {
96-
if (cfu.type == ControlType.FORWARD) {
96+
if (cfu.type == FlowType.FORWARD) {
9797
predecessors.add(edge.node());
9898
}
9999
} else predecessors.add(edge.node());
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
package de.mirkosertic.metair.ir;
2+
3+
import java.util.ArrayList;
4+
import java.util.Comparator;
5+
import java.util.HashMap;
6+
import java.util.HashSet;
7+
import java.util.List;
8+
import java.util.Map;
9+
import java.util.Set;
10+
11+
public class DFS2 {
12+
13+
private final List<Node> nodesInOrder;
14+
private final List<Node> workList;
15+
private final Set<Node> visited;
16+
private final Map<Node, Set<Node>> precomputedPredecessors;
17+
private final Map<Node, List<Node>> precomputedForwards;
18+
19+
public DFS2(final Node node) {
20+
21+
this.nodesInOrder = new ArrayList<>();
22+
this.workList = new ArrayList<>();
23+
this.visited = new HashSet<>();
24+
this.precomputedPredecessors = new HashMap<>();
25+
this.precomputedForwards = new HashMap<>();
26+
27+
long safelock = 0;
28+
29+
workList.add(node);
30+
listhandling: while (!workList.isEmpty()) {
31+
safelock++;
32+
if (safelock > 1000) {
33+
throw new IllegalStateException("Unschedulable IR detected!");
34+
}
35+
36+
for (final Node currentNode : workList) {
37+
if (check(currentNode)) continue listhandling;
38+
}
39+
}
40+
}
41+
42+
private boolean check(final Node currentNode) {
43+
final Set<Node> predecessors = precomputedPredecessors.computeIfAbsent(currentNode, this::predecessorsOf);
44+
45+
if (visited.containsAll(predecessors)) {
46+
// All predecessors are fully resolved, we can continue resolving this node
47+
48+
nodesInOrder.add(currentNode);
49+
50+
visited.add(currentNode);
51+
52+
final List<Node> forwardNodes = getForwardNodesFor(currentNode);
53+
54+
if (forwardNodes.isEmpty()) {
55+
workList.remove(currentNode);
56+
return true;
57+
} else {
58+
// TODO: Sort the nodes by their usage, with control flow use first, then data flow, then arg-flow, and then define flow
59+
forwardNodes.sort(Comparator.comparing(o -> o.getClass().getSimpleName()));
60+
for (final Node forwardNode : forwardNodes) {
61+
if (!workList.contains(forwardNode) && !visited.contains(forwardNode)) {
62+
workList.add(forwardNode);
63+
}
64+
}
65+
66+
workList.remove(currentNode);
67+
68+
return true;
69+
}
70+
}
71+
return false;
72+
}
73+
74+
private List<Node> getForwardNodesFor(final Node currentNode) {
75+
return precomputedForwards.computeIfAbsent(currentNode, key -> {
76+
final List<Node> forwardNodes = new ArrayList<>();
77+
for (final Node user : key.usedBy) {
78+
for (final Node.UseEdge edge : user.uses) {
79+
if (edge.node() == key) {
80+
if (edge.use() instanceof final ControlFlowUse cfu && cfu.type == FlowType.FORWARD) {
81+
forwardNodes.add(user);
82+
} else if (edge.use() instanceof final PHIUse pu && pu.type == FlowType.FORWARD) {
83+
forwardNodes.add(user);
84+
} else if (edge.use() instanceof DefinedByUse) {
85+
forwardNodes.add(user);
86+
} else if (edge.use() instanceof DataFlowUse) {
87+
forwardNodes.add(user);
88+
} else if (edge.use() instanceof MemoryUse) {
89+
forwardNodes.add(user);
90+
}
91+
}
92+
}
93+
}
94+
return forwardNodes;
95+
});
96+
}
97+
98+
public List<Node> getTopologicalOrder() {
99+
return nodesInOrder;
100+
}
101+
102+
private Set<Node> predecessorsOf(final Node node) {
103+
final Set<Node> predecessors = new HashSet<>();
104+
for (final Node.UseEdge edge : node.uses) {
105+
if (edge.use() instanceof final ControlFlowUse cfu) {
106+
if (cfu.type == FlowType.FORWARD) {
107+
predecessors.add(edge.node());
108+
}
109+
} else if (edge.use() instanceof final PHIUse pu) {
110+
if (pu.type == FlowType.FORWARD) {
111+
predecessors.add(edge.node());
112+
}
113+
} else predecessors.add(edge.node());
114+
}
115+
return predecessors;
116+
}
117+
}

src/main/java/de/mirkosertic/metair/ir/DOTExporter.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public static void writeTo(final Method method, final PrintStream ps) {
2727
final List<Node> nodeindex = new ArrayList<>();
2828
nodeindex.add(method);
2929

30-
for (final Node node : new DFS(method).getTopologicalOrder()) {
30+
for (final Node node : new DFS2(method).getTopologicalOrder()) {
3131
if (!nodeindex.contains(node)) {
3232
nodeindex.add(node);
3333
}
@@ -115,6 +115,9 @@ public static void writeTo(final Method method, final PrintStream ps) {
115115
if (useEdge.use() instanceof final PHIUse phiUse) {
116116
ps.print("[");
117117
ps.print("headlabel=\"if #" + nodeindex.indexOf(phiUse.origin) + "\", labeldistance=2, color=blue, constraint=false");
118+
if (phiUse.type == FlowType.BACKWARD) {
119+
ps.print(", style=dashed");
120+
}
118121
ps.print("]");
119122
} else if (useEdge.use() instanceof MemoryUse) {
120123
ps.print("[labeldistance=2, color=green, constraint=false]");
@@ -126,7 +129,7 @@ public static void writeTo(final Method method, final PrintStream ps) {
126129
ps.print("[style=dotted]");
127130
} else if (useEdge.use() instanceof final ControlFlowUse cfu) {
128131
ps.print("[labeldistance=2, color=red, fontcolor=red");
129-
if (cfu.type == ControlType.BACKWARD) {
132+
if (cfu.type == FlowType.BACKWARD) {
130133
ps.print(", style=dashed");
131134
}
132135
ps.print("]");
@@ -254,7 +257,7 @@ public static void writeTo(final DominatorTree tree, final PrintStream ps) {
254257
ps.print("]");
255258
} else if (useEdge.use() instanceof final ControlFlowUse cfu) {
256259
ps.print("[labeldistance=2, color=red, fontcolor=red");
257-
if (cfu.type == ControlType.BACKWARD) {
260+
if (cfu.type == FlowType.BACKWARD) {
258261
ps.print(", style=dashed");
259262
}
260263
ps.print("]");
@@ -335,7 +338,7 @@ public static void writeBytecodeCFGTo(final MethodAnalyzer analyzer, final Print
335338
ps.print(" -> node");
336339
ps.print(elementIndex);
337340
ps.print("[color=red");
338-
if (edge.controlType() == ControlType.BACKWARD) {
341+
if (edge.flowType() == FlowType.BACKWARD) {
339342
ps.print(", style=dotted");
340343
}
341344
ps.println("];");

src/main/java/de/mirkosertic/metair/ir/DominatorTree.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public class DominatorTree {
1717
final List<Node> rpo;
1818

1919
public DominatorTree(final Node start) {
20-
preOrder = new DFS(start).getTopologicalOrder();
20+
preOrder = new DFS2(start).getTopologicalOrder();
2121
idom = new HashMap<>();
2222
rpo = new ArrayList<>();
2323
computeDominators();
@@ -39,7 +39,7 @@ private void computeRPO(final Node current, final List<Node> finished, final Set
3939
for (final Node.UseEdge edge : user.uses) {
4040
if (edge.node() == current) {
4141
if (edge.use() instanceof final ControlFlowUse cfu) {
42-
if (cfu.type == ControlType.FORWARD) {
42+
if (cfu.type == FlowType.FORWARD) {
4343
computeRPO(user, finished, visited);
4444
}
4545
} else {

src/main/java/de/mirkosertic/metair/ir/ExceptionGuard.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@ public record Catches(Optional<ClassDesc> catchType) {
1515
if (catchEntry.catchType().isPresent()) {
1616
final ClassDesc catchType = catchEntry.catchType().get();
1717

18-
registerAs("catch:" + i + ":" + catchEntry.catchType().get().descriptorString(), controlFlowsTo(new CatchProjection(i, catchType), ControlType.FORWARD).controlFlowsTo(new Catch(catchType, this), ControlType.FORWARD));
18+
registerAs("catch:" + i + ":" + catchEntry.catchType().get().descriptorString(), controlFlowsTo(new CatchProjection(i, catchType), FlowType.FORWARD).controlFlowsTo(new Catch(catchType, this), FlowType.FORWARD));
1919
} else {
20-
registerAs("catch:" + i + ":any", controlFlowsTo(new CatchProjection(i), ControlType.FORWARD).controlFlowsTo(new Catch(ClassDesc.of(Throwable.class.getName()), this), ControlType.FORWARD));
20+
registerAs("catch:" + i + ":any", controlFlowsTo(new CatchProjection(i), FlowType.FORWARD).controlFlowsTo(new Catch(ClassDesc.of(Throwable.class.getName()), this), FlowType.FORWARD));
2121
}
2222
}
23-
registerAs("default", controlFlowsTo(new ExtractControlFlowProjection("default"), ControlType.FORWARD));
24-
registerAs("exit", controlFlowsTo(new ExtractControlFlowProjection("exit"), ControlType.FORWARD));
23+
registerAs("default", controlFlowsTo(new ExtractControlFlowProjection("default"), FlowType.FORWARD));
24+
registerAs("exit", controlFlowsTo(new ExtractControlFlowProjection("exit"), FlowType.FORWARD));
2525
}
2626

2727
public Node exitNode() {

src/main/java/de/mirkosertic/metair/ir/ControlType.java renamed to src/main/java/de/mirkosertic/metair/ir/FlowType.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
package de.mirkosertic.metair.ir;
22

3-
public enum ControlType {
3+
public enum FlowType {
44
FORWARD, BACKWARD
55
}

src/main/java/de/mirkosertic/metair/ir/If.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ public class If extends ConditionalNode {
88
If(final Value condition) {
99
use(condition, new ArgumentUse(0));
1010

11-
registerAs(TRUE, controlFlowsTo(new ExtractControlFlowProjection(TRUE), ControlType.FORWARD));
12-
registerAs(FALSE, controlFlowsTo(new ExtractControlFlowProjection(FALSE), ControlType.FORWARD));
11+
registerAs(TRUE, controlFlowsTo(new ExtractControlFlowProjection(TRUE), FlowType.FORWARD));
12+
registerAs(FALSE, controlFlowsTo(new ExtractControlFlowProjection(FALSE), FlowType.FORWARD));
1313
}
1414

1515
@Override

src/main/java/de/mirkosertic/metair/ir/LookupSwitch.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@ public class LookupSwitch extends TupleNode {
2020
this.defaultLabel = defaultLabel;
2121

2222
for (int i = 0; i < cases.size(); i++) {
23-
registerAs("case" + i, controlFlowsTo(new ExtractControlFlowProjection("case" + i), ControlType.FORWARD));
23+
registerAs("case" + i, controlFlowsTo(new ExtractControlFlowProjection("case" + i), FlowType.FORWARD));
2424
}
2525

26-
registerAs("default", controlFlowsTo(new ExtractControlFlowProjection("default"), ControlType.FORWARD));
26+
registerAs("default", controlFlowsTo(new ExtractControlFlowProjection("default"), FlowType.FORWARD));
2727
}
2828

2929
@Override

0 commit comments

Comments
 (0)