17a7e6055SDimitry Andric //===- lib/CodeGen/MachineTraceMetrics.cpp --------------------------------===//
27ae0e2c9SDimitry Andric //
37ae0e2c9SDimitry Andric // The LLVM Compiler Infrastructure
47ae0e2c9SDimitry Andric //
57ae0e2c9SDimitry Andric // This file is distributed under the University of Illinois Open Source
67ae0e2c9SDimitry Andric // License. See LICENSE.TXT for details.
77ae0e2c9SDimitry Andric //
87ae0e2c9SDimitry Andric //===----------------------------------------------------------------------===//
97ae0e2c9SDimitry Andric
10db17bf38SDimitry Andric #include "llvm/CodeGen/MachineTraceMetrics.h"
117a7e6055SDimitry Andric #include "llvm/ADT/ArrayRef.h"
127a7e6055SDimitry Andric #include "llvm/ADT/DenseMap.h"
137a7e6055SDimitry Andric #include "llvm/ADT/Optional.h"
14139f7f9bSDimitry Andric #include "llvm/ADT/PostOrderIterator.h"
157a7e6055SDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
167a7e6055SDimitry Andric #include "llvm/ADT/SmallVector.h"
17139f7f9bSDimitry Andric #include "llvm/ADT/SparseSet.h"
187ae0e2c9SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
197ae0e2c9SDimitry Andric #include "llvm/CodeGen/MachineBranchProbabilityInfo.h"
207a7e6055SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
217a7e6055SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
227ae0e2c9SDimitry Andric #include "llvm/CodeGen/MachineLoopInfo.h"
237a7e6055SDimitry Andric #include "llvm/CodeGen/MachineOperand.h"
247ae0e2c9SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
252cab237bSDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
262cab237bSDimitry Andric #include "llvm/CodeGen/TargetSchedule.h"
272cab237bSDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
287a7e6055SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
297a7e6055SDimitry Andric #include "llvm/Pass.h"
30139f7f9bSDimitry Andric #include "llvm/Support/Debug.h"
317a7e6055SDimitry Andric #include "llvm/Support/ErrorHandling.h"
32139f7f9bSDimitry Andric #include "llvm/Support/Format.h"
33139f7f9bSDimitry Andric #include "llvm/Support/raw_ostream.h"
347a7e6055SDimitry Andric #include <algorithm>
357a7e6055SDimitry Andric #include <cassert>
367a7e6055SDimitry Andric #include <iterator>
377a7e6055SDimitry Andric #include <tuple>
387a7e6055SDimitry Andric #include <utility>
397ae0e2c9SDimitry Andric
407ae0e2c9SDimitry Andric using namespace llvm;
417ae0e2c9SDimitry Andric
4291bc56edSDimitry Andric #define DEBUG_TYPE "machine-trace-metrics"
4391bc56edSDimitry Andric
447ae0e2c9SDimitry Andric char MachineTraceMetrics::ID = 0;
452cab237bSDimitry Andric
467ae0e2c9SDimitry Andric char &llvm::MachineTraceMetricsID = MachineTraceMetrics::ID;
477ae0e2c9SDimitry Andric
48302affcbSDimitry Andric INITIALIZE_PASS_BEGIN(MachineTraceMetrics, DEBUG_TYPE,
49302affcbSDimitry Andric "Machine Trace Metrics", false, true)
INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfo)507ae0e2c9SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfo)
517ae0e2c9SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo)
52302affcbSDimitry Andric INITIALIZE_PASS_END(MachineTraceMetrics, DEBUG_TYPE,
53302affcbSDimitry Andric "Machine Trace Metrics", false, true)
547ae0e2c9SDimitry Andric
557a7e6055SDimitry Andric MachineTraceMetrics::MachineTraceMetrics() : MachineFunctionPass(ID) {
5691bc56edSDimitry Andric std::fill(std::begin(Ensembles), std::end(Ensembles), nullptr);
577ae0e2c9SDimitry Andric }
587ae0e2c9SDimitry Andric
getAnalysisUsage(AnalysisUsage & AU) const597ae0e2c9SDimitry Andric void MachineTraceMetrics::getAnalysisUsage(AnalysisUsage &AU) const {
607ae0e2c9SDimitry Andric AU.setPreservesAll();
617ae0e2c9SDimitry Andric AU.addRequired<MachineBranchProbabilityInfo>();
627ae0e2c9SDimitry Andric AU.addRequired<MachineLoopInfo>();
637ae0e2c9SDimitry Andric MachineFunctionPass::getAnalysisUsage(AU);
647ae0e2c9SDimitry Andric }
657ae0e2c9SDimitry Andric
runOnMachineFunction(MachineFunction & Func)667ae0e2c9SDimitry Andric bool MachineTraceMetrics::runOnMachineFunction(MachineFunction &Func) {
677ae0e2c9SDimitry Andric MF = &Func;
68ff0cc061SDimitry Andric const TargetSubtargetInfo &ST = MF->getSubtarget();
69ff0cc061SDimitry Andric TII = ST.getInstrInfo();
70ff0cc061SDimitry Andric TRI = ST.getRegisterInfo();
717ae0e2c9SDimitry Andric MRI = &MF->getRegInfo();
727ae0e2c9SDimitry Andric Loops = &getAnalysis<MachineLoopInfo>();
734ba319b5SDimitry Andric SchedModel.init(&ST);
747ae0e2c9SDimitry Andric BlockInfo.resize(MF->getNumBlockIDs());
75139f7f9bSDimitry Andric ProcResourceCycles.resize(MF->getNumBlockIDs() *
76139f7f9bSDimitry Andric SchedModel.getNumProcResourceKinds());
777ae0e2c9SDimitry Andric return false;
787ae0e2c9SDimitry Andric }
797ae0e2c9SDimitry Andric
releaseMemory()807ae0e2c9SDimitry Andric void MachineTraceMetrics::releaseMemory() {
8191bc56edSDimitry Andric MF = nullptr;
827ae0e2c9SDimitry Andric BlockInfo.clear();
837ae0e2c9SDimitry Andric for (unsigned i = 0; i != TS_NumStrategies; ++i) {
847ae0e2c9SDimitry Andric delete Ensembles[i];
8591bc56edSDimitry Andric Ensembles[i] = nullptr;
867ae0e2c9SDimitry Andric }
877ae0e2c9SDimitry Andric }
887ae0e2c9SDimitry Andric
897ae0e2c9SDimitry Andric //===----------------------------------------------------------------------===//
907ae0e2c9SDimitry Andric // Fixed block information
917ae0e2c9SDimitry Andric //===----------------------------------------------------------------------===//
927ae0e2c9SDimitry Andric //
937ae0e2c9SDimitry Andric // The number of instructions in a basic block and the CPU resources used by
947ae0e2c9SDimitry Andric // those instructions don't depend on any given trace strategy.
957ae0e2c9SDimitry Andric
967ae0e2c9SDimitry Andric /// Compute the resource usage in basic block MBB.
977ae0e2c9SDimitry Andric const MachineTraceMetrics::FixedBlockInfo*
getResources(const MachineBasicBlock * MBB)987ae0e2c9SDimitry Andric MachineTraceMetrics::getResources(const MachineBasicBlock *MBB) {
997ae0e2c9SDimitry Andric assert(MBB && "No basic block");
1007ae0e2c9SDimitry Andric FixedBlockInfo *FBI = &BlockInfo[MBB->getNumber()];
1017ae0e2c9SDimitry Andric if (FBI->hasResources())
1027ae0e2c9SDimitry Andric return FBI;
1037ae0e2c9SDimitry Andric
1047ae0e2c9SDimitry Andric // Compute resource usage in the block.
1057ae0e2c9SDimitry Andric FBI->HasCalls = false;
1067ae0e2c9SDimitry Andric unsigned InstrCount = 0;
107139f7f9bSDimitry Andric
108139f7f9bSDimitry Andric // Add up per-processor resource cycles as well.
109139f7f9bSDimitry Andric unsigned PRKinds = SchedModel.getNumProcResourceKinds();
110139f7f9bSDimitry Andric SmallVector<unsigned, 32> PRCycles(PRKinds);
111139f7f9bSDimitry Andric
11291bc56edSDimitry Andric for (const auto &MI : *MBB) {
11391bc56edSDimitry Andric if (MI.isTransient())
1147ae0e2c9SDimitry Andric continue;
1157ae0e2c9SDimitry Andric ++InstrCount;
11691bc56edSDimitry Andric if (MI.isCall())
1177ae0e2c9SDimitry Andric FBI->HasCalls = true;
118139f7f9bSDimitry Andric
119139f7f9bSDimitry Andric // Count processor resources used.
120139f7f9bSDimitry Andric if (!SchedModel.hasInstrSchedModel())
121139f7f9bSDimitry Andric continue;
12291bc56edSDimitry Andric const MCSchedClassDesc *SC = SchedModel.resolveSchedClass(&MI);
123139f7f9bSDimitry Andric if (!SC->isValid())
124139f7f9bSDimitry Andric continue;
125139f7f9bSDimitry Andric
126139f7f9bSDimitry Andric for (TargetSchedModel::ProcResIter
127139f7f9bSDimitry Andric PI = SchedModel.getWriteProcResBegin(SC),
128139f7f9bSDimitry Andric PE = SchedModel.getWriteProcResEnd(SC); PI != PE; ++PI) {
129139f7f9bSDimitry Andric assert(PI->ProcResourceIdx < PRKinds && "Bad processor resource kind");
130139f7f9bSDimitry Andric PRCycles[PI->ProcResourceIdx] += PI->Cycles;
131139f7f9bSDimitry Andric }
1327ae0e2c9SDimitry Andric }
1337ae0e2c9SDimitry Andric FBI->InstrCount = InstrCount;
134139f7f9bSDimitry Andric
135139f7f9bSDimitry Andric // Scale the resource cycles so they are comparable.
136139f7f9bSDimitry Andric unsigned PROffset = MBB->getNumber() * PRKinds;
137139f7f9bSDimitry Andric for (unsigned K = 0; K != PRKinds; ++K)
138139f7f9bSDimitry Andric ProcResourceCycles[PROffset + K] =
139139f7f9bSDimitry Andric PRCycles[K] * SchedModel.getResourceFactor(K);
140139f7f9bSDimitry Andric
1417ae0e2c9SDimitry Andric return FBI;
1427ae0e2c9SDimitry Andric }
1437ae0e2c9SDimitry Andric
144139f7f9bSDimitry Andric ArrayRef<unsigned>
getProcResourceCycles(unsigned MBBNum) const145139f7f9bSDimitry Andric MachineTraceMetrics::getProcResourceCycles(unsigned MBBNum) const {
146139f7f9bSDimitry Andric assert(BlockInfo[MBBNum].hasResources() &&
147139f7f9bSDimitry Andric "getResources() must be called before getProcResourceCycles()");
148139f7f9bSDimitry Andric unsigned PRKinds = SchedModel.getNumProcResourceKinds();
149139f7f9bSDimitry Andric assert((MBBNum+1) * PRKinds <= ProcResourceCycles.size());
15039d628a0SDimitry Andric return makeArrayRef(ProcResourceCycles.data() + MBBNum * PRKinds, PRKinds);
151139f7f9bSDimitry Andric }
152139f7f9bSDimitry Andric
1537ae0e2c9SDimitry Andric //===----------------------------------------------------------------------===//
1547ae0e2c9SDimitry Andric // Ensemble utility functions
1557ae0e2c9SDimitry Andric //===----------------------------------------------------------------------===//
1567ae0e2c9SDimitry Andric
Ensemble(MachineTraceMetrics * ct)1577ae0e2c9SDimitry Andric MachineTraceMetrics::Ensemble::Ensemble(MachineTraceMetrics *ct)
1587ae0e2c9SDimitry Andric : MTM(*ct) {
1597ae0e2c9SDimitry Andric BlockInfo.resize(MTM.BlockInfo.size());
160139f7f9bSDimitry Andric unsigned PRKinds = MTM.SchedModel.getNumProcResourceKinds();
161139f7f9bSDimitry Andric ProcResourceDepths.resize(MTM.BlockInfo.size() * PRKinds);
162139f7f9bSDimitry Andric ProcResourceHeights.resize(MTM.BlockInfo.size() * PRKinds);
1637ae0e2c9SDimitry Andric }
1647ae0e2c9SDimitry Andric
1657ae0e2c9SDimitry Andric // Virtual destructor serves as an anchor.
1667a7e6055SDimitry Andric MachineTraceMetrics::Ensemble::~Ensemble() = default;
1677ae0e2c9SDimitry Andric
1687ae0e2c9SDimitry Andric const MachineLoop*
getLoopFor(const MachineBasicBlock * MBB) const1697ae0e2c9SDimitry Andric MachineTraceMetrics::Ensemble::getLoopFor(const MachineBasicBlock *MBB) const {
1707ae0e2c9SDimitry Andric return MTM.Loops->getLoopFor(MBB);
1717ae0e2c9SDimitry Andric }
1727ae0e2c9SDimitry Andric
1737ae0e2c9SDimitry Andric // Update resource-related information in the TraceBlockInfo for MBB.
1747ae0e2c9SDimitry Andric // Only update resources related to the trace above MBB.
1757ae0e2c9SDimitry Andric void MachineTraceMetrics::Ensemble::
computeDepthResources(const MachineBasicBlock * MBB)1767ae0e2c9SDimitry Andric computeDepthResources(const MachineBasicBlock *MBB) {
1777ae0e2c9SDimitry Andric TraceBlockInfo *TBI = &BlockInfo[MBB->getNumber()];
178139f7f9bSDimitry Andric unsigned PRKinds = MTM.SchedModel.getNumProcResourceKinds();
179139f7f9bSDimitry Andric unsigned PROffset = MBB->getNumber() * PRKinds;
1807ae0e2c9SDimitry Andric
1817ae0e2c9SDimitry Andric // Compute resources from trace above. The top block is simple.
1827ae0e2c9SDimitry Andric if (!TBI->Pred) {
1837ae0e2c9SDimitry Andric TBI->InstrDepth = 0;
1847ae0e2c9SDimitry Andric TBI->Head = MBB->getNumber();
185139f7f9bSDimitry Andric std::fill(ProcResourceDepths.begin() + PROffset,
186139f7f9bSDimitry Andric ProcResourceDepths.begin() + PROffset + PRKinds, 0);
1877ae0e2c9SDimitry Andric return;
1887ae0e2c9SDimitry Andric }
1897ae0e2c9SDimitry Andric
1907ae0e2c9SDimitry Andric // Compute from the block above. A post-order traversal ensures the
1917ae0e2c9SDimitry Andric // predecessor is always computed first.
192139f7f9bSDimitry Andric unsigned PredNum = TBI->Pred->getNumber();
193139f7f9bSDimitry Andric TraceBlockInfo *PredTBI = &BlockInfo[PredNum];
1947ae0e2c9SDimitry Andric assert(PredTBI->hasValidDepth() && "Trace above has not been computed yet");
1957ae0e2c9SDimitry Andric const FixedBlockInfo *PredFBI = MTM.getResources(TBI->Pred);
1967ae0e2c9SDimitry Andric TBI->InstrDepth = PredTBI->InstrDepth + PredFBI->InstrCount;
1977ae0e2c9SDimitry Andric TBI->Head = PredTBI->Head;
198139f7f9bSDimitry Andric
199139f7f9bSDimitry Andric // Compute per-resource depths.
200139f7f9bSDimitry Andric ArrayRef<unsigned> PredPRDepths = getProcResourceDepths(PredNum);
201139f7f9bSDimitry Andric ArrayRef<unsigned> PredPRCycles = MTM.getProcResourceCycles(PredNum);
202139f7f9bSDimitry Andric for (unsigned K = 0; K != PRKinds; ++K)
203139f7f9bSDimitry Andric ProcResourceDepths[PROffset + K] = PredPRDepths[K] + PredPRCycles[K];
2047ae0e2c9SDimitry Andric }
2057ae0e2c9SDimitry Andric
2067ae0e2c9SDimitry Andric // Update resource-related information in the TraceBlockInfo for MBB.
2077ae0e2c9SDimitry Andric // Only update resources related to the trace below MBB.
2087ae0e2c9SDimitry Andric void MachineTraceMetrics::Ensemble::
computeHeightResources(const MachineBasicBlock * MBB)2097ae0e2c9SDimitry Andric computeHeightResources(const MachineBasicBlock *MBB) {
2107ae0e2c9SDimitry Andric TraceBlockInfo *TBI = &BlockInfo[MBB->getNumber()];
211139f7f9bSDimitry Andric unsigned PRKinds = MTM.SchedModel.getNumProcResourceKinds();
212139f7f9bSDimitry Andric unsigned PROffset = MBB->getNumber() * PRKinds;
2137ae0e2c9SDimitry Andric
2147ae0e2c9SDimitry Andric // Compute resources for the current block.
2157ae0e2c9SDimitry Andric TBI->InstrHeight = MTM.getResources(MBB)->InstrCount;
216139f7f9bSDimitry Andric ArrayRef<unsigned> PRCycles = MTM.getProcResourceCycles(MBB->getNumber());
2177ae0e2c9SDimitry Andric
2187ae0e2c9SDimitry Andric // The trace tail is done.
2197ae0e2c9SDimitry Andric if (!TBI->Succ) {
2207ae0e2c9SDimitry Andric TBI->Tail = MBB->getNumber();
221*b5893f02SDimitry Andric llvm::copy(PRCycles, ProcResourceHeights.begin() + PROffset);
2227ae0e2c9SDimitry Andric return;
2237ae0e2c9SDimitry Andric }
2247ae0e2c9SDimitry Andric
2257ae0e2c9SDimitry Andric // Compute from the block below. A post-order traversal ensures the
2267ae0e2c9SDimitry Andric // predecessor is always computed first.
227139f7f9bSDimitry Andric unsigned SuccNum = TBI->Succ->getNumber();
228139f7f9bSDimitry Andric TraceBlockInfo *SuccTBI = &BlockInfo[SuccNum];
2297ae0e2c9SDimitry Andric assert(SuccTBI->hasValidHeight() && "Trace below has not been computed yet");
2307ae0e2c9SDimitry Andric TBI->InstrHeight += SuccTBI->InstrHeight;
2317ae0e2c9SDimitry Andric TBI->Tail = SuccTBI->Tail;
232139f7f9bSDimitry Andric
233139f7f9bSDimitry Andric // Compute per-resource heights.
234139f7f9bSDimitry Andric ArrayRef<unsigned> SuccPRHeights = getProcResourceHeights(SuccNum);
235139f7f9bSDimitry Andric for (unsigned K = 0; K != PRKinds; ++K)
236139f7f9bSDimitry Andric ProcResourceHeights[PROffset + K] = SuccPRHeights[K] + PRCycles[K];
2377ae0e2c9SDimitry Andric }
2387ae0e2c9SDimitry Andric
2397ae0e2c9SDimitry Andric // Check if depth resources for MBB are valid and return the TBI.
2407ae0e2c9SDimitry Andric // Return NULL if the resources have been invalidated.
2417ae0e2c9SDimitry Andric const MachineTraceMetrics::TraceBlockInfo*
2427ae0e2c9SDimitry Andric MachineTraceMetrics::Ensemble::
getDepthResources(const MachineBasicBlock * MBB) const2437ae0e2c9SDimitry Andric getDepthResources(const MachineBasicBlock *MBB) const {
2447ae0e2c9SDimitry Andric const TraceBlockInfo *TBI = &BlockInfo[MBB->getNumber()];
24591bc56edSDimitry Andric return TBI->hasValidDepth() ? TBI : nullptr;
2467ae0e2c9SDimitry Andric }
2477ae0e2c9SDimitry Andric
2487ae0e2c9SDimitry Andric // Check if height resources for MBB are valid and return the TBI.
2497ae0e2c9SDimitry Andric // Return NULL if the resources have been invalidated.
2507ae0e2c9SDimitry Andric const MachineTraceMetrics::TraceBlockInfo*
2517ae0e2c9SDimitry Andric MachineTraceMetrics::Ensemble::
getHeightResources(const MachineBasicBlock * MBB) const2527ae0e2c9SDimitry Andric getHeightResources(const MachineBasicBlock *MBB) const {
2537ae0e2c9SDimitry Andric const TraceBlockInfo *TBI = &BlockInfo[MBB->getNumber()];
25491bc56edSDimitry Andric return TBI->hasValidHeight() ? TBI : nullptr;
2557ae0e2c9SDimitry Andric }
2567ae0e2c9SDimitry Andric
257139f7f9bSDimitry Andric /// Get an array of processor resource depths for MBB. Indexed by processor
258139f7f9bSDimitry Andric /// resource kind, this array contains the scaled processor resources consumed
259139f7f9bSDimitry Andric /// by all blocks preceding MBB in its trace. It does not include instructions
260139f7f9bSDimitry Andric /// in MBB.
261139f7f9bSDimitry Andric ///
262139f7f9bSDimitry Andric /// Compare TraceBlockInfo::InstrDepth.
263139f7f9bSDimitry Andric ArrayRef<unsigned>
264139f7f9bSDimitry Andric MachineTraceMetrics::Ensemble::
getProcResourceDepths(unsigned MBBNum) const265139f7f9bSDimitry Andric getProcResourceDepths(unsigned MBBNum) const {
266139f7f9bSDimitry Andric unsigned PRKinds = MTM.SchedModel.getNumProcResourceKinds();
267139f7f9bSDimitry Andric assert((MBBNum+1) * PRKinds <= ProcResourceDepths.size());
26839d628a0SDimitry Andric return makeArrayRef(ProcResourceDepths.data() + MBBNum * PRKinds, PRKinds);
269139f7f9bSDimitry Andric }
270139f7f9bSDimitry Andric
271139f7f9bSDimitry Andric /// Get an array of processor resource heights for MBB. Indexed by processor
272139f7f9bSDimitry Andric /// resource kind, this array contains the scaled processor resources consumed
273139f7f9bSDimitry Andric /// by this block and all blocks following it in its trace.
274139f7f9bSDimitry Andric ///
275139f7f9bSDimitry Andric /// Compare TraceBlockInfo::InstrHeight.
276139f7f9bSDimitry Andric ArrayRef<unsigned>
277139f7f9bSDimitry Andric MachineTraceMetrics::Ensemble::
getProcResourceHeights(unsigned MBBNum) const278139f7f9bSDimitry Andric getProcResourceHeights(unsigned MBBNum) const {
279139f7f9bSDimitry Andric unsigned PRKinds = MTM.SchedModel.getNumProcResourceKinds();
280139f7f9bSDimitry Andric assert((MBBNum+1) * PRKinds <= ProcResourceHeights.size());
28139d628a0SDimitry Andric return makeArrayRef(ProcResourceHeights.data() + MBBNum * PRKinds, PRKinds);
282139f7f9bSDimitry Andric }
283139f7f9bSDimitry Andric
2847ae0e2c9SDimitry Andric //===----------------------------------------------------------------------===//
2857ae0e2c9SDimitry Andric // Trace Selection Strategies
2867ae0e2c9SDimitry Andric //===----------------------------------------------------------------------===//
2877ae0e2c9SDimitry Andric //
2887ae0e2c9SDimitry Andric // A trace selection strategy is implemented as a sub-class of Ensemble. The
2897ae0e2c9SDimitry Andric // trace through a block B is computed by two DFS traversals of the CFG
2907ae0e2c9SDimitry Andric // starting from B. One upwards, and one downwards. During the upwards DFS,
2917ae0e2c9SDimitry Andric // pickTracePred() is called on the post-ordered blocks. During the downwards
2927ae0e2c9SDimitry Andric // DFS, pickTraceSucc() is called in a post-order.
2937ae0e2c9SDimitry Andric //
2947ae0e2c9SDimitry Andric
2957ae0e2c9SDimitry Andric // We never allow traces that leave loops, but we do allow traces to enter
2967ae0e2c9SDimitry Andric // nested loops. We also never allow traces to contain back-edges.
2977ae0e2c9SDimitry Andric //
2987ae0e2c9SDimitry Andric // This means that a loop header can never appear above the center block of a
2997ae0e2c9SDimitry Andric // trace, except as the trace head. Below the center block, loop exiting edges
3007ae0e2c9SDimitry Andric // are banned.
3017ae0e2c9SDimitry Andric //
3027ae0e2c9SDimitry Andric // Return true if an edge from the From loop to the To loop is leaving a loop.
3037ae0e2c9SDimitry Andric // Either of To and From can be null.
isExitingLoop(const MachineLoop * From,const MachineLoop * To)3047ae0e2c9SDimitry Andric static bool isExitingLoop(const MachineLoop *From, const MachineLoop *To) {
3057ae0e2c9SDimitry Andric return From && !From->contains(To);
3067ae0e2c9SDimitry Andric }
3077ae0e2c9SDimitry Andric
3087ae0e2c9SDimitry Andric // MinInstrCountEnsemble - Pick the trace that executes the least number of
3097ae0e2c9SDimitry Andric // instructions.
3107ae0e2c9SDimitry Andric namespace {
3117a7e6055SDimitry Andric
3127ae0e2c9SDimitry Andric class MinInstrCountEnsemble : public MachineTraceMetrics::Ensemble {
getName() const31391bc56edSDimitry Andric const char *getName() const override { return "MinInstr"; }
31491bc56edSDimitry Andric const MachineBasicBlock *pickTracePred(const MachineBasicBlock*) override;
31591bc56edSDimitry Andric const MachineBasicBlock *pickTraceSucc(const MachineBasicBlock*) override;
3167ae0e2c9SDimitry Andric
3177ae0e2c9SDimitry Andric public:
MinInstrCountEnsemble(MachineTraceMetrics * mtm)3187ae0e2c9SDimitry Andric MinInstrCountEnsemble(MachineTraceMetrics *mtm)
3197ae0e2c9SDimitry Andric : MachineTraceMetrics::Ensemble(mtm) {}
3207ae0e2c9SDimitry Andric };
3217a7e6055SDimitry Andric
3227a7e6055SDimitry Andric } // end anonymous namespace
3237ae0e2c9SDimitry Andric
3247ae0e2c9SDimitry Andric // Select the preferred predecessor for MBB.
3257ae0e2c9SDimitry Andric const MachineBasicBlock*
pickTracePred(const MachineBasicBlock * MBB)3267ae0e2c9SDimitry Andric MinInstrCountEnsemble::pickTracePred(const MachineBasicBlock *MBB) {
3277ae0e2c9SDimitry Andric if (MBB->pred_empty())
32891bc56edSDimitry Andric return nullptr;
3297ae0e2c9SDimitry Andric const MachineLoop *CurLoop = getLoopFor(MBB);
3307ae0e2c9SDimitry Andric // Don't leave loops, and never follow back-edges.
3317ae0e2c9SDimitry Andric if (CurLoop && MBB == CurLoop->getHeader())
33291bc56edSDimitry Andric return nullptr;
3337ae0e2c9SDimitry Andric unsigned CurCount = MTM.getResources(MBB)->InstrCount;
33491bc56edSDimitry Andric const MachineBasicBlock *Best = nullptr;
3357ae0e2c9SDimitry Andric unsigned BestDepth = 0;
336ff0cc061SDimitry Andric for (const MachineBasicBlock *Pred : MBB->predecessors()) {
3377ae0e2c9SDimitry Andric const MachineTraceMetrics::TraceBlockInfo *PredTBI =
3387ae0e2c9SDimitry Andric getDepthResources(Pred);
3397ae0e2c9SDimitry Andric // Ignore cycles that aren't natural loops.
3407ae0e2c9SDimitry Andric if (!PredTBI)
3417ae0e2c9SDimitry Andric continue;
3427ae0e2c9SDimitry Andric // Pick the predecessor that would give this block the smallest InstrDepth.
3437ae0e2c9SDimitry Andric unsigned Depth = PredTBI->InstrDepth + CurCount;
3443ca95b02SDimitry Andric if (!Best || Depth < BestDepth) {
3453ca95b02SDimitry Andric Best = Pred;
3463ca95b02SDimitry Andric BestDepth = Depth;
3473ca95b02SDimitry Andric }
3487ae0e2c9SDimitry Andric }
3497ae0e2c9SDimitry Andric return Best;
3507ae0e2c9SDimitry Andric }
3517ae0e2c9SDimitry Andric
3527ae0e2c9SDimitry Andric // Select the preferred successor for MBB.
3537ae0e2c9SDimitry Andric const MachineBasicBlock*
pickTraceSucc(const MachineBasicBlock * MBB)3547ae0e2c9SDimitry Andric MinInstrCountEnsemble::pickTraceSucc(const MachineBasicBlock *MBB) {
3557ae0e2c9SDimitry Andric if (MBB->pred_empty())
35691bc56edSDimitry Andric return nullptr;
3577ae0e2c9SDimitry Andric const MachineLoop *CurLoop = getLoopFor(MBB);
35891bc56edSDimitry Andric const MachineBasicBlock *Best = nullptr;
3597ae0e2c9SDimitry Andric unsigned BestHeight = 0;
360ff0cc061SDimitry Andric for (const MachineBasicBlock *Succ : MBB->successors()) {
3617ae0e2c9SDimitry Andric // Don't consider back-edges.
3627ae0e2c9SDimitry Andric if (CurLoop && Succ == CurLoop->getHeader())
3637ae0e2c9SDimitry Andric continue;
3647ae0e2c9SDimitry Andric // Don't consider successors exiting CurLoop.
3657ae0e2c9SDimitry Andric if (isExitingLoop(CurLoop, getLoopFor(Succ)))
3667ae0e2c9SDimitry Andric continue;
3677ae0e2c9SDimitry Andric const MachineTraceMetrics::TraceBlockInfo *SuccTBI =
3687ae0e2c9SDimitry Andric getHeightResources(Succ);
3697ae0e2c9SDimitry Andric // Ignore cycles that aren't natural loops.
3707ae0e2c9SDimitry Andric if (!SuccTBI)
3717ae0e2c9SDimitry Andric continue;
3727ae0e2c9SDimitry Andric // Pick the successor that would give this block the smallest InstrHeight.
3737ae0e2c9SDimitry Andric unsigned Height = SuccTBI->InstrHeight;
3743ca95b02SDimitry Andric if (!Best || Height < BestHeight) {
3753ca95b02SDimitry Andric Best = Succ;
3763ca95b02SDimitry Andric BestHeight = Height;
3773ca95b02SDimitry Andric }
3787ae0e2c9SDimitry Andric }
3797ae0e2c9SDimitry Andric return Best;
3807ae0e2c9SDimitry Andric }
3817ae0e2c9SDimitry Andric
3827ae0e2c9SDimitry Andric // Get an Ensemble sub-class for the requested trace strategy.
3837ae0e2c9SDimitry Andric MachineTraceMetrics::Ensemble *
getEnsemble(MachineTraceMetrics::Strategy strategy)3847ae0e2c9SDimitry Andric MachineTraceMetrics::getEnsemble(MachineTraceMetrics::Strategy strategy) {
3857ae0e2c9SDimitry Andric assert(strategy < TS_NumStrategies && "Invalid trace strategy enum");
3867ae0e2c9SDimitry Andric Ensemble *&E = Ensembles[strategy];
3877ae0e2c9SDimitry Andric if (E)
3887ae0e2c9SDimitry Andric return E;
3897ae0e2c9SDimitry Andric
3907ae0e2c9SDimitry Andric // Allocate new Ensemble on demand.
3917ae0e2c9SDimitry Andric switch (strategy) {
3927ae0e2c9SDimitry Andric case TS_MinInstrCount: return (E = new MinInstrCountEnsemble(this));
3937ae0e2c9SDimitry Andric default: llvm_unreachable("Invalid trace strategy enum");
3947ae0e2c9SDimitry Andric }
3957ae0e2c9SDimitry Andric }
3967ae0e2c9SDimitry Andric
invalidate(const MachineBasicBlock * MBB)3977ae0e2c9SDimitry Andric void MachineTraceMetrics::invalidate(const MachineBasicBlock *MBB) {
3984ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "Invalidate traces through " << printMBBReference(*MBB)
3992cab237bSDimitry Andric << '\n');
4007ae0e2c9SDimitry Andric BlockInfo[MBB->getNumber()].invalidate();
4017ae0e2c9SDimitry Andric for (unsigned i = 0; i != TS_NumStrategies; ++i)
4027ae0e2c9SDimitry Andric if (Ensembles[i])
4037ae0e2c9SDimitry Andric Ensembles[i]->invalidate(MBB);
4047ae0e2c9SDimitry Andric }
4057ae0e2c9SDimitry Andric
verifyAnalysis() const4067ae0e2c9SDimitry Andric void MachineTraceMetrics::verifyAnalysis() const {
4077ae0e2c9SDimitry Andric if (!MF)
4087ae0e2c9SDimitry Andric return;
4097ae0e2c9SDimitry Andric #ifndef NDEBUG
4107ae0e2c9SDimitry Andric assert(BlockInfo.size() == MF->getNumBlockIDs() && "Outdated BlockInfo size");
4117ae0e2c9SDimitry Andric for (unsigned i = 0; i != TS_NumStrategies; ++i)
4127ae0e2c9SDimitry Andric if (Ensembles[i])
4137ae0e2c9SDimitry Andric Ensembles[i]->verify();
4147ae0e2c9SDimitry Andric #endif
4157ae0e2c9SDimitry Andric }
4167ae0e2c9SDimitry Andric
4177ae0e2c9SDimitry Andric //===----------------------------------------------------------------------===//
4187ae0e2c9SDimitry Andric // Trace building
4197ae0e2c9SDimitry Andric //===----------------------------------------------------------------------===//
4207ae0e2c9SDimitry Andric //
4217ae0e2c9SDimitry Andric // Traces are built by two CFG traversals. To avoid recomputing too much, use a
4227ae0e2c9SDimitry Andric // set abstraction that confines the search to the current loop, and doesn't
4237ae0e2c9SDimitry Andric // revisit blocks.
4247ae0e2c9SDimitry Andric
4257ae0e2c9SDimitry Andric namespace {
4267a7e6055SDimitry Andric
4277ae0e2c9SDimitry Andric struct LoopBounds {
4287ae0e2c9SDimitry Andric MutableArrayRef<MachineTraceMetrics::TraceBlockInfo> Blocks;
4297ae0e2c9SDimitry Andric SmallPtrSet<const MachineBasicBlock*, 8> Visited;
4307ae0e2c9SDimitry Andric const MachineLoopInfo *Loops;
4317a7e6055SDimitry Andric bool Downward = false;
4327a7e6055SDimitry Andric
LoopBounds__anone79e02740211::LoopBounds4337ae0e2c9SDimitry Andric LoopBounds(MutableArrayRef<MachineTraceMetrics::TraceBlockInfo> blocks,
4347a7e6055SDimitry Andric const MachineLoopInfo *loops) : Blocks(blocks), Loops(loops) {}
4357ae0e2c9SDimitry Andric };
4367a7e6055SDimitry Andric
4377a7e6055SDimitry Andric } // end anonymous namespace
4387ae0e2c9SDimitry Andric
4397ae0e2c9SDimitry Andric // Specialize po_iterator_storage in order to prune the post-order traversal so
4407ae0e2c9SDimitry Andric // it is limited to the current loop and doesn't traverse the loop back edges.
4417ae0e2c9SDimitry Andric namespace llvm {
4427a7e6055SDimitry Andric
4437ae0e2c9SDimitry Andric template<>
4447ae0e2c9SDimitry Andric class po_iterator_storage<LoopBounds, true> {
4457ae0e2c9SDimitry Andric LoopBounds &LB;
4467a7e6055SDimitry Andric
4477ae0e2c9SDimitry Andric public:
po_iterator_storage(LoopBounds & lb)4487ae0e2c9SDimitry Andric po_iterator_storage(LoopBounds &lb) : LB(lb) {}
4497a7e6055SDimitry Andric
finishPostorder(const MachineBasicBlock *)4507ae0e2c9SDimitry Andric void finishPostorder(const MachineBasicBlock*) {}
4517ae0e2c9SDimitry Andric
insertEdge(Optional<const MachineBasicBlock * > From,const MachineBasicBlock * To)452d88c1a5aSDimitry Andric bool insertEdge(Optional<const MachineBasicBlock *> From,
453d88c1a5aSDimitry Andric const MachineBasicBlock *To) {
4547ae0e2c9SDimitry Andric // Skip already visited To blocks.
4557ae0e2c9SDimitry Andric MachineTraceMetrics::TraceBlockInfo &TBI = LB.Blocks[To->getNumber()];
4567ae0e2c9SDimitry Andric if (LB.Downward ? TBI.hasValidHeight() : TBI.hasValidDepth())
4577ae0e2c9SDimitry Andric return false;
4587ae0e2c9SDimitry Andric // From is null once when To is the trace center block.
4597ae0e2c9SDimitry Andric if (From) {
460d88c1a5aSDimitry Andric if (const MachineLoop *FromLoop = LB.Loops->getLoopFor(*From)) {
4617ae0e2c9SDimitry Andric // Don't follow backedges, don't leave FromLoop when going upwards.
462d88c1a5aSDimitry Andric if ((LB.Downward ? To : *From) == FromLoop->getHeader())
4637ae0e2c9SDimitry Andric return false;
4647ae0e2c9SDimitry Andric // Don't leave FromLoop.
4657ae0e2c9SDimitry Andric if (isExitingLoop(FromLoop, LB.Loops->getLoopFor(To)))
4667ae0e2c9SDimitry Andric return false;
4677ae0e2c9SDimitry Andric }
4687ae0e2c9SDimitry Andric }
4697ae0e2c9SDimitry Andric // To is a new block. Mark the block as visited in case the CFG has cycles
4707ae0e2c9SDimitry Andric // that MachineLoopInfo didn't recognize as a natural loop.
47139d628a0SDimitry Andric return LB.Visited.insert(To).second;
4727ae0e2c9SDimitry Andric }
4737ae0e2c9SDimitry Andric };
4747a7e6055SDimitry Andric
4757a7e6055SDimitry Andric } // end namespace llvm
4767ae0e2c9SDimitry Andric
4777ae0e2c9SDimitry Andric /// Compute the trace through MBB.
computeTrace(const MachineBasicBlock * MBB)4787ae0e2c9SDimitry Andric void MachineTraceMetrics::Ensemble::computeTrace(const MachineBasicBlock *MBB) {
4794ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "Computing " << getName() << " trace through "
4802cab237bSDimitry Andric << printMBBReference(*MBB) << '\n');
4817ae0e2c9SDimitry Andric // Set up loop bounds for the backwards post-order traversal.
4827ae0e2c9SDimitry Andric LoopBounds Bounds(BlockInfo, MTM.Loops);
4837ae0e2c9SDimitry Andric
4847ae0e2c9SDimitry Andric // Run an upwards post-order search for the trace start.
4857ae0e2c9SDimitry Andric Bounds.Downward = false;
4867ae0e2c9SDimitry Andric Bounds.Visited.clear();
487ff0cc061SDimitry Andric for (auto I : inverse_post_order_ext(MBB, Bounds)) {
4884ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << " pred for " << printMBBReference(*I) << ": ");
4897ae0e2c9SDimitry Andric TraceBlockInfo &TBI = BlockInfo[I->getNumber()];
4907ae0e2c9SDimitry Andric // All the predecessors have been visited, pick the preferred one.
491ff0cc061SDimitry Andric TBI.Pred = pickTracePred(I);
4924ba319b5SDimitry Andric LLVM_DEBUG({
4937ae0e2c9SDimitry Andric if (TBI.Pred)
4942cab237bSDimitry Andric dbgs() << printMBBReference(*TBI.Pred) << '\n';
4957ae0e2c9SDimitry Andric else
4967ae0e2c9SDimitry Andric dbgs() << "null\n";
4977ae0e2c9SDimitry Andric });
4987ae0e2c9SDimitry Andric // The trace leading to I is now known, compute the depth resources.
499ff0cc061SDimitry Andric computeDepthResources(I);
5007ae0e2c9SDimitry Andric }
5017ae0e2c9SDimitry Andric
5027ae0e2c9SDimitry Andric // Run a downwards post-order search for the trace end.
5037ae0e2c9SDimitry Andric Bounds.Downward = true;
5047ae0e2c9SDimitry Andric Bounds.Visited.clear();
505ff0cc061SDimitry Andric for (auto I : post_order_ext(MBB, Bounds)) {
5064ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << " succ for " << printMBBReference(*I) << ": ");
5077ae0e2c9SDimitry Andric TraceBlockInfo &TBI = BlockInfo[I->getNumber()];
5087ae0e2c9SDimitry Andric // All the successors have been visited, pick the preferred one.
509ff0cc061SDimitry Andric TBI.Succ = pickTraceSucc(I);
5104ba319b5SDimitry Andric LLVM_DEBUG({
5117ae0e2c9SDimitry Andric if (TBI.Succ)
5122cab237bSDimitry Andric dbgs() << printMBBReference(*TBI.Succ) << '\n';
5137ae0e2c9SDimitry Andric else
5147ae0e2c9SDimitry Andric dbgs() << "null\n";
5157ae0e2c9SDimitry Andric });
5167ae0e2c9SDimitry Andric // The trace leaving I is now known, compute the height resources.
517ff0cc061SDimitry Andric computeHeightResources(I);
5187ae0e2c9SDimitry Andric }
5197ae0e2c9SDimitry Andric }
5207ae0e2c9SDimitry Andric
5217ae0e2c9SDimitry Andric /// Invalidate traces through BadMBB.
5227ae0e2c9SDimitry Andric void
invalidate(const MachineBasicBlock * BadMBB)5237ae0e2c9SDimitry Andric MachineTraceMetrics::Ensemble::invalidate(const MachineBasicBlock *BadMBB) {
5247ae0e2c9SDimitry Andric SmallVector<const MachineBasicBlock*, 16> WorkList;
5257ae0e2c9SDimitry Andric TraceBlockInfo &BadTBI = BlockInfo[BadMBB->getNumber()];
5267ae0e2c9SDimitry Andric
5277ae0e2c9SDimitry Andric // Invalidate height resources of blocks above MBB.
5287ae0e2c9SDimitry Andric if (BadTBI.hasValidHeight()) {
5297ae0e2c9SDimitry Andric BadTBI.invalidateHeight();
5307ae0e2c9SDimitry Andric WorkList.push_back(BadMBB);
5317ae0e2c9SDimitry Andric do {
5327ae0e2c9SDimitry Andric const MachineBasicBlock *MBB = WorkList.pop_back_val();
5334ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "Invalidate " << printMBBReference(*MBB) << ' '
5342cab237bSDimitry Andric << getName() << " height.\n");
5357ae0e2c9SDimitry Andric // Find any MBB predecessors that have MBB as their preferred successor.
5367ae0e2c9SDimitry Andric // They are the only ones that need to be invalidated.
537875ed548SDimitry Andric for (const MachineBasicBlock *Pred : MBB->predecessors()) {
538875ed548SDimitry Andric TraceBlockInfo &TBI = BlockInfo[Pred->getNumber()];
5397ae0e2c9SDimitry Andric if (!TBI.hasValidHeight())
5407ae0e2c9SDimitry Andric continue;
5417ae0e2c9SDimitry Andric if (TBI.Succ == MBB) {
5427ae0e2c9SDimitry Andric TBI.invalidateHeight();
543875ed548SDimitry Andric WorkList.push_back(Pred);
5447ae0e2c9SDimitry Andric continue;
5457ae0e2c9SDimitry Andric }
5467ae0e2c9SDimitry Andric // Verify that TBI.Succ is actually a *I successor.
547875ed548SDimitry Andric assert((!TBI.Succ || Pred->isSuccessor(TBI.Succ)) && "CFG changed");
5487ae0e2c9SDimitry Andric }
5497ae0e2c9SDimitry Andric } while (!WorkList.empty());
5507ae0e2c9SDimitry Andric }
5517ae0e2c9SDimitry Andric
5527ae0e2c9SDimitry Andric // Invalidate depth resources of blocks below MBB.
5537ae0e2c9SDimitry Andric if (BadTBI.hasValidDepth()) {
5547ae0e2c9SDimitry Andric BadTBI.invalidateDepth();
5557ae0e2c9SDimitry Andric WorkList.push_back(BadMBB);
5567ae0e2c9SDimitry Andric do {
5577ae0e2c9SDimitry Andric const MachineBasicBlock *MBB = WorkList.pop_back_val();
5584ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "Invalidate " << printMBBReference(*MBB) << ' '
5592cab237bSDimitry Andric << getName() << " depth.\n");
5607ae0e2c9SDimitry Andric // Find any MBB successors that have MBB as their preferred predecessor.
5617ae0e2c9SDimitry Andric // They are the only ones that need to be invalidated.
562875ed548SDimitry Andric for (const MachineBasicBlock *Succ : MBB->successors()) {
563875ed548SDimitry Andric TraceBlockInfo &TBI = BlockInfo[Succ->getNumber()];
5647ae0e2c9SDimitry Andric if (!TBI.hasValidDepth())
5657ae0e2c9SDimitry Andric continue;
5667ae0e2c9SDimitry Andric if (TBI.Pred == MBB) {
5677ae0e2c9SDimitry Andric TBI.invalidateDepth();
568875ed548SDimitry Andric WorkList.push_back(Succ);
5697ae0e2c9SDimitry Andric continue;
5707ae0e2c9SDimitry Andric }
5717ae0e2c9SDimitry Andric // Verify that TBI.Pred is actually a *I predecessor.
572875ed548SDimitry Andric assert((!TBI.Pred || Succ->isPredecessor(TBI.Pred)) && "CFG changed");
5737ae0e2c9SDimitry Andric }
5747ae0e2c9SDimitry Andric } while (!WorkList.empty());
5757ae0e2c9SDimitry Andric }
5767ae0e2c9SDimitry Andric
5777ae0e2c9SDimitry Andric // Clear any per-instruction data. We only have to do this for BadMBB itself
5787ae0e2c9SDimitry Andric // because the instructions in that block may change. Other blocks may be
5797ae0e2c9SDimitry Andric // invalidated, but their instructions will stay the same, so there is no
5807ae0e2c9SDimitry Andric // need to erase the Cycle entries. They will be overwritten when we
5817ae0e2c9SDimitry Andric // recompute.
58291bc56edSDimitry Andric for (const auto &I : *BadMBB)
58391bc56edSDimitry Andric Cycles.erase(&I);
5847ae0e2c9SDimitry Andric }
5857ae0e2c9SDimitry Andric
verify() const5867ae0e2c9SDimitry Andric void MachineTraceMetrics::Ensemble::verify() const {
5877ae0e2c9SDimitry Andric #ifndef NDEBUG
5887ae0e2c9SDimitry Andric assert(BlockInfo.size() == MTM.MF->getNumBlockIDs() &&
5897ae0e2c9SDimitry Andric "Outdated BlockInfo size");
5907ae0e2c9SDimitry Andric for (unsigned Num = 0, e = BlockInfo.size(); Num != e; ++Num) {
5917ae0e2c9SDimitry Andric const TraceBlockInfo &TBI = BlockInfo[Num];
5927ae0e2c9SDimitry Andric if (TBI.hasValidDepth() && TBI.Pred) {
5937ae0e2c9SDimitry Andric const MachineBasicBlock *MBB = MTM.MF->getBlockNumbered(Num);
5947ae0e2c9SDimitry Andric assert(MBB->isPredecessor(TBI.Pred) && "CFG doesn't match trace");
5957ae0e2c9SDimitry Andric assert(BlockInfo[TBI.Pred->getNumber()].hasValidDepth() &&
5967ae0e2c9SDimitry Andric "Trace is broken, depth should have been invalidated.");
5977ae0e2c9SDimitry Andric const MachineLoop *Loop = getLoopFor(MBB);
5987ae0e2c9SDimitry Andric assert(!(Loop && MBB == Loop->getHeader()) && "Trace contains backedge");
5997ae0e2c9SDimitry Andric }
6007ae0e2c9SDimitry Andric if (TBI.hasValidHeight() && TBI.Succ) {
6017ae0e2c9SDimitry Andric const MachineBasicBlock *MBB = MTM.MF->getBlockNumbered(Num);
6027ae0e2c9SDimitry Andric assert(MBB->isSuccessor(TBI.Succ) && "CFG doesn't match trace");
6037ae0e2c9SDimitry Andric assert(BlockInfo[TBI.Succ->getNumber()].hasValidHeight() &&
6047ae0e2c9SDimitry Andric "Trace is broken, height should have been invalidated.");
6057ae0e2c9SDimitry Andric const MachineLoop *Loop = getLoopFor(MBB);
6067ae0e2c9SDimitry Andric const MachineLoop *SuccLoop = getLoopFor(TBI.Succ);
6077ae0e2c9SDimitry Andric assert(!(Loop && Loop == SuccLoop && TBI.Succ == Loop->getHeader()) &&
6087ae0e2c9SDimitry Andric "Trace contains backedge");
6097ae0e2c9SDimitry Andric }
6107ae0e2c9SDimitry Andric }
6117ae0e2c9SDimitry Andric #endif
6127ae0e2c9SDimitry Andric }
6137ae0e2c9SDimitry Andric
6147ae0e2c9SDimitry Andric //===----------------------------------------------------------------------===//
6157ae0e2c9SDimitry Andric // Data Dependencies
6167ae0e2c9SDimitry Andric //===----------------------------------------------------------------------===//
6177ae0e2c9SDimitry Andric //
6187ae0e2c9SDimitry Andric // Compute the depth and height of each instruction based on data dependencies
6197ae0e2c9SDimitry Andric // and instruction latencies. These cycle numbers assume that the CPU can issue
6207ae0e2c9SDimitry Andric // an infinite number of instructions per cycle as long as their dependencies
6217ae0e2c9SDimitry Andric // are ready.
6227ae0e2c9SDimitry Andric
6237ae0e2c9SDimitry Andric // A data dependency is represented as a defining MI and operand numbers on the
6247ae0e2c9SDimitry Andric // defining and using MI.
6257ae0e2c9SDimitry Andric namespace {
6267a7e6055SDimitry Andric
6277ae0e2c9SDimitry Andric struct DataDep {
6287ae0e2c9SDimitry Andric const MachineInstr *DefMI;
6297ae0e2c9SDimitry Andric unsigned DefOp;
6307ae0e2c9SDimitry Andric unsigned UseOp;
6317ae0e2c9SDimitry Andric
DataDep__anone79e02740311::DataDep6327ae0e2c9SDimitry Andric DataDep(const MachineInstr *DefMI, unsigned DefOp, unsigned UseOp)
6337ae0e2c9SDimitry Andric : DefMI(DefMI), DefOp(DefOp), UseOp(UseOp) {}
6347ae0e2c9SDimitry Andric
6357ae0e2c9SDimitry Andric /// Create a DataDep from an SSA form virtual register.
DataDep__anone79e02740311::DataDep6367ae0e2c9SDimitry Andric DataDep(const MachineRegisterInfo *MRI, unsigned VirtReg, unsigned UseOp)
6377ae0e2c9SDimitry Andric : UseOp(UseOp) {
6387ae0e2c9SDimitry Andric assert(TargetRegisterInfo::isVirtualRegister(VirtReg));
6397ae0e2c9SDimitry Andric MachineRegisterInfo::def_iterator DefI = MRI->def_begin(VirtReg);
6407ae0e2c9SDimitry Andric assert(!DefI.atEnd() && "Register has no defs");
64191bc56edSDimitry Andric DefMI = DefI->getParent();
6427ae0e2c9SDimitry Andric DefOp = DefI.getOperandNo();
6437ae0e2c9SDimitry Andric assert((++DefI).atEnd() && "Register has multiple defs");
6447ae0e2c9SDimitry Andric }
6457ae0e2c9SDimitry Andric };
6467a7e6055SDimitry Andric
6477a7e6055SDimitry Andric } // end anonymous namespace
6487ae0e2c9SDimitry Andric
6497ae0e2c9SDimitry Andric // Get the input data dependencies that must be ready before UseMI can issue.
6507ae0e2c9SDimitry Andric // Return true if UseMI has any physreg operands.
getDataDeps(const MachineInstr & UseMI,SmallVectorImpl<DataDep> & Deps,const MachineRegisterInfo * MRI)6513ca95b02SDimitry Andric static bool getDataDeps(const MachineInstr &UseMI,
6527ae0e2c9SDimitry Andric SmallVectorImpl<DataDep> &Deps,
6537ae0e2c9SDimitry Andric const MachineRegisterInfo *MRI) {
654b6c25e0eSDimitry Andric // Debug values should not be included in any calculations.
6554ba319b5SDimitry Andric if (UseMI.isDebugInstr())
656b6c25e0eSDimitry Andric return false;
657b6c25e0eSDimitry Andric
6587ae0e2c9SDimitry Andric bool HasPhysRegs = false;
6593ca95b02SDimitry Andric for (MachineInstr::const_mop_iterator I = UseMI.operands_begin(),
6603ca95b02SDimitry Andric E = UseMI.operands_end(); I != E; ++I) {
66197bc6c73SDimitry Andric const MachineOperand &MO = *I;
66297bc6c73SDimitry Andric if (!MO.isReg())
6637ae0e2c9SDimitry Andric continue;
66497bc6c73SDimitry Andric unsigned Reg = MO.getReg();
6657ae0e2c9SDimitry Andric if (!Reg)
6667ae0e2c9SDimitry Andric continue;
6677ae0e2c9SDimitry Andric if (TargetRegisterInfo::isPhysicalRegister(Reg)) {
6687ae0e2c9SDimitry Andric HasPhysRegs = true;
6697ae0e2c9SDimitry Andric continue;
6707ae0e2c9SDimitry Andric }
6717ae0e2c9SDimitry Andric // Collect virtual register reads.
67297bc6c73SDimitry Andric if (MO.readsReg())
6733ca95b02SDimitry Andric Deps.push_back(DataDep(MRI, Reg, UseMI.getOperandNo(I)));
6747ae0e2c9SDimitry Andric }
6757ae0e2c9SDimitry Andric return HasPhysRegs;
6767ae0e2c9SDimitry Andric }
6777ae0e2c9SDimitry Andric
6787ae0e2c9SDimitry Andric // Get the input data dependencies of a PHI instruction, using Pred as the
6797ae0e2c9SDimitry Andric // preferred predecessor.
6807ae0e2c9SDimitry Andric // This will add at most one dependency to Deps.
getPHIDeps(const MachineInstr & UseMI,SmallVectorImpl<DataDep> & Deps,const MachineBasicBlock * Pred,const MachineRegisterInfo * MRI)6813ca95b02SDimitry Andric static void getPHIDeps(const MachineInstr &UseMI,
6827ae0e2c9SDimitry Andric SmallVectorImpl<DataDep> &Deps,
6837ae0e2c9SDimitry Andric const MachineBasicBlock *Pred,
6847ae0e2c9SDimitry Andric const MachineRegisterInfo *MRI) {
6857ae0e2c9SDimitry Andric // No predecessor at the beginning of a trace. Ignore dependencies.
6867ae0e2c9SDimitry Andric if (!Pred)
6877ae0e2c9SDimitry Andric return;
6883ca95b02SDimitry Andric assert(UseMI.isPHI() && UseMI.getNumOperands() % 2 && "Bad PHI");
6893ca95b02SDimitry Andric for (unsigned i = 1; i != UseMI.getNumOperands(); i += 2) {
6903ca95b02SDimitry Andric if (UseMI.getOperand(i + 1).getMBB() == Pred) {
6913ca95b02SDimitry Andric unsigned Reg = UseMI.getOperand(i).getReg();
6927ae0e2c9SDimitry Andric Deps.push_back(DataDep(MRI, Reg, i));
6937ae0e2c9SDimitry Andric return;
6947ae0e2c9SDimitry Andric }
6957ae0e2c9SDimitry Andric }
6967ae0e2c9SDimitry Andric }
6977ae0e2c9SDimitry Andric
6987ae0e2c9SDimitry Andric // Identify physreg dependencies for UseMI, and update the live regunit
6997ae0e2c9SDimitry Andric // tracking set when scanning instructions downwards.
updatePhysDepsDownwards(const MachineInstr * UseMI,SmallVectorImpl<DataDep> & Deps,SparseSet<LiveRegUnit> & RegUnits,const TargetRegisterInfo * TRI)7007ae0e2c9SDimitry Andric static void updatePhysDepsDownwards(const MachineInstr *UseMI,
7017ae0e2c9SDimitry Andric SmallVectorImpl<DataDep> &Deps,
7027ae0e2c9SDimitry Andric SparseSet<LiveRegUnit> &RegUnits,
7037ae0e2c9SDimitry Andric const TargetRegisterInfo *TRI) {
7047ae0e2c9SDimitry Andric SmallVector<unsigned, 8> Kills;
7057ae0e2c9SDimitry Andric SmallVector<unsigned, 8> LiveDefOps;
7067ae0e2c9SDimitry Andric
70797bc6c73SDimitry Andric for (MachineInstr::const_mop_iterator MI = UseMI->operands_begin(),
70897bc6c73SDimitry Andric ME = UseMI->operands_end(); MI != ME; ++MI) {
70997bc6c73SDimitry Andric const MachineOperand &MO = *MI;
71097bc6c73SDimitry Andric if (!MO.isReg())
7117ae0e2c9SDimitry Andric continue;
71297bc6c73SDimitry Andric unsigned Reg = MO.getReg();
7137ae0e2c9SDimitry Andric if (!TargetRegisterInfo::isPhysicalRegister(Reg))
7147ae0e2c9SDimitry Andric continue;
7157ae0e2c9SDimitry Andric // Track live defs and kills for updating RegUnits.
71697bc6c73SDimitry Andric if (MO.isDef()) {
71797bc6c73SDimitry Andric if (MO.isDead())
7187ae0e2c9SDimitry Andric Kills.push_back(Reg);
7197ae0e2c9SDimitry Andric else
72097bc6c73SDimitry Andric LiveDefOps.push_back(UseMI->getOperandNo(MI));
72197bc6c73SDimitry Andric } else if (MO.isKill())
7227ae0e2c9SDimitry Andric Kills.push_back(Reg);
7237ae0e2c9SDimitry Andric // Identify dependencies.
72497bc6c73SDimitry Andric if (!MO.readsReg())
7257ae0e2c9SDimitry Andric continue;
7267ae0e2c9SDimitry Andric for (MCRegUnitIterator Units(Reg, TRI); Units.isValid(); ++Units) {
7277ae0e2c9SDimitry Andric SparseSet<LiveRegUnit>::iterator I = RegUnits.find(*Units);
7287ae0e2c9SDimitry Andric if (I == RegUnits.end())
7297ae0e2c9SDimitry Andric continue;
73097bc6c73SDimitry Andric Deps.push_back(DataDep(I->MI, I->Op, UseMI->getOperandNo(MI)));
7317ae0e2c9SDimitry Andric break;
7327ae0e2c9SDimitry Andric }
7337ae0e2c9SDimitry Andric }
7347ae0e2c9SDimitry Andric
7357ae0e2c9SDimitry Andric // Update RegUnits to reflect live registers after UseMI.
7367ae0e2c9SDimitry Andric // First kills.
7377d523365SDimitry Andric for (unsigned Kill : Kills)
7387d523365SDimitry Andric for (MCRegUnitIterator Units(Kill, TRI); Units.isValid(); ++Units)
7397ae0e2c9SDimitry Andric RegUnits.erase(*Units);
7407ae0e2c9SDimitry Andric
7417ae0e2c9SDimitry Andric // Second, live defs.
7427d523365SDimitry Andric for (unsigned DefOp : LiveDefOps) {
7437ae0e2c9SDimitry Andric for (MCRegUnitIterator Units(UseMI->getOperand(DefOp).getReg(), TRI);
7447ae0e2c9SDimitry Andric Units.isValid(); ++Units) {
7457ae0e2c9SDimitry Andric LiveRegUnit &LRU = RegUnits[*Units];
7467ae0e2c9SDimitry Andric LRU.MI = UseMI;
7477ae0e2c9SDimitry Andric LRU.Op = DefOp;
7487ae0e2c9SDimitry Andric }
7497ae0e2c9SDimitry Andric }
7507ae0e2c9SDimitry Andric }
7517ae0e2c9SDimitry Andric
7527ae0e2c9SDimitry Andric /// The length of the critical path through a trace is the maximum of two path
7537ae0e2c9SDimitry Andric /// lengths:
7547ae0e2c9SDimitry Andric ///
7557ae0e2c9SDimitry Andric /// 1. The maximum height+depth over all instructions in the trace center block.
7567ae0e2c9SDimitry Andric ///
7577ae0e2c9SDimitry Andric /// 2. The longest cross-block dependency chain. For small blocks, it is
7587ae0e2c9SDimitry Andric /// possible that the critical path through the trace doesn't include any
7597ae0e2c9SDimitry Andric /// instructions in the block.
7607ae0e2c9SDimitry Andric ///
7617ae0e2c9SDimitry Andric /// This function computes the second number from the live-in list of the
7627ae0e2c9SDimitry Andric /// center block.
7637ae0e2c9SDimitry Andric unsigned MachineTraceMetrics::Ensemble::
computeCrossBlockCriticalPath(const TraceBlockInfo & TBI)7647ae0e2c9SDimitry Andric computeCrossBlockCriticalPath(const TraceBlockInfo &TBI) {
7657ae0e2c9SDimitry Andric assert(TBI.HasValidInstrDepths && "Missing depth info");
7667ae0e2c9SDimitry Andric assert(TBI.HasValidInstrHeights && "Missing height info");
7677ae0e2c9SDimitry Andric unsigned MaxLen = 0;
7687d523365SDimitry Andric for (const LiveInReg &LIR : TBI.LiveIns) {
7697ae0e2c9SDimitry Andric if (!TargetRegisterInfo::isVirtualRegister(LIR.Reg))
7707ae0e2c9SDimitry Andric continue;
7717ae0e2c9SDimitry Andric const MachineInstr *DefMI = MTM.MRI->getVRegDef(LIR.Reg);
7727ae0e2c9SDimitry Andric // Ignore dependencies outside the current trace.
7737ae0e2c9SDimitry Andric const TraceBlockInfo &DefTBI = BlockInfo[DefMI->getParent()->getNumber()];
774139f7f9bSDimitry Andric if (!DefTBI.isUsefulDominator(TBI))
7757ae0e2c9SDimitry Andric continue;
7767ae0e2c9SDimitry Andric unsigned Len = LIR.Height + Cycles[DefMI].Depth;
7777ae0e2c9SDimitry Andric MaxLen = std::max(MaxLen, Len);
7787ae0e2c9SDimitry Andric }
7797ae0e2c9SDimitry Andric return MaxLen;
7807ae0e2c9SDimitry Andric }
7817ae0e2c9SDimitry Andric
7827ae0e2c9SDimitry Andric void MachineTraceMetrics::Ensemble::
updateDepth(MachineTraceMetrics::TraceBlockInfo & TBI,const MachineInstr & UseMI,SparseSet<LiveRegUnit> & RegUnits)7832cab237bSDimitry Andric updateDepth(MachineTraceMetrics::TraceBlockInfo &TBI, const MachineInstr &UseMI,
7842cab237bSDimitry Andric SparseSet<LiveRegUnit> &RegUnits) {
7857ae0e2c9SDimitry Andric SmallVector<DataDep, 8> Deps;
7867ae0e2c9SDimitry Andric // Collect all data dependencies.
78791bc56edSDimitry Andric if (UseMI.isPHI())
7883ca95b02SDimitry Andric getPHIDeps(UseMI, Deps, TBI.Pred, MTM.MRI);
7893ca95b02SDimitry Andric else if (getDataDeps(UseMI, Deps, MTM.MRI))
79091bc56edSDimitry Andric updatePhysDepsDownwards(&UseMI, Deps, RegUnits, MTM.TRI);
7917ae0e2c9SDimitry Andric
7927ae0e2c9SDimitry Andric // Filter and process dependencies, computing the earliest issue cycle.
7937ae0e2c9SDimitry Andric unsigned Cycle = 0;
7943dac3a9bSDimitry Andric for (const DataDep &Dep : Deps) {
7957ae0e2c9SDimitry Andric const TraceBlockInfo&DepTBI =
7967ae0e2c9SDimitry Andric BlockInfo[Dep.DefMI->getParent()->getNumber()];
7977ae0e2c9SDimitry Andric // Ignore dependencies from outside the current trace.
798139f7f9bSDimitry Andric if (!DepTBI.isUsefulDominator(TBI))
7997ae0e2c9SDimitry Andric continue;
8007ae0e2c9SDimitry Andric assert(DepTBI.HasValidInstrDepths && "Inconsistent dependency");
8017ae0e2c9SDimitry Andric unsigned DepCycle = Cycles.lookup(Dep.DefMI).Depth;
8027ae0e2c9SDimitry Andric // Add latency if DefMI is a real instruction. Transients get latency 0.
8037ae0e2c9SDimitry Andric if (!Dep.DefMI->isTransient())
8043861d79fSDimitry Andric DepCycle += MTM.SchedModel
80591bc56edSDimitry Andric .computeOperandLatency(Dep.DefMI, Dep.DefOp, &UseMI, Dep.UseOp);
8067ae0e2c9SDimitry Andric Cycle = std::max(Cycle, DepCycle);
8077ae0e2c9SDimitry Andric }
8087ae0e2c9SDimitry Andric // Remember the instruction depth.
80991bc56edSDimitry Andric InstrCycles &MICycles = Cycles[&UseMI];
8107ae0e2c9SDimitry Andric MICycles.Depth = Cycle;
8117ae0e2c9SDimitry Andric
8122cab237bSDimitry Andric if (TBI.HasValidInstrHeights) {
8137ae0e2c9SDimitry Andric // Update critical path length.
8147ae0e2c9SDimitry Andric TBI.CriticalPath = std::max(TBI.CriticalPath, Cycle + MICycles.Height);
8154ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << TBI.CriticalPath << '\t' << Cycle << '\t' << UseMI);
8162cab237bSDimitry Andric } else {
8174ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << Cycle << '\t' << UseMI);
8182cab237bSDimitry Andric }
8192cab237bSDimitry Andric }
8202cab237bSDimitry Andric
8212cab237bSDimitry Andric void MachineTraceMetrics::Ensemble::
updateDepth(const MachineBasicBlock * MBB,const MachineInstr & UseMI,SparseSet<LiveRegUnit> & RegUnits)8222cab237bSDimitry Andric updateDepth(const MachineBasicBlock *MBB, const MachineInstr &UseMI,
8232cab237bSDimitry Andric SparseSet<LiveRegUnit> &RegUnits) {
8242cab237bSDimitry Andric updateDepth(BlockInfo[MBB->getNumber()], UseMI, RegUnits);
8252cab237bSDimitry Andric }
8262cab237bSDimitry Andric
8272cab237bSDimitry Andric void MachineTraceMetrics::Ensemble::
updateDepths(MachineBasicBlock::iterator Start,MachineBasicBlock::iterator End,SparseSet<LiveRegUnit> & RegUnits)8282cab237bSDimitry Andric updateDepths(MachineBasicBlock::iterator Start,
8292cab237bSDimitry Andric MachineBasicBlock::iterator End,
8302cab237bSDimitry Andric SparseSet<LiveRegUnit> &RegUnits) {
8312cab237bSDimitry Andric for (; Start != End; Start++)
8322cab237bSDimitry Andric updateDepth(Start->getParent(), *Start, RegUnits);
8332cab237bSDimitry Andric }
8342cab237bSDimitry Andric
8352cab237bSDimitry Andric /// Compute instruction depths for all instructions above or in MBB in its
8362cab237bSDimitry Andric /// trace. This assumes that the trace through MBB has already been computed.
8372cab237bSDimitry Andric void MachineTraceMetrics::Ensemble::
computeInstrDepths(const MachineBasicBlock * MBB)8382cab237bSDimitry Andric computeInstrDepths(const MachineBasicBlock *MBB) {
8392cab237bSDimitry Andric // The top of the trace may already be computed, and HasValidInstrDepths
8402cab237bSDimitry Andric // implies Head->HasValidInstrDepths, so we only need to start from the first
8412cab237bSDimitry Andric // block in the trace that needs to be recomputed.
8422cab237bSDimitry Andric SmallVector<const MachineBasicBlock*, 8> Stack;
8432cab237bSDimitry Andric do {
8442cab237bSDimitry Andric TraceBlockInfo &TBI = BlockInfo[MBB->getNumber()];
8452cab237bSDimitry Andric assert(TBI.hasValidDepth() && "Incomplete trace");
8462cab237bSDimitry Andric if (TBI.HasValidInstrDepths)
8472cab237bSDimitry Andric break;
8482cab237bSDimitry Andric Stack.push_back(MBB);
8492cab237bSDimitry Andric MBB = TBI.Pred;
8502cab237bSDimitry Andric } while (MBB);
8512cab237bSDimitry Andric
8522cab237bSDimitry Andric // FIXME: If MBB is non-null at this point, it is the last pre-computed block
8532cab237bSDimitry Andric // in the trace. We should track any live-out physregs that were defined in
8542cab237bSDimitry Andric // the trace. This is quite rare in SSA form, typically created by CSE
8552cab237bSDimitry Andric // hoisting a compare.
8562cab237bSDimitry Andric SparseSet<LiveRegUnit> RegUnits;
8572cab237bSDimitry Andric RegUnits.setUniverse(MTM.TRI->getNumRegUnits());
8582cab237bSDimitry Andric
8592cab237bSDimitry Andric // Go through trace blocks in top-down order, stopping after the center block.
8602cab237bSDimitry Andric while (!Stack.empty()) {
8612cab237bSDimitry Andric MBB = Stack.pop_back_val();
8624ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "\nDepths for " << printMBBReference(*MBB) << ":\n");
8632cab237bSDimitry Andric TraceBlockInfo &TBI = BlockInfo[MBB->getNumber()];
8642cab237bSDimitry Andric TBI.HasValidInstrDepths = true;
8652cab237bSDimitry Andric TBI.CriticalPath = 0;
8662cab237bSDimitry Andric
8672cab237bSDimitry Andric // Print out resource depths here as well.
8684ba319b5SDimitry Andric LLVM_DEBUG({
8692cab237bSDimitry Andric dbgs() << format("%7u Instructions\n", TBI.InstrDepth);
8702cab237bSDimitry Andric ArrayRef<unsigned> PRDepths = getProcResourceDepths(MBB->getNumber());
8712cab237bSDimitry Andric for (unsigned K = 0; K != PRDepths.size(); ++K)
8722cab237bSDimitry Andric if (PRDepths[K]) {
8732cab237bSDimitry Andric unsigned Factor = MTM.SchedModel.getResourceFactor(K);
8742cab237bSDimitry Andric dbgs() << format("%6uc @ ", MTM.getCycles(PRDepths[K]))
8752cab237bSDimitry Andric << MTM.SchedModel.getProcResource(K)->Name << " ("
8762cab237bSDimitry Andric << PRDepths[K]/Factor << " ops x" << Factor << ")\n";
8772cab237bSDimitry Andric }
8782cab237bSDimitry Andric });
8792cab237bSDimitry Andric
8802cab237bSDimitry Andric // Also compute the critical path length through MBB when possible.
8812cab237bSDimitry Andric if (TBI.HasValidInstrHeights)
8822cab237bSDimitry Andric TBI.CriticalPath = computeCrossBlockCriticalPath(TBI);
8832cab237bSDimitry Andric
8842cab237bSDimitry Andric for (const auto &UseMI : *MBB) {
8852cab237bSDimitry Andric updateDepth(TBI, UseMI, RegUnits);
8867ae0e2c9SDimitry Andric }
8877ae0e2c9SDimitry Andric }
8887ae0e2c9SDimitry Andric }
8897ae0e2c9SDimitry Andric
8907ae0e2c9SDimitry Andric // Identify physreg dependencies for MI when scanning instructions upwards.
8917ae0e2c9SDimitry Andric // Return the issue height of MI after considering any live regunits.
8927ae0e2c9SDimitry Andric // Height is the issue height computed from virtual register dependencies alone.
updatePhysDepsUpwards(const MachineInstr & MI,unsigned Height,SparseSet<LiveRegUnit> & RegUnits,const TargetSchedModel & SchedModel,const TargetInstrInfo * TII,const TargetRegisterInfo * TRI)8933ca95b02SDimitry Andric static unsigned updatePhysDepsUpwards(const MachineInstr &MI, unsigned Height,
8947ae0e2c9SDimitry Andric SparseSet<LiveRegUnit> &RegUnits,
8953861d79fSDimitry Andric const TargetSchedModel &SchedModel,
8967ae0e2c9SDimitry Andric const TargetInstrInfo *TII,
8977ae0e2c9SDimitry Andric const TargetRegisterInfo *TRI) {
8987ae0e2c9SDimitry Andric SmallVector<unsigned, 8> ReadOps;
89997bc6c73SDimitry Andric
9003ca95b02SDimitry Andric for (MachineInstr::const_mop_iterator MOI = MI.operands_begin(),
9013ca95b02SDimitry Andric MOE = MI.operands_end();
9023ca95b02SDimitry Andric MOI != MOE; ++MOI) {
90397bc6c73SDimitry Andric const MachineOperand &MO = *MOI;
90497bc6c73SDimitry Andric if (!MO.isReg())
9057ae0e2c9SDimitry Andric continue;
90697bc6c73SDimitry Andric unsigned Reg = MO.getReg();
9077ae0e2c9SDimitry Andric if (!TargetRegisterInfo::isPhysicalRegister(Reg))
9087ae0e2c9SDimitry Andric continue;
90997bc6c73SDimitry Andric if (MO.readsReg())
9103ca95b02SDimitry Andric ReadOps.push_back(MI.getOperandNo(MOI));
91197bc6c73SDimitry Andric if (!MO.isDef())
9127ae0e2c9SDimitry Andric continue;
9137ae0e2c9SDimitry Andric // This is a def of Reg. Remove corresponding entries from RegUnits, and
9147ae0e2c9SDimitry Andric // update MI Height to consider the physreg dependencies.
9157ae0e2c9SDimitry Andric for (MCRegUnitIterator Units(Reg, TRI); Units.isValid(); ++Units) {
9167ae0e2c9SDimitry Andric SparseSet<LiveRegUnit>::iterator I = RegUnits.find(*Units);
9177ae0e2c9SDimitry Andric if (I == RegUnits.end())
9187ae0e2c9SDimitry Andric continue;
9197ae0e2c9SDimitry Andric unsigned DepHeight = I->Cycle;
9203ca95b02SDimitry Andric if (!MI.isTransient()) {
9217ae0e2c9SDimitry Andric // We may not know the UseMI of this dependency, if it came from the
9223861d79fSDimitry Andric // live-in list. SchedModel can handle a NULL UseMI.
9233ca95b02SDimitry Andric DepHeight += SchedModel.computeOperandLatency(&MI, MI.getOperandNo(MOI),
9243ca95b02SDimitry Andric I->MI, I->Op);
9257ae0e2c9SDimitry Andric }
9267ae0e2c9SDimitry Andric Height = std::max(Height, DepHeight);
9277ae0e2c9SDimitry Andric // This regunit is dead above MI.
9287ae0e2c9SDimitry Andric RegUnits.erase(I);
9297ae0e2c9SDimitry Andric }
9307ae0e2c9SDimitry Andric }
9317ae0e2c9SDimitry Andric
9327ae0e2c9SDimitry Andric // Now we know the height of MI. Update any regunits read.
9337ae0e2c9SDimitry Andric for (unsigned i = 0, e = ReadOps.size(); i != e; ++i) {
9343ca95b02SDimitry Andric unsigned Reg = MI.getOperand(ReadOps[i]).getReg();
9357ae0e2c9SDimitry Andric for (MCRegUnitIterator Units(Reg, TRI); Units.isValid(); ++Units) {
9367ae0e2c9SDimitry Andric LiveRegUnit &LRU = RegUnits[*Units];
9377ae0e2c9SDimitry Andric // Set the height to the highest reader of the unit.
9383ca95b02SDimitry Andric if (LRU.Cycle <= Height && LRU.MI != &MI) {
9397ae0e2c9SDimitry Andric LRU.Cycle = Height;
9403ca95b02SDimitry Andric LRU.MI = &MI;
9417ae0e2c9SDimitry Andric LRU.Op = ReadOps[i];
9427ae0e2c9SDimitry Andric }
9437ae0e2c9SDimitry Andric }
9447ae0e2c9SDimitry Andric }
9457ae0e2c9SDimitry Andric
9467ae0e2c9SDimitry Andric return Height;
9477ae0e2c9SDimitry Andric }
9487ae0e2c9SDimitry Andric
9492cab237bSDimitry Andric using MIHeightMap = DenseMap<const MachineInstr *, unsigned>;
9507ae0e2c9SDimitry Andric
9517ae0e2c9SDimitry Andric // Push the height of DefMI upwards if required to match UseMI.
9527ae0e2c9SDimitry Andric // Return true if this is the first time DefMI was seen.
pushDepHeight(const DataDep & Dep,const MachineInstr & UseMI,unsigned UseHeight,MIHeightMap & Heights,const TargetSchedModel & SchedModel,const TargetInstrInfo * TII)9533ca95b02SDimitry Andric static bool pushDepHeight(const DataDep &Dep, const MachineInstr &UseMI,
9543ca95b02SDimitry Andric unsigned UseHeight, MIHeightMap &Heights,
9553861d79fSDimitry Andric const TargetSchedModel &SchedModel,
9567ae0e2c9SDimitry Andric const TargetInstrInfo *TII) {
9577ae0e2c9SDimitry Andric // Adjust height by Dep.DefMI latency.
9587ae0e2c9SDimitry Andric if (!Dep.DefMI->isTransient())
9593ca95b02SDimitry Andric UseHeight += SchedModel.computeOperandLatency(Dep.DefMI, Dep.DefOp, &UseMI,
9603ca95b02SDimitry Andric Dep.UseOp);
9617ae0e2c9SDimitry Andric
9627ae0e2c9SDimitry Andric // Update Heights[DefMI] to be the maximum height seen.
9637ae0e2c9SDimitry Andric MIHeightMap::iterator I;
9647ae0e2c9SDimitry Andric bool New;
96591bc56edSDimitry Andric std::tie(I, New) = Heights.insert(std::make_pair(Dep.DefMI, UseHeight));
9667ae0e2c9SDimitry Andric if (New)
9677ae0e2c9SDimitry Andric return true;
9687ae0e2c9SDimitry Andric
9697ae0e2c9SDimitry Andric // DefMI has been pushed before. Give it the max height.
9707ae0e2c9SDimitry Andric if (I->second < UseHeight)
9717ae0e2c9SDimitry Andric I->second = UseHeight;
9727ae0e2c9SDimitry Andric return false;
9737ae0e2c9SDimitry Andric }
9747ae0e2c9SDimitry Andric
9753861d79fSDimitry Andric /// Assuming that the virtual register defined by DefMI:DefOp was used by
9763861d79fSDimitry Andric /// Trace.back(), add it to the live-in lists of all the blocks in Trace. Stop
9773861d79fSDimitry Andric /// when reaching the block that contains DefMI.
9787ae0e2c9SDimitry Andric void MachineTraceMetrics::Ensemble::
addLiveIns(const MachineInstr * DefMI,unsigned DefOp,ArrayRef<const MachineBasicBlock * > Trace)9793861d79fSDimitry Andric addLiveIns(const MachineInstr *DefMI, unsigned DefOp,
9807ae0e2c9SDimitry Andric ArrayRef<const MachineBasicBlock*> Trace) {
9817ae0e2c9SDimitry Andric assert(!Trace.empty() && "Trace should contain at least one block");
9823861d79fSDimitry Andric unsigned Reg = DefMI->getOperand(DefOp).getReg();
9837ae0e2c9SDimitry Andric assert(TargetRegisterInfo::isVirtualRegister(Reg));
9847ae0e2c9SDimitry Andric const MachineBasicBlock *DefMBB = DefMI->getParent();
9857ae0e2c9SDimitry Andric
9867ae0e2c9SDimitry Andric // Reg is live-in to all blocks in Trace that follow DefMBB.
9877ae0e2c9SDimitry Andric for (unsigned i = Trace.size(); i; --i) {
9887ae0e2c9SDimitry Andric const MachineBasicBlock *MBB = Trace[i-1];
9897ae0e2c9SDimitry Andric if (MBB == DefMBB)
9907ae0e2c9SDimitry Andric return;
9917ae0e2c9SDimitry Andric TraceBlockInfo &TBI = BlockInfo[MBB->getNumber()];
9927ae0e2c9SDimitry Andric // Just add the register. The height will be updated later.
9937ae0e2c9SDimitry Andric TBI.LiveIns.push_back(Reg);
9947ae0e2c9SDimitry Andric }
9957ae0e2c9SDimitry Andric }
9967ae0e2c9SDimitry Andric
9977ae0e2c9SDimitry Andric /// Compute instruction heights in the trace through MBB. This updates MBB and
9987ae0e2c9SDimitry Andric /// the blocks below it in the trace. It is assumed that the trace has already
9997ae0e2c9SDimitry Andric /// been computed.
10007ae0e2c9SDimitry Andric void MachineTraceMetrics::Ensemble::
computeInstrHeights(const MachineBasicBlock * MBB)10017ae0e2c9SDimitry Andric computeInstrHeights(const MachineBasicBlock *MBB) {
10027ae0e2c9SDimitry Andric // The bottom of the trace may already be computed.
10037ae0e2c9SDimitry Andric // Find the blocks that need updating.
10047ae0e2c9SDimitry Andric SmallVector<const MachineBasicBlock*, 8> Stack;
10057ae0e2c9SDimitry Andric do {
10067ae0e2c9SDimitry Andric TraceBlockInfo &TBI = BlockInfo[MBB->getNumber()];
10077ae0e2c9SDimitry Andric assert(TBI.hasValidHeight() && "Incomplete trace");
10087ae0e2c9SDimitry Andric if (TBI.HasValidInstrHeights)
10097ae0e2c9SDimitry Andric break;
10107ae0e2c9SDimitry Andric Stack.push_back(MBB);
10117ae0e2c9SDimitry Andric TBI.LiveIns.clear();
10127ae0e2c9SDimitry Andric MBB = TBI.Succ;
10137ae0e2c9SDimitry Andric } while (MBB);
10147ae0e2c9SDimitry Andric
10157ae0e2c9SDimitry Andric // As we move upwards in the trace, keep track of instructions that are
10167ae0e2c9SDimitry Andric // required by deeper trace instructions. Map MI -> height required so far.
10177ae0e2c9SDimitry Andric MIHeightMap Heights;
10187ae0e2c9SDimitry Andric
10197ae0e2c9SDimitry Andric // For physregs, the def isn't known when we see the use.
10207ae0e2c9SDimitry Andric // Instead, keep track of the highest use of each regunit.
10217ae0e2c9SDimitry Andric SparseSet<LiveRegUnit> RegUnits;
10227ae0e2c9SDimitry Andric RegUnits.setUniverse(MTM.TRI->getNumRegUnits());
10237ae0e2c9SDimitry Andric
10247ae0e2c9SDimitry Andric // If the bottom of the trace was already precomputed, initialize heights
10257ae0e2c9SDimitry Andric // from its live-in list.
10267ae0e2c9SDimitry Andric // MBB is the highest precomputed block in the trace.
10277ae0e2c9SDimitry Andric if (MBB) {
10287ae0e2c9SDimitry Andric TraceBlockInfo &TBI = BlockInfo[MBB->getNumber()];
1029875ed548SDimitry Andric for (LiveInReg &LI : TBI.LiveIns) {
10307ae0e2c9SDimitry Andric if (TargetRegisterInfo::isVirtualRegister(LI.Reg)) {
10317ae0e2c9SDimitry Andric // For virtual registers, the def latency is included.
10327ae0e2c9SDimitry Andric unsigned &Height = Heights[MTM.MRI->getVRegDef(LI.Reg)];
10337ae0e2c9SDimitry Andric if (Height < LI.Height)
10347ae0e2c9SDimitry Andric Height = LI.Height;
10357ae0e2c9SDimitry Andric } else {
10367ae0e2c9SDimitry Andric // For register units, the def latency is not included because we don't
10377ae0e2c9SDimitry Andric // know the def yet.
10387ae0e2c9SDimitry Andric RegUnits[LI.Reg].Cycle = LI.Height;
10397ae0e2c9SDimitry Andric }
10407ae0e2c9SDimitry Andric }
10417ae0e2c9SDimitry Andric }
10427ae0e2c9SDimitry Andric
10437ae0e2c9SDimitry Andric // Go through the trace blocks in bottom-up order.
10447ae0e2c9SDimitry Andric SmallVector<DataDep, 8> Deps;
10457ae0e2c9SDimitry Andric for (;!Stack.empty(); Stack.pop_back()) {
10467ae0e2c9SDimitry Andric MBB = Stack.back();
10474ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "Heights for " << printMBBReference(*MBB) << ":\n");
10487ae0e2c9SDimitry Andric TraceBlockInfo &TBI = BlockInfo[MBB->getNumber()];
10497ae0e2c9SDimitry Andric TBI.HasValidInstrHeights = true;
10507ae0e2c9SDimitry Andric TBI.CriticalPath = 0;
10517ae0e2c9SDimitry Andric
10524ba319b5SDimitry Andric LLVM_DEBUG({
1053139f7f9bSDimitry Andric dbgs() << format("%7u Instructions\n", TBI.InstrHeight);
1054139f7f9bSDimitry Andric ArrayRef<unsigned> PRHeights = getProcResourceHeights(MBB->getNumber());
1055139f7f9bSDimitry Andric for (unsigned K = 0; K != PRHeights.size(); ++K)
1056139f7f9bSDimitry Andric if (PRHeights[K]) {
1057139f7f9bSDimitry Andric unsigned Factor = MTM.SchedModel.getResourceFactor(K);
1058139f7f9bSDimitry Andric dbgs() << format("%6uc @ ", MTM.getCycles(PRHeights[K]))
1059139f7f9bSDimitry Andric << MTM.SchedModel.getProcResource(K)->Name << " ("
1060139f7f9bSDimitry Andric << PRHeights[K]/Factor << " ops x" << Factor << ")\n";
1061139f7f9bSDimitry Andric }
1062139f7f9bSDimitry Andric });
1063139f7f9bSDimitry Andric
10647ae0e2c9SDimitry Andric // Get dependencies from PHIs in the trace successor.
10657ae0e2c9SDimitry Andric const MachineBasicBlock *Succ = TBI.Succ;
10667ae0e2c9SDimitry Andric // If MBB is the last block in the trace, and it has a back-edge to the
10677ae0e2c9SDimitry Andric // loop header, get loop-carried dependencies from PHIs in the header. For
10687ae0e2c9SDimitry Andric // that purpose, pretend that all the loop header PHIs have height 0.
10697ae0e2c9SDimitry Andric if (!Succ)
10707ae0e2c9SDimitry Andric if (const MachineLoop *Loop = getLoopFor(MBB))
10717ae0e2c9SDimitry Andric if (MBB->isSuccessor(Loop->getHeader()))
10727ae0e2c9SDimitry Andric Succ = Loop->getHeader();
10737ae0e2c9SDimitry Andric
10747ae0e2c9SDimitry Andric if (Succ) {
107591bc56edSDimitry Andric for (const auto &PHI : *Succ) {
107691bc56edSDimitry Andric if (!PHI.isPHI())
107791bc56edSDimitry Andric break;
10787ae0e2c9SDimitry Andric Deps.clear();
10793ca95b02SDimitry Andric getPHIDeps(PHI, Deps, MBB, MTM.MRI);
10807ae0e2c9SDimitry Andric if (!Deps.empty()) {
10817ae0e2c9SDimitry Andric // Loop header PHI heights are all 0.
108291bc56edSDimitry Andric unsigned Height = TBI.Succ ? Cycles.lookup(&PHI).Height : 0;
10834ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "pred\t" << Height << '\t' << PHI);
10843ca95b02SDimitry Andric if (pushDepHeight(Deps.front(), PHI, Height, Heights, MTM.SchedModel,
10853ca95b02SDimitry Andric MTM.TII))
10863861d79fSDimitry Andric addLiveIns(Deps.front().DefMI, Deps.front().DefOp, Stack);
10877ae0e2c9SDimitry Andric }
10887ae0e2c9SDimitry Andric }
10897ae0e2c9SDimitry Andric }
10907ae0e2c9SDimitry Andric
10917ae0e2c9SDimitry Andric // Go through the block backwards.
10927ae0e2c9SDimitry Andric for (MachineBasicBlock::const_iterator BI = MBB->end(), BB = MBB->begin();
10937ae0e2c9SDimitry Andric BI != BB;) {
10943ca95b02SDimitry Andric const MachineInstr &MI = *--BI;
10957ae0e2c9SDimitry Andric
10967ae0e2c9SDimitry Andric // Find the MI height as determined by virtual register uses in the
10977ae0e2c9SDimitry Andric // trace below.
10987ae0e2c9SDimitry Andric unsigned Cycle = 0;
10993ca95b02SDimitry Andric MIHeightMap::iterator HeightI = Heights.find(&MI);
11007ae0e2c9SDimitry Andric if (HeightI != Heights.end()) {
11017ae0e2c9SDimitry Andric Cycle = HeightI->second;
11027ae0e2c9SDimitry Andric // We won't be seeing any more MI uses.
11037ae0e2c9SDimitry Andric Heights.erase(HeightI);
11047ae0e2c9SDimitry Andric }
11057ae0e2c9SDimitry Andric
11067ae0e2c9SDimitry Andric // Don't process PHI deps. They depend on the specific predecessor, and
11077ae0e2c9SDimitry Andric // we'll get them when visiting the predecessor.
11087ae0e2c9SDimitry Andric Deps.clear();
11093ca95b02SDimitry Andric bool HasPhysRegs = !MI.isPHI() && getDataDeps(MI, Deps, MTM.MRI);
11107ae0e2c9SDimitry Andric
11117ae0e2c9SDimitry Andric // There may also be regunit dependencies to include in the height.
11127ae0e2c9SDimitry Andric if (HasPhysRegs)
11133ca95b02SDimitry Andric Cycle = updatePhysDepsUpwards(MI, Cycle, RegUnits, MTM.SchedModel,
11143ca95b02SDimitry Andric MTM.TII, MTM.TRI);
11157ae0e2c9SDimitry Andric
11167ae0e2c9SDimitry Andric // Update the required height of any virtual registers read by MI.
11173dac3a9bSDimitry Andric for (const DataDep &Dep : Deps)
11183dac3a9bSDimitry Andric if (pushDepHeight(Dep, MI, Cycle, Heights, MTM.SchedModel, MTM.TII))
11193dac3a9bSDimitry Andric addLiveIns(Dep.DefMI, Dep.DefOp, Stack);
11207ae0e2c9SDimitry Andric
11213ca95b02SDimitry Andric InstrCycles &MICycles = Cycles[&MI];
11227ae0e2c9SDimitry Andric MICycles.Height = Cycle;
11237ae0e2c9SDimitry Andric if (!TBI.HasValidInstrDepths) {
11244ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << Cycle << '\t' << MI);
11257ae0e2c9SDimitry Andric continue;
11267ae0e2c9SDimitry Andric }
11277ae0e2c9SDimitry Andric // Update critical path length.
11287ae0e2c9SDimitry Andric TBI.CriticalPath = std::max(TBI.CriticalPath, Cycle + MICycles.Depth);
11294ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << TBI.CriticalPath << '\t' << Cycle << '\t' << MI);
11307ae0e2c9SDimitry Andric }
11317ae0e2c9SDimitry Andric
11327ae0e2c9SDimitry Andric // Update virtual live-in heights. They were added by addLiveIns() with a 0
11337ae0e2c9SDimitry Andric // height because the final height isn't known until now.
11344ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << printMBBReference(*MBB) << " Live-ins:");
11353dac3a9bSDimitry Andric for (LiveInReg &LIR : TBI.LiveIns) {
11367ae0e2c9SDimitry Andric const MachineInstr *DefMI = MTM.MRI->getVRegDef(LIR.Reg);
11377ae0e2c9SDimitry Andric LIR.Height = Heights.lookup(DefMI);
11384ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << ' ' << printReg(LIR.Reg) << '@' << LIR.Height);
11397ae0e2c9SDimitry Andric }
11407ae0e2c9SDimitry Andric
11417ae0e2c9SDimitry Andric // Transfer the live regunits to the live-in list.
11427ae0e2c9SDimitry Andric for (SparseSet<LiveRegUnit>::const_iterator
11437ae0e2c9SDimitry Andric RI = RegUnits.begin(), RE = RegUnits.end(); RI != RE; ++RI) {
11447ae0e2c9SDimitry Andric TBI.LiveIns.push_back(LiveInReg(RI->RegUnit, RI->Cycle));
11454ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << ' ' << printRegUnit(RI->RegUnit, MTM.TRI) << '@'
11464ba319b5SDimitry Andric << RI->Cycle);
11477ae0e2c9SDimitry Andric }
11484ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << '\n');
11497ae0e2c9SDimitry Andric
11507ae0e2c9SDimitry Andric if (!TBI.HasValidInstrDepths)
11517ae0e2c9SDimitry Andric continue;
11527ae0e2c9SDimitry Andric // Add live-ins to the critical path length.
11537ae0e2c9SDimitry Andric TBI.CriticalPath = std::max(TBI.CriticalPath,
11547ae0e2c9SDimitry Andric computeCrossBlockCriticalPath(TBI));
11554ba319b5SDimitry Andric LLVM_DEBUG(dbgs() << "Critical path: " << TBI.CriticalPath << '\n');
11567ae0e2c9SDimitry Andric }
11577ae0e2c9SDimitry Andric }
11587ae0e2c9SDimitry Andric
11597ae0e2c9SDimitry Andric MachineTraceMetrics::Trace
getTrace(const MachineBasicBlock * MBB)11607ae0e2c9SDimitry Andric MachineTraceMetrics::Ensemble::getTrace(const MachineBasicBlock *MBB) {
1161875ed548SDimitry Andric TraceBlockInfo &TBI = BlockInfo[MBB->getNumber()];
1162875ed548SDimitry Andric
1163875ed548SDimitry Andric if (!TBI.hasValidDepth() || !TBI.hasValidHeight())
11647ae0e2c9SDimitry Andric computeTrace(MBB);
1165875ed548SDimitry Andric if (!TBI.HasValidInstrDepths)
11667ae0e2c9SDimitry Andric computeInstrDepths(MBB);
1167875ed548SDimitry Andric if (!TBI.HasValidInstrHeights)
11687ae0e2c9SDimitry Andric computeInstrHeights(MBB);
1169875ed548SDimitry Andric
1170875ed548SDimitry Andric return Trace(*this, TBI);
11717ae0e2c9SDimitry Andric }
11727ae0e2c9SDimitry Andric
11737ae0e2c9SDimitry Andric unsigned
getInstrSlack(const MachineInstr & MI) const11743ca95b02SDimitry Andric MachineTraceMetrics::Trace::getInstrSlack(const MachineInstr &MI) const {
11753ca95b02SDimitry Andric assert(getBlockNum() == unsigned(MI.getParent()->getNumber()) &&
11767ae0e2c9SDimitry Andric "MI must be in the trace center block");
11777ae0e2c9SDimitry Andric InstrCycles Cyc = getInstrCycles(MI);
11787ae0e2c9SDimitry Andric return getCriticalPath() - (Cyc.Depth + Cyc.Height);
11797ae0e2c9SDimitry Andric }
11807ae0e2c9SDimitry Andric
11817ae0e2c9SDimitry Andric unsigned
getPHIDepth(const MachineInstr & PHI) const11823ca95b02SDimitry Andric MachineTraceMetrics::Trace::getPHIDepth(const MachineInstr &PHI) const {
11837ae0e2c9SDimitry Andric const MachineBasicBlock *MBB = TE.MTM.MF->getBlockNumbered(getBlockNum());
11847ae0e2c9SDimitry Andric SmallVector<DataDep, 1> Deps;
11857ae0e2c9SDimitry Andric getPHIDeps(PHI, Deps, MBB, TE.MTM.MRI);
11867ae0e2c9SDimitry Andric assert(Deps.size() == 1 && "PHI doesn't have MBB as a predecessor");
11877ae0e2c9SDimitry Andric DataDep &Dep = Deps.front();
11883ca95b02SDimitry Andric unsigned DepCycle = getInstrCycles(*Dep.DefMI).Depth;
11897ae0e2c9SDimitry Andric // Add latency if DefMI is a real instruction. Transients get latency 0.
11907ae0e2c9SDimitry Andric if (!Dep.DefMI->isTransient())
11913ca95b02SDimitry Andric DepCycle += TE.MTM.SchedModel.computeOperandLatency(Dep.DefMI, Dep.DefOp,
11923ca95b02SDimitry Andric &PHI, Dep.UseOp);
11937ae0e2c9SDimitry Andric return DepCycle;
11947ae0e2c9SDimitry Andric }
11957ae0e2c9SDimitry Andric
119639d628a0SDimitry Andric /// When bottom is set include instructions in current block in estimate.
getResourceDepth(bool Bottom) const11977ae0e2c9SDimitry Andric unsigned MachineTraceMetrics::Trace::getResourceDepth(bool Bottom) const {
1198139f7f9bSDimitry Andric // Find the limiting processor resource.
1199139f7f9bSDimitry Andric // Numbers have been pre-scaled to be comparable.
1200139f7f9bSDimitry Andric unsigned PRMax = 0;
1201139f7f9bSDimitry Andric ArrayRef<unsigned> PRDepths = TE.getProcResourceDepths(getBlockNum());
1202139f7f9bSDimitry Andric if (Bottom) {
1203139f7f9bSDimitry Andric ArrayRef<unsigned> PRCycles = TE.MTM.getProcResourceCycles(getBlockNum());
1204139f7f9bSDimitry Andric for (unsigned K = 0; K != PRDepths.size(); ++K)
1205139f7f9bSDimitry Andric PRMax = std::max(PRMax, PRDepths[K] + PRCycles[K]);
1206139f7f9bSDimitry Andric } else {
1207139f7f9bSDimitry Andric for (unsigned K = 0; K != PRDepths.size(); ++K)
1208139f7f9bSDimitry Andric PRMax = std::max(PRMax, PRDepths[K]);
1209139f7f9bSDimitry Andric }
1210139f7f9bSDimitry Andric // Convert to cycle count.
1211139f7f9bSDimitry Andric PRMax = TE.MTM.getCycles(PRMax);
1212139f7f9bSDimitry Andric
121339d628a0SDimitry Andric /// All instructions before current block
12147ae0e2c9SDimitry Andric unsigned Instrs = TBI.InstrDepth;
121539d628a0SDimitry Andric // plus instructions in current block
12167ae0e2c9SDimitry Andric if (Bottom)
12177ae0e2c9SDimitry Andric Instrs += TE.MTM.BlockInfo[getBlockNum()].InstrCount;
12183861d79fSDimitry Andric if (unsigned IW = TE.MTM.SchedModel.getIssueWidth())
12193861d79fSDimitry Andric Instrs /= IW;
12207ae0e2c9SDimitry Andric // Assume issue width 1 without a schedule model.
1221139f7f9bSDimitry Andric return std::max(Instrs, PRMax);
12227ae0e2c9SDimitry Andric }
12237ae0e2c9SDimitry Andric
getResourceLength(ArrayRef<const MachineBasicBlock * > Extrablocks,ArrayRef<const MCSchedClassDesc * > ExtraInstrs,ArrayRef<const MCSchedClassDesc * > RemoveInstrs) const122439d628a0SDimitry Andric unsigned MachineTraceMetrics::Trace::getResourceLength(
122539d628a0SDimitry Andric ArrayRef<const MachineBasicBlock *> Extrablocks,
122639d628a0SDimitry Andric ArrayRef<const MCSchedClassDesc *> ExtraInstrs,
122739d628a0SDimitry Andric ArrayRef<const MCSchedClassDesc *> RemoveInstrs) const {
1228139f7f9bSDimitry Andric // Add up resources above and below the center block.
1229139f7f9bSDimitry Andric ArrayRef<unsigned> PRDepths = TE.getProcResourceDepths(getBlockNum());
1230139f7f9bSDimitry Andric ArrayRef<unsigned> PRHeights = TE.getProcResourceHeights(getBlockNum());
1231139f7f9bSDimitry Andric unsigned PRMax = 0;
123239d628a0SDimitry Andric
123339d628a0SDimitry Andric // Capture computing cycles from extra instructions
123439d628a0SDimitry Andric auto extraCycles = [this](ArrayRef<const MCSchedClassDesc *> Instrs,
123539d628a0SDimitry Andric unsigned ResourceIdx)
123639d628a0SDimitry Andric ->unsigned {
123739d628a0SDimitry Andric unsigned Cycles = 0;
1238875ed548SDimitry Andric for (const MCSchedClassDesc *SC : Instrs) {
1239284c1978SDimitry Andric if (!SC->isValid())
1240284c1978SDimitry Andric continue;
1241284c1978SDimitry Andric for (TargetSchedModel::ProcResIter
1242284c1978SDimitry Andric PI = TE.MTM.SchedModel.getWriteProcResBegin(SC),
124339d628a0SDimitry Andric PE = TE.MTM.SchedModel.getWriteProcResEnd(SC);
124439d628a0SDimitry Andric PI != PE; ++PI) {
124539d628a0SDimitry Andric if (PI->ProcResourceIdx != ResourceIdx)
1246284c1978SDimitry Andric continue;
124739d628a0SDimitry Andric Cycles +=
124839d628a0SDimitry Andric (PI->Cycles * TE.MTM.SchedModel.getResourceFactor(ResourceIdx));
1249284c1978SDimitry Andric }
1250284c1978SDimitry Andric }
125139d628a0SDimitry Andric return Cycles;
125239d628a0SDimitry Andric };
125339d628a0SDimitry Andric
125439d628a0SDimitry Andric for (unsigned K = 0; K != PRDepths.size(); ++K) {
125539d628a0SDimitry Andric unsigned PRCycles = PRDepths[K] + PRHeights[K];
1256875ed548SDimitry Andric for (const MachineBasicBlock *MBB : Extrablocks)
1257875ed548SDimitry Andric PRCycles += TE.MTM.getProcResourceCycles(MBB->getNumber())[K];
125839d628a0SDimitry Andric PRCycles += extraCycles(ExtraInstrs, K);
125939d628a0SDimitry Andric PRCycles -= extraCycles(RemoveInstrs, K);
1260139f7f9bSDimitry Andric PRMax = std::max(PRMax, PRCycles);
1261139f7f9bSDimitry Andric }
1262139f7f9bSDimitry Andric // Convert to cycle count.
1263139f7f9bSDimitry Andric PRMax = TE.MTM.getCycles(PRMax);
1264139f7f9bSDimitry Andric
126539d628a0SDimitry Andric // Instrs: #instructions in current trace outside current block.
12667ae0e2c9SDimitry Andric unsigned Instrs = TBI.InstrDepth + TBI.InstrHeight;
126739d628a0SDimitry Andric // Add instruction count from the extra blocks.
1268875ed548SDimitry Andric for (const MachineBasicBlock *MBB : Extrablocks)
1269875ed548SDimitry Andric Instrs += TE.MTM.getResources(MBB)->InstrCount;
127039d628a0SDimitry Andric Instrs += ExtraInstrs.size();
127139d628a0SDimitry Andric Instrs -= RemoveInstrs.size();
12723861d79fSDimitry Andric if (unsigned IW = TE.MTM.SchedModel.getIssueWidth())
12733861d79fSDimitry Andric Instrs /= IW;
12747ae0e2c9SDimitry Andric // Assume issue width 1 without a schedule model.
1275139f7f9bSDimitry Andric return std::max(Instrs, PRMax);
12767ae0e2c9SDimitry Andric }
12777ae0e2c9SDimitry Andric
isDepInTrace(const MachineInstr & DefMI,const MachineInstr & UseMI) const12783ca95b02SDimitry Andric bool MachineTraceMetrics::Trace::isDepInTrace(const MachineInstr &DefMI,
12793ca95b02SDimitry Andric const MachineInstr &UseMI) const {
12803ca95b02SDimitry Andric if (DefMI.getParent() == UseMI.getParent())
128139d628a0SDimitry Andric return true;
128239d628a0SDimitry Andric
12833ca95b02SDimitry Andric const TraceBlockInfo &DepTBI = TE.BlockInfo[DefMI.getParent()->getNumber()];
12843ca95b02SDimitry Andric const TraceBlockInfo &TBI = TE.BlockInfo[UseMI.getParent()->getNumber()];
128539d628a0SDimitry Andric
128639d628a0SDimitry Andric return DepTBI.isUsefulDominator(TBI);
128739d628a0SDimitry Andric }
128839d628a0SDimitry Andric
print(raw_ostream & OS) const12897ae0e2c9SDimitry Andric void MachineTraceMetrics::Ensemble::print(raw_ostream &OS) const {
12907ae0e2c9SDimitry Andric OS << getName() << " ensemble:\n";
12917ae0e2c9SDimitry Andric for (unsigned i = 0, e = BlockInfo.size(); i != e; ++i) {
12922cab237bSDimitry Andric OS << " %bb." << i << '\t';
12937ae0e2c9SDimitry Andric BlockInfo[i].print(OS);
12947ae0e2c9SDimitry Andric OS << '\n';
12957ae0e2c9SDimitry Andric }
12967ae0e2c9SDimitry Andric }
12977ae0e2c9SDimitry Andric
print(raw_ostream & OS) const12987ae0e2c9SDimitry Andric void MachineTraceMetrics::TraceBlockInfo::print(raw_ostream &OS) const {
12997ae0e2c9SDimitry Andric if (hasValidDepth()) {
13007ae0e2c9SDimitry Andric OS << "depth=" << InstrDepth;
13017ae0e2c9SDimitry Andric if (Pred)
13022cab237bSDimitry Andric OS << " pred=" << printMBBReference(*Pred);
13037ae0e2c9SDimitry Andric else
13047ae0e2c9SDimitry Andric OS << " pred=null";
13052cab237bSDimitry Andric OS << " head=%bb." << Head;
13067ae0e2c9SDimitry Andric if (HasValidInstrDepths)
13077ae0e2c9SDimitry Andric OS << " +instrs";
13087ae0e2c9SDimitry Andric } else
13097ae0e2c9SDimitry Andric OS << "depth invalid";
13107ae0e2c9SDimitry Andric OS << ", ";
13117ae0e2c9SDimitry Andric if (hasValidHeight()) {
13127ae0e2c9SDimitry Andric OS << "height=" << InstrHeight;
13137ae0e2c9SDimitry Andric if (Succ)
13142cab237bSDimitry Andric OS << " succ=" << printMBBReference(*Succ);
13157ae0e2c9SDimitry Andric else
13167ae0e2c9SDimitry Andric OS << " succ=null";
13172cab237bSDimitry Andric OS << " tail=%bb." << Tail;
13187ae0e2c9SDimitry Andric if (HasValidInstrHeights)
13197ae0e2c9SDimitry Andric OS << " +instrs";
13207ae0e2c9SDimitry Andric } else
13217ae0e2c9SDimitry Andric OS << "height invalid";
13227ae0e2c9SDimitry Andric if (HasValidInstrDepths && HasValidInstrHeights)
13237ae0e2c9SDimitry Andric OS << ", crit=" << CriticalPath;
13247ae0e2c9SDimitry Andric }
13257ae0e2c9SDimitry Andric
print(raw_ostream & OS) const13267ae0e2c9SDimitry Andric void MachineTraceMetrics::Trace::print(raw_ostream &OS) const {
13277ae0e2c9SDimitry Andric unsigned MBBNum = &TBI - &TE.BlockInfo[0];
13287ae0e2c9SDimitry Andric
13292cab237bSDimitry Andric OS << TE.getName() << " trace %bb." << TBI.Head << " --> %bb." << MBBNum
13302cab237bSDimitry Andric << " --> %bb." << TBI.Tail << ':';
13317ae0e2c9SDimitry Andric if (TBI.hasValidHeight() && TBI.hasValidDepth())
13327ae0e2c9SDimitry Andric OS << ' ' << getInstrCount() << " instrs.";
13337ae0e2c9SDimitry Andric if (TBI.HasValidInstrDepths && TBI.HasValidInstrHeights)
13347ae0e2c9SDimitry Andric OS << ' ' << TBI.CriticalPath << " cycles.";
13357ae0e2c9SDimitry Andric
13367ae0e2c9SDimitry Andric const MachineTraceMetrics::TraceBlockInfo *Block = &TBI;
13372cab237bSDimitry Andric OS << "\n%bb." << MBBNum;
13387ae0e2c9SDimitry Andric while (Block->hasValidDepth() && Block->Pred) {
13397ae0e2c9SDimitry Andric unsigned Num = Block->Pred->getNumber();
13402cab237bSDimitry Andric OS << " <- " << printMBBReference(*Block->Pred);
13417ae0e2c9SDimitry Andric Block = &TE.BlockInfo[Num];
13427ae0e2c9SDimitry Andric }
13437ae0e2c9SDimitry Andric
13447ae0e2c9SDimitry Andric Block = &TBI;
13457ae0e2c9SDimitry Andric OS << "\n ";
13467ae0e2c9SDimitry Andric while (Block->hasValidHeight() && Block->Succ) {
13477ae0e2c9SDimitry Andric unsigned Num = Block->Succ->getNumber();
13482cab237bSDimitry Andric OS << " -> " << printMBBReference(*Block->Succ);
13497ae0e2c9SDimitry Andric Block = &TE.BlockInfo[Num];
13507ae0e2c9SDimitry Andric }
13517ae0e2c9SDimitry Andric OS << '\n';
13527ae0e2c9SDimitry Andric }
1353