public inbox for fortran@gcc.gnu.org
 help / color / mirror / Atom feed
From: Julian Brown <julian@codesourcery.com>
To: Tobias Burnus <tobias@codesourcery.com>
Cc: <gcc-patches@gcc.gnu.org>, Jakub Jelinek <jakub@redhat.com>,
	<fortran@gcc.gnu.org>
Subject: [PATCH 2/2] OpenMP: Duplicate checking for map clauses in Fortran  (PR107214)
Date: Wed, 7 Dec 2022 19:13:55 +0000	[thread overview]
Message-ID: <20221207191355.2e43ea14@squid.athome> (raw)
In-Reply-To: <20221207190903.78a6b37f@squid.athome>

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

> Hi Julian,
> 
> I had a first quick lock at this patch, I should have a closer look
> later. However, I stumbled over the following:
> 
> On 20.10.22 18:14, Julian Brown wrote:
> > typedef struct gfc_symbol
> > {
> > ...
> >    struct gfc_symbol *old_symbol;
> >
> >    unsigned mark:1, comp_mark:1, data_mark:1, dev_mark:1,
> > gen_mark:1; unsigned reduc_mark:1, gfc_new:1;
> >
> >    struct gfc_symbol *tlink;
> >
> >    unsigned equiv_built:1;
> >    ...  
> I know that this was the case before, but can you move the mark:1 etc.
> after 'tlink'? In that case all bitfields are grouped together. If I
> have not miscounted, we have currently 7 bits before and 9 bits after
> 'tlink' and grouping them together reduced pointless padding.
> 
> * * *
> > +      else if (n->sym->mark)
> > +     gfc_error ("Symbol %qs present on both data and map clauses "
> > +                "at %L", n->sym->name, &n->where);  
> 
> I wonder whether that also rejects the following – which seems to be
> valid. The 'map' goes to 'target' and the 'firstprivate' to
> 'parallel', cf. OpenMP 5.2, "17.2 Clauses on Combined and Composite
> Constructs", [340:3-4 & 12-14]. (BTW: While some fixes went into 5.1
> regarding this section, a likewise wording is already in 5.0.)
> 
> (Testing showed: it give an ICE without the patch and an error with.)

...and this patch avoids the error for combined directives, and
reorders the gfc_symbol bitfields.

--

This patch adds duplicate checking for OpenMP "map" clauses, taking some
cues from the implementation for C in c-typeck.cc:c_finish_omp_clauses
(and similar for C++).

In addition to the existing use of the "mark" and "comp_mark" bitfields
in the gfc_symbol structure, the patch adds several new bits handling
duplicate checking within various categories of clause types.  If "mark"
is being used for map clauses, we need to use different bits for other
clauses for cases where "map" and some other clause can refer to the
same symbol (e.g. "map(n) shared(n)").

This version of the patch avoids flagging variables that are listed on
both map and firstprivate clauses when they are on a combined directive,
as they get moved to separate nested directives later (see previous
patch in series).

Tested with offloading to NVPTX alongside previous patch (and
dependencies).  OK?

2022-12-06  Julian Brown  <julian@codesourcery.com>

gcc/fortran/
        PR fortran/107214
        * gfortran.h (gfc_symbol): Add data_mark, dev_mark, gen_mark and
        reduc_mark bitfields.
        * openmp.cc (resolve_omp_clauses): Use above bitfields to improve
        duplicate clause detection.

gcc/testsuite/
        PR fortran/107214
        * gfortran.dg/gomp/pr107214.f90: New test.

