On 9/05/2018 2:49 AM, Dominik Gronkiewicz wrote:
> I agree that optimizing out the functions, unless they are declared
> "pure", should be forbidden. If non-pure functions can also be
> carelessly optimized out by the compiler, what is the purpose of
> "pure" word in the first place? Once could get rid of the "pure" word
> altogether and assume that all functions are pure and use subroutines
> for tasks with side effects.
I think there is a misconception about the role of PURE.
The presence of PURE in a subprogram places restrictions on that
subprogram, restrictions that must be diagnosed by a compiler. A
subprogram that compiles in the face of those restrictions provides a
guarantee to the *programmer* that the function may be called in certain
contexts and still have a reasonably deterministic outcome.
Those certain contexts are the various language constructs that permit
execution of things in an unspecified order (which includes there being
no order) - specification parts, FORALL, DO CONCURRENT, etc. As a
further service to the *programmer*, the language requires that
procedures invoked in those constructs be PURE, and that the compiler
diagnose attempts to invoke non-pure procedures.
(The requirements on subprograms go beyond what is actually required for
a reasonably deterministic outcome, as a consequence of ensuring that
the requirements are practicable for a compiler to diagnose.)
When compiling a subprogram, compilers are already quite capable of
understanding the semantics of Fortran source to the extent needed for
fancy optimisation - the PURE keyword does not give the compiler any
more information from an optimisation perspective.
In summary - PURE is an aid for the programmer, not the compiler.
I think there is also a misconception about the role of expressions in
the language. Outside of certain pointer related contexts, expressions
are principally intended to be evaluated to get a value. Whatever else
may happen along the way is almost irrelevant from a language
perspective. Explicit freedoms given to processors to support this
include the currently discussed freedom around the order and need to
evaluate operands, and the ability to evaluate a mathematical equivalent
of the original expression. Eliding function invocations that are not
required to satisfy the principal intent of evaluating the expression is
not being "careless".
Functions can easily be used as an operand within an expression. Given
this, it makes good sense to follow some guidelines on what should go in
a function to ensure that the use of the function is going to be
consistent with the principal intent of evaluating expressions. Details
vary, exceptions exist, etc, but a very common guideline is that
functions should be written as if they are PURE, and if a "side-effect"
of a function is actually its principal effect, then that function
should be a subroutine. But these are guidelines, not language rules.
There is no ambiguity. The code presented in the original post does not
conform to the requirements of the standard.
> Also, as someone pointed out, many external libraries written in C
> use functions rather than subroutines -- it would be shame to break
> interoperability by allowing unexpected behavior here.
If Fortran source code invokes such interoperable procedures in a manner
that complies with the rules of the Fortran language, then the behaviour
is as expected.
For interoperable functions with side effects, that simply comes down to
having the function as the only thing in an expression:
variable = c_fun(xxx)
Don't chain such function calls together in a larger expression.