# HG changeset patch # User Thomas Wuerthinger # Date 1339806002 -7200 # Node ID bda2ebe1fc6144b787d00a3eaa9c70fa005a1b19 # Parent 4d0f01e9f31b3f8694b56ebd59caf5a12dae3f73# Parent 63bd4fd90c27d0ba130b1d9dee0d360b8062388c Merge. diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java Sat Jun 16 02:19:38 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalOptions.java Sat Jun 16 02:20:02 2012 +0200 @@ -261,7 +261,7 @@ * Only instructions in methods whose fully qualified name contains this option will be HIR lowered. */ public static String HIRLowerCheckcast = ""; - public static String HIRLowerNewInstance = "NewInstanceTest"; + public static String HIRLowerNewInstance = "NewInstanceTest.new"; /** * The profiling info cache directory. diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/BasicInductionVariable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/BasicInductionVariable.java Sat Jun 16 02:20:02 2012 +0200 @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.loop; + +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.type.*; + + +public class BasicInductionVariable extends InductionVariable { + private PhiNode phi; + private ValueNode init; + private ValueNode rawStride; + private IntegerArithmeticNode op; + + public BasicInductionVariable(LoopEx loop, PhiNode phi, ValueNode init, ValueNode rawStride, IntegerArithmeticNode op) { + super(loop); + this.phi = phi; + this.init = init; + this.rawStride = rawStride; + this.op = op; + } + + @Override + public Direction direction() { + Stamp stamp = rawStride.stamp(); + if (stamp instanceof IntegerStamp) { + IntegerStamp integerStamp = (IntegerStamp) stamp; + Direction dir = null; + if (integerStamp.lowerBound() > 0) { + dir = Direction.Up; + } else if (integerStamp.upperBound() < 0) { + dir = Direction.Down; + } + if (dir != null) { + if (op instanceof IntegerAddNode) { + return dir; + } else { + assert op instanceof IntegerSubNode; + return dir.opposite(); + } + } + } + return null; + } + + @Override + public PhiNode valueNode() { + return phi; + } + + @Override + public ValueNode initNode() { + return init; + } + + @Override + public ValueNode strideNode() { + if (op instanceof IntegerAddNode) { + return rawStride; + } + if (op instanceof IntegerSubNode) { + return rawStride.graph().unique(new NegateNode(rawStride)); + } + throw GraalInternalError.shouldNotReachHere(); + } + + @Override + public boolean isConstantInit() { + return init.isConstant(); + } + + @Override + public boolean isConstantStride() { + return rawStride.isConstant(); + } + + @Override + public long constantInit() { + return init.asConstant().asLong(); + } + + @Override + public long constantStride() { + if (op instanceof IntegerAddNode) { + return rawStride.asConstant().asLong(); + } + if (op instanceof IntegerSubNode) { + return -rawStride.asConstant().asLong(); + } + throw GraalInternalError.shouldNotReachHere(); + } + + @Override + public ValueNode extremumNode() { + return IntegerArithmeticNode.add(IntegerArithmeticNode.mul(strideNode(), loop.counted().maxTripCountNode()), init); + } + + @Override + public boolean isConstantExtremum() { + return isConstantInit() && isConstantStride() && loop.counted().isConstantMaxTripCount(); + } + + @Override + public long constantExtremum() { + return constantStride() * loop.counted().constantMaxTripCount() + constantInit(); + } +} diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/CountedLoopInfo.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/CountedLoopInfo.java Sat Jun 16 02:20:02 2012 +0200 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.loop; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; + +public class CountedLoopInfo { + private final LoopEx loop; + private InductionVariable iv; + private ValueNode end; + + CountedLoopInfo(LoopEx loop, InductionVariable iv, ValueNode end) { + this.loop = loop; + this.iv = iv; + this.end = end; + } + + public ValueNode maxTripCountNode() { + return IntegerArithmeticNode.div(IntegerArithmeticNode.sub(end, iv.initNode()), iv.strideNode()); + } + + public boolean isConstantMaxTripCount() { + return end instanceof ConstantNode && iv.isConstantInit() && iv.isConstantStride(); + } + + public long constantMaxTripCount() { + return (((ConstantNode) end).asConstant().asLong() - iv.constantInit()) / iv.constantStride(); + } + + public boolean isExactTripCount() { + return loop.loopBegin().loopExits().count() == 1; + } + + public ValueNode exactTripCountNode() { + assert isExactTripCount(); + return maxTripCountNode(); + } + + public boolean isConstantExactTripCount() { + assert isExactTripCount(); + return isConstantMaxTripCount(); + } + + public long constantExactTripCount() { + assert isExactTripCount(); + return constantMaxTripCount(); + } +} diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/DerivedOffsetInductionVariable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/DerivedOffsetInductionVariable.java Sat Jun 16 02:20:02 2012 +0200 @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.loop; + +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; + + +public class DerivedOffsetInductionVariable extends InductionVariable { + private InductionVariable base; + private ValueNode offset; + private IntegerArithmeticNode value; + + public DerivedOffsetInductionVariable(LoopEx loop, InductionVariable base, ValueNode offset, IntegerArithmeticNode value) { + super(loop); + this.base = base; + this.offset = offset; + this.value = value; + } + + @Override + public Direction direction() { + return base.direction(); + } + + @Override + public ValueNode valueNode() { + return value; + } + + @Override + public boolean isConstantInit() { + return offset.isConstant() && base.isConstantInit(); + } + + @Override + public boolean isConstantStride() { + return base.isConstantStride(); + } + + @Override + public long constantInit() { + return op(base.constantInit(), offset.asConstant().asLong()); + } + + @Override + public long constantStride() { + if (value instanceof IntegerSubNode && base.valueNode() == value.y()) { + return -base.constantStride(); + } + return base.constantStride(); + } + + @Override + public ValueNode initNode() { + return op(base.initNode(), offset); + } + + @Override + public ValueNode strideNode() { + if (value instanceof IntegerSubNode && base.valueNode() == value.y()) { + return value.graph().unique(new NegateNode(base.strideNode())); + } + return base.strideNode(); + } + + @Override + public ValueNode extremumNode() { + return op(offset, base.extremumNode()); + } + + @Override + public boolean isConstantExtremum() { + return offset.isConstant() && base.isConstantExtremum(); + } + + @Override + public long constantExtremum() { + return op(base.constantExtremum(), offset.asConstant().asLong()); + } + + private long op(long b, long o) { + if (value instanceof IntegerAddNode) { + return b + o; + } + if (value instanceof IntegerSubNode) { + if (base.valueNode() == value.x()) { + return b - o; + } else { + assert base.valueNode() == value.y(); + return o - b; + } + } + throw GraalInternalError.shouldNotReachHere(); + } + + private ValueNode op(ValueNode b, ValueNode o) { + if (value instanceof IntegerAddNode) { + return IntegerArithmeticNode.add(b, o); + } + if (value instanceof IntegerSubNode) { + if (base.valueNode() == value.x()) { + return IntegerArithmeticNode.sub(b, o); + } else { + assert base.valueNode() == value.y(); + return IntegerArithmeticNode.sub(o, b); + } + } + throw GraalInternalError.shouldNotReachHere(); + } +} diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/DerivedScaledInductionVariable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/DerivedScaledInductionVariable.java Sat Jun 16 02:20:02 2012 +0200 @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.loop; + +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.type.*; + + +public class DerivedScaledInductionVariable extends InductionVariable { + private InductionVariable base; + private ValueNode scale; + private ValueNode value; + + public DerivedScaledInductionVariable(LoopEx loop, InductionVariable base, ValueNode scale, ValueNode value) { + super(loop); + this.base = base; + this.scale = scale; + this.value = value; + } + + public DerivedScaledInductionVariable(LoopEx loop, InductionVariable base, NegateNode value) { + super(loop); + this.base = base; + this.scale = ConstantNode.forInt(-1, value.graph()); + this.value = value; + } + + @Override + public Direction direction() { + Stamp stamp = scale.stamp(); + if (stamp instanceof IntegerStamp) { + IntegerStamp integerStamp = (IntegerStamp) stamp; + if (integerStamp.lowerBound() > 0) { + return base.direction(); + } else if (integerStamp.upperBound() < 0) { + return base.direction().opposite(); + } + } + return null; + } + + @Override + public ValueNode valueNode() { + return value; + } + + @Override + public ValueNode initNode() { + return IntegerArithmeticNode.mul(base.initNode(), scale); + } + + @Override + public ValueNode strideNode() { + return IntegerArithmeticNode.mul(base.strideNode(), scale); + } + + @Override + public boolean isConstantInit() { + return scale.isConstant() && base.isConstantInit(); + } + + @Override + public boolean isConstantStride() { + return scale.isConstant() && base.isConstantStride(); + } + + @Override + public long constantInit() { + return base.constantInit() * scale.asConstant().asLong(); + } + + @Override + public long constantStride() { + return base.constantStride() * scale.asConstant().asLong(); + } + + @Override + public ValueNode extremumNode() { + return IntegerArithmeticNode.mul(base.extremumNode(), scale); + } + + @Override + public boolean isConstantExtremum() { + return scale.isConstant() && base.isConstantExtremum(); + } + + @Override + public long constantExtremum() { + return base.constantExtremum() * scale.asConstant().asLong(); + } +} diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/InductionVariable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/InductionVariable.java Sat Jun 16 02:20:02 2012 +0200 @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.loop; + +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; + + +public abstract class InductionVariable { + public enum Direction { + Up, + Down; + public Direction opposite() { + switch(this) { + case Up: return Down; + case Down: return Up; + default: throw GraalInternalError.shouldNotReachHere(); + } + } + } + + protected final LoopEx loop; + + public InductionVariable(LoopEx loop) { + this.loop = loop; + } + + public abstract Direction direction(); + + public abstract ValueNode valueNode(); + + public abstract ValueNode initNode(); + public abstract ValueNode strideNode(); + + public abstract boolean isConstantInit(); + public abstract boolean isConstantStride(); + + public abstract long constantInit(); + public abstract long constantStride(); + + public abstract ValueNode extremumNode(); + public abstract boolean isConstantExtremum(); + public abstract long constantExtremum(); +} diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/InductionVariables.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/InductionVariables.java Sat Jun 16 02:20:02 2012 +0200 @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.compiler.loop; + +import java.util.*; + +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; + + +public class InductionVariables { + private final LoopEx loop; + private Map ivs; + + public InductionVariables(LoopEx loop) { + this.loop = loop; + ivs = new IdentityHashMap<>(); + findDerived(findBasic()); + } + + public InductionVariable get(ValueNode v) { + return ivs.get(v); + } + + private Collection findBasic() { + List bivs = new LinkedList<>(); + LoopBeginNode loopBegin = loop.loopBegin(); + EndNode forwardEnd = loopBegin.forwardEnd(); + for (PhiNode phi : loopBegin.phis()) { + ValueNode backValue = phi.singleBackValue(); + if (backValue == null) { + continue; + } + ValueNode stride = addSub(backValue, phi); + if (stride != null) { + BasicInductionVariable biv = new BasicInductionVariable(loop, phi, phi.valueAt(forwardEnd), stride, (IntegerArithmeticNode) backValue); + ivs.put(phi, biv); + bivs.add(biv); + } + } + return bivs; + } + + private void findDerived(Collection bivs) { + Queue scanQueue = new LinkedList(bivs); + while (!scanQueue.isEmpty()) { + InductionVariable baseIv = scanQueue.remove(); + ValueNode baseIvNode = baseIv.valueNode(); + for (ValueNode op : baseIvNode.usages().filter(ValueNode.class)) { + if (loop.isOutsideLoop(op)) { + continue; + } + InductionVariable iv = null; + ValueNode offset = addSub(op, baseIvNode); + ValueNode scale; + if (offset != null) { + iv = new DerivedOffsetInductionVariable(loop, baseIv, offset, (IntegerArithmeticNode) op); + } else if (op instanceof NegateNode) { + iv = new DerivedScaledInductionVariable(loop, baseIv, (NegateNode) op); + } else if ((scale = mul(op, baseIvNode)) != null) { + iv = new DerivedScaledInductionVariable(loop, baseIv, scale, op); + } + + if (iv != null) { + ivs.put(op, iv); + scanQueue.offer(iv); + } + } + } + } + + private ValueNode addSub(ValueNode op, ValueNode base) { + if (op instanceof IntegerAddNode || op instanceof IntegerSubNode) { + IntegerArithmeticNode aritOp = (IntegerArithmeticNode) op; + if (aritOp.x() == base && loop.isOutsideLoop(aritOp.y())) { + return aritOp.y(); + } else if (aritOp.y() == base && loop.isOutsideLoop(aritOp.x())) { + return aritOp.x(); + } + } + return null; + } + + private ValueNode mul(ValueNode op, ValueNode base) { + if (op instanceof IntegerMulNode) { + IntegerMulNode mul = (IntegerMulNode) op; + if (mul.x() == base && loop.isOutsideLoop(mul.y())) { + return mul.y(); + } else if (mul.y() == base && loop.isOutsideLoop(mul.x())) { + return mul.x(); + } + } + if (op instanceof LeftShiftNode) { + LeftShiftNode shift = (LeftShiftNode) op; + if (shift.x() == base && shift.y().isConstant()) { + return ConstantNode.forInt(1 << shift.y().asConstant().asInt(), base.graph()); + } + } + return null; + } +} diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopEx.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopEx.java Sat Jun 16 02:19:38 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopEx.java Sat Jun 16 02:20:02 2012 +0200 @@ -30,7 +30,7 @@ private final Loop lirLoop; private LoopFragmentInside inside; private LoopFragmentWhole whole; - private boolean isCounted; //TODO (gd) detect + private CountedLoopInfo counted; //TODO (gd) detect private LoopsData data; LoopEx(Loop lirLoop, LoopsData data) { @@ -68,7 +68,7 @@ return null; } - public boolean isInvariant(Node n) { + public boolean isOutsideLoop(Node n) { return !whole().contains(n); } @@ -85,7 +85,11 @@ } public boolean isCounted() { - return isCounted; + return counted != null; + } + + public CountedLoopInfo counted() { + return counted; } public LoopEx parent() { diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopFragment.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopFragment.java Sat Jun 16 02:19:38 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopFragment.java Sat Jun 16 02:20:02 2012 +0200 @@ -156,8 +156,9 @@ } for (BeginNode earlyExit : earlyExits) { FrameState stateAfter = earlyExit.stateAfter(); - assert stateAfter != null; - nodes.mark(stateAfter); + if (stateAfter != null) { + nodes.mark(stateAfter); + } nodes.mark(earlyExit); for (ValueProxyNode proxy : earlyExit.proxies()) { nodes.mark(proxy); diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopsData.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopsData.java Sat Jun 16 02:19:38 2012 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/loop/LoopsData.java Sat Jun 16 02:20:02 2012 +0200 @@ -24,8 +24,12 @@ import java.util.*; +import com.oracle.graal.compiler.loop.InductionVariable.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.graph.*; import com.oracle.graal.lir.cfg.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; public class LoopsData { private Map lirLoopToEx = new IdentityHashMap<>(); @@ -72,4 +76,72 @@ } return counted; } + + public void detectedCountedLoops() { + for (LoopEx loop : loops()) { + InductionVariables ivs = new InductionVariables(loop); + LoopBeginNode loopBegin = loop.loopBegin(); + FixedNode next = loopBegin.next(); + if (next instanceof IfNode) { + IfNode ifNode = (IfNode) next; + boolean negated = false; + if (!loopBegin.isLoopExit(ifNode.falseSuccessor())) { + if (!loopBegin.isLoopExit(ifNode.trueSuccessor())) { + continue; + } + negated = true; + } + BooleanNode ifTest = ifNode.compare(); + if (!(ifTest instanceof IntegerLessThanNode)) { + if (ifTest instanceof IntegerBelowThanNode) { + Debug.log("Ignored potential Counted loop at %s with |<|", loopBegin); + } + continue; + } + IntegerLessThanNode lessThan = (IntegerLessThanNode) ifTest; + Condition condition = null; + InductionVariable iv = null; + ValueNode limit = null; + if (loop.isOutsideLoop(lessThan.x())) { + iv = ivs.get(lessThan.y()); + if (iv != null) { + condition = lessThan.condition().mirror(); + limit = lessThan.x(); + } + } else if (loop.isOutsideLoop(lessThan.y())) { + iv = ivs.get(lessThan.x()); + if (iv != null) { + condition = lessThan.condition(); + limit = lessThan.y(); + } + } + if (condition == null) { + continue; + } + if (negated) { + condition = condition.negate(); + } + boolean oneOff = false; + switch (condition) { + case LE: + oneOff = true; // fall through + case LT: + if (iv.direction() != Direction.Up) { + continue; + } + break; + case GE: + oneOff = true; // fall through + case GT: + if (iv.direction() != Direction.Down) { + continue; + } + break; + default: throw GraalInternalError.shouldNotReachHere(); + } + // TODO (gd) + Debug.log("absorb %b %s", oneOff, limit); + } + } + } } diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java Sat Jun 16 02:19:38 2012 +0200 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java Sat Jun 16 02:20:02 2012 +0200 @@ -226,6 +226,14 @@ public PrintStream output() { return output; } + + @Override + public void addToContext(Object o) { + } + + @Override + public void removeFromContext(Object o) { + } }; } diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugConfig.java --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugConfig.java Sat Jun 16 02:19:38 2012 +0200 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/DebugConfig.java Sat Jun 16 02:20:02 2012 +0200 @@ -28,21 +28,39 @@ public interface DebugConfig { /** + * Determines if logging is enabled in the {@linkplain Debug#currentScope() current debug scope}. + * * @see Debug#log(String, Object...) */ boolean isLogEnabled(); /** + * Determines if metering is enabled in the {@linkplain Debug#currentScope() current debug scope}. + * * @see Debug#metric(String) */ boolean isMeterEnabled(); /** + * Determines if dumping is enabled in the {@linkplain Debug#currentScope() current debug scope}. + * * @see Debug#dump(Object, String, Object...) */ boolean isDumpEnabled(); /** + * Adds an object the context used by this configuration to do filtering. + */ + void addToContext(Object o); + + /** + * Removes an object the context used by this configuration to do filtering. + * + * This should only removes extra context added by {@link #addToContext(Object)}. + */ + void removeFromContext(Object o); + + /** * @see Debug#timer(String) */ boolean isTimeEnabled(); diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java Sat Jun 16 02:19:38 2012 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/Graph.java Sat Jun 16 02:20:02 2012 +0200 @@ -295,7 +295,7 @@ */ public NodeIterable getNewNodes(int mark) { final int index = mark; - return new NodeIterable() { + return new AbstractNodeIterable() { @Override public Iterator iterator() { return new NodeIterator(index); @@ -308,7 +308,7 @@ * @return an {@link Iterable} providing all the live nodes. */ public NodeIterable getNodes() { - return new NodeIterable() { + return new AbstractNodeIterable() { @Override public Iterator iterator() { return new NodeIterator(); @@ -385,7 +385,7 @@ */ public NodeIterable getNodes(final Class type) { final Node start = getStartNode(type); - return new NodeIterable() { + return new AbstractNodeIterable() { @Override public Iterator iterator() { return new TypedNodeIterator<>(start); diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeBitMap.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeBitMap.java Sat Jun 16 02:19:38 2012 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeBitMap.java Sat Jun 16 02:20:02 2012 +0200 @@ -28,7 +28,7 @@ -public final class NodeBitMap extends NodeIterable{ +public final class NodeBitMap extends AbstractNodeIterable{ private final boolean autoGrow; private final BitSet bitMap; private final Graph graph; diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeInputsIterable.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeInputsIterable.java Sat Jun 16 02:19:38 2012 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeInputsIterable.java Sat Jun 16 02:20:02 2012 +0200 @@ -25,7 +25,7 @@ import com.oracle.graal.graph.NodeClass.NodeClassIterator; import com.oracle.graal.graph.iterators.*; -public abstract class NodeInputsIterable extends NodeIterable { +public abstract class NodeInputsIterable extends AbstractNodeIterable { @Override public abstract NodeClassIterator iterator(); } diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java Sat Jun 16 02:19:38 2012 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeList.java Sat Jun 16 02:20:02 2012 +0200 @@ -25,13 +25,12 @@ import com.oracle.graal.graph.iterators.*; -public abstract class NodeList extends NodeIterable implements List { +public abstract class NodeList extends AbstractList implements NodeIterable { protected static final Node[] EMPTY_NODE_ARRAY = new Node[0]; protected Node[] nodes; private int size; - private int modCount; protected final int initialSize; protected NodeList() { @@ -327,46 +326,6 @@ } @Override - public boolean addAll(int index, Collection< ? extends T> c) { - throw new UnsupportedOperationException("not implemented"); - } - - @Override - public boolean removeAll(Collection< ? > c) { - throw new UnsupportedOperationException("not implemented"); - } - - @Override - public boolean retainAll(Collection< ? > c) { - throw new UnsupportedOperationException("not implemented"); - } - - @Override - public void add(int index, T element) { - throw new UnsupportedOperationException("not implemented"); - } - - @Override - public int lastIndexOf(Object o) { - throw new UnsupportedOperationException("not implemented"); - } - - @Override - public ListIterator listIterator() { - throw new UnsupportedOperationException("not implemented"); - } - - @Override - public ListIterator listIterator(int index) { - throw new UnsupportedOperationException("not implemented"); - } - - @Override - public List subList(int fromIndex, int toIndex) { - throw new UnsupportedOperationException("not implemented"); - } - - @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append('['); @@ -379,4 +338,41 @@ sb.append(']'); return sb.toString(); } + + @Override + public NodeIterable until(final T u) { + return new FilteredNodeIterable<>(this).until(u); + } + @Override + public NodeIterable until(final Class clazz) { + return new FilteredNodeIterable<>(this).until(clazz); + } + @Override + @SuppressWarnings("unchecked") + public NodeIterable filter(Class clazz) { + return (NodeIterable) new FilteredNodeIterable<>(this).and(NodePredicates.isA(clazz)); + } + @Override + public NodeIterable filterInterface(Class iface) { + return new FilteredNodeIterable<>(this).and(NodePredicates.isAInterface(iface)); + } + @Override + public FilteredNodeIterable filter(NodePredicate predicate) { + return new FilteredNodeIterable<>(this).and(predicate); + } + @Override + public FilteredNodeIterable nonNull() { + return new FilteredNodeIterable<>(this).and(NodePredicates.isNotNull()); + } + @Override + public NodeIterable distinct() { + return new FilteredNodeIterable<>(this).distinct(); + } + @Override + public T first() { + if (size() > 0) { + return get(0); + } + return null; + } } diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeSuccessorsIterable.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeSuccessorsIterable.java Sat Jun 16 02:19:38 2012 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeSuccessorsIterable.java Sat Jun 16 02:20:02 2012 +0200 @@ -25,7 +25,7 @@ import com.oracle.graal.graph.NodeClass.NodeClassIterator; import com.oracle.graal.graph.iterators.*; -public abstract class NodeSuccessorsIterable extends NodeIterable { +public abstract class NodeSuccessorsIterable extends AbstractNodeIterable { @Override public abstract NodeClassIterator iterator(); } diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeUsagesList.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeUsagesList.java Sat Jun 16 02:19:38 2012 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/NodeUsagesList.java Sat Jun 16 02:20:02 2012 +0200 @@ -26,7 +26,7 @@ import com.oracle.graal.graph.iterators.*; -public final class NodeUsagesList extends NodeIterable { +public final class NodeUsagesList extends AbstractNodeIterable { protected static final Node[] EMPTY_NODE_ARRAY = new Node[0]; diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/AbstractNodeIterable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/AbstractNodeIterable.java Sat Jun 16 02:20:02 2012 +0200 @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.graph.iterators; + +import java.util.*; + +import com.oracle.graal.graph.*; + +public abstract class AbstractNodeIterable implements NodeIterable { + @Override + public NodeIterable until(final T u) { + return new FilteredNodeIterable<>(this).until(u); + } + @Override + public NodeIterable until(final Class clazz) { + return new FilteredNodeIterable<>(this).until(clazz); + } + @Override + @SuppressWarnings("unchecked") + public NodeIterable filter(Class clazz) { + return (NodeIterable) new FilteredNodeIterable<>(this).and(NodePredicates.isA(clazz)); + } + @Override + public NodeIterable filterInterface(Class iface) { + return new FilteredNodeIterable<>(this).and(NodePredicates.isAInterface(iface)); + } + @Override + public FilteredNodeIterable filter(NodePredicate predicate) { + return new FilteredNodeIterable<>(this).and(predicate); + } + @Override + public FilteredNodeIterable nonNull() { + return new FilteredNodeIterable<>(this).and(NodePredicates.isNotNull()); + } + @Override + public NodeIterable distinct() { + return new FilteredNodeIterable<>(this).distinct(); + } + @Override + public List snapshot() { + ArrayList list = new ArrayList<>(); + for (T n : this) { + list.add(n); + } + return list; + } + @Override + public T first() { + Iterator iterator = iterator(); + if (iterator.hasNext()) { + return iterator.next(); + } + return null; + } + @Override + public int count() { + int count = 0; + Iterator iterator = iterator(); + while (iterator.hasNext()) { + iterator.next(); + count++; + } + return count; + } + @Override + public boolean isEmpty() { + return !iterator().hasNext(); + } + @Override + public boolean isNotEmpty() { + return iterator().hasNext(); + } + @Override + public boolean contains(T node) { + return this.filter(NodePredicates.equals(node)).isNotEmpty(); + } +} diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/FilteredNodeIterable.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/FilteredNodeIterable.java Sat Jun 16 02:19:38 2012 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/FilteredNodeIterable.java Sat Jun 16 02:20:02 2012 +0200 @@ -26,7 +26,7 @@ import com.oracle.graal.graph.*; -public class FilteredNodeIterable extends NodeIterable { +public class FilteredNodeIterable extends AbstractNodeIterable { private final NodeIterable nodeIterable; private NodePredicate predicate = NodePredicates.alwaysTrue(); private NodePredicate until = NodePredicates.isNull(); diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/NodeIterable.java --- a/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/NodeIterable.java Sat Jun 16 02:19:38 2012 +0200 +++ b/graal/com.oracle.graal.graph/src/com/oracle/graal/graph/iterators/NodeIterable.java Sat Jun 16 02:20:02 2012 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,59 +26,32 @@ import com.oracle.graal.graph.*; -public abstract class NodeIterable implements Iterable { - public NodeIterable until(final T u) { - return new FilteredNodeIterable<>(this).until(u); - } - public NodeIterable until(final Class clazz) { - return new FilteredNodeIterable<>(this).until(clazz); - } - @SuppressWarnings("unchecked") - public NodeIterable filter(Class clazz) { - return (NodeIterable) new FilteredNodeIterable<>(this).and(NodePredicates.isA(clazz)); - } - public NodeIterable filterInterface(Class iface) { - return new FilteredNodeIterable<>(this).and(NodePredicates.isAInterface(iface)); - } - public FilteredNodeIterable filter(NodePredicate predicate) { - return new FilteredNodeIterable<>(this).and(predicate); - } - public FilteredNodeIterable nonNull() { - return new FilteredNodeIterable<>(this).and(NodePredicates.isNotNull()); - } - public NodeIterable distinct() { - return new FilteredNodeIterable<>(this).distinct(); - } - public List snapshot() { - ArrayList list = new ArrayList<>(); - for (T n : this) { - list.add(n); - } - return list; - } - public T first() { - Iterator iterator = iterator(); - if (iterator.hasNext()) { - return iterator.next(); - } - return null; - } - public int count() { - int count = 0; - Iterator iterator = iterator(); - while (iterator.hasNext()) { - iterator.next(); - count++; - } - return count; - } - public boolean isEmpty() { - return !iterator().hasNext(); - } - public boolean isNotEmpty() { - return iterator().hasNext(); - } - public boolean contains(T node) { - return this.filter(NodePredicates.equals(node)).isNotEmpty(); - } +public interface NodeIterable extends Iterable { + + NodeIterable until(T u); + + NodeIterable until(Class< ? extends T> clazz); + + NodeIterable filter(Class clazz); + + NodeIterable filterInterface(Class< ? > iface); + + FilteredNodeIterable filter(NodePredicate predicate); + + FilteredNodeIterable nonNull(); + + NodeIterable distinct(); + + List snapshot(); + + T first(); + + int count(); + + boolean isEmpty(); + + boolean isNotEmpty(); + + boolean contains(T node); + } diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugConfig.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugConfig.java Sat Jun 16 02:19:38 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotDebugConfig.java Sat Jun 16 02:20:02 2012 +0200 @@ -43,6 +43,7 @@ private final MethodFilter[] methodFilter; private final List dumpHandlers = new ArrayList<>(); private final PrintStream output; + private final Set extraFilters = new HashSet<>(); public HotSpotDebugConfig(String logFilter, String meterFilter, String timerFilter, String dumpFilter, String methodFilter, PrintStream output) { this.logFilter = DebugFilter.parse(logFilter); @@ -102,14 +103,18 @@ } private boolean checkMethodFilter() { - if (methodFilter == null) { + if (methodFilter == null && extraFilters.isEmpty()) { return true; } else { for (Object o : Debug.context()) { - if (o instanceof JavaMethod) { - for (MethodFilter filter : methodFilter) { - if (filter.matches((JavaMethod) o)) { - return true; + if (extraFilters.contains(o)) { + return true; + } else if (methodFilter != null) { + if (o instanceof JavaMethod) { + for (MethodFilter filter : methodFilter) { + if (filter.matches((JavaMethod) o)) { + return true; + } } } } @@ -176,4 +181,14 @@ public Collection dumpHandlers() { return dumpHandlers; } + + @Override + public void addToContext(Object o) { + extraFilters.add(o); + } + + @Override + public void removeFromContext(Object o) { + extraFilters.remove(o); + } } diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Sat Jun 16 02:19:38 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Sat Jun 16 02:20:02 2012 +0200 @@ -37,7 +37,7 @@ // os information, register layout, code generation, ... public boolean windowsOs; public int codeEntryAlignment; - public boolean verifyPointers; + public boolean verifyOops; public boolean useFastLocking; public boolean useFastNewObjectArray; public boolean useFastNewTypeArray; @@ -103,7 +103,7 @@ public long monitorExitStub; public long fastMonitorEnterStub; public long fastMonitorExitStub; - public long verifyPointerStub; + public long verifyOopStub; public void check() { assert vmPageSize >= 16; diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaType.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaType.java Sat Jun 16 02:19:38 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaType.java Sat Jun 16 02:20:02 2012 +0200 @@ -201,6 +201,11 @@ return constantPool; } + /** + * Gets the instance size of this type. If an instance of this type cannot + * be fast path allocated, then the returned value is negative (its absolute + * value gives the size). + */ public int instanceSize() { return instanceSize; } diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotXirGenerator.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotXirGenerator.java Sat Jun 16 02:19:38 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotXirGenerator.java Sat Jun 16 02:20:02 2012 +0200 @@ -783,6 +783,7 @@ public XirSnippet genNewInstance(XirSite site, JavaType type) { HotSpotResolvedJavaType resolvedType = (HotSpotResolvedJavaType) type; int instanceSize = resolvedType.instanceSize(); + assert instanceSize >= 0; return new XirSnippet(newInstanceTemplates.get(site, instanceSize), XirArgument.forObject(resolvedType.klassOop())); } diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VerifyOopStubCall.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VerifyOopStubCall.java Sat Jun 16 02:20:02 2012 +0200 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.nodes; + +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.target.*; +import com.oracle.graal.hotspot.target.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.type.*; + +/** + * Node implementing a call to HotSpot's object pointer verification stub. + * + * @see AMD64VerifyOopStubCallOp + */ +public class VerifyOopStubCall extends FixedWithNextNode implements LIRGenLowerable { + + @Input private final ValueNode object; + + public VerifyOopStubCall(ValueNode object) { + super(StampFactory.objectNonNull()); + this.object = object; + } + + @Override + public void generate(LIRGenerator gen) { + LIRDebugInfo info = gen.state(); + AMD64VerifyOopStubCallOp op = new AMD64VerifyOopStubCallOp(gen.operand(object), info); + gen.append(op); + } + + @SuppressWarnings("unused") + @NodeIntrinsic + public static Object call(Object object) { + throw new UnsupportedOperationException(); + } +} diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewInstanceSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewInstanceSnippets.java Sat Jun 16 02:19:38 2012 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewInstanceSnippets.java Sat Jun 16 02:20:02 2012 +0200 @@ -70,9 +70,9 @@ if (klassState != klassStateFullyInitialized()) { if (logType != null) { Log.print(logType); - Log.println(" - uninitialized"); + Log.println(" - uninit alloc"); } - return NewInstanceStubCall.call(hub); + return verifyOop(NewInstanceStubCall.call(hub)); } } @@ -84,17 +84,28 @@ if (newTop.cmp(BE, end)) { Object instance = cast(top, Object.class); store(thread, 0, threadTlabTopOffset(), newTop); - return formatInstance(hub, size, instance, logType); - } else { + formatInstance(hub, size, instance); if (logType != null) { Log.print(logType); - Log.println(" - stub allocate"); + Log.print(" - fast alloc at "); + Log.printlnAddress(instance); } - return NewInstanceStubCall.call(hub); + return verifyOop(instance); } - } else { - return NewInstanceStubCall.call(hub); + } + + if (logType != null) { + Log.print(logType); + Log.println(" - slow alloc"); } + return verifyOop(NewInstanceStubCall.call(hub)); + } + + private static Object verifyOop(Object object) { + if (verifyOops()) { + VerifyOopStubCall.call(object); + } + return object; } private static Word asWord(Object object) { @@ -108,7 +119,7 @@ /** * Formats the header of a created instance and zeroes out its body. */ - private static Object formatInstance(Object hub, int size, Object instance, String logType) { + private static void formatInstance(Object hub, int size, Object instance) { Word headerPrototype = cast(load(hub, 0, instanceHeaderPrototypeOffset(), wordKind()), Word.class); store(instance, 0, 0, headerPrototype); store(instance, 0, hubOffset(), hub); @@ -116,13 +127,11 @@ for (int offset = 2 * wordSize(); offset < size; offset += wordSize()) { store(instance, 0, offset, 0); } - if (logType != null) { - Log.print("allocated instance of "); - Log.print(logType); - Log.print(" at "); - Log.printlnAddress(instance); - } - return instance; + } + + @Fold + private static boolean verifyOops() { + return HotSpotGraalRuntime.getInstance().getConfig().verifyOops; } @Fold @@ -192,11 +201,14 @@ HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) newInstanceNode.instanceClass(); HotSpotKlassOop hub = type.klassOop(); int instanceSize = type.instanceSize(); + assert (instanceSize % wordSize()) == 0; + assert instanceSize >= 0; Key key = new Key(newInstance).add("size", instanceSize).add("checkInit", !type.isInitialized()).add("useTLAB", useTLAB).add("logType", LOG_ALLOCATION ? type.name() : null); Arguments arguments = arguments("hub", hub); SnippetTemplate template = cache.get(key); Debug.log("Lowering newInstance in %s: node=%s, template=%s, arguments=%s", graph, newInstanceNode, template, arguments); //System.out.printf("Lowering newInstance in %s: node=%s, template=%s, arguments=%s%n", graph, newInstanceNode, template, arguments); + //DebugScope.getConfig().addToContext(graph.method()); template.instantiate(runtime, newInstanceNode, newInstanceNode, arguments); new DeadCodeEliminationPhase().apply(graph); } diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/AMD64VerifyOopStubCallOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/target/AMD64VerifyOopStubCallOp.java Sat Jun 16 02:20:02 2012 +0200 @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.target; + +import static com.oracle.graal.api.code.ValueUtil.*; + +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.amd64.*; +import com.oracle.graal.lir.asm.*; +import com.oracle.max.asm.target.amd64.*; + +/** + * A call to HotSpot's object pointer verification stub. + */ +public class AMD64VerifyOopStubCallOp extends AMD64LIRInstruction { + public AMD64VerifyOopStubCallOp(Value object, LIRDebugInfo info) { + super("VERIFY_OOP", LIRInstruction.NO_OPERANDS, info, new Value[] {object}, NO_OPERANDS, NO_OPERANDS); + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + Register object = asRegister(input(0)); + // r13: (in) object + if (object != AMD64.r13) { + masm.push(AMD64.r13); + masm.movl(AMD64.r13, object); + } + AMD64Call.directCall(tasm, masm, HotSpotGraalRuntime.getInstance().getConfig().verifyOopStub, info); + if (object != AMD64.r13) { + masm.pop(AMD64.r13); + } + } + + @Override + protected EnumSet flagsFor(OperandMode mode, int index) { + if (mode == OperandMode.Input) { + return EnumSet.of(OperandFlag.Register); + } + throw GraalInternalError.shouldNotReachHere(); + } +} diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/ArrayCopy02.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/ArrayCopy02.java Sat Jun 16 02:20:02 2012 +0200 @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.jtt.optimize; + +import org.junit.*; + +/* + * Tests calls to the array copy method. + */ +public class ArrayCopy02 { + + public static int[] src = new int[]{0, 1, 2, 3, 4, 5}; + public static int[] dest0 = new int[]{5, 4, 3, 2, 1, 0}; + public static int[] dest = new int[]{5, 4, 3, 2, 1, 0}; + + @Before + public void setUp() { + System.currentTimeMillis(); + for (int i = 0; i < dest.length; i++) { + dest[i] = dest0[i]; + } + } + + public static int[] test(int srcPos, int destPos, int length) { + System.arraycopy(src, srcPos, dest, destPos, length); + return dest; + } + + @Test + public void run0() throws Throwable { + Assert.assertArrayEquals(new int[] {5, 4, 3, 2, 1, 0}, test(0, 0, 0)); + } + + @Test(expected = java.lang.IndexOutOfBoundsException.class) + public void run1() throws Throwable { + test(0, 0, -1); + } + + @Test(expected = java.lang.IndexOutOfBoundsException.class) + public void run2() throws Throwable { + test(-1, 0, 0); + } + + @Test(expected = java.lang.IndexOutOfBoundsException.class) + public void run3() throws Throwable { + test(0, -1, 0); + } + + @Test + public void run4() throws Throwable { + Assert.assertArrayEquals(new int[] {0, 1, 3, 2, 1, 0}, test(0, 0, 2)); + } + + @Test(expected = java.lang.IndexOutOfBoundsException.class) + public void run5() throws Throwable { + test(0, 1, 6); + } + + @Test(expected = java.lang.IndexOutOfBoundsException.class) + public void run6() throws Throwable { + test(1, 0, 6); + } + + @Test(expected = java.lang.IndexOutOfBoundsException.class) + public void run7() throws Throwable { + test(1, 1, -1); + } + + @Test + public void run8() throws Throwable { + Assert.assertArrayEquals(new int[] {5, 0, 1, 2, 1, 0}, test(0, 1, 2)); + } + + @Test + public void run9() throws Throwable { + Assert.assertArrayEquals(new int[] {1, 2, 3, 2, 1, 0}, test(1, 0, 2)); + } + + @Test + public void run10() throws Throwable { + Assert.assertArrayEquals(new int[] {5, 1, 2, 2, 1, 0}, test(1, 1, 2)); + } + + @Test + public void run11() throws Throwable { + Assert.assertArrayEquals(new int[] {0, 1, 2, 3, 4, 5}, test(0, 0, 6)); + } + + @Test + public void run12() throws Throwable { + Assert.assertArrayEquals(new int[] {5, 0, 1, 2, 3, 4}, test(0, 1, 5)); + } + + @Test + public void run13() throws Throwable { + Assert.assertArrayEquals(new int[] {1, 2, 3, 4, 5, 0}, test(1, 0, 5)); + } + + @Test + public void run14() throws Throwable { + Assert.assertArrayEquals(new int[] {5, 1, 2, 3, 4, 5}, test(1, 1, 5)); + } + +} diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/ArrayCopy03.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/ArrayCopy03.java Sat Jun 16 02:20:02 2012 +0200 @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.jtt.optimize; + +import org.junit.*; + +/* + * Tests calls to the array copy method. + */ +public class ArrayCopy03 { + + public static byte[] src = new byte[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + public static byte[] dest0 = new byte[]{10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; + public static byte[] dest = new byte[]{10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}; + + @Before + public void setUp() { + System.currentTimeMillis(); + for (int i = 0; i < dest.length; i++) { + dest[i] = dest0[i]; + } + } + + public static byte[] test(int srcPos, int destPos, int length) { + System.arraycopy(src, srcPos, dest, destPos, length); + return dest; + } + + @Test + public void run0() throws Throwable { + Assert.assertArrayEquals(new byte[] {10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0}, test(0, 0, 0)); + } + + @Test(expected = java.lang.IndexOutOfBoundsException.class) + public void run1() throws Throwable { + test(0, 0, -1); + } + + @Test(expected = java.lang.IndexOutOfBoundsException.class) + public void run2() throws Throwable { + test(-1, 0, 0); + } + + @Test(expected = java.lang.IndexOutOfBoundsException.class) + public void run3() throws Throwable { + test(0, -1, 0); + } + + @Test + public void run4() throws Throwable { + Assert.assertArrayEquals(new byte[] {0, 1, 8, 7, 6, 5, 4, 3, 2, 1, 0}, test(0, 0, 2)); + } + + @Test(expected = java.lang.IndexOutOfBoundsException.class) + public void run5() throws Throwable { + test(0, 1, 11); + } + + @Test(expected = java.lang.IndexOutOfBoundsException.class) + public void run6() throws Throwable { + test(1, 0, 11); + } + + @Test(expected = java.lang.IndexOutOfBoundsException.class) + public void run7() throws Throwable { + test(1, 1, -1); + } + + @Test + public void run8() throws Throwable { + Assert.assertArrayEquals(new byte[] {10, 0, 1, 7, 6, 5, 4, 3, 2, 1, 0}, test(0, 1, 2)); + } + + @Test + public void run9() throws Throwable { + Assert.assertArrayEquals(new byte[] {1, 2, 8, 7, 6, 5, 4, 3, 2, 1, 0}, test(1, 0, 2)); + } + + @Test + public void run10() throws Throwable { + Assert.assertArrayEquals(new byte[] {10, 1, 2, 7, 6, 5, 4, 3, 2, 1, 0}, test(1, 1, 2)); + } + + @Test + public void run11() throws Throwable { + Assert.assertArrayEquals(new byte[] {0, 1, 2, 3, 4, 5, 4, 3, 2, 1, 0}, test(0, 0, 6)); + } + + @Test + public void run12() throws Throwable { + Assert.assertArrayEquals(new byte[] {10, 0, 1, 2, 3, 4, 4, 3, 2, 1, 0}, test(0, 1, 5)); + } + + @Test + public void run13() throws Throwable { + Assert.assertArrayEquals(new byte[] {1, 2, 3, 4, 5, 5, 4, 3, 2, 1, 0}, test(1, 0, 5)); + } + + @Test + public void run14() throws Throwable { + Assert.assertArrayEquals(new byte[] {10, 1, 2, 3, 4, 5, 4, 3, 2, 1, 0}, test(1, 1, 5)); + } + + @Test + public void run15() throws Throwable { + Assert.assertArrayEquals(new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, test(0, 0, 11)); + } +} diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/ReassociateConstants.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/optimize/ReassociateConstants.java Sat Jun 16 02:20:02 2012 +0200 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.jtt.optimize; + +import org.junit.*; + + +public class ReassociateConstants { + public static int rnd = (int) (Math.random() * 100); + @Test + public void run0() throws Throwable { + Assert.assertEquals(rnd + 3, 1 + (rnd + 2)); + Assert.assertEquals(rnd + 3, (rnd + 2) + 1); + Assert.assertEquals(rnd + 3, 1 + (2 + rnd)); + Assert.assertEquals(rnd + 3, (2 + rnd) + 1); + + Assert.assertEquals(-1 - rnd, 1 - (rnd + 2)); + Assert.assertEquals(rnd + 1, (rnd + 2) - 1); + Assert.assertEquals(-1 - rnd, 1 - (2 + rnd)); + Assert.assertEquals(rnd + 1, (2 + rnd) - 1); + + Assert.assertEquals(rnd - 1, 1 + (rnd - 2)); + Assert.assertEquals(rnd - 1, (rnd - 2) + 1); + Assert.assertEquals(-rnd + 3, 1 + (2 - rnd)); + Assert.assertEquals(-rnd + 3, (2 - rnd) + 1); + + Assert.assertEquals(-rnd + 3, 1 - (rnd - 2)); + Assert.assertEquals(rnd - 3, (rnd - 2) - 1); + Assert.assertEquals(rnd + -1, 1 - (2 - rnd)); + Assert.assertEquals(-rnd + 1, (2 - rnd) - 1); + } +} diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java Sat Jun 16 02:19:38 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/BeginNode.java Sat Jun 16 02:20:02 2012 +0200 @@ -143,7 +143,7 @@ } public NodeIterable getBlockNodes() { - return new NodeIterable() { + return new AbstractNodeIterable() { @Override public Iterator iterator() { return new BlockNodeIterator(BeginNode.this); diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java Sat Jun 16 02:19:38 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java Sat Jun 16 02:20:02 2012 +0200 @@ -155,4 +155,8 @@ public void simplify(SimplifierTool tool) { // nothing yet } + + public boolean isLoopExit(BeginNode begin) { + return begin instanceof LoopExitNode && ((LoopExitNode) begin).loopBegin() == this; + } } diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java Sat Jun 16 02:19:38 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/PhiNode.java Sat Jun 16 02:20:02 2012 +0200 @@ -191,6 +191,19 @@ return differentValue; } + public ValueNode singleBackValue() { + assert merge() instanceof LoopBeginNode; + ValueNode differentValue = null; + for (ValueNode n : values().subList(merge().forwardEndCount(), values().size())) { + if (differentValue == null) { + differentValue = n; + } else if (differentValue != n) { + return null; + } + } + return differentValue; + } + @Override public ValueNode canonical(CanonicalizerTool tool) { ValueNode singleValue = singleValue(); diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java Sat Jun 16 02:19:38 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/ValueNode.java Sat Jun 16 02:20:02 2012 +0200 @@ -26,6 +26,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; +import com.oracle.graal.graph.iterators.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.nodes.type.GenericStamp.*; import com.oracle.graal.nodes.util.*; @@ -89,6 +90,17 @@ return this instanceof ConstantNode; } + private static final NodePredicate IS_CONSTANT = new NodePredicate() { + @Override + public boolean apply(Node n) { + return n instanceof ValueNode && ((ValueNode) n).isConstant(); + } + }; + + public static NodePredicate isConstantPredicate() { + return IS_CONSTANT; + } + /** * Checks whether this value represents the null constant. * @return {@code true} if this value represents the null constant diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java Sat Jun 16 02:19:38 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java Sat Jun 16 02:20:02 2012 +0200 @@ -68,6 +68,7 @@ return ConstantNode.forLong(0, graph()); } } + return BinaryNode.reassociate(this, ValueNode.isConstantPredicate()); } return this; } diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryNode.java Sat Jun 16 02:19:38 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryNode.java Sat Jun 16 02:20:02 2012 +0200 @@ -23,6 +23,8 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.iterators.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.type.*; @@ -53,4 +55,135 @@ this.x = x; this.y = y; } + + public enum ReassociateMatch { + x, + y; + + public ValueNode getValue(BinaryNode binary) { + switch(this) { + case x: + return binary.x(); + case y: + return binary.y(); + default: throw GraalInternalError.shouldNotReachHere(); + } + } + + public ValueNode getOtherValue(BinaryNode binary) { + switch(this) { + case x: + return binary.y(); + case y: + return binary.x(); + default: throw GraalInternalError.shouldNotReachHere(); + } + } + } + + public static boolean canTryReassociate(BinaryNode node) { + return node instanceof IntegerAddNode || node instanceof IntegerSubNode || node instanceof IntegerMulNode + || node instanceof AndNode || node instanceof OrNode || node instanceof XorNode; + } + + public static ReassociateMatch findReassociate(BinaryNode binary, NodePredicate criterion) { + boolean resultX = criterion.apply(binary.x()); + boolean resultY = criterion.apply(binary.y()); + if (resultX && !resultY) { + return ReassociateMatch.x; + } + if (!resultX && resultY) { + return ReassociateMatch.y; + } + return null; + } + + /* In reassociate, complexity comes from the handling of IntegerSub (non commutative) which can be mixed with IntegerAdd. + * if first tries to find m1, m2 which match the criterion : + * (a o m2) o m1 + * (m2 o a) o m1 + * m1 o (a o m2) + * m1 o (m2 o a) + * It then produces 4 boolean for the -/+ case + * invertA : should the final expression be like *-a (rather than a+*) + * aSub : should the final expression be like a-* (rather than a+*) + * invertM1 : should the final expression contain -m1 + * invertM2 : should the final expression contain -m2 + */ + /** + * Tries to re-associate values which satisfy the criterion. + * For example with a constantness criterion : (a + 2) + 1 => a + (1 + 2)
+ * This method accepts only reassociable operations (see {@linkplain #canTryReassociate(BinaryNode)}) such as +, -, *, &, | and ^ + */ + public static BinaryNode reassociate(BinaryNode node, NodePredicate criterion) { + assert canTryReassociate(node); + ReassociateMatch match1 = findReassociate(node, criterion); + if (match1 == null) { + return node; + } + ValueNode otherValue = match1.getOtherValue(node); + boolean addSub = false; + boolean subAdd = false; + if (otherValue.getClass() != node.getClass()) { + if (node instanceof IntegerAddNode && otherValue instanceof IntegerSubNode) { + addSub = true; + } else if (node instanceof IntegerSubNode && otherValue instanceof IntegerAddNode) { + subAdd = true; + } else { + return node; + } + } + BinaryNode other = (BinaryNode) otherValue; + ReassociateMatch match2 = findReassociate(other, criterion); + if (match2 == null) { + return node; + } + boolean invertA = false; + boolean aSub = false; + boolean invertM1 = false; + boolean invertM2 = false; + if (addSub) { + invertM2 = match2 == ReassociateMatch.y; + invertA = !invertM2; + } else if (subAdd) { + invertA = invertM2 = match1 == ReassociateMatch.x; + invertM1 = !invertM2; + } else if (node instanceof IntegerSubNode && other instanceof IntegerSubNode) { + invertA = match1 == ReassociateMatch.x ^ match2 == ReassociateMatch.x; + aSub = match1 == ReassociateMatch.y && match2 == ReassociateMatch.y; + invertM1 = match1 == ReassociateMatch.y && match2 == ReassociateMatch.x; + invertM2 = match1 == ReassociateMatch.x && match2 == ReassociateMatch.x; + } + assert !(invertM1 && invertM2) && !(invertA && aSub); + ValueNode m1 = match1.getValue(node); + ValueNode m2 = match2.getValue(other); + ValueNode a = match2.getOtherValue(other); + if (node instanceof IntegerAddNode || node instanceof IntegerSubNode) { + BinaryNode associated; + if (invertM1) { + associated = IntegerArithmeticNode.sub(m2, m1); + } else if (invertM2) { + associated = IntegerArithmeticNode.sub(m1, m2); + } else { + associated = IntegerArithmeticNode.add(m1, m2); + } + if (invertA) { + return IntegerArithmeticNode.sub(associated, a); + } + if (aSub) { + return IntegerArithmeticNode.sub(a, associated); + } + return IntegerArithmeticNode.add(a, associated); + } else if (node instanceof IntegerMulNode) { + return IntegerArithmeticNode.mul(a, IntegerAddNode.mul(m1, m2)); + } else if (node instanceof AndNode) { + return LogicNode.and(a, LogicNode.and(m1, m2)); + } else if (node instanceof OrNode) { + return LogicNode.or(a, LogicNode.or(m1, m2)); + } else if (node instanceof XorNode) { + return LogicNode.xor(a, LogicNode.xor(m1, m2)); + } else { + throw GraalInternalError.shouldNotReachHere(); + } + } } diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java Sat Jun 16 02:19:38 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java Sat Jun 16 02:20:02 2012 +0200 @@ -48,33 +48,27 @@ return ConstantNode.forLong(x().asConstant().asLong() + y().asConstant().asLong(), graph()); } } else if (y().isConstant()) { - if (kind() == Kind.Int) { - int c = y().asConstant().asInt(); - if (c == 0) { - return x(); - } - } else { - assert kind() == Kind.Long; - long c = y().asConstant().asLong(); - if (c == 0) { - return x(); - } + long c = y().asConstant().asLong(); + if (c == 0) { + return x(); } // canonicalize expressions like "(a + 1) + 2" - if (x() instanceof IntegerAddNode) { - IntegerAddNode other = (IntegerAddNode) x(); - if (other.y().isConstant()) { - ConstantNode sum; - if (kind() == Kind.Int) { - sum = ConstantNode.forInt(y().asConstant().asInt() + other.y().asConstant().asInt(), graph()); - } else { - assert kind() == Kind.Long; - sum = ConstantNode.forLong(y().asConstant().asLong() + other.y().asConstant().asLong(), graph()); - } - return graph().unique(new IntegerAddNode(kind(), other.x(), sum)); + BinaryNode reassociated = BinaryNode.reassociate(this, ValueNode.isConstantPredicate()); + if (reassociated != this) { + return reassociated; + } + if (c < 0) { + if (kind() == Kind.Int) { + return IntegerArithmeticNode.sub(x(), ConstantNode.forInt((int) -c, graph())); + } else { + assert kind() == Kind.Long; + return IntegerArithmeticNode.sub(x(), ConstantNode.forLong(-c, graph())); } } } + if (x() instanceof NegateNode) { + return IntegerArithmeticNode.sub(y(), ((NegateNode) x()).x()); + } return this; } diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerArithmeticNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerArithmeticNode.java Sat Jun 16 02:19:38 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerArithmeticNode.java Sat Jun 16 02:20:02 2012 +0200 @@ -59,4 +59,30 @@ throw ValueNodeUtil.shouldNotReachHere(); } } + + public static IntegerSubNode sub(ValueNode v1, ValueNode v2) { + assert v1.kind() == v2.kind() && v1.graph() == v2.graph(); + Graph graph = v1.graph(); + switch(v1.kind()) { + case Int: + return graph.unique(new IntegerSubNode(Kind.Int, v1, v2)); + case Long: + return graph.unique(new IntegerSubNode(Kind.Long, v1, v2)); + default: + throw ValueNodeUtil.shouldNotReachHere(); + } + } + + public static IntegerDivNode div(ValueNode v1, ValueNode v2) { + assert v1.kind() == v2.kind() && v1.graph() == v2.graph(); + Graph graph = v1.graph(); + switch(v1.kind()) { + case Int: + return graph.unique(new IntegerDivNode(Kind.Int, v1, v2)); + case Long: + return graph.unique(new IntegerDivNode(Kind.Long, v1, v2)); + default: + throw ValueNodeUtil.shouldNotReachHere(); + } + } } diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java Sat Jun 16 02:19:38 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java Sat Jun 16 02:20:02 2012 +0200 @@ -59,19 +59,7 @@ return graph().unique(new LeftShiftNode(kind(), x(), ConstantNode.forInt(CodeUtil.log2(c), graph()))); } // canonicalize expressions like "(a * 1) * 2" - if (x() instanceof IntegerMulNode) { - IntegerMulNode other = (IntegerMulNode) x(); - if (other.y().isConstant()) { - ConstantNode sum; - if (kind() == Kind.Int) { - sum = ConstantNode.forInt(y().asConstant().asInt() * other.y().asConstant().asInt(), graph()); - } else { - assert kind() == Kind.Long; - sum = ConstantNode.forLong(y().asConstant().asLong() * other.y().asConstant().asLong(), graph()); - } - return graph().unique(new IntegerMulNode(kind(), other.x(), sum)); - } - } + return BinaryNode.reassociate(this, ValueNode.isConstantPredicate()); } return this; } diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java Sat Jun 16 02:19:38 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java Sat Jun 16 02:20:02 2012 +0200 @@ -51,17 +51,24 @@ if (c == 0) { return x(); } - if (kind() == Kind.Int) { - return graph().unique(new IntegerAddNode(kind(), x(), ConstantNode.forInt((int) -c, graph()))); - } else { - assert kind() == Kind.Long; - return graph().unique(new IntegerAddNode(kind(), x(), ConstantNode.forLong(-c, graph()))); + BinaryNode reassociated = BinaryNode.reassociate(this, ValueNode.isConstantPredicate()); + if (reassociated != this) { + return reassociated; + } + if (c < 0) { + if (kind() == Kind.Int) { + return IntegerArithmeticNode.add(x(), ConstantNode.forInt((int) -c, graph())); + } else { + assert kind() == Kind.Long; + return IntegerArithmeticNode.add(x(), ConstantNode.forLong(-c, graph())); + } } } else if (x().isConstant()) { long c = x().asConstant().asLong(); if (c == 0) { return graph().unique(new NegateNode(y())); } + return BinaryNode.reassociate(this, ValueNode.isConstantPredicate()); } return this; } diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LogicNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LogicNode.java Sat Jun 16 02:19:38 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LogicNode.java Sat Jun 16 02:20:02 2012 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; /** @@ -38,4 +39,43 @@ public LogicNode(Kind kind, ValueNode x, ValueNode y) { super(kind, x, y); } + + public static LogicNode and(ValueNode v1, ValueNode v2) { + assert v1.kind() == v2.kind() && v1.graph() == v2.graph(); + Graph graph = v1.graph(); + switch(v1.kind()) { + case Int: + return graph.unique(new AndNode(Kind.Int, v1, v2)); + case Long: + return graph.unique(new AndNode(Kind.Long, v1, v2)); + default: + throw ValueNodeUtil.shouldNotReachHere(); + } + } + + public static LogicNode or(ValueNode v1, ValueNode v2) { + assert v1.kind() == v2.kind() && v1.graph() == v2.graph(); + Graph graph = v1.graph(); + switch(v1.kind()) { + case Int: + return graph.unique(new OrNode(Kind.Int, v1, v2)); + case Long: + return graph.unique(new OrNode(Kind.Long, v1, v2)); + default: + throw ValueNodeUtil.shouldNotReachHere(); + } + } + + public static LogicNode xor(ValueNode v1, ValueNode v2) { + assert v1.kind() == v2.kind() && v1.graph() == v2.graph(); + Graph graph = v1.graph(); + switch(v1.kind()) { + case Int: + return graph.unique(new XorNode(Kind.Int, v1, v2)); + case Long: + return graph.unique(new XorNode(Kind.Long, v1, v2)); + default: + throw ValueNodeUtil.shouldNotReachHere(); + } + } } diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java Sat Jun 16 02:19:38 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java Sat Jun 16 02:20:02 2012 +0200 @@ -38,12 +38,12 @@ } /** - * Creates new NegateOp instance. + * Creates new NegateNode instance. * * @param x the instruction producing the value that is input to this instruction */ public NegateNode(ValueNode x) { - super(StampFactory.forKind(x.kind())); + super(x.stamp() instanceof IntegerStamp ? StampFactory.negate((IntegerStamp) x.stamp()) : StampFactory.forKind(x.kind())); this.x = x; } diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java Sat Jun 16 02:19:38 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java Sat Jun 16 02:20:02 2012 +0200 @@ -68,6 +68,7 @@ return x(); } } + return BinaryNode.reassociate(this, ValueNode.isConstantPredicate()); } return this; } diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java Sat Jun 16 02:19:38 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java Sat Jun 16 02:20:02 2012 +0200 @@ -62,6 +62,7 @@ return x(); } } + return BinaryNode.reassociate(this, ValueNode.isConstantPredicate()); } return this; } diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java Sat Jun 16 02:19:38 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampFactory.java Sat Jun 16 02:20:02 2012 +0200 @@ -128,6 +128,14 @@ } } + public static Stamp negate(IntegerStamp stamp) { + Kind kind = stamp.kind(); + if (stamp.lowerBound() != kind.minValue()) { + return new IntegerStamp(kind, -stamp.upperBound(), -stamp.lowerBound()); + } + return forKind(kind); + } + public static Stamp object() { return objectStamp; } diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.nodes/src/com/oracle/graal/util/NodeIterators.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/util/NodeIterators.java Sat Jun 16 02:19:38 2012 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/util/NodeIterators.java Sat Jun 16 02:20:02 2012 +0200 @@ -30,7 +30,7 @@ public class NodeIterators { public static NodeIterable dominators(final FixedNode n) { - return new NodeIterable() { + return new AbstractNodeIterable() { @Override public Iterator iterator() { return new NodeIterator(){ diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/NewInstanceTest.java --- a/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/NewInstanceTest.java Sat Jun 16 02:19:38 2012 +0200 +++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/NewInstanceTest.java Sat Jun 16 02:20:02 2012 +0200 @@ -36,12 +36,20 @@ Assert.assertTrue(expected != null); Assert.assertTrue(actual != null); super.assertEquals(expected.getClass(), actual.getClass()); + if (expected.getClass() != Object.class) { + try { + expected.getClass().getDeclaredMethod("equals", Object.class); + super.assertEquals(expected, actual); + } catch (Exception e) { + } + } } @Test public void test1() { test("newObject"); test("newBigObject"); + test("newSomeObject"); test("newEmptyString"); test("newString", "value"); test("newHashMap", 31); @@ -55,6 +63,10 @@ return new BigObject(); } + public static SomeObject newSomeObject() { + return new SomeObject(); + } + public static String newEmptyString() { return new String(); } @@ -67,6 +79,30 @@ return new HashMap(initialCapacity); } + static class SomeObject { + String name = "o1"; + HashMap map = new HashMap<>(); + + + public SomeObject() { + map.put(name, this.getClass()); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof SomeObject) { + SomeObject so = (SomeObject) obj; + return so.name.equals(name) && so.map.equals(map); + } + return false; + } + + @Override + public int hashCode() { + return name.hashCode(); + } + } + static class BigObject { Object f01; Object f02; diff -r 4d0f01e9f31b -r bda2ebe1fc61 graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/ReassociateAndCanonicalTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.tests/src/com/oracle/graal/compiler/tests/ReassociateAndCanonicalTest.java Sat Jun 16 02:20:02 2012 +0200 @@ -0,0 +1,249 @@ +/* + * 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.graal.compiler.tests; + +import org.junit.*; + +import com.oracle.graal.compiler.phases.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; + +public class ReassociateAndCanonicalTest extends GraalCompilerTest { + public static int rnd = (int) (Math.random() * 100); + + @Test + public void test1() { + test("test1Snippet", "ref1Snippet"); + } + + public static int test1Snippet() { + return 1 + (rnd + 2); + } + + public static int ref1Snippet() { + return rnd + 3; + } + + @Test + public void test2() { + test("test2Snippet", "ref2Snippet"); + } + + public static int test2Snippet() { + return rnd + 3; + } + + public static int ref2Snippet() { + return (rnd + 2) + 1; + } + + @Test + public void test3() { + test("test3Snippet", "ref3Snippet"); + } + + public static int test3Snippet() { + return rnd + 3; + } + + public static int ref3Snippet() { + return 1 + (2 + rnd); + } + + @Test + public void test4() { + test("test4Snippet", "ref4Snippet"); + } + + public static int test4Snippet() { + return rnd + 3; + } + + public static int ref4Snippet() { + return (2 + rnd) + 1; + } + + @Test + public void test5() { + test("test5Snippet", "ref5Snippet"); + } + + public static int test5Snippet() { + return -1 - rnd; + } + + public static int ref5Snippet() { + return 1 - (rnd + 2); + } + + @Test + public void test6() { + test("test6Snippet", "ref6Snippet"); + } + + public static int test6Snippet() { + return rnd + 1; + } + + public static int ref6Snippet() { + return (rnd + 2) - 1; + } + + @Test + public void test7() { + test("test7Snippet", "ref7Snippet"); + } + + public static int test7Snippet() { + return -1 - rnd; + } + + public static int ref7Snippet() { + return 1 - (2 + rnd); + } + + @Test + public void test8() { + test("test8Snippet", "ref8Snippet"); + } + + public static int test8Snippet() { + return rnd + 1; + } + + public static int ref8Snippet() { + return (2 + rnd) - 1; + } + + @Test + public void test9() { + test("test9Snippet", "ref9Snippet"); + } + + public static int test9Snippet() { + return rnd - 1; + } + + public static int ref9Snippet() { + return 1 + (rnd - 2); + } + + @Test + public void test10() { + test("test10Snippet", "ref10Snippet"); + } + + public static int test10Snippet() { + return rnd - 1; + } + + public static int ref10Snippet() { + return (rnd - 2) + 1; + } + + @Test + public void test11() { + test("test11Snippet", "ref11Snippet"); + } + + public static int test11Snippet() { + return -rnd + 3; + } + + public static int ref11Snippet() { + return 1 + (2 - rnd); + } + + @Test + public void test12() { + test("test12Snippet", "ref12Snippet"); + } + + public static int test12Snippet() { + return -rnd + 3; + } + + public static int ref12Snippet() { + return (2 - rnd) + 1; + } + + @Test + public void test13() { + test("test13Snippet", "ref13Snippet"); + } + + public static int test13Snippet() { + return -rnd + 3; + } + + public static int ref13Snippet() { + return 1 - (rnd - 2); + } + + @Test + public void test14() { + test("test14Snippet", "ref14Snippet"); + } + + public static int test14Snippet() { + return rnd - 3; + } + + public static int ref14Snippet() { + return (rnd - 2) - 1; + } + + @Test + public void test15() { + test("test15Snippet", "ref15Snippet"); + } + + public static int test15Snippet() { + return rnd + -1; + } + + public static int ref15Snippet() { + return 1 - (2 - rnd); + } + + @Test + public void test16() { + test("test16Snippet", "ref16Snippet"); + } + + public static int test16Snippet() { + return -rnd + 1; + } + + public static int ref16Snippet() { + return (2 - rnd) - 1; + } + + private void test(String test, String ref) { + StructuredGraph testGraph = parse(test); + new CanonicalizerPhase(null, runtime(), null).apply(testGraph); + StructuredGraph refGraph = parse(ref); + new CanonicalizerPhase(null, runtime(), null).apply(refGraph); + assertEquals(testGraph, refGraph); + } +} diff -r 4d0f01e9f31b -r bda2ebe1fc61 hotspot/.cproject --- a/hotspot/.cproject Sat Jun 16 02:19:38 2012 +0200 +++ b/hotspot/.cproject Sat Jun 16 02:20:02 2012 +0200 @@ -43,6 +43,7 @@ +