diff --git a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp index f37b4dc938d30..529f7309a1a27 100644 --- a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp +++ b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp @@ -2951,9 +2951,11 @@ void coro::salvageDebugInfo( // dbg.declare does. if (isa(DVI)) { std::optional InsertPt; - if (auto *I = dyn_cast(Storage)) + if (auto *I = dyn_cast(Storage)) { InsertPt = I->getInsertionPointAfterDef(); - else if (isa(Storage)) + if (!OptimizeFrame && I->getDebugLoc()) + DVI.setDebugLoc(I->getDebugLoc()); + } else if (isa(Storage)) InsertPt = F->getEntryBlock().begin(); if (InsertPt) DVI.moveBefore(*(*InsertPt)->getParent(), *InsertPt); diff --git a/llvm/test/Transforms/Coroutines/coro-debug-frame-variable-O1.ll b/llvm/test/Transforms/Coroutines/coro-debug-frame-variable-O1.ll new file mode 100644 index 0000000000000..acd6a08d7c1b8 --- /dev/null +++ b/llvm/test/Transforms/Coroutines/coro-debug-frame-variable-O1.ll @@ -0,0 +1,64 @@ +; RUN: opt < %s -passes='module(coro-early),cgscc(inline,coro-split)' -S | FileCheck %s +; RUN: opt --try-experimental-debuginfo-iterators < %s -passes='module(coro-early),cgscc(inline,coro-split)' -S | FileCheck %s + +; Simplified version from pr#75104. +; Make sure we do not update debug location for hosited dbg.declare intrinsics when optimizing coro frame. + +; CHECK-NOT: mismatched subprogram between llvm.dbg.declare variable and !dbg attachment + +%"struct.std::coroutine_handle" = type { i8 } + +define void @_Z1fv() presplitcoroutine { +entry: + %0 = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null) + %1 = call ptr @llvm.coro.begin(token %0, ptr null), !dbg !10 + br label %for.cond + +for.cond: ; preds = %for.cond, %entry + call void @_ZN1BD1Ev() + %2 = call token @llvm.coro.save(ptr null) + %3 = call i8 @llvm.coro.suspend(token none, i1 false) + br label %for.cond +} + +declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr) +declare ptr @llvm.coro.begin(token, ptr writeonly) +declare void @llvm.dbg.declare(metadata, metadata, metadata) +declare token @llvm.coro.save(ptr) +declare i8 @llvm.coro.suspend(token, i1) + +define void @_ZN1BD1Ev() { +entry: + %b11 = alloca [0 x [0 x %"struct.std::coroutine_handle"]], i32 0, align 1 + call void @llvm.dbg.declare(metadata ptr %b11, metadata !13, metadata !DIExpression()), !dbg !21 + %call = call i1 @_ZNSt16coroutine_handleIvEcvbEv(ptr %b11), !dbg !21 + ret void +} + +declare i1 @_ZNSt16coroutine_handleIvEcvbEv(ptr) + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!9} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 18.0.0git", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, globals: !2, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "", directory: "") +!2 = !{!3} +!3 = !DIGlobalVariableExpression(var: !4, expr: !DIExpression()) +!4 = distinct !DIGlobalVariable(name: "a", scope: !0, file: !5, line: 17, type: !6, isLocal: false, isDefinition: true) +!5 = !DIFile(filename: "bad.cpp", directory: "") +!6 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "coroutine_handle", scope: !7, file: !5, line: 2, size: 8, flags: DIFlagTypePassByValue, elements: !8, templateParams: !8, identifier: "_ZTSSt16coroutine_handleIvE") +!7 = !DINamespace(name: "std", scope: null) +!8 = !{} +!9 = !{i32 2, !"Debug Info Version", i32 3} +!10 = !DILocation(line: 31, column: 7, scope: !11) +!11 = distinct !DISubprogram(name: "f", linkageName: "_Z1fv", scope: !5, file: !5, line: 31, type: !12, scopeLine: 31, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !8) +!12 = distinct !DISubroutineType(types: !8) +!13 = !DILocalVariable(name: "b", scope: !14, file: !5, line: 27, type: !6) +!14 = distinct !DILexicalBlock(scope: !15, file: !5, line: 27, column: 14) +!15 = distinct !DILexicalBlock(scope: !16, file: !5, line: 26, column: 8) +!16 = distinct !DISubprogram(name: "~B", linkageName: "_ZN1BD2Ev", scope: !17, file: !5, line: 26, type: !18, scopeLine: 26, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, declaration: !20, retainedNodes: !8) +!17 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "B", file: !5, line: 18, size: 8, flags: DIFlagTypePassByReference | DIFlagNonTrivial, elements: !8, identifier: "_ZTS1B") +!18 = !DISubroutineType(types: !19) +!19 = !{null} +!20 = !DISubprogram(name: "~B", scope: !17, file: !5, line: 26, type: !18, scopeLine: 26, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized) +!21 = !DILocation(line: 27, column: 14, scope: !14) diff --git a/llvm/test/Transforms/Coroutines/coro-debug-frame-variable.ll b/llvm/test/Transforms/Coroutines/coro-debug-frame-variable.ll index 19a89fefd5269..bf51218590c2f 100644 --- a/llvm/test/Transforms/Coroutines/coro-debug-frame-variable.ll +++ b/llvm/test/Transforms/Coroutines/coro-debug-frame-variable.ll @@ -32,8 +32,8 @@ ; CHECK: entry: ; CHECK: %j = alloca i32, align 4 ; CHECK: call void @llvm.dbg.declare(metadata ptr %j, metadata ![[JVAR:[0-9]+]], metadata !DIExpression()), !dbg ![[JDBGLOC:[0-9]+]] -; CHECK: %[[MEMORY:.*]] = call ptr @new -; CHECK: call void @llvm.dbg.declare(metadata ptr %[[MEMORY]], metadata ![[XVAR:[0-9]+]], metadata !DIExpression(DW_OP_plus_uconst, 32)), !dbg ![[IDBGLOC:[0-9]+]] +; CHECK: %[[MEMORY:.*]] = call ptr @new({{.+}}), !dbg ![[IDBGLOC:[0-9]+]] +; CHECK: call void @llvm.dbg.declare(metadata ptr %[[MEMORY]], metadata ![[XVAR:[0-9]+]], metadata !DIExpression(DW_OP_plus_uconst, 32)), !dbg ![[IDBGLOC]] ; CHECK: call void @llvm.dbg.declare(metadata ptr %[[MEMORY]], metadata ![[IVAR:[0-9]+]], metadata !DIExpression(DW_OP_plus_uconst, 20)), !dbg ![[IDBGLOC]] ; CHECK: await.ready: ; @@ -49,18 +49,20 @@ ; CHECK: await.ready: ; ; CHECK-DAG: ![[IVAR]] = !DILocalVariable(name: "i" -; CHECK-DAG: ![[SCOPE:[0-9]+]] = distinct !DILexicalBlock(scope: !6, file: !1, line: 23, column: 12) -; CHECK-DAG: ![[IDBGLOC]] = !DILocation(line: 24, column: 7, scope: ![[SCOPE]]) +; CHECK-DAG: ![[PROG_SCOPE:[0-9]+]] = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov" +; CHECK-DAG: ![[BLK_SCOPE:[0-9]+]] = distinct !DILexicalBlock(scope: ![[PROG_SCOPE]], file: !1, line: 23, column: 12) +; CHECK-DAG: ![[IDBGLOC]] = !DILocation(line: 23, column: 6, scope: ![[PROG_SCOPE]]) ; CHECK-DAG: ![[XVAR]] = !DILocalVariable(name: "x" ; CHECK-DAG: ![[JVAR]] = !DILocalVariable(name: "j" -; CHECK-DAG: ![[JDBGLOC]] = !DILocation(line: 32, column: 7, scope: ![[SCOPE]]) +; CHECK-DAG: ![[JDBGLOC]] = !DILocation(line: 32, column: 7, scope: ![[BLK_SCOPE]]) ; CHECK-DAG: ![[XVAR_RESUME]] = !DILocalVariable(name: "x" -; CHECK-DAG: ![[IDBGLOC_RESUME]] = !DILocation(line: 24, column: 7, scope: ![[RESUME_SCOPE:[0-9]+]]) -; CHECK-DAG: ![[RESUME_SCOPE]] = distinct !DILexicalBlock(scope: !22, file: !1, line: 23, column: 12) +; CHECK-DAG: ![[RESUME_PROG_SCOPE:[0-9]+]] = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov" +; CHECK-DAG: ![[IDBGLOC_RESUME]] = !DILocation(line: 24, column: 7, scope: ![[RESUME_BLK_SCOPE:[0-9]+]]) +; CHECK-DAG: ![[RESUME_BLK_SCOPE]] = distinct !DILexicalBlock(scope: ![[RESUME_PROG_SCOPE]], file: !1, line: 23, column: 12) ; CHECK-DAG: ![[IVAR_RESUME]] = !DILocalVariable(name: "i" ; CHECK-DAG: ![[JVAR_RESUME]] = !DILocalVariable(name: "j" -; CHECK-DAG: ![[JDBGLOC_RESUME]] = !DILocation(line: 32, column: 7, scope: ![[RESUME_SCOPE]]) +; CHECK-DAG: ![[JDBGLOC_RESUME]] = !DILocation(line: 32, column: 7, scope: ![[RESUME_BLK_SCOPE]]) define void @f() presplitcoroutine !dbg !8 { entry: %__promise = alloca i8, align 8 @@ -72,13 +74,13 @@ entry: br i1 %alloc, label %coro.alloc, label %coro.init coro.alloc: ; preds = %entry - %size = call i64 @llvm.coro.size.i64() - %memory = call ptr @new(i64 %size) - br label %coro.init + %size = call i64 @llvm.coro.size.i64(), !dbg !23 + %memory = call ptr @new(i64 %size), !dbg !23 + br label %coro.init, !dbg !23 coro.init: ; preds = %coro.alloc, %entry - %phi.entry.alloc = phi ptr [ null, %entry ], [ %memory, %coro.alloc ] - %begin = call ptr @llvm.coro.begin(token %id, ptr %phi.entry.alloc) + %phi.entry.alloc = phi ptr [ null, %entry ], [ %memory, %coro.alloc ], !dbg !23 + %begin = call ptr @llvm.coro.begin(token %id, ptr %phi.entry.alloc), !dbg !23 %ready = call i1 @await_ready() br i1 %ready, label %init.ready, label %init.suspend @@ -240,3 +242,4 @@ declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) !20 = !DILocation(line: 43, column: 3, scope: !7) !21 = !DILocation(line: 43, column: 8, scope: !7) !22 = distinct !DILexicalBlock(scope: !8, file: !1, line: 23, column: 12) +!23 = !DILocation(line: 23, column: 6, scope: !8)