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