public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [patch] Fortran fix for PR70289
@ 2016-04-01 14:49 Cesar Philippidis
  2016-04-01 14:56 ` Jakub Jelinek
  0 siblings, 1 reply; 5+ messages in thread
From: Cesar Philippidis @ 2016-04-01 14:49 UTC (permalink / raw)
  To: gcc-patches, Fortran List; +Cc: Jakub Jelinek

[-- Attachment #1: Type: text/plain, Size: 2119 bytes --]

The bug in PR70289 is an assertion failure triggered by a static
variable used inside an offloaded acc region which doesn't have a data
clause associated with it. Basically, that static variable ends up in a
different lto partition, which was not streamed to the offloaded
compiler. I'm not sure if we should try to replicate the static storage
in the offloaded regions, but it probably doesn't make sense in a
parallel environment anyway.

My solution to this problem was to teach the fortran front end to create
a data clause for each reduction variable it encounters. Furthermore,
I've decided to update the semantics of the acc parallel reduction
clause such that gfortran will emit an error when a reduction variable
is private or firstprivate (note that an acc loop reduction still works
with private and firstprivate reductions, just not acc parallel
reductions). The second change is to emit a warning when an incompatible
data clause is used with a reduction, and promote that data clause to a
present_or_copy. My rationale behind the promotion is, you cannot have a
copyin reduction variable because the original variable on the host will
not be updated. Similarly, you cannot have a copyout reduction variable
because the reduction operator is supposed to combine the results of the
reduction with the original reduction variable, but in copyout the
original variable is not initialized on the accelerator. But perhaps the
copyout rule is too strict?

Tom and I are still working with the OpenACC technical committee to get
some clarification on how the reduction value should behave with respect
to data movement. In the meantime, I wanted to see if this type of
solution would be appropriate for trunk. I was trying to get this to
work in the gimplifier so that one patch could resolve the problem for
all of the front ends, but that was happening too late. Especially for
reference types.

By the way, we will also benefit from this patch too
<https://gcc.gnu.org/ml/gcc-patches/2016-01/msg00482.html>. If not for
these reduction, but for global acc variables which haven't been
properly declared.

Cesar

[-- Attachment #2: pr70289-20160331.diff --]
[-- Type: text/x-patch, Size: 6707 bytes --]

2016-03-31  Cesar Philippidis  <cesar@codesourcery.com>

	gcc/fortran/
	* openmp.c (resolve_oacc_private_reductions): New function.
	(resolve_omp_clauses): Ensure that acc parallel reductions
	have a copy, pcopy or present clause associated with it,
	otherwise emit a warning or error as appropriate.

	gcc/testsuite/
	* gfortran.dg/goacc/reduction-promotions.f90: New test.
	* gfortran.dg/goacc/reduction.f95:

	libgomp/
	* testsuite/libgomp.oacc-fortran/pr70289.f90: New test.


diff --git a/gcc/fortran/openmp.c b/gcc/fortran/openmp.c
index a6c39cd..e59997f 100644
--- a/gcc/fortran/openmp.c
+++ b/gcc/fortran/openmp.c
@@ -3146,6 +3146,46 @@ resolve_omp_udr_clause (gfc_omp_namelist *n, gfc_namespace *ns,
 /* OpenMP directive resolving routines.  */
 
 static void
+resolve_oacc_private_reductions (gfc_omp_clauses *omp_clauses, int list)
+{
+  gfc_omp_namelist *n;
+
+  /* Check for bogus private reductions.  */
+  for (n = omp_clauses->lists[list]; n; n = n->next)
+    n->sym->mark = 1;
+
+  for (n = omp_clauses->lists[OMP_LIST_REDUCTION]; n; n = n->next)
+    if (n->sym->mark)
+      {
+	gfc_omp_namelist *prev = NULL, *tmp = NULL;
+
+	/* Remove it from the list of private clauses.  */
+	tmp = omp_clauses->lists[list];
+	while (tmp)
+	  {
+	    if (tmp->sym == n->sym)
+	      {
+		gfc_error ("Reduction symbol %qs cannot be private "
+			   "at %L", tmp->sym->name, &tmp->where);
+
+		if (omp_clauses->lists[list] == tmp)
+		  omp_clauses->lists[list] = tmp->next;
+		else
+		  prev->next = tmp->next;
+		break;
+	      }
+	    else
+	      {
+		prev = tmp;
+		tmp = tmp->next;
+	      }
+	  }
+
+	n->sym->mark = 0;
+      }
+}
+
+static void
 resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
 		     gfc_namespace *ns, bool openacc = false)
 {
@@ -3320,6 +3360,50 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
 	    gfc_error ("Array %qs is not permitted in reduction at %L",
 		       n->sym->name, &n->where);
 	}
+
+      /* Parallel reductions have their own set of rules.  */
+      if (code->op == EXEC_OACC_PARALLEL)
+	{
+	  for (n = omp_clauses->lists[OMP_LIST_REDUCTION]; n; n = n->next)
+	    n->sym->mark = 0;
+
+	  resolve_oacc_private_reductions (omp_clauses, OMP_LIST_PRIVATE);
+	  resolve_oacc_private_reductions (omp_clauses, OMP_LIST_FIRSTPRIVATE);
+
+	  /* Check for data maps which aren't copy or present_or_copy.  */
+	  for (n = omp_clauses->lists[OMP_LIST_MAP]; n; n = n->next)
+	    {
+	      if (n->sym->mark == 0
+		  && !(n->u.map_op == OMP_MAP_TOFROM
+		       || n->u.map_op == OMP_MAP_FORCE_TOFROM
+		       || n->u.map_op == OMP_MAP_FORCE_PRESENT))
+		{
+		  gfc_warning (0, "incompatible data clause associated with "
+			       "symbol %qs; promoting this clause to "
+			       "present_or_copy at %L", n->sym->name,
+			       &n->where);
+		  n->u.map_op = OMP_MAP_TOFROM;
+		}
+	      n->sym->mark = 1;
+	    }
+
+	  /* Add a present_or_copy data clause for any reduction which
+	     doesnot already have one.  */
+	  for (n = omp_clauses->lists[OMP_LIST_REDUCTION]; n; n = n->next)
+	    {
+	      if (n->sym->mark == 0)
+		{
+		  gfc_omp_namelist *p = gfc_get_omp_namelist ();
+		  p->next = omp_clauses->lists[OMP_LIST_MAP];
+		  omp_clauses->lists[OMP_LIST_MAP] = p;
+		  p->sym = n->sym;
+		  p->expr = NULL;
+		  p->where = n->where;
+		  p->u.map_op = OMP_MAP_TOFROM;
+		}
+	      n->sym->mark = 1;
+	    }
+	}
     }
   
   for (n = omp_clauses->lists[OMP_LIST_TO]; n; n = n->next)
diff --git a/gcc/testsuite/gfortran.dg/goacc/reduction-promotions.f90 b/gcc/testsuite/gfortran.dg/goacc/reduction-promotions.f90
new file mode 100644
index 0000000..28d0951
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/goacc/reduction-promotions.f90
@@ -0,0 +1,43 @@
+! Ensure that each parallel reduction variable as a copy or pcopy
+! data clause.
+
+! { dg-additional-options "-fdump-tree-gimple" }
+
+program test
+  implicit none
+  integer :: var
+
+  !$acc parallel reduction(+:var)
+  !$acc end parallel
+  
+  !$acc parallel reduction(+:var) copy(var)
+  !$acc end parallel
+
+  !$acc parallel reduction(+:var) pcopy(var)
+  !$acc end parallel
+
+  !$acc parallel reduction(+:var) present(var)
+  !$acc end parallel
+  
+  !$acc parallel reduction(+:var) copyin(var) ! { dg-warning "incompatible data clause" }
+  !$acc end parallel
+
+  !$acc parallel reduction(+:var) pcopyin(var) ! { dg-warning "incompatible data clause" }
+  !$acc end parallel
+
+  !$acc parallel reduction(+:var) copyout(var) ! { dg-warning "incompatible data clause" }
+  !$acc end parallel
+
+  !$acc parallel reduction(+:var) pcopyout(var) ! { dg-warning "incompatible data clause" }
+  !$acc end parallel
+
+  !$acc parallel reduction(+:var) create(var) ! { dg-warning "incompatible data clause" }
+  !$acc end parallel
+
+  !$acc parallel reduction(+:var) pcreate(var) ! { dg-warning "incompatible data clause" }
+  !$acc end parallel
+end program test
+
+! { dg-final { scan-tree-dump-times "target oacc_parallel map.tofrom:var" 8 "gimple" } }
+! { dg-final { scan-tree-dump-times "target oacc_parallel map.force_tofrom:var" 1 "gimple" } }
+! { dg-final { scan-tree-dump-times "target oacc_parallel map.force_present:var" 1 "gimple" } }
diff --git a/gcc/testsuite/gfortran.dg/goacc/reduction.f95 b/gcc/testsuite/gfortran.dg/goacc/reduction.f95
index a13574b..9bef09a 100644
--- a/gcc/testsuite/gfortran.dg/goacc/reduction.f95
+++ b/gcc/testsuite/gfortran.dg/goacc/reduction.f95
@@ -134,8 +134,11 @@ common /blk/ i1
 !$acc end parallel
 !$acc parallel reduction (iand:ta1)	! { dg-error "OMP DECLARE REDUCTION iand not found for type TYPE" }
 !$acc end parallel
-
-end subroutine
+!$acc parallel reduction (+:i1) private(i1) ! { dg-error "Reduction symbol .i1. cannot be private" }
+!$acc end parallel
+!$acc parallel reduction (+:i2) firstprivate(i2) ! { dg-error "Reduction symbol .i2. cannot be private" }
+!$acc end parallel
+end subroutine foo
 
 ! { dg-error "Array 'ia2' is not permitted in reduction" "" { target "*-*-*" } 27 }
 ! { dg-error "Array 'ra1' is not permitted in reduction" "" { target "*-*-*" } 29 }
diff --git a/libgomp/testsuite/libgomp.oacc-fortran/pr70289.f90 b/libgomp/testsuite/libgomp.oacc-fortran/pr70289.f90
new file mode 100644
index 0000000..63bde44
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-fortran/pr70289.f90
@@ -0,0 +1,20 @@
+program foo
+  implicit none
+  integer :: i
+  integer :: temp = 0
+  integer :: temp2 = 0
+
+  !$acc parallel
+  !$acc loop gang private(temp)
+  do i=1, 10000
+     temp = 0
+  enddo
+  !$acc end parallel
+
+  !$acc parallel reduction(+:temp2)
+  !$acc loop gang reduction(+:temp2)
+  do i=1, 10000
+     temp2 = 0
+  enddo
+  !$acc end parallel
+end program foo

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2016-04-04 21:35 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-04-01 14:49 [patch] Fortran fix for PR70289 Cesar Philippidis
2016-04-01 14:56 ` Jakub Jelinek
2016-04-01 15:07   ` Cesar Philippidis
2016-04-01 15:17     ` Jakub Jelinek
2016-04-04 21:35       ` Cesar Philippidis

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).