diff options
Diffstat (limited to 'chapter18')
9 files changed, 50 insertions, 20 deletions
diff --git a/chapter18/src/main/java/com/seaofnodes/simple/Parser.java b/chapter18/src/main/java/com/seaofnodes/simple/Parser.java index 649145fd..8f0cf493 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/Parser.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/Parser.java @@ -708,7 +708,8 @@ public class Parser { if( inferType ) { if( expr._type==Type.NIL ) throw error("a not-null/non-zero expression"); - t = expr._type.glb(); + t = expr._type; + if( !xfinal ) t = t.glb(); // Widen if not final } if( t instanceof TypeFunPtr && expr._type instanceof TypeFunPtr tfp && tfp.isConstant() ) tfp.setName(name); diff --git a/chapter18/src/main/java/com/seaofnodes/simple/node/CallEndNode.java b/chapter18/src/main/java/com/seaofnodes/simple/node/CallEndNode.java index c9ea2f1f..48edc0eb 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/node/CallEndNode.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/node/CallEndNode.java @@ -26,8 +26,7 @@ public class CallEndNode extends CFGNode implements MultiNode { @Override StringBuilder _print1(StringBuilder sb, BitSet visited) { sb.append("cend( "); - if( call()==null ) sb.append("---, "); - else sb.append("Call, "); + sb.append( in(0) instanceof CallNode ? "Call, " : "----, "); for( int i=1; i<nIns()-1; i++ ) in(i)._print0(sb,visited).append(","); sb.setLength(sb.length()-1); @@ -36,8 +35,10 @@ public class CallEndNode extends CFGNode implements MultiNode { @Override public Type compute() { - Type ret = call().fptr()._type instanceof TypeFunPtr tfp ? tfp.ret() : Type.BOTTOM; - return TypeTuple.make(call()._type,TypeMem.BOT,ret); + if( !(in(0) instanceof CallNode call) ) + return TypeTuple.RET.dual(); + Type ret = call.fptr().addDep(this)._type instanceof TypeFunPtr tfp ? tfp.ret() : Type.BOTTOM; + return TypeTuple.make(call._type,TypeMem.BOT,ret); } @Override diff --git a/chapter18/src/main/java/com/seaofnodes/simple/node/IfNode.java b/chapter18/src/main/java/com/seaofnodes/simple/node/IfNode.java index 1e6b2878..c49ee662 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/node/IfNode.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/node/IfNode.java @@ -43,7 +43,7 @@ public class IfNode extends CFGNode implements MultiNode { // If constant is 0 then false branch is reachable // Else true branch is reachable if( t.isConstant() ) - return (t==Type.NIL || t==TypeInteger.ZERO) ? TypeTuple.IF_FALSE : TypeTuple.IF_TRUE; + return (t==Type.NIL || t==TypeInteger.ZERO || (t instanceof TypeFunPtr tfp && tfp._fidxs==0) ) ? TypeTuple.IF_FALSE : TypeTuple.IF_TRUE; // If adding a zero makes a difference, the predicate must not have a zero/null if( !t.makeZero().isa(t) ) return TypeTuple.IF_TRUE; diff --git a/chapter18/src/main/java/com/seaofnodes/simple/node/LoopNode.java b/chapter18/src/main/java/com/seaofnodes/simple/node/LoopNode.java index b54403b7..a31c8ac8 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/node/LoopNode.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/node/LoopNode.java @@ -25,7 +25,19 @@ public class LoopNode extends RegionNode { @Override public Node idealize() { - return inProgress() ? null : super.idealize(); + if( inProgress() ) return null; + // Dead infinite loops with NO control flow out stick around - as a + // dead infinite loop, to signal that control stops and spins here. + if( nIns()==2 && !hasPhi() && !hasCFG() ) + return null; + return super.idealize(); + } + + private boolean hasCFG() { + for( Node phi : _outputs ) + if( phi instanceof CFGNode ) + return true; + return false; } // Bypass Region idom, same as the default idom() using use in(1) instead of in(0) diff --git a/chapter18/src/main/java/com/seaofnodes/simple/node/RegionNode.java b/chapter18/src/main/java/com/seaofnodes/simple/node/RegionNode.java index 5045b43b..d8e24964 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/node/RegionNode.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/node/RegionNode.java @@ -86,7 +86,7 @@ public class RegionNode extends CFGNode { return 0; // All inputs alive } - private boolean hasPhi() { + boolean hasPhi() { for( Node phi : _outputs ) if( phi instanceof PhiNode ) return true; diff --git a/chapter18/src/main/java/com/seaofnodes/simple/node/ReturnNode.java b/chapter18/src/main/java/com/seaofnodes/simple/node/ReturnNode.java index f42adcf6..2fe722c6 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/node/ReturnNode.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/node/ReturnNode.java @@ -45,12 +45,14 @@ public class ReturnNode extends CFGNode { @Override public Type compute() { - if( inProgress() ) return TypeTuple.RET; // In progress + if( inProgress () ) return TypeTuple.RET; // In progress + if( _fun.isDead() ) return TypeTuple.RET.dual(); // Dead another way return TypeTuple.make(ctrl()._type,mem()._type,expr()._type); } @Override public Node idealize() { - if( inProgress() ) return null; + if( inProgress () ) return null; + if( _fun.isDead() ) return null; // Upgrade signature based on return type Type ret = expr()._type; diff --git a/chapter18/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java b/chapter18/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java index 5799fea9..cf92d3d7 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java @@ -24,7 +24,7 @@ public class TypeFunPtr extends TypeNil { // Cheesy easy implementation for a small set; 1 bit per unique function // within the TypeTuple. Can be upgraded to a BitSet for larger classes of // functions. Negative means "these 63 concrete bits plus infinite unknown more" - private final long _fidxs; // 63 unique functions per signature + public final long _fidxs; // 63 unique functions per signature public String _name; // Optional debug function name; only for named single function private TypeFunPtr(byte nil, TypeTuple sig, Type ret, long fidxs) { @@ -69,12 +69,13 @@ public class TypeFunPtr extends TypeNil { @Override public TypeFunPtr dual() { return TypeFunPtr.make(dual0(), _sig.dual(), _ret.dual(), ~_fidxs); } - // RHS is NIL + // RHS is NIL; do not deep-dual when crossing the centerline @Override public Type meet0() { return _nil==3 ? this : make((byte)3,_sig,_ret,_fidxs); } - @Override public TypeFunPtr glb() { return make(_nil,_sig,_ret,_fidxs); } + @Override public TypeFunPtr glb() { return make((byte)3,_sig,_ret,-1L); } - @Override public boolean isConstant() { return _nil==2 && Long.bitCount(_fidxs)==1; } + @Override public boolean isHigh () { return _nil <= 1 || (_nil==2 && _fidxs==0); } + @Override public boolean isConstant() { return (_nil==2 && Long.bitCount(_fidxs)==1) || (_nil==3 && _fidxs==0); } @Override public int log_size() { return 2; } // (1<<2)==4-byte pointers diff --git a/chapter18/src/main/java/com/seaofnodes/simple/type/TypeMemPtr.java b/chapter18/src/main/java/com/seaofnodes/simple/type/TypeMemPtr.java index c8a5c1f4..d7a8b17d 100644 --- a/chapter18/src/main/java/com/seaofnodes/simple/type/TypeMemPtr.java +++ b/chapter18/src/main/java/com/seaofnodes/simple/type/TypeMemPtr.java @@ -58,11 +58,8 @@ public class TypeMemPtr extends TypeNil { @Override public TypeMemPtr dual() { return TypeMemPtr.make( dual0(), _obj.dual()); } - // RHS is NIL - @Override Type meet0() { - // NOT DOING DUAL - return _nil==3 ? this : make((byte)3,_obj); - } + // RHS is NIL; do not deep-dual when crossing the centerline + @Override Type meet0() { return _nil==3 ? this : make((byte)3,_obj); } // True if this "isa" t up to named structures diff --git a/chapter18/src/test/java/com/seaofnodes/simple/Chapter18Test.java b/chapter18/src/test/java/com/seaofnodes/simple/Chapter18Test.java index 217c6275..3fc5c8de 100644 --- a/chapter18/src/test/java/com/seaofnodes/simple/Chapter18Test.java +++ b/chapter18/src/test/java/com/seaofnodes/simple/Chapter18Test.java @@ -115,7 +115,7 @@ var fcn = arg ? { int x -> x*x; } : { int x -> x+x; }; return fcn(3); """); code.parse().opto(); - assertEquals("Stop[ return Phi(Region,{ int -> int #1},{ int -> int #2})( 3); return (Parm_x($fun,int)*x); return (Parm_x($fun,int)*2); ]", code._stop.toString()); + assertEquals("Stop[ return Phi(Region,{ int -> int #1},{ int -> int #2})( 3); return (Parm_x($fun,int,3)*x); return (Parm_x($fun,int,3)*2); ]", code._stop.toString()); assertEquals("6", Eval2.eval(code, 0)); assertEquals("9", Eval2.eval(code, 1)); } @@ -180,6 +180,22 @@ for(;;) { } + @Test + public void testFcn9() { + CodeGen code = new CodeGen( +""" +{int -> int}? i2i = null; +for(;;) { + if (i2i) return i2i(arg); + var x = {int i-> return i;}; + arg = x(3); +} +"""); + code.parse().opto().typeCheck().GCM().localSched(); + assertEquals("Stop[ ]", code._stop.toString()); + assertEquals("0", Eval2.eval(code, 0)); + } + // Function break @Test public void testErr1() { |
