[PATCH][RFC]Overloading intrinsics

classic Classic list List threaded Threaded
45 messages Options
123
Reply | Threaded
Open this post in threaded view
|

[PATCH][RFC]Overloading intrinsics

Martin Liška-2
Hi.

Unlike the C and C++ front-ends, GNU Fortran does not know about
vector implementations of math routines provided by GLIBC. This
prevents vectorization of many loops which is a frequent cause of
performance that is worse than compilers with their own math library
such as ICC.

The purpose of the patch is to provide a mechanism that will tell Fotran FE
which intrinsics have simd cloned in math library.

I've been cooperating with Paul and we came to a proof-of-concept that consists
of 2 parts (patches):

The first patch adds support for inclusion a module via
command line. The module will be provided by glibc in order to synchronize which functions
are provided by a glibc version. Paul is suggesting to maybe include that into load machinery
of IEEE module.

Second patch propagates information about newly introduced attribute simd_notinbranch into
gfc_intrinsic_sym. That is later used to modify a corresponding __bultin_*.

Definition of the intrinsics module and it's usage can look like:

cat ~/Programming/testcases/use.f90
module overload
  interface
    function sin(arg)
      !GCC$ attributes simd_notinbranch :: sin
      real, intent(in) :: arg
      real :: sin
    end function sin
  end interface
end module

program test_overloaded_intrinsic
  real(4) :: x(3200), y(3200), z(3200)

  ! this should be using simd clone
  y = sin(x)
  print *, y

  ! this not
  z = cos(x)
  print *, z
end

Then using my patches one can see:
$ ./xgcc -B. ~/Programming/testcases/use.f90 -c -Ofast -fdump-tree-optimized=/dev/stdout -c

;; Function test_overloaded_intrinsic (MAIN__, funcdef_no=0, decl_uid=3815, cgraph_uid=1, symbol_order=0) (executed once)

test_overloaded_intrinsic ()
{
...
  vect__3.14_58 = sinf.simdclone.0 (vect__2.13_60);
  MEM[symbol: y, index: ivtmp.35_47, offset: 0B] = vect__3.14_58;
...
  _6 = __builtin_cosf (_5);
  MEM[symbol: z, index: ivtmp.30_46, offset: 0B] = _6;
...
}

That's what I have. I would like to ask Fortran folks about their opinion? I know
the part in gfc_match_gcc_attributes is bit tricky, but apart from that the rest
should be well formed.

Thoughts?
Thanks,
Martin


0002-Hacky-implementation-of-SIMD-for-math-builtins.patch (4K) Download Attachment
0001-Add-support-for-implicit-modules.patch (2K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH][RFC]Overloading intrinsics

Richard Biener-2
On Mon, Oct 29, 2018 at 2:49 PM Martin Liška <[hidden email]> wrote:

>
> Hi.
>
> Unlike the C and C++ front-ends, GNU Fortran does not know about
> vector implementations of math routines provided by GLIBC. This
> prevents vectorization of many loops which is a frequent cause of
> performance that is worse than compilers with their own math library
> such as ICC.
>
> The purpose of the patch is to provide a mechanism that will tell Fotran FE
> which intrinsics have simd cloned in math library.
>
> I've been cooperating with Paul and we came to a proof-of-concept that consists
> of 2 parts (patches):
>
> The first patch adds support for inclusion a module via
> command line. The module will be provided by glibc in order to synchronize which functions
> are provided by a glibc version. Paul is suggesting to maybe include that into load machinery
> of IEEE module.
>
> Second patch propagates information about newly introduced attribute simd_notinbranch into
> gfc_intrinsic_sym. That is later used to modify a corresponding __bultin_*.
>
> Definition of the intrinsics module and it's usage can look like:
>
> cat ~/Programming/testcases/use.f90
> module overload
>   interface
>     function sin(arg)
>       !GCC$ attributes simd_notinbranch :: sin
>       real, intent(in) :: arg
>       real :: sin
>     end function sin
>   end interface
> end module
>
> program test_overloaded_intrinsic
>   real(4) :: x(3200), y(3200), z(3200)
>
>   ! this should be using simd clone
>   y = sin(x)
>   print *, y
>
>   ! this not
>   z = cos(x)
>   print *, z
> end
>
> Then using my patches one can see:
> $ ./xgcc -B. ~/Programming/testcases/use.f90 -c -Ofast -fdump-tree-optimized=/dev/stdout -c
>
> ;; Function test_overloaded_intrinsic (MAIN__, funcdef_no=0, decl_uid=3815, cgraph_uid=1, symbol_order=0) (executed once)
>
> test_overloaded_intrinsic ()
> {
> ...
>   vect__3.14_58 = sinf.simdclone.0 (vect__2.13_60);
>   MEM[symbol: y, index: ivtmp.35_47, offset: 0B] = vect__3.14_58;
> ...
>   _6 = __builtin_cosf (_5);
>   MEM[symbol: z, index: ivtmp.30_46, offset: 0B] = _6;
> ...
> }
>
> That's what I have. I would like to ask Fortran folks about their opinion? I know
> the part in gfc_match_gcc_attributes is bit tricky, but apart from that the rest
> should be well formed.
>
> Thoughts?

The gfc_conv_intrinsic_lib_function should be in
gfc_get_intrinsic_lib_fndecl instead I think
as you are adding the attribute once for each call it seems.  I think
that it would be more
forward-looking to make the gfc_intrinsics_sym->simd flag a 'tree
attributes' list instead.

That you do the matching in gfc_match_gcc_attributes is quite odd IMHO
but you said
that already.  I'd say a more proper place would be where the FE
"ends" parsing of
the specification part of an interface.

Of course simd_notinbranch isn't exactly supporting all simd variants,
but not sure
how difficult it is to add this as 'simd' with arguments...

Some bikeshedding on the other part:

+module-include
+Fortran Joined Separate
+Use implicitelly a module
+

module-use or use-module or simply use?  Or import?  include sounds so C-ish.

+void
+gfc_add_implicit_use (const char *module_name)
+{
+  implicit_module_name = module_name;
+}

so this works for exactly one module...

I guess the part that is missing is to add target specific specs
fragments adding
-use FOO for fortran invocations, allowing FOO to not exist(?).

Richard.


> Thanks,
> Martin
>
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH][RFC]Overloading intrinsics

Martin Liška-2
On 10/29/18 4:24 PM, Richard Biener wrote:

> On Mon, Oct 29, 2018 at 2:49 PM Martin Liška <[hidden email]> wrote:
>>
>> Hi.
>>
>> Unlike the C and C++ front-ends, GNU Fortran does not know about
>> vector implementations of math routines provided by GLIBC. This
>> prevents vectorization of many loops which is a frequent cause of
>> performance that is worse than compilers with their own math library
>> such as ICC.
>>
>> The purpose of the patch is to provide a mechanism that will tell Fotran FE
>> which intrinsics have simd cloned in math library.
>>
>> I've been cooperating with Paul and we came to a proof-of-concept that consists
>> of 2 parts (patches):
>>
>> The first patch adds support for inclusion a module via
>> command line. The module will be provided by glibc in order to synchronize which functions
>> are provided by a glibc version. Paul is suggesting to maybe include that into load machinery
>> of IEEE module.
>>
>> Second patch propagates information about newly introduced attribute simd_notinbranch into
>> gfc_intrinsic_sym. That is later used to modify a corresponding __bultin_*.
>>
>> Definition of the intrinsics module and it's usage can look like:
>>
>> cat ~/Programming/testcases/use.f90
>> module overload
>>   interface
>>     function sin(arg)
>>       !GCC$ attributes simd_notinbranch :: sin
>>       real, intent(in) :: arg
>>       real :: sin
>>     end function sin
>>   end interface
>> end module
>>
>> program test_overloaded_intrinsic
>>   real(4) :: x(3200), y(3200), z(3200)
>>
>>   ! this should be using simd clone
>>   y = sin(x)
>>   print *, y
>>
>>   ! this not
>>   z = cos(x)
>>   print *, z
>> end
>>
>> Then using my patches one can see:
>> $ ./xgcc -B. ~/Programming/testcases/use.f90 -c -Ofast -fdump-tree-optimized=/dev/stdout -c
>>
>> ;; Function test_overloaded_intrinsic (MAIN__, funcdef_no=0, decl_uid=3815, cgraph_uid=1, symbol_order=0) (executed once)
>>
>> test_overloaded_intrinsic ()
>> {
>> ...
>>   vect__3.14_58 = sinf.simdclone.0 (vect__2.13_60);
>>   MEM[symbol: y, index: ivtmp.35_47, offset: 0B] = vect__3.14_58;
>> ...
>>   _6 = __builtin_cosf (_5);
>>   MEM[symbol: z, index: ivtmp.30_46, offset: 0B] = _6;
>> ...
>> }
>>
>> That's what I have. I would like to ask Fortran folks about their opinion? I know
>> the part in gfc_match_gcc_attributes is bit tricky, but apart from that the rest
>> should be well formed.
>>
>> Thoughts?
>
> The gfc_conv_intrinsic_lib_function should be in
> gfc_get_intrinsic_lib_fndecl instead I think
> as you are adding the attribute once for each call it seems.  I think
> that it would be more
Hi.

I fixed that by clearing of simd attribute. But yes, it makes sense to set
it just once.

> forward-looking to make the gfc_intrinsics_sym->simd flag a 'tree
> attributes' list instead.

Well, I believe all the flags gfc_intrinsic_sym flags are used in very similar way
as I use it for simd flag.

>
> That you do the matching in gfc_match_gcc_attributes is quite odd IMHO
> but you said
> that already.  I'd say a more proper place would be where the FE
> "ends" parsing of
> the specification part of an interface.

I improved that and I also do it only for a module with 'vector_math' name.
Will we want that?

>
> Of course simd_notinbranch isn't exactly supporting all simd variants,
> but not sure
> how difficult it is to add this as 'simd' with arguments...

Will we need multiple variants?

>
> Some bikeshedding on the other part:
>
> +module-include
> +Fortran Joined Separate
> +Use implicitelly a module
> +
>
> module-use or use-module or simply use?  Or import?  include sounds so C-ish.

Yep, I prefer module-use.

>
> +void
> +gfc_add_implicit_use (const char *module_name)
> +{
> +  implicit_module_name = module_name;
> +}
>
> so this works for exactly one module...

I extended that to support multiple ones.

>
> I guess the part that is missing is to add target specific specs
> fragments adding
> -use FOO for fortran invocations, allowing FOO to not exist(?).

Will take a look at that.

Now I've tried to separate real module and it's usage and I see strange error:

$ cat ~/Programming/testcases/module.f90
module vector_math
  interface
    function sin(arg)
      !GCC$ attributes simd_notinbranch :: sin
      real, intent(in) :: arg
      real :: sin
    end function sin
  end interface
end module

$ ./xgcc -B. -Ofast -c ~/Programming/testcases/module.f90

$ cat ~/Programming/testcases/use.f90
program test_overloaded_intrinsic
  use vector_math
  real(4) :: x(3200), y(3200), z(3200)

  ! this should be using simd clone
  y = sin(x)
  print *, y

  ! this not
  z = cos(x)
  print *, z

  z = sin (z)
  print *, z
end

$ ./xgcc -B. -Ofast -c ~/Programming/testcases/use.f90
/home/marxin/Programming/testcases/use.f90:6:10:

    6 |   y = sin(x)
      |          1
Error: Rank mismatch in argument ‘arg’ at (1) (scalar and rank-1)
/home/marxin/Programming/testcases/use.f90:13:11:

   13 |   z = sin (z)
      |           1
Error: Rank mismatch in argument ‘arg’ at (1) (scalar and rank-1)

Thanks,
Martin

>
> Richard.
>
>
>> Thanks,
>> Martin
>>


0002-Support-simd-attribute-propagation-for-a-vector_math.patch (5K) Download Attachment
0001-Add-support-for-implicit-modules.patch (3K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH][RFC]Overloading intrinsics

Janne Blomqvist-3
In reply to this post by Martin Liška-2
On Mon, Oct 29, 2018 at 3:49 PM Martin Liška <[hidden email]> wrote:

> Hi.
>
> Unlike the C and C++ front-ends, GNU Fortran does not know about
> vector implementations of math routines provided by GLIBC. This
> prevents vectorization of many loops which is a frequent cause of
> performance that is worse than compilers with their own math library
> such as ICC.
>
> The purpose of the patch is to provide a mechanism that will tell Fotran FE
> which intrinsics have simd cloned in math library.
>
> I've been cooperating with Paul and we came to a proof-of-concept that
> consists
> of 2 parts (patches):
>
> The first patch adds support for inclusion a module via
> command line. The module will be provided by glibc in order to synchronize
> which functions
> are provided by a glibc version. Paul is suggesting to maybe include that
> into load machinery
> of IEEE module.
>

Would this module be provided by glibc in source form, and included, or
would glibc provide a .mod file?

The problem is that the gfortran module format tends to change for every
release, so the glibc provided module would then only be compatible with
the version glibc was compiled with. I think we should try to avoid such a
situation.

Also, I suppose it would also be possible to use this same mechanism to
provide a similar module for svml, or other vector math libs? If not
shipped as part of gcc, or said math library, maybe as a separate 3rd party
project?

--
Janne Blomqvist
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH][RFC]Overloading intrinsics

Richard Biener-2
In reply to this post by Martin Liška-2
On Tue, Oct 30, 2018 at 4:40 PM Martin Liška <[hidden email]> wrote:

>
> On 10/29/18 4:24 PM, Richard Biener wrote:
> > On Mon, Oct 29, 2018 at 2:49 PM Martin Liška <[hidden email]> wrote:
> >>
> >> Hi.
> >>
> >> Unlike the C and C++ front-ends, GNU Fortran does not know about
> >> vector implementations of math routines provided by GLIBC. This
> >> prevents vectorization of many loops which is a frequent cause of
> >> performance that is worse than compilers with their own math library
> >> such as ICC.
> >>
> >> The purpose of the patch is to provide a mechanism that will tell Fotran FE
> >> which intrinsics have simd cloned in math library.
> >>
> >> I've been cooperating with Paul and we came to a proof-of-concept that consists
> >> of 2 parts (patches):
> >>
> >> The first patch adds support for inclusion a module via
> >> command line. The module will be provided by glibc in order to synchronize which functions
> >> are provided by a glibc version. Paul is suggesting to maybe include that into load machinery
> >> of IEEE module.
> >>
> >> Second patch propagates information about newly introduced attribute simd_notinbranch into
> >> gfc_intrinsic_sym. That is later used to modify a corresponding __bultin_*.
> >>
> >> Definition of the intrinsics module and it's usage can look like:
> >>
> >> cat ~/Programming/testcases/use.f90
> >> module overload
> >>   interface
> >>     function sin(arg)
> >>       !GCC$ attributes simd_notinbranch :: sin
> >>       real, intent(in) :: arg
> >>       real :: sin
> >>     end function sin
> >>   end interface
> >> end module
> >>
> >> program test_overloaded_intrinsic
> >>   real(4) :: x(3200), y(3200), z(3200)
> >>
> >>   ! this should be using simd clone
> >>   y = sin(x)
> >>   print *, y
> >>
> >>   ! this not
> >>   z = cos(x)
> >>   print *, z
> >> end
> >>
> >> Then using my patches one can see:
> >> $ ./xgcc -B. ~/Programming/testcases/use.f90 -c -Ofast -fdump-tree-optimized=/dev/stdout -c
> >>
> >> ;; Function test_overloaded_intrinsic (MAIN__, funcdef_no=0, decl_uid=3815, cgraph_uid=1, symbol_order=0) (executed once)
> >>
> >> test_overloaded_intrinsic ()
> >> {
> >> ...
> >>   vect__3.14_58 = sinf.simdclone.0 (vect__2.13_60);
> >>   MEM[symbol: y, index: ivtmp.35_47, offset: 0B] = vect__3.14_58;
> >> ...
> >>   _6 = __builtin_cosf (_5);
> >>   MEM[symbol: z, index: ivtmp.30_46, offset: 0B] = _6;
> >> ...
> >> }
> >>
> >> That's what I have. I would like to ask Fortran folks about their opinion? I know
> >> the part in gfc_match_gcc_attributes is bit tricky, but apart from that the rest
> >> should be well formed.
> >>
> >> Thoughts?
> >
> > The gfc_conv_intrinsic_lib_function should be in
> > gfc_get_intrinsic_lib_fndecl instead I think
> > as you are adding the attribute once for each call it seems.  I think
> > that it would be more
>
> Hi.
>
> I fixed that by clearing of simd attribute. But yes, it makes sense to set
> it just once.
>
> > forward-looking to make the gfc_intrinsics_sym->simd flag a 'tree
> > attributes' list instead.
>
> Well, I believe all the flags gfc_intrinsic_sym flags are used in very similar way
> as I use it for simd flag.
>
> >
> > That you do the matching in gfc_match_gcc_attributes is quite odd IMHO
> > but you said
> > that already.  I'd say a more proper place would be where the FE
> > "ends" parsing of
> > the specification part of an interface.
>
> I improved that and I also do it only for a module with 'vector_math' name.
> Will we want that?

I don't think so.

> >
> > Of course simd_notinbranch isn't exactly supporting all simd variants,
> > but not sure
> > how difficult it is to add this as 'simd' with arguments...
>
> Will we need multiple variants?

The simd attribute can be used on regular functions as well to get vectorization
without -fopenmp-simd.  But yes, for a standard vectorized math libary full
functionality isn't needed.

