https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71762
Richard Biener <rguenth at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |NEW Last reconfirmed| |2016-07-06 Ever confirmed|0 |1 --- Comment #4 from Richard Biener <rguenth at gcc dot gnu.org> --- (In reply to Andrew Pinski from comment #3) > So in this case, ifcombine can combine: > if (!__cond60) > { > if (__cond59) > { > > Into: > > (!__cond60) & __cond59 > > Yes the rhs will be unitialized but if __cond60 is true but that should not > cause wrong code. There is something else going wrong here than my patch. While this is true - ifcombine does <bb 8>: - if (__cond60_6 != 0) - goto <bb 11>; - else + _16 = ~__cond60_6; + _17 = __cond59_1 & _16; + if (_17 != 0) goto <bb 9>; later fwprop simplifies this condition to __cond59_1 > __cond60_6 which clearly doesn't work. It arrives here by simplifying __cond59_1 & (~cond60_6) into __cond59_1 > __cond60_6 via simplify_bitwise_binary_boolean. On the 5/6 branches we ifcombine the condition to _14 = len_5(D) <= 1; _13 = __cond59_1 & _14; if (_13 != 0) which is because ~__cond60_6 is optimized to len_5 <= 1 first. So we are lucky here that we see the actual comparison. Adjusted testcase that triggers the transform also with GCC5/6 but doesn't show "fail" (not with 4.9 either - I guess we're lucky with initialized regs here). For 4.9 and the original testcase IRA selects %r12b for the uninitialized value which isn't 1-bit and we expand the compare to a simple QImode compare. So this is really a corner case in that the transform to a compare is correct for uninitialized 1-bit values but wrong if we actually end up comparing larger values... so expansion misses bit-truncation of the comparison operands. struct S { void* get() { return 0; } ~S() { __builtin_printf("dtor\n"); } }; void foo(void* x) { __builtin_printf("foo\n"); } void __attribute__((noinline,noclone)) testFunc(bool __cond59, bool __cond60) { if (!__cond60) { if (__cond59) { __builtin_printf("fail\n"); } } } int len = 2; int main() { bool __cond59; bool __cond60; foo ((__cond60 = len > 1, __cond60) ? 0 : (__cond59 = len == 1, __cond59) ? S().get() : 0); testFunc (__cond59, __cond60); return 0; }