Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[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

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

Apochens
Copy link
Contributor

Fix #136532 .

@llvmbot
Copy link
Member

llvmbot commented Apr 24, 2025

@llvm/pr-subscribers-llvm-transforms

Author: Shan Huang (Apochens)

Changes

Fix #136532 .


Full diff: https://github.com/llvm/llvm-project/pull/137124.diff

2 Files Affected:

  • (modified) llvm/lib/Transforms/Scalar/LoopDistribute.cpp (+2)
  • (added) llvm/test/Transforms/LoopDistribute/salvage-dbg-values-in-distributed-loops.ll (+159)
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,
+;.

@Apochens
Copy link
Contributor Author

Apochens commented May 5, 2025

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!

Copy link
Contributor

@OCHyams OCHyams left a 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

@Apochens
Copy link
Contributor Author

Apochens commented May 6, 2025

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)
Copy link
Contributor

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.

Copy link
Contributor Author

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_values left in the test. Each one is used to test the salvage in one of the distributed loops. Meanwhile, the DILocalVariables has also been shrunk, keeping the ones used in the checks.

Copy link
Contributor

@OCHyams OCHyams left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[DebugInfo][LoopDistribute] Removing instructions without salvaging the debug variable Info
3 participants