Skip to content

Commit 25e12af

Browse files
authored
merge amd-debug into amd-staging (llvm#1987)
2 parents a65b329 + 5530265 commit 25e12af

File tree

9 files changed

+330
-21
lines changed

9 files changed

+330
-21
lines changed

llvm/include/llvm/CodeGen/MachineFunction.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,8 @@ class LLVM_ABI MachineFunction {
614614
void substituteDebugValuesForInst(const MachineInstr &Old, MachineInstr &New,
615615
unsigned MaxOperand = UINT_MAX);
616616

617+
using SalvageCopySSAResult = std::pair<DebugInstrOperandPair, MachineInstr *>;
618+
617619
/// Find the underlying defining instruction / operand for a COPY instruction
618620
/// while in SSA form. Copies do not actually define values -- they move them
619621
/// between registers. Labelling a COPY-like instruction with an instruction
@@ -625,11 +627,11 @@ class LLVM_ABI MachineFunction {
625627
/// \p MI The copy-like instruction to salvage.
626628
/// \p DbgPHICache A container to cache already-solved COPYs.
627629
/// \returns An instruction/operand pair identifying the defining value.
628-
DebugInstrOperandPair
630+
SalvageCopySSAResult
629631
salvageCopySSA(MachineInstr &MI,
630-
DenseMap<Register, DebugInstrOperandPair> &DbgPHICache);
632+
DenseMap<Register, SalvageCopySSAResult> &DbgPHICache);
631633

632-
DebugInstrOperandPair salvageCopySSAImpl(MachineInstr &MI);
634+
SalvageCopySSAResult salvageCopySSAImpl(MachineInstr &MI);
633635

634636
/// Finalise any partially emitted debug instructions. These are DBG_INSTR_REF
635637
/// instructions where we only knew the vreg of the value they use, not the

llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1195,7 +1195,27 @@ std::optional<NewOpResult> DwarfExpression::traverse(DIOp::Select Select,
11951195

11961196
std::optional<NewOpResult> DwarfExpression::traverse(DIOp::Composite Composite,
11971197
ChildrenT Children) {
1198-
return std::nullopt;
1198+
if (IsFragment)
1199+
emitOp(dwarf::DW_OP_lit0);
1200+
1201+
for (auto &Child : Children) {
1202+
auto R = traverse(Child.get(), std::nullopt);
1203+
if (!R)
1204+
return std::nullopt;
1205+
TypeSize Size = R->Ty->getPrimitiveSizeInBits();
1206+
if (!Size.isFixed() || Size.getFixedValue() % 8 != 0)
1207+
return std::nullopt;
1208+
emitOp(dwarf::DW_OP_piece);
1209+
emitUnsigned(Size.getFixedValue() / 8);
1210+
}
1211+
emitUserOp(dwarf::DW_OP_LLVM_USER_piece_end);
1212+
1213+
if (IsFragment) {
1214+
emitOp(dwarf::DW_OP_swap);
1215+
emitOp(dwarf::DW_OP_drop);
1216+
}
1217+
1218+
return NewOpResult{Composite.getResultType(), ValueKind::LocationDesc};
11991219
}
12001220

12011221
std::optional<NewOpResult> DwarfExpression::traverseMathOp(uint8_t DwarfOp,

llvm/lib/CodeGen/MachineFunction.cpp

Lines changed: 143 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
#include "llvm/IR/BasicBlock.h"
4646
#include "llvm/IR/Constant.h"
4747
#include "llvm/IR/DataLayout.h"
48+
#include "llvm/IR/DebugInfoMetadata.h"
4849
#include "llvm/IR/DerivedTypes.h"
4950
#include "llvm/IR/EHPersonalities.h"
5051
#include "llvm/IR/Function.h"
@@ -1052,8 +1053,8 @@ void MachineFunction::substituteDebugValuesForInst(const MachineInstr &Old,
10521053
}
10531054

10541055
auto MachineFunction::salvageCopySSA(
1055-
MachineInstr &MI, DenseMap<Register, DebugInstrOperandPair> &DbgPHICache)
1056-
-> DebugInstrOperandPair {
1056+
MachineInstr &MI, DenseMap<Register, SalvageCopySSAResult> &DbgPHICache)
1057+
-> SalvageCopySSAResult {
10571058
const TargetInstrInfo &TII = *getSubtarget().getInstrInfo();
10581059

10591060
// Check whether this copy-like instruction has already been salvaged into
@@ -1077,7 +1078,7 @@ auto MachineFunction::salvageCopySSA(
10771078
}
10781079

10791080
auto MachineFunction::salvageCopySSAImpl(MachineInstr &MI)
1080-
-> DebugInstrOperandPair {
1081+
-> SalvageCopySSAResult {
10811082
MachineRegisterInfo &MRI = getRegInfo();
10821083
const TargetRegisterInfo &TRI = *MRI.getTargetRegisterInfo();
10831084
const TargetInstrInfo &TII = *getSubtarget().getInstrInfo();
@@ -1175,7 +1176,8 @@ auto MachineFunction::salvageCopySSAImpl(MachineInstr &MI)
11751176
for (auto &MO : Inst->all_defs()) {
11761177
if (MO.getReg() != State.first)
11771178
continue;
1178-
return ApplySubregisters({Inst->getDebugInstrNum(), MO.getOperandNo()});
1179+
return {ApplySubregisters({Inst->getDebugInstrNum(), MO.getOperandNo()}),
1180+
Inst};
11791181
}
11801182

11811183
llvm_unreachable("Vreg def with no corresponding operand?");
@@ -1195,8 +1197,9 @@ auto MachineFunction::salvageCopySSAImpl(MachineInstr &MI)
11951197
if (!TRI.regsOverlap(RegToSeek, MO.getReg()))
11961198
continue;
11971199

1198-
return ApplySubregisters(
1199-
{ToExamine.getDebugInstrNum(), MO.getOperandNo()});
1200+
return {
1201+
ApplySubregisters({ToExamine.getDebugInstrNum(), MO.getOperandNo()}),
1202+
&ToExamine};
12001203
}
12011204
}
12021205

@@ -1217,7 +1220,131 @@ auto MachineFunction::salvageCopySSAImpl(MachineInstr &MI)
12171220
Builder.addReg(State.first);
12181221
unsigned NewNum = getNewDebugInstrNum();
12191222
Builder.addImm(NewNum);
1220-
return ApplySubregisters({NewNum, 0u});
1223+
return {ApplySubregisters({NewNum, 0u}), nullptr};
1224+
}
1225+
1226+
/// The Op operand to the DBG_INSTR_REF instruction DbgInstr is a virtual
1227+
/// register defined by the REG_SEQUENCE instruction RegSeq. In order to
1228+
/// finalize DbgInstr to use instruction references, find the defining
1229+
/// instruction for each register in the sequence and compose them with a
1230+
/// DIOpComposite.
1231+
static bool finalizeInstrRefRegSequenceNew(
1232+
MachineInstr &DbgInstr, MachineOperand &Op, MachineInstr &RegSeq,
1233+
DenseMap<Register, MachineFunction::SalvageCopySSAResult> &DbgPHICache) {
1234+
1235+
const DIExpression *Expr = DbgInstr.getDebugExpression();
1236+
if (Expr->holdsOldElements())
1237+
return false;
1238+
1239+
auto &MF = *DbgInstr.getParent()->getParent();
1240+
auto &Ctx = Expr->getContext();
1241+
auto &TRI = *MF.getSubtarget().getRegisterInfo();
1242+
auto &TII = *MF.getSubtarget().getInstrInfo();
1243+
auto &DL = MF.getDataLayout();
1244+
1245+
struct Part {
1246+
MachineFunction::DebugInstrOperandPair DbgInstrNum;
1247+
unsigned Size;
1248+
unsigned Offset;
1249+
};
1250+
SmallVector<Part> Parts;
1251+
1252+
// Walk through the reg sequence, collecting debug-instr-numbers and
1253+
// subregister piece sizes and offsets into Parts.
1254+
for (unsigned I = 1; I < RegSeq.getNumOperands(); I += 2) {
1255+
Register RegOp = RegSeq.getOperand(I).getReg();
1256+
if (!RegOp.isVirtual())
1257+
return false;
1258+
1259+
unsigned SubReg = RegSeq.getOperand(I + 1).getImm();
1260+
unsigned SubSize = TRI.getSubRegIdxSize(SubReg);
1261+
unsigned SubOffset = TRI.getSubRegIdxOffset(SubReg);
1262+
MachineInstr &DefMI = *MF.getRegInfo().def_instr_begin(RegOp);
1263+
1264+
if (DefMI.isCopyLike() || TII.isCopyInstr(DefMI)) {
1265+
auto P = MF.salvageCopySSA(DefMI, DbgPHICache);
1266+
Parts.push_back({P.first, SubSize, SubOffset});
1267+
continue;
1268+
}
1269+
1270+
// Otherwise, identify the operand number that the VReg refers to.
1271+
unsigned OperandIdx = 0;
1272+
for (const auto &DefMO : DefMI.operands()) {
1273+
if (DefMO.isReg() && DefMO.isDef() && DefMO.getReg() == RegOp)
1274+
break;
1275+
++OperandIdx;
1276+
}
1277+
assert(OperandIdx < DefMI.getNumOperands());
1278+
1279+
// Morph this instr ref to point at the given instruction and operand.
1280+
unsigned ID = DefMI.getDebugInstrNum();
1281+
MachineFunction::DebugInstrOperandPair P{ID, OperandIdx};
1282+
Parts.push_back({P, SubSize, SubOffset});
1283+
}
1284+
1285+
// Line up the Parts and make sure there aren't any gaps, DIOpComposite can't
1286+
// handle that easily.
1287+
std::sort(Parts.begin(), Parts.end(),
1288+
[](auto &LHS, auto &RHS) { return LHS.Offset < RHS.Offset; });
1289+
for (unsigned I = 1, E = Parts.size(); I < E; ++I)
1290+
if (Parts[I - 1].Offset + Parts[I - 1].Size != Parts[I].Offset)
1291+
return false;
1292+
if (Parts.empty() || Parts[0].Offset)
1293+
return false;
1294+
1295+
unsigned ArgNoToReplace = 0;
1296+
unsigned NumArgs = DbgInstr.getNumDebugOperands();
1297+
assert(NumArgs == Expr->getNewNumLocationOperands());
1298+
for (; ArgNoToReplace != NumArgs; ++ArgNoToReplace)
1299+
if (&DbgInstr.getDebugOperand(ArgNoToReplace) == &Op)
1300+
break;
1301+
if (ArgNoToReplace == NumArgs)
1302+
return false;
1303+
1304+
auto Elems = Expr->getNewElementsRef();
1305+
auto NewSize = TypeSize::getFixed(Parts.back().Offset + Parts.back().Size);
1306+
for (DIOp::Variant Elem : *Elems) {
1307+
// Only replace the argument with a composite if it has the same size as the
1308+
// parts.
1309+
if (auto *Arg = std::get_if<DIOp::Arg>(&Elem))
1310+
if (Arg->getIndex() == ArgNoToReplace &&
1311+
DL.getTypeSizeInBits(Arg->getResultType()) != NewSize)
1312+
return false;
1313+
}
1314+
1315+
Op.ChangeToDbgInstrRef(Parts[0].DbgInstrNum.first,
1316+
Parts[0].DbgInstrNum.second);
1317+
if (Parts.size() == 1)
1318+
return true;
1319+
1320+
// Split up the DIOpArg using a DIOpComposite.
1321+
DIExprBuilder B{Ctx};
1322+
for (DIOp::Variant Elem : *Elems) {
1323+
auto *Arg = std::get_if<DIOp::Arg>(&Elem);
1324+
if (!Arg || Arg->getIndex() != ArgNoToReplace) {
1325+
B.append(Elem);
1326+
continue;
1327+
}
1328+
bool FirstPart = true;
1329+
for (const Part &P : Parts) {
1330+
// Since these arguments have to line up with the order of the operands on
1331+
// the DBG_INSTR_REF, recycle Arg's index first, it lines up with the Op
1332+
// that was ChangeToDbgInstrRef'd above.
1333+
unsigned ArgNo = FirstPart ? Arg->getIndex() : NumArgs++;
1334+
FirstPart = false;
1335+
B.append<DIOp::Arg>(ArgNo, IntegerType::get(Ctx, P.Size));
1336+
}
1337+
B.append<DIOp::Composite>(Parts.size(), Arg->getResultType());
1338+
}
1339+
1340+
auto *NewExpr = B.intoExpression();
1341+
for (const Part &P : drop_begin(Parts, 1))
1342+
DbgInstr.addOperand(MachineOperand::CreateDbgInstrRef(
1343+
P.DbgInstrNum.first, P.DbgInstrNum.second));
1344+
DbgInstr.getDebugExpressionOp() = MachineOperand::CreateMetadata(NewExpr);
1345+
assert(NewExpr->getNewNumLocationOperands() ==
1346+
DbgInstr.getNumDebugOperands());
1347+
return true;
12211348
}
12221349

12231350
void MachineFunction::finalizeDebugInstrRefs() {
@@ -1229,15 +1356,16 @@ void MachineFunction::finalizeDebugInstrRefs() {
12291356
MI.setDebugValueUndef();
12301357
};
12311358

1232-
DenseMap<Register, DebugInstrOperandPair> ArgDbgPHIs;
1359+
DenseMap<Register, SalvageCopySSAResult> ArgDbgPHIs;
12331360
for (auto &MBB : *this) {
12341361
for (auto &MI : MBB) {
12351362
if (!MI.isDebugRef())
12361363
continue;
12371364

12381365
bool IsValidRef = true;
12391366

1240-
for (MachineOperand &MO : MI.debug_operands()) {
1367+
for (unsigned I = 0; I < MI.getNumDebugOperands(); ++I) {
1368+
MachineOperand &MO = MI.getDebugOperand(I);
12411369
if (!MO.isReg())
12421370
continue;
12431371

@@ -1259,7 +1387,12 @@ void MachineFunction::finalizeDebugInstrRefs() {
12591387
// for why this is important.
12601388
if (DefMI.isCopyLike() || TII->isCopyInstr(DefMI)) {
12611389
auto Result = salvageCopySSA(DefMI, ArgDbgPHIs);
1262-
MO.ChangeToDbgInstrRef(Result.first, Result.second);
1390+
if (!Result.second || !Result.second->isRegSequence() ||
1391+
!finalizeInstrRefRegSequenceNew(MI, MO, *Result.second,
1392+
ArgDbgPHIs))
1393+
MO.ChangeToDbgInstrRef(Result.first.first, Result.first.second);
1394+
} else if (DefMI.isRegSequence() &&
1395+
finalizeInstrRefRegSequenceNew(MI, MO, DefMI, ArgDbgPHIs)) {
12631396
} else {
12641397
// Otherwise, identify the operand number that the VReg refers to.
12651398
unsigned OperandIdx = 0;

llvm/lib/CodeGen/SelectionDAG/InstrEmitter.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -882,7 +882,8 @@ InstrEmitter::EmitDbgInstrRef(SDDbgValue *SD,
882882
// Avoid copy like instructions: they don't define values, only move them.
883883
// Leave a virtual-register reference until it can be fixed up later, to
884884
// find the underlying value definition.
885-
if (DefMI->isCopyLike() || TII->isCopyInstr(*DefMI)) {
885+
if (DefMI->isCopyLike() || TII->isCopyInstr(*DefMI) ||
886+
(Expr->holdsNewElements() && DefMI->isRegSequence())) {
886887
AddVRegOp(VReg);
887888
continue;
888889
}

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)