This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug middle-end/71762] [4.9/5/6/7 Regression] ifcombine exposes wrong codegen with uninitialized bools
- From: "rguenth at gcc dot gnu.org" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Wed, 06 Jul 2016 08:23:57 +0000
- Subject: [Bug middle-end/71762] [4.9/5/6/7 Regression] ifcombine exposes wrong codegen with uninitialized bools
- Auto-submitted: auto-generated
- References: <bug-71762-4@http.gcc.gnu.org/bugzilla/>
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;
}