LLVM: lib/Transforms/IPO/HotColdSplitting.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
56#include
57#include
58#include
59
60#define DEBUG_TYPE "hotcoldsplit"
61
62STATISTIC(NumColdRegionsFound, "Number of cold regions found.");
63STATISTIC(NumColdRegionsOutlined, "Number of cold regions outlined.");
64
65using namespace llvm;
66
69
72 cl::desc("Base penalty for splitting cold code (as a "
73 "multiple of TCC_Basic)"));
74
77 cl::desc("Enable placement of extracted cold functions"
78 " into a separate section after hot-cold splitting."));
79
83 cl::desc("Name for the section containing cold functions "
84 "extracted by hot-cold splitting."));
85
88 cl::desc("Maximum number of parameters for a split function"));
89
92 cl::desc("Divisor of cold branch probability."
93 "BranchProbability = 1/ColdBranchProbDenom"));
94
95namespace {
96
97
98
99
100
101
104 return false;
106 return true;
109}
110
111void analyzeProfMetadata(BasicBlock *BB,
114
116 if (!CondBr)
117 return;
118
121 return;
122
123 auto SumWt = TrueWt + FalseWt;
124 if (SumWt == 0)
125 return;
126
129
130 if (TrueProb <= ColdProbThresh)
132
133 if (FalseProb <= ColdProbThresh)
135}
136
137bool unlikelyExecuted(BasicBlock &BB) {
138
140 return true;
141
142
143
146 if (CB->hasFnAttr(Attribute::Cold) &&
147 !CB->getMetadata(LLVMContext::MD_nosanitize))
148 return true;
149
150
151
153 if (auto *CI =
155 if (CI->hasFnAttr(Attribute::NoReturn))
156 return false;
157 return true;
158 }
159
160 return false;
161}
162
163
164static bool mayExtractBlock(const BasicBlock &BB) {
165
166
167
168
169
170
171
173 return false;
176 return false;
177
178
179
180
181
182
184 BB, [](const Instruction &I) { return I.getType()->isTokenTy(); })) {
185 return false;
186 }
187
188 return true;
189}
190
191
192
193
194
195static bool markFunctionCold(Function &F, bool UpdateEntryCount = false) {
196 assert(.hasOptNone() && "Can't mark this cold");
198 if (.hasFnAttribute(Attribute::Cold)) {
199 F.addFnAttr(Attribute::Cold);
201 }
202 if (.hasMinSize()) {
203 F.addFnAttr(Attribute::MinSize);
205 }
206 if (UpdateEntryCount) {
207
208
209 F.setEntryCount(0);
211 }
212
214}
215
216}
217
218
219bool HotColdSplitting::isFunctionCold(const Function &F) const {
220 if (F.hasFnAttribute(Attribute::Cold))
221 return true;
222
224 return true;
225
226 if (PSI->isFunctionEntryCold(&F))
227 return true;
228
229 return false;
230}
231
232bool HotColdSplitting::isBasicBlockCold(
236 if (BFI) {
237 if (PSI->isColdBlock(BB, BFI))
238 return true;
239 } else {
240
241 analyzeProfMetadata(BB, ColdProbThresh, AnnotatedColdBlocks);
242
243
244
245 if (AnnotatedColdBlocks.count(BB))
246 return true;
247 }
248
250 return true;
251
252 return false;
253}
254
255
256
257bool HotColdSplitting::shouldOutlineFrom(const Function &F) const {
258 if (F.hasFnAttribute(Attribute::AlwaysInline))
259 return false;
260
261 if (F.hasFnAttribute(Attribute::NoInline))
262 return false;
263
264
265
266 if (F.hasFnAttribute(Attribute::NoReturn))
267 return false;
268
269 if (F.hasFnAttribute(Attribute::SanitizeAddress) ||
270 F.hasFnAttribute(Attribute::SanitizeHWAddress) ||
271 F.hasFnAttribute(Attribute::SanitizeThread) ||
272 F.hasFnAttribute(Attribute::SanitizeMemory))
273 return false;
274
275
276 if (F.hasPersonalityFn())
278 return false;
279
280 return true;
281}
282
283
286
287
292 Benefit +=
294
295 return Benefit;
296}
297
298
300 unsigned NumInputs, unsigned NumOutputs) {
302 LLVM_DEBUG(dbgs() << "Applying penalty for splitting: " << Penalty << "\n");
303
304
305
307 return Penalty;
308
309
310
311 bool NoBlocksReturn = true;
314
315
318 continue;
319 }
320
323 NoBlocksReturn = false;
324 SuccsOutsideRegion.insert(SuccBB);
325 }
326 }
327 }
328
329
330
331
332
333
334 unsigned NumSplitExitPhis = 0;
335 for (BasicBlock *ExitBB : SuccsOutsideRegion) {
336 for (PHINode &PN : ExitBB->phis()) {
337
338 int NumIncomingVals = 0;
339 for (unsigned i = 0; i < PN.getNumIncomingValues(); ++i)
341 ++NumIncomingVals;
342 if (NumIncomingVals > 1) {
343 ++NumSplitExitPhis;
344 break;
345 }
346 }
347 }
348 }
349
350
351
352 int NumOutputsAndSplitPhis = NumOutputs + NumSplitExitPhis;
353 int NumParams = NumInputs + NumOutputsAndSplitPhis;
355 LLVM_DEBUG(dbgs() << NumInputs << " inputs and " << NumOutputsAndSplitPhis
356 << " outputs exceeds parameter limit ("
358 return std::numeric_limits::max();
359 }
361 LLVM_DEBUG(dbgs() << "Applying penalty for: " << NumParams << " params\n");
362 Penalty += CostForArgMaterialization * NumParams;
363
364
365
366 LLVM_DEBUG(dbgs() << "Applying penalty for: " << NumOutputsAndSplitPhis
367 << " outputs/split phis\n");
369 Penalty += CostForRegionOutput * NumOutputsAndSplitPhis;
370
371
372 if (NoBlocksReturn) {
374 << " non-returning terminators\n");
375 Penalty -= Region.size();
376 }
377
378
379
380 if (SuccsOutsideRegion.size() > 1) {
381 LLVM_DEBUG(dbgs() << "Applying penalty for: " << SuccsOutsideRegion.size()
382 << " non-region successors\n");
384 }
385
386 return Penalty;
387}
388
389
390bool HotColdSplitting::isSplittingBeneficial(CodeExtractor &CE,
394
395
396
397 SetVector<Value *> Inputs, Outputs, Sinks;
398 CE.findInputsOutputs(Inputs, Outputs, Sinks);
400 int OutliningPenalty =
402 LLVM_DEBUG(dbgs() << "Split profitability: benefit = " << OutliningBenefit
403 << ", penalty = " << OutliningPenalty << "\n");
404 if (!OutliningBenefit.isValid() || OutliningBenefit <= OutliningPenalty)
405 return false;
406
407 return true;
408}
409
410
411
412Function *HotColdSplitting::extractColdRegion(
417 if (Function *OutF = CE.extractCodeRegion(CEAC)) {
418 User *U = *OutF->user_begin();
420 NumColdRegionsOutlined++;
424 }
426
429 else {
431 OutF->setSection(OrigF->getSection());
432 }
433
434 markFunctionCold(*OutF, BFI != nullptr);
435
437 ORE.emit([&]() {
438 return OptimizationRemark(DEBUG_TYPE, "HotColdSplit",
439 &*EntryPoint.begin())
440 << ore::NV("Original", OrigF) << " split cold code into "
441 << ore::NV("Split", OutF);
442 });
443 return OutF;
444 }
445
446 ORE.emit([&]() {
447 return OptimizationRemarkMissed(DEBUG_TYPE, "ExtractFailed",
448 &*EntryPoint.begin())
449 << "Failed to extract region at block "
450 << ore::NV("Block", &EntryPoint);
451 });
452 return nullptr;
453}
454
455
456using BlockTy = std::pair<BasicBlock *, unsigned>;
457
458namespace {
459
460
461
462
463class OutliningRegion {
464
465
466
468
469
470
471
472 BasicBlock *SuggestedEntryPoint = nullptr;
473
474
475 bool EntireFunctionCold = false;
476
477
478 static unsigned getEntryPointScore(BasicBlock &BB, unsigned Score) {
479 return mayExtractBlock(BB) ? Score : 0;
480 }
481
482
483
484 static constexpr unsigned ScoreForSuccBlock = 1;
485 static constexpr unsigned ScoreForSinkBlock = 1;
486
487 OutliningRegion(const OutliningRegion &) = delete;
488 OutliningRegion &operator=(const OutliningRegion &) = delete;
489
490public:
491 OutliningRegion() = default;
492 OutliningRegion(OutliningRegion &&) = default;
493 OutliningRegion &operator=(OutliningRegion &&) = default;
494
495 static std::vector create(BasicBlock &SinkBB,
498 std::vector Regions;
500
501 Regions.emplace_back();
502 OutliningRegion *ColdRegion = &Regions.back();
503
504 auto addBlockToRegion = [&](BasicBlock *BB, unsigned Score) {
505 RegionBlocks.insert(BB);
506 ColdRegion->Blocks.emplace_back(BB, Score);
507 };
508
509
510 unsigned SinkScore = getEntryPointScore(SinkBB, ScoreForSinkBlock);
511 ColdRegion->SuggestedEntryPoint = (SinkScore > 0) ? &SinkBB : nullptr;
512 unsigned BestScore = SinkScore;
513
514
515 auto PredIt = ++idf_begin(&SinkBB);
516 auto PredEnd = idf_end(&SinkBB);
517 while (PredIt != PredEnd) {
519 bool SinkPostDom = PDT.dominates(&SinkBB, &PredBB);
520
521
522
523 if (SinkPostDom && pred_empty(&PredBB)) {
524 ColdRegion->EntireFunctionCold = true;
525 return Regions;
526 }
527
528
529
530 if (!SinkPostDom || !mayExtractBlock(PredBB)) {
531 PredIt.skipChildren();
532 continue;
533 }
534
535
536
537
538 unsigned PredScore = getEntryPointScore(PredBB, PredIt.getPathLength());
539 if (PredScore > BestScore) {
540 ColdRegion->SuggestedEntryPoint = &PredBB;
541 BestScore = PredScore;
542 }
543
544 addBlockToRegion(&PredBB, PredScore);
545 ++PredIt;
546 }
547
548
549
550
551
552
553
554 if (mayExtractBlock(SinkBB)) {
555 addBlockToRegion(&SinkBB, SinkScore);
557 ColdRegion->EntireFunctionCold = true;
558 return Regions;
559 }
560 } else {
561 Regions.emplace_back();
562 ColdRegion = &Regions.back();
563 BestScore = 0;
564 }
565
566
567 auto SuccIt = ++df_begin(&SinkBB);
568 auto SuccEnd = df_end(&SinkBB);
569 while (SuccIt != SuccEnd) {
571 bool SinkDom = DT.dominates(&SinkBB, &SuccBB);
572
573
574 bool DuplicateBlock = RegionBlocks.count(&SuccBB);
575
576
577
578 if (DuplicateBlock || !SinkDom || !mayExtractBlock(SuccBB)) {
579 SuccIt.skipChildren();
580 continue;
581 }
582
583 unsigned SuccScore = getEntryPointScore(SuccBB, ScoreForSuccBlock);
584 if (SuccScore > BestScore) {
585 ColdRegion->SuggestedEntryPoint = &SuccBB;
586 BestScore = SuccScore;
587 }
588
589 addBlockToRegion(&SuccBB, SuccScore);
590 ++SuccIt;
591 }
592
593 return Regions;
594 }
595
596
597 bool empty() const { return !SuggestedEntryPoint; }
598
599
601
602
603 bool isEntireFunctionCold() const { return EntireFunctionCold; }
604
605
607 assert(!empty() && !isEntireFunctionCold() && "Nothing to extract");
608
609
610
611
613 BasicBlock *NextEntryPoint = nullptr;
614 unsigned NextScore = 0;
615 auto RegionEndIt = Blocks.end();
618 unsigned Score = Block.second;
619 bool InSubRegion =
620 BB == SuggestedEntryPoint || DT.dominates(SuggestedEntryPoint, BB);
621 if (!InSubRegion && Score > NextScore) {
622 NextEntryPoint = BB;
623 NextScore = Score;
624 }
625 if (InSubRegion && BB != SuggestedEntryPoint)
627 return InSubRegion;
628 });
629 Blocks.erase(RegionStartIt, RegionEndIt);
630
631
632 SuggestedEntryPoint = NextEntryPoint;
633
634 return SubRegion;
635 }
636};
637}
638
639bool HotColdSplitting::outlineColdRegions(Function &F, bool HasProfileSummary) {
640
641 SmallPtrSet<BasicBlock *, 4> ColdBlocks;
642
643
644 SmallPtrSet<BasicBlock *, 4> CannotBeOutlinedColdBlocks;
645
646
647 SmallPtrSet<BasicBlock *, 4> AnnotatedColdBlocks;
648
649
650
652
653
654
655
656 ReversePostOrderTraversal<Function *> RPOT(&F);
657
658
659 std::unique_ptr DT;
660 std::unique_ptr PDT;
661
662
663
664
665 BlockFrequencyInfo *BFI = nullptr;
666 if (HasProfileSummary)
667 BFI = GetBFI(F);
668
669 TargetTransformInfo &TTI = GetTTI(F);
670 OptimizationRemarkEmitter &ORE = (*GetORE)(F);
671 AssumptionCache *AC = LookupAC(F);
673
676
677 unsigned OutlinedFunctionID = 1;
678
679 for (BasicBlock *BB : RPOT) {
680
681 if (ColdBlocks.count(BB))
682 continue;
683
684
685 if (CannotBeOutlinedColdBlocks.count(BB))
686 continue;
687
688 if (!isBasicBlockCold(BB, ColdProbThresh, AnnotatedColdBlocks, BFI))
689 continue;
690
692 dbgs() << "Found a cold block:\n";
694 });
695
696 if (!DT)
697 DT = std::make_unique(F);
698 if (!PDT)
699 PDT = std::make_unique(F);
700
701 auto Regions = OutliningRegion::create(*BB, *DT, *PDT);
702 for (OutliningRegion &Region : Regions) {
704 continue;
705
706 if (Region.isEntireFunctionCold()) {
708 return markFunctionCold(F);
709 }
710
711 do {
714 dbgs() << "Hot/cold splitting attempting to outline these blocks:\n";
715 for (BasicBlock *BB : SubRegion)
717 });
718
719
720 CodeExtractor CE(
721 SubRegion, &*DT, false, nullptr,
722 nullptr, AC, false,
723 false, nullptr,
724 "cold." + std::to_string(OutlinedFunctionID));
725
726 if (CE.isEligible() && isSplittingBeneficial(CE, SubRegion, TTI) &&
727
728
729
730
731
732
735 })) {
737
739 for (auto *Block : SubRegion)
740 dbgs() << " contains cold block:" << Block->getName() << "\n";
741 });
742
744 std::make_pair(SubRegion[0], std::move(CE)));
745 ++OutlinedFunctionID;
746 } else {
747
748 for (auto *Block : SubRegion)
749 if ((DT->dominates(BB, Block) && PDT->dominates(Block, BB)) ||
750 (PDT->dominates(BB, Block) && DT->dominates(Block, BB)))
751
752 CannotBeOutlinedColdBlocks.insert(Block);
753 }
754 } while (.empty());
755
756 ++NumColdRegionsFound;
757 }
758 }
759
760 if (OutliningWorklist.empty())
761 return false;
762
763
764
765 CodeExtractorAnalysisCache CEAC(F);
766 for (auto &BCE : OutliningWorklist) {
768 extractColdRegion(*BCE.first, BCE.second, CEAC, BFI, TTI, ORE);
769 assert(Outlined && "Should be outlined");
770 (void)Outlined;
771 }
772
773 return true;
774}
775
778 bool HasProfileSummary = (M.getProfileSummary( false) != nullptr);
780
781 if (F.isDeclaration())
782 continue;
783
784
785 if (F.hasOptNone())
786 continue;
787
788
789 if (isFunctionCold(F)) {
790 Changed |= markFunctionCold(F);
791 continue;
792 }
793
794 if (!shouldOutlineFrom(F)) {
796 continue;
797 }
798
800 Changed |= outlineColdRegions(F, HasProfileSummary);
801 }
803}
804
808
811 };
812
815 };
816
820 };
821
822 std::unique_ptr ORE;
826 return *ORE;
827 };
828
830
834}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
bbsections Prepares for basic block by splitting functions into clusters of basic blocks
static bool blockEndsInUnreachable(const MachineBasicBlock *MBB)
A no successor, non-return block probably ends in unreachable and is cold.
std::pair< BasicBlock *, unsigned > BlockTy
A pair of (basic block, score).
Definition HotColdSplitting.cpp:456
static cl::opt< int > SplittingThreshold("hotcoldsplit-threshold", cl::init(2), cl::Hidden, cl::desc("Base penalty for splitting cold code (as a " "multiple of TCC_Basic)"))
static cl::opt< std::string > ColdSectionName("hotcoldsplit-cold-section-name", cl::init("__llvm_cold"), cl::Hidden, cl::desc("Name for the section containing cold functions " "extracted by hot-cold splitting."))
static cl::opt< int > ColdBranchProbDenom("hotcoldsplit-cold-probability-denom", cl::init(100), cl::Hidden, cl::desc("Divisor of cold branch probability." "BranchProbability = 1/ColdBranchProbDenom"))
static cl::opt< int > MaxParametersForSplit("hotcoldsplit-max-params", cl::init(4), cl::Hidden, cl::desc("Maximum number of parameters for a split function"))
static InstructionCost getOutliningBenefit(ArrayRef< BasicBlock * > Region, TargetTransformInfo &TTI)
Get the benefit score of outlining Region.
Definition HotColdSplitting.cpp:284
static cl::opt< bool > EnableColdSection("enable-cold-section", cl::init(false), cl::Hidden, cl::desc("Enable placement of extracted cold functions" " into a separate section after hot-cold splitting."))
static cl::opt< bool > EnableStaticAnalysis("hot-cold-static-analysis", cl::init(true), cl::Hidden)
static int getOutliningPenalty(ArrayRef< BasicBlock * > Region, unsigned NumInputs, unsigned NumOutputs)
Get the penalty score for outlining Region.
Definition HotColdSplitting.cpp:299
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.
This header defines various interfaces for pass management in LLVM.
FunctionAnalysisManager FAM
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
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.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
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.
bool hasAddressTaken() const
Returns true if there are any uses of this basic block other than direct branches,...
bool isEHPad() const
Return true if this basic block is an exception handling block.
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...
Conditional or Unconditional Branch instruction.
BasicBlock * getSuccessor(unsigned i) const
static LLVM_ABI BranchProbability getBranchProbability(uint64_t Numerator, uint64_t Denominator)
BranchProbability getCompl() const
void setCallingConv(CallingConv::ID CC)
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
LLVM_ABI bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
StringRef getSection() const
Get the custom section of this global if it has one.
bool hasSection() const
Check if this global has a custom object file section.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
Definition HotColdSplitting.cpp:806
bool run(Module &M)
Definition HotColdSplitting.cpp:776
A Module instance is used to store all the information related to an LLVM module.
PostDominatorTree Class - Concrete subclass of DominatorTree that is used to compute the post-dominat...
LLVM_ABI bool dominates(const Instruction *I1, const Instruction *I2) const
Return true if I1 dominates I2.
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.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
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.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
reference emplace_back(ArgTypes &&... Args)
iterator erase(const_iterator CI)
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.
This pass provides access to the codegen interfaces that are needed for IR-level transformations.
@ TCK_CodeSize
Instruction code size.
LLVM_ABI BranchProbability getPredictableBranchThreshold() const
If a branch or a select condition is skewed in one direction by more than this factor,...
@ TCC_Basic
The cost of a typical 'add' instruction.
LLVM_ABI bool useColdCCForColdCall(Function &F) const
Return true if the input function which is cold at all call sites, should use coldcc calling conventi...
LLVM_ABI void dump() const
Support for debugging, callable in GDB: V->dump()
@ Cold
Attempts to make code in the caller as efficient as possible under the assumption that the call is no...
@ CE
Windows NT (Windows on ARM)
initializer< Ty > init(const Ty &Val)
@ User
could "use" a pointer
DiagnosticInfoOptimizationBase::Argument NV
This is an optimization pass for GlobalISel generic memory operations.
bool succ_empty(const Instruction *I)
decltype(auto) dyn_cast(const From &Val)
dyn_cast - Return the argument parameter cast to the specified type.
auto successors(const MachineBasicBlock *BB)
df_iterator< T > df_begin(const T &G)
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
SmallVector< BasicBlock *, 0 > BlockSequence
A sequence of basic blocks.
bool isScopedEHPersonality(EHPersonality Pers)
Returns true if this personality uses scope-style EH IR instructions: catchswitch,...
auto dyn_cast_or_null(const Y &Val)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
LLVM_ABI EHPersonality classifyEHPersonality(const Value *Pers)
See if the given exception handling personality function is one that we understand.
idf_iterator< T > idf_end(const T &G)
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...
auto remove_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::remove_if which take ranges instead of having to pass begin/end explicitly.
idf_iterator< T > idf_begin(const T &G)
LLVM_ABI bool extractBranchWeights(const MDNode *ProfileData, SmallVectorImpl< uint32_t > &Weights)
Extract branch weights from MD_prof metadata.
decltype(auto) cast(const From &Val)
cast - Return the argument parameter cast to the specified type.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
bool pred_empty(const BasicBlock *BB)
df_iterator< T > df_end(const T &G)
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.