diff options
| author | Cliff Click <cliffc@acm.org> | 2025-01-09 12:08:51 -0800 |
|---|---|---|
| committer | Cliff Click <cliffc@acm.org> | 2025-01-15 15:07:30 -0800 |
| commit | 64ebe7529f9798ce036ab86ad4e09071152fe64d (patch) | |
| tree | e4b3bba870ff2f9b838ef3a00918f1ae5081449f | |
| parent | dd67005904ab8f93bacd595290159b20d10f75a5 (diff) | |
| download | Simple-64ebe7529f9798ce036ab86ad4e09071152fe64d.tar.gz Simple-64ebe7529f9798ce036ab86ad4e09071152fe64d.zip | |
Final vars and forced constants do not lazy-phi
Better comments on why a field is final
3 files changed, 33 insertions, 6 deletions
diff --git a/chapter18/src/main/java/com/seaofnodes/simple/Parser.java b/chapter18/src/main/java/com/seaofnodes/simple/Parser.java index 3f4484f5..a6185aa0 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/Parser.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/Parser.java @@ -694,10 +694,16 @@ public class Parser { Node expr; if( match("=") ) { expr = parseAsgn(); - // `val` is always final + // TOP means val and val is always final xfinal = (t==Type.TOP) || - // var is always not-final, final if no Bang AND TMP since primitives are not-final by default - (t!=Type.BOTTOM && !hasBang && (t instanceof TypeMemPtr)); + // BOTTOM is var and var is always not-final + (t!=Type.BOTTOM && + // no Bang AND + !hasBang && + // not-null (expecting null to be set to not-null) + expr._type != Type.NIL && + // Pointers are final by default; int/flt are not-final by default. + (t instanceof TypeNil)); // var/val, then type comes from expression if( inferType ) { if( expr._type==Type.NIL ) diff --git a/chapter18/src/main/java/com/seaofnodes/simple/node/ScopeNode.java b/chapter18/src/main/java/com/seaofnodes/simple/node/ScopeNode.java index 5620a2d2..d0d86b79 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/node/ScopeNode.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/node/ScopeNode.java @@ -209,6 +209,7 @@ public class ScopeNode extends MemMergeNode { : loop.setDef(v._idx,new PhiNode(v._name, v.lazyGLB(), loop.ctrl(), loop.in(loop.update(v,null)._idx),null).peephole()); setDef(v._idx,old); } + assert !v._final || st==null; if( st!=null ) setDef(v._idx,st); // Set new value return v; } @@ -258,7 +259,7 @@ public class ScopeNode extends MemMergeNode { for( int i=2; i<nIns(); i++ ) // For lazy phis on loops we use a sentinel // that will trigger phi creation on update - dup.addDef(loop ? this : in(i)); + dup.addDef(loop && !_vars.at(i)._final ? this : in(i)); return dup; } @@ -327,6 +328,8 @@ public class ScopeNode extends MemMergeNode { // Fill in the backedge of any inserted Phis void _endLoop( ScopeNode scope, Node back, Node exit ) { for( int i=2; i<nIns(); i++ ) { + if( _vars.at(i)._final ) continue; // Final vars did not get modified in the loop + if( _vars.at(i).type().isHighOrConst() ) continue; // Cannot lift higher than a constant, so no Phi if( back.in(i) != scope ) { PhiNode phi = (PhiNode)in(i); assert phi.region()==scope.ctrl() && phi.in(2)==null; diff --git a/chapter18/src/test/java/com/seaofnodes/simple/Chapter18Test.java b/chapter18/src/test/java/com/seaofnodes/simple/Chapter18Test.java index 39edb352..8852537b 100644 --- a/chapter18/src/test/java/com/seaofnodes/simple/Chapter18Test.java +++ b/chapter18/src/test/java/com/seaofnodes/simple/Chapter18Test.java @@ -13,7 +13,7 @@ public class Chapter18Test { """ return 0; """); - code.parse().opto().typeCheck().GCM(); + code.parse().opto().typeCheck().GCM().localSched(); assertEquals("return 0;", code._stop.toString()); assertEquals("0", Eval2.eval(code, 0)); } @@ -179,6 +179,24 @@ return 2; assertEquals("1", Eval2.eval(code, 0)); } + @Test + public void testFcn8() { + CodeGen code = new CodeGen( +""" +{int -> int}? i2i = null; +var id = {{int->int} f-> return f;}; +for(;;) { + if (i2i) return i2i(arg); + var x = {int i-> return i;}; + arg = x(3); + i2i = id(x); +} +"""); + code.parse().opto().typeCheck().GCM().localSched(); + assertEquals("Stop[ return x( Phi(Loop,arg,x( 3))); return Parm_i(x,int,3,Phi_arg); ]", code._stop.toString()); + assertEquals("3", Eval2.eval(code, 0)); + } + // Function break @Test @@ -203,7 +221,7 @@ return 1; public void testErr2() { CodeGen code = new CodeGen( """ -{int -> int}? i2i = { int i -> return i; }; +{int -> int}? !i2i = { int i -> return i; }; for(;;) { if (i2i(2) == arg) break; i2i = null; |
