Skip to content

Commit 59eda75

Browse files
authored
[AMDGPU][SIInsertHardClauses] Maintain instruction referencing debug info (llvm#1826)
Fixes SWDEV-508737
1 parent 79db903 commit 59eda75

File tree

2 files changed

+100
-0
lines changed

2 files changed

+100
-0
lines changed

llvm/lib/Target/AMDGPU/SIInsertHardClauses.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,18 +167,61 @@ class SIInsertHardClauses {
167167
SmallVector<const MachineOperand *, 4> BaseOps;
168168
};
169169

170+
void substituteDebugInstrNumbersToBundleHeader(MachineInstr &FirstInBundle) {
171+
auto *MBB = FirstInBundle.getParent();
172+
auto *MF = MBB->getParent();
173+
174+
// Make a map from registers defined within the bundle to their defining
175+
// debug instruction number and operand.
176+
DenseMap<Register, std::pair<unsigned, unsigned>> RegDefs;
177+
for (const MachineOperand &Op : const_mi_bundle_ops(FirstInBundle)) {
178+
const MachineInstr &MI = *Op.getParent();
179+
if (!MI.isBundle() && Op.isReg() && Op.isDef())
180+
RegDefs[Op.getReg()] = {MI.peekDebugInstrNum(), Op.getOperandNo()};
181+
}
182+
183+
MachineInstr &BundleHeader = *std::prev(FirstInBundle.getIterator());
184+
for (const MachineOperand &HeaderOp : BundleHeader.operands()) {
185+
if (!HeaderOp.isReg() || !HeaderOp.isDef() || HeaderOp.isDead())
186+
continue;
187+
auto It = RegDefs.find(HeaderOp.getReg());
188+
if (It == RegDefs.end())
189+
continue;
190+
auto [DINum, OpNum] = It->second;
191+
if (DINum == 0)
192+
continue;
193+
MF->makeDebugValueSubstitution(
194+
{DINum, OpNum},
195+
{BundleHeader.getDebugInstrNum(), HeaderOp.getOperandNo()});
196+
}
197+
}
198+
170199
bool emitClause(const ClauseInfo &CI, const SIInstrInfo *SII) {
171200
if (CI.First == CI.Last)
172201
return false;
173202
assert(CI.Length <= ST->maxHardClauseLength() &&
174203
"Hard clause is too long!");
175204

176205
auto &MBB = *CI.First->getParent();
206+
bool NeedDebugSubs = false;
207+
// Move debug instructions before the bundle and check if debug
208+
// substitutions need to be added to the bundle header.
209+
for (auto It = CI.First->getIterator(),
210+
E = std::next(CI.Last->getIterator());
211+
It != E;) {
212+
auto MI = It++;
213+
if (MI->isDebugInstr())
214+
MBB.splice(CI.First, &MBB, MI);
215+
else if (MI->peekDebugInstrNum() != 0)
216+
NeedDebugSubs = true;
217+
}
177218
auto ClauseMI =
178219
BuildMI(MBB, *CI.First, DebugLoc(), SII->get(AMDGPU::S_CLAUSE))
179220
.addImm(CI.Length - 1);
180221
finalizeBundle(MBB, ClauseMI->getIterator(),
181222
std::next(CI.Last->getIterator()));
223+
if (NeedDebugSubs)
224+
substituteDebugInstrNumbersToBundleHeader(*ClauseMI);
182225
return true;
183226
}
184227

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
2+
# RUN: llc -mtriple=amdgcn -mcpu=gfx1200 -verify-machineinstrs -run-pass si-insert-hard-clauses %s -o - | FileCheck %s
3+
4+
# CHECK-LABEL: name: debug_instrs
5+
# CHECK-LABEL: debugValueSubstitutions:
6+
# CHECK-NEXT: - { srcinst: 3, srcop: 0, dstinst: 4, dstop: 0, subreg: 0 }
7+
# CHECK-NEXT: - { srcinst: 2, srcop: 0, dstinst: 4, dstop: 3, subreg: 0 }
8+
9+
---
10+
name: debug_instrs
11+
tracksRegLiveness: true
12+
debugInstrRef: true
13+
body: |
14+
bb.0:
15+
liveins: $sgpr0_sgpr1
16+
; CHECK: liveins: $sgpr0_sgpr1
17+
; CHECK-NEXT: {{ $}}
18+
; CHECK-NEXT: DBG_VALUE_LIST
19+
; CHECK-NEXT: DBG_PHI
20+
; CHECK-NEXT: DBG_INSTR_REF
21+
; CHECK-NEXT: BUNDLE implicit-def $sgpr3, implicit-def $sgpr3_lo16, implicit-def $sgpr3_hi16, implicit-def $sgpr2, implicit-def $sgpr2_lo16, implicit-def $sgpr2_hi16, implicit $sgpr0_sgpr1, debug-instr-number 4 {
22+
; CHECK-NEXT: S_CLAUSE 2
23+
; CHECK-NEXT: $sgpr3 = S_LOAD_DWORD_IMM $sgpr0_sgpr1, 0, 0, debug-instr-number 1
24+
; CHECK-NEXT: $sgpr2 = S_LOAD_DWORD_IMM $sgpr0_sgpr1, 4, 0, debug-instr-number 2
25+
; CHECK-NEXT: $sgpr3 = S_LOAD_DWORD_IMM $sgpr0_sgpr1, 8, 0, debug-instr-number 3
26+
; CHECK-NEXT: }
27+
; CHECK-NEXT: DBG_VALUE
28+
DBG_VALUE_LIST
29+
$sgpr3 = S_LOAD_DWORD_IMM $sgpr0_sgpr1, 0, 0, debug-instr-number 1
30+
DBG_PHI
31+
$sgpr2 = S_LOAD_DWORD_IMM $sgpr0_sgpr1, 4, 0, debug-instr-number 2
32+
DBG_INSTR_REF
33+
$sgpr3 = S_LOAD_DWORD_IMM $sgpr0_sgpr1, 8, 0, debug-instr-number 3
34+
DBG_VALUE
35+
...
36+
37+
# CHECK-LABEL: name: only_last_instr
38+
# CHECK-LABEL: debugValueSubstitutions:
39+
# CHECK-NEXT: - { srcinst: 1, srcop: 0, dstinst: 2, dstop: 3, subreg: 0 }
40+
41+
---
42+
name: only_last_instr
43+
tracksRegLiveness: true
44+
debugInstrRef: true
45+
body: |
46+
bb.0:
47+
liveins: $sgpr0_sgpr1
48+
; CHECK: liveins: $sgpr0_sgpr1
49+
; CHECK-NEXT: {{ $}}
50+
; CHECK-NEXT: BUNDLE implicit-def $sgpr2, implicit-def $sgpr2_lo16, implicit-def $sgpr2_hi16, implicit-def $sgpr3, implicit-def $sgpr3_lo16, implicit-def $sgpr3_hi16, implicit $sgpr0_sgpr1, debug-instr-number 2 {
51+
; CHECK-NEXT: S_CLAUSE 1
52+
; CHECK-NEXT: $sgpr2 = S_LOAD_DWORD_IMM $sgpr0_sgpr1, 4, 0
53+
; CHECK-NEXT: $sgpr3 = S_LOAD_DWORD_IMM $sgpr0_sgpr1, 8, 0, debug-instr-number 1
54+
; CHECK-NEXT: }
55+
$sgpr2 = S_LOAD_DWORD_IMM $sgpr0_sgpr1, 4, 0
56+
$sgpr3 = S_LOAD_DWORD_IMM $sgpr0_sgpr1, 8, 0, debug-instr-number 1
57+
...

0 commit comments

Comments
 (0)