This patch depends on the middle-end / C FE patch:
http://gcc.gnu.org/ml/gcc-patches/2013-10/msg00655.html
It adds parsing support for #pragma ivdep and annotates the condition of
C-like for loops such that one can later set the vectorization safe
length (loop->safelen) to INT_MAX. I considered to add the annotation
also to C++11's range-based loops, but as those are unlikely to
vectorize, I didn't do so. (If one does, one might end up having a
CLEANUP_POINT_EXPR around the annotate; that implies that the annotate
internal function is not the direct predecessor of the GIMPLE_COND.)
Another question is how much diagnostic one gives, e.g. when there is no
condition: Should there be an error, a warning or should the pragma then
silently ignored?
Build and regtested on x86-64-gnu-linux.
OK for the trunk?
Tobias
2013-08-10 Tobias Burnus <bur...@net-b.de>
PR other/33426
* parser.c (cp_parser_iteration_statement,
cp_parser_for, cp_parser_c_for, cp_parser_pragma): Handle
IVDEP pragma.
* g++.dg/vect/vect-ivdep-1.cc: New.
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 90c1775..790ffbd 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -1930,13 +1930,13 @@ static tree cp_parser_selection_statement
static tree cp_parser_condition
(cp_parser *);
static tree cp_parser_iteration_statement
- (cp_parser *);
+ (cp_parser *, bool);
static bool cp_parser_for_init_statement
(cp_parser *, tree *decl);
static tree cp_parser_for
- (cp_parser *);
+ (cp_parser *, bool);
static tree cp_parser_c_for
- (cp_parser *, tree, tree);
+ (cp_parser *, tree, tree, bool);
static tree cp_parser_range_for
(cp_parser *, tree, tree, tree);
static void do_range_for_auto_deduction
@@ -9172,7 +9172,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
case RID_WHILE:
case RID_DO:
case RID_FOR:
- statement = cp_parser_iteration_statement (parser);
+ statement = cp_parser_iteration_statement (parser, false);
break;
case RID_BREAK:
@@ -9833,7 +9833,7 @@ cp_parser_condition (cp_parser* parser)
not included. */
static tree
-cp_parser_for (cp_parser *parser)
+cp_parser_for (cp_parser *parser, bool ivdep)
{
tree init, scope, decl;
bool is_range_for;
@@ -9847,11 +9847,11 @@ cp_parser_for (cp_parser *parser)
if (is_range_for)
return cp_parser_range_for (parser, scope, init, decl);
else
- return cp_parser_c_for (parser, scope, init);
+ return cp_parser_c_for (parser, scope, init, ivdep);
}
static tree
-cp_parser_c_for (cp_parser *parser, tree scope, tree init)
+cp_parser_c_for (cp_parser *parser, tree scope, tree init, bool ivdep)
{
/* Normal for loop */
tree condition = NULL_TREE;
@@ -9865,7 +9865,14 @@ cp_parser_c_for (cp_parser *parser, tree scope, tree init)
/* If there's a condition, process it. */
if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
- condition = cp_parser_condition (parser);
+ {
+ condition = cp_parser_condition (parser);
+ if (ivdep)
+ {
+ condition = build1 (ANNOTATE_EXPR, TREE_TYPE (condition), condition);
+ SET_ANNOTATE_EXPR_ID (condition, annot_expr_ivdep_kind);
+ }
+ }
finish_for_cond (condition, stmt);
/* Look for the `;'. */
cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
@@ -10228,7 +10235,7 @@ cp_parser_range_for_member_function (tree range, tree identifier)
Returns the new WHILE_STMT, DO_STMT, FOR_STMT or RANGE_FOR_STMT. */
static tree
-cp_parser_iteration_statement (cp_parser* parser)
+cp_parser_iteration_statement (cp_parser* parser, bool ivdep)
{
cp_token *token;
enum rid keyword;
@@ -10301,7 +10308,7 @@ cp_parser_iteration_statement (cp_parser* parser)
/* Look for the `('. */
cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
- statement = cp_parser_for (parser);
+ statement = cp_parser_for (parser, ivdep);
/* Look for the `)'. */
cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
@@ -28847,6 +28854,20 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
"%<#pragma omp sections%> construct");
break;
+ case PRAGMA_IVDEP:
+ {
+ cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+ cp_token *tok;
+ tok = cp_lexer_peek_token (the_parser->lexer);
+ if (tok->type != CPP_KEYWORD || tok->keyword != RID_FOR)
+ {
+ cp_parser_error (parser, "for statement expected");
+ return false;
+ }
+ cp_parser_iteration_statement (parser, true);
+ return true;
+ }
+
default:
gcc_assert (id >= PRAGMA_FIRST_EXTERNAL);
c_invoke_pragma_handler (id);
diff --git a/gcc/testsuite/g++.dg/vect/vect-ivdep-1.cc b/gcc/testsuite/g++.dg/vect/vect-ivdep-1.cc
new file mode 100644
index 0000000..3c25a0b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/vect/vect-ivdep-1.cc
@@ -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;
+#pragma 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" } } */