From 4cd6517df6f9fbf77215525cf0b736ab4f90b143 Mon Sep 17 00:00:00 2001 From: Cliff Click Date: Tue, 1 Apr 2025 19:59:02 -0700 Subject: Fix bug encoded inf loops Assert functions laid out end to end. Fix bug with layout on inf loops. Swap default Never jump order. --- .../main/java/com/seaofnodes/simple/codegen/Encoding.java | 15 ++++++++++++--- .../main/java/com/seaofnodes/simple/node/LoopNode.java | 14 ++++++-------- .../src/main/java/com/seaofnodes/simple/node/Node.java | 2 ++ .../com/seaofnodes/simple/node/cpus/riscv/NJmpRISC.java | 10 +++------- .../test/java/com/seaofnodes/simple/Chapter18Test.java | 2 +- 5 files changed, 24 insertions(+), 19 deletions(-) (limited to 'chapter21') 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 b4d5aefa..335715c6 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java @@ -159,8 +159,11 @@ public class Encoding { Ary rpo = new Ary<>(CFGNode.class); BitSet visit = _code.visit(); for( Node n : _code._start._outputs ) - if( n instanceof FunNode fun ) + if( n instanceof FunNode fun ) { + int x = rpo._len; _rpo_cfg(fun, visit, rpo); + assert rpo.at(x) instanceof ReturnNode; + } rpo.add(_code._start); // Reverse in-place @@ -227,13 +230,19 @@ public class Encoding { t.invert(); f.invert(); CProjNode tmp=f; f=t; t=tmp; // Swap t/f + int d=tld; tld=fld; fld=d; // Swap depth } - // Always visit the False side last (so True side first), so that + // Whichever side is visited first becomes last in the RPO. With + // no loops, visit the False side last (so True side first) so that // when the False RPO visit returns, the IF is immediately next. // When the RPO is reversed, the fall-through path will always be // following the IF. - if( t.nOuts()==1 && !invert ) { + + // If loops are involved, attempt to keep them in a line. Visit + // the exits first, so they follow the loop body when the order gets + // reversed. + if( fld < tld || (fld==tld && f.nOuts()==1) ) { _rpo_cfg(f,visit,rpo); _rpo_cfg(t,visit,rpo); } else { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/LoopNode.java b/chapter21/src/main/java/com/seaofnodes/simple/node/LoopNode.java index 6b4026c5..787b43d2 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/LoopNode.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/LoopNode.java @@ -49,18 +49,16 @@ public class LoopNode extends RegionNode { NeverNode iff = CodeGen.CODE._mach == null ? new NeverNode(back()) // Ideal never-branch : CodeGen.CODE._mach.never(back()); // Machine never-branch - for( Node use : _outputs ) - if( use instanceof PhiNode ) - iff.addDef(use); CProjNode t = new CProjNode(iff,0,"True" ).init(); CProjNode f = new CProjNode(iff,1,"False").init(); - setDef(2,f); - iff._ltree = t._ltree = f._ltree = _ltree; + setDef(2,t); + iff._ltree = t._ltree = _ltree; + ReturnNode ret = fun.ret(); + f._ltree = ret._ltree; // Now fold control into the exit. Might have 1 valid exit, or an // XCtrl or a bunch of prior NeverNode exits. Node top = new ConstantNode(Type.TOP).peephole(); - ReturnNode ret = fun.ret(); Node ctrl = ret.ctrl(), mem = ret.mem(), expr = ret.expr(); if( ctrl!=null && ctrl._type != Type.XCONTROL ) { // Perfect aligned exit? @@ -74,11 +72,11 @@ public class LoopNode extends RegionNode { expr = new PhiNode(r,expr).init(); } // Append new Never exit - ctrl.addDef(t ); + ctrl.addDef(f ); mem .addDef(top); expr.addDef(top); } else { - ctrl = t; + ctrl = f; mem = top; expr = top; } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/Node.java b/chapter21/src/main/java/com/seaofnodes/simple/node/Node.java index 1e9630e3..45217e80 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/Node.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/Node.java @@ -334,6 +334,8 @@ public abstract class Node { int i; if( use instanceof PhiNode phi ) { cfg = phi.region().cfg(uidx); + if( cfg instanceof CProjNode && cfg.in(0) instanceof NeverNode nvr ) + cfg = nvr.cfg0(); i = cfg.nOuts()-1; } else { i = cfg._outputs.find(use); diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NJmpRISC.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NJmpRISC.java index f0d28a3a..39e9052b 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NJmpRISC.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NJmpRISC.java @@ -14,17 +14,13 @@ public class NJmpRISC extends NeverNode implements MachNode, RIPRelSize { @Override public String label() { return op(); } @Override public String comment() { return "L"+cproj(1)._nid; } @Override public StringBuilder _print1( StringBuilder sb, BitSet visited ) { return sb.append("jmp "); } - @Override public RegMask regmap(int i) { - if( i!=3 ) return null; - TypeFunPtr tfp = cproj(0).uctrl().fun().sig(); - return riscv.retMask(tfp,2); - } + @Override public RegMask regmap(int i) { throw Utils.TODO(); } @Override public RegMask outregmap() { return null; } @Override public void encoding( Encoding enc ) { // Short form +/-4K: beq r0,r0,imm12 // Long form: auipc rX,imm20/32; jal r0,[rX+imm12/32] - enc.jump(this,cproj(1)); + enc.jump(this,cproj(0)); enc.add4(riscv.j_type(riscv.OP_JAL, 0, 0)); } @@ -45,6 +41,6 @@ public class NJmpRISC extends NeverNode implements MachNode, RIPRelSize { } @Override public void asm(CodeGen code, SB sb) { - sb.p(label(cproj(1).uctrl())); + sb.p(label(cproj(0).uctrl())); } } diff --git a/chapter21/src/test/java/com/seaofnodes/simple/Chapter18Test.java b/chapter21/src/test/java/com/seaofnodes/simple/Chapter18Test.java index d0623d12..21e6c777 100644 --- a/chapter21/src/test/java/com/seaofnodes/simple/Chapter18Test.java +++ b/chapter21/src/test/java/com/seaofnodes/simple/Chapter18Test.java @@ -193,7 +193,7 @@ for(;;) { """); code.parse().opto().typeCheck().GCM().localSched(); assertEquals("return Top;", code._stop.toString()); - assertEquals(null, Eval2.eval(code, 0)); + assertEquals("null", Eval2.eval(code, 0)); } -- cgit v1.2.3