Repository: bytecodealliance/wasmtime
Pull request #9361 (2024-10-03 08:18:05)

s390x: Hard code the link register for ElfTlsGetOffset
The ElfTlsGetOffset pseudo-instruction already hard codes the rest of the abi anyway and if another abi is ever needed, adding another pseudo-instruction or an enum field to the existing one would likely be necessary anyway. Also remove a couple of dead_code allows.

cfallin: cc @uweigand -- this looks reasonable to me overall, and there's no functional change to the emitted code or the regalloc metadata (fields were only ever used with one value) -- but maybe there's a reason it was generic?
uweigand: Well, as long as the ELF ABI is the only s390x ABI supported by wasmtime, I guess it doesn't make any difference, really.

That said, this seems a step in the wrong direction to me: there *are* other ABIs used by other OSes on the platforms, and they do use different registers than r14 as the link register, so I'm not sure why it's an improvement to hard-code that value?  Logically, it is an ABI property, that's why I placed that choice in ABI code rather than ISA code.

bjorn3: The ret instruction is also hard coding r15 (stack pointer?) and it has a debug assert that r14 is used as link register. What other OSes use a different link register?
uweigand: > The ret instruction is also hard coding r15 (stack pointer?) 

Ah, not really.  This instruction uses a condition mask field as "R1", not an actual register field, and the contents are 15 (all mask bits set) to indicate a "branch on any condition", i.e. an unconditional branch.  It would have been clearer to add a variant of the `enc_rr` helper instead of passing the condition mask as a "register".

> and it has a debug assert that r14 is used as link register.

Huh, I'm surprised to see that.  Looks like @elliottt added a bunch of asserts here: https://github.com/bytecodealliance/wasmtime/pull/5172 - I'm not sure if there's anything in that diff that makes those asserts necessary?

> What other OSes use a different link register?

Well, XPLINK (the current main calling convention on z/OS) uses %r4, as one major example.


In general, I'm pretty sure in case we ever wanted to support a significantly different calling convention like XPLINK that uses different registers for the link register, the stack register, and pretty much any ABI-defined register, we will find places where the current code isn't fully generalized.  I tried to keep things general where it seemed easily possible, but didn't attempt any full review ...   I just don't see why it's beneficial now to make the code *less* general.

elliottt: > Huh, I'm surprised to see that. Looks like @elliottt added a bunch of asserts here: #5172 - I'm not sure if there's anything in that diff that makes those asserts necessary?

I think you're right, we should probably remove them. They're added in other cases to check that fixed constraints are respected, but as there's no fixed constraints in the constraint generation code in mod.rs, I don't think that assertion applies.

uweigand: > > Huh, I'm surprised to see that. Looks like @elliottt added a bunch of asserts here: #5172 - I'm not sure if there's anything in that diff that makes those asserts necessary?
> 
> I think you're right, we should probably remove them. They're added in other cases to check that fixed constraints are respected, but as there's no fixed constraints in the constraint generation code in mod.rs, I don't think that assertion applies.

Thanks.  I've now submitted a PR: https://github.com/bytecodealliance/wasmtime/pull/9397
bjorn3: I removed the call instruction changes. I think it still makes sense to keep them for the ElfTlsGetOffset pseudo-instruction as that one hard codes a single abi anyway.

Patch:
diff --git a/cranelift/bforest/src/node.rs b/cranelift/bforest/src/node.rs
index 443c112ed..848c657e8 100644
--- a/cranelift/bforest/src/node.rs
+++ b/cranelift/bforest/src/node.rs
@@ -13,7 +13,6 @@ use core::fmt;
 ///
 /// An inner node contains at least M/2 node references unless it is the right-most node at its
 /// level. A leaf node contains at least N/2 keys unless it is the right-most leaf.
-#[allow(dead_code)] // workaround for https://github.com/rust-lang/rust/issues/64362
 pub(super) enum NodeData<F: Forest> {
     Inner {
         /// The number of keys in this node.
diff --git a/cranelift/codegen/src/isa/aarch64/inst.isle b/cranelift/codegen/src/isa/aarch64/inst.isle
index e5cd7d58e..eb2124507 100644
--- a/cranelift/codegen/src/isa/aarch64/inst.isle
+++ b/cranelift/codegen/src/isa/aarch64/inst.isle
@@ -3527,7 +3527,7 @@
         (c_lo Reg (value_regs_get c 0))
         (c_hi Reg (value_regs_get c 1))
         (c_test Reg (orr $I64 c_lo c_hi)))
-      (side_effect 
+      (side_effect
        (SideEffectNoResult.Inst
         (MInst.TrapIf (zero_cond_to_cond_br zero_cond c_test) trap_code)))))
 
