File: LinearScanRA.h

package info (click to toggle)
intel-graphics-compiler2 2.24.13-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 113,504 kB
  • sloc: cpp: 812,849; lisp: 288,219; ansic: 102,423; python: 4,010; yacc: 2,588; lex: 1,666; pascal: 318; sh: 162; makefile: 38
file content (426 lines) | stat: -rw-r--r-- 13,319 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
/*========================== begin_copyright_notice ============================

Copyright (C) 2020-2021 Intel Corporation

SPDX-License-Identifier: MIT

============================= end_copyright_notice ===========================*/

#ifndef _INC_LINEARSCANRA_H_
#define _INC_LINEARSCANRA_H_

#include "Assertions.h"
#include "BitSet.h"
#include "BuildIR.h"
#include "FlowGraph.h"
#include "G4_Opcode.h"
#include "SpillManagerGMRF.h"
#include <list>

// Forward decls
namespace vISA {
class G4_Declare;
class G4_INST;
class G4_BB;
class globalLinearScan;
class LSLiveRange;
class PhyRegLocalRA;
class PhyRegsManager;
class PhyRegSummary;
class BankConflictPass;
class GlobalRA;
} // namespace vISA

#define MAXIMAL_ITERATIONS 10
#define SCRATCH_MSG_LIMIT (128 * 1024)
vISA::G4_Declare *GetTopDclFromRegRegion(vISA::G4_Operand *opnd);

// Each declaration will have a LSLiveRange object allocated for it
namespace vISA {
class PhyRegsLocalRA;
class LSInputLiveRange;

// Metadata for each basic block used during Linear scan RA. It is stored as a
// vector indexed by the basic block id.
class G4_BB_LS {
private:
  bool refInput;
  bool backEdgeIn;
  bool backEdgeOut;

public:
  G4_BB_LS() {
    refInput = false;
    backEdgeIn = false;
    backEdgeOut = false;
  }

  ~G4_BB_LS() {}
  void setBackEdgeIn(bool val) { backEdgeIn = val; }
  bool hasBackEdgeIn() { return backEdgeIn; }
  void setBackEdgeOut(bool val) { backEdgeOut = val; }
  bool hasBackEdgeOut() { return backEdgeOut; }
  void setRefInput(bool val) { refInput = val; }
  bool hasRefInput() { return refInput; }
};

typedef std::vector<G4_BB_LS> BB_LS_VECTOR;

class LinearScanRA {
private:
  G4_Kernel &kernel;
  IR_Builder &builder;
  LivenessAnalysis &l;
  BB_LS_VECTOR BBVector;
  PhyRegsLocalRA *pregs = nullptr;
  std::vector<LSLiveRange *> globalLiveIntervals;
  std::vector<LSLiveRange *> preAssignedLiveIntervals;
  std::vector<LSLiveRange *> liveThroughIntervals;
  std::map<G4_BB *, std::vector<G4_BB *>> loopHeadExitMap;
  unsigned int numRegLRA = 0;
  unsigned int numRowsEOT = 0;
  unsigned int globalLRSize = 0;
  bool doSplitLLR = false;
  // Bump allocator for linear scan live ranges and their forbidden GRF vector.
  Mem_Manager LSMem;
  std::list<LSInputLiveRange *, std_arena_based_allocator<LSInputLiveRange *>>
      inputIntervals;
  BankConflictPass &bc;
  GlobalRA &gra;
  bool doBCR = false;
  bool highInternalConflict = false;
  bool hasSplitInsts = false;
  int regionID = -1;
  LSLiveRange *stackCallArgLR;
  LSLiveRange *stackCallRetLR;
  std::vector<G4_Declare *> globalDeclares;
  unsigned int funcCnt = 0;
  unsigned int lastInstLexID = 0;
  std::vector<unsigned int> funcLastLexID;

