LLVM: lib/Analysis/CGSCCPassManager.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

31#include

32#include

33

34#define DEBUG_TYPE "cgscc"

35

36using namespace llvm;

37

38STATISTIC(LargestCGSCC, "Number of functions in the largest SCC");

39

40

41

42namespace llvm {

44 "abort-on-max-devirt-iterations-reached",

45 cl::desc("Abort when the max iterations for devirtualization CGSCC repeat "

46 "pass is reached"));

47

49

50

62

63

64

65template <>

71

72

75

77

78

79

81

82

85

87

88

90 continue;

91

92 LargestCGSCC.updateMax(C->size());

93

95

96

99

100 auto *ResultFAMCP =

102 ResultFAMCP->updateFAM(FAM);

103 }

104

105

106

107 PA.intersect(PassPA);

108

109

110

113 LLVM_DEBUG(dbgs() << "Skipping invalidated root or island SCC!\n");

114 break;

115 }

116

117

118 assert(C->begin() != C->end() && "Cannot have an empty SCC!");

119

120

121

123

125 }

126

127

128

129

130

132

133

134

135

136

138

139 return PA;

140}

141

144

146 AM.getResult(M).getManager();

147

148

150

151

154

155

156

159

160

161

163

165 InlinedInternalEdges;

166

168

170 InvalidSCCSet,

171 nullptr,

173 InlinedInternalEdges,

174 DeadFunctions,

175 {}};

176

177

178

180

186 "Should always start with an empty RefSCC worklist");

187

188

189

190

191

192

193

194

195

196

197

198 RCWorklist.insert(&RC);

199

200 do {

203 "Should always start with an empty SCC worklist");

204

205 LLVM_DEBUG(dbgs() << "Running an SCC pass across the RefSCC: " << *RC

206 << "\n");

207

208

209

210

211

213

214

215

218

219 do {

221

222

223

224

225 if (InvalidSCCSet.count(C)) {

226 LLVM_DEBUG(dbgs() << "Skipping an invalid SCC...\n");

227 continue;

228 }

229 if (LastUpdatedC == C) {

230 LLVM_DEBUG(dbgs() << "Skipping redundant run on SCC: " << *C << "\n");

231 continue;

232 }

233

234

235

236

237

238

239

240

241

242

243

244

245

246

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

266

267 do {

268

269 assert(!InvalidSCCSet.count(C) && "Processing an invalid SCC!");

270 assert(C->begin() != C->end() && "Cannot have an empty SCC!");

271

274

275

276

277

279 continue;

280

282

283

285

287

288

291 }

292

293

294

296

297

298 PA.intersect(PassPA);

299

300

301

304 LLVM_DEBUG(dbgs() << "Skipping invalidated root or island SCC!\n");

305 break;

306 }

307

308

309 assert(C->begin() != C->end() && "Cannot have an empty SCC!");

310

311

312

313

314

315

316

317 CGAM.invalidate(*C, PassPA);

318

320

321

322

323

324

325

326

327

328

329

332 << "Re-running SCC passes after a refinement of the "

333 "current SCC: "

335

336

337

338

340 } while (!CWorklist.empty());

341

342

343

344

345 InlinedInternalEdges.clear();

346 } while (!RCWorklist.empty());

347 }

348

350 for (Function *DeadF : DeadFunctions)

351 DeadF->eraseFromParent();

352

353#if defined(EXPENSIVE_CHECKS)

354

356#endif

357

358

359

362 PA.preserve();

364 return PA;

365}

366

374

375

376

378

379

380

381 struct CallCount {

382 int Direct;

383 int Indirect;

384 };

385

386

387

390 assert(CallHandles.empty() && "Must start with a clear set of handles.");

391

393 CallCount CountLocal = {0, 0};

395 CallCount &Count =

396 CallCounts.insert(std::make_pair(&N.getFunction(), CountLocal))

397 .first->second;

400 if (CB->getCalledFunction()) {

402 } else {

403 ++Count.Indirect;

405 }

406 }

407 }

408

409 return CallCounts;

410 };

411

413

414 auto CallCounts = ScanSCC(*C, UR.IndirectVHs);

415

416 for (int Iteration = 0;; ++Iteration) {

418 continue;

419

421

423

424

425

428 LLVM_DEBUG(dbgs() << "Skipping invalidated root or island SCC!\n");

429 break;

430 }

