[llvm] [InstrRef] Preserve debug instr num in aarch64-ldst-opt. (PR #136009)
Shubham Sandeep Rastogi via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 17 11:26:16 PDT 2025
https://github.com/rastogishubham updated https://github.com/llvm/llvm-project/pull/136009
>From 00d0a52f8d6e7a0e820aa5188447b93164f2d420 Mon Sep 17 00:00:00 2001
From: Shubham Sandeep Rastogi <srastogi22 at apple.com>
Date: Wed, 16 Apr 2025 11:51:57 -0700
Subject: [PATCH] [InstrRef] Preserve debug instr num in aarch64-ldst-opt.
The aarch64-ldst-opt pass tries to merge two load instructions (LDR*) to
a load pair instruction (LDP*).
When merging the instructions, there is a case where one of the loads
would have to also be sign extended. In either case,
(sign extend or not), the pass needs to preserve the debug-instr-number
from the original loads to the load pair instruction to make sure
debug info isn't loast in the case where instruction referencing is
being used.
This patch addresses that problem.
---
.../AArch64/AArch64LoadStoreOptimizer.cpp | 81 +++++++++++++++++++
.../AArch64/aarch64-ldst-opt-instr-ref.mir | 79 ++++++++++++++++++
2 files changed, 160 insertions(+)
create mode 100644 llvm/test/CodeGen/AArch64/aarch64-ldst-opt-instr-ref.mir
diff --git a/llvm/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp b/llvm/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp
index cd976790ebb6f..3ec847dde3c83 100644
--- a/llvm/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp
+++ b/llvm/lib/Target/AArch64/AArch64LoadStoreOptimizer.cpp
@@ -963,6 +963,40 @@ static void updateDefinedRegisters(MachineInstr &MI, LiveRegUnits &Units,
Units.addReg(MOP.getReg());
}
+/// Find the DBG_INSTR_REF instruction that references the \p InstrNum
+static std::optional<MachineInstr *> findDebugInstrRef(MachineBasicBlock *MBB,
+ unsigned InstrNum) {
+
+ for (auto &MI : *MBB) {
+ if (MI.isDebugRef())
+ if (MI.getOperand(2).getInstrRefInstrIndex() == InstrNum)
+ return &MI;
+ }
+ return std::nullopt;
+}
+
+/// Set the correct debug-instr-number and the operand index in case of a merge.
+static void setDebugInstrNum(MachineBasicBlock::iterator OriginalInstr,
+ MachineInstrBuilder &MIB, unsigned InstrNumToFind,
+ unsigned InstrNumToSet, MachineBasicBlock *MBB) {
+
+ auto InstrRefMI = findDebugInstrRef(MBB, InstrNumToFind);
+ if (InstrRefMI) {
+ auto *MI = *InstrRefMI;
+ MI->getOperand(2).setInstrRefInstrIndex(InstrNumToSet);
+ // Set the Instruction Reference Op Index to be the same as the operand of
+ // the new merged pair instruction.
+ auto Reg = OriginalInstr->getOperand(0).getReg();
+ unsigned OperandNo = 0;
+ for (auto Op : MIB->operands()) {
+ if (Op.getReg() == Reg)
+ break;
+ OperandNo++;
+ }
+ MI->getOperand(2).setInstrRefOpIndex(OperandNo);
+ }
+}
+
MachineBasicBlock::iterator
AArch64LoadStoreOpt::mergePairedInsns(MachineBasicBlock::iterator I,
MachineBasicBlock::iterator Paired,
@@ -1225,9 +1259,56 @@ AArch64LoadStoreOpt::mergePairedInsns(MachineBasicBlock::iterator I,
.addImm(0)
.addImm(31);
(void)MIBSXTW;
+
+ if (I->peekDebugInstrNum()) {
+ auto InstrNum = I->peekDebugInstrNum();
+ // If I is the instruction which got sign extended, restore the debug
+ // instruction number from I to the SBFMXri instruction
+ if (DstRegX == I->getOperand(0).getReg())
+ MIBSXTW->setDebugInstrNum(InstrNum);
+ else {
+ MIB->setDebugInstrNum(InstrNum);
+ setDebugInstrNum(I, MIB, InstrNum, InstrNum, MBB);
+ }
+ }
+ if (Paired->peekDebugInstrNum()) {
+ auto InstrNum = Paired->peekDebugInstrNum();
+ // If Paired is the instruction which got sign extended, restore the debug
+ // instruction number from Paired to the SBFMXri instruction
+ if (DstRegX == Paired->getOperand(0).getReg())
+ MIBSXTW->setDebugInstrNum(InstrNum);
+ else {
+ MIB->setDebugInstrNum(InstrNum);
+ setDebugInstrNum(Paired, MIB, InstrNum, InstrNum, MBB);
+ }
+ }
+
LLVM_DEBUG(dbgs() << " Extend operand:\n ");
LLVM_DEBUG(((MachineInstr *)MIBSXTW)->print(dbgs()));
} else {
+
+ // Restore the debug instruction numbers to the merged instruction.
+ bool UseNewDebugInstrNum = false;
+ unsigned NewDebugInstrNum;
+ if (I->peekDebugInstrNum() && Paired->peekDebugInstrNum()) {
+ // Both instructions contain debug instruction numbers. We need to set a
+ // new instruction number for the paired instruction and update the
+ // DBG_INSTR_REFs that reference the instruction numbers of both
+ // instructions and update them.
+ NewDebugInstrNum = MIB->getDebugInstrNum();
+ UseNewDebugInstrNum = true;
+ }
+ if (I->peekDebugInstrNum())
+ setDebugInstrNum(
+ I, MIB, I->peekDebugInstrNum(),
+ UseNewDebugInstrNum ? NewDebugInstrNum : I->peekDebugInstrNum(), MBB);
+
+ if (Paired->peekDebugInstrNum())
+ setDebugInstrNum(Paired, MIB, Paired->peekDebugInstrNum(),
+ UseNewDebugInstrNum ? NewDebugInstrNum
+ : Paired->peekDebugInstrNum(),
+ MBB);
+
LLVM_DEBUG(((MachineInstr *)MIB)->print(dbgs()));
}
LLVM_DEBUG(dbgs() << "\n");
diff --git a/llvm/test/CodeGen/AArch64/aarch64-ldst-opt-instr-ref.mir b/llvm/test/CodeGen/AArch64/aarch64-ldst-opt-instr-ref.mir
new file mode 100644
index 0000000000000..a293d65be5b40
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/aarch64-ldst-opt-instr-ref.mir
@@ -0,0 +1,79 @@
+# RUN: llc -mtriple=aarch64-unknown-linux-gnu -o - %s -run-pass=aarch64-ldst-opt | FileCheck %s
+
+# This testcase was obtained by looking at FileCheck.cpp and reducing it down via llvm-reduce
+
+# The aarch64-ldst-opt pass tries to merge load instructions from LDR* to a load pair or LDP* instruction, in such a case, we must ensure that the debug-instr-number is properly preserved for instruction referencing.
+
+# Check that in the case of a sign extend, the debug instruction number is transferred to the sign extend instruction (SBFMXri in this case), whereas the LDP instruction gets the other debug instruction number for the load that doesn't get sign extended.
+
+# CHECK: $w[[REG1:[0-9]+]], renamable $w[[REG2:[0-9]+]] = LDPWi renamable ${{[a-z0-9]+}}, 0, debug-instr-number [[DBG_INSTR_NUM1:[0-9]+]]
+# CHECK-NEXT: $w[[REG1]] = KILL $w[[REG1]], implicit-def $x[[REG1]]
+# CHECK-NEXT: $x[[REG1]] = SBFMXri $x[[REG1]], 0, 31, debug-instr-number [[DBG_INSTR_NUM2:[0-9]+]]
+# CHECK-NEXT: DBG_INSTR_REF ![[DBG1:[0-9]+]], !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_fragment, 64, 64), dbg-instr-ref([[DBG_INSTR_NUM1]], 1), debug-location ![[DBG2:[0-9]+]]
+# CHECK-NEXT: DBG_INSTR_REF ![[DBG1]], !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_fragment, 64, 32), dbg-instr-ref([[DBG_INSTR_NUM2]], 0), debug-location ![[DBG2]]
+
+# Check that in the case there is no sign extend, the LDP instruction gets a new debug instruction number and both the DBG_INSTR_REFs use the new instruction number.
+
+# CHECK: renamable $x[[REG3:[0-9]+]], renamable $x[[REG4:[0-9]+]] = LDPXi renamable ${{[a-z0-9]+}}, 0, debug-instr-number [[DBG_INSTR_NUM3:[0-9]+]]
+# CHECK-NEXT: DBG_INSTR_REF ![[DBG3:[0-9]+]], !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_fragment, 64, 64), dbg-instr-ref([[DBG_INSTR_NUM3]], 1), debug-location ![[DBG4:[0-9]+]]
+# CHECK-NEXT: DBG_INSTR_REF ![[DBG3]], !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_fragment, 64, 32), dbg-instr-ref([[DBG_INSTR_NUM3]], 0), debug-location ![[DBG4]]
+
+--- |
+ define i64 @_ZNK4llvm9StringRef4sizeEv(ptr readonly captures(none) %this) local_unnamed_addr #0 {
+ entry:
+ %Length = getelementptr i8, ptr %this, i64 8
+ %0 = load i64, ptr %Length, align 4
+ ret i64 %0
+ }
+ define ptr @_ZNK4llvm9StringRef4dataEv(ptr readonly captures(none) %this) local_unnamed_addr #0 {
+ entry:
+ %0 = load ptr, ptr %this, align 8
+ ret ptr %0
+ }
+ define void @_ZNK4llvm7Pattern5matchENS_9StringRefERKNS_9SourceMgrE(ptr readonly captures(none) %agg.result) local_unnamed_addr !dbg !3 {
+ %call1541 = load volatile ptr, ptr null, align 4294967296, !dbg !9
+ %FullMatch.sroa.1.0.agg.result.sroa_idx = getelementptr inbounds nuw i8, ptr %agg.result, i64 8
+ ret void
+ }
+ define void @_ZNK4llvm7Pattern5matchENS_9StringRefERKNS_9SourceMgrE2(ptr readonly captures(none) %agg.result) local_unnamed_addr !dbg !10 {
+ %call1541 = load volatile ptr, ptr null, align 4294967296, !dbg !11
+ %FullMatch.sroa.1.0.agg.result.sroa_idx = getelementptr inbounds nuw i8, ptr %agg.result, i64 8
+ ret void
+ }
+ !llvm.module.flags = !{!0}
+ !llvm.dbg.cu = !{!1}
+ !0 = !{i32 2, !"Debug Info Version", i32 3}
+ !1 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !2, isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, sdk: "MacOSX15.3.sdk")
+ !2 = !DIFile(filename: "/Users/shubhamrastogi/Development/llvm-project-instr-ref/llvm-project/llvm/lib/FileCheck/FileCheck.cpp", directory: "/Users/shubhamrastogi/Development/llvm-project-instr-ref/llvm-project/build-baseline-stage2", checksumkind: CSK_MD5, checksum: "ac1d2352ab68b965fe7993c780cf92d7")
+ !3 = distinct !DISubprogram(scope: null, type: !4, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !6)
+ !4 = distinct !DISubroutineType(types: !5)
+ !5 = !{}
+ !6 = !{!7}
+ !7 = !DILocalVariable(name: "FullMatch", scope: !3, line: 1152, type: !8)
+ !8 = distinct !DICompositeType(tag: DW_TAG_class_type, size: 128, identifier: "_ZTSN4llvm9StringRefE")
+ !9 = !DILocation(line: 0, scope: !3)
+ !10 = distinct !DISubprogram(scope: null, type: !4, spFlags: DISPFlagDefinition, unit: !1, retainedNodes: !12)
+ !11 = !DILocation(line: 0, scope: !10)
+ !12 = !{!13}
+ !13 = !DILocalVariable(name: "FullMatch", scope: !10, line: 1152, type: !14)
+ !14 = distinct !DICompositeType(tag: DW_TAG_class_type, size: 128, identifier: "_ZTSN4llvm9StringRefE")
+
+name: _ZNK4llvm9StringRef4sizeEv
+---
+name: _ZNK4llvm9StringRef4dataEv
+...
+name: _ZNK4llvm7Pattern5matchENS_9StringRefERKNS_9SourceMgrE
+body: |
+ bb.0 (%ir-block.0):
+ renamable $w1 = LDRWui renamable $x0, 1, debug-instr-number 1 :: (load (s64) from %ir.FullMatch.sroa.1.0.agg.result.sroa_idx, align 1)
+ DBG_INSTR_REF !7, !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_fragment, 64, 64), dbg-instr-ref(1, 0), debug-location !9
+ renamable $x0 = LDRSWui killed renamable $x0, 0, debug-instr-number 2 :: (load (s64) from %ir.agg.result)
+ DBG_INSTR_REF !7, !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_fragment, 64, 32), dbg-instr-ref(2, 0), debug-location !9
+...
+name: _ZNK4llvm7Pattern5matchENS_9StringRefERKNS_9SourceMgrE2
+body: |
+ bb.0 (%ir-block.0):
+ renamable $x1 = LDRXui renamable $x0, 1, debug-instr-number 1 :: (load (s64) from %ir.FullMatch.sroa.1.0.agg.result.sroa_idx, align 1)
+ DBG_INSTR_REF !13, !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_fragment, 64, 64), dbg-instr-ref(1, 0), debug-location !11
+ renamable $x0 = LDRXui killed renamable $x0, 0, debug-instr-number 2 :: (load (s64) from %ir.agg.result)
+ DBG_INSTR_REF !13, !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_fragment, 64, 32), dbg-instr-ref(2, 0), debug-location !11
More information about the llvm-commits
mailing list