brintos

brintos / llvm-project-archived public Read only

0
0
Text · 12.8 KiB · c08423d Raw
418 lines · plain
1; Test no suspend coroutines2; RUN: opt < %s -passes='cgscc(coro-split),simplifycfg,early-cse,simplifycfg' -S | FileCheck %s3 4; Coroutine with no-suspends will turn into:5;6; CHECK-LABEL: define void @no_suspends(7; CHECK-NEXT:  entry:8; CHECK-NEXT:    call void @print(i32 %n)9; CHECK-NEXT:    ret void10;11define void @no_suspends(i32 %n) presplitcoroutine {12entry:13  %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)14  %need.dyn.alloc = call i1 @llvm.coro.alloc(token %id)15  br i1 %need.dyn.alloc, label %dyn.alloc, label %coro.begin16dyn.alloc:17  %size = call i32 @llvm.coro.size.i32()18  %alloc = call ptr @malloc(i32 %size)19  br label %coro.begin20coro.begin:21  %phi = phi ptr [ null, %entry ], [ %alloc, %dyn.alloc ]22  %hdl = call noalias ptr @llvm.coro.begin(token %id, ptr %phi)23  br label %body24body:25  call void @print(i32 %n)26  br label %cleanup27cleanup:28  %mem = call ptr @llvm.coro.free(token %id, ptr %hdl)29  %need.dyn.free = icmp ne ptr %mem, null30  br i1 %need.dyn.free, label %dyn.free, label %suspend31dyn.free:32  call void @free(ptr %mem)33  br label %suspend34suspend:35  call void @llvm.coro.end(ptr %hdl, i1 false, token none)36  ret void37}38 39; SimplifySuspendPoint will detect that coro.resume resumes itself and will40; replace suspend with a jump to %resume label turning it into no-suspend41; coroutine.42;43; CHECK-LABEL: define void @simplify_resume(44; CHECK-NEXT:  entry:45; CHECK-NEXT:    call void @llvm.memcpy46; CHECK-NEXT:    call void @print(i32 0)47; CHECK-NEXT:    ret void48;49define void @simplify_resume(ptr %src, ptr %dst) presplitcoroutine {50entry:51  %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)52  %need.dyn.alloc = call i1 @llvm.coro.alloc(token %id)53  br i1 %need.dyn.alloc, label %dyn.alloc, label %coro.begin54dyn.alloc:55  %size = call i32 @llvm.coro.size.i32()56  %alloc = call ptr @malloc(i32 %size)57  br label %coro.begin58coro.begin:59  %phi = phi ptr [ null, %entry ], [ %alloc, %dyn.alloc ]60  %hdl = call noalias ptr @llvm.coro.begin(token %id, ptr %phi)61  br label %body62body:63  %save = call token @llvm.coro.save(ptr %hdl)64  ; memcpy intrinsics should not prevent simplification.65  call void @llvm.memcpy.p0.p0.i64(ptr %dst, ptr %src, i64 1, i1 false)66  %subfn = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 0)67  call fastcc void %subfn(ptr %hdl)68  %0 = call i8 @llvm.coro.suspend(token %save, i1 false)69  switch i8 %0, label %suspend [i8 0, label %resume70                                i8 1, label %pre.cleanup]71resume:72  call void @print(i32 0)73  br label %cleanup74 75pre.cleanup:76  call void @print(i32 1)77  br label %cleanup78 79cleanup:80  %mem = call ptr @llvm.coro.free(token %id, ptr %hdl)81  call void @free(ptr %mem)82  br label %suspend83suspend:84  call void @llvm.coro.end(ptr %hdl, i1 false, token none)85  ret void86}87 88; SimplifySuspendPoint will detect that coroutine destroys itself and will89; replace suspend with a jump to %cleanup label turning it into no-suspend90; coroutine.91;92; CHECK-LABEL: define void @simplify_destroy(93; CHECK-NEXT:  entry:94; CHECK-NEXT:    call void @print(i32 1)95; CHECK-NEXT:    ret void96;97define void @simplify_destroy() presplitcoroutine personality i32 0 {98entry:99  %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)100  %need.dyn.alloc = call i1 @llvm.coro.alloc(token %id)101  br i1 %need.dyn.alloc, label %dyn.alloc, label %coro.begin102dyn.alloc:103  %size = call i32 @llvm.coro.size.i32()104  %alloc = call ptr @malloc(i32 %size)105  br label %coro.begin106coro.begin:107  %phi = phi ptr [ null, %entry ], [ %alloc, %dyn.alloc ]108  %hdl = call noalias ptr @llvm.coro.begin(token %id, ptr %phi)109  br label %body110body:111  %save = call token @llvm.coro.save(ptr %hdl)112  %subfn = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 1)113  invoke fastcc void %subfn(ptr %hdl) to label %real_susp unwind label %lpad114 115real_susp:116  %0 = call i8 @llvm.coro.suspend(token %save, i1 false)117  switch i8 %0, label %suspend [i8 0, label %resume118                                i8 1, label %pre.cleanup]119resume:120  call void @print(i32 0)121  br label %cleanup122 123pre.cleanup:124  call void @print(i32 1)125  br label %cleanup126 127cleanup:128  %mem = call ptr @llvm.coro.free(token %id, ptr %hdl)129  call void @free(ptr %mem)130  br label %suspend131suspend:132  call void @llvm.coro.end(ptr %hdl, i1 false, token none)133  ret void134lpad:135  %lpval = landingpad { ptr, i32 }136     cleanup137 138  call void @print(i32 2)139  resume { ptr, i32 } %lpval140}141 142; SimplifySuspendPoint will detect that coro.resume resumes itself and will143; replace suspend with a jump to %resume label turning it into no-suspend144; coroutine.145;146; CHECK-LABEL: define void @simplify_resume_with_inlined_if(147; CHECK-NEXT:  entry:148; CHECK-NEXT:    br i1149; CHECK:         call void @print(i32 0)150; CHECK-NEXT:    ret void151;152define void @simplify_resume_with_inlined_if(ptr %src, ptr %dst, i1 %cond) presplitcoroutine {153entry:154  %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)155  %need.dyn.alloc = call i1 @llvm.coro.alloc(token %id)156  br i1 %need.dyn.alloc, label %dyn.alloc, label %coro.begin157dyn.alloc:158  %size = call i32 @llvm.coro.size.i32()159  %alloc = call ptr @malloc(i32 %size)160  br label %coro.begin161coro.begin:162  %phi = phi ptr [ null, %entry ], [ %alloc, %dyn.alloc ]163  %hdl = call noalias ptr @llvm.coro.begin(token %id, ptr %phi)164  br label %body165body:166  %save = call token @llvm.coro.save(ptr %hdl)167  br i1 %cond, label %if.then, label %if.else168if.then:169  call void @llvm.memcpy.p0.p0.i64(ptr %dst, ptr %src, i64 1, i1 false)170  br label %if.end171if.else:172  call void @llvm.memcpy.p0.p0.i64(ptr %src, ptr %dst, i64 1, i1 false)173  br label %if.end174if.end:175  %subfn = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 0)176  call fastcc void %subfn(ptr %hdl)177  %0 = call i8 @llvm.coro.suspend(token %save, i1 false)178  switch i8 %0, label %suspend [i8 0, label %resume179                                i8 1, label %pre.cleanup]180resume:181  call void @print(i32 0)182  br label %cleanup183 184pre.cleanup:185  call void @print(i32 1)186  br label %cleanup187 188cleanup:189  %mem = call ptr @llvm.coro.free(token %id, ptr %hdl)190  call void @free(ptr %mem)191  br label %suspend192suspend:193  call void @llvm.coro.end(ptr %hdl, i1 false, token none)194  ret void195}196 197 198 199; SimplifySuspendPoint won't be able to simplify if it detects that there are200; other calls between coro.save and coro.suspend. They potentially can call201; resume or destroy, so we should not simplify this suspend point.202;203; CHECK-LABEL: define void @cannot_simplify_other_calls(204; CHECK-NEXT:  entry:205; CHECK-NEXT:     llvm.coro.id206 207define void @cannot_simplify_other_calls() presplitcoroutine {208entry:209  %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)210  %need.dyn.alloc = call i1 @llvm.coro.alloc(token %id)211  br i1 %need.dyn.alloc, label %dyn.alloc, label %coro.begin212dyn.alloc:213  %size = call i32 @llvm.coro.size.i32()214  %alloc = call ptr @malloc(i32 %size)215  br label %coro.begin216coro.begin:217  %phi = phi ptr [ null, %entry ], [ %alloc, %dyn.alloc ]218  %hdl = call noalias ptr @llvm.coro.begin(token %id, ptr %phi)219  br label %body220body:221  %save = call token @llvm.coro.save(ptr %hdl)222  br label %body1223 224body1:225  call void @foo()226  br label %body2227 228body2:229  %subfn = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 1)230  call fastcc void %subfn(ptr %hdl)231  %0 = call i8 @llvm.coro.suspend(token %save, i1 false)232  switch i8 %0, label %suspend [i8 0, label %resume233                                i8 1, label %pre.cleanup]234resume:235  call void @print(i32 0)236  br label %cleanup237 238pre.cleanup:239  call void @print(i32 1)240  br label %cleanup241 242cleanup:243  %mem = call ptr @llvm.coro.free(token %id, ptr %hdl)244  call void @free(ptr %mem)245  br label %suspend246suspend:247  call void @llvm.coro.end(ptr %hdl, i1 false, token none)248  ret void249}250 251; SimplifySuspendPoint won't be able to simplify if it detects that there are252; other calls between coro.save and coro.suspend. They potentially can call253; resume or destroy, so we should not simplify this suspend point.254;255; CHECK-LABEL: define void @cannot_simplify_calls_in_terminator(256; CHECK-NEXT:  entry:257; CHECK-NEXT:     llvm.coro.id258 259define void @cannot_simplify_calls_in_terminator() presplitcoroutine personality i32 0 {260entry:261  %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)262  %need.dyn.alloc = call i1 @llvm.coro.alloc(token %id)263  br i1 %need.dyn.alloc, label %dyn.alloc, label %coro.begin264dyn.alloc:265  %size = call i32 @llvm.coro.size.i32()266  %alloc = call ptr @malloc(i32 %size)267  br label %coro.begin268coro.begin:269  %phi = phi ptr [ null, %entry ], [ %alloc, %dyn.alloc ]270  %hdl = call noalias ptr @llvm.coro.begin(token %id, ptr %phi)271  br label %body272body:273  %save = call token @llvm.coro.save(ptr %hdl)274  invoke void @foo() to label %resume_cont unwind label %lpad275resume_cont:276  %subfn = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 1)277  call fastcc void %subfn(ptr %hdl)278  %0 = call i8 @llvm.coro.suspend(token %save, i1 false)279  switch i8 %0, label %suspend [i8 0, label %resume280                                i8 1, label %pre.cleanup]281resume:282  call void @print(i32 0)283  br label %cleanup284 285pre.cleanup:286  call void @print(i32 1)287  br label %cleanup288 289cleanup:290  %mem = call ptr @llvm.coro.free(token %id, ptr %hdl)291  call void @free(ptr %mem)292  br label %suspend293suspend:294  call void @llvm.coro.end(ptr %hdl, i1 false, token none)295  ret void296lpad:297  %lpval = landingpad { ptr, i32 }298     cleanup299 300  call void @print(i32 2)301  resume { ptr, i32 } %lpval302}303 304; SimplifySuspendPoint won't be able to simplify if it detects that resume or305; destroy does not immediately preceed coro.suspend.306;307; CHECK-LABEL: define void @cannot_simplify_not_last_instr(308; CHECK-NEXT:  entry:309; CHECK-NEXT:     llvm.coro.id310 311define void @cannot_simplify_not_last_instr(ptr %dst, ptr %src) presplitcoroutine {312entry:313  %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)314  %need.dyn.alloc = call i1 @llvm.coro.alloc(token %id)315  br i1 %need.dyn.alloc, label %dyn.alloc, label %coro.begin316dyn.alloc:317  %size = call i32 @llvm.coro.size.i32()318  %alloc = call ptr @malloc(i32 %size)319  br label %coro.begin320coro.begin:321  %phi = phi ptr [ null, %entry ], [ %alloc, %dyn.alloc ]322  %hdl = call noalias ptr @llvm.coro.begin(token %id, ptr %phi)323  br label %body324body:325  %save = call token @llvm.coro.save(ptr %hdl)326  %subfn = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 1)327  call fastcc void %subfn(ptr %hdl)328  ; memcpy separates destroy from suspend, therefore cannot simplify.329  call void @llvm.memcpy.p0.p0.i64(ptr %dst, ptr %src, i64 1, i1 false)330  %0 = call i8 @llvm.coro.suspend(token %save, i1 false)331  switch i8 %0, label %suspend [i8 0, label %resume332                                i8 1, label %pre.cleanup]333resume:334  call void @print(i32 0)335  br label %cleanup336 337pre.cleanup:338  call void @print(i32 1)339  br label %cleanup340 341cleanup:342  %mem = call ptr @llvm.coro.free(token %id, ptr %hdl)343  call void @free(ptr %mem)344  br label %suspend345suspend:346  call void @llvm.coro.end(ptr %hdl, i1 false, token none)347  ret void348}349 350; SimplifySuspendPoint should not simplify final suspend point351;352; CHECK-LABEL: define void @cannot_simplify_final_suspend(353; CHECK-NEXT:  entry:354; CHECK-NEXT:     llvm.coro.id355;356define void @cannot_simplify_final_suspend() presplitcoroutine personality i32 0 {357entry:358  %id = call token @llvm.coro.id(i32 0, ptr null, ptr null, ptr null)359  %need.dyn.alloc = call i1 @llvm.coro.alloc(token %id)360  br i1 %need.dyn.alloc, label %dyn.alloc, label %coro.begin361dyn.alloc:362  %size = call i32 @llvm.coro.size.i32()363  %alloc = call ptr @malloc(i32 %size)364  br label %coro.begin365coro.begin:366  %phi = phi ptr [ null, %entry ], [ %alloc, %dyn.alloc ]367  %hdl = call noalias ptr @llvm.coro.begin(token %id, ptr %phi)368  br label %body369body:370  %save = call token @llvm.coro.save(ptr %hdl)371  %subfn = call ptr @llvm.coro.subfn.addr(ptr %hdl, i8 1)372  invoke fastcc void %subfn(ptr %hdl) to label %real_susp unwind label %lpad373 374real_susp:375  %0 = call i8 @llvm.coro.suspend(token %save, i1 1)376  switch i8 %0, label %suspend [i8 0, label %resume377                                i8 1, label %pre.cleanup]378resume:379  call void @print(i32 0)380  br label %cleanup381 382pre.cleanup:383  call void @print(i32 1)384  br label %cleanup385 386cleanup:387  %mem = call ptr @llvm.coro.free(token %id, ptr %hdl)388  call void @free(ptr %mem)389  br label %suspend390suspend:391  call void @llvm.coro.end(ptr %hdl, i1 false, token none)392  ret void393lpad:394  %lpval = landingpad { ptr, i32 }395     cleanup396 397  call void @print(i32 2)398  resume { ptr, i32 } %lpval399}400 401declare ptr @malloc(i32) allockind("alloc,uninitialized") allocsize(0)402declare void @free(ptr) willreturn allockind("free")403declare void @print(i32)404declare void @foo()405 406declare token @llvm.coro.id(i32, ptr, ptr, ptr)407declare i1 @llvm.coro.alloc(token)408declare i32 @llvm.coro.size.i32()409declare ptr @llvm.coro.begin(token, ptr)410declare token @llvm.coro.save(ptr %hdl)411declare i8 @llvm.coro.suspend(token, i1)412declare ptr @llvm.coro.free(token, ptr)413declare void @llvm.coro.end(ptr, i1, token)414 415declare ptr @llvm.coro.subfn.addr(ptr, i8)416 417declare void @llvm.memcpy.p0.p0.i64(ptr nocapture writeonly, ptr nocapture readonly, i64, i1)418