changeset 3146:a8db5b0e499f

Intrinsify arraycopy of primitive types to vector instructions.
author Thomas Wuerthinger <thomas@wuerthinger.net>
date Mon, 04 Jul 2011 18:54:54 +0200
parents dcf2b46665a0
children 92b24e9e7e88
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/AbstractVectorNode.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AccessVectorNode.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/ir/Constant.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/CreateVectorNode.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FixedGuard.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/If.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerAddVectorNode.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LocationNode.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ReadVectorNode.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Value.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/WriteVectorNode.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.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.runtime/src/com/oracle/max/graal/runtime/HotSpotRuntime.java
diffstat 17 files changed, 735 insertions(+), 45 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Mon Jul 04 12:21:42 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Mon Jul 04 18:54:54 2011 +0200
@@ -201,6 +201,10 @@
         this.operands = new OperandPool(compilation.target);
     }
 
+    public CiTarget target() {
+        return compilation.target;
+    }
+
     public LIRList lir() {
         return lir;
     }
@@ -738,8 +742,11 @@
 
     @Override
     public void visitFixedGuard(FixedGuard fixedGuard) {
-        BooleanNode comp = fixedGuard.node();
-        emitGuardComp(comp);
+        for (Node n : fixedGuard.inputs()) {
+            if (n != null) {
+                emitGuardComp((BooleanNode) n);
+            }
+        }
     }
 
     public void emitGuardComp(BooleanNode comp) {
@@ -1070,7 +1077,7 @@
             lastState = fs;
         } else if (block.blockPredecessors().size() == 1) {
             FrameState fs = block.blockPredecessors().get(0).lastState();
-            assert fs != null;
+            //assert fs != null : "B" + block.blockID() + ", pred=B" + block.blockPredecessors().get(0).blockID();
             if (GraalOptions.TraceLIRGeneratorLevel >= 2) {
                 TTY.println("STATE CHANGE (singlePred)");
                 if (GraalOptions.TraceLIRGeneratorLevel >= 3) {
@@ -1457,8 +1464,11 @@
     @Override
     public void visitEndNode(EndNode end) {
         setNoResult(end);
+        assert end.merge() != null;
         moveToPhi(end.merge(), end);
-        lir.jump(getLIRBlock(end.merge()));
+        LIRBlock lirBlock = getLIRBlock(end.merge());
+        assert lirBlock != null : end;
+        lir.jump(lirBlock);
     }
 
     @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AbstractVectorNode.java	Mon Jul 04 18:54:54 2011 +0200
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 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.compiler.ir;
+
+import java.util.*;
+
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public abstract class AbstractVectorNode extends FixedNodeWithNext {
+
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_VECTOR = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    public void setVector(AbstractVectorNode length) {
+        inputs().set(super.inputCount() + INPUT_VECTOR, length);
+    }
+
+    public AbstractVectorNode vector() {
+        return (AbstractVectorNode) inputs().get(super.inputCount() + INPUT_VECTOR);
+    }
+
+    public AbstractVectorNode(CiKind kind, int inputCount, int successorCount, AbstractVectorNode vector, Graph graph) {
+        super(kind, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph);
+        setVector(vector);
+    }
+
+    protected static AbstractVectorNode findCommonNode(AbstractVectorNode left, AbstractVectorNode right, List<AbstractVectorNode> leftList, List<AbstractVectorNode> rightList) {
+        Set<AbstractVectorNode> occured = new HashSet<AbstractVectorNode>();
+        AbstractVectorNode common = null;
+        AbstractVectorNode cur = left;
+        while (cur != null) {
+            occured.add(cur);
+            cur = cur.vector();
+        }
+
+        cur = right;
+        while (cur != null) {
+            if (occured.contains(cur)) {
+                common = cur;
+                break;
+            }
+            cur = cur.vector();
+        }
+
+        fillUntil(left, cur, leftList);
+        fillUntil(right, cur, rightList);
+        return common;
+    }
+
+    private static void fillUntil(AbstractVectorNode left, AbstractVectorNode until, List<AbstractVectorNode> leftList) {
+        AbstractVectorNode cur = left;
+        while (cur != null && cur != until) {
+            leftList.add(cur);
+            cur = cur.vector();
+        }
+    }
+
+    public void addToLoop(LoopBegin loop, IdentityHashMap<AbstractVectorNode, Value> nodes) {
+        throw new IllegalStateException("unimplemented");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AccessVectorNode.java	Mon Jul 04 18:54:54 2011 +0200
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 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.compiler.ir;
+
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public abstract class AccessVectorNode extends AbstractVectorNode {
+    private static final int INPUT_COUNT = 2;
+    private static final int INPUT_OBJECT = 0;
+    private static final int INPUT_LOCATION = 1;
+    private static final int SUCCESSOR_COUNT = 0;
+
+    @Override
+    protected int inputCount() {
+        return super.inputCount() + INPUT_COUNT;
+    }
+
+    @Override
+    protected int successorCount() {
+        return super.successorCount() + SUCCESSOR_COUNT;
+    }
+
+    public void setObject(Value object) {
+        inputs().set(super.inputCount() + INPUT_OBJECT, object);
+    }
+
+    public Value object() {
+        return (Value) inputs().get(super.inputCount() + INPUT_OBJECT);
+    }
+
+    public void setLocation(LocationNode object) {
+        inputs().set(super.inputCount() + INPUT_LOCATION, object);
+    }
+
+    public LocationNode location() {
+        return (LocationNode) inputs().get(super.inputCount() + INPUT_LOCATION);
+    }
+
+    public AccessVectorNode(CiKind kind, int inputCount, int successorCount, AbstractVectorNode vector, Value object, LocationNode location, Graph graph) {
+        super(kind, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, vector, graph);
+        setObject(object);
+        setLocation(location);
+    }
+}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Condition.java	Mon Jul 04 12:21:42 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Condition.java	Mon Jul 04 18:54:54 2011 +0200
@@ -173,10 +173,10 @@
                     case LE: return x <= y;
                     case GT: return x > y;
                     case GE: return x >= y;
-                    case AE: return UnsignedComparisons.aboveOrEqual(x, y);
-                    case BE: return UnsignedComparisons.belowOrEqual(x, y);
-                    case AT: return UnsignedComparisons.aboveThan(x, y);
-                    case BT: return UnsignedComparisons.belowThan(x, y);
+                    case AE: return toUnsigned(x) >= toUnsigned(y);
+                    case BE: return toUnsigned(x) <= toUnsigned(y);
+                    case AT: return toUnsigned(x) > toUnsigned(y);
+                    case BT: return toUnsigned(x) < toUnsigned(y);
                 }
                 break;
             }
@@ -204,4 +204,11 @@
         }
         return null;
     }
+
+    private long toUnsigned(int x) {
+        if (x < 0) {
+            return ((long) (x & 0x7FFFFFFF)) + ((long) Integer.MAX_VALUE) + 1;
+        }
+        return x;
+    }
 }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Constant.java	Mon Jul 04 12:21:42 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Constant.java	Mon Jul 04 18:54:54 2011 +0200
