summaryrefslogtreecommitdiff
path: root/chapter18
diff options
context:
space:
mode:
Diffstat (limited to 'chapter18')
-rw-r--r--chapter18/README.ja.md2
-rw-r--r--chapter18/README.md32
-rw-r--r--chapter18/src/main/java/com/seaofnodes/simple/CodeGen.java112
-rw-r--r--chapter18/src/main/java/com/seaofnodes/simple/GlobalCodeMotion.java11
-rw-r--r--chapter18/src/main/java/com/seaofnodes/simple/TypeCheck.java15
-rw-r--r--chapter18/src/main/java/com/seaofnodes/simple/print/SimpleGraphObserver.java2
-rw-r--r--chapter18/src/test/java/com/seaofnodes/simple/BrainFuckTest.java2
-rw-r--r--chapter18/src/test/java/com/seaofnodes/simple/Chapter05Test.java16
-rw-r--r--chapter18/src/test/java/com/seaofnodes/simple/Chapter06Test.java32
-rw-r--r--chapter18/src/test/java/com/seaofnodes/simple/Chapter07Test.java14
-rw-r--r--chapter18/src/test/java/com/seaofnodes/simple/Chapter08Test.java22
-rw-r--r--chapter18/src/test/java/com/seaofnodes/simple/Chapter09Test.java40
-rw-r--r--chapter18/src/test/java/com/seaofnodes/simple/Chapter10Test.java56
-rw-r--r--chapter18/src/test/java/com/seaofnodes/simple/Chapter11Test.java6
-rw-r--r--chapter18/src/test/java/com/seaofnodes/simple/Chapter12Test.java30
-rw-r--r--chapter18/src/test/java/com/seaofnodes/simple/Chapter13Test.java28
-rw-r--r--chapter18/src/test/java/com/seaofnodes/simple/Chapter14FloatTest.java14
-rw-r--r--chapter18/src/test/java/com/seaofnodes/simple/Chapter14Test.java30
-rw-r--r--chapter18/src/test/java/com/seaofnodes/simple/Chapter15Test.java42
-rw-r--r--chapter18/src/test/java/com/seaofnodes/simple/Chapter16Test.java18
-rw-r--r--chapter18/src/test/java/com/seaofnodes/simple/Chapter17aTest.java16
-rw-r--r--chapter18/src/test/java/com/seaofnodes/simple/Chapter17bTest.java94
-rw-r--r--chapter18/src/test/java/com/seaofnodes/simple/Chapter18Test.java68
-rw-r--r--chapter18/src/test/java/com/seaofnodes/simple/CompoundAssignmentTest.java2
-rw-r--r--chapter18/src/test/java/com/seaofnodes/simple/Eval2.java4
-rw-r--r--chapter18/src/test/java/com/seaofnodes/simple/MergeSortTest.java2
-rw-r--r--chapter18/src/test/java/com/seaofnodes/simple/MutabilityTest.java4
-rw-r--r--chapter18/src/test/java/com/seaofnodes/simple/PhaseTest.java33
-rw-r--r--chapter18/src/test/java/com/seaofnodes/simple/SchedulerTest.java26
-rw-r--r--chapter18/src/test/java/com/seaofnodes/simple/fuzzer/Fuzzer.java2
-rw-r--r--chapter18/src/test/java/com/seaofnodes/simple/fuzzer/FuzzerUtils.java2
31 files changed, 432 insertions, 345 deletions
diff --git a/chapter18/README.ja.md b/chapter18/README.ja.md
index 6c0396b4..ad078163 100644
--- a/chapter18/README.ja.md
+++ b/chapter18/README.ja.md
@@ -214,7 +214,7 @@ Add は残りますが、今度は `arg` を直接消費します。引数が `3
```java
CodeGen code = new CodeGen("val sq = { int x -> x*x; }; return sq(arg);");
-code.parse().opto().typeCheck().GCM().localSched();
+code.driver(CodeGen.Phase.LocalSched);
```
大域的コード移動は、[第13章](../chapter13/README.ja.md)の処理を複数の関数に拡張します。関数本体を別々に保ち、共有される定数式には、それを使う各関数内に局所的なコピーを与え、呼び出しをまたぐメモリへの作用を尊重します。
diff --git a/chapter18/README.md b/chapter18/README.md
index 9b13e277..578ed7d4 100644
--- a/chapter18/README.md
+++ b/chapter18/README.md
@@ -81,8 +81,7 @@ es[1] = 9;
return find(es,9); // 1
```
-All reachable results of one function must have a common type. This is checked
-after optimization, so an unreachable return does not cause a type error.
+Return types are generally inferred, so all returns must have a common type.
There is no `void` type although a function can return `null` with no syntax,
and callers can ignore a result by using the call as a statement.
@@ -161,10 +160,10 @@ body contains branches, loops, and several return statements.
### Calls and return points
[CallNode](src/main/java/com/seaofnodes/simple/node/CallNode.java) takes inputs
-`{control, memory, arguments..., function pointer}`. The final input determines
-the target; it can be a constant function or the result of a function-valued
-expression. Argument expressions are evaluated before the Call takes its
-control and memory inputs.
+`{control, memory, arguments..., function pointer}`. The final input
+determines the target; it can be a constant function or the result of a
+function-valued expression. Argument expressions are evaluated in order before the Call
+takes its control and memory inputs.
Each Call has a [CallEndNode](src/main/java/com/seaofnodes/simple/node/CallEndNode.java),
the point where its caller continues. CallEnd takes the Call and the Returns
@@ -323,8 +322,9 @@ compilation process and its function lookup table. It enforces the phase order:
| Phase | Purpose |
|---|---|
| Parse | Build the functions and calls directly in the IR. |
-| Opto | Iterate peepholes, including call linking and trivial inlining. |
+| Iter | Iterate peepholes, including call linking and trivial inlining. |
| TypeCheck | Check the surviving graph after types and dead control have settled. |
+| LoopTree | Discover loop nesting and connect nonreturning loops with synthetic exits. |
| Schedule | Use global code motion to place operations in basic blocks. |
| LocalSched | Order operations within each block for execution. |
@@ -332,9 +332,25 @@ For example:
```java
CodeGen code = new CodeGen("val sq = { int x -> x*x; }; return sq(arg);");
-code.parse().opto().typeCheck().GCM().localSched();
+code.driver(CodeGen.Phase.TypeCheck);
```
+With six stages, writing the whole call chain at every use obscures what the
+caller needs. `driver(target)` runs the missing phases in order and stops at
+the requested stage. A later call resumes from there; asking for an already
+completed stage does not rerun it:
+
+```java
+code.driver(CodeGen.Phase.LoopTree); // Ready to inspect loops.
+code.driver(CodeGen.Phase.LocalSched); // Finish scheduling.
+```
+
+Short tests can still say `code.parse().iter()` to show exactly what they test.
+`Iter` is the worklist solve introduced in Chapter 9; an optimistic `Opto`
+phase arrives with SCCP in Chapter 24. Phase entry points check ordering and
+report their completion to the graph viewer. Loop-tree construction is now
+an explicit entry point instead of work hidden inside GCM.
+
Global code motion extends the work of [Chapter 13](../chapter13/README.md) to
multiple functions. It keeps their bodies separate, gives shared constant
expressions a local copy in each function that uses them, and respects memory
diff --git a/chapter18/src/main/java/com/seaofnodes/simple/CodeGen.java b/chapter18/src/main/java/com/seaofnodes/simple/CodeGen.java
index 864b3a1a..e5ac8530 100644
--- a/chapter18/src/main/java/com/seaofnodes/simple/CodeGen.java
+++ b/chapter18/src/main/java/com/seaofnodes/simple/CodeGen.java
@@ -1,4 +1,4 @@
- package com.seaofnodes.simple;
+package com.seaofnodes.simple;
import com.seaofnodes.graph.GraphObserver;
@@ -20,10 +20,45 @@ public class CodeGen {
public enum Phase {
- Parse, Opto, TypeCheck, Schedule, LocalSched, RegAlloc;
+ Parse, // Build ideal IR from source
+ Iter, // Pessimistic peepholes
+ TypeCheck, // Check the surviving ideal graph
+ LoopTree, // Discover loops and connect nonreturning paths
+ Schedule, // Global code motion
+ LocalSched; // Order instructions within blocks
+
}
public Phase _phase;
+ // Run through target, skipping phases already completed.
+ public CodeGen driver(Phase target) {
+ step(target, Phase.Parse, this::parse);
+ step(target, Phase.Iter, this::iter);
+ step(target, Phase.TypeCheck, this::typeCheck);
+ step(target, Phase.LoopTree, this::loopTree);
+ step(target, Phase.Schedule, this::GCM);
+ step(target, Phase.LocalSched, this::localSched);
+ return this;
+ }
+
+ private void step(Phase target, Phase next, Runnable work) {
+ if( next.ordinal()>target.ordinal() || (_phase!=null && _phase.ordinal()>=next.ordinal()) ) return;
+ work.run();
+ }
+
+ public final long[] _times = new long[Phase.values().length];
+ private CodeGen phase(Phase next, boolean ordered, Runnable work) {
+ assert ordered : "Cannot run "+next+" after "+_phase;
+ _phase = next;
+ long t0 = System.currentTimeMillis();
+ try { work.run(); }
+ finally { _times[next.ordinal()] = System.currentTimeMillis()-t0; }
+ if( _obs!=null ) _obs.phase(next.name());
+ return this;
+ }
+
+
+
public final String _src;
// Compile-time known initial argument type
public final TypeInteger _arg;
@@ -46,71 +81,38 @@ public class CodeGen {
public CodeGen( String src ) { this(src,TypeInteger.BOT); }
public CodeGen parse() {
- assert _phase == null;
- _phase = Phase.Parse;
- _linker.clear();
-
- P = new Parser(_src,_arg);
- _stop = P.parse();
- _start = Parser.START; // Capture global start
- if( _obs != null ) _obs.phase("Parse");
- P = null; // No longer parsing
- return this;
- }
+ return phase(Phase.Parse, _phase==null, () -> {
+ _linker.clear();
- public CodeGen opto() {
- assert _phase == Phase.Parse;
- _phase = Phase.Opto;
-
- // Optimization
- IterPeeps.iterate(_stop);
-
- // TODO:
- // Optimistic
- if( _obs != null ) _obs.phase("Opto");
- return this;
- }
-
- public CodeGen typeCheck() {
- // Demand phase Opto for cleaning up dead control flow at least,
- // required for the following GCM.
- assert _phase == Phase.Opto;
- _phase = Phase.TypeCheck;
-
- // Type check
- Parser.ParseException err = _stop.walk(n -> {
- Parser.ParseException msg = n.err();
- if( msg != null && _obs != null ) _obs.error(n, msg.getMessage());
- return msg;
+ P = new Parser(_src,_arg);
+ _stop = P.parse();
+ _start = Parser.START; // Capture global start
+ P = null; // No longer parsing
});
- if( err != null )
- throw err;
- if( _obs != null ) _obs.phase("TypeCheck");
- return this;
}
+ // Pessimistic peepholes reach a fixed point after parsing.
+ public CodeGen iter() { return phase(Phase.Iter, _phase==Phase.Parse, () -> IterPeeps.iterate(_stop)); }
- public CodeGen GCM() {
- assert _phase == Phase.TypeCheck;
- _phase = Phase.Schedule;
+ public CodeGen typeCheck() { return phase(Phase.TypeCheck, _phase==Phase.Iter, () -> TypeCheck.run(this)); }
- // Build the loop tree, fix never-exit loops
- _start.buildLoopTree(_stop);
+ public CodeGen loopTree() {
+ return phase(Phase.LoopTree, _phase==Phase.TypeCheck, () -> _start.buildLoopTree(_stop));
+ }
- // TODO:
- // loop unroll, peel, RCE, etc
- GlobalCodeMotion.buildCFG(_start,_stop);
- return this;
+ public CodeGen GCM() {
+ return phase(Phase.Schedule, _phase==Phase.LoopTree, () -> {
+ // TODO:
+ // loop unroll, peel, RCE, etc
+ GlobalCodeMotion.buildCFG(_start,_stop);
+ });
}
// Local (basic block) scheduler phase, a classic list scheduler
public CodeGen localSched() {
- assert _phase == Phase.Schedule;
- _phase = Phase.LocalSched;
- ListScheduler.sched(this);
- return this;
- }
+ return phase(Phase.LocalSched, _phase==Phase.Schedule, () -> ListScheduler.sched(this));
+ }
// Reverse from a constant function pointer to the IR function being called
public FunNode link( TypeFunPtr tfp ) {
diff --git a/chapter18/src/main/java/com/seaofnodes/simple/GlobalCodeMotion.java b/chapter18/src/main/java/com/seaofnodes/simple/GlobalCodeMotion.java
index 8221ede1..2019b714 100644
--- a/chapter18/src/main/java/com/seaofnodes/simple/GlobalCodeMotion.java
+++ b/chapter18/src/main/java/com/seaofnodes/simple/GlobalCodeMotion.java
@@ -260,10 +260,11 @@ public abstract class GlobalCodeMotion {
lca = anti_dep(load,late[st._nid],st.cfg0(),lca,st,anti);
break;
case PhiNode phi:
- // Repeat anti-dep for matching Phi inputs.
- // No anti-dep edges but may raise the LCA.
+ // Inputs carrying different memory might overwrite this alias.
+ // Raise the LCA for those paths; unchanged memory does not
+ // clobber the load. No scheduling edge to the Phi.
for( int i=1; i<phi.nIns(); i++ )
- if( phi.in(i)==load.mem() )
+ if( phi.in(i)!=load.mem() )
lca = anti_dep(load,phi.region().cfg(i),load.mem().cfg0(),lca,null,anti);
break;
case NewNode st:
@@ -278,7 +279,9 @@ public abstract class GlobalCodeMotion {
//
private static CFGNode anti_dep( LoadNode load, CFGNode stblk, CFGNode defblk, CFGNode lca, Node st, int[] anti ) {
- for( ; stblk != defblk.idom(); stblk = stblk.idom() ) {
+ // Another Phi input need not be dominated by this memory definition.
+ // Include its depth, and retain the sentinel for an entry's null idom.
+ for( ; stblk != defblk.idom() && stblk.idepth() >= defblk.idepth(); stblk = stblk.idom() ) {
// Store and Load overlap, need anti-dependence
if( anti[stblk._nid]==load._nid ) {
lca = stblk.domLCA(lca,null); // Raise Loads LCA
diff --git a/chapter18/src/main/java/com/seaofnodes/simple/TypeCheck.java b/chapter18/src/main/java/com/seaofnodes/simple/TypeCheck.java
new file mode 100644
index 00000000..a41e4161
--- /dev/null
+++ b/chapter18/src/main/java/com/seaofnodes/simple/TypeCheck.java
@@ -0,0 +1,15 @@
+package com.seaofnodes.simple;
+
+import com.seaofnodes.simple.Parser;
+
+abstract class TypeCheck {
+ static void run(CodeGen code) {
+ Parser.ParseException err = code._stop.walk(n -> {
+ Parser.ParseException msg = n.err();
+ if( msg != null && code._obs != null ) code._obs.error(n, msg.getMessage());
+ return msg;
+ });
+ if( err != null )
+ throw err;
+ }
+}
diff --git a/chapter18/src/main/java/com/seaofnodes/simple/print/SimpleGraphObserver.java b/chapter18/src/main/java/com/seaofnodes/simple/print/SimpleGraphObserver.java
index b2dd3107..4db81c70 100644
--- a/chapter18/src/main/java/com/seaofnodes/simple/print/SimpleGraphObserver.java
+++ b/chapter18/src/main/java/com/seaofnodes/simple/print/SimpleGraphObserver.java
@@ -17,7 +17,7 @@ public class SimpleGraphObserver extends GraphCapture<Node> {
@Override protected void compile(String src) {
_code = new CodeGen(src);
_code._obs = this;
- _code.parse().opto().typeCheck();
+ _code.driver(CodeGen.Phase.TypeCheck);
}
@Override protected String phase() { return _code._phase.name(); }
@Override protected int pos() { return _code.P != null ? _code.P.pos() : -1; }
diff --git a/chapter18/src/test/java/com/seaofnodes/simple/BrainFuckTest.java b/chapter18/src/test/java/com/seaofnodes/simple/BrainFuckTest.java
index 37ecde1c..43314312 100644
--- a/chapter18/src/test/java/com/seaofnodes/simple/BrainFuckTest.java
+++ b/chapter18/src/test/java/com/seaofnodes/simple/BrainFuckTest.java
@@ -63,7 +63,7 @@ for( int pc = 0; pc < program#; pc++ ) {
}
return output;
""");
- code.parse().opto().typeCheck().GCM();
+ code.driver(CodeGen.Phase.Schedule);
assertEquals("Hello World!\n", Eval2.eval(code, 0, 10000));
}
}
diff --git a/chapter18/src/test/java/com/seaofnodes/simple/Chapter05Test.java b/chapter18/src/test/java/com/seaofnodes/simple/Chapter05Test.java
index ff60c695..e88474a4 100644
--- a/chapter18/src/test/java/com/seaofnodes/simple/Chapter05Test.java
+++ b/chapter18/src/test/java/com/seaofnodes/simple/Chapter05Test.java
@@ -19,7 +19,7 @@ else {
}
return a;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Region,(arg+2),(arg-3));", code.print());
}
@@ -35,7 +35,7 @@ if (arg == 1) {
}
return c;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Region,4,3);", code.print());
}
@@ -63,7 +63,7 @@ if( arg==1 )
else
b=a+1;
return a+b;""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return ((arg*2)+Phi(Region,2,3));", code.print());
}
@@ -78,7 +78,7 @@ if( arg==1 )
else
a=b+1;
return a+b;""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return ((Phi(Region,(arg*2),arg)+arg)+Phi(Region,4,5));", code.print());
}
@@ -98,7 +98,7 @@ else
a=5;
return a;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Region,Phi(Region,2,3),Phi(Region,4,5));", code.print());
}
@@ -114,7 +114,7 @@ if( arg==0 )
b=2;
return arg+a+b;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return ((arg+Phi(Region,1,0))+Phi(Region,2,0));", code.print());
}
@@ -129,7 +129,7 @@ if( arg==1 )
}
return a;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return (arg==Phi(Region,3,2));", code.print());
}
@@ -144,7 +144,7 @@ else
a=3;
return a;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 3;", code.print());
}
diff --git a/chapter18/src/test/java/com/seaofnodes/simple/Chapter06Test.java b/chapter18/src/test/java/com/seaofnodes/simple/Chapter06Test.java
index 2107cdb0..ed51ebe3 100644
--- a/chapter18/src/test/java/com/seaofnodes/simple/Chapter06Test.java
+++ b/chapter18/src/test/java/com/seaofnodes/simple/Chapter06Test.java
@@ -14,7 +14,7 @@ public class Chapter06Test {
if( true ) return 2;
return 1;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 2;", code.print());
assertTrue(code.ctrl() instanceof FunNode);
}
@@ -28,7 +28,7 @@ if (arg)
a = 2;
return (arg < a) < 3; // Because (arg < a) is a bool/uint1/[0-1], its always less than 3
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 1;", code.print());
}
@@ -43,7 +43,7 @@ else
a=3;
return a;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 2;", code.print());
assertTrue(code.ctrl() instanceof FunNode);
}
@@ -64,7 +64,7 @@ else
b=5;
return b;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Region,42,5);", code.print());
}
@@ -83,7 +83,7 @@ if( arg==2 )
else
b=5;
return b;""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Region,2,5);", code.print());
}
@@ -104,7 +104,7 @@ else
a=5;
return a;
""", TypeInteger.constant(2));
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 5;", code.print());
}
@@ -125,7 +125,7 @@ else
a=5;
return a;
""", TypeInteger.constant(1));
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 3;", code.print());
}
@@ -145,7 +145,7 @@ else
a=5;
return a;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Region,3,Phi(Region,4,5));", code.print());
}
@@ -166,7 +166,7 @@ else
a=5;
return a;
""", TypeInteger.constant(1));
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 3;", code.print());
}
@@ -187,7 +187,7 @@ else
a=5;
return a;
""", TypeInteger.constant(3));
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 4;", code.print());
}
@@ -203,7 +203,7 @@ if( arg ) {
}
return a+b;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Region,4,1);", code.print());
}
@@ -221,7 +221,7 @@ if( arg ) {
}
return a+b;
""", TypeInteger.constant(1));
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 4;", code.print());
}
@@ -238,7 +238,7 @@ if( arg ) {
}
return a+b;
""", TypeInteger.constant(0));
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 1;", code.print());
}
@@ -256,7 +256,7 @@ if( arg ) {
}
return a+b+c;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return (Phi(Region,Phi(Region,2,3),0)+Phi(Region,3,1));", code.print());
}
@@ -276,7 +276,7 @@ if( arg ) {
}
return a+b+c;
""", TypeInteger.constant(1));
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 6;", code.print());
}
@@ -295,7 +295,7 @@ if( arg ) {
}
return a+b+c;
""", TypeInteger.constant(2));
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 5;", code.print());
}
diff --git a/chapter18/src/test/java/com/seaofnodes/simple/Chapter07Test.java b/chapter18/src/test/java/com/seaofnodes/simple/Chapter07Test.java
index 6d6a3ce7..a5c6ef14 100644
--- a/chapter18/src/test/java/com/seaofnodes/simple/Chapter07Test.java
+++ b/chapter18/src/test/java/com/seaofnodes/simple/Chapter07Test.java
@@ -33,7 +33,7 @@ if(arg){}else{
}
return a;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Region,1,Phi(Loop,1,(Phi_a+1)));", code.print());
}
@@ -53,7 +53,7 @@ while(i < arg) {
}
return sum;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Loop,0,Phi(Loop,Phi_sum,(Phi_sum+Phi(Loop,0,(Phi_j+1)))));", code.print());
}
@@ -88,7 +88,7 @@ while(a < 10) {
}
return b;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Loop,2,(Phi(Region,Phi_b,4)+1));", code.print());
assertTrue(code.ctrl() instanceof CProjNode);
}
@@ -121,7 +121,7 @@ while(a < 10) {
}
return a;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Loop,1,(Phi_a+3));", code.print());
assertTrue(code.ctrl() instanceof CProjNode);
}
@@ -147,7 +147,7 @@ int a = 1;
while(arg) a = 2;
return a;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Loop,1,2);", code.print());
assertTrue(code.ctrl() instanceof CProjNode);
}
@@ -179,7 +179,7 @@ while(a < 10) {
}
return a;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Loop,1,(Phi_a+3));", code.print());
assertTrue(code.ctrl() instanceof CProjNode);
}
@@ -213,7 +213,7 @@ while(a < 10) {
}
return a;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Loop,1,(Phi_a+3));", code.print());
assertTrue(code.ctrl() instanceof CProjNode);
}
diff --git a/chapter18/src/test/java/com/seaofnodes/simple/Chapter08Test.java b/chapter18/src/test/java/com/seaofnodes/simple/Chapter08Test.java
index 03a2c50a..379bb55b 100644
--- a/chapter18/src/test/java/com/seaofnodes/simple/Chapter08Test.java
+++ b/chapter18/src/test/java/com/seaofnodes/simple/Chapter08Test.java
@@ -23,7 +23,7 @@ while(arg < 10) {
}
return arg;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Region,Phi(Region,Phi(Loop,arg,(Phi_arg+1)),Add),Add);", code.print());
assertTrue(code.ctrl() instanceof RegionNode);
Assert.assertEquals( "5", Eval2.eval(code, 1));
@@ -46,7 +46,7 @@ while(arg < 10) {
}
return a;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Loop,1,Phi(Region,Phi_a,(Phi_a+1)));", code.print());
assertTrue(code.ctrl() instanceof CProjNode);
}
@@ -65,7 +65,7 @@ while(arg < 10) {
}
return arg;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Region,Phi(Loop,arg,(Phi_arg+1)),Add);", code.print());
assertTrue(code.ctrl() instanceof RegionNode);
}
@@ -81,7 +81,7 @@ while(arg < 10) {
}
return arg;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Region,Phi(Loop,arg,(Phi_arg+1)),Add);", code.print());
assertTrue(code.ctrl() instanceof RegionNode);
}
@@ -100,7 +100,7 @@ while(arg < 10) {
}
return arg;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Loop,arg,(Phi_arg+1));", code.print());
assertTrue(code.ctrl() instanceof CProjNode);
}
@@ -117,7 +117,7 @@ while(arg < 10) {
}
return arg;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Loop,arg,(Phi_arg+1));", code.print());
assertTrue(code.ctrl() instanceof CProjNode);
}
@@ -133,14 +133,14 @@ while( arg < 10 ) {
}
return arg;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return arg;", code.print());
}
@Test
public void testRegress2() {
CodeGen code = new CodeGen("if(1) return 0; else while(arg>- -arg) arg=arg+1; return 0;");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 0;", code.print());
}
@@ -168,7 +168,7 @@ while(arg < 10) {
}
return arg;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return arg;", code.print());
}
@@ -185,7 +185,7 @@ while(arg < 10) {
}
return a;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Region,Phi(Loop,1,(Phi_a+1)),Add);", code.print());
assertTrue(code.ctrl() instanceof RegionNode);
}
@@ -201,7 +201,7 @@ while(1) {
}
return a;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return (Phi(Loop,1,Add)+1);", code.print());
assertTrue(code.ctrl() instanceof CProjNode prj && prj._idx==1 );
}
diff --git a/chapter18/src/test/java/com/seaofnodes/simple/Chapter09Test.java b/chapter18/src/test/java/com/seaofnodes/simple/Chapter09Test.java
index b210f7e9..410e32cd 100644
--- a/chapter18/src/test/java/com/seaofnodes/simple/Chapter09Test.java
+++ b/chapter18/src/test/java/com/seaofnodes/simple/Chapter09Test.java
@@ -24,7 +24,7 @@ while(v0) {
}
return 0;
""");
- code.parse().opto();
+ code.parse().iter();
}
@Test
@@ -40,7 +40,7 @@ else {
}
return x;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Region,(arg*2),(Mul+1));", code.print());
Assert.assertEquals( "2", Eval2.eval(code, 1));
Assert.assertEquals("23", Eval2.eval(code, 11));
@@ -49,7 +49,7 @@ return x;
@Test
public void testGVN2() {
CodeGen code = new CodeGen("return arg*arg-arg*arg;");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 0;", code.print());
Assert.assertEquals("0", Eval2.eval(code, 1, 1));
}
@@ -63,7 +63,7 @@ while (arg < 10) {
}
return arg;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Loop,arg,(Phi_arg+2));", code.print());
Assert.assertEquals("11", Eval2.eval(code, 1));
}
@@ -80,7 +80,7 @@ while (arg < 10) {
}
return arg;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Loop,arg,(Phi_arg+4));", code.print());
Assert.assertEquals("13", Eval2.eval(code, 1));
}
@@ -109,7 +109,7 @@ while (arg) {
}
return arg;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 0;", code.print());
}
@@ -127,14 +127,14 @@ while(v1+arg) {
v1=v2;
}
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 0;", code.print());
}
@Test
public void testWhile0() {
CodeGen code = new CodeGen("while(0) continue; if(0) arg=0;");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 0;", code.print());
}
@@ -146,7 +146,7 @@ if(0) while(0) {
while(0) {}
}
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 0;", code.print());
}
@@ -154,14 +154,14 @@ if(0) while(0) {
@Test
public void testPrecedence() {
CodeGen code = new CodeGen("return 3-1+2;");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 4;", code.print());
}
@Test
public void testSwap2() {
CodeGen code = new CodeGen("return 1+(1+1);");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 3;", code.print());
}
@@ -179,7 +179,7 @@ while(arg) {
}
return a;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Loop,0,(-(Phi_a+3)));", code.print());
}
@@ -193,7 +193,7 @@ arg=0;
int v0=0!=0<-0;
return -0+0+0;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Top;", code.print());
}
@@ -201,14 +201,14 @@ return -0+0+0;
@Test
public void testFuzz2() {
CodeGen code = new CodeGen("return 0+-0;");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 0;", code.print());
}
@Test
public void testFuzz3() {
CodeGen code = new CodeGen("int v0=0; while(0==69) while(v0) return 0;");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 0;", code.print());
}
@@ -220,7 +220,7 @@ while(1) {
if(1<0) while(arg==-0) arg=arg-arg;
}
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Top;", code.print());
}
@@ -242,7 +242,7 @@ while(1) {
}
return 0!=0;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Top;", code.print());
}
@@ -254,7 +254,7 @@ int v0=0;
while(0==1) while(v0)
v0=1+v0;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return ~int;", code.print());
}
@@ -270,14 +270,14 @@ while(1)
v1=1;
return v1+v0;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Top;", code.print());
}
@Test
public void testFuzz8() {
CodeGen code = new CodeGen("while(arg) arg = arg - 1; return arg;");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 0;", code.print());
}
diff --git a/chapter18/src/test/java/com/seaofnodes/simple/Chapter10Test.java b/chapter18/src/test/java/com/seaofnodes/simple/Chapter10Test.java
index bcae373b..2681e878 100644
--- a/chapter18/src/test/java/com/seaofnodes/simple/Chapter10Test.java
+++ b/chapter18/src/test/java/com/seaofnodes/simple/Chapter10Test.java
@@ -13,7 +13,7 @@ public class Chapter10Test {
"if(1) return new S; else return 0;"
} ) {
String src = "struct S { int x; }; " + body;
- var code = new CodeGen(src).parse().opto().typeCheck();
+ var code = new CodeGen(src).parse().iter().typeCheck();
org.junit.Assert.assertTrue(body,
code.expr()._type instanceof com.seaofnodes.simple.type.TypeMemPtr);
}
@@ -38,7 +38,7 @@ public class Chapter10Test {
"if (!!!p) return -1; return p.x;",
"int b = !!p; if (b) return p.x + b - 1; return -1;"
} ) {
- CodeGen code = new CodeGen(NULLABLE_POINT_SOURCE+body).parse().opto().typeCheck();
+ CodeGen code = new CodeGen(NULLABLE_POINT_SOURCE+body).parse().iter().typeCheck();
assertEquals(body,"-1",Eval2.eval(code,0));
assertEquals(body,"42",Eval2.eval(code,1));
}
@@ -53,7 +53,7 @@ public class Chapter10Test {
"if (!!p) { int x = p.x; } return p.x;"
} ) {
try {
- new CodeGen(NULLABLE_POINT_SOURCE+body).parse().opto().typeCheck();
+ new CodeGen(NULLABLE_POINT_SOURCE+body).parse().iter().typeCheck();
fail(body);
} catch( RuntimeException e ) {
// Known null is rejected during parsing in these chapters.
@@ -85,7 +85,7 @@ if( (arg/13)==0 ) {
int r = g+h;
return p-r;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 0;", code.print());
}
@@ -105,7 +105,7 @@ bar.a = 1;
bar.a = 2;
return bar.a;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 2;", code.print());
}
@@ -121,7 +121,7 @@ else
v.y = 3;
return v;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Vector2D;", code.print());
}
@@ -159,7 +159,7 @@ while (arg) {
}
return bar.a;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Loop,0,(Phi_a+2));", code.print());
}
@@ -172,7 +172,7 @@ if (arg) bar = null;
bar.a = 1;
return bar.a;
""");
- try { code.parse().opto(); fail(); }
+ try { code.parse().iter(); fail(); }
catch( Exception e ) { assertEquals("Type null is not of declared type *Bar",e.getMessage()); }
}
@@ -185,7 +185,7 @@ if (arg) bar = new Bar;
bar.a = 1;
return bar.a;
""");
- try { code.parse().opto().typeCheck(); fail(); }
+ try { code.parse().iter().typeCheck(); fail(); }
catch( Exception e ) { assertEquals("Might be null accessing 'a'",e.getMessage()); }
}
@@ -211,7 +211,7 @@ if (arg) bar = null;
if( bar ) bar.a = 1;
return bar;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Region,null,Bar);", code.print());
}
@@ -227,7 +227,7 @@ if( !bar ) rez=4;
else bar.a = 1;
return rez;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Region,4,3);", code.print());
}
@@ -244,7 +244,7 @@ while(arg) {
}
return ret;
""");
- try { code.parse().opto().typeCheck(); fail(); }
+ try { code.parse().iter().typeCheck(); fail(); }
catch( Exception e ) {
assertEquals("Might be null accessing 'v0'", e.getMessage()); }
}
@@ -281,7 +281,7 @@ while( i.x < i.len ) {
}
return sum;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Loop,0,(Phi(Loop,0,(Phi_x+1))+Phi_sum));", code.print());
}
@@ -300,7 +300,7 @@ while(arg) {
}
return ret;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Loop,s0,Phi(Region,s0,Phi_ret));", code.print());
}
@@ -318,7 +318,7 @@ while(arg) {
}
return ret;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Loop,s0,Phi(Region,s0,Phi_ret));", code.print());
}
@@ -335,7 +335,7 @@ while(arg < 10) {
}
return ret;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Loop,s0,Phi(Region,s0,Phi_ret));", code.print());
}
@@ -362,7 +362,7 @@ if(0) {
}
}
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 0;", code.print());
}
@@ -376,7 +376,7 @@ if(0) return 0;
else return new s0;
if(new s0.f0) return 0;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return s0;", code.print());
}
@@ -392,7 +392,7 @@ while(0<arg) {
}
return 0;
""");
- code.parse().opto();
+ code.parse().iter();
}
@Test
@@ -404,7 +404,7 @@ while(v0.f0) {}
s0 v1 = v0;
return v1;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return (const)s0;", code.print());
}
@@ -436,7 +436,7 @@ while(0) {}
} }
}
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 0;", code.print());
}
@@ -447,7 +447,7 @@ int v0=arg==0;
while(v0) continue;
return 0;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 0;", code.print());
}
@@ -461,7 +461,7 @@ return 0;
a.y = 55; b.y = 66;
a.x = 33; b.x = 44;
return before*100 + p.x;
- """).parse().opto();
+ """).parse().iter();
StopNode stop = code._stop;
assertEquals("1133",Eval2.eval(code,0));
assertEquals("2244",Eval2.eval(code,1));
@@ -487,7 +487,7 @@ return 0;
""";
@Test public void testMemoryAcrossNestedLoops() {
- var code = new CodeGen(NESTED_MEMORY).parse().opto();
+ var code = new CodeGen(NESTED_MEMORY).parse().iter();
StopNode stop = code._stop;
for (int arg=0; arg<7; arg++) {
assertEquals("S{x="+(5L+arg)+",y="+(7L+arg*(arg+1)-(arg>=2 ? 2 : 0))+
@@ -503,7 +503,7 @@ return 0;
if (arg) { s.x = 11; s.z = 13; return s; }
s.y = 17;
return s;
- """).parse().opto();
+ """).parse().iter();
StopNode stop = code._stop;
for (int arg=0; arg<2; arg++) {
assertEquals(arg==0 ? "S{x=3,y=17,z=7}" : "S{x=11,y=5,z=13}",Eval2.eval(code,arg));
@@ -520,7 +520,7 @@ return 0;
int v;
if (arg>1) v=p.x; else v=q.x;
return v;
- """).parse().opto();
+ """).parse().iter();
StopNode stop = code._stop;
// The one-step safety check stops at the memory aggregate.
assertEquals(2,countMemoryNodes(stop,LoadNode.class,new BitSet()));
@@ -535,7 +535,7 @@ return 0;
!S !s = new S;
if (arg) s.x=arg+1; else s.x=arg+2;
return s;
- """).parse().opto();
+ """).parse().iter();
StopNode stop = code._stop;
assertEquals(1,countMemoryNodes(stop,StoreNode.class,new BitSet()));
assertEquals("S{x=2}",Eval2.eval(code,0));
@@ -553,7 +553,7 @@ return 0;
if (arg>1) { v=p.x; p.x=41; p.y=5; }
else { v=q.x; q.x=42; }
return v;
- """).parse().opto();
+ """).parse().iter();
StopNode stop = code._stop;
assertEquals(2,countMemoryNodes(stop,LoadNode.class,new BitSet()));
assertEquals("-1",Eval2.eval(code,-1));
diff --git a/chapter18/src/test/java/com/seaofnodes/simple/Chapter11Test.java b/chapter18/src/test/java/com/seaofnodes/simple/Chapter11Test.java
index 9fd392d2..b21d9e0e 100644
--- a/chapter18/src/test/java/com/seaofnodes/simple/Chapter11Test.java
+++ b/chapter18/src/test/java/com/seaofnodes/simple/Chapter11Test.java
@@ -12,7 +12,7 @@ public class Chapter11Test {
s.x = 42;
while (arg > 0) { s.y = s.y + arg; arg = arg - 1; }
return s.x;
- """).parse().opto();
+ """).parse().iter();
var stop = code._stop;
assertEquals("return 42;",stop.toString());
assertEquals("42",Eval2.eval(code,5));
@@ -31,7 +31,7 @@ public class Chapter11Test {
arg = arg - 1;
}
return a;
- """).parse().opto();
+ """).parse().iter();
var stop = code._stop;
int[] phis = {0};
stop.walk(n -> {
@@ -59,7 +59,7 @@ public class Chapter11Test {
field = work.getClass().getDeclaredField("_R");
field.setAccessible(true);
((java.util.Random)field.get(work)).setSeed(seed);
- code.opto();
+ code.iter();
assertEquals("S{x=9,y=25,z=17}",Eval2.eval(code,4));
}
}
diff --git a/chapter18/src/test/java/com/seaofnodes/simple/Chapter12Test.java b/chapter18/src/test/java/com/seaofnodes/simple/Chapter12Test.java
index a15132d4..aa4f1ae5 100644
--- a/chapter18/src/test/java/com/seaofnodes/simple/Chapter12Test.java
+++ b/chapter18/src/test/java/com/seaofnodes/simple/Chapter12Test.java
@@ -13,7 +13,7 @@ public class Chapter12Test {
"""
return 3.14;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 3.14;", code.print());
assertEquals("3.14", Eval2.eval(code, 0));
}
@@ -33,7 +33,7 @@ while( arg ) {
}
return head.next.i;
""");
- try { code.parse().opto().typeCheck(); fail(); }
+ try { code.parse().iter().typeCheck(); fail(); }
catch( Exception e ) { assertEquals("Might be null accessing 'i'",e.getMessage()); }
}
@@ -55,7 +55,7 @@ LLI? next = head.next;
if( next==null ) return 1;
return next.i;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Region,0,1,.i);", code.print());
assertEquals("2", Eval2.eval(code, 3));
}
@@ -74,7 +74,7 @@ i0.f = f0;
f0.i = i0;
return f0.i.f.i.i;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 17;", code.print());
}
@@ -86,7 +86,7 @@ struct N { !N? !next; int i; };
N n = new N;
return n.next;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return null;", code.print());
}
@@ -99,7 +99,7 @@ struct N { !M !next; int i; };
N n = new N { next = new M; };
return n.next;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return (const)M;", code.print());
}
@@ -112,7 +112,7 @@ struct N { !M !next; int i; };
N n = new N { next = null; }
return n.next;
""");
- try { code.parse().opto(); fail(); }
+ try { code.parse().iter(); fail(); }
catch( Exception e ) { assertEquals("Type null is not of declared type *M",e.getMessage()); }
}
@@ -125,20 +125,20 @@ struct N { !N? !next; int i; };
n.i = 3.14;
return n.i;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("3",Eval2.eval(code,0));
}
@Test
public void testNullRef4() {
CodeGen code = new CodeGen("-null-5/null-5;");
- try { code.parse().opto().typeCheck(); fail(); }
+ try { code.parse().iter().typeCheck(); fail(); }
catch( Exception e ) { assertEquals("Cannot 'Add' null",e.getMessage()); }
}
@Test public void testNullRef5() {
CodeGen code = new CodeGen("return null+42;");
- try { code.parse().opto().typeCheck(); fail(); }
+ try { code.parse().iter().typeCheck(); fail(); }
catch( Exception e ) { assertEquals("Cannot 'Add' null",e.getMessage()); }
}
@@ -148,7 +148,7 @@ return n.i;
"""
struct S{};
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 0;", code.print());
assertEquals("0", Eval2.eval(code, 0));
}
@@ -160,7 +160,7 @@ struct S{};
struct S1 { !S2? !s; };
return new S2;
""");
- try { code.parse().opto(); fail(); }
+ try { code.parse().iter(); fail(); }
catch( Exception e ) { assertEquals("Unknown struct type 'S2'",e.getMessage()); }
}
@@ -172,7 +172,7 @@ struct S1 { !S2? !s; };
struct S2 { int x; };
return new S1.s=new S2;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return S2;", code.print());
}
@@ -189,7 +189,7 @@ p2.pi.i = 2;
if (arg) p1 = new P;
return p1.pi.i + 1;
""");
- try { code.parse().opto().typeCheck(); fail(); }
+ try { code.parse().iter().typeCheck(); fail(); }
catch( Exception e ) { assertEquals("Might be null accessing 'i'",e.getMessage()); }
}
@@ -254,7 +254,7 @@ z.a=k; z.b=s; z.c=e;
return a.b.c.a.b.c.a.b.c.a.b.c.a.b.c.a.b.c;
""");
- code.parse().opto().typeCheck().GCM().localSched();
+ code.driver(CodeGen.Phase.LocalSched);
assertEquals("return R;", code._stop.toString());
assertEquals("R{a=C{a=N{a=Y{a=J{a=U{a=F{a=Q{a=B{a=M{a=X{a=I{a=T{a=E{a=P{a=A{a=L{a=W{a=H{a=S{a=D{a=O{a=Z{a=K{a=V{a=G{a=$cyclic,b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic},b=$cyclic,c=$cyclic}", Eval2.eval(code, 0));
}
diff --git a/chapter18/src/test/java/com/seaofnodes/simple/Chapter13Test.java b/chapter18/src/test/java/com/seaofnodes/simple/Chapter13Test.java
index 584377e4..498796ea 100644
--- a/chapter18/src/test/java/com/seaofnodes/simple/Chapter13Test.java
+++ b/chapter18/src/test/java/com/seaofnodes/simple/Chapter13Test.java
@@ -290,7 +290,7 @@ else {
}
}
""");
- code.parse().opto().typeCheck().GCM();
+ code.driver(CodeGen.Phase.Schedule);
assertEquals("return Phi(Region,9,Top,Top,Top,Top);", code.print());
}
@@ -322,7 +322,7 @@ while( prime <= arg ) {
}
return primeCount;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Region,0,Phi(Loop,1,Phi(Region,Phi_primeCount,Phi(Region,(Phi_primeCount+1),Phi_primeCount))));", code.print());
assertEquals("0", Eval2.eval(code, 1)); // No primes 1 or below
assertEquals("1", Eval2.eval(code, 2)); // 2
@@ -344,7 +344,7 @@ i=v.f;
if (arg) v.f=1;
return i;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 2;", code.print());
assertEquals("2", Eval2.eval(code, 0));
assertEquals("2", Eval2.eval(code, 1));
@@ -367,7 +367,7 @@ if (arg) {
}
return i;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Region,.f,0);", code.print());
}
@@ -386,7 +386,7 @@ if (v1) {
}
return v0;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return S;", code.print());
}
@@ -404,7 +404,7 @@ if (arg+1) arg= 0;
while (arg) v.f = 2;
return i;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return arg;", code.print());
}
@@ -421,7 +421,7 @@ while(1) {
}
return v;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return S;", code.print());
}
@@ -436,7 +436,7 @@ while( -arg )
while(1)
arg = arg+ptr.v;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Top;", code.print());
}
@@ -454,7 +454,7 @@ while (arg) {
}
return i;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 0;", code.print());
}
@@ -474,7 +474,7 @@ while(arg) {
}
return arg;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 0;", code.print());
}
@@ -492,7 +492,7 @@ if (arg) {
}
return v;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return S;", code.print());
}
@@ -511,7 +511,7 @@ while (arg > 0) {
}
return v;
""");
- code.parse().opto();
+ code.parse().iter();
//assertEquals("return new S;", code.print());
}
@@ -528,7 +528,7 @@ while(0>=0) {
}
return 0;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Top;", code.print());
}
@@ -546,7 +546,7 @@ u32 v0=0;
return v1;
}
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 0;", code.print());
}
diff --git a/chapter18/src/test/java/com/seaofnodes/simple/Chapter14FloatTest.java b/chapter18/src/test/java/com/seaofnodes/simple/Chapter14FloatTest.java
index a40b4f04..473a06fa 100644
--- a/chapter18/src/test/java/com/seaofnodes/simple/Chapter14FloatTest.java
+++ b/chapter18/src/test/java/com/seaofnodes/simple/Chapter14FloatTest.java
@@ -20,7 +20,7 @@ public class Chapter14FloatTest {
{"f32 rounded=arg+16777216.0; return rounded;", "1.6777232E7", "1.6777199E7"}
};
for( String[] test : tests ) {
- var code = new CodeGen(test[0]).parse().opto().typeCheck();
+ var code = new CodeGen(test[0]).parse().iter().typeCheck();
assertEquals(test[0],test[1],Eval2.eval(code,17));
assertEquals(test[0],test[2],Eval2.eval(code,-17));
}
@@ -28,7 +28,7 @@ public class Chapter14FloatTest {
@Test public void testSubZeroFloat() {
- var code = new CodeGen("flt x = arg; return 0-x;").parse().opto().typeCheck();
+ var code = new CodeGen("flt x = arg; return 0-x;").parse().iter().typeCheck();
// Compare strings so +0.0 and -0.0 remain distinct.
assertEquals("0.0", Eval2.eval(code,0));
assertEquals("-1.0", Eval2.eval(code,1));
@@ -42,7 +42,7 @@ public class Chapter14FloatTest {
{"return 2.5; return 7;", "2.5"}
} ) {
String src = test[0];
- var code = new CodeGen(src).parse().opto().typeCheck();
+ var code = new CodeGen(src).parse().iter().typeCheck();
assertEquals(src,test[1],Eval2.eval(code,0));
}
}
@@ -55,7 +55,7 @@ public class Chapter14FloatTest {
"""
return 3.14;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 3.14;", code.print());
assertEquals("3.14", Eval2.eval(code, 0));
}
@@ -66,7 +66,7 @@ return 3.14;
"""
return 3.14;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 3.14;", code.print());
assertEquals("3.14", Eval2.eval(code, 0));
}
@@ -83,7 +83,7 @@ while( 1 ) {
}
return guess;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Loop,(flt)arg,(((ToFloat/Phi_guess)+Phi_guess)/2.0f));", code.print());
assertEquals("3.0", Eval2.eval(code, 9));
assertEquals("1.414213562373095", Eval2.eval(code, 2));
@@ -96,7 +96,7 @@ return guess;
flt x = arg;
return x+1==x;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return ((flt)arg==(ToFloat+1.0f));", code.print());
assertEquals("0", Eval2.eval(code, 1));
}
diff --git a/chapter18/src/test/java/com/seaofnodes/simple/Chapter14Test.java b/chapter18/src/test/java/com/seaofnodes/simple/Chapter14Test.java
index 789a2113..c00549e2 100644
--- a/chapter18/src/test/java/com/seaofnodes/simple/Chapter14Test.java
+++ b/chapter18/src/test/java/com/seaofnodes/simple/Chapter14Test.java
@@ -16,7 +16,7 @@ public class Chapter14Test {
"""
return 3.14;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 3.14;", code.print());
assertEquals("3.14", Eval2.eval(code, 0));
}
@@ -32,7 +32,7 @@ if( b < 0 ) c = -1;
if( b > 2 ) c = 1;
return c;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 99;", code.print());
assertEquals("99", Eval2.eval(code, 0));
}
@@ -45,7 +45,7 @@ u8 b = 123;
b = b + 456;// Truncate
return b;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 67;", code.print());
assertEquals("67", Eval2.eval(code, 0));
}
@@ -59,7 +59,7 @@ u8 b = 123;
while( b ) b = b + 456;// Truncate
return b;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 0;", code.print());
}
@@ -72,7 +72,7 @@ b = b + 456;// Truncate
u1 c = b; // No more truncate needed
return c;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 1;", code.print());
assertEquals("1", Eval2.eval(code, 0));
}
@@ -85,7 +85,7 @@ int b = 123;
b = b+456 & 31; // Precedence
return b;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 3;", code.print());
assertEquals("3", Eval2.eval(code, 0));
}
@@ -99,7 +99,7 @@ struct Foo { u1 b; };
f.b = 123;
return f.b;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 1;", code.print());
assertEquals("1", Eval2.eval(code, 0));
}
@@ -111,7 +111,7 @@ return f.b;
i8 b = 255; // Chopped
return b; // Sign extend
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return -1;", code.print());
assertEquals("-1", Eval2.eval(code, 0));
}
@@ -124,7 +124,7 @@ i8 b = arg;
b = b + 1;// Truncate
return b;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return (((((arg<<56)>>56)+1)<<56)>>56);", code.print());
assertEquals("1", Eval2.eval(code, 0));
assertEquals("-128", Eval2.eval(code, 127));
@@ -138,7 +138,7 @@ u16 mask = (1<<16)-1; // AND mask
int c = 123456789 & mask;
return c; //
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 52501;", code.print());
assertEquals("52501", Eval2.eval(code, 0));
}
@@ -149,7 +149,7 @@ return c; //
"""
return (arg | 123 ^ 456) >>> 1;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return (((arg|123)^456)>>>1);", code.print());
assertEquals("217", Eval2.eval(code, 0));
}
@@ -162,7 +162,7 @@ flt f = arg;
arg = f & 1;
return arg;
""");
- try { code.parse().opto().typeCheck(); fail(); }
+ try { code.parse().iter().typeCheck(); fail(); }
catch( Exception e ) { assertEquals("Cannot '&' flt",e.getMessage()); }
}
@@ -175,7 +175,7 @@ while(arg) v1=-v0;
while(v1) break;
return v1;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return (Phi(Loop,((1<<arg)&1),0)&Phi(Loop,Shl,4294967295));", code.print());
assertEquals("1", Eval2.eval(code, 0));
}
@@ -194,7 +194,7 @@ if(0&0>>>0) {
}
return v0;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 0;", code.print());
assertEquals("0", Eval2.eval(code, 0));
}
@@ -220,7 +220,7 @@ f32 ff32 = 3.141592653589793; if( ff32 != 3.1415927410125732) return 5;
return 0;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 0;", code.print());
assertEquals("0", Eval2.eval(code, 0));
}
diff --git a/chapter18/src/test/java/com/seaofnodes/simple/Chapter15Test.java b/chapter18/src/test/java/com/seaofnodes/simple/Chapter15Test.java
index 97f695bf..5b8e0fea 100644
--- a/chapter18/src/test/java/com/seaofnodes/simple/Chapter15Test.java
+++ b/chapter18/src/test/java/com/seaofnodes/simple/Chapter15Test.java
@@ -13,7 +13,7 @@ public class Chapter15Test {
"""
return 3.14;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 3.14;", code.print());
assertEquals("3.14", Eval2.eval(code, 0));
}
@@ -27,7 +27,7 @@ struct C { !C? !l; };
c.l = c;
return c;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return C;", code.print());
assertEquals("C{l=$cyclic}", Eval2.eval(code, 0));
}
@@ -46,7 +46,7 @@ while (i < old#) {
output[i] = 1;
return output;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return [u8];", code.print());
assertEquals("\u0001", Eval2.eval(code, 0));
}
@@ -58,7 +58,7 @@ return output;
int[] is = new int[2];
return is[1];
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 0;", code.print());
assertEquals("0", Eval2.eval(code, 0));
}
@@ -71,7 +71,7 @@ int[] is = new int[2];
int[] is2 = new int[2];
return is[1];
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 0;", code.print());
assertEquals("0", Eval2.eval(code, 0));
}
@@ -85,7 +85,7 @@ a[0] = 1;
a[1] = 2;
return a[0];
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 1;", code.print());
assertEquals("1", Eval2.eval(code, 0));
}
@@ -98,7 +98,7 @@ struct A { int i; };
!A?[] !a = new !A?[2];
return a;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return [*A?];", code.print());
assertEquals("*A {int !i; }?[ null,null]", Eval2.eval(code, 0));
}
@@ -127,7 +127,7 @@ else {
}
return rez;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Region,1.2,Phi(Region,2.3,.y));", code.print());
assertEquals("3.14", Eval2.eval(code, 0));
assertEquals("1.2", Eval2.eval(code, 1));
@@ -153,7 +153,7 @@ if( iss[arg] )
rez = iss[arg][2].y;
return rez;
""");
- try { code.parse().opto().typeCheck(); fail(); }
+ try { code.parse().iter().typeCheck(); fail(); }
catch( Exception e ) { assertEquals("Might be null accessing '[]'",e.getMessage()); }
}
@@ -168,7 +168,7 @@ root._kids = new !Tree?[2]; // NO BANG SO ARRAY IS OF IMMUTABLE TREES????
root._kids[0] = new Tree;
return root;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Tree;", code.print());
assertEquals("Tree{_kids=*Tree?[ Tree{_kids=null},null]}", Eval2.eval(code, 0));
}
@@ -180,7 +180,7 @@ return root;
struct S { int a; int[] !b; };
return 0;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 0;", code.print());
}
@@ -203,7 +203,7 @@ while( i < ary# - 1 ) {
}
return ary[1] * 1000 + ary[3]; // 1 * 1000 + 6
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return (.[]+(.[]*1000));", code.print());
assertEquals("1006", Eval2.eval(code, 4));
}
@@ -244,7 +244,7 @@ while( j < nprimes ) {
}
return rez;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return [int];", code.print());
assertEquals("int[ 2,3,5,7,11,13,17,19]",Eval2.eval(code, 20));
}
@@ -261,7 +261,7 @@ s2.f = 2.0;
if (arg) s1 = new S;
return s1.i + s1.f;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return ((flt).i+.f);", code.print());
assertEquals("0.0", Eval2.eval(code, 0));
}
@@ -273,7 +273,7 @@ return s1.i + s1.f;
"""
return new flt;
""");
- try { code.parse().opto(); fail(); }
+ try { code.parse().iter(); fail(); }
catch( Exception e ) { assertEquals("Cannot allocate a flt",e.getMessage()); }
}
@@ -283,7 +283,7 @@ return new flt;
"""
int is = new int[2];
""");
- try { code.parse().opto(); fail(); }
+ try { code.parse().iter(); fail(); }
catch( Exception e ) { assertEquals("Type *[int] is not of declared type int",e.getMessage()); }
}
@@ -294,7 +294,7 @@ int is = new int[2];
int[] is = new int[3.14];
return is[1];
""");
- try { code.parse().opto(); fail(); }
+ try { code.parse().iter(); fail(); }
catch( Exception e ) { assertEquals("Cannot allocate an array with length 3.14",e.getMessage()); }
}
@@ -305,7 +305,7 @@ return is[1];
int[] is = new int[arg];
return is[1];
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 0;", code.print());
assertEquals("0", Eval2.eval(code, 4));
try { Eval2.eval(code,0); }
@@ -335,7 +335,7 @@ while(v5+(0&0)) {
}
return v1;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 0;", code.print());
assertEquals("0", Eval2.eval(code, 0));
}
@@ -350,7 +350,7 @@ u32 v7=0;
int v8=0;
while(0<--1>>>---(v7*0==v8)) {}
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 0;", code.print());
}
@@ -374,7 +374,7 @@ else {
}
}
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 0;", code.print());
}
}
diff --git a/chapter18/src/test/java/com/seaofnodes/simple/Chapter16Test.java b/chapter18/src/test/java/com/seaofnodes/simple/Chapter16Test.java
index fd028d57..d2ef9357 100644
--- a/chapter18/src/test/java/com/seaofnodes/simple/Chapter16Test.java
+++ b/chapter18/src/test/java/com/seaofnodes/simple/Chapter16Test.java
@@ -16,7 +16,7 @@ public class Chapter16Test {
"""
return 3.14;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 3.14;", code.print());
assertEquals("3.14", Eval2.eval(code, 0));
}
@@ -29,7 +29,7 @@ return 3.14;
int x, y;
return x+y;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 0;", code.print());
assertEquals("0", Eval2.eval(code, 0));
}
@@ -40,7 +40,7 @@ return x+y;
int x=2, y=x+1;
return x+y;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 5;", code.print());
assertEquals("5", Eval2.eval(code, 0));
}
@@ -53,7 +53,7 @@ struct X { int x=3; };
X z = new X;
return z.x;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 3;", code.print());
assertEquals("3", Eval2.eval(code, 0));
}
@@ -65,7 +65,7 @@ struct X { int x=3; };
X z = new X { x = 4; };
return z.x;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 4;", code.print());
assertEquals("4", Eval2.eval(code, 0));
}
@@ -86,7 +86,7 @@ LLI? next = head.next;
if( !next ) return 1;
return next.i;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Region,0,1,.i);", code.print());
assertEquals("0", Eval2.eval(code, 0));
assertEquals("1", Eval2.eval(code, 1));
@@ -117,7 +117,7 @@ LLI? next = head.next;
if( !next ) return 1;
return next.i;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Region,0,1,.i);", code.print());
assertEquals("0", Eval2.eval(code, 0));
assertEquals("1", Eval2.eval(code, 1));
@@ -142,7 +142,7 @@ struct Square {
};
return new Square;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Square;", code.print());
assertEquals("Square{side=3.0,diag=1.7320508075688772}", Eval2.eval(code, 3));
assertEquals("Square{side=4.0,diag=2.0}", Eval2.eval(code, 4));
@@ -166,7 +166,7 @@ return new Square;
""";
@Test public void testConstructorMemory() {
- var code = new CodeGen(CONSTRUCTOR_MEMORY).parse().opto();
+ var code = new CodeGen(CONSTRUCTOR_MEMORY).parse().iter();
assertEquals("111249",Eval2.eval(code,0));
assertEquals("222352",Eval2.eval(code,1));
}
diff --git a/chapter18/src/test/java/com/seaofnodes/simple/Chapter17aTest.java b/chapter18/src/test/java/com/seaofnodes/simple/Chapter17aTest.java
index ab92d439..52f20ace 100644
--- a/chapter18/src/test/java/com/seaofnodes/simple/Chapter17aTest.java
+++ b/chapter18/src/test/java/com/seaofnodes/simple/Chapter17aTest.java
@@ -16,7 +16,7 @@ int x=2, y=3;
if( arg ) { int x = y; x = x*x; y=x; } // Shadow final x
return y;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Region,9,3);", code.print());
assertEquals("3", Eval2.eval(code, 0));
assertEquals("9", Eval2.eval(code, 1));
@@ -29,7 +29,7 @@ struct X { int ~x; };
X z = new X { x=3; };
return z.x;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 3;", code.print());
assertEquals("3", Eval2.eval(code, 0));
}
@@ -41,7 +41,7 @@ struct Point { int ~x, ~y; };
Point p = new Point { x=3; y=4; };
return p;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return (const)Point;", code.print());
assertEquals("Point{x=3,y=4}", Eval2.eval(code, 0));
}
@@ -54,7 +54,7 @@ Point p = new Point { x=5; y=6; };
p.x++;
return p;
""");
- try { code.parse().opto().typeCheck(); fail(); }
+ try { code.parse().iter().typeCheck(); fail(); }
catch( Exception e ) { assertEquals("Cannot modify final field 'x'",e.getMessage()); }
}
@@ -66,7 +66,7 @@ Point p = new Point;
p.x++;
return p;
""");
- try { code.parse().opto().typeCheck(); fail(); }
+ try { code.parse().iter().typeCheck(); fail(); }
catch( Exception e ) { assertEquals("Cannot modify final field 'x'",e.getMessage()); }
}
@@ -74,7 +74,7 @@ return p;
public void testStructFinal3() {
for( String fields : new String[] { "var x; var y;", "int[] !x;", "int[] !x;" } ) {
String src = "struct Point { "+fields+" }; Point p = new Point; p.x++; return p;";
- try { new CodeGen(src).parse().opto(); fail(fields); }
+ try { new CodeGen(src).parse().iter(); fail(fields); }
catch( Exception e ) { assertEquals("'Point' is not fully initialized, field 'x' needs to be set in a constructor",e.getMessage()); }
}
}
@@ -87,7 +87,7 @@ Point p = new Point;
p.x++;
return p;
""");
- try { code.parse().opto(); fail(); }
+ try { code.parse().iter(); fail(); }
catch( Exception e ) { assertEquals("Cannot reassign final 'x'",e.getMessage()); }
}
@@ -99,7 +99,7 @@ struct Point { var x=3; var y=4; };
p.x++;
return p;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Point;", code.print());
assertEquals("Point{x=4,y=4}", Eval2.eval(code, 0));
}
diff --git a/chapter18/src/test/java/com/seaofnodes/simple/Chapter17bTest.java b/chapter18/src/test/java/com/seaofnodes/simple/Chapter17bTest.java
index e83b43af..a5ce8f49 100644
--- a/chapter18/src/test/java/com/seaofnodes/simple/Chapter17bTest.java
+++ b/chapter18/src/test/java/com/seaofnodes/simple/Chapter17bTest.java
@@ -16,7 +16,7 @@ int i = 0;
i=i=1;
return i;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 1;", code.print());
assertEquals("1", Eval2.eval(code, 0));
}
@@ -28,7 +28,7 @@ return i;
CodeGen code = new CodeGen("""
return arg++;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return arg;", code.print());
assertEquals("0", Eval2.eval(code, 0));
}
@@ -38,7 +38,7 @@ return arg++;
CodeGen code = new CodeGen("""
return arg+++arg++;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return ((arg*2)+1);", code.print());
assertEquals("1", Eval2.eval(code, 0));
}
@@ -49,7 +49,7 @@ return arg+++arg++;
// -(arg--)-(arg--)
return -arg---arg--;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return (-((arg*2)+-1));", code.print());
assertEquals("1", Eval2.eval(code, 0));
}
@@ -62,7 +62,7 @@ xs[0]++;
xs[1]++;
return xs[0];
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 1;", code.print());
assertEquals("1", Eval2.eval(code, 2));
}
@@ -74,7 +74,7 @@ u8[] !xs = new u8[1];
xs[0]--;
return xs[0];
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 255;", code.print());
assertEquals("255", Eval2.eval(code, 2));
}
@@ -87,7 +87,7 @@ struct S { u16 x; };
s.x--;
return s.x;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 65535;", code.print());
assertEquals("65535", Eval2.eval(code, 2));
}
@@ -95,7 +95,7 @@ return s.x;
@Test
public void testInc6() {
CodeGen code = new CodeGen("return --arg;");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return (arg+-1);", code.print());
assertEquals("-1", Eval2.eval(code, 0));
}
@@ -103,7 +103,7 @@ return s.x;
@Test
public void testInc7() {
CodeGen code = new CodeGen("u8 x=0; return --x;");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 255;", code.print());
assertEquals("255", Eval2.eval(code, 0));
}
@@ -111,7 +111,7 @@ return s.x;
@Test
public void testInc8() {
CodeGen code = new CodeGen("int x; x+=2; return x+=3;");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 5;", code.print());
assertEquals("5", Eval2.eval(code, 0));
}
@@ -119,14 +119,14 @@ return s.x;
@Test
public void testInc9() {
CodeGen code = new CodeGen("flt x = 1.5; x++; return x;");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 2.5f;", code.print());
assertEquals("2.5", Eval2.eval(code, 0));
}
@Test public void testInt10() {
CodeGen code = new CodeGen("flt x = 1.5; x++; int i = x; return i;");
- code.parse().opto();
+ code.parse().iter();
assertEquals("2",Eval2.eval(code,0));
}
@@ -134,73 +134,73 @@ return s.x;
// ---------------------------------------------------------------
@Test public void testVar0() {
CodeGen code = new CodeGen("var d; return d;");
- try { code.parse().opto(); fail(); }
+ try { code.parse().iter(); fail(); }
catch( Exception e ) { assertEquals("Syntax error, expected =expression: ;",e.getMessage()); }
}
@Test public void testVar1() {
CodeGen code = new CodeGen("val d; return d;");
- try { code.parse().opto(); fail(); }
+ try { code.parse().iter(); fail(); }
catch( Exception e ) { assertEquals("Syntax error, expected =expression: ;",e.getMessage()); }
}
@Test public void testVar2() {
CodeGen code = new CodeGen("int x; x=3; x++; return x; // Ok, no initializer so x is mutable ");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 4;", code.print());
assertEquals("4", Eval2.eval(code, 0));
}
@Test public void testVar3() {
CodeGen code = new CodeGen("int x=3; x++; return x; // Ok, primitive so x is mutable despite initializer ");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 4;", code.print());
assertEquals("4", Eval2.eval(code, 0));
}
@Test public void testVar4() {
CodeGen code = new CodeGen("struct S{int x;}; !S? !s; s=new S; s.x++; return s.x; // Ok, no initializer so x is mutable ");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 1;", code.print());
assertEquals("1", Eval2.eval(code, 0));
}
@Test public void testVar5() {
CodeGen code = new CodeGen("struct S{int x;}; !S? !s; s=new S{x=3;}; s.x++; return s.x; // Ok, no initializer so x is mutable ");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 4;", code.print());
assertEquals("4", Eval2.eval(code, 0));
}
@Test public void testVar6() {
CodeGen code = new CodeGen("struct S{int x;}; S s=new S; s.x++; return s.x; // Error initializer so x is immutable ");
- try { code.parse().opto().typeCheck(); fail(); }
+ try { code.parse().iter().typeCheck(); fail(); }
catch( Exception e ) { assertEquals("Cannot modify final field 'x'",e.getMessage()); }
}
@Test public void testVar7() {
CodeGen code = new CodeGen("struct S{int x;}; S s=new S{x=3;}; s.x++; return s.x; // Error initializer so x is immutable ");
- try { code.parse().opto().typeCheck(); fail(); }
+ try { code.parse().iter().typeCheck(); fail(); }
catch( Exception e ) { assertEquals("Cannot modify final field 'x'",e.getMessage()); }
}
@Test public void testVar8() {
CodeGen code = new CodeGen("struct S{int x;}; !S !s=new S; s.x++; return s.x; // Ok, has '!' so s.x is mutable ");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 1;", code.print());
assertEquals("1", Eval2.eval(code, 0));
}
@Test public void testVar9() {
CodeGen code = new CodeGen("struct S{int x;}; var s=new S; s.x++; return s.x; // Ok, has var so s.x is mutable ");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 1;", code.print());
assertEquals("1", Eval2.eval(code, 0));
}
@Test public void testVar10() {
CodeGen code = new CodeGen("struct S{int x;}; ~S s=new S; s.x++; return s.x; // Error, has val so x is immutable ");
- try { code.parse().opto().typeCheck(); fail(); }
+ try { code.parse().iter().typeCheck(); fail(); }
catch( Exception e ) { assertEquals("Cannot modify final field 'x'",e.getMessage()); }
}
@@ -218,7 +218,7 @@ foo.bar.x++; // Ok foo and foo.bar and foo.bar.x are all mutable
~Foo xfoo = foo; // Throw away mutability
xfoo.bar.x++; // Error, cannot mutate through xfoo
""");
- try { code.parse().opto().typeCheck(); fail(); }
+ try { code.parse().iter().typeCheck(); fail(); }
catch( Exception e ) { assertEquals("Cannot modify final field 'x'",e.getMessage()); }
}
@@ -239,7 +239,7 @@ foo.bar.x++; // Bumps to 5
int x5 = xfoo.bar.x; // Ok to read through xfoo, gets 5
return x4*10+x5;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 45;", code.print());
assertEquals("45", Eval2.eval(code, 0));
}
@@ -249,7 +249,7 @@ return x4*10+x5;
CodeGen code = new CodeGen("""
int i,i++;
""");
- try { code.parse().opto().typeCheck(); fail(); }
+ try { code.parse().iter().typeCheck(); fail(); }
catch( Exception e ) { assertEquals("Redefining name 'i'",e.getMessage()); }
}
@@ -264,7 +264,7 @@ A x = new A {
b = new B;
};
""");
- try { code.parse().opto(); fail(); }
+ try { code.parse().iter(); fail(); }
catch( Exception e ) { assertEquals("Cannot read uninitialized field 'b'",e.getMessage()); }
}
@@ -277,7 +277,7 @@ return new A {
if (arg) b = new B; // Constructor ends with partial init of b
}.b;
""");
- try { code.parse().opto(); fail(); }
+ try { code.parse().iter(); fail(); }
catch( Exception e ) { assertEquals("'A' is not fully initialized, field 'b' needs to be set in a constructor",e.getMessage()); }
}
@@ -291,7 +291,7 @@ val s = new S{x = 2;};
return x;
"""
);
- try { code.parse().opto().typeCheck(); fail(); }
+ try { code.parse().iter().typeCheck(); fail(); }
catch( Exception e ) { assertEquals("Cannot reassign final 'x'",e.getMessage()); }
}
@@ -310,7 +310,7 @@ focus(me);
return me;
"""
);
- try { code.parse().opto().typeCheck(); fail(); }
+ try { code.parse().iter().typeCheck(); fail(); }
catch( Exception e ) { assertEquals("Syntax error, expected =expression: ;",e.getMessage()); }
}
@@ -320,7 +320,7 @@ return me;
CodeGen code = new CodeGen("""
return arg ? 1 : 2;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Region,1,2);", code.print());
assertEquals("2", Eval2.eval(code, 0));
assertEquals("1", Eval2.eval(code, 1));
@@ -331,7 +331,7 @@ return arg ? 1 : 2;
CodeGen code = new CodeGen("""
return arg ? 0 : arg;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 0;", code.print());
assertEquals("0", Eval2.eval(code, 0));
}
@@ -343,7 +343,7 @@ struct Bar { int x; };
var b = arg ? new Bar : null;
return b ? b.x++ + b.x++ : -1;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Region,((.x*2)+1),-1);", code.print());
assertEquals("-1", Eval2.eval(code, 0));
assertEquals("1", Eval2.eval(code, 1));
@@ -356,7 +356,7 @@ struct Bar { int x; };
var b = arg ? new Bar;
return b ? b.x++ + b.x++ : -1;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Region,((.x*2)+1),-1);", code.print());
assertEquals("-1", Eval2.eval(code, 0));
assertEquals("1", Eval2.eval(code, 1));
@@ -370,7 +370,7 @@ 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"
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Region,Phi(Region,.x,.x),0);", code.print());
assertEquals("0", Eval2.eval(code, 0));
assertEquals("1", Eval2.eval(code, 1));
@@ -383,7 +383,7 @@ return b ? b.next ? b.next.x : b.x; // parses "b ? (b.next ? b.next.x : b.x) : 0
flt f=arg?1:1.2;
return f; // missing widening
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Region,1.0f,1.2);", code.print());
assertEquals("1.2", Eval2.eval(code, 0));
}
@@ -395,7 +395,7 @@ return f; // missing widening
struct S{};
return arg ? 7 : new S;
""");
- try { code.parse().opto().typeCheck(); fail(); }
+ try { code.parse().iter().typeCheck(); fail(); }
catch( Exception e ) { assertEquals("No common type amongst int and reference",e.getMessage()); }
}
@@ -408,7 +408,7 @@ for( int i=0; i<arg; i++ )
sum += i;
return sum;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Loop,0,(Phi_sum+Phi(Loop,0,(Phi_i+1))));", code.print());
assertEquals("3", Eval2.eval(code, 3));
assertEquals("45", Eval2.eval(code, 10));
@@ -421,7 +421,7 @@ for( ; i<arg; i++ )
sum += i;
return sum;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Loop,0,(Phi_sum+Phi(Loop,0,(Phi_i+1))));", code.print());
assertEquals("3", Eval2.eval(code, 3));
assertEquals("45", Eval2.eval(code, 10));
@@ -436,7 +436,7 @@ for( int i=0; ; i++ ) {
}
return sum;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Loop,0,(Phi_sum+Phi(Loop,0,(Phi_i+1))));", code.print());
assertEquals("3", Eval2.eval(code, 3));
assertEquals("45", Eval2.eval(code, 10));
@@ -449,7 +449,7 @@ for( int i=0; i<arg; )
sum += i++;
return sum;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Loop,0,(Phi_sum+Phi(Loop,0,(Phi_i+1))));", code.print());
assertEquals("3", Eval2.eval(code, 3));
assertEquals("45", Eval2.eval(code, 10));
@@ -462,7 +462,7 @@ for( int i=0; i<arg; i++ )
sum += i;
return i;
""");
- try { code.parse().opto(); fail(); }
+ try { code.parse().iter(); fail(); }
catch( Exception e ) { assertEquals("Undefined name 'i'",e.getMessage()); }
}
@Test
@@ -470,7 +470,7 @@ return i;
CodeGen code = new CodeGen("""
for(;;arg++;) {}
""");
- try { code.parse().opto(); fail(); }
+ try { code.parse().iter(); fail(); }
catch( Exception e ) { assertEquals("Syntax error, expected Unexpected code after expression: ;",e.getMessage()); }
}
@@ -486,7 +486,7 @@ struct A{
};
return new A;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return A;", code.print());
assertEquals("A{f1=null,f2=null}", Eval2.eval(code,0));
}
@@ -500,7 +500,7 @@ struct A{
};
return new A.not_array_of_b;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return [*B?];", code.print());
assertEquals("*B?[]", Eval2.eval(code,0));
}
@@ -519,7 +519,7 @@ for( ; ptr; ptr = ptr.next )
sum += ptr.i;
return sum;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return Phi(Loop,0,(Phi_sum+.i));", code.print());
assertEquals("45", Eval2.eval(code, 10));
}
@@ -550,7 +550,7 @@ for( int j=0; j<nprimes; j++ )
rez[j] = primes[j];
return rez;
""");
- code.parse().opto().typeCheck().GCM();
+ code.driver(CodeGen.Phase.Schedule);
assertEquals("return [int];", code.print());
assertEquals("int[ 2,3,5,7,11,13,17,19]",Eval2.eval(code, 20));
}
diff --git a/chapter18/src/test/java/com/seaofnodes/simple/Chapter18Test.java b/chapter18/src/test/java/com/seaofnodes/simple/Chapter18Test.java
index 7f2b92ac..87e703b4 100644
--- a/chapter18/src/test/java/com/seaofnodes/simple/Chapter18Test.java
+++ b/chapter18/src/test/java/com/seaofnodes/simple/Chapter18Test.java
@@ -12,24 +12,24 @@ public class Chapter18Test {
@Test public void testFloatArrays() {
for( String type : new String[]{"flt","f64","f32"} ) {
CodeGen zero = new CodeGen("var a = new "+type+"[arg]; return a[arg-1];")
- .parse().opto().typeCheck();
+ .parse().iter().typeCheck();
assertEquals("0.0",Eval2.eval(zero,3));
new CodeGen(type+" x = arg; var a = new "+type+"[arg]; a[0] = x; return a[0];")
- .parse().opto().typeCheck();
+ .parse().iter().typeCheck();
CodeGen loop = new CodeGen("var a = new "+type+"[arg]; "+
"for(int i=0; i<arg; i++) a[i] += i+0.25; return a[0]+a[arg-1];")
- .parse().opto().typeCheck();
+ .parse().iter().typeCheck();
assertEquals("0.5",Eval2.eval(loop,1));
assertEquals("3.5",Eval2.eval(loop,4));
CodeGen rounded = new CodeGen("var a = new "+type+"[arg]; "+
"for(int i=0; i<arg; i++) a[i] = 16777216.0+i; return a[arg-1];")
- .parse().opto().typeCheck();
+ .parse().iter().typeCheck();
assertEquals(type.equals("f32") ? "1.6777216E7" : "1.6777217E7",Eval2.eval(rounded,2));
}
CodeGen rounded = new CodeGen("var a = new f32[arg]; "+
"for(int i=0; i<arg; i++) a[i] = 16777217.0; return a[arg-1];")
- .parse().opto().typeCheck();
+ .parse().iter().typeCheck();
assertEquals("1.6777216E7",Eval2.eval(rounded,2));
}
@@ -41,7 +41,7 @@ public class Chapter18Test {
"int x=0; while(arg) { if(arg==2) while(1) { x++; } x++; arg--; } return x;"
};
for( String src : sources ) {
- CodeGen code = new CodeGen(src).parse().opto().typeCheck();
+ CodeGen code = new CodeGen(src).parse().iter().typeCheck();
code._start.buildLoopTree(code._stop);
int[] nevers = {0};
code._stop.walk(n -> {
@@ -74,7 +74,7 @@ public class Chapter18Test {
"val g = { int x -> x ? g(x-1)/305420988+x*305420988 : 1; }; "+
"return f(arg)+g(arg);";
CodeGen code = new CodeGen(src);
- code.parse().opto().typeCheck();
+ code.parse().iter().typeCheck();
Node con = code._stop.walk(n -> n instanceof ConstantNode &&
n._type==TypeInteger.constant(305420988) ? n : null);
assertNotNull(con);
@@ -85,7 +85,7 @@ public class Chapter18Test {
for( Node use : uses )
for( int i=1; i<use.nIns(); i++ )
if( use.in(i)==con ) use.setDef(i,cast);
- code.GCM();
+ code.driver(CodeGen.Phase.Schedule);
var owners = new java.util.IdentityHashMap<CFGNode,Boolean>();
code._stop.walk(n -> {
if( !(n instanceof CastNode) || !(n.in(1) instanceof CastNode) ) return null;
@@ -122,7 +122,7 @@ public class Chapter18Test {
"No common type amongst int and reference"}
} ) {
try {
- new CodeGen(test[0]).parse().opto().typeCheck();
+ new CodeGen(test[0]).parse().iter().typeCheck();
fail("Expected incompatible return types: " + test[0]);
} catch( Parser.ParseException e ) {
assertEquals(test[1],e.getMessage());
@@ -153,7 +153,7 @@ public class Chapter18Test {
"""
return 0;
""");
- code.parse().opto().typeCheck().GCM().localSched();
+ code.driver(CodeGen.Phase.LocalSched);
assertEquals("return 0;", code._stop.toString());
assertEquals("0", Eval2.eval(code, 2));
}
@@ -171,7 +171,7 @@ while(arg--) {
}
return a;
""");
- code.parse().opto().typeCheck().GCM();
+ code.driver(CodeGen.Phase.Schedule);
assertEquals("return Phi(Loop,1,Phi(Loop,2,Phi_a));", code._stop.toString());
assertEquals("1", Eval2.eval(code, 0));
assertEquals("2", Eval2.eval(code, 1));
@@ -188,7 +188,7 @@ return a;
{int -> int}? x2 = null; // null function ptr
return x2;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return null;", code._stop.toString());
assertEquals("null", Eval2.eval(code, 0 ) );
}
@@ -202,7 +202,7 @@ return x2;
};
return sq;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("Stop[ return { sq}; return (Parm_x(sq,int)*x); ]", code._stop.toString());
assertEquals("{ sq}", Eval2.eval(code, 3));
}
@@ -216,7 +216,7 @@ var sq = { int x ->
};
return sq(arg)+sq(3);
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("Stop[ return (sq( 3)+sq( arg)); return (Parm_x(sq,int,3,arg)*x); ]", code._stop.toString());
assertEquals("13", Eval2.eval(code, 2));
}
@@ -229,7 +229,7 @@ return sq(arg)+sq(3);
int cnt=1;
return { -> cnt; };
""");
- try { code.parse().opto(); fail(); }
+ try { code.parse().iter(); fail(); }
catch( Exception e ) { assertEquals("Variable 'cnt' is out of function scope and must be a final constant",e.getMessage()); }
}
@@ -241,7 +241,7 @@ return { -> cnt; };
val cnt=2;
return { -> cnt; }();
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("return 2;", code._stop.toString());
assertEquals("2", Eval2.eval(code, 0));
}
@@ -254,7 +254,7 @@ return { -> cnt; }();
var fcn = arg ? { int x -> x*x; } : { int x -> x+x; };
return fcn(3);
""");
- code.parse().opto();
+ code.parse().iter();
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));
@@ -264,7 +264,7 @@ return fcn(3);
@Test
public void testFcn5() {
CodeGen code = new CodeGen("val fact = { int x -> x <= 1 ? 1 : x*fact(x-1); }; return fact(arg);");
- code.parse().opto();
+ code.parse().iter();
assertEquals("Stop[ return fact( arg); return Phi(Region,1,(Parm_x(fact,int,arg,(x-1))*fact( Sub))); ]", code._stop.toString());
assertEquals( "1", Eval2.eval(code, 0));
assertEquals( "1", Eval2.eval(code, 1));
@@ -281,7 +281,7 @@ struct S { int i; };
val newS = { int x -> return new S { i=x; }; };
return newS(1).i;
""");
- code.parse().opto().typeCheck().GCM();
+ code.driver(CodeGen.Phase.Schedule);
assertEquals("return 1;", code._stop.toString());
assertEquals("1", Eval2.eval(code, 0));
}
@@ -296,7 +296,7 @@ val f = {->1;};
val g = {->2;};
return 2;
""");
- code.parse().opto().typeCheck().GCM();
+ code.driver(CodeGen.Phase.Schedule);
assertEquals("Stop[ return 1; return 1; return 2; ]", code._stop.toString());
assertEquals("1", Eval2.eval(code, 0));
}
@@ -314,7 +314,7 @@ for(;;) {
i2i = id(x);
}
""");
- code.parse().opto().typeCheck().GCM().localSched();
+ code.driver(CodeGen.Phase.LocalSched);
assertEquals("Stop[ return x( Phi(Loop,arg,x( 3))); return Parm_i(x,int,3,Phi_arg); ]", code._stop.toString());
assertEquals("3", Eval2.eval(code, 0));
}
@@ -331,7 +331,7 @@ for(;;) {
arg = x(3);
}
""");
- code.parse().opto().typeCheck().GCM().localSched();
+ code.driver(CodeGen.Phase.LocalSched);
assertEquals("return Top;", code._stop.toString());
assertEquals(null, Eval2.eval(code, 0));
}
@@ -350,7 +350,7 @@ for(;;) {
}
return 1;
""");
- try { code.parse().opto(); fail(); }
+ try { code.parse().iter(); fail(); }
catch( Exception e ) { assertEquals("No active loop for a break or continue",e.getMessage()); }
}
@@ -365,7 +365,7 @@ for(;;) {
i2i = null;
}
""");
- try { code.parse().opto().typeCheck(); fail(); }
+ try { code.parse().iter().typeCheck(); fail(); }
catch( Exception e ) { assertEquals("Might be null calling { int -> int #1}?",e.getMessage()); }
}
@@ -377,7 +377,7 @@ for(;;) {
val f = { int i, int j -> return i+j; };
return f();
""");
- try { code.parse().opto().typeCheck(); fail(); }
+ try { code.parse().iter().typeCheck(); fail(); }
catch( Exception e ) { assertEquals("Expecting 2 arguments, but found 0",e.getMessage()); }
}
@@ -395,7 +395,7 @@ for(;;) {
if (s) return s.x;
}
""");
- try { code.parse().opto().typeCheck(); fail(); }
+ try { code.parse().iter().typeCheck(); fail(); }
catch( Exception e ) { assertEquals("Accessing unknown field 'x' from '*S'",e.getMessage()); }
}
@@ -408,7 +408,7 @@ val g = { ->
};
return 0;
""");
- try { code.parse().opto().typeCheck(); fail(); }
+ try { code.parse().iter().typeCheck(); fail(); }
catch( Exception e ) { assertEquals("No defined return type",e.getMessage()); }
}
@@ -422,7 +422,7 @@ val is_even = { int x -> x ? is_odd (x-1) : true ; };
val is_odd = { int x -> x ? is_even(x-1) : false; };
return is_even(arg);
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("Stop[ return is_even( arg); return Phi(Region,Phi(Region,is_even( ((Parm_x(is_even,int,arg,Sub)-1)-1)),0),1); ]", code._stop.toString());
assertEquals("1", Eval2.eval(code, 0));
assertEquals("0", Eval2.eval(code, 1));
@@ -444,7 +444,7 @@ for(;;) {
if (s) return s.f;
}
""");
- code.parse().opto().typeCheck().GCM();
+ code.driver(CodeGen.Phase.Schedule);
assertEquals("return 0;", code._stop.toString());
assertEquals("0", Eval2.eval(code, 0));
}
@@ -461,7 +461,7 @@ if (arg) i2i = null;
if (i2i) return i2i(arg);
return f2f(o)(1);
""");
- code.parse().opto().typeCheck().GCM().localSched();
+ code.driver(CodeGen.Phase.LocalSched);
assertEquals("Stop[ return Phi(Region,o( arg),o( 1)); return Parm_i(o,int,arg,1); ]", code._stop.toString());
assertEquals("1", Eval2.eval(code, 2));
}
@@ -477,7 +477,7 @@ struct Person {
p.coffee_count += 1;
return p.coffee_count;
""");
- code.parse().opto().typeCheck().GCM().localSched();
+ code.driver(CodeGen.Phase.LocalSched);
assertEquals("return 1;", code._stop.toString());
assertEquals("1", Eval2.eval(code, 2));
}
@@ -496,7 +496,7 @@ return p.coffee_count;
""";
@Test public void testCallMemory() {
- var code = new CodeGen(CALL_MEMORY).parse().opto();
+ var code = new CodeGen(CALL_MEMORY).parse().iter();
int[] calls={0};
code._stop.walk(n -> { if(n instanceof CallNode) calls[0]++; return null; });
assertEquals(2,calls[0]); // Keep real calls so this checks scheduling across them.
@@ -525,7 +525,7 @@ return p.coffee_count;
""";
@Test public void testRecursiveMemory() {
- var code = new CodeGen(RECURSIVE_MEMORY).parse().opto();
+ var code = new CodeGen(RECURSIVE_MEMORY).parse().iter();
for(int n=0; n<7; n++)
assertEquals(Long.toString((10L*(n+1)+n*(n+1)/2)*100+10+n),Eval2.eval(code,n));
}
@@ -543,7 +543,7 @@ return p.coffee_count;
""";
@Test public void testInlineAllocationMemory() {
- var code = new CodeGen(INLINE_MEMORY).parse().opto();
+ var code = new CodeGen(INLINE_MEMORY).parse().iter();
assertNull(code._stop.walk(n -> n instanceof CallNode ? n : null));
assertEquals("400944",Eval2.eval(code,0));
assertEquals("420946",Eval2.eval(code,2));
diff --git a/chapter18/src/test/java/com/seaofnodes/simple/CompoundAssignmentTest.java b/chapter18/src/test/java/com/seaofnodes/simple/CompoundAssignmentTest.java
index 860827d7..2c1a138d 100644
--- a/chapter18/src/test/java/com/seaofnodes/simple/CompoundAssignmentTest.java
+++ b/chapter18/src/test/java/com/seaofnodes/simple/CompoundAssignmentTest.java
@@ -88,7 +88,7 @@ public class CompoundAssignmentTest {
}
private static void check(String src, long arg, long expected) {
- var code = new CodeGen(src).parse().opto().typeCheck();
+ var code = new CodeGen(src).parse().iter().typeCheck();
assertEquals(src, Long.toString(expected), Eval2.eval(code, arg));
}
}
diff --git a/chapter18/src/test/java/com/seaofnodes/simple/Eval2.java b/chapter18/src/test/java/com/seaofnodes/simple/Eval2.java
index 3f337e86..e62b63a6 100644
--- a/chapter18/src/test/java/com/seaofnodes/simple/Eval2.java
+++ b/chapter18/src/test/java/com/seaofnodes/simple/Eval2.java
@@ -114,9 +114,7 @@ public abstract class Eval2 {
public static String eval( CodeGen code, long arg, int timeout ) {
SB trace = null; // new SB(); // TRACE, set to null for off, new SB() for on
// Force local scheduling phase
- if( code._phase.ordinal() < CodeGen.Phase.TypeCheck .ordinal() ) code.typeCheck();
- if( code._phase.ordinal() < CodeGen.Phase.Schedule .ordinal() ) code.GCM();
- if( code._phase.ordinal() < CodeGen.Phase.LocalSched.ordinal() ) code.localSched();
+ code.driver(CodeGen.Phase.LocalSched);
// Set global, so don't have to pass everywhere
CODE = code;
diff --git a/chapter18/src/test/java/com/seaofnodes/simple/MergeSortTest.java b/chapter18/src/test/java/com/seaofnodes/simple/MergeSortTest.java
index a352530f..08b50d2c 100644
--- a/chapter18/src/test/java/com/seaofnodes/simple/MergeSortTest.java
+++ b/chapter18/src/test/java/com/seaofnodes/simple/MergeSortTest.java
@@ -57,7 +57,7 @@ merge_sort(a, b, a#);
return a;
""");
- code.parse().opto();
+ code.parse().iter();
assertEquals("Stop[ return [int]; return 0; ]", code._stop.toString());
assertEquals("int[ 1,2,3,4,5,6,7,8,9,10,11]", Eval2.eval(code, 11));
}
diff --git a/chapter18/src/test/java/com/seaofnodes/simple/MutabilityTest.java b/chapter18/src/test/java/com/seaofnodes/simple/MutabilityTest.java
index 0861424f..79d68843 100644
--- a/chapter18/src/test/java/com/seaofnodes/simple/MutabilityTest.java
+++ b/chapter18/src/test/java/com/seaofnodes/simple/MutabilityTest.java
@@ -5,12 +5,12 @@ import static org.junit.Assert.*;
public class MutabilityTest {
private static void ok(String src, String result) {
- var code = new CodeGen(src).parse().opto().typeCheck();
+ var code = new CodeGen(src).parse().iter().typeCheck();
assertEquals(result,Eval2.eval(code,0));
}
private static void bad(String src) {
try {
- new CodeGen(src).parse().opto().typeCheck();
+ new CodeGen(src).parse().iter().typeCheck();
} catch( RuntimeException expected ) {
String msg = expected.getMessage();
assertTrue("Expected a permission error, got: "+expected,
diff --git a/chapter18/src/test/java/com/seaofnodes/simple/PhaseTest.java b/chapter18/src/test/java/com/seaofnodes/simple/PhaseTest.java
new file mode 100644
index 00000000..d0cb173a
--- /dev/null
+++ b/chapter18/src/test/java/com/seaofnodes/simple/PhaseTest.java
@@ -0,0 +1,33 @@
+package com.seaofnodes.simple;
+
+import com.seaofnodes.graph.GraphObserver;
+import com.seaofnodes.simple.CodeGen;
+import com.seaofnodes.simple.CodeGen.Phase;
+import com.seaofnodes.simple.node.Node;
+import java.util.ArrayList;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+public class PhaseTest {
+ private static final String SRC = "int sum=0; for(int i=0; i<arg; i++) sum+=i; return sum;";
+
+ @Test public void testStopAndResume() {
+ ArrayList<String> phases = new ArrayList<>();
+ CodeGen code = new CodeGen(SRC);
+ code._obs = new GraphObserver<Node>() {
+ @Override public void before(Node n) {}
+ @Override public void after(Node n, Node repl, boolean applied) {}
+ @Override public void phase(String phase) { phases.add(phase); }
+ };
+ code.driver(Phase.Iter);
+ assertEquals(Phase.Iter,code._phase);
+ assertEquals("Parse Iter",String.join(" ",phases));
+ code.driver(Phase.TypeCheck);
+ code.driver(Phase.TypeCheck); // Repeated requests do not rerun phases.
+ code.driver(Phase.LoopTree);
+ assertEquals(Phase.LoopTree,code._phase);
+ code.driver(Phase.LocalSched);
+ assertEquals("Parse Iter TypeCheck LoopTree Schedule LocalSched",String.join(" ",phases));
+ assertEquals("45",Eval2.eval(code,10));
+ }
+}
diff --git a/chapter18/src/test/java/com/seaofnodes/simple/SchedulerTest.java b/chapter18/src/test/java/com/seaofnodes/simple/SchedulerTest.java
index d29166a7..95c062b5 100644
--- a/chapter18/src/test/java/com/seaofnodes/simple/SchedulerTest.java
+++ b/chapter18/src/test/java/com/seaofnodes/simple/SchedulerTest.java
@@ -10,6 +10,26 @@ import static org.junit.Assert.assertEquals;
public class SchedulerTest {
+ @Test public void testMemoryPhiAcrossSiblingBranch() {
+ // The inner memory Phi defines the load's memory. The outer Phi's
+ // other input comes from a branch not dominated by that definition.
+ String src = """
+ struct S { int x; }; !S !a=new S; !S !b=new S;
+ a.x=10; b.x=20; !S !p=a; if(arg>3) p=b;
+ int result=0;
+ if(arg>0) {
+ if(arg>2) p.x=30; else p.x=40;
+ result=a.x;
+ }
+ return result;
+ """;
+ var code = new CodeGen(src).driver(CodeGen.Phase.LocalSched);
+ long[] expected = {0,40,40,30,10,10};
+ for( int arg=0; arg<expected.length; arg++ )
+ assertEquals(Long.toString(expected[arg]),Eval2.eval(code,arg));
+ }
+
+
private static void assertObj(Object obj, String name, Object... fields) {
assertEquals(Evaluator.Obj.class, obj.getClass());
var o = (Evaluator.Obj)obj;
@@ -30,7 +50,7 @@ int i=v.f;
if (arg) v.f=1;
return i;
""");
- code.parse();//.opto();
+ code.parse();//.iter();
var eval = new Evaluator(code._stop);
assertEquals(2L, eval.evaluate(1, 10));
}
@@ -45,7 +65,7 @@ struct S {
if(arg) v0.f=1;
return v0;
""");
- code.parse().opto();
+ code.parse().iter();
var eval = new Evaluator(code._stop);
assertObj(eval.evaluate(0, 10), "S", 0L);
assertObj(eval.evaluate(1, 10), "S", 1L);
@@ -64,7 +84,7 @@ i=v.f;
if (arg) v.f=1;
return i;
""");
- code.parse().opto();
+ code.parse().iter();
var eval = new Evaluator(code._stop);
assertEquals(2L, eval.evaluate(0, 10));
assertEquals(2L, eval.evaluate(1, 10));
diff --git a/chapter18/src/test/java/com/seaofnodes/simple/fuzzer/Fuzzer.java b/chapter18/src/test/java/com/seaofnodes/simple/fuzzer/Fuzzer.java
index a5634e82..31274b58 100644
--- a/chapter18/src/test/java/com/seaofnodes/simple/fuzzer/Fuzzer.java
+++ b/chapter18/src/test/java/com/seaofnodes/simple/fuzzer/Fuzzer.java
@@ -134,7 +134,7 @@ public class Fuzzer {
double parse_peeps_per_node = (double)parse_peeps/nids;
- code.opto();
+ code.iter();
int iter_peeps= Node.ITER_CNT;
int iter_nops = Node.ITER_NOP_CNT;
double iter_nop_ratio = (double)iter_nops/iter_peeps;
diff --git a/chapter18/src/test/java/com/seaofnodes/simple/fuzzer/FuzzerUtils.java b/chapter18/src/test/java/com/seaofnodes/simple/fuzzer/FuzzerUtils.java
index 4509c6fc..254f9653 100644
--- a/chapter18/src/test/java/com/seaofnodes/simple/fuzzer/FuzzerUtils.java
+++ b/chapter18/src/test/java/com/seaofnodes/simple/fuzzer/FuzzerUtils.java
@@ -130,7 +130,7 @@ class FuzzerUtils {
var code = new CodeGen(script);
code.parse();
WorkRandom.setSeed(workListSeed);
- return code.opto().typeCheck().GCM().localSched();
+ return code.iter().driver(CodeGen.Phase.Schedule).localSched();
} finally {
NodeWalkVisit.clear();
System.setErr(err);