diff mbox

[OpenACC] num_gangs, num_workers and vector_length in c++

Message ID 5632A573.80002@codesourcery.com
State New
Headers show

Commit Message

Cesar Philippidis Oct. 29, 2015, 11:02 p.m. UTC
I noticed that num_gangs, num_workers and vector_length are parsed in
somewhat insistent ways in the c++ FE. Both vector_length and num_gangs
bail out whenever as soon as they detect errors, whereas num_workers
does not. Besides for that, they are also checking for integral
expressions as the arguments are scanned instead of deferring that check
to finish_omp_clauses. That check will cause ICEs when template
arguments are used when we add support for template arguments later on.

Rather than fix each function individually, I've consolidated them into
a single cp_parser_oacc_positive_int_clause function. While this
function could be extended to support openmp clauses which accept an
integer expression argument, like num_threads, I've decided to leave
those as-is since there are no known problems with those functions at
this moment.

It this OK for trunk? I've regression tested and bootstrapped on
x86_64-linux.

Cesar

Comments

Jakub Jelinek Oct. 30, 2015, 1:37 p.m. UTC | #1
On Thu, Oct 29, 2015 at 04:02:11PM -0700, Cesar Philippidis wrote:
> I noticed that num_gangs, num_workers and vector_length are parsed in
> somewhat insistent ways in the c++ FE. Both vector_length and num_gangs
> bail out whenever as soon as they detect errors, whereas num_workers
> does not. Besides for that, they are also checking for integral
> expressions as the arguments are scanned instead of deferring that check
> to finish_omp_clauses. That check will cause ICEs when template
> arguments are used when we add support for template arguments later on.
> 
> Rather than fix each function individually, I've consolidated them into
> a single cp_parser_oacc_positive_int_clause function. While this
> function could be extended to support openmp clauses which accept an
> integer expression argument, like num_threads, I've decided to leave
> those as-is since there are no known problems with those functions at
> this moment.

First question is what int-expr in OpenACC actually stands for (but I'll
have to raise similar question for OpenMP too).

Previously you were using cp_parser_condition, which is clearly undesirable
in this case, it allows e.g.
num_gangs (int a = 5)
but the question is if
num_gangs (5, 6)
is valid and stands for (5, 6) expression, then it should use
cp_parser_expression, or if you want to error on it, then you should use
cp_parser_assignment_expression.
From quick skimming of the (now removed) C/C++ Grammar Appendix in OpenMP,
I believe all the places where expression or scalar-expression is used
in the grammar are meant to be cp_parser_expression cases (except
expression-list used in UDRs which stands for normal C++ expression-list
non-terminal), so clearly I need to fix up omp_clause_{if,final} to call
cp_parser_expression instead of cp_parser_condition, and the various
OpenMP clauses that use cp_parser_assignment_expression to instead use
cp_parser_expression.  Say schedule(static, 3, 6) should be valid IMHO.
But, in OpenMP expression or scalar-expression in the grammar is never
followed by , or optional , while in OpenACC grammar clearly is (e.g. for
the gang clause).
If OpenACC wants something different, clearly you can't share the parsing
routines between say num_tasks and num_workers.

Another thing is what Jason as C++ maintainer wants, it is nice to get rid
of some code redundancies, on the other side the fact that there is one
function per non-terminal in the grammar is also quite nice property.
I know I've violated this a few times too.

Next question is, why do you call it cp_parser_oacc_positive_int_clause
when the parsing function actually doesn't verify neither the positive nor
the int properties (and it should not), so perhaps it should just reflect
in the name that it is a clause with assignment? expression.
Or, see the previous paragraph, have a helper that does that and then
have a separate function for each clause kind that calls those with the
right arguments.

	Jakub
Cesar Philippidis Oct. 30, 2015, 2:42 p.m. UTC | #2
On 10/30/2015 06:37 AM, Jakub Jelinek wrote:
> On Thu, Oct 29, 2015 at 04:02:11PM -0700, Cesar Philippidis wrote:
>> I noticed that num_gangs, num_workers and vector_length are parsed in
>> somewhat insistent ways in the c++ FE. Both vector_length and num_gangs
>> bail out whenever as soon as they detect errors, whereas num_workers
>> does not. Besides for that, they are also checking for integral
>> expressions as the arguments are scanned instead of deferring that check
>> to finish_omp_clauses. That check will cause ICEs when template
>> arguments are used when we add support for template arguments later on.
>>
>> Rather than fix each function individually, I've consolidated them into
>> a single cp_parser_oacc_positive_int_clause function. While this
>> function could be extended to support openmp clauses which accept an
>> integer expression argument, like num_threads, I've decided to leave
>> those as-is since there are no known problems with those functions at
>> this moment.
> 
> First question is what int-expr in OpenACC actually stands for (but I'll
> have to raise similar question for OpenMP too).
> 
> Previously you were using cp_parser_condition, which is clearly undesirable
> in this case, it allows e.g.
> num_gangs (int a = 5)
> but the question is if
> num_gangs (5, 6)
> is valid and stands for (5, 6) expression, then it should use
> cp_parser_expression, or if you want to error on it, then you should use
> cp_parser_assignment_expression.

The openacc spec doesn't actually define int-expr, but we take to me
mean a single integral value. In general, the openacc spec uses the term
list to describe comma separated expressions. So we've been assuming
that expr cannot contain commas. Besides, for num_gangs, num_workers and
vector_length it doesn't make sense to accept more than one value. A
construct can accept one than one of those clauses, but they'd have to
be associated with a different device_type.

> From quick skimming of the (now removed) C/C++ Grammar Appendix in OpenMP,
> I believe all the places where expression or scalar-expression is used
> in the grammar are meant to be cp_parser_expression cases (except
> expression-list used in UDRs which stands for normal C++ expression-list
> non-terminal), so clearly I need to fix up omp_clause_{if,final} to call
> cp_parser_expression instead of cp_parser_condition, and the various
> OpenMP clauses that use cp_parser_assignment_expression to instead use
> cp_parser_expression.  Say schedule(static, 3, 6) should be valid IMHO.
> But, in OpenMP expression or scalar-expression in the grammar is never
> followed by , or optional , while in OpenACC grammar clearly is (e.g. for
> the gang clause).
> If OpenACC wants something different, clearly you can't share the parsing
> routines between say num_tasks and num_workers.

So num_threads, num_tasks, grainsize, priority, hint, num_teams,
thread_limit should all accept comma-separated lists?

> Another thing is what Jason as C++ maintainer wants, it is nice to get rid
> of some code redundancies, on the other side the fact that there is one
> function per non-terminal in the grammar is also quite nice property.
> I know I've violated this a few times too.
> 
> Next question is, why do you call it cp_parser_oacc_positive_int_clause
> when the parsing function actually doesn't verify neither the positive nor
> the int properties (and it should not), so perhaps it should just reflect
> in the name that it is a clause with assignment? expression.
> Or, see the previous paragraph, have a helper that does that and then
> have a separate function for each clause kind that calls those with the
> right arguments.

That name had some legacy from the c FE in gomp-4_0-branch which the
function was inherited from. On one hand, it doesn't make sense to allow
negative integer values for those clauses, but at the same time, those
values aren't checked during scanning. Maybe it should be renamed
cp_parser_oacc_single_int_clause instead?

If you like, I could make a more general
cp_parser_omp_generic_expression that has a scan_list argument so that
it can be used for both general expressions and assignment-expressions.
That way it can be used for both omp and oacc clauses of the form 'foo (
expression )'.

What's your preference?

Thanks,
Cesar
Jakub Jelinek Oct. 30, 2015, 5:05 p.m. UTC | #3
On Fri, Oct 30, 2015 at 07:42:39AM -0700, Cesar Philippidis wrote:
> The openacc spec doesn't actually define int-expr, but we take to me
> mean a single integral value. In general, the openacc spec uses the term
> list to describe comma separated expressions. So we've been assuming

So does OpenMP use *-list, except one place in the grammar where
expression-list is used, but that is to describe function call arguments 
and the C++ expression-list non-terminal is essentially
{assignment-expression}-list.

> that expr cannot contain commas. Besides, for num_gangs, num_workers and
> vector_length it doesn't make sense to accept more than one value. A

Well, the comma expression are not a way to supply two values, but to
evaluate some side-effects before evaluating the expression you want.

> > From quick skimming of the (now removed) C/C++ Grammar Appendix in OpenMP,
> > I believe all the places where expression or scalar-expression is used
> > in the grammar are meant to be cp_parser_expression cases (except
> > expression-list used in UDRs which stands for normal C++ expression-list
> > non-terminal), so clearly I need to fix up omp_clause_{if,final} to call
> > cp_parser_expression instead of cp_parser_condition, and the various
> > OpenMP clauses that use cp_parser_assignment_expression to instead use
> > cp_parser_expression.  Say schedule(static, 3, 6) should be valid IMHO.
> > But, in OpenMP expression or scalar-expression in the grammar is never
> > followed by , or optional , while in OpenACC grammar clearly is (e.g. for
> > the gang clause).
> > If OpenACC wants something different, clearly you can't share the parsing
> > routines between say num_tasks and num_workers.
> 
> So num_threads, num_tasks, grainsize, priority, hint, num_teams,
> thread_limit should all accept comma-separated lists?

