LLVM: lib/Transforms/Scalar/LoopSimplifyCFG.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

32#include

33using namespace llvm;

34

35#define DEBUG_TYPE "loop-simplifycfg"

36

39

41 "Number of terminators folded to unconditional branches");

43 "Number of loop blocks deleted");

45 "Number of loop exiting edges deleted");

46

47

48

49

52 if (BranchInst *BI = dyn_cast(TI)) {

53 if (BI->isUnconditional())

54 return nullptr;

55 if (BI->getSuccessor(0) == BI->getSuccessor(1))

57 ConstantInt *Cond = dyn_cast(BI->getCondition());

59 return nullptr;

60 return Cond->isZero() ? BI->getSuccessor(1) : BI->getSuccessor(0);

61 }

62

63 if (SwitchInst *SI = dyn_cast(TI)) {

64 auto *CI = dyn_cast(SI->getCondition());

65 if (!CI)

66 return nullptr;

67 for (auto Case : SI->cases())

68 if (Case.getCaseValue() == CI)

69 return Case.getCaseSuccessor();

70 return SI->getDefaultDest();

71 }

72

73 return nullptr;

74}

75

76

78 Loop *LastLoop = nullptr) {

79 assert((!LastLoop || LastLoop->contains(FirstLoop->getHeader())) &&

80 "First loop is supposed to be inside of last loop!");

81 assert(FirstLoop->contains(BB) && "Must be a loop block!");

82 for (Loop *Current = FirstLoop; Current != LastLoop;

84 Current->removeBlockFromLoop(BB);

85}

86

87

88

91 Loop *Innermost = nullptr;

94 while (BBL && !BBL->contains(L.getHeader()))

96 if (BBL == &L)

98 if (!BBL)

99 continue;

101 Innermost = BBL;

102 }

103 return Innermost;

104}

105

106namespace {

107

108

109class ConstantTerminatorFoldingImpl {

110private:

119

120

121 bool HasIrreducibleCFG = false;

122

123

124

125

126

127

128

129

130 bool DeleteCurrentLoop = false;

131

132

133

135

136

138

139

141

142

144

146

147

148

150

151 void dump() const {

152 dbgs() << "Constant terminator folding for loop " << L << "\n";

153 dbgs() << "After terminator constant-folding, the loop will";

154 if (!DeleteCurrentLoop)

155 dbgs() << " not";

156 dbgs() << " be destroyed\n";

157 auto PrintOutVector = [&](const char *Message,

159 dbgs() << Message << "\n";

161 dbgs() << "\t" << BB->getName() << "\n";

162 };

163 auto PrintOutSet = [&](const char *Message,

165 dbgs() << Message << "\n";

167 dbgs() << "\t" << BB->getName() << "\n";

168 };

169 PrintOutVector("Blocks in which we can constant-fold terminator:",

170 FoldCandidates);

171 PrintOutSet("Live blocks from the original loop:", LiveLoopBlocks);

172 PrintOutVector("Dead blocks from the original loop:", DeadLoopBlocks);

173 PrintOutSet("Live exit blocks:", LiveExitBlocks);

174 PrintOutVector("Dead exit blocks:", DeadExitBlocks);

175 if (!DeleteCurrentLoop)

176 PrintOutSet("The following blocks will still be part of the loop:",

177 BlocksInLoopAfterFolding);

178 }

179

180

182 assert(DFS.isComplete() && "DFS is expected to be finished");

183

185 unsigned Current = 0;

187 RPO[*I] = Current++;

188

192 if (L.contains(Succ) && !LI.isLoopHeader(Succ) && RPO[BB] > RPO[Succ])

193

194

195

196 return true;

197 }

198 return false;

199 }

200

201

202

203 void analyze() {

205 assert(DFS.isComplete() && "DFS is expected to be finished");

206

207

208

209

210

211

212

213

214 if (hasIrreducibleCFG(DFS)) {

215 HasIrreducibleCFG = true;

216 return;

217 }

218

219

220 LiveLoopBlocks.insert(L.getHeader());

223

224

225 if (!LiveLoopBlocks.count(BB)) {

227 continue;

228 }

229

231

232

233

234

235

236 bool TakeFoldCandidate = TheOnlySucc && LI.getLoopFor(BB) == &L;

237 if (TakeFoldCandidate)

239

240

242 if (!TakeFoldCandidate || TheOnlySucc == Succ) {

243 if (L.contains(Succ))

244 LiveLoopBlocks.insert(Succ);

245 else

246 LiveExitBlocks.insert(Succ);

247 }

248 }

249

250

251

