This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [patch] various OpenACC reduction enhancements - FE changes


On Tue, 4 Dec 2018 13:57:24 +0100
Jakub Jelinek <jakub@redhat.com> wrote:

> On Fri, Jun 29, 2018 at 11:22:00AM -0700, Cesar Philippidis wrote:
> > 2018-06-29  Cesar Philippidis  <cesar@codesourcery.com>
> > 	    Nathan Sidwell  <nathan@acm.org>
> > 
> > 	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_omp_clause_reduction): Update call to
> > 	c_parser_omp_variable_list.  Propage OpenACC errors as
> > necessary. (c_parser_oacc_all_clauses): Update call to
> > 	p_parser_omp_clause_reduction.
> > 	(c_parser_omp_all_clauses): Likewise.
> > 	* c-typeck.c (c_finish_omp_clauses): Emit an error on
> > orphan OpenACC gang reductions.
> > 
> > 	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_clause_reduction): Update call to
> > 	cp_parser_omp_variable_list.  Propage OpenACC errors as
> > necessary. (cp_parser_oacc_all_clauses): Update call to
> > 	cp_parser_omp_clause_reduction.
> > 	(cp_parser_omp_all_clauses): Likewise.
> > 	* semantics.c (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 --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
> > index 7a926285f3a..a6f453dae54 100644
> > --- a/gcc/c/c-parser.c
> > +++ b/gcc/c/c-parser.c
> > @@ -965,12 +965,13 @@ class token_pair
> >  
> >    /* Like token_pair::require_close, except that tokens will be
> > skipped until the desired token is found.  An error message is
> > still produced
> > -     if the next token is not as expected.  */
> > +     if the next token is not as expected, unless QUIET is set.  */
> >  
> > -  void skip_until_found_close (c_parser *parser) const
> > +  void skip_until_found_close (c_parser *parser, bool quiet =
> > false) const {
> >      c_parser_skip_until_found (parser, traits_t::close_token_type,
> > -			       traits_t::close_gmsgid, m_open_loc);
> > +			       quiet ? NULL :
> > traits_t::close_gmsgid,
> > +			       m_open_loc);
> >    }  
> 
> I don't like these changes, why do you need them?  C++ FE doesn't
> have such changes either, and it is fine to diagnose missing ) even
> if there was some earlier error.  All other spots which require
> matching parens do it the same.  Please leave those out.

I've removed these bits.

>  static
> tree -c_parser_omp_clause_reduction (c_parser *parser, tree
> list) +c_parser_omp_clause_reduction (c_parser *parser, tree
> list,                                                                                       
> +                              enum c_omp_region_type
> ort)                                                                                         
> 
> Note, the signature is now different, it is ok to replace is_omp
> argument with enum c_omp_region_type if you wish.

I've done as you suggest.

> >  {
> >    location_t clause_loc = c_parser_peek_token (parser)->location;
> > +  bool seen_error = false;
> > +
> >    matching_parens parens;
> >    if (parens.require_open (parser))
> >      {
> > @@ -12855,7 +12876,13 @@ c_parser_omp_clause_reduction (c_parser
> > *parser, tree list) tree nl, c;
> >  
> >  	  nl = c_parser_omp_variable_list (parser, clause_loc,
> > -					   OMP_CLAUSE_REDUCTION,
> > list);
> > +					   OMP_CLAUSE_REDUCTION,
> > list, ort);
> > +	  if (c_parser_peek_token (parser)->type !=
> > CPP_CLOSE_PAREN)
> > +	    {
> > +	      seen_error = true;
> > +	      goto cleanup;
> > +	    }
> > +
> >  	  for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
> >  	    {
> >  	      tree d = OMP_CLAUSE_DECL (c), type;
> > @@ -12891,7 +12918,8 @@ c_parser_omp_clause_reduction (c_parser
> > *parser, tree list) 
> >  	  list = nl;
> >  	}
> > -      parens.skip_until_found_close (parser);
> > +    cleanup:
> > +      parens.skip_until_found_close (parser, seen_error);
> >      }
> >    return list;
> >  }  
> 
> And the above hunks as well.

Removed.

> > @@ -13998,7 +14026,7 @@ c_parser_oacc_all_clauses (c_parser
> > *parser, omp_clause_mask mask, c_name = "private";
> >  	  break;
> >  	case PRAGMA_OACC_CLAUSE_REDUCTION:
> > -	  clauses = c_parser_omp_clause_reduction (parser,
> > clauses);
> > +	  clauses = c_parser_omp_clause_reduction (parser,
> > clauses, C_ORT_ACC); c_name = "reduction";
> >  	  break;
> >  	case PRAGMA_OACC_CLAUSE_SEQ:
> > @@ -14157,7 +14185,7 @@ c_parser_omp_all_clauses (c_parser *parser,
> > omp_clause_mask mask, c_name = "private";
> >  	  break;
> >  	case PRAGMA_OMP_CLAUSE_REDUCTION:
> > -	  clauses = c_parser_omp_clause_reduction (parser,
> > clauses);
> > +	  clauses = c_parser_omp_clause_reduction (parser,
> > clauses, C_ORT_OMP); c_name = "reduction";
> >  	  break;
> >  	case PRAGMA_OMP_CLAUSE_SCHEDULE:  
> 
> Note, there are now also the IN_REDUCTION/TASK_REDUCTION clause cases
> that need adjustment.

Done.

> > diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
> > index 90ae306c99a..944db3fa8be 100644
> > --- a/gcc/c/c-typeck.c
> > +++ b/gcc/c/c-typeck.c
> > @@ -13087,6 +13087,14 @@ c_finish_omp_clauses (tree clauses, enum
> > c_omp_region_type ort) goto check_dup_generic;
> >  
> >  	case OMP_CLAUSE_REDUCTION:
> > +	  if (ort == C_ORT_ACC && oacc_get_fn_attrib
> > (current_function_decl)
> > +	      && omp_find_clause (clauses, OMP_CLAUSE_GANG))  
> 
> This is expensive if there are many clauses, we want to avoid O(n^2)
> behavior.  For C we only have one loop, so just remember in some
> variable whether there are reduction clause(s) that would conflict
> with gang, and in another one whether gang clause has been seen, then
> deal with it at the end if both the bools are true.

There are (now) two loops in the C frontend too -- so I've handled this
the same as C++, below, because there may be multiple reduction clauses
with a "gang" so removing them afterwards (like nogroup_seen) seems
awkward.

> > +	    {
> > +	      error_at (OMP_CLAUSE_LOCATION (c),
> > +			"gang reduction on an orphan loop");
> > +	      remove = true;
> > +	      break;
> > +	    }
> >  	  need_implicitly_determined = true;
> >  	  t = OMP_CLAUSE_DECL (c);
> >  	  if (TREE_CODE (t) == TREE_LIST)  
> 
> > @@ -31668,6 +31669,21 @@ cp_parser_omp_var_list_no_open (cp_parser
> > *parser, enum omp_clause_code kind, /* FALLTHROUGH.  */
> >  	    case OMP_CLAUSE_DEPEND:
> >  	    case OMP_CLAUSE_REDUCTION:
> > +	      if (kind == OMP_CLAUSE_REDUCTION && ort == C_ORT_ACC)
> > +		{
> > +		  switch (cp_lexer_peek_token
> > (parser->lexer)->type)
> > +		    {
> > +		    case CPP_OPEN_PAREN:
> > +		    case CPP_OPEN_SQUARE:
> > +		    case CPP_DOT:
> > +		    case CPP_DEREF:
> > +		      error ("invalid reduction variable");
> > +		      decl = error_mark_node;
> > +		      goto skip_comma;
> > +		    default:;
> > +		      break;
> > +		    }
> > +		}  
> 
> Any reason for the above (ditto in C), rather than just adding
> && ort != C_ORT_ACC to the while loop condition for CPP_OPEN_SQUARE?
> (, . or * after id-expression is like any other unhandled
> characters...

I think the reason was that 'decl' ('t' in the C version) is not set to
error_mark_node if the while loop is skipped, and then the gimplifier
gets confused. I've tried to tackle this in another way, by checking
there aren't any stray characters before the next comma or
close-parenthesis.

I'm not sure if you were objecting to the error message too -- with the
current patch, the user will just get e.g.:

error: expected ')' before '.' token

if they try to use an unsupported type of construct as a reduction
target.

> >  	      while (cp_lexer_next_token_is (parser->lexer,
> > CPP_OPEN_SQUARE)) {
> >  		  tree low_bound = NULL_TREE, length = NULL_TREE;  
> 
> > @@ -33868,7 +33885,7 @@ cp_parser_oacc_all_clauses (cp_parser
> > *parser, omp_clause_mask mask, c_name = "private";
> >  	  break;
> >  	case PRAGMA_OACC_CLAUSE_REDUCTION:
> > -	  clauses = cp_parser_omp_clause_reduction (parser,
> > clauses);
> > +	  clauses = cp_parser_omp_clause_reduction (parser,
> > clauses, C_ORT_ACC); c_name = "reduction";
> >  	  break;
> >  	case PRAGMA_OACC_CLAUSE_SEQ:
> > @@ -34055,7 +34072,7 @@ cp_parser_omp_all_clauses (cp_parser
> > *parser, omp_clause_mask mask, c_name = "private";
> >  	  break;
> >  	case PRAGMA_OMP_CLAUSE_REDUCTION:
> > -	  clauses = cp_parser_omp_clause_reduction (parser,
> > clauses);
> > +	  clauses = cp_parser_omp_clause_reduction (parser,
> > clauses, C_ORT_OMP); c_name = "reduction";
> >  	  break;
> >  	case PRAGMA_OMP_CLAUSE_SCHEDULE:  
> 
> Again, needs adjustement for IN_REDUCTION/TASK_REDUCTION.

Done.

> > diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
> > index c779137da45..177acdd9cc4 100644
> > --- a/gcc/cp/semantics.c
> > +++ b/gcc/cp/semantics.c
> > @@ -5875,6 +5875,14 @@ 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 (ort == C_ORT_ACC && oacc_get_fn_attrib
> > (current_function_decl)
> > +	      && omp_find_clause (clauses, OMP_CLAUSE_GANG))
> > +	    {
> > +	      error_at (OMP_CLAUSE_LOCATION (c),
> > +			"gang reduction on an orphan loop");
> > +	      remove = true;
> > +	      break;
> > +	    }
> >  	  field_ok = ((ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP);
> >  	  t = OMP_CLAUSE_DECL (c);
> >  	  if (TREE_CODE (t) == TREE_LIST)  
> 
> In C++ finish_omp_clauses there are 2 loops, so you can easily just
> remember if OMP_CLAUSE_GANG has been seen in the first loop and
> diagnose this in the second loop only.

Done.

Re-tested with offloading to nvptx, and with updates to the new
testcases (to be posted). OK?

Thanks,

Julian

ChangeLog

2018-xx-xx  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_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-typeck.c (c_finish_omp_clauses): Emit an error on orphan OpenACC
        gang reductions.

        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_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_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.
commit 0fcaa69b46d2661c3b133c42e0ce73693088b04e
Author: Julian Brown <julian@codesourcery.com>
Date:   Wed Dec 12 11:09:29 2018 -0800

    Various OpenACC reduction enhancements - FE changes
    
    2018-xx-xx  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_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-typeck.c (c_finish_omp_clauses): Emit an error on orphan OpenACC
    	gang reductions.
    
    	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_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_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 --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index b875c4f..59a461b 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -11869,7 +11869,8 @@ c_parser_oacc_wait_list (c_parser *parser, location_t clause_loc, tree list)
 static tree
 c_parser_omp_variable_list (c_parser *parser,
 			    location_t clause_loc,
-			    enum omp_clause_code kind, tree list)
+			    enum omp_clause_code kind, tree list,
+			    enum c_omp_region_type ort = C_ORT_OMP)
 {
   auto_vec<c_token> tokens;
   unsigned int tokens_avail = 0;
@@ -12004,7 +12005,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
+		     && c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
 		{
 		  tree low_bound = NULL_TREE, length = NULL_TREE;
 
@@ -12074,6 +12076,10 @@ c_parser_omp_variable_list (c_parser *parser,
 			}
 		    }
 		}
+	      if (ort == C_ORT_ACC
+	          && c_parser_next_token_is_not (parser, CPP_COMMA)
+		  && c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN))
+		t = error_mark_node;
 	      break;
 	    default:
 	      break;
@@ -13446,7 +13452,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;
@@ -13457,7 +13463,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)
@@ -13542,7 +13548,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;
@@ -14847,7 +14854,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:
@@ -14976,7 +14983,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:
@@ -15014,7 +15021,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:
@@ -15028,7 +15035,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:
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 1a89727..a251447 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -13683,6 +13683,7 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
   bool last_iterators_remove = false;
   tree *nogroup_seen = NULL;
   bool reduction_seen = false;
+  bool oacc_gang_seen = false;
 
   bitmap_obstack_initialize (NULL);
   bitmap_initialize (&generic_head, &bitmap_default_obstack);
@@ -13697,10 +13698,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)
@@ -13721,6 +13727,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;
+	    }
 	  reduction_seen = true;
 	  /* FALLTHRU */
 	case OMP_CLAUSE_IN_REDUCTION:
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 8b669a8..71e84ea 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -32111,7 +32111,8 @@ 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)
+				tree list, bool *colon,
+				enum c_omp_region_type ort = C_ORT_OMP)
 {
   cp_token *token;
   bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p;
@@ -32201,7 +32202,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
+		     && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE))
 		{
 		  tree low_bound = NULL_TREE, length = NULL_TREE;
 
@@ -32262,10 +32264,18 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
 		cp_parser_parse_definitely (parser);
 	    }
 
