summaryrefslogtreecommitdiff
path: root/chapter22
diff options
context:
space:
mode:
Diffstat (limited to 'chapter22')
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/node/MemOpNode.java3
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/node/StoreNode.java31
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/Int8RISC.java2
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/LUI.java2
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java2
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/type/TypeInteger.java8
-rw-r--r--chapter22/src/main/java/com/seaofnodes/simple/type/TypeMem.java1
-rw-r--r--chapter22/src/test/java/com/seaofnodes/simple/Chapter22Test.java78
-rw-r--r--chapter22/src/test/java/com/seaofnodes/simple/progs/person.smp2
-rw-r--r--chapter22/src/test/java/com/seaofnodes/simple/progs/riscv_load.smp5
-rw-r--r--chapter22/src/test/java/com/seaofnodes/simple/progs/sext_str_1.smp4
-rw-r--r--chapter22/src/test/java/com/seaofnodes/simple/progs/sext_str_fold_away.smp5
-rw-r--r--chapter22/src/test/java/com/seaofnodes/simple/progs/sext_str_not_fold_away.smp4
-rw-r--r--chapter22/src/test/java/com/seaofnodes/simple/progs/sext_str_not_fold_away_2.smp4
-rw-r--r--chapter22/src/test/java/com/seaofnodes/simple/progs/store_peep.smp3
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