Path: utzoo!utgpu!water!watmath!clyde!att!osu-cis!tut.cis.ohio-state.edu!mailrus!nrl-cmf!cmcl2!lanl!jlg
From: jlg@lanl.gov (Jim Giles)
Newsgroups: comp.lang.fortran
Subject: Re: Function call optimisations (was Re: i++, i+=1, i=i+1)
Message-ID: <3982@lanl.gov>
Date: 21 Sep 88 23:41:24 GMT
References: <13675@mimsy.UUCP>
Organization: Los Alamos National Laboratory
Lines: 45

From article <13675@mimsy.UUCP>, by chris@mimsy.UUCP (Chris Torek):
> 		PROGRAM P
> 		INTEGER F
> 		PRINT *, F(1), F(1)
> 		STOP
> 		END
> 
> Given this situation, may a Fortran compiler legally compile program P
> such that it in fact calls function F only once?
> It is true that the *order* of the calls to F is undefined, but I
> do not know whether the *number* of calls to F is undefined.

As you said, Fortran doesn't guarantee the order of the calls.  It
also (in this case) prohibits several side effects (anything that
might change the value of subsequent calls and any I/O).  If both
calls were part of a singlt mathematical expression, the standard
specifically allows optimizations as long as the mathematical result
is the same (but not, necessarily, the computational result).  So, 
in an expression, the two calls could be optimized to one.  But here, you
have two expressions - so the standard doesn't explicitly allow or
prohibit the optimization in question.  I suspect that if a compiler
did optimize the second call into oblivion, you would have a tough
case to make if you claimed it was illegal.

J. Giles
Los Alamos

P.S.  I would _prefer_ that a compiler would use only one call
      if the function is a known intrinsic and that it make both
      calls for all other functions.  But the standard doesn't require
      it, so do this instead (to be safe):

      tmp = F(1)
      PRINT *, tmp, F(1)

      But, don't do this unless you actually have side effects that you
      wish to protect!  In fact, if you know there are no side effects
      you might want to replace the PRINT with:

      PRINT *, tmp, tmp

      Wouldn't it be nice if you could just declare which functions
      had side effects and which didn't?  Then the normal code would
      always work correctly and could still be optimized when it was
      safe to do so.