diff --git a/cranelift/codegen/src/isa/x64/inst.isle b/cranelift/codegen/src/isa/x64/inst.isle index 96d1dc8759c7..872e14d3342e 100644 --- a/cranelift/codegen/src/isa/x64/inst.isle +++ b/cranelift/codegen/src/isa/x64/inst.isle @@ -5058,7 +5058,7 @@ (decl bitcast_gpr_to_xmm (u8 Gpr) Xmm) (rule (bitcast_gpr_to_xmm 16 src) - (x64_pinsrw (xmm_uninit_value) src 0)) + (x64_pinsrw (xmm_zero $I16X8) src 0)) (rule (bitcast_gpr_to_xmm 32 src) (x64_movd_to_xmm src)) (rule (bitcast_gpr_to_xmm 64 src) diff --git a/cranelift/filetests/filetests/isa/x64/bitcast.clif b/cranelift/filetests/filetests/isa/x64/bitcast.clif index a9f8fe52999a..b90a3d0f375a 100644 --- a/cranelift/filetests/filetests/isa/x64/bitcast.clif +++ b/cranelift/filetests/filetests/isa/x64/bitcast.clif @@ -38,6 +38,7 @@ block0(v0: i16): ; movq %rsp, %rbp ; block0: ; uninit %xmm0 +; pxor %xmm0, %xmm0 ; pinsrw $0x0, %edi, %xmm0 ; movq %rbp, %rsp ; popq %rbp @@ -48,6 +49,7 @@ block0(v0: i16): ; pushq %rbp ; movq %rsp, %rbp ; block1: ; offset 0x4 +; pxor %xmm0, %xmm0 ; pinsrw $0, %edi, %xmm0 ; movq %rbp, %rsp ; popq %rbp @@ -405,6 +407,7 @@ block0(v0: i16): ; movq %rsp, %rbp ; block0: ; uninit %xmm0 +; pxor %xmm0, %xmm0 ; pinsrw $0x0, %edi, %xmm0 ; movq %rbp, %rsp ; popq %rbp @@ -415,6 +418,7 @@ block0(v0: i16): ; pushq %rbp ; movq %rsp, %rbp ; block1: ; offset 0x4 +; pxor %xmm0, %xmm0 ; pinsrw $0, %edi, %xmm0 ; movq %rbp, %rsp ; popq %rbp diff --git a/cranelift/filetests/filetests/isa/x64/f16const.clif b/cranelift/filetests/filetests/isa/x64/f16const.clif index 1a762b63d76a..ce6d68a9fc28 100644 --- a/cranelift/filetests/filetests/isa/x64/f16const.clif +++ b/cranelift/filetests/filetests/isa/x64/f16const.clif @@ -39,6 +39,7 @@ block0(): ; block0: ; movl $15360, %esi ; uninit %xmm0 +; pxor %xmm0, %xmm0 ; pinsrw $0x0, %esi, %xmm0 ; movq %rbp, %rsp ; popq %rbp @@ -50,6 +51,7 @@ block0(): ; movq %rsp, %rbp ; block1: ; offset 0x4 ; movl $0x3c00, %esi +; pxor %xmm0, %xmm0 ; pinsrw $0, %esi, %xmm0 ; movq %rbp, %rsp ; popq %rbp diff --git a/cranelift/filetests/filetests/isa/x64/issue-10906.clif b/cranelift/filetests/filetests/isa/x64/issue-10906.clif new file mode 100644 index 000000000000..c5fad86b217f --- /dev/null +++ b/cranelift/filetests/filetests/isa/x64/issue-10906.clif @@ -0,0 +1,72 @@ +;; This has an associated runtest; this test explains that one by disassembling +;; the test case here. + +test compile precise-output +set opt_level=none +set preserve_frame_pointers=true +set enable_multi_ret_implicit_sret=true +target x86_64 + +function %munge_xmm0() -> i16x8 fast { +block0: + v0 = vconst.i16x8 [0xffff 0xffff 0xffff 0xffff 0xffff 0xffff 0xffff 0xffff] + return v0 +} + +; VCode: +; pushq %rbp +; movq %rsp, %rbp +; block0: +; uninit %xmm0 +; pcmpeqd %xmm0, %xmm0 +; movq %rbp, %rsp +; popq %rbp +; ret +; +; Disassembled: +; block0: ; offset 0x0 +; pushq %rbp +; movq %rsp, %rbp +; block1: ; offset 0x4 +; pcmpeqd %xmm0, %xmm0 +; movq %rbp, %rsp +; popq %rbp +; retq + +function %scalar_to_vector() -> i16x8 fast { + fn0 = %munge_xmm0() -> i16x8 fast +block0: + v0 = call fn0() + v1 = iconst.i16 42 + v2 = scalar_to_vector.i16x8 v1 + return v2 +} + +; VCode: +; pushq %rbp +; movq %rsp, %rbp +; block0: +; load_ext_name %munge_xmm0+0, %r8 +; call *%r8 +; movl $42, %r8d +; uninit %xmm0 +; pxor %xmm0, %xmm0 +; pinsrw $0x0, %r8d, %xmm0 +; movq %rbp, %rsp +; popq %rbp +; ret +; +; Disassembled: +; block0: ; offset 0x0 +; pushq %rbp +; movq %rsp, %rbp +; block1: ; offset 0x4 +; movabsq $0, %r8 ; reloc_external Abs8 %munge_xmm0 0 +; callq *%r8 +; movl $0x2a, %r8d +; pxor %xmm0, %xmm0 +; pinsrw $0, %r8d, %xmm0 +; movq %rbp, %rsp +; popq %rbp +; retq + diff --git a/cranelift/filetests/filetests/runtests/issue-10906.clif b/cranelift/filetests/filetests/runtests/issue-10906.clif new file mode 100644 index 000000000000..e23714057934 --- /dev/null +++ b/cranelift/filetests/filetests/runtests/issue-10906.clif @@ -0,0 +1,31 @@ +;; When CLIF's `scalar_to_vector` operates on an `i16x8` vector, we need to be +;; sure to zero out the upper bits before inserting the `i16` into the lowest +;; lane. This test uses some ABI knowledge (both functions return their result +;; in `xmm0`) to fill in all of the bits (`%munge_xmm0`) and see if they "show +;; through" in the actual test, `%scalar_to_vector`. See +;; https://github.com/bytecodealliance/wasmtime/issues/10906. + +test interpret +test run +set opt_level=none +set preserve_frame_pointers=true +set enable_multi_ret_implicit_sret=true +target x86_64 + +function %munge_xmm0() -> i16x8 fast { +block0: + v0 = vconst.i16x8 [0xffff 0xffff 0xffff 0xffff 0xffff 0xffff 0xffff 0xffff] + return v0 +} + +function %scalar_to_vector() -> i16x8 fast { + fn0 = %munge_xmm0() -> i16x8 fast +block0: + v0 = call fn0() + v1 = iconst.i16 42 + v2 = scalar_to_vector.i16x8 v1 + return v2 +} + +; run: %scalar_to_vector() == [42 0 0 0 0 0 0 0] +