diff options
Diffstat (limited to 'chapter22/src')
15 files changed, 128 insertions, 26 deletions
diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/MemOpNode.java b/chapter22/src/main/java/com/seaofnodes/simple/node/MemOpNode.java index 058c86fa..bb84019e 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/MemOpNode.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/MemOpNode.java @@ -75,7 +75,6 @@ public abstract class MemOpNode extends Node { _declaredType = Type.BOTTOM; } - // static String mlabel(String name) { return "[]".equals(name) ? "ary" : ("#".equals(name) ? "len" : name); } String mlabel() { return mlabel(_name); } @@ -85,7 +84,7 @@ public abstract class MemOpNode extends Node { @Override public StringBuilder _print1( StringBuilder sb, BitSet visited ) { return _printMach(sb,visited); } public StringBuilder _printMach( StringBuilder sb, BitSet visited ) { throw Utils.TODO(); } - + public int log_size() { return _declaredType.log_size(); } @Override public boolean eq(Node n) { diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/StoreNode.java b/chapter22/src/main/java/com/seaofnodes/simple/node/StoreNode.java index 4b73ac1b..2e9e38d5 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/StoreNode.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/StoreNode.java @@ -84,21 +84,22 @@ public class StoreNode extends MemOpNode { } } - // Store of zero after alloc - if( mem() instanceof ProjNode prj && prj.in(0) instanceof NewNode && - prj.in(0)==ptr().in(0) && // Same NewNode memory & pointer - (val()._type==TypeInteger.ZERO || val()._type==Type.NIL ) ) - return mem(); - - // TODO: Needs more love: the shift amount depends on the store size - //if( val() instanceof SarNode shr && - // shr.in(1) instanceof ShlNode shl && - // shr.in(2)._type.isConstant() && - // shl.in(2)._type.isConstant() ) { - // if( shl.in(2)._type == shr.in(2)._type ) - // return setDef(3, shl.in(1)); - //} - + if( val() instanceof SarNode shr && + shr.in(1) instanceof ShlNode shl && + shr.in(2)._type.isConstant() && + shl.in(2)._type.isConstant() ) { + TypeInteger shrC = (TypeInteger) shr.in(2)._type; + + // size of the thing that sign-extends + int base_size = (1 << shr.in(1)._type.log_size()) << 3; + int not_affected_bits = base_size - (int) shrC.value(); + int store_size = (1 << log_size()) << 3; + // if the store is unrelated to the shift amount, then get rid of the shift + if( shl.in(2)._type == shr.in(2)._type && shrC.value() >= store_size && not_affected_bits >= store_size) { + setDef(4, shl.in(1)); + return this; + } + } return null; } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/Int8RISC.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/Int8RISC.java index d620a471..f9b7daee 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/Int8RISC.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/Int8RISC.java @@ -32,7 +32,7 @@ public class Int8RISC extends ConstantNode implements MachNode, RIPRelSize { // Delta is from opcode start @Override public void patch( Encoding enc, int opStart, int opLen, int delta ) { - short dst = (short)(enc.reg(this)); + short dst = enc.reg(this); short tmp = (short)riscv.T6; // AUIPC dst,#hi20_constant_pool enc.patch4(opStart , riscv.u_type(riscv.OP_AUIPC, tmp, delta>>12)); diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LUI.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LUI.java index 75ad6496..b65afc79 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LUI.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LUI.java @@ -10,7 +10,7 @@ import com.seaofnodes.simple.type.TypeInteger; public class LUI extends ConstantNode implements MachNode { public LUI( int imm20 ) { super(TypeInteger.constant(imm20)); - assert riscv.imm20Exact((TypeInteger)_con); + assert (imm20 & 0xFFF)==0; } @Override public RegMask regmap(int i) { return null; } @Override public RegMask outregmap() { return riscv.WMASK; } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java index 3b8ff100..9c5bfa10 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java @@ -318,7 +318,7 @@ public class riscv extends Machine { // shift left 32 to clear out the upper 32 bits. // shift right SIGNED to sign-extend upper 32 bits; then shift 12 more to clear out lower 12 bits. // shift left 12 to re-center the bits. - return ti.isConstant() && (((ti.value()<<32)>>>44)<<12) == ti.value(); + return ti.isConstant() && (((ti.value()<<32)>>44)<<12) == ti.value(); } @Override public Node instSelect( Node n ) { diff --git a/chapter22/src/main/java/com/seaofnodes/simple/type/TypeInteger.java b/chapter22/src/main/java/com/seaofnodes/simple/type/TypeInteger.java index 9f017fd1..1128ce24 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/type/TypeInteger.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/type/TypeInteger.java @@ -75,11 +75,17 @@ public class TypeInteger extends Type { @Override public boolean isConstant() { return _min == _max; } @Override public int log_size() { + assert !isHigh(); // High types are dead, and should never hit code emission. if( this==I8 || this==U8 || this==BOOL ) return 0; // 1<<0 == 1 bytes if( this==I16 || this==U16 ) return 1; // 1<<1 == 2 bytes if( this==I32 || this==U32 ) return 2; // 1<<2 == 4 bytes if( this==BOT ) return 3; // 1<<3 == 8 bytes - if( isHighOrConst() ) return 0; + if( isConstant() ) { // just const here + if (-0xFF <= _min && _min <= 0xFF) return 0; + else if (-0xFFFF <= _min && _min <= 0xFFFF) return 1; + else if (-0xFFFFFFFFL <= _min && _min <= 0xFFFFFFFFL) return 2; + else return 3; + } throw Utils.TODO(); } diff --git a/chapter22/src/main/java/com/seaofnodes/simple/type/TypeMem.java b/chapter22/src/main/java/com/seaofnodes/simple/type/TypeMem.java index 9be4908b..63fb30ce 100644 --- a/chapter22/src/main/java/com/seaofnodes/simple/type/TypeMem.java +++ b/chapter22/src/main/java/com/seaofnodes/simple/type/TypeMem.java @@ -50,6 +50,7 @@ public class TypeMem extends Type { } @Override public boolean isHigh() { return _t.isHigh(); } + @Override public int log_size() { throw Utils.TODO(); } @Override public Type glb(boolean mem) { return make(_alias,_t.glb(true)); } @Override int hash() { return 9876543 + _alias + _t.hashCode(); } diff --git a/chapter22/src/test/java/com/seaofnodes/simple/Chapter22Test.java b/chapter22/src/test/java/com/seaofnodes/simple/Chapter22Test.java index bfb20705..394ba336 100644 --- a/chapter22/src/test/java/com/seaofnodes/simple/Chapter22Test.java +++ b/chapter22/src/test/java/com/seaofnodes/simple/Chapter22Test.java @@ -22,7 +22,7 @@ public class Chapter22Test { testCPU(src,"arm" , "SystemV",-1,null); } - static void testCPU( String src, String cpu, String os, int spills, String stop ) { + static CodeGen testCPU( String src, String cpu, String os, int spills, String stop ) { CodeGen code = new CodeGen(src).driver(CodeGen.Phase.Encoding,cpu,os); int delta = spills>>3; if( delta==0 ) delta = 1; @@ -30,15 +30,86 @@ public class Chapter22Test { assertEquals("Expect spills:",spills,code._regAlloc._spillScaled,delta); if( stop != null ) assertEquals(stop, code._stop.toString()); + return code; } - @Test public void testR5Load() throws IOException { - EvalRisc5 R5 = TestRisc5.build("riscv_load", 0, 0, false); + static int testCPUSize( String src, String cpu, String os, int spills, String stop ) { + return testCPU(src,cpu,os,spills,stop)._encoding._bits.size(); + } + + // Should not fold away + @Test public void testSextFail() throws IOException { + String src = """ +struct Person { i32 age;}; +Person !p = new Person; +p.age = (arg<<17)>>17; +return 0; +"""; + assertEquals(46, testCPUSize(src, "x86_64_v2","Win64",2,"return 0;")); + assertEquals(60, testCPUSize(src, "riscv","SystemV",4,"return 0;")); + assertEquals(56, testCPUSize(src, "arm","SystemV",4,"return 0;")); + + // do assertEquals here + EvalRisc5 R5 = TestRisc5.build("sext_str_not_fold_away", 0, 4, false); int trap = R5.step(100); assertEquals(0,trap); + + EvalArm64 A5 = TestArm64.build("sext_str_not_fold_away", 0, 4, false); + trap = A5.step(100); + assertEquals(0,trap); + + } + + // Should not fold away + @Test public void testSextFail2() throws IOException { + String src = """ + + struct Person { i32 age;}; + Person !p = new Person; + p.age = (arg<<48)>>48; + return 0; + """; + + EvalRisc5 R5 = TestRisc5.build("sext_str_not_fold_away_2", 0, 4, false); + int trap = R5.step(100); + assertEquals(0,trap); + + EvalArm64 A5 = TestArm64.build("sext_str_not_fold_away_2", 0, 4, false); + int trap_arm = A5.step(100); + assertEquals(0,trap_arm); + + assertEquals(46, testCPUSize(src, "x86_64_v2","Win64",2,"return 0;")); + assertEquals(60, testCPUSize(src, "riscv","SystemV",4,"return 0;")); + assertEquals(56, testCPUSize(src, "arm","SystemV",4,"return 0;")); + + } + + // Should fold away + @Test public void testSextSuccess() throws IOException { + String src = """ +// Should fold away sign extend +struct Person { i8 age;}; +Person !p = new Person; +p.age = (arg<<48)>>48; +return 0; + """; + + EvalRisc5 R5 = TestRisc5.build("sext_str_fold_away", 0, 5, false); + int trap = R5.step(100); + assertEquals(0,trap); + + EvalArm64 A5 = TestArm64.build("sext_str_fold_away", 0, 5, false); + int trap_arm = A5.step(100); + assertEquals(0,trap_arm); + + assertEquals(41, testCPUSize(src, "x86_64_v2","Win64",2,"return 0;")); + assertEquals(56, testCPUSize(src, "riscv","SystemV",5,"return 0;")); + assertEquals(52, testCPUSize(src, "arm","SystemV",5,"return 0;")); // do assertEquals here } + + // Int now is changed to 4 bytes. @Test public void testPerson() throws IOException { String person = "6\n"; @@ -165,4 +236,5 @@ return sum(is); assertEquals(0,arm.regs[0]); } + } diff --git a/chapter22/src/test/java/com/seaofnodes/simple/progs/person.smp b/chapter22/src/test/java/com/seaofnodes/simple/progs/person.smp index 9f0f5bea..507fb83b 100644 --- a/chapter22/src/test/java/com/seaofnodes/simple/progs/person.smp +++ b/chapter22/src/test/java/com/seaofnodes/simple/progs/person.smp @@ -1,6 +1,6 @@ // -*-java-*- struct Person { - int age; + i32 age; }; val fcn = { Person?[] ps, int x -> diff --git a/chapter22/src/test/java/com/seaofnodes/simple/progs/riscv_load.smp b/chapter22/src/test/java/com/seaofnodes/simple/progs/riscv_load.smp index 2366f354..67369feb 100644 --- a/chapter22/src/test/java/com/seaofnodes/simple/progs/riscv_load.smp +++ b/chapter22/src/test/java/com/seaofnodes/simple/progs/riscv_load.smp @@ -1 +1,4 @@ -return 123456789012345;
\ No newline at end of file +struct Person { i32 age;}; +Person !p = new Person; +p.age += arg; +return p.age; diff --git a/chapter22/src/test/java/com/seaofnodes/simple/progs/sext_str_1.smp b/chapter22/src/test/java/com/seaofnodes/simple/progs/sext_str_1.smp new file mode 100644 index 00000000..cfb3fbcc --- /dev/null +++ b/chapter22/src/test/java/com/seaofnodes/simple/progs/sext_str_1.smp @@ -0,0 +1,4 @@ +struct Person {i64 age;} +Person !p = new Person; +p.age += arg; +return p.age; diff --git a/chapter22/src/test/java/com/seaofnodes/simple/progs/sext_str_fold_away.smp b/chapter22/src/test/java/com/seaofnodes/simple/progs/sext_str_fold_away.smp new file mode 100644 index 00000000..0cf70392 --- /dev/null +++ b/chapter22/src/test/java/com/seaofnodes/simple/progs/sext_str_fold_away.smp @@ -0,0 +1,5 @@ +// Should fold away sign extend +struct Person { i8 age;}; +Person !p = new Person; +p.age = (arg<<48)>>48; +return 0;
\ No newline at end of file diff --git a/chapter22/src/test/java/com/seaofnodes/simple/progs/sext_str_not_fold_away.smp b/chapter22/src/test/java/com/seaofnodes/simple/progs/sext_str_not_fold_away.smp new file mode 100644 index 00000000..48cc6409 --- /dev/null +++ b/chapter22/src/test/java/com/seaofnodes/simple/progs/sext_str_not_fold_away.smp @@ -0,0 +1,4 @@ +struct Person { i32 age;}; +Person !p = new Person; +p.age = (arg<<17)>>17; +return 0;
\ No newline at end of file diff --git a/chapter22/src/test/java/com/seaofnodes/simple/progs/sext_str_not_fold_away_2.smp b/chapter22/src/test/java/com/seaofnodes/simple/progs/sext_str_not_fold_away_2.smp new file mode 100644 index 00000000..3120429b --- /dev/null +++ b/chapter22/src/test/java/com/seaofnodes/simple/progs/sext_str_not_fold_away_2.smp @@ -0,0 +1,4 @@ +struct Person { i32 age;}; +Person !p = new Person; +p.age = (arg<<48)>>48; +return 0;
\ No newline at end of file diff --git a/chapter22/src/test/java/com/seaofnodes/simple/progs/store_peep.smp b/chapter22/src/test/java/com/seaofnodes/simple/progs/store_peep.smp new file mode 100644 index 00000000..c3feddd5 --- /dev/null +++ b/chapter22/src/test/java/com/seaofnodes/simple/progs/store_peep.smp @@ -0,0 +1,3 @@ +i64 a = 123456789012345; +i32 b = a; // truncate high order bits +return b;
\ No newline at end of file |
