FloatEqualsNode.java revision 12968:4d8a004e5c6d
1/*
2 * Copyright (c) 2011, 2014, 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.FloatStamp;
27import org.graalvm.compiler.core.common.type.IntegerStamp;
28import org.graalvm.compiler.core.common.type.Stamp;
29import org.graalvm.compiler.debug.GraalError;
30import org.graalvm.compiler.graph.NodeClass;
31import org.graalvm.compiler.graph.spi.Canonicalizable.BinaryCommutative;
32import org.graalvm.compiler.graph.spi.CanonicalizerTool;
33import org.graalvm.compiler.nodeinfo.NodeCycles;
34import org.graalvm.compiler.nodeinfo.NodeInfo;
35import org.graalvm.compiler.nodes.LogicConstantNode;
36import org.graalvm.compiler.nodes.LogicNode;
37import org.graalvm.compiler.nodes.ValueNode;
38import org.graalvm.compiler.nodes.util.GraphUtil;
39
40import jdk.vm.ci.meta.ConstantReflectionProvider;
41import jdk.vm.ci.meta.TriState;
42
43@NodeInfo(shortName = "==", cycles = NodeCycles.CYCLES_3)
44public final class FloatEqualsNode extends CompareNode implements BinaryCommutative<ValueNode> {
45    public static final NodeClass<FloatEqualsNode> TYPE = NodeClass.create(FloatEqualsNode.class);
46
47    public FloatEqualsNode(ValueNode x, ValueNode y) {
48        super(TYPE, Condition.EQ, false, x, y);
49        assert x.stamp() instanceof FloatStamp && y.stamp() instanceof FloatStamp : x.stamp() + " " + y.stamp();
50        assert x.stamp().isCompatible(y.stamp());
51    }
52
53    public static LogicNode create(ValueNode x, ValueNode y, ConstantReflectionProvider constantReflection) {
54        LogicNode result = CompareNode.tryConstantFold(Condition.EQ, x, y, constantReflection, false);
55        if (result != null) {
56            return result;
57        } else {
58            return new FloatEqualsNode(x, y).maybeCommuteInputs();
59        }
60    }
61
62    @Override
63    public boolean isIdentityComparison() {
64        FloatStamp xStamp = (FloatStamp) x.stamp();
65        FloatStamp yStamp = (FloatStamp) y.stamp();
66        /*
67         * If both stamps have at most one 0.0 and it's the same 0.0 then this is an identity
68         * comparison. FloatStamp isn't careful about tracking the presence of -0.0 so assume that
69         * anything that includes 0.0 might include -0.0. So if either one is non-zero then it's an
70         * identity comparison.
71         */
72        return (!xStamp.contains(0.0) || !yStamp.contains(0.0));
73    }
74
75    @Override
76    public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
77        ValueNode result = super.canonical(tool, forX, forY);
78        if (result != this) {
79            return result;
80        }
81        Stamp xStampGeneric = forX.stamp();
82        Stamp yStampGeneric = forY.stamp();
83        if (xStampGeneric instanceof FloatStamp && yStampGeneric instanceof FloatStamp) {
84            FloatStamp xStamp = (FloatStamp) xStampGeneric;
85            FloatStamp yStamp = (FloatStamp) yStampGeneric;
86            if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY) && xStamp.isNonNaN() && yStamp.isNonNaN()) {
87                return LogicConstantNode.tautology();
88            } else if (xStamp.alwaysDistinct(yStamp)) {
89                return LogicConstantNode.contradiction();
90            }
91        }
92        return this;
93    }
94
95    @Override
96    protected CompareNode duplicateModified(ValueNode newX, ValueNode newY) {
97        if (newX.stamp() instanceof FloatStamp && newY.stamp() instanceof FloatStamp) {
98            return new FloatEqualsNode(newX, newY);
99        } else if (newX.stamp() instanceof IntegerStamp && newY.stamp() instanceof IntegerStamp) {
100            return new IntegerEqualsNode(newX, newY);
101        }
102        throw GraalError.shouldNotReachHere();
103    }
104
105    @Override
106    public Stamp getSucceedingStampForX(boolean negated, Stamp xStamp, Stamp yStamp) {
107        if (!negated) {
108            return xStamp.join(yStamp);
109        }
110        return null;
111    }
112
113    @Override
114    public Stamp getSucceedingStampForY(boolean negated, Stamp xStamp, Stamp yStamp) {
115        if (!negated) {
116            return xStamp.join(yStamp);
117        }
118        return null;
119    }
120
121    @Override
122    public TriState tryFold(Stamp xStampGeneric, Stamp yStampGeneric) {
123        if (xStampGeneric instanceof FloatStamp && yStampGeneric instanceof FloatStamp) {
124            FloatStamp xStamp = (FloatStamp) xStampGeneric;
125            FloatStamp yStamp = (FloatStamp) yStampGeneric;
126            if (xStamp.alwaysDistinct(yStamp)) {
127                return TriState.FALSE;
128            } else if (xStamp.neverDistinct(yStamp)) {
129                return TriState.TRUE;
130            }
131        }
132        return TriState.UNKNOWN;
133    }
134}
135