@@ -179,7 +179,7 @@
     public RiType declaredType() {
         RiRuntime runtime = compilation().runtime;
         if (kind.isPrimitive()) {
-            runtime.asRiType(kind);
+            return runtime.asRiType(kind);
         }
         return runtime.getTypeOf(asConstant());
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/CreateVectorNode.java	Mon Jul 04 18:54:54 2011 +0200
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 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.compiler.ir;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.compiler.phases.LoweringPhase.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public final class CreateVectorNode extends AbstractVectorNode {
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_LENGTH = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
+    private boolean reversed;
+
+    public void setLength(Value length) {
+        assert length == null || length.kind == CiKind.Int;
+        inputs().set(super.inputCount() + INPUT_LENGTH, length);
+    }
+
+    public boolean reversed() {
+        return reversed;
+    }
+
+    public void setReversed(boolean r) {
+        reversed = r;
+    }
+
+    public Value length() {
+        return (Value) inputs().get(super.inputCount() + INPUT_LENGTH);
+    }
+
+    public CreateVectorNode(boolean reversed, Value length, Graph graph) {
+        super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, null, graph);
+        setLength(length);
+        setReversed(reversed);
+    }
+
+    @Override
+    public Map<Object, Object> getDebugProperties() {
+        Map<Object, Object> debugProperties = super.getDebugProperties();
+        debugProperties.put("reversed", reversed);
+        return debugProperties;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == LIRGenerator.LIRGeneratorOp.class) {
+            return null;
+        } else if (clazz == LoweringOp.class) {
+            return (T) LOWERING_OP;
+        }
+        return super.lookup(clazz);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("vector with length ").print(length().toString());
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new CreateVectorNode(reversed, null, into);
+    }
+
+    @Override
+    public boolean valueEqual(Node i) {
+        return (i instanceof CreateVectorNode);
+    }
+
+    private LoopBegin createLoop(Map<AbstractVectorNode, Value> map) {
+        EndNode end = new EndNode(graph());
+        LoopBegin loopBegin = new LoopBegin(graph());
+        loopBegin.addEnd(end);
+        Phi loopVariable = new Phi(CiKind.Int, loopBegin, graph());
+
+        if (reversed) {
+            IntegerSub add = new IntegerSub(CiKind.Int, loopVariable, Constant.forInt(1, graph()), graph());
+            loopVariable.addInput(new IntegerSub(CiKind.Int, length(), Constant.forInt(1, graph()), graph()));
+            loopVariable.addInput(add);
+        } else {
+            IntegerAdd add = new IntegerAdd(CiKind.Int, loopVariable, Constant.forInt(1, graph()), graph());
+            loopVariable.addInput(Constant.forInt(0, graph()));
+            loopVariable.addInput(add);
+        }
+
+        LoopEnd loopEnd = new LoopEnd(graph());
+        loopEnd.setLoopBegin(loopBegin);
+        Compare condition;
+        if (reversed) {
+            condition = new Compare(loopVariable, Condition.GE, Constant.forInt(0, graph()), graph());
+        } else {
+            condition = new Compare(loopVariable, Condition.LT, length(), graph());
+        }
+        If ifNode = new If(condition, graph());
+        loopBegin.setNext(ifNode);
+        ifNode.setTrueSuccessor(loopEnd);
+        this.replaceAtPredecessors(end);
+        ifNode.setFalseSuccessor(this);
+        map.put(this, loopVariable);
+        return loopBegin;
+    }
+
+    private static final LoweringOp LOWERING_OP = new LoweringOp() {
+        @Override
+        public void lower(Node n, CiLoweringTool tool) {
+            CreateVectorNode vectorNode = (CreateVectorNode) n;
+
+            IdentityHashMap<AbstractVectorNode, Value> nodes = new IdentityHashMap<AbstractVectorNode, Value>();
+            LoopBegin begin = vectorNode.createLoop(nodes);
+            for (Node use : vectorNode.usages()) {
+                processUse(begin, use, nodes);
+            }
+        }
+
+        private void processUse(LoopBegin loop, Node use, IdentityHashMap<AbstractVectorNode, Value> nodes) {
+            AbstractVectorNode vectorNode = (AbstractVectorNode) use;
+            if (nodes.containsKey(vectorNode)) {
+                return;
+            }
+            nodes.put(vectorNode, null);
+
+            // Make sure inputs are evaluated.
+            for (Node input : use.inputs()) {
+                if (input instanceof AbstractVectorNode) {
+                    AbstractVectorNode abstractVectorNodeInput = (AbstractVectorNode) input;
+                    processUse(loop, abstractVectorNodeInput, nodes);
+                }
+            }
+
+            vectorNode.addToLoop(loop, nodes);
+
+            // Go on to usages.
+            for (Node usage : use.usages()) {
+                processUse(loop, usage, nodes);
+            }
+        }
+    };
+}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FixedGuard.java	Mon Jul 04 12:21:42 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FixedGuard.java	Mon Jul 04 18:54:54 2011 +0200
@@ -31,25 +31,16 @@
 
 
 public final class FixedGuard extends FixedNodeWithNext {
-    private static final int INPUT_COUNT = 1;
-    private static final int INPUT_NODE = 0;
-
+    private static final int INPUT_COUNT = 0;
     private static final int SUCCESSOR_COUNT = 0;
 
-    /**
-     * The instruction that produces the object tested against null.
-     */
-     public BooleanNode node() {
-        return (BooleanNode) inputs().get(super.inputCount() + INPUT_NODE);
+    public FixedGuard(BooleanNode node, Graph graph) {
+        this(graph);
+        addNode(node);
     }
 
-    public void setNode(BooleanNode n) {
-        inputs().set(super.inputCount() + INPUT_NODE, n);
-    }
-
-    public FixedGuard(BooleanNode node, Graph graph) {
+    public FixedGuard(Graph graph) {
         super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph);
-        setNode(node);
     }
 
     @Override
@@ -59,12 +50,16 @@
 
     @Override
     public void print(LogStream out) {
-        out.print("clip node ").print(node());
+        out.print("clip node ").print(inputs().toString());
+    }
+
+    public void addNode(BooleanNode node) {
+        inputs().add(node);
     }
 
     @Override
     public Node copy(Graph into) {
-        return new FixedGuard(null, into);
+        return new FixedGuard(into);
     }
 
     @SuppressWarnings("unchecked")
@@ -80,20 +75,26 @@
         @Override
         public Node canonical(Node node) {
             FixedGuard fixedGuard = (FixedGuard) node;
-            if (fixedGuard.node() instanceof Constant) {
-                Constant c = (Constant) fixedGuard.node();
-                if (c.asConstant().asBoolean()) {
-                    if (GraalOptions.TraceCanonicalizer) {
-                        TTY.println("Removing redundant fixed guard " + fixedGuard);
+            for (Node n : fixedGuard.inputs()) {
+                if (n instanceof Constant) {
+                    Constant c = (Constant) n;
+                    if (c.asConstant().asBoolean()) {
+                        if (GraalOptions.TraceCanonicalizer) {
+                            TTY.println("Removing redundant fixed guard " + fixedGuard);
+                        }
+                        fixedGuard.inputs().remove(c);
+                    } else {
+                        if (GraalOptions.TraceCanonicalizer) {
+                            TTY.println("Replacing fixed guard " + fixedGuard + " with deoptimization node");
+                        }
+                        return new Deoptimize(DeoptAction.InvalidateRecompile, fixedGuard.graph());
                     }
-                    return fixedGuard.next();
-                } else {
-                    if (GraalOptions.TraceCanonicalizer) {
-                        TTY.println("Replacing fixed guard " + fixedGuard + " with deoptimization node");
-                    }
-                    return new Deoptimize(DeoptAction.InvalidateRecompile, fixedGuard.graph());
                 }
             }
+
+            if (fixedGuard.inputs().size() == 0) {
+                return fixedGuard.next();
+            }
             return fixedGuard;
         }
     };
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/If.java	Mon Jul 04 12:21:42 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/If.java	Mon Jul 04 18:54:54 2011 +0200
@@ -81,6 +81,16 @@
         return blockSuccessor(1);
     }
 
+
+    public void setTrueSuccessor(FixedNode node) {
+        setBlockSuccessor(0, node);
+    }
+
+
+    public void setFalseSuccessor(FixedNode node) {
+        setBlockSuccessor(1, node);
+    }
+
     /**
      * Gets the block corresponding to the specified outcome of the branch.
      * @param istrue {@code true} if the true successor is requested, {@code false} otherwise
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerAddVectorNode.java	Mon Jul 04 18:54:54 2011 +0200
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 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.compiler.ir;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public final class IntegerAddVectorNode extends AbstractVectorNode {
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_VALUE = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
+    public Value value() {
+        return (Value) inputs().get(super.inputCount() + INPUT_VALUE);
+    }
+
+    public void setValue(Value v) {
+        inputs().set(super.inputCount() + INPUT_VALUE, v);
+    }
+
+    public IntegerAddVectorNode(AbstractVectorNode vector, Value value, Graph graph) {
+        super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, vector, graph);
+        setValue(value);
+    }
+
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == LIRGenerator.LIRGeneratorOp.class) {
+            return null;
+        }
+        return super.lookup(clazz);
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new IntegerAddVectorNode(null, null, into);
+    }
+
+    @Override
+    public void addToLoop(LoopBegin loop, IdentityHashMap<AbstractVectorNode, Value> nodes) {
+        nodes.put(this, new IntegerAdd(CiKind.Int, nodes.get(vector()), value(), graph()));
+    }
+}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LocationNode.java	Mon Jul 04 12:21:42 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LocationNode.java	Mon Jul 04 18:54:54 2011 +0200
@@ -26,18 +26,36 @@
 import com.oracle.max.graal.compiler.gen.*;
 import com.oracle.max.graal.graph.*;
 import com.sun.cri.ci.*;
+import com.sun.cri.ci.CiAddress.*;
 
 
 public final class LocationNode extends FloatingNode {
-    private static final int INPUT_COUNT = 0;
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_INDEX = 0;
     private static final int SUCCESSOR_COUNT = 0;
 
     public static final Object FINAL_LOCATION = new Object();
 
+    public static Object getArrayLocation(CiKind elementKind) {
+        return elementKind;
+    }
+
     private int displacement;
     private CiKind valueKind;
     private Object locationIdentity;
 
+    public int displacement() {
+        return displacement;
+    }
+
+    public Value index() {
+        return (Value) inputs().get(super.inputCount() + INPUT_INDEX);
+    }
+
+    public void setIndex(Value index) {
+        inputs().set(super.inputCount() + INPUT_INDEX, index);
+    }
+
     public static LocationNode create(Object identity, CiKind kind, int displacement, Graph graph) {
         LocationNode result = new LocationNode(identity, kind, displacement, graph);
         return graph.ideal(result);
@@ -73,7 +91,13 @@
     }
 
     public CiValue createAddress(LIRGenerator lirGenerator, Value object) {
-        return new CiAddress(valueKind, lirGenerator.load(object), displacement);
+        CiValue indexValue = CiValue.IllegalValue;
+        Scale indexScale = Scale.Times1;
+        if (this.index() != null) {
+            indexValue = lirGenerator.load(this.index());
+            indexScale = Scale.fromInt(valueKind.sizeInBytes(lirGenerator.target().wordSize));
+        }
+        return new CiAddress(valueKind, lirGenerator.load(object), indexValue, indexScale, displacement);
     }
 
     public Object locationIdentity() {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ReadVectorNode.java	Mon Jul 04 18:54:54 2011 +0200
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 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.compiler.ir;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public final class ReadVectorNode extends AccessVectorNode {
+    private static final int INPUT_COUNT = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
+    public ReadVectorNode(AbstractVectorNode vector, Value object, LocationNode location, Graph graph) {
+        super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, vector, object, location, graph);
+    }
+
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == LIRGenerator.LIRGeneratorOp.class) {
+            return null;
+        }
+        return super.lookup(clazz);
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new ReadVectorNode(null, null, null, into);
+    }
+
+
+    @Override
+    public void addToLoop(LoopBegin loop, IdentityHashMap<AbstractVectorNode, Value> nodes) {
+        LocationNode newLocation = LocationNode.create(LocationNode.getArrayLocation(location().getValueKind()), location().getValueKind(), location().displacement(), graph());
+        Value index = nodes.get(vector());
+        assert index != null;
+        newLocation.setIndex(index);
+        ReadNode readNode = new ReadNode(location().getValueKind().stackKind(), object(), newLocation, graph());
+        loop.loopEnd().replaceAtPredecessors(readNode);
+        readNode.setNext(loop.loopEnd());
+        nodes.put(this, readNode);
+    }
+}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Value.java	Mon Jul 04 12:21:42 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Value.java	Mon Jul 04 18:54:54 2011 +0200
@@ -53,7 +53,7 @@
      */
     public Value(CiKind kind, int inputCount, int successorCount, Graph graph) {
         super(inputCount, successorCount, graph);
-        assert kind == kind.stackKind() : kind + " != " + kind.stackKind();
+        assert kind != null && kind == kind.stackKind() : kind + " != " + kind.stackKind();
         this.kind = kind;
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/WriteVectorNode.java	Mon Jul 04 18:54:54 2011 +0200
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 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.compiler.ir;
+
+import java.util.*;
+
+import com.oracle.max.graal.compiler.debug.*;
+import com.oracle.max.graal.compiler.gen.*;
+import com.oracle.max.graal.graph.*;
+import com.sun.cri.ci.*;
+
+
+public final class WriteVectorNode extends AccessVectorNode {
+    private static final int INPUT_COUNT = 1;
+    private static final int INPUT_VALUES = 0;
+    private static final int SUCCESSOR_COUNT = 0;
+
+    public void setValues(AbstractVectorNode length) {
+        inputs().set(super.inputCount() + INPUT_VALUES, length);
+    }
+
+    public AbstractVectorNode values() {
+        return (AbstractVectorNode) inputs().get(super.inputCount() + INPUT_VALUES);
+    }
+
+    public WriteVectorNode(AbstractVectorNode vector, Value object, LocationNode location, AbstractVectorNode values, Graph graph) {
+        super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, vector, object, location, graph);
+        setValues(values);
+    }
+
+    @Override
+    public <T extends Op> T lookup(Class<T> clazz) {
+        if (clazz == LIRGenerator.LIRGeneratorOp.class) {
+            return null;
+        }
+        return super.lookup(clazz);
+    }
+
+    @Override
+    public void print(LogStream out) {
+        out.print("write vector node " + values());
+    }
+
+    @Override
+    public Node copy(Graph into) {
+        return new WriteVectorNode(null, null, null, null, into);
+    }
+
+
+    @Override
+    public void addToLoop(LoopBegin loop, IdentityHashMap<AbstractVectorNode, Value> nodes) {
+        LocationNode newLocation = LocationNode.create(LocationNode.getArrayLocation(location().getValueKind()), location().getValueKind(), location().displacement(), graph());
+        Value index = nodes.get(vector());
+        Value value = nodes.get(values());
+        assert index != null;
+        assert value != null;
+        newLocation.setIndex(index);
+        WriteNode writeNode = new WriteNode(location().getValueKind().stackKind(), object(), value, newLocation, graph());
+        loop.loopEnd().replaceAtPredecessors(writeNode);
+        writeNode.setNext(loop.loopEnd());
+    }
+}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java	Mon Jul 04 12:21:42 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java	Mon Jul 04 18:54:54 2011 +0200
@@ -73,6 +73,12 @@
                     flood.add(successor);
                 }
             }
+
+            if (current instanceof AbstractVectorNode) {
+                for (Node usage : current.usages()) {
+                    flood.add(usage);
+                }
+            }
         }
     }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java	Mon Jul 04 12:21:42 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java	Mon Jul 04 18:54:54 2011 +0200
