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

* c-pragma.h (enum pragma_kind): Add PRAGMA_NOVECTOR.
* c-pragma.cc (init_pragma): Use it.

gcc/c/ChangeLog:

* c-parser.cc (c_parser_while_statement, c_parser_do_statement,
c_parser_for_statement, c_parser_statement_after_labels,
c_parse_pragma_novector, c_parser_pragma): Wire through novector and
default to false.

gcc/testsuite/ChangeLog:

* gcc.dg/vect/vect-novector-pragma.c: New test.

gcc/c-family/c-pragma.cc
gcc/c-family/c-pragma.h
gcc/c/c-parser.cc
gcc/testsuite/gcc.dg/vect/vect-novector-pragma.c [new file with mode: 0644]

index 73d59df3bf4e9515e88465d91bab0c64e8dc4af0..293311dd4ce9fa58b9de486a257b09a26b0b98de 100644 (file)
@@ -1822,6 +1822,10 @@ init_pragma (void)
     cpp_register_deferred_pragma (parse_in, "GCC", "unroll", PRAGMA_UNROLL,
                                  false, false);
 
+  if (!flag_preprocess_only)
+    cpp_register_deferred_pragma (parse_in, "GCC", "novector", PRAGMA_NOVECTOR,
+                                 false, false);
+
 #ifdef HANDLE_PRAGMA_PACK_WITH_EXPANSION
   c_register_pragma_with_expansion (0, "pack", handle_pragma_pack);
 #else
index 198fa7723e5bbaa9d6ce1a3ee1d26c027fb9a9b3..603c5151978658ff80716c552b6ae1c351d74274 100644 (file)
@@ -87,6 +87,7 @@ enum pragma_kind {
   PRAGMA_GCC_PCH_PREPROCESS,
   PRAGMA_IVDEP,
   PRAGMA_UNROLL,
+  PRAGMA_NOVECTOR,
 
   PRAGMA_FIRST_EXTERNAL
 };
index 025817fb474ca8523ef251e2c74d51a2dbb3d55a..7a9fdda6c88b03e2c0ac7af389aa2b5f186d8890 100644 (file)
@@ -1572,9 +1572,11 @@ static tree c_parser_c99_block_statement (c_parser *, bool *,
                                          location_t * = NULL);
 static void c_parser_if_statement (c_parser *, bool *, vec<tree> *);
 static void c_parser_switch_statement (c_parser *, bool *);
-static void c_parser_while_statement (c_parser *, bool, unsigned short, bool *);
-static void c_parser_do_statement (c_parser *, bool, unsigned short);
-static void c_parser_for_statement (c_parser *, bool, unsigned short, bool *);
+static void c_parser_while_statement (c_parser *, bool, unsigned short, bool,
+                                     bool *);
+static void c_parser_do_statement (c_parser *, bool, unsigned short, bool);
+static void c_parser_for_statement (c_parser *, bool, unsigned short, bool,
+                                   bool *);
 static tree c_parser_asm_statement (c_parser *);
 static tree c_parser_asm_operands (c_parser *);
 static tree c_parser_asm_goto_operands (c_parser *);
