diff graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/IntrinsificationTest.java @ 7220:fcae6d960acd

added more compiler intrinsics
author Christian Haeubl <haeubl@ssw.jku.at>
date Tue, 11 Dec 2012 08:28:00 +0100
parents
children e2ea829fafd9
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/IntrinsificationTest.java	Tue Dec 11 08:28:00 2012 +0100
@@ -0,0 +1,393 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.snippets;
+
+import static org.junit.Assert.*;
+
+import java.util.concurrent.*;
+
+import org.junit.*;
+
+import sun.misc.*;
+
+import com.oracle.graal.api.code.*;
+import com.oracle.graal.compiler.test.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.common.*;
+
+
+public class IntrinsificationTest extends GraalCompilerTest {
+    @Test
+    public void testObjectIntrinsics() {
+        test("getClassSnippet");
+        test("objectHashCodeSnippet");
+    }
+
+    @SuppressWarnings("all")
+    public static boolean getClassSnippet(Object obj) {
+        return obj.getClass() == String.class;
+    }
+    @SuppressWarnings("all")
+    public static int objectHashCodeSnippet(A obj) {
+        return obj.hashCode();
+    }
+
+
+    @Test
+    public void testClassIntrinsics() {
+        test("getModifiersSnippet");
+//        test("isInstanceSnippet");
+        test("isInterfaceSnippet");
+        test("isArraySnippet");
+        test("isPrimitiveSnippet");
+        test("getSuperClassSnippet");
+        test("getComponentTypeSnippet");
+    }
+
+    @SuppressWarnings("all")
+    public static int getModifiersSnippet(Class<?> clazz) {
+        return clazz.getModifiers();
+    }
+    @SuppressWarnings("all")
+    public static boolean isInstanceSnippet(Class<?> clazz) {
+        return clazz.isInstance(Number.class);
+    }
+    @SuppressWarnings("all")
+    public static boolean isInterfaceSnippet(Class<?> clazz) {
+        return clazz.isInterface();
+    }
+    @SuppressWarnings("all")
+    public static boolean isArraySnippet(Class<?> clazz) {
+        return clazz.isArray();
+    }
+    @SuppressWarnings("all")
+    public static boolean isPrimitiveSnippet(Class<?> clazz) {
+        return clazz.isPrimitive();
+    }
+    @SuppressWarnings("all")
+    public static Class<?> getSuperClassSnippet(Class<?> clazz) {
+        return clazz.getSuperclass();
+    }
+    @SuppressWarnings("all")
+    public static Class<?> getComponentTypeSnippet(Class<?> clazz) {
+        return clazz.getComponentType();
+    }
+
+
+    @Test
+    public void testThreadIntrinsics() {
+        test("currentThreadSnippet");
+        test("threadIsInterruptedSnippet");
+        test("threadInterruptedSnippet");
+    }
+
+    @SuppressWarnings("all")
+    public static Thread currentThreadSnippet() {
+        return Thread.currentThread();
+    }
+    @SuppressWarnings("all")
+    public static boolean threadIsInterruptedSnippet(Thread thread) {
+        return thread.isInterrupted();
+    }
+    @SuppressWarnings("all")
+    public static boolean threadInterruptedSnippet() {
+        return Thread.interrupted();
+    }
+
+
+    @Test
+    public void testSystemIntrinsics() {
+        test("systemTimeSnippet");
+        test("systemIdentityHashCode");
+//        test("arraycopySnippet");
+    }
+
+    @SuppressWarnings("all")
+    public static long systemTimeSnippet() {
+        return System.currentTimeMillis() + System.nanoTime();
+    }
+    @SuppressWarnings("all")
+    public static int systemIdentityHashCode(Object obj) {
+        return System.identityHashCode(obj);
+    }
+    @SuppressWarnings("all")
+    public static void arraycopySnippet(int[] src, int srcPos, int[] dest, int destPos, int length) {
+        System.arraycopy(src, srcPos, dest, destPos, length);
+    }
+
+
+    @Test
+    public void testUnsafeIntrinsics() {
+        test("unsafeCompareAndSwapIntSnippet");
+        test("unsafeCompareAndSwapLongSnippet");
+        test("unsafeCompareAndSwapObjectSnippet");
+
+        test("unsafeGetBooleanSnippet");
+        test("unsafeGetByteSnippet");
+        test("unsafeGetShortSnippet");
+        test("unsafeGetCharSnippet");
+        test("unsafeGetIntSnippet");
+        test("unsafeGetFloatSnippet");
+        test("unsafeGetDoubleSnippet");
+        test("unsafeGetObjectSnippet");
+
+        test("unsafePutBooleanSnippet");
+        test("unsafePutByteSnippet");
+        test("unsafePutShortSnippet");
+        test("unsafePutCharSnippet");
+        test("unsafePutIntSnippet");
+        test("unsafePutFloatSnippet");
+        test("unsafePutDoubleSnippet");
+        test("unsafePutObjectSnippet");
+
+        // test("unsafeDirectMemoryReadSnippet");
+        // test("unsafeDirectMemoryWriteSnippet");
+    }
+
+    @SuppressWarnings("all")
+    public static boolean unsafeCompareAndSwapIntSnippet(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.compareAndSwapInt(obj, offset, 0, 1);
+    }
+    @SuppressWarnings("all")
+    public static boolean unsafeCompareAndSwapLongSnippet(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.compareAndSwapLong(obj, offset, 0, 1);
+    }
+    @SuppressWarnings("all")
+    public static boolean unsafeCompareAndSwapObjectSnippet(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.compareAndSwapObject(obj, offset, null, new Object());
+    }
+    @SuppressWarnings("all")
+    public static boolean unsafeGetBooleanSnippet(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.getBoolean(obj, offset) &&
+               unsafe.getBooleanVolatile(obj, offset);
+    }
+    @SuppressWarnings("all")
+    public static int unsafeGetByteSnippet(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.getByte(obj, offset) +
+               unsafe.getByteVolatile(obj, offset);
+    }
+    @SuppressWarnings("all")
+    public static int unsafeGetShortSnippet(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.getShort(obj, offset) +
+               unsafe.getShortVolatile(obj, offset);
+    }
+    @SuppressWarnings("all")
+    public static int unsafeGetCharSnippet(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.getChar(obj, offset) +
+               unsafe.getCharVolatile(obj, offset);
+    }
+    @SuppressWarnings("all")
+    public static int unsafeGetIntSnippet(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.getInt(obj, offset) +
+               unsafe.getIntVolatile(obj, offset);
+    }
+    @SuppressWarnings("all")
+    public static long unsafeGetLongSnippet(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.getLong(obj, offset) +
+               unsafe.getLongVolatile(obj, offset);
+    }
+    @SuppressWarnings("all")
+    public static float unsafeGetFloatSnippet(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.getFloat(obj, offset) +
+               unsafe.getFloatVolatile(obj, offset);
+    }
+    @SuppressWarnings("all")
+    public static double unsafeGetDoubleSnippet(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.getDouble(obj, offset) +
+               unsafe.getDoubleVolatile(obj, offset);
+    }
+    @SuppressWarnings("all")
+    public static boolean unsafeGetObjectSnippet(Unsafe unsafe, Object obj, long offset) {
+        return unsafe.getObject(obj, offset) == unsafe.getObjectVolatile(obj, offset);
+    }
+    @SuppressWarnings("all")
+    public static void unsafePutBooleanSnippet(Unsafe unsafe, Object obj, long offset, boolean value) {
+        unsafe.putBoolean(obj, offset, value);
+        unsafe.putBooleanVolatile(obj, offset, value);
+    }
+    @SuppressWarnings("all")
+    public static void unsafePutByteSnippet(Unsafe unsafe, Object obj, long offset, byte value) {
+        unsafe.putByte(obj, offset, value);
+        unsafe.putByteVolatile(obj, offset, value);
+    }
+    @SuppressWarnings("all")
+    public static void unsafePutShortSnippet(Unsafe unsafe, Object obj, long offset, short value) {
+        unsafe.putShort(obj, offset, value);
+        unsafe.putShortVolatile(obj, offset, value);
+    }
+    @SuppressWarnings("all")
+    public static void unsafePutCharSnippet(Unsafe unsafe, Object obj, long offset, char value) {
+        unsafe.putChar(obj, offset, value);
+        unsafe.putCharVolatile(obj, offset, value);
+    }
+    @SuppressWarnings("all")
+    public static void unsafePutIntSnippet(Unsafe unsafe, Object obj, long offset, int value) {
+        unsafe.putInt(obj, offset, value);
+        unsafe.putIntVolatile(obj, offset, value);
+        unsafe.putOrderedInt(obj, offset, value);
+    }
+    @SuppressWarnings("all")
+    public static void unsafePutLongSnippet(Unsafe unsafe, Object obj, long offset, long value) {
+        unsafe.putLong(obj, offset, value);
+        unsafe.putLongVolatile(obj, offset, value);
+        unsafe.putOrderedLong(obj, offset, value);
+    }
+    @SuppressWarnings("all")
+    public static void unsafePutFloatSnippet(Unsafe unsafe, Object obj, long offset, float value) {
+        unsafe.putFloat(obj, offset, value);
+        unsafe.putFloatVolatile(obj, offset, value);
+    }
+    @SuppressWarnings("all")
+    public static void unsafePutDoubleSnippet(Unsafe unsafe, Object obj, long offset, double value) {
+        unsafe.putDouble(obj, offset, value);
+        unsafe.putDoubleVolatile(obj, offset, value);
+    }
+    @SuppressWarnings("all")
+    public static void unsafePutObjectSnippet(Unsafe unsafe, Object obj, long offset, Object value) {
+        unsafe.putObject(obj, offset, value);
+        unsafe.putObjectVolatile(obj, offset, value);
+        unsafe.putOrderedObject(obj, offset, value);
+    }
+    @SuppressWarnings("all")
+    public static double unsafeDirectMemoryReadSnippet(Unsafe unsafe, long address) {
+        // Unsafe.getBoolean(long) and Unsafe.getObject(long) do not exist
+        return unsafe.getByte(address) +
+               unsafe.getShort(address) +
+               unsafe.getChar(address) +
+               unsafe.getInt(address) +
+               unsafe.getLong(address) +
+               unsafe.getFloat(address) +
+               unsafe.getDouble(address);
+    }
+    @SuppressWarnings("all")
+    public static void unsafeDirectMemoryWriteSnippet(Unsafe unsafe, long address, byte value) {
+        // Unsafe.putBoolean(long) and Unsafe.putObject(long) do not exist
+        unsafe.putByte(address, value);
+        unsafe.putShort(address, value);
+        unsafe.putChar(address, (char) value);
+        unsafe.putInt(address, value);
+        unsafe.putLong(address, value);
+        unsafe.putFloat(address, value);
+        unsafe.putDouble(address, value);
+    }
+
+
+    @Test
+    public void testMathIntrinsics() {
+        test("mathSnippet");
+    }
+
+    @SuppressWarnings("all")
+    public static double mathSnippet(double value) {
+        return Math.abs(value) +
+               Math.sqrt(value) +
+               Math.log(value) +
+               Math.log10(value) +
+               Math.sin(value) +
+               Math.cos(value) +
+               Math.tan(value);
+//               Math.exp(value) +
+//               Math.pow(value, 13);
+    }
+
+
+    @Test
+    public void testIntegerIntrinsics() {
+        // TODO (chaeubl): some methods have Java implementations -> check more than Invoke nodes
+        test("integerSnippet");
+    }
+
+    @SuppressWarnings("all")
+    public static int integerSnippet(int value) {
+        return Integer.reverseBytes(value) +
+               Integer.numberOfLeadingZeros(value) +
+               Integer.numberOfTrailingZeros(value);
+    }
+
+
+    @Test
+    public void testLongIntrinsics() {
+        test("longSnippet");
+    }
+
+    @SuppressWarnings("all")
+    public static long longSnippet(long value) {
+        return Long.reverseBytes(value) +
+               Long.numberOfLeadingZeros(value) +
+               Long.numberOfTrailingZeros(value);
+    }
+
+
+    @Test
+    public void testFloatIntrinsics() {
+        test("floatSnippet");
+    }
+
+    @SuppressWarnings("all")
+    public static float floatSnippet(float value) {
+        return Float.intBitsToFloat(Float.floatToIntBits(value));
+    }
+
+
+    @Test
+    public void testDoubleIntrinsics() {
+        test("doubleSnippet");
+    }
+
+    @SuppressWarnings("all")
+    public static double doubleSnippet(double value) {
+        return Double.longBitsToDouble(Double.doubleToLongBits(value));
+    }
+
+
+    private StructuredGraph test(final String snippet) {
+        return Debug.scope("IntrinsificationTest", new DebugDumpScope(snippet), new Callable<StructuredGraph>() {
+            @Override
+            public StructuredGraph call() {
+                StructuredGraph graph = parse(snippet);
+                PhasePlan phasePlan = getDefaultPhasePlan();
+                Assumptions assumptions = new Assumptions(true);
+                Debug.dump(graph, "Graph");
+                new InliningPhase(null, runtime(), null, assumptions, null, phasePlan, OptimisticOptimizations.ALL).apply(graph);
+                Debug.dump(graph, "Graph");
+                new CanonicalizerPhase(null, runtime(), assumptions).apply(graph);
+                new DeadCodeEliminationPhase().apply(graph);
+
+                assertNoInvokes(graph);
+                return graph;
+            }
+        });
+    }
+
+    private static boolean assertNoInvokes(StructuredGraph graph) {
+        for (Invoke invoke: graph.getInvokes()) {
+            fail(invoke.toString());
+        }
+        return false;
+    }
+
+    private static class A {
+    }
+}