use of org.graalvm.compiler.nodes.loop.InductionVariable in project graal by oracle.
the class AMD64HotSpotAddressLowering method signExtend.
/**
* Create a sign extend for {@code input}, or zero extend if {@code input} can be proven
* positive.
*/
private static ValueNode signExtend(ValueNode input, LoopEx loop) {
StructuredGraph graph = input.graph();
if (input instanceof PhiNode) {
EconomicMap<Node, InductionVariable> ivs = loop.getInductionVariables();
InductionVariable inductionVariable = ivs.get(input);
if (inductionVariable != null && inductionVariable instanceof BasicInductionVariable) {
CountedLoopInfo countedLoopInfo = loop.counted();
IntegerStamp initStamp = (IntegerStamp) inductionVariable.initNode().stamp(NodeView.DEFAULT);
if (initStamp.isPositive()) {
if (inductionVariable.isConstantExtremum() && countedLoopInfo.counterNeverOverflows()) {
long init = inductionVariable.constantInit();
long stride = inductionVariable.constantStride();
long extremum = inductionVariable.constantExtremum();
if (init >= 0 && extremum >= 0) {
long shortestTrip = (extremum - init) / stride + 1;
if (countedLoopInfo.constantMaxTripCount().equals(shortestTrip)) {
return graph.unique(new ZeroExtendNode(input, INT_BITS, ADDRESS_BITS, true));
}
}
}
if (countedLoopInfo.getLimitCheckedIV() == inductionVariable && inductionVariable.direction() == InductionVariable.Direction.Up && (countedLoopInfo.getOverFlowGuard() != null || countedLoopInfo.counterNeverOverflows())) {
return graph.unique(new ZeroExtendNode(input, INT_BITS, ADDRESS_BITS, true));
}
}
}
}
return input.graph().maybeAddOrUnique(SignExtendNode.create(input, ADDRESS_BITS, NodeView.DEFAULT));
}
use of org.graalvm.compiler.nodes.loop.InductionVariable in project graal by oracle.
the class LoopPredicationPhase method run.
@Override
@SuppressWarnings("try")
protected void run(StructuredGraph graph, MidTierContext context) {
DebugContext debug = graph.getDebug();
final SpeculationLog speculationLog = graph.getSpeculationLog();
if (graph.hasLoops() && graph.getGuardsStage().allowsFloatingGuards() && context.getOptimisticOptimizations().useLoopLimitChecks(graph.getOptions()) && speculationLog != null) {
LoopsData data = context.getLoopsDataProvider().getLoopsData(graph);
final ControlFlowGraph cfg = data.getCFG();
try (DebugContext.Scope s = debug.scope("predication", cfg)) {
for (LoopEx loop : data.loops()) {
// Only inner most loops.
if (!loop.loop().getChildren().isEmpty()) {
continue;
}
if (!loop.detectCounted()) {
continue;
}
final FrameState state = loop.loopBegin().stateAfter();
final BytecodePosition pos = new BytecodePosition(null, state.getMethod(), state.bci);
SpeculationLog.SpeculationReason reason = LOOP_PREDICATION.createSpeculationReason(pos);
if (speculationLog.maySpeculate(reason)) {
final CountedLoopInfo counted = loop.counted();
final InductionVariable counter = counted.getLimitCheckedIV();
final Condition condition = ((CompareNode) counted.getLimitTest().condition()).condition().asCondition();
final boolean inverted = loop.counted().isInverted();
if ((((IntegerStamp) counter.valueNode().stamp(NodeView.DEFAULT)).getBits() == 32) && !counted.isUnsignedCheck() && ((condition != NE && condition != EQ) || (counter.isConstantStride() && Math.abs(counter.constantStride()) == 1)) && (loop.loopBegin().isMainLoop() || loop.loopBegin().isSimpleLoop())) {
NodeIterable<GuardNode> guards = loop.whole().nodes().filter(GuardNode.class);
if (LoopPredicationMainPath.getValue(graph.getOptions())) {
// C2 only applies loop predication to guards dominating the
// backedge.
// The following logic emulates that behavior.
final NodeIterable<LoopEndNode> loopEndNodes = loop.loopBegin().loopEnds();
final Block end = data.getCFG().commonDominatorFor(loopEndNodes);
guards = guards.filter(guard -> {
final ValueNode anchor = ((GuardNode) guard).getAnchor().asNode();
final Block anchorBlock = data.getCFG().getNodeToBlock().get(anchor);
return AbstractControlFlowGraph.dominates(anchorBlock, end);
});
}
final AbstractBeginNode body = loop.counted().getBody();
final Block bodyBlock = cfg.getNodeToBlock().get(body);
for (GuardNode guard : guards) {
final AnchoringNode anchor = guard.getAnchor();
final Block anchorBlock = cfg.getNodeToBlock().get(anchor.asNode());
// for inverted loop the anchor can dominate the body
if (!inverted) {
if (!AbstractControlFlowGraph.dominates(bodyBlock, anchorBlock)) {
continue;
}
}
processGuard(loop, guard);
}
}
}
}
} catch (Throwable t) {
throw debug.handle(t);
}
}
}
use of org.graalvm.compiler.nodes.loop.InductionVariable in project graal by oracle.
the class LoopPredicationPhase method processGuard.
// Create a range check predicate for
//
// for (i = init; i < limit; i += stride) {
// a[scale*i+offset]
// }
private static void processGuard(LoopEx loop, GuardNode guard) {
final LogicNode condition = guard.getCondition();
if (!(condition instanceof IntegerBelowNode) || guard.isNegated()) {
return;
}
final IntegerBelowNode rangeCheck = (IntegerBelowNode) condition;
final ValueNode range = rangeCheck.getY();
if (!loop.isOutsideLoop(range) || ((IntegerStamp) range.stamp(NodeView.DEFAULT)).lowerBound() < 0) {
return;
}
final EconomicMap<Node, InductionVariable> inductionVariables = loop.getInductionVariables();
final ValueNode x = rangeCheck.getX();
if (!inductionVariables.containsKey(x)) {
return;
}
final StructuredGraph graph = guard.graph();
final InductionVariable iv = inductionVariables.get(x);
Long scale = null;
final InductionVariable counter = loop.counted().getLimitCheckedIV();
if (iv.isConstantScale(counter)) {
scale = iv.constantScale(counter);
}
ValueNode offset = null;
if (iv.offsetIsZero(counter)) {
offset = graph.unique(ConstantNode.forInt(0));
} else {
offset = iv.offsetNode(counter);
}
if (offset == null || scale == null || !loop.isOutsideLoop(offset)) {
return;
}
long scaleCon = scale;
replaceGuardNode(loop, guard, range, graph, scaleCon, offset);
}
use of org.graalvm.compiler.nodes.loop.InductionVariable in project graal by oracle.
the class LoopPredicationPhase method replaceGuardNode.
private static void replaceGuardNode(LoopEx loop, GuardNode guard, ValueNode range, StructuredGraph graph, long scaleCon, ValueNode offset) {
final InductionVariable counter = loop.counted().getLimitCheckedIV();
ValueNode rangeLong = IntegerConvertNode.convert(range, StampFactory.forInteger(64), graph, NodeView.DEFAULT);
ValueNode extremumNode = counter.extremumNode(false, StampFactory.forInteger(64));
final GuardingNode overFlowGuard = loop.counted().createOverFlowGuard();
assert overFlowGuard != null || loop.counted().counterNeverOverflows();
if (overFlowGuard != null) {
extremumNode = graph.unique(new GuardedValueNode(extremumNode, overFlowGuard));
}
final ValueNode upperNode = MathUtil.add(graph, MathUtil.mul(graph, extremumNode, ConstantNode.forLong(scaleCon, graph)), IntegerConvertNode.convert(offset, StampFactory.forInteger(64), graph, NodeView.DEFAULT));
final LogicNode upperCond = IntegerBelowNode.create(upperNode, rangeLong, NodeView.DEFAULT);
final ValueNode initNode = IntegerConvertNode.convert(loop.counted().getBodyIVStart(), StampFactory.forInteger(64), graph, NodeView.DEFAULT);
final ValueNode lowerNode = MathUtil.add(graph, MathUtil.mul(graph, initNode, ConstantNode.forLong(scaleCon, graph)), IntegerConvertNode.convert(offset, StampFactory.forInteger(64), graph, NodeView.DEFAULT));
final LogicNode lowerCond = IntegerBelowNode.create(lowerNode, rangeLong, NodeView.DEFAULT);
final FrameState state = loop.loopBegin().stateAfter();
final BytecodePosition pos = new BytecodePosition(null, state.getMethod(), state.bci);
SpeculationLog.SpeculationReason reason = LOOP_PREDICATION.createSpeculationReason(pos);
SpeculationLog.Speculation speculation = graph.getSpeculationLog().speculate(reason);
final AbstractBeginNode anchor = AbstractBeginNode.prevBegin(loop.entryPoint());
final GuardNode upperGuard = graph.addOrUniqueWithInputs(new GuardNode(upperCond, anchor, guard.getReason(), guard.getAction(), guard.isNegated(), speculation, null));
final GuardNode lowerGuard = graph.addOrUniqueWithInputs(new GuardNode(lowerCond, anchor, guard.getReason(), guard.getAction(), guard.isNegated(), speculation, null));
final GuardingNode combinedGuard = MultiGuardNode.combine(lowerGuard, upperGuard);
guard.replaceAtUsagesAndDelete(combinedGuard.asNode());
}
use of org.graalvm.compiler.nodes.loop.InductionVariable in project graal by oracle.
the class LoopSafepointEliminationPhase method loopIsIn32BitRange.
private static boolean loopIsIn32BitRange(LoopEx loop) {
if (loop.counted().getStamp().getBits() <= 32) {
return true;
}
final Stamp limitStamp = loop.counted().getTripCountLimit().stamp(NodeView.DEFAULT);
if (limitStamp instanceof IntegerStamp) {
final IntegerStamp limitIStamp = (IntegerStamp) limitStamp;
final long upperBoundLimit = limitIStamp.upperBound();
final Stamp startStamp = loop.counted().getBodyIVStart().stamp(NodeView.DEFAULT);
if (startStamp instanceof IntegerStamp) {
final IntegerStamp startIStamp = (IntegerStamp) startStamp;
final long lowerBoundStart = startIStamp.lowerBound();
if (IntegerStamp.subtractionOverflows(upperBoundLimit, lowerBoundStart, 64)) {
return false;
}
final long startToLimitDistance = Math.abs(upperBoundLimit - lowerBoundStart);
/*
* Divide the distance by the absolute value of the stride. For non-constant strides
* assume a worst case stride of 1 since a stride of 0 isn't recognized as an
* induction variable.
*/
final InductionVariable counter = loop.counted().getLimitCheckedIV();
final long stride = counter.isConstantStride() ? Math.abs(counter.constantStride()) : 1;
final long strideRelativeStartToLimitDistance = startToLimitDistance / stride;
return strideRelativeStartToLimitDistance <= IntegerRangeDistance;
}
}
return false;
}
Aggregations