llvm / llvm/llvm-project

[X86] Consider not emitting `pext`/`pdep` for constant masks with `slow-pdep`

Open
#223,238 5 comments 0 reactions 1 assignee Claimed by @RKSimon View on GitHub
backend:X86 missed-optimization optimization:AMDCPU performance
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

```llvm
define i32 @test(i32 %a) {
%r = call i32 @llvm.pdep.i32(i32 %a, i32 61680) ; 0xf0f0
ret i32 %r
}
```
With `-mattr=+bmi2,+slow-pdep` (https://godbolt.org/z/fv9a8cbrf):
```asm
test: # @test
mov eax, 61680
pdep eax, edi, eax
ret
```

This output seems extremely suspicious because `pext` and `pdep` on Zen 1/2 are known to be extremely slow, which is what the `slow-pdep` flag is for. Removing the `bmi2` flag yields:
```asm
test: # @test
mov ecx, edi
shl ecx, 8
and ecx, 61440
shl edi, 4
movzx eax, dil
or eax, ecx
ret
```
This seems "obviously" better and boils down to
```cpp
((a >> 8) & 0xf0) | ((a >> 4) & 0xf)
```
I haven't done any benchmarking yet, but the latter code may be an order of magnitude faster. It's still somewhat reasonable to use `pdep` directly in the case of runtime masks because the difference would shrink and because it has vastly lower code size, but for constant masks, it's hard to justify using `pext` and `pdep` on Zen 2.

CC @RKSimon

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.