Search in sources :

Example 1 with InductionVariable

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));
}
Also used : StructuredGraph(org.graalvm.compiler.nodes.StructuredGraph) PhiNode(org.graalvm.compiler.nodes.PhiNode) AMD64AddressNode(org.graalvm.compiler.core.amd64.AMD64AddressNode) ConstantNode(org.graalvm.compiler.nodes.ConstantNode) OffsetAddressNode(org.graalvm.compiler.nodes.memory.address.OffsetAddressNode) AddNode(org.graalvm.compiler.nodes.calc.AddNode) SignExtendNode(org.graalvm.compiler.nodes.calc.SignExtendNode) ZeroExtendNode(org.graalvm.compiler.nodes.calc.ZeroExtendNode) CompressionNode(org.graalvm.compiler.nodes.CompressionNode) AddressNode(org.graalvm.compiler.nodes.memory.address.AddressNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) Node(org.graalvm.compiler.graph.Node) PhiNode(org.graalvm.compiler.nodes.PhiNode) IntegerStamp(org.graalvm.compiler.core.common.type.IntegerStamp) CountedLoopInfo(org.graalvm.compiler.nodes.loop.CountedLoopInfo) BasicInductionVariable(org.graalvm.compiler.nodes.loop.BasicInductionVariable) DerivedInductionVariable(org.graalvm.compiler.nodes.loop.DerivedInductionVariable) InductionVariable(org.graalvm.compiler.nodes.loop.InductionVariable) BasicInductionVariable(org.graalvm.compiler.nodes.loop.BasicInductionVariable) ZeroExtendNode(org.graalvm.compiler.nodes.calc.ZeroExtendNode)

Example 2 with InductionVariable

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);
        }
    }
}
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 3 with InductionVariable

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);
}
Also used : IntegerBelowNode(org.graalvm.compiler.nodes.calc.IntegerBelowNode) StructuredGraph(org.graalvm.compiler.nodes.StructuredGraph) IntegerStamp(org.graalvm.compiler.core.common.type.IntegerStamp) CompareNode(org.graalvm.compiler.nodes.calc.CompareNode) GuardNode(org.graalvm.compiler.nodes.GuardNode) AnchoringNode(org.graalvm.compiler.nodes.extended.AnchoringNode) ConstantNode(org.graalvm.compiler.nodes.ConstantNode) IntegerConvertNode(org.graalvm.compiler.nodes.calc.IntegerConvertNode) GuardedValueNode(org.graalvm.compiler.nodes.GuardedValueNode) IntegerBelowNode(org.graalvm.compiler.nodes.calc.IntegerBelowNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) 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) Node(org.graalvm.compiler.graph.Node) GuardingNode(org.graalvm.compiler.nodes.extended.GuardingNode) GuardedValueNode(org.graalvm.compiler.nodes.GuardedValueNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) LogicNode(org.graalvm.compiler.nodes.LogicNode) InductionVariable(org.graalvm.compiler.nodes.loop.InductionVariable)

Example 4 with InductionVariable

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());
}
Also used : SpeculationLog(jdk.vm.ci.meta.SpeculationLog) BytecodePosition(jdk.vm.ci.code.BytecodePosition) GuardedValueNode(org.graalvm.compiler.nodes.GuardedValueNode) GuardedValueNode(org.graalvm.compiler.nodes.GuardedValueNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) GuardNode(org.graalvm.compiler.nodes.GuardNode) MultiGuardNode(org.graalvm.compiler.nodes.extended.MultiGuardNode) InductionVariable(org.graalvm.compiler.nodes.loop.InductionVariable) LogicNode(org.graalvm.compiler.nodes.LogicNode) FrameState(org.graalvm.compiler.nodes.FrameState) GuardingNode(org.graalvm.compiler.nodes.extended.GuardingNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode)

Example 5 with InductionVariable

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;
}
Also used : Stamp(org.graalvm.compiler.core.common.type.Stamp) IntegerStamp(org.graalvm.compiler.core.common.type.IntegerStamp) IntegerStamp(org.graalvm.compiler.core.common.type.IntegerStamp) InductionVariable(org.graalvm.compiler.nodes.loop.InductionVariable)

Aggregations

InductionVariable (org.graalvm.compiler.nodes.loop.InductionVariable)6 ValueNode (org.graalvm.compiler.nodes.ValueNode)5 IntegerStamp (org.graalvm.compiler.core.common.type.IntegerStamp)4 Node (org.graalvm.compiler.graph.Node)4 ConstantNode (org.graalvm.compiler.nodes.ConstantNode)4 AbstractBeginNode (org.graalvm.compiler.nodes.AbstractBeginNode)3 GuardNode (org.graalvm.compiler.nodes.GuardNode)3 GuardedValueNode (org.graalvm.compiler.nodes.GuardedValueNode)3 LogicNode (org.graalvm.compiler.nodes.LogicNode)3 StructuredGraph (org.graalvm.compiler.nodes.StructuredGraph)3 GuardingNode (org.graalvm.compiler.nodes.extended.GuardingNode)3 MultiGuardNode (org.graalvm.compiler.nodes.extended.MultiGuardNode)3 BytecodePosition (jdk.vm.ci.code.BytecodePosition)2 SpeculationLog (jdk.vm.ci.meta.SpeculationLog)2 AMD64AddressNode (org.graalvm.compiler.core.amd64.AMD64AddressNode)2 CompressionNode (org.graalvm.compiler.nodes.CompressionNode)2 FrameState (org.graalvm.compiler.nodes.FrameState)2 LoopEndNode (org.graalvm.compiler.nodes.LoopEndNode)2 PhiNode (org.graalvm.compiler.nodes.PhiNode)2 AddNode (org.graalvm.compiler.nodes.calc.AddNode)2