1; 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 3 4; Test that the tail-call attribute is accepted 5 6target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" 7target triple = "wasm32-unknown-unknown" 8 9%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 52; CHECK-LABEL: recursive_tail: 53; 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) 142 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" 150