Home | History | Annotate | Download | only in AMDGPU
      1 //===- GCNRegPressure.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 #ifndef LLVM_LIB_TARGET_AMDGPU_GCNREGPRESSURE_H
     11 #define LLVM_LIB_TARGET_AMDGPU_GCNREGPRESSURE_H
     12 
     13 #include "AMDGPUSubtarget.h"
     14 #include "llvm/ADT/DenseMap.h"
     15 #include "llvm/CodeGen/LiveIntervals.h"
     16 #include "llvm/CodeGen/MachineBasicBlock.h"
     17 #include "llvm/CodeGen/MachineInstr.h"
     18 #include "llvm/CodeGen/SlotIndexes.h"
     19 #include "llvm/MC/LaneBitmask.h"
     20 #include "llvm/Support/Debug.h"
     21 #include <algorithm>
     22 #include <limits>
     23 
     24 namespace llvm {
     25 
     26 class MachineRegisterInfo;
     27 class raw_ostream;
     28 
     29 struct GCNRegPressure {
     30   enum RegKind {
     31     SGPR32,
     32     SGPR_TUPLE,
     33     VGPR32,
     34     VGPR_TUPLE,
     35     TOTAL_KINDS
     36   };
     37 
     38   GCNRegPressure() {
     39     clear();
     40   }
     41 
     42   bool empty() const { return getSGPRNum() == 0 && getVGPRNum() == 0; }
     43 
     44   void clear() { std::fill(&Value[0], &Value[TOTAL_KINDS], 0); }
     45 
     46   unsigned getSGPRNum() const { return Value[SGPR32]; }
     47   unsigned getVGPRNum() const { return Value[VGPR32]; }
     48 
     49   unsigned getVGPRTuplesWeight() const { return Value[VGPR_TUPLE]; }
     50   unsigned getSGPRTuplesWeight() const { return Value[SGPR_TUPLE]; }
     51 
     52   unsigned getOccupancy(const GCNSubtarget &ST) const {
     53     return std::min(ST.getOccupancyWithNumSGPRs(getSGPRNum()),
     54                     ST.getOccupancyWithNumVGPRs(getVGPRNum()));
     55   }
     56 
     57   void inc(unsigned Reg,
     58            LaneBitmask PrevMask,
     59            LaneBitmask NewMask,
     60            const MachineRegisterInfo &MRI);
     61 
     62   bool higherOccupancy(const GCNSubtarget &ST, const GCNRegPressure& O) const {
     63     return getOccupancy(ST) > O.getOccupancy(ST);
     64   }
     65 
     66   bool less(const GCNSubtarget &ST, const GCNRegPressure& O,
     67     unsigned MaxOccupancy = std::numeric_limits<unsigned>::max()) const;
     68 
     69   bool operator==(const GCNRegPressure &O) const {
     70     return std::equal(&Value[0], &Value[TOTAL_KINDS], O.Value);
     71   }
     72 
     73   bool operator!=(const GCNRegPressure &O) const {
     74     return !(*this == O);
     75   }
     76 
     77   void print(raw_ostream &OS, const GCNSubtarget *ST = nullptr) const;
     78   void dump() const { print(dbgs()); }
     79 
     80 private:
     81   unsigned Value[TOTAL_KINDS];
     82 
     83   static unsigned getRegKind(unsigned Reg, const MachineRegisterInfo &MRI);
     84 
     85   friend GCNRegPressure max(const GCNRegPressure &P1,
     86                             const GCNRegPressure &P2);
     87 };
     88 
     89 inline GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2) {
     90   GCNRegPressure Res;
     91   for (unsigned I = 0; I < GCNRegPressure::TOTAL_KINDS; ++I)
     92     Res.Value[I] = std::max(P1.Value[I], P2.Value[I]);
     93   return Res;
     94 }
     95 
     96 class GCNRPTracker {
     97 public:
     98   using LiveRegSet = DenseMap<unsigned, LaneBitmask>;
     99 
    100 protected:
    101   const LiveIntervals &LIS;
    102   LiveRegSet LiveRegs;
    103   GCNRegPressure CurPressure, MaxPressure;
    104   const MachineInstr *LastTrackedMI = nullptr;
    105   mutable const MachineRegisterInfo *MRI = nullptr;
    106 
    107   GCNRPTracker(const LiveIntervals &LIS_) : LIS(LIS_) {}
    108 
    109   void reset(const MachineInstr &MI, const LiveRegSet *LiveRegsCopy,
    110              bool After);
    111 
    112 public:
    113   // live regs for the current state
    114   const decltype(LiveRegs) &getLiveRegs() const { return LiveRegs; }
    115   const MachineInstr *getLastTrackedMI() const { return LastTrackedMI; }
    116 
    117   void clearMaxPressure() { MaxPressure.clear(); }
    118 
    119   // returns MaxPressure, resetting it
    120   decltype(MaxPressure) moveMaxPressure() {
    121     auto Res = MaxPressure;
    122     MaxPressure.clear();
    123     return Res;
    124   }
    125 
    126   decltype(LiveRegs) moveLiveRegs() {
    127     return std::move(LiveRegs);
    128   }
    129 
    130   static void printLiveRegs(raw_ostream &OS, const LiveRegSet& LiveRegs,
    131                             const MachineRegisterInfo &MRI);
    132 };
    133 
    134 class GCNUpwardRPTracker : public GCNRPTracker {
    135 public:
    136   GCNUpwardRPTracker(const LiveIntervals &LIS_) : GCNRPTracker(LIS_) {}
    137 
    138   // reset tracker to the point just below MI
    139   // filling live regs upon this point using LIS
    140   void reset(const MachineInstr &MI, const LiveRegSet *LiveRegs = nullptr);
    141 
    142   // move to the state just above the MI
    143   void recede(const MachineInstr &MI);
    144 
    145   // checks whether the tracker's state after receding MI corresponds
    146   // to reported by LIS
    147   bool isValid() const;
    148 };
    149 
    150 class GCNDownwardRPTracker : public GCNRPTracker {
    151   // Last position of reset or advanceBeforeNext
    152   MachineBasicBlock::const_iterator NextMI;
    153 
    154   MachineBasicBlock::const_iterator MBBEnd;
    155 
    156 public:
    157   GCNDownwardRPTracker(const LiveIntervals &LIS_) : GCNRPTracker(LIS_) {}
    158 
    159   const MachineBasicBlock::const_iterator getNext() const { return NextMI; }
    160 
    161   // Reset tracker to the point before the MI
    162   // filling live regs upon this point using LIS.
    163   // Returns false if block is empty except debug values.
    164   bool reset(const MachineInstr &MI, const LiveRegSet *LiveRegs = nullptr);
    165 
    166   // Move to the state right before the next MI. Returns false if reached
    167   // end of the block.
    168   bool advanceBeforeNext();
    169 
    170   // Move to the state at the MI, advanceBeforeNext has to be called first.
    171   void advanceToNext();
    172 
    173   // Move to the state at the next MI. Returns false if reached end of block.
    174   bool advance();
    175 
    176   // Advance instructions until before End.
    177   bool advance(MachineBasicBlock::const_iterator End);
    178 
    179   // Reset to Begin and advance to End.
    180   bool advance(MachineBasicBlock::const_iterator Begin,
    181                MachineBasicBlock::const_iterator End,
    182                const LiveRegSet *LiveRegsCopy = nullptr);
    183 };
    184 
    185 LaneBitmask getLiveLaneMask(unsigned Reg,
    186                             SlotIndex SI,
    187                             const LiveIntervals &LIS,
    188                             const MachineRegisterInfo &MRI);
    189 
    190 GCNRPTracker::LiveRegSet getLiveRegs(SlotIndex SI,
    191                                      const LiveIntervals &LIS,
    192                                      const MachineRegisterInfo &MRI);
    193 
    194 inline GCNRPTracker::LiveRegSet getLiveRegsAfter(const MachineInstr &MI,
    195                                                  const LiveIntervals &LIS) {
    196   return getLiveRegs(LIS.getInstructionIndex(MI).getDeadSlot(), LIS,
    197                      MI.getParent()->getParent()->getRegInfo());
    198 }
    199 
    200 inline GCNRPTracker::LiveRegSet getLiveRegsBefore(const MachineInstr &MI,
    201                                                   const LiveIntervals &LIS) {
    202   return getLiveRegs(LIS.getInstructionIndex(MI).getBaseIndex(), LIS,
    203                      MI.getParent()->getParent()->getRegInfo());
    204 }
    205 
    206 template <typename Range>
    207 GCNRegPressure getRegPressure(const MachineRegisterInfo &MRI,
    208                               Range &&LiveRegs) {
    209   GCNRegPressure Res;
    210   for (const auto &RM : LiveRegs)
    211     Res.inc(RM.first, LaneBitmask::getNone(), RM.second, MRI);
    212   return Res;
    213 }
    214 
    215 void printLivesAt(SlotIndex SI,
    216                   const LiveIntervals &LIS,
    217                   const MachineRegisterInfo &MRI);
    218 
    219 } // end namespace llvm
    220 
    221 #endif // LLVM_LIB_TARGET_AMDGPU_GCNREGPRESSURE_H
    222