Search in sources :

Example 1 with ProfileSource

use of org.graalvm.compiler.nodes.ProfileData.ProfileSource in project graal by oracle.

the class BytecodeParser method getProfileData.

protected BranchProbabilityData getProfileData(boolean negate) {
    if (profilingInfo == null) {
        return BranchProbabilityData.unknown();
    }
    assert assertAtIfBytecode();
    double probability = profilingInfo.getBranchTakenProbability(bci());
    if (probability < 0) {
        assert probability == -1 : "invalid probability";
        debug.log("missing probability in %s at bci %d", code, bci());
        return BranchProbabilityData.unknown();
    }
    probability = clampProbability(probability);
    ProfileSource source = profilingInfo.isMature() ? ProfileSource.PROFILED : ProfileSource.UNKNOWN;
    BranchProbabilityData profileData = BranchProbabilityData.create(probability, source);
    if (negate) {
        // the probability coming from profile is about the original condition
        profileData = profileData.negated();
    }
    return profileData;
}
Also used : ProfileSource(org.graalvm.compiler.nodes.ProfileData.ProfileSource) BranchProbabilityData(org.graalvm.compiler.nodes.ProfileData.BranchProbabilityData)

Example 2 with ProfileSource

use of org.graalvm.compiler.nodes.ProfileData.ProfileSource in project graal by oracle.

the class IfNode method simplify.

@Override
public void simplify(SimplifierTool tool) {
    if (trueSuccessor().next() instanceof DeoptimizeNode) {
        if (getTrueSuccessorProbability() != 0) {
            CORRECTED_PROBABILITIES.increment(getDebug());
            profileData = BranchProbabilityNode.NEVER_TAKEN_PROFILE;
        }
    } else if (falseSuccessor().next() instanceof DeoptimizeNode) {
        if (getTrueSuccessorProbability() != 1) {
            CORRECTED_PROBABILITIES.increment(getDebug());
            profileData = BranchProbabilityNode.ALWAYS_TAKEN_PROFILE;
        }
    }
    if (condition() instanceof LogicNegationNode) {
        eliminateNegation();
    }
    if (condition() instanceof LogicConstantNode) {
        LogicConstantNode c = (LogicConstantNode) condition();
        if (c.getValue()) {
            tool.deleteBranch(falseSuccessor());
            tool.addToWorkList(trueSuccessor());
            graph().removeSplit(this, trueSuccessor());
        } else {
            tool.deleteBranch(trueSuccessor());
            tool.addToWorkList(falseSuccessor());
            graph().removeSplit(this, falseSuccessor());
        }
        return;
    }
    if (tool.allUsagesAvailable() && trueSuccessor().hasNoUsages() && falseSuccessor().hasNoUsages()) {
        pushNodesThroughIf(tool);
        if (checkForUnsignedCompare(tool) || removeOrMaterializeIf(tool)) {
            return;
        }
    }
    if (removeIntermediateMaterialization(tool)) {
        return;
    }
    if (conditionalNodeOptimization(tool)) {
        return;
    }
    if (switchTransformationOptimization(tool)) {
        return;
    }
    if (tool.finalCanonicalization()) {
        if (falseSuccessor().hasNoUsages() && (!(falseSuccessor() instanceof LoopExitNode)) && falseSuccessor().next() instanceof IfNode && !(((IfNode) falseSuccessor().next()).falseSuccessor() instanceof LoopExitNode)) {
            AbstractBeginNode intermediateBegin = falseSuccessor();
            IfNode nextIf = (IfNode) intermediateBegin.next();
            double probabilityB = (1.0 - this.getTrueSuccessorProbability()) * nextIf.getTrueSuccessorProbability();
            if (this.getTrueSuccessorProbability() < probabilityB) {
                // their probabilities.
                if (prepareForSwap(tool, condition(), nextIf.condition())) {
                    // @formatter:on
                    assert intermediateBegin.next() == nextIf;
                    AbstractBeginNode bothFalseBegin = nextIf.falseSuccessor();
                    nextIf.setFalseSuccessor(null);
                    intermediateBegin.setNext(null);
                    this.setFalseSuccessor(null);
                    this.replaceAtPredecessor(nextIf);
                    nextIf.setFalseSuccessor(intermediateBegin);
                    intermediateBegin.setNext(this);
                    this.setFalseSuccessor(bothFalseBegin);
                    NodeSourcePosition intermediateBeginPosition = intermediateBegin.getNodeSourcePosition();
                    intermediateBegin.setNodeSourcePosition(bothFalseBegin.getNodeSourcePosition());
                    bothFalseBegin.setNodeSourcePosition(intermediateBeginPosition);
                    ProfileSource combinedSource = profileData.getProfileSource().combine(nextIf.profileData.getProfileSource());
                    nextIf.setTrueSuccessorProbability(BranchProbabilityData.create(probabilityB, combinedSource));
                    if (probabilityB == 1.0) {
                        this.setTrueSuccessorProbability(BranchProbabilityData.create(0.0, combinedSource));
                    } else {
                        double newProbability = this.getTrueSuccessorProbability() / (1.0 - probabilityB);
                        this.setTrueSuccessorProbability(BranchProbabilityData.create(Math.min(1.0, newProbability), combinedSource));
                    }
                    return;
                }
            }
        }
    }
    if (tryEliminateBoxedReferenceEquals(tool)) {
        return;
    }
}
Also used : ProfileSource(org.graalvm.compiler.nodes.ProfileData.ProfileSource) NodeSourcePosition(org.graalvm.compiler.graph.NodeSourcePosition)

Example 3 with ProfileSource

use of org.graalvm.compiler.nodes.ProfileData.ProfileSource in project graal by oracle.

the class ControlFlowGraph method perBasicBlockFrequencyAction.

private void perBasicBlockFrequencyAction(Block b, boolean computingLocalLoopFrequencies) {
    double relativeFrequency = -1D;
    ProfileSource source = ProfileSource.UNKNOWN;
    Block[] predecessors = b.getPredecessors();
    if (predecessors.length == 0) {
        relativeFrequency = 1D;
    } else if (predecessors.length == 1) {
        Block pred = predecessors[0];
        relativeFrequency = pred.relativeFrequency;
        if (pred.getSuccessorCount() > 1) {
            assert pred.getEndNode() instanceof ControlSplitNode;
            ControlSplitNode controlSplit = (ControlSplitNode) pred.getEndNode();
            relativeFrequency = multiplyRelativeFrequencies(relativeFrequency, controlSplit.probability(b.getBeginNode()));
            if (computingLocalLoopFrequencies) {
                source = controlSplit.getProfileData().getProfileSource();
            }
        }
    } else {
        relativeFrequency = predecessors[0].relativeFrequency;
        for (int i = 1; i < predecessors.length; ++i) {
            relativeFrequency += predecessors[i].relativeFrequency;
            if (computingLocalLoopFrequencies) {
                if (predecessors[i].frequencySource != null) {
                    source = source.combine(predecessors[i].frequencySource);
                }
            }
        }
        if (b.getBeginNode() instanceof LoopBeginNode) {
            if (computingLocalLoopFrequencies) {
                // start with a "local" loop, i.e., assume no dominating code with different
                // frequencies
                relativeFrequency = 1D;
                source = ProfileSource.UNKNOWN;
            } else {
                // take the previously computed local frequency
                LoopBeginNode loopBegin = (LoopBeginNode) b.getBeginNode();
                relativeFrequency = multiplyRelativeFrequencies(relativeFrequency, localLoopFrequencyData.get(loopBegin).getLoopFrequency());
            }
        }
    }
    if (relativeFrequency < MIN_RELATIVE_FREQUENCY) {
        relativeFrequency = MIN_RELATIVE_FREQUENCY;
    } else if (relativeFrequency > MAX_RELATIVE_FREQUENCY) {
        relativeFrequency = MAX_RELATIVE_FREQUENCY;
    }
    b.setRelativeFrequency(relativeFrequency);
    if (computingLocalLoopFrequencies) {
        b.setFrequencySource(source);
    }
}
Also used : ProfileSource(org.graalvm.compiler.nodes.ProfileData.ProfileSource) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) ControlSplitNode(org.graalvm.compiler.nodes.ControlSplitNode)

Example 4 with ProfileSource

use of org.graalvm.compiler.nodes.ProfileData.ProfileSource in project graal by oracle.

the class ControlFlowGraph method calculateLocalLoopFrequency.

private double calculateLocalLoopFrequency(LoopBeginNode lb) {
    Block header = blockFor(lb);
    assert header != null;
    double loopFrequency = -1;
    ProfileSource source = ProfileSource.UNKNOWN;
    if (CFGOptions.UseLoopEndFrequencies.getValue(lb.graph().getOptions())) {
        double loopEndFrequency = 0D;
        for (LoopEndNode len : lb.loopEnds()) {
            Block endBlock = blockFor(len);
            assert endBlock != null;
            assert endBlock.relativeFrequency >= 0D;
            loopEndFrequency += endBlock.relativeFrequency;
            source = source.combine(endBlock.frequencySource);
        }
        loopEndFrequency = Math.min(1, loopEndFrequency);
        loopEndFrequency = Math.max(ControlFlowGraph.MIN_RELATIVE_FREQUENCY, loopEndFrequency);
        if (loopEndFrequency == 1D) {
            // endless loop, loop with exit and deopt unconditionally after the exit
            loopFrequency = MAX_RELATIVE_FREQUENCY;
        } else {
            double exitFrequency = 1D - loopEndFrequency;
            loopFrequency = 1D / exitFrequency;
            assert Double.isFinite(loopFrequency) : "Loop=" + lb + " Loop Frequency=" + loopFrequency + " endFrequency=" + loopEndFrequency;
            assert !Double.isNaN(loopFrequency) : "Loop=" + lb + " Loop Frequency=" + loopFrequency + " endFrequency=" + loopEndFrequency;
        }
    } else {
        /*
             * Ideally we would like to use the loop end frequency sum here because it respects
             * control flow sinks (unwinds and deopts) inside the loop (this can be seen in the
             * branch above). However, if we ever exit a loop in compiled code it means we did not
             * do so by an unwind or deopt but a loop exit, thus we ignore the end (and sink)
             * frequencies and compute loop frequency purely based on the exit frequencies.
             */
        double loopExitFrequencySum = 0D;
        for (LoopExitNode lex : lb.loopExits()) {
            Block lexBlock = blockFor(lex);
            assert lexBlock != null;
            assert lexBlock.relativeFrequency >= 0D;
            loopExitFrequencySum += lexBlock.relativeFrequency;
            source = source.combine(lexBlock.frequencySource);
        }
        loopExitFrequencySum = Math.min(1, loopExitFrequencySum);
        loopExitFrequencySum = Math.max(ControlFlowGraph.MIN_RELATIVE_FREQUENCY, loopExitFrequencySum);
        loopFrequency = 1D / loopExitFrequencySum;
        assert Double.isFinite(loopFrequency) : "Loop=" + lb + " Loop Frequency=" + loopFrequency + " lexFrequencySum=" + loopExitFrequencySum;
        assert !Double.isNaN(loopFrequency) : "Loop=" + lb + " Loop Frequency=" + loopFrequency + " lexFrequencySum=" + loopExitFrequencySum;
        if (CFGOptions.DumpEndVersusExitLoopFrequencies.getValue(lb.getOptions())) {
            debugLocalLoopFrequencies(lb, loopFrequency, loopExitFrequencySum);
        }
    }
    localLoopFrequencyData.put(lb, LoopFrequencyData.create(loopFrequency, source));
    return loopFrequency;
}
Also used : ProfileSource(org.graalvm.compiler.nodes.ProfileData.ProfileSource) LoopExitNode(org.graalvm.compiler.nodes.LoopExitNode) LoopEndNode(org.graalvm.compiler.nodes.LoopEndNode)

Example 5 with ProfileSource

use of org.graalvm.compiler.nodes.ProfileData.ProfileSource in project graal by oracle.

the class SwitchFoldable method switchTransformationOptimization.

/**
 * Collapses a cascade of foldables (IfNode, FixedGuard and IntegerSwitch) into a single switch.
 */
