From 50924bbe7cfeecfe7aec1885dae9bbda0013ac1b Mon Sep 17 00:00:00 2001 From: Cliff Click Date: Wed, 28 Oct 2026 15:05:08 -0700 Subject: Remove _phase checks from Arith & Compute Fix some monotonicty bugs, rounding bugs, in float ops --- .../java/com/seaofnodes/simple/ArithNodeTest.java | 96 ++++++++++++++++++++++ .../com/seaofnodes/simple/ConvertNodeTest.java | 69 ++++++++++++++++ 2 files changed, 165 insertions(+) create mode 100644 chapter27/src/test/java/com/seaofnodes/simple/ArithNodeTest.java create mode 100644 chapter27/src/test/java/com/seaofnodes/simple/ConvertNodeTest.java (limited to 'chapter27/src/test/java') diff --git a/chapter27/src/test/java/com/seaofnodes/simple/ArithNodeTest.java b/chapter27/src/test/java/com/seaofnodes/simple/ArithNodeTest.java new file mode 100644 index 00000000..708c32a2 --- /dev/null +++ b/chapter27/src/test/java/com/seaofnodes/simple/ArithNodeTest.java @@ -0,0 +1,96 @@ +package com.seaofnodes.simple; + +import com.seaofnodes.simple.codegen.CodeGen; +import com.seaofnodes.simple.node.*; +import com.seaofnodes.simple.type.*; +import java.util.ArrayList; +import java.util.Arrays; +import org.junit.Test; +import static org.junit.Assert.*; + +public class ArithNodeTest { + @Test public void testUnresolvedInput() { + new CodeGen("return 0;").driver(CodeGen.Phase.Opto); + Node lhs = new ConstantNode(TypeInteger.TRUE); + Node rhs = new ConstantNode(TypeInteger.TRUE); + ArithNode add = new AddNode(lhs,rhs); + assertSame(TypeInteger.constant(2),add.compute()); + lhs._type = TypeScalar.BOT; + assertSame(Type.BOTTOM,add.compute()); + add.setMode((byte)1); + assertSame(Type.BOTTOM,add.compute()); + } + + @Test public void testFloatPrecision() { + CodeGen code = new CodeGen("f32 x = arg; return x+1.0;").driver(CodeGen.Phase.TypeCheck); + assertEquals("1.6777217E7",Eval2.eval(code,16777216)); + code = new CodeGen("f32 x = arg; f32 y = x+1.0; return y;").driver(CodeGen.Phase.TypeCheck); + assertEquals("1.6777216E7",Eval2.eval(code,16777216)); + } + + @Test public void testMonotoneCompute() { + CodeGen code = new CodeGen("return 0;"); + ArrayList inputs = new ArrayList<>(Arrays.asList( + Type.BOTTOM,Type.CONTROL,Type.NIL,TypeScalar.BOT,TypeMem.BOT)); + TypeInteger.gather(inputs); + TypeFloat.gather(inputs); + TypePtr.gather(inputs); + TypeMemPtr.gather(inputs); + TypeFunPtr.gather(inputs); + inputs.add(TypeConAryB.make(new byte[]{1,2,3})); + for( long value : new long[]{Long.MIN_VALUE,Long.MIN_VALUE+1,-1,1,Long.MAX_VALUE} ) + inputs.add(TypeInteger.constant(value)); + for( double value : new double[]{-0.0,0.0,-1.0,1.0,16777216.0,16777217.0,Double.NaN,Double.NEGATIVE_INFINITY,Double.POSITIVE_INFINITY} ) + inputs.add(TypeFloat.constant(value)); + int size = inputs.size(); + for( int i = 0; i ops = new ArrayList<>(); + for( byte mode = 0; mode<3; mode++ ) { + ops.add(new AddNode(lhs,rhs,mode)); + ops.add(new SubNode(lhs,rhs,mode)); + ops.add(new MulNode(lhs,rhs,mode)); + ops.add(new DivNode(lhs,rhs,mode)); + } + ops.add(new AndNode(null,lhs,rhs)); + ops.add(new OrNode(null,lhs,rhs)); + ops.add(new XorNode(null,lhs,rhs)); + ops.add(new ShlNode(null,lhs,rhs)); + ops.add(new SarNode(null,lhs,rhs)); + ops.add(new ShrNode(null,lhs,rhs)); + Type[][][] expected = new Type[ops.size()][size][size]; + for( CodeGen.Phase phase : new CodeGen.Phase[]{CodeGen.Phase.Parse,CodeGen.Phase.Iter,CodeGen.Phase.Opto,CodeGen.Phase.IterPostOpto} ) { + code.driver(phase); + for( int op = 0; op "+inputs.get(j)+", other="+inputs.get(k)+ + "; lhs results "+results[i][k]+" -> "+results[j][k]+ + "; rhs results "+results[k][i]+" -> "+results[k][j]); + } + } + } + } +} diff --git a/chapter27/src/test/java/com/seaofnodes/simple/ConvertNodeTest.java b/chapter27/src/test/java/com/seaofnodes/simple/ConvertNodeTest.java new file mode 100644 index 00000000..2342b33a --- /dev/null +++ b/chapter27/src/test/java/com/seaofnodes/simple/ConvertNodeTest.java @@ -0,0 +1,69 @@ +package com.seaofnodes.simple; + +import com.seaofnodes.simple.codegen.CodeGen; +import com.seaofnodes.simple.node.ConstantNode; +import com.seaofnodes.simple.node.ConvertNode; +import com.seaofnodes.simple.node.Node; +import com.seaofnodes.simple.type.*; +import java.util.ArrayList; +import java.util.Arrays; +import org.junit.Test; +import static org.junit.Assert.*; + +public class ConvertNodeTest { + @Test public void testMonotoneCompute() { + CodeGen code = new CodeGen("return 0;"); + ArrayList inputs = new ArrayList<>(Arrays.asList( + Type.BOTTOM,Type.CONTROL,Type.NIL,TypeScalar.BOT,TypeMem.BOT)); + TypeInteger.gather(inputs); + TypeFloat.gather(inputs); + TypePtr.gather(inputs); + TypeMemPtr.gather(inputs); + TypeFunPtr.gather(inputs); + // Writable arrays require matching element access in both directions. + // Widening the element's access can make that check pass while keeping + // a known length; compute must not suddenly gain that length fact. + for( TypeInteger len : new TypeInteger[]{TypeInteger.U32,TypeInteger.TRUE} ) + for( boolean elementRO : new boolean[]{false,true} ) + for( boolean arrayRO : new boolean[]{false,true} ) + inputs.add(TypeMemPtr.make(TypeStruct.makeAry("[]test",len,-1, + TypeMemPtr.TEST.withAccess(elementRO),-2,false)).withAccess(arrayRO)); + inputs.add(TypeConAryB.make(new byte[]{1,2,3})); + for( long value : new long[]{Long.MIN_VALUE,-129,-128,-1,0,1,127,128,255,256,Long.MAX_VALUE} ) + inputs.add(TypeInteger.constant(value)); + for( double value : new double[]{-0.0,0.0,1.0,16777217.0,Double.NaN,Double.NEGATIVE_INFINITY,Double.POSITIVE_INFINITY} ) + inputs.add(TypeFloat.constant(value)); + int size = inputs.size(); + for( int i = 0; i destinations = new ArrayList<>(); + for( Type t : inputs ) + if( !t.isHigh() && (t instanceof TypeInteger || t instanceof TypeFloat || t instanceof TypeNil) ) + destinations.add(t); + + // Vary one isolated input without folding or lowering the conversion. + Node input = new ConstantNode(Type.BOTTOM); + input.setDef(0,null); + Type[][] expected = new Type[destinations.size()][inputs.size()]; + for( CodeGen.Phase phase : new CodeGen.Phase[]{CodeGen.Phase.Parse,CodeGen.Phase.Iter,CodeGen.Phase.Opto,CodeGen.Phase.IterPostOpto} ) { + code.driver(phase); + for( int d = 0; d "+inputs.get(j)+ + " gave "+results[i]+" -> "+results[j]); + } + } + } +} -- cgit v1.2.3