C++Guns – RoboBlog


FORTRAN: parameter variables in module evaluated at compile or runtime?

Filed under: Allgemein — Tags: — Thomas @ 10:06

Suggest you habe a fortran module with a collection of mathematical constant like PI.

module constant_m
  real, parameter :: PI = 3.1314_8
end module

Now you use this module in a function which calculate the circumcenter of a circle with given radius.

function U(r) 
  use constant_m
  implicit none
  real, intent(in) :: r
  real :: U
  U = 2*PI*r
end function

Will the expression 2*PI be evaluated a compile or runtime?
Lets check the generated assember code!
And you'll see only crap.

Let's start with an simpler example. Replace every real to integer. Truncate PI to 3, thats fair enough. And remove the "2*" expression. Somewhere in the assembler code are there must be the expression y=3*x.
Here it is:
gfortran --save-temps -O1 -c constants.F90 circle.F90

  movl	4(%esp), %eax        % Store the adress of r from stack pointer into eax
  movl	(%eax), %eax         % Dereference adress and store value from r into eax
  leal	(%eax,%eax,2), %eax  % eax = eax + 2*eax 

The last line is the one. The compiler optimize the multiplicaton with 3 to an assembler instrctuin which performs a multiplication with 2 and an addition.
What we not see is a constant "3" in assember code. Or a assembler register filled with "3".

Lets add the "2*" and see whats happens.

  movl	4(%esp), %eax
  movl	(%eax), %eax
  leal	(%eax,%eax,2), %eax
  addl	%eax, %eax

Only the last line is new. The compiler decide that x+x is more performance than 2*x. Cute.

Okay lets have some fun. We force the compiler to evaluate (2*PI) first. (2*PI)*r
And the resulting assembler code is the same HAHA.

Okay back to topic. We see that integer, parameter variables in modules are evaluated at compile time. Lets switch back to real.

Now the assembler code looks a litte bit more complicated:

  flds	.LC0@GOTOFF(%eax)   % Load constant into floading point register
  movl	4(%esp), %eax       % Store value from r into eax
  fmuls	(%eax)              % Multiply the constant with r and put the result back in eax
  .long	1086918230          % The constand 2*PI

Now you can see a constant in assember as a 4byte iteger. Its only one constant, so I guess its 2*PI here.
This constant is loaded into a floting point register. The value from r is loaded into a second register. Then both get multiplyed. Thats all. Only a single multiplaction.


No Comments

No comments yet.

RSS feed for comments on this post.

Sorry, the comment form is closed at this time.

Powered by WordPress