> >
> > Some bikeshedding on the other part:
> >
> > +module-include
> > +Fortran Joined Separate
> > +Use implicitelly a module
> > +
> >
> > module-use or use-module or simply use?  Or import?  include sounds so C-ish.
>
> Yep, I prefer module-use.
>
> >
> > +void
> > +gfc_add_implicit_use (const char *module_name)
> > +{
> > +  implicit_module_name = module_name;
> > +}
> >
> > so this works for exactly one module...
>
> I extended that to support multiple ones.
>
> >
> > I guess the part that is missing is to add target specific specs
> > fragments adding
> > -use FOO for fortran invocations, allowing FOO to not exist(?).
>
> Will take a look at that.
>
> Now I've tried to separate real module and it's usage and I see strange error:
>
> $ cat ~/Programming/testcases/module.f90
> module vector_math
>   interface
>     function sin(arg)
>       !GCC$ attributes simd_notinbranch :: sin
>       real, intent(in) :: arg
>       real :: sin
>     end function sin
>   end interface
> end module
>
> $ ./xgcc -B. -Ofast -c ~/Programming/testcases/module.f90
>
> $ cat ~/Programming/testcases/use.f90
> program test_overloaded_intrinsic
>   use vector_math
>   real(4) :: x(3200), y(3200), z(3200)
>
>   ! this should be using simd clone
>   y = sin(x)
>   print *, y
>
>   ! this not
>   z = cos(x)
>   print *, z
>
>   z = sin (z)
>   print *, z
> end
>
> $ ./xgcc -B. -Ofast -c ~/Programming/testcases/use.f90
> /home/marxin/Programming/testcases/use.f90:6:10:
>
>     6 |   y = sin(x)
>       |          1
> Error: Rank mismatch in argument ‘arg’ at (1) (scalar and rank-1)
> /home/marxin/Programming/testcases/use.f90:13:11:
>
>    13 |   z = sin (z)
>       |           1
> Error: Rank mismatch in argument ‘arg’ at (1) (scalar and rank-1)
>
> Thanks,
> Martin
>
> >
> > Richard.
> >
> >
> >> Thanks,
> >> Martin
> >>
>
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH][RFC]Overloading intrinsics

Richard Biener-2
In reply to this post by Janne Blomqvist-3
On Wed, Oct 31, 2018 at 9:29 AM Janne Blomqvist
<[hidden email]> wrote:

>
> On Mon, Oct 29, 2018 at 3:49 PM Martin Liška <[hidden email]> wrote:
>>
>> Hi.
>>
>> Unlike the C and C++ front-ends, GNU Fortran does not know about
>> vector implementations of math routines provided by GLIBC. This
>> prevents vectorization of many loops which is a frequent cause of
>> performance that is worse than compilers with their own math library
>> such as ICC.
>>
>> The purpose of the patch is to provide a mechanism that will tell Fotran FE
>> which intrinsics have simd cloned in math library.
>>
>> I've been cooperating with Paul and we came to a proof-of-concept that consists
>> of 2 parts (patches):
>>
>> The first patch adds support for inclusion a module via
>> command line. The module will be provided by glibc in order to synchronize which functions
>> are provided by a glibc version. Paul is suggesting to maybe include that into load machinery
>> of IEEE module.
>
>
> Would this module be provided by glibc in source form, and included, or would glibc provide a .mod file?

I think glibc will provide the module in source form and it's build
machinery or distributors build machinery
will likely build a .mod file.  An alternative variant would be to
provide the GCC build with a path to the
module source and build that into a GCC specific path (like where the
omp module sits).

> The problem is that the gfortran module format tends to change for every release, so the glibc provided module would then only be compatible with the version glibc was compiled with. I think we should try to avoid such a situation.

Yes, of course.

> Also, I suppose it would also be possible to use this same mechanism to provide a similar module for svml, or other vector math libs? If not shipped as part of gcc, or said math library, maybe as a separate 3rd party project?

I'm not sure that would work unless they provide the functions with
"standard" mangling for OpenMP SIMD.
If they do then yes.

Richard.

> --
> Janne Blomqvist
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH][RFC]Overloading intrinsics

Toon Moene-3
In reply to this post by Martin Liška-2
On 10/30/2018 04:40 PM, Martin Liška wrote:

Did anyone ever helped you with this error message ? I haven't seen a
reply to the list to that effect ...

> Now I've tried to separate real module and it's usage and I see strange error:
>
> $ cat ~/Programming/testcases/module.f90
> module vector_math
>    interface
>      function sin(arg)
>        !GCC$ attributes simd_notinbranch :: sin
>        real, intent(in) :: arg
>        real :: sin
>      end function sin
>    end interface
> end module
>
> $ ./xgcc -B. -Ofast -c ~/Programming/testcases/module.f90
>
> $ cat ~/Programming/testcases/use.f90
> program test_overloaded_intrinsic
>    use vector_math
>    real(4) :: x(3200), y(3200), z(3200)
>
>    ! this should be using simd clone
>    y = sin(x)
>    print *, y
>
>    ! this not
>    z = cos(x)
>    print *, z
>
>    z = sin (z)
>    print *, z
> end
>
> $ ./xgcc -B. -Ofast -c ~/Programming/testcases/use.f90
> /home/marxin/Programming/testcases/use.f90:6:10:
>
>      6 |   y = sin(x)
>        |          1
> Error: Rank mismatch in argument ‘arg’ at (1) (scalar and rank-1)
> /home/marxin/Programming/testcases/use.f90:13:11:
>
>     13 |   z = sin (z)
>        |           1
> Error: Rank mismatch in argument ‘arg’ at (1) (scalar and rank-1)

What is happening here is that you define an EXTERNAL function "sin"
which, according to your declaration [ I left out the GCC attribute ]:

 >      function sin(arg)
 >        real, intent(in) :: arg
 >        real :: sin

is a real function of a scalar argument returning a scalar result.

However, in using it, you pass it 32000 element arrays of reals (you
don't need, and should omit, the (4) on the real declaration).

This works for the INTRINSIC functions "sin", "cos", etc., because the
Fortran language declares them to be ELEMENTAL.

This means that, while you can pass them a scalar argument and get a
scalar result, you can also pass them a rank-N array and get a rank-N
array result OF THE SAME SHAPE.

I wonder if it works to change the declaration to:

 >      elemental real function sin(arg)
 >        real, intent(in) :: arg
 >        real :: sin

which declares a user-defined, EXTERNAL, ELEMENTAL function called "sin".

Hope this helps,

--
Toon Moene - e-mail: [hidden email] - phone: +31 346 214290
Saturnushof 14, 3738 XG  Maartensdijk, The Netherlands
At home: http://moene.org/~toon/; weather: http://moene.org/~hirlam/
Progress of GNU Fortran: http://gcc.gnu.org/wiki/GFortran#news
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH][RFC]Overloading intrinsics

