use of org.graalvm.compiler.nodes.loop.LoopEx 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.LoopEx in project graal by oracle.
the class ReassociationPhase method reassociateInvariants.
// @formatter:off
/**
* Re-associate loop invariant so that invariant parts of the expression can move outside of the
* loop.
*
* For example:
* for (int i = 0; i < LENGTH; i++) { for (int i = 0; i < LENGTH; i++) {
* arr[i] = (i * inv1) * inv2; => arr[i] = i * (inv1 * inv2);
* } }
*/
// @formatter:on
@SuppressWarnings("try")
private static void reassociateInvariants(StructuredGraph graph, CoreProviders context) {
DebugContext debug = graph.getDebug();
LoopsData loopsData = context.getLoopsDataProvider().getLoopsData(graph);
int iterations = 0;
try (DebugContext.Scope s = debug.scope("ReassociateInvariants")) {
boolean changed = true;
// bound.
while (changed && iterations < 32) {
changed = false;
for (LoopEx loop : loopsData.loops()) {
changed |= loop.reassociateInvariants();
}
loopsData.deleteUnusedNodes();
iterations++;
debug.dump(DebugContext.VERY_DETAILED_LEVEL, graph, "Reassociation: after iteration %d", iterations);
}
} catch (Throwable e) {
throw debug.handle(e);
}
}
use of org.graalvm.compiler.nodes.loop.LoopEx in project graal by oracle.
the class ReassociationPhase method reassociateConstants.
/**
* Push constant down the expression tree like "(a + 1) + b" => "(a + b) + 1". It creates more
* opportunities for optimizations like "(a + 1) + 2" => "(a + 3)", which has been implemented
* in the {@linkplain CanonicalizerPhase CanonicalizerPhase}. To avoid some unexpected
* regressions for loop invariants like "i + (inv + 1)" => "(i + inv) + 1", this re-association
* is applied after {@linkplain ReassociationPhase#reassociateInvariants reassociateInvariants}
* and only applied to expressions outside a loop.
*/
@SuppressWarnings("try")
private static void reassociateConstants(StructuredGraph graph, CoreProviders context) {
LoopsData loopsData = context.getLoopsDataProvider().getLoopsData(graph);
NodeBitMap loopNodes = graph.createNodeBitMap();
for (LoopEx loop : loopsData.loops()) {
loopNodes.union(loop.whole().nodes());
}
DebugContext debug = graph.getDebug();
try (DebugContext.Scope s = debug.scope("ReassociateConstants")) {
for (BinaryArithmeticNode<?> binary : graph.getNodes().filter(BinaryArithmeticNode.class)) {
// Skip re-associations to loop variant expressions.
if (!binary.isAssociative() || (!loopNodes.isNew(binary) && loopNodes.contains(binary))) {
continue;
}
ValueNode result = BinaryArithmeticNode.reassociateUnmatchedValues(binary, ValueNode.isConstantPredicate(), NodeView.DEFAULT);
if (result != binary) {
if (!result.isAlive()) {
assert !result.isDeleted();
result = graph.addOrUniqueWithInputs(result);
}
if (debug.isLogEnabled()) {
debug.log("%s : Re-associated %s into %s", graph.method().format("%H::%n"), binary, result);
}
binary.replaceAtUsages(result);
GraphUtil.killWithUnusedFloatingInputs(binary);
}
}
} catch (Throwable e) {
throw debug.handle(e);
}
}
use of org.graalvm.compiler.nodes.loop.LoopEx in project graal by oracle.
the class LoopUtility method removeObsoleteProxies.
/**
* Remove loop proxies that became obsolete over time, i.e., they proxy a value that already
* flowed out of a loop and dominates the loop now.
*
* @param canonicalizer must not be {@code null}, will be applied incrementally to nodes whose
* inputs changed
*/
@SuppressWarnings("try")
public static void removeObsoleteProxies(StructuredGraph graph, CoreProviders context, CanonicalizerPhase canonicalizer) {
LoopsData loopsData = context.getLoopsDataProvider().getLoopsData(graph);
final EconomicSetNodeEventListener inputChanges = new EconomicSetNodeEventListener(EnumSet.of(NodeEvent.INPUT_CHANGED));
try (NodeEventScope s = graph.trackNodeEvents(inputChanges)) {
for (LoopEx loop : loopsData.loops()) {
removeObsoleteProxiesForLoop(loop);
}
}
canonicalizer.applyIncremental(graph, context, inputChanges.getNodes());
}
use of org.graalvm.compiler.nodes.loop.LoopEx in project graal by oracle.
the class ConvertDeoptimizeToGuardPhase method isCountedLoopExit.
private static boolean isCountedLoopExit(IfNode ifNode, LazyValue<LoopsData> lazyLoops) {
LoopsData loopsData = lazyLoops.get();
Loop<Block> loop = loopsData.getCFG().getNodeToBlock().get(ifNode).getLoop();
if (loop != null) {
LoopEx loopEx = loopsData.loop(loop);
if (loopEx.detectCounted()) {
return ifNode == loopEx.counted().getLimitTest();
}
if (loopEx.canBecomeLimitTestAfterFloatingReads(ifNode)) {
return true;
}
}
return false;
}
Aggregations