default boolean switchTransformationOptimization(SimplifierTool tool) {
    ValueNode switchValue = switchValue();
    assert asNode().isAlive();
    if (switchValue == null || !isInSwitch(switchValue) || (Helper.getParentSwitchNode(this, switchValue) == null && Helper.getChildSwitchNode(this, switchValue) == null)) {
        // Don't bother trying if there is nothing to do.
        return false;
    }
    Stamp switchStamp = switchValue.stamp(NodeView.DEFAULT);
    // Abort if we do not have an int
    if (!(switchStamp instanceof IntegerStamp)) {
        return false;
    }
    if (PrimitiveStamp.getBits(switchStamp) > 32) {
        return false;
    }
    // PlaceHolder for cascade traversal.
    SwitchFoldable iteratingNode = this;
    SwitchFoldable topMostSwitchNode = this;
    // Find top-most foldable.
    while (iteratingNode != null) {
        topMostSwitchNode = iteratingNode;
        iteratingNode = Helper.getParentSwitchNode(iteratingNode, switchValue);
    }
    QuickQueryKeyData keyData = new QuickQueryKeyData();
    QuickQueryList<AbstractBeginNode> successors = new QuickQueryList<>();
    QuickQueryList<AbstractBeginNode> potentiallyUnreachable = new QuickQueryList<>();
    double[] cumulative = { 1.0d };
    double[] totalProbability = { 0.0d };
    iteratingNode = topMostSwitchNode;
    SwitchFoldable lowestSwitchNode = topMostSwitchNode;
    ProfileSource profileSource = topMostSwitchNode.profileSource();
    // If this stays true, we will need to spawn an uniform distribution.
    boolean uninitializedProfiles = true;
    // Go down the if cascade, collecting necessary data
    while (iteratingNode != null) {
        lowestSwitchNode = iteratingNode;
        Helper.updateSwitchData(iteratingNode, keyData, successors, cumulative, totalProbability, potentiallyUnreachable);
        if (!iteratingNode.isNonInitializedProfile()) {
            uninitializedProfiles = false;
        }
        profileSource.combine(iteratingNode.profileSource());
        iteratingNode = Helper.getChildSwitchNode(iteratingNode, switchValue);
    }
    if (keyData.size() < 4 || lowestSwitchNode == topMostSwitchNode) {
        // Abort if it's not worth the hassle
        return false;
    }
    // At that point, we will commit the optimization.
    StructuredGraph graph = asNode().graph();
    // Sort the keys
    keyData.sort();
    /*
         * The total probability might be different than 1 if there was a duplicate key which was
         * erased by another branch whose probability was different (/ex: in the case where a method
         * constituted of only a switch is inlined after a guard for a particular value of that
         * switch). In that case, we need to re-normalize the probabilities. A more "correct" way
         * would be to only re-normalize the probabilities of the switch after the guard, but this
         * cannot be done without an additional overhead.
         */
    totalProbability[0] += cumulative[0];
    assert totalProbability[0] > 0.0d;
    double normalizationFactor = 1 / totalProbability[0];
    // Spawn the required data structures
    int newKeyCount = keyData.list.size();
    int[] keys = new int[newKeyCount];
    double[] keyProbabilities = new double[newKeyCount + 1];
    int[] keySuccessors = new int[newKeyCount + 1];
    int nonDeoptSuccessorCount = Helper.countNonDeoptSuccessors(keyData) + (cumulative[0] > 0.0d ? 1 : 0);
    double uniform = (uninitializedProfiles && nonDeoptSuccessorCount > 0 ? 1 / (double) nonDeoptSuccessorCount : 1.0d);
    // Add default
    keyProbabilities[newKeyCount] = uninitializedProfiles && cumulative[0] > 0.0d ? uniform : normalizationFactor * cumulative[0];
    keySuccessors[newKeyCount] = Helper.addDefault(lowestSwitchNode, successors);
    // Add branches.
    for (int i = 0; i < newKeyCount; i++) {
        SwitchFoldable.KeyData data = keyData.get(i);
        keys[i] = data.key;
        keyProbabilities[i] = uninitializedProfiles && data.keyProbability > 0.0d ? uniform : normalizationFactor * data.keyProbability;
        keySuccessors[i] = data.keySuccessor != KeyData.KEY_UNKNOWN ? data.keySuccessor : keySuccessors[newKeyCount];
    }
    // Spin an adapter if the value is narrower than an int
    ValueNode adapter = null;
    if (((IntegerStamp) switchStamp).getBits() < 32) {
        adapter = graph.addOrUnique(new SignExtendNode(switchValue, 32));
    } else {
        adapter = switchValue;
    }
    // Spawn the switch node
    IntegerSwitchNode toInsert = new IntegerSwitchNode(adapter, successors.size(), keys, keySuccessors, SwitchProbabilityData.create(keyProbabilities, profileSource));
    graph.add(toInsert);
    // Detach the cascade from the graph
    lowestSwitchNode.cutOffLowestCascadeNode();
    iteratingNode = lowestSwitchNode;
    while (iteratingNode != null) {
        if (iteratingNode != lowestSwitchNode) {
            iteratingNode.cutOffCascadeNode();
        }
        iteratingNode = Helper.getParentSwitchNode(iteratingNode, switchValue);
    }
    // Place the new Switch node
    topMostSwitchNode.asNode().replaceAtPredecessor(toInsert);
    topMostSwitchNode.asNode().replaceAtUsages(toInsert);
    // Attach the branches to the switch.
    int pos = 0;
    for (AbstractBeginNode begin : successors.list) {
        if (begin.isUnregistered()) {
            graph.add(begin.next());
            graph.add(begin);
            begin.setNext(begin.next());
        }
        toInsert.setBlockSuccessor(pos++, begin);
    }
    // Remove the cascade and unreachable code
    GraphUtil.killCFG((FixedNode) topMostSwitchNode);
    for (AbstractBeginNode duplicate : potentiallyUnreachable.list) {
        if (duplicate.predecessor() == null) {
            // Make sure the duplicate is not reachable.
            assert duplicate.isAlive();
            GraphUtil.killCFG(duplicate);
        }
    }
    tool.addToWorkList(toInsert);
    return true;
}
Also used : PrimitiveStamp(org.graalvm.compiler.core.common.type.PrimitiveStamp) Stamp(org.graalvm.compiler.core.common.type.Stamp) IntegerStamp(org.graalvm.compiler.core.common.type.IntegerStamp) SignExtendNode(org.graalvm.compiler.nodes.calc.SignExtendNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) ProfileSource(org.graalvm.compiler.nodes.ProfileData.ProfileSource) StructuredGraph(org.graalvm.compiler.nodes.StructuredGraph) IntegerStamp(org.graalvm.compiler.core.common.type.IntegerStamp) ValueNode(org.graalvm.compiler.nodes.ValueNode) IntegerSwitchNode(org.graalvm.compiler.nodes.extended.IntegerSwitchNode)

