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

1

2

3

4

5

6

7

8

24

25using namespace llvm;

26

27#define DEBUG_TYPE "must-execute"

28

31 return BlockColors;

32}

33

35 ColorVector &ColorsForNewBlock = BlockColors[New];

36 ColorVector &ColorsForOldBlock = BlockColors[Old];

37 ColorsForNewBlock = ColorsForOldBlock;

38}

39

41 (void)BB;

43}

44

46 return MayThrow;

47}

48

50 assert(CurLoop != nullptr && "CurLoop can't be null");

52

54 MayThrow = HeaderMayThrow;

55

56

57

59 "First block must be header");

62 if (MayThrow)

63 break;

64 }

65

67}

68

70 return ICF.hasICF(BB);

71}

72

74 return MayThrow;

75}

76

78 assert(CurLoop != nullptr && "CurLoop can't be null");

81 MayThrow = false;

82

83 for (const auto &BB : CurLoop->blocks())

84 if (ICF.hasICF(&*BB)) {

85 MayThrow = true;

86 break;

87 }

89}

90

95}

96

100}

101

103

104

110}

111

112

113

114

117 const Loop *CurLoop) {

119 if (!CondExitBlock)

120

121 return false;

122 assert(CurLoop->contains(CondExitBlock) && "meaning of exit block");

123 auto *BI = dyn_cast(CondExitBlock->getTerminator());

124 if (!BI || !BI->isConditional())

125 return false;

126

127

128 if (auto *Cond = dyn_cast(BI->getCondition()))

129 return BI->getSuccessor(Cond->getZExtValue() ? 1 : 0) == ExitBlock;

130 auto *Cond = dyn_cast(BI->getCondition());

132 return false;

133

134

135

137 auto *LHS = dyn_cast(Cond->getOperand(0));

138 auto *RHS = Cond->getOperand(1);

140 Pred = Cond->getSwappedPredicate();

141 LHS = dyn_cast(Cond->getOperand(1));

142 RHS = Cond->getOperand(0);

144 return false;

145 }

146

148 auto *IVStart = LHS->getIncomingValueForBlock(CurLoop->getLoopPreheader());

150 Pred, IVStart, RHS, {DL, nullptr, DT, nullptr, BI});

151 auto *SimpleCst = dyn_cast_or_null(SimpleValOrNull);

152 if (!SimpleCst)

153 return false;

154 if (ExitBlock == BI->getSuccessor(0))

155 return SimpleCst->isZeroValue();

156 assert(ExitBlock == BI->getSuccessor(1) && "implied by above");

157 return SimpleCst->isAllOnesValue();

158}

159

160

161

162

163

164

165

169 assert(Predecessors.empty() && "Garbage in predecessors set?");

170 assert(CurLoop->contains(BB) && "Should only be called for loop blocks!");

172 return;

175 if (!CurLoop->contains(Pred))

176 continue;

177 Predecessors.insert(Pred);

179 }

180 while (!WorkList.empty()) {

182 assert(CurLoop->contains(Pred) && "Should only reach loop blocks!");

183

184 if (Pred == CurLoop->getHeader())

185 continue;

186

187

188

189

190

191

192 for (const auto *PredPred : predecessors(Pred))

193 if (CurLoop->contains(PredPred) && Predecessors.insert(PredPred).second)

195 }

196}

197

201 assert(CurLoop->contains(BB) && "Should only be called for loop blocks!");

202

203

205 return true;

206

207

208

211

212

213

214

216

217

218 if (Predecessors.contains(Pred))

219 return false;

220

221

222

223

224

225

226

228 for (const auto *Pred : Predecessors) {

229

231 return false;

232

233

234

236 continue;

237

238 for (const auto *Succ : successors(Pred))

239 if (CheckedSuccessors.insert(Succ).second &&

240 Succ != BB && !Predecessors.count(Succ))

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255 if (CurLoop->contains(Succ) ||

257 return false;

258 }

259

260

261 return true;

262}

263

264

265

268 const Loop *CurLoop) const {

269

270

271

273

274

275

276

277 return !HeaderMayThrow ||

278 Inst.getParent()->getFirstNonPHIOrDbg() == &Inst;

279

280

281

283}

284

287 const Loop *CurLoop) const {

290}

291

293 const Loop *CurLoop) const {

294 assert(CurLoop->contains(BB) && "Should only be called for loop blocks!");

295

296

298 return true;

299

300

301

304

305

306 for (const auto *Pred : Predecessors)

308 return false;

309 return true;

310}

311

313 const Loop *CurLoop) const {

314 auto *BB = I.getParent();

315 assert(CurLoop->contains(BB) && "Should only be called for loop blocks!");

318}

