llvm / llvm/llvm-project

[RISC-V] Knowledge of integer range leads to suboptimal codegen for instructions that could use sign-extended imm12

Open
#174,935 4 comments 0 reactions 0 assignees View on GitHub
backend:RISC-V missed-optimization
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

```c
#include

uint32_t foo(uint32_t arg) {
// __builtin_assume(arg <= 0x1FFFF);
return arg & 0xFFFFFBFF;
}
```

Compiled with `-O3`, clang correctly emits this as:

```asm
foo:
andi a0, a0, -1025 ; 0xBFF
ret
```

... taking advantage of the sign-extension of `0xBFF` into `0xFFFFFBFF`.

But when the `__builtin_assume` is uncommented, clang now knows that `arg` only has the lower 17 bits set. It then uses this information to optimize the `&` RHS into the 17-bit mask `0x1FBFF`. The downside of this is that constructing the value `0x1FBFF` in RISC-V then requires a `lui; addi` sequence that must then be `and`ed with the arg.

```asm
foo:
lui a1, 32 ; 0x20000
addi a1, a1, -1025 ; 0x20000 - 0x401 = 0x1FBFF
and a0, a0, a1
ret
```

This ends up being worse than if clang had not done the integer range optimization.

(In my original Rust code, the integer range knowledge comes implicitly from the calculations that produce `arg`, so I cannot simply make LLVM forget that knowledge.)

---

clang version 22.0.0git (https://github.com/llvm/llvm-project.git dc43062638852201464b7b3e8a7e716c4f23e47e)

("RISC-V rv64gc clang (trunk)" in godbolt.)

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.