They accept expression, which is e.g. for C++:
expression:
	assignment-expression
	expression , assignment-expression

> 
> > Another thing is what Jason as C++ maintainer wants, it is nice to get rid
> > of some code redundancies, on the other side the fact that there is one
> > function per non-terminal in the grammar is also quite nice property.
> > I know I've violated this a few times too.

> That name had some legacy from the c FE in gomp-4_0-branch which the
> function was inherited from. On one hand, it doesn't make sense to allow
> negative integer values for those clauses, but at the same time, those
> values aren't checked during scanning. Maybe it should be renamed
> cp_parser_oacc_single_int_clause instead?

That is better.

> If you like, I could make a more general
> cp_parser_omp_generic_expression that has a scan_list argument so that
> it can be used for both general expressions and assignment-expressions.
> That way it can be used for both omp and oacc clauses of the form 'foo (
> expression )'.

No, that will only confuse readers of the parser.  After all, the code to
parse an expression argument of a clause is not that large.
So, either cp_parser_oacc_single_int_clause or just keeping the old separate
parsing functions, just remove the cruft from those (testing the type,
using cp_parser_condition instead of cp_parser_assignment_expression) is ok
with me.  Please ping Jason on what he prefers from those two.

	Jakub
diff mbox

Patch

2015-10-29  Cesar Philippidis  <cesar@codesourcery.com>

	gcc/cp/
	* parser.c (cp_parser_oacc_positive_int_clause): New function.
	(cp_parser_oacc_clause_vector_length): Delete.
	(cp_parser_omp_clause_num_gangs): Delete.
	(cp_parser_omp_clause_num_workers): Delete.
	(cp_parser_oacc_all_clauses): Use cp_parser_oacc_positive_int_clause
	to handle OMP_CLAUSE_{NUM_GANGS,NUM_WORKERS,VECTOR_LENGTH}.

diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index c8f8b3d..b1172e7 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -29603,6 +29603,39 @@  cp_parser_oacc_simple_clause (cp_parser * /* parser  */,
   return c;
 }
 
+ /* OpenACC:
+   num_gangs ( expression )
+   num_workers ( expression )
+   vector_length ( expression )  */
+
+static tree
+cp_parser_oacc_positive_int_clause (cp_parser *parser, omp_clause_code code,
+				    const char *str, tree list)
+{
+  location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+    return list;
+
+  tree t = cp_parser_assignment_expression (parser, NULL, false, false);
+
+  if (t == error_mark_node
+      || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+    {
+      cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+					     /*or_comma=*/false,
+					     /*consume_paren=*/true);
+      return list;
+    }
+
+  check_no_duplicate_clause (list, code, str, loc);
+
+  tree c = build_omp_clause (loc, code);
+  OMP_CLAUSE_OPERAND (c, 0) = t;
+  OMP_CLAUSE_CHAIN (c) = list;
+  return c;
+}
+
 /* OpenACC:
 
     gang [( gang-arg-list )]
@@ -29726,45 +29759,6 @@  cp_parser_oacc_shape_clause (cp_parser *parser, omp_clause_code kind,
   return list;
 }
 
-/* OpenACC:
-   vector_length ( expression ) */
-
-static tree
-cp_parser_oacc_clause_vector_length (cp_parser *parser, tree list)
-{
-  tree t, c;
-  location_t location = cp_lexer_peek_token (parser->lexer)->location;
-  bool error = false;
-
-  if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
-    return list;
-
-  t = cp_parser_condition (parser);
-  if (t == error_mark_node || !INTEGRAL_TYPE_P (TREE_TYPE (t)))
-    {
-      error_at (location, "expected positive integer expression");
-      error = true;
-    }
-
-  if (error || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
-    {
-      cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
-					   /*or_comma=*/false,
-					   /*consume_paren=*/true);
-      return list;
-    }
-
-  check_no_duplicate_clause (list, OMP_CLAUSE_VECTOR_LENGTH, "vector_length",
-			     location);
-
-  c = build_omp_clause (location, OMP_CLAUSE_VECTOR_LENGTH);
-  OMP_CLAUSE_VECTOR_LENGTH_EXPR (c) = t;
-  OMP_CLAUSE_CHAIN (c) = list;
-  list = c;
-
-  return list;
-}
-
 /* OpenACC 2.0
    Parse wait clause or directive parameters.  */
 
