changeset 18495:fe0db662e982

adds ability for substitution guards to have a constructor with an Architecture argument added extra flags enum to AMD64 to drive code emission features (currently contains UseCountLeadingZerosInstruction and UseCountTrailingZerosInstruction) moved lzcnt/tzcnt nodes and substitutions to com.oracle.graal.replacements.amd64 Contributed-by: Igor Veresov <igor.veresov@oracle.com>
author Doug Simon <doug.simon@oracle.com>
date Mon, 24 Nov 2014 20:32:24 +0100
parents 9e944c7eaded
children 59ffee3765ec
files graal/com.oracle.graal.amd64/src/com/oracle/graal/amd64/AMD64.java graal/com.oracle.graal.api.replacements/src/com/oracle/graal/api/replacements/SubstitutionGuard.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CountLeadingZerosNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CountTrailingZerosNode.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSubstitutions.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotspotGuards.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/IntegerSubstitutions.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LongSubstitutions.java graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64CountLeadingZerosNode.java graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64CountTrailingZerosNode.java graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64Guards.java graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64IntegerSubstitutions.java graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64LongSubstitutions.java graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64Substitutions.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java mx/suite.py
diffstat 18 files changed, 383 insertions(+), 323 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.amd64/src/com/oracle/graal/amd64/AMD64.java	Mon Nov 24 17:29:51 2014 +0100
+++ b/graal/com.oracle.graal.amd64/src/com/oracle/graal/amd64/AMD64.java	Mon Nov 24 20:32:24 2014 +0100
@@ -138,9 +138,20 @@
 
     private final EnumSet<CPUFeature> features;
 
-    public AMD64(EnumSet<CPUFeature> features) {
+    /**
+     * Set of flags to control code emission.
+     */
+    public static enum Flag {
+        UseCountLeadingZerosInstruction,
+        UseCountTrailingZerosInstruction
+    }
+
+    private final EnumSet<Flag> flags;
+
+    public AMD64(EnumSet<CPUFeature> features, EnumSet<Flag> flags) {
         super("AMD64", 8, ByteOrder.LITTLE_ENDIAN, true, allRegisters, LOAD_STORE | STORE_STORE, 1, cpuRegisters.length + (xmmRegisters.length << XMM_REFERENCE_MAP_SHIFT), 8);
         this.features = features;
+        this.flags = flags;
         assert features.contains(CPUFeature.SSE2) : "minimum config for x64";
     }
 
@@ -148,6 +159,10 @@
         return features;
     }
 