252 assert(L.getNumBlocks() == LiveLoopBlocks.size() + DeadLoopBlocks.size() &&

253 "Malformed block sets?");

254

255

256

257

259 L.getExitBlocks(ExitBlocks);

261 for (auto *ExitBlock : ExitBlocks)

262 if (!LiveExitBlocks.count(ExitBlock) &&

263 UniqueDeadExits.insert(ExitBlock).second &&

265 [this](BasicBlock *Pred) { return L.contains(Pred); }))

266 DeadExitBlocks.push_back(ExitBlock);

267

268

269

272 return false;

274 return !TheOnlySucc || TheOnlySucc == To || LI.getLoopFor(From) != &L;

275 };

276

277

278 DeleteCurrentLoop = !IsEdgeLive(L.getLoopLatch(), L.getHeader());

279

280

281

282 if (DeleteCurrentLoop)

283 return;

284

285

286

287 BlocksInLoopAfterFolding.insert(L.getLoopLatch());

288

289

290

291

292 auto BlockIsInLoop = [&](BasicBlock *BB) {

294 return BlocksInLoopAfterFolding.count(Succ) && IsEdgeLive(BB, Succ);

295 });

296 };

299 if (BlockIsInLoop(BB))

300 BlocksInLoopAfterFolding.insert(BB);

301 }

302

303 assert(BlocksInLoopAfterFolding.count(L.getHeader()) &&

304 "Header not in loop?");

305 assert(BlocksInLoopAfterFolding.size() <= LiveLoopBlocks.size() &&

306 "All blocks that stay in loop should be live!");

307 }

308

309

310

311

312

313

314

315

316

317

318

319

320

321

322

323

324

325

326

327

328

329

330

331

332

333

334

335

336

337

338

339

340

341

342

343

344 void handleDeadExits() {

345

346 if (DeadExitBlocks.empty())

347 return;

348

349

350

351 BasicBlock *Preheader = L.getLoopPreheader();

353 Preheader, Preheader->getTerminator(), &DT, &LI, MSSAU);

354

357 Builder.CreateSwitch(Builder.getInt32(0), NewPreheader);

359

360 unsigned DummyIdx = 1;

361 for (BasicBlock *BB : DeadExitBlocks) {

362

363

365 for (auto &PN : BB->phis())

367

368 if (auto *LandingPad = dyn_cast(BB->getFirstNonPHI()))

370

374 I->eraseFromParent();

375 }

376

377 assert(DummyIdx != 0 && "Too many dead exits!");

378 DummySwitch->addCase(Builder.getInt32(DummyIdx++), BB);

379 DTUpdates.push_back({DominatorTree::Insert, Preheader, BB});

380 ++NumLoopExitsDeleted;

381 }

382

383 assert(L.getLoopPreheader() == NewPreheader && "Malformed CFG?");

385

386

387

388

390

391

392

393 if (StillReachable != OuterLoop) {

396 for (auto *BB : L.blocks())

398 OuterLoop->removeChildLoop(&L);

399 if (StillReachable)

401 else

403

404

405

406

407 Loop *FixLCSSALoop = OuterLoop;

408 while (FixLCSSALoop->getParentLoop() != StillReachable)

410 assert(FixLCSSALoop && "Should be a loop!");

411

412 if (MSSAU)

413 MSSAU->applyUpdates(DTUpdates, DT, true);

414 else

416 DTUpdates.clear();

419 }

420 }

421

422 if (MSSAU) {

423

424 MSSAU->applyUpdates(DTUpdates, DT, true);

425 DTUpdates.clear();

428 }

429 }

430

431

432

433 void deleteDeadLoopBlocks() {

434 if (MSSAU) {

436 DeadLoopBlocks.end());

438 }

439

440

441

442

443

444

445

446 for (auto *BB : DeadLoopBlocks)

448 assert(LI.getLoopFor(BB) != &L && "Attempt to remove current loop!");

450 if (DL->isOutermost()) {

451 for (auto *PL = DL->getParentLoop(); PL; PL = PL->getParentLoop())

452 for (auto *BB : DL->getBlocks())

453 PL->removeBlockFromLoop(BB);

454 DL->getParentLoop()->removeChildLoop(DL);

456 }

458 }

459

460 for (auto *BB : DeadLoopBlocks) {

461 assert(BB != L.getHeader() &&

462 "Header of the current loop cannot be dead!");

464 << "\n");

466 }

467

468 detachDeadBlocks(DeadLoopBlocks, &DTUpdates, true);

470 DTUpdates.clear();

471 for (auto *BB : DeadLoopBlocks)

473

474 NumLoopBlocksDeleted += DeadLoopBlocks.size();

475 }

476

477

478

479 void foldTerminators() {

480 for (BasicBlock *BB : FoldCandidates) {

481 assert(LI.getLoopFor(BB) == &L && "Should be a loop block!");

483 assert(TheOnlySucc && "Should have one live successor!");

484

486 << " with an unconditional branch to the block "

487 << TheOnlySucc->getName() << "\n");

488

490

491 unsigned TheOnlySuccDuplicates = 0;

493 if (Succ != TheOnlySucc) {

494 DeadSuccessors.insert(Succ);

495

496

497 bool PreserveLCSSAPhi = L.contains(Succ);

499 if (MSSAU)

501 } else

502 ++TheOnlySuccDuplicates;

503

504 assert(TheOnlySuccDuplicates > 0 && "Should be!");

505

506

507

508 bool PreserveLCSSAPhi = L.contains(TheOnlySucc);

509 for (unsigned Dup = 1; Dup < TheOnlySuccDuplicates; ++Dup)

511 if (MSSAU && TheOnlySuccDuplicates > 1)

513

516 Builder.SetInsertPoint(Term);

517 Builder.CreateBr(TheOnlySucc);

518 Term->eraseFromParent();

519

520 for (auto *DeadSucc : DeadSuccessors)

521 DTUpdates.push_back({DominatorTree::Delete, BB, DeadSucc});

522

523 ++NumTerminatorsFolded;

524 }

525 }

526

527public:

531 : L(L), LI(LI), DT(DT), SE(SE), MSSAU(MSSAU), DFS(&L),

533 bool run() {

534 assert(L.getLoopLatch() && "Should be single latch!");

535

536

537

538 analyze();

540 (void)Header;

541

542 LLVM_DEBUG(dbgs() << "In function " << Header->getParent()->getName()

543 << ": ");

544

545 if (HasIrreducibleCFG) {

546 LLVM_DEBUG(dbgs() << "Loops with irreducible CFG are not supported!\n");

547 return false;

548 }

549

550

551 if (FoldCandidates.empty()) {

553 dbgs() << "No constant terminator folding candidates found in loop "

554 << Header->getName() << "\n");

555 return false;

556 }

557

558

559 if (DeleteCurrentLoop) {

562 << "Give up constant terminator folding in loop " << Header->getName()

563 << ": we don't currently support deletion of the current loop.\n");

564 return false;

565 }

566

567

568

569 if (BlocksInLoopAfterFolding.size() + DeadLoopBlocks.size() !=

570 L.getNumBlocks()) {

572 dbgs() << "Give up constant terminator folding in loop "

573 << Header->getName() << ": we don't currently"

574 " support blocks that are not dead, but will stop "

575 "being a part of the loop after constant-folding.\n");

576 return false;

577 }

578

579

580

581

582 if (!DeadExitBlocks.empty() && L.isLCSSAForm(DT, false)) {

583 assert(L.isLCSSAForm(DT, true) &&

584 "LCSSA broken not by tokens?");

585 LLVM_DEBUG(dbgs() << "Give up constant terminator folding in loop "

586 << Header->getName()

587 << ": tokens uses potentially break LCSSA form.\n");

588 return false;

589 }

590

592

594

595 LLVM_DEBUG(dbgs() << "Constant-folding " << FoldCandidates.size()

596 << " terminators in loop " << Header->getName() << "\n");

597

598 if (!DeadLoopBlocks.empty())

600

601

602 handleDeadExits();

603 foldTerminators();

604

605 if (!DeadLoopBlocks.empty()) {

606 LLVM_DEBUG(dbgs() << "Deleting " << DeadLoopBlocks.size()

607 << " dead blocks in loop " << Header->getName() << "\n");

608 deleteDeadLoopBlocks();

609 } else {

610

612 DTUpdates.clear();

613 }

614

617

618#ifndef NDEBUG

619

620#if defined(EXPENSIVE_CHECKS)

621 assert(DT.verify(DominatorTree::VerificationLevel::Full) &&

622 "DT broken after transform!");

623#else

624 assert(DT.verify(DominatorTree::VerificationLevel::Fast) &&

625 "DT broken after transform!");

626#endif

629#endif

630

631 return true;

632 }

633

634 bool foldingBreaksCurrentLoop() const {

635 return DeleteCurrentLoop;

636 }

637};

638}

639

640

641

645 bool &IsLoopDeleted) {

647 return false;

648

649

650

651 if (!L.getLoopLatch())

652 return false;

653

654 ConstantTerminatorFoldingImpl BranchFolder(L, LI, DT, SE, MSSAU);

656 IsLoopDeleted = Changed && BranchFolder.foldingBreaksCurrentLoop();

657 return Changed;

658}

