blob: e960a18e718a0f36fd2e64a318c0bde2ac8d6be4 [file] [edit]
; RUN: llc < %s -asm-verbose=false | FileCheck %s
; ABI contract: the async context must always be available in local 0, so no
; other value may be written to the local of the swiftasync argument, even after
; the last use of the argument.
target triple = "wasm32-unknown-unknown"
declare swiftcc void @swift_task_dealloc(ptr)
; Register coloring does not give local 0 to the parent context.
; CHECK-LABEL: swiftasync:
; CHECK-NEXT: .functype swiftasync (i32, i32, i32, i32) -> ()
; CHECK-NEXT: .local i32
; CHECK-NEXT: local.get 0
; CHECK-NEXT: i32.load 0
; CHECK-NEXT: local.tee 4
; CHECK-NOT: local.{{set|tee}} 0{{$}}
; CHECK: end_function
define swiftcc void @swiftasync(ptr swiftasync %callee_ctx, i32 %result) {
%ctx = load ptr, ptr %callee_ctx
%saved = getelementptr inbounds i8, ptr %ctx, i32 8
%callee = load ptr, ptr %saved
call swiftcc void @swift_task_dealloc(ptr %callee)
%resume_addr = getelementptr inbounds i8, ptr %ctx, i32 4
%resume = load ptr, ptr %resume_addr
call swiftcc void %resume(ptr swiftasync %ctx, i32 %result)
ret void
}
; Without swiftasync, local 0 is reused.
; CHECK-LABEL: no_swiftasync:
; CHECK-NEXT: .functype no_swiftasync (i32, i32, i32, i32) -> ()
; CHECK-NEXT: local.get 0
; CHECK-NEXT: i32.load 0
; CHECK-NEXT: local.tee 0
define swiftcc void @no_swiftasync(ptr %callee_ctx, i32 %result) {
%ctx = load ptr, ptr %callee_ctx
%saved = getelementptr inbounds i8, ptr %ctx, i32 8
%callee = load ptr, ptr %saved
call swiftcc void @swift_task_dealloc(ptr %callee)
%resume_addr = getelementptr inbounds i8, ptr %ctx, i32 4
%resume = load ptr, ptr %resume_addr
call swiftcc void %resume(ptr %ctx, i32 %result)
ret void
}
; Register coalescing merges the swiftasync argument with the loop variable,
; which then gets another local.
; CHECK-LABEL: coalesced:
; CHECK-NEXT: .functype coalesced (i32, i32, i32, i32) -> (i32)
; CHECK-NEXT: .local i32, i32
; CHECK-NEXT: local.get 0
; CHECK-NEXT: local.set 4
; CHECK-NOT: local.{{set|tee}} 0{{$}}
; CHECK: end_function
define swiftcc ptr @coalesced(ptr swiftasync %ctx, i32 %n) {
entry:
br label %loop
loop:
%p = phi ptr [ %ctx, %entry ], [ %next, %loop ]
%i = phi i32 [ 0, %entry ], [ %inc, %loop ]
%next = load ptr, ptr %p
%inc = add i32 %i, 1
%c = icmp ult i32 %inc, %n
br i1 %c, label %loop, label %exit
exit:
ret ptr %next
}
; CHECK-LABEL: coalesced_with_call:
; CHECK-NEXT: .functype coalesced_with_call (i32, i32, i32, i32) -> (i32)
; CHECK: local.get 0
; CHECK-NEXT: local.set [[P:[0-9]+]]
; CHECK-NOT: local.{{set|tee}} 0{{$}}
; CHECK: end_function
define swiftcc ptr @coalesced_with_call(ptr swiftasync %ctx, i32 %n) {
entry:
%c0 = icmp eq i32 %n, 0
br i1 %c0, label %exit, label %loop
loop:
%p = phi ptr [ %ctx, %entry ], [ %next, %loop ]
%i = phi i32 [ 0, %entry ], [ %inc, %loop ]
%next = load ptr, ptr %p
call swiftcc void @swift_task_dealloc(ptr %next)
%inc = add i32 %i, 1
%c = icmp ult i32 %inc, %n
br i1 %c, label %loop, label %exit
exit:
%r = phi ptr [ %ctx, %entry ], [ %next, %loop ]
ret ptr %r
}