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
@@ -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" } }
-- 
2.38.1

Reply via email to