Reputation: 154
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
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
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