blob: 9061ed161a3741fb3907b46693c9684aa6a2b841 [file] [log] [blame]
Thomas Livelya1d97a92019-06-26 16:17:15 +00001; RUN: llc < %s -asm-verbose=false -verify-machineinstrs -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=+tail-call | FileCheck --check-prefixes=CHECK,SLOW %s
2; RUN: llc < %s -asm-verbose=false -verify-machineinstrs -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -fast-isel -mattr=+tail-call | FileCheck --check-prefixes=CHECK,FAST %s
Thomas Livelyeafe8ef2019-05-23 17:26:47 +00003
4; Test that the tail-call attribute is accepted
Thomas Livelyeafe8ef2019-05-23 17:26:47 +00005
6target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
7target triple = "wasm32-unknown-unknown"
8
Thomas Livelya1d97a92019-06-26 16:17:15 +00009%fn = type <{i32 (%fn, i32, i32)*}>
10declare i1 @foo(i1)
11declare i1 @bar(i1)
12
13; CHECK-LABEL: recursive_notail_nullary:
14; CHECK: {{^}} call recursive_notail_nullary{{$}}
15; CHECK-NEXT: return
16define void @recursive_notail_nullary() {
17 notail call void @recursive_notail_nullary()
18 ret void
19}
20
21; CHECK-LABEL: recursive_musttail_nullary:
22; CHECK: return_call recursive_musttail_nullary{{$}}
23define void @recursive_musttail_nullary() {
24 musttail call void @recursive_musttail_nullary()
25 ret void
26}
27
28; CHECK-LABEL: recursive_tail_nullary:
29; SLOW: return_call recursive_tail_nullary{{$}}
30; FAST: {{^}} call recursive_tail_nullary{{$}}
31; FAST-NEXT: return{{$}}
32define void @recursive_tail_nullary() {
33 tail call void @recursive_tail_nullary()
34 ret void
35}
36
37; CHECK-LABEL: recursive_notail:
38; CHECK: i32.call $push[[L:[0-9]+]]=, recursive_notail, $0, $1{{$}}
39; CHECK-NEXT: return $pop[[L]]{{$}}
40define i32 @recursive_notail(i32 %x, i32 %y) {
41 %v = notail call i32 @recursive_notail(i32 %x, i32 %y)
42 ret i32 %v
43}
44
45; CHECK-LABEL: recursive_musttail:
46; CHECK: return_call recursive_musttail, $0, $1{{$}}
47define i32 @recursive_musttail(i32 %x, i32 %y) {
48 %v = musttail call i32 @recursive_musttail(i32 %x, i32 %y)
49 ret i32 %v
50}
51
Thomas Livelyeafe8ef2019-05-23 17:26:47 +000052; CHECK-LABEL: recursive_tail:
Thomas Livelya1d97a92019-06-26 16:17:15 +000053; SLOW: return_call recursive_tail, $0, $1{{$}}
54; FAST: i32.call $push[[L:[0-9]+]]=, recursive_tail, $0, $1{{$}}
55; FAST-NEXT: return $pop[[L]]{{$}}
56define i32 @recursive_tail(i32 %x, i32 %y) {
57 %v = tail call i32 @recursive_tail(i32 %x, i32 %y)
58 ret i32 %v
59}
60
61; CHECK-LABEL: indirect_notail:
62; CHECK: i32.call_indirect $push[[L:[0-9]+]]=, $0, $1, $2, $0{{$}}
63; CHECK-NEXT: return $pop[[L]]{{$}}
64define i32 @indirect_notail(%fn %f, i32 %x, i32 %y) {
65 %p = extractvalue %fn %f, 0
66 %v = notail call i32 %p(%fn %f, i32 %x, i32 %y)
67 ret i32 %v
68}
69
70; CHECK-LABEL: indirect_musttail:
71; CHECK: return_call_indirect , $0, $1, $2, $0{{$}}
72define i32 @indirect_musttail(%fn %f, i32 %x, i32 %y) {
73 %p = extractvalue %fn %f, 0
74 %v = musttail call i32 %p(%fn %f, i32 %x, i32 %y)
75 ret i32 %v
76}
77
78; CHECK-LABEL: indirect_tail:
79; CHECK: return_call_indirect , $0, $1, $2, $0{{$}}
80define i32 @indirect_tail(%fn %f, i32 %x, i32 %y) {
81 %p = extractvalue %fn %f, 0
82 %v = tail call i32 %p(%fn %f, i32 %x, i32 %y)
83 ret i32 %v
84}
85
86; CHECK-LABEL: choice_notail:
87; CHECK: i32.call_indirect $push[[L:[0-9]+]]=, $0, $pop{{[0-9]+}}{{$}}
88; CHECK-NEXT: return $pop[[L]]{{$}}
89define i1 @choice_notail(i1 %x) {
90 %p = select i1 %x, i1 (i1)* @foo, i1 (i1)* @bar
91 %v = notail call i1 %p(i1 %x)
92 ret i1 %v
93}
94
95; CHECK-LABEL: choice_musttail:
96; CHECK: return_call_indirect , $0, $pop{{[0-9]+}}{{$}}
97define i1 @choice_musttail(i1 %x) {
98 %p = select i1 %x, i1 (i1)* @foo, i1 (i1)* @bar
99 %v = musttail call i1 %p(i1 %x)
100 ret i1 %v
101}
102
103; CHECK-LABEL: choice_tail:
104; SLOW: return_call_indirect , $0, $pop{{[0-9]+}}{{$}}
105; FAST: i32.call_indirect $push[[L:[0-9]+]]=, $0, $pop{{[0-9]+}}{{$}}
106; FAST: return $pop[[L]]{{$}}
107define i1 @choice_tail(i1 %x) {
108 %p = select i1 %x, i1 (i1)* @foo, i1 (i1)* @bar
109 %v = tail call i1 %p(i1 %x)
110 ret i1 %v
111}
112
113; It is an LLVM validation error for a 'musttail' callee to have a different
114; prototype than its caller, so the following tests can only be done with
115; 'tail'.
116
117; CHECK-LABEL: mismatched_prototypes:
118; SLOW: return_call baz, $pop{{[0-9]+}}, $pop{{[0-9]+}}, $pop{{[0-9]+}}{{$}}
119; FAST: i32.call $push[[L:[0-9]+]]=, baz, $pop{{[0-9]+}}, $pop{{[0-9]+}}, $pop{{[0-9]+}}{{$}}
120; FAST: return $pop[[L]]{{$}}
121declare i32 @baz(i32, i32, i32)
122define i32 @mismatched_prototypes() {
123 %v = tail call i32 @baz(i32 0, i32 42, i32 6)
124 ret i32 %v
125}
126
127; CHECK-LABEL: mismatched_byval:
128; CHECK: i32.store
129; CHECK: return_call quux, $pop{{[0-9]+}}{{$}}
130declare i32 @quux(i32* byval)
131define i32 @mismatched_byval(i32* %x) {
132 %v = tail call i32 @quux(i32* byval %x)
133 ret i32 %v
134}
135
136; CHECK-LABEL: varargs:
137; CHECK: i32.store
138; CHECK: return_call var, $1{{$}}
139declare i32 @var(...)
140define i32 @varargs(i32 %x) {
141 %v = tail call i32 (...) @var(i32 %x)
Thomas Livelyeafe8ef2019-05-23 17:26:47 +0000142 ret i32 %v
143}
144
145; CHECK-LABEL: .section .custom_section.target_features
146; CHECK-NEXT: .int8 1
147; CHECK-NEXT: .int8 43
148; CHECK-NEXT: .int8 9
149; CHECK-NEXT: .ascii "tail-call"