[InstCombine] Missed optimization for constant-LHS fsub of integer-to-float cast
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
### Description
InstCombine folds floating-point binary operations whose operands come from integer-to-floating-point casts, including the form `(fp_binop (s|u)itofp(X), C)`. It currently misses the constant-left-hand-side subtraction form:
```llvm
fsub C, (s|u)itofp(X)
```
When the conversions are exact and the corresponding integer subtraction cannot overflow, this can be folded to:
```llvm
(s|u)itofp(C_int - X)
```
### Real-world example
This pattern occurs in FFmpeg's AMR-WB decoder:
https://github.com/FFmpeg/FFmpeg/blob/a7e72069f15efbef1e25b25d35c4e0511b43262e/libavcodec/amrwbdec.c#L915-L917
```c
for (i = 0; i < AMRWB_SFR_SIZE_16k; i++)
hb_exc[i] = 32768.0 - (uint16_t) av_lfg_get(&ctx->prng);
```
The relevant optimized IR contains:
```llvm
%x = and i32 %x_in, 65535
%xf = uitofp i32 %x to float
%r = fsub nsz float 32768.0, %xf
```
### Reproducer
Run with `opt -passes=instcombine -S`:
```llvm
define float @test(i32 %x_in) {
%x = and i32 %x_in, 65535
%xf = uitofp i32 %x to float
%r = fsub nsz float 32768.0, %xf
ret float %r
}
```
### Current result
```llvm
%x = and i32 %x_in, 65535
%xf = uitofp nneg i32 %x to float
%r = fsub nsz float 32768.0, %xf
```
### Expected result
```llvm
%x = and i32 %x_in, 65535
%sub = sub nsw i32 32768, %x
%r = sitofp i32 %sub to float
```
The fold must be rejected when the floating-point constant is not exactly representable as the required integer or when the integer subtraction may overflow.
Contributor guide
Assessment
This issue has not been assessed yet.