changeset 12387:aff825fef0fd

Merge.
author Christian Humer <christian.humer@gmail.com>
date Wed, 02 Oct 2013 13:26:31 +0200
parents 91dbb0b7dc8b 04b039d82e86
children 96c1d057a5ed
files graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DeoptimizationAction.java graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ArrayTest.java graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ControlTest.java graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64SafepointOp.java graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCSafepointOp.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ArrayRangeWriteBarrier.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/G1ArrayRangePostWriteBarrier.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/G1ArrayRangePreWriteBarrier.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/G1PostWriteBarrier.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/G1PreWriteBarrier.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/G1ReferentFieldReadBarrier.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SerialArrayRangeWriteBarrier.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/SerialWriteBarrier.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ShortCircuitAndNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ShortCircuitBooleanNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/WriteBarrier.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AbstractCallNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/UnsafeArrayCastNode.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InsertStateAfterPlaceholderPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/SafepointInsertionPhase.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/phases/InlineTrivialGettersPhase.java graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/substitutions/SlowPathExceptionSubstitutions.java mx/.pylintrc src/gpu/ptx/vm/kernelArguments.cpp src/gpu/ptx/vm/kernelArguments.hpp
diffstat 508 files changed, 12280 insertions(+), 7752 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Fri Sep 06 21:37:50 2013 +0200
+++ b/.hgignore	Wed Oct 02 13:26:31 2013 +0200
@@ -1,5 +1,7 @@
 ^mx/env
 ^mx/checkstyle-timestamps
+^mx/eclipseinit.timestamp
+^mx/netbeansinit.timestamp
 ^mx/eclipse-launches
 ^mx/ecj.jar
 ^mx/includes
--- a/README_GRAAL.txt	Fri Sep 06 21:37:50 2013 +0200
+++ b/README_GRAAL.txt	Wed Oct 02 13:26:31 2013 +0200
@@ -11,11 +11,30 @@
 
 % mx build
 
-This builds the 'product' version of HotSpot with the Graal modifications.
-To build the debug or fastdebug versions:
+There are a number of VM configurations supported by mx which can
+be explicitly specified using the --vm option. However, you'll typically
+want one of these VM configurations:
 
-  mx build debug
-  mx build fastdebug
+1. The 'server' configuration is a standard HotSpot VM that includes the
+   runtime support for Graal but uses the existing compilers for normal
+   compilation (e.g., when the interpreter threshold is hit for a method).
+   Compilation with Graal is only done by explicit requests to the
+   Graal API. This is how Truffle uses Graal.
+   
+2. The 'graal' configuration is a VM where all compilation is performed
+   by Graal and no other compilers are built into the VM binary. This
+   VM will bootstrap Graal itself at startup unless the -XX:-BootstrapGraal
+   VM option is given.   
+
+Unless you use the --vm option with the build command, you will be presented
+with a dialogue to choose one of the above VM configurations for the build
+as well as have the option to make it your default for subsequent commands
+that need a VM specified.
+
+To build the debug or fastdebug builds:
+
+% mx --vmbuild debug build
+% mx --vmbuild fastdebug build
 
 Running Graal
 -------------
@@ -24,47 +43,28 @@
 
 % mx vm ...
 
-To select the fastdebug or debug versions of the VM:
+To select the fastdebug or debug builds of the VM:
 
-% mx --fastdebug vm ...
-% mx --debug vm ...
+% mx --vmbuild fastdebug vm ...
+% mx --vmbuild debug vm ...
 
-Graal has an optional bootstrap step where it compiles itself before
-compiling any application code. This bootstrap step currently takes about 7 seconds
-on a fast x64 machine. It's useful to disable this bootstrap step when running small
-programs with the -XX:-BootstrapGraal options. For example:
+Other VM Configurations
+-----------------------
 
-% mx vm -XX:-BootstrapGraal ...
+In addition to the VM configurations described above, there are
+VM configurations that omit all VM support for Graal:
 
+% mx --vm server-nograal build
+% mx --vm server-nograal vm -version
+java version "1.7.0_25"
+Java(TM) SE Runtime Environment (build 1.7.0_25-b15)
+OpenJDK 64-Bit Server VM (build 25.0-b43-internal, mixed mode)
 
-Other Build Configurations
---------------------------
+% mx --vm client-nograal build
+% mx --vm client-nograal vm -version
+java version "1.7.0_25"
+Java(TM) SE Runtime Environment (build 1.7.0_25-b15)
+OpenJDK 64-Bit Cleint VM (build 25.0-b43-internal, mixed mode)
 
-By default the build commands above create a HotSpot binary where Graal
-is the only compiler. This binary is the Graal VM binary and identifies as
-such with the -version option:
-
-% mx vm -XX:-BootstrapGraal -version
-java version "1.7.0_07"
-Java(TM) SE Runtime Environment (build 1.7.0_07-b10)
-OpenJDK 64-Bit Graal VM (build 25.0-b10-internal, mixed mode)
-
-It's also possible to build and execute the standard HotSpot binaries
-using the --vm option:
-
-% mx --vm server build
-% mx --vm server vm -version
-java version "1.7.0_07"
-Java(TM) SE Runtime Environment (build 1.7.0_07-b10)
-OpenJDK 64-Bit Server VM (build 25.0-b10-internal, mixed mode)
-
-These standard binaries still include the code necessary to support use of the
-Graal compiler for explicit compilation requests. However, in this configuration
-the Graal compiler will not service VM issued compilation requests (e.g., upon
-counter overflow in the interpreter).
-
-To build a HotSpot binary that completely omits all VM support for Graal,
-define an environment variable OMIT_GRAAL (its value does not matter) and build
-with the --vm option as above (doing a clean first if necessary):
-
-% env OMIT_GRAAL= mx --vm server build
+These configurations aim to match as closely as possible the
+VM(s) included in the OpenJDK binaries one can download.
\ No newline at end of file
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ArithmeticOperation.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ArithmeticOperation.java	Wed Oct 02 13:26:31 2013 +0200
@@ -22,9 +22,13 @@
  */
 package com.oracle.graal.api.code;
 
+import com.oracle.graal.api.meta.*;
+
 /**
  * An {@code ArithmeticOperation} is an operation that does primitive value arithmetic without side
  * effect.
  */
 public interface ArithmeticOperation {
+
+    Constant evalConst(Constant... inputs);
 }
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CallingConvention.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CallingConvention.java	Wed Oct 02 13:26:31 2013 +0200
@@ -151,7 +151,7 @@
     private boolean verify() {
         for (int i = 0; i < argumentLocations.length; i++) {
             Value location = argumentLocations[i];
-            assert isStackSlot(location) || isRegister(location);
+            assert isStackSlot(location) || isAllocatableValue(location);
         }
         return true;
     }
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java	Wed Oct 02 13:26:31 2013 +0200
@@ -72,13 +72,6 @@
     ForeignCallLinkage lookupForeignCall(ForeignCallDescriptor descriptor);
 
     /**
-     * Encodes a deoptimization action and a deoptimization reason in an integer value.
-     * 
-     * @return the encoded value as an integer
-     */
-    int encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason);
-
-    /**
      * Determines if a {@link DataPatch} should be created for a given
      * {@linkplain Constant#getPrimitiveAnnotation() annotated} primitive constant that part of a
      * {@link CompilationResult}. A data patch is always created for an object constant.
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DebugInfo.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DebugInfo.java	Wed Oct 02 13:26:31 2013 +0200
@@ -44,7 +44,6 @@
     private final BytecodePosition bytecodePosition;
     private final BitSet registerRefMap;
     private final BitSet frameRefMap;
-    private final short deoptimizationReason;
     private RegisterSaveLayout calleeSaveInfo;
 
     /**
@@ -55,11 +54,10 @@
      * @param registerRefMap the register map
      * @param frameRefMap the reference map for {@code frame}, which may be {@code null}
      */
-    public DebugInfo(BytecodePosition codePos, BitSet registerRefMap, BitSet frameRefMap, short deoptimizationReason) {
+    public DebugInfo(BytecodePosition codePos, BitSet registerRefMap, BitSet frameRefMap) {
         this.bytecodePosition = codePos;
         this.registerRefMap = registerRefMap;
         this.frameRefMap = frameRefMap;
-        this.deoptimizationReason = deoptimizationReason;
     }
 
     /**
@@ -127,15 +125,6 @@
     }
 
     /**
-     * Identifies the reason in case a deoptimization happens at this program counter.
-     * 
-     * @return the reason of the deoptimization
-     */
-    public short getDeoptimizationReason() {
-        return deoptimizationReason;
-    }
-
-    /**
      * Sets the map from the registers (in the caller's frame) to the slots where they are saved in
      * the current frame.
      */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DelegatingCodeCacheProvider.java	Wed Oct 02 13:26:31 2013 +0200
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2013, 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.code;
+
+import com.oracle.graal.api.meta.*;
+
+/**
+ * A {@link CodeCacheProvider} that delegates to another {@link CodeCacheProvider}.
+ */
+public class DelegatingCodeCacheProvider extends DelegatingMetaAccessProvider implements CodeCacheProvider {
+
+    public DelegatingCodeCacheProvider(CodeCacheProvider delegate) {
+        super(delegate);
+    }
+
+    @Override
+    protected CodeCacheProvider delegate() {
+        return (CodeCacheProvider) super.delegate();
+    }
+
+    public InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult) {
+        return delegate().addMethod(method, compResult);
+    }
+
+    public String disassemble(CompilationResult compResult, InstalledCode installedCode) {
+        return delegate().disassemble(compResult, installedCode);
+    }
+
+    public RegisterConfig lookupRegisterConfig() {
+        return delegate().lookupRegisterConfig();
+    }
+
+    public int getMinimumOutgoingSize() {
+        return delegate().getMinimumOutgoingSize();
+    }
+
+    public ForeignCallLinkage lookupForeignCall(ForeignCallDescriptor descriptor) {
+        return delegate().lookupForeignCall(descriptor);
+    }
+
+    public boolean needsDataPatch(Constant constant) {
+        return delegate().needsDataPatch(constant);
+    }
+
+    public TargetDescription getTarget() {
+        return delegate().getTarget();
+    }
+}
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/DeoptimizationAction.java	Fri Sep 06 21:37:50 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.graal.api.code;
-
-/**
- * Specifies the action that should be taken by the runtime in case a certain deoptimization is
- * triggered.
- */
-public enum DeoptimizationAction {
-    /**
-     * Do not invalidate the machine code. This is typically used when deoptimizing at a point where
-     * it's highly likely nothing will change the likelihood of the deoptimization happening again.
-     * For example, a compiled array allocation where the size is negative.
-     */
-    None(false),
-
-    /**
-     * Do not invalidate the machine code, but schedule a recompilation if this deoptimization is
-     * triggered too often.
-     */
-    RecompileIfTooManyDeopts(true),
-
-    /**
-     * Invalidate the machine code and reset the profiling information.
-     */
-    InvalidateReprofile(true),
-
-    /**
-     * Invalidate the machine code and immediately schedule a recompilation. This is typically used
-     * when deoptimizing to resolve an unresolved symbol in which case extra profiling is not
-     * required to determine that the deoptimization will not re-occur.
-     */
-    InvalidateRecompile(true),
-
-    /**
-     * Invalidate the machine code and stop compiling the outermost method of this compilation.
-     */
-    InvalidateStopCompiling(true);
-
-    private final boolean invalidatesCompilation;
-
-    private DeoptimizationAction(boolean invalidatesCompilation) {
-        this.invalidatesCompilation = invalidatesCompilation;
-    }
-
-    public boolean doesInvalidateCompilation() {
-        return invalidatesCompilation;
-    }
-
-}
--- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/SpeculationLog.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/SpeculationLog.java	Wed Oct 02 13:26:31 2013 +0200
@@ -36,11 +36,11 @@
 
     public static final int MAX_CACHE_SIZE = 1 << 15;
 
-    private List<DeoptimizationReason> speculations = new ArrayList<>();
+    private List<Object> speculations = new ArrayList<>();
     private boolean[] map = new boolean[10];
-    private Set<DeoptimizationReason> snapshot = new HashSet<>();
+    private Set<Object> snapshot = new HashSet<>();
 
-    public short addSpeculation(DeoptimizationReason reason) {
+    private short addSpeculation(Object reason) {
         short index = (short) speculations.indexOf(reason);
         if (index != -1) {
             // Nothing to add, reason already registered.
@@ -68,7 +68,10 @@
         }
     }
 
-    public boolean maySpeculate(DeoptimizationReason reason) {
-        return !snapshot.contains(reason);
+    public Constant maySpeculate(Object reason) {
+        if (snapshot.contains(reason)) {
+            return null;
+        }
+        return Constant.forShort(addSpeculation(reason));
     }
 }
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestMetaAccessProvider.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestMetaAccessProvider.java	Wed Oct 02 13:26:31 2013 +0200
@@ -107,15 +107,13 @@
     @Test
     public void lookupArrayLengthTest() {
         for (Constant c : constants) {
+            Integer actual = runtime.lookupArrayLength(c);
             if (c.getKind() != Kind.Object || c.isNull() || !c.asObject().getClass().isArray()) {
-                try {
-                    int length = runtime.lookupArrayLength(c);
-                    fail("Expected " + IllegalArgumentException.class.getName() + " for " + c + ", not " + length);
-                } catch (IllegalArgumentException e) {
-                    // pass
-                }
+                assertNull(actual);
             } else {
-                assertEquals(Array.getLength(c.asObject()), runtime.lookupArrayLength(c));
+                assertNotNull(actual);
+                int actualInt = actual;
+                assertEquals(Array.getLength(c.asObject()), actualInt);
             }
         }
     }
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaMethod.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaMethod.java	Wed Oct 02 13:26:31 2013 +0200
@@ -265,7 +265,9 @@
         ResolvedJavaMethod method2 = runtime.lookupJavaMethod(getClass().getDeclaredMethod("nullPointerExceptionOnFirstLine", Object.class, String.class));
         assertEquals(0, method1.getMaxStackSize());
         // some versions of javac produce bytecode with a stacksize of 2 for this method
-        assertTrue(3 == method2.getMaxStackSize() || 2 == method2.getMaxStackSize());
+        // JSR 292 also sometimes need one more stack slot
+        int method2StackSize = method2.getMaxStackSize();
+        assertTrue(2 <= method2StackSize && method2StackSize <= 4);
     }
 
     private Method findTestMethod(Method apiMethod) {
--- a/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaType.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.api.meta.test/src/com/oracle/graal/api/meta/test/TestResolvedJavaType.java	Wed Oct 02 13:26:31 2013 +0200
@@ -399,9 +399,11 @@
             }
             for (Method m : c.getDeclaredMethods()) {
                 if (!isStatic(m.getModifiers()) && !isPrivate(m.getModifiers())) {
-                    Method overridden = vtable.methods.put(new NameAndSignature(m), m);
-                    if (overridden != null) {
-                        // println(m + " overrides " + overridden);
+                    if (isAbstract(m.getModifiers())) {
+                        // A subclass makes a concrete method in a superclass abstract
+                        vtable.methods.remove(new NameAndSignature(m));
+                    } else {
+                        vtable.methods.put(new NameAndSignature(m), m);
                     }
                 }
             }
@@ -438,7 +440,13 @@
     @Test
     public void resolveMethodTest() {
         for (Class c : classes) {
-            if (!c.isPrimitive() && !c.isInterface()) {
+            if (c.isInterface() || c.isPrimitive()) {
+                ResolvedJavaType type = runtime.lookupJavaType(c);
+                for (Method m : c.getDeclaredMethods()) {
+                    ResolvedJavaMethod impl = type.resolveMethod(runtime.lookupJavaMethod(m));
+                    assertEquals(m.toString(), null, impl);
+                }
+            } else {
                 ResolvedJavaType type = runtime.lookupJavaType(c);
                 VTable vtable = getVTable(c);
                 for (Method impl : vtable.methods.values()) {
@@ -449,6 +457,11 @@
                         checkResolveMethod(type, m, i);
                     }
                 }
+                for (Method m : c.getDeclaredMethods()) {
+                    ResolvedJavaMethod impl = type.resolveMethod(runtime.lookupJavaMethod(m));
+                    ResolvedJavaMethod expected = isAbstract(m.getModifiers()) ? null : impl;
+                    assertEquals(type + " " + m.toString(), expected, impl);
+                }
             }
         }
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DelegatingMetaAccessProvider.java	Wed Oct 02 13:26:31 2013 +0200
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2013, 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.meta;
+
+import java.lang.reflect.*;
+
+/**
+ * A {@link MetaAccessProvider} that delegates to another {@link MetaAccessProvider}.
+ */
+public class DelegatingMetaAccessProvider implements MetaAccessProvider {
+
+    private final MetaAccessProvider delegate;
+
+    public DelegatingMetaAccessProvider(MetaAccessProvider delegate) {
+        this.delegate = delegate;
+    }
+
+    protected MetaAccessProvider delegate() {
+        return delegate;
+    }
+
+    public ResolvedJavaType lookupJavaType(Class<?> clazz) {
+        return delegate.lookupJavaType(clazz);
+    }
+
+    public ResolvedJavaMethod lookupJavaMethod(Method reflectionMethod) {
+        return delegate.lookupJavaMethod(reflectionMethod);
+    }
+
+    public ResolvedJavaMethod lookupJavaConstructor(Constructor reflectionConstructor) {
+        return delegate.lookupJavaConstructor(reflectionConstructor);
+    }
+
+    public ResolvedJavaField lookupJavaField(Field reflectionField) {
+        return delegate.lookupJavaField(reflectionField);
+    }
+
+    public ResolvedJavaType lookupJavaType(Constant constant) {
+        return delegate.lookupJavaType(constant);
+    }
+
+    public Signature parseMethodDescriptor(String methodDescriptor) {
+        return delegate.parseMethodDescriptor(methodDescriptor);
+    }
+
+    public boolean constantEquals(Constant x, Constant y) {
+        return delegate.constantEquals(x, y);
+    }
+
+    public Integer lookupArrayLength(Constant array) {
+        return delegate.lookupArrayLength(array);
+    }
+
+    public Constant readUnsafeConstant(Kind kind, Object base, long displacement, boolean compressible) {
+        return delegate.readUnsafeConstant(kind, base, displacement, compressible);
+    }
+
+    public boolean isReexecutable(ForeignCallDescriptor descriptor) {
+        return delegate.isReexecutable(descriptor);
+    }
+
+    public LocationIdentity[] getKilledLocations(ForeignCallDescriptor descriptor) {
+        return delegate.getKilledLocations(descriptor);
+    }
+
+    public boolean canDeoptimize(ForeignCallDescriptor descriptor) {
+        return delegate.canDeoptimize(descriptor);
+    }
+
+    public Constant encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason) {
+        return delegate().encodeDeoptActionAndReason(action, reason);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DeoptimizationAction.java	Wed Oct 02 13:26:31 2013 +0200
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.api.meta;
+
+/**
+ * Specifies the action that should be taken by the runtime in case a certain deoptimization is
+ * triggered.
+ */
+public enum DeoptimizationAction {
+    /**
+     * Do not invalidate the machine code. This is typically used when deoptimizing at a point where
+     * it's highly likely nothing will change the likelihood of the deoptimization happening again.
+     * For example, a compiled array allocation where the size is negative.
+     */
+    None(false),
+
+    /**
+     * Do not invalidate the machine code, but schedule a recompilation if this deoptimization is
+     * triggered too often.
+     */
+    RecompileIfTooManyDeopts(true),
+
+    /**
+     * Invalidate the machine code and reset the profiling information.
+     */
+    InvalidateReprofile(true),
+
+    /**
+     * Invalidate the machine code and immediately schedule a recompilation. This is typically used
+     * when deoptimizing to resolve an unresolved symbol in which case extra profiling is not
+     * required to determine that the deoptimization will not re-occur.
+     */
+    InvalidateRecompile(true),
+
+    /**
+     * Invalidate the machine code and stop compiling the outermost method of this compilation.
+     */
+    InvalidateStopCompiling(true);
+
+    private final boolean invalidatesCompilation;
+
+    private DeoptimizationAction(boolean invalidatesCompilation) {
+        this.invalidatesCompilation = invalidatesCompilation;
+    }
+
+    public boolean doesInvalidateCompilation() {
+        return invalidatesCompilation;
+    }
+
+}
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaAccessProvider.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/MetaAccessProvider.java	Wed Oct 02 13:26:31 2013 +0200
@@ -79,11 +79,11 @@
     boolean constantEquals(Constant x, Constant y);
 
     /**
-     * Returns the length of an array that is wrapped in a {@link Constant} object.
-     * 
-     * @throws IllegalArgumentException if {@code array} is not an array
+     * Returns the length of an array that is wrapped in a {@link Constant} object. If {@code array}
+     * is not an array, or the array length is not available at this point, the return value is
+     * {@code null}.
      */
-    int lookupArrayLength(Constant array);
+    Integer lookupArrayLength(Constant array);
 
     /**
      * Reads a value of this kind using a base address and a displacement.
@@ -113,4 +113,11 @@
      * Determines if deoptimization can occur during a given foreign call.
      */
     boolean canDeoptimize(ForeignCallDescriptor descriptor);
+
+    /**
+     * Encodes a deoptimization action and a deoptimization reason in an integer value.
+     * 
+     * @return the encoded value as an integer
+     */
+    Constant encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason);
 }
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaField.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaField.java	Wed Oct 02 13:26:31 2013 +0200
@@ -50,17 +50,21 @@
     boolean isSynthetic();
 
     /**
-     * Gets the constant value of this field for a given object, if available.
+     * Gets the constant value of this field. Note that a {@code static final} field may not be
+     * considered constant if its declaring class is not yet initialized or if it is a well known
+     * field that can be updated via other means (e.g., {@link System#setOut(java.io.PrintStream)}).
      * 
      * @param receiver object from which this field's value is to be read. This value is ignored if
      *            this field is static.
-     * @return the constant value of this field or {@code null} if the constant value is not
-     *         available
+     * @return the constant value of this field or {@code null} if this field is not considered
+     *         constant by the runtime
      */
     Constant readConstantValue(Constant receiver);
 
     /**
-     * Gets the current value of this field for a given object, if available.
+     * Gets the current value of this field for a given object, if available. There is no guarantee
+     * that the same value will be returned by this method for a field unless the field is
+     * considered to be {@link #readConstantValue(Constant)} by the runtime.
      * 
      * @param receiver object from which this field's value is to be read. This value is ignored if
      *            this field is static.
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaMethod.java	Wed Oct 02 13:26:31 2013 +0200
@@ -175,12 +175,14 @@
     boolean canBeInlined();
 
     /**
-     * Returns the LineNumberTable of this method.
+     * Returns the LineNumberTable of this method or null if this method does not have a line
+     * numbers table.
      */
     LineNumberTable getLineNumberTable();
 
     /**
-     * Returns the localvariable table of this method.
+     * Returns the local variable table of this method or null if this method does not have a local
+     * variable table.
      */
     LocalVariableTable getLocalVariableTable();
 
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java	Wed Oct 02 13:26:31 2013 +0200
@@ -112,7 +112,7 @@
     int getModifiers();
 
     /**
-     * Checks whether this type is initialized. If a type is initialized it implies that is was
+     * Checks whether this type is initialized. If a type is initialized it implies that it was
      * {@link #isLinked() linked} and that the static initializer has run.
      * 
      * @return {@code true} if this type is initialized
@@ -205,10 +205,13 @@
 
     /**
      * Resolves the method implementation for virtual dispatches on objects of this dynamic type.
+     * This resolution process only searches "up" the class hierarchy of this type. A broader search
+     * that also walks "down" the hierarchy is implemented by
+     * {@link #findUniqueConcreteMethod(ResolvedJavaMethod)}.
      * 
      * @param method the method to select the implementation of
-     * @return the method implementation that would be selected at runtime, or {@code null} if the
-     *         runtime cannot resolve the method at this point in time.
+     * @return the concrete method that would be selected at runtime, or {@code null} if there is no
+     *         concrete implementation of {@code method} in this type or any of its superclasses
      */
     ResolvedJavaMethod resolveMethod(ResolvedJavaMethod method);
 
--- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java	Wed Oct 02 13:26:31 2013 +0200
@@ -747,7 +747,7 @@
         emitOperandHelper(0, dst);
     }
 
-    private void jcc(ConditionFlag cc, int jumpTarget, boolean forceDisp32) {
+    public void jcc(ConditionFlag cc, int jumpTarget, boolean forceDisp32) {
         int shortSize = 2;
         int longSize = 6;
         long disp = jumpTarget - codeBuffer.position();
--- a/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAddress.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAddress.java	Wed Oct 02 13:26:31 2013 +0200
@@ -22,6 +22,7 @@
  */
 package com.oracle.graal.asm.ptx;
 
+import com.oracle.graal.lir.Variable;
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 
@@ -31,7 +32,7 @@
  */
 public final class PTXAddress extends AbstractAddress {
 
-    private final Register base;
+    private final Variable base;
     private final long displacement;
 
     /**
@@ -39,7 +40,7 @@
      * 
      * @param base the base register
      */
-    public PTXAddress(Register base) {
+    public PTXAddress(Variable base) {
         this(base, 0);
     }
 
@@ -50,7 +51,7 @@
      * @param base the base register
      * @param displacement the displacement
      */
-    public PTXAddress(Register base, long displacement) {
+    public PTXAddress(Variable base, long displacement) {
         this.base = base;
         this.displacement = displacement;
     }
@@ -59,7 +60,7 @@
      * @return Base register that defines the start of the address computation. If not present, is
      *         denoted by {@link Value#ILLEGAL}.
      */
-    public Register getBase() {
+    public Variable getBase() {
         return base;
     }
 
--- a/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXAssembler.java	Wed Oct 02 13:26:31 2013 +0200
@@ -22,7 +22,17 @@
  */
 package com.oracle.graal.asm.ptx;
 
-import com.oracle.graal.api.code.*;
+import static com.oracle.graal.api.code.ValueUtil.*;
+
+import com.oracle.graal.api.code.Register;
+import com.oracle.graal.api.code.RegisterConfig;
+import com.oracle.graal.api.code.TargetDescription;
+import com.oracle.graal.api.meta.Constant;
+import com.oracle.graal.api.meta.Kind;
+import com.oracle.graal.api.meta.Value;
+import com.oracle.graal.nodes.calc.Condition;
+import com.oracle.graal.graph.GraalInternalError;
+import com.oracle.graal.lir.Variable;
 
 public class PTXAssembler extends AbstractPTXAssembler {
 
@@ -30,535 +40,549 @@
         super(target);
     }
 
-    public final void at() {
-        emitString("@%p" + " " + "");
+    public enum ConditionOperator {
+        // @formatter:off
+
+        // Signed integer operators
+        S_EQ("eq"),
+        S_NE("ne"),
+        S_LT("lt"),
+        S_LE("le"),
+        S_GT("gt"),
+        S_GE("ge"),
+
+        // Unsigned integer operators
+        U_EQ("eq"),
+        U_NE("ne"),
+        U_LO("lo"),
+        U_LS("ls"),
+        U_HI("hi"),
+        U_HS("hs"),
+
+        // Bit-size integer operators
+        B_EQ("eq"),
+        B_NE("ne"),
+
+        // Floating-point operators
+        F_EQ("eq"),
+        F_NE("ne"),
+        F_LT("lt"),
+        F_LE("le"),
+        F_GT("gt"),
+        F_GE("ge"),
+
+        // Floating-point operators accepting NaN
+        F_EQU("equ"),
+        F_NEU("neu"),
+        F_LTU("ltu"),
+        F_LEU("leu"),
+        F_GTU("gtu"),
+        F_GEU("geu"),
+
+        // Floating-point operators testing for NaN
+        F_NUM("num"),
+        F_NAN("nan");
+
+        // @formatter:on
+
+        private final String operator;
+
+        private ConditionOperator(String op) {
+            this.operator = op;
+        }
+
+        public String getOperator() {
+            return operator;
+        }
     }
 
-    public final void atq() {
-        emitString("@%q" + " " + "");
+    public static class StandardFormat {
+
+        protected Kind valueKind;
+        protected Variable dest;
+        protected Value source1;
+        protected Value source2;
+        private boolean logicInstruction = false;
+
+        public StandardFormat(Variable dst, Value src1, Value src2) {
+            setDestination(dst);
+            setSource1(src1);
+            setSource2(src2);
+            setKind(dst.getKind());
+
+            // testAdd2B fails this assertion
+            // assert valueKind == src1.getKind();
+        }
+
+        public void setKind(Kind k) {
+            valueKind = k;
+        }
+
+        public void setDestination(Variable var) {
+            assert var != null;
+            dest = var;
+        }
+
+        public void setSource1(Value val) {
+            assert val != null;
+            source1 = val;
+        }
+
+        public void setSource2(Value val) {
+            assert val != null;
+            source2 = val;
+        }
+
+        public void setLogicInstruction(boolean b) {
+            logicInstruction = b;
+        }
+
+        public String typeForKind(Kind k) {
+            if (logicInstruction) {
+                switch (k.getTypeChar()) {
+                    case 's':
+                        return "b16";
+                    case 'i':
+                        return "b32";
+                    case 'j':
+                        return "b64";
+                    default:
+                        throw GraalInternalError.shouldNotReachHere();
+                }
+            } else {
+                switch (k.getTypeChar()) {
+                    case 'z':
+                        return "u8";
+                    case 'b':
+                        return "s8";
+                    case 's':
+                        return "s16";
+                    case 'c':
+                        return "u16";
+                    case 'i':
+                        return "s32";
+                    case 'f':
+                        return "f32";
+                    case 'j':
+                        return "s64";
+                    case 'd':
+                        return "f64";
+                    case 'a':
+                        return "u64";
+                    case '-':
+                        return "u32";
+                    default:
+                        throw GraalInternalError.shouldNotReachHere();
+                }
+            }
+        }
+
+        public String emit() {
+            return (typeForKind(valueKind) + emitRegister(dest, true) + emitValue(source1, true) + emitValue(source2, false) + ";");
+        }
+
+        public String emitValue(Value v, boolean comma) {
+            assert v != null;
+
+            if (isConstant(v)) {
+                return (emitConstant(v));
+            } else {
+                return (emitRegister((Variable) v, comma));
+            }
+        }
+
+        public String emitRegister(Variable v, boolean comma) {
+            return (" %r" + v.index + (comma ? "," : ""));
+        }
+
+        public String emitConstant(Value v) {
+            Constant constant = (Constant) v;
+
+            switch (v.getKind().getTypeChar()) {
+                case 'i':
+                    return (String.valueOf((int) constant.asLong()));
+                case 'f':
+                    return (String.valueOf(constant.asFloat()));
+                case 'j':
+                    return (String.valueOf(constant.asLong()));
+                case 'd':
+                    return (String.valueOf(constant.asDouble()));
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+    }
+
+    public static class SingleOperandFormat {
+
+        protected Variable dest;
+        protected Value    source;
+
+        public SingleOperandFormat(Variable dst, Value src) {
+            setDestination(dst);
+            setSource(src);
+        }
+
+        public void setDestination(Variable var) {
+            dest = var;
+        }
+
+        public void setSource(Value var) {
+            source = var;
+        }
+
+        public String typeForKind(Kind k) {
+            switch (k.getTypeChar()) {
+                case 'z':
+                    return "u8";
+                case 'b':
+                    return "s8";
+                case 's':
+                    return "s16";
+                case 'c':
+                    return "u16";
+                case 'i':
+                    return "s32";
+                case 'f':
+                    return "f32";
+                case 'j':
+                    return "s64";
+                case 'd':
+                    return "f64";
+                case 'a':
+                    return "u64";
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+
+        public String emit() {
+            return (typeForKind(dest.getKind()) + " " + emitVariable(dest) + ", " + emitValue(source) + ";");
+        }
+
+        public String emitValue(Value v) {
+            assert v != null;
+
+            if (isConstant(v)) {
+                return (emitConstant(v));
+            } else {
+                return (emitVariable((Variable) v));
+            }
+        }
+
+        public String emitConstant(Value v) {
+            Constant constant = (Constant) v;
+
+            switch (v.getKind().getTypeChar()) {
+                case 'i':
+                    return (String.valueOf((int) constant.asLong()));
+                case 'f':
+                    return (String.valueOf(constant.asFloat()));
+                case 'j':
+                    return (String.valueOf(constant.asLong()));
+                case 'd':
+                    return (String.valueOf(constant.asDouble()));
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+
+        public String emitVariable(Variable v) {
+            String name = v.getName();
+
+            if (name == null) {
+                return (" %r" + v.index);
+            } else {
+                return name;
+            }
+        }
+    }
+
+    public static class ConversionFormat extends SingleOperandFormat {
+
+        public ConversionFormat(Variable dst, Value src) {
+            super(dst, src);
+        }
+
+        @Override
+        public String emit() {
+            return (typeForKind(dest.getKind()) + "." + typeForKind(source.getKind()) + " " +
+                    emitVariable(dest) + ", " + emitValue(source) + ";");
+        }
+    }
+
+    public static class LoadStoreFormat extends StandardFormat {
+
+        protected PTXStateSpace space;
+
+        public LoadStoreFormat(PTXStateSpace space, Variable dst, Value src1, Value src2) {
+            super(dst, src1, src2);
+            setStateSpace(space);
+        }
+
+        public void setStateSpace(PTXStateSpace ss) {
+            space = ss;
+        }
+
+        public String emitAddress(Value var, Value val) {
+            assert var instanceof Variable;
+            assert val instanceof Constant;
+            Constant constant = (Constant) val;
+            return ("[" + emitRegister((Variable) var, false) + " + " + constant.asBoxedValue() + "]");
+        }
+
+        @Override
+        public String emitRegister(Variable var, boolean comma) {
+            /* if (space == Parameter) {
+                return ("param" + var.index);
+            } else {
+                return ("%r" + var.index);
+            } */
+            return ("%r" + var.index);
+        }
+
+        public String emit(boolean isLoad) {
+            if (isLoad) {
+                return (space.getStateName() + "." + typeForKind(valueKind) + " " +
+                        emitRegister(dest, false) + ", " + emitAddress(source1, source2) + ";");
+            } else {
+                return (space.getStateName() + "." + typeForKind(valueKind) + " " +
+                        emitAddress(source1, source2) + ", " + emitRegister(dest, false) + ";");
+            }
+        }
+    }
+
+    public static class Add extends StandardFormat {
+
+        public Add(Variable dst, Value src1, Value src2) {
+            super(dst, src1, src2);
+        }
+
+        public void emit(PTXAssembler asm) {
+            asm.emitString("add." + super.emit());
+        }
+    }
+
+    public static class And extends StandardFormat {
+
+        public And(Variable dst, Value src1, Value src2) {
+            super(dst, src1, src2);
+            setLogicInstruction(true);
+        }
+
+        public void emit(PTXAssembler asm) {
+            asm.emitString("and." + super.emit());
+        }
+    }
+
+    public static class Div extends StandardFormat {
+
+        public Div(Variable dst, Value src1, Value src2) {
+            super(dst, src1, src2);
+        }
+
+        public void emit(PTXAssembler asm) {
+            asm.emitString("div." + super.emit());
+        }
+    }
+
+    public static class Mul extends StandardFormat {
+
+        public Mul(Variable dst, Value src1, Value src2) {
+            super(dst, src1, src2);
+        }
+
+        public void emit(PTXAssembler asm) {
+            asm.emitString("mul.lo." + super.emit());
+        }
+    }
+
+    public static class Or extends StandardFormat {
+
+        public Or(Variable dst, Value src1, Value src2) {
+            super(dst, src1, src2);
+            setLogicInstruction(true);
+        }
+
+        public void emit(PTXAssembler asm) {
+            asm.emitString("or." + super.emit());
+        }
+    }
+
+    public static class Rem extends StandardFormat {
+
+        public Rem(Variable dst, Value src1, Value src2) {
+            super(dst, src1, src2);
+        }
+
+        public void emit(PTXAssembler asm) {
+            asm.emitString("rem." + super.emit());
+        }
+    }
+
+    public static class Shl extends StandardFormat {
+
+        public Shl(Variable dst, Value src1, Value src2) {
+            super(dst, src1, src2);
+            setLogicInstruction(true);
+        }
+
+        public void emit(PTXAssembler asm) {
+            asm.emitString("shl." + super.emit());
+        }
+    }
+
+    public static class Shr extends StandardFormat {
+
+        public Shr(Variable dst, Value src1, Value src2) {
+            super(dst, src1, src2);
+        }
+
+        public void emit(PTXAssembler asm) {
+            asm.emitString("shr." + super.emit());
+        }
+    }
+
+    public static class Sub extends StandardFormat {
+
+        public Sub(Variable dst, Value src1, Value src2) {
+            super(dst, src1, src2);
+        }
+
+        public void emit(PTXAssembler asm) {
+            asm.emitString("sub." + super.emit());
+        }
+    }
+
+    public static class Ushr extends StandardFormat {
+
+        public Ushr(Variable dst, Value src1, Value src2) {
+            super(dst, src1, src2);
+            setKind(Kind.Illegal);  // get around not having an Unsigned Kind
+        }
+
+        public void emit(PTXAssembler asm) {
+            asm.emitString("shr." + super.emit());
+        }
+    }
+
+    public static class Xor extends StandardFormat {
+
+        public Xor(Variable dst, Value src1, Value src2) {
+            super(dst, src1, src2);
+            setLogicInstruction(true);
+        }
+
+        public void emit(PTXAssembler asm) {
+            asm.emitString("xor." + super.emit());
+        }
     }
 
     // Checkstyle: stop method name check
-    public final void add_f32(Register d, Register a, Register b) {
-        emitString("add.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void add_f64(Register d, Register a, Register b) {
-        emitString("add.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void add_s16(Register d, Register a, Register b) {
-        emitString("add.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void add_s32(Register d, Register a, Register b) {
-        emitString("add.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void add_s64(Register d, Register a, Register b) {
-        emitString("add.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void add_s16(Register d, Register a, short s16) {
-        emitString("add.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s16 + ";" + "");
-    }
-
-    public final void add_s32(Register d, Register a, int s32) {
-        emitString("add.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s32 + ";" + "");
-    }
-
-    public final void add_s64(Register d, Register a, long s64) {
-        emitString("add.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s64 + ";" + "");
-    }
-
-    public final void add_f32(Register d, Register a, float f32) {
-        emitString("add.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f32 + ";" + "");
-    }
-
-    public final void add_f64(Register d, Register a, double f64) {
-        emitString("add.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f64 + ";" + "");
-    }
-
-    public final void add_u16(Register d, Register a, Register b) {
-        emitString("add.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void add_u32(Register d, Register a, Register b) {
-        emitString("add.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void add_u64(Register d, Register a, Register b) {
-        emitString("add.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void add_u16(Register d, Register a, short u16) {
-        emitString("add.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u16 + ";" + "");
-    }
-
-    public final void add_u32(Register d, Register a, int u32) {
-        emitString("add.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + "");
-    }
-
-    public final void add_u64(Register d, Register a, long u64) {
-        emitString("add.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u64 + ";" + "");
-    }
-
-    public final void add_sat_s32(Register d, Register a, Register b) {
-        emitString("add.sat.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void add_sat_s32(Register d, Register a, int s32) {
-        emitString("add.sat.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s32 + ";" + "");
-    }
-
-    public final void and_b16(Register d, Register a, Register b) {
-        emitString("and.b16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void and_b32(Register d, Register a, Register b) {
-        emitString("and.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void and_b64(Register d, Register a, Register b) {
-        emitString("and.b64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void and_b16(Register d, Register a, short b16) {
-        emitString("and.b16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b16 + ";" + "");
-    }
-
-    public final void and_b32(Register d, Register a, int b32) {
-        emitString("and.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b32 + ";" + "");
-    }
-
-    public final void and_b64(Register d, Register a, long b64) {
-        emitString("and.b64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b64 + ";" + "");
-    }
-
-    public final void bra(String tgt) {
-        emitString("bra" + " " + tgt + ";" + "");
+    public final void bra(String tgt, int pred) {
+        emitString((pred >= 0) ? "" : ("@%p" + pred + "  ") + "bra" + " " + tgt + ";" + "");
     }
 
     public final void bra_uni(String tgt) {
         emitString("bra.uni" + " " + tgt + ";" + "");
     }
 
-    public final void cvt_s32_f32(Register d, Register a) {
-        emitString("cvt.s32.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
+    public static class Cvt extends ConversionFormat {
+
+        public Cvt(Variable dst, Variable src) {
+            super(dst, src);
+        }
+
+        public void emit(PTXAssembler asm) {
+            asm.emitString("cvt." + super.emit());
+        }
+    }
+    
+    public static class Mov extends SingleOperandFormat {
+
+        public Mov(Variable dst, Value src) {
+            super(dst, src);
+        }
+
+        /*
+        public Mov(Variable dst, AbstractAddress src) {
+            throw GraalInternalError.unimplemented("AbstractAddress Mov");
+        }
+        */
+        
+        public void emit(PTXAssembler asm) {
+            asm.emitString("mov." + super.emit());
+        }
+    }
+    
+    public static class Neg extends SingleOperandFormat {
+
+        public Neg(Variable dst, Variable src) {
+            super(dst, src);
+        }
+
+        public void emit(PTXAssembler asm) {
+            asm.emitString("neg." + super.emit());
+        }
+    }
+    
+    public static class Not extends SingleOperandFormat {
+
+        public Not(Variable dst, Variable src) {
+            super(dst, src);
+        }
+
+        public void emit(PTXAssembler asm) {
+            asm.emitString("not." + super.emit());
+        }
+    }
+    
+    public static class Ld extends LoadStoreFormat {
+
+        public Ld(PTXStateSpace space, Variable dst, Variable src1, Value src2) {
+            super(space, dst, src1, src2);
+        }
+
+        public void emit(PTXAssembler asm) {
+            asm.emitString("ld." + super.emit(true));
+        }
     }
 
-    public final void cvt_s64_f32(Register d, Register a) {
-        emitString("cvt.s64.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
-    }
+    public static class St extends LoadStoreFormat {
 
-    public final void cvt_f64_f32(Register d, Register a) {
-        emitString("cvt.f64.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
-    }
+        public St(PTXStateSpace space, Variable dst, Variable src1, Value src2) {
+            super(space, dst, src1, src2);
+        }
 
-    public final void cvt_f32_f64(Register d, Register a) {
-        emitString("cvt.f32.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
-    }
-
-    public final void cvt_s32_f64(Register d, Register a) {
-        emitString("cvt.s32.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
-    }
-
-    public final void cvt_s64_f64(Register d, Register a) {
-        emitString("cvt.s64.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
-    }
-
-    public final void cvt_f32_s32(Register d, Register a) {
-        emitString("cvt.f32.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
-    }
-
-    public final void cvt_f64_s32(Register d, Register a) {
-        emitString("cvt.f64.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
-    }
-
-    public final void cvt_s8_s32(Register d, Register a) {
-        emitString("cvt.s8.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
-    }
-
-    public final void cvt_b16_s32(Register d, Register a) {
-        emitString("cvt.b16.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
-    }
-
-    public final void cvt_s64_s32(Register d, Register a) {
-        emitString("cvt.s64.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
-    }
-
-    public final void cvt_s32_s64(Register d, Register a) {
-        emitString("cvt.s32.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
-    }
-
-    public final void div_f32(Register d, Register a, Register b) {
-        emitString("div.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void div_f64(Register d, Register a, Register b) {
-        emitString("div.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void div_s16(Register d, Register a, Register b) {
-        emitString("div.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void div_s32(Register d, Register a, Register b) {
-        emitString("div.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void div_s64(Register d, Register a, Register b) {
-        emitString("div.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void div_s16(Register d, Register a, short s16) {
-        emitString("div.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s16 + ";" + "");
-    }
-
-    public final void div_s32(Register d, Register a, int s32) {
-        emitString("div.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s32 + ";" + "");
-    }
-
-    public final void div_s32(Register d, int s32, Register b) {
-        emitString("div.s32" + " " + "%r" + d.encoding() + ", " + s32 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void div_f32(Register d, float f32, Register b) {
-        emitString("div.f32" + " " + "%r" + d.encoding() + ", " + f32 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void div_f64(Register d, double f64, Register b) {
-        emitString("div.f64" + " " + "%r" + d.encoding() + ", " + f64 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void div_s64(Register d, Register a, long s64) {
-        emitString("div.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s64 + ";" + "");
-    }
-
-    public final void div_f32(Register d, Register a, float f32) {
-        emitString("div.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f32 + ";" + "");
-    }
-
-    public final void div_f64(Register d, Register a, double f64) {
-        emitString("div.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f64 + ";" + "");
-    }
-
-    public final void div_u16(Register d, Register a, Register b) {
-        emitString("div.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void div_u32(Register d, Register a, Register b) {
-        emitString("div.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void div_u64(Register d, Register a, Register b) {
-        emitString("div.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void div_u16(Register d, Register a, short u16) {
-        emitString("div.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u16 + ";" + "");
-    }
-
-    public final void div_u32(Register d, Register a, int u32) {
-        emitString("div.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + "");
-    }
-
-    public final void div_u64(Register d, Register a, long u64) {
-        emitString("div.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u64 + ";" + "");
+        public void emit(PTXAssembler asm) {
+            asm.emitString("st." + super.emit(false));
+        }
     }
 
     public final void exit() {
         emitString("exit;" + " " + "");
     }
 
-    public final void ld_global_b8(Register d, Register a, long immOff) {
-        emitString("ld.global.b8" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
-    }
+    public static class Param extends SingleOperandFormat {
 
-    public final void ld_global_b16(Register d, Register a, long immOff) {
-        emitString("ld.global.b16" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
-    }
+        private boolean lastParameter;
 
-    public final void ld_global_b32(Register d, Register a, long immOff) {
-        emitString("ld.global.b32" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
-    }
+        public Param(Variable d, boolean lastParam) {
+            super(d, null);
+            setLastParameter(lastParam);
+        }
 
-    public final void ld_global_b64(Register d, Register a, long immOff) {
-        emitString("ld.global.b64" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
-    }
+        public void setLastParameter(boolean value) {
+            lastParameter = value;
+        }
 
-    public final void ld_global_u8(Register d, Register a, long immOff) {
-        emitString("ld.global.u8" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
-    }
+        public String emitParameter(Variable v) {
+            return (" %r" + v.index);
+        }
 
-    public final void ld_global_u16(Register d, Register a, long immOff) {
-        emitString("ld.global.u16" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
-    }
-
-    public final void ld_global_u32(Register d, Register a, long immOff) {
-        emitString("ld.global.u32" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
-    }
-
-    public final void ld_global_u64(Register d, Register a, long immOff) {
-        emitString("ld.global.u64" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
-    }
-
-    public final void ld_global_s8(Register d, Register a, long immOff) {
-        emitString("ld.global.s8" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
-    }
-
-    public final void ld_global_s16(Register d, Register a, long immOff) {
-        emitString("ld.global.s16" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
-    }
-
-    public final void ld_global_s32(Register d, Register a, long immOff) {
-        emitString("ld.global.s32" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
-    }
-
-    public final void ld_global_s64(Register d, Register a, long immOff) {
-        emitString("ld.global.s64" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
-    }
-
-    public final void ld_global_f32(Register d, Register a, long immOff) {
-        emitString("ld.global.f32" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
-    }
-
-    public final void ld_global_f64(Register d, Register a, long immOff) {
-        emitString("ld.global.f64" + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
-    }
-
-    // Load from state space to destination register
-    public final void ld_from_state_space(String s, Register d, Register a, long immOff) {
-        emitString("ld" + s + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
-    }
-
-    // Load return address from return parameter which is in .param state space
-    public final void ld_return_address(String s, Register d, Register a, long immOff) {
-        emitString("ld.param." + s + " " + "%r" + d.encoding() + ", [" + a + " + " + immOff + "]" + ";" + "");
-    }
-
-    public final void mov_b16(Register d, Register a) {
-        emitString("mov.b16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
-    }
-
-    public final void mov_b32(Register d, Register a) {
-        emitString("mov.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
-    }
-
-    public final void mov_b64(Register d, Register a) {
-        emitString("mov.b64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
-    }
-
-    public final void mov_u16(Register d, Register a) {
-        emitString("mov.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
-    }
-
-    public final void mov_u32(Register d, Register a) {
-        emitString("mov.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
-    }
-
-    public final void mov_u64(Register d, Register a) {
-        emitString("mov.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
-    }
-
-    public final void mov_u64(@SuppressWarnings("unused") Register d, @SuppressWarnings("unused") AbstractAddress a) {
-        // emitString("mov.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
-    }
-
-    public final void mov_s16(Register d, Register a) {
-        emitString("mov.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
-    }
-
-    public final void mov_s32(Register d, Register a) {
-        emitString("mov.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
-    }
-
-    public final void mov_s64(Register d, Register a) {
-        emitString("mov.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
-    }
-
-    public final void mov_f32(Register d, Register a) {
-        emitString("mov.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
-    }
-
-    public final void mov_f64(Register d, Register a) {
-        emitString("mov.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
-    }
-
-    public final void mov_b16(Register d, short b16) {
-        emitString("mov.b16" + " " + "%r" + d.encoding() + ", " + b16 + ";" + "");
-    }
-
-    public final void mov_b32(Register d, int b32) {
-        emitString("mov.b32" + " " + "%r" + d.encoding() + ", " + b32 + ";" + "");
-    }
-
-    public final void mov_b64(Register d, long b64) {
-        emitString("mov.b64" + " " + "%r" + d.encoding() + ", " + b64 + ";" + "");
-    }
-
-    public final void mov_u16(Register d, short u16) {
-        emitString("mov.u16" + " " + "%r" + d.encoding() + ", " + u16 + ";" + "");
-    }
-
-    public final void mov_u32(Register d, int u32) {
-        emitString("mov.u32" + " " + "%r" + d.encoding() + ", " + u32 + ";" + "");
-    }
-
-    public final void mov_u64(Register d, long u64) {
-        emitString("mov.u64" + " " + "%r" + d.encoding() + ", " + u64 + ";" + "");
-    }
-
-    public final void mov_s16(Register d, short s16) {
-        emitString("mov.s16" + " " + "%r" + d.encoding() + ", " + s16 + ";" + "");
-    }
-
-    public final void mov_s32(Register d, int s32) {
-        emitString("mov.s32" + " " + "%r" + d.encoding() + ", " + s32 + ";" + "");
-    }
-
-    public final void mov_s64(Register d, long s64) {
-        emitString("mov.s64" + " " + "%r" + d.encoding() + ", " + s64 + ";" + "");
-    }
-
-    public final void mov_f32(Register d, float f32) {
-        emitString("mov.f32" + " " + "%r" + d.encoding() + ", " + f32 + ";" + "");
-    }
-
-    public final void mov_f64(Register d, double f64) {
-        emitString("mov.f64" + " " + "%r" + d.encoding() + ", " + f64 + ";" + "");
-    }
-
-    public final void mul_lo_f32(Register d, Register a, Register b) {
-        emitString("mul.lo.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void mul_lo_f64(Register d, Register a, Register b) {
-        emitString("mul.lo.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void mul_lo_s16(Register d, Register a, Register b) {
-        emitString("mul.lo.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void mul_lo_s32(Register d, Register a, Register b) {
-        emitString("mul.lo.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void mul_lo_s64(Register d, Register a, Register b) {
-        emitString("mul.lo.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void mul_lo_s16(Register d, Register a, short s16) {
-        emitString("mul.lo.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s16 + ";" + "");
-    }
-
-    public final void mul_lo_s32(Register d, Register a, int s32) {
-        emitString("mul.lo.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s32 + ";" + "");
-    }
-
-    public final void mul_lo_s64(Register d, Register a, long s64) {
-        emitString("mul.lo.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s64 + ";" + "");
-    }
-
-    public final void mul_lo_f32(Register d, Register a, float f32) {
-        emitString("mul.lo.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f32 + ";" + "");
-    }
-
-    public final void mul_lo_f64(Register d, Register a, double f64) {
-        emitString("mul.lo.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f64 + ";" + "");
-    }
-
-    public final void mul_lo_u16(Register d, Register a, Register b) {
-        emitString("mul.lo.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void mul_lo_u32(Register d, Register a, Register b) {
-        emitString("mul.lo.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void mul_lo_u64(Register d, Register a, Register b) {
-        emitString("mul.lo.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void mul_lo_u16(Register d, Register a, short u16) {
-        emitString("mul.lo.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u16 + ";" + "");
-    }
-
-    public final void mul_lo_u32(Register d, Register a, int u32) {
-        emitString("mul.lo.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + "");
-    }
-
-    public final void mul_lo_u64(Register d, Register a, long u64) {
-        emitString("mul.lo.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u64 + ";" + "");
-    }
-
-    public final void neg_f32(Register d, Register a) {
-        emitString("neg.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
-    }
-
-    public final void neg_f64(Register d, Register a) {
-        emitString("neg.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
-    }
-
-    public final void neg_s16(Register d, Register a) {
-        emitString("neg.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
-    }
-
-    public final void neg_s32(Register d, Register a) {
-        emitString("neg.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
-    }
-
-    public final void neg_s64(Register d, Register a) {
-        emitString("neg.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
-    }
-
-    public final void not_s16(Register d, Register a) {
-        emitString("not.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
-    }
-
-    public final void not_s32(Register d, Register a) {
-        emitString("not.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
-    }
-
-    public final void not_s64(Register d, Register a) {
-        emitString("not.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
-    }
-
-    public final void or_b16(Register d, Register a, Register b) {
-        emitString("or.b16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void or_b32(Register d, Register a, Register b) {
-        emitString("or.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void or_b64(Register d, Register a, Register b) {
-        emitString("or.b64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void or_b16(Register d, Register a, short b16) {
-        emitString("or.b16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b16 + ";" + "");
-    }
-
-    public final void or_b32(Register d, Register a, int b32) {
-        emitString("or.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b32 + ";" + "");
-    }
-
-    public final void or_b64(Register d, Register a, long b64) {
-        emitString("or.b64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b64 + ";" + "");
-    }
-
-    public final void param_8_decl(Register d, boolean lastParam) {
-        emitString(".param" + " " + ".s8" + " " + d + (lastParam ? "" : ","));
-    }
-
-    public final void param_32_decl(Register d, boolean lastParam) {
-        emitString(".param" + " " + ".s32" + " " + d + (lastParam ? "" : ","));
-    }
-
-    public final void param_64_decl(Register d, boolean lastParam) {
-        emitString(".param" + " " + ".s64" + " " + d + (lastParam ? "" : ","));
+        public void emit(PTXAssembler asm) {
+            asm.emitString(".param ." + typeForKind(dest.getKind()) + emitParameter(dest)  + (lastParameter ? "" : ","));
+        }
     }
 
     public final void popc_b32(Register d, Register a) {
@@ -569,54 +593,6 @@
         emitString("popc.b64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ";" + "");
     }
 
-    public final void rem_s16(Register d, Register a, Register b) {
-        emitString("rem.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void rem_s32(Register d, Register a, Register b) {
-        emitString("rem.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void rem_s64(Register d, Register a, Register b) {
-        emitString("rem.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void rem_s16(Register d, Register a, short s16) {
-        emitString("rem.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s16 + ";" + "");
-    }
-
-    public final void rem_s32(Register d, Register a, int s32) {
-        emitString("rem.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s32 + ";" + "");
-    }
-
-    public final void rem_s64(Register d, Register a, long s64) {
-        emitString("rem.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s64 + ";" + "");
-    }
-
-    public final void rem_u16(Register d, Register a, Register b) {
-        emitString("rem.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void rem_u32(Register d, Register a, Register b) {
-        emitString("rem.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void rem_u64(Register d, Register a, Register b) {
-        emitString("rem.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void rem_u16(Register d, Register a, short u16) {
-        emitString("rem.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u16 + ";" + "");
-    }
-
-    public final void rem_u32(Register d, Register a, int u32) {
-        emitString("rem.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + "");
-    }
-
-    public final void rem_u64(Register d, Register a, long u64) {
-        emitString("rem.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u64 + ";" + "");
-    }
-
     public final void ret() {
         emitString("ret;" + " " + "");
     }
@@ -625,501 +601,168 @@
         emitString("ret.uni;" + " " + "");
     }
 
-    public final void setp_eq_f32(Register a, Register b) {
-        emitString("setp.eq.f32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
+    public static class Setp  {
+
+        private ConditionOperator  operator;
+        private Value first, second;
+        private Kind kind;
+        private int predicate;
+
+        public Setp(Condition condition, Value first, Value second, int predicateRegisterNumber) {
+            setFirst(first);
+            setSecond(second);
+            setPredicate(predicateRegisterNumber);
+            setKind();
+            setConditionOperator(operatorForConditon(condition));
+        }
+
+        public void setFirst(Value v) {
+            first = v;
+        }
+
+        public void setSecond(Value v) {
+            second = v;
+        }
+
+        public void setPredicate(int p) {
+            predicate = p;
+        }
+
+        public void setConditionOperator(ConditionOperator co) {
+            operator = co;
+        }
+
+        private ConditionOperator operatorForConditon(Condition condition) {
+            char typeChar = kind.getTypeChar();
+
+            switch (typeChar) {
+                case 'z':
+                case 'c':
+                case 'a':
+                    // unsigned
+                    switch (condition) {
+                        case EQ: return ConditionOperator.U_EQ;
+                        case NE: return ConditionOperator.U_NE;
+                        case LT: return ConditionOperator.U_LO;
+                        case LE: return ConditionOperator.U_LS;
+                        case GT: return ConditionOperator.U_HI;
+                        case GE: return ConditionOperator.U_HS;
+                        default:
+                            throw GraalInternalError.shouldNotReachHere();
+                    }
+                case 'b':
+                case 's':
+                case 'i':
+                case 'j':
+                    // signed
+                    switch (condition) {
+                        case EQ: return ConditionOperator.S_EQ;
+                        case NE: return ConditionOperator.S_NE;
+                        case LT: return ConditionOperator.S_LT;
+                        case LE: return ConditionOperator.S_LE;
+                        case GT: return ConditionOperator.S_GT;
+                        case GE:
+                        case AE:
+                            return ConditionOperator.S_GE;
+                        default:
+                            throw GraalInternalError.shouldNotReachHere();
+                    }
+                case 'f':
+                case 'd':
+                    // floating point - do these need to accept NaN??
+                    switch (condition) {
+                        case EQ: return ConditionOperator.F_EQ;
+                        case NE: return ConditionOperator.F_NE;
+                        case LT: return ConditionOperator.F_LT;
+                        case LE: return ConditionOperator.F_LE;
+                        case GT: return ConditionOperator.F_GT;
+                        case GE: return ConditionOperator.F_GE;
+                        default:
+                            throw GraalInternalError.shouldNotReachHere();
+                    }
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+
+        public void setKind() {
+            // assert isConstant(first) && isConstant(second) == false;
+
+            if (isConstant(first)) {
+                kind = second.getKind();
+            } else {
+                kind = first.getKind();
+            }
+        }
+        
+        public String emitValue(Value v) {
+            assert v != null;
+
+            if (isConstant(v)) {
+                return (", " + emitConstant(v));
+            } else {
+                return (", " + emitVariable((Variable) v));
+            }
+        }
+
+        public String typeForKind(Kind k) {
+            switch (k.getTypeChar()) {
+                case 'z':
+                    return "u8";
+                case 'b':
+                    return "s8";
+                case 's':
+                    return "s16";
+                case 'c':
+                    return "u16";
+                case 'i':
+                    return "s32";
+                case 'f':
+                    return "f32";
+                case 'j':
+                    return "s64";
+                case 'd':
+                    return "f64";
+                case 'a':
+                    return "u64";
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+
+        public String emitConstant(Value v) {
+            Constant constant = (Constant) v;
+
+            switch (v.getKind().getTypeChar()) {
+                case 'i':
+                    return (String.valueOf((int) constant.asLong()));
+                case 'f':
+                    return (String.valueOf(constant.asFloat()));
+                case 'j':
+                    return (String.valueOf(constant.asLong()));
+                case 'd':
+                    return (String.valueOf(constant.asDouble()));
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+        }
+        
+        public String emitVariable(Variable v) {
+            return ("%r" + v.index);
+        }
+
+        public void emit(PTXAssembler asm) {
+            asm.emitString("setp." + operator.getOperator() + "." + typeForKind(kind) +
+                           " %p" + predicate + emitValue(first) + emitValue(second) + ";");
+        }
     }
-
-    public final void setp_ne_f32(Register a, Register b) {
-        emitString("setp.ne.f32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_lt_f32(Register a, Register b) {
-        emitString("setp.lt.f32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_le_f32(Register a, Register b) {
-        emitString("setp.le.f32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_gt_f32(Register a, Register b) {
-        emitString("setp.gt.f32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_ge_f32(Register a, Register b) {
-        emitString("setp.ge.f32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_eq_f32(float f32, Register b) {
-        emitString("setp.eq.f32" + " " + "%p" + ", " + f32 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_ne_f32(float f32, Register b) {
-        emitString("setp.ne.f32" + " " + "%p" + ", " + f32 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_lt_f32(float f32, Register b) {
-        emitString("setp.lt.f32" + " " + "%p" + ", " + f32 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_le_f32(float f32, Register b) {
-        emitString("setp.le.f32" + " " + "%p" + ", " + f32 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_gt_f32(float f32, Register b) {
-        emitString("setp.gt.f32" + " " + "%p" + ", " + f32 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_ge_f32(float f32, Register b) {
-        emitString("setp.ge.f32" + " " + "%p" + ", " + f32 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_eq_f64(double f64, Register b) {
-        emitString("setp.eq.f64" + " " + "%p" + ", " + f64 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_ne_f64(double f64, Register b) {
-        emitString("setp.ne.f64" + " " + "%p" + ", " + f64 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_lt_f64(double f64, Register b) {
-        emitString("setp.lt.f64" + " " + "%p" + ", " + f64 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_le_f64(double f64, Register b) {
-        emitString("setp.le.f64" + " " + "%p" + ", " + f64 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_gt_f64(double f64, Register b) {
-        emitString("setp.gt.f64" + " " + "%p" + ", " + f64 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_ge_f64(double f64, Register b) {
-        emitString("setp.ge.f64" + " " + "%p" + ", " + f64 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_eq_s64(Register a, Register b) {
-        emitString("setp.eq.s64" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_eq_s64(long s64, Register b) {
-        emitString("setp.eq.s64" + " " + "%p" + ", " + s64 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_eq_s32(Register a, Register b) {
-        emitString("setp.eq.s32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_ne_s32(Register a, Register b) {
-        emitString("setp.ne.s32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_lt_s32(Register a, Register b) {
-        emitString("setp.lt.s32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_le_s32(Register a, Register b) {
-        emitString("setp.le.s32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_gt_s32(Register a, Register b) {
-        emitString("setp.gt.s32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_ge_s32(Register a, Register b) {
-        emitString("setp.ge.s32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_eq_s32(Register a, int s32) {
-        emitString("setp.eq.s32" + " " + "%p" + ", %r" + a.encoding() + ", " + s32 + ";" + "");
-    }
-
-    public final void setp_ne_s32(Register a, int s32) {
-        emitString("setp.ne.s32" + " " + "%p" + ", %r" + a.encoding() + ", " + s32 + ";" + "");
-    }
-
-    public final void setp_lt_s32(Register a, int s32) {
-        emitString("setp.lt.s32" + " " + "%p" + ", %r" + a.encoding() + ", " + s32 + ";" + "");
-    }
-
-    public final void setp_le_s32(Register a, int s32) {
-        emitString("setp.le.s32" + " " + "%p" + ", %r" + a.encoding() + ", " + s32 + ";" + "");
-    }
-
-    public final void setp_gt_s32(Register a, int s32) {
-        emitString("setp.gt.s32" + " " + "%p" + ", %r" + a.encoding() + ", " + s32 + ";" + "");
-    }
-
-    public final void setp_ge_s32(Register a, int s32) {
-        emitString("setp.ge.s32" + " " + "%p" + ", %r" + a.encoding() + ", " + s32 + ";" + "");
-    }
-
-    public final void setp_eq_s32(int s32, Register b) {
-        emitString("setp.eq.s32" + " " + "%p" + ", " + s32 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_ne_s32(int s32, Register b) {
-        emitString("setp.ne.s32" + " " + "%p" + ", " + s32 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_lt_s32(int s32, Register b) {
-        emitString("setp.lt.s32" + " " + "%p" + ", " + s32 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_le_s32(int s32, Register b) {
-        emitString("setp.le.s32" + " " + "%p" + ", " + s32 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_gt_s32(int s32, Register b) {
-        emitString("setp.gt.s32" + " " + "%p" + ", " + s32 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_ge_s32(int s32, Register b) {
-        emitString("setp.ge.s32" + " " + "%p" + ", " + s32 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_eq_u32(Register a, Register b) {
-        emitString("setp.eq.u32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_ne_u32(Register a, Register b) {
-        emitString("setp.ne.u32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_lt_u32(Register a, Register b) {
-        emitString("setp.lt.u32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_le_u32(Register a, Register b) {
-        emitString("setp.le.u32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_gt_u32(Register a, Register b) {
-        emitString("setp.gt.u32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_ge_u32(Register a, Register b) {
-        emitString("setp.ge.u32" + " " + "%p" + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_eq_u32(Register a, int u32) {
-        emitString("setp.eq.u32" + " " + "%p" + ", %r" + a.encoding() + ", " + u32 + ";" + "");
-    }
-
-    public final void setp_ne_u32(Register a, int u32) {
-        emitString("setp.ne.u32" + " " + "%p" + ", %r" + a.encoding() + ", " + u32 + ";" + "");
-    }
-
-    public final void setp_lt_u32(Register a, int u32) {
-        emitString("setp.lt.u32" + " " + "%p" + ", %r" + a.encoding() + ", " + u32 + ";" + "");
-    }
-
-    public final void setp_le_u32(Register a, int u32) {
-        emitString("setp.le.u32" + " " + "%p" + ", %r" + a.encoding() + ", " + u32 + ";" + "");
-    }
-
-    public final void setp_gt_u32(Register a, int u32) {
-        emitString("setp.gt.u32" + " " + "%p" + ", %r" + a.encoding() + ", " + u32 + ";" + "");
-    }
-
-    public final void setp_ge_u32(Register a, int u32) {
-        emitString("setp.ge.u32" + " " + "%p" + ", %r" + a.encoding() + ", " + u32 + ";" + "");
-    }
-
-    public final void setp_eq_u32(int u32, Register b) {
-        emitString("setp.eq.u32" + " " + "%p" + ", " + u32 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_ne_u32(int u32, Register b) {
-        emitString("setp.ne.u32" + " " + "%p" + ", " + u32 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_lt_u32(int u32, Register b) {
-        emitString("setp.lt.u32" + " " + "%p" + ", " + u32 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_le_u32(int u32, Register b) {
-        emitString("setp.le.u32" + " " + "%p" + ", " + u32 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_gt_u32(int u32, Register b) {
-        emitString("setp.gt.u32" + " " + "%p" + ", " + u32 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void setp_ge_u32(int u32, Register b) {
-        emitString("setp.ge.u32" + " " + "%p" + ", " + u32 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    // Shift left - only types supported are .b16, .b32 and .b64
-    public final void shl_b16(Register d, Register a, Register b) {
-        emitString("shl.b16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void shl_b32(Register d, Register a, Register b) {
-        emitString("shl.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void shl_b64(Register d, Register a, Register b) {
-        emitString("shl.b64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void shl_b16_const(Register d, Register a, int b) {
-        emitString("shl.b16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b + ";" + "");
-    }
-
-    public final void shl_b32_const(Register d, Register a, int b) {
-        emitString("shl.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b + ";" + "");
-    }
-
-    public final void shl_b64_const(Register d, Register a, int b) {
-        emitString("shl.b64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b + ";" + "");
-    }
-
-    // Shift Right instruction
-    public final void shr_s16(Register d, Register a, Register b) {
-        emitString("shr.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void shr_s32(Register d, Register a, Register b) {
-        emitString("shr.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void shr_s64(Register d, Register a, Register b) {
-        emitString("shr.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void shr_s16(Register d, Register a, int u32) {
-        emitString("shr.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + "");
-    }
-
-    public final void shr_s32(Register d, Register a, int u32) {
-        emitString("shr.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + "");
-    }
-
-    public final void shr_s64(Register d, Register a, int u32) {
-        emitString("shr.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + "");
-    }
-
-    public final void shr_u16(Register d, Register a, Register b) {
-        emitString("shr.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void shr_u32(Register d, Register a, Register b) {
-        emitString("shr.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void shr_u64(Register d, Register a, Register b) {
-        emitString("shr.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void shr_u16(Register d, Register a, int u32) {
-        emitString("shr.u16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + "");
-    }
-
-    public final void shr_u32(Register d, Register a, int u32) {
-        emitString("shr.u32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u32 + ";" + "");
-    }
-
-    public final void shr_u64(Register d, Register a, long u64) {
-        emitString("shr.u64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + u64 + ";" + "");
-    }
-
-    // Store in global state space
-
-    public final void st_global_b8(Register a, long immOff, Register b) {
-        emitString("st.global.b8" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
-    }
-
-    public final void st_global_b16(Register a, long immOff, Register b) {
-        emitString("st.global.b16" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
-    }
-
-    public final void st_global_b32(Register a, long immOff, Register b) {
-        emitString("st.global.b32" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
-    }
-
-    public final void st_global_b64(Register a, long immOff, Register b) {
-        emitString("st.global.b64" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
-    }
-
-    public final void st_global_u8(Register a, long immOff, Register b) {
-        emitString("st.global.u8" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
-    }
-
-    public final void st_global_u16(Register a, long immOff, Register b) {
-        emitString("st.global.u16" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
-    }
-
-    public final void st_global_u32(Register a, long immOff, Register b) {
-        emitString("st.global.u32" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
-    }
-
-    public final void st_global_u64(Register a, long immOff, Register b) {
-        emitString("st.global.u64" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
-    }
-
-    public final void st_global_s8(Register a, long immOff, Register b) {
-        emitString("st.global.s8" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
-    }
-
-    public final void st_global_s16(Register a, long immOff, Register b) {
-        emitString("st.global.s16" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
-    }
-
-    public final void st_global_s32(Register a, long immOff, Register b) {
-        emitString("st.global.s32" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
-    }
-
-    public final void st_global_s64(Register a, long immOff, Register b) {
-        emitString("st.global.s64" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
-    }
-
-    public final void st_global_f32(Register a, long immOff, Register b) {
-        emitString("st.global.f32" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
-    }
-
-    public final void st_global_f64(Register a, long immOff, Register b) {
-        emitString("st.global.f64" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
-    }
-
-    // Store return value
-    public final void st_global_return_value_s8(Register a, long immOff, Register b) {
-        emitString("st.global.s8" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
-    }
-
-    public final void st_global_return_value_s32(Register a, long immOff, Register b) {
-        emitString("st.global.s32" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
-    }
-
-    public final void st_global_return_value_s64(Register a, long immOff, Register b) {
-        emitString("st.global.s64" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
-    }
-
-    public final void st_global_return_value_f32(Register a, long immOff, Register b) {
-        emitString("st.global.f32" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
-    }
-
-    public final void st_global_return_value_f64(Register a, long immOff, Register b) {
-        emitString("st.global.f64" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
-    }
-
-    public final void st_global_return_value_u32(Register a, long immOff, Register b) {
-        emitString("st.global.u32" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
-    }
-
-    public final void st_global_return_value_u64(Register a, long immOff, Register b) {
-        emitString("st.global.u64" + " " + "[%r" + a.encoding() + " + " + immOff + "], %r" + b.encoding() + ";" + "");
-    }
-
-    // Subtract instruction
-
-    public final void sub_f32(Register d, Register a, Register b) {
-        emitString("sub.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void sub_f64(Register d, Register a, Register b) {
-        emitString("sub.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void sub_s16(Register d, Register a, Register b) {
-        emitString("sub.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void sub_s32(Register d, Register a, Register b) {
-        emitString("sub.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void sub_s64(Register d, Register a, Register b) {
-        emitString("sub.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void sub_s16(Register d, Register a, short s16) {
-        emitString("sub.s16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s16 + ";" + "");
-    }
-
-    public final void sub_s32(Register d, Register a, int s32) {
-        emitString("sub.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s32 + ";" + "");
-    }
-
-    public final void sub_s64(Register d, Register a, int s32) {
-        emitString("sub.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s32 + ";" + "");
-    }
-
-    public final void sub_s64(Register d, Register a, long s64) {
-        emitString("sub.s64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s64 + ";" + "");
-    }
-
-    public final void sub_f32(Register d, Register a, float f32) {
-        emitString("sub.f32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f32 + ";" + "");
-    }
-
-    public final void sub_f64(Register d, Register a, double f64) {
-        emitString("sub.f64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + f64 + ";" + "");
-    }
-
-    public final void sub_s16(Register d, short s16, Register b) {
-        emitString("sub.s16" + " " + "%r" + d.encoding() + ", " + s16 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void sub_s32(Register d, int s32, Register b) {
-        emitString("sub.s32" + " " + "%r" + d.encoding() + ", " + s32 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void sub_s64(Register d, long s64, Register b) {
-        emitString("sub.s64" + " " + "%r" + d.encoding() + ", " + s64 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void sub_f32(Register d, float f32, Register b) {
-        emitString("sub.f32" + " " + "%r" + d.encoding() + ", %r" + b.encoding() + ", " + f32 + ";" + "");
-    }
-
-    public final void sub_f64(Register d, double f64, Register b) {
-        emitString("sub.f64" + " " + "%r" + d.encoding() + ", %r" + b.encoding() + ", " + f64 + ";" + "");
-    }
-
-    public final void sub_sat_s32(Register d, Register a, Register b) {
-        emitString("sub.sat.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void sub_sat_s32(Register d, Register a, int s32) {
-        emitString("sub.sat.s32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + s32 + ";" + "");
-    }
-
-    public final void sub_sat_s32(Register d, int s32, Register b) {
-        emitString("sub.sat.s32" + " " + "%r" + d.encoding() + ", " + s32 + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void xor_b16(Register d, Register a, Register b) {
-        emitString("xor.b16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void xor_b32(Register d, Register a, Register b) {
-        emitString("xor.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void xor_b64(Register d, Register a, Register b) {
-        emitString("xor.b64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", %r" + b.encoding() + ";" + "");
-    }
-
-    public final void xor_b16(Register d, Register a, short b16) {
-        emitString("xor.b16" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b16 + ";" + "");
-    }
-
-    public final void xor_b32(Register d, Register a, int b32) {
-        emitString("xor.b32" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b32 + ";" + "");
-    }
-
-    public final void xor_b64(Register d, Register a, long b64) {
-        emitString("xor.b64" + " " + "%r" + d.encoding() + ", %r" + a.encoding() + ", " + b64 + ";" + "");
-    }
-
     @Override
     public PTXAddress makeAddress(Register base, int displacement) {
-        return new PTXAddress(base, displacement);
+        throw GraalInternalError.shouldNotReachHere();
     }
 
     @Override
     public PTXAddress getPlaceholder() {
-        // TODO Auto-generated method stub
         return null;
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.asm.ptx/src/com/oracle/graal/asm/ptx/PTXStateSpace.java	Wed Oct 02 13:26:31 2013 +0200
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2013, 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.ptx;
+
+/**
+ * Represents the various PTX state spaces.
+ */
+public enum PTXStateSpace {
+
+    Parameter("param"),
+
+    Shared("shared"),
+
+    Local("local"),
+
+    Global("global"),
+
+    Const("const");
+
+    private final String stateName;
+
+    private PTXStateSpace(String name) {
+        this.stateName = name;
+    }
+
+    public String getStateName() {
+        return stateName;
+    }
+}
--- a/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAddress.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.asm.sparc/src/com/oracle/graal/asm/sparc/SPARCAddress.java	Wed Oct 02 13:26:31 2013 +0200
@@ -121,7 +121,7 @@
             throw GraalInternalError.shouldNotReachHere("address has index register");
         }
         // TODO Should we also hide the register save area size here?
-        if (getBase() == sp || getBase() == fp) {
+        if (getBase().equals(sp) || getBase().equals(fp)) {
             return displacement + STACK_BIAS;
         }
         return displacement;
--- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java	Wed Oct 02 13:26:31 2013 +0200
@@ -890,6 +890,6 @@
 
     @Override
     public void visitInfopointNode(InfopointNode i) {
-        append(new InfopointOp(stateFor(i.stateAfter(), DeoptimizationReason.None), i.reason));
+        append(new InfopointOp(stateFor(i.getState()), i.reason));
     }
 }
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticDoubleSpillTest.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticDoubleSpillTest.java	Wed Oct 02 13:26:31 2013 +0200
@@ -25,7 +25,8 @@
 import java.util.*;
 
 import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
-import org.junit.Test;
+
+import org.junit.*;
 
 /**
  * Tests the spilling of double variables into memory.
@@ -118,6 +119,7 @@
     }
 
     // Marked to only run on hardware until simulator spill bug is fixed.
+    @Ignore
     @Test
     public void test() {
         testGeneratedHsail();
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticIntSpillTest.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/StaticIntSpillTest.java	Wed Oct 02 13:26:31 2013 +0200
@@ -25,7 +25,8 @@
 import java.util.*;
 
 import com.oracle.graal.compiler.hsail.test.infra.GraalKernelTester;
-import org.junit.Test;
+
+import org.junit.*;
 
 /**
  * Tests the spilling of integers into memory.
@@ -87,6 +88,7 @@
     }
 
     // Marked to only run on hardware until simulator spill bug is fixed.
+    @Ignore
     @Test
     public void test() {
         testGeneratedHsail();
--- a/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILBackend.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILBackend.java	Wed Oct 02 13:26:31 2013 +0200
@@ -60,8 +60,16 @@
     }
 
     @Override
+    public boolean shouldAllocateRegisters() {
+        return true;
+    }
+
+    /**
+     * Use the HSAIL register set when the compilation target is HSAIL.
+     */
+    @Override
     public FrameMap newFrameMap() {
-        return new HSAILFrameMap(runtime(), target, runtime().lookupRegisterConfig());
+        return new HSAILFrameMap(runtime(), target, new HSAILRegisterConfig());
     }
 
     @Override
--- a/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILCompilationResult.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILCompilationResult.java	Wed Oct 02 13:26:31 2013 +0200
@@ -23,33 +23,25 @@
 
 package com.oracle.graal.compiler.hsail;
 
-import static com.oracle.graal.api.code.CodeUtil.*;
-
+import java.lang.reflect.*;
 import java.util.logging.*;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.code.CallingConvention.*;
-import com.oracle.graal.api.runtime.Graal;
-import com.oracle.graal.compiler.GraalCompiler;
-import com.oracle.graal.java.GraphBuilderConfiguration;
-import com.oracle.graal.java.GraphBuilderPhase;
-import com.oracle.graal.nodes.StructuredGraph;
-import com.oracle.graal.nodes.spi.GraalCodeCacheProvider;
-import com.oracle.graal.phases.OptimisticOptimizations;
-import com.oracle.graal.phases.PhasePlan;
+import com.oracle.graal.api.code.CallingConvention.Type;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.runtime.*;
+import com.oracle.graal.compiler.*;
+import com.oracle.graal.compiler.target.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.hsail.*;
+import com.oracle.graal.java.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.PhasePlan.PhasePosition;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.graph.GraalInternalError;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.tiers.*;
-import com.oracle.graal.nodes.spi.Replacements;
-import com.oracle.graal.compiler.target.Backend;
-import com.oracle.graal.hsail.*;
-
-import java.lang.reflect.Method;
 
 /**
  * Class that represents a HSAIL compilation result. Includes the compiled HSAIL code.
@@ -96,6 +88,33 @@
         return getHSAILCompilationResult(graph);
     }
 
+    /**
+     * HSAIL doesn't have a calling convention as such. Function arguments are actually passed in
+     * memory but then loaded into registers in the function body. This routine makes sure that
+     * arguments to a kernel or function are loaded (by the kernel or function body) into registers
+     * of the appropriate sizes. For example, int and float parameters should appear in S registers,
+     * whereas double and long parameters should appear in d registers.
+     */
+    public static CallingConvention getHSAILCallingConvention(CallingConvention.Type type, TargetDescription target, ResolvedJavaMethod method, boolean stackOnly) {
+        Signature sig = method.getSignature();
+        JavaType retType = sig.getReturnType(null);
+        int sigCount = sig.getParameterCount(false);
+        JavaType[] argTypes;
+        int argIndex = 0;
+        if (!Modifier.isStatic(method.getModifiers())) {
+            argTypes = new JavaType[sigCount + 1];
+            argTypes[argIndex++] = method.getDeclaringClass();
+        } else {
+            argTypes = new JavaType[sigCount];
+        }
+        for (int i = 0; i < sigCount; i++) {
+            argTypes[argIndex++] = sig.getParameterType(i, null);
+        }
+
+        RegisterConfig registerConfig = new HSAILRegisterConfig();
+        return registerConfig.getCallingConvention(type, retType, argTypes, target, stackOnly);
+    }
+
     public static HSAILCompilationResult getHSAILCompilationResult(StructuredGraph graph) {
         Debug.dump(graph, "Graph");
         TargetDescription target = new TargetDescription(new HSAIL(), true, 8, 0, true);
@@ -105,7 +124,7 @@
         phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
         phasePlan.addPhase(PhasePosition.AFTER_PARSING, new HSAILPhase());
         new HSAILPhase().apply(graph);
-        CallingConvention cc = getCallingConvention(runtime, Type.JavaCallee, graph.method(), false);
+        CallingConvention cc = getHSAILCallingConvention(Type.JavaCallee, target, graph.method(), false);
         try {
             CompilationResult compResult = GraalCompiler.compileGraph(graph, cc, graph.method(), runtime, replacements, hsailBackend, target, null, phasePlan, OptimisticOptimizations.NONE,
                             new SpeculationLog(), suitesProvider.getDefaultSuites(), new CompilationResult());
--- a/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java	Wed Oct 02 13:26:31 2013 +0200
@@ -143,12 +143,12 @@
             } else {
                 baseRegister = load(base);
             }
-        } else if (base == Value.ILLEGAL) {
+        } else if (base.equals(Value.ILLEGAL)) {
             baseRegister = Value.ILLEGAL;
         } else {
             baseRegister = asAllocatable(base);
         }
-        if (index != Value.ILLEGAL) {
+        if (!index.equals(Value.ILLEGAL)) {
             if (isConstant(index)) {
                 finalDisp += asConstant(index).asLong() * scale;
             } else {
@@ -160,7 +160,7 @@
                 } else {
                     indexRegister = convertedIndex;
                 }
-                if (baseRegister == Value.ILLEGAL) {
+                if (baseRegister.equals(Value.ILLEGAL)) {
                     baseRegister = asAllocatable(indexRegister);
                 } else {
                     baseRegister = emitAdd(baseRegister, indexRegister);
@@ -579,7 +579,7 @@
     }
 
     @Override
-    public void emitDeoptimize(DeoptimizationAction action, DeoptimizingNode deopting) {
+    public void emitDeoptimize(Value actionAndReason, DeoptimizingNode deopting) {
         append(new ReturnOp(Value.ILLEGAL));
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ArrayPTXTest.java	Wed Oct 02 13:26:31 2013 +0200
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2013, 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.compiler.ptx.test;
+
+import static com.oracle.graal.lir.ptx.ThreadDimension.*;
+
+import com.oracle.graal.lir.ptx.ParallelOver;
+import com.oracle.graal.lir.ptx.Warp;
+
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import org.junit.Test;
+
+public class ArrayPTXTest extends PTXTestBase {
+
+    @Test
+    public void testArray() {
+        int[] array1 = {
+            1, 2, 3, 4, 5, 6, 7, 8, 9
+        };
+        int[] array2 = {
+            1, 2, 3, 4, 5, 6, 7, 8, 9
+        };
+        int[] array3 = {
+            1, 2, 3, 4, 5, 6, 7, 8, 9
+        };
+
+        invoke(compile("testStoreArray1I"), array1, 2);
+        printReport("testStoreArray1I: " + Arrays.toString(array1));
+
+        invoke(compile("testStoreArrayWarp0"), array2, 2);
+        printReport("testStoreArrayWarp0: " + Arrays.toString(array2));
+
+        invoke(compile("testStoreArrayWarp1I"), array3, 2);
+        printReport("testStoreArrayWarp1I: " + Arrays.toString(array3));
+
+    }
+
+    public static void testStoreArray1I(int[] array, int i) {
+        array[i] = 42;
+    }
+
+    public static void testStoreArrayWarp0(int[] array,
+                                           @Warp(dimension = X) int i) {
+        array[i] = 42;
+    }
+
+    public static void testStoreArrayWarp1I(@ParallelOver(dimension = X) int[] array,
+                                            @Warp(dimension = X) int i) {
+        array[i] = 42;
+    }
+
+
+    public static void printReport(String message) {
+        // CheckStyle: stop system..print check
+        System.out.println(message);
+        // CheckStyle: resume system..print check
+    }
+
+    public static void main(String[] args) {
+        ArrayPTXTest test = new ArrayPTXTest();
+        for (Method m : ArrayPTXTest.class.getMethods()) {
+            String name = m.getName();
+            if (m.getAnnotation(Test.class) == null && name.startsWith("test")) {
+                // CheckStyle: stop system..print check
+                System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode()));
+                // CheckStyle: resume system..print check
+            }
+        }
+    }
+}
--- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ArrayTest.java	Fri Sep 06 21:37:50 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,117 +0,0 @@
-/*
- * Copyright (c) 2013, 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.compiler.ptx.test;
-
-import java.lang.reflect.Method;
-
-import org.junit.*;
-
-public class ArrayTest extends PTXTestBase {
-
-    @Ignore
-    @Test
-    public void testArray() {
-        compile("testArray1I");
-        compile("testArray1J");
-        compile("testArray1B");
-        compile("testArray1S");
-        compile("testArray1C");
-        compile("testArray1F");
-        compile("testArray1D");
-        compile("testArray1L");
-        compile("testStoreArray1I");
-        compile("testStoreArray1J");
-        compile("testStoreArray1B");
-        compile("testStoreArray1S");
-        compile("testStoreArray1F");
-        compile("testStoreArray1D");
-    }
-
-    public static int testArray1I(int[] array, int i) {
-        return array[i];
-    }
-
-    public static long testArray1J(long[] array, int i) {
-        return array[i];
-    }
-
-    public static byte testArray1B(byte[] array, int i) {
-        return array[i];
-    }
-
-    public static short testArray1S(short[] array, int i) {
-        return array[i];
-    }
-
-    public static char testArray1C(char[] array, int i) {
-        return array[i];
-    }
-
-    public static float testArray1F(float[] array, int i) {
-        return array[i];
-    }
-
-    public static double testArray1D(double[] array, int i) {
-        return array[i];
-    }
-
-    public static Object testArray1L(Object[] array, int i) {
-        return array[i];
-    }
-
-    public static void testStoreArray1I(int[] array, int i, int val) {
-        array[i] = val;
-    }
-
-    public static void testStoreArray1B(byte[] array, int i, byte val) {
-        array[i] = val;
-    }
-
-    public static void testStoreArray1S(short[] array, int i, short val) {
-        array[i] = val;
-    }
-
-    public static void testStoreArray1J(long[] array, int i, long val) {
-        array[i] = val;
-    }
-
-    public static void testStoreArray1F(float[] array, int i, float val) {
-        array[i] = val;
-    }
-
-    public static void testStoreArray1D(double[] array, int i, double val) {
-        array[i] = val;
-    }
-
-    public static void main(String[] args) {
-        ArrayTest test = new ArrayTest();
-        for (Method m : ArrayTest.class.getMethods()) {
-            String name = m.getName();
-            if (m.getAnnotation(Test.class) == null && name.startsWith("test")) {
-                // CheckStyle: stop system..print check
-                System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode()));
-                // CheckStyle: resume system..print check
-            }
-        }
-    }
-}
--- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/BasicPTXTest.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/BasicPTXTest.java	Wed Oct 02 13:26:31 2013 +0200
@@ -24,11 +24,13 @@
 
 import java.lang.reflect.Method;
 
+import org.junit.Ignore;
 import org.junit.Test;
 
 /**
  * Test class for small Java methods compiled to PTX kernels.
  */
+@Ignore
 public class BasicPTXTest extends PTXTestBase {
 
     @Test
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ControlPTXTest.java	Wed Oct 02 13:26:31 2013 +0200
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2013, 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.compiler.ptx.test;
+
+import org.junit.*;
+
+import java.lang.reflect.Method;
+
+public class ControlPTXTest extends PTXTestBase {
+
+    @Ignore
+    @Test
+    public void testControl() {
+        compile("testLoop");
+        // compile("testSwitch1I");
+        // compile("testStatic");
+        // compile("testCall");
+        // compile("testLookupSwitch1I");
+    }
+
+    public static int testLoop(int n) {
+        int sum = 0;
+
+        for (int i = 0; i < n; i++) {
+            sum++;
+        }
+        return sum;
+    }
+
+    public static int testSwitch1I(int a) {
+        switch (a) {
+            case 1:
+                return 2;
+            case 2:
+                return 3;
+            default:
+                return 4;
+        }
+    }
+
+    public static int testLookupSwitch1I(int a) {
+        switch (a) {
+            case 0:
+                return 1;
+            case 1:
+                return 2;
+            case 2:
+                return 3;
+            case 3:
+                return 1;
+            case 4:
+                return 2;
+            case 5:
+                return 3;
+            case 6:
+                return 1;
+            case 7:
+                return 2;
+            case 8:
+                return 3;
+            case 9:
+                return 1;
+            case 10:
+                return 2;
+            case 11:
+                return 3;
+            default:
+                return -1;
+        }
+    }
+
+    @SuppressWarnings("unused") private static Object foo = null;
+
+    public static boolean testStatic(Object o) {
+        foo = o;
+        return true;
+    }
+
+    private static int method(int a, int b) {
+        return a + b;
+    }
+
+    public static int testCall(@SuppressWarnings("unused") Object o, int a, int b) {
+        return method(a, b);
+    }
+
+    public static void main(String[] args) {
+        ControlPTXTest test = new ControlPTXTest();
+        for (Method m : ControlPTXTest.class.getMethods()) {
+            String name = m.getName();
+            if (m.getAnnotation(Test.class) == null && name.startsWith("test")) {
+                // CheckStyle: stop system..print check
+                System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode()));
+                // CheckStyle: resume system..print check
+            }
+        }
+    }
+}
--- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/ControlTest.java	Fri Sep 06 21:37:50 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,96 +0,0 @@
-/*
- * Copyright (c) 2013, 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.compiler.ptx.test;
-
-import org.junit.*;
-
-import java.lang.reflect.Method;
-
-public class ControlTest extends PTXTestBase {
-
-    @Ignore
-    @Test
-    public void testControl() {
-        compile("testSwitch1I");
-        compile("testStatic");
-        compile("testCall");
-        compile("testLookupSwitch1I");
-    }
-
-    public static int testSwitch1I(int a) {
-        switch (a) {
-        case 1:
-            return 2;
-        case 2:
-            return 3;
-        default:
-            return 4;
-        }
-    }
-
-    public static int testLookupSwitch1I(int a) {
-        switch (a) {
-        case 0:  return 1;
-        case 1:  return 2;
-        case 2:  return 3;
-        case 3:  return 1;
-        case 4:  return 2;
-        case 5:  return 3;
-        case 6:  return 1;
-        case 7:  return 2;
-        case 8:  return 3;
-        case 9:  return 1;
-        case 10: return 2;
-        case 11: return 3;
-        default: return -1;
-        }
-    }
-
-    @SuppressWarnings("unused")
-    private static Object foo = null;
-
-    public static boolean testStatic(Object o) {
-        foo = o;
-        return true;
-    }
-
-    private static int method(int a, int b) {
-        return a + b;
-    }
-
-    public static int testCall(@SuppressWarnings("unused") Object o, int a, int b) {
-        return method(a, b);
-    }
-
-    public static void main(String[] args) {
-        ControlTest test = new ControlTest();
-        for (Method m : ControlTest.class.getMethods()) {
-            String name = m.getName();
-            if (m.getAnnotation(Test.class) == null && name.startsWith("test")) {
-                // CheckStyle: stop system..print check
-                System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode()));
-                // CheckStyle: resume system..print check
-            }
-        }
-    }
-}
--- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/FloatPTXTest.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/FloatPTXTest.java	Wed Oct 02 13:26:31 2013 +0200
@@ -29,14 +29,18 @@
 import com.oracle.graal.api.code.CompilationResult;
 
 /* PTX ISA 3.1 - 8.7.3 Floating-Point Instructions */
+@Ignore
 public class FloatPTXTest extends PTXTestBase {
 
+    @Ignore
     @Test
     public void testAdd() {
         CompilationResult r = compile("testAdd2F");
         if (r.getTargetCode() == null) {
             printReport("Compilation of testAdd2F FAILED");
         }
+
+        /*
         r = compile("testAdd2D");
         if (r.getTargetCode() == null) {
             printReport("Compilation of testAdd2D FAILED");
@@ -58,6 +62,7 @@
         if (r.getTargetCode() == null) {
             printReport("Compilation of testConstD FAILED");
         }
+        */
     }
 
     public static float testAdd2F(float a, float b) {
@@ -84,6 +89,7 @@
         return 32.0 + a;
     }
 
+    @Ignore
     @Test
     public void testSub() {
         CompilationResult r = compile("testSub2F");
@@ -141,6 +147,7 @@
         return 32.0 - a;
     }
 
+    @Ignore
     @Test
     public void testMul() {
         CompilationResult r = compile("testMul2F");
@@ -198,6 +205,7 @@
         return 32.0 * a;
     }
 
+    @Ignore
     @Test
     public void testDiv() {
         CompilationResult r = compile("testDiv2F");
@@ -255,6 +263,7 @@
         return 32.0 / a;
     }
 
+    @Ignore
     @Test
     public void testNeg() {
         CompilationResult r = compile("testNeg2F");
@@ -276,6 +285,7 @@
         return -a;
     }
 
+    @Ignore
     @Test
     public void testRem() {
         // need linkage to PTX remainder()
@@ -360,9 +370,7 @@
         FloatPTXTest test = new FloatPTXTest();
         for (Method m : FloatPTXTest.class.getMethods()) {
             String name = m.getName();
-            if (m.getAnnotation(Test.class) == null &&
-                    name.startsWith("test") &&
-                    name.startsWith("testRem") == false) {
+            if (m.getAnnotation(Test.class) == null && name.startsWith("test") && name.startsWith("testRem") == false) {
                 // CheckStyle: stop system..print check
                 System.out.println(name + ": \n" + new String(test.compile(name).getTargetCode()));
                 // CheckStyle: resume system..print check
--- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/IntegerPTXTest.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/IntegerPTXTest.java	Wed Oct 02 13:26:31 2013 +0200
@@ -26,11 +26,19 @@
 
 import java.lang.reflect.Method;
 
-
 public class IntegerPTXTest extends PTXTestBase {
 
     @Test
     public void testAdd() {
+        /*
+        Integer r4 = (Integer) invoke(compile("testAdd2B"), (byte) 6, (byte) 4);
+        if (r4 == null) {
+            printReport("testAdd2B FAILED");
+        } else if (r4.intValue() == testAdd2B((byte) 6, (byte) 4)) {
+            printReport("testAdd2B PASSED");
+        } else {
+            printReport("testAdd2B FAILED");
+        } */
 
         Integer r4 = (Integer) invoke(compile("testAdd2I"), 18, 24);
         if (r4 == null) {
@@ -41,16 +49,14 @@
             printReport("testAdd2I FAILED");
         }
 
-        Long r2 = (Long) invoke(compile("testAdd2L"), (long) 12, (long) 6);
+        /* Long r2 = (Long) invoke(compile("testAdd2L"), (long) 12, (long) 6);
         if (r2 == null) {
             printReport("testAdd2L FAILED");
         } else if (r2.longValue() == testAdd2L(12, 6)) {
             printReport("testAdd2L PASSED");
         } else {
             printReport("testAdd2L FAILED");
-        }
-
-        //invoke(compile("testAdd2B"), (byte) 6, (byte) 4);
+        } 
 
         r4 = (Integer) invoke(compile("testAddIConst"), 5);
         if (r4 == null) {
@@ -68,8 +74,7 @@
             printReport("testAddConstI PASSED");
         } else {
             printReport("testAddConstI FAILED");
-        }
-
+        } */
     }
 
     public static int testAdd2I(int a, int b) {
@@ -92,6 +97,7 @@
         return 32 + a;
     }
 
+    @Ignore
     @Test
     public void testSub() {
 
@@ -149,6 +155,7 @@
         return 32 - a;
     }
 
+    @Ignore
     @Test
     public void testMul() {
 
@@ -260,6 +267,7 @@
         return 32 / a;
     }
 
+    @Ignore
     @Test
     public void testRem() {
         Integer r1 = (Integer) invoke(compile("testRem2I"), 8, 4);
@@ -288,6 +296,7 @@
     public static long testRem2L(long a, long b) {
         return a % b;
     }
+
     @Ignore
     @Test
     public void testIntConversion() {
--- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/LogicPTXTest.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/LogicPTXTest.java	Wed Oct 02 13:26:31 2013 +0200
@@ -24,10 +24,11 @@
 
 import java.lang.reflect.Method;
 
+import org.junit.Ignore;
 import org.junit.Test;
 
-
 /* PTX ISA 3.1 - 8.7.5 Logic and Shift Instructions */
+@Ignore
 public class LogicPTXTest extends PTXTestBase {
 
     @Test
@@ -105,7 +106,7 @@
         compile("testShiftRight2I");
         compile("testShiftRight2L");
         compile("testUnsignedShiftRight2I");
-        compile("testUnsignedShiftRight2L");
+        // compile("testUnsignedShiftRight2L");
     }
 
     public static int testShiftRight2I(int a, int b) {
--- a/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXTestBase.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler.ptx.test/src/com/oracle/graal/compiler/ptx/test/PTXTestBase.java	Wed Oct 02 13:26:31 2013 +0200
@@ -30,12 +30,16 @@
 import com.oracle.graal.api.runtime.Graal;
 import com.oracle.graal.compiler.GraalCompiler;
 import com.oracle.graal.compiler.ptx.PTXBackend;
+import com.oracle.graal.compiler.ptx.PTXTargetMethodAssembler;
 import com.oracle.graal.compiler.test.GraalCompilerTest;
 import com.oracle.graal.debug.Debug;
+import com.oracle.graal.hotspot.meta.HotSpotNmethod;
 import com.oracle.graal.hotspot.meta.HotSpotRuntime;
 import com.oracle.graal.hotspot.meta.HotSpotResolvedJavaMethod;
+import com.oracle.graal.hotspot.ptx.PTXHotSpotRuntime;
 import com.oracle.graal.java.GraphBuilderConfiguration;
 import com.oracle.graal.java.GraphBuilderPhase;
+import com.oracle.graal.lir.ptx.ParallelOver;
 import com.oracle.graal.nodes.StructuredGraph;
 import com.oracle.graal.nodes.spi.GraalCodeCacheProvider;
 import com.oracle.graal.phases.OptimisticOptimizations;
@@ -43,6 +47,8 @@
 import com.oracle.graal.phases.PhasePlan.PhasePosition;
 import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.ptx.PTX;
+
+import java.lang.annotation.Annotation;
 import java.lang.reflect.Modifier;
 
 public abstract class PTXTestBase extends GraalCompilerTest {
@@ -50,32 +56,36 @@
     private StructuredGraph sg;
 
     protected CompilationResult compile(String test) {
-        StructuredGraph graph = parse(test);
-        sg = graph;
-        Debug.dump(graph, "Graph");
-        TargetDescription target = new TargetDescription(new PTX(), true, 1, 0, true);
-        PTXBackend ptxBackend = new PTXBackend(Graal.getRequiredCapability(GraalCodeCacheProvider.class), target);
-        PhasePlan phasePlan = new PhasePlan();
-        GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.NONE);
-        phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
-        phasePlan.addPhase(PhasePosition.AFTER_PARSING, new PTXPhase());
-        new PTXPhase().apply(graph);
-        CallingConvention cc = getCallingConvention(runtime, Type.JavaCallee, graph.method(), false);
-        /*
-         * Use Suites.createDefaultSuites() instead of GraalCompilerTest.suites. The
-         * GraalCompilerTest.suites variable contains the Suites for the HotSpotRuntime. This code
-         * will not run on hotspot, so it should use the plain Graal default suites, without hotspot
-         * specific phases.
-         *
-         * Ultimately we might want to have both the kernel and the code natively compiled for GPU fallback to CPU in cases
-         * of ECC failure on kernel invocation.  
-         */
-        CompilationResult result = GraalCompiler.compileGraph(graph, cc, graph.method(), runtime,
-                                                              graalRuntime().getReplacements(), ptxBackend, target,
-                                                              null, phasePlan,
-                                                              OptimisticOptimizations.NONE, new SpeculationLog(),
-                                                              Suites.createDefaultSuites(), new ExternalCompilationResult());
-        return result;
+        if (runtime instanceof PTXHotSpotRuntime) {
+            StructuredGraph graph = parse(test);
+            sg = graph;
+            Debug.dump(graph, "Graph");
+            TargetDescription target = new TargetDescription(new PTX(), true, 1, 0, true);
+            PTXBackend ptxBackend = new PTXBackend(Graal.getRequiredCapability(GraalCodeCacheProvider.class), target);
+            PhasePlan phasePlan = new PhasePlan();
+            GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.NONE);
+            phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
+            phasePlan.addPhase(PhasePosition.AFTER_PARSING, new PTXPhase());
+            new PTXPhase().apply(graph);
+            CallingConvention cc = getCallingConvention(runtime, Type.JavaCallee, graph.method(), false);
+            /*
+             * Use Suites.createDefaultSuites() instead of GraalCompilerTest.suites. The
+             * GraalCompilerTest.suites variable contains the Suites for the HotSpotRuntime. This code
+             * will not run on hotspot, so it should use the plain Graal default suites, without hotspot
+             * specific phases.
+             *
+             * Ultimately we might want to have both the kernel and the code natively compiled for GPU fallback to CPU in cases
+             * of ECC failure on kernel invocation.  
+             */
+            CompilationResult result = GraalCompiler.compileGraph(graph, cc, graph.method(), runtime,
+                                                                  graalRuntime().getReplacements(), ptxBackend, target,
+                                                                  null, phasePlan,
+                                                                  OptimisticOptimizations.NONE, new SpeculationLog(),
+                                                                  Suites.createDefaultSuites(), new ExternalCompilationResult());
+            return result;
+        } else {
+            return null;
+        }
     }
 
     protected StructuredGraph getStructuredGraph() {
@@ -83,6 +93,9 @@
     }
 
     protected Object invoke(CompilationResult result, Object... args) {
+        if (result == null) {
+            return null;
+        }
         try {
             if (((ExternalCompilationResult) result).getEntryPoint() == 0) {
                 Debug.dump(result, "[CUDA] *** Null entry point - Not launching kernel");
@@ -94,8 +107,47 @@
             boolean isStatic = Modifier.isStatic(compiledMethod.getModifiers());
             Object[] executeArgs = argsWithReceiver((isStatic ? null : this), args);
             HotSpotRuntime hsr = (HotSpotRuntime) runtime;
-            InstalledCode installedCode = hsr.addExternalMethod(sg.method(), result, sg);
-            Object r = installedCode.executeVarargs(executeArgs);
+            InstalledCode installedCode = hsr.addExternalMethod(compiledMethod, result, sg);
+            Annotation[][] params = compiledMethod.getParameterAnnotations();
+
+            int dimensionX = 1;
+            int dimensionY = 1;
+            int dimensionZ = 1;
+
+            for (int p = 0; p < params.length; p++) {
+                Annotation[] annos = params[p];
+                if (annos != null) {
+                    for (int a = 0; a < annos.length; a++) {
+                        Annotation aa = annos[a];
+                        if (args[p] instanceof int[] && aa.annotationType().equals(ParallelOver.class)) {
+                            int[] iarray = (int[]) args[p];
+                            ParallelOver threadBlockDimension = (ParallelOver) aa;
+                            switch (threadBlockDimension.dimension()) {
+                                case X:
+                                    dimensionX = iarray.length;
+                                    break;
+                                case Y:
+                                    dimensionY = iarray.length;
+                                    break;
+                                case Z:
+                                    dimensionZ = iarray.length;
+                                    break;
+                            }
+                        }
+                    }
+                }
+            }
+            Object r;
+            if (dimensionX != 1 || dimensionY != 1 || dimensionZ != 1) {
+                /*
+                 * for now assert that the warp array block is no larger than the number of physical gpu cores.
+                 */
+                assert dimensionX * dimensionY * dimensionZ < PTXTargetMethodAssembler.getAvailableProcessors();
+
+                r = ((HotSpotNmethod) installedCode).executeParallel(dimensionX, dimensionY, dimensionZ, executeArgs);
+            } else {
+                r = installedCode.executeVarargs(executeArgs);
+            }
             return r;
         } catch (Throwable th) {
             th.printStackTrace();
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXBackend.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXBackend.java	Wed Oct 02 13:26:31 2013 +0200
@@ -22,7 +22,7 @@
  */
 package com.oracle.graal.compiler.ptx;
 
-import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.lir.LIRValueUtil.*;
 
 import java.util.*;
 
@@ -40,6 +40,7 @@
 import com.oracle.graal.lir.LIRInstruction.OperandFlag;
 import com.oracle.graal.lir.LIRInstruction.OperandMode;
 import com.oracle.graal.lir.LIRInstruction.ValueProcedure;
+import com.oracle.graal.lir.StandardOp.LabelOp;
 import com.oracle.graal.graph.GraalInternalError;
 
 /**
@@ -52,6 +53,11 @@
     }
 
     @Override
+    public boolean shouldAllocateRegisters() {
+        return false;
+    }
+
+    @Override
     public FrameMap newFrameMap() {
         return new PTXFrameMap(runtime(), target, runtime().lookupRegisterConfig());
     }
@@ -80,7 +86,7 @@
 
     @Override
     public TargetMethodAssembler newAssembler(LIRGenerator lirGen, CompilationResult compilationResult) {
-        // Omit the frame if the method:
+        // Omit the frame of the method:
         // - has no spill slots or other slots allocated during register allocation
         // - has no callee-saved registers
         // - has no incoming arguments passed on the stack
@@ -89,14 +95,13 @@
         AbstractAssembler masm = createAssembler(frameMap);
         HotSpotFrameContext frameContext = new HotSpotFrameContext();
         TargetMethodAssembler tasm = new PTXTargetMethodAssembler(target, runtime(), frameMap, masm, frameContext, compilationResult);
-        tasm.setFrameSize(frameMap.frameSize());
+        tasm.setFrameSize(0);
         return tasm;
     }
 
-    private static void emitKernelEntry(TargetMethodAssembler tasm, LIRGenerator lirGen,
-                                        ResolvedJavaMethod codeCacheOwner) {
+    private static void emitKernelEntry(TargetMethodAssembler tasm, LIRGenerator lirGen, ResolvedJavaMethod codeCacheOwner) {
         // Emit PTX kernel entry text based on PTXParameterOp
-        // instructions in the start block.  Remove the instructions
+        // instructions in the start block. Remove the instructions
         // once kernel entry text and directives are emitted to
         // facilitate seemless PTX code generation subsequently.
         assert codeCacheOwner != null : lirGen.getGraph() + " is not associated with a method";
@@ -132,8 +137,6 @@
         // Start emiting body of the PTX kernel.
         codeBuffer.emitString0(") {");
         codeBuffer.emitString("");
-
-        codeBuffer.emitString(".reg .u64" + " %rax;");
     }
 
     // Emit .reg space declarations
@@ -144,23 +147,53 @@
 
         final SortedSet<Integer> signed32 = new TreeSet<>();
         final SortedSet<Integer> signed64 = new TreeSet<>();
+        final SortedSet<Integer> unsigned64 = new TreeSet<>();
+        final SortedSet<Integer> float32 = new TreeSet<>();
+        final SortedSet<Integer> float64 = new TreeSet<>();
 
         ValueProcedure trackRegisterKind = new ValueProcedure() {
 
             @Override
             public Value doValue(Value value, OperandMode mode, EnumSet<OperandFlag> flags) {
-                if (isRegister(value)) {
-                    RegisterValue regVal = (RegisterValue) value;
+                if (isVariable(value)) {
+                    Variable regVal = (Variable) value;
                     Kind regKind = regVal.getKind();
                     switch (regKind) {
-                       case Int:
-                           signed32.add(regVal.getRegister().encoding());
-                           break;
-                       case Long:
-                           signed64.add(regVal.getRegister().encoding());
-                           break;
-                       default :
-                           throw GraalInternalError.shouldNotReachHere("unhandled register type "  + value.toString());
+                        case Int:
+                            // If the register was used as a wider signed type
+                            // do not add it here
+                            if (!signed64.contains(regVal.index)) {
+                                signed32.add(regVal.index);
+                            }
+                            break;
+                        case Long:
+                            // If the register was used as a narrower signed type
+                            // remove it from there and add it to wider type.
+                            if (signed32.contains(regVal.index)) {
+                                signed32.remove(regVal.index);
+                            }
+                            signed64.add(regVal.index);
+                            break;
+                        case Float:
+                            // If the register was used as a wider signed type
+                            // do not add it here
+                            if (!float64.contains(regVal.index)) {
+                                float32.add(regVal.index);
+                            }
+                            break;
+                        case Double:
+                            // If the register was used as a narrower signed type
+                            // remove it from there and add it to wider type.
+                            if (float32.contains(regVal.index)) {
+                                float32.remove(regVal.index);
+                            }
+                            float64.add(regVal.index);
+                            break;
+                        case Object:
+                            unsigned64.add(regVal.index);
+                            break;
+                        default:
+                            throw GraalInternalError.shouldNotReachHere("unhandled register type " + value.toString());
                     }
                 }
                 return value;
@@ -169,7 +202,12 @@
 
         for (Block b : lirGen.lir.codeEmittingOrder()) {
             for (LIRInstruction op : lirGen.lir.lir(b)) {
-                op.forEachOutput(trackRegisterKind);
+                if (op instanceof LabelOp) {
+                    // Don't consider this as a definition
+                } else {
+                    op.forEachTemp(trackRegisterKind);
+                    op.forEachOutput(trackRegisterKind);
+                }
             }
         }
 
@@ -179,6 +217,20 @@
         for (Integer i : signed64) {
             codeBuffer.emitString(".reg .s64 %r" + i.intValue() + ";");
         }
+        for (Integer i : unsigned64) {
+            codeBuffer.emitString(".reg .u64 %r" + i.intValue() + ";");
+        }
+        for (Integer i : float32) {
+            codeBuffer.emitString(".reg .f32 %r" + i.intValue() + ";");
+        }
+        for (Integer i : float64) {
+            codeBuffer.emitString(".reg .f64 %r" + i.intValue() + ";");
+        }
+        // emit predicate register declaration
+        int maxPredRegNum = ((PTXLIRGenerator) lirGen).getNextPredRegNumber();
+        if (maxPredRegNum > 0) {
+            codeBuffer.emitString(".reg .pred %p<" + maxPredRegNum + ">;");
+        }
     }
 
     @Override
@@ -192,6 +244,7 @@
         try {
             emitRegisterDecl(tasm, lirGen, codeCacheOwner);
         } catch (GraalInternalError e) {
+            e.printStackTrace();
             // TODO : Better error handling needs to be done once
             //        all types of parameters are handled.
             codeBuffer.setPosition(0);
@@ -202,6 +255,7 @@
         try {
             lirGen.lir.emitCode(tasm);
         } catch (GraalInternalError e) {
+            e.printStackTrace();
             // TODO : Better error handling needs to be done once
             //        all types of parameters are handled.
             codeBuffer.setPosition(0);
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java	Wed Oct 02 13:26:31 2013 +0200
@@ -24,6 +24,7 @@
 package com.oracle.graal.compiler.ptx;
 
 import static com.oracle.graal.api.code.ValueUtil.*;
+import static com.oracle.graal.api.meta.Value.*;
 import static com.oracle.graal.lir.ptx.PTXArithmetic.*;
 import static com.oracle.graal.lir.ptx.PTXBitManipulationOp.IntrinsicOpcode.*;
 import static com.oracle.graal.lir.ptx.PTXCompare.*;
@@ -32,6 +33,7 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.*;
 import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.debug.Debug;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.StandardOp.JumpOp;
@@ -44,8 +46,6 @@
 import com.oracle.graal.lir.ptx.PTXArithmetic.Unary2Op;
 import com.oracle.graal.lir.ptx.PTXCompare.CompareOp;
 import com.oracle.graal.lir.ptx.PTXControlFlow.BranchOp;
-import com.oracle.graal.lir.ptx.PTXControlFlow.CondMoveOp;
-import com.oracle.graal.lir.ptx.PTXControlFlow.FloatCondMoveOp;
 import com.oracle.graal.lir.ptx.PTXControlFlow.ReturnOp;
 import com.oracle.graal.lir.ptx.PTXControlFlow.ReturnNoValOp;
 import com.oracle.graal.lir.ptx.PTXControlFlow.SequentialSwitchOp;
@@ -59,13 +59,22 @@
 import com.oracle.graal.lir.ptx.PTXMemOp.StoreReturnValOp;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.calc.ConvertNode.Op;
 import com.oracle.graal.nodes.java.*;
 
+import java.lang.annotation.*;
+
+
 /**
  * This class implements the PTX specific portion of the LIR generator.
  */
 public class PTXLIRGenerator extends LIRGenerator {
 
+    // Number of the predicate register that can be used when needed.
+    // This value will be recorded and incremented in the LIR instruction
+    // that sets a predicate register. (e.g., CompareOp)
+    private int nextPredRegNum;
+
     public static final ForeignCallDescriptor ARITHMETIC_FREM = new ForeignCallDescriptor("arithmeticFrem", float.class, float.class, float.class);
     public static final ForeignCallDescriptor ARITHMETIC_DREM = new ForeignCallDescriptor("arithmeticDrem", double.class, double.class, double.class);
 
@@ -73,13 +82,20 @@
 
         @Override
         public LIRInstruction createMove(AllocatableValue result, Value input) {
-            throw new InternalError("NYI");
+            throw GraalInternalError.unimplemented("PTXSpillMoveFactory.createMove()");
         }
     }
 
     public PTXLIRGenerator(StructuredGraph graph, CodeCacheProvider runtime, TargetDescription target, FrameMap frameMap, CallingConvention cc, LIR lir) {
         super(graph, runtime, target, frameMap, cc, lir);
         lir.spillMoveFactory = new PTXSpillMoveFactory();
+        int callVariables = cc.getArgumentCount() + (cc.getReturn() == Value.ILLEGAL ? 0 : 1);
+        lir.setFirstVariableNumber(callVariables);
+        nextPredRegNum = 0;
+    }
+
+    public int getNextPredRegNumber() {
+        return nextPredRegNum;
     }
 
     @Override
@@ -107,7 +123,9 @@
             if (isRegister(value)) {
                 return asRegister(value).asValue(value.getKind().getStackKind());
             } else if (isStackSlot(value)) {
-                return StackSlot.get(value.getKind().getStackKind(), asStackSlot(value).getRawOffset(), asStackSlot(value).getRawAddFrameSize());
+                return StackSlot.get(value.getKind().getStackKind(),
+                                     asStackSlot(value).getRawOffset(),
+                                     asStackSlot(value).getRawAddFrameSize());
             } else {
                 throw GraalInternalError.shouldNotReachHere();
             }
@@ -119,23 +137,62 @@
     public void emitPrologue() {
         // Need to emit .param directives based on incoming arguments and return value
         CallingConvention incomingArguments = cc;
-        int argCount = incomingArguments.getArgumentCount();
-        // Additional argument for return value.
-        Value[] params = new Value[argCount + 1];
-        for (int i = 0; i < argCount; i++) {
-            params[i] = toParamKind(incomingArguments.getArgument(i));
+        Object returnObject = incomingArguments.getReturn();
+        AllocatableValue[] params;
+        int argCount;
+
+        if (returnObject == Value.ILLEGAL) {
+            params = incomingArguments.getArguments();
+        } else {
+            argCount = incomingArguments.getArgumentCount();
+            params = new Variable[argCount + 1];
+            for (int i = 0; i < argCount; i++) {
+                params[i] = incomingArguments.getArgument(i);
+            }
+            params[argCount] = (Variable) returnObject;
         }
-        // Add the return value as the last parameter.
-        params[argCount] =  incomingArguments.getReturn();
 
         append(new PTXParameterOp(params));
         for (LocalNode local : graph.getNodes(LocalNode.class)) {
             Value param = params[local.index()];
-            assert param.getKind() == local.kind().getStackKind();
-            setResult(local, emitLoadParam(param.getKind(), param, null));
+            Annotation[] annos = graph.method().getParameterAnnotations()[local.index()];
+            Warp warpAnnotation = null;
+
+            if (annos != null) {
+                for (int a = 0; a < annos.length; a++) {
+                    if (annos[a].annotationType().equals(Warp.class)) {
+                        warpAnnotation = (Warp) annos[a];
+                    }
+                }
+            }
+            if (warpAnnotation != null) {
+                setResult(local, emitWarpParam(param.getKind(), warpAnnotation));
+            } else {
+                setResult(local, emitLoadParam(param.getKind(), param, null));
+            }
         }
     }
 
+    public Variable emitWarpParam(Kind kind, Warp annotation) {
+        Variable result = newVariable(kind);
+        Variable tid = newVariable(Kind.Char);
+
+        switch (annotation.dimension()) {
+            case X:
+                tid.setName("%tid.x");
+                break;
+            case Y:
+                tid.setName("%tid.y");
+                break;
+            case Z:
+                tid.setName("%tid.y");
+                break;
+        }
+        emitMove(result, tid);
+
+        return result;
+    }
+
     @Override
     public Variable emitMove(Value input) {
         Variable result = newVariable(input.getKind());
@@ -156,37 +213,45 @@
     public PTXAddressValue emitAddress(Value base, long displacement, Value index, int scale) {
         AllocatableValue baseRegister;
         long finalDisp = displacement;
+
         if (isConstant(base)) {
             if (asConstant(base).isNull()) {
                 baseRegister = Value.ILLEGAL;
-            } else if (asConstant(base).getKind() != Kind.Object) {
+            } else if (asConstant(base).getKind() != Kind.Object && !runtime.needsDataPatch(asConstant(base))) {
                 finalDisp += asConstant(base).asLong();
                 baseRegister = Value.ILLEGAL;
             } else {
                 baseRegister = load(base);
             }
+        } else if (base.equals(Value.ILLEGAL)) {
+            baseRegister = Value.ILLEGAL;
         } else {
             baseRegister = asAllocatable(base);
         }
 
-        if (index != Value.ILLEGAL && scale != 0) {
+        if (!index.equals(Value.ILLEGAL)) {
             if (isConstant(index)) {
                 finalDisp += asConstant(index).asLong() * scale;
             } else {
+                Value convertedIndex;
                 Value indexRegister;
+
+                convertedIndex = emitConvert(Op.I2L, index);
                 if (scale != 1) {
-                    indexRegister = emitMul(index, Constant.forInt(scale));
+                    if (CodeUtil.isPowerOf2(scale)) {
+                        indexRegister = emitShl(convertedIndex, Constant.forInt(CodeUtil.log2(scale)));
+                    } else {
+                        indexRegister = emitMul(convertedIndex, Constant.forInt(scale));
+                    }
                 } else {
-                    indexRegister = index;
+                    indexRegister = convertedIndex;
                 }
-
-                if (baseRegister == Value.ILLEGAL) {
+                if (baseRegister.equals(Value.ILLEGAL)) {
                     baseRegister = asAllocatable(indexRegister);
                 } else {
-                    Variable newBase = newVariable(Kind.Int);
-                    emitMove(newBase, baseRegister);
-                    baseRegister = newBase;
-                    baseRegister = emitAdd(baseRegister, indexRegister);
+                    Variable longBaseRegister = newVariable(Kind.Long);
+                    emitMove(longBaseRegister, baseRegister);
+                    baseRegister = emitAdd(longBaseRegister, indexRegister);
                 }
             }
         }
@@ -195,6 +260,8 @@
     }
 
     private PTXAddressValue asAddress(Value address) {
+        assert address != null;
+
         if (address instanceof PTXAddressValue) {
             return (PTXAddressValue) address;
         } else {
@@ -219,7 +286,7 @@
 
     @Override
     public Variable emitAddress(StackSlot address) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented("PTXLIRGenerator.emitAddress()");
     }
 
     @Override
@@ -231,24 +298,24 @@
     public void emitCompareBranch(Value left, Value right, Condition cond, boolean unorderedIsTrue, LabelRef label) {
         switch (left.getKind().getStackKind()) {
             case Int:
-                append(new CompareOp(ICMP, cond, left, right));
-                append(new BranchOp(cond, label));
+                append(new CompareOp(ICMP, cond, left, right, nextPredRegNum));
+                append(new BranchOp(cond, label, nextPredRegNum++));
                 break;
             case Long:
-                append(new CompareOp(LCMP, cond, left, right));
-                append(new BranchOp(cond, label));
+                append(new CompareOp(LCMP, cond, left, right, nextPredRegNum));
+                append(new BranchOp(cond, label, nextPredRegNum++));
                 break;
             case Float:
-                append(new CompareOp(FCMP, cond, left, right));
-                append(new BranchOp(cond, label));
+                append(new CompareOp(FCMP, cond, left, right, nextPredRegNum));
+                append(new BranchOp(cond, label, nextPredRegNum++));
                 break;
             case Double:
-                append(new CompareOp(DCMP, cond, left, right));
-                append(new BranchOp(cond, label));
+                append(new CompareOp(DCMP, cond, left, right, nextPredRegNum));
+                append(new BranchOp(cond, label, nextPredRegNum++));
                 break;
             case Object:
-                append(new CompareOp(ACMP, cond, left, right));
-                append(new BranchOp(cond, label));
+                append(new CompareOp(ACMP, cond, left, right, nextPredRegNum));
+                append(new BranchOp(cond, label, nextPredRegNum++));
                 break;
             default:
                 throw GraalInternalError.shouldNotReachHere("" + left.getKind());
@@ -257,79 +324,22 @@
 
     @Override
     public void emitOverflowCheckBranch(LabelRef label, boolean negated) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented("PTXLIRGenerator.emitOverflowCheckBranch()");
     }
 
     @Override
     public void emitIntegerTestBranch(Value left, Value right, boolean negated, LabelRef label) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented("PTXLIRGenerator.emitIntegerTestBranch()");
     }
 
     @Override
     public Variable emitConditionalMove(Value left, Value right, Condition cond, boolean unorderedIsTrue, Value trueValue, Value falseValue) {
-        boolean mirrored = emitCompare(cond, left, right);
-        Condition finalCondition = mirrored ? cond.mirror() : cond;
-
-        Variable result = newVariable(trueValue.getKind());
-        switch (left.getKind().getStackKind()) {
-            case Int:
-            case Long:
-            case Object:
-                append(new CondMoveOp(result, finalCondition, load(trueValue), loadNonConst(falseValue)));
-                break;
-            case Float:
-            case Double:
-                append(new FloatCondMoveOp(result, finalCondition, unorderedIsTrue, load(trueValue), load(falseValue)));
-                break;
-            default:
-                throw GraalInternalError.shouldNotReachHere("missing: " + left.getKind());
-        }
-        return result;
+        // TODO: There is no conventional conditional move instruction in PTX.
+        // So, this method is changed to throw NYI exception.
+        // To be revisited if this needs to be really implemented.
+        throw GraalInternalError.unimplemented("PTXLIRGenerator.emitConditionalMove()");
     }
 
-    /**
-     * This method emits the compare instruction, and may reorder the operands. It returns true if
-     * it did so.
-     *
-     *
-     * @param a the left operand of the comparison
-     * @param b the right operand of the comparison
-     * @return true if the left and right operands were switched, false otherwise
-     */
-    private boolean emitCompare(Condition cond, Value a, Value b) {
-        Variable left;
-        Value right;
-        boolean mirrored;
-        if (LIRValueUtil.isVariable(b)) {
-            left = load(b);
-            right = loadNonConst(a);
-            mirrored = true;
-        } else {
-            left = load(a);
-            right = loadNonConst(b);
-            mirrored = false;
-        }
-        switch (left.getKind().getStackKind()) {
-            case Int:
-                append(new CompareOp(ICMP, cond, left, right));
-                break;
-            case Long:
-                append(new CompareOp(LCMP, cond, left, right));
-                break;
-            case Object:
-                append(new CompareOp(ACMP, cond, left, right));
-                break;
-            case Float:
-                append(new CompareOp(FCMP, cond, left, right));
-                break;
-            case Double:
-                append(new CompareOp(DCMP, cond, left, right));
-                break;
-            default:
-                throw GraalInternalError.shouldNotReachHere();
-        }
-        return mirrored;
-    }
 
     @Override
     public Variable emitIntegerTestMove(Value left, Value right, Value trueValue, Value falseValue) {
@@ -483,12 +493,12 @@
 
     @Override
     public Variable emitUDiv(Value a, Value b, DeoptimizingNode deopting) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented("PTXLIRGenerator.emitUDiv()");
     }
 
     @Override
     public Variable emitURem(Value a, Value b, DeoptimizingNode deopting) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented("PTXLIRGenerator.emitURem()");
     }
 
     @Override
@@ -548,7 +558,7 @@
                 append(new Op2Stack(ISHL, result, a, loadNonConst(b)));
                 break;
             case Long:
-                append(new Op1Stack(LSHL, result, loadNonConst(b)));
+                append(new Op2Stack(LSHL, result, a, loadNonConst(b)));
                 break;
             default:
                 throw GraalInternalError.shouldNotReachHere();
@@ -564,7 +574,7 @@
                 append(new Op2Stack(ISHR, result, a, loadNonConst(b)));
                 break;
             case Long:
-                append(new Op1Stack(LSHR, result, loadNonConst(b)));
+                append(new Op2Stack(LSHR, result, a, loadNonConst(b)));
                 break;
             default:
                 throw GraalInternalError.shouldNotReachHere();
@@ -663,28 +673,28 @@
     }
 
     @Override
-    public void emitDeoptimize(DeoptimizationAction action, DeoptimizingNode deopting) {
+    public void emitDeoptimize(Value actionAndReason, DeoptimizingNode deopting) {
         append(new ReturnOp(Value.ILLEGAL));
     }
 
     @Override
     public void emitMembar(int barriers) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented("PTXLIRGenerator.emitMembar()");
     }
 
     @Override
     protected void emitDirectCall(DirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented("PTXLIRGenerator.emitDirectCall()");
     }
 
     @Override
     protected void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented("PTXLIRGenerator.emitIndirectCall()");
     }
 
     @Override
     protected void emitForeignCall(ForeignCallLinkage callTarget, Value result, Value[] arguments, Value[] temps, LIRFrameState info) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented("PTXLIRGenerator.emitForeignCall()");
     }
 
     @Override
@@ -698,47 +708,47 @@
 
     @Override
     public void emitBitScanForward(Variable result, Value value) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented("PTXLIRGenerator.emitBitScanForward()");
     }
 
     @Override
     public void emitBitScanReverse(Variable result, Value value) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented("PTXLIRGenerator.emitBitScanReverse()");
     }
 
     @Override
     public Value emitMathAbs(Value input) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented("PTXLIRGenerator.emitMathAbs()");
     }
 
     @Override
     public Value emitMathSqrt(Value input) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented("PTXLIRGenerator.emitMathSqrt()");
     }
 
     @Override
     public Value emitMathLog(Value input, boolean base10) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented("PTXLIRGenerator.emitMathLog()");
     }
 
     @Override
     public Value emitMathCos(Value input) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented("PTXLIRGenerator.emitMathCos()");
     }
 
     @Override
     public Value emitMathSin(Value input) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented("PTXLIRGenerator.emitMathSin()");
     }
 
     @Override
     public Value emitMathTan(Value input) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented("PTXLIRGenerator.emitMathTan()");
     }
 
     @Override
     public void emitByteSwap(Variable result, Value input) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented("PTXLIRGenerator.emitByteSwap()");
     }
 
     @Override
@@ -755,10 +765,10 @@
         // Making a copy of the switch value is necessary because jump table destroys the input
         // value
         if (key.getKind() == Kind.Int || key.getKind() == Kind.Long) {
-            append(new SequentialSwitchOp(keyConstants, keyTargets, defaultTarget, key, Value.ILLEGAL));
+            append(new SequentialSwitchOp(keyConstants, keyTargets, defaultTarget, key, Value.ILLEGAL, nextPredRegNum));
         } else {
             assert key.getKind() == Kind.Object : key.getKind();
-            append(new SequentialSwitchOp(keyConstants, keyTargets, defaultTarget, key, newVariable(Kind.Object)));
+            append(new SequentialSwitchOp(keyConstants, keyTargets, defaultTarget, key, newVariable(Kind.Object), nextPredRegNum));
         }
     }
 
@@ -772,39 +782,39 @@
         // Making a copy of the switch value is necessary because jump table destroys the input
         // value
         Variable tmp = emitMove(key);
-        append(new TableSwitchOp(lowKey, defaultTarget, targets, tmp, newVariable(target.wordKind)));
+        append(new TableSwitchOp(lowKey, defaultTarget, targets, tmp, newVariable(target.wordKind), nextPredRegNum++));
     }
 
     @Override
     public void visitCompareAndSwap(LoweredCompareAndSwapNode node, Value address) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented("PTXLIRGenerator.visitCompareAndSwap()");
     }
 
     @Override
     public void visitBreakpointNode(BreakpointNode node) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented("PTXLIRGenerator.visitBreakpointNode()");
     }
 
     @Override
     public void visitSafepointNode(SafepointNode i) {
-        // LIRFrameState info = state();
+        // LIRFrameState info = state(i);
         // append(new PTXSafepointOp(info, runtime().config, this));
-        throw new InternalError("NYI");
+        Debug.log("visitSafePointNode unimplemented");
     }
 
     @Override
     public void emitUnwind(Value operand) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented("PTXLIRGenerator.emitUnwind()");
     }
 
     @Override
     public void emitNullCheck(ValueNode v, DeoptimizingNode deopting) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented("PTXLIRGenerator.emitNullCheck()");
     }
 
     @Override
     public void visitInfopointNode(InfopointNode i) {
-        throw new InternalError("NYI");
+        throw GraalInternalError.unimplemented("PTXLIRGenerator.visitInfopointNode()");
     }
 
     public Variable emitLoadParam(Kind kind, Value address, DeoptimizingNode deopting) {
@@ -827,6 +837,13 @@
         append(new StoreReturnValOp(kind, storeAddress, input, deopting != null ? state(deopting) : null));
     }
 
+    @Override
+    public AllocatableValue resultOperandFor(Kind kind) {
+        if (kind == Kind.Void) {
+            return ILLEGAL;
+        }
+        return (new Variable(kind, 0));
+    }
 
     @Override
     public void visitReturn(ReturnNode x) {
--- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXTargetMethodAssembler.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXTargetMethodAssembler.java	Wed Oct 02 13:26:31 2013 +0200
@@ -36,6 +36,12 @@
     private static CompilerToGPU toGPU = HotSpotGraalRuntime.graalRuntime().getCompilerToGPU();
     private static boolean validDevice = toGPU.deviceInit();
 
+    private static final int totalProcessors = (validDevice ? toGPU.availableProcessors() : 0);
+
+    public static int getAvailableProcessors() {
+        return totalProcessors;
+    }
+
     // detach ??
 
     public PTXTargetMethodAssembler(TargetDescription target, CodeCacheProvider runtime, FrameMap frameMap,
--- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java	Wed Oct 02 13:26:31 2013 +0200
@@ -837,7 +837,7 @@
     }
 
     @Override
-    public void emitDeoptimize(DeoptimizationAction action, DeoptimizingNode deopting) {
+    public void emitDeoptimize(Value actionAndReason, DeoptimizingNode deopting) {
         append(new ReturnOp(Value.ILLEGAL));
     }
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/BoxingEliminationTest.java	Wed Oct 02 13:26:31 2013 +0200
@@ -300,16 +300,16 @@
 
     final ValueNode getResult(String snippet) {
         processMethod(snippet);
-        assertEquals(1, graph.getNodes(ReturnNode.class).count());
-        return graph.getNodes(ReturnNode.class).first().result();
+        assertEquals(1, graph.getNodes().filter(ReturnNode.class).count());
+        return graph.getNodes().filter(ReturnNode.class).first().result();
     }
 
     private void processMethod(final String snippet) {
         graph = parse(snippet);
         Assumptions assumptions = new Assumptions(false);
         HighTierContext context = new HighTierContext(runtime(), assumptions, replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL);
-        new InliningPhase().apply(graph, context);
-        new PartialEscapePhase(false).apply(graph, context);
+        new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
+        new PartialEscapePhase(false, new CanonicalizerPhase(true)).apply(graph, context);
     }
 
     private void compareGraphs(final String snippet, final String referenceSnippet) {
@@ -326,19 +326,19 @@
                 Assumptions assumptions = new Assumptions(false);
                 HighTierContext context = new HighTierContext(runtime(), assumptions, replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL);
                 CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true);
-                new InliningPhase().apply(graph, context);
+                new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
                 if (loopPeeling) {
                     new LoopTransformHighPhase().apply(graph);
                 }
                 new DeadCodeEliminationPhase().apply(graph);
                 canonicalizer.apply(graph, context);
-                new PartialEscapePhase(false).apply(graph, context);
+                new PartialEscapePhase(false, canonicalizer).apply(graph, context);
 
                 new DeadCodeEliminationPhase().apply(graph);
                 canonicalizer.apply(graph, context);
 
                 StructuredGraph referenceGraph = parse(referenceSnippet);
-                new InliningPhase().apply(referenceGraph, context);
+                new InliningPhase(new CanonicalizerPhase(true)).apply(referenceGraph, context);
                 new DeadCodeEliminationPhase().apply(referenceGraph);
                 new CanonicalizerPhase(true).apply(referenceGraph, context);
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CompareCanonicalizerTest.java	Wed Oct 02 13:26:31 2013 +0200
@@ -30,12 +30,13 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
 
 public class CompareCanonicalizerTest extends GraalCompilerTest {
 
     private StructuredGraph getCanonicalizedGraph(String name) {
         StructuredGraph graph = parse(name);
-        new CanonicalizerPhase.Instance(runtime(), null, true).apply(graph);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), null, replacements));
         return graph;
     }
 
@@ -53,7 +54,7 @@
             assertEquals(referenceGraph, graph);
         }
         Assumptions assumptions = new Assumptions(false);
-        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(referenceGraph);
+        new CanonicalizerPhase(true).apply(referenceGraph, new PhaseContext(runtime(), assumptions, replacements));
         for (int i = 1; i < 4; i++) {
             StructuredGraph graph = getCanonicalizedGraph("canonicalCompare" + i);
             assertEquals(referenceGraph, graph);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionTest.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionTest.java	Wed Oct 02 13:26:31 2013 +0200
@@ -45,7 +45,7 @@
                         Constant b = Constant.forInt(i < 100 ? a.asInt() : rand.nextInt());
                         boolean result1 = c1.foldCondition(a, b, null, false);
                         boolean result2 = c2.foldCondition(a, b, null, false);
-                        if (result1 && implies) {
+                        if (result1) {
                             assertTrue(result2);
                         }
                     }
@@ -60,7 +60,7 @@
         for (Condition c1 : Condition.values()) {
             for (Condition c2 : Condition.values()) {
                 Condition join = c1.join(c2);
-                assertTrue(join == c2.join(c1));
+                assertEquals(join, c2.join(c1));
                 if (join != null) {
                     for (int i = 0; i < 1000; i++) {
                         Constant a = Constant.forInt(rand.nextInt());
@@ -70,6 +70,8 @@
                         boolean resultJoin = join.foldCondition(a, b, null, false);
                         if (result1 && result2) {
                             assertTrue(resultJoin);
+                        } else {
+                            assertFalse(resultJoin);
                         }
                     }
                 }
@@ -83,7 +85,7 @@
         for (Condition c1 : Condition.values()) {
             for (Condition c2 : Condition.values()) {
                 Condition meet = c1.meet(c2);
-                assertTrue(meet == c2.meet(c1));
+                assertEquals(meet, c2.meet(c1));
                 if (meet != null) {
                     for (int i = 0; i < 1000; i++) {
                         Constant a = Constant.forInt(rand.nextInt());
@@ -93,6 +95,8 @@
                         boolean resultMeet = meet.foldCondition(a, b, null, false);
                         if (result1 || result2) {
                             assertTrue(resultMeet);
+                        } else {
+                            assertFalse(resultMeet);
                         }
                     }
                 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ConditionalEliminationTest.java	Wed Oct 02 13:26:31 2013 +0200
@@ -32,6 +32,7 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.nodes.java.MethodCallTargetNode.InvokeKind;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
 
 /**
  * Collection of tests for {@link ConditionalEliminationPhase} including those that triggered bugs
@@ -141,7 +142,7 @@
 
         StructuredGraph graph = parse("testNullnessSnippet");
         new ConditionalEliminationPhase(runtime()).apply(graph);
-        new CanonicalizerPhase.Instance(runtime(), null, true).apply(graph);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), null, replacements));
         for (ConstantNode constant : graph.getNodes().filter(ConstantNode.class)) {
             assertTrue("unexpected constant: " + constant, constant.asConstant().isNull() || constant.asConstant().asInt() > 0);
         }
@@ -163,7 +164,7 @@
     @Test
     public void testDisjunction() {
         StructuredGraph graph = parse("testDisjunctionSnippet");
-        new CanonicalizerPhase.Instance(runtime(), null, true).apply(graph);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), null, replacements));
         IfNode ifNode = (IfNode) graph.start().next();
         InstanceOfNode instanceOf = (InstanceOfNode) ifNode.condition();
         IsNullNode x = graph.unique(new IsNullNode(graph.getLocal(0)));
@@ -171,9 +172,9 @@
         ShortCircuitOrNode disjunction = graph.unique(new ShortCircuitOrNode(x, false, y, false, NOT_FREQUENT_PROBABILITY));
         LogicNegationNode negation = graph.unique(new LogicNegationNode(disjunction));
         ifNode.setCondition(negation);
-        new CanonicalizerPhase.Instance(runtime(), null, true).apply(graph);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), null, replacements));
         new ConditionalEliminationPhase(runtime()).apply(graph);
-        new CanonicalizerPhase.Instance(runtime(), null, true).apply(graph);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), null, replacements));
         for (ConstantNode constant : graph.getNodes().filter(ConstantNode.class)) {
             assertTrue("unexpected constant: " + constant, constant.asConstant().isNull() || constant.asConstant().asInt() > 0);
         }
@@ -191,10 +192,10 @@
     public void testInvoke() {
         test("testInvokeSnippet", new Integer(16));
         StructuredGraph graph = parse("testInvokeSnippet");
-        new CanonicalizerPhase.Instance(runtime(), null, true).apply(graph);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), null, replacements));
         new ConditionalEliminationPhase(runtime()).apply(graph);
 
-        InvokeNode invoke = graph.getNodes(InvokeNode.class).first();
+        InvokeNode invoke = graph.getNodes().filter(InvokeNode.class).first();
         assertEquals(InvokeKind.Special, ((MethodCallTargetNode) invoke.callTarget()).invokeKind());
     }
 
@@ -221,11 +222,43 @@
     @Test
     public void testTypeMerging() {
         StructuredGraph graph = parse("testTypeMergingSnippet");
-        new CanonicalizerPhase.Instance(runtime(), null, true).apply(graph);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), null, replacements));
         new ConditionalEliminationPhase(runtime()).apply(graph);
-        new CanonicalizerPhase.Instance(runtime(), null, true).apply(graph);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), null, replacements));
 
         assertEquals(0, graph.getNodes().filter(StoreFieldNode.class).count());
     }
 
+    public static String testInstanceOfCheckCastSnippet(Object e) {
+        if (e instanceof Entry) {
+            return ((Entry) e).name;
+        }
+        return null;
+    }
+
+    @Test
+    public void testInstanceOfCheckCast() {
+        StructuredGraph graph = parse("testInstanceOfCheckCastSnippet");
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), null, replacements));
+        new ConditionalEliminationPhase(runtime()).apply(graph);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), null, replacements));
+
+        assertEquals(0, graph.getNodes().filter(CheckCastNode.class).count());
+    }
+
+    @Test
+    @Ignore
+    public void testInstanceOfCheckCastLowered() {
+        StructuredGraph graph = parse("testInstanceOfCheckCastSnippet");
+
+        CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true);
+        PhaseContext context = new PhaseContext(runtime(), null, replacements);
+
+        new LoweringPhase(canonicalizer).apply(graph, context);
+        canonicalizer.apply(graph, context);
+        new ConditionalEliminationPhase(runtime()).apply(graph);
+        canonicalizer.apply(graph, context);
+
+        assertEquals(0, graph.getNodes().filter(GuardNode.class).count());
+    }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/DegeneratedLoopsTest.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/DegeneratedLoopsTest.java	Wed Oct 02 13:26:31 2013 +0200
@@ -83,7 +83,7 @@
             public void run() {
                 StructuredGraph graph = parse(snippet);
                 HighTierContext context = new HighTierContext(runtime(), new Assumptions(false), replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL);
-                new InliningPhase().apply(graph, context);
+                new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
                 new CanonicalizerPhase(true).apply(graph, context);
                 Debug.dump(graph, "Graph");
                 StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/EliminateNestedCheckCastsTest.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/EliminateNestedCheckCastsTest.java	Wed Oct 02 13:26:31 2013 +0200
@@ -31,6 +31,7 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
 
 public class EliminateNestedCheckCastsTest extends GraalCompilerTest {
 
@@ -113,8 +114,8 @@
             public StructuredGraph call() throws Exception {
                 Debug.dump(graph, "After parsing: " + snippet);
                 Assert.assertEquals(checkcasts, graph.getNodes().filter(CheckCastNode.class).count());
-                new CanonicalizerPhase.Instance(runtime(), new Assumptions(false), true).apply(graph);
-                Assert.assertEquals(afterCanon, graph.getNodes(CheckCastNode.class).count());
+                new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), new Assumptions(false), replacements));
+                Assert.assertEquals(afterCanon, graph.getNodes().filter(CheckCastNode.class).count());
                 return graph;
             }
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FinalizableSubclassTest.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FinalizableSubclassTest.java	Wed Oct 02 13:26:31 2013 +0200
@@ -69,7 +69,7 @@
         GraphBuilderConfiguration conf = GraphBuilderConfiguration.getSnippetDefault();
         new GraphBuilderPhase(runtime, conf, OptimisticOptimizations.ALL).apply(graph);
         HighTierContext context = new HighTierContext(runtime(), assumptions, replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL);
-        new InliningPhase().apply(graph, context);
+        new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
         new CanonicalizerPhase(true).apply(graph, context);
         return graph;
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatingReadTest.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/FloatingReadTest.java	Wed Oct 02 13:26:31 2013 +0200
@@ -29,7 +29,6 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.spi.Lowerable.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
 
@@ -60,7 +59,7 @@
             public void run() {
                 StructuredGraph graph = parse(snippet);
                 PhaseContext context = new PhaseContext(runtime(), new Assumptions(false), replacements);
-                new LoweringPhase(LoweringType.BEFORE_GUARDS).apply(graph, context);
+                new LoweringPhase(new CanonicalizerPhase(true)).apply(graph, context);
                 new FloatingReadPhase().apply(graph);
 
                 ReturnNode returnNode = null;
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Wed Oct 02 13:26:31 2013 +0200
@@ -25,9 +25,11 @@
 import static com.oracle.graal.api.code.CodeUtil.*;
 import static com.oracle.graal.phases.GraalOptions.*;
 
+import java.io.*;
 import java.lang.reflect.*;
 import java.util.*;
 import java.util.concurrent.*;
+import java.util.concurrent.atomic.*;
 
 import org.junit.*;
 import org.junit.internal.*;
@@ -87,7 +89,7 @@
     }
 
     @BeforeClass
-    public static void initializeDebgging() {
+    public static void initializeDebugging() {
         DebugEnvironment.initialize(System.out);
     }
 
@@ -114,8 +116,8 @@
 
     protected void assertConstantReturn(StructuredGraph graph, int value) {
         String graphString = getCanonicalGraphString(graph, false);
-        Assert.assertEquals("unexpected number of ReturnNodes: " + graphString, graph.getNodes(ReturnNode.class).count(), 1);
-        ValueNode result = graph.getNodes(ReturnNode.class).first().result();
+        Assert.assertEquals("unexpected number of ReturnNodes: " + graphString, graph.getNodes().filter(ReturnNode.class).count(), 1);
+        ValueNode result = graph.getNodes().filter(ReturnNode.class).first().result();
         Assert.assertTrue("unexpected ReturnNode result node: " + graphString, result.isConstant());
         Assert.assertEquals("unexpected ReturnNode result kind: " + graphString, result.asConstant().getKind(), Kind.Int);
         Assert.assertEquals("unexpected ReturnNode result: " + graphString, result.asConstant().asInt(), value);
@@ -169,7 +171,7 @@
         return parse(getMethod(methodName));
     }
 
-    private static int compilationId = 0;
+    private static AtomicInteger compilationId = new AtomicInteger();
 
     /**
      * Compares two given objects for {@linkplain Assert#assertEquals(Object, Object) equality}.
@@ -206,11 +208,45 @@
         }
     }
 
+    @SuppressWarnings("serial")
+    public static class MultiCauseAssertionError extends AssertionError {
+
+        private Throwable[] causes;
+
+        public MultiCauseAssertionError(String message, Throwable... causes) {
+            super(message);
+            this.causes = causes;
+        }
+
+        @Override
+        public void printStackTrace(PrintStream out) {
+            super.printStackTrace(out);
+            int num = 0;
+            for (Throwable cause : causes) {
+                if (cause != null) {
+                    out.print("cause " + (num++));
+                    cause.printStackTrace(out);
+                }
+            }
+        }
+
+        @Override
+        public void printStackTrace(PrintWriter out) {
+            super.printStackTrace(out);
+            int num = 0;
+            for (Throwable cause : causes) {
+                if (cause != null) {
+                    out.print("cause " + (num++) + ": ");
+                    cause.printStackTrace(out);
+                }
+            }
+        }
+    }
+
     protected void testN(int n, final String name, final Object... args) {
-        final Throwable[] errors = new Throwable[n];
+        final List<Throwable> errors = new ArrayList<>(n);
         Thread[] threads = new Thread[n];
         for (int i = 0; i < n; i++) {
-            final int idx = i;
             Thread t = new Thread(i + ":" + name) {
 
                 @Override
@@ -218,26 +254,23 @@
                     try {
                         test(name, args);
                     } catch (Throwable e) {
-                        errors[idx] = e;
+                        errors.add(e);
                     }
                 }
             };
             threads[i] = t;
             t.start();
         }
-        int failed = 0;
         for (int i = 0; i < n; i++) {
             try {
                 threads[i].join();
             } catch (InterruptedException e) {
-                errors[i] = e;
-            }
-            if (errors[i] != null) {
-                errors[i].printStackTrace();
-                failed++;
+                errors.add(e);
             }
         }
-        Assert.assertTrue(failed + " of " + n + " failed", failed == 0);
+        if (!errors.isEmpty()) {
+            throw new MultiCauseAssertionError(errors.size() + " failures", errors.toArray(new Throwable[errors.size()]));
+        }
     }
 
     protected Object referenceInvoke(Method method, Object receiver, Object... args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
@@ -421,7 +454,7 @@
             }
         }
 
-        final int id = compilationId++;
+        final int id = compilationId.incrementAndGet();
 
         InstalledCode installedCode = Debug.scope("Compiling", new Object[]{runtime, new DebugDumpScope(String.valueOf(id), true)}, new Callable<InstalledCode>() {
 
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfCanonicalizerTest.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/IfCanonicalizerTest.java	Wed Oct 02 13:26:31 2013 +0200
@@ -31,6 +31,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
 
 /**
  * In the following tests, the usages of local variable "a" are replaced with the integer constant
@@ -144,7 +145,7 @@
             n.replaceFirstInput(local, constant);
         }
         Debug.dump(graph, "Graph");
-        new CanonicalizerPhase.Instance(runtime(), new Assumptions(false), true).apply(graph);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), new Assumptions(false), replacements));
         for (FrameState fs : local.usages().filter(FrameState.class).snapshot()) {
             fs.replaceFirstInput(local, null);
         }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InfopointReasonTest.java	Wed Oct 02 13:26:31 2013 +0200
@@ -74,7 +74,7 @@
         final Method method = getMethod("testMethod");
         final StructuredGraph graph = parseDebug(method);
         int graphLineSPs = 0;
-        for (InfopointNode ipn : graph.getNodes(InfopointNode.class)) {
+        for (InfopointNode ipn : graph.getNodes().filter(InfopointNode.class)) {
             if (ipn.reason == InfopointReason.LINE_NUMBER) {
                 ++graphLineSPs;
             }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeExceptionTest.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeExceptionTest.java	Wed Oct 02 13:26:31 2013 +0200
@@ -67,7 +67,7 @@
         }
         Assumptions assumptions = new Assumptions(false);
         HighTierContext context = new HighTierContext(runtime(), assumptions, replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL);
-        new InliningPhase(hints).apply(graph, context);
+        new InliningPhase(hints, new CanonicalizerPhase(true)).apply(graph, context);
         new CanonicalizerPhase(true).apply(graph, context);
         new DeadCodeEliminationPhase().apply(graph);
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeHintsTest.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/InvokeHintsTest.java	Wed Oct 02 13:26:31 2013 +0200
@@ -78,7 +78,7 @@
 
         Assumptions assumptions = new Assumptions(false);
         HighTierContext context = new HighTierContext(runtime(), assumptions, replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL);
-        new InliningPhase(hints).apply(graph, context);
+        new InliningPhase(hints, new CanonicalizerPhase(true)).apply(graph, context);
         new CanonicalizerPhase(true).apply(graph, context);
         new DeadCodeEliminationPhase().apply(graph);
         StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LockEliminationTest.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LockEliminationTest.java	Wed Oct 02 13:26:31 2013 +0200
@@ -29,7 +29,6 @@
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.java.*;
-import com.oracle.graal.nodes.spi.Lowerable.LoweringType;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
@@ -62,7 +61,7 @@
         test("testSynchronizedSnippet", new A(), new A());
 
         StructuredGraph graph = getGraph("testSynchronizedSnippet");
-        new CanonicalizerPhase.Instance(runtime(), null, true).apply(graph);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), null, replacements));
         new LockEliminationPhase().apply(graph);
         assertEquals(1, graph.getNodes().filter(MonitorEnterNode.class).count());
         assertEquals(1, graph.getNodes().filter(MonitorExitNode.class).count());
@@ -80,7 +79,7 @@
         test("testSynchronizedMethodSnippet", new A());
 
         StructuredGraph graph = getGraph("testSynchronizedMethodSnippet");
-        new CanonicalizerPhase.Instance(runtime(), null, true).apply(graph);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), null, replacements));
         new LockEliminationPhase().apply(graph);
         assertEquals(1, graph.getNodes().filter(MonitorEnterNode.class).count());
         assertEquals(1, graph.getNodes().filter(MonitorExitNode.class).count());
@@ -93,10 +92,10 @@
         Assumptions assumptions = new Assumptions(true);
         HighTierContext context = new HighTierContext(runtime(), assumptions, replacements, null, phasePlan, OptimisticOptimizations.ALL);
         new CanonicalizerPhase(true).apply(graph, context);
-        new InliningPhase().apply(graph, context);
+        new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
         new CanonicalizerPhase(true).apply(graph, context);
         new DeadCodeEliminationPhase().apply(graph);
-        new LoweringPhase(LoweringType.BEFORE_GUARDS).apply(graph, context);
+        new LoweringPhase(new CanonicalizerPhase(true)).apply(graph, context);
         new ValueAnchorCleanupPhase().apply(graph);
         new LockEliminationPhase().apply(graph);
         return graph;
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LoopUnswitchTest.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/LoopUnswitchTest.java	Wed Oct 02 13:26:31 2013 +0200
@@ -30,6 +30,7 @@
 import com.oracle.graal.loop.phases.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
 
 public class LoopUnswitchTest extends GraalCompilerTest {
 
@@ -133,8 +134,8 @@
         }
 
         Assumptions assumptions = new Assumptions(false);
-        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph);
-        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(referenceGraph);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), assumptions, replacements));
+        new CanonicalizerPhase(true).apply(referenceGraph, new PhaseContext(runtime(), assumptions, replacements));
         Debug.scope("Test", new DebugDumpScope("Test:" + snippet), new Runnable() {
 
             @Override
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java	Wed Oct 02 13:26:31 2013 +0200
@@ -36,7 +36,6 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.spi.Lowerable.LoweringType;
 import com.oracle.graal.nodes.util.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
@@ -222,7 +221,7 @@
     public void testArrayCopy() {
         SchedulePhase schedule = getFinalSchedule("testArrayCopySnippet", TestMode.INLINED_WITHOUT_FRAMESTATES, MemoryScheduling.OPTIMAL);
         StructuredGraph graph = schedule.getCFG().getStartBlock().getBeginNode().graph();
-        ReturnNode ret = graph.getNodes(ReturnNode.class).first();
+        ReturnNode ret = graph.getNodes().filter(ReturnNode.class).first();
         assertTrue(ret.result() instanceof FloatingReadNode);
         assertEquals(schedule.getCFG().blockFor(ret), schedule.getCFG().blockFor(ret.result()));
         assertReadWithinReturnBlock(schedule, true);
@@ -502,9 +501,9 @@
                 HighTierContext context = new HighTierContext(runtime(), assumptions, replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL);
                 new CanonicalizerPhase(true).apply(graph, context);
                 if (mode == TestMode.INLINED_WITHOUT_FRAMESTATES) {
-                    new InliningPhase().apply(graph, context);
+                    new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
                 }
-                new LoweringPhase(LoweringType.BEFORE_GUARDS).apply(graph, context);
+                new LoweringPhase(new CanonicalizerPhase(true)).apply(graph, context);
                 if (mode == TestMode.WITHOUT_FRAMESTATES || mode == TestMode.INLINED_WITHOUT_FRAMESTATES) {
                     for (Node node : graph.getNodes()) {
                         if (node instanceof StateSplit) {
@@ -523,8 +522,8 @@
 
                 MidTierContext midContext = new MidTierContext(runtime(), assumptions, replacements, runtime().getTarget(), OptimisticOptimizations.ALL);
                 new GuardLoweringPhase().apply(graph, midContext);
-                new LoweringPhase(LoweringType.AFTER_GUARDS).apply(graph, midContext);
-                new LoweringPhase(LoweringType.AFTER_FSA).apply(graph, midContext);
+                new LoweringPhase(new CanonicalizerPhase(true)).apply(graph, midContext);
+                new LoweringPhase(new CanonicalizerPhase(true)).apply(graph, midContext);
 
                 SchedulePhase schedule = new SchedulePhase(SchedulingStrategy.LATEST_OUT_OF_LOOPS, memsched);
                 schedule.apply(graph);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MonitorGraphTest.java	Wed Oct 02 13:26:31 2013 +0200
@@ -95,7 +95,7 @@
         }
         Assumptions assumptions = new Assumptions(false);
         HighTierContext context = new HighTierContext(runtime(), assumptions, replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL);
-        new InliningPhase(hints).apply(graph, context);
+        new InliningPhase(hints, new CanonicalizerPhase(true)).apply(graph, context);
         new CanonicalizerPhase(true).apply(graph, context);
         new DeadCodeEliminationPhase().apply(graph);
         return graph;
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/PushNodesThroughPiTest.java	Wed Oct 02 13:26:31 2013 +0200
@@ -30,7 +30,6 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.spi.Lowerable.LoweringType;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
@@ -94,7 +93,7 @@
         StructuredGraph graph = parse(snippet);
         PhaseContext context = new PhaseContext(runtime(), new Assumptions(false), replacements);
         CanonicalizerPhase canonicalizer = new CanonicalizerPhase(true);
-        new LoweringPhase(LoweringType.BEFORE_GUARDS).apply(graph, context);
+        new LoweringPhase(canonicalizer).apply(graph, context);
         canonicalizer.apply(graph, context);
         new PushThroughPiPhase().apply(graph);
         canonicalizer.apply(graph, context);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReadAfterCheckCastTest.java	Wed Oct 02 13:26:31 2013 +0200
@@ -29,7 +29,6 @@
 import com.oracle.graal.debug.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.extended.*;
-import com.oracle.graal.nodes.spi.Lowerable.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
 
@@ -85,7 +84,7 @@
             public void run() {
                 StructuredGraph graph = parse(snippet);
                 PhaseContext context = new PhaseContext(runtime(), new Assumptions(false), replacements);
-                new LoweringPhase(LoweringType.BEFORE_GUARDS).apply(graph, context);
+                new LoweringPhase(new CanonicalizerPhase(true)).apply(graph, context);
                 new FloatingReadPhase().apply(graph);
                 new EliminatePartiallyRedundantGuardsPhase(true, false).apply(graph);
                 new ReadEliminationPhase().apply(graph);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReassociateAndCanonicalTest.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ReassociateAndCanonicalTest.java	Wed Oct 02 13:26:31 2013 +0200
@@ -28,6 +28,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
 
 public class ReassociateAndCanonicalTest extends GraalCompilerTest {
 
@@ -241,12 +242,12 @@
         return (2 - rnd) - 1;
     }
 
-    private <T extends Node & Node.IterableNodeType> void test(String test, String ref) {
+    private <T extends Node & IterableNodeType> void test(String test, String ref) {
         StructuredGraph testGraph = parse(test);
         Assumptions assumptions = new Assumptions(false);
-        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(testGraph);
+        new CanonicalizerPhase(true).apply(testGraph, new PhaseContext(runtime(), assumptions, replacements));
         StructuredGraph refGraph = parse(ref);
-        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(refGraph);
+        new CanonicalizerPhase(true).apply(refGraph, new PhaseContext(runtime(), assumptions, replacements));
         assertEquals(testGraph, refGraph);
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ScalarTypeSystemTest.java	Wed Oct 02 13:26:31 2013 +0200
@@ -28,6 +28,7 @@
 import com.oracle.graal.debug.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
 
 /**
  * In the following tests, the scalar type system of the compiler should be complete enough to see
@@ -166,9 +167,9 @@
         StructuredGraph graph = parse(snippet);
         Debug.dump(graph, "Graph");
         Assumptions assumptions = new Assumptions(false);
-        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), assumptions, replacements));
         new ConditionalEliminationPhase(runtime()).apply(graph);
-        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), assumptions, replacements));
         StructuredGraph referenceGraph = parse(referenceSnippet);
         assertEquals(referenceGraph, graph);
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StampCanonicalizerTest.java	Wed Oct 02 13:26:31 2013 +0200
@@ -28,6 +28,7 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.type.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
 
 /**
  * This class tests some specific patterns the stamp system should be able to canonicalize away
@@ -109,7 +110,7 @@
 
     private void testZeroReturn(String methodName) {
         StructuredGraph graph = parse(methodName);
-        new CanonicalizerPhase.Instance(runtime(), new Assumptions(false), true).apply(graph);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), new Assumptions(false), replacements));
         new DeadCodeEliminationPhase().apply(graph);
         assertConstantReturn(graph, 0);
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/StraighteningTest.java	Wed Oct 02 13:26:31 2013 +0200
@@ -28,6 +28,7 @@
 import com.oracle.graal.debug.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
 
 public class StraighteningTest extends GraalCompilerTest {
 
@@ -89,7 +90,7 @@
         // No debug scope to reduce console noise for @Test(expected = ...) tests
         StructuredGraph graph = parse(snippet);
         Debug.dump(graph, "Graph");
-        new CanonicalizerPhase.Instance(runtime(), new Assumptions(false), true).apply(graph);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), new Assumptions(false), replacements));
         StructuredGraph referenceGraph = parse(REFERENCE_SNIPPET);
         assertEquals(referenceGraph, graph);
     }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java	Wed Oct 02 13:26:31 2013 +0200
@@ -35,6 +35,7 @@
 import com.oracle.graal.nodes.java.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.schedule.*;
+import com.oracle.graal.phases.tiers.*;
 
 /**
  * In the following tests, the scalar type system of the compiler should be complete enough to see
@@ -44,7 +45,7 @@
 
     @Test
     public void test1() {
-        test("test1Snippet", CheckCastNode.class);
+        testHelper("test1Snippet", CheckCastNode.class);
     }
 
     public static int test1Snippet(Object a) {
@@ -56,7 +57,7 @@
 
     @Test
     public void test2() {
-        test("test2Snippet", CheckCastNode.class);
+        testHelper("test2Snippet", CheckCastNode.class);
     }
 
     public static int test2Snippet(Object a) {
@@ -161,7 +162,7 @@
 
     @Test
     public void test6() {
-        test("test6Snippet", CheckCastNode.class);
+        testHelper("test6Snippet", CheckCastNode.class);
     }
 
     public static int test6Snippet(int i) throws IOException {
@@ -184,13 +185,13 @@
         StructuredGraph graph = parse(snippet);
         Debug.dump(graph, "Graph");
         Assumptions assumptions = new Assumptions(false);
-        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), assumptions, replacements));
         new ConditionalEliminationPhase(runtime()).apply(graph);
-        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), assumptions, replacements));
         // a second canonicalizer is needed to process nested MaterializeNodes
-        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), assumptions, replacements));
         StructuredGraph referenceGraph = parse(referenceSnippet);
-        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(referenceGraph);
+        new CanonicalizerPhase(true).apply(referenceGraph, new PhaseContext(runtime(), assumptions, replacements));
         assertEquals(referenceGraph, graph);
     }
 
@@ -236,14 +237,14 @@
         }
     }
 
-    private <T extends Node & Node.IterableNodeType> void test(String snippet, Class<T> clazz) {
+    private <T extends Node> void testHelper(String snippet, Class<T> clazz) {
         StructuredGraph graph = parse(snippet);
         Debug.dump(graph, "Graph");
         Assumptions assumptions = new Assumptions(false);
-        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), assumptions, replacements));
         new ConditionalEliminationPhase(runtime()).apply(graph);
-        new CanonicalizerPhase.Instance(runtime(), assumptions, true).apply(graph);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), assumptions, replacements));
         Debug.dump(graph, "Graph");
-        Assert.assertFalse("shouldn't have nodes of type " + clazz, graph.getNodes(clazz).iterator().hasNext());
+        Assert.assertFalse("shouldn't have nodes of type " + clazz, graph.getNodes().filter(clazz).iterator().hasNext());
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/deopt/CompiledMethodTest.java	Wed Oct 02 13:26:31 2013 +0200
@@ -32,6 +32,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.tiers.*;
 import com.oracle.graal.test.*;
 
 /**
@@ -55,7 +56,7 @@
     public void test1() {
         Method method = getMethod("testMethod");
         final StructuredGraph graph = parse(method);
-        new CanonicalizerPhase.Instance(runtime(), new Assumptions(false), true).apply(graph);
+        new CanonicalizerPhase(true).apply(graph, new PhaseContext(runtime(), new Assumptions(false), replacements));
         new DeadCodeEliminationPhase().apply(graph);
 
         for (Node node : graph.getNodes()) {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EarlyReadEliminationTest.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EarlyReadEliminationTest.java	Wed Oct 02 13:26:31 2013 +0200
@@ -42,7 +42,7 @@
         graph = parse(snippet);
         Assumptions assumptions = new Assumptions(false);
         HighTierContext context = new HighTierContext(runtime(), assumptions, replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL);
-        new InliningPhase().apply(graph, context);
-        new EarlyReadEliminationPhase().apply(graph, context);
+        new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
+        new EarlyReadEliminationPhase(new CanonicalizerPhase(true)).apply(graph, context);
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/EscapeAnalysisTest.java	Wed Oct 02 13:26:31 2013 +0200
@@ -234,17 +234,18 @@
 
                 Assumptions assumptions = new Assumptions(false);
                 HighTierContext context = new HighTierContext(runtime(), assumptions, replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL);
-                new InliningPhase().apply(graph, context);
+                new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
                 new DeadCodeEliminationPhase().apply(graph);
                 new CanonicalizerPhase(true).apply(graph, context);
-                new PartialEscapePhase(iterativeEscapeAnalysis).apply(graph, context);
-                Assert.assertEquals(1, graph.getNodes(ReturnNode.class).count());
-                ReturnNode returnNode = graph.getNodes(ReturnNode.class).first();
+                new PartialEscapePhase(iterativeEscapeAnalysis, new CanonicalizerPhase(true)).apply(graph, context);
+                Assert.assertEquals(1, graph.getNodes().filter(ReturnNode.class).count());
+                ReturnNode returnNode = graph.getNodes().filter(ReturnNode.class).first();
                 if (expectedConstantResult != null) {
                     Assert.assertTrue(returnNode.result().toString(), returnNode.result().isConstant());
                     Assert.assertEquals(expectedConstantResult, returnNode.result().asConstant());
                 }
-                int newInstanceCount = graph.getNodes(NewInstanceNode.class).count() + graph.getNodes(NewArrayNode.class).count() + graph.getNodes(CommitAllocationNode.class).count();
+                int newInstanceCount = graph.getNodes().filter(NewInstanceNode.class).count() + graph.getNodes().filter(NewArrayNode.class).count() +
+                                graph.getNodes().filter(CommitAllocationNode.class).count();
                 Assert.assertEquals(0, newInstanceCount);
                 return returnNode;
             }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/IterativeInliningTest.java	Wed Oct 02 13:26:31 2013 +0200
@@ -82,8 +82,8 @@
 
     final ReturnNode getReturn(String snippet) {
         processMethod(snippet);
-        assertEquals(1, graph.getNodes(ReturnNode.class).count());
-        return graph.getNodes(ReturnNode.class).first();
+        assertEquals(1, graph.getNodes().filter(ReturnNode.class).count());
+        return graph.getNodes().filter(ReturnNode.class).first();
     }
 
     private void processMethod(final String snippet) {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PEAReadEliminationTest.java	Wed Oct 02 13:26:31 2013 +0200
@@ -236,15 +236,15 @@
 
     final ReturnNode getReturn(String snippet) {
         processMethod(snippet);
-        assertEquals(1, graph.getNodes(ReturnNode.class).count());
-        return graph.getNodes(ReturnNode.class).first();
+        assertEquals(1, graph.getNodes().filter(ReturnNode.class).count());
+        return graph.getNodes().filter(ReturnNode.class).first();
     }
 
     protected void processMethod(final String snippet) {
         graph = parse(snippet);
         Assumptions assumptions = new Assumptions(false);
         HighTierContext context = new HighTierContext(runtime(), assumptions, replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL);
-        new InliningPhase().apply(graph, context);
-        new PartialEscapePhase(false, true).apply(graph, context);
+        new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
+        new PartialEscapePhase(false, true, new CanonicalizerPhase(true)).apply(graph, context);
     }
 }
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/ea/PartialEscapeAnalysisTest.java	Wed Oct 02 13:26:31 2013 +0200
@@ -126,7 +126,7 @@
 
     @Test
     public void testCache() {
-        testMaterialize("testCacheSnippet", 0.5, 1);
+        testMaterialize("testCacheSnippet", 0.75, 1);
     }
 
     public static class CacheKey {
@@ -167,13 +167,13 @@
     final void testMaterialize(final String snippet, double expectedProbability, int expectedCount, Class<? extends Node>... invalidNodeClasses) {
         StructuredGraph result = processMethod(snippet);
         try {
-            Assert.assertTrue("partial escape analysis should have removed all NewInstanceNode allocations", result.getNodes(NewInstanceNode.class).isEmpty());
-            Assert.assertTrue("partial escape analysis should have removed all NewArrayNode allocations", result.getNodes(NewArrayNode.class).isEmpty());
+            Assert.assertTrue("partial escape analysis should have removed all NewInstanceNode allocations", result.getNodes().filter(NewInstanceNode.class).isEmpty());
+            Assert.assertTrue("partial escape analysis should have removed all NewArrayNode allocations", result.getNodes().filter(NewArrayNode.class).isEmpty());
 
             NodesToDoubles nodeProbabilities = new ComputeProbabilityClosure(result).apply();
             double probabilitySum = 0;
             int materializeCount = 0;
-            for (CommitAllocationNode materialize : result.getNodes(CommitAllocationNode.class)) {
+            for (CommitAllocationNode materialize : result.getNodes().filter(CommitAllocationNode.class)) {
                 probabilitySum += nodeProbabilities.get(materialize) * materialize.getVirtualObjects().size();
                 materializeCount += materialize.getVirtualObjects().size();
             }
@@ -199,10 +199,10 @@
 
                 Assumptions assumptions = new Assumptions(false);
                 HighTierContext context = new HighTierContext(runtime(), assumptions, replacements, null, getDefaultPhasePlan(), OptimisticOptimizations.ALL);
-                new InliningPhase().apply(graph, context);
+                new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
                 new DeadCodeEliminationPhase().apply(graph);
                 new CanonicalizerPhase(true).apply(graph, context);
-                new PartialEscapePhase(false).apply(graph, context);
+                new PartialEscapePhase(false, new CanonicalizerPhase(true)).apply(graph, context);
 
                 for (MergeNode merge : graph.getNodes(MergeNode.class)) {
                     merge.setStateAfter(null);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/inlining/InliningTest.java	Wed Oct 02 13:26:31 2013 +0200
@@ -240,7 +240,7 @@
                 HighTierContext context = new HighTierContext(runtime(), assumptions, replacements, null, phasePlan, OptimisticOptimizations.ALL);
                 Debug.dump(graph, "Graph");
                 new CanonicalizerPhase(true).apply(graph, context);
-                new InliningPhase().apply(graph, context);
+                new InliningPhase(new CanonicalizerPhase(true)).apply(graph, context);
                 Debug.dump(graph, "Graph");
                 new CanonicalizerPhase(true).apply(graph, context);
                 new DeadCodeEliminationPhase().apply(graph);
@@ -279,7 +279,7 @@
     private static int[] countMethodInfopoints(StructuredGraph graph) {
         int start = 0;
         int end = 0;
-        for (InfopointNode ipn : graph.getNodes(InfopointNode.class)) {
+        for (InfopointNode ipn : graph.getNodes().filter(InfopointNode.class)) {
             if (ipn.reason == InfopointReason.METHOD_START) {
                 ++start;
             } else if (ipn.reason == InfopointReason.METHOD_END) {
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Wed Oct 02 13:26:31 2013 +0200
@@ -229,7 +229,7 @@
                 List<Block> codeEmittingOrder = ComputeBlockOrder.computeCodeEmittingOrder(blocks.length, startBlock, nodeProbabilities);
                 List<Block> linearScanOrder = ComputeBlockOrder.computeLinearScanOrder(blocks.length, startBlock, nodeProbabilities);
 
-                LIR lir = new LIR(schedule.getCFG(), schedule.getBlockToNodesMap(), linearScanOrder, codeEmittingOrder, speculationLog);
+                LIR lir = new LIR(schedule.getCFG(), schedule.getBlockToNodesMap(), linearScanOrder, codeEmittingOrder);
                 Debug.dump(lir, "After linear scan order");
                 return lir;
 
@@ -238,7 +238,7 @@
 
     }
 
-    public static LIRGenerator emitLIR(Backend backend, final TargetDescription target, final LIR lir, StructuredGraph graph, CallingConvention cc) {
+    public static LIRGenerator emitLIR(final Backend backend, final TargetDescription target, final LIR lir, StructuredGraph graph, CallingConvention cc) {
         final FrameMap frameMap = backend.newFrameMap();
         final LIRGenerator lirGen = backend.newLIRGenerator(graph, frameMap, cc, lir);
 
@@ -269,7 +269,9 @@
         Debug.scope("Allocator", new Runnable() {
 
             public void run() {
-                new LinearScan(target, lir, lirGen, frameMap).allocate();
+                if (backend.shouldAllocateRegisters()) {
+                    new LinearScan(target, lir, lirGen, frameMap).allocate();
+                }
             }
         });
         return lirGen;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalDebugConfig.java	Wed Oct 02 13:26:31 2013 +0200
@@ -36,8 +36,6 @@
 public class GraalDebugConfig implements DebugConfig {
 
     // @formatter:off
-    @Option(help = "Enable scope-based debugging", name = "Debug")
-    public static final OptionValue<Boolean> DebugEnabled = new OptionValue<>(true);
     @Option(help = "Pattern for scope(s) to in which dumping is enabled (see DebugFilter and Debug.dump)")
     public static final OptionValue<String> Dump = new OptionValue<>(null);
     @Option(help = "Pattern for scope(s) to in which metering is enabled (see DebugFilter and Debug.metric)")
@@ -53,7 +51,7 @@
                    "Partial - aggregate by partially qualified name (e.g., A.B.C.D.Counter and X.Y.Z.D.Counter will be merged to D.Counter)%n" +
                    "Complete - aggregate by qualified name%n" +
                    "Thread - aggregate by qualified name and thread")
-    public static final OptionValue<String> DebugValueSummary = new OptionValue<>("Complete");
+    public static final OptionValue<String> DebugValueSummary = new OptionValue<>("Name");
     @Option(help = "Send Graal IR to dump handlers on error")
     public static final OptionValue<Boolean> DumpOnError = new OptionValue<>(false);
     @Option(help = "Enable expensive assertions")
@@ -68,6 +66,10 @@
     };
     // @formatter:on
 
+    public static boolean areDebugScopePatternsEnabled() {
+        return DumpOnError.getValue() || Dump.getValue() != null || Meter.getValue() != null || Time.getValue() != null || Log.getValue() != null;
+    }
+
     private final DebugFilter logFilter;
     private final DebugFilter meterFilter;
     private final DebugFilter timerFilter;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/DebugInfoBuilder.java	Wed Oct 02 13:26:31 2013 +0200
@@ -48,7 +48,7 @@
     protected HashMap<VirtualObjectNode, VirtualObject> virtualObjects = new HashMap<>();
     protected IdentityHashMap<VirtualObjectNode, EscapeObjectState> objectStates = new IdentityHashMap<>();
 
-    public LIRFrameState build(FrameState topState, short reason, LabelRef exceptionEdge) {
+    public LIRFrameState build(FrameState topState, LabelRef exceptionEdge) {
         assert virtualObjects.size() == 0;
         assert objectStates.size() == 0;
 
@@ -101,11 +101,11 @@
         }
         objectStates.clear();
 
-        return newLIRFrameState(reason, exceptionEdge, frame, virtualObjectsArray);
+        return newLIRFrameState(exceptionEdge, frame, virtualObjectsArray);
     }
 
-    protected LIRFrameState newLIRFrameState(short reason, LabelRef exceptionEdge, BytecodeFrame frame, VirtualObject[] virtualObjectsArray) {
-        return new LIRFrameState(frame, virtualObjectsArray, exceptionEdge, reason);
+    protected LIRFrameState newLIRFrameState(LabelRef exceptionEdge, BytecodeFrame frame, VirtualObject[] virtualObjectsArray) {
+        return new LIRFrameState(frame, virtualObjectsArray, exceptionEdge);
     }
 
     protected BytecodeFrame computeFrameForState(FrameState state) {
@@ -122,7 +122,7 @@
         if (state.outerFrameState() != null) {
             caller = computeFrameForState(state.outerFrameState());
         }
-        assert state.bci != FrameState.UNKNOWN_BCI : "bci == " + state.bci;
+        assert state.bci >= FrameState.BEFORE_BCI : "bci == " + state.bci;
         return new BytecodeFrame(caller, state.method(), state.bci, state.rethrowException(), state.duringCall(), values, numLocals, numStack, numLocks);
     }
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Wed Oct 02 13:26:31 2013 +0200
@@ -228,26 +228,26 @@
         if (!deopt.canDeoptimize()) {
             return null;
         }
-        return stateFor(deopt.getDeoptimizationState(), deopt.getDeoptimizationReason());
+        return stateFor(deopt.getDeoptimizationState());
     }
 
     public LIRFrameState stateWithExceptionEdge(DeoptimizingNode deopt, LabelRef exceptionEdge) {
         if (!deopt.canDeoptimize()) {
             return null;
         }
-        return stateForWithExceptionEdge(deopt.getDeoptimizationState(), deopt.getDeoptimizationReason(), exceptionEdge);
+        return stateForWithExceptionEdge(deopt.getDeoptimizationState(), exceptionEdge);
     }
 
-    public LIRFrameState stateFor(FrameState state, DeoptimizationReason reason) {
-        return stateForWithExceptionEdge(state, reason, null);
+    public LIRFrameState stateFor(FrameState state) {
+        return stateForWithExceptionEdge(state, null);
     }
 
-    public LIRFrameState stateForWithExceptionEdge(FrameState state, DeoptimizationReason reason, LabelRef exceptionEdge) {
+    public LIRFrameState stateForWithExceptionEdge(FrameState state, LabelRef exceptionEdge) {
         if (needOnlyOopMaps()) {
-            return new LIRFrameState(null, null, null, (short) -1);
+            return new LIRFrameState(null, null, null);
         }
         assert state != null;
-        return debugInfoBuilder.build(state, lir.getDeoptimizationReasons().addSpeculation(reason), exceptionEdge);
+        return debugInfoBuilder.build(state, exceptionEdge);
     }
 
     /**
@@ -616,7 +616,15 @@
 
     @Override
     public Variable emitForeignCall(ForeignCallLinkage linkage, DeoptimizingNode info, Value... args) {
-        LIRFrameState state = !linkage.canDeoptimize() ? null : stateFor(info.getDeoptimizationState(), info.getDeoptimizationReason());
+        LIRFrameState state = null;
+        if (linkage.canDeoptimize()) {
+            if (info != null) {
+                state = stateFor(info.getDeoptimizationState());
+            } else {
+                assert needOnlyOopMaps();
+                state = new LIRFrameState(null, null, null);
+            }
+        }
 
         // move the arguments into the correct location
         CallingConvention linkageCc = linkage.getOutgoingCallingConvention();
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/HighTier.java	Wed Oct 02 13:26:31 2013 +0200
@@ -22,12 +22,12 @@
  */
 package com.oracle.graal.compiler.phases;
 
+import static com.oracle.graal.compiler.phases.HighTier.Options.*;
 import static com.oracle.graal.phases.GraalOptions.*;
 
 import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.loop.phases.*;
-import com.oracle.graal.nodes.spi.Lowerable.LoweringType;
 import com.oracle.graal.options.*;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
@@ -37,12 +37,15 @@
 
 public class HighTier extends PhaseSuite<HighTierContext> {
 
-    // @formatter:off
-    @Option(help = "")
-    public static final OptionValue<Boolean> VerifyUsageWithEquals = new OptionValue<>(true);
-    @Option(help = "Enable inlining")
-    public static final OptionValue<Boolean> Inline = new OptionValue<>(true);
-    // @formatter:on
+    static class Options {
+
+        // @formatter:off
+        @Option(help = "")
+        public static final OptionValue<Boolean> VerifyUsageWithEquals = new OptionValue<>(true);
+        @Option(help = "Enable inlining")
+        public static final OptionValue<Boolean> Inline = new OptionValue<>(true);
+        // @formatter:on
+    }
 
     public HighTier() {
         CanonicalizerPhase canonicalizer = new CanonicalizerPhase(!AOTCompilation.getValue());
@@ -60,12 +63,12 @@
             if (IterativeInlining.getValue()) {
                 appendPhase(new IterativeInliningPhase(canonicalizer));
             } else {
-                appendPhase(new InliningPhase());
+                appendPhase(new InliningPhase(canonicalizer));
                 appendPhase(new DeadCodeEliminationPhase());
 
                 if (ConditionalElimination.getValue() && OptCanonicalizer.getValue()) {
                     appendPhase(canonicalizer);
-                    appendPhase(new IterativeConditionalEliminationPhase());
+                    appendPhase(new IterativeConditionalEliminationPhase(canonicalizer));
                 }
             }
         }
@@ -73,15 +76,15 @@
         appendPhase(new CleanTypeProfileProxyPhase());
 
         if (FullUnroll.getValue()) {
-            appendPhase(new LoopFullUnrollPhase(!AOTCompilation.getValue()));
+            appendPhase(new LoopFullUnrollPhase(canonicalizer));
         }
 
         if (OptTailDuplication.getValue()) {
-            appendPhase(new TailDuplicationPhase());
+            appendPhase(new TailDuplicationPhase(canonicalizer));
         }
 
         if (PartialEscapeAnalysis.getValue()) {
-            appendPhase(new PartialEscapePhase(true));
+            appendPhase(new PartialEscapePhase(true, canonicalizer));
         }
 
         if (OptConvertDeoptsToGuards.getValue()) {
@@ -98,6 +101,6 @@
             appendPhase(canonicalizer);
         }
 
-        appendPhase(new LoweringPhase(LoweringType.BEFORE_GUARDS));
+        appendPhase(new LoweringPhase(canonicalizer));
     }
 }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java	Wed Oct 02 13:26:31 2013 +0200
@@ -22,7 +22,8 @@
  */
 package com.oracle.graal.compiler.phases;
 
-import com.oracle.graal.nodes.spi.Lowerable.LoweringType;
+import static com.oracle.graal.phases.GraalOptions.*;
+
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
@@ -30,7 +31,9 @@
 public class LowTier extends PhaseSuite<LowTierContext> {
 
     public LowTier() {
-        appendPhase(new LoweringPhase(LoweringType.AFTER_FSA));
+        CanonicalizerPhase canonicalizer = new CanonicalizerPhase(!AOTCompilation.getValue());
+
+        appendPhase(new LoweringPhase(canonicalizer));
 
         appendPhase(new ExpandLogicPhase());
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/MidTier.java	Wed Oct 02 13:26:31 2013 +0200
@@ -25,7 +25,6 @@
 import static com.oracle.graal.phases.GraalOptions.*;
 
 import com.oracle.graal.loop.phases.*;
-import com.oracle.graal.nodes.spi.Lowerable.LoweringType;
 import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.common.*;
 import com.oracle.graal.phases.tiers.*;
@@ -47,11 +46,11 @@
         appendPhase(new LockEliminationPhase());
 
         if (OptReadElimination.getValue()) {
-            appendPhase(new EarlyReadEliminationPhase());
+            appendPhase(new EarlyReadEliminationPhase(canonicalizer));
         }
 
         if (OptFloatingReads.getValue()) {
-            IncrementalCanonicalizerPhase<MidTierContext> incCanonicalizer = new IncrementalCanonicalizerPhase<>();
+            IncrementalCanonicalizerPhase<MidTierContext> incCanonicalizer = new IncrementalCanonicalizerPhase<>(canonicalizer);
             incCanonicalizer.appendPhase(new FloatingReadPhase());
             appendPhase(incCanonicalizer);
             if (OptReadElimination.getValue()) {
@@ -69,7 +68,7 @@
         }
 
         if (ConditionalElimination.getValue() && OptCanonicalizer.getValue()) {
-            appendPhase(new IterativeConditionalEliminationPhase());
+            appendPhase(new IterativeConditionalEliminationPhase(canonicalizer));
         }
 
         if (OptEliminatePartiallyRedundantGuards.getValue()) {
@@ -82,14 +81,16 @@
 
         appendPhase(new LoopSafepointEliminationPhase());
 
-        appendPhase(new SafepointInsertionPhase());
+        appendPhase(new LoopSafepointInsertionPhase());
 
         appendPhase(new GuardLoweringPhase());
 
-        appendPhase(new LoweringPhase(LoweringType.AFTER_GUARDS));
+        appendPhase(new LoweringPhase(canonicalizer));
 
         appendPhase(new FrameStateAssignmentPhase());
 
+        appendPhase(new DeoptimizationGroupingPhase());
+
         if (OptCanonicalizer.getValue()) {
             appendPhase(canonicalizer);
         }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java	Wed Oct 02 13:26:31 2013 +0200
@@ -55,6 +55,8 @@
 
     public abstract TargetMethodAssembler newAssembler(LIRGenerator lirGen, CompilationResult compilationResult);
 
+    public abstract boolean shouldAllocateRegisters();
+
     /**
      * Emits the code for a given graph.
      * 
--- a/graal/com.oracle.graal.debug.test/src/com/oracle/graal/debug/test/DebugHistogramTest.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.debug.test/src/com/oracle/graal/debug/test/DebugHistogramTest.java	Wed Oct 02 13:26:31 2013 +0200
@@ -27,6 +27,7 @@
 import org.junit.*;
 
 import com.oracle.graal.debug.*;
+import com.oracle.graal.debug.internal.*;
 
 public class DebugHistogramTest {
 
@@ -34,8 +35,13 @@
     public void testEmptyHistogram() {
         DebugHistogram histogram = Debug.createHistogram("TestHistogram");
         ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
-        histogram.print(new PrintStream(outputStream));
+
+        new DebugHistogramAsciiPrinter(new PrintStream(outputStream)).print(histogram);
         Assert.assertEquals("TestHistogram is empty.\n", outputStream.toString());
+
+        outputStream.reset();
+        new DebugHistogramRPrinter(new PrintStream(outputStream)).print(histogram);
+        Assert.assertEquals("", outputStream.toString());
     }
 
     @Test
@@ -44,19 +50,28 @@
         ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
         histogram.add(new Integer(1));
         histogram.add(new Integer(1));
-        histogram.print(new PrintStream(outputStream));
+        new DebugHistogramAsciiPrinter(new PrintStream(outputStream)).print(histogram);
         String[] lines = outputStream.toString().split("\n");
-        Assert.assertEquals(4, lines.length);
-        Assert.assertEquals("TestHistogram has 1 unique elements and 2 total elements:", lines[0]);
-        Assert.assertEquals(
-                        "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------",
-                        lines[1]);
-        Assert.assertEquals(
-                        "| 1                                                  | 2          | ==================================================================================================== |",
-                        lines[2]);
-        Assert.assertEquals(
-                        "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------",
-                        lines[3]);
+        // @formatter:off
+        String[] expected = {
+            "TestHistogram has 1 unique elements and 2 total elements:",
+            "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------",
+            "| 1                                                  | 2          | ==================================================================================================== |",
+            "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------"
+        };
+        // @formatter:on
+        Assert.assertArrayEquals(expected, lines);
+
+        outputStream.reset();
+        new DebugHistogramRPrinter(new PrintStream(outputStream)).print(histogram);
+        lines = outputStream.toString().split("\n");
+        // @formatter:off
+        expected = new String[] {
+            "TestHistogram <- c(2);",
+            "names(TestHistogram) <- c(\"1\");"
+        };
+        // @formatter:on
+        Assert.assertArrayEquals(expected, lines);
     }
 
     @Test
@@ -66,22 +81,29 @@
         histogram.add(new Integer(1));
         histogram.add(new Integer(2));
         histogram.add(new Integer(2));
-        histogram.print(new PrintStream(outputStream));
+        new DebugHistogramAsciiPrinter(new PrintStream(outputStream)).print(histogram);
         String[] lines = outputStream.toString().split("\n");
-        Assert.assertEquals(5, lines.length);
-        Assert.assertEquals("TestHistogram has 2 unique elements and 3 total elements:", lines[0]);
-        Assert.assertEquals(
-                        "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------",
-                        lines[1]);
-        Assert.assertEquals(
-                        "| 2                                                  | 2          | ==================================================================================================== |",
-                        lines[2]);
-        Assert.assertEquals(
-                        "| 1                                                  | 1          | ==================================================                                                   |",
-                        lines[3]);
-        Assert.assertEquals(
-                        "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------",
-                        lines[4]);
+        // @formatter:off
+        String[] expected = new String[] {
+            "TestHistogram has 2 unique elements and 3 total elements:",
+            "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------",
+            "| 2                                                  | 2          | ==================================================================================================== |",
+            "| 1                                                  | 1          | ==================================================                                                   |",
+            "--------------------------------------------------------------------------------------------------------------------------------------------------------------------------"
+        };
+        // @formatter:on
+        Assert.assertArrayEquals(expected, lines);
+
+        outputStream.reset();
+        new DebugHistogramRPrinter(new PrintStream(outputStream)).print(histogram);
+        lines = outputStream.toString().split("\n");
+        // @formatter:off
+        expected = new String[] {
+            "TestHistogram <- c(2, 1);",
+            "names(TestHistogram) <- c(\"2\", \"1\");"
+        };
+        // @formatter:on
+        Assert.assertArrayEquals(expected, lines);
     }
 
     @Test
@@ -89,7 +111,7 @@
         DebugHistogram histogram = Debug.createHistogram("TestHistogram");
         ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
         histogram.add("MyCustomValue");
-        histogram.print(new PrintStream(outputStream), Integer.MAX_VALUE, 10, 10);
+        new DebugHistogramAsciiPrinter(new PrintStream(outputStream), Integer.MAX_VALUE, 10, 10).print(histogram);
         String[] lines = outputStream.toString().split("\n");
         Assert.assertEquals(4, lines.length);
         Assert.assertEquals("TestHistogram has 1 unique elements and 1 total elements:", lines[0]);
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java	Wed Oct 02 13:26:31 2013 +0200
@@ -22,24 +22,49 @@
  */
 package com.oracle.graal.debug;
 
-import com.oracle.graal.debug.internal.*;
+import static com.oracle.graal.debug.Debug.Initialization.*;
 
 import java.io.*;
 import java.util.*;
 import java.util.concurrent.*;
 
+import com.oracle.graal.debug.internal.*;
+
+/**
+ * Scope based debugging facility. This facility is {@link #isEnabled()} if assertions are enabled
+ * for the {@link Debug} class or the {@value Initialization#INITIALIZER_PROPERTY_NAME} system
+ * property is {@code "true"} when {@link Debug} is initialized.
+ */
 public class Debug {
 
-    private static boolean ENABLED = false;
+    /**
+     * Class to assist with initialization of {@link Debug}.
+     */
+    public static class Initialization {
 
-    public static void enable() {
-        ENABLED = true;
+        public static final String INITIALIZER_PROPERTY_NAME = "graal.debug.enable";
+
+        private static boolean initialized;
+
+        /**
+         * Determines if {@link Debug} has been initialized.
+         */
+        public static boolean isDebugInitialized() {
+            return initialized;
+        }
+
     }
 
-    public static void disable() {
-        ENABLED = false;
+    @SuppressWarnings("all")
+    private static boolean initialize() {
+        boolean assertionsEnabled = false;
+        assert assertionsEnabled = true;
+        Initialization.initialized = true;
+        return assertionsEnabled || Boolean.getBoolean(INITIALIZER_PROPERTY_NAME);
     }
 
+    private static final boolean ENABLED = initialize();
+
     public static boolean isEnabled() {
         return ENABLED;
     }
@@ -330,7 +355,7 @@
 
     public static DebugMetric metric(String name) {
         if (ENABLED) {
-            return new MetricImpl(name);
+            return new MetricImpl(name, true);
         } else {
             return VOID_METRIC;
         }
@@ -342,6 +367,9 @@
         }
     }
 
+    /**
+     * Creates an object for counting value frequencies.
+     */
     public static DebugHistogram createHistogram(String name) {
         return new DebugHistogramImpl(name);
     }
@@ -402,11 +430,19 @@
 
         public void add(long value) {
         }
+
+        public void setConditional(boolean flag) {
+            throw new InternalError("Cannot make void metric conditional");
+        }
+
+        public boolean isConditional() {
+            return false;
+        }
     };
 
     public static DebugTimer timer(String name) {
         if (ENABLED) {
-            return new TimerImpl(name);
+            return new TimerImpl(name, true);
         } else {
             return VOID_TIMER;
         }
@@ -417,5 +453,13 @@
         public TimerCloseable start() {
             return TimerImpl.VOID_CLOSEABLE;
         }
+
+        public void setConditional(boolean flag) {
+            throw new InternalError("Cannot make void timer conditional");
+        }
+
+        public boolean isConditional() {
+            return false;
+        }
     };
 }
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugHistogram.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugHistogram.java	Wed Oct 02 13:26:31 2013 +0200
@@ -22,15 +22,75 @@
  */
 package com.oracle.graal.debug;
 
-import java.io.*;
+import java.util.*;
 
+/**
+ * Facility for recording value frequencies.
+ */
 public interface DebugHistogram {
 
+    /**
+     * Gets the name specified when this objected was {@linkplain Debug#createHistogram(String)
+     * created}.
+     */
     String getName();
 
+    /**
+     * Increments the count for a given value.
+     */
     void add(Object value);
 
-    void print(PrintStream os);
+    /**
+     * A value and a frequency. The ordering imposed by {@link #compareTo(CountedValue)} places
+     * values with higher frequencies first.
+     */
+    public class CountedValue implements Comparable<CountedValue> {
 
-    void print(PrintStream os, int limit, int nameSize, int barSize);
+        private int count;
+        private final Object value;
+
+        public CountedValue(int count, Object value) {
+            this.count = count;
+            this.value = value;
+        }
+
+        public int compareTo(CountedValue o) {
+            if (count < o.count) {
+                return 1;
+            } else if (count > o.count) {
+                return -1;
+            }
+            return 0;
+        }
+
+        @Override
+        public String toString() {
+            return count + " -> " + value;
+        }
+
+        public void inc() {
+            count++;
+        }
+
+        public int getCount() {
+            return count;
+        }
+
+        public Object getValue() {
+            return value;
+        }
+    }
+
+    /**
+     * Gets a list of the counted values, sorted in descending order of frequency.
+     */
+    List<CountedValue> getValues();
+
+    /**
+     * Interface for a service that can render a visualization of a histogram.
+     */
+    public interface Printer {
+
+        void print(DebugHistogram histogram);
+    }
 }
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugMetric.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugMetric.java	Wed Oct 02 13:26:31 2013 +0200
@@ -22,9 +22,32 @@
  */
 package com.oracle.graal.debug;
 
+/**
+ * A counter for some value of interest.
+ */
 public interface DebugMetric {
 
+    /**
+     * Adds 1 to this counter if metering is {@link Debug#isMeterEnabled() enabled} or this is an
+     * {@linkplain #isConditional() unconditional} metric.
+     */
     void increment();
 
+    /**
+     * Adds {@code value} to this counter if metering is {@link Debug#isMeterEnabled() enabled} or
+     * this is an {@linkplain #isConditional() unconditional} metric.
+     */
     void add(long value);
+
+    /**
+     * Sets a flag determining if this counter is only enabled if metering is
+     * {@link Debug#isMeterEnabled() enabled}.
+     */
+    void setConditional(boolean flag);
+
+    /**
+     * Determines if this counter is only enabled if metering is {@link Debug#isMeterEnabled()
+     * enabled}.
+     */
+    boolean isConditional();
 }
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugTimer.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugTimer.java	Wed Oct 02 13:26:31 2013 +0200
@@ -24,7 +24,36 @@
 
 import com.oracle.graal.debug.internal.*;
 
+/**
+ * A timer for some activity of interest. A timer should be deployed using the try-with-resources
+ * pattern:
+ * 
+ * <pre>
+ * try (TimerCloseable a = timer.start()) {
+ *     // the code to time
+ * }
+ * </pre>
+ */
 public interface DebugTimer {
 
+    /**
+     * Starts this timer if timing is {@linkplain Debug#isTimeEnabled() enabled} or this is an
+     * {@linkplain #isConditional() unconditional} timer.
+     * 
+     * @return an object that must be closed once the activity has completed to add the elapsed time
+     *         since this call to the total for this timer
+     */
     TimerCloseable start();
+
+    /**
+     * Sets a flag determining if this timer is only enabled if metering is
+     * {@link Debug#isMeterEnabled() enabled}.
+     */
+    void setConditional(boolean flag);
+
+    /**
+     * Determines if this timer is only enabled if metering is {@link Debug#isMeterEnabled()
+     * enabled}.
+     */
+    boolean isConditional();
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugHistogramAsciiPrinter.java	Wed Oct 02 13:26:31 2013 +0200
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2013, 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.debug.internal;
+
+import java.io.*;
+import java.util.*;
+
+import com.oracle.graal.debug.*;
+import com.oracle.graal.debug.DebugHistogram.*;
+
+/**
+ * Renders a textual representation of a histogram to a given print stream.
+ */
+public class DebugHistogramAsciiPrinter implements Printer {
+
+    public static final int NumberSize = 10;
+    public static final int DefaultNameSize = 50;
+    public static final int DefaultBarSize = 100;
+
+    private PrintStream os;
+    private int limit;
+    private int nameSize;
+    private int barSize;
+
+    public DebugHistogramAsciiPrinter(PrintStream os) {
+        this(os, Integer.MAX_VALUE, DefaultNameSize, DefaultBarSize);
+    }
+
+    /**
+     * @param os where to print
+     * @param limit limits printing to the {@code limit} most frequent values
+     * @param nameSize the width of the value names column
+     * @param barSize the width of the value frequency column
+     */
+    public DebugHistogramAsciiPrinter(PrintStream os, int limit, int nameSize, int barSize) {
+        this.os = os;
+        this.limit = limit;
+        this.nameSize = nameSize;
+        this.barSize = barSize;
+    }
+
+    public void print(DebugHistogram histogram) {
+        List<CountedValue> list = histogram.getValues();
+        if (list.isEmpty()) {
+            os.printf("%s is empty.\n", histogram.getName());
+            return;
+        }
+
+        // Sum up the total number of elements.
+        int total = 0;
+        for (CountedValue cv : list) {
+            total += cv.getCount();
+        }
+
+        // Print header.
+        os.printf("%s has %d unique elements and %d total elements:\n", histogram.getName(), list.size(), total);
+
+        int max = list.get(0).getCount();
+        final int lineSize = nameSize + NumberSize + barSize + 10;
+        printLine(os, '-', lineSize);
+        String formatString = "| %-" + nameSize + "s | %-" + NumberSize + "d | %-" + barSize + "s |\n";
+        for (int i = 0; i < list.size() && i < limit; ++i) {
+            CountedValue cv = list.get(i);
+            int value = cv.getCount();
+            char[] bar = new char[(int) (((double) value / (double) max) * barSize)];
+            Arrays.fill(bar, '=');
+            String objectString = String.valueOf(cv.getValue());
+            if (objectString.length() > nameSize) {
+                objectString = objectString.substring(0, nameSize - 3) + "...";
+            }
+            os.printf(formatString, objectString, value, new String(bar));
+        }
+        printLine(os, '-', lineSize);
+    }
+
+    private static void printLine(PrintStream printStream, char c, int lineSize) {
+        char[] charArr = new char[lineSize];
+        Arrays.fill(charArr, c);
+        printStream.printf("%s\n", new String(charArr));
+    }
+}
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugHistogramImpl.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugHistogramImpl.java	Wed Oct 02 13:26:31 2013 +0200
@@ -22,28 +22,25 @@
  */
 package com.oracle.graal.debug.internal;
 
-import java.io.*;
 import java.util.*;
 
 import com.oracle.graal.debug.*;
 
 public class DebugHistogramImpl implements DebugHistogram {
 
-    public static final int NumberSize = 10;
-    public static final int DefaultNameSize = 50;
-    public static final int DefaultBarSize = 100;
     private final String name;
-    private HashMap<Object, Integer> map = new HashMap<>();
+    private HashMap<Object, CountedValue> map = new HashMap<>();
 
     public DebugHistogramImpl(String name) {
         this.name = name;
     }
 
     public void add(Object value) {
-        if (!map.containsKey(value)) {
-            map.put(value, 1);
+        CountedValue cv = map.get(value);
+        if (cv == null) {
+            map.put(value, new CountedValue(1, value));
         } else {
-            map.put(value, map.get(value) + 1);
+            cv.inc();
         }
     }
 
@@ -52,59 +49,9 @@
         return name;
     }
 
-    @Override
-    public void print(PrintStream os) {
-        print(os, Integer.MAX_VALUE, DefaultNameSize, DefaultBarSize);
-    }
-
-    public void print(PrintStream os, int limit, int nameSize, int barSize) {
-
-        List<Object> list = new ArrayList<>(map.keySet());
-        if (list.size() == 0) {
-            // No elements in the histogram.
-            os.printf("%s is empty.\n", name);
-            return;
-        }
-
-        // Sort from highest to smallest.
-        Collections.sort(list, new Comparator<Object>() {
-
-            @Override
-            public int compare(Object o1, Object o2) {
-                return map.get(o2) - map.get(o1);
-            }
-        });
-
-        // Sum up the total number of elements.
-        int total = 0;
-        for (Object o : list) {
-            total += map.get(o);
-        }
-
-        // Print header.
-        os.printf("%s has %d unique elements and %d total elements:\n", name, list.size(), total);
-
-        int max = map.get(list.get(0));
-        final int lineSize = nameSize + NumberSize + barSize + 10;
-        printLine(os, '-', lineSize);
-        String formatString = "| %-" + nameSize + "s | %-" + NumberSize + "d | %-" + barSize + "s |\n";
-        for (int i = 0; i < list.size() && i < limit; ++i) {
-            Object o = list.get(i);
-            int value = map.get(o);
-            char[] bar = new char[(int) (((double) value / (double) max) * barSize)];
-            Arrays.fill(bar, '=');
-            String objectString = o.toString();
-            if (objectString.length() > nameSize) {
-                objectString = objectString.substring(0, nameSize - 3) + "...";
-            }
-            os.printf(formatString, objectString, value, new String(bar));
-        }
-        printLine(os, '-', lineSize);
-    }
-
-    private static void printLine(PrintStream printStream, char c, int lineSize) {
-        char[] charArr = new char[lineSize];
-        Arrays.fill(charArr, c);
-        printStream.printf("%s\n", new String(charArr));
+    public List<CountedValue> getValues() {
+        ArrayList<CountedValue> res = new ArrayList<>(map.values());
+        Collections.sort(res);
+        return res;
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugHistogramRPrinter.java	Wed Oct 02 13:26:31 2013 +0200
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2013, 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.debug.internal;
+
+import java.io.*;
+import java.util.*;
+
+import com.oracle.graal.debug.*;
+import com.oracle.graal.debug.DebugHistogram.CountedValue;
+import com.oracle.graal.debug.DebugHistogram.Printer;
+
+/**
+ * Renders a histogram as an R script to a given print stream. The R script emitted for a histogram
+ * is a simple set of statements for defining a vector of named objects.
+ */
+public class DebugHistogramRPrinter implements Printer {
+
+    private PrintStream os;
+    private int limit;
+
+    public DebugHistogramRPrinter(PrintStream os) {
+        this(os, Integer.MAX_VALUE);
+    }
+
+    /**
+     * @param os where to print
+     * @param limit limits printing to the {@code limit} most frequent values
+     */
+    public DebugHistogramRPrinter(PrintStream os, int limit) {
+        this.os = os;
+        this.limit = limit;
+    }
+
+    public void print(DebugHistogram histogram) {
+        List<CountedValue> list = histogram.getValues();
+        if (list.isEmpty()) {
+            return;
+        }
+
+        String var = histogram.getName().replace('-', '.').replace(' ', '_');
+        os.print(var + " <- c(");
+        for (int i = 0; i < list.size() && i < limit; ++i) {
+            CountedValue cv = list.get(i);
+            if (i != 0) {
+                os.print(", ");
+            }
+            os.print(cv.getCount());
+        }
+        os.println(");");
+
+        os.print("names(" + var + ") <- c(");
+        for (int i = 0; i < list.size() && i < limit; ++i) {
+            CountedValue cv = list.get(i);
+            if (i != 0) {
+                os.print(", ");
+            }
+            os.print("\"" + cv.getValue() + "\"");
+        }
+        os.println(");");
+    }
+}
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugScope.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugScope.java	Wed Oct 02 13:26:31 2013 +0200
@@ -92,7 +92,6 @@
     private static ThreadLocal<DebugScope> instanceTL = new ThreadLocal<>();
     private static ThreadLocal<DebugConfig> configTL = new ThreadLocal<>();
     private static ThreadLocal<Throwable> lastExceptionThrownTL = new ThreadLocal<>();
-    private static DebugTimer scopeTime = Debug.timer("ScopeTime");
 
     private final DebugScope parent;
     private IndentImpl lastUsedIndent;
@@ -210,6 +209,9 @@
             for (DebugDumpHandler dumpHandler : config.dumpHandlers()) {
                 dumpHandler.dump(object, message);
             }
+        } else {
+            PrintStream out = System.out;
+            out.println("Forced dump ignored because debugging is disabled - use -G:Dump=xxx option");
         }
     }
 
@@ -239,7 +241,7 @@
         }
         instanceTL.set(newChild);
         newChild.updateFlags();
-        try (TimerCloseable a = scopeTime.start()) {
+        try {
             return executeScope(runnable, callable);
         } finally {
             newChild.context = null;
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugValue.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugValue.java	Wed Oct 02 13:26:31 2013 +0200
@@ -30,10 +30,12 @@
 
     private final String name;
     private int index;
+    private boolean conditional;
 
-    protected DebugValue(String name) {
+    protected DebugValue(String name, boolean conditional) {
         this.name = name;
         this.index = -1;
+        this.conditional = conditional;
     }
 
     protected long getCurrentValue() {
@@ -46,6 +48,14 @@
         DebugScope.getInstance().setCurrentValue(index, l);
     }
 
+    public void setConditional(boolean flag) {
+        conditional = flag;
+    }
+
+    public boolean isConditional() {
+        return conditional;
+    }
+
     private void ensureInitialized() {
         if (index == -1) {
             index = KeyRegistry.register(this);
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/MetricImpl.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/MetricImpl.java	Wed Oct 02 13:26:31 2013 +0200
@@ -26,8 +26,8 @@
 
 public final class MetricImpl extends DebugValue implements DebugMetric {
 
-    public MetricImpl(String name) {
-        super(name);
+    public MetricImpl(String name, boolean conditional) {
+        super(name, conditional);
     }
 
     public void increment() {
@@ -35,7 +35,7 @@
     }
 
     public void add(long value) {
-        if (Debug.isMeterEnabled()) {
+        if (!isConditional() || Debug.isMeterEnabled()) {
             super.addToCurrentValue(value);
         }
     }
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/TimerCloseable.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/TimerCloseable.java	Wed Oct 02 13:26:31 2013 +0200
@@ -22,6 +22,12 @@
  */
 package com.oracle.graal.debug.internal;
 
+import com.oracle.graal.debug.*;
+
+/**
+ * An object returned by {@link DebugTimer#start()} that when closed, stops the associated timer and
+ * adds the elapsed time since {@code start()} to the total for the timer.
+ */
 public interface TimerCloseable extends AutoCloseable {
 
     void close();
--- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/TimerImpl.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/TimerImpl.java	Wed Oct 02 13:26:31 2013 +0200
@@ -37,59 +37,78 @@
         }
     };
 
-    private ThreadLocal<Long> valueToSubstract = new ThreadLocal<>();
+    /**
+     * Records the most recent active timer.
+     */
+    private static ThreadLocal<AbstractTimer> currentTimer = new ThreadLocal<>();
 
-    public TimerImpl(String name) {
-        super(name);
+    private final DebugValue flat;
+
+    public TimerImpl(String name, boolean conditional) {
+        super(name + "_Accm", conditional);
+        this.flat = new DebugValue(name + "_Flat", conditional) {
+
+            @Override
+            public String toString(long value) {
+                return valueToString(value);
+            }
+        };
     }
 
     @Override
     public TimerCloseable start() {
-        if (Debug.isTimeEnabled()) {
+        if (!isConditional() || Debug.isTimeEnabled()) {
             long startTime;
             if (threadMXBean.isCurrentThreadCpuTimeSupported()) {
                 startTime = threadMXBean.getCurrentThreadCpuTime();
             } else {
                 startTime = System.nanoTime();
             }
-            if (valueToSubstract.get() == null) {
-                valueToSubstract.set(0L);
-            }
-            long previousValueToSubstract = valueToSubstract.get();
+
             AbstractTimer result;
             if (threadMXBean.isCurrentThreadCpuTimeSupported()) {
-                result = new CpuTimeTimer(startTime, previousValueToSubstract);
+                result = new CpuTimeTimer(startTime);
             } else {
-                result = new SystemNanosTimer(startTime, previousValueToSubstract);
+                result = new SystemNanosTimer(startTime);
             }
-            valueToSubstract.set(0L);
+            currentTimer.set(result);
             return result;
         } else {
             return VOID_CLOSEABLE;
         }
     }
 
+    public static String valueToString(long value) {
+        return String.format("%d.%d ms", value / 1000000, (value / 100000) % 10);
+    }
+
     @Override
     public String toString(long value) {
-        return String.format("%d.%d ms", value / 1000000, (value / 100000) % 10);
+        return valueToString(value);
     }
 
     private abstract class AbstractTimer implements TimerCloseable {
 
+        private final AbstractTimer parent;
         private final long startTime;
-        private final long previousValueToSubstract;
+        private long nestedTimeToSubtract;
 
-        private AbstractTimer(long startTime, long previousValueToSubstract) {
+        private AbstractTimer(long startTime) {
+            this.parent = currentTimer.get();
             this.startTime = startTime;
-            this.previousValueToSubstract = previousValueToSubstract;
         }
 
         @Override
         public void close() {
-            long timeSpan = currentTime() - startTime;
-            long oldValueToSubstract = valueToSubstract.get();
-            valueToSubstract.set(timeSpan + previousValueToSubstract);
-            TimerImpl.this.addToCurrentValue(timeSpan - oldValueToSubstract);
+            long endTime = currentTime();
+            long timeSpan = endTime - startTime;
+            if (parent != null) {
+                parent.nestedTimeToSubtract += timeSpan;
+            }
+            currentTimer.set(parent);
+            long flatTime = timeSpan - nestedTimeToSubtract;
+            TimerImpl.this.addToCurrentValue(timeSpan);
+            flat.addToCurrentValue(flatTime);
         }
 
         protected abstract long currentTime();
@@ -97,8 +116,8 @@
 
     private final class SystemNanosTimer extends AbstractTimer {
 
-        public SystemNanosTimer(long startTime, long previousValueToSubstract) {
-            super(startTime, previousValueToSubstract);
+        public SystemNanosTimer(long startTime) {
+            super(startTime);
         }
 
         @Override
@@ -109,8 +128,8 @@
 
     private final class CpuTimeTimer extends AbstractTimer {
 
-        public CpuTimeTimer(long startTime, long previousValueToSubstract) {
-            super(startTime, previousValueToSubstract);
+        public CpuTimeTimer(long startTime) {
+            super(startTime);
         }
 
         @Override
--- a/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/TypedNodeIteratorTest.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/TypedNodeIteratorTest.java	Wed Oct 02 13:26:31 2013 +0200
@@ -32,7 +32,7 @@
 
 public class TypedNodeIteratorTest {
 
-    private static class TestNode extends Node implements Node.IterableNodeType, TestNodeInterface {
+    private static class TestNode extends Node implements IterableNodeType, TestNodeInterface {
 
         private final String name;
 
--- a/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/TypedNodeIteratorTest2.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.graph.test/src/com/oracle/graal/graph/test/TypedNodeIteratorTest2.java	Wed Oct 02 13:26:31 2013 +0200
@@ -43,7 +43,7 @@
         }
     }
 
-    private static class NodeB extends NodeA implements Node.IterableNodeType {
+    private static class NodeB extends NodeA implements IterableNodeType {
 
         public NodeB(String name) {
             super(name);
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java	Wed Oct 02 13:26:31 2013 +0200
@@ -25,7 +25,6 @@
 import java.util.*;
 
 import com.oracle.graal.graph.GraphEvent.NodeEvent;
-import com.oracle.graal.graph.Node.IterableNodeType;
 import com.oracle.graal.graph.Node.ValueNumberable;
 import com.oracle.graal.graph.iterators.*;
 
@@ -57,8 +56,8 @@
     private int deletedNodeCount;
     private GraphEventLog eventLog;
 
-    NodeChangedListener inputChanged;
-    NodeChangedListener usagesDroppedZero;
+    NodeChangedListener inputChangedListener;
+    NodeChangedListener usagesDroppedToZeroListener;
     private final HashMap<CacheEntry, Node> cachedNodes = new HashMap<>();
 
     private static final class CacheEntry {
@@ -66,6 +65,8 @@
         private final Node node;
 
         public CacheEntry(Node node) {
+            assert node.getNodeClass().valueNumberable();
+            assert node.getNodeClass().isLeafNode();
             this.node = node;
         }
 
@@ -82,8 +83,8 @@
             if (obj instanceof CacheEntry) {
                 CacheEntry other = (CacheEntry) obj;
                 NodeClass nodeClass = node.getNodeClass();
-                if (other.node.getNodeClass() == nodeClass) {
-                    return nodeClass.valueNumberable() && nodeClass.valueEqual(node, other.node) && nodeClass.edgesEqual(node, other.node);
+                if (other.node.getClass() == node.getClass()) {
+                    return nodeClass.valueEqual(node, other.node);
                 }
             }
             return false;
@@ -156,7 +157,7 @@
     int usageModCount(Node node) {
         int id = extractOriginalNodeId(node);
         if (id >= 0 && id < nodeUsageModCounts.length) {
-            return nodeUsageModCounts[node.id];
+            return nodeUsageModCounts[id];
         }
         return 0;
     }
@@ -187,8 +188,7 @@
      */
     public Graph copy(String newName) {
         Graph copy = new Graph(newName);
-        Map<Node, Node> emptyMap = Collections.emptyMap();
-        copy.addDuplicates(getNodes(), emptyMap);
+        copy.addDuplicates(getNodes(), this, this.getNodeCount(), (Map<Node, Node>) null);
         return copy;
     }
 
@@ -223,6 +223,24 @@
      * @return the node which was added to the graph
      */
     public <T extends Node> T add(T node) {
+        if (node.getNodeClass().valueNumberable()) {
+            throw new IllegalStateException("Using add for value numberable node. Consider using either unique or addWithoutUnique.");
+        }
+        return addHelper(node);
+    }
+
+    public <T extends Node> T addWithoutUnique(T node) {
+        return addHelper(node);
+    }
+
+    public <T extends Node> T addOrUnique(T node) {
+        if (node.getNodeClass().valueNumberable()) {
+            return uniqueHelper(node);
+        }
+        return add(node);
+    }
+
+    private <T extends Node> T addHelper(T node) {
         node.initialize(this);
         return node;
     }
@@ -232,24 +250,54 @@
         void nodeChanged(Node node);
     }
 
-    public void trackInputChange(NodeChangedListener inputChangedListener) {
-        assert this.inputChanged == null;
-        this.inputChanged = inputChangedListener;
+    private static class ChainedNodeChangedListener implements NodeChangedListener {
+
+        NodeChangedListener head;
+        NodeChangedListener next;
+
+        ChainedNodeChangedListener(NodeChangedListener head, NodeChangedListener next) {
+            this.head = head;
+            this.next = next;
+        }
+
+        public void nodeChanged(Node node) {
+            head.nodeChanged(node);
+            next.nodeChanged(node);
+        }
+    }
+
+    public void trackInputChange(NodeChangedListener listener) {
+        if (inputChangedListener == null) {
+            inputChangedListener = listener;
+        } else {
+            inputChangedListener = new ChainedNodeChangedListener(listener, inputChangedListener);
+        }
     }
 
     public void stopTrackingInputChange() {
-        assert inputChanged != null;
-        inputChanged = null;
+        assert inputChangedListener != null;
+        if (inputChangedListener instanceof ChainedNodeChangedListener) {
+            inputChangedListener = ((ChainedNodeChangedListener) inputChangedListener).next;
+        } else {
+            inputChangedListener = null;
+        }
     }
 
-    public void trackUsagesDroppedZero(NodeChangedListener usagesDroppedZeroListener) {
-        assert this.usagesDroppedZero == null;
-        this.usagesDroppedZero = usagesDroppedZeroListener;
+    public void trackUsagesDroppedZero(NodeChangedListener listener) {
+        if (usagesDroppedToZeroListener == null) {
+            usagesDroppedToZeroListener = listener;
+        } else {
+            usagesDroppedToZeroListener = new ChainedNodeChangedListener(listener, usagesDroppedToZeroListener);
+        }
     }
 
     public void stopTrackingUsagesDroppedZero() {
-        assert usagesDroppedZero != null;
-        usagesDroppedZero = null;
+        assert usagesDroppedToZeroListener != null;
+        if (usagesDroppedToZeroListener instanceof ChainedNodeChangedListener) {
+            usagesDroppedToZeroListener = ((ChainedNodeChangedListener) usagesDroppedToZeroListener).next;
+        } else {
+            usagesDroppedToZeroListener = null;
+        }
     }
 
     /**
@@ -261,53 +309,76 @@
      * @return the node which was added to the graph or a <i>similar</i> which was already in the
      *         graph.
      */
-    @SuppressWarnings("unchecked")
     public <T extends Node & ValueNumberable> T unique(T node) {
         assert checkValueNumberable(node);
+        return uniqueHelper(node);
+    }
 
-        for (Node input : node.inputs()) {
-            if (input != null) {
-                for (Node usage : input.usages()) {
-                    if (usage != node && node.getNodeClass().valueEqual(node, usage) && node.getNodeClass().edgesEqual(node, usage)) {
-                        return (T) usage;
-                    }
-                }
-                return add(node);
+    @SuppressWarnings("unchecked")
+    <T extends Node> T uniqueHelper(T node) {
+        assert node.getNodeClass().valueNumberable();
+        Node other = this.findDuplicate(node);
+        if (other != null) {
+            return (T) other;
+        } else {
+            Node result = addHelper(node);
+            if (node.getNodeClass().isLeafNode()) {
+                putNodeIntoCache(result);
             }
-        }
-        Node cachedNode = cachedNodes.get(new CacheEntry(node));
-        if (cachedNode != null && cachedNode.isAlive()) {
-            return (T) cachedNode;
-        } else {
-            Node result = add(node);
-            cachedNodes.put(new CacheEntry(node), result);
             return (T) result;
         }
     }
 
+    void putNodeIntoCache(Node node) {
+        assert node.graph() == this || node.graph() == null;
+        assert node.getNodeClass().valueNumberable();
+        assert node.getNodeClass().isLeafNode() : node.getClass();
+        cachedNodes.put(new CacheEntry(node), node);
+    }
+
+    Node findNodeInCache(Node node) {
+        CacheEntry key = new CacheEntry(node);
+        Node result = cachedNodes.get(key);
+        if (result != null && result.isDeleted()) {
+            cachedNodes.remove(key);
+            return null;
+        }
+        return result;
+    }
+
     public Node findDuplicate(Node node) {
-        if (node.getNodeClass().valueNumberable()) {
+        NodeClass nodeClass = node.getNodeClass();
+        assert nodeClass.valueNumberable();
+        if (nodeClass.isLeafNode()) {
+            Node cachedNode = findNodeInCache(node);
+            if (cachedNode != null) {
+                return cachedNode;
+            } else {
+                return null;
+            }
+        } else {
+
+            int minCount = Integer.MAX_VALUE;
+            Node minCountNode = null;
             for (Node input : node.inputs()) {
                 if (input != null) {
-                    for (Node usage : input.usages()) {
-                        if (usage != node && node.getNodeClass().valueEqual(node, usage) && node.getNodeClass().edgesEqual(node, usage)) {
-                            return usage;
-                        }
+                    int estimate = input.getUsageCountUpperBound();
+                    if (estimate == 0) {
+                        return null;
+                    } else if (estimate < minCount) {
+                        minCount = estimate;
+                        minCountNode = input;
                     }
-                    return null;
                 }
             }
-        }
-        CacheEntry key = new CacheEntry(node);
-        Node cachedNode = cachedNodes.get(key);
-        if (cachedNode != null) {
-            if (!cachedNode.isAlive()) {
-                cachedNodes.remove(key);
+            if (minCountNode != null) {
+                for (Node usage : minCountNode.usages()) {
+                    if (usage != node && nodeClass == usage.getNodeClass() && nodeClass.valueEqual(node, usage) && nodeClass.edgesEqual(node, usage)) {
+                        return usage;
+                    }
+                }
                 return null;
             }
-            return cachedNode != node ? cachedNode : null;
-        } else {
-            cachedNodes.put(key, node);
             return null;
         }
     }
@@ -319,6 +390,10 @@
         return true;
     }
 
+    public boolean isNew(int mark, Node node) {
+        return node.id >= mark;
+    }
+
     /**
      * Gets a mark that can be used with {@link #getNewNodes(int)}.
      */
@@ -518,7 +593,7 @@
      * {@code type}.
      * 
      * @param type the type of node to return
-     * @return an {@link Iterable} providing all the matching nodes.
+     * @return an {@link Iterable} providing all the matching nodes
      */
     public <T extends Node & IterableNodeType> NodeIterable<T> getNodes(final Class<T> type) {
         final NodeClass nodeClass = NodeClass.get(type);
@@ -671,14 +746,14 @@
      * @param replacementsMap the replacement map (can be null if no replacement is to be performed)
      * @return a map which associates the original nodes from {@code nodes} to their duplicates
      */
-    public Map<Node, Node> addDuplicates(Iterable<Node> newNodes, Map<Node, Node> replacementsMap) {
+    public Map<Node, Node> addDuplicates(Iterable<Node> newNodes, final Graph oldGraph, int estimatedNodeCount, Map<Node, Node> replacementsMap) {
         DuplicationReplacement replacements;
         if (replacementsMap == null) {
             replacements = null;
         } else {
             replacements = new MapReplacement(replacementsMap);
         }
-        return addDuplicates(newNodes, replacements);
+        return addDuplicates(newNodes, oldGraph, estimatedNodeCount, replacements);
     }
 
     public interface DuplicationReplacement {
@@ -702,19 +777,8 @@
 
     }
 
-    private static final DuplicationReplacement NO_REPLACEMENT = new DuplicationReplacement() {
-
-        @Override
-        public Node replacement(Node original) {
-            return original;
-        }
-    };
-
     @SuppressWarnings("all")
-    public Map<Node, Node> addDuplicates(Iterable<Node> newNodes, DuplicationReplacement replacements) {
-        if (replacements == null) {
-            replacements = NO_REPLACEMENT;
-        }
-        return NodeClass.addGraphDuplicate(this, newNodes, replacements);
+    public Map<Node, Node> addDuplicates(Iterable<Node> newNodes, final Graph oldGraph, int estimatedNodeCount, DuplicationReplacement replacements) {
+        return NodeClass.addGraphDuplicate(this, oldGraph, estimatedNodeCount, newNodes, replacements);
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/IterableNodeType.java	Wed Oct 02 13:26:31 2013 +0200
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2013, 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.graph;
+
+/**
+ * A marker for a node type supporting {@linkplain Graph#getNodes(Class) fast iteration} of its
+ * instances in a graph. The support for fast iteration comes with a memory cost (e.g., extra data
+ * structures {@link Graph}) so only node types for which fast iteration provides a compilation
+ * performance benefit should implement this interface.
+ */
+public interface IterableNodeType {
+}
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Node.java	Wed Oct 02 13:26:31 2013 +0200
@@ -104,6 +104,9 @@
         /**
          * Determines if the stamp of the instantiated intrinsic node has its stamp set from the
          * return type of the annotated method.
+         * <p>
+         * When it is set to true, the stamp that is passed in to the constructor of ValueNode is
+         * ignored and can therefore safely be {@code null}.
          */
         boolean setStampFromReturnType() default false;
     }
@@ -111,9 +114,6 @@
     public interface ValueNumberable {
     }
 
-    public interface IterableNodeType {
-    }
-
     private Graph graph;
     int id;
 
@@ -240,6 +240,16 @@
         }
     }
 
+    int getUsageCountUpperBound() {
+        if (usage0 == null) {
+            return 0;
+        }
+        if (usage1 == null) {
+            return 1;
+        }
+        return 2 + extraUsages.length;
+    }
+
     /**
      * Gets the list of nodes that use this node (e.g., as an input).
      */
@@ -423,15 +433,15 @@
                 assert assertTrue(result, "not found in usages, old input: %s", oldInput);
             }
             if (newInput != null) {
-                NodeChangedListener inputChanged = graph.inputChanged;
-                if (inputChanged != null) {
-                    inputChanged.nodeChanged(this);
+                NodeChangedListener listener = graph.inputChangedListener;
+                if (listener != null) {
+                    listener.nodeChanged(this);
                 }
                 newInput.addUsage(this);
             } else if (oldInput != null && oldInput.usages().isEmpty()) {
-                NodeChangedListener nodeChangedListener = graph.usagesDroppedZero;
-                if (nodeChangedListener != null) {
-                    nodeChangedListener.nodeChanged(oldInput);
+                NodeChangedListener listener = graph.usagesDroppedToZeroListener;
+                if (listener != null) {
+                    listener.nodeChanged(oldInput);
                 }
             }
         }
@@ -449,7 +459,7 @@
                 oldSuccessor.predecessor = null;
             }
             if (newSuccessor != null) {
-                assert assertTrue(newSuccessor.predecessor == null, "unexpected non-null predecessor in new successor (%s): %s", newSuccessor, newSuccessor.predecessor);
+                assert assertTrue(newSuccessor.predecessor == null, "unexpected non-null predecessor in new successor (%s): %s, this=%s", newSuccessor, newSuccessor.predecessor, this);
                 newSuccessor.predecessor = this;
             }
         }
@@ -485,9 +495,9 @@
             boolean result = usage.getNodeClass().replaceFirstInput(usage, this, other);
             assert assertTrue(result, "not found in inputs, usage: %s", usage);
             if (other != null) {
-                NodeChangedListener inputChanged = graph.inputChanged;
-                if (inputChanged != null) {
-                    inputChanged.nodeChanged(usage);
+                NodeChangedListener listener = graph.inputChangedListener;
+                if (listener != null) {
+                    listener.nodeChanged(usage);
                 }
                 other.addUsage(usage);
             }
@@ -532,9 +542,9 @@
         for (Node input : inputs()) {
             removeThisFromUsages(input);
             if (input.usages().isEmpty()) {
-                NodeChangedListener nodeChangedListener = graph.usagesDroppedZero;
-                if (nodeChangedListener != null) {
-                    nodeChangedListener.nodeChanged(input);
+                NodeChangedListener listener = graph.usagesDroppedToZeroListener;
+                if (listener != null) {
+                    listener.nodeChanged(input);
                 }
             }
         }
@@ -584,15 +594,31 @@
         return newNode;
     }
 
-    public Node clone(Graph into) {
+    static int count = 0;
+
+    public final Node clone(Graph into) {
+        return clone(into, true);
+    }
+
+    final Node clone(Graph into, boolean clearInputsAndSuccessors) {
+        NodeClass nodeClass = getNodeClass();
+        if (nodeClass.valueNumberable() && nodeClass.isLeafNode()) {
+            Node otherNode = into.findNodeInCache(this);
+            if (otherNode != null) {
+                return otherNode;
+            }
+        }
+
         Node newNode = null;
         try {
             newNode = (Node) this.clone();
         } catch (CloneNotSupportedException e) {
             throw new GraalInternalError(e).addContext(this);
         }
-        getNodeClass().clearInputs(newNode);
-        getNodeClass().clearSuccessors(newNode);
+        if (clearInputsAndSuccessors) {
+            nodeClass.clearInputs(newNode);
+            nodeClass.clearSuccessors(newNode);
+        }
         newNode.graph = into;
         newNode.typeCacheNext = null;
         newNode.id = INITIAL_ID;
@@ -601,9 +627,17 @@
         newNode.usage1 = null;
         newNode.extraUsages = NO_NODES;
         newNode.predecessor = null;
+
+        if (nodeClass.valueNumberable() && nodeClass.isLeafNode()) {
+            into.putNodeIntoCache(newNode);
+        }
+        newNode.afterClone(this);
         return newNode;
     }
 
+    protected void afterClone(@SuppressWarnings("unused") Node other) {
+    }
+
     public boolean verify() {
         assertTrue(isAlive(), "cannot verify inactive nodes (id=%d)", id);
         assertTrue(graph() != null, "null graph");
@@ -779,6 +813,7 @@
 
         boolean neighborsAlternate = ((flags & FormattableFlags.LEFT_JUSTIFY) == FormattableFlags.LEFT_JUSTIFY);
         int neighborsFlags = (neighborsAlternate ? FormattableFlags.ALTERNATE | FormattableFlags.LEFT_JUSTIFY : 0);
+        NodeClass nodeClass = getNodeClass();
         if (width > 0) {
             if (this.predecessor != null) {
                 formatter.format(" pred={");
@@ -789,10 +824,10 @@
             NodeClassIterator inputIter = inputs().iterator();
             while (inputIter.hasNext()) {
                 Position position = inputIter.nextPosition();
-                Node input = getNodeClass().get(this, position);
+                Node input = nodeClass.get(this, position);
                 if (input != null) {
                     formatter.format(" ");
-                    formatter.format(getNodeClass().getName(position));
+                    formatter.format(nodeClass.getName(position));
                     formatter.format("={");
                     input.formatTo(formatter, neighborsFlags, width - 1, 0);
                     formatter.format("}");
@@ -817,10 +852,10 @@
             NodeClassIterator succIter = successors().iterator();
             while (succIter.hasNext()) {
                 Position position = succIter.nextPosition();
-                Node successor = getNodeClass().get(this, position);
+                Node successor = nodeClass.get(this, position);
                 if (successor != null) {
                     formatter.format(" ");
-                    formatter.format(getNodeClass().getName(position));
+                    formatter.format(nodeClass.getName(position));
                     formatter.format("={");
                     successor.formatTo(formatter, neighborsFlags, 0, precision - 1);
                     formatter.format("}");
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeClass.java	Wed Oct 02 13:26:31 2013 +0200
@@ -26,12 +26,11 @@
 
 import java.lang.reflect.*;
 import java.util.*;
-import java.util.Map.Entry;
 import java.util.concurrent.*;
 
+import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.Graph.DuplicationReplacement;
 import com.oracle.graal.graph.Node.Input;
-import com.oracle.graal.graph.Node.IterableNodeType;
 import com.oracle.graal.graph.Node.Successor;
 import com.oracle.graal.graph.Node.Verbosity;
 
@@ -139,12 +138,16 @@
     private final long[] successorOffsets;
     private final Class<?>[] dataTypes;
     private final boolean canGVN;
+    private final boolean isLeafNode;
     private final int startGVNNumber;
     private final String shortName;
     private final String nameTemplate;
     private final int iterableId;
     private int[] iterableIds;
 
+    private static final DebugMetric ITERABLE_NODE_TYPES = Debug.metric("IterableNodeTypes");
+    private final DebugMetric nodeIterableCount;
+
     private NodeClass(Class<?> clazz) {
         super(clazz);
         assert NODE_CLASS.isAssignableFrom(clazz);
@@ -185,14 +188,15 @@
         }
         this.nameTemplate = newNameTemplate == null ? newShortName : newNameTemplate;
         this.shortName = newShortName;
-        if (Node.IterableNodeType.class.isAssignableFrom(clazz)) {
+        if (IterableNodeType.class.isAssignableFrom(clazz)) {
+            ITERABLE_NODE_TYPES.increment();
             this.iterableId = nextIterableId++;
             List<NodeClass> existingClasses = new LinkedList<>();
             for (FieldIntrospection nodeClass : allClasses.values()) {
                 if (clazz.isAssignableFrom(nodeClass.clazz)) {
                     existingClasses.add((NodeClass) nodeClass);
                 }
-                if (nodeClass.clazz.isAssignableFrom(clazz) && Node.IterableNodeType.class.isAssignableFrom(nodeClass.clazz)) {
+                if (nodeClass.clazz.isAssignableFrom(clazz) && IterableNodeType.class.isAssignableFrom(nodeClass.clazz)) {
                     NodeClass superNodeClass = (NodeClass) nodeClass;
                     superNodeClass.iterableIds = Arrays.copyOf(superNodeClass.iterableIds, superNodeClass.iterableIds.length + 1);
                     superNodeClass.iterableIds[superNodeClass.iterableIds.length - 1] = this.iterableId;
@@ -209,6 +213,9 @@
             this.iterableId = NOT_ITERABLE;
             this.iterableIds = null;
         }
+
+        isLeafNode = (this.inputOffsets.length == 0 && this.successorOffsets.length == 0);
+        nodeIterableCount = Debug.metric("NodeIterable_" + shortName);
     }
 
     @Override
@@ -236,6 +243,7 @@
     }
 
     public int[] iterableIds() {
+        nodeIterableCount.increment();
         return iterableIds;
     }
 
@@ -247,6 +255,10 @@
         return canGVN;
     }
 
+    public boolean isLeafNode() {
+        return isLeafNode;
+    }
+
     public static int cacheSize() {
         return nextIterableId;
     }
@@ -417,6 +429,7 @@
      */
     public static final class NodeClassIterator implements Iterator<Node> {
 
+        private final NodeClass nodeClass;
         private final Node node;
         private final int modCount;
         private final int directCount;
@@ -434,6 +447,7 @@
          */
         private NodeClassIterator(Node node, long[] offsets, int directCount) {
             this.node = node;
+            this.nodeClass = node.getNodeClass();
             this.modCount = MODIFICATION_COUNTS_ENABLED ? node.modCount() : 0;
             this.offsets = offsets;
             this.directCount = directCount;
@@ -500,9 +514,9 @@
         public Position nextPosition() {
             try {
                 if (index < directCount) {
-                    return new Position(offsets == node.getNodeClass().inputOffsets, index, NOT_ITERABLE);
+                    return new Position(offsets == nodeClass.inputOffsets, index, NOT_ITERABLE);
                 } else {
-                    return new Position(offsets == node.getNodeClass().inputOffsets, index, subIndex);
+                    return new Position(offsets == nodeClass.inputOffsets, index, subIndex);
                 }
             } finally {
                 forward();
@@ -581,7 +595,7 @@
     }
 
     public boolean valueEqual(Node a, Node b) {
-        if (!canGVN || a.getNodeClass() != b.getNodeClass()) {
+        if (!canGVN || a.getClass() != b.getClass()) {
             return a == b;
         }
         for (int i = 0; i < dataOffsets.length; ++i) {
@@ -659,6 +673,84 @@
         return fieldNames.get(pos.input ? inputOffsets[pos.index] : successorOffsets[pos.index]);
     }
 
+    void updateInputSuccInPlace(Node node, InplaceUpdateClosure duplicationReplacement) {
+        int index = 0;
+        while (index < directInputCount) {
+            Node input = getNode(node, inputOffsets[index]);
+            if (input != null) {
+                Node newInput = duplicationReplacement.replacement(input, true);
+                node.updateUsages(null, newInput);
+                putNode(node, inputOffsets[index], newInput);
+            }
+            index++;
+        }
+
+        if (index < inputOffsets.length) {
+            updateInputLists(node, duplicationReplacement, index);
+        }
+
+        index = 0;
+        while (index < directSuccessorCount) {
+            Node successor = getNode(node, successorOffsets[index]);
+            if (successor != null) {
+                Node newSucc = duplicationReplacement.replacement(successor, false);
+                node.updatePredecessor(null, newSucc);
+                putNode(node, successorOffsets[index], newSucc);
+            }
+            index++;
+        }
+
+        if (index < successorOffsets.length) {
+            updateSuccLists(node, duplicationReplacement, index);
+        }
+    }
+
+    private void updateInputLists(Node node, InplaceUpdateClosure duplicationReplacement, int startIndex) {
+        int index = startIndex;
+        while (index < inputOffsets.length) {
+            NodeList<Node> list = getNodeList(node, inputOffsets[index]);
+            putNodeList(node, inputOffsets[index], updateInputListCopy(list, node, duplicationReplacement));
+            assert list != null : clazz;
+            index++;
+        }
+    }
+
+    private void updateSuccLists(Node node, InplaceUpdateClosure duplicationReplacement, int startIndex) {
+        int index = startIndex;
+        while (index < successorOffsets.length) {
+            NodeList<Node> list = getNodeList(node, successorOffsets[index]);
+            putNodeList(node, successorOffsets[index], updateSuccListCopy(list, node, duplicationReplacement));
+            assert list != null : clazz;
+            index++;
+        }
+    }
+
+    private static NodeInputList<Node> updateInputListCopy(NodeList<Node> list, Node node, InplaceUpdateClosure duplicationReplacement) {
+        int size = list.size();
+        NodeInputList<Node> result = new NodeInputList<>(node, size);
+        for (int i = 0; i < list.count(); ++i) {
+            Node oldNode = list.get(i);
+            if (oldNode != null) {
+                Node newNode = duplicationReplacement.replacement(oldNode, true);
+                result.set(i, newNode);
+            }
+        }
+        return result;
+    }
+
+    private static NodeSuccessorList<Node> updateSuccListCopy(NodeList<Node> list, Node node, InplaceUpdateClosure duplicationReplacement) {
+        int size = list.size();
+        NodeSuccessorList<Node> result = new NodeSuccessorList<>(node, size);
+        for (int i = 0; i < list.count(); ++i) {
+            Node oldNode = list.get(i);
+            if (oldNode != null) {
+                Node newNode = duplicationReplacement.replacement(oldNode, false);
+                result.set(i, newNode);
+            }
+        }
+        return result;
+    }
+
     public void set(Node node, Position pos, Node x) {
         long offset = pos.input ? inputOffsets[pos.index] : successorOffsets[pos.index];
         if (pos.subIndex == NOT_ITERABLE) {
@@ -955,78 +1047,113 @@
         return nameTemplate;
     }
 
-    static Map<Node, Node> addGraphDuplicate(Graph graph, Iterable<Node> nodes, DuplicationReplacement replacements) {
-        Map<Node, Node> newNodes = new IdentityHashMap<>();
-        Map<Node, Node> replacementsMap = new IdentityHashMap<>();
-        // create node duplicates
+    interface InplaceUpdateClosure {
+
+        Node replacement(Node node, boolean isInput);
+    }
+
+    static Map<Node, Node> addGraphDuplicate(final Graph graph, final Graph oldGraph, int estimatedNodeCount, Iterable<Node> nodes, final DuplicationReplacement replacements) {
+        final Map<Node, Node> newNodes = (estimatedNodeCount > (oldGraph.getNodeCount() + oldGraph.getDeletedNodeCount() >> 4)) ? new NodeNodeMap(oldGraph) : new IdentityHashMap<Node, Node>();
+        createNodeDuplicates(graph, nodes, replacements, newNodes);
+
+        InplaceUpdateClosure replacementClosure = new InplaceUpdateClosure() {
+
+            public Node replacement(Node node, boolean isInput) {
+                Node target = newNodes.get(node);
+                if (target == null) {
+                    Node replacement = node;
+                    if (replacements != null) {
+                        replacement = replacements.replacement(node);
+                    }
+                    if (replacement != node) {
+                        target = replacement;
+                    } else if (node.graph() == graph && isInput) {
+                        // patch to the outer world
+                        target = node;
+                    }
+
+                }
+                return target;
+            }
+
+        };
+
+        // re-wire inputs
+        for (Node oldNode : nodes) {
+            Node node = newNodes.get(oldNode);
+            NodeClass oldNodeClass = oldNode.getNodeClass();
+            NodeClass nodeClass = node.getNodeClass();
+            if (replacements == null || replacements.replacement(oldNode) == oldNode) {
+                nodeClass.updateInputSuccInPlace(node, replacementClosure);
+            } else {
+                transferValuesDifferentNodeClass(graph, replacements, newNodes, oldNode, node, oldNodeClass, nodeClass);
+            }
+        }
+
+        return newNodes;
+    }
+
+    private static void createNodeDuplicates(final Graph graph, Iterable<Node> nodes, final DuplicationReplacement replacements, final Map<Node, Node> newNodes) {
         for (Node node : nodes) {
             if (node != null) {
                 assert !node.isDeleted() : "trying to duplicate deleted node: " + node;
-                Node replacement = replacements.replacement(node);
+                Node replacement = node;
+                if (replacements != null) {
+                    replacement = replacements.replacement(node);
+                }
                 if (replacement != node) {
                     assert replacement != null;
                     newNodes.put(node, replacement);
                 } else {
-                    Node newNode = node.clone(graph);
+                    Node newNode = node.clone(graph, false);
+                    assert newNode.usages().count() == 0 || newNode.inputs().count() == 0;
                     assert newNode.getClass() == node.getClass();
                     newNodes.put(node, newNode);
                 }
             }
         }
-        // re-wire inputs
-        for (Entry<Node, Node> entry : newNodes.entrySet()) {
-            Node oldNode = entry.getKey();
-            Node node = entry.getValue();
-            for (NodeClassIterator iter = oldNode.inputs().iterator(); iter.hasNext();) {
-                Position pos = iter.nextPosition();
-                if (!pos.isValidFor(node, oldNode)) {
-                    continue;
+    }
+
+    private static void transferValuesDifferentNodeClass(final Graph graph, final DuplicationReplacement replacements, final Map<Node, Node> newNodes, Node oldNode, Node node, NodeClass oldNodeClass,
+                    NodeClass nodeClass) {
+        for (NodeClassIterator iter = oldNode.inputs().iterator(); iter.hasNext();) {
+            Position pos = iter.nextPosition();
+            if (!nodeClass.isValid(pos, oldNodeClass)) {
+                continue;
+            }
+            Node input = oldNodeClass.get(oldNode, pos);
+            Node target = newNodes.get(input);
+            if (target == null) {
+                Node replacement = input;
+                if (replacements != null) {
+                    replacement = replacements.replacement(input);
                 }
-                Node input = oldNode.getNodeClass().get(oldNode, pos);
-                Node target = newNodes.get(input);
-                if (target == null) {
-                    target = replacementsMap.get(input);
-                    if (target == null) {
-                        Node replacement = replacements.replacement(input);
-                        if (replacement != input) {
-                            replacementsMap.put(input, replacement);
-                            assert isAssignable(node.getNodeClass().fieldTypes.get(node.getNodeClass().inputOffsets[pos.index]), replacement);
-                            target = replacement;
-                        } else if (input.graph() == graph) { // patch to the outer world
-                            target = input;
-                        }
-                    }
+                if (replacement != input) {
+                    assert isAssignable(nodeClass.fieldTypes.get(nodeClass.inputOffsets[pos.index]), replacement);
+                    target = replacement;
+                } else if (input.graph() == graph) { // patch to the outer world
+                    target = input;
                 }
-                node.getNodeClass().set(node, pos, target);
             }
+            nodeClass.set(node, pos, target);
         }
 
-        // re-wire successors
-        for (Entry<Node, Node> entry : newNodes.entrySet()) {
-            Node oldNode = entry.getKey();
-            Node node = entry.getValue();
-            for (NodeClassIterator iter = oldNode.successors().iterator(); iter.hasNext();) {
-                Position pos = iter.nextPosition();
-                if (!pos.isValidFor(node, oldNode)) {
-                    continue;
+        for (NodeClassIterator iter = oldNode.successors().iterator(); iter.hasNext();) {
+            Position pos = iter.nextPosition();
+            if (!nodeClass.isValid(pos, oldNodeClass)) {
+                continue;
+            }
+            Node succ = oldNodeClass.get(oldNode, pos);
+            Node target = newNodes.get(succ);
+            if (target == null) {
+                Node replacement = replacements.replacement(succ);
+                if (replacement != succ) {
+                    assert isAssignable(nodeClass.fieldTypes.get(node.getNodeClass().successorOffsets[pos.index]), replacement);
+                    target = replacement;
                 }
-                Node succ = oldNode.getNodeClass().get(oldNode, pos);
-                Node target = newNodes.get(succ);
-                if (target == null) {
-                    target = replacementsMap.get(succ);
-                    if (target == null) {
-                        Node replacement = replacements.replacement(succ);
-                        if (replacement != succ) {
-                            replacementsMap.put(succ, replacement);
-                            assert isAssignable(node.getNodeClass().fieldTypes.get(node.getNodeClass().successorOffsets[pos.index]), replacement);
-                            target = replacement;
-                        }
-                    }
-                }
-                node.getNodeClass().set(node, pos, target);
             }
+            nodeClass.set(node, pos, target);
         }
-        return newNodes;
     }
 
     private static boolean isAssignable(Class<?> fieldType, Node replacement) {
--- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeMap.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeMap.java	Wed Oct 02 13:26:31 2013 +0200
@@ -26,11 +26,11 @@
 import java.util.*;
 import java.util.Map.Entry;
 
-public final class NodeMap<T> {
+public class NodeMap<T> {
 
     private final Graph graph;
     private final boolean autogrow;
-    private Object[] values;
+    protected Object[] values;
 
     public NodeMap(Graph graph) {
         this(graph, false);
@@ -54,6 +54,29 @@
         return (T) values[node.id()];
     }
 
+    public boolean isEmpty() {
+        return !entries().iterator().hasNext();
+    }
+
+    public boolean containsKey(Object key) {
+        if (key instanceof Node) {
+            Node node = (Node) key;
+            if (node.graph() == graph()) {
+                return get(node) != null;
+            }
+        }
+        return false;
+    }
+
+    public boolean containsValue(Object value) {
+        for (Object o : values) {
+            if (o == value) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     public Graph graph() {
         return graph;
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeNodeMap.java	Wed Oct 02 13:26:31 2013 +0200
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2011, 2011, 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.graph;
+
+import java.util.*;
+
+public final class NodeNodeMap extends NodeMap<Node> implements Map<Node, Node> {
+
+    public NodeNodeMap(Graph graph) {
+        super(graph, true);
+    }
+
+    public NodeNodeMap(NodeNodeMap copyFrom) {
+        super(copyFrom);
+    }
+
+    public Node get(Object key) {
+        return super.get((Node) key);
+    }
+
+    public Node put(Node key, Node value) {
+        Node oldValue = super.get(key);
+        super.set(key, value);
+        return oldValue;
+    }
+
+    public Node remove(Object key) {
+        throw new UnsupportedOperationException("Cannot remove keys from this map");
+    }
+
+    public void putAll(Map<? extends Node, ? extends Node> m) {
+        for (Entry<? extends Node, ? extends Node> entry : m.entrySet()) {
+            put(entry.getKey(), entry.getValue());
+        }
+    }
+
+    public Set<Node> keySet() {
+        throw new UnsupportedOperationException("Cannot get key set from this map");
+    }
+
+    public Collection<Node> values() {
+        ArrayList<Node> result = new ArrayList<>(this.size());
+        for (int i = 0; i < values.length; ++i) {
+            Object v = values[i];
+            if (v != null) {
+                result.add((Node) v);
+            }
+        }
+        return result;
+    }
+
+    public Set<java.util.Map.Entry<Node, Node>> entrySet() {
+        throw new UnsupportedOperationException("Cannot get entry set for this map");
+    }
+}
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DeoptimizeOp.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DeoptimizeOp.java	Wed Oct 02 13:26:31 2013 +0200
@@ -23,12 +23,8 @@
 package com.oracle.graal.hotspot.amd64;
 
 import static com.oracle.graal.hotspot.HotSpotBackend.*;
-import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
-import com.oracle.graal.hotspot.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
@@ -36,21 +32,14 @@
 @Opcode("DEOPT")
 final class AMD64DeoptimizeOp extends AMD64LIRInstruction {
 
-    private DeoptimizationAction action;
-    private DeoptimizationReason reason;
     @State private LIRFrameState info;
 
-    AMD64DeoptimizeOp(DeoptimizationAction action, DeoptimizationReason reason, LIRFrameState info) {
-        this.action = action;
-        this.reason = reason;
+    AMD64DeoptimizeOp(LIRFrameState info) {
         this.info = info;
     }
 
     @Override
     public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
-        HotSpotGraalRuntime runtime = graalRuntime();
-        Register thread = runtime.getRuntime().threadRegister();
-        masm.movl(new AMD64Address(thread, runtime.getConfig().pendingDeoptimizationOffset), tasm.runtime.encodeDeoptActionAndReason(action, reason));
         AMD64Call.directCall(tasm, masm, tasm.runtime.lookupForeignCall(UNCOMMON_TRAP), null, false, info);
     }
 }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Wed Oct 02 13:26:31 2013 +0200
@@ -63,6 +63,11 @@
     }
 
     @Override
+    public boolean shouldAllocateRegisters() {
+        return true;
+    }
+
+    @Override
     public FrameMap newFrameMap() {
         return new AMD64FrameMap(runtime(), target, runtime().lookupRegisterConfig());
     }
@@ -231,11 +236,10 @@
         FrameMap frameMap = tasm.frameMap;
         RegisterConfig regConfig = frameMap.registerConfig;
         HotSpotVMConfig config = runtime().config;
-        Label unverifiedStub = installedCodeOwner == null || isStatic(installedCodeOwner.getModifiers()) ? null : new Label();
+        Label verifiedStub = new Label();
 
         // Emit the prefix
-
-        if (unverifiedStub != null) {
+        if (installedCodeOwner != null && !isStatic(installedCodeOwner.getModifiers())) {
             tasm.recordMark(Marks.MARK_UNVERIFIED_ENTRY);
             CallingConvention cc = regConfig.getCallingConvention(JavaCallee, null, new JavaType[]{runtime().lookupJavaType(Object.class)}, target, false);
             Register inlineCacheKlass = rax; // see definition of IC_Klass in
@@ -252,11 +256,12 @@
             } else {
                 asm.cmpq(inlineCacheKlass, src);
             }
-            asm.jcc(ConditionFlag.NotEqual, unverifiedStub);
+            AMD64Call.directConditionalJmp(tasm, asm, runtime().lookupForeignCall(IC_MISS_HANDLER), ConditionFlag.NotEqual);
         }
 
         asm.align(config.codeEntryAlignment);
         tasm.recordMark(Marks.MARK_OSR_ENTRY);
+        asm.bind(verifiedStub);
         tasm.recordMark(Marks.MARK_VERIFIED_ENTRY);
 
         // Emit code for the LIR
@@ -273,10 +278,5 @@
             // it has no calls that can cause such "return" entries
             assert !frameMap.accessesCallerFrame() : lirGen.getGraph();
         }
-
-        if (unverifiedStub != null) {
-            asm.bind(unverifiedStub);
-            AMD64Call.directJmp(tasm, asm, runtime().lookupForeignCall(IC_MISS_HANDLER));
-        }
     }
 }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotDeoptimizeCallerOp.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotDeoptimizeCallerOp.java	Wed Oct 02 13:26:31 2013 +0200
@@ -23,12 +23,8 @@
 package com.oracle.graal.hotspot.amd64;
 
 import static com.oracle.graal.hotspot.HotSpotBackend.*;
-import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 
-import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
-import com.oracle.graal.hotspot.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.asm.*;
@@ -39,21 +35,9 @@
 @Opcode("DEOPT_CALLER")
 final class AMD64HotSpotDeoptimizeCallerOp extends AMD64HotSpotEpilogueOp {
 
-    private final DeoptimizationAction action;
-    private final DeoptimizationReason reason;
-
-    AMD64HotSpotDeoptimizeCallerOp(DeoptimizationAction action, DeoptimizationReason reason) {
-        this.action = action;
-        this.reason = reason;
-    }
-
     @Override
     public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
         leaveFrameAndRestoreRbp(tasm, masm);
-
-        HotSpotGraalRuntime runtime = graalRuntime();
-        Register thread = runtime.getRuntime().threadRegister();
-        masm.movl(new AMD64Address(thread, runtime.getConfig().pendingDeoptimizationOffset), tasm.runtime.encodeDeoptActionAndReason(action, reason));
         AMD64Call.directJmp(tasm, masm, tasm.runtime.lookupForeignCall(UNCOMMON_TRAP));
     }
 }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Wed Oct 02 13:26:31 2013 +0200
@@ -25,6 +25,7 @@
 import static com.oracle.graal.amd64.AMD64.*;
 import static com.oracle.graal.api.code.ValueUtil.*;
 import static com.oracle.graal.hotspot.HotSpotBackend.*;
+import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 
 import java.lang.reflect.*;
 import java.util.*;
@@ -36,6 +37,7 @@
 import com.oracle.graal.asm.amd64.AMD64Address.Scale;
 import com.oracle.graal.compiler.amd64.*;
 import com.oracle.graal.compiler.gen.*;
+import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.hotspot.*;
 import com.oracle.graal.hotspot.amd64.AMD64HotSpotMove.CompareAndSwapCompressedOp;
@@ -176,7 +178,7 @@
 
     @Override
     protected void emitReturn(Value input) {
-        append(new AMD64HotSpotReturnOp(input));
+        append(new AMD64HotSpotReturnOp(input, getStub() != null));
     }
 
     @Override
@@ -242,7 +244,7 @@
         Variable result;
 
         if (linkage.canDeoptimize()) {
-            assert info != null;
+            assert info != null || stub != null;
             append(new AMD64HotSpotCRuntimeCallPrologueOp());
             result = super.emitForeignCall(linkage, info, args);
             append(new AMD64HotSpotCRuntimeCallEpilogueOp());
@@ -287,7 +289,7 @@
     @Override
     public void visitSafepointNode(SafepointNode i) {
         LIRFrameState info = state(i);
-        append(new AMD64SafepointOp(info, runtime().config, this));
+        append(new AMD64HotSpotSafepointOp(info, runtime().config, this));
     }
 
     @SuppressWarnings("hiding")
@@ -361,14 +363,29 @@
         append(new AMD64HotSpotUnwindOp(exceptionParameter));
     }
 
+    private void moveDeoptimizationActionAndReasonToThread(Value actionAndReason) {
+        int pendingDeoptimizationOffset = graalRuntime().getConfig().pendingDeoptimizationOffset;
+        RegisterValue thread = runtime().threadRegister().asValue(HotSpotGraalRuntime.wordKind());
+        AMD64AddressValue pendingDeoptAddress = new AMD64AddressValue(actionAndReason.getKind(), thread, pendingDeoptimizationOffset);
+        if (actionAndReason instanceof Constant && !runtime.needsDataPatch((Constant) actionAndReason)) {
+            Constant constantActionAndReason = (Constant) actionAndReason;
+            assert !runtime.needsDataPatch(constantActionAndReason);
+            append(new StoreConstantOp(constantActionAndReason.getKind(), pendingDeoptAddress, constantActionAndReason, null));
+        } else {
+            append(new StoreOp(actionAndReason.getKind(), pendingDeoptAddress, load(actionAndReason), null));
+        }
+    }
+
     @Override
-    public void emitDeoptimize(DeoptimizationAction action, DeoptimizingNode deopting) {
-        append(new AMD64DeoptimizeOp(action, deopting.getDeoptimizationReason(), state(deopting)));
+    public void emitDeoptimize(Value actionAndReason, DeoptimizingNode deopting) {
+        moveDeoptimizationActionAndReasonToThread(actionAndReason);
+        append(new AMD64DeoptimizeOp(state(deopting)));
     }
 
     @Override
     public void emitDeoptimizeCaller(DeoptimizationAction action, DeoptimizationReason reason) {
-        append(new AMD64HotSpotDeoptimizeCallerOp(action, reason));
+        moveDeoptimizationActionAndReasonToThread(runtime.encodeDeoptActionAndReason(action, reason));
+        append(new AMD64HotSpotDeoptimizeCallerOp());
     }
 
     @Override
@@ -522,4 +539,13 @@
         append(new CondMoveOp(result, Condition.EQ, load(Constant.TRUE), Constant.FALSE));
         setResult(node, result);
     }
+
+    @Override
+    public void visitInfopointNode(InfopointNode i) {
+        if (i.getState() != null && i.getState().bci == FrameState.AFTER_BCI) {
+            Debug.log("Ignoring InfopointNode for AFTER_BCI");
+        } else {
+            super.visitInfopointNode(i);
+        }
+    }
 }
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotReturnOp.java	Fri Sep 06 21:37:50 2013 +0200
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotReturnOp.java	Wed Oct 02 13:26:31 2013 +0200
@@ -22,10 +22,16 @@
  */
 package com.oracle.graal.hotspot.amd64;
 
+import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*;
 import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*;
+import static com.oracle.graal.phases.GraalOptions.*;
 
+import com.oracle.graal.amd64.*;
+import com.oracle.graal.api.code.*;
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.asm.amd64.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.hotspot.*;
 import com.oracle.graal.lir.*;
 import com.oracle.graal.lir.asm.*;
 
@@ -36,14 +42,31 @@
 final class AMD64HotSpotReturnOp extends AMD64HotSpotEpilogueOp {
 
     @Use({REG, ILLEGAL}) protected Value value;
+    private final boolean isStub;
 
-    AMD64HotSpotReturnOp(Value value) {
+    AMD64HotSpotReturnOp(Value value, boolean isStub) {
         this.value = value;
+        this.isStub = isStub;
     }
 
+    private static Register findPollOnReturnScratchRegister() {
+        RegisterConfig config = HotSpotGraalRuntime.graalRuntime().getRuntime().lookupRegisterConfig();
+        for (Register r : config.getAllocatableRegisters(Kind.Long)) {
+            if (r != config.getReturnRegister(Kind.Long) && r != AMD64.rbp) {
+                return r;
+            }
+        }
+        throw GraalInternalError.shouldNotReachHere();
+    }
+
+    private static final Register scratchForSafepointOnReturn = findPollOnReturnScratchRegister();
+
     @Override
     public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) {
         leaveFrameAndRestoreRbp(tasm, masm);
+        if (!isStub && (tasm.frameContext != null || !OptEliminateSafepoints.getValue())) {
+            AMD64HotSpotSafepointOp.emitCode(tasm, masm, graalRuntime().getConfig(), true, null, scratchForSafepointOnReturn);
+        }
         masm.ret(0);
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotSafepointOp.java	Wed Oct 02 13:26:31 2013 +0200
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA