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