[Patch] OpenMP: Fortran - fix ancestor's requires reverse_offload check

2022-06-08 Thread Tobias Burnus

The OpenMP requires directive may only be placed in the specification part of
a program unit (except it happens via the USE of a module).

But the target directive ancestor-requires-'reverse_offload' only checked
the current namespace.

OK for mainline?

Tobias
-
Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
München, HRB 106955
OpenMP: Fortran - fix ancestor's requires reverse_offload check

gcc/fortran/

	* openmp.cc (gfc_match_omp_clauses): Check also parent namespace
	for 'requires reverse_offload'.

gcc/testsuite/

	* gfortran.dg/gomp/target-device-ancestor-5.f90: New test.

 gcc/fortran/openmp.cc  |  9 ++-
 .../gfortran.dg/gomp/target-device-ancestor-5.f90  | 69 ++
 2 files changed, 77 insertions(+), 1 deletion(-)

diff --git a/gcc/fortran/openmp.cc b/gcc/fortran/openmp.cc
index d12cec43d64..aeb8a43e12e 100644
--- a/gcc/fortran/openmp.cc
+++ b/gcc/fortran/openmp.cc
@@ -2014,8 +2014,15 @@ gfc_match_omp_clauses (gfc_omp_clauses **cp, const omp_mask mask,
 		}
 	  else if (gfc_match ("ancestor : ") == MATCH_YES)
 		{
+		  bool has_requires = false;
 		  c->ancestor = true;
-		  if (!(gfc_current_ns->omp_requires & OMP_REQ_REVERSE_OFFLOAD))
+		  for (gfc_namespace *ns = gfc_current_ns; ns; ns = ns->parent)
+		if (ns->omp_requires & OMP_REQ_REVERSE_OFFLOAD)
+		  {
+			has_requires = true;
+			break;
+		  }
+		  if (!has_requires)
 		{
 		  gfc_error ("% device modifier not "
  "preceded by % directive "
diff --git a/gcc/testsuite/gfortran.dg/gomp/target-device-ancestor-5.f90 b/gcc/testsuite/gfortran.dg/gomp/target-device-ancestor-5.f90
new file mode 100644
index 000..06a11eb5092
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/gomp/target-device-ancestor-5.f90
@@ -0,0 +1,69 @@
+! { dg-do compile }
+!
+! Check that a requires directive is still recognized
+! if it is in the associated parent namespace of the
+! target directive.
+!
+
+module m
+  !$omp requires reverse_offload  ! { dg-error "REQUIRES directive is not yet supported" }
+contains
+  subroutine foo()
+!$omp target device(ancestor:1)
+!$omp end target
+  end subroutine foo
+
+  subroutine bar()
+block
+  block
+block
+  !$omp target device(ancestor:1)
+  !$omp end target
+end block
+  end block
+end block
+  end subroutine bar
+end module m
+
+subroutine foo()
+  !$omp requires reverse_offload  ! { dg-error "REQUIRES directive is not yet supported" }
+  block
+block
+  block
+!$omp target device(ancestor:1)
+!$omp end target
+  end block
+end block
+  end block
+contains
+  subroutine bar()
+block
+  block
+block
+  !$omp target device(ancestor:1)
+  !$omp end target
+end block
+  end block
+end block
+  end subroutine bar
+end subroutine foo
+
+program main
+  !$omp requires reverse_offload  ! { dg-error "REQUIRES directive is not yet supported" }
+contains
+  subroutine foo()
+!$omp target device(ancestor:1)
+!$omp end target
+  end subroutine foo
+
+  subroutine bar()
+block
+  block
+block
+  !$omp target device(ancestor:1)
+  !$omp end target
+end block
+  end block
+end block
+  end subroutine bar
+end


Re: [Patch] OpenMP: Fortran - fix ancestor's requires reverse_offload check

2022-06-08 Thread Jakub Jelinek via Fortran
On Wed, Jun 08, 2022 at 09:54:07AM +0200, Tobias Burnus wrote:
> The OpenMP requires directive may only be placed in the specification part of
> a program unit (except it happens via the USE of a module).
> 
> But the target directive ancestor-requires-'reverse_offload' only checked
> the current namespace.
> 
> OK for mainline?
> 
> Tobias
> -
> Siemens Electronic Design Automation GmbH; Anschrift: Arnulfstraße 201, 80634 
> München; Gesellschaft mit beschränkter Haftung; Geschäftsführer: Thomas 
> Heurung, Frank Thürauf; Sitz der Gesellschaft: München; Registergericht 
> München, HRB 106955

> OpenMP: Fortran - fix ancestor's requires reverse_offload check
> 
> gcc/fortran/
> 
>   * openmp.cc (gfc_match_omp_clauses): Check also parent namespace
>   for 'requires reverse_offload'.
> 
> gcc/testsuite/
> 
>   * gfortran.dg/gomp/target-device-ancestor-5.f90: New test.

LGTM, thanks.

Jakub



Re: [PATCH v2 01/11] OpenMP 5.0: Clause ordering for OpenMP 5.0 (topological sorting by base pointer)

2022-06-08 Thread Julian Brown
Hi Jakub,

Thanks for review!

On Tue, 24 May 2022 15:03:07 +0200
Jakub Jelinek via Fortran  wrote:

> On Fri, Mar 18, 2022 at 09:24:51AM -0700, Julian Brown wrote:
> > 2021-11-23  Julian Brown  
> > 
> > gcc/
> > * gimplify.c (is_or_contains_p,
> > omp_target_reorder_clauses): Delete functions.
> > (omp_tsort_mark): Add enum.
> > (omp_mapping_group): Add struct.
> > (debug_mapping_group, omp_get_base_pointer,
> > omp_get_attachment, omp_group_last, omp_gather_mapping_groups,
> > omp_group_base, omp_index_mapping_groups, omp_containing_struct,
> > omp_tsort_mapping_groups_1, omp_tsort_mapping_groups,
> > omp_segregate_mapping_groups, omp_reorder_mapping_groups):
> > New functions.
> > (gimplify_scan_omp_clauses): Call above functions instead of
> > omp_target_reorder_clauses, unless we've seen an error.
> > * omp-low.c (scan_sharing_clauses): Avoid strict test if we
> > haven't sorted mapping groups.
> > 
> > gcc/testsuite/
> > * g++.dg/gomp/target-lambda-1.C: Adjust expected output.
> > * g++.dg/gomp/target-this-3.C: Likewise.
> > * g++.dg/gomp/target-this-4.C: Likewise.
> > +  
> 
> Wouldn't hurt to add a comment on the meanings of the enumerators.

Added.

> > +enum omp_tsort_mark {
> > +  UNVISITED,
> > +  TEMPORARY,
> > +  PERMANENT
> > +};
> > +
> > +struct omp_mapping_group {
> > +  tree *grp_start;
> > +  tree grp_end;
> > +  omp_tsort_mark mark;
> > +  struct omp_mapping_group *sibling;
> > +  struct omp_mapping_group *next;
> > +};
> > +
> > +__attribute__((used)) static void  
> 
> I'd use what is used elsewhere,
> DEBUG_FUNCTION void
> without static.

Fixed.

> > +static tree
> > +omp_get_base_pointer (tree expr)

> I must say I don't see advantages of just a single loop that
> looks through all ARRAY_REFs and all COMPONENT_REFs and then just
> checks if the expr it got in the end is a decl or INDIRECT_REF
> or MEM_REF with offset 0.
> 
> > +static tree
> > +omp_containing_struct (tree expr)
> Again?

I've simplified these loops, and removed the "needs improvement"
comment.

> > @@ -9063,11 +9820,29 @@ gimplify_scan_omp_clauses (tree *list_p,
> > gimple_seq *pre_p, break;
> >}
> >  
> > -  if (code == OMP_TARGET
> > -  || code == OMP_TARGET_DATA
> > -  || code == OMP_TARGET_ENTER_DATA
> > -  || code == OMP_TARGET_EXIT_DATA)
> > -omp_target_reorder_clauses (list_p);
> > +  /* Topological sorting may fail if we have duplicate nodes, which
> > + we should have detected and shown an error for already.  Skip
> > + sorting in that case.  */
> > +  if (!seen_error ()
> > +  && (code == OMP_TARGET
> > + || code == OMP_TARGET_DATA
> > + || code == OMP_TARGET_ENTER_DATA
> > + || code == OMP_TARGET_EXIT_DATA))
> > +{
> > +  vec *groups;
> > +  groups = omp_gather_mapping_groups (list_p);
> > +  if (groups)
> > +   {
> > + hash_map *grpmap;
> > + grpmap = omp_index_mapping_groups (groups);
> > + omp_mapping_group *outlist
> > +   = omp_tsort_mapping_groups (groups, grpmap);
> > + outlist = omp_segregate_mapping_groups (outlist);
> > + list_p = omp_reorder_mapping_groups (groups, outlist,
> > list_p);
> > + delete grpmap;
> > + delete groups;
> > +   }
> > +}  
> 
> I think big question is if we do want to do this map clause reordering
> before processing the  omp target etc. clauses, or after (during
> gimplify_adjust_omp_clauses, when clauses from the implicit mappings
> are added too and especially with the declare mapper expansions),
> or both before and after.

The existing code constrains us a bit here, unless we want to
completely rewrite it!

We can only do sorting on clauses before gimplification, otherwise the
"structural" matching of the parsed syntax of base pointers inside other
clauses on the directive, etc. will certainly fail.

(Semi-relatedly, I asked this on the omp-lang mailing list:

  "When we have mappings that represent base pointers, and other
  mappings that use those base pointers, the former must be ordered to
  take place before the latter -- but should we determine that relation
  purely syntactically? How about if we write e.g. "p->" on one vs.
  "(*p)." on the other?"

but no reply...)

So, this is fine for sorting explicit mapping clauses. When planning
the approach I've used for "declare mapper" support, I wrote this (in
an internal email):

"At the moment, gimplifying OMP workshare regions proceeds in three
phases:

 1. Clauses are processed (gimplify_scan_omp_clauses), creating
records of mapped variables in a splay tree, with associated flags.

 2. The body of the workshare region is processed (gimplified),
augmenting the same splay tree with information about variables
which are used implicitly (and maybe also modifying the "explicit"
mappings from the first step).

 3. The clauses are modified based on the results of the second stage
(gimplify_adjust_omp_clauses). E.g. clauses are removed that refer