File indexing completed on 2026-05-10 08:43:14
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023 #ifndef LLVM_ANALYSIS_LOOPITERATOR_H
0024 #define LLVM_ANALYSIS_LOOPITERATOR_H
0025
0026 #include "llvm/ADT/PostOrderIterator.h"
0027 #include "llvm/Analysis/LoopInfo.h"
0028
0029 namespace llvm {
0030
0031 class LoopBlocksTraversal;
0032
0033
0034
0035
0036
0037
0038
0039
0040 struct LoopBodyTraits {
0041 using NodeRef = std::pair<const Loop *, BasicBlock *>;
0042
0043
0044
0045 class WrappedSuccIterator
0046 : public iterator_adaptor_base<
0047 WrappedSuccIterator, succ_iterator,
0048 typename std::iterator_traits<succ_iterator>::iterator_category,
0049 NodeRef, std::ptrdiff_t, NodeRef *, NodeRef> {
0050 using BaseT = iterator_adaptor_base<
0051 WrappedSuccIterator, succ_iterator,
0052 typename std::iterator_traits<succ_iterator>::iterator_category,
0053 NodeRef, std::ptrdiff_t, NodeRef *, NodeRef>;
0054
0055 const Loop *L;
0056
0057 public:
0058 WrappedSuccIterator(succ_iterator Begin, const Loop *L)
0059 : BaseT(Begin), L(L) {}
0060
0061 NodeRef operator*() const { return {L, *I}; }
0062 };
0063
0064 struct LoopBodyFilter {
0065 bool operator()(NodeRef N) const {
0066 const Loop *L = N.first;
0067 return N.second != L->getHeader() && L->contains(N.second);
0068 }
0069 };
0070
0071 using ChildIteratorType =
0072 filter_iterator<WrappedSuccIterator, LoopBodyFilter>;
0073
0074 static NodeRef getEntryNode(const Loop &G) { return {&G, G.getHeader()}; }
0075
0076 static ChildIteratorType child_begin(NodeRef Node) {
0077 return make_filter_range(make_range<WrappedSuccIterator>(
0078 {succ_begin(Node.second), Node.first},
0079 {succ_end(Node.second), Node.first}),
0080 LoopBodyFilter{})
0081 .begin();
0082 }
0083
0084 static ChildIteratorType child_end(NodeRef Node) {
0085 return make_filter_range(make_range<WrappedSuccIterator>(
0086 {succ_begin(Node.second), Node.first},
0087 {succ_end(Node.second), Node.first}),
0088 LoopBodyFilter{})
0089 .end();
0090 }
0091 };
0092
0093
0094
0095
0096
0097 class LoopBlocksDFS {
0098 public:
0099
0100 typedef std::vector<BasicBlock*>::const_iterator POIterator;
0101 typedef std::vector<BasicBlock*>::const_reverse_iterator RPOIterator;
0102
0103 friend class LoopBlocksTraversal;
0104
0105 private:
0106 Loop *L;
0107
0108
0109
0110
0111 DenseMap<BasicBlock*, unsigned> PostNumbers;
0112 std::vector<BasicBlock*> PostBlocks;
0113
0114 public:
0115 LoopBlocksDFS(Loop *Container) :
0116 L(Container), PostNumbers(NextPowerOf2(Container->getNumBlocks())) {
0117 PostBlocks.reserve(Container->getNumBlocks());
0118 }
0119
0120 Loop *getLoop() const { return L; }
0121
0122
0123 void perform(const LoopInfo *LI);
0124
0125
0126 bool isComplete() const { return PostBlocks.size() == L->getNumBlocks(); }
0127
0128
0129 POIterator beginPostorder() const {
0130 assert(isComplete() && "bad loop DFS");
0131 return PostBlocks.begin();
0132 }
0133 POIterator endPostorder() const { return PostBlocks.end(); }
0134
0135
0136 RPOIterator beginRPO() const {
0137 assert(isComplete() && "bad loop DFS");
0138 return PostBlocks.rbegin();
0139 }
0140 RPOIterator endRPO() const { return PostBlocks.rend(); }
0141
0142
0143 bool hasPreorder(BasicBlock *BB) const { return PostNumbers.count(BB); }
0144
0145
0146 bool hasPostorder(BasicBlock *BB) const {
0147 DenseMap<BasicBlock*, unsigned>::const_iterator I = PostNumbers.find(BB);
0148 return I != PostNumbers.end() && I->second;
0149 }
0150
0151
0152 unsigned getPostorder(BasicBlock *BB) const {
0153 DenseMap<BasicBlock*, unsigned>::const_iterator I = PostNumbers.find(BB);
0154 assert(I != PostNumbers.end() && "block not visited by DFS");
0155 assert(I->second && "block not finished by DFS");
0156 return I->second;
0157 }
0158
0159
0160 unsigned getRPO(BasicBlock *BB) const {
0161 return 1 + PostBlocks.size() - getPostorder(BB);
0162 }
0163
0164 void clear() {
0165 PostNumbers.clear();
0166 PostBlocks.clear();
0167 }
0168 };
0169
0170
0171
0172 class LoopBlocksRPO {
0173 private:
0174 LoopBlocksDFS DFS;
0175
0176 public:
0177 LoopBlocksRPO(Loop *Container) : DFS(Container) {}
0178
0179
0180 void perform(const LoopInfo *LI) {
0181 DFS.perform(LI);
0182 }
0183
0184
0185 LoopBlocksDFS::RPOIterator begin() const { return DFS.beginRPO(); }
0186 LoopBlocksDFS::RPOIterator end() const { return DFS.endRPO(); }
0187 };
0188
0189
0190 template<> class po_iterator_storage<LoopBlocksTraversal, true> {
0191 LoopBlocksTraversal &LBT;
0192 public:
0193 po_iterator_storage(LoopBlocksTraversal &lbs) : LBT(lbs) {}
0194
0195 bool insertEdge(std::optional<BasicBlock *> From, BasicBlock *To);
0196 void finishPostorder(BasicBlock *BB);
0197 };
0198
0199
0200 class LoopBlocksTraversal {
0201 public:
0202
0203 typedef po_iterator<BasicBlock*, LoopBlocksTraversal, true> POTIterator;
0204
0205 private:
0206 LoopBlocksDFS &DFS;
0207 const LoopInfo *LI;
0208
0209 public:
0210 LoopBlocksTraversal(LoopBlocksDFS &Storage, const LoopInfo *LInfo) :
0211 DFS(Storage), LI(LInfo) {}
0212
0213
0214
0215
0216 POTIterator begin() {
0217 assert(DFS.PostBlocks.empty() && "Need clear DFS result before traversing");
0218 assert(DFS.L->getNumBlocks() && "po_iterator cannot handle an empty graph");
0219 return po_ext_begin(DFS.L->getHeader(), *this);
0220 }
0221 POTIterator end() {
0222
0223 return po_ext_end(DFS.L->getHeader(), *this);
0224 }
0225
0226
0227
0228
0229
0230
0231 bool visitPreorder(BasicBlock *BB) {
0232 if (!DFS.L->contains(LI->getLoopFor(BB)))
0233 return false;
0234
0235 return DFS.PostNumbers.insert(std::make_pair(BB, 0)).second;
0236 }
0237
0238
0239
0240 void finishPostorder(BasicBlock *BB) {
0241 assert(DFS.PostNumbers.count(BB) && "Loop DFS skipped preorder");
0242 DFS.PostBlocks.push_back(BB);
0243 DFS.PostNumbers[BB] = DFS.PostBlocks.size();
0244 }
0245 };
0246
0247 inline bool po_iterator_storage<LoopBlocksTraversal, true>::insertEdge(
0248 std::optional<BasicBlock *> From, BasicBlock *To) {
0249 return LBT.visitPreorder(To);
0250 }
0251
0252 inline void po_iterator_storage<LoopBlocksTraversal, true>::
0253 finishPostorder(BasicBlock *BB) {
0254 LBT.finishPostorder(BB);
0255 }
0256
0257 }
0258
0259 #endif