LLVM: lib/Transforms/IPO/PartialInlining.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
54#include
55#include
56#include
57#include
58#include
59#include
60
61using namespace llvm;
62
63#define DEBUG_TYPE "partial-inlining"
64
66 "Number of callsites functions partially inlined into.");
67STATISTIC(NumColdOutlinePartialInlined, "Number of times functions with "
68 "cold outlined regions were partially "
69 "inlined into its caller(s).");
71 "Number of cold single entry/exit regions found.");
73 "Number of cold single entry/exit regions outlined.");
74
75
79
80
83 cl::desc("Disable multi-region partial inlining"));
84
85
86
89 cl::desc("Force outline regions with live exits"));
90
91
92
95 cl::desc("Mark outline function calls with ColdCC"));
96
97
99
101 cl::desc("Skip Cost Analysis"));
102
103
104
105
108 cl::desc("Minimum ratio comparing relative sizes of each "
109 "outline candidate and original function"));
110
111
114 cl::desc("Minimum block executions to consider "
115 "its BranchProbabilityInfo valid"));
116
117
120 cl::desc("Minimum BranchProbability to consider a region cold."));
121
124 cl::desc("Max number of blocks to be partially inlined"));
125
126
127
130 cl::desc("Max number of partial inlining. The default is unlimited"));
131
132
133
134
138 cl::desc("Relative frequency of outline region to "
139 "the entry block"));
140
143 cl::desc("A debug option to add additional penalty to the computed one."));
144
145namespace {
146
147struct FunctionOutliningInfo {
148 FunctionOutliningInfo() = default;
149
150
151
152 unsigned getNumInlinedBlocks() const { return Entries.size() + 1; }
153
154
155
157
158
160
161
162 BasicBlock *NonReturnBlock = nullptr;
163
164
166};
167
168struct FunctionOutliningMultiRegionInfo {
169 FunctionOutliningMultiRegionInfo() = default;
170
171
172 struct OutlineRegionInfo {
174 BasicBlock *ExitBlock, BasicBlock *ReturnBlock)
175 : Region(Region), EntryBlock(EntryBlock), ExitBlock(ExitBlock),
176 ReturnBlock(ReturnBlock) {}
177 SmallVector<BasicBlock *, 8> Region;
181 };
182
184};
185
186struct PartialInlinerImpl {
187
188 PartialInlinerImpl(
189 function_ref<AssumptionCache &(Function &)> GetAC,
190 function_ref<AssumptionCache *(Function &)> LookupAC,
191 function_ref<TargetTransformInfo &(Function &)> GTTI,
192 function_ref<const TargetLibraryInfo &(Function &)> GTLI,
193 ProfileSummaryInfo &ProfSI,
194 function_ref<BlockFrequencyInfo &(Function &)> GBFI = nullptr)
195 : GetAssumptionCache(GetAC), LookupAssumptionCache(LookupAC),
196 GetTTI(GTTI), GetBFI(GBFI), GetTLI(GTLI), PSI(ProfSI) {}
197
199
200
201
202
203
204
205
206 std::pair<bool, Function *> unswitchFunction(Function &F);
207
208
209
210
211
212 struct FunctionCloner {
213
214
215 FunctionCloner(Function *F, FunctionOutliningInfo *OI,
216 OptimizationRemarkEmitter &ORE,
217 function_ref<AssumptionCache *(Function &)> LookupAC,
218 function_ref<TargetTransformInfo &(Function &)> GetTTI);
219 FunctionCloner(Function *F, FunctionOutliningMultiRegionInfo *OMRI,
220 OptimizationRemarkEmitter &ORE,
221 function_ref<AssumptionCache *(Function &)> LookupAC,
222 function_ref<TargetTransformInfo &(Function &)> GetTTI);
223
224 ~FunctionCloner();
225
226
227
228
229 void normalizeReturnBlock() const;
230
231
232 bool doMultiRegionFunctionOutlining();
233
234
235
236
237
238
239 Function *doSingleRegionFunctionOutlining();
240
241 Function *OrigFunc = nullptr;
242 Function *ClonedFunc = nullptr;
243
244 typedef std::pair<Function *, BasicBlock *> FuncBodyCallerPair;
245
247
248
249
250 bool IsFunctionInlined = false;
251
253
254 std::unique_ptr ClonedOI = nullptr;
255
256 std::unique_ptr ClonedOMRI = nullptr;
257 std::unique_ptr ClonedFuncBFI = nullptr;
258 OptimizationRemarkEmitter &ORE;
259 function_ref<AssumptionCache *(Function &)> LookupAC;
260 function_ref<TargetTransformInfo &(Function &)> GetTTI;
261 };
262
263private:
264 int NumPartialInlining = 0;
265 function_ref<AssumptionCache &(Function &)> GetAssumptionCache;
266 function_ref<AssumptionCache *(Function &)> LookupAssumptionCache;
267 function_ref<TargetTransformInfo &(Function &)> GetTTI;
268 function_ref<BlockFrequencyInfo &(Function &)> GetBFI;
269 function_ref<const TargetLibraryInfo &(Function &)> GetTLI;
270 ProfileSummaryInfo &PSI;
271
272
273
274
275
276 BranchProbability
277 getOutliningCallBBRelativeFreq(FunctionCloner &Cloner) const;
278
279
280
281 bool shouldPartialInline(CallBase &CB, FunctionCloner &Cloner,
282 BlockFrequency WeightedOutliningRcost,
283 OptimizationRemarkEmitter &ORE) const;
284
285
286
287
288 bool tryPartialInline(FunctionCloner &Cloner);
289
290
291
292 void
293 computeCallsiteToProfCountMap(Function *DuplicateFunction,
294 DenseMap<User *, uint64_t> &SiteCountMap) const;
295
296 bool isLimitReached() const {
299 }
300
301 static CallBase *getSupportedCallBase(User *U) {
305 return nullptr;
306 }
307
308 static CallBase *getOneCallSiteTo(Function &F) {
310 return getSupportedCallBase(User);
311 }
312
313 std::tuple<DebugLoc, BasicBlock *> getOneDebugLoc(Function &F) const {
314 CallBase *CB = getOneCallSiteTo(F);
317 return std::make_tuple(DLoc, Block);
318 }
319
320
321
322
323
324
325
326 std::tuple<InstructionCost, InstructionCost>
327 computeOutliningCosts(FunctionCloner &Cloner) const;
328
329
330
331
332 static InstructionCost computeBBInlineCost(BasicBlock *BB,
333 TargetTransformInfo *TTI);
334
335 std::unique_ptr
336 computeOutliningInfo(Function &F) const;
337
338 std::unique_ptr
339 computeOutliningColdRegionsInfo(Function &F,
340 OptimizationRemarkEmitter &ORE) const;
341};
342
343}
344
345std::unique_ptr
346PartialInlinerImpl::computeOutliningColdRegionsInfo(
349
350 DominatorTree DT(F);
351 LoopInfo LI(DT);
352 BranchProbabilityInfo BPI(F, LI);
353 std::unique_ptr ScopedBFI;
354 BlockFrequencyInfo *BFI;
355 if (!GetBFI) {
356 ScopedBFI.reset(new BlockFrequencyInfo(F, BPI, LI));
357 BFI = ScopedBFI.get();
358 } else
359 BFI = &(GetBFI(F));
360
361
362 if (!PSI.hasInstrumentationProfile())
363 return std::unique_ptr();
364
365 std::unique_ptr OutliningInfo =
366 std::make_unique();
367
368 auto IsSingleExit =
369 [&ORE](SmallVectorImpl<BasicBlock *> &BlockList) -> BasicBlock * {
371 for (auto *Block : BlockList) {
374 if (ExitBlock) {
375 ORE.emit([&]() {
376 return OptimizationRemarkMissed(DEBUG_TYPE, "MultiExitRegion",
377 &Succ->front())
378 << "Region dominated by "
379 << ore::NV("Block", BlockList.front()->getName())
380 << " has more than one region exit edge.";
381 });
382 return nullptr;
383 }
384
385 ExitBlock = Block;
386 }
387 }
388 }
389 return ExitBlock;
390 };
391
392 auto BBProfileCount = [BFI](BasicBlock *BB) {
394 };
395
396
397
398 TargetTransformInfo *FTTI = &GetTTI(F);
400 for (auto &BB : F)
401 OverallFunctionCost += computeBBInlineCost(&BB, FTTI);
402
403 LLVM_DEBUG(dbgs() << "OverallFunctionCost = " << OverallFunctionCost
404 << "\n";);
405
408
409 BranchProbability MinBranchProbability(
412 bool ColdCandidateFound = false;
414 std::vector<BasicBlock *> DFS;
415 SmallPtrSet<BasicBlock *, 8> VisitedSet;
416 DFS.push_back(CurrEntry);
417 VisitedSet.insert(CurrEntry);
418
419
420
421
422
423
424
425 while (!DFS.empty()) {
426 auto *ThisBB = DFS.back();
427 DFS.pop_back();
428
429
430
431 if (PSI.isColdBlock(ThisBB, BFI) ||
433 continue;
435 if (!VisitedSet.insert(*SI).second)
436 continue;
437 DFS.push_back(*SI);
438
439 BranchProbability SuccProb = BPI.getEdgeProbability(ThisBB, *SI);
440 if (SuccProb > MinBranchProbability)
441 continue;
442
443 LLVM_DEBUG(dbgs() << "Found cold edge: " << ThisBB->getName() << "->"
444 << SI->getName()
445 << "\nBranch Probability = " << SuccProb << "\n";);
446
447 SmallVector<BasicBlock *, 8> DominateVector;
448 DT.getDescendants(*SI, DominateVector);
450 "SI should be reachable and have at least itself as descendant");
451
452
453 if (!DominateVector.front()->hasNPredecessors(1)) {
455 << " doesn't have a single predecessor in the "
456 "dominator tree\n";);
457 continue;
458 }
459
461
462 if (!(ExitBlock = IsSingleExit(DominateVector))) {
464 << " doesn't have a unique successor\n";);
465 continue;
466 }
467
469 for (auto *BB : DominateVector)
470 OutlineRegionCost += computeBBInlineCost(BB, &GetTTI(*BB->getParent()));
471
472 LLVM_DEBUG(dbgs() << "OutlineRegionCost = " << OutlineRegionCost
473 << "\n";);
474
475 if ( && OutlineRegionCost < MinOutlineRegionCost) {
476 ORE.emit([&]() {
477 return OptimizationRemarkAnalysis(DEBUG_TYPE, "TooCostly",
478 &SI->front())
480 << " inline cost-savings smaller than "
481 << ore::NV("Cost", MinOutlineRegionCost);
482 });
483
484 LLVM_DEBUG(dbgs() << "ABORT: Outline region cost is smaller than "
485 << MinOutlineRegionCost << "\n";);
486 continue;
487 }
488
489
490
491
492
494
495
497 FunctionOutliningMultiRegionInfo::OutlineRegionInfo RegInfo(
498 DominateVector, DominateVector.front(), ExitBlock, ReturnBlock);
499 OutliningInfo->ORI.push_back(RegInfo);
500 LLVM_DEBUG(dbgs() << "Found Cold Candidate starting at block: "
501 << DominateVector.front()->getName() << "\n";);
502 ColdCandidateFound = true;
503 NumColdRegionsFound++;
504 }
505 }
506
507 if (ColdCandidateFound)
508 return OutliningInfo;
509
510 return std::unique_ptr();
511}
512
513std::unique_ptr
514PartialInlinerImpl::computeOutliningInfo(Function &F) const {
518 return std::unique_ptr();
519
520
523 };
524
525 auto IsReturnBlock = [](BasicBlock *BB) {
528 };
529
531 if (IsReturnBlock(Succ1))
532 return std::make_tuple(Succ1, Succ2);
533 if (IsReturnBlock(Succ2))
534 return std::make_tuple(Succ2, Succ1);
535
536 return std::make_tuple<BasicBlock *, BasicBlock *>(nullptr, nullptr);
537 };
538
539
541 if (IsSuccessor(Succ1, Succ2))
542 return std::make_tuple(Succ1, Succ2);
543 if (IsSuccessor(Succ2, Succ1))
544 return std::make_tuple(Succ2, Succ1);
545
546 return std::make_tuple<BasicBlock *, BasicBlock *>(nullptr, nullptr);
547 };
548
549 std::unique_ptr OutliningInfo =
550 std::make_unique();
551
553 bool CandidateFound = false;
554 do {
555
556
557
559 break;
560
562 break;
563
566
567 BasicBlock *ReturnBlock, *NonReturnBlock;
568 std::tie(ReturnBlock, NonReturnBlock) = GetReturnBlock(Succ1, Succ2);
569
570 if (ReturnBlock) {
571 OutliningInfo->Entries.push_back(CurrEntry);
572 OutliningInfo->ReturnBlock = ReturnBlock;
573 OutliningInfo->NonReturnBlock = NonReturnBlock;
574 CandidateFound = true;
575 break;
576 }
577
579 std::tie(CommSucc, OtherSucc) = GetCommonSucc(Succ1, Succ2);
580
581 if (!CommSucc)
582 break;
583
584 OutliningInfo->Entries.push_back(CurrEntry);
586 } while (true);
587
588 if (!CandidateFound)
589 return std::unique_ptr();
590
591
592
593 assert(OutliningInfo->Entries[0] == &F.front() &&
594 "Function Entry must be the first in Entries vector");
595 DenseSet<BasicBlock *> Entries(llvm::from_range, OutliningInfo->Entries);
596
597
598
599 auto HasNonEntryPred = [Entries](BasicBlock *BB) {
601 if (!Entries.count(Pred))
602 return true;
603 }
604 return false;
605 };
606 auto CheckAndNormalizeCandidate =
607 [Entries, HasNonEntryPred](FunctionOutliningInfo *OutliningInfo) {
608 for (BasicBlock *E : OutliningInfo->Entries) {
610 if (Entries.count(Succ))
611 continue;
612 if (Succ == OutliningInfo->ReturnBlock)
613 OutliningInfo->ReturnBlockPreds.push_back(E);
614 else if (Succ != OutliningInfo->NonReturnBlock)
615 return false;
616 }
617
618 if (HasNonEntryPred(E))
619 return false;
620 }
621 return true;
622 };
623
624 if (!CheckAndNormalizeCandidate(OutliningInfo.get()))
625 return std::unique_ptr();
626
627
628
630 BasicBlock *Cand = OutliningInfo->NonReturnBlock;
632 break;
633
634 if (HasNonEntryPred(Cand))
635 break;
636
639
640 BasicBlock *ReturnBlock, *NonReturnBlock;
641 std::tie(ReturnBlock, NonReturnBlock) = GetReturnBlock(Succ1, Succ2);
642 if (!ReturnBlock || ReturnBlock != OutliningInfo->ReturnBlock)
643 break;
644
646 break;
647
648
649 OutliningInfo->Entries.push_back(Cand);
650 OutliningInfo->NonReturnBlock = NonReturnBlock;
651 OutliningInfo->ReturnBlockPreds.push_back(Cand);
652 Entries.insert(Cand);
653 }
654
655 return OutliningInfo;
656}
657
658
660 if (F.hasProfileData())
661 return true;
662
663 for (auto *E : OI.Entries) {
666 continue;
668 return true;
669 }
670 return false;
671}
672
673BranchProbability PartialInlinerImpl::getOutliningCallBBRelativeFreq(
674 FunctionCloner &Cloner) const {
675 BasicBlock *OutliningCallBB = Cloner.OutlinedFunctions.back().second;
676 auto EntryFreq =
677 Cloner.ClonedFuncBFI->getBlockFreq(&Cloner.ClonedFunc->getEntryBlock());
678 auto OutliningCallFreq =
679 Cloner.ClonedFuncBFI->getBlockFreq(OutliningCallBB);
680
681
682
683 if (OutliningCallFreq.getFrequency() > EntryFreq.getFrequency())
684 OutliningCallFreq = EntryFreq;
685
687 OutliningCallFreq.getFrequency(), EntryFreq.getFrequency());
688
689 if (hasProfileData(*Cloner.OrigFunc, *Cloner.ClonedOI))
690 return OutlineRegionRelFreq;
691
692
693
694
695
696
697
698
699
700
701
702
703
704 if (OutlineRegionRelFreq < BranchProbability(45, 100))
705 return OutlineRegionRelFreq;
706
707 OutlineRegionRelFreq = std::max(
709
710 return OutlineRegionRelFreq;
711}
712
713bool PartialInlinerImpl::shouldPartialInline(
714 CallBase &CB, FunctionCloner &Cloner, BlockFrequency WeightedOutliningRcost,
715 OptimizationRemarkEmitter &ORE) const {
716 using namespace ore;
717
719 assert(Callee == Cloner.ClonedFunc);
720
723
725 auto &CalleeTTI = GetTTI(*Callee);
726 bool RemarksEnabled =
727 Callee->getContext().getDiagHandlerPtr()->isMissedOptRemarkEnabled(
729 InlineCost IC =
731 GetTLI, GetBFI, &PSI, RemarksEnabled ? &ORE : nullptr);
732
734 ORE.emit([&]() {
735 return OptimizationRemarkAnalysis(DEBUG_TYPE, "AlwaysInline", &CB)
736 << NV("Callee", Cloner.OrigFunc)
737 << " should always be fully inlined, not partially";
738 });
739 return false;
740 }
741
743 ORE.emit([&]() {
744 return OptimizationRemarkMissed(DEBUG_TYPE, "NeverInline", &CB)
745 << NV("Callee", Cloner.OrigFunc) << " not partially inlined into "
746 << NV("Caller", Caller)
747 << " because it should never be inlined (cost=never)";
748 });
749 return false;
750 }
751
752 if (!IC) {
753 ORE.emit([&]() {
754 return OptimizationRemarkAnalysis(DEBUG_TYPE, "TooCostly", &CB)
755 << NV("Callee", Cloner.OrigFunc) << " not partially inlined into "
756 << NV("Caller", Caller) << " because too costly to inline (cost="
757 << NV("Cost", IC.getCost()) << ", threshold="
759 });
760 return false;
761 }
762 const DataLayout &DL = Caller->getDataLayout();
763
764
766 BlockFrequency NormWeightedSavings(NonWeightedSavings);
767
768
769 if (NormWeightedSavings < WeightedOutliningRcost) {
770 ORE.emit([&]() {
771 return OptimizationRemarkAnalysis(DEBUG_TYPE, "OutliningCallcostTooHigh",
772 &CB)
773 << NV("Callee", Cloner.OrigFunc) << " not partially inlined into "
774 << NV("Caller", Caller) << " runtime overhead (overhead="
775 << NV("Overhead", (unsigned)WeightedOutliningRcost.getFrequency())
776 << ", savings="
777 << NV("Savings", (unsigned)NormWeightedSavings.getFrequency())
778 << ")"
779 << " of making the outlined call is too high";
780 });
781
782 return false;
783 }
784
785 ORE.emit([&]() {
786 return OptimizationRemarkAnalysis(DEBUG_TYPE, "CanBePartiallyInlined", &CB)
787 << NV("Callee", Cloner.OrigFunc) << " can be partially inlined into "
788 << NV("Caller", Caller) << " with cost=" << NV("Cost", IC.getCost())
789 << " (threshold="
791 });
792 return true;
793}
794
795
796
797
799PartialInlinerImpl::computeBBInlineCost(BasicBlock *BB,
800 TargetTransformInfo *TTI) {
805
806 switch (I.getOpcode()) {
807 case Instruction::BitCast:
808 case Instruction::PtrToInt:
809 case Instruction::IntToPtr:
810 case Instruction::Alloca:
811 case Instruction::PHI:
812 continue;
813 case Instruction::GetElementPtr:
815 continue;
816 break;
817 default:
818 break;
819 }
820
821 if (I.isLifetimeStartOrEnd())
822 continue;
823
827 FastMathFlags FMF;
828 for (Value *Val : II->args())
830
832 FMF = FPMO->getFastMathFlags();
833
834 IntrinsicCostAttributes ICA(IID, II->getType(), Tys, FMF);
836 continue;
837 }
838
841 continue;
842 }
843
846 continue;
847 }
848
850 InlineCost += (SI->getNumCases() + 1) * InstrCost;
851 continue;
852 }
854 }
855
856 return InlineCost;
857}
858
859std::tuple<InstructionCost, InstructionCost>
860PartialInlinerImpl::computeOutliningCosts(FunctionCloner &Cloner) const {
861 InstructionCost OutliningFuncCallCost = 0, OutlinedFunctionCost = 0;
862 for (auto FuncBBPair : Cloner.OutlinedFunctions) {
863 Function *OutlinedFunc = FuncBBPair.first;
864 BasicBlock* OutliningCallBB = FuncBBPair.second;
865
866
867 auto *OutlinedFuncTTI = &GetTTI(*OutlinedFunc);
868 OutliningFuncCallCost +=
869 computeBBInlineCost(OutliningCallBB, OutlinedFuncTTI);
870
871
872 for (BasicBlock &BB : *OutlinedFunc)
873 OutlinedFunctionCost += computeBBInlineCost(&BB, OutlinedFuncTTI);
874 }
875 assert(OutlinedFunctionCost >= Cloner.OutlinedRegionCost &&
876 "Outlined function cost should be no less than the outlined region");
877
878
879
880
881 OutlinedFunctionCost -=
883
885 OutliningFuncCallCost +
886 (OutlinedFunctionCost - Cloner.OutlinedRegionCost) +
888
889 return std::make_tuple(OutliningFuncCallCost, OutliningRuntimeOverhead);
890}
891
892
893
894
895void PartialInlinerImpl::computeCallsiteToProfCountMap(
896 Function *DuplicateFunction,
897 DenseMap<User *, uint64_t> &CallSiteToProfCountMap) const {
898 std::vector<User *> Users(DuplicateFunction->user_begin(),
899 DuplicateFunction->user_end());
900 Function *CurrentCaller = nullptr;
901 std::unique_ptr TempBFI;
902 BlockFrequencyInfo *CurrentCallerBFI = nullptr;
903
905
906 if (!GetBFI) {
907 DominatorTree DT(*Caller);
908 LoopInfo LI(DT);
909 BranchProbabilityInfo BPI(*Caller, LI);
910 TempBFI.reset(new BlockFrequencyInfo(*Caller, BPI, LI));
911 CurrentCallerBFI = TempBFI.get();
912 } else {
913
914 CurrentCallerBFI = &(GetBFI(*Caller));
915 }
916 };
917
918 for (User *User : Users) {
919 CallBase *CB = getSupportedCallBase(User);
921 if (CurrentCaller != Caller) {
922 CurrentCaller = Caller;
923 ComputeCurrBFI(Caller);
924 } else {
925 assert(CurrentCallerBFI && "CallerBFI is not set");
926 }
930 CallSiteToProfCountMap[User] = *Count;
931 else
932 CallSiteToProfCountMap[User] = 0;
933 }
934}
935
936PartialInlinerImpl::FunctionCloner::FunctionCloner(
937 Function *F, FunctionOutliningInfo *OI, OptimizationRemarkEmitter &ORE,
938 function_ref<AssumptionCache *(Function &)> LookupAC,
939 function_ref<TargetTransformInfo &(Function &)> GetTTI)
940 : OrigFunc(F), ORE(ORE), LookupAC(LookupAC), GetTTI(GetTTI) {
941 ClonedOI = std::make_unique();
942
943
946
947 ClonedOI->ReturnBlock = cast(VMap[OI->ReturnBlock]);
948 ClonedOI->NonReturnBlock = cast(VMap[OI->NonReturnBlock]);
951
952 for (BasicBlock *E : OI->ReturnBlockPreds) {
954 ClonedOI->ReturnBlockPreds.push_back(NewE);
955 }
956
957
958 F->replaceAllUsesWith(ClonedFunc);
959}
960
961PartialInlinerImpl::FunctionCloner::FunctionCloner(
962 Function *F, FunctionOutliningMultiRegionInfo *OI,
966 : OrigFunc(F), ORE(ORE), LookupAC(LookupAC), GetTTI(GetTTI) {
967 ClonedOMRI = std::make_unique();
968
969
972
973
974
975 for (const FunctionOutliningMultiRegionInfo::OutlineRegionInfo &RegionInfo :
976 OI->ORI) {
980
983 BasicBlock *NewReturnBlock = nullptr;
986 FunctionOutliningMultiRegionInfo::OutlineRegionInfo MappedRegionInfo(
987 Region, NewEntryBlock, NewExitBlock, NewReturnBlock);
988 ClonedOMRI->ORI.push_back(MappedRegionInfo);
989 }
990
991
992 F->replaceAllUsesWith(ClonedFunc);
993}
994
995void PartialInlinerImpl::FunctionCloner::normalizeReturnBlock() const {
996 auto GetFirstPHI = [](BasicBlock *BB) {
998 PHINode *FirstPhi = nullptr;
999 while (I != BB->end()) {
1001 if (!Phi)
1002 break;
1003 if (!FirstPhi) {
1004 FirstPhi = Phi;
1005 break;
1006 }
1007 }
1008 return FirstPhi;
1009 };
1010
1011
1012
1013 if (!ClonedOI)
1014 return;
1015
1016
1017
1018
1019
1020 BasicBlock *PreReturn = ClonedOI->ReturnBlock;
1021
1022 PHINode *FirstPhi = GetFirstPHI(PreReturn);
1023 unsigned NumPredsFromEntries = ClonedOI->ReturnBlockPreds.size();
1024
1025 if (!FirstPhi || FirstPhi->getNumIncomingValues() <= NumPredsFromEntries + 1)
1026 return;
1027
1028 auto IsTrivialPhi = [](PHINode *PN) -> Value * {
1030 return PN->getIncomingValue(0);
1031 return nullptr;
1032 };
1033
1034 ClonedOI->ReturnBlock = ClonedOI->ReturnBlock->splitBasicBlock(
1035 ClonedOI->ReturnBlock->getFirstNonPHIIt());
1038 SmallVector<Instruction *, 4> DeadPhis;
1039 while (I != PreReturn->end()) {
1041 if (!OldPhi)
1042 break;
1043
1044 PHINode *RetPhi =
1048 Ins = ClonedOI->ReturnBlock->getFirstNonPHIIt();
1049
1051 for (BasicBlock *E : ClonedOI->ReturnBlockPreds) {
1054 }
1055
1056
1057
1058
1059
1060 if (auto *OldPhiVal = IsTrivialPhi(OldPhi)) {
1063 }
1064 ++I;
1065 }
1066 for (auto *DP : DeadPhis)
1067 DP->eraseFromParent();
1068
1069 for (auto *E : ClonedOI->ReturnBlockPreds)
1070 E->getTerminator()->replaceUsesOfWith(PreReturn, ClonedOI->ReturnBlock);
1071}
1072
1073bool PartialInlinerImpl::FunctionCloner::doMultiRegionFunctionOutlining() {
1074
1075 auto ComputeRegionCost =
1078 for (BasicBlock* BB : Region)
1079 Cost += computeBBInlineCost(BB, &GetTTI(*BB->getParent()));
1080 return Cost;
1081 };
1082
1083 assert(ClonedOMRI && "Expecting OutlineInfo for multi region outline");
1084
1085 if (ClonedOMRI->ORI.empty())
1086 return false;
1087
1088
1089 DominatorTree DT;
1091
1092
1093 LoopInfo LI(DT);
1094 BranchProbabilityInfo BPI(*ClonedFunc, LI);
1095 ClonedFuncBFI.reset(new BlockFrequencyInfo(*ClonedFunc, BPI, LI));
1096
1097
1098 CodeExtractorAnalysisCache CEAC(*ClonedFunc);
1099
1100 SetVector<Value *> Inputs, Outputs, Sinks;
1101 for (FunctionOutliningMultiRegionInfo::OutlineRegionInfo RegionInfo :
1102 ClonedOMRI->ORI) {
1104 ComputeRegionCost(RegionInfo.Region);
1105
1106 CodeExtractor CE(RegionInfo.Region, &DT, false,
1107 ClonedFuncBFI.get(), &BPI,
1108 LookupAC(*RegionInfo.EntryBlock->getParent()),
1109 false);
1110
1111 CE.findInputsOutputs(Inputs, Outputs, Sinks);
1112
1114 dbgs() << "inputs: " << Inputs.size() << "\n";
1115 dbgs() << "outputs: " << Outputs.size() << "\n";
1116 for (Value *value : Inputs)
1117 dbgs() << "value used in func: " << *value << "\n";
1118 for (Value *output : Outputs)
1119 dbgs() << "instr used in func: " << *output << "\n";
1120 });
1121
1122
1124 continue;
1125
1126 if (Function *OutlinedFunc = CE.extractCodeRegion(CEAC)) {
1127 CallBase *OCS = PartialInlinerImpl::getOneCallSiteTo(*OutlinedFunc);
1130 OutlinedFunctions.push_back(std::make_pair(OutlinedFunc,OutliningCallBB));
1131 NumColdRegionsOutlined++;
1132 OutlinedRegionCost += CurrentOutlinedRegionCost;
1133
1137 }
1138 } else
1139 ORE.emit([&]() {
1140 return OptimizationRemarkMissed(DEBUG_TYPE, "ExtractFailed",
1141 &RegionInfo.Region.front()->front())
1142 << "Failed to extract region at block "
1143 << ore::NV("Block", RegionInfo.Region.front());
1144 });
1145 }
1146
1147 return !OutlinedFunctions.empty();
1148}
1149
1151PartialInlinerImpl::FunctionCloner::doSingleRegionFunctionOutlining() {
1152
1153
1154 auto ToBeInlined = [&, this](BasicBlock *BB) {
1155 return BB == ClonedOI->ReturnBlock ||
1157 };
1158
1159 assert(ClonedOI && "Expecting OutlineInfo for single region outline");
1160
1161 DominatorTree DT;
1163
1164
1165 LoopInfo LI(DT);
1166 BranchProbabilityInfo BPI(*ClonedFunc, LI);
1167 ClonedFuncBFI.reset(new BlockFrequencyInfo(*ClonedFunc, BPI, LI));
1168
1169
1170 std::vector<BasicBlock *> ToExtract;
1171 auto *ClonedFuncTTI = &GetTTI(*ClonedFunc);
1172 ToExtract.push_back(ClonedOI->NonReturnBlock);
1173 OutlinedRegionCost += PartialInlinerImpl::computeBBInlineCost(
1174 ClonedOI->NonReturnBlock, ClonedFuncTTI);
1175 for (BasicBlock *BB : depth_first(&ClonedFunc->getEntryBlock()))
1176 if (!ToBeInlined(BB) && BB != ClonedOI->NonReturnBlock) {
1177 ToExtract.push_back(BB);
1178
1179
1180
1181
1182 OutlinedRegionCost += computeBBInlineCost(BB, ClonedFuncTTI);
1183 }
1184
1185
1186 CodeExtractorAnalysisCache CEAC(*ClonedFunc);
1188 CodeExtractor(ToExtract, &DT, false,
1189 ClonedFuncBFI.get(), &BPI, LookupAC(*ClonedFunc),
1190 true)
1191 .extractCodeRegion(CEAC);
1192
1193 if (OutlinedFunc) {
1195 PartialInlinerImpl::getOneCallSiteTo(*OutlinedFunc)->getParent();
1197 OutlinedFunctions.push_back(std::make_pair(OutlinedFunc, OutliningCallBB));
1198 } else
1199 ORE.emit([&]() {
1200 return OptimizationRemarkMissed(DEBUG_TYPE, "ExtractFailed",
1201 &ToExtract.front()->front())
1202 << "Failed to extract region at block "
1203 << ore::NV("Block", ToExtract.front());
1204 });
1205
1206 return OutlinedFunc;
1207}
1208
1209PartialInlinerImpl::FunctionCloner::~FunctionCloner() {
1210
1211
1213 ClonedFunc->eraseFromParent();
1214 if (!IsFunctionInlined) {
1215
1216
1217 for (auto FuncBBPair : OutlinedFunctions) {
1219 Func->eraseFromParent();
1220 }
1221 }
1222}
1223
1224std::pair<bool, Function *> PartialInlinerImpl::unswitchFunction(Function &F) {
1225 if (F.hasAddressTaken())
1226 return {false, nullptr};
1227
1228
1229 if (F.hasFnAttribute(Attribute::AlwaysInline))
1230 return {false, nullptr};
1231
1232 if (F.hasFnAttribute(Attribute::NoInline))
1233 return {false, nullptr};
1234
1235 if (PSI.isFunctionEntryCold(&F))
1236 return {false, nullptr};
1237
1238 if (F.users().empty())
1239 return {false, nullptr};
1240
1241 OptimizationRemarkEmitter ORE(&F);
1242
1243
1244
1245 if (PSI.hasProfileSummary() && F.hasProfileData() &&
1247 std::unique_ptr OMRI =
1248 computeOutliningColdRegionsInfo(F, ORE);
1249 if (OMRI) {
1250 FunctionCloner Cloner(&F, OMRI.get(), ORE, LookupAssumptionCache, GetTTI);
1251
1253 dbgs() << "HotCountThreshold = " << PSI.getHotCountThreshold() << "\n";
1254 dbgs() << "ColdCountThreshold = " << PSI.getColdCountThreshold()
1255 << "\n";
1256 });
1257
1258 bool DidOutline = Cloner.doMultiRegionFunctionOutlining();
1259
1260 if (DidOutline) {
1262 dbgs() << ">>>>>> Outlined (Cloned) Function >>>>>>\n";
1263 Cloner.ClonedFunc->print(dbgs());
1264 dbgs() << "<<<<<< Outlined (Cloned) Function <<<<<<\n";
1265 });
1266
1267 if (tryPartialInline(Cloner))
1268 return {true, nullptr};
1269 }
1270 }
1271 }
1272
1273
1274
1275
1276 std::unique_ptr OI = computeOutliningInfo(F);
1277 if (!OI)
1278 return {false, nullptr};
1279
1280 FunctionCloner Cloner(&F, OI.get(), ORE, LookupAssumptionCache, GetTTI);
1281 Cloner.normalizeReturnBlock();
1282
1283 Function *OutlinedFunction = Cloner.doSingleRegionFunctionOutlining();
1284
1285 if (!OutlinedFunction)
1286 return {false, nullptr};
1287
1288 if (tryPartialInline(Cloner))
1289 return {true, OutlinedFunction};
1290
1291 return {false, nullptr};
1292}
1293
1294bool PartialInlinerImpl::tryPartialInline(FunctionCloner &Cloner) {
1295 if (Cloner.OutlinedFunctions.empty())
1296 return false;
1297
1298 auto OutliningCosts = computeOutliningCosts(Cloner);
1299
1301 InstructionCost NonWeightedRcost = std::get<1>(OutliningCosts);
1302
1304 "Expected valid costs");
1305
1306
1307
1308 BranchProbability RelativeToEntryFreq;
1309 if (Cloner.ClonedOI)
1310 RelativeToEntryFreq = getOutliningCallBBRelativeFreq(Cloner);
1311 else
1312
1313
1314
1315
1316
1317 RelativeToEntryFreq = BranchProbability(0, 1);
1318
1319 BlockFrequency WeightedRcost =
1320 BlockFrequency(NonWeightedRcost.getValue()) * RelativeToEntryFreq;
1321
1322
1323
1324
1325
1326 if ( && Cloner.OutlinedRegionCost < SizeCost) {
1327 OptimizationRemarkEmitter OrigFuncORE(Cloner.OrigFunc);
1330 std::tie(DLoc, Block) = getOneDebugLoc(*Cloner.ClonedFunc);
1331 OrigFuncORE.emit([&]() {
1332 return OptimizationRemarkAnalysis(DEBUG_TYPE, "OutlineRegionTooSmall",
1334 << ore::NV("Function", Cloner.OrigFunc)
1335 << " not partially inlined into callers (Original Size = "
1336 << ore::NV("OutlinedRegionOriginalSize", Cloner.OutlinedRegionCost)
1337 << ", Size of call sequence to outlined function = "
1338 << ore::NV("NewSize", SizeCost) << ")";
1339 });
1340 return false;
1341 }
1342
1343 assert(Cloner.OrigFunc->users().empty() &&
1344 "F's users should all be replaced!");
1345
1346 std::vector<User *> Users(Cloner.ClonedFunc->user_begin(),
1347 Cloner.ClonedFunc->user_end());
1348
1349 DenseMap<User *, uint64_t> CallSiteToProfCountMap;
1350 auto CalleeEntryCount = Cloner.OrigFunc->getEntryCount();
1351 if (CalleeEntryCount)
1352 computeCallsiteToProfCountMap(Cloner.ClonedFunc, CallSiteToProfCountMap);
1353
1354 uint64_t CalleeEntryCountV =
1355 (CalleeEntryCount ? CalleeEntryCount->getCount() : 0);
1356
1357 bool AnyInline = false;
1358 for (User *User : Users) {
1359 CallBase *CB = getSupportedCallBase(User);
1360
1361 if (isLimitReached())
1362 continue;
1363
1364 OptimizationRemarkEmitter CallerORE(CB->getCaller());
1365 if (!shouldPartialInline(*CB, Cloner, WeightedRcost, CallerORE))
1366 continue;
1367
1368
1369
1370 OptimizationRemark OR(DEBUG_TYPE, "PartiallyInlined", CB);
1371 OR << ore::NV("Callee", Cloner.OrigFunc) << " partially inlined into "
1373
1374 InlineFunctionInfo IFI(GetAssumptionCache, &PSI);
1375
1376
1377 if ((*CB, IFI, false, nullptr, true,
1378 (Cloner.ClonedOI ? Cloner.OutlinedFunctions.back().first
1379 : nullptr))
1381 continue;
1382
1383 CallerORE.emit(OR);
1384
1385
1386 if (CalleeEntryCountV) {
1387 if (auto It = CallSiteToProfCountMap.find(User);
1388 It != CallSiteToProfCountMap.end()) {
1389 uint64_t CallSiteCount = It->second;
1390 CalleeEntryCountV -= std::min(CalleeEntryCountV, CallSiteCount);
1391 }
1392 }
1393
1394 AnyInline = true;
1395 NumPartialInlining++;
1396
1397 if (Cloner.ClonedOI)
1398 NumPartialInlined++;
1399 else
1400 NumColdOutlinePartialInlined++;
1401 }
1402
1403 if (AnyInline) {
1404 Cloner.IsFunctionInlined = true;
1405 if (CalleeEntryCount)
1406 Cloner.OrigFunc->setEntryCount(Function::ProfileCount(
1407 CalleeEntryCountV, CalleeEntryCount->getType()));
1408 OptimizationRemarkEmitter OrigFuncORE(Cloner.OrigFunc);
1409 OrigFuncORE.emit([&]() {
1410 return OptimizationRemark(DEBUG_TYPE, "PartiallyInlined", Cloner.OrigFunc)
1411 << "Partially inlined into at least one caller";
1412 });
1413 }
1414
1415 return AnyInline;
1416}
1417
1418bool PartialInlinerImpl::run(Module &M) {
1420 return false;
1421
1422 std::vector<Function *> Worklist;
1423 Worklist.reserve(M.size());
1424 for (Function &F : M)
1425 if (.use_empty() &&
.isDeclaration())
1426 Worklist.push_back(&F);
1427
1429 while (!Worklist.empty()) {
1430 Function *CurrFunc = Worklist.back();
1431 Worklist.pop_back();
1432
1434 continue;
1435
1436 std::pair<bool, Function *> Result = unswitchFunction(*CurrFunc);
1438 Worklist.push_back(Result.second);
1440 }
1441
1443}
1444
1448
1451 };
1452
1455 };
1456
1459 };
1460
1463 };
1464
1467 };
1468
1470
1471 if (PartialInlinerImpl(GetAssumptionCache, LookupAssumptionCache, GetTTI,
1472 GetTLI, PSI, GetBFI)
1473 .run(M))
1476}
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 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.
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
static cl::opt< int > InstrCost("inline-instr-cost", cl::Hidden, cl::init(5), cl::desc("Cost of a single instruction when inlining"))
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)
Definition PartialInlining.cpp:659
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 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)
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.
iterator begin()
Instruction iterator methods.
const Function * getParent() const
Return the enclosing method, or null if none.
LLVM_ABI iterator_range< filter_iterator< BasicBlock::const_iterator, std::function< bool(const Instruction &)> > > instructionsWithoutDebug(bool SkipPseudoOp=true) const
Return a const iterator range over the instructions in the block, skipping any debug instructions.
LLVM_ABI const BasicBlock * getSinglePredecessor() const
Return the predecessor of this block if it has a single predecessor block.
const Instruction & front() const
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...
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
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.
Conditional or Unconditional Branch instruction.
bool isUnconditional() const
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).
iterator find(const_arg_type_t< KeyT > Val)
void recalculate(ParentType &Func)
recalculate - compute a dominator tree for the given function
void setCallingConv(CallingConv::ID CC)
int getCost() const
Get the inline cost estimate.
int getCostDelta() const
Get the cost delta from the threshold for inlining.
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.
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...
PreservedAnalyses run(Module &M, ModuleAnalysisManager &)
Definition PartialInlining.cpp:1445
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
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.
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.
user_iterator user_begin()
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ BasicBlock
Various leaf nodes.
LLVM_ABI int getInstrCost()
@ CE
Windows NT (Windows on ARM)
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
NodeAddr< FuncNode * > Func
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
LLVM_ABI InlineResult InlineFunction(CallBase &CB, InlineFunctionInfo &IFI, bool MergeAttributes=false, AAResults *CalleeAAR=nullptr, bool InsertLifetime=true, Function *ForwardVarArgsTo=nullptr, OptimizationRemarkEmitter *ORE=nullptr)
This function inlines the called function into the basic block of the caller.
decltype(auto) dyn_cast(const From &Val)
dyn_cast - Return the argument parameter cast to the specified type.
auto successors(const MachineBasicBlock *BB)
constexpr from_range_t from_range
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
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.
FunctionAddr VTableAddr Count
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 - Return true if the parameter to the template is an instance of one of the template type argu...
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.
RNSuccIterator< NodeRef, BlockT, RegionT > succ_end(NodeRef Node)
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 - Return the argument parameter cast to the specified type.
auto predecessors(const MachineBasicBlock *BB)
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
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.
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.