[RISCV] Generic two source shuffle can be further optimized
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
For the fallback case of two operand shuffles (VRGATHER + VRGATHER.MASK), we currently load two separate shuffle indexes for both of the initial shuffles, when we can compress those two loads into a single load.
Currently, this is blocked by our recursive lowering strategy. This pattern is easiest to detect on the first pass lowering of a two source vector shuffle (prior to it being split into two vector shuffles and a merge) and merge the gather indxes then. However, applying this optimization can block more profitable optimizations that could have been made on the two child gathers (see #187048).
@preames and I have discussed two alternatives:
1. Make this into a `MIR` optimization. There's not a clean path forward with recognizing the constants and determining the demanded elements. Can be made to work, but neither of us have the time, and there is a better long-term solution (see 2). The one advantage of this approach is that it could be generalized into a pass to recognize constant pool values that can be condensed, not just in this scenario.
2. Refactor the shuffle lowering to have an intermediate format. @preames has played around with this idea before. This intermediate format could be costed allowing us to both compare across different lowering as well as better cost shuffles in earlier passes (i.e SLP).
I don't have data for how frequent this lowering pattern occurs, though likely not often since if we are forced to shuffle like this it likely makes it unprofitable to vectorize.
Example:
```
.LCPI0_0:
.zero 2
.zero 2
.zero 2
.zero 2
.zero 2
.zero 2
.zero 2
.zero 2
.half 3 # 0x3
.half 7 # 0x7
.half 8 # 0x8
.half 15 # 0xf
.half 2 # 0x2
.half 6 # 0x6
.half 10 # 0xa
.half 14 # 0xe
.LCPI0_1:
.half 0 # 0x0
.half 0 # 0x0
.half 8 # 0x8
.half 12 # 0xc
.half 1 # 0x1
.half 5 # 0x5
.half 9 # 0x9
.half 13 # 0xd
.zero 2
.zero 2
.zero 2
.zero 2
.zero 2
.zero 2
.zero 2
.zero 2
.text
.globl shuffle_shuffle_duplicated_lane
.p2align 1
.type shuffle_shuffle_duplicated_lane,@function
.variant_cc shuffle_shuffle_duplicated_lane
shuffle_shuffle_duplicated_lane: # @shuffle_shuffle_duplicated_lane
.cfi_startproc
# %bb.0:
li a0, -256
vsetivli zero, 16, e16, mf4, ta, mu
vmv.s.x v0, a0
lui a0, %hi(.LCPI0_1)
addi a0, a0, %lo(.LCPI0_1)
vle16.v v11, (a0)
lui a0, %hi(.LCPI0_0)
addi a0, a0, %lo(.LCPI0_0)
vrgather.vv v10, v8, v11
vle16.v v8, (a0)
vrgather.vv v10, v9, v8, v0.t
vmv1r.v v8, v10
ret
```
can be optimized to:
```
.LCPI0_0:
.half 0 # 0x0
.half 0 # 0x0
.half 8 # 0x8
.half 12 # 0xc
.half 1 # 0x1
.half 5 # 0x5
.half 9 # 0x9
.half 13 # 0xd
.half 3 # 0x3
.half 7 # 0x7
.half 8 # 0x8
.half 15 # 0xf
.half 2 # 0x2
.half 6 # 0x6
.half 10 # 0xa
.half 14 # 0xe
.text
.globl shuffle_shuffle_duplicated_lane
.p2align 1
.type shuffle_shuffle_duplicated_lane,@function
.variant_cc shuffle_shuffle_duplicated_lane
shuffle_shuffle_duplicated_lane: # @shuffle_shuffle_duplicated_lane
.cfi_startproc
# %bb.0:
li a0, -256
vsetivli zero, 16, e16, mf4, ta, mu
vmv.s.x v0, a0
lui a0, %hi(.LCPI0_0)
addi a0, a0, %lo(.LCPI0_0)
vle16.v v11, (a0)
vrgather.vv v10, v8, v11
vrgather.vv v10, v9, v11, v0.t
vmv1r.v v8, v10
ret
```
Contributor guide
Assessment
This issue has not been assessed yet.