src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/CompareNode.java
changeset 48861 47f19ff9903c
parent 48190 25cfedf27edc
child 49451 e06f9607f370
equal deleted inserted replaced
48860:5bce1b7e7800 48861:47f19ff9903c
    23 package org.graalvm.compiler.nodes.calc;
    23 package org.graalvm.compiler.nodes.calc;
    24 
    24 
    25 import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
    25 import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
    26 import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_1;
    26 import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_1;
    27 
    27 
    28 import jdk.vm.ci.meta.MetaAccessProvider;
    28 import org.graalvm.compiler.core.common.calc.CanonicalCondition;
    29 import org.graalvm.compiler.core.common.calc.Condition;
    29 import org.graalvm.compiler.core.common.calc.Condition;
    30 import org.graalvm.compiler.core.common.type.AbstractObjectStamp;
    30 import org.graalvm.compiler.core.common.type.AbstractObjectStamp;
    31 import org.graalvm.compiler.core.common.type.AbstractPointerStamp;
    31 import org.graalvm.compiler.core.common.type.AbstractPointerStamp;
    32 import org.graalvm.compiler.core.common.type.IntegerStamp;
    32 import org.graalvm.compiler.core.common.type.IntegerStamp;
    33 import org.graalvm.compiler.debug.GraalError;
    33 import org.graalvm.compiler.debug.GraalError;
    40 import org.graalvm.compiler.nodes.LogicNegationNode;
    40 import org.graalvm.compiler.nodes.LogicNegationNode;
    41 import org.graalvm.compiler.nodes.LogicNode;
    41 import org.graalvm.compiler.nodes.LogicNode;
    42 import org.graalvm.compiler.nodes.NodeView;
    42 import org.graalvm.compiler.nodes.NodeView;
    43 import org.graalvm.compiler.nodes.StructuredGraph;
    43 import org.graalvm.compiler.nodes.StructuredGraph;
    44 import org.graalvm.compiler.nodes.ValueNode;
    44 import org.graalvm.compiler.nodes.ValueNode;
       
    45 import org.graalvm.compiler.options.OptionValues;
    45 
    46 
    46 import jdk.vm.ci.meta.Constant;
    47 import jdk.vm.ci.meta.Constant;
    47 import jdk.vm.ci.meta.ConstantReflectionProvider;
    48 import jdk.vm.ci.meta.ConstantReflectionProvider;
       
    49 import jdk.vm.ci.meta.MetaAccessProvider;
    48 import jdk.vm.ci.meta.PrimitiveConstant;
    50 import jdk.vm.ci.meta.PrimitiveConstant;
    49 import org.graalvm.compiler.options.OptionValues;
       
    50 
    51 
    51 @NodeInfo(cycles = CYCLES_1)
    52 @NodeInfo(cycles = CYCLES_1)
    52 public abstract class CompareNode extends BinaryOpLogicNode implements Canonicalizable.Binary<ValueNode> {
    53 public abstract class CompareNode extends BinaryOpLogicNode implements Canonicalizable.Binary<ValueNode> {
    53 
    54 
    54     public static final NodeClass<CompareNode> TYPE = NodeClass.create(CompareNode.class);
    55     public static final NodeClass<CompareNode> TYPE = NodeClass.create(CompareNode.class);
    55     protected final Condition condition;
    56     protected final CanonicalCondition condition;
    56     protected final boolean unorderedIsTrue;
    57     protected final boolean unorderedIsTrue;
    57 
    58 
    58     /**
    59     /**
    59      * Constructs a new Compare instruction.
    60      * Constructs a new Compare instruction.
    60      *
    61      *
    61      * @param x the instruction producing the first input to the instruction
    62      * @param x the instruction producing the first input to the instruction
    62      * @param y the instruction that produces the second input to this instruction
    63      * @param y the instruction that produces the second input to this instruction
    63      */
    64      */
    64     protected CompareNode(NodeClass<? extends CompareNode> c, Condition condition, boolean unorderedIsTrue, ValueNode x, ValueNode y) {
    65     protected CompareNode(NodeClass<? extends CompareNode> c, CanonicalCondition condition, boolean unorderedIsTrue, ValueNode x, ValueNode y) {
    65         super(c, x, y);
    66         super(c, x, y);
    66         this.condition = condition;
    67         this.condition = condition;
    67         this.unorderedIsTrue = unorderedIsTrue;
    68         this.unorderedIsTrue = unorderedIsTrue;
    68     }
    69     }
    69 
    70 
    70     /**
    71     /**
    71      * Gets the condition (comparison operation) for this instruction.
    72      * Gets the condition (comparison operation) for this instruction.
    72      *
    73      *
    73      * @return the condition
    74      * @return the condition
    74      */
    75      */
    75     public final Condition condition() {
    76     public final CanonicalCondition condition() {
    76         return condition;
    77         return condition;
    77     }
    78     }
    78 
    79 
    79     /**
    80     /**
    80      * Checks whether unordered inputs mean true or false (only applies to float operations).
    81      * Checks whether unordered inputs mean true or false (only applies to float operations).
    83      */
    84      */
    84     public final boolean unorderedIsTrue() {
    85     public final boolean unorderedIsTrue() {
    85         return this.unorderedIsTrue;
    86         return this.unorderedIsTrue;
    86     }
    87     }
    87 
    88 
    88     public static LogicNode tryConstantFold(Condition condition, ValueNode forX, ValueNode forY, ConstantReflectionProvider constantReflection, boolean unorderedIsTrue) {
    89     public static LogicNode tryConstantFold(CanonicalCondition condition, ValueNode forX, ValueNode forY, ConstantReflectionProvider constantReflection, boolean unorderedIsTrue) {
    89         if (forX.isConstant() && forY.isConstant() && (constantReflection != null || forX.asConstant() instanceof PrimitiveConstant)) {
    90         if (forX.isConstant() && forY.isConstant() && (constantReflection != null || forX.asConstant() instanceof PrimitiveConstant)) {
    90             return LogicConstantNode.forBoolean(condition.foldCondition(forX.asConstant(), forY.asConstant(), constantReflection, unorderedIsTrue));
    91             return LogicConstantNode.forBoolean(condition.foldCondition(forX.asConstant(), forY.asConstant(), constantReflection, unorderedIsTrue));
    91         }
    92         }
    92         return null;
    93         return null;
    93     }
    94     }
    94 
    95 
    95     @SuppressWarnings("unused")
    96     @SuppressWarnings("unused")
    96     public static LogicNode tryConstantFoldPrimitive(Condition condition, ValueNode forX, ValueNode forY, boolean unorderedIsTrue, NodeView view) {
    97     public static LogicNode tryConstantFoldPrimitive(CanonicalCondition condition, ValueNode forX, ValueNode forY, boolean unorderedIsTrue, NodeView view) {
    97         if (forX.asConstant() instanceof PrimitiveConstant && forY.asConstant() instanceof PrimitiveConstant) {
    98         if (forX.asConstant() instanceof PrimitiveConstant && forY.asConstant() instanceof PrimitiveConstant) {
    98             return LogicConstantNode.forBoolean(condition.foldCondition((PrimitiveConstant) forX.asConstant(), (PrimitiveConstant) forY.asConstant(), unorderedIsTrue));
    99             return LogicConstantNode.forBoolean(condition.foldCondition((PrimitiveConstant) forX.asConstant(), (PrimitiveConstant) forY.asConstant(), unorderedIsTrue));
    99         }
   100         }
   100         return null;
   101         return null;
   101     }
   102     }
   105      * thing as y. This is generally true except for some floating point comparisons.
   106      * thing as y. This is generally true except for some floating point comparisons.
   106      *
   107      *
   107      * @return true for identity comparisons
   108      * @return true for identity comparisons
   108      */
   109      */
   109     public boolean isIdentityComparison() {
   110     public boolean isIdentityComparison() {
   110         return condition == Condition.EQ;
   111         return condition == CanonicalCondition.EQ;
   111     }
   112     }
   112 
   113 
   113     public abstract static class CompareOp {
   114     public abstract static class CompareOp {
   114         public LogicNode canonical(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, Condition condition,
   115         public LogicNode canonical(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth, CanonicalCondition condition,
   115                         boolean unorderedIsTrue, ValueNode forX, ValueNode forY, NodeView view) {
   116                         boolean unorderedIsTrue, ValueNode forX, ValueNode forY, NodeView view) {
   116             LogicNode constantCondition = tryConstantFold(condition, forX, forY, constantReflection, unorderedIsTrue);
   117             LogicNode constantCondition = tryConstantFold(condition, forX, forY, constantReflection, unorderedIsTrue);
   117             if (constantCondition != null) {
   118             if (constantCondition != null) {
   118                 return constantCondition;
   119                 return constantCondition;
   119             }
   120             }
   149             }
   150             }
   150             return null;
   151             return null;
   151         }
   152         }
   152 
   153 
   153         protected LogicNode canonicalizeSymmetricConstant(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth,
   154         protected LogicNode canonicalizeSymmetricConstant(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth,
   154                         Condition condition, Constant constant, ValueNode nonConstant, boolean mirrored, boolean unorderedIsTrue, NodeView view) {
   155                         CanonicalCondition condition, Constant constant, ValueNode nonConstant, boolean mirrored, boolean unorderedIsTrue, NodeView view) {
   155             if (nonConstant instanceof ConditionalNode) {
   156             if (nonConstant instanceof ConditionalNode) {
   156                 return optimizeConditional(constant, (ConditionalNode) nonConstant, constantReflection, mirrored ? condition.mirror() : condition, unorderedIsTrue);
   157                 Condition realCondition = condition.asCondition();
       
   158                 if (mirrored) {
       
   159                     realCondition = realCondition.mirror();
       
   160                 }
       
   161                 return optimizeConditional(constant, (ConditionalNode) nonConstant, constantReflection, realCondition, unorderedIsTrue);
   157             } else if (nonConstant instanceof NormalizeCompareNode) {
   162             } else if (nonConstant instanceof NormalizeCompareNode) {
   158                 return optimizeNormalizeCompare(constantReflection, metaAccess, options, smallestCompareWidth, constant, (NormalizeCompareNode) nonConstant, mirrored, view);
   163                 return optimizeNormalizeCompare(constantReflection, metaAccess, options, smallestCompareWidth, constant, (NormalizeCompareNode) nonConstant, mirrored, view);
   159             } else if (nonConstant instanceof ConvertNode) {
   164             } else if (nonConstant instanceof ConvertNode) {
   160                 ConvertNode convert = (ConvertNode) nonConstant;
   165                 ConvertNode convert = (ConvertNode) nonConstant;
   161                 boolean multiUsage = (convert.asNode().hasMoreThanOneUsage() && convert.getValue().hasExactlyOneUsage());
   166                 boolean multiUsage = (convert.asNode().hasMoreThanOneUsage() && convert.getValue().hasExactlyOneUsage());
   184             }
   189             }
   185 
   190 
   186             return null;
   191             return null;
   187         }
   192         }
   188 
   193 
   189         private static ConstantNode canonicalConvertConstant(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Condition condition,
   194         private static ConstantNode canonicalConvertConstant(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, CanonicalCondition condition,
   190                         ConvertNode convert, Constant constant, NodeView view) {
   195                         ConvertNode convert, Constant constant, NodeView view) {
   191             if (convert.preservesOrder(condition, constant, constantReflection)) {
   196             if (convert.preservesOrder(condition, constant, constantReflection)) {
   192                 Constant reverseConverted = convert.reverse(constant, constantReflection);
   197                 Constant reverseConverted = convert.reverse(constant, constantReflection);
   193                 if (reverseConverted != null && convert.convert(reverseConverted, constantReflection).equals(constant)) {
   198                 if (reverseConverted != null && convert.convert(reverseConverted, constantReflection).equals(constant)) {
   194                     if (GeneratePIC.getValue(options)) {
   199                     if (GeneratePIC.getValue(options)) {
   233         }
   238         }
   234 
   239 
   235         protected abstract LogicNode duplicateModified(ValueNode newW, ValueNode newY, boolean unorderedIsTrue, NodeView view);
   240         protected abstract LogicNode duplicateModified(ValueNode newW, ValueNode newY, boolean unorderedIsTrue, NodeView view);
   236     }
   241     }
   237 
   242 
   238     public static LogicNode createCompareNode(StructuredGraph graph, Condition condition, ValueNode x, ValueNode y, ConstantReflectionProvider constantReflection, NodeView view) {
   243     public static LogicNode createCompareNode(StructuredGraph graph, CanonicalCondition condition, ValueNode x, ValueNode y, ConstantReflectionProvider constantReflection, NodeView view) {
   239         LogicNode result = createCompareNode(condition, x, y, constantReflection, view);
   244         LogicNode result = createCompareNode(condition, x, y, constantReflection, view);
   240         return (result.graph() == null ? graph.addOrUniqueWithInputs(result) : result);
   245         return (result.graph() == null ? graph.addOrUniqueWithInputs(result) : result);
   241     }
   246     }
   242 
   247 
   243     public static LogicNode createCompareNode(Condition condition, ValueNode x, ValueNode y, ConstantReflectionProvider constantReflection, NodeView view) {
   248     public static LogicNode createCompareNode(CanonicalCondition condition, ValueNode x, ValueNode y, ConstantReflectionProvider constantReflection, NodeView view) {
   244         assert x.getStackKind() == y.getStackKind();
   249         assert x.getStackKind() == y.getStackKind();
   245         assert condition.isCanonical();
       
   246         assert !x.getStackKind().isNumericFloat();
   250         assert !x.getStackKind().isNumericFloat();
   247 
   251 
   248         LogicNode comparison;
   252         LogicNode comparison;
   249         if (condition == Condition.EQ) {
   253         if (condition == CanonicalCondition.EQ) {
   250             if (x.stamp(view) instanceof AbstractObjectStamp) {
   254             if (x.stamp(view) instanceof AbstractObjectStamp) {
   251                 comparison = ObjectEqualsNode.create(x, y, constantReflection, view);
   255                 comparison = ObjectEqualsNode.create(x, y, constantReflection, view);
   252             } else if (x.stamp(view) instanceof AbstractPointerStamp) {
   256             } else if (x.stamp(view) instanceof AbstractPointerStamp) {
   253                 comparison = PointerEqualsNode.create(x, y, view);
   257                 comparison = PointerEqualsNode.create(x, y, view);
   254             } else {
   258             } else {
   255                 assert x.getStackKind().isNumericInteger();
   259                 assert x.getStackKind().isNumericInteger();
   256                 comparison = IntegerEqualsNode.create(x, y, view);
   260                 comparison = IntegerEqualsNode.create(x, y, view);
   257             }
   261             }
   258         } else if (condition == Condition.LT) {
   262         } else if (condition == CanonicalCondition.LT) {
   259             assert x.getStackKind().isNumericInteger();
   263             assert x.getStackKind().isNumericInteger();
   260             comparison = IntegerLessThanNode.create(x, y, view);
   264             comparison = IntegerLessThanNode.create(x, y, view);
   261         } else {
   265         } else {
   262             assert condition == Condition.BT;
   266             assert condition == CanonicalCondition.BT;
   263             assert x.getStackKind().isNumericInteger();
   267             assert x.getStackKind().isNumericInteger();
   264             comparison = IntegerBelowNode.create(x, y, view);
   268             comparison = IntegerBelowNode.create(x, y, view);
   265         }
   269         }
   266 
   270 
   267         return comparison;
   271         return comparison;
   268     }
   272     }
   269 
   273 
   270     public static LogicNode createCompareNode(StructuredGraph graph, ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth,
   274     public static LogicNode createCompareNode(StructuredGraph graph, ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth,
   271                     Condition condition, ValueNode x, ValueNode y, NodeView view) {
   275                     CanonicalCondition condition, ValueNode x, ValueNode y, NodeView view) {
   272         LogicNode result = createCompareNode(constantReflection, metaAccess, options, smallestCompareWidth, condition, x, y, view);
   276         LogicNode result = createCompareNode(constantReflection, metaAccess, options, smallestCompareWidth, condition, x, y, view);
   273         return (result.graph() == null ? graph.addOrUniqueWithInputs(result) : result);
   277         return (result.graph() == null ? graph.addOrUniqueWithInputs(result) : result);
   274     }
   278     }
   275 
   279 
   276     public static LogicNode createCompareNode(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth,
   280     public static LogicNode createCompareNode(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth,
   277                     Condition condition, ValueNode x, ValueNode y, NodeView view) {
   281                     CanonicalCondition condition, ValueNode x, ValueNode y, NodeView view) {
   278         assert x.getStackKind() == y.getStackKind();
   282         assert x.getStackKind() == y.getStackKind();
   279         assert condition.isCanonical();
       
   280         assert !x.getStackKind().isNumericFloat();
   283         assert !x.getStackKind().isNumericFloat();
   281 
   284 
   282         LogicNode comparison;
   285         LogicNode comparison;
   283         if (condition == Condition.EQ) {
   286         if (condition == CanonicalCondition.EQ) {
   284             if (x.stamp(view) instanceof AbstractObjectStamp) {
   287             if (x.stamp(view) instanceof AbstractObjectStamp) {
   285                 assert smallestCompareWidth == null;
   288                 assert smallestCompareWidth == null;
   286                 comparison = ObjectEqualsNode.create(constantReflection, metaAccess, options, x, y, view);
   289                 comparison = ObjectEqualsNode.create(constantReflection, metaAccess, options, x, y, view);
   287             } else if (x.stamp(view) instanceof AbstractPointerStamp) {
   290             } else if (x.stamp(view) instanceof AbstractPointerStamp) {
   288                 comparison = PointerEqualsNode.create(x, y, view);
   291                 comparison = PointerEqualsNode.create(x, y, view);
   289             } else {
   292             } else {
   290                 assert x.getStackKind().isNumericInteger();
   293                 assert x.getStackKind().isNumericInteger();
   291                 comparison = IntegerEqualsNode.create(constantReflection, metaAccess, options, smallestCompareWidth, x, y, view);
   294                 comparison = IntegerEqualsNode.create(constantReflection, metaAccess, options, smallestCompareWidth, x, y, view);
   292             }
   295             }
   293         } else if (condition == Condition.LT) {
   296         } else if (condition == CanonicalCondition.LT) {
   294             assert x.getStackKind().isNumericInteger();
   297             assert x.getStackKind().isNumericInteger();
   295             comparison = IntegerLessThanNode.create(constantReflection, metaAccess, options, smallestCompareWidth, x, y, view);
   298             comparison = IntegerLessThanNode.create(constantReflection, metaAccess, options, smallestCompareWidth, x, y, view);
   296         } else {
   299         } else {
   297             assert condition == Condition.BT;
   300             assert condition == CanonicalCondition.BT;
   298             assert x.getStackKind().isNumericInteger();
   301             assert x.getStackKind().isNumericInteger();
   299             comparison = IntegerBelowNode.create(constantReflection, metaAccess, options, smallestCompareWidth, x, y, view);
   302             comparison = IntegerBelowNode.create(constantReflection, metaAccess, options, smallestCompareWidth, x, y, view);
   300         }
   303         }
   301 
   304 
   302         return comparison;
   305         return comparison;