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

1

2

3

4

5

6

7

8

29#include

30#include

31

32#define DEBUG_TYPE "cgscc"

33

34using namespace llvm;

35

36

37

38namespace llvm {

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

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

42 "pass is reached"));

43

45

46

55

56

57

58template <>

64

65

68

70

71

72

74

75

78

80

81

83 continue;

84

86

87

90

91 auto *ResultFAMCP =

93 ResultFAMCP->updateFAM(FAM);

94 }

95

96

97

98 PA.intersect(PassPA);

99

100

101

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

105 break;

106 }

107

108

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

110

111

112

114

116 }

117

118

119

120

121

123

124

125

126

127

129

130 return PA;

131}

132

135

138

139

141

142

145

146

147

150

151

152

154

156 InlinedInternalEdges;

157

159

161 InvalidSCCSet,

162 nullptr,

164 InlinedInternalEdges,

165 DeadFunctions,

166 {}};

167

168

169

171

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

178

179

180

181

182

183

184

185

186

187

188

189 RCWorklist.insert(&RC);

190

191 do {

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

195

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

197 << "\n");

198

199

200

201

202

204

205

206

209

210 do {

212

213

214

215

216 if (InvalidSCCSet.count(C)) {

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

218 continue;

219 }

220 if (LastUpdatedC == C) {

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

222 continue;

223 }

224

225

226

227

228

229

230

231

232

233

234

235

236

237

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

257

258 do {

259

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

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

262

265

266

267

268

270 continue;

271

273

274

276

278

279

282 }

283

284

285

287

288

289 PA.intersect(PassPA);

290

291

292

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

296 break;

297 }

298

299

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

301

302

303

304

305

306

307

309

311

312

313

314

315

316

317

318

319

320

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

324 "current SCC: "

326

327

328

329

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

332

333

334

335

336 InlinedInternalEdges.clear();

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

338 }

339

341 for (Function *DeadF : DeadFunctions)

342 DeadF->eraseFromParent();

343

344#if defined(EXPENSIVE_CHECKS)

345

347#endif

348

349

350

355 return PA;

356}

357

365

366

367

369

370

371

372 struct CallCount {

373 int Direct;

374 int Indirect;

375 };

376

377

378

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

382

384 CallCount CountLocal = {0, 0};

386 CallCount &Count =

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

388 .first->second;

390 if (auto *CB = dyn_cast(&I)) {

391 if (CB->getCalledFunction()) {

392 ++Count.Direct;

393 } else {

394 ++Count.Indirect;

396 }

397 }

398 }

399

400 return CallCounts;

401 };

402

404

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

406

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

409 continue;

410

412

414

415

416

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

420 break;

421 }

422

423

424

426

428

429

430

432 break;

433

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

435

436

438 if (P.second) {

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

440 if (CB->getCalledFunction()) {

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

442 return true;

443 }

444 }

445 }

446 return false;

447 });

448

449

450

451

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

454

455

456

457

458

459

460 if (!Devirt)

461

462

463 for (auto &Pair : NewCallCounts) {

464 auto &CallCountNew = Pair.second;

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

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

467 const auto &CallCountOld = CountIt->second;

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

469 CallCountOld.Direct < CallCountNew.Direct) {

470 Devirt = true;

471 break;

472 }

473 }

474 }

475

476 if (!Devirt) {

477 break;

478 }

479

480

481 if (Iteration >= MaxIterations) {

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

486 "number of repetitions ("

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

488 break;

489 }

490

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

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

494

495

496 CallCounts = std::move(NewCallCounts);

497 }

498

499

500

501

502 return PA;

503}

504

509

512

516

517

518

519

521

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

523

526

527

528

530 continue;

531

533

535 continue;

536

539 continue;

540

542

543

544

545

547

549

550

551

553

554

555

556

560 AM, UR, FAM);

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

563 }

564 }

565

566

567

568

569

572

573

575

576 return PA;

577}

578

579bool CGSCCAnalysisManagerModuleProxy::Result::invalidate(

582

584 return false;

585

586

587

588

589

590

591

592

593

598 InnerAM->clear();

599

600

601

602

603 return true;

604 }

605

606

607

608 bool AreSCCAnalysesPreserved =

610

611

612 G->buildRefSCCs();

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

