forked from OSchip/llvm-project
[BOLT] Expand BOLT report for basic block ordering
Summary: Add a new positional option onto bolt: "-print-function-statistics=<uint64>" which prints information about block ordering for requested number of functions. (cherry picked from FBD5105323)
This commit is contained in:
parent
ea53066287
commit
eb63a0b295
|
@ -53,6 +53,7 @@ extern cl::opt<bool> Relocs;
|
|||
extern cl::opt<bool> UpdateDebugSections;
|
||||
extern cl::opt<IndirectCallPromotionType> IndirectCallPromotion;
|
||||
extern cl::opt<unsigned> Verbosity;
|
||||
extern cl::opt<unsigned> PrintFuncStat;
|
||||
|
||||
static cl::opt<bool>
|
||||
AggressiveSplitting("split-all-cold",
|
||||
|
@ -2538,6 +2539,8 @@ void BinaryFunction::modifyLayout(LayoutType Type, bool MinBranchClusters,
|
|||
}
|
||||
|
||||
Algo->reorderBasicBlocks(*this, NewLayout);
|
||||
if (opts::PrintFuncStat > 0)
|
||||
BasicBlocksPreviousLayout = BasicBlocksLayout;
|
||||
BasicBlocksLayout.clear();
|
||||
BasicBlocksLayout.swap(NewLayout);
|
||||
|
||||
|
@ -2545,6 +2548,49 @@ void BinaryFunction::modifyLayout(LayoutType Type, bool MinBranchClusters,
|
|||
splitFunction();
|
||||
}
|
||||
|
||||
uint64_t BinaryFunction::getInstructionCount() const {
|
||||
uint64_t Count = 0;
|
||||
for (auto &Block : BasicBlocksLayout) {
|
||||
Count += Block->getNumNonPseudos();
|
||||
}
|
||||
return Count;
|
||||
}
|
||||
|
||||
bool BinaryFunction::hasLayoutChanged() const {
|
||||
assert(opts::PrintFuncStat > 0 && "PrintFuncStat flag is not on");
|
||||
return BasicBlocksPreviousLayout != BasicBlocksLayout;
|
||||
}
|
||||
|
||||
uint64_t BinaryFunction::getEditDistance() const {
|
||||
assert(opts::PrintFuncStat > 0 && "PrintFuncStat flag is not on");
|
||||
const auto LayoutSize = BasicBlocksPreviousLayout.size();
|
||||
if (LayoutSize < 2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<std::vector<uint64_t>> ChangeMatrix(
|
||||
LayoutSize + 1, std::vector<uint64_t>(LayoutSize + 1));
|
||||
|
||||
for (uint64_t I = 0; I <= LayoutSize; ++I) {
|
||||
ChangeMatrix[I][0] = I;
|
||||
ChangeMatrix[0][I] = I;
|
||||
}
|
||||
|
||||
for (uint64_t I = 1; I <= LayoutSize; ++I) {
|
||||
for (uint64_t J = 1; J <= LayoutSize; ++J) {
|
||||
if (BasicBlocksPreviousLayout[I] != BasicBlocksLayout[J]) {
|
||||
ChangeMatrix[I][J] =
|
||||
std::min(std::min(ChangeMatrix[I - 1][J], ChangeMatrix[I][J - 1]),
|
||||
ChangeMatrix[I - 1][J - 1]) + 1;
|
||||
} else {
|
||||
ChangeMatrix[I][J] = ChangeMatrix[I - 1][J - 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ChangeMatrix[LayoutSize][LayoutSize];
|
||||
}
|
||||
|
||||
void BinaryFunction::emitBody(MCStreamer &Streamer, bool EmitColdPart) {
|
||||
int64_t CurrentGnuArgsSize = 0;
|
||||
for (auto BB : layout()) {
|
||||
|
|
|
@ -694,6 +694,8 @@ private:
|
|||
BasicBlockListType BasicBlocks;
|
||||
BasicBlockListType DeletedBasicBlocks;
|
||||
BasicBlockOrderType BasicBlocksLayout;
|
||||
/// Previous layout replaced by modifyLayout
|
||||
BasicBlockOrderType BasicBlocksPreviousLayout;
|
||||
|
||||
/// BasicBlockOffsets are used during CFG construction to map from code
|
||||
/// offsets to BinaryBasicBlocks. Any modifications made to the CFG
|
||||
|
@ -1711,6 +1713,17 @@ public:
|
|||
/// and size.
|
||||
uint64_t getFunctionScore();
|
||||
|
||||
/// Return true if the layout has been changed by basic block reordering,
|
||||
/// false otherwise.
|
||||
bool hasLayoutChanged() const;
|
||||
|
||||
/// Get the edit distance of the new layout with respect to the previous
|
||||
/// layout after basic block reordering.
|
||||
uint64_t getEditDistance() const;
|
||||
|
||||
/// Get the number of instructions within this function.
|
||||
uint64_t getInstructionCount() const;
|
||||
|
||||
const CFIInstrMapType &getFDEProgram() const {
|
||||
return FrameInstructions;
|
||||
}
|
||||
|
|
|
@ -97,6 +97,13 @@ PrintSortedBy("print-sorted-by",
|
|||
cl::ZeroOrMore,
|
||||
cl::cat(BoltOptCategory));
|
||||
|
||||
cl::opt<unsigned>
|
||||
PrintFuncStat("print-function-statistics",
|
||||
cl::desc("print statistics about basic block ordering"),
|
||||
cl::init(0),
|
||||
cl::ZeroOrMore,
|
||||
cl::cat(BoltOptCategory));
|
||||
|
||||
static cl::opt<bolt::BinaryFunction::LayoutType>
|
||||
ReorderBlocks("reorder-blocks",
|
||||
cl::desc("change layout of basic blocks in a function"),
|
||||
|
@ -293,25 +300,64 @@ bool ReorderBasicBlocks::shouldPrint(const BinaryFunction &BF) const {
|
|||
}
|
||||
|
||||
void ReorderBasicBlocks::runOnFunctions(
|
||||
BinaryContext &BC,
|
||||
std::map<uint64_t, BinaryFunction> &BFs,
|
||||
std::set<uint64_t> &LargeFunctions) {
|
||||
BinaryContext &BC,
|
||||
std::map<uint64_t, BinaryFunction> &BFs,
|
||||
std::set<uint64_t> &LargeFunctions) {
|
||||
if (opts::ReorderBlocks == BinaryFunction::LT_NONE)
|
||||
return;
|
||||
|
||||
uint64_t ModifiedFuncCount = 0;
|
||||
for (auto &It : BFs) {
|
||||
auto &Function = It.second;
|
||||
|
||||
if (!shouldOptimize(Function))
|
||||
continue;
|
||||
if (!shouldOptimize(Function))
|
||||
continue;
|
||||
|
||||
const bool ShouldSplit =
|
||||
(opts::SplitFunctions == BinaryFunction::ST_ALL) ||
|
||||
(opts::SplitFunctions == BinaryFunction::ST_EH &&
|
||||
Function.hasEHRanges()) ||
|
||||
(LargeFunctions.find(It.first) != LargeFunctions.end());
|
||||
(opts::SplitFunctions == BinaryFunction::ST_ALL) ||
|
||||
(opts::SplitFunctions == BinaryFunction::ST_EH &&
|
||||
Function.hasEHRanges()) ||
|
||||
(LargeFunctions.find(It.first) != LargeFunctions.end());
|
||||
Function.modifyLayout(opts::ReorderBlocks, opts::MinBranchClusters,
|
||||
ShouldSplit);
|
||||
|
||||
if (opts::PrintFuncStat > 0 && Function.hasLayoutChanged()) {
|
||||
++ModifiedFuncCount;
|
||||
}
|
||||
}
|
||||
|
||||
if (opts::PrintFuncStat > 0) {
|
||||
raw_ostream &OS = outs();
|
||||
// Copy all the values into vector in order to sort them
|
||||
std::map<uint64_t, BinaryFunction &> ScoreMap;
|
||||
for (auto It = BFs.begin(); It != BFs.end(); ++It) {
|
||||
ScoreMap.insert(std::pair<uint64_t, BinaryFunction &>(
|
||||
It->second.getFunctionScore(), It->second));
|
||||
}
|
||||
|
||||
OS << "\nBOLT-INFO: Printing Function Statistics:\n\n";
|
||||
OS << " There are " << BFs.size() << " functions in total. \n";
|
||||
OS << " Number of functions being modified: " << ModifiedFuncCount
|
||||
<< "\n";
|
||||
OS << " User asks for detailed information on top "
|
||||
<< opts::PrintFuncStat << " functions. (Ranked by function score)"
|
||||
<< "\n\n";
|
||||
uint64_t I = 0;
|
||||
for (std::map<uint64_t, BinaryFunction &>::reverse_iterator
|
||||
Rit = ScoreMap.rbegin();
|
||||
Rit != ScoreMap.rend() && I < opts::PrintFuncStat; ++Rit, ++I) {
|
||||
auto &Function = Rit->second;
|
||||
|
||||
OS << " Information for function of top: " << (I + 1) << ": \n";
|
||||
OS << " Function Score is: " << Function.getFunctionScore()
|
||||
<< "\n";
|
||||
OS << " There are " << Function.size()
|
||||
<< " number of blocks in this function.\n";
|
||||
OS << " There are " << Function.getInstructionCount()
|
||||
<< " number of instructions in this function.\n";
|
||||
OS << " The edit distance for this function is: "
|
||||
<< Function.getEditDistance() << "\n\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue