Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Using MERGE intrinsic where TSOURCE is an optional parameter

John_U_
Beginner
665 Views

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?

program testit
implicit none
call question(50)
call question()  !! is 1000/value evaluated?
call question(0) !! intentional division by zero
contains
subroutine question(value)
integer,optional  :: value
   integer        :: value_local
   value_local=merge(1000/value,456,present(value))  !!  The optional parameter appears in the TSOURCE expression
   write(*,*)'VALUE_LOCAL=',value_local
   !!write(*,*)'VALUE=',value
end subroutine question
end program testit
 

0 Kudos
5 Replies
TimP
Honored Contributor III
665 Views

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.

0 Kudos
jimdempseyatthecove
Honored Contributor III
665 Views

Steve,

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.

Jim Dempsey

0 Kudos
IanH
Honored Contributor II
665 Views

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.

 

0 Kudos
John_U_
Beginner
665 Views

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 :>.

 

 

 

 

 

 

0 Kudos
Steven_L_Intel1
Employee
665 Views

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.

0 Kudos
Reply