Syntactically, the MERGE intrinsic at first appears to be a succinct way to set values for many optional parameters. But if the name of the optional parameter appears in the TSOURCE or FSOURCE expressions it seems like an expression might be evaluated using an undefined value. Does the MERGE intrinsic guarantee it evaluates only the expression returned by the function? Basically, is the following use of MERGE(3f) safe? So far this has worked where I have tried it, but it seems like it not be guaranteed to be portable as far as the Fortran Standard is concerned?
call question() !! is 1000/value evaluated?
call question(0) !! intentional division by zero
integer,optional :: value
integer :: value_local
value_local=merge(1000/value,456,present(value)) !! The optional parameter appears in the TSOURCE expression
end subroutine question
end program testit
I think you refer to the fact that, in practice, merge often performs speculative evaluation of scalar arguments, at normal high optimization settings. I don't see that a discarded value based on speculation with undefined variables is any worse than a value which is used but based on arithmetic with undefined result. If you are trying to catch exceptions under USE IEEE_exceptions, you must set options such as -fp-model strict, which presumably rule out speculative evaluation.
I'm somewhat amused by the statement in Metcalf, Reid, Cohen that the principal use of merge is with array arguments. There have been cases in the past where Intel Fortran optimized better for some targets with merge and array arguments, and for other targets with a DO loop with scalar assignments to array elements.
Merge is widely accepted among various as encouraging speculative evaluation to enable vectorization, although it may require options such as gfortran -ffast-math which may be even more aggressive than ifort -fp-model fast. In the case you pose, there seems relatively little incentive for aggressive optimization which might for example produce a segfault by referring to a .not. present array element.
In light of the ISA now having conditional move, the use of conditional move by compiler optimization of the following may present problems:
(edit from earlier post)
if(present(value)) then value_local=1000/value else value_local=456 endif
IOW over aggressive optimization to use conditional move in the above, could result in divide by 0.0 or divide by LOC==invalid address.
But if the name of the optional parameter appears in the TSOURCE or FSOURCE expressions it seems like an expression might be evaluated using an undefined value. Does the MERGE intrinsic guarantee it evaluates only the expression returned by the function? Basically, is the following use of MERGE(3f) safe?
For clarity, the code is not conforming. The semantics are that all argument expressions to a procedure are evaluated prior to execution of the procedure. MERGE is not special in this regard.
Use an IF statement instead.
Thanks to all;
It would be nice to have a simpler way to handle optional parameters, such as an initialization on the declaration that is used as a default value or a change to PRESENT() so that it returned a type and value set by FSOURCE when present (ie. VALUE=PRESENT(VALUE,100), which would cause VALUE to then appear as "present" instead of just a logical. The MERGE() was a tempting alternative that looked close to what I wanted but I was afraid of the issues confirmed here (and some new issues I hadn't thought about). Although I certainly didn't try all optimization levels or other compiler switches I was surprised tests showed MERGE() worked as hoped empirically on several compilers and had some hope it might be acceptable. Well, you dashed my hopes but I appreciate it :>.
Jim, the use of conditional move would not be valid in that circumstance. The optimizer is told which arguments might be omitted and it is supposed to avoid moving a reference to such outside a condition.
I am aware that some compilers skip evaluation of the TSOURCE expression if the mask is false. As Ian says, the standard doesn't specify this and you can't depend on it any more than you can depend on a compiler doing short-circuit evaluation.