Skip to content

Commit ec7e92a

Browse files
maksfbmemfrob
authored andcommitted
[BOLT][Refactoring] Move basic block reordering to BinaryPasses
Summary: Refactor basic block reordering code out of the BinaryFunction. BinaryFunction::isSplit() is now checking if the first and the last blocks in the layout belong to the same fragment. As a result, it no longer returns true for functions that have their cold part optimized away. Change type for returned "size" from unsigned to size_t. Fix lines over 80 characters long. (cherry picked from FBD6250825)
1 parent bab1c5d commit ec7e92a

File tree

5 files changed

+278
-280
lines changed

5 files changed

+278
-280
lines changed

bolt/BinaryBasicBlock.h

Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ class BinaryBasicBlock {
150150
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
151151

152152
bool empty() const { return Instructions.empty(); }
153-
unsigned size() const { return (unsigned)Instructions.size(); }
153+
size_t size() const { return Instructions.size(); }
154154
MCInst &front() { return Instructions.front(); }
155155
MCInst &back() { return Instructions.back(); }
156156
const MCInst &front() const { return Instructions.front(); }
@@ -176,9 +176,11 @@ class BinaryBasicBlock {
176176
using const_lp_iterator = decltype(LandingPads)::const_iterator;
177177

178178
using pred_reverse_iterator = std::reverse_iterator<pred_iterator>;
179-
using const_pred_reverse_iterator = std::reverse_iterator<const_pred_iterator>;
179+
using const_pred_reverse_iterator =
180+
std::reverse_iterator<const_pred_iterator>;
180181
using succ_reverse_iterator = std::reverse_iterator<succ_iterator>;
181-
using const_succ_reverse_iterator = std::reverse_iterator<const_succ_iterator>;
182+
using const_succ_reverse_iterator =
183+
std::reverse_iterator<const_succ_iterator>;
182184

183185
pred_iterator pred_begin() { return Predecessors.begin(); }
184186
const_pred_iterator pred_begin() const { return Predecessors.begin(); }
@@ -192,8 +194,8 @@ class BinaryBasicBlock {
192194
{ return Predecessors.rend(); }
193195
const_pred_reverse_iterator pred_rend() const
194196
{ return Predecessors.rend(); }
195-
unsigned pred_size() const {
196-
return (unsigned)Predecessors.size();
197+
size_t pred_size() const {
198+
return Predecessors.size();
197199
}
198200
bool pred_empty() const { return Predecessors.empty(); }
199201

@@ -209,17 +211,17 @@ class BinaryBasicBlock {
209211
{ return Successors.rend(); }
210212
const_succ_reverse_iterator succ_rend() const
211213
{ return Successors.rend(); }
212-
unsigned succ_size() const {
213-
return (unsigned)Successors.size();
214+
size_t succ_size() const {
215+
return Successors.size();
214216
}
215217
bool succ_empty() const { return Successors.empty(); }
216218

217219
throw_iterator throw_begin() { return Throwers.begin(); }
218220
const_throw_iterator throw_begin() const { return Throwers.begin(); }
219221
throw_iterator throw_end() { return Throwers.end(); }
220222
const_throw_iterator throw_end() const { return Throwers.end(); }
221-
unsigned throw_size() const {
222-
return (unsigned)Throwers.size();
223+
size_t throw_size() const {
224+
return Throwers.size();
223225
}
224226
bool throw_empty() const { return Throwers.empty(); }
225227
bool isLandingPad() const { return !Throwers.empty(); }
@@ -228,8 +230,8 @@ class BinaryBasicBlock {
228230
const_lp_iterator lp_begin() const { return LandingPads.begin(); }
229231
lp_iterator lp_end() { return LandingPads.end(); }
230232
const_lp_iterator lp_end() const { return LandingPads.end(); }
231-
unsigned lp_size() const {
232-
return (unsigned)LandingPads.size();
233+
size_t lp_size() const {
234+
return LandingPads.size();
233235
}
234236
bool lp_empty() const { return LandingPads.empty(); }
235237

@@ -273,23 +275,28 @@ class BinaryBasicBlock {
273275
using const_branch_info_reverse_iterator =
274276
std::reverse_iterator<const_branch_info_iterator>;
275277

276-
branch_info_iterator branch_info_begin() { return BranchInfo.begin(); }
277-
branch_info_iterator branch_info_end() { return BranchInfo.end(); }
278-
const_branch_info_iterator branch_info_begin() const
279-
{ return BranchInfo.begin(); }
280-
const_branch_info_iterator branch_info_end() const
281-
{ return BranchInfo.end(); }
282-
branch_info_reverse_iterator branch_info_rbegin()
283-
{ return BranchInfo.rbegin(); }
284-
branch_info_reverse_iterator branch_info_rend()
285-
{ return BranchInfo.rend(); }
286-
const_branch_info_reverse_iterator branch_info_rbegin() const
287-
{ return BranchInfo.rbegin(); }
288-
const_branch_info_reverse_iterator branch_info_rend() const
289-
{ return BranchInfo.rend(); }
290-
unsigned branch_info_size() const {
291-
return (unsigned)BranchInfo.size();
278+
branch_info_iterator branch_info_begin() { return BranchInfo.begin(); }
279+
branch_info_iterator branch_info_end() { return BranchInfo.end(); }
280+
const_branch_info_iterator branch_info_begin() const {
281+
return BranchInfo.begin();
292282
}
283+
const_branch_info_iterator branch_info_end() const {
284+
return BranchInfo.end();
285+
}
286+
branch_info_reverse_iterator branch_info_rbegin() {
287+
return BranchInfo.rbegin();
288+
}
289+
branch_info_reverse_iterator branch_info_rend() {
290+
return BranchInfo.rend();
291+
}
292+
const_branch_info_reverse_iterator branch_info_rbegin() const {
293+
return BranchInfo.rbegin();
294+
}
295+
const_branch_info_reverse_iterator branch_info_rend() const {
296+
return BranchInfo.rend();
297+
}
298+
299+
size_t branch_info_size() const { return BranchInfo.size(); }
293300
bool branch_info_empty() const { return BranchInfo.empty(); }
294301

295302
inline iterator_range<branch_info_iterator> branch_info() {

bolt/BinaryFunction.cpp

Lines changed: 22 additions & 187 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
#include "BinaryFunction.h"
1515
#include "DataReader.h"
1616
#include "Passes/MCF.h"
17-
#include "Passes/ReorderAlgorithm.h"
1817
#include "llvm/ADT/StringRef.h"
1918
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
2019
#include "llvm/MC/MCAsmInfo.h"
@@ -53,18 +52,32 @@ extern cl::opt<bool> Relocs;
5352
extern cl::opt<bool> UpdateDebugSections;
5453
extern cl::opt<IndirectCallPromotionType> IndirectCallPromotion;
5554
extern cl::opt<unsigned> Verbosity;
56-
extern cl::opt<unsigned> PrintFuncStat;
5755

5856
static cl::opt<bool>
59-
AggressiveSplitting("split-all-cold",
60-
cl::desc("outline as many cold basic blocks as possible"),
57+
AlignBlocks("align-blocks",
58+
cl::desc("try to align BBs inserting nops"),
6159
cl::ZeroOrMore,
6260
cl::cat(BoltOptCategory));
6361

64-
static cl::opt<bool>
65-
AlignBlocks("align-blocks",
66-
cl::desc("try to align BBs inserting nops"),
62+
static cl::opt<MCFCostFunction>
63+
DoMCF("mcf",
64+
cl::desc("solve a min cost flow problem on the CFG to fix edge counts "
65+
"(default=disable)"),
66+
cl::init(MCF_DISABLE),
67+
cl::values(
68+
clEnumValN(MCF_DISABLE, "none",
69+
"disable MCF"),
70+
clEnumValN(MCF_LINEAR, "linear",
71+
"cost function is inversely proportional to edge count"),
72+
clEnumValN(MCF_QUADRATIC, "quadratic",
73+
"cost function is inversely proportional to edge count squared"),
74+
clEnumValN(MCF_LOG, "log",
75+
"cost function is inversely proportional to log of edge count"),
76+
clEnumValN(MCF_BLAMEFTS, "blamefts",
77+
"tune cost to blame fall-through edges for surplus flow"),
78+
clEnumValEnd),
6779
cl::ZeroOrMore,
80+
cl::Hidden,
6881
cl::cat(BoltOptCategory));
6982

7083
static cl::opt<bool>
@@ -123,34 +136,6 @@ PrintOnly("print-only",
123136
cl::Hidden,
124137
cl::cat(BoltCategory));
125138

126-
static cl::opt<bool>
127-
SplitEH("split-eh",
128-
cl::desc("split C++ exception handling code (experimental)"),
129-
cl::ZeroOrMore,
130-
cl::Hidden,
131-
cl::cat(BoltOptCategory));
132-
133-
cl::opt<MCFCostFunction>
134-
DoMCF("mcf",
135-
cl::desc("solve a min cost flow problem on the CFG to fix edge counts "
136-
"(default=disable)"),
137-
cl::init(MCF_DISABLE),
138-
cl::values(
139-
clEnumValN(MCF_DISABLE, "none",
140-
"disable MCF"),
141-
clEnumValN(MCF_LINEAR, "linear",
142-
"cost function is inversely proportional to edge count"),
143-
clEnumValN(MCF_QUADRATIC, "quadratic",
144-
"cost function is inversely proportional to edge count squared"),
145-
clEnumValN(MCF_LOG, "log",
146-
"cost function is inversely proportional to log of edge count"),
147-
clEnumValN(MCF_BLAMEFTS, "blamefts",
148-
"tune cost to blame fall-through edges for surplus flow"),
149-
clEnumValEnd),
150-
cl::ZeroOrMore,
151-
cl::Hidden,
152-
cl::cat(BoltOptCategory));
153-
154139
bool shouldPrint(const BinaryFunction &Function) {
155140
if (PrintOnly.empty())
156141
return true;
@@ -386,8 +371,8 @@ void BinaryFunction::print(raw_ostream &OS, std::string Annotation,
386371
<< "\n Orc Section : " << getCodeSectionName()
387372
<< "\n LSDA : 0x" << Twine::utohexstr(getLSDAAddress())
388373
<< "\n IsSimple : " << IsSimple
389-
<< "\n IsSplit : " << IsSplit
390-
<< "\n BB Count : " << BasicBlocksLayout.size();
374+
<< "\n IsSplit : " << isSplit()
375+
<< "\n BB Count : " << size();
391376

392377
if (hasCFG()) {
393378
OS << "\n Hash : " << Twine::utohexstr(hash());
@@ -2415,68 +2400,6 @@ bool BinaryFunction::fixCFIState() {
24152400
return true;
24162401
}
24172402

2418-
void BinaryFunction::modifyLayout(LayoutType Type, bool MinBranchClusters,
2419-
bool Split) {
2420-
if (BasicBlocksLayout.empty() || Type == LT_NONE)
2421-
return;
2422-
2423-
BasicBlockOrderType NewLayout;
2424-
std::unique_ptr<ReorderAlgorithm> Algo;
2425-
2426-
// Cannot do optimal layout without profile.
2427-
if (Type != LT_REVERSE && !hasValidProfile())
2428-
return;
2429-
2430-
if (Type == LT_REVERSE) {
2431-
Algo.reset(new ReverseReorderAlgorithm());
2432-
}
2433-
else if (BasicBlocksLayout.size() <= FUNC_SIZE_THRESHOLD &&
2434-
Type != LT_OPTIMIZE_SHUFFLE) {
2435-
// Work on optimal solution if problem is small enough
2436-
DEBUG(dbgs() << "finding optimal block layout for " << *this << "\n");
2437-
Algo.reset(new OptimalReorderAlgorithm());
2438-
}
2439-
else {
2440-
DEBUG(dbgs() << "running block layout heuristics on " << *this << "\n");
2441-
2442-
std::unique_ptr<ClusterAlgorithm> CAlgo;
2443-
if (MinBranchClusters)
2444-
CAlgo.reset(new MinBranchGreedyClusterAlgorithm());
2445-
else
2446-
CAlgo.reset(new PHGreedyClusterAlgorithm());
2447-
2448-
switch(Type) {
2449-
case LT_OPTIMIZE:
2450-
Algo.reset(new OptimizeReorderAlgorithm(std::move(CAlgo)));
2451-
break;
2452-
2453-
case LT_OPTIMIZE_BRANCH:
2454-
Algo.reset(new OptimizeBranchReorderAlgorithm(std::move(CAlgo)));
2455-
break;
2456-
2457-
case LT_OPTIMIZE_CACHE:
2458-
Algo.reset(new OptimizeCacheReorderAlgorithm(std::move(CAlgo)));
2459-
break;
2460-
2461-
case LT_OPTIMIZE_SHUFFLE:
2462-
Algo.reset(new RandomClusterReorderAlgorithm(std::move(CAlgo)));
2463-
break;
2464-
2465-
default:
2466-
llvm_unreachable("unexpected layout type");
2467-
}
2468-
}
2469-
2470-
Algo->reorderBasicBlocks(*this, NewLayout);
2471-
if (opts::PrintFuncStat > 0)
2472-
BasicBlocksPreviousLayout = BasicBlocksLayout;
2473-
BasicBlocksLayout.clear();
2474-
BasicBlocksLayout.swap(NewLayout);
2475-
2476-
if (Split)
2477-
splitFunction();
2478-
}
2479-
24802403
uint64_t BinaryFunction::getInstructionCount() const {
24812404
uint64_t Count = 0;
24822405
for (auto &Block : BasicBlocksLayout) {
@@ -2486,12 +2409,10 @@ uint64_t BinaryFunction::getInstructionCount() const {
24862409
}
24872410

24882411
bool BinaryFunction::hasLayoutChanged() const {
2489-
assert(opts::PrintFuncStat > 0 && "PrintFuncStat flag is not on");
24902412
return BasicBlocksPreviousLayout != BasicBlocksLayout;
24912413
}
24922414

24932415
uint64_t BinaryFunction::getEditDistance() const {
2494-
assert(opts::PrintFuncStat > 0 && "PrintFuncStat flag is not on");
24952416
const auto LayoutSize = BasicBlocksPreviousLayout.size();
24962417
if (LayoutSize < 2) {
24972418
return 0;
@@ -2899,83 +2820,6 @@ void BinaryFunction::fixBranches() {
28992820
assert(validateCFG() && "Invalid CFG detected after fixing branches");
29002821
}
29012822

2902-
void BinaryFunction::splitFunction() {
2903-
bool AllCold = true;
2904-
for (BinaryBasicBlock *BB : BasicBlocksLayout) {
2905-
auto ExecCount = BB->getExecutionCount();
2906-
if (ExecCount == BinaryBasicBlock::COUNT_NO_PROFILE)
2907-
return;
2908-
if (ExecCount != 0)
2909-
AllCold = false;
2910-
}
2911-
2912-
if (AllCold)
2913-
return;
2914-
2915-
assert(BasicBlocksLayout.size() > 0);
2916-
2917-
// Never outline the first basic block.
2918-
BasicBlocks.front()->setCanOutline(false);
2919-
for (auto BB : BasicBlocks) {
2920-
if (!BB->canOutline())
2921-
continue;
2922-
if (BB->getExecutionCount() != 0) {
2923-
BB->setCanOutline(false);
2924-
continue;
2925-
}
2926-
if (hasEHRanges() && !opts::SplitEH) {
2927-
// We cannot move landing pads (or rather entry points for landing
2928-
// pads).
2929-
if (BB->isLandingPad()) {
2930-
BB->setCanOutline(false);
2931-
continue;
2932-
}
2933-
// We cannot move a block that can throw since exception-handling
2934-
// runtime cannot deal with split functions. However, if we can guarantee
2935-
// that the block never throws, it is safe to move the block to
2936-
// decrease the size of the function.
2937-
for (auto &Instr : *BB) {
2938-
if (BC.MIA->isInvoke(Instr)) {
2939-
BB->setCanOutline(false);
2940-
break;
2941-
}
2942-
}
2943-
}
2944-
}
2945-
2946-
if (opts::AggressiveSplitting) {
2947-
// All blocks with 0 count that we can move go to the end of the function.
2948-
// Even if they were natural to cluster formation and were seen in-between
2949-
// hot basic blocks.
2950-
std::stable_sort(BasicBlocksLayout.begin(), BasicBlocksLayout.end(),
2951-
[&] (BinaryBasicBlock *A, BinaryBasicBlock *B) {
2952-
return A->canOutline() < B->canOutline();
2953-
});
2954-
} else if (hasEHRanges() && !opts::SplitEH) {
2955-
// Typically functions with exception handling have landing pads at the end.
2956-
// We cannot move beginning of landing pads, but we can move 0-count blocks
2957-
// comprising landing pads to the end and thus facilitate splitting.
2958-
auto FirstLP = BasicBlocksLayout.begin();
2959-
while ((*FirstLP)->isLandingPad())
2960-
++FirstLP;
2961-
2962-
std::stable_sort(FirstLP, BasicBlocksLayout.end(),
2963-
[&] (BinaryBasicBlock *A, BinaryBasicBlock *B) {
2964-
return A->canOutline() < B->canOutline();
2965-
});
2966-
}
2967-
2968-
// Separate hot from cold starting from the bottom.
2969-
for (auto I = BasicBlocksLayout.rbegin(), E = BasicBlocksLayout.rend();
2970-
I != E; ++I) {
2971-
BinaryBasicBlock *BB = *I;
2972-
if (!BB->canOutline())
2973-
break;
2974-
BB->setIsCold(true);
2975-
IsSplit = true;
2976-
}
2977-
}
2978-
29792823
void BinaryFunction::propagateGnuArgsSizeInfo() {
29802824
assert(CurrentState == State::CFG && "unexpected function state");
29812825

@@ -3443,15 +3287,6 @@ void BinaryFunction::updateLayout(BinaryBasicBlock* Start,
34433287
updateLayoutIndices();
34443288
}
34453289

3446-
void BinaryFunction::updateLayout(LayoutType Type,
3447-
bool MinBranchClusters,
3448-
bool Split) {
3449-
// Recompute layout with original parameters.
3450-
BasicBlocksLayout = BasicBlocks;
3451-
modifyLayout(Type, MinBranchClusters, Split);
3452-
updateLayoutIndices();
3453-
}
3454-
34553290
bool BinaryFunction::replaceJumpTableEntryIn(BinaryBasicBlock *BB,
34563291
BinaryBasicBlock *OldDest,
34573292
BinaryBasicBlock *NewDest) {

0 commit comments

Comments
 (0)