431

432

433

435

437

438

439

441 break;

442

443 assert(C->begin() != C->end() && "Cannot have an empty SCC!");

444

445

447 if (P.second) {

448 if (CallBase *CB = dyn_cast(P.second)) {

449 if (CB->getCalledFunction()) {

450 LLVM_DEBUG(dbgs() << "Found devirtualized call: " << *CB << "\n");

451 return true;

452 }

453 }

454 }

455 return false;

456 });

457

458

459

460

462 auto NewCallCounts = ScanSCC(*C, UR.IndirectVHs);

463

464

465

466

467

468

469 if (!Devirt)

470

471

472 for (auto &Pair : NewCallCounts) {

473 auto &CallCountNew = Pair.second;

474 auto CountIt = CallCounts.find(Pair.first);

475 if (CountIt != CallCounts.end()) {

476 const auto &CallCountOld = CountIt->second;

477 if (CallCountOld.Indirect > CallCountNew.Indirect &&

478 CallCountOld.Direct < CallCountNew.Direct) {

479 Devirt = true;

480 break;

481 }

482 }

483 }

484

485 if (!Devirt) {

486 break;

487 }

488

489

490 if (Iteration >= MaxIterations) {

494 dbgs() << "Found another devirtualization after hitting the max "

495 "number of repetitions ("

496 << MaxIterations << ") on SCC: " << *C << "\n");

497 break;

498 }

499

501 dbgs() << "Repeating an SCC pass after finding a devirtualization in: "

502 << *C << "\n");

503

504

505 CallCounts = std::move(NewCallCounts);

506 }

507

508

509

510

511 return PA;

512}

513

518

521

523

524

525

526

528

529 LLVM_DEBUG(dbgs() << "Running function passes across an SCC: " << C << "\n");

530

533

534

535

537 continue;

538

540

542 continue;

543

546 continue;

547

549

550

551

552

554

556

557

558

560

561

562

563

567 AM, UR, FAM);

569 "Current SCC not updated to the SCC containing the current node!");

570 }

571 }

572

573

574

575

576

579

580

582

583 return PA;

584}

585

586bool CGSCCAnalysisManagerModuleProxy::Result::invalidate(

588 ModuleAnalysisManager::Invalidator &Inv) {

589

591 return false;

592

593

594

595

596

597

598

599

600

601 auto PAC = PA.getChecker();

605 InnerAM->clear();

606

607

608

609

610 return true;

611 }

612

613

614

615 bool AreSCCAnalysesPreserved =

617

618

619 G->buildRefSCCs();

620 for (auto &RC : G->postorder_ref_sccs())

621 for (auto &C : RC) {

622 std::optional InnerPA;

623

624

625

626

627 if (auto *OuterProxy =

629 for (const auto &OuterInvalidationPair :

630 OuterProxy->getOuterInvalidations()) {

631 AnalysisKey *OuterAnalysisID = OuterInvalidationPair.first;

632 const auto &InnerAnalysisIDs = OuterInvalidationPair.second;

633 if (Inv.invalidate(OuterAnalysisID, M, PA)) {

634 if (!InnerPA)

635 InnerPA = PA;

636 for (AnalysisKey *InnerAnalysisID : InnerAnalysisIDs)

637 InnerPA->abandon(InnerAnalysisID);

638 }

639 }

640

641

642

643 if (InnerPA) {

644 InnerAM->invalidate(C, *InnerPA);

645 continue;

646 }

647

648

649

650 if (!AreSCCAnalysesPreserved)

651 InnerAM->invalidate(C, PA);

652 }

653

654

655 return false;

656}

657

658template <>

659CGSCCAnalysisManagerModuleProxy::Result

661

662

663

664

666

668}

669

670AnalysisKey FunctionAnalysisManagerCGSCCProxy::Key;

671

676

677

678

680 Module &M = *C.begin()->getFunction().getParent();

681 bool ProxyExists =

683 assert(ProxyExists &&

684 "The CGSCC pass manager requires that the FAM module proxy is run "

685 "on the module prior to entering the CGSCC walk");

686 (void)ProxyExists;

687

688

689

690

692}

693

696 CGSCCAnalysisManager::Invalidator &Inv) {

697

699 return false;

700

701

702

703

704

705

706

707

708

712 FAM->invalidate(N.getFunction(), PA);

713

714 return false;

715 }

716

717

718 bool AreFunctionAnalysesPreserved =

720

721

722

725 std::optional FunctionPA;

726

727

728

729

730 if (auto *OuterProxy =

732 for (const auto &OuterInvalidationPair :

733 OuterProxy->getOuterInvalidations()) {

734 AnalysisKey *OuterAnalysisID = OuterInvalidationPair.first;

735 const auto &InnerAnalysisIDs = OuterInvalidationPair.second;

736 if (Inv.invalidate(OuterAnalysisID, C, PA)) {

737 if (!FunctionPA)

738 FunctionPA = PA;

739 for (AnalysisKey *InnerAnalysisID : InnerAnalysisIDs)

740 FunctionPA->abandon(InnerAnalysisID);

741 }

742 }

743

744

745

746 if (FunctionPA) {

747 FAM->invalidate(F, *FunctionPA);

748 continue;

749 }

750

751

752

753 if (!AreFunctionAnalysesPreserved)

754 FAM->invalidate(F, PA);

755 }

756

757

758 return false;

759}

760

761}

762

763

764

765

766

767

768

769

770

771

772

773

774

775

781

782

783

786

787 auto *OuterProxy =

789 if (!OuterProxy)

790

791 continue;

792

793

794

796 for (const auto &OuterInvalidationPair :

797 OuterProxy->getOuterInvalidations()) {

798 const auto &InnerAnalysisIDs = OuterInvalidationPair.second;

799 for (AnalysisKey *InnerAnalysisID : InnerAnalysisIDs)

800 PA.abandon(InnerAnalysisID);

801 }

802

803

804 FAM.invalidate(F, PA);

805 }

806}

807

808

809

810

811

812

813

814

815

816

817

818template

819static LazyCallGraph::SCC *

824

825 if (NewSCCRange.empty())

826 return C;

827

828

830 LLVM_DEBUG(dbgs() << "Enqueuing the existing SCC in the worklist:" << *C

831 << "\n");

832

833 SCC *OldC = C;

834

835

836

837 assert(C != &*NewSCCRange.begin() &&

838 "Cannot insert new SCCs without changing current SCC!");

839 C = &*NewSCCRange.begin();

840 assert(G.lookupSCC(N) == C && "Failed to update current SCC!");

841

842

843

845 if (auto *FAMProxy =

847 FAM = &FAMProxy->getManager();

848

849

850

851

852

853

854

855

859

860

863

865 assert(C != &NewC && "No need to re-visit the current SCC!");

866 assert(OldC != &NewC && "Already handled the original SCC!");

868 LLVM_DEBUG(dbgs() << "Enqueuing a newly formed SCC:" << NewC << "\n");

869

870

873

874

875

877 }

878 return C;

879}

880

889

891 SCC *C = &InitialC;

892 RefSCC *RC = &InitialRC;

894

895

896

904

905

906

907

910 if (Function *Callee = CB->getCalledFunction()) {

911 if (Visited.insert(Callee).second && !Callee->isDeclaration()) {

912 Node *CalleeN = G.lookup(*Callee);

914 "Visited function should already have an associated node");

915 Edge *E = N->lookup(*CalleeN);

917 "No function transformations should introduce *new* "

918 "call edges! Any new calls should be modeled as "

919 "promoted existing ref edges!");

920 bool Inserted = RetainedEdges.insert(CalleeN).second;

921 (void)Inserted;

922 assert(Inserted && "We should never visit a function twice.");

923 if (E)

924 NewCallEdges.insert(CalleeN);

925 else if (E->isCall())

926 PromotedRefTargets.insert(CalleeN);

927 }

928 } else {

929

930

934 else if (!Entry->second)

936 }

937 }

938 }

939

940

942 for (Value *Op : I.operand_values())

944 if (Visited.insert(OpC).second)

946

947 auto VisitRef = [&](Function &Referee) {

948 Node *RefereeN = G.lookup(Referee);

950 "Visited function should already have an associated node");

951 Edge *E = N->lookup(*RefereeN);

953 "No function transformations should introduce *new* ref "

954 "edges! Any new ref edges would require IPO which "

955 "function passes aren't allowed to do!");

956 bool Inserted = RetainedEdges.insert(RefereeN).second;

957 (void)Inserted;

