Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

inline function?

494 views
Skip to first unread message

Lurkos

unread,
May 15, 2013, 6:31:40 AM5/15/13
to
Could you please explain me why this example is working?
It seems a kind of "inline" definition of a function, that I never met before.
Is it part of the Fortran standard?

program bar
implicit none

real :: func,x,y
func(x,y) = x + y

write(*,*) func(7.3,2.7)

end program bar

Rudra Banerjee

unread,
May 15, 2013, 7:03:29 AM5/15/13
to
This is what is defined as statement function in fortran.
This is part of fortran standard (f2008 12.6.4(page #311) of Working
Document that I have access).

Anton Shterenlikht

unread,
May 15, 2013, 8:01:29 AM5/15/13
to
Rudra Banerjee <bnrj....@gmail.com> writes:

>This is what is defined as statement function in fortran.
>This is part of fortran standard (f2008 12.6.4(page #311) of Working
>Document that I have access).

Note that statement function is an obsolescent feature
since 1995 standard. It might (should?) be replaced
by an internal function, see. e.g. MFE, p. 421.

Anton

>On Wed, 2013-05-15 at 03:31 -0700, Lurkos wrote:
>> Could you please explain me why this example is working?
>> It seems a kind of "inline" definition of a function, that I never met be=
>fore.
>> Is it part of the Fortran standard?
>>=20
>> program bar
>> implicit none
>>=20
>> real :: func,x,y
>> func(x,y) =3D x + y
>>=20
>> write(*,*) func(7.3,2.7)
>>=20
>> end program bar


Lurkos

unread,
May 15, 2013, 8:31:23 AM5/15/13
to
And this one is a more complicated version, that actually works with ifort and not with gfortran nor g95.

Could you please why this different behaviour?
It should be something related on the actual support of newer standards, maybe, but I haven't identified which part.
Thanks!

[gfortran-4.8.1]
func(x,y) = x + y
1
Error: Symbol 'y' at (1) has no IMPLICIT type

[g95-0.94]
func(x,y) = x + y
1
Error: Unexpected array reference at (1)

---8<---
module foo
implicit none

contains
real function qux(a)
real, intent(in) :: a
real :: y
real :: z

z = contfun()

qux = z + a

contains
real function contfun()
real :: x, func
func(x,y) = x + y

contfun = 2. + func(6.,3.)

end function contfun
end function qux
end module foo

program bar
use foo
implicit none

write(*,*) qux(9.)

end program bar
--->8---

glen herrmannsfeldt

unread,
May 15, 2013, 8:42:07 AM5/15/13
to
Anton Shterenlikht <me...@mech-cluster241.men.bris.ac.uk> wrote:
> Rudra Banerjee <bnrj....@gmail.com> writes:

>>This is what is defined as statement function in fortran.
>>This is part of fortran standard (f2008 12.6.4(page #311) of Working
>>Document that I have access).

> Note that statement function is an obsolescent feature
> since 1995 standard. It might (should?) be replaced
> by an internal function, see. e.g. MFE, p. 421.

Personally, I always liked statement functions where a very
simple function was needed. Maybe this was just a fake
example, but if you really need a function that adds two
arguments, a statment function seems so much simpler than
an internal function.

Are nested internal functions allowed yet? If not, then that
would be another possible use for statement functions.

I suppose an alternative is a C preprocessor macro:

#define func(a,b) ((a)+((b))

-- glen

glen herrmannsfeldt

unread,
May 15, 2013, 10:32:20 AM5/15/13
to
Lurkos <lurkos...@gmail.com> wrote:
> And this one is a more complicated version, that actually works
> with ifort and not with gfortran nor g95.

> Could you please why this different behaviour?
> It should be something related on the actual support of
> newer standards, maybe, but I haven't identified which part.

> [gfortran-4.8.1]
> func(x,y) = x + y
> 1
> Error: Symbol 'y' at (1) has no IMPLICIT type

There is an IMPLICIT NONE that applies here, and no declaration
for Y.

> [g95-0.94]
> func(x,y) = x + y
> 1
> Error: Unexpected array reference at (1)

This one I don't understand, but maybe the same reason.
It might be that the compiler decided it wasn't a statement
function, since Y wasn't declared, and so then considered
it an assignment statement.

> ---8<---
> module foo
> implicit none

> contains
> real function qux(a)
> real, intent(in) :: a
> real :: y
> real :: z

> z = contfun()

> qux = z + a

> contains
> real function contfun()
> real :: x, func
> func(x,y) = x + y

Note that statement function arguments are not variables.
The real :: y in the containing function declares a variable,
but does not supply a type for Y in a nested internal function.


Note that if you instead said:

func(x) = x + y

then it would reference the variable y.

Also, consider:

real :: x, y, func
func(x,y) = x + y
y = 3
print *,y,func(1.,2.)
print *,y,func(3.,4.)

Now there is a variable y, which is not the same as the y in
the statement function.

-- glen

Richard Maine

unread,
May 15, 2013, 11:02:43 AM5/15/13
to
Lurkos <lurkos...@gmail.com> wrote:

> Could you please explain me why this example is working?
> It seems a kind of "inline" definition of a function, that I never met before.
> Is it part of the Fortran standard?

Yes. Look up "statement function" in any complete Fortran reference.
Depending on the reference, you might need to look in wherever it
documents obsolescent features if that's in a separate place. For
example, MR&C has them in an Appendix. I suppose you might have some
reference that omits mention of obsolecent features.

Although they are still in the standard, I recommend aginst the use of
statement functions. They have all manner of strange quirks. I am *NOT*
going to bother to help you navigate your way through those quirks, as I
would regard that as worse than a waste of time, but an active
disservice if it encourages you to use statement functions on new code.
One of those quirks is that the syntax is too much like that of an
assignment statement, so that both humans and compilers easily confuse
them, sometimes resulting in misleading error messages, one of which you
ran into. There are also subtle oddities relating to scope.

That being said, your other question relating to a more complicated case
isn't particularly subtle. You do specify implicit none (a practice I
recommend). You then use y as a variable, but have no declaration for
it. That's exactly the kind of thing implicit none is supposed to bitch
about. As to where a declaration for y belongs, well that gets into one
of the oddities of statement functions.

--
Richard Maine
email: last name at domain . net
domain: summer-triangle

Robin Vowels

unread,
May 15, 2013, 11:20:06 AM5/15/13
to
On May 16, 12:32 am, glen herrmannsfeldt <g...@ugcs.caltech.edu>
wrote:
That's because in the function statement, x and y on the left
are dummy arguments, and to the right of the equal sign,
they are references to the dummy arguments.

Nevertheless, the types of the dummy arguments are defined
in the REAL statement (seeing, as they are, in the same scope),
and the variable "y" in "y = 3" receives the same type as defined
earlier.

Walt Brainerd

unread,
May 15, 2013, 7:40:52 PM5/15/13
to
I think Glen and Robin and Rich have done a good job
illustrating why using statement functions is not
such a great idea.

Ian Harvey

unread,
May 16, 2013, 12:22:04 AM5/16/13
to
On 2013-05-15 10:42 PM, glen herrmannsfeldt wrote:
...

> I suppose an alternative is a C preprocessor macro:
>
> #define func(a,b) ((a)+((b))

Taking the expression as just a placeholder - the preprocessor
definition is one line, while the module procedure would be about five
lines.

function func(a, b)
real, intent(in) :: a, b
real :: func
func = a + b
end function func

Is it really worth the portability loss and other negatives associated
with preprocessor macros (lack of constrained scope, opacity, etc) for
four incremental lines? Not here!

> -- glen
>

glen herrmannsfeldt

unread,
May 16, 2013, 1:47:37 AM5/16/13
to
Ian Harvey <ian_h...@bigpond.com> wrote:

(snip, I wrote)
>> I suppose an alternative is a C preprocessor macro:

>> #define func(a,b) ((a)+((b))

> Taking the expression as just a placeholder - the preprocessor
> definition is one line, while the module procedure would be about five
> lines.

> function func(a, b)
> real, intent(in) :: a, b
> real :: func
> func = a + b
> end function func

> Is it really worth the portability loss and other negatives associated
> with preprocessor macros (lack of constrained scope, opacity, etc) for
> four incremental lines? Not here!

Well, the C proprocessor itself is pretty portable. That doesn't
mean that you will have it, though.

Otherwise, as far as I know it is usual for optimizing compilers
to expand statement functions inline. Preprocessor macros expand
as text, so the same as writing the whole thing in place, but
easier to change. (If it occurs in many places.)

I suppose many compilers also expand inline small internal functions,
but don't actually know about any specific compilers.

-- glen

Ian Harvey

unread,
May 16, 2013, 2:22:21 AM5/16/13
to
Even if you put "easier to optimise" on the ledger, I still think its a
poor option.

Practically these days, when I ask for it I expect my production
compiler to be able to inline (where it deems appropriate) *any* unit of
code in the program, whether it be a statement function, internal,
module, or external procedure. I don't think those expectations are
unrealistic.

Robin Vowels

unread,
May 16, 2013, 8:38:06 PM5/16/13
to
How about one incremental line? :-

Thomas Jahns

unread,
May 21, 2013, 4:35:55 AM5/21/13
to
On 05/16/2013 08:22 AM, Ian Harvey wrote:
> Practically these days, when I ask for it I expect my production
> compiler to be able to inline (where it deems appropriate) *any* unit of
> code in the program, whether it be a statement function, internal,
> module, or external procedure. I don't think those expectations are
> unrealistic.

Unfortunately I have experienced this to be not the case for optimization across
compilation units if the whole exceeds a trivial size.

Regards, Thomas

Tobias Burnus

unread,
May 21, 2013, 5:31:51 AM5/21/13
to
But is that necessarily a disadvantage? The overhead of a function call
is not that large. Inlining only matters if either the inlines code is
small - which avoids the calling overhead or when it can be used for
simplification (e.g. the compiler knows via inlining that the stride is
1). Instead of inlining, a compiler might also clone a procedure and
apply the simplification there.

Having said that, compilers might also be tuned for C code, which
typically has much more short functions while Fortran code has longer
functions. Hence, the code-side parameters used for inlining might not
be the best for Fortran. (Don't forget that inlining is heuristic - no
proven algorithm exists which can be used to decide when inlining is
profitable and when not.)


In case of GCC/gfortran, there was recently some work on the inliner,
which also takes Fortran now better into account. Thus, GCC 4.8's
settings should now be better for Fortran. One can also manually play
around with the inlining parameters (see "gfortran --help=params" for
the list) - and in particular -finline-limit=n (n = number of
pseudoinstructions).

Tobias

glen herrmannsfeldt

unread,
May 21, 2013, 10:22:51 AM5/21/13
to
Tobias Burnus <bur...@net-b.de> wrote:
> Am 21.05.2013 10:35, schrieb Thomas Jahns:

(snip regarding inlining of functions)
>> Unfortunately I have experienced this to be not the case for
>> optimization across
>> compilation units if the whole exceeds a trivial size.

> But is that necessarily a disadvantage? The overhead of a function call
> is not that large. Inlining only matters if either the inlines code is
> small - which avoids the calling overhead or when it can be used for
> simplification (e.g. the compiler knows via inlining that the stride is
> 1). Instead of inlining, a compiler might also clone a procedure and
> apply the simplification there.

But inlining also allows for other optimizations that might otherwise
not be possible. Especially constant folding and common subexpression
optimization.

My favorite example, though it might be 40 years old now, is a
story about a Fortran benchmark that did some very complicated
(for the time) calculations using nested calls to statement
functions. In the story, it was then run on the OS/360 Fortran H
compiler which, unusual for the time, expanded statement functions
inline and then did constant expression evaluation. The compiler
then did the whole calculation at compile time, likely much slower
than it would have at run time. (Which is mostly an example of
how not to write benchmarks.)

> Having said that, compilers might also be tuned for C code, which
> typically has much more short functions while Fortran code has longer
> functions. Hence, the code-side parameters used for inlining might not
> be the best for Fortran. (Don't forget that inlining is heuristic - no
> proven algorithm exists which can be used to decide when inlining is
> profitable and when not.)

The general assumption of optimizers is that loops will be run
enough times that it pays to move evaluations out of the loop.
In any real case, I suppose with the exception of loops with
constant limits, the compiler really doesn't know. (Anyone want
to bring back the FREQUENCY statement?)

In the case of very simple (say one operation) functions, an inline
statement function is likely better than a not-inline internal
or external function.

> In case of GCC/gfortran, there was recently some work on the inliner,
> which also takes Fortran now better into account. Thus, GCC 4.8's
> settings should now be better for Fortran. One can also manually play
> around with the inlining parameters (see "gfortran --help=params" for
> the list) - and in particular -finline-limit=n (n = number of
> pseudoinstructions).

Does gfortran inline statement functions?

-- glen

Tobias Burnus

unread,
May 21, 2013, 12:11:01 PM5/21/13
to
glen herrmannsfeldt wrote:
>> But is that necessarily a disadvantage? The overhead of a function call
>> is not that large. Inlining only matters if either the inlines code is
>> small - which avoids the calling overhead or when it can be used for
>> simplification (e.g. the compiler knows via inlining that the stride is
>> 1). Instead of inlining, a compiler might also clone a procedure and
>> apply the simplification there.
>
> But inlining also allows for other optimizations that might otherwise
> not be possible. Especially constant folding and common subexpression
> optimization.

Well, cloning also does so: It might clone a procedure where e.g. one
argument is eliminated as it is used as a constant.

Such kind of optimizations - which can be done by inlining or by cloning
- can be very profitable. Also avoiding the generation of temporaries
and inline replacements of library functions can help with the
performance. However, not always is an inline version faster than a
highly optimized library function - only if the inline-generated version
permits additional optimizations or is also highly optimized.


> The general assumption of optimizers is that loops will be run
> enough times that it pays to move evaluations out of the loop.
> In any real case, I suppose with the exception of loops with
> constant limits, the compiler really doesn't know. (Anyone want
> to bring back the FREQUENCY statement?)

Typically, the interesting loops do not have constant limits. Actually,
for loops more interesting are dependency information. Like OpenMP's
"!$omp simd" or Fortran 2008's DO CONCUCRRENT. If the compiler knows
that the loop order can be modified, it can apply vectorization (=
SIMD), which it otherwise couldn't.

gfortran currently treats do concurrent like a normal loop. However,
with GCC 4.9, it will make use of it.

(Also OpenMP 4 will be [mostly] supported, including "!$omp simd". C/C++
users will presumably also be able to use Cilk+'s features, including
"#pragma simd" - and Fortran-inspired array and elemental handling.)


> In the case of very simple (say one operation) functions, an inline
> statement function is likely better than a not-inline internal
> or external function.

I think it depends. Assume:

do i = 1, 1000000
if (mod(i,10000)) then
call func()
else
x = sin(i*x)
end
end do

Here, inlining "func" could make the program slower as it is only used
on a rare path but might cause that the hot path is not in the cache.

(Not the best example, but you might get the idea.)

Thus, inlining is not always profitable. The fewer instructions the
to-be inlined function has, the higher the chance that inlining is useful.


What also helps is if the compiler can see all users of a procedure. For
instance, with internal procedures, the compiler knows that a procedure
is only used in the host procedure and the siblings of the internal
procedure.

In that case, inlining can eliminate the original procedure, which makes
inlining more profitable.


In newer gfortran versions, also module procedures which are PRIVATE are
regarded as being limited to that module. (Unless they are externally
visible, e.g. via a generic name or by being using in a specification
expression in the interface of a public procedure.)


Similar optimizations apply to module variables, except that GCC doesn't
do apply as much optimization to SAVEd variables as it could be.


> Does gfortran inline statement functions?

Yes, it directly inserts the statement-function code in place.


If you want to see what it does, compile with -fdump-tree-original
-fdump-tree-optimized which gives you an internal representation of the
generated code. The code looks C like and is relatively readable, but it
does not contain the full information. (For instance, derived-type
declarations are missing or Fortran's INTENT which is used for
optimization by the GCC middle end.)

The dumps are written in separate files.

Tobiasg
0 new messages