summaryrefslogtreecommitdiff
path: root/chapter24
diff options
context:
space:
mode:
authorCliff Click <cliffc@acm.org>2026-10-07 21:31:18 -0700
committerCliff Click <cliffc@acm.org>2026-10-07 21:31:18 -0700
commit87a75c83b75480e65147a4d425fddd14a05df4d9 (patch)
treef486050aa3a13e218ad17ab57efaccbe35336483 /chapter24
parent2eba63966bdc3d9cfdf41ee085f35cbb6d529bbc (diff)
downloadSimple-87a75c83b75480e65147a4d425fddd14a05df4d9.tar.gz
Simple-87a75c83b75480e65147a4d425fddd14a05df4d9.zip
More test case vs RA cleanup
Missing a few risc/arm encodings. Make private many tests, so they don't escape and the escaped fcn inflate x86 spill numbers
Diffstat (limited to 'chapter24')
-rw-r--r--chapter24/README.md24
-rw-r--r--chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/LoadARM.java2
-rw-r--r--chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/NotARM.java4
-rw-r--r--chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java2
-rw-r--r--chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NotRISC.java3
-rw-r--r--chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetIRISC.java6
-rw-r--r--chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java2
-rw-r--r--chapter24/src/test/java/com/seaofnodes/simple/Chapter24Test.java22
8 files changed, 38 insertions, 27 deletions
diff --git a/chapter24/README.md b/chapter24/README.md
index 07c63ee3..ceb7e03e 100644
--- a/chapter24/README.md
+++ b/chapter24/README.md
@@ -305,19 +305,21 @@ also covers a backedge-only conflict where the first attempt inserts no copy:
that attempt must still consume the one permitted delay. A regression checks
both the cheaper first attempt and the mandatory fallback.
-Rows are fixed test cohorts; columns are the compiler/allocator chapters. Each
-cell is the sum of `_spillScaled`: retained split moves, including register
-copies, weighted by loopDepth. Lower is better. **# tests counts
-compilations** (program/CPU/ABI cases), including zero-spill cases, rather than
-JUnit methods. The count and membership of each row stay fixed across columns.
+Rows are fixed test cohorts; columns are compiler chapters. Each cell gives
+**Ops / RA / X**: executed ARM+RISC-V instructions, the subset emitted for
+allocator copies/rematerializations, and x86's loop-weighted split-move estimate.
+**Cases D / X** counts measured dynamic program/target cases and x86 compilations;
+membership and inputs stay fixed across columns. Native-library work is excluded.
+Chapter 20 has no encoder, hence no dynamic counts. Lower is better within each
+metric; see the [measurement details](../docs/regalloc-spills.md) for coverage.
<!-- spill-matrix:start -->
-| Test cohort | # tests | Ch 20 | Ch 21 | Ch 22 | Ch 23 | Ch 24 |
+| Test cohort | Cases D / X | Ch 20: Ops / RA / X | Ch 21: Ops / RA / X | Ch 22: Ops / RA / X | Ch 23: Ops / RA / X | Ch 24: Ops / RA / X |
|---|---:|---:|---:|---:|---:|---:|
-| Ch 20 | 39 | 360 | 576 | 430 | 442 | 441 |
-| Ch 21 | 52 | | 1,072 | 960 | 961 | 948 |
-| Ch 22 | 26 | | | 63 | 63 | 63 |
-| Ch 23 | 24 | | | | 103 | 103 |
-| Ch 24 | 58 | | | | | 1,387 |
+| Ch 20 | 22 / 13 | — / — / 161 | 55,173 / 5,407 / 174 | 58,751 / 9,099 / 175 | 58,736 / 9,084 / 184 | 58,720 / 9,068 / 183 |
+| Ch 21 | 20 / 18 | | 6,207 / 261 / 461 | 6,324 / 379 / 475 | 6,326 / 381 / 475 | 6,325 / 380 / 470 |
+| Ch 22 | 14 / 8 | | | 198 / 60 / 7 | 194 / 56 / 7 | 194 / 56 / 7 |
+| Ch 23 | 14 / 8 | | | | 630 / 160 / 36 | 630 / 160 / 36 |
+| Ch 24 | 36 / 20 | | | | | 4,923 / 1,341 / 790 |
<!-- spill-matrix:end -->
diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/LoadARM.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/LoadARM.java
index f3bbbbeb..8fc22a67 100644
--- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/LoadARM.java
+++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/LoadARM.java
@@ -17,7 +17,7 @@ public class LoadARM extends MemOpARM {
super(ld, base, idx, off, 0);
}
@Override public String op() { return "ld"+_sz; }
- @Override public RegMask outregmap() { return size() >= 4 ? arm.MEM_MASK : arm.RMASK; }
+ @Override public RegMask outregmap() { return size() >= 4 ? arm.MEM_MASK : arm.WMASK; }
private static final int[] OP_LOADS = new int[]{ Arm64.OP_LOAD_IMM_8, Arm64.OP_LOAD_IMM_16, Arm64.OP_LOAD_IMM_32, Arm64.OP_LOAD_IMM_64, };
diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/NotARM.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/NotARM.java
index ac21c706..f8e450f6 100644
--- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/NotARM.java
+++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/NotARM.java
@@ -18,9 +18,9 @@ public class NotARM extends MachConcreteNode implements MachNode{
// subtracting zero from rs will just yield rs, it sets the zero flag and then it's used in cset
short self = enc.reg(this );
short reg1 = enc.reg(in(1));
- int subs = Arm64.imm_inst(Arm64.OP_SUBS, 0, reg1, self);
+ int subs = Arm64.imm_inst(Arm64.OP_SUBS, 0, reg1, 31);
enc.add4(subs);
- int cset = Arm64.cond_set(Arm64.OP_CSET, 31, Arm64.COND.EQ, 31, reg1);
+ int cset = Arm64.cset(Arm64.OP_CSET, 31, Arm64.COND.EQ, 31, self);
enc.add4(cset);
}
diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java
index defec5ef..32c1e2fc 100644
--- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java
+++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java
@@ -215,7 +215,7 @@ public class arm extends Machine {
public static void f_cmp(Encoding enc, Node n) {
short reg1 = (short)(enc.reg(n.in(1))-D_OFFSET);
short reg2 = (short)(enc.reg(n.in(2))-D_OFFSET);
- int body = Arm64.f_cmp(0b00011110, 3, reg1, reg2);
+ int body = Arm64.f_cmp(0b00011110, 3, reg2, reg1);
enc.add4(body);
}
diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NotRISC.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NotRISC.java
index dbe9ceb0..6f499db1 100644
--- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NotRISC.java
+++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/NotRISC.java
@@ -15,7 +15,8 @@ public class NotRISC extends MachConcreteNode implements MachNode {
@Override public void encoding( Encoding enc ) {
short dst = enc.reg(this );
short src = enc.reg(in(1));
- enc.add4(RiscV.i_type(RiscV.OP_IMM, dst, 2, src, 1));
+ // SEQZ is unsigned: negative nonzero inputs must also produce false.
+ enc.add4(RiscV.i_type(RiscV.OP_IMM, dst, 3, src, 1));
}
@Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)); }
}
diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetIRISC.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetIRISC.java
index 690e2102..9bc86565 100644
--- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetIRISC.java
+++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/SetIRISC.java
@@ -7,7 +7,11 @@ import com.seaofnodes.simple.node.Node;
public class SetIRISC extends ImmRISC {
final boolean _unsigned; // slti vs sltiu
public SetIRISC( Node src, int imm12, boolean unsigned ) {
- super(src,imm12);
+ this(src,imm12,unsigned,true);
+ }
+ public SetIRISC( Node src, int imm12, boolean unsigned, boolean pop ) {
+ super(src,imm12,pop);
+ if( !pop ) _inputs.setLen(2);
_unsigned = unsigned;
}
@Override public String op() { return "slt" + (_unsigned ? "u":"") + "i"; }
diff --git a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java
index 78d21f3b..7c994624 100644
--- a/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java
+++ b/chapter24/src/main/java/com/seaofnodes/simple/node/cpus/riscv/riscv.java
@@ -305,7 +305,7 @@ public class riscv extends Machine {
// x <= y - flip and negate; !(y < x); `slt tmp=y,x; xori dst=tmp,#1`
case "<=" -> new XorIRISC(new SetRISC(bool.swap12(), false),1,false);
// x == y - sub and vs0 == `sub tmp=x-y; sltu dst=tmp,#1`
- case "==" -> new SetIRISC(new SubRISC(bool),1,true);
+ case "==" -> new SetIRISC(new SubRISC(bool),1,true,false);
default -> throw Utils.TODO();
};
}
diff --git a/chapter24/src/test/java/com/seaofnodes/simple/Chapter24Test.java b/chapter24/src/test/java/com/seaofnodes/simple/Chapter24Test.java
index bb89aa16..9a657855 100644
--- a/chapter24/src/test/java/com/seaofnodes/simple/Chapter24Test.java
+++ b/chapter24/src/test/java/com/seaofnodes/simple/Chapter24Test.java
@@ -585,17 +585,21 @@ return 0 < arg < arg+1 < 4;
""";
TestC.run(src, "stacked_r_13x", null, stack12,0);
- // Evaluate on RISC5 emulator
+ // Compile once per target, then check false, true and negative inputs.
EvalRisc5 R5 = TestRisc5.build("stacked_r_13", src2, 1, 0, false);
- int trap = R5.step(100);
- assertEquals(0,trap);
- assertEquals(1,R5.regs[riscv.A0]);
-
- // Evaluate on ARM emulator
+ for( int arg : new int[]{-1,0,1} ) {
+ R5._pc = 0;
+ R5.regs[riscv.A0] = arg;
+ assertEquals(0,R5.step(100));
+ assertEquals(arg==0 ? 1 : 0,R5.regs[riscv.A0]);
+ }
EvalArm64 arm = TestArm64.build("stacked_r_13", src2, 1, 0, false);
- trap = arm.step(100);
- assertEquals(0,trap);
- assertEquals(1,arm.regs[0]);
+ for( int arg : new int[]{-1,0,1} ) {
+ arm._pc = 0;
+ arm.regs[0] = arg;
+ assertEquals(0,arm.step(100));
+ assertEquals(arg==0 ? 1 : 0,arm.regs[0]);
+ }
}
@Test