[Patch] Fortran/OpenMP: Fix clause splitting for target/parallel/teams [PR99928]

2021-06-07 Thread Tobias Burnus

This removes the remaining xfails in gfortran.dg/gomp/pr99928-*.f90
and should in theory fix all splitting issues.

I see some differences for 'parallel do simd' with regards to attaching
lastprivate to 'for' vs. 'parallel' There are probably more.
(I hope none of them is relevant.)
There are also a couple of FIXME regarding 'parallel for' and the
clause attachment (in both the C/C++ and Fortran testcase.)

Still missing for C/C++ parity is the support for reduction with
array slides (→ pr88828-{9,10}.c).

I hope that I got the splitting correct.

Tobias

-
Mentor Graphics (Deutschland) GmbH, Arnulfstrasse 201, 80634 München 
Registergericht München HRB 106955, Geschäftsführer: Thomas Heurung, Frank 
Thürauf
Fortran/OpenMP: Fix clause splitting for target/parallel/teams [PR99928]

	PR middle-end/99928

gcc/fortran/ChangeLog:
 
	* trans-openmp.c (gfc_add_clause_implicitly,
	(gfc_split_omp_clauses): Use it.
	(gfc_free_split_omp_clauses): New.
	(gfc_trans_omp_do_simd, gfc_trans_omp_parallel_do,
	gfc_trans_omp_parallel_do_simd, gfc_trans_omp_distribute,
	gfc_trans_omp_teams, gfc_trans_omp_target, gfc_trans_omp_taskloop,
	gfc_trans_omp_master_taskloop, gfc_trans_omp_parallel_master): Use it.

gcc/testsuite/ChangeLog:

	* gfortran.dg/gomp/openmp-simd-6.f90: Update scan-tree-dump.
	* gfortran.dg/gomp/scan-5.f90: Likewise.
	* gfortran.dg/gomp/loop-1.f90: Likewise; remove xfail.
	* gfortran.dg/gomp/pr99928-1.f90: Remove xfail.
	* gfortran.dg/gomp/pr99928-2.f90: Likewise.
	* gfortran.dg/gomp/pr99928-3.f90: Likewise.
	* gfortran.dg/gomp/pr99928-8.f90: Likewise.

 gcc/fortran/trans-openmp.c   | 186 ++-
 gcc/testsuite/gfortran.dg/gomp/loop-1.f90|   7 +-
 gcc/testsuite/gfortran.dg/gomp/openmp-simd-6.f90 |   2 +-
 gcc/testsuite/gfortran.dg/gomp/pr99928-1.f90 |   4 +-
 gcc/testsuite/gfortran.dg/gomp/pr99928-2.f90 |   4 +-
 gcc/testsuite/gfortran.dg/gomp/pr99928-3.f90 |  16 +-
 gcc/testsuite/gfortran.dg/gomp/pr99928-8.f90 |  48 +++---
 gcc/testsuite/gfortran.dg/gomp/scan-5.f90|   2 +-
 8 files changed, 224 insertions(+), 45 deletions(-)

diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c
index 1e22cdb82b7..0b7df0d441f 100644
--- a/gcc/fortran/trans-openmp.c
+++ b/gcc/fortran/trans-openmp.c
@@ -5358,6 +5358,146 @@ enum
   GFC_OMP_MASK_TASKLOOP = (1 << GFC_OMP_SPLIT_TASKLOOP)
 };
 
