Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Beginner
1 View

ifort 16.0.2: no more targeting to elemental functions; Was it a feature, not a bug?

Hi,

Until lately I was using function pointers to alias different elemental procedures sharing the same abstract interface. Obviously that's forbidden according to the standard but allowed until the last version of the ifort compiler. Ifort 16.0.2 now prints the error:

error #6128: Non-intrinsic ELEMENTAL procedure is not allowed as a pointer procedure target.

First, where is the sense in this restriction and second, what else can I do to alias dynamically elemental functions?

Thanks for help!

0 Kudos
8 Replies
Highlighted
1 View

There are two constraints

There are two constraints involved here. The immediate one is (7.2.2.2):

C730 (R740) The proc-target shall not be a nonintrinsic elemental procedure.

There is also C1218, in the discussion of procedure pointer declarations (section 12.4.3.6):

C1218 (R1211) If a proc-interface describes an elemental procedure, each procedure-entity-name shall specify an external procedure.

That is, you can't declare a procedure pointer with an elemental interface.

I did a bit of archaeology here and found that procedure pointers were basically modeled on dummy procedures, and those were not allowed to be elemental, so procedure pointers were also not allowed to be elemental. I know this isn't satisfactory, but as I've often griped to the committee, the rationales for decisions were rarely recorded.

Retired 12/31/2016
0 Kudos
Highlighted
1 View

To answer your other

To answer your other questions, it was a bug that we didn't check the constraint. Offhand I don't know of another way to do this.

Retired 12/31/2016
0 Kudos
Highlighted
Beginner
1 View

Thanks a lot for explanation

Thanks a lot for explanation Steve,

If I understood that right, there are no obvious (rational) reasons to forbid pointing to elemental subroutines. I know that ifort isn't following the standard all the way, thatswhy flags as -standard-semantics are needed. So wouldn't that be a nice case of application for this flag, simply allowing targeting to elemental procedures if not set?

0 Kudos
Highlighted
Black Belt
1 View

This seems to stretch the

This seems to stretch the idea of -standard-semantics too much into new territory.  The option has been used to permit non-standard legacy usage to remain a default for ifort, not to support extensions.  In some cases optimization has been better for the legacy usage, but the developers have fixed some of those annoyances.  For example, I haven't seen any cases where properly written code performs better (and correctly) without protect_parens.

I was somewhat disappointed to see that the bug fix for -standard-semantics with 16.0 update 2 eliminated the attempt to perform simd optimization of maxloc and minloc.  So it is still necessary to add -old_maxminloc in order to optimize those intrinsics (although they will not fail as they might with update 1).

This leads to the suspicion that -standard-semantics is kept as non-default in order to perform better on certain benchmarks.  Those who wish benchmarks to be performed under standards compliant compile options haven't won any battles.

0 Kudos
Highlighted
1 View

If we made all of -standard

If we made all of -standard-semantics the default, it would break so many older programs that customers would be at our door with torches and pitchforks. We are evaluating each of the non-standard semantics (these are not extensions) to see if we can change individual defaults. For example, we are planning to make -assume realloc_lhs the default in the next major release, as most if not all other Fortran compilers already do, assuming we can resolve performance issues (which we have a handle on.) On the other hand, -assume byterecl will probably never become the default.

Tim is right that -standard-semantics is not about extensions, and we are very conservative about implementing extensions nowadays. There may well be a very good reason for the standard's restriction here that I am not aware of. I'll see if I can find out.

Retired 12/31/2016
0 Kudos
Highlighted
1 View

Some comments I got from

Some comments I got from those who have been on the committee longer than I:

My recollection of this is the question whether elemental is implemented by wrapping loops around procedure references, or having a version of the procedure for each rank.  There was some resistance to the possibility that allowing elemental procedure pointers (and arguments) might prejudice how developers implement elemental.  

The association of a procedure pointer with its target is as for the association of a dummy procedure with its actual procedure. A dummy procedure is essentially a pointer, so were just extending what had been around for a long time.

Retired 12/31/2016
0 Kudos
Highlighted
Beginner
1 View

Quote:Steve Lionel (Intel)

Steve Lionel (Intel) wrote:

There was some resistance to the possibility that allowing elemental procedure pointers (and arguments) might prejudice how developers implement elemental.  

So when the committee is that worried about prejudication, then why is this allowed?:

module epointer
implicit none

type, abstract :: I
    contains
        procedure(eint), nopass, deferred :: f
end type I

abstract interface
    elemental function eint(x,y) result(z)
        real, intent(in) :: x,y
        real :: z
    end function eint
end interface

type, extends(I) :: A
    contains
        procedure, nopass :: f => fA
end type A

type, extends(I) :: B
    contains
        procedure, nopass :: f => fB
end type B

contains

    elemental function fA(x,y) result(z)
        real, intent(in) :: x,y
        real :: z

        z=x*y
    end function fA
 
    elemental function fB(x,y) result(z)
        real, intent(in) :: x,y
        real :: z

        z=x/y
    end function fB

end module epointer

program main
    
    use epointer

    implicit none

    class(I), pointer :: gfo
    type(A),target :: ao
    type(B),target :: bo

    gfo=>ao
    write(*,*) gfo%f(12.0,3.0)
    write(*,*) gfo%f([15.0,18.0],[5.0,9.0])

    gfo=>bo
    write(*,*) gfo%f(12.0,3.0)
    write(*,*) gfo%f([15.0,18.0],[5.0,9.0])

end program main

 

From my understanding, this implementation leads basically to the same questioning for the developers when implementing the polymorphic functionalities.... but no arguing of the compiler....

Steve Lionel (Intel) wrote:

Tim is right that -standard-semantics is not about extensions, and we are very conservative about implementing extensions nowadays. There may well be a very good reason for the standard's restriction here that I am not aware of. I'll see if I can find out.

Well, until ifort 16.0.2 my code was working without complaints, so speaking of an extension might not be the right terminology. Probably it falls more under the category "legacy features support"...

0 Kudos
Highlighted
1 View

Neither. It's the category of

Neither. It's the category of "compiler bug  that we fixed". It was never intended as a feature. I'm not quite sure I get the point of your latest example.

You're the second customer I've come across who tripped over this, but the better course is to rewrite the code to conform to the standard.

Retired 12/31/2016
0 Kudos