blob: 6e81801abf06d4bf37015abc2abde02bcaa41b23 [file] [log] [blame]
Sriraman Tallamdf082ac2020-03-16 15:56:02 -07001//===-- BBSectionsPrepare.cpp ---=========---------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// BBSectionsPrepare implementation.
10//
11// The purpose of this pass is to assign sections to basic blocks when
Rahman Lavaee4ddf7ab2020-04-13 12:12:34 -070012// -fbasicblock-sections= option is used. Exception landing pad blocks are
13// specially handled by grouping them in a single section. Further, with
14// profile information only the subset of basic blocks with profiles are placed
15// in a separate section and the rest are grouped in a cold section.
Sriraman Tallamdf082ac2020-03-16 15:56:02 -070016//
17// Basic Block Sections
18// ====================
19//
Rahman Lavaee4ddf7ab2020-04-13 12:12:34 -070020// With option, -fbasicblock-sections=, each basic block could be placed in a
21// unique ELF text section in the object file along with a symbol labelling the
22// basic block. The linker can then order the basic block sections in any
23// arbitrary sequence which when done correctly can encapsulate block layout,
24// function layout and function splitting optimizations. However, there are a
25// couple of challenges to be addressed for this to be feasible:
Sriraman Tallamdf082ac2020-03-16 15:56:02 -070026//
Rahman Lavaee4ddf7ab2020-04-13 12:12:34 -070027// 1. The compiler must not allow any implicit fall-through between any two
28// adjacent basic blocks as they could be reordered at link time to be
29// non-adjacent. In other words, the compiler must make a fall-through
30// between adjacent basic blocks explicit by retaining the direct jump
31// instruction that jumps to the next basic block.
Sriraman Tallamdf082ac2020-03-16 15:56:02 -070032//
Rahman Lavaee4ddf7ab2020-04-13 12:12:34 -070033// 2. All inter-basic block branch targets would now need to be resolved by the
Sriraman Tallamdf082ac2020-03-16 15:56:02 -070034// linker as they cannot be calculated during compile time. This is done
35// using static relocations. Further, the compiler tries to use short branch
36// instructions on some ISAs for small branch offsets. This is not possible
Rahman Lavaee4ddf7ab2020-04-13 12:12:34 -070037// with basic block sections as the offset is not determined at compile time,
38// and long branch instructions have to be used everywhere.
Sriraman Tallamdf082ac2020-03-16 15:56:02 -070039//
Rahman Lavaee4ddf7ab2020-04-13 12:12:34 -070040// 3. Each additional section bloats object file sizes by tens of bytes. The
41// number of basic blocks can be potentially very large compared to the size
42// of functions and can bloat object sizes significantly. Option
43// fbasicblock-sections= also takes a file path which can be used to specify
44// a subset of basic blocks that needs unique sections to keep the bloats
45// small.
46//
47// 4. Debug Information (DebugInfo) and Call Frame Information (CFI) emission
Sriraman Tallamdf082ac2020-03-16 15:56:02 -070048// needs special handling with basic block sections. DebugInfo needs to be
49// emitted with more relocations as basic block sections can break a
50// function into potentially several disjoint pieces, and CFI needs to be
Rahman Lavaee4ddf7ab2020-04-13 12:12:34 -070051// emitted per basic block. This also bloats the object file and binary
52// sizes.
Sriraman Tallamdf082ac2020-03-16 15:56:02 -070053//
54// Basic Block Labels
55// ==================
56//
57// With -fbasicblock-sections=labels, or when a basic block is placed in a
58// unique section, it is labelled with a symbol. This allows easy mapping of
59// virtual addresses from PMU profiles back to the corresponding basic blocks.
60// Since the number of basic blocks is large, the labeling bloats the symbol
61// table sizes and the string table sizes significantly. While the binary size
62// does increase, it does not affect performance as the symbol table is not
63// loaded in memory during run-time. The string table size bloat is kept very
64// minimal using a unary naming scheme that uses string suffix compression. The
65// basic blocks for function foo are named "a.BB.foo", "aa.BB.foo", ... This
66// turns out to be very good for string table sizes and the bloat in the string
67// table size for a very large binary is ~8 %. The naming also allows using
68// the --symbol-ordering-file option in LLD to arbitrarily reorder the
69// sections.
70//
71//===----------------------------------------------------------------------===//
72
73#include "llvm/ADT/SmallSet.h"
74#include "llvm/ADT/StringMap.h"
75#include "llvm/ADT/StringRef.h"
76#include "llvm/CodeGen/MachineFunction.h"
77#include "llvm/CodeGen/MachineFunctionPass.h"
78#include "llvm/CodeGen/MachineModuleInfo.h"
79#include "llvm/CodeGen/Passes.h"
80#include "llvm/CodeGen/TargetInstrInfo.h"
81#include "llvm/InitializePasses.h"
82#include "llvm/Support/LineIterator.h"
83#include "llvm/Support/MemoryBuffer.h"
84#include "llvm/Target/TargetMachine.h"
85
Rahman Lavaee4ddf7ab2020-04-13 12:12:34 -070086#include <string>
87
Sriraman Tallamdf082ac2020-03-16 15:56:02 -070088using llvm::SmallSet;
89using llvm::StringMap;
90using llvm::StringRef;
91using namespace llvm;
92
93namespace {
94
95class BBSectionsPrepare : public MachineFunctionPass {
96public:
97 static char ID;
Rahman Lavaee4ddf7ab2020-04-13 12:12:34 -070098 StringMap<SmallSet<unsigned, 4>> BBSectionsList;
Sriraman Tallamdf082ac2020-03-16 15:56:02 -070099 const MemoryBuffer *MBuf = nullptr;
100
Rahman Lavaee4ddf7ab2020-04-13 12:12:34 -0700101 BBSectionsPrepare() : MachineFunctionPass(ID) {
102 initializeBBSectionsPreparePass(*PassRegistry::getPassRegistry());
103 }
Sriraman Tallamdf082ac2020-03-16 15:56:02 -0700104
105 BBSectionsPrepare(const MemoryBuffer *Buf)
106 : MachineFunctionPass(ID), MBuf(Buf) {
107 initializeBBSectionsPreparePass(*PassRegistry::getPassRegistry());
108 };
109
110 StringRef getPassName() const override {
111 return "Basic Block Sections Analysis";
112 }
113
114 void getAnalysisUsage(AnalysisUsage &AU) const override;
115
116 /// Read profiles of basic blocks if available here.
117 bool doInitialization(Module &M) override;
118
119 /// Identify basic blocks that need separate sections and prepare to emit them
120 /// accordingly.
121 bool runOnMachineFunction(MachineFunction &MF) override;
122};
123
124} // end anonymous namespace
125
126char BBSectionsPrepare::ID = 0;
127INITIALIZE_PASS(BBSectionsPrepare, "bbsections-prepare",
Rahman Lavaee4ddf7ab2020-04-13 12:12:34 -0700128 "Determine if a basic block needs a special section", false,
129 false)
Sriraman Tallamdf082ac2020-03-16 15:56:02 -0700130
Rahman Lavaee4ddf7ab2020-04-13 12:12:34 -0700131// This inserts an unconditional branch at the end of MBB to the next basic
132// block S if and only if the control-flow implicitly falls through from MBB to
133// S and S and MBB belong to different sections. This is necessary with basic
134// block sections as MBB and S could be potentially reordered.
135static void insertUnconditionalFallthroughBranch(MachineBasicBlock &MBB) {
136 MachineBasicBlock *Fallthrough = MBB.getFallThrough();
137
138 if (Fallthrough == nullptr)
139 return;
140
141 // If this basic block and the Fallthrough basic block are in the same
142 // section then do not insert the jump.
143 if (MBB.sameSection(Fallthrough))
144 return;
145
146 const TargetInstrInfo *TII = MBB.getParent()->getSubtarget().getInstrInfo();
Sriraman Tallamdf082ac2020-03-16 15:56:02 -0700147 SmallVector<MachineOperand, 4> Cond;
Rahman Lavaee4ddf7ab2020-04-13 12:12:34 -0700148 MachineBasicBlock *TBB = nullptr, *FBB = nullptr;
Sriraman Tallamdf082ac2020-03-16 15:56:02 -0700149
Rahman Lavaee4ddf7ab2020-04-13 12:12:34 -0700150 // If a branch to the fall through block already exists, return.
151 if (!TII->analyzeBranch(MBB, TBB, FBB, Cond) &&
152 (TBB == Fallthrough || FBB == Fallthrough)) {
153 return;
Sriraman Tallamdf082ac2020-03-16 15:56:02 -0700154 }
Rahman Lavaee4ddf7ab2020-04-13 12:12:34 -0700155
156 Cond.clear();
157 DebugLoc DL = MBB.findBranchDebugLoc();
158 TII->insertBranch(MBB, Fallthrough, nullptr, Cond, DL);
Sriraman Tallamdf082ac2020-03-16 15:56:02 -0700159}
160
Rahman Lavaee4ddf7ab2020-04-13 12:12:34 -0700161/// This function sorts basic blocks according to the sections in which they are
162/// emitted. Basic block sections automatically turn on function sections so
163/// the entry block is in the function section. The other sections that are
164/// created are:
165/// 1) Exception section - basic blocks that are landing pads
166/// 2) Cold section - basic blocks that will not have unique sections.
167/// 3) Unique section - one per basic block that is emitted in a unique section.
Sriraman Tallamdf082ac2020-03-16 15:56:02 -0700168static bool assignSectionsAndSortBasicBlocks(
169 MachineFunction &MF,
Rahman Lavaee4ddf7ab2020-04-13 12:12:34 -0700170 const StringMap<SmallSet<unsigned, 4>> &BBSectionsList) {
171 SmallSet<unsigned, 4> S = BBSectionsList.lookup(MF.getName());
172
173 bool HasHotEHPads = false;
Sriraman Tallamdf082ac2020-03-16 15:56:02 -0700174
175 for (auto &MBB : MF) {
Rahman Lavaee4ddf7ab2020-04-13 12:12:34 -0700176 // Entry basic block cannot start another section because the function
177 // starts one already.
178 if (MBB.getNumber() == MF.front().getNumber()) {
179 MBB.setSectionType(MachineBasicBlockSection::MBBS_Entry);
180 continue;
Sriraman Tallamdf082ac2020-03-16 15:56:02 -0700181 }
Rahman Lavaee4ddf7ab2020-04-13 12:12:34 -0700182 // Check if this BB is a cold basic block. With the list option, all cold
183 // basic blocks can be clustered in a single cold section.
184 // All Exception landing pads must be in a single section. If all the
185 // landing pads are cold, it can be kept in the cold section. Otherwise, we
186 // create a separate exception section.
187 bool isColdBB = ((MF.getTarget().getBBSectionsType() ==
188 llvm::BasicBlockSection::List) &&
189 !S.empty() && !S.count(MBB.getNumber()));
190 if (isColdBB) {
191 MBB.setSectionType(MachineBasicBlockSection::MBBS_Cold);
192 } else if (MBB.isEHPad()) {
193 // We handle non-cold basic eh blocks later.
194 HasHotEHPads = true;
195 } else {
196 // Place this MBB in a unique section. A unique section begins and ends
197 // that section by definition.
198 MBB.setSectionType(MachineBasicBlockSection::MBBS_Unique);
Sriraman Tallamdf082ac2020-03-16 15:56:02 -0700199 }
200 }
201
Rahman Lavaee4ddf7ab2020-04-13 12:12:34 -0700202 // If some EH Pads are not cold then we move all EH Pads to the exception
203 // section as we require that all EH Pads be in a single section.
204 if (HasHotEHPads) {
205 std::for_each(MF.begin(), MF.end(), [&](MachineBasicBlock &MBB) {
Sriraman Tallamdf082ac2020-03-16 15:56:02 -0700206 if (MBB.isEHPad())
Rahman Lavaee4ddf7ab2020-04-13 12:12:34 -0700207 MBB.setSectionType(MachineBasicBlockSection::MBBS_Exception);
208 });
209 }
Sriraman Tallamdf082ac2020-03-16 15:56:02 -0700210
Rahman Lavaee4ddf7ab2020-04-13 12:12:34 -0700211 for (auto &MBB : MF) {
212 // With -fbasicblock-sections, fall through blocks must be made
213 // explicitly reachable. Do this after sections is set as
214 // unnecessary fallthroughs can be avoided.
215 insertUnconditionalFallthroughBranch(MBB);
216 }
Sriraman Tallamdf082ac2020-03-16 15:56:02 -0700217
Rahman Lavaee4ddf7ab2020-04-13 12:12:34 -0700218 MF.sort(([&](MachineBasicBlock &X, MachineBasicBlock &Y) {
219 unsigned TypeX = X.getSectionType();
220 unsigned TypeY = Y.getSectionType();
Sriraman Tallamdf082ac2020-03-16 15:56:02 -0700221
Rahman Lavaee4ddf7ab2020-04-13 12:12:34 -0700222 return (TypeX != TypeY) ? TypeX < TypeY : X.getNumber() < Y.getNumber();
223 }));
Sriraman Tallamdf082ac2020-03-16 15:56:02 -0700224
Rahman Lavaee4ddf7ab2020-04-13 12:12:34 -0700225 MF.setSectionRange();
Sriraman Tallamdf082ac2020-03-16 15:56:02 -0700226 return true;
227}
228
229bool BBSectionsPrepare::runOnMachineFunction(MachineFunction &MF) {
230 auto BBSectionsType = MF.getTarget().getBBSectionsType();
231 assert(BBSectionsType != BasicBlockSection::None &&
232 "BB Sections not enabled!");
Rahman Lavaee4ddf7ab2020-04-13 12:12:34 -0700233
Sriraman Tallamdf082ac2020-03-16 15:56:02 -0700234 // Renumber blocks before sorting them for basic block sections. This is
235 // useful during sorting, basic blocks in the same section will retain the
236 // default order. This renumbering should also be done for basic block
237 // labels to match the profiles with the correct blocks.
238 MF.RenumberBlocks();
239
240 if (BBSectionsType == BasicBlockSection::Labels) {
241 MF.setBBSectionsType(BBSectionsType);
242 MF.createBBLabels();
243 return true;
244 }
245
246 if (BBSectionsType == BasicBlockSection::List &&
Rahman Lavaee4ddf7ab2020-04-13 12:12:34 -0700247 BBSectionsList.find(MF.getName()) == BBSectionsList.end())
Sriraman Tallamdf082ac2020-03-16 15:56:02 -0700248 return true;
Rahman Lavaee4ddf7ab2020-04-13 12:12:34 -0700249
Sriraman Tallamdf082ac2020-03-16 15:56:02 -0700250 MF.setBBSectionsType(BBSectionsType);
251 MF.createBBLabels();
Rahman Lavaee4ddf7ab2020-04-13 12:12:34 -0700252 assignSectionsAndSortBasicBlocks(MF, BBSectionsList);
253
Sriraman Tallamdf082ac2020-03-16 15:56:02 -0700254 return true;
255}
256
257// Basic Block Sections can be enabled for a subset of machine basic blocks.
258// This is done by passing a file containing names of functions for which basic
259// block sections are desired. Additionally, machine basic block ids of the
Rahman Lavaee4ddf7ab2020-04-13 12:12:34 -0700260// functions can also be specified for a finer granularity.
261// A file with basic block sections for all of function main and two blocks for
262// function foo looks like this:
Sriraman Tallamdf082ac2020-03-16 15:56:02 -0700263// ----------------------------
264// list.txt:
265// !main
266// !foo
Rahman Lavaee4ddf7ab2020-04-13 12:12:34 -0700267// !!2
Sriraman Tallamdf082ac2020-03-16 15:56:02 -0700268// !!4
Rahman Lavaee4ddf7ab2020-04-13 12:12:34 -0700269static bool getBBSectionsList(const MemoryBuffer *MBuf,
270 StringMap<SmallSet<unsigned, 4>> &bbMap) {
271 if (!MBuf)
272 return false;
273
Sriraman Tallamdf082ac2020-03-16 15:56:02 -0700274 line_iterator LineIt(*MBuf, /*SkipBlanks=*/true, /*CommentMarker=*/'#');
275
Rahman Lavaee4ddf7ab2020-04-13 12:12:34 -0700276 StringMap<SmallSet<unsigned, 4>>::iterator fi = bbMap.end();
Sriraman Tallamdf082ac2020-03-16 15:56:02 -0700277
278 for (; !LineIt.is_at_eof(); ++LineIt) {
Rahman Lavaee4ddf7ab2020-04-13 12:12:34 -0700279 StringRef s(*LineIt);
280 if (s[0] == '@')
Sriraman Tallamdf082ac2020-03-16 15:56:02 -0700281 continue;
282 // Check for the leading "!"
Rahman Lavaee4ddf7ab2020-04-13 12:12:34 -0700283 if (!s.consume_front("!") || s.empty())
Sriraman Tallamdf082ac2020-03-16 15:56:02 -0700284 break;
Rahman Lavaee4ddf7ab2020-04-13 12:12:34 -0700285 // Check for second "!" which encodes basic block ids.
286 if (s.consume_front("!")) {
287 if (fi != bbMap.end())
288 fi->second.insert(std::stoi(s.str()));
289 else
290 return false;
291 } else {
292 // Start a new function.
293 auto R = bbMap.try_emplace(s.split('/').first);
294 fi = R.first;
295 assert(R.second);
Sriraman Tallamdf082ac2020-03-16 15:56:02 -0700296 }
297 }
Rahman Lavaee4ddf7ab2020-04-13 12:12:34 -0700298 return true;
Sriraman Tallamdf082ac2020-03-16 15:56:02 -0700299}
300
301bool BBSectionsPrepare::doInitialization(Module &M) {
Rahman Lavaee4ddf7ab2020-04-13 12:12:34 -0700302 if (MBuf)
303 getBBSectionsList(MBuf, BBSectionsList);
304 return true;
Sriraman Tallamdf082ac2020-03-16 15:56:02 -0700305}
306
307void BBSectionsPrepare::getAnalysisUsage(AnalysisUsage &AU) const {
308 AU.setPreservesAll();
309 AU.addRequired<MachineModuleInfoWrapperPass>();
310}
311
312MachineFunctionPass *
313llvm::createBBSectionsPreparePass(const MemoryBuffer *Buf) {
314 return new BBSectionsPrepare(Buf);
315}