llvm / llvm/llvm-project

Inline `ilogb` when `x` is `normal`.

Open
#216,405 4 comments 0 reactions 1 assignee Claimed by @tadeuszjt View on GitHub
floating-point llvm:instcombine missed-optimization
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

If `x` is normal, (or if `x` is subnormal with the MSB of the mantissa set), then `ilogb` can be implemented by clearing the sign bit, right shifting the exponent, and subtracting a constant.

Converting a call to `ilogb` to a bitwise-and, right-shift, subtract may be profitable for some platforms without an FPU.

This transformation might not be profitable if the above operations take up more space than a call to `ilogb`, or if the above operations are slower than an assembly implementation of `ilogb`.

This transformation is invalid if the result of `ilogb(normal)` is outside the range of `int` (which should generally be false where `int` is 32 bits).

Currently, Clang does not perform this optimization, and Alive2 is unable to prove it. https://alive2.llvm.org/ce/z/v4eQZt

https://godbolt.org/z/dGGa6ebqP
```c++
int src_f32(float x) {
if (!__builtin_isnormal(x)) {
__builtin_unreachable();
}
return __builtin_ilogbf(x);
}

int tgt_f32(float x) {
if (!__builtin_isnormal(x)) {
__builtin_unreachable();
}
uint32_t bin;
__builtin_memcpy(&bin, &x, sizeof(x));
bin &= ~(UINT32_C(1) << 31);
bin >>= 23;
int ret = (int)bin;
return ret - 127;
}

int src_f64(double x) {
if (!__builtin_isnormal(x)) {
__builtin_unreachable();
}
return __builtin_ilogb(x);
}

int tgt_f64(double x) {
if (!__builtin_isnormal(x)) {
__builtin_unreachable();
}
uint64_t bin;
__builtin_memcpy(&bin, &x, sizeof(x));
bin &= ~(UINT64_C(1) << 63);
bin >>= 52;
int ret = (int)bin;
return ret - 1023;
}
```

***

Next steps:
- This can be generalized to `frexp(x, &exponent)` if only the exponent is needed.
- A similar transformation for `ilogb` exists if `x` is always subnormal (or has the smallest normal exponent) which turns `ilogb` into `__builtin_clz(x) - constant`.

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.