| ; REQUIRES: x86-registered-target |
| ; RUN: opt < %s -passes='pseudo-probe,cgscc(coro-split),coro-cleanup,always-inline' -mtriple=x86_64 -pass-remarks=inline -S -o %t.ll |
| ; RUN: llc -mtriple=x86_64 -stop-after=pseudo-probe-inserter < %t.ll --filetype=asm -o - | FileCheck -check-prefix=MIR %s |
| |
| ; Making sure PseudoProbeInserter is not generating GUID for `_Z3foov.resume` |
| ; MIR-NOT: PSEUDO_PROBE 4448042984153125393, |
| ; Checking the same for `_Z3foov.cleanup` |
| ; MIR-NOT: PSEUDO_PROBE 3532999944647676065, |
| ; Checking the same for `_Z3foov.destroy` |
| ; MIR-NOT: PSEUDO_PROBE -7235034626494519075, |
| |
| ; RUN: llc -mtriple=x86_64 < %t.ll --filetype=obj -o %t.obj |
| ; RUN: obj2yaml %t.obj | FileCheck -check-prefix=OBJ --match-full-lines %s |
| ; OBJ: - Name: '.pseudo_probe (1)'{{$}} |
| ; OBJ-NEXT: Type: SHT_PROGBITS{{$}} |
| ; OBJ-NEXT: Flags: [ SHF_LINK_ORDER ]{{$}} |
| ; OBJ-NEXT: Link: .text{{$}} |
| ; OBJ-NEXT: AddressAlign: 0x1{{$}} |
| |
| ; Making sure `_Z3foov.resume` is not a top-level function except when its a sentinel probe (i.e. 20{GUID}) |
| ; OBJ-NOT: Content: 11921D00879FBA3D{{[0-9A-F]+$}} |
| ; OBJ-NOT: {{([013-9A-F][0-9A-F])|(2[1-9A-F])}}11921D00879FBA3D{{[0-9A-F]+$}} |
| ; Checking the same for `_Z3foov.cleanup` |
| ; OBJ-NOT: Content: A1103324BBBC0731{{[0-9A-F]+$}} |
| ; OBJ-NOT: {{([013-9A-F][0-9A-F])|(2[1-9A-F])}}A1103324BBBC0731{{[0-9A-F]+$}} |
| ; Checking the same for `_Z3foov.destroy` |
| ; OBJ-NOT: Content: DDA8240E57FE979B{{[0-9A-F]+$}} |
| ; OBJ-NOT: {{([013-9A-F][0-9A-F])|(2[1-9A-F])}}DDA8240E57FE979B{{[0-9A-F]+$}} |
| |
| ; OBJ: - Name: .pseudo_probe{{$}} |
| ; OBJ-NEXT: Type: SHT_PROGBITS{{$}} |
| ; OBJ-NEXT: Flags: [ SHF_LINK_ORDER, SHF_GROUP ]{{$}} |
| ; OBJ-NEXT: Link: .text.__clang_call_terminate{{$}} |
| |
| |
| ; Reduced from original source code: |
| ; clang++ -S -g -O0 SampleProfile/Inputs/pseudo-probe-coro-debug-fix.cpp -emit-llvm -Xclang -disable-llvm-passes -std=c++20 -o SampleProfile/pseudo-probe-coro-debug-fix.ll |
| ; |
| ; #include <coroutine> |
| ; struct co_sleep { |
| ; co_sleep(int n) : delay{n} {} |
| ; constexpr bool await_ready() const noexcept { return false; } |
| ; void await_suspend(std::coroutine_handle<> h) const noexcept {} |
| ; void await_resume() const noexcept {} |
| ; int delay; |
| ; }; |
| ; struct Task { |
| ; struct promise_type { |
| ; promise_type() = default; |
| ; Task get_return_object() { return {}; } |
| ; std::suspend_never initial_suspend() { return {}; } |
| ; std::suspend_always final_suspend() noexcept { return {}; } |
| ; void unhandled_exception() {} |
| ; }; |
| ; }; |
| ; Task foo() noexcept { |
| ; co_await co_sleep{10}; |
| ; } |
| ; |
| ; int main() { |
| ; foo(); |
| ; } |
| |
| ; ModuleID = 'pseudo-probe-coro-debug-fix.cpp' |
| source_filename = "pseudo-probe-coro-debug-fix.cpp" |
| target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128" |
| target triple = "x86_64-redhat-linux-gnu" |
| |
| %"struct.Task::promise_type" = type { i8 } |
| %struct.Task = type { i8 } |
| %"struct.std::__n4861::suspend_never" = type { i8 } |
| %struct.co_sleep = type { i32 } |
| %"struct.std::__n4861::suspend_always" = type { i8 } |
| |
| $__clang_call_terminate = comdat any |
| |
| ; Function Attrs: mustprogress noinline nounwind optnone presplitcoroutine uwtable |
| define dso_local void @_Z3foov() #0 personality ptr @__gxx_personality_v0 !dbg !30 { |
| entry: |
| %__promise = alloca %"struct.Task::promise_type", align 1 |
| %undef.agg.tmp = alloca %struct.Task, align 1 |
| %ref.tmp = alloca %"struct.std::__n4861::suspend_never", align 1 |
| %undef.agg.tmp3 = alloca %"struct.std::__n4861::suspend_never", align 1 |
| %ref.tmp5 = alloca %struct.co_sleep, align 4 |
| %exn.slot = alloca ptr, align 8 |
| %ehselector.slot = alloca i32, align 4 |
| %ref.tmp13 = alloca %"struct.std::__n4861::suspend_always", align 1 |
| %undef.agg.tmp14 = alloca %"struct.std::__n4861::suspend_always", align 1 |
| %0 = call token @llvm.coro.id(i32 16, ptr %__promise, ptr @_Z3foov, ptr null), !dbg !33 |
| %1 = call i1 @llvm.coro.alloc(token %0), !dbg !33 |
| br i1 %1, label %coro.alloc, label %coro.init, !dbg !33 |
| |
| coro.alloc: ; preds = %entry |
| %2 = call i64 @llvm.coro.size.i64(), !dbg !34 |
| %call = invoke noalias noundef nonnull ptr @_Znwm(i64 noundef %2) #12 |
| to label %invoke.cont unwind label %terminate.lpad, !dbg !34 |
| |
| invoke.cont: ; preds = %coro.alloc |
| br label %coro.init, !dbg !33 |
| |
| coro.init: ; preds = %invoke.cont, %entry |
| %3 = phi ptr [ null, %entry ], [ %call, %invoke.cont ], !dbg !33 |
| %4 = call ptr @llvm.coro.begin(token %0, ptr %3), !dbg !33 |
| call void @llvm.lifetime.start.p0(ptr %__promise) #2, !dbg !34 |
| #dbg_declare(ptr %__promise, !35, !DIExpression(), !41) |
| call void @llvm.lifetime.start.p0(ptr %ref.tmp5) #2, !dbg !42 |
| %5 = call token @llvm.coro.save(ptr null), !dbg !44 |
| call void @llvm.coro.await.suspend.void(ptr %ref.tmp5, ptr %4, ptr @_Z3foov.__await_suspend_wrapper__await) #2, !dbg !44 |
| %6 = call i8 @llvm.coro.suspend(token %5, i1 false), !dbg !44 |
| switch i8 %6, label %coro.ret [ |
| i8 0, label %cleanup8 |
| i8 1, label %await.cleanup |
| ], !dbg !44 |
| |
| await.cleanup: ; preds = %coro.init |
| br label %cleanup8, !dbg !44 |
| |
| coro.final: ; preds = %cleanup8 |
| call void @llvm.lifetime.start.p0(ptr %ref.tmp13) #2, !dbg !34 |
| %7 = call token @llvm.coro.save(ptr null), !dbg !34 |
| call void @llvm.coro.await.suspend.void(ptr %ref.tmp13, ptr %4, ptr @_Z3foov.__await_suspend_wrapper__final) #2, !dbg !34 |
| %8 = call i8 @llvm.coro.suspend(token %7, i1 true), !dbg !34 |
| switch i8 %8, label %coro.ret [ |
| i8 0, label %cleanup16 |
| i8 1, label %final.cleanup |
| ], !dbg !34 |
| |
| final.cleanup: ; preds = %coro.final |
| br label %cleanup16, !dbg !34 |
| |
| cleanup8: ; preds = %await.cleanup, %coro.init |
| %cleanup.dest.slot.1 = phi i32 [ 0, %coro.init ], [ 2, %await.cleanup ] |
| call void @llvm.lifetime.end.p0(ptr %ref.tmp5) #2, !dbg !44 |
| switch i32 %cleanup.dest.slot.1, label %cleanup19 [ |
| i32 0, label %coro.final |
| ] |
| |
| cleanup16: ; preds = %final.cleanup, %coro.final |
| %cleanup.dest.slot.2 = phi i32 [ 0, %coro.final ], [ 2, %final.cleanup ] |
| call void @llvm.lifetime.end.p0(ptr %ref.tmp13) #2, !dbg !34 |
| switch i32 %cleanup.dest.slot.2, label %cleanup19 [ |
| i32 0, label %cleanup.cont18 |
| ] |
| |
| cleanup.cont18: ; preds = %cleanup16 |
| br label %cleanup19, !dbg !34 |
| |
| cleanup19: ; preds = %cleanup.cont18, %cleanup16, %cleanup8 |
| %cleanup.dest.slot.3 = phi i32 [ %cleanup.dest.slot.1, %cleanup8 ], [ %cleanup.dest.slot.2, %cleanup16 ], [ 0, %cleanup.cont18 ], !dbg !41 |
| call void @llvm.lifetime.end.p0(ptr %__promise) #2, !dbg !34 |
| %9 = call ptr @llvm.coro.free(token %0, ptr %4), !dbg !34 |
| %10 = icmp ne ptr %9, null, !dbg !34 |
| br i1 %10, label %coro.free, label %after.coro.free, !dbg !34 |
| |
| coro.free: ; preds = %cleanup19 |
| %11 = call i64 @llvm.coro.size.i64(), !dbg !34 |
| call void @_ZdlPvm(ptr noundef %9, i64 noundef %11) #2, !dbg !34 |
| br label %after.coro.free, !dbg !34 |
| |
| after.coro.free: ; preds = %coro.free, %cleanup19 |
| switch i32 %cleanup.dest.slot.3, label %unreachable [ |
| i32 0, label %cleanup.cont22 |
| i32 2, label %coro.ret |
| ] |
| |
| cleanup.cont22: ; preds = %after.coro.free |
| br label %coro.ret, !dbg !34 |
| |
| coro.ret: ; preds = %cleanup.cont22, %after.coro.free, %coro.final, %coro.init |
| call void @llvm.coro.end(ptr null, i1 false, token none), !dbg !34 |
| ret void, !dbg !34 |
| |
| terminate.lpad: ; preds = %coro.alloc |
| %12 = landingpad { ptr, i32 } |
| catch ptr null, !dbg !34 |
| %13 = extractvalue { ptr, i32 } %12, 0, !dbg !34 |
| call void @__clang_call_terminate(ptr %13) #13, !dbg !34 |
| unreachable, !dbg !34 |
| |
| unreachable: ; preds = %after.coro.free |
| unreachable |
| } |
| |
| ; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: read) |
| declare token @llvm.coro.id(i32, ptr readnone, ptr readonly captures(none), ptr) #1 |
| |
| ; Function Attrs: nounwind |
| declare i1 @llvm.coro.alloc(token) #2 |
| |
| ; Function Attrs: nobuiltin allocsize(0) |
| declare dso_local noundef nonnull ptr @_Znwm(i64 noundef) #3 |
| |
| ; Function Attrs: nounwind memory(none) |
| declare i64 @llvm.coro.size.i64() #4 |
| |
| declare dso_local i32 @__gxx_personality_v0(...) |
| |
| ; Function Attrs: noinline noreturn nounwind uwtable |
| define linkonce_odr hidden void @__clang_call_terminate(ptr noundef %0) #5 comdat { |
| %2 = call ptr @__cxa_begin_catch(ptr %0) #2 |
| call void @_ZSt9terminatev() #13 |
| unreachable |
| } |
| |
| declare dso_local ptr @__cxa_begin_catch(ptr) |
| |
| declare dso_local void @_ZSt9terminatev() |
| |
| ; Function Attrs: nounwind |
| declare ptr @llvm.coro.begin(token, ptr writeonly) #2 |
| |
| ; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) |
| declare void @llvm.lifetime.start.p0(ptr captures(none)) #6 |
| |
| ; Function Attrs: nomerge nounwind |
| declare token @llvm.coro.save(ptr) #7 |
| |
| ; Function Attrs: alwaysinline mustprogress |
| define internal void @_Z3foov.__await_suspend_wrapper__init(ptr noundef nonnull %0, ptr noundef %1) #8 !dbg !45 { |
| entry: |
| call void @_ZSt9terminatev() #13 |
| ret void, !dbg !47 |
| } |
| |
| declare void @llvm.coro.await.suspend.void(ptr, ptr, ptr) |
| |
| ; Function Attrs: nounwind |
| declare i8 @llvm.coro.suspend(token, i1) #2 |
| |
| ; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) |
| declare void @llvm.lifetime.end.p0(ptr captures(none)) #6 |
| |
| ; Function Attrs: alwaysinline mustprogress |
| define internal void @_Z3foov.__await_suspend_wrapper__await(ptr noundef nonnull %0, ptr noundef %1) #8 !dbg !48 { |
| entry: |
| call void @_ZSt9terminatev() #13 |
| ret void, !dbg !49 |
| } |
| |
| declare dso_local void @__cxa_end_catch() |
| |
| ; Function Attrs: alwaysinline mustprogress |
| define internal void @_Z3foov.__await_suspend_wrapper__final(ptr noundef nonnull %0, ptr noundef %1) #8 !dbg !50 { |
| entry: |
| call void @_ZSt9terminatev() #13 |
| ret void, !dbg !51 |
| } |
| |
| ; Function Attrs: nobuiltin nounwind |
| declare dso_local void @_ZdlPvm(ptr noundef, i64 noundef) #9 |
| |
| ; Function Attrs: nounwind memory(argmem: read) |
| declare ptr @llvm.coro.free(token, ptr readonly captures(none)) #10 |
| |
| ; Function Attrs: nounwind |
| declare void @llvm.coro.end(ptr, i1, token) #2 |
| |
| ; Function Attrs: mustprogress noinline norecurse nounwind optnone uwtable |
| define dso_local noundef i32 @main() #11 !dbg !52 { |
| entry: |
| %undef.agg.tmp = alloca %struct.Task, align 1 |
| call void @_Z3foov() #2, !dbg !55 |
| ret i32 0, !dbg !56 |
| } |
| |
| attributes #0 = { mustprogress noinline nounwind optnone presplitcoroutine uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } |
| attributes #1 = { nocallback nofree nosync nounwind willreturn memory(argmem: read) } |
| attributes #2 = { nounwind } |
| attributes #3 = { nobuiltin allocsize(0) "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } |
| attributes #4 = { nounwind memory(none) } |
| attributes #5 = { noinline noreturn nounwind uwtable "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } |
| attributes #6 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) } |
| attributes #7 = { nomerge nounwind } |
| attributes #8 = { alwaysinline mustprogress "min-legal-vector-width"="0" } |
| attributes #9 = { nobuiltin nounwind "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } |
| attributes #10 = { nounwind memory(argmem: read) } |
| attributes #11 = { mustprogress noinline norecurse nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" } |
| attributes #12 = { allocsize(0) } |
| attributes #13 = { noreturn nounwind } |
| |
| !llvm.dbg.cu = !{!0} |
| !llvm.module.flags = !{!24, !25, !26, !27, !28} |
| !llvm.ident = !{!29} |
| |
| !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 22.0.0git (https://github.com/llvm/llvm-project.git fe218aab737d55dfd67f4f84118744003f45958e)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, retainedTypes: !2, splitDebugInlining: false, nameTableKind: None) |
| !1 = !DIFile(filename: "pseudo-probe-coro-debug-fix.cpp", directory: "/tmp", checksumkind: CSK_MD5, checksum: "601552fedf6b88dcf699ea9d066126eb") |
| !2 = !{!3, !6, !15, !20} |
| !3 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "promise_type", scope: !4, file: !1, line: 10, size: 8, flags: DIFlagTypePassByValue, elements: !5, identifier: "_ZTSN4Task12promise_typeE") |
| !4 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Task", file: !1, line: 9, size: 8, flags: DIFlagTypePassByValue, elements: !5, identifier: "_ZTS4Task") |
| !5 = !{} |
| !6 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "coroutine_handle<void>", scope: !8, file: !7, line: 87, size: 64, flags: DIFlagTypePassByValue | DIFlagNonTrivial, elements: !10, templateParams: !13, identifier: "_ZTSNSt7__n486116coroutine_handleIvEE") |
| !7 = !DIFile(filename: "/usr/lib/gcc/x86_64-redhat-linux/11/../../../../include/c++/11/coroutine", directory: "") |
| !8 = !DINamespace(name: "__n4861", scope: !9, exportSymbols: true) |
| !9 = !DINamespace(name: "std", scope: null) |
| !10 = !{!11} |
| !11 = !DIDerivedType(tag: DW_TAG_member, name: "_M_fr_ptr", scope: !6, file: !7, line: 131, baseType: !12, size: 64, flags: DIFlagProtected) |
| !12 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, size: 64) |
| !13 = !{!14} |
| !14 = !DITemplateTypeParameter(name: "_Promise", type: null, defaulted: true) |
| !15 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "coroutine_handle<Task::promise_type>", scope: !8, file: !7, line: 182, size: 64, flags: DIFlagTypePassByValue | DIFlagNonTrivial, elements: !16, templateParams: !18, identifier: "_ZTSNSt7__n486116coroutine_handleIN4Task12promise_typeEEE") |
| !16 = !{!17} |
| !17 = !DIDerivedType(tag: DW_TAG_member, name: "_M_fr_ptr", scope: !15, file: !7, line: 244, baseType: !12, size: 64, flags: DIFlagPrivate) |
| !18 = !{!19} |
| !19 = !DITemplateTypeParameter(name: "_Promise", type: !3) |
| !20 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "co_sleep", file: !1, line: 2, size: 32, flags: DIFlagTypePassByValue | DIFlagNonTrivial, elements: !21, identifier: "_ZTS8co_sleep") |
| !21 = !{!22} |
| !22 = !DIDerivedType(tag: DW_TAG_member, name: "delay", scope: !20, file: !1, line: 7, baseType: !23, size: 32) |
| !23 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) |
| !24 = !{i32 7, !"Dwarf Version", i32 5} |
| !25 = !{i32 2, !"Debug Info Version", i32 3} |
| !26 = !{i32 1, !"wchar_size", i32 4} |
| !27 = !{i32 7, !"uwtable", i32 2} |
| !28 = !{i32 7, !"frame-pointer", i32 2} |
| !29 = !{!"clang version 22.0.0git (https://github.com/llvm/llvm-project.git fe218aab737d55dfd67f4f84118744003f45958e)"} |
| !30 = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov", scope: !1, file: !1, line: 18, type: !31, scopeLine: 18, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !5) |
| !31 = !DISubroutineType(types: !32) |
| !32 = !{!4} |
| !33 = !DILocation(line: 18, column: 21, scope: !30) |
| !34 = !DILocation(line: 18, column: 6, scope: !30) |
| !35 = !DILocalVariable(name: "__promise", scope: !30, type: !36, flags: DIFlagArtificial) |
| !36 = !DIDerivedType(tag: DW_TAG_typedef, name: "promise_type", scope: !37, file: !7, line: 75, baseType: !3) |
| !37 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "__coroutine_traits_impl<Task, void>", scope: !8, file: !7, line: 72, size: 8, flags: DIFlagTypePassByValue, elements: !5, templateParams: !38, identifier: "_ZTSNSt7__n486123__coroutine_traits_implI4TaskvEE") |
| !38 = !{!39, !40} |
| !39 = !DITemplateTypeParameter(name: "_Result", type: !4) |
| !40 = !DITemplateTypeParameter(type: null, defaulted: true) |
| !41 = !DILocation(line: 0, scope: !30) |
| !42 = !DILocation(line: 19, column: 12, scope: !43) |
| !43 = distinct !DILexicalBlock(scope: !30, file: !1, line: 18, column: 21) |
| !44 = !DILocation(line: 19, column: 3, scope: !43) |
| !45 = distinct !DISubprogram(linkageName: "_Z3foov.__await_suspend_wrapper__init", scope: !1, file: !1, type: !46, flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !0, retainedNodes: !5) |
| !46 = !DISubroutineType(types: !5) |
| !47 = !DILocation(line: 18, column: 6, scope: !45) |
| !48 = distinct !DISubprogram(linkageName: "_Z3foov.__await_suspend_wrapper__await", scope: !1, file: !1, type: !46, flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !0, retainedNodes: !5) |
| !49 = !DILocation(line: 19, column: 12, scope: !48) |
| !50 = distinct !DISubprogram(linkageName: "_Z3foov.__await_suspend_wrapper__final", scope: !1, file: !1, type: !46, flags: DIFlagArtificial, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !0, retainedNodes: !5) |
| !51 = !DILocation(line: 18, column: 6, scope: !50) |
| !52 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 22, type: !53, scopeLine: 22, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0) |
| !53 = !DISubroutineType(types: !54) |
| !54 = !{!23} |
| !55 = !DILocation(line: 23, column: 3, scope: !52) |
| !56 = !DILocation(line: 24, column: 1, scope: !52) |