LLVM 24.0.0git
LoopIterator.h
Go to the documentation of this file.
1//===--------- LoopIterator.h - Iterate over loop blocks --------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8// This file defines iterators to visit the basic blocks within a loop.
9//
10// These iterators currently visit blocks within subloops as well.
11// Unfortunately we have no efficient way of summarizing loop exits which would
12// allow skipping subloops during traversal.
13//
14// If you want to visit all blocks in a loop and don't need an ordered traveral,
15// use Loop::block_begin() instead.
16//
17// This is intentionally designed to work with ill-formed loops in which the
18// backedge has been deleted. The only prerequisite is that all blocks
19// contained within the loop according to the most recent LoopInfo analysis are
20// reachable from the loop header.
21//===----------------------------------------------------------------------===//
22
23#ifndef LLVM_ANALYSIS_LOOPITERATOR_H
24#define LLVM_ANALYSIS_LOOPITERATOR_H
25
28
29namespace llvm {
30
32
33/// Store the result of a depth first search within basic blocks contained by a
34/// single loop.
35///
36/// TODO: This could be generalized for any CFG region, or the entire CFG.
38public:
39 /// Postorder list iterators.
40 typedef std::vector<BasicBlock*>::const_iterator POIterator;
41 typedef std::vector<BasicBlock*>::const_reverse_iterator RPOIterator;
42
43 friend class LoopBlocksTraversal;
44
45private:
46 Loop *L;
47
48 /// Map each block to its postorder number. A block is only mapped after it is
49 /// preorder visited by DFS. It's postorder number is initially zero and set
50 /// to nonzero after it is finished by postorder traversal.
52 std::vector<BasicBlock*> PostBlocks;
53
54public:
55 LoopBlocksDFS(Loop *Container) :
56 L(Container), PostNumbers(NextPowerOf2(Container->getNumBlocks())) {
57 PostBlocks.reserve(Container->getNumBlocks());
58 }
59
60 Loop *getLoop() const { return L; }
61
62 /// Traverse the loop blocks and store the DFS result.
63 LLVM_ABI void perform(const LoopInfo *LI);
64
65 /// Return true if postorder numbers are assigned to all loop blocks.
66 bool isComplete() const { return PostBlocks.size() == L->getNumBlocks(); }
67
68 /// Iterate over the cached postorder blocks.
70 assert(isComplete() && "bad loop DFS");
71 return PostBlocks.begin();
72 }
73 POIterator endPostorder() const { return PostBlocks.end(); }
74
75 /// Reverse iterate over the cached postorder blocks.
77 assert(isComplete() && "bad loop DFS");
78 return PostBlocks.rbegin();
79 }
80 RPOIterator endRPO() const { return PostBlocks.rend(); }
81
82 /// Return true if this block has been preorder visited.
83 bool hasPreorder(BasicBlock *BB) const { return PostNumbers.count(BB); }
84
85 /// Return true if this block has a postorder number.
86 bool hasPostorder(BasicBlock *BB) const {
87 auto I = PostNumbers.find(BB);
88 return I != PostNumbers.end() && I->second;
89 }
90
91 /// Get a block's postorder number.
92 unsigned getPostorder(BasicBlock *BB) const {
93 auto I = PostNumbers.find(BB);
94 assert(I != PostNumbers.end() && "block not visited by DFS");
95 assert(I->second && "block not finished by DFS");
96 return I->second;
97 }
98
99 /// Get a block's reverse postorder number.
100 unsigned getRPO(BasicBlock *BB) const {
101 return 1 + PostBlocks.size() - getPostorder(BB);
102 }
103
104 void clear() {
105 PostNumbers.clear();
106 PostBlocks.clear();
107 }
108};
109
110/// Wrapper class to LoopBlocksDFS that provides a standard begin()/end()
111/// interface for the DFS reverse post-order traversal of blocks in a loop body.
113private:
114 LoopBlocksDFS DFS;
115
116public:
117 LoopBlocksRPO(Loop *Container) : DFS(Container) {}
118
119 /// Traverse the loop blocks and store the DFS result.
120 void perform(const LoopInfo *LI) {
121 DFS.perform(LI);
122 }
123
124 /// Reverse iterate over the cached postorder blocks.
125 LoopBlocksDFS::RPOIterator begin() const { return DFS.beginRPO(); }
126 LoopBlocksDFS::RPOIterator end() const { return DFS.endRPO(); }
127};
128
129/// Traverse the blocks in a loop using a depth-first search.
131 : public PostOrderTraversalBase<LoopBlocksTraversal,
132 GraphTraits<Function *>> {
133 LoopBlocksDFS &DFS;
134 const LoopInfo *LI;
135
136public:
138 : DFS(Storage), LI(LInfo) {}
139
140 /// Postorder traversal over the graph. This only needs to be done once.
141 /// PostOrderTraversalBase "automatically" calls back to insertEdge and
142 /// finishPostorder to record the DFS result.
143 iterator begin() {
144 assert(DFS.PostBlocks.empty() && "Need clear DFS result before traversing");
145 assert(DFS.L->getNumBlocks() && "cannot handle an empty graph");
146 init(DFS.L->getHeader());
148 }
149 iterator end() { return PostOrderTraversalBase::end(); }
150
151 /// Called upon reaching a block via a CFG edge. If this block is contained
152 /// in the loop and has not been visited, then mark it preorder visited and
153 /// return true (i.e., traverse the edge).
154 ///
155 /// TODO: If anyone is interested, we could record preorder numbers here.
156 bool insertEdge(std::optional<BasicBlock *> /*From*/, BasicBlock *BB) {
157 if (!DFS.L->contains(LI->getLoopFor(BB)))
158 return false;
159
160 return DFS.PostNumbers.insert(std::make_pair(BB, 0)).second;
161 }
162
163 /// Called each time the iterator advances, indicating a block's postorder.
165 assert(DFS.PostNumbers.count(BB) && "Loop DFS skipped preorder");
166 DFS.PostBlocks.push_back(BB);
167 DFS.PostNumbers[BB] = DFS.PostBlocks.size();
168 }
169};
170
171} // End namespace llvm
172
173#endif
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define LLVM_ABI
Definition Compiler.h:215
#define I(x, y, z)
Definition MD5.cpp:57
This file builds on the ADT/GraphTraits.h file to build a generic graph post order iterator.
LLVM Basic Block Representation.
Definition BasicBlock.h:62
unsigned getNumBlocks() const
Get the number of blocks in this loop in constant time.
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 hasPreorder(BasicBlock *BB) const
Return true if this block has been preorder visited.
unsigned getPostorder(BasicBlock *BB) const
Get a block's postorder number.
std::vector< BasicBlock * >::const_reverse_iterator RPOIterator
bool hasPostorder(BasicBlock *BB) const
Return true if this block has a postorder number.
unsigned getRPO(BasicBlock *BB) const
Get a block's reverse postorder number.
Loop * getLoop() const
LoopBlocksDFS(Loop *Container)
friend class LoopBlocksTraversal
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
std::vector< BasicBlock * >::const_iterator POIterator
Postorder list iterators.
LLVM_ABI void perform(const LoopInfo *LI)
Traverse the loop blocks and store the DFS result.
RPOIterator endRPO() const
LoopBlocksDFS::RPOIterator end() const
LoopBlocksDFS::RPOIterator begin() const
Reverse iterate over the cached postorder blocks.
LoopBlocksRPO(Loop *Container)
void perform(const LoopInfo *LI)
Traverse the loop blocks and store the DFS result.
Traverse the blocks in a loop using a depth-first search.
iterator begin()
Postorder traversal over the graph.
bool insertEdge(std::optional< BasicBlock * >, BasicBlock *BB)
Called upon reaching a block via a CFG edge.
void finishPostorder(BasicBlock *BB)
Called each time the iterator advances, indicating a block's postorder.
LoopBlocksTraversal(LoopBlocksDFS &Storage, const LoopInfo *LInfo)
Represents a single loop in the control flow graph.
Definition LoopInfo.h:40
This is an optimization pass for GlobalISel generic memory operations.
constexpr uint64_t NextPowerOf2(uint64_t A)
Returns the next power of two (in 64-bits) that is strictly greater than A.
Definition MathExtras.h:368