[Bug middle-end/85563] [8/9 regression] -Wmaybe-uninitialized false alarm regression with __builtin_unreachable and GCC 8

jakub at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Fri Feb 1 14:09:00 GMT 2019


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85563

--- Comment #7 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Before doing manual reduction, I've tried:
struct S { void *a, *b; int c; };
static inline int foo (void *p)
{
  return ((unsigned) ((__INTPTR_TYPE__) p) & 7) == 3;
}

static inline void *bar (void *p)
{
  struct S *s = (struct S *) ((__INTPTR_TYPE__) p & ~(__INTPTR_TYPE__) 7);
  return s->a;
}

static inline void *baz (void *p)
{
  struct S *s = (struct S *) ((__INTPTR_TYPE__) p & ~(__INTPTR_TYPE__) 7);
  return s->b;
}

static inline int quux (void *p)
{
  struct S *s = (struct S *) ((__INTPTR_TYPE__) p & ~(__INTPTR_TYPE__) 7);
  return s->c;
}

void *v;

void *
qux (void)
{
  foo (v) ? 0 : __builtin_unreachable ();
  void *q;
  for (void *p = v; foo (p) && (q = bar (p)); p = baz (p))
    if (quux (q))
      break;
  return q;
}

but that one doesn't warn for some reason, anyway, the visible change is that
the __builtin_unreachable () is removed during vrp1 only on the #c6 testcase,
and there is really no spot to actually record what the assertion asserted.
  Vframe_list.0_1 = Vframe_list;
  a.1_11 = (long int) Vframe_list.0_1;
  # RANGE [3, 4294967291]
  _9 = (unsigned int) a.1_11;
  # RANGE [3, 3] NONZERO 3
  _8 = _9 & 7;
  if (_8 != 3)
    goto <bb 3>; [0.00%]
  else
    goto <bb 7>; [100.00%]

  <bb 7> [local count: 118111600]:
  goto <bb 4>; [100.00%]

  <bb 3> [count: 0]:
  __builtin_unreachable ();
before vrp1, while the [3, 3] range for _8 is useful, that SSA_NAME is
immediately removed as nothing uses it.  And the [3, 4294967291] range is both
not really useful and _9 isn't used by anything either.  In the range info,
while we record a non-zero mask, we don't have a zero mask, so there is no way
to express that (whatever & 7) == 3 (let alone == 6 or similar).  Plus we don't
record any ranges for pointers, just NULL vs. non-NULL.  So, in the end the
__builtin_unreachable () here is totally useless.
The only hope is that if it is kept (e.g. with the rationale that the only
SSA_NAMEs where something could be recorded are single use and after the
__builtin_unreachable () removal they will have zero uses and removed), then we
decide to peel off the first iteration or tests from it and thus merge that
with the __builtin_unreachable ().

Or just rewrite whatever you are doing to something that doesn't suffer from
this.  Say:
  (tail) = Vframe_list;
  while ((frame1 = XCAR (tail), 1))
    {
      body...;
      tail = XCDR (tail);
      if (!CONSP (tail))
        break;
    }


More information about the Gcc-bugs mailing list