https://github.com/CarlosAlbertoEnciso updated https://github.com/llvm/llvm-project/pull/69920
>From 844ec47fb887a860b4f8e28d435848a245eeb388 Mon Sep 17 00:00:00 2001 From: Carlos Alberto Enciso <carlos.alberto.enc...@gmail.com> Date: Mon, 23 Oct 2023 11:44:22 +0100 Subject: [PATCH 1/5] [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 41c4d6236173472..0e20b5e62040374 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 000000000000000..de9a74522095659 --- /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 000000000000000..b9bdc8ca1b6fb09 --- /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 4b6c81971b11f59b701324c1bfa0afa849a4b127 Mon Sep 17 00:00:00 2001 From: Carlos Alberto Enciso <carlos.alberto.enc...@gmail.com> Date: Thu, 26 Oct 2023 06:56:46 +0100 Subject: [PATCH 2/5] [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 0e20b5e62040374..2a6997c48883d44 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 59485126b280abf..e52eff5837afb11 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 de9a74522095659..cb3e8fa43e3ecf6 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 b9bdc8ca1b6fb09..c86f8ed7d0274f0 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 031d298f5d0d759cec70400815821d5e86a7038d Mon Sep 17 00:00:00 2001 From: Carlos Alberto Enciso <carlos.alberto.enc...@gmail.com> Date: Fri, 8 Dec 2023 14:14:29 +0000 Subject: [PATCH 3/5] [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 5a1385d01d8e44d..26230fe97f67867 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 2a6997c48883d44..41c4d6236173472 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 e52eff5837afb11..5109666500c3f9d 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 cb3e8fa43e3ecf6..293553b000c13cc 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@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@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@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@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@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 c86f8ed7d0274f0..5eb8bb50f333594 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 50ec4d1d9fb478eebe6f36d9af5f0443378584d1 Mon Sep 17 00:00:00 2001 From: Carlos Alberto Enciso <carlos.alberto.enc...@gmail.com> Date: Tue, 9 Jan 2024 13:16:01 +0000 Subject: [PATCH 4/5] [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 26230fe97f67867..3328e9955e1258b 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 5109666500c3f9d..45408ff804e007e 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 293553b000c13cc..20cadcac47b60f7 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@Z"(i32 noundef %Param) !dbg !11 { entry: >From 0270560a07d37ae51cde9bc6e7e8b7e5d7832b69 Mon Sep 17 00:00:00 2001 From: Carlos Alberto Enciso <carlos.alberto.enc...@gmail.com> Date: Tue, 9 Jan 2024 14:44:10 +0000 Subject: [PATCH 5/5] [indvars] Missing variables at Og: https://bugs.llvm.org/show_bug.cgi?id=51735 https://github.com/llvm/llvm-project/issues/51077 Fix clang-format found issues in updated patch. --- llvm/lib/Transforms/Utils/LoopUtils.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Transforms/Utils/LoopUtils.cpp b/llvm/lib/Transforms/Utils/LoopUtils.cpp index 45408ff804e007e..420c99775a6e67b 100644 --- a/llvm/lib/Transforms/Utils/LoopUtils.cpp +++ b/llvm/lib/Transforms/Utils/LoopUtils.cpp @@ -1523,13 +1523,15 @@ 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, ExitBB); + RewritePhiSet.emplace_back(PN, i, ExitValue, InsertPt, HighCost, + ExitBB); // Add debug values if the PN is a induction variable. PHINode *IndVar = L->getInductionVariable(*SE); if (PN->getIncomingValue(i) == IndVar) if (BasicBlock *Successor = ExitBB->getSingleSuccessor()) - addDebugValuesToIncomingValue(Successor, PN->getIncomingValue(i), PN); + addDebugValuesToIncomingValue(Successor, PN->getIncomingValue(i), + PN); } } } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits