LLVM: include/llvm/Analysis/RegionInfoImpl.h Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11#ifndef LLVM_ANALYSIS_REGIONINFOIMPL_H

12#define LLVM_ANALYSIS_REGIONINFOIMPL_H

13

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

25#include

26#include

27#include

28#include

29#include

30#include

31#include <type_traits>

32#include

33

34#define DEBUG_TYPE "region"

35

36namespace llvm {

37class raw_ostream;

38

39

40

41template

43 typename Tr::RegionInfoT *RInfo, DomTreeT *dt,

44 RegionT *Parent)

45 : RegionNodeBase(Parent, Entry, 1), RI(RInfo), DT(dt), exit(Exit) {}

46

47template

49

50

51 BBNodeMap.clear();

52}

53

54template

56 this->entry.setPointer(BB);

57}

58

59template

61 assert(exit && "No exit to replace!");

62 exit = BB;

63}

64

65template

67 std::vector<RegionT *> RegionQueue;

68 BlockT *OldEntry = getEntry();

69

70 RegionQueue.push_back(static_cast<RegionT *>(this));

71 while (!RegionQueue.empty()) {

72 RegionT *R = RegionQueue.back();

73 RegionQueue.pop_back();

74

75 R->replaceEntry(NewEntry);

76 for (std::unique_ptr &Child : *R) {

77 if (Child->getEntry() == OldEntry)

78 RegionQueue.push_back(Child.get());

79 }

80 }

81}

82

83template

85 std::vector<RegionT *> RegionQueue;

86 BlockT *OldExit = getExit();

87

88 RegionQueue.push_back(static_cast<RegionT *>(this));

89 while (!RegionQueue.empty()) {

90 RegionT *R = RegionQueue.back();

91 RegionQueue.pop_back();

92

93 R->replaceExit(NewExit);

94 for (std::unique_ptr &Child : *R) {

95 if (Child->getExit() == OldExit)

96 RegionQueue.push_back(Child.get());

97 }

98 }

99}

100

101template

103 BlockT *BB = const_cast<BlockT *>(B);

104

105 if (!DT->getNode(BB))

106 return false;

107

109

110

111 if (!exit)

112 return true;

113

114 return (DT->dominates(entry, BB) &&

115 !(DT->dominates(exit, BB) && DT->dominates(entry, exit)));

116}

117

118template

120

121

122

123 if (!L)

124 return getExit() == nullptr;

125

126 if (contains(L->getHeader()))

127 return false;

128

130 L->getExitingBlocks(ExitingBlocks);

131

132 for (BlockT *BB : ExitingBlocks) {

134 return false;

135 }

136

137 return true;

138}

139

140template

143 return nullptr;

144

145 while (L && contains(L->getParentLoop())) {

146 L = L->getParentLoop();

147 }

148

149 return L;

150}

151

152template

154 BlockT *BB) const {

155 assert(LI && BB && "LI and BB cannot be null!");

156 LoopT *L = LI->getLoopFor(BB);

158}

159

160template

162 auto isEnteringBlock = [&](BlockT *Pred, bool AllowRepeats) -> BlockT * {

163 assert(!AllowRepeats && "Unexpected parameter value.");

164 return DT->getNode(Pred) && contains(Pred) ? Pred : nullptr;

165 };

167 isEnteringBlock);

168}

169

170template

173 bool CoverAll = true;

174

175 if (!exit)

176 return CoverAll;

177

181 continue;

182 }

183

184 CoverAll = false;

185 }

186

187 return CoverAll;

188}

189

190template

192 BlockT *exit = getExit();

193 if (!exit)

194 return nullptr;

195

196 auto isContained = [&](BlockT *Pred, bool AllowRepeats) -> BlockT * {

197 assert(!AllowRepeats && "Unexpected parameter value.");

198 return contains(Pred) ? Pred : nullptr;

199 };

202}

203

204template

208

209template

211 std::string exitName;

212 std::string entryName;

213

216

217 getEntry()->printAsOperand(OS, false);

218 } else

220

224

225 getExit()->printAsOperand(OS, false);

226 } else

228 } else

229 exitName = "";

230

231 return entryName + " => " + exitName;

232}

233

234template

