Follow up to d0858bffa11, add missing REQUIRES x86
[llvm-project.git] / llvm / test / Transforms / Coroutines / coro-debug-spill-dbg.declare.ll
blobe7a271a96ead125bffa7733ddb5ee54c5a0481a6
1 ; Test spilling a temp generates dbg.declare in resume/destroy/cleanup functions.
3 ; RUN: opt < %s -passes='cgscc(coro-split)' -S | FileCheck %s
5 ; The test case simulates a coroutine method in a class.
7 ; class Container {
8 ;  public:
9 ;    Container() : field(12) {}
10 ;    Task foo() {
11 ;      co_await std::suspend_always{};
12 ;      auto *copy = this;
13 ;      co_return;
14 ;    }
15 ;    int field;
16 ; };
18 ; We want to make sure that the "this" pointer is accessable in debugger before and after the suspension point.
20 ; CHECK: define internal fastcc void @foo.resume(ptr noundef nonnull align 8 dereferenceable(32) %[[HDL:.*]])
21 ; CHECK-NEXT: entry.resume:
22 ; CHECK-NEXT:   %[[HDL]].debug = alloca ptr, align 8
23 ; CHECK-NEXT:   call void @llvm.dbg.declare(metadata ptr %[[HDL]].debug, metadata ![[THIS_RESUME:[0-9]+]], metadata !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 24))
25 ; CHECK: define internal fastcc void @foo.destroy(ptr noundef nonnull align 8 dereferenceable(32) %[[HDL]])
26 ; CHECK-NEXT: entry.destroy:
27 ; CHECK-NEXT:   %[[HDL]].debug = alloca ptr, align 8
28 ; CHECK-NEXT:   call void @llvm.dbg.declare(metadata ptr %[[HDL]].debug, metadata ![[THIS_DESTROY:[0-9]+]], metadata !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 24))
30 ; CHECK: define internal fastcc void @foo.cleanup(ptr noundef nonnull align 8 dereferenceable(32) %[[HDL]])
31 ; CHECK-NEXT: entry.cleanup:
32 ; CHECK-NEXT:   %[[HDL]].debug = alloca ptr, align 8
33 ; CHECK-NEXT:   call void @llvm.dbg.declare(metadata ptr %[[HDL]].debug, metadata ![[THIS_CLEANUP:[0-9]+]], metadata !DIExpression(DW_OP_deref, DW_OP_plus_uconst, 24))
35 ; CHECK: ![[THIS_RESUME]] = !DILocalVariable(name: "this"
36 ; CHECK: ![[THIS_DESTROY]] = !DILocalVariable(name: "this"
37 ; CHECK: ![[THIS_CLEANUP]] = !DILocalVariable(name: "this"
39 ; Function Attrs: presplitcoroutine
40 define ptr @foo(ptr noundef nonnull align 1 dereferenceable(1) %this) #0 !dbg !11 {
41 entry:
42   %this.addr = alloca ptr, align 8
43   %__promise = alloca i8, align 1
44   store ptr %this, ptr %this.addr, align 8
45   call void @llvm.dbg.declare(metadata ptr %this.addr, metadata !20, metadata !DIExpression()), !dbg !22
46   %this1 = load ptr, ptr %this.addr, align 8
47   %0 = bitcast ptr %__promise to ptr
48   %id = call token @llvm.coro.id(i32 16, ptr %0, ptr null, ptr null)
49   %need.dyn.alloc = call i1 @llvm.coro.alloc(token %id)
50   br i1 %need.dyn.alloc, label %dyn.alloc, label %coro.begin
52 dyn.alloc:                                        ; preds = %entry
53   %size = call i32 @llvm.coro.size.i32()
54   %alloc = call ptr @malloc(i32 %size)
55   br label %coro.begin
57 coro.begin:                                       ; preds = %dyn.alloc, %entry
58   %phi = phi ptr [ null, %entry ], [ %alloc, %dyn.alloc ]
59   %hdl = call ptr @llvm.coro.begin(token %id, ptr %phi)
60   call void @llvm.dbg.declare(metadata ptr %__promise, metadata !23, metadata !DIExpression()), !dbg !22
61   %1 = call i8 @llvm.coro.suspend(token none, i1 false)
62   switch i8 %1, label %suspend [
63     i8 0, label %resume
64     i8 1, label %cleanup
65   ]
67 resume:                                           ; preds = %coro.begin
68   call void @bar(ptr %this1)
69   br label %cleanup
71 cleanup:                                          ; preds = %resume, %coro.begin
72   %mem = call ptr @llvm.coro.free(token %id, ptr %hdl)
73   call void @free(ptr %mem)
74   br label %suspend
76 suspend:                                          ; preds = %cleanup, %coro.begin
77   %2 = call i1 @llvm.coro.end(ptr %hdl, i1 false, token none)
78   ret ptr %hdl
81 ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
82 declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
84 ; Function Attrs: nounwind memory(argmem: read)
85 declare ptr @llvm.coro.free(token, ptr nocapture readonly) #2
87 ; Function Attrs: nounwind memory(none)
88 declare i32 @llvm.coro.size.i32() #3
90 ; Function Attrs: nounwind
91 declare i8 @llvm.coro.suspend(token, i1) #4
93 declare void @llvm.coro.resume(ptr)
95 declare void @llvm.coro.destroy(ptr)
97 ; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: read)
98 declare token @llvm.coro.id(i32, ptr readnone, ptr nocapture readonly, ptr) #5
100 ; Function Attrs: nounwind
101 declare i1 @llvm.coro.alloc(token) #4
103 ; Function Attrs: nounwind
104 declare ptr @llvm.coro.begin(token, ptr writeonly) #4
106 ; Function Attrs: nounwind
107 declare i1 @llvm.coro.end(ptr, i1, token) #4
109 declare noalias ptr @malloc(i32)
111 declare void @free(ptr)
113 declare void @bar(ptr)
115 attributes #0 = { presplitcoroutine }
116 attributes #1 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
117 attributes #2 = { nounwind memory(argmem: read) }
118 attributes #3 = { nounwind memory(none) }
119 attributes #4 = { nounwind }
120 attributes #5 = { nocallback nofree nosync nounwind willreturn memory(argmem: read) }
122 !llvm.dbg.cu = !{!0}
123 !llvm.linker.options = !{}
124 !llvm.module.flags = !{!3, !4, !5, !6, !7, !8, !9}
125 !llvm.ident = !{!10}
127 !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 17.0.20210610", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, retainedTypes: !2, splitDebugInlining: false, nameTableKind: None)
128 !1 = !DIFile(filename: "test.cpp", directory: ".")
129 !2 = !{}
130 !3 = !{i32 7, !"Dwarf Version", i32 5}
131 !4 = !{i32 2, !"Debug Info Version", i32 3}
132 !5 = !{i32 1, !"wchar_size", i32 4}
133 !6 = !{i32 8, !"PIC Level", i32 2}
134 !7 = !{i32 7, !"PIE Level", i32 2}
135 !8 = !{i32 7, !"uwtable", i32 2}
136 !9 = !{i32 7, !"frame-pointer", i32 2}
137 !10 = !{!"clang version 17.0.20210610"}
138 !11 = distinct !DISubprogram(name: "foo", linkageName: "_ZN9Container3fooEv", scope: !1, file: !1, line: 20, type: !12, scopeLine: 20, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, declaration: !13, retainedNodes: !2)
139 !12 = !DISubroutineType(types: !2)
140 !13 = !DISubprogram(name: "foo", linkageName: "_ZN9Container3fooEv", scope: !14, file: !1, line: 20, type: !12, scopeLine: 20, flags: DIFlagPublic | DIFlagPrototyped, spFlags: 0)
141 !14 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "Container", file: !1, line: 17, size: 8, flags: DIFlagTypePassByValue | DIFlagNonTrivial, elements: !15, identifier: "_ZTS9Container")
142 !15 = !{!16, !13}
143 !16 = !DISubprogram(name: "Container", scope: !14, file: !1, line: 19, type: !17, scopeLine: 19, flags: DIFlagPublic | DIFlagPrototyped, spFlags: 0)
144 !17 = !DISubroutineType(types: !18)
145 !18 = !{null, !19}
146 !19 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !14, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
147 !20 = !DILocalVariable(name: "this", arg: 1, scope: !11, type: !21, flags: DIFlagArtificial | DIFlagObjectPointer)
148 !21 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !14, size: 64)
149 !22 = !DILocation(line: 0, scope: !11)
150 !23 = !DILocalVariable(name: "__promise", scope: !11, type: !24, flags: DIFlagArtificial)
151 !24 = !DIDerivedType(tag: DW_TAG_typedef, name: "promise_type", scope: !11, file: !1, line: 40, baseType: !25)
152 !25 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "promise_type", scope: !11, file: !1, line: 6, size: 8, flags: DIFlagTypePassByValue, elements: !2, identifier: "_ZTSN4Task12promise_typeE")