--- /dev/null 2016-05-31 09:42:47.975716356 -0700 +++ new/src/jdk.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BitScanReverseNode.java 2016-12-09 00:57:08.185539865 -0800 @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.graalvm.compiler.replacements.nodes; + +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_3; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1; + +import org.graalvm.compiler.core.common.type.IntegerStamp; +import org.graalvm.compiler.core.common.type.PrimitiveStamp; +import org.graalvm.compiler.core.common.type.Stamp; +import org.graalvm.compiler.core.common.type.StampFactory; +import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.graph.spi.CanonicalizerTool; +import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool; +import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.ConstantNode; +import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.calc.UnaryNode; +import org.graalvm.compiler.nodes.spi.ArithmeticLIRLowerable; +import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; + +import jdk.vm.ci.code.CodeUtil; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaKind; + +/** + * Determines the index of the most significant "1" bit. Note that the result is undefined if the + * input is zero. + */ +@NodeInfo(cycles = CYCLES_3, size = SIZE_1) +public final class BitScanReverseNode extends UnaryNode implements ArithmeticLIRLowerable { + + public static final NodeClass TYPE = NodeClass.create(BitScanReverseNode.class); + + public BitScanReverseNode(ValueNode value) { + super(TYPE, StampFactory.forInteger(JavaKind.Int, 0, ((PrimitiveStamp) value.stamp()).getBits()), value); + assert value.getStackKind() == JavaKind.Int || value.getStackKind() == JavaKind.Long; + } + + @Override + public Stamp foldStamp(Stamp newStamp) { + assert newStamp.isCompatible(getValue().stamp()); + IntegerStamp valueStamp = (IntegerStamp) newStamp; + int min; + int max; + long mask = CodeUtil.mask(valueStamp.getBits()); + int lastAlwaysSetBit = scan(valueStamp.downMask() & mask); + if (lastAlwaysSetBit == -1) { + int firstMaybeSetBit = BitScanForwardNode.scan(valueStamp.upMask() & mask); + min = firstMaybeSetBit; + } else { + min = lastAlwaysSetBit; + } + int lastMaybeSetBit = scan(valueStamp.upMask() & mask); + max = lastMaybeSetBit; + return StampFactory.forInteger(JavaKind.Int, min, max); + } + + @Override + public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { + if (forValue.isConstant()) { + JavaConstant c = forValue.asJavaConstant(); + if (c.asLong() != 0) { + return ConstantNode.forInt(forValue.getStackKind() == JavaKind.Int ? scan(c.asInt()) : scan(c.asLong())); + } + } + return this; + } + + /** + * Utility method with defined return value for 0. + * + * @param v + * @return index of first set bit or -1 if {@code v} == 0. + */ + public static int scan(long v) { + return 63 - Long.numberOfLeadingZeros(v); + } + + /** + * Utility method with defined return value for 0. + * + * @param v + * @return index of first set bit or -1 if {@code v} == 0. + */ + public static int scan(int v) { + return 31 - Integer.numberOfLeadingZeros(v); + } + + /** + * Raw intrinsic for bsr instruction. + * + * @param v + * @return index of first set bit or an undefined value if {@code v} == 0. + */ + @NodeIntrinsic + public static native int unsafeScan(int v); + + /** + * Raw intrinsic for bsr instruction. + * + * @param v + * @return index of first set bit or an undefined value if {@code v} == 0. + */ + @NodeIntrinsic + public static native int unsafeScan(long v); + + @Override + public void generate(NodeLIRBuilderTool builder, ArithmeticLIRGeneratorTool gen) { + builder.setResult(this, gen.emitBitScanReverse(builder.operand(getValue()))); + } + +}