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
This commit is contained in:
Tobias Burnus 2013-10-24 18:25:44 +02:00 committed by Tobias Burnus
parent a079f50a72
commit 8170608bfc
18 changed files with 264 additions and 5 deletions

View 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>

View 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.

View 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

View File

@ -53,6 +53,7 @@ typedef enum pragma_kind {
PRAGMA_OMP_TEAMS,
PRAGMA_GCC_PCH_PREPROCESS,
PRAGMA_IVDEP,
PRAGMA_FIRST_EXTERNAL
} pragma_kind;

View 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.

View 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");

View 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}

View 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

View 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;

View 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

View 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)

View 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.

View File

@ -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];
}
}

View File

@ -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" } } */

View 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;
}

View File

@ -647,6 +647,10 @@ enum tree_node_kind {
all_kinds
};
enum annot_expr_kind {
annot_expr_ivdep_kind
};
/*---------------------------------------------------------------------------
Type definitions

View 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);

View 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