From: Jason Merrill <jason@redhat.com>
To: Tamar Christina <Tamar.Christina@arm.com>,
"gcc-patches@gcc.gnu.org" <gcc-patches@gcc.gnu.org>
Cc: nd <nd@arm.com>, "nathan@acm.org" <nathan@acm.org>
Subject: Re: [PATCH 1/2][frontend] Add novector C++ pragma
Date: Wed, 26 Jul 2023 16:52:26 -0400 [thread overview]
Message-ID: <e1d0e4ed-f517-4186-7db5-12445ce0aead@redhat.com> (raw)
In-Reply-To: <VI1PR08MB53256E75FC1DE820BA64FC0DFF00A@VI1PR08MB5325.eurprd08.prod.outlook.com>
On 7/26/23 15:32, Tamar Christina wrote:
>>> +
>>> + cp_token *tok = pragma_tok;
>>> +
>>> + do
>>> {
>>> - tok = cp_lexer_consume_token (parser->lexer);
>>> - ivdep = cp_parser_pragma_ivdep (parser, tok);
>>> - tok = cp_lexer_peek_token (the_parser->lexer);
>>> + 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);
>>> + tok = cp_lexer_peek_token (the_parser->lexer);
>>> + break;
>>> + }
>>> + case PRAGMA_UNROLL:
>>> + {
>>> + if (tok != pragma_tok)
>>> + tok = cp_lexer_consume_token (parser->lexer);
>>> + unroll = cp_parser_pragma_unroll (parser, tok);
>>> + tok = cp_lexer_peek_token (the_parser->lexer);
>>> + break;
>>> + }
>>> + case PRAGMA_NOVECTOR:
>>> + {
>>> + if (tok != pragma_tok)
>>> + tok = cp_lexer_consume_token (parser->lexer);
>>> + novector = cp_parser_pragma_novector (parser, tok);
>>> + tok = cp_lexer_peek_token (the_parser->lexer);
>>> + break;
>>> + }
>>> + default:
>>> + gcc_unreachable ();
>>
>> This unreachable seems to assert that if a pragma follows one of these
>> pragmas, it must be another one of these pragmas? That seems wrong;
>> instead of hitting gcc_unreachable() in that case we should fall through to the
>> diagnostic below.
>>
>
> Ah, good should. Since it has to exit two levels I had to introduce a bool
> for controlling the loop iterations. New patch below.
>
> Bootstrapped Regtested on aarch64-none-linux-gnu and no issues.
>
> Ok for master?
OK.
> Thanks,
> Tamar
>
> 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.
>
> --- inline copy of patch ---
>
> diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
> index 8398223311194837441107cb335d497ff5f5ec1c..bece7bff1f01a23cfc94386fd3295a0be8c462fe 100644
> --- a/gcc/cp/cp-tree.h
> +++ b/gcc/cp/cp-tree.h
> @@ -5377,6 +5377,7 @@ get_vec_init_expr (tree t)
> #define RANGE_FOR_UNROLL(NODE) TREE_OPERAND (RANGE_FOR_STMT_CHECK (NODE), 4)
> #define RANGE_FOR_INIT_STMT(NODE) TREE_OPERAND (RANGE_FOR_STMT_CHECK (NODE), 5)
> #define RANGE_FOR_IVDEP(NODE) TREE_LANG_FLAG_6 (RANGE_FOR_STMT_CHECK (NODE))
> +#define RANGE_FOR_NOVECTOR(NODE) TREE_LANG_FLAG_5 (RANGE_FOR_STMT_CHECK (NODE))
>
> /* STMT_EXPR accessor. */
> #define STMT_EXPR_STMT(NODE) TREE_OPERAND (STMT_EXPR_CHECK (NODE), 0)
> @@ -7286,7 +7287,7 @@ extern bool maybe_clone_body (tree);
>
> /* In parser.cc */
> extern tree cp_convert_range_for (tree, tree, tree, tree, unsigned int, bool,
> - unsigned short);
> + unsigned short, bool);
> extern void cp_convert_omp_range_for (tree &, vec<tree, va_gc> *, tree &,
> tree &, tree &, tree &, tree &, tree &);
> extern void cp_finish_omp_range_for (tree, tree);
> @@ -7609,16 +7610,19 @@ extern void begin_else_clause (tree);
> extern void finish_else_clause (tree);
> extern void finish_if_stmt (tree);
> extern tree begin_while_stmt (void);
> -extern void finish_while_stmt_cond (tree, tree, bool, unsigned short);
> +extern void finish_while_stmt_cond (tree, tree, bool, unsigned short,
> + bool);
> extern void finish_while_stmt (tree);
> extern tree begin_do_stmt (void);
> extern void finish_do_body (tree);
> -extern void finish_do_stmt (tree, tree, bool, unsigned short);
> +extern void finish_do_stmt (tree, tree, bool, unsigned short,
> + bool);
> extern tree finish_return_stmt (tree);
> extern tree begin_for_scope (tree *);
> extern tree begin_for_stmt (tree, tree);
> extern void finish_init_stmt (tree);
> -extern void finish_for_cond (tree, tree, bool, unsigned short);
> +extern void finish_for_cond (tree, tree, bool, unsigned short,
> + bool);
> extern void finish_for_expr (tree, tree);
> extern void finish_for_stmt (tree);
> extern tree begin_range_for_stmt (tree, tree);
> diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc
> index af6e30f511e142c7a594e742d128b2bf0aa8fb8d..5b735b27e6f5bc6b439ae64665902f4f1ca76f95 100644
> --- a/gcc/cp/init.cc
> +++ b/gcc/cp/init.cc
> @@ -4846,7 +4846,7 @@ build_vec_init (tree base, tree maxindex, tree init,
> finish_init_stmt (for_stmt);
> finish_for_cond (build2 (GT_EXPR, boolean_type_node, iterator,
> build_int_cst (TREE_TYPE (iterator), -1)),
> - for_stmt, false, 0);
> + for_stmt, false, 0, false);
> /* We used to pass this decrement to finish_for_expr; now we add it to
> elt_init below so it's part of the same full-expression as the
> initialization, and thus happens before any potentially throwing
> diff --git a/gcc/cp/method.cc b/gcc/cp/method.cc
> index 91cf943f11089c0e6bcbe8377daa4e016f956d56..fce49c796199c2c65cd70684e2942fea1b6b2ebd 100644
> --- a/gcc/cp/method.cc
> +++ b/gcc/cp/method.cc
> @@ -1645,7 +1645,8 @@ build_comparison_op (tree fndecl, bool defining, tsubst_flags_t complain)
> add_stmt (idx);
> finish_init_stmt (for_stmt);
> finish_for_cond (build2 (LE_EXPR, boolean_type_node, idx,
> - maxval), for_stmt, false, 0);
> + maxval), for_stmt, false, 0,
> + false);
> finish_for_expr (cp_build_unary_op (PREINCREMENT_EXPR,
> TARGET_EXPR_SLOT (idx),
> false, complain),
> diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
> index dd3665c8ccf48a8a0b1ba2c06400fe50999ea240..092f991d7a1b6aab8482d50848fb9fb96c377509 100644
> --- a/gcc/cp/parser.cc
> +++ b/gcc/cp/parser.cc
> @@ -2324,15 +2324,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
> @@ -12414,7 +12414,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:
> @@ -13594,7 +13595,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;
> @@ -13624,14 +13626,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;
> @@ -13658,7 +13660,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);
>
> @@ -13682,7 +13684,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;
> @@ -13758,6 +13761,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. */
> @@ -13770,7 +13775,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;
> }
> @@ -13948,7 +13953,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;
> @@ -14008,7 +14013,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,
> @@ -14175,7 +14180,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;
> @@ -14209,7 +14214,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. */
> @@ -14244,7 +14249,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 `;'. */
> @@ -14258,7 +14263,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);
> @@ -43815,7 +43820,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,
> @@ -49300,6 +49305,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. */
>
> @@ -49605,58 +49619,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
> @@ -49665,7 +49694,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;
> }
>
> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> index 2345a18becc1160b9d12f3d88cccb66c8917373c..7b0d01a90e3c4012ec603ebe04cbbb31a7dd1570 100644
> --- a/gcc/cp/pt.cc
> +++ b/gcc/cp/pt.cc
> @@ -19036,7 +19036,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
> RECUR (FOR_INIT_STMT (t));
> finish_init_stmt (stmt);
> tmp = RECUR (FOR_COND (t));
> - finish_for_cond (tmp, stmt, false, 0);
> + finish_for_cond (tmp, stmt, false, 0, false);
> tmp = RECUR (FOR_EXPR (t));
> finish_for_expr (tmp, stmt);
> {
> @@ -19073,6 +19073,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
> {
> RANGE_FOR_IVDEP (stmt) = RANGE_FOR_IVDEP (t);
> RANGE_FOR_UNROLL (stmt) = RANGE_FOR_UNROLL (t);
> + RANGE_FOR_NOVECTOR (stmt) = RANGE_FOR_NOVECTOR (t);
> finish_range_for_decl (stmt, decl, expr);
> if (decomp_first && decl != error_mark_node)
> cp_finish_decomp (decl, decomp_first, decomp_cnt);
> @@ -19083,7 +19084,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
> ? tree_to_uhwi (RANGE_FOR_UNROLL (t)) : 0);
> stmt = cp_convert_range_for (stmt, decl, expr,
> decomp_first, decomp_cnt,
> - RANGE_FOR_IVDEP (t), unroll);
> + RANGE_FOR_IVDEP (t), unroll,
> + RANGE_FOR_NOVECTOR (t));
> }
>
> bool prev = note_iteration_stmt_body_start ();
> @@ -19096,7 +19098,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
> case WHILE_STMT:
> stmt = begin_while_stmt ();
> tmp = RECUR (WHILE_COND (t));
> - finish_while_stmt_cond (tmp, stmt, false, 0);
> + finish_while_stmt_cond (tmp, stmt, false, 0, false);
> {
> bool prev = note_iteration_stmt_body_start ();
> RECUR (WHILE_BODY (t));
> @@ -19114,7 +19116,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
> }
> finish_do_body (stmt);
> tmp = RECUR (DO_COND (t));
> - finish_do_stmt (tmp, stmt, false, 0);
> + finish_do_stmt (tmp, stmt, false, 0, false);
> break;
>
> case IF_STMT:
> diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
> index 8fb47fd179eb2af2e82bf31d188023e9b9d41de9..b79975109c22ebcfcb060b4f20f32f69f3c3c444 100644
> --- a/gcc/cp/semantics.cc
> +++ b/gcc/cp/semantics.cc
> @@ -1148,7 +1148,7 @@ begin_while_stmt (void)
>
> void
> finish_while_stmt_cond (tree cond, tree while_stmt, bool ivdep,
> - unsigned short unroll)
> + unsigned short unroll, bool novector)
> {
> cond = maybe_convert_cond (cond);
> finish_cond (&WHILE_COND (while_stmt), cond);
> @@ -1168,6 +1168,13 @@ finish_while_stmt_cond (tree cond, tree while_stmt, bool ivdep,
> annot_expr_unroll_kind),
> build_int_cst (integer_type_node,
> unroll));
> + if (novector && cond != error_mark_node)
> + WHILE_COND (while_stmt) = build3 (ANNOTATE_EXPR,
> + TREE_TYPE (WHILE_COND (while_stmt)),
> + WHILE_COND (while_stmt),
> + build_int_cst (integer_type_node,
> + annot_expr_no_vector_kind),
> + integer_zero_node);
> simplify_loop_decl_cond (&WHILE_COND (while_stmt), WHILE_BODY (while_stmt));
> }
>
> @@ -1212,7 +1219,8 @@ finish_do_body (tree do_stmt)
> COND is as indicated. */
>
> void
> -finish_do_stmt (tree cond, tree do_stmt, bool ivdep, unsigned short unroll)
> +finish_do_stmt (tree cond, tree do_stmt, bool ivdep, unsigned short unroll,
> + bool novector)
> {
> cond = maybe_convert_cond (cond);
> end_maybe_infinite_loop (cond);
> @@ -1229,6 +1237,10 @@ finish_do_stmt (tree cond, tree do_stmt, bool ivdep, unsigned short unroll)
> cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
> build_int_cst (integer_type_node, annot_expr_unroll_kind),
> build_int_cst (integer_type_node, unroll));
> + if (novector && cond != error_mark_node)
> + cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
> + build_int_cst (integer_type_node, annot_expr_no_vector_kind),
> + integer_zero_node);
> DO_COND (do_stmt) = cond;
> }
>
> @@ -1325,7 +1337,7 @@ finish_init_stmt (tree for_stmt)
> FOR_STMT. */
>
> void
> -finish_for_cond (tree cond, tree for_stmt, bool ivdep, unsigned short unroll)
> +finish_for_cond (tree cond, tree for_stmt, bool ivdep, unsigned short unroll, bool novector)
> {
> cond = maybe_convert_cond (cond);
> finish_cond (&FOR_COND (for_stmt), cond);
> @@ -1345,6 +1357,13 @@ finish_for_cond (tree cond, tree for_stmt, bool ivdep, unsigned short unroll)
> annot_expr_unroll_kind),
> build_int_cst (integer_type_node,
> unroll));
> + if (novector && cond != error_mark_node)
> + FOR_COND (for_stmt) = build3 (ANNOTATE_EXPR,
> + TREE_TYPE (FOR_COND (for_stmt)),
> + FOR_COND (for_stmt),
> + build_int_cst (integer_type_node,
> + annot_expr_no_vector_kind),
> + integer_zero_node);
> simplify_loop_decl_cond (&FOR_COND (for_stmt), FOR_BODY (for_stmt));
> }
>
> diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
> index 3040a9bdea65d27f8d20572b4ed37375f5fe949b..baac6643d1abbf33d592e68aca49ac83e3c29188 100644
> --- a/gcc/doc/extend.texi
> +++ b/gcc/doc/extend.texi
> @@ -24349,6 +24349,25 @@ void ignore_vec_dep (int *a, int k, int c, int m)
> @}
> @end smallexample
>
> +@cindex pragma GCC novector
> +@item #pragma GCC novector
> +
> +With this pragma, the programmer asserts that the following loop should be
> +prevented from executing concurrently with SIMD (single instruction multiple
> +data) instructions.
> +
> +For example, the compiler cannot vectorize the following loop with the pragma:
> +
> +@smallexample
> +void foo (int n, int *a, int *b, int *c)
> +@{
> + int i, j;
> +#pragma GCC novector
> + for (i = 0; i < n; ++i)
> + a[i] = b[i] + c[i];
> +@}
> +@end smallexample
> +
> @cindex pragma GCC unroll @var{n}
> @item #pragma GCC unroll @var{n}
>
> diff --git a/gcc/testsuite/g++.dg/vect/vect-novector-pragma.cc b/gcc/testsuite/g++.dg/vect/vect-novector-pragma.cc
> new file mode 100644
> index 0000000000000000000000000000000000000000..8c6ff22fcaabaa97516be72b77acbd44df86b1d2
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/vect/vect-novector-pragma.cc
> @@ -0,0 +1,69 @@
> +/* { dg-do compile } */
> +/* { dg-require-effective-target vect_int } */
> +
> +#include <vector>
> +
> +void f4 (std::vector<int> a, std::vector<int> b, int n)
> +{
> + int i = 0;
> +#pragma GCC novector
> + while (i < (n & -8))
> + {
> + a[i] += b[i];
> + i++;
> + }
> +}
> +
> +void f5 (std::vector<int> a, std::vector<int> b, int n)
> +{
> + int i = 0;
> +#pragma GCC novector
> +#pragma GCC ivdep
> +#pragma GCC unroll 2
> + while (i < (n & -8))
> + {
> + a[i] += b[i];
> + i++;
> + }
> +}
> +
> +void f6 (std::vector<int> a, std::vector<int> b, int n)
> +{
> + int i = 0;
> +#pragma GCC ivdep
> +#pragma GCC novector
> +#pragma GCC unroll 2
> + while (i < (n & -8))
> + {
> + a[i] += b[i];
> + i++;
> + }
> +}
> +
> +void f7 (std::vector<int> a, std::vector<int> b, int n)
> +{
> + int i = 0;
> +#pragma GCC ivdep
> +#pragma GCC unroll 2
> +#pragma GCC novector
> + while (i < (n & -8))
> + {
> + a[i] += b[i];
> + i++;
> + }
> +}
> +
> +#if __cpp_range_based_for
> +void f8 (std::vector<int> a, std::vector<int> b, int n)
> +{
> + int i = 0;
> +#pragma GCC novector
> + for (int x : b)
> + {
> + a[i] += x;
> + i++;
> + }
> +}
> +#endif
> +
> +/* { dg-final { scan-tree-dump-not "LOOP VECTORIZED" "vect" } } */
> diff --git a/gcc/testsuite/g++.dg/vect/vect.exp b/gcc/testsuite/g++.dg/vect/vect.exp
> index df273233f47a788024bbe61128eaa96b639cb3b8..fc77120a83173c65ad147e8bb7c29ac82f06bb6d 100644
> --- a/gcc/testsuite/g++.dg/vect/vect.exp
> +++ b/gcc/testsuite/g++.dg/vect/vect.exp
> @@ -64,7 +64,7 @@ dg-init
>
> # Main loop.
> et-dg-runtest g++-dg-runtest [lsort [glob -nocomplain \
> - $srcdir/$subdir/{pr,simd}*.{c,cc,S} ]] "" $DEFAULT_VECTCFLAGS
> + $srcdir/$subdir/{pr,simd,vect-}*.{c,cc,S} ]] "" $DEFAULT_VECTCFLAGS
> et-dg-runtest g++-dg-runtest [lsort [glob -nocomplain \
> $srcdir/$subdir/slp-pr*.{c,cc,S} ]] "" $VECT_SLP_CFLAGS
>
prev parent reply other threads:[~2023-07-26 20:52 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-07-19 15:15 Tamar Christina
2023-07-19 15:16 ` [PATCH 2/2][frontend]: Add novector C pragma Tamar Christina
2023-07-26 19:35 ` Tamar Christina
2023-08-02 9:44 ` Tamar Christina
2023-08-02 17:54 ` Joseph Myers
2023-07-25 20:53 ` [PATCH 1/2][frontend] Add novector C++ pragma Jason Merrill
2023-07-26 19:32 ` Tamar Christina
2023-07-26 20:52 ` Jason Merrill [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=e1d0e4ed-f517-4186-7db5-12445ce0aead@redhat.com \
--to=jason@redhat.com \
--cc=Tamar.Christina@arm.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=nathan@acm.org \
--cc=nd@arm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).