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}