On Thu, 2 Apr 2020, Jakub Jelinek wrote:

> On Thu, Apr 02, 2020 at 11:12:48AM +0200, Richard Biener wrote:
> > > "The implementation may assume that any thread will eventually do one of 
> > > the
> > > following:
> > >  — terminate,
> > >  — make a call to a library I/O function,
> > >  — perform an access through a volatile glvalue, or
> > >  — perform a synchronization operation or an atomic operation.
> > > [Note: This is intended to allow compiler transformations such as removal 
> > > of
> > > empty loops, even when termination cannot be proven. — end note]"
> 
> With -ffinite-loops, do we actually not optimize if the loop has volatile 
> accesses
> or atomics or library I/O calls?

We don't remove the loop then, yes.  All of those are considered 
side-effects by GCC and thus they are considered needed and keep
the loop live.  From a technical point finite_loop_p will still
return true for those which is not correct but harmless at the
moment (I hope).  I read the above as

volatile int i;

int __attribute__((const,noinline)) baz(int i) { return i; }
int foo(int a)
{
  do
    {
      i;
      if (a != baz(a)) return 1;      
    }
  while (1);
}

being a valid endles loop which we indeed preserve.  But we notice
the opportunity to unswitch on the condition and elide _that_ loop:

  <bb 2> [local count: 118111600]:
  _1 = baz (a_4(D));
  if (_1 != a_4(D))
    goto <bb 4>; [11.00%]
  else
    goto <bb 3>; [89.00%]

  <bb 3> [local count: 955630224]:
  vol.0_5 ={v} i;
  goto <bb 3>; [100.00%]

  <bb 4> [local count: 118111600]:
  vol.0_3 ={v} i;
  return 1;

thus turn it into

  if (a != baz(a)) { i; return 1; }
  do { i; } while (1);

Richard.

Reply via email to