[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