1 //===- llvm/CodeGen/MachineInstrBundleIterator.h ----------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // Defines an iterator class that bundles MachineInstr.
12 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_CODEGEN_MACHINEINSTRBUNDLEITERATOR_H
15 #define LLVM_CODEGEN_MACHINEINSTRBUNDLEITERATOR_H
17 #include "llvm/ADT/ilist.h"
18 #include "llvm/ADT/simple_ilist.h"
21 #include <type_traits>
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;
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;
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;
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;
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) {
56 while (I->isBundledWithPred())
61 /// Get the final node of the current bundle.
62 template <class Iterator> static Iterator getBundleFinal(Iterator I) {
64 while (I->isBundledWithSucc())
69 /// Increment forward ilist iterator.
70 template <class Iterator> static void increment(Iterator &I) {
71 I = std::next(getBundleFinal(I));
74 /// Decrement forward ilist iterator.
75 template <class Iterator> static void decrement(Iterator &I) {
76 I = getBundleBegin(std::prev(I));
80 template <> struct MachineInstrBundleIteratorHelper<true> {
81 /// Get the beginning of the current bundle.
82 template <class Iterator> static Iterator getBundleBegin(Iterator I) {
83 return MachineInstrBundleIteratorHelper<false>::getBundleBegin(
88 /// Get the final node of the current bundle.
89 template <class Iterator> static Iterator getBundleFinal(Iterator I) {
90 return MachineInstrBundleIteratorHelper<false>::getBundleFinal(
95 /// Increment reverse ilist iterator.
96 template <class Iterator> static void increment(Iterator &I) {
97 I = getBundleBegin(std::next(I));
100 /// Decrement reverse ilist iterator.
101 template <class Iterator> static void decrement(Iterator &I) {
102 I = std::prev(getBundleFinal(I));
106 /// MachineBasicBlock iterator that automatically skips over MIs that are
107 /// 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;
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;
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,
130 using reverse_iterator = MachineInstrBundleIterator<Ty, !IsReverse>;
133 MachineInstrBundleIterator(instr_iterator MI) : MII(MI) {
134 assert((!MI.getNodePtr() || MI.isEnd() || !MI->isBundledWithPred()) &&
135 "It's not legal to initialize MachineInstrBundleIterator with a "
139 MachineInstrBundleIterator(reference MI) : MII(MI) {
140 assert(!MI.isBundledWithPred() && "It's not legal to initialize "
141 "MachineInstrBundleIterator with a "
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");
152 // Template allows conversion from const to nonconst.
153 template <class OtherTy>
154 MachineInstrBundleIterator(
155 const MachineInstrBundleIterator<OtherTy, IsReverse> &I,
156 typename std::enable_if<std::is_convertible<OtherTy *, Ty *>::value,
157 void *>::type = nullptr)
158 : MII(I.getInstrIterator()) {}
160 MachineInstrBundleIterator() : MII(nullptr) {}
162 /// Explicit conversion between forward/reverse iterators.
164 /// 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.
169 /// This matches std::reverse_iterator conversions.
170 explicit MachineInstrBundleIterator(
171 const MachineInstrBundleIterator<Ty, !IsReverse> &I)
172 : MachineInstrBundleIterator(++I.getReverse()) {}
174 /// Get the bundle iterator for the given instruction's bundle.
175 static MachineInstrBundleIterator getAtBundleBegin(instr_iterator MI) {
176 return MachineInstrBundleIteratorHelper<IsReverse>::getBundleBegin(MI);
179 reference operator*() const { return *MII; }
180 pointer operator->() const { return &operator*(); }
183 bool isValid() const { return MII.getNodePtr(); }
185 friend bool operator==(const MachineInstrBundleIterator &L,
186 const MachineInstrBundleIterator &R) {
187 return L.MII == R.MII;
189 friend bool operator==(const MachineInstrBundleIterator &L,
190 const const_instr_iterator &R) {
191 return L.MII == R; // Avoid assertion about validity of R.
193 friend bool operator==(const const_instr_iterator &L,
194 const MachineInstrBundleIterator &R) {
195 return L == R.MII; // Avoid assertion about validity of L.
197 friend bool operator==(const MachineInstrBundleIterator &L,
198 const nonconst_instr_iterator &R) {
199 return L.MII == R; // Avoid assertion about validity of R.
201 friend bool operator==(const nonconst_instr_iterator &L,
202 const MachineInstrBundleIterator &R) {
203 return L == R.MII; // Avoid assertion about validity of L.
205 friend bool operator==(const MachineInstrBundleIterator &L, const_pointer R) {
206 return L == const_instr_iterator(R); // Avoid assertion about validity of R.
208 friend bool operator==(const_pointer L, const MachineInstrBundleIterator &R) {
209 return const_instr_iterator(L) == R; // Avoid assertion about validity of L.
211 friend bool operator==(const MachineInstrBundleIterator &L,
213 return L == &R; // Avoid assertion about validity of R.
215 friend bool operator==(const_reference L,
216 const MachineInstrBundleIterator &R) {
217 return &L == R; // Avoid assertion about validity of L.
220 friend bool operator!=(const MachineInstrBundleIterator &L,
221 const MachineInstrBundleIterator &R) {
224 friend bool operator!=(const MachineInstrBundleIterator &L,
225 const const_instr_iterator &R) {
228 friend bool operator!=(const const_instr_iterator &L,
229 const MachineInstrBundleIterator &R) {
232 friend bool operator!=(const MachineInstrBundleIterator &L,
233 const nonconst_instr_iterator &R) {
236 friend bool operator!=(const nonconst_instr_iterator &L,
237 const MachineInstrBundleIterator &R) {
240 friend bool operator!=(const MachineInstrBundleIterator &L, const_pointer R) {
243 friend bool operator!=(const_pointer L, const MachineInstrBundleIterator &R) {
246 friend bool operator!=(const MachineInstrBundleIterator &L,
250 friend bool operator!=(const_reference L,
251 const MachineInstrBundleIterator &R) {
255 // Increment and decrement operators...
256 MachineInstrBundleIterator &operator--() {
257 this->decrement(MII);
260 MachineInstrBundleIterator &operator++() {
261 this->increment(MII);
264 MachineInstrBundleIterator operator--(int) {
265 MachineInstrBundleIterator Temp = *this;
269 MachineInstrBundleIterator operator++(int) {
270 MachineInstrBundleIterator Temp = *this;
275 instr_iterator getInstrIterator() const { return MII; }
277 nonconst_iterator getNonConstIterator() const { return MII.getNonConst(); }
279 /// Get a reverse iterator to the same node.
281 /// Gives a reverse iterator that will dereference (and have a handle) to the
282 /// same node. Converting the endpoint iterators in a range will give a
283 /// different range; for range operations, use the explicit conversions.
284 reverse_iterator getReverse() const { return MII.getReverse(); }
287 } // end namespace llvm
289 #endif // LLVM_CODEGEN_MACHINEINSTRBUNDLEITERATOR_H