235void RegionBase::verifyBBInRegion(BlockT *BB) const {

237 report_fatal_error("Broken region found: enumerated BB not in region!");

238

239 BlockT *entry = getEntry(), *exit = getExit();

240

242 if (contains(Succ) && exit != Succ)

243 report_fatal_error("Broken region found: edges leaving the region must go "

244 "to the exit node!");

245 }

246

247 if (entry != BB) {

249

250

251 if (contains(Pred) && DT->isReachableFromEntry(Pred))

252 report_fatal_error("Broken region found: edges entering the region must "

253 "go to the entry node!");

254 }

255 }

256}

257

258template

259void RegionBase::verifyWalk(BlockT *BB, std::set<BlockT *> *visited) const {

260 BlockT *exit = getExit();

261

262 visited->insert(BB);

263

264 verifyBBInRegion(BB);

265

267 if (Succ != exit && visited->find(Succ) == visited->end())

268 verifyWalk(Succ, visited);

269 }

270}

271

272template

274

275

276

278 return;

279

280 std::set<BlockT *> visited;

281 verifyWalk(getEntry(), &visited);

282}

283

284template

285void RegionBase::verifyRegionNest() const {

286 for (const std::unique_ptr &R : *this)

287 R->verifyRegionNest();

288

289 verifyRegion();

290}

291

292template

296

297template

301

302template

306 static_cast<const RegionT *>(this));

307}

308

309template

313 static_cast<const RegionT *>(this));

314}

315

316template

318 using RegionT = typename Tr::RegionT;

319

320 RegionT *R = RI->getRegionFor(BB);

321

322 if (!R || R == this)

323 return nullptr;

324

325

327

328 while (contains(R->getParent()) && R->getParent() != this)

329 R = R->getParent();

330

331 if (R->getEntry() != BB)

332 return nullptr;

333

334 return R;

335}

336

337template

339 assert(contains(BB) && "Can get BB node out of this region!");

340

341 auto [at, Inserted] = BBNodeMap.try_emplace(BB);

342 if (Inserted) {

344 at->second =

345 std::make_unique(static_cast<RegionT *>(Deconst), BB);

346 }

347 return at->second.get();

348}

349

350template

354 return Child->getNode();

355

357}

358

359template

361 for (std::unique_ptr &R : *this) {

362 R->parent = To;

363 To->children.push_back(std::move(R));

364 }

365 children.clear();

366}

367

368template

370 assert(!SubRegion->parent && "SubRegion already has a parent!");

372 [&](const std::unique_ptr &R) {

373 return R.get() == SubRegion;

374 }) &&

375 "Subregion already exists!");

376

377 SubRegion->parent = static_cast<RegionT *>(this);

378 children.push_back(std::unique_ptr(SubRegion));

379

380 if (!moveChildren)

381 return;

382

383 assert(SubRegion->children.empty() &&

384 "SubRegions that contain children are not supported");

385

386 for (RegionNodeT *Element : elements()) {

387 if (!Element->isSubRegion()) {

389

390 if (SubRegion->contains(BB))

391 RI->setRegionFor(BB, SubRegion);

392 }

393 }

394

395 std::vector<std::unique_ptr> Keep;

396 for (std::unique_ptr &R : *this) {

397 if (SubRegion->contains(R.get()) && R.get() != SubRegion) {

398 R->parent = SubRegion;

399 SubRegion->children.push_back(std::move(R));

400 } else

401 Keep.push_back(std::move(R));

402 }

403

405 children.insert(

406 children.begin(),

407 std::move_iterator(Keep.begin()),

408 std::move_iterator(Keep.end()));

409}

411template

413 assert(Child->parent == this && "Child is not a child of this region!");

414 Child->parent = nullptr;

415 typename RegionSet::iterator I =

416 llvm::find_if(children, [&](const std::unique_ptr &R) {

417 return R.get() == Child;

418 });

419 assert(I != children.end() && "Region does not exit. Unable to remove.");

421 return Child;

422}

423

424template

426 unsigned Depth = 0;

427

428 for (RegionT *R = getParent(); R != nullptr; R = R->getParent())

430

432}

433

434template

436 unsigned NumSuccessors = Tr::getNumSuccessors(exit);

437

438 if (NumSuccessors == 0)

