x64: fix register allocation panic due to load-coalesced value (#3954)

Fuzz testing identified a lowering case for CLIF's `icmp` in which the
double use of a loaded operand resulted in a register allocation error.
This change manually adds `put_in_xmm` to avoid load-coalescing these
values and includes a CLIF filetest to trigger this issue. Closes #3951.

I opened #3953 to discuss a way in which this kind of mistake (i.e.,
forgetting to add `put_in_*` in certain situations) could be avoided.
This commit is contained in:
Andrew Brown
2022-03-21 18:46:27 -07:00
committed by GitHub
parent 3bfbb3226e
commit 4d5bd5f90e
4 changed files with 171 additions and 142 deletions

View File

@@ -1470,13 +1470,21 @@
(rule (lower (icmp (IntCC.SignedLessThan) a @ (value_type (vec128 ty)) b))
(x64_pcmpgt ty b a))
(rule (lower (icmp (IntCC.UnsignedGreaterThan) a @ (value_type (vec128 ty)) b))
(let ((max Xmm (x64_pmaxu ty a b))
(eq Xmm (x64_pcmpeq ty max b))
;; N.B.: we must manually prevent load coalescing of these operands; the
;; register allocator gets confused otherwise. TODO:
;; https://github.com/bytecodealliance/wasmtime/issues/3953.
(let ((xmm_a Xmm (put_in_xmm a))
(xmm_b Xmm (put_in_xmm b))
(max Xmm (x64_pmaxu ty xmm_a xmm_b))
(eq Xmm (x64_pcmpeq ty max xmm_b))
(all_ones Xmm (vector_all_ones ty)))
(x64_pxor eq all_ones)))
(rule (lower (icmp (IntCC.UnsignedLessThan) a @ (value_type (vec128 ty)) b))
(let ((min Xmm (x64_pminu ty a b))
(eq Xmm (x64_pcmpeq ty min b))
;; N.B.: see note above.
(let ((xmm_a Xmm (put_in_xmm a))
(xmm_b Xmm (put_in_xmm b))
(min Xmm (x64_pminu ty xmm_a xmm_b))
(eq Xmm (x64_pcmpeq ty min xmm_b))
(all_ones Xmm (vector_all_ones ty)))
(x64_pxor eq all_ones)))
;; To lower signed and unsigned *-or-equals comparisons, we find the minimum