diff options
Diffstat (limited to 'llvm/tools/llvm-mca')
-rw-r--r-- | llvm/tools/llvm-mca/CMakeLists.txt | 1 | ||||
-rw-r--r-- | llvm/tools/llvm-mca/InstrBuilder.h | 7 | ||||
-rw-r--r-- | llvm/tools/llvm-mca/InstructionTables.cpp | 80 | ||||
-rw-r--r-- | llvm/tools/llvm-mca/InstructionTables.h | 47 | ||||
-rw-r--r-- | llvm/tools/llvm-mca/llvm-mca.cpp | 22 |
5 files changed, 156 insertions, 1 deletions
diff --git a/llvm/tools/llvm-mca/CMakeLists.txt b/llvm/tools/llvm-mca/CMakeLists.txt index 9358c083f1d..36af64c0bd8 100644 --- a/llvm/tools/llvm-mca/CMakeLists.txt +++ b/llvm/tools/llvm-mca/CMakeLists.txt @@ -18,6 +18,7 @@ add_llvm_tool(llvm-mca InstrBuilder.cpp Instruction.cpp InstructionInfoView.cpp + InstructionTables.cpp LSUnit.cpp llvm-mca.cpp ResourcePressureView.cpp diff --git a/llvm/tools/llvm-mca/InstrBuilder.h b/llvm/tools/llvm-mca/InstrBuilder.h index a74e0af6c2c..a3b7001b86b 100644 --- a/llvm/tools/llvm-mca/InstrBuilder.h +++ b/llvm/tools/llvm-mca/InstrBuilder.h @@ -51,6 +51,13 @@ public: } const InstrDesc &getOrCreateInstrDesc(const llvm::MCInst &MCI); + // Returns an array of processor resource masks. + // Masks are computed by function mca::computeProcResourceMasks. see + // Support.h for a description of how masks are computed and how masks can be + // used to solve set membership problems. + llvm::ArrayRef<uint64_t> getProcResourceMasks() const { + return ProcResourceMasks; + } std::unique_ptr<Instruction> createInstruction(unsigned Idx, const llvm::MCInst &MCI); diff --git a/llvm/tools/llvm-mca/InstructionTables.cpp b/llvm/tools/llvm-mca/InstructionTables.cpp new file mode 100644 index 00000000000..044b516db5d --- /dev/null +++ b/llvm/tools/llvm-mca/InstructionTables.cpp @@ -0,0 +1,80 @@ +//===--------------------- InstructionTables.cpp ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// This file implements method InstructionTables::run(). +/// Method run() prints a theoretical resource pressure distribution based on +/// the information available in the scheduling model, and without running +/// the backend pipeline. +/// +//===----------------------------------------------------------------------===// + +#include "InstructionTables.h" + +namespace mca { + +using namespace llvm; + +using ResourceRef = std::pair<uint64_t, uint64_t>; + +void InstructionTables::run() { + ArrayRef<uint64_t> Masks = IB.getProcResourceMasks(); + SmallVector<std::pair<ResourceRef, double>, 4> UsedResources; + + // Create an instruction descriptor for every instruction in the sequence. + while (S.hasNext()) { + UsedResources.clear(); + InstRef IR = S.peekNext(); + std::unique_ptr<Instruction> Inst = IB.createInstruction(IR.first, *IR.second); + const InstrDesc &Desc = Inst->getDesc(); + // Now identify the resources consumed by this instruction. + for (const std::pair<uint64_t, ResourceUsage> Resource : Desc.Resources) { + // Skip zero-cycle resources (i.e. unused resources). + if (!Resource.second.size()) + continue; + double Cycles = static_cast<double>(Resource.second.size()); + unsigned Index = + std::distance(Masks.begin(), std::find(Masks.begin(), Masks.end(), + Resource.first)); + const MCProcResourceDesc &ProcResource = *SM.getProcResource(Index); + unsigned NumUnits = ProcResource.NumUnits; + if (!ProcResource.SubUnitsIdxBegin) { + // The number of cycles consumed by each unit. + Cycles /= NumUnits; + for (unsigned I = 0, E = NumUnits; I < E; ++I) { + ResourceRef ResourceUnit = std::make_pair(Index, 1U << I); + UsedResources.emplace_back(std::make_pair(ResourceUnit, Cycles)); + } + continue; + } + + // This is a group. Obtain the set of resources contained in this + // group. Some of these resources may implement multiple units. + // Uniformly distribute Cycles across all of the units. + for (unsigned I1 = 0; I1 < NumUnits; ++I1) { + unsigned SubUnitIdx = ProcResource.SubUnitsIdxBegin[I1]; + const MCProcResourceDesc &SubUnit = *SM.getProcResource(SubUnitIdx); + // Compute the number of cycles consumed by each resource unit. + double RUCycles = Cycles / (NumUnits * SubUnit.NumUnits); + for (unsigned I2 = 0, E2 = SubUnit.NumUnits; I2 < E2; ++I2) { + ResourceRef ResourceUnit = std::make_pair(SubUnitIdx, 1U << I2); + UsedResources.emplace_back(std::make_pair(ResourceUnit, RUCycles)); + } + } + } + + // Now send a fake instruction issued event to all the listeners. + HWInstructionIssuedEvent Event(IR.first, UsedResources); + for (HWEventListener *Listener : Listeners) + Listener->onInstructionEvent(Event); + S.updateNext(); + } +} + +} // namespace mca diff --git a/llvm/tools/llvm-mca/InstructionTables.h b/llvm/tools/llvm-mca/InstructionTables.h new file mode 100644 index 00000000000..97dd9b8fc58 --- /dev/null +++ b/llvm/tools/llvm-mca/InstructionTables.h @@ -0,0 +1,47 @@ +//===--------------------- InstructionTables.h ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// This file implements a custom driver to generate instruction tables. +/// See the description of command-line flag -instruction-tables in +/// docs/CommandGuide/lvm-mca.rst +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_LLVM_MCA_INSTRUCTIONTABLES_H +#define LLVM_TOOLS_LLVM_MCA_INSTRUCTIONTABLES_H + +#include "HWEventListener.h" +#include "InstrBuilder.h" +#include "SourceMgr.h" +#include "llvm/MC/MCSchedule.h" + +namespace mca { + +class InstructionTables { + const llvm::MCSchedModel &SM; + InstrBuilder &IB; + SourceMgr &S; + std::set<HWEventListener *> Listeners; + +public: + InstructionTables(const llvm::MCSchedModel &Model, InstrBuilder &Builder, + SourceMgr &Source) + : SM(Model), IB(Builder), S(Source) {} + + void addEventListener(HWEventListener *Listener) { + if (Listener) + Listeners.insert(Listener); + } + + void run(); +}; +} // namespace mca + +#endif diff --git a/llvm/tools/llvm-mca/llvm-mca.cpp b/llvm/tools/llvm-mca/llvm-mca.cpp index b397a4c8095..127b22f67f4 100644 --- a/llvm/tools/llvm-mca/llvm-mca.cpp +++ b/llvm/tools/llvm-mca/llvm-mca.cpp @@ -24,6 +24,7 @@ #include "BackendPrinter.h" #include "BackendStatistics.h" #include "InstructionInfoView.h" +#include "InstructionTables.h" #include "ResourcePressureView.h" #include "SummaryView.h" #include "TimelineView.h" @@ -121,9 +122,15 @@ static cl::opt<bool> AssumeNoAlias( static cl::opt<unsigned> LoadQueueSize("lqueue", cl::desc("Size of the load queue"), cl::init(0)); + static cl::opt<unsigned> StoreQueueSize("squeue", cl::desc("Size of the store queue"), cl::init(0)); +static cl::opt<bool> + PrintInstructionTables("instruction-tables", + cl::desc("Print instruction tables"), + cl::init(false)); + static const Target *getTarget(const char *ProgName) { TripleName = Triple::normalize(TripleName); if (TripleName.empty()) @@ -260,8 +267,9 @@ int main(int argc, char **argv) { MOFI.InitMCObjectFileInfo(TheTriple, /* PIC= */ false, Ctx); std::unique_ptr<buffer_ostream> BOS; + std::unique_ptr<mca::SourceMgr> S = - llvm::make_unique<mca::SourceMgr>(Iterations); + llvm::make_unique<mca::SourceMgr>(PrintInstructionTables ? 1 : Iterations); MCStreamerWrapper Str(Ctx, S->getSequence()); std::unique_ptr<MCInstrInfo> MCII(TheTarget->createMCInstrInfo()); @@ -326,6 +334,18 @@ int main(int argc, char **argv) { std::unique_ptr<mca::InstrBuilder> IB = llvm::make_unique<mca::InstrBuilder>(*STI, *MCII); + if (PrintInstructionTables) { + mca::InstructionTables IT(STI->getSchedModel(), *IB, *S); + mca::ResourcePressureView RPV(*STI, *IP, *S); + mca::InstructionInfoView IIV(*STI, *MCII, *S, *IP); + IT.addEventListener(&IIV); + IT.addEventListener(&RPV); + IT.run(); + RPV.printView(TOF->os()); + TOF->keep(); + return 0; + } + std::unique_ptr<mca::Backend> B = llvm::make_unique<mca::Backend>( *STI, *MRI, *IB, *S, Width, RegisterFileSize, MaxRetirePerCycle, LoadQueueSize, StoreQueueSize, AssumeNoAlias); |