| Issue |
180097
|
| Summary |
`gepi i8 %ptr, i64 (srem x, y)` should optimize to `gepi i8 %ptr, (urem x, y)`
|
| Labels |
new issue
|
| Assignees |
|
| Reporter |
nagisa
|
I have the following case derived from real Rust code that operated on isizes rather than usizes when computing array indices and produced suboptimal code. Here's the minimized sample llvm-ir:
```llvm
define ptr @src(ptr dereferenceable(4) %foo, i64 noundef %x) {
%index = srem i64 %x, 4
%_6 = getelementptr inbounds nuw i8, ptr %foo, i64 %index
ret ptr %_6
}
```
Today this will produce
```asm
lea rax, [rsi + 3]
test rsi, rsi
cmovns rax, rsi
and rax, -4
sub rsi, rax
lea rax, [rsi + rdi]
ret
```
even though this should be possible to be a plain `and` without branching which is achieved if the `srem` is "optimized" to `urem`:
```asm
and esi, 3
lea rax, [rsi + rdi]
ret
```
---
Alive claims that replacing srem with urem is valid: https://alive2.llvm.org/ce/z/ffpUQ6. This also seems reasonable to me, for the purposes of this function `%foo` is its own object and `%index` cannot be negative, which then means means that `srem` cannot produce a negative value, which means that `%x` cannot be negative. For positive %x within bounds of `0` to `x` in `dereferenceable(x)` and rhs both `srem` and `urem` compute the same thing.
That said, for non-power-of-two RHS operands (e.g. 6 instead of 4) this transformation does not apply – there are plenty of examples of negative `%x` that compute to a `0` remainder (valid index for GEPi), but would compute to a different offset with `urem`. e.g. `-7680 % 6 = 0` but `-7680i64 as u64 % 6 = 4`.
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs