[MCSched] Bind PFM Counters to the CPUs instead of the SchedModel.
Summary:
The pfm counters are now in the ExegesisTarget rather than the
MCSchedModel (PR39165).
This also compresses the pfm counter tables (PR37068).
Reviewers: RKSimon, gchatelet
Subscribers: mgrang, llvm-commits
Differential Revision: https://reviews.llvm.org/D52932
llvm-svn: 345243
diff --git a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
index be8f0b4..0197420 100644
--- a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
@@ -53,6 +53,10 @@
} // namespace
class ExegesisAArch64Target : public ExegesisTarget {
+public:
+ ExegesisAArch64Target() : ExegesisTarget({}) {}
+
+private:
std::vector<llvm::MCInst> setRegTo(const llvm::MCSubtargetInfo &STI,
unsigned Reg,
const llvm::APInt &Value) const override {
diff --git a/llvm/tools/llvm-exegesis/lib/Latency.cpp b/llvm/tools/llvm-exegesis/lib/Latency.cpp
index 602b379..3d18e37 100644
--- a/llvm/tools/llvm-exegesis/lib/Latency.cpp
+++ b/llvm/tools/llvm-exegesis/lib/Latency.cpp
@@ -12,6 +12,8 @@
#include "Assembler.h"
#include "BenchmarkRunner.h"
#include "MCInstrDescView.h"
+#include "PerfHelper.h"
+#include "Target.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstBuilder.h"
@@ -165,12 +167,7 @@
}
const char *LatencyBenchmarkRunner::getCounterName() const {
- if (!State.getSubtargetInfo().getSchedModel().hasExtraProcessorInfo())
- llvm::report_fatal_error("sched model is missing extra processor info!");
- const char *CounterName = State.getSubtargetInfo()
- .getSchedModel()
- .getExtraProcessorInfo()
- .PfmCounters.CycleCounter;
+ const char *CounterName = State.getPfmCounters().CycleCounter;
if (!CounterName)
llvm::report_fatal_error("sched model does not define a cycle counter");
return CounterName;
diff --git a/llvm/tools/llvm-exegesis/lib/LlvmState.cpp b/llvm/tools/llvm-exegesis/lib/LlvmState.cpp
index 58e9db3..b5580c8 100644
--- a/llvm/tools/llvm-exegesis/lib/LlvmState.cpp
+++ b/llvm/tools/llvm-exegesis/lib/LlvmState.cpp
@@ -36,14 +36,17 @@
llvm::errs() << "no exegesis target for " << Triple << ", using default\n";
TheExegesisTarget = &ExegesisTarget::getDefault();
}
+ PfmCounters = &TheExegesisTarget->getPfmCounters(CpuName);
+
RATC.reset(new RegisterAliasingTrackerCache(
getRegInfo(), getFunctionReservedRegs(getTargetMachine())));
IC.reset(new InstructionsCache(getInstrInfo(), getRATC()));
}
-LLVMState::LLVMState()
+LLVMState::LLVMState(const std::string &CpuName)
: LLVMState(llvm::sys::getProcessTriple(),
- llvm::sys::getHostCPUName().str()) {}
+ CpuName.empty() ? llvm::sys::getHostCPUName().str() : CpuName) {
+}
std::unique_ptr<llvm::LLVMTargetMachine>
LLVMState::createTargetMachine() const {
diff --git a/llvm/tools/llvm-exegesis/lib/LlvmState.h b/llvm/tools/llvm-exegesis/lib/LlvmState.h
index 9187385..be1e797 100644
--- a/llvm/tools/llvm-exegesis/lib/LlvmState.h
+++ b/llvm/tools/llvm-exegesis/lib/LlvmState.h
@@ -30,12 +30,14 @@
namespace exegesis {
class ExegesisTarget;
+class PfmCountersInfo;
// An object to initialize LLVM and prepare objects needed to run the
// measurements.
class LLVMState {
public:
- LLVMState();
+ // Uses the host triple. If CpuName is empty, uses the host CPU.
+ LLVMState(const std::string &CpuName);
LLVMState(const std::string &Triple,
const std::string &CpuName); // For tests.
@@ -57,14 +59,18 @@
const llvm::MCSubtargetInfo &getSubtargetInfo() const {
return *TargetMachine->getMCSubtargetInfo();
}
+
const RegisterAliasingTrackerCache &getRATC() const { return *RATC; }
const InstructionsCache &getIC() const { return *IC; }
+ const PfmCountersInfo &getPfmCounters() const { return *PfmCounters; }
+
private:
const ExegesisTarget *TheExegesisTarget;
std::unique_ptr<const llvm::TargetMachine> TargetMachine;
std::unique_ptr<const RegisterAliasingTrackerCache> RATC;
std::unique_ptr<const InstructionsCache> IC;
+ const PfmCountersInfo *PfmCounters;
};
} // namespace exegesis
diff --git a/llvm/tools/llvm-exegesis/lib/Target.cpp b/llvm/tools/llvm-exegesis/lib/Target.cpp
index b7828a1..588c40e 100644
--- a/llvm/tools/llvm-exegesis/lib/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/Target.cpp
@@ -85,10 +85,37 @@
return llvm::make_unique<UopsBenchmarkRunner>(State);
}
+static_assert(std::is_pod<PfmCountersInfo>::value,
+ "We shouldn't have dynamic initialization here");
+const PfmCountersInfo PfmCountersInfo::Default = {nullptr, nullptr, nullptr};
+
+const PfmCountersInfo &
+ExegesisTarget::getPfmCounters(llvm::StringRef CpuName) const {
+ assert(std::is_sorted(
+ CpuPfmCounters.begin(), CpuPfmCounters.end(),
+ [](const CpuAndPfmCounters &LHS, const CpuAndPfmCounters &RHS) {
+ return strcmp(LHS.CpuName, RHS.CpuName) < 0;
+ }) &&
+ "CpuPfmCounters table is not sorted");
+
+ // Find entry
+ auto Found =
+ std::lower_bound(CpuPfmCounters.begin(), CpuPfmCounters.end(), CpuName);
+ if (Found == CpuPfmCounters.end() ||
+ llvm::StringRef(Found->CpuName) != CpuName) {
+ return PfmCountersInfo::Default;
+ }
+ assert(Found->PCI && "Missing counters");
+ return *Found->PCI;
+}
+
namespace {
// Default implementation.
class ExegesisDefaultTarget : public ExegesisTarget {
+public:
+ ExegesisDefaultTarget() : ExegesisTarget({}) {}
+
private:
std::vector<llvm::MCInst> setRegTo(const llvm::MCSubtargetInfo &STI,
unsigned Reg,
diff --git a/llvm/tools/llvm-exegesis/lib/Target.h b/llvm/tools/llvm-exegesis/lib/Target.h
index 2e94727..a6ec36b 100644
--- a/llvm/tools/llvm-exegesis/lib/Target.h
+++ b/llvm/tools/llvm-exegesis/lib/Target.h
@@ -31,8 +31,42 @@
namespace llvm {
namespace exegesis {
+struct PfmCountersInfo {
+ // An optional name of a performance counter that can be used to measure
+ // cycles.
+ const char *const CycleCounter;
+
+ // An optional name of a performance counter that can be used to measure
+ // uops.
+ const char *const UopsCounter;
+
+ // An IssueCounter specifies how to measure uops issued to specific proc
+ // resources.
+ struct IssueCounter {
+ const char *const Counter;
+ // The name of the ProcResource that this counter measures.
+ const char *const ProcResName;
+ };
+ // An optional list of IssueCounters.
+ const IssueCounter *const IssueCounters;
+ const unsigned NumIssueCounters;
+
+ static const PfmCountersInfo Default;
+};
+
+struct CpuAndPfmCounters {
+ const char *const CpuName;
+ const PfmCountersInfo *const PCI;
+ bool operator<(llvm::StringRef S) const {
+ return llvm::StringRef(CpuName) < S;
+ }
+};
+
class ExegesisTarget {
public:
+ explicit ExegesisTarget(llvm::ArrayRef<CpuAndPfmCounters> CpuPfmCounters)
+ : CpuPfmCounters(CpuPfmCounters) {}
+
// Targets can use this to add target-specific passes in assembleToStream();
virtual void addTargetSpecificPasses(llvm::PassManagerBase &PM) const {}
@@ -83,6 +117,10 @@
virtual ~ExegesisTarget();
+ // Returns the Pfm counters for the given CPU (or the default if no pfm
+ // counters are defined for this CPU).
+ const PfmCountersInfo &getPfmCounters(llvm::StringRef CpuName) const;
+
private:
virtual bool matchesArch(llvm::Triple::ArchType Arch) const = 0;
@@ -98,6 +136,7 @@
const LLVMState &State) const;
const ExegesisTarget *Next = nullptr;
+ const llvm::ArrayRef<CpuAndPfmCounters> CpuPfmCounters;
};
} // namespace exegesis
diff --git a/llvm/tools/llvm-exegesis/lib/Uops.cpp b/llvm/tools/llvm-exegesis/lib/Uops.cpp
index 5aa7262..9768f45 100644
--- a/llvm/tools/llvm-exegesis/lib/Uops.cpp
+++ b/llvm/tools/llvm-exegesis/lib/Uops.cpp
@@ -223,24 +223,22 @@
llvm::Expected<std::vector<BenchmarkMeasure>>
UopsBenchmarkRunner::runMeasurements(const FunctionExecutor &Executor) const {
- const auto &SchedModel = State.getSubtargetInfo().getSchedModel();
-
std::vector<BenchmarkMeasure> Result;
- const auto &PfmCounters = SchedModel.getExtraProcessorInfo().PfmCounters;
+ const PfmCountersInfo &PCI = State.getPfmCounters();
// Uops per port.
- for (unsigned ProcResIdx = 1;
- ProcResIdx < SchedModel.getNumProcResourceKinds(); ++ProcResIdx) {
- const char *const Counters = PfmCounters.IssueCounters[ProcResIdx];
- if (!Counters)
+ for (const auto *IssueCounter = PCI.IssueCounters,
+ *IssueCounterEnd = PCI.IssueCounters + PCI.NumIssueCounters;
+ IssueCounter != IssueCounterEnd; ++IssueCounter) {
+ if (!IssueCounter->Counter)
continue;
- auto ExpectedCounterValue = Executor.runAndMeasure(Counters);
+ auto ExpectedCounterValue = Executor.runAndMeasure(IssueCounter->Counter);
if (!ExpectedCounterValue)
return ExpectedCounterValue.takeError();
- Result.push_back(BenchmarkMeasure::Create(
- SchedModel.getProcResource(ProcResIdx)->Name, *ExpectedCounterValue));
+ Result.push_back(BenchmarkMeasure::Create(IssueCounter->ProcResName,
+ *ExpectedCounterValue));
}
// NumMicroOps.
- if (const char *const UopsCounter = PfmCounters.UopsCounter) {
+ if (const char *const UopsCounter = PCI.UopsCounter) {
auto ExpectedCounterValue = Executor.runAndMeasure(UopsCounter);
if (!ExpectedCounterValue)
return ExpectedCounterValue.takeError();
diff --git a/llvm/tools/llvm-exegesis/lib/X86/Target.cpp b/llvm/tools/llvm-exegesis/lib/X86/Target.cpp
index 6980484..6ae228e 100644
--- a/llvm/tools/llvm-exegesis/lib/X86/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/X86/Target.cpp
@@ -329,7 +329,13 @@
std::vector<llvm::MCInst> Instructions;
};
+#include "X86GenExegesis.inc"
+
class ExegesisX86Target : public ExegesisTarget {
+public:
+ ExegesisX86Target() : ExegesisTarget(X86CpuPfmCounters) {}
+
+private:
void addTargetSpecificPasses(llvm::PassManagerBase &PM) const override {
// Lowers FP pseudo-instructions, e.g. ABS_Fp32 -> ABS_F.
PM.add(llvm::createX86FloatingPointStackifierPass());
diff --git a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
index 689a1e0..a28e68e 100644
--- a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
+++ b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
@@ -94,6 +94,13 @@
AnalysisInconsistenciesOutputFile("analysis-inconsistencies-output-file",
cl::desc(""), cl::init("-"));
+static cl::opt<std::string>
+ CpuName("mcpu",
+ cl::desc(
+ "cpu name to use for pfm counters, leave empty to autodetect"),
+ cl::init(""));
+
+
static ExitOnError ExitOnErr;
#ifdef LLVM_EXEGESIS_INITIALIZE_NATIVE_TARGET
@@ -321,7 +328,7 @@
LLVM_EXEGESIS_INITIALIZE_NATIVE_TARGET();
#endif
- const LLVMState State;
+ const LLVMState State(CpuName);
const auto Opcodes = getOpcodesOrDie(State.getInstrInfo());
std::vector<BenchmarkCode> Configurations;
@@ -399,7 +406,7 @@
llvm::InitializeNativeTargetAsmPrinter();
llvm::InitializeNativeTargetDisassembler();
// Read benchmarks.
- const LLVMState State;
+ const LLVMState State("");
const std::vector<InstructionBenchmark> Points =
ExitOnErr(InstructionBenchmark::readYamls(State, BenchmarkFile));
llvm::outs() << "Parsed " << Points.size() << " benchmark points\n";