From 844ec47fb887a860b4f8e28d435848a245eeb388 Mon Sep 17 00:00:00 2001 From: Carlos Alberto Enciso Date: Mon, 23 Oct 2023 11:44:22 +0100 Subject: [PATCH] [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(IndVarSCEV)->getValue(); + SmallVector DbgUsers; + SmallVector DbgUsersCloned; + findDbgUsers(DbgUsers, IndVar); + for (auto &DebugUser : DbgUsers) { + auto *Cloned = cast(DebugUser->clone()); + Cloned->replaceVariableLocationOp(static_cast(0), + FinalIVValue); + DbgUsersCloned.push_back(Cloned); + } + + SmallVector 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)