changeset 13345:0393767ae0fc

Merge
author Erik Eckstein <erik.eckstein@oracle.com>
date Fri, 13 Dec 2013 16:40:41 +0100
parents e585ac5a385d (diff) e01fe53ec4b7 (current diff)
children f17969ae4a35
files graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java
diffstat 39 files changed, 1553 insertions(+), 200 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ExceptionHandler.java	Fri Dec 13 16:12:29 2013 +0100
+++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ExceptionHandler.java	Fri Dec 13 16:40:41 2013 +0100
@@ -111,4 +111,9 @@
     public String toString() {
         return "ExceptionHandler<startBCI=" + startBCI + ", endBCI=" + endBCI + ", handlerBCI=" + handlerBCI + ", catchTypeCPI=" + catchTypeCPI + ", catchType=" + catchType + ">";
     }
+
+    @Override
+    public int hashCode() {
+        return catchTypeCPI ^ endBCI ^ handlerBCI;
+    }
 }
--- a/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java	Fri Dec 13 16:12:29 2013 +0100
+++ b/graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java	Fri Dec 13 16:40:41 2013 +0100
@@ -1446,6 +1446,14 @@
         emitByte(0x50 | encode);
     }
 
+    public void pushfq() {
+        emitByte(0x9c);
+    }
+
+    public void popfq() {
+        emitByte(0x9D);
+    }
+
     public final void ret(int imm16) {
         if (imm16 == 0) {
             emitByte(0xC3);
@@ -2279,7 +2287,11 @@
         subq(dst, imm32, false);
     }
 
-    public final void subq(Register dst, int imm32, boolean force32Imm) {
+    public final void subqWide(Register dst, int imm32) {
+        subq(dst, imm32, true);
+    }
+
+    private void subq(Register dst, int imm32, boolean force32Imm) {
         prefixqAndEncode(dst.encoding);
         emitArith(0x81, 0xE8, dst, imm32, force32Imm);
     }
--- a/graal/com.oracle.graal.compiler.hsail.test.infra/src/com/oracle/graal/compiler/hsail/test/infra/KernelTester.java	Fri Dec 13 16:12:29 2013 +0100
+++ b/graal/com.oracle.graal.compiler.hsail.test.infra/src/com/oracle/graal/compiler/hsail/test/infra/KernelTester.java	Fri Dec 13 16:40:41 2013 +0100
@@ -280,10 +280,13 @@
     }
 
     /**
-     * This isEqualsFP method allows subclass to override what FP equality means for this particular
-     * unit test.
+     * Tests two floating point values for equality.
      */
     public boolean isEqualsFP(double first, double second) {
+        // Special case for checking whether expected and actual values are both NaNs.
+        if (Double.isNaN(first) && Double.isNaN(second)) {
+            return true;
+        }
         return first == second;
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/DoubleAbsTest.java	Fri Dec 13 16:40:41 2013 +0100
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2009, 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.hsail.test;
+
+import org.junit.Test;
+import com.oracle.graal.compiler.hsail.test.infra.*;
+
+/**
+ * Tests intrinsic for calls to Math.abs(double). Generates a abs_f64 instruction.
+ */
+public class DoubleAbsTest extends GraalKernelTester {
+
+    static final int num = 40;
+    // Output array storing the results of calling Math.abs().
+    @Result protected double[] outArray = new double[num];
+
+    /**
+     * The static "kernel" method we will be testing. This method calls Math.abs() on an element of
+     * an input array and writes the result to the corresponding index of an output array. By
+     * convention the gid is the last parameter.
+     * 
+     * @param out the output array.
+     * @param ina the input array.
+     * @param gid the parameter used to index into the input and output arrays.
+     */
+    public static void run(double[] out, double[] ina, int gid) {
+        out[gid] = Math.abs(ina[gid]);
+    }
+
+    /**
+     * Tests the HSAIL code generated for this unit test by comparing the result of executing this
+     * code with the result of executing a sequential Java version of this unit test.
+     */
+    @Test
+    public void test() {
+        super.testGeneratedHsail();
+    }
+
+    /**
+     * Initializes the input and output arrays passed to the run routine.
+     * 
+     * @param in the input array.
+     */
+    void setupArrays(double[] in) {
+        for (int i = 0; i < num; i++) {
+            // Include positive and negative values as well as corner cases.
+            if (i == 1) {
+                in[i] = Double.NaN;
+            } else if (i == 2) {
+                in[i] = Double.NEGATIVE_INFINITY;
+            } else if (i == 3) {
+                in[i] = Double.POSITIVE_INFINITY;
+            } else if (i == 4) {
+                in[i] = -0.0;
+            } else {
+                in[i] = i < num / 2 ? i : -i;
+            }
+            outArray[i] = 0;
+        }
+    }
+
+    /**
+     * Dispatches the HSAIL kernel for this test case.
+     */
+    @Override
+    public void runTest() {
+        double[] inArray = new double[num];
+        setupArrays(inArray);
+        dispatchMethodKernel(num, outArray, inArray);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/DoubleCeilTest.java	Fri Dec 13 16:40:41 2013 +0100
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2009, 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.hsail.test;
+
+import org.junit.Test;
+import com.oracle.graal.compiler.hsail.test.infra.*;
+
+/**
+ * Tests intrinsic for calls to Math.ceil(). Generates a ceil_f64 instruction.
+ */
+public class DoubleCeilTest extends GraalKernelTester {
+
+    static final int num = 40;
+    // Output array storing the results.
+    @Result protected double[] outArray = new double[num];
+
+    /**
+     * The static "kernel" method we will be testing. This method calls Math.ceil() on an element of
+     * an input array and writes the result to the corresponding index of an output array. By
+     * convention the gid is the last parameter.
+     * 
+     * @param out the output array.
+     * @param ina the input array.
+     * @param gid the parameter used to index into the input and output arrays.
+     */
+    public static void run(double[] out, double[] ina, int gid) {
+        out[gid] = Math.ceil(ina[gid]);
+    }
+
+    /**
+     * Tests the HSAIL code generated for this unit test by comparing the result of executing this
+     * code with the result of executing a sequential Java version of this unit test.
+     */
+    @Test
+    public void test() {
+        super.testGeneratedHsail();
+    }
+
+    /**
+     * Initializes the input and output arrays passed to the run routine.
+     * 
+     * @param in the input array.
+     */
+    void setupArrays(double[] in) {
+        // Initialize arrays with a mix of positive and negativ values and any corner cases.
+        for (int i = 0; i < num; i++) {
+            if (i == 0) {
+                in[i] = 0.0;
+            } else if (i == 1) {
+                in[i] = -0.0;
+            } else if (i == 2) {
+                in[i] = Double.NaN;
+            } else if (i == 3) {
+                in[i] = Double.NEGATIVE_INFINITY;
+            } else if (i == 4) {
+                in[i] = Double.POSITIVE_INFINITY;
+            } else {
+                in[i] = i < num / 2 ? i + 0.5 : -i - 0.5;
+            }
+            outArray[i] = 0;
+        }
+    }
+
+    /**
+     * Dispatches the HSAIL kernel for this test case.
+     */
+    @Override
+    public void runTest() {
+        double[] inArray = new double[num];
+        setupArrays(inArray);
+        dispatchMethodKernel(num, outArray, inArray);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/DoubleFloorTest.java	Fri Dec 13 16:40:41 2013 +0100
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2009, 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.hsail.test;
+
+import org.junit.Test;
+import com.oracle.graal.compiler.hsail.test.infra.*;
+
+/**
+ * Tests intrinsic for calls to Math.floor(). Generates a floor_f64 instruction.
+ */
+public class DoubleFloorTest extends GraalKernelTester {
+
+    static final int num = 40;
+    // Output array storing the results.
+    @Result protected double[] outArray = new double[num];
+
+    /**
+     * The static "kernel" method we will be testing. This method calls Math.floor() on an element
+     * of an input array and writes the result to the corresponding index of an output array. By
+     * convention the gid is the last parameter.
+     * 
+     * @param out the output array.
+     * @param ina the input array.
+     * @param gid the parameter used to index into the input and output arrays.
+     */
+    public static void run(double[] out, double[] ina, int gid) {
+        out[gid] = Math.floor(ina[gid]);
+    }
+
+    /**
+     * Tests the HSAIL code generated for this unit test by comparing the result of executing this
+     * code with the result of executing a sequential Java version of this unit test.
+     */
+    @Test
+    public void test() {
+        super.testGeneratedHsail();
+    }
+
+    /**
+     * Initializes the input and output arrays passed to the run routine.
+     * 
+     * @param in the input array.
+     */
+    void setupArrays(double[] in) {
+        // Initialize input array with a mix of positive and negative values and any corner cases.
+        for (int i = 0; i < num; i++) {
+            if (i == 0) {
+                in[i] = 0.0;
+            } else if (i == 1) {
+                in[i] = -0.0;
+            } else if (i == 2) {
+                in[i] = Double.NaN;
+            } else if (i == 3) {
+                in[i] = Double.NEGATIVE_INFINITY;
+            } else if (i == 4) {
+                in[i] = Double.POSITIVE_INFINITY;
+            } else {
+                in[i] = i < num / 2 ? i + 0.5 : -i - 0.5;
+            }
+            outArray[i] = 0;
+        }
+    }
+
+    /**
+     * Dispatches the HSAIL kernel for this test case.
+     */
+    @Override
+    public void runTest() {
+        double[] inArray = new double[num];
+        setupArrays(inArray);
+        dispatchMethodKernel(num, outArray, inArray);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/DoubleRintTest.java	Fri Dec 13 16:40:41 2013 +0100
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2009, 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.hsail.test;
+
+import org.junit.*;
+
+import com.oracle.graal.compiler.hsail.test.infra.*;
+
+/**
+ * Tests intrinsic for Math.rint(). Generates an rint_f64 instruction.
+ */
+public class DoubleRintTest extends GraalKernelTester {
+
+    static final int size = 64;
+    @Result double[] out = new double[size];
+
+    /**
+     * The static "kernel" method we will be testing. This method calls Math.rint() on an element of
+     * an input array and writes the result to the corresponding index of an output array. By
+     * convention the gid is the last parameter.
+     * 
+     * @param out the output array.
+     * @param in the input array.
+     * @param gid the parameter used to index into the input and output arrays.
+     */
+    public static void run(double[] out, double[] in, int gid) {
+        out[gid] = Math.rint(in[gid]);
+    }
+
+    /**
+     * Initialize input arrays.
+     * 
+     * @param in the input array
+     */
+    void setupArrays(double[] in) {
+        // Initialize input array with a mix of positive and negative values and corner cases.
+        for (int i = 0; i < size; i++) {
+            if (i == 1) {
+                in[i] = Double.NaN;
+            } else if (i == 2) {
+                in[i] = Double.NEGATIVE_INFINITY;
+            } else if (i == 3) {
+                in[i] = Double.POSITIVE_INFINITY;
+
+            } else if (i == 4) {
+                in[i] = 0.0;
+            } else if (i == 5) {
+                in[i] = -0.0;
+            } else {
+                in[i] = i < size / 2 ? i + 0.5 : -i - 0.6;
+            }
+            out[i] = 0;
+        }
+    }
+
+    /**
+     * Dispatches the HSAIL kernel for this test case.
+     */
+    @Override
+    public void runTest() {
+        double[] inArray = new double[size];
+        setupArrays(inArray);
+        dispatchMethodKernel(size, out, inArray);
+    }
+
+    /**
+     * Tests the HSAIL code generated for this unit test by comparing the result of executing this
+     * code with the result of executing a sequential Java version of this unit test.
+     */
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/DoubleSqrtTest.java	Fri Dec 13 16:40:41 2013 +0100
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2009, 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.hsail.test;
+
+import org.junit.*;
+
+import com.oracle.graal.compiler.hsail.test.infra.*;
+
+/**
+ * Tests intrinsic for call to Math.sqrt(double). Generates a sqrt_f64 instruction.
+ */
+public class DoubleSqrtTest extends GraalKernelTester {
+
+    static final int size = 64;
+    @Result double[] out = new double[size];
+
+    /**
+     * The static "kernel" method we will be testing. This method calls Math.sqrt() on an element of
+     * an input array and writes the result to the corresponding index of an output array. By
+     * convention the gid is the last parameter.
+     * 
+     * @param out the output array.
+     * @param in the input array.
+     * @param gid the parameter used to index into the input and output arrays.
+     */
+    public static void run(double[] in, double[] out, int gid) {
+        out[gid] = Math.sqrt(in[gid]);
+    }
+
+    /**
+     * Initializes the input and output arrays passed to the run routine.
+     * 
+     * @param in the input array.
+     */
+    void setupArrays(double[] in) {
+        for (int i = 0; i < size; i++) {
+            // Include positive and negative values as well as corner cases.
+            if (i == 1) {
+                in[i] = Double.NaN;
+            } else if (i == 2) {
+                in[i] = Double.NEGATIVE_INFINITY;
+            } else if (i == 3) {
+                in[i] = Double.POSITIVE_INFINITY;
+            } else if (i == 4) {
+                in[i] = -0.0;
+            } else if (i > 5 && i < 10) {
+                in[i] = i + 0.5;
+            } else {
+                in[i] = i < size / 2 ? i : -i;
+            }
+            out[i] = 0;
+        }
+    }
+
+    /**
+     * Dispatches the HSAIL kernel for this test case.
+     */
+    @Override
+    public void runTest() {
+        double[] inArray = new double[size];
+        setupArrays(inArray);
+        dispatchMethodKernel(size, inArray, out);
+    }
+
+    /**
+     * Tests the HSAIL code generated for this unit test by comparing the result of executing this
+     * code with the result of executing a sequential Java version of this unit test.
+     */
+    @Test
+    public void test() {
+        testGeneratedHsail();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/FloatAbsTest.java	Fri Dec 13 16:40:41 2013 +0100
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2009, 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.hsail.test;
+
+import org.junit.Test;
+import com.oracle.graal.compiler.hsail.test.infra.*;
+
+/**
+ * Tests intrinsic for calls to Math.abs(float). Generates an abs_f32 instruction.
+ */
+public class FloatAbsTest extends GraalKernelTester {
+
+    static final int num = 40;
+    // Output array storing the results of calling Math.abs().
+    @Result protected float[] outArray = new float[num];
+
+    /**
+     * The static "kernel" method we will be testing. This method calls Math.abs() on an element of
+     * an input array and writes the result to the corresponding index of an output array. By
+     * convention the gid is the last parameter.
+     * 
+     * @param out the output array.
+     * @param ina the input array.
+     * @param gid the parameter used to index into the input and output arrays.
+     */
+    public static void run(float[] out, float[] ina, int gid) {
+        out[gid] = Math.abs(ina[gid]);
+    }
+
+    /**
+     * Tests the HSAIL code generated for this unit test by comparing the result of executing this
+     * code with the result of executing a sequential Java version of this unit test.
+     */
+    @Test
+    public void test() {
+        super.testGeneratedHsail();
+    }
+
+    /**
+     * Initializes the input and output arrays passed to the run routine.
+     * 
+     * @param in the input array.
+     */
+    void setupArrays(float[] in) {
+        for (int i = 0; i < num; i++) {
+            // Initialize array with positive and negative values as well as corner cases.
+            if (i == 1) {
+                in[i] = Float.NaN;
+            } else if (i == 2) {
+                in[i] = Float.NEGATIVE_INFINITY;
+            } else if (i == 3) {
+                in[i] = Float.POSITIVE_INFINITY;
+            } else if (i == 4) {
+                in[i] = -0;
+            } else {
+                in[i] = i < num / 2 ? i : -i;
+            }
+            outArray[i] = 0;
+        }
+    }
+
+    /**
+     * Dispatches the HSAIL kernel for this test case.
+     */
+    @Override
+    public void runTest() {
+        float[] inArray = new float[num];
+        setupArrays(inArray);
+        dispatchMethodKernel(num, outArray, inArray);
+    }
+}
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/FloatDivPrecisionTest.java	Fri Dec 13 16:12:29 2013 +0100
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/FloatDivPrecisionTest.java	Fri Dec 13 16:40:41 2013 +0100
@@ -47,10 +47,6 @@
 
     }
 
-    /**
-     * Allows subclass to override what FP equality means for this particular unit test.
-     * 
-     */
     @Override
     public boolean isEqualsFP(double first, double second) {
         return Math.abs(first - second) == 0;
--- a/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/FloatSqrtTest.java	Fri Dec 13 16:12:29 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2009, 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.compiler.hsail.test;
-
-import org.junit.*;
-
-import com.oracle.graal.compiler.hsail.test.infra.*;
-
-/**
- * Tests floating point square root.
- */
-public class FloatSqrtTest extends GraalKernelTester {
-
-    static final int size = 64;
-    float[] input = new float[size];
-    @Result float[] output = new float[size];
-    {
-        for (int i = 0; i < size; i++) {
-            input[i] = i;
-            output[i] = -1.0f;
-        }
-
-    }
-
-    public static void run(float[] input1, float[] output1, int gid) {
-        output1[gid] = (float) Math.sqrt(input1[gid]);
-    }
-
-    @Override
-    public void runTest() {
-        dispatchMethodKernel(size, input, output);
-    }
-
-    @Test
-    public void test() {
-        testGeneratedHsail();
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/IntAbsTest.java	Fri Dec 13 16:40:41 2013 +0100
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2009, 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.hsail.test;
+
+import org.junit.Test;
+import com.oracle.graal.compiler.hsail.test.infra.*;
+
+/**
+ * Tests intrinsic for call to Math.abs(int). Generates an abs_s32 instruction.
+ */
+public class IntAbsTest extends GraalKernelTester {
+
+    static final int num = 20;
+    // Output array storing the results of negation operations.
+    @Result protected int[] outArray = new int[num];
+
+    /**
+     * The static "kernel" method we will be testing. This method calls Math.abs( ) on an element of
+     * an input array and writes the result to the corresponding index of an output array. By
+     * convention the gid is the last parameter.
+     * 
+     * @param out the output array.
+     * @param ina the input array.
+     * @param gid the parameter used to index into the input and output arrays.
+     */
+    public static void run(int[] out, int[] ina, int gid) {
+        out[gid] = Math.abs(ina[gid]);
+    }
+
+    /**
+     * Tests the HSAIL code generated for this unit test by comparing the result of executing this
+     * code with the result of executing a sequential Java version of this unit test.
+     */
+    @Test
+    public void test() {
+        super.testGeneratedHsail();
+    }
+
+    /**
+     * Initializes the input and output arrays passed to the run routine.
+     * 
+     * @param in the input array.
+     */
+    void setupArrays(int[] in) {
+        // initialize input array with a mix of positive and negative values and any corner cases.
+        for (int i = 0; i < num; i++) {
+            if (i == 1) {
+                in[i] = Integer.MIN_VALUE;
+            } else {
+                in[i] = i < num / 2 ? i : -i;
+            }
+            outArray[i] = 0;
+        }
+    }
+
+    /**
+     * Dispatches the HSAIL kernel for this test case.
+     */
+    @Override
+    public void runTest() {
+        int[] inArray = new int[num];
+        setupArrays(inArray);
+        dispatchMethodKernel(num, outArray, inArray);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/LongAbsTest.java	Fri Dec 13 16:40:41 2013 +0100
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2009, 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.hsail.test;
+
+import org.junit.Test;
+import com.oracle.graal.compiler.hsail.test.infra.*;
+
+/**
+ * Tests intrinsic for call to Math.abs(long). Generates an abs_s64 instruction.
+ */
+public class LongAbsTest extends GraalKernelTester {
+
+    static final int num = 20;
+    // Output array storing the results of the operations.
+    @Result protected long[] outArray = new long[num];
+
+    /**
+     * The static "kernel" method we will be testing. This method calls Math.abs( ) on an element of
+     * an input array and writes the result to the corresponding index of an output array. By
+     * convention the gid is the last parameter.
+     * 
+     * @param out the output array.
+     * @param ina the input array.
+     * @param gid the parameter used to index into the input and output arrays.
+     */
+    public static void run(long[] out, long[] ina, int gid) {
+        out[gid] = Math.abs(ina[gid]);
+    }
+
+    /**
+     * Tests the HSAIL code generated for this unit test by comparing the result of executing this
+     * code with the result of executing a sequential Java version of this unit test.
+     */
+    @Test
+    public void test() {
+        super.testGeneratedHsail();
+    }
+
+    /**
+     * Initializes the input and output arrays passed to the run routine.
+     * 
+     * @param in the input array.
+     */
+    void setupArrays(long[] in) {
+        // Initialize input array with a mix of positive and negative values and any corner cases.
+        for (int i = 0; i < num; i++) {
+            if (i == 1) {
+                in[i] = Long.MIN_VALUE;
+            } else {
+                in[i] = i < num / 2 ? i : -i;
+            }
+            outArray[i] = 0;
+        }
+    }
+
+    /**
+     * Dispatches the HSAIL kernel for this test case.
+     */
+    @Override
+    public void runTest() {
+        long[] inArray = new long[num];
+        setupArrays(inArray);
+        dispatchMethodKernel(num, outArray, inArray);
+    }
+}
--- a/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java	Fri Dec 13 16:12:29 2013 +0100
+++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java	Fri Dec 13 16:40:41 2013 +0100
@@ -646,11 +646,61 @@
         throw GraalInternalError.unimplemented();
     }
 
+    /**
+     * Emits the LIR code for the {@link HSAILArithmetic#ABS} operation.
+     * 
+     * @param input the source operand
+     * @return Value representing the result of the operation
+     */
     @Override
     public Value emitMathAbs(Value input) {
-        throw GraalInternalError.unimplemented();
+        Variable result = newVariable(input.getPlatformKind());
+        append(new Op1Stack(ABS, result, input));
+        return result;
+    }
+
+    /**
+     * Emits the LIR code for the {@link HSAILArithmetic#CEIL} operation.
+     * 
+     * @param input the source operand
+     * @return Value representing the result of the operation
+     */
+    public Value emitMathCeil(Value input) {
+        Variable result = newVariable(input.getPlatformKind());
+        append(new Op1Stack(CEIL, result, input));
+        return result;
     }
 
+    /**
+     * Emits the LIR code for the {@link HSAILArithmetic#FLOOR} operation.
+     * 
+     * @param input the source operand
+     * @return Value representing the result of the operation
+     */
+    public Value emitMathFloor(Value input) {
+        Variable result = newVariable(input.getPlatformKind());
+        append(new Op1Stack(FLOOR, result, input));
+        return result;
+    }
+
+    /**
+     * Emits the LIR code for the {@link HSAILArithmetic#RINT} operation.
+     * 
+     * @param input the source operand
+     * @return Value representing the result of the operation
+     */
+    public Value emitMathRint(Value input) {
+        Variable result = newVariable(input.getPlatformKind());
+        append(new Op1Stack(RINT, result, input));
+        return result;
+    }
+
+    /**
+     * Emits the LIR code for the {@link HSAILArithmetic#SQRT} operation.
+     * 
+     * @param input the source operand
+     * @return value representing the result of the operation
+     */
     @Override
     public Value emitMathSqrt(Value input) {
         Variable result = newVariable(input.getPlatformKind());
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CommonedConstantsTest.java	Fri Dec 13 16:40:41 2013 +0100
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.test;
+
+import java.lang.reflect.*;
+
+import org.junit.*;
+
+import com.oracle.graal.api.meta.*;
+
+/**
+ * Tests any optimization that commons loads of non-inlineable constants.
+ */
+public class CommonedConstantsTest extends GraalCompilerTest {
+
+    public static final String[] array = {"1", "2", null};
+
+    // A method where a constant is used on the normal and exception edge of a non-inlined call.
+    // The dominating block of both usages is the block containing the call.
+    public static Object testSnippet(String[] arr, int i) {
+        Object result = null;
+        try {
+            result = Array.get(arr, i);
+        } catch (ArrayIndexOutOfBoundsException e) {
+            result = array[0];
+        }
+        if (result == null) {
+            result = array[2];
+        }
+        return result;
+    }
+
+    @Test
+    public void test0() {
+        // Ensure the exception path is profiled
+        ResolvedJavaMethod javaMethod = getMetaAccess().lookupJavaMethod(getMethod("testSnippet"));
+        javaMethod.reprofile();
+        testSnippet(array, array.length);
+
+        test("testSnippet", array, 0);
+        test("testSnippet", array, 2);
+        test("testSnippet", array, 3);
+        test("testSnippet", array, 1);
+    }
+}
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Fri Dec 13 16:12:29 2013 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Fri Dec 13 16:40:41 2013 +0100
@@ -262,14 +262,13 @@
             for (Block b : lir.linearScanOrder()) {
                 emitBlock(lirGen, b);
             }
+            lirGen.beforeRegisterAllocation();
 
             Debug.dump(lir, "After LIR generation");
         } catch (Throwable e) {
             throw Debug.handle(e);
         }
 
-        lirGen.beforeRegisterAllocation();
-
         try (Scope s = Debug.scope("Allocator")) {
             if (backend.shouldAllocateRegisters()) {
                 new LinearScan(target, lir, lirGen, frameMap).allocate();
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Fri Dec 13 16:12:29 2013 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java	Fri Dec 13 16:40:41 2013 +0100
@@ -42,6 +42,7 @@
 import com.oracle.graal.lir.StandardOp.BlockEndOp;
 import com.oracle.graal.lir.StandardOp.JumpOp;
 import com.oracle.graal.lir.StandardOp.LabelOp;
+import com.oracle.graal.lir.StandardOp.NoOp;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.PhiNode.PhiType;
 import com.oracle.graal.nodes.calc.*;
@@ -82,11 +83,69 @@
     private final boolean printIRWithLIR;
 
     /**
-     * Maps constants the variables within the scope of a single block to avoid loading a constant
+     * Maps constants to variables within the scope of a single block to avoid loading a constant
      * more than once per block.
      */
     private Map<Constant, Variable> constantsLoadedInCurrentBlock;
 
+    /**
+     * Handle for an operation that loads a constant into a variable. The operation starts in the
+     * first block where the constant is used but will eventually be
+     * {@linkplain LIRGenerator#insertConstantLoads() moved} to a block dominating all usages of the
+     * constant.
+     */
+    public static class LoadConstant implements Comparable<LoadConstant> {
+        /**
+         * The index of {@link #op} within {@link #block}'s instruction list or -1 if {@code op} is
+         * to be moved to a dominator block.
+         */
+        int index;
+
+        /**
+         * The operation that loads the constant.
+         */
+        private final LIRInstruction op;
+
+        /**
+         * The block that does or will contain {@link #op}. This is initially the block where the
+         * first usage of the constant is seen during LIR generation.
+         */
+        private Block block;
+
+        /**
+         * The variable into which the constant is loaded.
+         */
+        private final Variable variable;
+
+        public LoadConstant(Variable variable, Block block, int index, LIRInstruction op) {
+            this.variable = variable;
+            this.block = block;
+            this.index = index;
+            this.op = op;
+        }
+
+        /**
+         * Sorts {@link LoadConstant} objects according to their enclosing blocks. This is used to
+         * group loads per block in {@link LIRGenerator#insertConstantLoads()}.
+         */
+        public int compareTo(LoadConstant o) {
+            if (block.getId() < o.block.getId()) {
+                return -1;
+            }
+            if (block.getId() > o.block.getId()) {
+                return 1;
+            }
+            return 0;
+        }
+
+        @Override
+        public String toString() {
+            return block + "#" + op;
+        }
+    }
+
+    private Map<Constant, LoadConstant> constantLoads;
+
     private ValueNode currentInstruction;
     private ValueNode lastInstructionPrinted; // Debugging only
 
@@ -194,6 +253,12 @@
         return operand;
     }
 
+    /**
+     * Controls whether commoning is performed on {@linkplain #canInlineConstant(Constant)
+     * non-inlinable} constants.
+     */
+    private static final boolean CommonConstantLoads = Boolean.parseBoolean(System.getProperty("graal.commonConstantLoads", "true"));
+
     private Value getConstantOperand(ValueNode node) {
         if (!ConstantNodeRecordsUsages) {
             Constant value = node.asConstant();
@@ -202,15 +267,42 @@
                     return !node.isExternal() ? setResult(node, value) : value;
                 } else {
                     Variable loadedValue;
-                    if (constantsLoadedInCurrentBlock == null) {
-                        constantsLoadedInCurrentBlock = new HashMap<>();
-                        loadedValue = null;
+                    if (CommonConstantLoads) {
+                        if (constantLoads == null) {
+                            constantLoads = new HashMap<>();
+                        }
+                        LoadConstant load = constantLoads.get(value);
+                        if (load == null) {
+                            int index = lir.lir(currentBlock).size();
+                            // loadedValue = newVariable(value.getPlatformKind());
+                            loadedValue = emitMove(value);
+                            LIRInstruction op = lir.lir(currentBlock).get(index);
+                            constantLoads.put(value, new LoadConstant(loadedValue, currentBlock, index, op));
+                        } else {
+                            Block dominator = ControlFlowGraph.commonDominator(load.block, currentBlock);
+                            loadedValue = load.variable;
+                            if (dominator != load.block) {
+                                if (load.index >= 0) {
+                                    List<LIRInstruction> instructions = lir.lir(load.block);
+                                    instructions.set(load.index, new NoOp(null, -1));
+                                    load.index = -1;
+                                }
+                            } else {
+                                assert load.block != currentBlock || load.index < lir.lir(currentBlock).size();
+                            }
+                            load.block = dominator;
+                        }
                     } else {
-                        loadedValue = constantsLoadedInCurrentBlock.get(value);
-                    }
-                    if (loadedValue == null) {
-                        loadedValue = emitMove(value);
-                        constantsLoadedInCurrentBlock.put(value, loadedValue);
+                        if (constantsLoadedInCurrentBlock == null) {
+                            constantsLoadedInCurrentBlock = new HashMap<>();
+                            loadedValue = null;
+                        } else {
+                            loadedValue = constantsLoadedInCurrentBlock.get(value);
+                        }
+                        if (loadedValue == null) {
+                            loadedValue = emitMove(value);
+                            constantsLoadedInCurrentBlock.put(value, loadedValue);
+                        }
                     }
                     return loadedValue;
                 }
@@ -808,10 +900,74 @@
 
     @Override
     public void beforeRegisterAllocation() {
+        insertConstantLoads();
     }
 
     /**
-     * Gets an garbage vale for a given kind.
+     * Moves deferred {@linkplain LoadConstant loads} of constants into blocks dominating all usages
+     * of the constant. Any operations inserted into a block are guaranteed to be immediately prior
+     * to the first control flow instruction near the end of the block.
+     */
+    private void insertConstantLoads() {
+        if (constantLoads != null) {
+            // Remove loads where all usages are in the same block.
+            for (Iterator<Map.Entry<Constant, LoadConstant>> iter = constantLoads.entrySet().iterator(); iter.hasNext();) {
+                LoadConstant lc = iter.next().getValue();
+                if (lc.index != -1) {
+                    assert lir.lir(lc.block).get(lc.index) == lc.op;
+                    iter.remove();
+                }
+            }
+            if (constantLoads.isEmpty()) {
+                return;
+            }
+
+            // Sorting groups the loads per block.
+            LoadConstant[] groupedByBlock = constantLoads.values().toArray(new LoadConstant[constantLoads.size()]);
+            Arrays.sort(groupedByBlock);
+
+            int groupBegin = 0;
+            while (true) {
+                int groupEnd = groupBegin + 1;
+                Block block = groupedByBlock[groupBegin].block;
+                while (groupEnd < groupedByBlock.length && groupedByBlock[groupEnd].block == block) {
+                    groupEnd++;
+                }
+                int groupSize = groupEnd - groupBegin;
+
+                List<LIRInstruction> ops = lir.lir(block);
+                int lastIndex = ops.size() - 1;
+                assert ops.get(lastIndex) instanceof BlockEndOp;
+                int insertionIndex = lastIndex;
+                for (int i = Math.max(0, lastIndex - MAX_EXCEPTION_EDGE_OP_DISTANCE_FROM_END); i < lastIndex; i++) {
+                    if (getExceptionEdge(ops.get(i)) != null) {
+                        insertionIndex = i;
+                        break;
+                    }
+                }
+
+                if (groupSize == 1) {
+                    ops.add(insertionIndex, groupedByBlock[groupBegin].op);
+                } else {
+                    assert groupSize > 1;
+                    List<LIRInstruction> moves = new ArrayList<>(groupSize);
+                    for (int i = groupBegin; i < groupEnd; i++) {
+                        moves.add(groupedByBlock[i].op);
+                    }
+                    ops.addAll(insertionIndex, moves);
+                }
+
+                if (groupEnd == groupedByBlock.length) {
+                    break;
+                }
+                groupBegin = groupEnd;
+            }
+            constantLoads = null;
+        }
+    }
+
+    /**
+     * Gets a garbage value for a given kind.
      */
     protected Constant zapValueForKind(PlatformKind kind) {
         long dead = 0xDEADDEADDEADDEADL;
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Fri Dec 13 16:12:29 2013 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java	Fri Dec 13 16:40:41 2013 +0100
@@ -83,8 +83,8 @@
      * @param isVerifiedEntryPoint specifies if the code buffer is currently at the verified entry
      *            point
      */
-    protected static void emitStackOverflowCheck(CompilationResultBuilder crb, int stackShadowPages, boolean afterFrameInit, boolean isVerifiedEntryPoint) {
-        if (stackShadowPages > 0) {
+    protected static void emitStackOverflowCheck(CompilationResultBuilder crb, int pagesToBang, boolean afterFrameInit, boolean isVerifiedEntryPoint) {
+        if (pagesToBang > 0) {
 
             AMD64MacroAssembler asm = (AMD64MacroAssembler) crb.asm;
             int frameSize = crb.frameMap.frameSize();
@@ -92,7 +92,7 @@
                 int lastFramePage = frameSize / unsafe.pageSize();
                 // emit multiple stack bangs for methods with frames larger than a page
                 for (int i = 0; i <= lastFramePage; i++) {
-                    int disp = (i + stackShadowPages) * unsafe.pageSize();
+                    int disp = (i + pagesToBang) * unsafe.pageSize();
                     if (afterFrameInit) {
                         disp -= frameSize;
                     }
@@ -141,12 +141,12 @@
                 }
             } else {
                 int verifiedEntryPointOffset = asm.codeBuffer.position();
-                if (!isStub && stackShadowPages > 0) {
-                    emitStackOverflowCheck(crb, stackShadowPages, false, true);
+                if (!isStub && pagesToBang > 0) {
+                    emitStackOverflowCheck(crb, pagesToBang, false, true);
                     assert asm.codeBuffer.position() - verifiedEntryPointOffset >= PATCHED_VERIFIED_ENTRY_POINT_INSTRUCTION_SIZE;
                 }
                 if (!isStub && asm.codeBuffer.position() == verifiedEntryPointOffset) {
-                    asm.subq(rsp, frameSize, true);
+                    asm.subqWide(rsp, frameSize);
                     assert asm.codeBuffer.position() - verifiedEntryPointOffset >= PATCHED_VERIFIED_ENTRY_POINT_INSTRUCTION_SIZE;
                 } else {
                     asm.decrementq(rsp, frameSize);
@@ -278,7 +278,7 @@
      * @param installedCodeOwner see {@link Backend#emitCode}
      */
     public void emitCodeBody(ResolvedJavaMethod installedCodeOwner, CompilationResultBuilder crb, LIRGenerator lirGen) {
-        lirGen.lir.emitCode(crb);
+        crb.emit(lirGen.lir);
     }
 
     /**
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Fri Dec 13 16:12:29 2013 +0100
+++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Fri Dec 13 16:40:41 2013 +0100
@@ -48,7 +48,7 @@
 import com.oracle.graal.hotspot.nodes.*;
 import com.oracle.graal.hotspot.stubs.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.StandardOp.PlaceholderOp;
+import com.oracle.graal.lir.StandardOp.NoOp;
 import com.oracle.graal.lir.StandardOp.SaveRegistersOp;
 import com.oracle.graal.lir.amd64.*;
 import com.oracle.graal.lir.amd64.AMD64ControlFlow.CondMoveOp;
@@ -93,14 +93,14 @@
      */
     class SaveRbp {
 
-        final PlaceholderOp placeholder;
+        final NoOp placeholder;
 
         /**
          * The slot reserved for saving RBP.
          */
         final StackSlot reservedSlot;
 
-        public SaveRbp(PlaceholderOp placeholder) {
+        public SaveRbp(NoOp placeholder) {
             this.placeholder = placeholder;
             this.reservedSlot = frameMap.allocateSpillSlot(Kind.Long);
             assert reservedSlot.getRawOffset() == -16 : reservedSlot.getRawOffset();
@@ -172,7 +172,7 @@
 
         emitIncomingValues(params);
 
-        saveRbp = new SaveRbp(new PlaceholderOp(currentBlock, lir.lir(currentBlock).size()));
+        saveRbp = new SaveRbp(new NoOp(currentBlock, lir.lir(currentBlock).size()));
         append(saveRbp.placeholder);
 
         for (LocalNode local : graph.getNodes(LocalNode.class)) {
@@ -433,6 +433,7 @@
 
     @Override
     public void beforeRegisterAllocation() {
+        super.beforeRegisterAllocation();
         boolean hasDebugInfo = lir.hasDebugInfo();
         AllocatableValue savedRbp = saveRbp.finalize(hasDebugInfo);
         if (hasDebugInfo) {
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java	Fri Dec 13 16:12:29 2013 +0100
+++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java	Fri Dec 13 16:40:41 2013 +0100
@@ -41,6 +41,8 @@
 import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.lir.hsail.*;
 import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.Replacements;
+import com.oracle.graal.replacements.hsail.*;
 
 /**
  * HSAIL specific backend.
@@ -63,12 +65,23 @@
         return true;
     }
 
+    /**
+     * Completes the initialization of the HSAIL backend. This includes initializing the providers
+     * and registering any method substitutions specified by the HSAIL backend.
+     */
     @Override
     public void completeInitialization() {
         final HotSpotProviders providers = getProviders();
         HotSpotVMConfig config = getRuntime().getConfig();
+        // Initialize the lowering provider.
         final HotSpotLoweringProvider lowerer = (HotSpotLoweringProvider) providers.getLowerer();
         lowerer.initialize(providers, config);
+
+        // Register the replacements used by the HSAIL backend.
+        Replacements replacements = providers.getReplacements();
+
+        // Register the substitutions for java.lang.Math routines.
+        replacements.registerSubstitutions(HSAILMathSubstitutions.class);
     }
 
     /**
@@ -284,7 +297,7 @@
             }
         }
         // Prologue done, Emit code for the LIR.
-        lirGen.lir.emitCode(crb);
+        crb.emit(lirGen.lir);
         // Now that code is emitted go back and figure out what the upper Bound stack size was.
         long maxStackSize = ((HSAILAssembler) crb.asm).upperBoundStackSize();
         String spillsegStringFinal;
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java	Fri Dec 13 16:12:29 2013 +0100
+++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java	Fri Dec 13 16:40:41 2013 +0100
@@ -284,7 +284,7 @@
         }
         // Emit code for the LIR
         try {
-            lirGen.lir.emitCode(crb);
+            crb.emit(lirGen.lir);
         } catch (GraalInternalError e) {
             e.printStackTrace();
             // TODO : Better error handling needs to be done once
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Fri Dec 13 16:12:29 2013 +0100
+++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java	Fri Dec 13 16:40:41 2013 +0100
@@ -81,15 +81,15 @@
      * @param afterFrameInit specifies if the stack pointer has already been adjusted to allocate
      *            the current frame
      */
-    protected static void emitStackOverflowCheck(CompilationResultBuilder crb, int stackShadowPages, boolean afterFrameInit) {
-        if (stackShadowPages > 0) {
+    protected static void emitStackOverflowCheck(CompilationResultBuilder crb, int pagesToBang, boolean afterFrameInit) {
+        if (pagesToBang > 0) {
             SPARCMacroAssembler masm = (SPARCMacroAssembler) crb.asm;
             final int frameSize = crb.frameMap.totalFrameSize();
             if (frameSize > 0) {
                 int lastFramePage = frameSize / unsafe.pageSize();
                 // emit multiple stack bangs for methods with frames larger than a page
                 for (int i = 0; i <= lastFramePage; i++) {
-                    int disp = (i + stackShadowPages) * unsafe.pageSize();
+                    int disp = (i + pagesToBang) * unsafe.pageSize();
                     if (afterFrameInit) {
                         disp -= frameSize;
                     }
@@ -124,8 +124,8 @@
             final int frameSize = crb.frameMap.totalFrameSize();
 
             SPARCMacroAssembler masm = (SPARCMacroAssembler) crb.asm;
-            if (!isStub && stackShadowPages > 0) {
-                emitStackOverflowCheck(crb, stackShadowPages, false);
+            if (!isStub && pagesToBang > 0) {
+                emitStackOverflowCheck(crb, pagesToBang, false);
             }
             new Save(sp, -frameSize, sp).emit(masm);
 
@@ -207,7 +207,7 @@
         crb.recordMark(Marks.MARK_VERIFIED_ENTRY);
 
         // Emit code for the LIR
-        lirGen.lir.emitCode(crb);
+        crb.emit(lirGen.lir);
 
         HotSpotFrameContext frameContext = (HotSpotFrameContext) crb.frameContext;
         HotSpotForeignCallsProvider foreignCalls = getProviders().getForeignCalls();
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java	Fri Dec 13 16:12:29 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java	Fri Dec 13 16:40:41 2013 +0100
@@ -40,11 +40,11 @@
     /**
      * This will be 0 if stack banging is disabled.
      */
-    protected final int stackShadowPages;
+    protected final int pagesToBang;
 
     public HotSpotHostBackend(HotSpotGraalRuntime runtime, HotSpotProviders providers) {
         super(runtime, providers);
-        this.stackShadowPages = runtime.getConfig().useStackBanging ? runtime.getConfig().stackShadowPages : 0;
+        this.pagesToBang = runtime.getConfig().useStackBanging ? runtime.getConfig().stackShadowPages : 0;
     }
 
     @Override
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java	Fri Dec 13 16:12:29 2013 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java	Fri Dec 13 16:40:41 2013 +0100
@@ -397,7 +397,7 @@
 
         @Override
         public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) {
-            return sb.append(format("count(%d)", getCounterValue(data, pos)));
+            return sb.append(format("count(%d) null_seen(%s) exception_seen(%s)", getCounterValue(data, pos), getNullSeen(data, pos), getExceptionSeen(data, pos)));
         }
     }
 
@@ -524,7 +524,9 @@
         public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) {
             RawItemProfile<ResolvedJavaType> profile = getRawTypeProfile(data, pos);
             TriState nullSeen = getNullSeen(data, pos);
-            sb.append(format("count(%d) null_seen(%s) nonprofiled_count(%d) entries(%d)", getCounterValue(data, pos), nullSeen, getTypesNotRecordedExecutionCount(data, pos), profile.entries));
+            TriState exceptionSeen = getExceptionSeen(data, pos);
+            sb.append(format("count(%d) null_seen(%s) exception_seen(%s) nonprofiled_count(%d) entries(%d)", getCounterValue(data, pos), nullSeen, exceptionSeen,
+                            getTypesNotRecordedExecutionCount(data, pos), profile.entries));
             for (int i = 0; i < profile.entries; i++) {
                 long count = profile.counts[i];
                 sb.append(format("%n  %s (%d, %4.2f)", MetaUtil.toJavaName(profile.items[i]), count, (double) count / profile.totalCount));
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java	Fri Dec 13 16:12:29 2013 +0100
+++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java	Fri Dec 13 16:40:41 2013 +0100
@@ -73,12 +73,11 @@
 
         @Override
         public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
-            int sourceIndex = crb.getCurrentBlockIndex();
-            if (trueDestination.isCodeEmittingOrderSuccessorEdge(sourceIndex)) {
+            if (crb.isSuccessorEdge(trueDestination)) {
                 jcc(masm, true, falseDestination);
             } else {
                 jcc(masm, false, trueDestination);
-                if (!falseDestination.isCodeEmittingOrderSuccessorEdge(sourceIndex)) {
+                if (!crb.isSuccessorEdge(falseDestination)) {
                     masm.jmp(falseDestination.label());
                 }
             }
--- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILArithmetic.java	Fri Dec 13 16:12:29 2013 +0100
+++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILArithmetic.java	Fri Dec 13 16:40:41 2013 +0100
@@ -29,14 +29,17 @@
 import com.oracle.graal.asm.hsail.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
-import com.oracle.graal.lir.asm.*;
+import com.oracle.graal.lir.asm.CompilationResultBuilder;
 
 /**
  * Defines arithmetic instruction nodes.
  */
 public enum HSAILArithmetic {
+    ABS,
     CALL,
+    CEIL,
     FDIV,
+    FLOOR,
     FREM,
     DADD,
     DDIV,
@@ -97,6 +100,7 @@
     LUSUB,
     LXOR,
     OADD,
+    RINT,
     SQRT,
     UNDEF;
 
@@ -289,10 +293,33 @@
         }
     }
 
+    /**
+     * Emits the HSAIL code for an arithmetic operation taking one input parameter.
+     * 
+     * @param crb the CompilationResultBuilder
+     * @param masm the HSAIL assembler
+     * @param opcode the opcode of the arithmetic operation
+     * @param dst the destination
+     * @param src the source parameter
+     * @param info structure that stores the LIRFrameState. Used for exception handling.
+     */
+
     public static void emit(CompilationResultBuilder crb, HSAILAssembler masm, HSAILArithmetic opcode, Value dst, Value src, LIRFrameState info) {
         int exceptionOffset = -1;
         if (isRegister(src)) {
             switch (opcode) {
+                case ABS:
+                    masm.emit("abs", dst, src);
+                    break;
+                case CEIL:
+                    masm.emit("ceil", dst, src);
+                    break;
+                case FLOOR:
+                    masm.emit("floor", dst, src);
+                    break;
+                case RINT:
+                    masm.emit("rint", dst, src);
+                    break;
                 case SQRT:
                     masm.emit("sqrt", dst, src);
                     break;
@@ -304,14 +331,12 @@
                     break;
                 case INOT:
                 case LNOT:
-                    // Emit the HSAIL instruction for a bitwise not.
                     masm.emitForceBitwise("not", dst, src);
                     break;
                 case INEG:
                 case LNEG:
                 case FNEG:
                 case DNEG:
-                    // Emit the HSAIL instruction for a negate operation.
                     masm.emit("neg", dst, src);
                     break;
                 default:
--- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILControlFlow.java	Fri Dec 13 16:12:29 2013 +0100
+++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILControlFlow.java	Fri Dec 13 16:40:41 2013 +0100
@@ -188,14 +188,13 @@
 
         @Override
         public void emitCode(CompilationResultBuilder crb, HSAILAssembler masm) {
-            int sourceIndex = crb.getCurrentBlockIndex();
-            if (trueDestination.isCodeEmittingOrderSuccessorEdge(sourceIndex)) {
+            if (crb.isSuccessorEdge(trueDestination)) {
                 HSAILCompare.emit(crb, masm, condition.negate(), x, y, z, !unordered);
                 masm.cbr(masm.nameOf(falseDestination.label()));
             } else {
                 HSAILCompare.emit(crb, masm, condition, x, y, z, unordered);
                 masm.cbr(masm.nameOf(trueDestination.label()));
-                if (!falseDestination.isCodeEmittingOrderSuccessorEdge(sourceIndex)) {
+                if (!crb.isSuccessorEdge(falseDestination)) {
                     masm.jmp(falseDestination.label());
                 }
             }
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXControlFlow.java	Fri Dec 13 16:12:29 2013 +0100
+++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXControlFlow.java	Fri Dec 13 16:40:41 2013 +0100
@@ -85,12 +85,11 @@
 
         @Override
         public void emitCode(CompilationResultBuilder crb, PTXMacroAssembler masm) {
-            int sourceIndex = crb.getCurrentBlockIndex();
-            if (trueDestination.isCodeEmittingOrderSuccessorEdge(sourceIndex)) {
+            if (crb.isSuccessorEdge(trueDestination)) {
                 masm.bra(masm.nameOf(falseDestination.label()), predRegNum);
             } else {
                 masm.bra(masm.nameOf(trueDestination.label()));
-                if (!falseDestination.isCodeEmittingOrderSuccessorEdge(sourceIndex)) {
+                if (!crb.isSuccessorEdge(falseDestination)) {
                     masm.jmp(falseDestination.label());
                 }
             }
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Fri Dec 13 16:12:29 2013 +0100
+++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java	Fri Dec 13 16:40:41 2013 +0100
@@ -73,18 +73,17 @@
 
         @Override
         public void emitCode(CompilationResultBuilder crb, SPARCMacroAssembler masm) {
-            int sourceIndex = crb.getCurrentBlockIndex();
             Label actualTarget;
             Condition actualCondition;
             boolean needJump;
-            if (trueDestination.isCodeEmittingOrderSuccessorEdge(sourceIndex)) {
+            if (crb.isSuccessorEdge(trueDestination)) {
                 actualCondition = condition.negate();
                 actualTarget = falseDestination.label();
                 needJump = false;
             } else {
                 actualCondition = condition;
                 actualTarget = trueDestination.label();
-                needJump = !falseDestination.isCodeEmittingOrderSuccessorEdge(sourceIndex);
+                needJump = !crb.isSuccessorEdge(falseDestination);
             }
             assert kind == Kind.Int || kind == Kind.Long || kind == Kind.Object;
             CC cc = kind == Kind.Int ? CC.Icc : CC.Xcc;
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java	Fri Dec 13 16:12:29 2013 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java	Fri Dec 13 16:40:41 2013 +0100
@@ -25,10 +25,8 @@
 import java.util.*;
 
 import com.oracle.graal.api.meta.*;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.graph.*;
+import com.oracle.graal.lir.LIRInstruction.StateProcedure;
 import com.oracle.graal.lir.StandardOp.BlockEndOp;
-import com.oracle.graal.lir.asm.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.cfg.*;
 
@@ -137,46 +135,6 @@
         firstVariableNumber = num;
     }
 
-    public void emitCode(CompilationResultBuilder crb) {
-        crb.frameContext.enter(crb);
-
-        // notifyBlocksOfSuccessors();
-
-        int index = 0;
-        for (Block b : codeEmittingOrder) {
-            crb.setCurrentBlockIndex(index++);
-            emitBlock(crb, b);
-        }
-    }
-
-    private void emitBlock(CompilationResultBuilder crb, Block block) {
-        if (Debug.isDumpEnabled()) {
-            crb.blockComment(String.format("block B%d %s", block.getId(), block.getLoop()));
-        }
-
-        for (LIRInstruction op : lir(block)) {
-            if (Debug.isDumpEnabled()) {
-                crb.blockComment(String.format("%d %s", op.id(), op));
-            }
-
-            try {
-                emitOp(crb, op);
-            } catch (GraalInternalError e) {
-                throw e.addContext("lir instruction", block + "@" + op.id() + " " + op + "\n" + codeEmittingOrder);
-            }
-        }
-    }
-
-    private static void emitOp(CompilationResultBuilder crb, LIRInstruction op) {
-        try {
-            op.emitCode(crb);
-        } catch (AssertionError t) {
-            throw new GraalInternalError(t);
-        } catch (RuntimeException t) {
-            throw new GraalInternalError(t);
-        }
-    }
-
     public void setHasArgInCallerFrame() {
         hasArgInCallerFrame = true;
     }
@@ -189,15 +147,55 @@
         return hasArgInCallerFrame;
     }
 
+    /**
+     * Gets the exception edge (if any) originating at a given operation.
+     */
+    public static LabelRef getExceptionEdge(LIRInstruction op) {
+        final LabelRef[] exceptionEdge = {null};
+        op.forEachState(new StateProcedure() {
+            @Override
+            protected void doState(LIRFrameState state) {
+                if (state.exceptionEdge != null) {
+                    assert exceptionEdge[0] == null;
+                    exceptionEdge[0] = state.exceptionEdge;
+                }
+            }
+        });
+        return exceptionEdge[0];
+    }
+
+    /**
+     * The maximum distance an operation with an {@linkplain #getExceptionEdge(LIRInstruction)
+     * exception edge} can be from the last instruction of a LIR block. The value of 2 is based on a
+     * non-void call operation that has an exception edge. Such a call op will have a move op after
+     * it to put the return value into the result variable.
+     * <p>
+     * The rationale for such a constant is to limit the search for an insertion point when adding
+     * move operations at the end of a block. Such moves must be inserted before all control flow
+     * instructions.
+     */
+    public static final int MAX_EXCEPTION_EDGE_OP_DISTANCE_FROM_END = 2;
+
     public static boolean verifyBlock(LIR lir, Block block) {
         List<LIRInstruction> ops = lir.lir(block);
         if (ops.size() == 0) {
-            return true;
+            return false;
         }
-        for (LIRInstruction op : ops.subList(0, ops.size() - 1)) {
+        LIRInstruction opWithExceptionEdge = null;
+        int index = 0;
+        int lastIndex = ops.size() - 1;
+        for (LIRInstruction op : ops.subList(0, lastIndex)) {
             assert !(op instanceof BlockEndOp) : op.getClass();
+            LabelRef exceptionEdge = getExceptionEdge(op);
+            if (exceptionEdge != null) {
+                assert opWithExceptionEdge == null : "multiple ops with an exception edge not allowed";
+                opWithExceptionEdge = op;
+                int distanceFromEnd = lastIndex - index;
+                assert distanceFromEnd <= MAX_EXCEPTION_EDGE_OP_DISTANCE_FROM_END;
+            }
+            index++;
         }
-        LIRInstruction end = ops.get(ops.size() - 1);
+        LIRInstruction end = ops.get(lastIndex);
         assert end instanceof BlockEndOp : end.getClass();
         return true;
     }
@@ -210,7 +208,9 @@
             for (Block pred : block.getPredecessors()) {
                 assert blocks.contains(pred) : "missing predecessor from: " + block + "to: " + pred;
             }
-            verifyBlock(lir, block);
+            if (!verifyBlock(lir, block)) {
+                return false;
+            }
         }
         return true;
     }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LabelRef.java	Fri Dec 13 16:12:29 2013 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LabelRef.java	Fri Dec 13 16:40:41 2013 +0100
@@ -22,8 +22,6 @@
  */
 package com.oracle.graal.lir;
 
-import java.util.*;
-
 import com.oracle.graal.asm.*;
 import com.oracle.graal.lir.StandardOp.BranchOp;
 import com.oracle.graal.lir.StandardOp.JumpOp;
@@ -78,21 +76,8 @@
         return ((StandardOp.LabelOp) lir.lir(getTargetBlock()).get(0)).getLabel();
     }
 
-    /**
-     * Determines if the edge represented by this object is from a block to its lexical successor in
-     * the code emitting order of blocks.
-     * 
-     * @param sourceIndex the index of this edge's {@linkplain #getSourceBlock() source} in the code
-     *            emitting order
-     */
-    public boolean isCodeEmittingOrderSuccessorEdge(int sourceIndex) {
-        List<Block> order = lir.codeEmittingOrder();
-        assert order.get(sourceIndex) == block;
-        return sourceIndex < order.size() - 1 && order.get(sourceIndex + 1) == getTargetBlock();
-    }
-
     @Override
     public String toString() {
-        return suxIndex < block.getSuccessorCount() ? getTargetBlock().toString() : "?" + block + ":" + suxIndex + "?";
+        return getSourceBlock() + " -> " + (suxIndex < block.getSuccessors().size() ? getTargetBlock() : "?");
     }
 }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java	Fri Dec 13 16:12:29 2013 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java	Fri Dec 13 16:40:41 2013 +0100
@@ -113,7 +113,7 @@
 
         @Override
         public void emitCode(CompilationResultBuilder crb) {
-            if (!destination.isCodeEmittingOrderSuccessorEdge(crb.getCurrentBlockIndex())) {
+            if (!crb.isSuccessorEdge(destination)) {
                 crb.asm.jmp(destination.label());
             }
         }
@@ -174,9 +174,10 @@
     }
 
     /**
-     * Placeholder for a LIR instruction that will be subsequently replaced.
+     * A LIR operation that does nothing. If the operation records its position, it can be
+     * subsequently {@linkplain #replace(LIR, LIRInstruction) replaced}.
      */
-    public static class PlaceholderOp extends LIRInstruction {
+    public static class NoOp extends LIRInstruction {
 
         /**
          * The block in which this instruction is located.
@@ -188,7 +189,7 @@
          */
         final int index;
 
-        public PlaceholderOp(Block block, int index) {
+        public NoOp(Block block, int index) {
             this.block = block;
             this.index = index;
         }
@@ -199,7 +200,9 @@
 
         @Override
         public void emitCode(CompilationResultBuilder crb) {
-            throw new GraalInternalError(this + " should have been replaced");
+            if (block != null) {
+                throw new GraalInternalError(this + " should have been replaced");
+            }
         }
     }
 }
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/SwitchStrategy.java	Fri Dec 13 16:12:29 2013 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/SwitchStrategy.java	Fri Dec 13 16:40:41 2013 +0100
@@ -116,9 +116,9 @@
         }
 
         public void conditionalJumpOrDefault(int index, Condition condition, boolean canFallThrough) {
-            if (canFallThrough && defaultTarget.isCodeEmittingOrderSuccessorEdge(crb.getCurrentBlockIndex())) {
+            if (canFallThrough && crb.isSuccessorEdge(defaultTarget)) {
                 conditionalJump(index, condition, keyTargets[index].label());
-            } else if (canFallThrough && keyTargets[index].isCodeEmittingOrderSuccessorEdge(crb.getCurrentBlockIndex())) {
+            } else if (canFallThrough && crb.isSuccessorEdge(keyTargets[index])) {
                 conditionalJump(index, condition.negate(), defaultTarget.label());
             } else {
                 conditionalJump(index, condition, keyTargets[index].label());
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java	Fri Dec 13 16:12:29 2013 +0100
+++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java	Fri Dec 13 16:40:41 2013 +0100
@@ -32,6 +32,7 @@
 import com.oracle.graal.debug.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.lir.*;
+import com.oracle.graal.nodes.cfg.*;
 
 /**
  * Fills in a {@link CompilationResult} as its code is being assembled.
@@ -59,7 +60,12 @@
     public final FrameMap frameMap;
 
     /**
-     * The index of the block currently being processed in the code emitting block order.
+     * The LIR for which code is being generated.
+     */
+    private LIR lir;
+
+    /**
+     * The index of the block currently being emitted.
      */
     private int currentBlockIndex;
 
@@ -285,16 +291,58 @@
     }
 
     /**
-     * Gets the index of the block currently being processed in the code emitting block order.
+     * Determines if a given edge from the block currently being emitted goes to its lexical
+     * successor.
      */
-    public int getCurrentBlockIndex() {
-        return currentBlockIndex;
+    public boolean isSuccessorEdge(LabelRef edge) {
+        assert lir != null;
+        List<Block> order = lir.codeEmittingOrder();
+        assert order.get(currentBlockIndex) == edge.getSourceBlock();
+        return currentBlockIndex < order.size() - 1 && order.get(currentBlockIndex + 1) == edge.getTargetBlock();
     }
 
     /**
-     * Sets the index of the block currently being processed in the code emitting block order.
+     * Emits code for {@code lir} in its {@linkplain LIR#codeEmittingOrder() code emitting order}.
      */
-    public void setCurrentBlockIndex(int index) {
-        this.currentBlockIndex = index;
+    public void emit(@SuppressWarnings("hiding") LIR lir) {
+        assert this.lir == null;
+        assert currentBlockIndex == 0;
+        this.lir = lir;
+        this.currentBlockIndex = 0;
+        frameContext.enter(this);
+        for (Block b : lir.codeEmittingOrder()) {
+            emitBlock(b);
+            currentBlockIndex++;
+        }
+        this.lir = null;
+        this.currentBlockIndex = 0;
+    }
+
+    private void emitBlock(Block block) {
+        if (Debug.isDumpEnabled()) {
+            blockComment(String.format("block B%d %s", block.getId(), block.getLoop()));
+        }
+
+        for (LIRInstruction op : lir.lir(block)) {
+            if (Debug.isDumpEnabled()) {
+                blockComment(String.format("%d %s", op.id(), op));
+            }
+
+            try {
+                emitOp(this, op);
+            } catch (GraalInternalError e) {
+                throw e.addContext("lir instruction", block + "@" + op.id() + " " + op + "\n" + lir.codeEmittingOrder());
+            }
+        }
+    }
+
+    private static void emitOp(CompilationResultBuilder crb, LIRInstruction op) {
+        try {
+            op.emitCode(crb);
+        } catch (AssertionError t) {
+            throw new GraalInternalError(t);
+        } catch (RuntimeException t) {
+            throw new GraalInternalError(t);
+        }
     }
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Fri Dec 13 16:12:29 2013 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java	Fri Dec 13 16:40:41 2013 +0100
@@ -102,6 +102,7 @@
 
     /**
      * Called just before register allocation is performed on the LIR owned by this generator.
+     * Overriding implementations of this method must call the overridden method.
      */
     void beforeRegisterAllocation();
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.hsail/src/com/oracle/graal/replacements/hsail/HSAILMathIntrinsicsNode.java	Fri Dec 13 16:40:41 2013 +0100
@@ -0,0 +1,178 @@
+/*
+ * 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.replacements.hsail;
+
+import com.oracle.graal.api.meta.Constant;
+import com.oracle.graal.api.meta.Value;
+import com.oracle.graal.compiler.hsail.HSAILLIRGenerator;
+import com.oracle.graal.graph.GraalInternalError;
+import com.oracle.graal.graph.Node;
+import com.oracle.graal.graph.spi.Canonicalizable;
+import com.oracle.graal.graph.spi.CanonicalizerTool;
+import com.oracle.graal.lir.hsail.HSAILArithmetic;
+import com.oracle.graal.nodes.calc.FloatingNode;
+import com.oracle.graal.nodes.ConstantNode;
+import com.oracle.graal.nodes.ValueNode;
+import com.oracle.graal.nodes.spi.ArithmeticLIRGenerator;
+import com.oracle.graal.nodes.spi.ArithmeticLIRLowerable;
+import com.oracle.graal.nodes.type.StampFactory;
+
+/**
+ * This node implements HSAIL intrinsics for specific {@link Math} routines.
+ */
+public class HSAILMathIntrinsicsNode extends FloatingNode implements Canonicalizable, ArithmeticLIRLowerable {
+
+    /**
+     * The parameter passed to the math operation that this node represents.
+     */
+    @Input private ValueNode param;
+
+    /**
+     * The math operation that this Node represents.
+     */
+    private final HSAILArithmetic operation;
+
+    /**
+     * Gets the parameter passed to the math operation that this node represents.
+     * 
+     * @return the parameter
+     */
+    public ValueNode getParameter() {
+        return param;
+    }
+
+    /**
+     * Returns the math operation represented by this node.
+     * 
+     * @return the operation
+     */
+    public HSAILArithmetic operation() {
+        return operation;
+    }
+
+    /**
+     * Creates a new HSAILMathIntrinsicNode.
+     * 
+     * @param x the argument to the math operation
+     * @param op the math operation
+     */
+    public HSAILMathIntrinsicsNode(ValueNode x, HSAILArithmetic op) {
+        super(StampFactory.forKind(x.kind()));
+        this.param = x;
+        this.operation = op;
+    }
+
+    /**
+     * Generates the LIR instructions for the math operation represented by this node.
+     */
+    @Override
+    public void generate(ArithmeticLIRGenerator gen) {
+        Value input = gen.operand(getParameter());
+        Value result;
+        switch (operation()) {
+            case ABS:
+                result = gen.emitMathAbs(input);
+                break;
+            case CEIL:
+                result = ((HSAILLIRGenerator) (gen)).emitMathCeil(input);
+                break;
+            case FLOOR:
+                result = ((HSAILLIRGenerator) (gen)).emitMathFloor(input);
+                break;
+            case RINT:
+                result = ((HSAILLIRGenerator) (gen)).emitMathRint(input);
+                break;
+            case SQRT:
+                result = gen.emitMathSqrt(input);
+                break;
+
+            default:
+                throw GraalInternalError.shouldNotReachHere();
+        }
+        gen.setResult(this, result);
+    }
+
+    /**
+     * Converts a constant to a boxed double.
+     */
+    public Constant evalConst(Constant... inputs) {
+        assert inputs.length == 1;
+        return Constant.forDouble(compute(inputs[0].asDouble(), operation()));
+    }
+
+    /**
+     * Converts the result of the math operation to a boxed Double constant node.
+     */
+    @Override
+    public Node canonical(CanonicalizerTool tool) {
+        if (getParameter().isConstant()) {
+            return ConstantNode.forPrimitive(evalConst(getParameter().asConstant()), graph());
+        }
+        return this;
+    }
+
+    // The routines below are node intrinsics. A call to any of these routines is replaced by a
+    // HSAILMathIntrinsicNode to handle the Math library operation represented by the
+    // HSAILArithmetic argument.
+
+    /**
+     * Node intrinsic for {@link Math} routines taking a single int parameter.
+     * 
+     * @param value
+     * @param op the math operation
+     * @return the result of the operation
+     */
+    @NodeIntrinsic
+    public static native int compute(int value, @ConstantNodeParameter HSAILArithmetic op);
+
+    /**
+     * Node intrinsic for {@link Math} routines taking a single double parameter.
+     * 
+     * @param value the input parameter
+     * @param op the math operation
+     * @return the result of the operation
+     */
+    @NodeIntrinsic
+    public static native long compute(long value, @ConstantNodeParameter HSAILArithmetic op);
+
+    /**
+     * Node intrinsic for {@link Math} routines taking a single float parameter.
+     * 
+     * @param value the input parameter
+     * @param op the math operation
+     * @return the result of the operation
+     */
+    @NodeIntrinsic
+    public static native float compute(float value, @ConstantNodeParameter HSAILArithmetic op);
+
+    /**
+     * Node intrinsic for {@link Math} routines taking a single double parameter.
+     * 
+     * @param value the input parameter
+     * @param op the math operation
+     * 
+     * @return the result of the operation
+     */
+    @NodeIntrinsic
+    public static native double compute(double value, @ConstantNodeParameter HSAILArithmetic op);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.replacements.hsail/src/com/oracle/graal/replacements/hsail/HSAILMathSubstitutions.java	Fri Dec 13 16:40:41 2013 +0100
@@ -0,0 +1,123 @@
+/*
+ * 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.replacements.hsail;
+
+import com.oracle.graal.api.replacements.ClassSubstitution;
+import com.oracle.graal.api.replacements.MethodSubstitution;
+import com.oracle.graal.lir.hsail.HSAILArithmetic;
+
+/**
+ * Substitutions for {@link Math} methods. For any calls to the routines listed below and annotated
+ * with {@link MethodSubstitution}, Graal replaces the call with a {@link HSAILMathIntrinsicsNode}.
+ */
+@ClassSubstitution(java.lang.Math.class)
+public class HSAILMathSubstitutions {
+
+    /**
+     * Substitution for {@link Math#abs(int)}.
+     * 
+     * @param x the input
+     * @return the result of the computation
+     */
+    @MethodSubstitution
+    public static int abs(int x) {
+        return HSAILMathIntrinsicsNode.compute(x, HSAILArithmetic.ABS);
+    }
+
+    /**
+     * Substitution for {@link Math#abs(long)}.
+     * 
+     * @param x the input
+     * @return the result of the computation
+     */
+    @MethodSubstitution
+    public static long abs(long x) {
+        return HSAILMathIntrinsicsNode.compute(x, HSAILArithmetic.ABS);
+    }
+
+    /**
+     * Substitution for {@link Math#abs(float)}.
+     * 
+     * @param x the input
+     * @return the result of the computation
+     */
+    @MethodSubstitution
+    public static float abs(float x) {
+        return HSAILMathIntrinsicsNode.compute(x, HSAILArithmetic.ABS);
+    }
+
+    /**
+     * Substitution for {@link Math#abs(double)}.
+     * 
+     * @param x the input
+     * @return the result of the computation
+     */
+    @MethodSubstitution
+    public static double abs(double x) {
+        return HSAILMathIntrinsicsNode.compute(x, HSAILArithmetic.ABS);
+    }
+
+    /**
+     * Substitution for Math.ceil(double).
+     * 
+     * @param x the input
+     * @return the result of the computation
+     */
+    @MethodSubstitution
+    public static double ceil(double x) {
+        return HSAILMathIntrinsicsNode.compute(x, HSAILArithmetic.CEIL);
+    }
+
+    /**
+     * Substitution for {@link Math#floor(double)}.
+     * 
+     * @param x the input
+     * @return the result of the computation
+     */
+    @MethodSubstitution
+    public static double floor(double x) {
+        return HSAILMathIntrinsicsNode.compute(x, HSAILArithmetic.FLOOR);
+    }
+
+    /**
+     * Substitution for {@link Math#rint(double)}.
+     * 
+     * @param x the input
+     * @return the result of the computation
+     */
+    @MethodSubstitution
+    public static double rint(double x) {
+        return HSAILMathIntrinsicsNode.compute(x, HSAILArithmetic.RINT);
+    }
+
+    /**
+     * Substitution for {@link Math#sqrt(double)}.
+     * 
+     * @param x the input
+     * @return the result of the computation
+     */
+    @MethodSubstitution
+    public static double sqrt(double x) {
+        return HSAILMathIntrinsicsNode.compute(x, HSAILArithmetic.SQRT);
+    }
+}
--- a/mx/mx_graal.py	Fri Dec 13 16:12:29 2013 +0100
+++ b/mx/mx_graal.py	Fri Dec 13 16:40:41 2013 +0100
@@ -808,7 +808,7 @@
         f_testfile.close()
         harness(projectscp, vmArgs)
 
-def _unittest(args, annotations):
+def _unittest(args, annotations, prefixcp=""):
     mxdir = dirname(__file__)
     name = 'JUnitWrapper'
     javaSource = join(mxdir, name + '.java')
@@ -830,9 +830,9 @@
         if len(testclasses) == 1:
             # Execute Junit directly when one test is being run. This simplifies
             # replaying the VM execution in a native debugger (e.g., gdb).
-            vm(prefixArgs + vmArgs + ['-cp', projectscp, 'org.junit.runner.JUnitCore'] + testclasses)
+            vm(prefixArgs + vmArgs + ['-cp', prefixcp + projectscp, 'org.junit.runner.JUnitCore'] + testclasses)
         else:
-            vm(prefixArgs + vmArgs + ['-cp', projectscp + os.pathsep + mxdir, name] + [testfile])
+            vm(prefixArgs + vmArgs + ['-cp', prefixcp + projectscp + os.pathsep + mxdir, name] + [testfile])
 
     try:
         _run_tests(args, harness, annotations, testfile)
@@ -1348,9 +1348,17 @@
 
 def trufflejar(args=None):
     """make truffle.jar"""
+    
+    # Test with the built classes
+    _unittest(["com.oracle.truffle.api.test", "com.oracle.truffle.api.dsl.test"], ['@Test', '@LongTest', '@Parameters'])
+    
     # We use the DSL processor as the starting point for the classpath - this
     # therefore includes the DSL processor, the DSL and the API.
-    packagejar(mx.classpath("com.oracle.truffle.dsl.processor").split(os.pathsep), "truffle.jar", None)
+    packagejar(mx.classpath("com.oracle.truffle.dsl.processor").split(os.pathsep), "truffle.jar", None, "com.oracle.truffle.dsl.processor.TruffleProcessor")
+    
+    # Test with the JAR
+    _unittest(["com.oracle.truffle.api.test", "com.oracle.truffle.api.dsl.test"], ['@Test', '@LongTest', '@Parameters'], "truffle.jar:")
+
 
 def isGraalEnabled(vm):
     return vm != 'original' and not vm.endswith('nograal')
@@ -1444,7 +1452,7 @@
 
     mx.distribution('GRAAL').add_update_listener(_installGraalJarInJdks)
 
-def packagejar(classpath, outputFile, mainClass):
+def packagejar(classpath, outputFile, mainClass, annotationProcessor=None):
     prefix = '' if mx.get_os() != 'windows' else '\\??\\' # long file name hack
     print "creating", outputFile
     filecount, totalsize = 0, 0
@@ -1453,6 +1461,8 @@
         if mainClass != None:
             manifest += "Main-Class: %s\n\n" % (mainClass)
         zf.writestr("META-INF/MANIFEST.MF", manifest)
+        if annotationProcessor != None:
+            zf.writestr("META-INF/services/javax.annotation.processing.Processor", annotationProcessor)
         for cp in classpath:
             print "+", cp
             if cp.endswith(".jar"):
--- a/mx/projects	Fri Dec 13 16:12:29 2013 +0100
+++ b/mx/projects	Fri Dec 13 16:40:41 2013 +0100
@@ -162,7 +162,7 @@
 # graal.hotspot.hsail
 project@com.oracle.graal.hotspot.hsail@subDir=graal
 project@com.oracle.graal.hotspot.hsail@sourceDirs=src
-project@com.oracle.graal.hotspot.hsail@dependencies=com.oracle.graal.compiler.hsail,com.oracle.graal.hotspot
+project@com.oracle.graal.hotspot.hsail@dependencies=com.oracle.graal.replacements.hsail,com.oracle.graal.hotspot
 project@com.oracle.graal.hotspot.hsail@checkstyle=com.oracle.graal.graph
 project@com.oracle.graal.hotspot.hsail@annotationProcessors=com.oracle.graal.service.processor
 project@com.oracle.graal.hotspot.hsail@javaCompliance=1.7
@@ -311,6 +311,14 @@
 project@com.oracle.graal.replacements.amd64@javaCompliance=1.7
 project@com.oracle.graal.replacements.amd64@workingSets=Graal,Replacements,AMD64
 
+# graal.replacements.hsail
+project@com.oracle.graal.replacements.hsail@subDir=graal
+project@com.oracle.graal.replacements.hsail@sourceDirs=src
+project@com.oracle.graal.replacements.hsail@dependencies=com.oracle.graal.compiler.hsail
+project@com.oracle.graal.replacements.hsail@checkstyle=com.oracle.graal.graph
+project@com.oracle.graal.replacements.hsail@javaCompliance=1.7
+project@com.oracle.graal.replacements.hsail@workingSets=Graal,Replacements,HSAIL
+
 # graal.replacements.test
 project@com.oracle.graal.replacements.test@subDir=graal
 project@com.oracle.graal.replacements.test@sourceDirs=src