x64: Add a smattering of lowerings for shuffle specializations (#5930)

* x64: Add lowerings for `punpck{h,l}wd`

Add some special cases for `shuffle` for more specialized x86
instructions.

* x64: Add `shuffle` lowerings for `pshufd`

This commit adds special-cased lowerings for the x64 `shuffle`
instruction when the `pshufd` instruction alone is necessary. This is
possible when the shuffle immediate permutes 32-bit values within one of
the vector inputs of the `shuffle` instruction, but not both.

* x64: Add shuffle lowerings for `punpck{h,l}{q,}dq`

This adds specific permutations for some x86 instructions which
specifically interleave high/low bytes for 32 and 64-bit values. This
corresponds to the preexisting specific lowerings for interleaving 8 and
16-bit values.

* x64: Add `shuffle` lowerings for `shufps`

This commit adds targeted lowerings for the `shuffle` instruction that
match the pattern that `shufps` supports. The `shufps` instruction
selects two elements from the first vector and two elements from the
second vector which means while it's not generally applicable it should
still be more useful than the catch-all lowering of `shuffle`.

* x64: Add shuffle support for `pshuf{l,h}w`

This commit adds special lowering cases for these instructions which
permute 16-bit values within a 128-bit value either within the upper or
lower half of the 128-bit value.

* x64: Specialize `shuffle` with an all-zeros immediate

Instead of loading the all-zeros immediate from a rip-relative address
at the end of the function instead generate a zero with a `pxor`
instruction and then use `pshufb` to do the broadcast.

* Review comments
This commit is contained in:
Alex Crichton
2023-03-09 16:58:19 -06:00
committed by GitHub
parent 8a2bf29444
commit 1c3a1bda6c
10 changed files with 1332 additions and 10 deletions

View File

@@ -863,6 +863,12 @@
Xorpd
Phaddw
Phaddd
Punpckhdq
Punpckldq
Punpckhqdq
Punpcklqdq
Pshuflw
Pshufhw
))
(type CmpOpcode extern
@@ -1347,6 +1353,12 @@
Vcvttps2dq
Vphaddw
Vphaddd
Vpunpckhdq
Vpunpckldq
Vpunpckhqdq
Vpunpcklqdq
Vpshuflw
Vpshufhw
))
(type Avx512Opcode extern
@@ -2729,6 +2741,38 @@
(if-let $true (has_avx))
(xmm_rmir_vex (AvxOpcode.Vpunpcklwd) src1 src2))
;; Helper for creating `punpckldq` instructions.
(decl x64_punpckldq (Xmm XmmMem) Xmm)
(rule 0 (x64_punpckldq src1 src2)
(xmm_rm_r (SseOpcode.Punpckldq) src1 src2))
(rule 1 (x64_punpckldq src1 src2)
(if-let $true (has_avx))
(xmm_rmir_vex (AvxOpcode.Vpunpckldq) src1 src2))
;; Helper for creating `punpckhdq` instructions.
(decl x64_punpckhdq (Xmm XmmMem) Xmm)
(rule 0 (x64_punpckhdq src1 src2)
(xmm_rm_r (SseOpcode.Punpckhdq) src1 src2))
(rule 1 (x64_punpckhdq src1 src2)
(if-let $true (has_avx))
(xmm_rmir_vex (AvxOpcode.Vpunpckhdq) src1 src2))
;; Helper for creating `punpcklqdq` instructions.
(decl x64_punpcklqdq (Xmm XmmMem) Xmm)
(rule 0 (x64_punpcklqdq src1 src2)
(xmm_rm_r (SseOpcode.Punpcklqdq) src1 src2))
(rule 1 (x64_punpcklqdq src1 src2)
(if-let $true (has_avx))
(xmm_rmir_vex (AvxOpcode.Vpunpcklqdq) src1 src2))
;; Helper for creating `punpckhqdq` instructions.
(decl x64_punpckhqdq (Xmm XmmMem) Xmm)
(rule 0 (x64_punpckhqdq src1 src2)
(xmm_rm_r (SseOpcode.Punpckhqdq) src1 src2))
(rule 1 (x64_punpckhqdq src1 src2)
(if-let $true (has_avx))
(xmm_rmir_vex (AvxOpcode.Vpunpckhqdq) src1 src2))
;; Helper for creating `unpcklps` instructions.
(decl x64_unpcklps (Xmm XmmMem) Xmm)
(rule 0 (x64_unpcklps src1 src2)
@@ -3284,6 +3328,22 @@
(if-let $true (has_avx))
(xmm_rmir_vex (AvxOpcode.Vpshufb) src1 src2))
;; Helper for creating `pshuflw` instructions.
(decl x64_pshuflw (XmmMem u8) Xmm)
(rule (x64_pshuflw src imm)
(xmm_unary_rm_r_imm (SseOpcode.Pshuflw) src imm))
(rule 1 (x64_pshuflw src imm)
(if-let $true (has_avx))
(xmm_unary_rm_r_imm_vex (AvxOpcode.Vpshuflw) src imm))
;; Helper for creating `pshufhw` instructions.
(decl x64_pshufhw (XmmMem u8) Xmm)
(rule (x64_pshufhw src imm)
(xmm_unary_rm_r_imm (SseOpcode.Pshufhw) src imm))
(rule 1 (x64_pshufhw src imm)
(if-let $true (has_avx))
(xmm_unary_rm_r_imm_vex (AvxOpcode.Vpshufhw) src imm))
;; Helper for creating `shufps` instructions.
(decl x64_shufps (Xmm XmmMem u8) Xmm)
(rule 0 (x64_shufps src1 src2 byte)