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 /// MachineBasicBlock iterator that automatically skips over MIs that are
23 /// inside bundles (i.e. walk top level MIs only).
24 template <typename Ty>
25 class MachineInstrBundleIterator
26     : public std::iterator<std::bidirectional_iterator_tag, Ty, ptrdiff_t> {
27   typedef std::iterator<std::bidirectional_iterator_tag, Ty, ptrdiff_t> super;
28   typedef ilist_iterator<Ty> instr_iterator;
29   instr_iterator MII;
30 
31 public:
32   typedef typename super::value_type value_type;
33   typedef typename super::difference_type difference_type;
34   typedef typename super::pointer pointer;
35   typedef typename super::reference reference;
36 
37   typedef typename instr_iterator::const_pointer const_pointer;
38   typedef typename instr_iterator::const_reference const_reference;
39 
40 private:
41   typedef typename std::remove_const<value_type>::type nonconst_value_type;
42   typedef ilist_node<nonconst_value_type> node_type;
43   typedef ilist_iterator<nonconst_value_type> nonconst_instr_iterator;
44   typedef MachineInstrBundleIterator<nonconst_value_type> nonconst_iterator;
45 
46 public:
47   MachineInstrBundleIterator(instr_iterator MI) : MII(MI) {}
48 
49   MachineInstrBundleIterator(reference MI) : MII(MI) {
50     assert(!MI.isBundledWithPred() && "It's not legal to initialize "
51                                       "MachineInstrBundleIterator with a "
52                                       "bundled MI");
53   }
54   MachineInstrBundleIterator(pointer MI) : MII(MI) {
55     // FIXME: This conversion should be explicit.
56     assert((!MI || !MI->isBundledWithPred()) && "It's not legal to initialize "
57                                                 "MachineInstrBundleIterator "
58                                                 "with a bundled MI");
59   }
60   // Template allows conversion from const to nonconst.
61   template <class OtherTy>
62   MachineInstrBundleIterator(
63       const MachineInstrBundleIterator<OtherTy> &I,
64       typename std::enable_if<std::is_convertible<OtherTy *, Ty *>::value,
65                               void *>::type = nullptr)
66       : MII(I.getInstrIterator()) {}
67   MachineInstrBundleIterator() : MII(nullptr) {}
68 
69   reference operator*() const { return *MII; }
70   pointer operator->() const { return &operator*(); }
71 
72   /// Check for null.
73   bool isValid() const { return MII.getNodePtr(); }
74 
75   friend bool operator==(const MachineInstrBundleIterator &L,
76                          const MachineInstrBundleIterator &R) {
77     return L.MII == R.MII;
78   }
79   friend bool operator==(const MachineInstrBundleIterator &L, const_pointer R) {
80     // Avoid assertion about validity of R.
81     return L.MII == instr_iterator(const_cast<pointer>(R));
82   }
83   friend bool operator==(const_pointer L, const MachineInstrBundleIterator &R) {
84     // Avoid assertion about validity of L.
85     return instr_iterator(const_cast<pointer>(L)) == R.MII;
86   }
87   friend bool operator==(const MachineInstrBundleIterator &L,
88                          const_reference R) {
89     return L == &R; // Avoid assertion about validity of R.
90   }
91   friend bool operator==(const_reference L,
92                          const MachineInstrBundleIterator &R) {
93     return &L == R; // Avoid assertion about validity of L.
94   }
95 
96   friend bool operator!=(const MachineInstrBundleIterator &L,
97                          const MachineInstrBundleIterator &R) {
98     return !(L == R);
99   }
100   friend bool operator!=(const MachineInstrBundleIterator &L, const_pointer R) {
101     return !(L == R);
102   }
103   friend bool operator!=(const_pointer L, const MachineInstrBundleIterator &R) {
104     return !(L == R);
105   }
106   friend bool operator!=(const MachineInstrBundleIterator &L,
107                          const_reference R) {
108     return !(L == R);
109   }
110   friend bool operator!=(const_reference L,
111                          const MachineInstrBundleIterator &R) {
112     return !(L == R);
113   }
114 
115   // Increment and decrement operators...
116   MachineInstrBundleIterator &operator--() {
117     do
118       --MII;
119     while (MII->isBundledWithPred());
120     return *this;
121   }
122   MachineInstrBundleIterator &operator++() {
123     while (MII->isBundledWithSucc())
124       ++MII;
125     ++MII;
126     return *this;
127   }
128   MachineInstrBundleIterator operator--(int) {
129     MachineInstrBundleIterator Temp = *this;
130     --*this;
131     return Temp;
132   }
133   MachineInstrBundleIterator operator++(int) {
134     MachineInstrBundleIterator Temp = *this;
135     ++*this;
136     return Temp;
137   }
138 
139   instr_iterator getInstrIterator() const { return MII; }
140 
141   nonconst_iterator getNonConstIterator() const {
142     if (auto *N = const_cast<node_type *>(MII.getNodePtr()))
143       return nonconst_iterator(nonconst_instr_iterator(*N));
144     return nonconst_iterator();
145   }
146 };
147 
148 } // end namespace llvm
149 
150 #endif
151