[llvm] [llvm-exegesis] Debug generated disassembly (PR #142540)
Lakshay Kumar via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 1 03:54:50 PDT 2025
================
@@ -655,6 +660,96 @@ 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
+ {
----------------
lakshayk-nv wrote:
How to use:
`--debug-only="print-gen-assembly"` debugs the whole generated assembly snippet .
`--debug-only=preview-gen-assembly` debugs the initial 10 instructions and ending 3 lines.
(Updated PR Description accordingly)
No, Given argument of `--debug-only="print-gen-assembly"` exegesis will print out the generated assembly only once with truncated middle part, so not to fill up whole terminal for large value of `min-instructions`
```
$ build/bin/llvm-exegesis -mcpu=neoverse-v2 --dump-object-to-disk=%d --benchmark-phase=measure --min-instructions=15 --mode=latency --opcode-name=ADCXr --debug-only="preview-gen-assembly"
setRegTo is not implemented, results will be unreliable
setRegTo is not implemented, results will be unreliable
Generated assembly snippet:
'''
0: d2800000 mov x0, #0
4: d280000e mov x14, #0
8: 9a0e0000 adc x0, x0, x14
c: 9a0e0000 adc x0, x0, x14
10: 9a0e0000 adc x0, x0, x14
14: 9a0e0000 adc x0, x0, x14
18: 9a0e0000 adc x0, x0, x14
1c: 9a0e0000 adc x0, x0, x14
20: 9a0e0000 adc x0, x0, x14
24: 9a0e0000 adc x0, x0, x14
... (5 more instructions)
3c: 9a0e0000 adc x0, x0, x14
40: 9a0e0000 adc x0, x0, x14
44: d65f03c0 ret
'''
Check generated assembly with: /usr/bin/objdump -d %d
---
mode: latency
key:
instructions:
- 'ADCXr X0 X0 X14'
config: ''
register_initial_values:
- 'X0=0x0'
- 'X14=0x0'
- 'NZCV=0x0'
cpu_name: neoverse-v2
llvm_triple: aarch64-unknown-linux-gnu
min_instructions: 15
measurements:
- { key: latency, value: 4.93333, per_snippet_value: 4.93333, validation_counters: {} }
error: ''
info: Repeating a single explicitly serial instruction
assembled_snippet: 000080D20E0080D200000E9A00000E9A00000E9A00000E9AC0035FD6
...
```
If we explicitly give argument `--debug-only="preview-gen-assembly,print-gen-assembly"` to exegesis, both preview and print debug will result in duplicate print.
https://github.com/llvm/llvm-project/pull/142540
More information about the llvm-commits
mailing list