614 for (auto &C : RC) {

615 std::optional InnerPA;

616

617

618

619

620 if (auto *OuterProxy =

622 for (const auto &OuterInvalidationPair :

623 OuterProxy->getOuterInvalidations()) {

624 AnalysisKey *OuterAnalysisID = OuterInvalidationPair.first;

625 const auto &InnerAnalysisIDs = OuterInvalidationPair.second;

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

627 if (!InnerPA)

628 InnerPA = PA;

629 for (AnalysisKey *InnerAnalysisID : InnerAnalysisIDs)

630 InnerPA->abandon(InnerAnalysisID);

631 }

632 }

633

634

635

636 if (InnerPA) {

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

638 continue;

639 }

640

641

642

643 if (!AreSCCAnalysesPreserved)

644 InnerAM->invalidate(C, PA);

645 }

646

647

648 return false;

649}

650

651template <>

654

655

656

657

659

661}

662

663AnalysisKey FunctionAnalysisManagerCGSCCProxy::Key;

664

669

670

671

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

674 bool ProxyExists =

676 assert(ProxyExists &&

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

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

679 (void)ProxyExists;

680

681

682

683

685}

686

690

692 return false;

693

694

695

696

697

698

699

700

701

706

707 return false;

708 }

709

710

711 bool AreFunctionAnalysesPreserved =

713

714

715

718 std::optional FunctionPA;

719

720

721

722

723 if (auto *OuterProxy =

725 for (const auto &OuterInvalidationPair :

726 OuterProxy->getOuterInvalidations()) {

727 AnalysisKey *OuterAnalysisID = OuterInvalidationPair.first;

728 const auto &InnerAnalysisIDs = OuterInvalidationPair.second;

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

730 if (!FunctionPA)

731 FunctionPA = PA;

732 for (AnalysisKey *InnerAnalysisID : InnerAnalysisIDs)

733 FunctionPA->abandon(InnerAnalysisID);

734 }

735 }

736

737

738

739 if (FunctionPA) {

741 continue;

742 }

743

744

745

746 if (!AreFunctionAnalysesPreserved)

748 }

749

750

751 return false;

752}

753

754}

755

756

757

758

759

760

761

762

763

764

765

766

767

768

774

775

776

779

780 auto *OuterProxy =

782 if (!OuterProxy)

783

784 continue;

785

786

787

789 for (const auto &OuterInvalidationPair :

790 OuterProxy->getOuterInvalidations()) {

791 const auto &InnerAnalysisIDs = OuterInvalidationPair.second;

792 for (AnalysisKey *InnerAnalysisID : InnerAnalysisIDs)

793 PA.abandon(InnerAnalysisID);

794 }

795

796

798 }

799}

800

801

802

803

804

805

806

807

808

809

810

811template

817

818 if (NewSCCRange.empty())

819 return C;

820

821

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

824 << "\n");

825

826 SCC *OldC = C;

827

828

829

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

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

832 C = &*NewSCCRange.begin();

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

834

835

836

838 if (auto *FAMProxy =

840 FAM = &FAMProxy->getManager();

841

842

843

844

845

846

847

848

849 auto PA = PreservedAnalyses::allInSet<AllAnalysesOn>();

852

853

856

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

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

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

862

863

866

867

868

870 }

871 return C;

872}

873

882

884 SCC *C = &InitialC;

885 RefSCC *RC = &InitialRC;

887

888

889

897

898

899

900

902 if (auto *CB = dyn_cast(&I)) {

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

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

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

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

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

910 "No function transformations should introduce *new* "

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

912 "promoted existing ref edges!");

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

914 (void)Inserted;

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

916 if (!E)

917 NewCallEdges.insert(CalleeN);

918 else if (!E->isCall())

919 PromotedRefTargets.insert(CalleeN);

920 }

921 } else {

922

923

927 else if (!Entry->second)

929 }

930 }

931 }

932

933

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

936 if (auto *OpC = dyn_cast(Op))

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

939

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

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

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

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

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

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

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

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

950 (void)Inserted;

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

952 if (!E)

953 NewRefEdges.insert(RefereeN);

954 else if (E->isCall())

955 DemotedCallTargets.insert(RefereeN);

956 };

958

959

960 for (Node *RefTarget : NewRefEdges) {

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

962 RefSCC &TargetRC = TargetC.getOuterRefSCC();

963 (void)TargetRC;

964

965#ifdef EXPENSIVE_CHECKS

966 assert((RC == &TargetRC ||

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

968#endif

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

970 }

971

972

973 for (Node *CallTarget : NewCallEdges) {

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

975 RefSCC &TargetRC = TargetC.getOuterRefSCC();

976 (void)TargetRC;

977

978#ifdef EXPENSIVE_CHECKS

979 assert((RC == &TargetRC ||

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

981#endif

982

983

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

985 }

986

987

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

989

990

991 if (!Visited.count(LibFn))

992 VisitRef(*LibFn);

993

994

995

996

998 for (Edge &E : *N) {

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

1000 continue;

1001

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

1003 RefSCC &TargetRC = TargetC.getOuterRefSCC();

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

1005 if (C != &TargetC) {

1006

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

1008 } else {

1009

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

1012 }

1013 }

1014

1015

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

1017 }

1018

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

1021 RefSCC &TargetRC = TargetC.getOuterRefSCC();

1022

1023

1024

1025 if (&TargetRC == RC)

1026 return false;

1027

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

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

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

1031 return true;

1032 });

1033

1034

1035

1036

1037 for (Node *RefTarget : DemotedCallTargets) {

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

1039 RefSCC &TargetRC = TargetC.getOuterRefSCC();

1040

1041

1042

1043 if (&TargetRC != RC) {

1044#ifdef EXPENSIVE_CHECKS

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

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

1047#endif

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

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

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

1051 continue;

1052 }

1053

1054

1055

1056 if (C != &TargetC) {

1057

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

1059 continue;

1060 }

1061

1062

1064 C, AM, UR);

1065 }

1066

1067

1068

1069 for (Node *E : NewCallEdges)

1070 PromotedRefTargets.insert(E);

1071

1072

1073 for (Node *CallTarget : PromotedRefTargets) {

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

1075 RefSCC &TargetRC = TargetC.getOuterRefSCC();

1076

1077

1078

1079 if (&TargetRC != RC) {

1080#ifdef EXPENSIVE_CHECKS

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

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

1083#endif

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

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

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

1087 continue;

1088 }

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

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

1091

1092

1093

1094

1095

1096 bool HasFunctionAnalysisProxy = false;

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

1098 bool FormedCycle = RC->switchInternalEdgeToCall(

1100 for (SCC *MergedC : MergedSCCs) {

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

1102

1103 HasFunctionAnalysisProxy |=

1105 *MergedC) != nullptr;

1106

1107

1109

1110

1111

1112

1113 auto PA = PreservedAnalyses::allInSet<AllAnalysesOn>();

1116 }

1117 });

1118

1119

1120

1121 if (FormedCycle) {

1122 C = &TargetC;

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

1124

1125

1126

1127

1128 if (HasFunctionAnalysisProxy)

1130

1131

1132

1133

1134 auto PA = PreservedAnalyses::allInSet<AllAnalysesOn>();

1137 }

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

1139

1140

1141

1142

1143

1144

1145

1146

1147 if (InitialSCCIndex < NewSCCIndex) {

1148

1149

1150

1151

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

1154 << "\n");

1155

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

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

1160 << MovedC << "\n");

1161 }

1162 }

1163 }

1164

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

1167

1168

1169

1170 if (C != &InitialC)

1172

1173 return *C;

1174}

1175

1181 true);

1182}

1188 false);

1189}

Expand Atomic instructions

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

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

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

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

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

Function const char * Passes

FunctionAnalysisManager FAM

Provides implementations for PassManager and AnalysisManager template methods.

This file provides a priority worklist.

assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())

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

This file defines the SmallPtrSet class.

This file defines the SmallVector class.

This templated class represents "all analyses that operate over " (e....

API to communicate dependencies between analyses during invalidation.

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

Trigger the invalidation of some other analysis pass if not already handled and return whether it was...

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

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

Runs the function pass across every function in the module.

This class represents an Operation in the Expression.

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

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.

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

A proxy from a FunctionAnalysisManager to an SCC.

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

Computes the FunctionAnalysisManager and stores it in the result proxy.

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(IRUnitT &IR, AnalysisManager< IRUnitT, ExtraArgTs... > &AM, ExtraArgTs...)

Run the analysis pass and create our proxy result object.

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.

static 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...

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.

PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)

Runs the CGSCC pass across every SCC in the module.

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.

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.

void intersect(const PreservedAnalyses &Arg)

Intersect this set with another in place.

void preserveSet()

Mark an analysis set as preserved.

PreservedAnalysisChecker getChecker() const

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

void abandon()

Mark an analysis as abandoned.

void preserve()

Mark an analysis as preserved.

bool empty() const

Determine if the PriorityWorklist is empty or not.

bool insert(const T &X)

Insert a new element into the PriorityWorklist.

bool insert(const value_type &X)

Insert a new element into the SetVector.

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.

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.

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.

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

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)

raw_ostream & dbgs()

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

void report_fatal_error(Error Err, bool gen_crash_diag=true)

Report a serious error, calling any installed error handler.

AnalysisManager< LazyCallGraph::SCC, LazyCallGraph & > CGSCCAnalysisManager

The CGSCC analysis manager.

void erase_if(Container &C, UnaryPredicate P)

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

AnalysisManager< Module > ModuleAnalysisManager

Convenience typedef for the Module 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"))

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.