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

1

2

3

4

5

6

7

8

9

10

11

12

18#include "llvm/Config/llvm-config.h"

27#include

28#include

29#include

30#include

31#include

32#include

33#include

34#include

35#include

36#include

37

38using namespace llvm;

40

41#define DEBUG_TYPE "block-freq"

42

43namespace llvm {

45 "check-bfi-unknown-block-queries",

47 cl::desc("Check if block frequency is queried for an unknown block "

48 "for debugging missed BFI updates"));

49

51 "use-iterative-bfi-inference", cl::Hidden,

52 cl::desc("Apply an iterative post-processing to infer correct BFI counts"));

53

56 cl::desc("Iterative inference: maximum number of update iterations "

57 "per block"));

58

61 cl::desc("Iterative inference: delta convergence precision; smaller values "

62 "typically lead to better results at the cost of worsen runtime"));

63}

64

69}

70

71#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)

73#endif

74

77 if (N < 10)

78 return '0' + N;

79 return 'a' + N - 10;

80}

81

83 for (int Digits = 0; Digits < 16; ++Digits)

84 OS << getHexDigit(Mass >> (60 - Digits * 4) & 0xf);

85 return OS;

86}

87

88namespace {

89

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116struct DitheringDistributer {

119

120 DitheringDistributer(Distribution &Dist, const BlockMass &Mass);

121

123};

124

125}

126

127DitheringDistributer::DitheringDistributer(Distribution &Dist,

129 Dist.normalize();

130 RemWeight = Dist.Total;

131 RemMass = Mass;

132}

133

135 assert(Weight && "invalid weight");

136 assert(Weight <= RemWeight);

138

139

140 RemWeight -= Weight;

141 RemMass -= Mass;

142 return Mass;

143}

144

145void Distribution::add(const BlockNode &Node, uint64_t Amount,

146 Weight::DistType Type) {

147 assert(Amount && "invalid weight of 0");

149

150

151 bool IsOverflow = NewTotal < Total;

152 assert(!(DidOverflow && IsOverflow) && "unexpected repeated overflow");

153 DidOverflow |= IsOverflow;

154

155

156 Total = NewTotal;

157

158

159 Weights.push_back(Weight(Type, Node, Amount));

160}

161

163 assert(OtherW.TargetNode.isValid());

164 if (!W.Amount) {

165 W = OtherW;

166 return;

167 }

168 assert(W.Type == OtherW.Type);

169 assert(W.TargetNode == OtherW.TargetNode);

170 assert(OtherW.Amount && "Expected non-zero weight");

171 if (W.Amount > W.Amount + OtherW.Amount)

172

174 else

175 W.Amount += OtherW.Amount;

176}

177

179

180 llvm::sort(Weights, [](const Weight &L, const Weight &R) {

181 return L.TargetNode < R.TargetNode;

182 });

183

184

185 WeightList::iterator O = Weights.begin();

186 for (WeightList::const_iterator I = O, L = O, E = Weights.end(); I != E;

187 ++O, (I = L)) {

188 *O = *I;

189

190

191 for (++L; L != E && I->TargetNode == L->TargetNode; ++L)

193 }

194

195

196 Weights.erase(O, Weights.end());

197}

198

200

202

203 HashTable Combined(NextPowerOf2(2 * Weights.size()));

204 for (const Weight &W : Weights)

206

207

208 if (Weights.size() == Combined.size())

209 return;

210

211

212 Weights.clear();

213 Weights.reserve(Combined.size());

214 for (const auto &I : Combined)

215 Weights.push_back(I.second);

216}

217

219

220 if (Weights.size() > 128) {

222 return;

223 }

224

226}

227

231 if (!Shift)

232 return N;

233 return (N >> Shift) + (UINT64_C(1) & N >> (Shift - 1));

234}

235

236void Distribution::normalize() {

237

238 if (Weights.empty())

239 return;

240

241

242 if (Weights.size() > 1)

244

245

246 if (Weights.size() == 1) {

248 Weights.front().Amount = 1;

249 return;

250 }

251

252

253

254

255

256 int Shift = 0;

257 if (DidOverflow)

258 Shift = 33;

259 else if (Total > UINT32_MAX)

261

262

263 if (!Shift) {

264

265

266 assert(Total == std::accumulate(Weights.begin(), Weights.end(), UINT64_C(0),

268 return Sum + W.Amount;

269 }) &&

270 "Expected total to be correct");

271 return;

272 }

