1 /* 2 * Copyright (c) 2011, 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.AbstractPointerStamp; 27 import org.graalvm.compiler.core.common.type.FloatStamp; 28 import org.graalvm.compiler.core.common.type.IntegerStamp; 29 import org.graalvm.compiler.core.common.type.Stamp; 30 import org.graalvm.compiler.debug.GraalError; 31 import org.graalvm.compiler.graph.IterableNodeType; 32 import org.graalvm.compiler.graph.NodeClass; 33 import org.graalvm.compiler.graph.spi.Canonicalizable.BinaryCommutative; 34 import org.graalvm.compiler.graph.spi.CanonicalizerTool; 35 import org.graalvm.compiler.nodeinfo.NodeInfo; 36 import org.graalvm.compiler.nodes.ConstantNode; 37 import org.graalvm.compiler.nodes.LogicConstantNode; 38 import org.graalvm.compiler.nodes.LogicNegationNode; 39 import org.graalvm.compiler.nodes.LogicNode; 40 import org.graalvm.compiler.nodes.ValueNode; 41 import org.graalvm.compiler.nodes.util.GraphUtil; 42 43 import jdk.vm.ci.meta.Constant; 44 import jdk.vm.ci.meta.ConstantReflectionProvider; 45 import jdk.vm.ci.meta.JavaKind; 46 import jdk.vm.ci.meta.PrimitiveConstant; 47 import jdk.vm.ci.meta.TriState; 48 49 @NodeInfo(shortName = "==") 50 public final class IntegerEqualsNode extends CompareNode implements BinaryCommutative<ValueNode>, IterableNodeType { 51 public static final NodeClass<IntegerEqualsNode> TYPE = NodeClass.create(IntegerEqualsNode.class); 52 53 public IntegerEqualsNode(ValueNode x, ValueNode y) { 54 super(TYPE, Condition.EQ, false, x, y); 55 assert !x.getStackKind().isNumericFloat() && x.getStackKind() != JavaKind.Object; 56 assert !y.getStackKind().isNumericFloat() && y.getStackKind() != JavaKind.Object; 57 } 58 59 public static LogicNode create(ValueNode x, ValueNode y, ConstantReflectionProvider constantReflection) { 60 LogicNode result = CompareNode.tryConstantFold(Condition.EQ, x, y, constantReflection, false); 61 if (result != null) { 62 return result; 63 } else { 64 if (x instanceof ConditionalNode) { 65 ConditionalNode conditionalNode = (ConditionalNode) x; 66 if (conditionalNode.trueValue() == y) { 67 return conditionalNode.condition(); 68 } 69 if (conditionalNode.falseValue() == y) { 70 return LogicNegationNode.create(conditionalNode.condition()); 71 } 72 } else if (y instanceof ConditionalNode) { 73 ConditionalNode conditionalNode = (ConditionalNode) y; 74 if (conditionalNode.trueValue() == x) { 75 return conditionalNode.condition(); 76 } 77 if (conditionalNode.falseValue() == x) { 78 return LogicNegationNode.create(conditionalNode.condition()); 79 } 80 } 81 82 return new IntegerEqualsNode(x, y).maybeCommuteInputs(); 83 } 84 } 85 86 @Override 87 protected ValueNode optimizeNormalizeCmp(Constant constant, NormalizeCompareNode normalizeNode, boolean mirrored) { 88 PrimitiveConstant primitive = (PrimitiveConstant) constant; 89 if (primitive.getJavaKind() == JavaKind.Int && primitive.asInt() == 0) { 90 ValueNode a = mirrored ? normalizeNode.getY() : normalizeNode.getX(); 91 ValueNode b = mirrored ? normalizeNode.getX() : normalizeNode.getY(); 92 93 if (normalizeNode.getX().getStackKind() == JavaKind.Double || normalizeNode.getX().getStackKind() == JavaKind.Float) { 94 return new FloatEqualsNode(a, b); 95 } else { 96 return new IntegerEqualsNode(a, b); 97 } 98 } 99 return this; 100 } 101 102 @Override 103 protected CompareNode duplicateModified(ValueNode newX, ValueNode newY) { 104 if (newX.stamp() instanceof FloatStamp && newY.stamp() instanceof FloatStamp) { 105 return new FloatEqualsNode(newX, newY); 106 } else if (newX.stamp() instanceof IntegerStamp && newY.stamp() instanceof IntegerStamp) { 107 return new IntegerEqualsNode(newX, newY); 108 } else if (newX.stamp() instanceof AbstractPointerStamp && newY.stamp() instanceof AbstractPointerStamp) { 109 return new IntegerEqualsNode(newX, newY); 110 } 111 throw GraalError.shouldNotReachHere(); 112 } 113 114 @Override 115 public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { 116 if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) { 117 return LogicConstantNode.tautology(); 118 } else if (forX.stamp().alwaysDistinct(forY.stamp())) { 119 return LogicConstantNode.contradiction(); 120 } 121 return super.canonical(tool, forX, forY); 122 } 123 124 @Override 125 protected ValueNode canonicalizeSymmetricConstant(CanonicalizerTool tool, Constant constant, ValueNode nonConstant, boolean mirrored) { 126 if (constant instanceof PrimitiveConstant && ((PrimitiveConstant) constant).asLong() == 0) { 127 if (nonConstant instanceof AndNode) { 128 AndNode andNode = (AndNode) nonConstant; 129 return new IntegerTestNode(andNode.getX(), andNode.getY()); 130 } else if (nonConstant instanceof SubNode) { 131 SubNode subNode = (SubNode) nonConstant; 132 return IntegerEqualsNode.create(subNode.getX(), subNode.getY(), tool.getConstantReflection()); 133 } else if (nonConstant instanceof ShiftNode && nonConstant.stamp() instanceof IntegerStamp) { 134 if (nonConstant instanceof LeftShiftNode) { 135 LeftShiftNode shift = (LeftShiftNode) nonConstant; 136 if (shift.getY().isConstant()) { 137 int mask = shift.getShiftAmountMask(); 138 int amount = shift.getY().asJavaConstant().asInt() & mask; 139 if (shift.getX().getStackKind() == JavaKind.Int) { 140 return new IntegerTestNode(shift.getX(), ConstantNode.forInt(-1 >>> amount)); 141 } else { 142 assert shift.getX().getStackKind() == JavaKind.Long; 143 return new IntegerTestNode(shift.getX(), ConstantNode.forLong(-1L >>> amount)); 144 } 145 } 146 } else if (nonConstant instanceof RightShiftNode) { 147 RightShiftNode shift = (RightShiftNode) nonConstant; 148 if (shift.getY().isConstant() && ((IntegerStamp) shift.getX().stamp()).isPositive()) { 149 int mask = shift.getShiftAmountMask(); 150 int amount = shift.getY().asJavaConstant().asInt() & mask; 151 if (shift.getX().getStackKind() == JavaKind.Int) { 152 return new IntegerTestNode(shift.getX(), ConstantNode.forInt(-1 << amount)); 153 } else { 154 assert shift.getX().getStackKind() == JavaKind.Long; 155 return new IntegerTestNode(shift.getX(), ConstantNode.forLong(-1L << amount)); 156 } 157 } 158 } else if (nonConstant instanceof UnsignedRightShiftNode) { 159 UnsignedRightShiftNode shift = (UnsignedRightShiftNode) nonConstant; 160 if (shift.getY().isConstant()) { 161 int mask = shift.getShiftAmountMask(); 162 int amount = shift.getY().asJavaConstant().asInt() & mask; 163 if (shift.getX().getStackKind() == JavaKind.Int) { 164 return new IntegerTestNode(shift.getX(), ConstantNode.forInt(-1 << amount)); 165 } else { 166 assert shift.getX().getStackKind() == JavaKind.Long; 167 return new IntegerTestNode(shift.getX(), ConstantNode.forLong(-1L << amount)); 168 } 169 } 170 } 171 } 172 } 173 if (nonConstant instanceof AndNode) { 174 /* 175 * a & c == c is the same as a & c != 0, if c is a single bit. 176 */ 177 AndNode andNode = (AndNode) nonConstant; 178 if (constant instanceof PrimitiveConstant && Long.bitCount(((PrimitiveConstant) constant).asLong()) == 1 && andNode.getY().isConstant() && 179 andNode.getY().asJavaConstant().equals(constant)) { 180 return new LogicNegationNode(new IntegerTestNode(andNode.getX(), andNode.getY())); 181 } 182 } 183 return super.canonicalizeSymmetricConstant(tool, constant, nonConstant, mirrored); 184 } 185 186 @Override 187 public Stamp getSucceedingStampForX(boolean negated) { 188 if (!negated) { 189 return getX().stamp().join(getY().stamp()); 190 } 191 return null; 192 } 193 194 @Override 195 public Stamp getSucceedingStampForY(boolean negated) { 196 if (!negated) { 197 return getX().stamp().join(getY().stamp()); 198 } 199 return null; 200 } 201 202 @Override 203 public TriState tryFold(Stamp xStampGeneric, Stamp yStampGeneric) { 204 if (xStampGeneric instanceof IntegerStamp && yStampGeneric instanceof IntegerStamp) { 205 IntegerStamp xStamp = (IntegerStamp) xStampGeneric; 206 IntegerStamp yStamp = (IntegerStamp) yStampGeneric; 207 if (xStamp.alwaysDistinct(yStamp)) { 208 return TriState.FALSE; 209 } else if (xStamp.neverDistinct(yStamp)) { 210 return TriState.TRUE; 211 } 212 } 213 return TriState.UNKNOWN; 214 } 215 }