]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
2013-08-24 Tobias Burnus <burnus@net-b.de>
authorburnus <burnus@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 24 Oct 2013 16:25:44 +0000 (16:25 +0000)
committerburnus <burnus@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 24 Oct 2013 16:25:44 +0000 (16:25 +0000)
        PR other/33426
        * c-pragma.c (init_pragma) Add #pragma ivdep handling.
        * c-pragma.h (pragma_kind): Add PRAGMA_IVDEP.

        PR other/33426
        * c-parser.c (c_parser_pragma, c_parser_for_statement):
        Handle PRAGMA_IVDEP.
        (c_parser_statement_after_labels): Update call.

        PR other/33426
        * tree-cfg.c (replace_loop_annotate): New function.
        (execute_build_cfg): Call it.
        * gimplify.c (gimple_boolify, gimplify_expr): Handle
        * ANNOTATE_EXPR.
        * internal-fn.c (expand_ANNOTATE): New function.
        * internal-fn.def (ANNOTATE): Define as new internal function.
        * tree-core.h (tree_node_kind): Add annot_expr_ivdep_kind.
        * tree-pretty-print.c (dump_generic_node): Handle ANNOTATE_EXPR.
        * tree.def (ANNOTATE_EXPR): New DEFTREECODE.
        * doc/extend.texi (Pragmas): Document #pragma ivdep.
        * doc/generic.texi (Expressions): Document ANNOTATE_EXPR.

        PR other/33426
        * testsuite/gcc.dg/ivdep.c: New.
        * testsuite/gcc.dg/vect/vect-ivdep-1.c: New.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@204021 138bc75d-0d04-0410-961f-82ee72b054a4

18 files changed:
gcc/ChangeLog
gcc/c-family/ChangeLog
gcc/c-family/c-pragma.c
gcc/c-family/c-pragma.h
gcc/c/ChangeLog
gcc/c/c-parser.c
gcc/doc/extend.texi
gcc/doc/generic.texi
gcc/gimplify.c
gcc/internal-fn.c
gcc/internal-fn.def
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/ivdep.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-ivdep-1.c [new file with mode: 0644]
gcc/tree-cfg.c
gcc/tree-core.h
gcc/tree-pretty-print.c
gcc/tree.def

index 60a9547df817a1f153690e71de1b74186fa2d8ac..ca9aa76cc0a48676f2bd043ff864432db37f8450 100644 (file)
@@ -1,3 +1,17 @@
+2013-08-24  Tobias Burnus  <burnus@net-b.de>
+
+       PR other/33426
+       * tree-cfg.c (replace_loop_annotate): New function.
+       (execute_build_cfg): Call it.
+       * gimplify.c (gimple_boolify, gimplify_expr): Handle ANNOTATE_EXPR.
+       * internal-fn.c (expand_ANNOTATE): New function.
+       * internal-fn.def (ANNOTATE): Define as new internal function.
+       * tree-core.h (tree_node_kind): Add annot_expr_ivdep_kind.
+       * tree-pretty-print.c (dump_generic_node): Handle ANNOTATE_EXPR.
+       * tree.def (ANNOTATE_EXPR): New DEFTREECODE.
+       * doc/extend.texi (Pragmas): Document #pragma ivdep.
+       * doc/generic.texi (Expressions): Document ANNOTATE_EXPR.
+
 2013-10-17  Ian Bolton  <ian.bolton@arm.com>
            Marcus Shawcroft  <marcus.shawcroft@arm.com>
 
index a4cfe0a6cddb0fac47f803c184d9b495657c9656..7b9174a9a6d21f6e0ebc0b6151c1871906daf84d 100644 (file)
@@ -1,3 +1,9 @@
+2013-08-24  Tobias Burnus  <burnus@net-b.de>
+
+       PR other/33426
+       * c-pragma.c (init_pragma) Add #pragma ivdep handling.
+       * c-pragma.h (pragma_kind): Add PRAGMA_IVDEP.
+
 2013-10-23  Jason Merrill  <jason@redhat.com>
 
        * c-format.c (gcc_cxxdiag_char_table): Add %X.
index be5748b1c53ca81581e53e9afcde99dbfdc2710c..1656000d9781d5721846a7c102df6c99be176f3a 100644 (file)
@@ -1362,6 +1362,8 @@ init_pragma (void)
     cpp_register_deferred_pragma (parse_in, "GCC", "pch_preprocess",
                                  PRAGMA_GCC_PCH_PREPROCESS, false, false);
 
+  cpp_register_deferred_pragma (parse_in, "GCC", "ivdep", PRAGMA_IVDEP, false,
+                               false);
 #ifdef HANDLE_PRAGMA_PACK_WITH_EXPANSION
   c_register_pragma_with_expansion (0, "pack", handle_pragma_pack);
 #else
index c421284a5c44a67d1ffb5f26751ca58f79015dcf..705bcb472a90a26f05e2b2511e60ff86c33555e6 100644 (file)
@@ -53,6 +53,7 @@ typedef enum pragma_kind {
   PRAGMA_OMP_TEAMS,
 
   PRAGMA_GCC_PCH_PREPROCESS,
+  PRAGMA_IVDEP,
 
   PRAGMA_FIRST_EXTERNAL
 } pragma_kind;
index 1d0dd9569f34f18b1a7d636a754051667629cad7..22cf8fff4444f6bccf99e086136959dbd37023bf 100644 (file)
@@ -1,3 +1,10 @@
+2013-08-24  Tobias Burnus  <burnus@net-b.de>
+
+       PR other/33426
+       * c-parser.c (c_parser_pragma, c_parser_for_statement):
+       Handle PRAGMA_IVDEP.
+       (c_parser_statement_after_labels): Update call.
+
 2013-10-24  Marek Polacek  <polacek@redhat.com>
 
        * c-parser.c (c_parser_struct_declaration): Add a comment.
index 4d6c9303918b220bae9c338f61ca4a0adc1a95da..4f250783945e4b9c84ac6c27f756ea1a25a51888 100644 (file)
@@ -1159,7 +1159,7 @@ static void c_parser_if_statement (c_parser *);
 static void c_parser_switch_statement (c_parser *);
 static void c_parser_while_statement (c_parser *);
 static void c_parser_do_statement (c_parser *);
-static void c_parser_for_statement (c_parser *);
+static void c_parser_for_statement (c_parser *, 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 *);
@@ -4585,7 +4585,7 @@ c_parser_statement_after_labels (c_parser *parser)
          c_parser_do_statement (parser);
          break;
        case RID_FOR:
-         c_parser_for_statement (parser);
+         c_parser_for_statement (parser, false);
          break;
        case RID_GOTO:
          c_parser_consume_token (parser);
@@ -5038,7 +5038,7 @@ c_parser_do_statement (c_parser *parser)
 */
 
 static void
