Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Target/AMDGPU/GCNRegPressure.h
Line
Count
Source (jump to first uncovered line)
1
//===- GCNRegPressure.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
#ifndef LLVM_LIB_TARGET_AMDGPU_GCNREGPRESSURE_H
10
#define LLVM_LIB_TARGET_AMDGPU_GCNREGPRESSURE_H
11
12
#include "AMDGPUSubtarget.h"
13
#include "llvm/ADT/DenseMap.h"
14
#include "llvm/CodeGen/LiveIntervals.h"
15
#include "llvm/CodeGen/MachineBasicBlock.h"
16
#include "llvm/CodeGen/MachineInstr.h"
17
#include "llvm/CodeGen/SlotIndexes.h"
18
#include "llvm/MC/LaneBitmask.h"
19
#include "llvm/Support/Debug.h"
20
#include <algorithm>
21
#include <limits>
22
23
namespace llvm {
24
25
class MachineRegisterInfo;
26
class raw_ostream;
27
28
struct GCNRegPressure {
29
  enum RegKind {
30
    SGPR32,
31
    SGPR_TUPLE,
32
    VGPR32,
33
    VGPR_TUPLE,
34
    AGPR32,
35
    AGPR_TUPLE,
36
    TOTAL_KINDS
37
  };
38
39
1.78M
  GCNRegPressure() {
40
1.78M
    clear();
41
1.78M
  }
42
43
0
  bool empty() const { return getSGPRNum() == 0 && getVGPRNum() == 0; }
44
45
1.87M
  void clear() { std::fill(&Value[0], &Value[TOTAL_KINDS], 0); }
46
47
46.3k
  unsigned getSGPRNum() const { return Value[SGPR32]; }
48
46.3k
  unsigned getVGPRNum() const { return std::max(Value[VGPR32], Value[AGPR32]); }
49
50
0
  unsigned getVGPRTuplesWeight() const { return std::max(Value[VGPR_TUPLE],
51
0
                                                         Value[AGPR_TUPLE]); }
52
0
  unsigned getSGPRTuplesWeight() const { return Value[SGPR_TUPLE]; }
53
54
10.3k
  unsigned getOccupancy(const GCNSubtarget &ST) const {
55
10.3k
    return std::min(ST.getOccupancyWithNumSGPRs(getSGPRNum()),
56
10.3k
                    ST.getOccupancyWithNumVGPRs(getVGPRNum()));
57
10.3k
  }
58
59
  void inc(unsigned Reg,
60
           LaneBitmask PrevMask,
61
           LaneBitmask NewMask,
62
           const MachineRegisterInfo &MRI);
63
64
0
  bool higherOccupancy(const GCNSubtarget &ST, const GCNRegPressure& O) const {
65
0
    return getOccupancy(ST) > O.getOccupancy(ST);
66
0
  }
67
68
  bool less(const GCNSubtarget &ST, const GCNRegPressure& O,
69
    unsigned MaxOccupancy = std::numeric_limits<unsigned>::max()) const;
70
71
0
  bool operator==(const GCNRegPressure &O) const {
72
0
    return std::equal(&Value[0], &Value[TOTAL_KINDS], O.Value);
73
0
  }
74
75
0
  bool operator!=(const GCNRegPressure &O) const {
76
0
    return !(*this == O);
77
0
  }
78
79
  void print(raw_ostream &OS, const GCNSubtarget *ST = nullptr) const;
80
0
  void dump() const { print(dbgs()); }
81
82
private:
83
  unsigned Value[TOTAL_KINDS];
84
85
  static unsigned getRegKind(unsigned Reg, const MachineRegisterInfo &MRI);
86
87
  friend GCNRegPressure max(const GCNRegPressure &P1,
88
                            const GCNRegPressure &P2);
89
};
90
91
1.55M
inline GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2) {
92
1.55M
  GCNRegPressure Res;
93
10.8M
  for (unsigned I = 0; I < GCNRegPressure::TOTAL_KINDS; 
++I9.30M
)
94
9.30M
    Res.Value[I] = std::max(P1.Value[I], P2.Value[I]);
95
1.55M
  return Res;
96
1.55M
}
97
98
class GCNRPTracker {
99
public:
100
  using LiveRegSet = DenseMap<unsigned, LaneBitmask>;
101
102
protected:
103
  const LiveIntervals &LIS;
104
  LiveRegSet LiveRegs;
105
  GCNRegPressure CurPressure, MaxPressure;
106
  const MachineInstr *LastTrackedMI = nullptr;
107
  mutable const MachineRegisterInfo *MRI = nullptr;
108
109
58.9k
  GCNRPTracker(const LiveIntervals &LIS_) : LIS(LIS_) {}
110
111
  void reset(const MachineInstr &MI, const LiveRegSet *LiveRegsCopy,
112
             bool After);
113
114
public:
115
  // live regs for the current state
116
28.1k
  const decltype(LiveRegs) &getLiveRegs() const { return LiveRegs; }
117
0
  const MachineInstr *getLastTrackedMI() const { return LastTrackedMI; }
118
119
26.9k
  void clearMaxPressure() { MaxPressure.clear(); }
120
121
  // returns MaxPressure, resetting it
122
63.0k
  decltype(MaxPressure) moveMaxPressure() {
123
63.0k
    auto Res = MaxPressure;
124
63.0k
    MaxPressure.clear();
125
63.0k
    return Res;
126
63.0k
  }
127
128
1.28k
  decltype(LiveRegs) moveLiveRegs() {
129
1.28k
    return std::move(LiveRegs);
130
1.28k
  }
131
132
  static void printLiveRegs(raw_ostream &OS, const LiveRegSet& LiveRegs,
133
                            const MachineRegisterInfo &MRI);
134
};
135
136
class GCNUpwardRPTracker : public GCNRPTracker {
137
public:
138
16
  GCNUpwardRPTracker(const LiveIntervals &LIS_) : GCNRPTracker(LIS_) {}
139
140
  // reset tracker to the point just below MI
141
  // filling live regs upon this point using LIS
142
  void reset(const MachineInstr &MI, const LiveRegSet *LiveRegs = nullptr);
143
144
  // move to the state just above the MI
145
  void recede(const MachineInstr &MI);
146
147
  // checks whether the tracker's state after receding MI corresponds
148
  // to reported by LIS
149
  bool isValid() const;
150
};
151
152
class GCNDownwardRPTracker : public GCNRPTracker {
153
  // Last position of reset or advanceBeforeNext
154
  MachineBasicBlock::const_iterator NextMI;
155
156
  MachineBasicBlock::const_iterator MBBEnd;
157
158
public:
159
58.9k
  GCNDownwardRPTracker(const LiveIntervals &LIS_) : GCNRPTracker(LIS_) {}
160
161
401k
  const MachineBasicBlock::const_iterator getNext() const { return NextMI; }
162
163
  // Reset tracker to the point before the MI
164
  // filling live regs upon this point using LIS.
165
  // Returns false if block is empty except debug values.
166
  bool reset(const MachineInstr &MI, const LiveRegSet *LiveRegs = nullptr);
167
168
  // Move to the state right before the next MI. Returns false if reached
169
  // end of the block.
170
  bool advanceBeforeNext();
171
172
  // Move to the state at the MI, advanceBeforeNext has to be called first.
173
  void advanceToNext();
174
175
  // Move to the state at the next MI. Returns false if reached end of block.
176
  bool advance();
177
178
  // Advance instructions until before End.
179
  bool advance(MachineBasicBlock::const_iterator End);
180
181
  // Reset to Begin and advance to End.
182
  bool advance(MachineBasicBlock::const_iterator Begin,
183
               MachineBasicBlock::const_iterator End,
184
               const LiveRegSet *LiveRegsCopy = nullptr);
185
};
186
187
LaneBitmask getLiveLaneMask(unsigned Reg,
188
                            SlotIndex SI,
189
                            const LiveIntervals &LIS,
190
                            const MachineRegisterInfo &MRI);
