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 --- chapter20/README.md | 15 +++++++-------- .../main/java/com/seaofnodes/simple/codegen/IFG.java | 2 +- .../seaofnodes/simple/node/cpus/x86_64_v2/MemOpX86.java | 2 +- .../test/java/com/seaofnodes/simple/Chapter20Test.java | 17 +++++++++++++++++ .../seaofnodes/simple/codegen/RegAllocTestSupport.java | 13 +++++++++++++ 5 files changed, 39 insertions(+), 10 deletions(-) (limited to 'chapter20') diff --git a/chapter20/README.md b/chapter20/README.md index e050a812..e463831a 100644 --- a/chapter20/README.md +++ b/chapter20/README.md @@ -505,21 +505,20 @@ checks, not additional program benchmarks. | Program-test cohort | Allocator chapter | Compilations | Split moves | Loop-weighted moves | |---|---:|---:|---:|---:| -| Chapter 20 | 20 | 39 | 236 | 355 | +| Chapter 20 | 20 | 39 | 238 | 357 | `_spills` counts surviving split moves, including register-to-register copies; it does not count only stack stores. `_spillScaled` weights each move by `8^loopDepth`, a rough cost estimate rather than measured execution frequency. -The weighted subtotals are 152 for x86-64, 101 for RISC-V, and 102 for ARM. +The weighted subtotals are 154 for x86-64, 101 for RISC-V, and 102 for ARM. ### Comments on the measurements -Before the correctness fixes, this same cohort had 235 moves and a weighted -count of 354. The corrected baseline is one higher in each measure: x86-64's -weighted count rises by two, ARM's by one, while RISC-V's falls by two. This is -a small correctness cost, not a claimed quality improvement. Individual cases -move more: the x86 array example rises from three to five, while its integer -Newton example stays at 23. Looking at just one example would be misleading. +Before the correctness fixes, this cohort had 235 moves / 354 weighted moves. +The final corrected baseline costs three more of each. The final narrow x86 +store-mask backport accounts for two of those moves: an integer byte/short store +cannot consume an XMM register. This is a correctness cost, not a quality gain. +The fixed-neighbor color-bias correction changes no counts in this cohort. Later chapters will add one quality technique at a time and end with this kind of table: Chapter 21 will measure both the Chapter 20 and Chapter 21 program diff --git a/chapter20/src/main/java/com/seaofnodes/simple/codegen/IFG.java b/chapter20/src/main/java/com/seaofnodes/simple/codegen/IFG.java index acfec53f..71a96d94 100644 --- a/chapter20/src/main/java/com/seaofnodes/simple/codegen/IFG.java +++ b/chapter20/src/main/java/com/seaofnodes/simple/codegen/IFG.java @@ -494,7 +494,7 @@ abstract public class IFG { if( reg == -1 && alrg._mask.size1() ) reg = alrg._mask.firstReg(); if( reg != -1 ) { - mask.clr(alrg._reg); + mask.clr(reg); if( mask.size1() ) return mask.firstReg(); } diff --git a/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemOpX86.java b/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemOpX86.java index dee4afd4..f65fe054 100644 --- a/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemOpX86.java +++ b/chapter20/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MemOpX86.java @@ -66,7 +66,7 @@ public abstract class MemOpX86 extends MemOpNode implements MachNode { if( i==1 ) return null; // Memory if( i==2 ) return x86_64_v2.RMASK; // base in GPR if( i==3 ) return x86_64_v2.RMASK; // index in GPR - if( i==4 ) return x86_64_v2.MEM_MASK; // value in GPR or XMM + if( i==4 ) return _sz >= '4' ? x86_64_v2.MEM_MASK : x86_64_v2.RMASK; // Narrow stores need GPRs throw Utils.TODO(); } diff --git a/chapter20/src/test/java/com/seaofnodes/simple/Chapter20Test.java b/chapter20/src/test/java/com/seaofnodes/simple/Chapter20Test.java index 00a8407f..71a4bc36 100644 --- a/chapter20/src/test/java/com/seaofnodes/simple/Chapter20Test.java +++ b/chapter20/src/test/java/com/seaofnodes/simple/Chapter20Test.java @@ -10,6 +10,23 @@ import static com.seaofnodes.simple.Main.PORTS; 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;") + .parse().opto().typeCheck().instSelect(PORTS,"x86_64_v2","SystemV").GCM().localSched().regAlloc(); + 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/chapter20/src/test/java/com/seaofnodes/simple/codegen/RegAllocTestSupport.java b/chapter20/src/test/java/com/seaofnodes/simple/codegen/RegAllocTestSupport.java index bb1d49bf..1b3963c5 100644 --- a/chapter20/src/test/java/com/seaofnodes/simple/codegen/RegAllocTestSupport.java +++ b/chapter20/src/test/java/com/seaofnodes/simple/codegen/RegAllocTestSupport.java @@ -30,6 +30,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