summaryrefslogtreecommitdiff
path: root/src/test/java/com/seaofnodes/simple
diff options
context:
space:
mode:
authorCliff Click <cliffc@acm.org>2025-06-13 15:42:08 -0700
committerCliff Click <cliffc@acm.org>2026-10-24 15:56:44 -0700
commitb59f51486393b2fae7b0015bc5099c5514c7335a (patch)
tree709c7ee19d0fb2467ecb353960f74722f3fd916d /src/test/java/com/seaofnodes/simple
parent89dd0a79da85b2c7102b7c8918a1466e6238fe94 (diff)
downloadSimple-b59f51486393b2fae7b0015bc5099c5514c7335a.tar.gz
Simple-b59f51486393b2fae7b0015bc5099c5514c7335a.zip
Chapter 24b: SCCP Across Functionslinear-chapter24b
Co-authored-by: Tamás Hadházy <85063808+Hels15@users.noreply.github.com> Co-authored-by: Hsiang-Ying Fu <66062782+fuhsnn@users.noreply.github.com> Co-authored-by: fuhsnn <66062782+fuhsnn@users.noreply.github.com> Co-authored-by: Symious <14933944+symious@users.noreply.github.com> Co-authored-by: Jun Kawasaki <jun784@gmail.com> Co-authored-by: Hadházy Tamás <helsgithub15@gmail.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Diffstat (limited to 'src/test/java/com/seaofnodes/simple')
-rw-r--r--src/test/java/com/seaofnodes/simple/Chapter18Test.java10
-rw-r--r--src/test/java/com/seaofnodes/simple/Chapter24Test.java14
-rw-r--r--src/test/java/com/seaofnodes/simple/SccpTest.java18
3 files changed, 25 insertions, 17 deletions
diff --git a/src/test/java/com/seaofnodes/simple/Chapter18Test.java b/src/test/java/com/seaofnodes/simple/Chapter18Test.java
index e5dd259b..b6a0ab57 100644
--- a/src/test/java/com/seaofnodes/simple/Chapter18Test.java
+++ b/src/test/java/com/seaofnodes/simple/Chapter18Test.java
@@ -406,8 +406,7 @@ return g();
}
- // Local SCCP cannot infer this recursive return type. The next chapter
- // solves across calls and checks the same program's execution results.
+ // Mutual recursion: check results, independent of how much gets inlined.
@Test
public void testFcnMutRec() {
CodeGen code = new CodeGen(
@@ -416,8 +415,11 @@ 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);
""");
- try { code.driver(CodeGen.Phase.TypeCheck); fail(); }
- catch( Parser.ParseException e ) { assertEquals("No defined return type",e.getMessage()); }
+ code.driver(CodeGen.Phase.FinalizeIR);
+ assertEquals("1", Eval2.eval(code, 0));
+ assertEquals("0", Eval2.eval(code, 1));
+ assertEquals("1", Eval2.eval(code, 2));
+ assertEquals("0", Eval2.eval(code, 3));
}
// Forward ref to 'x' means that
diff --git a/src/test/java/com/seaofnodes/simple/Chapter24Test.java b/src/test/java/com/seaofnodes/simple/Chapter24Test.java
index 4eb1324d..6e0fd95f 100644
--- a/src/test/java/com/seaofnodes/simple/Chapter24Test.java
+++ b/src/test/java/com/seaofnodes/simple/Chapter24Test.java
@@ -17,6 +17,20 @@ import org.junit.Test;
import static org.junit.Assert.*;
public class Chapter24Test {
+ @Test public void testRecursiveWidening() {
+ String[] srcs = {
+ // Parm(x) must widen even though the recursive result is constant.
+ "val f = { int x, int limit -> x >= limit ? 0 : f(x+1,limit); }; return f(0,arg);",
+ // The growing result has its own cycle, which never crosses Parm(x).
+ "val f = { int x -> x <= 0 ? 0 : f(x-1)+1; }; return f(3);"
+ };
+ for( int i=0; i<srcs.length; i++ )
+ for( long seed : new long[]{0,42,126} ) {
+ var code = new CodeGen(srcs[i],TypeInteger.BOT,seed,true).driver(CodeGen.Phase.LocalSched);
+ assertEquals(i==0 ? "0" : "3",Eval2.eval(code,3));
+ }
+ }
+
@Test public void testColdLoopSelfConflict() { com.seaofnodes.simple.codegen.RegAllocTestSupport.coldLoopSelfConflict(); }
@Test public void testPrintingDeadFunction() throws Exception {
diff --git a/src/test/java/com/seaofnodes/simple/SccpTest.java b/src/test/java/com/seaofnodes/simple/SccpTest.java
index afa0ec58..cad1b7de 100644
--- a/src/test/java/com/seaofnodes/simple/SccpTest.java
+++ b/src/test/java/com/seaofnodes/simple/SccpTest.java
@@ -7,25 +7,17 @@ import org.junit.Test;
import static org.junit.Assert.*;
public class SccpTest {
- @Test public void testLoopFixedPoint() {
- var code = new CodeGen("int x=1; while(arg) { x=2-x; arg--; } return x;").parse().iter();
- assertFalse(code.link(code._main).ret().expr()._type.isConstant());
- code.opto();
- assertSame(TypeInteger.TRUE,code.link(code._main).ret().expr()._type);
- code.driver(CodeGen.Phase.LocalSched);
- assertEquals("1",Eval2.eval(code,4));
- }
-
- @Test public void testConservativeCalls() {
+ @Test public void testCallArgumentFlow() {
var code = new CodeGen("val f={ int x -> x+1; }; return f(1)+f(2);").parse().iter().opto();
int[] parms = {0};
code._start.walk(n -> {
if( n instanceof ParmNode p && "x".equals(p._label) ) {
parms[0]++;
- assertSame(TypeInteger.BOT,p._type);
- assertTrue(p.fun().in(1) instanceof StartNode);
+ TypeInteger t = (TypeInteger)p._type;
+ assertEquals(1,t._min);
+ assertEquals(2,t._max);
+ assertFalse(p.fun().in(1) instanceof StartNode);
}
- if( n instanceof CallEndNode cend ) assertEquals(1,cend.nIns());
return null;
});
assertEquals(1,parms[0]);