[llvm] [llvm-exegesis] Debug generated disassembly (PR #142540)

Lakshay Kumar via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 1 01:44:50 PDT 2025


https://github.com/lakshayk-nv updated https://github.com/llvm/llvm-project/pull/142540

>From 3c9421c4185a27e8e6256f41b0e9e8898b08ad41 Mon Sep 17 00:00:00 2001
From: lakshayk-nv <lakshayk at nvidia.com>
Date: Fri, 30 May 2025 03:46:29 -0700
Subject: [PATCH 01/24] [llvm-exegesis] Added Debug flag for print disassembly
 using objdump

---
 .../llvm-exegesis/lib/BenchmarkRunner.cpp     | 31 +++++++++++++++++++
 1 file changed, 31 insertions(+)

diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
index a7771b99e97b1..bc2b0b4750e6a 100644
--- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
+++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
@@ -29,6 +29,8 @@
 #include <cmath>
 #include <memory>
 #include <string>
+#include "llvm/Support/Debug.h"
+#define DEBUG_TYPE "exegesis-benchmark-runner"
 
 #ifdef __linux__
 #ifdef HAVE_LIBPFM
@@ -709,6 +711,35 @@ std::pair<Error, Benchmark> BenchmarkRunner::runConfiguration(
     }
     outs() << "Check generated assembly with: /usr/bin/objdump -d "
            << *ObjectFilePath << "\n";
+
+    int StdOutFD, StdErrFD;
+    SmallString<128> StdOutFile, StdErrFile;
+    sys::fs::createTemporaryFile("temp-objdump-out", "txt", StdOutFD, StdOutFile);
+    sys::fs::createTemporaryFile("temp-objdump-err", "txt", StdErrFD, StdErrFile);
+
+    std::vector<std::optional<StringRef>> Redirects = {
+        std::nullopt,           // stdin
+        StringRef(StdOutFile),  // stdout
+        StringRef(StdErrFile)   // stderr
+    };
+
+#ifdef __linux__
+    std::string ErrMsg;
+    int Result = sys::ExecuteAndWait(
+        "/usr/bin/objdump", {"/usr/bin/objdump", "-d", *ObjectFilePath},
+        std::nullopt, Redirects, 0, 0, &ErrMsg);
+    auto StdOutBuf = MemoryBuffer::getFile(StdOutFile);
+    if (StdOutBuf && !(*StdOutBuf)->getBuffer().empty())
+      LLVM_DEBUG(dbgs() << "[llvm-exegesis][objdump] Generated assembly:\n"
+                        << (*StdOutBuf)->getBuffer() << '\n');
+    auto StdErrBuf = MemoryBuffer::getFile(StdErrFile);
+    if (StdErrBuf && !(*StdErrBuf)->getBuffer().empty())
+      LLVM_DEBUG(dbgs() << "[llvm-exegesis][objdump] stderr:\n"
+                        << (*StdErrBuf)->getBuffer() << '\n');
+    if (!ErrMsg.empty())
+      LLVM_DEBUG(dbgs() << "[llvm-exegesis][objdump] process error: " << ErrMsg << '\n');
+#endif
+    sys::fs::remove(StdOutFile); sys::fs::remove(StdErrFile);
   }
 
   if (BenchmarkPhaseSelector < BenchmarkPhaseSelectorE::Measure) {

>From 7d61a14b246ebd6b82fe046d63407a813d65da19 Mon Sep 17 00:00:00 2001
From: lakshayk-nv <lakshayk at nvidia.com>
Date: Mon, 2 Jun 2025 22:53:56 -0700
Subject: [PATCH 02/24] [llvm-exegesis] Formatting changes

---
 .../llvm-exegesis/lib/BenchmarkRunner.cpp     | 23 +++++++++++--------
 1 file changed, 13 insertions(+), 10 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
index bc2b0b4750e6a..7c2a6c966106a 100644
--- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
+++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
@@ -20,6 +20,7 @@
 #include "llvm/ADT/Twine.h"
 #include "llvm/Config/llvm-config.h" // for LLVM_ON_UNIX
 #include "llvm/Support/CrashRecoveryContext.h"
+#include "llvm/Support/Debug.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/MemoryBuffer.h"
@@ -29,7 +30,6 @@
 #include <cmath>
 #include <memory>
 #include <string>
-#include "llvm/Support/Debug.h"
 #define DEBUG_TYPE "exegesis-benchmark-runner"
 
 #ifdef __linux__
@@ -712,18 +712,19 @@ std::pair<Error, Benchmark> BenchmarkRunner::runConfiguration(
     outs() << "Check generated assembly with: /usr/bin/objdump -d "
            << *ObjectFilePath << "\n";
 
+#ifdef __linux__
     int StdOutFD, StdErrFD;
     SmallString<128> StdOutFile, StdErrFile;
-    sys::fs::createTemporaryFile("temp-objdump-out", "txt", StdOutFD, StdOutFile);
-    sys::fs::createTemporaryFile("temp-objdump-err", "txt", StdErrFD, StdErrFile);
-
+    sys::fs::createTemporaryFile("temp-objdump-out", "txt", StdOutFD,
+                                 StdOutFile);
+    sys::fs::createTemporaryFile("temp-objdump-err", "txt", StdErrFD,
+                                 StdErrFile);
     std::vector<std::optional<StringRef>> Redirects = {
-        std::nullopt,           // stdin
-        StringRef(StdOutFile),  // stdout
-        StringRef(StdErrFile)   // stderr
+        std::nullopt,          // stdin
+        StringRef(StdOutFile), // stdout
+        StringRef(StdErrFile)  // stderr
     };
 
-#ifdef __linux__
     std::string ErrMsg;
     int Result = sys::ExecuteAndWait(
         "/usr/bin/objdump", {"/usr/bin/objdump", "-d", *ObjectFilePath},
@@ -737,9 +738,11 @@ std::pair<Error, Benchmark> BenchmarkRunner::runConfiguration(
       LLVM_DEBUG(dbgs() << "[llvm-exegesis][objdump] stderr:\n"
                         << (*StdErrBuf)->getBuffer() << '\n');
     if (!ErrMsg.empty())
-      LLVM_DEBUG(dbgs() << "[llvm-exegesis][objdump] process error: " << ErrMsg << '\n');
+      LLVM_DEBUG(dbgs() << "[llvm-exegesis][objdump] process error: " << ErrMsg
+                        << '\n');
+    sys::fs::remove(StdOutFile);
+    sys::fs::remove(StdErrFile);
 #endif
-    sys::fs::remove(StdOutFile); sys::fs::remove(StdErrFile);
   }
 
   if (BenchmarkPhaseSelector < BenchmarkPhaseSelectorE::Measure) {

>From e53e3c8813d305edc2e1cdbeebc3dde372458c7f Mon Sep 17 00:00:00 2001
From: lakshayk-nv <lakshayk at nvidia.com>
Date: Mon, 30 Jun 2025 20:57:58 -0700
Subject: [PATCH 03/24] [llvm-exegesis] Debug (print or preview) generated
 assembly without external dependency outside llvm project

---
 .../llvm-exegesis/lib/BenchmarkRunner.cpp     | 128 +++++++++++++-----
 llvm/tools/llvm-exegesis/llvm-exegesis.cpp    |   4 +-
 2 files changed, 97 insertions(+), 35 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
index 7c2a6c966106a..6e733f59a6b65 100644
--- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
+++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
@@ -8,6 +8,7 @@
 
 #include "BenchmarkRunner.h"
 #include "Assembler.h"
+#include "DisassemblerHelper.h"
 #include "Error.h"
 #include "MCInstrDescView.h"
 #include "MmapUtils.h"
@@ -18,19 +19,21 @@
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Twine.h"
+#include "llvm/MC/TargetRegistry.h"
 #include "llvm/Config/llvm-config.h" // for LLVM_ON_UNIX
 #include "llvm/Support/CrashRecoveryContext.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/Error.h"
+#include "llvm/Support/Format.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Program.h"
 #include "llvm/Support/Signals.h"
+#include "llvm/Support/TargetSelect.h"
 #include "llvm/Support/SystemZ/zOSSupport.h"
 #include <cmath>
 #include <memory>
 #include <string>
-#define DEBUG_TYPE "exegesis-benchmark-runner"
 
 #ifdef __linux__
 #ifdef HAVE_LIBPFM
@@ -657,8 +660,97 @@ BenchmarkRunner::getRunnableConfiguration(
     if (Error E = Snippet.takeError())
       return std::move(E);
     RC.ObjectFile = getObjectFromBuffer(*Snippet);
-  }
 
+    // Print the assembled snippet by disassembling the binary data
+    // Extract the actual function bytes from the object file
+    std::vector<uint8_t> FunctionBytes;
+    if (auto Err = getBenchmarkFunctionBytes(*Snippet, FunctionBytes)) {
+      dbgs() << "Failed to extract function bytes: " << toString(std::move(Err))
+             << "\n";
+    } else {
+      DisassemblerHelper DisHelper(State);
+      ArrayRef<uint8_t> Bytes(FunctionBytes);
+
+      // Decode all instructions first
+      struct InstructionInfo {
+        std::string Text;
+        uint64_t Address;
+        std::string HexBytes;
+      };
+      std::vector<InstructionInfo> Instructions;
+      uint64_t Address = 0;
+
+      while (!Bytes.empty()) {
+        MCInst Inst;
+        uint64_t Size;
+        if (DisHelper.decodeInst(Inst, Size, Bytes)) {
+          // Format instruction text
+          std::string InstStr;
+          raw_string_ostream OS(InstStr);
+          DisHelper.printInst(&Inst, OS);
+
+          // Create hex string for this instruction (big-endian order)
+          std::string HexStr;
+          raw_string_ostream HexOS(HexStr);
+          for (int i = Size - 1; i >= 0; --i) {
+            HexOS << format_hex_no_prefix(Bytes[i], 2);
+          }
+
+          Instructions.push_back({OS.str(), Address, HexOS.str()});
+          Bytes = Bytes.slice(Size);
+          Address += Size;
+        } else {
+          Instructions.push_back({"<decode error>", Address, ""});
+          break;
+        }
+      }
+
+      auto printSnippet = [&](bool Preview, size_t PreviewFirst = 10,
+                              size_t PreviewLast = 3) {
+        dbgs() << "```\n";
+        size_t N = Instructions.size();
+        // Print first "PreviewFirst" lines or all if less
+        for (size_t i = 0; i < std::min(size_t(PreviewFirst), N); ++i) {
+          dbgs() << format_hex_no_prefix(Instructions[i].Address, 0) << ":\t"
+                 << Instructions[i].HexBytes << Instructions[i].Text << '\n';
+        }
+        if (N > (PreviewFirst + PreviewLast)) {
+          if (Preview) {
+            dbgs() << "...\t(" << (N - PreviewFirst - PreviewLast)
+                   << " more instructions)\n";
+          } else {
+            // Print all middle lines
+            for (size_t i = PreviewFirst; i < N - PreviewLast; ++i) {
+              dbgs() << format_hex_no_prefix(Instructions[i].Address, 0)
+                     << ":\t" << Instructions[i].HexBytes
+                     << Instructions[i].Text << '\n';
+            }
+          }
+          // Print last "PreviewLast" lines
+          for (size_t i = N - PreviewLast; i < N; ++i) {
+            dbgs() << format_hex_no_prefix(Instructions[i].Address, 0) << ":\t"
+                   << Instructions[i].HexBytes << Instructions[i].Text << '\n';
+          }
+        }
+        dbgs() << "```\n";
+      };
+
+      // Preview generated assembly snippet
+      {
+#undef DEBUG_TYPE
+#define DEBUG_TYPE "preview-gen-assembly"
+        LLVM_DEBUG(dbgs() << "Generated assembly snippet:\n");
+        LLVM_DEBUG(printSnippet(true));
+#undef DEBUG_TYPE
+#define DEBUG_TYPE "print-gen-assembly"
+      }
+      // Print generated assembly snippet
+      {
+        LLVM_DEBUG(dbgs() << "Generated assembly snippet:\n");
+        LLVM_DEBUG(printSnippet(false));
+      }
+    }
+  }
   return std::move(RC);
 }
 
@@ -711,38 +803,6 @@ std::pair<Error, Benchmark> BenchmarkRunner::runConfiguration(
     }
     outs() << "Check generated assembly with: /usr/bin/objdump -d "
            << *ObjectFilePath << "\n";
-
-#ifdef __linux__
-    int StdOutFD, StdErrFD;
-    SmallString<128> StdOutFile, StdErrFile;
-    sys::fs::createTemporaryFile("temp-objdump-out", "txt", StdOutFD,
-                                 StdOutFile);
-    sys::fs::createTemporaryFile("temp-objdump-err", "txt", StdErrFD,
-                                 StdErrFile);
-    std::vector<std::optional<StringRef>> Redirects = {
-        std::nullopt,          // stdin
-        StringRef(StdOutFile), // stdout
-        StringRef(StdErrFile)  // stderr
-    };
-
-    std::string ErrMsg;
-    int Result = sys::ExecuteAndWait(
-        "/usr/bin/objdump", {"/usr/bin/objdump", "-d", *ObjectFilePath},
-        std::nullopt, Redirects, 0, 0, &ErrMsg);
-    auto StdOutBuf = MemoryBuffer::getFile(StdOutFile);
-    if (StdOutBuf && !(*StdOutBuf)->getBuffer().empty())
-      LLVM_DEBUG(dbgs() << "[llvm-exegesis][objdump] Generated assembly:\n"
-                        << (*StdOutBuf)->getBuffer() << '\n');
-    auto StdErrBuf = MemoryBuffer::getFile(StdErrFile);
-    if (StdErrBuf && !(*StdErrBuf)->getBuffer().empty())
-      LLVM_DEBUG(dbgs() << "[llvm-exegesis][objdump] stderr:\n"
-                        << (*StdErrBuf)->getBuffer() << '\n');
-    if (!ErrMsg.empty())
-      LLVM_DEBUG(dbgs() << "[llvm-exegesis][objdump] process error: " << ErrMsg
-                        << '\n');
-    sys::fs::remove(StdOutFile);
-    sys::fs::remove(StdErrFile);
-#endif
   }
 
   if (BenchmarkPhaseSelector < BenchmarkPhaseSelectorE::Measure) {
diff --git a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
index babcffeb9666a..3ca0924cfbf2b 100644
--- a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
+++ b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
@@ -482,7 +482,8 @@ void benchmarkMain() {
   InitializeAllExegesisTargets();
 #define LLVM_EXEGESIS(TargetName)                                              \
   LLVMInitialize##TargetName##AsmPrinter();                                    \
-  LLVMInitialize##TargetName##AsmParser();
+  LLVMInitialize##TargetName##AsmParser();                                     \
+  LLVMInitialize##TargetName##Disassembler();
 #include "llvm/Config/TargetExegesis.def"
 
   const LLVMState State = ExitOnErr(
@@ -635,6 +636,7 @@ static void analysisMain() {
   InitializeAllExegesisTargets();
 #define LLVM_EXEGESIS(TargetName)                                              \
   LLVMInitialize##TargetName##AsmPrinter();                                    \
+  LLVMInitialize##TargetName##AsmParser();                                     \
   LLVMInitialize##TargetName##Disassembler();
 #include "llvm/Config/TargetExegesis.def"
 

>From 8caf0413e0d665170f411b92189eb6e10b3eeb4e Mon Sep 17 00:00:00 2001
From: lakshayk-nv <lakshayk at nvidia.com>
Date: Mon, 30 Jun 2025 21:07:42 -0700
Subject: [PATCH 04/24] [llvm-exegesis] Clang format

---
 llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
index 6e733f59a6b65..5acc3cbf480be 100644
--- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
+++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
@@ -19,18 +19,18 @@
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Twine.h"
-#include "llvm/MC/TargetRegistry.h"
 #include "llvm/Config/llvm-config.h" // for LLVM_ON_UNIX
+#include "llvm/MC/TargetRegistry.h"
 #include "llvm/Support/CrashRecoveryContext.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/Error.h"
-#include "llvm/Support/Format.h"
 #include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Format.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Program.h"
 #include "llvm/Support/Signals.h"
-#include "llvm/Support/TargetSelect.h"
 #include "llvm/Support/SystemZ/zOSSupport.h"
+#include "llvm/Support/TargetSelect.h"
 #include <cmath>
 #include <memory>
 #include <string>

>From b57c3ab5cfca7058cb5a5bea8e1e5cfadcf7cc27 Mon Sep 17 00:00:00 2001
From: lakshayk-nv <lakshayk at nvidia.com>
Date: Mon, 30 Jun 2025 21:12:40 -0700
Subject: [PATCH 05/24] [llvm-exegesis] Cleanup changes

---
 llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp | 2 +-
 llvm/tools/llvm-exegesis/llvm-exegesis.cpp       | 1 -
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
index 5acc3cbf480be..857bc577767f4 100644
--- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
+++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
@@ -649,7 +649,6 @@ BenchmarkRunner::getRunnableConfiguration(
                                              BenchmarkResult.AssembledSnippet))
       return std::move(Err);
   }
-
   // Assemble enough repetitions of the snippet so we have at least
   // MinInstructions instructions.
   if (BenchmarkPhaseSelector >
@@ -751,6 +750,7 @@ BenchmarkRunner::getRunnableConfiguration(
       }
     }
   }
+
   return std::move(RC);
 }
 
diff --git a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
index 3ca0924cfbf2b..b5820f8669f1d 100644
--- a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
+++ b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
@@ -636,7 +636,6 @@ static void analysisMain() {
   InitializeAllExegesisTargets();
 #define LLVM_EXEGESIS(TargetName)                                              \
   LLVMInitialize##TargetName##AsmPrinter();                                    \
-  LLVMInitialize##TargetName##AsmParser();                                     \
   LLVMInitialize##TargetName##Disassembler();
 #include "llvm/Config/TargetExegesis.def"
 

>From a56750fce1ff651f6f248573d77dfe86bd7b6223 Mon Sep 17 00:00:00 2001
From: abmajumder <abmajumder at nvidia.com>
Date: Tue, 6 May 2025 16:12:57 +0530
Subject: [PATCH 06/24] review comments

---
 .../llvm-exegesis/lib/AArch64/Target.cpp      | 42 +++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
index d6f4c5220f71d..9063b7cbea12b 100644
--- a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
@@ -151,6 +151,48 @@ class ExegesisAArch64Target : public ExegesisTarget {
     // Function return is a pseudo-instruction that needs to be expanded
     PM.add(createAArch64ExpandPseudoPass());
   }
+
+  const char *getIgnoredOpcodeReasonOrNull(const LLVMState &State,
+                                           unsigned Opcode) const override {
+    if (const char *Reason =
+            ExegesisTarget::getIgnoredOpcodeReasonOrNull(State, Opcode))
+      return Reason;
+
+    if (isPointerAuth(Opcode)) {
+#if defined(__aarch64__) && defined(__linux__)
+
+      // For some systems with existing PAC keys set, it is better to
+      // check the existing state of the key before setting it.
+      // For systems without PAC, this is a No-op but with PAC, it is
+      // safer to check the existing key state and then disable/enable them.
+      // Hence the guard placed for switching.
+      unsigned long pac_keys = 0;
+      if (prctl(PR_PAC_GET_ENABLED_KEYS, &pac_keys, 0, 0, 0) < 0) {
+        return "Failed to get PAC key status";
+      }
+
+      // Disable all PAC keys. Note that while we expect the measurements to
+      // be the same with PAC keys disabled, they could potentially be lower
+      // since authentication checks are bypassed.
+      if (pac_keys != 0) {
+        if (prctl(PR_PAC_SET_ENABLED_KEYS,
+                  PR_PAC_APIAKEY | PR_PAC_APIBKEY | PR_PAC_APDAKEY |
+                      PR_PAC_APDBKEY, // all keys
+                  0,                  // disable all
+                  0, 0) < 0) {
+          return "Failed to disable PAC keys";
+        }
+      }
+#else
+      return "Unsupported opcode: isPointerAuth";
+#endif
+    }
+
+    if (isLoadTagMultiple(Opcode))
+      return "Unsupported opcode: load tag multiple";
+
+    return nullptr;
+  }
 };
 
 } // namespace