@@ -30143,42 +30137,6 @@  cp_parser_omp_clause_nowait (cp_parser * /*parser*/,
   return c;
 }
 
-/* OpenACC:
-   num_gangs ( expression ) */
-
-static tree
-cp_parser_omp_clause_num_gangs (cp_parser *parser, tree list)
-{
-  tree t, c;
-  location_t location = cp_lexer_peek_token (parser->lexer)->location;
-
-  if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
-    return list;
-
-  t = cp_parser_condition (parser);
-
-  if (t == error_mark_node
-      || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
-    cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
-					   /*or_comma=*/false,
-					   /*consume_paren=*/true);
-
-  if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
-    {
-      error_at (location, "expected positive integer expression");
-      return list;
-    }
-
-  check_no_duplicate_clause (list, OMP_CLAUSE_NUM_GANGS, "num_gangs", location);
-
-  c = build_omp_clause (location, OMP_CLAUSE_NUM_GANGS);
-  OMP_CLAUSE_NUM_GANGS_EXPR (c) = t;
-  OMP_CLAUSE_CHAIN (c) = list;
-  list = c;
-
-  return list;
-}
-
 /* OpenMP 2.5:
    num_threads ( expression ) */
 
@@ -30387,43 +30345,6 @@  cp_parser_omp_clause_defaultmap (cp_parser *parser, tree list,
   return list;
 }
 
-/* OpenACC:
-   num_workers ( expression ) */
-
-static tree
-cp_parser_omp_clause_num_workers (cp_parser *parser, tree list)
-{
-  tree t, c;
-  location_t location = cp_lexer_peek_token (parser->lexer)->location;
-
-  if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
-    return list;
-
-  t = cp_parser_condition (parser);
-
-  if (t == error_mark_node
-      || !cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
-    cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
-					   /*or_comma=*/false,
-					   /*consume_paren=*/true);
-
-  if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
-    {
-      error_at (location, "expected positive integer expression");
-      return list;
-    }
-
-  check_no_duplicate_clause (list, OMP_CLAUSE_NUM_WORKERS, "num_gangs",
-								location);
-
-  c = build_omp_clause (location, OMP_CLAUSE_NUM_WORKERS);
-  OMP_CLAUSE_NUM_WORKERS_EXPR (c) = t;
-  OMP_CLAUSE_CHAIN (c) = list;
-  list = c;
-
-  return list;
-}
-
 /* OpenMP 2.5:
    ordered
 
@@ -31435,6 +31356,7 @@  cp_parser_oacc_all_clauses (cp_parser *parser, omp_clause_mask mask,
     {
       location_t here;
       pragma_omp_clause c_kind;
+      omp_clause_code code;
       const char *c_name;
       tree prev = clauses;
 
@@ -31501,12 +31423,16 @@  cp_parser_oacc_all_clauses (cp_parser *parser, omp_clause_mask mask,
 	  c_name = "if";
 	  break;
 	case PRAGMA_OACC_CLAUSE_NUM_GANGS:
-	  clauses = cp_parser_omp_clause_num_gangs (parser, clauses);
+	  code = OMP_CLAUSE_NUM_GANGS;
 	  c_name = "num_gangs";
+	  clauses = cp_parser_oacc_positive_int_clause (parser, code,
+							c_name, clauses);
 	  break;
 	case PRAGMA_OACC_CLAUSE_NUM_WORKERS:
-	  clauses = cp_parser_omp_clause_num_workers (parser, clauses);
 	  c_name = "num_workers";
+	  code = OMP_CLAUSE_NUM_WORKERS;
+	  clauses = cp_parser_oacc_positive_int_clause (parser, code,
+							c_name, clauses);
 	  break;
 	case PRAGMA_OACC_CLAUSE_PRESENT:
 	  clauses = cp_parser_oacc_data_clause (parser, c_kind, clauses);
@@ -31547,8 +31473,10 @@  cp_parser_oacc_all_clauses (cp_parser *parser, omp_clause_mask mask,
 						 c_name, clauses);
 	  break;
 	case PRAGMA_OACC_CLAUSE_VECTOR_LENGTH:
-	  clauses = cp_parser_oacc_clause_vector_length (parser, clauses);
 	  c_name = "vector_length";
+	  code = OMP_CLAUSE_VECTOR_LENGTH;
+	  clauses = cp_parser_oacc_positive_int_clause (parser, code,
+							c_name, clauses);
 	  break;
 	case PRAGMA_OACC_CLAUSE_WAIT:
 	  clauses = cp_parser_oacc_clause_wait (parser, clauses);