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;
}
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;
}
}
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);
}
}
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;
}
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;
}
Aggregations