439 return nullptr;

440

441 RegionT *R = RI->getRegionFor(exit);

442

443 if (R->getEntry() != exit) {

446 return nullptr;

447 if (Tr::getNumSuccessors(exit) == 1)

448 return new RegionT(getEntry(), *BlockTraits::child_begin(exit), RI, DT);

449 return nullptr;

450 }

451

452 while (R->getParent() && R->getParent()->getEntry() == exit)

453 R = R->getParent();

454

456 if (!(contains(Pred) || R->contains(Pred)))

457 return nullptr;

458 }

459

460 return new RegionT(getEntry(), R->getExit(), RI, DT);

461}

462

463template

466 if (print_tree)

467 OS.indent(level * 2) << '[' << level << "] " << getNameStr();

468 else

470

471 OS << '\n';

472

474 OS.indent(level * 2) << "{\n";

475 OS.indent(level * 2 + 2);

476

478 for (const auto *BB : blocks())

479 OS << BB->getName() << ", ";

480 } else if (Style == PrintRN) {

481 for (const RegionNodeT *Element : elements()) {

482 OS << *Element << ", ";

483 }

484 }

485

486 OS << '\n';

487 }

488

489 if (print_tree) {

490 for (const std::unique_ptr &R : *this)

491 R->print(OS, print_tree, level + 1, Style);

492 }

493

494 if (Style != PrintNone)

495 OS.indent(level * 2) << "} \n";

496}

497

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

499template

504

505template

507 BBNodeMap.clear();

508 for (std::unique_ptr &R : *this)

509 R->clearNodeCache();

510}

511

512

513

514

515

516template

517RegionInfoBase::RegionInfoBase() = default;

518

519template

520RegionInfoBase::~RegionInfoBase() {

521 releaseMemory();

522}

523

524template

525void RegionInfoBase::verifyBBMap(const RegionT *R) const {

526 assert(R && "Re must be non-null");

527 for (const typename Tr::RegionNodeT *Element : R->elements()) {

528 if (Element->isSubRegion()) {

530 verifyBBMap(SR);

532 BlockT *BB = Element->template getNodeAs();

533 if (getRegionFor(BB) != R)

535 }

537}

538

539template

540bool RegionInfoBase::isCommonDomFrontier(BlockT *BB, BlockT *entry,

541 BlockT *exit) const {

543 if (DT->dominates(entry, P) && !DT->dominates(exit, P))

544 return false;

545 }

546

547 return true;

548}

550template

551bool RegionInfoBase::isRegion(BlockT *entry, BlockT *exit) const {

552 assert(entry && exit && "entry and exit must not be null!");

553

554 using DST = typename DomFrontierT::DomSetType;

555

556 DST *entrySuccs = &DF->find(entry)->second;

557

558

559

560 if (!DT->dominates(entry, exit)) {

561 for (BlockT *successor : *entrySuccs) {

562 if (successor != exit && successor != entry)

563 return false;

564 }

565

566 return true;

567 }

568

569 DST *exitSuccs = &DF->find(exit)->second;

570

571

572 for (BlockT *Succ : *entrySuccs) {

573 if (Succ == exit || Succ == entry)

574 continue;

575 if (!exitSuccs->contains(Succ))

576 return false;

577 if (!isCommonDomFrontier(Succ, entry, exit))

578 return false;

579 }

580

581

582 for (BlockT *Succ : *exitSuccs) {

583 if (DT->properlyDominates(entry, Succ) && Succ != exit)

584 return false;

585 }

586

587 return true;

588}

589

590template

591void RegionInfoBase::insertShortCut(BlockT *entry, BlockT *exit,

592 BBtoBBMap *ShortCut) const {

593 assert(entry && exit && "entry and exit must not be null!");

594

595 typename BBtoBBMap::iterator e = ShortCut->find(exit);

596

597 if (e == ShortCut->end())

598

599 (*ShortCut)[entry] = exit;

600 else {

601

602

603

604 BlockT *BB = e->second;

605 (*ShortCut)[entry] = BB;

606 }

607}

608

609template

610typename Tr::DomTreeNodeT *