-c_parser_for_statement (c_parser *parser)
+c_parser_for_statement (c_parser *parser, bool ivdep)
 {
   tree block, cond, incr, save_break, save_cont, body;
   /* The following are only used when parsing an ObjC foreach statement.  */
@@ -5144,8 +5144,17 @@ c_parser_for_statement (c_parser *parser)
        {
          if (c_parser_next_token_is (parser, CPP_SEMICOLON))
            {
-             c_parser_consume_token (parser);
-             cond = NULL_TREE;
+             if (ivdep)
+               {
+                 c_parser_error (parser, "missing loop condition in loop with "
+                                 "%<GCC ivdep%> pragma");
+                 cond = error_mark_node;
+               }
+             else
+               {
+                 c_parser_consume_token (parser);
+                 cond = NULL_TREE;
+               }
            }
          else
            {
@@ -5159,6 +5168,10 @@ c_parser_for_statement (c_parser *parser)
              c_parser_skip_until_found (parser, CPP_SEMICOLON,
                                         "expected %<;%>");
            }
+         if (ivdep && cond != error_mark_node)
+           cond = build2 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
+                          build_int_cst (integer_type_node,
+                          annot_expr_ivdep_kind));
        }
       /* Parse the increment expression (the third expression in a
         for-statement).  In the case of a foreach-statement, this is
@@ -9086,6 +9099,16 @@ c_parser_pragma (c_parser *parser, enum pragma_context context)
     case PRAGMA_OMP_DECLARE_REDUCTION:
       c_parser_omp_declare (parser, context);
       return false;
+    case PRAGMA_IVDEP:
+      c_parser_consume_pragma (parser);
+      c_parser_skip_to_pragma_eol (parser);
+      if (!c_parser_next_token_is_keyword (parser, RID_FOR))
+       {
+         c_parser_error (parser, "for statement expected");
+         return false;
+       }
+      c_parser_for_statement (parser, true);
+      return false;
 
     case PRAGMA_GCC_PCH_PREPROCESS:
       c_parser_error (parser, "%<#pragma GCC pch_preprocess%> must be first");
index 562b676a47b1b718386dfd5a6facb9d8dccf0899..7623a5e550e925db7c1c3088deb5deef3823bde9 100644 (file)
@@ -15473,6 +15473,7 @@ for further explanation.
 * Visibility Pragmas::
 * Push/Pop Macro Pragmas::
 * Function Specific Option Pragmas::
+* Loop-Specific Pragmas::
 @end menu
 
 @node ARM Pragmas
@@ -15995,6 +15996,48 @@ The @samp{#pragma GCC reset_options} pragma is not implemented in GCC
 versions earlier than 4.4.
 @end table
 
+@node Loop-Specific Pragmas
+@subsection Loop-Specific Pragmas
+
+@table @code
+@item #pragma GCC ivdep
+@cindex pragma GCC ivdep
+@end table
+
+With this pragma, the programmer asserts that there are no loop-carried
+dependencies which would prevent that consecutive iterations of
+the following loop can be executed concurrently with SIMD
+(single instruction multiple data) instructions.
+
+For example, the compiler can only unconditionally vectorize the following
+loop with the pragma:
+
+@smallexample
+void foo (int n, int *a, int *b, int *c)
+@{
+  int i, j;
+#pragma GCC ivdep
+  for (i = 0; i < n; ++i)
+    a[i] = b[i] + c[i];
+@}
+@end smallexample
+
+@noindent
+In this example, using the @code{restrict} qualifier had the same
+effect. In the following example, that would not be possible. Assume
+@math{k < -m} or @math{k >= m}. Only with the pragma, the compiler knows
+that it can unconditionally vectorize the following loop:
+
+@smallexample
+void ignore_vec_dep (int *a, int k, int c, int m)
+@{
+#pragma GCC ivdep
+  for (int i = 0; i < m; i++)
+    a[i] = a[i + k] * c;
+@}
+@end smallexample
+
+
 @node Unnamed Fields
 @section Unnamed struct/union fields within structs/unions
 @cindex @code{struct}
index ccecd6e842f45324f5475230f5ee48ca4fdd76b0..75c47456fb933dbd5af6dc2ee5647f247c2a4f79 100644 (file)
@@ -1279,6 +1279,7 @@ the byte offset of the field, but should not be used directly; call
 @tindex SAVE_EXPR
 @tindex TARGET_EXPR
 @tindex VA_ARG_EXPR
+@tindex ANNOTATE_EXPR
 
 @table @code
 @item NEGATE_EXPR
@@ -1692,8 +1693,13 @@ mechanism.  It represents expressions like @code{va_arg (ap, type)}.
 Its @code{TREE_TYPE} yields the tree representation for @code{type} and
 its sole argument yields the representation for @code{ap}.
 
+@item ANNOTATE_EXPR
+This node is used to attach markers to an expression. The first operand
+is the annotated expression, the second is an @code{INTEGER_CST} with
+a value from @code{enum annot_expr_kind}.
 @end table
 
+
 @node Vectors
 @subsection Vectors
 @tindex VEC_LSHIFT_EXPR
index fa1b155007604aeb6d514eeffdd96af49b4c15de..8d7844005bf037d114ec37fc099b89cc91e371f2 100644 (file)
@@ -3076,6 +3076,17 @@ gimple_boolify (tree expr)
        TREE_TYPE (expr) = boolean_type_node;
       return expr;
 
+    case ANNOTATE_EXPR:
+      if ((enum annot_expr_kind) TREE_INT_CST_LOW (TREE_OPERAND (expr, 1))
+         == annot_expr_ivdep_kind)
+       {
+         TREE_OPERAND (expr, 0) = gimple_boolify (TREE_OPERAND (expr, 0));
+         if (TREE_CODE (type) != BOOLEAN_TYPE)
+           TREE_TYPE (expr) = boolean_type_node;
+         return expr;
+       }
+      /* FALLTHRU */
+
     default:
       if (COMPARISON_CLASS_P (expr))
        {
@@ -7731,6 +7742,21 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
          ret = gimplify_addr_expr (expr_p, pre_p, post_p);
          break;
 
+       case ANNOTATE_EXPR:
+         {
+           tree cond = TREE_OPERAND (*expr_p, 0);
+           tree id = TREE_OPERAND (*expr_p, 1);
+           tree tmp = create_tmp_var_raw (TREE_TYPE(cond), NULL);
+           gimplify_arg (&cond, pre_p, EXPR_LOCATION (*expr_p));
+           gimple call = gimple_build_call_internal (IFN_ANNOTATE, 2,
+                                                     cond, id);
+           gimple_call_set_lhs (call, tmp);
+           gimplify_seq_add_stmt (pre_p, call);
+           *expr_p = tmp;
+           ret = GS_ALL_DONE;
+           break;
+         }
+
        case VA_ARG_EXPR:
          ret = gimplify_va_arg_expr (expr_p, pre_p, post_p);
          break;
index 983efeb751b33f03f562bb01383a579c297d334f..a22f222012c97246bf20cc733d62a9c9b592050b 100644 (file)
@@ -109,6 +109,12 @@ expand_STORE_LANES (gimple stmt)
   expand_insn (get_multi_vector_move (type, vec_store_lanes_optab), 2, ops);
 }
 
+static void
+expand_ANNOTATE (gimple stmt ATTRIBUTE_UNUSED)
+{
+  gcc_unreachable ();
+}
+
 /* This should get expanded in adjust_simduid_builtins.  */
 
 static void
index 5427664b8e3c5c2bfe1efe2c7f608e733de8b552..0f5cc3cba42104ba43ef85d4271a210461fa0d44 100644 (file)
@@ -43,3 +43,4 @@ DEF_INTERNAL_FN (STORE_LANES, ECF_CONST | ECF_LEAF)
 DEF_INTERNAL_FN (GOMP_SIMD_LANE, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW)
 DEF_INTERNAL_FN (GOMP_SIMD_VF, ECF_CONST | ECF_LEAF | ECF_NOTHROW)
 DEF_INTERNAL_FN (GOMP_SIMD_LAST_LANE, ECF_CONST | ECF_LEAF | ECF_NOTHROW)
+DEF_INTERNAL_FN (ANNOTATE,  ECF_CONST | ECF_LEAF | ECF_NOTHROW)
index 57862a73cc85658191b7e835b7e8b103efef6de0..7283360a99b91401f571096d8fa7048507745e0b 100644 (file)
@@ -1,3 +1,9 @@
+2013-08-24  Tobias Burnus  <burnus@net-b.de>
+
+       PR other/33426
+       * testsuite/gcc.dg/ivdep.c: New.
+       * testsuite/gcc.dg/vect/vect-ivdep-1.c: New.
+
 2013-10-24  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
 
        * gcc.target/aarch64/c-output-mod-2.c: Fix for -fPIC.
