[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