Re-land "[llvm-exegesis] Save target state before running the benchmark.
authorClement Courbet <courbet@google.com>
Mon, 2 Nov 2020 14:31:58 +0000 (15:31 +0100)
committerClement Courbet <courbet@google.com>
Wed, 4 Nov 2020 07:34:33 +0000 (08:34 +0100)
Use `__builtin_ia32_fxsave64` under __GNUC__, (_fxsave64) does not exist in old versions of
gcc (pre-9.1).

This reverts commit e128f9cafca4e72b089fcd1381af5a1ec656d987.

llvm/test/tools/llvm-exegesis/X86/uops-FLDENVm.s [new file with mode: 0644]
llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
llvm/tools/llvm-exegesis/lib/Target.cpp
llvm/tools/llvm-exegesis/lib/Target.h
llvm/tools/llvm-exegesis/lib/X86/Target.cpp

diff --git a/llvm/test/tools/llvm-exegesis/X86/uops-FLDENVm.s b/llvm/test/tools/llvm-exegesis/X86/uops-FLDENVm.s
new file mode 100644 (file)
index 0000000..be182d8
--- /dev/null
@@ -0,0 +1,6 @@
+# RUN: llvm-exegesis -mode=uops -opcode-name=FLDENVm,FLDL2E -repetition-mode=duplicate | FileCheck %s
+
+CHECK:      mode:            uops
+CHECK-NEXT: key:
+CHECK-NEXT:   instructions:
+CHECK-NEXT:     FLDENVm
index 1bbad20..2304e91 100644 (file)
@@ -71,10 +71,10 @@ private:
     SmallVector<StringRef, 2> CounterNames;
     StringRef(Counters).split(CounterNames, '+');
     char *const ScratchPtr = Scratch->ptr();
+    const ExegesisTarget &ET = State.getExegesisTarget();
     for (auto &CounterName : CounterNames) {
       CounterName = CounterName.trim();
-      auto CounterOrError =
-          State.getExegesisTarget().createCounter(CounterName, State);
+      auto CounterOrError = ET.createCounter(CounterName, State);
 
       if (!CounterOrError)
         return CounterOrError.takeError();
@@ -93,6 +93,7 @@ private:
                 .concat(std::to_string(Reserved)));
       Scratch->clear();
       {
+        auto PS = ET.withSavedState();
         CrashRecoveryContext CRC;
         CrashRecoveryContext::Enable();
         const bool Crashed = !CRC.RunSafely([this, Counter, ScratchPtr]() {
@@ -101,6 +102,7 @@ private:
           Counter->stop();
         });
         CrashRecoveryContext::Disable();
+        PS.reset();
         if (Crashed) {
           std::string Msg = "snippet crashed while running";
 #ifdef LLVM_ON_UNIX
index ad26c16..85180a1 100644 (file)
@@ -147,6 +147,8 @@ const PfmCountersInfo &ExegesisTarget::getPfmCounters(StringRef CpuName) const {
   return *Found->PCI;
 }
 
+ExegesisTarget::SavedState::~SavedState() {} // anchor.
+
 namespace {
 
 // Default implementation.
index 8a5624b..28c103a 100644 (file)
@@ -172,6 +172,16 @@ public:
   // counters are defined for this CPU).
   const PfmCountersInfo &getPfmCounters(StringRef CpuName) const;
 
+  // Saves the CPU state that needs to be preserved when running a benchmark,
+  // and returns and RAII object that restores the state on destruction.
+  // By default no state is preserved.
+  struct SavedState {
+    virtual ~SavedState();
+  };
+  virtual std::unique_ptr<SavedState> withSavedState() const {
+    return std::make_unique<SavedState>();
+  }
+
 private:
   virtual bool matchesArch(Triple::ArchType Arch) const = 0;
 
index 827e2e2..8610afd 100644 (file)
@@ -26,6 +26,9 @@
 #include <memory>
 #include <string>
 #include <vector>
+#if defined(_MSC_VER)
+#include <immintrin.h>
+#endif
 
 namespace llvm {
 namespace exegesis {
@@ -594,6 +597,32 @@ void ConstantInliner::initStack(unsigned Bytes) {
 
 namespace {
 
+class X86SavedState : public ExegesisTarget::SavedState {
+public:
+  X86SavedState() {
+#if defined(_MSC_VER)
+    _fxsave64(FPState);
+#elif defined(__GNUC__)
+    __builtin_ia32_fxsave64(FPState);
+#endif
+  }
+
+  ~X86SavedState() {
+    // Restoring the X87 state does not flush pending exceptions, make sure
+    // these exceptions are flushed now.
+#if defined(_MSC_VER)
+    _clearfp();
+    _fxrstor64(FPState);
+#elif defined(__GNUC__)
+    asm volatile("fwait");
+    __builtin_ia32_fxrstor64(FPState);
+#endif
+  }
+
+private:
+  alignas(16) char FPState[512];
+};
+
 class ExegesisX86Target : public ExegesisTarget {
 public:
   ExegesisX86Target() : ExegesisTarget(X86CpuPfmCounters) {}
@@ -691,6 +720,10 @@ private:
 #endif
   }
 
+  std::unique_ptr<SavedState> withSavedState() const override {
+    return std::make_unique<X86SavedState>();
+  }
+
   static const unsigned kUnavailableRegisters[4];
 };