Skip to content

Commit e9a3ea2

Browse files
[SystemZ, DebugInfo] Instrument SystemZ backend passes for Instr-Ref DebugInfo (#133061)
This PR instruments the optimization passes in the SystemZ backend with calls to `MachineFunction::substituteDebugValuesForInst` where instruction substitutions are made to instructions that may compute tracked values. Tests are also added for each of the substitutions that were inserted. Details on the individual passes follow. ### systemz-copy-physregs When a copy targets an access register, we redirect the copy via an auxiliary register. This leads to the final result being written by a newly inserted SAR instruction, rather than the original MI, so we need to update the debug value tracking to account for this. ### systemz-long-branch This pass relaxes relative branch instructions based on the actual locations of blocks. Only one of the branch instructions qualifies for debug value tracking: BRCT, i.e. branch-relative-on-count, which subtracts 1 from a register and branches if the result is not zero. This is relaxed into an add-immediate and a conditional branch, so any `debug-instr-number` present must move to the add-immediate instruction. ### systemz-post-rewrite This pass replaces `LOCRMux` and `SELRMux` pseudoinstructions with either the real versions of those instructions, or with branching programs that implement the intent of the Pseudo. In all these cases, any `debug-instr-number` attached to the pseudo needs to be reallocated to the appropriate instruction in the result, either LOCR, SELR, or a COPY. ### systemz-elim-compare Similar to systemz-long-branch, for this pass, only few substitutions are necessary, since it mainly deals with conditional branch instructions. The only exceptiona are again branch-relative-on-count, as it modifies a counter as part of the instruction, as well as any of the load instructions that are affected.
1 parent 5edf127 commit e9a3ea2

File tree

8 files changed

+188
-16
lines changed

8 files changed

+188
-16
lines changed

llvm/lib/Target/SystemZ/SystemZCopyPhysRegs.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ bool SystemZCopyPhysRegs::visitMBB(MachineBasicBlock &MBB) {
7575
DebugLoc DL = MI->getDebugLoc();
7676
Register SrcReg = MI->getOperand(1).getReg();
7777
Register DstReg = MI->getOperand(0).getReg();
78+
7879
if (DstReg.isVirtual() &&
7980
(SrcReg == SystemZ::CC || SystemZ::AR32BitRegClass.contains(SrcReg))) {
8081
Register Tmp = MRI->createVirtualRegister(&SystemZ::GR32BitRegClass);
@@ -89,7 +90,10 @@ bool SystemZCopyPhysRegs::visitMBB(MachineBasicBlock &MBB) {
8990
SystemZ::AR32BitRegClass.contains(DstReg)) {
9091
Register Tmp = MRI->createVirtualRegister(&SystemZ::GR32BitRegClass);
9192
MI->getOperand(0).setReg(Tmp);
92-
BuildMI(MBB, MBBI, DL, TII->get(SystemZ::SAR), DstReg).addReg(Tmp);
93+
MachineInstr *NMI =
94+
BuildMI(MBB, MBBI, DL, TII->get(SystemZ::SAR), DstReg).addReg(Tmp);
95+
// SAR now writes the final value to DstReg, so update debug values.
96+
MBB.getParent()->substituteDebugValuesForInst(*MI, *NMI);
9397
Modified = true;
9498
}
9599
}

llvm/lib/Target/SystemZ/SystemZElimCompare.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,9 @@ bool SystemZElimCompare::convertToBRCT(
227227
// this is not necessary there.
228228
if (BRCT != SystemZ::BRCTH)
229229
MIB.addReg(SystemZ::CC, RegState::ImplicitDefine | RegState::Dead);
230+
// The debug instr tracking for the counter now used by BRCT needs to be
231+
// updated.
232+
MI.getParent()->getParent()->substituteDebugValuesForInst(MI, *MIB);
230233
MI.eraseFromParent();
231234
return true;
232235
}
@@ -268,6 +271,9 @@ bool SystemZElimCompare::convertToLoadAndTrap(
268271
.add(MI.getOperand(1))
269272
.add(MI.getOperand(2))
270273
.add(MI.getOperand(3));
274+
// The debug instr tracking for the load target now used by the load-and-trap
275+
// needs to be updated.
276+
MI.getParent()->getParent()->substituteDebugValuesForInst(MI, *Branch);
271277
MI.eraseFromParent();
272278
return true;
273279
}
@@ -288,6 +294,9 @@ bool SystemZElimCompare::convertToLoadAndTest(
288294
for (const auto &MO : MI.operands())
289295
MIB.add(MO);
290296
MIB.setMemRefs(MI.memoperands());
297+
// The debug instr tracking for the load target now needs to be updated
298+
// because the load has moved to a new instruction
299+
MI.getParent()->getParent()->substituteDebugValuesForInst(MI, *MIB);
291300
MI.eraseFromParent();
292301

293302
// Mark instruction as not raising an FP exception if applicable. We already

llvm/lib/Target/SystemZ/SystemZLongBranch.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -374,16 +374,19 @@ void SystemZLongBranch::splitBranchOnCount(MachineInstr *MI,
374374
unsigned AddOpcode) {
375375
MachineBasicBlock *MBB = MI->getParent();
376376
DebugLoc DL = MI->getDebugLoc();
377-
BuildMI(*MBB, MI, DL, TII->get(AddOpcode))
378-
.add(MI->getOperand(0))
379-
.add(MI->getOperand(1))
380-
.addImm(-1);
377+
MachineInstr *AddImm = BuildMI(*MBB, MI, DL, TII->get(AddOpcode))
378+
.add(MI->getOperand(0))
379+
.add(MI->getOperand(1))
380+
.addImm(-1);
381381
MachineInstr *BRCL = BuildMI(*MBB, MI, DL, TII->get(SystemZ::BRCL))
382382
.addImm(SystemZ::CCMASK_ICMP)
383383
.addImm(SystemZ::CCMASK_CMP_NE)
384384
.add(MI->getOperand(2));
385385
// The implicit use of CC is a killing use.
386386
BRCL->addRegisterKilled(SystemZ::CC, &TII->getRegisterInfo());
387+
// The result of the BRANCH ON COUNT MI is the new count in register 0, so the
388+
// debug tracking needs to go to the result of the Add immediate.
389+
MBB->getParent()->substituteDebugValuesForInst(*MI, *AddImm);
387390
MI->eraseFromParent();
388391
}
389392

@@ -402,6 +405,8 @@ void SystemZLongBranch::splitCompareBranch(MachineInstr *MI,
402405
.add(MI->getOperand(3));
403406
// The implicit use of CC is a killing use.
404407
BRCL->addRegisterKilled(SystemZ::CC, &TII->getRegisterInfo());
408+
// Since we are replacing branches that did not compute any value, no debug
409+
// value substitution is necessary.
405410
MI->eraseFromParent();
406411
}
407412

llvm/lib/Target/SystemZ/SystemZPostRewrite.cpp

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "llvm/ADT/Statistic.h"
2020
#include "llvm/CodeGen/LivePhysRegs.h"
2121
#include "llvm/CodeGen/MachineFunctionPass.h"
22+
#include "llvm/CodeGen/MachineInstr.h"
2223
#include "llvm/CodeGen/MachineInstrBuilder.h"
2324
using namespace llvm;
2425

@@ -108,15 +109,19 @@ void SystemZPostRewrite::selectSELRMux(MachineBasicBlock &MBB,
108109
bool DestIsHigh = SystemZ::isHighReg(DestReg);
109110
bool Src1IsHigh = SystemZ::isHighReg(Src1Reg);
110111
bool Src2IsHigh = SystemZ::isHighReg(Src2Reg);
112+
// A copy instruction that we might create, held here for the purpose of
113+
// debug instr value tracking.
114+
MachineInstr *CopyInst = nullptr;
111115

112116
// In rare cases both sources are the same register (after
113117
// machine-cse). This must be handled as it may lead to wrong-code (after
114118
// machine-cp) if the kill flag on Src1 isn't cleared (with
115119
// expandCondMove()).
116120
if (Src1Reg == Src2Reg) {
117-
BuildMI(*MBBI->getParent(), MBBI, MBBI->getDebugLoc(),
118-
TII->get(SystemZ::COPY), DestReg)
119-
.addReg(Src1Reg, getRegState(Src1MO) & getRegState(Src2MO));
121+
CopyInst = BuildMI(*MBBI->getParent(), MBBI, MBBI->getDebugLoc(),
122+
TII->get(SystemZ::COPY), DestReg)
123+
.addReg(Src1Reg, getRegState(Src1MO) & getRegState(Src2MO));
124+
MBB.getParent()->substituteDebugValuesForInst(*MBBI, *CopyInst, 1);
120125
MBBI->eraseFromParent();
121126
return;
122127
}
@@ -126,21 +131,24 @@ void SystemZPostRewrite::selectSELRMux(MachineBasicBlock &MBB,
126131
// first. But only if this doesn't clobber the other source.
127132
if (DestReg != Src1Reg && DestReg != Src2Reg) {
128133
if (DestIsHigh != Src1IsHigh) {
129-
BuildMI(*MBBI->getParent(), MBBI, MBBI->getDebugLoc(),
130-
TII->get(SystemZ::COPY), DestReg)
131-
.addReg(Src1Reg, getRegState(Src1MO));
134+
CopyInst = BuildMI(*MBBI->getParent(), MBBI, MBBI->getDebugLoc(),
135+
TII->get(SystemZ::COPY), DestReg)
136+
.addReg(Src1Reg, getRegState(Src1MO));
132137
Src1MO.setReg(DestReg);
133138
Src1Reg = DestReg;
134139
Src1IsHigh = DestIsHigh;
135140
} else if (DestIsHigh != Src2IsHigh) {
136-
BuildMI(*MBBI->getParent(), MBBI, MBBI->getDebugLoc(),
137-
TII->get(SystemZ::COPY), DestReg)
138-
.addReg(Src2Reg, getRegState(Src2MO));
141+
CopyInst = BuildMI(*MBBI->getParent(), MBBI, MBBI->getDebugLoc(),
142+
TII->get(SystemZ::COPY), DestReg)
143+
.addReg(Src2Reg, getRegState(Src2MO));
139144
Src2MO.setReg(DestReg);
140145
Src2Reg = DestReg;
141146
Src2IsHigh = DestIsHigh;
142147
}
143148
}
149+
// if a copy instruction was inserted, record the debug value substitution
150+
if (CopyInst)
151+
MBB.getParent()->substituteDebugValuesForInst(*MBBI, *CopyInst, 1);
144152

145153
// If the destination (now) matches one source, prefer this to be first.
146154
if (DestReg != Src1Reg && DestReg == Src2Reg) {
@@ -204,8 +212,11 @@ bool SystemZPostRewrite::expandCondMove(MachineBasicBlock &MBB,
204212

205213
// In MoveMBB, emit an instruction to move SrcReg into DestReg,
206214
// then fall through to RestMBB.
207-
BuildMI(*MoveMBB, MoveMBB->end(), DL, TII->get(SystemZ::COPY), DestReg)
208-
.addReg(MI.getOperand(2).getReg(), getRegState(MI.getOperand(2)));
215+
MachineInstr *CopyInst =
216+
BuildMI(*MoveMBB, MoveMBB->end(), DL, TII->get(SystemZ::COPY), DestReg)
217+
.addReg(MI.getOperand(2).getReg(), getRegState(MI.getOperand(2)));
218+
// record the debug value substitution for CopyInst
219+
MBB.getParent()->substituteDebugValuesForInst(*MBBI, *CopyInst, 1);
209220
MoveMBB->addSuccessor(RestMBB);
210221

211222
NextMBBI = MBB.end();
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# RUN: %python %s | llc -mtriple=s390x-linux-gnu -x mir --run-pass=systemz-long-branch \
2+
# RUN: | FileCheck %s
3+
4+
# CHECK: debugValueSubstitutions:
5+
# CHECK: - { srcinst: 1, srcop: 0, dstinst: 3, dstop: 0, subreg: 0 }
6+
# CHECK: - { srcinst: 1, srcop: 3, dstinst: 3, dstop: 3, subreg: 0 }
7+
# CHECK-NEXT: constants: []
8+
# CHECK: $r3l = AHI $r3l, -1
9+
# CHECK-NEXT: BRCL 14, 6, %bb.2
10+
print(" name: main")
11+
print(" alignment: 16")
12+
print(" tracksRegLiveness: true")
13+
print(" liveins: ")
14+
print(" - { reg: '$r1d', virtual-reg: '' }")
15+
print(" - { reg: '$r2d', virtual-reg: '' }")
16+
print(" - { reg: '$r3l', virtual-reg: '' }")
17+
print(" - { reg: '$r4l', virtual-reg: '' }")
18+
print(" debugValueSubstitutions: []")
19+
print(" body: |")
20+
print(" bb.0:")
21+
print(" liveins: $r3l, $r4l, $r2d, $r3d")
22+
print(" $r3l = BRCT $r3l, %bb.2, implicit-def $cc, debug-instr-number 1")
23+
print(" J %bb.1, debug-instr-number 2")
24+
print(" bb.1:")
25+
print(" liveins: $r1d, $r2d")
26+
for i in range(0, 8192):
27+
print(" $r1d = LGR $r2d")
28+
print(" $r2d = LGR $r1d")
29+
print(" Return implicit $r2d")
30+
print(" bb.2:")
31+
print(" liveins: $r4l")
32+
print(" Return implicit $r4l")
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Check that the backend properly tracks debug-instr-references across the
2+
# copy-physregs pass.
3+
#
4+
# RUN: llc %s -mtriple=s390x-linux-gnu -run-pass=systemz-copy-physregs \
5+
# RUN: -o - 2>&1 | FileCheck %s
6+
7+
# COPY 1: Copy VirtReg to AR
8+
# COPY 2: Copy AR to VirtReg
9+
# COPY 3: Copy CC to VirtReg
10+
# CHECK: name: foo
11+
# CHECK: debugValueSubstitutions:
12+
# these are the correct substitutions
13+
# CHECK-NEXT: - { srcinst: 1, srcop: 0, dstinst: 4, dstop: 0, subreg: 0 }
14+
# we also need to make sure that these are the only substitutions
15+
# CHECK-NEXT: constants: []
16+
name: foo
17+
body: |
18+
bb.0:
19+
liveins: $a1
20+
COPY def $a1, %1:gr32bit, debug-instr-number 1
21+
COPY def %2:gr32bit, $a1, debug-instr-number 2
22+
COPY def %3:gr32bit, $cc, debug-instr-number 3
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# Check that the backend properly tracks debug-instr-references across the
2+
# elim-compare pass.
3+
#
4+
# RUN: llc %s -mtriple=s390x-linux-gnu -mcpu=z14 -run-pass=systemz-elim-compare \
5+
# RUN: -o - 2>&1 | FileCheck %s
6+
7+
# bb.0 - elimination of CHI, modification of BRC, no substitutions
8+
# bb.1 - elimination of CHI, replacement of LR with LTR, one substitution
9+
# bb.2 - elimination of L and CHI, modification of CondTrap into LAT, one substitution
10+
# CHECK: name: foo
11+
# CHECK: debugValueSubstitutions:
12+
# these are the correct substitutions
13+
# CHECK-NEXT: - { srcinst: 5, srcop: 0, dstinst: 13, dstop: 0, subreg: 0 }
14+
# CHECK-NEXT: - { srcinst: 7, srcop: 0, dstinst: 9, dstop: 0, subreg: 0 }
15+
# CHECK-NEXT: - { srcinst: 10, srcop: 0, dstinst: 14, dstop: 0, subreg: 0 }
16+
# we also need to make sure that these are the only substitutions
17+
# CHECK-NEXT: constants: []
18+
---
19+
name: foo
20+
tracksRegLiveness: true
21+
liveins:
22+
- { reg: '$r2l', virtual-reg: '' }
23+
- { reg: '$r3l', virtual-reg: '' }
24+
- { reg: '$r4l', virtual-reg: '' }
25+
- { reg: '$r5d', virtual-reg: '' }
26+
debugValueSubstitutions: []
27+
body: |
28+
bb.0:
29+
successors: %bb.1(0x80000000)
30+
liveins: $r2l, $r3l, $r4l, $r5d
31+
32+
renamable $r3l = nsw AR killed renamable $r3l, renamable $r2l, implicit-def dead $cc, debug-instr-number 1
33+
CHI renamable $r3l, 0, implicit-def $cc, debug-instr-number 2
34+
BRC 14, 12, %bb.1, implicit $cc, debug-instr-number 3
35+
36+
bb.1:
37+
successors: %bb.2(0x80000000)
38+
liveins: $r2l, $r3l, $r4l, $r5d
39+
40+
CHI renamable $r2l, 0, implicit-def $cc, debug-instr-number 4
41+
renamable $r3l = LR renamable $r2l, debug-instr-number 5
42+
BRC 14, 8, %bb.2, implicit killed $cc, debug-instr-number 6
43+
44+
bb.2:
45+
successors: %bb.3(0x80000000)
46+
liveins: $r2l, $r3l, $r4l, $r5d
47+
48+
renamable $r2l = L killed renamable $r5d, 0, $noreg, debug-instr-number 7
49+
CHI renamable $r2l, 0, implicit-def $cc, debug-instr-number 8
50+
CondTrap 14, 8, implicit killed $cc, debug-instr-number 9
51+
J %bb.3
52+
53+
bb.3:
54+
successors: %bb.4(080000000)
55+
liveins: $r2l, $r3l, $r4l, $r5d
56+
57+
renamable $r3l = L renamable $r5d, 0, $noreg, debug-instr-number 10
58+
CHI renamable $r3l, 0, implicit-def $cc, debug-instr-number 11
59+
BRC 14, 8, %bb.4, implicit killed $cc, debug-instr-number 12
60+
61+
bb.4:
62+
$r2l = LHI 2
63+
Return implicit $r2l
64+
65+
...
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Check that the backend properly tracks debug-instr-references across the
2+
# post-rewrite pass.
3+
#
4+
# RUN: llc %s -mtriple=s390x-linux-gnu -run-pass=systemz-post-rewrite \
5+
# RUN: -o - 2>&1 | FileCheck %s
6+
7+
# SELRMux 1: simple replace with copy
8+
# SELRMux 2: simple mutation into selfhr
9+
# SELRMux 3: replace with if-then-else without prior copy
10+
# SELRMux 4: replace with if-then-else with prior copy
11+
# CHECK: name: foo
12+
# CHECK: debugValueSubstitutions:
13+
# CHECK-NEXT: - { srcinst: 1, srcop: 0, dstinst: 5, dstop: 0, subreg: 0 }
14+
# CHECK-NEXT: - { srcinst: 3, srcop: 0, dstinst: 6, dstop: 0, subreg: 0 }
15+
# CHECK-NEXT: - { srcinst: 4, srcop: 0, dstinst: 7, dstop: 0, subreg: 0 }
16+
# CHECK-NEXT: - { srcinst: 4, srcop: 0, dstinst: 8, dstop: 0, subreg: 0 }
17+
name: foo
18+
body: |
19+
bb.0:
20+
liveins: $r2h, $r3h, $r2l, $r3l, $cc
21+
SELRMux def $r2h, renamable $r3l, renamable $r3l, 1, 2, implicit $cc, debug-instr-number 1
22+
SELRMux def $r1h, renamable $r2h, renamable $r3h, 1, 2, implicit $cc, debug-instr-number 2
23+
SELRMux def $r2h, renamable $r2h, renamable $r3l, 1, 2, implicit $cc, debug-instr-number 3
24+
SELRMux def $r1h, renamable $r2l, renamable $r3l, 1, 2, implicit $cc, debug-instr-number 4

0 commit comments

Comments
 (0)