arraysfortranreturn-valuereturn-by-referencereturn-by-value

Fortran 2008: How are function return values returned?


Is it possible in modern Fortran to return an array from a function with performance equivalent to having a subroutine fill an array passed as argument?

Consider e.g. as simple example

PROGRAM PRETURN 

  INTEGER :: C(5)
  C = FUNC()
  WRITE(*,*) C
  CALL SUB(C)
  WRITE(*,*) C

CONTAINS 

  FUNCTION FUNC() RESULT(X)
    INTEGER :: X(5)
    X = [1,2,3,4,5]
  END FUNCTION FUNC

  SUBROUTINE SUB(X)
    INTEGER :: X(5)
    X = [1,2,3,4,5]
  END SUBROUTINE SUB

END PROGRAM PRETURN

Here the line C = FUNC() would copy the values from the function return value, before discarding the returned array from the stack. The subroutine version CALL SUB(C) would fill C directly, avoiding the extra coping step and memory usage associated with the temporary array – but making usage in expresions like SUM(FUNC()) impossible.

If however, the compiler implementation chose to allocate all arrays on the heap, the return value could be assigned simply by changing the underlying pointer of C, resulting in equivalent performance between the two versions.*

Are such optimizations made by common compilers, or is there some other way to get function semantics without the performance overhead?


* It would be more apparent with allocatable arrays, but this would run into compiler-support issues. Intel fortran by default doesn't (re)allocate arrays upon assignment of a different-size array but allows the same effect by using an ALLOCATE(C, SOURCE=FUNC()) statement. Gfortran meanwhile does the automatic allocation on assignment but has a bug that prevents ALLOCATE statements where the shape is derived from the SOURCE argument and the fix hasn't been included in binary releases yet.


Solution

  • The Fortran standard is silent on the actual mechanism for implementing pretty much anything in the language. The semantics of the language are that the function result is completely evaluated before the assignment starts. If one passed the destination as the output then if the function didn't complete for some reason the variable might be partially modified. A compiler might be able to do enough overlap analysis to optimize this somewhat. I am pretty sure that Intel Fortran doesn't do this - the semantic restrictions are significant.

    Your example is a toy program - the more interesting question is if there are production applications where such an optimization would be applicable and worthwhile.

    I will comment that Intel Fortran will change its default behavior for assignments to allocatable arrays so that, as of version 17, the automatic reallocation will occur as specified by the standard.