958 assert(Inserted && "We should never visit a function twice.");

959 if (E)

960 NewRefEdges.insert(RefereeN);

961 else if (E->isCall())

962 DemotedCallTargets.insert(RefereeN);

963 };

965

966

967 for (Node *RefTarget : NewRefEdges) {

968 SCC &TargetC = *G.lookupSCC(*RefTarget);

969 RefSCC &TargetRC = TargetC.getOuterRefSCC();

970 (void)TargetRC;

971

972#ifdef EXPENSIVE_CHECKS

973 assert((RC == &TargetRC ||

974 RC->isAncestorOf(TargetRC)) && "New ref edge is not trivial!");

975#endif

976 RC->insertTrivialRefEdge(N, *RefTarget);

977 }

978

979

980 for (Node *CallTarget : NewCallEdges) {

981 SCC &TargetC = *G.lookupSCC(*CallTarget);

982 RefSCC &TargetRC = TargetC.getOuterRefSCC();

983 (void)TargetRC;

984

985#ifdef EXPENSIVE_CHECKS

986 assert((RC == &TargetRC ||

987 RC->isAncestorOf(TargetRC)) && "New call edge is not trivial!");

988#endif

989

990

991 RC->insertTrivialRefEdge(N, *CallTarget);

992 }

993

994

995 for (auto *LibFn : G.getLibFunctions())

996

997

998 if (!Visited.count(LibFn))

999 VisitRef(*LibFn);

1000

1001

1002

1003

1005 for (Edge &E : *N) {

1006 if (RetainedEdges.count(&E.getNode()))

1007 continue;

1008

1009 SCC &TargetC = *G.lookupSCC(E.getNode());

1010 RefSCC &TargetRC = TargetC.getOuterRefSCC();

1011 if (&TargetRC == RC && E.isCall()) {

1012 if (C != &TargetC) {

1013

1014 RC->switchTrivialInternalEdgeToRef(N, E.getNode());

1015 } else {

1016

1018 G, N, C, AM, UR);

1019 }

1020 }

1021

1022

1023 DeadTargets.push_back(&E.getNode());

1024 }

1025

1027 SCC &TargetC = *G.lookupSCC(*TargetN);

1028 RefSCC &TargetRC = TargetC.getOuterRefSCC();

1029

1030

1031

1032 if (&TargetRC == RC)

1033 return false;

1034

1035 LLVM_DEBUG(dbgs() << "Deleting outgoing edge from '" << N << "' to '"

1036 << *TargetN << "'\n");

1037 RC->removeOutgoingEdge(N, *TargetN);

1038 return true;

1039 });

1040

1041

1042

1043

1044 for (Node *RefTarget : DemotedCallTargets) {

1045 SCC &TargetC = *G.lookupSCC(*RefTarget);

1046 RefSCC &TargetRC = TargetC.getOuterRefSCC();

1047

1048

1049

1050 if (&TargetRC != RC) {

1051#ifdef EXPENSIVE_CHECKS

1052 assert(RC->isAncestorOf(TargetRC) &&

1053 "Cannot potentially form RefSCC cycles here!");

1054#endif

1055 RC->switchOutgoingEdgeToRef(N, *RefTarget);

1056 LLVM_DEBUG(dbgs() << "Switch outgoing call edge to a ref edge from '" << N

1057 << "' to '" << *RefTarget << "'\n");

1058 continue;

1059 }

1060

1061

1062

1063 if (C != &TargetC) {

1064

1065 RC->switchTrivialInternalEdgeToRef(N, *RefTarget);

1066 continue;

1067 }

1068

1069

1071 C, AM, UR);

1072 }

1073

1074

1075

1076 PromotedRefTargets.insert_range(NewCallEdges);

1077

1078

