001/* 002 * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.nodes.calc; 024 025import jdk.internal.jvmci.common.*; 026import jdk.internal.jvmci.meta.*; 027 028import com.oracle.graal.compiler.common.calc.*; 029import com.oracle.graal.compiler.common.type.*; 030import com.oracle.graal.graph.*; 031import com.oracle.graal.graph.spi.Canonicalizable.BinaryCommutative; 032import com.oracle.graal.graph.spi.*; 033import com.oracle.graal.nodeinfo.*; 034import com.oracle.graal.nodes.*; 035import com.oracle.graal.nodes.util.*; 036 037@NodeInfo(shortName = "==") 038public final class IntegerEqualsNode extends CompareNode implements BinaryCommutative<ValueNode> { 039 public static final NodeClass<IntegerEqualsNode> TYPE = NodeClass.create(IntegerEqualsNode.class); 040 041 public IntegerEqualsNode(ValueNode x, ValueNode y) { 042 super(TYPE, Condition.EQ, false, x, y); 043 assert !x.getKind().isNumericFloat() && x.getKind() != Kind.Object; 044 assert !y.getKind().isNumericFloat() && y.getKind() != Kind.Object; 045 } 046 047 public static LogicNode create(ValueNode x, ValueNode y, ConstantReflectionProvider constantReflection) { 048 LogicNode result = CompareNode.tryConstantFold(Condition.EQ, x, y, constantReflection, false); 049 if (result != null) { 050 return result; 051 } else { 052 if (x instanceof ConditionalNode) { 053 ConditionalNode conditionalNode = (ConditionalNode) x; 054 if (conditionalNode.trueValue() == y) { 055 return conditionalNode.condition(); 056 } 057 if (conditionalNode.falseValue() == y) { 058 return LogicNegationNode.create(conditionalNode.condition()); 059 } 060 } else if (y instanceof ConditionalNode) { 061 ConditionalNode conditionalNode = (ConditionalNode) y; 062 if (conditionalNode.trueValue() == x) { 063 return conditionalNode.condition(); 064 } 065 if (conditionalNode.falseValue() == x) { 066 return LogicNegationNode.create(conditionalNode.condition()); 067 } 068 } 069 070 return new IntegerEqualsNode(x, y).maybeCommuteInputs(); 071 } 072 } 073 074 @Override 075 protected ValueNode optimizeNormalizeCmp(Constant constant, NormalizeCompareNode normalizeNode, boolean mirrored) { 076 PrimitiveConstant primitive = (PrimitiveConstant) constant; 077 if (primitive.getKind() == Kind.Int && primitive.asInt() == 0) { 078 ValueNode a = mirrored ? normalizeNode.getY() : normalizeNode.getX(); 079 ValueNode b = mirrored ? normalizeNode.getX() : normalizeNode.getY(); 080 081 if (normalizeNode.getX().getKind() == Kind.Double || normalizeNode.getX().getKind() == Kind.Float) { 082 return new FloatEqualsNode(a, b); 083 } else { 084 return new IntegerEqualsNode(a, b); 085 } 086 } 087 return this; 088 } 089 090 @Override 091 protected CompareNode duplicateModified(ValueNode newX, ValueNode newY) { 092 if (newX.stamp() instanceof FloatStamp && newY.stamp() instanceof FloatStamp) { 093 return new FloatEqualsNode(newX, newY); 094 } else if (newX.stamp() instanceof IntegerStamp && newY.stamp() instanceof IntegerStamp) { 095 return new IntegerEqualsNode(newX, newY); 096 } else if (newX.stamp() instanceof AbstractPointerStamp && newY.stamp() instanceof AbstractPointerStamp) { 097 return new IntegerEqualsNode(newX, newY); 098 } 099 throw JVMCIError.shouldNotReachHere(); 100 } 101 102 @Override 103 public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { 104 if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) { 105 return LogicConstantNode.tautology(); 106 } else if (forX.stamp().alwaysDistinct(forY.stamp())) { 107 return LogicConstantNode.contradiction(); 108 } 109 return super.canonical(tool, forX, forY); 110 } 111 112 @Override 113 protected ValueNode canonicalizeSymmetricConstant(CanonicalizerTool tool, Constant constant, ValueNode nonConstant, boolean mirrored) { 114 if (constant instanceof PrimitiveConstant && ((PrimitiveConstant) constant).asLong() == 0) { 115 if (nonConstant instanceof AndNode) { 116 AndNode andNode = (AndNode) nonConstant; 117 return new IntegerTestNode(andNode.getX(), andNode.getY()); 118 } else if (nonConstant instanceof ShiftNode && nonConstant.stamp() instanceof IntegerStamp) { 119 if (nonConstant instanceof LeftShiftNode) { 120 LeftShiftNode shift = (LeftShiftNode) nonConstant; 121 if (shift.getY().isConstant()) { 122 int mask = shift.getShiftAmountMask(); 123 int amount = shift.getY().asJavaConstant().asInt() & mask; 124 if (shift.getX().getKind() == Kind.Int) { 125 return new IntegerTestNode(shift.getX(), ConstantNode.forInt(-1 >>> amount)); 126 } else { 127 assert shift.getX().getKind() == Kind.Long; 128 return new IntegerTestNode(shift.getX(), ConstantNode.forLong(-1L >>> amount)); 129 } 130 } 131 } else if (nonConstant instanceof RightShiftNode) { 132 RightShiftNode shift = (RightShiftNode) nonConstant; 133 if (shift.getY().isConstant() && ((IntegerStamp) shift.getX().stamp()).isPositive()) { 134 int mask = shift.getShiftAmountMask(); 135 int amount = shift.getY().asJavaConstant().asInt() & mask; 136 if (shift.getX().getKind() == Kind.Int) { 137 return new IntegerTestNode(shift.getX(), ConstantNode.forInt(-1 << amount)); 138 } else { 139 assert shift.getX().getKind() == Kind.Long; 140 return new IntegerTestNode(shift.getX(), ConstantNode.forLong(-1L << amount)); 141 } 142 } 143 } else if (nonConstant instanceof UnsignedRightShiftNode) { 144 UnsignedRightShiftNode shift = (UnsignedRightShiftNode) nonConstant; 145 if (shift.getY().isConstant()) { 146 int mask = shift.getShiftAmountMask(); 147 int amount = shift.getY().asJavaConstant().asInt() & mask; 148 if (shift.getX().getKind() == Kind.Int) { 149 return new IntegerTestNode(shift.getX(), ConstantNode.forInt(-1 << amount)); 150 } else { 151 assert shift.getX().getKind() == Kind.Long; 152 return new IntegerTestNode(shift.getX(), ConstantNode.forLong(-1L << amount)); 153 } 154 } 155 } 156 } 157 } 158 return super.canonicalizeSymmetricConstant(tool, constant, nonConstant, mirrored); 159 } 160 161 @Override 162 public Stamp getSucceedingStampForX(boolean negated) { 163 if (!negated) { 164 return getX().stamp().join(getY().stamp()); 165 } 166 return null; 167 } 168 169 @Override 170 public Stamp getSucceedingStampForY(boolean negated) { 171 if (!negated) { 172 return getX().stamp().join(getY().stamp()); 173 } 174 return null; 175 } 176 177 @Override 178 public TriState tryFold(Stamp xStampGeneric, Stamp yStampGeneric) { 179 if (xStampGeneric instanceof IntegerStamp && yStampGeneric instanceof IntegerStamp) { 180 IntegerStamp xStamp = (IntegerStamp) xStampGeneric; 181 IntegerStamp yStamp = (IntegerStamp) yStampGeneric; 182 if (xStamp.alwaysDistinct(yStamp)) { 183 return TriState.FALSE; 184 } else if (xStamp.neverDistinct(yStamp)) { 185 return TriState.TRUE; 186 } 187 } 188 return TriState.UNKNOWN; 189 } 190}