  LSLiveRange *GetOrCreateLocalLiveRange(G4_Declare *topdcl);
  LSLiveRange *CreateLocalLiveRange(G4_Declare *topdcl);
  void createLiveIntervals();
  void linearScanMarkReferencesInOpnd(G4_Operand *opnd, bool isEOT,
                                      bool isCall);
  void linearScanMarkReferencesInInst(INST_LIST_ITER inst_it);
  void linearScanMarkReferences(unsigned int &numRowsEOT);
  void markBackEdges();
  void getGlobalDeclares();
  void preRAAnalysis();
  void getCalleeSaveRegisters();
  void getCallerSaveRegisters();
  void getSaveRestoreRegister();
  void calculateFuncLastID();
  int linearScanRA();
  void removeUnrequiredLifetimeOps();
  void setLexicalID();
  bool hasDstSrcOverlapPotential(G4_DstRegRegion *dst, G4_SrcRegRegion *src);
  void setPreAssignedLR(LSLiveRange *lr,
                        std::vector<LSLiveRange *> &preAssignedLiveIntervals);
  void setDstReferences(G4_BB *bb, INST_LIST_ITER inst_it, G4_Declare *dcl,
                        std::vector<LSLiveRange *> &liveIntervals,
                        std::vector<LSLiveRange *> &eotLiveIntervals);
  void setSrcReferences(G4_BB *bb, INST_LIST_ITER inst_it, int srcIdx,
                        G4_Declare *dcl,
                        std::vector<LSLiveRange *> &liveIntervals,
                        std::vector<LSLiveRange *> &eotLiveIntervals);
  void generateInputIntervals(G4_Declare *topdcl, G4_INST *inst,
                              std::vector<uint32_t> &inputRegLastRef,
                              PhyRegsLocalRA &initPregs,
                              bool avoidSameInstOverlap);
  void calculateInputIntervalsGlobal(PhyRegsLocalRA &initPregs);
  void calculateLiveInIntervals(G4_BB *bb,
                                std::vector<LSLiveRange *> &liveIntervals);
  void
  calculateCurrentBBLiveIntervals(G4_BB *bb,
                                  std::vector<LSLiveRange *> &liveIntervals,
                                  std::vector<LSLiveRange *> &eotLiveIntervals);
  void calculateLiveOutIntervals(G4_BB *bb,
                                 std::vector<LSLiveRange *> &liveIntervals);
  void calculateLiveThroughIntervals();
  void
  calculateLiveIntervalsGlobal(G4_BB *bb,
                               std::vector<LSLiveRange *> &liveIntervals,
                               std::vector<LSLiveRange *> &eotLiveIntervals);
  void printLiveIntervals(std::vector<LSLiveRange *> &liveIntervals);
  void printSpillLiveIntervals(std::list<LSLiveRange *> &liveIntervals);
  void printInputLiveIntervalsGlobal();
  bool isUseUnAvailableRegister(uint32_t startReg, uint32_t regNum);
  bool assignEOTLiveRanges(IR_Builder &builder,
                           std::vector<LSLiveRange *> &liveIntervals);

  // scratch fields used for parameter passing
  G4_BB *curBB_ = nullptr;

public:
  static void getRowInfo(int size, int &nrows, int &lastRowSize,
                         const IR_Builder &builder);
  static unsigned int convertSubRegOffFromWords(G4_Declare *dcl,
                                                int subregnuminwords);

  LinearScanRA(BankConflictPass &, GlobalRA &, LivenessAnalysis &);
  void allocForbiddenVector(LSLiveRange *lr);
  int doLinearScanRA();
  void undoLinearScanRAAssignments();
  bool hasHighInternalBC() const { return highInternalConflict; }
};

class LSLiveRange {
private:
  G4_Declare *topdcl;
  G4_INST *firstRef;
  G4_INST *lastRef;
  unsigned int lrStartIdx, lrEndIdx;
  bool pushed;
  G4_VarBase *preg;
  // pregoff is stored in word here
  // But subreg offset stored in regvar should be in units of dcl's element size
  int pregoff;

  unsigned int numRefsInFG;
  unsigned int numRefs;
  G4_BB *prevBBRef;

  bool *forbidden = nullptr;
  bool *retGRFs = nullptr;

  bool isIndirectAccess;
  bool eot;
  bool assigned;
  bool preAssigned;
  bool useUnAvailableReg;
  bool isActive;
  bool _isCall;
  bool _isCallSite;
  bool valid;

