changeset 3188:48bad23422a7

Added intrinsification example (safe add).
author Thomas Wuerthinger <thomas@wuerthinger.net>
date Thu, 07 Jul 2011 19:57:45 +0200
parents ef0ff458d074
children 78b183d482ba
files graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Condition.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRAssembler.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/extensions/Intrinsifier.java graal/com.oracle.max.graal.examples/bin/META-INF/services/com.oracle.max.graal.extensions.Intrinsifier graal/com.oracle.max.graal.examples/src/META-INF/services/com.oracle.max.graal.extensions.Intrinsifier graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/Main.java graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/intrinsics/IntrinsifierImpl.java graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/intrinsics/SafeAdd.java graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/intrinsics/SafeAddExample.java graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/opt/OptimizationExample.java
diffstat 12 files changed, 311 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Thu Jul 07 18:15:25 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Thu Jul 07 19:57:45 2011 +0200
@@ -801,23 +801,33 @@
             XirSnippet typeCheck = xir.genTypeCheck(site(x), toXirArgument(x.object()), clazz, x.type());
             emitXir(typeCheck, x, info, compilation.method, false);
         } else {
-            FrameState state = lastState;
-            assert state != null : "deoptimize instruction always needs a state";
-
             if (comp instanceof Constant && comp.asConstant().asBoolean()) {
                 // Nothing to emit.
             } else {
-            if (deoptimizationStubs == null) {
-                deoptimizationStubs = new ArrayList<DeoptimizationStub>();
+                DeoptimizationStub stub = createDeoptStub();
+                emitBooleanBranch(comp, null, new LIRBlock(stub.label, stub.info), stub.info);
             }
-
-            DeoptimizationStub stub = new DeoptimizationStub(DeoptAction.InvalidateReprofile, state);
-            deoptimizationStubs.add(stub);
-            emitBooleanBranch(comp, null, new LIRBlock(stub.label, stub.info), stub.info);
-        }
         }
     }
 
+    private DeoptimizationStub createDeoptStub() {
+        if (deoptimizationStubs == null) {
+            deoptimizationStubs = new ArrayList<DeoptimizationStub>();
+        }
+
+        FrameState state = lastState;
+        assert state != null : "deoptimize instruction always needs a state";
+        DeoptimizationStub stub = new DeoptimizationStub(DeoptAction.InvalidateReprofile, state);
+        deoptimizationStubs.add(stub);
+        return stub;
+    }
+
+    public void deoptimizeOn(Condition cond) {
+        DeoptimizationStub stub = createDeoptStub();
+        lir.branch(cond, stub.label, stub.info);
+    }
+
+
     @Override
     public void visitPhi(Phi i) {
         Util.shouldNotReachHere();
@@ -1270,7 +1280,7 @@
         }
     }
 