1079 for (Node *CallTarget : PromotedRefTargets) {

1080 SCC &TargetC = *G.lookupSCC(*CallTarget);

1081 RefSCC &TargetRC = TargetC.getOuterRefSCC();

1082

1083

1084

1085 if (&TargetRC != RC) {

1086#ifdef EXPENSIVE_CHECKS

1087 assert(RC->isAncestorOf(TargetRC) &&

1088 "Cannot potentially form RefSCC cycles here!");

1089#endif

1090 RC->switchOutgoingEdgeToCall(N, *CallTarget);

1091 LLVM_DEBUG(dbgs() << "Switch outgoing ref edge to a call edge from '" << N

1092 << "' to '" << *CallTarget << "'\n");

1093 continue;

1094 }

1095 LLVM_DEBUG(dbgs() << "Switch an internal ref edge to a call edge from '"

1096 << N << "' to '" << *CallTarget << "'\n");

1097

1098

1099

1100

1101

1102 bool HasFunctionAnalysisProxy = false;

1103 auto InitialSCCIndex = RC->find(*C) - RC->begin();

1104 bool FormedCycle = RC->switchInternalEdgeToCall(

1106 for (SCC *MergedC : MergedSCCs) {

1107 assert(MergedC != &TargetC && "Cannot merge away the target SCC!");

1108

1109 HasFunctionAnalysisProxy |=

1111 *MergedC) != nullptr;

1112

1113

1115

1116

1117

1118

1122 }

1123 });

1124

1125

1126

1127 if (FormedCycle) {

1128 C = &TargetC;

1129 assert(G.lookupSCC(N) == C && "Failed to update current SCC!");

1130

1131

1132

1133

1134 if (HasFunctionAnalysisProxy)

1136

1137

1138

1139

1143 }

1144 auto NewSCCIndex = RC->find(*C) - RC->begin();

1145

1146

1147

1148

1149

1150

1151

1152

1153 if (InitialSCCIndex < NewSCCIndex) {

1154

1155

1156

1157

1159 LLVM_DEBUG(dbgs() << "Enqueuing the existing SCC in the worklist: " << *C

1160 << "\n");

1161

1163 RC->begin() + NewSCCIndex))) {

1165 LLVM_DEBUG(dbgs() << "Enqueuing a newly earlier in post-order SCC: "

1166 << MovedC << "\n");

1167 }

1168 }

1169 }

1170

1172 assert(&C->getOuterRefSCC() == RC && "Current SCC not in current RefSCC!");

1173

1174

1175

1176 if (C != &InitialC)

1178

1179 return *C;

1180}

1181

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

Expand Atomic instructions

static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")

static LazyCallGraph::SCC & updateCGAndAnalysisManagerForPass(LazyCallGraph &G, LazyCallGraph::SCC &InitialC, LazyCallGraph::Node &N, CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR, FunctionAnalysisManager &FAM, bool FunctionPass)

Definition CGSCCPassManager.cpp:881

static LazyCallGraph::SCC * incorporateNewSCCRange(const SCCRangeT &NewSCCRange, LazyCallGraph &G, LazyCallGraph::Node &N, LazyCallGraph::SCC *C, CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR)

Helper function to update both the CGSCCAnalysisManager AM and the CGSCCPassManager's CGSCCUpdateResu...

Definition CGSCCPassManager.cpp:820

static void updateNewSCCFunctionAnalyses(LazyCallGraph::SCC &C, LazyCallGraph &G, CGSCCAnalysisManager &AM, FunctionAnalysisManager &FAM)

When a new SCC is created for the graph we first update the FunctionAnalysisManager in the Proxy's re...

Definition CGSCCPassManager.cpp:776

This header provides classes for managing passes over SCCs of the call graph.

#define LLVM_EXPORT_TEMPLATE

This header defines various interfaces for pass management in LLVM.

Implements a lazy call graph analysis and related passes for the new pass manager.

CGSCCAnalysisManager CGAM

FunctionAnalysisManager FAM

Provides implementations for PassManager and AnalysisManager template methods.

This file provides a priority worklist.

This file implements a set that has insertion order iteration characteristics.

This file defines the SmallPtrSet class.

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 templated class represents "all analyses that operate over " (e....

A container for analyses that lazily runs them and caches their results.

void invalidate(IRUnitT &IR, const PreservedAnalyses &PA)

Invalidate cached analyses for an IR unit.

PassT::Result * getCachedResult(IRUnitT &IR) const

Get the cached result of an analysis pass for a given IR unit.

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),...

We need a specialized result for the CGSCCAnalysisManagerModuleProxy so it can have access to the cal...

LLVM_ABI PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &CG, CGSCCUpdateResult &UR)

Runs the function pass across every function in the module.

Definition CGSCCPassManager.cpp:514

std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)

