# HG changeset patch # User Erik Eckstein # Date 1386949241 -3600 # Node ID 0393767ae0fc674bf45e2055f679b01ef7b0b931 # Parent e585ac5a385d9a07722f78e1aa18faf4888ba9b5# Parent e01fe53ec4b77a75c4982a6e91ef7c30d5a30bec Merge diff -r e01fe53ec4b7 -r 0393767ae0fc graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ExceptionHandler.java --- 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"; } + + @Override + public int hashCode() { + return catchTypeCPI ^ endBCI ^ handlerBCI; + } } diff -r e01fe53ec4b7 -r 0393767ae0fc graal/com.oracle.graal.asm.amd64/src/com/oracle/graal/asm/amd64/AMD64Assembler.java --- 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); } diff -r e01fe53ec4b7 -r 0393767ae0fc graal/com.oracle.graal.compiler.hsail.test.infra/src/com/oracle/graal/compiler/hsail/test/infra/KernelTester.java --- 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; } diff -r e01fe53ec4b7 -r 0393767ae0fc graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/DoubleAbsTest.java --- /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); + } +} diff -r e01fe53ec4b7 -r 0393767ae0fc graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/DoubleCeilTest.java --- /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); + } +} diff -r e01fe53ec4b7 -r 0393767ae0fc graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/DoubleFloorTest.java --- /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); + } +} diff -r e01fe53ec4b7 -r 0393767ae0fc graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/DoubleRintTest.java --- /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(); + } +} diff -r e01fe53ec4b7 -r 0393767ae0fc graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/DoubleSqrtTest.java --- /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(); + } +} diff -r e01fe53ec4b7 -r 0393767ae0fc graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/FloatAbsTest.java --- /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); + } +} diff -r e01fe53ec4b7 -r 0393767ae0fc graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/FloatDivPrecisionTest.java --- 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; diff -r e01fe53ec4b7 -r 0393767ae0fc graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/FloatSqrtTest.java --- 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(); - } -} diff -r e01fe53ec4b7 -r 0393767ae0fc graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/IntAbsTest.java --- /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); + } +} diff -r e01fe53ec4b7 -r 0393767ae0fc graal/com.oracle.graal.compiler.hsail.test/src/com/oracle/graal/compiler/hsail/test/LongAbsTest.java --- /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); + } +} diff -r e01fe53ec4b7 -r 0393767ae0fc graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILLIRGenerator.java --- 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()); diff -r e01fe53ec4b7 -r 0393767ae0fc graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/CommonedConstantsTest.java --- /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); + } +} diff -r e01fe53ec4b7 -r 0393767ae0fc graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java --- 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(); diff -r e01fe53ec4b7 -r 0393767ae0fc graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java --- 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 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 { + /** + * 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 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 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> 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 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 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; diff -r e01fe53ec4b7 -r 0393767ae0fc graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java --- 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); } /** diff -r e01fe53ec4b7 -r 0393767ae0fc graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java --- 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) { diff -r e01fe53ec4b7 -r 0393767ae0fc graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java --- 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; diff -r e01fe53ec4b7 -r 0393767ae0fc graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java --- 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 diff -r e01fe53ec4b7 -r 0393767ae0fc graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java --- 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(); diff -r e01fe53ec4b7 -r 0393767ae0fc graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotHostBackend.java --- 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 diff -r e01fe53ec4b7 -r 0393767ae0fc graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotMethodData.java --- 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 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)); diff -r e01fe53ec4b7 -r 0393767ae0fc graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ControlFlow.java --- 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()); } } diff -r e01fe53ec4b7 -r 0393767ae0fc graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILArithmetic.java --- 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: diff -r e01fe53ec4b7 -r 0393767ae0fc graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILControlFlow.java --- 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()); } } diff -r e01fe53ec4b7 -r 0393767ae0fc graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXControlFlow.java --- 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()); } } diff -r e01fe53ec4b7 -r 0393767ae0fc graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCControlFlow.java --- 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; diff -r e01fe53ec4b7 -r 0393767ae0fc graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java --- 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. + *

+ * 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 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; } diff -r e01fe53ec4b7 -r 0393767ae0fc graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LabelRef.java --- 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 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() : "?"); } } diff -r e01fe53ec4b7 -r 0393767ae0fc graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java --- 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"); + } } } } diff -r e01fe53ec4b7 -r 0393767ae0fc graal/com.oracle.graal.lir/src/com/oracle/graal/lir/SwitchStrategy.java --- 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()); diff -r e01fe53ec4b7 -r 0393767ae0fc graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java --- 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 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); + } } } diff -r e01fe53ec4b7 -r 0393767ae0fc graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java --- 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(); diff -r e01fe53ec4b7 -r 0393767ae0fc graal/com.oracle.graal.replacements.hsail/src/com/oracle/graal/replacements/hsail/HSAILMathIntrinsicsNode.java --- /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); +} diff -r e01fe53ec4b7 -r 0393767ae0fc graal/com.oracle.graal.replacements.hsail/src/com/oracle/graal/replacements/hsail/HSAILMathSubstitutions.java --- /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); + } +} diff -r e01fe53ec4b7 -r 0393767ae0fc mx/mx_graal.py --- 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"): diff -r e01fe53ec4b7 -r 0393767ae0fc mx/projects --- 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