diff options
author | Tamar Christina <tamar.christina@arm.com> | 2023-08-04 13:50:53 +0100 |
---|---|---|
committer | Tamar Christina <tamar.christina@arm.com> | 2023-08-04 13:50:53 +0100 |
commit | 73b98860767ac03aa31ad4ca8b73f40484bd7562 (patch) | |
tree | 2eadd043502b52f267c5b0fe449c57596c4a5acc /gcc/cp/parser.cc | |
parent | 451391a6477f5b012faeca42cdba1bfb8e6eecc0 (diff) | |
download | gcc-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.cc | 149 |
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; } |