Skip to content

Commit 8a16422

Browse files
authored
[RemoveDIs] Add DPLabels support [3a/3] (#82633)
Patch 2 of 3 to add llvm.dbg.label support to the RemoveDIs project. The patch stack adds the DPLabel class, which is the RemoveDIs llvm.dbg.label equivalent. 1. Add DbgRecord base class for DPValue and the not-yet-added DPLabel class. 2. Add the DPLabel class. -> 3. Add support to passes. The next patch, #82639, will enable conversion between dbg.labels and DPLabels. AssignemntTrackingAnalysis support could have gone two ways: 1. Have the analysis store a DPLabel representation in its results - SelectionDAGBuilder reads the analysis results and ignores all DbgRecord kinds. 2. Ignore DPLabels in the analysis - SelectionDAGBuilder reads the analysis results but still needs to iterate over DPLabels from the IR. I went with option 2 because it's less work and is no less correct than 1. It's worth noting that causes labels to sink to the bottom of packs of debug records. e.g., [value, label, value] becomes [value, value, label]. This shouldn't be a problem because labels and variable locations don't have an ordering requirement. The ordering between variable locations is maintained and the label movement is deterministic
1 parent 3c90fce commit 8a16422

File tree

13 files changed

+114
-44
lines changed

13 files changed

+114
-44
lines changed

llvm/include/llvm/IR/DebugProgramInstruction.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,11 @@ class DbgRecord : public ilist_node<DbgRecord> {
157157
~DbgRecord() = default;
158158
};
159159

160+
inline raw_ostream &operator<<(raw_ostream &OS, const DbgRecord &R) {
161+
R.print(OS);
162+
return OS;
163+
}
164+
160165
/// Records a position in IR for a source label (DILabel). Corresponds to the
161166
/// llvm.dbg.label intrinsic.
162167
/// FIXME: Rename DbgLabelRecord when DPValue is renamed to DbgVariableRecord.
@@ -536,11 +541,6 @@ inline raw_ostream &operator<<(raw_ostream &OS, const DPMarker &Marker) {
536541
return OS;
537542
}
538543

539-
inline raw_ostream &operator<<(raw_ostream &OS, const DPValue &Value) {
540-
Value.print(OS);
541-
return OS;
542-
}
543-
544544
/// Inline helper to return a range of DPValues attached to a marker. It needs
545545
/// to be inlined as it's frequently called, but also come after the declaration
546546
/// of DPMarker. Thus: it's pre-declared by users like Instruction, then an

llvm/include/llvm/IR/IntrinsicInst.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,9 @@ class DbgAssignIntrinsic : public DbgValueInst {
531531
class DbgLabelInst : public DbgInfoIntrinsic {
532532
public:
533533
DILabel *getLabel() const { return cast<DILabel>(getRawLabel()); }
534+
void setLabel(DILabel *NewLabel) {
535+
setArgOperand(0, MetadataAsValue::get(getContext(), NewLabel));
536+
}
534537

535538
Metadata *getRawLabel() const {
536539
return cast<MetadataAsValue>(getArgOperand(0))->getMetadata();

llvm/lib/CodeGen/AssignmentTrackingAnalysis.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -829,11 +829,7 @@ class MemLocFragmentFill {
829829
void process(BasicBlock &BB, VarFragMap &LiveSet) {
830830
BBInsertBeforeMap[&BB].clear();
831831
for (auto &I : BB) {
832-
for (DbgRecord &DR : I.getDbgValueRange()) {
833-
// FIXME: DPValue::filter usage needs attention in this file; we need
834-
// to make sure dbg.labels are handled correctly in RemoveDIs mode.
835-
// Cast below to ensure this gets fixed when DPLabels are introduced.
836-
DPValue &DPV = cast<DPValue>(DR);
832+
for (DPValue &DPV : DPValue::filter(I.getDbgValueRange())) {
837833
if (const auto *Locs = FnVarLocs->getWedge(&DPV)) {
838834
for (const VarLocInfo &Loc : *Locs) {
839835
addDef(Loc, &DPV, *I.getParent(), LiveSet);
@@ -1919,6 +1915,9 @@ void AssignmentTrackingLowering::process(BasicBlock &BB, BlockInfo *LiveSet) {
19191915
// attached DPValues, or a non-debug instruction with attached unprocessed
19201916
// DPValues.
19211917
if (II != EI && II->hasDbgValues()) {
1918+
// Skip over non-variable debug records (i.e., labels). They're going to
1919+
// be read from IR (possibly re-ordering them within the debug record
1920+
// range) rather than from the analysis results.
19221921
for (DPValue &DPV : DPValue::filter(II->getDbgValueRange())) {
19231922
resetInsertionPoint(DPV);
19241923
processDPValue(DPV, LiveSet);

llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3275,7 +3275,17 @@ void IRTranslator::translateDbgDeclareRecord(Value *Address, bool HasArgList,
32753275

32763276
void IRTranslator::translateDbgInfo(const Instruction &Inst,
32773277
MachineIRBuilder &MIRBuilder) {
3278-
for (DPValue &DPV : DPValue::filter(Inst.getDbgValueRange())) {
3278+
for (DbgRecord &DR : Inst.getDbgValueRange()) {
3279+
if (DPLabel *DPL = dyn_cast<DPLabel>(&DR)) {
3280+
MIRBuilder.setDebugLoc(DPL->getDebugLoc());
3281+
assert(DPL->getLabel() && "Missing label");
3282+
assert(DPL->getLabel()->isValidLocationForIntrinsic(
3283+
MIRBuilder.getDebugLoc()) &&
3284+
"Expected inlined-at fields to agree");
3285+
MIRBuilder.buildDbgLabel(DPL->getLabel());
3286+
continue;
3287+
}
3288+
DPValue &DPV = cast<DPValue>(DR);
32793289
const DILocalVariable *Variable = DPV.getVariable();
32803290
const DIExpression *Expression = DPV.getExpression();
32813291
Value *V = DPV.getVariableLocationOp(0);

llvm/lib/CodeGen/SelectionDAG/FastISel.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1188,11 +1188,24 @@ void FastISel::handleDbgInfo(const Instruction *II) {
11881188
MIMD = MIMetadata();
11891189

11901190
// Reverse order of debug records, because fast-isel walks through backwards.
1191-
for (DbgRecord &DPR : llvm::reverse(II->getDbgValueRange())) {
1191+
for (DbgRecord &DR : llvm::reverse(II->getDbgValueRange())) {
11921192
flushLocalValueMap();
11931193
recomputeInsertPt();
11941194

1195-
DPValue &DPV = cast<DPValue>(DPR);
1195+
if (DPLabel *DPL = dyn_cast<DPLabel>(&DR)) {
1196+
assert(DPL->getLabel() && "Missing label");
1197+
if (!FuncInfo.MF->getMMI().hasDebugInfo()) {
1198+
LLVM_DEBUG(dbgs() << "Dropping debug info for " << *DPL << "\n");
1199+
continue;
1200+
}
1201+
1202+
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DPL->getDebugLoc(),
1203+
TII.get(TargetOpcode::DBG_LABEL))
1204+
.addMetadata(DPL->getLabel());
1205+
continue;
1206+
}
1207+
1208+
DPValue &DPV = cast<DPValue>(DR);
11961209

11971210
Value *V = nullptr;
11981211
if (!DPV.hasArgList())

llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1241,17 +1241,30 @@ void SelectionDAGBuilder::visitDbgInfo(const Instruction &I) {
12411241
It->Expr, Vals.size() > 1, It->DL, SDNodeOrder);
12421242
}
12431243
}
1244-
// We must early-exit here to prevent any DPValues from being emitted below,
1245-
// as we have just emitted the debug values resulting from assignment
1246-
// tracking analysis, making any existing DPValues redundant (and probably
1247-
// less correct).
1248-
return;
12491244
}
12501245

1246+
// We must skip DPValues if they've already been processed above as we
1247+
// have just emitted the debug values resulting from assignment tracking
1248+
// analysis, making any existing DPValues redundant (and probably less
1249+
// correct). We still need to process DPLabels. This does sink DPLabels
1250+
// to the bottom of the group of debug records. That sholdn't be important
1251+
// as it does so deterministcally and ordering between DPLabels and DPValues
1252+
// is immaterial (other than for MIR/IR printing).
1253+
bool SkipDPValues = DAG.getFunctionVarLocs();
12511254
// Is there is any debug-info attached to this instruction, in the form of
1252-
// DPValue non-instruction debug-info records.
1253-
for (DbgRecord &DPR : I.getDbgValueRange()) {
1254-
DPValue &DPV = cast<DPValue>(DPR);
1255+
// DbgRecord non-instruction debug-info records.
1256+
for (DbgRecord &DR : I.getDbgValueRange()) {
1257+
if (DPLabel *DPL = dyn_cast<DPLabel>(&DR)) {
1258+
assert(DPL->getLabel() && "Missing label");
1259+
SDDbgLabel *SDV =
1260+
DAG.getDbgLabel(DPL->getLabel(), DPL->getDebugLoc(), SDNodeOrder);
1261+
DAG.AddDbgLabel(SDV);
1262+
continue;
1263+
}
1264+
1265+
if (SkipDPValues)
1266+
continue;
1267+
DPValue &DPV = cast<DPValue>(DR);
12551268
DILocalVariable *Variable = DPV.getVariable();
12561269
DIExpression *Expression = DPV.getExpression();
12571270
dropDanglingDebugInfo(Variable, Expression);

llvm/lib/IR/AsmWriter.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1141,12 +1141,14 @@ void SlotTracker::processFunctionMetadata(const Function &F) {
11411141
void SlotTracker::processDbgRecordMetadata(const DbgRecord &DR) {
11421142
if (const DPValue *DPV = dyn_cast<const DPValue>(&DR)) {
11431143
CreateMetadataSlot(DPV->getVariable());
1144-
CreateMetadataSlot(DPV->getDebugLoc());
11451144
if (DPV->isDbgAssign())
11461145
CreateMetadataSlot(DPV->getAssignID());
1146+
} else if (const DPLabel *DPL = dyn_cast<const DPLabel>(&DR)) {
1147+
CreateMetadataSlot(DPL->getLabel());
11471148
} else {
11481149
llvm_unreachable("unsupported DbgRecord kind");
11491150
}
1151+
CreateMetadataSlot(DR.getDebugLoc());
11501152
}
11511153

11521154
void SlotTracker::processInstructionMetadata(const Instruction &I) {

llvm/lib/Transforms/Scalar/SpeculativeExecution.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -291,9 +291,9 @@ bool SpeculativeExecutionPass::considerHoistingFromTo(
291291
InstructionCost TotalSpeculationCost = 0;
292292
unsigned NotHoistedInstCount = 0;
293293
for (const auto &I : FromBlock) {
294-
// Make note of any DPValues that need hoisting.
295-
for (DbgRecord &DR : I.getDbgValueRange()) {
296-
DPValue &DPV = cast<DPValue>(DR);
294+
// Make note of any DPValues that need hoisting. DPLabels
295+
// get left behind just like llvm.dbg.labels.
296+
for (DPValue &DPV : DPValue::filter(I.getDbgValueRange())) {
297297
if (HasNoUnhoistedInstr(DPV.location_ops()))
298298
DPValuesToHoist[DPV.getInstruction()].push_back(&DPV);
299299
}

llvm/lib/Transforms/Utils/BasicBlockUtils.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,15 @@ static bool DPValuesRemoveRedundantDbgInstrsUsingBackwardScan(BasicBlock *BB) {
386386
SmallVector<DPValue *, 8> ToBeRemoved;
387387
SmallDenseSet<DebugVariable> VariableSet;
388388
for (auto &I : reverse(*BB)) {
389-
for (DPValue &DPV : reverse(DPValue::filter(I.getDbgValueRange()))) {
389+
for (DbgRecord &DR : reverse(I.getDbgValueRange())) {
390+
if (isa<DPLabel>(DR)) {
391+
// Emulate existing behaviour (see comment below for dbg.declares).
392+
// FIXME: Don't do this.
393+
VariableSet.clear();
394+
continue;
395+
}
396+
397+
DPValue &DPV = cast<DPValue>(DR);
390398
// Skip declare-type records, as the debug intrinsic method only works
391399
// on dbg.value intrinsics.
392400
if (DPV.getType() == DPValue::LocationType::Declare) {

llvm/lib/Transforms/Utils/CodeExtractor.cpp

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1585,8 +1585,30 @@ static void fixupDebugInfoPostExtraction(Function &OldFunc, Function &NewFunc,
15851585
return cast<DILocalVariable>(NewVar);
15861586
};
15871587

1588-
auto UpdateDPValuesOnInst = [&](Instruction &I) -> void {
1589-
for (DPValue &DPV : DPValue::filter(I.getDbgValueRange())) {
1588+
auto UpdateDbgLabel = [&](auto *LabelRecord) {
1589+
// Point the label record to a fresh label within the new function if
1590+
// the record was not inlined from some other function.
1591+
if (LabelRecord->getDebugLoc().getInlinedAt())
1592+
return;
1593+
DILabel *OldLabel = LabelRecord->getLabel();
1594+
DINode *&NewLabel = RemappedMetadata[OldLabel];
1595+
if (!NewLabel) {
1596+
DILocalScope *NewScope = DILocalScope::cloneScopeForSubprogram(
1597+
*OldLabel->getScope(), *NewSP, Ctx, Cache);
1598+
NewLabel = DILabel::get(Ctx, NewScope, OldLabel->getName(),
1599+
OldLabel->getFile(), OldLabel->getLine());
1600+
}
1601+
LabelRecord->setLabel(cast<DILabel>(NewLabel));
1602+
};
1603+
1604+
auto UpdateDbgRecordsOnInst = [&](Instruction &I) -> void {
1605+
for (DbgRecord &DR : I.getDbgValueRange()) {
1606+
if (DPLabel *DPL = dyn_cast<DPLabel>(&DR)) {
1607+
UpdateDbgLabel(DPL);
1608+
continue;
1609+
}
1610+
1611+
DPValue &DPV = cast<DPValue>(DR);
15901612
// Apply the two updates that dbg.values get: invalid operands, and
15911613
// variable metadata fixup.
15921614
if (any_of(DPV.location_ops(), IsInvalidLocation)) {
@@ -1599,13 +1621,11 @@ static void fixupDebugInfoPostExtraction(Function &OldFunc, Function &NewFunc,
15991621
}
16001622
if (!DPV.getDebugLoc().getInlinedAt())
16011623
DPV.setVariable(GetUpdatedDIVariable(DPV.getVariable()));
1602-
DPV.setDebugLoc(DebugLoc::replaceInlinedAtSubprogram(DPV.getDebugLoc(),
1603-
*NewSP, Ctx, Cache));
16041624
}
16051625
};
16061626

16071627
for (Instruction &I : instructions(NewFunc)) {
1608-
UpdateDPValuesOnInst(I);
1628+
UpdateDbgRecordsOnInst(I);
16091629

16101630
auto *DII = dyn_cast<DbgInfoIntrinsic>(&I);
16111631
if (!DII)
@@ -1614,17 +1634,7 @@ static void fixupDebugInfoPostExtraction(Function &OldFunc, Function &NewFunc,
16141634
// Point the intrinsic to a fresh label within the new function if the
16151635
// intrinsic was not inlined from some other function.
16161636
if (auto *DLI = dyn_cast<DbgLabelInst>(&I)) {
1617-
if (DLI->getDebugLoc().getInlinedAt())
1618-
continue;
1619-
DILabel *OldLabel = DLI->getLabel();
1620-
DINode *&NewLabel = RemappedMetadata[OldLabel];
1621-
if (!NewLabel) {
1622-
DILocalScope *NewScope = DILocalScope::cloneScopeForSubprogram(
1623-
*OldLabel->getScope(), *NewSP, Ctx, Cache);
1624-
NewLabel = DILabel::get(Ctx, NewScope, OldLabel->getName(),
1625-
OldLabel->getFile(), OldLabel->getLine());
1626-
}
1627-
DLI->setArgOperand(0, MetadataAsValue::get(Ctx, NewLabel));
1637+
UpdateDbgLabel(DLI);
16281638
continue;
16291639
}
16301640

@@ -1658,6 +1668,9 @@ static void fixupDebugInfoPostExtraction(Function &OldFunc, Function &NewFunc,
16581668
if (const DebugLoc &DL = I.getDebugLoc())
16591669
I.setDebugLoc(
16601670
DebugLoc::replaceInlinedAtSubprogram(DL, *NewSP, Ctx, Cache));
1671+
for (DbgRecord &DR : I.getDbgValueRange())
1672+
DR.setDebugLoc(DebugLoc::replaceInlinedAtSubprogram(DR.getDebugLoc(),
1673+
*NewSP, Ctx, Cache));
16611674

16621675
// Loop info metadata may contain line locations. Fix them up.
16631676
auto updateLoopInfoLoc = [&Ctx, &Cache, NewSP](Metadata *MD) -> Metadata * {

llvm/lib/Transforms/Utils/MemoryTaggingSupport.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,7 @@ Instruction *getUntagLocationIfFunctionExit(Instruction &Inst) {
111111

112112
void StackInfoBuilder::visit(Instruction &Inst) {
113113
// Visit non-intrinsic debug-info records attached to Inst.
114-
for (DbgRecord &DR : Inst.getDbgValueRange()) {
115-
DPValue &DPV = cast<DPValue>(DR);
114+
for (DPValue &DPV : DPValue::filter(Inst.getDbgValueRange())) {
116115
auto AddIfInteresting = [&](Value *V) {
117116
if (auto *AI = dyn_cast_or_null<AllocaInst>(V)) {
118117
if (!isInterestingAlloca(*AI))

llvm/lib/Transforms/Utils/ValueMapper.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,11 @@ Value *Mapper::mapValue(const Value *V) {
538538
}
539539

540540
void Mapper::remapDPValue(DbgRecord &DR) {
541+
if (DPLabel *DPL = dyn_cast<DPLabel>(&DR)) {
542+
DPL->setLabel(cast<DILabel>(mapMetadata(DPL->getLabel())));
543+
return;
544+
}
545+
541546
DPValue &V = cast<DPValue>(DR);
542547
// Remap variables and DILocations.
543548
auto *MappedVar = mapMetadata(V.getVariable());

llvm/test/Transforms/SpeculativeExecution/PR46267.ll

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,16 @@ land.rhs: ; preds = %entry
4141
; CHECK-NEXT: call void @llvm.dbg.declare(metadata ptr %y
4242
; CHECK-NEXT: %a0 = load i32, ptr undef, align 1
4343
; CHECK-NEXT: call void @llvm.dbg.value(metadata i32 %a0
44+
; CHECK-NEXT: call void @llvm.dbg.label
4445
call void @llvm.dbg.label(metadata !11), !dbg !10
4546
%y = alloca i32, align 4
4647
call void @llvm.dbg.declare(metadata ptr %y, metadata !14, metadata !DIExpression()), !dbg !10
4748

4849
%a0 = load i32, ptr undef, align 1
4950
call void @llvm.dbg.value(metadata i32 %a0, metadata !9, metadata !DIExpression()), !dbg !10
51+
;; RemoveDIs: Check a label that is attached to a hoisted instruction
52+
;; gets left behind (match intrinsic-style debug info behaviour).
53+
call void @llvm.dbg.label(metadata !15), !dbg !10
5054

5155
%a2 = add i32 %i, 0
5256
call void @llvm.dbg.value(metadata i32 %a2, metadata !13, metadata !DIExpression()), !dbg !10
@@ -82,3 +86,4 @@ attributes #1 = { nounwind readnone speculatable willreturn }
8286
!12 = !DILocalVariable(name: "x", scope: !6, file: !1, line: 3, type: !4)
8387
!13 = !DILocalVariable(name: "a2", scope: !6, file: !1, line: 3, type: !4)
8488
!14 = !DILocalVariable(name: "y", scope: !6, file: !1, line: 3, type: !4)
89+
!15 = !DILabel(scope: !6, name: "label2", file: !1, line: 2)

0 commit comments

Comments
 (0)