File indexing completed on 2026-05-10 08:43:07
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #ifndef LLVM_ADT_POSTORDERITERATOR_H
0017 #define LLVM_ADT_POSTORDERITERATOR_H
0018
0019 #include "llvm/ADT/GraphTraits.h"
0020 #include "llvm/ADT/SmallPtrSet.h"
0021 #include "llvm/ADT/SmallVector.h"
0022 #include "llvm/ADT/iterator_range.h"
0023 #include <iterator>
0024 #include <optional>
0025 #include <set>
0026 #include <type_traits>
0027 #include <utility>
0028
0029 namespace llvm {
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058 template<class SetType, bool External>
0059 class po_iterator_storage {
0060 SetType Visited;
0061
0062 public:
0063
0064 template <typename NodeRef>
0065 bool insertEdge(std::optional<NodeRef> From, NodeRef To) {
0066 return Visited.insert(To).second;
0067 }
0068
0069
0070 template <typename NodeRef> void finishPostorder(NodeRef BB) {}
0071 };
0072
0073
0074 template<class SetType>
0075 class po_iterator_storage<SetType, true> {
0076 SetType &Visited;
0077
0078 public:
0079 po_iterator_storage(SetType &VSet) : Visited(VSet) {}
0080 po_iterator_storage(const po_iterator_storage &S) : Visited(S.Visited) {}
0081
0082
0083
0084
0085 template <class NodeRef>
0086 bool insertEdge(std::optional<NodeRef> From, NodeRef To) {
0087 return Visited.insert(To).second;
0088 }
0089
0090
0091 template <class NodeRef> void finishPostorder(NodeRef BB) {}
0092 };
0093
0094 template <class GraphT,
0095 class SetType = SmallPtrSet<typename GraphTraits<GraphT>::NodeRef, 8>,
0096 bool ExtStorage = false, class GT = GraphTraits<GraphT>>
0097 class po_iterator : public po_iterator_storage<SetType, ExtStorage> {
0098 public:
0099
0100 using iterator_category =
0101 std::conditional_t<ExtStorage, std::input_iterator_tag,
0102 std::forward_iterator_tag>;
0103 using value_type = typename GT::NodeRef;
0104 using difference_type = std::ptrdiff_t;
0105 using pointer = value_type *;
0106 using reference = const value_type &;
0107
0108 private:
0109 using NodeRef = typename GT::NodeRef;
0110 using ChildItTy = typename GT::ChildIteratorType;
0111
0112
0113
0114
0115 SmallVector<std::tuple<NodeRef, ChildItTy, ChildItTy>, 8> VisitStack;
0116
0117 po_iterator(NodeRef BB) {
0118 this->insertEdge(std::optional<NodeRef>(), BB);
0119 VisitStack.emplace_back(BB, GT::child_begin(BB), GT::child_end(BB));
0120 traverseChild();
0121 }
0122
0123 po_iterator() = default;
0124
0125 po_iterator(NodeRef BB, SetType &S)
0126 : po_iterator_storage<SetType, ExtStorage>(S) {
0127 if (this->insertEdge(std::optional<NodeRef>(), BB)) {
0128 VisitStack.emplace_back(BB, GT::child_begin(BB), GT::child_end(BB));
0129 traverseChild();
0130 }
0131 }
0132
0133 po_iterator(SetType &S)
0134 : po_iterator_storage<SetType, ExtStorage>(S) {
0135 }
0136
0137 void traverseChild() {
0138 while (true) {
0139 auto &Entry = VisitStack.back();
0140 if (std::get<1>(Entry) == std::get<2>(Entry))
0141 break;
0142 NodeRef BB = *std::get<1>(Entry)++;
0143 if (this->insertEdge(std::optional<NodeRef>(std::get<0>(Entry)), BB)) {
0144
0145 VisitStack.emplace_back(BB, GT::child_begin(BB), GT::child_end(BB));
0146 }
0147 }
0148 }
0149
0150 public:
0151
0152 static po_iterator begin(const GraphT &G) {
0153 return po_iterator(GT::getEntryNode(G));
0154 }
0155 static po_iterator end(const GraphT &G) { return po_iterator(); }
0156
0157 static po_iterator begin(const GraphT &G, SetType &S) {
0158 return po_iterator(GT::getEntryNode(G), S);
0159 }
0160 static po_iterator end(const GraphT &G, SetType &S) { return po_iterator(S); }
0161
0162 bool operator==(const po_iterator &x) const {
0163 return VisitStack == x.VisitStack;
0164 }
0165 bool operator!=(const po_iterator &x) const { return !(*this == x); }
0166
0167 reference operator*() const { return std::get<0>(VisitStack.back()); }
0168
0169
0170
0171
0172
0173 NodeRef operator->() const { return **this; }
0174
0175 po_iterator &operator++() {
0176 this->finishPostorder(std::get<0>(VisitStack.back()));
0177 VisitStack.pop_back();
0178 if (!VisitStack.empty())
0179 traverseChild();
0180 return *this;
0181 }
0182
0183 po_iterator operator++(int) {
0184 po_iterator tmp = *this;
0185 ++*this;
0186 return tmp;
0187 }
0188 };
0189
0190
0191
0192 template <class T>
0193 po_iterator<T> po_begin(const T &G) { return po_iterator<T>::begin(G); }
0194 template <class T>
0195 po_iterator<T> po_end (const T &G) { return po_iterator<T>::end(G); }
0196
0197 template <class T> iterator_range<po_iterator<T>> post_order(const T &G) {
0198 return make_range(po_begin(G), po_end(G));
0199 }
0200
0201
0202 template <class T, class SetType = std::set<typename GraphTraits<T>::NodeRef>>
0203 struct po_ext_iterator : public po_iterator<T, SetType, true> {
0204 po_ext_iterator(const po_iterator<T, SetType, true> &V) :
0205 po_iterator<T, SetType, true>(V) {}
0206 };
0207
0208 template<class T, class SetType>
0209 po_ext_iterator<T, SetType> po_ext_begin(T G, SetType &S) {
0210 return po_ext_iterator<T, SetType>::begin(G, S);
0211 }
0212
0213 template<class T, class SetType>
0214 po_ext_iterator<T, SetType> po_ext_end(T G, SetType &S) {
0215 return po_ext_iterator<T, SetType>::end(G, S);
0216 }
0217
0218 template <class T, class SetType>
0219 iterator_range<po_ext_iterator<T, SetType>> post_order_ext(const T &G, SetType &S) {
0220 return make_range(po_ext_begin(G, S), po_ext_end(G, S));
0221 }
0222
0223
0224 template <class T, class SetType = std::set<typename GraphTraits<T>::NodeRef>,
0225 bool External = false>
0226 struct ipo_iterator : public po_iterator<Inverse<T>, SetType, External> {
0227 ipo_iterator(const po_iterator<Inverse<T>, SetType, External> &V) :
0228 po_iterator<Inverse<T>, SetType, External> (V) {}
0229 };
0230
0231 template <class T>
0232 ipo_iterator<T> ipo_begin(const T &G) {
0233 return ipo_iterator<T>::begin(G);
0234 }
0235
0236 template <class T>
0237 ipo_iterator<T> ipo_end(const T &G){
0238 return ipo_iterator<T>::end(G);
0239 }
0240
0241 template <class T>
0242 iterator_range<ipo_iterator<T>> inverse_post_order(const T &G) {
0243 return make_range(ipo_begin(G), ipo_end(G));
0244 }
0245
0246
0247 template <class T, class SetType = std::set<typename GraphTraits<T>::NodeRef>>
0248 struct ipo_ext_iterator : public ipo_iterator<T, SetType, true> {
0249 ipo_ext_iterator(const ipo_iterator<T, SetType, true> &V) :
0250 ipo_iterator<T, SetType, true>(V) {}
0251 ipo_ext_iterator(const po_iterator<Inverse<T>, SetType, true> &V) :
0252 ipo_iterator<T, SetType, true>(V) {}
0253 };
0254
0255 template <class T, class SetType>
0256 ipo_ext_iterator<T, SetType> ipo_ext_begin(const T &G, SetType &S) {
0257 return ipo_ext_iterator<T, SetType>::begin(G, S);
0258 }
0259
0260 template <class T, class SetType>
0261 ipo_ext_iterator<T, SetType> ipo_ext_end(const T &G, SetType &S) {
0262 return ipo_ext_iterator<T, SetType>::end(G, S);
0263 }
0264
0265 template <class T, class SetType>
0266 iterator_range<ipo_ext_iterator<T, SetType>>
0267 inverse_post_order_ext(const T &G, SetType &S) {
0268 return make_range(ipo_ext_begin(G, S), ipo_ext_end(G, S));
0269 }
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296
0297
0298 template<class GraphT, class GT = GraphTraits<GraphT>>
0299 class ReversePostOrderTraversal {
0300 using NodeRef = typename GT::NodeRef;
0301
0302 using VecTy = SmallVector<NodeRef, 8>;
0303 VecTy Blocks;
0304
0305 void Initialize(const GraphT &G) {
0306 std::copy(po_begin(G), po_end(G), std::back_inserter(Blocks));
0307 }
0308
0309 public:
0310 using rpo_iterator = typename VecTy::reverse_iterator;
0311 using const_rpo_iterator = typename VecTy::const_reverse_iterator;
0312
0313 ReversePostOrderTraversal(const GraphT &G) { Initialize(G); }
0314
0315
0316 rpo_iterator begin() { return Blocks.rbegin(); }
0317 const_rpo_iterator begin() const { return Blocks.rbegin(); }
0318 rpo_iterator end() { return Blocks.rend(); }
0319 const_rpo_iterator end() const { return Blocks.rend(); }
0320 };
0321
0322 }
0323
0324 #endif