summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorburnus <burnus@138bc75d-0d04-0410-961f-82ee72b054a4>2013-10-24 16:25:44 +0000
committerburnus <burnus@138bc75d-0d04-0410-961f-82ee72b054a4>2013-10-24 16:25:44 +0000
commit4644b59321661f7641c3d2a3816c811d8cb1de2f (patch)
treeddaa06506f828f6ab35f493e688951e5b042fbdf /gcc
parentc4d85af9120b0f854cf24f7124c0b5c82d939c71 (diff)
downloadgcc-4644b59321661f7641c3d2a3816c811d8cb1de2f.tar.gz
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. 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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog14
-rw-r--r--gcc/c-family/ChangeLog6
-rw-r--r--gcc/c-family/c-pragma.c2
-rw-r--r--gcc/c-family/c-pragma.h1
-rw-r--r--gcc/c/ChangeLog7
-rw-r--r--gcc/c/c-parser.c33
-rw-r--r--gcc/doc/extend.texi43
-rw-r--r--gcc/doc/generic.texi6
-rw-r--r--gcc/gimplify.c26
-rw-r--r--gcc/internal-fn.c6
-rw-r--r--gcc/internal-fn.def1
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.dg/ivdep.c11
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-ivdep-1.c19
-rw-r--r--gcc/tree-cfg.c66
-rw-r--r--gcc/tree-core.h4
-rw-r--r--gcc/tree-pretty-print.c12
-rw-r--r--gcc/tree.def6
18 files changed, 264 insertions, 5 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 60a9547df81..ca9aa76cc0a 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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>
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index a4cfe0a6cdd..7b9174a9a6d 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -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.
diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c
index be5748b1c53..1656000d978 100644
--- a/gcc/c-family/c-pragma.c
+++ b/gcc/c-family/c-pragma.c
@@ -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
diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h
index c421284a5c4..705bcb472a9 100644
--- a/gcc/c-family/c-pragma.h
+++ b/gcc/c-family/c-pragma.h
@@ -53,6 +53,7 @@ typedef enum pragma_kind {
PRAGMA_OMP_TEAMS,
PRAGMA_GCC_PCH_PREPROCESS,
+ PRAGMA_IVDEP,
PRAGMA_FIRST_EXTERNAL
} pragma_kind;
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 1d0dd9569f3..22cf8fff444 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -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.
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 4d6c9303918..4f250783945 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -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");
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 562b676a47b..7623a5e550e 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -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}
diff --git a/gcc/doc/generic.texi b/gcc/doc/generic.texi
index ccecd6e842f..75c47456fb9 100644
--- a/gcc/doc/generic.texi
+++ b/gcc/doc/generic.texi
@@ -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
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index fa1b1550076..8d7844005bf 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -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;
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index 983efeb751b..a22f222012c 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -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
diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def
index 5427664b8e3..0f5cc3cba42 100644
--- a/gcc/internal-fn.def
+++ b/gcc/internal-fn.def
@@ -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)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 57862a73cc8..7283360a99b 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 00000000000..23d51de9fe3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ivdep.c
@@ -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
index 00000000000..8767bb87b7e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-ivdep-1.c
@@ -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" } } */
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 2021d942596..cf8200a9f35 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -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;
}
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index c7fc84f87ad..ea110bc09e3 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -647,6 +647,10 @@ enum tree_node_kind {
all_kinds
};
+enum annot_expr_kind {
+ annot_expr_ivdep_kind
+};
+
/*---------------------------------------------------------------------------
Type definitions
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index b3bd8faa76f..150333b208f 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -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);
diff --git a/gcc/tree.def b/gcc/tree.def
index 88c850af120..9bd1b3d21c2 100644
--- a/gcc/tree.def
+++ b/gcc/tree.def
@@ -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