# HG changeset patch # User Thomas Wuerthinger # Date 1309798494 -7200 # Node ID a8db5b0e499fd39b96cb8a08190f1f0ce2cefd6e # Parent dcf2b46665a01694d340c66909add5441bccbafa Intrinsify arraycopy of primitive types to vector instructions. diff -r dcf2b46665a0 -r a8db5b0e499f graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java --- 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 diff -r dcf2b46665a0 -r a8db5b0e499f graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AbstractVectorNode.java --- /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 leftList, List rightList) { + Set occured = new HashSet(); + 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 leftList) { + AbstractVectorNode cur = left; + while (cur != null && cur != until) { + leftList.add(cur); + cur = cur.vector(); + } + } + + public void addToLoop(LoopBegin loop, IdentityHashMap nodes) { + throw new IllegalStateException("unimplemented"); + } +} diff -r dcf2b46665a0 -r a8db5b0e499f graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/AccessVectorNode.java --- /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); + } +} diff -r dcf2b46665a0 -r a8db5b0e499f graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Condition.java --- 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; + } } diff -r dcf2b46665a0 -r a8db5b0e499f graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Constant.java --- 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()); } diff -r dcf2b46665a0 -r a8db5b0e499f graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/CreateVectorNode.java --- /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 getDebugProperties() { + Map debugProperties = super.getDebugProperties(); + debugProperties.put("reversed", reversed); + return debugProperties; + } + + @SuppressWarnings("unchecked") + @Override + public T lookup(Class 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 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 nodes = new IdentityHashMap(); + LoopBegin begin = vectorNode.createLoop(nodes); + for (Node use : vectorNode.usages()) { + processUse(begin, use, nodes); + } + } + + private void processUse(LoopBegin loop, Node use, IdentityHashMap 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); + } + } + }; +} diff -r dcf2b46665a0 -r a8db5b0e499f graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FixedGuard.java --- 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; } }; diff -r dcf2b46665a0 -r a8db5b0e499f graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/If.java --- 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 diff -r dcf2b46665a0 -r a8db5b0e499f graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerAddVectorNode.java --- /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 lookup(Class 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 nodes) { + nodes.put(this, new IntegerAdd(CiKind.Int, nodes.get(vector()), value(), graph())); + } +} diff -r dcf2b46665a0 -r a8db5b0e499f graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LocationNode.java --- 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() { diff -r dcf2b46665a0 -r a8db5b0e499f graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ReadVectorNode.java --- /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 lookup(Class 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 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); + } +} diff -r dcf2b46665a0 -r a8db5b0e499f graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Value.java --- 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; } diff -r dcf2b46665a0 -r a8db5b0e499f graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/WriteVectorNode.java --- /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 lookup(Class 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 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()); + } +} diff -r dcf2b46665a0 -r a8db5b0e499f graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/DeadCodeEliminationPhase.java --- 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); + } + } } } diff -r dcf2b46665a0 -r a8db5b0e499f graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/InliningPhase.java --- 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) { diff -r dcf2b46665a0 -r a8db5b0e499f graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRAssembler.java --- 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 diff -r dcf2b46665a0 -r a8db5b0e499f graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotRuntime.java --- 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)) {