VooDooS
VooDooS

Reputation: 154

How does fortran compilers optimize operations in routines' arguments

I am using subroutines in Fortran 90 which have too arguments. On the first call of these subroutines the second one is useless but still present. I know that this is not a nice way to do things but for historical reasons it has been made like this.

For example:

CALL myroutine(A, B + C)

where:

SUBROUTINE myroutine (A, B)
    IF(.NOT. first) THEN
       !Using B in a way or another..
    ELSE
       !Other operations, not using B.
    END IF
END SUBROUTINE routine

I am using gfortran 4.4.7 to compile with -O3.

I would like to know if the operation B + C, useless when it's the first call to myroutine because the second argument is unused, is performed or not...

Moreover, precise compiling optimizations are new to me, and I would be interested in knowing which resources I can refer to when facing such questions.

Upvotes: 2

Views: 152

Answers (2)

francescalus
francescalus

Reputation: 32366

In the subroutine reference CALL myroutine(A, B + C) the B+C is an actual argument expression. In Fortran, actual argument expressions are always evaluated, and evaluated before argument association happens (F2023, 15.5.4; similar in F90 as tagged):

When a subroutine is invoked, all actual argument expressions are evaluated, then the arguments are associated, and then the subroutine is executed.

To a degree, what Fortran says and what a compiler can do to "optimize" do differ. If it's known that evaluation of an expression has no observable effect then a compiler can simply pretend it was evaluated (and we have no way of knowing). Recall benchmarking tests which are entirely optimized away.

However, floating point addition, for example, is rife with potential side effects. Many things are. A compiler would have to be confident an actual argument expression's evaluation has no (possible) side effect before skipping it.

Upvotes: 0

Kyle Kanos
Kyle Kanos

Reputation: 3264

This isn't quite an answer to the question, more a comment on possibly optimizing the code.

As Floris & High Performance Mark comment, it is likely that the compiler still will execute B+C even if the subroutine does not use it. As an alternative to passing B+C to the subroutine every time, you could use the flag OPTIONAL for the variable B in the subroutine, combined with the PRESENT inquiry. You could then eliminate the B+C in the first call to the subroutine and then add it in for the second call:

PROGRAM main
    IMPLICIT NONE
    ! definitions of a, b, c, etc

    CALL myroutine(a)
    CALL myroutine(a,b+c)

  CONTAINS
    SUBROUTINE myroutine(a,b)
       <TYPE> :: a
       <TYPE>, OPTIONAL :: b
       IF(PRESENT(b)) THEN
          ! operations using b and a
       ELSE
          ! operations using a only
       ENDIF
    END SUBROUTINE
END PROGRAM

Where <TYPE> is whatever type A and B are supposed to be.

Upvotes: 3

Related Questions