summaryrefslogtreecommitdiffstats
path: root/llvm/tools
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/tools')
-rw-r--r--llvm/tools/llvm-mca/CMakeLists.txt1
-rw-r--r--llvm/tools/llvm-mca/InstrBuilder.h7
-rw-r--r--llvm/tools/llvm-mca/InstructionTables.cpp80
-rw-r--r--llvm/tools/llvm-mca/InstructionTables.h47
-rw-r--r--llvm/tools/llvm-mca/llvm-mca.cpp22
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);
OpenPOWER on IntegriCloud