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.