llvm/llvm/test/Transforms/Coroutines/coro-async-nomerge.ll

; RUN: opt < %s -O2 -S
; RUN: opt -S -hoist-common-insts -hoist-common-insts -passes=simplifycfg < %s | FileCheck %s --check-prefixes=CHECK
target datalayout = "p:64:64:64"
%swift.async_func_pointer = type <{ i32, i32 }>
%swift.context = type { ptr, ptr }

declare void @f()
declare void @g()
declare ptr @llvm.coro.async.resume()
declare { ptr } @llvm.coro.suspend.async.sl_p0i8s(i32, ptr, ptr, ...)
declare ptr @llvm.coro.begin(token, ptr writeonly)
declare token @llvm.coro.id.async(i32, i32, i32, ptr)

declare i1 @llvm.coro.end.async(ptr, i1, ...)

define linkonce_odr hidden ptr @__swift_async_resume_get_context(ptr %0) {
entry:
  ret ptr %0
}

@repoTU = hidden global %swift.async_func_pointer <{ i32 trunc (i64 sub (i64 ptrtoint (ptr @repo to i64), i64 ptrtoint (ptr @repoTU to i64)) to i32), i32 16 }>, align 8

; This test used to crash in optimized mode because simplify cfg would sink the
; suspend.async() instruction into a common successor block.

; CHECK: swifttailcc void @repo
; CHECK:llvm.coro.suspend.async.sl_p0s
; CHECK: br
; CHECK:llvm.coro.suspend.async.sl_p0s
; CHECK: br
; CHECK: ret

define hidden swifttailcc void @repo(ptr swiftasync %0, i1 %cond) {
entry:
  %tok = call token @llvm.coro.id.async(i32 16, i32 16, i32 0, ptr @repoTU)
  %id = call ptr @llvm.coro.begin(token %tok, ptr null)
  br i1 %cond, label %bb1, label %bb2

bb1:
  call void @f()
  %ptr0 = call ptr @llvm.coro.async.resume()
  call void @f()
  ; Simplifycfg must not sink the suspend instruction.
  %t3 = call { ptr } (i32, ptr, ptr, ...) @llvm.coro.suspend.async.sl_p0i8s(i32 0, ptr %ptr0, ptr @__swift_async_resume_get_context, ptr @repo.1, ptr %ptr0, ptr %0)
  br label %tailblock

bb2:
  call void @g()
  %ptr1 = call ptr @llvm.coro.async.resume()
  call void @g()
  ; Simplifycfg must not sink the suspend instruction.
  %t4 = call { ptr } (i32, ptr, ptr, ...) @llvm.coro.suspend.async.sl_p0i8s(i32 0, ptr %ptr1, ptr @__swift_async_resume_get_context, ptr @repo.1, ptr %ptr1, ptr %0)
  br label %tailblock

tailblock:
  %t = call i1 (ptr, i1, ...) @llvm.coro.end.async(ptr %id, i1 false, ptr @repo.0, ptr @return, ptr %0)
  unreachable
}

define internal swifttailcc void @repo.0(ptr %0, ptr %1) {
entry:
  musttail call swifttailcc void %0(ptr swiftasync %1)
  ret void
}

declare swifttailcc void @swift_task_switch(ptr, ptr)

define internal swifttailcc void @repo.1(ptr %0, ptr %1) {
entry:
  musttail call swifttailcc void @swift_task_switch(ptr swiftasync %1, ptr %0)
  ret void
}

declare swifttailcc void @return(ptr swiftasync)

@repoTU2 = hidden global %swift.async_func_pointer <{ i32 trunc (i64 sub (i64 ptrtoint (ptr @repo2 to i64), i64 ptrtoint (ptr @repoTU2 to i64)) to i32), i32 16 }>, align 8

; This test used to crash in optimized mode because simplify cfg would hoist the
; async.resume() instruction into a common block.

; CHECK: swifttailcc void @repo2
; CHECK: entry:
; CHECK: br i1

; CHECK: @llvm.coro.async.resume()
; CHECK: llvm.coro.suspend.async.sl_p0s
; CHECK: br

; CHECK:@llvm.coro.async.resume()
; CHECK:llvm.coro.suspend.async.sl_p0s
; CHECK: br

; CHECK: ret

define hidden swifttailcc void @repo2(ptr swiftasync %0, i1 %cond) {
entry:
  %tok = call token @llvm.coro.id.async(i32 16, i32 16, i32 0, ptr @repoTU2)
  %id = call ptr @llvm.coro.begin(token %tok, ptr null)
  br i1 %cond, label %bb1, label %bb2

bb1:
  ; Simplifycfg must not hoist the resume instruction.
  %ptr0 = call ptr @llvm.coro.async.resume()
  call void @f()
  %t3 = call { ptr } (i32, ptr, ptr, ...) @llvm.coro.suspend.async.sl_p0i8s(i32 0, ptr %ptr0, ptr @__swift_async_resume_get_context, ptr @repo.1, ptr %ptr0, ptr %0)
  call void @f()
  br label %tailblock

bb2:
  ; Simplifycfg must not hoist the resume instruction.
  %ptr1 = call ptr @llvm.coro.async.resume()
  call void @g()
  %t4 = call { ptr } (i32, ptr, ptr, ...) @llvm.coro.suspend.async.sl_p0i8s(i32 0, ptr %ptr1, ptr @__swift_async_resume_get_context, ptr @repo.1, ptr %ptr1, ptr %0)
  call void @g()
  br label %tailblock

tailblock:
  %t = call i1 (ptr, i1, ...) @llvm.coro.end.async(ptr %id, i1 false, ptr @repo.0, ptr @return, ptr %0)
  unreachable
}