314 lines · plain
1; RUN: llc < %s -asm-verbose=false -verify-machineinstrs -mcpu=mvp -mattr=+multivalue,+tail-call -target-abi=experimental-mv | FileCheck %s2; RUN: llc < %s -asm-verbose=false -verify-machineinstrs -mcpu=mvp -mattr=+reference-types,+multivalue,+tail-call -target-abi=experimental-mv | FileCheck --check-prefix REF %s3; RUN: llc < %s -asm-verbose=false -verify-machineinstrs -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mcpu=mvp -mattr=+multivalue,+tail-call -target-abi=experimental-mv | FileCheck %s --check-prefix REGS4; RUN: llc < %s --filetype=obj -mcpu=mvp -mattr=+multivalue,+tail-call -target-abi=experimental-mv | obj2yaml | FileCheck %s --check-prefix OBJ5; RUN: llc < %s -asm-verbose=false -verify-machineinstrs -mcpu=mvp -mattr=+multivalue,+tail-call | FileCheck %s --check-prefix NO-MULTIVALUE6 7; Test that the multivalue calls, returns, function types, and block8; types work as expected.9 10target triple = "wasm32-unknown-unknown"11 12%pair = type { i32, i64 }13%rpair = type { i64, i32 }14 15declare void @use_i32(i32)16declare void @use_i64(i64)17 18; CHECK-LABEL: pair_const:19; CHECK-NEXT: .functype pair_const () -> (i32, i64)20; CHECK-NEXT: i32.const 42{{$}}21; CHECK-NEXT: i64.const 42{{$}}22; CHECK-NEXT: end_function{{$}}23; NO-MULTIVALUE-NOT: .functype pair_const () -> (i32, i64)24define %pair @pair_const() {25 ret %pair { i32 42, i64 42 }26}27 28; CHECK-LABEL: pair_ident:29; CHECK-NEXT: .functype pair_ident (i32, i64) -> (i32, i64)30; CHECK-NEXT: local.get 0{{$}}31; CHECK-NEXT: local.get 1{{$}}32; CHECK-NEXT: end_function{{$}}33define %pair @pair_ident(%pair %p) {34 ret %pair %p35}36 37; CHECK-LABEL: pair_call:38; CHECK-NEXT: .functype pair_call () -> ()39; CHECK-NEXT: call pair_const{{$}}40; CHECK-NEXT: drop{{$}}41; CHECK-NEXT: drop{{$}}42; CHECK-NEXT: end_function{{$}}43; REGS: call $drop=, $drop=, pair_const{{$}}44define void @pair_call() {45 %p = call %pair @pair_const()46 ret void47}48 49; CHECK-LABEL: pair_call_return:50; CHECK-NEXT: .functype pair_call_return () -> (i32, i64)51; CHECK-NEXT: call pair_const{{$}}52; CHECK-NEXT: end_function{{$}}53; REGS: call $push{{[0-9]+}}=, $push{{[0-9]+}}=, pair_const{{$}}54define %pair @pair_call_return() {55 %p = call %pair @pair_const()56 ret %pair %p57}58 59; CHECK-LABEL: pair_call_indirect:60; CHECK-NEXT: .functype pair_call_indirect (i32) -> (i32, i64)61; CHECK-NEXT: local.get 0{{$}}62; CHECK-NEXT: call_indirect () -> (i32, i64){{$}}63; REF: call_indirect __indirect_function_table, () -> (i32, i64){{$}}64; CHECK-NEXT: end_function{{$}}65; REGS: call_indirect $push{{[0-9]+}}=, $push{{[0-9]+}}=, $0{{$}}66define %pair @pair_call_indirect(ptr %f) {67 %p = call %pair %f()68 ret %pair %p69}70 71; CHECK-LABEL: pair_tail_call:72; CHECK-NEXT: .functype pair_tail_call () -> (i32, i64)73; CHECK-NEXT: return_call pair_const{{$}}74; CHECK-NEXT: end_function{{$}}75; REGS: return_call pair_const{{$}}76define %pair @pair_tail_call() {77 %p = musttail call %pair @pair_const()78 ret %pair %p79}80 81; CHECK-LABEL: pair_call_return_first:82; CHECK-NEXT: .functype pair_call_return_first () -> (i32)83; CHECK-NEXT: call pair_const{{$}}84; CHECK-NEXT: drop{{$}}85; CHECK-NEXT: end_function{{$}}86; REGS: call $push{{[0-9]+}}=, $drop=, pair_const{{$}}87define i32 @pair_call_return_first() {88 %p = call %pair @pair_const()89 %v = extractvalue %pair %p, 090 ret i32 %v91}92 93; CHECK-LABEL: pair_call_return_second:94; CHECK-NEXT: .functype pair_call_return_second () -> (i64)95; CHECK-NEXT: .local i64{{$}}96; CHECK-NEXT: call pair_const{{$}}97; CHECK-NEXT: local.set 0{{$}}98; CHECK-NEXT: drop{{$}}99; CHECK-NEXT: local.get 0{{$}}100; CHECK-NEXT: end_function{{$}}101; REGS: call $drop=, $0=, pair_const{{$}}102define i64 @pair_call_return_second() {103 %p = call %pair @pair_const()104 %v = extractvalue %pair %p, 1105 ret i64 %v106}107 108; CHECK-LABEL: pair_call_use_first:109; CHECK-NEXT: .functype pair_call_use_first () -> ()110; CHECK-NEXT: call pair_const{{$}}111; CHECK-NEXT: drop{{$}}112; CHECK-NEXT: call use_i32{{$}}113; CHECK-NEXT: end_function{{$}}114; REGS: call $push{{[0-9]+}}=, $drop=, pair_const{{$}}115define void @pair_call_use_first() {116 %p = call %pair @pair_const()117 %v = extractvalue %pair %p, 0118 call void @use_i32(i32 %v)119 ret void120}121 122; CHECK-LABEL: pair_call_use_second:123; CHECK-NEXT: .functype pair_call_use_second () -> ()124; CHECK-NEXT: .local i64125; CHECK-NEXT: call pair_const{{$}}126; CHECK-NEXT: local.set 0{{$}}127; CHECK-NEXT: drop{{$}}128; CHECK-NEXT: local.get 0{{$}}129; CHECK-NEXT: call use_i64{{$}}130; CHECK-NEXT: end_function{{$}}131; REGS: call $drop=, $0=, pair_const{{$}}132define void @pair_call_use_second() {133 %p = call %pair @pair_const()134 %v = extractvalue %pair %p, 1135 call void @use_i64(i64 %v)136 ret void137}138 139; CHECK-LABEL: pair_call_use_first_return_second:140; CHECK-NEXT: .functype pair_call_use_first_return_second () -> (i64)141; CHECK-NEXT: .local i64{{$}}142; CHECK-NEXT: call pair_const{{$}}143; CHECK-NEXT: local.set 0{{$}}144; CHECK-NEXT: call use_i32{{$}}145; CHECK-NEXT: local.get 0{{$}}146; CHECK-NEXT: end_function{{$}}147; REGS: call $push{{[0-9]+}}=, $0=, pair_const{{$}}148define i64 @pair_call_use_first_return_second() {149 %p = call %pair @pair_const()150 %v = extractvalue %pair %p, 0151 call void @use_i32(i32 %v)152 %r = extractvalue %pair %p, 1153 ret i64 %r154}155 156; CHECK-LABEL: pair_call_use_second_return_first:157; CHECK-NEXT: .functype pair_call_use_second_return_first () -> (i32)158; CHECK-NEXT: .local i32, i64{{$}}159; CHECK-NEXT: call pair_const{{$}}160; CHECK-NEXT: local.set 1{{$}}161; CHECK-NEXT: local.set 0{{$}}162; CHECK-NEXT: local.get 1{{$}}163; CHECK-NEXT: call use_i64{{$}}164; CHECK-NEXT: local.get 0{{$}}165; CHECK-NEXT: end_function{{$}}166; REGS: call $0=, $1=, pair_const{{$}}167define i32 @pair_call_use_second_return_first() {168 %p = call %pair @pair_const()169 %v = extractvalue %pair %p, 1170 call void @use_i64(i64 %v)171 %r = extractvalue %pair %p, 0172 ret i32 %r173}174 175; CHECK-LABEL: pair_pass_through:176; CHECK-NEXT: .functype pair_pass_through (i32, i64) -> (i32, i64)177; CHECK-NEXT: local.get 0178; CHECK-NEXT: local.get 1179; CHECK-NEXT: call pair_ident{{$}}180; CHECK-NEXT: end_function{{$}}181; REGS: call $push{{[0-9]+}}=, $push{{[0-9]+}}=, pair_ident, $0, $1{{$}}182define %pair @pair_pass_through(%pair %p) {183 %r = call %pair @pair_ident(%pair %p)184 ret %pair %r185}186 187; CHECK-LABEL: pair_swap:188; CHECK-NEXT: .functype pair_swap (i32, i64) -> (i64, i32)189; CHECK-NEXT: local.get 1{{$}}190; CHECK-NEXT: local.get 0{{$}}191; CHECK-NEXT: end_function{{$}}192define %rpair @pair_swap(%pair %p) {193 %first = extractvalue %pair %p, 0194 %second = extractvalue %pair %p, 1195 %r1 = insertvalue %rpair undef, i32 %first, 1196 %r2 = insertvalue %rpair %r1, i64 %second, 0197 ret %rpair %r2198}199 200; CHECK-LABEL: pair_call_swap:201; CHECK-NEXT: .functype pair_call_swap () -> (i64, i32)202; CHECK-NEXT: .local i32, i64{{$}}203; CHECK-NEXT: call pair_const{{$}}204; CHECK-NEXT: local.set 1{{$}}205; CHECK-NEXT: local.set 0{{$}}206; CHECK-NEXT: local.get 1{{$}}207; CHECK-NEXT: local.get 0{{$}}208; CHECK-NEXT: end_function{{$}}209; REGS: call $0=, $1=, pair_const{{$}}210define %rpair @pair_call_swap() {211 %p = call %pair @pair_const()212 %first = extractvalue %pair %p, 0213 %second = extractvalue %pair %p, 1214 %r1 = insertvalue %rpair undef, i32 %first, 1215 %r2 = insertvalue %rpair %r1, i64 %second, 0216 ret %rpair %r2217}218 219; CHECK-LABEL: pair_pass_through_swap:220; CHECK-NEXT: .functype pair_pass_through_swap (i32, i64) -> (i64, i32)221; CHECK-NEXT: local.get 0{{$}}222; CHECK-NEXT: local.get 1{{$}}223; CHECK-NEXT: call pair_ident{{$}}224; CHECK-NEXT: local.set 1{{$}}225; CHECK-NEXT: local.set 0{{$}}226; CHECK-NEXT: local.get 1{{$}}227; CHECK-NEXT: local.get 0{{$}}228; CHECK-NEXT: end_function{{$}}229; REGS: call $0=, $1=, pair_ident, $0, $1{{$}}230define %rpair @pair_pass_through_swap(%pair %p) {231 %p1 = call %pair @pair_ident(%pair %p)232 %first = extractvalue %pair %p1, 0233 %second = extractvalue %pair %p1, 1234 %r1 = insertvalue %rpair undef, i32 %first, 1235 %r2 = insertvalue %rpair %r1, i64 %second, 0236 ret %rpair %r2237}238 239; CHECK-LABEL: minimal_loop:240; CHECK-NEXT: .functype minimal_loop (i32) -> (i32, i64)241; CHECK-NEXT: .LBB{{[0-9]+}}_1:242; CHECK-NEXT: loop () -> (i32, i64)243; CHECK-NEXT: br 0{{$}}244; CHECK-NEXT: .LBB{{[0-9]+}}_2:245; CHECK-NEXT: end_loop{{$}}246; CHECK-NEXT: end_function{{$}}247define %pair @minimal_loop(ptr %p) {248entry:249 br label %loop250loop:251 br label %loop252}253 254; CHECK-LABEL: .section .custom_section.target_features255; CHECK-NEXT: .int8 2256; CHECK-NEXT: .int8 43257; CHECK-NEXT: .int8 10258; CHECK-NEXT: .ascii "multivalue"259; CHECK-NEXT: .int8 43260; CHECK-NEXT: .int8 9261; CHECK-NEXT: .ascii "tail-call"262 263; OBJ-LABEL: - Type: TYPE264; OBJ-NEXT: Signatures:265; OBJ-NEXT: - Index: 0266; OBJ-NEXT: ParamTypes: []267; OBJ-NEXT: ReturnTypes:268; OBJ-NEXT: - I32269; OBJ-NEXT: - I64270; OBJ-NEXT: - Index: 1271; OBJ-NEXT: ParamTypes:272; OBJ-NEXT: - I32273; OBJ-NEXT: - I64274; OBJ-NEXT: ReturnTypes:275; OBJ-NEXT: - I32276; OBJ-NEXT: - I64277; OBJ-NEXT: - Index: 2278; OBJ-NEXT: ParamTypes: []279; OBJ-NEXT: ReturnTypes: []280; OBJ-NEXT: - Index: 3281; OBJ-NEXT: ParamTypes:282; OBJ-NEXT: - I32283; OBJ-NEXT: ReturnTypes:284; OBJ-NEXT: - I32285; OBJ-NEXT: - I64286; OBJ-NEXT: - Index: 4287; OBJ-NEXT: ParamTypes: []288; OBJ-NEXT: ReturnTypes:289; OBJ-NEXT: - I32290; OBJ-NEXT: - Index: 5291; OBJ-NEXT: ParamTypes: []292; OBJ-NEXT: ReturnTypes:293; OBJ-NEXT: - I64294; OBJ-NEXT: - Index: 6295; OBJ-NEXT: ParamTypes:296; OBJ-NEXT: - I32297; OBJ-NEXT: ReturnTypes: []298; OBJ-NEXT: - Index: 7299; OBJ-NEXT: ParamTypes:300; OBJ-NEXT: - I64301; OBJ-NEXT: ReturnTypes: []302; OBJ-NEXT: - Index: 8303; OBJ-NEXT: ParamTypes:304; OBJ-NEXT: - I32305; OBJ-NEXT: - I64306; OBJ-NEXT: ReturnTypes:307; OBJ-NEXT: - I64308; OBJ-NEXT: - I32309; OBJ-NEXT: - Index: 9310; OBJ-NEXT: ParamTypes: []311; OBJ-NEXT: ReturnTypes:312; OBJ-NEXT: - I64313; OBJ-NEXT: - I32314