Issue |
96395
|
Summary |
LLVM should recognize more patterns that map to pmovmsk or similar instructions
|
Labels |
new issue
|
Assignees |
|
Reporter |
jhorstmann
|
This comes up regularly in functions that process or detect ascii inputs. My current example is in rust, int a `const` function, which prevents me from using explicit simd intrinsics, but the code generated by clang is nearly the same.
```rust
pub unsafe fn ascii_prefix(input: &[u8]) -> usize {
let mut mask = 0_u16;
for i in 0..16 {
mask |= ((*input.get_unchecked(i) < 128) as u16) << i;
}
mask.trailing_ones() as usize
}
```
Ideally this would map to 4 instructions: `compare`, `movmsk`, `not` and `tzcnt`. But currently it gets compiled to about 50 instructions with a mix of scalar and vector instructions: https://godbolt.org/z/jaKb5TMrn
A sightly simpler example that only tries to detect fully ascii chunks leads to similar complex output.
```rust
pub unsafe fn is_ascii_mask(input: &[u8]) -> bool {
let mut is_ascii = [false; 16];
for i in 0..16 {
is_ascii[i] = *input.get_unchecked(i) <= 127;
}
let mut mask = 0_u16;
for i in 0..16 {
mask |= (is_ascii[i] as u16) << i;
}
mask == 0xFFFF
}
```
However, for detection only I found one pattern that generates the wanted instruction sequence, so LLVM has some logic to detect this pattern:
```rust
pub unsafe fn is_ascii_sum(input: &[u8]) -> bool {
let mut is_ascii = [false; 16];
for i in 0..16 {
is_ascii[i] = *input.get_unchecked(i) <= 127;
}
let mut count = 0_u8;
for i in 0..16 {
count += is_ascii[i] as u8;
}
count == 16
}
```
```asm
example::is_ascii_sum::h00bc3be7e76426eb:
vmovdqu xmm0, xmmword ptr [rdi]
vpmovmskb eax, xmm0
test eax, eax
sete al
ret
```
Unfortunately this pattern using `sum` cannot be used for the initial example which needs a mask as output.
#45398 seems related, but focuses a bit more on the bit counting aspect, where `movmsk` might only be beneficial if the `popcnt` instruction is also available.
_______________________________________________
llvm-bugs mailing list
llvm-bugs@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs