xref: /freebsd-src/contrib/llvm-project/llvm/lib/CodeGen/MachineTraceMetrics.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- lib/CodeGen/MachineTraceMetrics.cpp --------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "llvm/CodeGen/MachineTraceMetrics.h"
100b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
110b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h"
120b57cec5SDimitry Andric #include "llvm/ADT/PostOrderIterator.h"
130b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
140b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
150b57cec5SDimitry Andric #include "llvm/ADT/SparseSet.h"
160b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
170b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBranchProbabilityInfo.h"
180b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
190b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h"
200b57cec5SDimitry Andric #include "llvm/CodeGen/MachineLoopInfo.h"
210b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOperand.h"
220b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
230b57cec5SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
240b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSchedule.h"
250b57cec5SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
26480093f4SDimitry Andric #include "llvm/InitializePasses.h"
270b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
280b57cec5SDimitry Andric #include "llvm/Pass.h"
290b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
300b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
310b57cec5SDimitry Andric #include "llvm/Support/Format.h"
320b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
330b57cec5SDimitry Andric #include <algorithm>
340b57cec5SDimitry Andric #include <cassert>
350b57cec5SDimitry Andric #include <iterator>
360b57cec5SDimitry Andric #include <tuple>
370b57cec5SDimitry Andric #include <utility>
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric using namespace llvm;
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric #define DEBUG_TYPE "machine-trace-metrics"
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric char MachineTraceMetrics::ID = 0;
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric char &llvm::MachineTraceMetricsID = MachineTraceMetrics::ID;
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric INITIALIZE_PASS_BEGIN(MachineTraceMetrics, DEBUG_TYPE,
480b57cec5SDimitry Andric                       "Machine Trace Metrics", false, true)
49*0fca6ea1SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfoWrapperPass)
50*0fca6ea1SDimitry Andric INITIALIZE_PASS_DEPENDENCY(MachineLoopInfoWrapperPass)
510b57cec5SDimitry Andric INITIALIZE_PASS_END(MachineTraceMetrics, DEBUG_TYPE,
520b57cec5SDimitry Andric                     "Machine Trace Metrics", false, true)
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric MachineTraceMetrics::MachineTraceMetrics() : MachineFunctionPass(ID) {
550b57cec5SDimitry Andric   std::fill(std::begin(Ensembles), std::end(Ensembles), nullptr);
560b57cec5SDimitry Andric }
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric void MachineTraceMetrics::getAnalysisUsage(AnalysisUsage &AU) const {
590b57cec5SDimitry Andric   AU.setPreservesAll();
60*0fca6ea1SDimitry Andric   AU.addRequired<MachineBranchProbabilityInfoWrapperPass>();
61*0fca6ea1SDimitry Andric   AU.addRequired<MachineLoopInfoWrapperPass>();
620b57cec5SDimitry Andric   MachineFunctionPass::getAnalysisUsage(AU);
630b57cec5SDimitry Andric }
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric bool MachineTraceMetrics::runOnMachineFunction(MachineFunction &Func) {
660b57cec5SDimitry Andric   MF = &Func;
670b57cec5SDimitry Andric   const TargetSubtargetInfo &ST = MF->getSubtarget();
680b57cec5SDimitry Andric   TII = ST.getInstrInfo();
690b57cec5SDimitry Andric   TRI = ST.getRegisterInfo();
700b57cec5SDimitry Andric   MRI = &MF->getRegInfo();
71*0fca6ea1SDimitry Andric   Loops = &getAnalysis<MachineLoopInfoWrapperPass>().getLI();
720b57cec5SDimitry Andric   SchedModel.init(&ST);
730b57cec5SDimitry Andric   BlockInfo.resize(MF->getNumBlockIDs());
745f757f3fSDimitry Andric   ProcReleaseAtCycles.resize(MF->getNumBlockIDs() *
750b57cec5SDimitry Andric                             SchedModel.getNumProcResourceKinds());
760b57cec5SDimitry Andric   return false;
770b57cec5SDimitry Andric }
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric void MachineTraceMetrics::releaseMemory() {
800b57cec5SDimitry Andric   MF = nullptr;
810b57cec5SDimitry Andric   BlockInfo.clear();
820eae32dcSDimitry Andric   for (Ensemble *&E : Ensembles) {
830eae32dcSDimitry Andric     delete E;
840eae32dcSDimitry Andric     E = nullptr;
850b57cec5SDimitry Andric   }
860b57cec5SDimitry Andric }
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
890b57cec5SDimitry Andric //                          Fixed block information
900b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
910b57cec5SDimitry Andric //
920b57cec5SDimitry Andric // The number of instructions in a basic block and the CPU resources used by
930b57cec5SDimitry Andric // those instructions don't depend on any given trace strategy.
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric /// Compute the resource usage in basic block MBB.
960b57cec5SDimitry Andric const MachineTraceMetrics::FixedBlockInfo*
970b57cec5SDimitry Andric MachineTraceMetrics::getResources(const MachineBasicBlock *MBB) {
980b57cec5SDimitry Andric   assert(MBB && "No basic block");
990b57cec5SDimitry Andric   FixedBlockInfo *FBI = &BlockInfo[MBB->getNumber()];
1000b57cec5SDimitry Andric   if (FBI->hasResources())
1010b57cec5SDimitry Andric     return FBI;
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric   // Compute resource usage in the block.
1040b57cec5SDimitry Andric   FBI->HasCalls = false;
1050b57cec5SDimitry Andric   unsigned InstrCount = 0;
1060b57cec5SDimitry Andric 
1070b57cec5SDimitry Andric   // Add up per-processor resource cycles as well.
1080b57cec5SDimitry Andric   unsigned PRKinds = SchedModel.getNumProcResourceKinds();
1090b57cec5SDimitry Andric   SmallVector<unsigned, 32> PRCycles(PRKinds);
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric   for (const auto &MI : *MBB) {
1120b57cec5SDimitry Andric     if (MI.isTransient())
1130b57cec5SDimitry Andric       continue;
1140b57cec5SDimitry Andric     ++InstrCount;
1150b57cec5SDimitry Andric     if (MI.isCall())
1160b57cec5SDimitry Andric       FBI->HasCalls = true;
1170b57cec5SDimitry Andric 
1180b57cec5SDimitry Andric     // Count processor resources used.
1190b57cec5SDimitry Andric     if (!SchedModel.hasInstrSchedModel())
1200b57cec5SDimitry Andric       continue;
1210b57cec5SDimitry Andric     const MCSchedClassDesc *SC = SchedModel.resolveSchedClass(&MI);
1220b57cec5SDimitry Andric     if (!SC->isValid())
1230b57cec5SDimitry Andric       continue;
1240b57cec5SDimitry Andric 
1250b57cec5SDimitry Andric     for (TargetSchedModel::ProcResIter
1260b57cec5SDimitry Andric          PI = SchedModel.getWriteProcResBegin(SC),
1270b57cec5SDimitry Andric          PE = SchedModel.getWriteProcResEnd(SC); PI != PE; ++PI) {
1280b57cec5SDimitry Andric       assert(PI->ProcResourceIdx < PRKinds && "Bad processor resource kind");
1295f757f3fSDimitry Andric       PRCycles[PI->ProcResourceIdx] += PI->ReleaseAtCycle;
1300b57cec5SDimitry Andric     }
1310b57cec5SDimitry Andric   }
1320b57cec5SDimitry Andric   FBI->InstrCount = InstrCount;
1330b57cec5SDimitry Andric 
1340b57cec5SDimitry Andric   // Scale the resource cycles so they are comparable.
1350b57cec5SDimitry Andric   unsigned PROffset = MBB->getNumber() * PRKinds;
1360b57cec5SDimitry Andric   for (unsigned K = 0; K != PRKinds; ++K)
1375f757f3fSDimitry Andric     ProcReleaseAtCycles[PROffset + K] =
1380b57cec5SDimitry Andric       PRCycles[K] * SchedModel.getResourceFactor(K);
1390b57cec5SDimitry Andric 
1400b57cec5SDimitry Andric   return FBI;
1410b57cec5SDimitry Andric }
1420b57cec5SDimitry Andric 
1430b57cec5SDimitry Andric ArrayRef<unsigned>
1445f757f3fSDimitry Andric MachineTraceMetrics::getProcReleaseAtCycles(unsigned MBBNum) const {
1450b57cec5SDimitry Andric   assert(BlockInfo[MBBNum].hasResources() &&
1465f757f3fSDimitry Andric          "getResources() must be called before getProcReleaseAtCycles()");
1470b57cec5SDimitry Andric   unsigned PRKinds = SchedModel.getNumProcResourceKinds();
1485f757f3fSDimitry Andric   assert((MBBNum+1) * PRKinds <= ProcReleaseAtCycles.size());
1495f757f3fSDimitry Andric   return ArrayRef(ProcReleaseAtCycles.data() + MBBNum * PRKinds, PRKinds);
1500b57cec5SDimitry Andric }
1510b57cec5SDimitry Andric 
1520b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
1530b57cec5SDimitry Andric //                         Ensemble utility functions
1540b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
1550b57cec5SDimitry Andric 
1560b57cec5SDimitry Andric MachineTraceMetrics::Ensemble::Ensemble(MachineTraceMetrics *ct)
1570b57cec5SDimitry Andric   : MTM(*ct) {
1580b57cec5SDimitry Andric   BlockInfo.resize(MTM.BlockInfo.size());
1590b57cec5SDimitry Andric   unsigned PRKinds = MTM.SchedModel.getNumProcResourceKinds();
1600b57cec5SDimitry Andric   ProcResourceDepths.resize(MTM.BlockInfo.size() * PRKinds);
1610b57cec5SDimitry Andric   ProcResourceHeights.resize(MTM.BlockInfo.size() * PRKinds);
1620b57cec5SDimitry Andric }
1630b57cec5SDimitry Andric 
1640b57cec5SDimitry Andric // Virtual destructor serves as an anchor.
1650b57cec5SDimitry Andric MachineTraceMetrics::Ensemble::~Ensemble() = default;
1660b57cec5SDimitry Andric 
1670b57cec5SDimitry Andric const MachineLoop*
1680b57cec5SDimitry Andric MachineTraceMetrics::Ensemble::getLoopFor(const MachineBasicBlock *MBB) const {
1690b57cec5SDimitry Andric   return MTM.Loops->getLoopFor(MBB);
1700b57cec5SDimitry Andric }
1710b57cec5SDimitry Andric 
1720b57cec5SDimitry Andric // Update resource-related information in the TraceBlockInfo for MBB.
1730b57cec5SDimitry Andric // Only update resources related to the trace above MBB.
1740b57cec5SDimitry Andric void MachineTraceMetrics::Ensemble::
1750b57cec5SDimitry Andric computeDepthResources(const MachineBasicBlock *MBB) {
1760b57cec5SDimitry Andric   TraceBlockInfo *TBI = &BlockInfo[MBB->getNumber()];
1770b57cec5SDimitry Andric   unsigned PRKinds = MTM.SchedModel.getNumProcResourceKinds();
1780b57cec5SDimitry Andric   unsigned PROffset = MBB->getNumber() * PRKinds;
1790b57cec5SDimitry Andric 
1800b57cec5SDimitry Andric   // Compute resources from trace above. The top block is simple.
1810b57cec5SDimitry Andric   if (!TBI->Pred) {
1820b57cec5SDimitry Andric     TBI->InstrDepth = 0;
1830b57cec5SDimitry Andric     TBI->Head = MBB->getNumber();
1840b57cec5SDimitry Andric     std::fill(ProcResourceDepths.begin() + PROffset,
1850b57cec5SDimitry Andric               ProcResourceDepths.begin() + PROffset + PRKinds, 0);
1860b57cec5SDimitry Andric     return;
1870b57cec5SDimitry Andric   }
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric   // Compute from the block above. A post-order traversal ensures the
1900b57cec5SDimitry Andric   // predecessor is always computed first.
1910b57cec5SDimitry Andric   unsigned PredNum = TBI->Pred->getNumber();
1920b57cec5SDimitry Andric   TraceBlockInfo *PredTBI = &BlockInfo[PredNum];
1930b57cec5SDimitry Andric   assert(PredTBI->hasValidDepth() && "Trace above has not been computed yet");
1940b57cec5SDimitry Andric   const FixedBlockInfo *PredFBI = MTM.getResources(TBI->Pred);
1950b57cec5SDimitry Andric   TBI->InstrDepth = PredTBI->InstrDepth + PredFBI->InstrCount;
1960b57cec5SDimitry Andric   TBI->Head = PredTBI->Head;
1970b57cec5SDimitry Andric 
1980b57cec5SDimitry Andric   // Compute per-resource depths.
1990b57cec5SDimitry Andric   ArrayRef<unsigned> PredPRDepths = getProcResourceDepths(PredNum);
2005f757f3fSDimitry Andric   ArrayRef<unsigned> PredPRCycles = MTM.getProcReleaseAtCycles(PredNum);
2010b57cec5SDimitry Andric   for (unsigned K = 0; K != PRKinds; ++K)
2020b57cec5SDimitry Andric     ProcResourceDepths[PROffset + K] = PredPRDepths[K] + PredPRCycles[K];
2030b57cec5SDimitry Andric }
2040b57cec5SDimitry Andric 
2050b57cec5SDimitry Andric // Update resource-related information in the TraceBlockInfo for MBB.
2060b57cec5SDimitry Andric // Only update resources related to the trace below MBB.
2070b57cec5SDimitry Andric void MachineTraceMetrics::Ensemble::
2080b57cec5SDimitry Andric computeHeightResources(const MachineBasicBlock *MBB) {
2090b57cec5SDimitry Andric   TraceBlockInfo *TBI = &BlockInfo[MBB->getNumber()];
2100b57cec5SDimitry Andric   unsigned PRKinds = MTM.SchedModel.getNumProcResourceKinds();
2110b57cec5SDimitry Andric   unsigned PROffset = MBB->getNumber() * PRKinds;
2120b57cec5SDimitry Andric 
2130b57cec5SDimitry Andric   // Compute resources for the current block.
2140b57cec5SDimitry Andric   TBI->InstrHeight = MTM.getResources(MBB)->InstrCount;
2155f757f3fSDimitry Andric   ArrayRef<unsigned> PRCycles = MTM.getProcReleaseAtCycles(MBB->getNumber());
2160b57cec5SDimitry Andric 
2170b57cec5SDimitry Andric   // The trace tail is done.
2180b57cec5SDimitry Andric   if (!TBI->Succ) {
2190b57cec5SDimitry Andric     TBI->Tail = MBB->getNumber();
2200b57cec5SDimitry Andric     llvm::copy(PRCycles, ProcResourceHeights.begin() + PROffset);
2210b57cec5SDimitry Andric     return;
2220b57cec5SDimitry Andric   }
2230b57cec5SDimitry Andric 
2240b57cec5SDimitry Andric   // Compute from the block below. A post-order traversal ensures the
2250b57cec5SDimitry Andric   // predecessor is always computed first.
2260b57cec5SDimitry Andric   unsigned SuccNum = TBI->Succ->getNumber();
2270b57cec5SDimitry Andric   TraceBlockInfo *SuccTBI = &BlockInfo[SuccNum];
2280b57cec5SDimitry Andric   assert(SuccTBI->hasValidHeight() && "Trace below has not been computed yet");
2290b57cec5SDimitry Andric   TBI->InstrHeight += SuccTBI->InstrHeight;
2300b57cec5SDimitry Andric   TBI->Tail = SuccTBI->Tail;
2310b57cec5SDimitry Andric 
2320b57cec5SDimitry Andric   // Compute per-resource heights.
2330b57cec5SDimitry Andric   ArrayRef<unsigned> SuccPRHeights = getProcResourceHeights(SuccNum);
2340b57cec5SDimitry Andric   for (unsigned K = 0; K != PRKinds; ++K)
2350b57cec5SDimitry Andric     ProcResourceHeights[PROffset + K] = SuccPRHeights[K] + PRCycles[K];
2360b57cec5SDimitry Andric }
2370b57cec5SDimitry Andric 
2380b57cec5SDimitry Andric // Check if depth resources for MBB are valid and return the TBI.
2390b57cec5SDimitry Andric // Return NULL if the resources have been invalidated.
2400b57cec5SDimitry Andric const MachineTraceMetrics::TraceBlockInfo*
2410b57cec5SDimitry Andric MachineTraceMetrics::Ensemble::
2420b57cec5SDimitry Andric getDepthResources(const MachineBasicBlock *MBB) const {
2430b57cec5SDimitry Andric   const TraceBlockInfo *TBI = &BlockInfo[MBB->getNumber()];
2440b57cec5SDimitry Andric   return TBI->hasValidDepth() ? TBI : nullptr;
2450b57cec5SDimitry Andric }
2460b57cec5SDimitry Andric 
2470b57cec5SDimitry Andric // Check if height resources for MBB are valid and return the TBI.
2480b57cec5SDimitry Andric // Return NULL if the resources have been invalidated.
2490b57cec5SDimitry Andric const MachineTraceMetrics::TraceBlockInfo*
2500b57cec5SDimitry Andric MachineTraceMetrics::Ensemble::
2510b57cec5SDimitry Andric getHeightResources(const MachineBasicBlock *MBB) const {
2520b57cec5SDimitry Andric   const TraceBlockInfo *TBI = &BlockInfo[MBB->getNumber()];
2530b57cec5SDimitry Andric   return TBI->hasValidHeight() ? TBI : nullptr;
2540b57cec5SDimitry Andric }
2550b57cec5SDimitry Andric 
2560b57cec5SDimitry Andric /// Get an array of processor resource depths for MBB. Indexed by processor
2570b57cec5SDimitry Andric /// resource kind, this array contains the scaled processor resources consumed
2580b57cec5SDimitry Andric /// by all blocks preceding MBB in its trace. It does not include instructions
2590b57cec5SDimitry Andric /// in MBB.
2600b57cec5SDimitry Andric ///
2610b57cec5SDimitry Andric /// Compare TraceBlockInfo::InstrDepth.
2620b57cec5SDimitry Andric ArrayRef<unsigned>
2630b57cec5SDimitry Andric MachineTraceMetrics::Ensemble::
2640b57cec5SDimitry Andric getProcResourceDepths(unsigned MBBNum) const {
2650b57cec5SDimitry Andric   unsigned PRKinds = MTM.SchedModel.getNumProcResourceKinds();
2660b57cec5SDimitry Andric   assert((MBBNum+1) * PRKinds <= ProcResourceDepths.size());
267bdd1243dSDimitry Andric   return ArrayRef(ProcResourceDepths.data() + MBBNum * PRKinds, PRKinds);
2680b57cec5SDimitry Andric }
2690b57cec5SDimitry Andric 
2700b57cec5SDimitry Andric /// Get an array of processor resource heights for MBB. Indexed by processor
2710b57cec5SDimitry Andric /// resource kind, this array contains the scaled processor resources consumed
2720b57cec5SDimitry Andric /// by this block and all blocks following it in its trace.
2730b57cec5SDimitry Andric ///
2740b57cec5SDimitry Andric /// Compare TraceBlockInfo::InstrHeight.
2750b57cec5SDimitry Andric ArrayRef<unsigned>
2760b57cec5SDimitry Andric MachineTraceMetrics::Ensemble::
2770b57cec5SDimitry Andric getProcResourceHeights(unsigned MBBNum) const {
2780b57cec5SDimitry Andric   unsigned PRKinds = MTM.SchedModel.getNumProcResourceKinds();
2790b57cec5SDimitry Andric   assert((MBBNum+1) * PRKinds <= ProcResourceHeights.size());
280bdd1243dSDimitry Andric   return ArrayRef(ProcResourceHeights.data() + MBBNum * PRKinds, PRKinds);
2810b57cec5SDimitry Andric }
2820b57cec5SDimitry Andric 
2830b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
2840b57cec5SDimitry Andric //                         Trace Selection Strategies
2850b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
2860b57cec5SDimitry Andric //
2870b57cec5SDimitry Andric // A trace selection strategy is implemented as a sub-class of Ensemble. The
2880b57cec5SDimitry Andric // trace through a block B is computed by two DFS traversals of the CFG
2890b57cec5SDimitry Andric // starting from B. One upwards, and one downwards. During the upwards DFS,
2900b57cec5SDimitry Andric // pickTracePred() is called on the post-ordered blocks. During the downwards
2910b57cec5SDimitry Andric // DFS, pickTraceSucc() is called in a post-order.
2920b57cec5SDimitry Andric //
2930b57cec5SDimitry Andric 
2940b57cec5SDimitry Andric // We never allow traces that leave loops, but we do allow traces to enter
2950b57cec5SDimitry Andric // nested loops. We also never allow traces to contain back-edges.
2960b57cec5SDimitry Andric //
2970b57cec5SDimitry Andric // This means that a loop header can never appear above the center block of a
2980b57cec5SDimitry Andric // trace, except as the trace head. Below the center block, loop exiting edges
2990b57cec5SDimitry Andric // are banned.
3000b57cec5SDimitry Andric //
3010b57cec5SDimitry Andric // Return true if an edge from the From loop to the To loop is leaving a loop.
3020b57cec5SDimitry Andric // Either of To and From can be null.
3030b57cec5SDimitry Andric static bool isExitingLoop(const MachineLoop *From, const MachineLoop *To) {
3040b57cec5SDimitry Andric   return From && !From->contains(To);
3050b57cec5SDimitry Andric }
3060b57cec5SDimitry Andric 
3070b57cec5SDimitry Andric // MinInstrCountEnsemble - Pick the trace that executes the least number of
3080b57cec5SDimitry Andric // instructions.
3090b57cec5SDimitry Andric namespace {
3100b57cec5SDimitry Andric 
3110b57cec5SDimitry Andric class MinInstrCountEnsemble : public MachineTraceMetrics::Ensemble {
3120b57cec5SDimitry Andric   const char *getName() const override { return "MinInstr"; }
3130b57cec5SDimitry Andric   const MachineBasicBlock *pickTracePred(const MachineBasicBlock*) override;
3140b57cec5SDimitry Andric   const MachineBasicBlock *pickTraceSucc(const MachineBasicBlock*) override;
3150b57cec5SDimitry Andric 
3160b57cec5SDimitry Andric public:
3170b57cec5SDimitry Andric   MinInstrCountEnsemble(MachineTraceMetrics *mtm)
3180b57cec5SDimitry Andric     : MachineTraceMetrics::Ensemble(mtm) {}
3190b57cec5SDimitry Andric };
3200b57cec5SDimitry Andric 
32106c3fb27SDimitry Andric /// Pick only the current basic block for the trace and do not choose any
32206c3fb27SDimitry Andric /// predecessors/successors.
32306c3fb27SDimitry Andric class LocalEnsemble : public MachineTraceMetrics::Ensemble {
32406c3fb27SDimitry Andric   const char *getName() const override { return "Local"; }
32506c3fb27SDimitry Andric   const MachineBasicBlock *pickTracePred(const MachineBasicBlock *) override {
32606c3fb27SDimitry Andric     return nullptr;
32706c3fb27SDimitry Andric   };
32806c3fb27SDimitry Andric   const MachineBasicBlock *pickTraceSucc(const MachineBasicBlock *) override {
32906c3fb27SDimitry Andric     return nullptr;
33006c3fb27SDimitry Andric   };
33106c3fb27SDimitry Andric 
33206c3fb27SDimitry Andric public:
33306c3fb27SDimitry Andric   LocalEnsemble(MachineTraceMetrics *MTM)
33406c3fb27SDimitry Andric       : MachineTraceMetrics::Ensemble(MTM) {}
33506c3fb27SDimitry Andric };
3360b57cec5SDimitry Andric } // end anonymous namespace
3370b57cec5SDimitry Andric 
3380b57cec5SDimitry Andric // Select the preferred predecessor for MBB.
3390b57cec5SDimitry Andric const MachineBasicBlock*
3400b57cec5SDimitry Andric MinInstrCountEnsemble::pickTracePred(const MachineBasicBlock *MBB) {
3410b57cec5SDimitry Andric   if (MBB->pred_empty())
3420b57cec5SDimitry Andric     return nullptr;
3430b57cec5SDimitry Andric   const MachineLoop *CurLoop = getLoopFor(MBB);
3440b57cec5SDimitry Andric   // Don't leave loops, and never follow back-edges.
3450b57cec5SDimitry Andric   if (CurLoop && MBB == CurLoop->getHeader())
3460b57cec5SDimitry Andric     return nullptr;
3470b57cec5SDimitry Andric   unsigned CurCount = MTM.getResources(MBB)->InstrCount;
3480b57cec5SDimitry Andric   const MachineBasicBlock *Best = nullptr;
3490b57cec5SDimitry Andric   unsigned BestDepth = 0;
3500b57cec5SDimitry Andric   for (const MachineBasicBlock *Pred : MBB->predecessors()) {
3510b57cec5SDimitry Andric     const MachineTraceMetrics::TraceBlockInfo *PredTBI =
3520b57cec5SDimitry Andric       getDepthResources(Pred);
3530b57cec5SDimitry Andric     // Ignore cycles that aren't natural loops.
3540b57cec5SDimitry Andric     if (!PredTBI)
3550b57cec5SDimitry Andric       continue;
3560b57cec5SDimitry Andric     // Pick the predecessor that would give this block the smallest InstrDepth.
3570b57cec5SDimitry Andric     unsigned Depth = PredTBI->InstrDepth + CurCount;
3580b57cec5SDimitry Andric     if (!Best || Depth < BestDepth) {
3590b57cec5SDimitry Andric       Best = Pred;
3600b57cec5SDimitry Andric       BestDepth = Depth;
3610b57cec5SDimitry Andric     }
3620b57cec5SDimitry Andric   }
3630b57cec5SDimitry Andric   return Best;
3640b57cec5SDimitry Andric }
3650b57cec5SDimitry Andric 
3660b57cec5SDimitry Andric // Select the preferred successor for MBB.
3670b57cec5SDimitry Andric const MachineBasicBlock*
3680b57cec5SDimitry Andric MinInstrCountEnsemble::pickTraceSucc(const MachineBasicBlock *MBB) {
369bdd1243dSDimitry Andric   if (MBB->succ_empty())
3700b57cec5SDimitry Andric     return nullptr;
3710b57cec5SDimitry Andric   const MachineLoop *CurLoop = getLoopFor(MBB);
3720b57cec5SDimitry Andric   const MachineBasicBlock *Best = nullptr;
3730b57cec5SDimitry Andric   unsigned BestHeight = 0;
3740b57cec5SDimitry Andric   for (const MachineBasicBlock *Succ : MBB->successors()) {
3750b57cec5SDimitry Andric     // Don't consider back-edges.
3760b57cec5SDimitry Andric     if (CurLoop && Succ == CurLoop->getHeader())
3770b57cec5SDimitry Andric       continue;
3780b57cec5SDimitry Andric     // Don't consider successors exiting CurLoop.
3790b57cec5SDimitry Andric     if (isExitingLoop(CurLoop, getLoopFor(Succ)))
3800b57cec5SDimitry Andric       continue;
3810b57cec5SDimitry Andric     const MachineTraceMetrics::TraceBlockInfo *SuccTBI =
3820b57cec5SDimitry Andric       getHeightResources(Succ);
3830b57cec5SDimitry Andric     // Ignore cycles that aren't natural loops.
3840b57cec5SDimitry Andric     if (!SuccTBI)
3850b57cec5SDimitry Andric       continue;
3860b57cec5SDimitry Andric     // Pick the successor that would give this block the smallest InstrHeight.
3870b57cec5SDimitry Andric     unsigned Height = SuccTBI->InstrHeight;
3880b57cec5SDimitry Andric     if (!Best || Height < BestHeight) {
3890b57cec5SDimitry Andric       Best = Succ;
3900b57cec5SDimitry Andric       BestHeight = Height;
3910b57cec5SDimitry Andric     }
3920b57cec5SDimitry Andric   }
3930b57cec5SDimitry Andric   return Best;
3940b57cec5SDimitry Andric }
3950b57cec5SDimitry Andric 
3960b57cec5SDimitry Andric // Get an Ensemble sub-class for the requested trace strategy.
3970b57cec5SDimitry Andric MachineTraceMetrics::Ensemble *
39806c3fb27SDimitry Andric MachineTraceMetrics::getEnsemble(MachineTraceStrategy strategy) {
39906c3fb27SDimitry Andric   assert(strategy < MachineTraceStrategy::TS_NumStrategies &&
40006c3fb27SDimitry Andric          "Invalid trace strategy enum");
40106c3fb27SDimitry Andric   Ensemble *&E = Ensembles[static_cast<size_t>(strategy)];
4020b57cec5SDimitry Andric   if (E)
4030b57cec5SDimitry Andric     return E;
4040b57cec5SDimitry Andric 
4050b57cec5SDimitry Andric   // Allocate new Ensemble on demand.
4060b57cec5SDimitry Andric   switch (strategy) {
40706c3fb27SDimitry Andric   case MachineTraceStrategy::TS_MinInstrCount:
40806c3fb27SDimitry Andric     return (E = new MinInstrCountEnsemble(this));
40906c3fb27SDimitry Andric   case MachineTraceStrategy::TS_Local:
41006c3fb27SDimitry Andric     return (E = new LocalEnsemble(this));
4110b57cec5SDimitry Andric   default: llvm_unreachable("Invalid trace strategy enum");
4120b57cec5SDimitry Andric   }
4130b57cec5SDimitry Andric }
4140b57cec5SDimitry Andric 
4150b57cec5SDimitry Andric void MachineTraceMetrics::invalidate(const MachineBasicBlock *MBB) {
4160b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Invalidate traces through " << printMBBReference(*MBB)
4170b57cec5SDimitry Andric                     << '\n');
4180b57cec5SDimitry Andric   BlockInfo[MBB->getNumber()].invalidate();
4190eae32dcSDimitry Andric   for (Ensemble *E : Ensembles)
4200eae32dcSDimitry Andric     if (E)
4210eae32dcSDimitry Andric       E->invalidate(MBB);
4220b57cec5SDimitry Andric }
4230b57cec5SDimitry Andric 
4240b57cec5SDimitry Andric void MachineTraceMetrics::verifyAnalysis() const {
4250b57cec5SDimitry Andric   if (!MF)
4260b57cec5SDimitry Andric     return;
4270b57cec5SDimitry Andric #ifndef NDEBUG
4280b57cec5SDimitry Andric   assert(BlockInfo.size() == MF->getNumBlockIDs() && "Outdated BlockInfo size");
4290eae32dcSDimitry Andric   for (Ensemble *E : Ensembles)
4300eae32dcSDimitry Andric     if (E)
4310eae32dcSDimitry Andric       E->verify();
4320b57cec5SDimitry Andric #endif
4330b57cec5SDimitry Andric }
4340b57cec5SDimitry Andric 
4350b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
4360b57cec5SDimitry Andric //                               Trace building
4370b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
4380b57cec5SDimitry Andric //
4390b57cec5SDimitry Andric // Traces are built by two CFG traversals. To avoid recomputing too much, use a
4400b57cec5SDimitry Andric // set abstraction that confines the search to the current loop, and doesn't
4410b57cec5SDimitry Andric // revisit blocks.
4420b57cec5SDimitry Andric 
4430b57cec5SDimitry Andric namespace {
4440b57cec5SDimitry Andric 
4450b57cec5SDimitry Andric struct LoopBounds {
4460b57cec5SDimitry Andric   MutableArrayRef<MachineTraceMetrics::TraceBlockInfo> Blocks;
4470b57cec5SDimitry Andric   SmallPtrSet<const MachineBasicBlock*, 8> Visited;
4480b57cec5SDimitry Andric   const MachineLoopInfo *Loops;
4490b57cec5SDimitry Andric   bool Downward = false;
4500b57cec5SDimitry Andric 
4510b57cec5SDimitry Andric   LoopBounds(MutableArrayRef<MachineTraceMetrics::TraceBlockInfo> blocks,
4520b57cec5SDimitry Andric              const MachineLoopInfo *loops) : Blocks(blocks), Loops(loops) {}
4530b57cec5SDimitry Andric };
4540b57cec5SDimitry Andric 
4550b57cec5SDimitry Andric } // end anonymous namespace
4560b57cec5SDimitry Andric 
4570b57cec5SDimitry Andric // Specialize po_iterator_storage in order to prune the post-order traversal so
4580b57cec5SDimitry Andric // it is limited to the current loop and doesn't traverse the loop back edges.
4590b57cec5SDimitry Andric namespace llvm {
4600b57cec5SDimitry Andric 
4610b57cec5SDimitry Andric template<>
4620b57cec5SDimitry Andric class po_iterator_storage<LoopBounds, true> {
4630b57cec5SDimitry Andric   LoopBounds &LB;
4640b57cec5SDimitry Andric 
4650b57cec5SDimitry Andric public:
4660b57cec5SDimitry Andric   po_iterator_storage(LoopBounds &lb) : LB(lb) {}
4670b57cec5SDimitry Andric 
4680b57cec5SDimitry Andric   void finishPostorder(const MachineBasicBlock*) {}
4690b57cec5SDimitry Andric 
470bdd1243dSDimitry Andric   bool insertEdge(std::optional<const MachineBasicBlock *> From,
4710b57cec5SDimitry Andric                   const MachineBasicBlock *To) {
4720b57cec5SDimitry Andric     // Skip already visited To blocks.
4730b57cec5SDimitry Andric     MachineTraceMetrics::TraceBlockInfo &TBI = LB.Blocks[To->getNumber()];
4740b57cec5SDimitry Andric     if (LB.Downward ? TBI.hasValidHeight() : TBI.hasValidDepth())
4750b57cec5SDimitry Andric       return false;
4760b57cec5SDimitry Andric     // From is null once when To is the trace center block.
4770b57cec5SDimitry Andric     if (From) {
4780b57cec5SDimitry Andric       if (const MachineLoop *FromLoop = LB.Loops->getLoopFor(*From)) {
4790b57cec5SDimitry Andric         // Don't follow backedges, don't leave FromLoop when going upwards.
4800b57cec5SDimitry Andric         if ((LB.Downward ? To : *From) == FromLoop->getHeader())
4810b57cec5SDimitry Andric           return false;
4820b57cec5SDimitry Andric         // Don't leave FromLoop.
4830b57cec5SDimitry Andric         if (isExitingLoop(FromLoop, LB.Loops->getLoopFor(To)))
4840b57cec5SDimitry Andric           return false;
4850b57cec5SDimitry Andric       }
4860b57cec5SDimitry Andric     }
4870b57cec5SDimitry Andric     // To is a new block. Mark the block as visited in case the CFG has cycles
4880b57cec5SDimitry Andric     // that MachineLoopInfo didn't recognize as a natural loop.
4890b57cec5SDimitry Andric     return LB.Visited.insert(To).second;
4900b57cec5SDimitry Andric   }
4910b57cec5SDimitry Andric };
4920b57cec5SDimitry Andric 
4930b57cec5SDimitry Andric } // end namespace llvm
4940b57cec5SDimitry Andric 
4950b57cec5SDimitry Andric /// Compute the trace through MBB.
4960b57cec5SDimitry Andric void MachineTraceMetrics::Ensemble::computeTrace(const MachineBasicBlock *MBB) {
4970b57cec5SDimitry Andric   LLVM_DEBUG(dbgs() << "Computing " << getName() << " trace through "
4980b57cec5SDimitry Andric                     << printMBBReference(*MBB) << '\n');
4990b57cec5SDimitry Andric   // Set up loop bounds for the backwards post-order traversal.
5000b57cec5SDimitry Andric   LoopBounds Bounds(BlockInfo, MTM.Loops);
5010b57cec5SDimitry Andric 
5020b57cec5SDimitry Andric   // Run an upwards post-order search for the trace start.
5030b57cec5SDimitry Andric   Bounds.Downward = false;
5040b57cec5SDimitry Andric   Bounds.Visited.clear();
505fcaf7f86SDimitry Andric   for (const auto *I : inverse_post_order_ext(MBB, Bounds)) {
5060b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "  pred for " << printMBBReference(*I) << ": ");
5070b57cec5SDimitry Andric     TraceBlockInfo &TBI = BlockInfo[I->getNumber()];
5080b57cec5SDimitry Andric     // All the predecessors have been visited, pick the preferred one.
5090b57cec5SDimitry Andric     TBI.Pred = pickTracePred(I);
5100b57cec5SDimitry Andric     LLVM_DEBUG({
5110b57cec5SDimitry Andric       if (TBI.Pred)
5120b57cec5SDimitry Andric         dbgs() << printMBBReference(*TBI.Pred) << '\n';
5130b57cec5SDimitry Andric       else
5140b57cec5SDimitry Andric         dbgs() << "null\n";
5150b57cec5SDimitry Andric     });
5160b57cec5SDimitry Andric     // The trace leading to I is now known, compute the depth resources.
5170b57cec5SDimitry Andric     computeDepthResources(I);
5180b57cec5SDimitry Andric   }
5190b57cec5SDimitry Andric 
5200b57cec5SDimitry Andric   // Run a downwards post-order search for the trace end.
5210b57cec5SDimitry Andric   Bounds.Downward = true;
5220b57cec5SDimitry Andric   Bounds.Visited.clear();
523fcaf7f86SDimitry Andric   for (const auto *I : post_order_ext(MBB, Bounds)) {
5240b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "  succ for " << printMBBReference(*I) << ": ");
5250b57cec5SDimitry Andric     TraceBlockInfo &TBI = BlockInfo[I->getNumber()];
5260b57cec5SDimitry Andric     // All the successors have been visited, pick the preferred one.
5270b57cec5SDimitry Andric     TBI.Succ = pickTraceSucc(I);
5280b57cec5SDimitry Andric     LLVM_DEBUG({
5290b57cec5SDimitry Andric       if (TBI.Succ)
5300b57cec5SDimitry Andric         dbgs() << printMBBReference(*TBI.Succ) << '\n';
5310b57cec5SDimitry Andric       else
5320b57cec5SDimitry Andric         dbgs() << "null\n";
5330b57cec5SDimitry Andric     });
5340b57cec5SDimitry Andric     // The trace leaving I is now known, compute the height resources.
5350b57cec5SDimitry Andric     computeHeightResources(I);
5360b57cec5SDimitry Andric   }
5370b57cec5SDimitry Andric }
5380b57cec5SDimitry Andric 
5390b57cec5SDimitry Andric /// Invalidate traces through BadMBB.
5400b57cec5SDimitry Andric void
5410b57cec5SDimitry Andric MachineTraceMetrics::Ensemble::invalidate(const MachineBasicBlock *BadMBB) {
5420b57cec5SDimitry Andric   SmallVector<const MachineBasicBlock*, 16> WorkList;
5430b57cec5SDimitry Andric   TraceBlockInfo &BadTBI = BlockInfo[BadMBB->getNumber()];
5440b57cec5SDimitry Andric 
5450b57cec5SDimitry Andric   // Invalidate height resources of blocks above MBB.
5460b57cec5SDimitry Andric   if (BadTBI.hasValidHeight()) {
5470b57cec5SDimitry Andric     BadTBI.invalidateHeight();
5480b57cec5SDimitry Andric     WorkList.push_back(BadMBB);
5490b57cec5SDimitry Andric     do {
5500b57cec5SDimitry Andric       const MachineBasicBlock *MBB = WorkList.pop_back_val();
5510b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "Invalidate " << printMBBReference(*MBB) << ' '
5520b57cec5SDimitry Andric                         << getName() << " height.\n");
5530b57cec5SDimitry Andric       // Find any MBB predecessors that have MBB as their preferred successor.
5540b57cec5SDimitry Andric       // They are the only ones that need to be invalidated.
5550b57cec5SDimitry Andric       for (const MachineBasicBlock *Pred : MBB->predecessors()) {
5560b57cec5SDimitry Andric         TraceBlockInfo &TBI = BlockInfo[Pred->getNumber()];
5570b57cec5SDimitry Andric         if (!TBI.hasValidHeight())
5580b57cec5SDimitry Andric           continue;
5590b57cec5SDimitry Andric         if (TBI.Succ == MBB) {
5600b57cec5SDimitry Andric           TBI.invalidateHeight();
5610b57cec5SDimitry Andric           WorkList.push_back(Pred);
5620b57cec5SDimitry Andric           continue;
5630b57cec5SDimitry Andric         }
5640b57cec5SDimitry Andric         // Verify that TBI.Succ is actually a *I successor.
5650b57cec5SDimitry Andric         assert((!TBI.Succ || Pred->isSuccessor(TBI.Succ)) && "CFG changed");
5660b57cec5SDimitry Andric       }
5670b57cec5SDimitry Andric     } while (!WorkList.empty());
5680b57cec5SDimitry Andric   }
5690b57cec5SDimitry Andric 
5700b57cec5SDimitry Andric   // Invalidate depth resources of blocks below MBB.
5710b57cec5SDimitry Andric   if (BadTBI.hasValidDepth()) {
5720b57cec5SDimitry Andric     BadTBI.invalidateDepth();
5730b57cec5SDimitry Andric     WorkList.push_back(BadMBB);
5740b57cec5SDimitry Andric     do {
5750b57cec5SDimitry Andric       const MachineBasicBlock *MBB = WorkList.pop_back_val();
5760b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << "Invalidate " << printMBBReference(*MBB) << ' '
5770b57cec5SDimitry Andric                         << getName() << " depth.\n");
5780b57cec5SDimitry Andric       // Find any MBB successors that have MBB as their preferred predecessor.
5790b57cec5SDimitry Andric       // They are the only ones that need to be invalidated.
5800b57cec5SDimitry Andric       for (const MachineBasicBlock *Succ : MBB->successors()) {
5810b57cec5SDimitry Andric         TraceBlockInfo &TBI = BlockInfo[Succ->getNumber()];
5820b57cec5SDimitry Andric         if (!TBI.hasValidDepth())
5830b57cec5SDimitry Andric           continue;
5840b57cec5SDimitry Andric         if (TBI.Pred == MBB) {
5850b57cec5SDimitry Andric           TBI.invalidateDepth();
5860b57cec5SDimitry Andric           WorkList.push_back(Succ);
5870b57cec5SDimitry Andric           continue;
5880b57cec5SDimitry Andric         }
5890b57cec5SDimitry Andric         // Verify that TBI.Pred is actually a *I predecessor.
5900b57cec5SDimitry Andric         assert((!TBI.Pred || Succ->isPredecessor(TBI.Pred)) && "CFG changed");
5910b57cec5SDimitry Andric       }
5920b57cec5SDimitry Andric     } while (!WorkList.empty());
5930b57cec5SDimitry Andric   }
5940b57cec5SDimitry Andric 
5950b57cec5SDimitry Andric   // Clear any per-instruction data. We only have to do this for BadMBB itself
5960b57cec5SDimitry Andric   // because the instructions in that block may change. Other blocks may be
5970b57cec5SDimitry Andric   // invalidated, but their instructions will stay the same, so there is no
5980b57cec5SDimitry Andric   // need to erase the Cycle entries. They will be overwritten when we
5990b57cec5SDimitry Andric   // recompute.
6000b57cec5SDimitry Andric   for (const auto &I : *BadMBB)
6010b57cec5SDimitry Andric     Cycles.erase(&I);
6020b57cec5SDimitry Andric }
6030b57cec5SDimitry Andric 
6040b57cec5SDimitry Andric void MachineTraceMetrics::Ensemble::verify() const {
6050b57cec5SDimitry Andric #ifndef NDEBUG
6060b57cec5SDimitry Andric   assert(BlockInfo.size() == MTM.MF->getNumBlockIDs() &&
6070b57cec5SDimitry Andric          "Outdated BlockInfo size");
6080b57cec5SDimitry Andric   for (unsigned Num = 0, e = BlockInfo.size(); Num != e; ++Num) {
6090b57cec5SDimitry Andric     const TraceBlockInfo &TBI = BlockInfo[Num];
6100b57cec5SDimitry Andric     if (TBI.hasValidDepth() && TBI.Pred) {
6110b57cec5SDimitry Andric       const MachineBasicBlock *MBB = MTM.MF->getBlockNumbered(Num);
6120b57cec5SDimitry Andric       assert(MBB->isPredecessor(TBI.Pred) && "CFG doesn't match trace");
6130b57cec5SDimitry Andric       assert(BlockInfo[TBI.Pred->getNumber()].hasValidDepth() &&
6140b57cec5SDimitry Andric              "Trace is broken, depth should have been invalidated.");
6150b57cec5SDimitry Andric       const MachineLoop *Loop = getLoopFor(MBB);
6160b57cec5SDimitry Andric       assert(!(Loop && MBB == Loop->getHeader()) && "Trace contains backedge");
6170b57cec5SDimitry Andric     }
6180b57cec5SDimitry Andric     if (TBI.hasValidHeight() && TBI.Succ) {
6190b57cec5SDimitry Andric       const MachineBasicBlock *MBB = MTM.MF->getBlockNumbered(Num);
6200b57cec5SDimitry Andric       assert(MBB->isSuccessor(TBI.Succ) && "CFG doesn't match trace");
6210b57cec5SDimitry Andric       assert(BlockInfo[TBI.Succ->getNumber()].hasValidHeight() &&
6220b57cec5SDimitry Andric              "Trace is broken, height should have been invalidated.");
6230b57cec5SDimitry Andric       const MachineLoop *Loop = getLoopFor(MBB);
6240b57cec5SDimitry Andric       const MachineLoop *SuccLoop = getLoopFor(TBI.Succ);
6250b57cec5SDimitry Andric       assert(!(Loop && Loop == SuccLoop && TBI.Succ == Loop->getHeader()) &&
6260b57cec5SDimitry Andric              "Trace contains backedge");
6270b57cec5SDimitry Andric     }
6280b57cec5SDimitry Andric   }
6290b57cec5SDimitry Andric #endif
6300b57cec5SDimitry Andric }
6310b57cec5SDimitry Andric 
6320b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
6330b57cec5SDimitry Andric //                             Data Dependencies
6340b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
6350b57cec5SDimitry Andric //
6360b57cec5SDimitry Andric // Compute the depth and height of each instruction based on data dependencies
6370b57cec5SDimitry Andric // and instruction latencies. These cycle numbers assume that the CPU can issue
6380b57cec5SDimitry Andric // an infinite number of instructions per cycle as long as their dependencies
6390b57cec5SDimitry Andric // are ready.
6400b57cec5SDimitry Andric 
6410b57cec5SDimitry Andric // A data dependency is represented as a defining MI and operand numbers on the
6420b57cec5SDimitry Andric // defining and using MI.
6430b57cec5SDimitry Andric namespace {
6440b57cec5SDimitry Andric 
6450b57cec5SDimitry Andric struct DataDep {
6460b57cec5SDimitry Andric   const MachineInstr *DefMI;
6470b57cec5SDimitry Andric   unsigned DefOp;
6480b57cec5SDimitry Andric   unsigned UseOp;
6490b57cec5SDimitry Andric 
6500b57cec5SDimitry Andric   DataDep(const MachineInstr *DefMI, unsigned DefOp, unsigned UseOp)
6510b57cec5SDimitry Andric     : DefMI(DefMI), DefOp(DefOp), UseOp(UseOp) {}
6520b57cec5SDimitry Andric 
6530b57cec5SDimitry Andric   /// Create a DataDep from an SSA form virtual register.
6540b57cec5SDimitry Andric   DataDep(const MachineRegisterInfo *MRI, unsigned VirtReg, unsigned UseOp)
6550b57cec5SDimitry Andric     : UseOp(UseOp) {
6568bcb0991SDimitry Andric     assert(Register::isVirtualRegister(VirtReg));
6570b57cec5SDimitry Andric     MachineRegisterInfo::def_iterator DefI = MRI->def_begin(VirtReg);
6580b57cec5SDimitry Andric     assert(!DefI.atEnd() && "Register has no defs");
6590b57cec5SDimitry Andric     DefMI = DefI->getParent();
6600b57cec5SDimitry Andric     DefOp = DefI.getOperandNo();
6610b57cec5SDimitry Andric     assert((++DefI).atEnd() && "Register has multiple defs");
6620b57cec5SDimitry Andric   }
6630b57cec5SDimitry Andric };
6640b57cec5SDimitry Andric 
6650b57cec5SDimitry Andric } // end anonymous namespace
6660b57cec5SDimitry Andric 
6670b57cec5SDimitry Andric // Get the input data dependencies that must be ready before UseMI can issue.
6680b57cec5SDimitry Andric // Return true if UseMI has any physreg operands.
6690b57cec5SDimitry Andric static bool getDataDeps(const MachineInstr &UseMI,
6700b57cec5SDimitry Andric                         SmallVectorImpl<DataDep> &Deps,
6710b57cec5SDimitry Andric                         const MachineRegisterInfo *MRI) {
6720b57cec5SDimitry Andric   // Debug values should not be included in any calculations.
6730b57cec5SDimitry Andric   if (UseMI.isDebugInstr())
6740b57cec5SDimitry Andric     return false;
6750b57cec5SDimitry Andric 
6760b57cec5SDimitry Andric   bool HasPhysRegs = false;
67706c3fb27SDimitry Andric   for (const MachineOperand &MO : UseMI.operands()) {
6780b57cec5SDimitry Andric     if (!MO.isReg())
6790b57cec5SDimitry Andric       continue;
6808bcb0991SDimitry Andric     Register Reg = MO.getReg();
6810b57cec5SDimitry Andric     if (!Reg)
6820b57cec5SDimitry Andric       continue;
683bdd1243dSDimitry Andric     if (Reg.isPhysical()) {
6840b57cec5SDimitry Andric       HasPhysRegs = true;
6850b57cec5SDimitry Andric       continue;
6860b57cec5SDimitry Andric     }
6870b57cec5SDimitry Andric     // Collect virtual register reads.
6880b57cec5SDimitry Andric     if (MO.readsReg())
68906c3fb27SDimitry Andric       Deps.push_back(DataDep(MRI, Reg, MO.getOperandNo()));
6900b57cec5SDimitry Andric   }
6910b57cec5SDimitry Andric   return HasPhysRegs;
6920b57cec5SDimitry Andric }
6930b57cec5SDimitry Andric 
6940b57cec5SDimitry Andric // Get the input data dependencies of a PHI instruction, using Pred as the
6950b57cec5SDimitry Andric // preferred predecessor.
6960b57cec5SDimitry Andric // This will add at most one dependency to Deps.
6970b57cec5SDimitry Andric static void getPHIDeps(const MachineInstr &UseMI,
6980b57cec5SDimitry Andric                        SmallVectorImpl<DataDep> &Deps,
6990b57cec5SDimitry Andric                        const MachineBasicBlock *Pred,
7000b57cec5SDimitry Andric                        const MachineRegisterInfo *MRI) {
7010b57cec5SDimitry Andric   // No predecessor at the beginning of a trace. Ignore dependencies.
7020b57cec5SDimitry Andric   if (!Pred)
7030b57cec5SDimitry Andric     return;
7040b57cec5SDimitry Andric   assert(UseMI.isPHI() && UseMI.getNumOperands() % 2 && "Bad PHI");
7050b57cec5SDimitry Andric   for (unsigned i = 1; i != UseMI.getNumOperands(); i += 2) {
7060b57cec5SDimitry Andric     if (UseMI.getOperand(i + 1).getMBB() == Pred) {
7078bcb0991SDimitry Andric       Register Reg = UseMI.getOperand(i).getReg();
7080b57cec5SDimitry Andric       Deps.push_back(DataDep(MRI, Reg, i));
7090b57cec5SDimitry Andric       return;
7100b57cec5SDimitry Andric     }
7110b57cec5SDimitry Andric   }
7120b57cec5SDimitry Andric }
7130b57cec5SDimitry Andric 
7140b57cec5SDimitry Andric // Identify physreg dependencies for UseMI, and update the live regunit
7150b57cec5SDimitry Andric // tracking set when scanning instructions downwards.
7160b57cec5SDimitry Andric static void updatePhysDepsDownwards(const MachineInstr *UseMI,
7170b57cec5SDimitry Andric                                     SmallVectorImpl<DataDep> &Deps,
7180b57cec5SDimitry Andric                                     SparseSet<LiveRegUnit> &RegUnits,
7190b57cec5SDimitry Andric                                     const TargetRegisterInfo *TRI) {
720e8d8bef9SDimitry Andric   SmallVector<MCRegister, 8> Kills;
7210b57cec5SDimitry Andric   SmallVector<unsigned, 8> LiveDefOps;
7220b57cec5SDimitry Andric 
72306c3fb27SDimitry Andric   for (const MachineOperand &MO : UseMI->operands()) {
724e8d8bef9SDimitry Andric     if (!MO.isReg() || !MO.getReg().isPhysical())
7250b57cec5SDimitry Andric       continue;
726e8d8bef9SDimitry Andric     MCRegister Reg = MO.getReg().asMCReg();
7270b57cec5SDimitry Andric     // Track live defs and kills for updating RegUnits.
7280b57cec5SDimitry Andric     if (MO.isDef()) {
7290b57cec5SDimitry Andric       if (MO.isDead())
7300b57cec5SDimitry Andric         Kills.push_back(Reg);
7310b57cec5SDimitry Andric       else
73206c3fb27SDimitry Andric         LiveDefOps.push_back(MO.getOperandNo());
7330b57cec5SDimitry Andric     } else if (MO.isKill())
7340b57cec5SDimitry Andric       Kills.push_back(Reg);
7350b57cec5SDimitry Andric     // Identify dependencies.
7360b57cec5SDimitry Andric     if (!MO.readsReg())
7370b57cec5SDimitry Andric       continue;
73806c3fb27SDimitry Andric     for (MCRegUnit Unit : TRI->regunits(Reg)) {
73906c3fb27SDimitry Andric       SparseSet<LiveRegUnit>::iterator I = RegUnits.find(Unit);
7400b57cec5SDimitry Andric       if (I == RegUnits.end())
7410b57cec5SDimitry Andric         continue;
74206c3fb27SDimitry Andric       Deps.push_back(DataDep(I->MI, I->Op, MO.getOperandNo()));
7430b57cec5SDimitry Andric       break;
7440b57cec5SDimitry Andric     }
7450b57cec5SDimitry Andric   }
7460b57cec5SDimitry Andric 
7470b57cec5SDimitry Andric   // Update RegUnits to reflect live registers after UseMI.
7480b57cec5SDimitry Andric   // First kills.
749e8d8bef9SDimitry Andric   for (MCRegister Kill : Kills)
75006c3fb27SDimitry Andric     for (MCRegUnit Unit : TRI->regunits(Kill))
75106c3fb27SDimitry Andric       RegUnits.erase(Unit);
7520b57cec5SDimitry Andric 
7530b57cec5SDimitry Andric   // Second, live defs.
7540b57cec5SDimitry Andric   for (unsigned DefOp : LiveDefOps) {
75506c3fb27SDimitry Andric     for (MCRegUnit Unit :
75606c3fb27SDimitry Andric          TRI->regunits(UseMI->getOperand(DefOp).getReg().asMCReg())) {
75706c3fb27SDimitry Andric       LiveRegUnit &LRU = RegUnits[Unit];
7580b57cec5SDimitry Andric       LRU.MI = UseMI;
7590b57cec5SDimitry Andric       LRU.Op = DefOp;
7600b57cec5SDimitry Andric     }
7610b57cec5SDimitry Andric   }
7620b57cec5SDimitry Andric }
7630b57cec5SDimitry Andric 
7640b57cec5SDimitry Andric /// The length of the critical path through a trace is the maximum of two path
7650b57cec5SDimitry Andric /// lengths:
7660b57cec5SDimitry Andric ///
7670b57cec5SDimitry Andric /// 1. The maximum height+depth over all instructions in the trace center block.
7680b57cec5SDimitry Andric ///
7690b57cec5SDimitry Andric /// 2. The longest cross-block dependency chain. For small blocks, it is
7700b57cec5SDimitry Andric ///    possible that the critical path through the trace doesn't include any
7710b57cec5SDimitry Andric ///    instructions in the block.
7720b57cec5SDimitry Andric ///
7730b57cec5SDimitry Andric /// This function computes the second number from the live-in list of the
7740b57cec5SDimitry Andric /// center block.
7750b57cec5SDimitry Andric unsigned MachineTraceMetrics::Ensemble::
7760b57cec5SDimitry Andric computeCrossBlockCriticalPath(const TraceBlockInfo &TBI) {
7770b57cec5SDimitry Andric   assert(TBI.HasValidInstrDepths && "Missing depth info");
7780b57cec5SDimitry Andric   assert(TBI.HasValidInstrHeights && "Missing height info");
7790b57cec5SDimitry Andric   unsigned MaxLen = 0;
7800b57cec5SDimitry Andric   for (const LiveInReg &LIR : TBI.LiveIns) {
781e8d8bef9SDimitry Andric     if (!LIR.Reg.isVirtual())
7820b57cec5SDimitry Andric       continue;
7830b57cec5SDimitry Andric     const MachineInstr *DefMI = MTM.MRI->getVRegDef(LIR.Reg);
7840b57cec5SDimitry Andric     // Ignore dependencies outside the current trace.
7850b57cec5SDimitry Andric     const TraceBlockInfo &DefTBI = BlockInfo[DefMI->getParent()->getNumber()];
7860b57cec5SDimitry Andric     if (!DefTBI.isUsefulDominator(TBI))
7870b57cec5SDimitry Andric       continue;
7880b57cec5SDimitry Andric     unsigned Len = LIR.Height + Cycles[DefMI].Depth;
7890b57cec5SDimitry Andric     MaxLen = std::max(MaxLen, Len);
7900b57cec5SDimitry Andric   }
7910b57cec5SDimitry Andric   return MaxLen;
7920b57cec5SDimitry Andric }
7930b57cec5SDimitry Andric 
7940b57cec5SDimitry Andric void MachineTraceMetrics::Ensemble::
7950b57cec5SDimitry Andric updateDepth(MachineTraceMetrics::TraceBlockInfo &TBI, const MachineInstr &UseMI,
7960b57cec5SDimitry Andric             SparseSet<LiveRegUnit> &RegUnits) {
7970b57cec5SDimitry Andric   SmallVector<DataDep, 8> Deps;
7980b57cec5SDimitry Andric   // Collect all data dependencies.
7990b57cec5SDimitry Andric   if (UseMI.isPHI())
8000b57cec5SDimitry Andric     getPHIDeps(UseMI, Deps, TBI.Pred, MTM.MRI);
8010b57cec5SDimitry Andric   else if (getDataDeps(UseMI, Deps, MTM.MRI))
8020b57cec5SDimitry Andric     updatePhysDepsDownwards(&UseMI, Deps, RegUnits, MTM.TRI);
8030b57cec5SDimitry Andric 
8040b57cec5SDimitry Andric   // Filter and process dependencies, computing the earliest issue cycle.
8050b57cec5SDimitry Andric   unsigned Cycle = 0;
8060b57cec5SDimitry Andric   for (const DataDep &Dep : Deps) {
8070b57cec5SDimitry Andric     const TraceBlockInfo&DepTBI =
8080b57cec5SDimitry Andric       BlockInfo[Dep.DefMI->getParent()->getNumber()];
8090b57cec5SDimitry Andric     // Ignore dependencies from outside the current trace.
8100b57cec5SDimitry Andric     if (!DepTBI.isUsefulDominator(TBI))
8110b57cec5SDimitry Andric       continue;
8120b57cec5SDimitry Andric     assert(DepTBI.HasValidInstrDepths && "Inconsistent dependency");
8130b57cec5SDimitry Andric     unsigned DepCycle = Cycles.lookup(Dep.DefMI).Depth;
8140b57cec5SDimitry Andric     // Add latency if DefMI is a real instruction. Transients get latency 0.
8150b57cec5SDimitry Andric     if (!Dep.DefMI->isTransient())
8160b57cec5SDimitry Andric       DepCycle += MTM.SchedModel
8170b57cec5SDimitry Andric         .computeOperandLatency(Dep.DefMI, Dep.DefOp, &UseMI, Dep.UseOp);
8180b57cec5SDimitry Andric     Cycle = std::max(Cycle, DepCycle);
8190b57cec5SDimitry Andric   }
8200b57cec5SDimitry Andric   // Remember the instruction depth.
8210b57cec5SDimitry Andric   InstrCycles &MICycles = Cycles[&UseMI];
8220b57cec5SDimitry Andric   MICycles.Depth = Cycle;
8230b57cec5SDimitry Andric 
8240b57cec5SDimitry Andric   if (TBI.HasValidInstrHeights) {
8250b57cec5SDimitry Andric     // Update critical path length.
8260b57cec5SDimitry Andric     TBI.CriticalPath = std::max(TBI.CriticalPath, Cycle + MICycles.Height);
8270b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << TBI.CriticalPath << '\t' << Cycle << '\t' << UseMI);
8280b57cec5SDimitry Andric   } else {
8290b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << Cycle << '\t' << UseMI);
8300b57cec5SDimitry Andric   }
8310b57cec5SDimitry Andric }
8320b57cec5SDimitry Andric 
8330b57cec5SDimitry Andric void MachineTraceMetrics::Ensemble::
8340b57cec5SDimitry Andric updateDepth(const MachineBasicBlock *MBB, const MachineInstr &UseMI,
8350b57cec5SDimitry Andric             SparseSet<LiveRegUnit> &RegUnits) {
8360b57cec5SDimitry Andric   updateDepth(BlockInfo[MBB->getNumber()], UseMI, RegUnits);
8370b57cec5SDimitry Andric }
8380b57cec5SDimitry Andric 
8390b57cec5SDimitry Andric void MachineTraceMetrics::Ensemble::
8400b57cec5SDimitry Andric updateDepths(MachineBasicBlock::iterator Start,
8410b57cec5SDimitry Andric              MachineBasicBlock::iterator End,
8420b57cec5SDimitry Andric              SparseSet<LiveRegUnit> &RegUnits) {
8430b57cec5SDimitry Andric     for (; Start != End; Start++)
8440b57cec5SDimitry Andric       updateDepth(Start->getParent(), *Start, RegUnits);
8450b57cec5SDimitry Andric }
8460b57cec5SDimitry Andric 
8470b57cec5SDimitry Andric /// Compute instruction depths for all instructions above or in MBB in its
8480b57cec5SDimitry Andric /// trace. This assumes that the trace through MBB has already been computed.
8490b57cec5SDimitry Andric void MachineTraceMetrics::Ensemble::
8500b57cec5SDimitry Andric computeInstrDepths(const MachineBasicBlock *MBB) {
8510b57cec5SDimitry Andric   // The top of the trace may already be computed, and HasValidInstrDepths
8520b57cec5SDimitry Andric   // implies Head->HasValidInstrDepths, so we only need to start from the first
8530b57cec5SDimitry Andric   // block in the trace that needs to be recomputed.
8540b57cec5SDimitry Andric   SmallVector<const MachineBasicBlock*, 8> Stack;
8550b57cec5SDimitry Andric   do {
8560b57cec5SDimitry Andric     TraceBlockInfo &TBI = BlockInfo[MBB->getNumber()];
8570b57cec5SDimitry Andric     assert(TBI.hasValidDepth() && "Incomplete trace");
8580b57cec5SDimitry Andric     if (TBI.HasValidInstrDepths)
8590b57cec5SDimitry Andric       break;
8600b57cec5SDimitry Andric     Stack.push_back(MBB);
8610b57cec5SDimitry Andric     MBB = TBI.Pred;
8620b57cec5SDimitry Andric   } while (MBB);
8630b57cec5SDimitry Andric 
8640b57cec5SDimitry Andric   // FIXME: If MBB is non-null at this point, it is the last pre-computed block
8650b57cec5SDimitry Andric   // in the trace. We should track any live-out physregs that were defined in
8660b57cec5SDimitry Andric   // the trace. This is quite rare in SSA form, typically created by CSE
8670b57cec5SDimitry Andric   // hoisting a compare.
8680b57cec5SDimitry Andric   SparseSet<LiveRegUnit> RegUnits;
8690b57cec5SDimitry Andric   RegUnits.setUniverse(MTM.TRI->getNumRegUnits());
8700b57cec5SDimitry Andric 
8710b57cec5SDimitry Andric   // Go through trace blocks in top-down order, stopping after the center block.
8720b57cec5SDimitry Andric   while (!Stack.empty()) {
8730b57cec5SDimitry Andric     MBB = Stack.pop_back_val();
8740b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "\nDepths for " << printMBBReference(*MBB) << ":\n");
8750b57cec5SDimitry Andric     TraceBlockInfo &TBI = BlockInfo[MBB->getNumber()];
8760b57cec5SDimitry Andric     TBI.HasValidInstrDepths = true;
8770b57cec5SDimitry Andric     TBI.CriticalPath = 0;
8780b57cec5SDimitry Andric 
8790b57cec5SDimitry Andric     // Print out resource depths here as well.
8800b57cec5SDimitry Andric     LLVM_DEBUG({
8810b57cec5SDimitry Andric       dbgs() << format("%7u Instructions\n", TBI.InstrDepth);
8820b57cec5SDimitry Andric       ArrayRef<unsigned> PRDepths = getProcResourceDepths(MBB->getNumber());
8830b57cec5SDimitry Andric       for (unsigned K = 0; K != PRDepths.size(); ++K)
8840b57cec5SDimitry Andric         if (PRDepths[K]) {
8850b57cec5SDimitry Andric           unsigned Factor = MTM.SchedModel.getResourceFactor(K);
8860b57cec5SDimitry Andric           dbgs() << format("%6uc @ ", MTM.getCycles(PRDepths[K]))
8870b57cec5SDimitry Andric                  << MTM.SchedModel.getProcResource(K)->Name << " ("
8880b57cec5SDimitry Andric                  << PRDepths[K]/Factor << " ops x" << Factor << ")\n";
8890b57cec5SDimitry Andric         }
8900b57cec5SDimitry Andric     });
8910b57cec5SDimitry Andric 
8920b57cec5SDimitry Andric     // Also compute the critical path length through MBB when possible.
8930b57cec5SDimitry Andric     if (TBI.HasValidInstrHeights)
8940b57cec5SDimitry Andric       TBI.CriticalPath = computeCrossBlockCriticalPath(TBI);
8950b57cec5SDimitry Andric 
8960b57cec5SDimitry Andric     for (const auto &UseMI : *MBB) {
8970b57cec5SDimitry Andric       updateDepth(TBI, UseMI, RegUnits);
8980b57cec5SDimitry Andric     }
8990b57cec5SDimitry Andric   }
9000b57cec5SDimitry Andric }
9010b57cec5SDimitry Andric 
9020b57cec5SDimitry Andric // Identify physreg dependencies for MI when scanning instructions upwards.
9030b57cec5SDimitry Andric // Return the issue height of MI after considering any live regunits.
9040b57cec5SDimitry Andric // Height is the issue height computed from virtual register dependencies alone.
9050b57cec5SDimitry Andric static unsigned updatePhysDepsUpwards(const MachineInstr &MI, unsigned Height,
9060b57cec5SDimitry Andric                                       SparseSet<LiveRegUnit> &RegUnits,
9070b57cec5SDimitry Andric                                       const TargetSchedModel &SchedModel,
9080b57cec5SDimitry Andric                                       const TargetInstrInfo *TII,
9090b57cec5SDimitry Andric                                       const TargetRegisterInfo *TRI) {
9100b57cec5SDimitry Andric   SmallVector<unsigned, 8> ReadOps;
9110b57cec5SDimitry Andric 
91206c3fb27SDimitry Andric   for (const MachineOperand &MO : MI.operands()) {
9130b57cec5SDimitry Andric     if (!MO.isReg())
9140b57cec5SDimitry Andric       continue;
9158bcb0991SDimitry Andric     Register Reg = MO.getReg();
916bdd1243dSDimitry Andric     if (!Reg.isPhysical())
9170b57cec5SDimitry Andric       continue;
9180b57cec5SDimitry Andric     if (MO.readsReg())
91906c3fb27SDimitry Andric       ReadOps.push_back(MO.getOperandNo());
9200b57cec5SDimitry Andric     if (!MO.isDef())
9210b57cec5SDimitry Andric       continue;
9220b57cec5SDimitry Andric     // This is a def of Reg. Remove corresponding entries from RegUnits, and
9230b57cec5SDimitry Andric     // update MI Height to consider the physreg dependencies.
92406c3fb27SDimitry Andric     for (MCRegUnit Unit : TRI->regunits(Reg.asMCReg())) {
92506c3fb27SDimitry Andric       SparseSet<LiveRegUnit>::iterator I = RegUnits.find(Unit);
9260b57cec5SDimitry Andric       if (I == RegUnits.end())
9270b57cec5SDimitry Andric         continue;
9280b57cec5SDimitry Andric       unsigned DepHeight = I->Cycle;
9290b57cec5SDimitry Andric       if (!MI.isTransient()) {
9300b57cec5SDimitry Andric         // We may not know the UseMI of this dependency, if it came from the
9310b57cec5SDimitry Andric         // live-in list. SchedModel can handle a NULL UseMI.
93206c3fb27SDimitry Andric         DepHeight += SchedModel.computeOperandLatency(&MI, MO.getOperandNo(),
9330b57cec5SDimitry Andric                                                       I->MI, I->Op);
9340b57cec5SDimitry Andric       }
9350b57cec5SDimitry Andric       Height = std::max(Height, DepHeight);
9360b57cec5SDimitry Andric       // This regunit is dead above MI.
9370b57cec5SDimitry Andric       RegUnits.erase(I);
9380b57cec5SDimitry Andric     }
9390b57cec5SDimitry Andric   }
9400b57cec5SDimitry Andric 
9410b57cec5SDimitry Andric   // Now we know the height of MI. Update any regunits read.
942*0fca6ea1SDimitry Andric   for (unsigned Op : ReadOps) {
943*0fca6ea1SDimitry Andric     MCRegister Reg = MI.getOperand(Op).getReg().asMCReg();
94406c3fb27SDimitry Andric     for (MCRegUnit Unit : TRI->regunits(Reg)) {
94506c3fb27SDimitry Andric       LiveRegUnit &LRU = RegUnits[Unit];
9460b57cec5SDimitry Andric       // Set the height to the highest reader of the unit.
9470b57cec5SDimitry Andric       if (LRU.Cycle <= Height && LRU.MI != &MI) {
9480b57cec5SDimitry Andric         LRU.Cycle = Height;
9490b57cec5SDimitry Andric         LRU.MI = &MI;
950*0fca6ea1SDimitry Andric         LRU.Op = Op;
9510b57cec5SDimitry Andric       }
9520b57cec5SDimitry Andric     }
9530b57cec5SDimitry Andric   }
9540b57cec5SDimitry Andric 
9550b57cec5SDimitry Andric   return Height;
9560b57cec5SDimitry Andric }
9570b57cec5SDimitry Andric 
9580b57cec5SDimitry Andric using MIHeightMap = DenseMap<const MachineInstr *, unsigned>;
9590b57cec5SDimitry Andric 
9600b57cec5SDimitry Andric // Push the height of DefMI upwards if required to match UseMI.
9610b57cec5SDimitry Andric // Return true if this is the first time DefMI was seen.
9620b57cec5SDimitry Andric static bool pushDepHeight(const DataDep &Dep, const MachineInstr &UseMI,
9630b57cec5SDimitry Andric                           unsigned UseHeight, MIHeightMap &Heights,
9640b57cec5SDimitry Andric                           const TargetSchedModel &SchedModel,
9650b57cec5SDimitry Andric                           const TargetInstrInfo *TII) {
9660b57cec5SDimitry Andric   // Adjust height by Dep.DefMI latency.
9670b57cec5SDimitry Andric   if (!Dep.DefMI->isTransient())
9680b57cec5SDimitry Andric     UseHeight += SchedModel.computeOperandLatency(Dep.DefMI, Dep.DefOp, &UseMI,
9690b57cec5SDimitry Andric                                                   Dep.UseOp);
9700b57cec5SDimitry Andric 
9710b57cec5SDimitry Andric   // Update Heights[DefMI] to be the maximum height seen.
9720b57cec5SDimitry Andric   MIHeightMap::iterator I;
9730b57cec5SDimitry Andric   bool New;
9740b57cec5SDimitry Andric   std::tie(I, New) = Heights.insert(std::make_pair(Dep.DefMI, UseHeight));
9750b57cec5SDimitry Andric   if (New)
9760b57cec5SDimitry Andric     return true;
9770b57cec5SDimitry Andric 
9780b57cec5SDimitry Andric   // DefMI has been pushed before. Give it the max height.
9790b57cec5SDimitry Andric   if (I->second < UseHeight)
9800b57cec5SDimitry Andric     I->second = UseHeight;
9810b57cec5SDimitry Andric   return false;
9820b57cec5SDimitry Andric }
9830b57cec5SDimitry Andric 
9840b57cec5SDimitry Andric /// Assuming that the virtual register defined by DefMI:DefOp was used by
9850b57cec5SDimitry Andric /// Trace.back(), add it to the live-in lists of all the blocks in Trace. Stop
9860b57cec5SDimitry Andric /// when reaching the block that contains DefMI.
9870b57cec5SDimitry Andric void MachineTraceMetrics::Ensemble::
9880b57cec5SDimitry Andric addLiveIns(const MachineInstr *DefMI, unsigned DefOp,
9890b57cec5SDimitry Andric            ArrayRef<const MachineBasicBlock*> Trace) {
9900b57cec5SDimitry Andric   assert(!Trace.empty() && "Trace should contain at least one block");
991e8d8bef9SDimitry Andric   Register Reg = DefMI->getOperand(DefOp).getReg();
992bdd1243dSDimitry Andric   assert(Reg.isVirtual());
9930b57cec5SDimitry Andric   const MachineBasicBlock *DefMBB = DefMI->getParent();
9940b57cec5SDimitry Andric 
9950b57cec5SDimitry Andric   // Reg is live-in to all blocks in Trace that follow DefMBB.
9960eae32dcSDimitry Andric   for (const MachineBasicBlock *MBB : llvm::reverse(Trace)) {
9970b57cec5SDimitry Andric     if (MBB == DefMBB)
9980b57cec5SDimitry Andric       return;
9990b57cec5SDimitry Andric     TraceBlockInfo &TBI = BlockInfo[MBB->getNumber()];
10000b57cec5SDimitry Andric     // Just add the register. The height will be updated later.
10010b57cec5SDimitry Andric     TBI.LiveIns.push_back(Reg);
10020b57cec5SDimitry Andric   }
10030b57cec5SDimitry Andric }
10040b57cec5SDimitry Andric 
10050b57cec5SDimitry Andric /// Compute instruction heights in the trace through MBB. This updates MBB and
10060b57cec5SDimitry Andric /// the blocks below it in the trace. It is assumed that the trace has already
10070b57cec5SDimitry Andric /// been computed.
10080b57cec5SDimitry Andric void MachineTraceMetrics::Ensemble::
10090b57cec5SDimitry Andric computeInstrHeights(const MachineBasicBlock *MBB) {
10100b57cec5SDimitry Andric   // The bottom of the trace may already be computed.
10110b57cec5SDimitry Andric   // Find the blocks that need updating.
10120b57cec5SDimitry Andric   SmallVector<const MachineBasicBlock*, 8> Stack;
10130b57cec5SDimitry Andric   do {
10140b57cec5SDimitry Andric     TraceBlockInfo &TBI = BlockInfo[MBB->getNumber()];
10150b57cec5SDimitry Andric     assert(TBI.hasValidHeight() && "Incomplete trace");
10160b57cec5SDimitry Andric     if (TBI.HasValidInstrHeights)
10170b57cec5SDimitry Andric       break;
10180b57cec5SDimitry Andric     Stack.push_back(MBB);
10190b57cec5SDimitry Andric     TBI.LiveIns.clear();
10200b57cec5SDimitry Andric     MBB = TBI.Succ;
10210b57cec5SDimitry Andric   } while (MBB);
10220b57cec5SDimitry Andric 
10230b57cec5SDimitry Andric   // As we move upwards in the trace, keep track of instructions that are
10240b57cec5SDimitry Andric   // required by deeper trace instructions. Map MI -> height required so far.
10250b57cec5SDimitry Andric   MIHeightMap Heights;
10260b57cec5SDimitry Andric 
10270b57cec5SDimitry Andric   // For physregs, the def isn't known when we see the use.
10280b57cec5SDimitry Andric   // Instead, keep track of the highest use of each regunit.
10290b57cec5SDimitry Andric   SparseSet<LiveRegUnit> RegUnits;
10300b57cec5SDimitry Andric   RegUnits.setUniverse(MTM.TRI->getNumRegUnits());
10310b57cec5SDimitry Andric 
10320b57cec5SDimitry Andric   // If the bottom of the trace was already precomputed, initialize heights
10330b57cec5SDimitry Andric   // from its live-in list.
10340b57cec5SDimitry Andric   // MBB is the highest precomputed block in the trace.
10350b57cec5SDimitry Andric   if (MBB) {
10360b57cec5SDimitry Andric     TraceBlockInfo &TBI = BlockInfo[MBB->getNumber()];
10370b57cec5SDimitry Andric     for (LiveInReg &LI : TBI.LiveIns) {
1038e8d8bef9SDimitry Andric       if (LI.Reg.isVirtual()) {
10390b57cec5SDimitry Andric         // For virtual registers, the def latency is included.
10400b57cec5SDimitry Andric         unsigned &Height = Heights[MTM.MRI->getVRegDef(LI.Reg)];
10410b57cec5SDimitry Andric         if (Height < LI.Height)
10420b57cec5SDimitry Andric           Height = LI.Height;
10430b57cec5SDimitry Andric       } else {
10440b57cec5SDimitry Andric         // For register units, the def latency is not included because we don't
10450b57cec5SDimitry Andric         // know the def yet.
10460b57cec5SDimitry Andric         RegUnits[LI.Reg].Cycle = LI.Height;
10470b57cec5SDimitry Andric       }
10480b57cec5SDimitry Andric     }
10490b57cec5SDimitry Andric   }
10500b57cec5SDimitry Andric 
10510b57cec5SDimitry Andric   // Go through the trace blocks in bottom-up order.
10520b57cec5SDimitry Andric   SmallVector<DataDep, 8> Deps;
10530b57cec5SDimitry Andric   for (;!Stack.empty(); Stack.pop_back()) {
10540b57cec5SDimitry Andric     MBB = Stack.back();
10550b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "Heights for " << printMBBReference(*MBB) << ":\n");
10560b57cec5SDimitry Andric     TraceBlockInfo &TBI = BlockInfo[MBB->getNumber()];
10570b57cec5SDimitry Andric     TBI.HasValidInstrHeights = true;
10580b57cec5SDimitry Andric     TBI.CriticalPath = 0;
10590b57cec5SDimitry Andric 
10600b57cec5SDimitry Andric     LLVM_DEBUG({
10610b57cec5SDimitry Andric       dbgs() << format("%7u Instructions\n", TBI.InstrHeight);
10620b57cec5SDimitry Andric       ArrayRef<unsigned> PRHeights = getProcResourceHeights(MBB->getNumber());
10630b57cec5SDimitry Andric       for (unsigned K = 0; K != PRHeights.size(); ++K)
10640b57cec5SDimitry Andric         if (PRHeights[K]) {
10650b57cec5SDimitry Andric           unsigned Factor = MTM.SchedModel.getResourceFactor(K);
10660b57cec5SDimitry Andric           dbgs() << format("%6uc @ ", MTM.getCycles(PRHeights[K]))
10670b57cec5SDimitry Andric                  << MTM.SchedModel.getProcResource(K)->Name << " ("
10680b57cec5SDimitry Andric                  << PRHeights[K]/Factor << " ops x" << Factor << ")\n";
10690b57cec5SDimitry Andric         }
10700b57cec5SDimitry Andric     });
10710b57cec5SDimitry Andric 
10720b57cec5SDimitry Andric     // Get dependencies from PHIs in the trace successor.
10730b57cec5SDimitry Andric     const MachineBasicBlock *Succ = TBI.Succ;
10740b57cec5SDimitry Andric     // If MBB is the last block in the trace, and it has a back-edge to the
10750b57cec5SDimitry Andric     // loop header, get loop-carried dependencies from PHIs in the header. For
10760b57cec5SDimitry Andric     // that purpose, pretend that all the loop header PHIs have height 0.
10770b57cec5SDimitry Andric     if (!Succ)
10780b57cec5SDimitry Andric       if (const MachineLoop *Loop = getLoopFor(MBB))
10790b57cec5SDimitry Andric         if (MBB->isSuccessor(Loop->getHeader()))
10800b57cec5SDimitry Andric           Succ = Loop->getHeader();
10810b57cec5SDimitry Andric 
10820b57cec5SDimitry Andric     if (Succ) {
10830b57cec5SDimitry Andric       for (const auto &PHI : *Succ) {
10840b57cec5SDimitry Andric         if (!PHI.isPHI())
10850b57cec5SDimitry Andric           break;
10860b57cec5SDimitry Andric         Deps.clear();
10870b57cec5SDimitry Andric         getPHIDeps(PHI, Deps, MBB, MTM.MRI);
10880b57cec5SDimitry Andric         if (!Deps.empty()) {
10890b57cec5SDimitry Andric           // Loop header PHI heights are all 0.
10900b57cec5SDimitry Andric           unsigned Height = TBI.Succ ? Cycles.lookup(&PHI).Height : 0;
10910b57cec5SDimitry Andric           LLVM_DEBUG(dbgs() << "pred\t" << Height << '\t' << PHI);
10920b57cec5SDimitry Andric           if (pushDepHeight(Deps.front(), PHI, Height, Heights, MTM.SchedModel,
10930b57cec5SDimitry Andric                             MTM.TII))
10940b57cec5SDimitry Andric             addLiveIns(Deps.front().DefMI, Deps.front().DefOp, Stack);
10950b57cec5SDimitry Andric         }
10960b57cec5SDimitry Andric       }
10970b57cec5SDimitry Andric     }
10980b57cec5SDimitry Andric 
10990b57cec5SDimitry Andric     // Go through the block backwards.
110006c3fb27SDimitry Andric     for (const MachineInstr &MI : reverse(*MBB)) {
11010b57cec5SDimitry Andric       // Find the MI height as determined by virtual register uses in the
11020b57cec5SDimitry Andric       // trace below.
11030b57cec5SDimitry Andric       unsigned Cycle = 0;
11040b57cec5SDimitry Andric       MIHeightMap::iterator HeightI = Heights.find(&MI);
11050b57cec5SDimitry Andric       if (HeightI != Heights.end()) {
11060b57cec5SDimitry Andric         Cycle = HeightI->second;
11070b57cec5SDimitry Andric         // We won't be seeing any more MI uses.
11080b57cec5SDimitry Andric         Heights.erase(HeightI);
11090b57cec5SDimitry Andric       }
11100b57cec5SDimitry Andric 
11110b57cec5SDimitry Andric       // Don't process PHI deps. They depend on the specific predecessor, and
11120b57cec5SDimitry Andric       // we'll get them when visiting the predecessor.
11130b57cec5SDimitry Andric       Deps.clear();
11140b57cec5SDimitry Andric       bool HasPhysRegs = !MI.isPHI() && getDataDeps(MI, Deps, MTM.MRI);
11150b57cec5SDimitry Andric 
11160b57cec5SDimitry Andric       // There may also be regunit dependencies to include in the height.
11170b57cec5SDimitry Andric       if (HasPhysRegs)
11180b57cec5SDimitry Andric         Cycle = updatePhysDepsUpwards(MI, Cycle, RegUnits, MTM.SchedModel,
11190b57cec5SDimitry Andric                                       MTM.TII, MTM.TRI);
11200b57cec5SDimitry Andric 
11210b57cec5SDimitry Andric       // Update the required height of any virtual registers read by MI.
11220b57cec5SDimitry Andric       for (const DataDep &Dep : Deps)
11230b57cec5SDimitry Andric         if (pushDepHeight(Dep, MI, Cycle, Heights, MTM.SchedModel, MTM.TII))
11240b57cec5SDimitry Andric           addLiveIns(Dep.DefMI, Dep.DefOp, Stack);
11250b57cec5SDimitry Andric 
11260b57cec5SDimitry Andric       InstrCycles &MICycles = Cycles[&MI];
11270b57cec5SDimitry Andric       MICycles.Height = Cycle;
11280b57cec5SDimitry Andric       if (!TBI.HasValidInstrDepths) {
11290b57cec5SDimitry Andric         LLVM_DEBUG(dbgs() << Cycle << '\t' << MI);
11300b57cec5SDimitry Andric         continue;
11310b57cec5SDimitry Andric       }
11320b57cec5SDimitry Andric       // Update critical path length.
11330b57cec5SDimitry Andric       TBI.CriticalPath = std::max(TBI.CriticalPath, Cycle + MICycles.Depth);
11340b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << TBI.CriticalPath << '\t' << Cycle << '\t' << MI);
11350b57cec5SDimitry Andric     }
11360b57cec5SDimitry Andric 
11370b57cec5SDimitry Andric     // Update virtual live-in heights. They were added by addLiveIns() with a 0
11380b57cec5SDimitry Andric     // height because the final height isn't known until now.
11390b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << printMBBReference(*MBB) << " Live-ins:");
11400b57cec5SDimitry Andric     for (LiveInReg &LIR : TBI.LiveIns) {
11410b57cec5SDimitry Andric       const MachineInstr *DefMI = MTM.MRI->getVRegDef(LIR.Reg);
11420b57cec5SDimitry Andric       LIR.Height = Heights.lookup(DefMI);
11430b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << ' ' << printReg(LIR.Reg) << '@' << LIR.Height);
11440b57cec5SDimitry Andric     }
11450b57cec5SDimitry Andric 
11460b57cec5SDimitry Andric     // Transfer the live regunits to the live-in list.
114706c3fb27SDimitry Andric     for (const LiveRegUnit &RU : RegUnits) {
114806c3fb27SDimitry Andric       TBI.LiveIns.push_back(LiveInReg(RU.RegUnit, RU.Cycle));
114906c3fb27SDimitry Andric       LLVM_DEBUG(dbgs() << ' ' << printRegUnit(RU.RegUnit, MTM.TRI) << '@'
115006c3fb27SDimitry Andric                         << RU.Cycle);
11510b57cec5SDimitry Andric     }
11520b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << '\n');
11530b57cec5SDimitry Andric 
11540b57cec5SDimitry Andric     if (!TBI.HasValidInstrDepths)
11550b57cec5SDimitry Andric       continue;
11560b57cec5SDimitry Andric     // Add live-ins to the critical path length.
11570b57cec5SDimitry Andric     TBI.CriticalPath = std::max(TBI.CriticalPath,
11580b57cec5SDimitry Andric                                 computeCrossBlockCriticalPath(TBI));
11590b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "Critical path: " << TBI.CriticalPath << '\n');
11600b57cec5SDimitry Andric   }
11610b57cec5SDimitry Andric }
11620b57cec5SDimitry Andric 
11630b57cec5SDimitry Andric MachineTraceMetrics::Trace
11640b57cec5SDimitry Andric MachineTraceMetrics::Ensemble::getTrace(const MachineBasicBlock *MBB) {
11650b57cec5SDimitry Andric   TraceBlockInfo &TBI = BlockInfo[MBB->getNumber()];
11660b57cec5SDimitry Andric 
11670b57cec5SDimitry Andric   if (!TBI.hasValidDepth() || !TBI.hasValidHeight())
11680b57cec5SDimitry Andric     computeTrace(MBB);
11690b57cec5SDimitry Andric   if (!TBI.HasValidInstrDepths)
11700b57cec5SDimitry Andric     computeInstrDepths(MBB);
11710b57cec5SDimitry Andric   if (!TBI.HasValidInstrHeights)
11720b57cec5SDimitry Andric     computeInstrHeights(MBB);
11730b57cec5SDimitry Andric 
11740b57cec5SDimitry Andric   return Trace(*this, TBI);
11750b57cec5SDimitry Andric }
11760b57cec5SDimitry Andric 
11770b57cec5SDimitry Andric unsigned
11780b57cec5SDimitry Andric MachineTraceMetrics::Trace::getInstrSlack(const MachineInstr &MI) const {
11790b57cec5SDimitry Andric   assert(getBlockNum() == unsigned(MI.getParent()->getNumber()) &&
11800b57cec5SDimitry Andric          "MI must be in the trace center block");
11810b57cec5SDimitry Andric   InstrCycles Cyc = getInstrCycles(MI);
11820b57cec5SDimitry Andric   return getCriticalPath() - (Cyc.Depth + Cyc.Height);
11830b57cec5SDimitry Andric }
11840b57cec5SDimitry Andric 
11850b57cec5SDimitry Andric unsigned
11860b57cec5SDimitry Andric MachineTraceMetrics::Trace::getPHIDepth(const MachineInstr &PHI) const {
11870b57cec5SDimitry Andric   const MachineBasicBlock *MBB = TE.MTM.MF->getBlockNumbered(getBlockNum());
11880b57cec5SDimitry Andric   SmallVector<DataDep, 1> Deps;
11890b57cec5SDimitry Andric   getPHIDeps(PHI, Deps, MBB, TE.MTM.MRI);
11900b57cec5SDimitry Andric   assert(Deps.size() == 1 && "PHI doesn't have MBB as a predecessor");
11910b57cec5SDimitry Andric   DataDep &Dep = Deps.front();
11920b57cec5SDimitry Andric   unsigned DepCycle = getInstrCycles(*Dep.DefMI).Depth;
11930b57cec5SDimitry Andric   // Add latency if DefMI is a real instruction. Transients get latency 0.
11940b57cec5SDimitry Andric   if (!Dep.DefMI->isTransient())
11950b57cec5SDimitry Andric     DepCycle += TE.MTM.SchedModel.computeOperandLatency(Dep.DefMI, Dep.DefOp,
11960b57cec5SDimitry Andric                                                         &PHI, Dep.UseOp);
11970b57cec5SDimitry Andric   return DepCycle;
11980b57cec5SDimitry Andric }
11990b57cec5SDimitry Andric 
12000b57cec5SDimitry Andric /// When bottom is set include instructions in current block in estimate.
12010b57cec5SDimitry Andric unsigned MachineTraceMetrics::Trace::getResourceDepth(bool Bottom) const {
12020b57cec5SDimitry Andric   // Find the limiting processor resource.
12030b57cec5SDimitry Andric   // Numbers have been pre-scaled to be comparable.
12040b57cec5SDimitry Andric   unsigned PRMax = 0;
12050b57cec5SDimitry Andric   ArrayRef<unsigned> PRDepths = TE.getProcResourceDepths(getBlockNum());
12060b57cec5SDimitry Andric   if (Bottom) {
12075f757f3fSDimitry Andric     ArrayRef<unsigned> PRCycles = TE.MTM.getProcReleaseAtCycles(getBlockNum());
12080b57cec5SDimitry Andric     for (unsigned K = 0; K != PRDepths.size(); ++K)
12090b57cec5SDimitry Andric       PRMax = std::max(PRMax, PRDepths[K] + PRCycles[K]);
12100b57cec5SDimitry Andric   } else {
12110eae32dcSDimitry Andric     for (unsigned PRD : PRDepths)
12120eae32dcSDimitry Andric       PRMax = std::max(PRMax, PRD);
12130b57cec5SDimitry Andric   }
12140b57cec5SDimitry Andric   // Convert to cycle count.
12150b57cec5SDimitry Andric   PRMax = TE.MTM.getCycles(PRMax);
12160b57cec5SDimitry Andric 
12170b57cec5SDimitry Andric   /// All instructions before current block
12180b57cec5SDimitry Andric   unsigned Instrs = TBI.InstrDepth;
12190b57cec5SDimitry Andric   // plus instructions in current block
12200b57cec5SDimitry Andric   if (Bottom)
12210b57cec5SDimitry Andric     Instrs += TE.MTM.BlockInfo[getBlockNum()].InstrCount;
12220b57cec5SDimitry Andric   if (unsigned IW = TE.MTM.SchedModel.getIssueWidth())
12230b57cec5SDimitry Andric     Instrs /= IW;
12240b57cec5SDimitry Andric   // Assume issue width 1 without a schedule model.
12250b57cec5SDimitry Andric   return std::max(Instrs, PRMax);
12260b57cec5SDimitry Andric }
12270b57cec5SDimitry Andric 
12280b57cec5SDimitry Andric unsigned MachineTraceMetrics::Trace::getResourceLength(
12290b57cec5SDimitry Andric     ArrayRef<const MachineBasicBlock *> Extrablocks,
12300b57cec5SDimitry Andric     ArrayRef<const MCSchedClassDesc *> ExtraInstrs,
12310b57cec5SDimitry Andric     ArrayRef<const MCSchedClassDesc *> RemoveInstrs) const {
12320b57cec5SDimitry Andric   // Add up resources above and below the center block.
12330b57cec5SDimitry Andric   ArrayRef<unsigned> PRDepths = TE.getProcResourceDepths(getBlockNum());
12340b57cec5SDimitry Andric   ArrayRef<unsigned> PRHeights = TE.getProcResourceHeights(getBlockNum());
12350b57cec5SDimitry Andric   unsigned PRMax = 0;
12360b57cec5SDimitry Andric 
12370b57cec5SDimitry Andric   // Capture computing cycles from extra instructions
12380b57cec5SDimitry Andric   auto extraCycles = [this](ArrayRef<const MCSchedClassDesc *> Instrs,
12390b57cec5SDimitry Andric                             unsigned ResourceIdx)
12400b57cec5SDimitry Andric                          ->unsigned {
12410b57cec5SDimitry Andric     unsigned Cycles = 0;
12420b57cec5SDimitry Andric     for (const MCSchedClassDesc *SC : Instrs) {
12430b57cec5SDimitry Andric       if (!SC->isValid())
12440b57cec5SDimitry Andric         continue;
12450b57cec5SDimitry Andric       for (TargetSchedModel::ProcResIter
12460b57cec5SDimitry Andric                PI = TE.MTM.SchedModel.getWriteProcResBegin(SC),
12470b57cec5SDimitry Andric                PE = TE.MTM.SchedModel.getWriteProcResEnd(SC);
12480b57cec5SDimitry Andric            PI != PE; ++PI) {
12490b57cec5SDimitry Andric         if (PI->ProcResourceIdx != ResourceIdx)
12500b57cec5SDimitry Andric           continue;
12515f757f3fSDimitry Andric         Cycles += (PI->ReleaseAtCycle *
12525f757f3fSDimitry Andric                    TE.MTM.SchedModel.getResourceFactor(ResourceIdx));
12530b57cec5SDimitry Andric       }
12540b57cec5SDimitry Andric     }
12550b57cec5SDimitry Andric     return Cycles;
12560b57cec5SDimitry Andric   };
12570b57cec5SDimitry Andric 
12580b57cec5SDimitry Andric   for (unsigned K = 0; K != PRDepths.size(); ++K) {
12590b57cec5SDimitry Andric     unsigned PRCycles = PRDepths[K] + PRHeights[K];
12600b57cec5SDimitry Andric     for (const MachineBasicBlock *MBB : Extrablocks)
12615f757f3fSDimitry Andric       PRCycles += TE.MTM.getProcReleaseAtCycles(MBB->getNumber())[K];
12620b57cec5SDimitry Andric     PRCycles += extraCycles(ExtraInstrs, K);
12630b57cec5SDimitry Andric     PRCycles -= extraCycles(RemoveInstrs, K);
12640b57cec5SDimitry Andric     PRMax = std::max(PRMax, PRCycles);
12650b57cec5SDimitry Andric   }
12660b57cec5SDimitry Andric   // Convert to cycle count.
12670b57cec5SDimitry Andric   PRMax = TE.MTM.getCycles(PRMax);
12680b57cec5SDimitry Andric 
12690b57cec5SDimitry Andric   // Instrs: #instructions in current trace outside current block.
12700b57cec5SDimitry Andric   unsigned Instrs = TBI.InstrDepth + TBI.InstrHeight;
12710b57cec5SDimitry Andric   // Add instruction count from the extra blocks.
12720b57cec5SDimitry Andric   for (const MachineBasicBlock *MBB : Extrablocks)
12730b57cec5SDimitry Andric     Instrs += TE.MTM.getResources(MBB)->InstrCount;
12740b57cec5SDimitry Andric   Instrs += ExtraInstrs.size();
12750b57cec5SDimitry Andric   Instrs -= RemoveInstrs.size();
12760b57cec5SDimitry Andric   if (unsigned IW = TE.MTM.SchedModel.getIssueWidth())
12770b57cec5SDimitry Andric     Instrs /= IW;
12780b57cec5SDimitry Andric   // Assume issue width 1 without a schedule model.
12790b57cec5SDimitry Andric   return std::max(Instrs, PRMax);
12800b57cec5SDimitry Andric }
12810b57cec5SDimitry Andric 
12820b57cec5SDimitry Andric bool MachineTraceMetrics::Trace::isDepInTrace(const MachineInstr &DefMI,
12830b57cec5SDimitry Andric                                               const MachineInstr &UseMI) const {
12840b57cec5SDimitry Andric   if (DefMI.getParent() == UseMI.getParent())
12850b57cec5SDimitry Andric     return true;
12860b57cec5SDimitry Andric 
12870b57cec5SDimitry Andric   const TraceBlockInfo &DepTBI = TE.BlockInfo[DefMI.getParent()->getNumber()];
12880b57cec5SDimitry Andric   const TraceBlockInfo &TBI = TE.BlockInfo[UseMI.getParent()->getNumber()];
12890b57cec5SDimitry Andric 
12900b57cec5SDimitry Andric   return DepTBI.isUsefulDominator(TBI);
12910b57cec5SDimitry Andric }
12920b57cec5SDimitry Andric 
12930b57cec5SDimitry Andric void MachineTraceMetrics::Ensemble::print(raw_ostream &OS) const {
12940b57cec5SDimitry Andric   OS << getName() << " ensemble:\n";
12950b57cec5SDimitry Andric   for (unsigned i = 0, e = BlockInfo.size(); i != e; ++i) {
12960b57cec5SDimitry Andric     OS << "  %bb." << i << '\t';
12970b57cec5SDimitry Andric     BlockInfo[i].print(OS);
12980b57cec5SDimitry Andric     OS << '\n';
12990b57cec5SDimitry Andric   }
13000b57cec5SDimitry Andric }
13010b57cec5SDimitry Andric 
13020b57cec5SDimitry Andric void MachineTraceMetrics::TraceBlockInfo::print(raw_ostream &OS) const {
13030b57cec5SDimitry Andric   if (hasValidDepth()) {
13040b57cec5SDimitry Andric     OS << "depth=" << InstrDepth;
13050b57cec5SDimitry Andric     if (Pred)
13060b57cec5SDimitry Andric       OS << " pred=" << printMBBReference(*Pred);
13070b57cec5SDimitry Andric     else
13080b57cec5SDimitry Andric       OS << " pred=null";
13090b57cec5SDimitry Andric     OS << " head=%bb." << Head;
13100b57cec5SDimitry Andric     if (HasValidInstrDepths)
13110b57cec5SDimitry Andric       OS << " +instrs";
13120b57cec5SDimitry Andric   } else
13130b57cec5SDimitry Andric     OS << "depth invalid";
13140b57cec5SDimitry Andric   OS << ", ";
13150b57cec5SDimitry Andric   if (hasValidHeight()) {
13160b57cec5SDimitry Andric     OS << "height=" << InstrHeight;
13170b57cec5SDimitry Andric     if (Succ)
13180b57cec5SDimitry Andric       OS << " succ=" << printMBBReference(*Succ);
13190b57cec5SDimitry Andric     else
13200b57cec5SDimitry Andric       OS << " succ=null";
13210b57cec5SDimitry Andric     OS << " tail=%bb." << Tail;
13220b57cec5SDimitry Andric     if (HasValidInstrHeights)
13230b57cec5SDimitry Andric       OS << " +instrs";
13240b57cec5SDimitry Andric   } else
13250b57cec5SDimitry Andric     OS << "height invalid";
13260b57cec5SDimitry Andric   if (HasValidInstrDepths && HasValidInstrHeights)
13270b57cec5SDimitry Andric     OS << ", crit=" << CriticalPath;
13280b57cec5SDimitry Andric }
13290b57cec5SDimitry Andric 
13300b57cec5SDimitry Andric void MachineTraceMetrics::Trace::print(raw_ostream &OS) const {
13310b57cec5SDimitry Andric   unsigned MBBNum = &TBI - &TE.BlockInfo[0];
13320b57cec5SDimitry Andric 
13330b57cec5SDimitry Andric   OS << TE.getName() << " trace %bb." << TBI.Head << " --> %bb." << MBBNum
13340b57cec5SDimitry Andric      << " --> %bb." << TBI.Tail << ':';
13350b57cec5SDimitry Andric   if (TBI.hasValidHeight() && TBI.hasValidDepth())
13360b57cec5SDimitry Andric     OS << ' ' << getInstrCount() << " instrs.";
13370b57cec5SDimitry Andric   if (TBI.HasValidInstrDepths && TBI.HasValidInstrHeights)
13380b57cec5SDimitry Andric     OS << ' ' << TBI.CriticalPath << " cycles.";
13390b57cec5SDimitry Andric 
13400b57cec5SDimitry Andric   const MachineTraceMetrics::TraceBlockInfo *Block = &TBI;
13410b57cec5SDimitry Andric   OS << "\n%bb." << MBBNum;
13420b57cec5SDimitry Andric   while (Block->hasValidDepth() && Block->Pred) {
13430b57cec5SDimitry Andric     unsigned Num = Block->Pred->getNumber();
13440b57cec5SDimitry Andric     OS << " <- " << printMBBReference(*Block->Pred);
13450b57cec5SDimitry Andric     Block = &TE.BlockInfo[Num];
13460b57cec5SDimitry Andric   }
13470b57cec5SDimitry Andric 
13480b57cec5SDimitry Andric   Block = &TBI;
13490b57cec5SDimitry Andric   OS << "\n    ";
13500b57cec5SDimitry Andric   while (Block->hasValidHeight() && Block->Succ) {
13510b57cec5SDimitry Andric     unsigned Num = Block->Succ->getNumber();
13520b57cec5SDimitry Andric     OS << " -> " << printMBBReference(*Block->Succ);
13530b57cec5SDimitry Andric     Block = &TE.BlockInfo[Num];
13540b57cec5SDimitry Andric   }
13550b57cec5SDimitry Andric   OS << '\n';
13560b57cec5SDimitry Andric }
1357