From d947a297d224ced389abd7ad74d3519b4a0e8d32 Mon Sep 17 00:00:00 2001
From: Thomas Schwinge <thomas@codesourcery.com>
Date: Thu, 28 Feb 2019 21:58:14 +0100
Subject: [PATCH 2/2] [PR72741] Encode OpenACC 'routine' directive inside
 Fortran module files

	gcc/fortran/
	* gfortran.h (oacc_routine_lop_types): Declare.
	* module.c (MOD_VERSION): Increment
	(oacc_routine_lop): New DECL_MIO_NAME.
	(mio_symbol_attribute): Set the oacc_routine_lop attribute.
	* symbol.c (oacc_routine_lop_types): Define.
	gcc/testsuite/
	* gfortran.dg/goacc/routine-module-1.f90: New file.
	* gfortran.dg/goacc/routine-module-2.f90: Likewise.
	* gfortran.dg/goacc/routine-module-mod-1.f90: Likewise.
---
 gcc/fortran/gfortran.h                        |  1 +
 gcc/fortran/module.c                          |  6 +-
 gcc/fortran/symbol.c                          | 12 +++
 .../gfortran.dg/goacc/routine-module-1.f90    | 47 +++++++++++
 .../gfortran.dg/goacc/routine-module-2.f90    | 31 ++++++++
 .../goacc/routine-module-mod-1.f90            | 79 +++++++++++++++++++
 6 files changed, 175 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gfortran.dg/goacc/routine-module-1.f90
 create mode 100644 gcc/testsuite/gfortran.dg/goacc/routine-module-2.f90
 create mode 100644 gcc/testsuite/gfortran.dg/goacc/routine-module-mod-1.f90

diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 3e0f634c3a8e..0d929d4d0c2c 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -336,6 +336,7 @@ extern const mstring intents[];
 extern const mstring access_types[];
 extern const mstring ifsrc_types[];
 extern const mstring save_status[];
+extern const mstring oacc_routine_lop_types[];
 
 /* Strings for DTIO procedure names.  In symbol.c.  */
 extern const mstring dtio_procs[];
diff --git a/gcc/fortran/module.c b/gcc/fortran/module.c
index 320b30c529ac..ce43997ccf48 100644
--- a/gcc/fortran/module.c
+++ b/gcc/fortran/module.c
@@ -84,7 +84,7 @@ along with GCC; see the file COPYING3.  If not see
 
 /* Don't put any single quote (') in MOD_VERSION, if you want it to be
    recognized.  */
-#define MOD_VERSION "15"
+#define MOD_VERSION "16"
 
 
 /* Structure that describes a position within a module file.  */
@@ -2126,6 +2126,7 @@ DECL_MIO_NAME (ref_type)
 DECL_MIO_NAME (sym_flavor)
 DECL_MIO_NAME (sym_intent)
 DECL_MIO_NAME (inquiry_type)
+DECL_MIO_NAME (oacc_routine_lop)
 #undef DECL_MIO_NAME
 
 /* Symbol attributes are stored in list with the first three elements
@@ -2147,6 +2148,9 @@ mio_symbol_attribute (symbol_attribute *attr)
   attr->proc = MIO_NAME (procedure_type) (attr->proc, procedures);
   attr->if_source = MIO_NAME (ifsrc) (attr->if_source, ifsrc_types);
   attr->save = MIO_NAME (save_state) (attr->save, save_status);
+  attr->oacc_routine_lop
+    = MIO_NAME (oacc_routine_lop) (attr->oacc_routine_lop,
+				   oacc_routine_lop_types);
 
   ext_attr = attr->ext_attr;
   mio_integer ((int *) &ext_attr);
diff --git a/gcc/fortran/symbol.c b/gcc/fortran/symbol.c
index c8a1f842d353..3c3d8cb22f7b 100644
--- a/gcc/fortran/symbol.c
+++ b/gcc/fortran/symbol.c
@@ -96,6 +96,18 @@ const mstring dtio_procs[] =
     minit ("_dtio_unformatted_write", DTIO_WUF),
 };
 
+const mstring oacc_routine_lop_types[] =
+{
+    minit ("OACC_ROUTINE_LOP_NONE", OACC_ROUTINE_LOP_NONE),
+    minit ("OACC_ROUTINE_LOP_GANG", OACC_ROUTINE_LOP_GANG),
+    minit ("OACC_ROUTINE_LOP_WORKER", OACC_ROUTINE_LOP_WORKER),
+    minit ("OACC_ROUTINE_LOP_VECTOR", OACC_ROUTINE_LOP_VECTOR),
+    minit ("OACC_ROUTINE_LOP_SEQ", OACC_ROUTINE_LOP_SEQ),
+    /* 'OACC_ROUTINE_LOP_ERROR' intentionally ommitted here; it's only unsed
+       internally.  */
+    minit (NULL, -1)
+};
+
 /* This is to make sure the backend generates setup code in the correct
    order.  */
 
diff --git a/gcc/testsuite/gfortran.dg/goacc/routine-module-1.f90 b/gcc/testsuite/gfortran.dg/goacc/routine-module-1.f90
new file mode 100644
index 000000000000..4e81f11fec86
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/goacc/routine-module-1.f90
@@ -0,0 +1,47 @@
+! Valid use of routines defined inside a Fortran module.
+
+! { dg-compile-aux-modules "routine-module-mod-1.f90" }
+! { dg-additional-options "-fopt-info-optimized-omp" }
+
+program main
+  use routine_module_mod_1
+  implicit none
+
+  integer :: i
+
+  call pl_1
+
+  !$acc parallel loop seq ! { dg-message "optimized: assigned OpenACC seq loop parallelism" }
+  do i = 1, 10
+     call s_1 ! { dg-message "optimized: assigned OpenACC seq loop parallelism" }
+     call s_2 ! { dg-message "optimized: assigned OpenACC seq loop parallelism" }
+     call g_1 ! { dg-message "optimized: assigned OpenACC gang worker vector loop parallelism" }
+     call w_1 ! { dg-message "optimized: assigned OpenACC worker vector loop parallelism" }
+     call v_1 ! { dg-message "optimized: assigned OpenACC vector loop parallelism" }
+  end do
+  !$acc end parallel loop
+
+  !$acc parallel loop gang ! { dg-message "optimized: assigned OpenACC gang loop parallelism" }
+  do i = 1, 10
+     call s_1 ! { dg-message "optimized: assigned OpenACC seq loop parallelism" }
+     call s_2 ! { dg-message "optimized: assigned OpenACC seq loop parallelism" }
+     call w_1 ! { dg-message "optimized: assigned OpenACC worker vector loop parallelism" }
+     call v_1 ! { dg-message "optimized: assigned OpenACC vector loop parallelism" }
+  end do
+  !$acc end parallel loop
+
+  !$acc parallel loop worker ! { dg-message "optimized: assigned OpenACC worker loop parallelism" }
+  do i = 1, 10
+     call s_1 ! { dg-message "optimized: assigned OpenACC seq loop parallelism" }
+     call s_2 ! { dg-message "optimized: assigned OpenACC seq loop parallelism" }
+     call v_1 ! { dg-message "optimized: assigned OpenACC vector loop parallelism" }
+  end do
+  !$acc end parallel loop
+
+  !$acc parallel loop vector ! { dg-message "optimized: assigned OpenACC vector loop parallelism" }
+  do i = 1, 10
+     call s_1 ! { dg-message "optimized: assigned OpenACC seq loop parallelism" }
+     call s_2 ! { dg-message "optimized: assigned OpenACC seq loop parallelism" }
+  end do
+  !$acc end parallel loop
+end program main
diff --git a/gcc/testsuite/gfortran.dg/goacc/routine-module-2.f90 b/gcc/testsuite/gfortran.dg/goacc/routine-module-2.f90
new file mode 100644
index 000000000000..eae0807643c9
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/goacc/routine-module-2.f90
@@ -0,0 +1,31 @@
+! Invalid use of routines defined inside a Fortran module.
+
+! { dg-compile-aux-modules "routine-module-mod-1.f90" }
+
+program main
+  use routine_module_mod_1
+  implicit none
+
+  integer :: i
+
+  !$acc parallel loop gang
+  do i = 1, 10
+     call g_1 ! { dg-error "routine call uses same OpenACC parallelism as containing loop" }
+  end do
+  !$acc end parallel loop
+
+  !$acc parallel loop worker
+  do i = 1, 10
+     call g_1 ! { dg-error "routine call uses same OpenACC parallelism as containing loop" }
+     call w_1 ! { dg-error "routine call uses same OpenACC parallelism as containing loop" }
+  end do
+  !$acc end parallel loop
+
+  !$acc parallel loop vector
+  do i = 1, 10
+     call g_1 ! { dg-error "routine call uses same OpenACC parallelism as containing loop" }
+     call w_1 ! { dg-error "routine call uses same OpenACC parallelism as containing loop" }
+     call v_1 ! { dg-error "routine call uses same OpenACC parallelism as containing loop" }
+  end do
+  !$acc end parallel loop
+end program main
diff --git a/gcc/testsuite/gfortran.dg/goacc/routine-module-mod-1.f90 b/gcc/testsuite/gfortran.dg/goacc/routine-module-mod-1.f90
new file mode 100644
index 000000000000..8f73db41d523
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/goacc/routine-module-mod-1.f90
@@ -0,0 +1,79 @@
+! OpenACC 'routine' directives inside a Fortran module.
+
+! { dg-additional-options "-fopt-info-optimized-omp" }
+
+module routine_module_mod_1
+contains
+  subroutine s_1
+    implicit none
+    !$acc routine
+
+    integer :: i
+
+    !$acc loop ! { dg-message "optimized: assigned OpenACC seq loop parallelism" }
+    ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+    do i = 1, 3
+    end do
+  end subroutine s_1
+
+  subroutine s_2
+    implicit none
+    !$acc routine seq
+
+    integer :: i
+
+    !$acc loop ! { dg-message "optimized: assigned OpenACC seq loop parallelism" }
+    ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+    do i = 1, 3
+    end do
+  end subroutine s_2
+
+  subroutine v_1
+    implicit none
+    !$acc routine vector
+
+    integer :: i
+
+    !$acc loop ! { dg-message "optimized: assigned OpenACC vector loop parallelism" }
+    do i = 1, 3
+    end do
+  end subroutine v_1
+
+  subroutine w_1
+    implicit none
+    !$acc routine worker
+
+    integer :: i
+
+    !$acc loop ! { dg-message "optimized: assigned OpenACC worker vector loop parallelism" }
+    do i = 1, 3
+    end do
+  end subroutine w_1
+
+  subroutine g_1
+    implicit none
+    !$acc routine gang
+
+    integer :: i
+
+    !$acc loop ! { dg-message "optimized: assigned OpenACC gang vector loop parallelism" }
+    do i = 1, 3
+    end do
+  end subroutine g_1
+
+  subroutine pl_1
+    implicit none
+
+    integer :: i
+
+    !$acc parallel loop ! { dg-message "optimized: assigned OpenACC seq loop parallelism" }
+    ! { dg-warning "insufficient partitioning available to parallelize loop" "" { target *-*-* } .-1 }
+    do i = 1, 3
+       call s_1 ! { dg-message "optimized: assigned OpenACC seq loop parallelism" }
+       call s_2 ! { dg-message "optimized: assigned OpenACC seq loop parallelism" }
+       call g_1 ! { dg-message "optimized: assigned OpenACC gang worker vector loop parallelism" }
+       call w_1 ! { dg-message "optimized: assigned OpenACC worker vector loop parallelism" }
+       call v_1 ! { dg-message "optimized: assigned OpenACC vector loop parallelism" }
+    end do
+  end subroutine pl_1
+end module routine_module_mod_1
-- 
2.17.1

