Using linear (added by the compiler) + explicit lastprivate gives an error.

To quote Jakub from the PR:
"If it is the FE that adds the linear clause, then it
shouldn't when there is explicit lastprivate clause.
This is a new thing in OpenMP 5.0, in 4.5 it was invalid to
make the iterate anything but linear in this case, now
it can be made private or lastprivate."

Actually, the check which permitted this was committed
early during GCC 11 development, but the some updates of
trans-openmp.c were missing.

OK?

Tobias

-----------------
Mentor Graphics (Deutschland) GmbH, Arnulfstraße 201, 80634 München / Germany
Registergericht München HRB 106955, Geschäftsführer: Thomas Heurung, Alexander 
Walter
Fortran: OpenMP - fix simd with (last)private (PR97061)

gcc/fortran/ChangeLog:

	PR fortran/97061
	* trans-openmp.c (gfc_trans_omp_do): Handle simd with (last)private.

gcc/testsuite/ChangeLog:

	PR fortran/97061
	* gfortran.dg/gomp/openmp-simd-6.f90: New test.

 gcc/fortran/trans-openmp.c                       | 37 ++++++++------
 gcc/testsuite/gfortran.dg/gomp/openmp-simd-6.f90 | 62 ++++++++++++++++++++++++
 2 files changed, 85 insertions(+), 14 deletions(-)

diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c
index 9ec0df204ac..378088a9d04 100644
--- a/gcc/fortran/trans-openmp.c
+++ b/gcc/fortran/trans-openmp.c
@@ -4401,20 +4401,29 @@ gfc_trans_omp_do (gfc_code *code, gfc_exec_op op, stmtblock_t *pblock,
       if (clauses)
 	{
 	  gfc_omp_namelist *n = NULL;
-	  if (op != EXEC_OMP_DISTRIBUTE)
-	    for (n = clauses->lists[(op == EXEC_OMP_SIMD && collapse == 1)
-				    ? OMP_LIST_LINEAR : OMP_LIST_LASTPRIVATE];
+	  if (op == EXEC_OMP_SIMD && collapse == 1)
+	    for (n = clauses->lists[OMP_LIST_LINEAR];
 		 n != NULL; n = n->next)
 	      if (code->ext.iterator->var->symtree->n.sym == n->sym)
-		break;
-	  if (n != NULL)
-	    dovar_found = 1;
-	  else if (n == NULL && op != EXEC_OMP_SIMD)
+		{
+		  dovar_found = 3;
+		  break;
+		}
+	  if (n == NULL && op != EXEC_OMP_DISTRIBUTE)
+	    for (n = clauses->lists[OMP_LIST_LASTPRIVATE];
+		 n != NULL; n = n->next)
+	      if (code->ext.iterator->var->symtree->n.sym == n->sym)
+		{
+		  dovar_found = 2;
+		  break;
+		}
+	  if (n == NULL)
 	    for (n = clauses->lists[OMP_LIST_PRIVATE]; n != NULL; n = n->next)
 	      if (code->ext.iterator->var->symtree->n.sym == n->sym)
-		break;
-	  if (n != NULL)
-	    dovar_found++;
+		{
+		  dovar_found = 1;
+		  break;
+		}
 	}
 
       /* Evaluate all the expressions in the iterator.  */
@@ -4512,7 +4521,7 @@ gfc_trans_omp_do (gfc_code *code, gfc_exec_op op, stmtblock_t *pblock,
       if (orig_decls)
 	TREE_VEC_ELT (orig_decls, i) = dovar_decl;
 
-      if (dovar_found == 2
+      if (dovar_found == 3
 	  && op == EXEC_OMP_SIMD
 	  && collapse == 1
 	  && !simple)
@@ -4536,7 +4545,7 @@ gfc_trans_omp_do (gfc_code *code, gfc_exec_op op, stmtblock_t *pblock,
 	      omp_clauses = gfc_trans_add_clause (tmp, omp_clauses);
 	    }
 	  if (!simple)
-	    dovar_found = 2;
+	    dovar_found = 3;
 	}
       else if (!dovar_found && !simple)
 	{
@@ -4544,7 +4553,7 @@ gfc_trans_omp_do (gfc_code *code, gfc_exec_op op, stmtblock_t *pblock,
 	  OMP_CLAUSE_DECL (tmp) = dovar_decl;
 	  omp_clauses = gfc_trans_add_clause (tmp, omp_clauses);
 	}
-      if (dovar_found == 2)
+      if (dovar_found > 1)
 	{
 	  tree c = NULL;
 
@@ -4612,7 +4621,7 @@ gfc_trans_omp_do (gfc_code *code, gfc_exec_op op, stmtblock_t *pblock,
 	}
       if (!simple)
 	{
-	  if (op != EXEC_OMP_SIMD)
+	  if (op != EXEC_OMP_SIMD || dovar_found == 1)
 	    tmp = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE);
 	  else if (collapse == 1)
 	    {
diff --git a/gcc/testsuite/gfortran.dg/gomp/openmp-simd-6.f90 b/gcc/testsuite/gfortran.dg/gomp/openmp-simd-6.f90
new file mode 100644
index 00000000000..361e0dad343
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/openmp-simd-6.f90
@@ -0,0 +1,62 @@
+! { dg-additional-options "-fdump-tree-original" }
+!
+! PR fortran/97061
+
+integer function f3 (a1, b1, u)
+  implicit none
+  integer :: a1, b1, d1
+  integer u(0:1023)
+  !$omp teams distribute parallel do simd default(none) firstprivate (a1, b1) shared(u) lastprivate(d1) 
+  do d1 = a1, b1-1
+      u(d1) = 5
+  end do
+end
+
+subroutine foo(n, m, u)
+  implicit none
+  integer :: hh, ii, jj, n, m
+  integer u(0:1023)
+  !$omp simd private(ii)
+  do ii = n, m
+    u(ii) = 5
+  end do
+  !$omp simd linear(jj:1)
+  do jj = 2, m+n
+    u(jj) = 6
+  end do
+  !$omp simd
+  do hh = 2, m+n
+    u(hh) = 6
+  end do
+end
+
+subroutine bar(n, m, u)
+  implicit none
+  integer :: kkk, lll, ooo, ppp, n, m
+  integer u(:,:)
+  !$omp simd lastprivate(kkk) lastprivate(lll) collapse(2)
+  do kkk = n, m
+    do lll = n, m
+      u(kkk, lll) = 5
+    end do
+  end do
+  !$omp simd private(kkk) private(lll) collapse(2)
+  do ooo = n, m
+    do ppp = n, m
+      u(ooo, ppp) = 5
+    end do
+  end do
+end
+
+
+! { dg-final { scan-tree-dump-times "#pragma omp teams firstprivate\\(a1\\) firstprivate\\(b1\\) shared\\(u\\) default\\(none\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp distribute lastprivate\\(d1\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp parallel firstprivate\\(a1\\) firstprivate\\(b1\\) lastprivate\\(d1\\) shared\\(u\\) default\\(none\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp for nowait" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp simd lastprivate\\(d1\\)" 1 "original" } }
+
+! { dg-final { scan-tree-dump-times "#pragma omp simd private\\(ii\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp simd linear\\(jj:1\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp simd linear\\(hh:1\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp simd lastprivate\\(kkk\\) lastprivate\\(lll\\) collapse\\(2\\)" 1 "original" } }
+! { dg-final { scan-tree-dump-times "#pragma omp simd private\\(kkk\\) private\\(lll\\) collapse\\(2\\)" 1 "original" } }

Reply via email to