changeset 19045:862997951c0a

Add GraalDirectives API to influence compiler behavior.
author Roland Schatz <roland.schatz@oracle.com>
date Thu, 29 Jan 2015 16:45:09 +0100
parents c9ef5e8bda3a
children 2358c0e65b9e
files CHANGELOG.md graal/com.oracle.graal.api.directives/src/com/oracle/graal/api/directives/GraalDirectives.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTestSubstitutions.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/ControlFlowAnchorNode.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalDirectivesSubstitutions.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BlackholeNode.java graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/OpaqueNode.java mx/suite.py
diffstat 10 files changed, 587 insertions(+), 55 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGELOG.md	Wed Jan 28 12:08:21 2015 +0100
+++ b/CHANGELOG.md	Thu Jan 29 16:45:09 2015 +0100
@@ -6,6 +6,7 @@
 ## `tip`
 ### Graal
 * Add utilities ModifiersProvider#isConcrete, ResolvedJavaMethod#hasBytecodes, ResolvedJavaMethod#hasReceiver to Graal API.
+* Add `GraalDirectives` API, containing methods to influence compiler behavior for unittests and microbenchmarks.
 * ...
 
 ### Truffle
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.directives/src/com/oracle/graal/api/directives/GraalDirectives.java	Thu Jan 29 16:45:09 2015 +0100
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.api.directives;
+
+/**
+ * Directives that influence the compilation of methods by Graal. They don't influence the semantics
+ * of the code, but they are useful for unit testing and benchmarking.
+ */
+public final class GraalDirectives {
+
+    public static final double LIKELY_PROBABILITY = 0.75;
+    public static final double UNLIKELY_PROBABILITY = 1.0 - LIKELY_PROBABILITY;
+
+    public static final double SLOWPATH_PROBABILITY = 0.0001;
+    public static final double FASTPATH_PROBABILITY = 1.0 - SLOWPATH_PROBABILITY;
+
+    /**
+     * Directive for the compiler to fall back to the bytecode interpreter at this point.
+     */
+    public static void deoptimize() {
+    }
+
+    /**
+     * Directive for the compiler to fall back to the bytecode interpreter at this point, invalidate
+     * the compiled code and reprofile the method.
+     */
+    public static void deoptimizeAndInvalidate() {
+    }
+
+    /**
+     * Returns a boolean value indicating whether the method is executed in Graal-compiled code.
+     */
+    public static boolean inCompiledCode() {
+        return false;
+    }
+
+    /**
+     * A call to this method will never be duplicated by control flow optimizations in the compiler.
+     */
+    public static void controlFlowAnchor() {
+    }
+
+    /**
+     * Injects a probability for the given condition into the profiling information of a branch
+     * instruction. The probability must be a value between 0.0 and 1.0 (inclusive).
+     *
+     * Example usage (it specifies that the likelihood for a to be greater than b is 90%):
+     *
+     * <code>
+     * if (injectBranchProbability(0.9, a &gt; b)) {
+     *    // ...
+     * }
+     * </code>
+     *
+     * There are predefined constants for commonly used probabilities (see
+     * {@link #LIKELY_PROBABILITY} , {@link #UNLIKELY_PROBABILITY}, {@link #SLOWPATH_PROBABILITY},
+     * {@link #FASTPATH_PROBABILITY} ).
+     *
+     * @param probability the probability value between 0.0 and 1.0 that should be injected
+     */
+    public static boolean injectBranchProbability(double probability, boolean condition) {
+        assert probability >= 0.0 && probability <= 1.0;
+        return condition;
+    }
+
+    /**
+     * Injects an average iteration count of a loop into the probability information of a loop exit
+     * condition. The iteration count specifies how often the condition is checked, i.e. in for and
+     * while loops it is one more than the body iteration count, and in do-while loops it is equal
+     * to the body iteration count. The iteration count must be >= 1.0.
+     *
+     * Example usage (it specifies that the expected iteration count of the loop condition is 500,
+     * so the iteration count of the loop body is 499):
+     *
+     * <code>
+     * for (int i = 0; injectIterationCount(500, i < array.length); i++) {
+     *     // ...
+     * }
+     * </code>
+     *
+     * @param iterations the expected number of iterations that should be injected
+     */
+    public static boolean injectIterationCount(double iterations, boolean condition) {
+        return injectBranchProbability(1. - 1. / iterations, condition);
+    }
+
+    /**
+     * Consume a value, making sure the compiler doesn't optimize away the computation of this
+     * value, even if it is otherwise unused.
+     */
+    @SuppressWarnings("unused")
+    public static void blackhole(boolean value) {
+    }
+
+    /**
+     * Consume a value, making sure the compiler doesn't optimize away the computation of this
+     * value, even if it is otherwise unused.
+     */
+    @SuppressWarnings("unused")
+    public static void blackhole(byte value) {
+    }
+
+    /**
+     * Consume a value, making sure the compiler doesn't optimize away the computation of this
+     * value, even if it is otherwise unused.
+     */
+    @SuppressWarnings("unused")
+    public static void blackhole(short value) {
+    }
+
+    /**
+     * Consume a value, making sure the compiler doesn't optimize away the computation of this
+     * value, even if it is otherwise unused.
+     */
+    @SuppressWarnings("unused")
+    public static void blackhole(char value) {
+    }
+
+    /**
+     * Consume a value, making sure the compiler doesn't optimize away the computation of this
+     * value, even if it is otherwise unused.
+     */
+    @SuppressWarnings("unused")
+    public static void blackhole(int value) {
+    }
+
+    /**
+     * Consume a value, making sure the compiler doesn't optimize away the computation of this
+     * value, even if it is otherwise unused.
+     */
+    @SuppressWarnings("unused")
+    public static void blackhole(long value) {
+    }
+
+    /**
+     * Consume a value, making sure the compiler doesn't optimize away the computation of this
+     * value, even if it is otherwise unused.
+     */
+    @SuppressWarnings("unused")
+    public static void blackhole(float value) {
+    }
+
+    /**
+     * Consume a value, making sure the compiler doesn't optimize away the computation of this
+     * value, even if it is otherwise unused.
+     */
+    @SuppressWarnings("unused")
+    public static void blackhole(double value) {
+    }
+
+    /**
+     * Consume a value, making sure the compiler doesn't optimize away the computation of this
+     * value, even if it is otherwise unused.
+     */
+    @SuppressWarnings("unused")
+    public static void blackhole(Object value) {
+    }
+
+    /**
+     * Do nothing, but also make sure the compiler doesn't do any optimizations across this call.
+     *
+     * For example, the compiler will constant fold the expression 5 * 3, but the expression 5 *
+     * opaque(3) will result in a real multiplication, because the compiler will not see that
+     * opaque(3) is a constant.
+     */
+    public static boolean opaque(boolean value) {
+        return value;
+    }
+
+    /**
+     * Do nothing, but also make sure the compiler doesn't do any optimizations across this call.
+     *
+     * For example, the compiler will constant fold the expression 5 * 3, but the expression 5 *
+     * opaque(3) will result in a real multiplication, because the compiler will not see that
+     * opaque(3) is a constant.
+     */
+    public static byte opaque(byte value) {
+        return value;
+    }
+
+    /**
+     * Do nothing, but also make sure the compiler doesn't do any optimizations across this call.
+     *
+     * For example, the compiler will constant fold the expression 5 * 3, but the expression 5 *
+     * opaque(3) will result in a real multiplication, because the compiler will not see that
+     * opaque(3) is a constant.
+     */
+    public static short opaque(short value) {
+        return value;
+    }
+
+    /**
+     * Do nothing, but also make sure the compiler doesn't do any optimizations across this call.
+     *
+     * For example, the compiler will constant fold the expression 5 * 3, but the expression 5 *
+     * opaque(3) will result in a real multiplication, because the compiler will not see that
+     * opaque(3) is a constant.
+     */
+    public static char opaque(char value) {
+        return value;
+    }
+
+    /**
+     * Do nothing, but also make sure the compiler doesn't do any optimizations across this call.
+     *
+     * For example, the compiler will constant fold the expression 5 * 3, but the expression 5 *
+     * opaque(3) will result in a real multiplication, because the compiler will not see that
+     * opaque(3) is a constant.
+     */
+    public static int opaque(int value) {
+        return value;
+    }
+
+    /**
+     * Do nothing, but also make sure the compiler doesn't do any optimizations across this call.
+     *
+     * For example, the compiler will constant fold the expression 5 * 3, but the expression 5 *
+     * opaque(3) will result in a real multiplication, because the compiler will not see that
+     * opaque(3) is a constant.
+     */
+    public static long opaque(long value) {
+        return value;
+    }
+
+    /**
+     * Do nothing, but also make sure the compiler doesn't do any optimizations across this call.
+     *
+     * For example, the compiler will constant fold the expression 5 * 3, but the expression 5 *
+     * opaque(3) will result in a real multiplication, because the compiler will not see that
+     * opaque(3) is a constant.
+     */
+    public static float opaque(float value) {
+        return value;
+    }
+
+    /**
+     * Do nothing, but also make sure the compiler doesn't do any optimizations across this call.
+     *
+     * For example, the compiler will constant fold the expression 5 * 3, but the expression 5 *
+     * opaque(3) will result in a real multiplication, because the compiler will not see that
+     * opaque(3) is a constant.
+     */
+    public static double opaque(double value) {
+        return value;
+    }
+
+    /**
+     * Do nothing, but also make sure the compiler doesn't do any optimizations across this call.
+     *
+     * For example, the compiler will constant fold the expression 5 * 3, but the expression 5 *
+     * opaque(3) will result in a real multiplication, because the compiler will not see that
+     * opaque(3) is a constant.
+     */
+    public static <T> T opaque(T value) {
+        return value;
+    }
+}
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Wed Jan 28 12:08:21 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Thu Jan 29 16:45:09 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -36,6 +36,7 @@
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.code.CallingConvention.Type;
+import com.oracle.graal.api.directives.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.api.runtime.*;
@@ -855,7 +856,7 @@
      * @return cond
      */
     protected static boolean branchProbability(double p, boolean cond) {
-        return cond;
+        return GraalDirectives.injectBranchProbability(p, cond);
     }
 
     /**
@@ -867,7 +868,7 @@
      * @return cond
      */
     protected static boolean iterationCount(double i, boolean cond) {
-        return cond;
+        return GraalDirectives.injectIterationCount(i, cond);
     }
 
     /**
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTestSubstitutions.java	Wed Jan 28 12:08:21 2015 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTestSubstitutions.java	Thu Jan 29 16:45:09 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,22 +24,11 @@
 
 import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.nodes.*;
-import com.oracle.graal.nodes.extended.*;
 
 @ClassSubstitution(GraalCompilerTest.class)
 class GraalCompilerTestSubstitutions {
 
     @MethodSubstitution
-    public static boolean branchProbability(double p, boolean cond) {
-        return BranchProbabilityNode.probability(p, cond);
-    }
-
-    @MethodSubstitution
-    public static boolean iterationCount(double i, boolean cond) {
-        return BranchProbabilityNode.probability(1. - 1. / i, cond);
-    }
-
-    @MethodSubstitution
     public static void breakpoint() {
         BreakpointNode.breakpoint();
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/debug/ControlFlowAnchorNode.java	Thu Jan 29 16:45:09 2015 +0100
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.nodes.debug;
+
+import com.oracle.graal.compiler.common.type.*;
+import com.oracle.graal.nodeinfo.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+
+/**
+ * This node prevents control flow optimizations. It is never duplicated or merged with other
+ * control flow anchors.
+ */
+@NodeInfo
+public class ControlFlowAnchorNode extends FixedWithNextNode implements LIRLowerable {
+
+    private static class Unique {
+    }
+
+    protected Unique unique;
+
+    public ControlFlowAnchorNode(@SuppressWarnings("unused") Invoke invoke) {
+        super(StampFactory.forVoid());
+        this.unique = new Unique();
+    }
+
+    public void generate(NodeLIRBuilderTool generator) {
+        // do nothing
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalDirectivesSubstitutions.java	Thu Jan 29 16:45:09 2015 +0100
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.replacements;
+
+import com.oracle.graal.api.directives.*;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.replacements.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.debug.*;
+import com.oracle.graal.nodes.extended.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.replacements.nodes.*;
+
+@ClassSubstitution(GraalDirectives.class)
+public class GraalDirectivesSubstitutions {
+
+    @MethodSubstitution(forced = true)
+    public static void deoptimize() {
+        DeoptimizeNode.deopt(DeoptimizationAction.None, DeoptimizationReason.TransferToInterpreter);
+    }
+
+    @MethodSubstitution(forced = true)
+    public static void deoptimizeAndInvalidate() {
+        DeoptimizeNode.deopt(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.TransferToInterpreter);
+    }
+
+    @MethodSubstitution(forced = true)
+    public static boolean inCompiledCode() {
+        return true;
+    }
+
+    @MacroSubstitution(forced = true, macro = ControlFlowAnchorNode.class)
+    public static native void controlFlowAnchor();
+
+    @MethodSubstitution(forced = true)
+    public static boolean injectBranchProbability(double probability, boolean condition) {
+        return BranchProbabilityNode.probability(probability, condition);
+    }
+
+    @MethodSubstitution(forced = true)
+    public static void blackhole(boolean value) {
+        BlackholeNode.consume(value);
+    }
+
+    @MethodSubstitution(forced = true)
+    public static void blackhole(byte value) {
+        BlackholeNode.consume(value);
+    }
+
+    @MethodSubstitution(forced = true)
+    public static void blackhole(short value) {
+        BlackholeNode.consume(value);
+    }
+
+    @MethodSubstitution(forced = true)
+    public static void blackhole(char value) {
+        BlackholeNode.consume(value);
+    }
+
+    @MethodSubstitution(forced = true)
+    public static void blackhole(int value) {
+        BlackholeNode.consume(value);
+    }
+
+    @MethodSubstitution(forced = true)
+    public static void blackhole(long value) {
+        BlackholeNode.consume(value);
+    }
+
+    @MethodSubstitution(forced = true)
+    public static void blackhole(float value) {
+        BlackholeNode.consume(value);
+    }
+
+    @MethodSubstitution(forced = true)
+    public static void blackhole(double value) {
+        BlackholeNode.consume(value);
+    }
+
+    @MethodSubstitution(forced = true)
+    public static void blackhole(Object value) {
+        BlackholeNode.consume(value);
+    }
+
+    @MethodSubstitution(forced = true)
+    public static boolean opaque(boolean value) {
+        return OpaqueNode.opaque(value);
+    }
+
+    @MethodSubstitution(forced = true)
+    public static byte opaque(byte value) {
+        return OpaqueNode.opaque(value);
+    }
+
+    @MethodSubstitution(forced = true)
+    public static short opaque(short value) {
+        return OpaqueNode.opaque(value);
+    }
+
+    @MethodSubstitution(forced = true)
+    public static char opaque(char value) {
+        return OpaqueNode.opaque(value);
+    }
+
+    @MethodSubstitution(forced = true)
+    public static int opaque(int value) {
+        return OpaqueNode.opaque(value);
+    }
+
+    @MethodSubstitution(forced = true)
+    public static long opaque(long value) {
+        return OpaqueNode.opaque(value);
+    }
+
+    @MethodSubstitution(forced = true)
+    public static float opaque(float value) {
+        return OpaqueNode.opaque(value);
+    }
+
+    @MethodSubstitution(forced = true)
+    public static double opaque(double value) {
+        return OpaqueNode.opaque(value);
+    }
+
+    @MethodSubstitution(forced = true)
+    public static <T> T opaque(T value) {
+        return OpaqueNode.opaque(value);
+    }
+}
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java	Wed Jan 28 12:08:21 2015 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java	Thu Jan 29 16:45:09 2015 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,6 +28,7 @@
 import java.util.*;
 
 import com.oracle.graal.api.code.*;
+import com.oracle.graal.api.directives.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.api.replacements.*;
 import com.oracle.graal.api.runtime.*;
@@ -47,6 +48,7 @@
 
     public void registerReplacements(MetaAccessProvider metaAccess, LoweringProvider loweringProvider, SnippetReflectionProvider snippetReflection, Replacements replacements, TargetDescription target) {
         BoxingSubstitutions.registerReplacements(replacements);
+        replacements.registerSubstitutions(GraalDirectives.class, GraalDirectivesSubstitutions.class);
         if (Intrinsify.getValue()) {
             replacements.registerSubstitutions(Arrays.class, ArraysSubstitutions.class);
             replacements.registerSubstitutions(Array.class, ArraySubstitutions.class);
@@ -60,18 +62,18 @@
             replacements.registerSubstitutions(Short.class, ShortSubstitutions.class);
             replacements.registerSubstitutions(UnsignedMath.class, UnsignedMathSubstitutions.class);
             replacements.registerSubstitutions(Edges.class, EdgesSubstitutions.class);
-            if (Options.UseBlackholeSubstitution.getValue()) {
-                replacements.registerSubstitutions(new Type() {
-                    public String getTypeName() {
-                        return "org.openjdk.jmh.infra.Blackhole";
-                    }
-                }, BlackholeSubstitutions.class);
-                replacements.registerSubstitutions(new Type() {
-                    public String getTypeName() {
-                        return "org.openjdk.jmh.logic.BlackHole";
-                    }
-                }, BlackholeSubstitutions.class);
-            }
+        }
+        if (Options.UseBlackholeSubstitution.getValue()) {
+            replacements.registerSubstitutions(new Type() {
+                public String getTypeName() {
+                    return "org.openjdk.jmh.infra.Blackhole";
+                }
+            }, BlackholeSubstitutions.class);
+            replacements.registerSubstitutions(new Type() {
+                public String getTypeName() {
+                    return "org.openjdk.jmh.logic.BlackHole";
+                }
+            }, BlackholeSubstitutions.class);
         }
     }
 }
--- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BlackholeNode.java	Wed Jan 28 12:08:21 2015 +0100
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/BlackholeNode.java	Thu Jan 29 16:45:09 2015 +0100
@@ -43,47 +43,29 @@
     }
 
     @NodeIntrinsic
