-
Notifications
You must be signed in to change notification settings - Fork 13.4k
[DebugInfo][LoopDistribute] Salvage debug values using dead instructions in the distributed loops #137124
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
base: main
Are you sure you want to change the base?
[DebugInfo][LoopDistribute] Salvage debug values using dead instructions in the distributed loops #137124
Conversation
@llvm/pr-subscribers-llvm-transforms Author: Shan Huang (Apochens) ChangesFix #136532 . Full diff: https://github.com/llvm/llvm-project/pull/137124.diff 2 Files Affected:
diff --git a/llvm/lib/Transforms/Scalar/LoopDistribute.cpp b/llvm/lib/Transforms/Scalar/LoopDistribute.cpp
index e10d0c0defd96..0ac1a15981770 100644
--- a/llvm/lib/Transforms/Scalar/LoopDistribute.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopDistribute.cpp
@@ -58,6 +58,7 @@
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/Cloning.h"
+#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Transforms/Utils/LoopUtils.h"
#include "llvm/Transforms/Utils/LoopVersioning.h"
#include "llvm/Transforms/Utils/ValueMapper.h"
@@ -224,6 +225,7 @@ class InstPartition {
// Delete the instructions backwards, as it has a reduced likelihood of
// having to update as many def-use and use-def chains.
for (auto *Inst : reverse(Unused)) {
+ salvageDebugInfo(*Inst);
if (!Inst->use_empty())
Inst->replaceAllUsesWith(PoisonValue::get(Inst->getType()));
Inst->eraseFromParent();
diff --git a/llvm/test/Transforms/LoopDistribute/salvage-dbg-values-in-distributed-loops.ll b/llvm/test/Transforms/LoopDistribute/salvage-dbg-values-in-distributed-loops.ll
new file mode 100644
index 0000000000000..9927d796a3deb
--- /dev/null
+++ b/llvm/test/Transforms/LoopDistribute/salvage-dbg-values-in-distributed-loops.ll
@@ -0,0 +1,159 @@
+; RUN: opt -passes=loop-distribute -enable-loop-distribute -S < %s | FileCheck %s
+
+; Check that removeUnusedInsts() salvages `dbg_value`s which use dead
+; instructions in the distributed loops.
+
+define void @f(ptr noalias %a, ptr noalias %b, ptr noalias %c, ptr noalias %d, ptr noalias %e) !dbg !5 {
+; CHECK-LABEL: define void @f(
+; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]], ptr noalias [[D:%.*]], ptr noalias [[E:%.*]])
+
+; CHECK: for.body.ldist1:
+; CHECK-NEXT: [[IND_LDIST1:%.*]] = phi i64 [ 0, %[[ENTRY_SPLIT_LDIST1:.*]] ], [ [[ADD_LDIST1:%.*]], %for.body.ldist1 ], !dbg [[DBG28:![0-9]+]]
+
+; CHECK: store i32
+; CHECK-NEXT: #dbg_value(!DIArgList(ptr [[D]], i64 [[IND_LDIST1]]), [[META19:![0-9]+]], !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_constu, 4, DW_OP_mul, DW_OP_plus, DW_OP_stack_value), [[META37:![0-9]+]])
+; CHECK-NEXT: #dbg_value(i32 poison, [[META20:![0-9]+]], !DIExpression(), [[META38:![0-9]+]])
+; CHECK-NEXT: #dbg_value(!DIArgList(ptr [[E]], i64 [[IND_LDIST1]]), [[META21:![0-9]+]], !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_constu, 4, DW_OP_mul, DW_OP_plus, DW_OP_stack_value), [[META39:![0-9]+]])
+; CHECK-NEXT: #dbg_value(i32 poison, [[META22:![0-9]+]], !DIExpression(), [[META40:![0-9]+]])
+; CHECK-NEXT: #dbg_value(!DIArgList(i32 poison, i32 poison), [[META23:![0-9]+]], !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_mul, DW_OP_stack_value), [[META41:![0-9]+]])
+; CHECK-NEXT: #dbg_value(!DIArgList(ptr [[C]], i64 [[IND_LDIST1]]), [[META24:![0-9]+]], !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_constu, 4, DW_OP_mul, DW_OP_plus, DW_OP_stack_value), [[META42:![0-9]+]])
+; CHECK-NEXT: [[EXITCOND_LDIST1:%.*]] = icmp eq i64 [[ADD_LDIST1]], 20, !dbg [[DBG43:![0-9]+]]
+; CHECK-NEXT: #dbg_value(i1 [[EXITCOND_LDIST1]], [[META25:![0-9]+]], !DIExpression(), [[DBG43]])
+; CHECK-NEXT: br i1 [[EXITCOND_LDIST1]], label %[[ENTRY_SPLIT:.*]], label %for.body.ldist1, !dbg [[DBG44:![0-9]+]]
+
+; CHECK: for.body:
+; CHECK-NEXT: [[IND:%.*]] = phi i64 [ 0, %[[ENTRY_SPLIT:.*]] ], [ [[ADD:%.*]], %for.body ], !dbg [[DBG28]]
+; CHECK-NEXT: #dbg_value(i64 [[IND]], [[META9:![0-9]+]], !DIExpression(), [[DBG28]])
+; CHECK-NEXT: #dbg_value(!DIArgList(ptr [[A]], i64 [[IND]]), [[META11:![0-9]+]], !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_constu, 4, DW_OP_mul, DW_OP_plus, DW_OP_stack_value), [[DBG29:![0-9]+]])
+; CHECK-NEXT: #dbg_value(i32 poison, [[META12:![0-9]+]], !DIExpression(), [[DBG30:![0-9]+]])
+; CHECK-NEXT: #dbg_value(!DIArgList(ptr [[B]], i64 [[IND]]), [[META14:![0-9]+]], !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_constu, 4, DW_OP_mul, DW_OP_plus, DW_OP_stack_value), [[DBG31:![0-9]+]])
+; CHECK-NEXT: #dbg_value(i32 poison, [[META15:![0-9]+]], !DIExpression(), [[DBG32:![0-9]+]])
+; CHECK-NEXT: #dbg_value(!DIArgList(i32 poison, i32 poison), [[META16:![0-9]+]], !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_mul, DW_OP_stack_value), [[DBG33:![0-9]+]])
+; CHECK-NEXT: [[ADD]] = add nuw nsw i64 [[IND]], 1, !dbg [[DBG34:![0-9]+]]
+; CHECK-NEXT: #dbg_value(i64 [[ADD]], [[META17:![0-9]+]], !DIExpression(), [[DBG34]])
+; CHECK-NEXT: #dbg_value(!DIArgList(ptr [[A]], i64 [[ADD]]), [[META18:![0-9]+]], !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_arg, 1, DW_OP_constu, 4, DW_OP_mul, DW_OP_plus, DW_OP_stack_value), [[DBG35:![0-9]+]])
+;
+entry:
+ br label %for.body, !dbg !27
+
+for.body: ; preds = %for.body, %entry
+ %ind = phi i64 [ 0, %entry ], [ %add, %for.body ], !dbg !28
+ #dbg_value(i64 %ind, !9, !DIExpression(), !28)
+ %arrayidxA = getelementptr inbounds i32, ptr %a, i64 %ind, !dbg !29
+ #dbg_value(ptr %arrayidxA, !11, !DIExpression(), !29)
+ %loadA = load i32, ptr %arrayidxA, align 4, !dbg !30
+ #dbg_value(i32 %loadA, !12, !DIExpression(), !30)
+ %arrayidxB = getelementptr inbounds i32, ptr %b, i64 %ind, !dbg !31
+ #dbg_value(ptr %arrayidxB, !14, !DIExpression(), !31)
+ %loadB = load i32, ptr %arrayidxB, align 4, !dbg !32
+ #dbg_value(i32 %loadB, !15, !DIExpression(), !32)
+ %mulA = mul i32 %loadB, %loadA, !dbg !33
+ #dbg_value(i32 %mulA, !16, !DIExpression(), !33)
+ %add = add nuw nsw i64 %ind, 1, !dbg !34
+ #dbg_value(i64 %add, !17, !DIExpression(), !34)
+ %arrayidxA_plus_4 = getelementptr inbounds i32, ptr %a, i64 %add, !dbg !35
+ #dbg_value(ptr %arrayidxA_plus_4, !18, !DIExpression(), !35)
+ store i32 %mulA, ptr %arrayidxA_plus_4, align 4, !dbg !36
+ %arrayidxD = getelementptr inbounds i32, ptr %d, i64 %ind, !dbg !37
+ #dbg_value(ptr %arrayidxD, !19, !DIExpression(), !37)
+ %loadD = load i32, ptr %arrayidxD, align 4, !dbg !38
+ #dbg_value(i32 %loadD, !20, !DIExpression(), !38)
+ %arrayidxE = getelementptr inbounds i32, ptr %e, i64 %ind, !dbg !39
+ #dbg_value(ptr %arrayidxE, !21, !DIExpression(), !39)
+ %loadE = load i32, ptr %arrayidxE, align 4, !dbg !40
+ #dbg_value(i32 %loadE, !22, !DIExpression(), !40)
+ %mulC = mul i32 %loadD, %loadE, !dbg !41
+ #dbg_value(i32 %mulC, !23, !DIExpression(), !41)
+ %arrayidxC = getelementptr inbounds i32, ptr %c, i64 %ind, !dbg !42
+ #dbg_value(ptr %arrayidxC, !24, !DIExpression(), !42)
+ store i32 %mulC, ptr %arrayidxC, align 4, !dbg !43
+ %exitcond = icmp eq i64 %add, 20, !dbg !44
+ #dbg_value(i1 %exitcond, !25, !DIExpression(), !44)
+ br i1 %exitcond, label %for.end, label %for.body, !dbg !45
+
+for.end: ; preds = %for.body
+ ret void, !dbg !46
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.debugify = !{!2, !3}
+!llvm.module.flags = !{!4}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug)
+!1 = !DIFile(filename: "/app/example.ll", directory: "/")
+!2 = !{i32 20}
+!3 = !{i32 15}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!5 = distinct !DISubprogram(name: "f", linkageName: "f", scope: null, file: !1, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8)
+!6 = !DISubroutineType(types: !7)
+!7 = !{}
+!8 = !{!9, !11, !12, !14, !15, !16, !17, !18, !19, !20, !21, !22, !23, !24, !25}
+!9 = !DILocalVariable(name: "1", scope: !5, file: !1, line: 2, type: !10)
+!10 = !DIBasicType(name: "ty64", size: 64, encoding: DW_ATE_unsigned)
+!11 = !DILocalVariable(name: "2", scope: !5, file: !1, line: 3, type: !10)
+!12 = !DILocalVariable(name: "3", scope: !5, file: !1, line: 4, type: !13)
+!13 = !DIBasicType(name: "ty32", size: 32, encoding: DW_ATE_unsigned)
+!14 = !DILocalVariable(name: "4", scope: !5, file: !1, line: 5, type: !10)
+!15 = !DILocalVariable(name: "5", scope: !5, file: !1, line: 6, type: !13)
+!16 = !DILocalVariable(name: "6", scope: !5, file: !1, line: 7, type: !13)
+!17 = !DILocalVariable(name: "7", scope: !5, file: !1, line: 8, type: !10)
+!18 = !DILocalVariable(name: "8", scope: !5, file: !1, line: 9, type: !10)
+!19 = !DILocalVariable(name: "9", scope: !5, file: !1, line: 11, type: !10)
+!20 = !DILocalVariable(name: "10", scope: !5, file: !1, line: 12, type: !13)
+!21 = !DILocalVariable(name: "11", scope: !5, file: !1, line: 13, type: !10)
+!22 = !DILocalVariable(name: "12", scope: !5, file: !1, line: 14, type: !13)
+!23 = !DILocalVariable(name: "13", scope: !5, file: !1, line: 15, type: !13)
+!24 = !DILocalVariable(name: "14", scope: !5, file: !1, line: 16, type: !10)
+!25 = !DILocalVariable(name: "15", scope: !5, file: !1, line: 18, type: !26)
+!26 = !DIBasicType(name: "ty8", size: 8, encoding: DW_ATE_unsigned)
+!27 = !DILocation(line: 1, column: 1, scope: !5)
+!28 = !DILocation(line: 2, column: 1, scope: !5)
+!29 = !DILocation(line: 3, column: 1, scope: !5)
+!30 = !DILocation(line: 4, column: 1, scope: !5)
+!31 = !DILocation(line: 5, column: 1, scope: !5)
+!32 = !DILocation(line: 6, column: 1, scope: !5)
+!33 = !DILocation(line: 7, column: 1, scope: !5)
+!34 = !DILocation(line: 8, column: 1, scope: !5)
+!35 = !DILocation(line: 9, column: 1, scope: !5)
+!36 = !DILocation(line: 10, column: 1, scope: !5)
+!37 = !DILocation(line: 11, column: 1, scope: !5)
+!38 = !DILocation(line: 12, column: 1, scope: !5)
+!39 = !DILocation(line: 13, column: 1, scope: !5)
+!40 = !DILocation(line: 14, column: 1, scope: !5)
+!41 = !DILocation(line: 15, column: 1, scope: !5)
+!42 = !DILocation(line: 16, column: 1, scope: !5)
+!43 = !DILocation(line: 17, column: 1, scope: !5)
+!44 = !DILocation(line: 18, column: 1, scope: !5)
+!45 = !DILocation(line: 19, column: 1, scope: !5)
+!46 = !DILocation(line: 20, column: 1, scope: !5)
+;.
+; CHECK: [[META9]] = !DILocalVariable(name: "1",
+; CHECK: [[META11]] = !DILocalVariable(name: "2",
+; CHECK: [[META12]] = !DILocalVariable(name: "3",
+; CHECK: [[META14]] = !DILocalVariable(name: "4",
+; CHECK: [[META15]] = !DILocalVariable(name: "5",
+; CHECK: [[META16]] = !DILocalVariable(name: "6",
+; CHECK: [[META17]] = !DILocalVariable(name: "7",
+; CHECK: [[META18]] = !DILocalVariable(name: "8",
+; CHECK: [[META19]] = !DILocalVariable(name: "9",
+; CHECK: [[META20]] = !DILocalVariable(name: "10",
+; CHECK: [[META21]] = !DILocalVariable(name: "11",
+; CHECK: [[META22]] = !DILocalVariable(name: "12",
+; CHECK: [[META23]] = !DILocalVariable(name: "13",
+; CHECK: [[META24]] = !DILocalVariable(name: "14",
+; CHECK: [[META25]] = !DILocalVariable(name: "15",
+; CHECK: [[DBG28]] = !DILocation(line: 2, column: 1,
+; CHECK: [[DBG29]] = !DILocation(line: 3, column: 1,
+; CHECK: [[DBG30]] = !DILocation(line: 4, column: 1,
+; CHECK: [[DBG31]] = !DILocation(line: 5, column: 1,
+; CHECK: [[DBG33]] = !DILocation(line: 7, column: 1,
+; CHECK: [[DBG34]] = !DILocation(line: 8, column: 1,
+; CHECK: [[DBG35]] = !DILocation(line: 9, column: 1,
+; CHECK: [[META37]] = !DILocation(line: 11, column: 1,
+; CHECK: [[META39]] = !DILocation(line: 13, column: 1,
+; CHECK: [[META40]] = !DILocation(line: 14, column: 1,
+; CHECK: [[META41]] = !DILocation(line: 15, column: 1,
+; CHECK: [[META42]] = !DILocation(line: 16, column: 1,
+; CHECK: [[DBG43]] = !DILocation(line: 18, column: 1,
+; CHECK: [[DBG44]] = !DILocation(line: 19, column: 1,
+;.
|
Hi @OCHyams , just following up on this PR. It’s been open for a few days and I’d appreciate your feedback when you get a chance. Thanks! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry @Apochens, it got lost in the github notifications.
Would it be possible to reduce the test case a bit? If the dbg_value
s are all testing the same code path then just one is sufficient for the test. And if we can reduce the number of instructions too, that will help future maintainers understand what's going on.
Otherwise SGTM
Thanks @OCHyams ! I've refined the regression test by removing some instructions and checks in it. As a result, the test is more concise now. |
store i32 %loadD, ptr %arrayidxC, align 4, !dbg !31 | ||
|
||
%exitcond = icmp eq i64 %add, 20, !dbg !32 | ||
#dbg_value(i1 %exitcond, !19, !DIExpression(), !32) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need all the dbg_values? I feel like we probably get the same coverage (and a simpler test) if there's just one dbg_value
?
nit: please can you indent the dbg_values by two spaces? that's how LLVM prints them, and it's easier to read that way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now there are only two dbg_value
s left in the test. Each one is used to test the salvage in one of the distributed loops. Meanwhile, the DILocalVariable
s has also been shrunk, keeping the ones used in the checks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! LGTM
Fix #136532 .