[Webassembly][multivalue] update libcall signature when multivalue feature enabled
authorCongcong Cai <congcong.ca.cai@bmw.com>
Tue, 21 Mar 2023 04:04:41 +0000 (12:04 +0800)
committerCongcong Cai <congcong.ca.cai@bmw.com>
Tue, 21 Mar 2023 04:10:51 +0000 (12:10 +0800)
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

llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp
llvm/test/CodeGen/WebAssembly/multivalue_libcall.ll [new file with mode: 0644]

index 72a53b6..c48a13e 100644 (file)
@@ -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 (file)
index 0000000..270fdae
--- /dev/null
@@ -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
+}