Skip to content

Commit e097582

Browse files
authored
[DebugInfo][RemoveDIs] Instrument jump-threading to update DPValues (#73127)
This patch makes jump-threading handle non-instruction debug-info stored in DPValues in the same way that it updates dbg.values nowadays. This involves re-targetting their operands as with dbg.values getting moved from one block to another, and manually cloning them when duplicating blocks. The SSAUpdater class also grows some functions for SSA-updating DPValues in the same way as dbg.values. All of this is largely covered by existing debug-info tests, except for the cloning of DPValues attached to elidable instructions and branches, where I've added a test to thread-debug-info.ll. Where previously we could rely on dbg.values being copied and cloned as normal instructions are, as we need to explicitly perform that operation now I've added some explicit testing for it.
1 parent 906f598 commit e097582

File tree

5 files changed

+130
-5
lines changed

5 files changed

+130
-5
lines changed

llvm/include/llvm/Transforms/Utils/SSAUpdater.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class BasicBlock;
2323
class Instruction;
2424
class LoadInst;
2525
class PHINode;
26+
class DPValue;
2627
template <typename T> class SmallVectorImpl;
2728
template <typename T> class SSAUpdaterTraits;
2829
class Type;
@@ -123,6 +124,7 @@ class SSAUpdater {
123124
void UpdateDebugValues(Instruction *I);
124125
void UpdateDebugValues(Instruction *I,
125126
SmallVectorImpl<DbgValueInst *> &DbgValues);
127+
void UpdateDebugValues(Instruction *I, SmallVectorImpl<DPValue *> &DbgValues);
126128

127129
/// Rewrite a use like \c RewriteUse but handling in-block definitions.
128130
///
@@ -134,6 +136,7 @@ class SSAUpdater {
134136
private:
135137
Value *GetValueAtEndOfBlockInternal(BasicBlock *BB);
136138
void UpdateDebugValue(Instruction *I, DbgValueInst *DbgValue);
139+
void UpdateDebugValue(Instruction *I, DPValue *DbgValue);
137140
};
138141

139142
/// Helper class for promoting a collection of loads and stores into SSA

llvm/lib/Transforms/Scalar/JumpThreading.cpp

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,10 @@ static bool replaceFoldableUses(Instruction *Cond, Value *ToVal,
410410
if (Cond->getParent() == KnownAtEndOfBB)
411411
Changed |= replaceNonLocalUsesWith(Cond, ToVal);
412412
for (Instruction &I : reverse(*KnownAtEndOfBB)) {
413+
// Replace any debug-info record users of Cond with ToVal.
414+
for (DPValue &DPV : I.getDbgValueRange())
415+
DPV.replaceVariableLocationOp(Cond, ToVal, true);
416+
413417
// Reached the Cond whose uses we are trying to replace, so there are no
414418
// more uses.
415419
if (&I == Cond)
@@ -1961,6 +1965,7 @@ void JumpThreadingPass::updateSSA(
19611965
SSAUpdater SSAUpdate;
19621966
SmallVector<Use *, 16> UsesToRename;
19631967
SmallVector<DbgValueInst *, 4> DbgValues;
1968+
SmallVector<DPValue *, 4> DPValues;
19641969

19651970
for (Instruction &I : *BB) {
19661971
// Scan all uses of this instruction to see if it is used outside of its
@@ -1977,10 +1982,13 @@ void JumpThreadingPass::updateSSA(
19771982
}
19781983

19791984
// Find debug values outside of the block
1980-
findDbgValues(DbgValues, &I);
1985+
findDbgValues(DbgValues, &I, &DPValues);
19811986
llvm::erase_if(DbgValues, [&](const DbgValueInst *DbgVal) {
19821987
return DbgVal->getParent() == BB;
19831988
});
1989+
llvm::erase_if(DPValues, [&](const DPValue *DPVal) {
1990+
return DPVal->getParent() == BB;
1991+
});
19841992

19851993
// If there are no uses outside the block, we're done with this instruction.
19861994
if (UsesToRename.empty() && DbgValues.empty())
@@ -1996,9 +2004,11 @@ void JumpThreadingPass::updateSSA(
19962004

19972005
while (!UsesToRename.empty())
19982006
SSAUpdate.RewriteUse(*UsesToRename.pop_back_val());
1999-
if (!DbgValues.empty()) {
2007+
if (!DbgValues.empty() || !DPValues.empty()) {
20002008
SSAUpdate.UpdateDebugValues(&I, DbgValues);
2009+
SSAUpdate.UpdateDebugValues(&I, DPValues);
20012010
DbgValues.clear();
2011+
DPValues.clear();
20022012
}
20032013

20042014
LLVM_DEBUG(dbgs() << "\n");
@@ -2041,6 +2051,26 @@ JumpThreadingPass::cloneInstructions(BasicBlock::iterator BI,
20412051
return true;
20422052
};
20432053

2054+
// Duplicate implementation of the above dbg.value code, using DPValues
2055+
// instead.
2056+
auto RetargetDPValueIfPossible = [&](DPValue *DPV) {
2057+
SmallSet<std::pair<Value *, Value *>, 16> OperandsToRemap;
2058+
for (auto *Op : DPV->location_ops()) {
2059+
Instruction *OpInst = dyn_cast<Instruction>(Op);
2060+
if (!OpInst)
2061+
continue;
2062+
2063+
auto I = ValueMapping.find(OpInst);
2064+
if (I != ValueMapping.end())
2065+
OperandsToRemap.insert({OpInst, I->second});
2066+
}
2067+
2068+
for (auto &[OldOp, MappedOp] : OperandsToRemap)
2069+
DPV->replaceVariableLocationOp(OldOp, MappedOp);
2070+
};
2071+
2072+
BasicBlock *RangeBB = BI->getParent();
2073+
20442074
// Clone the phi nodes of the source basic block into NewBB. The resulting
20452075
// phi nodes are trivial since NewBB only has one predecessor, but SSAUpdater
20462076
// might need to rewrite the operand of the cloned phi.
@@ -2059,6 +2089,12 @@ JumpThreadingPass::cloneInstructions(BasicBlock::iterator BI,
20592089
identifyNoAliasScopesToClone(BI, BE, NoAliasScopes);
20602090
cloneNoAliasScopes(NoAliasScopes, ClonedScopes, "thread", Context);
20612091

2092+
auto CloneAndRemapDbgInfo = [&](Instruction *NewInst, Instruction *From) {
2093+
auto DPVRange = NewInst->cloneDebugInfoFrom(From);
2094+
for (DPValue &DPV : DPVRange)
2095+
RetargetDPValueIfPossible(&DPV);
2096+
};
2097+
20622098
// Clone the non-phi instructions of the source basic block into NewBB,
20632099
// keeping track of the mapping and using it to remap operands in the cloned
20642100
// instructions.
@@ -2069,6 +2105,8 @@ JumpThreadingPass::cloneInstructions(BasicBlock::iterator BI,
20692105
ValueMapping[&*BI] = New;
20702106
adaptNoAliasScopes(New, ClonedScopes, Context);
20712107

2108+
CloneAndRemapDbgInfo(New, &*BI);
2109+
20722110
if (RetargetDbgValueIfPossible(New))
20732111
continue;
20742112

@@ -2081,6 +2119,17 @@ JumpThreadingPass::cloneInstructions(BasicBlock::iterator BI,
20812119
}
20822120
}
20832121

2122+
// There may be DPValues on the terminator, clone directly from marker
2123+
// to marker as there isn't an instruction there.
2124+
if (BE != RangeBB->end() && BE->hasDbgValues()) {
2125+
// Dump them at the end.
2126+
DPMarker *Marker = RangeBB->getMarker(BE);
2127+
DPMarker *EndMarker = NewBB->createMarker(NewBB->end());
2128+
auto DPVRange = EndMarker->cloneDebugInfoFrom(Marker, std::nullopt);
2129+
for (DPValue &DPV : DPVRange)
2130+
RetargetDPValueIfPossible(&DPV);
2131+
}
2132+
20842133
return ValueMapping;
20852134
}
20862135

@@ -2666,13 +2715,18 @@ bool JumpThreadingPass::duplicateCondBranchOnPHIIntoPred(
26662715
if (!New->mayHaveSideEffects()) {
26672716
New->eraseFromParent();
26682717
New = nullptr;
2718+
// Clone debug-info on the elided instruction to the destination
2719+
// position.
2720+
OldPredBranch->cloneDebugInfoFrom(&*BI, std::nullopt, true);
26692721
}
26702722
} else {
26712723
ValueMapping[&*BI] = New;
26722724
}
26732725
if (New) {
26742726
// Otherwise, insert the new instruction into the block.
26752727
New->setName(BI->getName());
2728+
// Clone across any debug-info attached to the old instruction.
2729+
New->cloneDebugInfoFrom(&*BI);
26762730
// Update Dominance from simplified New instruction operands.
26772731
for (unsigned i = 0, e = New->getNumOperands(); i != e; ++i)
26782732
if (BasicBlock *SuccBB = dyn_cast<BasicBlock>(New->getOperand(i)))

llvm/lib/Transforms/Utils/SSAUpdater.cpp

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -199,12 +199,18 @@ void SSAUpdater::RewriteUse(Use &U) {
199199

200200
void SSAUpdater::UpdateDebugValues(Instruction *I) {
201201
SmallVector<DbgValueInst *, 4> DbgValues;
202-
llvm::findDbgValues(DbgValues, I);
202+
SmallVector<DPValue *, 4> DPValues;
203+
llvm::findDbgValues(DbgValues, I, &DPValues);
203204
for (auto &DbgValue : DbgValues) {
204205
if (DbgValue->getParent() == I->getParent())
205206
continue;
206207
UpdateDebugValue(I, DbgValue);
207208
}
209+
for (auto &DPV : DPValues) {
210+
if (DPV->getParent() == I->getParent())
211+
continue;
212+
UpdateDebugValue(I, DPV);
213+
}
208214
}
209215

210216
void SSAUpdater::UpdateDebugValues(Instruction *I,
@@ -214,16 +220,31 @@ void SSAUpdater::UpdateDebugValues(Instruction *I,
214220
}
215221
}
216222

223+
void SSAUpdater::UpdateDebugValues(Instruction *I,
224+
SmallVectorImpl<DPValue *> &DPValues) {
225+
for (auto &DPV : DPValues) {
226+
UpdateDebugValue(I, DPV);
227+
}
228+
}
229+
217230
void SSAUpdater::UpdateDebugValue(Instruction *I, DbgValueInst *DbgValue) {
218231
BasicBlock *UserBB = DbgValue->getParent();
219232
if (HasValueForBlock(UserBB)) {
220233
Value *NewVal = GetValueAtEndOfBlock(UserBB);
221234
DbgValue->replaceVariableLocationOp(I, NewVal);
222-
}
223-
else
235+
} else
224236
DbgValue->setKillLocation();
225237
}
226238

239+
void SSAUpdater::UpdateDebugValue(Instruction *I, DPValue *DPV) {
240+
BasicBlock *UserBB = DPV->getParent();
241+
if (HasValueForBlock(UserBB)) {
242+
Value *NewVal = GetValueAtEndOfBlock(UserBB);
243+
DPV->replaceVariableLocationOp(I, NewVal);
244+
} else
245+
DPV->setKillLocation();
246+
}
247+
227248
void SSAUpdater::RewriteUseAfterInsertions(Use &U) {
228249
Instruction *User = cast<Instruction>(U.getUser());
229250

llvm/test/Transforms/JumpThreading/redundant-dbg-info.ll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
; RUN: opt -passes=jump-threading -S < %s | FileCheck %s
2+
; RUN: opt -passes=jump-threading -S < %s --try-experimental-debuginfo-iterators | FileCheck %s
23

34
define dso_local i32 @_Z3fooi(i32 %a) !dbg !7 {
45
entry:

llvm/test/Transforms/JumpThreading/thread-debug-info.ll

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
; RUN: opt -S -passes=jump-threading < %s | FileCheck %s
2+
; RUN: opt -S -passes=jump-threading < %s --try-experimental-debuginfo-iterators | FileCheck %s
23

34
@a = global i32 0, align 4
45
; Test that the llvm.dbg.value calls in a threaded block are correctly updated to
@@ -91,6 +92,47 @@ exit: ; preds = %bb.f4, %bb.f3, %bb.
9192
ret void, !dbg !29
9293
}
9394

95+
; Test for the cloning of dbg.values on elided instructions -- down one path
96+
; being threaded, the `and` in the function below is optimised away, but its
97+
; debug-info should still be preserved.
98+
; Similarly, the call to f1 gets cloned, its dbg.value should be cloned too.
99+
define void @test16(i1 %c, i1 %c2, i1 %c3, i1 %c4) nounwind ssp !dbg !30 {
100+
; CHECK-LABEL: define void @test16(i1
101+
entry:
102+
%cmp = icmp sgt i32 undef, 1, !dbg !33
103+
br i1 %c, label %land.end, label %land.rhs, !dbg !33
104+
105+
land.rhs:
106+
br i1 %c2, label %lor.lhs.false.i, label %land.end, !dbg !33
107+
108+
lor.lhs.false.i:
109+
br i1 %c3, label %land.end, label %land.end, !dbg !33
110+
111+
; CHECK-LABEL: land.end.thr_comm:
112+
; CHECK-NEXT: call void @llvm.dbg.value(metadata i32 0,
113+
; CHECK-NEXT: call void @llvm.dbg.value(metadata i32 1,
114+
; CHECK-NEXT: call void @f1()
115+
; CHECK-NEXT: br i1 %c4,
116+
117+
; CHECK-LABEL: land.end:
118+
; CHECK-NEXT: %0 = phi i1
119+
; CHECK-NEXT: call void @llvm.dbg.value(metadata i32 0,
120+
land.end:
121+
%0 = phi i1 [ true, %entry ], [ false, %land.rhs ], [false, %lor.lhs.false.i], [false, %lor.lhs.false.i]
122+
call void @llvm.dbg.value(metadata i32 0, metadata !32, metadata !DIExpression()), !dbg !33
123+
%cmp12 = and i1 %cmp, %0, !dbg !33
124+
%xor1 = xor i1 %cmp12, %c4, !dbg !33
125+
call void @llvm.dbg.value(metadata i32 1, metadata !32, metadata !DIExpression()), !dbg !33
126+
call void @f1()
127+
br i1 %xor1, label %if.then, label %if.end, !dbg !33
128+
129+
if.then:
130+
ret void, !dbg !33
131+
132+
if.end:
133+
ret void, !dbg !33
134+
}
135+
94136
declare void @f1()
95137

96138
declare void @f2()
@@ -138,3 +180,7 @@ attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memo
138180
!27 = !DILocation(line: 13, column: 1, scope: !5)
139181
!28 = !DILocation(line: 14, column: 1, scope: !5)
140182
!29 = !DILocation(line: 15, column: 1, scope: !5)
183+
!30 = distinct !DISubprogram(name: "test13", linkageName: "test13", scope: null, file: !1, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !31)
184+
!31 = !{!32}
185+
!32 = !DILocalVariable(name: "1", scope: !30, file: !1, line: 1, type: !10)
186+
!33 = !DILocation(line: 1, column: 1, scope: !30)

0 commit comments

Comments
 (0)