-	  tree u = build_omp_clause (token->location, kind);
-	  OMP_CLAUSE_DECL (u) = decl;
-	  OMP_CLAUSE_CHAIN (u) = list;
-	  list = u;
+	  if (ort == C_ORT_ACC
+	      && cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA)
+	      && cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
+	    decl = error_mark_node;
+
+	  if (decl != error_mark_node)
+	    {
+	      tree u = build_omp_clause (token->location, kind);
+	      OMP_CLAUSE_DECL (u) = decl;
+	      OMP_CLAUSE_CHAIN (u) = list;
+	      list = u;
+	    }
 	}
       else
 	list = tree_cons (decl, NULL_TREE, list);
@@ -33442,7 +33452,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;
@@ -33452,7 +33462,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))
@@ -33553,8 +33563,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;
@@ -34798,7 +34807,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:
@@ -34948,7 +34957,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:
@@ -34992,7 +35001,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:
@@ -35009,7 +35018,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 c1240cc..fc63e3c 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -6055,6 +6055,7 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
   tree last_iterators = NULL_TREE;
   bool last_iterators_remove = false;
   bool reduction_seen = false;
+  bool oacc_gang_seen = false;
 
   bitmap_obstack_initialize (NULL);
   bitmap_initialize (&generic_head, &bitmap_default_obstack);
@@ -6069,10 +6070,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)
@@ -6089,6 +6095,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;
+	    }
 	  reduction_seen = true;
 	  /* FALLTHRU */
 	case OMP_CLAUSE_IN_REDUCTION:
diff --git a/gcc/fortran/openmp.c b/gcc/fortran/openmp.c
index 261a54a..ffa04e6 100644
--- a/gcc/fortran/openmp.c
+++ b/gcc/fortran/openmp.c
@@ -5843,6 +5843,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 bf3f469..fbe0d3c 100644
--- a/gcc/fortran/trans-openmp.c
+++ b/gcc/fortran/trans-openmp.c
@@ -564,7 +564,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)

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]