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

Reply via email to