int f(int a) { return ((2 << a) & 1) == 0; } This can be optimized to `return 1;`. This transformation is done by GCC, but by LLVM. Godbolt comparison here: https://godbolt.org/z/dTfsbx alive2 check here: https://alive2.llvm.org/ce/z/U3DMgJ
PS: This can also be optimized in cases where the low bits aren't necessarily unset, e.g. int f(int a) { return ((2 << a) & 16) != 0; } Can be optimized to `return a == b;` (done by GCC, not by LLVM).
PPS: I messed up and typed `a == b` where I meant `a == 3` in the previous message.
This is presumably caused by the early exit at https://github.com/llvm/llvm-project/blob/75347ba1fae25819a086fc29ad52d813419887a8/llvm/lib/Analysis/ValueTracking.cpp#L1010.
This would catch the example in the description (and similar): https://reviews.llvm.org/D95959
Should be fixed after: https://reviews.llvm.org/rG0be0a1237cb9