@@ -6668,13 +6670,13 @@ c_parser_statement_after_labels (c_parser *parser, bool *if_p,
          c_parser_switch_statement (parser, if_p);
          break;
        case RID_WHILE:
-         c_parser_while_statement (parser, false, 0, if_p);
+         c_parser_while_statement (parser, false, 0, false, if_p);
          break;
        case RID_DO:
-         c_parser_do_statement (parser, false, 0);
+         c_parser_do_statement (parser, false, 0, false);
          break;
        case RID_FOR:
-         c_parser_for_statement (parser, false, 0, if_p);
+         c_parser_for_statement (parser, false, 0, false, if_p);
          break;
        case RID_GOTO:
          c_parser_consume_token (parser);
@@ -7170,7 +7172,7 @@ c_parser_switch_statement (c_parser *parser, bool *if_p)
 
 static void
 c_parser_while_statement (c_parser *parser, bool ivdep, unsigned short unroll,
-                         bool *if_p)
+                         bool novector, bool *if_p)
 {
   tree block, cond, body;
   unsigned char save_in_statement;
@@ -7192,6 +7194,11 @@ c_parser_while_statement (c_parser *parser, bool ivdep, unsigned short unroll,
                   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);
   save_in_statement = in_statement;
   in_statement = IN_ITERATION_STMT;
 
@@ -7223,7 +7230,8 @@ c_parser_while_statement (c_parser *parser, bool ivdep, unsigned short unroll,
 */
 
 static void
-c_parser_do_statement (c_parser *parser, bool ivdep, unsigned short unroll)
+c_parser_do_statement (c_parser *parser, bool ivdep, unsigned short unroll,
+                      bool novector)
 {
   tree block, cond, body;
   unsigned char save_in_statement;
@@ -7252,6 +7260,11 @@ c_parser_do_statement (c_parser *parser, bool ivdep, unsigned short unroll)
                   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);
   if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
     c_parser_skip_to_end_of_block_or_statement (parser);
 
@@ -7320,7 +7333,7 @@ c_parser_do_statement (c_parser *parser, bool ivdep, unsigned short unroll)
 
 static void
 c_parser_for_statement (c_parser *parser, bool ivdep, unsigned short unroll,
-                       bool *if_p)
+                       bool novector, bool *if_p)
 {
   tree block, cond, incr, body;
   unsigned char save_in_statement;
@@ -7476,6 +7489,11 @@ c_parser_for_statement (c_parser *parser, bool ivdep, unsigned short unroll,
                           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);
        }
       /* Parse the increment expression (the third expression in a
         for-statement).  In the case of a foreach-statement, this is
@@ -13061,6 +13079,16 @@ c_parse_pragma_ivdep (c_parser *parser)
   return true;
 }
 
+/* Parse a pragma GCC novector.  */
+
+static bool
+c_parse_pragma_novector (c_parser *parser)
+{
+  c_parser_consume_pragma (parser);
+  c_parser_skip_to_pragma_eol (parser);
+  return true;
+}
+
 /* Parse a pragma GCC unroll.  */
 
 static unsigned short
@@ -13285,38 +13313,51 @@ c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p)
     case PRAGMA_OMP_ORDERED:
       return c_parser_omp_ordered (parser, context, if_p);
 
+    case PRAGMA_NOVECTOR:
+    case PRAGMA_UNROLL:
     case PRAGMA_IVDEP:
       {
-       const bool ivdep = c_parse_pragma_ivdep (parser);
-       unsigned short unroll;
-       if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_UNROLL)
-         unroll = c_parser_pragma_unroll (parser);
-       else
-         unroll = 0;
-       if (!c_parser_next_token_is_keyword (parser, RID_FOR)
-           && !c_parser_next_token_is_keyword (parser, RID_WHILE)
-           && !c_parser_next_token_is_keyword (parser, RID_DO))
+       bool novector = false;
+       unsigned short unroll = 0;
+       bool ivdep = false;
+
+       switch (id)
          {
-           c_parser_error (parser, "for, while or do statement expected");
-           return false;
+         case PRAGMA_NOVECTOR:
+           novector = c_parse_pragma_novector (parser);
+           break;
+         case PRAGMA_UNROLL:
+           unroll = c_parser_pragma_unroll (parser);
+           break;
+         case PRAGMA_IVDEP:
+           ivdep = c_parse_pragma_ivdep (parser);
+           break;
+         default:
+           gcc_unreachable ();
          }
-       if (c_parser_next_token_is_keyword (parser, RID_FOR))
-         c_parser_for_statement (parser, ivdep, unroll, if_p);
-       else if (c_parser_next_token_is_keyword (parser, RID_WHILE))
-         c_parser_while_statement (parser, ivdep, unroll, if_p);
-       else
-         c_parser_do_statement (parser, ivdep, unroll);
-      }
-      return true;
 
-    case PRAGMA_UNROLL:
-      {
-       unsigned short unroll = c_parser_pragma_unroll (parser);
-       bool ivdep;
-       if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_IVDEP)
-         ivdep = c_parse_pragma_ivdep (parser);
-       else
-         ivdep = false;
+       c_token *tok = c_parser_peek_token (parser);
+       bool has_more = tok->type == CPP_PRAGMA;
+       while (has_more)
+         {
+           switch (tok->pragma_kind)
+             {
+             case PRAGMA_IVDEP:
+               ivdep = c_parse_pragma_ivdep (parser);
+               break;
+             case PRAGMA_UNROLL:
+               unroll = c_parser_pragma_unroll (parser);
+               break;
+             case PRAGMA_NOVECTOR:
+               novector = c_parse_pragma_novector (parser);
+               break;
+             default:
+               has_more = false;
+               break;
+             }
+           tok = c_parser_peek_token (parser);
+           has_more = has_more && tok->type == CPP_PRAGMA;
+         }
        if (!c_parser_next_token_is_keyword (parser, RID_FOR)
            && !c_parser_next_token_is_keyword (parser, RID_WHILE)
            && !c_parser_next_token_is_keyword (parser, RID_DO))
@@ -13325,11 +13366,11 @@ c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p)
            return false;
          }
        if (c_parser_next_token_is_keyword (parser, RID_FOR))
-         c_parser_for_statement (parser, ivdep, unroll, if_p);
+         c_parser_for_statement (parser, ivdep, unroll, novector, if_p);
        else if (c_parser_next_token_is_keyword (parser, RID_WHILE))
-         c_parser_while_statement (parser, ivdep, unroll, if_p);
+         c_parser_while_statement (parser, ivdep, unroll, novector, if_p);
        else
-         c_parser_do_statement (parser, ivdep, unroll);
+         c_parser_do_statement (parser, ivdep, unroll, novector);
       }
       return true;
 
diff --git a/gcc/testsuite/gcc.dg/vect/vect-novector-pragma.c b/gcc/testsuite/gcc.dg/vect/vect-novector-pragma.c
new file mode 100644 (file)
index 0000000..3c0b8f5
--- /dev/null
@@ -0,0 +1,61 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_int } */
+
+void f1 (int * restrict a, int * restrict b, int n)
+{
+#pragma GCC novector
+    for (int i = 0; i < (n & -8); i++)
+      a[i] += b[i];
+}
+
+void f2 (int * restrict a, int * restrict b, int n)
+{
+#pragma GCC novector
+#pragma GCC ivdep
+#pragma GCC unroll 2
+    for (int i = 0; i < (n & -8); i++)
+      a[i] += b[i];
+}
+
+void f3 (int * restrict a, int * restrict b, int n)
+{
+#pragma GCC ivdep
+#pragma GCC novector
+#pragma GCC unroll 2
+    for (int i = 0; i < (n & -8); i++)
+      a[i] += b[i];
+}
+
+void f4 (int * restrict a, int * restrict b, int n)
+{
+#pragma GCC ivdep
+#pragma GCC unroll 2
+#pragma GCC novector
+    for (int i = 0; i < (n & -8); i++)
+      a[i] += b[i];
+}
+
+void f5 (int * restrict a, int * restrict b, int n)
+{
+    int i = 0;
+#pragma GCC novector
+    do
+      {
+        a[i] += b[i];
+        i++;
+      }
+    while (i < (n & -8));
+}
+
+void f6 (int * restrict a, int * restrict b, int n)
+{
+    int i = 0;
+#pragma GCC novector
+    while (i < (n & -8))
+      {
+        a[i] += b[i];
+        i++;
+      }
+}
+
+/* { dg-final { scan-tree-dump-not "LOOP VECTORIZED" "vect" } } */
This page took 0.095553 seconds and 5 git commands to generate.