# HG changeset patch # User Gilles Duboscq # Date 1312562672 -7200 # Node ID e04e88087e98b583076d34e7a0dc413fb600db21 # Parent 2ae2861243b170886703ded66f96db5149647bde# Parent 66e8bde93b6d20c6efcd61ba8c05f01a5e0b41c6 Merga diff -r 66e8bde93b6d -r e04e88087e98 .hgignore --- a/.hgignore Fri Aug 05 15:14:03 2011 +0200 +++ b/.hgignore Fri Aug 05 18:44:32 2011 +0200 @@ -36,3 +36,4 @@ ^src/share/tools/IdealGraphVisualizer/dist/ ^.hgtip ^make/solaris/solaris_amd64_compiler1/ +^RemoteSystemsTempFiles/ diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/GraalCompilation.java diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/LinearScan.java Fri Aug 05 18:44:32 2011 +0200 @@ -44,7 +44,6 @@ import com.oracle.max.graal.compiler.value.FrameState.ValueProcedure; import com.oracle.max.graal.extensions.*; import com.oracle.max.graal.graph.*; -import com.oracle.max.graal.graph.collections.*; import com.sun.cri.ci.*; import com.sun.cri.ri.*; diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/OperandPool.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/OperandPool.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/alloc/OperandPool.java Fri Aug 05 18:44:32 2011 +0200 @@ -27,7 +27,6 @@ import com.oracle.max.graal.compiler.*; import com.oracle.max.graal.compiler.ir.*; import com.oracle.max.graal.graph.*; -import com.oracle.max.graal.graph.collections.*; import com.sun.cri.ci.*; /** diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/CFGPrinter.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/CFGPrinter.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/CFGPrinter.java Fri Aug 05 18:44:32 2011 +0200 @@ -27,18 +27,17 @@ import com.oracle.max.graal.compiler.*; import com.oracle.max.graal.compiler.alloc.*; -import com.oracle.max.graal.compiler.alloc.Interval.*; +import com.oracle.max.graal.compiler.alloc.Interval.UsePosList; import com.oracle.max.graal.compiler.graph.*; import com.oracle.max.graal.compiler.ir.*; import com.oracle.max.graal.compiler.lir.*; -import com.oracle.max.graal.compiler.lir.LIRInstruction.*; +import com.oracle.max.graal.compiler.lir.LIRInstruction.OperandFormatter; import com.oracle.max.graal.compiler.schedule.*; import com.oracle.max.graal.compiler.util.*; import com.oracle.max.graal.compiler.value.*; import com.oracle.max.graal.graph.*; -import com.oracle.max.graal.graph.collections.*; import com.sun.cri.ci.*; -import com.sun.cri.ci.CiAddress.*; +import com.sun.cri.ci.CiAddress.Scale; import com.sun.cri.ri.*; /** diff -r 66e8bde93b6d -r e04e88087e98 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 Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java Fri Aug 05 18:44:32 2011 +0200 @@ -581,23 +581,11 @@ LIRItem xin = xitem; LIRItem yin = yitem; - if (kind.isLong()) { - // for longs, only conditions "eql", "neq", "lss", "geq" are valid; - // mirror for other conditions - if (cond == Condition.GT || cond == Condition.LE) { - cond = cond.mirror(); - xin = yitem; - yin = xitem; - } - xin.setDestroysRegister(); + if (kind.isFloat() || kind.isDouble()) { + cond = floatingPointCondition(cond); } + xin.loadItem(); - if (kind.isLong() && yin.result().isConstant() && yin.instruction.asConstant().asLong() == 0 && (cond == Condition.EQ || cond == Condition.NE)) { - // dont load item - } else if (kind.isLong() || kind.isFloat() || kind.isDouble()) { - // longs cannot handle constants at right side - yin.loadItem(); - } CiValue left = xin.result(); CiValue right = yin.result(); @@ -618,32 +606,6 @@ } } - @Override - public void visitIfOp(Conditional i) { - Value x = i.x(); - Value y = i.y(); - CiKind xtype = x.kind; - CiKind ttype = i.trueValue().kind; - assert xtype.isInt() || xtype.isObject() : "cannot handle others"; - assert ttype.isInt() || ttype.isObject() || ttype.isLong() || ttype.isWord() : "cannot handle others"; - assert ttype.equals(i.falseValue().kind) : "cannot handle others"; - - CiValue left = load(x); - CiValue right = null; - if (!canInlineAsConstant(y)) { - right = load(y); - } else { - right = makeOperand(y); - } - - CiValue tVal = makeOperand(i.trueValue()); - CiValue fVal = makeOperand(i.falseValue()); - CiValue reg = createResultVariable(i); - - lir.cmp(i.condition(), left, right); - lir.cmove(i.condition(), tVal, fVal, reg); - } - protected FrameState stateBeforeInvokeReturn(Invoke invoke) { return invoke.stateAfter().duplicateModified(invoke.bci, invoke.stateAfter().rethrowException(), invoke.kind); } @@ -1787,7 +1749,7 @@ } } - protected abstract boolean canInlineAsConstant(Value i); + public abstract boolean canInlineAsConstant(Value i); protected abstract boolean canStoreAsConstant(Value i, CiKind kind); @@ -1884,4 +1846,6 @@ ((Value) n).accept(generator); } }; + + public abstract Condition floatingPointCondition(Condition cond); } diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java Fri Aug 05 18:44:32 2011 +0200 @@ -136,6 +136,8 @@ graph.stopRecordModifications(); } + new ConvertConditionalPhase().apply(graph); + new LoweringPhase(compilation.runtime).apply(graph); if (GraalOptions.Lower) { new MemoryPhase().apply(graph); diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/And.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/And.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/And.java Fri Aug 05 18:44:32 2011 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.max.graal.compiler.ir; +import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.NotifyReProcess; import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.*; import com.oracle.max.graal.graph.*; import com.sun.cri.bytecode.*; @@ -62,7 +63,7 @@ private static class AndCanonicalizerOp implements CanonicalizerOp { @Override - public Node canonical(Node node) { + public Node canonical(Node node, NotifyReProcess reProcess) { assert node instanceof And; And and = (And) node; CiKind kind = and.kind; diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ArrayLength.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ArrayLength.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ArrayLength.java Fri Aug 05 18:44:32 2011 +0200 @@ -24,6 +24,7 @@ import com.oracle.max.graal.compiler.debug.*; import com.oracle.max.graal.compiler.graph.*; +import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.NotifyReProcess; import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.*; import com.oracle.max.graal.compiler.util.*; import com.oracle.max.graal.graph.*; @@ -95,7 +96,7 @@ private static class ArrayLengthCanonicalizerOp implements CanonicalizerOp { @Override - public Node canonical(Node node) { + public Node canonical(Node node, NotifyReProcess reProcess) { ArrayLength arrayLength = (ArrayLength) node; Value array = arrayLength.array(); if (array instanceof NewArray) { diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/CheckCast.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/CheckCast.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/CheckCast.java Fri Aug 05 18:44:32 2011 +0200 @@ -24,6 +24,7 @@ import com.oracle.max.graal.compiler.debug.*; import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.CanonicalizerOp; +import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.NotifyReProcess; import com.oracle.max.graal.graph.*; import com.sun.cri.bytecode.*; import com.sun.cri.ci.*; @@ -94,7 +95,7 @@ private static CanonicalizerOp CANONICALIZER = new CanonicalizerOp() { @Override - public Node canonical(Node node) { + public Node canonical(Node node, NotifyReProcess reProcess) { CheckCast checkCast = (CheckCast) node; Value object = checkCast.object(); RiType exactType = object.exactType(); diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Compare.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Compare.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Compare.java Fri Aug 05 18:44:32 2011 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.max.graal.compiler.ir; +import java.util.*; + import com.oracle.max.graal.compiler.*; import com.oracle.max.graal.compiler.debug.*; import com.oracle.max.graal.compiler.graph.*; @@ -63,8 +65,8 @@ this.y = x; } - Condition condition; - boolean unorderedIsTrue; + private Condition condition; + private boolean unorderedIsTrue; /** * Constructs a new Compare instruction. @@ -117,6 +119,11 @@ setY(t); } + public void negate() { + condition = condition.negate(); + unorderedIsTrue = !unorderedIsTrue; + } + @Override public void accept(ValueVisitor v) { } @@ -146,6 +153,13 @@ } @Override + public Map getDebugProperties() { + Map properties = super.getDebugProperties(); + properties.put("unorderedIsTrue", unorderedIsTrue()); + return properties; + } + + @Override public Node copy(Graph into) { Compare x = new Compare(null, condition, null, into); x.unorderedIsTrue = unorderedIsTrue; @@ -154,17 +168,14 @@ private static CanonicalizerOp CANONICALIZER = new CanonicalizerOp() { @Override - public Node canonical(Node node) { + public Node canonical(Node node, NotifyReProcess reProcess) { Compare compare = (Compare) node; if (compare.x().isConstant() && !compare.y().isConstant()) { // move constants to the left (y) - Value x = compare.x(); - compare.setX(compare.y()); - compare.setY(x); - compare.condition = compare.condition.mirror(); + compare.swapOperands(); } else if (compare.x().isConstant() && compare.y().isConstant()) { CiConstant constX = compare.x().asConstant(); CiConstant constY = compare.y().asConstant(); - Boolean result = compare.condition().foldCondition(constX, constY, ((CompilerGraph) node.graph()).runtime()); + Boolean result = compare.condition().foldCondition(constX, constY, ((CompilerGraph) node.graph()).runtime(), compare.unorderedIsTrue()); if (result != null) { if (GraalOptions.TraceCanonicalizer) { TTY.println("folded condition " + constX + " " + compare.condition() + " " + constY); @@ -205,6 +216,19 @@ } } } + boolean allUsagesNegate = true; + for (Node usage : compare.usages()) { + if (!(usage instanceof NegateBooleanNode)) { + allUsagesNegate = false; + break; + } + } + if (allUsagesNegate) { + compare.negate(); + for (Node usage : compare.usages().snapshot()) { + usage.replaceAtUsages(compare); + } + } return compare; } @@ -215,7 +239,7 @@ if (compare.condition == Condition.NE) { isFalseCheck = !isFalseCheck; } - BooleanNode result = materializeNode.value(); + BooleanNode result = materializeNode.condition(); if (isFalseCheck) { result = new NegateBooleanNode(result, compare.graph()); } diff -r 66e8bde93b6d -r e04e88087e98 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 Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Condition.java Fri Aug 05 18:44:32 2011 +0200 @@ -129,6 +129,8 @@ case BE: return AT; case AT: return BE; case AE: return BT; + case OF: return NOF; + case NOF: return OF; } throw new IllegalArgumentException(this.toString()); } @@ -169,7 +171,7 @@ * @return {@link Boolean#TRUE} if the comparison is known to be true, * {@link Boolean#FALSE} if the comparison is known to be false, {@code null} otherwise. */ - public Boolean foldCondition(CiConstant lt, CiConstant rt, RiRuntime runtime) { + public Boolean foldCondition(CiConstant lt, CiConstant rt, RiRuntime runtime, boolean unorderedIsTrue) { switch (lt.kind) { case Boolean: case Int: { @@ -209,7 +211,44 @@ } break; } - // XXX: folding of floating comparisons should be possible + case Float: { + float x = lt.asFloat(); + float y = rt.asFloat(); + if (Float.isNaN(x) || Float.isNaN(y)) { + return unorderedIsTrue; + } + switch (this) { + case EQ: return x == y; + case NE: return x != y; + case BT: + case LT: return x < y; + case BE: + case LE: return x <= y; + case AT: + case GT: return x > y; + case AE: + case GE: return x >= y; + } + } + case Double: { + double x = lt.asDouble(); + double y = rt.asDouble(); + if (Double.isNaN(x) || Double.isNaN(y)) { + return unorderedIsTrue; + } + switch (this) { + case EQ: return x == y; + case NE: return x != y; + case BT: + case LT: return x < y; + case BE: + case LE: return x <= y; + case AT: + case GT: return x > y; + case AE: + case GE: return x >= y; + } + } } return null; } diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Conditional.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Conditional.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Conditional.java Fri Aug 05 18:44:32 2011 +0200 @@ -22,45 +22,45 @@ */ package com.oracle.max.graal.compiler.ir; +import com.oracle.max.graal.compiler.*; import com.oracle.max.graal.compiler.debug.*; +import com.oracle.max.graal.compiler.gen.*; +import com.oracle.max.graal.compiler.gen.LIRGenerator.LIRGeneratorOp; +import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.CanonicalizerOp; +import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.NotifyReProcess; import com.oracle.max.graal.compiler.util.*; +import com.oracle.max.graal.compiler.value.*; import com.oracle.max.graal.graph.*; import com.sun.cri.bytecode.*; import com.sun.cri.ci.*; /** - * The {@code IfOp} class represents a comparison that yields one of two values. + * The {@code Conditional} class represents a comparison that yields one of two values. * Note that these nodes are not built directly from the bytecode but are introduced * by conditional expression elimination. */ -public final class Conditional extends Binary { - - @NodeInput - private Value trueValue; +public class Conditional extends Binary { + @NodeInput private BooleanNode condition; + @NodeInput private FrameState stateDuring; - @NodeInput - private Value falseValue; - - public Value trueValue() { - return trueValue; + public BooleanNode condition() { + return condition; } - public void setTrueValue(Value x) { - updateUsages(trueValue, x); - trueValue = x; + public void setCondition(BooleanNode n) { + updateUsages(condition, n); + condition = n; } - public Value falseValue() { - return falseValue; + public FrameState stateDuring() { + return stateDuring; } - public void setFalseValue(Value x) { - updateUsages(falseValue, x); - falseValue = x; + public void setStateDuring(FrameState n) { + updateUsages(stateDuring, n); + stateDuring = n; } - Condition condition; - /** * Constructs a new IfOp. * @param x the instruction producing the first value to be compared @@ -69,51 +69,37 @@ * @param trueValue the value produced if the condition is true * @param falseValue the value produced if the condition is false */ - public Conditional(Value x, Condition condition, Value y, Value trueValue, Value falseValue, Graph graph) { + public Conditional(BooleanNode condition, Value trueValue, Value falseValue, Graph graph) { // TODO: return the appropriate bytecode IF_ICMPEQ, etc - super(trueValue.kind.meet(falseValue.kind), Bytecodes.ILLEGAL, x, y, graph); - this.condition = condition; - setTrueValue(trueValue); - setFalseValue(falseValue); + super(trueValue.kind.meet(falseValue.kind), Bytecodes.ILLEGAL, trueValue, falseValue, graph); + setCondition(condition); } // for copying - private Conditional(CiKind kind, Condition cond, Graph graph) { + private Conditional(CiKind kind, Graph graph) { super(kind, Bytecodes.ILLEGAL, null, null, graph); - this.condition = cond; } - /** - * Gets the condition of this if operation. - * @return the condition - */ - public Condition condition() { - return condition; + public Value trueValue() { + return x(); } - /** - * Checks whether this comparison operator is commutative (i.e. it is either == or !=). - * @return {@code true} if this comparison is commutative - */ - public boolean isCommutative() { - return condition == Condition.EQ || condition == Condition.NE; + public Value falseValue() { + return y(); } - @Override - public void accept(ValueVisitor v) { - v.visitIfOp(this); + public void setTrueValue(Value value) { + setX(value); } - @Override - public int valueNumber() { - return Util.hash4(condition.hashCode(), x(), y(), trueValue(), falseValue()); + public void setFalseValue(Value value) { + setY(value); } @Override public boolean valueEqual(Node i) { if (i instanceof Conditional) { - Conditional o = (Conditional) i; - return opcode == o.opcode && x() == o.x() && y() == o.y() && trueValue() == o.trueValue() && falseValue() == o.falseValue(); + return super.valueEqual(i); } return false; } @@ -122,7 +108,7 @@ public void print(LogStream out) { out.print(x()). print(' '). - print(condition().operator). + print(condition()). print(' '). print(y()). print(" ? "). @@ -133,7 +119,129 @@ @Override public Node copy(Graph into) { - Conditional x = new Conditional(kind, condition, into); + Conditional x = new Conditional(kind, into); return x; } + + @SuppressWarnings("unchecked") + @Override + public T lookup(Class clazz) { + if (clazz == CanonicalizerOp.class) { + return (T) CANONICALIZER; + } + if (clazz == LIRGeneratorOp.class) { + return (T) LIRGEN; + } + return super.lookup(clazz); + } + + private static final CanonicalizerOp CANONICALIZER = new CanonicalizerOp() { + @Override + public Node canonical(Node node, NotifyReProcess reProcess) { + Conditional conditional = (Conditional) node; + BooleanNode condition = conditional.condition(); + Value trueValue = conditional.trueValue(); + Value falseValue = conditional.falseValue(); + if (condition instanceof Constant) { + Constant c = (Constant) condition; + if (c.asConstant().asBoolean()) { + return trueValue; + } else { + return falseValue; + } + } + if (trueValue == falseValue) { + return trueValue; + } + if (!(conditional instanceof MaterializeNode) && trueValue instanceof Constant && falseValue instanceof Constant + && trueValue.kind == CiKind.Int && falseValue.kind == CiKind.Int) { + int trueInt = trueValue.asConstant().asInt(); + int falseInt = falseValue.asConstant().asInt(); + if (trueInt == 0 && falseInt == 1) { + if (GraalOptions.TraceCanonicalizer) { + TTY.println("> Conditional canon'ed to ~Materialize"); + } + reProcess.reProccess(condition); // because we negate it + MaterializeNode materializeNode = new MaterializeNode(new NegateBooleanNode(condition, node.graph()), node.graph()); + materializeNode.setStateDuring(conditional.stateDuring()); + return materializeNode; + } else if (trueInt == 1 && falseInt == 0) { + if (GraalOptions.TraceCanonicalizer) { + TTY.println("> Conditional canon'ed to Materialize"); + } + MaterializeNode materializeNode = new MaterializeNode(condition, node.graph()); + materializeNode.setStateDuring(conditional.stateDuring()); + return materializeNode; + } + } else if (falseValue instanceof Constant && !(trueValue instanceof Constant)) { + conditional.setTrueValue(falseValue); + conditional.setFalseValue(trueValue); + condition = new NegateBooleanNode(condition, node.graph()); + conditional.setCondition(condition); + } + return conditional; + } + }; + + private static final LIRGeneratorOp LIRGEN = new LIRGeneratorOp() { + + @Override + public void generate(Node n, LIRGenerator generator) { + Conditional conditional = (Conditional) n; + BooleanNode condition = conditional.condition(); + + CiVariable result = generator.createResultVariable(conditional); + // try to use cmp + cmov first + Condition cond = null; + CiValue left = null; + CiValue right = null; + boolean floating = false; + boolean unOrderedIsSecond = false; + boolean negate = false; + while (condition instanceof NegateBooleanNode) { + negate = !negate; + condition = ((NegateBooleanNode) condition).value(); + } + if (condition instanceof Compare) { + Compare compare = (Compare) condition; + Value x = compare.x(); + Value y = compare.y(); + cond = compare.condition(); + if (x.kind.isFloatOrDouble()) { + floating = true; + unOrderedIsSecond = !compare.unorderedIsTrue(); + cond = generator.floatingPointCondition(cond); + } + left = generator.load(x); + if (!generator.canInlineAsConstant(y)) { + right = generator.load(y); + } else { + right = generator.makeOperand(y); + } + } else if (condition instanceof IsNonNull) { + IsNonNull isNonNull = (IsNonNull) condition; + left = generator.load(isNonNull.object()); + right = CiConstant.NULL_OBJECT; + cond = Condition.NE; + } else if (condition instanceof Constant) { + generator.lir().move(result, condition.asConstant()); + } else { + throw Util.shouldNotReachHere("Currently not implemented because we can not create blocks during LIRGen : " + condition); + } + CiValue tVal = generator.makeOperand(conditional.trueValue()); + CiValue fVal = generator.makeOperand(conditional.falseValue()); + if (cond != null) { + if (negate) { + cond = cond.negate(); + } + assert left != null && right != null; + generator.lir().cmp(cond, left, right); + if (floating) { + generator.lir().fcmove(cond, tVal, fVal, result, unOrderedIsSecond); + } else { + generator.lir().cmove(cond, tVal, fVal, result); + } + } + } + }; } diff -r 66e8bde93b6d -r e04e88087e98 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 Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FixedGuard.java Fri Aug 05 18:44:32 2011 +0200 @@ -26,6 +26,7 @@ import com.oracle.max.graal.compiler.debug.*; import com.oracle.max.graal.compiler.ir.Deoptimize.DeoptAction; import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.CanonicalizerOp; +import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.NotifyReProcess; import com.oracle.max.graal.graph.*; import com.sun.cri.ci.*; @@ -76,7 +77,7 @@ private static CanonicalizerOp CANONICALIZER = new CanonicalizerOp() { @Override - public Node canonical(Node node) { + public Node canonical(Node node, NotifyReProcess reProcess) { FixedGuard fixedGuard = (FixedGuard) node; for (BooleanNode n : fixedGuard.conditions.snapshot()) { if (n instanceof Constant) { diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FloatAdd.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FloatAdd.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FloatAdd.java Fri Aug 05 18:44:32 2011 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.max.graal.compiler.ir; +import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.NotifyReProcess; import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.*; import com.oracle.max.graal.graph.*; import com.sun.cri.bytecode.*; @@ -57,7 +58,7 @@ private static class FloatAddCanonicalizerOp implements CanonicalizerOp { @Override - public Node canonical(Node node) { + public Node canonical(Node node, NotifyReProcess reProcess) { FloatAdd add = (FloatAdd) node; Value x = add.x(); Value y = add.y(); diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FloatDiv.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FloatDiv.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FloatDiv.java Fri Aug 05 18:44:32 2011 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.max.graal.compiler.ir; +import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.NotifyReProcess; import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.*; import com.oracle.max.graal.graph.*; import com.sun.cri.bytecode.*; @@ -56,7 +57,7 @@ private static class FloatDivCanonicalizerOp implements CanonicalizerOp { @Override - public Node canonical(Node node) { + public Node canonical(Node node, NotifyReProcess reProcess) { FloatDiv div = (FloatDiv) node; Value x = div.x(); Value y = div.y(); diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FloatMul.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FloatMul.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FloatMul.java Fri Aug 05 18:44:32 2011 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.max.graal.compiler.ir; +import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.NotifyReProcess; import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.*; import com.oracle.max.graal.graph.*; import com.sun.cri.bytecode.*; @@ -67,7 +68,7 @@ private static class FloatMulCanonicalizerOp implements CanonicalizerOp { @Override - public Node canonical(Node node) { + public Node canonical(Node node, NotifyReProcess reProcess) { FloatMul mul = (FloatMul) node; Value x = mul.x(); Value y = mul.y(); diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FloatRem.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FloatRem.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FloatRem.java Fri Aug 05 18:44:32 2011 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.max.graal.compiler.ir; +import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.NotifyReProcess; import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.*; import com.oracle.max.graal.graph.*; import com.sun.cri.bytecode.*; @@ -56,7 +57,7 @@ private static class FloatRemCanonicalizerOp implements CanonicalizerOp { @Override - public Node canonical(Node node) { + public Node canonical(Node node, NotifyReProcess reProcess) { FloatRem rem = (FloatRem) node; Value x = rem.x(); Value y = rem.y(); diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FloatSub.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FloatSub.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FloatSub.java Fri Aug 05 18:44:32 2011 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.max.graal.compiler.ir; +import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.NotifyReProcess; import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.*; import com.oracle.max.graal.graph.*; import com.sun.cri.bytecode.*; @@ -56,7 +57,7 @@ private static class FloatSubCanonicalizerOp implements CanonicalizerOp { @Override - public Node canonical(Node node) { + public Node canonical(Node node, NotifyReProcess reProcess) { FloatSub sub = (FloatSub) node; Value x = sub.x(); Value y = sub.y(); diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/GuardNode.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/GuardNode.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/GuardNode.java Fri Aug 05 18:44:32 2011 +0200 @@ -24,6 +24,7 @@ import com.oracle.max.graal.compiler.*; import com.oracle.max.graal.compiler.debug.*; +import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.NotifyReProcess; import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.*; import com.oracle.max.graal.graph.*; import com.sun.cri.ci.*; @@ -46,6 +47,9 @@ anchor = x; } + /** + * The instruction that produces the tested boolean value. + */ public BooleanNode node() { return node; } @@ -91,7 +95,7 @@ private static CanonicalizerOp CANONICALIZER = new CanonicalizerOp() { @Override - public Node canonical(Node node) { + public Node canonical(Node node, NotifyReProcess reProcess) { GuardNode guard = (GuardNode) node; if (guard.node() instanceof Constant) { Constant c = (Constant) guard.node(); diff -r 66e8bde93b6d -r e04e88087e98 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 Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/If.java Fri Aug 05 18:44:32 2011 +0200 @@ -25,6 +25,7 @@ import com.oracle.max.graal.compiler.*; import com.oracle.max.graal.compiler.debug.*; import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.CanonicalizerOp; +import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.NotifyReProcess; import com.oracle.max.graal.graph.*; import com.sun.cri.ci.*; @@ -132,7 +133,7 @@ private static CanonicalizerOp CANONICALIZER = new CanonicalizerOp() { @Override - public Node canonical(Node node) { + public Node canonical(Node node, NotifyReProcess reProcess) { If ifNode = (If) node; if (ifNode.compare() instanceof Constant) { Constant c = (Constant) ifNode.compare(); @@ -148,6 +149,28 @@ return ifNode.falseSuccessor(); } } + if (ifNode.trueSuccessor() instanceof EndNode && ifNode.falseSuccessor() instanceof EndNode) { + EndNode trueEnd = (EndNode) ifNode.trueSuccessor(); + EndNode falseEnd = (EndNode) ifNode.falseSuccessor(); + Merge merge = trueEnd.merge(); + if (merge == falseEnd.merge() && merge.phis().size() == 0) { + FixedNode next = merge.next(); + merge.setNext(null); //disconnect to avoid next from having 2 preds + if (ifNode.compare().usages().size() == 1 && /*ifNode.compare().hasSideEffets()*/ true) { // TODO (gd) ifNode.compare().hasSideEffets() ? + if (GraalOptions.TraceCanonicalizer) { + TTY.println("> Useless if with side effects Canon'ed to guard"); + } + ValueAnchor anchor = new ValueAnchor(ifNode.compare(), node.graph()); + anchor.setNext(next); + return anchor; + } else { + if (GraalOptions.TraceCanonicalizer) { + TTY.println("> Useless if Canon'ed away"); + } + return next; + } + } + } return ifNode; } }; diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/InstanceOf.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/InstanceOf.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/InstanceOf.java Fri Aug 05 18:44:32 2011 +0200 @@ -24,6 +24,7 @@ import com.oracle.max.graal.compiler.debug.*; import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.CanonicalizerOp; +import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.NotifyReProcess; import com.oracle.max.graal.compiler.util.*; import com.oracle.max.graal.graph.*; import com.sun.cri.bytecode.*; @@ -82,7 +83,7 @@ private static CanonicalizerOp CANONICALIZER = new CanonicalizerOp() { @Override - public Node canonical(Node node) { + public Node canonical(Node node, NotifyReProcess reProcess) { InstanceOf isInstance = (InstanceOf) node; Value object = isInstance.object(); RiType exactType = object.exactType(); diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerAdd.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerAdd.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerAdd.java Fri Aug 05 18:44:32 2011 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.max.graal.compiler.ir; +import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.NotifyReProcess; import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.*; import com.oracle.max.graal.graph.*; import com.sun.cri.bytecode.*; @@ -56,7 +57,7 @@ private static class IntegerAddCanonicalizerOp implements CanonicalizerOp { @Override - public Node canonical(Node node) { + public Node canonical(Node node, NotifyReProcess reProcess) { IntegerAdd add = (IntegerAdd) node; Value x = add.x(); Value y = add.y(); diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerDiv.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerDiv.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerDiv.java Fri Aug 05 18:44:32 2011 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.max.graal.compiler.ir; +import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.NotifyReProcess; import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.*; import com.oracle.max.graal.graph.*; import com.sun.cri.bytecode.*; @@ -56,7 +57,7 @@ private static class IntegerDivCanonicalizerOp implements CanonicalizerOp { @Override - public Node canonical(Node node) { + public Node canonical(Node node, NotifyReProcess reProcess) { IntegerDiv div = (IntegerDiv) node; Value x = div.x(); Value y = div.y(); diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerMul.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerMul.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerMul.java Fri Aug 05 18:44:32 2011 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.max.graal.compiler.ir; +import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.NotifyReProcess; import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.*; import com.oracle.max.graal.graph.*; import com.sun.cri.bytecode.*; @@ -56,7 +57,7 @@ private static class IntegerMulCanonicalizerOp implements CanonicalizerOp { @Override - public Node canonical(Node node) { + public Node canonical(Node node, NotifyReProcess reProcess) { IntegerMul mul = (IntegerMul) node; Value x = mul.x(); Value y = mul.y(); diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerRem.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerRem.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerRem.java Fri Aug 05 18:44:32 2011 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.max.graal.compiler.ir; +import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.NotifyReProcess; import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.*; import com.oracle.max.graal.graph.*; import com.sun.cri.bytecode.*; @@ -56,7 +57,7 @@ private static class IntegerRemCanonicalizerOp implements CanonicalizerOp { @Override - public Node canonical(Node node) { + public Node canonical(Node node, NotifyReProcess reProcess) { IntegerRem rem = (IntegerRem) node; Value x = rem.x(); Value y = rem.y(); diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerSub.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerSub.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerSub.java Fri Aug 05 18:44:32 2011 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.max.graal.compiler.ir; +import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.NotifyReProcess; import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.*; import com.oracle.max.graal.graph.*; import com.sun.cri.bytecode.*; @@ -56,7 +57,7 @@ private static class IntegerSubCanonicalizerOp implements CanonicalizerOp { @Override - public Node canonical(Node node) { + public Node canonical(Node node, NotifyReProcess reProcess) { IntegerSub sub = (IntegerSub) node; Value x = sub.x(); Value y = sub.y(); diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IsNonNull.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IsNonNull.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IsNonNull.java Fri Aug 05 18:44:32 2011 +0200 @@ -24,6 +24,7 @@ import com.oracle.max.graal.compiler.debug.*; import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.CanonicalizerOp; +import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.NotifyReProcess; import com.oracle.max.graal.compiler.util.*; import com.oracle.max.graal.graph.*; import com.sun.cri.bytecode.*; @@ -106,7 +107,7 @@ private static CanonicalizerOp CANONICALIZER = new CanonicalizerOp() { @Override - public Node canonical(Node node) { + public Node canonical(Node node, NotifyReProcess reProcess) { IsNonNull isNonNull = (IsNonNull) node; Value object = isNonNull.object(); if (object instanceof NewInstance || object instanceof NewArray) { diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IsType.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IsType.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IsType.java Fri Aug 05 18:44:32 2011 +0200 @@ -26,6 +26,7 @@ import com.oracle.max.graal.compiler.debug.*; import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.CanonicalizerOp; +import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.NotifyReProcess; import com.oracle.max.graal.compiler.util.*; import com.oracle.max.graal.graph.*; import com.sun.cri.bytecode.*; @@ -126,7 +127,7 @@ private static CanonicalizerOp CANONICALIZER = new CanonicalizerOp() { @Override - public Node canonical(Node node) { + public Node canonical(Node node, NotifyReProcess reProcess) { IsType isType = (IsType) node; Value object = isType.object(); RiType exactType = object.exactType(); diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LeftShift.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LeftShift.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LeftShift.java Fri Aug 05 18:44:32 2011 +0200 @@ -23,6 +23,7 @@ package com.oracle.max.graal.compiler.ir; import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.CanonicalizerOp; +import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.NotifyReProcess; import com.oracle.max.graal.graph.*; import com.sun.cri.bytecode.*; import com.sun.cri.ci.*; @@ -57,7 +58,7 @@ private static class LeftShiftCanonicalizerOp implements CanonicalizerOp { @Override - public Node canonical(Node node) { + public Node canonical(Node node, NotifyReProcess reProcess) { LeftShift leftShift = (LeftShift) node; CiKind kind = leftShift.kind; Graph graph = leftShift.graph(); diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoadField.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoadField.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoadField.java Fri Aug 05 18:44:32 2011 +0200 @@ -25,6 +25,7 @@ import com.oracle.max.graal.compiler.debug.*; import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.CanonicalizerOp; import com.oracle.max.graal.compiler.phases.*; +import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.NotifyReProcess; import com.oracle.max.graal.compiler.phases.LoweringPhase.LoweringOp; import com.oracle.max.graal.graph.*; import com.sun.cri.ci.*; @@ -124,7 +125,7 @@ private static class LoadFieldCanonicalizerOp implements CanonicalizerOp { @Override - public Node canonical(Node node) { + public Node canonical(Node node, NotifyReProcess reProcess) { LoadField loadField = (LoadField) node; Graph graph = node.graph(); CiConstant constant = null; diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/MaterializeNode.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/MaterializeNode.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/MaterializeNode.java Fri Aug 05 18:44:32 2011 +0200 @@ -22,34 +22,14 @@ */ package com.oracle.max.graal.compiler.ir; -import com.oracle.max.asm.*; import com.oracle.max.graal.compiler.debug.*; -import com.oracle.max.graal.compiler.gen.*; -import com.oracle.max.graal.compiler.lir.*; import com.oracle.max.graal.graph.*; -import com.sun.cri.ci.*; - -public final class MaterializeNode extends FloatingNode { - @NodeInput - private BooleanNode value; +public final class MaterializeNode extends Conditional { - public BooleanNode value() { - return value; - } - - public void setValue(BooleanNode x) { - updateUsages(value, x); - value = x; - } public MaterializeNode(BooleanNode value, Graph graph) { - super(CiKind.Int, graph); - setValue(value); - } - - @Override - public void accept(ValueVisitor v) { + super(value, Constant.forInt(1, graph), Constant.forInt(0, graph), graph); } @Override @@ -57,35 +37,9 @@ return (i instanceof MaterializeNode); } - @SuppressWarnings("unchecked") - @Override - public T lookup(Class clazz) { - if (clazz == LIRGenerator.LIRGeneratorOp.class) { - return (T) LIR_GENERATOR_OP; - } - return super.lookup(clazz); - } - - public static final LIRGenerator.LIRGeneratorOp LIR_GENERATOR_OP = new LIRGenerator.LIRGeneratorOp() { - - @Override - public void generate(Node n, LIRGenerator generator) { - LIRBlock trueSuccessor = new LIRBlock(new Label(), null); - generator.emitBooleanBranch(((MaterializeNode) n).value(), trueSuccessor, null, null); - CiValue result = generator.createResultVariable((Value) n); - LIRList lir = generator.lir(); - lir.move(CiConstant.FALSE, result); - Label label = new Label(); - lir.branch(Condition.TRUE, label); - lir.branchDestination(trueSuccessor.label); - lir.move(CiConstant.TRUE, result); - lir.branchDestination(label); - } - }; - @Override public void print(LogStream out) { - out.print("materialize(").print(value().toString()).print(')'); + out.print("materialize(").print(condition().toString()).print(')'); } @Override diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Negate.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Negate.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Negate.java Fri Aug 05 18:44:32 2011 +0200 @@ -23,6 +23,7 @@ package com.oracle.max.graal.compiler.ir; import com.oracle.max.graal.compiler.debug.*; +import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.NotifyReProcess; import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.*; import com.oracle.max.graal.compiler.util.*; import com.oracle.max.graal.graph.*; @@ -102,7 +103,7 @@ private static class NegateCanonicalizerOp implements CanonicalizerOp { @Override - public Node canonical(Node node) { + public Node canonical(Node node, NotifyReProcess reProcess) { Negate negate = (Negate) node; Value x = negate.x(); Graph graph = negate.graph(); diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NegateBooleanNode.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NegateBooleanNode.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NegateBooleanNode.java Fri Aug 05 18:44:32 2011 +0200 @@ -24,6 +24,7 @@ import com.oracle.max.graal.compiler.debug.*; import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.CanonicalizerOp; +import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.NotifyReProcess; import com.oracle.max.graal.graph.*; import com.sun.cri.ci.*; @@ -76,7 +77,7 @@ private static final CanonicalizerOp CANONICALIZER = new CanonicalizerOp() { @Override - public Node canonical(Node node) { + public Node canonical(Node node, NotifyReProcess reProcess) { NegateBooleanNode negateNode = (NegateBooleanNode) node; Value value = negateNode.value(); if (value instanceof NegateBooleanNode) { diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NormalizeCompare.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NormalizeCompare.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/NormalizeCompare.java Fri Aug 05 18:44:32 2011 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.max.graal.compiler.ir; +import java.util.*; + import com.oracle.max.graal.compiler.debug.*; import com.oracle.max.graal.graph.*; import com.sun.cri.bytecode.*; @@ -45,7 +47,7 @@ @Override public void accept(ValueVisitor v) { - v.visitMaterialize(this); + v.visitNormalizeCompare(this); } @Override @@ -62,6 +64,13 @@ return new NormalizeCompare(opcode, kind, null, null, into); } + @Override + public Map getDebugProperties() { + Map properties = super.getDebugProperties(); + properties.put("isUnorderedLess", isUnorderedLess()); + return properties; + } + public boolean isUnorderedLess() { return this.opcode == Bytecodes.FCMPL || this.opcode == Bytecodes.DCMPL; } diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Or.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Or.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Or.java Fri Aug 05 18:44:32 2011 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.max.graal.compiler.ir; +import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.NotifyReProcess; import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.*; import com.oracle.max.graal.graph.*; import com.sun.cri.bytecode.*; @@ -66,7 +67,7 @@ private static class OrCanonicalizerOp implements CanonicalizerOp { @Override - public Node canonical(Node node) { + public Node canonical(Node node, NotifyReProcess reProcess) { Or or = (Or) node; CiKind kind = or.kind; Graph graph = or.graph(); diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Phi.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Phi.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Phi.java Fri Aug 05 18:44:32 2011 +0200 @@ -24,9 +24,11 @@ import java.util.*; +import com.oracle.max.graal.compiler.*; import com.oracle.max.graal.compiler.debug.*; -import com.oracle.max.graal.compiler.ir.StateSplit.*; -import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.*; +import com.oracle.max.graal.compiler.ir.StateSplit.FilteringIterator; +import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.CanonicalizerOp; +import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.NotifyReProcess; import com.oracle.max.graal.graph.*; import com.sun.cri.ci.*; @@ -174,48 +176,45 @@ private static CanonicalizerOp CANONICALIZER = new CanonicalizerOp() { @Override - public Node canonical(Node node) { + public Node canonical(Node node, NotifyReProcess reProcess) { Phi phiNode = (Phi) node; -// if (phiNode.valueCount() != 2 || phiNode.merge().endCount() != 2 || phiNode.merge().phis().size() != 1) { -// return phiNode; -// } -// if (!(phiNode.valueAt(0) instanceof Constant && phiNode.valueAt(1) instanceof Constant)) { -// return phiNode; -// } -// Merge merge = phiNode.merge(); -// Node end0 = merge.endAt(0); -// Node end1 = merge.endAt(1); -// if (end0.predecessors().size() != 1 || end1.predecessors().size() != 1) { -// return phiNode; -// } -// Node endPred0 = end0.predecessors().get(0); -// Node endPred1 = end1.predecessors().get(0); -// if (endPred0 != endPred1 || !(endPred0 instanceof If)) { -// return phiNode; -// } -// If ifNode = (If) endPred0; -// if (ifNode.predecessors().size() != 1) { -// return phiNode; -// } -// boolean inverted = ((If) endPred0).trueSuccessor() == end1; -// CiConstant trueValue = phiNode.valueAt(inverted ? 1 : 0).asConstant(); -// CiConstant falseValue = phiNode.valueAt(inverted ? 0 : 1).asConstant(); -// if (trueValue.kind != CiKind.Int || falseValue.kind != CiKind.Int) { -// return phiNode; -// } -// if ((trueValue.asInt() == 0 || trueValue.asInt() == 1) && (falseValue.asInt() == 0 || falseValue.asInt() == 1) && (trueValue.asInt() != falseValue.asInt())) { -// MaterializeNode result; -// if (trueValue.asInt() == 1) { -// result = new MaterializeNode(ifNode.compare(), phiNode.graph()); -// } else { -// result = new MaterializeNode(new NegateBooleanNode(ifNode.compare(), phiNode.graph()), phiNode.graph()); -// } -// Node next = merge.next(); -// merge.setNext(null); -// ifNode.predecessors().get(0).successors().replace(ifNode, next); -// return result; -// } - return phiNode; + if (phiNode.valueCount() != 2 || phiNode.merge().endCount() != 2) { + return phiNode; + } + Merge merge = phiNode.merge(); + if (merge.phis().size() > 1) { // XXX (gd) disable canonicalization of multiple conditional while we are not able to fuse them and the potentially leftover If in the backend + return phiNode; + } + Node end0 = merge.endAt(0); + Node end1 = merge.endAt(1); + Node endPred0 = end0.predecessor(); + Node endPred1 = end1.predecessor(); + if (endPred0 != endPred1 || !(endPred0 instanceof If)) { + return phiNode; + } + If ifNode = (If) endPred0; + boolean inverted = ifNode.trueSuccessor() == end1; + Value trueValue = phiNode.valueAt(inverted ? 1 : 0); + Value falseValue = phiNode.valueAt(inverted ? 0 : 1); + if ((trueValue.kind != CiKind.Int && trueValue.kind != CiKind.Long) || (falseValue.kind != CiKind.Int && falseValue.kind != CiKind.Long)) { + return phiNode; + } + if ((!(trueValue instanceof Constant) && trueValue.usages().size() == 1) || (!(falseValue instanceof Constant) && falseValue.usages().size() == 1)) { + return phiNode; + } + BooleanNode compare = ifNode.compare(); + while (compare instanceof NegateBooleanNode) { + compare = ((NegateBooleanNode) compare).value(); + } + if (!(compare instanceof Compare || compare instanceof IsNonNull || compare instanceof NegateBooleanNode || compare instanceof Constant)) { + return phiNode; + } + if (GraalOptions.TraceCanonicalizer) { + TTY.println("> Phi canon'ed to Conditional"); + } + reProcess.reProccess(ifNode); + Conditional conditional = new Conditional(ifNode.compare(), trueValue, falseValue, node.graph()); + return conditional; } }; } diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/RegisterFinalizer.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/RegisterFinalizer.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/RegisterFinalizer.java Fri Aug 05 18:44:32 2011 +0200 @@ -26,6 +26,7 @@ import com.oracle.max.graal.compiler.debug.*; import com.oracle.max.graal.compiler.graph.*; import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.CanonicalizerOp; +import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.NotifyReProcess; import com.oracle.max.graal.graph.*; import com.sun.cri.ci.*; import com.sun.cri.ri.*; @@ -69,7 +70,7 @@ private static final CanonicalizerOp CANONICALIZER = new CanonicalizerOp() { @Override - public Node canonical(Node node) { + public Node canonical(Node node, NotifyReProcess reProcess) { RegisterFinalizer finalizer = (RegisterFinalizer) node; Value object = finalizer.object(); diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/RightShift.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/RightShift.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/RightShift.java Fri Aug 05 18:44:32 2011 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.max.graal.compiler.ir; +import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.NotifyReProcess; import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.*; import com.oracle.max.graal.graph.*; import com.sun.cri.bytecode.*; @@ -57,7 +58,7 @@ private static class RighShiftCanonicalizerOp implements CanonicalizerOp { @Override - public Node canonical(Node node) { + public Node canonical(Node node, NotifyReProcess reProcess) { RightShift rightShift = (RightShift) node; CiKind kind = rightShift.kind; Graph graph = rightShift.graph(); diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/UnsignedRightShift.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/UnsignedRightShift.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/UnsignedRightShift.java Fri Aug 05 18:44:32 2011 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.max.graal.compiler.ir; +import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.NotifyReProcess; import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.*; import com.oracle.max.graal.graph.*; import com.sun.cri.bytecode.*; @@ -57,7 +58,7 @@ private static class UnsignedRightShiftCanonicalizerOp implements CanonicalizerOp { @Override - public Node canonical(Node node) { + public Node canonical(Node node, NotifyReProcess reProcess) { UnsignedRightShift ushr = (UnsignedRightShift) node; CiKind kind = ushr.kind; Graph graph = ushr.graph(); diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ValueVisitor.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ValueVisitor.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/ValueVisitor.java Fri Aug 05 18:44:32 2011 +0200 @@ -35,7 +35,7 @@ public abstract void visitArrayLength(ArrayLength i); public abstract void visitMerge(Merge i); public abstract void visitCheckCast(CheckCast i); - public abstract void visitMaterialize(NormalizeCompare i); + public abstract void visitNormalizeCompare(NormalizeCompare i); public abstract void visitConstant(Constant i); public abstract void visitConvert(Convert i); public abstract void visitExceptionObject(ExceptionObject i); @@ -43,7 +43,6 @@ public abstract void visitFrameState(FrameState i); public abstract void visitAnchor(Anchor i); public abstract void visitIf(If i); - public abstract void visitIfOp(Conditional i); public abstract void visitInvoke(Invoke i); public abstract void visitLoadField(LoadField i); public abstract void visitLoadIndexed(LoadIndexed i); diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Xor.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Xor.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Xor.java Fri Aug 05 18:44:32 2011 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.max.graal.compiler.ir; +import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.NotifyReProcess; import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.*; import com.oracle.max.graal.graph.*; import com.sun.cri.bytecode.*; @@ -63,7 +64,7 @@ private static class XorCanonicalizerOp implements CanonicalizerOp { @Override - public Node canonical(Node node) { + public Node canonical(Node node, NotifyReProcess reProcess) { assert node instanceof Xor; Xor xor = (Xor) node; CiKind kind = xor.kind; diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRAssembler.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRAssembler.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRAssembler.java Fri Aug 05 18:44:32 2011 +0200 @@ -276,8 +276,14 @@ emitCompare2Int(op.code, op.operand1(), op.operand2(), op.result(), op); break; + case FCmove: + emitConditionalMove(op.condition(), op.operand1(), op.operand2(), op.result(), true, false); + break; + case UFCmove: + emitConditionalMove(op.condition(), op.operand1(), op.operand2(), op.result(), true, true); + break; case Cmove: - emitConditionalMove(op.condition(), op.operand1(), op.operand2(), op.result()); + emitConditionalMove(op.condition(), op.operand1(), op.operand2(), op.result(), false, false); break; case Shl: @@ -418,7 +424,7 @@ protected abstract void emitSignificantBitOp(boolean most, CiValue inOpr1, CiValue dst); - protected abstract void emitConditionalMove(Condition condition, CiValue inOpr1, CiValue inOpr2, CiValue dst); + protected abstract void emitConditionalMove(Condition condition, CiValue inOpr1, CiValue inOpr2, CiValue dst, boolean mayBeUnordered, boolean unorderedcmovOpr1); protected abstract void emitCompare2Int(LIROpcode code, CiValue inOpr1, CiValue inOpr2, CiValue dst, LIROp2 op); @@ -470,4 +476,15 @@ protected abstract void reg2reg(CiValue src, CiValue dest); + protected abstract boolean trueOnUnordered(Condition condition); + + protected abstract boolean falseOnUnordered(Condition condition); + + protected boolean mayBeTrueOnUnordered(Condition condition) { + return trueOnUnordered(condition) || !falseOnUnordered(condition); + } + + protected boolean mayBeFalseOnUnordered(Condition condition) { + return falseOnUnordered(condition) || !trueOnUnordered(condition); + } } diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRBlock.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRBlock.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRBlock.java Fri Aug 05 18:44:32 2011 +0200 @@ -31,7 +31,6 @@ import com.oracle.max.graal.compiler.util.*; import com.oracle.max.graal.compiler.value.*; import com.oracle.max.graal.graph.*; -import com.oracle.max.graal.graph.collections.*; /** * The {@code LIRBlock} class definition. diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRDebugInfo.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRDebugInfo.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRDebugInfo.java Fri Aug 05 18:44:32 2011 +0200 @@ -26,7 +26,6 @@ import com.oracle.max.graal.compiler.ir.*; import com.oracle.max.graal.compiler.value.*; import com.oracle.max.graal.graph.*; -import com.oracle.max.graal.graph.collections.*; import com.sun.cri.ci.*; /** diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRInstruction.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRInstruction.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRInstruction.java Fri Aug 05 18:44:32 2011 +0200 @@ -27,9 +27,9 @@ import java.util.*; import com.oracle.max.graal.compiler.*; -import com.oracle.max.graal.compiler.lir.LIROperand.*; +import com.oracle.max.graal.compiler.lir.LIROperand.LIRAddressOperand; +import com.oracle.max.graal.compiler.lir.LIROperand.LIRVariableOperand; import com.oracle.max.graal.graph.*; -import com.oracle.max.graal.graph.collections.*; import com.sun.cri.ci.*; /** diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRList.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRList.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIRList.java Fri Aug 05 18:44:32 2011 +0200 @@ -195,6 +195,10 @@ append(new LIROp2(LIROpcode.Cmove, condition, src1, src2, dst)); } + public void fcmove(Condition condition, CiValue src1, CiValue src2, CiValue dst, boolean unorderedIsSecond) { + append(new LIROp2(unorderedIsSecond ? LIROpcode.FCmove : LIROpcode.UFCmove, condition, src1, src2, dst)); + } + public void abs(CiValue from, CiValue to, CiValue tmp) { append(new LIROp2(LIROpcode.Abs, from, tmp, to)); } diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIROp2.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIROp2.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIROp2.java Fri Aug 05 18:44:32 2011 +0200 @@ -63,7 +63,7 @@ public LIROp2(LIROpcode opcode, Condition condition, CiValue opr1, CiValue opr2, CiValue result) { super(opcode, result, null, false, 0, 0, opr1, opr2); this.condition = condition; - assert opcode == LIROpcode.Cmove : "Instruction opcode should be of type LIROpcode.Cmove"; + assert opcode == LIROpcode.Cmove || opcode == LIROpcode.FCmove || opcode == LIROpcode.UFCmove : "Instruction opcode should be of type LIROpcode.Cmove"; } /** @@ -156,7 +156,7 @@ * @return condition the condition of this instruction */ public Condition condition() { - assert code == LIROpcode.Cmp || code == LIROpcode.Cmove : "Field access only valid for cmp and cmove"; + assert code == LIROpcode.Cmp || code == LIROpcode.Cmove || code == LIROpcode.FCmove || code == LIROpcode.UFCmove : "Field access only valid for cmp and cmove"; return condition; } diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIROpcode.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIROpcode.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/lir/LIROpcode.java Fri Aug 05 18:44:32 2011 +0200 @@ -59,6 +59,8 @@ Ucmpfd2i, Cmpfd2i, Cmove, + FCmove, + UFCmove, Add, Sub, Mul, diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/CanonicalizerPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/CanonicalizerPhase.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/CanonicalizerPhase.java Fri Aug 05 18:44:32 2011 +0200 @@ -41,25 +41,38 @@ @Override protected void run(Graph graph) { - NodeWorkList nodeWorkList = graph.createNodeWorkList(!newNodes, MAX_ITERATION_PER_NODE); + final NodeWorkList nodeWorkList = graph.createNodeWorkList(!newNodes, MAX_ITERATION_PER_NODE); if (newNodes) { nodeWorkList.addAll(graph.getNewNodes()); } + NotifyReProcess reProcess = new NotifyReProcess() { + @Override + public void reProccess(Node n) { + nodeWorkList.addAgain(n); + } + }; for (Node node : nodeWorkList) { CanonicalizerOp op = node.lookup(CanonicalizerOp.class); if (op != null) { - Node canonical = op.canonical(node); + graph.mark(); + Node canonical = op.canonical(node, reProcess); if (canonical != node) { node.replaceAndDelete(canonical); - nodeWorkList.replaced(canonical, node, true, EdgeType.USAGES); - //System.out.println("-->" + n + " canonicalized to " + canonical); + nodeWorkList.replaced(canonical, node, false, EdgeType.USAGES); + for (Node newNode : graph.getNewNodes()) { + nodeWorkList.add(newNode); + } GraalMetrics.NodesCanonicalized++; } } } } + public interface NotifyReProcess { + void reProccess(Node n); + } + public interface CanonicalizerOp extends Op { - Node canonical(Node node); + Node canonical(Node node, NotifyReProcess reProcess); } } diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/ConvertConditionalPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/ConvertConditionalPhase.java Fri Aug 05 18:44:32 2011 +0200 @@ -0,0 +1,138 @@ +/* + * 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.phases; + +import com.oracle.max.graal.compiler.ir.*; +import com.oracle.max.graal.compiler.ir.Phi.PhiType; +import com.oracle.max.graal.compiler.schedule.*; +import com.oracle.max.graal.compiler.value.*; +import com.oracle.max.graal.graph.*; + + +/** + * Temporary phase that converts Conditional/Materialize Nodes that can not be LIRGenered properly for now. + * Currently LIRGenerating something like + * BRANCHcc L1 // (compare, instanceof...) + * mov res, fVal + * jmp L2 + * L1: + * mov res, tVal + * L2: + * + * or + * + * mov res, tVal + * BRANCHcc L1: + * mov res, fVal + * L1: + * + * may create a few problems around register allocation: + * - in the first construct, register allocation may decide to spill an other variable to allocate res, resulting ina spilling that is done only in one branch : + * BRANCHcc L1 // (compare, instanceof...) + * mov SpillSplot, res + * mov res, fVal + * jmp L2 + * L1: + * mov res, tVal + * L2: + * + * - in the second construct the register allocator will thing that the first definition of res is not used and BRANCHcc may need some temporary register + * the allocator could then allocate the same register for res and this temporary + */ +public class ConvertConditionalPhase extends Phase { + + @Override + protected void run(Graph graph) { + IdentifyBlocksPhase schedule = null; + for (Conditional conditional : graph.getNodes(Conditional.class)) { + BooleanNode condition = conditional.condition(); + while (condition instanceof NegateBooleanNode) { + condition = ((NegateBooleanNode) condition).value(); + } + if (!(condition instanceof Compare || condition instanceof IsNonNull || condition instanceof NegateBooleanNode || condition instanceof Constant)) { + If ifNode = new If(conditional.condition(), 0.5, graph); + EndNode trueEnd = new EndNode(graph); + EndNode falseEnd = new EndNode(graph); + ifNode.setTrueSuccessor(trueEnd); + ifNode.setFalseSuccessor(falseEnd); + Merge merge = new Merge(graph); + merge.addEnd(trueEnd); + merge.addEnd(falseEnd); + Phi phi = new Phi(conditional.kind, merge, PhiType.Value, graph); + phi.addInput(conditional.trueValue()); + phi.addInput(conditional.falseValue()); + //recreate framestate + FrameState stateDuring = conditional.stateDuring(); + FrameStateBuilder builder = new FrameStateBuilder(stateDuring); + builder.push(phi.kind, phi); + merge.setStateAfter(builder.create(stateDuring.bci)); + // schedule the if... + if (schedule == null) { + schedule = new IdentifyBlocksPhase(false, false); + schedule.apply(graph); + } + schedule.assignBlockToNode(conditional); + Block block = schedule.getNodeToBlock().get(conditional); + FixedNodeWithNext prev; + Node firstNode = block.firstNode(); + if (firstNode instanceof Merge) { + prev = (Merge) firstNode; + } else if (firstNode instanceof EndNode) { + EndNode end = (EndNode) firstNode; + Node pred = end.predecessor(); + Anchor anchor = new Anchor(graph); + pred.replaceFirstSuccessor(end, anchor); + anchor.setNext(end); + prev = anchor; + } else if (firstNode instanceof StartNode) { + StartNode start = (StartNode) firstNode; + Anchor anchor = new Anchor(graph); + Node next = start.next(); + start.setNext(null); + anchor.setNext((FixedNode) next); + start.setNext(anchor); + prev = anchor; + } else if (firstNode instanceof If) { + Node pred = firstNode.predecessor(); + Anchor anchor = new Anchor(graph); + pred.replaceFirstSuccessor(firstNode, anchor); + anchor.setNext((If) firstNode); + prev = anchor; + } else { + prev = (FixedNodeWithNext) firstNode; + } + FixedNode next = prev.next(); + prev.setNext(null); + merge.setNext(next); + prev.setNext(ifNode); + conditional.replaceAndDelete(phi); + } else { + FrameState stateDuring = conditional.stateDuring(); + conditional.setStateDuring(null); + if (stateDuring != null && stateDuring.usages().size() == 0) { + stateDuring.delete(); + } + } + } + } +} diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GraphBuilderPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GraphBuilderPhase.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/GraphBuilderPhase.java Fri Aug 05 18:44:32 2011 +0200 @@ -762,7 +762,9 @@ Constant typeInstruction = genTypeOrDeopt(RiType.Representation.ObjectHub, type, type.isResolved()); Value object = frameState.apop(); if (typeInstruction != null) { - frameState.ipush(append(new MaterializeNode(new InstanceOf(typeInstruction, object, false, graph), graph))); + MaterializeNode materialize = new MaterializeNode(new InstanceOf(typeInstruction, object, false, graph), graph); + materialize.setStateDuring(frameState.create(bci())); + frameState.ipush(append(materialize)); } else { frameState.ipush(appendConstant(CiConstant.INT_0)); } diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/RematerializationPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/RematerializationPhase.java Fri Aug 05 15:14:03 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,286 +0,0 @@ -/* - * 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.phases; - -import java.text.*; -import java.util.*; - -import com.oracle.max.graal.compiler.*; -import com.oracle.max.graal.compiler.ir.*; -import com.oracle.max.graal.compiler.schedule.*; -import com.oracle.max.graal.compiler.util.*; -import com.oracle.max.graal.graph.*; -import com.oracle.max.graal.graph.collections.*; - - -public class RematerializationPhase extends Phase { - - private NodeMap nodeToBlock; - private HashMap newNodesToBlock; - private List blocks; - private UsageProbability[] probablityCache; - private boolean ignoreUsages; - - @Override - protected void run(Graph graph) { - Iterable modifiedNodes = graph.getModifiedNodes(); - graph.stopRecordModifications(); - NodeWorkList work = graph.createNodeWorkList(); - for (Node modified : modifiedNodes) { - if (modified instanceof FloatingNode) { - work.add(modified); - } - } - - if (work.isEmpty()) { - return; - } - - final IdentifyBlocksPhase s = new IdentifyBlocksPhase(true); - s.apply(graph); - - newNodesToBlock = new HashMap(); - nodeToBlock = s.getNodeToBlock(); - blocks = s.getBlocks(); - probablityCache = new UsageProbability[blocks.size()]; - - for (Node node : work) { - if (node instanceof Phi || node instanceof Local || node instanceof Constant || node instanceof LocationNode) { - continue; - } - boolean delay = false; - for (Node usage : node.usages()) { - if (usage instanceof FloatingNode && !(usage instanceof Phi) && work.isInQueue(usage)) { - delay = true; - break; - } - } - if (delay) { - work.addAgain(node); - continue; - } - Arrays.fill(probablityCache, null); - ignoreUsages = true; - Block block = nodeToBlock.get(node); - if (block == null) { - continue; - } - UsageProbability usageProbability = usageProbability(node, block); - if (usageProbability.probability < GraalOptions.MinimumUsageProbability) { - if (ignoreUsages) { - ignoreUsages = false; - Arrays.fill(probablityCache, null); - usageProbability = usageProbability(node, block); // recompute with usage maps - } - //TTY.println("going to remarterialize " + node + " at " + block + " : " + toString(usageProbability)); - boolean first = true; - for (Block sux : block.getSuccessors()) { - if (first) { - first = false; - continue; - } - usageProbability = usageProbability(node, sux); - List usages = new LinkedList(); - for (Node usage : usageProbability.usages) { - usages.add(usage); - } - if (!usages.isEmpty()) { - Node copy = node.copyWithEdges(); - newNodesToBlock.put(copy, sux); - GraalMetrics.Rematerializations++; - //TTY.println("> Rematerialized " + node + " : " + toString(usageProbability)); - for (Node usage : usages) { - usage.inputs().replace(node, copy); - if (usageProbability.phiUsages != null) { - Set phis = usageProbability.phiUsages.get(usage); - if (phis != null) { - for (Phi phi : phis) { - int index = phi.merge().phiPredecessorIndex(usage); - assert phi.valueAt(index) == node; - phi.setValueAt(index, (Value) copy); - } - } - } - } - } - } - } - } - } - - private UsageProbability usageProbability(Node n, Block b) { - UsageProbability cached = probablityCache[b.blockID()]; - if (cached != null) { - return cached; - } - if (ignoreUsages) { - GraalMetrics.PartialUsageProbability++; - } else { - GraalMetrics.FullUsageProbability++; - } - for (Node usage : n.usages()) { - if (usage instanceof Phi) { - Phi phi = (Phi) usage; - Merge merge = phi.merge(); - for (int i = 0; i < phi.valueCount(); i++) { - if (phi.valueAt(i) == n) { - insertUsageInCache(merge.phiPredecessorAt(i), phi); - } - } - } else { - insertUsageInCache(usage); - } - } - return usageProbability0(n, b); - } - - private void insertUsageInCache(Node usage) { - insertUsageInCache(usage, null); - } - - private void insertUsageInCache(Node usage, Phi phi) { - Block block = block(usage); - if (block == null) { - return; - } - int blockID = block.blockID(); - UsageProbability usageProbability = probablityCache[blockID]; - if (usageProbability == null) { - usageProbability = new UsageProbability(usage); - probablityCache[blockID] = usageProbability; - } else if (!ignoreUsages) { - usageProbability.usages.mark(usage); - } - if (phi != null) { - usageProbability.addPhiUsage(phi, usage); - } - } - - private Block block(Node node) { - Block block; - if (!nodeToBlock.isNew(node)) { - block = nodeToBlock.get(node); - } else { - block = newNodesToBlock.get(node); - assert block != null; - } - return block; - } - - private UsageProbability usageProbability0(Node n, Block b) { - //System.out.println("usageProbability0(" + n.id() + ", " + b + ")"); - UsageProbability cached = probablityCache[b.blockID()]; - if (cached != null && (cached.computed || ignoreUsages)) { - return cached; - } - UsageProbability result = cached; - if (result == null) { - result = new UsageProbability(n.graph()); - } - if (b.getSuccessors().size() > 0) { - if (b.isLoopEnd()) { - Block loopHeader = b.getSuccessors().get(0); - assert loopHeader.isLoopHeader(); - UsageProbability headerUsages = probablityCache[loopHeader.blockID()]; - if (headerUsages != null) { - result.merge(headerUsages, 1.0); - } - } else if (b.getSuccessors().size() == 1) { - result.merge(usageProbability0(n, b.getSuccessors().get(0)), 1.0); - } else { - Node lastNode = b.lastNode(); - if (lastNode instanceof Invoke) { - result.merge(usageProbability0(n, nodeToBlock.get(((Invoke) lastNode).next())), 1.0); - result.merge(usageProbability0(n, nodeToBlock.get(((Invoke) lastNode).exceptionEdge())), 0.0); - } else if (lastNode instanceof ControlSplit) { - ControlSplit split = (ControlSplit) lastNode; - for (int i = 0; i < split.blockSuccessorCount(); i++) { - result.merge(usageProbability0(n, nodeToBlock.get(split.blockSuccessor(i))), split.probability(i)); - } - } else { - throw Util.shouldNotReachHere(); - } - } - } - probablityCache[b.blockID()] = result; - result.computed = true; - return result; - } - - private class UsageProbability { - double probability; - NodeBitMap usages; - NodeMap> phiUsages; - boolean computed; - - public UsageProbability(Node usage) { - if (!ignoreUsages) { - usages = usage.graph().createNodeBitMap(); - usages.mark(usage); - } - probability = 1.0; - } - - public UsageProbability(Graph graph) { - if (!ignoreUsages) { - usages = graph.createNodeBitMap(); - } - probability = 0.0; - } - - public void merge(UsageProbability sux, double suxProbability) { - if (!ignoreUsages) { - usages.setUnion(sux.usages); - } - probability += suxProbability * sux.probability; - } - - public void addPhiUsage(Phi phi, Node usage) { - if (phiUsages == null) { - phiUsages = phi.graph().createNodeMap(); - } - Set phis = phiUsages.get(usage); - if (phis == null) { - phis = new HashSet(2); - phiUsages.set(usage, phis); - } - phis.add(phi); - } - } - - private String toString(UsageProbability up) { - NumberFormat nf = NumberFormat.getPercentInstance(); - StringBuilder sb = new StringBuilder("p="); - sb.append(nf.format(up.probability)); - if (up.usages != null) { - sb.append(" U=["); - for (Node n : up.usages) { - sb.append(n); - sb.append(", "); - } - sb.append("]"); - } - return sb.toString(); - } -} - diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/Block.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/Block.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/Block.java Fri Aug 05 18:44:32 2011 +0200 @@ -26,7 +26,6 @@ import com.oracle.max.graal.compiler.ir.*; import com.oracle.max.graal.graph.*; -import com.oracle.max.graal.graph.collections.*; public class Block { diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java Fri Aug 05 18:44:32 2011 +0200 @@ -314,7 +314,7 @@ } } - private void assignBlockToNode(Node n) { + public void assignBlockToNode(Node n) { if (n == null) { return; } diff -r 66e8bde93b6d -r e04e88087e98 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 Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRAssembler.java Fri Aug 05 18:44:32 2011 +0200 @@ -533,15 +533,17 @@ } else { unorderedLabel = op.unorderedBlock().label; } - masm.jcc(ConditionFlag.parity, unorderedLabel); + if (unorderedLabel != op.label() || !trueOnUnordered(op.cond())) { + masm.jcc(ConditionFlag.parity, unorderedLabel); + } // Checkstyle: off switch (op.cond()) { case EQ : acond = ConditionFlag.equal; break; case NE : acond = ConditionFlag.notEqual; break; - case LT : acond = ConditionFlag.below; break; - case LE : acond = ConditionFlag.belowEqual; break; - case GE : acond = ConditionFlag.aboveEqual; break; - case GT : acond = ConditionFlag.above; break; + case BT : acond = ConditionFlag.below; break; + case BE : acond = ConditionFlag.belowEqual; break; + case AE : acond = ConditionFlag.aboveEqual; break; + case AT : acond = ConditionFlag.above; break; default : throw Util.shouldNotReachHere(); } } else { @@ -710,7 +712,8 @@ } @Override - protected void emitConditionalMove(Condition condition, CiValue opr1, CiValue opr2, CiValue result) { + protected void emitConditionalMove(Condition condition, CiValue opr1, CiValue opr2, CiValue result, boolean mayBeUnordered, boolean unorderedcmovOpr1) { + //TTY.println("cmov " + condition + " " + opr1 + " : " + opr2 + " mayBeUnordered:" + mayBeUnordered + " pcmovop=" + (unorderedcmovOpr1 ? 1 : 2)); ConditionFlag acond; ConditionFlag ncond; switch (condition) { @@ -754,6 +757,14 @@ acond = ConditionFlag.above; ncond = ConditionFlag.belowEqual; break; + case OF: + acond = ConditionFlag.overflow; + ncond = ConditionFlag.noOverflow; + break; + case NOF: + acond = ConditionFlag.noOverflow; + ncond = ConditionFlag.overflow; + break; default: throw Util.shouldNotReachHere(); } @@ -766,13 +777,17 @@ def = opr2; other = opr1; // and flip the condition + condition = condition.negate(); ConditionFlag tcond = acond; acond = ncond; ncond = tcond; + unorderedcmovOpr1 = !unorderedcmovOpr1; } if (def.isRegister()) { - reg2reg(def, result); + if (def.asRegister() != result.asRegister()) { + reg2reg(def, result); + } } else if (def.isStackSlot()) { stack2reg(def, result, result.kind); } else { @@ -780,29 +795,24 @@ const2reg(def, result, null); } - if (!other.isConstant()) { + boolean cmovOnParity = (unorderedcmovOpr1 && mayBeTrueOnUnordered(condition.negate())) || (!unorderedcmovOpr1 && mayBeFalseOnUnordered(condition.negate())); + if (!other.isConstant() && !(cmovOnParity && def.isConstant())) { // optimized version that does not require a branch - if (other.isRegister()) { - assert other.asRegister() != result.asRegister() : "other already overwritten by previous move"; - if (other.kind.isInt()) { - masm.cmovq(ncond, result.asRegister(), other.asRegister()); - } else { - masm.cmovq(ncond, result.asRegister(), other.asRegister()); - } - } else { - assert other.isStackSlot(); - CiStackSlot otherSlot = (CiStackSlot) other; - if (other.kind.isInt()) { - masm.cmovl(ncond, result.asRegister(), frameMap.toStackAddress(otherSlot)); - } else { - masm.cmovq(ncond, result.asRegister(), frameMap.toStackAddress(otherSlot)); - } + //TTY.println("> emitting cmov" + (mayBeUnordered && cmovOnParity ? " (with parity check)" : "")); + cmov(result, ncond, other); + if (mayBeUnordered && cmovOnParity) { + cmov(result, ConditionFlag.parity, unorderedcmovOpr1 ? def : other); } - } else { + //TTY.println("> emitting jumps instead of cmov"); // conditional move not available, use emit a branch and move Label skip = new Label(); + Label mov = new Label(); + if (mayBeUnordered && ((mayBeTrueOnUnordered(condition) && !unorderedcmovOpr1) || (mayBeFalseOnUnordered(condition) && unorderedcmovOpr1))) { + masm.jcc(ConditionFlag.parity, unorderedcmovOpr1 ? skip : mov); + } masm.jcc(acond, skip); + masm.bind(mov); if (other.isRegister()) { reg2reg(other, result); } else if (other.isStackSlot()) { @@ -815,6 +825,25 @@ } } + private void cmov(CiValue result, ConditionFlag ncond, CiValue other) { + if (other.isRegister()) { + assert other.asRegister() != result.asRegister() : "other already overwritten by previous move"; + if (other.kind.isInt()) { + masm.cmovl(ncond, result.asRegister(), other.asRegister()); + } else { + masm.cmovq(ncond, result.asRegister(), other.asRegister()); + } + } else { + assert other.isStackSlot(); + CiStackSlot otherSlot = (CiStackSlot) other; + if (other.kind.isInt()) { + masm.cmovl(ncond, result.asRegister(), frameMap.toStackAddress(otherSlot)); + } else { + masm.cmovq(ncond, result.asRegister(), frameMap.toStackAddress(otherSlot)); + } + } + } + @Override protected void emitArithOp(LIROpcode code, CiValue left, CiValue right, CiValue dest, LIRDebugInfo info) { assert info == null : "should never be used : idiv/irem and ldiv/lrem not handled by this method"; @@ -1260,8 +1289,8 @@ case Double : masm.ucomisd(reg1, tasm.recordDataReferenceInCode(CiConstant.forDouble(((CiConstant) opr2).asDouble()))); break; case Long : case Word : { - if (c.asLong() == 0) { - masm.cmpq(reg1, 0); + if (NumUtil.isInt(c.asLong())) { + masm.cmpq(reg1, (int) c.asLong()); } else { masm.movq(rscratch1, c.asLong()); masm.cmpq(reg1, rscratch1); @@ -1291,10 +1320,21 @@ case Short : case Int : masm.cmpl(left, right.asInt()); break; case Long : - case Word : assert NumUtil.isInt(right.asLong()); - masm.cmpq(left, right.asInt()); break; - case Object : assert right.isNull(); - masm.cmpq(left, 0); break; + case Word : if (NumUtil.isInt(right.asLong())) { + masm.cmpq(left, (int) right.asLong()); + } else { + masm.movq(rscratch1, right.asLong()); + masm.cmpq(left, rscratch1); + + } + break; + case Object : if (right.isNull()) { + masm.cmpq(left, 0); + } else { + movoop(rscratch1, right); + masm.cmpq(left, rscratch1); + } + break; default : throw Util.shouldNotReachHere(); } } else { @@ -2225,6 +2265,51 @@ tasm.recordExceptionHandlers(after, info); } + @Override + public boolean falseOnUnordered(Condition condition) { + switch(condition) { + case AE: + case NE: + case GT: + case AT: + return true; + case EQ: + case LE: + case BE: + case BT: + case LT: + case GE: + case OF: + case NOF: + return false; + default: + throw Util.shouldNotReachHere(); + } + } + + @Override + public boolean trueOnUnordered(Condition condition) { + switch(condition) { + case AE: + case NE: + case GT: + case AT: + return false; + case EQ: + case LE: + case BE: + case BT: + return true; + case LT: + case GE: + case OF: + case NOF: + return false; + default: + throw Util.shouldNotReachHere(); + } + } + protected void stop(String msg) { if (GraalOptions.GenAssertionCode) { // TODO: pass a pointer to the message diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRGenerator.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRGenerator.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRGenerator.java Fri Aug 05 18:44:32 2011 +0200 @@ -71,12 +71,12 @@ } @Override - protected boolean canInlineAsConstant(Value v) { + public boolean canInlineAsConstant(Value v) { + if (!v.isConstant()) { + return false; + } if (v.kind == CiKind.Long) { - if (v.isConstant() && NumUtil.isInt(v.asConstant().asLong())) { - return true; - } - return false; + return NumUtil.isInt(v.asConstant().asLong()); } return v.kind != CiKind.Object || v.isNullConstant(); } @@ -408,7 +408,7 @@ } @Override - public void visitMaterialize(NormalizeCompare x) { + public void visitNormalizeCompare(NormalizeCompare x) { LIRItem left = new LIRItem(x.x(), this); LIRItem right = new LIRItem(x.y(), this); if (!x.kind.isVoid() && x.x().kind.isLong()) { @@ -463,4 +463,20 @@ public void visitValueAnchor(ValueAnchor valueAnchor) { // nothing to do for ValueAnchors } + + @Override + public Condition floatingPointCondition(Condition cond) { + switch(cond) { + case LT: + return Condition.BT; + case LE: + return Condition.BE; + case GT: + return Condition.AT; + case GE: + return Condition.AE; + default : + return cond; + } + } } diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/BitMap2D.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/BitMap2D.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/BitMap2D.java Fri Aug 05 18:44:32 2011 +0200 @@ -23,7 +23,6 @@ package com.oracle.max.graal.compiler.util; import com.oracle.max.graal.graph.*; -import com.oracle.max.graal.graph.collections.*; /** * This class implements a two-dimensional bitmap. diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/GraphUtil.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/GraphUtil.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/GraphUtil.java Fri Aug 05 18:44:32 2011 +0200 @@ -31,8 +31,9 @@ import com.oracle.max.graal.compiler.observer.*; import com.oracle.max.graal.compiler.value.*; import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.graph.NodeClass.*; import com.oracle.max.graal.graph.collections.*; -import com.oracle.max.graal.graph.collections.NodeWorkList.*; +import com.oracle.max.graal.graph.collections.NodeWorkList.InfiniteWorkException; public class GraphUtil { @@ -87,17 +88,12 @@ } private static Collection colorCFGDownToMerge(Node from, T color, NodeMap colors) { - throw new UnsupportedOperationException(); - /* - //System.out.println("colorCFGDownToMerge(" + from + ", " + color + ", colors)"); NodeFlood work = from.graph().createNodeFlood(); Collection merges = new LinkedList(); work.add(from); for (Node node : work) { - //System.out.println("colorToMerge : work on " + node); Node current = node; while (current != null) { - //System.out.println("colorToMerge : current " + current); if (current instanceof Merge) { merges.add((Merge) current); break; @@ -126,8 +122,7 @@ } } } - //System.out.println("return " + merges); - return merges;*/ + return merges; } public static interface ColorSplitingLambda { @@ -141,8 +136,6 @@ // TODO (gd) rework that code around Phi handling : too complicated public static void splitFromColoring(NodeMap coloring, ColorSplitingLambda lambda) { - throw new UnsupportedOperationException(); - /* Map internalColoring = new HashMap(); NodeWorkList work = coloring.graph().createNodeWorkList(); for (Entry entry : coloring.entries()) { @@ -154,7 +147,6 @@ Set colors = new HashSet(); try { for (Node node : work) { - //System.out.println("Split : work on " + node); if (node instanceof Phi) { Phi phi = (Phi) node; Merge merge = phi.merge(); @@ -168,7 +160,6 @@ phi.setValueAt(i, replace); } else { if (lambda.explore(v) && coloring.get(v) == null && !work.isNew(v)) { - //System.out.println("Split : Add input " + input + " to work from " + node); work.add(v); } } @@ -180,7 +171,6 @@ colors.clear(); T originalColoringColor = coloring.get(node); if (originalColoringColor == null && internalColoring.get(node) != null) { - //System.out.println("Split : ori == null && intern != null -> continue"); continue; } if (originalColoringColor == null) { @@ -188,7 +178,6 @@ if (usage instanceof Phi) { Phi phi = (Phi) usage; Merge merge = phi.merge(); - //System.out.println("Split merge : " + merge + ".endCount = " + merge.endCount() + " phi " + phi + ".valueCount : " + phi.valueCount()); for (int i = 0; i < phi.valueCount(); i++) { Value v = phi.valueAt(i); if (v == node) { @@ -201,7 +190,6 @@ } else { T color = internalColoring.get(usage); if (color == null) { - //System.out.println("Split : color from " + usage + " is null : " + (lambda.explore(usage) ? "Should be colored" : "Should be white")); if (lambda.explore(usage)) { delay = true; break; @@ -212,7 +200,6 @@ } } if (delay) { - //System.out.println("Split : delay"); work.addAgain(node); continue; } @@ -220,7 +207,6 @@ colors.add(originalColoringColor); } if (colors.size() == 1) { - //System.out.println("Split : 1 color, coloring, fixing"); T color = colors.iterator().next(); internalColoring.put(node, color); lambda.fixNode(node, color); @@ -246,18 +232,18 @@ Phi phi = new Phi(((Value) node).kind, lambda.merge(color), PhiType.Value, node.graph()); for (T parentColor : parentColors) { Node input = newNodes.get(parentColor); - phi.addInput(input); + phi.addInput((Value) input); } newNode = phi; } else { - newNode = node.copy(); - for (int i = 0; i < node.inputs().size(); i++) { - Node input = node.inputs().get(i); - newNode.inputs().setOrExpand(i, input); + newNode = node.copy(node.graph()); + for (NodeClassIterator iter = node.inputs().iterator(); iter.hasNext();) { + Position pos = iter.nextPosition(); + newNode.set(pos, node.get(pos)); } - for (int i = 0; i < node.successors().size(); i++) { - Node input = node.successors().get(i); - newNode.successors().setOrExpand(i, input); + for (NodeClassIterator iter = node.successors().iterator(); iter.hasNext();) { + Position pos = iter.nextPosition(); + newNode.set(pos, node.get(pos)); } internalColoring.put(newNode, color); lambda.fixSplit(node, newNode, color); @@ -288,12 +274,11 @@ } } } - lambda.fixNode(node, null*/ /*white*/ /*); + lambda.fixNode(node, null /*white*/); } if (node instanceof StateSplit) { FrameState stateAfter = ((StateSplit) node).stateAfter(); if (stateAfter != null && lambda.explore(stateAfter) && !work.isNew(stateAfter)) { - //System.out.println("Split : Add framestate to work"); if (!(node instanceof Merge && coloring.get(((Merge) node).next()) == null)) { // not dangling colored merge work.add(stateAfter); } @@ -314,7 +299,6 @@ for (Node input : node.dataInputs()) { if (lambda.explore(input) && coloring.get(input) == null && !work.isNew(input)) { - //System.out.println("Split : Add input " + input + " to work from " + node); work.add(input); } } @@ -346,6 +330,6 @@ Map debug = new HashMap(); debug.put("split", debugColoring); compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "Split end!!", coloring.graph(), true, false, debug)); - }*/ + } } } diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/LoopUtil.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/LoopUtil.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/util/LoopUtil.java Fri Aug 05 18:44:32 2011 +0200 @@ -277,32 +277,13 @@ LoopEnd loopEnd = loop.loopBegin().loopEnd(); PeelingResult peeling = preparePeeling(loop, loopEnd); GraalCompilation compilation = GraalCompilation.compilation(); + if (compilation.compiler.isObserved()) { compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "After peeling preparation", loopEnd.graph(), true, false)); } - /*System.out.println("Peeling : "); - System.out.println(" begin = " + peeling.begin); - System.out.println(" end = " + peeling.end); - System.out.println(" Phis :"); - for (Entry entry : peeling.phis.entries()) { - System.out.println(" - " + entry.getKey() + " -> " + entry.getValue()); - } - System.out.println(" Exits :"); - for (Entry entry : peeling.exits.entries()) { - System.out.println(" - " + entry.getKey() + " -> " + entry.getValue()); - } - System.out.println(" PhiInits :"); - for (Entry entry : peeling.phiInits.entries()) { - System.out.println(" - " + entry.getKey() + " -> " + entry.getValue()); - } - System.out.println(" DataOut :"); - for (Entry entry : peeling.dataOut.entries()) { - System.out.println(" - " + entry.getKey() + " -> " + entry.getValue()); - }*/ + rewirePeeling(peeling, loop); - /*if (compilation.compiler.isObserved()) { - compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "After rewirePeeling", loopEnd.graph(), true, false)); - }*/ + loop.invalidateCached(); // update parents Loop parent = loop.parent(); @@ -333,8 +314,6 @@ if (originalLast == loopBegin.loopEnd()) { originalLast = loopBegin.loopEnd().predecessor(); } - for (Node sux : originalLast.successors()) { - } boolean found = false; for (NodeClassIterator iter = originalLast.successors().iterator(); iter.hasNext();) { Position pos = iter.nextPosition(); @@ -358,7 +337,6 @@ for (Entry dataEntry : peeling.dataOut.entries()) { if (dataEntry.getValue() == p) { dataEntry.setValue(init); - //System.out.println("Patch dataOut : " + dataEntry.getKey() + " -> " + dataEntry.getValue()); } } } @@ -486,14 +464,6 @@ colors.set(exitPoint, exitPoint); } - /*System.out.println("newExitValues"); - for (Entry> entry : newExitValues.entries()) { - System.out.println(" - " + entry.getKey() + " :"); - for (Entry entry2 : entry.getValue().entries()) { - System.out.println(" + " + entry2.getKey() + " -> " + entry2.getValue()); - } - }*/ - // color GraphUtil.colorCFGDown(colors, new ColoringLambda() { @Override @@ -550,7 +520,6 @@ private Value getValueAt(Node point, NodeMap valueMap, CiKind kind) { Value value = valueMap.get(point); if (value != null) { - //System.out.println("getValueAt(" + point + ", valueMap, kind) = (cached) " + value); return value; } Merge merge = (Merge) point; @@ -572,24 +541,16 @@ for (EndNode end : merge.cfgPredecessors()) { phi.addInput(getValueAt(colors.get(end), valueMap, kind)); } - //System.out.println("getValueAt(" + point + ", valueMap, kind) = (new-phi) " + phi); return phi; } else { assert v != null; valueMap.set(point, v); - //System.out.println("getValueAt(" + point + ", valueMap, kind) = (unique) " + v); return v; } } @Override public boolean explore(Node n) { - /*System.out.println("Explore " + n + "?"); - System.out.println(" - exitFS : " + (!exitFrameStates.isNew(n) && exitFrameStates.isMarked(n))); - System.out.println(" - !inOrBefore : " + (!inOrBefore.isNew(n) && !inOrBefore.isMarked(n))); - System.out.println(" - inputs > 0 : " + (n.inputs().size() > 0)); - System.out.println(" - !danglingMergeFrameState : " + (!danglingMergeFrameState(n)));*/ - return exitFrameStates.isNotNewMarked(n) - || (inOrBefore.isNotNewNotMarked(n) && n.inputs().explicitCount() > 0 && !afterColoringFramestate(n)); //TODO (gd) hum + return exitFrameStates.isNotNewMarked(n) || (inOrBefore.isNotNewNotMarked(n) && n.getNodeClass().directInputCount() > 0 && !afterColoringFramestate(n)); //TODO (gd) hum } public boolean afterColoringFramestate(Node n) { if (!(n instanceof FrameState)) { @@ -613,7 +574,6 @@ } @Override public void fixNode(Node node, Node color) { - //System.out.println("fixNode(" + node + ", " + color + ")"); if (color == null) { // 'white' it out : make non-explorable if (!exitFrameStates.isNew(node)) { @@ -663,22 +623,12 @@ return (Merge) color; } }); - - /*if (compilation.compiler.isObserved()) { - compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "After split from colors", graph, true, false)); - }*/ } private static PeelingResult preparePeeling(Loop loop, FixedNode from) { LoopBegin loopBegin = loop.loopBegin(); Graph graph = loopBegin.graph(); NodeBitMap marked = computeLoopNodesFrom(loop, from); - GraalCompilation compilation = GraalCompilation.compilation(); - /*if (compilation.compiler.isObserved()) { - Map debug = new HashMap(); - debug.put("marked", marked); - compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "After computeLoopNodesFrom", loopBegin.graph(), true, false, debug)); - }*/ if (from == loopBegin.loopEnd()) { clearWithState(from, marked); } @@ -731,20 +681,8 @@ } } - //GraalCompilation compilation = GraalCompilation.compilation(); - if (compilation.compiler.isObserved()) { - Map debug = new HashMap(); - debug.put("marked", marked); - compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "Before addDuplicate loop#" + loopBegin.id(), loopBegin.graph(), true, false, debug)); - } - Map duplicates = graph.addDuplicate(marked, replacements); - /*System.out.println("Dup mapping :"); - for (Entry entry : duplicates.entrySet()) { - System.out.println(" - " + entry.getKey().id() + " -> " + entry.getValue().id()); - }*/ - NodeMap dataOutMapping = graph.createNodeMap(); for (Node n : dataOut) { Node newOut = duplicates.get(n); @@ -812,7 +750,6 @@ NodeFlood work = graph.createNodeFlood(); work.addAll(cfgNodes); for (Node n : work) { - //inOrAfter.mark(n); markWithState(n, inOrAfter); if (full) { for (Node sux : n.successors()) { diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameStateBuilder.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameStateBuilder.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/value/FrameStateBuilder.java Fri Aug 05 18:44:32 2011 +0200 @@ -47,6 +47,16 @@ private final RiMethod method; + public FrameStateBuilder(FrameState fs) { + this.method = fs.method; + this.graph = fs.graph(); + this.locals = new Value[method.maxLocals()]; + int stackSize = Math.max(1, method.maxStackSize()); + this.stack = new Value[stackSize]; + this.locks = new ArrayList(); + this.initializeFrom(fs); + } + public FrameStateBuilder(RiMethod method, Graph graph) { assert graph != null; this.method = method; diff -r 66e8bde93b6d -r e04e88087e98 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 Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/HotSpotRuntime.java Fri Aug 05 18:44:32 2011 +0200 @@ -514,7 +514,7 @@ graph.setReturn(ret); return graph; } - } else if (holderName.equals("Ljava/lang/Float;")) { + } else if (holderName.equals("Ljava/lang/Float;")) { //XXX (gd) the non-raw versions of (F/D)2(I/L) should return a sanitized NaN in the NaN case. also check NaN case for (I/L)2(F/D) if (fullName.equals("floatToRawIntBits(F)I") || fullName.equals("floatToIntBits(F)I")) { CompilerGraph graph = new CompilerGraph(this); Return ret = new Return(new FPConversionNode(CiKind.Int, new Local(CiKind.Float, 0, graph), graph), graph); diff -r 66e8bde93b6d -r e04e88087e98 graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/FPConversionNode.java --- a/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/FPConversionNode.java Fri Aug 05 15:14:03 2011 +0200 +++ b/graal/com.oracle.max.graal.runtime/src/com/oracle/max/graal/runtime/nodes/FPConversionNode.java Fri Aug 05 18:44:32 2011 +0200 @@ -24,7 +24,9 @@ import com.oracle.max.graal.compiler.debug.*; import com.oracle.max.graal.compiler.gen.*; +import com.oracle.max.graal.compiler.gen.LIRGenerator.LIRGeneratorOp; import com.oracle.max.graal.compiler.ir.*; +import com.oracle.max.graal.compiler.phases.CanonicalizerPhase.*; import com.oracle.max.graal.graph.*; import com.sun.cri.ci.*; @@ -52,17 +54,11 @@ @SuppressWarnings("unchecked") @Override public T lookup(Class clazz) { - if (clazz == LIRGenerator.LIRGeneratorOp.class) { - return (T) new LIRGenerator.LIRGeneratorOp() { - @Override - public void generate(Node n, LIRGenerator generator) { - FPConversionNode conv = (FPConversionNode) n; - CiValue reg = generator.createResultVariable(conv); - CiValue value = generator.load(conv.value()); - CiValue tmp = generator.forceToSpill(value, conv.kind, false); - generator.lir().move(tmp, reg); - } - }; + if (clazz == LIRGeneratorOp.class) { + return (T) LIRGEN; + } + if (clazz == CanonicalizerOp.class) { + return (T) CANON; } return super.lookup(clazz); } @@ -81,4 +77,37 @@ public Node copy(Graph into) { return new FPConversionNode(kind, null, into); } + + private static final CanonicalizerOp CANON = new CanonicalizerOp() { + @Override + public Node canonical(Node node, NotifyReProcess reProcess) { + FPConversionNode conv = (FPConversionNode) node; + Value value = conv.value(); + if (value instanceof Constant) { + CiKind toKind = conv.kind; + CiKind fromKind = value.kind; + if (toKind == CiKind.Int && fromKind == CiKind.Float) { + return Constant.forInt(Float.floatToRawIntBits(((Constant) value).asConstant().asFloat()), node.graph()); + } else if (toKind == CiKind.Long && fromKind == CiKind.Double) { + return Constant.forLong(Double.doubleToRawLongBits(((Constant) value).asConstant().asDouble()), node.graph()); + } else if (toKind == CiKind.Float && fromKind == CiKind.Int) { + return Constant.forFloat(Float.intBitsToFloat(((Constant) value).asConstant().asInt()), node.graph()); + } else if (toKind == CiKind.Double && fromKind == CiKind.Long) { + return Constant.forDouble(Double.longBitsToDouble(((Constant) value).asConstant().asLong()), node.graph()); + } + } + return conv; + } + }; + + private static final LIRGeneratorOp LIRGEN = new LIRGeneratorOp() { + @Override + public void generate(Node n, LIRGenerator generator) { + FPConversionNode conv = (FPConversionNode) n; + CiValue reg = generator.createResultVariable(conv); + CiValue value = generator.load(conv.value()); + CiValue tmp = generator.forceToSpill(value, conv.kind, false); + generator.lir().move(tmp, reg); + } + }; }