[llvm] [indvars] Missing variables at Og: (PR #69920)
Carlos Alberto Enciso via llvm-commits
llvm-commits at lists.llvm.org
Tue Jan 9 06:17:57 PST 2024
https://github.com/CarlosAlbertoEnciso updated https://github.com/llvm/llvm-project/pull/69920
>From 8313589dabc41763f0ce4e772e0df467b592afc9 Mon Sep 17 00:00:00 2001
From: Carlos Alberto Enciso <carlos.alberto.enciso at gmail.com>
Date: Mon, 23 Oct 2023 11:44:22 +0100
Subject: [PATCH 1/4] [indvars] Missing variables at Og:
https://bugs.llvm.org/show_bug.cgi?id=51735
https://github.com/llvm/llvm-project/issues/51077
In the given test case:
4 ...
5 void bar() {
6 int End = 777;
7 int Index = 27;
8 char Var = 1;
9 for (; Index < End; ++Index)
10 ;
11 nop(Index);
12 }
13 ...
Missing local variable 'Index' after loop 'Induction Variable Elimination'.
When adding a breakpoint at line 11, LLDB does not have information on
the variable. But it has info on 'Var' and 'End'.
---
llvm/lib/Transforms/Scalar/IndVarSimplify.cpp | 25 ++++
.../test/Transforms/LoopSimplify/pr51735-1.ll | 115 ++++++++++++++++++
llvm/test/Transforms/LoopSimplify/pr51735.ll | 106 ++++++++++++++++
3 files changed, 246 insertions(+)
create mode 100644 llvm/test/Transforms/LoopSimplify/pr51735-1.ll
create mode 100644 llvm/test/Transforms/LoopSimplify/pr51735.ll
diff --git a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
index 41c4d623617347..0e20b5e6204037 100644
--- a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
+++ b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
@@ -46,6 +46,7 @@
#include "llvm/IR/ConstantRange.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Function.h"
@@ -1931,6 +1932,30 @@ bool IndVarSimplify::run(Loop *L) {
}
}
+ // The loop exit values have been updated; insert the debug location
+ // for the induction variable with its final value.
+ if (PHINode *IndVar = L->getInductionVariable(*SE)) {
+ const SCEV *IndVarSCEV = SE->getSCEVAtScope(IndVar, L->getParentLoop());
+ if (IndVarSCEV->getSCEVType() == SCEVTypes::scConstant) {
+ Value *FinalIVValue = cast<SCEVConstant>(IndVarSCEV)->getValue();
+ SmallVector<DbgVariableIntrinsic *> DbgUsers;
+ SmallVector<DbgVariableIntrinsic *> DbgUsersCloned;
+ findDbgUsers(DbgUsers, IndVar);
+ for (auto &DebugUser : DbgUsers) {
+ auto *Cloned = cast<DbgVariableIntrinsic>(DebugUser->clone());
+ Cloned->replaceVariableLocationOp(static_cast<unsigned>(0),
+ FinalIVValue);
+ DbgUsersCloned.push_back(Cloned);
+ }
+
+ SmallVector<BasicBlock *> ExitBlocks;
+ L->getExitBlocks(ExitBlocks);
+ for (BasicBlock *Exit : ExitBlocks)
+ for (auto &DebugUser : DbgUsersCloned)
+ DebugUser->insertBefore(Exit->getFirstNonPHI());
+ }
+ }
+
// Eliminate redundant IV cycles.
NumElimIV += Rewriter.replaceCongruentIVs(L, DT, DeadInsts, TTI);
diff --git a/llvm/test/Transforms/LoopSimplify/pr51735-1.ll b/llvm/test/Transforms/LoopSimplify/pr51735-1.ll
new file mode 100644
index 00000000000000..de9a7452209565
--- /dev/null
+++ b/llvm/test/Transforms/LoopSimplify/pr51735-1.ll
@@ -0,0 +1,115 @@
+; RUN: opt -passes=indvars -S -o - < %s | FileCheck %s
+
+; Missing local variable 'Index' after loop 'Induction Variable Elimination'.
+; When adding a breakpoint at line 11, LLDB does not have information on
+; the variable. But it has info on 'Var' and 'End'.
+
+; 1 __attribute__((optnone)) int nop(int Param) {
+; 2 return 0;
+; 3 }
+; 4
+; 5 void bar() {
+; 6 int End = 777;
+; 7 int Index = 27;
+; 8 char Var = 1;
+; 9 for (; Index < End; ++Index)
+; 10 ;
+; 11 nop(Index);
+; 12 }
+; 13
+; 14 int main () {
+; 15 bar();
+; 16 }
+
+; CHECK: for.cond: {{.*}}
+; CHECK: call void @llvm.dbg.value(metadata i32 poison, metadata ![[DBG:[0-9]+]], {{.*}}
+; CHECK: call void @llvm.dbg.value(metadata i32 poison, metadata ![[DBG:[0-9]+]], {{.*}}
+; CHECK: br i1 false, label %for.cond, label %for.end, {{.*}}
+; CHECK: for.end: {{.*}}
+; CHECK: call void @llvm.dbg.value(metadata i32 777, metadata ![[DBG:[0-9]+]], {{.*}}
+; CHECK: %call = tail call noundef i32 @_Z3nopi(i32 noundef 777), {{.*}}
+; CHECK-DAG: ![[DBG]] = !DILocalVariable(name: "Index"{{.*}})
+
+define dso_local noundef i32 @_Z3nopi(i32 noundef %Param) local_unnamed_addr #0 !dbg !10 {
+entry:
+ %Param.addr = alloca i32, align 4
+ store i32 %Param, ptr %Param.addr, align 4
+ call void @llvm.dbg.declare(metadata ptr %Param.addr, metadata !15, metadata !DIExpression()), !dbg !16
+ ret i32 0, !dbg !17
+}
+
+define dso_local void @_Z3barv() local_unnamed_addr #2 !dbg !18 {
+entry:
+ call void @llvm.dbg.value(metadata i32 777, metadata !21, metadata !DIExpression()), !dbg !22
+ call void @llvm.dbg.value(metadata i32 27, metadata !23, metadata !DIExpression()), !dbg !22
+ call void @llvm.dbg.value(metadata i32 1, metadata !24, metadata !DIExpression()), !dbg !22
+ br label %for.cond, !dbg !25
+
+for.cond: ; preds = %for.cond, %entry
+ %Index.0 = phi i32 [ 27, %entry ], [ %inc, %for.cond ], !dbg !22
+ call void @llvm.dbg.value(metadata i32 %Index.0, metadata !23, metadata !DIExpression()), !dbg !22
+ %cmp = icmp ult i32 %Index.0, 777, !dbg !26
+ %inc = add nuw nsw i32 %Index.0, 1, !dbg !29
+ call void @llvm.dbg.value(metadata i32 %inc, metadata !23, metadata !DIExpression()), !dbg !22
+ br i1 %cmp, label %for.cond, label %for.end, !dbg !30, !llvm.loop !31
+
+for.end: ; preds = %for.cond
+ %Index.0.lcssa = phi i32 [ %Index.0, %for.cond ], !dbg !22
+ %call = tail call noundef i32 @_Z3nopi(i32 noundef %Index.0.lcssa), !dbg !34
+ ret void, !dbg !35
+}
+
+define dso_local noundef i32 @main() local_unnamed_addr #3 !dbg !36 {
+entry:
+ call void @_Z3barv(), !dbg !39
+ ret i32 0, !dbg !40
+}
+
+declare void @llvm.dbg.value(metadata, metadata, metadata)
+declare void @llvm.dbg.declare(metadata, metadata, metadata)
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3, !4, !5, !6, !7, !8}
+!llvm.ident = !{!9}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 18.0.0 (https://github.com/llvm/llvm-project.git 18c2eb2bf02bd7666523aa566e45d62053b7db80)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "test.cpp", directory: "")
+!2 = !{i32 7, !"Dwarf Version", i32 5}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = !{i32 1, !"wchar_size", i32 4}
+!5 = !{i32 8, !"PIC Level", i32 2}
+!6 = !{i32 7, !"PIE Level", i32 2}
+!7 = !{i32 7, !"uwtable", i32 2}
+!8 = !{i32 7, !"frame-pointer", i32 2}
+!9 = !{!"clang version 18.0.0"}
+!10 = distinct !DISubprogram(name: "nop", linkageName: "_Z3nopi", scope: !1, file: !1, line: 1, type: !11, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !14)
+!11 = !DISubroutineType(types: !12)
+!12 = !{!13, !13}
+!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!14 = !{}
+!15 = !DILocalVariable(name: "Param", arg: 1, scope: !10, file: !1, line: 1, type: !13)
+!16 = !DILocation(line: 1, column: 38, scope: !10)
+!17 = !DILocation(line: 2, column: 3, scope: !10)
+!18 = distinct !DISubprogram(name: "bar", linkageName: "_Z3barv", scope: !1, file: !1, line: 5, type: !19, scopeLine: 5, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !14)
+!19 = !DISubroutineType(types: !20)
+!20 = !{null}
+!21 = !DILocalVariable(name: "End", scope: !18, file: !1, line: 6, type: !13)
+!22 = !DILocation(line: 0, scope: !18)
+!23 = !DILocalVariable(name: "Index", scope: !18, file: !1, line: 7, type: !13)
+!24 = !DILocalVariable(name: "Var", scope: !18, file: !1, line: 8, type: !13)
+!25 = !DILocation(line: 9, column: 3, scope: !18)
+!26 = !DILocation(line: 9, column: 16, scope: !27)
+!27 = distinct !DILexicalBlock(scope: !28, file: !1, line: 9, column: 3)
+!28 = distinct !DILexicalBlock(scope: !18, file: !1, line: 9, column: 3)
+!29 = !DILocation(line: 9, column: 23, scope: !27)
+!30 = !DILocation(line: 9, column: 3, scope: !28)
+!31 = distinct !{!31, !30, !32, !33}
+!32 = !DILocation(line: 10, column: 5, scope: !28)
+!33 = !{!"llvm.loop.mustprogress"}
+!34 = !DILocation(line: 11, column: 3, scope: !18)
+!35 = !DILocation(line: 12, column: 1, scope: !18)
+!36 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 14, type: !37, scopeLine: 14, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0)
+!37 = !DISubroutineType(types: !38)
+!38 = !{!13}
+!39 = !DILocation(line: 15, column: 3, scope: !36)
+!40 = !DILocation(line: 16, column: 1, scope: !36)
diff --git a/llvm/test/Transforms/LoopSimplify/pr51735.ll b/llvm/test/Transforms/LoopSimplify/pr51735.ll
new file mode 100644
index 00000000000000..b9bdc8ca1b6fb0
--- /dev/null
+++ b/llvm/test/Transforms/LoopSimplify/pr51735.ll
@@ -0,0 +1,106 @@
+; RUN: opt -passes=indvars -S -o - < %s | FileCheck %s
+
+; Missing local variable 'Index' after loop 'Induction Variable Elimination'.
+; When adding a breakpoint at line 11, LLDB does not have information on
+; the variable. But it has info on 'Var' and 'End'.
+
+; 1 __attribute__((optnone)) int nop() {
+; 2 return 0;
+; 3 }
+; 4
+; 5 void bar() {
+; 6 int End = 777;
+; 7 int Index = 27;
+; 8 char Var = 1;
+; 9 for (; Index < End; ++Index)
+; 10 ;
+; 11 nop();
+; 12 }
+; 13
+; 14 int main () {
+; 15 bar();
+; 16 }
+
+; CHECK: for.cond: {{.*}}
+; CHECK: call void @llvm.dbg.value(metadata i32 poison, metadata ![[DBG:[0-9]+]], {{.*}}
+; CHECK: call void @llvm.dbg.value(metadata i32 poison, metadata ![[DBG:[0-9]+]], {{.*}}
+; CHECK: br i1 false, label %for.cond, label %for.end, {{.*}}
+; CHECK: for.end: {{.*}}
+; CHECK: call void @llvm.dbg.value(metadata i32 777, metadata ![[DBG:[0-9]+]], {{.*}}
+; CHECK: %call = tail call noundef i32 @_Z3nopv(), {{.*}}
+; CHECK-DAG: ![[DBG]] = !DILocalVariable(name: "Index"{{.*}})
+
+define dso_local noundef i32 @_Z3nopv() local_unnamed_addr #0 !dbg !10 {
+entry:
+ ret i32 0, !dbg !14
+}
+
+define dso_local void @_Z3barv() local_unnamed_addr #1 !dbg !15 {
+entry:
+ call void @llvm.dbg.value(metadata i32 777, metadata !19, metadata !DIExpression()), !dbg !20
+ call void @llvm.dbg.value(metadata i32 27, metadata !21, metadata !DIExpression()), !dbg !20
+ call void @llvm.dbg.value(metadata i32 1, metadata !22, metadata !DIExpression()), !dbg !20
+ br label %for.cond, !dbg !23
+
+for.cond: ; preds = %for.cond, %entry
+ %Index.0 = phi i32 [ 27, %entry ], [ %inc, %for.cond ], !dbg !20
+ call void @llvm.dbg.value(metadata i32 %Index.0, metadata !21, metadata !DIExpression()), !dbg !20
+ %cmp = icmp ult i32 %Index.0, 777, !dbg !24
+ %inc = add nuw nsw i32 %Index.0, 1, !dbg !27
+ call void @llvm.dbg.value(metadata i32 %inc, metadata !21, metadata !DIExpression()), !dbg !20
+ br i1 %cmp, label %for.cond, label %for.end, !dbg !28, !llvm.loop !29
+
+for.end: ; preds = %for.cond
+ %call = tail call noundef i32 @_Z3nopv(), !dbg !32
+ ret void, !dbg !33
+}
+
+define dso_local noundef i32 @main() local_unnamed_addr #2 !dbg !34 {
+entry:
+ call void @_Z3barv(), !dbg !35
+ ret i32 0, !dbg !36
+}
+
+declare void @llvm.dbg.value(metadata, metadata, metadata)
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3, !4, !5, !6, !7, !8}
+!llvm.ident = !{!9}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 18.0.0 (https://github.com/llvm/llvm-project.git 18c2eb2bf02bd7666523aa566e45d62053b7db80)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "test.cpp", directory: "")
+!2 = !{i32 7, !"Dwarf Version", i32 5}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
+!4 = !{i32 1, !"wchar_size", i32 4}
+!5 = !{i32 8, !"PIC Level", i32 2}
+!6 = !{i32 7, !"PIE Level", i32 2}
+!7 = !{i32 7, !"uwtable", i32 2}
+!8 = !{i32 7, !"frame-pointer", i32 2}
+!9 = !{!"clang version 18.0.0"}
+!10 = distinct !DISubprogram(name: "nop", linkageName: "_Z3nopv", scope: !1, file: !1, line: 1, type: !11, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0)
+!11 = !DISubroutineType(types: !12)
+!12 = !{!13}
+!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!14 = !DILocation(line: 2, column: 3, scope: !10)
+!15 = distinct !DISubprogram(name: "bar", linkageName: "_Z3barv", scope: !1, file: !1, line: 5, type: !16, scopeLine: 5, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !18)
+!16 = !DISubroutineType(types: !17)
+!17 = !{null}
+!18 = !{}
+!19 = !DILocalVariable(name: "End", scope: !15, file: !1, line: 6, type: !13)
+!20 = !DILocation(line: 0, scope: !15)
+!21 = !DILocalVariable(name: "Index", scope: !15, file: !1, line: 7, type: !13)
+!22 = !DILocalVariable(name: "Var", scope: !15, file: !1, line: 8, type: !13)
+!23 = !DILocation(line: 9, column: 3, scope: !15)
+!24 = !DILocation(line: 9, column: 16, scope: !25)
+!25 = distinct !DILexicalBlock(scope: !26, file: !1, line: 9, column: 3)
+!26 = distinct !DILexicalBlock(scope: !15, file: !1, line: 9, column: 3)
+!27 = !DILocation(line: 9, column: 23, scope: !25)
+!28 = !DILocation(line: 9, column: 3, scope: !26)
+!29 = distinct !{!29, !28, !30, !31}
+!30 = !DILocation(line: 10, column: 5, scope: !26)
+!31 = !{!"llvm.loop.mustprogress"}
+!32 = !DILocation(line: 11, column: 3, scope: !15)
+!33 = !DILocation(line: 12, column: 1, scope: !15)
+!34 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 14, type: !11, scopeLine: 14, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0)
+!35 = !DILocation(line: 15, column: 3, scope: !34)
+!36 = !DILocation(line: 16, column: 1, scope: !34)
>From 325281f096bcf785f0dea71dead90f16b836d17f Mon Sep 17 00:00:00 2001
From: Carlos Alberto Enciso <carlos.alberto.enciso at gmail.com>
Date: Thu, 26 Oct 2023 06:56:46 +0100
Subject: [PATCH 2/4] [indvars] Missing variables at Og:
https://bugs.llvm.org/show_bug.cgi?id=51735
https://github.com/llvm/llvm-project/issues/51077
In the given test case:
4 ...
5 void bar() {
6 int End = 777;
7 int Index = 27;
8 char Var = 1;
9 for (; Index < End; ++Index)
10 ;
11 nop(Index);
12 }
13 ...
Missing local variable 'Index' after loop 'Induction Variable Elimination'.
When adding a breakpoint at line 11, LLDB does not have information on
the variable. But it has info on 'Var' and 'End'.
- Moved the new logic to 'rewriteLoopExitValues'.
- Removed from the test cases, the unrelated functions: 'nop' and 'main'.
- Use 'isa<SCEVConstant>'.
---
llvm/lib/Transforms/Scalar/IndVarSimplify.cpp | 24 -------------
llvm/lib/Transforms/Utils/LoopUtils.cpp | 26 ++++++++++++++
.../test/Transforms/LoopSimplify/pr51735-1.ll | 34 ++-----------------
llvm/test/Transforms/LoopSimplify/pr51735.ll | 23 +------------
4 files changed, 30 insertions(+), 77 deletions(-)
diff --git a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
index 0e20b5e6204037..2a6997c48883d4 100644
--- a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
+++ b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
@@ -1932,30 +1932,6 @@ bool IndVarSimplify::run(Loop *L) {
}
}
- // The loop exit values have been updated; insert the debug location
- // for the induction variable with its final value.
- if (PHINode *IndVar = L->getInductionVariable(*SE)) {
- const SCEV *IndVarSCEV = SE->getSCEVAtScope(IndVar, L->getParentLoop());
- if (IndVarSCEV->getSCEVType() == SCEVTypes::scConstant) {
- Value *FinalIVValue = cast<SCEVConstant>(IndVarSCEV)->getValue();
- SmallVector<DbgVariableIntrinsic *> DbgUsers;
- SmallVector<DbgVariableIntrinsic *> DbgUsersCloned;
- findDbgUsers(DbgUsers, IndVar);
- for (auto &DebugUser : DbgUsers) {
- auto *Cloned = cast<DbgVariableIntrinsic>(DebugUser->clone());
- Cloned->replaceVariableLocationOp(static_cast<unsigned>(0),
- FinalIVValue);
- DbgUsersCloned.push_back(Cloned);
- }
-
- SmallVector<BasicBlock *> ExitBlocks;
- L->getExitBlocks(ExitBlocks);
- for (BasicBlock *Exit : ExitBlocks)
- for (auto &DebugUser : DbgUsersCloned)
- DebugUser->insertBefore(Exit->getFirstNonPHI());
- }
- }
-
// Eliminate redundant IV cycles.
NumElimIV += Rewriter.replaceCongruentIVs(L, DT, DeadInsts, TTI);
diff --git a/llvm/lib/Transforms/Utils/LoopUtils.cpp b/llvm/lib/Transforms/Utils/LoopUtils.cpp
index 59485126b280ab..e52eff5837afb1 100644
--- a/llvm/lib/Transforms/Utils/LoopUtils.cpp
+++ b/llvm/lib/Transforms/Utils/LoopUtils.cpp
@@ -31,6 +31,7 @@
#include "llvm/Analysis/ScalarEvolutionAliasAnalysis.h"
#include "llvm/Analysis/ScalarEvolutionExpressions.h"
#include "llvm/IR/DIBuilder.h"
+#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
@@ -1548,6 +1549,31 @@ int llvm::rewriteLoopExitValues(Loop *L, LoopInfo *LI, TargetLibraryInfo *TLI,
// The insertion point instruction may have been deleted; clear it out
// so that the rewriter doesn't trip over it later.
Rewriter.clearInsertPoint();
+
+ // The loop exit values have been updated; insert the debug location
+ // for the induction variable with its final value.
+ if (PHINode *IndVar = L->getInductionVariable(*SE)) {
+ const SCEV *IndVarSCEV = SE->getSCEVAtScope(IndVar, L->getParentLoop());
+ if (isa<SCEVConstant>(IndVarSCEV)) {
+ Value *FinalIVValue = cast<SCEVConstant>(IndVarSCEV)->getValue();
+ SmallVector<DbgVariableIntrinsic *> DbgUsers;
+ SmallVector<DbgVariableIntrinsic *> DbgUsersCloned;
+ findDbgUsers(DbgUsers, IndVar);
+ for (auto &DebugUser : DbgUsers) {
+ auto *Cloned = cast<DbgVariableIntrinsic>(DebugUser->clone());
+ Cloned->replaceVariableLocationOp(static_cast<unsigned>(0),
+ FinalIVValue);
+ DbgUsersCloned.push_back(Cloned);
+ }
+
+ SmallVector<BasicBlock *> ExitBlocks;
+ L->getExitBlocks(ExitBlocks);
+ for (BasicBlock *Exit : ExitBlocks)
+ for (auto &DebugUser : DbgUsersCloned)
+ DebugUser->insertBefore(Exit->getFirstNonPHI());
+ }
+ }
+
return NumReplaced;
}
diff --git a/llvm/test/Transforms/LoopSimplify/pr51735-1.ll b/llvm/test/Transforms/LoopSimplify/pr51735-1.ll
index de9a7452209565..cb3e8fa43e3ecf 100644
--- a/llvm/test/Transforms/LoopSimplify/pr51735-1.ll
+++ b/llvm/test/Transforms/LoopSimplify/pr51735-1.ll
@@ -22,22 +22,12 @@
; 16 }
; CHECK: for.cond: {{.*}}
-; CHECK: call void @llvm.dbg.value(metadata i32 poison, metadata ![[DBG:[0-9]+]], {{.*}}
-; CHECK: call void @llvm.dbg.value(metadata i32 poison, metadata ![[DBG:[0-9]+]], {{.*}}
-; CHECK: br i1 false, label %for.cond, label %for.end, {{.*}}
+; CHECK: call void @llvm.dbg.value(metadata i32 %Index.{{[0-9]+}}, metadata ![[DBG:[0-9]+]], {{.*}}
+; CHECK: call void @llvm.dbg.value(metadata i32 %inc, metadata ![[DBG:[0-9]+]], {{.*}}
; CHECK: for.end: {{.*}}
; CHECK: call void @llvm.dbg.value(metadata i32 777, metadata ![[DBG:[0-9]+]], {{.*}}
-; CHECK: %call = tail call noundef i32 @_Z3nopi(i32 noundef 777), {{.*}}
; CHECK-DAG: ![[DBG]] = !DILocalVariable(name: "Index"{{.*}})
-define dso_local noundef i32 @_Z3nopi(i32 noundef %Param) local_unnamed_addr #0 !dbg !10 {
-entry:
- %Param.addr = alloca i32, align 4
- store i32 %Param, ptr %Param.addr, align 4
- call void @llvm.dbg.declare(metadata ptr %Param.addr, metadata !15, metadata !DIExpression()), !dbg !16
- ret i32 0, !dbg !17
-}
-
define dso_local void @_Z3barv() local_unnamed_addr #2 !dbg !18 {
entry:
call void @llvm.dbg.value(metadata i32 777, metadata !21, metadata !DIExpression()), !dbg !22
@@ -55,24 +45,16 @@ for.cond: ; preds = %for.cond, %entry
for.end: ; preds = %for.cond
%Index.0.lcssa = phi i32 [ %Index.0, %for.cond ], !dbg !22
- %call = tail call noundef i32 @_Z3nopi(i32 noundef %Index.0.lcssa), !dbg !34
ret void, !dbg !35
}
-define dso_local noundef i32 @main() local_unnamed_addr #3 !dbg !36 {
-entry:
- call void @_Z3barv(), !dbg !39
- ret i32 0, !dbg !40
-}
-
declare void @llvm.dbg.value(metadata, metadata, metadata)
-declare void @llvm.dbg.declare(metadata, metadata, metadata)
!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!2, !3, !4, !5, !6, !7, !8}
!llvm.ident = !{!9}
-!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 18.0.0 (https://github.com/llvm/llvm-project.git 18c2eb2bf02bd7666523aa566e45d62053b7db80)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
!1 = !DIFile(filename: "test.cpp", directory: "")
!2 = !{i32 7, !"Dwarf Version", i32 5}
!3 = !{i32 2, !"Debug Info Version", i32 3}
@@ -82,14 +64,9 @@ declare void @llvm.dbg.declare(metadata, metadata, metadata)
!7 = !{i32 7, !"uwtable", i32 2}
!8 = !{i32 7, !"frame-pointer", i32 2}
!9 = !{!"clang version 18.0.0"}
-!10 = distinct !DISubprogram(name: "nop", linkageName: "_Z3nopi", scope: !1, file: !1, line: 1, type: !11, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !14)
-!11 = !DISubroutineType(types: !12)
!12 = !{!13, !13}
!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!14 = !{}
-!15 = !DILocalVariable(name: "Param", arg: 1, scope: !10, file: !1, line: 1, type: !13)
-!16 = !DILocation(line: 1, column: 38, scope: !10)
-!17 = !DILocation(line: 2, column: 3, scope: !10)
!18 = distinct !DISubprogram(name: "bar", linkageName: "_Z3barv", scope: !1, file: !1, line: 5, type: !19, scopeLine: 5, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !14)
!19 = !DISubroutineType(types: !20)
!20 = !{null}
@@ -108,8 +85,3 @@ declare void @llvm.dbg.declare(metadata, metadata, metadata)
!33 = !{!"llvm.loop.mustprogress"}
!34 = !DILocation(line: 11, column: 3, scope: !18)
!35 = !DILocation(line: 12, column: 1, scope: !18)
-!36 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 14, type: !37, scopeLine: 14, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0)
-!37 = !DISubroutineType(types: !38)
-!38 = !{!13}
-!39 = !DILocation(line: 15, column: 3, scope: !36)
-!40 = !DILocation(line: 16, column: 1, scope: !36)
diff --git a/llvm/test/Transforms/LoopSimplify/pr51735.ll b/llvm/test/Transforms/LoopSimplify/pr51735.ll
index b9bdc8ca1b6fb0..c86f8ed7d0274f 100644
--- a/llvm/test/Transforms/LoopSimplify/pr51735.ll
+++ b/llvm/test/Transforms/LoopSimplify/pr51735.ll
@@ -27,14 +27,8 @@
; CHECK: br i1 false, label %for.cond, label %for.end, {{.*}}
; CHECK: for.end: {{.*}}
; CHECK: call void @llvm.dbg.value(metadata i32 777, metadata ![[DBG:[0-9]+]], {{.*}}
-; CHECK: %call = tail call noundef i32 @_Z3nopv(), {{.*}}
; CHECK-DAG: ![[DBG]] = !DILocalVariable(name: "Index"{{.*}})
-define dso_local noundef i32 @_Z3nopv() local_unnamed_addr #0 !dbg !10 {
-entry:
- ret i32 0, !dbg !14
-}
-
define dso_local void @_Z3barv() local_unnamed_addr #1 !dbg !15 {
entry:
call void @llvm.dbg.value(metadata i32 777, metadata !19, metadata !DIExpression()), !dbg !20
@@ -51,23 +45,16 @@ for.cond: ; preds = %for.cond, %entry
br i1 %cmp, label %for.cond, label %for.end, !dbg !28, !llvm.loop !29
for.end: ; preds = %for.cond
- %call = tail call noundef i32 @_Z3nopv(), !dbg !32
ret void, !dbg !33
}
-define dso_local noundef i32 @main() local_unnamed_addr #2 !dbg !34 {
-entry:
- call void @_Z3barv(), !dbg !35
- ret i32 0, !dbg !36
-}
-
declare void @llvm.dbg.value(metadata, metadata, metadata)
!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!2, !3, !4, !5, !6, !7, !8}
!llvm.ident = !{!9}
-!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 18.0.0 (https://github.com/llvm/llvm-project.git 18c2eb2bf02bd7666523aa566e45d62053b7db80)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
!1 = !DIFile(filename: "test.cpp", directory: "")
!2 = !{i32 7, !"Dwarf Version", i32 5}
!3 = !{i32 2, !"Debug Info Version", i32 3}
@@ -77,11 +64,7 @@ declare void @llvm.dbg.value(metadata, metadata, metadata)
!7 = !{i32 7, !"uwtable", i32 2}
!8 = !{i32 7, !"frame-pointer", i32 2}
!9 = !{!"clang version 18.0.0"}
-!10 = distinct !DISubprogram(name: "nop", linkageName: "_Z3nopv", scope: !1, file: !1, line: 1, type: !11, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0)
-!11 = !DISubroutineType(types: !12)
-!12 = !{!13}
!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
-!14 = !DILocation(line: 2, column: 3, scope: !10)
!15 = distinct !DISubprogram(name: "bar", linkageName: "_Z3barv", scope: !1, file: !1, line: 5, type: !16, scopeLine: 5, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !18)
!16 = !DISubroutineType(types: !17)
!17 = !{null}
@@ -99,8 +82,4 @@ declare void @llvm.dbg.value(metadata, metadata, metadata)
!29 = distinct !{!29, !28, !30, !31}
!30 = !DILocation(line: 10, column: 5, scope: !26)
!31 = !{!"llvm.loop.mustprogress"}
-!32 = !DILocation(line: 11, column: 3, scope: !15)
!33 = !DILocation(line: 12, column: 1, scope: !15)
-!34 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 14, type: !11, scopeLine: 14, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0)
-!35 = !DILocation(line: 15, column: 3, scope: !34)
-!36 = !DILocation(line: 16, column: 1, scope: !34)
>From 58ab7910339b22ee9674d54d372c1a82d4fc95ca Mon Sep 17 00:00:00 2001
From: Carlos Alberto Enciso <carlos.alberto.enciso at gmail.com>
Date: Fri, 8 Dec 2023 14:14:29 +0000
Subject: [PATCH 3/4] [indvars] Missing variables at Og:
https://bugs.llvm.org/show_bug.cgi?id=51735
https://github.com/llvm/llvm-project/issues/51077
In the given test case:
4 ...
5 void bar() {
6 int End = 777;
7 int Index = 27;
8 char Var = 1;
9 for (; Index < End; ++Index)
10 ;
11 nop();
12 }
13 ...
Missing local variable 'Index' after loop 'Induction Variable Elimination'.
When adding a breakpoint at line 11, LLDB does not have information on
the variable. But it has info on 'Var' and 'End'.
Address reviewers comments.
- Early exit to simplify the logic.
- Avoid inserting the same instruction in multiple blocks.
- Skip debug-users with variadic variable locations.
- Change some comments to improve readability.
- Add code to clone and move the debug value.
- Modify second test case to include multiple exit blocks.
---
.../include/llvm/Transforms/Utils/LoopUtils.h | 4 +
llvm/lib/Transforms/Scalar/IndVarSimplify.cpp | 1 -
llvm/lib/Transforms/Utils/LoopUtils.cpp | 81 ++++++---
.../test/Transforms/LoopSimplify/pr51735-1.ll | 155 +++++++++++-------
llvm/test/Transforms/LoopSimplify/pr51735.ll | 13 +-
5 files changed, 159 insertions(+), 95 deletions(-)
diff --git a/llvm/include/llvm/Transforms/Utils/LoopUtils.h b/llvm/include/llvm/Transforms/Utils/LoopUtils.h
index 5a1385d01d8e44..26230fe97f6786 100644
--- a/llvm/include/llvm/Transforms/Utils/LoopUtils.h
+++ b/llvm/include/llvm/Transforms/Utils/LoopUtils.h
@@ -468,6 +468,10 @@ int rewriteLoopExitValues(Loop *L, LoopInfo *LI, TargetLibraryInfo *TLI,
ReplaceExitVal ReplaceExitValue,
SmallVector<WeakTrackingVH, 16> &DeadInsts);
+/// Assign exit values to variables that use this loop variable during the loop.
+void addDebugValuesToLoopVariable(Loop *L, ScalarEvolution *SE, PHINode *PN);
+void addDebugValuesToLoopVariable(Loop *L, Value *ExitValue, PHINode *PN);
+
/// Set weights for \p UnrolledLoop and \p RemainderLoop based on weights for
/// \p OrigLoop and the following distribution of \p OrigLoop iteration among \p
/// UnrolledLoop and \p RemainderLoop. \p UnrolledLoop receives weights that
diff --git a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
index 2a6997c48883d4..41c4d623617347 100644
--- a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
+++ b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
@@ -46,7 +46,6 @@
#include "llvm/IR/ConstantRange.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
-#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/Function.h"
diff --git a/llvm/lib/Transforms/Utils/LoopUtils.cpp b/llvm/lib/Transforms/Utils/LoopUtils.cpp
index e52eff5837afb1..5109666500c3f9 100644
--- a/llvm/lib/Transforms/Utils/LoopUtils.cpp
+++ b/llvm/lib/Transforms/Utils/LoopUtils.cpp
@@ -1342,6 +1342,36 @@ static bool checkIsIndPhi(PHINode *Phi, Loop *L, ScalarEvolution *SE,
return InductionDescriptor::isInductionPHI(Phi, L, SE, ID);
}
+void llvm::addDebugValuesToLoopVariable(Loop *L, Value *ExitValue,
+ PHINode *PN) {
+ SmallVector<BasicBlock *> ExitBlocks;
+ L->getExitBlocks(ExitBlocks);
+ SmallVector<DbgVariableIntrinsic *> DbgUsers;
+ findDbgUsers(DbgUsers, PN);
+ for (auto *DebugUser : DbgUsers) {
+ // Skip debug-users with variadic variable locations; they will not,
+ // get updated, which is fine as that is the existing behaviour.
+ if (DebugUser->hasArgList())
+ continue;
+ for (BasicBlock *Exit : ExitBlocks) {
+ auto *Cloned = cast<DbgVariableIntrinsic>(DebugUser->clone());
+ Cloned->replaceVariableLocationOp(0u, ExitValue);
+ Cloned->insertBefore(Exit->getFirstNonPHI());
+ }
+ }
+}
+
+void llvm::addDebugValuesToLoopVariable(Loop *L, ScalarEvolution *SE,
+ PHINode *PN) {
+ if (!PN)
+ return;
+ const SCEV *PNSCEV = SE->getSCEVAtScope(PN, L->getParentLoop());
+ if (auto *Const = dyn_cast<SCEVConstant>(PNSCEV)) {
+ Value *FinalIVValue = Const->getValue();
+ addDebugValuesToLoopVariable(L, FinalIVValue, PN);
+ }
+}
+
int llvm::rewriteLoopExitValues(Loop *L, LoopInfo *LI, TargetLibraryInfo *TLI,
ScalarEvolution *SE,
const TargetTransformInfo *TTI,
@@ -1483,6 +1513,21 @@ int llvm::rewriteLoopExitValues(Loop *L, LoopInfo *LI, TargetLibraryInfo *TLI,
(isa<PHINode>(Inst) || isa<LandingPadInst>(Inst)) ?
&*Inst->getParent()->getFirstInsertionPt() : Inst;
RewritePhiSet.emplace_back(PN, i, ExitValue, InsertPt, HighCost);
+
+ // Add debug values if the PN is a induction variable.
+ PHINode *IndVar = L->getInductionVariable(*SE);
+ for (Value *V : PN->incoming_values())
+ if (V == IndVar) {
+ if (BasicBlock *Successor = ExitBB->getSingleSuccessor()) {
+ SmallVector<DbgVariableIntrinsic *> DbgUsers;
+ findDbgUsers(DbgUsers, V);
+ for (auto *DebugUser : DbgUsers) {
+ auto *Cloned = cast<DbgVariableIntrinsic>(DebugUser->clone());
+ Cloned->replaceVariableLocationOp(0u, PN);
+ Cloned->insertBefore(Successor->getFirstNonPHI());
+ }
+ }
+ }
}
}
}
@@ -1541,39 +1586,25 @@ int llvm::rewriteLoopExitValues(Loop *L, LoopInfo *LI, TargetLibraryInfo *TLI,
// Replace PN with ExitVal if that is legal and does not break LCSSA.
if (PN->getNumIncomingValues() == 1 &&
LI->replacementPreservesLCSSAForm(PN, ExitVal)) {
+ addDebugValuesToLoopVariable(L, ExitVal, PN);
PN->replaceAllUsesWith(ExitVal);
PN->eraseFromParent();
}
}
+ // If there are no PHIs to be rewritten then there are no loop live-out
+ // values, try to rewrite variables corresponding to the induction variable
+ // with their constant exit-values if we computed any. Otherwise debug-info
+ // will completely forget that this loop happened.
+ if (RewritePhiSet.empty()) {
+ // The loop exit value has been updated; insert the debug location
+ // for the given the induction variable with its final value.
+ addDebugValuesToLoopVariable(L, SE, L->getInductionVariable(*SE));
+ }
+
// The insertion point instruction may have been deleted; clear it out
// so that the rewriter doesn't trip over it later.
Rewriter.clearInsertPoint();
-
- // The loop exit values have been updated; insert the debug location
- // for the induction variable with its final value.
- if (PHINode *IndVar = L->getInductionVariable(*SE)) {
- const SCEV *IndVarSCEV = SE->getSCEVAtScope(IndVar, L->getParentLoop());
- if (isa<SCEVConstant>(IndVarSCEV)) {
- Value *FinalIVValue = cast<SCEVConstant>(IndVarSCEV)->getValue();
- SmallVector<DbgVariableIntrinsic *> DbgUsers;
- SmallVector<DbgVariableIntrinsic *> DbgUsersCloned;
- findDbgUsers(DbgUsers, IndVar);
- for (auto &DebugUser : DbgUsers) {
- auto *Cloned = cast<DbgVariableIntrinsic>(DebugUser->clone());
- Cloned->replaceVariableLocationOp(static_cast<unsigned>(0),
- FinalIVValue);
- DbgUsersCloned.push_back(Cloned);
- }
-
- SmallVector<BasicBlock *> ExitBlocks;
- L->getExitBlocks(ExitBlocks);
- for (BasicBlock *Exit : ExitBlocks)
- for (auto &DebugUser : DbgUsersCloned)
- DebugUser->insertBefore(Exit->getFirstNonPHI());
- }
- }
-
return NumReplaced;
}
diff --git a/llvm/test/Transforms/LoopSimplify/pr51735-1.ll b/llvm/test/Transforms/LoopSimplify/pr51735-1.ll
index cb3e8fa43e3ecf..293553b000c13c 100644
--- a/llvm/test/Transforms/LoopSimplify/pr51735-1.ll
+++ b/llvm/test/Transforms/LoopSimplify/pr51735-1.ll
@@ -1,54 +1,78 @@
; RUN: opt -passes=indvars -S -o - < %s | FileCheck %s
-; Missing local variable 'Index' after loop 'Induction Variable Elimination'.
-; When adding a breakpoint at line 11, LLDB does not have information on
-; the variable. But it has info on 'Var' and 'End'.
-
-; 1 __attribute__((optnone)) int nop(int Param) {
-; 2 return 0;
-; 3 }
-; 4
-; 5 void bar() {
-; 6 int End = 777;
-; 7 int Index = 27;
-; 8 char Var = 1;
-; 9 for (; Index < End; ++Index)
-; 10 ;
-; 11 nop(Index);
-; 12 }
-; 13
-; 14 int main () {
-; 15 bar();
-; 16 }
-
-; CHECK: for.cond: {{.*}}
-; CHECK: call void @llvm.dbg.value(metadata i32 %Index.{{[0-9]+}}, metadata ![[DBG:[0-9]+]], {{.*}}
-; CHECK: call void @llvm.dbg.value(metadata i32 %inc, metadata ![[DBG:[0-9]+]], {{.*}}
-; CHECK: for.end: {{.*}}
-; CHECK: call void @llvm.dbg.value(metadata i32 777, metadata ![[DBG:[0-9]+]], {{.*}}
+; Make sure that when we delete the loop, that the variable Index has
+; the 777 value.
+
+; CHECK: for.cond:
+; CHECK: call void @llvm.dbg.value(metadata i32 %Index.0, metadata ![[DBG:[0-9]+]], {{.*}}
+
+; CHECK: for.extra:
+; CHECK: %call.0 = call noundef i32 @"?nop@@YAHH at Z"(i32 noundef %Index.0), {{.*}}
+; CHECK: br i1 %cmp.0, label %for.cond, label %if.else, {{.*}}
+
+; CHECK: if.then:
+; CHECK: call void @llvm.dbg.value(metadata i32 777, metadata ![[DBG]], {{.*}}
+; CHECK: br label %for.end, {{.*}}
+
+; CHECK: if.else:
+; CHECK: call void @llvm.dbg.value(metadata i32 777, metadata ![[DBG]], {{.*}}
+; CHECK: br label %for.end, {{.*}}
+
+; CHECK: for.end:
+; CHECK: call void @llvm.dbg.value(metadata i32 777, metadata ![[DBG]], {{.*}}
+
; CHECK-DAG: ![[DBG]] = !DILocalVariable(name: "Index"{{.*}})
-define dso_local void @_Z3barv() local_unnamed_addr #2 !dbg !18 {
+define dso_local noundef i32 @"?nop@@YAHH at Z"(i32 noundef %Param) !dbg !11 {
entry:
- call void @llvm.dbg.value(metadata i32 777, metadata !21, metadata !DIExpression()), !dbg !22
- call void @llvm.dbg.value(metadata i32 27, metadata !23, metadata !DIExpression()), !dbg !22
- call void @llvm.dbg.value(metadata i32 1, metadata !24, metadata !DIExpression()), !dbg !22
- br label %for.cond, !dbg !25
+ %Param.addr = alloca i32, align 4
+ store i32 %Param, ptr %Param.addr, align 4
+ call void @llvm.dbg.declare(metadata ptr %Param.addr, metadata !32, metadata !DIExpression()), !dbg !35
+ ret i32 0, !dbg !36
+}
+
+define dso_local void @_Z3barv() local_unnamed_addr #1 !dbg !12 {
+entry:
+ call void @llvm.dbg.value(metadata i32 777, metadata !16, metadata !DIExpression()), !dbg !17
+ call void @llvm.dbg.value(metadata i32 27, metadata !18, metadata !DIExpression()), !dbg !17
+ call void @llvm.dbg.value(metadata i32 1, metadata !19, metadata !DIExpression()), !dbg !17
+ call void @llvm.dbg.value(metadata i32 1, metadata !30, metadata !DIExpression()), !dbg !17
+ br label %for.cond, !dbg !20
for.cond: ; preds = %for.cond, %entry
- %Index.0 = phi i32 [ 27, %entry ], [ %inc, %for.cond ], !dbg !22
- call void @llvm.dbg.value(metadata i32 %Index.0, metadata !23, metadata !DIExpression()), !dbg !22
- %cmp = icmp ult i32 %Index.0, 777, !dbg !26
- %inc = add nuw nsw i32 %Index.0, 1, !dbg !29
- call void @llvm.dbg.value(metadata i32 %inc, metadata !23, metadata !DIExpression()), !dbg !22
- br i1 %cmp, label %for.cond, label %for.end, !dbg !30, !llvm.loop !31
-
-for.end: ; preds = %for.cond
- %Index.0.lcssa = phi i32 [ %Index.0, %for.cond ], !dbg !22
- ret void, !dbg !35
+ %Index.0 = phi i32 [ 27, %entry ], [ %inc, %for.extra ], !dbg !17
+ call void @llvm.dbg.value(metadata i32 %Index.0, metadata !18, metadata !DIExpression()), !dbg !17
+ %cmp = icmp ult i32 %Index.0, 777, !dbg !21
+ %inc = add nuw nsw i32 %Index.0, 1, !dbg !24
+ call void @llvm.dbg.value(metadata i32 %inc, metadata !18, metadata !DIExpression()), !dbg !17
+ br i1 %cmp, label %for.extra, label %if.then, !dbg !25, !llvm.loop !26
+
+for.extra:
+ %call.0 = call noundef i32 @"?nop@@YAHH at Z"(i32 noundef %Index.0), !dbg !21
+ %cmp.0 = icmp ult i32 %Index.0, %call.0, !dbg !21
+ br i1 %cmp.0, label %for.cond, label %if.else, !dbg !25, !llvm.loop !26
+
+if.then: ; preds = %for.cond
+ %Var.1 = add nsw i32 %Index.0, 1, !dbg !20
+ call void @llvm.dbg.value(metadata i32 %Var.1, metadata !19, metadata !DIExpression()), !dbg !20
+ br label %for.end, !dbg !20
+
+if.else:
+ %Var.2 = add nsw i32 %Index.0, 2, !dbg !20
+ call void @llvm.dbg.value(metadata i32 %Var.2, metadata !19, metadata !DIExpression()), !dbg !20
+ br label %for.end, !dbg !20
+
+for.end: ; preds = %if.else, %if.then
+ %Zeta.0 = phi i32 [ %Var.1, %if.then ], [ %Var.2, %if.else ], !dbg !20
+ call void @llvm.dbg.value(metadata i32 %Zeta.0, metadata !30, metadata !DIExpression()), !dbg !20
+ %Var.3 = add nsw i32 %Index.0, 1, !dbg !20
+ call void @llvm.dbg.value(metadata i32 %Var.3, metadata !19, metadata !DIExpression()), !dbg !20
+ %call = call noundef i32 @"?nop@@YAHH at Z"(i32 noundef %Index.0), !dbg !37
+ ret void, !dbg !29
}
declare void @llvm.dbg.value(metadata, metadata, metadata)
+declare void @llvm.dbg.declare(metadata, metadata, metadata)
!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!2, !3, !4, !5, !6, !7, !8}
@@ -64,24 +88,31 @@ declare void @llvm.dbg.value(metadata, metadata, metadata)
!7 = !{i32 7, !"uwtable", i32 2}
!8 = !{i32 7, !"frame-pointer", i32 2}
!9 = !{!"clang version 18.0.0"}
-!12 = !{!13, !13}
-!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
-!14 = !{}
-!18 = distinct !DISubprogram(name: "bar", linkageName: "_Z3barv", scope: !1, file: !1, line: 5, type: !19, scopeLine: 5, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !14)
-!19 = !DISubroutineType(types: !20)
-!20 = !{null}
-!21 = !DILocalVariable(name: "End", scope: !18, file: !1, line: 6, type: !13)
-!22 = !DILocation(line: 0, scope: !18)
-!23 = !DILocalVariable(name: "Index", scope: !18, file: !1, line: 7, type: !13)
-!24 = !DILocalVariable(name: "Var", scope: !18, file: !1, line: 8, type: !13)
-!25 = !DILocation(line: 9, column: 3, scope: !18)
-!26 = !DILocation(line: 9, column: 16, scope: !27)
-!27 = distinct !DILexicalBlock(scope: !28, file: !1, line: 9, column: 3)
-!28 = distinct !DILexicalBlock(scope: !18, file: !1, line: 9, column: 3)
-!29 = !DILocation(line: 9, column: 23, scope: !27)
-!30 = !DILocation(line: 9, column: 3, scope: !28)
-!31 = distinct !{!31, !30, !32, !33}
-!32 = !DILocation(line: 10, column: 5, scope: !28)
-!33 = !{!"llvm.loop.mustprogress"}
-!34 = !DILocation(line: 11, column: 3, scope: !18)
-!35 = !DILocation(line: 12, column: 1, scope: !18)
+!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!11 = distinct !DISubprogram(name: "nop", linkageName: "?nop@@YAHH at Z", scope: !1, file: !1, line: 1, type: !33, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !31)
+!12 = distinct !DISubprogram(name: "bar", linkageName: "_Z3barv", scope: !1, file: !1, line: 5, type: !13, scopeLine: 5, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !15)
+!13 = !DISubroutineType(types: !14)
+!14 = !{null}
+!15 = !{}
+!16 = !DILocalVariable(name: "End", scope: !12, file: !1, line: 6, type: !10)
+!17 = !DILocation(line: 0, scope: !12)
+!18 = !DILocalVariable(name: "Index", scope: !12, file: !1, line: 7, type: !10)
+!19 = !DILocalVariable(name: "Var", scope: !12, file: !1, line: 8, type: !10)
+!20 = !DILocation(line: 9, column: 3, scope: !12)
+!21 = !DILocation(line: 9, column: 16, scope: !22)
+!22 = distinct !DILexicalBlock(scope: !23, file: !1, line: 9, column: 3)
+!23 = distinct !DILexicalBlock(scope: !12, file: !1, line: 9, column: 3)
+!24 = !DILocation(line: 9, column: 23, scope: !22)
+!25 = !DILocation(line: 9, column: 3, scope: !23)
+!26 = distinct !{!26, !25, !27, !28}
+!27 = !DILocation(line: 10, column: 5, scope: !23)
+!28 = !{!"llvm.loop.mustprogress"}
+!29 = !DILocation(line: 12, column: 1, scope: !12)
+!30 = !DILocalVariable(name: "Zeta", scope: !12, file: !1, line: 8, type: !10)
+!31 = !{!32}
+!32 = !DILocalVariable(name: "Param", arg: 1, scope: !11, file: !1, line: 1, type: !10)
+!33 = !DISubroutineType(types: !34)
+!34 = !{!10, !10}
+!35 = !DILocation(line: 1, scope: !11)
+!36 = !DILocation(line: 2, scope: !11)
+!37 = !DILocation(line: 20, scope: !12)
diff --git a/llvm/test/Transforms/LoopSimplify/pr51735.ll b/llvm/test/Transforms/LoopSimplify/pr51735.ll
index c86f8ed7d0274f..5eb8bb50f33359 100644
--- a/llvm/test/Transforms/LoopSimplify/pr51735.ll
+++ b/llvm/test/Transforms/LoopSimplify/pr51735.ll
@@ -1,8 +1,7 @@
; RUN: opt -passes=indvars -S -o - < %s | FileCheck %s
-; Missing local variable 'Index' after loop 'Induction Variable Elimination'.
-; When adding a breakpoint at line 11, LLDB does not have information on
-; the variable. But it has info on 'Var' and 'End'.
+; Make sure that when we delete the loop in the code below, that the variable
+; Index has the 777 value.
; 1 __attribute__((optnone)) int nop() {
; 2 return 0;
@@ -21,12 +20,12 @@
; 15 bar();
; 16 }
-; CHECK: for.cond: {{.*}}
-; CHECK: call void @llvm.dbg.value(metadata i32 poison, metadata ![[DBG:[0-9]+]], {{.*}}
+; CHECK: for.cond:
; CHECK: call void @llvm.dbg.value(metadata i32 poison, metadata ![[DBG:[0-9]+]], {{.*}}
+; CHECK: call void @llvm.dbg.value(metadata i32 poison, metadata ![[DBG]], {{.*}}
; CHECK: br i1 false, label %for.cond, label %for.end, {{.*}}
-; CHECK: for.end: {{.*}}
-; CHECK: call void @llvm.dbg.value(metadata i32 777, metadata ![[DBG:[0-9]+]], {{.*}}
+; CHECK: for.end:
+; CHECK: call void @llvm.dbg.value(metadata i32 777, metadata ![[DBG]], {{.*}}
; CHECK-DAG: ![[DBG]] = !DILocalVariable(name: "Index"{{.*}})
define dso_local void @_Z3barv() local_unnamed_addr #1 !dbg !15 {
>From 88f7d8cc0e3135a58d66698560aa05a2d85ae0df Mon Sep 17 00:00:00 2001
From: Carlos Alberto Enciso <carlos.alberto.enciso at gmail.com>
Date: Tue, 9 Jan 2024 13:16:01 +0000
Subject: [PATCH 4/4] [indvars] Missing variables at Og:
https://bugs.llvm.org/show_bug.cgi?id=51735
https://github.com/llvm/llvm-project/issues/51077
In the given test case:
4 ...
5 void bar() {
6 int End = 777;
7 int Index = 27;
8 char Var = 1;
9 for (; Index < End; ++Index)
10 ;
11 nop();
12 }
13 ...
Missing local variable 'Index' after loop 'Induction Variable Elimination'.
When adding a breakpoint at line 11, LLDB does not have information on
the variable. But it has info on 'Var' and 'End'.
Address reviewers comments.
- Early exit to simplify the logic.
- Avoid inserting the same instruction in multiple blocks.
- Skip debug-users with variadic variable locations.
- Change some comments to improve readability.
- Add code to clone and move the debug value.
- Modify second test case to include multiple exit blocks.
Addressed the upstream feedback in relation to:
- Each exit block has its own exit value.
- Separate the debug values for incoming and exit values.
---
.../include/llvm/Transforms/Utils/LoopUtils.h | 5 +-
llvm/lib/Transforms/Utils/LoopUtils.cpp | 52 ++++++++++---------
.../test/Transforms/LoopSimplify/pr51735-1.ll | 4 +-
3 files changed, 34 insertions(+), 27 deletions(-)
diff --git a/llvm/include/llvm/Transforms/Utils/LoopUtils.h b/llvm/include/llvm/Transforms/Utils/LoopUtils.h
index 26230fe97f6786..3328e9955e1258 100644
--- a/llvm/include/llvm/Transforms/Utils/LoopUtils.h
+++ b/llvm/include/llvm/Transforms/Utils/LoopUtils.h
@@ -469,8 +469,11 @@ int rewriteLoopExitValues(Loop *L, LoopInfo *LI, TargetLibraryInfo *TLI,
SmallVector<WeakTrackingVH, 16> &DeadInsts);
/// Assign exit values to variables that use this loop variable during the loop.
+void addDebugValuesToIncomingValue(BasicBlock *Successor, Value *IndVar,
+ PHINode *PN);
+void addDebugValuesToLoopVariable(BasicBlock *Successor, Value *ExitValue,
+ PHINode *PN);
void addDebugValuesToLoopVariable(Loop *L, ScalarEvolution *SE, PHINode *PN);
-void addDebugValuesToLoopVariable(Loop *L, Value *ExitValue, PHINode *PN);
/// Set weights for \p UnrolledLoop and \p RemainderLoop based on weights for
/// \p OrigLoop and the following distribution of \p OrigLoop iteration among \p
diff --git a/llvm/lib/Transforms/Utils/LoopUtils.cpp b/llvm/lib/Transforms/Utils/LoopUtils.cpp
index 5109666500c3f9..45408ff804e007 100644
--- a/llvm/lib/Transforms/Utils/LoopUtils.cpp
+++ b/llvm/lib/Transforms/Utils/LoopUtils.cpp
@@ -1267,11 +1267,12 @@ struct RewritePhi {
const SCEV *ExpansionSCEV; // The SCEV of the incoming value we are rewriting.
Instruction *ExpansionPoint; // Where we'd like to expand that SCEV?
bool HighCost; // Is this expansion a high-cost?
+ BasicBlock *ExitBlock; // Exit block for PHI node.
RewritePhi(PHINode *P, unsigned I, const SCEV *Val, Instruction *ExpansionPt,
- bool H)
+ bool H, BasicBlock *Exit)
: PN(P), Ith(I), ExpansionSCEV(Val), ExpansionPoint(ExpansionPt),
- HighCost(H) {}
+ HighCost(H), ExitBlock(Exit) {}
};
// Check whether it is possible to delete the loop after rewriting exit
@@ -1342,10 +1343,19 @@ static bool checkIsIndPhi(PHINode *Phi, Loop *L, ScalarEvolution *SE,
return InductionDescriptor::isInductionPHI(Phi, L, SE, ID);
}
-void llvm::addDebugValuesToLoopVariable(Loop *L, Value *ExitValue,
+void llvm::addDebugValuesToIncomingValue(BasicBlock *Successor, Value *IndVar,
+ PHINode *PN) {
+ SmallVector<DbgVariableIntrinsic *> DbgUsers;
+ findDbgUsers(DbgUsers, IndVar);
+ for (auto *DebugUser : DbgUsers) {
+ auto *Cloned = cast<DbgVariableIntrinsic>(DebugUser->clone());
+ Cloned->replaceVariableLocationOp(0u, PN);
+ Cloned->insertBefore(Successor->getFirstNonPHI());
+ }
+}
+
+void llvm::addDebugValuesToLoopVariable(BasicBlock *Successor, Value *ExitValue,
PHINode *PN) {
- SmallVector<BasicBlock *> ExitBlocks;
- L->getExitBlocks(ExitBlocks);
SmallVector<DbgVariableIntrinsic *> DbgUsers;
findDbgUsers(DbgUsers, PN);
for (auto *DebugUser : DbgUsers) {
@@ -1353,11 +1363,9 @@ void llvm::addDebugValuesToLoopVariable(Loop *L, Value *ExitValue,
// get updated, which is fine as that is the existing behaviour.
if (DebugUser->hasArgList())
continue;
- for (BasicBlock *Exit : ExitBlocks) {
- auto *Cloned = cast<DbgVariableIntrinsic>(DebugUser->clone());
- Cloned->replaceVariableLocationOp(0u, ExitValue);
- Cloned->insertBefore(Exit->getFirstNonPHI());
- }
+ auto *Cloned = cast<DbgVariableIntrinsic>(DebugUser->clone());
+ Cloned->replaceVariableLocationOp(0u, ExitValue);
+ Cloned->insertBefore(Successor->getFirstNonPHI());
}
}
@@ -1368,7 +1376,10 @@ void llvm::addDebugValuesToLoopVariable(Loop *L, ScalarEvolution *SE,
const SCEV *PNSCEV = SE->getSCEVAtScope(PN, L->getParentLoop());
if (auto *Const = dyn_cast<SCEVConstant>(PNSCEV)) {
Value *FinalIVValue = Const->getValue();
- addDebugValuesToLoopVariable(L, FinalIVValue, PN);
+ SmallVector<BasicBlock *> ExitBlocks;
+ L->getExitBlocks(ExitBlocks);
+ for (BasicBlock *Exit : ExitBlocks)
+ addDebugValuesToLoopVariable(Exit, FinalIVValue, PN);
}
}
@@ -1512,22 +1523,13 @@ int llvm::rewriteLoopExitValues(Loop *L, LoopInfo *LI, TargetLibraryInfo *TLI,
Instruction *InsertPt =
(isa<PHINode>(Inst) || isa<LandingPadInst>(Inst)) ?
&*Inst->getParent()->getFirstInsertionPt() : Inst;
- RewritePhiSet.emplace_back(PN, i, ExitValue, InsertPt, HighCost);
+ RewritePhiSet.emplace_back(PN, i, ExitValue, InsertPt, HighCost, ExitBB);
// Add debug values if the PN is a induction variable.
PHINode *IndVar = L->getInductionVariable(*SE);
- for (Value *V : PN->incoming_values())
- if (V == IndVar) {
- if (BasicBlock *Successor = ExitBB->getSingleSuccessor()) {
- SmallVector<DbgVariableIntrinsic *> DbgUsers;
- findDbgUsers(DbgUsers, V);
- for (auto *DebugUser : DbgUsers) {
- auto *Cloned = cast<DbgVariableIntrinsic>(DebugUser->clone());
- Cloned->replaceVariableLocationOp(0u, PN);
- Cloned->insertBefore(Successor->getFirstNonPHI());
- }
- }
- }
+ if (PN->getIncomingValue(i) == IndVar)
+ if (BasicBlock *Successor = ExitBB->getSingleSuccessor())
+ addDebugValuesToIncomingValue(Successor, PN->getIncomingValue(i), PN);
}
}
}
@@ -1586,7 +1588,7 @@ int llvm::rewriteLoopExitValues(Loop *L, LoopInfo *LI, TargetLibraryInfo *TLI,
// Replace PN with ExitVal if that is legal and does not break LCSSA.
if (PN->getNumIncomingValues() == 1 &&
LI->replacementPreservesLCSSAForm(PN, ExitVal)) {
- addDebugValuesToLoopVariable(L, ExitVal, PN);
+ addDebugValuesToLoopVariable(Phi.ExitBlock, ExitVal, PN);
PN->replaceAllUsesWith(ExitVal);
PN->eraseFromParent();
}
diff --git a/llvm/test/Transforms/LoopSimplify/pr51735-1.ll b/llvm/test/Transforms/LoopSimplify/pr51735-1.ll
index 293553b000c13c..20cadcac47b60f 100644
--- a/llvm/test/Transforms/LoopSimplify/pr51735-1.ll
+++ b/llvm/test/Transforms/LoopSimplify/pr51735-1.ll
@@ -12,16 +12,18 @@
; CHECK: if.then:
; CHECK: call void @llvm.dbg.value(metadata i32 777, metadata ![[DBG]], {{.*}}
+; CHECK: call void @llvm.dbg.value(metadata i32 %Var.1, metadata ![[VAR:[0-9]+]], {{.*}}
; CHECK: br label %for.end, {{.*}}
; CHECK: if.else:
-; CHECK: call void @llvm.dbg.value(metadata i32 777, metadata ![[DBG]], {{.*}}
+; CHECK: call void @llvm.dbg.value(metadata i32 %Var.2, metadata ![[VAR:[0-9]+]], {{.*}}
; CHECK: br label %for.end, {{.*}}
; CHECK: for.end:
; CHECK: call void @llvm.dbg.value(metadata i32 777, metadata ![[DBG]], {{.*}}
; CHECK-DAG: ![[DBG]] = !DILocalVariable(name: "Index"{{.*}})
+; CHECK-DAG: ![[VAR]] = !DILocalVariable(name: "Var"{{.*}})
define dso_local noundef i32 @"?nop@@YAHH at Z"(i32 noundef %Param) !dbg !11 {
entry:
More information about the llvm-commits
mailing list