@@ -4036,9 +4036,15 @@
         (fpu_extend (vec_dup_imm imm $false (VectorSize.Size64x2)) (ScalarSize.Size64)))
 
 (rule 1 (splat_const n size)
+        (if-let $true (vec_dup_fp_imm_supports_lane_size (vector_lane_size size)))
         (if-let imm (asimd_fp_mod_imm_from_u64 n (vector_lane_size size)))
         (vec_dup_fp_imm imm size))
 
+(decl pure vec_dup_fp_imm_supports_lane_size (ScalarSize) bool)
+(rule 1 (vec_dup_fp_imm_supports_lane_size (ScalarSize.Size32)) $true)
+(rule 1 (vec_dup_fp_imm_supports_lane_size (ScalarSize.Size64)) $true)
+(rule (vec_dup_fp_imm_supports_lane_size _) $false)
+
 ;; The base case for splat is to use `vec_dup` with the immediate loaded into a
 ;; register.
 (rule (splat_const n size)
diff --git a/cranelift/codegen/src/isa/riscv64/inst/imms.rs b/cranelift/codegen/src/isa/riscv64/inst/imms.rs
index 28f279154..8f53506ce 100644
--- a/cranelift/codegen/src/isa/riscv64/inst/imms.rs
+++ b/cranelift/codegen/src/isa/riscv64/inst/imms.rs
@@ -2,7 +2,6 @@
 
 // Some variants are never constructed, but we still want them as options in the future.
 use super::Inst;
-#[allow(dead_code)]
 use std::fmt::{Debug, Display, Formatter, Result};
 
 #[derive(Copy, Clone, Debug, Default)]
diff --git a/cranelift/codegen/src/isa/s390x/inst.isle b/cranelift/codegen/src/isa/s390x/inst.isle
index 342f5846f..173cb7bd2 100644
--- a/cranelift/codegen/src/isa/s390x/inst.isle
+++ b/cranelift/codegen/src/isa/s390x/inst.isle
@@ -1020,7 +1020,6 @@
       (tls_offset WritableReg)
       (got Reg)
       (got_offset Reg)
-      (link WritableReg)
       (symbol BoxSymbolReloc))
 ))
 
diff --git a/cranelift/codegen/src/isa/s390x/inst/emit.rs b/cranelift/codegen/src/isa/s390x/inst/emit.rs
index eb42cc15a..24bd4cb0f 100644
--- a/cranelift/codegen/src/isa/s390x/inst/emit.rs
+++ b/cranelift/codegen/src/isa/s390x/inst/emit.rs
@@ -3250,9 +3250,7 @@ impl Inst {
                 put(sink, &enc_rr(opcode, gpr(15), rn));
                 sink.add_call_site();
             }
