File indexing completed on 2026-05-10 08:43:16
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
0029
0030
0031
0032
0033
0034
0035
0036 #ifndef LLVM_ANALYSIS_REGIONINFO_H
0037 #define LLVM_ANALYSIS_REGIONINFO_H
0038
0039 #include "llvm/ADT/DenseMap.h"
0040 #include "llvm/ADT/DepthFirstIterator.h"
0041 #include "llvm/ADT/GraphTraits.h"
0042 #include "llvm/ADT/PointerIntPair.h"
0043 #include "llvm/ADT/iterator_range.h"
0044 #include "llvm/IR/Dominators.h"
0045 #include "llvm/IR/PassManager.h"
0046 #include "llvm/Pass.h"
0047 #include <algorithm>
0048 #include <cassert>
0049 #include <map>
0050 #include <memory>
0051 #include <set>
0052 #include <string>
0053 #include <type_traits>
0054 #include <vector>
0055
0056 namespace llvm {
0057
0058 class DominanceFrontier;
0059 class Loop;
0060 class LoopInfo;
0061 class PostDominatorTree;
0062 class Region;
0063 template <class RegionTr> class RegionBase;
0064 class RegionInfo;
0065 template <class RegionTr> class RegionInfoBase;
0066 class RegionNode;
0067 class raw_ostream;
0068
0069
0070
0071
0072 template <class FuncT_>
0073 struct RegionTraits {
0074
0075
0076
0077
0078
0079 using BrokenT = typename FuncT_::UnknownRegionTypeError;
0080 };
0081
0082 template <>
0083 struct RegionTraits<Function> {
0084 using FuncT = Function;
0085 using BlockT = BasicBlock;
0086 using RegionT = Region;
0087 using RegionNodeT = RegionNode;
0088 using RegionInfoT = RegionInfo;
0089 using DomTreeT = DominatorTree;
0090 using DomTreeNodeT = DomTreeNode;
0091 using DomFrontierT = DominanceFrontier;
0092 using PostDomTreeT = PostDominatorTree;
0093 using InstT = Instruction;
0094 using LoopT = Loop;
0095 using LoopInfoT = LoopInfo;
0096
0097 static unsigned getNumSuccessors(BasicBlock *BB) {
0098 return BB->getTerminator()->getNumSuccessors();
0099 }
0100 };
0101
0102
0103
0104
0105
0106
0107
0108
0109 template <class GraphType>
0110 class FlatIt {};
0111
0112
0113
0114 template <class Tr>
0115 class RegionNodeBase {
0116 friend class RegionBase<Tr>;
0117
0118 public:
0119 using BlockT = typename Tr::BlockT;
0120 using RegionT = typename Tr::RegionT;
0121
0122 private:
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133 PointerIntPair<BlockT *, 1, bool> entry;
0134
0135
0136
0137 RegionT *parent;
0138
0139 protected:
0140
0141
0142
0143
0144
0145
0146
0147
0148 inline RegionNodeBase(RegionT *Parent, BlockT *Entry,
0149 bool isSubRegion = false)
0150 : entry(Entry, isSubRegion), parent(Parent) {}
0151
0152 public:
0153 RegionNodeBase(const RegionNodeBase &) = delete;
0154 RegionNodeBase &operator=(const RegionNodeBase &) = delete;
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164 inline RegionT *getParent() const { return parent; }
0165
0166
0167
0168
0169
0170
0171
0172 inline BlockT *getEntry() const { return entry.getPointer(); }
0173
0174
0175
0176
0177
0178
0179
0180 template <class T> inline T *getNodeAs() const;
0181
0182
0183
0184
0185
0186 inline bool isSubRegion() const { return entry.getInt(); }
0187 };
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251 template <class Tr>
0252 class RegionBase : public RegionNodeBase<Tr> {
0253 friend class RegionInfoBase<Tr>;
0254
0255 using FuncT = typename Tr::FuncT;
0256 using BlockT = typename Tr::BlockT;
0257 using RegionInfoT = typename Tr::RegionInfoT;
0258 using RegionT = typename Tr::RegionT;
0259 using RegionNodeT = typename Tr::RegionNodeT;
0260 using DomTreeT = typename Tr::DomTreeT;
0261 using LoopT = typename Tr::LoopT;
0262 using LoopInfoT = typename Tr::LoopInfoT;
0263 using InstT = typename Tr::InstT;
0264
0265 using BlockTraits = GraphTraits<BlockT *>;
0266 using InvBlockTraits = GraphTraits<Inverse<BlockT *>>;
0267 using SuccIterTy = typename BlockTraits::ChildIteratorType;
0268 using PredIterTy = typename InvBlockTraits::ChildIteratorType;
0269
0270
0271 RegionInfoT *RI;
0272 DomTreeT *DT;
0273
0274
0275
0276 BlockT *exit;
0277
0278 using RegionSet = std::vector<std::unique_ptr<RegionT>>;
0279
0280
0281 RegionSet children;
0282
0283 using BBNodeMapT = std::map<BlockT *, std::unique_ptr<RegionNodeT>>;
0284
0285
0286 mutable BBNodeMapT BBNodeMap;
0287
0288
0289
0290 void verifyBBInRegion(BlockT *BB) const;
0291
0292
0293
0294
0295 void verifyWalk(BlockT *BB, std::set<BlockT *> *visitedBB) const;
0296
0297
0298 void verifyRegionNest() const;
0299
0300 public:
0301
0302
0303
0304
0305
0306
0307
0308
0309 RegionBase(BlockT *Entry, BlockT *Exit, RegionInfoT *RI, DomTreeT *DT,
0310 RegionT *Parent = nullptr);
0311
0312 RegionBase(const RegionBase &) = delete;
0313 RegionBase &operator=(const RegionBase &) = delete;
0314
0315
0316 ~RegionBase();
0317
0318
0319
0320 BlockT *getEntry() const {
0321 return RegionNodeBase<Tr>::getEntry();
0322 }
0323
0324
0325
0326
0327
0328 void replaceEntry(BlockT *BB);
0329
0330
0331
0332
0333
0334 void replaceExit(BlockT *BB);
0335
0336
0337
0338
0339
0340
0341
0342
0343 void replaceEntryRecursive(BlockT *NewEntry);
0344
0345
0346
0347
0348
0349
0350
0351
0352 void replaceExitRecursive(BlockT *NewExit);
0353
0354
0355
0356
0357 BlockT *getExit() const { return exit; }
0358
0359
0360
0361
0362 RegionT *getParent() const {
0363 return RegionNodeBase<Tr>::getParent();
0364 }
0365
0366
0367
0368 RegionNodeT *getNode() const {
0369 return const_cast<RegionNodeT *>(
0370 reinterpret_cast<const RegionNodeT *>(this));
0371 }
0372
0373
0374
0375
0376
0377
0378 unsigned getDepth() const;
0379
0380
0381
0382
0383 bool isTopLevelRegion() const { return exit == nullptr; }
0384
0385
0386
0387
0388
0389
0390
0391 RegionT *getExpandedRegion() const;
0392
0393
0394
0395
0396
0397
0398 BlockT *getEnteringBlock() const;
0399
0400
0401
0402
0403
0404
0405 BlockT *getExitingBlock() const;
0406
0407
0408
0409
0410 bool getExitingBlocks(SmallVectorImpl<BlockT *> &Exitings) const;
0411
0412
0413
0414
0415
0416
0417 bool isSimple() const;
0418
0419
0420
0421 std::string getNameStr() const;
0422
0423
0424 RegionInfoT *getRegionInfo() const { return RI; }
0425
0426
0427 enum PrintStyle { PrintNone, PrintBB, PrintRN };
0428
0429
0430
0431
0432
0433
0434 void print(raw_ostream &OS, bool printTree = true, unsigned level = 0,
0435 PrintStyle Style = PrintNone) const;
0436
0437 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
0438
0439 void dump() const;
0440 #endif
0441
0442
0443
0444
0445
0446 bool contains(const BlockT *BB) const;
0447
0448
0449
0450
0451
0452 bool contains(const RegionT *SubRegion) const {
0453
0454 if (!getExit())
0455 return true;
0456
0457 return contains(SubRegion->getEntry()) &&
0458 (contains(SubRegion->getExit()) ||
0459 SubRegion->getExit() == getExit());
0460 }
0461
0462
0463
0464
0465
0466
0467 bool contains(const InstT *Inst) const { return contains(Inst->getParent()); }
0468
0469
0470
0471
0472
0473
0474
0475
0476 bool contains(const LoopT *L) const;
0477
0478
0479
0480
0481
0482
0483
0484
0485
0486 LoopT *outermostLoopInRegion(LoopT *L) const;
0487
0488
0489
0490
0491
0492
0493
0494
0495
0496
0497 LoopT *outermostLoopInRegion(LoopInfoT *LI, BlockT *BB) const;
0498
0499
0500
0501
0502
0503 RegionT *getSubRegionNode(BlockT *BB) const;
0504
0505
0506
0507
0508
0509
0510
0511 RegionNodeT *getNode(BlockT *BB) const;
0512
0513
0514
0515
0516
0517 RegionNodeT *getBBNode(BlockT *BB) const;
0518
0519
0520
0521
0522
0523
0524 void addSubRegion(RegionT *SubRegion, bool moveChildren = false);
0525
0526
0527
0528
0529
0530
0531 RegionT *removeSubRegion(RegionT *SubRegion);
0532
0533
0534
0535
0536 void transferChildrenTo(RegionT *To);
0537
0538
0539
0540
0541
0542 void verifyRegion() const;
0543
0544
0545
0546
0547
0548
0549 void clearNodeCache();
0550
0551
0552
0553
0554
0555 using iterator = typename RegionSet::iterator;
0556 using const_iterator = typename RegionSet::const_iterator;
0557
0558 iterator begin() { return children.begin(); }
0559 iterator end() { return children.end(); }
0560
0561 const_iterator begin() const { return children.begin(); }
0562 const_iterator end() const { return children.end(); }
0563
0564
0565
0566
0567
0568
0569
0570
0571 template <bool IsConst>
0572 class block_iterator_wrapper
0573 : public df_iterator<
0574 std::conditional_t<IsConst, const BlockT, BlockT> *> {
0575 using super =
0576 df_iterator<std::conditional_t<IsConst, const BlockT, BlockT> *>;
0577
0578 public:
0579 using Self = block_iterator_wrapper<IsConst>;
0580 using value_type = typename super::value_type;
0581
0582
0583 block_iterator_wrapper(value_type Entry, value_type Exit)
0584 : super(df_begin(Entry)) {
0585
0586
0587
0588 super::Visited.insert(Exit);
0589 }
0590
0591
0592 block_iterator_wrapper() : super(df_end<value_type>((BlockT *)nullptr)) {}
0593
0594 block_iterator_wrapper(super I) : super(I) {}
0595
0596
0597
0598
0599 BlockT *operator*() const {
0600 return const_cast<BlockT *>(super::operator*());
0601 }
0602 };
0603
0604 using block_iterator = block_iterator_wrapper<false>;
0605 using const_block_iterator = block_iterator_wrapper<true>;
0606
0607 block_iterator block_begin() { return block_iterator(getEntry(), getExit()); }
0608
0609 block_iterator block_end() { return block_iterator(); }
0610
0611 const_block_iterator block_begin() const {
0612 return const_block_iterator(getEntry(), getExit());
0613 }
0614 const_block_iterator block_end() const { return const_block_iterator(); }
0615
0616 using block_range = iterator_range<block_iterator>;
0617 using const_block_range = iterator_range<const_block_iterator>;
0618
0619
0620 inline block_range blocks() {
0621 return block_range(block_begin(), block_end());
0622 }
0623
0624
0625
0626
0627 inline const_block_range blocks() const {
0628 return const_block_range(block_begin(), block_end());
0629 }
0630
0631
0632
0633
0634
0635
0636
0637
0638 using element_iterator =
0639 df_iterator<RegionNodeT *, df_iterator_default_set<RegionNodeT *>, false,
0640 GraphTraits<RegionNodeT *>>;
0641
0642 using const_element_iterator =
0643 df_iterator<const RegionNodeT *,
0644 df_iterator_default_set<const RegionNodeT *>, false,
0645 GraphTraits<const RegionNodeT *>>;
0646
0647 element_iterator element_begin();
0648 element_iterator element_end();
0649 iterator_range<element_iterator> elements() {
0650 return make_range(element_begin(), element_end());
0651 }
0652
0653 const_element_iterator element_begin() const;
0654 const_element_iterator element_end() const;
0655 iterator_range<const_element_iterator> elements() const {
0656 return make_range(element_begin(), element_end());
0657 }
0658
0659 };
0660
0661
0662 template <class Tr>
0663 inline raw_ostream &operator<<(raw_ostream &OS, const RegionNodeBase<Tr> &Node);
0664
0665
0666
0667
0668
0669
0670
0671 template <class Tr>
0672 class RegionInfoBase {
0673 friend class RegionInfo;
0674 friend class MachineRegionInfo;
0675
0676 using BlockT = typename Tr::BlockT;
0677 using FuncT = typename Tr::FuncT;
0678 using RegionT = typename Tr::RegionT;
0679 using RegionInfoT = typename Tr::RegionInfoT;
0680 using DomTreeT = typename Tr::DomTreeT;
0681 using DomTreeNodeT = typename Tr::DomTreeNodeT;
0682 using PostDomTreeT = typename Tr::PostDomTreeT;
0683 using DomFrontierT = typename Tr::DomFrontierT;
0684 using BlockTraits = GraphTraits<BlockT *>;
0685 using InvBlockTraits = GraphTraits<Inverse<BlockT *>>;
0686 using SuccIterTy = typename BlockTraits::ChildIteratorType;
0687 using PredIterTy = typename InvBlockTraits::ChildIteratorType;
0688
0689 using BBtoBBMap = DenseMap<BlockT *, BlockT *>;
0690 using BBtoRegionMap = DenseMap<BlockT *, RegionT *>;
0691
0692 RegionInfoBase();
0693
0694 RegionInfoBase(RegionInfoBase &&Arg)
0695 : DT(std::move(Arg.DT)), PDT(std::move(Arg.PDT)), DF(std::move(Arg.DF)),
0696 TopLevelRegion(std::move(Arg.TopLevelRegion)),
0697 BBtoRegion(std::move(Arg.BBtoRegion)) {
0698 Arg.wipe();
0699 }
0700
0701 RegionInfoBase &operator=(RegionInfoBase &&RHS) {
0702 DT = std::move(RHS.DT);
0703 PDT = std::move(RHS.PDT);
0704 DF = std::move(RHS.DF);
0705 TopLevelRegion = std::move(RHS.TopLevelRegion);
0706 BBtoRegion = std::move(RHS.BBtoRegion);
0707 RHS.wipe();
0708 return *this;
0709 }
0710
0711 virtual ~RegionInfoBase();
0712
0713 DomTreeT *DT;
0714 PostDomTreeT *PDT;
0715 DomFrontierT *DF;
0716
0717
0718 RegionT *TopLevelRegion = nullptr;
0719
0720
0721 BBtoRegionMap BBtoRegion;
0722
0723 protected:
0724
0725
0726
0727
0728 template<typename TheRegionT>
0729 void updateRegionTree(RegionInfoT &RI, TheRegionT *R) {
0730 if (!R)
0731 return;
0732 R->RI = &RI;
0733 for (auto &SubR : *R)
0734 updateRegionTree(RI, SubR.get());
0735 }
0736
0737 private:
0738
0739
0740
0741
0742 void wipe() {
0743 DT = nullptr;
0744 PDT = nullptr;
0745 DF = nullptr;
0746 TopLevelRegion = nullptr;
0747 BBtoRegion.clear();
0748 }
0749
0750
0751
0752
0753 void verifyBBMap(const RegionT *SR) const;
0754
0755
0756
0757
0758 bool isCommonDomFrontier(BlockT *BB, BlockT *entry, BlockT *exit) const;
0759
0760
0761
0762 bool isRegion(BlockT *entry, BlockT *exit) const;
0763
0764
0765
0766 void insertShortCut(BlockT *entry, BlockT *exit, BBtoBBMap *ShortCut) const;
0767
0768
0769
0770 DomTreeNodeT *getNextPostDom(DomTreeNodeT *N, BBtoBBMap *ShortCut) const;
0771
0772
0773 bool isTrivialRegion(BlockT *entry, BlockT *exit) const;
0774
0775
0776 RegionT *createRegion(BlockT *entry, BlockT *exit);
0777
0778
0779 void findRegionsWithEntry(BlockT *entry, BBtoBBMap *ShortCut);
0780
0781
0782 void scanForRegions(FuncT &F, BBtoBBMap *ShortCut);
0783
0784
0785 RegionT *getTopMostParent(RegionT *region);
0786
0787
0788 void buildRegionsTree(DomTreeNodeT *N, RegionT *region);
0789
0790
0791 virtual void updateStatistics(RegionT *R) = 0;
0792
0793
0794 void calculate(FuncT &F);
0795
0796 public:
0797 RegionInfoBase(const RegionInfoBase &) = delete;
0798 RegionInfoBase &operator=(const RegionInfoBase &) = delete;
0799
0800 static bool VerifyRegionInfo;
0801 static typename RegionT::PrintStyle printStyle;
0802
0803 void print(raw_ostream &OS) const;
0804 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
0805 void dump() const;
0806 #endif
0807
0808 void releaseMemory();
0809
0810
0811
0812
0813
0814
0815 RegionT *getRegionFor(BlockT *BB) const;
0816
0817
0818
0819
0820
0821 void setRegionFor(BlockT *BB, RegionT *R);
0822
0823
0824
0825
0826
0827
0828 RegionT *operator[](BlockT *BB) const;
0829
0830
0831
0832
0833
0834 BlockT *getMaxRegionExit(BlockT *BB) const;
0835
0836
0837
0838
0839
0840
0841 RegionT *getCommonRegion(RegionT *A, RegionT *B) const;
0842
0843
0844
0845
0846
0847
0848 RegionT *getCommonRegion(BlockT *A, BlockT *B) const {
0849 return getCommonRegion(getRegionFor(A), getRegionFor(B));
0850 }
0851
0852
0853
0854
0855
0856 RegionT *getCommonRegion(SmallVectorImpl<RegionT *> &Regions) const;
0857
0858
0859
0860
0861
0862 RegionT *getCommonRegion(SmallVectorImpl<BlockT *> &BBs) const;
0863
0864 RegionT *getTopLevelRegion() const { return TopLevelRegion; }
0865
0866
0867
0868
0869 void clearNodeCache() {
0870 if (TopLevelRegion)
0871 TopLevelRegion->clearNodeCache();
0872 }
0873
0874 void verifyAnalysis() const;
0875 };
0876
0877 class RegionNode : public RegionNodeBase<RegionTraits<Function>> {
0878 public:
0879 inline RegionNode(Region *Parent, BasicBlock *Entry, bool isSubRegion = false)
0880 : RegionNodeBase<RegionTraits<Function>>(Parent, Entry, isSubRegion) {}
0881
0882 bool operator==(const Region &RN) const {
0883 return this == reinterpret_cast<const RegionNode *>(&RN);
0884 }
0885 };
0886
0887 class Region : public RegionBase<RegionTraits<Function>> {
0888 public:
0889 Region(BasicBlock *Entry, BasicBlock *Exit, RegionInfo *RI, DominatorTree *DT,
0890 Region *Parent = nullptr);
0891 ~Region();
0892
0893 bool operator==(const RegionNode &RN) const {
0894 return &RN == reinterpret_cast<const RegionNode *>(this);
0895 }
0896 };
0897
0898 class RegionInfo : public RegionInfoBase<RegionTraits<Function>> {
0899 public:
0900 using Base = RegionInfoBase<RegionTraits<Function>>;
0901
0902 explicit RegionInfo();
0903
0904 RegionInfo(RegionInfo &&Arg) : Base(std::move(static_cast<Base &>(Arg))) {
0905 updateRegionTree(*this, TopLevelRegion);
0906 }
0907
0908 RegionInfo &operator=(RegionInfo &&RHS) {
0909 Base::operator=(std::move(static_cast<Base &>(RHS)));
0910 updateRegionTree(*this, TopLevelRegion);
0911 return *this;
0912 }
0913
0914 ~RegionInfo() override;
0915
0916
0917 bool invalidate(Function &F, const PreservedAnalyses &PA,
0918 FunctionAnalysisManager::Invalidator &);
0919
0920
0921 void updateStatistics(Region *R) final;
0922
0923 void recalculate(Function &F, DominatorTree *DT, PostDominatorTree *PDT,
0924 DominanceFrontier *DF);
0925
0926 #ifndef NDEBUG
0927
0928
0929
0930 void view();
0931
0932
0933
0934
0935
0936 void viewOnly();
0937 #endif
0938 };
0939
0940 class RegionInfoPass : public FunctionPass {
0941 RegionInfo RI;
0942
0943 public:
0944 static char ID;
0945
0946 explicit RegionInfoPass();
0947 ~RegionInfoPass() override;
0948
0949 RegionInfo &getRegionInfo() { return RI; }
0950
0951 const RegionInfo &getRegionInfo() const { return RI; }
0952
0953
0954
0955 bool runOnFunction(Function &F) override;
0956 void releaseMemory() override;
0957 void verifyAnalysis() const override;
0958 void getAnalysisUsage(AnalysisUsage &AU) const override;
0959 void print(raw_ostream &OS, const Module *) const override;
0960 void dump() const;
0961
0962 };
0963
0964
0965 class RegionInfoAnalysis : public AnalysisInfoMixin<RegionInfoAnalysis> {
0966 friend AnalysisInfoMixin<RegionInfoAnalysis>;
0967
0968 static AnalysisKey Key;
0969
0970 public:
0971 using Result = RegionInfo;
0972
0973 RegionInfo run(Function &F, FunctionAnalysisManager &AM);
0974 };
0975
0976
0977 class RegionInfoPrinterPass : public PassInfoMixin<RegionInfoPrinterPass> {
0978 raw_ostream &OS;
0979
0980 public:
0981 explicit RegionInfoPrinterPass(raw_ostream &OS);
0982
0983 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
0984
0985 static bool isRequired() { return true; }
0986 };
0987
0988
0989 struct RegionInfoVerifierPass : PassInfoMixin<RegionInfoVerifierPass> {
0990 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
0991 static bool isRequired() { return true; }
0992 };
0993
0994 template <>
0995 template <>
0996 inline BasicBlock *
0997 RegionNodeBase<RegionTraits<Function>>::getNodeAs<BasicBlock>() const {
0998 assert(!isSubRegion() && "This is not a BasicBlock RegionNode!");
0999 return getEntry();
1000 }
1001
1002 template <>
1003 template <>
1004 inline Region *
1005 RegionNodeBase<RegionTraits<Function>>::getNodeAs<Region>() const {
1006 assert(isSubRegion() && "This is not a subregion RegionNode!");
1007 auto Unconst = const_cast<RegionNodeBase<RegionTraits<Function>> *>(this);
1008 return reinterpret_cast<Region *>(Unconst);
1009 }
1010
1011 template <class Tr>
1012 inline raw_ostream &operator<<(raw_ostream &OS,
1013 const RegionNodeBase<Tr> &Node) {
1014 using BlockT = typename Tr::BlockT;
1015 using RegionT = typename Tr::RegionT;
1016
1017 if (Node.isSubRegion())
1018 return OS << Node.template getNodeAs<RegionT>()->getNameStr();
1019 else
1020 return OS << Node.template getNodeAs<BlockT>()->getName();
1021 }
1022
1023 extern template class RegionBase<RegionTraits<Function>>;
1024 extern template class RegionNodeBase<RegionTraits<Function>>;
1025 extern template class RegionInfoBase<RegionTraits<Function>>;
1026
1027 }
1028
1029 #endif