diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp --- a/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp @@ -687,72 +687,72 @@ Params.push_back(PtrTy); break; case i64_i64_func_f32: -#if 0 // TODO: Enable this when wasm gets multiple-return-value support. - Rets.push_back(wasm::ValType::I64); - Rets.push_back(wasm::ValType::I64); -#else - Params.push_back(PtrTy); -#endif + if (Subtarget.hasMultivalue()) { + Rets.push_back(wasm::ValType::I64); + Rets.push_back(wasm::ValType::I64); + } else { + Params.push_back(PtrTy); + } Params.push_back(wasm::ValType::F32); break; case i64_i64_func_f64: -#if 0 // TODO: Enable this when wasm gets multiple-return-value support. - Rets.push_back(wasm::ValType::I64); - Rets.push_back(wasm::ValType::I64); -#else - Params.push_back(PtrTy); -#endif + if (Subtarget.hasMultivalue()) { + Rets.push_back(wasm::ValType::I64); + Rets.push_back(wasm::ValType::I64); + } else { + Params.push_back(PtrTy); + } Params.push_back(wasm::ValType::F64); break; case i16_i16_func_i16_i16: -#if 0 // TODO: Enable this when wasm gets multiple-return-value support. - Rets.push_back(wasm::ValType::I32); - Rets.push_back(wasm::ValType::I32); -#else - Params.push_back(PtrTy); -#endif + if (Subtarget.hasMultivalue()) { + Rets.push_back(wasm::ValType::I32); + Rets.push_back(wasm::ValType::I32); + } else { + Params.push_back(PtrTy); + } Params.push_back(wasm::ValType::I32); Params.push_back(wasm::ValType::I32); break; case i32_i32_func_i32_i32: -#if 0 // TODO: Enable this when wasm gets multiple-return-value support. - Rets.push_back(wasm::ValType::I32); - Rets.push_back(wasm::ValType::I32); -#else - Params.push_back(PtrTy); -#endif + if (Subtarget.hasMultivalue()) { + Rets.push_back(wasm::ValType::I32); + Rets.push_back(wasm::ValType::I32); + } else { + Params.push_back(PtrTy); + } Params.push_back(wasm::ValType::I32); Params.push_back(wasm::ValType::I32); break; case i64_i64_func_i64_i64: -#if 0 // TODO: Enable this when wasm gets multiple-return-value support. - Rets.push_back(wasm::ValType::I64); - Rets.push_back(wasm::ValType::I64); -#else - Params.push_back(PtrTy); -#endif + if (Subtarget.hasMultivalue()) { + Rets.push_back(wasm::ValType::I64); + Rets.push_back(wasm::ValType::I64); + } else { + Params.push_back(PtrTy); + } Params.push_back(wasm::ValType::I64); Params.push_back(wasm::ValType::I64); break; case i64_i64_func_i64_i64_i64_i64: -#if 0 // TODO: Enable this when wasm gets multiple-return-value support. - Rets.push_back(wasm::ValType::I64); - Rets.push_back(wasm::ValType::I64); -#else - Params.push_back(PtrTy); -#endif + if (Subtarget.hasMultivalue()) { + Rets.push_back(wasm::ValType::I64); + Rets.push_back(wasm::ValType::I64); + } else { + Params.push_back(PtrTy); + } Params.push_back(wasm::ValType::I64); Params.push_back(wasm::ValType::I64); Params.push_back(wasm::ValType::I64); Params.push_back(wasm::ValType::I64); break; case i64_i64_func_i64_i64_i64_i64_iPTR: -#if 0 // TODO: Enable this when wasm gets multiple-return-value support. - Rets.push_back(wasm::ValType::I64); - Rets.push_back(wasm::ValType::I64); -#else - Params.push_back(PtrTy); -#endif + if (Subtarget.hasMultivalue()) { + Rets.push_back(wasm::ValType::I64); + Rets.push_back(wasm::ValType::I64); + } else { + Params.push_back(PtrTy); + } Params.push_back(wasm::ValType::I64); Params.push_back(wasm::ValType::I64); Params.push_back(wasm::ValType::I64); @@ -760,28 +760,28 @@ Params.push_back(PtrTy); break; case i64_i64_i64_i64_func_i64_i64_i64_i64: -#if 0 // TODO: Enable this when wasm gets multiple-return-value support. - Rets.push_back(wasm::ValType::I64); - Rets.push_back(wasm::ValType::I64); - Rets.push_back(wasm::ValType::I64); - Rets.push_back(wasm::ValType::I64); -#else - Params.push_back(PtrTy); -#endif + if (Subtarget.hasMultivalue()) { + Rets.push_back(wasm::ValType::I64); + Rets.push_back(wasm::ValType::I64); + Rets.push_back(wasm::ValType::I64); + Rets.push_back(wasm::ValType::I64); + } else { + Params.push_back(PtrTy); + } Params.push_back(wasm::ValType::I64); Params.push_back(wasm::ValType::I64); Params.push_back(wasm::ValType::I64); Params.push_back(wasm::ValType::I64); break; case i64_i64_func_i64_i64_i32: -#if 0 // TODO: Enable this when wasm gets multiple-return-value support. - Rets.push_back(wasm::ValType::I64); - Rets.push_back(wasm::ValType::I64); - Rets.push_back(wasm::ValType::I64); - Rets.push_back(wasm::ValType::I64); -#else - Params.push_back(PtrTy); -#endif + if (Subtarget.hasMultivalue()) { + Rets.push_back(wasm::ValType::I64); + Rets.push_back(wasm::ValType::I64); + Rets.push_back(wasm::ValType::I64); + Rets.push_back(wasm::ValType::I64); + } else { + Params.push_back(PtrTy); + } Params.push_back(wasm::ValType::I64); Params.push_back(wasm::ValType::I64); Params.push_back(wasm::ValType::I32); @@ -904,8 +904,8 @@ auto Val = Map.find(Name); #ifndef NDEBUG if (Val == Map.end()) { - auto message = std::string("unexpected runtime library name: ") + - std::string(Name); + auto message = + std::string("unexpected runtime library name: ") + std::string(Name); llvm_unreachable(message.c_str()); } #endif diff --git a/llvm/test/CodeGen/WebAssembly/multivalue_libcall.ll b/llvm/test/CodeGen/WebAssembly/multivalue_libcall.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/multivalue_libcall.ll @@ -0,0 +1,61 @@ +; RUN: llc < %s -asm-verbose=false -verify-machineinstrs -mcpu=mvp -mattr=+multivalue | FileCheck %s --check-prefix=MULTIVALUE +; RUN: llc < %s -asm-verbose=false -verify-machineinstrs -mcpu=mvp | FileCheck %s --check-prefix=NO_MULTIVALUE + +; Test libcall signature when multivalue enabled and disabled + +target triple = "wasm32-unknown-unknown" + +@c = global i128 0, align 16 + +; CHECK-LABEL: multivalue_sdiv: +define void @multivalue_sdiv(i128 noundef %a, i128 noundef %b) #0 { +; NO_MULTIVALUE: .local i32 +; NO_MULTIVALUE: global.get __stack_pointer +; NO_MULTIVALUE: i32.const 16 +; NO_MULTIVALUE: i32.sub +; NO_MULTIVALUE: local.tee 4 +; NO_MULTIVALUE: global.set __stack_pointer + +; NO_MULTIVALUE: local.get 4 + +; NO_MULTIVALUE: local.get 0 +; NO_MULTIVALUE: local.get 1 +; NO_MULTIVALUE: local.get 2 +; NO_MULTIVALUE: local.get 3 +; NO_MULTIVALUE: call __divti3 +; MULTIVALUE: local.get 0 +; MULTIVALUE: local.get 1 +; MULTIVALUE: local.get 2 +; MULTIVALUE: local.get 3 +; MULTIVALUE: call __divti3 + %div = sdiv i128 %a, %b + + +; NO_MULTIVALUE: i32.const c +; NO_MULTIVALUE: local.get 4 +; NO_MULTIVALUE: i32.const 8 +; NO_MULTIVALUE: i32.add +; NO_MULTIVALUE: i64.load 0 +; NO_MULTIVALUE: i64.store 8 +; NO_MULTIVALUE: i32.const 0 +; NO_MULTIVALUE: local.get 4 +; NO_MULTIVALUE: i64.load 0 +; NO_MULTIVALUE: i64.store c + +; MULTIVALUE: local.set 2 +; MULTIVALUE: local.set 3 +; MULTIVALUE: i32.const c +; MULTIVALUE: local.get 2 +; MULTIVALUE: i64.store 8 +; MULTIVALUE: i32.const 0 +; MULTIVALUE: local.get 3 +; MULTIVALUE: i64.store c + store i128 %div, ptr @c, align 16 + +; NO_MULTIVALUE: local.get 4 +; NO_MULTIVALUE: i32.const 16 +; NO_MULTIVALUE: i32.add +; NO_MULTIVALUE: global.set __stack_pointer + + ret void +}