changeset 7280:f368ec89e231

added intrinsifications for Integer.bitCount() and Long.bitCount()
author Doug Simon <doug.simon@oracle.com>
date Wed, 19 Dec 2012 15:52:50 +0100
parents 9e27795a9d05
children e960cda050d7 3964f3d4eb18 dc3e86fd3be1
files graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/IntegerBits.java graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/jdk/LongBits.java graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64BitManipulationOp.java graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64BitScanOp.java graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/IntrinsificationTest.java graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/IntegerSnippets.java graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/LongSnippets.java graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/nodes/BitCountNode.java
diffstat 11 files changed, 253 insertions(+), 89 deletions(-) [+]
line wrap: on
line diff
--- 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);
--- 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
--- 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);
 
--- 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));
+    }
 }
--- 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));
+    }
 }
--- /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;
+            }
+        }
+    }
+
+}
--- 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;
-            }
-        }
-    }
-
-}
--- 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
--- 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);
+    }
 }
--- 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);
+    }
 }
--- /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);
+    }
+}