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

Lakshay Kumar via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 4 03:36:16 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/10] [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/10] [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/10] [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/10] [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/10] [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 7e9550e668e26fa3678e21455b825fb7562745e8 Mon Sep 17 00:00:00 2001
From: lakshayk-nv <lakshayk at nvidia.com>
Date: Tue, 1 Jul 2025 02:30:05 -0700
Subject: [PATCH 06/10] [llvm-exegesis] Add tests for generated assembly
 snippets in AArch64

---
 .../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 >

>From 1e97fad43d93c84373a350c9386a085c653b041a Mon Sep 17 00:00:00 2001
From: lakshayk-nv <lakshayk at nvidia.com>
Date: Wed, 2 Jul 2025 03:27:24 -0700
Subject: [PATCH 07/10] [llvm-exegesis] Refactor assembly snippet printing into
 helper functions

---
 .../llvm-exegesis/lib/BenchmarkRunner.cpp     | 183 +++++++++---------
 1 file changed, 95 insertions(+), 88 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
index 789326287f4e9..28fef72ebd3ac 100644
--- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
+++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
@@ -31,6 +31,7 @@
 #include "llvm/Support/Signals.h"
 #include "llvm/Support/SystemZ/zOSSupport.h"
 #include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/raw_ostream.h"
 #include <cmath>
 #include <memory>
 #include <string>
@@ -593,6 +594,99 @@ class SubProcessFunctionExecutorImpl
   const std::optional<int> BenchmarkProcessCPU;
 };
 #endif // __linux__
+
+// Helper function to print generated assembly snippets
+void printGeneratedAssembly(
+    const std::vector<std::pair<std::string, std::pair<uint64_t, std::string>>>
+        &Instructions,
+    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].second.first, 0) << ":\t"
+           << Instructions[i].second.second << Instructions[i].first << '\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].second.first, 0) << ":\t"
+               << Instructions[i].second.second << Instructions[i].first
+               << '\n';
+      }
+    }
+    // Print last "PreviewLast" lines
+    for (size_t i = N - PreviewLast; i < N; ++i) {
+      dbgs() << format_hex_no_prefix(Instructions[i].second.first, 0) << ":\t"
+             << Instructions[i].second.second << Instructions[i].first << '\n';
+    }
+  }
+  dbgs() << "```\n";
+}
+
+// Function to extract and print assembly from snippet
+void printAssembledSnippet(const LLVMState &State,
+                           const SmallString<0> &Snippet) {
+  // 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";
+    return;
+  }
+
+  DisassemblerHelper DisHelper(State);
+  ArrayRef<uint8_t> Bytes(FunctionBytes);
+
+  // Decode all instructions first
+  std::vector<std::pair<std::string, std::pair<uint64_t, std::string>>>
+      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;
+    }
+  }
+
+  // Preview generated assembly snippet
+  {
+#undef DEBUG_TYPE
+#define DEBUG_TYPE "preview-gen-assembly"
+    LLVM_DEBUG(dbgs() << "Generated assembly snippet:\n");
+    LLVM_DEBUG(printGeneratedAssembly(Instructions, true));
+#undef DEBUG_TYPE
+#define DEBUG_TYPE "print-gen-assembly"
+  }
+  // Print generated assembly snippet
+  {
+    LLVM_DEBUG(dbgs() << "Generated assembly snippet:\n");
+    LLVM_DEBUG(printGeneratedAssembly(Instructions, false));
+  }
+}
 } // namespace
 
 Expected<SmallString<0>> BenchmarkRunner::assembleSnippet(
@@ -662,94 +756,7 @@ BenchmarkRunner::getRunnableConfiguration(
     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));
-      }
-    }
+    printAssembledSnippet(State, *Snippet);
   }
 
   return std::move(RC);

>From 989d7b0ca0691bff46b4079581ba57e8cdd42ac5 Mon Sep 17 00:00:00 2001
From: lakshayk-nv <lakshayk at nvidia.com>
Date: Wed, 2 Jul 2025 23:03:53 -0700
Subject: [PATCH 08/10] [llvm-exegesis] Refactor instruction decoding and
 assembly snippet generation

---
 .../llvm-exegesis/lib/BenchmarkRunner.cpp     | 70 ++++++++++---------
 1 file changed, 36 insertions(+), 34 deletions(-)

diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
index 28fef72ebd3ac..89ac5d7eefb71 100644
--- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
+++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
@@ -603,73 +603,72 @@ void printGeneratedAssembly(
   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) {
+  for (size_t i = 0; i < std::min(size_t(PreviewFirst), N); ++i)
     dbgs() << format_hex_no_prefix(Instructions[i].second.first, 0) << ":\t"
            << Instructions[i].second.second << Instructions[i].first << '\n';
-  }
+
   if (N > (PreviewFirst + PreviewLast)) {
-    if (Preview) {
+    if (Preview)
       dbgs() << "...\t(" << (N - PreviewFirst - PreviewLast)
              << " more instructions)\n";
-    } else {
+    else {
       // Print all middle lines
-      for (size_t i = PreviewFirst; i < N - PreviewLast; ++i) {
+      for (size_t i = PreviewFirst; i < N - PreviewLast; ++i)
         dbgs() << format_hex_no_prefix(Instructions[i].second.first, 0) << ":\t"
                << Instructions[i].second.second << Instructions[i].first
                << '\n';
-      }
     }
     // Print last "PreviewLast" lines
-    for (size_t i = N - PreviewLast; i < N; ++i) {
+    for (size_t i = N - PreviewLast; i < N; ++i)
       dbgs() << format_hex_no_prefix(Instructions[i].second.first, 0) << ":\t"
              << Instructions[i].second.second << Instructions[i].first << '\n';
-    }
   }
   dbgs() << "```\n";
 }
 
 // Function to extract and print assembly from snippet
-void printAssembledSnippet(const LLVMState &State,
-                           const SmallString<0> &Snippet) {
+Error printAssembledSnippet(const LLVMState &State,
+                            const SmallString<0> &Snippet) {
   // 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";
-    return;
-  }
+  if (auto Err = getBenchmarkFunctionBytes(Snippet, FunctionBytes))
+    return make_error<Failure>("Failed to extract function bytes: " +
+                               toString(std::move(Err)));
 
   DisassemblerHelper DisHelper(State);
-  ArrayRef<uint8_t> Bytes(FunctionBytes);
+  size_t Offset = 0;
+  const size_t FunctionBytesSize = FunctionBytes.size();
 
   // Decode all instructions first
   std::vector<std::pair<std::string, std::pair<uint64_t, std::string>>>
       Instructions;
   uint64_t Address = 0;
 
-  while (!Bytes.empty()) {
+  while (Offset < FunctionBytesSize) {
     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);
-      }
+    ArrayRef<uint8_t> Bytes(FunctionBytes.data() + Offset,
+                            FunctionBytesSize - Offset);
 
-      Instructions.push_back({OS.str(), {Address, HexOS.str()}});
-      Bytes = Bytes.slice(Size);
-      Address += Size;
-    } else {
+    if (!DisHelper.decodeInst(Inst, Size, Bytes)) {
       Instructions.push_back({"<decode error>", {Address, ""}});
       break;
     }
+
+    // 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()}});
+    Offset += Size;
+    Address += Size;
   }
 
   // Preview generated assembly snippet
@@ -686,6 +685,8 @@ void printAssembledSnippet(const LLVMState &State,
     LLVM_DEBUG(dbgs() << "Generated assembly snippet:\n");
     LLVM_DEBUG(printGeneratedAssembly(Instructions, false));
   }
+
+  return Error::success();
 }
 } // namespace
 
@@ -756,7 +757,8 @@ BenchmarkRunner::getRunnableConfiguration(
     RC.ObjectFile = getObjectFromBuffer(*Snippet);
 
     // Print the assembled snippet by disassembling the binary data
-    printAssembledSnippet(State, *Snippet);
+    if (Error E = printAssembledSnippet(State, *Snippet))
+      return std::move(E);
   }
 
   return std::move(RC);

>From a987b50eea76717d287314564bd924c06ba75e44 Mon Sep 17 00:00:00 2001
From: lakshayk-nv <lakshayk at nvidia.com>
Date: Fri, 4 Jul 2025 01:06:18 -0700
Subject: [PATCH 09/10] [llvm-exegesis] Introduced --print-gen-assembly=<> for
 number of lines to print

