Commit 8170608b by Tobias Burnus Committed by Tobias Burnus

re PR other/33426 (Support of #pragma ivdep)

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.

From-SVN: r204021
parent a079f50a
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> 2013-10-17 Ian Bolton <ian.bolton@arm.com>
Marcus Shawcroft <marcus.shawcroft@arm.com> Marcus Shawcroft <marcus.shawcroft@arm.com>
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> 2013-10-23 Jason Merrill <jason@redhat.com>
* c-format.c (gcc_cxxdiag_char_table): Add %X. * c-format.c (gcc_cxxdiag_char_table): Add %X.
......
...@@ -1362,6 +1362,8 @@ init_pragma (void) ...@@ -1362,6 +1362,8 @@ init_pragma (void)
cpp_register_deferred_pragma (parse_in, "GCC", "pch_preprocess", cpp_register_deferred_pragma (parse_in, "GCC", "pch_preprocess",
PRAGMA_GCC_PCH_PREPROCESS, false, false); PRAGMA_GCC_PCH_PREPROCESS, false, false);
cpp_register_deferred_pragma (parse_in, "GCC", "ivdep", PRAGMA_IVDEP, false,
false);
#ifdef HANDLE_PRAGMA_PACK_WITH_EXPANSION #ifdef HANDLE_PRAGMA_PACK_WITH_EXPANSION
c_register_pragma_with_expansion (0, "pack", handle_pragma_pack); c_register_pragma_with_expansion (0, "pack", handle_pragma_pack);
#else #else
......
...@@ -53,6 +53,7 @@ typedef enum pragma_kind { ...@@ -53,6 +53,7 @@ typedef enum pragma_kind {
PRAGMA_OMP_TEAMS, PRAGMA_OMP_TEAMS,
PRAGMA_GCC_PCH_PREPROCESS, PRAGMA_GCC_PCH_PREPROCESS,
PRAGMA_IVDEP,
PRAGMA_FIRST_EXTERNAL PRAGMA_FIRST_EXTERNAL
} pragma_kind; } pragma_kind;
......
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> 2013-10-24 Marek Polacek <polacek@redhat.com>
* c-parser.c (c_parser_struct_declaration): Add a comment. * c-parser.c (c_parser_struct_declaration): Add a comment.
......
...@@ -1159,7 +1159,7 @@ static void c_parser_if_statement (c_parser *); ...@@ -1159,7 +1159,7 @@ static void c_parser_if_statement (c_parser *);
static void c_parser_switch_statement (c_parser *); static void c_parser_switch_statement (c_parser *);
static void c_parser_while_statement (c_parser *); static void c_parser_while_statement (c_parser *);
static void c_parser_do_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_statement (c_parser *);
static tree c_parser_asm_operands (c_parser *); static tree c_parser_asm_operands (c_parser *);
static tree c_parser_asm_goto_operands (c_parser *); static tree c_parser_asm_goto_operands (c_parser *);
...@@ -4585,7 +4585,7 @@ c_parser_statement_after_labels (c_parser *parser) ...@@ -4585,7 +4585,7 @@ c_parser_statement_after_labels (c_parser *parser)
c_parser_do_statement (parser); c_parser_do_statement (parser);
break; break;
case RID_FOR: case RID_FOR:
c_parser_for_statement (parser); c_parser_for_statement (parser, false);
break; break;
case RID_GOTO: case RID_GOTO:
c_parser_consume_token (parser); c_parser_consume_token (parser);
...@@ -5038,7 +5038,7 @@ c_parser_do_statement (c_parser *parser) ...@@ -5038,7 +5038,7 @@ c_parser_do_statement (c_parser *parser)
*/ */
static void 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; tree block, cond, incr, save_break, save_cont, body;
/* The following are only used when parsing an ObjC foreach statement. */ /* The following are only used when parsing an ObjC foreach statement. */
...@@ -5144,8 +5144,17 @@ c_parser_for_statement (c_parser *parser) ...@@ -5144,8 +5144,17 @@ c_parser_for_statement (c_parser *parser)
{ {
if (c_parser_next_token_is (parser, CPP_SEMICOLON)) if (c_parser_next_token_is (parser, CPP_SEMICOLON))
{ {
c_parser_consume_token (parser); if (ivdep)
cond = NULL_TREE; {
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 else
{ {
...@@ -5159,6 +5168,10 @@ c_parser_for_statement (c_parser *parser) ...@@ -5159,6 +5168,10 @@ c_parser_for_statement (c_parser *parser)
c_parser_skip_until_found (parser, CPP_SEMICOLON, c_parser_skip_until_found (parser, CPP_SEMICOLON,
"expected %<;%>"); "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 /* Parse the increment expression (the third expression in a
for-statement). In the case of a foreach-statement, this is 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) ...@@ -9086,6 +9099,16 @@ c_parser_pragma (c_parser *parser, enum pragma_context context)
case PRAGMA_OMP_DECLARE_REDUCTION: case PRAGMA_OMP_DECLARE_REDUCTION:
c_parser_omp_declare (parser, context); c_parser_omp_declare (parser, context);
return false; 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: case PRAGMA_GCC_PCH_PREPROCESS:
c_parser_error (parser, "%<#pragma GCC pch_preprocess%> must be first"); c_parser_error (parser, "%<#pragma GCC pch_preprocess%> must be first");
......
...@@ -15473,6 +15473,7 @@ for further explanation. ...@@ -15473,6 +15473,7 @@ for further explanation.
* Visibility Pragmas:: * Visibility Pragmas::
* Push/Pop Macro Pragmas:: * Push/Pop Macro Pragmas::
* Function Specific Option Pragmas:: * Function Specific Option Pragmas::
* Loop-Specific Pragmas::
@end menu @end menu
@node ARM Pragmas @node ARM Pragmas
...@@ -15995,6 +15996,48 @@ The @samp{#pragma GCC reset_options} pragma is not implemented in GCC ...@@ -15995,6 +15996,48 @@ The @samp{#pragma GCC reset_options} pragma is not implemented in GCC
versions earlier than 4.4. versions earlier than 4.4.
@end table @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 @node Unnamed Fields
@section Unnamed struct/union fields within structs/unions @section Unnamed struct/union fields within structs/unions
@cindex @code{struct} @cindex @code{struct}
......
...@@ -1279,6 +1279,7 @@ the byte offset of the field, but should not be used directly; call ...@@ -1279,6 +1279,7 @@ the byte offset of the field, but should not be used directly; call
@tindex SAVE_EXPR @tindex SAVE_EXPR
@tindex TARGET_EXPR @tindex TARGET_EXPR
@tindex VA_ARG_EXPR @tindex VA_ARG_EXPR
@tindex ANNOTATE_EXPR
@table @code @table @code
@item NEGATE_EXPR @item NEGATE_EXPR
...@@ -1692,8 +1693,13 @@ mechanism. It represents expressions like @code{va_arg (ap, type)}. ...@@ -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 @code{TREE_TYPE} yields the tree representation for @code{type} and
its sole argument yields the representation for @code{ap}. 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 @end table
@node Vectors @node Vectors
@subsection Vectors @subsection Vectors
@tindex VEC_LSHIFT_EXPR @tindex VEC_LSHIFT_EXPR
......
...@@ -3076,6 +3076,17 @@ gimple_boolify (tree expr) ...@@ -3076,6 +3076,17 @@ gimple_boolify (tree expr)
TREE_TYPE (expr) = boolean_type_node; TREE_TYPE (expr) = boolean_type_node;
return expr; 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: default:
if (COMPARISON_CLASS_P (expr)) if (COMPARISON_CLASS_P (expr))
{ {
...@@ -7731,6 +7742,21 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, ...@@ -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); ret = gimplify_addr_expr (expr_p, pre_p, post_p);
break; 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: case VA_ARG_EXPR:
ret = gimplify_va_arg_expr (expr_p, pre_p, post_p); ret = gimplify_va_arg_expr (expr_p, pre_p, post_p);
break; break;
......
...@@ -109,6 +109,12 @@ expand_STORE_LANES (gimple stmt) ...@@ -109,6 +109,12 @@ expand_STORE_LANES (gimple stmt)
expand_insn (get_multi_vector_move (type, vec_store_lanes_optab), 2, ops); 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. */ /* This should get expanded in adjust_simduid_builtins. */
static void static void
......
...@@ -43,3 +43,4 @@ DEF_INTERNAL_FN (STORE_LANES, ECF_CONST | ECF_LEAF) ...@@ -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_LANE, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW)
DEF_INTERNAL_FN (GOMP_SIMD_VF, ECF_CONST | 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 (GOMP_SIMD_LAST_LANE, ECF_CONST | ECF_LEAF | ECF_NOTHROW)
DEF_INTERNAL_FN (ANNOTATE, ECF_CONST | ECF_LEAF | ECF_NOTHROW)
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> 2013-10-24 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
* gcc.target/aarch64/c-output-mod-2.c: Fix for -fPIC. * gcc.target/aarch64/c-output-mod-2.c: Fix for -fPIC.
......
/* { 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];
}
}
/* { 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" } } */
...@@ -250,6 +250,71 @@ build_gimple_cfg (gimple_seq seq) ...@@ -250,6 +250,71 @@ build_gimple_cfg (gimple_seq seq)
discriminator_per_locus.dispose (); 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 static unsigned int
execute_build_cfg (void) execute_build_cfg (void)
{ {
...@@ -264,6 +329,7 @@ execute_build_cfg (void) ...@@ -264,6 +329,7 @@ execute_build_cfg (void)
} }
cleanup_tree_cfg (); cleanup_tree_cfg ();
loop_optimizer_init (AVOID_CFG_MODIFICATIONS); loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
replace_loop_annotate ();
return 0; return 0;
} }
......
...@@ -647,6 +647,10 @@ enum tree_node_kind { ...@@ -647,6 +647,10 @@ enum tree_node_kind {
all_kinds all_kinds
}; };
enum annot_expr_kind {
annot_expr_ivdep_kind
};
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Type definitions Type definitions
......
...@@ -2095,6 +2095,18 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags, ...@@ -2095,6 +2095,18 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
pp_string (buffer, " predictor."); pp_string (buffer, " predictor.");
break; 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: case RETURN_EXPR:
pp_string (buffer, "return"); pp_string (buffer, "return");
op0 = TREE_OPERAND (node, 0); op0 = TREE_OPERAND (node, 0);
......
...@@ -1261,6 +1261,12 @@ DEFTREECODE (OPTIMIZATION_NODE, "optimization_node", tcc_exceptional, 0) ...@@ -1261,6 +1261,12 @@ DEFTREECODE (OPTIMIZATION_NODE, "optimization_node", tcc_exceptional, 0)
/* TARGET_OPTION_NODE. Node to store the target specific options. */ /* TARGET_OPTION_NODE. Node to store the target specific options. */
DEFTREECODE (TARGET_OPTION_NODE, "target_option_node", tcc_exceptional, 0) 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: Local variables:
mode:c mode:c
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment