| Issue |
115767
|
| Summary |
Failure to optimize `udiv`/`urem` when non-constant divisor is known power of two
|
| Labels |
missed-optimization
|
| Assignees |
|
| Reporter |
Kmeakin
|
Strength reduction can be performed on `udiv`/`urem` if the divisor is known to be a power of two, due to dominating condition or assume:
Compiler explorer: https://godbolt.org/z/4ncnjsPTM
Alive proof: https://alive2.llvm.org/ce/z/3FJYeg
```rust
#![feature(core_intrinsics)]
use std::hint::assert_unchecked as assume;
use std::intrinsics::unchecked_div;
use std::intrinsics::unchecked_rem;
#[no_mangle]
pub fn src_udiv_if(x: u32, y: u32) -> u32 {
if y.is_power_of_two() {
unsafe { unchecked_div(x, y) }
} else {
0
}
}
#[no_mangle]
pub fn tgt_udiv_if(x: u32, y: u32) -> u32 {
if y.is_power_of_two() {
x >> y.trailing_zeros()
} else {
0
}
}
#[no_mangle]
pub fn src_udiv_assume(x: u32, y: u32) -> u32 {
unsafe {
assume(y.is_power_of_two());
unchecked_div(x, y)
}
}
#[no_mangle]
pub fn tgt_udiv_assume(x: u32, y: u32) -> u32 {
unsafe {
assume(y.is_power_of_two());
x >> y.trailing_zeros()
}
}
#[no_mangle]
pub fn src_urem_if(x: u32, y: u32) -> u32 {
if y.is_power_of_two() {
unsafe { unchecked_rem(x, y) }
} else {
0
}
}
#[no_mangle]
pub fn tgt_urem_if(x: u32, y: u32) -> u32 {
if y.is_power_of_two() {
x & (y - 1)
} else {
0
}
}
#[no_mangle]
pub fn src_urem_assume(x: u32, y: u32) -> u32 {
unsafe {
assume(y.is_power_of_two());
unchecked_rem(x, y)
}
}
#[no_mangle]
pub fn tgt_urem_assume(x: u32, y: u32) -> u32 {
unsafe {
assume(y.is_power_of_two());
x & (y - 1)
}
}
```
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs