From 5097e9f08dacb25e4c4aca20b48aa7d523067628 Mon Sep 17 00:00:00 2001 From: Cliff Click Date: Sat, 15 Mar 2025 16:05:04 -0700 Subject: Encoding fixes --- .../com/seaofnodes/simple/codegen/Encoding.java | 12 +++++++-- .../seaofnodes/simple/node/cpus/arm/BranchARM.java | 9 ++++--- .../seaofnodes/simple/node/cpus/arm/CallARM.java | 2 +- .../seaofnodes/simple/node/cpus/arm/FloatARM.java | 2 +- .../seaofnodes/simple/node/cpus/riscv/AUIPC.java | 3 +-- .../simple/node/cpus/riscv/BranchRISC.java | 6 ++++- .../simple/node/cpus/riscv/CallRISC.java | 5 ++-- .../seaofnodes/simple/node/cpus/riscv/FltRISC.java | 14 ++++------- .../simple/node/cpus/riscv/SetFRISC.java | 2 +- .../seaofnodes/simple/node/cpus/riscv/SetRISC.java | 2 +- .../seaofnodes/simple/node/cpus/riscv/riscv.java | 17 +++---------- .../simple/node/cpus/x86_64_v2/AddFX86.java | 2 +- .../simple/node/cpus/x86_64_v2/DivFX86.java | 2 +- .../simple/node/cpus/x86_64_v2/FltX86.java | 4 +-- .../simple/node/cpus/x86_64_v2/JmpX86.java | 7 ++++-- .../simple/node/cpus/x86_64_v2/MulFX86.java | 2 +- .../simple/node/cpus/x86_64_v2/SubFX86.java | 2 +- .../simple/node/cpus/x86_64_v2/x86_64_v2.java | 21 +++------------- .../com/seaofnodes/simple/print/ASMPrinter.java | 29 ++++++++++++++++------ .../java/com/seaofnodes/simple/Chapter21Test.java | 20 +++++++++++++++ 20 files changed, 94 insertions(+), 69 deletions(-) (limited to 'chapter21/src') 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 413754b0..4971624d 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/codegen/Encoding.java @@ -45,7 +45,7 @@ public class Encoding { _bits = new BAOS(); } - // Short cut to the defining register + // Shortcut to the defining register public short reg(Node n) { return _code._regAlloc.regnum(n); } @@ -153,7 +153,15 @@ public class Encoding { } // Else nothing } else if( tld > bld ) { // True enters a deeper loop throw Utils.TODO(); - } // Else True exits a loop, always forward and good + } else if( fld == bld && f.out(0) instanceof LoopNode ) { // Else True exits a loop, always forward and good + // if false is the loop backedge, make sure its true/taken + // Invert test and Proj fields + iff.invert(); + t.invert(); + f.invert(); + CProjNode tmp=f; f=t; t=tmp; // Swap t/f + + } // Always visit the False side last (so True side first), so that // when the False RPO visit returns, the IF is immediately next. diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/BranchARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/BranchARM.java index daa212f5..a7cbd1aa 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/BranchARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/BranchARM.java @@ -7,7 +7,7 @@ import com.seaofnodes.simple.node.*; // Jump on flags, uses flags public class BranchARM extends IfNode implements MachNode{ - final String _bop; + String _bop; BranchARM(IfNode iff, String bop ) { super(iff); _bop = bop; @@ -27,9 +27,11 @@ public class BranchARM extends IfNode implements MachNode{ @Override public RegMask regmap(int i) { assert i==1; return arm.FLAGS_MASK; } @Override public RegMask outregmap() { return null; } + @Override public void invert() { _bop = invert(_bop); } // Encoding is appended into the byte array; size is returned @Override public void encoding( Encoding enc ) { + enc.jump(this,cproj(0)); // Assuming that condition flags are already set. These flags are set // by comparison (or sub). No need for regs because it uses flags arm.COND cond = switch (_bop) { @@ -47,9 +49,10 @@ public class BranchARM extends IfNode implements MachNode{ @Override public void asm(CodeGen code, SB sb) { String src = code.reg(in(1)); if( src!="flags" ) sb.p(src); - else sb.p(" "); Node prj = cproj(0); - sb.p(prj instanceof LoopNode ? "LOOP" : "L").p(prj._nid); + while( prj.nOuts() == 1 ) + prj = prj.out(0); // Skip empty blocks + sb.p(prj instanceof LoopNode ? " LOOP" : " L").p(prj._nid); } @Override public String comment() { return "L"+cproj(1)._nid+", L"+cproj(0)._nid; } } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallARM.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallARM.java index 3058e7c8..2a815f37 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallARM.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/arm/CallARM.java @@ -33,7 +33,7 @@ public class CallARM extends CallNode implements MachNode { @Override public void asm(CodeGen code, SB sb) { sb.p(_name); for( int i=0; i 0x33; - case "<=" -> 0x13; - case "==" -> 0x33; - default -> throw Utils.TODO(); - }; - } // Since opcode is the same just return back func3 - // BEQ: 01100011 - // BLT: 01100011 - // BLE: bge rt, rs, offset: static public int jumpop(String op) { return switch(op) { + case "==" -> 0x0; + case "!=" -> 0x1; case "<" -> 0x4; case "<=" -> 0x5; - case "==" -> 0; + case "u<" -> 0x6; + case "u<=" -> 0x7; default -> throw Utils.TODO(); }; } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFX86.java index 86b3b365..839b147c 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/AddFX86.java @@ -27,6 +27,6 @@ public class AddFX86 extends MachConcreteNode implements MachNode { // General form: "addf dst += src" @Override public void asm(CodeGen code, SB sb) { - sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" + ").p(code.reg(in(2))); + sb.p(code.reg(this)).p(" += ").p(code.reg(in(2))); } } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivFX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivFX86.java index bfd57b34..52988d13 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivFX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/DivFX86.java @@ -29,6 +29,6 @@ public class DivFX86 extends MachConcreteNode implements MachNode { // General form: "divf dst /= src" @Override public void asm(CodeGen code, SB sb) { - sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" / ").p(code.reg(in(2))); + sb.p(code.reg(this)).p(" /= ").p(code.reg(in(2))); } } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java index 5c4002e1..2d332764 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/FltX86.java @@ -15,7 +15,7 @@ public class FltX86 extends ConstantNode implements MachNode { // Encoding is appended into the byte array; size is returned @Override public void encoding( Encoding enc ) { enc.largeConstant(this,_con); - // Simply move the constant into a FPR + // Load the constant into a FPR // movsd xmm, [rip + 0] // F2 0F 10 /r MOVSD xmm1, m64 short dst = (short)(enc.reg(this ) - x86_64_v2.XMM_OFFSET); @@ -32,6 +32,6 @@ public class FltX86 extends ConstantNode implements MachNode { } @Override public void asm(CodeGen code, SB sb) { - _con.print(sb.p(code.reg(this)).p(" #")); + _con.print(sb.p(code.reg(this)).p(" = #")); } } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/JmpX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/JmpX86.java index 1a5a4d0a..ae5635b8 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/JmpX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/JmpX86.java @@ -6,7 +6,7 @@ import com.seaofnodes.simple.node.*; // Jump on flags, uses flags public class JmpX86 extends IfNode implements MachNode { - final String _bop; + String _bop; JmpX86( IfNode iff, String bop ) { super(iff); _bop = bop; @@ -26,6 +26,7 @@ public class JmpX86 extends IfNode implements MachNode { } @Override public RegMask regmap(int i) { assert i==1; return x86_64_v2.FLAGS_MASK; } @Override public RegMask outregmap() { return null; } + @Override public void invert() { _bop = invert(_bop); } // Encoding is appended into the byte array; size is returned @Override public void encoding( Encoding enc ) { @@ -39,7 +40,9 @@ public class JmpX86 extends IfNode implements MachNode { @Override public void asm(CodeGen code, SB sb) { String src = code.reg(in(1)); if( src!="flags" ) sb.p(src); - Node prj = cproj(0); + Node prj = cproj(0); // 0 is True is jump target + while( prj.nOuts() == 1 ) + prj = prj.out(0); // Skip empty blocks sb.p(prj instanceof LoopNode ? " LOOP" : " L").p(prj._nid); } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulFX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulFX86.java index bac84140..cb18e708 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulFX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/MulFX86.java @@ -29,6 +29,6 @@ public class MulFX86 extends MachConcreteNode implements MachNode { // General form: "mulf dst *= src" @Override public void asm(CodeGen code, SB sb) { - sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" * ").p(code.reg(in(2))); + sb.p(code.reg(this)).p(" *= ").p(code.reg(in(2))); } } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SubFX86.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SubFX86.java index d727d429..0c952ddc 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SubFX86.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/SubFX86.java @@ -26,6 +26,6 @@ public class SubFX86 extends MachConcreteNode implements MachNode { // General form: "subf dst -= src" @Override public void asm(CodeGen code, SB sb) { - sb.p(code.reg(this)).p(" = ").p(code.reg(in(1))).p(" - ").p(code.reg(in(2))); + sb.p(code.reg(this)).p(" -= ").p(code.reg(in(2))); } } diff --git a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java index 9263616e..8cd7128d 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/node/cpus/x86_64_v2/x86_64_v2.java @@ -62,18 +62,6 @@ public class x86_64_v2 extends Machine { DIRECT, // mem }; - // Inverting IfNode - static public String invert(String op) { - return switch (op) { - case "==" -> "!="; - case "!=" -> "=="; - case ">" -> "<="; - case "<" -> ">="; - case ">=" -> "<" ; - case "<=" -> ">" ; - default -> throw new IllegalStateException("Unexpected value: " + op); - }; - } // opcode included here // 0F 84 cd JE rel32 // 0F 85 cd JNE rel32 @@ -81,8 +69,6 @@ public class x86_64_v2 extends Machine { // 0F 8C cd JL rel32 // 0F 8E cd JLE rel32 // 0F 8D cd JGE rel32 - - static public int jumpop(String op) { return switch (op) { case "==" -> 0x84; @@ -512,9 +498,10 @@ public class x86_64_v2 extends Machine { // If/Bool combos will match to a Cmp/Set which sets flags. // Most general arith ops will also set flags, which the Jmp needs directly. // Loads do not set the flags, and will need an explicit TEST - if(!(iff.in(1) instanceof BoolNode)) - iff.setDef(1, new BoolNode.EQ(iff.in(1), new ConstantNode(TypeInteger.ZERO))); - return new JmpX86(iff, invert(((BoolNode) iff.in(1)).op())); + BoolNode bool; + if( iff.in(1) instanceof BoolNode bool0 ) bool = bool0; + else iff.setDef(1, bool=new BoolNode.EQ(iff.in(1), new ConstantNode(TypeInteger.ZERO))); + return new JmpX86(iff, bool.op()); } private Node ld(LoadNode ld) { diff --git a/chapter21/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java b/chapter21/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java index 55a45a32..d511d8ad 100644 --- a/chapter21/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java +++ b/chapter21/src/main/java/com/seaofnodes/simple/print/ASMPrinter.java @@ -38,7 +38,7 @@ public abstract class ASMPrinter { return iadr; } - static private final int encWidth = 8; + static private final int encWidth = 10; static private final int opWidth = 5; static private final int argWidth = 30; static int doBlock(int iadr, SB sb, CodeGen code, FunNode fun, int cfgidx) { @@ -47,6 +47,7 @@ public abstract class ASMPrinter { sb.p(label(bb)).p(":").nl(); if( bb instanceof CallNode ) return iadr; final boolean postAlloc = code._phase.ordinal() > CodeGen.Phase.RegAlloc.ordinal(); + final boolean postEncode= code._phase.ordinal() >=CodeGen.Phase.Encoding.ordinal(); boolean once=false; for( Node n : bb.outs() ) { @@ -73,20 +74,22 @@ public abstract class ASMPrinter { // All the non-phis for( int i=0; i>1); i++ ) sb.hex1(code._encoding._bits.buf()[iadr++]); for( int i=size*2; i>1); // Not-printed parts of encoding } else sb.fix(encWidth,""); sb.p(" "); @@ -151,11 +155,20 @@ public abstract class ASMPrinter { sb.nl(); + + if( fatEncoding > 0 ) { + sb.hex2(iadr).p(" "); + for( int i=0; i + flt guess = x; + while( 1 ) { + flt next = (x/guess + guess)/2; + if( next == guess ) return guess; + guess = next; + } +}; +flt farg = arg; +return sqrt(farg) + sqrt(farg+2.0); +"""; + testCPU(src,"x86_64_v2", "SystemV",25,null); + testCPU(src,"riscv" , "SystemV",17,null); + testCPU(src,"arm" , "SystemV",18,null); + } } -- cgit v1.2.3