Aggregations

ProfileSource (org.graalvm.compiler.nodes.ProfileData.ProfileSource)6 ValueNode (org.graalvm.compiler.nodes.ValueNode)2 ArrayList (java.util.ArrayList)1 RuntimeConstraint (jdk.vm.ci.meta.DeoptimizationReason.RuntimeConstraint)1 IntegerStamp (org.graalvm.compiler.core.common.type.IntegerStamp)1 PrimitiveStamp (org.graalvm.compiler.core.common.type.PrimitiveStamp)1 Stamp (org.graalvm.compiler.core.common.type.Stamp)1 NodeSourcePosition (org.graalvm.compiler.graph.NodeSourcePosition)1 BciBlock (org.graalvm.compiler.java.BciBlockMapping.BciBlock)1 AbstractBeginNode (org.graalvm.compiler.nodes.AbstractBeginNode)1 ControlSplitNode (org.graalvm.compiler.nodes.ControlSplitNode)1 LoopBeginNode (org.graalvm.compiler.nodes.LoopBeginNode)1 LoopEndNode (org.graalvm.compiler.nodes.LoopEndNode)1 LoopExitNode (org.graalvm.compiler.nodes.LoopExitNode)1 BranchProbabilityData (org.graalvm.compiler.nodes.ProfileData.BranchProbabilityData)1 StructuredGraph (org.graalvm.compiler.nodes.StructuredGraph)1 SignExtendNode (org.graalvm.compiler.nodes.calc.SignExtendNode)1 IntegerSwitchNode (org.graalvm.compiler.nodes.extended.IntegerSwitchNode)1