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 org.graalvm.compiler.core.common.type.ArithmeticOpTable; 28 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp; 29 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp.And; 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.lir.gen.ArithmeticLIRGeneratorTool; 36 import org.graalvm.compiler.nodeinfo.NodeInfo; 37 import org.graalvm.compiler.nodes.ConstantNode; 38 import org.graalvm.compiler.nodes.NodeView; 39 import org.graalvm.compiler.nodes.ValueNode; 40 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; 41 import org.graalvm.compiler.nodes.util.GraphUtil; 42 43 import jdk.vm.ci.meta.Constant; 44 import jdk.vm.ci.meta.PrimitiveConstant; 45 46 @NodeInfo(shortName = "&") 47 public final class AndNode extends BinaryArithmeticNode<And> implements NarrowableArithmeticNode, BinaryCommutative<ValueNode> { 48 49 public static final NodeClass<AndNode> TYPE = NodeClass.create(AndNode.class); 50 AndNode(ValueNode x, ValueNode y)51 public AndNode(ValueNode x, ValueNode y) { 52 super(TYPE, getArithmeticOpTable(x).getAnd(), x, y); 53 } 54 create(ValueNode x, ValueNode y, NodeView view)55 public static ValueNode create(ValueNode x, ValueNode y, NodeView view) { 56 BinaryOp<And> op = ArithmeticOpTable.forStamp(x.stamp(view)).getAnd(); 57 Stamp stamp = op.foldStamp(x.stamp(view), y.stamp(view)); 58 ConstantNode tryConstantFold = tryConstantFold(op, x, y, stamp, view); 59 if (tryConstantFold != null) { 60 return tryConstantFold; 61 } 62 return canonical(null, op, x, y, view); 63 } 64 65 @Override getOp(ArithmeticOpTable table)66 protected BinaryOp<And> getOp(ArithmeticOpTable table) { 67 return table.getAnd(); 68 } 69 70 @Override canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY)71 public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { 72 ValueNode ret = super.canonical(tool, forX, forY); 73 if (ret != this) { 74 return ret; 75 } 76 77 NodeView view = NodeView.from(tool); 78 return canonical(this, getOp(forX, forY), forX, forY, view); 79 } 80 canonical(AndNode self, BinaryOp<And> op, ValueNode forX, ValueNode forY, NodeView view)81 private static ValueNode canonical(AndNode self, BinaryOp<And> op, ValueNode forX, ValueNode forY, NodeView view) { 82 if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) { 83 return forX; 84 } 85 if (forX.isConstant() && !forY.isConstant()) { 86 return new AndNode(forY, forX); 87 } 88 89 Stamp rawXStamp = forX.stamp(view); 90 Stamp rawYStamp = forY.stamp(view); 91 if (rawXStamp instanceof IntegerStamp && rawYStamp instanceof IntegerStamp) { 92 IntegerStamp xStamp = (IntegerStamp) rawXStamp; 93 IntegerStamp yStamp = (IntegerStamp) rawYStamp; 94 if (((~xStamp.downMask()) & yStamp.upMask()) == 0) { 95 return forY; 96 } else if (((~yStamp.downMask()) & xStamp.upMask()) == 0) { 97 return forX; 98 } 99 } 100 101 if (forY.isConstant()) { 102 Constant c = forY.asConstant(); 103 if (op.isNeutral(c)) { 104 return forX; 105 } 106 107 if (c instanceof PrimitiveConstant && ((PrimitiveConstant) c).getJavaKind().isNumericInteger()) { 108 long rawY = ((PrimitiveConstant) c).asLong(); 109 if (forX instanceof SignExtendNode) { 110 SignExtendNode ext = (SignExtendNode) forX; 111 if (rawY == ((1L << ext.getInputBits()) - 1)) { 112 return new ZeroExtendNode(ext.getValue(), ext.getResultBits()); 113 } 114 } 115 } 116 117 return reassociate(self != null ? self : (AndNode) new AndNode(forX, forY).maybeCommuteInputs(), ValueNode.isConstantPredicate(), forX, forY, view); 118 } 119 if (forX instanceof NotNode && forY instanceof NotNode) { 120 return new NotNode(OrNode.create(((NotNode) forX).getValue(), ((NotNode) forY).getValue(), view)); 121 } 122 return self != null ? self : new AndNode(forX, forY).maybeCommuteInputs(); 123 } 124 125 @Override generate(NodeLIRBuilderTool nodeValueMap, ArithmeticLIRGeneratorTool gen)126 public void generate(NodeLIRBuilderTool nodeValueMap, ArithmeticLIRGeneratorTool gen) { 127 nodeValueMap.setResult(this, gen.emitAnd(nodeValueMap.operand(getX()), nodeValueMap.operand(getY()))); 128 } 129 } 130