[llvm] cc8fafa - [llvm-exegesis] Make a few counter methods virtual to allow targets to provide target-specific support.
Vy Nguyen via llvm-commits
llvm-commits at lists.llvm.org
Thu May 28 09:38:39 PDT 2020
Author: Vy Nguyen
Date: 2020-05-28T12:38:25-04:00
New Revision: cc8fafa2be8d5315cc55aec54b2a6d7e60f470c4
URL: https://github.com/llvm/llvm-project/commit/cc8fafa2be8d5315cc55aec54b2a6d7e60f470c4
DIFF: https://github.com/llvm/llvm-project/commit/cc8fafa2be8d5315cc55aec54b2a6d7e60f470c4.diff
LOG: [llvm-exegesis] Make a few counter methods virtual to allow targets to provide target-specific support.
Misc: Also include errno in failure message.
Differential Revision: https://reviews.llvm.org/D80610
Added:
Modified:
llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
llvm/tools/llvm-exegesis/lib/PerfHelper.cpp
llvm/tools/llvm-exegesis/lib/PerfHelper.h
llvm/tools/llvm-exegesis/lib/Target.cpp
llvm/tools/llvm-exegesis/lib/Target.h
Removed:
################################################################################
diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
index 9592fd8faa0c..522d4210245c 100644
--- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
+++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include <array>
+#include <memory>
#include <string>
#include "Assembler.h"
@@ -14,11 +15,13 @@
#include "Error.h"
#include "MCInstrDescView.h"
#include "PerfHelper.h"
+#include "Target.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/CrashRecoveryContext.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Program.h"
@@ -38,7 +41,7 @@ class FunctionExecutorImpl : public BenchmarkRunner::FunctionExecutor {
FunctionExecutorImpl(const LLVMState &State,
object::OwningBinary<object::ObjectFile> Obj,
BenchmarkRunner::ScratchSpace *Scratch)
- : Function(State.createTargetMachine(), std::move(Obj)),
+ : State(State), Function(State.createTargetMachine(), std::move(Obj)),
Scratch(Scratch) {}
private:
@@ -51,30 +54,33 @@ class FunctionExecutorImpl : public BenchmarkRunner::FunctionExecutor {
char *const ScratchPtr = Scratch->ptr();
for (auto &CounterName : CounterNames) {
CounterName = CounterName.trim();
- pfm::PerfEvent PerfEvent(CounterName);
- if (!PerfEvent.valid())
- return make_error<Failure>(
- Twine("invalid perf event '").concat(CounterName).concat("'"));
- pfm::Counter Counter(std::move(PerfEvent));
+ auto CounterOrError =
+ State.getExegesisTarget().createCounter(CounterName.data(), State);
+
+ if (!CounterOrError)
+ return CounterOrError.takeError();
+
+ pfm::Counter *Counter = CounterOrError.get().get();
Scratch->clear();
{
CrashRecoveryContext CRC;
CrashRecoveryContext::Enable();
- const bool Crashed = !CRC.RunSafely([this, &Counter, ScratchPtr]() {
- Counter.start();
+ const bool Crashed = !CRC.RunSafely([this, Counter, ScratchPtr]() {
+ Counter->start();
this->Function(ScratchPtr);
- Counter.stop();
+ Counter->stop();
});
CrashRecoveryContext::Disable();
// FIXME: Better diagnosis.
if (Crashed)
return make_error<SnippetCrash>("snippet crashed while running");
}
- CounterValue += Counter.read();
+ CounterValue += Counter->read();
}
return CounterValue;
}
+ const LLVMState &State;
const ExecutableFunction Function;
BenchmarkRunner::ScratchSpace *const Scratch;
};
diff --git a/llvm/tools/llvm-exegesis/lib/PerfHelper.cpp b/llvm/tools/llvm-exegesis/lib/PerfHelper.cpp
index c36bd5c8b9c3..c372ac4f364e 100644
--- a/llvm/tools/llvm-exegesis/lib/PerfHelper.cpp
+++ b/llvm/tools/llvm-exegesis/lib/PerfHelper.cpp
@@ -8,13 +8,19 @@
#include "PerfHelper.h"
#include "llvm/Config/config.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/raw_ostream.h"
#ifdef HAVE_LIBPFM
#include "perfmon/perf_event.h"
#include "perfmon/pfmlib.h"
#include "perfmon/pfmlib_perf_event.h"
#endif
+
#include <cassert>
+#include <cstddef>
+#include <errno.h> // for erno
+#include <string.h> // for strerror()
namespace llvm {
namespace exegesis {
@@ -97,7 +103,8 @@ Counter::Counter(PerfEvent &&E) : Event(std::move(E)){
perf_event_attr AttrCopy = *Event.attribute();
FileDescriptor = perf_event_open(&AttrCopy, Pid, Cpu, GroupFd, Flags);
if (FileDescriptor == -1) {
- errs() << "Unable to open event, make sure your kernel allows user "
+ errs() << "Unable to open event. ERRNO: " << strerror(errno)
+ << ". Make sure your kernel allows user "
"space perf monitoring.\nYou may want to try:\n$ sudo sh "
"-c 'echo -1 > /proc/sys/kernel/perf_event_paranoid'\n";
}
@@ -111,12 +118,21 @@ void Counter::start() { ioctl(FileDescriptor, PERF_EVENT_IOC_RESET, 0); }
void Counter::stop() { ioctl(FileDescriptor, PERF_EVENT_IOC_DISABLE, 0); }
int64_t Counter::read() const {
+ auto ValueOrError = readOrError();
+ if (ValueOrError)
+ return ValueOrError.get();
+
+ errs() << ValueOrError.takeError() << "\n";
+ return -1;
+}
+
+llvm::Expected<int64_t> Counter::readOrError() const {
int64_t Count = 0;
ssize_t ReadSize = ::read(FileDescriptor, &Count, sizeof(Count));
- if (ReadSize != sizeof(Count)) {
- Count = -1;
- errs() << "Failed to read event counter\n";
- }
+ if (ReadSize != sizeof(Count))
+ return llvm::make_error<llvm::StringError>("Failed to read event counter",
+ llvm::errc::io_error);
+
return Count;
}
@@ -132,6 +148,11 @@ void Counter::stop() {}
int64_t Counter::read() const { return 42; }
+llvm::Expected<int64_t> Counter::readOrError() const {
+ return llvm::make_error<llvm::StringError>("Not implemented",
+ llvm::errc::io_error);
+}
+
#endif
} // namespace pfm
diff --git a/llvm/tools/llvm-exegesis/lib/PerfHelper.h b/llvm/tools/llvm-exegesis/lib/PerfHelper.h
index 99c555587c53..7562af9c4524 100644
--- a/llvm/tools/llvm-exegesis/lib/PerfHelper.h
+++ b/llvm/tools/llvm-exegesis/lib/PerfHelper.h
@@ -17,6 +17,8 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Config/config.h"
+#include "llvm/Support/Error.h"
+#include <cstdint>
#include <functional>
#include <memory>
@@ -36,7 +38,7 @@ class PerfEvent {
public:
// http://perfmon2.sourceforge.net/manv4/libpfm.html
// Events are expressed as strings. e.g. "INSTRUCTION_RETIRED"
- explicit PerfEvent(StringRef pfm_event_string);
+ explicit PerfEvent(StringRef PfmEventString);
PerfEvent(const PerfEvent &) = delete;
PerfEvent(PerfEvent &&other);
@@ -63,18 +65,27 @@ class PerfEvent {
// Uses a valid PerfEvent to configure the Kernel so we can measure the
// underlying event.
-struct Counter {
+class Counter {
+public:
// event: the PerfEvent to measure.
explicit Counter(PerfEvent &&event);
Counter(const Counter &) = delete;
Counter(Counter &&other) = default;
- ~Counter();
+ virtual ~Counter();
+
+ /// Starts the measurement of the event.
+ virtual void start();
+
+ /// Stops the measurement of the event.
+ void stop();
+
+ /// Returns the current value of the counter or -1 if it cannot be read.
+ int64_t read() const;
- void start(); // Starts the measurement of the event.
- void stop(); // Stops the measurement of the event.
- int64_t read() const; // Return the current value of the counter.
+ /// Returns the current value of the counter or error if it cannot be read.
+ virtual llvm::Expected<int64_t> readOrError() const;
private:
PerfEvent Event;
diff --git a/llvm/tools/llvm-exegesis/lib/Target.cpp b/llvm/tools/llvm-exegesis/lib/Target.cpp
index 4e0de9375669..61821bf4bb4d 100644
--- a/llvm/tools/llvm-exegesis/lib/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/Target.cpp
@@ -11,6 +11,8 @@
#include "ParallelSnippetGenerator.h"
#include "SerialSnippetGenerator.h"
#include "UopsBenchmarkRunner.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/Error.h"
namespace llvm {
namespace exegesis {
@@ -27,6 +29,19 @@ const ExegesisTarget *ExegesisTarget::lookup(Triple TT) {
return nullptr;
}
+Expected<std::unique_ptr<pfm::Counter>>
+ExegesisTarget::createCounter(const char *CounterName,
+ const LLVMState &) const {
+ pfm::PerfEvent Event(CounterName);
+ if (!Event.valid())
+ return llvm::make_error<Failure>(
+ llvm::Twine("Unable to create counter with name '")
+ .concat(CounterName)
+ .concat("'"));
+
+ return std::make_unique<pfm::Counter>(std::move(Event));
+}
+
void ExegesisTarget::registerTarget(ExegesisTarget *Target) {
if (FirstTarget == nullptr) {
FirstTarget = Target;
diff --git a/llvm/tools/llvm-exegesis/lib/Target.h b/llvm/tools/llvm-exegesis/lib/Target.h
index 298cfac23e81..937b88ddb4cc 100644
--- a/llvm/tools/llvm-exegesis/lib/Target.h
+++ b/llvm/tools/llvm-exegesis/lib/Target.h
@@ -20,6 +20,7 @@
#include "BenchmarkRunner.h"
#include "Error.h"
#include "LlvmState.h"
+#include "PerfHelper.h"
#include "SnippetGenerator.h"
#include "llvm/ADT/Triple.h"
#include "llvm/CodeGen/TargetPassConfig.h"
@@ -27,6 +28,7 @@
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/Support/Error.h"
namespace llvm {
namespace exegesis {
@@ -65,6 +67,10 @@ class ExegesisTarget {
explicit ExegesisTarget(ArrayRef<CpuAndPfmCounters> CpuPfmCounters)
: CpuPfmCounters(CpuPfmCounters) {}
+ // Targets can use this to create target-specific perf counters.
+ virtual Expected<std::unique_ptr<pfm::Counter>>
+ createCounter(const char *CounterName, const LLVMState &State) const;
+
// Targets can use this to add target-specific passes in assembleToStream();
virtual void addTargetSpecificPasses(PassManagerBase &PM) const {}
More information about the llvm-commits
mailing list