611RegionInfoBase::getNextPostDom(DomTreeNodeT *N, BBtoBBMap *ShortCut) const {

612 typename BBtoBBMap::iterator e = ShortCut->find(N->getBlock());

613

614 if (e == ShortCut->end())

615 return N->getIDom();

616

617 return PDT->getNode(e->second)->getIDom();

618}

619

620template

621bool RegionInfoBase::isTrivialRegion(BlockT *entry, BlockT *exit) const {

622 assert(entry && exit && "entry and exit must not be null!");

623

624 unsigned num_successors =

625 BlockTraits::child_end(entry) - BlockTraits::child_begin(entry);

626

627 if (num_successors <= 1 && exit == *(BlockTraits::child_begin(entry)))

628 return true;

629

630 return false;

631}

632

633template

634typename Tr::RegionT *RegionInfoBase::createRegion(BlockT *entry,

635 BlockT *exit) {

636 assert(entry && exit && "entry and exit must not be null!");

637

638 if (isTrivialRegion(entry, exit))

639 return nullptr;

640

642 new RegionT(entry, exit, static_cast<RegionInfoT *>(this), DT);

643 BBtoRegion.insert({entry, region});

644

645 region->verifyRegion();

646

649}

650

651template

652void RegionInfoBase::findRegionsWithEntry(BlockT *entry,

653 BBtoBBMap *ShortCut) {

655

656 DomTreeNodeT *N = PDT->getNode(entry);

657 if (N)

658 return;

659

660 RegionT *lastRegion = nullptr;

661 BlockT *lastExit = entry;

662

663

664

665 while ((N = getNextPostDom(N, ShortCut))) {

666 BlockT *exit = N->getBlock();

667

668 if (!exit)

669 break;

670

671 if (isRegion(entry, exit)) {

672 RegionT *newRegion = createRegion(entry, exit);

673

674 if (lastRegion)

675 newRegion->addSubRegion(lastRegion);

676

677 lastRegion = newRegion;

678 lastExit = exit;

679 }

680

681

682 if (!DT->dominates(entry, exit))

683 break;

684 }

685

686

687

688 if (lastExit != entry)

689 insertShortCut(entry, lastExit, ShortCut);

690}

691

692template

693void RegionInfoBase::scanForRegions(FuncT &F, BBtoBBMap *ShortCut) {

694 using FuncPtrT = std::add_pointer_t;

695

697 DomTreeNodeT *N = DT->getNode(entry);

698

699

700

701

702

704 findRegionsWithEntry(DomNode->getBlock(), ShortCut);

705}

706

707template

708typename Tr::RegionT *RegionInfoBase::getTopMostParent(RegionT *region) {

709 while (region->getParent())

711

713}

714

715template

716void RegionInfoBase::buildRegionsTree(DomTreeNodeT *N, RegionT *region) {

717 BlockT *BB = N->getBlock();

718

719

720 while (BB == region->getExit())

722

723 auto [It, Inserted] = BBtoRegion.try_emplace(BB, region);

724

725

726

727 if (!Inserted) {

728 RegionT *newRegion = It->second;

729 region->addSubRegion(getTopMostParent(newRegion));

731 }

732

734 buildRegionsTree(C, region);

735 }

736}

737

738#ifdef EXPENSIVE_CHECKS

739template

741#else

742template

744#endif

745

746template

749

750template

752 OS << "Region tree:\n";

753 TopLevelRegion->print(OS, true, 0, printStyle);

754 OS << "End region tree\n";

755}

756

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

758template

760#endif

761

763 BBtoRegion.clear();

764 if (TopLevelRegion) {

765 delete TopLevelRegion;

766 TopLevelRegion = nullptr;

767 }

768}

769

770template

772

773

775 return;

776

777 TopLevelRegion->verifyRegionNest();

778

779 verifyBBMap(TopLevelRegion);

780}

781

782

783template

785 return BBtoRegion.lookup(BB);

786}

787

788template

790 BBtoRegion[BB] = R;

791}

792

793template

797

798template

799typename RegionInfoBase::BlockT *

801 BlockT *Exit = nullptr;

802

