MachineInstrBundleIterator.h revision 321369
1303231Sdim//===- llvm/CodeGen/MachineInstrBundleIterator.h ----------------*- C++ -*-===// 2303231Sdim// 3303231Sdim// The LLVM Compiler Infrastructure 4303231Sdim// 5303231Sdim// This file is distributed under the University of Illinois Open Source 6303231Sdim// License. See LICENSE.TXT for details. 7303231Sdim// 8303231Sdim//===----------------------------------------------------------------------===// 9303231Sdim// 10303231Sdim// Defines an iterator class that bundles MachineInstr. 11303231Sdim// 12303231Sdim//===----------------------------------------------------------------------===// 13303231Sdim 14303231Sdim#ifndef LLVM_CODEGEN_MACHINEINSTRBUNDLEITERATOR_H 15303231Sdim#define LLVM_CODEGEN_MACHINEINSTRBUNDLEITERATOR_H 16303231Sdim 17303231Sdim#include "llvm/ADT/ilist.h" 18321369Sdim#include "llvm/ADT/simple_ilist.h" 19321369Sdim#include <cassert> 20303231Sdim#include <iterator> 21321369Sdim#include <type_traits> 22303231Sdim 23303231Sdimnamespace llvm { 24303231Sdim 25314564Sdimtemplate <class T, bool IsReverse> struct MachineInstrBundleIteratorTraits; 26314564Sdimtemplate <class T> struct MachineInstrBundleIteratorTraits<T, false> { 27321369Sdim using list_type = simple_ilist<T, ilist_sentinel_tracking<true>>; 28321369Sdim using instr_iterator = typename list_type::iterator; 29321369Sdim using nonconst_instr_iterator = typename list_type::iterator; 30321369Sdim using const_instr_iterator = typename list_type::const_iterator; 31314564Sdim}; 32314564Sdimtemplate <class T> struct MachineInstrBundleIteratorTraits<T, true> { 33321369Sdim using list_type = simple_ilist<T, ilist_sentinel_tracking<true>>; 34321369Sdim using instr_iterator = typename list_type::reverse_iterator; 35321369Sdim using nonconst_instr_iterator = typename list_type::reverse_iterator; 36321369Sdim using const_instr_iterator = typename list_type::const_reverse_iterator; 37314564Sdim}; 38314564Sdimtemplate <class T> struct MachineInstrBundleIteratorTraits<const T, false> { 39321369Sdim using list_type = simple_ilist<T, ilist_sentinel_tracking<true>>; 40321369Sdim using instr_iterator = typename list_type::const_iterator; 41321369Sdim using nonconst_instr_iterator = typename list_type::iterator; 42321369Sdim using const_instr_iterator = typename list_type::const_iterator; 43314564Sdim}; 44314564Sdimtemplate <class T> struct MachineInstrBundleIteratorTraits<const T, true> { 45321369Sdim using list_type = simple_ilist<T, ilist_sentinel_tracking<true>>; 46321369Sdim using instr_iterator = typename list_type::const_reverse_iterator; 47321369Sdim using nonconst_instr_iterator = typename list_type::reverse_iterator; 48321369Sdim using const_instr_iterator = typename list_type::const_reverse_iterator; 49314564Sdim}; 50314564Sdim 51314564Sdimtemplate <bool IsReverse> struct MachineInstrBundleIteratorHelper; 52314564Sdimtemplate <> struct MachineInstrBundleIteratorHelper<false> { 53314564Sdim /// Get the beginning of the current bundle. 54314564Sdim template <class Iterator> static Iterator getBundleBegin(Iterator I) { 55314564Sdim if (!I.isEnd()) 56314564Sdim while (I->isBundledWithPred()) 57314564Sdim --I; 58314564Sdim return I; 59314564Sdim } 60314564Sdim 61314564Sdim /// Get the final node of the current bundle. 62314564Sdim template <class Iterator> static Iterator getBundleFinal(Iterator I) { 63314564Sdim if (!I.isEnd()) 64314564Sdim while (I->isBundledWithSucc()) 65314564Sdim ++I; 66314564Sdim return I; 67314564Sdim } 68314564Sdim 69314564Sdim /// Increment forward ilist iterator. 70314564Sdim template <class Iterator> static void increment(Iterator &I) { 71314564Sdim I = std::next(getBundleFinal(I)); 72314564Sdim } 73314564Sdim 74314564Sdim /// Decrement forward ilist iterator. 75314564Sdim template <class Iterator> static void decrement(Iterator &I) { 76314564Sdim I = getBundleBegin(std::prev(I)); 77314564Sdim } 78314564Sdim}; 79314564Sdim 80314564Sdimtemplate <> struct MachineInstrBundleIteratorHelper<true> { 81314564Sdim /// Get the beginning of the current bundle. 82314564Sdim template <class Iterator> static Iterator getBundleBegin(Iterator I) { 83314564Sdim return MachineInstrBundleIteratorHelper<false>::getBundleBegin( 84314564Sdim I.getReverse()) 85314564Sdim .getReverse(); 86314564Sdim } 87314564Sdim 88314564Sdim /// Get the final node of the current bundle. 89314564Sdim template <class Iterator> static Iterator getBundleFinal(Iterator I) { 90314564Sdim return MachineInstrBundleIteratorHelper<false>::getBundleFinal( 91314564Sdim I.getReverse()) 92314564Sdim .getReverse(); 93314564Sdim } 94314564Sdim 95314564Sdim /// Increment reverse ilist iterator. 96314564Sdim template <class Iterator> static void increment(Iterator &I) { 97314564Sdim I = getBundleBegin(std::next(I)); 98314564Sdim } 99314564Sdim 100314564Sdim /// Decrement reverse ilist iterator. 101314564Sdim template <class Iterator> static void decrement(Iterator &I) { 102314564Sdim I = std::prev(getBundleFinal(I)); 103314564Sdim } 104314564Sdim}; 105314564Sdim 106303231Sdim/// MachineBasicBlock iterator that automatically skips over MIs that are 107303231Sdim/// inside bundles (i.e. walk top level MIs only). 108314564Sdimtemplate <typename Ty, bool IsReverse = false> 109314564Sdimclass MachineInstrBundleIterator : MachineInstrBundleIteratorHelper<IsReverse> { 110321369Sdim using Traits = MachineInstrBundleIteratorTraits<Ty, IsReverse>; 111321369Sdim using instr_iterator = typename Traits::instr_iterator; 112321369Sdim 113303231Sdim instr_iterator MII; 114303231Sdim 115303231Sdimpublic: 116321369Sdim using value_type = typename instr_iterator::value_type; 117321369Sdim using difference_type = typename instr_iterator::difference_type; 118321369Sdim using pointer = typename instr_iterator::pointer; 119321369Sdim using reference = typename instr_iterator::reference; 120321369Sdim using const_pointer = typename instr_iterator::const_pointer; 121321369Sdim using const_reference = typename instr_iterator::const_reference; 122321369Sdim using iterator_category = std::bidirectional_iterator_tag; 123303231Sdim 124314564Sdimprivate: 125321369Sdim using nonconst_instr_iterator = typename Traits::nonconst_instr_iterator; 126321369Sdim using const_instr_iterator = typename Traits::const_instr_iterator; 127321369Sdim using nonconst_iterator = 128321369Sdim MachineInstrBundleIterator<typename nonconst_instr_iterator::value_type, 129321369Sdim IsReverse>; 130321369Sdim using reverse_iterator = MachineInstrBundleIterator<Ty, !IsReverse>; 131314564Sdim 132314564Sdimpublic: 133314564Sdim MachineInstrBundleIterator(instr_iterator MI) : MII(MI) { 134314564Sdim assert((!MI.getNodePtr() || MI.isEnd() || !MI->isBundledWithPred()) && 135314564Sdim "It's not legal to initialize MachineInstrBundleIterator with a " 136314564Sdim "bundled MI"); 137314564Sdim } 138314564Sdim 139314564Sdim MachineInstrBundleIterator(reference MI) : MII(MI) { 140303231Sdim assert(!MI.isBundledWithPred() && "It's not legal to initialize " 141303231Sdim "MachineInstrBundleIterator with a " 142303231Sdim "bundled MI"); 143303231Sdim } 144321369Sdim 145314564Sdim MachineInstrBundleIterator(pointer MI) : MII(MI) { 146303231Sdim // FIXME: This conversion should be explicit. 147303231Sdim assert((!MI || !MI->isBundledWithPred()) && "It's not legal to initialize " 148303231Sdim "MachineInstrBundleIterator " 149303231Sdim "with a bundled MI"); 150303231Sdim } 151321369Sdim 152303231Sdim // Template allows conversion from const to nonconst. 153303231Sdim template <class OtherTy> 154314564Sdim MachineInstrBundleIterator( 155314564Sdim const MachineInstrBundleIterator<OtherTy, IsReverse> &I, 156314564Sdim typename std::enable_if<std::is_convertible<OtherTy *, Ty *>::value, 157314564Sdim void *>::type = nullptr) 158303231Sdim : MII(I.getInstrIterator()) {} 159321369Sdim 160303231Sdim MachineInstrBundleIterator() : MII(nullptr) {} 161303231Sdim 162314564Sdim /// Explicit conversion between forward/reverse iterators. 163314564Sdim /// 164314564Sdim /// Translate between forward and reverse iterators without changing range 165314564Sdim /// boundaries. The resulting iterator will dereference (and have a handle) 166314564Sdim /// to the previous node, which is somewhat unexpected; but converting the 167314564Sdim /// two endpoints in a range will give the same range in reverse. 168314564Sdim /// 169314564Sdim /// This matches std::reverse_iterator conversions. 170314564Sdim explicit MachineInstrBundleIterator( 171314564Sdim const MachineInstrBundleIterator<Ty, !IsReverse> &I) 172314564Sdim : MachineInstrBundleIterator(++I.getReverse()) {} 173303231Sdim 174314564Sdim /// Get the bundle iterator for the given instruction's bundle. 175314564Sdim static MachineInstrBundleIterator getAtBundleBegin(instr_iterator MI) { 176314564Sdim return MachineInstrBundleIteratorHelper<IsReverse>::getBundleBegin(MI); 177314564Sdim } 178303231Sdim 179314564Sdim reference operator*() const { return *MII; } 180314564Sdim pointer operator->() const { return &operator*(); } 181314564Sdim 182314564Sdim /// Check for null. 183314564Sdim bool isValid() const { return MII.getNodePtr(); } 184314564Sdim 185314564Sdim friend bool operator==(const MachineInstrBundleIterator &L, 186314564Sdim const MachineInstrBundleIterator &R) { 187314564Sdim return L.MII == R.MII; 188303231Sdim } 189314564Sdim friend bool operator==(const MachineInstrBundleIterator &L, 190314564Sdim const const_instr_iterator &R) { 191314564Sdim return L.MII == R; // Avoid assertion about validity of R. 192303231Sdim } 193314564Sdim friend bool operator==(const const_instr_iterator &L, 194314564Sdim const MachineInstrBundleIterator &R) { 195314564Sdim return L == R.MII; // Avoid assertion about validity of L. 196314564Sdim } 197314564Sdim friend bool operator==(const MachineInstrBundleIterator &L, 198314564Sdim const nonconst_instr_iterator &R) { 199314564Sdim return L.MII == R; // Avoid assertion about validity of R. 200314564Sdim } 201314564Sdim friend bool operator==(const nonconst_instr_iterator &L, 202314564Sdim const MachineInstrBundleIterator &R) { 203314564Sdim return L == R.MII; // Avoid assertion about validity of L. 204314564Sdim } 205314564Sdim friend bool operator==(const MachineInstrBundleIterator &L, const_pointer R) { 206314564Sdim return L == const_instr_iterator(R); // Avoid assertion about validity of R. 207314564Sdim } 208314564Sdim friend bool operator==(const_pointer L, const MachineInstrBundleIterator &R) { 209314564Sdim return const_instr_iterator(L) == R; // Avoid assertion about validity of L. 210314564Sdim } 211314564Sdim friend bool operator==(const MachineInstrBundleIterator &L, 212314564Sdim const_reference R) { 213314564Sdim return L == &R; // Avoid assertion about validity of R. 214314564Sdim } 215314564Sdim friend bool operator==(const_reference L, 216314564Sdim const MachineInstrBundleIterator &R) { 217314564Sdim return &L == R; // Avoid assertion about validity of L. 218314564Sdim } 219303231Sdim 220314564Sdim friend bool operator!=(const MachineInstrBundleIterator &L, 221314564Sdim const MachineInstrBundleIterator &R) { 222314564Sdim return !(L == R); 223314564Sdim } 224314564Sdim friend bool operator!=(const MachineInstrBundleIterator &L, 225314564Sdim const const_instr_iterator &R) { 226314564Sdim return !(L == R); 227314564Sdim } 228314564Sdim friend bool operator!=(const const_instr_iterator &L, 229314564Sdim const MachineInstrBundleIterator &R) { 230314564Sdim return !(L == R); 231314564Sdim } 232314564Sdim friend bool operator!=(const MachineInstrBundleIterator &L, 233314564Sdim const nonconst_instr_iterator &R) { 234314564Sdim return !(L == R); 235314564Sdim } 236314564Sdim friend bool operator!=(const nonconst_instr_iterator &L, 237314564Sdim const MachineInstrBundleIterator &R) { 238314564Sdim return !(L == R); 239314564Sdim } 240314564Sdim friend bool operator!=(const MachineInstrBundleIterator &L, const_pointer R) { 241314564Sdim return !(L == R); 242314564Sdim } 243314564Sdim friend bool operator!=(const_pointer L, const MachineInstrBundleIterator &R) { 244314564Sdim return !(L == R); 245314564Sdim } 246314564Sdim friend bool operator!=(const MachineInstrBundleIterator &L, 247314564Sdim const_reference R) { 248314564Sdim return !(L == R); 249314564Sdim } 250314564Sdim friend bool operator!=(const_reference L, 251314564Sdim const MachineInstrBundleIterator &R) { 252314564Sdim return !(L == R); 253314564Sdim } 254314564Sdim 255303231Sdim // Increment and decrement operators... 256303231Sdim MachineInstrBundleIterator &operator--() { 257314564Sdim this->decrement(MII); 258303231Sdim return *this; 259303231Sdim } 260303231Sdim MachineInstrBundleIterator &operator++() { 261314564Sdim this->increment(MII); 262303231Sdim return *this; 263303231Sdim } 264303231Sdim MachineInstrBundleIterator operator--(int) { 265303231Sdim MachineInstrBundleIterator Temp = *this; 266303231Sdim --*this; 267303231Sdim return Temp; 268303231Sdim } 269303231Sdim MachineInstrBundleIterator operator++(int) { 270303231Sdim MachineInstrBundleIterator Temp = *this; 271303231Sdim ++*this; 272303231Sdim return Temp; 273303231Sdim } 274303231Sdim 275303231Sdim instr_iterator getInstrIterator() const { return MII; } 276314564Sdim 277314564Sdim nonconst_iterator getNonConstIterator() const { return MII.getNonConst(); } 278314564Sdim 279314564Sdim /// Get a reverse iterator to the same node. 280314564Sdim /// 281314564Sdim /// Gives a reverse iterator that will dereference (and have a handle) to the 282314564Sdim /// same node. Converting the endpoint iterators in a range will give a 283314564Sdim /// different range; for range operations, use the explicit conversions. 284314564Sdim reverse_iterator getReverse() const { return MII.getReverse(); } 285303231Sdim}; 286303231Sdim 287303231Sdim} // end namespace llvm 288303231Sdim 289321369Sdim#endif // LLVM_CODEGEN_MACHINEINSTRBUNDLEITERATOR_H 290