]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
frontend: Add novector C++ pragma
authorTamar Christina <tamar.christina@arm.com>
Fri, 4 Aug 2023 12:50:53 +0000 (13:50 +0100)
committerTamar Christina <tamar.christina@arm.com>
Fri, 4 Aug 2023 12:50:53 +0000 (13:50 +0100)
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.

gcc/cp/cp-tree.h
gcc/cp/init.cc
gcc/cp/method.cc
gcc/cp/parser.cc
gcc/cp/pt.cc
gcc/cp/semantics.cc
gcc/doc/extend.texi
gcc/testsuite/g++.dg/vect/vect-novector-pragma.cc [new file with mode: 0644]
gcc/testsuite/g++.dg/vect/vect.exp

index e0c181d9aef271f0d133bbc23f29d958a818cf23..d051ee85f7017b27a85c0a7ab0b32949e44657a7 100644 (file)
@@ -5393,6 +5393,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)
@@ -7310,7 +7311,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);
@@ -7633,16 +7634,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);
index 3b9a7783391c5d6cc6e118623ec63d023cdcb187..c5830297b931266099b00efc2958b454a55ed4c9 100644 (file)
@@ -4853,7 +4853,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
index 8ed967ddb215a123c17a91a35fad40e6727ee6fe..4ba00175048a54de4bb78fcccf8596021101c9e6 100644 (file)
@@ -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),
index 2e245865ea74770b2eebdaa33742acf4df5aeebc..ba15a095e83ebdeedf3ca285d39af1c3adcf3fe3 100644 (file)
@@ -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;
       }
 
index 36344dcf91b35bbc988ffbc00ea3363af7b089bd..2706fa619bf8b8a4e9fd01539c60221a4e725d23 100644 (file)
@@ -19094,7 +19094,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);
       {
@@ -19131,6 +19131,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);
@@ -19141,7 +19142,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 ();
@@ -19154,7 +19156,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));
@@ -19172,7 +19174,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:
index 720521b7f1aa0986d2d35f798ba3a62486e3c3d5..e810bc41fc8e13b0b97a5de841184afa0e140fe4 100644 (file)
@@ -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;
 }
 
@@ -1327,7 +1339,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);
@@ -1347,6 +1359,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));
 }
 
index e06caf38e467be3bb0f9b0350e5b8060cb93bfce..89c5b4ea2b20dbdaa566a65467f158d96ced9265 100644 (file)
@@ -24581,6 +24581,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 (file)
index 0000000..8c6ff22
--- /dev/null
@@ -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" } } */
index df273233f47a788024bbe61128eaa96b639cb3b8..fc77120a83173c65ad147e8bb7c29ac82f06bb6d 100644 (file)
@@ -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