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

--- Comment #6 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
And the same with some auto var renames, so that there is no confusion for what
is from which function:
unsigned short a, c, d;

short
foo (short g, short h)
{
  return h;
}

short
bar (short g, short h)
{
  return g;
}

__attribute__((noipa)) void
baz (int b)
{
  __builtin_abort ();
}

__attribute__((noinline)) int
qux (signed char g)
{
  unsigned short j;
  int b = 0, k;
  while (d < 8)
    {
      if ((b = a != g) ^ a)
        {
          j = b + a;
          k = j;
          return a ? 0 : k >> a;
        }
      b = foo (d && c, a);
    }
  baz (b);
  return 100;
}

__attribute__((noinline)) int
fred (signed char p)
{
  unsigned short o;
  int m = 0, n;
  while (d < 8)
    {
      if ((m = a != p) ^ a)
        {
          o = m + a;
          n = o;
          return a ? 0 : n >> a;
        }
      m = bar (a, d && c);
    }
  baz (m);
  return 100;
}

int
main ()
{
  if (qux (1) != 1 || fred (1) != 1)
    __builtin_abort ();
}

At runtime in both cases a is 0 and b/m are 1, so the right shift is 1.
Figuring out that it is >> 0 is correct, and that because it is in ?: last
operand
b + a or m + a is equal to just b or m and that it is [0, 1] is correct, but
somehow it only thinks about [0, 0] and not [0, 1].

Reply via email to