Closed
Description
I tried this code:
pub fn accumulate(arr: &[u8], weight: f32) {
let weight = (weight * 256. * 256. * 256.) as u32;
let weight = weight.min(256 * 256 * 256);
// If you uncomment this, all examples will get optimized out fine on all versions.
// let weight = weight.min(256 * 256 * 256 - 1);
for x in arr {
// This avoids overflow checks on 1.64.0 (but not on beta/nightly).
// let result = f(*x, weight);
// This inlined version has overflow checks.
assert!(weight <= 256 * 256 * 256);
let result = *x as u32 * weight;
// This also has overflow checks for some reason.
// let result = f2(*x as u32, weight);
}
}
#[inline(always)]
fn f(x: u8, weight: u32) -> u32 {
assert!(weight <= 256 * 256 * 256);
x as u32 * weight
}
#[inline(always)]
fn f2(x: u32, weight: u32) -> u32 {
assert!(weight <= 256 * 256 * 256);
x * weight
}
https://godbolt.org/z/9c8qc88qo
I expected to see this happen: all three versions of the loop body have no overflow checks and are optimized out.
Instead, this happened: let result = f(*x, weight);
has no overflow checks whereas the two other versions do have overflow checks on 1.64.0 and below, and on beta/nightly all versions have overflow checks. Also, uncommenting line #6, which makes weight
bound one smaller, makes all three versions have no overflow checks on both 1.64.0 and nightly, which is extra weird because the bounds are satisfied with either value.
Metadata
Metadata
Assignees
Labels
Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.Category: This is a bug.Call for participation: An issue has been fixed and does not reproduce, but no test has been added.Issue: Problems and improvements with respect to performance of generated code.Relevant to the compiler team, which will review and decide on the PR/issue.