[llvm] [WebAssembly] Support v128.load{32,64}_zero for f32 and f64 types (PR #172291)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Dec 22 23:48:25 PST 2025
https://github.com/ParkHanbum updated https://github.com/llvm/llvm-project/pull/172291
>From de69ce46d02d73b3fb50a9415e3f5e782def9af1 Mon Sep 17 00:00:00 2001
From: Hanbum Park <kese111 at gmail.com>
Date: Mon, 15 Dec 2025 19:55:21 +0900
Subject: [PATCH 1/2] add testcases for upcoming patch
---
.../WebAssembly/simd-load-store-alignment.ll | 121 +++++++++
.../WebAssembly/simd-load-zero-offset.ll | 251 ++++++++++++++++++
2 files changed, 372 insertions(+)
diff --git a/llvm/test/CodeGen/WebAssembly/simd-load-store-alignment.ll b/llvm/test/CodeGen/WebAssembly/simd-load-store-alignment.ll
index bfab5fe36b3f4..896a8bfd79945 100644
--- a/llvm/test/CodeGen/WebAssembly/simd-load-store-alignment.ll
+++ b/llvm/test/CodeGen/WebAssembly/simd-load-store-alignment.ll
@@ -1425,6 +1425,60 @@ define void @store_v4f32_a32(ptr %p, <4 x float> %v) {
ret void
}
+define <4 x float> @load_zero_float_a1(ptr %p) {
+; CHECK-LABEL: load_zero_float_a1:
+; CHECK: .functype load_zero_float_a1 (i32) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: v128.const 0x0p0, 0x0p0, 0x0p0, 0x0p0
+; CHECK-NEXT: v128.load32_lane 0:p2align=0, 0
+; CHECK-NEXT: # fallthrough-return
+ %x = load float, ptr %p, align 1
+ %v = insertelement <4 x float> zeroinitializer, float %x, i32 0
+ ret <4 x float> %v
+}
+
+define <4 x float> @load_zero_float_a2(ptr %p) {
+; CHECK-LABEL: load_zero_float_a2:
+; CHECK: .functype load_zero_float_a2 (i32) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: v128.const 0x0p0, 0x0p0, 0x0p0, 0x0p0
+; CHECK-NEXT: v128.load32_lane 0:p2align=1, 0
+; CHECK-NEXT: # fallthrough-return
+ %x = load float, ptr %p, align 2
+ %v = insertelement <4 x float> zeroinitializer, float %x, i32 0
+ ret <4 x float> %v
+}
+
+; 4 is the default alignment for v128.load32_zero so no attribute is needed.
+define <4 x float> @load_zero_float_a4(ptr %p) {
+; CHECK-LABEL: load_zero_float_a4:
+; CHECK: .functype load_zero_float_a4 (i32) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: v128.const 0x0p0, 0x0p0, 0x0p0, 0x0p0
+; CHECK-NEXT: v128.load32_lane 0, 0
+; CHECK-NEXT: # fallthrough-return
+ %x = load float, ptr %p, align 4
+ %v = insertelement <4 x float> zeroinitializer, float %x, i32 0
+ ret <4 x float> %v
+}
+
+; 8 is greater than the default alignment so it is ignored.
+define <4 x float> @load_zero_float_a8(ptr %p) {
+; CHECK-LABEL: load_zero_float_a8:
+; CHECK: .functype load_zero_float_a8 (i32) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: v128.const 0x0p0, 0x0p0, 0x0p0, 0x0p0
+; CHECK-NEXT: v128.load32_lane 0, 0
+; CHECK-NEXT: # fallthrough-return
+ %x = load float, ptr %p, align 8
+ %v = insertelement <4 x float> zeroinitializer, float %x, i32 0
+ ret <4 x float> %v
+}
+
; ==============================================================================
; 2 x double
; ==============================================================================
@@ -1524,3 +1578,70 @@ define void @store_v2f64_a32(ptr %p, <2 x double> %v) {
store <2 x double> %v, ptr %p, align 32
ret void
}
+
+define <2 x double> @load_zero_double_a1(ptr %p) {
+; CHECK-LABEL: load_zero_double_a1:
+; CHECK: .functype load_zero_double_a1 (i32) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: v128.const 0x0p0, 0x0p0
+; CHECK-NEXT: v128.load64_lane 0:p2align=0, 0
+; CHECK-NEXT: # fallthrough-return
+ %x = load double, ptr %p, align 1
+ %v = insertelement <2 x double> zeroinitializer, double %x, i32 0
+ ret <2 x double> %v
+}
+
+define <2 x double> @load_zero_double_a2(ptr %p) {
+; CHECK-LABEL: load_zero_double_a2:
+; CHECK: .functype load_zero_double_a2 (i32) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: v128.const 0x0p0, 0x0p0
+; CHECK-NEXT: v128.load64_lane 0:p2align=1, 0
+; CHECK-NEXT: # fallthrough-return
+ %x = load double, ptr %p, align 2
+ %v = insertelement <2 x double> zeroinitializer, double %x, i32 0
+ ret <2 x double> %v
+}
+
+define <2 x double> @load_zero_double_a4(ptr %p) {
+; CHECK-LABEL: load_zero_double_a4:
+; CHECK: .functype load_zero_double_a4 (i32) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: v128.const 0x0p0, 0x0p0
+; CHECK-NEXT: v128.load64_lane 0:p2align=2, 0
+; CHECK-NEXT: # fallthrough-return
+ %x = load double, ptr %p, align 4
+ %v = insertelement <2 x double> zeroinitializer, double %x, i32 0
+ ret <2 x double> %v
+}
+
+; 8 is the default alignment for v128.load64_zero so no attribute is needed.
+define <2 x double> @load_zero_double_a8(ptr %p) {
+; CHECK-LABEL: load_zero_double_a8:
+; CHECK: .functype load_zero_double_a8 (i32) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: v128.const 0x0p0, 0x0p0
+; CHECK-NEXT: v128.load64_lane 0, 0
+; CHECK-NEXT: # fallthrough-return
+ %x = load double, ptr %p, align 8
+ %v = insertelement <2 x double> zeroinitializer, double %x, i32 0
+ ret <2 x double> %v
+}
+
+; 16 is greater than the default alignment so it is ignored.
+define <2 x double> @load_zero_double_a16(ptr %p) {
+; CHECK-LABEL: load_zero_double_a16:
+; CHECK: .functype load_zero_double_a16 (i32) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: v128.const 0x0p0, 0x0p0
+; CHECK-NEXT: v128.load64_lane 0, 0
+; CHECK-NEXT: # fallthrough-return
+ %x = load double, ptr %p, align 16
+ %v = insertelement <2 x double> zeroinitializer, double %x, i32 0
+ ret <2 x double> %v
+}
diff --git a/llvm/test/CodeGen/WebAssembly/simd-load-zero-offset.ll b/llvm/test/CodeGen/WebAssembly/simd-load-zero-offset.ll
index 81487f300cdf6..06fda8a1061d6 100644
--- a/llvm/test/CodeGen/WebAssembly/simd-load-zero-offset.ll
+++ b/llvm/test/CodeGen/WebAssembly/simd-load-zero-offset.ll
@@ -122,6 +122,131 @@ define <4 x i32> @load_zero_i32_from_global_address() {
ret <4 x i32> %t
}
+define <4 x float> @load_zero_float_no_offset(ptr %p) {
+; CHECK-LABEL: load_zero_float_no_offset:
+; CHECK: .functype load_zero_float_no_offset (i32) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: v128.const 0x0p0, 0x0p0, 0x0p0, 0x0p0
+; CHECK-NEXT: v128.load32_lane 0, 0
+; CHECK-NEXT: # fallthrough-return
+ %x = load float, ptr %p
+ %v = insertelement <4 x float> zeroinitializer, float %x, i32 0
+ ret <4 x float> %v
+}
+
+define <4 x float> @load_zero_float_with_folded_offset(ptr %p) {
+; CHECK-LABEL: load_zero_float_with_folded_offset:
+; CHECK: .functype load_zero_float_with_folded_offset (i32) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: i32.const 24
+; CHECK-NEXT: i32.add
+; CHECK-NEXT: v128.const 0x0p0, 0x0p0, 0x0p0, 0x0p0
+; CHECK-NEXT: v128.load32_lane 0, 0
+; CHECK-NEXT: # fallthrough-return
+ %q = ptrtoint ptr %p to i32
+ %r = add nuw i32 %q, 24
+ %s = inttoptr i32 %r to ptr
+ %x = load float, ptr %s
+ %t = insertelement <4 x float> zeroinitializer, float %x, i32 0
+ ret <4 x float> %t
+}
+
+define <4 x float> @load_zero_float_with_folded_gep_offset(ptr %p) {
+; CHECK-LABEL: load_zero_float_with_folded_gep_offset:
+; CHECK: .functype load_zero_float_with_folded_gep_offset (i32) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: i32.const 24
+; CHECK-NEXT: i32.add
+; CHECK-NEXT: v128.const 0x0p0, 0x0p0, 0x0p0, 0x0p0
+; CHECK-NEXT: v128.load32_lane 0, 0
+; CHECK-NEXT: # fallthrough-return
+ %s = getelementptr inbounds float, ptr %p, i32 6
+ %x = load float, ptr %s
+ %t = insertelement <4 x float> zeroinitializer, float %x, i32 0
+ ret <4 x float> %t
+}
+
+define <4 x float> @load_zero_float_with_unfolded_gep_negative_offset(ptr %p) {
+; CHECK-LABEL: load_zero_float_with_unfolded_gep_negative_offset:
+; CHECK: .functype load_zero_float_with_unfolded_gep_negative_offset (i32) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: i32.const -24
+; CHECK-NEXT: i32.add
+; CHECK-NEXT: v128.const 0x0p0, 0x0p0, 0x0p0, 0x0p0
+; CHECK-NEXT: v128.load32_lane 0, 0
+; CHECK-NEXT: # fallthrough-return
+ %s = getelementptr inbounds float, ptr %p, i32 -6
+ %x = load float, ptr %s
+ %t = insertelement <4 x float> zeroinitializer, float %x, i32 0
+ ret <4 x float> %t
+}
+
+define <4 x float> @load_zero_float_with_unfolded_offset(ptr %p) {
+; CHECK-LABEL: load_zero_float_with_unfolded_offset:
+; CHECK: .functype load_zero_float_with_unfolded_offset (i32) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: i32.const 24
+; CHECK-NEXT: i32.add
+; CHECK-NEXT: v128.const 0x0p0, 0x0p0, 0x0p0, 0x0p0
+; CHECK-NEXT: v128.load32_lane 0, 0
+; CHECK-NEXT: # fallthrough-return
+ %q = ptrtoint ptr %p to i32
+ %r = add nsw i32 %q, 24
+ %s = inttoptr i32 %r to ptr
+ %x = load float, ptr %s
+ %t = insertelement <4 x float> zeroinitializer, float %x, i32 0
+ ret <4 x float> %t
+}
+
+define <4 x float> @load_zero_float_with_unfolded_gep_offset(ptr %p) {
+; CHECK-LABEL: load_zero_float_with_unfolded_gep_offset:
+; CHECK: .functype load_zero_float_with_unfolded_gep_offset (i32) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: i32.const 24
+; CHECK-NEXT: i32.add
+; CHECK-NEXT: v128.const 0x0p0, 0x0p0, 0x0p0, 0x0p0
+; CHECK-NEXT: v128.load32_lane 0, 0
+; CHECK-NEXT: # fallthrough-return
+ %s = getelementptr float, ptr %p, i32 6
+ %x = load float, ptr %s
+ %t = insertelement <4 x float> zeroinitializer, float %x, i32 0
+ ret <4 x float> %t
+}
+
+define <4 x float> @load_zero_float_from_numeric_address() {
+; CHECK-LABEL: load_zero_float_from_numeric_address:
+; CHECK: .functype load_zero_float_from_numeric_address () -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: i32.const 42
+; CHECK-NEXT: v128.const 0x0p0, 0x0p0, 0x0p0, 0x0p0
+; CHECK-NEXT: v128.load32_lane 0, 0
+; CHECK-NEXT: # fallthrough-return
+ %s = inttoptr i32 42 to ptr
+ %x = load float, ptr %s
+ %t = insertelement <4 x float> zeroinitializer, float %x, i32 0
+ ret <4 x float> %t
+}
+
+ at gv_float = global i32 0
+define <4 x float> @load_zero_float_from_global_address() {
+; CHECK-LABEL: load_zero_float_from_global_address:
+; CHECK: .functype load_zero_float_from_global_address () -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: i32.const gv_float
+; CHECK-NEXT: v128.const 0x0p0, 0x0p0, 0x0p0, 0x0p0
+; CHECK-NEXT: v128.load32_lane 0, 0
+; CHECK-NEXT: # fallthrough-return
+ %x = load float, ptr @gv_float
+ %t = insertelement <4 x float> zeroinitializer, float %x, i32 0
+ ret <4 x float> %t
+}
+
;===----------------------------------------------------------------------------
; v128.load64_zero
;===----------------------------------------------------------------------------
@@ -238,3 +363,129 @@ define <2 x i64> @load_zero_i64_from_global_address() {
%t = insertelement <2 x i64> zeroinitializer, i64 %x, i32 0
ret <2 x i64> %t
}
+
+
+define <2 x double> @load_zero_double_no_offset(ptr %p) {
+; CHECK-LABEL: load_zero_double_no_offset:
+; CHECK: .functype load_zero_double_no_offset (i32) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: v128.const 0x0p0, 0x0p0
+; CHECK-NEXT: v128.load64_lane 0, 0
+; CHECK-NEXT: # fallthrough-return
+ %x = load double, ptr %p
+ %v = insertelement <2 x double> zeroinitializer, double %x, i32 0
+ ret <2 x double> %v
+}
+
+define <2 x double> @load_zero_double_with_folded_offset(ptr %p) {
+; CHECK-LABEL: load_zero_double_with_folded_offset:
+; CHECK: .functype load_zero_double_with_folded_offset (i32) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: i32.const 24
+; CHECK-NEXT: i32.add
+; CHECK-NEXT: v128.const 0x0p0, 0x0p0
+; CHECK-NEXT: v128.load64_lane 0, 0
+; CHECK-NEXT: # fallthrough-return
+ %q = ptrtoint ptr %p to i32
+ %r = add nuw i32 %q, 24
+ %s = inttoptr i32 %r to ptr
+ %x = load double, ptr %s
+ %t = insertelement <2 x double> zeroinitializer, double %x, i32 0
+ ret <2 x double> %t
+}
+
+define <2 x double> @load_zero_double_with_folded_gep_offset(ptr %p) {
+; CHECK-LABEL: load_zero_double_with_folded_gep_offset:
+; CHECK: .functype load_zero_double_with_folded_gep_offset (i32) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: i32.const 48
+; CHECK-NEXT: i32.add
+; CHECK-NEXT: v128.const 0x0p0, 0x0p0
+; CHECK-NEXT: v128.load64_lane 0, 0
+; CHECK-NEXT: # fallthrough-return
+ %s = getelementptr inbounds double, ptr %p, i32 6
+ %x = load double, ptr %s
+ %t = insertelement <2 x double> zeroinitializer, double %x, i32 0
+ ret <2 x double> %t
+}
+
+define <2 x double> @load_zero_double_with_unfolded_gep_negative_offset(ptr %p) {
+; CHECK-LABEL: load_zero_double_with_unfolded_gep_negative_offset:
+; CHECK: .functype load_zero_double_with_unfolded_gep_negative_offset (i32) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: i32.const -48
+; CHECK-NEXT: i32.add
+; CHECK-NEXT: v128.const 0x0p0, 0x0p0
+; CHECK-NEXT: v128.load64_lane 0, 0
+; CHECK-NEXT: # fallthrough-return
+ %s = getelementptr inbounds double, ptr %p, i32 -6
+ %x = load double, ptr %s
+ %t = insertelement <2 x double> zeroinitializer, double %x, i32 0
+ ret <2 x double> %t
+}
+
+define <2 x double> @load_zero_double_with_unfolded_offset(ptr %p) {
+; CHECK-LABEL: load_zero_double_with_unfolded_offset:
+; CHECK: .functype load_zero_double_with_unfolded_offset (i32) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: i32.const 24
+; CHECK-NEXT: i32.add
+; CHECK-NEXT: v128.const 0x0p0, 0x0p0
+; CHECK-NEXT: v128.load64_lane 0, 0
+; CHECK-NEXT: # fallthrough-return
+ %q = ptrtoint ptr %p to i32
+ %r = add nsw i32 %q, 24
+ %s = inttoptr i32 %r to ptr
+ %x = load double, ptr %s
+ %t = insertelement <2 x double> zeroinitializer, double %x, i32 0
+ ret <2 x double> %t
+}
+
+define <2 x double> @load_zero_double_with_unfolded_gep_offset(ptr %p) {
+; CHECK-LABEL: load_zero_double_with_unfolded_gep_offset:
+; CHECK: .functype load_zero_double_with_unfolded_gep_offset (i32) -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get 0
+; CHECK-NEXT: i32.const 48
+; CHECK-NEXT: i32.add
+; CHECK-NEXT: v128.const 0x0p0, 0x0p0
+; CHECK-NEXT: v128.load64_lane 0, 0
+; CHECK-NEXT: # fallthrough-return
+ %s = getelementptr double, ptr %p, i32 6
+ %x = load double, ptr %s
+ %t = insertelement <2 x double> zeroinitializer, double %x, i32 0
+ ret <2 x double> %t
+}
+
+define <2 x double> @load_zero_double_from_numeric_address() {
+; CHECK-LABEL: load_zero_double_from_numeric_address:
+; CHECK: .functype load_zero_double_from_numeric_address () -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: i32.const 42
+; CHECK-NEXT: v128.const 0x0p0, 0x0p0
+; CHECK-NEXT: v128.load64_lane 0, 0
+; CHECK-NEXT: # fallthrough-return
+ %s = inttoptr i32 42 to ptr
+ %x = load double, ptr %s
+ %t = insertelement <2 x double> zeroinitializer, double %x, i32 0
+ ret <2 x double> %t
+}
+
+ at gv_double = global i32 0
+define <2 x double> @load_zero_double_from_global_address() {
+; CHECK-LABEL: load_zero_double_from_global_address:
+; CHECK: .functype load_zero_double_from_global_address () -> (v128)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: i32.const gv_double
+; CHECK-NEXT: v128.const 0x0p0, 0x0p0
+; CHECK-NEXT: v128.load64_lane 0, 0
+; CHECK-NEXT: # fallthrough-return
+ %x = load double, ptr @gv_double
+ %t = insertelement <2 x double> zeroinitializer, double %x, i32 0
+ ret <2 x double> %t
+}
>From 885106e92baff444d64e50500a7f45bdb71d69d1 Mon Sep 17 00:00:00 2001
From: Hanbum Park <kese111 at gmail.com>
Date: Mon, 15 Dec 2025 19:55:14 +0900
Subject: [PATCH 2/2] [WebAssembly] Support v128.load{32,64}_zero for f32 and
f64 types
This patch extends the `load_zero` pattern matching to
support floating-point vector types (`v4f32` and `v2f64`).
Previously, the optimization to generate `v128.load32_zero` and
`v128.load64_zero` was only enabled for integer types
(`v4i32` and `v2i64`). This change adds the necessary TableGen
patterns to correctly match scalar floating-point loads inserted
into zero-initialized vectors.
---
.../WebAssembly/WebAssemblyInstrInfo.td | 5 ++
.../WebAssembly/WebAssemblyInstrSIMD.td | 8 ++-
.../WebAssembly/simd-load-store-alignment.ll | 27 +++-----
.../WebAssembly/simd-load-zero-offset.ll | 64 ++++++-------------
4 files changed, 41 insertions(+), 63 deletions(-)
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
index 13d048a98d6ea..4c550768cef0f 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
@@ -245,6 +245,11 @@ def bool_node : PatLeaf<(i32 I32:$cond), [{
return CurDAG->computeKnownBits(Op).countMinLeadingZeros() == 31;
}]>;
+/// Floating point constants
+def fpimm0 : PatLeaf<(fpimm), [{
+ return N->isExactlyValue(+0.0);
+}]>;
+
//===----------------------------------------------------------------------===//
// WebAssembly Register to Stack instruction mapping
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td
index 0bdddcffd723d..72feb5492c67a 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td
@@ -300,7 +300,6 @@ foreach vec = [I32x4, I64x2, F32x4, F64x2] in {
defm : LoadPat<vec.vt, pat, inst>;
}
-// TODO: f32x4 and f64x2 as well
foreach vec = [I32x4, I64x2] in {
defvar inst = "LOAD_ZERO_"#vec.lane_bits;
defvar pat = PatFrag<(ops node:$ptr),
@@ -308,6 +307,13 @@ foreach vec = [I32x4, I64x2] in {
defm : LoadPat<vec.vt, pat, inst>;
}
+foreach vec = [F32x4, F64x2] in {
+ defvar inst = "LOAD_ZERO_"#vec.lane_bits;
+ defvar pat = PatFrag<(ops node:$ptr),
+ (vector_insert (vec.splat (vec.lane_vt fpimm0)), (vec.lane_vt (load $ptr)), 0)>;
+ defm : LoadPat<vec.vt, pat, inst>;
+}
+
// Load lane
multiclass SIMDLoadLane<bits<32> lane_bits, bits<32> simdop> {
defvar name = "v128.load"#lane_bits#"_lane";
diff --git a/llvm/test/CodeGen/WebAssembly/simd-load-store-alignment.ll b/llvm/test/CodeGen/WebAssembly/simd-load-store-alignment.ll
index 896a8bfd79945..59ad44439c456 100644
--- a/llvm/test/CodeGen/WebAssembly/simd-load-store-alignment.ll
+++ b/llvm/test/CodeGen/WebAssembly/simd-load-store-alignment.ll
@@ -1430,8 +1430,7 @@ define <4 x float> @load_zero_float_a1(ptr %p) {
; CHECK: .functype load_zero_float_a1 (i32) -> (v128)
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 0
-; CHECK-NEXT: v128.const 0x0p0, 0x0p0, 0x0p0, 0x0p0
-; CHECK-NEXT: v128.load32_lane 0:p2align=0, 0
+; CHECK-NEXT: v128.load32_zero 0:p2align=0
; CHECK-NEXT: # fallthrough-return
%x = load float, ptr %p, align 1
%v = insertelement <4 x float> zeroinitializer, float %x, i32 0
@@ -1443,8 +1442,7 @@ define <4 x float> @load_zero_float_a2(ptr %p) {
; CHECK: .functype load_zero_float_a2 (i32) -> (v128)
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 0
-; CHECK-NEXT: v128.const 0x0p0, 0x0p0, 0x0p0, 0x0p0
-; CHECK-NEXT: v128.load32_lane 0:p2align=1, 0
+; CHECK-NEXT: v128.load32_zero 0:p2align=1
; CHECK-NEXT: # fallthrough-return
%x = load float, ptr %p, align 2
%v = insertelement <4 x float> zeroinitializer, float %x, i32 0
@@ -1457,8 +1455,7 @@ define <4 x float> @load_zero_float_a4(ptr %p) {
; CHECK: .functype load_zero_float_a4 (i32) -> (v128)
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 0
-; CHECK-NEXT: v128.const 0x0p0, 0x0p0, 0x0p0, 0x0p0
-; CHECK-NEXT: v128.load32_lane 0, 0
+; CHECK-NEXT: v128.load32_zero 0
; CHECK-NEXT: # fallthrough-return
%x = load float, ptr %p, align 4
%v = insertelement <4 x float> zeroinitializer, float %x, i32 0
@@ -1471,8 +1468,7 @@ define <4 x float> @load_zero_float_a8(ptr %p) {
; CHECK: .functype load_zero_float_a8 (i32) -> (v128)
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 0
-; CHECK-NEXT: v128.const 0x0p0, 0x0p0, 0x0p0, 0x0p0
-; CHECK-NEXT: v128.load32_lane 0, 0
+; CHECK-NEXT: v128.load32_zero 0
; CHECK-NEXT: # fallthrough-return
%x = load float, ptr %p, align 8
%v = insertelement <4 x float> zeroinitializer, float %x, i32 0
@@ -1584,8 +1580,7 @@ define <2 x double> @load_zero_double_a1(ptr %p) {
; CHECK: .functype load_zero_double_a1 (i32) -> (v128)
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 0
-; CHECK-NEXT: v128.const 0x0p0, 0x0p0
-; CHECK-NEXT: v128.load64_lane 0:p2align=0, 0
+; CHECK-NEXT: v128.load64_zero 0:p2align=0
; CHECK-NEXT: # fallthrough-return
%x = load double, ptr %p, align 1
%v = insertelement <2 x double> zeroinitializer, double %x, i32 0
@@ -1597,8 +1592,7 @@ define <2 x double> @load_zero_double_a2(ptr %p) {
; CHECK: .functype load_zero_double_a2 (i32) -> (v128)
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 0
-; CHECK-NEXT: v128.const 0x0p0, 0x0p0
-; CHECK-NEXT: v128.load64_lane 0:p2align=1, 0
+; CHECK-NEXT: v128.load64_zero 0:p2align=1
; CHECK-NEXT: # fallthrough-return
%x = load double, ptr %p, align 2
%v = insertelement <2 x double> zeroinitializer, double %x, i32 0
@@ -1610,8 +1604,7 @@ define <2 x double> @load_zero_double_a4(ptr %p) {
; CHECK: .functype load_zero_double_a4 (i32) -> (v128)
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 0
-; CHECK-NEXT: v128.const 0x0p0, 0x0p0
-; CHECK-NEXT: v128.load64_lane 0:p2align=2, 0
+; CHECK-NEXT: v128.load64_zero 0:p2align=2
; CHECK-NEXT: # fallthrough-return
%x = load double, ptr %p, align 4
%v = insertelement <2 x double> zeroinitializer, double %x, i32 0
@@ -1624,8 +1617,7 @@ define <2 x double> @load_zero_double_a8(ptr %p) {
; CHECK: .functype load_zero_double_a8 (i32) -> (v128)
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 0
-; CHECK-NEXT: v128.const 0x0p0, 0x0p0
-; CHECK-NEXT: v128.load64_lane 0, 0
+; CHECK-NEXT: v128.load64_zero 0
; CHECK-NEXT: # fallthrough-return
%x = load double, ptr %p, align 8
%v = insertelement <2 x double> zeroinitializer, double %x, i32 0
@@ -1638,8 +1630,7 @@ define <2 x double> @load_zero_double_a16(ptr %p) {
; CHECK: .functype load_zero_double_a16 (i32) -> (v128)
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 0
-; CHECK-NEXT: v128.const 0x0p0, 0x0p0
-; CHECK-NEXT: v128.load64_lane 0, 0
+; CHECK-NEXT: v128.load64_zero 0
; CHECK-NEXT: # fallthrough-return
%x = load double, ptr %p, align 16
%v = insertelement <2 x double> zeroinitializer, double %x, i32 0
diff --git a/llvm/test/CodeGen/WebAssembly/simd-load-zero-offset.ll b/llvm/test/CodeGen/WebAssembly/simd-load-zero-offset.ll
index 06fda8a1061d6..94b3ce2bb0974 100644
--- a/llvm/test/CodeGen/WebAssembly/simd-load-zero-offset.ll
+++ b/llvm/test/CodeGen/WebAssembly/simd-load-zero-offset.ll
@@ -127,8 +127,7 @@ define <4 x float> @load_zero_float_no_offset(ptr %p) {
; CHECK: .functype load_zero_float_no_offset (i32) -> (v128)
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 0
-; CHECK-NEXT: v128.const 0x0p0, 0x0p0, 0x0p0, 0x0p0
-; CHECK-NEXT: v128.load32_lane 0, 0
+; CHECK-NEXT: v128.load32_zero 0
; CHECK-NEXT: # fallthrough-return
%x = load float, ptr %p
%v = insertelement <4 x float> zeroinitializer, float %x, i32 0
@@ -140,10 +139,7 @@ define <4 x float> @load_zero_float_with_folded_offset(ptr %p) {
; CHECK: .functype load_zero_float_with_folded_offset (i32) -> (v128)
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 0
-; CHECK-NEXT: i32.const 24
-; CHECK-NEXT: i32.add
-; CHECK-NEXT: v128.const 0x0p0, 0x0p0, 0x0p0, 0x0p0
-; CHECK-NEXT: v128.load32_lane 0, 0
+; CHECK-NEXT: v128.load32_zero 24
; CHECK-NEXT: # fallthrough-return
%q = ptrtoint ptr %p to i32
%r = add nuw i32 %q, 24
@@ -158,10 +154,7 @@ define <4 x float> @load_zero_float_with_folded_gep_offset(ptr %p) {
; CHECK: .functype load_zero_float_with_folded_gep_offset (i32) -> (v128)
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 0
-; CHECK-NEXT: i32.const 24
-; CHECK-NEXT: i32.add
-; CHECK-NEXT: v128.const 0x0p0, 0x0p0, 0x0p0, 0x0p0
-; CHECK-NEXT: v128.load32_lane 0, 0
+; CHECK-NEXT: v128.load32_zero 24
; CHECK-NEXT: # fallthrough-return
%s = getelementptr inbounds float, ptr %p, i32 6
%x = load float, ptr %s
@@ -176,8 +169,7 @@ define <4 x float> @load_zero_float_with_unfolded_gep_negative_offset(ptr %p) {
; CHECK-NEXT: local.get 0
; CHECK-NEXT: i32.const -24
; CHECK-NEXT: i32.add
-; CHECK-NEXT: v128.const 0x0p0, 0x0p0, 0x0p0, 0x0p0
-; CHECK-NEXT: v128.load32_lane 0, 0
+; CHECK-NEXT: v128.load32_zero 0
; CHECK-NEXT: # fallthrough-return
%s = getelementptr inbounds float, ptr %p, i32 -6
%x = load float, ptr %s
@@ -192,8 +184,7 @@ define <4 x float> @load_zero_float_with_unfolded_offset(ptr %p) {
; CHECK-NEXT: local.get 0
; CHECK-NEXT: i32.const 24
; CHECK-NEXT: i32.add
-; CHECK-NEXT: v128.const 0x0p0, 0x0p0, 0x0p0, 0x0p0
-; CHECK-NEXT: v128.load32_lane 0, 0
+; CHECK-NEXT: v128.load32_zero 0
; CHECK-NEXT: # fallthrough-return
%q = ptrtoint ptr %p to i32
%r = add nsw i32 %q, 24
@@ -210,8 +201,7 @@ define <4 x float> @load_zero_float_with_unfolded_gep_offset(ptr %p) {
; CHECK-NEXT: local.get 0
; CHECK-NEXT: i32.const 24
; CHECK-NEXT: i32.add
-; CHECK-NEXT: v128.const 0x0p0, 0x0p0, 0x0p0, 0x0p0
-; CHECK-NEXT: v128.load32_lane 0, 0
+; CHECK-NEXT: v128.load32_zero 0
; CHECK-NEXT: # fallthrough-return
%s = getelementptr float, ptr %p, i32 6
%x = load float, ptr %s
@@ -223,9 +213,8 @@ define <4 x float> @load_zero_float_from_numeric_address() {
; CHECK-LABEL: load_zero_float_from_numeric_address:
; CHECK: .functype load_zero_float_from_numeric_address () -> (v128)
; CHECK-NEXT: # %bb.0:
-; CHECK-NEXT: i32.const 42
-; CHECK-NEXT: v128.const 0x0p0, 0x0p0, 0x0p0, 0x0p0
-; CHECK-NEXT: v128.load32_lane 0, 0
+; CHECK-NEXT: i32.const 0
+; CHECK-NEXT: v128.load32_zero 42
; CHECK-NEXT: # fallthrough-return
%s = inttoptr i32 42 to ptr
%x = load float, ptr %s
@@ -238,9 +227,8 @@ define <4 x float> @load_zero_float_from_global_address() {
; CHECK-LABEL: load_zero_float_from_global_address:
; CHECK: .functype load_zero_float_from_global_address () -> (v128)
; CHECK-NEXT: # %bb.0:
-; CHECK-NEXT: i32.const gv_float
-; CHECK-NEXT: v128.const 0x0p0, 0x0p0, 0x0p0, 0x0p0
-; CHECK-NEXT: v128.load32_lane 0, 0
+; CHECK-NEXT: i32.const 0
+; CHECK-NEXT: v128.load32_zero gv_float
; CHECK-NEXT: # fallthrough-return
%x = load float, ptr @gv_float
%t = insertelement <4 x float> zeroinitializer, float %x, i32 0
@@ -370,8 +358,7 @@ define <2 x double> @load_zero_double_no_offset(ptr %p) {
; CHECK: .functype load_zero_double_no_offset (i32) -> (v128)
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 0
-; CHECK-NEXT: v128.const 0x0p0, 0x0p0
-; CHECK-NEXT: v128.load64_lane 0, 0
+; CHECK-NEXT: v128.load64_zero 0
; CHECK-NEXT: # fallthrough-return
%x = load double, ptr %p
%v = insertelement <2 x double> zeroinitializer, double %x, i32 0
@@ -383,10 +370,7 @@ define <2 x double> @load_zero_double_with_folded_offset(ptr %p) {
; CHECK: .functype load_zero_double_with_folded_offset (i32) -> (v128)
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 0
-; CHECK-NEXT: i32.const 24
-; CHECK-NEXT: i32.add
-; CHECK-NEXT: v128.const 0x0p0, 0x0p0
-; CHECK-NEXT: v128.load64_lane 0, 0
+; CHECK-NEXT: v128.load64_zero 24
; CHECK-NEXT: # fallthrough-return
%q = ptrtoint ptr %p to i32
%r = add nuw i32 %q, 24
@@ -401,10 +385,7 @@ define <2 x double> @load_zero_double_with_folded_gep_offset(ptr %p) {
; CHECK: .functype load_zero_double_with_folded_gep_offset (i32) -> (v128)
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 0
-; CHECK-NEXT: i32.const 48
-; CHECK-NEXT: i32.add
-; CHECK-NEXT: v128.const 0x0p0, 0x0p0
-; CHECK-NEXT: v128.load64_lane 0, 0
+; CHECK-NEXT: v128.load64_zero 48
; CHECK-NEXT: # fallthrough-return
%s = getelementptr inbounds double, ptr %p, i32 6
%x = load double, ptr %s
@@ -419,8 +400,7 @@ define <2 x double> @load_zero_double_with_unfolded_gep_negative_offset(ptr %p)
; CHECK-NEXT: local.get 0
; CHECK-NEXT: i32.const -48
; CHECK-NEXT: i32.add
-; CHECK-NEXT: v128.const 0x0p0, 0x0p0
-; CHECK-NEXT: v128.load64_lane 0, 0
+; CHECK-NEXT: v128.load64_zero 0
; CHECK-NEXT: # fallthrough-return
%s = getelementptr inbounds double, ptr %p, i32 -6
%x = load double, ptr %s
@@ -435,8 +415,7 @@ define <2 x double> @load_zero_double_with_unfolded_offset(ptr %p) {
; CHECK-NEXT: local.get 0
; CHECK-NEXT: i32.const 24
; CHECK-NEXT: i32.add
-; CHECK-NEXT: v128.const 0x0p0, 0x0p0
-; CHECK-NEXT: v128.load64_lane 0, 0
+; CHECK-NEXT: v128.load64_zero 0
; CHECK-NEXT: # fallthrough-return
%q = ptrtoint ptr %p to i32
%r = add nsw i32 %q, 24
@@ -453,8 +432,7 @@ define <2 x double> @load_zero_double_with_unfolded_gep_offset(ptr %p) {
; CHECK-NEXT: local.get 0
; CHECK-NEXT: i32.const 48
; CHECK-NEXT: i32.add
-; CHECK-NEXT: v128.const 0x0p0, 0x0p0
-; CHECK-NEXT: v128.load64_lane 0, 0
+; CHECK-NEXT: v128.load64_zero 0
; CHECK-NEXT: # fallthrough-return
%s = getelementptr double, ptr %p, i32 6
%x = load double, ptr %s
@@ -466,9 +444,8 @@ define <2 x double> @load_zero_double_from_numeric_address() {
; CHECK-LABEL: load_zero_double_from_numeric_address:
; CHECK: .functype load_zero_double_from_numeric_address () -> (v128)
; CHECK-NEXT: # %bb.0:
-; CHECK-NEXT: i32.const 42
-; CHECK-NEXT: v128.const 0x0p0, 0x0p0
-; CHECK-NEXT: v128.load64_lane 0, 0
+; CHECK-NEXT: i32.const 0
+; CHECK-NEXT: v128.load64_zero 42
; CHECK-NEXT: # fallthrough-return
%s = inttoptr i32 42 to ptr
%x = load double, ptr %s
@@ -481,9 +458,8 @@ define <2 x double> @load_zero_double_from_global_address() {
; CHECK-LABEL: load_zero_double_from_global_address:
; CHECK: .functype load_zero_double_from_global_address () -> (v128)
; CHECK-NEXT: # %bb.0:
-; CHECK-NEXT: i32.const gv_double
-; CHECK-NEXT: v128.const 0x0p0, 0x0p0
-; CHECK-NEXT: v128.load64_lane 0, 0
+; CHECK-NEXT: i32.const 0
+; CHECK-NEXT: v128.load64_zero gv_double
; CHECK-NEXT: # fallthrough-return
%x = load double, ptr @gv_double
%t = insertelement <2 x double> zeroinitializer, double %x, i32 0
More information about the llvm-commits
mailing list