191
192
GCNRPTracker::LiveRegSet getLiveRegs(SlotIndex SI,
193
                                     const LiveIntervals &LIS,
194
                                     const MachineRegisterInfo &MRI);
195
196
/// creates a map MachineInstr -> LiveRegSet
197
/// R - range of iterators on instructions
198
/// After - upon entry or exit of every instruction
199
/// Note: there is no entry in the map for instructions with empty live reg set
200
/// Complexity = O(NumVirtRegs * averageLiveRangeSegmentsPerReg * lg(R))
201
template <typename Range>
202
DenseMap<MachineInstr*, GCNRPTracker::LiveRegSet>
203
23.6k
getLiveRegMap(Range &&R, bool After, LiveIntervals &LIS) {
204
23.6k
  std::vector<SlotIndex> Indexes;
205
23.6k
  Indexes.reserve(std::distance(R.begin(), R.end()));
206
23.6k
  auto &SII = *LIS.getSlotIndexes();
207
26.1k
  for (MachineInstr *I : R) {
208
26.1k
    auto SI = SII.getInstructionIndex(*I);
209
26.1k
    Indexes.push_back(After ? 
SI.getDeadSlot()0
: SI.getBaseIndex());
210
26.1k
  }
211
23.6k
  std::sort(Indexes.begin(), Indexes.end());
212
23.6k
213
23.6k
  auto &MRI = (*R.begin())->getParent()->getParent()->getRegInfo();
214
23.6k
  DenseMap<MachineInstr *, GCNRPTracker::LiveRegSet> LiveRegMap;
215
23.6k
  SmallVector<SlotIndex, 32> LiveIdxs, SRLiveIdxs;
216
865k
  for (unsigned I = 0, E = MRI.getNumVirtRegs(); I != E; 
++I842k
) {
217
842k
    auto Reg = TargetRegisterInfo::index2VirtReg(I);
218
842k
    if (!LIS.hasInterval(Reg))
219
597k
      continue;
220
244k
    auto &LI = LIS.getInterval(Reg);
221
244k
    LiveIdxs.clear();
222
244k
    if (!LI.findIndexesLiveAt(Indexes, std::back_inserter(LiveIdxs)))
223
236k
      continue;
224
7.42k
    if (!LI.hasSubRanges()) {
225
5.93k
      for (auto SI : LiveIdxs)
226
12.8k
        LiveRegMap[SII.getInstructionFromIndex(SI)][Reg] =
227
12.8k
          MRI.getMaxLaneMaskForVReg(Reg);
228
5.93k
    } else
229
4.37k
      
for (const auto &S : LI.subranges())1.48k
{
230
4.37k
        // constrain search for subranges by indexes live at main range
231
4.37k
        SRLiveIdxs.clear();
232
4.37k
        S.findIndexesLiveAt(LiveIdxs, std::back_inserter(SRLiveIdxs));
233
4.37k
        for (auto SI : SRLiveIdxs)
234
7.43k
          LiveRegMap[SII.getInstructionFromIndex(SI)][Reg] |= S.LaneMask;
235
4.37k
      }
236
7.42k
  }
237
23.6k
  return LiveRegMap;
238
23.6k
}
239
240
inline GCNRPTracker::LiveRegSet getLiveRegsAfter(const MachineInstr &MI,
241
20
                                                 const LiveIntervals &LIS) {
242
20
  return getLiveRegs(LIS.getInstructionIndex(MI).getDeadSlot(), LIS,
243
20
                     MI.getParent()->getParent()->getRegInfo());
244
20
}
245
246
inline GCNRPTracker::LiveRegSet getLiveRegsBefore(const MachineInstr &MI,
247
5.74k
                                                  const LiveIntervals &LIS) {
248
5.74k
  return getLiveRegs(LIS.getInstructionIndex(MI).getBaseIndex(), LIS,
249
5.74k
                     MI.getParent()->getParent()->getRegInfo());
250
5.74k
}
251
252
template <typename Range>
253
GCNRegPressure getRegPressure(const MachineRegisterInfo &MRI,
254
60.2k
                              Range &&LiveRegs) {
255
60.2k
  GCNRegPressure Res;
256
60.2k
  for (const auto &RM : LiveRegs)
257
66.4k
    Res.inc(RM.first, LaneBitmask::getNone(), RM.second, MRI);
258
60.2k
  return Res;
259
60.2k
}
260
261
bool isEqual(const GCNRPTracker::LiveRegSet &S1,
262
             const GCNRPTracker::LiveRegSet &S2);
263
264
void printLivesAt(SlotIndex SI,
265
                  const LiveIntervals &LIS,
266
                  const MachineRegisterInfo &MRI);
267
268
} // end namespace llvm
269
270
#endif // LLVM_LIB_TARGET_AMDGPU_GCNREGPRESSURE_H