mirror of git://gcc.gnu.org/git/gcc.git
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:
parent
a079f50a72
commit
8170608bfc
|
|
@ -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>
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ typedef enum pragma_kind {
|
|||
PRAGMA_OMP_TEAMS,
|
||||
|
||||
PRAGMA_GCC_PCH_PREPROCESS,
|
||||
PRAGMA_IVDEP,
|
||||
|
||||
PRAGMA_FIRST_EXTERNAL
|
||||
} pragma_kind;
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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. */
|
||||
|
|
@ -5143,10 +5143,19 @@ c_parser_for_statement (c_parser *parser)
|
|||
if (!is_foreach_statement)
|
||||
{
|
||||
if (c_parser_next_token_is (parser, CPP_SEMICOLON))
|
||||
{
|
||||
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
|
||||
{
|
||||
cond = c_parser_condition (parser);
|
||||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
}
|
||||
}
|
||||
|
|
@ -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" } } */
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -647,6 +647,10 @@ enum tree_node_kind {
|
|||
all_kinds
|
||||
};
|
||||
|
||||
enum annot_expr_kind {
|
||||
annot_expr_ivdep_kind
|
||||
};
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
Type definitions
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue