[llvm] [WebAssembly][GlobalISel] CallLowering `lowerReturn` (PR #190247)

via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 2 12:57:05 PDT 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-globalisel

Author: Demetrius Kanios (QuantumSegfault)

<details>
<summary>Changes</summary>

Implements `WebAssemblyCallLowering::lowerReturn`

Split from #<!-- -->157161

---

Patch is 36.56 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/190247.diff


4 Files Affected:

- (modified) llvm/lib/Target/WebAssembly/GISel/WebAssemblyCallLowering.cpp (+139-25) 
- (added) llvm/test/CodeGen/WebAssembly/GlobalISel/irtranslator/ret-aggregates.ll (+265) 
- (added) llvm/test/CodeGen/WebAssembly/GlobalISel/irtranslator/ret-basics.ll (+153) 
- (added) llvm/test/CodeGen/WebAssembly/GlobalISel/irtranslator/ret-simd.ll (+90) 


``````````diff
diff --git a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyCallLowering.cpp b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyCallLowering.cpp
index 9450749a4f6ab..3009c2334273d 100644
--- a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyCallLowering.cpp
+++ b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyCallLowering.cpp
@@ -23,11 +23,13 @@
 #include "llvm/CodeGen/Analysis.h"
 #include "llvm/CodeGen/FunctionLoweringInfo.h"
 #include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
+#include "llvm/CodeGen/LowLevelTypeUtils.h"
 #include "llvm/CodeGen/MachineInstrBuilder.h"
 #include "llvm/CodeGen/RegisterBankInfo.h"
 #include "llvm/IR/DataLayout.h"
 #include "llvm/IR/DebugLoc.h"
 #include "llvm/IR/Value.h"
+#include "llvm/Support/ErrorHandling.h"
 
 #define DEBUG_TYPE "wasm-call-lowering"
 
@@ -48,6 +50,32 @@ static bool callingConvSupported(CallingConv::ID CallConv) {
          CallConv == CallingConv::Swift;
 }
 
+static unsigned extendOpFromFlags(ISD::ArgFlagsTy Flags) {
+  if (Flags.isSExt())
+    return TargetOpcode::G_SEXT;
+  if (Flags.isZExt())
+    return TargetOpcode::G_ZEXT;
+  return TargetOpcode::G_ANYEXT;
+}
+
+static LLT getLLTForWasmMVT(MVT Ty, const DataLayout &DL) {
+  if (Ty == MVT::externref) {
+    return LLT::pointer(
+        WebAssembly::WasmAddressSpace::WASM_ADDRESS_SPACE_EXTERNREF,
+        DL.getPointerSizeInBits(
+            WebAssembly::WasmAddressSpace::WASM_ADDRESS_SPACE_EXTERNREF));
+  }
+
+  if (Ty == MVT::funcref) {
+    return LLT::pointer(
+        WebAssembly::WasmAddressSpace::WASM_ADDRESS_SPACE_FUNCREF,
+        DL.getPointerSizeInBits(
+            WebAssembly::WasmAddressSpace::WASM_ADDRESS_SPACE_FUNCREF));
+  }
+
+  return llvm::getLLTForMVT(Ty);
+}
+
 WebAssemblyCallLowering::WebAssemblyCallLowering(
     const WebAssemblyTargetLowering &TLI)
     : CallLowering(&TLI) {}
@@ -65,13 +93,117 @@ bool WebAssemblyCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder,
                                           ArrayRef<Register> VRegs,
                                           FunctionLoweringInfo &FLI,
                                           Register SwiftErrorVReg) const {
-  if (!Val)
-    return true; // allow only void returns for now
+  MachineFunction &MF = MIRBuilder.getMF();
+  const WebAssemblySubtarget &Subtarget =
+      MF.getSubtarget<WebAssemblySubtarget>();
+  const RegisterBankInfo &RBI = *Subtarget.getRegBankInfo();
+  const Function &F = MF.getFunction();
+  MachineRegisterInfo &MRI = MF.getRegInfo();
+  const WebAssemblyTargetLowering &TLI = *getTLI<WebAssemblyTargetLowering>();
+  const DataLayout &DL = F.getDataLayout();
 
-  return false;
+  MachineInstrBuilder MIB = MIRBuilder.buildInstrNoInsert(WebAssembly::RETURN);
+
+  assert(((Val && !VRegs.empty()) || (!Val && VRegs.empty())) &&
+         "Return value without a vreg or vice versa");
+
+  if (Val) {
+    LLVMContext &Ctx = Val->getType()->getContext();
+
+    if (!FLI.CanLowerReturn) {
+      insertSRetStores(MIRBuilder, Val->getType(), VRegs, FLI.DemoteRegister);
+    } else {
+      SmallVector<EVT, 4> SplitEVTs;
+      ComputeValueVTs(TLI, DL, Val->getType(), SplitEVTs);
+      assert(VRegs.size() == SplitEVTs.size() &&
+             "For each split Type there should be exactly one VReg.");
+
+      SmallVector<ArgInfo, 8> SplitRets;
+      CallingConv::ID CallConv = F.getCallingConv();
+
+      unsigned RetIdx = 0;
+      for (EVT SplitEVT : SplitEVTs) {
+        Register CurVReg = VRegs[RetIdx];
+        ArgInfo CurRetInfo = ArgInfo{CurVReg, SplitEVT.getTypeForEVT(Ctx), 0};
+        setArgFlags(CurRetInfo, AttributeList::ReturnIndex, DL, F);
+
+        splitToValueTypes(CurRetInfo, SplitRets, DL, CallConv);
+        ++RetIdx;
+      }
+
+      for (ArgInfo &Ret : SplitRets) {
+        const EVT OrigVT = TLI.getValueType(DL, Ret.Ty);
+        const MVT NewVT =
+            TLI.getRegisterTypeForCallingConv(Ctx, CallConv, OrigVT);
+        const LLT OrigLLT =
+            getLLTForType(*OrigVT.getTypeForEVT(F.getContext()), DL);
+        const LLT NewLLT = getLLTForWasmMVT(NewVT, DL);
+
+        const TargetRegisterClass &NewRegClass = *TLI.getRegClassFor(NewVT);
+
+        // If we need to split the type over multiple regs, check it's a
+        // scenario we currently support.
+        const unsigned NumParts =
+            TLI.getNumRegistersForCallingConv(Ctx, CallConv, OrigVT);
+
+        const ISD::ArgFlagsTy OrigFlags = Ret.Flags[0];
+        Ret.Flags.clear();
+
+        for (unsigned Part = 0; Part < NumParts; ++Part) {
+          ISD::ArgFlagsTy Flags = OrigFlags;
+
+          if (Part == 0) {
+            Flags.setSplit();
+          } else {
+            Flags.setOrigAlign(Align(1));
+            if (Part == NumParts - 1)
+              Flags.setSplitEnd();
+          }
+
+          Ret.Flags.push_back(Flags);
+        }
+
+        Ret.OrigRegs.assign(Ret.Regs.begin(), Ret.Regs.end());
+        if (NumParts != 1 || OrigLLT != NewLLT) {
+          // If we can't directly assign the register, we need one or more
+          // intermediate values.
+          Ret.Regs.resize(NumParts);
+
+          // For each split register, create and assign a vreg that will store
+          // the incoming component of the larger value. These will later be
+          // merged to form the final vreg.
+          for (unsigned Part = 0; Part < NumParts; ++Part) {
+            Register NewOutReg = MRI.createGenericVirtualRegister(NewLLT);
+
+            if (!RBI.constrainGenericRegister(NewOutReg, NewRegClass, MRI))
+              reportFatalInternalError(
+                  "Couldn't constrain brand-new register?");
+
+            MIB.addUse(NewOutReg);
+
+            Ret.Regs[Part] = NewOutReg;
+          }
+
+          buildCopyToRegs(MIRBuilder, Ret.Regs, Ret.OrigRegs[0], OrigLLT,
+                          NewLLT, extendOpFromFlags(Ret.Flags[0]));
+        } else {
+          MIB.addUse(Ret.Regs[0]);
+        }
+      }
+    }
+  }
+
+  if (SwiftErrorVReg) {
+    reportFatalInternalError(
+        "Wasm does not `supportSwiftError`, yet SwiftErrorVReg is "
+        "improperly valid.");
+  }
+
+  MIRBuilder.insertInstr(MIB);
+  return true;
 }
 
-static unsigned getWASMArgumentOpcode(MVT ArgType) {
+static unsigned getWasmArgumentOpcode(MVT ArgType) {
   switch (ArgType.SimpleTy) {
   case MVT::i32:
     return WebAssembly::ARGUMENT_i32;
@@ -106,25 +238,7 @@ static unsigned getWASMArgumentOpcode(MVT ArgType) {
   default:
     break;
   }
-  llvm_unreachable("Found unexpected type for WASM argument");
-}
-
-static LLT getLLTForWasmMVT(MVT Ty, const DataLayout &DL) {
-  if (Ty == MVT::externref) {
-    return LLT::pointer(
-        WebAssembly::WasmAddressSpace::WASM_ADDRESS_SPACE_EXTERNREF,
-        DL.getPointerSizeInBits(
-            WebAssembly::WasmAddressSpace::WASM_ADDRESS_SPACE_EXTERNREF));
-  }
-
-  if (Ty == MVT::funcref) {
-    return LLT::pointer(
-        WebAssembly::WasmAddressSpace::WASM_ADDRESS_SPACE_FUNCREF,
-        DL.getPointerSizeInBits(
-            WebAssembly::WasmAddressSpace::WASM_ADDRESS_SPACE_FUNCREF));
-  }
-
-  return llvm::getLLTForMVT(Ty);
+  llvm_unreachable("Found unexpected type for Wasm argument");
 }
 
 bool WebAssemblyCallLowering::lowerFormalArguments(
@@ -221,7 +335,7 @@ bool WebAssemblyCallLowering::lowerFormalArguments(
 
     for (unsigned Part = 0; Part < NumParts; ++Part) {
       MachineInstrBuilder ArgInst =
-          MIRBuilder.buildInstr(getWASMArgumentOpcode(NewVT))
+          MIRBuilder.buildInstr(getWasmArgumentOpcode(NewVT))
               .addDef(Arg.Regs[Part])
               .addImm(FinalArgIdx);
 
@@ -262,7 +376,7 @@ bool WebAssemblyCallLowering::lowerFormalArguments(
     MFI->setVarargBufferVreg(VarargVreg);
 
     MachineInstrBuilder ArgInst =
-        MIRBuilder.buildInstr(getWASMArgumentOpcode(PtrVT))
+        MIRBuilder.buildInstr(getWasmArgumentOpcode(PtrVT))
             .addDef(VarargVreg)
             .addImm(FinalArgIdx);
 
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/irtranslator/ret-aggregates.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/irtranslator/ret-aggregates.ll
new file mode 100644
index 0000000000000..02c72cf9f157d
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/irtranslator/ret-aggregates.ll
@@ -0,0 +1,265 @@
+; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -mtriple=wasm32 -mattr=-simd128 -global-isel -stop-after=irtranslator -verify-machineinstrs < %s | FileCheck %s -check-prefixes=WASM32-NOMULTIVAL
+; RUN: llc -mtriple=wasm64 -mattr=-simd128 -global-isel -stop-after=irtranslator -verify-machineinstrs < %s | FileCheck %s -check-prefixes=WASM64-NOMULTIVAL
+; RUN: llc -mtriple=wasm32 -mattr=-simd128,+multivalue -target-abi=experimental-mv -global-isel -stop-after=irtranslator -verify-machineinstrs < %s | FileCheck %s -check-prefixes=MULTIVAL,WASM32-MULTIVAL
+; RUN: llc -mtriple=wasm64 -mattr=-simd128,+multivalue -target-abi=experimental-mv -global-isel -stop-after=irtranslator -verify-machineinstrs < %s | FileCheck %s -check-prefixes=MULTIVAL,WASM64-MULTIVAL
+
+define i128 @test_ret_i128() {
+  ; WASM32-NOMULTIVAL-LABEL: name: test_ret_i128
+  ; WASM32-NOMULTIVAL: bb.1 (%ir-block.0):
+  ; WASM32-NOMULTIVAL-NEXT:   liveins: $arguments
+  ; WASM32-NOMULTIVAL-NEXT: {{  $}}
+  ; WASM32-NOMULTIVAL-NEXT:   [[ARGUMENT_i32_:%[0-9]+]]:i32(p0) = ARGUMENT_i32 0, implicit $arguments
+  ; WASM32-NOMULTIVAL-NEXT:   [[C:%[0-9]+]]:_(s128) = G_CONSTANT i128 0
+  ; WASM32-NOMULTIVAL-NEXT:   G_STORE [[C]](s128), [[ARGUMENT_i32_]](p0) :: (store (s128))
+  ; WASM32-NOMULTIVAL-NEXT:   RETURN implicit-def $arguments
+  ;
+  ; WASM64-NOMULTIVAL-LABEL: name: test_ret_i128
+  ; WASM64-NOMULTIVAL: bb.1 (%ir-block.0):
+  ; WASM64-NOMULTIVAL-NEXT:   liveins: $arguments
+  ; WASM64-NOMULTIVAL-NEXT: {{  $}}
+  ; WASM64-NOMULTIVAL-NEXT:   [[ARGUMENT_i64_:%[0-9]+]]:i64(p0) = ARGUMENT_i64 0, implicit $arguments
+  ; WASM64-NOMULTIVAL-NEXT:   [[C:%[0-9]+]]:_(s128) = G_CONSTANT i128 0
+  ; WASM64-NOMULTIVAL-NEXT:   G_STORE [[C]](s128), [[ARGUMENT_i64_]](p0) :: (store (s128))
+  ; WASM64-NOMULTIVAL-NEXT:   RETURN implicit-def $arguments
+  ;
+  ; MULTIVAL-LABEL: name: test_ret_i128
+  ; MULTIVAL: bb.1 (%ir-block.0):
+  ; MULTIVAL-NEXT:   liveins: $arguments
+  ; MULTIVAL-NEXT: {{  $}}
+  ; MULTIVAL-NEXT:   [[C:%[0-9]+]]:_(s128) = G_CONSTANT i128 0
+  ; MULTIVAL-NEXT:   [[UV:%[0-9]+]]:i64(s64), [[UV1:%[0-9]+]]:i64(s64) = G_UNMERGE_VALUES [[C]](s128)
+  ; MULTIVAL-NEXT:   RETURN [[UV]](s64), [[UV1]](s64), implicit-def $arguments
+  ret i128 0
+}
+
+define fp128 @test_ret_f128() {
+  ; WASM32-NOMULTIVAL-LABEL: name: test_ret_f128
+  ; WASM32-NOMULTIVAL: bb.1 (%ir-block.0):
+  ; WASM32-NOMULTIVAL-NEXT:   liveins: $arguments
+  ; WASM32-NOMULTIVAL-NEXT: {{  $}}
+  ; WASM32-NOMULTIVAL-NEXT:   [[ARGUMENT_i32_:%[0-9]+]]:i32(p0) = ARGUMENT_i32 0, implicit $arguments
+  ; WASM32-NOMULTIVAL-NEXT:   [[C:%[0-9]+]]:_(s128) = G_FCONSTANT fp128 0xL00000000000000000000000000000000
+  ; WASM32-NOMULTIVAL-NEXT:   G_STORE [[C]](s128), [[ARGUMENT_i32_]](p0) :: (store (s128))
+  ; WASM32-NOMULTIVAL-NEXT:   RETURN implicit-def $arguments
+  ;
+  ; WASM64-NOMULTIVAL-LABEL: name: test_ret_f128
+  ; WASM64-NOMULTIVAL: bb.1 (%ir-block.0):
+  ; WASM64-NOMULTIVAL-NEXT:   liveins: $arguments
+  ; WASM64-NOMULTIVAL-NEXT: {{  $}}
+  ; WASM64-NOMULTIVAL-NEXT:   [[ARGUMENT_i64_:%[0-9]+]]:i64(p0) = ARGUMENT_i64 0, implicit $arguments
+  ; WASM64-NOMULTIVAL-NEXT:   [[C:%[0-9]+]]:_(s128) = G_FCONSTANT fp128 0xL00000000000000000000000000000000
+  ; WASM64-NOMULTIVAL-NEXT:   G_STORE [[C]](s128), [[ARGUMENT_i64_]](p0) :: (store (s128))
+  ; WASM64-NOMULTIVAL-NEXT:   RETURN implicit-def $arguments
+  ;
+  ; MULTIVAL-LABEL: name: test_ret_f128
+  ; MULTIVAL: bb.1 (%ir-block.0):
+  ; MULTIVAL-NEXT:   liveins: $arguments
+  ; MULTIVAL-NEXT: {{  $}}
+  ; MULTIVAL-NEXT:   [[C:%[0-9]+]]:_(s128) = G_FCONSTANT fp128 0xL00000000000000000000000000000000
+  ; MULTIVAL-NEXT:   [[UV:%[0-9]+]]:i64(s64), [[UV1:%[0-9]+]]:i64(s64) = G_UNMERGE_VALUES [[C]](s128)
+  ; MULTIVAL-NEXT:   RETURN [[UV]](s64), [[UV1]](s64), implicit-def $arguments
+  ret fp128 zeroinitializer
+}
+
+define <4 x i32> @test_ret_v4i32() {
+  ; WASM32-NOMULTIVAL-LABEL: name: test_ret_v4i32
+  ; WASM32-NOMULTIVAL: bb.1 (%ir-block.0):
+  ; WASM32-NOMULTIVAL-NEXT:   liveins: $arguments
+  ; WASM32-NOMULTIVAL-NEXT: {{  $}}
+  ; WASM32-NOMULTIVAL-NEXT:   [[ARGUMENT_i32_:%[0-9]+]]:i32(p0) = ARGUMENT_i32 0, implicit $arguments
+  ; WASM32-NOMULTIVAL-NEXT:   [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+  ; WASM32-NOMULTIVAL-NEXT:   [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C]](s32), [[C]](s32), [[C]](s32), [[C]](s32)
+  ; WASM32-NOMULTIVAL-NEXT:   G_STORE [[BUILD_VECTOR]](<4 x s32>), [[ARGUMENT_i32_]](p0) :: (store (<4 x s32>))
+  ; WASM32-NOMULTIVAL-NEXT:   RETURN implicit-def $arguments
+  ;
+  ; WASM64-NOMULTIVAL-LABEL: name: test_ret_v4i32
+  ; WASM64-NOMULTIVAL: bb.1 (%ir-block.0):
+  ; WASM64-NOMULTIVAL-NEXT:   liveins: $arguments
+  ; WASM64-NOMULTIVAL-NEXT: {{  $}}
+  ; WASM64-NOMULTIVAL-NEXT:   [[ARGUMENT_i64_:%[0-9]+]]:i64(p0) = ARGUMENT_i64 0, implicit $arguments
+  ; WASM64-NOMULTIVAL-NEXT:   [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+  ; WASM64-NOMULTIVAL-NEXT:   [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C]](s32), [[C]](s32), [[C]](s32), [[C]](s32)
+  ; WASM64-NOMULTIVAL-NEXT:   G_STORE [[BUILD_VECTOR]](<4 x s32>), [[ARGUMENT_i64_]](p0) :: (store (<4 x s32>))
+  ; WASM64-NOMULTIVAL-NEXT:   RETURN implicit-def $arguments
+  ;
+  ; MULTIVAL-LABEL: name: test_ret_v4i32
+  ; MULTIVAL: bb.1 (%ir-block.0):
+  ; MULTIVAL-NEXT:   liveins: $arguments
+  ; MULTIVAL-NEXT: {{  $}}
+  ; MULTIVAL-NEXT:   [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+  ; MULTIVAL-NEXT:   [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C]](s32), [[C]](s32), [[C]](s32), [[C]](s32)
+  ; MULTIVAL-NEXT:   [[UV:%[0-9]+]]:i32(s32), [[UV1:%[0-9]+]]:i32(s32), [[UV2:%[0-9]+]]:i32(s32), [[UV3:%[0-9]+]]:i32(s32) = G_UNMERGE_VALUES [[BUILD_VECTOR]](<4 x s32>)
+  ; MULTIVAL-NEXT:   RETURN [[UV]](s32), [[UV1]](s32), [[UV2]](s32), [[UV3]](s32), implicit-def $arguments
+  ret <4 x i32> zeroinitializer
+}
+
+define [5 x i16] @test_array_arg() {
+  ; WASM32-NOMULTIVAL-LABEL: name: test_array_arg
+  ; WASM32-NOMULTIVAL: bb.1 (%ir-block.0):
+  ; WASM32-NOMULTIVAL-NEXT:   liveins: $arguments
+  ; WASM32-NOMULTIVAL-NEXT: {{  $}}
+  ; WASM32-NOMULTIVAL-NEXT:   [[ARGUMENT_i32_:%[0-9]+]]:i32(p0) = ARGUMENT_i32 0, implicit $arguments
+  ; WASM32-NOMULTIVAL-NEXT:   [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 0
+  ; WASM32-NOMULTIVAL-NEXT:   G_STORE [[C]](s16), [[ARGUMENT_i32_]](p0) :: (store (s16))
+  ; WASM32-NOMULTIVAL-NEXT:   [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 2
+  ; WASM32-NOMULTIVAL-NEXT:   [[PTR_ADD:%[0-9]+]]:_(p0) = nuw inbounds G_PTR_ADD [[ARGUMENT_i32_]], [[C1]](s32)
+  ; WASM32-NOMULTIVAL-NEXT:   G_STORE [[C]](s16), [[PTR_ADD]](p0) :: (store (s16))
+  ; WASM32-NOMULTIVAL-NEXT:   [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 4
+  ; WASM32-NOMULTIVAL-NEXT:   [[PTR_ADD1:%[0-9]+]]:_(p0) = nuw inbounds G_PTR_ADD [[ARGUMENT_i32_]], [[C2]](s32)
+  ; WASM32-NOMULTIVAL-NEXT:   G_STORE [[C]](s16), [[PTR_ADD1]](p0) :: (store (s16))
+  ; WASM32-NOMULTIVAL-NEXT:   [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 6
+  ; WASM32-NOMULTIVAL-NEXT:   [[PTR_ADD2:%[0-9]+]]:_(p0) = nuw inbounds G_PTR_ADD [[ARGUMENT_i32_]], [[C3]](s32)
+  ; WASM32-NOMULTIVAL-NEXT:   G_STORE [[C]](s16), [[PTR_ADD2]](p0) :: (store (s16))
+  ; WASM32-NOMULTIVAL-NEXT:   [[C4:%[0-9]+]]:_(s32) = G_CONSTANT i32 8
+  ; WASM32-NOMULTIVAL-NEXT:   [[PTR_ADD3:%[0-9]+]]:_(p0) = nuw inbounds G_PTR_ADD [[ARGUMENT_i32_]], [[C4]](s32)
+  ; WASM32-NOMULTIVAL-NEXT:   G_STORE [[C]](s16), [[PTR_ADD3]](p0) :: (store (s16))
+  ; WASM32-NOMULTIVAL-NEXT:   RETURN implicit-def $arguments
+  ;
+  ; WASM64-NOMULTIVAL-LABEL: name: test_array_arg
+  ; WASM64-NOMULTIVAL: bb.1 (%ir-block.0):
+  ; WASM64-NOMULTIVAL-NEXT:   liveins: $arguments
+  ; WASM64-NOMULTIVAL-NEXT: {{  $}}
+  ; WASM64-NOMULTIVAL-NEXT:   [[ARGUMENT_i64_:%[0-9]+]]:i64(p0) = ARGUMENT_i64 0, implicit $arguments
+  ; WASM64-NOMULTIVAL-NEXT:   [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 0
+  ; WASM64-NOMULTIVAL-NEXT:   G_STORE [[C]](s16), [[ARGUMENT_i64_]](p0) :: (store (s16))
+  ; WASM64-NOMULTIVAL-NEXT:   [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 2
+  ; WASM64-NOMULTIVAL-NEXT:   [[PTR_ADD:%[0-9]+]]:_(p0) = nuw inbounds G_PTR_ADD [[ARGUMENT_i64_]], [[C1]](s64)
+  ; WASM64-NOMULTIVAL-NEXT:   G_STORE [[C]](s16), [[PTR_ADD]](p0) :: (store (s16))
+  ; WASM64-NOMULTIVAL-NEXT:   [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 4
+  ; WASM64-NOMULTIVAL-NEXT:   [[PTR_ADD1:%[0-9]+]]:_(p0) = nuw inbounds G_PTR_ADD [[ARGUMENT_i64_]], [[C2]](s64)
+  ; WASM64-NOMULTIVAL-NEXT:   G_STORE [[C]](s16), [[PTR_ADD1]](p0) :: (store (s16))
+  ; WASM64-NOMULTIVAL-NEXT:   [[C3:%[0-9]+]]:_(s64) = G_CONSTANT i64 6
+  ; WASM64-NOMULTIVAL-NEXT:   [[PTR_ADD2:%[0-9]+]]:_(p0) = nuw inbounds G_PTR_ADD [[ARGUMENT_i64_]], [[C3]](s64)
+  ; WASM64-NOMULTIVAL-NEXT:   G_STORE [[C]](s16), [[PTR_ADD2]](p0) :: (store (s16))
+  ; WASM64-NOMULTIVAL-NEXT:   [[C4:%[0-9]+]]:_(s64) = G_CONSTANT i64 8
+  ; WASM64-NOMULTIVAL-NEXT:   [[PTR_ADD3:%[0-9]+]]:_(p0) = nuw inbounds G_PTR_ADD [[ARGUMENT_i64_]], [[C4]](s64)
+  ; WASM64-NOMULTIVAL-NEXT:   G_STORE [[C]](s16), [[PTR_ADD3]](p0) :: (store (s16))
+  ; WASM64-NOMULTIVAL-NEXT:   RETURN implicit-def $arguments
+  ;
+  ; MULTIVAL-LABEL: name: test_array_arg
+  ; MULTIVAL: bb.1 (%ir-block.0):
+  ; MULTIVAL-NEXT:   liveins: $arguments
+  ; MULTIVAL-NEXT: {{  $}}
+  ; MULTIVAL-NEXT:   [[C:%[0-9]+]]:_(s16) = G_CONSTANT i16 0
+  ; MULTIVAL-NEXT:   [[ANYEXT:%[0-9]+]]:i32(s32) = G_ANYEXT [[C]](s16)
+  ; MULTIVAL-NEXT:   [[ANYEXT1:%[0-9]+]]:i32(s32) = G_ANYEXT [[C]](s16)
+  ; MULTIVAL-NEXT:   [[ANYEXT2:%[0-9]+]]:i32(s32) = G_ANYEXT [[C]](s16)
+  ; MULTIVAL-NEXT:   [[ANYEXT3:%[0-9]+]]:i32(s32) = G_ANYEXT [[C]](s16)
+  ; MULTIVAL-NEXT:   [[ANYEXT4:%[0-9]+]]:i32(s32) = G_ANYEXT [[C]](s16)
+  ; MULTIVAL-NEXT:   RETURN [[ANYEXT]](s32), [[ANYEXT1]](s32), [[ANYEXT2]](s32), [[ANYEXT3]](s32), [[ANYEXT4]](s32), implicit-def $arguments
+  ret [5 x i16] zeroinitializer
+}
+
+%StructTy = type { i8, i16, i32, i64, ptr, float, double, i128 }
+
+define %StructTy @test_ret_struct() {
+  ; WASM32-NOMULTIVAL-LABEL: name: test_ret_struct
+  ; WASM32-NOMULTIVAL: bb.1 (%ir-block.0):
+  ; WASM32-NOMULTIVAL-NEXT:   liveins: $arguments
+  ; WASM32-NOMULTIVAL-NEXT: {{  $}}
+  ; WASM32-NOMULTIVAL-NEXT:   [[ARGUMENT_i32_:%[0-9]+]]:i32(p0) = ARGUMENT_i32 0, implicit $arguments
+  ; WASM32-NOMULTIVAL-NEXT:   [[C:%[0-9]+]]:_(s8) = G_CONSTANT i8 0
+  ; WASM32-NOMULTIVAL-NEXT:   [[C1:%[0-9]+]]:_(s16) = G_CONSTANT i16 0
+  ; WASM32-NOMULTIVAL-NEXT:   [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+  ; WASM32-NOMULTIVAL-NEXT:   [[C3:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
+  ; WASM32-NOMULTIVAL-NEXT:   [[C4:%[0-9]+]]:_(p0) = G_CONSTANT i32 0
+  ; WASM32-NOMULTIVAL-NEXT:   [[C5:%[0-9]+]]:_(s32) = G_FCONSTANT float 0.000000e+00
+  ; WASM32-NOMULTIVAL-NEXT:   [[C6:%[0-9]+]]:_(s64) = G_FCONSTANT double 0.000000e+00
+  ; WASM32-NOMULTIVAL-NEXT:   [[C7:%[0-9]+]]:_(s128) = G_CONSTANT i128 0
+  ; WASM32-NOMULTIVAL-NEXT:   G_STORE [[C]](s8), [[ARGUMENT_i32_]](p0) :: (store (s8), align 16)
+  ; WASM32-NOMULTIVAL-NEXT:   [[C8:%[0-9]+]]:_(s32) = G_CONSTANT i32 2
+  ; WASM32-NOMULTIVAL-NEXT:   [[PTR_ADD:%[0-9]+]]:_(p0) = nuw inbounds G_PTR_ADD [[ARGUMENT_i32_]], [[C8]](s32)
+  ; WASM32-NOMULTIVAL-NEXT:   G_STORE [[C1]](s16), [[PTR_ADD]](p0) :: (store (s16))
+  ; WASM32-NOMULTIVAL-NEXT:   [[C9:%[0-9]+]]:_(s32) = G_CONSTANT i32 4
+  ; WASM32-NOMULTIVAL-NEXT:   [[PTR_ADD1:%[0-9]+]]:_(p0) = nuw inbounds G_PTR_ADD [[ARGUMENT_i32_]], [[C9]](s32)
+  ; WASM32-NOMULTIVAL-NEXT:   G_STORE [[C2]](s32), [[PTR_ADD1]](p0) :: (store (s32))
+  ; WASM32-NOMULTIVAL-NEXT:   [[C10:%[0-9]+]]:_(s32) = G_CONSTANT i32 8
+  ; WASM32-NOMULTIVAL-NEXT:   [[PTR_ADD2:%[0-9]+]]:_(p0) = nuw inbounds G_PTR_ADD [[ARGUMENT_i32_]], [[C10]](s32)
+  ; WASM32-NOMULTIVAL-NEXT:   G_STORE [[C3]](s64), [[PTR_ADD2]](p0) :: (store (s64))
+  ; WASM32-NOMULTIVAL-NEXT:   [[C11:%[0-9]+]]:_(s32) = G_CONSTANT i32 16
+  ; WASM32-NOMULTIVAL-NEXT:   [[PTR_ADD3:%[0-9]+]]:_(p0) = nuw inbounds G_PTR_ADD [[ARGUMENT_i32_]], [[C11]](s32)
+  ; WASM32-NOMULTIVAL-NEXT:   G_STORE [[C4]](p0), [[PTR_ADD3]](p0) :: (store (p0), align 16)
+  ; WASM32-NOMULTIVAL-NEXT:   [[C12:%[0-9]+]]:_(s32) = G_CONSTANT i32 20
+  ; WASM32-NO...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/190247


More information about the llvm-commits mailing list