diff --git a/gcc/testsuite/gcc.dg/ivdep.c b/gcc/testsuite/gcc.dg/ivdep.c
new file mode 100644 (file)
index 0000000..23d51de
--- /dev/null
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+
+/* PR other/33426 */
+
+void foo(int n, int *a, int *b, int *c, int *d, int *e) {
+  int i, j;
+#pragma GCC ivdep
+  for (i = 0; ; ++i) { /* { dg-error "missing loop condition in loop with 'GCC ivdep' pragma before ';' token" } */
+    a[i] = b[i] + c[i];
+  }
+}
diff --git a/gcc/testsuite/gcc.dg/vect/vect-ivdep-1.c b/gcc/testsuite/gcc.dg/vect/vect-ivdep-1.c
new file mode 100644 (file)
index 0000000..8767bb8
--- /dev/null
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_float } */
+/* { dg-options "-O3 -fopt-info-vec-optimized" } */
+
+/* PR other/33426 */
+/* Testing whether #pragma ivdep is working.  */
+
+void foo(int n, int *a, int *b, int *c, int *d, int *e) {
+  int i, j;
+#pragma GCC ivdep
+  for (i = 0; i < n; ++i) {
+    a[i] = b[i] + c[i];
+  }
+}
+
+/* { dg-message "loop vectorized" "" { target *-*-* } 0 } */
+/* { dg-bogus "version" "" { target *-*-* } 0 } */
+/* { dg-bogus "alias" "" { target *-*-* } 0 } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
index 2021d94259611aef6706ad46d90db80b5d050a9e..cf8200a9f355b212bbafc9827c92b0c2ef30e849 100644 (file)
@@ -250,6 +250,71 @@ build_gimple_cfg (gimple_seq seq)
   discriminator_per_locus.dispose ();
 }
 
+
+/* Search for ANNOTATE call with annot_expr_ivdep_kind; if found, remove
+   it and set loop->safelen to INT_MAX.  We assume that the annotation
+   comes immediately before the condition.  */
+
+static void
+replace_loop_annotate ()
+{
+  struct loop *loop;
+  loop_iterator li;
+  basic_block bb;
+  gimple_stmt_iterator gsi;
+  gimple stmt;
+
+  FOR_EACH_LOOP (li, loop, 0)
+    {
+      gsi = gsi_last_bb (loop->header);
+      stmt = gsi_stmt (gsi);
+      if (stmt && gimple_code (stmt) == GIMPLE_COND)
+       {
+         gsi_prev_nondebug (&gsi);
+         if (gsi_end_p (gsi))
+           continue;
+         stmt = gsi_stmt (gsi);
+         if (gimple_code (stmt) != GIMPLE_CALL)
+               continue;
+         if (!gimple_call_internal_p (stmt)
+                 || gimple_call_internal_fn (stmt) != IFN_ANNOTATE)
+           continue;
+         if ((annot_expr_kind) tree_low_cst (gimple_call_arg (stmt, 1), 0)
+             != annot_expr_ivdep_kind)
+           continue;
+         stmt = gimple_build_assign (gimple_call_lhs (stmt),
+                                     gimple_call_arg (stmt, 0));
+         gsi_replace (&gsi, stmt, true);
+         loop->safelen = INT_MAX;
+       }
+    }
+
+  /* Remove IFN_ANNOTATE. Safeguard for the case loop->latch == NULL.  */
+  FOR_EACH_BB (bb)
+    {
+      gsi = gsi_last_bb (bb);
+      stmt = gsi_stmt (gsi);
+      if (stmt && gimple_code (stmt) == GIMPLE_COND)
+       gsi_prev_nondebug (&gsi);
+      if (gsi_end_p (gsi))
+       continue;
+      stmt = gsi_stmt (gsi);
+      if (gimple_code (stmt) != GIMPLE_CALL)
+       continue;
+      if (!gimple_call_internal_p (stmt)
+         || gimple_call_internal_fn (stmt) != IFN_ANNOTATE)
+       continue;
+      if ((annot_expr_kind) tree_low_cst (gimple_call_arg (stmt, 1), 0)
+         != annot_expr_ivdep_kind)
+       continue;
+      warning (0, "ignoring %<GCC ivdep%> annotation");
+      stmt = gimple_build_assign (gimple_call_lhs (stmt),
+                                 gimple_call_arg (stmt, 0));
+      gsi_replace (&gsi, stmt, true);
+    }
+}
+
+
 static unsigned int
 execute_build_cfg (void)
 {
@@ -264,6 +329,7 @@ execute_build_cfg (void)
     }
   cleanup_tree_cfg ();
   loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
+  replace_loop_annotate ();
   return 0;
 }
 
index c7fc84f87ada7fd4a00934d6f5b9cd763d2f4189..ea110bc09e374efe1d9c53f4538eb339b6dc2ec9 100644 (file)
@@ -647,6 +647,10 @@ enum tree_node_kind {
   all_kinds
 };
 
+enum annot_expr_kind {
+  annot_expr_ivdep_kind
+};
+
 
 /*---------------------------------------------------------------------------
                                 Type definitions
index b3bd8faa76fb5b86e70bc83eacaffac388eb5f30..150333b208f117121e5496e7a35d943a94af036e 100644 (file)
@@ -2095,6 +2095,18 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
       pp_string (buffer, " predictor.");
       break;
 
+    case ANNOTATE_EXPR:
+      pp_string (buffer, "ANNOTATE_EXPR <");
+      switch ((enum annot_expr_kind) TREE_INT_CST_LOW (TREE_OPERAND (node, 1)))
+       {
+       case annot_expr_ivdep_kind:
+         pp_string (buffer, "ivdep, ");
+         break;
+       }
+      dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false);
+      pp_greater (buffer);
+      break;
+
     case RETURN_EXPR:
       pp_string (buffer, "return");
       op0 = TREE_OPERAND (node, 0);
index 88c850af120922e1cd348780dff88d4a014543c1..9bd1b3d21c2beb4dff5494568b59983c0a22e786 100644 (file)
@@ -1261,6 +1261,12 @@ DEFTREECODE (OPTIMIZATION_NODE, "optimization_node", tcc_exceptional, 0)
 /* TARGET_OPTION_NODE.  Node to store the target specific options.  */
 DEFTREECODE (TARGET_OPTION_NODE, "target_option_node", tcc_exceptional, 0)
 
+/* ANNOTATE_EXPR.
+   Operand 0 is the expression to be annotated.
+   Operand 1 is the annotation id. */
+DEFTREECODE (ANNOTATE_EXPR, "annotate_expr", tcc_expression, 2)
+
+
 /*
 Local variables:
 mode:c