-    protected void arithmeticOpLong(int code, CiValue result, CiValue left, CiValue right) {
+    public void arithmeticOpLong(int code, CiValue result, CiValue left, CiValue right) {
         CiValue leftOp = left;
 
         if (isTwoOperand && leftOp != result) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Condition.java	Thu Jul 07 18:15:25 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Condition.java	Thu Jul 07 19:57:45 2011 +0200
@@ -79,6 +79,16 @@
      */
     BT("|<|"),
 
+    /**
+     * Operation produced an overflow.
+     */
+    OF("overflow"),
+
+    /**
+     * Operation did not produce an overflow.
+     */
+    NOF("noOverflow"),
+
     TRUE("TRUE");
 
     public final String operator;
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java	Thu Jul 07 18:15:25 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java	Thu Jul 07 19:57:45 2011 +0200
@@ -121,9 +121,14 @@
     private RiMethod inlineInvoke(Invoke invoke, int iterations, float ratio) {
         RiMethod parent = invoke.stateAfter().method();
         RiTypeProfile profile = parent.typeProfile(invoke.bci);
-        if (GraalOptions.Intrinsify && compilation.runtime.intrinsicGraph(parent, invoke.bci, invoke.target, invoke.arguments()) != null) {
-            // Always intrinsify.
-            return invoke.target;
+        if (GraalOptions.Intrinsify) {
+            if (GraalOptions.Extend && intrinsicGraph(parent, invoke.bci, invoke.target, invoke.arguments()) != null) {
+                return invoke.target;
+            }
+            if (compilation.runtime.intrinsicGraph(parent, invoke.bci, invoke.target, invoke.arguments()) != null) {
+                // Always intrinsify.
+                return invoke.target;
+            }
         }
         if (!checkInvokeConditions(invoke)) {
             return null;
@@ -366,6 +371,25 @@
         return previousDecision;
     }
 
+
+    public static ThreadLocal<ServiceLoader<Intrinsifier>> intrinsicLoader = new ThreadLocal<ServiceLoader<Intrinsifier>>();
+
+    private Graph intrinsicGraph(RiMethod parent, int bci, RiMethod target, List<Value> arguments) {
+        ServiceLoader<Intrinsifier> serviceLoader = intrinsicLoader.get();
+        if (serviceLoader == null) {
+            serviceLoader = ServiceLoader.load(Intrinsifier.class);
+            intrinsicLoader.set(serviceLoader);
+        }
+
+        for (Intrinsifier intrinsifier : serviceLoader) {
+            Graph result = intrinsifier.intrinsicGraph(compilation.runtime, parent, bci, target, arguments);
+            if (result != null) {
+                return result;
+            }
+        }
+        return null;
+    }
+
     private void inlineMethod(Invoke invoke, RiMethod method) {
         RiMethod parent = invoke.stateAfter().method();
         FrameState stateAfter = invoke.stateAfter();
@@ -390,7 +414,12 @@
 
         CompilerGraph graph = null;
         if (GraalOptions.Intrinsify) {
-            graph = (CompilerGraph) compilation.runtime.intrinsicGraph(parent, invoke.bci, method, invoke.arguments());
+            if (GraalOptions.Extend) {
+                graph = (CompilerGraph) intrinsicGraph(parent, invoke.bci, method, invoke.arguments());
+            }
+            if (graph == null) {
+                graph = (CompilerGraph) compilation.runtime.intrinsicGraph(parent, invoke.bci, method, invoke.arguments());
+            }
         }
         if (graph != null) {
             if (GraalOptions.TraceInlining) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRAssembler.java	Thu Jul 07 18:15:25 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRAssembler.java	Thu Jul 07 19:57:45 2011 +0200
@@ -556,6 +556,8 @@
                     case AE : acond = ConditionFlag.aboveEqual; break;
                     case AT : acond = ConditionFlag.above; break;
                     case BT : acond = ConditionFlag.below; break;
+                    case OF : acond = ConditionFlag.overflow; break;
+                    case NOF : acond = ConditionFlag.noOverflow; break;
                     default : throw Util.shouldNotReachHere();
                 }
                 // Checkstyle: on
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/extensions/Intrinsifier.java	Thu Jul 07 19:57:45 2011 +0200
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.extensions;
+
+import java.util.*;
+
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ri.*;
+
+
+public interface Intrinsifier {
+    Graph intrinsicGraph(RiRuntime runtime, RiMethod caller, int bci, RiMethod method, List<? extends Node> parameters);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/bin/META-INF/services/com.oracle.max.graal.extensions.Intrinsifier	Thu Jul 07 19:57:45 2011 +0200
@@ -0,0 +1,1 @@
+com.oracle.max.graal.examples.intrinsics.IntrinsifierImpl
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/src/META-INF/services/com.oracle.max.graal.extensions.Intrinsifier	Thu Jul 07 19:57:45 2011 +0200
@@ -0,0 +1,1 @@
+com.oracle.max.graal.examples.intrinsics.IntrinsifierImpl
\ No newline at end of file
--- a/graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/Main.java	Thu Jul 07 18:15:25 2011 +0200
+++ b/graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/Main.java	Thu Jul 07 19:57:45 2011 +0200
@@ -22,13 +22,14 @@
  */
 package com.oracle.max.graal.examples;
 
-import com.oracle.max.graal.examples.inlining.*;
+import com.oracle.max.graal.examples.intrinsics.*;
 
 
 public class Main {
 
     public static void main(String[] args) {
-        InliningExample.run();
+//        InliningExample.run();
+        SafeAddExample.run();
     }
 
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/intrinsics/IntrinsifierImpl.java	Thu Jul 07 19:57:45 2011 +0200
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.examples.intrinsics;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.graph.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.extensions.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+import com.sun.cri.ri.*;
+
+
+public class IntrinsifierImpl implements Intrinsifier {
+
+    @Override
+    public Graph intrinsicGraph(RiRuntime runtime, RiMethod caller, int bci, RiMethod method, List<? extends Node> parameters) {
+        if (method.holder().name().equals("Lcom/oracle/max/graal/examples/intrinsics/SafeAddExample;") && method.name().equals("safeAdd")) {
+            CompilerGraph graph = new CompilerGraph(runtime);
+            Return returnNode = new Return(new SafeAdd(new Local(CiKind.Long, 0, graph), new Local(CiKind.Long, 1, graph), graph), graph);
+            graph.start().setNext(returnNode);
+            graph.setReturn(returnNode);
+            return graph;
+        }
+        return null;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/intrinsics/SafeAdd.java	Thu Jul 07 19:57:45 2011 +0200
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.examples.intrinsics;
+
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.compiler.ir.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.bytecode.*;
+import com.sun.cri.ci.*;
+
+
+public final class SafeAdd extends IntegerArithmetic {
+    public SafeAdd(Value x, Value y, Graph graph) {
+        super(CiKind.Long, Bytecodes.LADD, x, y, graph);
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new SafeAdd(null, null, into);
+    }
+
+    @Override
+    public String shortName() {
+        return "[+]";
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == LIRGenerator.LIRGeneratorOp.class) {
+            return (T) GENERATOR_OP;
+        }
+        return super.lookup(clazz);
+    }
+
+    private static final LIRGenerator.LIRGeneratorOp GENERATOR_OP = new LIRGenerator.LIRGeneratorOp() {
+        @Override
+        public void generate(Node n, LIRGenerator generator) {
+            SafeAdd add = (SafeAdd) n;
+            generator.arithmeticOpLong(Bytecodes.LADD, generator.createResultVariable(add), generator.load(add.x()), generator.load(add.y()));
+            generator.deoptimizeOn(Condition.OF);
+        }
+    };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/intrinsics/SafeAddExample.java	Thu Jul 07 19:57:45 2011 +0200
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.examples.intrinsics;
+
+
+public class SafeAddExample {
+
+    public static final int N = 100000000;
+
+    public static void run() {
+        long start = System.currentTimeMillis();
+        System.out.println(test());
+        System.out.println(System.currentTimeMillis() - start);
+    }
+
+    private static long test() {
+        long sum = 0;
+        for (long i = -N; i < N; ++i) {
+            sum = safeAdd(sum, i);
+        }
+        return sum;
+    }
+
+    private static long safeAdd(long a, long b) {
+        long result = a + b;
+        if (b < 0 && result > a) {
+            throw new IllegalStateException("underflow when adding " + a + " and " + b);
+        } else if (b > 0 && result < a) {
+            throw new IllegalStateException("overflow when adding " + a + " and " + b);
+        }
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.examples/src/com/oracle/max/graal/examples/opt/OptimizationExample.java	Thu Jul 07 19:57:45 2011 +0200
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.max.graal.examples.opt;
+
+import java.math.*;
+
+
+public class OptimizationExample {
+
+    public static void run() {
+        long start = System.currentTimeMillis();
+        System.out.println(test(1, 2));
+        System.out.println(System.currentTimeMillis() - start);
+    }
+
+    private static long test(long a, long b) {
+        BigInteger bigA = BigInteger.valueOf(a);
+        BigInteger bigB = BigInteger.valueOf(b);
+        return bigA.add(bigB).longValue();
+    }
+}