273

274

275

277

278

279 for (Weight &W : Weights) {

280

281

282 assert(W.TargetNode.isValid());

283 W.Amount = std::max(UINT64_C(1), shiftRightAndRound(W.Amount, Shift));

284 assert(W.Amount <= UINT32_MAX);

285

286

287 Total += W.Amount;

288 }

290}

291

293

294

295 std::vector().swap(Freqs);

296 IsIrrLoopHeader.clear();

297 std::vector().swap(Working);

299}

300

301

302

303

305 std::vector SavedFreqs(std::move(BFI.Freqs));

306 SparseBitVector<> SavedIsIrrLoopHeader(std::move(BFI.IsIrrLoopHeader));

307 BFI.clear();

308 BFI.Freqs = std::move(SavedFreqs);

309 BFI.IsIrrLoopHeader = std::move(SavedIsIrrLoopHeader);

310}

311

319

320 auto isLoopHeader = [&OuterLoop](const BlockNode &Node) {

321 return OuterLoop && OuterLoop->isHeader(Node);

322 };

323

324 BlockNode Resolved = Working[Succ.Index].getResolvedNode();

325

326#ifndef NDEBUG

327 auto debugSuccessor = [&](const char *Type) {

328 dbgs() << " =>"

329 << " [" << Type << "] weight = " << Weight;

330 if (!isLoopHeader(Resolved))

332 if (Resolved != Succ)

334 dbgs() << "\n";

335 };

336 (void)debugSuccessor;

337#endif

338

339 if (isLoopHeader(Resolved)) {

340 LLVM_DEBUG(debugSuccessor("backedge"));

342 return true;

343 }

344

345 if (Working[Resolved.Index].getContainingLoop() != OuterLoop) {

346 LLVM_DEBUG(debugSuccessor(" exit "));

348 return true;

349 }

350

351 if (Resolved < Pred) {

352 if (!isLoopHeader(Pred)) {

353

355 "unhandled irreducible control flow");

356

357

358 LLVM_DEBUG(debugSuccessor("abort!!!"));

359 return false;

360 }

361

362

363

364

365 assert(OuterLoop && OuterLoop->isIrreducible() && !isLoopHeader(Resolved) &&

366 "unhandled irreducible control flow");

367 }

368

369 LLVM_DEBUG(debugSuccessor(" local "));

371 return true;

372}

373

376

377 for (const auto &I : Loop.Exits)

378 if (!addToDist(Dist, OuterLoop, Loop.getHeader(), I.first,

379 I.second.getMass()))

380

381 return false;

382

383 return true;

384}

385

386

388

389 LLVM_DEBUG(dbgs() << "compute-loop-scale: " << getLoopName(Loop) << "\n");

390

391

392

393

394

395

396

397

398

399

400 const Scaled64 InfiniteLoopScale(1, 12);

401

402

403

405 for (auto &Mass : Loop.BackedgeMass)

406 TotalBackedgeMass += Mass;

408

409

410

411

414

415 LLVM_DEBUG(dbgs() << " - exit-mass = " << ExitMass << " ("

417 << ")\n"

418 << " - scale = " << Loop.Scale << "\n");

419}

420

421

423 LLVM_DEBUG(dbgs() << "packaging-loop: " << getLoopName(Loop) << "\n");

424

425

427 if (auto *Loop = Working[M.Index].getPackagedLoop())

428 Loop->Exits.clear();

430 }

431 Loop.IsPackaged = true;

432}

433

434#ifndef NDEBUG

436 const DitheringDistributer &D, const BlockNode &T,

438 dbgs() << " => assign " << M << " (" << D.RemMass << ")";

440 dbgs() << " [" << Desc << "]";

441 if (T.isValid())

442 dbgs() << " to " << BFI.getBlockName(T);

443 dbgs() << "\n";

444}

445#endif

446

452

453

454 DitheringDistributer D(Dist, Mass);

455

457

458 BlockMass Taken = D.takeMass(W.Amount);

459 if (W.Type == Weight::Local) {

460 Working[W.TargetNode.Index].getMass() += Taken;

462 continue;

463 }

464

465

466 assert(OuterLoop && "backedge or exit outside of loop");

467

468

469 if (W.Type == Weight::Backedge) {

472 continue;

473 }

474

475

476 assert(W.Type == Weight::Exit);

477 OuterLoop->Exits.push_back(std::make_pair(W.TargetNode, Taken));

479 }

480}

481

483 const Scaled64 &Min, const Scaled64 &Max) {

484

485

486

487

488

489

490

491 const unsigned MaxBits = sizeof(Scaled64::DigitsType) * CHAR_BIT;

492

493

494

495 const unsigned Slack = 10;

496 Scaled64 ScalingFactor = Scaled64(1, MaxBits - Slack) / Max;

497

498

499 LLVM_DEBUG(dbgs() << "float-to-int: min = " << Min << ", max = " << Max

500 << ", factor = " << ScalingFactor << "\n");

501 (void)Min;

502 for (size_t Index = 0; Index < BFI.Freqs.size(); ++Index) {

503 Scaled64 Scaled = BFI.Freqs[Index].Scaled * ScalingFactor;

504 BFI.Freqs[Index].Integer = std::max(UINT64_C(1), Scaled.toInt<uint64_t>());

505 LLVM_DEBUG(dbgs() << " - " << BFI.getBlockName(Index) << ": float = "

506 << BFI.Freqs[Index].Scaled << ", scaled = " << Scaled

507 << ", int = " << BFI.Freqs[Index].Integer << "\n");

508 }

509}

510

511

512

513

514

516 LLVM_DEBUG(dbgs() << "unwrap-loop-package: " << BFI.getLoopName(Loop)

517 << ": mass = " << Loop.Mass << ", scale = " << Loop.Scale

518 << "\n");

519 Loop.Scale *= Loop.Mass.toScaled();

520 Loop.IsPackaged = false;

522

523

524

525

526 for (const BlockNode &N : Loop.Nodes) {

527 const auto &Working = BFI.Working[N.Index];

528 Scaled64 &F = Working.isAPackage() ? Working.getPackagedLoop()->Scale

529 : BFI.Freqs[N.Index].Scaled;

530 Scaled64 New = Loop.Scale * F;

531 LLVM_DEBUG(dbgs() << " - " << BFI.getBlockName(N) << ": " << F << " => "

532 << New << "\n");

533 F = New;

534 }

535}

536

538

539 for (size_t Index = 0; Index < Working.size(); ++Index)

540 Freqs[Index].Scaled = Working[Index].Mass.toScaled();

541

544}

545

547

548

549 auto Min = Scaled64::getLargest();

550 auto Max = Scaled64::getZero();

551 for (size_t Index = 0; Index < Working.size(); ++Index) {

552

553 Min = std::min(Min, Freqs[Index].Scaled);

554 Max = std::max(Max, Freqs[Index].Scaled);

555 }

556

557

559

560

562

563

565}

566

569 if (!Node.isValid()) {

570#ifndef NDEBUG

574 OS << "*** Detected BFI query for unknown block " << getBlockName(Node);

576 }

577#endif

579 }

581}

582

583std::optional<uint64_t>

586 bool AllowSynthetic) const {

587 return getProfileCountFromFreq(F, getBlockFreq(Node), AllowSynthetic);

588}

589

592 auto EntryCount = F.getEntryCount(AllowSynthetic);

593 if (!EntryCount)

594 return std::nullopt;

595

596 APInt BlockCount(128, EntryCount->getCount());

598 APInt EntryFreq(128, getEntryFreq().getFrequency());

599 BlockCount *= BlockFreq;

600

601

602 BlockCount = (BlockCount + EntryFreq.lshr(1)).udiv(EntryFreq);

604}

605

606bool

608 if (!Node.isValid())

609 return false;

610 return IsIrrLoopHeader.test(Node.Index);

611}

612

613Scaled64

615 if (!Node.isValid())

616 return Scaled64::getZero();

617 return Freqs[Node.Index].Scaled;

618}

619

622 assert(Node.isValid() && "Expected valid node");

623 assert(Node.Index < Freqs.size() && "Expected legal index");

624 Freqs[Node.Index].Integer = Freq.getFrequency();