659

663 bool Changed = false;

664 DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager);

665

666

668

670

671

673 if (!Succ)

674 continue;

675

678 continue;

679

680

682

685

686 Changed = true;

687 }

688

689 if (Changed)

691

692 return Changed;

693}

694

697 bool &IsLoopDeleted) {

698 bool Changed = false;

699

700

702

703 if (IsLoopDeleted)

704 return true;

705

706

708

709 if (Changed)

711

712 return Changed;

713}

714

718 std::optional MSSAU;

721 bool DeleteCurrentLoop = false;

723 DeleteCurrentLoop))

725

726 if (DeleteCurrentLoop)

728

732 return PA;

733}

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

BlockVerifier::State From

DenseMap< Block *, BlockRelaxAux > Blocks

This header provides classes for managing a pipeline of passes over loops in LLVM IR.

static BasicBlock * getOnlyLiveSuccessor(BasicBlock *BB)

If BB is a switch or a conditional branch, but only one of its successors can be reached from this bl...

static bool constantFoldTerminators(Loop &L, DominatorTree &DT, LoopInfo &LI, ScalarEvolution &SE, MemorySSAUpdater *MSSAU, bool &IsLoopDeleted)

Turn branches and switches with known constant conditions into unconditional branches.

static Loop * getInnermostLoopFor(SmallPtrSetImpl< BasicBlock * > &BBs, Loop &L, LoopInfo &LI)

Find innermost loop that contains at least one block from BBs and contains the header of loop L.

static bool mergeBlocksIntoPredecessors(Loop &L, DominatorTree &DT, LoopInfo &LI, MemorySSAUpdater *MSSAU, ScalarEvolution &SE)

static bool simplifyLoopCFG(Loop &L, DominatorTree &DT, LoopInfo &LI, ScalarEvolution &SE, MemorySSAUpdater *MSSAU, bool &IsLoopDeleted)

static cl::opt< bool > EnableTermFolding("enable-loop-simplifycfg-term-folding", cl::init(true))

static void removeBlockFromLoops(BasicBlock *BB, Loop *FirstLoop, Loop *LastLoop=nullptr)

Removes BB from all loops from [FirstLoop, LastLoop) in parent chain.

This file exposes an interface to building/using memory SSA to walk memory instructions using a use/d...

const SmallVectorImpl< MachineOperand > & Cond

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

This file defines the SmallVector class.

This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...

#define STATISTIC(VARNAME, DESC)

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

LLVM Basic Block Representation.

iterator_range< const_phi_iterator > phis() const

Returns a range that iterates over the phis in the basic block.

const Instruction * getFirstNonPHI() const

Returns a pointer to the first instruction in this block that is not a PHINode instruction.

const BasicBlock * getSinglePredecessor() const

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

const BasicBlock * getSingleSuccessor() const

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

LLVMContext & getContext() const

Get the context in which this basic block lives.

const Instruction * getTerminator() const LLVM_READONLY

Returns the terminator instruction if the block is well formed or null if the block is not well forme...

void removePredecessor(BasicBlock *Pred, bool KeepOneInputPHIs=false)

Update PHI nodes in this BasicBlock before removal of predecessor Pred.

Conditional or Unconditional Branch instruction.

This is the shared class of boolean and integer constants.

void deleteBB(BasicBlock *DelBB)

Delete DelBB.

bool verify(VerificationLevel VL=VerificationLevel::Full) const

verify - checks if the tree is correct.

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

bool isReachableFromEntry(const Use &U) const

Provide an overload for a Use.

void applyUpdates(ArrayRef< UpdateT > Updates)

Submit updates to all available trees.

This provides a uniform API for creating instructions and inserting them into a basic block: either a...

InstListType::iterator eraseFromParent()

This method unlinks 'this' from the containing basic block and deletes it.

BasicBlock * getSuccessor(unsigned Idx) const LLVM_READONLY

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

This class provides an interface for updating the loop pass manager based on mutations to the loop ne...

void markLoopAsDeleted(Loop &L, llvm::StringRef Name)

Loop passes should use this method to indicate they have deleted a loop from the nest.

bool contains(const LoopT *L) const

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

BlockT * getHeader() const

unsigned getLoopDepth() const

Return the nesting level of this loop.

void addChildLoop(LoopT *NewChild)

Add the specified loop to be a child of this loop.

LoopT * getParentLoop() const

Return the parent loop if it exists or nullptr for top level loops.

Store the result of a depth first search within basic blocks contained by a single loop.

