diff options
| author | Thalia Archibald <thalia@archibald.dev> | 2024-06-21 06:13:09 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-06-21 14:13:09 +0100 |
| commit | e5f4f7b85fbb91a293a7d89d7b85adfbaeeb51f4 (patch) | |
| tree | 9b6ecc7ef37b1ec7f08efed6f908f478dc551e03 /chapter08/src/main/java/com/seaofnodes | |
| parent | a749c244bea3e2774d453165cbd18ed52863a8f5 (diff) | |
| download | Simple-e5f4f7b85fbb91a293a7d89d7b85adfbaeeb51f4.tar.gz Simple-e5f4f7b85fbb91a293a7d89d7b85adfbaeeb51f4.zip | |
Format whitespace (#86)
* Trim trailing whitespace
* Ensure final new lines
* Convert line endings from CRLF to LF
* Replace tabs with spaces
Diffstat (limited to 'chapter08/src/main/java/com/seaofnodes')
26 files changed, 271 insertions, 271 deletions
diff --git a/chapter08/src/main/java/com/seaofnodes/simple/GraphEvaluator.java b/chapter08/src/main/java/com/seaofnodes/simple/GraphEvaluator.java index b89189f5..f5694a78 100644 --- a/chapter08/src/main/java/com/seaofnodes/simple/GraphEvaluator.java +++ b/chapter08/src/main/java/com/seaofnodes/simple/GraphEvaluator.java @@ -1,181 +1,181 @@ -package com.seaofnodes.simple;
-
-import com.seaofnodes.simple.node.*;
-import com.seaofnodes.simple.type.TypeInteger;
-
-import java.util.Arrays;
-import java.util.BitSet;
-import java.util.HashMap;
-
-public class GraphEvaluator {
-
- public enum ResultType { VALUE, FALLTHROUGH, TIMEOUT }
-
- public record Result(ResultType type, long value) {}
-
- /**
- * Find the start node from some node in the graph or null if there is no start node
- */
- private static StartNode findStart(BitSet visit, Node node) {
- if (node == null) return null;
- if (node instanceof StartNode start) return start;
- if( visit.get(node._nid) ) return null;
- visit.set(node._nid);
- for( Node def : node._inputs ) {
- var res = findStart(visit,def);
- if( res != null ) return res;
- }
- for( Node use : node._outputs ) {
- var res = findStart(visit,use);
- if( res != null ) return res;
- }
- return null;
- }
-
- /**
- * Find the control output from a control node
- */
- private static Node findControl(Node control) {
- for( Node use : control._outputs ) {
- if (use.isCFG()) return use;
- }
- return null;
- }
-
- /**
- * Find the projection for a node
- */
- private static ProjNode findProjection(Node node, int idx) {
- for( Node use : node._outputs ) {
- if (use instanceof ProjNode proj && proj._idx == idx) return proj;
- }
- return null;
- }
-
- /**
- * Cache values for phi and parameter projection nodes.
- */
- private final HashMap<Node, Long> cacheValues = new HashMap<>();
- /**
- * Cache for loop phis as they can depend on itself or other loop phis
- */
- private long[] loopPhiCache = new long[16];
-
- private GraphEvaluator() {
- }
-
- private long div(DivNode div) {
- long in2 = getValue(div.in(2));
- return in2 == 0 ? 0 : getValue(div.in(1)) / in2;
- }
-
- /**
- * Calculate the value of a node
- */
- private long getValue(Node node) {
- var cache = cacheValues.get(node);
- if (cache != null) return cache;
- return switch (node) {
- case ConstantNode cons -> ((TypeInteger)cons.compute()).value();
- case AddNode add -> getValue(add.in(1)) + getValue(add.in(2));
- case BoolNode.EQ eq -> getValue(eq.in(1)) == getValue(eq.in(2)) ? 1 : 0;
- case BoolNode.LE le -> getValue(le.in(1)) <= getValue(le.in(2)) ? 1 : 0;
- case BoolNode.LT lt -> getValue(lt.in(1)) < getValue(lt.in(2)) ? 1 : 0;
- case DivNode div -> div(div);
- case MinusNode minus -> -getValue(minus.in(1));
- case MulNode mul -> getValue(mul.in(1)) * getValue(mul.in(2));
- case NotNode not -> getValue(not.in(1)) == 0 ? 1 : 0;
- case SubNode sub -> getValue(sub.in(1)) - getValue(sub.in(2));
- default -> throw Utils.TODO("Unexpected node " + node);
- };
- }
-
- /**
- * Special case of latchPhis when phis can depend on phis of the same region.
- */
- private void latchLoopPhis(RegionNode region, Node prev) {
- int idx = Utils.find(region._inputs, prev);
- assert idx > 0;
- int i = 0;
- for( Node use : region._outputs ) {
- if (use instanceof PhiNode phi) {
- var value = getValue(phi.in(idx));
- if (i == loopPhiCache.length) loopPhiCache = Arrays.copyOf(loopPhiCache, loopPhiCache.length*2);
- loopPhiCache[i++] = value;
- }
- }
- i = 0;
- for( Node use : region._outputs ) {
- if (use instanceof PhiNode phi) cacheValues.put(phi, loopPhiCache[i++]);
- }
- }
-
- /**
- * Calculate the values of phis of the region and caches the values. The phis are not allowed to depend on other phis of the region.
- */
- private void latchPhis(RegionNode region, Node prev) {
- int idx = Utils.find(region._inputs, prev);
- assert idx > 0;
- for( Node use : region._outputs ) {
- if (use instanceof PhiNode phi) {
- var value = getValue(phi.in(idx));
- cacheValues.put(phi, value);
- }
- }
- }
-
- /**
- * Run the graph until either a return is found or the number of loop iterations are done.
- */
- private Result evaluate(StartNode start, long parameter, int loops) {
- var parameter1 = findProjection(start, 1);
- if (parameter1 != null) cacheValues.put(parameter1, parameter);
- Node control = findProjection(start, 0);
- Node prev = start;
- while (control != null) {
- Node next;
- switch (control) {
- case RegionNode region -> {
- if (region instanceof LoopNode && region.in(1) != prev) {
- if (loops--<=0) return new Result(ResultType.TIMEOUT, 0);
- latchLoopPhis(region, prev);
- } else {
- latchPhis(region, prev);
- }
- next = findControl(region);
- }
- case IfNode cond -> next = findProjection(cond, getValue(cond.in(1)) != 0 ? 0 : 1);
- case ReturnNode ret -> {
- return new Result(ResultType.VALUE, getValue(ret.in(1)));
- }
- case ProjNode ignored -> next = findControl(control);
- default -> throw Utils.TODO("Unexpected control node " + control);
- }
- prev = control;
- control = next;
- }
- return new Result(ResultType.FALLTHROUGH, 0);
- }
-
- public static long evaluate(Node graph) {
- return evaluate(graph, 0);
- }
-
- public static long evaluate(Node graph, long parameter) {
- return evaluate(graph, parameter, 1000);
- }
-
- public static long evaluate(Node graph, long parameter, int loops) {
- var res = evaluateWithResult(graph, parameter, loops);
- if (res.type==ResultType.TIMEOUT) throw new RuntimeException("Timeout");
- return res.value;
- }
-
- public static Result evaluateWithResult(Node graph, long parameter, int loops) {
- var start = findStart(new BitSet(), graph);
- if (start == null) return new Result(ResultType.TIMEOUT, 0);
- var evaluator = new GraphEvaluator();
- return evaluator.evaluate(start, parameter, loops);
- }
-
-}
+package com.seaofnodes.simple; + +import com.seaofnodes.simple.node.*; +import com.seaofnodes.simple.type.TypeInteger; + +import java.util.Arrays; +import java.util.BitSet; +import java.util.HashMap; + +public class GraphEvaluator { + + public enum ResultType { VALUE, FALLTHROUGH, TIMEOUT } + + public record Result(ResultType type, long value) {} + + /** + * Find the start node from some node in the graph or null if there is no start node + */ + private static StartNode findStart(BitSet visit, Node node) { + if (node == null) return null; + if (node instanceof StartNode start) return start; + if( visit.get(node._nid) ) return null; + visit.set(node._nid); + for( Node def : node._inputs ) { + var res = findStart(visit,def); + if( res != null ) return res; + } + for( Node use : node._outputs ) { + var res = findStart(visit,use); + if( res != null ) return res; + } + return null; + } + + /** + * Find the control output from a control node + */ + private static Node findControl(Node control) { + for( Node use : control._outputs ) { + if (use.isCFG()) return use; + } + return null; + } + + /** + * Find the projection for a node + */ + private static ProjNode findProjection(Node node, int idx) { + for( Node use : node._outputs ) { + if (use instanceof ProjNode proj && proj._idx == idx) return proj; + } + return null; + } + + /** + * Cache values for phi and parameter projection nodes. + */ + private final HashMap<Node, Long> cacheValues = new HashMap<>(); + /** + * Cache for loop phis as they can depend on itself or other loop phis + */ + private long[] loopPhiCache = new long[16]; + + private GraphEvaluator() { + } + + private long div(DivNode div) { + long in2 = getValue(div.in(2)); + return in2 == 0 ? 0 : getValue(div.in(1)) / in2; + } + + /** + * Calculate the value of a node + */ + private long getValue(Node node) { + var cache = cacheValues.get(node); + if (cache != null) return cache; + return switch (node) { + case ConstantNode cons -> ((TypeInteger)cons.compute()).value(); + case AddNode add -> getValue(add.in(1)) + getValue(add.in(2)); + case BoolNode.EQ eq -> getValue(eq.in(1)) == getValue(eq.in(2)) ? 1 : 0; + case BoolNode.LE le -> getValue(le.in(1)) <= getValue(le.in(2)) ? 1 : 0; + case BoolNode.LT lt -> getValue(lt.in(1)) < getValue(lt.in(2)) ? 1 : 0; + case DivNode div -> div(div); + case MinusNode minus -> -getValue(minus.in(1)); + case MulNode mul -> getValue(mul.in(1)) * getValue(mul.in(2)); + case NotNode not -> getValue(not.in(1)) == 0 ? 1 : 0; + case SubNode sub -> getValue(sub.in(1)) - getValue(sub.in(2)); + default -> throw Utils.TODO("Unexpected node " + node); + }; + } + + /** + * Special case of latchPhis when phis can depend on phis of the same region. + */ + private void latchLoopPhis(RegionNode region, Node prev) { + int idx = Utils.find(region._inputs, prev); + assert idx > 0; + int i = 0; + for( Node use : region._outputs ) { + if (use instanceof PhiNode phi) { + var value = getValue(phi.in(idx)); + if (i == loopPhiCache.length) loopPhiCache = Arrays.copyOf(loopPhiCache, loopPhiCache.length*2); + loopPhiCache[i++] = value; + } + } + i = 0; + for( Node use : region._outputs ) { + if (use instanceof PhiNode phi) cacheValues.put(phi, loopPhiCache[i++]); + } + } + + /** + * Calculate the values of phis of the region and caches the values. The phis are not allowed to depend on other phis of the region. + */ + private void latchPhis(RegionNode region, Node prev) { + int idx = Utils.find(region._inputs, prev); + assert idx > 0; + for( Node use : region._outputs ) { + if (use instanceof PhiNode phi) { + var value = getValue(phi.in(idx)); + cacheValues.put(phi, value); + } + } + } + + /** + * Run the graph until either a return is found or the number of loop iterations are done. + */ + private Result evaluate(StartNode start, long parameter, int loops) { + var parameter1 = findProjection(start, 1); + if (parameter1 != null) cacheValues.put(parameter1, parameter); + Node control = findProjection(start, 0); + Node prev = start; + while (control != null) { + Node next; + switch (control) { + case RegionNode region -> { + if (region instanceof LoopNode && region.in(1) != prev) { + if (loops--<=0) return new Result(ResultType.TIMEOUT, 0); + latchLoopPhis(region, prev); + } else { + latchPhis(region, prev); + } + next = findControl(region); + } + case IfNode cond -> next = findProjection(cond, getValue(cond.in(1)) != 0 ? 0 : 1); + case ReturnNode ret -> { + return new Result(ResultType.VALUE, getValue(ret.in(1))); + } + case ProjNode ignored -> next = findControl(control); + default -> throw Utils.TODO("Unexpected control node " + control); + } + prev = control; + control = next; + } + return new Result(ResultType.FALLTHROUGH, 0); + } + + public static long evaluate(Node graph) { + return evaluate(graph, 0); + } + + public static long evaluate(Node graph, long parameter) { + return evaluate(graph, parameter, 1000); + } + + public static long evaluate(Node graph, long parameter, int loops) { + var res = evaluateWithResult(graph, parameter, loops); + if (res.type==ResultType.TIMEOUT) throw new RuntimeException("Timeout"); + return res.value; + } + + public static Result evaluateWithResult(Node graph, long parameter, int loops) { + var start = findStart(new BitSet(), graph); + if (start == null) return new Result(ResultType.TIMEOUT, 0); + var evaluator = new GraphEvaluator(); + return evaluator.evaluate(start, parameter, loops); + } + +} diff --git a/chapter08/src/main/java/com/seaofnodes/simple/GraphVisualizer.java b/chapter08/src/main/java/com/seaofnodes/simple/GraphVisualizer.java index 5009264f..d75e5bea 100644 --- a/chapter08/src/main/java/com/seaofnodes/simple/GraphVisualizer.java +++ b/chapter08/src/main/java/com/seaofnodes/simple/GraphVisualizer.java @@ -30,7 +30,7 @@ public class GraphVisualizer { sb.append("/*\n"); sb.append(parser.src()); sb.append("\n*/\n"); - + // To keep the Scopes below the graph and pointing up into the graph we // need to group the Nodes in a subgraph cluster, and the scopes into a // different subgraph cluster. THEN we can draw edges between the @@ -50,7 +50,7 @@ public class GraphVisualizer { // Just the Nodes first, in a cluster no edges nodes(sb, all); - + // Now the scopes, in a cluster no edges for( ScopeNode scope : parser._xScopes ) scope( sb, scope ); @@ -61,7 +61,7 @@ public class GraphVisualizer { // Walk the active Scope edges for( ScopeNode scope : parser._xScopes ) scopeEdges( sb, scope ); - + sb.append("}\n"); return sb.toString(); } @@ -195,13 +195,13 @@ public class GraphVisualizer { sb.append(" color=red"); // Backedges do not add a ranking constraint if( i==2 && (n instanceof PhiNode || n instanceof LoopNode) ) - sb.append(" constraint=false"); + sb.append(" constraint=false"); sb.append("];\n"); } } } } - + // Walk the scope edges private void scopeEdges( StringBuilder sb, ScopeNode scope ) { sb.append("\tedge [style=dashed color=cornflowerblue];\n"); @@ -228,7 +228,7 @@ public class GraphVisualizer { level++; } } - + /** * Finds all nodes in the graph. */ diff --git a/chapter08/src/main/java/com/seaofnodes/simple/Parser.java b/chapter08/src/main/java/com/seaofnodes/simple/Parser.java index 45332396..d4b0c327 100644 --- a/chapter08/src/main/java/com/seaofnodes/simple/Parser.java +++ b/chapter08/src/main/java/com/seaofnodes/simple/Parser.java @@ -13,7 +13,7 @@ import java.util.*; * This is a simple recursive descent parser. All lexical analysis is done here as well. */ public class Parser { - + /** * A Global Static, unique to each compilation. This is a public, so we * can make constants everywhere without having to thread the StartNode @@ -57,7 +57,7 @@ public class Parser { add("while"); }}; - + /** * We clone ScopeNodes when control flows branch; it is useful to have * a list of all active ScopeNodes for purposes of visualization of the SoN graph @@ -82,12 +82,12 @@ public class Parser { @Override public String toString() { return _lexer.toString(); } - + String src() { return new String( _lexer._input ); } // Debugging utility to find a Node by index public static Node find(int nid) { return START.find(nid); } - + private Node ctrl() { return _scope.ctrl(); } private Node ctrl(Node n) { return _scope.ctrl(n); } @@ -108,7 +108,7 @@ public class Parser { return STOP; } - + /** * Parses a block * @@ -199,7 +199,7 @@ public class Parser { // No continues yet _continueScope = null; - + // Parse the true side, which corresponds to loop body // Our current scope is the body Scope ctrl(ifT); // set ctrl token to ifTrue projection @@ -283,7 +283,7 @@ public class Parser { ctrl(ifT); // set ctrl token to ifTrue projection parseStatement(); // Parse true-side ScopeNode tScope = _scope; - + // Parse the false side _scope = fScope; // Restore scope, then parse else block if any ctrl(ifF); // Ctrl token is now set to ifFalse projection @@ -294,7 +294,7 @@ public class Parser { if( tScope.nIns() != ndefs || fScope.nIns() != ndefs ) throw error("Cannot define a new name on one arm of an if"); - + // Merge results _scope = tScope; _xScopes.pop(); // Discard pushed from graph display @@ -583,7 +583,7 @@ public class Parser { skipWhiteSpace(); return peek()==ch; } - + // Return an identifier or null String matchId() { skipWhiteSpace(); @@ -610,7 +610,7 @@ public class Parser { return TypeInteger.constant(Long.parseLong(snum)); } - // First letter of an identifier + // First letter of an identifier private boolean isIdStart(char ch) { return Character.isAlphabetic(ch) || ch == '_'; } @@ -626,7 +626,7 @@ public class Parser { return new String(_input, start, --_position - start); } - // + // private boolean isPunctuation(char ch) { return "=;[]<>()+-/*".indexOf(ch) != -1; } diff --git a/chapter08/src/main/java/com/seaofnodes/simple/Utils.java b/chapter08/src/main/java/com/seaofnodes/simple/Utils.java index 4d663c25..45f15327 100644 --- a/chapter08/src/main/java/com/seaofnodes/simple/Utils.java +++ b/chapter08/src/main/java/com/seaofnodes/simple/Utils.java @@ -36,4 +36,4 @@ public class Utils { return i; return -1; } -}
\ No newline at end of file +} diff --git a/chapter08/src/main/java/com/seaofnodes/simple/node/AddNode.java b/chapter08/src/main/java/com/seaofnodes/simple/node/AddNode.java index 5878f340..84a368fd 100644 --- a/chapter08/src/main/java/com/seaofnodes/simple/node/AddNode.java +++ b/chapter08/src/main/java/com/seaofnodes/simple/node/AddNode.java @@ -8,7 +8,7 @@ public class AddNode extends Node { public AddNode(Node lhs, Node rhs) { super(null, lhs, rhs); } @Override public String label() { return "Add"; } - + @Override public String glabel() { return "+"; } @Override @@ -17,7 +17,7 @@ public class AddNode extends Node { in(2)._print0(sb.append("+"), visited); return sb.append(")"); } - + @Override public Type compute() { @@ -44,13 +44,13 @@ public class AddNode extends Node { // canonicalize to (x+0) if( t2 instanceof TypeInteger i && i.value()==0 ) return lhs; - + // Add of same to a multiply by 2 if( lhs==rhs ) return new MulNode(lhs,new ConstantNode(TypeInteger.constant(2)).peephole()); // Goal: a left-spine set of adds, with constants on the rhs (which then fold). - + // Move non-adds to RHS if( !(lhs instanceof AddNode) && rhs instanceof AddNode ) return swap12(); @@ -74,7 +74,7 @@ public class AddNode extends Node { // the loop will peep as dead after a bit. if( lhs.in(1) == lhs ) return null; - + // Do we have (x + con1) + con2? // Replace with (x + (con1+con2) which then fold the constants if( lhs.in(2)._type.isConstant() && t2.isConstant() ) @@ -88,12 +88,12 @@ public class AddNode extends Node { if( phicon!=null ) return phicon; // Now we sort along the spline via rotates, to gather similar things together. - + // Do we rotate (x + y) + z // into (x + z) + y ? if( spline_cmp(lhs.in(2),rhs) ) return new AddNode(new AddNode(lhs.in(1),rhs).peephole(),lhs.in(2)); - + return null; } @@ -111,11 +111,11 @@ public class AddNode extends Node { lphi = pcon(lhs.in(2)); // Will rotate with the Phi push } if( lphi==null ) return null; - + // RHS is a constant or a Phi of constants if( !(rhs instanceof ConstantNode con) && pcon(rhs)==null ) return null; - + // If both are Phis, must be same Region if( rhs instanceof PhiNode && lphi.in(0) != rhs.in(0) ) return null; @@ -137,7 +137,7 @@ public class AddNode extends Node { static PhiNode pcon(Node op) { return op instanceof PhiNode phi && phi.allCons() ? phi : null; } - + // Compare two off-spline nodes and decide what order they should be in. // Do we rotate ((x + hi) + lo) into ((x + lo) + hi) ? // Generally constants always go right, then Phi-of-constants, then muls, then others. @@ -146,16 +146,16 @@ public class AddNode extends Node { static boolean spline_cmp( Node hi, Node lo ) { if( lo._type.isConstant() ) return false; if( hi._type.isConstant() ) return true ; - + if( lo instanceof PhiNode && lo.allCons() ) return false; if( hi instanceof PhiNode && hi.allCons() ) return true ; if( lo instanceof PhiNode && !(hi instanceof PhiNode) ) return true; if( hi instanceof PhiNode && !(lo instanceof PhiNode) ) return false; - + // Same category of "others" return lo._nid > hi._nid; } - + @Override Node copy(Node lhs, Node rhs) { return new AddNode(lhs,rhs); } } diff --git a/chapter08/src/main/java/com/seaofnodes/simple/node/BoolNode.java b/chapter08/src/main/java/com/seaofnodes/simple/node/BoolNode.java index d65fbf14..0c32d50d 100644 --- a/chapter08/src/main/java/com/seaofnodes/simple/node/BoolNode.java +++ b/chapter08/src/main/java/com/seaofnodes/simple/node/BoolNode.java @@ -12,7 +12,7 @@ abstract public class BoolNode extends Node { } abstract String op(); // String opcode name - + @Override public String label() { return getClass().getSimpleName(); } @@ -41,7 +41,7 @@ abstract public class BoolNode extends Node { @Override public Node idealize() { - // Compare of same + // Compare of same if( in(1)==in(2) ) return new ConstantNode(TypeInteger.constant(doOp(3,3)?1:0)); diff --git a/chapter08/src/main/java/com/seaofnodes/simple/node/ConstantNode.java b/chapter08/src/main/java/com/seaofnodes/simple/node/ConstantNode.java index 0e13d2f2..13006bfb 100644 --- a/chapter08/src/main/java/com/seaofnodes/simple/node/ConstantNode.java +++ b/chapter08/src/main/java/com/seaofnodes/simple/node/ConstantNode.java @@ -23,10 +23,10 @@ public class ConstantNode extends Node { super(Parser.START); _con = type; } - + @Override public String label() { return ""+_con; } - + @Override public String uniqueName() { return "Con_" + _nid; } @@ -34,9 +34,9 @@ public class ConstantNode extends Node { StringBuilder _print1(StringBuilder sb, BitSet visited) { return _con._print(sb); } - + @Override public boolean isMultiTail() { return true; } - + @Override public Type compute() { return _con; } diff --git a/chapter08/src/main/java/com/seaofnodes/simple/node/DivNode.java b/chapter08/src/main/java/com/seaofnodes/simple/node/DivNode.java index b0e12547..2213d2e7 100644 --- a/chapter08/src/main/java/com/seaofnodes/simple/node/DivNode.java +++ b/chapter08/src/main/java/com/seaofnodes/simple/node/DivNode.java @@ -18,7 +18,7 @@ public class DivNode extends Node { in(2)._print0(sb.append("/"), visited); return sb.append(")"); } - + @Override public Type compute() { if (in(1)._type instanceof TypeInteger i0 && @@ -34,6 +34,6 @@ public class DivNode extends Node { @Override public Node idealize() { return null; } - + @Override Node copy(Node lhs, Node rhs) { return new DivNode(lhs,rhs); } } diff --git a/chapter08/src/main/java/com/seaofnodes/simple/node/IfNode.java b/chapter08/src/main/java/com/seaofnodes/simple/node/IfNode.java index 1d1da4fa..23a8fafc 100644 --- a/chapter08/src/main/java/com/seaofnodes/simple/node/IfNode.java +++ b/chapter08/src/main/java/com/seaofnodes/simple/node/IfNode.java @@ -47,7 +47,7 @@ public class IfNode extends MultiNode { // Repeated test, dominated on one side. Test result is the same. ? (proj._idx==0 ? TypeTuple.IF_TRUE : TypeTuple.IF_FALSE) : dom._type; // Repeated test not dominated on one side - + return TypeTuple.IF_BOTH; } diff --git a/chapter08/src/main/java/com/seaofnodes/simple/node/LoopNode.java b/chapter08/src/main/java/com/seaofnodes/simple/node/LoopNode.java index 0b84f897..c192bc20 100644 --- a/chapter08/src/main/java/com/seaofnodes/simple/node/LoopNode.java +++ b/chapter08/src/main/java/com/seaofnodes/simple/node/LoopNode.java @@ -25,5 +25,5 @@ public class LoopNode extends RegionNode { return inProgress() ? null : super.idealize(); } - @Override Node idom() { return entry(); } + @Override Node idom() { return entry(); } } diff --git a/chapter08/src/main/java/com/seaofnodes/simple/node/MinusNode.java b/chapter08/src/main/java/com/seaofnodes/simple/node/MinusNode.java index 8a96693d..3d944fd4 100644 --- a/chapter08/src/main/java/com/seaofnodes/simple/node/MinusNode.java +++ b/chapter08/src/main/java/com/seaofnodes/simple/node/MinusNode.java @@ -9,15 +9,15 @@ public class MinusNode extends Node { public MinusNode(Node in) { super(null, in); } @Override public String label() { return "Minus"; } - + @Override public String glabel() { return "-"; } - + @Override StringBuilder _print1(StringBuilder sb, BitSet visited) { in(1)._print0(sb.append("(-"), visited); return sb.append(")"); } - + @Override public Type compute() { if (in(1)._type instanceof TypeInteger i0) diff --git a/chapter08/src/main/java/com/seaofnodes/simple/node/MulNode.java b/chapter08/src/main/java/com/seaofnodes/simple/node/MulNode.java index 70e6c0db..2e701a4e 100644 --- a/chapter08/src/main/java/com/seaofnodes/simple/node/MulNode.java +++ b/chapter08/src/main/java/com/seaofnodes/simple/node/MulNode.java @@ -9,7 +9,7 @@ public class MulNode extends Node { public MulNode(Node lhs, Node rhs) { super(null, lhs, rhs); } @Override public String label() { return "Mul"; } - + @Override public String glabel() { return "*"; } @Override @@ -36,12 +36,12 @@ public class MulNode extends Node { Node rhs = in(2); Type t1 = lhs._type; Type t2 = rhs._type; - + // Mul of 1. We do not check for (1*x) because this will already // canonicalize to (x*1) if ( t2.isConstant() && t2 instanceof TypeInteger i && i.value()==1 ) return lhs; - + // Move constants to RHS: con*arg becomes arg*con if ( t1.isConstant() && !t2.isConstant() ) return swap12(); diff --git a/chapter08/src/main/java/com/seaofnodes/simple/node/MultiNode.java b/chapter08/src/main/java/com/seaofnodes/simple/node/MultiNode.java index 81c90f68..7ba1aa19 100644 --- a/chapter08/src/main/java/com/seaofnodes/simple/node/MultiNode.java +++ b/chapter08/src/main/java/com/seaofnodes/simple/node/MultiNode.java @@ -1,7 +1,7 @@ package com.seaofnodes.simple.node; public abstract class MultiNode extends Node { - + public MultiNode(Node... inputs) { super(inputs); } } diff --git a/chapter08/src/main/java/com/seaofnodes/simple/node/Node.java b/chapter08/src/main/java/com/seaofnodes/simple/node/Node.java index fd312c3d..2d6d5ad5 100644 --- a/chapter08/src/main/java/com/seaofnodes/simple/node/Node.java +++ b/chapter08/src/main/java/com/seaofnodes/simple/node/Node.java @@ -47,7 +47,7 @@ public abstract class Node { */ public Type _type; - + /** * Immediate dominator tree depth, used to approximate a real IDOM during * parsing where we do not have the whole program, and also peepholes @@ -56,7 +56,7 @@ public abstract class Node { * See {@link <a href="https://en.wikipedia.org/wiki/Dominator_(graph_theory)">...</a>} */ int _idepth; - + /** * A private Global Static mutable counter, for unique node id generation. * To make the compiler multithreaded, this field will have to move into a TLS. @@ -85,9 +85,9 @@ public abstract class Node { // ------------------------------------------------------------------------ - + // Debugger Printing. - + // {@code toString} is what you get in the debugger. It has to print 1 // line (because this is what a debugger typically displays by default) and // has to be robust with broken graph/nodes. @@ -101,7 +101,7 @@ public abstract class Node { public final String print() { return _print0(new StringBuilder(), new BitSet()).toString(); } - + // This is the common print: check for repeats, check for DEAD and print // "DEAD" else call the per-Node print1. final StringBuilder _print0(StringBuilder sb, BitSet visited) { @@ -141,13 +141,13 @@ public abstract class Node { } public String p(int depth) { return IRPrinter.prettyPrint(this,depth); } - + public boolean isMultiHead() { return false; } public boolean isMultiTail() { return false; } - + // ------------------------------------------------------------------------ // Graph Node & Edge manipulation - + /** * Gets the ith input node * @param i Offset of the input node @@ -162,19 +162,19 @@ public abstract class Node { public boolean isUnused() { return nOuts() == 0; } public boolean isCFG() { return false; } - + /** * Change a <em>def</em> into a Node. Keeps the edges correct, by removing * the corresponding <em>use->def</em> edge. This may make the original * <em>def</em> go dead. This function is co-recursive with {@link #kill}. * <p> - + * This method is the normal path for altering a Node, because it does the * proper default edge maintenance. It also <em>immediately</em> kills * Nodes that lose their last use; at times care must be taken to avoid * killing Nodes that are being used without having an output Node. This * definitely happens in the middle of recursive {@link #peephole} calls. - * + * * @param idx which def to set * @param new_def the new definition * @return new_def for flow coding @@ -195,7 +195,7 @@ public abstract class Node { // Return self for easy flow-coding return new_def; } - + // Remove the numbered input, compressing the inputs in-place. This // shuffles the order deterministically - which is suitable for Region and // Phi, but not for every Node. @@ -244,7 +244,7 @@ public abstract class Node { old_def.kill(); // Kill old def } } - + /** * Kill a Node with no <em>uses</em>, by setting all of its <em>defs</em> * to null. This may recursively kill more Nodes and is basically dead @@ -278,10 +278,10 @@ public abstract class Node { } kill(); } - + // ------------------------------------------------------------------------ // Graph-based optimizations - + /** * We allow disabling peephole opt so that we can observe the * full graph, vs the optimized graph. @@ -306,7 +306,7 @@ public abstract class Node { public final Node peephole( ) { // Compute initial or improved Type Type type = _type = compute(); - + if (_disablePeephole) return this; // Peephole optimizations turned off @@ -315,13 +315,13 @@ public abstract class Node { return deadCodeElim(new ConstantNode(type).peephole()); // Future chapter: Global Value Numbering goes here - + // Ask each node for a better replacement Node n = idealize(); if( n != null ) // Something changed // Recursively optimize return deadCodeElim(n.peephole()); - + return this; // No progress } @@ -341,7 +341,7 @@ public abstract class Node { } return m; } - + /** * This function needs to be * <a href="https://en.wikipedia.org/wiki/Monotonic_function">Monotonic</a> @@ -410,7 +410,7 @@ public abstract class Node { // ------------------------------------------------------------------------ // Peephole utilities - + // Swap inputs without letting either input go dead during the swap. Node swap12() { Node tmp = in(1); @@ -418,7 +418,7 @@ public abstract class Node { _inputs.set(2,tmp); return this; } - + // does this node contain all constants? // Ignores in(0), as is usually control. boolean allCons() { diff --git a/chapter08/src/main/java/com/seaofnodes/simple/node/NotNode.java b/chapter08/src/main/java/com/seaofnodes/simple/node/NotNode.java index 04e6c75b..39df410d 100644 --- a/chapter08/src/main/java/com/seaofnodes/simple/node/NotNode.java +++ b/chapter08/src/main/java/com/seaofnodes/simple/node/NotNode.java @@ -9,15 +9,15 @@ public class NotNode extends Node { public NotNode(Node in) { super(null, in); } @Override public String label() { return "Not"; } - + @Override public String glabel() { return "!"; } - + @Override StringBuilder _print1(StringBuilder sb, BitSet visited) { in(1)._print0(sb.append("(!"), visited); return sb.append(")"); } - + @Override public Type compute() { if( in(1)._type instanceof TypeInteger i0 ) diff --git a/chapter08/src/main/java/com/seaofnodes/simple/node/PhiNode.java b/chapter08/src/main/java/com/seaofnodes/simple/node/PhiNode.java index 975630d0..c7b5b357 100644 --- a/chapter08/src/main/java/com/seaofnodes/simple/node/PhiNode.java +++ b/chapter08/src/main/java/com/seaofnodes/simple/node/PhiNode.java @@ -7,7 +7,7 @@ import java.util.BitSet; public class PhiNode extends Node { final String _label; - + public PhiNode(String label, Node... inputs) { super(inputs); _label = label; } @Override public String label() { return "Phi_"+_label; } @@ -35,7 +35,7 @@ public class PhiNode extends Node { @Override public Type compute() { if( !(region() instanceof RegionNode r) || r.inProgress() ) - return Type.BOTTOM; + return Type.BOTTOM; Type t = Type.TOP; for (int i = 1; i < nIns(); i++) t = t.meet(in(i)._type); @@ -53,7 +53,7 @@ public class PhiNode extends Node { return live; // Pull "down" a common data op. One less op in the world. One more - // Phi, but Phis do not make code. + // Phi, but Phis do not make code. // Phi(op(A,B),op(Q,R),op(X,Y)) becomes // op(Phi(A,Q,X), Phi(B,R,Y)). Node op = in(1); diff --git a/chapter08/src/main/java/com/seaofnodes/simple/node/ProjNode.java b/chapter08/src/main/java/com/seaofnodes/simple/node/ProjNode.java index 79ba9d13..c263502d 100644 --- a/chapter08/src/main/java/com/seaofnodes/simple/node/ProjNode.java +++ b/chapter08/src/main/java/com/seaofnodes/simple/node/ProjNode.java @@ -12,7 +12,7 @@ public class ProjNode extends Node { // Debugging label public final String _label; - + public ProjNode(MultiNode ctrl, int idx, String label) { super(ctrl); _idx = idx; diff --git a/chapter08/src/main/java/com/seaofnodes/simple/node/RegionNode.java b/chapter08/src/main/java/com/seaofnodes/simple/node/RegionNode.java index 00c010b2..453d028f 100644 --- a/chapter08/src/main/java/com/seaofnodes/simple/node/RegionNode.java +++ b/chapter08/src/main/java/com/seaofnodes/simple/node/RegionNode.java @@ -9,7 +9,7 @@ import java.util.BitSet; public class RegionNode extends Node { public RegionNode(Node... nodes) { super(nodes); } - + @Override public String label() { return "Region"; } diff --git a/chapter08/src/main/java/com/seaofnodes/simple/node/ReturnNode.java b/chapter08/src/main/java/com/seaofnodes/simple/node/ReturnNode.java index 4dea773a..312058b9 100644 --- a/chapter08/src/main/java/com/seaofnodes/simple/node/ReturnNode.java +++ b/chapter08/src/main/java/com/seaofnodes/simple/node/ReturnNode.java @@ -21,7 +21,7 @@ public class ReturnNode extends Node { public Node ctrl() { return in(0); } public Node expr() { return in(1); } - + @Override public String label() { return "Return"; } @@ -31,7 +31,7 @@ public class ReturnNode extends Node { } @Override public boolean isCFG() { return true; } - + @Override public Type compute() { return new TypeTuple(ctrl()._type,expr()._type); diff --git a/chapter08/src/main/java/com/seaofnodes/simple/node/ScopeNode.java b/chapter08/src/main/java/com/seaofnodes/simple/node/ScopeNode.java index a6a7f536..e5d03d93 100644 --- a/chapter08/src/main/java/com/seaofnodes/simple/node/ScopeNode.java +++ b/chapter08/src/main/java/com/seaofnodes/simple/node/ScopeNode.java @@ -28,8 +28,8 @@ public class ScopeNode extends Node { _scopes = new Stack<>(); _type = Type.BOTTOM; } - - + + @Override public String label() { return "Scope"; } @Override @@ -63,7 +63,7 @@ public class ScopeNode extends Node { names[syms.get(name)] = name; return names; } - + @Override public Type compute() { return Type.BOTTOM; } @Override public Node idealize() { return null; } @@ -190,7 +190,7 @@ public class ScopeNode extends Node { that.kill(); // Kill merged scope return r.unkeep().peephole(); } - + // Merge the backedge scope into this loop head scope // We set the second input to the phi from the back edge (i.e. loop body) public void endLoop(ScopeNode back, ScopeNode exit ) { diff --git a/chapter08/src/main/java/com/seaofnodes/simple/node/StartNode.java b/chapter08/src/main/java/com/seaofnodes/simple/node/StartNode.java index 19d03e0f..01f1485a 100644 --- a/chapter08/src/main/java/com/seaofnodes/simple/node/StartNode.java +++ b/chapter08/src/main/java/com/seaofnodes/simple/node/StartNode.java @@ -15,7 +15,7 @@ import java.util.BitSet; public class StartNode extends MultiNode { final TypeTuple _args; - + public StartNode(Type[] args) { super(); _args = new TypeTuple(args); diff --git a/chapter08/src/main/java/com/seaofnodes/simple/node/StopNode.java b/chapter08/src/main/java/com/seaofnodes/simple/node/StopNode.java index a0aacf2b..417790d9 100644 --- a/chapter08/src/main/java/com/seaofnodes/simple/node/StopNode.java +++ b/chapter08/src/main/java/com/seaofnodes/simple/node/StopNode.java @@ -30,7 +30,7 @@ public class StopNode extends Node { public ReturnNode ret() { return nIns()==1 ? (ReturnNode)in(0) : null; } - + @Override public Type compute() { return Type.BOTTOM; diff --git a/chapter08/src/main/java/com/seaofnodes/simple/node/SubNode.java b/chapter08/src/main/java/com/seaofnodes/simple/node/SubNode.java index 1484ab8a..4a06fcb3 100644 --- a/chapter08/src/main/java/com/seaofnodes/simple/node/SubNode.java +++ b/chapter08/src/main/java/com/seaofnodes/simple/node/SubNode.java @@ -18,7 +18,7 @@ public class SubNode extends Node { in(2)._print0(sb.append("-"), visited); return sb.append(")"); } - + @Override public Type compute() { if (in(1)._type instanceof TypeInteger i0 && diff --git a/chapter08/src/main/java/com/seaofnodes/simple/type/Type.java b/chapter08/src/main/java/com/seaofnodes/simple/type/Type.java index f88403a5..2f0e6171 100644 --- a/chapter08/src/main/java/com/seaofnodes/simple/type/Type.java +++ b/chapter08/src/main/java/com/seaofnodes/simple/type/Type.java @@ -4,7 +4,7 @@ package com.seaofnodes.simple.type; /** * These types are part of a Monotone Analysis Framework, * @see <a href="https://www.cse.psu.edu/~gxt29/teaching/cse597s21/slides/08monotoneFramework.pdf">see for example this set of slides</a>. - * <p> + * <p> * The types form a lattice; @see <a href="https://en.wikipedia.org/wiki/Lattice_(order)">a symmetric complete bounded (ranked) lattice.</a> * <p> * This wild lattice theory will be needed later to allow us to easily beef up @@ -15,7 +15,7 @@ package com.seaofnodes.simple.type; * actual implementation is darn near trivial and is generally really obvious * what we're doing with it. Right now, it's just simple integer math to do * simple constant folding e.g. 1+2 == 3 stuff. - */ + */ public class Type { diff --git a/chapter08/src/main/java/com/seaofnodes/simple/type/TypeInteger.java b/chapter08/src/main/java/com/seaofnodes/simple/type/TypeInteger.java index 93f5eae3..b30e21d8 100644 --- a/chapter08/src/main/java/com/seaofnodes/simple/type/TypeInteger.java +++ b/chapter08/src/main/java/com/seaofnodes/simple/type/TypeInteger.java @@ -28,7 +28,7 @@ public class TypeInteger extends Type { public boolean isTop() { return !_is_con && _con==0; } public boolean isBot() { return !_is_con && _con==1; } - @Override + @Override public StringBuilder _print(StringBuilder sb) { if (isTop()) return sb.append("IntTop"); if (isBot()) return sb.append("IntBot"); diff --git a/chapter08/src/main/java/com/seaofnodes/simple/type/TypeTuple.java b/chapter08/src/main/java/com/seaofnodes/simple/type/TypeTuple.java index f8c3b3c8..0f8b95bd 100644 --- a/chapter08/src/main/java/com/seaofnodes/simple/type/TypeTuple.java +++ b/chapter08/src/main/java/com/seaofnodes/simple/type/TypeTuple.java @@ -1,7 +1,7 @@ package com.seaofnodes.simple.type; public class TypeTuple extends Type { - + public final Type[] _types; public TypeTuple(Type... _types) { |