+/* If a var is in lastprivate/firstprivate/reduction but not in a
+   data mapping/sharing clause, add it to 'map(tofrom:' if is_target
+   and to 'shared' otherwise.  */
+static void
+gfc_add_clause_implicitly (gfc_omp_clauses *clauses_out,
+			   gfc_omp_clauses *clauses_in,
+			   bool is_target, bool is_parallel_do)
+{
+  int clauselist_to_add = is_target ? OMP_LIST_MAP : OMP_LIST_SHARED;
+  gfc_omp_namelist *tail = NULL;
+  for (int i = 0; i < 5; ++i)
+{
+  gfc_omp_namelist *n;
+  switch (i)
+	{
+	case 0: n = clauses_in->lists[OMP_LIST_FIRSTPRIVATE]; break;
+	case 1: n = clauses_in->lists[OMP_LIST_LASTPRIVATE]; break;
+	case 2: n = clauses_in->lists[OMP_LIST_REDUCTION]; break;
+	case 3: n = clauses_in->lists[OMP_LIST_REDUCTION_INSCAN]; break;
+	case 4: n = clauses_in->lists[OMP_LIST_REDUCTION_TASK]; break;
+	default: gcc_unreachable ();
+	}
+  for (; n != NULL; n = n->next)
+	{
+	  gfc_omp_namelist *n2, **n_firstp = NULL, **n_lastp = NULL;
+	  for (int j = 0; j < 6; ++j)
+	{
+	  gfc_omp_namelist **n2ref = NULL, *prev2 = NULL;
+	  switch (j)
+		{
+		case 0:
+		  n2ref = &clauses_out->lists[clauselist_to_add];
+		  break;
+		case 1:
+		  n2ref = &clauses_out->lists[OMP_LIST_FIRSTPRIVATE];
+		  break;
+		case 2:
+		  if (is_target)
+		n2ref = &clauses_in->lists[OMP_LIST_LASTPRIVATE];
+		  else
+		n2ref = &clauses_out->lists[OMP_LIST_LASTPRIVATE];
+		  break;
+		case 3: n2ref = &clauses_out->lists[OMP_LIST_REDUCTION]; break;
+		case 4:
+		  n2ref = &clauses_out->lists[OMP_LIST_REDUCTION_INSCAN];
+		  break;
+		case 5:
+		  n2ref = &clauses_out->lists[OMP_LIST_REDUCTION_TASK];
+		  break;
+		default: gcc_unreachable ();
+		}
+	  for (n2 = *n2ref; n2 != NULL; prev2 = n2, n2 = n2->next)
+		if (n2->sym == n->sym)
+		  break;
+	  if (n2)
+		{
+		  if (j == 0 /* clauselist_to_add */)
+		break;  /* Already present.  */
+		  if (j == 1 /* OMP_LIST_FIRSTPRIVATE */)
+		{
+		  n_firstp = prev2 ? &prev2->next : n2ref;
+		  continue;
+		}
+		  if (j == 2 /* OMP_LIST_LASTPRIVATE */)
+		{
+		  n_lastp = prev2 ? &prev2->next : n2ref;
+		  continue;
+		}
+		  break;
+		}
+	}
+	  if (n_firstp && n_lastp)
+	{
+	  /* For parallel do, GCC puts firstprivatee/lastprivate
+		 on the parallel.  */
+	  if (is_parallel_do)
+		continue;
+	  *n_firstp = (*n_firstp)->next;
+	  if (!is_target)
+		*n_lastp = (*n_lastp)->next;
+	}
+	  else if (is_target && n_lastp)
+	;
+	  else if (n2 || n_firstp || n_lastp)
+	continue;
+	  if (clauses_out->lists[clauselist_t

Re: [Patch] Fortran/OpenMP: Fix clause splitting for target/parallel/teams [PR99928]

2021-06-07 Thread Jakub Jelinek via Fortran
On Mon, Jun 07, 2021 at 03:21:10PM +0200, Tobias Burnus wrote:
> +static void
> +gfc_add_clause_implicitly (gfc_omp_clauses *clauses_out,
> +gfc_omp_clauses *clauses_in,
> +bool is_target, bool is_parallel_do)
> +{
> +  int clauselist_to_add = is_target ? OMP_LIST_MAP : OMP_LIST_SHARED;

For SHARED and array sections on reduction shared should be for the whole
variable rather than just the array section.
But I guess that can be solved only when the support is there.

> +   if (clauses_out->lists[clauselist_to_add]
> +   && clauses_out->lists[clauselist_to_add] == 
> clauses_in->lists[clauselist_to_add])

Too long line.

Otherwise LGTM.

Jakub