diff options
| author | Cliff Click <cliffc@acm.org> | 2026-08-10 11:11:18 -0700 |
|---|---|---|
| committer | Cliff Click <cliffc@acm.org> | 2026-10-08 16:52:27 -0700 |
| commit | d32f97238c903765dec4e9a9f3cbfa5fd12cded6 (patch) | |
| tree | a5ac731801ef7066bab6359c4e85c2bdd20082a6 /src/test/java/com/seaofnodes/simple/SpillStats.java | |
| parent | b5ebb2032aa04cf4506d533127d373d4cf5a25c6 (diff) | |
| download | Simple-linear.tar.gz Simple-linear.zip | |
Chapter 25: Modules, Separate Compilation, and SSA Constructionlinear
Co-authored-by: Hsiang-Ying Fu <66062782+fuhsnn@users.noreply.github.com>
Co-authored-by: fuhsnn <66062782+fuhsnn@users.noreply.github.com>
Co-authored-by: Symious <14933944+symious@users.noreply.github.com>
Co-authored-by: Jun Kawasaki <jun784@gmail.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Diffstat (limited to 'src/test/java/com/seaofnodes/simple/SpillStats.java')
| -rw-r--r-- | src/test/java/com/seaofnodes/simple/SpillStats.java | 83 |
1 files changed, 51 insertions, 32 deletions
diff --git a/src/test/java/com/seaofnodes/simple/SpillStats.java b/src/test/java/com/seaofnodes/simple/SpillStats.java index ad044a52..d43f1a36 100644 --- a/src/test/java/com/seaofnodes/simple/SpillStats.java +++ b/src/test/java/com/seaofnodes/simple/SpillStats.java @@ -1,13 +1,15 @@ 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.*; -// Run existing tests and sum actual allocations, including ones without goldens. -// Helpers call record after allocation; ordinary JUnit runs collect nothing. +// Earlier cohorts freeze source/target membership; Chapter 25 retains native checks. public class SpillStats extends RunListener { private static SpillStats ACTIVE; private Description _test; @@ -15,30 +17,25 @@ public class SpillStats extends RunListener { private final Map<String,long[]> _totals = new TreeMap<>(); @Override public void testStarted(Description test) { _test = test; } - public static void record(CodeGen code, String cohort, String cpu, String abi) { - if( ACTIVE==null ) return; - String test = ACTIVE._test.getTestClass().getSimpleName()+"."+ACTIVE._test.getMethodName(); + @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 = ACTIVE._totals.computeIfAbsent(key,k -> new long[3]); + 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); } - // The same native helpers serve old and new program cohorts. - public static void recordNative(CodeGen code, String cpu, String abi) { - String cohort = ACTIVE!=null && (ACTIVE._test.getTestClass()==Chapter24Test.class || ACTIVE._test.getTestClass()==Chapter24AllocTest.class) - ? "Chapter24" : ACTIVE!=null && ACTIVE._test.getTestClass()==Chapter23Test.class - ? "Chapter23" : ACTIVE!=null && ACTIVE._test.getTestClass()==Chapter22Test.class - ? "Chapter22" : "Chapter21"; - record(code,cohort,cpu,abi); - } - - // Keep running every CPU and native result check when measuring quality. - // A changed golden still makes spill-stats fail at the end. + // Keep native result checks running during a quality comparison. public static void checkSpills(int expected, int actual) { - if( expected==-1 ) return; + 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; @@ -47,27 +44,49 @@ public class SpillStats extends RunListener { } } - public static void main(String[] args) throws ClassNotFoundException { - if( args.length==0 ) args = new String[]{"Chapter20Test","Chapter21Test","Chapter21AllocTest","Chapter22Test","Chapter23Test","Chapter23AllocTest","Chapter24Test","Chapter24AllocTest","BrainFuckTest","MergeSortTest"}; - Class<?>[] tests = new Class<?>[args.length]; - for( int i=0; i<args.length; i++ ) - tests[i] = Class.forName("com.seaofnodes.simple."+args[i]); + 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(tests); - boolean passed = result.wasSuccessful() && ACTIVE._qualityFailures==0; - if( !result.wasSuccessful() ) System.out.println("FAILED test run: totals are not a complete comparison."); - else if( !passed ) System.out.println("Spill expectations differ; allocation and runtime checks passed."); + 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]); } - for( Failure failure : result.getFailures() ) System.err.println(failure.getTrace()); - System.out.println("Tests: "+result.getRunCount()+", failures: "+result.getFailureCount()); - System.out.println("Spill golden failures: "+ACTIVE._qualityFailures); + System.out.println("Historical allocations: "+attempts+"; native tests: "+result.getRunCount()+"; failures: "+failures+"; spill golden failures: "+ACTIVE._qualityFailures); + failures += ACTIVE._qualityFailures; ACTIVE = null; - if( !passed ) System.exit(1); + if( failures!=0 ) System.exit(1); } -} +}
\ No newline at end of file |