319

321

322

323

328}

329

330namespace {

331

332

335

336public:

337 MustExecuteAnnotatedWriter(const Function &F,

341 while (L) {

343 MustExec[&I].push_back(L);

344 }

345 L = L->getParentLoop();

346 };

347 }

348 }

349 MustExecuteAnnotatedWriter(const Module &M,

351 for (const auto &F : M)

354 while (L) {

356 MustExec[&I].push_back(L);

357 }

358 L = L->getParentLoop();

359 };

360 }

361 }

362

363

365 if (!MustExec.count(&V))

366 return;

367

369 const auto NumLoops = Loops.size();

370 if (NumLoops > 1)

371 OS << " ; (mustexec in " << NumLoops << " loops: ";

372 else

373 OS << " ; (mustexec in: ";

374

375 ListSeparator LS;

377 OS << LS << L->getHeader()->getName();

378 OS << ")";

379 }

380};

381}

382

383

385 if (L.getHeader()->getParent()->hasFnAttribute(Attribute::WillReturn))

386 return false;

387

388

389 return true;

390}

391

393 if (!LI)

394 return false;

396 RPOTraversal FuncRPOT(&F);

398 const LoopInfo>(FuncRPOT, *LI);

399}

400

401

402

403template <typename K, typename V, typename FnTy, typename... ArgsTy>

405 FnTy &&Fn, ArgsTy &&...args) {

406 std::optional &OptVal = Map[Key];

407 if (!OptVal)

408 OptVal = Fn(std::forward(args)...);

409 return *OptVal;

410}

411

416

418 << (LI ? " [LI]" : "") << (PDT ? " [PDT]" : ""));

419

421 const Loop *L = LI ? LI->getLoopFor(InitBB) : nullptr;

422 const BasicBlock *HeaderBB = L ? L->getHeader() : InitBB;

423 bool WillReturnAndNoThrow = (F.hasFnAttribute(Attribute::WillReturn) ||

425 F.doesNotThrow();

427 << (WillReturnAndNoThrow ? " [WillReturn] [NoUnwind]" : "")

428 << "\n");

429

430

431

434 bool IsLatch = SuccBB == HeaderBB;

435

436

437 if (!WillReturnAndNoThrow || !IsLatch)

439 }

441

442

443 if (Worklist.empty())

444 return nullptr;

445

446

447 if (Worklist.size() == 1)

448 return Worklist[0];

449

450

451

452

454 if (PDT)

455 if (const auto *InitNode = PDT->getNode(InitBB))

456 if (const auto *IDomNode = InitNode->getIDom())

457 JoinBB = IDomNode->getBlock();

458

459 if (!JoinBB && Worklist.size() == 2) {

460 const BasicBlock *Succ0 = Worklist[0];

461 const BasicBlock *Succ1 = Worklist[1];

464 if (Succ0UniqueSucc == InitBB) {

465

466

467 JoinBB = Succ1;

468 } else if (Succ1UniqueSucc == InitBB) {

469

470

471 JoinBB = Succ0;

472 } else if (Succ0 == Succ1UniqueSucc) {

473

474

475 JoinBB = Succ0;

476 } else if (Succ1 == Succ0UniqueSucc) {

477

478

479 JoinBB = Succ1;

480 } else if (Succ0UniqueSucc == Succ1UniqueSucc) {

481

482

483 JoinBB = Succ0UniqueSucc;

484 }

485 }

486

487 if (!JoinBB && L)

488 JoinBB = L->getUniqueExitBlock();

489

490 if (!JoinBB)

491 return nullptr;

492

494

495

496

497

498

499

500

501

502

503 if (F.hasFnAttribute(Attribute::WillReturn) || F.doesNotThrow()) {

504

505 auto BlockTransfersExecutionToSuccessor = [](const BasicBlock *BB) {

507 };

508

510 while (!Worklist.empty()) {

512 if (ToBB == JoinBB)

513 continue;

514

515

516 if (!Visited.insert(ToBB).second) {

517 if (F.hasFnAttribute(Attribute::WillReturn)) {

518 if (!LI)

519 return nullptr;

520

523 if (MayContainIrreducibleControl)

524 return nullptr;

525

528 return nullptr;

529 }

530

531 continue;

532 }

533

534

535

537 ToBB, BlockTransferMap, BlockTransfersExecutionToSuccessor, ToBB);

538 if (!TransfersExecution)

539 return nullptr;

540

542 }

543 }

544

546 return JoinBB;

547}

553 << (LI ? " [LI]" : "") << (DT ? " [DT]" : ""));

554

555

556

557

