]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/include/llvm/CodeGen/MachineInstrBundleIterator.h
Merge ^/head r318658 through r318963.
[FreeBSD/FreeBSD.git] / contrib / llvm / include / llvm / CodeGen / MachineInstrBundleIterator.h
1 //===- llvm/CodeGen/MachineInstrBundleIterator.h ----------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // Defines an iterator class that bundles MachineInstr.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_CODEGEN_MACHINEINSTRBUNDLEITERATOR_H
15 #define LLVM_CODEGEN_MACHINEINSTRBUNDLEITERATOR_H
16
17 #include "llvm/ADT/ilist.h"
18 #include <iterator>
19
20 namespace llvm {
21
22 template <class T, bool IsReverse> struct MachineInstrBundleIteratorTraits;
23 template <class T> struct MachineInstrBundleIteratorTraits<T, false> {
24   typedef simple_ilist<T, ilist_sentinel_tracking<true>> list_type;
25   typedef typename list_type::iterator instr_iterator;
26   typedef typename list_type::iterator nonconst_instr_iterator;
27   typedef typename list_type::const_iterator const_instr_iterator;
28 };
29 template <class T> struct MachineInstrBundleIteratorTraits<T, true> {
30   typedef simple_ilist<T, ilist_sentinel_tracking<true>> list_type;
31   typedef typename list_type::reverse_iterator instr_iterator;
32   typedef typename list_type::reverse_iterator nonconst_instr_iterator;
33   typedef typename list_type::const_reverse_iterator const_instr_iterator;
34 };
35 template <class T> struct MachineInstrBundleIteratorTraits<const T, false> {
36   typedef simple_ilist<T, ilist_sentinel_tracking<true>> list_type;
37   typedef typename list_type::const_iterator instr_iterator;
38   typedef typename list_type::iterator nonconst_instr_iterator;
39   typedef typename list_type::const_iterator const_instr_iterator;
40 };
41 template <class T> struct MachineInstrBundleIteratorTraits<const T, true> {
42   typedef simple_ilist<T, ilist_sentinel_tracking<true>> list_type;
43   typedef typename list_type::const_reverse_iterator instr_iterator;
44   typedef typename list_type::reverse_iterator nonconst_instr_iterator;
45   typedef typename list_type::const_reverse_iterator const_instr_iterator;
46 };
47
48 template <bool IsReverse> struct MachineInstrBundleIteratorHelper;
49 template <> struct MachineInstrBundleIteratorHelper<false> {
50   /// Get the beginning of the current bundle.
51   template <class Iterator> static Iterator getBundleBegin(Iterator I) {
52     if (!I.isEnd())
53       while (I->isBundledWithPred())
54         --I;
55     return I;
56   }
57
58   /// Get the final node of the current bundle.
59   template <class Iterator> static Iterator getBundleFinal(Iterator I) {
60     if (!I.isEnd())
61       while (I->isBundledWithSucc())
62         ++I;
63     return I;
64   }
65
66   /// Increment forward ilist iterator.
67   template <class Iterator> static void increment(Iterator &I) {
68     I = std::next(getBundleFinal(I));
69   }
70
71   /// Decrement forward ilist iterator.
72   template <class Iterator> static void decrement(Iterator &I) {
73     I = getBundleBegin(std::prev(I));
74   }
75 };
76
77 template <> struct MachineInstrBundleIteratorHelper<true> {
78   /// Get the beginning of the current bundle.
79   template <class Iterator> static Iterator getBundleBegin(Iterator I) {
80     return MachineInstrBundleIteratorHelper<false>::getBundleBegin(
81                I.getReverse())
82         .getReverse();
83   }
84
85   /// Get the final node of the current bundle.
86   template <class Iterator> static Iterator getBundleFinal(Iterator I) {
87     return MachineInstrBundleIteratorHelper<false>::getBundleFinal(
88                I.getReverse())
89         .getReverse();
90   }
91
92   /// Increment reverse ilist iterator.
93   template <class Iterator> static void increment(Iterator &I) {
94     I = getBundleBegin(std::next(I));
95   }
96
97   /// Decrement reverse ilist iterator.
98   template <class Iterator> static void decrement(Iterator &I) {
99     I = std::prev(getBundleFinal(I));
100   }
101 };
102
103 /// MachineBasicBlock iterator that automatically skips over MIs that are
104 /// inside bundles (i.e. walk top level MIs only).
105 template <typename Ty, bool IsReverse = false>
106 class MachineInstrBundleIterator : MachineInstrBundleIteratorHelper<IsReverse> {
107   typedef MachineInstrBundleIteratorTraits<Ty, IsReverse> Traits;
108   typedef typename Traits::instr_iterator instr_iterator;
109   instr_iterator MII;
110
111 public:
112   typedef typename instr_iterator::value_type value_type;
113   typedef typename instr_iterator::difference_type difference_type;
114   typedef typename instr_iterator::pointer pointer;
115   typedef typename instr_iterator::reference reference;
116   typedef std::bidirectional_iterator_tag iterator_category;
117
118   typedef typename instr_iterator::const_pointer const_pointer;
119   typedef typename instr_iterator::const_reference const_reference;
120
121 private:
122   typedef typename Traits::nonconst_instr_iterator nonconst_instr_iterator;
123   typedef typename Traits::const_instr_iterator const_instr_iterator;
124   typedef MachineInstrBundleIterator<
125       typename nonconst_instr_iterator::value_type, IsReverse>
126       nonconst_iterator;
127   typedef MachineInstrBundleIterator<Ty, !IsReverse> reverse_iterator;
128
129 public:
130   MachineInstrBundleIterator(instr_iterator MI) : MII(MI) {
131     assert((!MI.getNodePtr() || MI.isEnd() || !MI->isBundledWithPred()) &&
132            "It's not legal to initialize MachineInstrBundleIterator with a "
133            "bundled MI");
134   }
135
136   MachineInstrBundleIterator(reference MI) : MII(MI) {
137     assert(!MI.isBundledWithPred() && "It's not legal to initialize "
138                                       "MachineInstrBundleIterator with a "
139                                       "bundled MI");
140   }
141   MachineInstrBundleIterator(pointer MI) : MII(MI) {
142     // FIXME: This conversion should be explicit.
143     assert((!MI || !MI->isBundledWithPred()) && "It's not legal to initialize "
144                                                 "MachineInstrBundleIterator "
145                                                 "with a bundled MI");
146   }
147   // Template allows conversion from const to nonconst.
148   template <class OtherTy>
149   MachineInstrBundleIterator(
150       const MachineInstrBundleIterator<OtherTy, IsReverse> &I,
151       typename std::enable_if<std::is_convertible<OtherTy *, Ty *>::value,
152                               void *>::type = nullptr)
153       : MII(I.getInstrIterator()) {}
154   MachineInstrBundleIterator() : MII(nullptr) {}
155
156   /// Explicit conversion between forward/reverse iterators.
157   ///
158   /// Translate between forward and reverse iterators without changing range
159   /// boundaries.  The resulting iterator will dereference (and have a handle)
160   /// to the previous node, which is somewhat unexpected; but converting the
161   /// two endpoints in a range will give the same range in reverse.
162   ///
163   /// This matches std::reverse_iterator conversions.
164   explicit MachineInstrBundleIterator(
165       const MachineInstrBundleIterator<Ty, !IsReverse> &I)
166       : MachineInstrBundleIterator(++I.getReverse()) {}
167
168   /// Get the bundle iterator for the given instruction's bundle.
169   static MachineInstrBundleIterator getAtBundleBegin(instr_iterator MI) {
170     return MachineInstrBundleIteratorHelper<IsReverse>::getBundleBegin(MI);
171   }
172
173   reference operator*() const { return *MII; }
174   pointer operator->() const { return &operator*(); }
175
176   /// Check for null.
177   bool isValid() const { return MII.getNodePtr(); }
178
179   friend bool operator==(const MachineInstrBundleIterator &L,
180                          const MachineInstrBundleIterator &R) {
181     return L.MII == R.MII;
182   }
183   friend bool operator==(const MachineInstrBundleIterator &L,
184                          const const_instr_iterator &R) {
185     return L.MII == R; // Avoid assertion about validity of R.
186   }
187   friend bool operator==(const const_instr_iterator &L,
188                          const MachineInstrBundleIterator &R) {
189     return L == R.MII; // Avoid assertion about validity of L.
190   }
191   friend bool operator==(const MachineInstrBundleIterator &L,
192                          const nonconst_instr_iterator &R) {
193     return L.MII == R; // Avoid assertion about validity of R.
194   }
195   friend bool operator==(const nonconst_instr_iterator &L,
196                          const MachineInstrBundleIterator &R) {
197     return L == R.MII; // Avoid assertion about validity of L.
198   }
199   friend bool operator==(const MachineInstrBundleIterator &L, const_pointer R) {
200     return L == const_instr_iterator(R); // Avoid assertion about validity of R.
201   }
202   friend bool operator==(const_pointer L, const MachineInstrBundleIterator &R) {
203     return const_instr_iterator(L) == R; // Avoid assertion about validity of L.
204   }
205   friend bool operator==(const MachineInstrBundleIterator &L,
206                          const_reference R) {
207     return L == &R; // Avoid assertion about validity of R.
208   }
209   friend bool operator==(const_reference L,
210                          const MachineInstrBundleIterator &R) {
211     return &L == R; // Avoid assertion about validity of L.
212   }
213
214   friend bool operator!=(const MachineInstrBundleIterator &L,
215                          const MachineInstrBundleIterator &R) {
216     return !(L == R);
217   }
218   friend bool operator!=(const MachineInstrBundleIterator &L,
219                          const const_instr_iterator &R) {
220     return !(L == R);
221   }
222   friend bool operator!=(const const_instr_iterator &L,
223                          const MachineInstrBundleIterator &R) {
224     return !(L == R);
225   }
226   friend bool operator!=(const MachineInstrBundleIterator &L,
227                          const nonconst_instr_iterator &R) {
228     return !(L == R);
229   }
230   friend bool operator!=(const nonconst_instr_iterator &L,
231                          const MachineInstrBundleIterator &R) {
232     return !(L == R);
233   }
234   friend bool operator!=(const MachineInstrBundleIterator &L, const_pointer R) {
235     return !(L == R);
236   }
237   friend bool operator!=(const_pointer L, const MachineInstrBundleIterator &R) {
238     return !(L == R);
239   }
240   friend bool operator!=(const MachineInstrBundleIterator &L,
241                          const_reference R) {
242     return !(L == R);
243   }
244   friend bool operator!=(const_reference L,
245                          const MachineInstrBundleIterator &R) {
246     return !(L == R);
247   }
248
249   // Increment and decrement operators...
250   MachineInstrBundleIterator &operator--() {
251     this->decrement(MII);
252     return *this;
253   }
254   MachineInstrBundleIterator &operator++() {
255     this->increment(MII);
256     return *this;
257   }
258   MachineInstrBundleIterator operator--(int) {
259     MachineInstrBundleIterator Temp = *this;
260     --*this;
261     return Temp;
262   }
263   MachineInstrBundleIterator operator++(int) {
264     MachineInstrBundleIterator Temp = *this;
265     ++*this;
266     return Temp;
267   }
268
269   instr_iterator getInstrIterator() const { return MII; }
270
271   nonconst_iterator getNonConstIterator() const { return MII.getNonConst(); }
272
273   /// Get a reverse iterator to the same node.
274   ///
275   /// Gives a reverse iterator that will dereference (and have a handle) to the
276   /// same node.  Converting the endpoint iterators in a range will give a
277   /// different range; for range operations, use the explicit conversions.
278   reverse_iterator getReverse() const { return MII.getReverse(); }
279 };
280
281 } // end namespace llvm
282
283 #endif