Martin Liška-2
On 10/31/18 8:58 PM, Toon Moene wrote:
> On 10/30/2018 04:40 PM, Martin Liška wrote:
>
> Did anyone ever helped you with this error message ? I haven't seen a reply to the list to that effect ...

Hello.

No, you're the first one who replied. Thanks for it.

>
>> Now I've tried to separate real module and it's usage and I see strange error:
>>
>> $ cat ~/Programming/testcases/module.f90
>> module vector_math
>>    interface
>>      function sin(arg)
>>        !GCC$ attributes simd_notinbranch :: sin
>>        real, intent(in) :: arg
>>        real :: sin
>>      end function sin
>>    end interface
>> end module
>>
>> $ ./xgcc -B. -Ofast -c ~/Programming/testcases/module.f90
>>
>> $ cat ~/Programming/testcases/use.f90
>> program test_overloaded_intrinsic
>>    use vector_math
>>    real(4) :: x(3200), y(3200), z(3200)
>>
>>    ! this should be using simd clone
>>    y = sin(x)
>>    print *, y
>>
>>    ! this not
>>    z = cos(x)
>>    print *, z
>>
>>    z = sin (z)
>>    print *, z
>> end
>>
>> $ ./xgcc -B. -Ofast -c ~/Programming/testcases/use.f90
>> /home/marxin/Programming/testcases/use.f90:6:10:
>>
>>      6 |   y = sin(x)
>>        |          1
>> Error: Rank mismatch in argument ‘arg’ at (1) (scalar and rank-1)
>> /home/marxin/Programming/testcases/use.f90:13:11:
>>
>>     13 |   z = sin (z)
>>        |           1
>> Error: Rank mismatch in argument ‘arg’ at (1) (scalar and rank-1)
>
> What is happening here is that you define an EXTERNAL function "sin" which, according to your declaration [ I left out the GCC attribute ]:
>
>>      function sin(arg)
>>        real, intent(in) :: arg
>>        real :: sin
>
> is a real function of a scalar argument returning a scalar result.
>
> However, in using it, you pass it 32000 element arrays of reals (you don't need, and should omit, the (4) on the real declaration).
>
> This works for the INTRINSIC functions "sin", "cos", etc., because the Fortran language declares them to be ELEMENTAL.
I see!

>
> This means that, while you can pass them a scalar argument and get a scalar result, you can also pass them a rank-N array and get a rank-N array result OF THE SAME SHAPE.
>
> I wonder if it works to change the declaration to:
>
>>      elemental real function sin(arg)
>>        real, intent(in) :: arg
>>        real :: sin
>
> which declares a user-defined, EXTERNAL, ELEMENTAL function called "sin".
I can confirm that adding ELEMENTAL removes the compilation error.

Now I slightly adjusted the 0001-Support-simd-attribute-propagation-for-a-vector_math.patch patch:
- I do not math match module by name
- I mark simd flag in mio_symbol, which is the place where a module symbol is created.

Now I'm able to add 'use vector_math' directive to my test:

module vector_math
  interface
    elemental function sin(arg)
      !GCC$ attributes simd_notinbranch :: sin
      real, intent(in) :: arg
      real :: sin
    end function sin
  end interface
end module

program test_overloaded_intrinsic
  use vector_math
  real :: x(3200), y(3200), z(3200)

  ! this should be using simd clone
  y = sin(x)
  print *, y

  ! this not
  z = cos(x)
  print *, z

  z = sin (z)
  print *, z
end

However, now I need significant hacking in resolve.c in order to persuade Fortran FE
that my "sin" function (being external module function)
can really be seen as intrinsic (please see 0002-* patch).
Any ideas how to make the resolution working without hacking?

Thank you,
Martin

>
> Hope this helps,
>


0002-Bend-symbol-resolution-in-fortran.patch (1K) Download Attachment
0001-Support-simd-attribute-propagation-for-a-vector_math.patch (6K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH][RFC]Overloading intrinsics

Thomas Koenig-6
Hi Martin,

> module vector_math
>    interface
>      elemental function sin(arg)
>        !GCC$ attributes simd_notinbranch :: sin
>        real, intent(in) :: arg
>        real :: sin
>      end function sin
>    end interface
> end module

I'm glad that this project we discussed at the GNU Cauldron is
moving forward!

Regarding the syntax: I am not sure that using an external function
and then trying to coerce it to an intrinsic is something that is
easily or cleanly done (as you yourself noted).

Would it be possible to use something like

module x
   !GCC$ attributes simd_notinbranch, real(4) :: sin
   !GCC$ attributes simd_notinbranch, real(8) :: sin
end module x

Attribute parsing might have to be extended a little, but
this would create one clear point where to create the
specific version of the library routine.

What do you think?

Regards

        Thomas
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH][RFC]Overloading intrinsics

Toon Moene-3
On 11/01/2018 08:40 PM, Thomas Koenig wrote:

> Would it be possible to use something like
>
> module x
>    !GCC$ attributes simd_notinbranch, real(4) :: sin
>    !GCC$ attributes simd_notinbranch, real(8) :: sin
> end module x
>
> Attribute parsing might have to be extended a little, but
> this would create one clear point where to create the
> specific version of the library routine.

Wouldn't it be much simpler to simply add the attribute *in the Front
End* while generating the call to the INTRINSIC sin ?

Or is there something I miss here ...

--
Toon Moene - e-mail: [hidden email] - phone: +31 346 214290
Saturnushof 14, 3738 XG  Maartensdijk, The Netherlands
At home: http://moene.org/~toon/; weather: http://moene.org/~hirlam/
Progress of GNU Fortran: http://gcc.gnu.org/wiki/GFortran#news
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH][RFC]Overloading intrinsics

Martin Liška-2
In reply to this post by Thomas Koenig-6
On 11/1/18 8:40 PM, Thomas Koenig wrote:

> Hi Martin,
>
>> module vector_math
>>    interface
>>      elemental function sin(arg)
>>        !GCC$ attributes simd_notinbranch :: sin
>>        real, intent(in) :: arg
>>        real :: sin
>>      end function sin
>>    end interface
>> end module
>
> I'm glad that this project we discussed at the GNU Cauldron is
> moving forward!

Hello.

Agree with that. So far I've been provided very nice guidance and
I hope we can get it into GCC 9.1.

>
> Regarding the syntax: I am not sure that using an external function
> and then trying to coerce it to an intrinsic is something that is
> easily or cleanly done (as you yourself noted).
>
> Would it be possible to use something like
>
> module x
>    !GCC$ attributes simd_notinbranch, real(4) :: sin
>    !GCC$ attributes simd_notinbranch, real(8) :: sin
> end module x
>
> Attribute parsing might have to be extended a little, but
> this would create one clear point where to create the
> specific version of the library routine.
>
> What do you think?

Sounds reasonable for me, I can play with the idea tomorrow.

Thank you,
Martin

>
> Regards
>
>      Thomas

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH][RFC]Overloading intrinsics

Martin Liška-2
In reply to this post by Toon Moene-3
On 11/1/18 9:45 PM, Toon Moene wrote:

> On 11/01/2018 08:40 PM, Thomas Koenig wrote:
>
>> Would it be possible to use something like
>>
>> module x
>>    !GCC$ attributes simd_notinbranch, real(4) :: sin
>>    !GCC$ attributes simd_notinbranch, real(8) :: sin
>> end module x
>>
>> Attribute parsing might have to be extended a little, but
>> this would create one clear point where to create the
>> specific version of the library routine.
>
> Wouldn't it be much simpler to simply add the attribute *in the Front End* while generating the call to the INTRINSIC sin ?
>
> Or is there something I miss here ...
>

Hi.

Can you please explain that more?

Martin
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH][RFC]Overloading intrinsics

Thomas Koenig-6
In reply to this post by Toon Moene-3
Hi Toon,

> Wouldn't it be much simpler to simply add the attribute *in the Front
> End* while generating the call to the INTRINSIC sin ?

The problem is that it is not clear, when building the compiler,
if the target system supplies the vectorized version of the intrinsics,
as modern glibc does, but there are people using other libraries
or older versions.

So, the idea is that glibc supplies a configuration file (we can't
really use a header file, like we can in C) which is read in on
compiler startup.  And it would be easiest to make this
some sort of module, consisting of Fortran code.

Regards

        Thomas
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH][RFC]Overloading intrinsics

Richard Biener-2
In reply to this post by Thomas Koenig-6
On Thu, Nov 1, 2018 at 8:40 PM Thomas Koenig <[hidden email]> wrote:

>
> Hi Martin,
>
> > module vector_math
> >    interface
> >      elemental function sin(arg)
> >        !GCC$ attributes simd_notinbranch :: sin
> >        real, intent(in) :: arg
> >        real :: sin
> >      end function sin
> >    end interface
> > end module
>
> I'm glad that this project we discussed at the GNU Cauldron is
> moving forward!
>
> Regarding the syntax: I am not sure that using an external function
> and then trying to coerce it to an intrinsic is something that is
> easily or cleanly done (as you yourself noted).
>
> Would it be possible to use something like
>
> module x
>    !GCC$ attributes simd_notinbranch, real(4) :: sin
>    !GCC$ attributes simd_notinbranch, real(8) :: sin
> end module x

That might very well work better indeed.  Are there any
math library routines that are _not_ intrinsics?  Are all
builtins we initialize through mathbuiltins.def also
Fortran intrinsics?  The important implementation detail
is that we need to amend those builtin declarations via
the module - so one of my thoughts (for future improvement...)
would be to re-organize the mathbuiltins.def thing more
like an intrinsic module that is unconditionally USEd.  Of
course if there's no way to "declare" an intrinsic in fortran
syntax that becomes somewhat difficult.

> Attribute parsing might have to be extended a little, but
> this would create one clear point where to create the
> specific version of the library routine.
>
> What do you think?
>
> Regards
>
>         Thomas
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH][RFC]Overloading intrinsics

Thomas Koenig-6
Am 02.11.18 um 09:18 schrieb Richard Biener:

> On Thu, Nov 1, 2018 at 8:40 PM Thomas Koenig <[hidden email]> wrote:
>>
>> Hi Martin,
>>
>>> module vector_math
>>>     interface
>>>       elemental function sin(arg)
>>>         !GCC$ attributes simd_notinbranch :: sin
>>>         real, intent(in) :: arg
>>>         real :: sin
>>>       end function sin
>>>     end interface
>>> end module
>>
>> I'm glad that this project we discussed at the GNU Cauldron is
>> moving forward!
>>
>> Regarding the syntax: I am not sure that using an external function
>> and then trying to coerce it to an intrinsic is something that is
>> easily or cleanly done (as you yourself noted).
>>
>> Would it be possible to use something like
>>
>> module x
>>     !GCC$ attributes simd_notinbranch, real(4) :: sin
>>     !GCC$ attributes simd_notinbranch, real(8) :: sin
>> end module x
>
> That might very well work better indeed.

Mabe it would not even need a module - just having encountered
the attributes line could be enough to modify the declaration.

> Are there any
> math library routines that are _not_ intrinsics?

If you mean glibc math functions, there are a few missing -
Fortran does not have cbrt, copysign and exp2, just to mention the
first few that strike me reading the list in alphabetical order.

> Are all
> builtins we initialize through mathbuiltins.def also
> Fortran intrinsics?

You have to be a bit careful here about generic functions (which many
of the intrinsics are). For example, in Fortran, SIN is a generic
function which can take different argument types.  This is then
mapped to the specific function, which may be something like
__builtin_sinf.

> The important implementation detail
> is that we need to amend those builtin declarations via
> the module - so one of my thoughts (for future improvement...)
> would be to re-organize the mathbuiltins.def thing more
> like an intrinsic module that is unconditionally USEd.  Of
> course if there's no way to "declare" an intrinsic in fortran
> syntax that becomes somewhat difficult.

I'm not sure we really need a module. Just modifying the
declarations (changing whatever generates the declaration
of __builtin_sinf to use something else) directly might
be enough.

Actually, you can affirm that something is an intrinsic
function, via the INTRINSIC statement or attribute.
You can't do that twice, though, but something like

intrinsic :: sin
!GCC$ attributes simd_notinbranch, real(4) :: sin
!GCC$ attributes simd_notinbranch, real(8) :: sin

would be legal.

(The intended use of INTRINSIC is something else:
A compiler can provide additional intrinsics, more than
what the languages specifies. This ist mostly harmless because
a user can still use the name for his own variables or
procedures.  However, if you use these extensions, it
is sometimes a good idea to specify them as INTRINSIC,
so that if you try to compile the code with another
compiler, you get at least a clean error message).

Regards

        Thomas
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH][RFC]Overloading intrinsics

Richard Biener-2
On Fri, Nov 2, 2018 at 8:21 PM Thomas Koenig <[hidden email]> wrote:

>
> Am 02.11.18 um 09:18 schrieb Richard Biener:
> > On Thu, Nov 1, 2018 at 8:40 PM Thomas Koenig <[hidden email]> wrote:
> >>
> >> Hi Martin,
> >>
> >>> module vector_math
> >>>     interface
> >>>       elemental function sin(arg)
> >>>         !GCC$ attributes simd_notinbranch :: sin
> >>>         real, intent(in) :: arg
> >>>         real :: sin
> >>>       end function sin
> >>>     end interface
> >>> end module
> >>
> >> I'm glad that this project we discussed at the GNU Cauldron is
> >> moving forward!
> >>
> >> Regarding the syntax: I am not sure that using an external function
> >> and then trying to coerce it to an intrinsic is something that is
> >> easily or cleanly done (as you yourself noted).
> >>
> >> Would it be possible to use something like
> >>
> >> module x
> >>     !GCC$ attributes simd_notinbranch, real(4) :: sin
> >>     !GCC$ attributes simd_notinbranch, real(8) :: sin
> >> end module x
> >
> > That might very well work better indeed.
>
> Mabe it would not even need a module - just having encountered
> the attributes line could be enough to modify the declaration.
>
> > Are there any
> > math library routines that are _not_ intrinsics?
>
> If you mean glibc math functions, there are a few missing -
> Fortran does not have cbrt, copysign and exp2, just to mention the
> first few that strike me reading the list in alphabetical order.
>
> > Are all
> > builtins we initialize through mathbuiltins.def also
> > Fortran intrinsics?
>
> You have to be a bit careful here about generic functions (which many
> of the intrinsics are). For example, in Fortran, SIN is a generic
> function which can take different argument types.  This is then
> mapped to the specific function, which may be something like
> __builtin_sinf.
>
> > The important implementation detail
> > is that we need to amend those builtin declarations via
> > the module - so one of my thoughts (for future improvement...)
> > would be to re-organize the mathbuiltins.def thing more
> > like an intrinsic module that is unconditionally USEd.  Of
> > course if there's no way to "declare" an intrinsic in fortran
> > syntax that becomes somewhat difficult.
>
> I'm not sure we really need a module. Just modifying the
> declarations (changing whatever generates the declaration
> of __builtin_sinf to use something else) directly might
> be enough.

Hmm, OK.  So of course I originally thought of doing
an "include file" but a module looked more "modern"...

So if we'd instead do sth like the C -include command-line
option and have glibc just produce a textual file with
!GCC$ attributes lines then would that work when being
pre-"included" to each fortran source?  That would even
solve the issue of having multiple .mod variants for
several GCC versions...

> Actually, you can affirm that something is an intrinsic
> function, via the INTRINSIC statement or attribute.
> You can't do that twice, though, but something like
>
> intrinsic :: sin
> !GCC$ attributes simd_notinbranch, real(4) :: sin
> !GCC$ attributes simd_notinbranch, real(8) :: sin
>
> would be legal.
>
> (The intended use of INTRINSIC is something else:
> A compiler can provide additional intrinsics, more than
> what the languages specifies. This ist mostly harmless because
> a user can still use the name for his own variables or
> procedures.  However, if you use these extensions, it
> is sometimes a good idea to specify them as INTRINSIC,
> so that if you try to compile the code with another
> compiler, you get at least a clean error message).
>
> Regards
>
>         Thomas
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH][RFC]Overloading intrinsics

Martin Liška-2
On 11/5/18 11:13 AM, Richard Biener wrote:

> On Fri, Nov 2, 2018 at 8:21 PM Thomas Koenig <[hidden email]> wrote:
>>
>> Am 02.11.18 um 09:18 schrieb Richard Biener:
>>> On Thu, Nov 1, 2018 at 8:40 PM Thomas Koenig <[hidden email]> wrote:
>>>>
>>>> Hi Martin,
>>>>
>>>>> module vector_math
>>>>>     interface
>>>>>       elemental function sin(arg)
>>>>>         !GCC$ attributes simd_notinbranch :: sin
>>>>>         real, intent(in) :: arg
>>>>>         real :: sin
>>>>>       end function sin
>>>>>     end interface
>>>>> end module
>>>>
>>>> I'm glad that this project we discussed at the GNU Cauldron is
>>>> moving forward!
>>>>
>>>> Regarding the syntax: I am not sure that using an external function
>>>> and then trying to coerce it to an intrinsic is something that is
>>>> easily or cleanly done (as you yourself noted).
>>>>
>>>> Would it be possible to use something like
>>>>
>>>> module x
>>>>     !GCC$ attributes simd_notinbranch, real(4) :: sin
>>>>     !GCC$ attributes simd_notinbranch, real(8) :: sin
>>>> end module x
>>>
>>> That might very well work better indeed.
>>
>> Mabe it would not even need a module - just having encountered
>> the attributes line could be enough to modify the declaration.
>>
>>> Are there any
>>> math library routines that are _not_ intrinsics?
>>
>> If you mean glibc math functions, there are a few missing -
>> Fortran does not have cbrt, copysign and exp2, just to mention the
>> first few that strike me reading the list in alphabetical order.
>>
>>> Are all
>>> builtins we initialize through mathbuiltins.def also
>>> Fortran intrinsics?
>>
>> You have to be a bit careful here about generic functions (which many
>> of the intrinsics are). For example, in Fortran, SIN is a generic
>> function which can take different argument types.  This is then
>> mapped to the specific function, which may be something like
>> __builtin_sinf.
>>
>>> The important implementation detail
>>> is that we need to amend those builtin declarations via
>>> the module - so one of my thoughts (for future improvement...)
>>> would be to re-organize the mathbuiltins.def thing more
>>> like an intrinsic module that is unconditionally USEd.  Of
>>> course if there's no way to "declare" an intrinsic in fortran
>>> syntax that becomes somewhat difficult.
>>
>> I'm not sure we really need a module. Just modifying the
>> declarations (changing whatever generates the declaration
>> of __builtin_sinf to use something else) directly might
>> be enough.
>
> Hmm, OK.  So of course I originally thought of doing
> an "include file" but a module looked more "modern"...
>
> So if we'd instead do sth like the C -include command-line
> option and have glibc just produce a textual file with
> !GCC$ attributes lines then would that work when being
> pre-"included" to each fortran source?  That would even
> solve the issue of having multiple .mod variants for
> several GCC versions...
>
>> Actually, you can affirm that something is an intrinsic
>> function, via the INTRINSIC statement or attribute.
>> You can't do that twice, though, but something like
>>
>> intrinsic :: sin
>> !GCC$ attributes simd_notinbranch, real(4) :: sin
>> !GCC$ attributes simd_notinbranch, real(8) :: sin
>>
>> would be legal.
>>
>> (The intended use of INTRINSIC is something else:
>> A compiler can provide additional intrinsics, more than
>> what the languages specifies. This ist mostly harmless because
>> a user can still use the name for his own variables or
>> procedures.  However, if you use these extensions, it
>> is sometimes a good idea to specify them as INTRINSIC,
>> so that if you try to compile the code with another
>> compiler, you get at least a clean error message).
>>
>> Regards
>>
>>         Thomas
Hi.

Thank you all for comments. I'm sending patch that works with following code snippets:

$ cat usage.F90
program test_overloaded_intrinsic
#include "vector-math.f90"

  real :: x(3200), y(3200), z(3200)

  ! this should be using simd clone
  y = sin(x)
  print *, y

  ! this not
  z = cos(x)
  print *, z

  z = sin (z)
  print *, z
end

$ cat vector-math.f90
intrinsic :: sin
!GCC$ attributes simd_notinbranch :: sin

$ ./xgcc -B. -Ofast  -c ~/Programming/testcases/usage.F90  -fdump-tree-optimized=/dev/stdout | grep sin
  vect__3.23_101 = sinf.simdclone.0 (vect__2.22_100);
  vect__9.17_87 = sinf.simdclone.0 (vect__8.16_10);

Now the question is how to add a new argument that will implicitly include additional file.
Should that be added to Fortran pre-processor? Hints welcomed.

Note that I removed the ', real(4)' from attribute definition as there's just single gfc_intrinsic_sym
for sin* functions in Fortran FE. Is it fine?

About the math functions that are not intrinsics. If I see correctly current list of vectorized
math functions is here:
https://sourceware.org/git/?p=glibc.git;a=blob_plain;f=sysdeps/x86/fpu/bits/math-vector.h;hb=HEAD

Martin

0001-Support-simd-attribute-propagation-for-a-vector_math.patch (4K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH][RFC]Overloading intrinsics

Thomas Koenig-6
In reply to this post by Richard Biener-2
Hi Richi,

> So if we'd instead do sth like the C -include command-line
> option and have glibc just produce a textual file with
> !GCC$ attributes lines then would that work when being
> pre-"included" to each fortran source?  That would even
> solve the issue of having multiple .mod variants for
> several GCC versions...

Yes, I think this would work.

We would have to make sure that the attribute lines work before
the first translation unit (so no INTRINSIC statement
can be there).

Regards

        Thomas
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH][RFC]Overloading intrinsics

Thomas Koenig-6
In reply to this post by Martin Liška-2
Hi Martin,

> Thank you all for comments. I'm sending patch that works with following code snippets:
>
> $ cat usage.F90
> program test_overloaded_intrinsic
> #include "vector-math.f90"
>
>    real :: x(3200), y(3200), z(3200)
>
>    ! this should be using simd clone
>    y = sin(x)
>    print *, y
>
>    ! this not
>    z = cos(x)
>    print *, z
>
>    z = sin (z)
>    print *, z
> end

This is looking good, in principle.

A few points:

If we want to add this to the top of each translation unit, the
!GCC$ attributes simd_notinbranch :: sin

work if it is put into the first lines of program code.

> Note that I removed the ', real(4)' from attribute definition as there's just single gfc_intrinsic_sym
> for sin* functions in Fortran FE. Is it fine?

No. The problem is that "sin" is generic and overloaded with different
versions for different real types.

We may have vectorization for real(kind=4) and real(kind=8), but not for
real (kind=16), for example.

So, you could use either the intrinsic name with the precision or (maybe
that is an even better idea) the name of the C function that is
overloaded.

> About the math functions that are not intrinsics. If I see correctly current list of vectorized
> math functions is here:
> https://sourceware.org/git/?p=glibc.git;a=blob_plain;f=sysdeps/x86/fpu/bits/math-vector.h;hb=HEAD

I see sincos and sincosf there. There is no sincos intrinsic in Fortran,
but there could be a lot of value in having a vecorized sincos if
the middle end detects an opportunity for it.

So, putting the attributes on the middle end declarations might actually
be the better way handling this.

Regards

        Thomas

Reply | Threaded
Open this post in threaded view
|

Re: [PATCH][RFC]Overloading intrinsics

Thomas Koenig-6
Am 05.11.18 um 22:47 schrieb Thomas Koenig:
>
> If we want to add this to the top of each translation unit, the
> !GCC$ attributes simd_notinbranch :: sin
>
> work if it is put into the first lines of program code.

Or even more radical:

Could we just add a
-fvectorized-function=sin,cos,sinf,cosf,sincos,sincosf, ...

option and read that from a predefined place via @FILE ?

This could be even more straightforward than implementnig this
as an extension to the Fortran parser.

Regards

        Thomas
123