--- old/graal/com.oracle.graal.amd64/src/com/oracle/graal/amd64/AMD64.java 2014-11-17 20:38:09.000000000 -0800 +++ new/graal/com.oracle.graal.amd64/src/com/oracle/graal/amd64/AMD64.java 2014-11-17 20:38:08.000000000 -0800 @@ -133,6 +133,7 @@ ERMS, AMD_3DNOW_PREFETCH, AES, + BMI1 } private final EnumSet features; --- old/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java 2014-11-17 20:38:09.000000000 -0800 +++ new/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java 2014-11-17 20:38:09.000000000 -0800 @@ -500,7 +500,6 @@ } public final void bsrq(Register dst, Register src) { - assert !supports(CPUFeature.LZCNT); int encode = prefixqAndEncode(dst.encoding, src.encoding); emitByte(0x0F); emitByte(0xBD); @@ -508,7 +507,6 @@ } public final void bsrq(Register dst, AMD64Address src) { - assert !supports(CPUFeature.LZCNT); prefixq(src, dst); emitByte(0x0F); emitByte(0xBD); @@ -516,7 +514,6 @@ } public final void bsrl(Register dst, Register src) { - assert !supports(CPUFeature.LZCNT); int encode = prefixAndEncode(dst.encoding, src.encoding); emitByte(0x0F); emitByte(0xBD); @@ -524,7 +521,6 @@ } public final void bsrl(Register dst, AMD64Address src) { - assert !supports(CPUFeature.LZCNT); prefix(src, dst); emitByte(0x0F); emitByte(0xBD); @@ -1327,6 +1323,42 @@ nop(); } + public final void lzcntl(Register dst, Register src) { + assert supports(CPUFeature.LZCNT); + emitByte(0xF3); + int encode = prefixAndEncode(dst.encoding, src.encoding); + emitByte(0x0F); + emitByte(0xBD); + emitByte(0xC0 | encode); + } + + public final void lzcntq(Register dst, Register src) { + assert supports(CPUFeature.LZCNT); + emitByte(0xF3); + int encode = prefixqAndEncode(dst.encoding, src.encoding); + emitByte(0x0F); + emitByte(0xBD); + emitByte(0xC0 | encode); + } + + public final void lzcntl(Register dst, AMD64Address src) { + assert supports(CPUFeature.LZCNT); + emitByte(0xF3); + prefix(src, dst); + emitByte(0x0F); + emitByte(0xBD); + emitOperandHelper(dst, src); + } + + public final void lzcntq(Register dst, AMD64Address src) { + assert supports(CPUFeature.LZCNT); + emitByte(0xF3); + prefixq(src, dst); + emitByte(0x0F); + emitByte(0xBD); + emitOperandHelper(dst, src); + } + public final void nop() { nop(1); } @@ -1878,6 +1910,42 @@ emitOperandHelper(dst, src); } + public final void tzcntl(Register dst, Register src) { + assert supports(CPUFeature.BMI1); + emitByte(0xF3); + int encode = prefixAndEncode(dst.encoding, src.encoding); + emitByte(0x0F); + emitByte(0xBC); + emitByte(0xC0 | encode); + } + + public final void tzcntq(Register dst, Register src) { + assert supports(CPUFeature.BMI1); + emitByte(0xF3); + int encode = prefixqAndEncode(dst.encoding, src.encoding); + emitByte(0x0F); + emitByte(0xBC); + emitByte(0xC0 | encode); + } + + public final void tzcntl(Register dst, AMD64Address src) { + assert supports(CPUFeature.BMI1); + emitByte(0xF3); + prefix(src, dst); + emitByte(0x0F); + emitByte(0xBC); + emitOperandHelper(dst, src); + } + + public final void tzcntq(Register dst, AMD64Address src) { + assert supports(CPUFeature.BMI1); + emitByte(0xF3); + prefixq(src, dst); + emitByte(0x0F); + emitByte(0xBC); + emitOperandHelper(dst, src); + } + public final void ucomisd(Register dst, AMD64Address src) { assert dst.getRegisterCategory().equals(AMD64.XMM); emitByte(0x66); --- old/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java 2014-11-17 20:38:09.000000000 -0800 +++ new/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java 2014-11-17 20:38:09.000000000 -0800 @@ -1004,6 +1004,26 @@ return result; } + public Value emitCountLeadingZeros(Value value) { + Variable result = newVariable(LIRKind.derive(value).changeType(Kind.Int)); + if (value.getKind().getStackKind() == Kind.Int) { + append(new AMD64BitManipulationOp(ILZCNT, result, asAllocatable(value))); + } else { + append(new AMD64BitManipulationOp(LLZCNT, result, asAllocatable(value))); + } + return result; + } + + public Value emitCountTrailingZeros(Value value) { + Variable result = newVariable(LIRKind.derive(value).changeType(Kind.Int)); + if (value.getKind().getStackKind() == Kind.Int) { + append(new AMD64BitManipulationOp(ITZCNT, result, asAllocatable(value))); + } else { + append(new AMD64BitManipulationOp(LTZCNT, result, asAllocatable(value))); + } + return result; + } + @Override public Value emitMathAbs(Value input) { Variable result = newVariable(LIRKind.derive(input)); --- old/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java 2014-11-17 20:38:10.000000000 -0800 +++ new/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java 2014-11-17 20:38:09.000000000 -0800 @@ -85,6 +85,9 @@ if ((config.x86CPUFeatures & config.cpu3DNOWPREFETCH) != 0) { features.add(AMD64.CPUFeature.AMD_3DNOW_PREFETCH); } + if ((config.x86CPUFeatures & config.cpuBMI1) != 0) { + features.add(AMD64.CPUFeature.BMI1); + } return features; } @@ -237,15 +240,15 @@ } else { /* * System V Application Binary Interface, AMD64 Architecture Processor Supplement - * + * * Draft Version 0.96 - * + * * http://www.uclibc.org/docs/psABI-x86_64.pdf - * + * * 3.2.1 - * + * * ... - * + * * This subsection discusses usage of each register. Registers %rbp, %rbx and %r12 * through %r15 "belong" to the calling function and the called function is required to * preserve their values. In other words, a called function must preserve these --- old/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java 2014-11-17 20:38:10.000000000 -0800 +++ new/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java 2014-11-17 20:38:10.000000000 -0800 @@ -34,6 +34,8 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.phases.util.*; import com.oracle.graal.replacements.*; +import com.oracle.graal.replacements.IntegerSubstitutions; +import com.oracle.graal.replacements.LongSubstitutions; import com.oracle.graal.word.phases.*; /** @@ -63,7 +65,10 @@ } } else if (substituteMethod.getName().equals("numberOfLeadingZeros")) { if (config.useCountLeadingZerosInstruction) { - // bsr is lzcnt + return null; + } + } else if (substituteMethod.getName().equals("numberOfTrailingZeros")) { + if (config.useCountTrailingZerosInstruction) { return null; } } --- old/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java 2014-11-17 20:38:10.000000000 -0800 +++ new/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java 2014-11-17 20:38:10.000000000 -0800 @@ -726,6 +726,7 @@ @HotSpotVMFlag(name = "UseBiasedLocking") @Stable public boolean useBiasedLocking; @HotSpotVMFlag(name = "UsePopCountInstruction") @Stable public boolean usePopCountInstruction; @HotSpotVMFlag(name = "UseCountLeadingZerosInstruction", archs = {"amd64"}) @Stable public boolean useCountLeadingZerosInstruction; + @HotSpotVMFlag(name = "UseCountTrailingZerosInstruction", archs = {"amd64"}) @Stable public boolean useCountTrailingZerosInstruction; @HotSpotVMFlag(name = "UseAESIntrinsics") @Stable public boolean useAESIntrinsics; @HotSpotVMFlag(name = "UseCRC32Intrinsics") @Stable public boolean useCRC32Intrinsics; @HotSpotVMFlag(name = "UseG1GC") @Stable public boolean useG1GC; @@ -794,6 +795,7 @@ @HotSpotVMConstant(name = "VM_Version::CPU_AES", archs = {"amd64"}) @Stable public int cpuAES; @HotSpotVMConstant(name = "VM_Version::CPU_ERMS", archs = {"amd64"}) @Stable public int cpuERMS; @HotSpotVMConstant(name = "VM_Version::CPU_CLMUL", archs = {"amd64"}) @Stable public int cpuCLMUL; + @HotSpotVMConstant(name = "VM_Version::CPU_BMI1", archs = {"amd64"}) @Stable public int cpuBMI1; // SPARC specific values @HotSpotVMField(name = "VM_Version::_features", type = "int", get = HotSpotVMField.Type.VALUE, archs = {"sparc"}) @Stable public int sparcFeatures; --- old/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSubstitutions.java 2014-11-17 20:38:11.000000000 -0800 +++ new/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSubstitutions.java 2014-11-17 20:38:10.000000000 -0800 @@ -67,5 +67,7 @@ replacements.registerSubstitutions(CompositeValueClass.class, CompositeValueClassSubstitutions.class); replacements.registerSubstitutions(new NamedType("com.sun.crypto.provider.AESCrypt"), AESCryptSubstitutions.class); replacements.registerSubstitutions(new NamedType("com.sun.crypto.provider.CipherBlockChaining"), CipherBlockChainingSubstitutions.class); + replacements.registerSubstitutions(Integer.class, IntegerSubstitutions.class); + replacements.registerSubstitutions(Long.class, LongSubstitutions.class); } } --- old/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64BitManipulationOp.java 2014-11-17 20:38:11.000000000 -0800 +++ new/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64BitManipulationOp.java 2014-11-17 20:38:11.000000000 -0800 @@ -35,7 +35,11 @@ LPOPCNT, IBSR, LBSR, - BSF; + BSF, + ILZCNT, + LLZCNT, + ITZCNT, + LTZCNT } @Opcode private final IntrinsicOpcode opcode; @@ -69,6 +73,18 @@ case LBSR: masm.bsrq(dst, src); break; + case ILZCNT: + masm.lzcntl(dst, src); + break; + case LLZCNT: + masm.lzcntq(dst, src); + break; + case ITZCNT: + masm.tzcntl(dst, src); + break; + case LTZCNT: + masm.tzcntq(dst, src); + break; } } else { AMD64Address src = (AMD64Address) crb.asAddress(input); @@ -88,6 +104,18 @@ case LBSR: masm.bsrq(dst, src); break; + case ILZCNT: + masm.lzcntl(dst, src); + break; + case LLZCNT: + masm.lzcntq(dst, src); + break; + case ITZCNT: + masm.tzcntl(dst, src); + break; + case LTZCNT: + masm.tzcntq(dst, src); + break; } } } --- old/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGeneratorTool.java 2014-11-17 20:38:11.000000000 -0800 +++ new/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGeneratorTool.java 2014-11-17 20:38:11.000000000 -0800 @@ -189,4 +189,14 @@ Value emitArrayEquals(Kind kind, Value array1, Value array2, Value length); + @SuppressWarnings("unused") + default Value emitCountLeadingZeros(Value value) { + throw GraalInternalError.unimplemented(); + } + + @SuppressWarnings("unused") + default Value emitCountTrailingZeros(Value value) { + throw GraalInternalError.unimplemented(); + } + } --- old/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/BitOpNodesTest.java 2014-11-17 20:38:12.000000000 -0800 +++ new/graal/com.oracle.graal.replacements.test/src/com/oracle/graal/replacements/test/BitOpNodesTest.java 2014-11-17 20:38:11.000000000 -0800 @@ -164,7 +164,7 @@ @Test public void testScanForwardLongEmpty() { ValueNode result = parseAndInline("scanForwardLongEmptySnippet"); - Assert.assertEquals(StampFactory.forInteger(Kind.Int, -1, 64), result.stamp()); + Assert.assertEquals(StampFactory.forInteger(Kind.Int, 24, 64), result.stamp()); } /* --- old/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanForwardNode.java 2014-11-17 20:38:12.000000000 -0800 +++ new/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanForwardNode.java 2014-11-17 20:38:12.000000000 -0800 @@ -54,12 +54,12 @@ int max; long mask = CodeUtil.mask(valueStamp.getBits()); int firstAlwaysSetBit = scan(valueStamp.downMask() & mask); + int firstMaybeSetBit = scan(valueStamp.upMask() & mask); if (firstAlwaysSetBit == -1) { int lastMaybeSetBit = BitScanReverseNode.scan(valueStamp.upMask() & mask); - min = -1; + min = firstMaybeSetBit; max = lastMaybeSetBit; } else { - int firstMaybeSetBit = scan(valueStamp.upMask() & mask); min = firstMaybeSetBit; max = firstAlwaysSetBit; } --- old/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanReverseNode.java 2014-11-17 20:38:12.000000000 -0800 +++ new/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BitScanReverseNode.java 2014-11-17 20:38:12.000000000 -0800 @@ -55,7 +55,8 @@ long mask = CodeUtil.mask(valueStamp.getBits()); int lastAlwaysSetBit = scan(valueStamp.downMask() & mask); if (lastAlwaysSetBit == -1) { - min = -1; + int firstMaybeSetBit = BitScanForwardNode.scan(valueStamp.upMask() & mask); + min = firstMaybeSetBit; } else { min = lastAlwaysSetBit; } --- old/src/cpu/x86/vm/vmStructs_x86.hpp 2014-11-17 20:38:12.000000000 -0800 +++ new/src/cpu/x86/vm/vmStructs_x86.hpp 2014-11-17 20:38:12.000000000 -0800 @@ -70,7 +70,9 @@ declare_constant(VM_Version::CPU_AVX2) \ declare_constant(VM_Version::CPU_AES) \ declare_constant(VM_Version::CPU_ERMS) \ - declare_constant(VM_Version::CPU_CLMUL) + declare_constant(VM_Version::CPU_CLMUL) \ + declare_constant(VM_Version::CPU_BMI1) \ + declare_constant(VM_Version::CPU_BMI2) #define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) --- /dev/null 2014-11-17 20:38:13.000000000 -0800 +++ new/graal/com.oracle.graal.asm.amd64.test/src/com/oracle/graal/asm/amd64/test/BitOpsTest.java 2014-11-17 20:38:13.000000000 -0800 @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2013, 2014, 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.asm.amd64.test; + +import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.compiler.common.UnsafeAccess.*; +import static org.junit.Assume.*; + +import org.junit.*; + +import java.lang.reflect.*; +import java.util.*; + +import com.oracle.graal.amd64.*; +import com.oracle.graal.amd64.AMD64.*; +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.amd64.*; +import com.oracle.graal.asm.test.*; + +public class BitOpsTest extends AssemblerTest { + private static boolean lzcntSupported; + private static boolean tzcntSupported; + + @Before + public void checkAMD64() { + assumeTrue("skipping AMD64 specific test", codeCache.getTarget().arch instanceof AMD64); + EnumSet features = ((AMD64) codeCache.getTarget().arch).getFeatures(); + lzcntSupported = features.contains(CPUFeature.LZCNT); + tzcntSupported = features.contains(CPUFeature.BMI1); + } + + @Test + public void lzcntlTest() { + if (lzcntSupported) { + CodeGenTest test = new CodeGenTest() { + + @Override + public byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) { + AMD64Assembler asm = new AMD64Assembler(target, registerConfig); + Register ret = registerConfig.getReturnRegister(Kind.Int); + Register arg = asRegister(cc.getArgument(0)); + asm.lzcntl(ret, arg); + asm.ret(0); + return asm.close(true); + } + }; + assertReturn("intStub", test, 31, 1); + } + } + + @Test + public void lzcntlMemTest() { + if (lzcntSupported) { + CodeGenTest test = new CodeGenTest() { + + @Override + public byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) { + AMD64Assembler asm = new AMD64Assembler(target, registerConfig); + Register ret = registerConfig.getReturnRegister(Kind.Int); + try { + Field f = IntField.class.getDeclaredField("x"); + AMD64Address arg = new AMD64Address(asRegister(cc.getArgument(0)), (int) unsafe.objectFieldOffset(f)); + asm.lzcntl(ret, arg); + asm.ret(0); + return asm.close(true); + } catch (Exception e) { + throw new RuntimeException("exception while trying to generate field access:", e); + } + } + }; + assertReturn("intFieldStub", test, 31, new IntField(1)); + } + } + + @Test + public void lzcntqTest() { + if (lzcntSupported) { + CodeGenTest test = new CodeGenTest() { + + @Override + public byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) { + AMD64Assembler asm = new AMD64Assembler(target, registerConfig); + Register ret = registerConfig.getReturnRegister(Kind.Int); + Register arg = asRegister(cc.getArgument(0)); + asm.lzcntq(ret, arg); + asm.ret(0); + return asm.close(true); + } + }; + assertReturn("longStub", test, 63, 1L); + } + } + + @Test + public void lzcntqMemTest() { + if (lzcntSupported) { + CodeGenTest test = new CodeGenTest() { + + @Override + public byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) { + AMD64Assembler asm = new AMD64Assembler(target, registerConfig); + Register ret = registerConfig.getReturnRegister(Kind.Int); + try { + Field f = LongField.class.getDeclaredField("x"); + AMD64Address arg = new AMD64Address(asRegister(cc.getArgument(0)), (int) unsafe.objectFieldOffset(f)); + asm.lzcntq(ret, arg); + asm.ret(0); + return asm.close(true); + } catch (Exception e) { + throw new RuntimeException("exception while trying to generate field access:", e); + } + } + }; + assertReturn("longFieldStub", test, 63, new LongField(1)); + } + } + + @Test + public void tzcntlTest() { + if (tzcntSupported) { + CodeGenTest test = new CodeGenTest() { + + @Override + public byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) { + AMD64Assembler asm = new AMD64Assembler(target, registerConfig); + Register ret = registerConfig.getReturnRegister(Kind.Int); + Register arg = asRegister(cc.getArgument(0)); + asm.tzcntl(ret, arg); + asm.ret(0); + return asm.close(true); + } + }; + assertReturn("intStub", test, 31, 0x8000_0000); + } + } + + @Test + public void tzcntlMemTest() { + if (tzcntSupported) { + CodeGenTest test = new CodeGenTest() { + + @Override + public byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) { + AMD64Assembler asm = new AMD64Assembler(target, registerConfig); + Register ret = registerConfig.getReturnRegister(Kind.Int); + try { + Field f = IntField.class.getDeclaredField("x"); + AMD64Address arg = new AMD64Address(asRegister(cc.getArgument(0)), (int) unsafe.objectFieldOffset(f)); + asm.tzcntl(ret, arg); + asm.ret(0); + return asm.close(true); + } catch (Exception e) { + throw new RuntimeException("exception while trying to generate field access:", e); + } + } + }; + assertReturn("intFieldStub", test, 31, new IntField(0x8000_0000)); + } + } + + @Test + public void tzcntqTest() { + if (tzcntSupported) { + CodeGenTest test = new CodeGenTest() { + + @Override + public byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) { + AMD64Assembler asm = new AMD64Assembler(target, registerConfig); + Register ret = registerConfig.getReturnRegister(Kind.Int); + Register arg = asRegister(cc.getArgument(0)); + asm.tzcntq(ret, arg); + asm.ret(0); + return asm.close(true); + } + }; + assertReturn("longStub", test, 63, 0x8000_0000_0000_0000L); + } + } + + @Test + public void tzcntqMemTest() { + if (tzcntSupported) { + CodeGenTest test = new CodeGenTest() { + + @Override + public byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc) { + AMD64Assembler asm = new AMD64Assembler(target, registerConfig); + Register ret = registerConfig.getReturnRegister(Kind.Int); + try { + Field f = LongField.class.getDeclaredField("x"); + AMD64Address arg = new AMD64Address(asRegister(cc.getArgument(0)), (int) unsafe.objectFieldOffset(f)); + asm.tzcntq(ret, arg); + asm.ret(0); + return asm.close(true); + } catch (Exception e) { + throw new RuntimeException("exception while trying to generate field access:", e); + } + } + }; + assertReturn("longFieldStub", test, 63, new LongField(0x8000_0000_0000_0000L)); + } + } + + @SuppressWarnings("unused") + public static int intStub(int arg) { + return 0; + } + + @SuppressWarnings("unused") + public static int longStub(long arg) { + return 0; + } + + public static class IntField { + public int x; + + IntField(int x) { + this.x = x; + } + } + + public static class LongField { + public long x; + + LongField(long x) { + this.x = x; + } + } + + @SuppressWarnings("unused") + public static int intFieldStub(IntField arg) { + return 0; + } + + @SuppressWarnings("unused") + public static int longFieldStub(LongField arg) { + return 0; + } +} --- /dev/null 2014-11-17 20:38:13.000000000 -0800 +++ new/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CountLeadingZerosNode.java 2014-11-17 20:38:13.000000000 -0800 @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2012, 2014, 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.hotspot.replacements; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.spi.*; + +/** + * Count the number of leading zeros. + */ +@NodeInfo +public class CountLeadingZerosNode extends UnaryNode implements LIRLowerable { + + public static CountLeadingZerosNode create(ValueNode value) { + return new CountLeadingZerosNode(value); + } + + protected CountLeadingZerosNode(ValueNode value) { + super(StampFactory.forInteger(Kind.Int, 0, ((PrimitiveStamp) value.stamp()).getBits()), value); + assert value.getKind() == Kind.Int || value.getKind() == Kind.Long; + } + + @Override + public boolean inferStamp() { + IntegerStamp valueStamp = (IntegerStamp) getValue().stamp(); + long mask = CodeUtil.mask(valueStamp.getBits()); + int min = Long.numberOfLeadingZeros(valueStamp.upMask() & mask); + int max = Long.numberOfLeadingZeros(valueStamp.downMask() & mask); + return updateStamp(StampFactory.forInteger(Kind.Int, min, max)); + } + + @Override + public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { + if (forValue.isConstant()) { + JavaConstant c = forValue.asJavaConstant(); + if (forValue.getKind() == Kind.Int) { + return ConstantNode.forInt(Integer.numberOfLeadingZeros(c.asInt())); + } else { + return ConstantNode.forInt(Long.numberOfLeadingZeros(c.asLong())); + } + } + return this; + } + + /** + * Raw intrinsic for lzcntq instruction. + * + * @param v + * @return number of trailing zeros + */ + @NodeIntrinsic + public static native int count(long v); + + /** + * Raw intrinsic for lzcntl instruction. + * + * @param v + * @return number of trailing zeros + */ + @NodeIntrinsic + public static native int count(int v); + + @Override + public void generate(NodeLIRBuilderTool gen) { + Value result = gen.getLIRGeneratorTool().emitCountLeadingZeros(gen.operand(getValue())); + gen.setResult(this, result); + } +} --- /dev/null 2014-11-17 20:38:13.000000000 -0800 +++ new/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CountTrailingZerosNode.java 2014-11-17 20:38:13.000000000 -0800 @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2012, 2014, 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.hotspot.replacements; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.spi.*; + +/** + * Count the number of trailing zeros. + */ +@NodeInfo +public class CountTrailingZerosNode extends UnaryNode implements LIRLowerable { + + public static CountTrailingZerosNode create(ValueNode value) { + return new CountTrailingZerosNode(value); + } + + protected CountTrailingZerosNode(ValueNode value) { + super(StampFactory.forInteger(Kind.Int, 0, ((PrimitiveStamp) value.stamp()).getBits()), value); + assert value.getKind() == Kind.Int || value.getKind() == Kind.Long; + } + + @Override + public boolean inferStamp() { + IntegerStamp valueStamp = (IntegerStamp) getValue().stamp(); + long mask = CodeUtil.mask(valueStamp.getBits()); + int min = Long.numberOfTrailingZeros(valueStamp.upMask() & mask); + int max = Long.numberOfTrailingZeros(valueStamp.downMask() & mask); + return updateStamp(StampFactory.forInteger(Kind.Int, min, max)); + } + + @Override + public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { + if (forValue.isConstant()) { + JavaConstant c = forValue.asJavaConstant(); + if (forValue.getKind() == Kind.Int) { + return ConstantNode.forInt(Integer.numberOfTrailingZeros(c.asInt())); + } else { + return ConstantNode.forInt(Long.numberOfTrailingZeros(c.asLong())); + } + } + return this; + } + + /** + * Raw intrinsic for tzcntq instruction. + * + * @param v + * @return number of trailing zeros + */ + @NodeIntrinsic + public static native int count(long v); + + /** + * Raw intrinsic for tzcntl instruction. + * + * @param v + * @return number of trailing zeros + */ + @NodeIntrinsic + public static native int count(int v); + + @Override + public void generate(NodeLIRBuilderTool gen) { + Value result = gen.getLIRGeneratorTool().emitCountTrailingZeros(gen.operand(getValue())); + gen.setResult(this, result); + } +} --- /dev/null 2014-11-17 20:38:14.000000000 -0800 +++ new/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotspotGuards.java 2014-11-17 20:38:13.000000000 -0800 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2012, 2014, 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.hotspot.replacements; + +import com.oracle.graal.api.replacements.*; +import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; + +public class HotspotGuards { + public static class CountLeadingZerosSupported implements SubstitutionGuard { + public boolean execute() { + return runtime().getConfig().useCountLeadingZerosInstruction; + } + } + + public static class CountTrailingZerosSupported implements SubstitutionGuard { + public boolean execute() { + return runtime().getConfig().useCountTrailingZerosInstruction; + } + } +} --- /dev/null 2014-11-17 20:38:14.000000000 -0800 +++ new/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/IntegerSubstitutions.java 2014-11-17 20:38:14.000000000 -0800 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2012, 2014, 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.hotspot.replacements; + +import com.oracle.graal.api.replacements.*; + +@ClassSubstitution(Integer.class) +public class IntegerSubstitutions { + + @MethodSubstitution(guard = HotspotGuards.CountLeadingZerosSupported.class) + public static int numberOfLeadingZeros(int i) { + return CountLeadingZerosNode.count(i); + } + + @MethodSubstitution(guard = HotspotGuards.CountTrailingZerosSupported.class) + public static int numberOfTrailingZeros(int i) { + return CountTrailingZerosNode.count(i); + } +} --- /dev/null 2014-11-17 20:38:14.000000000 -0800 +++ new/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LongSubstitutions.java 2014-11-17 20:38:14.000000000 -0800 @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2012, 2014, 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.hotspot.replacements; + +import com.oracle.graal.api.replacements.*; + +@ClassSubstitution(Long.class) +public class LongSubstitutions { + + @MethodSubstitution(guard = HotspotGuards.CountLeadingZerosSupported.class) + public static int numberOfLeadingZeros(long i) { + return CountLeadingZerosNode.count(i); + } + + @MethodSubstitution(guard = HotspotGuards.CountTrailingZerosSupported.class) + public static int numberOfTrailingZeros(long i) { + return CountTrailingZerosNode.count(i); + } +}