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

Conditional compilation vs. standard Fortran for dead code elimination

rorban
Beginner
535 Views

This question regards the ability of the multi-file optimizer to eliminate dead code. 

I have a multi-file project that is conditionally compiled for several different products. I want to minimize the use of non-standard Fortran (conditional compilation) in favor of standard Fortran wherever possible. The project runs in real time, so efficiency is very important. Take the following example, where there are two files, and a pre-processor constant isAM is set to 0.

File 1:

MODULE specify_product
IMPLICIT NONE
!DIR$ IF (isAM==1)
LOGICAL,  PARAMETER, PUBLIC  :: AM = .TRUE.    
!DIR$ ELSE
LOGICAL,  PARAMETER, PUBLIC  :: AM = .FALSE.    
!DIR$ END IF
END MODULE

File 2:

MODULE calculate
USE specify_product
IMPLICIT NONE
CONTAINS
  SUBROUTINE do_calculation
  IF (AM) THEN
    [do something]
  ELSE
    [do something else]
  END IF
  END SUBROUTINE
END MODULE

The subroutine is then called elsewhere in the code.

I could also achieve the same functionality by conditionally compiling the IF-THEN-ELSE like so:

!DIR$ IF (isAM==1)
   [do something].    
!DIR$ ELSE
   [do something else].    
!DIR$ END IF

My question is whether the multi-file optimizer will recognize that AM is a constant, it is always .FALSE., and therefore the IF-THEN-ELSE loop can be reduced to

[do something else]

In other words, is using standard Fortran as efficient as using the pre-processor?

I tried compiling my code with diagnostics at Level 5 and Optimization = Maximize Speed, but this did not report that the "dead" part of the IF-THEN-ELSE loop had been eliminated. But I don't know if it is supposed to report this. 

0 Kudos
8 Replies
Steve_Lionel
Honored Contributor III
535 Views

Yes, the compiler will see that AM is a constant and will use that in determining whether code should be generated. I am not aware that the Intel compiler's optimization report includes dead code messages. It's pretty easy to look at the assembly output and determine if the IF branch was evaporated, but I'm reasonably confident that in a case such as you describe, it will be.

0 Kudos
rorban
Beginner
535 Views

Thanks for your quick reply. That's the answer I was hoping for!

0 Kudos
jimdempseyatthecove
Honored Contributor III
535 Views

Rorban,

Bare in mind, while the IF...THEN...ENDIF will eliminate the test and the dead code branch of your example, it will not (necessarily) eliminate a subroutine that is only called from within the dead code branch of the sample code. To resolve this you will need to use

!DIR$ ATTRIBUTES FORCEINLINE :: YourProcedureNameHere

You will need to test to see if the  IF...THEN...ENDIF and the inlined subroutine need to be in the same compilation unit (not necessarily as a CONTAINED procedure).

Another alternative is to compile the conditional use subroutine external to the main program as a static library, individual, object file. Then the linker would handle the inclusion or exclusion of the subroutine.

Jim Dempsey

0 Kudos
rorban
Beginner
535 Views

Jim,

Thanks for the clarification. Will the linker also ignore subroutines that are in modules other than MODULE calculate and that are only called by the unreachable code? 

0 Kudos
Steve_Lionel
Honored Contributor III
535 Views

The linker excludes only by object files. If an object has subroutines A and B, both will get loaded if only A is called. If every subroutine is in its own source file, they'll be in separate objects and un-called routines won't get loaded.

 

0 Kudos
rorban
Beginner
535 Views

So I presume that this means that if a module is in a separate file and contains only subroutines that cannot be reached, nothing from that module will be loaded? (In other words, I am trying to verify that the "non-loading" occurs when code is written in a modern style with modules providing explicit interfaces, provided that all executable routines in the module cannot be reached.) 

0 Kudos
Steve_Lionel
Honored Contributor III
535 Views

If NO symbols from that module are used, then nothing from that module will be loaded. Sometimes non-routine definitions in a module results in an object contribution (especially variables).

0 Kudos
jimdempseyatthecove
Honored Contributor III
535 Views

>> I am trying to verify that the "non-loading" occurs

Generate a map file and look for the (absences of) entry points, named commons, or anything identifiable with the file you want excluded.

You could also use the debugger, open a Memory or disassembly window, and type in the procedure name.

Jim Dempsey

0 Kudos
Reply