LLVM 24.0.0git
PartialInlining.cpp
Go to the documentation of this file.
1//===- PartialInlining.cpp - Inline parts of functions --------------------===//
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// This pass performs partial inlining, typically by inlining an if statement
10// that surrounds the body of the function.
11//
12//===----------------------------------------------------------------------===//
13
15#include "llvm/ADT/DenseMap.h"
16#include "llvm/ADT/DenseSet.h"
18#include "llvm/ADT/STLExtras.h"
20#include "llvm/ADT/Statistic.h"
29#include "llvm/IR/Attributes.h"
30#include "llvm/IR/BasicBlock.h"
31#include "llvm/IR/CFG.h"
32#include "llvm/IR/CycleInfo.h"
33#include "llvm/IR/DebugLoc.h"
35#include "llvm/IR/Dominators.h"
36#include "llvm/IR/Function.h"
37#include "llvm/IR/InstrTypes.h"
38#include "llvm/IR/Instruction.h"
41#include "llvm/IR/Intrinsics.h"
42#include "llvm/IR/Module.h"
43#include "llvm/IR/Operator.h"
45#include "llvm/IR/User.h"
51#include "llvm/Transforms/IPO.h"
55#include <algorithm>
56#include <cassert>
57#include <cstdint>
58#include <memory>
59#include <tuple>
60#include <vector>
61
62using namespace llvm;
63
64#define DEBUG_TYPE "partial-inlining"
65
66STATISTIC(NumPartialInlined,
67 "Number of callsites functions partially inlined into.");
68STATISTIC(NumColdOutlinePartialInlined, "Number of times functions with "
69 "cold outlined regions were partially "
70 "inlined into its caller(s).");
71STATISTIC(NumColdRegionsFound,
72 "Number of cold single entry/exit regions found.");
73STATISTIC(NumColdRegionsOutlined,
74 "Number of cold single entry/exit regions outlined.");
75
76// Command line option to disable partial-inlining. The default is false:
77static cl::opt<bool>
78 DisablePartialInlining("disable-partial-inlining", cl::init(false),
79 cl::Hidden, cl::desc("Disable partial inlining"));
80// Command line option to disable multi-region partial-inlining. The default is
81// false:
83 "disable-mr-partial-inlining", cl::init(false), cl::Hidden,
84 cl::desc("Disable multi-region partial inlining"));
85
86// Command line option to force outlining in regions with live exit variables.
87// The default is false:
88static cl::opt<bool>
89 ForceLiveExit("pi-force-live-exit-outline", cl::init(false), cl::Hidden,
90 cl::desc("Force outline regions with live exits"));
91
92// Command line option to enable marking outline functions with Cold Calling
93// Convention. The default is false:
94static cl::opt<bool>
95 MarkOutlinedColdCC("pi-mark-coldcc", cl::init(false), cl::Hidden,
96 cl::desc("Mark outline function calls with ColdCC"));
97
98// This is an option used by testing:
99static cl::opt<bool> SkipCostAnalysis("skip-partial-inlining-cost-analysis",
100
102 cl::desc("Skip Cost Analysis"));
103// Used to determine if a cold region is worth outlining based on
104// its inlining cost compared to the original function. Default is set at 10%.
105// ie. if the cold region reduces the inlining cost of the original function by
106// at least 10%.
108 "min-region-size-ratio", cl::init(0.1), cl::Hidden,
109 cl::desc("Minimum ratio comparing relative sizes of each "
110 "outline candidate and original function"));
111// Used to tune the minimum number of execution counts needed in the predecessor
112// block to the cold edge. ie. confidence interval.
114 MinBlockCounterExecution("min-block-execution", cl::init(100), cl::Hidden,
115 cl::desc("Minimum block executions to consider "
116 "its BranchProbabilityInfo valid"));
117// Used to determine when an edge is considered cold. Default is set to 10%. ie.
118// if the branch probability is 10% or less, then it is deemed as 'cold'.
120 "cold-branch-ratio", cl::init(0.1), cl::Hidden,
121 cl::desc("Minimum BranchProbability to consider a region cold."));
122
124 "max-num-inline-blocks", cl::init(5), cl::Hidden,
125 cl::desc("Max number of blocks to be partially inlined"));
126
127// Command line option to set the maximum number of partial inlining allowed
128// for the module. The default value of -1 means no limit.
130 "max-partial-inlining", cl::init(-1), cl::Hidden,
131 cl::desc("Max number of partial inlining. The default is unlimited"));
132
133// Used only when PGO or user annotated branch data is absent. It is
134// the least value that is used to weigh the outline region. If BFI
135// produces larger value, the BFI value will be used.
136static cl::opt<int>
137 OutlineRegionFreqPercent("outline-region-freq-percent", cl::init(75),
139 cl::desc("Relative frequency of outline region to "
140 "the entry block"));
141
143 "partial-inlining-extra-penalty", cl::init(0), cl::Hidden,
144 cl::desc("A debug option to add additional penalty to the computed one."));
145
146namespace {
147
148struct FunctionOutliningInfo {
149 FunctionOutliningInfo() = default;
150
151 // Returns the number of blocks to be inlined including all blocks
152 // in Entries and one return block.
153 unsigned getNumInlinedBlocks() const { return Entries.size() + 1; }
154
155 // A set of blocks including the function entry that guard
156 // the region to be outlined.
158
159 // The return block that is not included in the outlined region.
160 BasicBlock *ReturnBlock = nullptr;
161
162 // The dominating block of the region to be outlined.
163 BasicBlock *NonReturnBlock = nullptr;
164
165 // The set of blocks in Entries that are predecessors to ReturnBlock
166 SmallVector<BasicBlock *, 4> ReturnBlockPreds;
167};
168
169struct FunctionOutliningMultiRegionInfo {
170 FunctionOutliningMultiRegionInfo() = default;
171
172 // Container for outline regions
173 struct OutlineRegionInfo {
174 OutlineRegionInfo(ArrayRef<BasicBlock *> Region, BasicBlock *EntryBlock,
175 BasicBlock *ExitBlock, BasicBlock *ReturnBlock)
176 : Region(Region), EntryBlock(EntryBlock), ExitBlock(ExitBlock),
177 ReturnBlock(ReturnBlock) {}
178 SmallVector<BasicBlock *, 8> Region;
179 BasicBlock *EntryBlock;
180 BasicBlock *ExitBlock;
181 BasicBlock *ReturnBlock;
182 };
183
185};
186
187struct PartialInlinerImpl {
188
189 PartialInlinerImpl(
190 function_ref<AssumptionCache &(Function &)> GetAC,
191 function_ref<AssumptionCache *(Function &)> LookupAC,
192 function_ref<TargetTransformInfo &(Function &)> GTTI,
193 function_ref<const TargetLibraryInfo &(Function &)> GTLI,
194 ProfileSummaryInfo &ProfSI,
195 function_ref<BlockFrequencyInfo &(Function &)> GBFI = nullptr)
196 : GetAssumptionCache(GetAC), LookupAssumptionCache(LookupAC),
197 GetTTI(GTTI), GetBFI(GBFI), GetTLI(GTLI), PSI(ProfSI) {}
198
199 bool run(Module &M);
200 // Main part of the transformation that calls helper functions to find
201 // outlining candidates, clone & outline the function, and attempt to
202 // partially inline the resulting function. Returns true if
203 // inlining was successful, false otherwise. Also returns the outline
204 // function (only if we partially inlined early returns) as there is a
205 // possibility to further "peel" early return statements that were left in the
206 // outline function due to code size.
207 std::pair<bool, Function *> unswitchFunction(Function &F);
208
209 // This class speculatively clones the function to be partial inlined.
210 // At the end of partial inlining, the remaining callsites to the cloned
211 // function that are not partially inlined will be fixed up to reference
212 // the original function, and the cloned function will be erased.
213 struct FunctionCloner {
214 // Two constructors, one for single region outlining, the other for
215 // multi-region outlining.
216 FunctionCloner(Function *F, FunctionOutliningInfo *OI,
217 OptimizationRemarkEmitter &ORE,
218 function_ref<AssumptionCache *(Function &)> LookupAC,
219 function_ref<TargetTransformInfo &(Function &)> GetTTI);
220 FunctionCloner(Function *F, FunctionOutliningMultiRegionInfo *OMRI,
221 OptimizationRemarkEmitter &ORE,
222 function_ref<AssumptionCache *(Function &)> LookupAC,
223 function_ref<TargetTransformInfo &(Function &)> GetTTI);
224
225 ~FunctionCloner();
226
227 // Prepare for function outlining: making sure there is only
228 // one incoming edge from the extracted/outlined region to
229 // the return block.
230 void normalizeReturnBlock() const;
231
232 // Do function outlining for cold regions.
233 bool doMultiRegionFunctionOutlining();
234 // Do function outlining for region after early return block(s).
235 // NOTE: For vararg functions that do the vararg handling in the outlined
236 // function, we temporarily generate IR that does not properly
237 // forward varargs to the outlined function. Calling InlineFunction
238 // will update calls to the outlined functions to properly forward
239 // the varargs.
240 Function *doSingleRegionFunctionOutlining();
241
242 Function *OrigFunc = nullptr;
243 Function *ClonedFunc = nullptr;
244
245 typedef std::pair<Function *, BasicBlock *> FuncBodyCallerPair;
246 // Keep track of Outlined Functions and the basic block they're called from.
247 SmallVector<FuncBodyCallerPair, 4> OutlinedFunctions;
248
249 // ClonedFunc is inlined in one of its callers after function
250 // outlining.
251 bool IsFunctionInlined = false;
252 // The cost of the region to be outlined.
253 InstructionCost OutlinedRegionCost = 0;
254 // ClonedOI is specific to outlining non-early return blocks.
255 std::unique_ptr<FunctionOutliningInfo> ClonedOI = nullptr;
256 // ClonedOMRI is specific to outlining cold regions.
257 std::unique_ptr<FunctionOutliningMultiRegionInfo> ClonedOMRI = nullptr;
258 std::unique_ptr<BlockFrequencyInfo> ClonedFuncBFI = nullptr;
259 OptimizationRemarkEmitter &ORE;
260 function_ref<AssumptionCache *(Function &)> LookupAC;
261 function_ref<TargetTransformInfo &(Function &)> GetTTI;
262 };
263
264private:
265 int NumPartialInlining = 0;
266 function_ref<AssumptionCache &(Function &)> GetAssumptionCache;
267 function_ref<AssumptionCache *(Function &)> LookupAssumptionCache;
268 function_ref<TargetTransformInfo &(Function &)> GetTTI;
269 function_ref<BlockFrequencyInfo &(Function &)> GetBFI;
270 function_ref<const TargetLibraryInfo &(Function &)> GetTLI;
271 ProfileSummaryInfo &PSI;
272
273 // Return the frequency of the OutlininingBB relative to F's entry point.
274 // The result is no larger than 1 and is represented using BP.
275 // (Note that the outlined region's 'head' block can only have incoming
276 // edges from the guarding entry blocks).
277 BranchProbability
278 getOutliningCallBBRelativeFreq(FunctionCloner &Cloner) const;
279
280 // Return true if the callee of CB should be partially inlined with
281 // profit.
282 bool shouldPartialInline(CallBase &CB, FunctionCloner &Cloner,
283 BlockFrequency WeightedOutliningRcost,
284 OptimizationRemarkEmitter &ORE) const;
285
286 // Try to inline DuplicateFunction (cloned from F with call to
287 // the OutlinedFunction into its callers. Return true
288 // if there is any successful inlining.
289 bool tryPartialInline(FunctionCloner &Cloner);
290
291 // Compute the mapping from use site of DuplicationFunction to the enclosing
292 // BB's profile count.
293 void
294 computeCallsiteToProfCountMap(Function *DuplicateFunction,
295 DenseMap<User *, uint64_t> &SiteCountMap) const;
296
297 bool isLimitReached() const {
298 return (MaxNumPartialInlining != -1 &&
299 NumPartialInlining >= MaxNumPartialInlining);
300 }
301
302 static CallBase *getSupportedCallBase(User *U) {
303 if (isa<CallInst>(U) || isa<InvokeInst>(U))
304 return cast<CallBase>(U);
305 llvm_unreachable("All uses must be calls");
306 return nullptr;
307 }
308
309 static CallBase *getOneCallSiteTo(Function &F) {
310 User *User = *F.user_begin();
311 return getSupportedCallBase(User);
312 }
313
314 std::tuple<DebugLoc, BasicBlock *> getOneDebugLoc(Function &F) const {
315 CallBase *CB = getOneCallSiteTo(F);
316 DebugLoc DLoc = CB->getDebugLoc();
317 BasicBlock *Block = CB->getParent();
318 return std::make_tuple(DLoc, Block);
319 }
320
321 // Returns the costs associated with function outlining:
322 // - The first value is the non-weighted runtime cost for making the call
323 // to the outlined function, including the addtional setup cost in the
324 // outlined function itself;
325 // - The second value is the estimated size of the new call sequence in
326 // basic block Cloner.OutliningCallBB;
327 std::tuple<InstructionCost, InstructionCost>
328 computeOutliningCosts(FunctionCloner &Cloner) const;
329
330 // Compute the 'InlineCost' of block BB. InlineCost is a proxy used to
331 // approximate both the size and runtime cost (Note that in the current
332 // inline cost analysis, there is no clear distinction there either).
333 static InstructionCost computeBBInlineCost(BasicBlock *BB,
334 TargetTransformInfo *TTI);
335
336 std::unique_ptr<FunctionOutliningInfo>
337 computeOutliningInfo(Function &F) const;
338
339 std::unique_ptr<FunctionOutliningMultiRegionInfo>
340 computeOutliningColdRegionsInfo(Function &F,
341 OptimizationRemarkEmitter &ORE) const;
342};
343
344} // end anonymous namespace
345
346std::unique_ptr<FunctionOutliningMultiRegionInfo>
347PartialInlinerImpl::computeOutliningColdRegionsInfo(
348 Function &F, OptimizationRemarkEmitter &ORE) const {
349 BasicBlock *EntryBlock = &F.front();
350
351 DominatorTree DT(F);
352 CycleInfo CI;
353 CI.compute(F);
354 LoopInfo LI(DT);
355 BranchProbabilityInfo BPI(F, CI);
356 std::unique_ptr<BlockFrequencyInfo> ScopedBFI;
357 BlockFrequencyInfo *BFI;
358 if (!GetBFI) {
359 ScopedBFI.reset(new BlockFrequencyInfo(F, BPI, CI));
360 BFI = ScopedBFI.get();
361 } else
362 BFI = &(GetBFI(F));
363
364 // Return if we don't have profiling information.
365 if (!PSI.hasInstrumentationProfile())
366 return std::unique_ptr<FunctionOutliningMultiRegionInfo>();
367
368 std::unique_ptr<FunctionOutliningMultiRegionInfo> OutliningInfo =
369 std::make_unique<FunctionOutliningMultiRegionInfo>();
370
371 auto IsSingleExit =
372 [&ORE](SmallVectorImpl<BasicBlock *> &BlockList) -> BasicBlock * {
373 BasicBlock *ExitBlock = nullptr;
374 for (auto *Block : BlockList) {
375 for (BasicBlock *Succ : successors(Block)) {
376 if (!is_contained(BlockList, Succ)) {
377 if (ExitBlock) {
378 ORE.emit([&]() {
379 return OptimizationRemarkMissed(DEBUG_TYPE, "MultiExitRegion",
380 &Succ->front())
381 << "Region dominated by "
382 << ore::NV("Block", BlockList.front()->getName())
383 << " has more than one region exit edge.";
384 });
385 return nullptr;
386 }
387
388 ExitBlock = Block;
389 }
390 }
391 }
392 return ExitBlock;
393 };
394
395 auto BBProfileCount = [BFI](BasicBlock *BB) {
396 return BFI->getBlockProfileCount(BB).value_or(0);
397 };
398
399 // Use the same computeBBInlineCost function to compute the cost savings of
400 // the outlining the candidate region.
401 TargetTransformInfo *FTTI = &GetTTI(F);
402 InstructionCost OverallFunctionCost = 0;
403 for (auto &BB : F)
404 OverallFunctionCost += computeBBInlineCost(&BB, FTTI);
405
406 LLVM_DEBUG(dbgs() << "OverallFunctionCost = " << OverallFunctionCost
407 << "\n";);
408
409 InstructionCost MinOutlineRegionCost = OverallFunctionCost.map(
410 [&](auto Cost) { return Cost * MinRegionSizeRatio; });
411
412 BranchProbability MinBranchProbability(
413 static_cast<int>(ColdBranchRatio * MinBlockCounterExecution),
415 bool ColdCandidateFound = false;
416 BasicBlock *CurrEntry = EntryBlock;
417 std::vector<BasicBlock *> DFS;
418 SmallPtrSet<BasicBlock *, 8> VisitedSet;
419 DFS.push_back(CurrEntry);
420 VisitedSet.insert(CurrEntry);
421
422 // Use Depth First Search on the basic blocks to find CFG edges that are
423 // considered cold.
424 // Cold regions considered must also have its inline cost compared to the
425 // overall inline cost of the original function. The region is outlined only
426 // if it reduced the inline cost of the function by 'MinOutlineRegionCost' or
427 // more.
428 while (!DFS.empty()) {
429 auto *ThisBB = DFS.back();
430 DFS.pop_back();
431 // Only consider regions with predecessor blocks that are considered
432 // not-cold (default: part of the top 99.99% of all block counters)
433 // AND greater than our minimum block execution count (default: 100).
434 if (PSI.isColdBlock(ThisBB, BFI) ||
435 BBProfileCount(ThisBB) < MinBlockCounterExecution)
436 continue;
437 for (auto SI = succ_begin(ThisBB); SI != succ_end(ThisBB); ++SI) {
438 if (!VisitedSet.insert(*SI).second)
439 continue;
440 DFS.push_back(*SI);
441 // If branch isn't cold, we skip to the next one.
442 BranchProbability SuccProb = BPI.getEdgeProbability(ThisBB, *SI);
443 if (SuccProb > MinBranchProbability)
444 continue;
445
446 LLVM_DEBUG(dbgs() << "Found cold edge: " << ThisBB->getName() << "->"
447 << SI->getName()
448 << "\nBranch Probability = " << SuccProb << "\n";);
449
450 SmallVector<BasicBlock *, 8> DominateVector;
451 DT.getDescendants(*SI, DominateVector);
452 assert(!DominateVector.empty() &&
453 "SI should be reachable and have at least itself as descendant");
454
455 // We can only outline single entry regions (for now).
456 if (!DominateVector.front()->hasNPredecessors(1)) {
457 LLVM_DEBUG(dbgs() << "ABORT: Block " << SI->getName()
458 << " doesn't have a single predecessor in the "
459 "dominator tree\n";);
460 continue;
461 }
462
463 BasicBlock *ExitBlock = nullptr;
464 // We can only outline single exit regions (for now).
465 if (!(ExitBlock = IsSingleExit(DominateVector))) {
466 LLVM_DEBUG(dbgs() << "ABORT: Block " << SI->getName()
467 << " doesn't have a unique successor\n";);
468 continue;
469 }
470
471 InstructionCost OutlineRegionCost = 0;
472 for (auto *BB : DominateVector)
473 OutlineRegionCost += computeBBInlineCost(BB, &GetTTI(*BB->getParent()));
474
475 LLVM_DEBUG(dbgs() << "OutlineRegionCost = " << OutlineRegionCost
476 << "\n";);
477
478 if (!SkipCostAnalysis && OutlineRegionCost < MinOutlineRegionCost) {
479 ORE.emit([&]() {
480 return OptimizationRemarkAnalysis(DEBUG_TYPE, "TooCostly",
481 &SI->front())
482 << ore::NV("Callee", &F)
483 << " inline cost-savings smaller than "
484 << ore::NV("Cost", MinOutlineRegionCost);
485 });
486
487 LLVM_DEBUG(dbgs() << "ABORT: Outline region cost is smaller than "
488 << MinOutlineRegionCost << "\n";);
489 continue;
490 }
491
492 // For now, ignore blocks that belong to a SISE region that is a
493 // candidate for outlining. In the future, we may want to look
494 // at inner regions because the outer region may have live-exit
495 // variables.
496 VisitedSet.insert_range(DominateVector);
497
498 // ReturnBlock here means the block after the outline call
499 BasicBlock *ReturnBlock = ExitBlock->getSingleSuccessor();
500 FunctionOutliningMultiRegionInfo::OutlineRegionInfo RegInfo(
501 DominateVector, DominateVector.front(), ExitBlock, ReturnBlock);
502 OutliningInfo->ORI.push_back(RegInfo);
503 LLVM_DEBUG(dbgs() << "Found Cold Candidate starting at block: "
504 << DominateVector.front()->getName() << "\n";);
505 ColdCandidateFound = true;
506 NumColdRegionsFound++;
507 }
508 }
509
510 if (ColdCandidateFound)
511 return OutliningInfo;
512
513 return std::unique_ptr<FunctionOutliningMultiRegionInfo>();
514}
515
516std::unique_ptr<FunctionOutliningInfo>
517PartialInlinerImpl::computeOutliningInfo(Function &F) const {
518 BasicBlock *EntryBlock = &F.front();
519 CondBrInst *BR = dyn_cast<CondBrInst>(EntryBlock->getTerminator());
520 if (!BR)
521 return std::unique_ptr<FunctionOutliningInfo>();
522
523 // Returns true if Succ is BB's successor
524 auto IsSuccessor = [](BasicBlock *Succ, BasicBlock *BB) {
525 return is_contained(successors(BB), Succ);
526 };
527
528 auto IsReturnBlock = [](BasicBlock *BB) {
529 Instruction *TI = BB->getTerminator();
530 return isa<ReturnInst>(TI);
531 };
532
533 auto GetReturnBlock = [&](BasicBlock *Succ1, BasicBlock *Succ2) {
534 if (IsReturnBlock(Succ1))
535 return std::make_tuple(Succ1, Succ2);
536 if (IsReturnBlock(Succ2))
537 return std::make_tuple(Succ2, Succ1);
538
539 return std::make_tuple<BasicBlock *, BasicBlock *>(nullptr, nullptr);
540 };
541
542 // Detect a triangular shape:
543 auto GetCommonSucc = [&](BasicBlock *Succ1, BasicBlock *Succ2) {
544 if (IsSuccessor(Succ1, Succ2))
545 return std::make_tuple(Succ1, Succ2);
546 if (IsSuccessor(Succ2, Succ1))
547 return std::make_tuple(Succ2, Succ1);
548
549 return std::make_tuple<BasicBlock *, BasicBlock *>(nullptr, nullptr);
550 };
551
552 std::unique_ptr<FunctionOutliningInfo> OutliningInfo =
553 std::make_unique<FunctionOutliningInfo>();
554
555 BasicBlock *CurrEntry = EntryBlock;
556 bool CandidateFound = false;
557 do {
558 // The number of blocks to be inlined has already reached
559 // the limit. When MaxNumInlineBlocks is set to 0 or 1, this
560 // disables partial inlining for the function.
561 if (OutliningInfo->getNumInlinedBlocks() >= MaxNumInlineBlocks)
562 break;
563
564 if (succ_size(CurrEntry) != 2)
565 break;
566
567 BasicBlock *Succ1 = *succ_begin(CurrEntry);
568 BasicBlock *Succ2 = *(succ_begin(CurrEntry) + 1);
569
570 BasicBlock *ReturnBlock, *NonReturnBlock;
571 std::tie(ReturnBlock, NonReturnBlock) = GetReturnBlock(Succ1, Succ2);
572
573 if (ReturnBlock) {
574 OutliningInfo->Entries.push_back(CurrEntry);
575 OutliningInfo->ReturnBlock = ReturnBlock;
576 OutliningInfo->NonReturnBlock = NonReturnBlock;
577 CandidateFound = true;
578 break;
579 }
580
581 BasicBlock *CommSucc, *OtherSucc;
582 std::tie(CommSucc, OtherSucc) = GetCommonSucc(Succ1, Succ2);
583
584 if (!CommSucc)
585 break;
586
587 OutliningInfo->Entries.push_back(CurrEntry);
588 CurrEntry = OtherSucc;
589 } while (true);
590
591 if (!CandidateFound)
592 return std::unique_ptr<FunctionOutliningInfo>();
593
594 // There should not be any successors (not in the entry set) other than
595 // {ReturnBlock, NonReturnBlock}
596 assert(OutliningInfo->Entries[0] == &F.front() &&
597 "Function Entry must be the first in Entries vector");
598 DenseSet<BasicBlock *> Entries(llvm::from_range, OutliningInfo->Entries);
599
600 // Returns true of BB has Predecessor which is not
601 // in Entries set.
602 auto HasNonEntryPred = [Entries](BasicBlock *BB) {
603 for (auto *Pred : predecessors(BB)) {
604 if (!Entries.count(Pred))
605 return true;
606 }
607 return false;
608 };
609 auto CheckAndNormalizeCandidate =
610 [Entries, HasNonEntryPred](FunctionOutliningInfo *OutliningInfo) {
611 for (BasicBlock *E : OutliningInfo->Entries) {
612 for (auto *Succ : successors(E)) {
613 if (Entries.count(Succ))
614 continue;
615 if (Succ == OutliningInfo->ReturnBlock)
616 OutliningInfo->ReturnBlockPreds.push_back(E);
617 else if (Succ != OutliningInfo->NonReturnBlock)
618 return false;
619 }
620 // There should not be any outside incoming edges either:
621 if (HasNonEntryPred(E))
622 return false;
623 }
624 return true;
625 };
626
627 if (!CheckAndNormalizeCandidate(OutliningInfo.get()))
628 return std::unique_ptr<FunctionOutliningInfo>();
629
630 // Now further growing the candidate's inlining region by
631 // peeling off dominating blocks from the outlining region:
632 while (OutliningInfo->getNumInlinedBlocks() < MaxNumInlineBlocks) {
633 BasicBlock *Cand = OutliningInfo->NonReturnBlock;
634 if (succ_size(Cand) != 2)
635 break;
636
637 if (HasNonEntryPred(Cand))
638 break;
639
640 BasicBlock *Succ1 = *succ_begin(Cand);
641 BasicBlock *Succ2 = *(succ_begin(Cand) + 1);
642
643 BasicBlock *ReturnBlock, *NonReturnBlock;
644 std::tie(ReturnBlock, NonReturnBlock) = GetReturnBlock(Succ1, Succ2);
645 if (!ReturnBlock || ReturnBlock != OutliningInfo->ReturnBlock)
646 break;
647
648 if (NonReturnBlock->getSinglePredecessor() != Cand)
649 break;
650
651 // Now grow and update OutlininigInfo:
652 OutliningInfo->Entries.push_back(Cand);
653 OutliningInfo->NonReturnBlock = NonReturnBlock;
654 OutliningInfo->ReturnBlockPreds.push_back(Cand);
655 Entries.insert(Cand);
656 }
657
658 return OutliningInfo;
659}
660
661// Check if there is PGO data or user annotated branch data:
662static bool hasProfileData(const Function &F, const FunctionOutliningInfo &OI) {
663 if (F.hasProfileData())
664 return true;
665 // Now check if any of the entry block has MD_prof data:
666 for (auto *E : OI.Entries) {
667 CondBrInst *BR = dyn_cast<CondBrInst>(E->getTerminator());
668 if (BR && hasBranchWeightMD(*BR))
669 return true;
670 }
671 return false;
672}
673
674BranchProbability PartialInlinerImpl::getOutliningCallBBRelativeFreq(
675 FunctionCloner &Cloner) const {
676 BasicBlock *OutliningCallBB = Cloner.OutlinedFunctions.back().second;
677 auto EntryFreq =
678 Cloner.ClonedFuncBFI->getBlockFreq(&Cloner.ClonedFunc->getEntryBlock());
679 auto OutliningCallFreq =
680 Cloner.ClonedFuncBFI->getBlockFreq(OutliningCallBB);
681 // FIXME Hackery needed because ClonedFuncBFI is based on the function BEFORE
682 // we outlined any regions, so we may encounter situations where the
683 // OutliningCallFreq is *slightly* bigger than the EntryFreq.
684 if (OutliningCallFreq.getFrequency() > EntryFreq.getFrequency())
685 OutliningCallFreq = EntryFreq;
686
687 auto OutlineRegionRelFreq = BranchProbability::getBranchProbability(
688 OutliningCallFreq.getFrequency(), EntryFreq.getFrequency());
689
690 if (hasProfileData(*Cloner.OrigFunc, *Cloner.ClonedOI))
691 return OutlineRegionRelFreq;
692
693 // When profile data is not available, we need to be conservative in
694 // estimating the overall savings. Static branch prediction can usually
695 // guess the branch direction right (taken/non-taken), but the guessed
696 // branch probability is usually not biased enough. In case when the
697 // outlined region is predicted to be likely, its probability needs
698 // to be made higher (more biased) to not under-estimate the cost of
699 // function outlining. On the other hand, if the outlined region
700 // is predicted to be less likely, the predicted probablity is usually
701 // higher than the actual. For instance, the actual probability of the
702 // less likely target is only 5%, but the guessed probablity can be
703 // 40%. In the latter case, there is no need for further adjustment.
704 // FIXME: add an option for this.
705 if (OutlineRegionRelFreq < BranchProbability(45, 100))
706 return OutlineRegionRelFreq;
707
708 OutlineRegionRelFreq = std::max(
709 OutlineRegionRelFreq, BranchProbability(OutlineRegionFreqPercent, 100));
710
711 return OutlineRegionRelFreq;
712}
713
714bool PartialInlinerImpl::shouldPartialInline(
715 CallBase &CB, FunctionCloner &Cloner, BlockFrequency WeightedOutliningRcost,
716 OptimizationRemarkEmitter &ORE) const {
717 using namespace ore;
718
720 assert(Callee == Cloner.ClonedFunc);
721
723 return isInlineViable(*Callee).isSuccess();
724
725 Function *Caller = CB.getCaller();
726 auto &CalleeTTI = GetTTI(*Callee);
727 bool RemarksEnabled =
728 Callee->getContext().getDiagHandlerPtr()->isMissedOptRemarkEnabled(
729 DEBUG_TYPE);
730 InlineCost IC =
731 getInlineCost(CB, getInlineParams(), CalleeTTI, GetAssumptionCache,
732 GetTLI, GetBFI, &PSI, RemarksEnabled ? &ORE : nullptr);
733
734 if (IC.isAlways()) {
735 ORE.emit([&]() {
736 return OptimizationRemarkAnalysis(DEBUG_TYPE, "AlwaysInline", &CB)
737 << NV("Callee", Cloner.OrigFunc)
738 << " should always be fully inlined, not partially";
739 });
740 return false;
741 }
742
743 if (IC.isNever()) {
744 ORE.emit([&]() {
745 return OptimizationRemarkMissed(DEBUG_TYPE, "NeverInline", &CB)
746 << NV("Callee", Cloner.OrigFunc) << " not partially inlined into "
747 << NV("Caller", Caller)
748 << " because it should never be inlined (cost=never)";
749 });
750 return false;
751 }
752
753 if (!IC) {
754 ORE.emit([&]() {
755 return OptimizationRemarkAnalysis(DEBUG_TYPE, "TooCostly", &CB)
756 << NV("Callee", Cloner.OrigFunc) << " not partially inlined into "
757 << NV("Caller", Caller) << " because too costly to inline (cost="
758 << NV("Cost", IC.getCost()) << ", threshold="
759 << NV("Threshold", IC.getCostDelta() + IC.getCost()) << ")";
760 });
761 return false;
762 }
763 const DataLayout &DL = Caller->getDataLayout();
764
765 // The savings of eliminating the call:
766 int NonWeightedSavings = getCallsiteCost(CalleeTTI, CB, DL);
767 BlockFrequency NormWeightedSavings(NonWeightedSavings);
768
769 // Weighted saving is smaller than weighted cost, return false
770 if (NormWeightedSavings < WeightedOutliningRcost) {
771 ORE.emit([&]() {
772 return OptimizationRemarkAnalysis(DEBUG_TYPE, "OutliningCallcostTooHigh",
773 &CB)
774 << NV("Callee", Cloner.OrigFunc) << " not partially inlined into "
775 << NV("Caller", Caller) << " runtime overhead (overhead="
776 << NV("Overhead", (unsigned)WeightedOutliningRcost.getFrequency())
777 << ", savings="
778 << NV("Savings", (unsigned)NormWeightedSavings.getFrequency())
779 << ")"
780 << " of making the outlined call is too high";
781 });
782
783 return false;
784 }
785
786 ORE.emit([&]() {
787 return OptimizationRemarkAnalysis(DEBUG_TYPE, "CanBePartiallyInlined", &CB)
788 << NV("Callee", Cloner.OrigFunc) << " can be partially inlined into "
789 << NV("Caller", Caller) << " with cost=" << NV("Cost", IC.getCost())
790 << " (threshold="
791 << NV("Threshold", IC.getCostDelta() + IC.getCost()) << ")";
792 });
793 return true;
794}
795
796// TODO: Ideally we should share Inliner's InlineCost Analysis code.
797// For now use a simplified version. The returned 'InlineCost' will be used
798// to esimate the size cost as well as runtime cost of the BB.
800PartialInlinerImpl::computeBBInlineCost(BasicBlock *BB,
801 TargetTransformInfo *TTI) {
802 InstructionCost InlineCost = 0;
803 const DataLayout &DL = BB->getDataLayout();
805 for (Instruction &I : *BB) {
806 // Skip free instructions.
807 switch (I.getOpcode()) {
808 case Instruction::BitCast:
809 case Instruction::PtrToInt:
810 case Instruction::IntToPtr:
811 case Instruction::Alloca:
812 case Instruction::PHI:
813 continue;
814 case Instruction::GetElementPtr:
815 if (cast<GetElementPtrInst>(&I)->hasAllZeroIndices())
816 continue;
817 break;
818 default:
819 break;
820 }
821
822 if (I.isLifetimeStartOrEnd())
823 continue;
824
825 if (auto *II = dyn_cast<IntrinsicInst>(&I)) {
826 Intrinsic::ID IID = II->getIntrinsicID();
828 FastMathFlags FMF;
829 for (Value *Val : II->args())
830 Tys.push_back(Val->getType());
831
832 if (auto *FPMO = dyn_cast<FPMathOperator>(II))
833 FMF = FPMO->getFastMathFlags();
834
835 IntrinsicCostAttributes ICA(IID, II->getType(), Tys, FMF);
837 continue;
838 }
839
840 if (CallInst *CI = dyn_cast<CallInst>(&I)) {
841 InlineCost += getCallsiteCost(*TTI, *CI, DL);
842 continue;
843 }
844
845 if (InvokeInst *II = dyn_cast<InvokeInst>(&I)) {
846 InlineCost += getCallsiteCost(*TTI, *II, DL);
847 continue;
848 }
849
850 if (SwitchInst *SI = dyn_cast<SwitchInst>(&I)) {
851 InlineCost += (SI->getNumCases() + 1) * InstrCost;
852 continue;
853 }
854 InlineCost += InstrCost;
855 }
856
857 return InlineCost;
858}
859
860std::tuple<InstructionCost, InstructionCost>
861PartialInlinerImpl::computeOutliningCosts(FunctionCloner &Cloner) const {
862 InstructionCost OutliningFuncCallCost = 0, OutlinedFunctionCost = 0;
863 for (auto FuncBBPair : Cloner.OutlinedFunctions) {
864 Function *OutlinedFunc = FuncBBPair.first;
865 BasicBlock* OutliningCallBB = FuncBBPair.second;
866 // Now compute the cost of the call sequence to the outlined function
867 // 'OutlinedFunction' in BB 'OutliningCallBB':
868 auto *OutlinedFuncTTI = &GetTTI(*OutlinedFunc);
869 OutliningFuncCallCost +=
870 computeBBInlineCost(OutliningCallBB, OutlinedFuncTTI);
871
872 // Now compute the cost of the extracted/outlined function itself:
873 for (BasicBlock &BB : *OutlinedFunc)
874 OutlinedFunctionCost += computeBBInlineCost(&BB, OutlinedFuncTTI);
875 }
876 assert(OutlinedFunctionCost >= Cloner.OutlinedRegionCost &&
877 "Outlined function cost should be no less than the outlined region");
878
879 // The code extractor introduces a new root and exit stub blocks with
880 // additional unconditional branches. Those branches will be eliminated
881 // later with bb layout. The cost should be adjusted accordingly:
882 OutlinedFunctionCost -=
883 2 * InlineConstants::getInstrCost() * Cloner.OutlinedFunctions.size();
884
885 InstructionCost OutliningRuntimeOverhead =
886 OutliningFuncCallCost +
887 (OutlinedFunctionCost - Cloner.OutlinedRegionCost) +
889
890 return std::make_tuple(OutliningFuncCallCost, OutliningRuntimeOverhead);
891}
892
893// Create the callsite to profile count map which is
894// used to update the original function's entry count,
895// after the function is partially inlined into the callsite.
896void PartialInlinerImpl::computeCallsiteToProfCountMap(
897 Function *DuplicateFunction,
898 DenseMap<User *, uint64_t> &CallSiteToProfCountMap) const {
899 std::vector<User *> Users(DuplicateFunction->user_begin(),
900 DuplicateFunction->user_end());
901 Function *CurrentCaller = nullptr;
902 std::unique_ptr<BlockFrequencyInfo> TempBFI;
903 BlockFrequencyInfo *CurrentCallerBFI = nullptr;
904
905 auto ComputeCurrBFI = [&,this](Function *Caller) {
906 // For the old pass manager:
907 if (!GetBFI) {
908 CycleInfo CI;
909 CI.compute(*Caller);
910 BranchProbabilityInfo BPI(*Caller, CI);
911 TempBFI.reset(new BlockFrequencyInfo(*Caller, BPI, CI));
912 CurrentCallerBFI = TempBFI.get();
913 } else {
914 // New pass manager:
915 CurrentCallerBFI = &(GetBFI(*Caller));
916 }
917 };
918
919 for (User *User : Users) {
920 CallBase *CB = getSupportedCallBase(User);
921 Function *Caller = CB->getCaller();
922 if (CurrentCaller != Caller) {
923 CurrentCaller = Caller;
924 ComputeCurrBFI(Caller);
925 } else {
926 assert(CurrentCallerBFI && "CallerBFI is not set");
927 }
928 BasicBlock *CallBB = CB->getParent();
929 auto Count = CurrentCallerBFI->getBlockProfileCount(CallBB);
930 if (Count)
931 CallSiteToProfCountMap[User] = *Count;
932 else
933 CallSiteToProfCountMap[User] = 0;
934 }
935}
936
937PartialInlinerImpl::FunctionCloner::FunctionCloner(
938 Function *F, FunctionOutliningInfo *OI, OptimizationRemarkEmitter &ORE,
939 function_ref<AssumptionCache *(Function &)> LookupAC,
940 function_ref<TargetTransformInfo &(Function &)> GetTTI)
941 : OrigFunc(F), ORE(ORE), LookupAC(LookupAC), GetTTI(GetTTI) {
942 ClonedOI = std::make_unique<FunctionOutliningInfo>();
943
944 // Clone the function, so that we can hack away on it.
946 ClonedFunc = CloneFunction(F, VMap);
947
948 ClonedOI->ReturnBlock = cast<BasicBlock>(VMap[OI->ReturnBlock]);
949 ClonedOI->NonReturnBlock = cast<BasicBlock>(VMap[OI->NonReturnBlock]);
950 for (BasicBlock *BB : OI->Entries)
951 ClonedOI->Entries.push_back(cast<BasicBlock>(VMap[BB]));
952
953 for (BasicBlock *E : OI->ReturnBlockPreds) {
954 BasicBlock *NewE = cast<BasicBlock>(VMap[E]);
955 ClonedOI->ReturnBlockPreds.push_back(NewE);
956 }
957 // Go ahead and update all uses to the duplicate, so that we can just
958 // use the inliner functionality when we're done hacking.
959 F->replaceAllUsesWith(ClonedFunc);
960}
961
962PartialInlinerImpl::FunctionCloner::FunctionCloner(
963 Function *F, FunctionOutliningMultiRegionInfo *OI,
967 : OrigFunc(F), ORE(ORE), LookupAC(LookupAC), GetTTI(GetTTI) {
968 ClonedOMRI = std::make_unique<FunctionOutliningMultiRegionInfo>();
969
970 // Clone the function, so that we can hack away on it.
972 ClonedFunc = CloneFunction(F, VMap);
973
974 // Go through all Outline Candidate Regions and update all BasicBlock
975 // information.
976 for (const FunctionOutliningMultiRegionInfo::OutlineRegionInfo &RegionInfo :
977 OI->ORI) {
979 for (BasicBlock *BB : RegionInfo.Region)
980 Region.push_back(cast<BasicBlock>(VMap[BB]));
981
982 BasicBlock *NewEntryBlock = cast<BasicBlock>(VMap[RegionInfo.EntryBlock]);
983 BasicBlock *NewExitBlock = cast<BasicBlock>(VMap[RegionInfo.ExitBlock]);
984 BasicBlock *NewReturnBlock = nullptr;
985 if (RegionInfo.ReturnBlock)
986 NewReturnBlock = cast<BasicBlock>(VMap[RegionInfo.ReturnBlock]);
987 FunctionOutliningMultiRegionInfo::OutlineRegionInfo MappedRegionInfo(
988 Region, NewEntryBlock, NewExitBlock, NewReturnBlock);
989 ClonedOMRI->ORI.push_back(MappedRegionInfo);
990 }
991 // Go ahead and update all uses to the duplicate, so that we can just
992 // use the inliner functionality when we're done hacking.
993 F->replaceAllUsesWith(ClonedFunc);
994}
995
996void PartialInlinerImpl::FunctionCloner::normalizeReturnBlock() const {
997 auto GetFirstPHI = [](BasicBlock *BB) {
998 BasicBlock::iterator I = BB->begin();
999 PHINode *FirstPhi = nullptr;
1000 while (I != BB->end()) {
1001 PHINode *Phi = dyn_cast<PHINode>(I);
1002 if (!Phi)
1003 break;
1004 if (!FirstPhi) {
1005 FirstPhi = Phi;
1006 break;
1007 }
1008 }
1009 return FirstPhi;
1010 };
1011
1012 // Shouldn't need to normalize PHIs if we're not outlining non-early return
1013 // blocks.
1014 if (!ClonedOI)
1015 return;
1016
1017 // Special hackery is needed with PHI nodes that have inputs from more than
1018 // one extracted block. For simplicity, just split the PHIs into a two-level
1019 // sequence of PHIs, some of which will go in the extracted region, and some
1020 // of which will go outside.
1021 BasicBlock *PreReturn = ClonedOI->ReturnBlock;
1022 // only split block when necessary:
1023 PHINode *FirstPhi = GetFirstPHI(PreReturn);
1024 unsigned NumPredsFromEntries = ClonedOI->ReturnBlockPreds.size();
1025
1026 if (!FirstPhi || FirstPhi->getNumIncomingValues() <= NumPredsFromEntries + 1)
1027 return;
1028
1029 auto IsTrivialPhi = [](PHINode *PN) -> Value * {
1030 if (llvm::all_equal(PN->incoming_values()))
1031 return PN->getIncomingValue(0);
1032 return nullptr;
1033 };
1034
1035 ClonedOI->ReturnBlock = ClonedOI->ReturnBlock->splitBasicBlock(
1036 ClonedOI->ReturnBlock->getFirstNonPHIIt());
1037 BasicBlock::iterator I = PreReturn->begin();
1038 BasicBlock::iterator Ins = ClonedOI->ReturnBlock->begin();
1039 SmallVector<Instruction *, 4> DeadPhis;
1040 while (I != PreReturn->end()) {
1041 PHINode *OldPhi = dyn_cast<PHINode>(I);
1042 if (!OldPhi)
1043 break;
1044
1045 PHINode *RetPhi =
1046 PHINode::Create(OldPhi->getType(), NumPredsFromEntries + 1, "");
1047 RetPhi->insertBefore(Ins);
1048 OldPhi->replaceAllUsesWith(RetPhi);
1049 Ins = ClonedOI->ReturnBlock->getFirstNonPHIIt();
1050
1051 RetPhi->addIncoming(&*I, PreReturn);
1052 for (BasicBlock *E : ClonedOI->ReturnBlockPreds) {
1053 RetPhi->addIncoming(OldPhi->getIncomingValueForBlock(E), E);
1054 OldPhi->removeIncomingValue(E);
1055 }
1056
1057 // After incoming values splitting, the old phi may become trivial.
1058 // Keeping the trivial phi can introduce definition inside the outline
1059 // region which is live-out, causing necessary overhead (load, store
1060 // arg passing etc).
1061 if (auto *OldPhiVal = IsTrivialPhi(OldPhi)) {
1062 OldPhi->replaceAllUsesWith(OldPhiVal);
1063 DeadPhis.push_back(OldPhi);
1064 }
1065 ++I;
1066 }
1067 for (auto *DP : DeadPhis)
1068 DP->eraseFromParent();
1069
1070 for (auto *E : ClonedOI->ReturnBlockPreds)
1071 E->getTerminator()->replaceUsesOfWith(PreReturn, ClonedOI->ReturnBlock);
1072}
1073
1074bool PartialInlinerImpl::FunctionCloner::doMultiRegionFunctionOutlining() {
1075
1076 auto ComputeRegionCost =
1077 [&](SmallVectorImpl<BasicBlock *> &Region) -> InstructionCost {
1079 for (BasicBlock* BB : Region)
1080 Cost += computeBBInlineCost(BB, &GetTTI(*BB->getParent()));
1081 return Cost;
1082 };
1083
1084 assert(ClonedOMRI && "Expecting OutlineInfo for multi region outline");
1085
1086 if (ClonedOMRI->ORI.empty())
1087 return false;
1088
1089 // The CodeExtractor needs a dominator tree.
1090 DominatorTree DT;
1091 DT.recalculate(*ClonedFunc);
1092
1093 // Manually calculate a BlockFrequencyInfo and BranchProbabilityInfo.
1094 CycleInfo CI;
1095 CI.compute(*ClonedFunc);
1096 BranchProbabilityInfo BPI(*ClonedFunc, CI);
1097 ClonedFuncBFI.reset(new BlockFrequencyInfo(*ClonedFunc, BPI, CI));
1098
1099 // Cache and recycle the CodeExtractor analysis to avoid O(n^2) compile-time.
1100 CodeExtractorAnalysisCache CEAC(*ClonedFunc);
1101
1102 SetVector<Value *> Inputs, Outputs, Sinks;
1103 for (FunctionOutliningMultiRegionInfo::OutlineRegionInfo RegionInfo :
1104 ClonedOMRI->ORI) {
1105 InstructionCost CurrentOutlinedRegionCost =
1106 ComputeRegionCost(RegionInfo.Region);
1107
1108 CodeExtractor CE(RegionInfo.Region, &DT, /*AggregateArgs*/ false,
1109 ClonedFuncBFI.get(), &BPI,
1110 LookupAC(*RegionInfo.EntryBlock->getParent()),
1111 /* AllowVarargs */ false, /* AllowAlloca */ false,
1112 /* AllocaBlock */ nullptr, /* DeallocationBlocks */ {},
1113 /* Suffix */ "", /* ArgsInZeroAddressSpace */ false,
1114 /* VoidReturnWithSingleOutput */ false);
1115
1116 CE.findInputsOutputs(Inputs, Outputs, Sinks);
1117
1118 LLVM_DEBUG({
1119 dbgs() << "inputs: " << Inputs.size() << "\n";
1120 dbgs() << "outputs: " << Outputs.size() << "\n";
1121 for (Value *value : Inputs)
1122 dbgs() << "value used in func: " << *value << "\n";
1123 for (Value *output : Outputs)
1124 dbgs() << "instr used in func: " << *output << "\n";
1125 });
1126
1127 // Do not extract regions that have live exit variables.
1128 if (Outputs.size() > 0 && !ForceLiveExit)
1129 continue;
1130
1131 if (Function *OutlinedFunc = CE.extractCodeRegion(CEAC)) {
1132 CallBase *OCS = PartialInlinerImpl::getOneCallSiteTo(*OutlinedFunc);
1133 BasicBlock *OutliningCallBB = OCS->getParent();
1134 assert(OutliningCallBB->getParent() == ClonedFunc);
1135 OutlinedFunctions.push_back(std::make_pair(OutlinedFunc,OutliningCallBB));
1136 NumColdRegionsOutlined++;
1137 OutlinedRegionCost += CurrentOutlinedRegionCost;
1138
1139 if (MarkOutlinedColdCC) {
1140 OutlinedFunc->setCallingConv(CallingConv::Cold);
1141 OCS->setCallingConv(CallingConv::Cold);
1142 }
1143 } else
1144 ORE.emit([&]() {
1145 return OptimizationRemarkMissed(DEBUG_TYPE, "ExtractFailed",
1146 &RegionInfo.Region.front()->front())
1147 << "Failed to extract region at block "
1148 << ore::NV("Block", RegionInfo.Region.front());
1149 });
1150 }
1151
1152 return !OutlinedFunctions.empty();
1153}
1154
1155Function *
1156PartialInlinerImpl::FunctionCloner::doSingleRegionFunctionOutlining() {
1157 // Returns true if the block is to be partial inlined into the caller
1158 // (i.e. not to be extracted to the out of line function)
1159 auto ToBeInlined = [&, this](BasicBlock *BB) {
1160 return BB == ClonedOI->ReturnBlock ||
1161 llvm::is_contained(ClonedOI->Entries, BB);
1162 };
1163
1164 assert(ClonedOI && "Expecting OutlineInfo for single region outline");
1165 // The CodeExtractor needs a dominator tree.
1166 DominatorTree DT;
1167 DT.recalculate(*ClonedFunc);
1168
1169 // Manually calculate a BlockFrequencyInfo and BranchProbabilityInfo.
1170 CycleInfo CI;
1171 CI.compute(*ClonedFunc);
1172 BranchProbabilityInfo BPI(*ClonedFunc, CI);
1173 ClonedFuncBFI.reset(new BlockFrequencyInfo(*ClonedFunc, BPI, CI));
1174
1175 // Gather up the blocks that we're going to extract.
1176 std::vector<BasicBlock *> ToExtract;
1177 auto *ClonedFuncTTI = &GetTTI(*ClonedFunc);
1178 ToExtract.push_back(ClonedOI->NonReturnBlock);
1179 OutlinedRegionCost += PartialInlinerImpl::computeBBInlineCost(
1180 ClonedOI->NonReturnBlock, ClonedFuncTTI);
1181 for (BasicBlock *BB : depth_first(&ClonedFunc->getEntryBlock()))
1182 if (!ToBeInlined(BB) && BB != ClonedOI->NonReturnBlock) {
1183 ToExtract.push_back(BB);
1184 // FIXME: the code extractor may hoist/sink more code
1185 // into the outlined function which may make the outlining
1186 // overhead (the difference of the outlined function cost
1187 // and OutliningRegionCost) look larger.
1188 OutlinedRegionCost += computeBBInlineCost(BB, ClonedFuncTTI);
1189 }
1190
1191 // Extract the body of the if.
1192 CodeExtractorAnalysisCache CEAC(*ClonedFunc);
1193 Function *OutlinedFunc =
1194 CodeExtractor(ToExtract, &DT, /*AggregateArgs*/ false,
1195 ClonedFuncBFI.get(), &BPI, LookupAC(*ClonedFunc),
1196 /* AllowVarargs */ true, /* AllowAlloca */ false,
1197 /* AllocaBlock */ nullptr, /* DeallocationBlocks */ {},
1198 /* Suffix */ "", /* ArgsInZeroAddressSpace */ false,
1199 /* VoidReturnWithSingleOutput */ false)
1200 .extractCodeRegion(CEAC);
1201
1202 if (OutlinedFunc) {
1203 BasicBlock *OutliningCallBB =
1204 PartialInlinerImpl::getOneCallSiteTo(*OutlinedFunc)->getParent();
1205 assert(OutliningCallBB->getParent() == ClonedFunc);
1206 OutlinedFunctions.push_back(std::make_pair(OutlinedFunc, OutliningCallBB));
1207 } else
1208 ORE.emit([&]() {
1209 return OptimizationRemarkMissed(DEBUG_TYPE, "ExtractFailed",
1210 &ToExtract.front()->front())
1211 << "Failed to extract region at block "
1212 << ore::NV("Block", ToExtract.front());
1213 });
1214
1215 return OutlinedFunc;
1216}
1217
1218PartialInlinerImpl::FunctionCloner::~FunctionCloner() {
1219 // Ditch the duplicate, since we're done with it, and rewrite all remaining
1220 // users (function pointers, etc.) back to the original function.
1221 ClonedFunc->replaceAllUsesWith(OrigFunc);
1222 ClonedFunc->eraseFromParent();
1223 if (!IsFunctionInlined) {
1224 // Remove each function that was speculatively created if there is no
1225 // reference.
1226 for (auto FuncBBPair : OutlinedFunctions) {
1227 Function *Func = FuncBBPair.first;
1228 Func->eraseFromParent();
1229 }
1230 }
1231}
1232
1233std::pair<bool, Function *> PartialInlinerImpl::unswitchFunction(Function &F) {
1234 if (F.hasAddressTaken())
1235 return {false, nullptr};
1236
1237 // Let inliner handle it
1238 if (F.hasFnAttribute(Attribute::AlwaysInline))
1239 return {false, nullptr};
1240
1241 if (F.hasFnAttribute(Attribute::NoInline))
1242 return {false, nullptr};
1243
1244 if (PSI.isFunctionEntryCold(&F))
1245 return {false, nullptr};
1246
1247 if (F.users().empty())
1248 return {false, nullptr};
1249
1250 OptimizationRemarkEmitter ORE(&F);
1251
1252 // Only try to outline cold regions if we have a profile summary, which
1253 // implies we have profiling information.
1254 if (PSI.hasProfileSummary() && F.hasProfileData() &&
1256 std::unique_ptr<FunctionOutliningMultiRegionInfo> OMRI =
1257 computeOutliningColdRegionsInfo(F, ORE);
1258 if (OMRI) {
1259 FunctionCloner Cloner(&F, OMRI.get(), ORE, LookupAssumptionCache, GetTTI);
1260
1261 LLVM_DEBUG({
1262 dbgs() << "HotCountThreshold = " << PSI.getHotCountThreshold() << "\n";
1263 dbgs() << "ColdCountThreshold = " << PSI.getColdCountThreshold()
1264 << "\n";
1265 });
1266
1267 bool DidOutline = Cloner.doMultiRegionFunctionOutlining();
1268
1269 if (DidOutline) {
1270 LLVM_DEBUG({
1271 dbgs() << ">>>>>> Outlined (Cloned) Function >>>>>>\n";
1272 Cloner.ClonedFunc->print(dbgs());
1273 dbgs() << "<<<<<< Outlined (Cloned) Function <<<<<<\n";
1274 });
1275
1276 if (tryPartialInline(Cloner))
1277 return {true, nullptr};
1278 }
1279 }
1280 }
1281
1282 // Fall-thru to regular partial inlining if we:
1283 // i) can't find any cold regions to outline, or
1284 // ii) can't inline the outlined function anywhere.
1285 std::unique_ptr<FunctionOutliningInfo> OI = computeOutliningInfo(F);
1286 if (!OI)
1287 return {false, nullptr};
1288
1289 FunctionCloner Cloner(&F, OI.get(), ORE, LookupAssumptionCache, GetTTI);
1290 Cloner.normalizeReturnBlock();
1291
1292 Function *OutlinedFunction = Cloner.doSingleRegionFunctionOutlining();
1293
1294 if (!OutlinedFunction)
1295 return {false, nullptr};
1296
1297 if (tryPartialInline(Cloner))
1298 return {true, OutlinedFunction};
1299
1300 return {false, nullptr};
1301}
1302
1303bool PartialInlinerImpl::tryPartialInline(FunctionCloner &Cloner) {
1304 if (Cloner.OutlinedFunctions.empty())
1305 return false;
1306
1307 auto OutliningCosts = computeOutliningCosts(Cloner);
1308
1309 InstructionCost SizeCost = std::get<0>(OutliningCosts);
1310 InstructionCost NonWeightedRcost = std::get<1>(OutliningCosts);
1311
1312 assert(SizeCost.isValid() && NonWeightedRcost.isValid() &&
1313 "Expected valid costs");
1314
1315 // Only calculate RelativeToEntryFreq when we are doing single region
1316 // outlining.
1317 BranchProbability RelativeToEntryFreq;
1318 if (Cloner.ClonedOI)
1319 RelativeToEntryFreq = getOutliningCallBBRelativeFreq(Cloner);
1320 else
1321 // RelativeToEntryFreq doesn't make sense when we have more than one
1322 // outlined call because each call will have a different relative frequency
1323 // to the entry block. We can consider using the average, but the
1324 // usefulness of that information is questionable. For now, assume we never
1325 // execute the calls to outlined functions.
1326 RelativeToEntryFreq = BranchProbability(0, 1);
1327
1328 BlockFrequency WeightedRcost =
1329 BlockFrequency(NonWeightedRcost.getValue()) * RelativeToEntryFreq;
1330
1331 // The call sequence(s) to the outlined function(s) are larger than the sum of
1332 // the original outlined region size(s), it does not increase the chances of
1333 // inlining the function with outlining (The inliner uses the size increase to
1334 // model the cost of inlining a callee).
1335 if (!SkipCostAnalysis && Cloner.OutlinedRegionCost < SizeCost) {
1336 OptimizationRemarkEmitter OrigFuncORE(Cloner.OrigFunc);
1337 DebugLoc DLoc;
1339 std::tie(DLoc, Block) = getOneDebugLoc(*Cloner.ClonedFunc);
1340 OrigFuncORE.emit([&]() {
1341 return OptimizationRemarkAnalysis(DEBUG_TYPE, "OutlineRegionTooSmall",
1342 DLoc, Block)
1343 << ore::NV("Function", Cloner.OrigFunc)
1344 << " not partially inlined into callers (Original Size = "
1345 << ore::NV("OutlinedRegionOriginalSize", Cloner.OutlinedRegionCost)
1346 << ", Size of call sequence to outlined function = "
1347 << ore::NV("NewSize", SizeCost) << ")";
1348 });
1349 return false;
1350 }
1351
1352 assert(Cloner.OrigFunc->users().empty() &&
1353 "F's users should all be replaced!");
1354
1355 std::vector<User *> Users(Cloner.ClonedFunc->user_begin(),
1356 Cloner.ClonedFunc->user_end());
1357
1358 DenseMap<User *, uint64_t> CallSiteToProfCountMap;
1359 auto CalleeEntryCount = Cloner.OrigFunc->getEntryCount();
1360 if (CalleeEntryCount)
1361 computeCallsiteToProfCountMap(Cloner.ClonedFunc, CallSiteToProfCountMap);
1362
1363 uint64_t CalleeEntryCountV = (CalleeEntryCount ? *CalleeEntryCount : 0);
1364
1365 bool AnyInline = false;
1366 for (User *User : Users) {
1367 CallBase *CB = getSupportedCallBase(User);
1368
1369 if (isLimitReached())
1370 continue;
1371
1372 OptimizationRemarkEmitter CallerORE(CB->getCaller());
1373 if (!shouldPartialInline(*CB, Cloner, WeightedRcost, CallerORE))
1374 continue;
1375
1376 // Construct remark before doing the inlining, as after successful inlining
1377 // the callsite is removed.
1378 OptimizationRemark OR(DEBUG_TYPE, "PartiallyInlined", CB);
1379 OR << ore::NV("Callee", Cloner.OrigFunc) << " partially inlined into "
1380 << ore::NV("Caller", CB->getCaller());
1381
1382 InlineFunctionInfo IFI(GetAssumptionCache, &PSI);
1383 // We can only forward varargs when we outlined a single region, else we
1384 // bail on vararg functions.
1385 if (!InlineFunction(*CB, IFI, /*MergeAttributes=*/false, nullptr,
1386 /*InsertLifetime=*/true, /*TrackInlineHistory=*/true,
1387 (Cloner.ClonedOI ? Cloner.OutlinedFunctions.back().first
1388 : nullptr))
1389 .isSuccess())
1390 continue;
1391
1392 CallerORE.emit(OR);
1393
1394 // Now update the entry count:
1395 if (CalleeEntryCountV) {
1396 if (auto It = CallSiteToProfCountMap.find(User);
1397 It != CallSiteToProfCountMap.end()) {
1398 uint64_t CallSiteCount = It->second;
1399 CalleeEntryCountV -= std::min(CalleeEntryCountV, CallSiteCount);
1400 }
1401 }
1402
1403 AnyInline = true;
1404 NumPartialInlining++;
1405 // Update the stats
1406 if (Cloner.ClonedOI)
1407 NumPartialInlined++;
1408 else
1409 NumColdOutlinePartialInlined++;
1410 }
1411
1412 if (AnyInline) {
1413 Cloner.IsFunctionInlined = true;
1414 if (CalleeEntryCount)
1415 Cloner.OrigFunc->setEntryCount(CalleeEntryCountV);
1416 OptimizationRemarkEmitter OrigFuncORE(Cloner.OrigFunc);
1417 OrigFuncORE.emit([&]() {
1418 return OptimizationRemark(DEBUG_TYPE, "PartiallyInlined", Cloner.OrigFunc)
1419 << "Partially inlined into at least one caller";
1420 });
1421 }
1422
1423 return AnyInline;
1424}
1425
1426bool PartialInlinerImpl::run(Module &M) {
1428 return false;
1429
1430 std::vector<Function *> Worklist;
1431 Worklist.reserve(M.size());
1432 for (Function &F : M)
1433 if (!F.use_empty() && !F.isDeclaration())
1434 Worklist.push_back(&F);
1435
1436 bool Changed = false;
1437 while (!Worklist.empty()) {
1438 Function *CurrFunc = Worklist.back();
1439 Worklist.pop_back();
1440
1441 if (CurrFunc->use_empty())
1442 continue;
1443
1444 std::pair<bool, Function *> Result = unswitchFunction(*CurrFunc);
1445 if (Result.second)
1446 Worklist.push_back(Result.second);
1447 Changed |= Result.first;
1448 }
1449
1450 return Changed;
1451}
1452
1455 auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
1456
1457 auto GetAssumptionCache = [&FAM](Function &F) -> AssumptionCache & {
1458 return FAM.getResult<AssumptionAnalysis>(F);
1459 };
1460
1461 auto LookupAssumptionCache = [&FAM](Function &F) -> AssumptionCache * {
1462 return FAM.getCachedResult<AssumptionAnalysis>(F);
1463 };
1464
1465 auto GetBFI = [&FAM](Function &F) -> BlockFrequencyInfo & {
1466 return FAM.getResult<BlockFrequencyAnalysis>(F);
1467 };
1468
1469 auto GetTTI = [&FAM](Function &F) -> TargetTransformInfo & {
1470 return FAM.getResult<TargetIRAnalysis>(F);
1471 };
1472
1473 auto GetTLI = [&FAM](Function &F) -> TargetLibraryInfo & {
1474 return FAM.getResult<TargetLibraryAnalysis>(F);
1475 };
1476
1478
1479 if (PartialInlinerImpl(GetAssumptionCache, LookupAssumptionCache, GetTTI,
1480 GetTLI, PSI, GetBFI)
1481 .run(M))
1482 return PreservedAnalyses::none();
1483 return PreservedAnalyses::all();
1484}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static MachineBasicBlock * OtherSucc(MachineBasicBlock *MBB, MachineBasicBlock *Succ)
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
This file contains the simple types necessary to represent the attributes associated with functions a...
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
cl::opt< unsigned > MinBlockCounterExecution
This file declares the LLVM IR specialization of the GenericCycle templates.
This file defines the DenseMap class.
This file defines the DenseSet and SmallDenseSet classes.
This file builds on the ADT/GraphTraits.h file to build generic depth first graph iterator.
#define DEBUG_TYPE
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
Module.h This file contains the declarations for the Module class.
iv Induction Variable Users
Definition IVUsers.cpp:48
static cl::opt< int > InstrCost("inline-instr-cost", cl::Hidden, cl::init(5), cl::desc("Cost of a single instruction when inlining"))
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Machine Check Debug Module
uint64_t IntrinsicInst * II
static cl::opt< unsigned > MaxNumInlineBlocks("max-num-inline-blocks", cl::init(5), cl::Hidden, cl::desc("Max number of blocks to be partially inlined"))
static cl::opt< int > OutlineRegionFreqPercent("outline-region-freq-percent", cl::init(75), cl::Hidden, cl::desc("Relative frequency of outline region to " "the entry block"))
static cl::opt< bool > MarkOutlinedColdCC("pi-mark-coldcc", cl::init(false), cl::Hidden, cl::desc("Mark outline function calls with ColdCC"))
static cl::opt< float > MinRegionSizeRatio("min-region-size-ratio", cl::init(0.1), cl::Hidden, cl::desc("Minimum ratio comparing relative sizes of each " "outline candidate and original function"))
static cl::opt< bool > DisableMultiRegionPartialInline("disable-mr-partial-inlining", cl::init(false), cl::Hidden, cl::desc("Disable multi-region partial inlining"))
cl::opt< unsigned > MinBlockCounterExecution("min-block-execution", cl::init(100), cl::Hidden, cl::desc("Minimum block executions to consider " "its BranchProbabilityInfo valid"))
static cl::opt< int > MaxNumPartialInlining("max-partial-inlining", cl::init(-1), cl::Hidden, cl::desc("Max number of partial inlining. The default is unlimited"))
static cl::opt< bool > DisablePartialInlining("disable-partial-inlining", cl::init(false), cl::Hidden, cl::desc("Disable partial inlining"))
static bool hasProfileData(const Function &F, const FunctionOutliningInfo &OI)
static cl::opt< float > ColdBranchRatio("cold-branch-ratio", cl::init(0.1), cl::Hidden, cl::desc("Minimum BranchProbability to consider a region cold."))
static cl::opt< bool > ForceLiveExit("pi-force-live-exit-outline", cl::init(false), cl::Hidden, cl::desc("Force outline regions with live exits"))
static cl::opt< unsigned > ExtraOutliningPenalty("partial-inlining-extra-penalty", cl::init(0), cl::Hidden, cl::desc("A debug option to add additional penalty to the computed one."))
static cl::opt< bool > SkipCostAnalysis("skip-partial-inlining-cost-analysis", cl::ReallyHidden, cl::desc("Skip Cost Analysis"))
FunctionAnalysisManager FAM
This file contains the declarations for profiling metadata utility functions.
This file contains some templates that are useful if you are working with the STL at all.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition Statistic.h:171
#define LLVM_DEBUG(...)
Definition Debug.h:119
This pass exposes codegen information to IR-level passes.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
A function analysis which provides an AssumptionCache.
A cache of @llvm.assume calls within a function.
LLVM Basic Block Representation.
Definition BasicBlock.h:62
iterator end()
Definition BasicBlock.h:459
iterator begin()
Instruction iterator methods.
Definition BasicBlock.h:446
const Function * getParent() const
Return the enclosing method, or null if none.
Definition BasicBlock.h:213
LLVM_ABI const BasicBlock * getSinglePredecessor() const
Return the predecessor of this block if it has a single predecessor block.
const Instruction & front() const
Definition BasicBlock.h:469
LLVM_ABI const BasicBlock * getSingleSuccessor() const
Return the successor of this block if it has a single successor.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this basic block belongs to.
InstListType::iterator iterator
Instruction iterators...
Definition BasicBlock.h:170
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
Definition BasicBlock.h:237
Analysis pass which computes BlockFrequencyInfo.
BlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate IR basic block frequen...
LLVM_ABI std::optional< uint64_t > getBlockProfileCount(const BasicBlock *BB, bool AllowSynthetic=false) const
Returns the estimated profile count of BB.
uint64_t getFrequency() const
Returns the frequency as a fixpoint number scaled by the entry frequency.
static LLVM_ABI BranchProbability getBranchProbability(uint64_t Numerator, uint64_t Denominator)
void setCallingConv(CallingConv::ID CC)
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
LLVM_ABI Function * getCaller()
Helper to get the caller (the parent function).
Conditional Branch instruction.
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:223
iterator end()
Definition DenseMap.h:141
void recalculate(ParentType &Func)
recalculate - compute a dominator tree for the given function
void setCallingConv(CallingConv::ID CC)
Definition Function.h:276
void compute(FunctionT &F)
Compute the cycle info for a function.
int getCost() const
Get the inline cost estimate.
Definition InlineCost.h:146
bool isAlways() const
Definition InlineCost.h:140
int getCostDelta() const
Get the cost delta from the threshold for inlining.
Definition InlineCost.h:176
bool isNever() const
Definition InlineCost.h:141
bool isSuccess() const
Definition InlineCost.h:190
auto map(const Function &F) const -> InstructionCost
CostType getValue() const
This function is intended to be used as sparingly as possible, since the class provides the full rang...
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI void insertBefore(InstListType::iterator InsertPos)
Insert an unlinked instruction into a basic block immediately before the specified position.
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
The optimization diagnostic interface.
LLVM_ABI void emit(DiagnosticInfoOptimizationBase &OptDiag)
Output the remark via the diagnostic handler and to the optimization record file.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
LLVM_ABI Value * removeIncomingValue(unsigned Idx, bool DeletePHIIfEmpty=true)
Remove an incoming value.
Value * getIncomingValueForBlock(const BasicBlock *BB) const
unsigned getNumIncomingValues() const
Return the number of incoming edges.
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &)
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition Analysis.h:115
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
An analysis pass based on the new PM to deliver ProfileSummaryInfo.
Analysis providing profile information.
size_type size() const
Determine the number of elements in the SetVector.
Definition SetVector.h:103
void insert_range(Range &&R)
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Analysis pass providing the TargetTransformInfo.
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
This pass provides access to the codegen interfaces that are needed for IR-level transformations.
LLVM_ABI InstructionCost getIntrinsicInstrCost(const IntrinsicCostAttributes &ICA, TTI::TargetCostKind CostKind) const
@ TCK_SizeAndLatency
The weighted sum of size and latency.
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:255
user_iterator user_begin()
Definition Value.h:402
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition Value.cpp:553
bool use_empty() const
Definition Value.h:346
user_iterator user_end()
Definition Value.h:410
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
Definition ilist_node.h:34
Changed
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ BR
Control flow instructions. These all have token chains.
@ BasicBlock
Various leaf nodes.
Definition ISDOpcodes.h:81
LLVM_ABI int getInstrCost()
@ CE
Windows NT (Windows on ARM)
Definition MCAsmInfo.h:51
initializer< Ty > init(const Ty &Val)
DXILDebugInfoMap run(Module &M)
@ User
could "use" a pointer
DiagnosticInfoOptimizationBase::Argument NV
NodeAddr< PhiNode * > Phi
Definition RDFGraph.h:390
NodeAddr< FuncNode * > Func
Definition RDFGraph.h:393
friend class Instruction
Iterator for Instructions in a `BasicBlock.
Definition BasicBlock.h:73
This is an optimization pass for GlobalISel generic memory operations.
InstructionCost Cost
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
auto successors(const MachineBasicBlock *BB)
constexpr from_range_t from_range
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
LLVM_ABI InlineResult InlineFunction(CallBase &CB, InlineFunctionInfo &IFI, bool MergeAttributes=false, AAResults *CalleeAAR=nullptr, bool InsertLifetime=true, bool TrackInlineHistory=false, Function *ForwardVarArgsTo=nullptr, OptimizationRemarkEmitter *ORE=nullptr)
This function inlines the called function into the basic block of the caller.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
LLVM_ABI InlineResult isInlineViable(Function &Callee)
Check if it is mechanically possible to inline the function Callee, based on the contents of the func...
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
auto succ_size(const MachineBasicBlock *BB)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
RNSuccIterator< NodeRef, BlockT, RegionT > succ_begin(NodeRef Node)
LLVM_ABI InlineCost getInlineCost(CallBase &Call, const InlineParams &Params, TargetTransformInfo &CalleeTTI, function_ref< AssumptionCache &(Function &)> GetAssumptionCache, function_ref< const TargetLibraryInfo &(Function &)> GetTLI, function_ref< BlockFrequencyInfo &(Function &)> GetBFI=nullptr, ProfileSummaryInfo *PSI=nullptr, OptimizationRemarkEmitter *ORE=nullptr, function_ref< EphemeralValuesCache &(Function &)> GetEphValuesCache=nullptr)
Get an InlineCost object representing the cost of inlining this callsite.
TargetTransformInfo TTI
RNSuccIterator< NodeRef, BlockT, RegionT > succ_end(NodeRef Node)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
Definition InstrProf.h:145
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI InlineParams getInlineParams()
Generate the parameters to tune the inline cost analysis based only on the commandline options.
LLVM_ABI int getCallsiteCost(const TargetTransformInfo &TTI, const CallBase &Call, const DataLayout &DL)
Return the cost associated with a callsite, including parameter passing and the call/return instructi...
ValueMap< const Value *, WeakTrackingVH > ValueToValueMapTy
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
auto predecessors(const MachineBasicBlock *BB)
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1947
iterator_range< df_iterator< T > > depth_first(const T &G)
bool all_equal(std::initializer_list< T > Values)
Returns true if all Values in the initializer lists are equal or the list.
Definition STLExtras.h:2166
LLVM_ABI bool hasBranchWeightMD(const Instruction &I)
Checks if an instructions has Branch Weight Metadata.
LLVM_ABI Function * CloneFunction(Function *F, ValueToValueMapTy &VMap, ClonedCodeInfo *CodeInfo=nullptr)
Return a copy of the specified function and add it to that function's module.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39