LLVM_ABI PreservedAnalyses run(LazyCallGraph::SCC &InitialC, CGSCCAnalysisManager &AM, LazyCallGraph &CG, CGSCCUpdateResult &UR)

Runs the wrapped pass up to MaxIterations on the SCC, iterating whenever an indirect call is refined.

Definition CGSCCPassManager.cpp:367

LLVM_ABI bool invalidate(LazyCallGraph::SCC &C, const PreservedAnalyses &PA, CGSCCAnalysisManager::Invalidator &Inv)

Definition CGSCCPassManager.cpp:694

A proxy from a FunctionAnalysisManager to an SCC.

LLVM_ABI Result run(LazyCallGraph::SCC &C, CGSCCAnalysisManager &AM, LazyCallGraph &)

Computes the FunctionAnalysisManager and stores it in the result proxy.

Definition CGSCCPassManager.cpp:673

FunctionPass class - This class is used to implement most global optimizations.

An analysis over an "outer" IR unit that provides access to an analysis manager over an "inner" IR un...

Result run(Module &IR, AnalysisManager< Module, ExtraArgTs... > &AM, ExtraArgTs...)

An analysis pass which computes the call graph for a module.

A class used to represent edges in the call graph.

A node in the call graph.

A RefSCC of the call graph.

An SCC of the call graph.

RefSCC & getOuterRefSCC() const

A lazily constructed view of the call graph of a module.

LLVM_ABI void buildRefSCCs()

static LLVM_ABI void visitReferences(SmallVectorImpl< Constant * > &Worklist, SmallPtrSetImpl< Constant * > &Visited, function_ref< void(Function &)> Callback)

Recursively visits the defined functions whose address is reachable from every constant in the Workli...

LLVM_ABI void removeDeadFunctions(ArrayRef< Function * > DeadFs)

Remove dead functions from the call graph.

SCC * lookupSCC(Node &N) const

Lookup a function's SCC in the graph.

iterator_range< postorder_ref_scc_iterator > postorder_ref_sccs()

void verify()

Verify that every RefSCC is valid.

LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)

Runs the CGSCC pass across every SCC in the module.

Definition CGSCCPassManager.cpp:143

A Module instance is used to store all the information related to an LLVM module.

An analysis over an "inner" IR unit that provides access to an analysis manager over a "outer" IR uni...

Pseudo-analysis pass that exposes the PassInstrumentation to pass managers.

This class provides instrumentation entry points for the Pass Manager, doing calls to callbacks regis...

void runAfterPassInvalidated(const PassT &Pass, const PreservedAnalyses &PA) const

AfterPassInvalidated instrumentation point - takes Pass instance that has just been executed.

void runAfterPass(const PassT &Pass, const IRUnitT &IR, const PreservedAnalyses &PA) const

AfterPass instrumentation point - takes Pass instance that has just been executed and constant refere...

bool runBeforePass(const PassT &Pass, const IRUnitT &IR) const

BeforePass instrumentation point - takes Pass instance to be executed and constant reference to IR it...

Manages a sequence of passes over a particular unit of IR.

std::vector< std::unique_ptr< PassConceptT > > Passes

PreservedAnalyses run(LazyCallGraph::SCC &IR, CGSCCAnalysisManager &AM, ExtraArgTs... ExtraArgs)

Pass interface - Implemented by all 'passes'.

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.

bool areAllPreserved() const

Test whether all analyses are preserved (and none are abandoned).

static PreservedAnalyses all()

Construct a special preserved set that preserves all passes.

bool allAnalysesInSetPreserved() const

Directly test whether a set of analyses is preserved.

PreservedAnalyses & preserveSet()

Mark an analysis set as preserved.

void intersect(const PreservedAnalyses &Arg)

Intersect this set with another in place.

PreservedAnalyses & preserve()

Mark an analysis as preserved.

PreservedAnalysisChecker getChecker() const

Build a checker for this PreservedAnalyses and the specified analysis type.

static PreservedAnalyses allInSet()

Construct a preserved analyses object with a single preserved set.

bool empty() const

Determine if the PriorityWorklist is empty or not.

bool insert(const T &X)

Insert a new element into the PriorityWorklist.

void insert_range(Range &&R)

bool insert(const value_type &X)

Insert a new element into the SetVector.

static LLVM_ABI AnalysisKey Key

Implements a dense probed hash-table based set with some number of buckets stored inline.

