2011-06-16 20:22:37 +00:00
|
|
|
//===- MachineBranchProbabilityInfo.cpp - Machine Branch Probability Info -===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This analysis uses probability info stored in Machine Basic Blocks.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "llvm/Instructions.h"
|
|
|
|
#include "llvm/CodeGen/MachineBranchProbabilityInfo.h"
|
|
|
|
#include "llvm/CodeGen/MachineBasicBlock.h"
|
|
|
|
#include "llvm/Support/Debug.h"
|
|
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
|
|
|
|
INITIALIZE_PASS_BEGIN(MachineBranchProbabilityInfo, "machine-branch-prob",
|
|
|
|
"Machine Branch Probability Analysis", false, true)
|
|
|
|
INITIALIZE_PASS_END(MachineBranchProbabilityInfo, "machine-branch-prob",
|
|
|
|
"Machine Branch Probability Analysis", false, true)
|
|
|
|
|
|
|
|
char MachineBranchProbabilityInfo::ID = 0;
|
|
|
|
|
2011-12-20 02:50:00 +00:00
|
|
|
void MachineBranchProbabilityInfo::anchor() { }
|
|
|
|
|
2011-06-16 20:22:37 +00:00
|
|
|
uint32_t MachineBranchProbabilityInfo::
|
2011-12-20 20:03:10 +00:00
|
|
|
getSumForBlock(const MachineBasicBlock *MBB, uint32_t &Scale) const {
|
Fix an overflow bug in MachineBranchProbabilityInfo. This pass relied on
the sum of the edge weights not overflowing uint32, and crashed when
they did. This is generally safe as BranchProbabilityInfo tries to
provide this guarantee. However, the CFG can get modified during codegen
in a way that grows the *sum* of the edge weights. This doesn't seem
unreasonable (imagine just adding more blocks all with the default
weight of 16), but it is hard to come up with a case that actually
triggers 32-bit overflow. Fortuately, the single-source GCC build is
good at this. The solution isn't very pretty, but its no worse than the
previous code. We're already summing all of the edge weights on each
query, we can sum them, check for an overflow, compute a scale, and sum
them again.
I've included a *greatly* reduced test case out of the GCC source that
triggers it. It's a pretty lame test, as it clearly is just barely
triggering the overflow. I'd like to have something that is much more
definitive, but I don't understand the fundamental pattern that triggers
an explosion in the edge weight sums.
The buggy code is duplicated within this file. I'll colapse them into
a single implementation in a subsequent commit.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@144526 91177308-0d34-0410-b5e6-96231b3b80d8
2011-11-14 08:50:16 +00:00
|
|
|
// First we compute the sum with 64-bits of precision, ensuring that cannot
|
|
|
|
// overflow by bounding the number of weights considered. Hopefully no one
|
|
|
|
// actually needs 2^32 successors.
|
|
|
|
assert(MBB->succ_size() < UINT32_MAX);
|
|
|
|
uint64_t Sum = 0;
|
|
|
|
Scale = 1;
|
2011-06-16 20:22:37 +00:00
|
|
|
for (MachineBasicBlock::const_succ_iterator I = MBB->succ_begin(),
|
|
|
|
E = MBB->succ_end(); I != E; ++I) {
|
2012-08-08 01:10:31 +00:00
|
|
|
uint32_t Weight = getEdgeWeight(MBB, *I);
|
2011-06-16 20:22:37 +00:00
|
|
|
Sum += Weight;
|
|
|
|
}
|
|
|
|
|
Fix an overflow bug in MachineBranchProbabilityInfo. This pass relied on
the sum of the edge weights not overflowing uint32, and crashed when
they did. This is generally safe as BranchProbabilityInfo tries to
provide this guarantee. However, the CFG can get modified during codegen
in a way that grows the *sum* of the edge weights. This doesn't seem
unreasonable (imagine just adding more blocks all with the default
weight of 16), but it is hard to come up with a case that actually
triggers 32-bit overflow. Fortuately, the single-source GCC build is
good at this. The solution isn't very pretty, but its no worse than the
previous code. We're already summing all of the edge weights on each
query, we can sum them, check for an overflow, compute a scale, and sum
them again.
I've included a *greatly* reduced test case out of the GCC source that
triggers it. It's a pretty lame test, as it clearly is just barely
triggering the overflow. I'd like to have something that is much more
definitive, but I don't understand the fundamental pattern that triggers
an explosion in the edge weight sums.
The buggy code is duplicated within this file. I'll colapse them into
a single implementation in a subsequent commit.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@144526 91177308-0d34-0410-b5e6-96231b3b80d8
2011-11-14 08:50:16 +00:00
|
|
|
// If the computed sum fits in 32-bits, we're done.
|
|
|
|
if (Sum <= UINT32_MAX)
|
|
|
|
return Sum;
|
|
|
|
|
|
|
|
// Otherwise, compute the scale necessary to cause the weights to fit, and
|
|
|
|
// re-sum with that scale applied.
|
|
|
|
assert((Sum / UINT32_MAX) < UINT32_MAX);
|
|
|
|
Scale = (Sum / UINT32_MAX) + 1;
|
|
|
|
Sum = 0;
|
|
|
|
for (MachineBasicBlock::const_succ_iterator I = MBB->succ_begin(),
|
|
|
|
E = MBB->succ_end(); I != E; ++I) {
|
2012-08-08 01:10:31 +00:00
|
|
|
uint32_t Weight = getEdgeWeight(MBB, *I);
|
Fix an overflow bug in MachineBranchProbabilityInfo. This pass relied on
the sum of the edge weights not overflowing uint32, and crashed when
they did. This is generally safe as BranchProbabilityInfo tries to
provide this guarantee. However, the CFG can get modified during codegen
in a way that grows the *sum* of the edge weights. This doesn't seem
unreasonable (imagine just adding more blocks all with the default
weight of 16), but it is hard to come up with a case that actually
triggers 32-bit overflow. Fortuately, the single-source GCC build is
good at this. The solution isn't very pretty, but its no worse than the
previous code. We're already summing all of the edge weights on each
query, we can sum them, check for an overflow, compute a scale, and sum
them again.
I've included a *greatly* reduced test case out of the GCC source that
triggers it. It's a pretty lame test, as it clearly is just barely
triggering the overflow. I'd like to have something that is much more
definitive, but I don't understand the fundamental pattern that triggers
an explosion in the edge weight sums.
The buggy code is duplicated within this file. I'll colapse them into
a single implementation in a subsequent commit.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@144526 91177308-0d34-0410-b5e6-96231b3b80d8
2011-11-14 08:50:16 +00:00
|
|
|
Sum += Weight / Scale;
|
|
|
|
}
|
|
|
|
assert(Sum <= UINT32_MAX);
|
2011-06-16 20:22:37 +00:00
|
|
|
return Sum;
|
|
|
|
}
|
|
|
|
|
2012-08-08 01:10:31 +00:00
|
|
|
uint32_t
|
|
|
|
MachineBranchProbabilityInfo::getEdgeWeight(const MachineBasicBlock *Src,
|
|
|
|
const MachineBasicBlock *Dst) const {
|
2011-06-16 20:22:37 +00:00
|
|
|
uint32_t Weight = Src->getSuccWeight(Dst);
|
|
|
|
if (!Weight)
|
|
|
|
return DEFAULT_WEIGHT;
|
|
|
|
return Weight;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool MachineBranchProbabilityInfo::isEdgeHot(MachineBasicBlock *Src,
|
|
|
|
MachineBasicBlock *Dst) const {
|
|
|
|
// Hot probability is at least 4/5 = 80%
|
2011-10-28 11:14:31 +00:00
|
|
|
// FIXME: Compare against a static "hot" BranchProbability.
|
|
|
|
return getEdgeProbability(Src, Dst) > BranchProbability(4, 5);
|
2011-06-16 20:22:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
MachineBasicBlock *
|
|
|
|
MachineBranchProbabilityInfo::getHotSucc(MachineBasicBlock *MBB) const {
|
|
|
|
uint32_t MaxWeight = 0;
|
|
|
|
MachineBasicBlock *MaxSucc = 0;
|
|
|
|
for (MachineBasicBlock::const_succ_iterator I = MBB->succ_begin(),
|
|
|
|
E = MBB->succ_end(); I != E; ++I) {
|
2012-08-08 01:10:31 +00:00
|
|
|
uint32_t Weight = getEdgeWeight(MBB, *I);
|
2011-06-16 20:22:37 +00:00
|
|
|
if (Weight > MaxWeight) {
|
|
|
|
MaxWeight = Weight;
|
2011-11-14 08:55:59 +00:00
|
|
|
MaxSucc = *I;
|
2011-06-16 20:22:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-11-14 08:55:59 +00:00
|
|
|
if (getEdgeProbability(MBB, MaxSucc) >= BranchProbability(4, 5))
|
2011-06-16 20:22:37 +00:00
|
|
|
return MaxSucc;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
BranchProbability
|
|
|
|
MachineBranchProbabilityInfo::getEdgeProbability(MachineBasicBlock *Src,
|
|
|
|
MachineBasicBlock *Dst) const {
|
Fix an overflow bug in MachineBranchProbabilityInfo. This pass relied on
the sum of the edge weights not overflowing uint32, and crashed when
they did. This is generally safe as BranchProbabilityInfo tries to
provide this guarantee. However, the CFG can get modified during codegen
in a way that grows the *sum* of the edge weights. This doesn't seem
unreasonable (imagine just adding more blocks all with the default
weight of 16), but it is hard to come up with a case that actually
triggers 32-bit overflow. Fortuately, the single-source GCC build is
good at this. The solution isn't very pretty, but its no worse than the
previous code. We're already summing all of the edge weights on each
query, we can sum them, check for an overflow, compute a scale, and sum
them again.
I've included a *greatly* reduced test case out of the GCC source that
triggers it. It's a pretty lame test, as it clearly is just barely
triggering the overflow. I'd like to have something that is much more
definitive, but I don't understand the fundamental pattern that triggers
an explosion in the edge weight sums.
The buggy code is duplicated within this file. I'll colapse them into
a single implementation in a subsequent commit.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@144526 91177308-0d34-0410-b5e6-96231b3b80d8
2011-11-14 08:50:16 +00:00
|
|
|
uint32_t Scale = 1;
|
|
|
|
uint32_t D = getSumForBlock(Src, Scale);
|
|
|
|
uint32_t N = getEdgeWeight(Src, Dst) / Scale;
|
2011-06-16 20:22:37 +00:00
|
|
|
|
|
|
|
return BranchProbability(N, D);
|
|
|
|
}
|
|
|
|
|
|
|
|
raw_ostream &MachineBranchProbabilityInfo::
|
|
|
|
printEdgeProbability(raw_ostream &OS, MachineBasicBlock *Src,
|
|
|
|
MachineBasicBlock *Dst) const {
|
|
|
|
|
|
|
|
const BranchProbability Prob = getEdgeProbability(Src, Dst);
|
|
|
|
OS << "edge MBB#" << Src->getNumber() << " -> MBB#" << Dst->getNumber()
|
|
|
|
<< " probability is " << Prob
|
|
|
|
<< (isEdgeHot(Src, Dst) ? " [HOT edge]\n" : "\n");
|
|
|
|
|
|
|
|
return OS;
|
|
|
|
}
|