@@ -118,13 +118,13 @@
     private RiMethod inlineInvoke(Invoke invoke, int iterations, float ratio) {
         RiMethod parent = invoke.stateAfter().method();
         RiTypeProfile profile = parent.typeProfile(invoke.bci);
-        if (!checkInvokeConditions(invoke)) {
-            return null;
-        }
         if (GraalOptions.Intrinsify && compilation.runtime.intrinsicGraph(invoke.target, invoke.arguments()) != null) {
             // Always intrinsify.
             return invoke.target;
         }
+        if (!checkInvokeConditions(invoke)) {
+            return null;
+        }
         if (invoke.opcode() == Bytecodes.INVOKESPECIAL || invoke.target.canBeStaticallyBound()) {
             if (checkTargetConditions(invoke.target, iterations) && checkSizeConditions(invoke.target, invoke, profile, ratio)) {
                 return invoke.target;
@@ -323,7 +323,7 @@
             exceptionEdge = ((Placeholder) exceptionEdge).next();
         }
 
-        boolean withReceiver = !Modifier.isStatic(method.accessFlags());
+        boolean withReceiver = !invoke.isStatic();
 
         int argumentCount = method.signature().argumentCount(false);
         Value[] parameters = new Value[argumentCount + (withReceiver ? 1 : 0)];
@@ -340,6 +340,12 @@
         CompilerGraph graph = null;
         if (GraalOptions.Intrinsify) {
             graph = (CompilerGraph) compilation.runtime.intrinsicGraph(method, invoke.arguments());
+            if (graph != null && graph.getNodes(Merge.class).iterator().hasNext()) {
+                WriteMemoryCheckpointNode checkpoint = new WriteMemoryCheckpointNode(invoke.graph());
+                checkpoint.setStateAfter(invoke.stateAfter());
+                checkpoint.setNext(invoke.next());
+                invoke.setNext(checkpoint);
+            }
         }
         if (graph != null) {
             if (GraalOptions.TraceInlining) {
@@ -351,7 +357,7 @@
 
         if (graph != null) {
             if (GraalOptions.TraceInlining) {
-                TTY.println("Reusing graph for %s, locals: %d, stack: %d", methodName(method, invoke), method.maxLocals(), method.maxStackSize());
+                TTY.println("Reusing graph for %s", methodName(method, invoke));
             }
         } else {
             if (GraalOptions.TraceInlining) {
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRAssembler.java	Mon Jul 04 12:21:42 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRAssembler.java	Mon Jul 04 18:54:54 2011 +0200
@@ -554,6 +554,8 @@
                     case GT : acond = ConditionFlag.greater; break;
                     case BE : acond = ConditionFlag.belowEqual; break;
                     case AE : acond = ConditionFlag.aboveEqual; break;
+                    case AT : acond = ConditionFlag.above; break;
+                    case BT : acond = ConditionFlag.below; break;
                     default : throw Util.shouldNotReachHere();
                 }
                 // Checkstyle: on
--- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotRuntime.java	Mon Jul 04 12:21:42 2011 +0200
+++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotRuntime.java	Mon Jul 04 18:54:54 2011 +0200
@@ -26,6 +26,8 @@
 import java.lang.reflect.*;
 import java.util.*;
 
+import com.oracle.max.graal.compiler.*;
+import com.oracle.max.graal.compiler.debug.*;
 import com.oracle.max.graal.compiler.graph.*;
 import com.oracle.max.graal.compiler.ir.*;
 import com.oracle.max.graal.graph.*;
@@ -284,7 +286,8 @@
         if (!intrinsicGraphs.containsKey(method)) {
             RiType holder = method.holder();
             String fullName = method.name() + method.signature().asString();
-            if (holder.name().equals("Ljava/lang/Object;")) {
+            String holderName = holder.name();
+            if (holderName.equals("Ljava/lang/Object;")) {
                 if (fullName.equals("getClass()Ljava/lang/Class;")) {
                     CompilerGraph graph = new CompilerGraph(this);
                     Local receiver = new Local(CiKind.Object, 0, graph);
@@ -294,6 +297,88 @@
                     graph.setReturn(ret);
                     intrinsicGraphs.put(method, graph);
                 }
+            } else if (holderName.equals("Ljava/lang/System;")) {
+                if (fullName.equals("arraycopy(Ljava/lang/Object;ILjava/lang/Object;II)V")) {
+                    CompilerGraph graph = new CompilerGraph(this);
+                    Local src = new Local(CiKind.Object, 0, graph);
+                    Local srcPos = new Local(CiKind.Int, 1, graph);
+                    Local dest = new Local(CiKind.Object, 2, graph);
+                    Local destPos = new Local(CiKind.Int, 3, graph);
+                    Local length = new Local(CiKind.Int, 4, graph);
+                    src.setDeclaredType(((Value) parameters.get(0)).declaredType());
+                    dest.setDeclaredType(((Value) parameters.get(2)).declaredType());
+
+                    if (src.declaredType() == null || dest.declaredType() == null) {
+                        return null;
+                    }
+
+                    if (src.declaredType() != dest.declaredType()) {
+                        return null;
+                    }
+
+                    if (!src.declaredType().isArrayClass()) {
+                        return null;
+                    }
+
+                    CiKind componentType = src.declaredType().componentType().kind();
+
+                    if (componentType == CiKind.Object) {
+                        return null;
+                    }
+
+                    // Add preconditions.
+                    FixedGuard guard = new FixedGuard(graph);
+                    ArrayLength srcLength = new ArrayLength(src, graph);
+                    ArrayLength destLength = new ArrayLength(dest, graph);
+                    IntegerAdd upperLimitSrc = new IntegerAdd(CiKind.Int, srcPos, length, graph);
+                    IntegerAdd upperLimitDest = new IntegerAdd(CiKind.Int, destPos, length, graph);
+                    guard.addNode(new Compare(srcPos, Condition.BE, srcLength, graph));
+                    guard.addNode(new Compare(destPos, Condition.BE, destLength, graph));
+                    guard.addNode(new Compare(length, Condition.GE, Constant.forInt(0, graph), graph));
+                    guard.addNode(new Compare(upperLimitSrc, Condition.LE, srcLength, graph));
+                    guard.addNode(new Compare(upperLimitDest, Condition.LE, destLength, graph));
+                    graph.start().setNext(guard);
+
+                    LocationNode location = LocationNode.create(LocationNode.FINAL_LOCATION, componentType, config.getArrayOffset(componentType), graph);
+
+                    // Build normal vector instruction.
+                    CreateVectorNode normalVector = new CreateVectorNode(false, length, graph);
+                    ReadVectorNode values = new ReadVectorNode(new IntegerAddVectorNode(normalVector, srcPos, graph), src, location, graph);
+                    new WriteVectorNode(new IntegerAddVectorNode(normalVector, destPos, graph), dest, location, values, graph);
+
+                    // Build reverse vector instruction.
+                    CreateVectorNode reverseVector = new CreateVectorNode(true, length, graph);
+                    ReadVectorNode reverseValues = new ReadVectorNode(new IntegerAddVectorNode(reverseVector, srcPos, graph), src, location, graph);
+                    new WriteVectorNode(new IntegerAddVectorNode(reverseVector, destPos, graph), dest, location, reverseValues, graph);
+
+                    If ifNode = new If(new Compare(src, Condition.EQ, dest, graph), graph);
+                    guard.setNext(ifNode);
+
+                    If secondIf = new If(new Compare(srcPos, Condition.LT, destPos, graph), graph);
+                    ifNode.setTrueSuccessor(secondIf);
+
+                    secondIf.setTrueSuccessor(reverseVector);
+
+                    Merge merge1 = new Merge(graph);
+                    merge1.addEnd(new EndNode(graph));
+                    merge1.addEnd(new EndNode(graph));
+
+                    ifNode.setFalseSuccessor(merge1.endAt(0));
+                    secondIf.setFalseSuccessor(merge1.endAt(1));
+                    merge1.setNext(normalVector);
+
+                    Merge merge2 = new Merge(graph);
+                    merge2.addEnd(new EndNode(graph));
+                    merge2.addEnd(new EndNode(graph));
+
+                    normalVector.setNext(merge2.endAt(0));
+                    reverseVector.setNext(merge2.endAt(1));
+
+                    Return ret = new Return(null, graph);
+                    merge2.setNext(ret);
+                    graph.setReturn(ret);
+                    return graph;
+                }
             }
 
             if (!intrinsicGraphs.containsKey(method)) {