File indexing completed on 2026-05-10 08:43:05
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028 #ifndef LLVM_ADT_GENERICCYCLEINFO_H
0029 #define LLVM_ADT_GENERICCYCLEINFO_H
0030
0031 #include "llvm/ADT/DenseSet.h"
0032 #include "llvm/ADT/GenericSSAContext.h"
0033 #include "llvm/ADT/GraphTraits.h"
0034 #include "llvm/ADT/SetVector.h"
0035 #include "llvm/Support/Debug.h"
0036 #include "llvm/Support/raw_ostream.h"
0037
0038 namespace llvm {
0039
0040 template <typename ContextT> class GenericCycleInfo;
0041 template <typename ContextT> class GenericCycleInfoCompute;
0042
0043
0044 template <typename ContextT> class GenericCycle {
0045 public:
0046 using BlockT = typename ContextT::BlockT;
0047 using FunctionT = typename ContextT::FunctionT;
0048 template <typename> friend class GenericCycleInfo;
0049 template <typename> friend class GenericCycleInfoCompute;
0050
0051 private:
0052
0053
0054 GenericCycle *ParentCycle = nullptr;
0055
0056
0057
0058
0059 SmallVector<BlockT *, 1> Entries;
0060
0061
0062 std::vector<std::unique_ptr<GenericCycle>> Children;
0063
0064
0065
0066 using BlockSetVectorT = SetVector<BlockT *, SmallVector<BlockT *, 8>,
0067 DenseSet<const BlockT *>, 8>;
0068 BlockSetVectorT Blocks;
0069
0070
0071
0072
0073
0074
0075 unsigned Depth = 0;
0076
0077
0078 mutable SmallVector<BlockT *, 4> ExitBlocksCache;
0079
0080 void clear() {
0081 Entries.clear();
0082 Children.clear();
0083 Blocks.clear();
0084 Depth = 0;
0085 ParentCycle = nullptr;
0086 clearCache();
0087 }
0088
0089 void appendEntry(BlockT *Block) {
0090 Entries.push_back(Block);
0091 clearCache();
0092 }
0093
0094 void appendBlock(BlockT *Block) {
0095 Blocks.insert(Block);
0096 clearCache();
0097 }
0098
0099 GenericCycle(const GenericCycle &) = delete;
0100 GenericCycle &operator=(const GenericCycle &) = delete;
0101 GenericCycle(GenericCycle &&Rhs) = delete;
0102 GenericCycle &operator=(GenericCycle &&Rhs) = delete;
0103
0104 public:
0105 GenericCycle() = default;
0106
0107
0108 bool isReducible() const { return Entries.size() == 1; }
0109
0110 BlockT *getHeader() const { return Entries[0]; }
0111
0112 const SmallVectorImpl<BlockT *> & getEntries() const {
0113 return Entries;
0114 }
0115
0116
0117
0118
0119 void clearCache() const { ExitBlocksCache.clear(); }
0120
0121
0122 bool isEntry(const BlockT *Block) const {
0123 return is_contained(Entries, Block);
0124 }
0125
0126
0127 void setSingleEntry(BlockT *Block) {
0128 assert(contains(Block));
0129 Entries.clear();
0130 Entries.push_back(Block);
0131 clearCache();
0132 }
0133
0134
0135 bool contains(const BlockT *Block) const { return Blocks.contains(Block); }
0136
0137
0138
0139
0140
0141 bool contains(const GenericCycle *C) const;
0142
0143 const GenericCycle *getParentCycle() const { return ParentCycle; }
0144 GenericCycle *getParentCycle() { return ParentCycle; }
0145 unsigned getDepth() const { return Depth; }
0146
0147
0148
0149
0150
0151 void getExitBlocks(SmallVectorImpl<BlockT *> &TmpStorage) const;
0152
0153
0154
0155 void getExitingBlocks(SmallVectorImpl<BlockT *> &TmpStorage) const;
0156
0157
0158
0159
0160
0161 BlockT *getCyclePreheader() const;
0162
0163
0164
0165 BlockT *getCyclePredecessor() const;
0166
0167 void verifyCycle() const;
0168 void verifyCycleNest() const;
0169
0170
0171
0172 using const_child_iterator_base =
0173 typename std::vector<std::unique_ptr<GenericCycle>>::const_iterator;
0174 struct const_child_iterator
0175 : iterator_adaptor_base<const_child_iterator, const_child_iterator_base> {
0176 using Base =
0177 iterator_adaptor_base<const_child_iterator, const_child_iterator_base>;
0178
0179 const_child_iterator() = default;
0180 explicit const_child_iterator(const_child_iterator_base I) : Base(I) {}
0181
0182 const const_child_iterator_base &wrapped() { return Base::wrapped(); }
0183 GenericCycle *operator*() const { return Base::I->get(); }
0184 };
0185
0186 const_child_iterator child_begin() const {
0187 return const_child_iterator{Children.begin()};
0188 }
0189 const_child_iterator child_end() const {
0190 return const_child_iterator{Children.end()};
0191 }
0192 size_t getNumChildren() const { return Children.size(); }
0193 iterator_range<const_child_iterator> children() const {
0194 return llvm::make_range(const_child_iterator{Children.begin()},
0195 const_child_iterator{Children.end()});
0196 }
0197
0198
0199
0200
0201 using const_block_iterator = typename BlockSetVectorT::const_iterator;
0202
0203 const_block_iterator block_begin() const {
0204 return const_block_iterator{Blocks.begin()};
0205 }
0206 const_block_iterator block_end() const {
0207 return const_block_iterator{Blocks.end()};
0208 }
0209 size_t getNumBlocks() const { return Blocks.size(); }
0210 iterator_range<const_block_iterator> blocks() const {
0211 return llvm::make_range(block_begin(), block_end());
0212 }
0213
0214
0215
0216
0217 using const_entry_iterator =
0218 typename SmallVectorImpl<BlockT *>::const_iterator;
0219 const_entry_iterator entry_begin() const { return Entries.begin(); }
0220 const_entry_iterator entry_end() const { return Entries.end(); }
0221 size_t getNumEntries() const { return Entries.size(); }
0222 iterator_range<const_entry_iterator> entries() const {
0223 return llvm::make_range(entry_begin(), entry_end());
0224 }
0225 using const_reverse_entry_iterator =
0226 typename SmallVectorImpl<BlockT *>::const_reverse_iterator;
0227 const_reverse_entry_iterator entry_rbegin() const { return Entries.rbegin(); }
0228 const_reverse_entry_iterator entry_rend() const { return Entries.rend(); }
0229
0230
0231 Printable printEntries(const ContextT &Ctx) const {
0232 return Printable([this, &Ctx](raw_ostream &Out) {
0233 bool First = true;
0234 for (auto *Entry : Entries) {
0235 if (!First)
0236 Out << ' ';
0237 First = false;
0238 Out << Ctx.print(Entry);
0239 }
0240 });
0241 }
0242
0243 Printable print(const ContextT &Ctx) const {
0244 return Printable([this, &Ctx](raw_ostream &Out) {
0245 Out << "depth=" << Depth << ": entries(" << printEntries(Ctx) << ')';
0246
0247 for (auto *Block : Blocks) {
0248 if (isEntry(Block))
0249 continue;
0250
0251 Out << ' ' << Ctx.print(Block);
0252 }
0253 });
0254 }
0255 };
0256
0257
0258 template <typename ContextT> class GenericCycleInfo {
0259 public:
0260 using BlockT = typename ContextT::BlockT;
0261 using CycleT = GenericCycle<ContextT>;
0262 using FunctionT = typename ContextT::FunctionT;
0263 template <typename> friend class GenericCycle;
0264 template <typename> friend class GenericCycleInfoCompute;
0265
0266 private:
0267 ContextT Context;
0268
0269
0270 DenseMap<BlockT *, CycleT *> BlockMap;
0271
0272
0273 DenseMap<BlockT *, CycleT *> BlockMapTopLevel;
0274
0275
0276
0277
0278
0279 std::vector<std::unique_ptr<CycleT>> TopLevelCycles;
0280
0281
0282
0283
0284
0285 void moveTopLevelCycleToNewParent(CycleT *NewParent, CycleT *Child);
0286
0287 public:
0288 GenericCycleInfo() = default;
0289 GenericCycleInfo(GenericCycleInfo &&) = default;
0290 GenericCycleInfo &operator=(GenericCycleInfo &&) = default;
0291
0292 void clear();
0293 void compute(FunctionT &F);
0294 void splitCriticalEdge(BlockT *Pred, BlockT *Succ, BlockT *New);
0295
0296 const FunctionT *getFunction() const { return Context.getFunction(); }
0297 const ContextT &getSSAContext() const { return Context; }
0298
0299 CycleT *getCycle(const BlockT *Block) const;
0300 CycleT *getSmallestCommonCycle(CycleT *A, CycleT *B) const;
0301 unsigned getCycleDepth(const BlockT *Block) const;
0302 CycleT *getTopLevelParentCycle(BlockT *Block);
0303
0304
0305
0306
0307
0308 void addBlockToCycle(BlockT *Block, CycleT *Cycle);
0309
0310
0311
0312 void verifyCycleNest(bool VerifyFull = false) const;
0313 void verify() const;
0314 void print(raw_ostream &Out) const;
0315 void dump() const { print(dbgs()); }
0316 Printable print(const CycleT *Cycle) { return Cycle->print(Context); }
0317
0318
0319
0320
0321 using const_toplevel_iterator_base =
0322 typename std::vector<std::unique_ptr<CycleT>>::const_iterator;
0323 struct const_toplevel_iterator
0324 : iterator_adaptor_base<const_toplevel_iterator,
0325 const_toplevel_iterator_base> {
0326 using Base = iterator_adaptor_base<const_toplevel_iterator,
0327 const_toplevel_iterator_base>;
0328
0329 const_toplevel_iterator() = default;
0330 explicit const_toplevel_iterator(const_toplevel_iterator_base I)
0331 : Base(I) {}
0332
0333 const const_toplevel_iterator_base &wrapped() { return Base::wrapped(); }
0334 CycleT *operator*() const { return Base::I->get(); }
0335 };
0336
0337 const_toplevel_iterator toplevel_begin() const {
0338 return const_toplevel_iterator{TopLevelCycles.begin()};
0339 }
0340 const_toplevel_iterator toplevel_end() const {
0341 return const_toplevel_iterator{TopLevelCycles.end()};
0342 }
0343
0344 iterator_range<const_toplevel_iterator> toplevel_cycles() const {
0345 return llvm::make_range(const_toplevel_iterator{TopLevelCycles.begin()},
0346 const_toplevel_iterator{TopLevelCycles.end()});
0347 }
0348
0349 };
0350
0351
0352 template <typename CycleRefT, typename ChildIteratorT> struct CycleGraphTraits {
0353 using NodeRef = CycleRefT;
0354
0355 using nodes_iterator = ChildIteratorT;
0356 using ChildIteratorType = nodes_iterator;
0357
0358 static NodeRef getEntryNode(NodeRef Graph) { return Graph; }
0359
0360 static ChildIteratorType child_begin(NodeRef Ref) {
0361 return Ref->child_begin();
0362 }
0363 static ChildIteratorType child_end(NodeRef Ref) { return Ref->child_end(); }
0364
0365
0366
0367
0368
0369
0370
0371
0372
0373
0374
0375
0376
0377
0378
0379
0380
0381
0382
0383
0384 };
0385
0386 template <typename BlockT>
0387 struct GraphTraits<const GenericCycle<BlockT> *>
0388 : CycleGraphTraits<const GenericCycle<BlockT> *,
0389 typename GenericCycle<BlockT>::const_child_iterator> {};
0390 template <typename BlockT>
0391 struct GraphTraits<GenericCycle<BlockT> *>
0392 : CycleGraphTraits<GenericCycle<BlockT> *,
0393 typename GenericCycle<BlockT>::const_child_iterator> {};
0394
0395 }
0396
0397 #endif