From 628452bb9f6137d433395fae5a9f5d780fb0f1e1 Mon Sep 17 00:00:00 2001 From: Cliff Click Date: Mon, 10 Aug 2026 15:21:17 -0700 Subject: More hardening Allow setting random seeds to not fail tests due to e.g. spill-counts or exact graph shapes. A few missing addDeps or stalling-for-constants fixed. --- .../main/java/com/seaofnodes/simple/IterPeeps.java | 5 ++++- .../com/seaofnodes/simple/codegen/CodeGen.java | 8 +++++++- .../com/seaofnodes/simple/node/BulkMemPhiNode.java | 23 +++++++++++++++++++++- .../java/com/seaofnodes/simple/node/LoadNode.java | 14 +++++++------ .../main/java/com/seaofnodes/simple/node/Node.java | 4 ++++ .../com/seaofnodes/simple/node/ReturnNode.java | 9 --------- .../java/com/seaofnodes/simple/Chapter05Test.java | 5 ++++- .../java/com/seaofnodes/simple/Chapter18Test.java | 4 +++- .../java/com/seaofnodes/simple/Chapter20Test.java | 2 +- .../java/com/seaofnodes/simple/Chapter21Test.java | 2 +- .../java/com/seaofnodes/simple/Chapter22Test.java | 2 +- .../java/com/seaofnodes/simple/Chapter23Test.java | 2 +- .../java/com/seaofnodes/simple/Chapter24Test.java | 2 +- .../test/java/com/seaofnodes/simple/TestArm64.java | 2 +- .../src/test/java/com/seaofnodes/simple/TestC.java | 2 +- .../test/java/com/seaofnodes/simple/TestRisc5.java | 2 +- 16 files changed, 60 insertions(+), 28 deletions(-) (limited to 'chapter25/src') diff --git a/chapter25/src/main/java/com/seaofnodes/simple/IterPeeps.java b/chapter25/src/main/java/com/seaofnodes/simple/IterPeeps.java index 608f368d..9fac7a99 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/IterPeeps.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/IterPeeps.java @@ -81,11 +81,14 @@ public class IterPeeps { // Everybody gets a free "go again" in case they didn't get // made in their final form. _work.push(x); + // A self-returning peephole can have rewritten its input + // edges. The new defs gained a user and may have + // backwards, user-sensitive peepholes of their own. + for( Node z : x._inputs ) _work.push(z); // If the result is not self, revisit all inputs (because // there's a new user), and replace in the graph. if( x != n ) { for( Node z : n. _inputs ) _work.push(z); - for( Node z : x. _inputs ) _work.push(z); for( Node z : x._outputs ) _work.push(z); n.subsume(x); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java b/chapter25/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java index 85407ddc..85d8143b 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java @@ -42,6 +42,9 @@ public class CodeGen { } public Phase _phase; + /** True when tests deliberately randomize Iter worklist order. */ + public static boolean iterSeedOverridden() { return System.getProperty("simple.iter.seed") != null; } + // --------------------------- // Module Source Root public final String _modDir; @@ -196,7 +199,10 @@ public class CodeGen { _phase = null; // Start GVN table _gvn = new HashMap<>(); - _iter = new IterPeeps(workListSeed); + // Allow whole-suite worklist-order sweeps without rewriting the many + // explicit seeds used by tests and command-line compilation. + String iterSeed = System.getProperty("simple.iter.seed"); + _iter = new IterPeeps(iterSeed == null ? workListSeed : Long.parseLong(iterSeed)); // End points of graph _stop = new StopNode().init(); _start = new StartNode(null,_stop,arg).init(); diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/BulkMemPhiNode.java b/chapter25/src/main/java/com/seaofnodes/simple/node/BulkMemPhiNode.java index c4a13375..cab85e44 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/BulkMemPhiNode.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/BulkMemPhiNode.java @@ -140,6 +140,7 @@ public class BulkMemPhiNode extends PhiNode { return true; } + // True if the MemMerge has no precise slice still covered by this Phi. private boolean canPeek(MemMergeNode mmm) { return missingAlias(mmm,false)==0; @@ -165,7 +166,11 @@ public class BulkMemPhiNode extends PhiNode { // Return an alias required by a user but still covered by this Phi, or 0. private int outputAlias(Node use) { - use = addDep(use); // User alias sharpening changes this decision + // This decision depends backwards on an immediate user's alias/set. + // Normal graph-neighbor enqueueing flows from defs to uses, so retain + // an explicit forward dependency to revisit this Phi when the user + // sharpens. + use = addDepForwards(use); return switch(use) { case ScopeNode scope -> 0; case ParmNode parm -> 0; @@ -217,6 +222,11 @@ public class BulkMemPhiNode extends PhiNode { for( int i=0; i x <= 1 ? 1 : x*_fact(x-1); }; return _fact(arg);"); code.parse().opto().typeCheck(); - assertEquals("Stop[ return Phi(Region,1,(arg*#2)); return Phi(Region,1,(Parm_x(_fact,(arg-1),(x-1))*#2)); ]", code.print()); + String ir = code.print(); + assertTrue(ir.equals("Stop[ return Phi(Region,1,(arg*#2)); return Phi(Region,1,(Parm_x(_fact,(arg-1),(x-1))*#2)); ]") || + ir.equals("Stop[ return Phi(Region,1,(arg*Phi(Region,1,((arg-1)*#2)))); return Phi(Region,1,(Parm_x(_fact,(Sub-1),(x-1))*#2)); ]")); assertEquals( "1", Eval2.eval(code, 0)); assertEquals( "1", Eval2.eval(code, 1)); assertEquals( "2", Eval2.eval(code, 2)); diff --git a/chapter25/src/test/java/com/seaofnodes/simple/Chapter20Test.java b/chapter25/src/test/java/com/seaofnodes/simple/Chapter20Test.java index e4754213..17b0fd0a 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/Chapter20Test.java +++ b/chapter25/src/test/java/com/seaofnodes/simple/Chapter20Test.java @@ -19,7 +19,7 @@ public class Chapter20Test { code.driver(CodeGen.Phase.RegAlloc,cpu,os); int delta = spills>>3; if( delta==0 ) delta = 1; - if( spills != -1 ) + if( spills != -1 && !CodeGen.iterSeedOverridden() ) assertEquals("Expect spills:",spills,code._regAlloc._spillScaled,delta); if( stop != null ) assertEquals(stop, code.print()); diff --git a/chapter25/src/test/java/com/seaofnodes/simple/Chapter21Test.java b/chapter25/src/test/java/com/seaofnodes/simple/Chapter21Test.java index a4621165..e4d49e7f 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/Chapter21Test.java +++ b/chapter25/src/test/java/com/seaofnodes/simple/Chapter21Test.java @@ -40,7 +40,7 @@ return new _s0.v1; CodeGen code = new CodeGen(src).driver(CodeGen.Phase.Encoding,cpu,os); int delta = spills>>3; if( delta==0 ) delta = 1; - if( spills != -1 ) + if( spills != -1 && !CodeGen.iterSeedOverridden() ) assertEquals("Expect spills:",spills,code._regAlloc._spillScaled,delta); if( stop != null ) assertEquals(stop, code.print()); diff --git a/chapter25/src/test/java/com/seaofnodes/simple/Chapter22Test.java b/chapter25/src/test/java/com/seaofnodes/simple/Chapter22Test.java index 5a171659..91b8310d 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/Chapter22Test.java +++ b/chapter25/src/test/java/com/seaofnodes/simple/Chapter22Test.java @@ -40,7 +40,7 @@ return new s0.v1; CodeGen code = new CodeGen(src).driver(CodeGen.Phase.Encoding,cpu,os); int delta = spills>>3; if( delta==0 ) delta = 1; - if( spills != -1 ) + if( spills != -1 && !CodeGen.iterSeedOverridden() ) assertEquals("Expect spills:",spills,code._regAlloc._spillScaled,delta); if( stop != null ) assertEquals(stop, code.print()); diff --git a/chapter25/src/test/java/com/seaofnodes/simple/Chapter23Test.java b/chapter25/src/test/java/com/seaofnodes/simple/Chapter23Test.java index 7e64f226..08acfd32 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/Chapter23Test.java +++ b/chapter25/src/test/java/com/seaofnodes/simple/Chapter23Test.java @@ -25,7 +25,7 @@ public class Chapter23Test { CodeGen code = new CodeGen(src).driver(CodeGen.Phase.Encoding,cpu,os); int delta = spills>>3; if( delta==0 ) delta = 1; - if( spills != -1 ) + if( spills != -1 && !CodeGen.iterSeedOverridden() ) assertEquals("Expect spills:",spills,code._regAlloc._spillScaled,delta); if( stop != null ) assertEquals(stop, code.print()); diff --git a/chapter25/src/test/java/com/seaofnodes/simple/Chapter24Test.java b/chapter25/src/test/java/com/seaofnodes/simple/Chapter24Test.java index 0f2e1bed..fe8aaf2e 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/Chapter24Test.java +++ b/chapter25/src/test/java/com/seaofnodes/simple/Chapter24Test.java @@ -20,7 +20,7 @@ public class Chapter24Test { CodeGen code = new CodeGen(src).driver(CodeGen.Phase.Encoding,cpu,os); int delta = spills>>3; if( delta==0 ) delta = 1; - if( spills != -1 ) + if( spills != -1 && !CodeGen.iterSeedOverridden() ) assertEquals("Expect spills:",spills,code._regAlloc._spillScaled,delta); if( stop != null ) assertEquals(stop, code.print()); diff --git a/chapter25/src/test/java/com/seaofnodes/simple/TestArm64.java b/chapter25/src/test/java/com/seaofnodes/simple/TestArm64.java index 7394b578..14864d64 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/TestArm64.java +++ b/chapter25/src/test/java/com/seaofnodes/simple/TestArm64.java @@ -19,7 +19,7 @@ public class TestArm64 { // Allocation quality not degraded int delta = spills>>3; if( delta == 0 ) delta =1; - if( spills != -1 ) assertEquals("Expect spills:", spills, code._regAlloc._spillScaled, delta); + if( spills != -1 && !CodeGen.iterSeedOverridden() ) assertEquals("Expect spills:", spills, code._regAlloc._spillScaled, delta); // Image byte[] image = new byte[1<<20]; // A megabyte (1024*1024 bytes) diff --git a/chapter25/src/test/java/com/seaofnodes/simple/TestC.java b/chapter25/src/test/java/com/seaofnodes/simple/TestC.java index 5c49d3a8..7177f765 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/TestC.java +++ b/chapter25/src/test/java/com/seaofnodes/simple/TestC.java @@ -99,7 +99,7 @@ public abstract class TestC { // Allocation quality not degraded int delta = spills>>3; if( delta==0 ) delta = 1; - if( spills != -1 ) + if( spills != -1 && !CodeGen.iterSeedOverridden() ) assertEquals("Expect spills:",spills,code._regAlloc._spillScaled,delta); } diff --git a/chapter25/src/test/java/com/seaofnodes/simple/TestRisc5.java b/chapter25/src/test/java/com/seaofnodes/simple/TestRisc5.java index aff95c38..658909ca 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/TestRisc5.java +++ b/chapter25/src/test/java/com/seaofnodes/simple/TestRisc5.java @@ -19,7 +19,7 @@ public abstract class TestRisc5 { // Allocation quality not degraded int delta = spills>>3; if( delta==0 ) delta = 1; - if( spills != -1 ) + if( spills != -1 && !CodeGen.iterSeedOverridden() ) assertEquals("Expect spills:",spills,code._regAlloc._spillScaled,delta); // Image -- cgit v1.2.3