# HG changeset patch # User Doug Simon # Date 1355928770 -3600 # Node ID f368ec89e231e03b3e89da2597cd0d6b131c870b # Parent 9e27795a9d0559e39cc141dd1c3c84f8e5409889 added intrinsifications for Integer.bitCount() and Long.bitCount() diff -r 9e27795a9d05 -r f368ec89e231 graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java --- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java Wed Dec 19 12:39:47 2012 +0100 +++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java Wed Dec 19 15:52:50 2012 +0100 @@ -1553,6 +1553,38 @@ emitArith(0x0B, 0xC0, dst, src); } + public final void popcntl(Register dst, Address src) { + emitByte(0xF3); + prefix(src, dst); + emitByte(0x0F); + emitByte(0xB8); + emitOperandHelper(dst, src); + } + + public final void popcntl(Register dst, Register src) { + emitByte(0xF3); + int encode = prefixAndEncode(dst.encoding, src.encoding); + emitByte(0x0F); + emitByte(0xB8); + emitByte(0xC0 | encode); + } + + public final void popcntq(Register dst, Address src) { + emitByte(0xF3); + prefixq(src, dst); + emitByte(0x0F); + emitByte(0xB8); + emitOperandHelper(dst, src); + } + + public final void popcntq(Register dst, Register src) { + emitByte(0xF3); + int encode = prefixqAndEncode(dst.encoding, src.encoding); + emitByte(0x0F); + emitByte(0xB8); + emitByte(0xC0 | encode); + } + // generic public final void pop(Register dst) { int encode = prefixAndEncode(dst.encoding); diff -r 9e27795a9d05 -r f368ec89e231 graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java --- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Wed Dec 19 12:39:47 2012 +0100 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Wed Dec 19 15:52:50 2012 +0100 @@ -26,6 +26,8 @@ import static com.oracle.graal.api.code.ValueUtil.*; import static com.oracle.graal.lir.amd64.AMD64Arithmetic.*; import static com.oracle.graal.lir.amd64.AMD64Compare.*; +import static com.oracle.graal.lir.amd64.AMD64BitManipulationOp.IntrinsicOpcode.*; +import static com.oracle.graal.lir.amd64.AMD64MathIntrinsicOp.IntrinsicOpcode.*; import com.oracle.graal.amd64.*; import com.oracle.graal.api.code.*; @@ -57,7 +59,6 @@ import com.oracle.graal.lir.amd64.AMD64ControlFlow.SequentialSwitchOp; import com.oracle.graal.lir.amd64.AMD64ControlFlow.SwitchRangesOp; import com.oracle.graal.lir.amd64.AMD64ControlFlow.TableSwitchOp; -import com.oracle.graal.lir.amd64.AMD64MathIntrinsicOp.IntrinsicOpcode; import com.oracle.graal.lir.amd64.AMD64Move.CompareAndSwapOp; import com.oracle.graal.lir.amd64.AMD64Move.LeaOp; import com.oracle.graal.lir.amd64.AMD64Move.LoadOp; @@ -580,16 +581,25 @@ } @Override + public void emitBitCount(Variable result, Value value) { + if (value.getKind().getStackKind() == Kind.Int) { + append(new AMD64BitManipulationOp(IPOPCNT, result, value)); + } else { + append(new AMD64BitManipulationOp(LPOPCNT, result, value)); + } + } + + @Override public void emitBitScanForward(Variable result, Value value) { - append(new AMD64BitScanOp(AMD64BitScanOp.IntrinsicOpcode.BSF, result, value)); + append(new AMD64BitManipulationOp(BSF, result, value)); } @Override public void emitBitScanReverse(Variable result, Value value) { if (value.getKind().getStackKind() == Kind.Int) { - append(new AMD64BitScanOp(AMD64BitScanOp.IntrinsicOpcode.IBSR, result, value)); + append(new AMD64BitManipulationOp(IBSR, result, value)); } else { - append(new AMD64BitScanOp(AMD64BitScanOp.IntrinsicOpcode.LBSR, result, value)); + append(new AMD64BitManipulationOp(LBSR, result, value)); } } @@ -600,28 +610,27 @@ @Override public void emitMathSqrt(Variable result, Variable input) { - append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.IntrinsicOpcode.SQRT, result, input)); + append(new AMD64MathIntrinsicOp(SQRT, result, input)); } @Override public void emitMathLog(Variable result, Variable input, boolean base10) { - IntrinsicOpcode opcode = base10 ? AMD64MathIntrinsicOp.IntrinsicOpcode.LOG10 : AMD64MathIntrinsicOp.IntrinsicOpcode.LOG; - append(new AMD64MathIntrinsicOp(opcode, result, input)); + append(new AMD64MathIntrinsicOp(base10 ? LOG10 : LOG, result, input)); } @Override public void emitMathCos(Variable result, Variable input) { - append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.IntrinsicOpcode.COS, result, input)); + append(new AMD64MathIntrinsicOp(COS, result, input)); } @Override public void emitMathSin(Variable result, Variable input) { - append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.IntrinsicOpcode.SIN, result, input)); + append(new AMD64MathIntrinsicOp(SIN, result, input)); } @Override public void emitMathTan(Variable result, Variable input) { - append(new AMD64MathIntrinsicOp(AMD64MathIntrinsicOp.IntrinsicOpcode.TAN, result, input)); + append(new AMD64MathIntrinsicOp(TAN, result, input)); } @Override diff -r 9e27795a9d05 -r f368ec89e231 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Wed Dec 19 12:39:47 2012 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Wed Dec 19 15:52:50 2012 +0100 @@ -958,6 +958,7 @@ return frameMap; } + public abstract void emitBitCount(Variable result, Value operand); public abstract void emitBitScanForward(Variable result, Value operand); public abstract void emitBitScanReverse(Variable result, Value operand); diff -r 9e27795a9d05 -r f368ec89e231 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/IntegerBits.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/IntegerBits.java Wed Dec 19 12:39:47 2012 +0100 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/IntegerBits.java Wed Dec 19 15:52:50 2012 +0100 @@ -45,6 +45,10 @@ return Integer.numberOfTrailingZeros(o); } + public static int test4(int o) { + return Integer.bitCount(o); + } + @Test public void run0() { Assert.assertEquals(reversed, test(original)); @@ -94,4 +98,9 @@ public void run9() { Assert.assertEquals(32, test2(0)); } + + @Test + public void run10() { + Assert.assertEquals(32, test4(0xffffffff)); + } } diff -r 9e27795a9d05 -r f368ec89e231 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/LongBits.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/LongBits.java Wed Dec 19 12:39:47 2012 +0100 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/LongBits.java Wed Dec 19 15:52:50 2012 +0100 @@ -46,6 +46,10 @@ return Long.numberOfTrailingZeros(o); } + public static int test4(long o) { + return Long.bitCount(o); + } + @Test public void run0() { Assert.assertEquals(reversed, test(original)); @@ -115,4 +119,15 @@ public void run13() { Assert.assertEquals(32, test3(0x0100000000L)); } + + @Test + public void run14() { + Assert.assertEquals(0, test4(0L)); + Assert.assertEquals(1, test4(1L)); + Assert.assertEquals(24, test4(0xffff00ffL)); + Assert.assertEquals(32, test4(0xffffffffL)); + Assert.assertEquals(34, test4(0x3ffffffffL)); + Assert.assertEquals(34, test4(0xffffffff3L)); + Assert.assertEquals(64, test4(0xffffffffffffffffL)); + } } diff -r 9e27795a9d05 -r f368ec89e231 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64BitManipulationOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64BitManipulationOp.java Wed Dec 19 15:52:50 2012 +0100 @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2012, 2012, 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 com.oracle.graal.lir.amd64; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.amd64.*; +import com.oracle.graal.lir.asm.*; + +public class AMD64BitManipulationOp extends AMD64LIRInstruction { + public enum IntrinsicOpcode { + IPOPCNT, LPOPCNT, + IBSR, LBSR, + BSF; + } + + @Opcode private final IntrinsicOpcode opcode; + @Def protected Value result; + @Use({OperandFlag.REG, OperandFlag.ADDR}) protected Value input; + + public AMD64BitManipulationOp(IntrinsicOpcode opcode, Value result, Value input) { + this.opcode = opcode; + this.result = result; + this.input = input; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + Register dst = ValueUtil.asIntReg(result); + if (ValueUtil.isAddress(input)) { + Address src = ValueUtil.asAddress(input); + switch(opcode) { + case IPOPCNT: + masm.popcntl(dst, src); + break; + case LPOPCNT: + masm.popcntq(dst, src); + break; + case BSF: + masm.bsfq(dst, src); + break; + case IBSR: + masm.bsrl(dst, src); + break; + case LBSR: + masm.bsrq(dst, src); + break; + } + } else { + Register src = ValueUtil.asRegister(input); + switch(opcode) { + case IPOPCNT: + masm.popcntl(dst, src); + break; + case LPOPCNT: + masm.popcntq(dst, src); + break; + case BSF: + masm.bsfq(dst, src); + break; + case IBSR: + masm.bsrl(dst, src); + break; + case LBSR: + masm.bsrq(dst, src); + break; + } + } + } + +} diff -r 9e27795a9d05 -r f368ec89e231 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64BitScanOp.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64BitScanOp.java Wed Dec 19 12:39:47 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2012, 2012, 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 com.oracle.graal.lir.amd64; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.asm.amd64.*; -import com.oracle.graal.lir.asm.*; - - -public class AMD64BitScanOp extends AMD64LIRInstruction { - public enum IntrinsicOpcode { - IBSR, LBSR, - BSF; - } - - @Opcode private final IntrinsicOpcode opcode; - @Def protected Value result; - @Use({OperandFlag.REG, OperandFlag.ADDR}) protected Value input; - - public AMD64BitScanOp(IntrinsicOpcode opcode, Value result, Value input) { - this.opcode = opcode; - this.result = result; - this.input = input; - } - - @Override - public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - Register dst = ValueUtil.asIntReg(result); - if (ValueUtil.isAddress(input)) { - Address src = ValueUtil.asAddress(input); - switch(opcode) { - case BSF: - masm.bsfq(dst, src); - break; - case IBSR: - masm.bsrl(dst, src); - break; - case LBSR: - masm.bsrq(dst, src); - break; - } - } else { - Register src = ValueUtil.asRegister(input); - switch(opcode) { - case BSF: - masm.bsfq(dst, src); - break; - case IBSR: - masm.bsrl(dst, src); - break; - case LBSR: - masm.bsrq(dst, src); - break; - } - } - } - -} diff -r 9e27795a9d05 -r f368ec89e231 graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/IntrinsificationTest.java --- a/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/IntrinsificationTest.java Wed Dec 19 12:39:47 2012 +0100 +++ b/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/IntrinsificationTest.java Wed Dec 19 15:52:50 2012 +0100 @@ -325,6 +325,7 @@ assertInGraph(test("integerReverseBytesSnippet"), ReverseBytesNode.class); // Java assertInGraph(test("integerNumberOfLeadingZerosSnippet"), BitScanReverseNode.class); // Java assertInGraph(test("integerNumberOfTrailingZerosSnippet"), BitScanForwardNode.class); // Java + assertInGraph(test("integerBitCountSnippet"), BitCountNode.class); // Java } @SuppressWarnings("all") @@ -339,6 +340,10 @@ public static int integerNumberOfTrailingZerosSnippet(int value) { return Integer.numberOfTrailingZeros(value); } + @SuppressWarnings("all") + public static int integerBitCountSnippet(int value) { + return Integer.bitCount(value); + } @Test @@ -346,6 +351,7 @@ assertInGraph(test("longReverseBytesSnippet"), ReverseBytesNode.class); // Java assertInGraph(test("longNumberOfLeadingZerosSnippet"), BitScanReverseNode.class); // Java assertInGraph(test("longNumberOfTrailingZerosSnippet"), BitScanForwardNode.class); // Java + assertInGraph(test("longBitCountSnippet"), BitCountNode.class); // Java } @SuppressWarnings("all") @@ -360,6 +366,10 @@ public static long longNumberOfTrailingZerosSnippet(long value) { return Long.numberOfTrailingZeros(value); } + @SuppressWarnings("all") + public static int longBitCountSnippet(long value) { + return Long.bitCount(value); + } @Test diff -r 9e27795a9d05 -r f368ec89e231 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/IntegerSnippets.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/IntegerSnippets.java Wed Dec 19 12:39:47 2012 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/IntegerSnippets.java Wed Dec 19 15:52:50 2012 +0100 @@ -44,4 +44,8 @@ } return BitScanForwardNode.scan(i); } + + public static int bitCount(int i) { + return BitCountNode.bitCount(i); + } } diff -r 9e27795a9d05 -r f368ec89e231 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/LongSnippets.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/LongSnippets.java Wed Dec 19 12:39:47 2012 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/LongSnippets.java Wed Dec 19 15:52:50 2012 +0100 @@ -44,4 +44,8 @@ } return BitScanForwardNode.scan(i); } + + public static int bitCount(long i) { + return BitCountNode.bitCount(i); + } } diff -r 9e27795a9d05 -r f368ec89e231 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/BitCountNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/BitCountNode.java Wed Dec 19 15:52:50 2012 +0100 @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2012, 2012, 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 com.oracle.graal.snippets.nodes; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.target.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + + +public class BitCountNode extends FloatingNode implements LIRGenLowerable, Canonicalizable { + @Input private ValueNode value; + + public BitCountNode(ValueNode value) { + super(StampFactory.forInteger(Kind.Int, 0, value.kind().getBitCount())); + this.value = value; + } + + @Override + public ValueNode canonical(CanonicalizerTool tool) { + if (value.isConstant()) { + long v = value.asConstant().asLong(); + if (value.kind().getStackKind() == Kind.Int) { + return ConstantNode.forInt(Integer.bitCount((int) v), graph()); + } else if (value.kind() == Kind.Long) { + return ConstantNode.forInt(Long.bitCount(v), graph()); + } + } + return this; + } + + @NodeIntrinsic + public static native int bitCount(int v); + + @NodeIntrinsic + public static native int bitCount(long v); + + @Override + public void generate(LIRGenerator gen) { + Variable result = gen.newVariable(Kind.Int); + gen.emitBitCount(result, gen.operand(value)); + gen.setResult(this, result); + } +}