summaryrefslogtreecommitdiff
path: root/chapter28a/src/test/java
diff options
context:
space:
mode:
authorCliff Click <cliffc@acm.org>2026-10-28 12:26:28 -0700
committerCliff Click <cliffc@acm.org>2026-10-28 12:26:28 -0700
commite481e3d215882faa82b19f29cfde5746d4e51863 (patch)
treed6035c13e4ee471b67d7dd4732a62bc04020fbd1 /chapter28a/src/test/java
parent07a87b4461015dd81f1d40cef1e2378882c86479 (diff)
downloadSimple-e481e3d215882faa82b19f29cfde5746d4e51863.tar.gz
Simple-e481e3d215882faa82b19f29cfde5746d4e51863.zip
Backport Opto speedups and Minus fix
Diffstat (limited to 'chapter28a/src/test/java')
-rw-r--r--chapter28a/src/test/java/com/seaofnodes/simple/MinusNodeTest.java73
1 files changed, 73 insertions, 0 deletions
diff --git a/chapter28a/src/test/java/com/seaofnodes/simple/MinusNodeTest.java b/chapter28a/src/test/java/com/seaofnodes/simple/MinusNodeTest.java
new file mode 100644
index 00000000..497546df
--- /dev/null
+++ b/chapter28a/src/test/java/com/seaofnodes/simple/MinusNodeTest.java
@@ -0,0 +1,73 @@
+package com.seaofnodes.simple;
+
+import com.seaofnodes.simple.codegen.CodeGen;
+import com.seaofnodes.simple.node.ConstantNode;
+import com.seaofnodes.simple.node.MinusNode;
+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 MinusNodeTest {
+ @Test public void testMonotoneCompute() {
+ CodeGen code = new CodeGen("return 0;");
+ // Type.gather also loads cached fixtures which do not survive later compiler resets.
+ ArrayList<Type> inputs = new ArrayList<>(Arrays.asList(
+ Type.BOTTOM,Type.CONTROL,Type.NIL,TypeScalar.BOT,TypePtr.PTR,
+ TypeMemPtr.BOT,TypeFunPtr.BOT,TypeMem.BOT,
+ TypeConAryB.make(new byte[]{1,2,3})));
+ TypeInteger.gather(inputs);
+ TypeFloat.gather(inputs);
+ int size = inputs.size();
+ for( int i=0; i<size; i++ ) inputs.add(inputs.get(i).dual());
+ 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,Double.NaN,Double.NEGATIVE_INFINITY,Double.POSITIVE_INFINITY} )
+ inputs.add(TypeFloat.constant(value));
+ Type[][] expected = new Type[3][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( byte mode=0; mode<3; mode++ ) {
+ // An isolated analysis input: vary its type without peepholes
+ // selecting a mode or folding the node under test.
+ Node input = new ConstantNode(Type.BOTTOM);
+ input.setDef(0,null);
+ MinusNode minus = new MinusNode(input,mode);
+ Type[] results = new Type[inputs.size()];
+ for( int i=0; i<inputs.size(); i++ ) {
+ input._type = inputs.get(i);
+ results[i] = minus.compute();
+ if( phase==CodeGen.Phase.Parse ) expected[mode][i] = results[i];
+ else assertSame("Phase changed compute",expected[mode][i],results[i]);
+ }
+ // The same order relation covers both falling SCCP types
+ // and rising Iter types, including crossing numeric families.
+ for( int i=0; i<inputs.size(); i++ )
+ for( int j=0; j<inputs.size(); j++ )
+ if( inputs.get(i).isa(inputs.get(j)) )
+ assertTrue("mode="+mode+": "+inputs.get(i)+" -> "+inputs.get(j)+
+ " gave "+results[i]+" -> "+results[j],results[i].isa(results[j]));
+ }
+ }
+ }
+
+ @Test public void testUnresolvedInput() {
+ new CodeGen("return 0;").driver(CodeGen.Phase.Opto);
+ Node input = new ConstantNode(TypeInteger.TRUE);
+ MinusNode minus = new MinusNode(input);
+ assertSame(TypeInteger.constant(-1),minus.compute());
+ input._type = Type.BOTTOM;
+ assertSame(Type.BOTTOM,minus.compute());
+ minus.setMode((byte)1);
+ assertSame(Type.BOTTOM,minus.compute());
+ }
+
+ @Test public void testRecursiveFloat() {
+ CodeGen code = new CodeGen("val _neg = { int x -> x ? -_neg(x-1) : 1.0; }; return _neg(arg);")
+ .driver(CodeGen.Phase.TypeCheck);
+ for( int i=0; i<4; i++ )
+ assertEquals((i&1)==0 ? "1.0" : "-1.0",Eval2.eval(code,i));
+ }
+}