IntegerEqualsNode.java revision 12651:6ef01bd40ce2
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 */
23package org.graalvm.compiler.nodes.calc;
24
25import org.graalvm.compiler.core.common.calc.Condition;
26import org.graalvm.compiler.core.common.type.AbstractPointerStamp;
27import org.graalvm.compiler.core.common.type.FloatStamp;
28import org.graalvm.compiler.core.common.type.IntegerStamp;
29import org.graalvm.compiler.core.common.type.Stamp;
30import org.graalvm.compiler.debug.GraalError;
31import org.graalvm.compiler.graph.IterableNodeType;
32import org.graalvm.compiler.graph.NodeClass;
33import org.graalvm.compiler.graph.spi.Canonicalizable.BinaryCommutative;
34import org.graalvm.compiler.graph.spi.CanonicalizerTool;
35import org.graalvm.compiler.nodeinfo.NodeInfo;
36import org.graalvm.compiler.nodes.ConstantNode;
37import org.graalvm.compiler.nodes.LogicConstantNode;
38import org.graalvm.compiler.nodes.LogicNegationNode;
39import org.graalvm.compiler.nodes.LogicNode;
40import org.graalvm.compiler.nodes.ValueNode;
41import org.graalvm.compiler.nodes.util.GraphUtil;
42
43import jdk.vm.ci.meta.Constant;
44import jdk.vm.ci.meta.ConstantReflectionProvider;
45import jdk.vm.ci.meta.JavaKind;
46import jdk.vm.ci.meta.PrimitiveConstant;
47import jdk.vm.ci.meta.TriState;
48
49@NodeInfo(shortName = "==")
50public 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}
216