803 while (true) {

804

806 while (R && R->getParent() && R->getParent()->getEntry() == BB)

807 R = R->getParent();

809

810 if (R && R->getEntry() == BB)

811 Exit = R->getExit();

812 else if (std::next(BlockTraits::child_begin(BB)) ==

813 BlockTraits::child_end(BB))

814 Exit = *BlockTraits::child_begin(BB);

815 else

816 return Exit;

817

818

820 while (ExitR && ExitR->getParent() &&

821 ExitR->getParent()->getEntry() == Exit)

822 ExitR = ExitR->getParent();

823

825 if (!R->contains(Pred) && !ExitR->contains(Pred))

826 break;

827 }

829

830 if (DT->dominates(Exit, BB))

831 break;

832

833 BB = Exit;

835

836 return Exit;

837}

838

839template

841 RegionT *B) const {

842 assert(A && B && "One of the Regions is NULL");

843

844 if (A->contains(B))

845 return A;

846

847 while (B->contains(A))

848 B = B->getParent();

849

850 return B;

851}

852

853template

854typename Tr::RegionT *

857

858 for (RegionT *R : Regions)

860

861 return ret;

862}

863

864template

865typename Tr::RegionT *

869

870 for (BlockT *BB : BBs)

872

873 return ret;

875

876template

877void RegionInfoBase::calculate(FuncT &F) {

878 using FuncPtrT = std::add_pointer_t;

879

880

881

882

883 BBtoBBMap ShortCut;

884

885 scanForRegions(F, &ShortCut);

887 buildRegionsTree(DT->getNode(BB), TopLevelRegion);

888}

889

890}

891

892#undef DEBUG_TYPE

893

894#endif

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

static const Function * getParent(const Value *V)

bbsections Prepares for basic block by splitting functions into clusters of basic blocks

static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")

static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")

bool isContained(DIScope *Inner, DIScope *Outer)

static RegisterPass< DebugifyFunctionPass > DF("debugify-function", "Attach debug info to a function")

This file defines the little GraphTraits template class that should be specialized by classes that...

This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.

static StringRef getName(Value *V)

static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)

This file defines the SmallVector class.

Base class for the actual dominator tree node.

void replaceExit(BlockT *BB)

Replace the exit basic block of the region with the new basic block.

Definition RegionInfoImpl.h:60

void clearNodeCache()

Clear the cache for BB RegionNodes.

Definition RegionInfoImpl.h:506

std::string getNameStr() const

Returns the name of the Region.

Definition RegionInfoImpl.h:210

BlockT * getExit() const

Get the exit BasicBlock of the Region.

void transferChildrenTo(RegionT *To)

Move all direct child nodes of this Region to another Region.

Definition RegionInfoImpl.h:360

RegionNodeT * getBBNode(BlockT *BB) const

Get the BasicBlock RegionNode for a BasicBlock.

Definition RegionInfoImpl.h:338

bool getExitingBlocks(SmallVectorImpl< BlockT * > &Exitings) const

Collect all blocks of this region's single exit edge, if existing.

Definition RegionInfoImpl.h:171

RegionNodeT * getNode() const

Get the RegionNode representing the current Region.

iterator_range< element_iterator > elements()

LoopT * outermostLoopInRegion(LoopT *L) const

Get the outermost loop in the region that contains a loop.

Definition RegionInfoImpl.h:141

unsigned getDepth() const

Get the nesting level of this Region.

Definition RegionInfoImpl.h:425

void replaceEntry(BlockT *BB)

Replace the entry basic block of the region with the new basic block.

Definition RegionInfoImpl.h:55

void dump() const

Print the region to stderr.

Definition RegionInfoImpl.h:500

void replaceEntryRecursive(BlockT *NewEntry)

Recursively replace the entry basic block of the region.

Definition RegionInfoImpl.h:66

bool contains(const BlockT *BB) const

Check if the region contains a BasicBlock.

Definition RegionInfoImpl.h:102

element_iterator element_begin()

Definition RegionInfoImpl.h:293

void replaceExitRecursive(BlockT *NewExit)

Recursively replace the exit basic block of the region.

Definition RegionInfoImpl.h:84

void verifyRegion() const

Verify if the region is a correct region.

Definition RegionInfoImpl.h:273

BlockT * getEntry() const

Get the entry BasicBlock of the Region.

void addSubRegion(RegionT *SubRegion, bool moveChildren=false)

Add a new subregion to this Region.

Definition RegionInfoImpl.h:369

