Search in sources :

Example 6 with LoopEx

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);
        }
    }
}
Also used : Condition(org.graalvm.compiler.core.common.calc.Condition) CompareNode(org.graalvm.compiler.nodes.calc.CompareNode) ControlFlowGraph(org.graalvm.compiler.nodes.cfg.ControlFlowGraph) GuardNode(org.graalvm.compiler.nodes.GuardNode) AnchoringNode(org.graalvm.compiler.nodes.extended.AnchoringNode) EQ(org.graalvm.compiler.core.common.calc.Condition.EQ) ConstantNode(org.graalvm.compiler.nodes.ConstantNode) IntegerConvertNode(org.graalvm.compiler.nodes.calc.IntegerConvertNode) CountedLoopInfo(org.graalvm.compiler.nodes.loop.CountedLoopInfo) IntegerStamp(org.graalvm.compiler.core.common.type.IntegerStamp) StampFactory(org.graalvm.compiler.core.common.type.StampFactory) DebugContext(org.graalvm.compiler.debug.DebugContext) EconomicMap(org.graalvm.collections.EconomicMap) BytecodePosition(jdk.vm.ci.code.BytecodePosition) GuardedValueNode(org.graalvm.compiler.nodes.GuardedValueNode) InductionVariable(org.graalvm.compiler.nodes.loop.InductionVariable) LoopEx(org.graalvm.compiler.nodes.loop.LoopEx) SpeculationReasonGroup(org.graalvm.compiler.serviceprovider.SpeculationReasonGroup) Condition(org.graalvm.compiler.core.common.calc.Condition) IntegerBelowNode(org.graalvm.compiler.nodes.calc.IntegerBelowNode) LoopPredicationMainPath(org.graalvm.compiler.core.common.GraalOptions.LoopPredicationMainPath) BasePhase(org.graalvm.compiler.phases.BasePhase) NodeView(org.graalvm.compiler.nodes.NodeView) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) MidTierContext(org.graalvm.compiler.phases.tiers.MidTierContext) LoopsData(org.graalvm.compiler.nodes.loop.LoopsData) NE(org.graalvm.compiler.core.common.calc.Condition.NE) LoopEndNode(org.graalvm.compiler.nodes.LoopEndNode) LogicNode(org.graalvm.compiler.nodes.LogicNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) MultiGuardNode(org.graalvm.compiler.nodes.extended.MultiGuardNode) StructuredGraph(org.graalvm.compiler.nodes.StructuredGraph) FrameState(org.graalvm.compiler.nodes.FrameState) NodeIterable(org.graalvm.compiler.graph.iterators.NodeIterable) Block(org.graalvm.compiler.nodes.cfg.Block) Node(org.graalvm.compiler.graph.Node) GuardingNode(org.graalvm.compiler.nodes.extended.GuardingNode) SpeculationLog(jdk.vm.ci.meta.SpeculationLog) MathUtil(org.graalvm.compiler.nodes.loop.MathUtil) AbstractControlFlowGraph(org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph) LoopsData(org.graalvm.compiler.nodes.loop.LoopsData) BytecodePosition(jdk.vm.ci.code.BytecodePosition) CountedLoopInfo(org.graalvm.compiler.nodes.loop.CountedLoopInfo) GuardNode(org.graalvm.compiler.nodes.GuardNode) MultiGuardNode(org.graalvm.compiler.nodes.extended.MultiGuardNode) AnchoringNode(org.graalvm.compiler.nodes.extended.AnchoringNode) DebugContext(org.graalvm.compiler.debug.DebugContext) FrameState(org.graalvm.compiler.nodes.FrameState) LoopEndNode(org.graalvm.compiler.nodes.LoopEndNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) SpeculationLog(jdk.vm.ci.meta.SpeculationLog) ControlFlowGraph(org.graalvm.compiler.nodes.cfg.ControlFlowGraph) AbstractControlFlowGraph(org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph) LoopEx(org.graalvm.compiler.nodes.loop.LoopEx) GuardedValueNode(org.graalvm.compiler.nodes.GuardedValueNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) Block(org.graalvm.compiler.nodes.cfg.Block) InductionVariable(org.graalvm.compiler.nodes.loop.InductionVariable)

Example 7 with LoopEx

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);
    }
}
Also used : LoopsData(org.graalvm.compiler.nodes.loop.LoopsData) LoopEx(org.graalvm.compiler.nodes.loop.LoopEx) DebugContext(org.graalvm.compiler.debug.DebugContext)

Example 8 with LoopEx

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);
    }
}
Also used : LoopsData(org.graalvm.compiler.nodes.loop.LoopsData) NodeBitMap(org.graalvm.compiler.graph.NodeBitMap) LoopEx(org.graalvm.compiler.nodes.loop.LoopEx) ValueNode(org.graalvm.compiler.nodes.ValueNode) DebugContext(org.graalvm.compiler.debug.DebugContext)

Example 9 with LoopEx

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());
}
Also used : LoopsData(org.graalvm.compiler.nodes.loop.LoopsData) NodeEventScope(org.graalvm.compiler.graph.Graph.NodeEventScope) LoopEx(org.graalvm.compiler.nodes.loop.LoopEx)

Example 10 with LoopEx

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;
}
Also used : LoopsData(org.graalvm.compiler.nodes.loop.LoopsData) LoopEx(org.graalvm.compiler.nodes.loop.LoopEx) Block(org.graalvm.compiler.nodes.cfg.Block)

Aggregations

LoopEx (org.graalvm.compiler.nodes.loop.LoopEx)21 LoopsData (org.graalvm.compiler.nodes.loop.LoopsData)19 DebugContext (org.graalvm.compiler.debug.DebugContext)8 Node (org.graalvm.compiler.graph.Node)4 StructuredGraph (org.graalvm.compiler.nodes.StructuredGraph)4 ValueNode (org.graalvm.compiler.nodes.ValueNode)4 Block (org.graalvm.compiler.nodes.cfg.Block)4 GraalCompilerTest (org.graalvm.compiler.core.test.GraalCompilerTest)3 LoopBeginNode (org.graalvm.compiler.nodes.LoopBeginNode)3 HashSet (java.util.HashSet)2 SpeculationLog (jdk.vm.ci.meta.SpeculationLog)2 FixedNode (org.graalvm.compiler.nodes.FixedNode)2 FrameState (org.graalvm.compiler.nodes.FrameState)2 LogicNode (org.graalvm.compiler.nodes.LogicNode)2 LoopEndNode (org.graalvm.compiler.nodes.LoopEndNode)2 PiNode (org.graalvm.compiler.nodes.PiNode)2 CanonicalizerPhase (org.graalvm.compiler.phases.common.CanonicalizerPhase)2 DeadCodeEliminationPhase (org.graalvm.compiler.phases.common.DeadCodeEliminationPhase)2 Test (org.junit.Test)2 BytecodePosition (jdk.vm.ci.code.BytecodePosition)1