From 9f63e104271eb91e545fa8cdb16fb9e10a8a9578 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Thu, 26 Jul 2012 18:38:11 +0000 Subject: Start scaffolding for a MachineTraceMetrics analysis pass. This is still a work in progress. Out-of-order CPUs usually execute instructions from multiple basic blocks simultaneously, so it is necessary to look at longer traces when estimating the performance effects of code transformations. The MachineTraceMetrics analysis will pick a typical trace through a given basic block and provide performance metrics for the trace. Metrics will include: - Instruction count through the trace. - Issue count per functional unit. - Critical path length, and per-instruction 'slack'. These metrics can be used to determine the performance limiting factor when executing the trace, and how it will be affected by a code transformation. Initially, this will be used by the early if-conversion pass. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@160796 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MachineTraceMetrics.cpp | 477 ++++++++++++++++++++++++++++++++++++ 1 file changed, 477 insertions(+) create mode 100644 lib/CodeGen/MachineTraceMetrics.cpp (limited to 'lib/CodeGen/MachineTraceMetrics.cpp') diff --git a/lib/CodeGen/MachineTraceMetrics.cpp b/lib/CodeGen/MachineTraceMetrics.cpp new file mode 100644 index 0000000..b302101 --- /dev/null +++ b/lib/CodeGen/MachineTraceMetrics.cpp @@ -0,0 +1,477 @@ +//===- lib/CodeGen/MachineTraceMetrics.cpp ----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "early-ifcvt" +#include "MachineTraceMetrics.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineBranchProbabilityInfo.h" +#include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/PostOrderIterator.h" + +using namespace llvm; + +char MachineTraceMetrics::ID = 0; +char &llvm::MachineTraceMetricsID = MachineTraceMetrics::ID; + +INITIALIZE_PASS_BEGIN(MachineTraceMetrics, + "machine-trace-metrics", "Machine Trace Metrics", false, true) +INITIALIZE_PASS_DEPENDENCY(MachineBranchProbabilityInfo) +INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo) +INITIALIZE_PASS_END(MachineTraceMetrics, + "machine-trace-metrics", "Machine Trace Metrics", false, true) + +MachineTraceMetrics::MachineTraceMetrics() + : MachineFunctionPass(ID), TII(0), TRI(0), MRI(0), Loops(0) { + std::fill(Ensembles, array_endof(Ensembles), (Ensemble*)0); +} + +void MachineTraceMetrics::getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired(); + AU.addRequired(); + MachineFunctionPass::getAnalysisUsage(AU); +} + +bool MachineTraceMetrics::runOnMachineFunction(MachineFunction &MF) { + TII = MF.getTarget().getInstrInfo(); + TRI = MF.getTarget().getRegisterInfo(); + MRI = &MF.getRegInfo(); + Loops = &getAnalysis(); + unsigned NumBlocks = MF.getNumBlockIDs(); + BlockInfo.resize(NumBlocks); + return false; +} + +void MachineTraceMetrics::releaseMemory() { + BlockInfo.clear(); + for (unsigned i = 0; i != TS_NumStrategies; ++i) { + delete Ensembles[i]; + Ensembles[i] = 0; + } +} + +//===----------------------------------------------------------------------===// +// Fixed block information +//===----------------------------------------------------------------------===// +// +// The number of instructions in a basic block and the CPU resources used by +// those instructions don't depend on any given trace strategy. + +/// Is MI an instruction that should be considered free because it will likely +/// be eliminated by later passes? +static bool isFree(const MachineInstr *MI) { + switch(MI->getOpcode()) { + default: return false; + case TargetOpcode::PHI: + case TargetOpcode::PROLOG_LABEL: + case TargetOpcode::EH_LABEL: + case TargetOpcode::GC_LABEL: + case TargetOpcode::KILL: + case TargetOpcode::EXTRACT_SUBREG: + case TargetOpcode::INSERT_SUBREG: + case TargetOpcode::IMPLICIT_DEF: + case TargetOpcode::SUBREG_TO_REG: + case TargetOpcode::COPY_TO_REGCLASS: + case TargetOpcode::DBG_VALUE: + case TargetOpcode::REG_SEQUENCE: + case TargetOpcode::COPY: + return true; + } +} + +/// Compute the resource usage in basic block MBB. +const MachineTraceMetrics::FixedBlockInfo* +MachineTraceMetrics::getResources(const MachineBasicBlock *MBB) { + assert(MBB && "No basic block"); + FixedBlockInfo *FBI = &BlockInfo[MBB->getNumber()]; + if (FBI->hasResources()) + return FBI; + + // Compute resource usage in the block. + // FIXME: Compute per-functional unit counts. + FBI->HasCalls = false; + unsigned InstrCount = 0; + for (MachineBasicBlock::const_iterator I = MBB->begin(), E = MBB->end(); + I != E; ++I) { + const MachineInstr *MI = I; + if (isFree(MI)) + continue; + ++InstrCount; + if (MI->isCall()) + FBI->HasCalls = true; + } + FBI->InstrCount = InstrCount; + return FBI; +} + +//===----------------------------------------------------------------------===// +// Ensemble utility functions +//===----------------------------------------------------------------------===// + +MachineTraceMetrics::Ensemble::Ensemble(MachineTraceMetrics *ct) + : CT(*ct) { + BlockInfo.resize(CT.BlockInfo.size()); +} + +// Virtual destructor serves as an anchor. +MachineTraceMetrics::Ensemble::~Ensemble() {} + +MachineLoop* +MachineTraceMetrics::Ensemble::getLoopFor(const MachineBasicBlock *MBB) { + return CT.Loops->getLoopFor(MBB); +} + +// Update resource-related information in the TraceBlockInfo for MBB. +// Only update resources related to the trace above MBB. +void MachineTraceMetrics::Ensemble:: +computeDepthResources(const MachineBasicBlock *MBB) { + TraceBlockInfo *TBI = &BlockInfo[MBB->getNumber()]; + + // Compute resources from trace above. The top block is simple. + if (!TBI->Pred) { + TBI->InstrDepth = 0; + return; + } + + // Compute from the block above. A post-order traversal ensures the + // predecessor is always computed first. + TraceBlockInfo *PredTBI = &BlockInfo[TBI->Pred->getNumber()]; + assert(PredTBI->hasValidDepth() && "Trace above has not been computed yet"); + const FixedBlockInfo *PredFBI = CT.getResources(TBI->Pred); + TBI->InstrDepth = PredTBI->InstrDepth + PredFBI->InstrCount; +} + +// Update resource-related information in the TraceBlockInfo for MBB. +// Only update resources related to the trace below MBB. +void MachineTraceMetrics::Ensemble:: +computeHeightResources(const MachineBasicBlock *MBB) { + TraceBlockInfo *TBI = &BlockInfo[MBB->getNumber()]; + + // Compute resources for the current block. + TBI->InstrHeight = CT.getResources(MBB)->InstrCount; + + // The trace tail is done. + if (!TBI->Succ) + return; + + // Compute from the block below. A post-order traversal ensures the + // predecessor is always computed first. + TraceBlockInfo *SuccTBI = &BlockInfo[TBI->Succ->getNumber()]; + assert(SuccTBI->hasValidHeight() && "Trace below has not been computed yet"); + TBI->InstrHeight += SuccTBI->InstrHeight; +} + +// Check if depth resources for MBB are valid and return the TBI. +// Return NULL if the resources have been invalidated. +const MachineTraceMetrics::TraceBlockInfo* +MachineTraceMetrics::Ensemble:: +getDepthResources(const MachineBasicBlock *MBB) const { + const TraceBlockInfo *TBI = &BlockInfo[MBB->getNumber()]; + return TBI->hasValidDepth() ? TBI : 0; +} + +// Check if height resources for MBB are valid and return the TBI. +// Return NULL if the resources have been invalidated. +const MachineTraceMetrics::TraceBlockInfo* +MachineTraceMetrics::Ensemble:: +getHeightResources(const MachineBasicBlock *MBB) const { + const TraceBlockInfo *TBI = &BlockInfo[MBB->getNumber()]; + return TBI->hasValidHeight() ? TBI : 0; +} + +//===----------------------------------------------------------------------===// +// Trace Selection Strategies +//===----------------------------------------------------------------------===// +// +// A trace selection strategy is implemented as a sub-class of Ensemble. The +// trace through a block B is computed by two DFS traversals of the CFG +// starting from B. One upwards, and one downwards. During the upwards DFS, +// pickTracePred() is called on the post-ordered blocks. During the downwards +// DFS, pickTraceSucc() is called in a post-order. +// + +// MinInstrCountEnsemble - Pick the trace that executes the least number of +// instructions. +namespace { +class MinInstrCountEnsemble : public MachineTraceMetrics::Ensemble { + const char *getName() { return "MinInstr"; } + const MachineBasicBlock *pickTracePred(const MachineBasicBlock*); + const MachineBasicBlock *pickTraceSucc(const MachineBasicBlock*); + +public: + MinInstrCountEnsemble(MachineTraceMetrics *ct) + : MachineTraceMetrics::Ensemble(ct) {} +}; +} + +// Select the preferred predecessor for MBB. +const MachineBasicBlock* +MinInstrCountEnsemble::pickTracePred(const MachineBasicBlock *MBB) { + if (MBB->pred_empty()) + return 0; + MachineLoop *CurLoop = getLoopFor(MBB); + // Don't leave loops, and never follow back-edges. + if (CurLoop && MBB == CurLoop->getHeader()) + return 0; + unsigned CurCount = CT.getResources(MBB)->InstrCount; + const MachineBasicBlock *Best = 0; + unsigned BestDepth = 0; + for (MachineBasicBlock::const_pred_iterator + I = MBB->pred_begin(), E = MBB->pred_end(); I != E; ++I) { + const MachineBasicBlock *Pred = *I; + const MachineTraceMetrics::TraceBlockInfo *PredTBI = + getDepthResources(Pred); + // Ignore invalidated predecessors. This never happens on the first scan, + // but if we rejected this predecessor earlier, it won't be revalidated. + if (!PredTBI) + continue; + // Don't consider predecessors in other loops. + if (getLoopFor(Pred) != CurLoop) + continue; + // Pick the predecessor that would give this block the smallest InstrDepth. + unsigned Depth = PredTBI->InstrDepth + CurCount; + if (!Best || Depth < BestDepth) + Best = Pred, BestDepth = Depth; + } + return Best; +} + +// Select the preferred successor for MBB. +const MachineBasicBlock* +MinInstrCountEnsemble::pickTraceSucc(const MachineBasicBlock *MBB) { + if (MBB->pred_empty()) + return 0; + MachineLoop *CurLoop = getLoopFor(MBB); + const MachineBasicBlock *Best = 0; + unsigned BestHeight = 0; + for (MachineBasicBlock::const_succ_iterator + I = MBB->succ_begin(), E = MBB->succ_end(); I != E; ++I) { + const MachineBasicBlock *Succ = *I; + const MachineTraceMetrics::TraceBlockInfo *SuccTBI = + getHeightResources(Succ); + // Ignore invalidated successors. + if (!SuccTBI) + continue; + // Don't consider back-edges. + if (CurLoop && Succ == CurLoop->getHeader()) + continue; + // Don't consider successors in other loops. + if (getLoopFor(Succ) != CurLoop) + continue; + // Pick the successor that would give this block the smallest InstrHeight. + unsigned Height = SuccTBI->InstrHeight; + if (!Best || Height < BestHeight) + Best = Succ, BestHeight = Height; + } + return Best; +} + +// Get an Ensemble sub-class for the requested trace strategy. +MachineTraceMetrics::Ensemble * +MachineTraceMetrics::getEnsemble(MachineTraceMetrics::Strategy strategy) { + assert(strategy < TS_NumStrategies && "Invalid trace strategy enum"); + Ensemble *&E = Ensembles[strategy]; + if (E) + return E; + + // Allocate new Ensemble on demand. + switch (strategy) { + case TS_MinInstrCount: return (E = new MinInstrCountEnsemble(this)); + default: llvm_unreachable("Invalid trace strategy enum"); + } +} + +void MachineTraceMetrics::invalidate(const MachineBasicBlock *MBB) { + DEBUG(dbgs() << "Invalidate traces through BB#" << MBB->getNumber() << '\n'); + BlockInfo[MBB->getNumber()].invalidate(); + for (unsigned i = 0; i != TS_NumStrategies; ++i) + if (Ensembles[i]) + Ensembles[i]->invalidate(MBB); +} + +//===----------------------------------------------------------------------===// +// Trace building +//===----------------------------------------------------------------------===// +// +// Traces are built by two CFG traversals. To avoid recomputing too much, use a +// set abstraction that confines the search to the current loop, and doesn't +// revisit blocks. + +namespace { +struct LoopBounds { + MutableArrayRef Blocks; + const MachineLoopInfo *Loops; + const MachineLoop *CurLoop; + bool Downward; + LoopBounds(MutableArrayRef blocks, + const MachineLoopInfo *loops, const MachineLoop *curloop) + : Blocks(blocks), Loops(loops), CurLoop(curloop), Downward(false) {} +}; +} + +// Specialize po_iterator_storage in order to prune the post-order traversal so +// it is limited to the current loop and doesn't traverse the loop back edges. +namespace llvm { +template<> +class po_iterator_storage { + LoopBounds &LB; +public: + po_iterator_storage(LoopBounds &lb) : LB(lb) {} + void finishPostorder(const MachineBasicBlock*) {} + + bool insertEdge(const MachineBasicBlock *From, const MachineBasicBlock *To) { + // Skip already visited To blocks. + MachineTraceMetrics::TraceBlockInfo &TBI = LB.Blocks[To->getNumber()]; + if (LB.Downward ? TBI.hasValidHeight() : TBI.hasValidDepth()) + return false; + // Don't follow CurLoop backedges. + if (LB.CurLoop && (LB.Downward ? To : From) == LB.CurLoop->getHeader()) + return false; + // Don't leave CurLoop. + if (LB.Loops->getLoopFor(To) != LB.CurLoop) + return false; + // This is a new block. The PO traversal will compute height/depth + // resources, causing us to reject new edges to To. This only works because + // we reject back-edges, so the CFG is cycle-free. + return true; + } +}; +} + +/// Compute the trace through MBB. +void MachineTraceMetrics::Ensemble::computeTrace(const MachineBasicBlock *MBB) { + DEBUG(dbgs() << "Computing " << getName() << " trace through BB#" + << MBB->getNumber() << '\n'); + // Set up loop bounds for the backwards post-order traversal. + LoopBounds Bounds(BlockInfo, CT.Loops, getLoopFor(MBB)); + + // Run an upwards post-order search for the trace start. + Bounds.Downward = false; + typedef ipo_ext_iterator UpwardPO; + for (UpwardPO I = ipo_ext_begin(MBB, Bounds), E = ipo_ext_end(MBB, Bounds); + I != E; ++I) { + DEBUG(dbgs() << " pred for BB#" << I->getNumber() << ": "); + TraceBlockInfo &TBI = BlockInfo[I->getNumber()]; + // All the predecessors have been visited, pick the preferred one. + TBI.Pred = pickTracePred(*I); + DEBUG({ + if (TBI.Pred) + dbgs() << "BB#" << TBI.Pred->getNumber() << '\n'; + else + dbgs() << "null\n"; + }); + // The trace leading to I is now known, compute the depth resources. + computeDepthResources(*I); + } + + // Run a downwards post-order search for the trace end. + Bounds.Downward = true; + typedef po_ext_iterator DownwardPO; + for (DownwardPO I = po_ext_begin(MBB, Bounds), E = po_ext_end(MBB, Bounds); + I != E; ++I) { + DEBUG(dbgs() << " succ for BB#" << I->getNumber() << ": "); + TraceBlockInfo &TBI = BlockInfo[I->getNumber()]; + // All the successors have been visited, pick the preferred one. + BlockInfo[I->getNumber()].Succ = pickTraceSucc(*I); + DEBUG({ + if (TBI.Pred) + dbgs() << "BB#" << TBI.Succ->getNumber() << '\n'; + else + dbgs() << "null\n"; + }); + // The trace leaving I is now known, compute the height resources. + computeHeightResources(*I); + } +} + +/// Invalidate traces through BadMBB. +void +MachineTraceMetrics::Ensemble::invalidate(const MachineBasicBlock *BadMBB) { + SmallVector WorkList; + TraceBlockInfo &BadTBI = BlockInfo[BadMBB->getNumber()]; + + // Invalidate height resources of blocks above MBB. + if (BadTBI.hasValidHeight()) { + BadTBI.invalidateHeight(); + WorkList.push_back(BadMBB); + do { + const MachineBasicBlock *MBB = WorkList.pop_back_val(); + DEBUG(dbgs() << "Invalidate BB#" << MBB->getNumber() << ' ' << getName() + << " height.\n"); + // Find any MBB predecessors that have MBB as their preferred successor. + // They are the only ones that need to be invalidated. + for (MachineBasicBlock::const_pred_iterator + I = MBB->pred_begin(), E = MBB->pred_end(); I != E; ++I) { + TraceBlockInfo &TBI = BlockInfo[(*I)->getNumber()]; + if (TBI.hasValidHeight() && TBI.Succ == MBB) { + TBI.invalidateHeight(); + WorkList.push_back(*I); + } + } + } while (!WorkList.empty()); + } + + // Invalidate depth resources of blocks below MBB. + if (BadTBI.hasValidDepth()) { + BadTBI.invalidateDepth(); + WorkList.push_back(BadMBB); + do { + const MachineBasicBlock *MBB = WorkList.pop_back_val(); + DEBUG(dbgs() << "Invalidate BB#" << MBB->getNumber() << ' ' << getName() + << " depth.\n"); + // Find any MBB successors that have MBB as their preferred predecessor. + // They are the only ones that need to be invalidated. + for (MachineBasicBlock::const_succ_iterator + I = MBB->succ_begin(), E = MBB->succ_end(); I != E; ++I) { + TraceBlockInfo &TBI = BlockInfo[(*I)->getNumber()]; + if (TBI.hasValidDepth() && TBI.Pred == MBB) { + TBI.invalidateDepth(); + WorkList.push_back(*I); + } + } + } while (!WorkList.empty()); + } +} + + +MachineTraceMetrics::Trace +MachineTraceMetrics::Ensemble::getTrace(const MachineBasicBlock *MBB) { + // FIXME: Check cache tags, recompute as needed. + computeTrace(MBB); + return Trace(*this, BlockInfo[MBB->getNumber()]); +} + +void MachineTraceMetrics::Trace::print(raw_ostream &OS) const { + OS << TE.getName() << " trace:"; + if (TBI.hasValidHeight() && TBI.hasValidDepth()) + OS << ' ' << getInstrCount() << " instrs."; + + const MachineTraceMetrics::TraceBlockInfo *Block = &TBI; + OS << "\n *"; + while (Block->hasValidDepth() && Block->Pred) { + unsigned Num = Block->Pred->getNumber(); + OS << " <- BB#" << Num; + Block = &TE.BlockInfo[Num]; + } + + Block = &TBI; + OS << "\n *"; + while (Block->hasValidHeight() && Block->Succ) { + unsigned Num = Block->Succ->getNumber(); + OS << " -> BB#" << Num; + Block = &TE.BlockInfo[Num]; + } + OS << '\n'; +} -- cgit v1.1 From 0fc44869ffb5c180ec12f86f2fd02a35a1affb4a Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Thu, 26 Jul 2012 19:42:56 +0000 Subject: Use an otherwise unused variable. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@160798 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MachineTraceMetrics.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/CodeGen/MachineTraceMetrics.cpp') diff --git a/lib/CodeGen/MachineTraceMetrics.cpp b/lib/CodeGen/MachineTraceMetrics.cpp index b302101..557d473 100644 --- a/lib/CodeGen/MachineTraceMetrics.cpp +++ b/lib/CodeGen/MachineTraceMetrics.cpp @@ -384,7 +384,7 @@ void MachineTraceMetrics::Ensemble::computeTrace(const MachineBasicBlock *MBB) { DEBUG(dbgs() << " succ for BB#" << I->getNumber() << ": "); TraceBlockInfo &TBI = BlockInfo[I->getNumber()]; // All the successors have been visited, pick the preferred one. - BlockInfo[I->getNumber()].Succ = pickTraceSucc(*I); + TBI.Succ = pickTraceSucc(*I); DEBUG({ if (TBI.Pred) dbgs() << "BB#" << TBI.Succ->getNumber() << '\n'; -- cgit v1.1 From 0271a5fa29f73150fad891ca4c43a0a89a64b3bf Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Fri, 27 Jul 2012 23:58:36 +0000 Subject: Keep track of the head and tail of the trace through each block. This makes it possible to quickly detect blocks that are outside the trace. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@160904 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MachineTraceMetrics.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'lib/CodeGen/MachineTraceMetrics.cpp') diff --git a/lib/CodeGen/MachineTraceMetrics.cpp b/lib/CodeGen/MachineTraceMetrics.cpp index 557d473..8ae6f37 100644 --- a/lib/CodeGen/MachineTraceMetrics.cpp +++ b/lib/CodeGen/MachineTraceMetrics.cpp @@ -142,6 +142,7 @@ computeDepthResources(const MachineBasicBlock *MBB) { // Compute resources from trace above. The top block is simple. if (!TBI->Pred) { TBI->InstrDepth = 0; + TBI->Head = MBB->getNumber(); return; } @@ -151,6 +152,7 @@ computeDepthResources(const MachineBasicBlock *MBB) { assert(PredTBI->hasValidDepth() && "Trace above has not been computed yet"); const FixedBlockInfo *PredFBI = CT.getResources(TBI->Pred); TBI->InstrDepth = PredTBI->InstrDepth + PredFBI->InstrCount; + TBI->Head = PredTBI->Head; } // Update resource-related information in the TraceBlockInfo for MBB. @@ -163,14 +165,17 @@ computeHeightResources(const MachineBasicBlock *MBB) { TBI->InstrHeight = CT.getResources(MBB)->InstrCount; // The trace tail is done. - if (!TBI->Succ) + if (!TBI->Succ) { + TBI->Tail = MBB->getNumber(); return; + } // Compute from the block below. A post-order traversal ensures the // predecessor is always computed first. TraceBlockInfo *SuccTBI = &BlockInfo[TBI->Succ->getNumber()]; assert(SuccTBI->hasValidHeight() && "Trace below has not been computed yet"); TBI->InstrHeight += SuccTBI->InstrHeight; + TBI->Tail = SuccTBI->Tail; } // Check if depth resources for MBB are valid and return the TBI. @@ -454,12 +459,15 @@ MachineTraceMetrics::Ensemble::getTrace(const MachineBasicBlock *MBB) { } void MachineTraceMetrics::Trace::print(raw_ostream &OS) const { - OS << TE.getName() << " trace:"; + unsigned MBBNum = &TBI - &TE.BlockInfo[0]; + + OS << TE.getName() << " trace BB#" << TBI.Head << " --> BB#" << MBBNum + << " --> BB#" << TBI.Tail << ':'; if (TBI.hasValidHeight() && TBI.hasValidDepth()) OS << ' ' << getInstrCount() << " instrs."; const MachineTraceMetrics::TraceBlockInfo *Block = &TBI; - OS << "\n *"; + OS << "\nBB#" << MBBNum; while (Block->hasValidDepth() && Block->Pred) { unsigned Num = Block->Pred->getNumber(); OS << " <- BB#" << Num; @@ -467,7 +475,7 @@ void MachineTraceMetrics::Trace::print(raw_ostream &OS) const { } Block = &TBI; - OS << "\n *"; + OS << "\n "; while (Block->hasValidHeight() && Block->Succ) { unsigned Num = Block->Succ->getNumber(); OS << " -> BB#" << Num; -- cgit v1.1 From 08f6ef6a7807250d84446661b7a6ec4afa762099 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Fri, 27 Jul 2012 23:58:38 +0000 Subject: Add more debug output to MachineTraceMetrics. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@160905 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MachineTraceMetrics.cpp | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) (limited to 'lib/CodeGen/MachineTraceMetrics.cpp') diff --git a/lib/CodeGen/MachineTraceMetrics.cpp b/lib/CodeGen/MachineTraceMetrics.cpp index 8ae6f37..54c886b 100644 --- a/lib/CodeGen/MachineTraceMetrics.cpp +++ b/lib/CodeGen/MachineTraceMetrics.cpp @@ -211,7 +211,7 @@ getHeightResources(const MachineBasicBlock *MBB) const { // instructions. namespace { class MinInstrCountEnsemble : public MachineTraceMetrics::Ensemble { - const char *getName() { return "MinInstr"; } + const char *getName() const { return "MinInstr"; } const MachineBasicBlock *pickTracePred(const MachineBasicBlock*); const MachineBasicBlock *pickTraceSucc(const MachineBasicBlock*); @@ -458,6 +458,37 @@ MachineTraceMetrics::Ensemble::getTrace(const MachineBasicBlock *MBB) { return Trace(*this, BlockInfo[MBB->getNumber()]); } +void MachineTraceMetrics::Ensemble::print(raw_ostream &OS) const { + OS << getName() << " ensemble:\n"; + for (unsigned i = 0, e = BlockInfo.size(); i != e; ++i) { + OS << " BB#" << i << '\t'; + BlockInfo[i].print(OS); + OS << '\n'; + } +} + +void MachineTraceMetrics::TraceBlockInfo::print(raw_ostream &OS) const { + if (hasValidDepth()) { + OS << "depth=" << InstrDepth; + if (Pred) + OS << " pred=BB#" << Pred->getNumber(); + else + OS << " pred=null"; + OS << " head=BB#" << Head; + } else + OS << "depth invalid"; + OS << ", "; + if (hasValidHeight()) { + OS << "height=" << InstrHeight; + if (Succ) + OS << " succ=BB#" << Succ->getNumber(); + else + OS << " succ=null"; + OS << " tail=BB#" << Tail; + } else + OS << "height invalid"; +} + void MachineTraceMetrics::Trace::print(raw_ostream &OS) const { unsigned MBBNum = &TBI - &TE.BlockInfo[0]; -- cgit v1.1 From ee31ae12e8a7b843e97285b321cb1f485cd77248 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Mon, 30 Jul 2012 17:36:49 +0000 Subject: Verify that the CFG hasn't changed during invalidate(). The MachineTraceMetrics analysis must be invalidated before modifying the CFG. This will catch some of the violations of that rule. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@160969 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MachineTraceMetrics.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'lib/CodeGen/MachineTraceMetrics.cpp') diff --git a/lib/CodeGen/MachineTraceMetrics.cpp b/lib/CodeGen/MachineTraceMetrics.cpp index 54c886b..d5ff128 100644 --- a/lib/CodeGen/MachineTraceMetrics.cpp +++ b/lib/CodeGen/MachineTraceMetrics.cpp @@ -420,10 +420,15 @@ MachineTraceMetrics::Ensemble::invalidate(const MachineBasicBlock *BadMBB) { for (MachineBasicBlock::const_pred_iterator I = MBB->pred_begin(), E = MBB->pred_end(); I != E; ++I) { TraceBlockInfo &TBI = BlockInfo[(*I)->getNumber()]; - if (TBI.hasValidHeight() && TBI.Succ == MBB) { + if (!TBI.hasValidHeight()) + continue; + if (TBI.Succ == MBB) { TBI.invalidateHeight(); WorkList.push_back(*I); + continue; } + // Verify that TBI.Succ is actually a *I successor. + assert((!TBI.Succ || (*I)->isSuccessor(TBI.Succ)) && "CFG changed"); } } while (!WorkList.empty()); } @@ -441,10 +446,15 @@ MachineTraceMetrics::Ensemble::invalidate(const MachineBasicBlock *BadMBB) { for (MachineBasicBlock::const_succ_iterator I = MBB->succ_begin(), E = MBB->succ_end(); I != E; ++I) { TraceBlockInfo &TBI = BlockInfo[(*I)->getNumber()]; - if (TBI.hasValidDepth() && TBI.Pred == MBB) { + if (!TBI.hasValidDepth()) + continue; + if (TBI.Pred == MBB) { TBI.invalidateDepth(); WorkList.push_back(*I); + continue; } + // Verify that TBI.Pred is actually a *I predecessor. + assert((!TBI.Pred || (*I)->isPredecessor(TBI.Pred)) && "CFG changed"); } } while (!WorkList.empty()); } -- cgit v1.1 From a1b2bf79796d8c44b1321a69a7236b85c33ef7ca Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Mon, 30 Jul 2012 18:34:11 +0000 Subject: Add MachineTraceMetrics::verify(). This function verifies the consistency of cached data in the MachineTraceMetrics analysis. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@160976 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MachineTraceMetrics.cpp | 56 ++++++++++++++++++++++++++++++------- 1 file changed, 46 insertions(+), 10 deletions(-) (limited to 'lib/CodeGen/MachineTraceMetrics.cpp') diff --git a/lib/CodeGen/MachineTraceMetrics.cpp b/lib/CodeGen/MachineTraceMetrics.cpp index d5ff128..3037cb3 100644 --- a/lib/CodeGen/MachineTraceMetrics.cpp +++ b/lib/CodeGen/MachineTraceMetrics.cpp @@ -44,13 +44,13 @@ void MachineTraceMetrics::getAnalysisUsage(AnalysisUsage &AU) const { MachineFunctionPass::getAnalysisUsage(AU); } -bool MachineTraceMetrics::runOnMachineFunction(MachineFunction &MF) { - TII = MF.getTarget().getInstrInfo(); - TRI = MF.getTarget().getRegisterInfo(); - MRI = &MF.getRegInfo(); +bool MachineTraceMetrics::runOnMachineFunction(MachineFunction &Func) { + MF = &Func; + TII = MF->getTarget().getInstrInfo(); + TRI = MF->getTarget().getRegisterInfo(); + MRI = &MF->getRegInfo(); Loops = &getAnalysis(); - unsigned NumBlocks = MF.getNumBlockIDs(); - BlockInfo.resize(NumBlocks); + BlockInfo.resize(MF->getNumBlockIDs()); return false; } @@ -128,8 +128,8 @@ MachineTraceMetrics::Ensemble::Ensemble(MachineTraceMetrics *ct) // Virtual destructor serves as an anchor. MachineTraceMetrics::Ensemble::~Ensemble() {} -MachineLoop* -MachineTraceMetrics::Ensemble::getLoopFor(const MachineBasicBlock *MBB) { +const MachineLoop* +MachineTraceMetrics::Ensemble::getLoopFor(const MachineBasicBlock *MBB) const { return CT.Loops->getLoopFor(MBB); } @@ -226,7 +226,7 @@ const MachineBasicBlock* MinInstrCountEnsemble::pickTracePred(const MachineBasicBlock *MBB) { if (MBB->pred_empty()) return 0; - MachineLoop *CurLoop = getLoopFor(MBB); + const MachineLoop *CurLoop = getLoopFor(MBB); // Don't leave loops, and never follow back-edges. if (CurLoop && MBB == CurLoop->getHeader()) return 0; @@ -258,7 +258,7 @@ const MachineBasicBlock* MinInstrCountEnsemble::pickTraceSucc(const MachineBasicBlock *MBB) { if (MBB->pred_empty()) return 0; - MachineLoop *CurLoop = getLoopFor(MBB); + const MachineLoop *CurLoop = getLoopFor(MBB); const MachineBasicBlock *Best = 0; unsigned BestHeight = 0; for (MachineBasicBlock::const_succ_iterator @@ -306,6 +306,15 @@ void MachineTraceMetrics::invalidate(const MachineBasicBlock *MBB) { Ensembles[i]->invalidate(MBB); } +void MachineTraceMetrics::verify() const { +#ifndef NDEBUG + assert(BlockInfo.size() == MF->getNumBlockIDs() && "Outdated BlockInfo size"); + for (unsigned i = 0; i != TS_NumStrategies; ++i) + if (Ensembles[i]) + Ensembles[i]->verify(); +#endif +} + //===----------------------------------------------------------------------===// // Trace building //===----------------------------------------------------------------------===// @@ -460,6 +469,33 @@ MachineTraceMetrics::Ensemble::invalidate(const MachineBasicBlock *BadMBB) { } } +void MachineTraceMetrics::Ensemble::verify() const { +#ifndef NDEBUG + assert(BlockInfo.size() == CT.MF->getNumBlockIDs() && + "Outdated BlockInfo size"); + for (unsigned Num = 0, e = BlockInfo.size(); Num != e; ++Num) { + const TraceBlockInfo &TBI = BlockInfo[Num]; + if (TBI.hasValidDepth() && TBI.Pred) { + const MachineBasicBlock *MBB = CT.MF->getBlockNumbered(Num); + assert(MBB->isPredecessor(TBI.Pred) && "CFG doesn't match trace"); + assert(BlockInfo[TBI.Pred->getNumber()].hasValidDepth() && + "Trace is broken, depth should have been invalidated."); + const MachineLoop *Loop = getLoopFor(MBB); + assert(!(Loop && MBB == Loop->getHeader()) && "Trace contains backedge"); + } + if (TBI.hasValidHeight() && TBI.Succ) { + const MachineBasicBlock *MBB = CT.MF->getBlockNumbered(Num); + assert(MBB->isSuccessor(TBI.Succ) && "CFG doesn't match trace"); + assert(BlockInfo[TBI.Succ->getNumber()].hasValidHeight() && + "Trace is broken, height should have been invalidated."); + const MachineLoop *Loop = getLoopFor(MBB); + const MachineLoop *SuccLoop = getLoopFor(TBI.Succ); + assert(!(Loop && Loop == SuccLoop && TBI.Succ == Loop->getHeader()) && + "Trace contains backedge"); + } + } +#endif +} MachineTraceMetrics::Trace MachineTraceMetrics::Ensemble::getTrace(const MachineBasicBlock *MBB) { -- cgit v1.1 From 3f63a589788995a724bc4587d022fe15ea8576ba Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Mon, 30 Jul 2012 18:34:14 +0000 Subject: Add MachineInstr::isTransient(). This is a cleaned up version of the isFree() function in MachineTraceMetrics.cpp. Transient instructions are very unlikely to produce any code in the final output. Either because they get eliminated by RegisterCoalescing, or because they are pseudo-instructions like labels and debug values. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@160977 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MachineTraceMetrics.cpp | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) (limited to 'lib/CodeGen/MachineTraceMetrics.cpp') diff --git a/lib/CodeGen/MachineTraceMetrics.cpp b/lib/CodeGen/MachineTraceMetrics.cpp index 3037cb3..cf0d9c6 100644 --- a/lib/CodeGen/MachineTraceMetrics.cpp +++ b/lib/CodeGen/MachineTraceMetrics.cpp @@ -69,28 +69,6 @@ void MachineTraceMetrics::releaseMemory() { // The number of instructions in a basic block and the CPU resources used by // those instructions don't depend on any given trace strategy. -/// Is MI an instruction that should be considered free because it will likely -/// be eliminated by later passes? -static bool isFree(const MachineInstr *MI) { - switch(MI->getOpcode()) { - default: return false; - case TargetOpcode::PHI: - case TargetOpcode::PROLOG_LABEL: - case TargetOpcode::EH_LABEL: - case TargetOpcode::GC_LABEL: - case TargetOpcode::KILL: - case TargetOpcode::EXTRACT_SUBREG: - case TargetOpcode::INSERT_SUBREG: - case TargetOpcode::IMPLICIT_DEF: - case TargetOpcode::SUBREG_TO_REG: - case TargetOpcode::COPY_TO_REGCLASS: - case TargetOpcode::DBG_VALUE: - case TargetOpcode::REG_SEQUENCE: - case TargetOpcode::COPY: - return true; - } -} - /// Compute the resource usage in basic block MBB. const MachineTraceMetrics::FixedBlockInfo* MachineTraceMetrics::getResources(const MachineBasicBlock *MBB) { @@ -106,7 +84,7 @@ MachineTraceMetrics::getResources(const MachineBasicBlock *MBB) { for (MachineBasicBlock::const_iterator I = MBB->begin(), E = MBB->end(); I != E; ++I) { const MachineInstr *MI = I; - if (isFree(MI)) + if (MI->isTransient()) continue; ++InstrCount; if (MI->isCall()) -- cgit v1.1 From ef6c76c984f821ea866902a7f9e695b16e971468 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Mon, 30 Jul 2012 20:57:50 +0000 Subject: Hook into PassManager's analysis verification. By overriding Pass::verifyAnalysis(), the pass contents will be verified by the pass manager. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@160994 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MachineTraceMetrics.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/CodeGen/MachineTraceMetrics.cpp') diff --git a/lib/CodeGen/MachineTraceMetrics.cpp b/lib/CodeGen/MachineTraceMetrics.cpp index cf0d9c6..c31e6bd 100644 --- a/lib/CodeGen/MachineTraceMetrics.cpp +++ b/lib/CodeGen/MachineTraceMetrics.cpp @@ -284,7 +284,7 @@ void MachineTraceMetrics::invalidate(const MachineBasicBlock *MBB) { Ensembles[i]->invalidate(MBB); } -void MachineTraceMetrics::verify() const { +void MachineTraceMetrics::verifyAnalysis() const { #ifndef NDEBUG assert(BlockInfo.size() == MF->getNumBlockIDs() && "Outdated BlockInfo size"); for (unsigned i = 0; i != TS_NumStrategies; ++i) -- cgit v1.1 From 8e54ab5c7618bf3813c337ad181a741f30eb36cc Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Mon, 30 Jul 2012 21:10:27 +0000 Subject: Assert that all trace candidate blocks have been visited by the PO. When computing a trace, all the candidates for pred/succ must have been visited. Filter out back-edges first, though. The PO traversal ignores them. Thanks to Andy for spotting this in review. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@160995 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MachineTraceMetrics.cpp | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) (limited to 'lib/CodeGen/MachineTraceMetrics.cpp') diff --git a/lib/CodeGen/MachineTraceMetrics.cpp b/lib/CodeGen/MachineTraceMetrics.cpp index c31e6bd..64f4a95 100644 --- a/lib/CodeGen/MachineTraceMetrics.cpp +++ b/lib/CodeGen/MachineTraceMetrics.cpp @@ -214,15 +214,12 @@ MinInstrCountEnsemble::pickTracePred(const MachineBasicBlock *MBB) { for (MachineBasicBlock::const_pred_iterator I = MBB->pred_begin(), E = MBB->pred_end(); I != E; ++I) { const MachineBasicBlock *Pred = *I; - const MachineTraceMetrics::TraceBlockInfo *PredTBI = - getDepthResources(Pred); - // Ignore invalidated predecessors. This never happens on the first scan, - // but if we rejected this predecessor earlier, it won't be revalidated. - if (!PredTBI) - continue; // Don't consider predecessors in other loops. if (getLoopFor(Pred) != CurLoop) continue; + const MachineTraceMetrics::TraceBlockInfo *PredTBI = + getDepthResources(Pred); + assert(PredTBI && "Predecessor must be visited first"); // Pick the predecessor that would give this block the smallest InstrDepth. unsigned Depth = PredTBI->InstrDepth + CurCount; if (!Best || Depth < BestDepth) @@ -242,17 +239,15 @@ MinInstrCountEnsemble::pickTraceSucc(const MachineBasicBlock *MBB) { for (MachineBasicBlock::const_succ_iterator I = MBB->succ_begin(), E = MBB->succ_end(); I != E; ++I) { const MachineBasicBlock *Succ = *I; - const MachineTraceMetrics::TraceBlockInfo *SuccTBI = - getHeightResources(Succ); - // Ignore invalidated successors. - if (!SuccTBI) - continue; // Don't consider back-edges. if (CurLoop && Succ == CurLoop->getHeader()) continue; // Don't consider successors in other loops. if (getLoopFor(Succ) != CurLoop) continue; + const MachineTraceMetrics::TraceBlockInfo *SuccTBI = + getHeightResources(Succ); + assert(SuccTBI && "Successor must be visited first"); // Pick the successor that would give this block the smallest InstrHeight. unsigned Height = SuccTBI->InstrHeight; if (!Best || Height < BestHeight) -- cgit v1.1 From 1c899cf47c13a107cf0f85ae69fcd36c92b37f14 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Mon, 30 Jul 2012 23:15:10 +0000 Subject: Allow traces to enter nested loops. This lets traces include the final iteration of a nested loop above the center block, and the first iteration of a nested loop below the center block. We still don't allow traces to contain backedges, and traces are truncated where they would leave a loop, as seen from the center block. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@161003 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MachineTraceMetrics.cpp | 43 +++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 14 deletions(-) (limited to 'lib/CodeGen/MachineTraceMetrics.cpp') diff --git a/lib/CodeGen/MachineTraceMetrics.cpp b/lib/CodeGen/MachineTraceMetrics.cpp index 64f4a95..e688d78 100644 --- a/lib/CodeGen/MachineTraceMetrics.cpp +++ b/lib/CodeGen/MachineTraceMetrics.cpp @@ -185,6 +185,19 @@ getHeightResources(const MachineBasicBlock *MBB) const { // DFS, pickTraceSucc() is called in a post-order. // +// We never allow traces that leave loops, but we do allow traces to enter +// nested loops. We also never allow traces to contain back-edges. +// +// This means that a loop header can never appear above the center block of a +// trace, except as the trace head. Below the center block, loop exiting edges +// are banned. +// +// Return true if an edge from the From loop to the To loop is leaving a loop. +// Either of To and From can be null. +static bool isExitingLoop(const MachineLoop *From, const MachineLoop *To) { + return From && !From->contains(To); +} + // MinInstrCountEnsemble - Pick the trace that executes the least number of // instructions. namespace { @@ -214,9 +227,6 @@ MinInstrCountEnsemble::pickTracePred(const MachineBasicBlock *MBB) { for (MachineBasicBlock::const_pred_iterator I = MBB->pred_begin(), E = MBB->pred_end(); I != E; ++I) { const MachineBasicBlock *Pred = *I; - // Don't consider predecessors in other loops. - if (getLoopFor(Pred) != CurLoop) - continue; const MachineTraceMetrics::TraceBlockInfo *PredTBI = getDepthResources(Pred); assert(PredTBI && "Predecessor must be visited first"); @@ -242,8 +252,8 @@ MinInstrCountEnsemble::pickTraceSucc(const MachineBasicBlock *MBB) { // Don't consider back-edges. if (CurLoop && Succ == CurLoop->getHeader()) continue; - // Don't consider successors in other loops. - if (getLoopFor(Succ) != CurLoop) + // Don't consider successors exiting CurLoop. + if (isExitingLoop(CurLoop, getLoopFor(Succ))) continue; const MachineTraceMetrics::TraceBlockInfo *SuccTBI = getHeightResources(Succ); @@ -300,11 +310,10 @@ namespace { struct LoopBounds { MutableArrayRef Blocks; const MachineLoopInfo *Loops; - const MachineLoop *CurLoop; bool Downward; LoopBounds(MutableArrayRef blocks, - const MachineLoopInfo *loops, const MachineLoop *curloop) - : Blocks(blocks), Loops(loops), CurLoop(curloop), Downward(false) {} + const MachineLoopInfo *loops) + : Blocks(blocks), Loops(loops), Downward(false) {} }; } @@ -323,11 +332,17 @@ public: MachineTraceMetrics::TraceBlockInfo &TBI = LB.Blocks[To->getNumber()]; if (LB.Downward ? TBI.hasValidHeight() : TBI.hasValidDepth()) return false; - // Don't follow CurLoop backedges. - if (LB.CurLoop && (LB.Downward ? To : From) == LB.CurLoop->getHeader()) + // From is null once when To is the trace center block. + if (!From) + return true; + const MachineLoop *FromLoop = LB.Loops->getLoopFor(From); + if (!FromLoop) + return true; + // Don't follow backedges, don't leave FromLoop when going upwards. + if ((LB.Downward ? To : From) == FromLoop->getHeader()) return false; - // Don't leave CurLoop. - if (LB.Loops->getLoopFor(To) != LB.CurLoop) + // Don't leave FromLoop. + if (isExitingLoop(FromLoop, LB.Loops->getLoopFor(To))) return false; // This is a new block. The PO traversal will compute height/depth // resources, causing us to reject new edges to To. This only works because @@ -342,7 +357,7 @@ void MachineTraceMetrics::Ensemble::computeTrace(const MachineBasicBlock *MBB) { DEBUG(dbgs() << "Computing " << getName() << " trace through BB#" << MBB->getNumber() << '\n'); // Set up loop bounds for the backwards post-order traversal. - LoopBounds Bounds(BlockInfo, CT.Loops, getLoopFor(MBB)); + LoopBounds Bounds(BlockInfo, CT.Loops); // Run an upwards post-order search for the trace start. Bounds.Downward = false; @@ -373,7 +388,7 @@ void MachineTraceMetrics::Ensemble::computeTrace(const MachineBasicBlock *MBB) { // All the successors have been visited, pick the preferred one. TBI.Succ = pickTraceSucc(*I); DEBUG({ - if (TBI.Pred) + if (TBI.Succ) dbgs() << "BB#" << TBI.Succ->getNumber() << '\n'; else dbgs() << "null\n"; -- cgit v1.1 From 2f6b62b09f07d63b7f3ee2de50735dd8c83c0f0f Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Mon, 30 Jul 2012 23:15:12 +0000 Subject: Avoid looking at stale data in verifyAnalysis(). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@161004 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MachineTraceMetrics.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'lib/CodeGen/MachineTraceMetrics.cpp') diff --git a/lib/CodeGen/MachineTraceMetrics.cpp b/lib/CodeGen/MachineTraceMetrics.cpp index e688d78..9c961c6 100644 --- a/lib/CodeGen/MachineTraceMetrics.cpp +++ b/lib/CodeGen/MachineTraceMetrics.cpp @@ -33,7 +33,7 @@ INITIALIZE_PASS_END(MachineTraceMetrics, "machine-trace-metrics", "Machine Trace Metrics", false, true) MachineTraceMetrics::MachineTraceMetrics() - : MachineFunctionPass(ID), TII(0), TRI(0), MRI(0), Loops(0) { + : MachineFunctionPass(ID), MF(0), TII(0), TRI(0), MRI(0), Loops(0) { std::fill(Ensembles, array_endof(Ensembles), (Ensemble*)0); } @@ -55,6 +55,7 @@ bool MachineTraceMetrics::runOnMachineFunction(MachineFunction &Func) { } void MachineTraceMetrics::releaseMemory() { + MF = 0; BlockInfo.clear(); for (unsigned i = 0; i != TS_NumStrategies; ++i) { delete Ensembles[i]; @@ -290,6 +291,8 @@ void MachineTraceMetrics::invalidate(const MachineBasicBlock *MBB) { } void MachineTraceMetrics::verifyAnalysis() const { + if (!MF) + return; #ifndef NDEBUG assert(BlockInfo.size() == MF->getNumBlockIDs() && "Outdated BlockInfo size"); for (unsigned i = 0; i != TS_NumStrategies; ++i) -- cgit v1.1 From 64e2973bf78970aedecbb5fda44e19f93f56dd9b Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Tue, 31 Jul 2012 20:25:13 +0000 Subject: Rename CT -> MTM. MachineTraceMetrics is abbreviated MTM. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@161072 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MachineTraceMetrics.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'lib/CodeGen/MachineTraceMetrics.cpp') diff --git a/lib/CodeGen/MachineTraceMetrics.cpp b/lib/CodeGen/MachineTraceMetrics.cpp index 9c961c6..a81fc54 100644 --- a/lib/CodeGen/MachineTraceMetrics.cpp +++ b/lib/CodeGen/MachineTraceMetrics.cpp @@ -100,8 +100,8 @@ MachineTraceMetrics::getResources(const MachineBasicBlock *MBB) { //===----------------------------------------------------------------------===// MachineTraceMetrics::Ensemble::Ensemble(MachineTraceMetrics *ct) - : CT(*ct) { - BlockInfo.resize(CT.BlockInfo.size()); + : MTM(*ct) { + BlockInfo.resize(MTM.BlockInfo.size()); } // Virtual destructor serves as an anchor. @@ -109,7 +109,7 @@ MachineTraceMetrics::Ensemble::~Ensemble() {} const MachineLoop* MachineTraceMetrics::Ensemble::getLoopFor(const MachineBasicBlock *MBB) const { - return CT.Loops->getLoopFor(MBB); + return MTM.Loops->getLoopFor(MBB); } // Update resource-related information in the TraceBlockInfo for MBB. @@ -129,7 +129,7 @@ computeDepthResources(const MachineBasicBlock *MBB) { // predecessor is always computed first. TraceBlockInfo *PredTBI = &BlockInfo[TBI->Pred->getNumber()]; assert(PredTBI->hasValidDepth() && "Trace above has not been computed yet"); - const FixedBlockInfo *PredFBI = CT.getResources(TBI->Pred); + const FixedBlockInfo *PredFBI = MTM.getResources(TBI->Pred); TBI->InstrDepth = PredTBI->InstrDepth + PredFBI->InstrCount; TBI->Head = PredTBI->Head; } @@ -141,7 +141,7 @@ computeHeightResources(const MachineBasicBlock *MBB) { TraceBlockInfo *TBI = &BlockInfo[MBB->getNumber()]; // Compute resources for the current block. - TBI->InstrHeight = CT.getResources(MBB)->InstrCount; + TBI->InstrHeight = MTM.getResources(MBB)->InstrCount; // The trace tail is done. if (!TBI->Succ) { @@ -208,8 +208,8 @@ class MinInstrCountEnsemble : public MachineTraceMetrics::Ensemble { const MachineBasicBlock *pickTraceSucc(const MachineBasicBlock*); public: - MinInstrCountEnsemble(MachineTraceMetrics *ct) - : MachineTraceMetrics::Ensemble(ct) {} + MinInstrCountEnsemble(MachineTraceMetrics *mtm) + : MachineTraceMetrics::Ensemble(mtm) {} }; } @@ -222,7 +222,7 @@ MinInstrCountEnsemble::pickTracePred(const MachineBasicBlock *MBB) { // Don't leave loops, and never follow back-edges. if (CurLoop && MBB == CurLoop->getHeader()) return 0; - unsigned CurCount = CT.getResources(MBB)->InstrCount; + unsigned CurCount = MTM.getResources(MBB)->InstrCount; const MachineBasicBlock *Best = 0; unsigned BestDepth = 0; for (MachineBasicBlock::const_pred_iterator @@ -360,7 +360,7 @@ void MachineTraceMetrics::Ensemble::computeTrace(const MachineBasicBlock *MBB) { DEBUG(dbgs() << "Computing " << getName() << " trace through BB#" << MBB->getNumber() << '\n'); // Set up loop bounds for the backwards post-order traversal. - LoopBounds Bounds(BlockInfo, CT.Loops); + LoopBounds Bounds(BlockInfo, MTM.Loops); // Run an upwards post-order search for the trace start. Bounds.Downward = false; @@ -462,12 +462,12 @@ MachineTraceMetrics::Ensemble::invalidate(const MachineBasicBlock *BadMBB) { void MachineTraceMetrics::Ensemble::verify() const { #ifndef NDEBUG - assert(BlockInfo.size() == CT.MF->getNumBlockIDs() && + assert(BlockInfo.size() == MTM.MF->getNumBlockIDs() && "Outdated BlockInfo size"); for (unsigned Num = 0, e = BlockInfo.size(); Num != e; ++Num) { const TraceBlockInfo &TBI = BlockInfo[Num]; if (TBI.hasValidDepth() && TBI.Pred) { - const MachineBasicBlock *MBB = CT.MF->getBlockNumbered(Num); + const MachineBasicBlock *MBB = MTM.MF->getBlockNumbered(Num); assert(MBB->isPredecessor(TBI.Pred) && "CFG doesn't match trace"); assert(BlockInfo[TBI.Pred->getNumber()].hasValidDepth() && "Trace is broken, depth should have been invalidated."); @@ -475,7 +475,7 @@ void MachineTraceMetrics::Ensemble::verify() const { assert(!(Loop && MBB == Loop->getHeader()) && "Trace contains backedge"); } if (TBI.hasValidHeight() && TBI.Succ) { - const MachineBasicBlock *MBB = CT.MF->getBlockNumbered(Num); + const MachineBasicBlock *MBB = MTM.MF->getBlockNumbered(Num); assert(MBB->isSuccessor(TBI.Succ) && "CFG doesn't match trace"); assert(BlockInfo[TBI.Succ->getNumber()].hasValidHeight() && "Trace is broken, height should have been invalidated."); -- cgit v1.1 From 5f8e8bd656bb174b3e22c0e56ce3d1eb958ac2e2 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Tue, 31 Jul 2012 20:44:38 +0000 Subject: Compute instruction depths through the current trace. Assuming infinite issue width, compute the earliest each instruction in the trace can issue, when considering the latency of data dependencies. The issue cycle is record as a 'depth' from the beginning of the trace. This is half the computation required to find the length of the critical path through the trace. Heights are next. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@161074 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MachineTraceMetrics.cpp | 232 ++++++++++++++++++++++++++++++++++++ 1 file changed, 232 insertions(+) (limited to 'lib/CodeGen/MachineTraceMetrics.cpp') diff --git a/lib/CodeGen/MachineTraceMetrics.cpp b/lib/CodeGen/MachineTraceMetrics.cpp index a81fc54..1baab9b 100644 --- a/lib/CodeGen/MachineTraceMetrics.cpp +++ b/lib/CodeGen/MachineTraceMetrics.cpp @@ -19,6 +19,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include "llvm/ADT/PostOrderIterator.h" +#include "llvm/ADT/SparseSet.h" using namespace llvm; @@ -48,6 +49,7 @@ bool MachineTraceMetrics::runOnMachineFunction(MachineFunction &Func) { MF = &Func; TII = MF->getTarget().getInstrInfo(); TRI = MF->getTarget().getRegisterInfo(); + ItinData = MF->getTarget().getInstrItineraryData(); MRI = &MF->getRegInfo(); Loops = &getAnalysis(); BlockInfo.resize(MF->getNumBlockIDs()); @@ -458,6 +460,15 @@ MachineTraceMetrics::Ensemble::invalidate(const MachineBasicBlock *BadMBB) { } } while (!WorkList.empty()); } + + // Clear any per-instruction data. We only have to do this for BadMBB itself + // because the instructions in that block may change. Other blocks may be + // invalidated, but their instructions will stay the same, so there is no + // need to erase the Cycle entries. They will be overwritten when we + // recompute. + for (MachineBasicBlock::const_iterator I = BadMBB->begin(), E = BadMBB->end(); + I != E; ++I) + Cycles.erase(I); } void MachineTraceMetrics::Ensemble::verify() const { @@ -488,10 +499,227 @@ void MachineTraceMetrics::Ensemble::verify() const { #endif } +//===----------------------------------------------------------------------===// +// Data Dependencies +//===----------------------------------------------------------------------===// +// +// Compute the depth and height of each instruction based on data dependencies +// and instruction latencies. These cycle numbers assume that the CPU can issue +// an infinite number of instructions per cycle as long as their dependencies +// are ready. + +// A data dependency is represented as a defining MI and operand numbers on the +// defining and using MI. +namespace { +struct DataDep { + const MachineInstr *DefMI; + unsigned DefOp; + unsigned UseOp; +}; +} + +// Get the input data dependencies that must be ready before UseMI can issue. +// Return true if UseMI has any physreg operands. +static bool getDataDeps(const MachineInstr *UseMI, + SmallVectorImpl &Deps, + const MachineRegisterInfo *MRI) { + bool HasPhysRegs = false; + for (ConstMIOperands MO(UseMI); MO.isValid(); ++MO) { + if (!MO->isReg()) + continue; + unsigned Reg = MO->getReg(); + if (!Reg) + continue; + if (TargetRegisterInfo::isPhysicalRegister(Reg)) { + HasPhysRegs = true; + continue; + } + // Collect virtual register reads. + if (!MO->readsReg()) + continue; + MachineRegisterInfo::def_iterator DefI = MRI->def_begin(Reg); + DataDep Dep; + Dep.DefMI = &*DefI; + Dep.DefOp = DefI.getOperandNo(); + Dep.UseOp = MO.getOperandNo(); + Deps.push_back(Dep); + } + return HasPhysRegs; +} + +// Get the input data dependencies of a PHI instruction, using Pred as the +// preferred predecessor. +// This will add at most one dependency to Deps. +static void getPHIDeps(const MachineInstr *UseMI, + SmallVectorImpl &Deps, + const MachineBasicBlock *Pred, + const MachineRegisterInfo *MRI) { + // No predecessor at the beginning of a trace. Ignore dependencies. + if (!Pred) + return; + assert(UseMI->isPHI() && UseMI->getNumOperands() % 2 && "Bad PHI"); + for (unsigned i = 1; i != UseMI->getNumOperands(); i += 2) { + if (UseMI->getOperand(i + 1).getMBB() == Pred) { + unsigned Reg = UseMI->getOperand(i).getReg(); + assert(TargetRegisterInfo::isVirtualRegister(Reg) && "Bad PHI op"); + MachineRegisterInfo::def_iterator DefI = MRI->def_begin(Reg); + DataDep Dep; + Dep.DefMI = &*DefI; + Dep.DefOp = DefI.getOperandNo(); + Dep.UseOp = i; + Deps.push_back(Dep); + return; + } + } +} + +// Keep track of physreg data dependencies by recording each live register unit. +namespace { +struct LiveRegUnit { + unsigned RegUnit; + unsigned DefOp; + const MachineInstr *DefMI; + + unsigned getSparseSetIndex() const { return RegUnit; } + + LiveRegUnit(unsigned RU, const MachineInstr *MI = 0, unsigned OpNo = 0) + : RegUnit(RU), DefOp(OpNo), DefMI(MI) {} +}; +} + +// Identify physreg dependencies for UseMI, and update the live regunit +// tracking set when scanning instructions downwards. +static void updatePhysDepsDownwards(const MachineInstr *UseMI, + SmallVectorImpl &Deps, + SparseSet &RegUnits, + const TargetRegisterInfo *TRI) { + SmallVector Kills; + SmallVector LiveDefOps; + + for (ConstMIOperands MO(UseMI); MO.isValid(); ++MO) { + if (!MO->isReg()) + continue; + unsigned Reg = MO->getReg(); + if (!TargetRegisterInfo::isPhysicalRegister(Reg)) + continue; + // Track live defs and kills for updating RegUnits. + if (MO->isDef()) { + if (MO->isDead()) + Kills.push_back(Reg); + else + LiveDefOps.push_back(MO.getOperandNo()); + } else if (MO->isKill()) + Kills.push_back(Reg); + // Identify dependencies. + if (!MO->readsReg()) + continue; + for (MCRegUnitIterator Units(Reg, TRI); Units.isValid(); ++Units) { + SparseSet::iterator I = RegUnits.find(*Units); + if (I == RegUnits.end()) + continue; + DataDep Dep; + Dep.DefMI = I->DefMI; + Dep.DefOp = I->DefOp; + Dep.UseOp = MO.getOperandNo(); + Deps.push_back(Dep); + break; + } + } + + // Update RegUnits to reflect live registers after UseMI. + // First kills. + for (unsigned i = 0, e = Kills.size(); i != e; ++i) + for (MCRegUnitIterator Units(Kills[i], TRI); Units.isValid(); ++Units) + RegUnits.erase(*Units); + + // Second, live defs. + for (unsigned i = 0, e = LiveDefOps.size(); i != e; ++i) { + unsigned DefOp = LiveDefOps[i]; + for (MCRegUnitIterator Units(UseMI->getOperand(DefOp).getReg(), TRI); + Units.isValid(); ++Units) { + LiveRegUnit &LRU = RegUnits[*Units]; + LRU.DefMI = UseMI; + LRU.DefOp = DefOp; + } + } +} + + + + +/// Compute instruction depths for all instructions above or in MBB in its +/// trace. This assumes that the trace through MBB has already been computed. +void MachineTraceMetrics::Ensemble:: +computeInstrDepths(const MachineBasicBlock *MBB) { + // The top of the trace may already be computed, and HasValidInstrDepths + // implies Head->HasValidInstrDepths, so we only need to start from the first + // block in the trace that needs to be recomputed. + SmallVector Stack; + do { + TraceBlockInfo &TBI = BlockInfo[MBB->getNumber()]; + assert(TBI.hasValidDepth() && "Incomplete trace"); + if (TBI.HasValidInstrDepths) + break; + Stack.push_back(MBB); + MBB = TBI.Pred; + } while (MBB); + + // FIXME: If MBB is non-null at this point, it is the last pre-computed block + // in the trace. We should track any live-out physregs that were defined in + // the trace. This is quite rare in SSA form, typically created by CSE + // hoisting a compare. + SparseSet RegUnits; + RegUnits.setUniverse(MTM.TRI->getNumRegUnits()); + + // Go through trace blocks in top-down order, stopping after the center block. + SmallVector Deps; + while (!Stack.empty()) { + MBB = Stack.pop_back_val(); + DEBUG(dbgs() << "Depths for BB#" << MBB->getNumber() << ":\n"); + TraceBlockInfo &TBI = BlockInfo[MBB->getNumber()]; + TBI.HasValidInstrDepths = true; + for (MachineBasicBlock::const_iterator I = MBB->begin(), E = MBB->end(); + I != E; ++I) { + const MachineInstr *UseMI = I; + + // Collect all data dependencies. + Deps.clear(); + if (UseMI->isPHI()) + getPHIDeps(UseMI, Deps, TBI.Pred, MTM.MRI); + else if (getDataDeps(UseMI, Deps, MTM.MRI)) + updatePhysDepsDownwards(UseMI, Deps, RegUnits, MTM.TRI); + + // Filter and process dependencies, computing the earliest issue cycle. + unsigned Cycle = 0; + for (unsigned i = 0, e = Deps.size(); i != e; ++i) { + const DataDep &Dep = Deps[i]; + const TraceBlockInfo&DepTBI = + BlockInfo[Dep.DefMI->getParent()->getNumber()]; + // Ignore dependencies from outside the current trace. + if (!DepTBI.hasValidDepth() || DepTBI.Head != TBI.Head) + continue; + assert(DepTBI.HasValidInstrDepths && "Inconsistent dependency"); + unsigned DepCycle = Cycles.lookup(Dep.DefMI).Depth; + // Add latency if DefMI is a real instruction. Transients get latency 0. + if (!Dep.DefMI->isTransient()) + DepCycle += MTM.TII->computeOperandLatency(MTM.ItinData, + Dep.DefMI, Dep.DefOp, + UseMI, Dep.UseOp, + /* FindMin = */ false); + Cycle = std::max(Cycle, DepCycle); + } + // Remember the instruction depth. + Cycles[UseMI].Depth = Cycle; + DEBUG(dbgs() << Cycle << '\t' << *UseMI); + } + } +} + MachineTraceMetrics::Trace MachineTraceMetrics::Ensemble::getTrace(const MachineBasicBlock *MBB) { // FIXME: Check cache tags, recompute as needed. computeTrace(MBB); + computeInstrDepths(MBB); return Trace(*this, BlockInfo[MBB->getNumber()]); } @@ -512,6 +740,8 @@ void MachineTraceMetrics::TraceBlockInfo::print(raw_ostream &OS) const { else OS << " pred=null"; OS << " head=BB#" << Head; + if (HasValidInstrDepths) + OS << " +instrs"; } else OS << "depth invalid"; OS << ", "; @@ -522,6 +752,8 @@ void MachineTraceMetrics::TraceBlockInfo::print(raw_ostream &OS) const { else OS << " succ=null"; OS << " tail=BB#" << Tail; + if (HasValidInstrHeights) + OS << " +instrs"; } else OS << "height invalid"; } -- cgit v1.1 From 9dae457e2b9a9919c3f7d48b229035d2b956a2d4 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Wed, 1 Aug 2012 16:02:59 +0000 Subject: Add DataDep constructors. Explicitly check SSA form. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@161115 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MachineTraceMetrics.cpp | 38 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 20 deletions(-) (limited to 'lib/CodeGen/MachineTraceMetrics.cpp') diff --git a/lib/CodeGen/MachineTraceMetrics.cpp b/lib/CodeGen/MachineTraceMetrics.cpp index 1baab9b..0711614 100644 --- a/lib/CodeGen/MachineTraceMetrics.cpp +++ b/lib/CodeGen/MachineTraceMetrics.cpp @@ -515,6 +515,20 @@ struct DataDep { const MachineInstr *DefMI; unsigned DefOp; unsigned UseOp; + + DataDep(const MachineInstr *DefMI, unsigned DefOp, unsigned UseOp) + : DefMI(DefMI), DefOp(DefOp), UseOp(UseOp) {} + + /// Create a DataDep from an SSA form virtual register. + DataDep(const MachineRegisterInfo *MRI, unsigned VirtReg, unsigned UseOp) + : UseOp(UseOp) { + assert(TargetRegisterInfo::isVirtualRegister(VirtReg)); + MachineRegisterInfo::def_iterator DefI = MRI->def_begin(VirtReg); + assert(!DefI.atEnd() && "Register has no defs"); + DefMI = &*DefI; + DefOp = DefI.getOperandNo(); + assert((++DefI).atEnd() && "Register has multiple defs"); + } }; } @@ -535,14 +549,8 @@ static bool getDataDeps(const MachineInstr *UseMI, continue; } // Collect virtual register reads. - if (!MO->readsReg()) - continue; - MachineRegisterInfo::def_iterator DefI = MRI->def_begin(Reg); - DataDep Dep; - Dep.DefMI = &*DefI; - Dep.DefOp = DefI.getOperandNo(); - Dep.UseOp = MO.getOperandNo(); - Deps.push_back(Dep); + if (MO->readsReg()) + Deps.push_back(DataDep(MRI, Reg, MO.getOperandNo())); } return HasPhysRegs; } @@ -561,13 +569,7 @@ static void getPHIDeps(const MachineInstr *UseMI, for (unsigned i = 1; i != UseMI->getNumOperands(); i += 2) { if (UseMI->getOperand(i + 1).getMBB() == Pred) { unsigned Reg = UseMI->getOperand(i).getReg(); - assert(TargetRegisterInfo::isVirtualRegister(Reg) && "Bad PHI op"); - MachineRegisterInfo::def_iterator DefI = MRI->def_begin(Reg); - DataDep Dep; - Dep.DefMI = &*DefI; - Dep.DefOp = DefI.getOperandNo(); - Dep.UseOp = i; - Deps.push_back(Dep); + Deps.push_back(DataDep(MRI, Reg, i)); return; } } @@ -617,11 +619,7 @@ static void updatePhysDepsDownwards(const MachineInstr *UseMI, SparseSet::iterator I = RegUnits.find(*Units); if (I == RegUnits.end()) continue; - DataDep Dep; - Dep.DefMI = I->DefMI; - Dep.DefOp = I->DefOp; - Dep.UseOp = MO.getOperandNo(); - Deps.push_back(Dep); + Deps.push_back(DataDep(I->DefMI, I->DefOp, MO.getOperandNo())); break; } } -- cgit v1.1 From c7f44b8b8fca87cdd28ffe420c3b87141d88c099 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Wed, 1 Aug 2012 22:36:00 +0000 Subject: Compute instruction heights through a trace. The height on an instruction is the minimum number of cycles from the instruction is issued to the end of the trace. Heights are computed for all instructions in and below the trace center block. The method for computing heights is different from the depth computation. As we visit instructions in the trace bottom-up, heights of used instructions are pushed upwards. This way, we avoid scanning long use lists, looking for uses in the current trace. At each basic block boundary, a list of live-in registers and their minimum heights is saved in the trace block info. These live-in lists are used when restarting depth computations on a trace that converges with an already computed trace. They will also be used to accurately compute the critical path length. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@161138 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MachineTraceMetrics.cpp | 256 ++++++++++++++++++++++++++++++++++-- 1 file changed, 246 insertions(+), 10 deletions(-) (limited to 'lib/CodeGen/MachineTraceMetrics.cpp') diff --git a/lib/CodeGen/MachineTraceMetrics.cpp b/lib/CodeGen/MachineTraceMetrics.cpp index 0711614..272a55f 100644 --- a/lib/CodeGen/MachineTraceMetrics.cpp +++ b/lib/CodeGen/MachineTraceMetrics.cpp @@ -576,16 +576,19 @@ static void getPHIDeps(const MachineInstr *UseMI, } // Keep track of physreg data dependencies by recording each live register unit. +// Associate each regunit with an instruction operand. Depending on the +// direction instructions are scanned, it could be the operand that defined the +// regunit, or the highest operand to read the regunit. namespace { struct LiveRegUnit { unsigned RegUnit; - unsigned DefOp; - const MachineInstr *DefMI; + unsigned Cycle; + const MachineInstr *MI; + unsigned Op; unsigned getSparseSetIndex() const { return RegUnit; } - LiveRegUnit(unsigned RU, const MachineInstr *MI = 0, unsigned OpNo = 0) - : RegUnit(RU), DefOp(OpNo), DefMI(MI) {} + LiveRegUnit(unsigned RU) : RegUnit(RU), Cycle(0), MI(0), Op(0) {} }; } @@ -619,7 +622,7 @@ static void updatePhysDepsDownwards(const MachineInstr *UseMI, SparseSet::iterator I = RegUnits.find(*Units); if (I == RegUnits.end()) continue; - Deps.push_back(DataDep(I->DefMI, I->DefOp, MO.getOperandNo())); + Deps.push_back(DataDep(I->MI, I->Op, MO.getOperandNo())); break; } } @@ -636,15 +639,12 @@ static void updatePhysDepsDownwards(const MachineInstr *UseMI, for (MCRegUnitIterator Units(UseMI->getOperand(DefOp).getReg(), TRI); Units.isValid(); ++Units) { LiveRegUnit &LRU = RegUnits[*Units]; - LRU.DefMI = UseMI; - LRU.DefOp = DefOp; + LRU.MI = UseMI; + LRU.Op = DefOp; } } } - - - /// Compute instruction depths for all instructions above or in MBB in its /// trace. This assumes that the trace through MBB has already been computed. void MachineTraceMetrics::Ensemble:: @@ -713,11 +713,247 @@ computeInstrDepths(const MachineBasicBlock *MBB) { } } +// Identify physreg dependencies for MI when scanning instructions upwards. +// Return the issue height of MI after considering any live regunits. +// Height is the issue height computed from virtual register dependencies alone. +static unsigned updatePhysDepsUpwards(const MachineInstr *MI, unsigned Height, + SparseSet &RegUnits, + const InstrItineraryData *ItinData, + const TargetInstrInfo *TII, + const TargetRegisterInfo *TRI) { + SmallVector ReadOps; + for (ConstMIOperands MO(MI); MO.isValid(); ++MO) { + if (!MO->isReg()) + continue; + unsigned Reg = MO->getReg(); + if (!TargetRegisterInfo::isPhysicalRegister(Reg)) + continue; + if (MO->readsReg()) + ReadOps.push_back(MO.getOperandNo()); + if (!MO->isDef()) + continue; + // This is a def of Reg. Remove corresponding entries from RegUnits, and + // update MI Height to consider the physreg dependencies. + for (MCRegUnitIterator Units(Reg, TRI); Units.isValid(); ++Units) { + SparseSet::iterator I = RegUnits.find(*Units); + if (I == RegUnits.end()) + continue; + unsigned DepHeight = I->Cycle; + if (!MI->isTransient()) { + // We may not know the UseMI of this dependency, if it came from the + // live-in list. + if (I->MI) + DepHeight += TII->computeOperandLatency(ItinData, + MI, MO.getOperandNo(), + I->MI, I->Op); + else + // No UseMI. Just use the MI latency instead. + DepHeight += TII->getInstrLatency(ItinData, MI); + } + Height = std::max(Height, DepHeight); + // This regunit is dead above MI. + RegUnits.erase(I); + } + } + + // Now we know the height of MI. Update any regunits read. + for (unsigned i = 0, e = ReadOps.size(); i != e; ++i) { + unsigned Reg = MI->getOperand(ReadOps[i]).getReg(); + for (MCRegUnitIterator Units(Reg, TRI); Units.isValid(); ++Units) { + LiveRegUnit &LRU = RegUnits[*Units]; + // Set the height to the highest reader of the unit. + if (LRU.Cycle <= Height && LRU.MI != MI) { + LRU.Cycle = Height; + LRU.MI = MI; + LRU.Op = ReadOps[i]; + } + } + } + + return Height; +} + + +typedef DenseMap MIHeightMap; + +// Push the height of DefMI upwards if required to match UseMI. +// Return true if this is the first time DefMI was seen. +static bool pushDepHeight(const DataDep &Dep, + const MachineInstr *UseMI, unsigned UseHeight, + MIHeightMap &Heights, + const InstrItineraryData *ItinData, + const TargetInstrInfo *TII) { + // Adjust height by Dep.DefMI latency. + if (!Dep.DefMI->isTransient()) + UseHeight += TII->computeOperandLatency(ItinData, Dep.DefMI, Dep.DefOp, + UseMI, Dep.UseOp); + + // Update Heights[DefMI] to be the maximum height seen. + MIHeightMap::iterator I; + bool New; + tie(I, New) = Heights.insert(std::make_pair(Dep.DefMI, UseHeight)); + if (New) + return true; + + // DefMI has been pushed before. Give it the max height. + if (I->second < UseHeight) + I->second = UseHeight; + return false; +} + +/// Assuming that DefMI was used by Trace.back(), add it to the live-in lists +/// of all the blocks in Trace. Stop when reaching the block that contains +/// DefMI. +void MachineTraceMetrics::Ensemble:: +addLiveIns(const MachineInstr *DefMI, + ArrayRef Trace) { + assert(!Trace.empty() && "Trace should contain at least one block"); + unsigned Reg = DefMI->getOperand(0).getReg(); + assert(TargetRegisterInfo::isVirtualRegister(Reg)); + const MachineBasicBlock *DefMBB = DefMI->getParent(); + + // Reg is live-in to all blocks in Trace that follow DefMBB. + for (unsigned i = Trace.size(); i; --i) { + const MachineBasicBlock *MBB = Trace[i-1]; + if (MBB == DefMBB) + return; + TraceBlockInfo &TBI = BlockInfo[MBB->getNumber()]; + // Just add the register. The height will be updated later. + TBI.LiveIns.push_back(Reg); + } +} + +/// Compute instruction heights in the trace through MBB. This updates MBB and +/// the blocks below it in the trace. It is assumed that the trace has already +/// been computed. +void MachineTraceMetrics::Ensemble:: +computeInstrHeights(const MachineBasicBlock *MBB) { + // The bottom of the trace may already be computed. + // Find the blocks that need updating. + SmallVector Stack; + do { + TraceBlockInfo &TBI = BlockInfo[MBB->getNumber()]; + assert(TBI.hasValidHeight() && "Incomplete trace"); + if (TBI.HasValidInstrHeights) + break; + Stack.push_back(MBB); + TBI.LiveIns.clear(); + MBB = TBI.Succ; + } while (MBB); + + // As we move upwards in the trace, keep track of instructions that are + // required by deeper trace instructions. Map MI -> height required so far. + MIHeightMap Heights; + + // For physregs, the def isn't known when we see the use. + // Instead, keep track of the highest use of each regunit. + SparseSet RegUnits; + RegUnits.setUniverse(MTM.TRI->getNumRegUnits()); + + // If the bottom of the trace was already precomputed, initialize heights + // from its live-in list. + // MBB is the highest precomputed block in the trace. + if (MBB) { + TraceBlockInfo &TBI = BlockInfo[MBB->getNumber()]; + for (unsigned i = 0, e = TBI.LiveIns.size(); i != e; ++i) { + LiveInReg LI = TBI.LiveIns[i]; + if (TargetRegisterInfo::isVirtualRegister(LI.Reg)) { + // For virtual registers, the def latency is included. + unsigned &Height = Heights[MTM.MRI->getVRegDef(LI.Reg)]; + if (Height < LI.Height) + Height = LI.Height; + } else { + // For register units, the def latency is not included because we don't + // know the def yet. + RegUnits[LI.Reg].Cycle = LI.Height; + } + } + } + + // Go through the trace blocks in bottom-up order. + SmallVector Deps; + for (;!Stack.empty(); Stack.pop_back()) { + MBB = Stack.back(); + DEBUG(dbgs() << "Heights for BB#" << MBB->getNumber() << ":\n"); + TraceBlockInfo &TBI = BlockInfo[MBB->getNumber()]; + TBI.HasValidInstrHeights = true; + + // Get dependencies from PHIs in the trace successor. + if (TBI.Succ) { + for (MachineBasicBlock::const_iterator + I = TBI.Succ->begin(), E = TBI.Succ->end(); + I != E && !I->isPHI(); ++I) { + const MachineInstr *PHI = I; + Deps.clear(); + getPHIDeps(PHI, Deps, MBB, MTM.MRI); + if (!Deps.empty()) + if (pushDepHeight(Deps.front(), PHI, Cycles.lookup(PHI).Height, + Heights, MTM.ItinData, MTM.TII)) + addLiveIns(Deps.front().DefMI, Stack); + } + } + + // Go through the block backwards. + for (MachineBasicBlock::const_iterator BI = MBB->end(), BB = MBB->begin(); + BI != BB;) { + const MachineInstr *MI = --BI; + + // Find the MI height as determined by virtual register uses in the + // trace below. + unsigned Cycle = 0; + MIHeightMap::iterator HeightI = Heights.find(MI); + if (HeightI != Heights.end()) { + Cycle = HeightI->second; + // We won't be seeing any more MI uses. + Heights.erase(HeightI); + } + + // Don't process PHI deps. They depend on the specific predecessor, and + // we'll get them when visiting the predecessor. + Deps.clear(); + bool HasPhysRegs = !MI->isPHI() && getDataDeps(MI, Deps, MTM.MRI); + + // There may also be regunit dependencies to include in the height. + if (HasPhysRegs) + Cycle = updatePhysDepsUpwards(MI, Cycle, RegUnits, + MTM.ItinData, MTM.TII, MTM.TRI); + + DEBUG(dbgs() << Cycle << '\t' << *MI); + Cycles[MI].Height = Cycle; + + // Update the required height of any virtual registers read by MI. + for (unsigned i = 0, e = Deps.size(); i != e; ++i) + if (pushDepHeight(Deps[i], MI, Cycle, Heights, MTM.ItinData, MTM.TII)) + addLiveIns(Deps[i].DefMI, Stack); + } + + // Update virtual live-in heights. They were added by addLiveIns() with a 0 + // height because the final height isn't known until now. + DEBUG(dbgs() << "BB#" << MBB->getNumber() << " Live-ins:"); + for (unsigned i = 0, e = TBI.LiveIns.size(); i != e; ++i) { + LiveInReg &LIR = TBI.LiveIns[i]; + const MachineInstr *DefMI = MTM.MRI->getVRegDef(LIR.Reg); + LIR.Height = Heights.lookup(DefMI); + DEBUG(dbgs() << ' ' << PrintReg(LIR.Reg) << '@' << LIR.Height); + } + + // Transfer the live regunits to the live-in list. + for (SparseSet::const_iterator + RI = RegUnits.begin(), RE = RegUnits.end(); RI != RE; ++RI) { + TBI.LiveIns.push_back(LiveInReg(RI->RegUnit, RI->Cycle)); + DEBUG(dbgs() << ' ' << PrintRegUnit(RI->RegUnit, MTM.TRI) + << '@' << RI->Cycle); + } + DEBUG(dbgs() << '\n'); + } +} + MachineTraceMetrics::Trace MachineTraceMetrics::Ensemble::getTrace(const MachineBasicBlock *MBB) { // FIXME: Check cache tags, recompute as needed. computeTrace(MBB); computeInstrDepths(MBB); + computeInstrHeights(MBB); return Trace(*this, BlockInfo[MBB->getNumber()]); } -- cgit v1.1 From 79a20ce6f0d6c1041a5031aca41b50a1e58b1d4b Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Thu, 2 Aug 2012 18:45:54 +0000 Subject: Compute the critical path length through a trace. Whenever both instruction depths and instruction heights are known in a block, it is possible to compute the length of the critical path as max(depth+height) over the instructions in the block. The stored live-in lists make it possible to accurately compute the length of a critical path that bypasses the current (small) block. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@161197 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MachineTraceMetrics.cpp | 74 ++++++++++++++++++++++++++++++++++--- 1 file changed, 69 insertions(+), 5 deletions(-) (limited to 'lib/CodeGen/MachineTraceMetrics.cpp') diff --git a/lib/CodeGen/MachineTraceMetrics.cpp b/lib/CodeGen/MachineTraceMetrics.cpp index 272a55f..1c0894e 100644 --- a/lib/CodeGen/MachineTraceMetrics.cpp +++ b/lib/CodeGen/MachineTraceMetrics.cpp @@ -645,6 +645,37 @@ static void updatePhysDepsDownwards(const MachineInstr *UseMI, } } +/// The length of the critical path through a trace is the maximum of two path +/// lengths: +/// +/// 1. The maximum height+depth over all instructions in the trace center block. +/// +/// 2. The longest cross-block dependency chain. For small blocks, it is +/// possible that the critical path through the trace doesn't include any +/// instructions in the block. +/// +/// This function computes the second number from the live-in list of the +/// center block. +unsigned MachineTraceMetrics::Ensemble:: +computeCrossBlockCriticalPath(const TraceBlockInfo &TBI) { + assert(TBI.HasValidInstrDepths && "Missing depth info"); + assert(TBI.HasValidInstrHeights && "Missing height info"); + unsigned MaxLen = 0; + for (unsigned i = 0, e = TBI.LiveIns.size(); i != e; ++i) { + const LiveInReg &LIR = TBI.LiveIns[i]; + if (!TargetRegisterInfo::isVirtualRegister(LIR.Reg)) + continue; + const MachineInstr *DefMI = MTM.MRI->getVRegDef(LIR.Reg); + // Ignore dependencies outside the current trace. + const TraceBlockInfo &DefTBI = BlockInfo[DefMI->getParent()->getNumber()]; + if (!DefTBI.hasValidDepth() || DefTBI.Head != TBI.Head) + continue; + unsigned Len = LIR.Height + Cycles[DefMI].Depth; + MaxLen = std::max(MaxLen, Len); + } + return MaxLen; +} + /// Compute instruction depths for all instructions above or in MBB in its /// trace. This assumes that the trace through MBB has already been computed. void MachineTraceMetrics::Ensemble:: @@ -676,6 +707,12 @@ computeInstrDepths(const MachineBasicBlock *MBB) { DEBUG(dbgs() << "Depths for BB#" << MBB->getNumber() << ":\n"); TraceBlockInfo &TBI = BlockInfo[MBB->getNumber()]; TBI.HasValidInstrDepths = true; + TBI.CriticalPath = 0; + + // Also compute the critical path length through MBB when possible. + if (TBI.HasValidInstrHeights) + TBI.CriticalPath = computeCrossBlockCriticalPath(TBI); + for (MachineBasicBlock::const_iterator I = MBB->begin(), E = MBB->end(); I != E; ++I) { const MachineInstr *UseMI = I; @@ -707,8 +744,16 @@ computeInstrDepths(const MachineBasicBlock *MBB) { Cycle = std::max(Cycle, DepCycle); } // Remember the instruction depth. - Cycles[UseMI].Depth = Cycle; - DEBUG(dbgs() << Cycle << '\t' << *UseMI); + InstrCycles &MICycles = Cycles[UseMI]; + MICycles.Depth = Cycle; + + if (!TBI.HasValidInstrHeights) { + DEBUG(dbgs() << Cycle << '\t' << *UseMI); + continue; + } + // Update critical path length. + TBI.CriticalPath = std::max(TBI.CriticalPath, Cycle + MICycles.Height); + DEBUG(dbgs() << TBI.CriticalPath << '\t' << Cycle << '\t' << *UseMI); } } } @@ -877,6 +922,7 @@ computeInstrHeights(const MachineBasicBlock *MBB) { DEBUG(dbgs() << "Heights for BB#" << MBB->getNumber() << ":\n"); TraceBlockInfo &TBI = BlockInfo[MBB->getNumber()]; TBI.HasValidInstrHeights = true; + TBI.CriticalPath = 0; // Get dependencies from PHIs in the trace successor. if (TBI.Succ) { @@ -918,13 +964,20 @@ computeInstrHeights(const MachineBasicBlock *MBB) { Cycle = updatePhysDepsUpwards(MI, Cycle, RegUnits, MTM.ItinData, MTM.TII, MTM.TRI); - DEBUG(dbgs() << Cycle << '\t' << *MI); - Cycles[MI].Height = Cycle; - // Update the required height of any virtual registers read by MI. for (unsigned i = 0, e = Deps.size(); i != e; ++i) if (pushDepHeight(Deps[i], MI, Cycle, Heights, MTM.ItinData, MTM.TII)) addLiveIns(Deps[i].DefMI, Stack); + + InstrCycles &MICycles = Cycles[MI]; + MICycles.Height = Cycle; + if (!TBI.HasValidInstrDepths) { + DEBUG(dbgs() << Cycle << '\t' << *MI); + continue; + } + // Update critical path length. + TBI.CriticalPath = std::max(TBI.CriticalPath, Cycle + MICycles.Depth); + DEBUG(dbgs() << TBI.CriticalPath << '\t' << Cycle << '\t' << *MI); } // Update virtual live-in heights. They were added by addLiveIns() with a 0 @@ -945,6 +998,13 @@ computeInstrHeights(const MachineBasicBlock *MBB) { << '@' << RI->Cycle); } DEBUG(dbgs() << '\n'); + + if (!TBI.HasValidInstrDepths) + continue; + // Add live-ins to the critical path length. + TBI.CriticalPath = std::max(TBI.CriticalPath, + computeCrossBlockCriticalPath(TBI)); + DEBUG(dbgs() << "Critical path: " << TBI.CriticalPath << '\n'); } } @@ -990,6 +1050,8 @@ void MachineTraceMetrics::TraceBlockInfo::print(raw_ostream &OS) const { OS << " +instrs"; } else OS << "height invalid"; + if (HasValidInstrDepths && HasValidInstrHeights) + OS << ", crit=" << CriticalPath; } void MachineTraceMetrics::Trace::print(raw_ostream &OS) const { @@ -999,6 +1061,8 @@ void MachineTraceMetrics::Trace::print(raw_ostream &OS) const { << " --> BB#" << TBI.Tail << ':'; if (TBI.hasValidHeight() && TBI.hasValidDepth()) OS << ' ' << getInstrCount() << " instrs."; + if (TBI.HasValidInstrDepths && TBI.HasValidInstrHeights) + OS << ' ' << TBI.CriticalPath << " cycles."; const MachineTraceMetrics::TraceBlockInfo *Block = &TBI; OS << "\nBB#" << MBBNum; -- cgit v1.1 From 84ef6ba44394f983d985b02e328cbb2dd779e4b0 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Tue, 7 Aug 2012 18:02:19 +0000 Subject: Add trace accessor methods, implement primitive if-conversion heuristic. Compare the critical paths of the two traces through an if-conversion candidate. If the difference is larger than the branch brediction penalty, reject the if-conversion. If would never pay. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@161433 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MachineTraceMetrics.cpp | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'lib/CodeGen/MachineTraceMetrics.cpp') diff --git a/lib/CodeGen/MachineTraceMetrics.cpp b/lib/CodeGen/MachineTraceMetrics.cpp index 1c0894e..09b6e9c 100644 --- a/lib/CodeGen/MachineTraceMetrics.cpp +++ b/lib/CodeGen/MachineTraceMetrics.cpp @@ -14,6 +14,7 @@ #include "llvm/CodeGen/MachineLoopInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/Passes.h" +#include "llvm/MC/MCInstrItineraries.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Support/Debug.h" @@ -1017,6 +1018,29 @@ MachineTraceMetrics::Ensemble::getTrace(const MachineBasicBlock *MBB) { return Trace(*this, BlockInfo[MBB->getNumber()]); } +unsigned +MachineTraceMetrics::Trace::getInstrSlack(const MachineInstr *MI) const { + assert(MI && "Not an instruction."); + assert(getBlockNum() == unsigned(MI->getParent()->getNumber()) && + "MI must be in the trace center block"); + InstrCycles Cyc = getInstrCycles(MI); + return getCriticalPath() - (Cyc.Depth + Cyc.Height); +} + +unsigned MachineTraceMetrics::Trace::getResourceDepth(bool Bottom) const { + // For now, we compute the resource depth from instruction count / issue + // width. Eventually, we should compute resource depth per functional unit + // and return the max. + unsigned Instrs = TBI.InstrDepth; + if (Bottom) + Instrs += TE.MTM.BlockInfo[getBlockNum()].InstrCount; + if (const MCSchedModel *Model = TE.MTM.ItinData->SchedModel) + if (Model->IssueWidth != 0) + return Instrs / Model->IssueWidth; + // Assume issue width 1 without a schedule model. + return Instrs; +} + void MachineTraceMetrics::Ensemble::print(raw_ostream &OS) const { OS << getName() << " ensemble:\n"; for (unsigned i = 0, e = BlockInfo.size(); i != e; ++i) { -- cgit v1.1 From 7a8f311ece7108e44ded601237091c23ef7782eb Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Tue, 7 Aug 2012 18:32:57 +0000 Subject: Fix a couple of typos. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@161437 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MachineTraceMetrics.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/CodeGen/MachineTraceMetrics.cpp') diff --git a/lib/CodeGen/MachineTraceMetrics.cpp b/lib/CodeGen/MachineTraceMetrics.cpp index 09b6e9c..67427dd 100644 --- a/lib/CodeGen/MachineTraceMetrics.cpp +++ b/lib/CodeGen/MachineTraceMetrics.cpp @@ -929,7 +929,7 @@ computeInstrHeights(const MachineBasicBlock *MBB) { if (TBI.Succ) { for (MachineBasicBlock::const_iterator I = TBI.Succ->begin(), E = TBI.Succ->end(); - I != E && !I->isPHI(); ++I) { + I != E && I->isPHI(); ++I) { const MachineInstr *PHI = I; Deps.clear(); getPHIDeps(PHI, Deps, MBB, MTM.MRI); -- cgit v1.1 From e723007ee6911c77bedaa2e914961e86b0b4ce61 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Wed, 8 Aug 2012 22:12:01 +0000 Subject: Deal with irreducible control flow when building traces. We filter out MachineLoop back-edges during the trace-building PO traversals, but it is possible to have CFG cycles that aren't natural loops, and MachineLoopInfo doesn't include such cycles. Use a standard visited set to detect such CFG cycles, and completely ignore them when picking traces. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@161532 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MachineTraceMetrics.cpp | 39 +++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 17 deletions(-) (limited to 'lib/CodeGen/MachineTraceMetrics.cpp') diff --git a/lib/CodeGen/MachineTraceMetrics.cpp b/lib/CodeGen/MachineTraceMetrics.cpp index 67427dd..d0e6398 100644 --- a/lib/CodeGen/MachineTraceMetrics.cpp +++ b/lib/CodeGen/MachineTraceMetrics.cpp @@ -233,7 +233,9 @@ MinInstrCountEnsemble::pickTracePred(const MachineBasicBlock *MBB) { const MachineBasicBlock *Pred = *I; const MachineTraceMetrics::TraceBlockInfo *PredTBI = getDepthResources(Pred); - assert(PredTBI && "Predecessor must be visited first"); + // Ignore cycles that aren't natural loops. + if (!PredTBI) + continue; // Pick the predecessor that would give this block the smallest InstrDepth. unsigned Depth = PredTBI->InstrDepth + CurCount; if (!Best || Depth < BestDepth) @@ -261,7 +263,9 @@ MinInstrCountEnsemble::pickTraceSucc(const MachineBasicBlock *MBB) { continue; const MachineTraceMetrics::TraceBlockInfo *SuccTBI = getHeightResources(Succ); - assert(SuccTBI && "Successor must be visited first"); + // Ignore cycles that aren't natural loops. + if (!SuccTBI) + continue; // Pick the successor that would give this block the smallest InstrHeight. unsigned Height = SuccTBI->InstrHeight; if (!Best || Height < BestHeight) @@ -315,6 +319,7 @@ void MachineTraceMetrics::verifyAnalysis() const { namespace { struct LoopBounds { MutableArrayRef Blocks; + SmallPtrSet Visited; const MachineLoopInfo *Loops; bool Downward; LoopBounds(MutableArrayRef blocks, @@ -339,21 +344,19 @@ public: if (LB.Downward ? TBI.hasValidHeight() : TBI.hasValidDepth()) return false; // From is null once when To is the trace center block. - if (!From) - return true; - const MachineLoop *FromLoop = LB.Loops->getLoopFor(From); - if (!FromLoop) - return true; - // Don't follow backedges, don't leave FromLoop when going upwards. - if ((LB.Downward ? To : From) == FromLoop->getHeader()) - return false; - // Don't leave FromLoop. - if (isExitingLoop(FromLoop, LB.Loops->getLoopFor(To))) - return false; - // This is a new block. The PO traversal will compute height/depth - // resources, causing us to reject new edges to To. This only works because - // we reject back-edges, so the CFG is cycle-free. - return true; + if (From) { + if (const MachineLoop *FromLoop = LB.Loops->getLoopFor(From)) { + // Don't follow backedges, don't leave FromLoop when going upwards. + if ((LB.Downward ? To : From) == FromLoop->getHeader()) + return false; + // Don't leave FromLoop. + if (isExitingLoop(FromLoop, LB.Loops->getLoopFor(To))) + return false; + } + } + // To is a new block. Mark the block as visited in case the CFG has cycles + // that MachineLoopInfo didn't recognize as a natural loop. + return LB.Visited.insert(To); } }; } @@ -367,6 +370,7 @@ void MachineTraceMetrics::Ensemble::computeTrace(const MachineBasicBlock *MBB) { // Run an upwards post-order search for the trace start. Bounds.Downward = false; + Bounds.Visited.clear(); typedef ipo_ext_iterator UpwardPO; for (UpwardPO I = ipo_ext_begin(MBB, Bounds), E = ipo_ext_end(MBB, Bounds); I != E; ++I) { @@ -386,6 +390,7 @@ void MachineTraceMetrics::Ensemble::computeTrace(const MachineBasicBlock *MBB) { // Run a downwards post-order search for the trace end. Bounds.Downward = true; + Bounds.Visited.clear(); typedef po_ext_iterator DownwardPO; for (DownwardPO I = po_ext_begin(MBB, Bounds), E = po_ext_end(MBB, Bounds); I != E; ++I) { -- cgit v1.1 From 8828c4ccd44cb49d13360cf86fd0b963f211f03f Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Fri, 10 Aug 2012 20:11:38 +0000 Subject: Include loop-carried dependencies when computing instr heights. When a trace ends with a back-edge, include PHIs in the loop header in the height computations. This makes the critical path through a loop more accurate by including the latencies of the last instructions in the loop. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@161688 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MachineTraceMetrics.cpp | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) (limited to 'lib/CodeGen/MachineTraceMetrics.cpp') diff --git a/lib/CodeGen/MachineTraceMetrics.cpp b/lib/CodeGen/MachineTraceMetrics.cpp index d0e6398..c6a6d58 100644 --- a/lib/CodeGen/MachineTraceMetrics.cpp +++ b/lib/CodeGen/MachineTraceMetrics.cpp @@ -931,17 +931,29 @@ computeInstrHeights(const MachineBasicBlock *MBB) { TBI.CriticalPath = 0; // Get dependencies from PHIs in the trace successor. - if (TBI.Succ) { - for (MachineBasicBlock::const_iterator - I = TBI.Succ->begin(), E = TBI.Succ->end(); + const MachineBasicBlock *Succ = TBI.Succ; + // If MBB is the last block in the trace, and it has a back-edge to the + // loop header, get loop-carried dependencies from PHIs in the header. For + // that purpose, pretend that all the loop header PHIs have height 0. + if (!Succ) + if (const MachineLoop *Loop = getLoopFor(MBB)) + if (MBB->isSuccessor(Loop->getHeader())) + Succ = Loop->getHeader(); + + if (Succ) { + for (MachineBasicBlock::const_iterator I = Succ->begin(), E = Succ->end(); I != E && I->isPHI(); ++I) { const MachineInstr *PHI = I; Deps.clear(); getPHIDeps(PHI, Deps, MBB, MTM.MRI); - if (!Deps.empty()) - if (pushDepHeight(Deps.front(), PHI, Cycles.lookup(PHI).Height, - Heights, MTM.ItinData, MTM.TII)) + if (!Deps.empty()) { + // Loop header PHI heights are all 0. + unsigned Height = TBI.Succ ? Cycles.lookup(PHI).Height : 0; + DEBUG(dbgs() << "pred\t" << Height << '\t' << *PHI); + if (pushDepHeight(Deps.front(), PHI, Height, + Heights, MTM.ItinData, MTM.TII)) addLiveIns(Deps.front().DefMI, Stack); + } } } -- cgit v1.1 From 5413b68b1f59041a821287790dbc1ee2e272cf4e Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Fri, 10 Aug 2012 22:27:27 +0000 Subject: Add more trace query functions. Trace::getResourceLength() computes the number of cycles required to execute the trace when ignoring data dependencies. The number can be compared to the critical path to estimate the trace ILP. Trace::getPHIDepth() computes the data dependency depth of a PHI in a trace successor that isn't necessarily part of the trace. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@161711 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MachineTraceMetrics.cpp | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) (limited to 'lib/CodeGen/MachineTraceMetrics.cpp') diff --git a/lib/CodeGen/MachineTraceMetrics.cpp b/lib/CodeGen/MachineTraceMetrics.cpp index c6a6d58..fc858be 100644 --- a/lib/CodeGen/MachineTraceMetrics.cpp +++ b/lib/CodeGen/MachineTraceMetrics.cpp @@ -1044,6 +1044,23 @@ MachineTraceMetrics::Trace::getInstrSlack(const MachineInstr *MI) const { return getCriticalPath() - (Cyc.Depth + Cyc.Height); } +unsigned +MachineTraceMetrics::Trace::getPHIDepth(const MachineInstr *PHI) const { + const MachineBasicBlock *MBB = TE.MTM.MF->getBlockNumbered(getBlockNum()); + SmallVector Deps; + getPHIDeps(PHI, Deps, MBB, TE.MTM.MRI); + assert(Deps.size() == 1 && "PHI doesn't have MBB as a predecessor"); + DataDep &Dep = Deps.front(); + unsigned DepCycle = getInstrCycles(Dep.DefMI).Depth; + // Add latency if DefMI is a real instruction. Transients get latency 0. + if (!Dep.DefMI->isTransient()) + DepCycle += TE.MTM.TII->computeOperandLatency(TE.MTM.ItinData, + Dep.DefMI, Dep.DefOp, + PHI, Dep.UseOp, + /* FindMin = */ false); + return DepCycle; +} + unsigned MachineTraceMetrics::Trace::getResourceDepth(bool Bottom) const { // For now, we compute the resource depth from instruction count / issue // width. Eventually, we should compute resource depth per functional unit @@ -1058,6 +1075,18 @@ unsigned MachineTraceMetrics::Trace::getResourceDepth(bool Bottom) const { return Instrs; } +unsigned MachineTraceMetrics::Trace:: +getResourceLength(ArrayRef Extrablocks) const { + unsigned Instrs = TBI.InstrDepth + TBI.InstrHeight; + for (unsigned i = 0, e = Extrablocks.size(); i != e; ++i) + Instrs += TE.MTM.getResources(Extrablocks[i])->InstrCount; + if (const MCSchedModel *Model = TE.MTM.ItinData->SchedModel) + if (Model->IssueWidth != 0) + return Instrs / Model->IssueWidth; + // Assume issue width 1 without a schedule model. + return Instrs; +} + void MachineTraceMetrics::Ensemble::print(raw_ostream &OS) const { OS << getName() << " ensemble:\n"; for (unsigned i = 0, e = BlockInfo.size(); i != e; ++i) { -- cgit v1.1 From a35bf506f41f4231dc649f3af5255e0b1087b2e3 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Fri, 10 Aug 2012 22:27:29 +0000 Subject: Give MachineTraceMetrics its own debug tag. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@161712 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/MachineTraceMetrics.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/CodeGen/MachineTraceMetrics.cpp') diff --git a/lib/CodeGen/MachineTraceMetrics.cpp b/lib/CodeGen/MachineTraceMetrics.cpp index fc858be..1a3aa60 100644 --- a/lib/CodeGen/MachineTraceMetrics.cpp +++ b/lib/CodeGen/MachineTraceMetrics.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "early-ifcvt" +#define DEBUG_TYPE "machine-trace-metrics" #include "MachineTraceMetrics.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineBranchProbabilityInfo.h" -- cgit v1.1