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

--- Comment #3 from Vincent Lefèvre <vincent-gcc at vinc17 dot net> ---
(In reply to Richard Biener from comment #2)
> it's loop invariant motion that hoists the v + v compute out of the loop
> and thus outside of its controlling condition.  You can see it's careful
> to not introduce undefined overflow that is possibly conditionally
> executed only but it fails to consider the case of 'v' being conditionally
> uninitialized.
> 
> It's very difficult to do the right thing here - it might be tempting to
> hoist the compute as
> 
>   if (c)
>     tem = v+v;
>   while (1)
>     if (c)
>       f(tem);

Couldn't the -Wmaybe-uninitialized warning be disabled on hoisted code, so that
the controlling condition wouldn't be needed?

To make sure not to disable potential warnings, the information that v was used
for tem should be kept together with tem in the loop. Something like
((void)v,tem), though GCC doesn't currently warn on that if v is uninitialized
(but that's another issue that should be solved).

However...

> Maybe the simplest thing would be to never hoist v + v, or only
> hoist it when the controlling branch is not loop invariant.
> 
> The original testcase is probably more "sensible", does it still have
> a loop invariant controlling condition and a loop invariant computation
> under that control?

In my tmd/binary32/hrcases.c file, there doesn't seem to be a loop invariant,
so I'm wondering what is the real cause. The code looks like the following:

static inline double cldiff (clock_t t1, clock_t t0)
{
  return (double) (t1 - t0) / CLOCKS_PER_SEC;
}

and in a function hrsearch() where its mprog argument (named c above) is an
integer that enables progress output when it is nonzero:

  if (mprog)
    {
      mctr = 0;
      nctr = 0;
      t0 = ti = clock ();
    }

  do
    {
[...]
      if (mprog && ++mctr == mprog)
        {
          mctr = 0;
          tj = clock ();
          mpfr_fprintf (stderr, "[exponent %ld: %8.2fs %8.2fs  %5lu / %lu]\n",
                        e, cldiff (tj, ti), cldiff (tj, t0), ++nctr, nprog);
          ti = tj;
        }
[...]
    }
  while (mpfr_get_exp (x) < e + 2);

The warning I get is

In function ‘cldiff’,
    inlined from ‘hrsearch’ at hrcases.c:298:11,
    inlined from ‘main’ at hrcases.c:520:9:
hrcases.c:46:23: warning: ‘t0’ may be used uninitialized
[-Wmaybe-uninitialized]
   46 |   return (double) (t1 - t0) / CLOCKS_PER_SEC;
      |                   ~~~~^~~~~
hrcases.c: In function ‘main’:
hrcases.c:128:11: note: ‘t0’ was declared here
  128 |   clock_t t0, ti, tj;
      |           ^~

So the operation on t0 is tj - t0, and as tj is set just before, I don't see
how it can be used in a loop invariant.

This can be simplified as follows:

int f (int);
void g (int mprog)
{
  int t0, ti, tj;

  if (mprog)
    t0 = ti = f(0);

  do
    if (mprog)
      {
        tj = f(0);
        f(tj - ti);
        f(tj - t0);
        ti = tj;
      }
  while (f(0));
}

and I get

tst.c: In function ‘g’:
tst.c:13:9: warning: ‘t0’ may be used uninitialized [-Wmaybe-uninitialized]
   13 |         f(tj - ti);
      |         ^~~~~~~~~~
tst.c:4:7: note: ‘t0’ was declared here
    4 |   int t0, ti, tj;
      |       ^~

BTW, the warning is incorrect: I can't see t0 in "f(tj - ti);".

Reply via email to