  // std::unordered_set<unsigned int> forbiddenGRFs;
  // std::unordered_set<unsigned int> retGRFs;
public:
  LSLiveRange() {
    topdcl = NULL;
    firstRef = lastRef = NULL;
    lrStartIdx = lrEndIdx = 0;
    isIndirectAccess = false;
    numRefsInFG = 0;
    numRefs = 0;
    prevBBRef = NULL;
    preg = NULL;
    pregoff = 0;
    assigned = false;
    preAssigned = false;
    eot = false;
    useUnAvailableReg = false;
    pushed = false;
    isActive = false;
    _isCall = false;
    _isCallSite = false;
    valid = true;
  }

  void setActiveLR(bool a) { isActive = a; }
  bool isActiveLR() { return isActive; }
  const bool *getForbidden() { return forbidden; }
  void setForbidden(bool *f) { forbidden = f; }
  void setRegGRFs(bool *f) { retGRFs = f; }

  void setUseUnAvailableReg(bool avail) { useUnAvailableReg = avail; }
  bool isUseUnAvailableReg() { return useUnAvailableReg; }
  void setPushed(bool p) { pushed = p; }
  bool isPushedToIntervalList() { return pushed; }
  bool isValid() { return valid; }
  void setValid(bool v) { valid = v; }

  // A reference to this live range exists in bb basic block, record it
  void markIndirectRef(bool indirectAccess) {
    isIndirectAccess = indirectAccess;
  }

  void recordRef(G4_BB *bb, bool fromEntry);
  unsigned int getNumRefs() const { return numRefs; }
  bool isGRFRegAssigned();

  void setTopDcl(G4_Declare *dcl) {
    vISA_ASSERT(topdcl == NULL, "Redefining top dcl");
    topdcl = dcl;
  }

  G4_Declare *getTopDcl() const { return topdcl; }

  void *operator new(size_t sz, Mem_Manager &m) { return m.alloc(sz); }

  bool hasIndirectAccess() const { return isIndirectAccess; }

  void setFirstRef(G4_INST *inst, unsigned int idx) {
    if (!firstRef && lrStartIdx == 0) {
      firstRef = inst;
      lrStartIdx = idx;
      return;
    }

    if (idx < lrStartIdx) {
      firstRef = inst;
      lrStartIdx = idx;
    }
  }

  G4_INST *getFirstRef(unsigned int &idx) {
    idx = lrStartIdx;
    return firstRef;
  }

  void setLastRef(G4_INST *inst, unsigned int idx) {
    lastRef = inst;
    if (idx > lrEndIdx) {
      lrEndIdx = idx;
    }
  }

  G4_INST *getLastRef(unsigned int &idx) const {
    idx = lrEndIdx;
    return lastRef;
  }

  void setPhyReg(G4_VarBase *pr, int subreg) {
    preg = pr;
    pregoff = subreg;
  }
  G4_VarBase *getPhyReg(int &subreg) {
    subreg = pregoff;
    return preg;
  }
  void resetPhyReg() {
    preg = NULL;
    pregoff = 0;
  }

  unsigned int getSizeInWords(const IR_Builder &builder);

  bool isLiveRangeGlobal() const;

  void setAssigned(bool a) { assigned = a; }
  bool getAssigned() { return assigned; }

  void setPreAssigned(bool a) { preAssigned = a; }
  bool getPreAssigned() { return preAssigned; }

  void setIsCall(bool a) { _isCall = a; }
  bool isCall() { return _isCall; }

  void setIsCallSite(bool a) { _isCallSite = a; }
  bool isCallSite() { return _isCallSite; }

  void markEOT() { eot = true; }
  bool isEOT() { return eot; }

  void addForbidden(unsigned int f) { /*forbiddenGRFs.insert(f);*/
    forbidden[f] = true;
  }
  void addRetRegs(unsigned int f) { retGRFs[f] = true; }
  const bool *getRetGRFs() { return retGRFs; }
  void clearRetGRF(unsigned GRFSize) {
      memset(retGRFs, false, GRFSize);
  }
  void clearForbiddenGRF(unsigned GRFSize) {
    if (retGRFs) {
      memset(retGRFs, false, GRFSize);
    }
    memset(forbidden, false, GRFSize);
  }
};

class LSInputLiveRange {
private:
  unsigned int regWordIdx;
  unsigned int lrEndIdx;

public:
  LSInputLiveRange(unsigned int regId, unsigned int endId)
      : regWordIdx(regId), lrEndIdx(endId) {}

