blob: 820d08316d65d207742e6b30ce45421a1d5c698d [file] [log] [blame]
Aditya Kumar801394a2018-09-07 15:03:49 +00001//===- HotColdSplitting.cpp -- Outline Cold Regions -------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Outline cold regions to a separate function.
11// TODO: Update BFI and BPI
12// TODO: Add all the outlined functions to a separate section.
13//
14//===----------------------------------------------------------------------===//
15
16#include "llvm/ADT/SmallVector.h"
17#include "llvm/ADT/Statistic.h"
18#include "llvm/Analysis/AliasAnalysis.h"
19#include "llvm/Analysis/BlockFrequencyInfo.h"
20#include "llvm/Analysis/BranchProbabilityInfo.h"
21#include "llvm/Analysis/CFG.h"
22#include "llvm/Analysis/OptimizationRemarkEmitter.h"
23#include "llvm/Analysis/PostDominators.h"
24#include "llvm/Analysis/ProfileSummaryInfo.h"
Sebastian Popa1f20fc2018-09-10 15:08:02 +000025#include "llvm/Analysis/TargetTransformInfo.h"
Aditya Kumar801394a2018-09-07 15:03:49 +000026#include "llvm/IR/BasicBlock.h"
27#include "llvm/IR/CFG.h"
28#include "llvm/IR/DataLayout.h"
29#include "llvm/IR/DiagnosticInfo.h"
30#include "llvm/IR/Dominators.h"
31#include "llvm/IR/Function.h"
32#include "llvm/IR/Instruction.h"
33#include "llvm/IR/Instructions.h"
34#include "llvm/IR/Metadata.h"
35#include "llvm/IR/Module.h"
36#include "llvm/IR/PassManager.h"
37#include "llvm/IR/Type.h"
38#include "llvm/IR/Use.h"
39#include "llvm/IR/User.h"
40#include "llvm/IR/Value.h"
41#include "llvm/Pass.h"
42#include "llvm/Support/BlockFrequency.h"
43#include "llvm/Support/BranchProbability.h"
44#include "llvm/Support/Debug.h"
45#include "llvm/Support/raw_ostream.h"
46#include "llvm/Transforms/IPO.h"
Aditya Kumar9e20ade2018-10-03 05:55:20 +000047#include "llvm/Transforms/IPO/HotColdSplitting.h"
Aditya Kumar801394a2018-09-07 15:03:49 +000048#include "llvm/Transforms/Scalar.h"
49#include "llvm/Transforms/Utils/BasicBlockUtils.h"
50#include "llvm/Transforms/Utils/Cloning.h"
51#include "llvm/Transforms/Utils/CodeExtractor.h"
52#include "llvm/Transforms/Utils/Local.h"
53#include "llvm/Transforms/Utils/SSAUpdater.h"
54#include "llvm/Transforms/Utils/ValueMapper.h"
55#include <algorithm>
56#include <cassert>
57
58#define DEBUG_TYPE "hotcoldsplit"
59
60STATISTIC(NumColdSESEFound,
61 "Number of cold single entry single exit (SESE) regions found.");
62STATISTIC(NumColdSESEOutlined,
63 "Number of cold single entry single exit (SESE) regions outlined.");
64
65using namespace llvm;
66
67static cl::opt<bool> EnableStaticAnalyis("hot-cold-static-analysis",
68 cl::init(true), cl::Hidden);
69
70
71namespace {
72
73struct PostDomTree : PostDomTreeBase<BasicBlock> {
74 PostDomTree(Function &F) { recalculate(F); }
75};
76
77typedef DenseSet<const BasicBlock *> DenseSetBB;
Sebastian Pop12171602018-09-14 20:36:10 +000078typedef DenseMap<const BasicBlock *, uint64_t> DenseMapBBInt;
Aditya Kumar801394a2018-09-07 15:03:49 +000079
80// From: https://reviews.llvm.org/D22558
81// Exit is not part of the region.
82static bool isSingleEntrySingleExit(BasicBlock *Entry, const BasicBlock *Exit,
83 DominatorTree *DT, PostDomTree *PDT,
84 SmallVectorImpl<BasicBlock *> &Region) {
85 if (!DT->dominates(Entry, Exit))
86 return false;
87
88 if (!PDT->dominates(Exit, Entry))
89 return false;
90
Aditya Kumar801394a2018-09-07 15:03:49 +000091 for (auto I = df_begin(Entry), E = df_end(Entry); I != E;) {
92 if (*I == Exit) {
93 I.skipChildren();
94 continue;
95 }
96 if (!DT->dominates(Entry, *I))
97 return false;
98 Region.push_back(*I);
99 ++I;
100 }
101 return true;
102}
103
104bool blockEndsInUnreachable(const BasicBlock &BB) {
105 if (BB.empty())
106 return true;
107 const TerminatorInst *I = BB.getTerminator();
108 if (isa<ReturnInst>(I) || isa<IndirectBrInst>(I))
109 return true;
110 // Unreachable blocks do not have any successor.
111 return succ_empty(&BB);
112}
113
114static
115bool unlikelyExecuted(const BasicBlock &BB) {
116 if (blockEndsInUnreachable(BB))
117 return true;
118 // Exception handling blocks are unlikely executed.
119 if (BB.isEHPad())
120 return true;
121 for (const Instruction &I : BB)
122 if (const CallInst *CI = dyn_cast<CallInst>(&I)) {
123 // The block is cold if it calls functions tagged as cold or noreturn.
124 if (CI->hasFnAttr(Attribute::Cold) ||
125 CI->hasFnAttr(Attribute::NoReturn))
126 return true;
127
128 // Assume that inline assembly is hot code.
129 if (isa<InlineAsm>(CI->getCalledValue()))
130 return false;
131 }
132 return false;
133}
134
135static DenseSetBB getHotBlocks(Function &F) {
Sebastian Pop12171602018-09-14 20:36:10 +0000136
137 // Mark all cold basic blocks.
138 DenseSetBB ColdBlocks;
Aditya Kumar801394a2018-09-07 15:03:49 +0000139 for (BasicBlock &BB : F)
140 if (unlikelyExecuted(BB))
Sebastian Pop12171602018-09-14 20:36:10 +0000141 ColdBlocks.insert((const BasicBlock *)&BB);
142
143 // Forward propagation: basic blocks are hot when they are reachable from the
144 // beginning of the function through a path that does not contain cold blocks.
Aditya Kumar801394a2018-09-07 15:03:49 +0000145 SmallVector<const BasicBlock *, 8> WL;
Sebastian Pop12171602018-09-14 20:36:10 +0000146 DenseSetBB HotBlocks;
Aditya Kumar801394a2018-09-07 15:03:49 +0000147
148 const BasicBlock *It = &F.front();
Aditya Kumar801394a2018-09-07 15:03:49 +0000149 if (!ColdBlocks.count(It)) {
Sebastian Pop12171602018-09-14 20:36:10 +0000150 HotBlocks.insert(It);
151 // Breadth First Search to mark edges reachable from hot.
Aditya Kumar801394a2018-09-07 15:03:49 +0000152 WL.push_back(It);
153 while (WL.size() > 0) {
154 It = WL.pop_back_val();
Sebastian Pop12171602018-09-14 20:36:10 +0000155
156 for (const BasicBlock *Succ : successors(It)) {
Aditya Kumar801394a2018-09-07 15:03:49 +0000157 // Do not visit blocks that are cold.
Sebastian Pop12171602018-09-14 20:36:10 +0000158 if (!ColdBlocks.count(Succ) && !HotBlocks.count(Succ)) {
159 HotBlocks.insert(Succ);
Aditya Kumar801394a2018-09-07 15:03:49 +0000160 WL.push_back(Succ);
161 }
162 }
163 }
164 }
165
Sebastian Pop12171602018-09-14 20:36:10 +0000166 assert(WL.empty() && "work list should be empty");
167
168 DenseMapBBInt NumHotSuccessors;
169 // Back propagation: when all successors of a basic block are cold, the
170 // basic block is cold as well.
171 for (BasicBlock &BBRef : F) {
172 const BasicBlock *BB = &BBRef;
173 if (HotBlocks.count(BB)) {
174 // Keep a count of hot successors for every hot block.
175 NumHotSuccessors[BB] = 0;
176 for (const BasicBlock *Succ : successors(BB))
177 if (!ColdBlocks.count(Succ))
178 NumHotSuccessors[BB] += 1;
179
180 // Add to work list the blocks with all successors cold. Those are the
181 // root nodes in the next loop, where we will move those blocks from
182 // HotBlocks to ColdBlocks and iterate over their predecessors.
183 if (NumHotSuccessors[BB] == 0)
184 WL.push_back(BB);
185 }
186 }
187
188 while (WL.size() > 0) {
189 It = WL.pop_back_val();
190 if (ColdBlocks.count(It))
191 continue;
192
193 // Move the block from HotBlocks to ColdBlocks.
194 HotBlocks.erase(It);
195 ColdBlocks.insert(It);
196
197 // Iterate over the predecessors.
198 for (const BasicBlock *Pred : predecessors(It)) {
199 if (HotBlocks.count(Pred)) {
200 NumHotSuccessors[Pred] -= 1;
201
202 // If Pred has no more hot successors, add it to the work list.
203 if (NumHotSuccessors[Pred] == 0)
204 WL.push_back(Pred);
205 }
206 }
207 }
208
209 return HotBlocks;
Aditya Kumar801394a2018-09-07 15:03:49 +0000210}
211
212class HotColdSplitting {
213public:
214 HotColdSplitting(ProfileSummaryInfo *ProfSI,
215 function_ref<BlockFrequencyInfo *(Function &)> GBFI,
Sebastian Popa1f20fc2018-09-10 15:08:02 +0000216 function_ref<TargetTransformInfo &(Function &)> GTTI,
Aditya Kumar801394a2018-09-07 15:03:49 +0000217 std::function<OptimizationRemarkEmitter &(Function &)> *GORE)
Sebastian Popa1f20fc2018-09-10 15:08:02 +0000218 : PSI(ProfSI), GetBFI(GBFI), GetTTI(GTTI), GetORE(GORE) {}
Aditya Kumar801394a2018-09-07 15:03:49 +0000219 bool run(Module &M);
220
221private:
222 bool shouldOutlineFrom(const Function &F) const;
Sebastian Pop0f30f082018-09-14 20:36:19 +0000223 const Function *outlineColdBlocks(Function &F, const DenseSetBB &ColdBlock,
224 DominatorTree *DT, PostDomTree *PDT);
Aditya Kumar801394a2018-09-07 15:03:49 +0000225 Function *extractColdRegion(const SmallVectorImpl<BasicBlock *> &Region,
226 DominatorTree *DT, BlockFrequencyInfo *BFI,
227 OptimizationRemarkEmitter &ORE);
228 bool isOutlineCandidate(const SmallVectorImpl<BasicBlock *> &Region,
229 const BasicBlock *Exit) const {
230 if (!Exit)
231 return false;
Sebastian Pop3abcf692018-09-14 20:36:14 +0000232
Aditya Kumar801394a2018-09-07 15:03:49 +0000233 // Regions with landing pads etc.
234 for (const BasicBlock *BB : Region) {
235 if (BB->isEHPad() || BB->hasAddressTaken())
236 return false;
237 }
238 return true;
239 }
240 SmallPtrSet<const Function *, 2> OutlinedFunctions;
241 ProfileSummaryInfo *PSI;
242 function_ref<BlockFrequencyInfo *(Function &)> GetBFI;
Sebastian Popa1f20fc2018-09-10 15:08:02 +0000243 function_ref<TargetTransformInfo &(Function &)> GetTTI;
Aditya Kumar801394a2018-09-07 15:03:49 +0000244 std::function<OptimizationRemarkEmitter &(Function &)> *GetORE;
245};
246
247class HotColdSplittingLegacyPass : public ModulePass {
248public:
249 static char ID;
250 HotColdSplittingLegacyPass() : ModulePass(ID) {
251 initializeHotColdSplittingLegacyPassPass(*PassRegistry::getPassRegistry());
252 }
253
254 void getAnalysisUsage(AnalysisUsage &AU) const override {
255 AU.addRequired<AssumptionCacheTracker>();
256 AU.addRequired<BlockFrequencyInfoWrapperPass>();
257 AU.addRequired<ProfileSummaryInfoWrapperPass>();
Sebastian Popa1f20fc2018-09-10 15:08:02 +0000258 AU.addRequired<TargetTransformInfoWrapperPass>();
Aditya Kumar801394a2018-09-07 15:03:49 +0000259 }
260
261 bool runOnModule(Module &M) override;
262};
263
264} // end anonymous namespace
265
266// Returns false if the function should not be considered for hot-cold split
Sebastian Pop0f30f082018-09-14 20:36:19 +0000267// optimization.
Aditya Kumar801394a2018-09-07 15:03:49 +0000268bool HotColdSplitting::shouldOutlineFrom(const Function &F) const {
Sebastian Pop0f30f082018-09-14 20:36:19 +0000269 // Do not try to outline again from an already outlined cold function.
270 if (OutlinedFunctions.count(&F))
271 return false;
272
Aditya Kumar801394a2018-09-07 15:03:49 +0000273 if (F.size() <= 2)
274 return false;
275
276 if (F.hasAddressTaken())
277 return false;
278
279 if (F.hasFnAttribute(Attribute::AlwaysInline))
280 return false;
281
282 if (F.hasFnAttribute(Attribute::NoInline))
283 return false;
284
285 if (F.getCallingConv() == CallingConv::Cold)
286 return false;
287
288 if (PSI->isFunctionEntryCold(&F))
289 return false;
290 return true;
291}
292
293Function *
294HotColdSplitting::extractColdRegion(const SmallVectorImpl<BasicBlock *> &Region,
295 DominatorTree *DT, BlockFrequencyInfo *BFI,
296 OptimizationRemarkEmitter &ORE) {
297 LLVM_DEBUG(for (auto *BB : Region)
298 llvm::dbgs() << "\nExtracting: " << *BB;);
Sebastian Pop12171602018-09-14 20:36:10 +0000299
Aditya Kumar801394a2018-09-07 15:03:49 +0000300 // TODO: Pass BFI and BPI to update profile information.
Sebastian Pop12171602018-09-14 20:36:10 +0000301 CodeExtractor CE(Region, DT);
Aditya Kumar801394a2018-09-07 15:03:49 +0000302
303 SetVector<Value *> Inputs, Outputs, Sinks;
304 CE.findInputsOutputs(Inputs, Outputs, Sinks);
305
306 // Do not extract regions that have live exit variables.
307 if (Outputs.size() > 0)
308 return nullptr;
309
310 if (Function *OutF = CE.extractCodeRegion()) {
311 User *U = *OutF->user_begin();
312 CallInst *CI = cast<CallInst>(U);
313 CallSite CS(CI);
314 NumColdSESEOutlined++;
Sebastian Popa1f20fc2018-09-10 15:08:02 +0000315 if (GetTTI(*OutF).useColdCCForColdCall(*OutF)) {
316 OutF->setCallingConv(CallingConv::Cold);
317 CS.setCallingConv(CallingConv::Cold);
318 }
Aditya Kumar801394a2018-09-07 15:03:49 +0000319 CI->setIsNoInline();
Sebastian Pop0f30f082018-09-14 20:36:19 +0000320 LLVM_DEBUG(llvm::dbgs() << "Outlined Region: " << *OutF);
Aditya Kumar801394a2018-09-07 15:03:49 +0000321 return OutF;
322 }
323
324 ORE.emit([&]() {
325 return OptimizationRemarkMissed(DEBUG_TYPE, "ExtractFailed",
326 &*Region[0]->begin())
327 << "Failed to extract region at block "
328 << ore::NV("Block", Region.front());
329 });
330 return nullptr;
331}
332
333// Return the function created after outlining, nullptr otherwise.
Sebastian Pop0f30f082018-09-14 20:36:19 +0000334const Function *HotColdSplitting::outlineColdBlocks(Function &F,
335 const DenseSetBB &HotBlocks,
336 DominatorTree *DT,
337 PostDomTree *PDT) {
Aditya Kumar801394a2018-09-07 15:03:49 +0000338 auto BFI = GetBFI(F);
339 auto &ORE = (*GetORE)(F);
340 // Walking the dominator tree allows us to find the largest
341 // cold region.
342 BasicBlock *Begin = DT->getRootNode()->getBlock();
343 for (auto I = df_begin(Begin), E = df_end(Begin); I != E; ++I) {
344 BasicBlock *BB = *I;
Sebastian Pop12171602018-09-14 20:36:10 +0000345 if (PSI->isColdBB(BB, BFI) || !HotBlocks.count(BB)) {
Aditya Kumar801394a2018-09-07 15:03:49 +0000346 SmallVector<BasicBlock *, 4> ValidColdRegion, Region;
Sebastian Pop3abcf692018-09-14 20:36:14 +0000347 BasicBlock *Exit = (*PDT)[BB]->getIDom()->getBlock();
Aditya Kumar801394a2018-09-07 15:03:49 +0000348 BasicBlock *ExitColdRegion = nullptr;
Sebastian Pop0f30f082018-09-14 20:36:19 +0000349
Aditya Kumar801394a2018-09-07 15:03:49 +0000350 // Estimated cold region between a BB and its dom-frontier.
Sebastian Pop0f30f082018-09-14 20:36:19 +0000351 while (Exit && isSingleEntrySingleExit(BB, Exit, DT, PDT, Region) &&
Aditya Kumar801394a2018-09-07 15:03:49 +0000352 isOutlineCandidate(Region, Exit)) {
353 ExitColdRegion = Exit;
354 ValidColdRegion = Region;
355 Region.clear();
356 // Update Exit recursively to its dom-frontier.
357 Exit = (*PDT)[Exit]->getIDom()->getBlock();
358 }
359 if (ExitColdRegion) {
Sebastian Pop3abcf692018-09-14 20:36:14 +0000360 // Do not outline a region with only one block.
361 if (ValidColdRegion.size() == 1)
362 continue;
363
Aditya Kumar801394a2018-09-07 15:03:49 +0000364 ++NumColdSESEFound;
Sebastian Pop0f30f082018-09-14 20:36:19 +0000365 ValidColdRegion.push_back(ExitColdRegion);
Aditya Kumar801394a2018-09-07 15:03:49 +0000366 // Candidate for outlining. FIXME: Continue outlining.
Aditya Kumar801394a2018-09-07 15:03:49 +0000367 return extractColdRegion(ValidColdRegion, DT, BFI, ORE);
368 }
369 }
370 }
371 return nullptr;
372}
373
374bool HotColdSplitting::run(Module &M) {
375 for (auto &F : M) {
376 if (!shouldOutlineFrom(F))
377 continue;
378 DominatorTree DT(F);
379 PostDomTree PDT(F);
380 PDT.recalculate(F);
381 DenseSetBB HotBlocks;
382 if (EnableStaticAnalyis) // Static analysis of cold blocks.
383 HotBlocks = getHotBlocks(F);
384
Sebastian Pop0f30f082018-09-14 20:36:19 +0000385 const Function *Outlined = outlineColdBlocks(F, HotBlocks, &DT, &PDT);
Aditya Kumar801394a2018-09-07 15:03:49 +0000386 if (Outlined)
387 OutlinedFunctions.insert(Outlined);
388 }
389 return true;
390}
391
392bool HotColdSplittingLegacyPass::runOnModule(Module &M) {
393 if (skipModule(M))
394 return false;
395 ProfileSummaryInfo *PSI =
396 getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI();
Sebastian Popa1f20fc2018-09-10 15:08:02 +0000397 auto GTTI = [this](Function &F) -> TargetTransformInfo & {
398 return this->getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
399 };
Aditya Kumar801394a2018-09-07 15:03:49 +0000400 auto GBFI = [this](Function &F) {
401 return &this->getAnalysis<BlockFrequencyInfoWrapperPass>(F).getBFI();
402 };
403 std::unique_ptr<OptimizationRemarkEmitter> ORE;
404 std::function<OptimizationRemarkEmitter &(Function &)> GetORE =
405 [&ORE](Function &F) -> OptimizationRemarkEmitter & {
406 ORE.reset(new OptimizationRemarkEmitter(&F));
407 return *ORE.get();
408 };
409
Sebastian Popa1f20fc2018-09-10 15:08:02 +0000410 return HotColdSplitting(PSI, GBFI, GTTI, &GetORE).run(M);
Aditya Kumar801394a2018-09-07 15:03:49 +0000411}
412
Aditya Kumar9e20ade2018-10-03 05:55:20 +0000413PreservedAnalyses
414HotColdSplittingPass::run(Module &M, ModuleAnalysisManager &AM) {
415 auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
416
417 std::function<AssumptionCache &(Function &)> GetAssumptionCache =
418 [&FAM](Function &F) -> AssumptionCache & {
419 return FAM.getResult<AssumptionAnalysis>(F);
420 };
421
422 auto GBFI = [&FAM](Function &F) {
423 return &FAM.getResult<BlockFrequencyAnalysis>(F);
424 };
425
426 std::function<TargetTransformInfo &(Function &)> GTTI =
427 [&FAM](Function &F) -> TargetTransformInfo & {
428 return FAM.getResult<TargetIRAnalysis>(F);
429 };
430
431 std::unique_ptr<OptimizationRemarkEmitter> ORE;
432 std::function<OptimizationRemarkEmitter &(Function &)> GetORE =
433 [&ORE](Function &F) -> OptimizationRemarkEmitter & {
434 ORE.reset(new OptimizationRemarkEmitter(&F));
435 return *ORE.get();
436 };
437
438 ProfileSummaryInfo *PSI = &AM.getResult<ProfileSummaryAnalysis>(M);
439
440 if (HotColdSplitting(PSI, GBFI, GTTI, &GetORE).run(M))
441 return PreservedAnalyses::none();
442 return PreservedAnalyses::all();
443}
444
Aditya Kumar801394a2018-09-07 15:03:49 +0000445char HotColdSplittingLegacyPass::ID = 0;
446INITIALIZE_PASS_BEGIN(HotColdSplittingLegacyPass, "hotcoldsplit",
447 "Hot Cold Splitting", false, false)
448INITIALIZE_PASS_DEPENDENCY(ProfileSummaryInfoWrapperPass)
449INITIALIZE_PASS_DEPENDENCY(BlockFrequencyInfoWrapperPass)
450INITIALIZE_PASS_END(HotColdSplittingLegacyPass, "hotcoldsplit",
451 "Hot Cold Splitting", false, false)
452
453ModulePass *llvm::createHotColdSplittingPass() {
454 return new HotColdSplittingLegacyPass();
455}