Skip to content

[Transforms] Debug values are not remapped when cloning. #87747

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Apr 26, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion llvm/include/llvm/IR/IntrinsicInst.h
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,8 @@ class DbgVariableIntrinsic : public DbgInfoIntrinsic {

Value *getVariableLocationOp(unsigned OpIdx) const;

void replaceVariableLocationOp(Value *OldValue, Value *NewValue);
void replaceVariableLocationOp(Value *OldValue, Value *NewValue,
bool AllowEmpty = false);
void replaceVariableLocationOp(unsigned OpIdx, Value *NewValue);
/// Adding a new location operand will always result in this intrinsic using
/// an ArgList, and must always be accompanied by a new expression that uses
Expand Down
5 changes: 4 additions & 1 deletion llvm/lib/IR/IntrinsicInst.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,8 @@ static ValueAsMetadata *getAsMetadata(Value *V) {
}

void DbgVariableIntrinsic::replaceVariableLocationOp(Value *OldValue,
Value *NewValue) {
Value *NewValue,
bool AllowEmpty) {
// If OldValue is used as the address part of a dbg.assign intrinsic replace
// it with NewValue and return true.
auto ReplaceDbgAssignAddress = [this, OldValue, NewValue]() -> bool {
Expand All @@ -136,6 +137,8 @@ void DbgVariableIntrinsic::replaceVariableLocationOp(Value *OldValue,
auto Locations = location_ops();
auto OldIt = find(Locations, OldValue);
if (OldIt == Locations.end()) {
if (AllowEmpty || DbgAssignAddrReplaced)
return;
assert(DbgAssignAddrReplaced &&
"OldValue must be dbg.assign addr if unused in DIArgList");
return;
Expand Down
29 changes: 29 additions & 0 deletions llvm/lib/Transforms/Scalar/JumpThreading.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2694,6 +2694,35 @@ bool JumpThreadingPass::duplicateCondBranchOnPHIIntoPred(
New->setOperand(i, I->second);
}

// Remap debug variable operands.
auto RemapDebugVariable = [](auto &Mapping, auto *Inst) {
auto RemapDebugOperands = [&Mapping](auto *DV, auto Set) {
for (auto *Op : Set)
if (Instruction *InstOp = dyn_cast<Instruction>(Op)) {
auto I = Mapping.find(InstOp);
if (I != Mapping.end())
DV->replaceVariableLocationOp(Op, I->second, /*AllowEmpty=*/true);
}
};
auto RemapAssignAddress = [&Mapping](auto *DA) {
if (Instruction *Addr = dyn_cast<Instruction>(DA->getAddress())) {
auto I = Mapping.find(Addr);
if (I != Mapping.end())
DA->setAddress(I->second);
}
};
if (auto DVI = dyn_cast<DbgVariableIntrinsic>(Inst))
RemapDebugOperands(DVI, DVI->location_ops());
if (auto DAI = dyn_cast<DbgAssignIntrinsic>(Inst))
RemapAssignAddress(DAI);
for (DbgVariableRecord &DVR : filterDbgVars(Inst->getDbgRecordRange())) {
RemapDebugOperands(&DVR, DVR.location_ops());
if (DVR.isDbgAssign())
RemapAssignAddress(&DVR);
}
};
RemapDebugVariable(ValueMapping, New);

// If this instruction can be simplified after the operands are updated,
// just use the simplified value instead. This frequently happens due to
// phi translation.
Expand Down
29 changes: 29 additions & 0 deletions llvm/lib/Transforms/Utils/CloneFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1131,6 +1131,35 @@ BasicBlock *llvm::DuplicateInstructionsInSplitBetween(
if (I != ValueMapping.end())
New->setOperand(i, I->second);
}

// Remap debug variable operands.
auto RemapDebugVariable = [](auto &Mapping, auto *Inst) {
auto RemapDebugOperands = [&Mapping](auto *DV, auto Set) {
for (auto *Op : Set)
if (Instruction *InstOp = dyn_cast<Instruction>(Op)) {
auto I = Mapping.find(InstOp);
if (I != Mapping.end())
DV->replaceVariableLocationOp(Op, I->second, /*AllowEmpty=*/true);
}
};
auto RemapAssignAddress = [&Mapping](auto *DA) {
if (Instruction *Addr = dyn_cast<Instruction>(DA->getAddress())) {
auto I = Mapping.find(Addr);
if (I != Mapping.end())
DA->setAddress(I->second);
}
};
if (auto DVI = dyn_cast<DbgVariableIntrinsic>(Inst))
RemapDebugOperands(DVI, DVI->location_ops());
if (auto DAI = dyn_cast<DbgAssignIntrinsic>(Inst))
RemapAssignAddress(DAI);
for (DbgVariableRecord &DVR : filterDbgVars(Inst->getDbgRecordRange())) {
RemapDebugOperands(&DVR, DVR.location_ops());
if (DVR.isDbgAssign())
RemapAssignAddress(&DVR);
}
};
RemapDebugVariable(ValueMapping, New);
}

return NewBB;
Expand Down
36 changes: 35 additions & 1 deletion llvm/test/Transforms/CallSiteSplitting/callsite-split-debug.ll
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
; RUN: opt -S -passes=callsite-splitting -o - < %s | FileCheck %s
; RUN: opt -S -passes=callsite-splitting -o - < %s | FileCheck %s --check-prefixes=CHECK,CHECK-DEBUG
; RUN: opt -S -strip-debug -passes=callsite-splitting -o - < %s | FileCheck %s

define internal i16 @bar(i16 %p1, i16 %p2) {
Expand All @@ -8,6 +8,9 @@ define internal i16 @bar(i16 %p1, i16 %p2) {

define i16 @foo(i16 %in) {
bb0:
%a = alloca i16, align 4, !DIAssignID !12
call void @llvm.dbg.assign(metadata i1 undef, metadata !11, metadata !DIExpression(), metadata !12, metadata ptr %a, metadata !DIExpression()), !dbg !8
store i16 7, ptr %a, align 4, !DIAssignID !13
br label %bb1

bb1:
Expand All @@ -20,13 +23,21 @@ bb2:
CallsiteBB:
%1 = phi i16 [ 0, %bb1 ], [ 1, %bb2 ]
%c = phi i16 [ 2, %bb1 ], [ 3, %bb2 ]
%p = phi ptr [ %a, %bb1 ], [ %a, %bb2 ]
call void @llvm.dbg.value(metadata i16 %1, metadata !7, metadata !DIExpression()), !dbg !8
call void @llvm.dbg.value(metadata i16 %c, metadata !7, metadata !DIExpression()), !dbg !8
call void @llvm.dbg.value(metadata !DIArgList(i16 %1, i16 %c), metadata !7, metadata !DIExpression()), !dbg !8
call void @llvm.dbg.value(metadata !DIArgList(i16 %c, i16 %c), metadata !7, metadata !DIExpression()), !dbg !8
call void @llvm.dbg.assign(metadata i16 %1, metadata !11, metadata !DIExpression(), metadata !13, metadata ptr %a, metadata !DIExpression()), !dbg !8
call void @llvm.dbg.assign(metadata i16 %c, metadata !11, metadata !DIExpression(), metadata !13, metadata ptr %a, metadata !DIExpression()), !dbg !8
call void @llvm.dbg.assign(metadata i16 %1, metadata !11, metadata !DIExpression(), metadata !13, metadata ptr %p, metadata !DIExpression()), !dbg !8
%2 = call i16 @bar(i16 %1, i16 5)
ret i16 %2
}

; Function Attrs: nounwind readnone speculatable
declare void @llvm.dbg.value(metadata, metadata, metadata) #0
declare void @llvm.dbg.assign(metadata, metadata, metadata, metadata, metadata, metadata)

attributes #0 = { nounwind readnone speculatable }

Expand All @@ -43,14 +54,37 @@ attributes #0 = { nounwind readnone speculatable }
!6 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 4, unit: !0)
!7 = !DILocalVariable(name: "c", scope: !6, line: 5, type: !5)
!8 = !DILocation(line: 5, column: 7, scope: !6)
!11 = !DILocalVariable(name: "a", scope: !6, line: 6, type: !5)
!12 = distinct !DIAssignID()
!13 = distinct !DIAssignID()

; The optimization should trigger even in the presence of the dbg.value in
; CallSiteBB.

; CHECK-LABEL: @foo
; CHECK-LABEL: bb1.split:
; CHECK-DEBUG: call void @llvm.dbg.value(metadata i16 0, metadata ![[DBG_1:[0-9]+]], {{.*}}
; CHECK-DEBUG: call void @llvm.dbg.value(metadata i16 2, metadata ![[DBG_1]], {{.*}}
; CHECK-DEBUG: call void @llvm.dbg.value(metadata !DIArgList(i16 0, i16 2), {{.*}}
; CHECK-DEBUG: call void @llvm.dbg.value(metadata !DIArgList(i16 2, i16 2), {{.*}}
; CHECK-DEBUG: call void @llvm.dbg.assign(metadata i16 0, metadata ![[DBG_2:[0-9]+]], {{.*}}
; CHECK-DEBUG: call void @llvm.dbg.assign(metadata i16 2, metadata ![[DBG_2]], {{.*}}
; CHECK-DEBUG: call void @llvm.dbg.assign(metadata i16 0, metadata ![[DBG_2]], metadata !DIExpression(), metadata ![[ID_1:[0-9]+]], metadata ptr %a, {{.*}}
; CHECK: [[TMP1:%[0-9]+]] = call i16 @bar(i16 0, i16 5)

; CHECK-LABEL: bb2.split:
; CHECK-DEBUG: call void @llvm.dbg.value(metadata i16 1, metadata ![[DBG_1]], {{.*}}
; CHECK-DEBUG: call void @llvm.dbg.value(metadata i16 3, metadata ![[DBG_1]], {{.*}}
; CHECK-DEBUG: call void @llvm.dbg.value(metadata !DIArgList(i16 1, i16 3), {{.*}}
; CHECK-DEBUG: call void @llvm.dbg.value(metadata !DIArgList(i16 3, i16 3), {{.*}}
; CHECK-DEBUG: call void @llvm.dbg.assign(metadata i16 1, metadata ![[DBG_2]], {{.*}}
; CHECK-DEBUG: call void @llvm.dbg.assign(metadata i16 3, metadata ![[DBG_2]], {{.*}}
; CHECK-DEBUG: call void @llvm.dbg.assign(metadata i16 1, metadata ![[DBG_2]], metadata !DIExpression(), metadata ![[ID_1:[0-9]+]], metadata ptr %a, {{.*}}
; CHECK: [[TMP2:%[0-9]+]] = call i16 @bar(i16 1, i16 5)

; CHECK-LABEL: CallsiteBB
; CHECK: %phi.call = phi i16 [ [[TMP2]], %bb2.split ], [ [[TMP1]], %bb1.split

; CHECK-DEBUG-DAG: ![[DBG_1]] = !DILocalVariable(name: "c"{{.*}})
; CHECK-DEBUG-DAG: ![[DBG_2]] = !DILocalVariable(name: "a"{{.*}})
; CHECK-DEBUG-DAG: ![[ID_1]] = distinct !DIAssignID()