https://gcc.gnu.org/bugzilla/show_bug.cgi?id=122018
--- Comment #10 from uis <uis9936 at gmail dot com> --- Ah, register pressure. Well, in one branch result of bts can be discarded, while in other it's one load less and one store earlier. Assuming visibility does not escape function. Oops again. I'll reorder it slightly to show there is no way for a with unset bit to be seen: #include <stdbool.h> void g(); void h(); int f(int a, int b) { // if bit b is not set in a if(!(a & (1 << b))) { // then set bit b there // or rather store result of bts done during branching a = a | (1 << b); h(); } else // setting already set bit does nothing // call g() if bit was set g(); return a; } Without call to function h() it will have exactly same behavior as original testcase, but with potentially(maybe, I'm not a compiler developer) harder to recognize pattern.