2013-10-30 Tobias Burnus <burnus@net-b.de>
gcc/cp/
PR other/33426
* cp-tree.h (RANGE_FOR_IVDEP): Define.
(cp_convert_range_for, finish_while_stmt_cond, finish_do_stmt,
finish_for_cond): Take 'bool ivdep' parameter.
* cp-array-notation.c (create_an_loop): Update call.
* init.c (build_vec_init): Ditto.
* pt.c (tsubst_expr): Ditto.
* parser.c (cp_parser_iteration_statement, cp_parser_for,
cp_parser_range_for, cp_convert_range_for): Update calls.
(cp_parser_pragma): Accept GCC ivdep for 'while' and 'do'.
* semantics.c (finish_while_stmt_cond, finish_do_stmt,
finish_for_cond): Optionally build ivdep annotation.
gcc/testsuite/
PR other/33426
* g++.dg/vect/pr33426-ivdep-2.cc: New.
* g++.dg/vect/pr33426-ivdep-3.cc: New.
* g++.dg/vect/pr33426-ivdep-4.cc: New.
gcc/
PR other/33426
* gcc/tree-cfg.c (replace_loop_annotate): Replace warning by
warning_at.
@@ -71,7 +71,7 @@ create_an_loop (tree init, tree cond, tree incr, tree body)
finish_expr_stmt (init);
for_stmt = begin_for_stmt (NULL_TREE, NULL_TREE);
finish_for_init_stmt (for_stmt);
- finish_for_cond (cond, for_stmt);
+ finish_for_cond (cond, for_stmt, false);
finish_for_expr (incr, for_stmt);
finish_expr_stmt (body);
finish_for_stmt (for_stmt);
@@ -116,6 +116,7 @@ c-common.h, not after.
6: IDENTIFIER_REPO_CHOSEN (in IDENTIFIER_NODE)
DECL_CONSTRUCTION_VTABLE_P (in VAR_DECL)
TYPE_MARKED_P (in _TYPE)
+ RANGE_FOR_IVDEP (in RANGE_FOR_STMT)
Usage of TYPE_LANG_FLAG_?:
0: TYPE_DEPENDENT_P
@@ -4088,6 +4089,7 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
#define RANGE_FOR_EXPR(NODE) TREE_OPERAND (RANGE_FOR_STMT_CHECK (NODE), 1)
#define RANGE_FOR_BODY(NODE) TREE_OPERAND (RANGE_FOR_STMT_CHECK (NODE), 2)
#define RANGE_FOR_SCOPE(NODE) TREE_OPERAND (RANGE_FOR_STMT_CHECK (NODE), 3)
+#define RANGE_FOR_IVDEP(NODE) TREE_LANG_FLAG_6 (RANGE_FOR_STMT_CHECK (NODE))
#define SWITCH_STMT_COND(NODE) TREE_OPERAND (SWITCH_STMT_CHECK (NODE), 0)
#define SWITCH_STMT_BODY(NODE) TREE_OPERAND (SWITCH_STMT_CHECK (NODE), 1)
@@ -4321,7 +4323,7 @@ extern int comparing_specializations;
sizeof can be nested. */
extern int cp_unevaluated_operand;
-extern tree cp_convert_range_for (tree, tree, tree);
+extern tree cp_convert_range_for (tree, tree, tree, bool);
extern bool parsing_nsdmi (void);
/* in pt.c */
@@ -5671,16 +5673,16 @@ extern void begin_else_clause (tree);
extern void finish_else_clause (tree);
extern void finish_if_stmt (tree);
extern tree begin_while_stmt (void);
-extern void finish_while_stmt_cond (tree, tree);
+extern void finish_while_stmt_cond (tree, tree, bool);
extern void finish_while_stmt (tree);
extern tree begin_do_stmt (void);
extern void finish_do_body (tree);
-extern void finish_do_stmt (tree, tree);
+extern void finish_do_stmt (tree, tree, bool);
extern tree finish_return_stmt (tree);
extern tree begin_for_scope (tree *);
extern tree begin_for_stmt (tree, tree);
extern void finish_for_init_stmt (tree);
-extern void finish_for_cond (tree, tree);
+extern void finish_for_cond (tree, tree, bool);
extern void finish_for_expr (tree, tree);
extern void finish_for_stmt (tree);
extern tree begin_range_for_stmt (tree, tree);
@@ -3667,7 +3667,7 @@ build_vec_init (tree base, tree maxindex, tree init,
finish_for_init_stmt (for_stmt);
finish_for_cond (build2 (NE_EXPR, boolean_type_node, iterator,
build_int_cst (TREE_TYPE (iterator), -1)),
- for_stmt);
+ for_stmt, false);
elt_init = cp_build_unary_op (PREDECREMENT_EXPR, iterator, 0,
complain);
if (elt_init == error_mark_node)
@@ -1978,7 +1978,7 @@ static tree cp_parser_for
static tree cp_parser_c_for
(cp_parser *, tree, tree, bool);
static tree cp_parser_range_for
- (cp_parser *, tree, tree, tree);
+ (cp_parser *, tree, tree, tree, bool);
static void do_range_for_auto_deduction
(tree, tree);
static tree cp_parser_perform_range_for_lookup
@@ -9904,7 +9904,7 @@ cp_parser_for (cp_parser *parser, bool ivdep)
is_range_for = cp_parser_for_init_statement (parser, &decl);
if (is_range_for)
- return cp_parser_range_for (parser, scope, init, decl);
+ return cp_parser_range_for (parser, scope, init, decl, ivdep);
else
return cp_parser_c_for (parser, scope, init, ivdep);
}
@@ -9924,20 +9924,14 @@ cp_parser_c_for (cp_parser *parser, tree scope, tree init, bool ivdep)
/* If there's a condition, process it. */
if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
- {
- condition = cp_parser_condition (parser);
- if (ivdep)
- condition = build2 (ANNOTATE_EXPR, TREE_TYPE (condition), condition,
- build_int_cst (integer_type_node,
- annot_expr_ivdep_kind));
- }
+ condition = cp_parser_condition (parser);
else if (ivdep)
{
cp_parser_error (parser, "missing loop condition in loop with "
"%<GCC ivdep%> pragma");
condition = error_mark_node;
}
- finish_for_cond (condition, stmt);
+ finish_for_cond (condition, stmt, ivdep);
/* Look for the `;'. */
cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
@@ -9960,7 +9954,8 @@ cp_parser_c_for (cp_parser *parser, tree scope, tree init, bool ivdep)
regular FOR_STMT. */
static tree
-cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl)
+cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl,
+ bool ivdep)
{
tree stmt, range_expr;
@@ -9979,6 +9974,8 @@ cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl)
if (check_for_bare_parameter_packs (range_expr))
range_expr = error_mark_node;
stmt = begin_range_for_stmt (scope, init);
+ if (ivdep)
+ RANGE_FOR_IVDEP (stmt) = 1;
finish_range_for_decl (stmt, range_decl, range_expr);
if (!type_dependent_expression_p (range_expr)
/* do_auto_deduction doesn't mess with template init-lists. */
@@ -9988,7 +9985,7 @@ cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl)
else
{
stmt = begin_for_stmt (scope, init);
- stmt = cp_convert_range_for (stmt, range_decl, range_expr);
+ stmt = cp_convert_range_for (stmt, range_decl, range_expr, ivdep);
}
return stmt;
}
@@ -10079,7 +10076,8 @@ do_range_for_auto_deduction (tree decl, tree range_expr)
namespace. */
tree
-cp_convert_range_for (tree statement, tree range_decl, tree range_expr)
+cp_convert_range_for (tree statement, tree range_decl, tree range_expr,
+ bool ivdep)
{
tree begin, end;
tree iter_type, begin_expr, end_expr;
@@ -10136,7 +10134,7 @@ cp_convert_range_for (tree statement, tree range_decl, tree range_expr)
begin, ERROR_MARK,
end, ERROR_MARK,
NULL, tf_warning_or_error);
- finish_for_cond (condition, statement);
+ finish_for_cond (condition, statement, ivdep);
/* The new increment expression. */
expression = finish_unary_op_expr (input_location,
@@ -10329,7 +10327,7 @@ cp_parser_iteration_statement (cp_parser* parser, bool ivdep)
cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
/* Parse the condition. */
condition = cp_parser_condition (parser);
- finish_while_stmt_cond (condition, statement);
+ finish_while_stmt_cond (condition, statement, ivdep);
/* Look for the `)'. */
cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
/* Parse the dependent statement. */
@@ -10359,7 +10357,7 @@ cp_parser_iteration_statement (cp_parser* parser, bool ivdep)
/* Parse the expression. */
expression = cp_parser_expression (parser, /*cast_p=*/false, NULL);
/* We're done with the do-statement. */
- finish_do_stmt (expression, statement);
+ finish_do_stmt (expression, statement, ivdep);
/* Look for the `)'. */
cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
/* Look for the `;'. */
@@ -30926,9 +30924,11 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
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)
+ if (tok->type != CPP_KEYWORD
+ || (tok->keyword != RID_FOR && tok->keyword != RID_WHILE
+ && tok->keyword != RID_DO))
{
- cp_parser_error (parser, "for statement expected");
+ cp_parser_error (parser, "for, while or do statement expected");
return false;
}
cp_parser_iteration_statement (parser, true);
@@ -13318,7 +13318,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
RECUR (FOR_INIT_STMT (t));
finish_for_init_stmt (stmt);
tmp = RECUR (FOR_COND (t));
- finish_for_cond (tmp, stmt);
+ finish_for_cond (tmp, stmt, false);
tmp = RECUR (FOR_EXPR (t));
finish_for_expr (tmp, stmt);
RECUR (FOR_BODY (t));
@@ -13333,7 +13333,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
decl = tsubst (decl, args, complain, in_decl);
maybe_push_decl (decl);
expr = RECUR (RANGE_FOR_EXPR (t));
- stmt = cp_convert_range_for (stmt, decl, expr);
+ stmt = cp_convert_range_for (stmt, decl, expr, RANGE_FOR_IVDEP (t));
RECUR (RANGE_FOR_BODY (t));
finish_for_stmt (stmt);
}
@@ -13342,7 +13342,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
case WHILE_STMT:
stmt = begin_while_stmt ();
tmp = RECUR (WHILE_COND (t));
- finish_while_stmt_cond (tmp, stmt);
+ finish_while_stmt_cond (tmp, stmt, false);
RECUR (WHILE_BODY (t));
finish_while_stmt (stmt);
break;
@@ -13352,7 +13352,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
RECUR (DO_BODY (t));
finish_do_body (stmt);
tmp = RECUR (DO_COND (t));
- finish_do_stmt (tmp, stmt);
+ finish_do_stmt (tmp, stmt, false);
break;
case IF_STMT:
@@ -726,9 +726,15 @@ begin_while_stmt (void)
WHILE_STMT. */
void
-finish_while_stmt_cond (tree cond, tree while_stmt)
+finish_while_stmt_cond (tree cond, tree while_stmt, bool ivdep)
{
finish_cond (&WHILE_COND (while_stmt), maybe_convert_cond (cond));
+ if (ivdep && cond != error_mark_node)
+ WHILE_COND (while_stmt) = build2 (ANNOTATE_EXPR,
+ TREE_TYPE (WHILE_COND (while_stmt)),
+ WHILE_COND (while_stmt),
+ build_int_cst (integer_type_node,
+ annot_expr_ivdep_kind));
simplify_loop_decl_cond (&WHILE_COND (while_stmt), WHILE_BODY (while_stmt));
}
@@ -771,9 +777,12 @@ finish_do_body (tree do_stmt)
COND is as indicated. */
void
-finish_do_stmt (tree cond, tree do_stmt)
+finish_do_stmt (tree cond, tree do_stmt, bool ivdep)
{
cond = maybe_convert_cond (cond);
+ if (ivdep && cond != error_mark_node)
+ cond = build2 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
+ build_int_cst (integer_type_node, annot_expr_ivdep_kind));
DO_COND (do_stmt) = cond;
}
@@ -876,9 +885,15 @@ finish_for_init_stmt (tree for_stmt)
FOR_STMT. */
void
-finish_for_cond (tree cond, tree for_stmt)
+finish_for_cond (tree cond, tree for_stmt, bool ivdep)
{
finish_cond (&FOR_COND (for_stmt), maybe_convert_cond (cond));
+ if (ivdep && cond != error_mark_node)
+ FOR_COND (for_stmt) = build2 (ANNOTATE_EXPR,
+ TREE_TYPE (FOR_COND (for_stmt)),
+ FOR_COND (for_stmt),
+ build_int_cst (integer_type_node,
+ annot_expr_ivdep_kind));
simplify_loop_decl_cond (&FOR_COND (for_stmt), FOR_BODY (for_stmt));
}
new file mode 100644
@@ -0,0 +1,39 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_float } */
+/* { dg-additional-options "-O3 -fopt-info-vec-optimized -fdump-tree-original -fdump-tree-gimple" } */
+
+/* PR other/33426 */
+/* Testing whether #pragma ivdep is working. */
+
+void foo(int n, int *a, int *b, int *c) {
+ int i;
+ i = 0;
+#pragma GCC ivdep
+ while(i < n)
+ {
+ a[i] = b[i] + c[i];
+ ++i;
+ }
+}
+
+void bar(int n, int *a, int *b, int *c) {
+ int i;
+ i = 0;
+#pragma GCC ivdep
+ do
+ {
+ a[i] = b[i] + c[i];
+ ++i;
+ }
+ while(i < n);
+}
+
+/* { dg-message "loop vectorized" "" { target *-*-* } 0 } */
+/* { dg-bogus " version" "" { target *-*-* } 0 } */
+/* { dg-bogus " alias" "" { target *-*-* } 0 } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
+
+/* { dg-final { scan-tree-dump-times "ANNOTATE_EXPR " 2 "original" } } */
+/* { dg-final { cleanup-tree-dump "original" } } */
+/* { dg-final { scan-tree-dump-times "ANNOTATE " 2 "gimple" } } */
+/* { dg-final { cleanup-tree-dump "gimple" } } */
new file mode 100644
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_float } */
+/* { dg-additional-options "-std=c++11 -O3 -fopt-info-vec-optimized -fdump-tree-original -fdump-tree-gimple" } */
+
+/* PR other/33426 */
+/* Testing whether #pragma ivdep is working. */
+
+int ar[100];
+
+void foo(int *a) {
+#pragma GCC ivdep
+ for (auto &i : ar) {
+ i *= *a;
+ }
+}
+
+/* { dg-message "loop vectorized" "" { target *-*-* } 0 } */
+/* { dg-bogus " version" "" { target *-*-* } 0 } */
+/* { dg-bogus " alias" "" { target *-*-* } 0 } */
+/* { dg-final { cleanup-tree-dump "vect" } } */
+
+/* { dg-final { scan-tree-dump-times "ANNOTATE_EXPR " 1 "original" } } */
+/* { dg-final { cleanup-tree-dump "original" } } */
+/* { dg-final { scan-tree-dump-times "ANNOTATE " 1 "gimple" } } */
+/* { dg-final { cleanup-tree-dump "gimple" } } */
new file mode 100644
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_float } */
+/* { dg-additional-options "-std=c++11 -O3 -fopt-info-vec-optimized -fdump-tree-original -fdump-tree-gimple" } */
+
+/* PR other/33426 */
+/* Testing whether #pragma ivdep is working. */
+
+#include <vector>
+
+template<class T, class T2>
+void Loop(T *b, T2 c) {
+#pragma GCC ivdep
+ for (auto &i : *b) {
+ i *= *c;
+ }
+}
+
+void foo(std::vector<int> *ar, int *b) {
+ Loop<std::vector<int>, int*>(ar, b);
+}
+
+/* { dg-message "loop vectorized" "" { target *-*-* } 0 } */
+/* FIXME: dg-bogus " version" "" { target *-*-* } 0 */
+/* FIXME: dg-bogus " alias" "" { target *-*-* } 0 */
+/* { dg-final { cleanup-tree-dump "vect" } } */
+
+/* { dg-final { scan-tree-dump-times "ANNOTATE_EXPR " 1 "original" } } */
+/* { dg-final { cleanup-tree-dump "original" } } */
+/* { dg-final { scan-tree-dump-times "ANNOTATE " 1 "gimple" } } */
+/* { dg-final { cleanup-tree-dump "gimple" } } */
@@ -307,7 +307,8 @@ replace_loop_annotate ()
if ((annot_expr_kind) tree_low_cst (gimple_call_arg (stmt, 1), 0)
!= annot_expr_ivdep_kind)
continue;
- warning (0, "ignoring %<GCC ivdep%> annotation");
+ warning_at (gimple_location (stmt), 0, "ignoring %<GCC ivdep%> "
+ "annotation");
stmt = gimple_build_assign (gimple_call_lhs (stmt),
gimple_call_arg (stmt, 0));
gsi_replace (&gsi, stmt, true);