A version of PriorityWorklist that selects small size optimized data structures for the vector and ma...

size_type count(ConstPtrType Ptr) const

count - Return 1 if the specified pointer is in the set, 0 otherwise.

std::pair< iterator, bool > insert(PtrType Ptr)

Inserts Ptr if and only if there is no element in the container equal to Ptr.

SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.

A SetVector that performs no allocations if smaller than a certain size.

void push_back(const T &Elt)

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

LLVM Value Representation.

Value handle that is nullable, but tries to track the Value.

This provides a very simple, boring adaptor for a begin and end iterator into a range type.

@ C

The default llvm calling convention, compatible with C.

This is an optimization pass for GlobalISel generic memory operations.

auto drop_begin(T &&RangeOrContainer, size_t N=1)

Return a range covering RangeOrContainer with the first N elements excluded.

OuterAnalysisManagerProxy< CGSCCAnalysisManager, Function > CGSCCAnalysisManagerFunctionProxy

A proxy from a CGSCCAnalysisManager to a Function.

decltype(auto) dyn_cast(const From &Val)

dyn_cast - Return the argument parameter cast to the specified type.

LLVM_ABI LazyCallGraph::SCC & updateCGAndAnalysisManagerForFunctionPass(LazyCallGraph &G, LazyCallGraph::SCC &C, LazyCallGraph::Node &N, CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR, FunctionAnalysisManager &FAM)

Helper to update the call graph after running a function pass.

Definition CGSCCPassManager.cpp:1182

LLVM_ABI LazyCallGraph::SCC & updateCGAndAnalysisManagerForCGSCCPass(LazyCallGraph &G, LazyCallGraph::SCC &C, LazyCallGraph::Node &N, CGSCCAnalysisManager &AM, CGSCCUpdateResult &UR, FunctionAnalysisManager &FAM)

Helper to update the call graph after running a CGSCC pass.

Definition CGSCCPassManager.cpp:1189

iterator_range< T > make_range(T x, T y)

Convenience function for iterating over sub-ranges.

iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)

Make a range that does early increment to allow mutation of the underlying range without disrupting i...

InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy

Provide the FunctionAnalysisManager to Module proxy.

AnalysisManager< LazyCallGraph::SCC, LazyCallGraph & > CGSCCAnalysisManager

The CGSCC analysis manager.

bool any_of(R &&range, UnaryPredicate P)

Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.

auto reverse(ContainerTy &&C)

LLVM_ABI raw_ostream & dbgs()

dbgs() - This returns a reference to a raw_ostream for debugging messages.

LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)

FunctionAddr VTableAddr Count

OuterAnalysisManagerProxy< ModuleAnalysisManager, LazyCallGraph::SCC, LazyCallGraph & > ModuleAnalysisManagerCGSCCProxy

A proxy from a ModuleAnalysisManager to an SCC.

DWARFExpression::Operation Op

void erase_if(Container &C, UnaryPredicate P)

Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...

iterator_range< pointer_iterator< WrappedIteratorT > > make_pointer_range(RangeT &&Range)

AnalysisManager< Function > FunctionAnalysisManager

Convenience typedef for the Function analysis manager.

static cl::opt< bool > AbortOnMaxDevirtIterationsReached("abort-on-max-devirt-iterations-reached", cl::desc("Abort when the max iterations for devirtualization CGSCC repeat " "pass is reached"))

AnalysisManager< Module > ModuleAnalysisManager

Convenience typedef for the Module analysis manager.

A special type used by analysis passes to provide an address that identifies that particular analysis...

Support structure for SCC passes to communicate updates the call graph back to the CGSCC pass manager...

SmallMapVector< Value *, WeakTrackingVH, 16 > IndirectVHs

Weak VHs to keep track of indirect calls for the purposes of detecting devirtualization.

SmallPriorityWorklist< LazyCallGraph::SCC *, 1 > & CWorklist

Worklist of the SCCs queued for processing.

SmallPtrSetImpl< LazyCallGraph::SCC * > & InvalidatedSCCs

The set of invalidated SCCs which should be skipped if they are found in CWorklist.

LazyCallGraph::SCC * UpdatedC

If non-null, the updated current SCC being processed.

PreservedAnalyses CrossSCCPA

Preserved analyses across SCCs.

A MapVector that performs no allocations if smaller than a certain size.