From 40b33cb6f8b8dc4d8551c3b522e7c5682a44540a Mon Sep 17 00:00:00 2001 From: Cliff Click Date: Sun, 20 Sep 2026 22:38:58 -0700 Subject: Final reg-alloc across chapters cleanup --- .../java/com/seaofnodes/simple/Chapter20Test.java | 17 ++++++++++++ .../java/com/seaofnodes/simple/Chapter21Test.java | 32 ++++++++++++++++++++++ .../test/java/com/seaofnodes/simple/EvalArm64.java | 14 +++++----- .../simple/codegen/RegAllocTestSupport.java | 13 +++++++++ 4 files changed, 69 insertions(+), 7 deletions(-) (limited to 'chapter22/src/test/java') diff --git a/chapter22/src/test/java/com/seaofnodes/simple/Chapter20Test.java b/chapter22/src/test/java/com/seaofnodes/simple/Chapter20Test.java index 337d58ea..1765512a 100644 --- a/chapter22/src/test/java/com/seaofnodes/simple/Chapter20Test.java +++ b/chapter22/src/test/java/com/seaofnodes/simple/Chapter20Test.java @@ -11,6 +11,23 @@ import org.junit.Test; import static org.junit.Assert.*; public class Chapter20Test { + @Test public void testAllocatorFixedNeighbor() throws Exception { com.seaofnodes.simple.codegen.RegAllocTestSupport.uncoloredFixedNeighbor(); } + + @Test public void testNarrowStoreMasks() { + for( String type : new String[]{"i8","u8","i16","u16"} ) { + CodeGen code = new CodeGen("struct S { "+type+" x; }; S !s=new S; s.x=arg; return 0;") + .driver(CodeGen.Phase.RegAlloc,"x86_64_v2","SystemV"); + int stores=0; + for( var bb : code._cfg ) + for( var node : bb.outs() ) + if( node instanceof com.seaofnodes.simple.node.cpus.x86_64_v2.StoreX86 st ) { + stores++; + assertEquals(-1,st.regmap(4).nextReg((short)15)); + } + assertEquals(1,stores); + } + } + @Test public void testInlinedReturnValue() { String src = """ struct S { int x; }; diff --git a/chapter22/src/test/java/com/seaofnodes/simple/Chapter21Test.java b/chapter22/src/test/java/com/seaofnodes/simple/Chapter21Test.java index 85e92bd8..b27e16fd 100644 --- a/chapter22/src/test/java/com/seaofnodes/simple/Chapter21Test.java +++ b/chapter22/src/test/java/com/seaofnodes/simple/Chapter21Test.java @@ -12,6 +12,38 @@ import org.junit.Test; import static org.junit.Assert.*; public class Chapter21Test { + @Test public void testArmFloatMemory() throws IOException { + for( String type : new String[]{"f32","f64"} ) { + String src = type+"[] !a=new "+type+"[3]; a[arg]=1.25; return a[1];"; + CodeGen code = new CodeGen(src).driver("arm","SystemV",null); + byte[] image = new byte[1<<20]; + byte[] bits = code._encoding.bits(); + System.arraycopy(bits,0,image,0,bits.length); + EvalArm64 cpu = new EvalArm64(image,1<<16); + cpu.regs[arm.X0]=1; + assertEquals(0,cpu.step(1000)); + assertEquals(1.25,cpu.fregs[0],0); + } + // Independently exercise both SIMD widths and addressing modes. Keep + // the GPR value different so accidentally reading that bank is visible. + for( boolean wide : new boolean[]{false,true} ) + for( boolean indexed : new boolean[]{false,true} ) { + EvalArm64 cpu = new EvalArm64(new byte[512],256); + cpu.regs[1]=128; cpu.regs[2]=16; cpu.regs[3]=99; + cpu.fregs[3]=-13.25; + int store = (wide ? 0xFD000000 : 0xBD000000) | ((16/(wide?8:4))<<10) | (1<<5) | 3; + if( indexed ) store=(wide ? 0xFC226823 : 0xBC226823); // STR D3/S3,[X1,X2] + cpu.st4(0,store); + cpu.st4(4,store | (1<<22)); // LDR to the same SIMD register. + assertEquals(0,cpu.step(1)); + assertEquals(-13.25,wide ? cpu.ld8f(144) : cpu.ld4f(144),0); + cpu.fregs[3]=0; + assertEquals(0,cpu.step(1)); + assertEquals(-13.25,cpu.fregs[3],0); + } + } + + @Test public void testArmCallInstructions() { EvalArm64 cpu = new EvalArm64(new byte[512],256); for( int delta : new int[]{4,32,-4} ) { diff --git a/chapter22/src/test/java/com/seaofnodes/simple/EvalArm64.java b/chapter22/src/test/java/com/seaofnodes/simple/EvalArm64.java index b9c5e415..c6151340 100644 --- a/chapter22/src/test/java/com/seaofnodes/simple/EvalArm64.java +++ b/chapter22/src/test/java/com/seaofnodes/simple/EvalArm64.java @@ -480,7 +480,7 @@ public class EvalArm64 { switch(opc) { case 0x1: { if(opcode1 == arm.OPF_STORE_R_32) { - st4((int)regs[rn] + (int)regs[rm], (int)regs[rdid]); + st4((int)regs[rn] + (int)regs[rm], Float.floatToRawIntBits((float)fregs[rdid])); }else { trap = (2+1); } @@ -519,7 +519,7 @@ public class EvalArm64 { case 0x0: { // store if(opcode1 == arm.OPF_STORE_IMM_32) { - st4((int)rval, (int)regs[rdid]); + st4((int)rval, Float.floatToRawIntBits((float)fregs[rdid])); } else trap = (2+1); rdid = -1; @@ -528,7 +528,7 @@ public class EvalArm64 { case 0x1: { // LDR (immediate) if(opcode1 == arm.OPF_LOAD_IMM_32) { - frval = ld4s((int)rval); + frval = ld4f((int)rval); } else trap = (2+1); break; } @@ -682,7 +682,7 @@ public class EvalArm64 { switch(opc) { case 0x1: { if(opcode1 == arm.OPF_STORE_R_64) { - st8((int)regs[rn] + (int)regs[rm], (int)regs[rdid]); + st8((int)regs[rn] + (int)regs[rm], Double.doubleToRawLongBits(fregs[rdid])); }else { trap = (2+1); } @@ -710,7 +710,7 @@ public class EvalArm64 { int base = ir >> 5 & 0x1F; int imm = (ir >> 10) & 0xFFF; - imm *= 4; + imm *= 8; is_f = true; rval = regs[base] + imm; int opc = (ir >> 22) & 0x3; @@ -720,7 +720,7 @@ public class EvalArm64 { case 0x0: { // store if(opcode1 == arm.OPF_STORE_IMM_64) { - st8((int)rval, regs[rdid]); + st8((int)rval, Double.doubleToRawLongBits(fregs[rdid])); } else trap = (2+1); rdid = -1; @@ -729,7 +729,7 @@ public class EvalArm64 { case 0x1: { // LDR (immediate) if(opcode1 == arm.OPF_LOAD_IMM_64) { - frval = ld8((int)rval); + frval = ld8f((int)rval); } else trap = (2+1); break; } diff --git a/chapter22/src/test/java/com/seaofnodes/simple/codegen/RegAllocTestSupport.java b/chapter22/src/test/java/com/seaofnodes/simple/codegen/RegAllocTestSupport.java index 85de8b36..e4643ee6 100644 --- a/chapter22/src/test/java/com/seaofnodes/simple/codegen/RegAllocTestSupport.java +++ b/chapter22/src/test/java/com/seaofnodes/simple/codegen/RegAllocTestSupport.java @@ -29,6 +29,19 @@ public class RegAllocTestSupport { return code; } + public static void uncoloredFixedNeighbor() throws Exception { + CodeGen code = graph(); + RegAlloc alloc = new RegAlloc(code); + Op def = new Op(new RegMask(3L),null,null,false,code._start); + LRG lrg = alloc.newLRG(def); + LRG neighbor = new LRG((short)99); + neighbor._mask = A; + lrg.addNeighbor(neighbor); // Uncolored, but its only possible color is A. + var bias = IFG.class.getDeclaredMethod("biasColorNeighbors",RegAlloc.class,Node.class,RegMask.class); + bias.setAccessible(true); + assertEquals((short)1,bias.invoke(null,alloc,def,new RegMaskRW(3L,0L))); + } + public static void masks() { for( int reg : new int[]{0,63,64,65,127} ) { RegMask mask = new RegMask(reg); -- cgit v1.2.3