From 955e7816da5bcb39843230438a4a0e1e4dd7f9f8 Mon Sep 17 00:00:00 2001 From: Cliff Click Date: Tue, 22 Apr 2025 09:59:23 -0700 Subject: bring back more loop help from ch22 --- .../com/seaofnodes/simple/codegen/Encoding.java | 24 +++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java b/chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java index c822a73e..3d6cd209 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java @@ -256,7 +256,7 @@ public class Encoding { ? (bb.nOuts()>1 || !(bb.cfg0() instanceof IfNode) ) // Forwards jump. If all the blocks, in RPO order, to our // target are empty, we will fall in and not need a jump. - : !isEmptyBackwardsScan(rpo,next); + : !backwardsEmptyScan(rpo,next); if( needJump ) { CFGNode jmp = _code._mach.jump(); jmp._ltree = bb._ltree; @@ -277,12 +277,18 @@ public class Encoding { // bld` is true, the `fld < bld` must be false, or else both directions // exit the loop... and the IF test would not be in the loop. - // true to exit a loop usually, keep true if taking an empty backwards branch - if( tld < bld ) return emptyBackBlock(f,bld); + // true to exit a loop usually (and false falls into Yet Another Loop + // Block), invert if false is taking an empty backwards branch. + if( tld < bld ) return forwardsEmptyScan(f,bld); // false to exit a loop, normally invert to true (except empty back) - if( fld < bld ) return !emptyBackBlock(t,bld); + if( fld < bld ) return !forwardsEmptyScan(t,bld); // Not exiting the loop; staying at this depth (or going deeper loop). + + // Jump/true to an empty backwards block + if( forwardsEmptyScan(t,bld) ) return false; + if( forwardsEmptyScan(f,bld) ) return true ; + // Fall/false into a full block, Jump/true to an empty block. if( f.nOuts()>1 && t.nOuts()==1 ) return false; if( t.nOuts()>1 && f.nOuts()==1 ) return true ; @@ -290,13 +296,17 @@ public class Encoding { return t._pre > f._pre; } - private static boolean emptyBackBlock( CFGNode c, int bld ) { - return c.loopDepth()==bld && c.nOuts()==1 && c.uctrl() instanceof LoopNode; + // Do we continue forwards from 'c' to the Loop back edge, without doing + // anything else? Then this branch can directly jump to the loop head. + private static boolean forwardsEmptyScan( CFGNode c, int bld ) { + if( c.nOuts()!=1 || c.loopDepth()!=bld ) return false; + return c.uctrl() instanceof RegionNode cfg && + (cfg instanceof LoopNode || forwardsEmptyScan(cfg,bld)); } // Is the CFG from "next" to the end empty? This means jumping to "next" // will naturally fall into the end. - private static boolean isEmptyBackwardsScan(Ary rpo, CFGNode next) { + private static boolean backwardsEmptyScan(Ary rpo, CFGNode next) { for( int i=rpo._len-1; rpo.at(i)!=next; i-- ) if( rpo.at(i).nOuts()!=1 ) return false; -- cgit v1.2.3