1 /*
2 * Copyright (c) 2011, 2018, 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
24
25 package org.graalvm.compiler.nodes.calc;
26
27 import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2;
28 import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_2;
29
30 import org.graalvm.compiler.core.common.type.IntegerStamp;
31 import org.graalvm.compiler.core.common.type.Stamp;
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.BinaryOpLogicNode;
37 import org.graalvm.compiler.nodes.LogicConstantNode;
38 import org.graalvm.compiler.nodes.NodeView;
39 import org.graalvm.compiler.nodes.ValueNode;
40
41 import jdk.vm.ci.meta.TriState;
42
43 /**
44 * This node will perform a "test" operation on its arguments. Its result is equivalent to the
45 * expression "(x & y) == 0", meaning that it will return true if (and only if) no bit is set in
46 * both x and y.
47 */
48 @NodeInfo(cycles = CYCLES_2, size = SIZE_2)
49 public final class IntegerTestNode extends BinaryOpLogicNode implements BinaryCommutative<ValueNode> {
50 public static final NodeClass<IntegerTestNode> TYPE = NodeClass.create(IntegerTestNode.class);
51
52 public IntegerTestNode(ValueNode x, ValueNode y) {
53 super(TYPE, x, y);
54 }
55
56 @Override
57 public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
58 NodeView view = NodeView.from(tool);
59 if (forX.isConstant() && forY.isConstant()) {
60 return LogicConstantNode.forBoolean((forX.asJavaConstant().asLong() & forY.asJavaConstant().asLong()) == 0);
61 }
62 if (forX.stamp(view) instanceof IntegerStamp && forY.stamp(view) instanceof IntegerStamp) {
63 IntegerStamp xStamp = (IntegerStamp) forX.stamp(view);
64 IntegerStamp yStamp = (IntegerStamp) forY.stamp(view);
65 if ((xStamp.upMask() & yStamp.upMask()) == 0) {
66 return LogicConstantNode.tautology();
67 } else if ((xStamp.downMask() & yStamp.downMask()) != 0) {
68 return LogicConstantNode.contradiction();
69 }
70 }
71 return this;
72 }
73
74 @Override
75 public Stamp getSucceedingStampForX(boolean negated, Stamp xStamp, Stamp yStamp) {
76 return getSucceedingStamp(negated, xStamp, yStamp);
77 }
78
79 private static Stamp getSucceedingStamp(boolean negated, Stamp xStampGeneric, Stamp otherStampGeneric) {
80 if (xStampGeneric instanceof IntegerStamp && otherStampGeneric instanceof IntegerStamp) {
81 IntegerStamp xStamp = (IntegerStamp) xStampGeneric;
82 IntegerStamp otherStamp = (IntegerStamp) otherStampGeneric;
83 if (negated) {
84 if (Long.bitCount(otherStamp.upMask()) == 1) {
85 long newDownMask = xStamp.downMask() | otherStamp.upMask();
86 if (xStamp.downMask() != newDownMask) {
87 return IntegerStamp.stampForMask(xStamp.getBits(), newDownMask, xStamp.upMask()).join(xStamp);
88 }
89 }
90 } else {
91 long restrictedUpMask = ((~otherStamp.downMask()) & xStamp.upMask());
|
1 /*
2 * Copyright (c) 2011, 2019, 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
24
25 package org.graalvm.compiler.nodes.calc;
26
27 import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_2;
28 import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_2;
29
30 import java.nio.ByteBuffer;
31
32 import org.graalvm.compiler.core.common.type.IntegerStamp;
33 import org.graalvm.compiler.core.common.type.Stamp;
34 import org.graalvm.compiler.graph.NodeClass;
35 import org.graalvm.compiler.graph.spi.Canonicalizable.BinaryCommutative;
36 import org.graalvm.compiler.graph.spi.CanonicalizerTool;
37 import org.graalvm.compiler.nodeinfo.NodeInfo;
38 import org.graalvm.compiler.nodes.BinaryOpLogicNode;
39 import org.graalvm.compiler.nodes.LogicConstantNode;
40 import org.graalvm.compiler.nodes.LogicNode;
41 import org.graalvm.compiler.nodes.NodeView;
42 import org.graalvm.compiler.nodes.ValueNode;
43
44 import jdk.vm.ci.meta.TriState;
45
46 /**
47 * This node will perform a "test" operation on its arguments. Its result is equivalent to the
48 * expression "(x & y) == 0", meaning that it will return true if (and only if) no bit is set in
49 * both x and y.
50 */
51 @NodeInfo(cycles = CYCLES_2, size = SIZE_2)
52 public final class IntegerTestNode extends BinaryOpLogicNode implements BinaryCommutative<ValueNode> {
53 public static final NodeClass<IntegerTestNode> TYPE = NodeClass.create(IntegerTestNode.class);
54
55 public IntegerTestNode(ValueNode x, ValueNode y) {
56 super(TYPE, x, y);
57 }
58
59 public static LogicNode create(ValueNode x, ValueNode y, NodeView view) {
60 LogicNode value = canonical(x, y, view);
61 if (value != null) {
62 return value;
63 }
64 return new IntegerTestNode(x, y);
65 }
66
67 private static LogicNode canonical(ValueNode forX, ValueNode forY, NodeView view) {
68 if (forX.isConstant() && forY.isConstant()) {
69 if (forX.isJavaConstant() && forY.isJavaConstant()) {
70 return LogicConstantNode.forBoolean((forX.asJavaConstant().asLong() & forY.asJavaConstant().asLong()) == 0);
71 }
72 if (forX.isSerializableConstant() && forY.isSerializableConstant()) {
73 int bufSize = Math.min(forX.asSerializableConstant().getSerializedSize(), forX.asSerializableConstant().getSerializedSize());
74 ByteBuffer xBuf = ByteBuffer.allocate(bufSize);
75 ByteBuffer yBuf = ByteBuffer.allocate(bufSize);
76 forX.asSerializableConstant().serialize(xBuf);
77 forY.asSerializableConstant().serialize(yBuf);
78 return serializableToConst(xBuf, yBuf, bufSize);
79 }
80 }
81 if (forX.stamp(view) instanceof IntegerStamp && forY.stamp(view) instanceof IntegerStamp) {
82 IntegerStamp xStamp = (IntegerStamp) forX.stamp(view);
83 IntegerStamp yStamp = (IntegerStamp) forY.stamp(view);
84 if ((xStamp.upMask() & yStamp.upMask()) == 0) {
85 return LogicConstantNode.tautology();
86 } else if ((xStamp.downMask() & yStamp.downMask()) != 0) {
87 return LogicConstantNode.contradiction();
88 }
89 }
90 return null;
91 }
92
93 @Override
94 public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
95 ValueNode value = canonical(forX, forY, NodeView.from(tool));
96 return value != null ? value : this;
97 }
98
99 private static LogicNode serializableToConst(ByteBuffer xBuf, ByteBuffer yBuf, int bufSize) {
100 for (int i = 0; i < bufSize; i++) {
101 if ((xBuf.get(i) & yBuf.get(i)) != 0) {
102 return LogicConstantNode.contradiction();
103 }
104 }
105 return LogicConstantNode.tautology();
106 }
107
108 @Override
109 public Stamp getSucceedingStampForX(boolean negated, Stamp xStamp, Stamp yStamp) {
110 return getSucceedingStamp(negated, xStamp, yStamp);
111 }
112
113 private static Stamp getSucceedingStamp(boolean negated, Stamp xStampGeneric, Stamp otherStampGeneric) {
114 if (xStampGeneric instanceof IntegerStamp && otherStampGeneric instanceof IntegerStamp) {
115 IntegerStamp xStamp = (IntegerStamp) xStampGeneric;
116 IntegerStamp otherStamp = (IntegerStamp) otherStampGeneric;
117 if (negated) {
118 if (Long.bitCount(otherStamp.upMask()) == 1) {
119 long newDownMask = xStamp.downMask() | otherStamp.upMask();
120 if (xStamp.downMask() != newDownMask) {
121 return IntegerStamp.stampForMask(xStamp.getBits(), newDownMask, xStamp.upMask()).join(xStamp);
122 }
123 }
124 } else {
125 long restrictedUpMask = ((~otherStamp.downMask()) & xStamp.upMask());
|