---
 .../llvm-exegesis/AArch64/debug-gen-asm.s     |  18 +--
 .../llvm-exegesis/lib/BenchmarkRunner.cpp     | 106 +++++++++---------
 2 files changed, 56 insertions(+), 68 deletions(-)

diff --git a/llvm/test/tools/llvm-exegesis/AArch64/debug-gen-asm.s b/llvm/test/tools/llvm-exegesis/AArch64/debug-gen-asm.s
index d1b96f02e3986..119814f1c62fe 100644
--- a/llvm/test/tools/llvm-exegesis/AArch64/debug-gen-asm.s
+++ b/llvm/test/tools/llvm-exegesis/AArch64/debug-gen-asm.s
@@ -1,22 +1,12 @@
 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
+RUN: llvm-exegesis -mcpu=neoverse-v2 --benchmark-phase=measure --min-instructions=100 --mode=latency --print-gen-assembly=10 --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:      {{[04]}}: {{.*}}      movi    d{{[0-9]+}}, #0000000000000000
+PREVIEW-NEXT: {{[48]}}: {{.*}}      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: ```
+PREVIEW-NEXT:```
\ No newline at end of file
diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
index 89ac5d7eefb71..c2c796e29552a 100644
--- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
+++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
@@ -21,6 +21,7 @@
 #include "llvm/ADT/Twine.h"
 #include "llvm/Config/llvm-config.h" // for LLVM_ON_UNIX
 #include "llvm/MC/TargetRegistry.h"
+#include "llvm/Support/CommandLine.h"
 #include "llvm/Support/CrashRecoveryContext.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/Error.h"
@@ -59,6 +60,12 @@
 namespace llvm {
 namespace exegesis {
 
+static cl::opt<int> PrintGenAssembly(
+    "print-gen-assembly", cl::Optional, cl::init(0),
+    cl::desc("Print generated assembly snippets. -1 prints all lines, "
+             "positive N prints first N lines with truncated middle part"),
+    cl::cat(BenchmarkOptions));
+
 BenchmarkRunner::BenchmarkRunner(const LLVMState &State, Benchmark::ModeE Mode,
                                  BenchmarkPhaseSelectorE BenchmarkPhaseSelector,
                                  ExecutionModeE ExecutionMode,
@@ -595,35 +602,36 @@ class SubProcessFunctionExecutorImpl
 };
 #endif // __linux__
 
+// Structure to hold instruction information for assembly printing
+struct InstructionInfo {
+  std::string Text;
+  uint64_t Address;
+  std::string HexBytes;
+};
+
 // Helper function to print generated assembly snippets
-void printGeneratedAssembly(
-    const std::vector<std::pair<std::string, std::pair<uint64_t, std::string>>>
-        &Instructions,
-    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].second.first, 0) << ":\t"
-           << Instructions[i].second.second << Instructions[i].first << '\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].second.first, 0) << ":\t"
-               << Instructions[i].second.second << Instructions[i].first
-               << '\n';
-    }
-    // Print last "PreviewLast" lines
-    for (size_t i = N - PreviewLast; i < N; ++i)
-      dbgs() << format_hex_no_prefix(Instructions[i].second.first, 0) << ":\t"
-             << Instructions[i].second.second << Instructions[i].first << '\n';
-  }
-  dbgs() << "```\n";
+void printInstructions(const std::vector<InstructionInfo> &Instructions,
+                       int InitialLinesCount, int LastLinesCount) {
+  int N = Instructions.size();
+  outs() << "Generated assembly snippet:\n```\n";
+
+  // Print initial lines
+  for (int i = 0; i < InitialLinesCount; ++i)
+    outs() << format_hex_no_prefix(Instructions[i].Address, 0) << ":\t"
+           << Instructions[i].HexBytes << Instructions[i].Text << '\n';
+
+  // Show truncation message if needed
+  int SkippedInstructions = N - InitialLinesCount - LastLinesCount;
+  if (SkippedInstructions > 0)
+    outs() << "...\t(" << SkippedInstructions << " more instructions)\n";
+
+  // Print last min(PreviewLast, N - PreviewFirst) lines
+  int LastLinesToPrint = std::min(
+      LastLinesCount, N > InitialLinesCount ? N - InitialLinesCount : 0);
+  for (int i = N - LastLinesToPrint; i < N; ++i)
+    outs() << format_hex_no_prefix(Instructions[i].Address, 0) << ":\t"
+           << Instructions[i].HexBytes << Instructions[i].Text << '\n';
+  outs() << "```\n";
 }
 
 // Function to extract and print assembly from snippet
@@ -635,23 +643,20 @@ Error printAssembledSnippet(const LLVMState &State,
     return make_error<Failure>("Failed to extract function bytes: " +
                                toString(std::move(Err)));
 
-  DisassemblerHelper DisHelper(State);
-  size_t Offset = 0;
-  const size_t FunctionBytesSize = FunctionBytes.size();
-
   // Decode all instructions first
-  std::vector<std::pair<std::string, std::pair<uint64_t, std::string>>>
-      Instructions;
+  DisassemblerHelper DisHelper(State);
   uint64_t Address = 0;
+  std::vector<InstructionInfo> Instructions;
+  const size_t FunctionBytesSize = FunctionBytes.size();
 
-  while (Offset < FunctionBytesSize) {
+  while (Address < FunctionBytesSize) {
     MCInst Inst;
     uint64_t Size;
-    ArrayRef<uint8_t> Bytes(FunctionBytes.data() + Offset,
-                            FunctionBytesSize - Offset);
+    ArrayRef<uint8_t> Bytes(FunctionBytes.data() + Address,
+                            FunctionBytesSize - Address);
 
     if (!DisHelper.decodeInst(Inst, Size, Bytes)) {
-      Instructions.push_back({"<decode error>", {Address, ""}});
+      Instructions.push_back({"<decode error>", Address, ""});
       break;
     }
 
@@ -666,26 +671,19 @@ Error printAssembledSnippet(const LLVMState &State,
     for (int i = Size - 1; i >= 0; --i)
       HexOS << format_hex_no_prefix(Bytes[i], 2);
 
-    Instructions.push_back({OS.str(), {Address, HexOS.str()}});
-    Offset += Size;
+    Instructions.push_back({OS.str(), Address, HexOS.str()});
     Address += Size;
   }
 
-  // Preview generated assembly snippet
-  {
-#undef DEBUG_TYPE
-#define DEBUG_TYPE "preview-gen-assembly"
-    LLVM_DEBUG(dbgs() << "Generated assembly snippet:\n");
-    LLVM_DEBUG(printGeneratedAssembly(Instructions, true));
-#undef DEBUG_TYPE
-#define DEBUG_TYPE "print-gen-assembly"
-  }
-  // Print generated assembly snippet
-  {
-    LLVM_DEBUG(dbgs() << "Generated assembly snippet:\n");
-    LLVM_DEBUG(printGeneratedAssembly(Instructions, false));
-  }
+  if (PrintGenAssembly == 0 || PrintGenAssembly < -1)
+    return Error::success();
 
+  int InitialLinesCount = PrintGenAssembly;
+  int LastLinesCount = 3;
+  if (PrintGenAssembly == -1 ||
+      PrintGenAssembly > static_cast<int>(Instructions.size()))
+    InitialLinesCount = Instructions.size() - LastLinesCount;
+  printInstructions(Instructions, InitialLinesCount, LastLinesCount);
   return Error::success();
 }
 } // namespace

>From 4acfe17aa4b2d7b6b601e054db280bbbd829fccb Mon Sep 17 00:00:00 2001
From: lakshayk-nv <lakshayk at nvidia.com>
Date: Fri, 4 Jul 2025 03:35:48 -0700
Subject: [PATCH 10/10] [llvm-exegesis] Newline added in testfile

---
 llvm/test/tools/llvm-exegesis/AArch64/debug-gen-asm.s | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/test/tools/llvm-exegesis/AArch64/debug-gen-asm.s b/llvm/test/tools/llvm-exegesis/AArch64/debug-gen-asm.s
index 119814f1c62fe..3bb6bf962a2ca 100644
--- a/llvm/test/tools/llvm-exegesis/AArch64/debug-gen-asm.s
+++ b/llvm/test/tools/llvm-exegesis/AArch64/debug-gen-asm.s
@@ -9,4 +9,4 @@ PREVIEW-NEXT: {{[48]}}: {{.*}}      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:```
\ No newline at end of file
+PREVIEW-NEXT:```



More information about the llvm-commits mailing list