summaryrefslogtreecommitdiff
path: root/chapter17
diff options
context:
space:
mode:
authorCliff Click <cliffc@acm.org>2024-11-10 12:01:48 -0800
committerCliff Click <cliffc@acm.org>2024-11-23 09:03:20 -0800
commitc523a94308747083a08cc8e698d5f02c043c6127 (patch)
treea8a378e11994413a6b8bc1951b6f0993d85518d3 /chapter17
parente386e6323e34f2a3d4e5b5779cdefd12c9552bd6 (diff)
downloadSimple-c523a94308747083a08cc8e698d5f02c043c6127.tar.gz
Simple-c523a94308747083a08cc8e698d5f02c043c6127.zip
Much more robust guarded expression upcasting
Region does not print id, making all test cases much more stable (and slightly weaker). NotNode gets more precise compute
Diffstat (limited to 'chapter17')
-rw-r--r--chapter17/src/main/java/com/seaofnodes/simple/Parser.java70
-rw-r--r--chapter17/src/main/java/com/seaofnodes/simple/node/Node.java4
-rw-r--r--chapter17/src/main/java/com/seaofnodes/simple/node/NotNode.java9
-rw-r--r--chapter17/src/main/java/com/seaofnodes/simple/node/RegionNode.java2
-rw-r--r--chapter17/src/main/java/com/seaofnodes/simple/node/ScopeNode.java107
-rw-r--r--chapter17/src/test/java/com/seaofnodes/simple/Chapter05Test.java19
-rw-r--r--chapter17/src/test/java/com/seaofnodes/simple/Chapter06Test.java10
-rw-r--r--chapter17/src/test/java/com/seaofnodes/simple/Chapter07Test.java26
-rw-r--r--chapter17/src/test/java/com/seaofnodes/simple/Chapter08Test.java16
-rw-r--r--chapter17/src/test/java/com/seaofnodes/simple/Chapter09Test.java6
-rw-r--r--chapter17/src/test/java/com/seaofnodes/simple/Chapter10Test.java14
-rw-r--r--chapter17/src/test/java/com/seaofnodes/simple/Chapter11Test.java4
-rw-r--r--chapter17/src/test/java/com/seaofnodes/simple/Chapter12Test.java2
-rw-r--r--chapter17/src/test/java/com/seaofnodes/simple/Chapter14Test.java2
-rw-r--r--chapter17/src/test/java/com/seaofnodes/simple/Chapter15Test.java4
-rw-r--r--chapter17/src/test/java/com/seaofnodes/simple/Chapter16Test.java2
-rw-r--r--chapter17/src/test/java/com/seaofnodes/simple/Chapter17Test.java12
17 files changed, 187 insertions, 122 deletions
diff --git a/chapter17/src/main/java/com/seaofnodes/simple/Parser.java b/chapter17/src/main/java/com/seaofnodes/simple/Parser.java
index 371bddf1..799e0629 100644
--- a/chapter17/src/main/java/com/seaofnodes/simple/Parser.java
+++ b/chapter17/src/main/java/com/seaofnodes/simple/Parser.java
@@ -2,7 +2,6 @@ package com.seaofnodes.simple;
import com.seaofnodes.simple.node.*;
import com.seaofnodes.simple.type.*;
-import static com.seaofnodes.simple.Utils.TODO;
import java.util.*;
@@ -91,7 +90,7 @@ public class Parser {
public final Stack<ScopeNode> _xScopes = new Stack<>();
ScopeNode _continueScope;
- ScopeNode _breakScope;
+ ScopeNode _breakScope; // Merge all the while-breaks here
// Mapping from a type name to a Type. The string name matches
// `type.str()` call. No TypeMemPtrs are in here, because Simple does not
@@ -169,7 +168,7 @@ public class Parser {
if( ctrl()._type==Type.CONTROL )
STOP.addReturn(new ReturnNode(ctrl(), ZERO, _scope).peephole());
- _scope.pop();
+ _scope.kill();
_xScopes.pop();
for( StructNode init : INITS.values() )
init.unkeep().kill();
@@ -269,7 +268,7 @@ public class Parser {
// the loop predicate. Note that body Scope is still our current scope.
ctrl(ifF);
_xScopes.push(_breakScope = _scope.dup());
- _breakScope.upcast(ifF,pred,true); // Up-cast predicate
+ _breakScope.addGuards(ifF,pred,true); // Up-cast predicate
// No continues yet
_continueScope = null;
@@ -277,8 +276,9 @@ public class Parser {
// Parse the true side, which corresponds to loop body
// Our current scope is the body Scope
ctrl(ifT.unkeep()); // set ctrl token to ifTrue projection
- _scope.upcast(ifT,pred,false); // Up-cast predicate
+ _scope.addGuards(ifT,pred,false); // Up-cast predicate
parseStatement(); // Parse loop body
+ _scope.removeGuards(ifT);
// Merge the loop bottom into other continue statements
if (_continueScope != null) {
@@ -330,8 +330,17 @@ public class Parser {
private void checkLoopActive() { if (_breakScope == null) throw Parser.error("No active loop for a break or continue"); }
- private Node parseBreak () { checkLoopActive(); return ( _breakScope = require(jumpTo( _breakScope ),";")); }
private Node parseContinue() { checkLoopActive(); return (_continueScope = require(jumpTo( _continueScope ),";")); }
+ private Node parseBreak () {
+ checkLoopActive();
+ // At the time of the break, and loop-exit conditions are only valid if
+ // they are ALSO valid at the break. It is the intersection of
+ // conditions here, not the union.
+ _breakScope.removeGuards(_breakScope.ctrl());
+ _breakScope = require(jumpTo(_breakScope ),";");
+ _breakScope.addGuards(_breakScope.ctrl(), null, false);
+ return _breakScope;
+ }
/**
* Parses a statement
@@ -365,8 +374,10 @@ public class Parser {
// Parse the true side
ctrl(ifT.unkeep()); // set ctrl token to ifTrue projection
- _scope.upcast(ifT,pred,false); // Up-cast predicate
+ _scope.addGuards(ifT,pred,false); // Up-cast predicate
Node lhs = stmt ? parseStatement() : parseExpression().keep(); // Parse true-side
+ _scope.removeGuards(ifT);
+
ScopeNode tScope = _scope;
// Parse the false side
@@ -374,11 +385,12 @@ public class Parser {
ctrl(ifF.unkeep()); // Ctrl token is now set to ifFalse projection
// Up-cast predicate, even if not else clause, because predicate can
// remain true if the true clause exits: `if( !ptr ) return 0; return ptr.fld;`
- _scope.upcast(ifF,pred,true);
+ _scope.addGuards(ifF,pred,true);
boolean doRHS = match(fside);
Node rhs = doRHS
? (stmt ? parseStatement() : parseExpression())
: (stmt ? null : con(lhs._type.makeZero()));
+ _scope.removeGuards(ifF);
if( doRHS )
fScope = _scope;
pred.unkeep();
@@ -392,7 +404,7 @@ public class Parser {
_xScopes.pop(); // Discard pushed from graph display
RegionNode r = ctrl(tScope.mergeScopes(fScope));
- Node ret = stmt ? r : new PhiNode("",lhs._type.meet(rhs._type),r,lhs,rhs).peephole();
+ Node ret = stmt ? r : peep(new PhiNode("",lhs._type.meet(rhs._type),r,lhs,rhs));
r.peephole();
return ret;
}
@@ -461,7 +473,7 @@ public class Parser {
// Auto-widen int to float
if( expr._type instanceof TypeInteger && t instanceof TypeFloat )
- expr = new ToFloatNode(expr).peephole();
+ expr = peep(new ToFloatNode(expr));
// Auto-narrow wide ints to narrow ints
expr = zsMask(expr,t);
// Auto-deepen forward ref types
@@ -653,7 +665,7 @@ public class Parser {
else if( match("^") ) lhs = new XorNode(lhs,null);
else break;
lhs.setDef(2,parseComparison());
- lhs = lhs.peephole();
+ lhs = peep(lhs);
}
return lhs;
}
@@ -681,9 +693,9 @@ public class Parser {
else break;
// Peepholes can fire, but lhs is already "hooked", kept alive
lhs.setDef(idx,parseShift());
- lhs = lhs.widen().peephole();
+ lhs = peep(lhs.widen());
if( negate ) // Extra negate for !=
- lhs = new NotNode(lhs).peephole();
+ lhs = peep(new NotNode(lhs));
}
return lhs;
}
@@ -705,7 +717,7 @@ public class Parser {
else if( match(">>") ) lhs = new SarNode(lhs,null);
else break;
lhs.setDef(2,parseAddition());
- lhs = lhs.widen().peephole();
+ lhs = peep(lhs.widen());
}
return lhs;
}
@@ -726,7 +738,7 @@ public class Parser {
else if( match("-") ) lhs = new SubNode(lhs,null);
else break;
lhs.setDef(2,parseMultiplication());
- lhs = lhs.widen().peephole();
+ lhs = peep(lhs.widen());
}
return lhs;
}
@@ -747,7 +759,7 @@ public class Parser {
else if( match("/") ) lhs = new DivNode(lhs,null);
else break;
lhs.setDef(2,parseUnary());
- lhs = lhs.widen().peephole();
+ lhs = peep(lhs.widen());
}
return lhs;
}
@@ -761,8 +773,8 @@ public class Parser {
* @return a unary expression {@link Node}, never {@code null}
*/
private Node parseUnary() {
- if (match("-")) return new MinusNode(parseUnary()).widen().peephole();
- if (match("!")) return new NotNode(parseUnary()).peephole();
+ if (match("-")) return peep(new MinusNode(parseUnary()).widen());
+ if (match("!")) return peep(new NotNode(parseUnary()));
return parsePostfix(parsePrimary());
}
@@ -787,7 +799,7 @@ public class Parser {
if( matchx("++") || matchx("--") ) {
if( n._final )
throw error("Cannot reassign final '"+n._name+"'");
- _scope.update(n,new AddNode(rvalue,con( _lexer.peek(-1)=='+' ? 1 : -1)).peephole());
+ _scope.update(n,peep(new AddNode(rvalue,con( _lexer.peek(-1)=='+' ? 1 : -1))));
}
return rvalue.unkeep();
}
@@ -882,7 +894,7 @@ public class Parser {
private Node newArray(TypeStruct ary, Node len) {
int base = ary.aryBase ();
int scale= ary.aryScale();
- Node size = new AddNode(con(base),new ShlNode(len,con(scale)).peephole()).peephole();
+ Node size = peep(new AddNode(con(base),peep(new ShlNode(len,con(scale)))));
ALTMP.clear(); ALTMP.add(len); ALTMP.add(con(ary._fields[1]._type.makeInit()));
return newStruct(ary,size,0,ALTMP);
}
@@ -935,7 +947,7 @@ public class Parser {
Node off = (name.equals("[]") // If field is an array body
// Array index math
- ? new AddNode(con(base.aryBase()),new ShlNode(require(parseExpression(),"]"),con(base.aryScale())).peephole()).peephole()
+ ? peep(new AddNode(con(base.aryBase()),peep(new ShlNode(require(parseExpression(),"]"),con(base.aryScale())))))
// Struct field offsets are hardwired
: con(base.offset(fidx))).keep();
@@ -958,20 +970,20 @@ public class Parser {
// Structs don't need this; they only need a NPE check which is
// done via the type system.
if( base.isAry() ) load.setDef(0,ctrl());
- load = load.peephole();
+ load = peep(load);
// ary[idx]++
if( matchx("++") || matchx("--") ) {
if( f._final && !f._fname.equals("[]") )
throw error("Cannot reassign final '"+f._fname+"'");
- Node inc = new AddNode(load,con( _lexer.peek(-1)=='+' ? 1 : -1)).peephole();
+ Node inc = peep(new AddNode(load,con( _lexer.peek(-1)=='+' ? 1 : -1)));
Node val = zsMask(inc,f._type);
Node st = new StoreNode(name, f._alias, f._type, memAlias(f._alias), expr, off, val, false);
// Arrays include control, as a proxy for a safety range check.
// Structs don't need this; they only need a NPE check which is
// done via the type system.
if( base.isAry() ) st.setDef(0,ctrl());
- memAlias(f._alias, st.peephole());
+ memAlias(f._alias, peep(st));
// And use the original loaded value as the result
}
if( off.unkeep().isDead() ) off.kill();
@@ -987,16 +999,16 @@ public class Parser {
if( !(val._type instanceof TypeFloat tval && t instanceof TypeFloat t0 && !tval.isa(t0)) )
return val;
// Float rounding
- return new RoundF32Node(val).peephole();
+ return peep(new RoundF32Node(val));
}
if( t0._min==0 ) // Unsigned
- return new AndNode(val,con(t0._max)).peephole();
+ return peep(new AndNode(val,con(t0._max)));
// Signed extension
int shift = Long.numberOfLeadingZeros(t0._max)-1;
Node shf = con(shift);
if( shf._type==TypeInteger.ZERO )
return val;
- return new SarNode(new ShlNode(val,shf.keep()).peephole(),shf.unkeep()).peephole();
+ return peep(new SarNode(peep(new ShlNode(val,shf.keep())),shf.unkeep()));
}
@@ -1011,6 +1023,10 @@ public class Parser {
private ConstantNode parseLiteral() { return con(_lexer.parseNumber()); }
public static Node con( long con ) { return con(TypeInteger.constant(con)); }
public static ConstantNode con( Type t ) { return (ConstantNode)new ConstantNode(t).peephole(); }
+ public Node peep( Node n ) {
+ // Peephole, then improve with lexically scoped guards
+ return _scope.upcastGuard(n.peephole());
+ }
//////////////////////////////////
// Utilities for lexical analysis
diff --git a/chapter17/src/main/java/com/seaofnodes/simple/node/Node.java b/chapter17/src/main/java/com/seaofnodes/simple/node/Node.java
index 35dbc19e..3827fdac 100644
--- a/chapter17/src/main/java/com/seaofnodes/simple/node/Node.java
+++ b/chapter17/src/main/java/com/seaofnodes/simple/node/Node.java
@@ -267,6 +267,10 @@ public abstract class Node implements OutNode {
}
// Test "keep" status
public boolean iskeep() { return _outputs.find(null) != -1; }
+ public void unkill() {
+ if( unkeep().isUnused() )
+ kill();
+ }
// Replace self with nnn in the graph, making 'this' go dead
diff --git a/chapter17/src/main/java/com/seaofnodes/simple/node/NotNode.java b/chapter17/src/main/java/com/seaofnodes/simple/node/NotNode.java
index ffd3e01e..664d7c7b 100644
--- a/chapter17/src/main/java/com/seaofnodes/simple/node/NotNode.java
+++ b/chapter17/src/main/java/com/seaofnodes/simple/node/NotNode.java
@@ -28,15 +28,14 @@ public class NotNode extends Node {
// top->top, bot->bot, null->1, *void->0, not-null ptr->0, ptr/nil->bot
// If input in null then true
// If input is not null ptr then false
- if( p0 == TypeMemPtr.TOP ) return TypeInteger.TOP;
- if( p0 == TypeMemPtr.NULLPTR ) return TypeInteger.constant(1);
- if( !p0._nil ) return TypeInteger.constant(0);
- return TypeInteger.BOT;
+ if( p0 == TypeMemPtr.NULLPTR ) return TypeInteger.TRUE;
+ if( !p0._nil ) return TypeInteger.FALSE;
+ return TypeInteger.BOOL;
case Type t:
if( t0.getClass() != Type.class )
// Only doing NOT on ints and ptrs
throw Utils.TODO();
- return t0==Type.TOP ? Type.TOP : Type.BOTTOM;
+ return TypeInteger.BOOL;
}
}
diff --git a/chapter17/src/main/java/com/seaofnodes/simple/node/RegionNode.java b/chapter17/src/main/java/com/seaofnodes/simple/node/RegionNode.java
index a55bb479..9e0f46cb 100644
--- a/chapter17/src/main/java/com/seaofnodes/simple/node/RegionNode.java
+++ b/chapter17/src/main/java/com/seaofnodes/simple/node/RegionNode.java
@@ -18,7 +18,7 @@ public class RegionNode extends CFGNode {
@Override
StringBuilder _print1(StringBuilder sb, BitSet visited) {
- return sb.append(label()).append(_nid);
+ return sb.append(label());
}
@Override public boolean isMultiHead() { return true; }
diff --git a/chapter17/src/main/java/com/seaofnodes/simple/node/ScopeNode.java b/chapter17/src/main/java/com/seaofnodes/simple/node/ScopeNode.java
index 2fc495c5..5a735515 100644
--- a/chapter17/src/main/java/com/seaofnodes/simple/node/ScopeNode.java
+++ b/chapter17/src/main/java/com/seaofnodes/simple/node/ScopeNode.java
@@ -32,12 +32,19 @@ public class ScopeNode extends ScopeMinNode {
// True if parsing inside of a constructor
public final Ary<Boolean> _inCons;
+ // Extra guards; tested predicates and casted results
+ private final Ary<Node> _guards;
+
// A new ScopeNode
- public ScopeNode() { _vars = new Ary<>(Var.class); _lexSize = new Ary<>(Integer.class); _inCons = new Ary<>(Boolean.class); }
+ public ScopeNode() {
+ _vars = new Ary<>(Var .class);
+ _lexSize= new Ary<>(Integer.class);
+ _inCons = new Ary<>(Boolean.class);
+ _guards = new Ary<>(Node .class);
+ }
@Override public String label() { return "Scope"; }
-
@Override
StringBuilder _print1(StringBuilder sb, BitSet visited) {
sb.append("Scope[ ");
@@ -187,9 +194,15 @@ public class ScopeNode extends ScopeMinNode {
// 1) duplicate the name bindings of the ScopeNode across all stack levels
// 2) Make the new ScopeNode a user of all the nodes bound
// 3) Ensure that the order of defs is the same to allow easy merging
- dup._vars.addAll(_vars);
+ dup._vars .addAll(_vars );
dup._lexSize.addAll(_lexSize);
dup._inCons .addAll(_inCons );
+ dup._guards .addAll(_guards );
+ // The dup'd guards all need dup'd keepers, to keep proper accounting
+ // when later removing all guards
+ for( Node n : _guards )
+ if( !(n instanceof CFGNode) )
+ n.keep();
dup.addDef(ctrl()); // Control input is just copied
// Memory input is a shallow copy
@@ -274,44 +287,78 @@ public class ScopeNode extends ScopeMinNode {
// Up-casting: using the results of an If to improve a value.
// E.g. "if( ptr ) ptr.field;" is legal because ptr is known not-null.
-
- // This Scope looks for direct variable uses, or certain simple
- // combinations, and replaces the variable with the upcast variant.
- public Node upcast( Node ctrl, Node pred, boolean invert ) {
- if( ctrl._type == Type.XCONTROL || pred.isDead() )
- return null; // Dead, do not do anything
+ public void addGuards( Node ctrl, Node pred, boolean invert ) {
+ 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() )
+ return; // Dead, do not add any guards
// Invert the If conditional
if( invert )
pred = pred instanceof NotNode not ? not.in(1) : IterPeeps.add(new NotNode(pred).peephole());
-
- // Direct use of a value as predicate. This is a zero/null test.
- if( _inputs.find(pred) != -1 ) {
- if( !(pred._type instanceof TypeMemPtr tmp) )
- // Must be an `int`, since int and ptr are the only two value types
- // being tested. No representation for a generic not-null int, so no upcast.
- return null;
- if( tmp.isa(TypeMemPtr.VOIDPTR) )
- return null; // Already not-null, no reason to upcast
- // Upcast the ptr to not-null ptr, and replace in scope
- return replace(pred,new CastNode(TypeMemPtr.VOIDPTR,ctrl,pred).peephole());
+ // This is a zero/null test.
+ // Compute the positive test type.
+ Type tnz = pred._type.nonZero();
+ Type tcast = tnz.join(pred._type);
+ if( tcast != pred._type ) {
+ Node cast = new CastNode(tnz,ctrl,pred.keep()).peephole().keep();
+ _guards.add(pred);
+ _guards.add(cast);
+ replace(pred,cast);
}
+ // Compute the negative test type.
if( pred instanceof NotNode not ) {
- // Direct use of a !value as predicate. This is a zero/null test.
- if( _inputs.find(not.in(1)) != -1 ) {
- Type tinit = not.in(1)._type.makeInit();
- if( not.in(1)._type.isa(tinit) ) return null; // Already zero/null, no reason to upcast
- return replace(not.in(1), new ConstantNode(tinit).peephole());
+ Node npred = not.in(1);
+ Type tzero = npred._type.makeZero();
+ Type tzcast= tzero.join(npred._type);
+ if( tzcast != npred._type ) {
+ Node cast = new CastNode(tzero,ctrl,npred.keep()).peephole().keep();
+ _guards.add(npred);
+ _guards.add( cast);
+ replace(npred,cast);
}
}
- // Apr/9/2024: Attempted to replace X with Y if guarded by a test of
- // X==Y. This didn't seem to help very much, or at least in the test
- // cases seen so far was a very minor help.
+ }
- // No upcast
- return null;
+ // Remove matching pred/cast pairs from this guarded region.
+ public void removeGuards( Node ctrl ) {
+ assert ctrl instanceof CFGNode;
+ // 0,1 or 2 guards
+ while( true ) {
+ Node g = _guards.pop();
+ if( g == ctrl ) break;
+ if( g instanceof CFGNode ) continue;
+ g .unkill(); // Pop/kill cast
+ _guards.pop().unkill(); // Pop/kill pred
+ }
}
+ // If we find a guarded instance of pred, replace with the upcasted version
+ public Node upcastGuard( Node pred ) {
+ // If finding an instanceof pred, replace with cast.
+ // Otherwise, just pred itself.
+ int i = _guards._len;
+ while( i > 0 ) {
+ Node cast = _guards.at(--i);
+ if( cast instanceof CFGNode ) continue; // Marker between guard sets
+ Node xpred = _guards.at(--i);
+ if( xpred == pred )
+ return cast;
+ }
+ return pred;
+ }
+
+ // Kill guards also
+ @Override public void kill() {
+ for( Node n : _guards )
+ if( !(n instanceof CFGNode) )
+ n.unkill();
+ _guards.clear();
+ super.kill();
+ }
+
+
private Node replace( Node old, Node cast ) {
assert old!=null && old!=cast;
for( int i=0; i<nIns(); i++ )
diff --git a/chapter17/src/test/java/com/seaofnodes/simple/Chapter05Test.java b/chapter17/src/test/java/com/seaofnodes/simple/Chapter05Test.java
index b5920125..9afb8f28 100644
--- a/chapter17/src/test/java/com/seaofnodes/simple/Chapter05Test.java
+++ b/chapter17/src/test/java/com/seaofnodes/simple/Chapter05Test.java
@@ -17,12 +17,11 @@ if (arg == 1)
a = arg+2;
else {
a = arg-3;
-
}
-
-return a;""");
+return a;
+""");
StopNode ret = parser.parse().iterate();
- assertEquals("return Phi(Region23,(arg+2),(arg-3));", ret.toString());
+ assertEquals("return Phi(Region,(arg+2),(arg-3));", ret.toString());
}
@Test
@@ -37,7 +36,7 @@ if (arg == 1) {
}
return c;""", TypeInteger.BOT);
StopNode ret = parser.parse().iterate();
- assertEquals("return Phi(Region22,4,3);", ret.toString());
+ assertEquals("return Phi(Region,4,3);", ret.toString());
}
@Test
@@ -65,7 +64,7 @@ else
b=a+1;
return a+b;""");
StopNode ret = parser.parse().iterate();
- assertEquals("return ((arg*2)+Phi(Region26,2,3));", ret.toString());
+ assertEquals("return ((arg*2)+Phi(Region,2,3));", ret.toString());
}
@Test
@@ -80,7 +79,7 @@ else
a=b+1;
return a+b;""");
StopNode ret = parser.parse().iterate();
- assertEquals("return ((Phi(Region37,(arg*2),arg)+arg)+Phi(Region,4,5));", ret.toString());
+ assertEquals("return ((Phi(Region,(arg*2),arg)+arg)+Phi(Region,4,5));", ret.toString());
}
@Test
@@ -100,7 +99,7 @@ else
return a;
""", TypeInteger.BOT);
StopNode stop = parser.parse().iterate();
- assertEquals("return Phi(Region43,Phi(Region28,2,3),Phi(Region41,4,5));", stop.toString());
+ assertEquals("return Phi(Region,Phi(Region,2,3),Phi(Region,4,5));", stop.toString());
}
@Test
@@ -116,7 +115,7 @@ if( arg==0 )
return arg+a+b;
""", TypeInteger.BOT);
StopNode stop = parser.parse();
- assertEquals("return ((arg+Phi(Region20,1,0))+Phi(Region37,2,0));", stop.toString());
+ assertEquals("return ((arg+Phi(Region,1,0))+Phi(Region,2,0));", stop.toString());
}
@Test
@@ -130,7 +129,7 @@ if( arg==1 )
}
return a;""");
StopNode ret = parser.parse().iterate();
- assertEquals("return (arg==Phi(Region22,3,2));", ret.toString());
+ assertEquals("return (arg==Phi(Region,3,2));", ret.toString());
}
@Test
diff --git a/chapter17/src/test/java/com/seaofnodes/simple/Chapter06Test.java b/chapter17/src/test/java/com/seaofnodes/simple/Chapter06Test.java
index 6308bdea..50c0580d 100644
--- a/chapter17/src/test/java/com/seaofnodes/simple/Chapter06Test.java
+++ b/chapter17/src/test/java/com/seaofnodes/simple/Chapter06Test.java
@@ -65,7 +65,7 @@ else
b=5;
return b;""", TypeInteger.BOT);
StopNode stop = parser.parse().iterate();
- assertEquals("return Phi(Region43,42,5);", stop.toString());
+ assertEquals("return Phi(Region,42,5);", stop.toString());
}
@Test
@@ -84,7 +84,7 @@ else
b=5;
return b;""", TypeInteger.BOT);
StopNode stop = parser.parse().iterate();
- assertEquals("return Phi(Region36,2,5);", stop.toString());
+ assertEquals("return Phi(Region,2,5);", stop.toString());
}
@Test
@@ -144,7 +144,7 @@ else
return a;
""", TypeInteger.BOT);
StopNode stop = parser.parse().iterate();
- assertEquals("return Phi(Region48,3,Phi(Region46,4,5));", stop.toString());
+ assertEquals("return Phi(Region,3,Phi(Region,4,5));", stop.toString());
}
@Test
@@ -200,7 +200,7 @@ if( arg ) {
return a+b;
""");
StopNode ret = parser.parse().iterate();
- assertEquals("return Phi(Region32,4,1);", ret.toString());
+ assertEquals("return Phi(Region,4,1);", ret.toString());
}
@@ -251,7 +251,7 @@ if( arg ) {
return a+b+c;
""");
StopNode ret = parser.parse().iterate();
- assertEquals("return (Phi(Region45,Phi(Region29,2,3),0)+Phi(Region,3,1));", ret.toString());
+ assertEquals("return (Phi(Region,Phi(Region,2,3),0)+Phi(Region,3,1));", ret.toString());
}
diff --git a/chapter17/src/test/java/com/seaofnodes/simple/Chapter07Test.java b/chapter17/src/test/java/com/seaofnodes/simple/Chapter07Test.java
index 80cb15d4..23ad18f1 100644
--- a/chapter17/src/test/java/com/seaofnodes/simple/Chapter07Test.java
+++ b/chapter17/src/test/java/com/seaofnodes/simple/Chapter07Test.java
@@ -18,7 +18,7 @@ public class Chapter07Test {
""");
Node._disablePeephole = true;
StopNode stop = parser.parse();
- assertEquals("return Phi(Loop10,arg,(Phi_arg+1));", stop.toString());
+ assertEquals("return Phi(Loop,arg,(Phi_arg+1));", stop.toString());
assertTrue(stop.ret().ctrl() instanceof CProjNode);
Node._disablePeephole = false;
}
@@ -36,7 +36,7 @@ if(arg){}else{
return a;
""");
StopNode stop = parser.parse().iterate();
- assertEquals("return Phi(Region32,1,Phi(Loop18,1,(Phi_a+1)));", stop.toString());
+ assertEquals("return Phi(Region,1,Phi(Loop,1,(Phi_a+1)));", stop.toString());
}
@Test
@@ -56,7 +56,7 @@ while(i < arg) {
return sum;
""");
StopNode stop = parser.parse().iterate();
- assertEquals("return Phi(Loop12,0,Phi(Loop27,Phi_sum,(Phi_sum+Phi(Loop,0,(Phi_j+1)))));", stop.toString());
+ assertEquals("return Phi(Loop,0,Phi(Loop,Phi_sum,(Phi_sum+Phi(Loop,0,(Phi_j+1)))));", stop.toString());
}
@Test
@@ -73,7 +73,7 @@ return b;
""");
Node._disablePeephole = true;
StopNode stop = parser.parse();
- assertEquals("return Phi(Loop12,2,Phi(Region35,Phi_b,4));", stop.toString());
+ assertEquals("return Phi(Loop,2,Phi(Region,Phi_b,4));", stop.toString());
assertTrue(stop.ret().ctrl() instanceof CProjNode);
Node._disablePeephole = false;
}
@@ -93,7 +93,7 @@ while(a < 10) {
return b;
""");
StopNode stop = parser.parse().iterate();
- assertEquals("return Phi(Loop12,2,(Phi(Region35,Phi_b,4)+1));", stop.toString());
+ assertEquals("return Phi(Loop,2,(Phi(Region,Phi_b,4)+1));", stop.toString());
assertTrue(stop.ret().ctrl() instanceof CProjNode);
}
@@ -111,7 +111,7 @@ return a;
""");
Node._disablePeephole = true;
StopNode stop = parser.parse();
- assertEquals("return Phi(Loop11,1,((Phi_a+1)+2));", stop.toString());
+ assertEquals("return Phi(Loop,1,((Phi_a+1)+2));", stop.toString());
assertTrue(stop.ret().ctrl() instanceof CProjNode);
Node._disablePeephole = false;
}
@@ -128,7 +128,7 @@ while(a < 10) {
return a;
""");
StopNode stop = parser.parse().iterate();
- assertEquals("return Phi(Loop11,1,(Phi_a+3));", stop.toString());
+ assertEquals("return Phi(Loop,1,(Phi_a+3));", stop.toString());
assertTrue(stop.ret().ctrl() instanceof CProjNode);
}
@@ -142,7 +142,7 @@ return a;
""");
Node._disablePeephole = true;
StopNode stop = parser.parse();
- assertEquals("return Phi(Loop11,1,2);", stop.toString());
+ assertEquals("return Phi(Loop,1,2);", stop.toString());
assertTrue(stop.ret().ctrl() instanceof CProjNode);
Node._disablePeephole = false;
}
@@ -156,7 +156,7 @@ while(arg) a = 2;
return a;
""");
StopNode stop = parser.parse().iterate();
- assertEquals("return Phi(Loop11,1,2);", stop.toString());
+ assertEquals("return Phi(Loop,1,2);", stop.toString());
assertTrue(stop.ret().ctrl() instanceof CProjNode);
}
@@ -173,7 +173,7 @@ return a;
""");
Node._disablePeephole = true;
StopNode stop = parser.parse();
- assertEquals("return Phi(Loop11,1,((Phi_a+1)+2));", stop.toString());
+ assertEquals("return Phi(Loop,1,((Phi_a+1)+2));", stop.toString());
assertTrue(stop.ret().ctrl() instanceof CProjNode);
Node._disablePeephole = false;
}
@@ -190,7 +190,7 @@ while(a < 10) {
return a;
""");
StopNode stop = parser.parse().iterate();
- assertEquals("return Phi(Loop11,1,(Phi_a+3));", stop.toString());
+ assertEquals("return Phi(Loop,1,(Phi_a+3));", stop.toString());
assertTrue(stop.ret().ctrl() instanceof CProjNode);
}
@@ -208,7 +208,7 @@ return a;
""");
Node._disablePeephole = true;
StopNode stop = parser.parse();
- assertEquals("return Phi(Loop12,1,((Phi_a+1)+2));", stop.toString());
+ assertEquals("return Phi(Loop,1,((Phi_a+1)+2));", stop.toString());
assertTrue(stop.ret().ctrl() instanceof CProjNode);
Node._disablePeephole = false;
}
@@ -226,7 +226,7 @@ while(a < 10) {
return a;
""");
StopNode stop = parser.parse().iterate();
- assertEquals("return Phi(Loop12,1,(Phi_a+3));", stop.toString());
+ assertEquals("return Phi(Loop,1,(Phi_a+3));", stop.toString());
assertTrue(stop.ret().ctrl() instanceof CProjNode);
}
diff --git a/chapter17/src/test/java/com/seaofnodes/simple/Chapter08Test.java b/chapter17/src/test/java/com/seaofnodes/simple/Chapter08Test.java
index 5372388b..29fd09dc 100644
--- a/chapter17/src/test/java/com/seaofnodes/simple/Chapter08Test.java
+++ b/chapter17/src/test/java/com/seaofnodes/simple/Chapter08Test.java
@@ -23,7 +23,7 @@ while(arg < 10) {
return arg;
""");
StopNode stop = parser.parse().iterate();
- assertEquals("return Phi(Region46,Phi(Region33,Phi(Loop10,arg,(Phi_arg+1)),Add),Add);", stop.toString());
+ assertEquals("return Phi(Region,Phi(Region,Phi(Loop,arg,(Phi_arg+1)),Add),Add);", stop.toString());
assertTrue(stop.ret().ctrl() instanceof RegionNode);
Assert.assertEquals(5L, Evaluator.evaluate(stop, 1));
Assert.assertEquals(10L, Evaluator.evaluate(stop, 6));
@@ -46,7 +46,7 @@ while(arg < 10) {
return a;
""");
StopNode stop = parser.parse().iterate();
- assertEquals("return Phi(Loop11,1,Phi(Region53,Phi_a,(Phi_a+1)));", stop.toString());
+ assertEquals("return Phi(Loop,1,Phi(Region,Phi_a,(Phi_a+1)));", stop.toString());
assertTrue(stop.ret().ctrl() instanceof CProjNode);
}
@@ -65,7 +65,7 @@ while(arg < 10) {
return arg;
""");
StopNode stop = parser.parse().iterate();
- assertEquals("return Phi(Region44,Phi(Loop10,arg,(Phi_arg+1)),Add);", stop.toString());
+ assertEquals("return Phi(Region,Phi(Loop,arg,(Phi_arg+1)),Add);", stop.toString());
assertTrue(stop.ret().ctrl() instanceof RegionNode);
}
@@ -81,7 +81,7 @@ while(arg < 10) {
return arg;
""");
StopNode stop = parser.parse().iterate();
- assertEquals("return Phi(Region33,Phi(Loop10,arg,(Phi_arg+1)),Add);", stop.toString());
+ assertEquals("return Phi(Region,Phi(Loop,arg,(Phi_arg+1)),Add);", stop.toString());
assertTrue(stop.ret().ctrl() instanceof RegionNode);
}
@@ -100,7 +100,7 @@ while(arg < 10) {
return arg;
""");
StopNode stop = parser.parse().iterate();
- assertEquals("return Phi(Loop10,arg,(Phi_arg+1));", stop.toString());
+ assertEquals("return Phi(Loop,arg,(Phi_arg+1));", stop.toString());
assertTrue(stop.ret().ctrl() instanceof CProjNode);
}
@@ -117,7 +117,7 @@ while(arg < 10) {
return arg;
""");
StopNode stop = parser.parse().iterate();
- assertEquals("return Phi(Loop10,arg,(Phi_arg+1));", stop.toString());
+ assertEquals("return Phi(Loop,arg,(Phi_arg+1));", stop.toString());
assertTrue(stop.ret().ctrl() instanceof CProjNode);
}
@@ -185,7 +185,7 @@ while(arg < 10) {
return a;
""");
StopNode stop = parser.parse().iterate();
- assertEquals("return Phi(Region36,Phi(Loop11,1,(Phi_a+1)),Add);", stop.toString());
+ assertEquals("return Phi(Region,Phi(Loop,1,(Phi_a+1)),Add);", stop.toString());
assertTrue(stop.ret().ctrl() instanceof RegionNode);
}
@@ -201,7 +201,7 @@ while(1) {
return a;
""");
StopNode stop = parser.parse().iterate();
- assertEquals("return (Phi(Loop11,1,Add)+1);", stop.toString());
+ assertEquals("return (Phi(Loop,1,Add)+1);", stop.toString());
assertTrue(stop.ret().ctrl() instanceof CProjNode prj && prj._idx==1 );
}
diff --git a/chapter17/src/test/java/com/seaofnodes/simple/Chapter09Test.java b/chapter17/src/test/java/com/seaofnodes/simple/Chapter09Test.java
index 04ab8001..c31afcd6 100644
--- a/chapter17/src/test/java/com/seaofnodes/simple/Chapter09Test.java
+++ b/chapter17/src/test/java/com/seaofnodes/simple/Chapter09Test.java
@@ -69,7 +69,7 @@ while (arg < 10) {
return arg;
""");
StopNode stop = parser.parse().iterate();
- assertEquals("return Phi(Loop11,arg,(Phi_arg+2));", stop.toString());
+ assertEquals("return Phi(Loop,arg,(Phi_arg+2));", stop.toString());
Assert.assertEquals(11L, Evaluator.evaluate(stop, 1));
}
@@ -86,7 +86,7 @@ while (arg < 10) {
return arg;
""");
StopNode stop = parser.parse().iterate();
- assertEquals("return Phi(Loop12,arg,(Phi_arg+4));", stop.toString());
+ assertEquals("return Phi(Loop,arg,(Phi_arg+4));", stop.toString());
Assert.assertEquals(13L, Evaluator.evaluate(stop, 1));
}
@@ -185,7 +185,7 @@ while(arg) {
return a;
""");
StopNode stop = parser.parse().iterate();
- assertEquals("return Phi(Loop13,0,(-(Phi_a+3)));", stop.toString());
+ assertEquals("return Phi(Loop,0,(-(Phi_a+3)));", stop.toString());
}
@Test
diff --git a/chapter17/src/test/java/com/seaofnodes/simple/Chapter10Test.java b/chapter17/src/test/java/com/seaofnodes/simple/Chapter10Test.java
index 0bf921f6..44d71b1e 100644
--- a/chapter17/src/test/java/com/seaofnodes/simple/Chapter10Test.java
+++ b/chapter17/src/test/java/com/seaofnodes/simple/Chapter10Test.java
@@ -104,7 +104,7 @@ while (arg) {
return bar.a;
""");
StopNode stop = parser.parse().iterate();
- assertEquals("return Phi(Loop16,0,(Phi_a+2));", stop.toString());
+ assertEquals("return Phi(Loop,0,(Phi_a+2));", stop.toString());
}
@Test
@@ -156,7 +156,7 @@ if( bar ) bar.a = 1;
return bar;
""");
StopNode stop = parser.parse(false).iterate();
- assertEquals("return Phi(Region38,(*void)Phi(Region24,null,Bar),null);", stop.toString());
+ assertEquals("return Phi(Region,(*void)Phi(Region,null,Bar),null);", stop.toString());
}
@Test
@@ -172,7 +172,7 @@ else bar.a = 1;
return rez;
""");
StopNode stop = parser.parse(false).iterate();
- assertEquals("return Phi(Region44,4,3);", stop.toString());
+ assertEquals("return Phi(Region,4,3);", stop.toString());
}
@Test
@@ -226,7 +226,7 @@ while( i.x < i.len ) {
return sum;
""");
StopNode stop = parser.parse().iterate();
- assertEquals("return Phi(Loop21,0,(Phi(Loop,0,(Phi_x+1))+Phi_sum));", stop.toString());
+ assertEquals("return Phi(Loop,0,(Phi(Loop,0,(Phi_x+1))+Phi_sum));", stop.toString());
}
@@ -245,7 +245,7 @@ while(arg) {
return ret;
""");
StopNode stop = parser.parse().iterate();
- assertEquals("return Phi(Loop16,s0,Phi(Region45,s0,Phi_ret));", stop.toString());
+ assertEquals("return Phi(Loop,s0,Phi(Region,s0,Phi_ret));", stop.toString());
}
@Test
@@ -263,7 +263,7 @@ while(arg) {
return ret;
""");
StopNode stop = parser.parse().iterate();
- assertEquals("return Phi(Loop20,s0,Phi(Region46,s0,Phi_ret));", stop.toString());
+ assertEquals("return Phi(Loop,s0,Phi(Region,s0,Phi_ret));", stop.toString());
}
@@ -280,7 +280,7 @@ while(arg < 10) {
return ret;
""");
StopNode stop = parser.parse().iterate();
- assertEquals("return Phi(Loop16,s0,Phi(Region42,s0,Phi_ret));", stop.toString());
+ assertEquals("return Phi(Loop,s0,Phi(Region,s0,Phi_ret));", stop.toString());
}
@Test
diff --git a/chapter17/src/test/java/com/seaofnodes/simple/Chapter11Test.java b/chapter17/src/test/java/com/seaofnodes/simple/Chapter11Test.java
index 44814d53..11424720 100644
--- a/chapter17/src/test/java/com/seaofnodes/simple/Chapter11Test.java
+++ b/chapter17/src/test/java/com/seaofnodes/simple/Chapter11Test.java
@@ -324,7 +324,7 @@ while( prime <= arg ) {
return primeCount;
""");
StopNode stop = parser.parse().iterate();
- assertEquals("Stop[ return 0; return Phi(Loop23,1,Phi(Region102,Phi_primeCount,Phi(Region95,(Phi_primeCount+1),Phi_primeCount))); ]", stop.toString());
+ assertEquals("Stop[ return 0; return Phi(Loop,1,Phi(Region,Phi_primeCount,Phi(Region,(Phi_primeCount+1),Phi_primeCount))); ]", stop.toString());
assertEquals(0L, Evaluator.evaluate(stop, 1)); // No primes 1 or below
assertEquals(1L, Evaluator.evaluate(stop, 2)); // 2
assertEquals(2L, Evaluator.evaluate(stop, 3)); // 2, 3
@@ -369,7 +369,7 @@ if (arg) {
return i;
""");
StopNode stop = parser.parse().iterate();
- assertEquals("return Phi(Region45,.f,0);", stop.toString());
+ assertEquals("return Phi(Region,.f,0);", stop.toString());
}
@Test
diff --git a/chapter17/src/test/java/com/seaofnodes/simple/Chapter12Test.java b/chapter17/src/test/java/com/seaofnodes/simple/Chapter12Test.java
index c0f6266a..a70a5f33 100644
--- a/chapter17/src/test/java/com/seaofnodes/simple/Chapter12Test.java
+++ b/chapter17/src/test/java/com/seaofnodes/simple/Chapter12Test.java
@@ -43,7 +43,7 @@ while( 1 ) {
return guess;
""");
StopNode stop = parser.parse().iterate();
- assertEquals("return Phi(Loop11,(flt)arg,(((ToFloat/Phi_guess)+Phi_guess)/2.0));", stop.toString());
+ assertEquals("return Phi(Loop,(flt)arg,(((ToFloat/Phi_guess)+Phi_guess)/2.0));", stop.toString());
assertEquals(3.0, Evaluator.evaluate(stop, 9));
assertEquals(1.414213562373095, Evaluator.evaluate(stop, 2));
}
diff --git a/chapter17/src/test/java/com/seaofnodes/simple/Chapter14Test.java b/chapter17/src/test/java/com/seaofnodes/simple/Chapter14Test.java
index e72b0c76..01cecebb 100644
--- a/chapter17/src/test/java/com/seaofnodes/simple/Chapter14Test.java
+++ b/chapter17/src/test/java/com/seaofnodes/simple/Chapter14Test.java
@@ -175,7 +175,7 @@ while(v1) break;
return v1;
""");
StopNode stop = parser.parse().iterate();
- assertEquals("return (Phi(Loop18,((1<<arg)&1),0)&Phi(Loop,Shl,4294967295));", stop.toString());
+ assertEquals("return (Phi(Loop,((1<<arg)&1),0)&Phi(Loop,Shl,4294967295));", stop.toString());
assertEquals(1L, Evaluator.evaluate(stop, 0));
}
diff --git a/chapter17/src/test/java/com/seaofnodes/simple/Chapter15Test.java b/chapter17/src/test/java/com/seaofnodes/simple/Chapter15Test.java
index 4226c201..04958819 100644
--- a/chapter17/src/test/java/com/seaofnodes/simple/Chapter15Test.java
+++ b/chapter17/src/test/java/com/seaofnodes/simple/Chapter15Test.java
@@ -130,7 +130,7 @@ else {
return rez;
""");
StopNode stop = parser.parse().iterate();
- assertEquals("return Phi(Region117,1.2,Phi(Region114,2.3,3.14));", stop.toString());
+ assertEquals("return Phi(Region,1.2,Phi(Region,2.3,3.14));", stop.toString());
assertEquals(3.14, Evaluator.evaluate(stop, 0));
assertEquals(1.2 , Evaluator.evaluate(stop, 1));
}
@@ -157,7 +157,7 @@ if( iss[arg] )
return rez;
""");
StopNode stop = parser.parse().iterate();
- assertEquals("return Phi(Region122,Phi(Region118,.y,1.2),1.2);", stop.toString());
+ assertEquals("return Phi(Region,Phi(Region,.y,1.2),1.2);", stop.toString());
assertEquals(3.14, Evaluator.evaluate(stop, 0));
}
diff --git a/chapter17/src/test/java/com/seaofnodes/simple/Chapter16Test.java b/chapter17/src/test/java/com/seaofnodes/simple/Chapter16Test.java
index be48ec55..d0e30a7c 100644
--- a/chapter17/src/test/java/com/seaofnodes/simple/Chapter16Test.java
+++ b/chapter17/src/test/java/com/seaofnodes/simple/Chapter16Test.java
@@ -64,7 +64,7 @@ if( arg ) { int x = y; x = x*x; y=x; } // Shadow final x
return y;
""");
StopNode stop = parser.parse().iterate();
- assertEquals("return Phi(Region21,9,3);", stop.toString());
+ assertEquals("return Phi(Region,9,3);", stop.toString());
assertEquals(3L, Evaluator.evaluate(stop, 0));
assertEquals(9L, Evaluator.evaluate(stop, 1));
}
diff --git a/chapter17/src/test/java/com/seaofnodes/simple/Chapter17Test.java b/chapter17/src/test/java/com/seaofnodes/simple/Chapter17Test.java
index 5db9592e..fe275ee9 100644
--- a/chapter17/src/test/java/com/seaofnodes/simple/Chapter17Test.java
+++ b/chapter17/src/test/java/com/seaofnodes/simple/Chapter17Test.java
@@ -105,7 +105,7 @@ return d;
return arg ? 1 : 2;
""");
StopNode stop = parser.parse().iterate();
- assertEquals("return Phi(Region19,1,2);", stop.toString());
+ assertEquals("return Phi(Region,1,2);", stop.toString());
assertEquals(2L, Evaluator.evaluate(stop, 0));
assertEquals(1L, Evaluator.evaluate(stop, 1));
}
@@ -128,7 +128,7 @@ var b = arg ? new Bar : null;
return b ? b.x++ + b.x++ : -1;
""");
StopNode stop = parser.parse().iterate();
- assertEquals("return Phi(Region54,1,-1);", stop.toString());
+ assertEquals("return Phi(Region,1,-1);", stop.toString());
assertEquals(-1L, Evaluator.evaluate(stop, 0));
assertEquals( 1L, Evaluator.evaluate(stop, 1));
}
@@ -141,21 +141,21 @@ var b = arg ? new Bar;
return b ? b.x++ + b.x++ : -1;
""");
StopNode stop = parser.parse().iterate();
- assertEquals("return Phi(Region54,1,-1);", stop.toString());
+ assertEquals("return Phi(Region,1,-1);", stop.toString());
assertEquals(-1L, Evaluator.evaluate(stop, 0));
assertEquals( 1L, Evaluator.evaluate(stop, 1));
}
- @Ignore
@Test
public void testTrinary4() {
+ // This test case will benefit from an unzipping transformation
Parser parser = new Parser("""
struct Bar { Bar? next; int x; };
var b = arg ? new Bar { next = (arg==2) ? new Bar{x=2;}; x=1; };
return b ? b.next ? b.next.x : b.x; // parses "b ? (b.next ? b.next.x : b.x) : 0"
""");
StopNode stop = parser.parse().iterate();
- assertEquals("return Phi(Region51,1,-1);", stop.toString());
+ assertEquals("return Phi(Region,Phi(Region,.x,.x),0);", stop.toString());
assertEquals( 0L, Evaluator.evaluate(stop, 0));
assertEquals( 1L, Evaluator.evaluate(stop, 1));
assertEquals( 2L, Evaluator.evaluate(stop, 2));
@@ -178,7 +178,7 @@ while( head ) {
return sum;
""");
StopNode stop = parser.parse().iterate();
- assertEquals("return Phi(Loop35,0,(Phi_sum+.i));", stop.toString());
+ assertEquals("return Phi(Loop,0,(Phi_sum+.i));", stop.toString());
assertEquals(45L, Evaluator.evaluate(stop, 10));
}