From 40b33cb6f8b8dc4d8551c3b522e7c5682a44540a Mon Sep 17 00:00:00 2001 From: Cliff Click Date: Sun, 20 Sep 2026 22:38:58 -0700 Subject: Final reg-alloc across chapters cleanup --- chapter25/Makefile | 6 + chapter25/README.md | 63 ++++++ .../java/com/seaofnodes/simple/codegen/IFG.java | 2 +- .../seaofnodes/simple/node/cpus/arm/LoadARM.java | 10 +- .../seaofnodes/simple/node/cpus/arm/MemOpARM.java | 11 +- .../seaofnodes/simple/node/cpus/arm/StoreARM.java | 8 +- .../com/seaofnodes/simple/node/cpus/arm/arm.java | 2 +- .../java/com/seaofnodes/simple/Chapter20Test.java | 17 ++ .../java/com/seaofnodes/simple/Chapter21Test.java | 28 +++ .../java/com/seaofnodes/simple/Chapter25Test.java | 3 +- .../test/java/com/seaofnodes/simple/EvalArm64.java | 14 +- .../java/com/seaofnodes/simple/SpillStats.java | 92 +++++++++ .../src/test/java/com/seaofnodes/simple/TestC.java | 5 +- .../simple/codegen/RegAllocTestSupport.java | 14 ++ .../simple/spill/BrainFuckTest-testBrainFuck.smp | 46 +++++ .../simple/spill/Chapter20Test-testAlloc0.smp | 1 + .../simple/spill/Chapter20Test-testAlloc2.smp | 1 + .../simple/spill/Chapter20Test-testArray1.smp | 8 + .../simple/spill/Chapter20Test-testBasic1.smp | 1 + .../simple/spill/Chapter20Test-testBrainfuck.smp | 43 ++++ .../simple/spill/Chapter20Test-testCast.smp | 1 + .../simple/spill/Chapter20Test-testFlags1.smp | 5 + .../simple/spill/Chapter20Test-testFlags2.smp | 6 + .../simple/spill/Chapter20Test-testFltArg.smp | 1 + .../simple/spill/Chapter20Test-testMergeSort.smp | 46 +++++ .../simple/spill/Chapter20Test-testNewtonFloat.smp | 11 ++ .../spill/Chapter20Test-testNewtonInteger.smp | 10 + .../simple/spill/Chapter20Test-testString.smp | 35 ++++ .../simple/spill/Chapter21AllocTest-testArray1.smp | 9 + .../spill/Chapter21AllocTest-testNewtonFloat.smp | 13 ++ .../simple/spill/Chapter21AllocTest-testString.smp | 31 +++ .../simple/spill/Chapter21Test-testAntiDeps1.smp | 10 + .../simple/spill/Chapter21Test-testArgCount-2.smp | 6 + .../simple/spill/Chapter21Test-testArgCount.smp | 6 + .../simple/spill/Chapter21Test-testFibExport.smp | 10 + .../simple/spill/Chapter21Test-testInfinite.smp | 1 + .../simple/spill/Chapter21Test-testLoop2.smp | 9 + .../spill/Chapter21Test-testNewtonExport.smp | 10 + .../simple/spill/Chapter21Test-testPerson.smp | 9 + .../simple/spill/Chapter21Test-testSieve.smp | 30 +++ .../spill/Chapter21Test-testStringExport.smp | 29 +++ .../simple/spill/Chapter22Test-testHelloWorld.smp | 4 + .../spill/Chapter22Test-testInfiniteReturn.smp | 1 + .../simple/spill/Chapter22Test-testPerson.smp | 8 + .../simple/spill/Chapter22Test-testSextFail.smp | 4 + .../simple/spill/Chapter22Test-testSextFail2.smp | 5 + .../simple/spill/Chapter22Test-testSextSuccess.smp | 5 + .../simple/spill/Chapter23AllocTest-testJig21.smp | 16 ++ .../simple/spill/Chapter23AllocTest-testString.smp | 30 +++ .../simple/spill/Chapter23Test-testAnd.smp | 11 ++ .../simple/spill/Chapter23Test-testAndPtr.smp | 12 ++ .../spill/Chapter23Test-testCondSideEffAnd.smp | 17 ++ .../spill/Chapter23Test-testCondSideEffOr.smp | 24 +++ .../simple/spill/Chapter23Test-testFRefFields.smp | 20 ++ .../simple/spill/Chapter23Test-testFuncCall.smp | 16 ++ .../simple/spill/Chapter23Test-testMethod.smp | 17 ++ .../simple/spill/Chapter23Test-testOr.smp | 13 ++ .../spill/Chapter23Test-testOrRhsLoopLocal.smp | 10 + .../spill/Chapter23Test-testOrRhsLoopMemory.smp | 11 ++ .../spill/Chapter24AllocTest-testBubbleSort.smp | 217 +++++++++++++++++++++ .../simple/spill/Chapter24AllocTest-testJig21.smp | 16 ++ .../simple/spill/Chapter24AllocTest-testJig22.smp | 15 ++ .../spill/Chapter24AllocTest-testNewtonInteger.smp | 11 ++ .../Chapter24AllocTest-testStackArguments.smp | 5 + .../simple/spill/Chapter24Test-testJig.smp | 1 + .../simple/spill/Chapter24Test-testStack1.smp | 10 + .../simple/spill/Chapter24Test-testStack10-2.smp | 1 + .../simple/spill/Chapter24Test-testStack10.smp | 3 + .../simple/spill/Chapter24Test-testStack11-2.smp | 1 + .../simple/spill/Chapter24Test-testStack11.smp | 3 + .../simple/spill/Chapter24Test-testStack12-2.smp | 1 + .../simple/spill/Chapter24Test-testStack12.smp | 3 + .../simple/spill/Chapter24Test-testStack13-2.smp | 1 + .../simple/spill/Chapter24Test-testStack13.smp | 3 + .../simple/spill/Chapter24Test-testStack2.smp | 10 + .../simple/spill/Chapter24Test-testStack3.smp | 11 ++ .../simple/spill/Chapter24Test-testStack4.smp | 10 + .../simple/spill/Chapter24Test-testStack5.smp | 15 ++ .../simple/spill/Chapter24Test-testStack9-2.smp | 1 + .../simple/spill/Chapter24Test-testStack9.smp | 3 + .../simple/spill/MergeSortTest-testMergeSort0.smp | 35 ++++ .../java/com/seaofnodes/simple/spill/README.md | 40 ++++ .../java/com/seaofnodes/simple/spill/cohorts.tsv | 213 ++++++++++++++++++++ 83 files changed, 1486 insertions(+), 30 deletions(-) create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/SpillStats.java create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/BrainFuckTest-testBrainFuck.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter20Test-testAlloc0.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter20Test-testAlloc2.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter20Test-testArray1.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter20Test-testBasic1.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter20Test-testBrainfuck.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter20Test-testCast.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter20Test-testFlags1.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter20Test-testFlags2.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter20Test-testFltArg.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter20Test-testMergeSort.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter20Test-testNewtonFloat.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter20Test-testNewtonInteger.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter20Test-testString.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21AllocTest-testArray1.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21AllocTest-testNewtonFloat.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21AllocTest-testString.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21Test-testAntiDeps1.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21Test-testArgCount-2.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21Test-testArgCount.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21Test-testFibExport.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21Test-testInfinite.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21Test-testLoop2.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21Test-testNewtonExport.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21Test-testPerson.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21Test-testSieve.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21Test-testStringExport.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter22Test-testHelloWorld.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter22Test-testInfiniteReturn.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter22Test-testPerson.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter22Test-testSextFail.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter22Test-testSextFail2.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter22Test-testSextSuccess.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23AllocTest-testJig21.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23AllocTest-testString.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23Test-testAnd.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23Test-testAndPtr.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23Test-testCondSideEffAnd.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23Test-testCondSideEffOr.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23Test-testFRefFields.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23Test-testFuncCall.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23Test-testMethod.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23Test-testOr.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23Test-testOrRhsLoopLocal.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23Test-testOrRhsLoopMemory.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24AllocTest-testBubbleSort.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24AllocTest-testJig21.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24AllocTest-testJig22.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24AllocTest-testNewtonInteger.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24AllocTest-testStackArguments.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testJig.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack1.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack10-2.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack10.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack11-2.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack11.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack12-2.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack12.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack13-2.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack13.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack2.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack3.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack4.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack5.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack9-2.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack9.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/MergeSortTest-testMergeSort0.smp create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/README.md create mode 100644 chapter25/src/test/java/com/seaofnodes/simple/spill/cohorts.tsv (limited to 'chapter25') diff --git a/chapter25/Makefile b/chapter25/Makefile index 9cacde76..fa743535 100644 --- a/chapter25/Makefile +++ b/chapter25/Makefile @@ -242,3 +242,9 @@ tags: TAGS TAGS: $(main_javas) $(test_javas) @rm -f TAGS @$(CTAGS) -e --recurse=yes --fields=+fksaiS $(SRC) $(TST) + +# Frozen earlier allocation cohorts, followed by Chapter 25's native tests. +spill-stats: $(CLZDIR)/test/.ttag $(TEST_SYS) $(RELEASE_SYS) $(RELEASE_CRT) + @$(JVM) com.seaofnodes.simple.SpillStats + +.PHONY: spill-stats diff --git a/chapter25/README.md b/chapter25/README.md index 971c4746..b6a7ded5 100644 --- a/chapter25/README.md +++ b/chapter25/README.md @@ -122,3 +122,66 @@ the environment; the Makefile currently defaults to x86-64/win64. Compiler changes can invalidate both serialized IR and native code in `sys.o`. Rebuild it before interpreting linked-program test results. A source-only subset is not equivalent to this chapter's full `make tests`. + +## RegAlloc improvements: live-range area and split cost + +Chapter 24 tried cold copies before splitting a loop Phi's hot edges. This +chapter also estimates how much scheduled code a spill frees from register +pressure, divided by the estimated cost of the new copies. Callee-save ranges +cover a whole function. Cloneable constants can be rebuilt nearer their uses. +Copies inside loops cost more: the estimate weights them by `8^loopDepth`. +These are inexpensive approximations, especially for values with many uses. + +The other Chapter 25 conflict-handling rules remain here: direct splitting of +several fixed-register uses and deeper splits for some multi-definition ranges. +Their size thresholds are heuristics, not general invariants to backport to the +first allocator. Shared legality fixes still start in the earliest affected +chapter. The final audit corrected fixed-neighbor color bias in 20-25, narrow +store masks in 20-21, and ARM register-bank/float-memory encoding in 21-25. + +Run `make spill-stats`. Each row uses **Chapter 25's compiler**. The first five +rows preserve the earlier 212 program/target entries, adapted to this chapter's +syntax and library organization; the [fixture notes](src/test/java/com/seaofnodes/simple/spill/README.md) +list those adaptations and the measurement limits. They use optimizer seed 123. +The last row includes nine allocations from `Chapter25Test` at its existing +seeds plus a fresh system-library compilation at the driver's seed 456. Reusing +`sys.o` must not make that substantial workload disappear from the measurements. +These results are from Windows x86-64; earlier cohorts also include RISC-V/ARM +SystemV and x86 SystemV. The reporter prints per-target totals as well. + +| Program cohort | Compilations | Split/move count | Loop-weighted count | +|---|---:|---:|---:| +| Chapter 20 | 39 | 381 | 612 | +| Chapter 21 | 52 | 464 | 1,185 | +| Chapter 22 | 24 | 103 | 131 | +| Chapter 23 | 30 | 122 | 346 | +| Chapter 24 | 67 | 744 | 1,479 | +| Chapter 25 | 10 | 783 | 1,826 | +| **Total** | **222** | **2,597** | **5,579** | + +`_spills` counts retained SplitNodes, including register-to-register moves; +`_spillScaled` applies the loop weight. Neither measures just memory traffic. +The old cohorts are allocation replays with register-legality checks, not reruns +of their native harnesses. `Chapter25Test` still runs its native/result checks. +Use `make -j 4 tests` for the full chapter, including inherited emulator tests. + +### Comments on the measurements + +There is no uniform improvement to claim. Substituting Chapter 24's ranking +while keeping the rest of this compiler unchanged saves five moves on the 221 +client compilations (2,206 / 4,719 versus 2,211 / 4,724), but fails to allocate +the system library within eight rounds. It is therefore an incomplete comparison, +not a lower valid whole-suite total. The existing area/cost ranking is retained; +the round limit and correctness checks are unchanged. The system library itself +contributes 386 moves / 855 weighted moves. + +A trial that favored all multi-use cloneable constants saved one move against +the earlier ranking on those clients, but also failed the fresh library build. +It was rejected. This is why both aggregate statistics and complete compilation +and execution checks matter; a favorable subtotal cannot justify a change. + +The earlier-cohort total rises from Chapter 24's 1,332 / 2,956 to 1,814 / 3,753. +Chapter 25 adds class initializers, module ownership, different escape analysis, +and syntax/library adaptations. These are different machine graphs; the increase +cannot be attributed to allocator quality alone. Compare a heuristic within one +compiler and fixed corpus before drawing conclusions from the chapter tables. diff --git a/chapter25/src/main/java/com/seaofnodes/simple/codegen/IFG.java b/chapter25/src/main/java/com/seaofnodes/simple/codegen/IFG.java index 8d09b58c..8649b68c 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/codegen/IFG.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/codegen/IFG.java @@ -556,7 +556,7 @@ abstract public class IFG { if( reg == -1 && alrg._mask.size1() ) reg = alrg._mask.firstReg(); if( reg != -1 ) { - mask.clr(alrg._reg); + mask.clr(reg); if( mask.size1() ) return mask.firstReg(); } diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/LoadARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/LoadARM.java index f8c9bfef..827db545 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/LoadARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/LoadARM.java @@ -3,7 +3,6 @@ package com.seaofnodes.simple.node.cpus.arm; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.LoadNode; import com.seaofnodes.simple.node.Node; -import com.seaofnodes.simple.type.TypeFloat; import com.seaofnodes.simple.util.SB; // Load memory addressing on ARM @@ -17,20 +16,15 @@ public class LoadARM extends MemOpARM { super(ld, base, idx, off, 0); } @Override public String op() { return "ld"+_sz; } - @Override public RegMask outregmap() { return arm.MEM_MASK; } + @Override public RegMask outregmap() { return size() >= 4 ? arm.MEM_MASK : arm.RMASK; } private static final int[] OP_LOADS = new int[]{ arm.OP_LOAD_IMM_8, arm.OP_LOAD_IMM_16, arm.OP_LOAD_IMM_32, arm.OP_LOAD_IMM_64, }; - private int imm_op() { - return _con == TypeFloat.F32 ? arm.OPF_LOAD_IMM_32 - : _con == TypeFloat.F64 ? arm.OPF_LOAD_IMM_64 - : OP_LOADS[_con.log_size()]; - } private static final int[] OP_LOAD_RS = new int[]{ arm.OP_LOAD_R_8 , arm.OP_LOAD_R_16 , arm.OP_LOAD_R_32 , arm.OP_LOAD_R_64, }; // ldr(immediate - unsigned offset) | ldr(register) @Override public void encoding( Encoding enc ) { - ldst_encode(enc, imm_op(), OP_LOAD_RS[_con.log_size()], this, size()); + ldst_encode(enc, OP_LOADS[Integer.numberOfTrailingZeros(size())], OP_LOAD_RS[_con.log_size()], this, size()); } @Override public void asm(CodeGen code, SB sb) { sb.p(code.reg(this)).p(","); diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/MemOpARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/MemOpARM.java index 25402018..53a0f8cf 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/MemOpARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/MemOpARM.java @@ -46,7 +46,7 @@ public abstract class MemOpARM extends MemOpNode implements MachNode { if( i==1 ) return null; // memory if( i==2 ) return arm.RMASK; // ptr/base if( i==3 ) return arm.RMASK; // off/index - if( i==4 ) return arm.RMASK; // value + if( i==4 ) return size() >= 4 ? arm.MEM_MASK : arm.RMASK; // value return null; // Anti-dependence } @@ -55,6 +55,15 @@ public abstract class MemOpARM extends MemOpNode implements MachNode { short ptr = enc.reg(ptr()); short off = enc.reg(off()); short val = enc.reg(xval); + // The allocated register selects integer vs SIMD/FP encoding, even for + // bitwise copies. ARM numbers each register bank from zero in the opcode. + boolean fp = val >= arm.D0; + assert !fp || size >= 4; + if( fp ) { + opcode_imm |= 1<<4; + opcode_reg |= 1<<5; + val -= arm.D0; + } int body = off() == null ? arm.load_str_imm(opcode_imm, _off, ptr, val, size) : arm.indr_adr(opcode_reg, off, arm.STORE_LOAD_OPTION.SXTX, 0, ptr, val); diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/StoreARM.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/StoreARM.java index b11a2c89..36b6bcdb 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/StoreARM.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/StoreARM.java @@ -3,7 +3,6 @@ package com.seaofnodes.simple.node.cpus.arm; import com.seaofnodes.simple.codegen.*; import com.seaofnodes.simple.node.Node; import com.seaofnodes.simple.node.StoreNode; -import com.seaofnodes.simple.type.TypeFloat; import com.seaofnodes.simple.util.SB; // Store memory addressing on ARM @@ -24,16 +23,11 @@ public class StoreARM extends MemOpARM { @Override public RegMask outregmap() { return null; } private static final int[] OP_STORES = new int[]{ arm.OP_STORE_IMM_8, arm.OP_STORE_IMM_16, arm.OP_STORE_IMM_32, arm.OP_STORE_IMM_64, }; - private int imm_op() { - return val()!=null && val()._type instanceof TypeFloat - ? (_bytes==4 ? arm.OPF_STORE_IMM_32 : arm.OPF_STORE_IMM_64) - : OP_STORES[Integer.numberOfTrailingZeros(_bytes)]; - } private static final int[] OP_STORE_RS = new int[]{ arm.OP_STORE_R_8, arm.OP_STORE_R_16, arm.OP_STORE_R_32, arm.OP_STORE_R_64, }; @Override public void encoding( Encoding enc ) { - ldst_encode(enc, imm_op(), OP_STORE_RS[Integer.numberOfTrailingZeros(_bytes)], val(), size()); + ldst_encode(enc, OP_STORES[Integer.numberOfTrailingZeros(size())], OP_STORE_RS[Integer.numberOfTrailingZeros(_bytes)], val(), size()); } @Override public void asm(CodeGen code, SB sb) { asm_address(code,sb).p(","); diff --git a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java index 510d5e78..d4e10404 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/node/cpus/arm/arm.java @@ -169,7 +169,7 @@ public class arm extends Machine { public static int OPF_STORE_R_64 = 0b11111100001; public static int OPF_STORE_R_32 = 0b10111100001; - public static int OPF_STORE_IMM_32 = 0b1111110100; + public static int OPF_STORE_IMM_32 = 0b1011110100; public static int OPF_STORE_IMM_64 = 0b1111110100; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/Chapter20Test.java b/chapter25/src/test/java/com/seaofnodes/simple/Chapter20Test.java index 647b253e..a9f7dde7 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/Chapter20Test.java +++ b/chapter25/src/test/java/com/seaofnodes/simple/Chapter20Test.java @@ -8,6 +8,23 @@ import org.junit.Test; import static org.junit.Assert.*; public class Chapter20Test { + @Test public void testAllocatorFixedNeighbor() throws Exception { com.seaofnodes.simple.codegen.RegAllocTestSupport.uncoloredFixedNeighbor(); } + + @Test public void testNarrowStoreMasks() { + for( String type : new String[]{"i8","u8","i16","u16"} ) { + CodeGen code = new CodeGen("struct S { "+type+" x; }; S !s=new S; s.x=arg; return 0;") + .driver(CodeGen.Phase.RegAlloc,"x86_64_v2","SystemV"); + int stores=0; + for( var bb : code._cfg ) + for( var node : bb.outs() ) + if( node instanceof com.seaofnodes.simple.node.cpus.x86_64_v2.StoreX86 st && st._name.equals("x") ) { + stores++; + assertEquals(-1,st.regmap(4).nextReg((short)15)); + } + assertTrue(stores>0); + } + } + @Test public void testInlinedReturnValue() { String src = """ struct S { int x; }; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/Chapter21Test.java b/chapter25/src/test/java/com/seaofnodes/simple/Chapter21Test.java index 10d52ea7..c7677345 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/Chapter21Test.java +++ b/chapter25/src/test/java/com/seaofnodes/simple/Chapter21Test.java @@ -10,6 +10,34 @@ import org.junit.Test; import static org.junit.Assert.*; public class Chapter21Test { + @Test public void testArmFloatMemory() throws IOException { + for( String type : new String[]{"f32","f64"} ) { + String src = type+"[] !a=new "+type+"[3]; a[arg]=1.25; return a[1];"; + EvalArm64 cpu = TestArm64.build("probe","val probe={ int arg -> "+src+" };",1,-1,false); + cpu.regs[arm.X0]=1; + assertEquals(0,cpu.step(1000)); + assertEquals(1.25,cpu.fregs[0],0); + } + // Independently exercise both SIMD widths and addressing modes. Keep + // the GPR value different so accidentally reading that bank is visible. + for( boolean wide : new boolean[]{false,true} ) + for( boolean indexed : new boolean[]{false,true} ) { + EvalArm64 cpu = new EvalArm64(new byte[512],256); + cpu.regs[1]=128; cpu.regs[2]=16; cpu.regs[3]=99; + cpu.fregs[3]=-13.25; + int store = (wide ? 0xFD000000 : 0xBD000000) | ((16/(wide?8:4))<<10) | (1<<5) | 3; + if( indexed ) store=(wide ? 0xFC226823 : 0xBC226823); // STR D3/S3,[X1,X2] + cpu.st4(0,store); + cpu.st4(4,store | (1<<22)); // LDR to the same SIMD register. + assertEquals(0,cpu.step(1)); + assertEquals(-13.25,wide ? cpu.ld8f(144) : cpu.ld4f(144),0); + cpu.fregs[3]=0; + assertEquals(0,cpu.step(1)); + assertEquals(-13.25,cpu.fregs[3],0); + } + } + + @Test public void testArmCallInstructions() { EvalArm64 cpu = new EvalArm64(new byte[512],256); for( int delta : new int[]{4,32,-4} ) { diff --git a/chapter25/src/test/java/com/seaofnodes/simple/Chapter25Test.java b/chapter25/src/test/java/com/seaofnodes/simple/Chapter25Test.java index b96ae836..0ac55a9e 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/Chapter25Test.java +++ b/chapter25/src/test/java/com/seaofnodes/simple/Chapter25Test.java @@ -1,6 +1,7 @@ package com.seaofnodes.simple; import com.seaofnodes.simple.codegen.CodeGen; +import com.seaofnodes.simple.codegen.RegAllocTestSupport.CheckedCodeGen; import com.seaofnodes.simple.codegen.ElfReader; import com.seaofnodes.simple.codegen.ParseAll; import com.seaofnodes.simple.type.TypeInteger; @@ -282,7 +283,7 @@ int v0=0^0; String base = "helloWorldNoInline"; String expected = "Hello, World!\n"; String prog = "return sys.io.p_noInline(\""+expected+"\") - "+expected.length()+";"; - CodeGen code = new CodeGen(null,"build/objs",new Ary<>(new String[]{SYS_BLDDIR}), + CodeGen code = new CheckedCodeGen(null,"build/objs",new Ary<>(new String[]{SYS_BLDDIR}), base,prog,123L,true,TypeInteger.BOT); code.driver(TestC.CPU_PORT,TestC.CALL_CONVENTION,false,true); diff --git a/chapter25/src/test/java/com/seaofnodes/simple/EvalArm64.java b/chapter25/src/test/java/com/seaofnodes/simple/EvalArm64.java index aa128b72..e8121927 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/EvalArm64.java +++ b/chapter25/src/test/java/com/seaofnodes/simple/EvalArm64.java @@ -483,7 +483,7 @@ public class EvalArm64 { switch(opc) { case 0x1: { if(opcode1 == arm.OPF_STORE_R_32) { - st4((int)regs[rn] + (int)regs[rm], (int)regs[rdid]); + st4((int)regs[rn] + (int)regs[rm], Float.floatToRawIntBits((float)fregs[rdid])); }else { trap = (2+1); } @@ -522,7 +522,7 @@ public class EvalArm64 { case 0x0: { // store if(opcode1 == arm.OPF_STORE_IMM_32) { - st4((int)rval, (int)regs[rdid]); + st4((int)rval, Float.floatToRawIntBits((float)fregs[rdid])); } else trap = (2+1); rdid = -1; @@ -531,7 +531,7 @@ public class EvalArm64 { case 0x1: { // LDR (immediate) if(opcode1 == arm.OPF_LOAD_IMM_32) { - frval = ld4s((int)rval); + frval = ld4f((int)rval); } else trap = (2+1); break; } @@ -685,7 +685,7 @@ public class EvalArm64 { switch(opc) { case 0x1: { if(opcode1 == arm.OPF_STORE_R_64) { - st8((int)regs[rn] + (int)regs[rm], (int)regs[rdid]); + st8((int)regs[rn] + (int)regs[rm], Double.doubleToRawLongBits(fregs[rdid])); }else { trap = (2+1); } @@ -713,7 +713,7 @@ public class EvalArm64 { int base = ir >> 5 & 0x1F; int imm = (ir >> 10) & 0xFFF; - imm *= 4; + imm *= 8; is_f = true; rval = regs[base] + imm; int opc = (ir >> 22) & 0x3; @@ -723,7 +723,7 @@ public class EvalArm64 { case 0x0: { // store if(opcode1 == arm.OPF_STORE_IMM_64) { - st8((int)rval, regs[rdid]); + st8((int)rval, Double.doubleToRawLongBits(fregs[rdid])); } else trap = (2+1); rdid = -1; @@ -732,7 +732,7 @@ public class EvalArm64 { case 0x1: { // LDR (immediate) if(opcode1 == arm.OPF_LOAD_IMM_64) { - frval = ld8((int)rval); + frval = ld8f((int)rval); } else trap = (2+1); break; } diff --git a/chapter25/src/test/java/com/seaofnodes/simple/SpillStats.java b/chapter25/src/test/java/com/seaofnodes/simple/SpillStats.java new file mode 100644 index 00000000..d43f1a36 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/SpillStats.java @@ -0,0 +1,92 @@ +package com.seaofnodes.simple; + +import com.seaofnodes.simple.codegen.CodeGen; +import com.seaofnodes.simple.codegen.RegAllocTestSupport.CheckedCodeGen; +import com.seaofnodes.simple.type.TypeInteger; +import java.nio.file.*; +import java.util.Map; +import java.util.TreeMap; +import org.junit.runner.*; +import org.junit.runner.notification.*; + +// Earlier cohorts freeze source/target membership; Chapter 25 retains native checks. +public class SpillStats extends RunListener { + private static SpillStats ACTIVE; + private Description _test; + private int _qualityFailures; + private final Map _totals = new TreeMap<>(); + + @Override public void testStarted(Description test) { _test = test; } + @Override public void testFinished(Description test) { _test = null; } + + public static void record25(CodeGen code) { + if( ACTIVE==null || ACTIVE._test==null || ACTIVE._test.getTestClass()!=Chapter25Test.class ) return; + ACTIVE.record(code,"Chapter25",ACTIVE._test.getMethodName(),code._mach.getClass().getSimpleName(),code._callingConv); + } + + private void record(CodeGen code, String cohort, String test, String cpu, String abi) { + for( String key : new String[]{cohort+","+cpu+","+abi,cohort+",ALL,ALL"} ) { + long[] sum = _totals.computeIfAbsent(key,k -> new long[3]); + sum[0]++; sum[1] += code._regAlloc._spills; sum[2] += code._regAlloc._spillScaled; + } + System.out.println("allocation,"+cohort+","+test+","+cpu+","+abi+","+ + code._regAlloc._spills+","+code._regAlloc._spillScaled); + } + + // Keep native result checks running during a quality comparison. + public static void checkSpills(int expected, int actual) { + if( expected==-1 || CodeGen.iterSeedOverridden() ) return; + try { org.junit.Assert.assertEquals("Expect spills:",expected,actual,Math.max(1,expected>>3)); } + catch( AssertionError error ) { + if( ACTIVE==null ) throw error; + ACTIVE._qualityFailures++; + System.err.println(ACTIVE._test+": "+error.getMessage()); + } + } + + public static void main(String[] args) throws Exception { + ACTIVE = new SpillStats(); + Path dir = Path.of("src/test/java/com/seaofnodes/simple/spill"); + int failures=0, attempts=0; + for( String line : Files.readAllLines(dir.resolve("cohorts.tsv")) ) { + if( line.startsWith("#") || line.isBlank() ) continue; + attempts++; + String[] row = line.split("\t"); + try { + String src = Files.readString(dir.resolve(row[5])); + CodeGen code = new CheckedCodeGen(null,null,null,null,src,123L,true,TypeInteger.BOT) + .driver(CodeGen.Phase.RegAlloc,row[2],row[3]); + ACTIVE.record(code,row[0],row[1],row[2],row[3]); + } catch( Throwable error ) { + failures++; + System.err.println(line); + error.printStackTrace(); + } + } + // Include the library's allocation even when make's sys.o is up to date. + try { + CodeGen code = new CheckedCodeGen("src/main/smp","build/spill-sys",null,"sys", + Files.readString(Path.of("src/main/smp/sys.smp")),456L,true,TypeInteger.BOT) + .driver(CodeGen.Phase.Encoding,TestC.CPU_PORT,TestC.CALL_CONVENTION); + ACTIVE.record(code,"Chapter25","sys",TestC.CPU_PORT,TestC.CALL_CONVENTION); + } catch( Throwable error ) { + failures++; + error.printStackTrace(); + } + JUnitCore junit = new JUnitCore(); + junit.addListener(ACTIVE); + Result result = junit.run(Chapter25Test.class); + for( Failure failure : result.getFailures() ) System.err.println(failure.getTrace()); + failures += result.getFailureCount(); + if( failures!=0 ) System.out.println("FAILED: totals are not a complete comparison."); + System.out.println("cohort,cpu,abi,allocations,splits,scaled"); + for( var row : ACTIVE._totals.entrySet() ) { + long[] sum = row.getValue(); + System.out.println(row.getKey()+","+sum[0]+","+sum[1]+","+sum[2]); + } + System.out.println("Historical allocations: "+attempts+"; native tests: "+result.getRunCount()+"; failures: "+failures+"; spill golden failures: "+ACTIVE._qualityFailures); + failures += ACTIVE._qualityFailures; + ACTIVE = null; + if( failures!=0 ) System.exit(1); + } +} \ No newline at end of file diff --git a/chapter25/src/test/java/com/seaofnodes/simple/TestC.java b/chapter25/src/test/java/com/seaofnodes/simple/TestC.java index e0ee701a..44291196 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/TestC.java +++ b/chapter25/src/test/java/com/seaofnodes/simple/TestC.java @@ -125,10 +125,7 @@ public abstract class TestC { linkExe(obj, c_conv, cfile, linkObjs(externPaths), exe); // Allocation quality not degraded - int delta = spills>>3; - if( delta==0 ) delta = 1; - if( spills != -1 && !CodeGen.iterSeedOverridden() ) - assertEquals("Expect spills:",spills,code._regAlloc._spillScaled,delta); + SpillStats.checkSpills(spills,code._regAlloc._spillScaled); return exe; } diff --git a/chapter25/src/test/java/com/seaofnodes/simple/codegen/RegAllocTestSupport.java b/chapter25/src/test/java/com/seaofnodes/simple/codegen/RegAllocTestSupport.java index 038d6882..6c6b9ad5 100644 --- a/chapter25/src/test/java/com/seaofnodes/simple/codegen/RegAllocTestSupport.java +++ b/chapter25/src/test/java/com/seaofnodes/simple/codegen/RegAllocTestSupport.java @@ -29,6 +29,19 @@ public class RegAllocTestSupport { return code; } + public static void uncoloredFixedNeighbor() throws Exception { + CodeGen code = graph(); + RegAlloc alloc = new RegAlloc(code); + Op def = new Op(new RegMask(3L),null,null,false,code._start); + LRG lrg = alloc.newLRG(def,null); + LRG neighbor = new LRG((short)99,null); + neighbor._mask = A; + lrg.addNeighbor(neighbor); // Uncolored, but its only possible color is A. + var bias = IFG.class.getDeclaredMethod("biasColorNeighbors",RegAlloc.class,Node.class,RegMask.class); + bias.setAccessible(true); + assertEquals((short)1,bias.invoke(null,alloc,def,new RegMaskRW(3L,0L))); + } + public static void masks() { for( int reg : new int[]{0,63,64,65,127} ) { RegMask mask = new RegMask(reg); @@ -157,6 +170,7 @@ public class RegAllocTestSupport { @Override public CodeGen regAlloc() { super.regAlloc(); checkRegisters(this); + com.seaofnodes.simple.SpillStats.record25(this); return this; } } diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/BrainFuckTest-testBrainFuck.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/BrainFuckTest-testBrainFuck.smp new file mode 100644 index 00000000..71af2b7a --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/BrainFuckTest-testBrainFuck.smp @@ -0,0 +1,46 @@ +// -*- mode: java; -*- +val brain_fuck = { -> + var !program = "++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++."; + int d = 0; + u8[] !output = new u8[0]; + u8[] !data = new u8[100]; + + for( int pc = 0; pc < program#; pc++ ) { + var command = program[pc]; + if (command == 62) { + d++; + } else if (command == 60) { + d--; + } else if (command == 43) { + data[d]++; + } else if (command == 45) { + data[d]--; + } else if (command == 46) { + // Output a byte; increase the output array size + var old = output; + output = new u8[output# + 1]; + for( int i = 0; i < old#; i++ ) + output[i] = old[i]; + output[old#] = data[d]; // Add the extra byte on the end + } else if (command == 44) { + data[d] = 42; + } else if (command == 91) { + if (data[d] == 0) { + for( int d = 1; d > 0; ) { + command = program[++pc]; + if (command == 91) d++; + if (command == 93) d--; + } + } + } else if (command == 93) { + if (data[d]) { + for( int d = 1; d > 0; ) { + command = program[--pc]; + if (command == 93) d++; + if (command == 91) d--; + } + } + } + } + return output; +}; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter20Test-testAlloc0.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter20Test-testAlloc0.smp new file mode 100644 index 00000000..d85e39e5 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter20Test-testAlloc0.smp @@ -0,0 +1 @@ +return new u8[arg]; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter20Test-testAlloc2.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter20Test-testAlloc2.smp new file mode 100644 index 00000000..864bcdc8 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter20Test-testAlloc2.smp @@ -0,0 +1 @@ +int[] !xs = new int[3]; xs[arg]=1; return xs[arg&1]; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter20Test-testArray1.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter20Test-testArray1.smp new file mode 100644 index 00000000..7f3bd007 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter20Test-testArray1.smp @@ -0,0 +1,8 @@ +int[] !ary = new int[arg]; +// Fill [0,1,2,3,4,...] +for( int i=0; i 0; ) { + command = program[++pc]; + if (command == 91) d++; + if (command == 93) d--; + } + } + } else if (command == 93) { + if (data[d]) { + for( int d = 1; d > 0; ) { + command = program[--pc]; + if (command == 93) d++; + if (command == 91) d--; + } + } + } +} +return output; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter20Test-testCast.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter20Test-testCast.smp new file mode 100644 index 00000000..19c36ebb --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter20Test-testCast.smp @@ -0,0 +1 @@ +struct Bar { int x; }; var b = arg ? new Bar; return b ? b.x++ + b.x++ : -1; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter20Test-testFlags1.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter20Test-testFlags1.smp new file mode 100644 index 00000000..f630e959 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter20Test-testFlags1.smp @@ -0,0 +1,5 @@ +bool b1 = arg == 1; +bool b2 = arg == 2; +if (b2) if (b1) return 1; +if (b1) return 2; +return 0; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter20Test-testFlags2.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter20Test-testFlags2.smp new file mode 100644 index 00000000..70bfc226 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter20Test-testFlags2.smp @@ -0,0 +1,6 @@ +bool b1 = arg == 1; +while (arg > 0) { + arg--; + if (b1) arg--; +} +return arg; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter20Test-testFltArg.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter20Test-testFltArg.smp new file mode 100644 index 00000000..caa11f12 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter20Test-testFltArg.smp @@ -0,0 +1 @@ +return {int i, flt f, int j->return i+f+j;}; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter20Test-testMergeSort.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter20Test-testMergeSort.smp new file mode 100644 index 00000000..eddf1799 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter20Test-testMergeSort.smp @@ -0,0 +1,46 @@ +// based on the top-down version from https://en.wikipedia.org/wiki/Merge_sort + +val merge_sort = { int[] a, int[] b, int n -> + copy_array(a, 0, n, b); + split_merge(a, 0, n, b); +}; + +val split_merge = { int[] b, int begin, int end, int[] a -> + if (end - begin <= 1) + return 0; + int middle = (end + begin) / 2; + split_merge(a, begin, middle, b); + split_merge(a, middle, end, b); + merge(b, begin, middle, end, a); + return 0; +}; + +val merge = { int[] b, int begin, int middle, int end, int[] a -> + int i = begin, j = middle; + + for (int k = begin; k < end; k++) { + // && and || + bool cond = false; + if (i < middle) { + if (j >= end) cond = true; + else if (a[i] <= a[j]) cond = true; + } + if (cond) b[k] = a[i++]; + else b[k] = a[j++]; + } +}; + +val copy_array = { int[] a, int begin, int end, int[] b -> + for (int k = begin; k < end; k++) + b[k] = a[k]; +}; + +int[] !a = new int[arg]; +int[] !b = new int[a#]; + +for (int i = 0; i < a#; i++) + a[i] = a# - i; + +merge_sort(a, b, a#); + +return a; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter20Test-testNewtonFloat.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter20Test-testNewtonFloat.smp new file mode 100644 index 00000000..7fa66a33 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter20Test-testNewtonFloat.smp @@ -0,0 +1,11 @@ +// Newtons approximation to the square root +val sqrt = { flt x -> + 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); diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter20Test-testNewtonInteger.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter20Test-testNewtonInteger.smp new file mode 100644 index 00000000..b97da1f3 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter20Test-testNewtonInteger.smp @@ -0,0 +1,10 @@ +// Newtons approximation to the square root +val sqrt = { int x -> + int guess = x; + while( 1 ) { + int next = (x/guess + guess)/2; + if( next == guess ) return guess; + guess = next; + } +}; +return sqrt(arg) + sqrt(arg+2); diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter20Test-testString.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter20Test-testString.smp new file mode 100644 index 00000000..8c56636f --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter20Test-testString.smp @@ -0,0 +1,35 @@ +struct String { + u8[] cs; + new String={ u8[] b -> cs=b; }; + int _hashCode; +}; + +val equals = { String self, String s -> + if( self == s ) return true; + if( self.cs# != s.cs# ) return false; + for( int i=0; i< self.cs#; i++ ) + if( self.cs[i] != s.cs[i] ) + return false; + return true; +}; + +val hashCode = { String self -> + self._hashCode + ? self._hashCode + : (self._hashCode = _hashCodeString(self)); +}; + +val _hashCodeString = { String self -> + int hash=0; + if( self.cs ) { + for( int i=0; i< self.cs#; i++ ) + hash = hash*31 + self.cs[i]; + } + if( !hash ) hash = 123456789; + return hash; +}; + +String !s = new String(new u8[17]); +s.cs[0] = 67; // C +s.cs[1] = 108; // l +hashCode(s); diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21AllocTest-testArray1.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21AllocTest-testArray1.smp new file mode 100644 index 00000000..6b10f92c --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21AllocTest-testArray1.smp @@ -0,0 +1,9 @@ +// -*- mode: java; -*- +int[] !ary = new int[arg]; +// Fill [0,1,2,3,4,...] +for( int i=0; i + flt epsilon = 1e-15; + flt guess = x; + while( 1 ) { + flt next = (x/guess + guess)/2; + if( guess-epsilon <= next & next <= guess+epsilon ) return guess; + //if( guess==next ) return guess; + guess = next; + } +}; +flt farg = arg; return test_sqrt(farg) + test_sqrt(farg+2.0); diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21AllocTest-testString.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21AllocTest-testString.smp new file mode 100644 index 00000000..dafa7456 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21AllocTest-testString.smp @@ -0,0 +1,31 @@ +// -*- mode: java; -*- +struct String { + u8[] cs; + int _hashCode; +}; + +// Compare two Strings +val equals = { String self, String s -> + if( self == s ) return true; + if( self.cs# != s.cs# ) return false; + for( int i=0; i< self.cs#; i++ ) + if( self.cs[i] != s.cs[i] ) + return false; + return true; +}; + +// Return the String hashCode (cached, and never 0) +val hashCode = { String self -> + self._hashCode + ? self._hashCode + : (self._hashCode = _hashCodeString(self)); +}; + +val _hashCodeString = { String self -> + int hash=0; + if( self.cs ) + for( int i=0; i< self.cs#; i++ ) + hash = hash*31 + self.cs[i]; + if( !hash ) hash = 123456789; + return hash; +}; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21Test-testAntiDeps1.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21Test-testAntiDeps1.smp new file mode 100644 index 00000000..baf77c92 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21Test-testAntiDeps1.smp @@ -0,0 +1,10 @@ +struct S { int f; }; +var v0 = new S; +S? v1; +if (arg) v1 = new S; +if (v1) { + v0.f = v1.f; +} else { + v0.f = 2; +} +return v0; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21Test-testArgCount-2.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21Test-testArgCount-2.smp new file mode 100644 index 00000000..20a05445 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21Test-testArgCount-2.smp @@ -0,0 +1,6 @@ +// -*- mode: java; -*- +val addAll = { int i0, flt f1, int i2, flt f3, int i4, flt f5, int i6, flt f7, int x8, flt f9, int i10, flt f11, int i12, flt f13, int i14, flt f15 -> + return + i0 + f1+ i2+ f3+ i4+ f5+ i6+ f7+ x8 +f9 + + i10+f11+i12+f13+i14+f15; +}; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21Test-testArgCount.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21Test-testArgCount.smp new file mode 100644 index 00000000..6b6bc0ae --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21Test-testArgCount.smp @@ -0,0 +1,6 @@ +// -*- mode: java; -*- +val addAll = { int i0, flt f1, int i2, flt f3, int i4, flt f5, int i6, flt f7, int x8, flt f9, int i10, flt f11, int i12, flt f13, int i14, flt f15, int x16, flt f17 int x18, flt f19 -> + return + i0 + f1+ i2+ f3+ i4+ f5+ i6+ f7+ x8 +f9 + + i10+f11+i12+f13+i14+f15+x16+f17+x18+f19 ; +}; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21Test-testFibExport.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21Test-testFibExport.smp new file mode 100644 index 00000000..149872a7 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21Test-testFibExport.smp @@ -0,0 +1,10 @@ +val fib = {int n -> + int f1=1; + int f2=1; + while( n-- > 1 ){ + int temp = f1+f2; + f1=f2; + f2=temp; + } + return f2; +}; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21Test-testInfinite.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21Test-testInfinite.smp new file mode 100644 index 00000000..1e4557d3 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21Test-testInfinite.smp @@ -0,0 +1 @@ +struct S { int i; }; S !s = new S; while(1) s.i++; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21Test-testLoop2.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21Test-testLoop2.smp new file mode 100644 index 00000000..cc54f790 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21Test-testLoop2.smp @@ -0,0 +1,9 @@ +int i = 0; +while(true) { + i += 1; + if( i==0 ) continue; + if( i==1 ) continue; + if( i==2 ) break; + continue; +} +return i; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21Test-testNewtonExport.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21Test-testNewtonExport.smp new file mode 100644 index 00000000..2786558e --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21Test-testNewtonExport.smp @@ -0,0 +1,10 @@ +val test_sqrt = { flt x -> + flt epsilon = 1e-15; + flt guess = x; + while( 1 ) { + flt next = (x/guess + guess)/2; + if( guess-epsilon <= next & next <= guess+epsilon ) return guess; + //if( guess==next ) return guess; + guess = next; + } +}; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21Test-testPerson.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21Test-testPerson.smp new file mode 100644 index 00000000..06c2861e --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21Test-testPerson.smp @@ -0,0 +1,9 @@ +// -*-java-*- +struct Person { + int age; +}; + +val fcn = { Person?[] ps, int x -> + if( ps[x] ) + ps[x].age++; +}; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21Test-testSieve.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21Test-testSieve.smp new file mode 100644 index 00000000..beb0b3ad --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21Test-testSieve.smp @@ -0,0 +1,30 @@ +val sieve = { int N -> + // The main Sieve array + bool[] !ary = new bool[N]; + // The primes less than N + u32[] !primes = new u32[N>>1]; + // Number of primes so far, searching at index p + int nprimes = 0, p=2; + // Find primes while p^2 < N + while( p*p < N ) { + // skip marked non-primes + while( ary[p] ) p++; + // p is now a prime + primes[nprimes++] = p; + // Mark out the rest non-primes + for( int i = p + p; i < ary#; i+= p ) + ary[i] = true; + p++; + } + + // Now just collect the remaining primes, no more marking + for( ; p < N; p++ ) + if( !ary[p] ) + primes[nprimes++] = p; + + // Copy/shrink the result array + u32[] !rez = new u32[nprimes]; + for( int j=0; j < nprimes; j++ ) + rez[j] = primes[j]; + return rez; +}; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21Test-testStringExport.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21Test-testStringExport.smp new file mode 100644 index 00000000..6cc28315 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter21Test-testStringExport.smp @@ -0,0 +1,29 @@ +struct String { + u8[] cs; + int _hashCode; +}; + +// Compare two Strings +val equals = { String self, String s -> + if( self == s ) return true; + if( self.cs# != s.cs# ) return false; + for( int i=0; i< self.cs#; i++ ) + if( self.cs[i] != s.cs[i] ) + return false; + return true; +}; + +// Return the String hashCode (cached, and never 0) +val hashCode = { String self -> + self._hashCode + ? self._hashCode + : (self._hashCode = _hashCodeString(self)); +}; + +val _hashCodeString = { String self -> + int hash=0; + for( int i=0; i< self.cs#; i++ ) + hash = hash*31 + self.cs[i]; + if( !hash ) hash = 123456789; + return hash; +}; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter22Test-testHelloWorld.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter22Test-testHelloWorld.smp new file mode 100644 index 00000000..1bcac36d --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter22Test-testHelloWorld.smp @@ -0,0 +1,4 @@ +{i32 i64 u32 -> u32} write="C"; +val _p={u8[~] str -> i64 ptr=str; return write(1,ptr,str#);}; +_p("Hello, World!"); +return 0; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter22Test-testInfiniteReturn.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter22Test-testInfiniteReturn.smp new file mode 100644 index 00000000..523fc6f9 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter22Test-testInfiniteReturn.smp @@ -0,0 +1 @@ +struct S { int i; }; S !s = new S; while(1) s.i++; return s.i; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter22Test-testPerson.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter22Test-testPerson.smp new file mode 100644 index 00000000..a3cafc9a --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter22Test-testPerson.smp @@ -0,0 +1,8 @@ +struct Person { + i32 age; +}; + +val fcn = { Person?[] ps, int x -> + if( ps[x] ) + ps[x].age++; +}; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter22Test-testSextFail.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter22Test-testSextFail.smp new file mode 100644 index 00000000..2d431705 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter22Test-testSextFail.smp @@ -0,0 +1,4 @@ +struct Person { i32 age;}; +Person !p = new Person; +p.age = (arg<<17)>>17; +return 0; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter22Test-testSextFail2.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter22Test-testSextFail2.smp new file mode 100644 index 00000000..01e070c8 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter22Test-testSextFail2.smp @@ -0,0 +1,5 @@ + + struct Person { i32 age;}; + Person !p = new Person; + p.age = (arg<<48)>>48; + return 0; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter22Test-testSextSuccess.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter22Test-testSextSuccess.smp new file mode 100644 index 00000000..6d11a431 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter22Test-testSextSuccess.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; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23AllocTest-testJig21.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23AllocTest-testJig21.smp new file mode 100644 index 00000000..f7a5d202 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23AllocTest-testJig21.smp @@ -0,0 +1,16 @@ +// -*- mode: java; -*- +val fib = {int n -> + int temp=0; + int f1=1; + int f2=1; + int i=n; + while( i>1 ){ + temp = f1+f2; + f1=f2; + f2=temp; + i=i-1; + } + return f2; +}; + +fib(10); diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23AllocTest-testString.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23AllocTest-testString.smp new file mode 100644 index 00000000..3fa2174c --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23AllocTest-testString.smp @@ -0,0 +1,30 @@ +// -*- mode: java; -*- +struct String { + u8[] cs; + int _hashCode; +}; + +// Compare two Strings +val equals = { String self, String s -> + if( self == s ) return true; + if( self.cs# != s.cs# ) return false; + for( int i=0; i< self.cs#; i++ ) + if( self.cs[i] != s.cs[i] ) + return false; + return true; +}; + +// Return the String hashCode (cached, and never 0) +val hashCode = { String self -> + self._hashCode + ? self._hashCode + : (self._hashCode = _hashCodeString(self)); +}; + +val _hashCodeString = { String self -> + int hash=0; + for( int i=0; i< self.cs#; i++ ) + hash = hash*31 + self.cs[i]; + if( !hash ) hash = 123456789; + return hash; +}; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23Test-testAnd.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23Test-testAnd.smp new file mode 100644 index 00000000..da85ef0e --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23Test-testAnd.smp @@ -0,0 +1,11 @@ +{i32 i64 u32 -> u32} write="C"; +val _p={u8[~] str -> i64 ptr=str; return write(1,ptr,str#);}; +int a = 1; +int b = 1; + +if(a && b) { + _p("And"); +} else { + _p("Or"); +} +return 0; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23Test-testAndPtr.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23Test-testAndPtr.smp new file mode 100644 index 00000000..5d300ede --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23Test-testAndPtr.smp @@ -0,0 +1,12 @@ +{i32 i64 u32 -> u32} write="C"; +val _p={u8[~] str -> i64 ptr=str; return write(1,ptr,str#);}; +struct S { S? fld; new S={ S? f -> fld=f; }; }; + +val ptr = arg == 1 ? null : new S(arg==1 ? null : new S(null)); +if( ptr && ptr.fld ) { + _p("true"); +} else { + _p("false"); +} + +return 0; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23Test-testCondSideEffAnd.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23Test-testCondSideEffAnd.smp new file mode 100644 index 00000000..1a6b5cf3 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23Test-testCondSideEffAnd.smp @@ -0,0 +1,17 @@ +{i32 i64 u32 -> u32} write="C"; +val _p={u8[~] str -> i64 ptr=str; return write(1,ptr,str#);}; +int a = 1; +int b = 1; + +int x=1; +int y=1; +int z=0; + +int g = x++ && y++ && z++; + +if(x == 2 && y == 2 && z == 1 && g == 0) { + _p("Effected"); +} else { + _p("Not effected"); +} +return 0; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23Test-testCondSideEffOr.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23Test-testCondSideEffOr.smp new file mode 100644 index 00000000..f2bb16c5 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23Test-testCondSideEffOr.smp @@ -0,0 +1,24 @@ +{i32 i64 u32 -> u32} write="C"; +val _p={u8[~] str -> i64 ptr=str; return write(1,ptr,str#);}; +int a = 1; +int b = 1; + +int x = -1; +int y=1; +int z= -1; + +int g = x++ || y++ || z++; + +int switch = 0; +if(x == 4 || y == 4 || z == 4) { + switch = -1; +} else { + switch = 1; +} +int cd = 1; +if((x == 0 && y == 1 && z==-1) && switch && g) { + _p("Effected"); +} else { + _p("Not effected"); +} +return 0; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23Test-testFRefFields.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23Test-testFRefFields.smp new file mode 100644 index 00000000..8eb86522 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23Test-testFRefFields.smp @@ -0,0 +1,20 @@ +// A hypothetical scanner class +struct Scan { + int !x; + u8[~] buf; + new Scan={ u8[~] b -> buf=b; }; + // Skip whitespace + val skip = { -> + while( buf[x] <= ' ' ) + x++; + }; + // Peek a character; if matched consume it, else false. + val peek = { u8 c -> + skip(); + if( buf[x] != c ) return false; + x++; + return true; + }; +}; +Scan !s = new Scan(" q"); +return s.peek('q'); diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23Test-testFuncCall.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23Test-testFuncCall.smp new file mode 100644 index 00000000..b522a811 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23Test-testFuncCall.smp @@ -0,0 +1,16 @@ +{i32 i64 u32 -> u32} write="C"; +val _p={u8[~] str -> i64 ptr=str; return write(1,ptr,str#);}; +// -*- mode: java; -*- +int a = 1; +int b = 1; + +var sq = { int x -> + x*x; +}; + +if(a && sq(0)) { + _p("And"); +} else { + _p("Or"); +} +return 0; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23Test-testMethod.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23Test-testMethod.smp new file mode 100644 index 00000000..3ba33216 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23Test-testMethod.smp @@ -0,0 +1,17 @@ +// A hypothetical scanner class +struct Scan { + int !x; + u8[~] buf; + new Scan={ u8[~] b -> buf=b; }; + // Skip whitespace + val skip = { -> + while( buf[x] <= ' ' ) + x++; + }; + val require = { u8 ch -> + skip(); + buf[x++]==ch; + }; +}; +Scan !s = new Scan(" [1,2]"); +return s.require('['); diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23Test-testOr.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23Test-testOr.smp new file mode 100644 index 00000000..dbab1ae5 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23Test-testOr.smp @@ -0,0 +1,13 @@ +{i32 i64 u32 -> u32} write="C"; +val _p={u8[~] str -> i64 ptr=str; return write(1,ptr,str#);}; +int a = 1; +int b = 0; + +if(a++ || b++ ) { + if(b == 0 && a == 2) { + _p("Or"); + } +} else{ + _p("And"); +} +return 0; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23Test-testOrRhsLoopLocal.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23Test-testOrRhsLoopLocal.smp new file mode 100644 index 00000000..a4c8a9f5 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23Test-testOrRhsLoopLocal.smp @@ -0,0 +1,10 @@ +struct S { int f; }; +int x=0; +int result=arg&1; +if(!result) { + S !s=new S; + while(x<3) x++; + s.f=++x; + result=!!s.f; +} +return x*10+result; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23Test-testOrRhsLoopMemory.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23Test-testOrRhsLoopMemory.smp new file mode 100644 index 00000000..775b92b5 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter23Test-testOrRhsLoopMemory.smp @@ -0,0 +1,11 @@ +struct S { int f; }; +S !s=new S; +int result=arg&1; +if(!result) { + S !t=new S; + while(s.f<3) s.f++; + s.f++; + t.f=s.f; + result=!!t.f; +} +return s.f*10+result; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24AllocTest-testBubbleSort.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24AllocTest-testBubbleSort.smp new file mode 100644 index 00000000..a61ca332 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24AllocTest-testBubbleSort.smp @@ -0,0 +1,217 @@ + + i32 errno = "C"; + // fd buf len -> len + { i32 i64 u32 -> u32 } write = "C"; + // fd buf len -> len + { i32 i64 u32 -> u32 } read = "C"; + // status + { i32 -> i32 } _exit = "C"; + // addr len prot flags fd off -> void* + { i64 i64 i32 i32 i32 i32 -> i64 } mmap = "C"; + // mmap flags + i32 PROT_EXEC = 4; + i32 PROT_READ = 1; + i32 PROT_WRITE= 2; + i32 PROT_NONE = 0; + i32 MAP_PRIVATE = 2; + i32 MAP_ANON = 32; + + val copy = { u8[] dst, int doff, u8[~] src, int soff, int len -> + for( int i=0; i buf=b; }; + // Grow as needed + val _grow = { int len2 -> + if( len+len2 < buf# ) return self; + int newlen = buf# * 2; + while( len+len2 >= newlen ) newlen *= 2; + u8[] !buf2 = new u8[newlen]; + copy(buf2,0,buf,0,buf#); + buf = buf2; + self; + }; + + // Add a character to aryu8 + val add = { u8 c -> + _grow(1).buf[len++] = c; + self; + }; + + // Add a plain array to the aryu8 + val addAry = { u8[~] ary -> + _grow(ary#); + copy(buf,len,ary,0,ary#); + len += ary#; + self; + }; + + // Remove x chars from the tail. + val undo = { int x -> + len = len >= x ? len-x : 0; + self; + }; + + // Print ASCII number into aryu8 + val num = { i64 x -> + if( !x ) { add('0'); return self; } + if( x < 0 ) { add('-'); x = -x; } + i64 ten = 1, log = 0; + while( ten <= x ) { ten *= 10; log++; } + for( int i=0; i i64 ptr = buf; write(fd,ptr,len); }; + }; +struct Scan { + int !x; + u8[~] buf; + new Scan={ u8[~] b -> buf=b; }; + + // Skip whitespace + val skip = { -> + while( buf[x] <= ' ' ) + x++; + return self; + }; + + // True if find required character, and skip it; else False. + val match = { u8 c -> + skip(); + if( buf[x] != c ) return false; + x++; + return true; + }; + + // Parse a simple number + val number = { -> + skip(); + bool neg = match('-'); + i64 n = 0; + while( '0' <= buf[x] & buf[x] <= '9' ) + n = n*10 + (buf[x++] - '0'); + return neg ? -n : n; + }; + }; +struct aryi64 { + u32 !len = 0; + i64[] !buf; + new aryi64={ i64[] b -> buf=b; }; + // Grow as needed + val _grow = { int len2 -> + if( len+len2 < buf# ) return self; + int newlen = buf# * 2; + while( len+len2 >= newlen ) newlen *= 2; + i64[] !buf2 = new i64[newlen]; + for( int i=0; i + _grow(1).buf[len++] = c; + self; + }; + + // Write to aryu8 + val str = { -> + // TODO: clunky default constructor syntax + var str = new aryu8(new u8[1]).add('['); + for( int i=0; i + Scan !s = new Scan(str); + if( !s.match('[') ) return null; + // Array of parsed results + var nums = new aryi64(new i64[1]); + // Parse a list of numbers + if( !s.match(']') ) { // Handle the empty list + // Parse "123, " until a something else + while( s.x < s.buf# ) { + nums.add(s.number()); + if( !s.match(',') ) + break; + }; + if( !s.match(']') ) return null; // Close the list + } + return nums; + }; + + + // Print string to stdout + val p = { u8[~] str -> + i64 ptr = str; // cast array base to i64 + return write(1,ptr,str#); + }; + + // Return stdin as a u8[] + val stdin = { -> + var buf = new u8[8*1024]; + i64 ptr = buf; + int len = 0; + while( true ) { + int rez = read(0,ptr,buf#); + if( rez < 0 ) _exit(errno); + len += rez; + if( rez < buf# ) + break; + _exit(-2); // Need to implement + } + // Compress + var dst = new u8[len]; + return copy(dst,0,buf,0,len); + }; + // -*- mode: java; -*- + +// An implementation of +// https://sampleprograms.io/projects/bubble-sort/ +// +// Bubble sort, with reading (parsing) and writing (formatting) the data. + +val sort = { aryi64 nums -> + var done = false; + while( !done ) { + done = true; + for( var i = 0; i < nums.len-1; i++ ) + if( nums.buf[i] > nums.buf[i+1] ) { + int tmp = nums.buf[i]; + nums.buf[i] = nums.buf[i+1]; + nums.buf[i+1] = tmp; // Swap + done = false; + } + } +}; + +// Read from stdin a line of the form "[ 4, 3, 2, 1]" and print it sorted. +val main = { -> + // Parse array of numbers from stdin + var nums = parseAryI64( stdin() ); + if( !nums ) { + p("stdin must look like [4, 3, 2, 1]"); + return 1; + } + + // Bubble sort array of integers + sort(nums); + + // Print a list of numbers to stdout + nums.str().write(1); + return 0; +}; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24AllocTest-testJig21.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24AllocTest-testJig21.smp new file mode 100644 index 00000000..f09915a1 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24AllocTest-testJig21.smp @@ -0,0 +1,16 @@ +struct s0 { + bool v1; + i16 v2; + int v3; + i8 v4; + byte v5; +}; +while(new s0.v3) + while(new s0.v5< + int temp=0; + int f1=1; + int f2=1; + int i=n; + while( i>1 ){ + temp = f1+f2; + f1=f2; + f2=temp; + i=i-1; + } + return f2; +}; + +fib(10); diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24AllocTest-testNewtonInteger.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24AllocTest-testNewtonInteger.smp new file mode 100644 index 00000000..0423585b --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24AllocTest-testNewtonInteger.smp @@ -0,0 +1,11 @@ +// Newtons approximation to the square root +val sqrt = { int x -> + int guess = x; + while( 1 ) { + int next = (x/guess + guess)/2; + if( next == guess ) return guess; + guess = next; + } +}; +int cast_int = arg+2; +return sqrt(arg) + sqrt(cast_int); diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24AllocTest-testStackArguments.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24AllocTest-testStackArguments.smp new file mode 100644 index 00000000..b7d52dc5 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24AllocTest-testStackArguments.smp @@ -0,0 +1,5 @@ +val addAll = { int i0, flt f1, int i2, flt f3, int i4, flt f5, int i6, flt f7, int x8, flt f9, int i10, flt f11, int i12, flt f13, int i14, flt f15, int x16, flt f17 int x18, flt f19 -> + return + i0 + f1+ i2+ f3+ i4+ f5+ i6+ f7+ x8 +f9 + + i10+f11+i12+f13+i14+f15+x16+f17+x18+f19 ; +}; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testJig.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testJig.smp new file mode 100644 index 00000000..5c9d3aa5 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testJig.smp @@ -0,0 +1 @@ +int v0=0; v0 = arg && 0== 0 !=0; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack1.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack1.smp new file mode 100644 index 00000000..ded92426 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack1.smp @@ -0,0 +1,10 @@ +{i32 i64 u32 -> u32} write="C"; +val _p={u8[~] str -> i64 ptr=str; return write(1,ptr,str#);}; +int something_specific = 11; + +if (10 < something_specific < 20) { + _p("In Range"); +} else { + _p("Out of Range"); +} +return 0; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack10-2.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack10-2.smp new file mode 100644 index 00000000..d9fb38d5 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack10-2.smp @@ -0,0 +1 @@ +return (0 < 1) == (1>0); diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack10.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack10.smp new file mode 100644 index 00000000..f92e5b00 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack10.smp @@ -0,0 +1,3 @@ +var stack10 = { int x -> + (x < 1) == (1>x); +}; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack11-2.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack11-2.smp new file mode 100644 index 00000000..b5aac70b --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack11-2.smp @@ -0,0 +1 @@ +return 0 < arg < arg+1 < 4; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack11.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack11.smp new file mode 100644 index 00000000..f50e3512 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack11.smp @@ -0,0 +1,3 @@ +var stack11 = { int x -> + 0 < x < x+1 < 4; +}; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack12-2.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack12-2.smp new file mode 100644 index 00000000..575d1b4e --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack12-2.smp @@ -0,0 +1 @@ +return 0 != arg != 2; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack12.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack12.smp new file mode 100644 index 00000000..b4f36c2e --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack12.smp @@ -0,0 +1,3 @@ +var stack12 = { int x -> + 0 != x != 2; +}; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack13-2.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack13-2.smp new file mode 100644 index 00000000..9bde9687 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack13-2.smp @@ -0,0 +1 @@ +return 0 == arg == 1; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack13.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack13.smp new file mode 100644 index 00000000..ae7b38a3 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack13.smp @@ -0,0 +1,3 @@ +var stack13 = { int x -> + 0 == x == 1; +}; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack2.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack2.smp new file mode 100644 index 00000000..5590c42f --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack2.smp @@ -0,0 +1,10 @@ +{i32 i64 u32 -> u32} write="C"; +val _p={u8[~] str -> i64 ptr=str; return write(1,ptr,str#);}; +int score = 75; + +if (60 <= score < 90) { + _p("In Range"); +} else { +_p("Out of range"); +} +return 0; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack3.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack3.smp new file mode 100644 index 00000000..6a3db406 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack3.smp @@ -0,0 +1,11 @@ +{i32 i64 u32 -> u32} write="C"; +val _p={u8[~] str -> i64 ptr=str; return write(1,ptr,str#);}; +var sq = { int x -> + x*x; +}; + +int score = 5; + +val str = (sq(2) <= score < sq(3)) ? "In Range" : "Out of range"; +_p(str); +return 0; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack4.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack4.smp new file mode 100644 index 00000000..47623b30 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack4.smp @@ -0,0 +1,10 @@ +{i32 i64 u32 -> u32} write="C"; +val _p={u8[~] str -> i64 ptr=str; return write(1,ptr,str#);}; +int something_specific = 9; + +if (10 < something_specific < 20) { + _p("In Range"); +} else { + _p("Out of Range"); +} +return 0; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack5.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack5.smp new file mode 100644 index 00000000..e4660752 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack5.smp @@ -0,0 +1,15 @@ +{i32 i64 u32 -> u32} write="C"; +val _p={u8[~] str -> i64 ptr=str; return write(1,ptr,str#);}; +var sq = { int x -> + x*x; +}; + +int score = 5; + +if (sq(2) <= score < sq(3)) { +_p("In Range"); +} else { +_p("Out of range"); +} + +return 0; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack9-2.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack9-2.smp new file mode 100644 index 00000000..f54558f5 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack9-2.smp @@ -0,0 +1 @@ +return (0 < 1) == 1; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack9.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack9.smp new file mode 100644 index 00000000..15979be6 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/Chapter24Test-testStack9.smp @@ -0,0 +1,3 @@ +var stack9 = { int x -> + (x < 1) == 1; +}; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/MergeSortTest-testMergeSort0.smp b/chapter25/src/test/java/com/seaofnodes/simple/spill/MergeSortTest-testMergeSort0.smp new file mode 100644 index 00000000..e6478eeb --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/MergeSortTest-testMergeSort0.smp @@ -0,0 +1,35 @@ + val merge_sort = { int[] a -> + int[] !b = new int[a#]; + copy_array (a, 0, a#, b); + split_merge(a, 0, a#, b); + }; + + val split_merge = { int[] b, int begin, int end, int[] a -> + if (end - begin <= 1) + return 0; + int middle = (end + begin) / 2; + split_merge(a, begin, middle, b); + split_merge(a, middle, end, b); + merge(b, begin, middle, end, a); + return 0; + }; + + val merge = { int[] b, int begin, int middle, int end, int[] a -> + int i = begin, j = middle; + + for (int k = begin; k < end; k++) { + // && and || + bool cond = false; + if (i < middle) { + if (j >= end) cond = true; + else if (a[i] <= a[j]) cond = true; + } + if (cond) b[k] = a[i++]; + else b[k] = a[j++]; + } + }; + + val copy_array = { int[] a, int begin, int end, int[] b -> + for (int k = begin; k < end; k++) + b[k] = a[k]; + }; diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/README.md b/chapter25/src/test/java/com/seaofnodes/simple/spill/README.md new file mode 100644 index 00000000..fae44126 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/README.md @@ -0,0 +1,40 @@ +# Historical allocation cohorts + +`cohorts.tsv` freezes the 212 compilation entries measured by Chapter 24's +`SpillStats`: 39, 52, 24, 30, and 67 entries for cohorts 20-24. The source files +are deduplicated by contents and named for their first referring test. The +manifest preserves test identity, target, ABI, and the original stopping phase. +`Win64` becomes `win64`, the Chapter 25 ABI spelling. Argument type is i64 and +the replay seed is 123 throughout. + +These inputs were captured from the Chapter 24 tests before this final audit's +new correctness regressions. They are a stable comparison corpus; changing one +requires explaining the resulting break in comparability. Synthetic allocator +and instruction regressions do not contribute allocations to these cohorts. + +Chapter 25 cannot parse all earlier sources unchanged. Adaptations are explicit: + +- String, Scan, and linked S constructors replace `new S { field=...; }` with + declared constructors and arguments. The explicit-receiver scanner functions + become instance methods, preserving their operations. +- The two short-circuit RHS initializer loops become equivalent guarded blocks, + preserving allocation, side effects, and the final result. +- Simple I/O cases include the old `write` binding and print helper directly. + Bubble Sort includes the old library bodies, with namespace prefixes flattened, + explicit constructors, and mutable replacement buffers. This retains the old + workload instead of substituting Chapter 25's substantially revised example. +- Other source texts, including both original Newton float variants, are retained. + +All entries replay **through RegAlloc**, checking scheduled register constraints. +The historical phase column is provenance, not a promise to run those old native +harnesses in Chapter 25. In particular, the adapted Bubble Sort still exposes a +pre-existing ARM extern-data encoding limitation (`i32 errno="C"; return 0;` is +sufficient to reproduce it). Allocation succeeds; ARM encoding does not. That +separate failure remains in the backport queue. Do not count this corpus as +historical runtime coverage. + +`SpillStats` then compiles the current system library through encoding at seed +456, and runs Chapter25Test with its existing seeds and native checks. Together +these form cohort 25. A library or test failure makes the report fail; partial +totals cannot establish an improvement. The ordinary full chapter suite remains +the execution validation for the current compiler. diff --git a/chapter25/src/test/java/com/seaofnodes/simple/spill/cohorts.tsv b/chapter25/src/test/java/com/seaofnodes/simple/spill/cohorts.tsv new file mode 100644 index 00000000..e1643e39 --- /dev/null +++ b/chapter25/src/test/java/com/seaofnodes/simple/spill/cohorts.tsv @@ -0,0 +1,213 @@ +# cohort test cpu abi original phase source +Chapter20 Chapter20Test.testMergeSort x86_64_v2 SystemV RegAlloc Chapter20Test-testMergeSort.smp +Chapter20 Chapter20Test.testMergeSort riscv SystemV RegAlloc Chapter20Test-testMergeSort.smp +Chapter20 Chapter20Test.testMergeSort arm SystemV RegAlloc Chapter20Test-testMergeSort.smp +Chapter20 Chapter20Test.testNewtonInteger x86_64_v2 SystemV RegAlloc Chapter20Test-testNewtonInteger.smp +Chapter20 Chapter20Test.testNewtonInteger riscv SystemV RegAlloc Chapter20Test-testNewtonInteger.smp +Chapter20 Chapter20Test.testNewtonInteger arm SystemV RegAlloc Chapter20Test-testNewtonInteger.smp +Chapter20 Chapter20Test.testCast x86_64_v2 SystemV RegAlloc Chapter20Test-testCast.smp +Chapter20 Chapter20Test.testCast riscv SystemV RegAlloc Chapter20Test-testCast.smp +Chapter20 Chapter20Test.testCast arm SystemV RegAlloc Chapter20Test-testCast.smp +Chapter20 Chapter20Test.testNewtonFloat x86_64_v2 SystemV RegAlloc Chapter20Test-testNewtonFloat.smp +Chapter20 Chapter20Test.testNewtonFloat riscv SystemV RegAlloc Chapter20Test-testNewtonFloat.smp +Chapter20 Chapter20Test.testNewtonFloat arm SystemV RegAlloc Chapter20Test-testNewtonFloat.smp +Chapter20 Chapter20Test.testBrainfuck x86_64_v2 SystemV RegAlloc Chapter20Test-testBrainfuck.smp +Chapter20 Chapter20Test.testBrainfuck riscv SystemV RegAlloc Chapter20Test-testBrainfuck.smp +Chapter20 Chapter20Test.testBrainfuck arm SystemV RegAlloc Chapter20Test-testBrainfuck.smp +Chapter20 Chapter20Test.testAlloc0 x86_64_v2 SystemV RegAlloc Chapter20Test-testAlloc0.smp +Chapter20 Chapter20Test.testAlloc0 riscv SystemV RegAlloc Chapter20Test-testAlloc0.smp +Chapter20 Chapter20Test.testAlloc0 arm SystemV RegAlloc Chapter20Test-testAlloc0.smp +Chapter20 Chapter20Test.testAlloc2 x86_64_v2 SystemV RegAlloc Chapter20Test-testAlloc2.smp +Chapter20 Chapter20Test.testAlloc2 riscv SystemV RegAlloc Chapter20Test-testAlloc2.smp +Chapter20 Chapter20Test.testAlloc2 arm SystemV RegAlloc Chapter20Test-testAlloc2.smp +Chapter20 Chapter20Test.testArray1 x86_64_v2 SystemV RegAlloc Chapter20Test-testArray1.smp +Chapter20 Chapter20Test.testArray1 riscv SystemV RegAlloc Chapter20Test-testArray1.smp +Chapter20 Chapter20Test.testArray1 arm SystemV RegAlloc Chapter20Test-testArray1.smp +Chapter20 Chapter20Test.testBasic1 x86_64_v2 SystemV RegAlloc Chapter20Test-testBasic1.smp +Chapter20 Chapter20Test.testBasic1 riscv SystemV RegAlloc Chapter20Test-testBasic1.smp +Chapter20 Chapter20Test.testBasic1 arm SystemV RegAlloc Chapter20Test-testBasic1.smp +Chapter20 Chapter20Test.testFlags1 x86_64_v2 SystemV RegAlloc Chapter20Test-testFlags1.smp +Chapter20 Chapter20Test.testFlags1 riscv SystemV RegAlloc Chapter20Test-testFlags1.smp +Chapter20 Chapter20Test.testFlags1 arm SystemV RegAlloc Chapter20Test-testFlags1.smp +Chapter20 Chapter20Test.testFlags2 x86_64_v2 SystemV RegAlloc Chapter20Test-testFlags2.smp +Chapter20 Chapter20Test.testFlags2 riscv SystemV RegAlloc Chapter20Test-testFlags2.smp +Chapter20 Chapter20Test.testFlags2 arm SystemV RegAlloc Chapter20Test-testFlags2.smp +Chapter20 Chapter20Test.testFltArg x86_64_v2 SystemV RegAlloc Chapter20Test-testFltArg.smp +Chapter20 Chapter20Test.testFltArg riscv SystemV RegAlloc Chapter20Test-testFltArg.smp +Chapter20 Chapter20Test.testFltArg arm SystemV RegAlloc Chapter20Test-testFltArg.smp +Chapter20 Chapter20Test.testString x86_64_v2 SystemV RegAlloc Chapter20Test-testString.smp +Chapter20 Chapter20Test.testString riscv SystemV RegAlloc Chapter20Test-testString.smp +Chapter20 Chapter20Test.testString arm SystemV RegAlloc Chapter20Test-testString.smp +Chapter21 Chapter21Test.testFibExport x86_64_v2 win64 Export Chapter21Test-testFibExport.smp +Chapter21 Chapter21Test.testFibExport riscv SystemV Export Chapter21Test-testFibExport.smp +Chapter21 Chapter21Test.testFibExport arm SystemV Export Chapter21Test-testFibExport.smp +Chapter21 Chapter21Test.testAntiDeps1 x86_64_v2 SystemV Encoding Chapter21Test-testAntiDeps1.smp +Chapter21 Chapter21Test.testAntiDeps1 riscv SystemV Encoding Chapter21Test-testAntiDeps1.smp +Chapter21 Chapter21Test.testAntiDeps1 arm SystemV Encoding Chapter21Test-testAntiDeps1.smp +Chapter21 Chapter21Test.testLoop2 x86_64_v2 win64 Encoding Chapter21Test-testLoop2.smp +Chapter21 Chapter21Test.testLoop2 riscv SystemV Encoding Chapter21Test-testLoop2.smp +Chapter21 Chapter21Test.testLoop2 arm SystemV Encoding Chapter21Test-testLoop2.smp +Chapter21 Chapter21Test.testSieve x86_64_v2 win64 Export Chapter21Test-testSieve.smp +Chapter21 Chapter21Test.testSieve riscv SystemV Export Chapter21Test-testSieve.smp +Chapter21 Chapter21Test.testSieve arm SystemV Export Chapter21Test-testSieve.smp +Chapter21 Chapter21Test.testArgCount x86_64_v2 win64 Export Chapter21Test-testArgCount.smp +Chapter21 Chapter21Test.testArgCount riscv SystemV Export Chapter21Test-testArgCount-2.smp +Chapter21 Chapter21Test.testArgCount arm SystemV Export Chapter21Test-testArgCount-2.smp +Chapter21 Chapter21Test.testStringExport x86_64_v2 win64 Export Chapter21Test-testStringExport.smp +Chapter21 Chapter21Test.testInfinite x86_64_v2 SystemV Encoding Chapter21Test-testInfinite.smp +Chapter21 Chapter21Test.testInfinite riscv SystemV Encoding Chapter21Test-testInfinite.smp +Chapter21 Chapter21Test.testInfinite arm SystemV Encoding Chapter21Test-testInfinite.smp +Chapter21 Chapter21Test.testArray1 x86_64_v2 SystemV Encoding Chapter20Test-testArray1.smp +Chapter21 Chapter21Test.testArray1 riscv SystemV Encoding Chapter20Test-testArray1.smp +Chapter21 Chapter21Test.testArray1 arm SystemV Encoding Chapter20Test-testArray1.smp +Chapter21 Chapter21Test.testBasic1 x86_64_v2 SystemV Encoding Chapter20Test-testBasic1.smp +Chapter21 Chapter21Test.testBasic1 riscv SystemV Encoding Chapter20Test-testBasic1.smp +Chapter21 Chapter21Test.testBasic1 arm SystemV Encoding Chapter20Test-testBasic1.smp +Chapter21 Chapter21Test.testNewtonExport x86_64_v2 win64 Export Chapter21Test-testNewtonExport.smp +Chapter21 Chapter21Test.testNewtonExport riscv SystemV Export Chapter21Test-testNewtonExport.smp +Chapter21 Chapter21Test.testNewtonExport arm SystemV Export Chapter21Test-testNewtonExport.smp +Chapter21 Chapter21Test.testPerson x86_64_v2 win64 Export Chapter21Test-testPerson.smp +Chapter21 Chapter21Test.testPerson riscv SystemV Export Chapter21Test-testPerson.smp +Chapter21 Chapter21Test.testPerson arm SystemV Export Chapter21Test-testPerson.smp +Chapter21 Chapter21Test.testString x86_64_v2 SystemV Encoding Chapter21Test-testStringExport.smp +Chapter21 Chapter21Test.testString riscv SystemV Encoding Chapter21Test-testStringExport.smp +Chapter21 Chapter21Test.testString arm SystemV Encoding Chapter21Test-testStringExport.smp +Chapter21 Chapter21AllocTest.testNewtonInteger x86_64_v2 win64 Encoding Chapter20Test-testNewtonInteger.smp +Chapter21 Chapter21AllocTest.testNewtonInteger riscv SystemV Encoding Chapter20Test-testNewtonInteger.smp +Chapter21 Chapter21AllocTest.testNewtonInteger arm SystemV Encoding Chapter20Test-testNewtonInteger.smp +Chapter21 Chapter21AllocTest.testNewtonFloat x86_64_v2 SystemV Encoding Chapter21AllocTest-testNewtonFloat.smp +Chapter21 Chapter21AllocTest.testNewtonFloat riscv SystemV Encoding Chapter21AllocTest-testNewtonFloat.smp +Chapter21 Chapter21AllocTest.testNewtonFloat arm SystemV Encoding Chapter21AllocTest-testNewtonFloat.smp +Chapter21 Chapter21AllocTest.testArray1 x86_64_v2 SystemV Encoding Chapter21AllocTest-testArray1.smp +Chapter21 Chapter21AllocTest.testArray1 riscv SystemV Encoding Chapter21AllocTest-testArray1.smp +Chapter21 Chapter21AllocTest.testArray1 arm SystemV Encoding Chapter21AllocTest-testArray1.smp +Chapter21 Chapter21AllocTest.testString x86_64_v2 SystemV Encoding Chapter21AllocTest-testString.smp +Chapter21 Chapter21AllocTest.testString riscv SystemV Encoding Chapter21AllocTest-testString.smp +Chapter21 Chapter21AllocTest.testString arm SystemV Encoding Chapter21AllocTest-testString.smp +Chapter22 Chapter22Test.testSextFail x86_64_v2 win64 Encoding Chapter22Test-testSextFail.smp +Chapter22 Chapter22Test.testSextFail riscv SystemV Encoding Chapter22Test-testSextFail.smp +Chapter22 Chapter22Test.testSextFail arm SystemV Encoding Chapter22Test-testSextFail.smp +Chapter22 Chapter22Test.testSextFail riscv SystemV Export Chapter22Test-testSextFail.smp +Chapter22 Chapter22Test.testSextFail arm SystemV Export Chapter22Test-testSextFail.smp +Chapter22 Chapter22Test.testSextSuccess riscv SystemV Export Chapter22Test-testSextSuccess.smp +Chapter22 Chapter22Test.testSextSuccess arm SystemV Export Chapter22Test-testSextSuccess.smp +Chapter22 Chapter22Test.testSextSuccess x86_64_v2 win64 Encoding Chapter22Test-testSextSuccess.smp +Chapter22 Chapter22Test.testSextSuccess riscv SystemV Encoding Chapter22Test-testSextSuccess.smp +Chapter22 Chapter22Test.testSextSuccess arm SystemV Encoding Chapter22Test-testSextSuccess.smp +Chapter22 Chapter22Test.testInfiniteReturn x86_64_v2 SystemV Encoding Chapter22Test-testInfiniteReturn.smp +Chapter22 Chapter22Test.testInfiniteReturn riscv SystemV Encoding Chapter22Test-testInfiniteReturn.smp +Chapter22 Chapter22Test.testInfiniteReturn arm SystemV Encoding Chapter22Test-testInfiniteReturn.smp +Chapter22 Chapter22Test.testSextFail2 riscv SystemV Export Chapter22Test-testSextFail2.smp +Chapter22 Chapter22Test.testSextFail2 arm SystemV Export Chapter22Test-testSextFail2.smp +Chapter22 Chapter22Test.testSextFail2 x86_64_v2 win64 Encoding Chapter22Test-testSextFail2.smp +Chapter22 Chapter22Test.testSextFail2 riscv SystemV Encoding Chapter22Test-testSextFail2.smp +Chapter22 Chapter22Test.testSextFail2 arm SystemV Encoding Chapter22Test-testSextFail2.smp +Chapter22 Chapter22Test.testPerson x86_64_v2 win64 Export Chapter22Test-testPerson.smp +Chapter22 Chapter22Test.testPerson riscv SystemV Export Chapter22Test-testPerson.smp +Chapter22 Chapter22Test.testPerson arm SystemV Export Chapter22Test-testPerson.smp +Chapter22 Chapter22Test.testHelloWorld x86_64_v2 win64 Export Chapter22Test-testHelloWorld.smp +Chapter22 Chapter22Test.testHelloWorld riscv SystemV Export Chapter22Test-testHelloWorld.smp +Chapter22 Chapter22Test.testHelloWorld arm SystemV Export Chapter22Test-testHelloWorld.smp +Chapter23 Chapter23Test.testAnd x86_64_v2 win64 Export Chapter23Test-testAnd.smp +Chapter23 Chapter23Test.testAnd riscv SystemV Export Chapter23Test-testAnd.smp +Chapter23 Chapter23Test.testAnd arm SystemV Export Chapter23Test-testAnd.smp +Chapter23 Chapter23Test.testOr x86_64_v2 win64 Export Chapter23Test-testOr.smp +Chapter23 Chapter23Test.testOr riscv SystemV Export Chapter23Test-testOr.smp +Chapter23 Chapter23Test.testOr arm SystemV Export Chapter23Test-testOr.smp +Chapter23 Chapter23Test.testCondSideEffAnd x86_64_v2 win64 Export Chapter23Test-testCondSideEffAnd.smp +Chapter23 Chapter23Test.testCondSideEffAnd riscv SystemV Export Chapter23Test-testCondSideEffAnd.smp +Chapter23 Chapter23Test.testCondSideEffAnd arm SystemV Export Chapter23Test-testCondSideEffAnd.smp +Chapter23 Chapter23Test.testFRefFields x86_64_v2 win64 Encoding Chapter23Test-testFRefFields.smp +Chapter23 Chapter23Test.testAndPtr riscv SystemV Export Chapter23Test-testAndPtr.smp +Chapter23 Chapter23Test.testAndPtr arm SystemV Export Chapter23Test-testAndPtr.smp +Chapter23 Chapter23Test.testOrRhsLoopLocal riscv SystemV Export Chapter23Test-testOrRhsLoopLocal.smp +Chapter23 Chapter23Test.testMethod x86_64_v2 win64 Encoding Chapter23Test-testMethod.smp +Chapter23 Chapter23Test.testOrRhsLoopMemory riscv SystemV Export Chapter23Test-testOrRhsLoopMemory.smp +Chapter23 Chapter23Test.testCondSideEffOr x86_64_v2 win64 Export Chapter23Test-testCondSideEffOr.smp +Chapter23 Chapter23Test.testCondSideEffOr riscv SystemV Export Chapter23Test-testCondSideEffOr.smp +Chapter23 Chapter23Test.testCondSideEffOr arm SystemV Export Chapter23Test-testCondSideEffOr.smp +Chapter23 Chapter23Test.testFuncCall x86_64_v2 win64 Export Chapter23Test-testFuncCall.smp +Chapter23 Chapter23Test.testFuncCall riscv SystemV Export Chapter23Test-testFuncCall.smp +Chapter23 Chapter23Test.testFuncCall arm SystemV Export Chapter23Test-testFuncCall.smp +Chapter23 Chapter23AllocTest.testJig21 x86_64_v2 win64 Encoding Chapter23AllocTest-testJig21.smp +Chapter23 Chapter23AllocTest.testJig21 riscv SystemV Encoding Chapter23AllocTest-testJig21.smp +Chapter23 Chapter23AllocTest.testJig21 arm SystemV Encoding Chapter23AllocTest-testJig21.smp +Chapter23 Chapter23AllocTest.testJig22 x86_64_v2 win64 Encoding Chapter23AllocTest-testJig21.smp +Chapter23 Chapter23AllocTest.testJig22 riscv SystemV Encoding Chapter23AllocTest-testJig21.smp +Chapter23 Chapter23AllocTest.testJig22 arm SystemV Encoding Chapter23AllocTest-testJig21.smp +Chapter23 Chapter23AllocTest.testString x86_64_v2 SystemV Encoding Chapter23AllocTest-testString.smp +Chapter23 Chapter23AllocTest.testString riscv SystemV Encoding Chapter23AllocTest-testString.smp +Chapter23 Chapter23AllocTest.testString arm SystemV Encoding Chapter23AllocTest-testString.smp +Chapter24 Chapter24Test.testAnd x86_64_v2 win64 Export Chapter23Test-testAnd.smp +Chapter24 Chapter24Test.testAnd riscv SystemV Export Chapter23Test-testAnd.smp +Chapter24 Chapter24Test.testAnd arm SystemV Export Chapter23Test-testAnd.smp +Chapter24 Chapter24Test.testJig x86_64_v2 win64 Encoding Chapter24Test-testJig.smp +Chapter24 Chapter24Test.testJig riscv SystemV Encoding Chapter24Test-testJig.smp +Chapter24 Chapter24Test.testJig arm SystemV Encoding Chapter24Test-testJig.smp +Chapter24 Chapter24Test.testOr x86_64_v2 win64 Export Chapter23Test-testOr.smp +Chapter24 Chapter24Test.testOr riscv SystemV Export Chapter23Test-testOr.smp +Chapter24 Chapter24Test.testOr arm SystemV Export Chapter23Test-testOr.smp +Chapter24 Chapter24Test.testCondSideEffAnd x86_64_v2 win64 Export Chapter23Test-testCondSideEffAnd.smp +Chapter24 Chapter24Test.testCondSideEffAnd riscv SystemV Export Chapter23Test-testCondSideEffAnd.smp +Chapter24 Chapter24Test.testCondSideEffAnd arm SystemV Export Chapter23Test-testCondSideEffAnd.smp +Chapter24 Chapter24Test.testFRefFields x86_64_v2 win64 Encoding Chapter23Test-testFRefFields.smp +Chapter24 Chapter24Test.testAndPtr riscv SystemV Export Chapter23Test-testAndPtr.smp +Chapter24 Chapter24Test.testAndPtr arm SystemV Export Chapter23Test-testAndPtr.smp +Chapter24 Chapter24Test.testMethod x86_64_v2 win64 Encoding Chapter23Test-testMethod.smp +Chapter24 Chapter24Test.testStack1 x86_64_v2 win64 Export Chapter24Test-testStack1.smp +Chapter24 Chapter24Test.testStack1 riscv SystemV Export Chapter24Test-testStack1.smp +Chapter24 Chapter24Test.testStack1 arm SystemV Export Chapter24Test-testStack1.smp +Chapter24 Chapter24Test.testStack2 x86_64_v2 win64 Export Chapter24Test-testStack2.smp +Chapter24 Chapter24Test.testStack2 riscv SystemV Export Chapter24Test-testStack2.smp +Chapter24 Chapter24Test.testStack2 arm SystemV Export Chapter24Test-testStack2.smp +Chapter24 Chapter24Test.testStack3 x86_64_v2 win64 Export Chapter24Test-testStack3.smp +Chapter24 Chapter24Test.testStack3 riscv SystemV Export Chapter24Test-testStack3.smp +Chapter24 Chapter24Test.testStack3 arm SystemV Export Chapter24Test-testStack3.smp +Chapter24 Chapter24Test.testStack4 x86_64_v2 win64 Export Chapter24Test-testStack4.smp +Chapter24 Chapter24Test.testStack4 riscv SystemV Export Chapter24Test-testStack4.smp +Chapter24 Chapter24Test.testStack4 arm SystemV Export Chapter24Test-testStack4.smp +Chapter24 Chapter24Test.testStack5 x86_64_v2 win64 Export Chapter24Test-testStack5.smp +Chapter24 Chapter24Test.testStack5 riscv SystemV Export Chapter24Test-testStack5.smp +Chapter24 Chapter24Test.testStack5 arm SystemV Export Chapter24Test-testStack5.smp +Chapter24 Chapter24Test.testStack9 x86_64_v2 win64 Export Chapter24Test-testStack9.smp +Chapter24 Chapter24Test.testStack9 riscv SystemV Export Chapter24Test-testStack9-2.smp +Chapter24 Chapter24Test.testStack9 arm SystemV Export Chapter24Test-testStack9-2.smp +Chapter24 Chapter24Test.testCondSideEffOr x86_64_v2 win64 Export Chapter23Test-testCondSideEffOr.smp +Chapter24 Chapter24Test.testCondSideEffOr riscv SystemV Export Chapter23Test-testCondSideEffOr.smp +Chapter24 Chapter24Test.testCondSideEffOr arm SystemV Export Chapter23Test-testCondSideEffOr.smp +Chapter24 Chapter24Test.testStack10 x86_64_v2 win64 Export Chapter24Test-testStack10.smp +Chapter24 Chapter24Test.testStack10 riscv SystemV Export Chapter24Test-testStack10-2.smp +Chapter24 Chapter24Test.testStack10 arm SystemV Export Chapter24Test-testStack10-2.smp +Chapter24 Chapter24Test.testStack11 x86_64_v2 win64 Export Chapter24Test-testStack11.smp +Chapter24 Chapter24Test.testStack11 riscv SystemV Export Chapter24Test-testStack11-2.smp +Chapter24 Chapter24Test.testStack11 arm SystemV Export Chapter24Test-testStack11-2.smp +Chapter24 Chapter24Test.testStack12 x86_64_v2 win64 Export Chapter24Test-testStack12.smp +Chapter24 Chapter24Test.testStack12 riscv SystemV Export Chapter24Test-testStack12-2.smp +Chapter24 Chapter24Test.testStack12 arm SystemV Export Chapter24Test-testStack12-2.smp +Chapter24 Chapter24Test.testStack13 x86_64_v2 win64 Export Chapter24Test-testStack13.smp +Chapter24 Chapter24Test.testStack13 riscv SystemV Export Chapter24Test-testStack13-2.smp +Chapter24 Chapter24Test.testStack13 arm SystemV Export Chapter24Test-testStack13-2.smp +Chapter24 Chapter24Test.testFuncCall x86_64_v2 win64 Export Chapter23Test-testFuncCall.smp +Chapter24 Chapter24Test.testFuncCall riscv SystemV Export Chapter23Test-testFuncCall.smp +Chapter24 Chapter24Test.testFuncCall arm SystemV Export Chapter23Test-testFuncCall.smp +Chapter24 Chapter24AllocTest.testNewtonInteger x86_64_v2 win64 Encoding Chapter24AllocTest-testNewtonInteger.smp +Chapter24 Chapter24AllocTest.testNewtonInteger riscv SystemV Encoding Chapter24AllocTest-testNewtonInteger.smp +Chapter24 Chapter24AllocTest.testNewtonInteger arm SystemV Encoding Chapter24AllocTest-testNewtonInteger.smp +Chapter24 Chapter24AllocTest.testJig21 x86_64_v2 win64 Encoding Chapter24AllocTest-testJig21.smp +Chapter24 Chapter24AllocTest.testJig21 riscv SystemV Encoding Chapter24AllocTest-testJig21.smp +Chapter24 Chapter24AllocTest.testJig21 arm SystemV Encoding Chapter24AllocTest-testJig21.smp +Chapter24 Chapter24AllocTest.testJig22 x86_64_v2 win64 Encoding Chapter24AllocTest-testJig22.smp +Chapter24 Chapter24AllocTest.testJig22 riscv SystemV Encoding Chapter24AllocTest-testJig22.smp +Chapter24 Chapter24AllocTest.testJig22 arm SystemV Encoding Chapter24AllocTest-testJig22.smp +Chapter24 Chapter24AllocTest.testStackArguments x86_64_v2 win64 Export Chapter24AllocTest-testStackArguments.smp +Chapter24 Chapter24AllocTest.testStackArguments riscv SystemV Export Chapter24AllocTest-testStackArguments.smp +Chapter24 Chapter24AllocTest.testStackArguments arm SystemV Export Chapter24AllocTest-testStackArguments.smp +Chapter24 Chapter24AllocTest.testBubbleSort x86_64_v2 win64 Encoding Chapter24AllocTest-testBubbleSort.smp +Chapter24 Chapter24AllocTest.testBubbleSort riscv SystemV Encoding Chapter24AllocTest-testBubbleSort.smp +Chapter24 Chapter24AllocTest.testBubbleSort arm SystemV Encoding Chapter24AllocTest-testBubbleSort.smp +Chapter21 BrainFuckTest.testBrainFuck x86_64_v2 win64 Export BrainFuckTest-testBrainFuck.smp +Chapter21 BrainFuckTest.testBrainFuck riscv SystemV Export BrainFuckTest-testBrainFuck.smp +Chapter21 BrainFuckTest.testBrainFuck arm SystemV Export BrainFuckTest-testBrainFuck.smp +Chapter21 MergeSortTest.testMergeSort0 x86_64_v2 win64 Export MergeSortTest-testMergeSort0.smp +Chapter21 MergeSortTest.testMergeSort0 riscv SystemV Export MergeSortTest-testMergeSort0.smp +Chapter21 MergeSortTest.testMergeSort0 arm SystemV Encoding MergeSortTest-testMergeSort0.smp -- cgit v1.2.3