This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug middle-end/71762] [4.9/5/6/7 Regression] ifcombine exposes wrong codegen with uninitialized bools


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;
}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]