From dd907c2d86eaaad0910e7bfe3f0d25e5caf8bdf7 Mon Sep 17 00:00:00 2001 From: Hsiang-Ying Fu <66062782+fuhsnn@users.noreply.github.com> Date: Sat, 26 Sep 2026 06:35:22 +0800 Subject: Extend and backport SubNode peephole (#254) * Extend and backport SubNode peephole * Add tests * Restrict subtraction zero peepholes to integer operands Require resolved integer mode in chapter 25 so zero subtraction preserves floating-point signed zero. Keep nonnumeric operands in the graph for subtraction diagnostics. Add signed-zero coverage from chapter 12 and null-subtraction diagnostics from chapter 22. Confirmed the regressions fail on the original PR. Full Make suites pass in chapters 4-25 (5462 tests), including fresh chapter 25 sys.o compilation. --------- Co-authored-by: Cliff Click --- .../java/com/seaofnodes/simple/node/SubNode.java | 19 +++++++++++++++ .../java/com/seaofnodes/simple/Chapter04Test.java | 28 ++++++++++++++++++++++ 2 files changed, 47 insertions(+) (limited to 'chapter05/src') diff --git a/chapter05/src/main/java/com/seaofnodes/simple/node/SubNode.java b/chapter05/src/main/java/com/seaofnodes/simple/node/SubNode.java index d3fd1c7e..bd43bc6c 100644 --- a/chapter05/src/main/java/com/seaofnodes/simple/node/SubNode.java +++ b/chapter05/src/main/java/com/seaofnodes/simple/node/SubNode.java @@ -32,6 +32,25 @@ public class SubNode extends Node { @Override public Node idealize() { + Node lhs = in(1); + Node rhs = in(2); + Type t1 = lhs._type; + Type t2 = rhs._type; + + // Keep invalid operands for type checking. + if( t1 instanceof TypeInteger x && t2 instanceof TypeInteger y ) { + if( y.isConstant() && y.value()==0 ) return lhs; + if( x.isConstant() && x.value()==0 ) return new MinusNode(rhs); + } + + // x - (-y) is x+y + if( rhs instanceof MinusNode minus ) + return new AddNode(lhs,minus.in(1)); + + // (-x) - y is -(x+y) + if( lhs instanceof MinusNode minus ) + return new MinusNode(new AddNode(minus.in(1),rhs).peephole()); + return null; } diff --git a/chapter05/src/test/java/com/seaofnodes/simple/Chapter04Test.java b/chapter05/src/test/java/com/seaofnodes/simple/Chapter04Test.java index 2e2abb25..f1603cc4 100644 --- a/chapter05/src/test/java/com/seaofnodes/simple/Chapter04Test.java +++ b/chapter05/src/test/java/com/seaofnodes/simple/Chapter04Test.java @@ -50,6 +50,34 @@ public class Chapter04Test { assertEquals("return arg;", ret.print()); } + @Test + public void testSub0() { + Parser parser = new Parser("return arg-0;"); + StopNode ret = parser.parse(); + assertEquals("return arg;", ret.print()); + } + + @Test + public void test0Sub() { + Parser parser = new Parser("return 0-arg;"); + StopNode ret = parser.parse(); + assertEquals("return (-arg);", ret.print()); + } + + @Test + public void testSubNeg() { + Parser parser = new Parser("return 3--arg;"); + StopNode ret = parser.parse(); + assertEquals("return (arg+3);", ret.print()); + } + + @Test + public void testNegSub() { + Parser parser = new Parser("return -arg-3;"); + StopNode ret = parser.parse(); + assertEquals("return (-(arg+3));", ret.print()); + } + @Test public void testVarArg() { Parser parser = new Parser("return arg; "); -- cgit v1.2.3