From 2c9dc7bbbf514b1ed7bdefacb3213beae5916b3d Mon Sep 17 00:00:00 2001 From: Michael Liao Date: Wed, 30 Sep 2020 23:15:35 -0400 Subject: [PATCH] Revert "[llvm-exegesis] Add option to check the hardware support for a given feature before benchmarking." This reverts commit 4fcd1a8e6528ca42fe656f2745e15d2b7f5de495 as `llvm/test/tools/llvm-exegesis/X86/lbr/mov-add.s` failed on hosts without LBR supported if the build has LIBPFM enabled. On that host, `perf_event_open` fails with `EOPNOTSUPP` on LBR config. That change's basic assumption > If this is run on a non-supported hardware, it will produce all zeroes for latency. could not stand as `perf_event_open` system call will fail if the underlying hardware really don't have LBR supported. --- .../test/tools/llvm-exegesis/X86/lbr/lit.local.cfg | 4 +- llvm/tools/llvm-exegesis/lib/Target.h | 5 -- llvm/tools/llvm-exegesis/lib/X86/Target.cpp | 17 ------ llvm/tools/llvm-exegesis/lib/X86/X86Counter.cpp | 65 ++++------------------ llvm/tools/llvm-exegesis/lib/X86/X86Counter.h | 5 -- llvm/tools/llvm-exegesis/llvm-exegesis.cpp | 15 ++++- 6 files changed, 25 insertions(+), 86 deletions(-) diff --git a/llvm/test/tools/llvm-exegesis/X86/lbr/lit.local.cfg b/llvm/test/tools/llvm-exegesis/X86/lbr/lit.local.cfg index 69b08f2..431967c 100644 --- a/llvm/test/tools/llvm-exegesis/X86/lbr/lit.local.cfg +++ b/llvm/test/tools/llvm-exegesis/X86/lbr/lit.local.cfg @@ -19,9 +19,9 @@ else: try: with open(os.devnull, 'w') as quiet: check_llvm_exegesis_uops_result = subprocess.call( - [llvm_exegesis_exe, '-mode', 'uops', '-snippets-file', '/dev/null'], stdout=quiet, stderr=quiet) + [llvm_exegesis_exe, '-allowed-host-cpu', 'skylake', '-allowed-host-cpu', 'skylake-avx512', '-mode', 'uops', '-snippets-file', '/dev/null'], stdout=quiet, stderr=quiet) check_llvm_exegesis_latency_result = subprocess.call( - [llvm_exegesis_exe, '-mode', 'latency', '-snippets-file', '/dev/null'], stdout=quiet, stderr=quiet) + [llvm_exegesis_exe, '-allowed-host-cpu', 'skylake', '-allowed-host-cpu', 'skylake-avx512', '-mode', 'latency', '-snippets-file', '/dev/null'], stdout=quiet, stderr=quiet) except OSError: print('could not exec llvm-exegesis') config.unsupported = True diff --git a/llvm/tools/llvm-exegesis/lib/Target.h b/llvm/tools/llvm-exegesis/lib/Target.h index 8a5624b4..7089079 100644 --- a/llvm/tools/llvm-exegesis/lib/Target.h +++ b/llvm/tools/llvm-exegesis/lib/Target.h @@ -142,11 +142,6 @@ public: return {&Instr}; } - // Checks hardware and software support for current benchmark mode. - // Returns an error if the target host does not have support to run the - // benchmark. - virtual Error checkFeatureSupport() const { return Error::success(); } - // Creates a snippet generator for the given mode. std::unique_ptr createSnippetGenerator(InstructionBenchmark::ModeE Mode, diff --git a/llvm/tools/llvm-exegesis/lib/X86/Target.cpp b/llvm/tools/llvm-exegesis/lib/X86/Target.cpp index 270825a..9f045fa 100644 --- a/llvm/tools/llvm-exegesis/lib/X86/Target.cpp +++ b/llvm/tools/llvm-exegesis/lib/X86/Target.cpp @@ -674,23 +674,6 @@ private: return Arch == Triple::x86_64 || Arch == Triple::x86; } - Error checkFeatureSupport() const override { - // LBR is the only feature we conditionally support now. - // So if LBR is not requested, then we should be able to run the benchmarks. - if (LbrSamplingPeriod == 0) - return Error::success(); - -#if defined(__linux__) && defined(HAVE_LIBPFM) && \ - defined(LIBPFM_HAS_FIELD_CYCLES) - // If the kernel supports it, the hardware still may not have it. - return X86LbrCounter::checkLbrSupport(); -#else - return llvm::make_error( - "LBR not supported on this kernel and/or platform", - llvm::errc::not_supported); -#endif - } - static const unsigned kUnavailableRegisters[4]; }; diff --git a/llvm/tools/llvm-exegesis/lib/X86/X86Counter.cpp b/llvm/tools/llvm-exegesis/lib/X86/X86Counter.cpp index 25ec4f8..57b4938 100644 --- a/llvm/tools/llvm-exegesis/lib/X86/X86Counter.cpp +++ b/llvm/tools/llvm-exegesis/lib/X86/X86Counter.cpp @@ -21,7 +21,6 @@ #endif // HAVE_LIBPFM #include -#include #include #include #include @@ -36,8 +35,6 @@ namespace llvm { namespace exegesis { -// Number of entries in the LBR. -static constexpr int kLbrEntries = 16; static constexpr size_t kBufferPages = 8; static const size_t kDataBufferSize = kBufferPages * getpagesize(); @@ -73,6 +70,7 @@ static void copyDataBuffer(void *MMappedBuffer, char *Buf, uint64_t Tail, static llvm::Error parseDataBuffer(const char *DataBuf, size_t DataSize, const void *From, const void *To, llvm::SmallVector *CycleArray) { + assert(From != nullptr && To != nullptr); const char *DataPtr = DataBuf; while (DataPtr < DataBuf + DataSize) { struct perf_event_header Header; @@ -151,47 +149,21 @@ void X86LbrCounter::start() { ioctl(FileDescriptor, PERF_EVENT_IOC_REFRESH, 1024 /* kMaxPollsPerFd */); } -llvm::Error X86LbrCounter::checkLbrSupport() { - // Do a sample read and check if the results contain non-zero values. - - X86LbrCounter counter(X86LbrPerfEvent(123)); - counter.start(); - - // Prevent the compiler from unrolling the loop and get rid of all the - // branches. We need at least 16 iterations. - int Sum = 0; - int V = 1; - - volatile int *P = &V; - auto TimeLimit = - std::chrono::high_resolution_clock::now() + std::chrono::microseconds(5); - - for (int I = 0; - I < kLbrEntries || std::chrono::high_resolution_clock::now() < TimeLimit; - ++I) { - Sum += *P; - } - - counter.stop(); - - auto ResultOrError = counter.doReadCounter(nullptr, nullptr); - if (ResultOrError) - if (!ResultOrError.get().empty()) - // If there is at least one non-zero entry, then LBR is supported. - for (const int64_t &Value : ResultOrError.get()) - if (Value != 0) - return Error::success(); - - return llvm::make_error( - "LBR format with cycles is not suppported on the host.", - llvm::errc::not_supported); -} - llvm::Expected> X86LbrCounter::readOrError(StringRef FunctionBytes) const { + // The max number of time-outs/retries before we give up. + static constexpr int kMaxTimeouts = 160; + // Disable the event before reading ioctl(FileDescriptor, PERF_EVENT_IOC_DISABLE, 0); + // Parses the LBR buffer and fills CycleArray with the sequence of cycle + // counts from the buffer. + llvm::SmallVector CycleArray; + std::unique_ptr DataBuf(new char[kDataBufferSize]); + int NumTimeouts = 0; + int PollResult = 0; + // Find the boundary of the function so that we could filter the LBRs // to keep only the relevant records. if (FunctionBytes.empty()) @@ -200,21 +172,6 @@ X86LbrCounter::readOrError(StringRef FunctionBytes) const { const void *From = reinterpret_cast(FunctionBytes.data()); const void *To = reinterpret_cast(FunctionBytes.data() + FunctionBytes.size()); - return doReadCounter(From, To); -} - -llvm::Expected> -X86LbrCounter::doReadCounter(const void *From, const void *To) const { - // The max number of time-outs/retries before we give up. - static constexpr int kMaxTimeouts = 160; - - // Parses the LBR buffer and fills CycleArray with the sequence of cycle - // counts from the buffer. - llvm::SmallVector CycleArray; - auto DataBuf = std::make_unique(kDataBufferSize); - int NumTimeouts = 0; - int PollResult = 0; - while (PollResult <= 0) { PollResult = pollLbrPerfEvent(FileDescriptor); if (PollResult > 0) diff --git a/llvm/tools/llvm-exegesis/lib/X86/X86Counter.h b/llvm/tools/llvm-exegesis/lib/X86/X86Counter.h index 73e4dc5..9406201 100644 --- a/llvm/tools/llvm-exegesis/lib/X86/X86Counter.h +++ b/llvm/tools/llvm-exegesis/lib/X86/X86Counter.h @@ -33,8 +33,6 @@ public: class X86LbrCounter : public pfm::Counter { public: - static llvm::Error checkLbrSupport(); - explicit X86LbrCounter(pfm::PerfEvent &&Event); virtual ~X86LbrCounter(); @@ -45,9 +43,6 @@ public: readOrError(StringRef FunctionBytes) const override; private: - llvm::Expected> - doReadCounter(const void *From, const void *To) const; - void *MMappedBuffer = nullptr; }; diff --git a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp index bc2f348..fb3f41e1 100644 --- a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp +++ b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp @@ -160,6 +160,12 @@ static cl::opt cl::desc(""), cl::cat(AnalysisOptions), cl::init("")); +static cl::list + AllowedHostCpus("allowed-host-cpu", + cl::desc("If specified, only run the benchmark if the host " + "CPU matches the names"), + cl::cat(Options), cl::ZeroOrMore); + static cl::opt AnalysisDisplayUnstableOpcodes( "analysis-display-unstable-clusters", cl::desc("if there is more than one benchmark for an opcode, said " @@ -296,9 +302,12 @@ void benchmarkMain() { const LLVMState State(CpuName); - // Preliminary check to ensure features needed for requested - // benchmark mode are present on target CPU and/or OS. - ExitOnErr(State.getExegesisTarget().checkFeatureSupport()); + llvm::StringRef ActualCpu = State.getTargetMachine().getTargetCPU(); + for (auto Begin = AllowedHostCpus.begin(); Begin != AllowedHostCpus.end(); + ++Begin) { + if (ActualCpu != *Begin) + ExitWithError(llvm::Twine("Unexpected host CPU ").concat(ActualCpu)); + } const std::unique_ptr Runner = ExitOnErr(State.getExegesisTarget().createBenchmarkRunner( -- 2.7.4