From b09370af9db2be3b763eb72a61a34aecb743dcd9 Mon Sep 17 00:00:00 2001 From: Cliff Click Date: Sat, 29 Mar 2025 10:48:05 -0700 Subject: Split popular constants --- .../com/seaofnodes/simple/codegen/RegAlloc.java | 94 +++++++++++++++------- .../com/seaofnodes/simple/codegen/RegMask.java | 1 + .../main/java/com/seaofnodes/simple/node/Node.java | 12 ++- .../java/com/seaofnodes/simple/MergeSortTest.java | 6 +- 4 files changed, 77 insertions(+), 36 deletions(-) (limited to 'chapter21/src') diff --git a/chapter21/src/main/java/com/seaofnodes/simple/codegen/RegAlloc.java b/chapter21/src/main/java/com/seaofnodes/simple/codegen/RegAlloc.java index 32fca074..6ffb42c9 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/codegen/RegAlloc.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/codegen/RegAlloc.java @@ -4,6 +4,7 @@ import com.seaofnodes.simple.Ary; import com.seaofnodes.simple.Utils; import com.seaofnodes.simple.node.*; import java.util.Arrays; +import java.util.BitSet; import java.util.IdentityHashMap; /** @@ -206,7 +207,7 @@ public class RegAlloc { split(round,lrg); } - // Split this live range + // Split this live range, top level heuristic boolean split( byte round, LRG lrg ) { assert lrg.leader(); // Already rolled up @@ -220,8 +221,11 @@ public class RegAlloc { lrg._1regUseCnt <= 1 && (lrg._1regDefCnt + lrg._1regUseCnt) > 0 ) return splitEmptyMaskSimple(round,lrg); - // Default to splitByLoop - //return splitEmptyMask(round,lrg); + // Repeated single-reg uses from a single def. Special for archs + // with more fixed regs. + if( !lrg._multiDef && lrg._1regDefCnt <= 1 && lrg._1regUseCnt > 2 ) + if( splitEmptyMaskByUse(round,lrg) ) + return true; } // Generic split-by-loop depth. @@ -244,39 +248,69 @@ public class RegAlloc { // alloc // V2/rax - kills prior RAX // st4 [V1],len - No good, must split around - makeSplit("def/empty1",round,lrg).insertAfter((Node)lrg._machDef, false/*true*/); + makeSplit("def/empty1",round,lrg).insertAfterAndReplace((Node)lrg._machDef, false/*true*/); // Split just before use if( lrg._1regUseCnt==1 || (lrg._1regDefCnt==1 && ((Node)lrg._machDef).nOuts()==1) ) insertBefore((Node)lrg._machUse,lrg._uidx,"use/empty1",round,lrg,true); return true; } - // Split live range with an empty mask. Specifically forces splits at - // single-register defs or uses everywhere. - boolean splitEmptyMask( byte round, LRG lrg ) { - findAllLRG(lrg); - // If no single-use or single-def, assume this is a complete register - // kill and force spilling everywhere. - boolean all = lrg._killed || (lrg._1regDefCnt + lrg._1regUseCnt)==0; - for( Node n : _ns ) { - if( !(n instanceof MachNode mach) ) continue; - // Find def of spilling live range; spilling everywhere, OR - // single-register DEF and not cloneable (since these will clone - // before every use) - if( lrg(n)==lrg && (all || (!mach.isClone() && mach.outregmap().size1() )) ) - makeSplit(n,"def/empty2",round,lrg).insertAfter(n,true); - // Find all uses - for( int i=1; i rclass = new Ary<>(RegMask.class); + boolean done=false; + while( !done ) { + done = true; + for( Node use : def._outputs ) + if( use instanceof MachNode mach ) + for( int i=1; i rclass, RegMask rmask ) { + for( int i=0; i=0; j-- ) { // Can we avoid a split of a split? 'this' split is used by // another split in the same block. diff --git a/chapter21/src/test/java/com/seaofnodes/simple/MergeSortTest.java b/chapter21/src/test/java/com/seaofnodes/simple/MergeSortTest.java index bf775b4f..fb250fc8 100644 --- a/chapter21/src/test/java/com/seaofnodes/simple/MergeSortTest.java +++ b/chapter21/src/test/java/com/seaofnodes/simple/MergeSortTest.java @@ -58,9 +58,9 @@ merge_sort(a, b, a#); return a; """; - Chapter20Test.testCPU(src,"x86_64_v2", "SystemV",54,"Stop[ return mov(mov([int])); return 0; ]"); - Chapter20Test.testCPU(src,"riscv" , "SystemV",44,"Stop[ return mov(mov([int])); return 0; ]"); - Chapter20Test.testCPU(src,"arm" , "SystemV",44,"Stop[ return mov(mov([int])); return 0; ]"); + Chapter21Test.testCPU(src,"x86_64_v2", "SystemV",54,"Stop[ return mov(mov([int])); return 0; ]"); + Chapter21Test.testCPU(src,"riscv" , "SystemV",44,"Stop[ return mov(mov([int])); return 0; ]"); + Chapter21Test.testCPU(src,"arm" , "SystemV",44,"Stop[ return mov(mov([int])); return 0; ]"); //assertEquals("int[ 1,2,3,4,5,6,7,8,9,10,11]", Eval2.eval(code, 11)); } -- cgit v1.2.3