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

--- Comment #9 from Steve Kargl <sgk at troutmask dot apl.washington.edu> ---
On Wed, May 02, 2018 at 08:53:27AM +0000, janus at gcc dot gnu.org wrote:
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85599
> 
> --- Comment #4 from janus at gcc dot gnu.org ---
> (In reply to kargl from comment #1)
> > The behavior may not be buggy, and it's best not to depend
> > on side-effects.  From F2018,
> > 
> > 10.1.5.4.2 Evaluation of logical intrinsic operations
> > 
> >   Once the interpretation of a logical intrinsic operation is
> >   established, the processor may evaluate any other expression
> >   that is logically equivalent, provided that the integrity of
> >   parentheses in any expression is not violated.
> > 
> >   Two expressions of type logical are logically equivalent
> >   if their values are equal for all possible values of their
> >   primaries.
> > 
> 
> Thanks for the standard quote, Steve. It certainly goes in
> the right direction, but I feel like it's not quite to the point.
> 
> Some other (possibly) relevant passages I found in the 2008 standard:
> 
> *****
> 7.1.7 Evaluation of operands
> 1 It is not necessary for a processor to evaluate all of the operands of an
> expression, or to evaluate entirely each operand, if the value of the
> expression can be determined otherwise.
> *****

The above is actually the clause I went looking for, but I was
short on time yesterday.  I think that this is the one along with
the description of evaluation of a logical expression that 
applies.

> That also sounds like optimizing away the function call might be valid, but
> then there is also this one:
> 
> *****
> 7.1.4 Evaluation of operations
> 2 The evaluation of a function reference shall neither affect nor be affected
> by the evaluation of any other entity within the statement.
> *****

You could be right in that this clause applies.  I, however,
tend to think that this is meant to prevent a side effect 
such as

program foo
   integer i, j
   integer, external :: ping, pong
   common /ah/i
   i = 1
   j = ping() + pong()  ! ping() changes value of i
   print *, pong(), j   ! which effects the output of pong()
   i = 1
   j = pong() + ping()
   print *, pong(), j
end program foo

function ping() result(n)
   integer k
   common /ah/ k
   k = k + 1
   n = 42
end function ping

function pong() result(n)
   common /ah/ m
   if (m > 0) then
      n = m
   else
      n = 0
   end if
end function pong

Yes, it is admittedly a contrived example.  It is also possible
for a compiler to replace

j = 0 * ping() + pong()

with simply

j = pong()

where ping() is never evaluated.  I'll note that gfortran currently
will evaluate ping(), but if ping() takes ages to compute it might
be nice to have -ffrontend-optimize remove its evaluation.

> What worries me most is that other compilers choose different implementations.
> Can this kind of code really be processor-dependent?

Yes, that is troublesome.

Reply via email to