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

}

Godbolt link

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:

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.