625}

626

627std::string

629 return {};

630}

631

632std::string

635}

636

640 for (auto N : OuterLoop.Nodes)

643}

644

648 if (BFI.Working[Index].isPackaged())

651}

652

654 for (auto &I : Nodes)

656}

657

660 if (OuterLoop && OuterLoop->isHeader(Succ))

661 return;

663 if (L == Lookup.end())

664 return;

665 IrrNode &SuccIrr = *L->second;

666 Irr.Edges.push_back(&SuccIrr);

667 SuccIrr.Edges.push_front(&Irr);

669}

670

671namespace llvm {

672

677

681};

682

683}

684

685

686

687

688

692 const std::vector<const IrreducibleGraph::IrrNode *> &SCC,

693 LoopData::NodeList &Headers, LoopData::NodeList &Others) {

694

696

697

698 for (const auto *I : SCC)

699 InSCC[I] = false;

700

701 for (auto I = InSCC.begin(), E = InSCC.end(); I != E; ++I) {

702 auto &Irr = *I->first;

703 for (const auto *P : make_range(Irr.pred_begin(), Irr.pred_end())) {

705 continue;

706

707

708 I->second = true;

709 Headers.push_back(Irr.Node);

710 LLVM_DEBUG(dbgs() << " => entry = " << BFI.getBlockName(Irr.Node)

711 << "\n");

712 break;

713 }

714 }

715 assert(Headers.size() >= 2 &&

716 "Expected irreducible CFG; -loop-info is likely invalid");

717 if (Headers.size() == InSCC.size()) {

718

720 return;

721 }

722

723

724 for (const auto &I : InSCC) {

725

726 if (I.second)

727 continue;

728

729 auto &Irr = *I.first;

730 for (const auto *P : make_range(Irr.pred_begin(), Irr.pred_end())) {

731

732 if (P->Node < Irr.Node)

733 continue;

734

735

736

738 continue;

739

740

741 Headers.push_back(Irr.Node);

742 LLVM_DEBUG(dbgs() << " => extra = " << BFI.getBlockName(Irr.Node)

743 << "\n");

744 break;

745 }

746 if (Headers.back() == Irr.Node)

747

748 continue;

749

750

751 Others.push_back(Irr.Node);

752 LLVM_DEBUG(dbgs() << " => other = " << BFI.getBlockName(Irr.Node) << "\n");

753 }

756}

757

760 LoopData *OuterLoop, std::list::iterator Insert,

761 const std::vector<const IrreducibleGraph::IrrNode *> &SCC) {

762

764

765 LoopData::NodeList Headers;

766 LoopData::NodeList Others;

768

769 auto Loop = BFI.Loops.emplace(Insert, OuterLoop, Headers.begin(),

770 Headers.end(), Others.begin(), Others.end());

771

772

773 for (const auto &N : Loop->Nodes)

774 if (BFI.Working[N.Index].isLoopHeader())

775 BFI.Working[N.Index].Loop->Parent = &*Loop;

776 else

777 BFI.Working[N.Index].Loop = &*Loop;

778}

779

783 std::list::iterator Insert) {

784 assert((OuterLoop == nullptr) == (Insert == Loops.begin()));

785 auto Prev = OuterLoop ? std::prev(Insert) : Loops.end();

786

788 if (I->size() < 2)

789 continue;

790

791

793 }

794

795 if (OuterLoop)

796 return make_range(std::next(Prev), Insert);

798}

799

800void

805 auto O = OuterLoop.Nodes.begin() + 1;

806 for (auto I = O, E = OuterLoop.Nodes.end(); I != E; ++I)

807 if (!Working[I->Index].isPackaged())

808 *O++ = *I;

810}

811

813 assert(Loop.isIrreducible() && "this only makes sense on irreducible loops");

814

815

816

817

818

819

820

823

826 auto &HeaderNode = Loop.Nodes[H];

827 auto &BackedgeMass = Loop.BackedgeMass[Loop.getHeaderIndex(HeaderNode)];

828 LLVM_DEBUG(dbgs() << " - Add back edge mass for node "

829 << getBlockName(HeaderNode) << ": " << BackedgeMass

830 << "\n");

831 if (BackedgeMass.getMass() > 0)

832 Dist.addLocal(HeaderNode, BackedgeMass.getMass());

833 else

834 LLVM_DEBUG(dbgs() << " Nothing added. Back edge mass is zero\n");

835 }

836

837 DitheringDistributer D(Dist, LoopMass);

838

839 LLVM_DEBUG(dbgs() << " Distribute loop mass " << LoopMass

840 << " to headers using above weights\n");

842 BlockMass Taken = D.takeMass(W.Amount);

843 assert(W.Type == Weight::Local && "all weights should be local");

844 Working[W.TargetNode.Index].getMass() = Taken;

846 }

847}

848

851 DitheringDistributer D(Dist, LoopMass);

853 BlockMass Taken = D.takeMass(W.Amount);

854 assert(W.Type == Weight::Local && "all weights should be local");

855 Working[W.TargetNode.Index].getMass() = Taken;

857 }

858}

This file implements a class to represent arbitrary precision integral constant values and operations...

static void combineWeightsBySorting(WeightList &Weights)

static void cleanup(BlockFrequencyInfoImplBase &BFI)

Clear all memory not needed downstream.

static void combineWeightsByHashing(WeightList &Weights)

static void unwrapLoop(BlockFrequencyInfoImplBase &BFI, LoopData &Loop)

Unwrap a loop package.

static void combineWeight(Weight &W, const Weight &OtherW)

static void debugAssign(const BlockFrequencyInfoImplBase &BFI, const DitheringDistributer &D, const BlockNode &T, const BlockMass &M, const char *Desc)

static void combineWeights(WeightList &Weights)

static char getHexDigit(int N)

static void findIrreducibleHeaders(const BlockFrequencyInfoImplBase &BFI, const IrreducibleGraph &G, const std::vector< const IrreducibleGraph::IrrNode * > &SCC, LoopData::NodeList &Headers, LoopData::NodeList &Others)

Find extra irreducible headers.

static void convertFloatingToInteger(BlockFrequencyInfoImplBase &BFI, const Scaled64 &Min, const Scaled64 &Max)

static void createIrreducibleLoop(BlockFrequencyInfoImplBase &BFI, const IrreducibleGraph &G, LoopData *OuterLoop, std::list< LoopData >::iterator Insert, const std::vector< const IrreducibleGraph::IrrNode * > &SCC)

static uint64_t shiftRightAndRound(uint64_t N, int Shift)

static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")

#define LLVM_DUMP_METHOD

Mark debug helper function definitions like dump() that should not be stripped from debug builds.

This file defines the DenseMap class.

This builds on the llvm/ADT/GraphTraits.h file to find the strongly connected components (SCCs) of a ...

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

This file defines the SmallString class.

Class for arbitrary precision integers.

uint64_t getLimitedValue(uint64_t Limit=UINT64_MAX) const

If this value is smaller than the specified limit, return it, otherwise return the limit value.

APInt lshr(unsigned shiftAmt) const

Logical right-shift function.

Base class for BlockFrequencyInfoImpl.

std::vector< WorkingData > Working

Loop data: see initializeLoops().

bool addLoopSuccessorsToDist(const LoopData *OuterLoop, LoopData &Loop, Distribution &Dist)

Add all edges out of a packaged loop to the distribution.

ScaledNumber< uint64_t > Scaled64

std::string getLoopName(const LoopData &Loop) const

bool isIrrLoopHeader(const BlockNode &Node)

void computeLoopScale(LoopData &Loop)

Compute the loop scale for a loop.

void packageLoop(LoopData &Loop)

Package up a loop.

virtual std::string getBlockName(const BlockNode &Node) const

void finalizeMetrics()

Finalize frequency metrics.

void setBlockFreq(const BlockNode &Node, BlockFrequency Freq)

void updateLoopWithIrreducible(LoopData &OuterLoop)

Update a loop after packaging irreducible SCCs inside of it.

void clear()

Clear all memory.

std::optional< uint64_t > getBlockProfileCount(const Function &F, const BlockNode &Node, bool AllowSynthetic=false) const

BlockFrequency getBlockFreq(const BlockNode &Node) const

void distributeIrrLoopHeaderMass(Distribution &Dist)

