Skip to content

Commit 4495485

Browse files
authored
[DebugInfo][RemoveDIs] Interpret DPValue objects in SelectionDAG (#72253)
DPValues are the non-intrinsic replacements for dbg.values, and when an IR function is converted by SelectionDAG we need to convert the variable location information in the same way. Happily all the information is in the same format, it's just stored in a slightly different object, therefore this patch refactors a few things to store the set of {Variable,Expr,DILocation,Location} instead of just a pointer to a DbgValueInst. This also adds a hook in llc that's much like the one I've added to opt in PR #71937, allowing tests to optionally ask for the use RemoveDIs mode if support for it is built into the compiler. I've added that flag to a variety of SelectionDAG debug-info tests to ensure that we get some coverage on the RemoveDIs / debug-info-iterator buildbot.
1 parent 2fe24fd commit 4495485

15 files changed

+176
-100
lines changed

llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp

Lines changed: 87 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1148,12 +1148,7 @@ SDValue SelectionDAGBuilder::getControlRoot() {
11481148
return updateRoot(PendingExports);
11491149
}
11501150

1151-
void SelectionDAGBuilder::visit(const Instruction &I) {
1152-
// Set up outgoing PHI node register values before emitting the terminator.
1153-
if (I.isTerminator()) {
1154-
HandlePHINodesInSuccessorBlocks(I.getParent());
1155-
}
1156-
1151+
void SelectionDAGBuilder::visitDbgInfo(const Instruction &I) {
11571152
// Add SDDbgValue nodes for any var locs here. Do so before updating
11581153
// SDNodeOrder, as this mapping is {Inst -> Locs BEFORE Inst}.
11591154
if (FunctionVarLocs const *FnVarLocs = DAG.getFunctionVarLocs()) {
@@ -1169,10 +1164,56 @@ void SelectionDAGBuilder::visit(const Instruction &I) {
11691164
}
11701165
SmallVector<Value *> Values(It->Values.location_ops());
11711166
if (!handleDebugValue(Values, Var, It->Expr, It->DL, SDNodeOrder,
1172-
It->Values.hasArgList()))
1173-
addDanglingDebugInfo(It, SDNodeOrder);
1167+
It->Values.hasArgList())) {
1168+
SmallVector<Value *, 4> Vals;
1169+
for (Value *V : It->Values.location_ops())
1170+
Vals.push_back(V);
1171+
addDanglingDebugInfo(Vals,
1172+
FnVarLocs->getDILocalVariable(It->VariableID),
1173+
It->Expr, Vals.size() > 1, It->DL, SDNodeOrder);
1174+
}
1175+
}
1176+
}
1177+
1178+
// Is there is any debug-info attached to this instruction, in the form of
1179+
// DPValue non-instruction debug-info records.
1180+
for (DPValue &DPV : I.getDbgValueRange()) {
1181+
DILocalVariable *Variable = DPV.getVariable();
1182+
DIExpression *Expression = DPV.getExpression();
1183+
dropDanglingDebugInfo(Variable, Expression);
1184+
1185+
// A DPValue with no locations is a kill location.
1186+
SmallVector<Value *, 4> Values(DPV.location_ops());
1187+
if (Values.empty()) {
1188+
handleKillDebugValue(Variable, Expression, DPV.getDebugLoc(),
1189+
SDNodeOrder);
1190+
continue;
1191+
}
1192+
1193+
// A DPValue with an undef or absent location is also a kill location.
1194+
if (llvm::any_of(Values,
1195+
[](Value *V) { return !V || isa<UndefValue>(V); })) {
1196+
handleKillDebugValue(Variable, Expression, DPV.getDebugLoc(),
1197+
SDNodeOrder);
1198+
continue;
1199+
}
1200+
1201+
bool IsVariadic = DPV.hasArgList();
1202+
if (!handleDebugValue(Values, Variable, Expression, DPV.getDebugLoc(),
1203+
SDNodeOrder, IsVariadic)) {
1204+
addDanglingDebugInfo(Values, Variable, Expression, IsVariadic,
1205+
DPV.getDebugLoc(), SDNodeOrder);
11741206
}
11751207
}
1208+
}
1209+
1210+
void SelectionDAGBuilder::visit(const Instruction &I) {
1211+
visitDbgInfo(I);
1212+
1213+
// Set up outgoing PHI node register values before emitting the terminator.
1214+
if (I.isTerminator()) {
1215+
HandlePHINodesInSuccessorBlocks(I.getParent());
1216+
}
11761217

11771218
// Increase the SDNodeOrder if dealing with a non-debug instruction.
11781219
if (!isa<DbgInfoIntrinsic>(I))
@@ -1232,14 +1273,12 @@ void SelectionDAGBuilder::visit(unsigned Opcode, const User &I) {
12321273
static bool handleDanglingVariadicDebugInfo(SelectionDAG &DAG,
12331274
DILocalVariable *Variable,
12341275
DebugLoc DL, unsigned Order,
1235-
RawLocationWrapper Values,
1276+
SmallVectorImpl<Value *> &Values,
12361277
DIExpression *Expression) {
1237-
if (!Values.hasArgList())
1238-
return false;
12391278
// For variadic dbg_values we will now insert an undef.
12401279
// FIXME: We can potentially recover these!
12411280
SmallVector<SDDbgOperand, 2> Locs;
1242-
for (const Value *V : Values.location_ops()) {
1281+
for (const Value *V : Values) {
12431282
auto *Undef = UndefValue::get(V->getType());
12441283
Locs.push_back(SDDbgOperand::fromConst(Undef));
12451284
}
@@ -1250,44 +1289,31 @@ static bool handleDanglingVariadicDebugInfo(SelectionDAG &DAG,
12501289
return true;
12511290
}
12521291

1253-
void SelectionDAGBuilder::addDanglingDebugInfo(const VarLocInfo *VarLoc,
1254-
unsigned Order) {
1255-
if (!handleDanglingVariadicDebugInfo(
1256-
DAG,
1257-
const_cast<DILocalVariable *>(DAG.getFunctionVarLocs()
1258-
->getVariable(VarLoc->VariableID)
1259-
.getVariable()),
1260-
VarLoc->DL, Order, VarLoc->Values, VarLoc->Expr)) {
1261-
DanglingDebugInfoMap[VarLoc->Values.getVariableLocationOp(0)].emplace_back(
1262-
VarLoc, Order);
1263-
}
1264-
}
1265-
1266-
void SelectionDAGBuilder::addDanglingDebugInfo(const DbgValueInst *DI,
1292+
void SelectionDAGBuilder::addDanglingDebugInfo(SmallVectorImpl<Value *> &Values,
1293+
DILocalVariable *Var,
1294+
DIExpression *Expr,
1295+
bool IsVariadic, DebugLoc DL,
12671296
unsigned Order) {
1268-
// We treat variadic dbg_values differently at this stage.
1269-
if (!handleDanglingVariadicDebugInfo(
1270-
DAG, DI->getVariable(), DI->getDebugLoc(), Order,
1271-
DI->getWrappedLocation(), DI->getExpression())) {
1272-
// TODO: Dangling debug info will eventually either be resolved or produce
1273-
// an Undef DBG_VALUE. However in the resolution case, a gap may appear
1274-
// between the original dbg.value location and its resolved DBG_VALUE,
1275-
// which we should ideally fill with an extra Undef DBG_VALUE.
1276-
assert(DI->getNumVariableLocationOps() == 1 &&
1277-
"DbgValueInst without an ArgList should have a single location "
1278-
"operand.");
1279-
DanglingDebugInfoMap[DI->getValue(0)].emplace_back(DI, Order);
1297+
if (IsVariadic) {
1298+
handleDanglingVariadicDebugInfo(DAG, Var, DL, Order, Values, Expr);
1299+
return;
12801300
}
1301+
// TODO: Dangling debug info will eventually either be resolved or produce
1302+
// an Undef DBG_VALUE. However in the resolution case, a gap may appear
1303+
// between the original dbg.value location and its resolved DBG_VALUE,
1304+
// which we should ideally fill with an extra Undef DBG_VALUE.
1305+
assert(Values.size() == 1);
1306+
DanglingDebugInfoMap[Values[0]].emplace_back(Var, Expr, DL, Order);
12811307
}
12821308

12831309
void SelectionDAGBuilder::dropDanglingDebugInfo(const DILocalVariable *Variable,
12841310
const DIExpression *Expr) {
12851311
auto isMatchingDbgValue = [&](DanglingDebugInfo &DDI) {
1286-
DIVariable *DanglingVariable = DDI.getVariable(DAG.getFunctionVarLocs());
1312+
DIVariable *DanglingVariable = DDI.getVariable();
12871313
DIExpression *DanglingExpr = DDI.getExpression();
12881314
if (DanglingVariable == Variable && Expr->fragmentsOverlap(DanglingExpr)) {
1289-
LLVM_DEBUG(dbgs() << "Dropping dangling debug info for " << printDDI(DDI)
1290-
<< "\n");
1315+
LLVM_DEBUG(dbgs() << "Dropping dangling debug info for "
1316+
<< printDDI(nullptr, DDI) << "\n");
12911317
return true;
12921318
}
12931319
return false;
@@ -1300,7 +1326,7 @@ void SelectionDAGBuilder::dropDanglingDebugInfo(const DILocalVariable *Variable,
13001326
// whether it can be salvaged.
13011327
for (auto &DDI : DDIV)
13021328
if (isMatchingDbgValue(DDI))
1303-
salvageUnresolvedDbgValue(DDI);
1329+
salvageUnresolvedDbgValue(DDIMI.first, DDI);
13041330

13051331
erase_if(DDIV, isMatchingDbgValue);
13061332
}
@@ -1319,7 +1345,7 @@ void SelectionDAGBuilder::resolveDanglingDebugInfo(const Value *V,
13191345
DebugLoc DL = DDI.getDebugLoc();
13201346
unsigned ValSDNodeOrder = Val.getNode()->getIROrder();
13211347
unsigned DbgSDNodeOrder = DDI.getSDNodeOrder();
1322-
DILocalVariable *Variable = DDI.getVariable(DAG.getFunctionVarLocs());
1348+
DILocalVariable *Variable = DDI.getVariable();
13231349
DIExpression *Expr = DDI.getExpression();
13241350
assert(Variable->isValidLocationForIntrinsic(DL) &&
13251351
"Expected inlined-at fields to agree");
@@ -1333,8 +1359,8 @@ void SelectionDAGBuilder::resolveDanglingDebugInfo(const Value *V,
13331359
// calling EmitFuncArgumentDbgValue here.
13341360
if (!EmitFuncArgumentDbgValue(V, Variable, Expr, DL,
13351361
FuncArgumentDbgValueKind::Value, Val)) {
1336-
LLVM_DEBUG(dbgs() << "Resolve dangling debug info for " << printDDI(DDI)
1337-
<< "\n");
1362+
LLVM_DEBUG(dbgs() << "Resolve dangling debug info for "
1363+
<< printDDI(V, DDI) << "\n");
13381364
LLVM_DEBUG(dbgs() << " By mapping to:\n "; Val.dump());
13391365
// Increase the SDNodeOrder for the DbgValue here to make sure it is
13401366
// inserted after the definition of Val when emitting the instructions
@@ -1348,9 +1374,11 @@ void SelectionDAGBuilder::resolveDanglingDebugInfo(const Value *V,
13481374
DAG.AddDbgValue(SDV, false);
13491375
} else
13501376
LLVM_DEBUG(dbgs() << "Resolved dangling debug info for "
1351-
<< printDDI(DDI) << " in EmitFuncArgumentDbgValue\n");
1377+
<< printDDI(V, DDI)
1378+
<< " in EmitFuncArgumentDbgValue\n");
13521379
} else {
1353-
LLVM_DEBUG(dbgs() << "Dropping debug info for " << printDDI(DDI) << "\n");
1380+
LLVM_DEBUG(dbgs() << "Dropping debug info for " << printDDI(V, DDI)
1381+
<< "\n");
13541382
auto Undef = UndefValue::get(V->getType());
13551383
auto SDV =
13561384
DAG.getConstantDbgValue(Variable, Expr, Undef, DL, DbgSDNodeOrder);
@@ -1360,14 +1388,14 @@ void SelectionDAGBuilder::resolveDanglingDebugInfo(const Value *V,
13601388
DDIV.clear();
13611389
}
13621390

1363-
void SelectionDAGBuilder::salvageUnresolvedDbgValue(DanglingDebugInfo &DDI) {
1391+
void SelectionDAGBuilder::salvageUnresolvedDbgValue(const Value *V,
1392+
DanglingDebugInfo &DDI) {
13641393
// TODO: For the variadic implementation, instead of only checking the fail
13651394
// state of `handleDebugValue`, we need know specifically which values were
13661395
// invalid, so that we attempt to salvage only those values when processing
13671396
// a DIArgList.
1368-
Value *V = DDI.getVariableLocationOp(0);
1369-
Value *OrigV = V;
1370-
DILocalVariable *Var = DDI.getVariable(DAG.getFunctionVarLocs());
1397+
const Value *OrigV = V;
1398+
DILocalVariable *Var = DDI.getVariable();
13711399
DIExpression *Expr = DDI.getExpression();
13721400
DebugLoc DL = DDI.getDebugLoc();
13731401
unsigned SDOrder = DDI.getSDNodeOrder();
@@ -1384,11 +1412,12 @@ void SelectionDAGBuilder::salvageUnresolvedDbgValue(DanglingDebugInfo &DDI) {
13841412
// a non-instruction is seen, such as a constant expression or global
13851413
// variable. FIXME: Further work could recover those too.
13861414
while (isa<Instruction>(V)) {
1387-
Instruction &VAsInst = *cast<Instruction>(V);
1415+
const Instruction &VAsInst = *cast<const Instruction>(V);
13881416
// Temporary "0", awaiting real implementation.
13891417
SmallVector<uint64_t, 16> Ops;
13901418
SmallVector<Value *, 4> AdditionalValues;
1391-
V = salvageDebugInfoImpl(VAsInst, Expr->getNumLocationOperands(), Ops,
1419+
V = salvageDebugInfoImpl(const_cast<Instruction &>(VAsInst),
1420+
Expr->getNumLocationOperands(), Ops,
13921421
AdditionalValues);
13931422
// If we cannot salvage any further, and haven't yet found a suitable debug
13941423
// expression, bail out.
@@ -1421,8 +1450,8 @@ void SelectionDAGBuilder::salvageUnresolvedDbgValue(DanglingDebugInfo &DDI) {
14211450
auto *Undef = UndefValue::get(OrigV->getType());
14221451
auto *SDV = DAG.getConstantDbgValue(Var, Expr, Undef, DL, SDNodeOrder);
14231452
DAG.AddDbgValue(SDV, false);
1424-
LLVM_DEBUG(dbgs() << "Dropping debug value info for:\n " << printDDI(DDI)
1425-
<< "\n");
1453+
LLVM_DEBUG(dbgs() << "Dropping debug value info for:\n "
1454+
<< printDDI(OrigV, DDI) << "\n");
14261455
}
14271456

14281457
void SelectionDAGBuilder::handleKillDebugValue(DILocalVariable *Var,
@@ -1572,7 +1601,7 @@ void SelectionDAGBuilder::resolveOrClearDbgInfo() {
15721601
// Try to fixup any remaining dangling debug info -- and drop it if we can't.
15731602
for (auto &Pair : DanglingDebugInfoMap)
15741603
for (auto &DDI : Pair.second)
1575-
salvageUnresolvedDbgValue(DDI);
1604+
salvageUnresolvedDbgValue(const_cast<Value *>(Pair.first), DDI);
15761605
clearDanglingDebugInfo();
15771606
}
15781607

@@ -6315,7 +6344,8 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
63156344
bool IsVariadic = DI.hasArgList();
63166345
if (!handleDebugValue(Values, Variable, Expression, DI.getDebugLoc(),
63176346
SDNodeOrder, IsVariadic))
6318-
addDanglingDebugInfo(&DI, SDNodeOrder);
6347+
addDanglingDebugInfo(Values, Variable, Expression, IsVariadic,
6348+
DI.getDebugLoc(), SDNodeOrder);
63196349
return;
63206350
}
63216351

llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h

Lines changed: 29 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -106,54 +106,39 @@ class SelectionDAGBuilder {
106106

107107
/// Helper type for DanglingDebugInfoMap.
108108
class DanglingDebugInfo {
109-
using DbgValTy = const DbgValueInst *;
110-
using VarLocTy = const VarLocInfo *;
111-
PointerUnion<DbgValTy, VarLocTy> Info;
112109
unsigned SDNodeOrder = 0;
113110

114111
public:
112+
DILocalVariable *Variable;
113+
DIExpression *Expression;
114+
DebugLoc dl;
115115
DanglingDebugInfo() = default;
116-
DanglingDebugInfo(const DbgValueInst *DI, unsigned SDNO)
117-
: Info(DI), SDNodeOrder(SDNO) {}
118-
DanglingDebugInfo(const VarLocInfo *VarLoc, unsigned SDNO)
119-
: Info(VarLoc), SDNodeOrder(SDNO) {}
120-
121-
DILocalVariable *getVariable(const FunctionVarLocs *Locs) const {
122-
if (isa<VarLocTy>(Info))
123-
return Locs->getDILocalVariable(cast<VarLocTy>(Info)->VariableID);
124-
return cast<DbgValTy>(Info)->getVariable();
125-
}
126-
DIExpression *getExpression() const {
127-
if (isa<VarLocTy>(Info))
128-
return cast<VarLocTy>(Info)->Expr;
129-
return cast<DbgValTy>(Info)->getExpression();
130-
}
131-
Value *getVariableLocationOp(unsigned Idx) const {
132-
assert(Idx == 0 && "Dangling variadic debug values not supported yet");
133-
if (isa<VarLocTy>(Info))
134-
return cast<VarLocTy>(Info)->Values.getVariableLocationOp(Idx);
135-
return cast<DbgValTy>(Info)->getVariableLocationOp(Idx);
136-
}
137-
DebugLoc getDebugLoc() const {
138-
if (isa<VarLocTy>(Info))
139-
return cast<VarLocTy>(Info)->DL;
140-
return cast<DbgValTy>(Info)->getDebugLoc();
141-
}
116+
DanglingDebugInfo(DILocalVariable *Var, DIExpression *Expr, DebugLoc DL,
117+
unsigned SDNO)
118+
: SDNodeOrder(SDNO), Variable(Var), Expression(Expr),
119+
dl(std::move(DL)) {}
120+
121+
DILocalVariable *getVariable() const { return Variable; }
122+
DIExpression *getExpression() const { return Expression; }
123+
DebugLoc getDebugLoc() const { return dl; }
142124
unsigned getSDNodeOrder() const { return SDNodeOrder; }
143125

144126
/// Helper for printing DanglingDebugInfo. This hoop-jumping is to
145-
/// accommodate the fact that an argument is required for getVariable.
127+
/// store a Value pointer, so that we can print a whole DDI as one object.
146128
/// Call SelectionDAGBuilder::printDDI instead of using directly.
147129
struct Print {
148-
Print(const DanglingDebugInfo &DDI, const FunctionVarLocs *VarLocs)
149-
: DDI(DDI), VarLocs(VarLocs) {}
130+
Print(const Value *V, const DanglingDebugInfo &DDI) : V(V), DDI(DDI) {}
131+
const Value *V;
150132
const DanglingDebugInfo &DDI;
151-
const FunctionVarLocs *VarLocs;
152133
friend raw_ostream &operator<<(raw_ostream &OS,
153134
const DanglingDebugInfo::Print &P) {
154-
OS << "DDI(var=" << *P.DDI.getVariable(P.VarLocs)
155-
<< ", val= " << *P.DDI.getVariableLocationOp(0)
156-
<< ", expr=" << *P.DDI.getExpression()
135+
OS << "DDI(var=" << *P.DDI.getVariable();
136+
if (P.V)
137+
OS << ", val=" << *P.V;
138+
else
139+
OS << ", val=nullptr";
140+
141+
OS << ", expr=" << *P.DDI.getExpression()
157142
<< ", order=" << P.DDI.getSDNodeOrder()
158143
<< ", loc=" << P.DDI.getDebugLoc() << ")";
159144
return OS;
@@ -164,8 +149,9 @@ class SelectionDAGBuilder {
164149
/// Returns an object that defines `raw_ostream &operator<<` for printing.
165150
/// Usage example:
166151
//// errs() << printDDI(MyDanglingInfo) << " is dangling\n";
167-
DanglingDebugInfo::Print printDDI(const DanglingDebugInfo &DDI) {
168-
return DanglingDebugInfo::Print(DDI, DAG.getFunctionVarLocs());
152+
DanglingDebugInfo::Print printDDI(const Value *V,
153+
const DanglingDebugInfo &DDI) {
154+
return DanglingDebugInfo::Print(V, DDI);
169155
}
170156

171157
/// Helper type for DanglingDebugInfoMap.
@@ -344,6 +330,7 @@ class SelectionDAGBuilder {
344330
ISD::NodeType ExtendType = ISD::ANY_EXTEND);
345331

346332
void visit(const Instruction &I);
333+
void visitDbgInfo(const Instruction &I);
347334

348335
void visit(unsigned Opcode, const User &I);
349336

@@ -352,8 +339,9 @@ class SelectionDAGBuilder {
352339
SDValue getCopyFromRegs(const Value *V, Type *Ty);
353340

354341
/// Register a dbg_value which relies on a Value which we have not yet seen.
355-
void addDanglingDebugInfo(const DbgValueInst *DI, unsigned Order);
356-
void addDanglingDebugInfo(const VarLocInfo *VarLoc, unsigned Order);
342+
void addDanglingDebugInfo(SmallVectorImpl<Value *> &Values,
343+
DILocalVariable *Var, DIExpression *Expr,
344+
bool IsVariadic, DebugLoc DL, unsigned Order);
357345

358346
/// If we have dangling debug info that describes \p Variable, or an
359347
/// overlapping part of variable considering the \p Expr, then this method
@@ -368,7 +356,7 @@ class SelectionDAGBuilder {
368356
/// For the given dangling debuginfo record, perform last-ditch efforts to
369357
/// resolve the debuginfo to something that is represented in this DAG. If
370358
/// this cannot be done, produce an Undef debug value record.
371-
void salvageUnresolvedDbgValue(DanglingDebugInfo &DDI);
359+
void salvageUnresolvedDbgValue(const Value *V, DanglingDebugInfo &DDI);
372360

373361
/// For a given list of Values, attempt to create and record a SDDbgValue in
374362
/// the SelectionDAG.

llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -719,10 +719,13 @@ void SelectionDAGISel::SelectBasicBlock(BasicBlock::const_iterator Begin,
719719
CurDAG->NewNodesMustHaveLegalTypes = false;
720720

721721
// Lower the instructions. If a call is emitted as a tail call, cease emitting
722-
// nodes for this block.
722+
// nodes for this block. If an instruction is elided, don't emit it, but do
723+
// handle any debug-info attached to it.
723724
for (BasicBlock::const_iterator I = Begin; I != End && !SDB->HasTailCall; ++I) {
724725
if (!ElidedArgCopyInstrs.count(&*I))
725726
SDB->visit(*I);
727+
else
728+
SDB->visitDbgInfo(*I);
726729
}
727730

728731
// Make sure the root of the DAG is up-to-date.

llvm/test/DebugInfo/X86/arg-dbg-value-list.ll

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
; RUN: llc %s -start-after=codegenprepare --experimental-debug-variable-locations=false -stop-before=finalize-isel -o - | FileCheck %s
66
; RUN: llc %s -start-after=codegenprepare --experimental-debug-variable-locations -stop-before=finalize-isel -o - | FileCheck %s
77

8+
; RUN: llc %s -start-after=codegenprepare --experimental-debug-variable-locations=false -stop-before=finalize-isel -o - --try-experimental-debuginfo-iterators | FileCheck %s
9+
; RUN: llc %s -start-after=codegenprepare --experimental-debug-variable-locations -stop-before=finalize-isel -o - --try-experimental-debuginfo-iterators | FileCheck %s
10+
811
;; Check that unused argument values are handled the same way for variadic
912
;; dbg_values as non-variadics.
1013

0 commit comments

Comments
 (0)