brintos

brintos / llvm-project-archived public Read only

0
0
Text · 20.3 KiB · 84bd142 Raw
591 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 22; RUN: llc < %s -verify-machineinstrs -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mcpu=mvp -mattr=+tail-call | FileCheck --check-prefixes=CHECK,SLOW %s3; RUN: llc < %s -verify-machineinstrs -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -fast-isel -mcpu=mvp -mattr=+tail-call | FileCheck --check-prefixes=CHECK,FAST %s4; RUN: llc < %s --filetype=obj -mattr=+tail-call | obj2yaml | FileCheck --check-prefix=YAML %s5 6; Test that the tail calls lower correctly7 8target triple = "wasm32-unknown-unknown"9 10%fn = type <{ptr}>11declare i1 @foo(i1)12declare i1 @bar(i1)13 14define void @recursive_notail_nullary() {15; CHECK-LABEL: recursive_notail_nullary:16; CHECK:         .functype recursive_notail_nullary () -> ()17; CHECK-NEXT:  # %bb.0:18; CHECK-NEXT:    call recursive_notail_nullary19; CHECK-NEXT:    return20  notail call void @recursive_notail_nullary()21  ret void22}23 24define void @recursive_musttail_nullary() {25; CHECK-LABEL: recursive_musttail_nullary:26; CHECK:         .functype recursive_musttail_nullary () -> ()27; CHECK-NEXT:  # %bb.0:28; CHECK-NEXT:    return_call recursive_musttail_nullary29  musttail call void @recursive_musttail_nullary()30  ret void31}32define void @recursive_tail_nullary() {33; SLOW-LABEL: recursive_tail_nullary:34; SLOW:         .functype recursive_tail_nullary () -> ()35; SLOW-NEXT:  # %bb.0:36; SLOW-NEXT:    return_call recursive_tail_nullary37;38; FAST-LABEL: recursive_tail_nullary:39; FAST:         .functype recursive_tail_nullary () -> ()40; FAST-NEXT:  # %bb.0:41; FAST-NEXT:    call recursive_tail_nullary42; FAST-NEXT:    return43  tail call void @recursive_tail_nullary()44  ret void45}46 47define i32 @recursive_notail(i32 %x, i32 %y) {48; CHECK-LABEL: recursive_notail:49; CHECK:         .functype recursive_notail (i32, i32) -> (i32)50; CHECK-NEXT:  # %bb.0:51; CHECK-NEXT:    call $push0=, recursive_notail, $0, $152; CHECK-NEXT:    return $pop053  %v = notail call i32 @recursive_notail(i32 %x, i32 %y)54  ret i32 %v55}56 57define i32 @recursive_musttail(i32 %x, i32 %y) {58; CHECK-LABEL: recursive_musttail:59; CHECK:         .functype recursive_musttail (i32, i32) -> (i32)60; CHECK-NEXT:  # %bb.0:61; CHECK-NEXT:    return_call recursive_musttail, $0, $162  %v = musttail call i32 @recursive_musttail(i32 %x, i32 %y)63  ret i32 %v64}65 66define i32 @recursive_tail(i32 %x, i32 %y) {67; SLOW-LABEL: recursive_tail:68; SLOW:         .functype recursive_tail (i32, i32) -> (i32)69; SLOW-NEXT:  # %bb.0:70; SLOW-NEXT:    return_call recursive_tail, $0, $171;72; FAST-LABEL: recursive_tail:73; FAST:         .functype recursive_tail (i32, i32) -> (i32)74; FAST-NEXT:  # %bb.0:75; FAST-NEXT:    call $push0=, recursive_tail, $0, $176; FAST-NEXT:    return $pop077  %v = tail call i32 @recursive_tail(i32 %x, i32 %y)78  ret i32 %v79}80 81define i32 @indirect_notail(%fn %f, i32 %x, i32 %y) {82; CHECK-LABEL: indirect_notail:83; CHECK:         .functype indirect_notail (i32, i32, i32) -> (i32)84; CHECK-NEXT:  # %bb.0:85; CHECK-NEXT:    call_indirect $push0=, $0, $1, $2, $0 # Invalid depth argument!86; CHECK-NEXT:    return $pop087  %p = extractvalue %fn %f, 088  %v = notail call i32 %p(%fn %f, i32 %x, i32 %y)89  ret i32 %v90}91 92define i32 @indirect_musttail(%fn %f, i32 %x, i32 %y) {93; CHECK-LABEL: indirect_musttail:94; CHECK:         .functype indirect_musttail (i32, i32, i32) -> (i32)95; CHECK-NEXT:  # %bb.0:96; CHECK-NEXT:    return_call_indirect , $0, $1, $2, $097  %p = extractvalue %fn %f, 098  %v = musttail call i32 %p(%fn %f, i32 %x, i32 %y)99  ret i32 %v100}101 102define i32 @indirect_tail(%fn %f, i32 %x, i32 %y) {103; CHECK-LABEL: indirect_tail:104; CHECK:         .functype indirect_tail (i32, i32, i32) -> (i32)105; CHECK-NEXT:  # %bb.0:106; CHECK-NEXT:    return_call_indirect , $0, $1, $2, $0107  %p = extractvalue %fn %f, 0108  %v = tail call i32 %p(%fn %f, i32 %x, i32 %y)109  ret i32 %v110}111 112define i1 @choice_notail(i1 %x) {113; SLOW-LABEL: choice_notail:114; SLOW:         .functype choice_notail (i32) -> (i32)115; SLOW-NEXT:  # %bb.0:116; SLOW-NEXT:    i32.const $push3=, foo117; SLOW-NEXT:    i32.const $push2=, bar118; SLOW-NEXT:    i32.const $push0=, 1119; SLOW-NEXT:    i32.and $push1=, $0, $pop0120; SLOW-NEXT:    i32.select $push4=, $pop3, $pop2, $pop1121; SLOW-NEXT:    call_indirect $push5=, $0, $pop4 # Invalid depth argument!122; SLOW-NEXT:    return $pop5123;124; FAST-LABEL: choice_notail:125; FAST:         .functype choice_notail (i32) -> (i32)126; FAST-NEXT:  # %bb.0:127; FAST-NEXT:    i32.const $push3=, foo128; FAST-NEXT:    i32.const $push4=, bar129; FAST-NEXT:    i32.const $push1=, 1130; FAST-NEXT:    i32.and $push2=, $0, $pop1131; FAST-NEXT:    i32.select $push5=, $pop3, $pop4, $pop2132; FAST-NEXT:    call_indirect $push0=, $0, $pop5 # Invalid depth argument!133; FAST-NEXT:    return $pop0134  %p = select i1 %x, ptr @foo, ptr @bar135  %v = notail call i1 %p(i1 %x)136  ret i1 %v137}138 139define i1 @choice_musttail(i1 %x) {140; SLOW-LABEL: choice_musttail:141; SLOW:         .functype choice_musttail (i32) -> (i32)142; SLOW-NEXT:  # %bb.0:143; SLOW-NEXT:    i32.const $push3=, foo144; SLOW-NEXT:    i32.const $push2=, bar145; SLOW-NEXT:    i32.const $push0=, 1146; SLOW-NEXT:    i32.and $push1=, $0, $pop0147; SLOW-NEXT:    i32.select $push4=, $pop3, $pop2, $pop1148; SLOW-NEXT:    return_call_indirect , $0, $pop4149;150; FAST-LABEL: choice_musttail:151; FAST:         .functype choice_musttail (i32) -> (i32)152; FAST-NEXT:  # %bb.0:153; FAST-NEXT:    i32.const $push4=, foo154; FAST-NEXT:    i32.const $push3=, bar155; FAST-NEXT:    i32.const $push1=, 1156; FAST-NEXT:    i32.and $push2=, $0, $pop1157; FAST-NEXT:    i32.select $push0=, $pop4, $pop3, $pop2158; FAST-NEXT:    return_call_indirect , $0, $pop0159  %p = select i1 %x, ptr @foo, ptr @bar160  %v = musttail call i1 %p(i1 %x)161  ret i1 %v162}163 164define i1 @choice_tail(i1 %x) {165; SLOW-LABEL: choice_tail:166; SLOW:         .functype choice_tail (i32) -> (i32)167; SLOW-NEXT:  # %bb.0:168; SLOW-NEXT:    i32.const $push3=, foo169; SLOW-NEXT:    i32.const $push2=, bar170; SLOW-NEXT:    i32.const $push0=, 1171; SLOW-NEXT:    i32.and $push1=, $0, $pop0172; SLOW-NEXT:    i32.select $push4=, $pop3, $pop2, $pop1173; SLOW-NEXT:    return_call_indirect , $0, $pop4174;175; FAST-LABEL: choice_tail:176; FAST:         .functype choice_tail (i32) -> (i32)177; FAST-NEXT:  # %bb.0:178; FAST-NEXT:    i32.const $push3=, foo179; FAST-NEXT:    i32.const $push4=, bar180; FAST-NEXT:    i32.const $push1=, 1181; FAST-NEXT:    i32.and $push2=, $0, $pop1182; FAST-NEXT:    i32.select $push5=, $pop3, $pop4, $pop2183; FAST-NEXT:    call_indirect $push0=, $0, $pop5 # Invalid depth argument!184; FAST-NEXT:    return $pop0185  %p = select i1 %x, ptr @foo, ptr @bar186  %v = tail call i1 %p(i1 %x)187  ret i1 %v188}189 190; It is an LLVM validation error for a 'musttail' callee to have a different191; prototype than its caller, so the following tests can only be done with192; 'tail'.193 194declare i32 @baz(i32, i32, i32)195define i32 @mismatched_prototypes() {196; SLOW-LABEL: mismatched_prototypes:197; SLOW:         .functype mismatched_prototypes () -> (i32)198; SLOW-NEXT:  # %bb.0:199; SLOW-NEXT:    i32.const $push2=, 0200; SLOW-NEXT:    i32.const $push1=, 42201; SLOW-NEXT:    i32.const $push0=, 6202; SLOW-NEXT:    return_call baz, $pop2, $pop1, $pop0203;204; FAST-LABEL: mismatched_prototypes:205; FAST:         .functype mismatched_prototypes () -> (i32)206; FAST-NEXT:  # %bb.0:207; FAST-NEXT:    i32.const $push1=, 0208; FAST-NEXT:    i32.const $push2=, 42209; FAST-NEXT:    i32.const $push3=, 6210; FAST-NEXT:    call $push0=, baz, $pop1, $pop2, $pop3211; FAST-NEXT:    return $pop0212  %v = tail call i32 @baz(i32 0, i32 42, i32 6)213  ret i32 %v214}215 216define void @mismatched_return_void() {217; SLOW-LABEL: mismatched_return_void:218; SLOW:         .functype mismatched_return_void () -> ()219; SLOW-NEXT:  # %bb.0:220; SLOW-NEXT:    i32.const $push2=, 0221; SLOW-NEXT:    i32.const $push1=, 42222; SLOW-NEXT:    i32.const $push0=, 6223; SLOW-NEXT:    call $drop=, baz, $pop2, $pop1, $pop0224; SLOW-NEXT:    return225;226; FAST-LABEL: mismatched_return_void:227; FAST:         .functype mismatched_return_void () -> ()228; FAST-NEXT:  # %bb.0:229; FAST-NEXT:    i32.const $push0=, 0230; FAST-NEXT:    i32.const $push1=, 42231; FAST-NEXT:    i32.const $push2=, 6232; FAST-NEXT:    call $drop=, baz, $pop0, $pop1, $pop2233; FAST-NEXT:    return234  %v = tail call i32 @baz(i32 0, i32 42, i32 6)235  ret void236}237 238define float @mismatched_return_f32() {239; SLOW-LABEL: mismatched_return_f32:240; SLOW:         .functype mismatched_return_f32 () -> (f32)241; SLOW-NEXT:  # %bb.0:242; SLOW-NEXT:    i32.const $push2=, 0243; SLOW-NEXT:    i32.const $push1=, 42244; SLOW-NEXT:    i32.const $push0=, 6245; SLOW-NEXT:    call $push3=, baz, $pop2, $pop1, $pop0246; SLOW-NEXT:    f32.reinterpret_i32 $push4=, $pop3247; SLOW-NEXT:    return $pop4248;249; FAST-LABEL: mismatched_return_f32:250; FAST:         .functype mismatched_return_f32 () -> (f32)251; FAST-NEXT:  # %bb.0:252; FAST-NEXT:    i32.const $push2=, 0253; FAST-NEXT:    i32.const $push3=, 42254; FAST-NEXT:    i32.const $push4=, 6255; FAST-NEXT:    call $push1=, baz, $pop2, $pop3, $pop4256; FAST-NEXT:    f32.reinterpret_i32 $push0=, $pop1257; FAST-NEXT:    return $pop0258  %v = tail call i32 @baz(i32 0, i32 42, i32 6)259  %u = bitcast i32 %v to float260  ret float %u261}262 263define void @mismatched_indirect_void(%fn %f, i32 %x, i32 %y) {264; CHECK-LABEL: mismatched_indirect_void:265; CHECK:         .functype mismatched_indirect_void (i32, i32, i32) -> ()266; CHECK-NEXT:  # %bb.0:267; CHECK-NEXT:    call_indirect $drop=, $0, $1, $2, $0 # Invalid depth argument!268; CHECK-NEXT:    return269  %p = extractvalue %fn %f, 0270  %v = tail call i32 %p(%fn %f, i32 %x, i32 %y)271  ret void272}273 274define float @mismatched_indirect_f32(%fn %f, i32 %x, i32 %y) {275; CHECK-LABEL: mismatched_indirect_f32:276; CHECK:         .functype mismatched_indirect_f32 (i32, i32, i32) -> (f32)277; CHECK-NEXT:  # %bb.0:278; CHECK-NEXT:    call_indirect $push0=, $0, $1, $2, $0 # Invalid depth argument!279; CHECK-NEXT:    f32.reinterpret_i32 $push1=, $pop0280; CHECK-NEXT:    return $pop1281  %p = extractvalue %fn %f, 0282  %v = tail call i32 %p(%fn %f, i32 %x, i32 %y)283  %u = bitcast i32 %v to float284  ret float %u285}286 287declare i32 @quux(ptr byval(i32))288define i32 @mismatched_byval(ptr %x) {289; CHECK-LABEL: mismatched_byval:290; CHECK:         .functype mismatched_byval (i32) -> (i32)291; CHECK-NEXT:  # %bb.0:292; CHECK-NEXT:    global.get $push1=, __stack_pointer293; CHECK-NEXT:    i32.const $push2=, 16294; CHECK-NEXT:    i32.sub $push8=, $pop1, $pop2295; CHECK-NEXT:    local.tee $push7=, $1=, $pop8296; CHECK-NEXT:    global.set __stack_pointer, $pop7297; CHECK-NEXT:    i32.load $push0=, 0($0)298; CHECK-NEXT:    i32.store 12($1), $pop0299; CHECK-NEXT:    i32.const $push3=, 16300; CHECK-NEXT:    i32.add $push4=, $1, $pop3301; CHECK-NEXT:    global.set __stack_pointer, $pop4302; CHECK-NEXT:    i32.const $push5=, 12303; CHECK-NEXT:    i32.add $push6=, $1, $pop5304; CHECK-NEXT:    return_call quux, $pop6305  %v = tail call i32 @quux(ptr byval(i32) %x)306  ret i32 %v307}308 309declare i32 @var(...)310define i32 @varargs(i32 %x) {311; CHECK-LABEL: varargs:312; CHECK:         .functype varargs (i32) -> (i32)313; CHECK-NEXT:  # %bb.0:314; CHECK-NEXT:    global.get $push0=, __stack_pointer315; CHECK-NEXT:    i32.const $push1=, 16316; CHECK-NEXT:    i32.sub $push5=, $pop0, $pop1317; CHECK-NEXT:    local.tee $push4=, $1=, $pop5318; CHECK-NEXT:    global.set __stack_pointer, $pop4319; CHECK-NEXT:    i32.store 0($1), $0320; CHECK-NEXT:    call $0=, var, $1321; CHECK-NEXT:    i32.const $push2=, 16322; CHECK-NEXT:    i32.add $push3=, $1, $pop2323; CHECK-NEXT:    global.set __stack_pointer, $pop3324; CHECK-NEXT:    return $0325  %v = tail call i32 (...) @var(i32 %x)326  ret i32 %v327}328 329; Type transformations inhibit tail calls, even when they are nops330 331define i32 @mismatched_return_zext() {332; SLOW-LABEL: mismatched_return_zext:333; SLOW:         .functype mismatched_return_zext () -> (i32)334; SLOW-NEXT:  # %bb.0:335; SLOW-NEXT:    i32.const $push0=, 1336; SLOW-NEXT:    call $push1=, foo, $pop0337; SLOW-NEXT:    i32.const $push3=, 1338; SLOW-NEXT:    i32.and $push2=, $pop1, $pop3339; SLOW-NEXT:    return $pop2340;341; FAST-LABEL: mismatched_return_zext:342; FAST:         .functype mismatched_return_zext () -> (i32)343; FAST-NEXT:  # %bb.0:344; FAST-NEXT:    i32.const $push2=, 1345; FAST-NEXT:    call $push1=, foo, $pop2346; FAST-NEXT:    i32.const $push3=, 1347; FAST-NEXT:    i32.and $push0=, $pop1, $pop3348; FAST-NEXT:    return $pop0349  %v = tail call i1 @foo(i1 1)350  %u = zext i1 %v to i32351  ret i32 %u352}353 354define i32 @mismatched_return_sext() {355; SLOW-LABEL: mismatched_return_sext:356; SLOW:         .functype mismatched_return_sext () -> (i32)357; SLOW-NEXT:  # %bb.0:358; SLOW-NEXT:    i32.const $push3=, 0359; SLOW-NEXT:    i32.const $push0=, 1360; SLOW-NEXT:    call $push1=, foo, $pop0361; SLOW-NEXT:    i32.const $push5=, 1362; SLOW-NEXT:    i32.and $push2=, $pop1, $pop5363; SLOW-NEXT:    i32.sub $push4=, $pop3, $pop2364; SLOW-NEXT:    return $pop4365;366; FAST-LABEL: mismatched_return_sext:367; FAST:         .functype mismatched_return_sext () -> (i32)368; FAST-NEXT:  # %bb.0:369; FAST-NEXT:    i32.const $push4=, 1370; FAST-NEXT:    call $push3=, foo, $pop4371; FAST-NEXT:    i32.const $push0=, 31372; FAST-NEXT:    i32.shl $push1=, $pop3, $pop0373; FAST-NEXT:    i32.const $push5=, 31374; FAST-NEXT:    i32.shr_s $push2=, $pop1, $pop5375; FAST-NEXT:    return $pop2376  %v = tail call i1 @foo(i1 1)377  %u = sext i1 %v to i32378  ret i32 %u379}380 381declare i32 @int()382define i1 @mismatched_return_trunc() {383; CHECK-LABEL: mismatched_return_trunc:384; CHECK:         .functype mismatched_return_trunc () -> (i32)385; CHECK-NEXT:  # %bb.0:386; CHECK-NEXT:    call $push0=, int387; CHECK-NEXT:    return $pop0388  %v = tail call i32 @int()389  %u = trunc i32 %v to i1390  ret i1 %u391}392 393; Stack-allocated arguments inhibit tail calls394 395define i32 @stack_arg(ptr %x) {396; SLOW-LABEL: stack_arg:397; SLOW:         .functype stack_arg (i32) -> (i32)398; SLOW-NEXT:  # %bb.0:399; SLOW-NEXT:    global.get $push0=, __stack_pointer400; SLOW-NEXT:    i32.const $push1=, 16401; SLOW-NEXT:    i32.sub $push7=, $pop0, $pop1402; SLOW-NEXT:    local.tee $push6=, $2=, $pop7403; SLOW-NEXT:    global.set __stack_pointer, $pop6404; SLOW-NEXT:    i32.const $push4=, 12405; SLOW-NEXT:    i32.add $push5=, $2, $pop4406; SLOW-NEXT:    call $1=, stack_arg, $pop5407; SLOW-NEXT:    i32.const $push2=, 16408; SLOW-NEXT:    i32.add $push3=, $2, $pop2409; SLOW-NEXT:    global.set __stack_pointer, $pop3410; SLOW-NEXT:    return $1411;412; FAST-LABEL: stack_arg:413; FAST:         .functype stack_arg (i32) -> (i32)414; FAST-NEXT:  # %bb.0:415; FAST-NEXT:    global.get $push1=, __stack_pointer416; FAST-NEXT:    i32.const $push2=, 16417; FAST-NEXT:    i32.sub $push8=, $pop1, $pop2418; FAST-NEXT:    local.tee $push7=, $2=, $pop8419; FAST-NEXT:    global.set __stack_pointer, $pop7420; FAST-NEXT:    i32.const $push5=, 12421; FAST-NEXT:    i32.add $push6=, $2, $pop5422; FAST-NEXT:    local.copy $push0=, $pop6423; FAST-NEXT:    call $1=, stack_arg, $pop0424; FAST-NEXT:    i32.const $push3=, 16425; FAST-NEXT:    i32.add $push4=, $2, $pop3426; FAST-NEXT:    global.set __stack_pointer, $pop4427; FAST-NEXT:    return $1428  %a = alloca i32429  %v = tail call i32 @stack_arg(ptr %a)430  ret i32 %v431}432 433define i32 @stack_arg_gep(ptr %x) {434; SLOW-LABEL: stack_arg_gep:435; SLOW:         .functype stack_arg_gep (i32) -> (i32)436; SLOW-NEXT:  # %bb.0:437; SLOW-NEXT:    global.get $push2=, __stack_pointer438; SLOW-NEXT:    i32.const $push3=, 16439; SLOW-NEXT:    i32.sub $push9=, $pop2, $pop3440; SLOW-NEXT:    local.tee $push8=, $2=, $pop9441; SLOW-NEXT:    global.set __stack_pointer, $pop8442; SLOW-NEXT:    i32.const $push6=, 8443; SLOW-NEXT:    i32.add $push7=, $2, $pop6444; SLOW-NEXT:    i32.const $push0=, 4445; SLOW-NEXT:    i32.or $push1=, $pop7, $pop0446; SLOW-NEXT:    call $1=, stack_arg_gep, $pop1447; SLOW-NEXT:    i32.const $push4=, 16448; SLOW-NEXT:    i32.add $push5=, $2, $pop4449; SLOW-NEXT:    global.set __stack_pointer, $pop5450; SLOW-NEXT:    return $1451;452; FAST-LABEL: stack_arg_gep:453; FAST:         .functype stack_arg_gep (i32) -> (i32)454; FAST-NEXT:  # %bb.0:455; FAST-NEXT:    global.get $push3=, __stack_pointer456; FAST-NEXT:    i32.const $push4=, 16457; FAST-NEXT:    i32.sub $push10=, $pop3, $pop4458; FAST-NEXT:    local.tee $push9=, $2=, $pop10459; FAST-NEXT:    global.set __stack_pointer, $pop9460; FAST-NEXT:    i32.const $push7=, 8461; FAST-NEXT:    i32.add $push8=, $2, $pop7462; FAST-NEXT:    local.copy $push0=, $pop8463; FAST-NEXT:    i32.const $push1=, 4464; FAST-NEXT:    i32.add $push2=, $pop0, $pop1465; FAST-NEXT:    call $1=, stack_arg_gep, $pop2466; FAST-NEXT:    i32.const $push5=, 16467; FAST-NEXT:    i32.add $push6=, $2, $pop5468; FAST-NEXT:    global.set __stack_pointer, $pop6469; FAST-NEXT:    return $1470  %a = alloca { i32, i32 }471  %p = getelementptr { i32, i32 }, ptr %a, i32 0, i32 1472  %v = tail call i32 @stack_arg_gep(ptr %p)473  ret i32 %v474}475 476define i32 @stack_arg_cast(i32 %x) {477; SLOW-LABEL: stack_arg_cast:478; SLOW:         .functype stack_arg_cast (i32) -> (i32)479; SLOW-NEXT:  # %bb.0:480; SLOW-NEXT:    global.get $push0=, __stack_pointer481; SLOW-NEXT:    i32.const $push1=, 256482; SLOW-NEXT:    i32.sub $push5=, $pop0, $pop1483; SLOW-NEXT:    local.tee $push4=, $1=, $pop5484; SLOW-NEXT:    global.set __stack_pointer, $pop4485; SLOW-NEXT:    i32.const $push2=, 256486; SLOW-NEXT:    i32.add $push3=, $1, $pop2487; SLOW-NEXT:    global.set __stack_pointer, $pop3488; SLOW-NEXT:    return_call stack_arg_cast, $1489;490; FAST-LABEL: stack_arg_cast:491; FAST:         .functype stack_arg_cast (i32) -> (i32)492; FAST-NEXT:  # %bb.0:493; FAST-NEXT:    global.get $push1=, __stack_pointer494; FAST-NEXT:    i32.const $push2=, 256495; FAST-NEXT:    i32.sub $push6=, $pop1, $pop2496; FAST-NEXT:    local.tee $push5=, $2=, $pop6497; FAST-NEXT:    global.set __stack_pointer, $pop5498; FAST-NEXT:    local.copy $push0=, $2499; FAST-NEXT:    call $1=, stack_arg_cast, $pop0500; FAST-NEXT:    i32.const $push3=, 256501; FAST-NEXT:    i32.add $push4=, $2, $pop3502; FAST-NEXT:    global.set __stack_pointer, $pop4503; FAST-NEXT:    return $1504  %a = alloca [64 x i32]505  %i = ptrtoint ptr %a to i32506  %v = tail call i32 @stack_arg_cast(i32 %i)507  ret i32 %v508}509 510; Checks that epilogues are inserted after return calls.511define i32 @direct_epilogue() {512; CHECK-LABEL: direct_epilogue:513; CHECK:         .functype direct_epilogue () -> (i32)514; CHECK-NEXT:  # %bb.0:515; CHECK-NEXT:    global.get $push0=, __stack_pointer516; CHECK-NEXT:    i32.const $push1=, 256517; CHECK-NEXT:    i32.sub $push5=, $pop0, $pop1518; CHECK-NEXT:    local.tee $push4=, $0=, $pop5519; CHECK-NEXT:    global.set __stack_pointer, $pop4520; CHECK-NEXT:    i32.const $push2=, 256521; CHECK-NEXT:    i32.add $push3=, $0, $pop2522; CHECK-NEXT:    global.set __stack_pointer, $pop3523; CHECK-NEXT:    return_call direct_epilogue524  %a = alloca [64 x i32]525  %v = musttail call i32 @direct_epilogue()526  ret i32 %v527}528 529define i32 @indirect_epilogue(ptr %p) {530; CHECK-LABEL: indirect_epilogue:531; CHECK:         .functype indirect_epilogue (i32) -> (i32)532; CHECK-NEXT:  # %bb.0:533; CHECK-NEXT:    global.get $push0=, __stack_pointer534; CHECK-NEXT:    i32.const $push1=, 256535; CHECK-NEXT:    i32.sub $push5=, $pop0, $pop1536; CHECK-NEXT:    local.tee $push4=, $1=, $pop5537; CHECK-NEXT:    global.set __stack_pointer, $pop4538; CHECK-NEXT:    i32.const $push2=, 256539; CHECK-NEXT:    i32.add $push3=, $1, $pop2540; CHECK-NEXT:    global.set __stack_pointer, $pop3541; CHECK-NEXT:    return_call_indirect , $0, $0542  %a = alloca [64 x i32]543  %v = musttail call i32 %p(ptr %p)544  ret i32 %v545}546 547; Check that the signatures generated for external indirectly548; return-called functions include the proper return types549 550; YAML-LABEL: - Index:           8551; YAML-NEXT:    ParamTypes:552; YAML-NEXT:      - I32553; YAML-NEXT:      - F32554; YAML-NEXT:      - I64555; YAML-NEXT:      - F64556; YAML-NEXT:    ReturnTypes:557; YAML-NEXT:      - I32558define i32 @unique_caller(ptr %p) {559; SLOW-LABEL: unique_caller:560; SLOW:         .functype unique_caller (i32) -> (i32)561; SLOW-NEXT:  # %bb.0:562; SLOW-NEXT:    i32.const $push4=, 0563; SLOW-NEXT:    f32.const $push3=, 0x0p0564; SLOW-NEXT:    i64.const $push2=, 0565; SLOW-NEXT:    f64.const $push1=, 0x0p0566; SLOW-NEXT:    i32.load $push0=, 0($0)567; SLOW-NEXT:    return_call_indirect , $pop4, $pop3, $pop2, $pop1, $pop0568;569; FAST-LABEL: unique_caller:570; FAST:         .functype unique_caller (i32) -> (i32)571; FAST-NEXT:  # %bb.0:572; FAST-NEXT:    i32.const $push1=, 0573; FAST-NEXT:    i32.const $push7=, 0574; FAST-NEXT:    f32.convert_i32_s $push2=, $pop7575; FAST-NEXT:    i64.const $push3=, 0576; FAST-NEXT:    i32.const $push6=, 0577; FAST-NEXT:    f64.convert_i32_s $push4=, $pop6578; FAST-NEXT:    i32.load $push5=, 0($0)579; FAST-NEXT:    call_indirect $push0=, $pop1, $pop2, $pop3, $pop4, $pop5 # Invalid depth argument!580; FAST-NEXT:    return $pop0581  %f = load ptr, ptr %p582  %v = tail call i32 %f(i32 0, float 0., i64 0, double 0.)583  ret i32 %v584}585 586; CHECK-LABEL: .section .custom_section.target_features587; CHECK-NEXT: .int8 1588; CHECK-NEXT: .int8 43589; CHECK-NEXT: .int8 9590; CHECK-NEXT: .ascii "tail-call"591