iterator_range< std::list< LoopData >::iterator > analyzeIrreducible(const bfi_detail::IrreducibleGraph &G, LoopData *OuterLoop, std::list< LoopData >::iterator Insert)

Analyze irreducible SCCs.

bool addToDist(Distribution &Dist, const LoopData *OuterLoop, const BlockNode &Pred, const BlockNode &Succ, uint64_t Weight)

Add an edge to the distribution.

void unwrapLoops()

Unwrap loops.

std::optional< uint64_t > getProfileCountFromFreq(const Function &F, BlockFrequency Freq, bool AllowSynthetic=false) const

Scaled64 getFloatingBlockFreq(const BlockNode &Node) const

void distributeMass(const BlockNode &Source, LoopData *OuterLoop, Distribution &Dist)

Distribute mass according to a distribution.

void adjustLoopHeaderMass(LoopData &Loop)

Adjust the mass of all headers in an irreducible loop.

uint64_t getFrequency() const

Returns the frequency as a fixpoint number scaled by the entry frequency.

ValueT lookup(const_arg_type_t< KeyT > Val) const

lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...

size_type count(const_arg_type_t< KeyT > Val) const

Return 1 if the specified key is in the map, 0 otherwise.

BlockT * getHeader() const

Represents a single loop in the control flow graph.

Simple representation of a scaled number.

ScaledNumber inverse() const

SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...

iterator erase(const_iterator CI)

void push_back(const T &Elt)

The instances of the Type class are immutable: once they are created, they are never changed.

raw_ostream & print(raw_ostream &OS) const

static BlockMass getEmpty()

static BlockMass getFull()

ScaledNumber< uint64_t > toScaled() const

Convert to scaled number.

A range adaptor for a pair of iterators.

This class implements an extremely fast bulk output stream that can only output to a stream.

A raw_ostream that writes to an SmallVector or SmallString.

std::string getBlockName(const BlockT *BB)

Get the name of a MachineBasicBlock.

initializer< Ty > init(const Ty &Val)

This is an optimization pass for GlobalISel generic memory operations.

void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)

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

Convenience function for iterating over sub-ranges.

scc_iterator< T > scc_begin(const T &G)

Construct the begin iterator for a deduced graph type T.

llvm:🆑:opt< unsigned > IterativeBFIMaxIterationsPerBlock

int countl_zero(T Val)

Count number of 0's from the most significant bit to the least stopping at the first 1.

void sort(IteratorTy Start, IteratorTy End)

llvm:🆑:opt< bool > UseIterativeBFIInference

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.

llvm:🆑:opt< bool > CheckBFIUnknownBlockQueries

llvm:🆑:opt< double > IterativeBFIPrecision

constexpr uint64_t NextPowerOf2(uint64_t A)

Returns the next power of two (in 64-bits) that is strictly greater than A.

Representative of a block.

Distribution of unscaled probability weight.

void addBackedge(const BlockNode &Node, uint64_t Amount)

SmallVector< Weight, 4 > WeightList

WeightList Weights

Individual successor weights.

void addExit(const BlockNode &Node, uint64_t Amount)

void addLocal(const BlockNode &Node, uint64_t Amount)

Stats about a block itself.

bool isHeader(const BlockNode &Node) const

ExitMap Exits

Successor edges (and weights).

bool isIrreducible() const

BlockNode getHeader() const

NodeList Nodes

Header and the members of the loop.

HeaderMassList BackedgeMass

Mass returned to each loop header.

HeaderMassList::difference_type getHeaderIndex(const BlockNode &B)

Unscaled probability weight.

Description of the encoding of one expression Op.

static ChildIteratorType child_begin(NodeRef N)

static ChildIteratorType child_end(NodeRef N)

GraphT::IrrNode::iterator ChildIteratorType

static NodeRef getEntryNode(const GraphT &G)

std::deque< const IrrNode * > Edges

Graph of irreducible control flow.

void addNodesInFunction()

void addEdge(IrrNode &Irr, const BlockNode &Succ, const BFIBase::LoopData *OuterLoop)

std::vector< IrrNode > Nodes

SmallDenseMap< uint32_t, IrrNode *, 4 > Lookup

void addNode(const BlockNode &Node)

void addNodesInLoop(const BFIBase::LoopData &OuterLoop)