  void *operator new(size_t sz, Mem_Manager &m) { return m.alloc(sz); }

  unsigned int getRegWordIdx() { return regWordIdx; }
  unsigned int getLrEndIdx() { return lrEndIdx; }
  void setLrEndIdx(unsigned int idx) { lrEndIdx = idx; }
};

} // namespace vISA

namespace vISA {
typedef struct _ACTIVE_GRFS {
  std::vector<LSLiveRange *> activeLV;
  std::vector<LSInputLiveRange *> activeInput;
} ACTIVE_GRFS;

typedef std::map<vISA::G4_Declare *,
                 std::pair<vISA::G4_INST *, G4_BB *>>
    CALL_DECL_MAP;

class globalLinearScan {
private:
  GlobalRA &gra;
  IR_Builder &builder;
  Mem_Manager *GLSMem;
  PhyRegsManager &pregManager;
  std::vector<LSLiveRange *> &liveIntervals;
  std::vector<LSLiveRange *> *preAssignedIntervals;
  std::list<LSInputLiveRange *, std_arena_based_allocator<LSInputLiveRange *>>
      &inputIntervals;
  std::list<LSLiveRange *> active;
  std::vector<ACTIVE_GRFS> activeGRF;
  LSLiveRange *calleeSaveLR = nullptr;
  LivenessAnalysis *liveAnalysis = nullptr;

  void printActives();
  void expireGlobalRanges(unsigned int idx);
  void expireInputRanges(unsigned int global_idx);
  BankAlign getBankAlign(LSLiveRange *lr);
  bool allocateRegsLinearScan(LSLiveRange *lr, IR_Builder &builder);
  void allocRetRegsVector(LSLiveRange *lr);
  void freeAllocedRegs(LSLiveRange *, bool);
  void updateGlobalActiveList(LSLiveRange *lr);
  bool insertLiveRange(std::list<LSLiveRange *> *liveIntervals,
                       LSLiveRange *lr);
  bool canBeSpilledLR(LSLiveRange *lr);
  int findSpillCandidate(LSLiveRange *tlr);
  void freeSelectedRegistsers(int startGRF, LSLiveRange *tlr,
                              std::list<LSLiveRange *> &spillLRs);
  bool spillFromActiveList(LSLiveRange *tlr,
                           std::list<LSLiveRange *> &spillLRs);

  unsigned int startGRFReg = 0;
  unsigned int numRegLRA = 0;
  unsigned int numRowsEOT = 0;
  unsigned int lastLexicalID = 0;

  bool doBankConflict = false;
  bool highInternalConflict = false;

public:
  globalLinearScan(GlobalRA &g, LivenessAnalysis *l,
                   std::vector<LSLiveRange *> &liveIntervals,
                   std::vector<LSLiveRange *> *eotLiveIntervals,
                   std::list<LSInputLiveRange *,
                             std_arena_based_allocator<LSInputLiveRange *>>
                       &inputLivelIntervals,
                   PhyRegsManager &pregMgr, unsigned int numReg,
                   unsigned int numEOT, unsigned int lastLexID,
                   bool bankConflict, bool internalConflict, Mem_Manager* GLSMem);

  void getCalleeSaveGRF(std::vector<unsigned int> &regNum, G4_Kernel *kernel);

  void getCallerSaveGRF(std::vector<unsigned int> &regNum,
                        std::vector<unsigned int> &regRegNum,
                        G4_Kernel *kernel);

  void updateCallSiteLiveIntervals(LSLiveRange *callSiteLR);

  bool runLinearScan(IR_Builder &builder,
                     std::vector<LSLiveRange *> &liveIntervals,
                     std::list<LSLiveRange *> &spillLRs);
  void expireAllActive();
};
} // namespace vISA
#endif // _INC_LINEARSCANRA_H_