[llvm] [WebAssembly] Select lane stores for floating-point vectors (PR #219186)

via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 27 04:33:30 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-webassembly

Author: Anutosh Bhat (anutosh491)

<details>
<summary>Changes</summary>

This extends the existing integer vector lane-store patterns to the equivalent floating-point vector types. The underlying WebAssembly instructions are type-agnostic lane stores. 

That being said I think something like `STORE_LANE_I32x4_A32` can be misleading when dealing with floating-point vectors. (should there be a rename or something ?)

---
Full diff: https://github.com/llvm/llvm-project/pull/219186.diff


2 Files Affected:

- (modified) llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td (+19-12) 
- (modified) llvm/test/CodeGen/WebAssembly/simd-load-lane-offset.ll (+90) 


``````````diff
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td
index 3e9783a9d1f25..17f9379e5453e 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td
@@ -442,16 +442,18 @@ defm "" : SIMDStoreLane<I16x8, 0x59>;
 defm "" : SIMDStoreLane<I32x4, 0x5a>;
 defm "" : SIMDStoreLane<I64x2, 0x5b>;
 
-multiclass StoreLanePat<Vec vec, SDPatternOperator kind> {
+multiclass StoreLanePat<Vec vec, Vec instVec, SDPatternOperator kind> {
   def : Pat<(kind (AddrOps32 offset32_op:$offset, I32:$addr),
                   (vec.vt V128:$vec),
                   (i32 vec.lane_idx:$idx)),
-            (!cast<NI>("STORE_LANE_"#vec#"_A32") 0, $offset, imm:$idx, $addr, $vec)>,
+            (!cast<NI>("STORE_LANE_"#instVec#"_A32") 0, $offset, imm:$idx,
+                                                       $addr, $vec)>,
         Requires<[HasAddr32]>;
   def : Pat<(kind (AddrOps64 offset64_op:$offset, I64:$addr),
                   (vec.vt V128:$vec),
                   (i32 vec.lane_idx:$idx)),
-            (!cast<NI>("STORE_LANE_"#vec#"_A64") 0, $offset, imm:$idx, $addr, $vec)>,
+            (!cast<NI>("STORE_LANE_"#instVec#"_A64") 0, $offset, imm:$idx,
+                                                       $addr, $vec)>,
         Requires<[HasAddr64]>;
 }
 
@@ -462,18 +464,23 @@ def store16_lane :
   PatFrag<(ops node:$ptr, node:$vec, node:$idx),
           (truncstorei16 (i32 (vector_extract $vec, $idx)), $ptr)>;
 def store32_lane :
-  PatFrag<(ops node:$ptr, node:$vec, node:$idx),
-          (store (i32 (vector_extract $vec, $idx)), $ptr)>;
+  PatFrags<(ops node:$ptr, node:$vec, node:$idx), [
+           (store (i32 (vector_extract $vec, $idx)), $ptr),
+           (store (f32 (vector_extract $vec, $idx)), $ptr)
+]>;
 def store64_lane :
-  PatFrag<(ops node:$ptr, node:$vec, node:$idx),
-          (store (i64 (vector_extract $vec, $idx)), $ptr)>;
-// TODO: floating point lanes as well
+  PatFrags<(ops node:$ptr, node:$vec, node:$idx), [
+           (store (i64 (vector_extract $vec, $idx)), $ptr),
+           (store (f64 (vector_extract $vec, $idx)), $ptr)
+]>;
 
 let AddedComplexity = 1 in {
-defm : StoreLanePat<I8x16, store8_lane>;
-defm : StoreLanePat<I16x8, store16_lane>;
-defm : StoreLanePat<I32x4, store32_lane>;
-defm : StoreLanePat<I64x2, store64_lane>;
+defm : StoreLanePat<I8x16, I8x16, store8_lane>;
+defm : StoreLanePat<I16x8, I16x8, store16_lane>;
+defm : StoreLanePat<I32x4, I32x4, store32_lane>;
+defm : StoreLanePat<I64x2, I64x2, store64_lane>;
+defm : StoreLanePat<F32x4, I32x4, store32_lane>;
+defm : StoreLanePat<F64x2, I64x2, store64_lane>;
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/llvm/test/CodeGen/WebAssembly/simd-load-lane-offset.ll b/llvm/test/CodeGen/WebAssembly/simd-load-lane-offset.ll
index ff31d342b84f5..2e2dfcb26d5ac 100644
--- a/llvm/test/CodeGen/WebAssembly/simd-load-lane-offset.ll
+++ b/llvm/test/CodeGen/WebAssembly/simd-load-lane-offset.ll
@@ -1594,3 +1594,93 @@ define void @store_lane_i64_from_global_address(<2 x i64> %v) {
   store i64 %x, ptr @gv_i64
   ret void
 }
+
+;===----------------------------------------------------------------------------
+; Floating-point lane stores
+;===----------------------------------------------------------------------------
+
+define void @store_lane_f32_no_offset(<4 x float> %v, ptr %p) {
+; CHECK-LABEL: store_lane_f32_no_offset:
+; CHECK:         .functype store_lane_f32_no_offset (v128, i32) -> ()
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:    local.get 1
+; CHECK-NEXT:    local.get 0
+; CHECK-NEXT:    v128.store32_lane 0, 2
+; CHECK-NEXT:    # fallthrough-return
+;
+; MEM64-LABEL: store_lane_f32_no_offset:
+; MEM64:         .functype store_lane_f32_no_offset (v128, i64) -> ()
+; MEM64-NEXT:  # %bb.0:
+; MEM64-NEXT:    local.get 1
+; MEM64-NEXT:    local.get 0
+; MEM64-NEXT:    v128.store32_lane 0, 2
+; MEM64-NEXT:    # fallthrough-return
+  %x = extractelement <4 x float> %v, i32 2
+  store float %x, ptr %p
+  ret void
+}
+
+define void @store_lane_f32_with_folded_gep_offset(<4 x float> %v, ptr %p) {
+; CHECK-LABEL: store_lane_f32_with_folded_gep_offset:
+; CHECK:         .functype store_lane_f32_with_folded_gep_offset (v128, i32) -> ()
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:    local.get 1
+; CHECK-NEXT:    local.get 0
+; CHECK-NEXT:    v128.store32_lane 24, 2
+; CHECK-NEXT:    # fallthrough-return
+;
+; MEM64-LABEL: store_lane_f32_with_folded_gep_offset:
+; MEM64:         .functype store_lane_f32_with_folded_gep_offset (v128, i64) -> ()
+; MEM64-NEXT:  # %bb.0:
+; MEM64-NEXT:    local.get 1
+; MEM64-NEXT:    local.get 0
+; MEM64-NEXT:    v128.store32_lane 24, 2
+; MEM64-NEXT:    # fallthrough-return
+  %s = getelementptr inbounds float, ptr %p, i32 6
+  %x = extractelement <4 x float> %v, i32 2
+  store float %x, ptr %s
+  ret void
+}
+
+define void @store_lane_f64_no_offset(<2 x double> %v, ptr %p) {
+; CHECK-LABEL: store_lane_f64_no_offset:
+; CHECK:         .functype store_lane_f64_no_offset (v128, i32) -> ()
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:    local.get 1
+; CHECK-NEXT:    local.get 0
+; CHECK-NEXT:    v128.store64_lane 0, 1
+; CHECK-NEXT:    # fallthrough-return
+;
+; MEM64-LABEL: store_lane_f64_no_offset:
+; MEM64:         .functype store_lane_f64_no_offset (v128, i64) -> ()
+; MEM64-NEXT:  # %bb.0:
+; MEM64-NEXT:    local.get 1
+; MEM64-NEXT:    local.get 0
+; MEM64-NEXT:    v128.store64_lane 0, 1
+; MEM64-NEXT:    # fallthrough-return
+  %x = extractelement <2 x double> %v, i32 1
+  store double %x, ptr %p
+  ret void
+}
+
+define void @store_lane_f64_with_folded_gep_offset(<2 x double> %v, ptr %p) {
+; CHECK-LABEL: store_lane_f64_with_folded_gep_offset:
+; CHECK:         .functype store_lane_f64_with_folded_gep_offset (v128, i32) -> ()
+; CHECK-NEXT:  # %bb.0:
+; CHECK-NEXT:    local.get 1
+; CHECK-NEXT:    local.get 0
+; CHECK-NEXT:    v128.store64_lane 48, 1
+; CHECK-NEXT:    # fallthrough-return
+;
+; MEM64-LABEL: store_lane_f64_with_folded_gep_offset:
+; MEM64:         .functype store_lane_f64_with_folded_gep_offset (v128, i64) -> ()
+; MEM64-NEXT:  # %bb.0:
+; MEM64-NEXT:    local.get 1
+; MEM64-NEXT:    local.get 0
+; MEM64-NEXT:    v128.store64_lane 48, 1
+; MEM64-NEXT:    # fallthrough-return
+  %s = getelementptr inbounds double, ptr %p, i32 6
+  %x = extractelement <2 x double> %v, i32 1
+  store double %x, ptr %s
+  ret void
+}

``````````

</details>


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


More information about the llvm-commits mailing list