aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/parser.cc
diff options
context:
space:
mode:
authorTamar Christina <tamar.christina@arm.com>2023-08-04 13:50:53 +0100
committerTamar Christina <tamar.christina@arm.com>2023-08-04 13:50:53 +0100
commit73b98860767ac03aa31ad4ca8b73f40484bd7562 (patch)
tree2eadd043502b52f267c5b0fe449c57596c4a5acc /gcc/cp/parser.cc
parent451391a6477f5b012faeca42cdba1bfb8e6eecc0 (diff)
downloadgcc-73b98860767ac03aa31ad4ca8b73f40484bd7562.zip
gcc-73b98860767ac03aa31ad4ca8b73f40484bd7562.tar.gz
gcc-73b98860767ac03aa31ad4ca8b73f40484bd7562.tar.bz2
frontend: Add novector C++ pragma
FORTRAN currently has a pragma NOVECTOR for indicating that vectorization should not be applied to a particular loop. ICC/ICX also has such a pragma for C and C++ called #pragma novector. As part of this patch series I need a way to easily turn off vectorization of particular loops, particularly for testsuite reasons. This patch proposes a #pragma GCC novector that does the same for C++ as gfortan does for FORTRAN and what ICX/ICX does for C++. I added only some basic tests here, but the next patch in the series uses this in the testsuite in about ~800 tests. gcc/cp/ChangeLog: * cp-tree.h (RANGE_FOR_NOVECTOR): New. (cp_convert_range_for, finish_while_stmt_cond, finish_do_stmt, finish_for_cond): Add novector param. * init.cc (build_vec_init): Default novector to false. * method.cc (build_comparison_op): Likewise. * parser.cc (cp_parser_statement): Likewise. (cp_parser_for, cp_parser_c_for, cp_parser_range_for, cp_convert_range_for, cp_parser_iteration_statement, cp_parser_omp_for_loop, cp_parser_pragma): Support novector. (cp_parser_pragma_novector): New. * pt.cc (tsubst_expr): Likewise. * semantics.cc (finish_while_stmt_cond, finish_do_stmt, finish_for_cond): Likewise. gcc/ChangeLog: * doc/extend.texi: Document it. gcc/testsuite/ChangeLog: * g++.dg/vect/vect.exp (support vect- prefix). * g++.dg/vect/vect-novector-pragma.cc: New test.
Diffstat (limited to 'gcc/cp/parser.cc')
-rw-r--r--gcc/cp/parser.cc149
1 files changed, 89 insertions, 60 deletions
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 2e24586..ba15a09 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -2333,15 +2333,15 @@ static tree cp_parser_selection_statement
static tree cp_parser_condition
(cp_parser *);
static tree cp_parser_iteration_statement
- (cp_parser *, bool *, bool, unsigned short);
+ (cp_parser *, bool *, bool, unsigned short, bool);
static bool cp_parser_init_statement
(cp_parser *, tree *decl);
static tree cp_parser_for
- (cp_parser *, bool, unsigned short);
+ (cp_parser *, bool, unsigned short, bool);
static tree cp_parser_c_for
- (cp_parser *, tree, tree, bool, unsigned short);
+ (cp_parser *, tree, tree, bool, unsigned short, bool);
static tree cp_parser_range_for
- (cp_parser *, tree, tree, tree, bool, unsigned short, bool);
+ (cp_parser *, tree, tree, tree, bool, unsigned short, bool, bool);
static void do_range_for_auto_deduction
(tree, tree, tree, unsigned int);
static tree cp_parser_perform_range_for_lookup
@@ -12422,7 +12422,8 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
case RID_DO:
case RID_FOR:
std_attrs = process_stmt_hotness_attribute (std_attrs, attrs_loc);
- statement = cp_parser_iteration_statement (parser, if_p, false, 0);
+ statement = cp_parser_iteration_statement (parser, if_p, false, 0,
+ false);
break;
case RID_BREAK:
@@ -13602,7 +13603,8 @@ cp_parser_condition (cp_parser* parser)
not included. */
static tree
-cp_parser_for (cp_parser *parser, bool ivdep, unsigned short unroll)
+cp_parser_for (cp_parser *parser, bool ivdep, unsigned short unroll,
+ bool novector)
{
tree init, scope, decl;
bool is_range_for;
@@ -13632,14 +13634,14 @@ cp_parser_for (cp_parser *parser, bool ivdep, unsigned short unroll)
if (is_range_for)
return cp_parser_range_for (parser, scope, init, decl, ivdep, unroll,
- false);
+ novector, false);
else
- return cp_parser_c_for (parser, scope, init, ivdep, unroll);
+ return cp_parser_c_for (parser, scope, init, ivdep, unroll, novector);
}
static tree
cp_parser_c_for (cp_parser *parser, tree scope, tree init, bool ivdep,
- unsigned short unroll)
+ unsigned short unroll, bool novector)
{
/* Normal for loop */
tree condition = NULL_TREE;
@@ -13666,7 +13668,7 @@ cp_parser_c_for (cp_parser *parser, tree scope, tree init, bool ivdep,
"%<GCC unroll%> pragma");
condition = error_mark_node;
}
- finish_for_cond (condition, stmt, ivdep, unroll);
+ finish_for_cond (condition, stmt, ivdep, unroll, novector);
/* Look for the `;'. */
cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
@@ -13690,7 +13692,8 @@ cp_parser_c_for (cp_parser *parser, tree scope, tree init, bool ivdep,
static tree
cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl,
- bool ivdep, unsigned short unroll, bool is_omp)
+ bool ivdep, unsigned short unroll, bool novector,
+ bool is_omp)
{
tree stmt, range_expr;
auto_vec <cxx_binding *, 16> bindings;
@@ -13766,6 +13769,8 @@ cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl,
RANGE_FOR_IVDEP (stmt) = 1;
if (unroll)
RANGE_FOR_UNROLL (stmt) = build_int_cst (integer_type_node, unroll);
+ if (novector)
+ RANGE_FOR_NOVECTOR (stmt) = 1;
finish_range_for_decl (stmt, range_decl, range_expr);
if (!type_dependent_expression_p (range_expr)
/* do_auto_deduction doesn't mess with template init-lists. */
@@ -13778,7 +13783,7 @@ cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl,
stmt = begin_for_stmt (scope, init);
stmt = cp_convert_range_for (stmt, range_decl, range_expr,
decomp_first_name, decomp_cnt, ivdep,
- unroll);
+ unroll, novector);
}
return stmt;
}
@@ -13956,7 +13961,7 @@ warn_for_range_copy (tree decl, tree expr)
tree
cp_convert_range_for (tree statement, tree range_decl, tree range_expr,
tree decomp_first_name, unsigned int decomp_cnt,
- bool ivdep, unsigned short unroll)
+ bool ivdep, unsigned short unroll, bool novector)
{
tree begin, end;
tree iter_type, begin_expr, end_expr;
@@ -14016,7 +14021,7 @@ cp_convert_range_for (tree statement, tree range_decl, tree range_expr,
begin, ERROR_MARK,
end, ERROR_MARK,
NULL_TREE, NULL, tf_warning_or_error);
- finish_for_cond (condition, statement, ivdep, unroll);
+ finish_for_cond (condition, statement, ivdep, unroll, novector);
/* The new increment expression. */
expression = finish_unary_op_expr (input_location,
@@ -14183,7 +14188,7 @@ cp_parser_range_for_member_function (tree range, tree identifier)
static tree
cp_parser_iteration_statement (cp_parser* parser, bool *if_p, bool ivdep,
- unsigned short unroll)
+ unsigned short unroll, bool novector)
{
cp_token *token;
enum rid keyword;
@@ -14217,7 +14222,7 @@ cp_parser_iteration_statement (cp_parser* parser, bool *if_p, bool ivdep,
parens.require_open (parser);
/* Parse the condition. */
condition = cp_parser_condition (parser);
- finish_while_stmt_cond (condition, statement, ivdep, unroll);
+ finish_while_stmt_cond (condition, statement, ivdep, unroll, novector);
/* Look for the `)'. */
parens.require_close (parser);
/* Parse the dependent statement. */
@@ -14252,7 +14257,7 @@ cp_parser_iteration_statement (cp_parser* parser, bool *if_p, bool ivdep,
/* Parse the expression. */
expression = cp_parser_expression (parser);
/* We're done with the do-statement. */
- finish_do_stmt (expression, statement, ivdep, unroll);
+ finish_do_stmt (expression, statement, ivdep, unroll, novector);
/* Look for the `)'. */
parens.require_close (parser);
/* Look for the `;'. */
@@ -14266,7 +14271,7 @@ cp_parser_iteration_statement (cp_parser* parser, bool *if_p, bool ivdep,
matching_parens parens;
parens.require_open (parser);
- statement = cp_parser_for (parser, ivdep, unroll);
+ statement = cp_parser_for (parser, ivdep, unroll, novector);
/* Look for the `)'. */
parens.require_close (parser);
@@ -43828,7 +43833,7 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
cp_parser_require (parser, CPP_COLON, RT_COLON);
init = cp_parser_range_for (parser, NULL_TREE, NULL_TREE, decl,
- false, 0, true);
+ false, 0, false, true);
cp_convert_omp_range_for (this_pre_body, for_block, decl,
orig_decl, init, orig_init,
@@ -49320,6 +49325,15 @@ cp_parser_pragma_unroll (cp_parser *parser, cp_token *pragma_tok)
return unroll;
}
+/* Parse a pragma GCC novector. */
+
+static bool
+cp_parser_pragma_novector (cp_parser *parser, cp_token *pragma_tok)
+{
+ cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+ return true;
+}
+
/* Normal parsing of a pragma token. Here we can (and must) use the
regular lexer. */
@@ -49625,58 +49639,73 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p)
break;
case PRAGMA_IVDEP:
+ case PRAGMA_UNROLL:
+ case PRAGMA_NOVECTOR:
{
- if (context == pragma_external)
+ bool ivdep;
+ unsigned short unroll = 0;
+ bool novector = false;
+ const char *pragma_str;
+
+ switch (id)
{
- error_at (pragma_tok->location,
- "%<#pragma GCC ivdep%> must be inside a function");
+ case PRAGMA_IVDEP:
+ pragma_str = "ivdep";
break;
- }
- const bool ivdep = cp_parser_pragma_ivdep (parser, pragma_tok);
- unsigned short unroll;
- cp_token *tok = cp_lexer_peek_token (the_parser->lexer);
- if (tok->type == CPP_PRAGMA
- && cp_parser_pragma_kind (tok) == PRAGMA_UNROLL)
- {
- tok = cp_lexer_consume_token (parser->lexer);
- unroll = cp_parser_pragma_unroll (parser, tok);
- tok = cp_lexer_peek_token (the_parser->lexer);
- }
- else
- unroll = 0;
- if (tok->type != CPP_KEYWORD
- || (tok->keyword != RID_FOR
- && tok->keyword != RID_WHILE
- && tok->keyword != RID_DO))
- {
- cp_parser_error (parser, "for, while or do statement expected");
- return false;
- }
- cp_parser_iteration_statement (parser, if_p, ivdep, unroll);
- return true;
- }
+ case PRAGMA_UNROLL:
+ pragma_str = "unroll";
+ break;
+ case PRAGMA_NOVECTOR:
+ pragma_str = "novector";
+ break;
+ default:
+ gcc_unreachable ();
+ }
- case PRAGMA_UNROLL:
- {
if (context == pragma_external)
{
error_at (pragma_tok->location,
- "%<#pragma GCC unroll%> must be inside a function");
+ "%<#pragma GCC %s%> must be inside a function",
+ pragma_str);
break;
}
- const unsigned short unroll
- = cp_parser_pragma_unroll (parser, pragma_tok);
- bool ivdep;
- cp_token *tok = cp_lexer_peek_token (the_parser->lexer);
- if (tok->type == CPP_PRAGMA
- && cp_parser_pragma_kind (tok) == PRAGMA_IVDEP)
+
+ cp_token *tok = pragma_tok;
+ bool has_more = true;
+ do
{
- tok = cp_lexer_consume_token (parser->lexer);
- ivdep = cp_parser_pragma_ivdep (parser, tok);
+ switch (cp_parser_pragma_kind (tok))
+ {
+ case PRAGMA_IVDEP:
+ {
+ if (tok != pragma_tok)
+ tok = cp_lexer_consume_token (parser->lexer);
+ ivdep = cp_parser_pragma_ivdep (parser, tok);
+ break;
+ }
+ case PRAGMA_UNROLL:
+ {
+ if (tok != pragma_tok)
+ tok = cp_lexer_consume_token (parser->lexer);
+ unroll = cp_parser_pragma_unroll (parser, tok);
+ break;
+ }
+ case PRAGMA_NOVECTOR:
+ {
+ if (tok != pragma_tok)
+ tok = cp_lexer_consume_token (parser->lexer);
+ novector = cp_parser_pragma_novector (parser, tok);
+ break;
+ }
+ default:
+ has_more = false;
+ break;
+ }
tok = cp_lexer_peek_token (the_parser->lexer);
+ has_more = has_more && tok->type == CPP_PRAGMA;
}
- else
- ivdep = false;
+ while (has_more);
+
if (tok->type != CPP_KEYWORD
|| (tok->keyword != RID_FOR
&& tok->keyword != RID_WHILE
@@ -49685,7 +49714,7 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p)
cp_parser_error (parser, "for, while or do statement expected");
return false;
}
- cp_parser_iteration_statement (parser, if_p, ivdep, unroll);
+ cp_parser_iteration_statement (parser, if_p, ivdep, unroll, novector);
return true;
}