diff options
author | burnus <burnus@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-10-24 16:25:44 +0000 |
---|---|---|
committer | burnus <burnus@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-10-24 16:25:44 +0000 |
commit | 4644b59321661f7641c3d2a3816c811d8cb1de2f (patch) | |
tree | ddaa06506f828f6ab35f493e688951e5b042fbdf /gcc | |
parent | c4d85af9120b0f854cf24f7124c0b5c82d939c71 (diff) | |
download | gcc-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/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/c-family/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/c-family/c-pragma.c | 2 | ||||
-rw-r--r-- | gcc/c-family/c-pragma.h | 1 | ||||
-rw-r--r-- | gcc/c/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/c/c-parser.c | 33 | ||||
-rw-r--r-- | gcc/doc/extend.texi | 43 | ||||
-rw-r--r-- | gcc/doc/generic.texi | 6 | ||||
-rw-r--r-- | gcc/gimplify.c | 26 | ||||
-rw-r--r-- | gcc/internal-fn.c | 6 | ||||
-rw-r--r-- | gcc/internal-fn.def | 1 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/ivdep.c | 11 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/vect-ivdep-1.c | 19 | ||||
-rw-r--r-- | gcc/tree-cfg.c | 66 | ||||
-rw-r--r-- | gcc/tree-core.h | 4 | ||||
-rw-r--r-- | gcc/tree-pretty-print.c | 12 | ||||
-rw-r--r-- | gcc/tree.def | 6 |
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 |