summaryrefslogtreecommitdiff
path: root/chapter15/src/main/java/com
diff options
context:
space:
mode:
Diffstat (limited to 'chapter15/src/main/java/com')
-rw-r--r--chapter15/src/main/java/com/seaofnodes/simple/node/RegionNode.java56
-rw-r--r--chapter15/src/main/java/com/seaofnodes/simple/type/Type.java1
-rw-r--r--chapter15/src/main/java/com/seaofnodes/simple/type/TypeInteger.java8
-rw-r--r--chapter15/src/main/java/com/seaofnodes/simple/type/TypeMemPtr.java1
4 files changed, 65 insertions, 1 deletions
diff --git a/chapter15/src/main/java/com/seaofnodes/simple/node/RegionNode.java b/chapter15/src/main/java/com/seaofnodes/simple/node/RegionNode.java
index d5105614..0c7cd1e4 100644
--- a/chapter15/src/main/java/com/seaofnodes/simple/node/RegionNode.java
+++ b/chapter15/src/main/java/com/seaofnodes/simple/node/RegionNode.java
@@ -72,9 +72,65 @@ public class RegionNode extends CFGNode {
p1.in(0) instanceof IfNode iff )
return iff.ctrl();
+
+
+ // Look for direct uses of a guarded expression, and replace with the guard result.
+ if( !(idom() instanceof StartNode) && // Dead or dying
+ !(this instanceof LoopNode) ) {
+ VISIT.clear();
+ boolean progress = false;
+ outer:
+ for( int i=1; i<nIns(); i++ ) {
+ CFGNode idom = cfg(i);
+ while( !(idom instanceof CProjNode cproj) ) {
+ idom = idom.idom();
+ if( idom==null || idom.idepth() < idom().idepth() )
+ continue outer;
+ }
+ if( cproj.cfg0() instanceof IfNode iff && cproj.compute()==Type.CONTROL ) {
+ VISIT.set(iff.pred()._nid);
+ for( Node out : _outputs )
+ if( out instanceof PhiNode phi )
+ progress |= walk(iff,cproj,phi.in(i));
+ }
+ }
+ if( progress )
+ return this;
+ }
+
return null;
}
+ // A walk that can be cutoff early
+ private static final BitSet VISIT = new BitSet();
+ private static boolean walk( IfNode iff, CProjNode cproj, Node n ) {
+ if( VISIT.get(n._nid) ) return false;
+ VISIT.set(n._nid);
+ if( n instanceof CFGNode ) return false;
+ if( n.in(0)!=null && n.cfg0().idepth() < iff.idepth() )
+ return false;
+ boolean progress = false;
+ Node pred = iff.pred();
+ for( int i=1; i<n.nIns(); i++ ) {
+ // Using a tested value
+ if( n.in(i) == pred && !(n instanceof CastNode) ) {
+ // Checking pred for T/F
+ Type t = pred._type;
+ Type tcast = cproj._idx==0 ? t.nonZero() : t.makeInit();
+ if( t!=tcast ) { // Progress to cast
+ Node cast = new CastNode( tcast, cproj, pred ).peephole();
+ n.setDef( i, cast );
+ IterPeeps.add(n);
+ progress = true;
+ }
+ }
+ if( n.in(i)!=null )
+ progress |= walk(iff,cproj,n.in(i));
+ }
+ return progress;
+ }
+
+
private int findDeadInput() {
for( int i=1; i<nIns(); i++ )
if( in(i)._type==Type.XCONTROL )
diff --git a/chapter15/src/main/java/com/seaofnodes/simple/type/Type.java b/chapter15/src/main/java/com/seaofnodes/simple/type/Type.java
index 983fcf98..989eff9e 100644
--- a/chapter15/src/main/java/com/seaofnodes/simple/type/Type.java
+++ b/chapter15/src/main/java/com/seaofnodes/simple/type/Type.java
@@ -82,6 +82,7 @@ public class Type {
public StringBuilder typeName( StringBuilder sb) { return print(sb); }
public Type makeInit() { return null; }
+ public Type nonZero() { return glb(); }
// ----------------------------------------------------------
diff --git a/chapter15/src/main/java/com/seaofnodes/simple/type/TypeInteger.java b/chapter15/src/main/java/com/seaofnodes/simple/type/TypeInteger.java
index fca3362e..042b4ba8 100644
--- a/chapter15/src/main/java/com/seaofnodes/simple/type/TypeInteger.java
+++ b/chapter15/src/main/java/com/seaofnodes/simple/type/TypeInteger.java
@@ -113,8 +113,14 @@ public class TypeInteger extends Type {
}
@Override public TypeInteger dual() { return make(_max,_min); }
- @Override public Type glb() { return BOT; }
+ @Override public TypeInteger glb() { return BOT; }
@Override public TypeInteger makeInit() { return ZERO; }
+ @Override public TypeInteger nonZero() {
+ if( isHigh() ) return this;
+ if( _min==0 ) return make(1,_max); // specifically good on BOOL
+ if( _max==0 ) return make(_min,-1);
+ return this;
+ }
@Override int hash() { return (int)((_min ^ (_min>>32)) *(_max ^ (_max>>32))); }
@Override
public boolean eq( Type t ) {
diff --git a/chapter15/src/main/java/com/seaofnodes/simple/type/TypeMemPtr.java b/chapter15/src/main/java/com/seaofnodes/simple/type/TypeMemPtr.java
index 7743c80d..8b484235 100644
--- a/chapter15/src/main/java/com/seaofnodes/simple/type/TypeMemPtr.java
+++ b/chapter15/src/main/java/com/seaofnodes/simple/type/TypeMemPtr.java
@@ -58,6 +58,7 @@ public class TypeMemPtr extends Type {
@Override
public TypeMemPtr glb() { return make(_obj.glb(),true); }
@Override public TypeMemPtr makeInit() { return NULLPTR; }
+ @Override public Type nonZero() { return VOIDPTR; }
@Override public boolean isHigh() { return this==TOP; }