# HG changeset patch # User Lukas Stadler # Date 1398329052 -7200 # Node ID 7766f486f5d6c1f442473d4c495162afdfd422c8 # Parent 1c347436d596d5170eb86b37911d3c503ae71573 evaluate for BinaryOpLogicNodes diff -r 1c347436d596 -r 7766f486f5d6 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BinaryOpLogicNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BinaryOpLogicNode.java Thu Apr 24 10:44:12 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BinaryOpLogicNode.java Thu Apr 24 10:44:12 2014 +0200 @@ -22,10 +22,14 @@ */ package com.oracle.graal.nodes; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.meta.ProfilingInfo.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; -public abstract class BinaryOpLogicNode extends LogicNode implements LIRLowerable, MemoryArithmeticLIRLowerable { +public abstract class BinaryOpLogicNode extends LogicNode implements LIRLowerable, MemoryArithmeticLIRLowerable, Canonicalizable { @Input private ValueNode x; @Input private ValueNode y; @@ -54,6 +58,8 @@ this.y = y; } + public abstract TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY); + @Override public boolean verify() { assertTrue(x.stamp().isCompatible(y.stamp()), "stamps not compatible: %s, %s", x.stamp(), y.stamp()); @@ -61,6 +67,17 @@ } @Override + public Node canonical(CanonicalizerTool tool) { + switch (evaluate(tool.getConstantReflection(), x(), y())) { + case FALSE: + return LogicConstantNode.contradiction(graph()); + case TRUE: + return LogicConstantNode.tautology(graph()); + } + return this; + } + + @Override public void generate(NodeLIRBuilderTool gen) { } diff -r 1c347436d596 -r 7766f486f5d6 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java Thu Apr 24 10:44:12 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/CompareNode.java Thu Apr 24 10:44:12 2014 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.meta.ProfilingInfo.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.graph.*; @@ -35,7 +36,7 @@ * Compare should probably be made a value (so that it can be canonicalized for example) and in later stages some Compare usage should be transformed * into variants that do not materialize the value (CompareIf, CompareGuard...) */ -public abstract class CompareNode extends BinaryOpLogicNode implements Canonicalizable { +public abstract class CompareNode extends BinaryOpLogicNode { /** * Constructs a new Compare instruction. @@ -90,9 +91,18 @@ } @Override + public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) { + if (x().isConstant() && y().isConstant()) { + return TriState.get(condition().foldCondition(x().asConstant(), y().asConstant(), constantReflection, unorderedIsTrue())); + } + return TriState.UNKNOWN; + } + + @Override public Node canonical(CanonicalizerTool tool) { - if (x().isConstant() && y().isConstant() && tool.getMetaAccess() != null) { - return LogicConstantNode.forBoolean(condition().foldCondition(x().asConstant(), y().asConstant(), tool.getConstantReflection(), unorderedIsTrue()), graph()); + Node result = super.canonical(tool); + if (result != this) { + return result; } if (x().isConstant()) { if (y() instanceof ConditionalNode) { diff -r 1c347436d596 -r 7766f486f5d6 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatEqualsNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatEqualsNode.java Thu Apr 24 10:44:12 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatEqualsNode.java Thu Apr 24 10:44:12 2014 +0200 @@ -22,17 +22,20 @@ */ package com.oracle.graal.nodes.calc; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.meta.ProfilingInfo.*; import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.util.*; @NodeInfo(shortName = "==") public final class FloatEqualsNode extends CompareNode { /** * Constructs a new floating point equality comparison node. - * + * * @param x the instruction producing the first input to the instruction * @param y the instruction that produces the second input to this instruction */ @@ -51,4 +54,18 @@ public boolean unorderedIsTrue() { return false; } + + @Override + public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) { + if (forX.stamp() instanceof FloatStamp && forY.stamp() instanceof FloatStamp) { + FloatStamp xStamp = (FloatStamp) forX.stamp(); + FloatStamp yStamp = (FloatStamp) forY.stamp(); + if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY) && xStamp.isNonNaN() && yStamp.isNonNaN()) { + return TriState.TRUE; + } else if (xStamp.alwaysDistinct(yStamp)) { + return TriState.FALSE; + } + } + return super.evaluate(constantReflection, forX, forY); + } } diff -r 1c347436d596 -r 7766f486f5d6 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatLessThanNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatLessThanNode.java Thu Apr 24 10:44:12 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/FloatLessThanNode.java Thu Apr 24 10:44:12 2014 +0200 @@ -22,11 +22,13 @@ */ package com.oracle.graal.nodes.calc; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.meta.ProfilingInfo.TriState; import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; -import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.util.*; @NodeInfo(shortName = "<") public final class FloatLessThanNode extends CompareNode { @@ -35,7 +37,7 @@ /** * Constructs a new floating point comparison node. - * + * * @param x the instruction producing the first input to the instruction * @param y the instruction that produces the second input to this instruction * @param unorderedIsTrue whether a comparison that is undecided (involving NaNs, etc.) leads to @@ -59,10 +61,10 @@ } @Override - public Node canonical(CanonicalizerTool tool) { - if (x() == y() && !unorderedIsTrue()) { - return LogicConstantNode.contradiction(graph()); + public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) { + if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY) && !unorderedIsTrue()) { + return TriState.FALSE; } - return super.canonical(tool); + return super.evaluate(constantReflection, forX, forY); } } diff -r 1c347436d596 -r 7766f486f5d6 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowThanNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowThanNode.java Thu Apr 24 10:44:12 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerBelowThanNode.java Thu Apr 24 10:44:12 2014 +0200 @@ -23,18 +23,20 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.meta.ProfilingInfo.*; import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.util.*; @NodeInfo(shortName = "|<|") public final class IntegerBelowThanNode extends CompareNode { /** * Constructs a new unsigned integer comparison node. - * + * * @param x the instruction producing the first input to the instruction * @param y the instruction that produces the second input to this instruction */ @@ -55,28 +57,33 @@ } @Override - public Node canonical(CanonicalizerTool tool) { - if (x() == y()) { - return LogicConstantNode.contradiction(graph()); - } else { - if (x().isConstant() && x().asConstant().asLong() == 0) { - // 0 |<| y is the same as 0 != y - return graph().unique(new LogicNegationNode(CompareNode.createCompareNode(graph(), Condition.EQ, x(), y()))); - } - - if (x().stamp() instanceof IntegerStamp && y().stamp() instanceof IntegerStamp) { - IntegerStamp xStamp = (IntegerStamp) x().stamp(); - IntegerStamp yStamp = (IntegerStamp) y().stamp(); - if (yStamp.isPositive()) { - if (xStamp.isPositive() && xStamp.upperBound() < yStamp.lowerBound()) { - return LogicConstantNode.tautology(graph()); - } else if (xStamp.isStrictlyNegative() || xStamp.lowerBound() >= yStamp.upperBound()) { - return LogicConstantNode.contradiction(graph()); - } + public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) { + if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) { + return TriState.FALSE; + } else if (forX.stamp() instanceof IntegerStamp && forY.stamp() instanceof IntegerStamp) { + IntegerStamp xStamp = (IntegerStamp) forX.stamp(); + IntegerStamp yStamp = (IntegerStamp) forY.stamp(); + if (yStamp.isPositive()) { + if (xStamp.isPositive() && xStamp.upperBound() < yStamp.lowerBound()) { + return TriState.TRUE; + } else if (xStamp.isStrictlyNegative() || xStamp.lowerBound() >= yStamp.upperBound()) { + return TriState.FALSE; } } } + return super.evaluate(constantReflection, forX, forY); + } - return super.canonical(tool); + @Override + public Node canonical(CanonicalizerTool tool) { + Node result = super.canonical(tool); + if (result != this) { + return result; + } + if (x().isConstant() && x().asConstant().asLong() == 0) { + // 0 |<| y is the same as 0 != y + return graph().unique(new LogicNegationNode(CompareNode.createCompareNode(graph(), Condition.EQ, x(), y()))); + } + return this; } } diff -r 1c347436d596 -r 7766f486f5d6 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java Thu Apr 24 10:44:12 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java Thu Apr 24 10:44:12 2014 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.meta.ProfilingInfo.*; import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; @@ -35,7 +36,7 @@ /** * Constructs a new integer equality comparison node. - * + * * @param x the instruction producing the first input to the instruction * @param y the instruction that produces the second input to this instruction */ @@ -71,24 +72,28 @@ } @Override + public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) { + if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) { + return TriState.TRUE; + } else if (forX.stamp().alwaysDistinct(forY.stamp())) { + return TriState.FALSE; + } + return super.evaluate(constantReflection, forX, forY); + } + + @Override public Node canonical(CanonicalizerTool tool) { - if (GraphUtil.unproxify(x()) == GraphUtil.unproxify(y())) { - return LogicConstantNode.tautology(graph()); - } else if (x().stamp().alwaysDistinct(y().stamp())) { - return LogicConstantNode.contradiction(graph()); - } - - ValueNode result = canonicalizeSymmetric(x(), y()); - if (result != null) { + Node result = super.canonical(tool); + if (result != this) { return result; } - result = canonicalizeSymmetric(y(), x()); - if (result != null) { + result = canonicalizeSymmetric(x(), y()); + if (result != this) { return result; } - return super.canonical(tool); + return canonicalizeSymmetric(y(), x()); } private ValueNode canonicalizeSymmetric(ValueNode x, ValueNode y) { @@ -133,6 +138,6 @@ } } } - return null; + return this; } } diff -r 1c347436d596 -r 7766f486f5d6 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerLessThanNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerLessThanNode.java Thu Apr 24 10:44:12 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerLessThanNode.java Thu Apr 24 10:44:12 2014 +0200 @@ -23,18 +23,20 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.meta.ProfilingInfo.*; import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.util.*; @NodeInfo(shortName = "<") public final class IntegerLessThanNode extends CompareNode { /** * Constructs a new integer comparison node. - * + * * @param x the instruction producing the first input to the instruction * @param y the instruction that produces the second input to this instruction */ @@ -71,22 +73,32 @@ } @Override + public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) { + if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) { + return TriState.FALSE; + } else if (forX.stamp() instanceof IntegerStamp && forY.stamp() instanceof IntegerStamp) { + IntegerStamp xStamp = (IntegerStamp) forX.stamp(); + IntegerStamp yStamp = (IntegerStamp) forY.stamp(); + if (xStamp.upperBound() < yStamp.lowerBound()) { + return TriState.TRUE; + } else if (xStamp.lowerBound() >= yStamp.upperBound()) { + return TriState.FALSE; + } + } + return super.evaluate(constantReflection, forX, forY); + } + + @Override public Node canonical(CanonicalizerTool tool) { - if (x() == y()) { - return LogicConstantNode.contradiction(graph()); + Node result = super.canonical(tool); + if (result != this) { + return result; } if (x().stamp() instanceof IntegerStamp && y().stamp() instanceof IntegerStamp) { - IntegerStamp xStamp = (IntegerStamp) x().stamp(); - IntegerStamp yStamp = (IntegerStamp) y().stamp(); - if (xStamp.upperBound() < yStamp.lowerBound()) { - return LogicConstantNode.tautology(graph()); - } else if (xStamp.lowerBound() >= yStamp.upperBound()) { - return LogicConstantNode.contradiction(graph()); - } - if (IntegerStamp.sameSign(xStamp, yStamp)) { + if (IntegerStamp.sameSign((IntegerStamp) x().stamp(), (IntegerStamp) y().stamp())) { return graph().unique(new IntegerBelowThanNode(x(), y())); } } - return super.canonical(tool); + return this; } } diff -r 1c347436d596 -r 7766f486f5d6 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java Thu Apr 24 10:44:12 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerTestNode.java Thu Apr 24 10:44:12 2014 +0200 @@ -22,9 +22,9 @@ */ package com.oracle.graal.nodes.calc; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.meta.ProfilingInfo.TriState; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; /** @@ -32,7 +32,7 @@ * expression "(x & y) == 0", meaning that it will return true if (and only if) no bit is set in * both x and y. */ -public class IntegerTestNode extends BinaryOpLogicNode implements Canonicalizable { +public class IntegerTestNode extends BinaryOpLogicNode { /** * Constructs a new Test instruction. @@ -45,19 +45,19 @@ } @Override - public Node canonical(CanonicalizerTool tool) { - if (x().isConstant() && y().isConstant()) { - return LogicConstantNode.forBoolean((x().asConstant().asLong() & y().asConstant().asLong()) == 0, graph()); + public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) { + if (forX.isConstant() && forY.isConstant()) { + return TriState.get((forX.asConstant().asLong() & forY.asConstant().asLong()) == 0); } if (x().stamp() instanceof IntegerStamp && y().stamp() instanceof IntegerStamp) { - IntegerStamp xStamp = (IntegerStamp) x().stamp(); - IntegerStamp yStamp = (IntegerStamp) y().stamp(); + IntegerStamp xStamp = (IntegerStamp) forX.stamp(); + IntegerStamp yStamp = (IntegerStamp) forY.stamp(); if ((xStamp.upMask() & yStamp.upMask()) == 0) { - return LogicConstantNode.tautology(graph()); + return TriState.TRUE; } else if ((xStamp.downMask() & yStamp.downMask()) != 0) { - return LogicConstantNode.contradiction(graph()); + return TriState.FALSE; } } - return this; + return TriState.UNKNOWN; } } diff -r 1c347436d596 -r 7766f486f5d6 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java Thu Apr 24 10:44:12 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ObjectEqualsNode.java Thu Apr 24 10:44:12 2014 +0200 @@ -23,19 +23,21 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.meta.ProfilingInfo.*; import com.oracle.graal.compiler.common.calc.*; import com.oracle.graal.graph.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; +import com.oracle.graal.nodes.util.*; @NodeInfo(shortName = "==") public final class ObjectEqualsNode extends CompareNode implements Virtualizable { /** * Constructs a new object equality comparison node. - * + * * @param x the instruction producing the first input to the instruction * @param y the instruction that produces the second input to this instruction */ @@ -56,21 +58,28 @@ } @Override + public TriState evaluate(ConstantReflectionProvider constantReflection, ValueNode forX, ValueNode forY) { + if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) { + return TriState.TRUE; + } else if (forX.stamp().alwaysDistinct(forY.stamp())) { + return TriState.FALSE; + } else { + return super.evaluate(constantReflection, forX, forY); + } + } + + @Override public Node canonical(CanonicalizerTool tool) { - if (x() == y()) { - return LogicConstantNode.tautology(graph()); + Node result = super.canonical(tool); + if (result != this) { + return result; } - if (StampTool.isObjectAlwaysNull(x())) { return graph().unique(new IsNullNode(y())); } else if (StampTool.isObjectAlwaysNull(y())) { return graph().unique(new IsNullNode(x())); } - if (x().stamp().alwaysDistinct(y().stamp())) { - return LogicConstantNode.contradiction(graph()); - } - - return super.canonical(tool); + return this; } private void virtualizeNonVirtualComparison(State state, ValueNode other, VirtualizerTool tool) {