[gcc/devel/omp/gcc-10] Various OpenACC reduction enhancements - FE changes

Kwok Yeung kcy@gcc.gnu.org
Tue Jun 9 22:34:02 GMT 2020


https://gcc.gnu.org/g:6b3e1f7f05cd360bbd356b3f78511aa2ec3f40c3

commit 6b3e1f7f05cd360bbd356b3f78511aa2ec3f40c3
Author: Julian Brown <julian@codesourcery.com>
Date:   Tue Feb 12 14:56:12 2019 -0800

    Various OpenACC reduction enhancements - FE changes
    
    This version differs somewhat from the last version posted upstream
    (and addresses some of Jakub's review comments).
    
    2018-12-13  Cesar Philippidis  <cesar@codesourcery.com>
                Nathan Sidwell  <nathan@acm.org>
                Julian Brown  <julian@codesourcery.com>
    
            gcc/c/
            * c-parser.c (c_parser_omp_variable_list): New c_omp_region_type
            argument.  Use it to specialize handling of OMP_CLAUSE_REDUCTION for
            OpenACC.
            (c_parser_oacc_data_clause): Add region-type argument.
            (c_parser_oacc_data_clause_deviceptr): Likewise.
            (c_parser_omp_clause_reduction): Change is_omp boolean parameter to
            c_omp_region_type.  Update call to c_parser_omp_variable_list.
            (c_parser_oacc_all_clauses): Update calls to
            c_parser_omp_clause_reduction.
            (c_parser_omp_all_clauses): Likewise.
            (c_parser_oacc_cache): Update call to c_parser_omp_var_list_parens.
            * c-typeck.c (c_finish_omp_clauses): Emit an error on orphan OpenACC
            gang reductions.  Suppress user-defined reduction error for OpenACC.
    
            gcc/cp/
            * parser.c (cp_parser_omp_var_list_no_open):  New c_omp_region_type
            argument.  Use it to specialize handling of OMP_CLAUSE_REDUCTION for
            OpenACC.
            (cp_parser_omp_var_list): Add c_omp_region_type argument. Update call
            to cp_parser_omp_var_list_parens.
            (cp_parser_oacc_data_clause): Update call to cp_parser_omp_var_list.
            (cp_parser_omp_clause_reduction): Change is_omp boolean parameter to
            c_omp_region_type.  Update call to cp_parser_omp_var_list_no_open.
            (cp_parser_oacc_all_clauses): Update call to
            cp_parser_omp_clause_reduction.
            (cp_parser_omp_all_clauses): Likewise.
            * semantics.c (finish_omp_reduction_clause): Add c_omp_region_type
            argument.  Suppress user-defined reduction error for OpenACC.
            (finish_omp_clauses): Emit an error on orphan OpenACC gang reductions.
    
            gcc/fortran/
            * openmp.c (resolve_oacc_loop_blocks): Emit an error on orphan OpenACC
            gang reductions.
            * trans-openmp.c (gfc_omp_clause_copy_ctor): Permit reductions.

Diff:
---
 gcc/c/ChangeLog.omp        | 18 ++++++++++++++++++
 gcc/c/c-parser.c           | 35 ++++++++++++++++++++++-------------
 gcc/c/c-typeck.c           | 24 ++++++++++++++++++++----
 gcc/cp/ChangeLog.omp       | 19 +++++++++++++++++++
 gcc/cp/parser.c            | 24 +++++++++++++-----------
 gcc/cp/semantics.c         | 30 +++++++++++++++++++++++-------
 gcc/fortran/ChangeLog.omp  |  8 ++++++++
 gcc/fortran/openmp.c       | 12 ++++++++++++
 gcc/fortran/trans-openmp.c |  3 ++-
 9 files changed, 137 insertions(+), 36 deletions(-)

diff --git a/gcc/c/ChangeLog.omp b/gcc/c/ChangeLog.omp
index 9ed0068df65..673f344544b 100644
--- a/gcc/c/ChangeLog.omp
+++ b/gcc/c/ChangeLog.omp
@@ -1,3 +1,21 @@
+2018-12-13  Cesar Philippidis  <cesar@codesourcery.com>
+            Nathan Sidwell  <nathan@acm.org>
+            Julian Brown  <julian@codesourcery.com>
+
+        * c-parser.c (c_parser_omp_variable_list): New c_omp_region_type
+        argument.  Use it to specialize handling of OMP_CLAUSE_REDUCTION for
+        OpenACC.
+	(c_parser_oacc_data_clause): Add region-type argument.
+	(c_parser_oacc_data_clause_deviceptr): Likewise.
+        (c_parser_omp_clause_reduction): Change is_omp boolean parameter to
+        c_omp_region_type.  Update call to c_parser_omp_variable_list.
+        (c_parser_oacc_all_clauses): Update calls to
+        c_parser_omp_clause_reduction.
+        (c_parser_omp_all_clauses): Likewise.
+	(c_parser_oacc_cache): Update call to c_parser_omp_var_list_parens.
+        * c-typeck.c (c_finish_omp_clauses): Emit an error on orphan OpenACC
+        gang reductions.  Suppress user-defined reduction error for OpenACC.
+
 2018-10-02  Thomas Schwinge  <thomas@codesourcery.com>
 	    Cesar Philippidis  <cesar@codesourcery.com>
 
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 50cbcc48a5b..000691e1b0b 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -12881,6 +12881,7 @@ static tree
 c_parser_omp_variable_list (c_parser *parser,
 			    location_t clause_loc,
 			    enum omp_clause_code kind, tree list,
+			    enum c_omp_region_type ort = C_ORT_OMP,
 			    bool allow_deref = false)
 {
   auto_vec<c_token> tokens;
@@ -13034,7 +13035,8 @@ c_parser_omp_variable_list (c_parser *parser,
 	    case OMP_CLAUSE_REDUCTION:
 	    case OMP_CLAUSE_IN_REDUCTION:
 	    case OMP_CLAUSE_TASK_REDUCTION:
-	      while (c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
+	      while ((ort != C_ORT_ACC || kind != OMP_CLAUSE_REDUCTION)
+		     && c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
 		{
 		  tree low_bound = NULL_TREE, length = NULL_TREE;
 
@@ -13141,7 +13143,9 @@ c_parser_omp_variable_list (c_parser *parser,
 
 static tree
 c_parser_omp_var_list_parens (c_parser *parser, enum omp_clause_code kind,
-			      tree list, bool allow_deref = false)
+			      tree list,
+			      enum c_omp_region_type ort = C_ORT_OMP,
+			      bool allow_deref = false)
 {
   /* The clauses location.  */
   location_t loc = c_parser_peek_token (parser)->location;
@@ -13149,7 +13153,8 @@ c_parser_omp_var_list_parens (c_parser *parser, enum omp_clause_code kind,
   matching_parens parens;
   if (parens.require_open (parser))
     {
-      list = c_parser_omp_variable_list (parser, loc, kind, list, allow_deref);
+      list = c_parser_omp_variable_list (parser, loc, kind, list, ort,
+					 allow_deref);
       parens.skip_until_found_close (parser);
     }
   return list;
@@ -13218,7 +13223,8 @@ c_parser_oacc_data_clause (c_parser *parser, pragma_omp_clause c_kind,
       gcc_unreachable ();
     }
   tree nl, c;
-  nl = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_MAP, list, true);
+  nl = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_MAP, list, C_ORT_ACC,
+				     true);
 
   for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
     OMP_CLAUSE_SET_MAP_KIND (c, kind);
@@ -13238,7 +13244,8 @@ c_parser_oacc_data_clause_deviceptr (c_parser *parser, tree list)
   /* Can't use OMP_CLAUSE_MAP here (that is, can't use the generic
      c_parser_oacc_data_clause), as for PRAGMA_OACC_CLAUSE_DEVICEPTR,
      variable-list must only allow for pointer variables.  */
-  vars = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ERROR, NULL);
+  vars = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ERROR, NULL,
+				       C_ORT_ACC);
   for (t = vars; t && t; t = TREE_CHAIN (t))
     {
       tree v = TREE_PURPOSE (t);
@@ -14587,7 +14594,7 @@ c_parser_omp_clause_private (c_parser *parser, tree list)
 
 static tree
 c_parser_omp_clause_reduction (c_parser *parser, enum omp_clause_code kind,
-			       bool is_omp, tree list)
+			       enum c_omp_region_type ort, tree list)
 {
   location_t clause_loc = c_parser_peek_token (parser)->location;
   matching_parens parens;
@@ -14598,7 +14605,7 @@ c_parser_omp_clause_reduction (c_parser *parser, enum omp_clause_code kind,
       enum tree_code code = ERROR_MARK;
       tree reduc_id = NULL_TREE;
 
-      if (kind == OMP_CLAUSE_REDUCTION && is_omp)
+      if (kind == OMP_CLAUSE_REDUCTION && ort == C_ORT_OMP)
 	{
 	  if (c_parser_next_token_is_keyword (parser, RID_DEFAULT)
 	      && c_parser_peek_2nd_token (parser)->type == CPP_COMMA)
@@ -14679,7 +14686,8 @@ c_parser_omp_clause_reduction (c_parser *parser, enum omp_clause_code kind,
 	{
 	  tree nl, c;
 
-	  nl = c_parser_omp_variable_list (parser, clause_loc, kind, list);
+	  nl = c_parser_omp_variable_list (parser, clause_loc, kind, list, ort);
+
 	  for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
 	    {
 	      tree d = OMP_CLAUSE_DECL (c), type;
@@ -16049,7 +16057,7 @@ c_parser_oacc_all_clauses (c_parser *parser, omp_clause_mask mask,
 	case PRAGMA_OACC_CLAUSE_REDUCTION:
 	  clauses
 	    = c_parser_omp_clause_reduction (parser, OMP_CLAUSE_REDUCTION,
-					     false, clauses);
+					     C_ORT_ACC, clauses);
 	  c_name = "reduction";
 	  break;
 	case PRAGMA_OACC_CLAUSE_SEQ:
@@ -16197,7 +16205,7 @@ c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask,
 	case PRAGMA_OMP_CLAUSE_IN_REDUCTION:
 	  clauses
 	    = c_parser_omp_clause_reduction (parser, OMP_CLAUSE_IN_REDUCTION,
-					     true, clauses);
+					     C_ORT_OMP, clauses);
 	  c_name = "in_reduction";
 	  break;
 	case PRAGMA_OMP_CLAUSE_LASTPRIVATE:
@@ -16239,7 +16247,7 @@ c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask,
 	case PRAGMA_OMP_CLAUSE_REDUCTION:
 	  clauses
 	    = c_parser_omp_clause_reduction (parser, OMP_CLAUSE_REDUCTION,
-					     true, clauses);
+					     C_ORT_OMP, clauses);
 	  c_name = "reduction";
 	  break;
 	case PRAGMA_OMP_CLAUSE_SCHEDULE:
@@ -16253,7 +16261,7 @@ c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask,
 	case PRAGMA_OMP_CLAUSE_TASK_REDUCTION:
 	  clauses
 	    = c_parser_omp_clause_reduction (parser, OMP_CLAUSE_TASK_REDUCTION,
-					     true, clauses);
+					     C_ORT_OMP, clauses);
 	  c_name = "task_reduction";
 	  break;
 	case PRAGMA_OMP_CLAUSE_UNTIED:
@@ -16466,7 +16474,8 @@ c_parser_oacc_cache (location_t loc, c_parser *parser)
 {
   tree stmt, clauses;
 
-  clauses = c_parser_omp_var_list_parens (parser, OMP_CLAUSE__CACHE_, NULL);
+  clauses = c_parser_omp_var_list_parens (parser, OMP_CLAUSE__CACHE_, NULL,
+					  C_ORT_ACC);
   clauses = c_finish_omp_clauses (clauses, C_ORT_ACC);
 
   c_parser_skip_to_pragma_eol (parser);
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 276c37f2dc4..c53a64c9a71 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -13829,6 +13829,7 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
   /* 1 if normal/task reduction has been seen, -1 if inscan reduction
      has been seen, -2 if mixed inscan/normal reduction diagnosed.  */
   int reduction_seen = 0;
+  bool oacc_gang_seen = false;
 
   bitmap_obstack_initialize (NULL);
   bitmap_initialize (&generic_head, &bitmap_default_obstack);
@@ -13844,10 +13845,15 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
 
   if (ort & C_ORT_ACC)
     for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
-      if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ASYNC)
-	{
+      switch (OMP_CLAUSE_CODE (c))
+        {
+	case OMP_CLAUSE_ASYNC:
 	  oacc_async = true;
 	  break;
+	case OMP_CLAUSE_GANG:
+	  oacc_gang_seen = true;
+	  break;
+	default:;
 	}
 
   for (pc = &clauses, c = clauses; c ; c = *pc)
@@ -13868,6 +13874,13 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
 	  goto check_dup_generic;
 
 	case OMP_CLAUSE_REDUCTION:
+	  if (oacc_gang_seen && oacc_get_fn_attrib (current_function_decl))
+	    {
+	      error_at (OMP_CLAUSE_LOCATION (c),
+			"gang reduction on an orphan loop");
+	      remove = true;
+	      break;
+	    }
 	  if (reduction_seen == 0)
 	    reduction_seen = OMP_CLAUSE_REDUCTION_INSCAN (c) ? -1 : 1;
 	  else if (reduction_seen != -2
@@ -14029,8 +14042,11 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
 	    }
 	  else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) == error_mark_node)
 	    {
-	      error_at (OMP_CLAUSE_LOCATION (c),
-			"user defined reduction not found for %qE", t);
+	      /* There are no user-defined reductions in OpenACC (as of
+		 2.6).  */
+	      if (ort & C_ORT_OMP)
+		error_at (OMP_CLAUSE_LOCATION (c),
+			  "user defined reduction not found for %qE", t);
 	      remove = true;
 	      break;
 	    }
diff --git a/gcc/cp/ChangeLog.omp b/gcc/cp/ChangeLog.omp
index 881083d3d15..0e08348ed91 100644
--- a/gcc/cp/ChangeLog.omp
+++ b/gcc/cp/ChangeLog.omp
@@ -1,3 +1,22 @@
+2018-12-13  Cesar Philippidis  <cesar@codesourcery.com>
+            Nathan Sidwell  <nathan@acm.org>
+            Julian Brown  <julian@codesourcery.com>
+
+        * parser.c (cp_parser_omp_var_list_no_open):  New c_omp_region_type
+        argument.  Use it to specialize handling of OMP_CLAUSE_REDUCTION for
+        OpenACC.
+	(cp_parser_omp_var_list): Add c_omp_region_type argument. Update call
+	to cp_parser_omp_var_list_parens.
+	(cp_parser_oacc_data_clause): Update call to cp_parser_omp_var_list.
+        (cp_parser_omp_clause_reduction): Change is_omp boolean parameter to
+        c_omp_region_type.  Update call to cp_parser_omp_var_list_no_open.
+        (cp_parser_oacc_all_clauses): Update call to
+        cp_parser_omp_clause_reduction.
+        (cp_parser_omp_all_clauses): Likewise.
+        * semantics.c (finish_omp_reduction_clause): Add c_omp_region_type
+	argument.  Suppress user-defined reduction error for OpenACC.
+	(finish_omp_clauses): Emit an error on orphan OpenACC gang reductions.
+
 2018-10-02  Thomas Schwinge  <thomas@codesourcery.com>
 	    Cesar Philippidis  <cesar@codesourcery.com>
 
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index b22fa8bfac9..6f76d56cd62 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -34191,6 +34191,7 @@ check_no_duplicate_clause (tree clauses, enum omp_clause_code code,
 static tree
 cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
 				tree list, bool *colon,
+				enum c_omp_region_type ort = C_ORT_OMP,
 				bool allow_deref = false)
 {
   cp_token *token;
@@ -34296,7 +34297,8 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
 	    case OMP_CLAUSE_REDUCTION:
 	    case OMP_CLAUSE_IN_REDUCTION:
 	    case OMP_CLAUSE_TASK_REDUCTION:
-	      while (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE))
+	      while ((ort != C_ORT_ACC || kind != OMP_CLAUSE_REDUCTION)
+		     && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE))
 		{
 		  tree low_bound = NULL_TREE, length = NULL_TREE;
 
@@ -34406,10 +34408,11 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
 
 static tree
 cp_parser_omp_var_list (cp_parser *parser, enum omp_clause_code kind, tree list,
+			enum c_omp_region_type ort = C_ORT_OMP,
 			bool allow_deref = false)
 {
   if (cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
-    return cp_parser_omp_var_list_no_open (parser, kind, list, NULL,
+    return cp_parser_omp_var_list_no_open (parser, kind, list, NULL, ort,
 					   allow_deref);
   return list;
 }
@@ -34477,7 +34480,7 @@ cp_parser_oacc_data_clause (cp_parser *parser, pragma_omp_clause c_kind,
       gcc_unreachable ();
     }
   tree nl, c;
-  nl = cp_parser_omp_var_list (parser, OMP_CLAUSE_MAP, list, true);
+  nl = cp_parser_omp_var_list (parser, OMP_CLAUSE_MAP, list, C_ORT_ACC, true);
 
   for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
     OMP_CLAUSE_SET_MAP_KIND (c, kind);
@@ -35654,7 +35657,7 @@ cp_parser_omp_clause_ordered (cp_parser *parser,
 
 static tree
 cp_parser_omp_clause_reduction (cp_parser *parser, enum omp_clause_code kind,
-				bool is_omp, tree list)
+				enum c_omp_region_type ort, tree list)
 {
   enum tree_code code = ERROR_MARK;
   tree nlist, c, id = NULL_TREE;
@@ -35664,7 +35667,7 @@ cp_parser_omp_clause_reduction (cp_parser *parser, enum omp_clause_code kind,
   if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
     return list;
 
-  if (kind == OMP_CLAUSE_REDUCTION && is_omp)
+  if (kind == OMP_CLAUSE_REDUCTION && ort == C_ORT_OMP)
     {
       if (cp_lexer_next_token_is_keyword (parser->lexer, RID_DEFAULT)
 	  && cp_lexer_nth_token_is (parser->lexer, 2, CPP_COMMA))
@@ -35761,8 +35764,7 @@ cp_parser_omp_clause_reduction (cp_parser *parser, enum omp_clause_code kind,
   if (!cp_parser_require (parser, CPP_COLON, RT_COLON))
     goto resync_fail;
 
-  nlist = cp_parser_omp_var_list_no_open (parser, kind, list,
-					  NULL);
+  nlist = cp_parser_omp_var_list_no_open (parser, kind, list, NULL, ort);
   for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c))
     {
       OMP_CLAUSE_REDUCTION_CODE (c) = code;
@@ -37073,7 +37075,7 @@ cp_parser_oacc_all_clauses (cp_parser *parser, omp_clause_mask mask,
 	case PRAGMA_OACC_CLAUSE_REDUCTION:
 	  clauses
 	    = cp_parser_omp_clause_reduction (parser, OMP_CLAUSE_REDUCTION,
-					      false, clauses);
+					      C_ORT_ACC, clauses);
 	  c_name = "reduction";
 	  break;
 	case PRAGMA_OACC_CLAUSE_SEQ:
@@ -37251,7 +37253,7 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask,
 	case PRAGMA_OMP_CLAUSE_IN_REDUCTION:
 	  clauses
 	    = cp_parser_omp_clause_reduction (parser, OMP_CLAUSE_IN_REDUCTION,
-					      true, clauses);
+					      C_ORT_OMP, clauses);
 	  c_name = "in_reduction";
 	  break;
 	case PRAGMA_OMP_CLAUSE_LASTPRIVATE:
@@ -37301,7 +37303,7 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask,
 	case PRAGMA_OMP_CLAUSE_REDUCTION:
 	  clauses
 	    = cp_parser_omp_clause_reduction (parser, OMP_CLAUSE_REDUCTION,
-					      true, clauses);
+					      C_ORT_OMP, clauses);
 	  c_name = "reduction";
 	  break;
 	case PRAGMA_OMP_CLAUSE_SCHEDULE:
@@ -37318,7 +37320,7 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask,
 	  clauses
 	    = cp_parser_omp_clause_reduction (parser,
 					      OMP_CLAUSE_TASK_REDUCTION,
-					      true, clauses);
+					      C_ORT_OMP, clauses);
 	  c_name = "task_reduction";
 	  break;
 	case PRAGMA_OMP_CLAUSE_UNTIED:
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 95281ad5e6d..c12e647a3b2 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -5814,7 +5814,8 @@ find_omp_placeholder_r (tree *tp, int *, void *data)
    Return true if there is some error and the clause should be removed.  */
 
 static bool
-finish_omp_reduction_clause (tree c, bool *need_default_ctor, bool *need_dtor)
+finish_omp_reduction_clause (tree c, enum c_omp_region_type ort,
+			     bool *need_default_ctor, bool *need_dtor)
 {
   tree t = OMP_CLAUSE_DECL (c);
   bool predefined = false;
@@ -6063,9 +6064,11 @@ finish_omp_reduction_clause (tree c, bool *need_default_ctor, bool *need_dtor)
     *need_dtor = true;
   else
     {
-      error_at (OMP_CLAUSE_LOCATION (c),
-		"user defined reduction not found for %qE",
-		omp_clause_printable_decl (t));
+      /* There are no user-defined reductions for OpenACC (as of 2.6).  */
+      if (ort & C_ORT_OMP)
+	error_at (OMP_CLAUSE_LOCATION (c),
+		  "user defined reduction not found for %qE",
+		  omp_clause_printable_decl (t));
       return true;
     }
   if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
@@ -6355,6 +6358,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
   /* 1 if normal/task reduction has been seen, -1 if inscan reduction
      has been seen, -2 if mixed inscan/normal reduction diagnosed.  */
   int reduction_seen = 0;
+  bool oacc_gang_seen = false;
 
   bitmap_obstack_initialize (NULL);
   bitmap_initialize (&generic_head, &bitmap_default_obstack);
@@ -6370,10 +6374,15 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
 
   if (ort & C_ORT_ACC)
     for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
-      if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ASYNC)
-	{
+      switch (OMP_CLAUSE_CODE (c))
+        {
+	case OMP_CLAUSE_ASYNC:
 	  oacc_async = true;
 	  break;
+	case OMP_CLAUSE_GANG:
+	  oacc_gang_seen = true;
+	  break;
+	default:;
 	}
 
   for (pc = &clauses, c = clauses; c ; c = *pc)
@@ -6390,6 +6399,13 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
 	  field_ok = ((ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP);
 	  goto check_dup_generic;
 	case OMP_CLAUSE_REDUCTION:
+	  if (oacc_gang_seen && oacc_get_fn_attrib (current_function_decl))
+	    {
+	      error_at (OMP_CLAUSE_LOCATION (c),
+			"gang reduction on an orphan loop");
+	      remove = true;
+	      break;
+	    }
 	  if (reduction_seen == 0)
 	    reduction_seen = OMP_CLAUSE_REDUCTION_INSCAN (c) ? -1 : 1;
 	  else if (reduction_seen != -2
@@ -8102,7 +8118,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
 	case OMP_CLAUSE_REDUCTION:
 	case OMP_CLAUSE_IN_REDUCTION:
 	case OMP_CLAUSE_TASK_REDUCTION:
-	  if (finish_omp_reduction_clause (c, &need_default_ctor,
+	  if (finish_omp_reduction_clause (c, ort, &need_default_ctor,
 					   &need_dtor))
 	    remove = true;
 	  else
diff --git a/gcc/fortran/ChangeLog.omp b/gcc/fortran/ChangeLog.omp
index 5020b76e682..bcd40d26a09 100644
--- a/gcc/fortran/ChangeLog.omp
+++ b/gcc/fortran/ChangeLog.omp
@@ -1,3 +1,11 @@
+2018-12-13  Cesar Philippidis  <cesar@codesourcery.com>
+            Nathan Sidwell  <nathan@acm.org>
+            Julian Brown  <julian@codesourcery.com>
+
+        * openmp.c (resolve_oacc_loop_blocks): Emit an error on orphan OpenACC
+        gang reductions.
+        * trans-openmp.c (gfc_omp_clause_copy_ctor): Permit reductions.
+
 2018-06-29  Cesar Philippidis  <cesar@codesourcery.com>
 	    James Norris  <jnorris@codesourcery.com>
 
diff --git a/gcc/fortran/openmp.c b/gcc/fortran/openmp.c
index ee2f2129bd2..dbf5122e950 100644
--- a/gcc/fortran/openmp.c
+++ b/gcc/fortran/openmp.c
@@ -6193,6 +6193,18 @@ resolve_oacc_loop_blocks (gfc_code *code)
   if (!oacc_is_loop (code))
     return;
 
+  if (code->op == EXEC_OACC_LOOP
+      && code->ext.omp_clauses->lists[OMP_LIST_REDUCTION]
+      && code->ext.omp_clauses->gang)
+    {
+      fortran_omp_context *c;
+      for (c = omp_current_ctx; c; c = c->previous)
+	if (!oacc_is_loop (c->code))
+	  break;
+      if (c == NULL || !oacc_is_parallel (c->code))
+	gfc_error ("gang reduction on an orphan loop at %L", &code->loc);
+    }
+
   if (code->ext.omp_clauses->tile_list && code->ext.omp_clauses->gang
       && code->ext.omp_clauses->worker && code->ext.omp_clauses->vector)
     gfc_error ("Tiled loop cannot be parallelized across gangs, workers and "
diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c
index 3ce645c2baa..5feb77585cb 100644
--- a/gcc/fortran/trans-openmp.c
+++ b/gcc/fortran/trans-openmp.c
@@ -716,7 +716,8 @@ gfc_omp_clause_copy_ctor (tree clause, tree dest, tree src)
   stmtblock_t block, cond_block;
 
   gcc_assert (OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_FIRSTPRIVATE
-	      || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LINEAR);
+	      || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_LINEAR
+	      || OMP_CLAUSE_CODE (clause) == OMP_CLAUSE_REDUCTION);
 
   if ((! GFC_DESCRIPTOR_TYPE_P (type)
        || GFC_TYPE_ARRAY_AKIND (type) != GFC_ARRAY_ALLOCATABLE)


More information about the Gcc-cvs mailing list