RPOIterator beginRPO() const

Reverse iterate over the cached postorder blocks.

bool isComplete() const

Return true if postorder numbers are assigned to all loop blocks.

POIterator beginPostorder() const

Iterate over the cached postorder blocks.

POIterator endPostorder() const

void perform(const LoopInfo *LI)

Traverse the loop blocks and store the DFS result.

RPOIterator endRPO() const

void verify(const DominatorTreeBase< BlockT, false > &DomTree) const

void addTopLevelLoop(LoopT *New)

This adds the specified loop to the collection of top-level loops.

void removeBlock(BlockT *BB)

This method completely removes BB from all data structures, including all of the Loop objects it is n...

bool isLoopHeader(const BlockT *BB) const

void changeLoopFor(BlockT *BB, LoopT *L)

Change the top-level loop that contains BB to the specified loop.

LoopT * getLoopFor(const BlockT *BB) const

Return the inner most loop that BB lives in.

void erase(Loop *L)

Update LoopInfo after removing the last backedge from a loop.

PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM, LoopStandardAnalysisResults &AR, LPMUpdater &U)

Represents a single loop in the control flow graph.

An analysis that produces MemorySSA for a function.

MemorySSA * getMemorySSA() const

Get handle on MemorySSA.

void removeEdge(BasicBlock *From, BasicBlock *To)

Update the MemoryPhi in To following an edge deletion between From and To.

void removeDuplicatePhiEdgesBetween(const BasicBlock *From, const BasicBlock *To)

Update the MemoryPhi in To to have a single incoming edge from From, following a CFG change that repl...

void removeBlocks(const SmallSetVector< BasicBlock *, 8 > &DeadBlocks)

Remove all MemoryAcceses in a set of BasicBlocks about to be deleted.

void applyUpdates(ArrayRef< CFGUpdate > Updates, DominatorTree &DT, bool UpdateDTFirst=false)

Apply CFG updates, analogous with the DT edge updates.

void verifyMemorySSA(VerificationLevel=VerificationLevel::Fast) const

Verify that MemorySSA is self consistent (IE definitions dominate all uses, uses appear in the right ...

static PoisonValue * get(Type *T)

Static factory methods - Return an 'poison' object of the specified type.

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.

The main scalar evolution driver.

void forgetTopmostLoop(const Loop *L)

void forgetBlockAndLoopDispositions(Value *V=nullptr)

Called when the client has changed the disposition of values in a loop or block.

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.

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.

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

reference emplace_back(ArgTypes &&... Args)

void push_back(const T &Elt)

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

void addCase(ConstantInt *OnVal, BasicBlock *Dest)

Add an entry to the switch instruction.

StringRef getName() const

Return a constant reference to the value's name.

initializer< Ty > init(const Ty &Val)

PointerTypeMap run(const Module &M)

Compute the PointerTypeMap for the module M.

This is an optimization pass for GlobalISel generic memory operations.

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

bool all_of(R &&range, UnaryPredicate P)

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

void detachDeadBlocks(ArrayRef< BasicBlock * > BBs, SmallVectorImpl< DominatorTree::UpdateType > *Updates, bool KeepOneInputPHIs=false)

Replace contents of every block in BBs with single unreachable instruction.

auto successors(const MachineBasicBlock *BB)

bool formLCSSARecursively(Loop &L, const DominatorTree &DT, const LoopInfo *LI, ScalarEvolution *SE)

Put a loop nest into LCSSA form.

bool any_of(R &&range, UnaryPredicate P)

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

raw_ostream & dbgs()

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

bool VerifyMemorySSA

Enables verification of MemorySSA.

bool MergeBlockIntoPredecessor(BasicBlock *BB, DomTreeUpdater *DTU=nullptr, LoopInfo *LI=nullptr, MemorySSAUpdater *MSSAU=nullptr, MemoryDependenceResults *MemDep=nullptr, bool PredecessorWithTwoSuccessors=false, DominatorTree *DT=nullptr)

Attempts to merge a block into its predecessor, if possible.

BasicBlock * SplitBlock(BasicBlock *Old, BasicBlock::iterator SplitPt, DominatorTree *DT, LoopInfo *LI=nullptr, MemorySSAUpdater *MSSAU=nullptr, const Twine &BBName="", bool Before=false)

Split the specified block at the specified instruction.

PreservedAnalyses getLoopPassPreservedAnalyses()

Returns the minimum set of Analyses that all loop passes must preserve.

auto predecessors(const MachineBasicBlock *BB)

The adaptor from a function pass to a loop pass computes these analyses and makes them available to t...