use of org.graalvm.compiler.nodes.LoopBeginNode in project graal by oracle.
the class LoopFragmentInside method mergeEnds.
private AbstractBeginNode mergeEnds() {
assert isDuplicate();
List<EndNode> endsToMerge = new LinkedList<>();
// map peel exits to the corresponding loop exits
EconomicMap<AbstractEndNode, LoopEndNode> reverseEnds = EconomicMap.create(Equivalence.IDENTITY);
LoopBeginNode loopBegin = original().loop().loopBegin();
for (LoopEndNode le : loopBegin.loopEnds()) {
AbstractEndNode duplicate = getDuplicatedNode(le);
if (duplicate != null) {
endsToMerge.add((EndNode) duplicate);
reverseEnds.put(duplicate, le);
}
}
mergedInitializers = EconomicMap.create(Equivalence.IDENTITY);
AbstractBeginNode newExit;
StructuredGraph graph = graph();
if (endsToMerge.size() == 1) {
AbstractEndNode end = endsToMerge.get(0);
assert end.hasNoUsages();
newExit = graph.add(new BeginNode());
end.replaceAtPredecessor(newExit);
end.safeDelete();
} else {
assert endsToMerge.size() > 1;
AbstractMergeNode newExitMerge = graph.add(new MergeNode());
newExit = newExitMerge;
FrameState state = loopBegin.stateAfter();
FrameState duplicateState = null;
if (state != null) {
duplicateState = state.duplicateWithVirtualState();
newExitMerge.setStateAfter(duplicateState);
}
for (EndNode end : endsToMerge) {
newExitMerge.addForwardEnd(end);
}
for (final PhiNode phi : loopBegin.phis().snapshot()) {
if (phi.hasNoUsages()) {
continue;
}
final PhiNode firstPhi = patchPhi(graph, phi, newExitMerge);
for (AbstractEndNode end : newExitMerge.forwardEnds()) {
LoopEndNode loopEnd = reverseEnds.get(end);
ValueNode prim = prim(phi.valueAt(loopEnd));
assert prim != null;
firstPhi.addInput(prim);
}
ValueNode initializer = firstPhi;
if (duplicateState != null) {
// fix the merge's state after
duplicateState.applyToNonVirtual(new NodeClosure<ValueNode>() {
@Override
public void apply(Node from, ValueNode node) {
if (node == phi) {
from.replaceFirstInput(phi, firstPhi);
}
}
});
}
mergedInitializers.put(phi, initializer);
}
}
return newExit;
}
use of org.graalvm.compiler.nodes.LoopBeginNode in project graal by oracle.
the class LoopFragmentInside method insertWithinAfter.
/**
* Duplicate the body within the loop after the current copy copy of the body.
*
* @param loop
* @param updateLimit true if the iteration limit should be adjusted.
*/
public void insertWithinAfter(LoopEx loop, boolean updateLimit) {
assert isDuplicate() && original().loop() == loop;
patchNodes(dataFixWithinAfter);
/*
* Collect any new back edges values before updating them since they might reference each
* other.
*/
LoopBeginNode mainLoopBegin = loop.loopBegin();
ArrayList<ValueNode> backedgeValues = new ArrayList<>();
for (PhiNode mainPhiNode : mainLoopBegin.phis()) {
ValueNode duplicatedNode = getDuplicatedNode(mainPhiNode.valueAt(1));
if (duplicatedNode == null) {
if (mainLoopBegin.isPhiAtMerge(mainPhiNode.valueAt(1))) {
duplicatedNode = ((PhiNode) (mainPhiNode.valueAt(1))).valueAt(1);
} else {
assert mainPhiNode.valueAt(1).isConstant() : mainPhiNode.valueAt(1);
}
}
backedgeValues.add(duplicatedNode);
}
int index = 0;
for (PhiNode mainPhiNode : mainLoopBegin.phis()) {
ValueNode duplicatedNode = backedgeValues.get(index++);
if (duplicatedNode != null) {
mainPhiNode.setValueAt(1, duplicatedNode);
}
}
placeNewSegmentAndCleanup(loop);
// Remove any safepoints from the original copy leaving only the duplicated one
assert loop.whole().nodes().filter(SafepointNode.class).count() == nodes().filter(SafepointNode.class).count();
for (SafepointNode safepoint : loop.whole().nodes().filter(SafepointNode.class)) {
graph().removeFixed(safepoint);
}
int unrollFactor = mainLoopBegin.getUnrollFactor();
StructuredGraph graph = mainLoopBegin.graph();
if (updateLimit) {
// Now use the previous unrollFactor to update the exit condition to power of two
InductionVariable iv = loop.counted().getCounter();
CompareNode compareNode = (CompareNode) loop.counted().getLimitTest().condition();
ValueNode compareBound;
if (compareNode.getX() == iv.valueNode()) {
compareBound = compareNode.getY();
} else if (compareNode.getY() == iv.valueNode()) {
compareBound = compareNode.getX();
} else {
throw GraalError.shouldNotReachHere();
}
long originalStride = unrollFactor == 1 ? iv.constantStride() : iv.constantStride() / unrollFactor;
if (iv.direction() == InductionVariable.Direction.Up) {
ConstantNode aboveVal = graph.unique(ConstantNode.forIntegerStamp(iv.initNode().stamp(NodeView.DEFAULT), unrollFactor * originalStride));
ValueNode newLimit = graph.addWithoutUnique(new SubNode(compareBound, aboveVal));
compareNode.replaceFirstInput(compareBound, newLimit);
} else if (iv.direction() == InductionVariable.Direction.Down) {
ConstantNode aboveVal = graph.unique(ConstantNode.forIntegerStamp(iv.initNode().stamp(NodeView.DEFAULT), unrollFactor * -originalStride));
ValueNode newLimit = graph.addWithoutUnique(new AddNode(compareBound, aboveVal));
compareNode.replaceFirstInput(compareBound, newLimit);
}
}
mainLoopBegin.setUnrollFactor(unrollFactor * 2);
mainLoopBegin.setLoopFrequency(mainLoopBegin.loopFrequency() / 2);
graph.getDebug().dump(DebugContext.DETAILED_LEVEL, graph, "LoopPartialUnroll %s", loop);
mainLoopBegin.getDebug().dump(DebugContext.VERBOSE_LEVEL, mainLoopBegin.graph(), "After insertWithinAfter %s", mainLoopBegin);
}
use of org.graalvm.compiler.nodes.LoopBeginNode in project graal by oracle.
the class LoopEx method detectCounted.
public boolean detectCounted() {
LoopBeginNode loopBegin = loopBegin();
FixedNode next = loopBegin.next();
while (next instanceof FixedGuardNode || next instanceof ValueAnchorNode || next instanceof FullInfopointNode) {
next = ((FixedWithNextNode) next).next();
}
if (next instanceof IfNode) {
IfNode ifNode = (IfNode) next;
boolean negated = false;
if (!loopBegin.isLoopExit(ifNode.falseSuccessor())) {
if (!loopBegin.isLoopExit(ifNode.trueSuccessor())) {
return false;
}
negated = true;
}
LogicNode ifTest = ifNode.condition();
if (!(ifTest instanceof IntegerLessThanNode) && !(ifTest instanceof IntegerEqualsNode)) {
if (ifTest instanceof IntegerBelowNode) {
ifTest.getDebug().log("Ignored potential Counted loop at %s with |<|", loopBegin);
}
return false;
}
CompareNode lessThan = (CompareNode) ifTest;
Condition condition = null;
InductionVariable iv = null;
ValueNode limit = null;
if (isOutsideLoop(lessThan.getX())) {
iv = getInductionVariables().get(lessThan.getY());
if (iv != null) {
condition = lessThan.condition().asCondition().mirror();
limit = lessThan.getX();
}
} else if (isOutsideLoop(lessThan.getY())) {
iv = getInductionVariables().get(lessThan.getX());
if (iv != null) {
condition = lessThan.condition().asCondition();
limit = lessThan.getY();
}
}
if (condition == null) {
return false;
}
if (negated) {
condition = condition.negate();
}
boolean oneOff = false;
switch(condition) {
case EQ:
return false;
case NE:
{
if (!iv.isConstantStride() || Math.abs(iv.constantStride()) != 1) {
return false;
}
IntegerStamp initStamp = (IntegerStamp) iv.initNode().stamp(NodeView.DEFAULT);
IntegerStamp limitStamp = (IntegerStamp) limit.stamp(NodeView.DEFAULT);
if (iv.direction() == Direction.Up) {
if (initStamp.upperBound() > limitStamp.lowerBound()) {
return false;
}
} else if (iv.direction() == Direction.Down) {
if (initStamp.lowerBound() < limitStamp.upperBound()) {
return false;
}
} else {
return false;
}
break;
}
case LE:
oneOff = true;
if (iv.direction() != Direction.Up) {
return false;
}
break;
case LT:
if (iv.direction() != Direction.Up) {
return false;
}
break;
case GE:
oneOff = true;
if (iv.direction() != Direction.Down) {
return false;
}
break;
case GT:
if (iv.direction() != Direction.Down) {
return false;
}
break;
default:
throw GraalError.shouldNotReachHere();
}
counted = new CountedLoopInfo(this, iv, ifNode, limit, oneOff, negated ? ifNode.falseSuccessor() : ifNode.trueSuccessor());
return true;
}
return false;
}
use of org.graalvm.compiler.nodes.LoopBeginNode in project graal by oracle.
the class LoopEx method findInductionVariables.
/**
* Collect all the basic induction variables for the loop and the find any induction variables
* which are derived from the basic ones.
*
* @param loop
* @return a map from node to induction variable
*/
private static EconomicMap<Node, InductionVariable> findInductionVariables(LoopEx loop) {
EconomicMap<Node, InductionVariable> ivs = EconomicMap.create(Equivalence.IDENTITY);
Queue<InductionVariable> scanQueue = new LinkedList<>();
LoopBeginNode loopBegin = loop.loopBegin();
AbstractEndNode forwardEnd = loopBegin.forwardEnd();
for (PhiNode phi : loopBegin.valuePhis()) {
ValueNode backValue = phi.singleBackValueOrThis();
if (backValue == phi) {
continue;
}
ValueNode stride = addSub(loop, backValue, phi);
if (stride != null) {
BasicInductionVariable biv = new BasicInductionVariable(loop, (ValuePhiNode) phi, phi.valueAt(forwardEnd), stride, (BinaryArithmeticNode<?>) backValue);
ivs.put(phi, biv);
scanQueue.add(biv);
}
}
while (!scanQueue.isEmpty()) {
InductionVariable baseIv = scanQueue.remove();
ValueNode baseIvNode = baseIv.valueNode();
for (ValueNode op : baseIvNode.usages().filter(ValueNode.class)) {
if (loop.isOutsideLoop(op)) {
continue;
}
if (op.usages().count() == 1 && op.usages().first() == baseIvNode) {
/*
* This is just the base induction variable increment with no other uses so
* don't bother reporting it.
*/
continue;
}
InductionVariable iv = null;
ValueNode offset = addSub(loop, op, baseIvNode);
ValueNode scale;
if (offset != null) {
iv = new DerivedOffsetInductionVariable(loop, baseIv, offset, (BinaryArithmeticNode<?>) op);
} else if (op instanceof NegateNode) {
iv = new DerivedScaledInductionVariable(loop, baseIv, (NegateNode) op);
} else if ((scale = mul(loop, op, baseIvNode)) != null) {
iv = new DerivedScaledInductionVariable(loop, baseIv, scale, op);
} else {
boolean isValidConvert = op instanceof PiNode || op instanceof SignExtendNode;
if (!isValidConvert && op instanceof ZeroExtendNode) {
ZeroExtendNode zeroExtendNode = (ZeroExtendNode) op;
isValidConvert = zeroExtendNode.isInputAlwaysPositive() || ((IntegerStamp) zeroExtendNode.stamp(NodeView.DEFAULT)).isPositive();
}
if (isValidConvert) {
iv = new DerivedConvertedInductionVariable(loop, baseIv, op.stamp(NodeView.DEFAULT), op);
}
}
if (iv != null) {
ivs.put(op, iv);
scanQueue.offer(iv);
}
}
}
return ivs;
}
use of org.graalvm.compiler.nodes.LoopBeginNode in project graal by oracle.
the class AMD64AddressNode method canonicalizeIndex.
public void canonicalizeIndex(SimplifierTool tool) {
if (index instanceof AddNode && ((IntegerStamp) index.stamp(NodeView.DEFAULT)).getBits() == 64) {
AddNode add = (AddNode) index;
ValueNode valX = add.getX();
if (valX instanceof PhiNode) {
PhiNode phi = (PhiNode) valX;
if (phi.merge() instanceof LoopBeginNode) {
LoopBeginNode loopNode = (LoopBeginNode) phi.merge();
if (!loopNode.isSimpleLoop()) {
ValueNode valY = add.getY();
if (valY instanceof ConstantNode) {
int addBy = valY.asJavaConstant().asInt();
displacement = displacement + scale.value * addBy;
replaceFirstInput(index, phi);
tool.addToWorkList(index);
}
}
}
}
}
}
Aggregations