-    @SuppressWarnings("unused")
-    public static void consume(boolean v) {
-    }
+    public static native void consume(boolean v);
 
     @NodeIntrinsic
-    @SuppressWarnings("unused")
-    public static void consume(byte v) {
-    }
+    public static native void consume(byte v);
 
     @NodeIntrinsic
-    @SuppressWarnings("unused")
-    public static void consume(short v) {
-    }
+    public static native void consume(short v);
 
     @NodeIntrinsic
-    @SuppressWarnings("unused")
-    public static void consume(char v) {
-    }
+    public static native void consume(char v);
 
     @NodeIntrinsic
-    @SuppressWarnings("unused")
-    public static void consume(int v) {
-    }
+    public static native void consume(int v);
 
     @NodeIntrinsic
-    @SuppressWarnings("unused")
-    public static void consume(long v) {
-    }
+    public static native void consume(long v);
 
     @NodeIntrinsic
-    @SuppressWarnings("unused")
-    public static void consume(float v) {
-    }
+    public static native void consume(float v);
 
     @NodeIntrinsic
-    @SuppressWarnings("unused")
-    public static void consume(double v) {
-    }
+    public static native void consume(double v);
 
     @NodeIntrinsic
-    @SuppressWarnings("unused")
-    public static void consume(Object v) {
-    }
+    public static native void consume(Object v);
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/OpaqueNode.java	Thu Jan 29 16:45:09 2015 +0100
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.replacements.nodes;
+
+import com.oracle.graal.nodeinfo.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.spi.*;
+
+@NodeInfo
+public class OpaqueNode extends FloatingNode implements LIRLowerable {
+
+    @Input ValueNode value;
+
+    public OpaqueNode(ValueNode value) {
+        super(value.stamp().unrestricted());
+        this.value = value;
+    }
+
+    @Override
+    public void generate(NodeLIRBuilderTool gen) {
+        gen.setResult(this, gen.operand(value));
+    }
+
+    @NodeIntrinsic
+    public static native boolean opaque(boolean v);
+
+    @NodeIntrinsic
+    public static native byte opaque(byte v);
+
+    @NodeIntrinsic
+    public static native short opaque(short v);
+
+    @NodeIntrinsic
+    public static native char opaque(char v);
+
+    @NodeIntrinsic
+    public static native int opaque(int v);
+
+    @NodeIntrinsic
+    public static native long opaque(long v);
+
+    @NodeIntrinsic
+    public static native float opaque(float v);
+
+    @NodeIntrinsic
+    public static native double opaque(double v);
+
+    @NodeIntrinsic
+    public static native <T> T opaque(T v);
+}
--- a/mx/suite.py	Wed Jan 28 12:08:21 2015 +0100
+++ b/mx/suite.py	Thu Jan 29 16:45:09 2015 +0100
@@ -220,6 +220,14 @@
       "workingSets" : "API,Graal",
     },
 
+    "com.oracle.graal.api.directives" : {
+      "subDir" : "graal",
+      "sourceDirs" : ["src"],
+      "checkstyle" : "com.oracle.graal.graph",
+      "javaCompliance" : "1.8",
+      "workingSets" : "API,Graal",
+    },
+
     "com.oracle.graal.api.runtime" : {
       "subDir" : "graal",
       "sourceDirs" : ["src"],
@@ -582,6 +590,7 @@
       "subDir" : "graal",
       "sourceDirs" : ["src"],
       "dependencies" : [
+        "com.oracle.graal.api.directives",
         "com.oracle.graal.compiler",
         "com.oracle.graal.java",
         "com.oracle.graal.word",
@@ -854,6 +863,7 @@
       "subDir" : "graal",
       "sourceDirs" : ["src"],
       "dependencies" : [
+        "com.oracle.graal.api.directives",
         "com.oracle.graal.test",
         "com.oracle.graal.printer",
         "com.oracle.graal.runtime",