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(F.hasOptNone() && "Can't mark this cold");

198 if (F.hasFnAttribute(Attribute::Cold)) {

199 F.addFnAttr(Attribute::Cold);

201 }

202 if (F.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 (Region.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.