+    public EnumSet<Flag> getFlags() {
+        return flags;
+    }
+
     @Override
     public boolean canStoreValue(RegisterCategory category, PlatformKind platformKind) {
         if (!(platformKind instanceof Kind)) {
--- a/graal/com.oracle.graal.api.replacements/src/com/oracle/graal/api/replacements/SubstitutionGuard.java	Mon Nov 24 17:29:51 2014 +0100
+++ b/graal/com.oracle.graal.api.replacements/src/com/oracle/graal/api/replacements/SubstitutionGuard.java	Mon Nov 24 20:32:24 2014 +0100
@@ -26,6 +26,12 @@
 /**
  * Guards the installation of substitutions for {@link ClassSubstitution} and
  * {@link MethodSubstitution}.
+ * <p>
+ * Implementor must have a single public constructor with one of the following signatures:
+ * <ul>
+ * <li>{@code Guard(Architecture)}</li>
+ * <li>{@code Guard()} (an implicit constructor is OK as well)</li>
+ * </ul>
  */
 public interface SubstitutionGuard {
 
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java	Mon Nov 24 17:29:51 2014 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackendFactory.java	Mon Nov 24 20:32:24 2014 +0100
@@ -40,7 +40,7 @@
 public class AMD64HotSpotBackendFactory implements HotSpotBackendFactory {
 
     protected Architecture createArchitecture(HotSpotVMConfig config) {
-        return new AMD64(computeFeatures(config));
+        return new AMD64(computeFeatures(config), computeFlags(config));
     }
 
     protected EnumSet<AMD64.CPUFeature> computeFeatures(HotSpotVMConfig config) {
@@ -91,6 +91,17 @@
         return features;
     }
 
+    protected EnumSet<AMD64.Flag> computeFlags(HotSpotVMConfig config) {
+        EnumSet<AMD64.Flag> flags = EnumSet.noneOf(AMD64.Flag.class);
+        if (config.useCountLeadingZerosInstruction) {
+            flags.add(AMD64.Flag.UseCountLeadingZerosInstruction);
+        }
+        if (config.useCountTrailingZerosInstruction) {
+            flags.add(AMD64.Flag.UseCountTrailingZerosInstruction);
+        }
+        return flags;
+    }
+
     protected TargetDescription createTarget(HotSpotVMConfig config) {
         final int stackFrameAlignment = 16;
         final int implicitNullCheckLimit = 4096;
@@ -240,15 +251,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
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java	Mon Nov 24 17:29:51 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReplacementsImpl.java	Mon Nov 24 20:32:24 2014 +0100
@@ -34,8 +34,6 @@
 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.*;
 
 /**
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CountLeadingZerosNode.java	Mon Nov 24 17:29:51 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-/*
- * 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);
-    }
-}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/CountTrailingZerosNode.java	Mon Nov 24 17:29:51 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-/*
- * 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);
-    }
-}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSubstitutions.java	Mon Nov 24 17:29:51 2014 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSubstitutions.java	Mon Nov 24 20:32:24 2014 +0100
@@ -67,7 +67,5 @@
         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);
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotspotGuards.java	Mon Nov 24 17:29:51 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/*
- * 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;
-        }
-    }
-}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/IntegerSubstitutions.java	Mon Nov 24 17:29:51 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * 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);
-    }
-}
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/LongSubstitutions.java	Mon Nov 24 17:29:51 2014 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * 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);
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64CountLeadingZerosNode.java	Mon Nov 24 20:32:24 2014 +0100
@@ -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.replacements.amd64;
+
+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 AMD64CountLeadingZerosNode extends UnaryNode implements LIRLowerable {
+
+    public static AMD64CountLeadingZerosNode create(ValueNode value) {
+        return new AMD64CountLeadingZerosNode(value);
+    }
+
+    protected AMD64CountLeadingZerosNode(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	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64CountTrailingZerosNode.java	Mon Nov 24 20:32:24 2014 +0100
@@ -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.replacements.amd64;
+
+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 AMD64CountTrailingZerosNode extends UnaryNode implements LIRLowerable {
+
+    public static AMD64CountTrailingZerosNode create(ValueNode value) {
+        return new AMD64CountTrailingZerosNode(value);
+    }
+
+    protected AMD64CountTrailingZerosNode(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	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64Guards.java	Mon Nov 24 20:32:24 2014 +0100
@@ -0,0 +1,54 @@
+/*
+ * 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.replacements.amd64;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.amd64.*;
+
+public class AMD64Guards {
+    public static class CountLeadingZerosSupported implements SubstitutionGuard {
+        private AMD64 arch;
+
+        public CountLeadingZerosSupported(Architecture arch) {
+            this.arch = (AMD64) arch;
+        }
+
+        public boolean execute() {
+            return arch.getFlags().contains(AMD64.Flag.UseCountLeadingZerosInstruction);
+        }
+    }
+
+    public static class CountTrailingZerosSupported implements SubstitutionGuard {
+        private AMD64 arch;
+
+        public CountTrailingZerosSupported(Architecture arch) {
+            this.arch = (AMD64) arch;
+        }
+
+        public boolean execute() {
+            return arch.getFlags().contains(AMD64.Flag.UseCountTrailingZerosInstruction);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64IntegerSubstitutions.java	Mon Nov 24 20:32:24 2014 +0100
@@ -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.replacements.amd64;
+
+import com.oracle.graal.api.replacements.*;
+
+@ClassSubstitution(Integer.class)
+public class AMD64IntegerSubstitutions {
+
+    @MethodSubstitution(guard = AMD64Guards.CountLeadingZerosSupported.class)
+    public static int numberOfLeadingZeros(int i) {
+        return AMD64CountLeadingZerosNode.count(i);
+    }
+
+    @MethodSubstitution(guard = AMD64Guards.CountTrailingZerosSupported.class)
+    public static int numberOfTrailingZeros(int i) {
+        return AMD64CountTrailingZerosNode.count(i);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64LongSubstitutions.java	Mon Nov 24 20:32:24 2014 +0100
@@ -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.replacements.amd64;
+
+import com.oracle.graal.api.replacements.*;
+
+@ClassSubstitution(Long.class)
+public class AMD64LongSubstitutions {
+
+    @MethodSubstitution(guard = AMD64Guards.CountLeadingZerosSupported.class)
+    public static int numberOfLeadingZeros(long i) {
+        return AMD64CountLeadingZerosNode.count(i);
+    }
+
+    @MethodSubstitution(guard = AMD64Guards.CountTrailingZerosSupported.class)
+    public static int numberOfTrailingZeros(long i) {
+        return AMD64CountTrailingZerosNode.count(i);
+    }
+}
--- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64Substitutions.java	Mon Nov 24 17:29:51 2014 +0100
+++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64Substitutions.java	Mon Nov 24 20:32:24 2014 +0100
@@ -44,6 +44,8 @@
         if (Intrinsify.getValue()) {
             replacements.registerSubstitutions(Arrays.class, ArraysSubstitutions.class);
             replacements.registerSubstitutions(String.class, StringSubstitutions.class);
+            replacements.registerSubstitutions(Integer.class, AMD64IntegerSubstitutions.class);
+            replacements.registerSubstitutions(Long.class, AMD64LongSubstitutions.class);
         }
     }
 
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Mon Nov 24 17:29:51 2014 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java	Mon Nov 24 20:32:24 2014 +0100
@@ -303,13 +303,27 @@
         return assumptions;
     }
 
-    private static SubstitutionGuard getGuard(Class<? extends SubstitutionGuard> guardClass) {
+    private SubstitutionGuard getGuard(Class<? extends SubstitutionGuard> guardClass) {
         if (guardClass != SubstitutionGuard.class) {
+            Constructor<?>[] constructors = guardClass.getConstructors();
+            if (constructors.length != 1) {
+                throw new GraalInternalError("Substitution guard " + guardClass.getSimpleName() + " must have a single public constructor");
+            }
+            Constructor<?> constructor = constructors[0];
+            Class<?>[] paramTypes = constructor.getParameterTypes();
+            // Check for supported constructor signatures
             try {
-                return guardClass.newInstance();
+                if (constructor.getParameterCount() == 1 && paramTypes[0] == Architecture.class) {
+                    // Guard(Architecture)
+                    return (SubstitutionGuard) constructor.newInstance(target.arch);
+                } else if (constructor.getParameterCount() == 0) {
+                    // Guard()
+                    return (SubstitutionGuard) constructor.newInstance();
+                }
             } catch (Exception e) {
                 throw new GraalInternalError(e);
             }
+            throw new GraalInternalError("Unsupported constructor signature in substitution guard: " + constructor);
         }
         return null;
     }
--- a/mx/suite.py	Mon Nov 24 17:29:51 2014 +0100
+++ b/mx/suite.py	Mon Nov 24 20:32:24 2014 +0100
@@ -632,7 +632,10 @@
     "com.oracle.graal.replacements.amd64" : {
       "subDir" : "graal",
       "sourceDirs" : ["src"],
-      "dependencies" : ["com.oracle.graal.replacements"],
+      "dependencies" : [
+          "com.oracle.graal.replacements",
+          "com.oracle.graal.amd64",
+          ],
       "checkstyle" : "com.oracle.graal.graph",
       "javaCompliance" : "1.8",
       "annotationProcessors" : ["com.oracle.graal.service.processor"],