summaryrefslogtreecommitdiff
path: root/chapter18/src/main/java/com/seaofnodes
diff options
context:
space:
mode:
Diffstat (limited to 'chapter18/src/main/java/com/seaofnodes')
-rw-r--r--chapter18/src/main/java/com/seaofnodes/simple/CodeGen.java2
-rw-r--r--chapter18/src/main/java/com/seaofnodes/simple/Parser.java9
-rw-r--r--chapter18/src/main/java/com/seaofnodes/simple/node/CFGNode.java2
-rw-r--r--chapter18/src/main/java/com/seaofnodes/simple/node/CastNode.java10
-rw-r--r--chapter18/src/main/java/com/seaofnodes/simple/node/LoadNode.java7
-rw-r--r--chapter18/src/main/java/com/seaofnodes/simple/node/LoopNode.java35
-rw-r--r--chapter18/src/main/java/com/seaofnodes/simple/node/MemOpNode.java1
-rw-r--r--chapter18/src/main/java/com/seaofnodes/simple/node/Node.java3
-rw-r--r--chapter18/src/main/java/com/seaofnodes/simple/node/PhiNode.java2
-rw-r--r--chapter18/src/main/java/com/seaofnodes/simple/node/ScopeMinNode.java4
-rw-r--r--chapter18/src/main/java/com/seaofnodes/simple/node/ScopeNode.java10
-rw-r--r--chapter18/src/main/java/com/seaofnodes/simple/type/Field.java3
-rw-r--r--chapter18/src/main/java/com/seaofnodes/simple/type/TypeFloat.java4
-rw-r--r--chapter18/src/main/java/com/seaofnodes/simple/type/TypeInteger.java3
14 files changed, 65 insertions, 30 deletions
diff --git a/chapter18/src/main/java/com/seaofnodes/simple/CodeGen.java b/chapter18/src/main/java/com/seaofnodes/simple/CodeGen.java
index 394b6d1c..51a6e78e 100644
--- a/chapter18/src/main/java/com/seaofnodes/simple/CodeGen.java
+++ b/chapter18/src/main/java/com/seaofnodes/simple/CodeGen.java
@@ -66,7 +66,7 @@ public class CodeGen {
// Type check
String err = _stop.walk( Node::err );
if( err != null )
- throw new RuntimeException(err);
+ throw new Parser.ParserException(err);
return this;
}
diff --git a/chapter18/src/main/java/com/seaofnodes/simple/Parser.java b/chapter18/src/main/java/com/seaofnodes/simple/Parser.java
index 6267c09d..79d5ce4a 100644
--- a/chapter18/src/main/java/com/seaofnodes/simple/Parser.java
+++ b/chapter18/src/main/java/com/seaofnodes/simple/Parser.java
@@ -1006,7 +1006,7 @@ public class Parser {
String name = _lexer.matchId();
if( name!=null ) {
ScopeMinNode.Var n = _scope.lookup(name);
- if( n != null ) {
+ if( n != null && !(n.type() instanceof TypeMemPtr) ) {
if( n._final )
throw error("Cannot reassign final '"+n._name+"'");
Node expr = n.type() instanceof TypeFloat
@@ -1597,6 +1597,7 @@ public class Parser {
if( "+-/*&|^".indexOf(ch0) == -1 ) return 0;
char ch1 = (char)_input[_position+1];
if( ch1 == '=' ) { _position += 2; return ch0; }
+ if( isIdLetter((char)_input[_position+2]) ) return 0;
if( ch0 == '+' && ch1 == '+' ) { _position += 2; return (char) 1; }
if( ch0 == '-' && ch1 == '-' ) { _position += 2; return (char)-1; }
return 0;
@@ -1605,7 +1606,11 @@ public class Parser {
public RuntimeException error( String errorMessage ) {
// file:line:charoff err
//String msg = "src:"+_line_number+":"+(_position-_line_start)+" "+errorMessage;
- return new RuntimeException(errorMessage);
+ return new ParserException(errorMessage);
}
+
+ }
+ public static class ParserException extends RuntimeException {
+ ParserException(String msg) { super(msg); }
}
}
diff --git a/chapter18/src/main/java/com/seaofnodes/simple/node/CFGNode.java b/chapter18/src/main/java/com/seaofnodes/simple/node/CFGNode.java
index bacc1935..78071920 100644
--- a/chapter18/src/main/java/com/seaofnodes/simple/node/CFGNode.java
+++ b/chapter18/src/main/java/com/seaofnodes/simple/node/CFGNode.java
@@ -109,6 +109,8 @@ public abstract class CFGNode extends Node {
for( Node use : _outputs ) {
if( !(use instanceof CFGNode usecfg) ) continue;
if( usecfg instanceof XCtrlNode ) continue;
+ if( usecfg._type == Type.XCONTROL ) continue; // Dead, only possible if peeps disabled
+ if( usecfg._type == TypeTuple.IF_NEITHER ) continue; // Dead again
// Child visited but not post-visited?
if( !post.get(usecfg._nid) ) {
// Must be a backedge to a LoopNode then
diff --git a/chapter18/src/main/java/com/seaofnodes/simple/node/CastNode.java b/chapter18/src/main/java/com/seaofnodes/simple/node/CastNode.java
index 462d6cba..4adc81ff 100644
--- a/chapter18/src/main/java/com/seaofnodes/simple/node/CastNode.java
+++ b/chapter18/src/main/java/com/seaofnodes/simple/node/CastNode.java
@@ -22,6 +22,7 @@ public class CastNode extends Node {
public String uniqueName() { return "Cast_" + _nid; }
@Override public boolean isPinned() { return true; }
+ @Override public boolean isConst() { return true; }
@Override
StringBuilder _print1(StringBuilder sb, BitSet visited) {
@@ -37,4 +38,13 @@ public class CastNode extends Node {
public Node idealize() {
return in(1)._type.isa(_t) ? in(1) : null;
}
+
+ @Override
+ boolean eq(Node n) {
+ CastNode cast = (CastNode)n; // Contract
+ return _t==cast._t;
+ }
+
+ @Override
+ int hash() { return _t.hashCode(); }
}
diff --git a/chapter18/src/main/java/com/seaofnodes/simple/node/LoadNode.java b/chapter18/src/main/java/com/seaofnodes/simple/node/LoadNode.java
index 1528f2e9..c69d319e 100644
--- a/chapter18/src/main/java/com/seaofnodes/simple/node/LoadNode.java
+++ b/chapter18/src/main/java/com/seaofnodes/simple/node/LoadNode.java
@@ -70,7 +70,7 @@ public class LoadNode extends MemOpNode {
while( true ) {
switch( mem ) {
case StoreNode st:
- if( ptr == st.ptr() && off() == st.off() )
+ if( ptr == st.ptr().addDep(this) && off() == st.off() )
return castRO(st.val()); // Proved equal
// Can we prove unequal? Offsets do not overlap?
if( !off()._type.join(st.off()._type).isHigh() && // Offsets overlap
@@ -79,7 +79,10 @@ public class LoadNode extends MemOpNode {
// Pointers cannot overlap
mem = st.mem(); // Proved never equal
break;
- case PhiNode phi: break outer; // Assume related
+ case PhiNode phi:
+ // Assume related
+ phi.addDep(this);
+ break outer;
case ConstantNode top: break outer; // Assume shortly dead
case ProjNode mproj:
if( mproj.in(0) instanceof NewNode nnn1 ) {
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 001ab8f2..f7f6f80d 100644
--- a/chapter18/src/main/java/com/seaofnodes/simple/node/LoopNode.java
+++ b/chapter18/src/main/java/com/seaofnodes/simple/node/LoopNode.java
@@ -53,29 +53,38 @@ public class LoopNode extends RegionNode {
for( Node use : _outputs )
if( use instanceof PhiNode )
iff.addDef(use);
- CProjNode t = new CProjNode(iff,0,"True" );
- CProjNode f = new CProjNode(iff,1,"False");
+ CProjNode t = new CProjNode(iff,0,"True" ).init();
+ CProjNode f = new CProjNode(iff,1,"False").init();
setDef(2,f);
// Now fold control into the exit. Might have 1 valid exit, or an
// XCtrl or a bunch of prior NeverNode exits.
Node top = new ConstantNode(Type.TOP).peephole();
ReturnNode ret = fun.ret();
- if( ret.ctrl()._type == Type.XCONTROL ) {
- ret.setDef(0,t);
- ret.setDef(1,top);
- ret.setDef(2,top);
- } else {
- RegionNode ctrl = ret.ctrl() instanceof RegionNode r ? r : new RegionNode(null,ret.ctrl());
- PhiNode mem = ret.mem () instanceof PhiNode phi && phi.in(0)==ctrl ? phi : new PhiNode(ctrl,ret.mem ());
- PhiNode expr = ret.expr() instanceof PhiNode phi && phi.in(0)==ctrl ? phi : new PhiNode(ctrl,ret.expr());
- if( ret.ctrl()!=ctrl ) ret.setDef(0,ctrl);
- if( ret.mem ()!=mem ) ret.setDef(1,mem );
- if( ret.expr()!=expr ) ret.setDef(2,expr).peepholeOpt();
+ Node ctrl = ret.ctrl(), mem = ret.mem(), expr = ret.expr();
+ if( ctrl._type != Type.XCONTROL ) {
+ // Perfect aligned exit?
+ if( !(ctrl instanceof RegionNode r &&
+ mem instanceof PhiNode pmem && pmem.region()==r &&
+ expr instanceof PhiNode prez && prez.region()==r ) ) {
+ // Nope, insert an aligned exit layer
+ ctrl = new RegionNode(null,ctrl).init();
+ mem = new PhiNode((RegionNode)ctrl,mem ).init();
+ expr = new PhiNode((RegionNode)ctrl,expr).init();
+ }
+ // Append new Never exit
ctrl.addDef(t );
mem .addDef(top);
expr.addDef(top);
+ } else {
+ ctrl = t;
+ mem = top;
+ expr = top;
}
+ ret.setDef(0,ctrl);
+ ret.setDef(1,mem );
+ ret.setDef(2,expr);
+
return stop;
}
}
diff --git a/chapter18/src/main/java/com/seaofnodes/simple/node/MemOpNode.java b/chapter18/src/main/java/com/seaofnodes/simple/node/MemOpNode.java
index 96274789..f0e66952 100644
--- a/chapter18/src/main/java/com/seaofnodes/simple/node/MemOpNode.java
+++ b/chapter18/src/main/java/com/seaofnodes/simple/node/MemOpNode.java
@@ -48,6 +48,7 @@ public abstract class MemOpNode extends Node {
Type ptr = ptr()._type;
// Already an error, but better error messages come from elsewhere
if( ptr == Type.BOTTOM ) return null;
+ if( ptr.isHigh() ) return null; // Assume it will fall to not-null
// Better be a not-nil TMP
if( ptr instanceof TypeMemPtr tmp && tmp.notNull() )
return null;
diff --git a/chapter18/src/main/java/com/seaofnodes/simple/node/Node.java b/chapter18/src/main/java/com/seaofnodes/simple/node/Node.java
index 9aa123a5..b0b19311 100644
--- a/chapter18/src/main/java/com/seaofnodes/simple/node/Node.java
+++ b/chapter18/src/main/java/com/seaofnodes/simple/node/Node.java
@@ -341,7 +341,7 @@ public abstract class Node {
// Replace constant computations from non-constants with a constant
// node. If peeps are disabled, still allow high Phis to collapse;
- // they typically come from dead Regions and we want the Region to
+ // they typically come from dead Regions, and we want the Region to
// collapse, which requires the Phis to die first.
if( _type.isHighOrConst() && !isConst() && (!_disablePeephole || _type.isHigh()) )
return ConstantNode.make(_type).peepholeOpt();
@@ -420,6 +420,7 @@ public abstract class Node {
return old;
}
+ public <N extends Node> N init() { _type = compute(); return (N)this; }
/**
* This function rewrites the current Node into a more "idealized" form.
diff --git a/chapter18/src/main/java/com/seaofnodes/simple/node/PhiNode.java b/chapter18/src/main/java/com/seaofnodes/simple/node/PhiNode.java
index ccbdd460..35a60cd1 100644
--- a/chapter18/src/main/java/com/seaofnodes/simple/node/PhiNode.java
+++ b/chapter18/src/main/java/com/seaofnodes/simple/node/PhiNode.java
@@ -55,7 +55,7 @@ public class PhiNode extends Node {
// During parsing Phis have to be computed type pessimistically.
if( r.inProgress() ) return _declaredType;
// Set type to local top of the starting type
- Type t = Type.TOP;
+ Type t = _declaredType.glb().dual();//Type.TOP;
for (int i = 1; i < nIns(); i++)
// If the region's control input is live, add this as a dependency
// to the control because we can be peeped should it become dead.
diff --git a/chapter18/src/main/java/com/seaofnodes/simple/node/ScopeMinNode.java b/chapter18/src/main/java/com/seaofnodes/simple/node/ScopeMinNode.java
index f29ed20b..ebf650fc 100644
--- a/chapter18/src/main/java/com/seaofnodes/simple/node/ScopeMinNode.java
+++ b/chapter18/src/main/java/com/seaofnodes/simple/node/ScopeMinNode.java
@@ -45,7 +45,7 @@ public class ScopeMinNode extends Node {
// If being used by a Scope, this is "in progress" from the Parser.
- // Otherwise its a memory merge
+ // Otherwise, it's a memory merge
boolean inProgress() { return _inProgress; }
@Override public String label() { return "ALLMEM"; }
@@ -60,7 +60,7 @@ public class ScopeMinNode extends Node {
Node n = in(j);
while( n instanceof ScopeNode loop ) {
sb.append("Lazy_");
- n = loop.in(j);
+ n = loop.mem(j);
}
if( n==null ) sb.append("___ ");
else n._print0(sb, visited).append(" ");
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 e4a4ddc0..cf993561 100644
--- a/chapter18/src/main/java/com/seaofnodes/simple/node/ScopeNode.java
+++ b/chapter18/src/main/java/com/seaofnodes/simple/node/ScopeNode.java
@@ -288,7 +288,7 @@ public class ScopeNode extends ScopeMinNode {
assert ctrl instanceof CFGNode;
_guards.add(ctrl); // Marker to distinguish 0,1,2 guards
// add pred & its cast to the normal input list, with special Vars
- if( ctrl._type == Type.XCONTROL || pred==null || pred.isDead() )
+ if( pred==null || pred.isDead() )
return; // Dead, do not add any guards
// Invert the If conditional
if( invert )
@@ -296,7 +296,8 @@ public class ScopeNode extends ScopeMinNode {
// This is a zero/null test.
// Compute the positive test type.
Type tnz = pred._type.nonZero();
- _addGuard(tnz,ctrl,pred);
+ if( tnz!=null )
+ _addGuard(tnz,ctrl,pred);
// Compute the negative test type.
if( pred instanceof NotNode not ) {
@@ -308,7 +309,7 @@ public class ScopeNode extends ScopeMinNode {
private void _addGuard(Type guard, Node ctrl, Node pred) {
Type tcast = guard.join(pred._type);
- if( tcast != pred._type ) {
+ if( tcast != pred._type && !tcast.isHigh() ) {
Node cast = new CastNode(tcast,ctrl,pred.keep()).peephole().keep();
_guards.add(pred);
_guards.add(cast);
@@ -357,12 +358,11 @@ public class ScopeNode extends ScopeMinNode {
}
- private Node replace( Node old, Node cast ) {
+ private void replace( Node old, Node cast ) {
assert old!=null && old!=cast;
for( int i=0; i<nIns(); i++ )
if( in(i)==old )
setDef(i,cast);
- return cast;
}
}
diff --git a/chapter18/src/main/java/com/seaofnodes/simple/type/Field.java b/chapter18/src/main/java/com/seaofnodes/simple/type/Field.java
index 1ed75fe4..ffa9d2a6 100644
--- a/chapter18/src/main/java/com/seaofnodes/simple/type/Field.java
+++ b/chapter18/src/main/java/com/seaofnodes/simple/type/Field.java
@@ -38,7 +38,8 @@ public class Field extends Type {
@Override public boolean isFinal() { return _final && _type.isFinal(); }
public static final Field TEST = make("test",Type.NIL,-2,false);
- public static void gather(ArrayList<Type> ts) { ts.add(TEST); }
+ public static final Field TEST2= make("test",Type.NIL,-2,true);
+ public static void gather(ArrayList<Type> ts) { ts.add(TEST); ts.add(TEST2); }
@Override Field xmeet( Type that ) {
Field fld = (Field)that; // Invariant
diff --git a/chapter18/src/main/java/com/seaofnodes/simple/type/TypeFloat.java b/chapter18/src/main/java/com/seaofnodes/simple/type/TypeFloat.java
index df99b630..258cda03 100644
--- a/chapter18/src/main/java/com/seaofnodes/simple/type/TypeFloat.java
+++ b/chapter18/src/main/java/com/seaofnodes/simple/type/TypeFloat.java
@@ -79,6 +79,7 @@ public class TypeFloat extends Type {
return isConstant() ? this : make(-_sz,0); // Constants are a self-dual
}
+ @Override public Type makeZero() { return FZERO; }
@Override public Type glb() { return F64; }
@Override
@@ -86,7 +87,8 @@ public class TypeFloat extends Type {
@Override
public boolean eq( Type t ) {
TypeFloat i = (TypeFloat)t; // Contract
- return _con==i._con && _sz==i._sz;
+ // Allow NaN to check for equality
+ return _sz==i._sz && Double.doubleToLongBits(_con)==Double.doubleToLongBits(i._con);
}
}
diff --git a/chapter18/src/main/java/com/seaofnodes/simple/type/TypeInteger.java b/chapter18/src/main/java/com/seaofnodes/simple/type/TypeInteger.java
index 77b280f3..cccb85a5 100644
--- a/chapter18/src/main/java/com/seaofnodes/simple/type/TypeInteger.java
+++ b/chapter18/src/main/java/com/seaofnodes/simple/type/TypeInteger.java
@@ -113,11 +113,12 @@ public class TypeInteger extends Type {
@Override public TypeInteger nonZero() {
if( isHigh() ) return this;
+ if( this==ZERO ) return null; // No sane answer
if( _min==0 ) return make(1,Math.max(_max,1)); // specifically good on BOOL
if( _max==0 ) return make(_min,-1);
return this;
}
- @Override public Type makeZero() { return TypeInteger.ZERO; }
+ @Override public Type makeZero() { return ZERO; }
@Override public TypeInteger glb() { return BOT; }
@Override int hash() { return Utils.fold(_min) * Utils.fold(_max); }
@Override public boolean eq( Type t ) {