File: VarSplit.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 (162 lines) | stat: -rw-r--r-- 5,304 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
/*========================== begin_copyright_notice ============================

Copyright (C) 2019-2021 Intel Corporation

SPDX-License-Identifier: MIT

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

#ifndef _VARSPLIT_H_
#define _VARSPLIT_H_

#include "BuildIR.h"
#include "FlowGraph.h"
#include "RPE.h"

namespace vISA {
class LiveRange;
class GraphColor;
class RPE;
class GlobalRA;

// store mapping of a split variable to original variable. if any split
// variable is spilled, we can reuse spill location of original variable.
// also store all instructions emitted in preheader, loop exit for each
// split variable. this helps eliminate those instruction in case the
// split variable itself spills.
class SplitResults {
public:
  G4_Declare *origDcl = nullptr;
  std::unordered_map<G4_BB *, std::unordered_set<G4_INST *>> insts;
};

class CComparator {
public:
  bool operator()(const G4_Declare *first, const G4_Declare *second) const {
    return first->getDeclId() < second->getDeclId();
  }
};

class LoopVarSplit {
public:
  LoopVarSplit(G4_Kernel &k, GraphColor *c,
               const LivenessAnalysis *liveAnalysis);
  ~LoopVarSplit() { delete rpe; }
  LoopVarSplit(const LoopVarSplit&) = delete;
  LoopVarSplit& operator=(const LoopVarSplit&) = delete;

  void run();

  std::vector<G4_SrcRegRegion *> getReads(G4_Declare *dcl, Loop &loop);
  std::vector<G4_DstRegRegion *> getWrites(G4_Declare *dcl, Loop &loop);
  unsigned int getMaxRegPressureInLoop(Loop &loop);
  void dump(std::ostream &of = std::cerr);

  static void removeAllSplitInsts(GlobalRA *gra, G4_Declare *dcl);
  static void removeSplitInsts(GlobalRA *gra, G4_Declare *spillDcl, G4_BB *bb);
  static bool removeFromPreheader(GlobalRA *gra, G4_Declare *spillDcl,
                                  G4_BB *bb, INST_LIST_ITER filledInstIter);
  static bool removeFromLoopExit(GlobalRA *gra, G4_Declare *spillDcl, G4_BB *bb,
                                 INST_LIST_ITER filledInstIter);
  static const std::unordered_set<G4_INST *> getSplitInsts(GlobalRA *gra,
                                                           G4_BB *bb);

private:
  const unsigned int cLargeLoop = 500;

  bool split(G4_Declare *dcl, Loop &loop);
  void copy(G4_BB *bb, G4_Declare *dst, G4_Declare *src,
            SplitResults *splitData, bool isDefault32bMask,
            bool isDefault64bMask, bool pushBack = true);
  void replaceSrc(G4_SrcRegRegion *src, G4_Declare *dcl, const Loop &loop);
  void replaceDst(G4_DstRegRegion *dst, G4_Declare *dcl, const Loop &loop);
  G4_Declare *getNewDcl(G4_Declare *dcl1, G4_Declare *dcl2, const Loop &loop);
  std::vector<Loop *> getLoopsToSplitAround(G4_Declare *dcl);
  void adjustLoopMaxPressure(Loop &loop, unsigned int numRows);

  G4_Kernel &kernel;
  GraphColor *coloring = nullptr;
  RPE *rpe = nullptr;
  VarReferences references;
  const LivenessAnalysis *liveness;

  // store set of dcls marked as spill in current RA iteration
  std::unordered_set<G4_Declare *> spilledDclSet;

  // store spill cost for each dcl
  std::map<G4_Declare *, float, CComparator> dclSpillCost;

  std::unordered_map<const Loop *,
                     std::unordered_map<G4_Declare *, G4_Declare *>>
      oldNewDclPerLoop;

  std::unordered_map<Loop *, std::unordered_set<G4_Declare *>> splitsPerLoop;

  std::unordered_map<Loop *, unsigned int> maxRegPressureCache;

  std::unordered_map<Loop *, unsigned int> scalarBytesSplit;

  // a spilled dcl may be split multiple times, once per loop
  // store this information to uplevel to GlobalRA class so
  // anytime we spill a split variable, we reuse spill location.
  // Orig dcl, vector<Tmp Dcl, Loop>
  std::unordered_map<G4_Declare *, std::vector<std::pair<G4_Declare *, Loop *>>>
      splitResults;

  class Size {
  public:
    enum class State {
      Undef = 0,
      Small = 1,
      Large = 2,
    };
    State state = State::Undef;
  };

  std::unordered_map<Loop *, Size> loopSizeCache;

  bool isLargeLoop(Loop &loop) {
    auto &size = loopSizeCache[&loop];
    if (size.state != Size::State::Undef)
      return size.state == Size::State::Large;
    unsigned int instCount = 0;
    std::for_each(loop.getBBs().begin(), loop.getBBs().end(),
                  [&instCount](G4_BB *bb) { instCount += bb->size(); });
    if (instCount > cLargeLoop)
      size.state = Size::State::Large;
    return size.state == Size::State::Large;
  }
};

class VarProperties {
public:
  enum class AccessGranularity { OneGrf = 1, TwoGrf = 2, Unknown = 3 };

  AccessGranularity ag = AccessGranularity::Unknown;
  unsigned int numDefs = 0;
  std::pair<G4_DstRegRegion *, G4_BB *> def;
  std::vector<std::pair<G4_SrcRegRegion *, G4_BB *>> srcs;
  bool candidateDef = false;
  bool legitCandidate = true;

  // API to check whether variable is local or global
  bool isDefUsesInSameBB() {
    auto defBB = def.second;
    for (auto src : srcs) {
      if (src.second != defBB)
        return false;
    }
    return true;
  }

  bool isPartDclUsed(unsigned int lb, unsigned int rb) {
    // Return true if lb/rb is part of any src regions
    for (auto &src : srcs) {
      if (src.first->getLeftBound() >= lb && src.first->getRightBound() <= rb)
        return true;
    }
    return false;
  }
};
}; // namespace vISA
#endif