llvm.org GIT mirror llvm / 9f63e10
Start scaffolding for a MachineTraceMetrics analysis pass. This is still a work in progress. Out-of-order CPUs usually execute instructions from multiple basic blocks simultaneously, so it is necessary to look at longer traces when estimating the performance effects of code transformations. The MachineTraceMetrics analysis will pick a typical trace through a given basic block and provide performance metrics for the trace. Metrics will include: - Instruction count through the trace. - Issue count per functional unit. - Critical path length, and per-instruction 'slack'. These metrics can be used to determine the performance limiting factor when executing the trace, and how it will be affected by a code transformation. Initially, this will be used by the early if-conversion pass. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@160796 91177308-0d34-0410-b5e6-96231b3b80d8 Jakob Stoklund Olesen 7 years ago
6 changed file(s) with 731 addition(s) and 1 deletion(s). Raw diff Collapse all Expand all
391391 /// into tails of their predecessors.
392392 extern char &TailDuplicateID;
393393
394 /// MachineTraceMetrics - This pass computes critical path and CPU resource
395 /// usage in an ensemble of traces.
396 extern char &MachineTraceMetricsID;
397
394398 /// EarlyIfConverter - This pass performs if-conversion on SSA form by
395399 /// inserting cmov instructions.
396400 extern char &EarlyIfConverterID;
171171 void initializeMachineModuleInfoPass(PassRegistry&);
172172 void initializeMachineSchedulerPass(PassRegistry&);
173173 void initializeMachineSinkingPass(PassRegistry&);
174 void initializeMachineTraceMetricsPass(PassRegistry&);
174175 void initializeMachineVerifierPassPass(PassRegistry&);
175176 void initializeMemCpyOptPass(PassRegistry&);
176177 void initializeMemDepPrinterPass(PassRegistry&);
6060 MachineSSAUpdater.cpp
6161 MachineScheduler.cpp
6262 MachineSink.cpp
63 MachineTraceMetrics.cpp
6364 MachineVerifier.cpp
6465 OcamlGC.cpp
6566 OptimizePHIs.cpp
1616 //===----------------------------------------------------------------------===//
1717
1818 #define DEBUG_TYPE "early-ifcvt"
19 #include "MachineTraceMetrics.h"
1920 #include "llvm/Function.h"
2021 #include "llvm/ADT/BitVector.h"
2122 #include "llvm/ADT/PostOrderIterator.h"
514515 MachineRegisterInfo *MRI;
515516 MachineDominatorTree *DomTree;
516517 MachineLoopInfo *Loops;
518 MachineTraceMetrics *Traces;
519 MachineTraceMetrics::Ensemble *MinInstr;
517520 SSAIfConv IfConv;
518521
519522 public:
526529 bool tryConvertIf(MachineBasicBlock*);
527530 void updateDomTree(ArrayRef Removed);
528531 void updateLoops(ArrayRef Removed);
532 void invalidateTraces();
533 bool shouldConvertIf();
529534 };
530535 } // end anonymous namespace
531536
536541 "early-ifcvt", "Early If Converter", false, false)
537542 INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfo)
538543 INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree)
544 INITIALIZE_PASS_DEPENDENCY(MachineTraceMetrics)
539545 INITIALIZE_PASS_END(EarlyIfConverter,
540546 "early-ifcvt", "Early If Converter", false, false)
541547
545551 AU.addPreserved();
546552 AU.addRequired();
547553 AU.addPreserved();
554 AU.addRequired();
555 AU.addPreserved();
548556 MachineFunctionPass::getAnalysisUsage(AU);
549557 }
550558
575583 Loops->removeBlock(Removed[i]);
576584 }
577585
586 /// Invalidate MachineTraceMetrics before if-conversion.
587 void EarlyIfConverter::invalidateTraces() {
588 Traces->invalidate(IfConv.Head);
589 Traces->invalidate(IfConv.Tail);
590 Traces->invalidate(IfConv.TBB);
591 Traces->invalidate(IfConv.FBB);
592 }
593
594 /// Apply cost model and heuristics to the if-conversion in IfConv.
595 /// Return true if the conversion is a good idea.
596 ///
597 bool EarlyIfConverter::shouldConvertIf() {
598 if (!MinInstr)
599 MinInstr = Traces->getEnsemble(MachineTraceMetrics::TS_MinInstrCount);
600 DEBUG(dbgs() << MinInstr->getTrace(IfConv.Head));
601 return true;
602 }
603
578604 /// Attempt repeated if-conversion on MBB, return true if successful.
579605 ///
580606 bool EarlyIfConverter::tryConvertIf(MachineBasicBlock *MBB) {
581607 bool Changed = false;
582 while (IfConv.canConvertIf(MBB)) {
608 while (IfConv.canConvertIf(MBB) && shouldConvertIf()) {
583609 // If-convert MBB and update analyses.
610 invalidateTraces();
584611 SmallVector RemovedBlocks;
585612 IfConv.convertIf(RemovedBlocks);
586613 Changed = true;
599626 MRI = &MF.getRegInfo();
600627 DomTree = &getAnalysis();
601628 Loops = getAnalysisIfAvailable();
629 Traces = &getAnalysis();
630 MinInstr = 0;
602631
603632 bool Changed = false;
604633 IfConv.runOnMachineFunction(MF);
0 //===- lib/CodeGen/MachineTraceMetrics.cpp ----------------------*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #define DEBUG_TYPE "early-ifcvt"
10 #include "MachineTraceMetrics.h"
11 #include "llvm/CodeGen/MachineBasicBlock.h"
12 #include "llvm/CodeGen/MachineBranchProbabilityInfo.h"
13 #include "llvm/CodeGen/MachineLoopInfo.h"
14 #include "llvm/CodeGen/MachineRegisterInfo.h"
15 #include "llvm/CodeGen/Passes.h"
16 #include "llvm/Target/TargetInstrInfo.h"
17 #include "llvm/Target/TargetRegisterInfo.h"
18 #include "llvm/Support/Debug.h"
19 #include "llvm/Support/raw_ostream.h"
20 #include "llvm/ADT/PostOrderIterator.h"
21
22 using namespace llvm;
23
24 char MachineTraceMetrics::ID = 0;
25 char &llvm::MachineTraceMetricsID = MachineTraceMetrics::ID;
26
27 INITIALIZE_PASS_BEGIN(MachineTraceMetrics,
28 "machine-trace-metrics", "Machine Trace Metrics", false, true)
29 INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfo)
30 INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo)
31 INITIALIZE_PASS_END(MachineTraceMetrics,
32 "machine-trace-metrics", "Machine Trace Metrics", false, true)
33
34 MachineTraceMetrics::MachineTraceMetrics()
35 : MachineFunctionPass(ID), TII(0), TRI(0), MRI(0), Loops(0) {
36 std::fill(Ensembles, array_endof(Ensembles), (Ensemble*)0);
37 }
38
39 void MachineTraceMetrics::getAnalysisUsage(AnalysisUsage &AU) const {
40 AU.setPreservesAll();
41 AU.addRequired();
42 AU.addRequired();
43 MachineFunctionPass::getAnalysisUsage(AU);
44 }
45
46 bool MachineTraceMetrics::runOnMachineFunction(MachineFunction &MF) {
47 TII = MF.getTarget().getInstrInfo();
48 TRI = MF.getTarget().getRegisterInfo();
49 MRI = &MF.getRegInfo();
50 Loops = &getAnalysis();
51 unsigned NumBlocks = MF.getNumBlockIDs();
52 BlockInfo.resize(NumBlocks);
53 return false;
54 }
55
56 void MachineTraceMetrics::releaseMemory() {
57 BlockInfo.clear();
58 for (unsigned i = 0; i != TS_NumStrategies; ++i) {
59 delete Ensembles[i];
60 Ensembles[i] = 0;
61 }
62 }
63
64 //===----------------------------------------------------------------------===//
65 // Fixed block information
66 //===----------------------------------------------------------------------===//
67 //
68 // The number of instructions in a basic block and the CPU resources used by
69 // those instructions don't depend on any given trace strategy.
70
71 /// Is MI an instruction that should be considered free because it will likely
72 /// be eliminated by later passes?
73 static bool isFree(const MachineInstr *MI) {
74 switch(MI->getOpcode()) {
75 default: return false;
76 case TargetOpcode::PHI:
77 case TargetOpcode::PROLOG_LABEL:
78 case TargetOpcode::EH_LABEL:
79 case TargetOpcode::GC_LABEL:
80 case TargetOpcode::KILL:
81 case TargetOpcode::EXTRACT_SUBREG:
82 case TargetOpcode::INSERT_SUBREG:
83 case TargetOpcode::IMPLICIT_DEF:
84 case TargetOpcode::SUBREG_TO_REG:
85 case TargetOpcode::COPY_TO_REGCLASS:
86 case TargetOpcode::DBG_VALUE:
87 case TargetOpcode::REG_SEQUENCE:
88 case TargetOpcode::COPY:
89 return true;
90 }
91 }
92
93 /// Compute the resource usage in basic block MBB.
94 const MachineTraceMetrics::FixedBlockInfo*
95 MachineTraceMetrics::getResources(const MachineBasicBlock *MBB) {
96 assert(MBB && "No basic block");
97 FixedBlockInfo *FBI = &BlockInfo[MBB->getNumber()];
98 if (FBI->hasResources())
99 return FBI;
100
101 // Compute resource usage in the block.
102 // FIXME: Compute per-functional unit counts.
103 FBI->HasCalls = false;
104 unsigned InstrCount = 0;
105 for (MachineBasicBlock::const_iterator I = MBB->begin(), E = MBB->end();
106 I != E; ++I) {
107 const MachineInstr *MI = I;
108 if (isFree(MI))
109 continue;
110 ++InstrCount;
111 if (MI->isCall())
112 FBI->HasCalls = true;
113 }
114 FBI->InstrCount = InstrCount;
115 return FBI;
116 }
117
118 //===----------------------------------------------------------------------===//
119 // Ensemble utility functions
120 //===----------------------------------------------------------------------===//
121
122 MachineTraceMetrics::Ensemble::Ensemble(MachineTraceMetrics *ct)
123 : CT(*ct) {
124 BlockInfo.resize(CT.BlockInfo.size());
125 }
126
127 // Virtual destructor serves as an anchor.
128 MachineTraceMetrics::Ensemble::~Ensemble() {}
129
130 MachineLoop*
131 MachineTraceMetrics::Ensemble::getLoopFor(const MachineBasicBlock *MBB) {
132 return CT.Loops->getLoopFor(MBB);
133 }
134
135 // Update resource-related information in the TraceBlockInfo for MBB.
136 // Only update resources related to the trace above MBB.
137 void MachineTraceMetrics::Ensemble::
138 computeDepthResources(const MachineBasicBlock *MBB) {
139 TraceBlockInfo *TBI = &BlockInfo[MBB->getNumber()];
140
141 // Compute resources from trace above. The top block is simple.
142 if (!TBI->Pred) {
143 TBI->InstrDepth = 0;
144 return;
145 }
146
147 // Compute from the block above. A post-order traversal ensures the
148 // predecessor is always computed first.
149 TraceBlockInfo *PredTBI = &BlockInfo[TBI->Pred->getNumber()];
150 assert(PredTBI->hasValidDepth() && "Trace above has not been computed yet");
151 const FixedBlockInfo *PredFBI = CT.getResources(TBI->Pred);
152 TBI->InstrDepth = PredTBI->InstrDepth + PredFBI->InstrCount;
153 }
154
155 // Update resource-related information in the TraceBlockInfo for MBB.
156 // Only update resources related to the trace below MBB.
157 void MachineTraceMetrics::Ensemble::
158 computeHeightResources(const MachineBasicBlock *MBB) {
159 TraceBlockInfo *TBI = &BlockInfo[MBB->getNumber()];
160
161 // Compute resources for the current block.
162 TBI->InstrHeight = CT.getResources(MBB)->InstrCount;
163
164 // The trace tail is done.
165 if (!TBI->Succ)
166 return;
167
168 // Compute from the block below. A post-order traversal ensures the
169 // predecessor is always computed first.
170 TraceBlockInfo *SuccTBI = &BlockInfo[TBI->Succ->getNumber()];
171 assert(SuccTBI->hasValidHeight() && "Trace below has not been computed yet");
172 TBI->InstrHeight += SuccTBI->InstrHeight;
173 }
174
175 // Check if depth resources for MBB are valid and return the TBI.
176 // Return NULL if the resources have been invalidated.
177 const MachineTraceMetrics::TraceBlockInfo*
178 MachineTraceMetrics::Ensemble::
179 getDepthResources(const MachineBasicBlock *MBB) const {
180 const TraceBlockInfo *TBI = &BlockInfo[MBB->getNumber()];
181 return TBI->hasValidDepth() ? TBI : 0;
182 }
183
184 // Check if height resources for MBB are valid and return the TBI.
185 // Return NULL if the resources have been invalidated.
186 const MachineTraceMetrics::TraceBlockInfo*
187 MachineTraceMetrics::Ensemble::
188 getHeightResources(const MachineBasicBlock *MBB) const {
189 const TraceBlockInfo *TBI = &BlockInfo[MBB->getNumber()];
190 return TBI->hasValidHeight() ? TBI : 0;
191 }
192
193 //===----------------------------------------------------------------------===//
194 // Trace Selection Strategies
195 //===----------------------------------------------------------------------===//
196 //
197 // A trace selection strategy is implemented as a sub-class of Ensemble. The
198 // trace through a block B is computed by two DFS traversals of the CFG
199 // starting from B. One upwards, and one downwards. During the upwards DFS,
200 // pickTracePred() is called on the post-ordered blocks. During the downwards
201 // DFS, pickTraceSucc() is called in a post-order.
202 //
203
204 // MinInstrCountEnsemble - Pick the trace that executes the least number of
205 // instructions.
206 namespace {
207 class MinInstrCountEnsemble : public MachineTraceMetrics::Ensemble {
208 const char *getName() { return "MinInstr"; }
209 const MachineBasicBlock *pickTracePred(const MachineBasicBlock*);
210 const MachineBasicBlock *pickTraceSucc(const MachineBasicBlock*);
211
212 public:
213 MinInstrCountEnsemble(MachineTraceMetrics *ct)
214 : MachineTraceMetrics::Ensemble(ct) {}
215 };
216 }
217
218 // Select the preferred predecessor for MBB.
219 const MachineBasicBlock*
220 MinInstrCountEnsemble::pickTracePred(const MachineBasicBlock *MBB) {
221 if (MBB->pred_empty())
222 return 0;
223 MachineLoop *CurLoop = getLoopFor(MBB);
224 // Don't leave loops, and never follow back-edges.
225 if (CurLoop && MBB == CurLoop->getHeader())
226 return 0;
227 unsigned CurCount = CT.getResources(MBB)->InstrCount;
228 const MachineBasicBlock *Best = 0;
229 unsigned BestDepth = 0;
230 for (MachineBasicBlock::const_pred_iterator
231 I = MBB->pred_begin(), E = MBB->pred_end(); I != E; ++I) {
232 const MachineBasicBlock *Pred = *I;
233 const MachineTraceMetrics::TraceBlockInfo *PredTBI =
234 getDepthResources(Pred);
235 // Ignore invalidated predecessors. This never happens on the first scan,
236 // but if we rejected this predecessor earlier, it won't be revalidated.
237 if (!PredTBI)
238 continue;
239 // Don't consider predecessors in other loops.
240 if (getLoopFor(Pred) != CurLoop)
241 continue;
242 // Pick the predecessor that would give this block the smallest InstrDepth.
243 unsigned Depth = PredTBI->InstrDepth + CurCount;
244 if (!Best || Depth < BestDepth)
245 Best = Pred, BestDepth = Depth;
246 }
247 return Best;
248 }
249
250 // Select the preferred successor for MBB.
251 const MachineBasicBlock*
252 MinInstrCountEnsemble::pickTraceSucc(const MachineBasicBlock *MBB) {
253 if (MBB->pred_empty())
254 return 0;
255 MachineLoop *CurLoop = getLoopFor(MBB);
256 const MachineBasicBlock *Best = 0;
257 unsigned BestHeight = 0;
258 for (MachineBasicBlock::const_succ_iterator
259 I = MBB->succ_begin(), E = MBB->succ_end(); I != E; ++I) {
260 const MachineBasicBlock *Succ = *I;
261 const MachineTraceMetrics::TraceBlockInfo *SuccTBI =
262 getHeightResources(Succ);
263 // Ignore invalidated successors.
264 if (!SuccTBI)
265 continue;
266 // Don't consider back-edges.
267 if (CurLoop && Succ == CurLoop->getHeader())
268 continue;
269 // Don't consider successors in other loops.
270 if (getLoopFor(Succ) != CurLoop)
271 continue;
272 // Pick the successor that would give this block the smallest InstrHeight.
273 unsigned Height = SuccTBI->InstrHeight;
274 if (!Best || Height < BestHeight)
275 Best = Succ, BestHeight = Height;
276 }
277 return Best;
278 }
279
280 // Get an Ensemble sub-class for the requested trace strategy.
281 MachineTraceMetrics::Ensemble *
282 MachineTraceMetrics::getEnsemble(MachineTraceMetrics::Strategy strategy) {
283 assert(strategy < TS_NumStrategies && "Invalid trace strategy enum");
284 Ensemble *&E = Ensembles[strategy];
285 if (E)
286 return E;
287
288 // Allocate new Ensemble on demand.
289 switch (strategy) {
290 case TS_MinInstrCount: return (E = new MinInstrCountEnsemble(this));
291 default: llvm_unreachable("Invalid trace strategy enum");
292 }
293 }
294
295 void MachineTraceMetrics::invalidate(const MachineBasicBlock *MBB) {
296 DEBUG(dbgs() << "Invalidate traces through BB#" << MBB->getNumber() << '\n');
297 BlockInfo[MBB->getNumber()].invalidate();
298 for (unsigned i = 0; i != TS_NumStrategies; ++i)
299 if (Ensembles[i])
300 Ensembles[i]->invalidate(MBB);
301 }
302
303 //===----------------------------------------------------------------------===//
304 // Trace building
305 //===----------------------------------------------------------------------===//
306 //
307 // Traces are built by two CFG traversals. To avoid recomputing too much, use a
308 // set abstraction that confines the search to the current loop, and doesn't
309 // revisit blocks.
310
311 namespace {
312 struct LoopBounds {
313 MutableArrayRef Blocks;
314 const MachineLoopInfo *Loops;
315 const MachineLoop *CurLoop;
316 bool Downward;
317 LoopBounds(MutableArrayRef blocks,
318 const MachineLoopInfo *loops, const MachineLoop *curloop)
319 : Blocks(blocks), Loops(loops), CurLoop(curloop), Downward(false) {}
320 };
321 }
322
323 // Specialize po_iterator_storage in order to prune the post-order traversal so
324 // it is limited to the current loop and doesn't traverse the loop back edges.
325 namespace llvm {
326 template<>
327 class po_iterator_storage {
328 LoopBounds &LB;
329 public:
330 po_iterator_storage(LoopBounds &lb) : LB(lb) {}
331 void finishPostorder(const MachineBasicBlock*) {}
332
333 bool insertEdge(const MachineBasicBlock *From, const MachineBasicBlock *To) {
334 // Skip already visited To blocks.
335 MachineTraceMetrics::TraceBlockInfo &TBI = LB.Blocks[To->getNumber()];
336 if (LB.Downward ? TBI.hasValidHeight() : TBI.hasValidDepth())
337 return false;
338 // Don't follow CurLoop backedges.
339 if (LB.CurLoop && (LB.Downward ? To : From) == LB.CurLoop->getHeader())
340 return false;
341 // Don't leave CurLoop.
342 if (LB.Loops->getLoopFor(To) != LB.CurLoop)
343 return false;
344 // This is a new block. The PO traversal will compute height/depth
345 // resources, causing us to reject new edges to To. This only works because
346 // we reject back-edges, so the CFG is cycle-free.
347 return true;
348 }
349 };
350 }
351
352 /// Compute the trace through MBB.
353 void MachineTraceMetrics::Ensemble::computeTrace(const MachineBasicBlock *MBB) {
354 DEBUG(dbgs() << "Computing " << getName() << " trace through BB#"
355 << MBB->getNumber() << '\n');
356 // Set up loop bounds for the backwards post-order traversal.
357 LoopBounds Bounds(BlockInfo, CT.Loops, getLoopFor(MBB));
358
359 // Run an upwards post-order search for the trace start.
360 Bounds.Downward = false;
361 typedef ipo_ext_iterator UpwardPO;
362 for (UpwardPO I = ipo_ext_begin(MBB, Bounds), E = ipo_ext_end(MBB, Bounds);
363 I != E; ++I) {
364 DEBUG(dbgs() << " pred for BB#" << I->getNumber() << ": ");
365 TraceBlockInfo &TBI = BlockInfo[I->getNumber()];
366 // All the predecessors have been visited, pick the preferred one.
367 TBI.Pred = pickTracePred(*I);
368 DEBUG({
369 if (TBI.Pred)
370 dbgs() << "BB#" << TBI.Pred->getNumber() << '\n';
371 else
372 dbgs() << "null\n";
373 });
374 // The trace leading to I is now known, compute the depth resources.
375 computeDepthResources(*I);
376 }
377
378 // Run a downwards post-order search for the trace end.
379 Bounds.Downward = true;
380 typedef po_ext_iterator DownwardPO;
381 for (DownwardPO I = po_ext_begin(MBB, Bounds), E = po_ext_end(MBB, Bounds);
382 I != E; ++I) {
383 DEBUG(dbgs() << " succ for BB#" << I->getNumber() << ": ");
384 TraceBlockInfo &TBI = BlockInfo[I->getNumber()];
385 // All the successors have been visited, pick the preferred one.
386 BlockInfo[I->getNumber()].Succ = pickTraceSucc(*I);
387 DEBUG({
388 if (TBI.Pred)
389 dbgs() << "BB#" << TBI.Succ->getNumber() << '\n';
390 else
391 dbgs() << "null\n";
392 });
393 // The trace leaving I is now known, compute the height resources.
394 computeHeightResources(*I);
395 }
396 }
397
398 /// Invalidate traces through BadMBB.
399 void
400 MachineTraceMetrics::Ensemble::invalidate(const MachineBasicBlock *BadMBB) {
401 SmallVector WorkList;
402 TraceBlockInfo &BadTBI = BlockInfo[BadMBB->getNumber()];
403
404 // Invalidate height resources of blocks above MBB.
405 if (BadTBI.hasValidHeight()) {
406 BadTBI.invalidateHeight();
407 WorkList.push_back(BadMBB);
408 do {
409 const MachineBasicBlock *MBB = WorkList.pop_back_val();
410 DEBUG(dbgs() << "Invalidate BB#" << MBB->getNumber() << ' ' << getName()
411 << " height.\n");
412 // Find any MBB predecessors that have MBB as their preferred successor.
413 // They are the only ones that need to be invalidated.
414 for (MachineBasicBlock::const_pred_iterator
415 I = MBB->pred_begin(), E = MBB->pred_end(); I != E; ++I) {
416 TraceBlockInfo &TBI = BlockInfo[(*I)->getNumber()];
417 if (TBI.hasValidHeight() && TBI.Succ == MBB) {
418 TBI.invalidateHeight();
419 WorkList.push_back(*I);
420 }
421 }
422 } while (!WorkList.empty());
423 }
424
425 // Invalidate depth resources of blocks below MBB.
426 if (BadTBI.hasValidDepth()) {
427 BadTBI.invalidateDepth();
428 WorkList.push_back(BadMBB);
429 do {
430 const MachineBasicBlock *MBB = WorkList.pop_back_val();
431 DEBUG(dbgs() << "Invalidate BB#" << MBB->getNumber() << ' ' << getName()
432 << " depth.\n");
433 // Find any MBB successors that have MBB as their preferred predecessor.
434 // They are the only ones that need to be invalidated.
435 for (MachineBasicBlock::const_succ_iterator
436 I = MBB->succ_begin(), E = MBB->succ_end(); I != E; ++I) {
437 TraceBlockInfo &TBI = BlockInfo[(*I)->getNumber()];
438 if (TBI.hasValidDepth() && TBI.Pred == MBB) {
439 TBI.invalidateDepth();
440 WorkList.push_back(*I);
441 }
442 }
443 } while (!WorkList.empty());
444 }
445 }
446
447
448 MachineTraceMetrics::Trace
449 MachineTraceMetrics::Ensemble::getTrace(const MachineBasicBlock *MBB) {
450 // FIXME: Check cache tags, recompute as needed.
451 computeTrace(MBB);
452 return Trace(*this, BlockInfo[MBB->getNumber()]);
453 }
454
455 void MachineTraceMetrics::Trace::print(raw_ostream &OS) const {
456 OS << TE.getName() << " trace:";
457 if (TBI.hasValidHeight() && TBI.hasValidDepth())
458 OS << ' ' << getInstrCount() << " instrs.";
459
460 const MachineTraceMetrics::TraceBlockInfo *Block = &TBI;
461 OS << "\n *";
462 while (Block->hasValidDepth() && Block->Pred) {
463 unsigned Num = Block->Pred->getNumber();
464 OS << " <- BB#" << Num;
465 Block = &TE.BlockInfo[Num];
466 }
467
468 Block = &TBI;
469 OS << "\n *";
470 while (Block->hasValidHeight() && Block->Succ) {
471 unsigned Num = Block->Succ->getNumber();
472 OS << " -> BB#" << Num;
473 Block = &TE.BlockInfo[Num];
474 }
475 OS << '\n';
476 }
0 //===- lib/CodeGen/MachineTraceMetrics.h - Super-scalar metrics -*- C++ -*-===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines the interface for the MachineTraceMetrics analysis pass
10 // that estimates CPU resource usage and critical data dependency paths through
11 // preferred traces. This is useful for super-scalar CPUs where execution speed
12 // can be limited both by data dependencies and by limited execution resources.
13 //
14 // Out-of-order CPUs will often be executing instructions from multiple basic
15 // blocks at the same time. This makes it difficult to estimate the resource
16 // usage accurately in a single basic block. Resources can be estimated better
17 // by looking at a trace through the current basic block.
18 //
19 // For every block, the MachineTraceMetrics pass will pick a preferred trace
20 // that passes through the block. The trace is chosen based on loop structure,
21 // branch probabilities, and resource usage. The intention is to pick likely
22 // traces that would be the most affected by code transformations.
23 //
24 // It is expensive to compute a full arbitrary trace for every block, so to
25 // save some computations, traces are chosen to be convergent. This means that
26 // if the traces through basic blocks A and B ever cross when moving away from
27 // A and B, they never diverge again. This applies in both directions - If the
28 // traces meet above A and B, they won't diverge when going further back.
29 //
30 // Traces tend to align with loops. The trace through a block in an inner loop
31 // will begin at the loop entry block and end at a back edge. If there are
32 // nested loops, the trace may begin and end at those instead.
33 //
34 // For each trace, we compute the critical path length, which is the number of
35 // cycles required to execute the trace when execution is limited by data
36 // dependencies only. We also compute the resource height, which is the number
37 // of cycles required to execute all instructions in the trace when ignoring
38 // data dependencies.
39 //
40 // Every instruction in the current block has a slack - the number of cycles
41 // execution of the instruction can be delayed without extending the critical
42 // path.
43 //
44 //===----------------------------------------------------------------------===//
45
46 #ifndef LLVM_CODEGEN_MACHINE_TRACE_METRICS_H
47 #define LLVM_CODEGEN_MACHINE_TRACE_METRICS_H
48
49 #include "llvm/ADT/SmallVector.h"
50 #include "llvm/CodeGen/MachineFunctionPass.h"
51
52 namespace llvm {
53
54 class TargetInstrInfo;
55 class TargetRegisterInfo;
56 class MachineBasicBlock;
57 class MachineRegisterInfo;
58 class MachineLoopInfo;
59 class MachineLoop;
60 class raw_ostream;
61
62 class MachineTraceMetrics : public MachineFunctionPass {
63 const TargetInstrInfo *TII;
64 const TargetRegisterInfo *TRI;
65 const MachineRegisterInfo *MRI;
66 const MachineLoopInfo *Loops;
67
68 public:
69 class Ensemble;
70 class Trace;
71 static char ID;
72 MachineTraceMetrics();
73 void getAnalysisUsage(AnalysisUsage&) const;
74 bool runOnMachineFunction(MachineFunction&);
75 void releaseMemory();
76
77 friend class Ensemble;
78 friend class Trace;
79
80 /// Per-basic block information that doesn't depend on the trace through the
81 /// block.
82 struct FixedBlockInfo {
83 /// The number of non-trivial instructions in the block.
84 /// Doesn't count PHI and COPY instructions that are likely to be removed.
85 unsigned InstrCount;
86
87 /// True when the block contains calls.
88 bool HasCalls;
89
90 FixedBlockInfo() : InstrCount(~0u), HasCalls(false) {}
91
92 /// Returns true when resource information for this block has been computed.
93 bool hasResources() const { return InstrCount != ~0u; }
94
95 /// Invalidate resource information.
96 void invalidate() { InstrCount = ~0u; }
97 };
98
99 /// Get the fixed resource information about MBB. Compute it on demand.
100 const FixedBlockInfo *getResources(const MachineBasicBlock*);
101
102 /// Per-basic block information that relates to a specific trace through the
103 /// block. Convergent traces means that only one of these is required per
104 /// block in a trace ensemble.
105 struct TraceBlockInfo {
106 /// Trace predecessor, or NULL for the first block in the trace.
107 const MachineBasicBlock *Pred;
108
109 /// Trace successor, or NULL for the last block in the trace.
110 const MachineBasicBlock *Succ;
111
112 /// Accumulated number of instructions in the trace above this block.
113 /// Does not include instructions in this block.
114 unsigned InstrDepth;
115
116 /// Accumulated number of instructions in the trace below this block.
117 /// Includes instructions in this block.
118 unsigned InstrHeight;
119
120 TraceBlockInfo() : Pred(0), Succ(0), InstrDepth(~0u), InstrHeight(~0u) {}
121
122 /// Returns true if the depth resources have been computed from the trace
123 /// above this block.
124 bool hasValidDepth() const { return InstrDepth != ~0u; }
125
126 /// Returns true if the height resources have been computed from the trace
127 /// below this block.
128 bool hasValidHeight() const { return InstrHeight != ~0u; }
129
130 /// Invalidate depth resources when some block above this one has changed.
131 void invalidateDepth() { InstrDepth = ~0u; }
132
133 /// Invalidate height resources when a block below this one has changed.
134 void invalidateHeight() { InstrHeight = ~0u; }
135 };
136
137 /// A trace represents a plausible sequence of executed basic blocks that
138 /// passes through the current basic block one. The Trace class serves as a
139 /// handle to internal cached data structures.
140 class Trace {
141 Ensemble &TE;
142 TraceBlockInfo &TBI;
143
144 public:
145 explicit Trace(Ensemble &te, TraceBlockInfo &tbi) : TE(te), TBI(tbi) {}
146 void print(raw_ostream&) const;
147
148 /// Compute the total number of instructions in the trace.
149 unsigned getInstrCount() const {
150 return TBI.InstrDepth + TBI.InstrHeight;
151 }
152 };
153
154 /// A trace ensemble is a collection of traces selected using the same
155 /// strategy, for example 'minimum resource height'. There is one trace for
156 /// every block in the function.
157 class Ensemble {
158 SmallVector BlockInfo;
159 friend class Trace;
160
161 void computeTrace(const MachineBasicBlock*);
162 void computeDepthResources(const MachineBasicBlock*);
163 void computeHeightResources(const MachineBasicBlock*);
164
165 protected:
166 MachineTraceMetrics &CT;
167 virtual const MachineBasicBlock *pickTracePred(const MachineBasicBlock*) =0;
168 virtual const MachineBasicBlock *pickTraceSucc(const MachineBasicBlock*) =0;
169 explicit Ensemble(MachineTraceMetrics*);
170 MachineLoop *getLoopFor(const MachineBasicBlock*);
171 const TraceBlockInfo *getDepthResources(const MachineBasicBlock*) const;
172 const TraceBlockInfo *getHeightResources(const MachineBasicBlock*) const;
173
174 public:
175 virtual ~Ensemble();
176 virtual const char *getName() =0;
177 void invalidate(const MachineBasicBlock *MBB);
178
179 /// Get the trace that passes through MBB.
180 /// The trace is computed on demand.
181 Trace getTrace(const MachineBasicBlock *MBB);
182 };
183
184 /// Strategies for selecting traces.
185 enum Strategy {
186 /// Select the trace through a block that has the fewest instructions.
187 TS_MinInstrCount,
188
189 TS_NumStrategies
190 };
191
192 /// Get the trace ensemble representing the given trace selection strategy.
193 /// The returned Ensemble object is owned by the MachineTraceMetrics analysis,
194 /// and valid for the lifetime of the analysis pass.
195 Ensemble *getEnsemble(Strategy);
196
197 /// Invalidate cached information about MBB. This must be called *before* MBB
198 /// is erased, or the CFG is otherwise changed.
199 void invalidate(const MachineBasicBlock *MBB);
200
201 private:
202 // One entry per basic block, indexed by block number.
203 SmallVector BlockInfo;
204
205 // One ensemble per strategy.
206 Ensemble* Ensembles[TS_NumStrategies];
207 };
208
209 inline raw_ostream &operator<<(raw_ostream &OS,
210 const MachineTraceMetrics::Trace &Tr) {
211 Tr.print(OS);
212 return OS;
213 }
214
215 } // end namespace llvm
216
217 #endif