From d9661d79f46601698b21c01788c244e6294f5eb1 Mon Sep 17 00:00:00 2001 From: Congcong Cai Date: Tue, 21 Mar 2023 12:04:41 +0800 Subject: [PATCH] [Webassembly][multivalue] update libcall signature when multivalue feature enabled fixed: #59095 Update libcall signatures to use multivalue return rather than returning via a pointer when the multivalue features is enabled in the WebAssembly backend. Reviewed By: tlively Differential Revision: https://reviews.llvm.org/D146271 --- .../WebAssemblyRuntimeLibcallSignatures.cpp | 120 +++++++++--------- .../CodeGen/WebAssembly/multivalue_libcall.ll | 63 +++++++++ 2 files changed, 123 insertions(+), 60 deletions(-) create mode 100644 llvm/test/CodeGen/WebAssembly/multivalue_libcall.ll diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp index 72a53b6c388ea4..c48a13ef7eb59a 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp @@ -687,72 +687,72 @@ void llvm::getLibcallSignature(const WebAssemblySubtarget &Subtarget, 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 @@ void llvm::getLibcallSignature(const WebAssemblySubtarget &Subtarget, 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 @@ void llvm::getLibcallSignature(const WebAssemblySubtarget &Subtarget, 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 index 00000000000000..270fdae3366783 --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/multivalue_libcall.ll @@ -0,0 +1,63 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2 +; RUN: llc < %s -verify-machineinstrs -mcpu=mvp -mattr=+multivalue | FileCheck %s --check-prefix=MULTIVALUE +; RUN: llc < %s -verify-machineinstrs -mcpu=mvp | FileCheck %s --check-prefix=NO_MULTIVALUE + +; Test libcall signatures when multivalue is enabled and disabled + +target triple = "wasm32-unknown-unknown" + +@c = global i128 0, align 16 + +define void @multivalue_sdiv(i128 noundef %a, i128 noundef %b) #0 { +; MULTIVALUE-LABEL: multivalue_sdiv: +; MULTIVALUE: .functype multivalue_sdiv (i64, i64, i64, i64) -> () +; MULTIVALUE-NEXT: # %bb.0: +; MULTIVALUE-NEXT: local.get 0 +; MULTIVALUE-NEXT: local.get 1 +; MULTIVALUE-NEXT: local.get 2 +; MULTIVALUE-NEXT: local.get 3 +; MULTIVALUE-NEXT: call __divti3 +; MULTIVALUE-NEXT: local.set 2 +; MULTIVALUE-NEXT: local.set 3 +; MULTIVALUE-NEXT: i32.const c +; MULTIVALUE-NEXT: local.get 2 +; MULTIVALUE-NEXT: i64.store 8 +; MULTIVALUE-NEXT: i32.const 0 +; MULTIVALUE-NEXT: local.get 3 +; MULTIVALUE-NEXT: i64.store c +; MULTIVALUE-NEXT: # fallthrough-return +; +; NO_MULTIVALUE-LABEL: multivalue_sdiv: +; NO_MULTIVALUE: .functype multivalue_sdiv (i64, i64, i64, i64) -> () +; NO_MULTIVALUE-NEXT: .local i32 +; NO_MULTIVALUE-NEXT: # %bb.0: +; NO_MULTIVALUE-NEXT: global.get __stack_pointer +; NO_MULTIVALUE-NEXT: i32.const 16 +; NO_MULTIVALUE-NEXT: i32.sub +; NO_MULTIVALUE-NEXT: local.tee 4 +; NO_MULTIVALUE-NEXT: global.set __stack_pointer +; NO_MULTIVALUE-NEXT: local.get 4 +; NO_MULTIVALUE-NEXT: local.get 0 +; NO_MULTIVALUE-NEXT: local.get 1 +; NO_MULTIVALUE-NEXT: local.get 2 +; NO_MULTIVALUE-NEXT: local.get 3 +; NO_MULTIVALUE-NEXT: call __divti3 +; NO_MULTIVALUE-NEXT: i32.const c +; NO_MULTIVALUE-NEXT: local.get 4 +; NO_MULTIVALUE-NEXT: i32.const 8 +; NO_MULTIVALUE-NEXT: i32.add +; NO_MULTIVALUE-NEXT: i64.load 0 +; NO_MULTIVALUE-NEXT: i64.store 8 +; NO_MULTIVALUE-NEXT: i32.const 0 +; NO_MULTIVALUE-NEXT: local.get 4 +; NO_MULTIVALUE-NEXT: i64.load 0 +; NO_MULTIVALUE-NEXT: i64.store c +; NO_MULTIVALUE-NEXT: local.get 4 +; NO_MULTIVALUE-NEXT: i32.const 16 +; NO_MULTIVALUE-NEXT: i32.add +; NO_MULTIVALUE-NEXT: global.set __stack_pointer +; NO_MULTIVALUE-NEXT: # fallthrough-return + %div = sdiv i128 %a, %b + store i128 %div, ptr @c, align 16 + ret void +}