diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h --- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h +++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h @@ -89,8 +89,15 @@ public: virtual ~FunctionExecutor(); + Expected> + runAndSample(const char *Counters) const; + + protected: + static void + accumulateCounterValues(const llvm::SmallVectorImpl &NewValues, + llvm::SmallVectorImpl *Result); virtual Expected> - runAndSample(const char *Counters) const = 0; + runWithCounter(StringRef CounterName) const = 0; }; protected: diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp --- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp +++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp @@ -37,6 +37,34 @@ BenchmarkRunner::~BenchmarkRunner() = default; +void BenchmarkRunner::FunctionExecutor::accumulateCounterValues( + const llvm::SmallVectorImpl &NewValues, + llvm::SmallVectorImpl *Result) { + const size_t NumValues = std::max(NewValues.size(), Result->size()); + if (NumValues > Result->size()) + Result->resize(NumValues, 0); + for (size_t I = 0, End = NewValues.size(); I < End; ++I) + (*Result)[I] += NewValues[I]; +} + +Expected> +BenchmarkRunner::FunctionExecutor::runAndSample(const char *Counters) const { + // We sum counts when there are several counters for a single ProcRes + // (e.g. P23 on SandyBridge). + llvm::SmallVector CounterValues; + SmallVector CounterNames; + StringRef(Counters).split(CounterNames, '+'); + for (auto &CounterName : CounterNames) { + CounterName = CounterName.trim(); + Expected> ValueOrError = + runWithCounter(CounterName); + if (!ValueOrError) + return ValueOrError.takeError(); + accumulateCounterValues(ValueOrError.get(), &CounterValues); + } + return CounterValues; +}; + namespace { class FunctionExecutorImpl : public BenchmarkRunner::FunctionExecutor { public: @@ -58,67 +86,43 @@ } Expected> - runAndSample(const char *Counters) const override { - // We sum counts when there are several counters for a single ProcRes - // (e.g. P23 on SandyBridge). - llvm::SmallVector CounterValues; - int Reserved = 0; - SmallVector CounterNames; - StringRef(Counters).split(CounterNames, '+'); - char *const ScratchPtr = Scratch->ptr(); + runWithCounter(StringRef CounterName) const override { const ExegesisTarget &ET = State.getExegesisTarget(); - for (auto &CounterName : CounterNames) { - CounterName = CounterName.trim(); - auto CounterOrError = ET.createCounter(CounterName, State); - - if (!CounterOrError) - return CounterOrError.takeError(); - - pfm::Counter *Counter = CounterOrError.get().get(); - if (Reserved == 0) { - Reserved = Counter->numValues(); - CounterValues.reserve(Reserved); - } else if (Reserved != Counter->numValues()) - // It'd be wrong to accumulate vectors of different sizes. - return make_error( - llvm::Twine("Inconsistent number of values for counter ") - .concat(CounterName) - .concat(std::to_string(Counter->numValues())) - .concat(" vs expected of ") - .concat(std::to_string(Reserved))); - Scratch->clear(); - { - auto PS = ET.withSavedState(); - CrashRecoveryContext CRC; - CrashRecoveryContext::Enable(); - const bool Crashed = !CRC.RunSafely([this, Counter, ScratchPtr]() { - Counter->start(); - this->Function(ScratchPtr); - Counter->stop(); - }); - CrashRecoveryContext::Disable(); - PS.reset(); - if (Crashed) { - std::string Msg = "snippet crashed while running"; + char *const ScratchPtr = Scratch->ptr(); + auto CounterOrError = ET.createCounter(CounterName, State); + + if (!CounterOrError) + return CounterOrError.takeError(); + + pfm::Counter *Counter = CounterOrError.get().get(); + Scratch->clear(); + { + auto PS = ET.withSavedState(); + CrashRecoveryContext CRC; + CrashRecoveryContext::Enable(); + const bool Crashed = !CRC.RunSafely([this, Counter, ScratchPtr]() { + Counter->start(); + this->Function(ScratchPtr); + Counter->stop(); + }); + CrashRecoveryContext::Disable(); + PS.reset(); + if (Crashed) { + std::string Msg = "snippet crashed while running"; #ifdef LLVM_ON_UNIX - // See "Exit Status for Commands": - // https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xcu_chap02.html - constexpr const int kSigOffset = 128; - if (const char *const SigName = strsignal(CRC.RetCode - kSigOffset)) { - Msg += ": "; - Msg += SigName; - } -#endif - return make_error(std::move(Msg)); + // See "Exit Status for Commands": + // https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xcu_chap02.html + constexpr const int kSigOffset = 128; + if (const char *const SigName = strsignal(CRC.RetCode - kSigOffset)) { + Msg += ": "; + Msg += SigName; } +#endif + return make_error(std::move(Msg)); } - - auto ValueOrError = Counter->readOrError(Function.getFunctionBytes()); - if (!ValueOrError) - return ValueOrError.takeError(); - accumulateCounterValues(ValueOrError.get(), &CounterValues); } - return CounterValues; + + return Counter->readOrError(Function.getFunctionBytes()); } const LLVMState &State;