blob: 1d804ccb7670402170af5e8d10a0f107eb69dedb [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
Sebastian Pop542e5222018-10-15 21:43:11 +0000104// Same as blockEndsInUnreachable in CodeGen/BranchFolding.cpp. Do not modify
105// this function unless you modify the MBB version as well.
106//
107/// A no successor, non-return block probably ends in unreachable and is cold.
108/// Also consider a block that ends in an indirect branch to be a return block,
109/// since many targets use plain indirect branches to return.
Aditya Kumar801394a2018-09-07 15:03:49 +0000110bool blockEndsInUnreachable(const BasicBlock &BB) {
Sebastian Pop542e5222018-10-15 21:43:11 +0000111 if (!succ_empty(&BB))
112 return false;
Aditya Kumar801394a2018-09-07 15:03:49 +0000113 if (BB.empty())
114 return true;
Chandler Carruthedb12a82018-10-15 10:04:59 +0000115 const Instruction *I = BB.getTerminator();
Sebastian Pop542e5222018-10-15 21:43:11 +0000116 return !(isa<ReturnInst>(I) || isa<IndirectBrInst>(I));
Aditya Kumar801394a2018-09-07 15:03:49 +0000117}
118
Aditya Kumara27014b2018-10-03 06:21:05 +0000119static bool exceptionHandlingFunctions(const CallInst *CI) {
120 auto F = CI->getCalledFunction();
121 if (!F)
122 return false;
123 auto FName = F->getName();
124 return FName == "__cxa_begin_catch" ||
125 FName == "__cxa_free_exception" ||
126 FName == "__cxa_allocate_exception" ||
127 FName == "__cxa_begin_catch" ||
128 FName == "__cxa_end_catch";
129}
130
Sebastian Pop542e5222018-10-15 21:43:11 +0000131static bool unlikelyExecuted(const BasicBlock &BB) {
Aditya Kumar801394a2018-09-07 15:03:49 +0000132 if (blockEndsInUnreachable(BB))
133 return true;
134 // Exception handling blocks are unlikely executed.
135 if (BB.isEHPad())
136 return true;
137 for (const Instruction &I : BB)
138 if (const CallInst *CI = dyn_cast<CallInst>(&I)) {
139 // The block is cold if it calls functions tagged as cold or noreturn.
140 if (CI->hasFnAttr(Attribute::Cold) ||
Aditya Kumara27014b2018-10-03 06:21:05 +0000141 CI->hasFnAttr(Attribute::NoReturn) ||
142 exceptionHandlingFunctions(CI))
Aditya Kumar801394a2018-09-07 15:03:49 +0000143 return true;
144
145 // Assume that inline assembly is hot code.
146 if (isa<InlineAsm>(CI->getCalledValue()))
147 return false;
148 }
149 return false;
150}
151
Sebastian Pop542e5222018-10-15 21:43:11 +0000152static bool returnsOrHasSideEffects(const BasicBlock &BB) {
Lang Hames8f9a2442018-10-15 22:27:03 +0000153 const Instruction *I = BB.getTerminator();
Sebastian Pop542e5222018-10-15 21:43:11 +0000154 if (isa<ReturnInst>(I) || isa<IndirectBrInst>(I) || isa<InvokeInst>(I))
155 return true;
156
157 for (const Instruction &I : BB)
158 if (const CallInst *CI = dyn_cast<CallInst>(&I)) {
159 if (CI->hasFnAttr(Attribute::NoReturn))
160 return true;
161
162 if (isa<InlineAsm>(CI->getCalledValue()))
163 return true;
164 }
165
166 return false;
167}
168
Aditya Kumar801394a2018-09-07 15:03:49 +0000169static DenseSetBB getHotBlocks(Function &F) {
Sebastian Pop12171602018-09-14 20:36:10 +0000170
171 // Mark all cold basic blocks.
172 DenseSetBB ColdBlocks;
Aditya Kumar801394a2018-09-07 15:03:49 +0000173 for (BasicBlock &BB : F)
Sebastian Pop542e5222018-10-15 21:43:11 +0000174 if (unlikelyExecuted(BB)) {
175 LLVM_DEBUG(llvm::dbgs() << "\nForward propagation marks cold: " << BB);
Sebastian Pop12171602018-09-14 20:36:10 +0000176 ColdBlocks.insert((const BasicBlock *)&BB);
Sebastian Pop542e5222018-10-15 21:43:11 +0000177 }
Sebastian Pop12171602018-09-14 20:36:10 +0000178
179 // Forward propagation: basic blocks are hot when they are reachable from the
180 // beginning of the function through a path that does not contain cold blocks.
Aditya Kumar801394a2018-09-07 15:03:49 +0000181 SmallVector<const BasicBlock *, 8> WL;
Sebastian Pop12171602018-09-14 20:36:10 +0000182 DenseSetBB HotBlocks;
Aditya Kumar801394a2018-09-07 15:03:49 +0000183
184 const BasicBlock *It = &F.front();
Aditya Kumar801394a2018-09-07 15:03:49 +0000185 if (!ColdBlocks.count(It)) {
Sebastian Pop12171602018-09-14 20:36:10 +0000186 HotBlocks.insert(It);
187 // Breadth First Search to mark edges reachable from hot.
Aditya Kumar801394a2018-09-07 15:03:49 +0000188 WL.push_back(It);
189 while (WL.size() > 0) {
190 It = WL.pop_back_val();
Sebastian Pop12171602018-09-14 20:36:10 +0000191
192 for (const BasicBlock *Succ : successors(It)) {
Aditya Kumar801394a2018-09-07 15:03:49 +0000193 // Do not visit blocks that are cold.
Sebastian Pop12171602018-09-14 20:36:10 +0000194 if (!ColdBlocks.count(Succ) && !HotBlocks.count(Succ)) {
195 HotBlocks.insert(Succ);
Aditya Kumar801394a2018-09-07 15:03:49 +0000196 WL.push_back(Succ);
197 }
198 }
199 }
200 }
201
Sebastian Pop12171602018-09-14 20:36:10 +0000202 assert(WL.empty() && "work list should be empty");
203
204 DenseMapBBInt NumHotSuccessors;
205 // Back propagation: when all successors of a basic block are cold, the
206 // basic block is cold as well.
207 for (BasicBlock &BBRef : F) {
208 const BasicBlock *BB = &BBRef;
209 if (HotBlocks.count(BB)) {
210 // Keep a count of hot successors for every hot block.
211 NumHotSuccessors[BB] = 0;
212 for (const BasicBlock *Succ : successors(BB))
213 if (!ColdBlocks.count(Succ))
214 NumHotSuccessors[BB] += 1;
215
216 // Add to work list the blocks with all successors cold. Those are the
217 // root nodes in the next loop, where we will move those blocks from
218 // HotBlocks to ColdBlocks and iterate over their predecessors.
219 if (NumHotSuccessors[BB] == 0)
220 WL.push_back(BB);
221 }
222 }
223
224 while (WL.size() > 0) {
225 It = WL.pop_back_val();
226 if (ColdBlocks.count(It))
227 continue;
228
Sebastian Pop542e5222018-10-15 21:43:11 +0000229 // Do not back-propagate to blocks that return or have side effects.
230 if (returnsOrHasSideEffects(*It))
231 continue;
232
Sebastian Pop12171602018-09-14 20:36:10 +0000233 // Move the block from HotBlocks to ColdBlocks.
Sebastian Pop542e5222018-10-15 21:43:11 +0000234 LLVM_DEBUG(llvm::dbgs() << "\nBack propagation marks cold: " << *It);
Sebastian Pop12171602018-09-14 20:36:10 +0000235 HotBlocks.erase(It);
236 ColdBlocks.insert(It);
237
238 // Iterate over the predecessors.
239 for (const BasicBlock *Pred : predecessors(It)) {
240 if (HotBlocks.count(Pred)) {
241 NumHotSuccessors[Pred] -= 1;
242
243 // If Pred has no more hot successors, add it to the work list.
244 if (NumHotSuccessors[Pred] == 0)
245 WL.push_back(Pred);
246 }
247 }
248 }
249
250 return HotBlocks;
Aditya Kumar801394a2018-09-07 15:03:49 +0000251}
252
253class HotColdSplitting {
254public:
255 HotColdSplitting(ProfileSummaryInfo *ProfSI,
256 function_ref<BlockFrequencyInfo *(Function &)> GBFI,
Sebastian Popa1f20fc2018-09-10 15:08:02 +0000257 function_ref<TargetTransformInfo &(Function &)> GTTI,
Aditya Kumar801394a2018-09-07 15:03:49 +0000258 std::function<OptimizationRemarkEmitter &(Function &)> *GORE)
Sebastian Popa1f20fc2018-09-10 15:08:02 +0000259 : PSI(ProfSI), GetBFI(GBFI), GetTTI(GTTI), GetORE(GORE) {}
Aditya Kumar801394a2018-09-07 15:03:49 +0000260 bool run(Module &M);
261
262private:
263 bool shouldOutlineFrom(const Function &F) const;
Sebastian Pop0f30f082018-09-14 20:36:19 +0000264 const Function *outlineColdBlocks(Function &F, const DenseSetBB &ColdBlock,
265 DominatorTree *DT, PostDomTree *PDT);
Aditya Kumar801394a2018-09-07 15:03:49 +0000266 Function *extractColdRegion(const SmallVectorImpl<BasicBlock *> &Region,
267 DominatorTree *DT, BlockFrequencyInfo *BFI,
268 OptimizationRemarkEmitter &ORE);
269 bool isOutlineCandidate(const SmallVectorImpl<BasicBlock *> &Region,
270 const BasicBlock *Exit) const {
271 if (!Exit)
272 return false;
Sebastian Pop3abcf692018-09-14 20:36:14 +0000273
Aditya Kumar801394a2018-09-07 15:03:49 +0000274 // Regions with landing pads etc.
275 for (const BasicBlock *BB : Region) {
276 if (BB->isEHPad() || BB->hasAddressTaken())
277 return false;
278 }
279 return true;
280 }
281 SmallPtrSet<const Function *, 2> OutlinedFunctions;
282 ProfileSummaryInfo *PSI;
283 function_ref<BlockFrequencyInfo *(Function &)> GetBFI;
Sebastian Popa1f20fc2018-09-10 15:08:02 +0000284 function_ref<TargetTransformInfo &(Function &)> GetTTI;
Aditya Kumar801394a2018-09-07 15:03:49 +0000285 std::function<OptimizationRemarkEmitter &(Function &)> *GetORE;
286};
287
288class HotColdSplittingLegacyPass : public ModulePass {
289public:
290 static char ID;
291 HotColdSplittingLegacyPass() : ModulePass(ID) {
292 initializeHotColdSplittingLegacyPassPass(*PassRegistry::getPassRegistry());
293 }
294
295 void getAnalysisUsage(AnalysisUsage &AU) const override {
296 AU.addRequired<AssumptionCacheTracker>();
297 AU.addRequired<BlockFrequencyInfoWrapperPass>();
298 AU.addRequired<ProfileSummaryInfoWrapperPass>();
Sebastian Popa1f20fc2018-09-10 15:08:02 +0000299 AU.addRequired<TargetTransformInfoWrapperPass>();
Aditya Kumar801394a2018-09-07 15:03:49 +0000300 }
301
302 bool runOnModule(Module &M) override;
303};
304
305} // end anonymous namespace
306
307// Returns false if the function should not be considered for hot-cold split
Sebastian Pop0f30f082018-09-14 20:36:19 +0000308// optimization.
Aditya Kumar801394a2018-09-07 15:03:49 +0000309bool HotColdSplitting::shouldOutlineFrom(const Function &F) const {
Sebastian Pop0f30f082018-09-14 20:36:19 +0000310 // Do not try to outline again from an already outlined cold function.
311 if (OutlinedFunctions.count(&F))
312 return false;
313
Aditya Kumar801394a2018-09-07 15:03:49 +0000314 if (F.size() <= 2)
315 return false;
316
317 if (F.hasAddressTaken())
318 return false;
319
320 if (F.hasFnAttribute(Attribute::AlwaysInline))
321 return false;
322
323 if (F.hasFnAttribute(Attribute::NoInline))
324 return false;
325
326 if (F.getCallingConv() == CallingConv::Cold)
327 return false;
328
329 if (PSI->isFunctionEntryCold(&F))
330 return false;
331 return true;
332}
333
334Function *
335HotColdSplitting::extractColdRegion(const SmallVectorImpl<BasicBlock *> &Region,
336 DominatorTree *DT, BlockFrequencyInfo *BFI,
337 OptimizationRemarkEmitter &ORE) {
Teresa Johnsonf431a2f2018-10-22 19:06:42 +0000338 assert(!Region.empty());
Aditya Kumar801394a2018-09-07 15:03:49 +0000339 LLVM_DEBUG(for (auto *BB : Region)
340 llvm::dbgs() << "\nExtracting: " << *BB;);
Sebastian Pop12171602018-09-14 20:36:10 +0000341
Aditya Kumar801394a2018-09-07 15:03:49 +0000342 // TODO: Pass BFI and BPI to update profile information.
Sebastian Pop12171602018-09-14 20:36:10 +0000343 CodeExtractor CE(Region, DT);
Aditya Kumar801394a2018-09-07 15:03:49 +0000344
345 SetVector<Value *> Inputs, Outputs, Sinks;
346 CE.findInputsOutputs(Inputs, Outputs, Sinks);
347
348 // Do not extract regions that have live exit variables.
349 if (Outputs.size() > 0)
350 return nullptr;
351
Teresa Johnsonf431a2f2018-10-22 19:06:42 +0000352 Function *OrigF = Region[0]->getParent();
Aditya Kumar801394a2018-09-07 15:03:49 +0000353 if (Function *OutF = CE.extractCodeRegion()) {
354 User *U = *OutF->user_begin();
355 CallInst *CI = cast<CallInst>(U);
356 CallSite CS(CI);
357 NumColdSESEOutlined++;
Sebastian Popa1f20fc2018-09-10 15:08:02 +0000358 if (GetTTI(*OutF).useColdCCForColdCall(*OutF)) {
359 OutF->setCallingConv(CallingConv::Cold);
360 CS.setCallingConv(CallingConv::Cold);
361 }
Aditya Kumar801394a2018-09-07 15:03:49 +0000362 CI->setIsNoInline();
Sebastian Pop0f30f082018-09-14 20:36:19 +0000363 LLVM_DEBUG(llvm::dbgs() << "Outlined Region: " << *OutF);
Teresa Johnsonf431a2f2018-10-22 19:06:42 +0000364 ORE.emit([&]() {
365 return OptimizationRemark(DEBUG_TYPE, "HotColdSplit",
366 &*Region[0]->begin())
367 << ore::NV("Original", OrigF) << " split cold code into "
368 << ore::NV("Split", OutF);
369 });
Aditya Kumar801394a2018-09-07 15:03:49 +0000370 return OutF;
371 }
372
373 ORE.emit([&]() {
374 return OptimizationRemarkMissed(DEBUG_TYPE, "ExtractFailed",
375 &*Region[0]->begin())
376 << "Failed to extract region at block "
377 << ore::NV("Block", Region.front());
378 });
379 return nullptr;
380}
381
382// Return the function created after outlining, nullptr otherwise.
Sebastian Pop0f30f082018-09-14 20:36:19 +0000383const Function *HotColdSplitting::outlineColdBlocks(Function &F,
384 const DenseSetBB &HotBlocks,
385 DominatorTree *DT,
386 PostDomTree *PDT) {
Aditya Kumar801394a2018-09-07 15:03:49 +0000387 auto BFI = GetBFI(F);
388 auto &ORE = (*GetORE)(F);
389 // Walking the dominator tree allows us to find the largest
390 // cold region.
391 BasicBlock *Begin = DT->getRootNode()->getBlock();
Sebastian Pop542e5222018-10-15 21:43:11 +0000392
393 // Early return if the beginning of the function has been marked cold,
394 // otherwise all the function gets outlined.
395 if (PSI->isColdBB(Begin, BFI) || !HotBlocks.count(Begin))
396 return nullptr;
397
Aditya Kumar801394a2018-09-07 15:03:49 +0000398 for (auto I = df_begin(Begin), E = df_end(Begin); I != E; ++I) {
399 BasicBlock *BB = *I;
Sebastian Pop12171602018-09-14 20:36:10 +0000400 if (PSI->isColdBB(BB, BFI) || !HotBlocks.count(BB)) {
Aditya Kumar801394a2018-09-07 15:03:49 +0000401 SmallVector<BasicBlock *, 4> ValidColdRegion, Region;
Sebastian Pop3abcf692018-09-14 20:36:14 +0000402 BasicBlock *Exit = (*PDT)[BB]->getIDom()->getBlock();
Aditya Kumar801394a2018-09-07 15:03:49 +0000403 BasicBlock *ExitColdRegion = nullptr;
Sebastian Pop0f30f082018-09-14 20:36:19 +0000404
Aditya Kumar801394a2018-09-07 15:03:49 +0000405 // Estimated cold region between a BB and its dom-frontier.
Sebastian Pop0f30f082018-09-14 20:36:19 +0000406 while (Exit && isSingleEntrySingleExit(BB, Exit, DT, PDT, Region) &&
Aditya Kumar801394a2018-09-07 15:03:49 +0000407 isOutlineCandidate(Region, Exit)) {
408 ExitColdRegion = Exit;
409 ValidColdRegion = Region;
410 Region.clear();
411 // Update Exit recursively to its dom-frontier.
412 Exit = (*PDT)[Exit]->getIDom()->getBlock();
413 }
414 if (ExitColdRegion) {
Sebastian Pop3abcf692018-09-14 20:36:14 +0000415 // Do not outline a region with only one block.
416 if (ValidColdRegion.size() == 1)
417 continue;
418
Aditya Kumar801394a2018-09-07 15:03:49 +0000419 ++NumColdSESEFound;
Sebastian Pop0f30f082018-09-14 20:36:19 +0000420 ValidColdRegion.push_back(ExitColdRegion);
Aditya Kumar801394a2018-09-07 15:03:49 +0000421 // Candidate for outlining. FIXME: Continue outlining.
Aditya Kumar801394a2018-09-07 15:03:49 +0000422 return extractColdRegion(ValidColdRegion, DT, BFI, ORE);
423 }
424 }
425 }
426 return nullptr;
427}
428
429bool HotColdSplitting::run(Module &M) {
430 for (auto &F : M) {
431 if (!shouldOutlineFrom(F))
432 continue;
433 DominatorTree DT(F);
434 PostDomTree PDT(F);
435 PDT.recalculate(F);
436 DenseSetBB HotBlocks;
437 if (EnableStaticAnalyis) // Static analysis of cold blocks.
438 HotBlocks = getHotBlocks(F);
439
Sebastian Pop0f30f082018-09-14 20:36:19 +0000440 const Function *Outlined = outlineColdBlocks(F, HotBlocks, &DT, &PDT);
Aditya Kumar801394a2018-09-07 15:03:49 +0000441 if (Outlined)
442 OutlinedFunctions.insert(Outlined);
443 }
444 return true;
445}
446
447bool HotColdSplittingLegacyPass::runOnModule(Module &M) {
448 if (skipModule(M))
449 return false;
450 ProfileSummaryInfo *PSI =
451 getAnalysis<ProfileSummaryInfoWrapperPass>().getPSI();
Sebastian Popa1f20fc2018-09-10 15:08:02 +0000452 auto GTTI = [this](Function &F) -> TargetTransformInfo & {
453 return this->getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
454 };
Aditya Kumar801394a2018-09-07 15:03:49 +0000455 auto GBFI = [this](Function &F) {
456 return &this->getAnalysis<BlockFrequencyInfoWrapperPass>(F).getBFI();
457 };
458 std::unique_ptr<OptimizationRemarkEmitter> ORE;
459 std::function<OptimizationRemarkEmitter &(Function &)> GetORE =
460 [&ORE](Function &F) -> OptimizationRemarkEmitter & {
461 ORE.reset(new OptimizationRemarkEmitter(&F));
462 return *ORE.get();
463 };
464
Sebastian Popa1f20fc2018-09-10 15:08:02 +0000465 return HotColdSplitting(PSI, GBFI, GTTI, &GetORE).run(M);
Aditya Kumar801394a2018-09-07 15:03:49 +0000466}
467
Aditya Kumar9e20ade2018-10-03 05:55:20 +0000468PreservedAnalyses
469HotColdSplittingPass::run(Module &M, ModuleAnalysisManager &AM) {
470 auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
471
472 std::function<AssumptionCache &(Function &)> GetAssumptionCache =
473 [&FAM](Function &F) -> AssumptionCache & {
474 return FAM.getResult<AssumptionAnalysis>(F);
475 };
476
477 auto GBFI = [&FAM](Function &F) {
478 return &FAM.getResult<BlockFrequencyAnalysis>(F);
479 };
480
481 std::function<TargetTransformInfo &(Function &)> GTTI =
482 [&FAM](Function &F) -> TargetTransformInfo & {
483 return FAM.getResult<TargetIRAnalysis>(F);
484 };
485
486 std::unique_ptr<OptimizationRemarkEmitter> ORE;
487 std::function<OptimizationRemarkEmitter &(Function &)> GetORE =
488 [&ORE](Function &F) -> OptimizationRemarkEmitter & {
489 ORE.reset(new OptimizationRemarkEmitter(&F));
490 return *ORE.get();
491 };
492
493 ProfileSummaryInfo *PSI = &AM.getResult<ProfileSummaryAnalysis>(M);
494
495 if (HotColdSplitting(PSI, GBFI, GTTI, &GetORE).run(M))
496 return PreservedAnalyses::none();
497 return PreservedAnalyses::all();
498}
499
Aditya Kumar801394a2018-09-07 15:03:49 +0000500char HotColdSplittingLegacyPass::ID = 0;
501INITIALIZE_PASS_BEGIN(HotColdSplittingLegacyPass, "hotcoldsplit",
502 "Hot Cold Splitting", false, false)
503INITIALIZE_PASS_DEPENDENCY(ProfileSummaryInfoWrapperPass)
504INITIALIZE_PASS_DEPENDENCY(BlockFrequencyInfoWrapperPass)
505INITIALIZE_PASS_END(HotColdSplittingLegacyPass, "hotcoldsplit",
506 "Hot Cold Splitting", false, false)
507
508ModulePass *llvm::createHotColdSplittingPass() {
509 return new HotColdSplittingLegacyPass();
510}