diff options
Diffstat (limited to 'chapter25/src/main/java')
10 files changed, 46 insertions, 14 deletions
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 24a12e6d..ca2cc955 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/codegen/CodeGen.java @@ -342,19 +342,23 @@ public class CodeGen { // idepths are cached and valid until *inserting* CFG edges (deleting is // OK). This happens with inlining, which bumps the version to bulk // invalidate the idepth caches. + private static final int IDEPTH_STRIDE = 1_000_000; private int _iDepthVersion = 0; - public void invalidateIDepthCaches() { _iDepthVersion++; } + public void invalidateIDepthCaches() { + ++_iDepthVersion; + assert _iDepthVersion < IDEPTH_STRIDE; // Wrapped; needs a major hack to fix + } public boolean validIDepth(int idepth) { if( idepth==0 ) return false; if( _iDepthVersion==0 ) return true; - return (idepth%100)==_iDepthVersion; + return (idepth%IDEPTH_STRIDE)==_iDepthVersion; } public int iDepthAt(int idepth) { - return 100*idepth+_iDepthVersion; + return IDEPTH_STRIDE*idepth+_iDepthVersion; } public int iDepthFrom(int idepth) { assert idepth==0 || validIDepth(idepth); - return idepth+100; + return idepth+IDEPTH_STRIDE; } // Popular visit bitset, declared here, so it gets reused all over @@ -815,7 +819,7 @@ public class CodeGen { // need to be re-hooked to stop/start less they go dead. for( FunNode fun : _linker ) { // Already linked to start, not going dead - if( fun==null || fun.isDead() || fun._type.isHigh() ) + if( fun==null || fun.isDead() ) continue; // Imported functions are not emitted by this object. Unlink any @@ -854,7 +858,7 @@ public class CodeGen { ReturnNode ret = fun.ret(); StartNode start = fun._compunit._start; assert start!=null; - if( fun.in(1) != start ) { + if( fun.nIns() <= 1 || fun.in(1) != start ) { fun.insertDef(1,start); for( Node use : fun._outputs ) if( use instanceof ParmNode parm ) @@ -876,6 +880,16 @@ public class CodeGen { } } + _stop.walk(n -> { + if( n instanceof CallEndNode cend ) + for( int i=1; i<cend.nIns(); i++ ) + if( cend.in(i) instanceof ReturnNode ) + cend.delDef(i--); + if( n instanceof CallNode call ) + call.unlink_all(); + return null; + }); + _times[Phase.Unlink.ordinal()] = System.currentTimeMillis() - t0; } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/AndNode.java b/chapter25/src/main/java/com/seaofnodes/simple/node/AndNode.java index 083a9a8c..95095ac3 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/AndNode.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/AndNode.java @@ -22,6 +22,7 @@ public class AndNode extends ArithNode { public Node idealize() { Node lhs = in(1); Node rhs = in(2); + Type t1 = lhs._type; Type t2 = rhs._type; if( !(t1 instanceof TypeInteger && t2 instanceof TypeInteger t2i) ) @@ -30,7 +31,7 @@ public class AndNode extends ArithNode { // And of -1. We do not check for (-1&x) because this will already // canonicalize to (x&-1). We do not check for zero, because // the compute() call will return a zero already. - if( t2i.isConstant() && t2i.value()==-1 ) + if( t2i.isConstant() && t2i.value()==-1 && forceInt(lhs) ) return lhs; // Move constants to RHS: con*arg becomes arg*con diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/ArithNode.java b/chapter25/src/main/java/com/seaofnodes/simple/node/ArithNode.java index ffba1f16..dfd81504 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/ArithNode.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/ArithNode.java @@ -50,6 +50,18 @@ public abstract class ArithNode extends Node implements ModeNode { return 0; } + // Int-only ops, such as &, | and shifts, can collapse to one input. If + // that input, or the live arms of a Phi input, are still mode-polymorphic + // ops, settle them before returning the value so the replacement remains + // at least as narrow as the int-only op. + static boolean forceInt(Node n) { + if( n instanceof ModeNode mode && mode.mode()==0 ) { + mode.setMode((byte)1); + n.setType(n.compute()); + } + return true; + } + // Check that a settled mode agrees with all data inputs. Takes the Node // instead of a varargs list both to avoid allocation and to keep this ready // to become shared mode-aware Node behavior later. diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/MinusNode.java b/chapter25/src/main/java/com/seaofnodes/simple/node/MinusNode.java index 4df68a3b..2261adab 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/MinusNode.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/MinusNode.java @@ -1,6 +1,7 @@ package com.seaofnodes.simple.node; import com.seaofnodes.simple.Parser; +import com.seaofnodes.simple.codegen.CodeGen; import com.seaofnodes.simple.type.*; import com.seaofnodes.simple.util.BAOS; import com.seaofnodes.simple.util.Utils; @@ -49,7 +50,7 @@ public class MinusNode extends Node implements ModeNode { if( t instanceof TypeInteger ) mode=1; } if( mode==0 ) - return Type.BOTTOM; + return CodeGen.CODE._phase.ordinal() < CodeGen.Phase.Opto.ordinal() ? Type.BOTTOM : Type.TOP; if( mode==1 ) { if( t instanceof TypeInteger i0 && i0._min != Long.MIN_VALUE && i0._max != Long.MIN_VALUE ) diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/OrNode.java b/chapter25/src/main/java/com/seaofnodes/simple/node/OrNode.java index 66e561dc..31d0565b 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/OrNode.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/OrNode.java @@ -22,12 +22,13 @@ public class OrNode extends ArithNode { public Node idealize() { Node lhs = in(1); Node rhs = in(2); + Type t1 = lhs._type; Type t2 = rhs._type; // Or of 0. We do not check for (0|x) because this will already // canonicalize to (x|0) - if( t2.isConstant() && t2 instanceof TypeInteger i && i.value()==0 && t1.isa(TypeInteger.BOT) ) + if( t2.isConstant() && t2 instanceof TypeInteger i && i.value()==0 && t1.isa(TypeInteger.BOT) && forceInt(lhs) ) return lhs; // Move constants to RHS: con*arg becomes arg*con diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/RegionNode.java b/chapter25/src/main/java/com/seaofnodes/simple/node/RegionNode.java index dc48f6f2..81d0d6b9 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/RegionNode.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/RegionNode.java @@ -111,7 +111,8 @@ public class RegionNode extends CFGNode { CodeGen.CODE.addAll(phi.delDef(path)._outputs); } } - return isDead() ? CodeGen.CODE.XCTRL : delDef(path); + if( !isDead() ) delDef(path); + return isDead() ? CodeGen.CODE.XCTRL : this; } private int findDeadInput(int startIdx) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/SarNode.java b/chapter25/src/main/java/com/seaofnodes/simple/node/SarNode.java index 8ad5988d..e3f99ed4 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/SarNode.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/SarNode.java @@ -24,10 +24,11 @@ public class SarNode extends ArithNode { public Node idealize() { Node lhs = in(1); Node rhs = in(2); + Type t2 = rhs._type; // Sar of 0. - if( t2.isConstant() && t2 instanceof TypeInteger i && (i.value()&63)==0 ) + if( t2.isConstant() && t2 instanceof TypeInteger i && (i.value()&63)==0 && forceInt(lhs) ) return lhs; // TODO: x >> 3 >> (y ? 1 : 2) ==> x >> (y ? 4 : 5) diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/ShlNode.java b/chapter25/src/main/java/com/seaofnodes/simple/node/ShlNode.java index 459b26eb..24d9bdb4 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/ShlNode.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/ShlNode.java @@ -33,7 +33,7 @@ public class ShlNode extends ArithNode { if( rhs._type instanceof TypeInteger shl && shl.isConstant() ) { // Shl of 0. - if( (shl.value()&63)==0 ) + if( (shl.value()&63)==0 && forceInt(lhs) ) return lhs; // (x + c) << i => (x << i) + (c << i) if( lhs instanceof AddNode add && addDep(add).in(2)._type instanceof TypeInteger c && c.isConstant() ) { diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/ShrNode.java b/chapter25/src/main/java/com/seaofnodes/simple/node/ShrNode.java index 5e4870d1..1bf7d118 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/ShrNode.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/ShrNode.java @@ -23,7 +23,7 @@ public class ShrNode extends ArithNode { Type t2 = rhs._type; // Shr of 0. - if( t2.isConstant() && t2 instanceof TypeInteger i && (i.value()&63)==0 ) + if( t2.isConstant() && t2 instanceof TypeInteger i && (i.value()&63)==0 && forceInt(lhs) ) return lhs; // TODO: x >>> 3 >>> (y ? 1 : 2) ==> x >>> (y ? 4 : 5) diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/XorNode.java b/chapter25/src/main/java/com/seaofnodes/simple/node/XorNode.java index 95d4461e..27ebc3dc 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/XorNode.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/XorNode.java @@ -20,12 +20,13 @@ public class XorNode extends ArithNode { public Node idealize() { Node lhs = in(1); Node rhs = in(2); + Type t1 = lhs._type; Type t2 = rhs._type; // Xor of 0. We do not check for (0^x) because this will already // canonicalize to (x^0) - if( t2.isConstant() && t2 instanceof TypeInteger i && i.value()==0 ) + if( t2.isConstant() && t2 instanceof TypeInteger i && i.value()==0 && forceInt(lhs) ) return lhs; // Move constants to RHS: con*arg becomes arg*con |
