brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.2 KiB · 633045d Raw
348 lines · plain
1; Tests that the dynamic allocation and deallocation of the coroutine frame is2; elided and any tail calls referencing the coroutine frame has the tail3; call attribute removed.4; RUN: opt < %s -S \5; RUN: -passes='cgscc(inline,function(coro-elide,instsimplify,simplifycfg))' \6; RUN:   -aa-pipeline='basic-aa' | FileCheck %s7 8declare void @print(i32) nounwind9 10%f.frame = type {i32}11 12declare void @bar(ptr)13 14declare fastcc void @f.resume(ptr align 4 dereferenceable(4))15declare fastcc void @f.destroy(ptr)16declare fastcc void @f.cleanup(ptr)17 18declare void @may_throw()19declare ptr @CustomAlloc(i32)20declare void @CustomFree(ptr)21 22@f.resumers = internal constant [3 x ptr]23  [ptr @f.resume, ptr @f.destroy, ptr @f.cleanup]24 25; a coroutine start function26define ptr @f() personality ptr null {27entry:28  %id = call token @llvm.coro.id(i32 0, ptr null,29                      ptr @f,30                      ptr @f.resumers)31  %need.dyn.alloc = call i1 @llvm.coro.alloc(token %id)32  br i1 %need.dyn.alloc, label %dyn.alloc, label %coro.begin33dyn.alloc:34  %alloc = call ptr @CustomAlloc(i32 4)35  br label %coro.begin36coro.begin:37  %phi = phi ptr [ null, %entry ], [ %alloc, %dyn.alloc ]38  %hdl = call ptr @llvm.coro.begin(token %id, ptr %phi)39  invoke void @may_throw()40    to label %ret unwind label %ehcleanup41ret:42  ret ptr %hdl43 44ehcleanup:45  %tok = cleanuppad within none []46  %mem = call ptr @llvm.coro.free(token %id, ptr %hdl)47  %need.dyn.free = icmp ne ptr %mem, null48  br i1 %need.dyn.free, label %dyn.free, label %if.end49dyn.free:50  call void @CustomFree(ptr %mem)51  br label %if.end52if.end:53  cleanupret from %tok unwind to caller54}55 56; CHECK-LABEL: @callResume(57define void @callResume() {58entry:59; CHECK: alloca [4 x i8], align 460; CHECK-NOT: coro.begin61; CHECK-NOT: CustomAlloc62; CHECK: call void @may_throw()63  %hdl = call ptr @f()64 65; Need to remove 'tail' from the first call to @bar66; CHECK-NOT: tail call void @bar(67; CHECK: call void @bar(68  tail call void @bar(ptr %hdl)69; CHECK: tail call void @bar(70  tail call void @bar(ptr null)71 72; CHECK-NEXT: call fastcc void @f.resume(ptr %0)73  %0 = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 0)74  call fastcc void %0(ptr %hdl)75 76; CHECK-NEXT: call fastcc void @f.cleanup(ptr %0)77  %1 = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 1)78  call fastcc void %1(ptr %hdl)79 80; CHECK-NEXT: ret void81  ret void82}83 84; CHECK-LABEL: @callResume_with_coro_suspend_1(85define void @callResume_with_coro_suspend_1() {86entry:87; CHECK: alloca [4 x i8], align 488; CHECK-NOT: coro.begin89; CHECK-NOT: CustomAlloc90; CHECK: call void @may_throw()91  %hdl = call ptr @f()92 93; CHECK-NEXT: call fastcc void @f.resume(ptr %0)94  %0 = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 0)95  call fastcc void %0(ptr %hdl)96  %1 = call token @llvm.coro.save(ptr %hdl)97  %2 = call i8 @llvm.coro.suspend(token %1, i1 false)98  switch i8 %2, label  %coro.ret [99    i8 0, label %final.suspend100    i8 1, label %cleanups101  ]102 103; CHECK-LABEL: final.suspend:104final.suspend:105; CHECK-NEXT: call fastcc void @f.cleanup(ptr %0)106  %3 = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 1)107  call fastcc void %3(ptr %hdl)108  %4 = call token @llvm.coro.save(ptr %hdl)109  %5 = call i8 @llvm.coro.suspend(token %4, i1 true)110  switch i8 %5, label  %coro.ret [111    i8 0, label %coro.ret112    i8 1, label %cleanups113  ]114 115; CHECK-LABEL: cleanups:116cleanups:117; CHECK-NEXT: call fastcc void @f.cleanup(ptr %0)118  %6 = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 1)119  call fastcc void %6(ptr %hdl)120  br label %coro.ret121 122; CHECK-LABEL: coro.ret:123coro.ret:124; CHECK-NEXT: ret void125  ret void126}127 128; CHECK-LABEL: @callResume_with_coro_suspend_2(129define void @callResume_with_coro_suspend_2() personality ptr null {130entry:131; CHECK: alloca [4 x i8], align 4132; CHECK-NOT: coro.begin133; CHECK-NOT: CustomAlloc134; CHECK: call void @may_throw()135  %hdl = call ptr @f()136 137  %0 = call token @llvm.coro.save(ptr %hdl)138; CHECK: invoke fastcc void @f.resume(ptr %0)139  %1 = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 0)140  invoke fastcc void %1(ptr %hdl)141    to label %invoke.cont1 unwind label %lpad142 143; CHECK-LABEL: invoke.cont1:144invoke.cont1:145  %2 = call i8 @llvm.coro.suspend(token %0, i1 false)146  switch i8 %2, label  %coro.ret [147    i8 0, label %final.ready148    i8 1, label %cleanups149  ]150 151; CHECK-LABEL: lpad:152lpad:153  %3 = landingpad { ptr, i32 }154          catch ptr null155; CHECK: call fastcc void @f.cleanup(ptr %0)156  %4 = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 1)157  call fastcc void %4(ptr %hdl)158  br label %final.suspend159 160; CHECK-LABEL: final.ready:161final.ready:162; CHECK-NEXT: call fastcc void @f.cleanup(ptr %0)163  %5 = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 1)164  call fastcc void %5(ptr %hdl)165  br label %final.suspend166 167; CHECK-LABEL: final.suspend:168final.suspend:169  %6 = call token @llvm.coro.save(ptr %hdl)170  %7 = call i8 @llvm.coro.suspend(token %6, i1 true)171  switch i8 %7, label  %coro.ret [172    i8 0, label %coro.ret173    i8 1, label %cleanups174  ]175 176; CHECK-LABEL: cleanups:177cleanups:178; CHECK-NEXT: call fastcc void @f.cleanup(ptr %0)179  %8 = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 1)180  call fastcc void %8(ptr %hdl)181  br label %coro.ret182 183; CHECK-LABEL: coro.ret:184coro.ret:185; CHECK-NEXT: ret void186  ret void187}188 189; CHECK-LABEL: @callResume_with_coro_suspend_3(190define void @callResume_with_coro_suspend_3(i8 %cond) {191entry:192; CHECK: alloca [4 x i8], align 4193  switch i8 %cond, label  %coro.ret [194    i8 0, label %init.suspend195    i8 1, label %coro.ret196  ]197 198init.suspend:199; CHECK-NOT: llvm.coro.begin200; CHECK-NOT: CustomAlloc201; CHECK: call void @may_throw()202  %hdl = call ptr @f()203; CHECK-NEXT: call fastcc void @f.resume(ptr %0)204  %0 = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 0)205  call fastcc void %0(ptr %hdl)206  %1 = call token @llvm.coro.save(ptr %hdl)207  %2 = call i8 @llvm.coro.suspend(token %1, i1 false)208  switch i8 %2, label  %coro.ret [209    i8 0, label %final.suspend210    i8 1, label %cleanups211  ]212 213; CHECK-LABEL: final.suspend:214final.suspend:215; CHECK-NEXT: call fastcc void @f.cleanup(ptr %0)216  %3 = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 1)217  call fastcc void %3(ptr %hdl)218  %4 = call token @llvm.coro.save(ptr %hdl)219  %5 = call i8 @llvm.coro.suspend(token %4, i1 true)220  switch i8 %5, label  %coro.ret [221    i8 0, label %coro.ret222    i8 1, label %cleanups223  ]224 225; CHECK-LABEL: cleanups:226cleanups:227; CHECK-NEXT: call fastcc void @f.cleanup(ptr %0)228  %6 = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 1)229  call fastcc void %6(ptr %hdl)230  br label %coro.ret231 232; CHECK-LABEL: coro.ret:233coro.ret:234; CHECK-NEXT: ret void235  ret void236}237 238 239 240; CHECK-LABEL: @callResume_PR34897_no_elision(241define void @callResume_PR34897_no_elision(i1 %cond) {242; CHECK-LABEL: entry:243entry:244; CHECK: call ptr @CustomAlloc(245  %hdl = call ptr @f()246; CHECK: tail call void @bar(247  tail call void @bar(ptr %hdl)248; CHECK: tail call void @bar(249  tail call void @bar(ptr null)250  br i1 %cond, label %if.then, label %if.else251 252; CHECK-LABEL: if.then:253if.then:254; CHECK: call fastcc void @f.resume(ptr255  %0 = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 0)256  call fastcc void %0(ptr %hdl)257; CHECK-NEXT: call fastcc void @f.destroy(ptr258  %1 = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 1)259  call fastcc void %1(ptr %hdl)260  br label %return261 262if.else:263  br label %return264 265; CHECK-LABEL: return:266return:267; CHECK: ret void268  ret void269}270 271; CHECK-LABEL: @callResume_PR34897_elision(272define void @callResume_PR34897_elision(i1 %cond) {273; CHECK-LABEL: entry:274entry:275; CHECK: alloca [4 x i8], align 4276; CHECK: tail call void @bar(277  tail call void @bar(ptr null)278  br i1 %cond, label %if.then, label %if.else279 280if.then:281; CHECK-NOT: CustomAlloc282; CHECK: call void @may_throw()283  %hdl = call ptr @f()284; CHECK: call void @bar(285  tail call void @bar(ptr %hdl)286; CHECK: call fastcc void @f.resume(ptr287  %0 = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 0)288  call fastcc void %0(ptr %hdl)289; CHECK-NEXT: call fastcc void @f.cleanup(ptr290  %1 = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 1)291  call fastcc void %1(ptr %hdl)292  br label %return293 294if.else:295  br label %return296 297; CHECK-LABEL: return:298return:299; CHECK: ret void300  ret void301}302 303 304; a coroutine start function (cannot elide heap alloc, due to second argument to305; coro.begin not pointint to coro.alloc)306define ptr @f_no_elision() personality ptr null {307entry:308  %id = call token @llvm.coro.id(i32 0, ptr null,309                      ptr @f_no_elision,310                      ptr @f.resumers)311  %alloc = call ptr @CustomAlloc(i32 4)312  %hdl = call ptr @llvm.coro.begin(token %id, ptr %alloc)313  ret ptr %hdl314}315 316; CHECK-LABEL: @callResume_no_elision(317define void @callResume_no_elision() {318entry:319; CHECK: call ptr @CustomAlloc(320  %hdl = call ptr @f_no_elision()321 322; Tail call should remain tail calls323; CHECK: tail call void @bar(324  tail call void @bar(ptr %hdl)325; CHECK: tail call void @bar(326  tail call void @bar(ptr null)327 328; CHECK-NEXT: call fastcc void @f.resume(ptr329  %0 = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 0)330  call fastcc void %0(ptr %hdl)331 332; CHECK-NEXT: call fastcc void @f.destroy(ptr333  %1 = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 1)334  call fastcc void %1(ptr %hdl)335 336; CHECK-NEXT: ret void337  ret void338}339 340declare token @llvm.coro.id(i32, ptr, ptr, ptr)341declare i1 @llvm.coro.alloc(token)342declare ptr @llvm.coro.free(token, ptr)343declare ptr @llvm.coro.begin(token, ptr)344declare ptr @llvm.coro.frame(token)345declare ptr @llvm.coro.subfn.addr(ptr, i8)346declare i8 @llvm.coro.suspend(token, i1)347declare token @llvm.coro.save(ptr)348