x86-64 optimization: Use 32-bit popcnt instruction if operand is known to fit
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
x86_64 target, with `-Os -mpopcnt` compiler flags.
Compiler Explorer link:
https://godbolt.org/z/v8PhhrzGs
```c
int func6(unsigned long long x) {
if (x > 0xFFFFFFFFULL) {
__builtin_unreachable();
}
return __builtin_popcountll(x);
}
int func6b(unsigned long long x) {
if (x > 0xFFFFFFFFULL) {
__builtin_unreachable();
}
return __builtin_popcountll(x & 0xFFFFFFFF);
}
```
Clang 22.1.0 misses that for this func6() case, a 32-bit popcnt instruction can be used.
[Related GCC bug report](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125221)
Note: in the Compiler Explorer link I've given, there are `func1` to `func5` examples that Clang optimizes correctly (using a 32-bit popcnt instruction rather than 64-bit). It's just the `func6` case that Clang missed.
```c
int func1(unsigned long long x) {
return __builtin_popcountll(x & 0x87878787);
}
int func2(unsigned long long x) {
return __builtin_popcountll(x >> 32);
}
int func3(unsigned char x) {
if (x >= 64) {
__builtin_unreachable();
}
return __builtin_popcountll(0x87878787ULL >> x);
}
int func4(unsigned long long x) {
return __builtin_popcountll(x % 4294967291U);
}
int func5(unsigned long long x) {
return __builtin_popcountll(x / 4294967311U);
}
```
Contributor guide
Assessment
This issue has not been assessed yet.