23 24 25 package org.graalvm.compiler.replacements.test; 26 27 import static org.junit.Assert.assertNotNull; 28 29 import java.util.ArrayList; 30 import java.util.Collection; 31 import java.util.List; 32 33 import org.graalvm.compiler.core.common.type.IntegerStamp; 34 import org.graalvm.compiler.core.common.type.StampFactory; 35 import org.graalvm.compiler.core.test.GraalCompilerTest; 36 import org.graalvm.compiler.graph.Node; 37 import org.graalvm.compiler.nodes.NodeView; 38 import org.graalvm.compiler.nodes.ParameterNode; 39 import org.graalvm.compiler.nodes.PiNode; 40 import org.graalvm.compiler.nodes.ReturnNode; 41 import org.graalvm.compiler.nodes.StructuredGraph; 42 import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; 43 import org.graalvm.compiler.nodes.StructuredGraph.GuardsStage; 44 import org.graalvm.compiler.nodes.ValueNode; 45 import org.graalvm.compiler.nodes.spi.LoweringTool; 46 import org.graalvm.compiler.phases.common.CanonicalizerPhase; 47 import org.graalvm.compiler.phases.common.LoweringPhase; 48 import org.graalvm.compiler.phases.tiers.HighTierContext; 49 import org.graalvm.compiler.phases.tiers.PhaseContext; 50 import org.graalvm.compiler.replacements.nodes.arithmetic.IntegerExactArithmeticNode; 51 import org.graalvm.compiler.replacements.nodes.arithmetic.IntegerExactArithmeticSplitNode; 52 import org.junit.Assert; 53 import org.junit.Ignore; 54 import org.junit.Test; 55 import org.junit.runner.RunWith; 56 import org.junit.runners.Parameterized; 57 import org.junit.runners.Parameterized.Parameters; 58 59 @Ignore 60 @RunWith(Parameterized.class) 61 public class IntegerExactFoldTest extends GraalCompilerTest { 62 private final long lowerBoundA; 63 private final long upperBoundA; 64 private final long lowerBoundB; 65 private final long upperBoundB; 66 private final int bits; 67 private final Operation operation; 68 69 public IntegerExactFoldTest(long lowerBoundA, long upperBoundA, long lowerBoundB, long upperBoundB, int bits, Operation operation) { 70 this.lowerBoundA = lowerBoundA; 71 this.upperBoundA = upperBoundA; 72 this.lowerBoundB = lowerBoundB; 73 this.upperBoundB = upperBoundB; 74 this.bits = bits; 75 this.operation = operation; 76 77 assert bits == 32 || bits == 64; 78 assert lowerBoundA <= upperBoundA; 79 assert lowerBoundB <= upperBoundB; 80 assert bits == 64 || isInteger(lowerBoundA); 81 assert bits == 64 || isInteger(upperBoundA); 82 assert bits == 64 || isInteger(lowerBoundB); 83 assert bits == 64 || isInteger(upperBoundB); 84 } 85 86 @Test 87 public void testFolding() { 88 StructuredGraph graph = prepareGraph(); 89 IntegerStamp a = StampFactory.forInteger(bits, lowerBoundA, upperBoundA); 90 IntegerStamp b = StampFactory.forInteger(bits, lowerBoundB, upperBoundB); 91 92 List<ParameterNode> params = graph.getNodes(ParameterNode.TYPE).snapshot(); 93 params.get(0).replaceAtMatchingUsages(graph.addOrUnique(new PiNode(params.get(0), a)), x -> x instanceof IntegerExactArithmeticNode); 94 params.get(1).replaceAtMatchingUsages(graph.addOrUnique(new PiNode(params.get(1), b)), x -> x instanceof IntegerExactArithmeticNode); 95 96 Node originalNode = graph.getNodes().filter(x -> x instanceof IntegerExactArithmeticNode).first(); 97 assertNotNull("original node must be in the graph", originalNode); 98 99 new CanonicalizerPhase().apply(graph, getDefaultHighTierContext()); 100 ValueNode node = findNode(graph); 101 boolean overflowExpected = node instanceof IntegerExactArithmeticNode; 102 103 IntegerStamp resultStamp = (IntegerStamp) node.stamp(NodeView.DEFAULT); 104 operation.verifyOverflow(lowerBoundA, upperBoundA, lowerBoundB, upperBoundB, bits, overflowExpected, resultStamp); 105 } 106 107 @Test 108 public void testFoldingAfterLowering() { 109 StructuredGraph graph = prepareGraph(); 110 111 Node originalNode = graph.getNodes().filter(x -> x instanceof IntegerExactArithmeticNode).first(); 112 assertNotNull("original node must be in the graph", originalNode); 113 114 graph.setGuardsStage(GuardsStage.FIXED_DEOPTS); 115 CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); 116 PhaseContext context = new PhaseContext(getProviders()); 117 new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context); 118 IntegerExactArithmeticSplitNode loweredNode = graph.getNodes().filter(IntegerExactArithmeticSplitNode.class).first(); 119 assertNotNull("the lowered node must be in the graph", loweredNode); 120 121 loweredNode.getX().setStamp(StampFactory.forInteger(bits, lowerBoundA, upperBoundA)); 122 loweredNode.getY().setStamp(StampFactory.forInteger(bits, lowerBoundB, upperBoundB)); 123 new CanonicalizerPhase().apply(graph, context); 124 125 ValueNode node = findNode(graph); 126 boolean overflowExpected = node instanceof IntegerExactArithmeticSplitNode; 127 128 IntegerStamp resultStamp = (IntegerStamp) node.stamp(NodeView.DEFAULT); 129 operation.verifyOverflow(lowerBoundA, upperBoundA, lowerBoundB, upperBoundB, bits, overflowExpected, resultStamp); 130 } 131 132 private static boolean isInteger(long value) { 133 return value >= Integer.MIN_VALUE && value <= Integer.MAX_VALUE; 134 } 135 136 private static ValueNode findNode(StructuredGraph graph) { 137 ValueNode resultNode = graph.getNodes().filter(ReturnNode.class).first().result(); 138 assertNotNull("some node must be the returned value", resultNode); 139 return resultNode; 140 } 141 142 protected StructuredGraph prepareGraph() { 143 String snippet = "snippetInt" + bits; | 23 24 25 package org.graalvm.compiler.replacements.test; 26 27 import static org.junit.Assert.assertNotNull; 28 29 import java.util.ArrayList; 30 import java.util.Collection; 31 import java.util.List; 32 33 import org.graalvm.compiler.core.common.type.IntegerStamp; 34 import org.graalvm.compiler.core.common.type.StampFactory; 35 import org.graalvm.compiler.core.test.GraalCompilerTest; 36 import org.graalvm.compiler.graph.Node; 37 import org.graalvm.compiler.nodes.NodeView; 38 import org.graalvm.compiler.nodes.ParameterNode; 39 import org.graalvm.compiler.nodes.PiNode; 40 import org.graalvm.compiler.nodes.ReturnNode; 41 import org.graalvm.compiler.nodes.StructuredGraph; 42 import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; 43 import org.graalvm.compiler.nodes.ValueNode; 44 import org.graalvm.compiler.nodes.spi.LoweringTool; 45 import org.graalvm.compiler.phases.common.CanonicalizerPhase; 46 import org.graalvm.compiler.phases.common.GuardLoweringPhase; 47 import org.graalvm.compiler.phases.common.LoweringPhase; 48 import org.graalvm.compiler.phases.tiers.HighTierContext; 49 import org.graalvm.compiler.phases.tiers.MidTierContext; 50 import org.graalvm.compiler.replacements.nodes.arithmetic.IntegerExactArithmeticNode; 51 import org.graalvm.compiler.replacements.nodes.arithmetic.IntegerExactArithmeticSplitNode; 52 import org.junit.Assert; 53 import org.junit.Test; 54 import org.junit.runner.RunWith; 55 import org.junit.runners.Parameterized; 56 import org.junit.runners.Parameterized.Parameters; 57 58 @RunWith(Parameterized.class) 59 public class IntegerExactFoldTest extends GraalCompilerTest { 60 private final long lowerBoundA; 61 private final long upperBoundA; 62 private final long lowerBoundB; 63 private final long upperBoundB; 64 private final int bits; 65 private final Operation operation; 66 67 public IntegerExactFoldTest(long lowerBoundA, long upperBoundA, long lowerBoundB, long upperBoundB, int bits, Operation operation) { 68 this.lowerBoundA = lowerBoundA; 69 this.upperBoundA = upperBoundA; 70 this.lowerBoundB = lowerBoundB; 71 this.upperBoundB = upperBoundB; 72 this.bits = bits; 73 this.operation = operation; 74 75 assert bits == 32 || bits == 64; 76 assert lowerBoundA <= upperBoundA; 77 assert lowerBoundB <= upperBoundB; 78 assert bits == 64 || isInteger(lowerBoundA); 79 assert bits == 64 || isInteger(upperBoundA); 80 assert bits == 64 || isInteger(lowerBoundB); 81 assert bits == 64 || isInteger(upperBoundB); 82 } 83 84 @Test 85 public void testFolding() { 86 StructuredGraph graph = prepareGraph(); 87 IntegerStamp a = StampFactory.forInteger(bits, lowerBoundA, upperBoundA); 88 IntegerStamp b = StampFactory.forInteger(bits, lowerBoundB, upperBoundB); 89 90 List<ParameterNode> params = graph.getNodes(ParameterNode.TYPE).snapshot(); 91 params.get(0).replaceAtMatchingUsages(graph.addOrUnique(new PiNode(params.get(0), a)), x -> x instanceof IntegerExactArithmeticNode); 92 params.get(1).replaceAtMatchingUsages(graph.addOrUnique(new PiNode(params.get(1), b)), x -> x instanceof IntegerExactArithmeticNode); 93 94 Node originalNode = graph.getNodes().filter(x -> x instanceof IntegerExactArithmeticNode).first(); 95 assertNotNull("original node must be in the graph", originalNode); 96 97 new CanonicalizerPhase().apply(graph, getDefaultHighTierContext()); 98 99 ValueNode node = findNode(graph); 100 boolean overflowExpected = node instanceof IntegerExactArithmeticNode; 101 102 IntegerStamp resultStamp = (IntegerStamp) node.stamp(NodeView.DEFAULT); 103 operation.verifyOverflow(lowerBoundA, upperBoundA, lowerBoundB, upperBoundB, bits, overflowExpected, resultStamp); 104 } 105 106 @Test 107 public void testFoldingAfterLowering() { 108 StructuredGraph graph = prepareGraph(); 109 110 Node originalNode = graph.getNodes().filter(x -> x instanceof IntegerExactArithmeticNode).first(); 111 assertNotNull("original node must be in the graph", originalNode); 112 CanonicalizerPhase canonicalizer = new CanonicalizerPhase(); 113 HighTierContext highTierContext = getDefaultHighTierContext(); 114 new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, highTierContext); 115 MidTierContext midTierContext = getDefaultMidTierContext(); 116 new GuardLoweringPhase().apply(graph, midTierContext); 117 new CanonicalizerPhase().apply(graph, midTierContext); 118 119 IntegerExactArithmeticSplitNode loweredNode = graph.getNodes().filter(IntegerExactArithmeticSplitNode.class).first(); 120 assertNotNull("the lowered node must be in the graph", loweredNode); 121 122 loweredNode.getX().setStamp(StampFactory.forInteger(bits, lowerBoundA, upperBoundA)); 123 loweredNode.getY().setStamp(StampFactory.forInteger(bits, lowerBoundB, upperBoundB)); 124 new CanonicalizerPhase().apply(graph, midTierContext); 125 126 ValueNode node = findNode(graph); 127 boolean overflowExpected = node instanceof IntegerExactArithmeticSplitNode; 128 129 IntegerStamp resultStamp = (IntegerStamp) node.stamp(NodeView.DEFAULT); 130 operation.verifyOverflow(lowerBoundA, upperBoundA, lowerBoundB, upperBoundB, bits, overflowExpected, resultStamp); 131 } 132 133 private static boolean isInteger(long value) { 134 return value >= Integer.MIN_VALUE && value <= Integer.MAX_VALUE; 135 } 136 137 private static ValueNode findNode(StructuredGraph graph) { 138 ValueNode resultNode = graph.getNodes().filter(ReturnNode.class).first().result(); 139 assertNotNull("some node must be the returned value", resultNode); 140 return resultNode; 141 } 142 143 protected StructuredGraph prepareGraph() { 144 String snippet = "snippetInt" + bits; |