File: LoopAnalysis.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 (242 lines) | stat: -rw-r--r-- 7,130 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
/*========================== begin_copyright_notice ============================

Copyright (C) 2021 Intel Corporation

SPDX-License-Identifier: MIT

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

#pragma once

#include "G4_IR.hpp"
#include <list>
#include <unordered_set>
#include <vector>

namespace vISA {
class G4_BB;
class FlowGraph;
class PointsToAnalysis;

// Top level Analysis class that each analysis needs to inherit.
// Each inherited class needs to implement their own reset() and
// run() classes.
class Analysis {
public:
  virtual ~Analysis() {}
  void setStale() { stale = true; }
  void setValid() { stale = false; }

  bool isStale() const { return stale; }

  void recomputeIfStale();

  virtual void reset() = 0;
  virtual void run() = 0;
  virtual void dump(std::ostream &os = std::cerr) = 0;

private:
  bool stale = true;
  // flag to avoid re-triggering of analysis run when run is already in progress
  bool inProgress = false;
};

class ImmDominator : public Analysis {
public:
  ImmDominator(G4_Kernel &k) : kernel(k) {}

  ~ImmDominator() {}

  bool dominates(G4_BB *bb1, G4_BB *bb2);
  void dumpImmDom(std::ostream &os = std::cerr);
  const std::vector<G4_BB *> &getIDoms();

private:
  G4_Kernel &kernel;
  G4_BB *entryBB = nullptr;
  std::vector<G4_BB *> iDoms;
  // TODO: Internal data to be removed.
  std::vector<std::vector<G4_BB *>> immDoms;
  // FIXME: It's already defined inFlowGraph.h, but #include the header causes a
  // bunch of build errors..
  using BBIDMap = std::unordered_map<G4_BB *, uint32_t>;
  BBIDMap preIDMap;

  void runIDOM();
  G4_BB *InterSect(G4_BB *bb, int i, int k);

  void reset() override;
  void run() override;
  void dump(std::ostream &os = std::cerr) override;
};

class PostDom : public Analysis {
public:
  PostDom(G4_Kernel &);
  std::unordered_set<G4_BB *> &getPostDom(G4_BB *);
  std::vector<G4_BB *> &getImmPostDom(G4_BB *);
  void dumpImmDom(std::ostream &os = std::cerr);

  G4_BB *getCommonImmDom(std::unordered_set<G4_BB *> &);

private:
  G4_Kernel &kernel;
  G4_BB *exitBB = nullptr;
  std::vector<std::unordered_set<G4_BB *>> postDoms;
  std::vector<std::vector<G4_BB *>> immPostDoms;

  void updateImmPostDom();

  void reset() override;
  void run() override;
  void dump(std::ostream &os = std::cerr) override { dumpImmDom(os); }
};

// Computes and stores direct references of variables.
// Indirects references are computed only if PointsToAnalysis instance
// is valid.
class VarReferences : public Analysis {
public:
  VarReferences(G4_Kernel &k, bool GRF = false, bool bounds = true,
                bool pseudoKills = false, PointsToAnalysis* p = nullptr)
      : kernel(k), onlyGRF(GRF), needBounds(bounds),
        reportPseudoKill(pseudoKills), p2a(p) {}

  // Defs -> vector[tuple<inst, bb, lb, rb>]
  // Uses -> vector[tuple<inst, bb>]
  // TODO: Store G4_DstRegRegion instead of G4_INST* in Defs,
  //             G4_SrcRegResion instead of G4_INST* in Uses
  using Defs =
      std::vector<std::tuple<G4_INST *, G4_BB *, unsigned int, unsigned int>>;
  using Uses = std::vector<std::tuple<G4_INST *, G4_BB *>>;
  // Set to large enough number so its never a valid bound
  const unsigned int UnknownBound = 0xffff;

  bool isUniqueDef(G4_Operand *dst);
  unsigned int getDefCount(G4_Declare *dcl);
  unsigned int getUseCount(G4_Declare *dcl);
  const Defs *getDefs(G4_Declare *dcl);
  const Uses *getUses(G4_Declare *dcl);

private:
  // Dcl -> vector[<inst, bb, lb, rb>]
  // this data structure helps check whether a definition or part of it
  // has multiple definitions in the program.
  std::unordered_map<G4_Declare *, std::pair<Defs, Uses>> VarRefs;
  G4_Kernel &kernel;
  bool onlyGRF = false;
  bool needBounds = true;
  bool reportPseudoKill = false;
  PointsToAnalysis *p2a = nullptr;

  void reset() override;
  void run() override;
  void dump(std::ostream &os = std::cerr) override;
};

using BackEdge = std::pair<G4_BB *, G4_BB *>;
using BackEdges = std::vector<BackEdge>;

class Loop {
public:
  Loop(BackEdge b) : be(b) {}

  Loop *parent = nullptr;
  G4_BB *preHeader = nullptr;
  std::vector<Loop *> immNested;
  unsigned int subCalls = 0;

  void addBBToLoopHierarchy(G4_BB *bb);
  void addBBToLoop(G4_BB *bb);

  unsigned int id = 0;

  std::vector<Loop *> getAllSiblings(std::vector<Loop *> &topLoops);

  // BBs not in loop are considered to have nesting level of 0.
  // BBs in outermost loop report nesting level 1.
  // BB in loopn reports nesting level to be 1+it's parent nesting level.
  unsigned int getNestingLevel() const;

  void dump(std::ostream &os = std::cerr);

  bool contains(const G4_BB *);

  unsigned int getBBSize() { return BBs.size(); }

  // Return the number of direct child loops
  unsigned int getNumImmChildLoops() const {
    return (unsigned int)immNested.size();
  }

  G4_BB *getHeader() const { return be.second; }
  G4_BB *backEdgeSrc() const { return be.first; }

  bool fullSubset(Loop *other);
  bool fullSuperset(Loop *other);

  Loop *getInnerMostLoop(const G4_BB *bb);
  Loop *getOuterMostChildLoop(const G4_BB *bb);

  std::vector<G4_BB *> &getLoopExits();

  const std::vector<G4_BB *> &getBBs() { return BBs; }

  // iterators for all its immediate child loops
  std::vector<Loop *>::iterator begin() { return immNested.begin(); }
  std::vector<Loop *>::iterator end() { return immNested.end(); }
  std::vector<Loop *>::const_iterator begin() const { return immNested.begin(); }
  std::vector<Loop *>::const_iterator end() const { return immNested.end(); }

private:
  std::vector<G4_BB *> BBs;
  std::unordered_set<const G4_BB *> BBsLookup;
  BackEdge be;
  std::vector<G4_BB *> loopExits;
};

class FuncInfo;

class LoopDetection : public Analysis {
public:
  LoopDetection(G4_Kernel &);

  std::vector<Loop *> getTopLoops();
  Loop *getInnerMostLoop(const G4_BB *);
  Loop *getOuterMostLoop(const G4_BB *);
  void computePreheaders();

  std::vector<Loop *>::iterator begin() { return topLoops.begin(); }
  std::vector<Loop *>::iterator end() { return topLoops.end(); }
  std::vector<Loop *>::const_iterator begin() const { return topLoops.begin(); }
  std::vector<Loop *>::const_iterator end() const { return topLoops.end(); }

private:
  std::vector<Loop *> topLoops;
  // list owns memory, so no need for dynamic allocation
  std::list<Loop> allLoops;
  // closest Loop per G4_BB* to speed up lookup for programs
  // with lots of loops
  std::unordered_map<const G4_BB *, Loop *> innerMostLoop;

  // store G4_BB -> <preId, rpostId>
  std::unordered_map<const G4_BB *, std::pair<unsigned int, unsigned int>>
      PreIdRPostId;

  G4_Kernel &kernel;
  FlowGraph &fg;

  void reset() override;
  void run() override;
  void dump(std::ostream &os = std::cerr) override;

  void DFSTraverse(const G4_BB *startBB, unsigned &preId, unsigned &postId,
                   BackEdges &bes);
  void findDominatingBackEdges(BackEdges &bes);
  void populateLoop(BackEdge &);
  void computeLoopTree();
  void addLoop(Loop *newLoop, Loop *aParent);
  G4_BB *getPreheader(Loop *loop);
  void computeInnermostLoops();
};
} // namespace vISA