Range of index variables forgotten in an else if (original) (raw)
LLVM issue: llvm/llvm-project#151078
pub fn choose(v: &[i32], a: usize, b: usize, c: usize, cond1: i32, cond2: i32) -> usize { if a >= v.len() || b >= v.len() || c >= v.len() { return 0; }
let va = v[a];
let vb = v[b]; // v[a]
let res = if va < cond1 {
a
} else if vb < cond2 {
b
} else {
c
};
assert!(res < v.len());
res}
I expected the assert to be optimized out, because the only possible values are a/b/c which have been checked at the start of the function. However, in this case the bounds check seems to be lost, and the assert stays.
The optimization failure happens when both conditions are met:
- two different slice indices must be used (e.g.
v[a]andv[b]). There's no problem when both conditions use the samev[a]. - there must be an
else if. There's no problem if there's onlyif/elseeven if the conditions uses two different valuesif va < cond1 || vb < cond2
Does not optimize:
let res = if va < cond1 {
a
} else if vb < cond2 {
a
} else {
b
};Does optimize:
let res = if va < cond1 || vb < cond2 {
a
} else {
b
};In C va < cond1 || vb < cond2 doens't optimize, but va < cond1 | vb < cond2 does, so it may be related to extra branches.