public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
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
> 


      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).