From c5ef4e52fd7d183861b33476db999fa04f777607 Mon Sep 17 00:00:00 2001 From: Cliff Click Date: Sun, 27 Sep 2026 08:52:12 -0700 Subject: Remove -disablePeephole --- chapter08/README.md | 2 +- .../main/java/com/seaofnodes/simple/node/Node.java | 10 ----- .../java/com/seaofnodes/simple/Chapter02Test.java | 4 +- .../java/com/seaofnodes/simple/Chapter03Test.java | 9 ---- .../java/com/seaofnodes/simple/Chapter07Test.java | 18 ++------ .../java/com/seaofnodes/simple/fuzzer/Fuzzer.java | 52 +++++----------------- .../com/seaofnodes/simple/fuzzer/FuzzerUtils.java | 5 +-- 7 files changed, 17 insertions(+), 83 deletions(-) (limited to 'chapter08') diff --git a/chapter08/README.md b/chapter08/README.md index 6761d16d..f1718fbb 100644 --- a/chapter08/README.md +++ b/chapter08/README.md @@ -299,7 +299,7 @@ return t; In this code, the two statements within the loop may be evaluated in either order by the graph, so we must ensure that the new value `arg` is not cached before the value of `t` can be set to the previous value of `arg`. -This approach to evaluation is useful for testing because it allows a program to be executed without worrying about instruction selection, register allocation or code generation. It can execute on any valid Sea of Nodes graph, as well, so execution results of unoptimized code can be checked against the results of optimized code! This fact lends itself to some interesting automated / regression testing ideas. For instance, the result of execution could be checked after every optimization step, possibly helping isolate some types of errors. +This approach to evaluation is useful for testing because it allows a program to be executed without worrying about instruction selection, register allocation or code generation. It executes the graph produced with normal peephole optimization. In later chapters, the evaluator can compare graphs optimized with different worklist orders to detect inconsistent results. This chapter's fuzzer checks generated programs for compiler and evaluator failures. ``` java arg=arg+arg; 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 f20e9c2f..ffb868cb 100644 --- a/chapter08/src/main/java/com/seaofnodes/simple/node/Node.java +++ b/chapter08/src/main/java/com/seaofnodes/simple/node/Node.java @@ -280,12 +280,6 @@ public abstract class Node { // ------------------------------------------------------------------------ // Graph-based optimizations - /** - * We allow disabling peephole opt so that we can observe the - * full graph, vs the optimized graph. - */ - public static boolean _disablePeephole = false; - /** * Try to peephole at this node and return a better replacement Node if * possible. We compute a {@link Type} and then check and replace: @@ -315,9 +309,6 @@ public abstract class Node { // Compute initial or improved Type Type type = _type = compute(); - if (_disablePeephole) - return null; // Peephole optimizations turned off - // Replace constant computations from non-constants with a constant node if (!(this instanceof ConstantNode) && type.isConstant()) return deadCodeElim(new ConstantNode(type).peephole()); @@ -471,7 +462,6 @@ public abstract class Node { */ public static void reset() { UNIQUE_ID = 1; - _disablePeephole=false; } /** diff --git a/chapter08/src/test/java/com/seaofnodes/simple/Chapter02Test.java b/chapter08/src/test/java/com/seaofnodes/simple/Chapter02Test.java index 47cee096..a6075b75 100644 --- a/chapter08/src/test/java/com/seaofnodes/simple/Chapter02Test.java +++ b/chapter08/src/test/java/com/seaofnodes/simple/Chapter02Test.java @@ -11,10 +11,8 @@ public class Chapter02Test { @Test public void testParseGrammar() { Parser parser = new Parser("return 1+2*3+-5;"); - Node._disablePeephole = true; // disable peephole so we can observe full graph StopNode ret = parser.parse(); - assertEquals("return (1+((2*3)+(-5)));", ret.print()); - Node._disablePeephole = false; + assertEquals("return 2;", ret.print()); } @Test diff --git a/chapter08/src/test/java/com/seaofnodes/simple/Chapter03Test.java b/chapter08/src/test/java/com/seaofnodes/simple/Chapter03Test.java index 64ff153e..609dff76 100644 --- a/chapter08/src/test/java/com/seaofnodes/simple/Chapter03Test.java +++ b/chapter08/src/test/java/com/seaofnodes/simple/Chapter03Test.java @@ -29,15 +29,6 @@ public class Chapter03Test { assertEquals("return 4;", ret.print()); } - @Test - public void testVarScopeNoPeephole() { - Parser parser = new Parser("int a=1; int b=2; int c=0; { int b=3; c=a+b; } return c; "); - Node._disablePeephole = true; - StopNode ret = parser.parse(); - Node._disablePeephole = false; - assertEquals("return (1+3);", ret.print()); - } - @Test public void testVarDist() { Parser parser = new Parser("int x0=1; int y0=2; int x1=3; int y1=4; return (x0-x1)*(x0-x1) + (y0-y1)*(y0-y1); "); diff --git a/chapter08/src/test/java/com/seaofnodes/simple/Chapter07Test.java b/chapter08/src/test/java/com/seaofnodes/simple/Chapter07Test.java index 40933f21..26b5c17d 100644 --- a/chapter08/src/test/java/com/seaofnodes/simple/Chapter07Test.java +++ b/chapter08/src/test/java/com/seaofnodes/simple/Chapter07Test.java @@ -17,11 +17,9 @@ public class Chapter07Test { } return arg; """); - Node._disablePeephole = true; StopNode stop = parser.parse(); assertEquals("return Phi(Loop6,arg,(Phi_arg+1));", stop.toString()); assertTrue(stop.ret().ctrl() instanceof ProjNode); - Node._disablePeephole = false; } @Test @@ -72,11 +70,9 @@ while(a < 10) { } return b; """); - Node._disablePeephole = true; StopNode stop = parser.parse(); assertEquals("return Phi(Loop8,2,Phi(Region26,Phi_b,4));", stop.toString()); assertTrue(stop.ret().ctrl() instanceof ProjNode); - Node._disablePeephole = false; } @Test @@ -110,11 +106,9 @@ while(a < 10) { } return a; """); - Node._disablePeephole = true; StopNode stop = parser.parse(); - assertEquals("return Phi(Loop7,1,((Phi_a+1)+2));", stop.toString()); + assertEquals("return Phi(Loop7,1,(Phi_a+3));", stop.toString()); assertTrue(stop.ret().ctrl() instanceof ProjNode); - Node._disablePeephole = false; } @Test @@ -141,11 +135,9 @@ int a = 1; while(arg) a = 2; return a; """); - Node._disablePeephole = true; StopNode stop = parser.parse(); assertEquals("return Phi(Loop7,1,2);", stop.toString()); assertTrue(stop.ret().ctrl() instanceof ProjNode); - Node._disablePeephole = false; } @Test @@ -172,11 +164,9 @@ while(a < 10) { } return a; """); - Node._disablePeephole = true; StopNode stop = parser.parse(); - assertEquals("return Phi(Loop7,1,((Phi_a+1)+2));", stop.toString()); + assertEquals("return Phi(Loop7,1,(Phi_a+3));", stop.toString()); assertTrue(stop.ret().ctrl() instanceof ProjNode); - Node._disablePeephole = false; } @Test @@ -207,11 +197,9 @@ while(a < 10) { } return a; """); - Node._disablePeephole = true; StopNode stop = parser.parse(); - assertEquals("return Phi(Loop8,1,((Phi_a+1)+2));", stop.toString()); + assertEquals("return Phi(Loop8,1,(Phi_a+3));", stop.toString()); assertTrue(stop.ret().ctrl() instanceof ProjNode); - Node._disablePeephole = false; } @Test diff --git a/chapter08/src/test/java/com/seaofnodes/simple/fuzzer/Fuzzer.java b/chapter08/src/test/java/com/seaofnodes/simple/fuzzer/Fuzzer.java index 861c8b3a..ef73fa4b 100644 --- a/chapter08/src/test/java/com/seaofnodes/simple/fuzzer/Fuzzer.java +++ b/chapter08/src/test/java/com/seaofnodes/simple/fuzzer/Fuzzer.java @@ -13,8 +13,8 @@ import java.util.function.Consumer; * This will generate a script similar to how the parser parses it but instead of parsing it will * randomly choose a variation the parser would parse and generate it. * These scripts are the parsed by the parser and all exceptions are caught and filtered - * to only show one occurrence of one problem. This includes script which generate different - * results when the compiled graph with and without peeps is executed. + * to only show one occurrence of one problem. Generated graphs are evaluated + * to detect compiler/evaluator failures; this chapter has no differential oracle. * To aid debugging scripts that cause errors are then reduced by applying rules and checking * that the same issue persists. */ @@ -49,49 +49,17 @@ public class Fuzzer { System.out.flush(); } - /** - * Check that two graphs result in the same output when supplied with a value - * @param stop1 Stop node of the first graph - * @param stop2 Stop node of the second graph - * @param in The input value to both graphs to test for an equal output - */ - private static void checkGraphs(StopNode stop1, StopNode stop2, long in) { - var e1 = GraphEvaluator.evaluateWithResult(stop1, in, EVAL_TIMEOUT); - var e2 = GraphEvaluator.evaluateWithResult(stop2, in, EVAL_TIMEOUT); - if (e1.type() == GraphEvaluator.ResultType.TIMEOUT || e2.type() == GraphEvaluator.ResultType.TIMEOUT) return; - if (e1.type() != e2.type()) - throw new RuntimeException("Different calculations types " + e1.type() + " vs " + e2.type()); - if (e1.value() != e2.value()) - throw new RuntimeException("Different calculations values " + e1.value() + " vs " + e2.value()); - } - - /** - * Run checks for script. Compile the script with peeps enabled and disabled. - * Check that exceptions raised in the parser by both methods are the same and only happens if the script may be invalid. - * If the script was successfully parsed check that both version behave the same. - * @param script The script to test - * @param valid If the script is definitely valid. If not some exceptions may be suppressed. - */ + /** Compile and evaluate generated programs with normal peepholes. */ private static void runCheck(String script, boolean valid) { - StopNode stop1; + StopNode stop; try { - stop1 = FuzzerUtils.parse(script, false); - } catch (RuntimeException e1) { - try { - FuzzerUtils.parse(script, true); - } catch (RuntimeException e2) { - if (FuzzerUtils.isExceptionFromSameCause(e1, e2)) { - if (!valid || e1.getClass() == RuntimeException.class) return; - } else { - e1.addSuppressed(e2); - } - } - throw e1; + stop = FuzzerUtils.parse(script); + } catch (RuntimeException e) { + if (!valid || e.getClass() == RuntimeException.class) return; + throw e; } - var stop2 = FuzzerUtils.parse(script, true); - checkGraphs(stop1, stop2, 0); - checkGraphs(stop1, stop2, 1); - checkGraphs(stop1, stop2, 10); + for (int input : new int[] {0, 1, 10}) + GraphEvaluator.evaluateWithResult(stop, input, EVAL_TIMEOUT); } /** diff --git a/chapter08/src/test/java/com/seaofnodes/simple/fuzzer/FuzzerUtils.java b/chapter08/src/test/java/com/seaofnodes/simple/fuzzer/FuzzerUtils.java index 37a57e11..0e83861d 100644 --- a/chapter08/src/test/java/com/seaofnodes/simple/fuzzer/FuzzerUtils.java +++ b/chapter08/src/test/java/com/seaofnodes/simple/fuzzer/FuzzerUtils.java @@ -47,11 +47,10 @@ class FuzzerUtils { } /** - * Parse script with peepholes enabled or disabled + * Parse script with normal peephole optimization */ - public static StopNode parse(String script, boolean runPeeps) { + public static StopNode parse(String script) { var parser = new Parser(script); - Node._disablePeephole = !runPeeps; return parser.parse(); } -- cgit v1.2.3