[-- Attachment #2: 0002-OpenMP-Duplicate-checking-for-map-clauses-in-Fortran.patch --]
[-- Type: text/x-patch, Size: 9807 bytes --]

From fa6d1e273449aff61833064027fed3787c13121f Mon Sep 17 00:00:00 2001
Message-Id: <fa6d1e273449aff61833064027fed3787c13121f.1670438768.git.julian@codesourcery.com>
In-Reply-To: <c66db363066913ae4939f2aa706427338b109d71.1670438768.git.julian@codesourcery.com>
References: <c66db363066913ae4939f2aa706427338b109d71.1670438768.git.julian@codesourcery.com>
From: Julian Brown <julian@codesourcery.com>
Date: Tue, 6 Dec 2022 23:10:58 +0000
Subject: [PATCH 2/2] OpenMP: Duplicate checking for map clauses in Fortran
 (PR107214)

This patch adds duplicate checking for OpenMP "map" clauses, taking some
cues from the implementation for C in c-typeck.cc:c_finish_omp_clauses
(and similar for C++).

In addition to the existing use of the "mark" and "comp_mark" bitfields
in the gfc_symbol structure, the patch adds several new bits handling
duplicate checking within various categories of clause types.  If "mark"
is being used for map clauses, we need to use different bits for other
clauses for cases where "map" and some other clause can refer to the
same symbol (e.g. "map(n) shared(n)").

This version of the patch avoids flagging variables that are listed on
both map and firstprivate clauses when they are on a combined directive,
as they get moved to separate nested directives later (see previous
patch in series).

Tested with offloading to NVPTX alongside previous patch (and
dependencies).  OK?

2022-12-06  Julian Brown  <julian@codesourcery.com>

gcc/fortran/
	PR fortran/107214
	* gfortran.h (gfc_symbol): Add data_mark, dev_mark, gen_mark and
	reduc_mark bitfields.
	* openmp.cc (resolve_omp_clauses): Use above bitfields to improve
	duplicate clause detection.

gcc/testsuite/
	PR fortran/107214
	* gfortran.dg/gomp/pr107214.f90: New test.
---
 gcc/fortran/gfortran.h                      | 32 ++++++---
 gcc/fortran/openmp.cc                       | 73 +++++++++++++++++----
 gcc/testsuite/gfortran.dg/gomp/pr107214.f90 |  7 ++
 3 files changed, 90 insertions(+), 22 deletions(-)
 create mode 100644 gcc/testsuite/gfortran.dg/gomp/pr107214.f90

diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index df90ed39bea7..47a7f5552385 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -1871,16 +1871,6 @@ typedef struct gfc_symbol
 
   gfc_namelist *namelist, *namelist_tail;
 
-  /* Change management fields.  Symbols that might be modified by the
-     current statement have the mark member nonzero.  Of these symbols,
-     symbols with old_symbol equal to NULL are symbols created within
-     the current statement.  Otherwise, old_symbol points to a copy of
-     the old symbol. gfc_new is used in symbol.cc to flag new symbols.
-     comp_mark is used to indicate variables which have component accesses
-     in OpenMP/OpenACC directive clauses.  */
-  struct gfc_symbol *old_symbol;
-  unsigned mark:1, comp_mark:1, gfc_new:1;
-
   /* The tlink field is used in the front end to carry the module
      declaration of separate module procedures so that the characteristics
      can be compared with the corresponding declaration in a submodule. In
@@ -1888,6 +1878,28 @@ typedef struct gfc_symbol
      deferred initialization.  */
   struct gfc_symbol *tlink;
 
+  /* Change management fields.  Symbols that might be modified by the
+     current statement have the mark member nonzero.  Of these symbols,
+     symbols with old_symbol equal to NULL are symbols created within
+     the current statement.  Otherwise, old_symbol points to a copy of
+     the old symbol. gfc_new is used in symbol.cc to flag new symbols.
+     comp_mark is used to indicate variables which have component accesses
+     in OpenMP/OpenACC directive clauses (cf. c-typeck.cc:c_finish_omp_clauses,
+     map_field_head).
+     data_mark is used to check duplicate mappings for OpenMP data-sharing
+     clauses (see firstprivate_head/lastprivate_head in the above function).
+     dev_mark is used to check duplicate mappings for OpenMP
+     is_device_ptr/has_device_addr clauses (see is_on_device_head in above
+     function).
+     gen_mark is used to check duplicate mappings for OpenMP
+     use_device_ptr/use_device_addr/private/shared clauses (see generic_head in
+     above functon).
+     reduc_mark is used to check duplicate mappings for OpenMP reduction
+     clauses.  */
+  struct gfc_symbol *old_symbol;
+  unsigned mark:1, comp_mark:1, data_mark:1, dev_mark:1, gen_mark:1;
+  unsigned reduc_mark:1, gfc_new:1;
+
   /* Nonzero if all equivalences associated with this symbol have been
      processed.  */
   unsigned equiv_built:1;
diff --git a/gcc/fortran/openmp.cc b/gcc/fortran/openmp.cc
index 653c43f79ffb..63a14daa6d7b 100644
--- a/gcc/fortran/openmp.cc
+++ b/gcc/fortran/openmp.cc
@@ -7135,6 +7135,10 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
 	  continue;
 	n->sym->mark = 0;
 	n->sym->comp_mark = 0;
+	n->sym->data_mark = 0;
+	n->sym->dev_mark = 0;
+	n->sym->gen_mark = 0;
+	n->sym->reduc_mark = 0;
 	if (n->sym->attr.flavor == FL_VARIABLE
 	    || n->sym->attr.proc_pointer
 	    || (!code && (!n->sym->attr.dummy || n->sym->ns != ns)))
@@ -7203,7 +7207,6 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
 	&& list != OMP_LIST_LASTPRIVATE
 	&& list != OMP_LIST_ALIGNED
 	&& list != OMP_LIST_DEPEND
-	&& (list != OMP_LIST_MAP || openacc)
 	&& list != OMP_LIST_FROM
 	&& list != OMP_LIST_TO
 	&& (list != OMP_LIST_REDUCTION || !openacc)
@@ -7222,10 +7225,43 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
 	    for (gfc_ref *ref = n->expr->ref; ref; ref = ref->next)
 	      if (ref->type == REF_COMPONENT)
 		component_ref_p = true;
-	  if ((!component_ref_p && n->sym->comp_mark)
-	      || (component_ref_p && n->sym->mark))
-	    gfc_error ("Symbol %qs has mixed component and non-component "
-		       "accesses at %L", n->sym->name, &n->where);
+	  if ((list == OMP_LIST_IS_DEVICE_PTR
+	       || list == OMP_LIST_HAS_DEVICE_ADDR)
+	      && !component_ref_p)
+	    {
+	      if (n->sym->gen_mark || n->sym->dev_mark || n->sym->reduc_mark)
+		gfc_error ("Symbol %qs present on multiple clauses at %L",
+			   n->sym->name, &n->where);
+	      else
+		n->sym->dev_mark = 1;
+	    }
+	  else if ((list == OMP_LIST_USE_DEVICE_PTR
+		    || list == OMP_LIST_USE_DEVICE_ADDR
+		    || list == OMP_LIST_PRIVATE
+		    || list == OMP_LIST_SHARED)
+		   && !component_ref_p)
+	    {
+	      if (n->sym->gen_mark || n->sym->dev_mark || n->sym->reduc_mark)
+		gfc_error ("Symbol %qs present on multiple clauses at %L",
+			   n->sym->name, &n->where);
+	      else
+		n->sym->gen_mark = 1;
+	    }
+	  else if (list == OMP_LIST_REDUCTION && !component_ref_p)
+	    {
+	      if (n->sym->gen_mark || n->sym->dev_mark || n->sym->reduc_mark)
+		gfc_error ("Symbol %qs present on multiple clauses at %L",
+			   n->sym->name, &n->where);
+	      else
+		n->sym->reduc_mark = 1;
+	    }
+	  else if ((!component_ref_p && n->sym->comp_mark)
+		   || (component_ref_p && n->sym->mark))
+	    {
+	      if (openacc)
+		gfc_error ("Symbol %qs has mixed component and non-component "
+			   "accesses at %L", n->sym->name, &n->where);
+	    }
 	  else if (n->sym->mark)
 	    gfc_error ("Symbol %qs present on multiple clauses at %L",
 		       n->sym->name, &n->where);
@@ -7241,31 +7277,44 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses,
   gcc_assert (OMP_LIST_LASTPRIVATE == OMP_LIST_FIRSTPRIVATE + 1);
   for (list = OMP_LIST_FIRSTPRIVATE; list <= OMP_LIST_LASTPRIVATE; list++)
     for (n = omp_clauses->lists[list]; n; n = n->next)
-      if (n->sym->mark)
+      if (n->sym->data_mark || n->sym->gen_mark || n->sym->dev_mark)
 	{
 	  gfc_error ("Symbol %qs present on multiple clauses at %L",
 		     n->sym->name, &n->where);
-	  n->sym->mark = 0;
+	  n->sym->data_mark = 0;
 	}
+      else if (n->sym->mark
+	       && code->op != EXEC_OMP_TARGET_TEAMS
+	       && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE
+	       && code->op != EXEC_OMP_TARGET_TEAMS_LOOP
+	       && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD
+	       && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO
+	       && code->op != EXEC_OMP_TARGET_PARALLEL
+	       && code->op != EXEC_OMP_TARGET_PARALLEL_DO
+	       && code->op != EXEC_OMP_TARGET_PARALLEL_LOOP
+	       && code->op != EXEC_OMP_TARGET_PARALLEL_DO_SIMD
+	       && code->op != EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD)
+	gfc_error ("Symbol %qs present on both data and map clauses "
+		   "at %L", n->sym->name, &n->where);
 
   for (n = omp_clauses->lists[OMP_LIST_FIRSTPRIVATE]; n; n = n->next)
     {
-      if (n->sym->mark)
+      if (n->sym->data_mark || n->sym->gen_mark || n->sym->dev_mark)
 	gfc_error ("Symbol %qs present on multiple clauses at %L",
 		   n->sym->name, &n->where);
       else
-	n->sym->mark = 1;
+	n->sym->data_mark = 1;
     }
   for (n = omp_clauses->lists[OMP_LIST_LASTPRIVATE]; n; n = n->next)
-    n->sym->mark = 0;
+    n->sym->data_mark = 0;
 
   for (n = omp_clauses->lists[OMP_LIST_LASTPRIVATE]; n; n = n->next)
     {
-      if (n->sym->mark)
+      if (n->sym->data_mark || n->sym->gen_mark || n->sym->dev_mark)
 	gfc_error ("Symbol %qs present on multiple clauses at %L",
 		   n->sym->name, &n->where);
       else
-	n->sym->mark = 1;
+	n->sym->data_mark = 1;
     }
 
   for (n = omp_clauses->lists[OMP_LIST_ALIGNED]; n; n = n->next)
diff --git a/gcc/testsuite/gfortran.dg/gomp/pr107214.f90 b/gcc/testsuite/gfortran.dg/gomp/pr107214.f90
new file mode 100644
index 000000000000..25949934e840
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/pr107214.f90
@@ -0,0 +1,7 @@
+! { dg-do compile }
+
+program p
+   integer, allocatable :: a
+   !$omp target map(tofrom: a, a) ! { dg-error "Symbol 'a' present on multiple clauses" }
+   !$omp end target
+end
-- 
2.29.2


  reply	other threads:[~2022-12-07 19:14 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-10-20 16:14 [PATCH] " Julian Brown
2022-10-26 10:39 ` Tobias Burnus
2022-12-07 19:09   ` [PATCH 1/2] OpenMP/Fortran: Combined directives with map/firstprivate of same symbol Julian Brown
2022-12-07 19:13     ` Julian Brown [this message]
2022-12-08 12:04       ` [PATCH 2/2] OpenMP: Duplicate checking for map clauses in Fortran (PR107214) Tobias Burnus
2022-12-10 12:10         ` Julian Brown
2022-12-10 12:48           ` Tobias Burnus
2022-12-08 10:22     ` [PATCH 1/2] OpenMP/Fortran: Combined directives with map/firstprivate of same symbol Tobias Burnus

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20221207191355.2e43ea14@squid.athome \
    --to=julian@codesourcery.com \
    --cc=fortran@gcc.gnu.org \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=jakub@redhat.com \
    --cc=tobias@codesourcery.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).