-            &Inst::ElfTlsGetOffset {
-                ref symbol, link, ..
-            } => {
+            &Inst::ElfTlsGetOffset { ref symbol, .. } => {
                 let opcode = 0xc05; // BRASL
 
                 // Add relocation for target function. This has to be done
@@ -3265,7 +3263,7 @@ impl Inst {
                     _ => unreachable!(),
                 }
 
-                put(sink, &enc_ril_b(opcode, link.to_reg(), 0));
+                put(sink, &enc_ril_b(opcode, gpr(14), 0));
                 sink.add_call_site();
             }
             &Inst::Args { .. } => {}
diff --git a/cranelift/codegen/src/isa/s390x/inst/mod.rs b/cranelift/codegen/src/isa/s390x/inst/mod.rs
index 65c5d52ec..75e7daab7 100644
--- a/cranelift/codegen/src/isa/s390x/inst/mod.rs
+++ b/cranelift/codegen/src/isa/s390x/inst/mod.rs
@@ -923,7 +923,6 @@ fn s390x_get_operands(inst: &mut Inst, collector: &mut DenyReuseVisitor<impl Ope
             tls_offset,
             got,
             got_offset,
-            link,
             ..
         } => {
             collector.reg_fixed_use(got, gpr(12));
@@ -931,7 +930,7 @@ fn s390x_get_operands(inst: &mut Inst, collector: &mut DenyReuseVisitor<impl Ope
             collector.reg_fixed_def(tls_offset, gpr(2));
 
             let mut clobbers = S390xMachineDeps::get_regs_clobbered_by_call(CallConv::SystemV);
-            clobbers.add(link.to_reg().to_real_reg().unwrap().into());
+            clobbers.add(gpr_preg(14));
             clobbers.remove(gpr_preg(2));
             collector.reg_clobbers(clobbers);
         }
@@ -3164,19 +3163,14 @@ impl Inst {
                 };
                 format!("return_call_ind {rn}{callee_pop_size}")
             }
-            &Inst::ElfTlsGetOffset {
-                ref symbol,
-                ref link,
-                ..
-            } => {
-                let link = link.to_reg();
+            &Inst::ElfTlsGetOffset { ref symbol, .. } => {
                 let dest = match &**symbol {
                     SymbolReloc::TlsGd { name } => {
                         format!("tls_gdcall:{}", name.display(None))
                     }
                     _ => unreachable!(),
                 };
-                format!("brasl {}, {}", show_reg(link), dest)
+                format!("brasl {}, {}", show_reg(gpr(14)), dest)
             }
             &Inst::Args { ref args } => {
                 let mut s = "args".to_string();
diff --git a/cranelift/codegen/src/isa/s390x/lower.isle b/cranelift/codegen/src/isa/s390x/lower.isle
index 225918a22..1b21021f0 100644
--- a/cranelift/codegen/src/isa/s390x/lower.isle
+++ b/cranelift/codegen/src/isa/s390x/lower.isle
@@ -2279,7 +2279,7 @@
 (rule (lib_call_tls_get_offset got got_offset symbol)
       (let ((tls_offset WritableReg (temp_writable_reg $I64))
             (_ Unit (abi_for_elf_tls_get_offset))
-            (_ Unit (emit (MInst.ElfTlsGetOffset tls_offset got got_offset (writable_link_reg) symbol))))
+            (_ Unit (emit (MInst.ElfTlsGetOffset tls_offset got got_offset symbol))))
         tls_offset))
 
 (decl abi_for_elf_tls_get_offset () Unit)
diff --git a/crates/cranelift/src/gc/enabled/drc.rs b/crates/cranelift/src/gc/enabled/drc.rs
index 18e7fa3cb..e86068da7 100644
--- a/crates/cranelift/src/gc/enabled/drc.rs
+++ b/crates/cranelift/src/gc/enabled/drc.rs
@@ -484,6 +484,14 @@ impl GcCompiler for DrcCompiler {
         );
 
         // Second, initialize each of the newly-allocated struct's fields.
+        //
+        // Note: we don't need to bounds-check the GC ref access here, since we
+        // trust the results of the allocation libcall.
+
+        let base = func_env.get_gc_heap_base(builder);
+        let extended_struct_ref =
+            uextend_i32_to_pointer_type(builder, func_env.pointer_type(), struct_ref);
+        let struct_addr = builder.ins().iadd(base, extended_struct_ref);
 
         let struct_ty = match &func_env.types[interned_type_index].composite_type {
             WasmCompositeType::Struct(s) => s,
@@ -497,13 +505,7 @@ impl GcCompiler for DrcCompiler {
                 wasmtime_environ::byte_size_of_wasm_ty_in_gc_heap(&ty.element_type);
             assert!(offset + size_of_access <= struct_size);
 
-            let field_addr = func_env.prepare_gc_ref_access(
-                builder,
-                struct_ref,
-                Offset::Static(offset),
-                BoundsCheck::Object(struct_size_val),
-            );
-
+            let field_addr = builder.ins().iadd_imm(struct_addr, i64::from(offset));
             self.init_field(func_env, builder, field_addr, ty.element_type, *val)?;
         }
 


Test patch:
diff --git a/tests/disas/gc/funcref-in-gc-heap-new.wat b/tests/disas/gc/funcref-in-gc-heap-new.wat
index 865f8cbf1..6b41cc34b 100644
--- a/tests/disas/gc/funcref-in-gc-heap-new.wat
+++ b/tests/disas/gc/funcref-in-gc-heap-new.wat
@@ -27,23 +27,18 @@
 ;; @0020                               v4 = iconst.i32 24
 ;; @0020                               v8 = iconst.i32 8
 ;; @0020                               v9 = call fn0(v0, v6, v7, v4, v8)  ; v6 = -1342177280, v7 = 0, v4 = 24, v8 = 8
-;;                                     v25 = stack_addr.i64 ss0
-;;                                     store notrap v9, v25
-;; @0020                               v14 = uextend.i64 v9
-;; @0020                               v15 = iconst.i64 16
-;; @0020                               v16 = uadd_overflow_trap v14, v15, user1  ; v15 = 16
-;;                                     v28 = iconst.i64 24
-;; @0020                               v18 = uadd_overflow_trap v14, v28, user1  ; v28 = 24
-;; @0020                               v13 = load.i64 notrap aligned readonly v0+48
-;; @0020                               v19 = icmp ule v18, v13
-;; @0020                               trapz v19, user1
-;; @0020                               v22 = call fn1(v0, v2), stack_map=[i32 @ ss0+0]
+;;                                     v19 = stack_addr.i64 ss0
+;;                                     store notrap v9, v19
+;; @0020                               v16 = call fn1(v0, v2), stack_map=[i32 @ ss0+0]
 ;; @0020                               v11 = load.i64 notrap aligned readonly v0+40
-;; @0020                               v20 = iadd v11, v16
-;; @0020                               store notrap aligned little v22, v20
-;;                                     v23 = load.i32 notrap v25
+;; @0020                               v12 = uextend.i64 v9
+;; @0020                               v13 = iadd v11, v12
+;;                                     v21 = iconst.i64 16
+;; @0020                               v14 = iadd v13, v21  ; v21 = 16
+;; @0020                               store notrap aligned little v16, v14
+;;                                     v17 = load.i32 notrap v19
 ;; @0023                               jump block1
 ;;
 ;;                                 block1:
-;; @0023                               return v23
+;; @0023                               return v17
 ;; }
diff --git a/tests/disas/gc/struct-new-default.wat b/tests/disas/gc/struct-new-default.wat
index c9d22b9c0..56cf3b7be 100644
--- a/tests/disas/gc/struct-new-default.wat
+++ b/tests/disas/gc/struct-new-default.wat
@@ -26,48 +26,40 @@
 ;; @0021                               v6 = iconst.i32 32
 ;; @0021                               v10 = iconst.i32 8
 ;; @0021                               v11 = call fn0(v0, v8, v4, v6, v10)  ; v8 = -1342177280, v4 = 0, v6 = 32, v10 = 8
-;; @0021                               v16 = uextend.i64 v11
-;; @0021                               v17 = iconst.i64 16
-;; @0021                               v18 = uadd_overflow_trap v16, v17, user1  ; v17 = 16
-;;                                     v74 = iconst.i64 32
-;; @0021                               v20 = uadd_overflow_trap v16, v74, user1  ; v74 = 32
-;; @0021                               v15 = load.i64 notrap aligned readonly v0+48
-;; @0021                               v21 = icmp ule v20, v15
-;; @0021                               trapz v21, user1
 ;; @0021                               v3 = f32const 0.0
 ;; @0021                               v13 = load.i64 notrap aligned readonly v0+40
-;; @0021                               v22 = iadd v13, v18
-;; @0021                               store notrap aligned little v3, v22  ; v3 = 0.0
-;; @0021                               v28 = iconst.i64 20
-;; @0021                               v29 = uadd_overflow_trap v16, v28, user1  ; v28 = 20
-;; @0021                               trapz v21, user1
-;; @0021                               v33 = iadd v13, v29
-;; @0021                               istore8 notrap aligned little v4, v33  ; v4 = 0
-;; @0021                               v39 = iconst.i64 24
-;; @0021                               v40 = uadd_overflow_trap v16, v39, user1  ; v39 = 24
-;; @0021                               trapz v21, user1
-;;                                     v81 = iconst.i8 1
-;; @0021                               brif v81, block3, block2  ; v81 = 1
+;; @0021                               v14 = uextend.i64 v11
+;; @0021                               v15 = iadd v13, v14
+;;                                     v46 = iconst.i64 16
+;; @0021                               v16 = iadd v15, v46  ; v46 = 16
+;; @0021                               store notrap aligned little v3, v16  ; v3 = 0.0
+;;                                     v47 = iconst.i64 20
+;; @0021                               v17 = iadd v15, v47  ; v47 = 20
+;; @0021                               istore8 notrap aligned little v4, v17  ; v4 = 0
+;;                                     v57 = iconst.i8 1
+;; @0021                               brif v57, block3, block2  ; v57 = 1
 ;;
 ;;                                 block2:
-;;                                     v88 = iconst.i64 0
-;; @0021                               v53 = iconst.i64 8
-;; @0021                               v54 = uadd_overflow_trap v88, v53, user1  ; v88 = 0, v53 = 8
-;; @0021                               v56 = uadd_overflow_trap v54, v53, user1  ; v53 = 8
-;; @0021                               v57 = icmp ule v56, v15
-;; @0021                               trapz v57, user1
-;; @0021                               v58 = iadd.i64 v13, v54
-;; @0021                               v59 = load.i64 notrap aligned v58
-;; @0021                               trapz v57, user1
-;;                                     v73 = iconst.i64 1
-;; @0021                               v60 = iadd v59, v73  ; v73 = 1
-;; @0021                               store notrap aligned v60, v58
+;;                                     v64 = iconst.i64 0
+;; @0021                               v27 = iconst.i64 8
+;; @0021                               v28 = uadd_overflow_trap v64, v27, user1  ; v64 = 0, v27 = 8
+;; @0021                               v30 = uadd_overflow_trap v28, v27, user1  ; v27 = 8
+;; @0021                               v25 = load.i64 notrap aligned readonly v0+48
+;; @0021                               v31 = icmp ule v30, v25
+;; @0021                               trapz v31, user1
+;; @0021                               v32 = iadd.i64 v13, v28
+;; @0021                               v33 = load.i64 notrap aligned v32
+;; @0021                               trapz v31, user1
+;;                                     v50 = iconst.i64 1
+;; @0021                               v34 = iadd v33, v50  ; v50 = 1
+;; @0021                               store notrap aligned v34, v32
 ;; @0021                               jump block3
 ;;
 ;;                                 block3:
-;;                                     v89 = iconst.i32 0
-;; @0021                               v44 = iadd.i64 v13, v40
-;; @0021                               store notrap aligned little v89, v44  ; v89 = 0
+;;                                     v65 = iconst.i32 0
+;;                                     v48 = iconst.i64 24
+;; @0021                               v18 = iadd.i64 v15, v48  ; v48 = 24
+;; @0021                               store notrap aligned little v65, v18  ; v65 = 0
 ;; @0024                               jump block1
 ;;
 ;;                                 block1:
diff --git a/tests/disas/gc/struct-new.wat b/tests/disas/gc/struct-new.wat
index 07c73449f..336de9fab 100644
--- a/tests/disas/gc/struct-new.wat
+++ b/tests/disas/gc/struct-new.wat
@@ -22,63 +22,55 @@
 ;;     stack_limit = gv2
 ;;
 ;;                                 block0(v0: i64, v1: i64, v2: f32, v3: i32, v4: i32):
-;;                                     v76 = stack_addr.i64 ss0
-;;                                     store notrap v4, v76
+;;                                     v50 = stack_addr.i64 ss0
+;;                                     store notrap v4, v50
 ;; @002a                               v8 = iconst.i32 -1342177280
 ;; @002a                               v9 = iconst.i32 0
 ;; @002a                               v6 = iconst.i32 32
 ;; @002a                               v10 = iconst.i32 8
 ;; @002a                               v11 = call fn0(v0, v8, v9, v6, v10), stack_map=[i32 @ ss0+0]  ; v8 = -1342177280, v9 = 0, v6 = 32, v10 = 8
-;; @002a                               v16 = uextend.i64 v11
-;; @002a                               v17 = iconst.i64 16
-;; @002a                               v18 = uadd_overflow_trap v16, v17, user1  ; v17 = 16
-;;                                     v83 = iconst.i64 32
-;; @002a                               v20 = uadd_overflow_trap v16, v83, user1  ; v83 = 32
-;; @002a                               v15 = load.i64 notrap aligned readonly v0+48
-;; @002a                               v21 = icmp ule v20, v15
-;; @002a                               trapz v21, user1
 ;; @002a                               v13 = load.i64 notrap aligned readonly v0+40
-;; @002a                               v22 = iadd v13, v18
-;; @002a                               store notrap aligned little v2, v22
-;; @002a                               v28 = iconst.i64 20
-;; @002a                               v29 = uadd_overflow_trap v16, v28, user1  ; v28 = 20
-;; @002a                               trapz v21, user1
-;; @002a                               v33 = iadd v13, v29
-;; @002a                               istore8 notrap aligned little v3, v33
-;; @002a                               v39 = iconst.i64 24
-;; @002a                               v40 = uadd_overflow_trap v16, v39, user1  ; v39 = 24
-;; @002a                               trapz v21, user1
-;;                                     v75 = load.i32 notrap v76
-;; @002a                               v45 = iconst.i32 -2
-;; @002a                               v46 = band v75, v45  ; v45 = -2
-;; @002a                               v47 = icmp eq v46, v9  ; v9 = 0
-;; @002a                               brif v47, block3, block2
+;; @002a                               v14 = uextend.i64 v11
+;; @002a                               v15 = iadd v13, v14
+;;                                     v51 = iconst.i64 16
+;; @002a                               v16 = iadd v15, v51  ; v51 = 16
+;; @002a                               store notrap aligned little v2, v16
+;;                                     v52 = iconst.i64 20
+;; @002a                               v17 = iadd v15, v52  ; v52 = 20
+;; @002a                               istore8 notrap aligned little v3, v17
+;;                                     v49 = load.i32 notrap v50
+;; @002a                               v19 = iconst.i32 -2
+;; @002a                               v20 = band v49, v19  ; v19 = -2
+;; @002a                               v21 = icmp eq v20, v9  ; v9 = 0
+;; @002a                               brif v21, block3, block2
 ;;
 ;;                                 block2:
-;; @002a                               v52 = uextend.i64 v75
-;; @002a                               v53 = iconst.i64 8
-;; @002a                               v54 = uadd_overflow_trap v52, v53, user1  ; v53 = 8
-;; @002a                               v56 = uadd_overflow_trap v54, v53, user1  ; v53 = 8
-;; @002a                               v57 = icmp ule v56, v15
-;; @002a                               trapz v57, user1
-;; @002a                               v58 = iadd.i64 v13, v54
-;; @002a                               v59 = load.i64 notrap aligned v58
-;;                                     v73 = load.i32 notrap v76
-;; @002a                               v65 = uextend.i64 v73
-;; @002a                               v67 = uadd_overflow_trap v65, v53, user1  ; v53 = 8
-;; @002a                               v69 = uadd_overflow_trap v67, v53, user1  ; v53 = 8
-;; @002a                               v70 = icmp ule v69, v15
-;; @002a                               trapz v70, user1
-;;                                     v80 = iconst.i64 1
-;; @002a                               v60 = iadd v59, v80  ; v80 = 1
-;; @002a                               v71 = iadd.i64 v13, v67
-;; @002a                               store notrap aligned v60, v71
+;; @002a                               v26 = uextend.i64 v49
+;; @002a                               v27 = iconst.i64 8
+;; @002a                               v28 = uadd_overflow_trap v26, v27, user1  ; v27 = 8
+;; @002a                               v30 = uadd_overflow_trap v28, v27, user1  ; v27 = 8
+;; @002a                               v25 = load.i64 notrap aligned readonly v0+48
+;; @002a                               v31 = icmp ule v30, v25
+;; @002a                               trapz v31, user1
+;; @002a                               v32 = iadd.i64 v13, v28
+;; @002a                               v33 = load.i64 notrap aligned v32
+;;                                     v47 = load.i32 notrap v50
+;; @002a                               v39 = uextend.i64 v47
+;; @002a                               v41 = uadd_overflow_trap v39, v27, user1  ; v27 = 8
+;; @002a                               v43 = uadd_overflow_trap v41, v27, user1  ; v27 = 8
+;; @002a                               v44 = icmp ule v43, v25
+;; @002a                               trapz v44, user1
+;;                                     v57 = iconst.i64 1
+;; @002a                               v34 = iadd v33, v57  ; v57 = 1
+;; @002a                               v45 = iadd.i64 v13, v41
+;; @002a                               store notrap aligned v34, v45
 ;; @002a                               jump block3
 ;;
 ;;                                 block3:
-;;                                     v72 = load.i32 notrap v76
-;; @002a                               v44 = iadd.i64 v13, v40
-;; @002a                               store notrap aligned little v72, v44
+;;                                     v46 = load.i32 notrap v50
+;;                                     v53 = iconst.i64 24
+;; @002a                               v18 = iadd.i64 v15, v53  ; v53 = 24
+;; @002a                               store notrap aligned little v46, v18
 ;; @002d                               jump block1
 ;;
 ;;                                 block1:
diff --git a/tests/misc_testsuite/simd/interesting-float-splat.wast b/tests/misc_testsuite/simd/interesting-float-splat.wast
new file mode 100644
index 000000000..ab19f12d2
--- /dev/null
+++ b/tests/misc_testsuite/simd/interesting-float-splat.wast
@@ -0,0 +1,7 @@
+(module
+  (func (export "") (result v128)
+    v128.const i32x4 0x3f803f80 0x3f803f80 0x3f803f80 0x3f803f80
+  )
+)
+
+(assert_return (invoke "") (v128.const i32x4 0x3f803f80 0x3f803f80 0x3f803f80 0x3f803f80))