558 if (DT)

559 if (const auto *InitNode = DT->getNode(InitBB))

560 if (const auto *IDomNode = InitNode->getIDom())

561 return IDomNode->getBlock();

562

563 const Loop *L = LI ? LI->getLoopFor(InitBB) : nullptr;

564 const BasicBlock *HeaderBB = L ? L->getHeader() : nullptr;

565

566

569 bool IsBackedge =

570 (PredBB == InitBB) || (HeaderBB == InitBB && L->contains(PredBB));

571

572

573 if (!IsBackedge)

575 }

576

577

578 if (Worklist.empty())

579 return nullptr;

580

581

582 if (Worklist.size() == 1)

583 return Worklist[0];

584

586 if (Worklist.size() == 2) {

587 const BasicBlock *Pred0 = Worklist[0];

588 const BasicBlock *Pred1 = Worklist[1];

591 if (Pred0 == Pred1UniquePred) {

592

593

594 JoinBB = Pred0;

595 } else if (Pred1 == Pred0UniquePred) {

596

597

598 JoinBB = Pred1;

599 } else if (Pred0UniquePred == Pred1UniquePred) {

600

601

602 JoinBB = Pred0UniquePred;

603 }

604 }

605

606 if (!JoinBB && L)

607 JoinBB = L->getHeader();

608

609

610

611

612 return JoinBB;

613}

614

618 if (!PP)

619 return PP;

620 LLVM_DEBUG(dbgs() << "Find next instruction for " << *PP << "\n");

621

622

624 LLVM_DEBUG(dbgs() << "\tReached terminator in intra-block mode, done\n");

625 return nullptr;

626 }

627

628

629

630

632 if (!TransfersExecution)

633 return nullptr;

634

635

636

637

638

641 LLVM_DEBUG(dbgs() << "\tIntermediate instruction does transfer control\n");

642 return NextPP;

643 }

644

645

647

648

651 return nullptr;

652 }

653

654

655

658 dbgs() << "\tUnconditional terminator, continue with successor\n");

660 }

661

662

663

664

666 return &JoinBB->front();

667

669 return nullptr;

670}

671

675 if (!PP)

676 return PP;

677

679 LLVM_DEBUG(dbgs() << "Find next instruction for " << *PP

680 << (IsFirst ? " [IsFirst]" : "") << "\n");

681

682

683

685 LLVM_DEBUG(dbgs() << "\tReached block front in intra-block mode, done\n");

686 return nullptr;

687 }

688

689

691

692

693

694 if (!IsFirst) {

697 dbgs() << "\tIntermediate instruction, continue with previous\n");

698

699 return PrevPP;

700 }

701

702

703

704

705

707 return &JoinBB->back();

708

710 return nullptr;

711}

712

715 : Explorer(Explorer), CurInst(I) {

716 reset(I);

717}

718

719void MustBeExecutedIterator::reset(const Instruction *I) {

721 resetInstruction(I);

722}

723

724void MustBeExecutedIterator::resetInstruction(const Instruction *I) {

725 CurInst = I;

726 Head = Tail = nullptr;

730 Head = I;

732 Tail = I;

733}

734

735const Instruction *MustBeExecutedIterator::advance() {

736 assert(CurInst && "Cannot advance an end iterator!");

738 if (Head && Visited.insert({Head, ExplorationDirection ::FORWARD}).second)

739 return Head;

740 Head = nullptr;

741

743 if (Tail && Visited.insert({Tail, ExplorationDirection ::BACKWARD}).second)

744 return Tail;

745 Tail = nullptr;

746 return nullptr;

747}

748

753

754 MustExecuteAnnotatedWriter Writer(F, DT, LI);

755 F.print(OS, &Writer);

757}

758

763 GetterTy LIGetter = [&](const Function &F) {

765 };

766 GetterTy DTGetter = [&](const Function &F) {

768 };

769 GetterTy PDTGetter = [&](const Function &F) {

771 };

772

774 true,

775 true,

776 true, LIGetter, DTGetter, PDTGetter);

777

780 OS << "-- Explore context of: " << I << "\n";

782 OS << " [F: " << CI->getFunction()->getName() << "] " << *CI << "\n";

783 }

784 }

786}

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

Expand Atomic instructions

Module.h This file contains the declarations for the Module class.

This header defines various interfaces for pass management in LLVM.

static void collectTransitivePredecessors(const Loop *CurLoop, const BasicBlock *BB, SmallPtrSetImpl< const BasicBlock * > &Predecessors)