element_iterator element_end()

Definition RegionInfoImpl.h:298

bool isSimple() const

Is this a simple region?

Definition RegionInfoImpl.h:205

bool isTopLevelRegion() const

Check if a Region is the TopLevel region.

RegionBase(BlockT *Entry, BlockT *Exit, RegionInfoT *RI, DomTreeT *DT, RegionT *Parent=nullptr)

Create a new region.

Definition RegionInfoImpl.h:42

BlockT * getExitingBlock() const

Return the first block of this region's single exit edge, if existing.

Definition RegionInfoImpl.h:191

~RegionBase()

Delete the Region and all its subregions.

Definition RegionInfoImpl.h:48

df_iterator< const RegionNodeT *, df_iterator_default_set< const RegionNodeT * >, false, GraphTraits< const RegionNodeT * > > const_element_iterator

PrintStyle

PrintStyle - Print region in difference ways.

RegionT * removeSubRegion(RegionT *SubRegion)

Remove a subregion from this Region.

Definition RegionInfoImpl.h:412

BlockT * getEnteringBlock() const

Return the first block of this region's single entry edge, if existing.

Definition RegionInfoImpl.h:161

RegionT * getExpandedRegion() const

Return a new (non-canonical) region, that is obtained by joining this region with its predecessors.

Definition RegionInfoImpl.h:435

void print(raw_ostream &OS, bool printTree=true, unsigned level=0, PrintStyle Style=PrintNone) const

Print the region.

Definition RegionInfoImpl.h:464

RegionT * getSubRegionNode(BlockT *BB) const

Get the subregion that starts at a BasicBlock.

Definition RegionInfoImpl.h:317

df_iterator< RegionNodeT *, df_iterator_default_set< RegionNodeT * >, false, GraphTraits< RegionNodeT * > > element_iterator

void dump() const

Definition RegionInfoImpl.h:759

BlockT * getMaxRegionExit(BlockT *BB) const

Return the exit of the maximal refined region, that starts at a BasicBlock.

Definition RegionInfoImpl.h:800

static bool VerifyRegionInfo

void print(raw_ostream &OS) const

Definition RegionInfoImpl.h:751

RegionT * getRegionFor(BlockT *BB) const

Get the smallest region that contains a BasicBlock.

Definition RegionInfoImpl.h:784

void verifyAnalysis() const

Definition RegionInfoImpl.h:771

void releaseMemory()

Definition RegionInfoImpl.h:762

void setRegionFor(BlockT *BB, RegionT *R)

Set the smallest region that surrounds a basic block.

Definition RegionInfoImpl.h:789

RegionT * operator[](BlockT *BB) const

A shortcut for getRegionFor().

Definition RegionInfoImpl.h:794

static RegionT::PrintStyle printStyle

RegionT * getCommonRegion(RegionT *A, RegionT *B) const

Find the smallest region that contains two regions.

Definition RegionInfoImpl.h:840

RegionNodeBase(RegionT *Parent, BlockT *Entry, bool isSubRegion=false)

Create a RegionNode.

BasicBlock * getNodeAs() const

This class consists of common code factored out of the SmallVector class to reduce code duplication b...

void push_back(const T &Elt)

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

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

raw_ostream & indent(unsigned NumSpaces)

indent - Insert 'NumSpaces' spaces.

A raw_ostream that writes to an std::string.

@ C

The default llvm calling convention, compatible with C.

Assignment Tracking (at).

This is an optimization pass for GlobalISel generic memory operations.

Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)

iterator_range< po_iterator< T > > post_order(const T &G)

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 void report_fatal_error(Error Err, bool gen_crash_diag=true)

T * find_singleton(R &&Range, Predicate P, bool AllowRepeats=false)

Return the single value in Range that satisfies P( *, AllowRepeats)->T * returning n...

iterator_range< typename GraphTraits< Inverse< GraphType > >::ChildIteratorType > inverse_children(const typename GraphTraits< GraphType >::NodeRef &G)

auto find_if(R &&Range, UnaryPredicate P)

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

iterator_range< typename GraphTraits< GraphType >::ChildIteratorType > children(const typename GraphTraits< GraphType >::NodeRef &G)

@ Keep

No function return thunk.