[llvm] [WebAssembly][GlobalISel] Implement pointer and memory ops. (PR #206885)
Demetrius Kanios via llvm-commits
llvm-commits at lists.llvm.org
Sun Aug 2 21:52:44 PDT 2026
https://github.com/QuantumSegfault updated https://github.com/llvm/llvm-project/pull/206885
>From 79f2eeb1a00ce544a3e436333efbfcd355d99da7 Mon Sep 17 00:00:00 2001
From: Demetrius Kanios <demetrius at kanios.net>
Date: Tue, 30 Jun 2026 21:21:40 -0700
Subject: [PATCH 1/2] Implement pointer and memory ops.
---
.../GISel/WebAssemblyInstructionSelector.cpp | 142 ++++++++++-
.../GISel/WebAssemblyLegalizerInfo.cpp | 74 +++++-
.../GISel/WebAssemblyRegisterBankInfo.cpp | 2 +-
.../Target/WebAssembly/WebAssemblyGISel.td | 29 +++
.../GlobalISel/instructions/constant.ll | 20 +-
.../GlobalISel/instructions/frame_index.ll | 35 +++
.../GlobalISel/instructions/global_value.ll | 127 ++++++++++
.../GlobalISel/instructions/implicit_def.mir | 25 +-
.../GlobalISel/instructions/inttoptr.ll | 79 ++++++
.../GlobalISel/instructions/load.ll | 198 +++++++++++++++
.../GlobalISel/instructions/ptradd.ll | 91 +++++++
.../GlobalISel/instructions/ptrmask.ll | 17 ++
.../instructions/ptrmask_wasm32.mir | 85 +++++++
.../instructions/ptrmask_wasm64.mir | 87 +++++++
.../GlobalISel/instructions/ptrtoint.ll | 71 ++++++
.../GlobalISel/instructions/sextload.mir | 220 ++++++++++++++++
.../GlobalISel/instructions/store.ll | 236 ++++++++++++++++++
.../GlobalISel/instructions/zextload.mir | 208 +++++++++++++++
18 files changed, 1736 insertions(+), 10 deletions(-)
create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/frame_index.ll
create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/global_value.ll
create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/inttoptr.ll
create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/load.ll
create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/ptradd.ll
create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/ptrmask.ll
create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/ptrmask_wasm32.mir
create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/ptrmask_wasm64.mir
create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/ptrtoint.ll
create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/sextload.mir
create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/store.ll
create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/zextload.mir
diff --git a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyInstructionSelector.cpp b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyInstructionSelector.cpp
index 2331b8b636603..3709327170ac6 100644
--- a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyInstructionSelector.cpp
+++ b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyInstructionSelector.cpp
@@ -13,6 +13,8 @@
#include "GISel/WebAssemblyRegisterBankInfo.h"
#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
+#include "Utils/WasmAddressSpaces.h"
+#include "Utils/WebAssemblyTypeUtilities.h"
#include "WebAssemblyRegisterInfo.h"
#include "WebAssemblySubtarget.h"
#include "WebAssemblyTargetMachine.h"
@@ -42,14 +44,23 @@ class WebAssemblyInstructionSelector : public InstructionSelector {
bool select(MachineInstr &I) override;
+ InstructionSelector::ComplexRendererFns
+ selectAddrOperands32(MachineOperand &Root) const;
+ InstructionSelector::ComplexRendererFns
+ selectAddrOperands64(MachineOperand &Root) const;
+
static const char *getName() { return DEBUG_TYPE; }
private:
bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const;
bool selectCopy(MachineInstr &I, MachineRegisterInfo &MRI) const;
+ InstructionSelector::ComplexRendererFns
+ selectAddrOperands(LLT AddrType, unsigned int ConstOpc,
+ MachineOperand &Root) const;
+
const WebAssemblyTargetMachine &TM;
- // const WebAssemblySubtarget &STI;
+ const WebAssemblySubtarget &STI;
const WebAssemblyInstrInfo &TII;
const WebAssemblyRegisterInfo &TRI;
const WebAssemblyRegisterBankInfo &RBI;
@@ -72,8 +83,8 @@ class WebAssemblyInstructionSelector : public InstructionSelector {
WebAssemblyInstructionSelector::WebAssemblyInstructionSelector(
const WebAssemblyTargetMachine &TM, const WebAssemblySubtarget &STI,
const WebAssemblyRegisterBankInfo &RBI)
- : TM(TM), /*STI(STI),*/ TII(*STI.getInstrInfo()),
- TRI(*STI.getRegisterInfo()), RBI(RBI),
+ : TM(TM), STI(STI), TII(*STI.getInstrInfo()), TRI(*STI.getRegisterInfo()),
+ RBI(RBI),
#define GET_GLOBALISEL_PREDICATES_INIT
#include "WebAssemblyGenGlobalISel.inc"
@@ -84,6 +95,32 @@ WebAssemblyInstructionSelector::WebAssemblyInstructionSelector(
{
}
+InstructionSelector::ComplexRendererFns
+WebAssemblyInstructionSelector::selectAddrOperands(LLT AddrType,
+ unsigned int ConstOpc,
+ MachineOperand &Root) const {
+
+ if (!Root.isReg())
+ return std::nullopt;
+
+ return {{
+ [=](MachineInstrBuilder &MIB) { MIB.addImm(0); },
+ [=](MachineInstrBuilder &MIB) { MIB.addReg(Root.getReg()); },
+ }};
+}
+
+InstructionSelector::ComplexRendererFns
+WebAssemblyInstructionSelector::selectAddrOperands32(
+ MachineOperand &Root) const {
+ return selectAddrOperands(LLT::integer(32), WebAssembly::CONST_I32, Root);
+}
+
+InstructionSelector::ComplexRendererFns
+WebAssemblyInstructionSelector::selectAddrOperands64(
+ MachineOperand &Root) const {
+ return selectAddrOperands(LLT::integer(64), WebAssembly::CONST_I64, Root);
+}
+
bool WebAssemblyInstructionSelector::selectCopy(
MachineInstr &I, MachineRegisterInfo &MRI) const {
const TargetRegisterClass *DstRC =
@@ -140,6 +177,7 @@ bool WebAssemblyInstructionSelector::select(MachineInstr &I) {
MachineBasicBlock &MBB = *I.getParent();
MachineFunction &MF = *MBB.getParent();
MachineRegisterInfo &MRI = MF.getRegInfo();
+ const TargetLowering &TLI = *STI.getTargetLowering();
if (!I.isPreISelOpcode()) {
if (I.isCopy())
@@ -152,6 +190,9 @@ bool WebAssemblyInstructionSelector::select(MachineInstr &I) {
using namespace TargetOpcode;
+ auto PointerWidth = MF.getDataLayout().getPointerSizeInBits();
+ auto PtrIsI64 = PointerWidth == 64;
+
switch (I.getOpcode()) {
case G_IMPLICIT_DEF: {
const Register DefReg = I.getOperand(0).getReg();
@@ -165,6 +206,101 @@ bool WebAssemblyInstructionSelector::select(MachineInstr &I) {
I.setDesc(TII.get(TargetOpcode::IMPLICIT_DEF));
return RBI.constrainGenericRegister(DefReg, *DefRC, MRI) != nullptr;
}
+ case G_PTRTOINT: {
+ assert(MRI.getType(I.getOperand(1).getReg()).isPointer() &&
+ "G_PTRTOINT selection with non-pointer?");
+
+ I.setDesc(
+ TII.get(PtrIsI64 ? WebAssembly::COPY_I64 : WebAssembly::COPY_I32));
+ constrainSelectedInstRegOperands(I, TII, TRI, RBI);
+
+ return true;
+ }
+ case G_INTTOPTR: {
+ assert(MRI.getType(I.getOperand(0).getReg()).isPointer() &&
+ "G_INTTOPTR selection with non-pointer?");
+
+ I.setDesc(
+ TII.get(PtrIsI64 ? WebAssembly::COPY_I64 : WebAssembly::COPY_I32));
+ constrainSelectedInstRegOperands(I, TII, TRI, RBI);
+
+ return true;
+ }
+ case G_PTRMASK: {
+ assert(MRI.getType(I.getOperand(0).getReg()).isPointer() &&
+ "G_PTRMASK selection with non-pointer?");
+
+ I.setDesc(TII.get(PtrIsI64 ? WebAssembly::AND_I64 : WebAssembly::AND_I32));
+ constrainSelectedInstRegOperands(I, TII, TRI, RBI);
+
+ return true;
+ }
+ case G_GLOBAL_VALUE: {
+ assert(I.getOperand(1).getTargetFlags() == 0 &&
+ "Unexpected target flags on generic G_GLOBAL_VALUE instruction");
+ assert(WebAssembly::isValidAddressSpace(
+ MRI.getType(I.getOperand(0).getReg()).getAddressSpace()) &&
+ "Invalid address space for WebAssembly target");
+
+ unsigned OperandFlags = 0;
+ const llvm::GlobalValue *GV = I.getOperand(1).getGlobal();
+
+ if (TLI.isPositionIndependent()) {
+ if (TM.shouldAssumeDSOLocal(GV)) {
+ const char *BaseName;
+ if (GV->getValueType()->isFunctionTy()) {
+ BaseName = MF.createExternalSymbolName("__table_base");
+ OperandFlags = WebAssemblyII::MO_TABLE_BASE_REL;
+ } else {
+ BaseName = MF.createExternalSymbolName("__memory_base");
+ OperandFlags = WebAssemblyII::MO_MEMORY_BASE_REL;
+ }
+ MachineIRBuilder B(I);
+
+ auto MemBase =
+ MRI.createGenericVirtualRegister(LLT::pointer(0, PointerWidth));
+ MRI.setRegClass(MemBase, PtrIsI64 ? &WebAssembly::I64RegClass
+ : &WebAssembly::I32RegClass);
+ auto Offset =
+ MRI.createGenericVirtualRegister(LLT::pointer(0, PointerWidth));
+ MRI.setRegClass(Offset, PtrIsI64 ? &WebAssembly::I64RegClass
+ : &WebAssembly::I32RegClass);
+
+ B.buildInstr(PtrIsI64 ? WebAssembly::GLOBAL_GET_I64
+ : WebAssembly::GLOBAL_GET_I32)
+ .addDef(MemBase)
+ .addExternalSymbol(BaseName);
+
+ B.buildInstr(PtrIsI64 ? WebAssembly::CONST_I64 : WebAssembly::CONST_I32)
+ .addDef(Offset)
+ .addGlobalAddress(GV, I.getOperand(1).getOffset(), OperandFlags);
+
+ auto MIB =
+ B.buildInstr(PtrIsI64 ? WebAssembly::ADD_I64 : WebAssembly::ADD_I32)
+ .addDef(I.getOperand(0).getReg())
+ .addReg(MemBase)
+ .addReg(Offset);
+ constrainSelectedInstRegOperands(*MIB, TII, TRI, RBI);
+
+ I.eraseFromParent();
+ return true;
+ }
+ OperandFlags = WebAssemblyII::MO_GOT;
+ }
+
+ auto NewOpc = PtrIsI64 ? WebAssembly::CONST_I64 : WebAssembly::CONST_I32;
+
+ if (OperandFlags & WebAssemblyII::MO_GOT) {
+ NewOpc =
+ PtrIsI64 ? WebAssembly::GLOBAL_GET_I64 : WebAssembly::GLOBAL_GET_I32;
+ }
+
+ I.setDesc(TII.get(NewOpc));
+ I.getOperand(1).setTargetFlags(OperandFlags);
+ constrainSelectedInstRegOperands(I, TII, TRI, RBI);
+
+ return true;
+ }
default:
break;
}
diff --git a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyLegalizerInfo.cpp b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyLegalizerInfo.cpp
index 956432a78fb50..8ceebac8c4c72 100644
--- a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyLegalizerInfo.cpp
+++ b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyLegalizerInfo.cpp
@@ -25,6 +25,8 @@ WebAssemblyLegalizerInfo::WebAssemblyLegalizerInfo(
const WebAssemblySubtarget &ST) {
using namespace TargetOpcode;
+ const LLT i8 = LLT::integer(8);
+ const LLT i16 = LLT::integer(16);
const LLT i32 = LLT::integer(32);
const LLT i64 = LLT::integer(64);
@@ -34,13 +36,22 @@ WebAssemblyLegalizerInfo::WebAssemblyLegalizerInfo(
const LLT s32 = LLT::scalar(32);
const LLT s64 = LLT::scalar(64);
+ const LLT p0 = LLT::pointer(0, ST.hasAddr64() ? 64 : 32);
+ const LLT p0i = LLT::integer(ST.hasAddr64() ? 64 : 32);
+ const LLT p0s = LLT::scalar(ST.hasAddr64() ? 64 : 32);
+
getActionDefinitionsBuilder(G_IMPLICIT_DEF)
- .legalFor({i32, i64, f32, f64})
+ .legalFor({i32, i64, f32, f64, p0})
.widenScalarToNextPow2(0)
.clampScalar(0, s32, s64);
- getActionDefinitionsBuilder({G_CONSTANT, G_ADD, G_SUB, G_MUL, G_UDIV, G_SDIV,
- G_UREM, G_SREM, G_AND, G_OR, G_XOR})
+ getActionDefinitionsBuilder(G_CONSTANT)
+ .legalFor({i32, i64, p0})
+ .widenScalarToNextPow2(0)
+ .clampScalar(0, s32, s64);
+
+ getActionDefinitionsBuilder(
+ {G_ADD, G_SUB, G_MUL, G_UDIV, G_SDIV, G_UREM, G_SREM, G_AND, G_OR, G_XOR})
.legalFor({i32, i64})
.widenScalarToNextPow2(0)
.clampScalar(0, s32, s64);
@@ -146,6 +157,63 @@ WebAssemblyLegalizerInfo::WebAssemblyLegalizerInfo(
.widenScalarToNextPow2(0)
.clampScalar(0, s32, s64)
.clampScalar(1, s32, s32);
+
+ getActionDefinitionsBuilder(G_PTRTOINT)
+ .legalFor({{p0i, p0}})
+ .clampScalar(0, p0s, p0s);
+ getActionDefinitionsBuilder(G_INTTOPTR)
+ .legalFor({{p0, p0i}})
+ .clampScalar(1, p0s, p0s);
+
+ getActionDefinitionsBuilder({G_PTR_ADD, G_PTRMASK})
+ .legalFor({{p0, p0i}})
+ .clampScalar(1, p0s, p0s);
+
+ getActionDefinitionsBuilder({G_FRAME_INDEX, G_GLOBAL_VALUE}).legalFor({p0});
+
+ getActionDefinitionsBuilder(G_LOAD)
+ .legalForTypesWithMemDesc({{i32, p0, i8, 1},
+ {i32, p0, i16, 1},
+ {i32, p0, i32, 1},
+
+ {i64, p0, i8, 1},
+ {i64, p0, i16, 1},
+ {i64, p0, i32, 1},
+ {i64, p0, i64, 1},
+
+ {f32, p0, f32, 1},
+ {f64, p0, f64, 1},
+
+ {p0, p0, p0, 1}})
+ .clampScalar(0, s32, s64)
+ .lowerIfMemSizeNotByteSizePow2();
+
+ getActionDefinitionsBuilder({G_ZEXTLOAD, G_SEXTLOAD})
+ .legalForTypesWithMemDesc({{i32, p0, i8, 1},
+ {i32, p0, i16, 1},
+
+ {i64, p0, i8, 1},
+ {i64, p0, i16, 1},
+ {i64, p0, i32, 1}})
+ .clampScalar(0, s32, s64)
+ .lowerIfMemSizeNotByteSizePow2();
+
+ getActionDefinitionsBuilder(G_STORE)
+ .legalForTypesWithMemDesc({{i32, p0, i8, 1},
+ {i32, p0, i16, 1},
+ {i32, p0, i32, 1},
+
+ {i64, p0, i8, 1},
+ {i64, p0, i16, 1},
+ {i64, p0, s32, 1},
+ {i64, p0, i64, 1},
+
+ {f32, p0, f32, 1},
+ {f64, p0, f64, 1},
+
+ {p0, p0, p0, 1}})
+ .clampScalar(0, s32, s64)
+ .lowerIfMemSizeNotByteSizePow2();
}
bool WebAssemblyLegalizerInfo::legalizeCustom(
diff --git a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyRegisterBankInfo.cpp b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyRegisterBankInfo.cpp
index 7e50ca6ab22fe..78f2f3d3fae03 100644
--- a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyRegisterBankInfo.cpp
+++ b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyRegisterBankInfo.cpp
@@ -77,7 +77,7 @@ WebAssemblyRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
OpSize[Idx] = Ty.getSizeInBits().getKnownMinValue();
- if (Ty.isInteger()) {
+ if (Ty.isInteger() || (Ty.isPointer() && Ty.getAddressSpace() == 0)) {
if (OpSize[Idx] == 32) {
OpRegBankIdx[Idx] = WebAssembly::PMI_I32;
} else if (OpSize[Idx] == 64) {
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyGISel.td b/llvm/lib/Target/WebAssembly/WebAssemblyGISel.td
index 0e49d61deca67..640bd279cb20b 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyGISel.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyGISel.td
@@ -15,3 +15,32 @@
include "WebAssembly.td"
include "WebAssemblyCombine.td"
+
+defvar ModeAddr32 = DefaultMode;
+def ModeAddr64 : HwMode<[HasAddr64]>;
+
+def p0i : ValueTypeByHwMode<[ModeAddr32, ModeAddr64],
+ [i32, i64]>;
+def p0 : PtrValueTypeByHwMode<p0i, 0>;
+
+
+def : Pat<(p0 (ptradd p0:$lhs, p0i:$rhs)),
+ (ADD_I32 I32:$lhs, I32:$rhs)>, Requires<[HasAddr32]>;
+def : Pat<(p0 (ptradd p0:$lhs, p0i:$rhs)),
+ (ADD_I64 I64:$lhs, I64:$rhs)>, Requires<[HasAddr64]>;
+
+def : Pat<(frameindex:$fi),
+ (COPY_I32 (to_tframeindex $fi))>, Requires<[HasAddr32]>;
+def : Pat<(frameindex:$fi),
+ (COPY_I64 (to_tframeindex $fi))>, Requires<[HasAddr64]>;
+
+
+//===----------------------------------------------------------------------===//
+// Complex pattern equivalents
+//===----------------------------------------------------------------------===//
+
+def gi_AddrOps32 : GIComplexOperandMatcher<s32, "selectAddrOperands32">,
+ GIComplexPatternEquiv<AddrOps32>;
+
+def gi_AddrOps64 : GIComplexOperandMatcher<s64, "selectAddrOperands64">,
+ GIComplexPatternEquiv<AddrOps64>;
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/constant.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/constant.ll
index 8ceda5bb3740a..7e74d6035afa4 100644
--- a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/constant.ll
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/constant.ll
@@ -1,7 +1,7 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
-; RUN: llc < %s -O0 --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s
+; RUN: llc < %s -O0 -mtriple=wasm32-unknown-unknown --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s --check-prefixes=CHECK,WASM32
+; RUN: llc < %s -O0 -mtriple=wasm64-unknown-unknown --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s --check-prefixes=CHECK,WASM64
-target triple = "wasm32-unknown-unknown"
define i1 @const_i1() {
; CHECK-LABEL: const_i1:
@@ -83,3 +83,19 @@ define i64 @const_i64() {
; CHECK-NEXT: return $pop0
ret i64 18446744073709551615
}
+
+
+define ptr @const_p0() {
+; WASM32-LABEL: const_p0:
+; WASM32: .functype const_p0 () -> (i32)
+; WASM32-NEXT: # %bb.0:
+; WASM32-NEXT: i32.const $push0=, 0
+; WASM32-NEXT: return $pop0
+;
+; WASM64-LABEL: const_p0:
+; WASM64: .functype const_p0 () -> (i64)
+; WASM64-NEXT: # %bb.0:
+; WASM64-NEXT: i64.const $push0=, 0
+; WASM64-NEXT: return $pop0
+ ret ptr null
+}
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/frame_index.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/frame_index.ll
new file mode 100644
index 0000000000000..998adf5ce5885
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/frame_index.ll
@@ -0,0 +1,35 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -O0 -mtriple=wasm32-unknown-unknown --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s --check-prefix=WASM32
+; RUN: llc < %s -O0 -mtriple=wasm64-unknown-unknown --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s --check-prefix=WASM64
+
+define ptr @frame_index() {
+; WASM32-LABEL: frame_index:
+; WASM32: .functype frame_index () -> (i32)
+; WASM32-NEXT: .local i32
+; WASM32-NEXT: # %bb.0:
+; WASM32-NEXT: global.get $push1=, __stack_pointer
+; WASM32-NEXT: i32.const $push2=, 16
+; WASM32-NEXT: i32.sub $push4=, $pop1, $pop2
+; WASM32-NEXT: local.set 0, $pop4
+; WASM32-NEXT: local.get $push5=, 0
+; WASM32-NEXT: i32.const $push3=, 14
+; WASM32-NEXT: i32.add $push0=, $pop5, $pop3
+; WASM32-NEXT: return $pop0
+;
+; WASM64-LABEL: frame_index:
+; WASM64: .functype frame_index () -> (i64)
+; WASM64-NEXT: .local i64
+; WASM64-NEXT: # %bb.0:
+; WASM64-NEXT: global.get $push1=, __stack_pointer
+; WASM64-NEXT: i64.const $push2=, 16
+; WASM64-NEXT: i64.sub $push4=, $pop1, $pop2
+; WASM64-NEXT: local.set 0, $pop4
+; WASM64-NEXT: local.get $push5=, 0
+; WASM64-NEXT: i64.const $push3=, 14
+; WASM64-NEXT: i64.add $push0=, $pop5, $pop3
+; WASM64-NEXT: return $pop0
+ %a = alloca i16
+ %b = alloca double
+
+ ret ptr %a
+}
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/global_value.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/global_value.ll
new file mode 100644
index 0000000000000..481f4e84a5967
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/global_value.ll
@@ -0,0 +1,127 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -O0 -mtriple=wasm32-unknown-unknown --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s --check-prefix=WASM32
+; RUN: llc < %s -O0 -mtriple=wasm64-unknown-unknown --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s --check-prefix=WASM64
+; RUN: llc < %s -O0 -mtriple=wasm32-unknown-unknown --global-isel -relocation-model=pic -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s --check-prefix=WASM32-PIC
+; RUN: llc < %s -O0 -mtriple=wasm64-unknown-unknown --global-isel -relocation-model=pic -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s --check-prefix=WASM64-PIC
+
+ at globl = global i32 0
+declare void @func()
+
+ at globl_local = dso_local global i32 0
+declare dso_local void @func_local()
+
+define ptr @global_value_globl() {
+; WASM32-LABEL: global_value_globl:
+; WASM32: .functype global_value_globl () -> (i32)
+; WASM32-NEXT: # %bb.0:
+; WASM32-NEXT: i32.const $push0=, globl
+; WASM32-NEXT: return $pop0
+;
+; WASM64-LABEL: global_value_globl:
+; WASM64: .functype global_value_globl () -> (i64)
+; WASM64-NEXT: # %bb.0:
+; WASM64-NEXT: i64.const $push0=, globl
+; WASM64-NEXT: return $pop0
+;
+; WASM32-PIC-LABEL: global_value_globl:
+; WASM32-PIC: .functype global_value_globl () -> (i32)
+; WASM32-PIC-NEXT: # %bb.0:
+; WASM32-PIC-NEXT: global.get $push0=, globl at GOT
+; WASM32-PIC-NEXT: return $pop0
+;
+; WASM64-PIC-LABEL: global_value_globl:
+; WASM64-PIC: .functype global_value_globl () -> (i64)
+; WASM64-PIC-NEXT: # %bb.0:
+; WASM64-PIC-NEXT: global.get $push0=, globl at GOT
+; WASM64-PIC-NEXT: return $pop0
+ ret ptr @globl
+}
+
+define ptr @global_value_func() {
+; WASM32-LABEL: global_value_func:
+; WASM32: .functype global_value_func () -> (i32)
+; WASM32-NEXT: # %bb.0:
+; WASM32-NEXT: i32.const $push0=, func
+; WASM32-NEXT: return $pop0
+;
+; WASM64-LABEL: global_value_func:
+; WASM64: .functype global_value_func () -> (i64)
+; WASM64-NEXT: # %bb.0:
+; WASM64-NEXT: i64.const $push0=, func
+; WASM64-NEXT: return $pop0
+;
+; WASM32-PIC-LABEL: global_value_func:
+; WASM32-PIC: .functype global_value_func () -> (i32)
+; WASM32-PIC-NEXT: # %bb.0:
+; WASM32-PIC-NEXT: global.get $push0=, func at GOT
+; WASM32-PIC-NEXT: return $pop0
+;
+; WASM64-PIC-LABEL: global_value_func:
+; WASM64-PIC: .functype global_value_func () -> (i64)
+; WASM64-PIC-NEXT: # %bb.0:
+; WASM64-PIC-NEXT: global.get $push0=, func at GOT
+; WASM64-PIC-NEXT: return $pop0
+ ret ptr @func
+}
+
+define ptr @global_value_globl_local() {
+; WASM32-LABEL: global_value_globl_local:
+; WASM32: .functype global_value_globl_local () -> (i32)
+; WASM32-NEXT: # %bb.0:
+; WASM32-NEXT: i32.const $push0=, globl_local
+; WASM32-NEXT: return $pop0
+;
+; WASM64-LABEL: global_value_globl_local:
+; WASM64: .functype global_value_globl_local () -> (i64)
+; WASM64-NEXT: # %bb.0:
+; WASM64-NEXT: i64.const $push0=, globl_local
+; WASM64-NEXT: return $pop0
+;
+; WASM32-PIC-LABEL: global_value_globl_local:
+; WASM32-PIC: .functype global_value_globl_local () -> (i32)
+; WASM32-PIC-NEXT: # %bb.0:
+; WASM32-PIC-NEXT: global.get $push1=, __memory_base
+; WASM32-PIC-NEXT: i32.const $push2=, globl_local at MBREL
+; WASM32-PIC-NEXT: i32.add $push0=, $pop1, $pop2
+; WASM32-PIC-NEXT: return $pop0
+;
+; WASM64-PIC-LABEL: global_value_globl_local:
+; WASM64-PIC: .functype global_value_globl_local () -> (i64)
+; WASM64-PIC-NEXT: # %bb.0:
+; WASM64-PIC-NEXT: global.get $push1=, __memory_base
+; WASM64-PIC-NEXT: i64.const $push2=, globl_local at MBREL
+; WASM64-PIC-NEXT: i64.add $push0=, $pop1, $pop2
+; WASM64-PIC-NEXT: return $pop0
+ ret ptr @globl_local
+}
+
+define ptr @global_value_func_local() {
+; WASM32-LABEL: global_value_func_local:
+; WASM32: .functype global_value_func_local () -> (i32)
+; WASM32-NEXT: # %bb.0:
+; WASM32-NEXT: i32.const $push0=, func_local
+; WASM32-NEXT: return $pop0
+;
+; WASM64-LABEL: global_value_func_local:
+; WASM64: .functype global_value_func_local () -> (i64)
+; WASM64-NEXT: # %bb.0:
+; WASM64-NEXT: i64.const $push0=, func_local
+; WASM64-NEXT: return $pop0
+;
+; WASM32-PIC-LABEL: global_value_func_local:
+; WASM32-PIC: .functype global_value_func_local () -> (i32)
+; WASM32-PIC-NEXT: # %bb.0:
+; WASM32-PIC-NEXT: global.get $push1=, __table_base
+; WASM32-PIC-NEXT: i32.const $push2=, func_local at TBREL
+; WASM32-PIC-NEXT: i32.add $push0=, $pop1, $pop2
+; WASM32-PIC-NEXT: return $pop0
+;
+; WASM64-PIC-LABEL: global_value_func_local:
+; WASM64-PIC: .functype global_value_func_local () -> (i64)
+; WASM64-PIC-NEXT: # %bb.0:
+; WASM64-PIC-NEXT: global.get $push1=, __table_base
+; WASM64-PIC-NEXT: i64.const $push2=, func_local at TBREL
+; WASM64-PIC-NEXT: i64.add $push0=, $pop1, $pop2
+; WASM64-PIC-NEXT: return $pop0
+ ret ptr @func_local
+}
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/implicit_def.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/implicit_def.mir
index 3498ff229ca81..3f5406f78ed74 100644
--- a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/implicit_def.mir
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/implicit_def.mir
@@ -1,5 +1,6 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
-# RUN: llc -mtriple=wasm32-unknown-unknown -run-pass=legalizer,regbankselect,instruction-select %s -o - | FileCheck %s
+# RUN: llc -mtriple=wasm32-unknown-unknown -run-pass=legalizer,regbankselect,instruction-select %s -o - | FileCheck %s --check-prefixes=CHECK,WASM32
+# RUN: llc -mtriple=wasm64-unknown-unknown -run-pass=legalizer,regbankselect,instruction-select %s -o - | FileCheck %s --check-prefixes=CHECK,WASM64
---
name: implicit_def_i8
@@ -98,3 +99,25 @@ body: |
%0:_(f64) = G_IMPLICIT_DEF
RETURN %0(f64), implicit-def $arguments
...
+
+---
+name: implicit_def_p0
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $arguments
+
+ ; WASM32-LABEL: name: implicit_def_p0
+ ; WASM32: liveins: $arguments
+ ; WASM32-NEXT: {{ $}}
+ ; WASM32-NEXT: [[DEF:%[0-9]+]]:i32 = IMPLICIT_DEF
+ ; WASM32-NEXT: RETURN [[DEF]], implicit-def $arguments
+ ;
+ ; WASM64-LABEL: name: implicit_def_p0
+ ; WASM64: liveins: $arguments
+ ; WASM64-NEXT: {{ $}}
+ ; WASM64-NEXT: [[DEF:%[0-9]+]]:i64 = IMPLICIT_DEF
+ ; WASM64-NEXT: RETURN [[DEF]], implicit-def $arguments
+ %0:_(p0) = G_IMPLICIT_DEF
+ RETURN %0(p0), implicit-def $arguments
+...
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/inttoptr.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/inttoptr.ll
new file mode 100644
index 0000000000000..8aaa8b400c7b5
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/inttoptr.ll
@@ -0,0 +1,79 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -O0 -mtriple=wasm32-unknown-unknown --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s --check-prefix=WASM32
+; RUN: llc < %s -O0 -mtriple=wasm64-unknown-unknown --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s --check-prefix=WASM64
+
+define ptr @inttoptr_i8(i8 %x) {
+; WASM32-LABEL: inttoptr_i8:
+; WASM32: .functype inttoptr_i8 (i32) -> (i32)
+; WASM32-NEXT: # %bb.0:
+; WASM32-NEXT: local.get $push2=, 0
+; WASM32-NEXT: i32.const $push1=, 255
+; WASM32-NEXT: i32.and $push0=, $pop2, $pop1
+; WASM32-NEXT: return $pop0
+;
+; WASM64-LABEL: inttoptr_i8:
+; WASM64: .functype inttoptr_i8 (i32) -> (i64)
+; WASM64-NEXT: # %bb.0:
+; WASM64-NEXT: local.get $push3=, 0
+; WASM64-NEXT: i64.extend_i32_u $push1=, $pop3
+; WASM64-NEXT: i64.const $push2=, 255
+; WASM64-NEXT: i64.and $push0=, $pop1, $pop2
+; WASM64-NEXT: return $pop0
+ %a = inttoptr i8 %x to ptr
+ ret ptr %a
+}
+
+define ptr @inttoptr_i16(i16 %x) {
+; WASM32-LABEL: inttoptr_i16:
+; WASM32: .functype inttoptr_i16 (i32) -> (i32)
+; WASM32-NEXT: # %bb.0:
+; WASM32-NEXT: local.get $push2=, 0
+; WASM32-NEXT: i32.const $push1=, 65535
+; WASM32-NEXT: i32.and $push0=, $pop2, $pop1
+; WASM32-NEXT: return $pop0
+;
+; WASM64-LABEL: inttoptr_i16:
+; WASM64: .functype inttoptr_i16 (i32) -> (i64)
+; WASM64-NEXT: # %bb.0:
+; WASM64-NEXT: local.get $push3=, 0
+; WASM64-NEXT: i64.extend_i32_u $push1=, $pop3
+; WASM64-NEXT: i64.const $push2=, 65535
+; WASM64-NEXT: i64.and $push0=, $pop1, $pop2
+; WASM64-NEXT: return $pop0
+ %a = inttoptr i16 %x to ptr
+ ret ptr %a
+}
+
+define ptr @inttoptr_i32(i32 %x) {
+; WASM32-LABEL: inttoptr_i32:
+; WASM32: .functype inttoptr_i32 (i32) -> (i32)
+; WASM32-NEXT: # %bb.0:
+; WASM32-NEXT: local.get $push0=, 0
+; WASM32-NEXT: return $pop0
+;
+; WASM64-LABEL: inttoptr_i32:
+; WASM64: .functype inttoptr_i32 (i32) -> (i64)
+; WASM64-NEXT: # %bb.0:
+; WASM64-NEXT: local.get $push1=, 0
+; WASM64-NEXT: i64.extend_i32_u $push0=, $pop1
+; WASM64-NEXT: return $pop0
+ %a = inttoptr i32 %x to ptr
+ ret ptr %a
+}
+
+define ptr @inttoptr_i64(i64 %x) {
+; WASM32-LABEL: inttoptr_i64:
+; WASM32: .functype inttoptr_i64 (i64) -> (i32)
+; WASM32-NEXT: # %bb.0:
+; WASM32-NEXT: local.get $push1=, 0
+; WASM32-NEXT: i32.wrap_i64 $push0=, $pop1
+; WASM32-NEXT: return $pop0
+;
+; WASM64-LABEL: inttoptr_i64:
+; WASM64: .functype inttoptr_i64 (i64) -> (i64)
+; WASM64-NEXT: # %bb.0:
+; WASM64-NEXT: local.get $push0=, 0
+; WASM64-NEXT: return $pop0
+ %a = inttoptr i64 %x to ptr
+ ret ptr %a
+}
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/load.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/load.ll
new file mode 100644
index 0000000000000..cfed662c7a333
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/load.ll
@@ -0,0 +1,198 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -O0 -mtriple=wasm32-unknown-unknown --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s --check-prefix=WASM32
+; RUN: llc < %s -O0 -mtriple=wasm64-unknown-unknown --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s --check-prefix=WASM64
+
+define i1 @load_i1(ptr %x) {
+; WASM32-LABEL: load_i1:
+; WASM32: .functype load_i1 (i32) -> (i32)
+; WASM32-NEXT: # %bb.0:
+; WASM32-NEXT: local.get $push1=, 0
+; WASM32-NEXT: i32.load8_u $push0=, 0($pop1)
+; WASM32-NEXT: return $pop0
+;
+; WASM64-LABEL: load_i1:
+; WASM64: .functype load_i1 (i64) -> (i32)
+; WASM64-NEXT: # %bb.0:
+; WASM64-NEXT: local.get $push1=, 0
+; WASM64-NEXT: i32.load8_u $push0=, 0($pop1)
+; WASM64-NEXT: return $pop0
+ %a = load i1, ptr %x
+ ret i1 %a
+}
+
+define i8 @load_i8(ptr %x) {
+; WASM32-LABEL: load_i8:
+; WASM32: .functype load_i8 (i32) -> (i32)
+; WASM32-NEXT: # %bb.0:
+; WASM32-NEXT: local.get $push1=, 0
+; WASM32-NEXT: i32.load8_u $push0=, 0($pop1)
+; WASM32-NEXT: return $pop0
+;
+; WASM64-LABEL: load_i8:
+; WASM64: .functype load_i8 (i64) -> (i32)
+; WASM64-NEXT: # %bb.0:
+; WASM64-NEXT: local.get $push1=, 0
+; WASM64-NEXT: i32.load8_u $push0=, 0($pop1)
+; WASM64-NEXT: return $pop0
+ %a = load i8, ptr %x
+ ret i8 %a
+}
+
+define i16 @load_i16(ptr %x) {
+; WASM32-LABEL: load_i16:
+; WASM32: .functype load_i16 (i32) -> (i32)
+; WASM32-NEXT: # %bb.0:
+; WASM32-NEXT: local.get $push1=, 0
+; WASM32-NEXT: i32.load16_u $push0=, 0($pop1)
+; WASM32-NEXT: return $pop0
+;
+; WASM64-LABEL: load_i16:
+; WASM64: .functype load_i16 (i64) -> (i32)
+; WASM64-NEXT: # %bb.0:
+; WASM64-NEXT: local.get $push1=, 0
+; WASM64-NEXT: i32.load16_u $push0=, 0($pop1)
+; WASM64-NEXT: return $pop0
+ %a = load i16, ptr %x
+ ret i16 %a
+}
+
+define i32 @load_i32(ptr %x) {
+; WASM32-LABEL: load_i32:
+; WASM32: .functype load_i32 (i32) -> (i32)
+; WASM32-NEXT: # %bb.0:
+; WASM32-NEXT: local.get $push1=, 0
+; WASM32-NEXT: i32.load $push0=, 0($pop1)
+; WASM32-NEXT: return $pop0
+;
+; WASM64-LABEL: load_i32:
+; WASM64: .functype load_i32 (i64) -> (i32)
+; WASM64-NEXT: # %bb.0:
+; WASM64-NEXT: local.get $push1=, 0
+; WASM64-NEXT: i32.load $push0=, 0($pop1)
+; WASM64-NEXT: return $pop0
+ %a = load i32, ptr %x
+ ret i32 %a
+}
+
+define i32 @load_i32_align1(ptr %x) {
+; WASM32-LABEL: load_i32_align1:
+; WASM32: .functype load_i32_align1 (i32) -> (i32)
+; WASM32-NEXT: # %bb.0:
+; WASM32-NEXT: local.get $push1=, 0
+; WASM32-NEXT: i32.load $push0=, 0($pop1):p2align=0
+; WASM32-NEXT: return $pop0
+;
+; WASM64-LABEL: load_i32_align1:
+; WASM64: .functype load_i32_align1 (i64) -> (i32)
+; WASM64-NEXT: # %bb.0:
+; WASM64-NEXT: local.get $push1=, 0
+; WASM64-NEXT: i32.load $push0=, 0($pop1):p2align=0
+; WASM64-NEXT: return $pop0
+ %a = load i32, ptr %x, align 1
+ ret i32 %a
+}
+
+define i48 @load_i48(ptr %x) {
+; WASM32-LABEL: load_i48:
+; WASM32: .functype load_i48 (i32) -> (i64)
+; WASM32-NEXT: # %bb.0:
+; WASM32-NEXT: local.get $push7=, 0
+; WASM32-NEXT: i64.load32_u $push0=, 0($pop7)
+; WASM32-NEXT: local.get $push8=, 0
+; WASM32-NEXT: i32.const $push1=, 4
+; WASM32-NEXT: i32.add $push2=, $pop8, $pop1
+; WASM32-NEXT: i64.load16_u $push3=, 0($pop2)
+; WASM32-NEXT: i64.const $push4=, 32
+; WASM32-NEXT: i64.shl $push5=, $pop3, $pop4
+; WASM32-NEXT: i64.or $push6=, $pop0, $pop5
+; WASM32-NEXT: return $pop6
+;
+; WASM64-LABEL: load_i48:
+; WASM64: .functype load_i48 (i64) -> (i64)
+; WASM64-NEXT: # %bb.0:
+; WASM64-NEXT: local.get $push7=, 0
+; WASM64-NEXT: i64.load32_u $push0=, 0($pop7)
+; WASM64-NEXT: local.get $push8=, 0
+; WASM64-NEXT: i64.const $push1=, 4
+; WASM64-NEXT: i64.add $push2=, $pop8, $pop1
+; WASM64-NEXT: i64.load16_u $push3=, 0($pop2)
+; WASM64-NEXT: i64.const $push4=, 32
+; WASM64-NEXT: i64.shl $push5=, $pop3, $pop4
+; WASM64-NEXT: i64.or $push6=, $pop0, $pop5
+; WASM64-NEXT: return $pop6
+ %a = load i48, ptr %x
+ ret i48 %a
+}
+
+define i64 @load_i64(ptr %x) {
+; WASM32-LABEL: load_i64:
+; WASM32: .functype load_i64 (i32) -> (i64)
+; WASM32-NEXT: # %bb.0:
+; WASM32-NEXT: local.get $push1=, 0
+; WASM32-NEXT: i64.load $push0=, 0($pop1)
+; WASM32-NEXT: return $pop0
+;
+; WASM64-LABEL: load_i64:
+; WASM64: .functype load_i64 (i64) -> (i64)
+; WASM64-NEXT: # %bb.0:
+; WASM64-NEXT: local.get $push1=, 0
+; WASM64-NEXT: i64.load $push0=, 0($pop1)
+; WASM64-NEXT: return $pop0
+ %a = load i64, ptr %x
+ ret i64 %a
+}
+
+
+define float @load_f32(ptr %x) {
+; WASM32-LABEL: load_f32:
+; WASM32: .functype load_f32 (i32) -> (f32)
+; WASM32-NEXT: # %bb.0:
+; WASM32-NEXT: local.get $push1=, 0
+; WASM32-NEXT: f32.load $push0=, 0($pop1)
+; WASM32-NEXT: return $pop0
+;
+; WASM64-LABEL: load_f32:
+; WASM64: .functype load_f32 (i64) -> (f32)
+; WASM64-NEXT: # %bb.0:
+; WASM64-NEXT: local.get $push1=, 0
+; WASM64-NEXT: f32.load $push0=, 0($pop1)
+; WASM64-NEXT: return $pop0
+ %a = load float, ptr %x
+ ret float %a
+}
+
+define double @load_f64(ptr %x) {
+; WASM32-LABEL: load_f64:
+; WASM32: .functype load_f64 (i32) -> (f64)
+; WASM32-NEXT: # %bb.0:
+; WASM32-NEXT: local.get $push1=, 0
+; WASM32-NEXT: f64.load $push0=, 0($pop1)
+; WASM32-NEXT: return $pop0
+;
+; WASM64-LABEL: load_f64:
+; WASM64: .functype load_f64 (i64) -> (f64)
+; WASM64-NEXT: # %bb.0:
+; WASM64-NEXT: local.get $push1=, 0
+; WASM64-NEXT: f64.load $push0=, 0($pop1)
+; WASM64-NEXT: return $pop0
+ %a = load double, ptr %x
+ ret double %a
+}
+
+define ptr @load_ptr(ptr %x) {
+; WASM32-LABEL: load_ptr:
+; WASM32: .functype load_ptr (i32) -> (i32)
+; WASM32-NEXT: # %bb.0:
+; WASM32-NEXT: local.get $push1=, 0
+; WASM32-NEXT: i32.load $push0=, 0($pop1)
+; WASM32-NEXT: return $pop0
+;
+; WASM64-LABEL: load_ptr:
+; WASM64: .functype load_ptr (i64) -> (i64)
+; WASM64-NEXT: # %bb.0:
+; WASM64-NEXT: local.get $push1=, 0
+; WASM64-NEXT: i64.load $push0=, 0($pop1)
+; WASM64-NEXT: return $pop0
+ %a = load ptr, ptr %x
+ ret ptr %a
+}
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/ptradd.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/ptradd.ll
new file mode 100644
index 0000000000000..44083d110c8e4
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/ptradd.ll
@@ -0,0 +1,91 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -O0 -mtriple=wasm32-unknown-unknown --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s --check-prefix=WASM32
+; RUN: llc < %s -O0 -mtriple=wasm64-unknown-unknown --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s --check-prefix=WASM64
+
+define ptr @ptradd_i8(ptr %x, i8 %y) {
+; WASM32-LABEL: ptradd_i8:
+; WASM32: .functype ptradd_i8 (i32, i32) -> (i32)
+; WASM32-NEXT: # %bb.0:
+; WASM32-NEXT: local.get $push3=, 0
+; WASM32-NEXT: local.get $push2=, 1
+; WASM32-NEXT: i32.extend8_s $push0=, $pop2
+; WASM32-NEXT: i32.add $push1=, $pop3, $pop0
+; WASM32-NEXT: return $pop1
+;
+; WASM64-LABEL: ptradd_i8:
+; WASM64: .functype ptradd_i8 (i64, i32) -> (i64)
+; WASM64-NEXT: # %bb.0:
+; WASM64-NEXT: local.get $push4=, 0
+; WASM64-NEXT: local.get $push3=, 1
+; WASM64-NEXT: i64.extend_i32_u $push2=, $pop3
+; WASM64-NEXT: i64.extend8_s $push0=, $pop2
+; WASM64-NEXT: i64.add $push1=, $pop4, $pop0
+; WASM64-NEXT: return $pop1
+ %a = getelementptr i8, ptr %x, i8 %y
+ ret ptr %a
+}
+
+define ptr @ptradd_i16(ptr %x, i16 %y) {
+; WASM32-LABEL: ptradd_i16:
+; WASM32: .functype ptradd_i16 (i32, i32) -> (i32)
+; WASM32-NEXT: # %bb.0:
+; WASM32-NEXT: local.get $push3=, 0
+; WASM32-NEXT: local.get $push2=, 1
+; WASM32-NEXT: i32.extend16_s $push0=, $pop2
+; WASM32-NEXT: i32.add $push1=, $pop3, $pop0
+; WASM32-NEXT: return $pop1
+;
+; WASM64-LABEL: ptradd_i16:
+; WASM64: .functype ptradd_i16 (i64, i32) -> (i64)
+; WASM64-NEXT: # %bb.0:
+; WASM64-NEXT: local.get $push4=, 0
+; WASM64-NEXT: local.get $push3=, 1
+; WASM64-NEXT: i64.extend_i32_u $push2=, $pop3
+; WASM64-NEXT: i64.extend16_s $push0=, $pop2
+; WASM64-NEXT: i64.add $push1=, $pop4, $pop0
+; WASM64-NEXT: return $pop1
+ %a = getelementptr i8, ptr %x, i16 %y
+ ret ptr %a
+}
+
+define ptr @ptradd_i32(ptr %x, i32 %y) {
+; WASM32-LABEL: ptradd_i32:
+; WASM32: .functype ptradd_i32 (i32, i32) -> (i32)
+; WASM32-NEXT: # %bb.0:
+; WASM32-NEXT: local.get $push2=, 0
+; WASM32-NEXT: local.get $push1=, 1
+; WASM32-NEXT: i32.add $push0=, $pop2, $pop1
+; WASM32-NEXT: return $pop0
+;
+; WASM64-LABEL: ptradd_i32:
+; WASM64: .functype ptradd_i32 (i64, i32) -> (i64)
+; WASM64-NEXT: # %bb.0:
+; WASM64-NEXT: local.get $push3=, 0
+; WASM64-NEXT: local.get $push2=, 1
+; WASM64-NEXT: i64.extend_i32_s $push0=, $pop2
+; WASM64-NEXT: i64.add $push1=, $pop3, $pop0
+; WASM64-NEXT: return $pop1
+ %a = getelementptr i8, ptr %x, i32 %y
+ ret ptr %a
+}
+
+define ptr @ptradd_i64(ptr %x, i64 %y) {
+; WASM32-LABEL: ptradd_i64:
+; WASM32: .functype ptradd_i64 (i32, i64) -> (i32)
+; WASM32-NEXT: # %bb.0:
+; WASM32-NEXT: local.get $push3=, 0
+; WASM32-NEXT: local.get $push2=, 1
+; WASM32-NEXT: i32.wrap_i64 $push0=, $pop2
+; WASM32-NEXT: i32.add $push1=, $pop3, $pop0
+; WASM32-NEXT: return $pop1
+;
+; WASM64-LABEL: ptradd_i64:
+; WASM64: .functype ptradd_i64 (i64, i64) -> (i64)
+; WASM64-NEXT: # %bb.0:
+; WASM64-NEXT: local.get $push2=, 0
+; WASM64-NEXT: local.get $push1=, 1
+; WASM64-NEXT: i64.add $push0=, $pop2, $pop1
+; WASM64-NEXT: return $pop0
+ %a = getelementptr i8, ptr %x, i64 %y
+ ret ptr %a
+}
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/ptrmask.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/ptrmask.ll
new file mode 100644
index 0000000000000..ab4e4de2ad79d
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/ptrmask.ll
@@ -0,0 +1,17 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: sed 's/iX/i32/g' < %s > %t && llc < %t -O0 -mtriple=wasm32-unknown-unknown --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %t
+; RUN: sed 's/iX/i64/g' < %s > %t && llc < %t -O0 -mtriple=wasm64-unknown-unknown --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %t
+
+declare ptr @llvm.ptrmask(ptr, iX)
+
+define ptr @ptrmask(ptr %x, iX %y) {
+; CHECK-LABEL: ptrmask:
+; CHECK: .functype ptrmask (iX, iX) -> (iX)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: iX.and $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = call ptr @llvm.ptrmask(ptr %x, iX %y)
+ ret ptr %a
+}
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/ptrmask_wasm32.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/ptrmask_wasm32.mir
new file mode 100644
index 0000000000000..5ed664d6de902
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/ptrmask_wasm32.mir
@@ -0,0 +1,85 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -mtriple=wasm32-unknown-unknown -run-pass=legalizer,regbankselect,instruction-select %s -o - | FileCheck %s --check-prefixes=CHECK
+
+---
+name: ptrmask_i8
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $arguments
+ ; CHECK-LABEL: name: ptrmask_i8
+ ; CHECK: liveins: $arguments
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32 = ARGUMENT_i32 0, implicit $arguments
+ ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32 = ARGUMENT_i32 1, implicit $arguments
+ ; CHECK-NEXT: [[CONST_I32_:%[0-9]+]]:i32 = CONST_I32 255, implicit-def dead $arguments
+ ; CHECK-NEXT: [[AND_I32_:%[0-9]+]]:i32 = AND_I32 [[ARGUMENT_i32_1]], [[CONST_I32_]], implicit-def dead $arguments
+ ; CHECK-NEXT: [[AND_I32_1:%[0-9]+]]:i32 = AND_I32 [[ARGUMENT_i32_]], [[AND_I32_]]
+ ; CHECK-NEXT: RETURN [[AND_I32_1]], implicit-def $arguments
+ %0:i32(p0) = ARGUMENT_i32 0, implicit $arguments
+ %2:i32(i32) = ARGUMENT_i32 1, implicit $arguments
+ %1:_(i8) = G_TRUNC %2(i32)
+ %3:_(p0) = G_PTRMASK %0, %1(i8)
+ RETURN %3(p0), implicit-def $arguments
+...
+
+---
+name: ptrmask_i16
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $arguments
+ ; CHECK-LABEL: name: ptrmask_i16
+ ; CHECK: liveins: $arguments
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32 = ARGUMENT_i32 0, implicit $arguments
+ ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32 = ARGUMENT_i32 1, implicit $arguments
+ ; CHECK-NEXT: [[CONST_I32_:%[0-9]+]]:i32 = CONST_I32 65535, implicit-def dead $arguments
+ ; CHECK-NEXT: [[AND_I32_:%[0-9]+]]:i32 = AND_I32 [[ARGUMENT_i32_1]], [[CONST_I32_]], implicit-def dead $arguments
+ ; CHECK-NEXT: [[AND_I32_1:%[0-9]+]]:i32 = AND_I32 [[ARGUMENT_i32_]], [[AND_I32_]]
+ ; CHECK-NEXT: RETURN [[AND_I32_1]], implicit-def $arguments
+ %0:i32(p0) = ARGUMENT_i32 0, implicit $arguments
+ %2:i32(i32) = ARGUMENT_i32 1, implicit $arguments
+ %1:_(i16) = G_TRUNC %2(i32)
+ %3:_(p0) = G_PTRMASK %0, %1(i16)
+ RETURN %3(p0), implicit-def $arguments
+...
+
+---
+name: ptrmask_i32
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $arguments
+ ; CHECK-LABEL: name: ptrmask_i32
+ ; CHECK: liveins: $arguments
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32 = ARGUMENT_i32 0, implicit $arguments
+ ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32 = ARGUMENT_i32 1, implicit $arguments
+ ; CHECK-NEXT: [[AND_I32_:%[0-9]+]]:i32 = AND_I32 [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]]
+ ; CHECK-NEXT: RETURN [[AND_I32_]], implicit-def $arguments
+ %0:i32(p0) = ARGUMENT_i32 0, implicit $arguments
+ %1:i32(i32) = ARGUMENT_i32 1, implicit $arguments
+ %2:_(p0) = G_PTRMASK %0, %1(i32)
+ RETURN %2(p0), implicit-def $arguments
+...
+
+---
+name: ptrmask_i64
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $arguments
+ ; CHECK-LABEL: name: ptrmask_i64
+ ; CHECK: liveins: $arguments
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32 = ARGUMENT_i32 0, implicit $arguments
+ ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64 = ARGUMENT_i64 1, implicit $arguments
+ ; CHECK-NEXT: [[I32_WRAP_I64_:%[0-9]+]]:i32 = I32_WRAP_I64 [[ARGUMENT_i64_]], implicit-def dead $arguments
+ ; CHECK-NEXT: [[AND_I32_:%[0-9]+]]:i32 = AND_I32 [[ARGUMENT_i32_]], [[I32_WRAP_I64_]]
+ ; CHECK-NEXT: RETURN [[AND_I32_]], implicit-def $arguments
+ %0:i32(p0) = ARGUMENT_i32 0, implicit $arguments
+ %1:i64(i64) = ARGUMENT_i64 1, implicit $arguments
+ %2:_(p0) = G_PTRMASK %0, %1(i64)
+ RETURN %2(p0), implicit-def $arguments
+...
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/ptrmask_wasm64.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/ptrmask_wasm64.mir
new file mode 100644
index 0000000000000..3106f7bd9670b
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/ptrmask_wasm64.mir
@@ -0,0 +1,87 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -mtriple=wasm64-unknown-unknown -run-pass=legalizer,regbankselect,instruction-select %s -o - | FileCheck %s --check-prefixes=CHECK
+
+---
+name: ptrmask_i8
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $arguments
+ ; CHECK-LABEL: name: ptrmask_i8
+ ; CHECK: liveins: $arguments
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64 = ARGUMENT_i64 0, implicit $arguments
+ ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32 = ARGUMENT_i32 1, implicit $arguments
+ ; CHECK-NEXT: [[I64_EXTEND_U_I32_:%[0-9]+]]:i64 = I64_EXTEND_U_I32 [[ARGUMENT_i32_]], implicit-def dead $arguments
+ ; CHECK-NEXT: [[CONST_I64_:%[0-9]+]]:i64 = CONST_I64 255, implicit-def dead $arguments
+ ; CHECK-NEXT: [[AND_I64_:%[0-9]+]]:i64 = AND_I64 [[I64_EXTEND_U_I32_]], [[CONST_I64_]], implicit-def dead $arguments
+ ; CHECK-NEXT: [[AND_I64_1:%[0-9]+]]:i64 = AND_I64 [[ARGUMENT_i64_]], [[AND_I64_]]
+ ; CHECK-NEXT: RETURN [[AND_I64_1]], implicit-def $arguments
+ %0:i64(p0) = ARGUMENT_i64 0, implicit $arguments
+ %2:i32(i32) = ARGUMENT_i32 1, implicit $arguments
+ %1:_(i8) = G_TRUNC %2(i32)
+ %3:_(p0) = G_PTRMASK %0, %1(i8)
+ RETURN %3(p0), implicit-def $arguments
+...
+
+---
+name: ptrmask_i16
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $arguments
+ ; CHECK-LABEL: name: ptrmask_i16
+ ; CHECK: liveins: $arguments
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64 = ARGUMENT_i64 0, implicit $arguments
+ ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32 = ARGUMENT_i32 1, implicit $arguments
+ ; CHECK-NEXT: [[I64_EXTEND_U_I32_:%[0-9]+]]:i64 = I64_EXTEND_U_I32 [[ARGUMENT_i32_]], implicit-def dead $arguments
+ ; CHECK-NEXT: [[CONST_I64_:%[0-9]+]]:i64 = CONST_I64 65535, implicit-def dead $arguments
+ ; CHECK-NEXT: [[AND_I64_:%[0-9]+]]:i64 = AND_I64 [[I64_EXTEND_U_I32_]], [[CONST_I64_]], implicit-def dead $arguments
+ ; CHECK-NEXT: [[AND_I64_1:%[0-9]+]]:i64 = AND_I64 [[ARGUMENT_i64_]], [[AND_I64_]]
+ ; CHECK-NEXT: RETURN [[AND_I64_1]], implicit-def $arguments
+ %0:i64(p0) = ARGUMENT_i64 0, implicit $arguments
+ %2:i32(i32) = ARGUMENT_i32 1, implicit $arguments
+ %1:_(i16) = G_TRUNC %2(i32)
+ %3:_(p0) = G_PTRMASK %0, %1(i16)
+ RETURN %3(p0), implicit-def $arguments
+...
+
+---
+name: ptrmask_i32
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $arguments
+ ; CHECK-LABEL: name: ptrmask_i32
+ ; CHECK: liveins: $arguments
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64 = ARGUMENT_i64 0, implicit $arguments
+ ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32 = ARGUMENT_i32 1, implicit $arguments
+ ; CHECK-NEXT: [[I64_EXTEND_U_I32_:%[0-9]+]]:i64 = I64_EXTEND_U_I32 [[ARGUMENT_i32_]], implicit-def dead $arguments
+ ; CHECK-NEXT: [[AND_I64_:%[0-9]+]]:i64 = AND_I64 [[ARGUMENT_i64_]], [[I64_EXTEND_U_I32_]]
+ ; CHECK-NEXT: RETURN [[AND_I64_]], implicit-def $arguments
+ %0:i64(p0) = ARGUMENT_i64 0, implicit $arguments
+ %1:i32(i32) = ARGUMENT_i32 1, implicit $arguments
+ %2:_(p0) = G_PTRMASK %0, %1(i32)
+ RETURN %2(p0), implicit-def $arguments
+...
+
+---
+name: ptrmask_i64
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $arguments
+ ; CHECK-LABEL: name: ptrmask_i64
+ ; CHECK: liveins: $arguments
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64 = ARGUMENT_i64 0, implicit $arguments
+ ; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64 = ARGUMENT_i64 1, implicit $arguments
+ ; CHECK-NEXT: [[AND_I64_:%[0-9]+]]:i64 = AND_I64 [[ARGUMENT_i64_]], [[ARGUMENT_i64_1]]
+ ; CHECK-NEXT: RETURN [[AND_I64_]], implicit-def $arguments
+ %0:i64(p0) = ARGUMENT_i64 0, implicit $arguments
+ %1:i64(i64) = ARGUMENT_i64 1, implicit $arguments
+ %2:_(p0) = G_PTRMASK %0, %1(i64)
+ RETURN %2(p0), implicit-def $arguments
+...
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/ptrtoint.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/ptrtoint.ll
new file mode 100644
index 0000000000000..fe90bfe260f75
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/ptrtoint.ll
@@ -0,0 +1,71 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -O0 -mtriple=wasm32-unknown-unknown --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s --check-prefix=WASM32
+; RUN: llc < %s -O0 -mtriple=wasm64-unknown-unknown --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s --check-prefix=WASM64
+
+define i8 @ptrtoint_i8(ptr %x) {
+; WASM32-LABEL: ptrtoint_i8:
+; WASM32: .functype ptrtoint_i8 (i32) -> (i32)
+; WASM32-NEXT: # %bb.0:
+; WASM32-NEXT: local.get $push0=, 0
+; WASM32-NEXT: return $pop0
+;
+; WASM64-LABEL: ptrtoint_i8:
+; WASM64: .functype ptrtoint_i8 (i64) -> (i32)
+; WASM64-NEXT: # %bb.0:
+; WASM64-NEXT: local.get $push1=, 0
+; WASM64-NEXT: i32.wrap_i64 $push0=, $pop1
+; WASM64-NEXT: return $pop0
+ %a = ptrtoint ptr %x to i8
+ ret i8 %a
+}
+
+define i16 @ptrtoint_i16(ptr %x) {
+; WASM32-LABEL: ptrtoint_i16:
+; WASM32: .functype ptrtoint_i16 (i32) -> (i32)
+; WASM32-NEXT: # %bb.0:
+; WASM32-NEXT: local.get $push0=, 0
+; WASM32-NEXT: return $pop0
+;
+; WASM64-LABEL: ptrtoint_i16:
+; WASM64: .functype ptrtoint_i16 (i64) -> (i32)
+; WASM64-NEXT: # %bb.0:
+; WASM64-NEXT: local.get $push1=, 0
+; WASM64-NEXT: i32.wrap_i64 $push0=, $pop1
+; WASM64-NEXT: return $pop0
+ %a = ptrtoint ptr %x to i16
+ ret i16 %a
+}
+
+define i32 @ptrtoint_i32(ptr %x) {
+; WASM32-LABEL: ptrtoint_i32:
+; WASM32: .functype ptrtoint_i32 (i32) -> (i32)
+; WASM32-NEXT: # %bb.0:
+; WASM32-NEXT: local.get $push0=, 0
+; WASM32-NEXT: return $pop0
+;
+; WASM64-LABEL: ptrtoint_i32:
+; WASM64: .functype ptrtoint_i32 (i64) -> (i32)
+; WASM64-NEXT: # %bb.0:
+; WASM64-NEXT: local.get $push1=, 0
+; WASM64-NEXT: i32.wrap_i64 $push0=, $pop1
+; WASM64-NEXT: return $pop0
+ %a = ptrtoint ptr %x to i32
+ ret i32 %a
+}
+
+define i64 @ptrtoint_i64(ptr %x) {
+; WASM32-LABEL: ptrtoint_i64:
+; WASM32: .functype ptrtoint_i64 (i32) -> (i64)
+; WASM32-NEXT: # %bb.0:
+; WASM32-NEXT: local.get $push1=, 0
+; WASM32-NEXT: i64.extend_i32_u $push0=, $pop1
+; WASM32-NEXT: return $pop0
+;
+; WASM64-LABEL: ptrtoint_i64:
+; WASM64: .functype ptrtoint_i64 (i64) -> (i64)
+; WASM64-NEXT: # %bb.0:
+; WASM64-NEXT: local.get $push0=, 0
+; WASM64-NEXT: return $pop0
+ %a = ptrtoint ptr %x to i64
+ ret i64 %a
+}
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/sextload.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/sextload.mir
new file mode 100644
index 0000000000000..273f501048f2a
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/sextload.mir
@@ -0,0 +1,220 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -mtriple=wasm32-unknown-unknown -run-pass=legalizer,regbankselect,instruction-select %s -o - | FileCheck %s --check-prefixes=WASM32
+# RUN: llc -mtriple=wasm64-unknown-unknown -run-pass=legalizer,regbankselect,instruction-select %s -o - | FileCheck %s --check-prefixes=WASM64
+
+---
+name: sextload_i1_i32
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $arguments
+
+ ; WASM32-LABEL: name: sextload_i1_i32
+ ; WASM32: liveins: $arguments
+ ; WASM32-NEXT: {{ $}}
+ ; WASM32-NEXT: [[DEF:%[0-9]+]]:i32 = IMPLICIT_DEF
+ ; WASM32-NEXT: [[LOAD8_U_I32_A32_:%[0-9]+]]:i32 = LOAD8_U_I32_A32 0, 0, [[DEF]], implicit-def dead $arguments :: (load (i8))
+ ; WASM32-NEXT: [[CONST_I32_:%[0-9]+]]:i32 = CONST_I32 31, implicit-def dead $arguments
+ ; WASM32-NEXT: [[SHL_I32_:%[0-9]+]]:i32 = SHL_I32 [[LOAD8_U_I32_A32_]], [[CONST_I32_]], implicit-def dead $arguments
+ ; WASM32-NEXT: [[SHR_S_I32_:%[0-9]+]]:i32 = SHR_S_I32 [[SHL_I32_]], [[CONST_I32_]], implicit-def dead $arguments
+ ; WASM32-NEXT: RETURN [[SHR_S_I32_]], implicit-def $arguments
+ ;
+ ; WASM64-LABEL: name: sextload_i1_i32
+ ; WASM64: liveins: $arguments
+ ; WASM64-NEXT: {{ $}}
+ ; WASM64-NEXT: [[DEF:%[0-9]+]]:i64 = IMPLICIT_DEF
+ ; WASM64-NEXT: [[LOAD8_U_I32_A64_:%[0-9]+]]:i32 = LOAD8_U_I32_A64 0, 0, [[DEF]], implicit-def dead $arguments :: (load (i8))
+ ; WASM64-NEXT: [[CONST_I32_:%[0-9]+]]:i32 = CONST_I32 31, implicit-def dead $arguments
+ ; WASM64-NEXT: [[SHL_I32_:%[0-9]+]]:i32 = SHL_I32 [[LOAD8_U_I32_A64_]], [[CONST_I32_]], implicit-def dead $arguments
+ ; WASM64-NEXT: [[SHR_S_I32_:%[0-9]+]]:i32 = SHR_S_I32 [[SHL_I32_]], [[CONST_I32_]], implicit-def dead $arguments
+ ; WASM64-NEXT: RETURN [[SHR_S_I32_]], implicit-def $arguments
+ %0:_(p0) = G_IMPLICIT_DEF
+ %1:_(i32) = G_SEXTLOAD %0(p0) :: (load (i1))
+ RETURN %1(i32), implicit-def $arguments
+...
+---
+name: sextload_i1_i64
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $arguments
+
+ ; WASM32-LABEL: name: sextload_i1_i64
+ ; WASM32: liveins: $arguments
+ ; WASM32-NEXT: {{ $}}
+ ; WASM32-NEXT: [[DEF:%[0-9]+]]:i32 = IMPLICIT_DEF
+ ; WASM32-NEXT: [[LOAD8_U_I64_A32_:%[0-9]+]]:i64 = LOAD8_U_I64_A32 0, 0, [[DEF]], implicit-def dead $arguments :: (load (i8))
+ ; WASM32-NEXT: [[CONST_I64_:%[0-9]+]]:i64 = CONST_I64 63, implicit-def dead $arguments
+ ; WASM32-NEXT: [[SHL_I64_:%[0-9]+]]:i64 = SHL_I64 [[LOAD8_U_I64_A32_]], [[CONST_I64_]], implicit-def dead $arguments
+ ; WASM32-NEXT: [[SHR_S_I64_:%[0-9]+]]:i64 = SHR_S_I64 [[SHL_I64_]], [[CONST_I64_]], implicit-def dead $arguments
+ ; WASM32-NEXT: RETURN [[SHR_S_I64_]], implicit-def $arguments
+ ;
+ ; WASM64-LABEL: name: sextload_i1_i64
+ ; WASM64: liveins: $arguments
+ ; WASM64-NEXT: {{ $}}
+ ; WASM64-NEXT: [[DEF:%[0-9]+]]:i64 = IMPLICIT_DEF
+ ; WASM64-NEXT: [[LOAD8_U_I64_A64_:%[0-9]+]]:i64 = LOAD8_U_I64_A64 0, 0, [[DEF]], implicit-def dead $arguments :: (load (i8))
+ ; WASM64-NEXT: [[CONST_I64_:%[0-9]+]]:i64 = CONST_I64 63, implicit-def dead $arguments
+ ; WASM64-NEXT: [[SHL_I64_:%[0-9]+]]:i64 = SHL_I64 [[LOAD8_U_I64_A64_]], [[CONST_I64_]], implicit-def dead $arguments
+ ; WASM64-NEXT: [[SHR_S_I64_:%[0-9]+]]:i64 = SHR_S_I64 [[SHL_I64_]], [[CONST_I64_]], implicit-def dead $arguments
+ ; WASM64-NEXT: RETURN [[SHR_S_I64_]], implicit-def $arguments
+ %0:_(p0) = G_IMPLICIT_DEF
+ %1:_(i64) = G_SEXTLOAD %0(p0) :: (load (i1))
+ RETURN %1(i64), implicit-def $arguments
+...
+---
+name: sextload_i8_i32
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $arguments
+
+ ; WASM32-LABEL: name: sextload_i8_i32
+ ; WASM32: liveins: $arguments
+ ; WASM32-NEXT: {{ $}}
+ ; WASM32-NEXT: [[DEF:%[0-9]+]]:i32 = IMPLICIT_DEF
+ ; WASM32-NEXT: [[LOAD8_S_I32_A32_:%[0-9]+]]:i32 = LOAD8_S_I32_A32 0, 0, [[DEF]], implicit-def dead $arguments :: (load (i8))
+ ; WASM32-NEXT: RETURN [[LOAD8_S_I32_A32_]], implicit-def $arguments
+ ;
+ ; WASM64-LABEL: name: sextload_i8_i32
+ ; WASM64: liveins: $arguments
+ ; WASM64-NEXT: {{ $}}
+ ; WASM64-NEXT: [[DEF:%[0-9]+]]:i64 = IMPLICIT_DEF
+ ; WASM64-NEXT: [[LOAD8_S_I32_A64_:%[0-9]+]]:i32 = LOAD8_S_I32_A64 0, 0, [[DEF]], implicit-def dead $arguments :: (load (i8))
+ ; WASM64-NEXT: RETURN [[LOAD8_S_I32_A64_]], implicit-def $arguments
+ %0:_(p0) = G_IMPLICIT_DEF
+ %1:_(i32) = G_SEXTLOAD %0(p0) :: (load (i8))
+ RETURN %1(i32), implicit-def $arguments
+...
+---
+name: sextload_i8_i64
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $arguments
+
+ ; WASM32-LABEL: name: sextload_i8_i64
+ ; WASM32: liveins: $arguments
+ ; WASM32-NEXT: {{ $}}
+ ; WASM32-NEXT: [[DEF:%[0-9]+]]:i32 = IMPLICIT_DEF
+ ; WASM32-NEXT: [[LOAD8_S_I64_A32_:%[0-9]+]]:i64 = LOAD8_S_I64_A32 0, 0, [[DEF]], implicit-def dead $arguments :: (load (i8))
+ ; WASM32-NEXT: RETURN [[LOAD8_S_I64_A32_]], implicit-def $arguments
+ ;
+ ; WASM64-LABEL: name: sextload_i8_i64
+ ; WASM64: liveins: $arguments
+ ; WASM64-NEXT: {{ $}}
+ ; WASM64-NEXT: [[DEF:%[0-9]+]]:i64 = IMPLICIT_DEF
+ ; WASM64-NEXT: [[LOAD8_S_I64_A64_:%[0-9]+]]:i64 = LOAD8_S_I64_A64 0, 0, [[DEF]], implicit-def dead $arguments :: (load (i8))
+ ; WASM64-NEXT: RETURN [[LOAD8_S_I64_A64_]], implicit-def $arguments
+ %0:_(p0) = G_IMPLICIT_DEF
+ %1:_(i64) = G_SEXTLOAD %0(p0) :: (load (i8))
+ RETURN %1(i64), implicit-def $arguments
+...
+---
+name: sextload_i16_i32
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $arguments
+
+ ; WASM32-LABEL: name: sextload_i16_i32
+ ; WASM32: liveins: $arguments
+ ; WASM32-NEXT: {{ $}}
+ ; WASM32-NEXT: [[DEF:%[0-9]+]]:i32 = IMPLICIT_DEF
+ ; WASM32-NEXT: [[LOAD16_S_I32_A32_:%[0-9]+]]:i32 = LOAD16_S_I32_A32 0, 0, [[DEF]], implicit-def dead $arguments :: (load (i16))
+ ; WASM32-NEXT: RETURN [[LOAD16_S_I32_A32_]], implicit-def $arguments
+ ;
+ ; WASM64-LABEL: name: sextload_i16_i32
+ ; WASM64: liveins: $arguments
+ ; WASM64-NEXT: {{ $}}
+ ; WASM64-NEXT: [[DEF:%[0-9]+]]:i64 = IMPLICIT_DEF
+ ; WASM64-NEXT: [[LOAD16_S_I32_A64_:%[0-9]+]]:i32 = LOAD16_S_I32_A64 0, 0, [[DEF]], implicit-def dead $arguments :: (load (i16))
+ ; WASM64-NEXT: RETURN [[LOAD16_S_I32_A64_]], implicit-def $arguments
+ %0:_(p0) = G_IMPLICIT_DEF
+ %1:_(i32) = G_SEXTLOAD %0(p0) :: (load (i16))
+ RETURN %1(i32), implicit-def $arguments
+...
+---
+name: sextload_i16_i64
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $arguments
+
+ ; WASM32-LABEL: name: sextload_i16_i64
+ ; WASM32: liveins: $arguments
+ ; WASM32-NEXT: {{ $}}
+ ; WASM32-NEXT: [[DEF:%[0-9]+]]:i32 = IMPLICIT_DEF
+ ; WASM32-NEXT: [[LOAD16_S_I64_A32_:%[0-9]+]]:i64 = LOAD16_S_I64_A32 0, 0, [[DEF]], implicit-def dead $arguments :: (load (i16))
+ ; WASM32-NEXT: RETURN [[LOAD16_S_I64_A32_]], implicit-def $arguments
+ ;
+ ; WASM64-LABEL: name: sextload_i16_i64
+ ; WASM64: liveins: $arguments
+ ; WASM64-NEXT: {{ $}}
+ ; WASM64-NEXT: [[DEF:%[0-9]+]]:i64 = IMPLICIT_DEF
+ ; WASM64-NEXT: [[LOAD16_S_I64_A64_:%[0-9]+]]:i64 = LOAD16_S_I64_A64 0, 0, [[DEF]], implicit-def dead $arguments :: (load (i16))
+ ; WASM64-NEXT: RETURN [[LOAD16_S_I64_A64_]], implicit-def $arguments
+ %0:_(p0) = G_IMPLICIT_DEF
+ %1:_(i64) = G_SEXTLOAD %0(p0) :: (load (i16))
+ RETURN %1(i64), implicit-def $arguments
+...
+---
+name: sextload_i32_i64
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $arguments
+
+ ; WASM32-LABEL: name: sextload_i32_i64
+ ; WASM32: liveins: $arguments
+ ; WASM32-NEXT: {{ $}}
+ ; WASM32-NEXT: [[DEF:%[0-9]+]]:i32 = IMPLICIT_DEF
+ ; WASM32-NEXT: [[LOAD32_S_I64_A32_:%[0-9]+]]:i64 = LOAD32_S_I64_A32 0, 0, [[DEF]], implicit-def dead $arguments :: (load (i32))
+ ; WASM32-NEXT: RETURN [[LOAD32_S_I64_A32_]], implicit-def $arguments
+ ;
+ ; WASM64-LABEL: name: sextload_i32_i64
+ ; WASM64: liveins: $arguments
+ ; WASM64-NEXT: {{ $}}
+ ; WASM64-NEXT: [[DEF:%[0-9]+]]:i64 = IMPLICIT_DEF
+ ; WASM64-NEXT: [[LOAD32_S_I64_A64_:%[0-9]+]]:i64 = LOAD32_S_I64_A64 0, 0, [[DEF]], implicit-def dead $arguments :: (load (i32))
+ ; WASM64-NEXT: RETURN [[LOAD32_S_I64_A64_]], implicit-def $arguments
+ %0:_(p0) = G_IMPLICIT_DEF
+ %1:_(i64) = G_SEXTLOAD %0(p0) :: (load (i32))
+ RETURN %1(i64), implicit-def $arguments
+...
+---
+name: sextload_i48_i64
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $arguments
+
+ ; WASM32-LABEL: name: sextload_i48_i64
+ ; WASM32: liveins: $arguments
+ ; WASM32-NEXT: {{ $}}
+ ; WASM32-NEXT: [[DEF:%[0-9]+]]:i32 = IMPLICIT_DEF
+ ; WASM32-NEXT: [[LOAD32_U_I64_A32_:%[0-9]+]]:i64 = LOAD32_U_I64_A32 0, 0, [[DEF]], implicit-def dead $arguments :: (load (s32), align 8)
+ ; WASM32-NEXT: [[CONST_I32_:%[0-9]+]]:i32 = CONST_I32 4, implicit-def dead $arguments
+ ; WASM32-NEXT: [[ADD_I32_:%[0-9]+]]:i32 = nuw inbounds ADD_I32 [[DEF]], [[CONST_I32_]], implicit-def dead $arguments
+ ; WASM32-NEXT: [[LOAD16_S_I64_A32_:%[0-9]+]]:i64 = LOAD16_S_I64_A32 0, 0, [[ADD_I32_]], implicit-def dead $arguments :: (load (s16) from unknown-address + 4, align 4)
+ ; WASM32-NEXT: [[CONST_I64_:%[0-9]+]]:i64 = CONST_I64 32, implicit-def dead $arguments
+ ; WASM32-NEXT: [[SHL_I64_:%[0-9]+]]:i64 = SHL_I64 [[LOAD16_S_I64_A32_]], [[CONST_I64_]], implicit-def dead $arguments
+ ; WASM32-NEXT: [[OR_I64_:%[0-9]+]]:i64 = OR_I64 [[SHL_I64_]], [[LOAD32_U_I64_A32_]], implicit-def dead $arguments
+ ; WASM32-NEXT: RETURN [[OR_I64_]], implicit-def $arguments
+ ;
+ ; WASM64-LABEL: name: sextload_i48_i64
+ ; WASM64: liveins: $arguments
+ ; WASM64-NEXT: {{ $}}
+ ; WASM64-NEXT: [[DEF:%[0-9]+]]:i64 = IMPLICIT_DEF
+ ; WASM64-NEXT: [[LOAD32_U_I64_A64_:%[0-9]+]]:i64 = LOAD32_U_I64_A64 0, 0, [[DEF]], implicit-def dead $arguments :: (load (s32), align 8)
+ ; WASM64-NEXT: [[CONST_I64_:%[0-9]+]]:i64 = CONST_I64 4, implicit-def dead $arguments
+ ; WASM64-NEXT: [[ADD_I64_:%[0-9]+]]:i64 = nuw inbounds ADD_I64 [[DEF]], [[CONST_I64_]], implicit-def dead $arguments
+ ; WASM64-NEXT: [[LOAD16_S_I64_A64_:%[0-9]+]]:i64 = LOAD16_S_I64_A64 0, 0, [[ADD_I64_]], implicit-def dead $arguments :: (load (s16) from unknown-address + 4, align 4)
+ ; WASM64-NEXT: [[CONST_I64_1:%[0-9]+]]:i64 = CONST_I64 32, implicit-def dead $arguments
+ ; WASM64-NEXT: [[SHL_I64_:%[0-9]+]]:i64 = SHL_I64 [[LOAD16_S_I64_A64_]], [[CONST_I64_1]], implicit-def dead $arguments
+ ; WASM64-NEXT: [[OR_I64_:%[0-9]+]]:i64 = OR_I64 [[SHL_I64_]], [[LOAD32_U_I64_A64_]], implicit-def dead $arguments
+ ; WASM64-NEXT: RETURN [[OR_I64_]], implicit-def $arguments
+ %0:_(p0) = G_IMPLICIT_DEF
+ %1:_(i64) = G_SEXTLOAD %0(p0) :: (load (i48))
+ RETURN %1(i64), implicit-def $arguments
+...
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/store.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/store.ll
new file mode 100644
index 0000000000000..2bfc59dfe37ee
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/store.ll
@@ -0,0 +1,236 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -O0 -mtriple=wasm32-unknown-unknown --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s --check-prefix=WASM32
+; RUN: llc < %s -O0 -mtriple=wasm64-unknown-unknown --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s --check-prefix=WASM64
+
+define void @store_i1(ptr %x, i1 %y) {
+; WASM32-LABEL: store_i1:
+; WASM32: .functype store_i1 (i32, i32) -> ()
+; WASM32-NEXT: # %bb.0:
+; WASM32-NEXT: local.get $push5=, 0
+; WASM32-NEXT: local.get $push4=, 1
+; WASM32-NEXT: i32.const $push3=, 1
+; WASM32-NEXT: i32.and $push0=, $pop4, $pop3
+; WASM32-NEXT: i32.const $push1=, 1
+; WASM32-NEXT: i32.and $push2=, $pop0, $pop1
+; WASM32-NEXT: i32.store8 0($pop5), $pop2
+; WASM32-NEXT: return
+;
+; WASM64-LABEL: store_i1:
+; WASM64: .functype store_i1 (i64, i32) -> ()
+; WASM64-NEXT: # %bb.0:
+; WASM64-NEXT: local.get $push5=, 0
+; WASM64-NEXT: local.get $push4=, 1
+; WASM64-NEXT: i32.const $push3=, 1
+; WASM64-NEXT: i32.and $push0=, $pop4, $pop3
+; WASM64-NEXT: i32.const $push1=, 1
+; WASM64-NEXT: i32.and $push2=, $pop0, $pop1
+; WASM64-NEXT: i32.store8 0($pop5), $pop2
+; WASM64-NEXT: return
+ store i1 %y, ptr %x
+ ret void
+}
+
+define void @store_i8(ptr %x, i8 %y) {
+; WASM32-LABEL: store_i8:
+; WASM32: .functype store_i8 (i32, i32) -> ()
+; WASM32-NEXT: # %bb.0:
+; WASM32-NEXT: local.get $push1=, 0
+; WASM32-NEXT: local.get $push0=, 1
+; WASM32-NEXT: i32.store8 0($pop1), $pop0
+; WASM32-NEXT: return
+;
+; WASM64-LABEL: store_i8:
+; WASM64: .functype store_i8 (i64, i32) -> ()
+; WASM64-NEXT: # %bb.0:
+; WASM64-NEXT: local.get $push1=, 0
+; WASM64-NEXT: local.get $push0=, 1
+; WASM64-NEXT: i32.store8 0($pop1), $pop0
+; WASM64-NEXT: return
+ store i8 %y, ptr %x
+ ret void
+}
+
+define void @store_i16(ptr %x, i16 %y) {
+; WASM32-LABEL: store_i16:
+; WASM32: .functype store_i16 (i32, i32) -> ()
+; WASM32-NEXT: # %bb.0:
+; WASM32-NEXT: local.get $push1=, 0
+; WASM32-NEXT: local.get $push0=, 1
+; WASM32-NEXT: i32.store16 0($pop1), $pop0
+; WASM32-NEXT: return
+;
+; WASM64-LABEL: store_i16:
+; WASM64: .functype store_i16 (i64, i32) -> ()
+; WASM64-NEXT: # %bb.0:
+; WASM64-NEXT: local.get $push1=, 0
+; WASM64-NEXT: local.get $push0=, 1
+; WASM64-NEXT: i32.store16 0($pop1), $pop0
+; WASM64-NEXT: return
+ store i16 %y, ptr %x
+ ret void
+}
+
+define void @store_i32(ptr %x, i32 %y) {
+; WASM32-LABEL: store_i32:
+; WASM32: .functype store_i32 (i32, i32) -> ()
+; WASM32-NEXT: # %bb.0:
+; WASM32-NEXT: local.get $push1=, 0
+; WASM32-NEXT: local.get $push0=, 1
+; WASM32-NEXT: i32.store 0($pop1), $pop0
+; WASM32-NEXT: return
+;
+; WASM64-LABEL: store_i32:
+; WASM64: .functype store_i32 (i64, i32) -> ()
+; WASM64-NEXT: # %bb.0:
+; WASM64-NEXT: local.get $push1=, 0
+; WASM64-NEXT: local.get $push0=, 1
+; WASM64-NEXT: i32.store 0($pop1), $pop0
+; WASM64-NEXT: return
+ store i32 %y, ptr %x
+ ret void
+}
+
+define void @store_i32_align1(ptr %x, i32 %y) {
+; WASM32-LABEL: store_i32_align1:
+; WASM32: .functype store_i32_align1 (i32, i32) -> ()
+; WASM32-NEXT: # %bb.0:
+; WASM32-NEXT: local.get $push1=, 0
+; WASM32-NEXT: local.get $push0=, 1
+; WASM32-NEXT: i32.store 0($pop1):p2align=0, $pop0
+; WASM32-NEXT: return
+;
+; WASM64-LABEL: store_i32_align1:
+; WASM64: .functype store_i32_align1 (i64, i32) -> ()
+; WASM64-NEXT: # %bb.0:
+; WASM64-NEXT: local.get $push1=, 0
+; WASM64-NEXT: local.get $push0=, 1
+; WASM64-NEXT: i32.store 0($pop1):p2align=0, $pop0
+; WASM64-NEXT: return
+ store i32 %y, ptr %x, align 1
+ ret void
+}
+
+define void @store_i48(ptr %x, i48 %y) {
+; WASM32-LABEL: store_i48:
+; WASM32: .functype store_i48 (i32, i64) -> ()
+; WASM32-NEXT: .local i64, i32
+; WASM32-NEXT: # %bb.0:
+; WASM32-NEXT: local.get $push3=, 1
+; WASM32-NEXT: i64.const $push0=, 32
+; WASM32-NEXT: i64.shr_u $push2=, $pop3, $pop0
+; WASM32-NEXT: local.set 2, $pop2
+; WASM32-NEXT: local.get $push5=, 0
+; WASM32-NEXT: i32.const $push1=, 4
+; WASM32-NEXT: i32.add $push4=, $pop5, $pop1
+; WASM32-NEXT: local.set 3, $pop4
+; WASM32-NEXT: local.get $push7=, 0
+; WASM32-NEXT: local.get $push6=, 1
+; WASM32-NEXT: i64.store32 0($pop7), $pop6
+; WASM32-NEXT: local.get $push9=, 3
+; WASM32-NEXT: local.get $push8=, 2
+; WASM32-NEXT: i64.store16 0($pop9), $pop8
+; WASM32-NEXT: return
+;
+; WASM64-LABEL: store_i48:
+; WASM64: .functype store_i48 (i64, i64) -> ()
+; WASM64-NEXT: .local i64, i64
+; WASM64-NEXT: # %bb.0:
+; WASM64-NEXT: local.get $push3=, 1
+; WASM64-NEXT: i64.const $push0=, 32
+; WASM64-NEXT: i64.shr_u $push2=, $pop3, $pop0
+; WASM64-NEXT: local.set 2, $pop2
+; WASM64-NEXT: local.get $push5=, 0
+; WASM64-NEXT: i64.const $push1=, 4
+; WASM64-NEXT: i64.add $push4=, $pop5, $pop1
+; WASM64-NEXT: local.set 3, $pop4
+; WASM64-NEXT: local.get $push7=, 0
+; WASM64-NEXT: local.get $push6=, 1
+; WASM64-NEXT: i64.store32 0($pop7), $pop6
+; WASM64-NEXT: local.get $push9=, 3
+; WASM64-NEXT: local.get $push8=, 2
+; WASM64-NEXT: i64.store16 0($pop9), $pop8
+; WASM64-NEXT: return
+ store i48 %y, ptr %x
+ ret void
+}
+
+define void @store_i64(ptr %x, i64 %y) {
+; WASM32-LABEL: store_i64:
+; WASM32: .functype store_i64 (i32, i64) -> ()
+; WASM32-NEXT: # %bb.0:
+; WASM32-NEXT: local.get $push1=, 0
+; WASM32-NEXT: local.get $push0=, 1
+; WASM32-NEXT: i64.store 0($pop1), $pop0
+; WASM32-NEXT: return
+;
+; WASM64-LABEL: store_i64:
+; WASM64: .functype store_i64 (i64, i64) -> ()
+; WASM64-NEXT: # %bb.0:
+; WASM64-NEXT: local.get $push1=, 0
+; WASM64-NEXT: local.get $push0=, 1
+; WASM64-NEXT: i64.store 0($pop1), $pop0
+; WASM64-NEXT: return
+ store i64 %y, ptr %x
+ ret void
+}
+
+
+define void @store_f32(ptr %x, float %y) {
+; WASM32-LABEL: store_f32:
+; WASM32: .functype store_f32 (i32, f32) -> ()
+; WASM32-NEXT: # %bb.0:
+; WASM32-NEXT: local.get $push1=, 0
+; WASM32-NEXT: local.get $push0=, 1
+; WASM32-NEXT: i32.store 0($pop1), $pop0
+; WASM32-NEXT: return
+;
+; WASM64-LABEL: store_f32:
+; WASM64: .functype store_f32 (i64, f32) -> ()
+; WASM64-NEXT: # %bb.0:
+; WASM64-NEXT: local.get $push1=, 0
+; WASM64-NEXT: local.get $push0=, 1
+; WASM64-NEXT: i32.store 0($pop1), $pop0
+; WASM64-NEXT: return
+ store float %y, ptr %x
+ ret void
+}
+
+define void @store_f64(ptr %x, double %y) {
+; WASM32-LABEL: store_f64:
+; WASM32: .functype store_f64 (i32, f64) -> ()
+; WASM32-NEXT: # %bb.0:
+; WASM32-NEXT: local.get $push1=, 0
+; WASM32-NEXT: local.get $push0=, 1
+; WASM32-NEXT: i64.store 0($pop1), $pop0
+; WASM32-NEXT: return
+;
+; WASM64-LABEL: store_f64:
+; WASM64: .functype store_f64 (i64, f64) -> ()
+; WASM64-NEXT: # %bb.0:
+; WASM64-NEXT: local.get $push1=, 0
+; WASM64-NEXT: local.get $push0=, 1
+; WASM64-NEXT: i64.store 0($pop1), $pop0
+; WASM64-NEXT: return
+ store double %y, ptr %x
+ ret void
+}
+
+define void @store_ptr(ptr %x, ptr %y) {
+; WASM32-LABEL: store_ptr:
+; WASM32: .functype store_ptr (i32, i32) -> ()
+; WASM32-NEXT: # %bb.0:
+; WASM32-NEXT: local.get $push1=, 0
+; WASM32-NEXT: local.get $push0=, 1
+; WASM32-NEXT: i32.store 0($pop1), $pop0
+; WASM32-NEXT: return
+;
+; WASM64-LABEL: store_ptr:
+; WASM64: .functype store_ptr (i64, i64) -> ()
+; WASM64-NEXT: # %bb.0:
+; WASM64-NEXT: local.get $push1=, 0
+; WASM64-NEXT: local.get $push0=, 1
+; WASM64-NEXT: i64.store 0($pop1), $pop0
+; WASM64-NEXT: return
+ store ptr %y, ptr %x
+ ret void
+}
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/zextload.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/zextload.mir
new file mode 100644
index 0000000000000..6bf9ba7230121
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/zextload.mir
@@ -0,0 +1,208 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -mtriple=wasm32-unknown-unknown -run-pass=legalizer,regbankselect,instruction-select %s -o - | FileCheck %s --check-prefixes=WASM32
+# RUN: llc -mtriple=wasm64-unknown-unknown -run-pass=legalizer,regbankselect,instruction-select %s -o - | FileCheck %s --check-prefixes=WASM64
+
+---
+name: zextload_i1_i32
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $arguments
+
+ ; WASM32-LABEL: name: zextload_i1_i32
+ ; WASM32: liveins: $arguments
+ ; WASM32-NEXT: {{ $}}
+ ; WASM32-NEXT: [[DEF:%[0-9]+]]:i32 = IMPLICIT_DEF
+ ; WASM32-NEXT: [[LOAD8_U_I32_A32_:%[0-9]+]]:i32 = LOAD8_U_I32_A32 0, 0, [[DEF]], implicit-def dead $arguments :: (load (i8))
+ ; WASM32-NEXT: RETURN [[LOAD8_U_I32_A32_]], implicit-def $arguments
+ ;
+ ; WASM64-LABEL: name: zextload_i1_i32
+ ; WASM64: liveins: $arguments
+ ; WASM64-NEXT: {{ $}}
+ ; WASM64-NEXT: [[DEF:%[0-9]+]]:i64 = IMPLICIT_DEF
+ ; WASM64-NEXT: [[LOAD8_U_I32_A64_:%[0-9]+]]:i32 = LOAD8_U_I32_A64 0, 0, [[DEF]], implicit-def dead $arguments :: (load (i8))
+ ; WASM64-NEXT: RETURN [[LOAD8_U_I32_A64_]], implicit-def $arguments
+ %0:_(p0) = G_IMPLICIT_DEF
+ %1:_(i32) = G_ZEXTLOAD %0(p0) :: (load (i1))
+ RETURN %1(i32), implicit-def $arguments
+...
+---
+name: zextload_i1_i64
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $arguments
+
+ ; WASM32-LABEL: name: zextload_i1_i64
+ ; WASM32: liveins: $arguments
+ ; WASM32-NEXT: {{ $}}
+ ; WASM32-NEXT: [[DEF:%[0-9]+]]:i32 = IMPLICIT_DEF
+ ; WASM32-NEXT: [[LOAD8_U_I64_A32_:%[0-9]+]]:i64 = LOAD8_U_I64_A32 0, 0, [[DEF]], implicit-def dead $arguments :: (load (i8))
+ ; WASM32-NEXT: RETURN [[LOAD8_U_I64_A32_]], implicit-def $arguments
+ ;
+ ; WASM64-LABEL: name: zextload_i1_i64
+ ; WASM64: liveins: $arguments
+ ; WASM64-NEXT: {{ $}}
+ ; WASM64-NEXT: [[DEF:%[0-9]+]]:i64 = IMPLICIT_DEF
+ ; WASM64-NEXT: [[LOAD8_U_I64_A64_:%[0-9]+]]:i64 = LOAD8_U_I64_A64 0, 0, [[DEF]], implicit-def dead $arguments :: (load (i8))
+ ; WASM64-NEXT: RETURN [[LOAD8_U_I64_A64_]], implicit-def $arguments
+ %0:_(p0) = G_IMPLICIT_DEF
+ %1:_(i64) = G_ZEXTLOAD %0(p0) :: (load (i1))
+ RETURN %1(i64), implicit-def $arguments
+...
+---
+name: zextload_i8_i32
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $arguments
+
+ ; WASM32-LABEL: name: zextload_i8_i32
+ ; WASM32: liveins: $arguments
+ ; WASM32-NEXT: {{ $}}
+ ; WASM32-NEXT: [[DEF:%[0-9]+]]:i32 = IMPLICIT_DEF
+ ; WASM32-NEXT: [[LOAD8_U_I32_A32_:%[0-9]+]]:i32 = LOAD8_U_I32_A32 0, 0, [[DEF]], implicit-def dead $arguments :: (load (i8))
+ ; WASM32-NEXT: RETURN [[LOAD8_U_I32_A32_]], implicit-def $arguments
+ ;
+ ; WASM64-LABEL: name: zextload_i8_i32
+ ; WASM64: liveins: $arguments
+ ; WASM64-NEXT: {{ $}}
+ ; WASM64-NEXT: [[DEF:%[0-9]+]]:i64 = IMPLICIT_DEF
+ ; WASM64-NEXT: [[LOAD8_U_I32_A64_:%[0-9]+]]:i32 = LOAD8_U_I32_A64 0, 0, [[DEF]], implicit-def dead $arguments :: (load (i8))
+ ; WASM64-NEXT: RETURN [[LOAD8_U_I32_A64_]], implicit-def $arguments
+ %0:_(p0) = G_IMPLICIT_DEF
+ %1:_(i32) = G_ZEXTLOAD %0(p0) :: (load (i8))
+ RETURN %1(i32), implicit-def $arguments
+...
+---
+name: zextload_i8_i64
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $arguments
+
+ ; WASM32-LABEL: name: zextload_i8_i64
+ ; WASM32: liveins: $arguments
+ ; WASM32-NEXT: {{ $}}
+ ; WASM32-NEXT: [[DEF:%[0-9]+]]:i32 = IMPLICIT_DEF
+ ; WASM32-NEXT: [[LOAD8_U_I64_A32_:%[0-9]+]]:i64 = LOAD8_U_I64_A32 0, 0, [[DEF]], implicit-def dead $arguments :: (load (i8))
+ ; WASM32-NEXT: RETURN [[LOAD8_U_I64_A32_]], implicit-def $arguments
+ ;
+ ; WASM64-LABEL: name: zextload_i8_i64
+ ; WASM64: liveins: $arguments
+ ; WASM64-NEXT: {{ $}}
+ ; WASM64-NEXT: [[DEF:%[0-9]+]]:i64 = IMPLICIT_DEF
+ ; WASM64-NEXT: [[LOAD8_U_I64_A64_:%[0-9]+]]:i64 = LOAD8_U_I64_A64 0, 0, [[DEF]], implicit-def dead $arguments :: (load (i8))
+ ; WASM64-NEXT: RETURN [[LOAD8_U_I64_A64_]], implicit-def $arguments
+ %0:_(p0) = G_IMPLICIT_DEF
+ %1:_(i64) = G_ZEXTLOAD %0(p0) :: (load (i8))
+ RETURN %1(i64), implicit-def $arguments
+...
+---
+name: zextload_i16_i32
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $arguments
+
+ ; WASM32-LABEL: name: zextload_i16_i32
+ ; WASM32: liveins: $arguments
+ ; WASM32-NEXT: {{ $}}
+ ; WASM32-NEXT: [[DEF:%[0-9]+]]:i32 = IMPLICIT_DEF
+ ; WASM32-NEXT: [[LOAD16_U_I32_A32_:%[0-9]+]]:i32 = LOAD16_U_I32_A32 0, 0, [[DEF]], implicit-def dead $arguments :: (load (i16))
+ ; WASM32-NEXT: RETURN [[LOAD16_U_I32_A32_]], implicit-def $arguments
+ ;
+ ; WASM64-LABEL: name: zextload_i16_i32
+ ; WASM64: liveins: $arguments
+ ; WASM64-NEXT: {{ $}}
+ ; WASM64-NEXT: [[DEF:%[0-9]+]]:i64 = IMPLICIT_DEF
+ ; WASM64-NEXT: [[LOAD16_U_I32_A64_:%[0-9]+]]:i32 = LOAD16_U_I32_A64 0, 0, [[DEF]], implicit-def dead $arguments :: (load (i16))
+ ; WASM64-NEXT: RETURN [[LOAD16_U_I32_A64_]], implicit-def $arguments
+ %0:_(p0) = G_IMPLICIT_DEF
+ %1:_(i32) = G_ZEXTLOAD %0(p0) :: (load (i16))
+ RETURN %1(i32), implicit-def $arguments
+...
+---
+name: zextload_i16_i64
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $arguments
+
+ ; WASM32-LABEL: name: zextload_i16_i64
+ ; WASM32: liveins: $arguments
+ ; WASM32-NEXT: {{ $}}
+ ; WASM32-NEXT: [[DEF:%[0-9]+]]:i32 = IMPLICIT_DEF
+ ; WASM32-NEXT: [[LOAD16_U_I64_A32_:%[0-9]+]]:i64 = LOAD16_U_I64_A32 0, 0, [[DEF]], implicit-def dead $arguments :: (load (i16))
+ ; WASM32-NEXT: RETURN [[LOAD16_U_I64_A32_]], implicit-def $arguments
+ ;
+ ; WASM64-LABEL: name: zextload_i16_i64
+ ; WASM64: liveins: $arguments
+ ; WASM64-NEXT: {{ $}}
+ ; WASM64-NEXT: [[DEF:%[0-9]+]]:i64 = IMPLICIT_DEF
+ ; WASM64-NEXT: [[LOAD16_U_I64_A64_:%[0-9]+]]:i64 = LOAD16_U_I64_A64 0, 0, [[DEF]], implicit-def dead $arguments :: (load (i16))
+ ; WASM64-NEXT: RETURN [[LOAD16_U_I64_A64_]], implicit-def $arguments
+ %0:_(p0) = G_IMPLICIT_DEF
+ %1:_(i64) = G_ZEXTLOAD %0(p0) :: (load (i16))
+ RETURN %1(i64), implicit-def $arguments
+...
+---
+name: zextload_i32_i64
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $arguments
+
+ ; WASM32-LABEL: name: zextload_i32_i64
+ ; WASM32: liveins: $arguments
+ ; WASM32-NEXT: {{ $}}
+ ; WASM32-NEXT: [[DEF:%[0-9]+]]:i32 = IMPLICIT_DEF
+ ; WASM32-NEXT: [[LOAD32_U_I64_A32_:%[0-9]+]]:i64 = LOAD32_U_I64_A32 0, 0, [[DEF]], implicit-def dead $arguments :: (load (i32))
+ ; WASM32-NEXT: RETURN [[LOAD32_U_I64_A32_]], implicit-def $arguments
+ ;
+ ; WASM64-LABEL: name: zextload_i32_i64
+ ; WASM64: liveins: $arguments
+ ; WASM64-NEXT: {{ $}}
+ ; WASM64-NEXT: [[DEF:%[0-9]+]]:i64 = IMPLICIT_DEF
+ ; WASM64-NEXT: [[LOAD32_U_I64_A64_:%[0-9]+]]:i64 = LOAD32_U_I64_A64 0, 0, [[DEF]], implicit-def dead $arguments :: (load (i32))
+ ; WASM64-NEXT: RETURN [[LOAD32_U_I64_A64_]], implicit-def $arguments
+ %0:_(p0) = G_IMPLICIT_DEF
+ %1:_(i64) = G_ZEXTLOAD %0(p0) :: (load (i32))
+ RETURN %1(i64), implicit-def $arguments
+...
+---
+name: zextload_i48_i64
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $arguments
+
+ ; WASM32-LABEL: name: zextload_i48_i64
+ ; WASM32: liveins: $arguments
+ ; WASM32-NEXT: {{ $}}
+ ; WASM32-NEXT: [[DEF:%[0-9]+]]:i32 = IMPLICIT_DEF
+ ; WASM32-NEXT: [[LOAD32_U_I64_A32_:%[0-9]+]]:i64 = LOAD32_U_I64_A32 0, 0, [[DEF]], implicit-def dead $arguments :: (load (s32), align 8)
+ ; WASM32-NEXT: [[CONST_I32_:%[0-9]+]]:i32 = CONST_I32 4, implicit-def dead $arguments
+ ; WASM32-NEXT: [[ADD_I32_:%[0-9]+]]:i32 = nuw inbounds ADD_I32 [[DEF]], [[CONST_I32_]], implicit-def dead $arguments
+ ; WASM32-NEXT: [[LOAD16_U_I64_A32_:%[0-9]+]]:i64 = LOAD16_U_I64_A32 0, 0, [[ADD_I32_]], implicit-def dead $arguments :: (load (s16) from unknown-address + 4, align 4)
+ ; WASM32-NEXT: [[CONST_I64_:%[0-9]+]]:i64 = CONST_I64 32, implicit-def dead $arguments
+ ; WASM32-NEXT: [[SHL_I64_:%[0-9]+]]:i64 = SHL_I64 [[LOAD16_U_I64_A32_]], [[CONST_I64_]], implicit-def dead $arguments
+ ; WASM32-NEXT: [[OR_I64_:%[0-9]+]]:i64 = OR_I64 [[SHL_I64_]], [[LOAD32_U_I64_A32_]], implicit-def dead $arguments
+ ; WASM32-NEXT: RETURN [[OR_I64_]], implicit-def $arguments
+ ;
+ ; WASM64-LABEL: name: zextload_i48_i64
+ ; WASM64: liveins: $arguments
+ ; WASM64-NEXT: {{ $}}
+ ; WASM64-NEXT: [[DEF:%[0-9]+]]:i64 = IMPLICIT_DEF
+ ; WASM64-NEXT: [[LOAD32_U_I64_A64_:%[0-9]+]]:i64 = LOAD32_U_I64_A64 0, 0, [[DEF]], implicit-def dead $arguments :: (load (s32), align 8)
+ ; WASM64-NEXT: [[CONST_I64_:%[0-9]+]]:i64 = CONST_I64 4, implicit-def dead $arguments
+ ; WASM64-NEXT: [[ADD_I64_:%[0-9]+]]:i64 = nuw inbounds ADD_I64 [[DEF]], [[CONST_I64_]], implicit-def dead $arguments
+ ; WASM64-NEXT: [[LOAD16_U_I64_A64_:%[0-9]+]]:i64 = LOAD16_U_I64_A64 0, 0, [[ADD_I64_]], implicit-def dead $arguments :: (load (s16) from unknown-address + 4, align 4)
+ ; WASM64-NEXT: [[CONST_I64_1:%[0-9]+]]:i64 = CONST_I64 32, implicit-def dead $arguments
+ ; WASM64-NEXT: [[SHL_I64_:%[0-9]+]]:i64 = SHL_I64 [[LOAD16_U_I64_A64_]], [[CONST_I64_1]], implicit-def dead $arguments
+ ; WASM64-NEXT: [[OR_I64_:%[0-9]+]]:i64 = OR_I64 [[SHL_I64_]], [[LOAD32_U_I64_A64_]], implicit-def dead $arguments
+ ; WASM64-NEXT: RETURN [[OR_I64_]], implicit-def $arguments
+ %0:_(p0) = G_IMPLICIT_DEF
+ %1:_(i64) = G_ZEXTLOAD %0(p0) :: (load (i48))
+ RETURN %1(i64), implicit-def $arguments
+...
>From 2399bfd8474cf5b867206217307c8ec845942dc7 Mon Sep 17 00:00:00 2001
From: Demetrius Kanios <demetrius at kanios.net>
Date: Wed, 1 Jul 2026 11:32:16 -0700
Subject: [PATCH 2/2] InstructionSelector tweaks after review
---
.../GISel/WebAssemblyInstructionSelector.cpp | 42 +++++++------------
1 file changed, 14 insertions(+), 28 deletions(-)
diff --git a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyInstructionSelector.cpp b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyInstructionSelector.cpp
index 3709327170ac6..6fdbe38ace1ab 100644
--- a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyInstructionSelector.cpp
+++ b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyInstructionSelector.cpp
@@ -99,10 +99,6 @@ InstructionSelector::ComplexRendererFns
WebAssemblyInstructionSelector::selectAddrOperands(LLT AddrType,
unsigned int ConstOpc,
MachineOperand &Root) const {
-
- if (!Root.isReg())
- return std::nullopt;
-
return {{
[=](MachineInstrBuilder &MIB) { MIB.addImm(0); },
[=](MachineInstrBuilder &MIB) { MIB.addReg(Root.getReg()); },
@@ -190,9 +186,6 @@ bool WebAssemblyInstructionSelector::select(MachineInstr &I) {
using namespace TargetOpcode;
- auto PointerWidth = MF.getDataLayout().getPointerSizeInBits();
- auto PtrIsI64 = PointerWidth == 64;
-
switch (I.getOpcode()) {
case G_IMPLICIT_DEF: {
const Register DefReg = I.getOperand(0).getReg();
@@ -207,43 +200,36 @@ bool WebAssemblyInstructionSelector::select(MachineInstr &I) {
return RBI.constrainGenericRegister(DefReg, *DefRC, MRI) != nullptr;
}
case G_PTRTOINT: {
- assert(MRI.getType(I.getOperand(1).getReg()).isPointer() &&
- "G_PTRTOINT selection with non-pointer?");
+ bool PtrIsI64 = MRI.getType(I.getOperand(1).getReg()).getSizeInBits() == 64;
I.setDesc(
TII.get(PtrIsI64 ? WebAssembly::COPY_I64 : WebAssembly::COPY_I32));
constrainSelectedInstRegOperands(I, TII, TRI, RBI);
-
return true;
}
case G_INTTOPTR: {
- assert(MRI.getType(I.getOperand(0).getReg()).isPointer() &&
- "G_INTTOPTR selection with non-pointer?");
+ bool PtrIsI64 = MRI.getType(I.getOperand(0).getReg()).getSizeInBits() == 64;
I.setDesc(
TII.get(PtrIsI64 ? WebAssembly::COPY_I64 : WebAssembly::COPY_I32));
constrainSelectedInstRegOperands(I, TII, TRI, RBI);
-
return true;
}
case G_PTRMASK: {
- assert(MRI.getType(I.getOperand(0).getReg()).isPointer() &&
- "G_PTRMASK selection with non-pointer?");
+ bool PtrIsI64 = MRI.getType(I.getOperand(0).getReg()).getSizeInBits() == 64;
I.setDesc(TII.get(PtrIsI64 ? WebAssembly::AND_I64 : WebAssembly::AND_I32));
constrainSelectedInstRegOperands(I, TII, TRI, RBI);
-
return true;
}
case G_GLOBAL_VALUE: {
assert(I.getOperand(1).getTargetFlags() == 0 &&
"Unexpected target flags on generic G_GLOBAL_VALUE instruction");
- assert(WebAssembly::isValidAddressSpace(
- MRI.getType(I.getOperand(0).getReg()).getAddressSpace()) &&
- "Invalid address space for WebAssembly target");
unsigned OperandFlags = 0;
const llvm::GlobalValue *GV = I.getOperand(1).getGlobal();
+ LLT PtrTy = MRI.getType(I.getOperand(0).getReg());
+ bool PtrIsI64 = PtrTy.getSizeInBits() == 64;
if (TLI.isPositionIndependent()) {
if (TM.shouldAssumeDSOLocal(GV)) {
@@ -257,14 +243,13 @@ bool WebAssemblyInstructionSelector::select(MachineInstr &I) {
}
MachineIRBuilder B(I);
- auto MemBase =
- MRI.createGenericVirtualRegister(LLT::pointer(0, PointerWidth));
- MRI.setRegClass(MemBase, PtrIsI64 ? &WebAssembly::I64RegClass
- : &WebAssembly::I32RegClass);
- auto Offset =
- MRI.createGenericVirtualRegister(LLT::pointer(0, PointerWidth));
- MRI.setRegClass(Offset, PtrIsI64 ? &WebAssembly::I64RegClass
- : &WebAssembly::I32RegClass);
+ Register MemBase = MRI.createVirtualRegister(
+ PtrIsI64 ? &WebAssembly::I64RegClass : &WebAssembly::I32RegClass);
+ MRI.setType(MemBase, PtrTy);
+
+ Register Offset = MRI.createVirtualRegister(
+ PtrIsI64 ? &WebAssembly::I64RegClass : &WebAssembly::I32RegClass);
+ MRI.setType(Offset, PtrTy);
B.buildInstr(PtrIsI64 ? WebAssembly::GLOBAL_GET_I64
: WebAssembly::GLOBAL_GET_I32)
@@ -288,7 +273,8 @@ bool WebAssemblyInstructionSelector::select(MachineInstr &I) {
OperandFlags = WebAssemblyII::MO_GOT;
}
- auto NewOpc = PtrIsI64 ? WebAssembly::CONST_I64 : WebAssembly::CONST_I32;
+ unsigned NewOpc =
+ PtrIsI64 ? WebAssembly::CONST_I64 : WebAssembly::CONST_I32;
if (OperandFlags & WebAssemblyII::MO_GOT) {
NewOpc =
More information about the llvm-commits
mailing list