llvm.org GIT mirror llvm / 919946c
[MCA] Slightly refactor the bottleneck analysis view. NFCI This patch slightly refactors data structures internally used by the bottleneck analysis to track data and resource dependencies. This patch also updates methods used to print out information about dependency edges when in debug mode. This is the last of a sequence of commits done in preparation for an upcoming patch that fixes PR37494. No functional change intended. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@363677 91177308-0d34-0410-b5e6-96231b3b80d8 Andrea Di Biagio 30 days ago
4 changed file(s) with 111 addition(s) and 90 deletion(s). Raw diff Collapse all Expand all
157157 }
158158
159159 void cycleEvent() {
160 if (CriticalPredecessor.Cycles)
160 if (isWaiting() && CriticalPredecessor.Cycles)
161161 CriticalPredecessor.Cycles--;
162162 }
163163 };
142142 }
143143
144144 #ifndef NDEBUG
145 void DependencyGraph::dumpDependencyEdge(raw_ostream &OS, unsigned FromIID,
146 const DependencyEdge &DE,
145 void DependencyGraph::dumpDependencyEdge(raw_ostream &OS,
146 const DependencyEdge &DepEdge,
147147 MCInstPrinter &MCIP) const {
148 bool LoopCarried = FromIID >= DE.IID;
149 OS << " FROM: " << FromIID << " TO: " << DE.IID
150 << (LoopCarried ? " (loop carried)" : " ");
151 if (DE.Type == DT_REGISTER) {
148 unsigned FromIID = DepEdge.FromIID;
149 unsigned ToIID = DepEdge.ToIID;
150 assert(FromIID < ToIID && "Graph should be acyclic!");
151
152 const DependencyEdge::Dependency &DE = DepEdge.Dep;
153 assert(DE.Type != DependencyEdge::DT_INVALID && "Unexpected invalid edge!");
154
155 OS << " FROM: " << FromIID << " TO: " << ToIID << " ";
156 if (DE.Type == DependencyEdge::DT_REGISTER) {
152157 OS << " - REGISTER: ";
153158 MCIP.printRegName(OS, DE.ResourceOrRegID);
154 } else if (DE.Type == DT_MEMORY) {
159 } else if (DE.Type == DependencyEdge::DT_MEMORY) {
155160 OS << " - MEMORY";
156161 } else {
157 assert(DE.Type == DT_RESOURCE && "Unexpected unsupported dependency type!");
162 assert(DE.Type == DependencyEdge::DT_RESOURCE &&
163 "Unexpected unsupported dependency type!");
158164 OS << " - RESOURCE MASK: " << DE.ResourceOrRegID;
159165 }
160 OS << " - CYCLES: " << DE.Cycles << '\n';
166 OS << " - CYCLES: " << DE.Cost << '\n';
161167 }
162168
163169 void DependencyGraph::dump(raw_ostream &OS, MCInstPrinter &MCIP) const {
164170 OS << "\nREG DEPS\n";
165 for (unsigned I = 0, E = Nodes.size(); I < E; ++I) {
166 const DGNode &Node = Nodes[I];
167 for (const DependencyEdge &DE : Node.OutgoingEdges) {
168 if (DE.Type == DT_REGISTER)
169 dumpDependencyEdge(OS, I, DE, MCIP);
170 }
171 }
171 for (const DGNode &Node : Nodes)
172 for (const DependencyEdge &DE : Node.OutgoingEdges)
173 if (DE.Dep.Type == DependencyEdge::DT_REGISTER)
174 dumpDependencyEdge(OS, DE, MCIP);
172175
173176 OS << "\nMEM DEPS\n";
174 for (unsigned I = 0, E = Nodes.size(); I < E; ++I) {
175 const DGNode &Node = Nodes[I];
176 for (const DependencyEdge &DE : Node.OutgoingEdges) {
177 if (DE.Type == DT_MEMORY)
178 dumpDependencyEdge(OS, I, DE, MCIP);
179 }
180 }
177 for (const DGNode &Node : Nodes)
178 for (const DependencyEdge &DE : Node.OutgoingEdges)
179 if (DE.Dep.Type == DependencyEdge::DT_MEMORY)
180 dumpDependencyEdge(OS, DE, MCIP);
181181
182182 OS << "\nRESOURCE DEPS\n";
183 for (unsigned I = 0, E = Nodes.size(); I < E; ++I) {
184 const DGNode &Node = Nodes[I];
185 for (const DependencyEdge &DE : Node.OutgoingEdges) {
186 if (DE.Type == DT_RESOURCE)
187 dumpDependencyEdge(OS, I, DE, MCIP);
188 }
189 }
183 for (const DGNode &Node : Nodes)
184 for (const DependencyEdge &DE : Node.OutgoingEdges)
185 if (DE.Dep.Type == DependencyEdge::DT_RESOURCE)
186 dumpDependencyEdge(OS, DE, MCIP);
190187 }
191188 #endif // NDEBUG
192189
193 void DependencyGraph::addDependency(unsigned From, DependencyEdge &&Dep) {
190 void DependencyGraph::addDependency(unsigned From, unsigned To,
191 DependencyEdge::Dependency &&Dep) {
194192 DGNode &NodeFrom = Nodes[From];
195 DGNode &NodeTo = Nodes[Dep.IID];
193 DGNode &NodeTo = Nodes[To];
196194 SmallVectorImpl &Vec = NodeFrom.OutgoingEdges;
197195
198 auto It = find_if(Vec, [Dep](DependencyEdge &DE) {
199 return DE.IID == Dep.IID && DE.ResourceOrRegID == Dep.ResourceOrRegID;
196 auto It = find_if(Vec, [To, Dep](DependencyEdge &DE) {
197 return DE.ToIID == To && DE.Dep.ResourceOrRegID == Dep.ResourceOrRegID;
200198 });
201199
202200 if (It != Vec.end()) {
203 It->Cycles += Dep.Cycles;
204 return;
205 }
206
207 Vec.emplace_back(Dep);
201 It->Dep.Cost += Dep.Cost;
202 return;
203 }
204
205 DependencyEdge DE = {Dep, From, To};
206 Vec.emplace_back(DE);
208207 NodeTo.NumPredecessors++;
209208 }
210209
211210 BottleneckAnalysis::BottleneckAnalysis(const MCSubtargetInfo &sti,
212211 MCInstPrinter &Printer,
213 ArrayRef S)
212 ArrayRef S, unsigned NumIter)
214213 : STI(sti), Tracker(STI.getSchedModel()), DG(S.size() * 3),
215 Source(S), TotalCycles(0), PressureIncreasedBecauseOfResources(false),
214 Source(S), Iterations(NumIter), TotalCycles(0),
215 PressureIncreasedBecauseOfResources(false),
216216 PressureIncreasedBecauseOfRegisterDependencies(false),
217217 PressureIncreasedBecauseOfMemoryDependencies(false),
218218 SeenStallCycles(false), BPI() {}
219219
220220 void BottleneckAnalysis::addRegisterDep(unsigned From, unsigned To,
221 unsigned RegID, unsigned Cy) {
221 unsigned RegID, unsigned Cost) {
222222 bool IsLoopCarried = From >= To;
223223 unsigned SourceSize = Source.size();
224224 if (IsLoopCarried) {
225 DG.addRegisterDep(From, To + SourceSize, RegID, Cy);
226 DG.addRegisterDep(From + SourceSize, To + (SourceSize * 2), RegID, Cy);
227 return;
228 }
229 DG.addRegisterDep(From + SourceSize, To + SourceSize, RegID, Cy);
230 }
231
232 void BottleneckAnalysis::addMemoryDep(unsigned From, unsigned To, unsigned Cy) {
225 Cost *= Iterations / 2;
226 DG.addRegisterDep(From, To + SourceSize, RegID, Cost);
227 DG.addRegisterDep(From + SourceSize, To + (SourceSize * 2), RegID, Cost);
228 return;
229 }
230 DG.addRegisterDep(From + SourceSize, To + SourceSize, RegID, Cost);
231 }
232
233 void BottleneckAnalysis::addMemoryDep(unsigned From, unsigned To,
234 unsigned Cost) {
233235 bool IsLoopCarried = From >= To;
234236 unsigned SourceSize = Source.size();
235237 if (IsLoopCarried) {
236 DG.addMemoryDep(From, To + SourceSize, Cy);
237 DG.addMemoryDep(From + SourceSize, To + (SourceSize * 2), Cy);
238 return;
239 }
240 DG.addMemoryDep(From + SourceSize, To + SourceSize, Cy);
238 Cost *= Iterations / 2;
239 DG.addMemoryDep(From, To + SourceSize, Cost);
240 DG.addMemoryDep(From + SourceSize, To + (SourceSize * 2), Cost);
241 return;
242 }
243 DG.addMemoryDep(From + SourceSize, To + SourceSize, Cost);
241244 }
242245
243246 void BottleneckAnalysis::addResourceDep(unsigned From, unsigned To,
244 uint64_t Mask, unsigned Cy) {
247 uint64_t Mask, unsigned Cost) {
245248 bool IsLoopCarried = From >= To;
246249 unsigned SourceSize = Source.size();
247250 if (IsLoopCarried) {
248 DG.addResourceDep(From, To + SourceSize, Mask, Cy);
249 DG.addResourceDep(From + SourceSize, To + (SourceSize * 2), Mask, Cy);
250 return;
251 }
252 DG.addResourceDep(From + SourceSize, To + SourceSize, Mask, Cy);
251 Cost *= Iterations / 2;
252 DG.addResourceDep(From, To + SourceSize, Mask, Cost);
253 DG.addResourceDep(From + SourceSize, To + (SourceSize * 2), Mask, Cost);
254 return;
255 }
256 DG.addResourceDep(From + SourceSize, To + SourceSize, Mask, Cost);
253257 }
254258
255259 void BottleneckAnalysis::onEvent(const HWInstructionEvent &Event) {
114114 void handleInstructionIssuedEvent(const HWInstructionIssuedEvent &Event);
115115 };
116116
117 // An edge of a dependency graph.
118 // Vertices of the graph are instructions identified by their ID.
119 struct DependencyEdge {
120 enum DependencyType { DT_INVALID, DT_REGISTER, DT_MEMORY, DT_RESOURCE };
121
122 // Dependency edge descriptor.
123 //
124 // It describe the dependency reason, as well as the edge cost in cycles.
125 struct Dependency {
126 DependencyType Type;
127 uint64_t ResourceOrRegID;
128 uint64_t Cost;
129 };
130 Dependency Dep;
131
132 // Pair of vertices connected by this edge.
133 unsigned FromIID;
134 unsigned ToIID;
135 };
136
117137 class DependencyGraph {
118 enum DependencyType { DT_REGISTER, DT_MEMORY, DT_RESOURCE };
119
120 struct DependencyEdge {
121 DependencyType Type;
122 unsigned IID;
123 uint64_t ResourceOrRegID;
124 uint64_t Cycles;
125 };
126
127138 struct DGNode {
128139 unsigned NumPredecessors;
129140 SmallVector OutgoingEdges;
133144 DependencyGraph(const DependencyGraph &) = delete;
134145 DependencyGraph &operator=(const DependencyGraph &) = delete;
135146
136 void addDependency(unsigned From, DependencyEdge &&DE);
147 void addDependency(unsigned From, unsigned To,
148 DependencyEdge::Dependency &&DE);
137149
138150 #ifndef NDEBUG
139 void dumpDependencyEdge(raw_ostream &OS, unsigned FromIID,
140 const DependencyEdge &DE, MCInstPrinter &MCIP) const;
151 void dumpDependencyEdge(raw_ostream &OS, const DependencyEdge &DE,
152 MCInstPrinter &MCIP) const;
141153 #endif
142154
143155 public:
144156 DependencyGraph(unsigned Size) : Nodes(Size) {}
145157
146 void addRegisterDep(unsigned From, unsigned To, unsigned RegID, unsigned Cy) {
147 addDependency(From, {DT_REGISTER, To, RegID, Cy});
148 }
149
150 void addMemoryDep(unsigned From, unsigned To, unsigned Cy) {
151 addDependency(From, {DT_MEMORY, To, /* unused */ 0, Cy});
152 }
153
154 void addResourceDep(unsigned From, unsigned To, uint64_t Mask, unsigned Cy) {
155 addDependency(From, {DT_RESOURCE, To, Mask, Cy});
158 void addRegisterDep(unsigned From, unsigned To, unsigned RegID,
159 unsigned Cost) {
160 addDependency(From, To, {DependencyEdge::DT_REGISTER, RegID, Cost});
161 }
162
163 void addMemoryDep(unsigned From, unsigned To, unsigned Cost) {
164 addDependency(From, To, {DependencyEdge::DT_MEMORY, /* unused */ 0, Cost});
165 }
166
167 void addResourceDep(unsigned From, unsigned To, uint64_t Mask,
168 unsigned Cost) {
169 addDependency(From, To, {DependencyEdge::DT_RESOURCE, Mask, Cost});
156170 }
157171
158172 #ifndef NDEBUG
167181 DependencyGraph DG;
168182
169183 ArrayRef Source;
184 unsigned Iterations;
170185 unsigned TotalCycles;
171186
172187 bool PressureIncreasedBecauseOfResources;
189204 };
190205 BackPressureInfo BPI;
191206
192 // Prints a bottleneck message to OS.
193 void printBottleneckHints(raw_ostream &OS) const;
194
195207 // Used to populate the dependency graph DG.
196208 void addRegisterDep(unsigned From, unsigned To, unsigned RegID, unsigned Cy);
197209 void addMemoryDep(unsigned From, unsigned To, unsigned Cy);
198210 void addResourceDep(unsigned From, unsigned To, uint64_t Mask, unsigned Cy);
199211
212 // Prints a bottleneck message to OS.
213 void printBottleneckHints(raw_ostream &OS) const;
214
200215 public:
201216 BottleneckAnalysis(const MCSubtargetInfo &STI, MCInstPrinter &MCIP,
202 ArrayRef Sequence);
217 ArrayRef Sequence, unsigned Iterations);
203218
204219 void onCycleEnd() override;
205220 void onEvent(const HWStallEvent &Event) override { SeenStallCycles = true; }
486486 Printer.addView(
487487 llvm::make_unique(SM, Insts, DispatchWidth));
488488
489 if (EnableBottleneckAnalysis)
490 Printer.addView(llvm::make_unique(*STI, *IP, Insts));
489 if (EnableBottleneckAnalysis) {
490 Printer.addView(llvm::make_unique(
491 *STI, *IP, Insts, S.getNumIterations()));
492 }
491493
492494 if (PrintInstructionInfoView)
493495 Printer.addView(