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 &CallerTTI = GetTTI(*Caller);
727 bool RemarksEnabled =
728 Callee->getContext().getDiagHandlerPtr()->isMissedOptRemarkEnabled(
729 DEBUG_TYPE);
730 InlineCost IC = getInlineCost(CB, getInlineParams(CB.getContext()), CallerTTI,
731 GetAssumptionCache, GetTLI, GetBFI, &PSI,
732 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(CallerTTI, 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();
804 int InstrCost = InlineConstants::getInstrCost(BB->getContext());
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.OrigFunc->getContext()) *
884 Cloner.OutlinedFunctions.size();
885
886 InstructionCost OutliningRuntimeOverhead =
887 OutliningFuncCallCost +
888 (OutlinedFunctionCost - Cloner.OutlinedRegionCost) +
890
891 return std::make_tuple(OutliningFuncCallCost, OutliningRuntimeOverhead);
892}
893
894// Create the callsite to profile count map which is
895// used to update the original function's entry count,
896// after the function is partially inlined into the callsite.
897void PartialInlinerImpl::computeCallsiteToProfCountMap(
898 Function *DuplicateFunction,
899 DenseMap<User *, uint64_t> &CallSiteToProfCountMap) const {
900 std::vector<User *> Users(DuplicateFunction->user_begin(),
901 DuplicateFunction->user_end());
902 Function *CurrentCaller = nullptr;
903 std::unique_ptr<BlockFrequencyInfo> TempBFI;
904 BlockFrequencyInfo *CurrentCallerBFI = nullptr;
905
906 auto ComputeCurrBFI = [&,this](Function *Caller) {
907 // For the old pass manager:
908 if (!GetBFI) {
909 CycleInfo CI;
910 CI.compute(*Caller);
911 BranchProbabilityInfo BPI(*Caller, CI);
912 TempBFI.reset(new BlockFrequencyInfo(*Caller, BPI, CI));
913 CurrentCallerBFI = TempBFI.get();
914 } else {
915 // New pass manager:
916 CurrentCallerBFI = &(GetBFI(*Caller));
917 }
918 };
919
920 for (User *User : Users) {
921 CallBase *CB = getSupportedCallBase(User);
922 Function *Caller = CB->getCaller();
923 if (CurrentCaller != Caller) {
924 CurrentCaller = Caller;
925 ComputeCurrBFI(Caller);
926 } else {
927 assert(CurrentCallerBFI && "CallerBFI is not set");
928 }
929 BasicBlock *CallBB = CB->getParent();
930 auto Count = CurrentCallerBFI->getBlockProfileCount(CallBB);
931 if (Count)
932 CallSiteToProfCountMap[User] = *Count;
933 else
934 CallSiteToProfCountMap[User] = 0;
935 }
936}
937
938PartialInlinerImpl::FunctionCloner::FunctionCloner(
939 Function *F, FunctionOutliningInfo *OI, OptimizationRemarkEmitter &ORE,
940 function_ref<AssumptionCache *(Function &)> LookupAC,
941 function_ref<TargetTransformInfo &(Function &)> GetTTI)
942 : OrigFunc(F), ORE(ORE), LookupAC(LookupAC), GetTTI(GetTTI) {
943 ClonedOI = std::make_unique<FunctionOutliningInfo>();
944
945 // Clone the function, so that we can hack away on it.
947 ClonedFunc = CloneFunction(F, VMap);
948
949 ClonedOI->ReturnBlock = cast<BasicBlock>(VMap[OI->ReturnBlock]);
950 ClonedOI->NonReturnBlock = cast<BasicBlock>(VMap[OI->NonReturnBlock]);
951 for (BasicBlock *BB : OI->Entries)
952 ClonedOI->Entries.push_back(cast<BasicBlock>(VMap[BB]));
953
954 for (BasicBlock *E : OI->ReturnBlockPreds) {
955 BasicBlock *NewE = cast<BasicBlock>(VMap[E]);
956 ClonedOI->ReturnBlockPreds.push_back(NewE);
957 }
958 // Go ahead and update all uses to the duplicate, so that we can just
959 // use the inliner functionality when we're done hacking.
960 F->replaceAllUsesWith(ClonedFunc);
961}
962
963PartialInlinerImpl::FunctionCloner::FunctionCloner(
964 Function *F, FunctionOutliningMultiRegionInfo *OI,
968 : OrigFunc(F), ORE(ORE), LookupAC(LookupAC), GetTTI(GetTTI) {
969 ClonedOMRI = std::make_unique<FunctionOutliningMultiRegionInfo>();
970
971 // Clone the function, so that we can hack away on it.
973 ClonedFunc = CloneFunction(F, VMap);
974
975 // Go through all Outline Candidate Regions and update all BasicBlock
976 // information.
977 for (const FunctionOutliningMultiRegionInfo::OutlineRegionInfo &RegionInfo :
978 OI->ORI) {
980 for (BasicBlock *BB : RegionInfo.Region)
981 Region.push_back(cast<BasicBlock>(VMap[BB]));
982
983 BasicBlock *NewEntryBlock = cast<BasicBlock>(VMap[RegionInfo.EntryBlock]);
984 BasicBlock *NewExitBlock = cast<BasicBlock>(VMap[RegionInfo.ExitBlock]);
985 BasicBlock *NewReturnBlock = nullptr;
986 if (RegionInfo.ReturnBlock)
987 NewReturnBlock = cast<BasicBlock>(VMap[RegionInfo.ReturnBlock]);
988 FunctionOutliningMultiRegionInfo::OutlineRegionInfo MappedRegionInfo(
989 Region, NewEntryBlock, NewExitBlock, NewReturnBlock);
990 ClonedOMRI->ORI.push_back(MappedRegionInfo);
991 }
992 // Go ahead and update all uses to the duplicate, so that we can just
993 // use the inliner functionality when we're done hacking.
994 F->replaceAllUsesWith(ClonedFunc);
995}
996
997void PartialInlinerImpl::FunctionCloner::normalizeReturnBlock() const {
998 auto GetFirstPHI = [](BasicBlock *BB) {
999 BasicBlock::iterator I = BB->begin();
1000 PHINode *FirstPhi = nullptr;
1001 while (I != BB->end()) {
1002 PHINode *Phi = dyn_cast<PHINode>(I);
1003 if (!Phi)
1004 break;
1005 if (!FirstPhi) {
1006 FirstPhi = Phi;
1007 break;
1008 }
1009 }
1010 return FirstPhi;
1011 };
1012
1013 // Shouldn't need to normalize PHIs if we're not outlining non-early return
1014 // blocks.
1015 if (!ClonedOI)
1016 return;
1017
1018 // Special hackery is needed with PHI nodes that have inputs from more than
1019 // one extracted block. For simplicity, just split the PHIs into a two-level
1020 // sequence of PHIs, some of which will go in the extracted region, and some
1021 // of which will go outside.
1022 BasicBlock *PreReturn = ClonedOI->ReturnBlock;
1023 // only split block when necessary:
1024 PHINode *FirstPhi = GetFirstPHI(PreReturn);
1025 unsigned NumPredsFromEntries = ClonedOI->ReturnBlockPreds.size();
1026
1027 if (!FirstPhi || FirstPhi->getNumIncomingValues() <= NumPredsFromEntries + 1)
1028 return;
1029
1030 auto IsTrivialPhi = [](PHINode *PN) -> Value * {
1031 if (llvm::all_equal(PN->incoming_values()))
1032 return PN->getIncomingValue(0);
1033 return nullptr;
1034 };
1035
1036 ClonedOI->ReturnBlock = ClonedOI->ReturnBlock->splitBasicBlock(
1037 ClonedOI->ReturnBlock->getFirstNonPHIIt());
1038 BasicBlock::iterator I = PreReturn->begin();
1039 BasicBlock::iterator Ins = ClonedOI->ReturnBlock->begin();
1040 SmallVector<Instruction *, 4> DeadPhis;
1041 while (I != PreReturn->end()) {
1042 PHINode *OldPhi = dyn_cast<PHINode>(I);
1043 if (!OldPhi)
1044 break;
1045
1046 PHINode *RetPhi =
1047 PHINode::Create(OldPhi->getType(), NumPredsFromEntries + 1, "");
1048 RetPhi->insertBefore(Ins);
1049 OldPhi->replaceAllUsesWith(RetPhi);
1050 Ins = ClonedOI->ReturnBlock->getFirstNonPHIIt();
1051
1052 RetPhi->addIncoming(&*I, PreReturn);
1053 for (BasicBlock *E : ClonedOI->ReturnBlockPreds) {
1054 RetPhi->addIncoming(OldPhi->getIncomingValueForBlock(E), E);
1055 OldPhi->removeIncomingValue(E);
1056 }
1057
1058 // After incoming values splitting, the old phi may become trivial.
1059 // Keeping the trivial phi can introduce definition inside the outline
1060 // region which is live-out, causing necessary overhead (load, store
1061 // arg passing etc).
1062 if (auto *OldPhiVal = IsTrivialPhi(OldPhi)) {
1063 OldPhi->replaceAllUsesWith(OldPhiVal);
1064 DeadPhis.push_back(OldPhi);
1065 }
1066 ++I;
1067 }
1068 for (auto *DP : DeadPhis)
1069 DP->eraseFromParent();
1070
1071 for (auto *E : ClonedOI->ReturnBlockPreds)
1072 E->getTerminator()->replaceUsesOfWith(PreReturn, ClonedOI->ReturnBlock);
1073}
1074
1075bool PartialInlinerImpl::FunctionCloner::doMultiRegionFunctionOutlining() {
1076
1077 auto ComputeRegionCost =
1078 [&](SmallVectorImpl<BasicBlock *> &Region) -> InstructionCost {
1080 for (BasicBlock* BB : Region)
1081 Cost += computeBBInlineCost(BB, &GetTTI(*BB->getParent()));
1082 return Cost;
1083 };
1084
1085 assert(ClonedOMRI && "Expecting OutlineInfo for multi region outline");
1086
1087 if (ClonedOMRI->ORI.empty())
1088 return false;
1089
1090 // The CodeExtractor needs a dominator tree.
1091 DominatorTree DT;
1092 DT.recalculate(*ClonedFunc);
1093
1094 // Manually calculate a BlockFrequencyInfo and BranchProbabilityInfo.
1095 CycleInfo CI;
1096 CI.compute(*ClonedFunc);
1097 BranchProbabilityInfo BPI(*ClonedFunc, CI);
1098 ClonedFuncBFI.reset(new BlockFrequencyInfo(*ClonedFunc, BPI, CI));
1099
1100 // Cache and recycle the CodeExtractor analysis to avoid O(n^2) compile-time.
1101 CodeExtractorAnalysisCache CEAC(*ClonedFunc);
1102
1103 SetVector<Value *> Inputs, Outputs, Sinks;
1104 for (FunctionOutliningMultiRegionInfo::OutlineRegionInfo RegionInfo :
1105 ClonedOMRI->ORI) {
1106 InstructionCost CurrentOutlinedRegionCost =
1107 ComputeRegionCost(RegionInfo.Region);
1108
1109 CodeExtractor CE(RegionInfo.Region, &DT, /*AggregateArgs*/ false,
1110 ClonedFuncBFI.get(), &BPI,
1111 LookupAC(*RegionInfo.EntryBlock->getParent()),
1112 /* AllowVarargs */ false, /* AllowAlloca */ false,
1113 /* AllocaBlock */ nullptr, /* DeallocationBlocks */ {},
1114 /* Suffix */ "", /* ArgsInZeroAddressSpace */ false,
1115 /* VoidReturnWithSingleOutput */ false);
1116
1117 CE.findInputsOutputs(Inputs, Outputs, Sinks);
1118
1119 LLVM_DEBUG({
1120 dbgs() << "inputs: " << Inputs.size() << "\n";
1121 dbgs() << "outputs: " << Outputs.size() << "\n";
1122 for (Value *value : Inputs)
1123 dbgs() << "value used in func: " << *value << "\n";
1124 for (Value *output : Outputs)
1125 dbgs() << "instr used in func: " << *output << "\n";
1126 });
1127
1128 // Do not extract regions that have live exit variables.
1129 if (Outputs.size() > 0 && !ForceLiveExit)
1130 continue;
1131
1132 if (Function *OutlinedFunc = CE.extractCodeRegion(CEAC)) {
1133 CallBase *OCS = PartialInlinerImpl::getOneCallSiteTo(*OutlinedFunc);
1134 BasicBlock *OutliningCallBB = OCS->getParent();
1135 assert(OutliningCallBB->getParent() == ClonedFunc);
1136 OutlinedFunctions.push_back(std::make_pair(OutlinedFunc,OutliningCallBB));
1137 NumColdRegionsOutlined++;
1138 OutlinedRegionCost += CurrentOutlinedRegionCost;
1139
1140 if (MarkOutlinedColdCC) {
1141 OutlinedFunc->setCallingConv(CallingConv::Cold);
1142 OCS->setCallingConv(CallingConv::Cold);
1143 }
1144 } else
1145 ORE.emit([&]() {
1146 return OptimizationRemarkMissed(DEBUG_TYPE, "ExtractFailed",
1147 &RegionInfo.Region.front()->front())
1148 << "Failed to extract region at block "
1149 << ore::NV("Block", RegionInfo.Region.front());
1150 });
1151 }
1152
1153 return !OutlinedFunctions.empty();
1154}
1155
1156Function *
1157PartialInlinerImpl::FunctionCloner::doSingleRegionFunctionOutlining() {
1158 // Returns true if the block is to be partial inlined into the caller
1159 // (i.e. not to be extracted to the out of line function)
1160 auto ToBeInlined = [&, this](BasicBlock *BB) {
1161 return BB == ClonedOI->ReturnBlock ||
1162 llvm::is_contained(ClonedOI->Entries, BB);
1163 };
1164
1165 assert(ClonedOI && "Expecting OutlineInfo for single region outline");
1166 // The CodeExtractor needs a dominator tree.
1167 DominatorTree DT;
1168 DT.recalculate(*ClonedFunc);
1169
1170 // Manually calculate a BlockFrequencyInfo and BranchProbabilityInfo.
1171 CycleInfo CI;
1172 CI.compute(*ClonedFunc);
1173 BranchProbabilityInfo BPI(*ClonedFunc, CI);
1174 ClonedFuncBFI.reset(new BlockFrequencyInfo(*ClonedFunc, BPI, CI));
1175
1176 // Gather up the blocks that we're going to extract.
1177 std::vector<BasicBlock *> ToExtract;
1178 auto *ClonedFuncTTI = &GetTTI(*ClonedFunc);
1179 ToExtract.push_back(ClonedOI->NonReturnBlock);
1180 OutlinedRegionCost += PartialInlinerImpl::computeBBInlineCost(
1181 ClonedOI->NonReturnBlock, ClonedFuncTTI);
1182 for (BasicBlock *BB : depth_first(&ClonedFunc->getEntryBlock()))
1183 if (!ToBeInlined(BB) && BB != ClonedOI->NonReturnBlock) {
1184 ToExtract.push_back(BB);
1185 // FIXME: the code extractor may hoist/sink more code
1186 // into the outlined function which may make the outlining
1187 // overhead (the difference of the outlined function cost
1188 // and OutliningRegionCost) look larger.
1189 OutlinedRegionCost += computeBBInlineCost(BB, ClonedFuncTTI);
1190 }
1191
1192 // Extract the body of the if.
1193 CodeExtractorAnalysisCache CEAC(*ClonedFunc);
1194 Function *OutlinedFunc =
1195 CodeExtractor(ToExtract, &DT, /*AggregateArgs*/ false,
1196 ClonedFuncBFI.get(), &BPI, LookupAC(*ClonedFunc),
1197 /* AllowVarargs */ true, /* AllowAlloca */ false,
1198 /* AllocaBlock */ nullptr, /* DeallocationBlocks */ {},
1199 /* Suffix */ "", /* ArgsInZeroAddressSpace */ false,
1200 /* VoidReturnWithSingleOutput */ false)
1201 .extractCodeRegion(CEAC);
1202
1203 if (OutlinedFunc) {
1204 BasicBlock *OutliningCallBB =
1205 PartialInlinerImpl::getOneCallSiteTo(*OutlinedFunc)->getParent();
1206 assert(OutliningCallBB->getParent() == ClonedFunc);
1207 OutlinedFunctions.push_back(std::make_pair(OutlinedFunc, OutliningCallBB));
1208 } else
1209 ORE.emit([&]() {
1210 return OptimizationRemarkMissed(DEBUG_TYPE, "ExtractFailed",
1211 &ToExtract.front()->front())
1212 << "Failed to extract region at block "
1213 << ore::NV("Block", ToExtract.front());
1214 });
1215
1216 return OutlinedFunc;
1217}
1218
1219PartialInlinerImpl::FunctionCloner::~FunctionCloner() {
1220 // Ditch the duplicate, since we're done with it, and rewrite all remaining
1221 // users (function pointers, etc.) back to the original function.
1222 ClonedFunc->replaceAllUsesWith(OrigFunc);
1223 ClonedFunc->eraseFromParent();
1224 if (!IsFunctionInlined) {
1225 // Remove each function that was speculatively created if there is no
1226 // reference.
1227 for (auto FuncBBPair : OutlinedFunctions) {
1228 Function *Func = FuncBBPair.first;
1229 Func->eraseFromParent();
1230 }
1231 }
1232}
1233
1234std::pair<bool, Function *> PartialInlinerImpl::unswitchFunction(Function &F) {
1235 if (F.hasAddressTaken())
1236 return {false, nullptr};
1237
1238 // Let inliner handle it
1239 if (F.hasFnAttribute(Attribute::AlwaysInline))
1240 return {false, nullptr};
1241
1242 if (F.hasFnAttribute(Attribute::NoInline))
1243 return {false, nullptr};
1244
1245 if (PSI.isFunctionEntryCold(&F))
1246 return {false, nullptr};
1247
1248 if (F.users().empty())
1249 return {false, nullptr};
1250
1251 OptimizationRemarkEmitter ORE(&F);
1252
1253 // Only try to outline cold regions if we have a profile summary, which
1254 // implies we have profiling information.
1255 if (PSI.hasProfileSummary() && F.hasProfileData() &&
1257 std::unique_ptr<FunctionOutliningMultiRegionInfo> OMRI =
1258 computeOutliningColdRegionsInfo(F, ORE);
1259 if (OMRI) {
1260 FunctionCloner Cloner(&F, OMRI.get(), ORE, LookupAssumptionCache, GetTTI);
1261
1262 LLVM_DEBUG({
1263 dbgs() << "HotCountThreshold = " << PSI.getHotCountThreshold() << "\n";
1264 dbgs() << "ColdCountThreshold = " << PSI.getColdCountThreshold()
1265 << "\n";
1266 });
1267
1268 bool DidOutline = Cloner.doMultiRegionFunctionOutlining();
1269
1270 if (DidOutline) {
1271 LLVM_DEBUG({
1272 dbgs() << ">>>>>> Outlined (Cloned) Function >>>>>>\n";
1273 Cloner.ClonedFunc->print(dbgs());
1274 dbgs() << "<<<<<< Outlined (Cloned) Function <<<<<<\n";
1275 });
1276
1277 if (tryPartialInline(Cloner))
1278 return {true, nullptr};
1279 }
1280 }
1281 }
1282
1283 // Fall-thru to regular partial inlining if we:
1284 // i) can't find any cold regions to outline, or
1285 // ii) can't inline the outlined function anywhere.
1286 std::unique_ptr<FunctionOutliningInfo> OI = computeOutliningInfo(F);
1287 if (!OI)
1288 return {false, nullptr};
1289
1290 FunctionCloner Cloner(&F, OI.get(), ORE, LookupAssumptionCache, GetTTI);
1291 Cloner.normalizeReturnBlock();
1292
1293 Function *OutlinedFunction = Cloner.doSingleRegionFunctionOutlining();
1294
1295 if (!OutlinedFunction)
1296 return {false, nullptr};
1297
1298 if (tryPartialInline(Cloner))
1299 return {true, OutlinedFunction};
1300
1301 return {false, nullptr};
1302}
1303
1304bool PartialInlinerImpl::tryPartialInline(FunctionCloner &Cloner) {
1305 if (Cloner.OutlinedFunctions.empty())
1306 return false;
1307
1308 auto OutliningCosts = computeOutliningCosts(Cloner);
1309
1310 InstructionCost SizeCost = std::get<0>(OutliningCosts);
1311 InstructionCost NonWeightedRcost = std::get<1>(OutliningCosts);
1312
1313 assert(SizeCost.isValid() && NonWeightedRcost.isValid() &&
1314 "Expected valid costs");
1315
1316 // Only calculate RelativeToEntryFreq when we are doing single region
1317 // outlining.
1318 BranchProbability RelativeToEntryFreq;
1319 if (Cloner.ClonedOI)
1320 RelativeToEntryFreq = getOutliningCallBBRelativeFreq(Cloner);
1321 else
1322 // RelativeToEntryFreq doesn't make sense when we have more than one
1323 // outlined call because each call will have a different relative frequency
1324 // to the entry block. We can consider using the average, but the
1325 // usefulness of that information is questionable. For now, assume we never
1326 // execute the calls to outlined functions.
1327 RelativeToEntryFreq = BranchProbability(0, 1);
1328
1329 BlockFrequency WeightedRcost =
1330 BlockFrequency(NonWeightedRcost.getValue()) * RelativeToEntryFreq;
1331
1332 // The call sequence(s) to the outlined function(s) are larger than the sum of
1333 // the original outlined region size(s), it does not increase the chances of
1334 // inlining the function with outlining (The inliner uses the size increase to
1335 // model the cost of inlining a callee).
1336 if (!SkipCostAnalysis && Cloner.OutlinedRegionCost < SizeCost) {
1337 OptimizationRemarkEmitter OrigFuncORE(Cloner.OrigFunc);
1338 DebugLoc DLoc;
1340 std::tie(DLoc, Block) = getOneDebugLoc(*Cloner.ClonedFunc);
1341 OrigFuncORE.emit([&]() {
1342 return OptimizationRemarkAnalysis(DEBUG_TYPE, "OutlineRegionTooSmall",
1343 DLoc, Block)
1344 << ore::NV("Function", Cloner.OrigFunc)
1345 << " not partially inlined into callers (Original Size = "
1346 << ore::NV("OutlinedRegionOriginalSize", Cloner.OutlinedRegionCost)
1347 << ", Size of call sequence to outlined function = "
1348 << ore::NV("NewSize", SizeCost) << ")";
1349 });
1350 return false;
1351 }
1352
1353 assert(Cloner.OrigFunc->users().empty() &&
1354 "F's users should all be replaced!");
1355
1356 std::vector<User *> Users(Cloner.ClonedFunc->user_begin(),
1357 Cloner.ClonedFunc->user_end());
1358
1359 DenseMap<User *, uint64_t> CallSiteToProfCountMap;
1360 auto CalleeEntryCount = Cloner.OrigFunc->getEntryCount();
1361 if (CalleeEntryCount)
1362 computeCallsiteToProfCountMap(Cloner.ClonedFunc, CallSiteToProfCountMap);
1363
1364 uint64_t CalleeEntryCountV = (CalleeEntryCount ? *CalleeEntryCount : 0);
1365
1366 bool AnyInline = false;
1367 for (User *User : Users) {
1368 CallBase *CB = getSupportedCallBase(User);
1369
1370 if (isLimitReached())
1371 continue;
1372
1373 OptimizationRemarkEmitter CallerORE(CB->getCaller());
1374 if (!shouldPartialInline(*CB, Cloner, WeightedRcost, CallerORE))
1375 continue;
1376
1377 // Construct remark before doing the inlining, as after successful inlining
1378 // the callsite is removed.
1379 OptimizationRemark OR(DEBUG_TYPE, "PartiallyInlined", CB);
1380 OR << ore::NV("Callee", Cloner.OrigFunc) << " partially inlined into "
1381 << ore::NV("Caller", CB->getCaller());
1382
1383 InlineFunctionInfo IFI(GetAssumptionCache, &PSI);
1384 // We can only forward varargs when we outlined a single region, else we
1385 // bail on vararg functions.
1386 if (!InlineFunction(*CB, IFI, /*MergeAttributes=*/false, nullptr,
1387 /*InsertLifetime=*/true, /*TrackInlineHistory=*/true,
1388 (Cloner.ClonedOI ? Cloner.OutlinedFunctions.back().first
1389 : nullptr))
1390 .isSuccess())
1391 continue;
1392
1393 CallerORE.emit(OR);
1394
1395 // Now update the entry count:
1396 if (CalleeEntryCountV) {
1397 if (auto It = CallSiteToProfCountMap.find(User);
1398 It != CallSiteToProfCountMap.end()) {
1399 uint64_t CallSiteCount = It->second;
1400 CalleeEntryCountV -= std::min(CalleeEntryCountV, CallSiteCount);
1401 }
1402 }
1403
1404 AnyInline = true;
1405 NumPartialInlining++;
1406 // Update the stats
1407 if (Cloner.ClonedOI)
1408 NumPartialInlined++;
1409 else
1410 NumColdOutlinePartialInlined++;
1411 }
1412
1413 if (AnyInline) {
1414 Cloner.IsFunctionInlined = true;
1415 if (CalleeEntryCount)
1416 Cloner.OrigFunc->setEntryCount(CalleeEntryCountV);
1417 OptimizationRemarkEmitter OrigFuncORE(Cloner.OrigFunc);
1418 OrigFuncORE.emit([&]() {
1419 return OptimizationRemark(DEBUG_TYPE, "PartiallyInlined", Cloner.OrigFunc)
1420 << "Partially inlined into at least one caller";
1421 });
1422 }
1423
1424 return AnyInline;
1425}
1426
1427bool PartialInlinerImpl::run(Module &M) {
1429 return false;
1430
1431 std::vector<Function *> Worklist;
1432 Worklist.reserve(M.size());
1433 for (Function &F : M)
1434 if (!F.use_empty() && !F.isDeclaration())
1435 Worklist.push_back(&F);
1436
1437 bool Changed = false;
1438 while (!Worklist.empty()) {
1439 Function *CurrFunc = Worklist.back();
1440 Worklist.pop_back();
1441
1442 if (CurrFunc->use_empty())
1443 continue;
1444
1445 std::pair<bool, Function *> Result = unswitchFunction(*CurrFunc);
1446 if (Result.second)
1447 Worklist.push_back(Result.second);
1448 Changed |= Result.first;
1449 }
1450
1451 return Changed;
1452}
1453
1456 auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
1457
1458 auto GetAssumptionCache = [&FAM](Function &F) -> AssumptionCache & {
1459 return FAM.getResult<AssumptionAnalysis>(F);
1460 };
1461
1462 auto LookupAssumptionCache = [&FAM](Function &F) -> AssumptionCache * {
1463 return FAM.getCachedResult<AssumptionAnalysis>(F);
1464 };
1465
1466 auto GetBFI = [&FAM](Function &F) -> BlockFrequencyInfo & {
1467 return FAM.getResult<BlockFrequencyAnalysis>(F);
1468 };
1469
1470 auto GetTTI = [&FAM](Function &F) -> TargetTransformInfo & {
1471 return FAM.getResult<TargetIRAnalysis>(F);
1472 };
1473
1474 auto GetTLI = [&FAM](Function &F) -> TargetLibraryInfo & {
1475 return FAM.getResult<TargetLibraryAnalysis>(F);
1476 };
1477
1479
1480 if (PartialInlinerImpl(GetAssumptionCache, LookupAssumptionCache, GetTTI,
1481 GetTLI, PSI, GetBFI)
1482 .run(M))
1483 return PreservedAnalyses::none();
1484 return PreservedAnalyses::all();
1485}
SDValue Pred
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
uint64_t uint64_t
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
#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:453
iterator begin()
Instruction iterator methods.
Definition BasicBlock.h:440
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:463
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
LLVM_ABI LLVMContext & getContext() const
Get the context in which this basic block lives.
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) 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:766
iterator end()
Definition DenseMap.h:686
void recalculate(ParentType &Func)
recalculate - compute a dominator tree for the given function
void setCallingConv(CallingConv::ID CC)
Definition Function.h:277
void compute(FunctionT &F)
Compute the cycle info for a function.
int getCost() const
Get the inline cost estimate.
Definition InlineCost.h:149
bool isAlways() const
Definition InlineCost.h:143
int getCostDelta() const
Get the cost delta from the threshold for inlining.
Definition InlineCost.h:179
bool isNever() const
Definition InlineCost.h:144
bool isSuccess() const
Definition InlineCost.h:193
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:68
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:257
user_iterator user_begin()
Definition Value.h:404
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition Value.cpp:548
LLVMContext & getContext() const
All values hold a context through their type.
Definition Value.h:260
bool use_empty() const
Definition Value.h:348
user_iterator user_end()
Definition Value.h:412
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
Definition ilist_node.h:34
#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:83
LLVM_ABI int getInstrCost(const LLVMContext &C)
Return -inline-instr-cost.
@ CE
Windows NT (Windows on ARM)
Definition MCAsmInfo.h:51
initializer< Ty > init(const Ty &Val)
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the 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
LLVM_ABI InlineCost getInlineCost(CallBase &Call, const InlineParams &Params, TargetTransformInfo &CallerTTI, 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.
LLVM_ABI InlineParams getInlineParams(const LLVMContext &C)
Generate the parameters to tune the inline cost analysis based only on the commandline options.
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)
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 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:1963
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:2182
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