>From 7b3ead61e1020c428c68b437f38205cd2318e04a Mon Sep 17 00:00:00 2001
From: abmajumder <abmajumder at nvidia.com>
Date: Wed, 7 May 2025 17:12:59 +0530
Subject: [PATCH 07/24] review comments

---
 llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
index 9063b7cbea12b..40b39a2113334 100644
--- a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
@@ -166,7 +166,7 @@ class ExegesisAArch64Target : public ExegesisTarget {
       // For systems without PAC, this is a No-op but with PAC, it is
       // safer to check the existing key state and then disable/enable them.
       // Hence the guard placed for switching.
-      unsigned long pac_keys = 0;
+      unsigned long PacKeys = 0;
       if (prctl(PR_PAC_GET_ENABLED_KEYS, &pac_keys, 0, 0, 0) < 0) {
         return "Failed to get PAC key status";
       }
@@ -174,7 +174,7 @@ class ExegesisAArch64Target : public ExegesisTarget {
       // Disable all PAC keys. Note that while we expect the measurements to
       // be the same with PAC keys disabled, they could potentially be lower
       // since authentication checks are bypassed.
-      if (pac_keys != 0) {
+      if (PacKeys != 0) {
         if (prctl(PR_PAC_SET_ENABLED_KEYS,
                   PR_PAC_APIAKEY | PR_PAC_APIBKEY | PR_PAC_APDAKEY |
                       PR_PAC_APDBKEY, // all keys

>From a45bd7a3d83cf0bdb8eaf95cb97bd51be935f3fc Mon Sep 17 00:00:00 2001
From: abmajumder <abmajumder at nvidia.com>
Date: Wed, 7 May 2025 20:25:25 +0530
Subject: [PATCH 08/24] typo build error

---
 llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
index 40b39a2113334..53f497e5da43e 100644
--- a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
@@ -165,9 +165,9 @@ class ExegesisAArch64Target : public ExegesisTarget {
       // check the existing state of the key before setting it.
       // For systems without PAC, this is a No-op but with PAC, it is
       // safer to check the existing key state and then disable/enable them.
-      // Hence the guard placed for switching.
+      // Hence the guard for switching.
       unsigned long PacKeys = 0;
-      if (prctl(PR_PAC_GET_ENABLED_KEYS, &pac_keys, 0, 0, 0) < 0) {
+      if (prctl(PR_PAC_GET_ENABLED_KEYS, &PacKeys, 0, 0, 0) < 0) {
         return "Failed to get PAC key status";
       }
 

>From b9d47e9b91f44a539aa4ff1f0d7527371a3e420d Mon Sep 17 00:00:00 2001
From: abmajumder <debabhi1396 at gmail.com>
Date: Fri, 9 May 2025 14:19:33 +0530
Subject: [PATCH 09/24] add einval condition and reviews

---
 .../llvm-exegesis/lib/AArch64/Target.cpp      | 32 ++++++++++++++-----
 1 file changed, 24 insertions(+), 8 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
index 53f497e5da43e..6ee99d1aa8e02 100644
--- a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
@@ -10,6 +10,7 @@
 #include "AArch64RegisterInfo.h"
 
 #if defined(__aarch64__) && defined(__linux__)
+#include <errno.h>
 #include <linux/prctl.h> // For PR_PAC_* constants
 #include <sys/prctl.h>
 #ifndef PR_PAC_APIAKEY
@@ -152,6 +153,11 @@ class ExegesisAArch64Target : public ExegesisTarget {
     PM.add(createAArch64ExpandPseudoPass());
   }
 
+  static long prctl_wrapper(int op, long arg2 = 0, long arg3 = 0, long arg4 = 0,
+                            long arg5 = 0) {
+    return prctl(op, arg2, arg3, arg4, arg5);
+  }
+
   const char *getIgnoredOpcodeReasonOrNull(const LLVMState &State,
                                            unsigned Opcode) const override {
     if (const char *Reason =
@@ -166,20 +172,30 @@ class ExegesisAArch64Target : public ExegesisTarget {
       // For systems without PAC, this is a No-op but with PAC, it is
       // safer to check the existing key state and then disable/enable them.
       // Hence the guard for switching.
-      unsigned long PacKeys = 0;
-      if (prctl(PR_PAC_GET_ENABLED_KEYS, &PacKeys, 0, 0, 0) < 0) {
+      errno = 0;
+      unsigned long PacKeys = prctl_wrapper(PR_PAC_GET_ENABLED_KEYS,
+                                            0,  // unused
+                                            0,  // unused
+                                            0,  // unused
+                                            0); // unused
+      if ((long)PacKeys < 0) {
+        if (errno == EINVAL) {
+          return "PAuth not supported on this system";
+        }
         return "Failed to get PAC key status";
       }
 
       // Disable all PAC keys. Note that while we expect the measurements to
       // be the same with PAC keys disabled, they could potentially be lower
       // since authentication checks are bypassed.
-      if (PacKeys != 0) {
-        if (prctl(PR_PAC_SET_ENABLED_KEYS,
-                  PR_PAC_APIAKEY | PR_PAC_APIBKEY | PR_PAC_APDAKEY |
-                      PR_PAC_APDBKEY, // all keys
-                  0,                  // disable all
-                  0, 0) < 0) {
+      if ((long)PacKeys != 0) {
+        if (prctl_wrapper(PR_PAC_SET_ENABLED_KEYS,
+                          PR_PAC_APIAKEY | PR_PAC_APIBKEY | PR_PAC_APDAKEY |
+                              PR_PAC_APDBKEY, // all keys
+                          0,                  // disable all
+                          0,                  // unused
+                          0)                  // unused
+            < 0) {
           return "Failed to disable PAC keys";
         }
       }

>From 9680a821b6d8d1ec1b795061ab3bf745f845f081 Mon Sep 17 00:00:00 2001
From: Abhilash Majumder <30946547+abhilash1910 at users.noreply.github.com>
Date: Mon, 12 May 2025 18:15:47 +0530
Subject: [PATCH 10/24] Update llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp

Co-authored-by: Anatoly Trosinenko <anatoly.trosinenko at gmail.com>
---
 llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
index 6ee99d1aa8e02..d0ae9b6a392a2 100644
--- a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
@@ -173,11 +173,7 @@ class ExegesisAArch64Target : public ExegesisTarget {
       // safer to check the existing key state and then disable/enable them.
       // Hence the guard for switching.
       errno = 0;
-      unsigned long PacKeys = prctl_wrapper(PR_PAC_GET_ENABLED_KEYS,
-                                            0,  // unused
-                                            0,  // unused
-                                            0,  // unused
-                                            0); // unused
+      unsigned long PacKeys = prctl_wrapper(PR_PAC_GET_ENABLED_KEYS);
       if ((long)PacKeys < 0) {
         if (errno == EINVAL) {
           return "PAuth not supported on this system";

>From 5f0876d25b0fe2c86ffce9747f35ea5b8b9b9c06 Mon Sep 17 00:00:00 2001
From: Abhilash Majumder <30946547+abhilash1910 at users.noreply.github.com>
Date: Mon, 12 May 2025 18:15:57 +0530
Subject: [PATCH 11/24] Update llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp

Co-authored-by: Anatoly Trosinenko <anatoly.trosinenko at gmail.com>
---
 llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
index d0ae9b6a392a2..b6544c17455a7 100644
--- a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
@@ -185,13 +185,13 @@ class ExegesisAArch64Target : public ExegesisTarget {
       // be the same with PAC keys disabled, they could potentially be lower
       // since authentication checks are bypassed.
       if ((long)PacKeys != 0) {
-        if (prctl_wrapper(PR_PAC_SET_ENABLED_KEYS,
-                          PR_PAC_APIAKEY | PR_PAC_APIBKEY | PR_PAC_APDAKEY |
-                              PR_PAC_APDBKEY, // all keys
-                          0,                  // disable all
-                          0,                  // unused
-                          0)                  // unused
-            < 0) {
+        // Operate on all keys.
+        const long KeysToControl = 
+            PR_PAC_APIAKEY | PR_PAC_APIBKEY | PR_PAC_APDAKEY | PR_PAC_APDBKEY;
+        // Disable all.
+        const long EnabledBitMask = 0;
+        if (prctl_wrapper(PR_PAC_SET_ENABLED_KEYS, KeysToControl, 
+                          EnabledBitMask) < 0) {
           return "Failed to disable PAC keys";
         }
       }

>From 54cac7a157d7ada6e2aff89ed2d57cff6fc3f5fe Mon Sep 17 00:00:00 2001
From: Abhilash Majumder <abmajumder at nvidia.com>
Date: Mon, 12 May 2025 18:18:07 +0530
Subject: [PATCH 12/24] review updates

---
 llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
index b6544c17455a7..46628575d0dc5 100644
--- a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
@@ -153,9 +153,10 @@ class ExegesisAArch64Target : public ExegesisTarget {
     PM.add(createAArch64ExpandPseudoPass());
   }
 
-  static long prctl_wrapper(int op, long arg2 = 0, long arg3 = 0, long arg4 = 0,
-                            long arg5 = 0) {
-    return prctl(op, arg2, arg3, arg4, arg5);
+  // Converts variadic arguments to `long` and passes zeros for the unused
+  // arg2-arg5, as tested by the Linux kernel.
+  static long prctl_wrapper(int op, long arg2 = 0, long arg3 = 0) {
+    return prctl(op, arg2, arg3, /*arg4=*/0L, /*arg5=*/0L);
   }
 
   const char *getIgnoredOpcodeReasonOrNull(const LLVMState &State,

>From 514c7f4547c1d94b77e6e208a3762b5792251387 Mon Sep 17 00:00:00 2001
From: Abhilash Majumder <abmajumder at nvidia.com>
Date: Mon, 12 May 2025 18:19:58 +0530
Subject: [PATCH 13/24] format fix

---
 llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
index 46628575d0dc5..c0bceba0be2c7 100644
--- a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
@@ -187,11 +187,11 @@ class ExegesisAArch64Target : public ExegesisTarget {
       // since authentication checks are bypassed.
       if ((long)PacKeys != 0) {
         // Operate on all keys.
-        const long KeysToControl = 
+        const long KeysToControl =
             PR_PAC_APIAKEY | PR_PAC_APIBKEY | PR_PAC_APDAKEY | PR_PAC_APDBKEY;
         // Disable all.
         const long EnabledBitMask = 0;
-        if (prctl_wrapper(PR_PAC_SET_ENABLED_KEYS, KeysToControl, 
+        if (prctl_wrapper(PR_PAC_SET_ENABLED_KEYS, KeysToControl,
                           EnabledBitMask) < 0) {
           return "Failed to disable PAC keys";
         }

>From 60a74917bc6bd34a2d91c3c6cee9bd9ea4b93e3e Mon Sep 17 00:00:00 2001
From: Abhilash Majumder <abmajumder at nvidia.com>
Date: Mon, 12 May 2025 18:22:20 +0530
Subject: [PATCH 14/24] format fix

---
 llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
index c0bceba0be2c7..fd19b37649fc2 100644
--- a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
@@ -167,7 +167,6 @@ class ExegesisAArch64Target : public ExegesisTarget {
 
     if (isPointerAuth(Opcode)) {
 #if defined(__aarch64__) && defined(__linux__)
-
       // For some systems with existing PAC keys set, it is better to
       // check the existing state of the key before setting it.
       // For systems without PAC, this is a No-op but with PAC, it is

>From e958fa47c55bd0c5870af09540f30b3ea26d1517 Mon Sep 17 00:00:00 2001
From: Abhilash Majumder <abmajumder at nvidia.com>
Date: Tue, 13 May 2025 21:07:24 +0530
Subject: [PATCH 15/24] use nullptr as silentcondition

---
 llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
index fd19b37649fc2..fceb232cf3976 100644
--- a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
@@ -153,11 +153,13 @@ class ExegesisAArch64Target : public ExegesisTarget {
     PM.add(createAArch64ExpandPseudoPass());
   }
 
+#if defined(__aarch64__) && defined(__linux__)
   // Converts variadic arguments to `long` and passes zeros for the unused
   // arg2-arg5, as tested by the Linux kernel.
   static long prctl_wrapper(int op, long arg2 = 0, long arg3 = 0) {
     return prctl(op, arg2, arg3, /*arg4=*/0L, /*arg5=*/0L);
   }
+#endif
 
   const char *getIgnoredOpcodeReasonOrNull(const LLVMState &State,
                                            unsigned Opcode) const override {
@@ -175,9 +177,8 @@ class ExegesisAArch64Target : public ExegesisTarget {
       errno = 0;
       unsigned long PacKeys = prctl_wrapper(PR_PAC_GET_ENABLED_KEYS);
       if ((long)PacKeys < 0) {
-        if (errno == EINVAL) {
-          return "PAuth not supported on this system";
-        }
+        if (errno == EINVAL)
+          return nullptr;
         return "Failed to get PAC key status";
       }
 
@@ -194,9 +195,12 @@ class ExegesisAArch64Target : public ExegesisTarget {
                           EnabledBitMask) < 0) {
           return "Failed to disable PAC keys";
         }
+        llvm::errs() << "llvm-exegesis: PAC keys were disabled at runtime for "
+                        "benchmarking.\n";
       }
 #else
-      return "Unsupported opcode: isPointerAuth";
+      // Silently return nullptr to ensure forward progress
+      return nullptr;
 #endif
     }
 

>From 9a8c19a26939855f24c63975bd205da0ed5da968 Mon Sep 17 00:00:00 2001
From: Abhilash Majumder <abmajumder at nvidia.com>
Date: Tue, 13 May 2025 21:40:41 +0530
Subject: [PATCH 16/24] use nullptr as silentcondition

---
 llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
index fceb232cf3976..6beffa18aa299 100644
--- a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
@@ -176,11 +176,8 @@ class ExegesisAArch64Target : public ExegesisTarget {
       // Hence the guard for switching.
       errno = 0;
       unsigned long PacKeys = prctl_wrapper(PR_PAC_GET_ENABLED_KEYS);
-      if ((long)PacKeys < 0) {
-        if (errno == EINVAL)
-          return nullptr;
-        return "Failed to get PAC key status";
-      }
+      if ((long)PacKeys < 0 || errno == EINVAL)
+        return nullptr;
 
       // Disable all PAC keys. Note that while we expect the measurements to
       // be the same with PAC keys disabled, they could potentially be lower

>From 73cab4c2cbfe5ff1dd9fa6462d4dd699767749d9 Mon Sep 17 00:00:00 2001
From: Abhilash Majumder <abmajumder at nvidia.com>
Date: Thu, 15 May 2025 23:16:02 +0530
Subject: [PATCH 17/24] update patch

---
 llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
index 6beffa18aa299..c995d46391d04 100644
--- a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
@@ -172,17 +172,20 @@ class ExegesisAArch64Target : public ExegesisTarget {
       // For some systems with existing PAC keys set, it is better to
       // check the existing state of the key before setting it.
       // For systems without PAC, this is a No-op but with PAC, it is
-      // safer to check the existing key state and then disable/enable them.
+      // better to check the existing key state and then disable/enable them
+      // to avoid runtime crashes owing to unsupported prctl opcodes or if the
+      // CPU implements FEAT_PAuth with FEAT_FPAC (in which case this method
+      // would silently return.).
       // Hence the guard for switching.
       errno = 0;
       unsigned long PacKeys = prctl_wrapper(PR_PAC_GET_ENABLED_KEYS);
-      if ((long)PacKeys < 0 || errno == EINVAL)
+      if (static_cast<long> PacKeys < 0 || errno == EINVAL)
         return nullptr;
 
       // Disable all PAC keys. Note that while we expect the measurements to
       // be the same with PAC keys disabled, they could potentially be lower
       // since authentication checks are bypassed.
-      if ((long)PacKeys != 0) {
+      if (static_cast<long> PacKeys != 0) {
         // Operate on all keys.
         const long KeysToControl =
             PR_PAC_APIAKEY | PR_PAC_APIBKEY | PR_PAC_APDAKEY | PR_PAC_APDBKEY;

>From ac6e98587d0af313d58838f218d831af863a6e62 Mon Sep 17 00:00:00 2001
From: Abhilash Majumder <abmajumder at nvidia.com>
Date: Fri, 23 May 2025 18:55:00 +0530
Subject: [PATCH 18/24] refine

---
 .../llvm-exegesis/lib/AArch64/Target.cpp      | 66 +++++++++++--------
 llvm/tools/llvm-exegesis/llvm-exegesis.cpp    | 12 ++--
 2 files changed, 47 insertions(+), 31 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
index c995d46391d04..24439ced45490 100644
--- a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
@@ -169,34 +169,46 @@ class ExegesisAArch64Target : public ExegesisTarget {
 
     if (isPointerAuth(Opcode)) {
 #if defined(__aarch64__) && defined(__linux__)
-      // For some systems with existing PAC keys set, it is better to
-      // check the existing state of the key before setting it.
-      // For systems without PAC, this is a No-op but with PAC, it is
-      // better to check the existing key state and then disable/enable them
-      // to avoid runtime crashes owing to unsupported prctl opcodes or if the
-      // CPU implements FEAT_PAuth with FEAT_FPAC (in which case this method
-      // would silently return.).
-      // Hence the guard for switching.
-      errno = 0;
-      unsigned long PacKeys = prctl_wrapper(PR_PAC_GET_ENABLED_KEYS);
-      if (static_cast<long> PacKeys < 0 || errno == EINVAL)
-        return nullptr;
-
-      // Disable all PAC keys. Note that while we expect the measurements to
-      // be the same with PAC keys disabled, they could potentially be lower
-      // since authentication checks are bypassed.
-      if (static_cast<long> PacKeys != 0) {
-        // Operate on all keys.
-        const long KeysToControl =
-            PR_PAC_APIAKEY | PR_PAC_APIBKEY | PR_PAC_APDAKEY | PR_PAC_APDBKEY;
-        // Disable all.
-        const long EnabledBitMask = 0;
-        if (prctl_wrapper(PR_PAC_SET_ENABLED_KEYS, KeysToControl,
-                          EnabledBitMask) < 0) {
-          return "Failed to disable PAC keys";
+      // Only proceed with PAC key control if explicitly requested
+      if (!AArch64DisablePacControl) {
+        // For some systems with existing PAC keys set, it is better to
+        // check the existing state of the key before setting it.
+        // For systems without PAC, this is a No-op but with PAC, it is
+        // better to check the existing key state and then disable/enable them
+        // to avoid runtime crashes owing to unsupported prctl opcodes or if the
+        // CPU implements FEAT_PAuth with FEAT_FPAC (in which case this method
+        // would silently return.). If the CPU implements FEAT_FPAC,
+        // authentication instructions almost certainly crash when being
+        // benchmarked, so disable all the keys by default. On the other hand,
+        // disabling the keys at run-time can probably crash llvm-exegesis at
+        // some later point, depending on how it was built. For that reason, the
+        // user may pass
+        // --COMMAND-LINE-OPTION-NAME in case llvm-exegesis crashes or
+        // instruction timings are affected. Hence the guard for switching.
+        errno = 0;
+        long PacKeys = prctl_wrapper(PR_PAC_GET_ENABLED_KEYS);
+        if (PacKeys < 0 || errno == EINVAL)
+          return nullptr;
+
+        // Disable all PAC keys. Note that while we expect the measurements to
+        // be the same with PAC keys disabled, they could potentially be lower
+        // since authentication checks are bypassed.PR_PAC_* prctl operations
+        // return EINVAL when Pointer Authentication is not available, but no
+        // more errors are expected if we got here.
+        if (PacKeys != 0) {
+          // Operate on all keys.
+          const long KeysToControl =
+              PR_PAC_APIAKEY | PR_PAC_APIBKEY | PR_PAC_APDAKEY | PR_PAC_APDBKEY;
+          // Disable all.
+          const long EnabledBitMask = 0;
+          if (prctl_wrapper(PR_PAC_SET_ENABLED_KEYS, KeysToControl,
+                            EnabledBitMask) < 0) {
+            return "Failed to disable PAC keys";
+          }
+          llvm::errs()
+              << "llvm-exegesis: PAC keys were disabled at runtime for "
+                 "benchmarking.\n";
         }
-        llvm::errs() << "llvm-exegesis: PAC keys were disabled at runtime for "
-                        "benchmarking.\n";
       }
 #else
       // Silently return nullptr to ensure forward progress
diff --git a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
index b5820f8669f1d..48285990f3b19 100644
--- a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
+++ b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
@@ -107,6 +107,12 @@ static cl::opt<Benchmark::RepetitionModeE> RepetitionMode(
                    "Middle half loop mode")),
     cl::init(Benchmark::Duplicate));
 
+static cl::opt<bool> AArch64DisablePacControl(
+    "aarch64-disable-pac-control",
+    cl::desc("Disable PAC key control at runtime for benchmarking. Use this if "
+             "llvm-exegesis crashes or instruction timings are affected."),
+    cl::init(false));
+
 static cl::opt<bool> BenchmarkMeasurementsPrintProgress(
     "measurements-print-progress",
     cl::desc("Produce progress indicator when performing measurements"),
@@ -444,8 +450,7 @@ static void runBenchmarkConfigurations(
     Benchmark &Result = AllResults.front();
 
     // If any of our measurements failed, pretend they all have failed.
-    if (AllResults.size() > 1 &&
-        any_of(AllResults, [](const Benchmark &R) {
+    if (AllResults.size() > 1 && any_of(AllResults, [](const Benchmark &R) {
           return R.Measurements.empty();
         }))
       Result.Measurements.clear();
@@ -644,8 +649,7 @@ static void analysisMain() {
       errorOrToExpected(MemoryBuffer::getFile(BenchmarkFile, /*IsText=*/true)));
 
   const auto TriplesAndCpus = ExitOnFileError(
-      BenchmarkFile,
-      Benchmark::readTriplesAndCpusFromYamls(*MemoryBuffer));
+      BenchmarkFile, Benchmark::readTriplesAndCpusFromYamls(*MemoryBuffer));
   if (TriplesAndCpus.empty()) {
     errs() << "no benchmarks to analyze\n";
     return;

>From cad4ed0efc56c1d51eafc55c27fbe752d9fcb49d Mon Sep 17 00:00:00 2001
From: Abhilash Majumder <abmajumder at nvidia.com>
Date: Tue, 27 May 2025 16:47:13 +0530
Subject: [PATCH 19/24] fix duplicate includes

---
 llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
index 24439ced45490..42c48a32cd698 100644
--- a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
@@ -11,8 +11,18 @@
 
 #if defined(__aarch64__) && defined(__linux__)
 #include <errno.h>
+<<<<<<< HEAD
 #include <linux/prctl.h> // For PR_PAC_* constants
 #include <sys/prctl.h>
+=======
+#include <sys/prctl.h>   // For PR_PAC_* constants 
+#ifndef PR_PAC_SET_ENABLED_KEYS
+#define PR_PAC_SET_ENABLED_KEYS 60
+#endif
+#ifndef PR_PAC_GET_ENABLED_KEYS
+#define PR_PAC_GET_ENABLED_KEYS 61
+#endif
+>>>>>>> 977612dd173f (fix duplicate includes)
 #ifndef PR_PAC_APIAKEY
 #define PR_PAC_APIAKEY (1UL << 0)
 #endif

>From 90a50c8799f063475ef8f251e53b42c4deb40461 Mon Sep 17 00:00:00 2001
From: Abhilash Majumder <abmajumder at nvidia.com>
Date: Tue, 27 May 2025 16:51:15 +0530
Subject: [PATCH 20/24] clang-format

---
 llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
index 42c48a32cd698..c48eb82bd711d 100644
--- a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
@@ -11,11 +11,7 @@
 
 #if defined(__aarch64__) && defined(__linux__)
 #include <errno.h>
-<<<<<<< HEAD
-#include <linux/prctl.h> // For PR_PAC_* constants
-#include <sys/prctl.h>
-=======
-#include <sys/prctl.h>   // For PR_PAC_* constants 
+#include <sys/prctl.h> // For PR_PAC_* constants
 #ifndef PR_PAC_SET_ENABLED_KEYS
 #define PR_PAC_SET_ENABLED_KEYS 60
 #endif

>From 1bb9f2f0545e66e80f43ec245ff95401766898b3 Mon Sep 17 00:00:00 2001
From: Abhilash Majumder <abmajumder at nvidia.com>
Date: Tue, 3 Jun 2025 11:39:41 +0530
Subject: [PATCH 21/24] refresh

---
 .../llvm-exegesis/lib/AArch64/Target.cpp      | 59 ++++++++++++++++---
 1 file changed, 50 insertions(+), 9 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
index c48eb82bd711d..ffe607af7cea1 100644
--- a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
@@ -8,6 +8,7 @@
 #include "../Target.h"
 #include "AArch64.h"
 #include "AArch64RegisterInfo.h"
+#include "llvm/Support/CommandLine.h"
 
 #if defined(__aarch64__) && defined(__linux__)
 #include <errno.h>
@@ -39,6 +40,49 @@
 namespace llvm {
 namespace exegesis {
 
+extern llvm::cl::opt<bool> AArch64DisablePacControl;
+
+bool isPointerAuth(unsigned Opcode) {
+  switch (Opcode) {
+  default:
+    return false;
+
+  // FIXME: Pointer Authentication instructions.
+  // We would like to measure these instructions, but they can behave
+  // differently on different platforms, and maybe the snippets need to look
+  // different for these instructions,
+  // Platform-specific handling:  On Linux, we disable authentication, may
+  // interfere with measurements. On non-Linux platforms, disable opcodes for
+  // now.
+  case AArch64::AUTDA:
+  case AArch64::AUTDB:
+  case AArch64::AUTDZA:
+  case AArch64::AUTDZB:
+  case AArch64::AUTIA:
+  case AArch64::AUTIA1716:
+  case AArch64::AUTIASP:
+  case AArch64::AUTIAZ:
+  case AArch64::AUTIB:
+  case AArch64::AUTIB1716:
+  case AArch64::AUTIBSP:
+  case AArch64::AUTIBZ:
+  case AArch64::AUTIZA:
+  case AArch64::AUTIZB:
+    return true;
+  }
+}
+
+bool isLoadTagMultiple(unsigned Opcode) {
+  switch (Opcode) {
+  default:
+    return false;
+
+  // Load tag multiple instruction
+  case AArch64::LDGM:
+    return true;
+  }
+}
+
 static unsigned getLoadImmediateOpcode(unsigned RegBitWidth) {
   switch (RegBitWidth) {
   case 32:
@@ -179,18 +223,14 @@ class ExegesisAArch64Target : public ExegesisTarget {
       if (!AArch64DisablePacControl) {
         // For some systems with existing PAC keys set, it is better to
         // check the existing state of the key before setting it.
-        // For systems without PAC, this is a No-op but with PAC, it is
-        // better to check the existing key state and then disable/enable them
-        // to avoid runtime crashes owing to unsupported prctl opcodes or if the
-        // CPU implements FEAT_PAuth with FEAT_FPAC (in which case this method
-        // would silently return.). If the CPU implements FEAT_FPAC,
+        // If the CPU implements FEAT_FPAC,
         // authentication instructions almost certainly crash when being
         // benchmarked, so disable all the keys by default. On the other hand,
         // disabling the keys at run-time can probably crash llvm-exegesis at
         // some later point, depending on how it was built. For that reason, the
-        // user may pass
-        // --COMMAND-LINE-OPTION-NAME in case llvm-exegesis crashes or
-        // instruction timings are affected. Hence the guard for switching.
+        // user may pass --aarch64-disable-pac-control in case
+        // llvm-exegesis crashes or instruction timings are affected.
+        // Hence the guard for switching.
         errno = 0;
         long PacKeys = prctl_wrapper(PR_PAC_GET_ENABLED_KEYS);
         if (PacKeys < 0 || errno == EINVAL)
@@ -205,7 +245,8 @@ class ExegesisAArch64Target : public ExegesisTarget {
           // Operate on all keys.
           const long KeysToControl =
               PR_PAC_APIAKEY | PR_PAC_APIBKEY | PR_PAC_APDAKEY | PR_PAC_APDBKEY;
-          // Disable all.
+          // PR_PAC_* prctl operations return EINVAL when Pointer Authentication
+          // is not available but no more errors are expected if we got here.
           const long EnabledBitMask = 0;
           if (prctl_wrapper(PR_PAC_SET_ENABLED_KEYS, KeysToControl,
                             EnabledBitMask) < 0) {

>From 1e0e65c672bcdd7e47bd72f0fdf7a5083bdeb978 Mon Sep 17 00:00:00 2001
From: Abhilash Majumder <abmajumder at nvidia.com>
Date: Tue, 3 Jun 2025 22:35:04 +0530
Subject: [PATCH 22/24] refresh

---
 llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp |  6 +++++-
 llvm/tools/llvm-exegesis/llvm-exegesis.cpp      | 14 +++++---------
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
index ffe607af7cea1..607196a0af67d 100644
--- a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
@@ -40,7 +40,11 @@
 namespace llvm {
 namespace exegesis {
 
-extern llvm::cl::opt<bool> AArch64DisablePacControl;
+static cl::opt<bool> AArch64DisablePacControl(
+    "aarch64-disable-pac-control",
+    cl::desc("Disable PAC key control at runtime for benchmarking. Use this if "
+             "llvm-exegesis crashes or instruction timings are affected."),
+    cl::init(false));
 
 bool isPointerAuth(unsigned Opcode) {
   switch (Opcode) {
diff --git a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
index 48285990f3b19..2114cabddcb42 100644
--- a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
+++ b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
@@ -107,12 +107,6 @@ static cl::opt<Benchmark::RepetitionModeE> RepetitionMode(
                    "Middle half loop mode")),
     cl::init(Benchmark::Duplicate));
 
-static cl::opt<bool> AArch64DisablePacControl(
-    "aarch64-disable-pac-control",
-    cl::desc("Disable PAC key control at runtime for benchmarking. Use this if "
-             "llvm-exegesis crashes or instruction timings are affected."),
-    cl::init(false));
-
 static cl::opt<bool> BenchmarkMeasurementsPrintProgress(
     "measurements-print-progress",
     cl::desc("Produce progress indicator when performing measurements"),
@@ -450,7 +444,8 @@ static void runBenchmarkConfigurations(
     Benchmark &Result = AllResults.front();
 
     // If any of our measurements failed, pretend they all have failed.
-    if (AllResults.size() > 1 && any_of(AllResults, [](const Benchmark &R) {
+    if (AllResults.size() > 1 &&
+        any_of(AllResults, [](const Benchmark &R) {
           return R.Measurements.empty();
         }))
       Result.Measurements.clear();
@@ -649,7 +644,8 @@ static void analysisMain() {
       errorOrToExpected(MemoryBuffer::getFile(BenchmarkFile, /*IsText=*/true)));
 
   const auto TriplesAndCpus = ExitOnFileError(
-      BenchmarkFile, Benchmark::readTriplesAndCpusFromYamls(*MemoryBuffer));
+      BenchmarkFile,
+      Benchmark::readTriplesAndCpusFromYamls(*MemoryBuffer));
   if (TriplesAndCpus.empty()) {
     errs() << "no benchmarks to analyze\n";
     return;
@@ -739,4 +735,4 @@ int main(int Argc, char **Argv) {
     exegesis::benchmarkMain();
   }
   return EXIT_SUCCESS;
-}
+}
\ No newline at end of file

>From 32c83865ed9cf6d38ddb65d572a9e5dc6a3229e7 Mon Sep 17 00:00:00 2001
From: lakshayk-nv <lakshayk at nvidia.com>
Date: Tue, 1 Jul 2025 01:40:50 -0700
Subject: [PATCH 23/24] newline

---
 llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp | 1 -
 llvm/tools/llvm-exegesis/llvm-exegesis.cpp      | 2 +-
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
index 607196a0af67d..9297711d53612 100644
--- a/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
+++ b/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
@@ -19,7 +19,6 @@
 #ifndef PR_PAC_GET_ENABLED_KEYS
 #define PR_PAC_GET_ENABLED_KEYS 61
 #endif
->>>>>>> 977612dd173f (fix duplicate includes)
 #ifndef PR_PAC_APIAKEY
 #define PR_PAC_APIAKEY (1UL << 0)
 #endif
diff --git a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
index 2114cabddcb42..b5820f8669f1d 100644
--- a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
+++ b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
@@ -735,4 +735,4 @@ int main(int Argc, char **Argv) {
     exegesis::benchmarkMain();
   }
   return EXIT_SUCCESS;
-}
\ No newline at end of file
+}

>From a8160ae429c3750938565a1063b208afa1dd698f Mon Sep 17 00:00:00 2001
From: lakshayk-nv <lakshayk at nvidia.com>
Date: Tue, 1 Jul 2025 01:43:55 -0700
Subject: [PATCH 24/24] [llvm-exegesis] [AArch64] Added testcase to check 
 assembly generation via debug-only

---
 .../llvm-exegesis/AArch64/debug-gen-asm.s     | 22 +++++++++++++++++++
 .../llvm-exegesis/lib/BenchmarkRunner.cpp     |  1 +
 2 files changed, 23 insertions(+)
 create mode 100644 llvm/test/tools/llvm-exegesis/AArch64/debug-gen-asm.s

diff --git a/llvm/test/tools/llvm-exegesis/AArch64/debug-gen-asm.s b/llvm/test/tools/llvm-exegesis/AArch64/debug-gen-asm.s
new file mode 100644
index 0000000000000..d1b96f02e3986
--- /dev/null
+++ b/llvm/test/tools/llvm-exegesis/AArch64/debug-gen-asm.s
@@ -0,0 +1,22 @@
+REQUIRES: aarch64-registered-target
+
+RUN: llvm-exegesis -mcpu=neoverse-v2 --benchmark-phase=measure --min-instructions=100 --mode=latency --debug-only="preview-gen-assembly" --opcode-name=ADDVv4i16v 2>&1 | FileCheck %s -check-prefix=PREVIEW
+
+PREVIEW: Generated assembly snippet:
+PREVIEW-NEXT: ```
+PREVIEW:      {{.*}}   movi    d{{[0-9]+}}, #0000000000000000
+PREVIEW-NEXT: {{.*}}   addv    h{{[0-9]+}}, v{{[0-9]+}}.4h
+PREVIEW:      {{.*}}   addv    h{{[0-9]+}}, v{{[0-9]+}}.4h
+PREVIEW:      ...      ({{[0-9]+}} more instructions)
+PREVIEW-NEXT: {{.*}}   addv    h{{[0-9]+}}, v{{[0-9]+}}.4h
+PREVIEW:      {{.*}}   ret
+PREVIEW-NEXT:```
+
+RUN: llvm-exegesis -mcpu=neoverse-v2 --benchmark-phase=measure --min-instructions=100 --mode=latency --debug-only="print-gen-assembly" --opcode-name=ADDVv4i16v 2>&1 | FileCheck %s -check-prefix=PRINT
+
+PRINT: Generated assembly snippet:
+PRINT-NEXT: ```
+PRINT:       {{.*}}     movi    d{{[0-9]+}}, #0000000000000000
+PRINT:       {{.*}}     addv    h{{[0-9]+}}, v{{[0-9]+}}.4h
+PRINT:       {{.*}}     ret
+PRINT-NEXT: ```
diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
index 857bc577767f4..789326287f4e9 100644
--- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
+++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
@@ -649,6 +649,7 @@ BenchmarkRunner::getRunnableConfiguration(
                                              BenchmarkResult.AssembledSnippet))
       return std::move(Err);
   }
+
   // Assemble enough repetitions of the snippet so we have at least
   // MinInstructions instructions.
   if (BenchmarkPhaseSelector >



More information about the llvm-commits mailing list