From c4dcf6f751b35c7a2a3b46fa2d69b95d37d082a6 Mon Sep 17 00:00:00 2001 From: Cliff Click Date: Wed, 30 Sep 2026 19:25:04 -0700 Subject: Finish forward-port mem ops thru ch25 --- .../java/com/seaofnodes/simple/Chapter11Test.java | 2 + .../java/com/seaofnodes/simple/Chapter20Test.java | 2 +- .../java/com/seaofnodes/simple/Chapter21Test.java | 4 +- .../test/java/com/seaofnodes/simple/EvalArm64.java | 7 +- .../com/seaofnodes/simple/MemoryEncodingTest.java | 104 +++++++++++++++++++++ 5 files changed, 114 insertions(+), 5 deletions(-) create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/MemoryEncodingTest.java (limited to 'chapter25/src/test') diff --git a/chapter25/src/test/java/com/seaofnodes/simple/Chapter11Test.java b/chapter25/src/test/java/com/seaofnodes/simple/Chapter11Test.java index 2e661901..d515df8d 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/Chapter11Test.java +++ b/chapter25/src/test/java/com/seaofnodes/simple/Chapter11Test.java @@ -152,6 +152,8 @@ return v.f; """); code.parse().opto(); assertEquals("return Phi(Loop,0,2);", code.print()); + for( int arg : new int[]{-1,0,1,3,100} ) + assertEquals("0",Eval2.eval(code,arg)); } @Test diff --git a/chapter25/src/test/java/com/seaofnodes/simple/Chapter20Test.java b/chapter25/src/test/java/com/seaofnodes/simple/Chapter20Test.java index ce604cf1..e39c09e7 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/Chapter20Test.java +++ b/chapter25/src/test/java/com/seaofnodes/simple/Chapter20Test.java @@ -183,7 +183,7 @@ for( int i=0; i // Evaluate on ARM5 emulator; expect return of an array of primes in // the simulated heap. - EvalArm64 A5 = TestArm64.build("sieve", src, 100, 105, false); + EvalArm64 A5 = TestArm64.build("sieve", src, 100, 88, false); int trap_arm = A5.step(10000); assertEquals(0, trap_arm); int ary_arm = (int)A5.regs[arm.X0]; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/EvalArm64.java b/chapter25/src/test/java/com/seaofnodes/simple/EvalArm64.java index 86fcf96f..1503adb5 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/EvalArm64.java +++ b/chapter25/src/test/java/com/seaofnodes/simple/EvalArm64.java @@ -544,10 +544,13 @@ public class EvalArm64 { break; } - case 0xD2: { + case 0xD2: // MOVZ + case 0xF2: { // MOVK preserves the other halfwords // movz // get immediate - rval = (ir >> 5) & 0x7FFF; + int shift = ((ir >> 21) & 3)*16; + rval = ((ir >> 5) & 0xFFFFL) << shift; + if( opcode1==0xF2 ) rval |= regs[rdid] & ~(0xFFFFL << shift); break; } diff --git a/chapter25/src/test/java/com/seaofnodes/simple/MemoryEncodingTest.java b/chapter25/src/test/java/com/seaofnodes/simple/MemoryEncodingTest.java new file mode 100644 index 00000000..2786b403 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/MemoryEncodingTest.java @@ -0,0 +1,104 @@ +package com.seaofnodes.simple; + +import com.seaofnodes.simple.codegen.CodeGen; +import com.seaofnodes.simple.node.*; +import java.util.BitSet; +import org.junit.Test; +import static org.junit.Assert.*; + +// Execution regressions are separate from the fixed spill-measurement cohorts. +public class MemoryEncodingTest { + @Test public void testLoopLoadSearch() { + String[] sources = { + """ + u8[] !program=new u8[106]; u8[] !out=new u8[0]; + int sum=0; + for(int i=0; i + n instanceof LoadNode ld && ld.ptr() instanceof ProjNode ptr && + ptr.in(0) instanceof NewNode nn && + nn.size()._type==com.seaofnodes.simple.type.TypeInteger.constant(110) ? ld : null)); + for( int arg=0; arg<7; arg++ ) { + long expected=switch(p) { + case 0 -> 106*arg+(arg>=2 ? 2 : 0); + case 1 -> (arg&1)==0 ? 140 : 60; + case 2 -> 130; + default -> 16; + }; + assertEquals(Long.toString(expected),Eval2.eval(code,arg)); + } + } + } + + @Test public void testKeepReadsBeforeWrites() { + var code = new CodeGen(""" + struct S { int x; int y; }; + S !a = new S; S !b = new S; + a.x=arg; b.x=arg+1; + S !p=a; S !q=b; + if (arg<0) { p=b; q=a; } + int v; + if (arg>1) { v=p.x; p.x=41; p.y=5; } + else { v=q.x; q.x=42; } + return v; + """).parse().opto(); + StopNode stop = code._stop; + assertEquals(2,countMemoryNodes(stop,LoadNode.class,new BitSet())); + assertEquals("-1",Eval2.eval(code,-1)); + assertEquals("1",Eval2.eval(code,0)); + assertEquals("3",Eval2.eval(code,3)); + } + + private static int countMemoryNodes(Node n, Class kind, BitSet seen) { + if (n==null || seen.get(n._nid)) return 0; + seen.set(n._nid); + int cnt=kind.isInstance(n) ? 1 : 0; + for (Node def : n._inputs) cnt+=countMemoryNodes(def,kind,seen); + return cnt; + } +} -- cgit v1.2.3