[2/2] Fortran: Add attribute flatten

Message ID 20221110102031.1366016-3-aldot@gcc.gnu.org
State New
Headers
Series Fortran: Add attribute flatten |

Commit Message

Bernhard Reutner-Fischer Nov. 10, 2022, 10:20 a.m. UTC
  Bootstrapped and regtested cleanly on x86_unknown-linux.
The document bits will be rewritten for rst.
Ok for trunk if the prerequisite target_clones patch is approved?

gcc/fortran/ChangeLog:

	* decl.cc (gfc_match_gcc_attributes): Handle flatten.
	* f95-lang.cc (gfc_attribute_table): Add flatten.
	* gfortran.texi: Document attribute flatten.

gcc/testsuite/ChangeLog:

	* gfortran.dg/attr_flatten-1.f90: New test.
---
 gcc/fortran/decl.cc                          |  8 +++-
 gcc/fortran/f95-lang.cc                      |  2 +
 gcc/fortran/gfortran.texi                    |  8 ++++
 gcc/testsuite/gfortran.dg/attr_flatten-1.f90 | 41 ++++++++++++++++++++
 4 files changed, 57 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gfortran.dg/attr_flatten-1.f90
  

Comments

Mikael Morin Nov. 21, 2022, 11:24 a.m. UTC | #1
Le 10/11/2022 à 11:20, Bernhard Reutner-Fischer via Fortran a écrit :
> Bootstrapped and regtested cleanly on x86_unknown-linux.
> The document bits will be rewritten for rst.
> Ok for trunk if the prerequisite target_clones patch is approved?
> 
> gcc/fortran/ChangeLog:
> 
> 	* decl.cc (gfc_match_gcc_attributes): Handle flatten.
> 	* f95-lang.cc (gfc_attribute_table): Add flatten.
> 	* gfortran.texi: Document attribute flatten.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* gfortran.dg/attr_flatten-1.f90: New test.
> ---
>   gcc/fortran/decl.cc                          |  8 +++-
>   gcc/fortran/f95-lang.cc                      |  2 +
>   gcc/fortran/gfortran.texi                    |  8 ++++
>   gcc/testsuite/gfortran.dg/attr_flatten-1.f90 | 41 ++++++++++++++++++++
>   4 files changed, 57 insertions(+), 2 deletions(-)
>   create mode 100644 gcc/testsuite/gfortran.dg/attr_flatten-1.f90
> 
> diff --git a/gcc/fortran/decl.cc b/gcc/fortran/decl.cc
> index d312d4812b6..3d210c26eb5 100644
> --- a/gcc/fortran/decl.cc
> +++ b/gcc/fortran/decl.cc
(...)
> @@ -11849,7 +11850,9 @@ gfc_match_gcc_attributes (void)
>   	if (strcmp (name, ext_attr_list[id].name) == 0)
>   	  break;
>   
> -      if (id == EXT_ATTR_LAST)
> +      if (strcmp (name, "flatten") == 0)
> +	known_attr0args = true; /* Handled below.  We do not need a bit.  */

I don't see the point to have all the attributes needing a bit except 
one that doesn't but needs a specific handling.
What does it look like without the 1/2 patch and if one bit is also used 
for flatten, like the other attributes?

> +      else if (id == EXT_ATTR_LAST)
>   	{
>   	  gfc_error ("Unknown attribute in !GCC$ ATTRIBUTES statement at %C");
>   	  return MATCH_ERROR;

> diff --git a/gcc/fortran/gfortran.texi b/gcc/fortran/gfortran.texi
> index 06e4c8c00a1..be650f28b62 100644
> --- a/gcc/fortran/gfortran.texi
> +++ b/gcc/fortran/gfortran.texi
> @@ -3280,6 +3280,14 @@ contains
>   end module mymod
>   @end smallexample
>   
> +@node flatten
> +
> +Procedures annotated with the @code{flatten} attribute have their
> +callees inlined, if possible.
I'm not a native speaker, but I find this sentence confusing.
The words of the gcc manual you are refering to seem more clear: "every 
call inside the function is inlined, if possible".

> +Please refer to
> +@ref{Top,,Common Function Attributes,gcc,Using the GNU Compiler Collection (GCC)}
> +for details about the respective attribute.
> +
>   The attributes are specified using the syntax
>   
>   @code{!GCC$ ATTRIBUTES} @var{attribute-list} @code{::} @var{variable-list}
  
Bernhard Reutner-Fischer Nov. 21, 2022, 8:13 p.m. UTC | #2
On Mon, 21 Nov 2022 12:24:11 +0100
Mikael Morin <morin-mikael@orange.fr> wrote:

> > --- a/gcc/fortran/decl.cc
> > +++ b/gcc/fortran/decl.cc  
> (...)
> > @@ -11849,7 +11850,9 @@ gfc_match_gcc_attributes (void)
> >   	if (strcmp (name, ext_attr_list[id].name) == 0)
> >   	  break;
> >   
> > -      if (id == EXT_ATTR_LAST)
> > +      if (strcmp (name, "flatten") == 0)
> > +	known_attr0args = true; /* Handled below.  We do not need a bit.  */  
> 
> I don't see the point to have all the attributes needing a bit except 
> one that doesn't but needs a specific handling.
> What does it look like without the 1/2 patch and if one bit is also used 
> for flatten, like the other attributes?

I've changed target_clones not to use a bit locally because it's not
needed. From my understanding, we only need the bits for attributes
that change the calling convention or the caller(at least so far, but
that does make sense to me). Remember that we store these bits in the
module. Presumably because we have to make sure that a program/module
uses the correct calling convention for a module function annotated
with such an attribute (think cdecl, stdcall, fastcall, dllimport,
dllexport, or the non-implemented regparm, sseregparm) or for
attributes that otherwise influence the callers or callees (like
deprecated or no_arg_check).

Attributes like target_clones or flatten or (probably) optimize etc, do
not influence the callees, so we really do not need to store them in
the module.

Can you think of a reason to store them nevertheless?

> > +      else if (id == EXT_ATTR_LAST)
> >   	{
> >   	  gfc_error ("Unknown attribute in !GCC$ ATTRIBUTES statement at %C");
> >   	  return MATCH_ERROR;  
> 
> > diff --git a/gcc/fortran/gfortran.texi b/gcc/fortran/gfortran.texi
> > index 06e4c8c00a1..be650f28b62 100644
> > --- a/gcc/fortran/gfortran.texi
> > +++ b/gcc/fortran/gfortran.texi
> > @@ -3280,6 +3280,14 @@ contains
> >   end module mymod
> >   @end smallexample
> >   
> > +@node flatten
> > +
> > +Procedures annotated with the @code{flatten} attribute have their
> > +callees inlined, if possible.  
> I'm not a native speaker, but I find this sentence confusing.
> The words of the gcc manual you are refering to seem more clear: "every 
> call inside the function is inlined, if possible".

Me neither and it was a bit too brief. I've changed this to:
Every call inside a procedure annotated with the @code{flatten} attribute
is inlined, if possible.  Please refer to
@ref{Top,,Common Function Attributes,gcc,Using the GNU Compiler Collection (GCC>
for details about the respective attribute.

Is that better?

That said, i think this whole attribute section in the manual is not
structured too well. I'd prefer to have a list of attributes like in the
"Common Function Attributes" section in the extend.texi.
Maybe it would be better to just start a new list of attributes at the
end of the current @subsection ATTRIBUTES directive, a subsubsection
with "Other attributes" and just itemize the new ones? We'd point
people to the Top docs once for further details and then just briefly
list the attributes we support. Would that be acceptable?

Many thanks for your comments!

> 
> > +Please refer to
> > +@ref{Top,,Common Function Attributes,gcc,Using the GNU Compiler Collection (GCC)}
> > +for details about the respective attribute.
> > +
> >   The attributes are specified using the syntax
> >   
> >   @code{!GCC$ ATTRIBUTES} @var{attribute-list} @code{::} @var{variable-list}  
>
  

Patch

diff --git a/gcc/fortran/decl.cc b/gcc/fortran/decl.cc
index d312d4812b6..3d210c26eb5 100644
--- a/gcc/fortran/decl.cc
+++ b/gcc/fortran/decl.cc
@@ -11841,6 +11841,7 @@  gfc_match_gcc_attributes (void)
   for(;;)
     {
       char ch;
+      bool known_attr0args = false;
 
       if (gfc_match_name (name) != MATCH_YES)
 	return MATCH_ERROR;
@@ -11849,7 +11850,9 @@  gfc_match_gcc_attributes (void)
 	if (strcmp (name, ext_attr_list[id].name) == 0)
 	  break;
 
-      if (id == EXT_ATTR_LAST)
+      if (strcmp (name, "flatten") == 0)
+	known_attr0args = true; /* Handled below.  We do not need a bit.  */
+      else if (id == EXT_ATTR_LAST)
 	{
 	  gfc_error ("Unknown attribute in !GCC$ ATTRIBUTES statement at %C");
 	  return MATCH_ERROR;
@@ -11864,7 +11867,8 @@  gfc_match_gcc_attributes (void)
 	       || id == EXT_ATTR_DLLEXPORT
 	       || id == EXT_ATTR_CDECL
 	       || id == EXT_ATTR_STDCALL
-	       || id == EXT_ATTR_FASTCALL)
+	       || id == EXT_ATTR_FASTCALL
+	       || known_attr0args)
 	attr.ext_attr_args
 	  = chainon (attr.ext_attr_args,
 		     build_tree_list (get_identifier (name), NULL_TREE));
diff --git a/gcc/fortran/f95-lang.cc b/gcc/fortran/f95-lang.cc
index 7154568aec5..ddb5b686cf6 100644
--- a/gcc/fortran/f95-lang.cc
+++ b/gcc/fortran/f95-lang.cc
@@ -101,6 +101,8 @@  static const struct attribute_spec gfc_attribute_table[] =
 			      gfc_handle_omp_declare_target_attribute, NULL },
   { "target_clones",          1, -1, true, false, false, false,
 			      gfc_handle_omp_declare_target_attribute, NULL },
+  { "flatten",                0, 0, true,  false, false, false,
+			      gfc_handle_omp_declare_target_attribute, NULL },
   { NULL,		  0, 0, false, false, false, false, NULL, NULL }
 };
 
diff --git a/gcc/fortran/gfortran.texi b/gcc/fortran/gfortran.texi
index 06e4c8c00a1..be650f28b62 100644
--- a/gcc/fortran/gfortran.texi
+++ b/gcc/fortran/gfortran.texi
@@ -3280,6 +3280,14 @@  contains
 end module mymod
 @end smallexample
 
+@node flatten
+
+Procedures annotated with the @code{flatten} attribute have their
+callees inlined, if possible.
+Please refer to
+@ref{Top,,Common Function Attributes,gcc,Using the GNU Compiler Collection (GCC)}
+for details about the respective attribute.
+
 The attributes are specified using the syntax
 
 @code{!GCC$ ATTRIBUTES} @var{attribute-list} @code{::} @var{variable-list}
diff --git a/gcc/testsuite/gfortran.dg/attr_flatten-1.f90 b/gcc/testsuite/gfortran.dg/attr_flatten-1.f90
new file mode 100644
index 00000000000..0b72f1ba17c
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/attr_flatten-1.f90
@@ -0,0 +1,41 @@ 
+! { dg-do compile }
+! { dg-additional-options "-fdump-tree-optimized" }
+! Test __attribute__((flatten))
+!
+module attr_flttn_1_a
+  implicit none
+contains
+  subroutine sub1(i)
+    integer, intent(in) :: i
+    integer :: n
+    do n = 1, i
+      print *, "marker1 ", i, i+n;
+    enddo
+  end
+  subroutine sub2(i)
+    integer, intent(in) :: i
+    integer :: n
+    do n = 1, i
+      print *, "marker2 ", i, i*i-n;
+    enddo
+  end
+end module
+module attr_flttn_1_b
+  use attr_flttn_1_a
+contains
+  subroutine sub3
+!GCC$ ATTRIBUTES flatten :: sub3
+    print *, "marker3 "
+    call sub2(4711)
+    call sub1(42)
+  end
+end module
+! Without the attribute flatten we would have 1 character write for each marker.
+! That would be 3 _gfortran_transfer_character_write.*marker
+! With the attribute, we have one for each sub plus marker1 and marker2
+! which were inlined into sub3.
+! So this gives 5 _gfortran_transfer_character_write.*marker
+! and there should be no calls to sub1 (); nor sub2 ();
+! { dg-final { scan-tree-dump-times { _gfortran_transfer_character_write .*?marker} 5 "optimized" } }
+! { dg-final { scan-tree-dump-not { sub1 \([^\)][^\)]*\);} "optimized" } }
+! { dg-final { scan-tree-dump-not { sub2 \([^\)][^\)]*\);} "optimized" } }