Collect all blocks from CurLoop which lie on all possible paths from the header of CurLoop (inclusive...

static bool maybeEndlessLoop(const Loop &L)

Return true if L might be an endless loop.

static V getOrCreateCachedOptional(K Key, DenseMap< K, std::optional< V > > &Map, FnTy &&Fn, ArgsTy &&...args)

Lookup Key in Map and return the result, potentially after initializing the optional through Fn(args)...

static bool isMustExecuteIn(const Instruction &I, Loop *L, DominatorTree *DT)

static bool CanProveNotTakenFirstIteration(const BasicBlock *ExitBlock, const DominatorTree *DT, const Loop *CurLoop)

Return true if we can prove that the given ExitBlock is not reached on the first iteration of the giv...

Contains a collection of routines for determining if a given instruction is guaranteed to execute if ...

FunctionAnalysisManager FAM

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

const SmallVectorImpl< MachineOperand > & Cond

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

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

PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)

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

LLVM Basic Block Representation.

const Instruction & front() const

const BasicBlock * getUniqueSuccessor() const

Return the successor of this block if it has a unique successor.

const BasicBlock * getSinglePredecessor() const

Return the predecessor of this block if it has a single predecessor block.

const BasicBlock * getUniquePredecessor() const

Return the predecessor of this block if it has a unique predecessor block.

const Function * getParent() const

Return the enclosing method, or null if none.

const Module * getModule() const

Return the module owning the function this basic block belongs to, or nullptr if the function does no...

Predicate

This enumeration lists the possible predicates for CmpInst subclasses.

This is an important base class in LLVM.

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.

Analysis pass which computes a DominatorTree.

DomTreeNodeBase< NodeT > * getNode(const NodeT *BB) const

getNode - return the (Post)DominatorTree node for the specified basic block.

Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.

bool dominates(const BasicBlock *BB, const Use &U) const

Return true if the (end of the) basic block BB dominates the use U.

bool hasPersonalityFn() const

Check whether this function has a personality function.

Constant * getPersonalityFn() const

Get the personality function associated with this function.

bool blockMayThrow(const BasicBlock *BB) const override

Returns true iff the block BB potentially may throw exception.

bool doesNotWriteMemoryBefore(const BasicBlock *BB, const Loop *CurLoop) const

Returns true if we could not execute a memory-modifying instruction before we enter BB under assumpti...

void removeInstruction(const Instruction *Inst)

Inform safety info that we are planning to remove the instruction Inst from its block.

bool isGuaranteedToExecute(const Instruction &Inst, const DominatorTree *DT, const Loop *CurLoop) const override

Returns true if the instruction in a loop is guaranteed to execute at least once (under the assumptio...

bool anyBlockMayThrow() const override

Returns true iff any block of the loop for which this info is contains an instruction that may throw ...

void computeLoopSafetyInfo(const Loop *CurLoop) override

Computes safety information for a loop checks loop body & header for the possibility of may throw exc...

void insertInstructionTo(const Instruction *Inst, const BasicBlock *BB)

Inform the safety info that we are planning to insert a new instruction Inst into the basic block BB.

bool isDominatedByICFIFromSameBlock(const Instruction *Insn)

Returns true if the first ICFI of Insn's block exists and dominates Insn.

bool hasICF(const BasicBlock *BB)

Returns true if at least one instruction from the given basic block has implicit control flow.

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

void clear()

Invalidates all information from this tracking.

void insertInstructionTo(const Instruction *Inst, const BasicBlock *BB)

Notifies this tracking that we are going to insert a new instruction Inst to the basic block BB.

void removeInstruction(const Instruction *Inst)

Notifies this tracking that we are going to remove the instruction Inst It makes all necessary update...

unsigned getNumSuccessors() const LLVM_READONLY

Return the number of successors that this instruction has.

BasicBlock * getSuccessor(unsigned Idx) const LLVM_READONLY

Return the specified successor. This instruction must be a terminator.

bool isTerminator() const

Analysis pass that exposes the LoopInfo for a function.

bool contains(const LoopT *L) const

Return true if the specified loop is contained within in this loop.

BlockT * getHeader() const

iterator_range< block_iterator > blocks() const

BlockT * getLoopPreheader() const

If there is a preheader for this loop, return it.

ArrayRef< BlockT * > getBlocks() const

Get a list of the basic blocks which make up this loop.

LoopT * getLoopFor(const BlockT *BB) const

Return the inner most loop that BB lives in.

bool allLoopPathsLeadToBlock(const Loop *CurLoop, const BasicBlock *BB, const DominatorTree *DT) const

Return true if we must reach the block BB under assumption that the loop CurLoop is entered.

void copyColors(BasicBlock *New, BasicBlock *Old)

Copy colors of block Old into the block New.

void computeBlockColors(const Loop *CurLoop)

Computes block colors.

const DenseMap< BasicBlock *, ColorVector > & getBlockColors() const

Returns block colors map that is used to update funclet operand bundles.

virtual bool blockMayThrow(const BasicBlock *BB) const =0

Returns true iff the block BB potentially may throw exception.

Represents a single loop in the control flow graph.

bool mayWriteToMemory(const BasicBlock *BB)

Returns true if at least one instruction from the given basic block may write memory.

bool isDominatedByMemoryWriteFromSameBlock(const Instruction *Insn)

Returns true if the first memory writing instruction of Insn's block exists and dominates Insn.

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

const DataLayout & getDataLayout() const

Get the data layout for the module's target platform.

PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)

PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)

Analysis pass which computes a PostDominatorTree.

PostDominatorTree Class - Concrete subclass of DominatorTree that is used to compute the post-dominat...

A set of analyses that are preserved following a run of a transformation pass.

static PreservedAnalyses all()

Construct a special preserved set that preserves all passes.

Simple and conservative implementation of LoopSafetyInfo that can give false-positive answers to its ...

bool isGuaranteedToExecute(const Instruction &Inst, const DominatorTree *DT, const Loop *CurLoop) const override

Returns true if the instruction in a loop is guaranteed to execute at least once.

void computeLoopSafetyInfo(const Loop *CurLoop) override

Computes safety information for a loop checks loop body & header for the possibility of may throw exc...

bool anyBlockMayThrow() const override

Returns true iff any block of the loop for which this info is contains an instruction that may throw ...

bool blockMayThrow(const BasicBlock *BB) const override

Returns true iff the block BB potentially may throw exception.

A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...

size_type count(ConstPtrType Ptr) const

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

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

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

bool contains(ConstPtrType Ptr) const

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

void push_back(const T &Elt)

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

TinyPtrVector - This class is specialized for cases where there are normally 0 or 1 element in a vect...

LLVM Value Representation.

StringRef getName() const

Return a constant reference to the value's name.

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

formatted_raw_ostream - A raw_ostream that wraps another one and keeps track of line and column posit...

const ParentTy * getParent() const

NodeTy * getNextNode()

Get the next node, or nullptr for the list tail.

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.

auto successors(const MachineBasicBlock *BB)

bool isGuaranteedToExecuteForEveryIteration(const Instruction *I, const Loop *L)

Return true if this function can prove that the instruction I is executed for every iteration of the ...

void append_range(Container &C, Range &&R)

Wrapper function to append range R to container C.

DenseMap< BasicBlock *, ColorVector > colorEHFunclets(Function &F)

If an EH funclet personality is in use (see isFuncletEHPersonality), this will recompute which blocks...

bool isScopedEHPersonality(EHPersonality Pers)

Returns true if this personality uses scope-style EH IR instructions: catchswitch,...

bool containsIrreducibleCFG(RPOTraversalT &RPOTraversal, const LoopInfoT &LI)

Return true if the control flow in RPOTraversal is irreducible.

raw_ostream & dbgs()

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

EHPersonality classifyEHPersonality(const Value *Pers)

See if the given exception handling personality function is one that we understand.

bool isGuaranteedToTransferExecutionToSuccessor(const Instruction *I)

Return true if this function can prove that the instruction I will always transfer execution to one o...

auto predecessors(const MachineBasicBlock *BB)

Value * simplifyCmpInst(CmpPredicate Predicate, Value *LHS, Value *RHS, const SimplifyQuery &Q)

Given operands for a CmpInst, fold the result or return null.

bool mayContainIrreducibleControl(const Function &F, const LoopInfo *LI)

A "must be executed context" for a given program point PP is the set of instructions,...

const bool ExploreInterBlock

Parameter that limit the performed exploration.

const BasicBlock * findBackwardJoinPoint(const BasicBlock *InitBB)

Find the next join point from InitBB in backward direction.

const Instruction * getMustBeExecutedNextInstruction(MustBeExecutedIterator &It, const Instruction *PP)

Return the next instruction that is guaranteed to be executed after PP.

const bool ExploreCFGBackward

const bool ExploreCFGForward

llvm::iterator_range< iterator > range(const Instruction *PP)

}

const Instruction * getMustBeExecutedPrevInstruction(MustBeExecutedIterator &It, const Instruction *PP)

Return the previous instr.

const BasicBlock * findForwardJoinPoint(const BasicBlock *InitBB)

Find the next join point from InitBB in forward direction.

Must be executed iterators visit stretches of instructions that are guaranteed to be executed togethe...

MustBeExecutedIterator(const MustBeExecutedIterator &Other)=default