Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

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