1 /*
   2  * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 package org.graalvm.compiler.nodes.calc;
  24 
  25 import org.graalvm.compiler.core.common.calc.Condition;
  26 import org.graalvm.compiler.core.common.type.FloatStamp;
  27 import org.graalvm.compiler.core.common.type.Stamp;
  28 import org.graalvm.compiler.core.common.type.StampFactory;
  29 import org.graalvm.compiler.graph.NodeClass;
  30 import org.graalvm.compiler.graph.spi.CanonicalizerTool;
  31 import org.graalvm.compiler.nodeinfo.NodeCycles;
  32 import org.graalvm.compiler.nodeinfo.NodeInfo;
  33 import org.graalvm.compiler.nodeinfo.NodeSize;
  34 import org.graalvm.compiler.nodes.ConstantNode;
  35 import org.graalvm.compiler.nodes.LogicConstantNode;
  36 import org.graalvm.compiler.nodes.LogicNode;
  37 import org.graalvm.compiler.nodes.ValueNode;
  38 import org.graalvm.compiler.nodes.spi.Lowerable;
  39 import org.graalvm.compiler.nodes.spi.LoweringTool;
  40 
  41 import jdk.vm.ci.meta.ConstantReflectionProvider;
  42 import jdk.vm.ci.meta.JavaKind;
  43 
  44 /**
  45  * Returns -1, 0, or 1 if either x < y, x == y, or x > y. If the comparison is undecided (one
  46  * of the inputs is NaN), the result is 1 if isUnorderedLess is false and -1 if isUnorderedLess is
  47  * true.
  48  */
  49 @NodeInfo(cycles = NodeCycles.CYCLES_2, size = NodeSize.SIZE_4)
  50 public final class NormalizeCompareNode extends BinaryNode implements Lowerable {
  51 
  52     public static final NodeClass<NormalizeCompareNode> TYPE = NodeClass.create(NormalizeCompareNode.class);
  53     protected final boolean isUnorderedLess;
  54 
  55     public NormalizeCompareNode(ValueNode x, ValueNode y, boolean isUnorderedLess) {
  56         super(TYPE, StampFactory.forKind(JavaKind.Int), x, y);
  57         this.isUnorderedLess = isUnorderedLess;
  58     }
  59 
  60     public static ValueNode create(ValueNode x, ValueNode y, boolean isUnorderedLess, ConstantReflectionProvider constantReflection) {
  61         LogicNode result = CompareNode.tryConstantFold(Condition.EQ, x, y, constantReflection, false);
  62         if (result instanceof LogicConstantNode) {
  63             LogicConstantNode logicConstantNode = (LogicConstantNode) result;
  64             LogicNode resultLT = CompareNode.tryConstantFold(Condition.LT, x, y, constantReflection, isUnorderedLess);
  65             if (resultLT instanceof LogicConstantNode) {
  66                 LogicConstantNode logicConstantNodeLT = (LogicConstantNode) resultLT;
  67                 if (logicConstantNodeLT.getValue()) {
  68                     return ConstantNode.forInt(-1);
  69                 } else if (logicConstantNode.getValue()) {
  70                     return ConstantNode.forInt(0);
  71                 } else {
  72                     return ConstantNode.forInt(1);
  73                 }
  74             }
  75         }
  76 
  77         return new NormalizeCompareNode(x, y, isUnorderedLess);
  78     }
  79 
  80     @Override
  81     public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
  82         // nothing to do
  83         return this;
  84     }
  85 
  86     @Override
  87     public boolean inferStamp() {
  88         return false;
  89     }
  90 
  91     @Override
  92     public void lower(LoweringTool tool) {
  93         LogicNode equalComp;
  94         LogicNode lessComp;
  95         if (getX().stamp() instanceof FloatStamp) {
  96             equalComp = graph().unique(FloatEqualsNode.create(getX(), getY(), tool.getConstantReflection()));
  97             lessComp = graph().unique(FloatLessThanNode.create(getX(), getY(), isUnorderedLess, tool.getConstantReflection()));
  98         } else {
  99             equalComp = graph().unique(IntegerEqualsNode.create(getX(), getY(), tool.getConstantReflection()));
 100             lessComp = graph().unique(IntegerLessThanNode.create(getX(), getY(), tool.getConstantReflection()));
 101         }
 102 
 103         ConditionalNode equalValue = graph().unique(new ConditionalNode(equalComp, ConstantNode.forInt(0, graph()), ConstantNode.forInt(1, graph())));
 104         ConditionalNode value = graph().unique(new ConditionalNode(lessComp, ConstantNode.forInt(-1, graph()), equalValue));
 105         replaceAtUsagesAndDelete(value);
 106     }
 107 
 108     @Override
 109     public Stamp foldStamp(Stamp stampX, Stamp stampY) {
 110         return stamp();
 111     }
 112 }