bool foo(int a) {
int z;
if (a > 5) { z=1; } else { z=2; }
int y;
if (a > 10) {
// here z=1, so y = 2
y=z + 1;
} else {
// here z=1 or 2, so y = 3 or 4
y=z + 2;
}
// here y is either 2, 3 or 4
if (y == 5) {
// it is unreachable
return true;
} else {
return false;
}
}

My guess is that GCC’s value range propagation catches that and LLVM currently misses a bit on that side.

There are some patches to improve LLVM’s constant propagation to also support constant ranges (https://reviews.llvm.org/D60582 and linked patches). With all those patches, LLVM should simplify the example. There’s been some progress on the patches recently and I am hoping to submit them over the next few months.

Locally I get the Attributor to do it with -O3 -mllvm -attributor-disable=false -fexperimental-new-pass-manager but not on godbold: Compiler Explorer
EDIT 3: “trunk” on godbold with the new PM works now (link above). Soon it will work with the old PM (see below).
EDIT 2: With https://reviews.llvm.org/rG7e7e6594b3450dbdaffbbeb39e832f6f39ce45a9 the old PM version of the Attributor should be able to simplify this. (In the old PM version LVI and ScalarEvolution are not used but they are not needed her.)

While I thought it didn’t work I found some easy improvements for AAValueConstantRange that I’ll upstream soon. It will still only work in the new pass manager but it will be more robust.