aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBalaji V. Iyer <balaji.v.iyer@intel.com>2013-04-19 22:13:05 +0000
committerBalaji V. Iyer <balaji.v.iyer@intel.com>2013-04-19 22:13:05 +0000
commitf9c0e5fd5c46776d2579799cb6c3e6ced94a69bd (patch)
treeffd5a1d93562b400de6801fc3b0a19bccb43c6c9
parent6ef66167cc520bfc248fa0507297c42f134b99e5 (diff)
Mixed a couple bugs in Array Notation and also Replaced mallocs,
tree-lists with VEC_TREES. git-svn-id: https://gcc.gnu.org/svn/gcc/branches/cilkplus-4_8-branch@198105 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog.cilkplus64
-rw-r--r--gcc/basic-block.h2
-rw-r--r--gcc/c-family/ChangeLog.cilkplus6
-rw-r--r--gcc/c-family/c-common.h1
-rw-r--r--gcc/c-family/c-pragma.c22
-rw-r--r--gcc/c-family/c-pragma.h10
-rw-r--r--gcc/c/Make-lang.in2
-rw-r--r--gcc/c/c-array-notation.c277
-rw-r--r--gcc/c/c-parser.c926
-rwxr-xr-xgcc/c/c-pragma-simd.c82
-rw-r--r--gcc/c/c-typeck.c25
-rw-r--r--gcc/cfgloop.h2
-rw-r--r--gcc/cilk.h9
-rw-r--r--gcc/cp/ChangeLog.cilkplus34
-rw-r--r--gcc/cp/Make-lang.in6
-rw-r--r--gcc/cp/cp-array-notation.c161
-rwxr-xr-xgcc/cp/cp-pragma-simd.c118
-rw-r--r--gcc/cp/parser.c920
-rw-r--r--gcc/gimple.h2
-rw-r--r--gcc/pragma_simd.c892
-rw-r--r--gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/errors/cilkplus_AN_cpp_errors.exp25
-rw-r--r--gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/errors/fp_triplet_values.cc4
-rw-r--r--gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/errors/parser_errors.cc4
-rw-r--r--gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/errors/sec_implicit.cc4
-rw-r--r--gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/errors/sec_implicit2.cc4
-rw-r--r--gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/errors/sec_inside_sec.cc22
-rw-r--r--gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/errors/sec_inside_sec2.cc25
-rw-r--r--gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/errors/sec_reduce_max_min_ind.cc4
-rw-r--r--gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/errors/tst_lngth.cc39
-rw-r--r--gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/execute/multiple_insert_check.cc17
-rw-r--r--gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/execute/sec_red_zero_test.cc26
-rw-r--r--gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/execute/test_sec_limits.cc28
-rw-r--r--gcc/testsuite/g++.dg/cilk-plus/pragma_simd_tests/compile/cilkplus_PS_cpp_compile.exp24
-rw-r--r--gcc/testsuite/g++.dg/cilk-plus/pragma_simd_tests/compile/tst1.cc52
-rw-r--r--gcc/testsuite/g++.dg/cilk-plus/pragma_simd_tests/errors/cilkplus_PS_cpp_errors.exp24
-rw-r--r--gcc/testsuite/g++.dg/cilk-plus/pragma_simd_tests/errors/for_body_errors.cc54
-rw-r--r--gcc/testsuite/gcc.dg/cilk-plus/array_notation_tests/errors/sec_inside_sec2.c27
-rw-r--r--gcc/testsuite/gcc.dg/cilk-plus/array_notation_tests/errors/tst_lngth.c19
-rw-r--r--gcc/testsuite/gcc.dg/cilk-plus/array_notation_tests/execute/test_sec_limits.c18
-rw-r--r--gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/compile/assert1.c17
-rw-r--r--gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/compile/assert2.c12
-rw-r--r--gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/compile/cilkplus_PS_c_compile.exp31
-rw-r--r--gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/compile/cond_vlength.c5
-rw-r--r--gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/errors/cilkplus_PS_c_errors.exp24
-rw-r--r--gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/errors/for_body_errors.c34
-rw-r--r--gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/errors/opt_error.c13
-rw-r--r--gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/errors/opt_error2.c13
-rw-r--r--gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/errors/same_var_multiple_clauses.c48
-rw-r--r--gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/execute/cilkplus_PS_c_execute.exp44
-rw-r--r--gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/execute/p_simd_test1.c2
-rw-r--r--gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/execute/p_simd_test2.c4
-rw-r--r--gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/execute/reduction_ex.c36
-rw-r--r--gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/execute/vlength_comma.c4
-rw-r--r--gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/execute/vlength_comma2.c3
-rw-r--r--gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/execute/vlength_comma3.c4
-rw-r--r--gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/pragma-simd-for.c0
-rw-r--r--gcc/tree-loop-distribution.c2
-rw-r--r--gcc/tree-vect-loop.c18
-rw-r--r--gcc/tree-vectorizer.c64
-rw-r--r--gcc/tree.h99
60 files changed, 2578 insertions, 1880 deletions
diff --git a/gcc/ChangeLog.cilkplus b/gcc/ChangeLog.cilkplus
index e6f2604675f..51eb4aaf6fe 100644
--- a/gcc/ChangeLog.cilkplus
+++ b/gcc/ChangeLog.cilkplus
@@ -1,3 +1,67 @@
+2013-04-19 Balaji V. Iyer <balaji.v.iyer@intel.com>
+
+ * c/c-array-notation.c (fix_builtin_array_notation_fn): Added a check
+ for array notation functions inside array notations. If so, return an
+ error.
+ (build_array_notation_expr): Fixed a bug and popped a statement list.
+ (build_array_notation_expr): Added a check for length mismatch. Also
+ changed loading array_list so that array refs can be used with array
+ notations. Finally, store array notation components into variable only
+ if it is not a INTEGER constant.
+ (find_rank): Changed the computation method so that array ref can be
+ used with array notations.
+ (length_mismatch_in_expr_p): New function.
+ (fix_builtin_array_notation_fn): Added a check to see if max/min value
+ is available for the type. If so, set it as the starting point for
+ min and max reduction functions.
+ * c/Make-lang.in (C_AND_OBJC_OBJS): Added c/c-pragma-simd.o.
+ * c/c-typeck.c (c_finish_loop): Added new parameter to pass in pragma
+ simd information.
+ * c/c-parser.c (c_parser_for_statement): Likewise.
+ (c_parser_simd_pragma): added CILKPLUS_PRAGMA_SIMD case. Removed
+ PRAGMA_SIMD_ASSERT, PRAGMA_SIMD_VECTORLENGTH, PRAGMA_SIMD_PRIVATE,
+ PRAGMA_SIMD_LINEAR cases.
+ (same_var_in_multiple_lists_p): New function.
+ (c_parser_simd_construct): Likewise.
+ (c_parser_simd_assert): Changed the function to use vecs intead of
+ mallocs, linked-list and TREE_LIST. Also, added a parameter to pass in
+ pragma simd information.
+ (c_parser_simd_vectorlength): Likewise.
+ (c_parser_simd_reduction): Likewise.
+ (c_parser_simd_linear): Likewise.
+ (c_parser_simd_private): Likewise.
+ * pragma_simd.c (psv_find_node): Changed the function to use vecs
+ instead of mallocs, linked-list and TREE_LIST.
+ (clause_resolved_p): Likewise.
+ (pragma_simd_assert_requested_p): Likewise.
+ (pragma_simd_verify_clauses): Likewise.
+ (set_OK_for_certain_clause): Likewise.
+ (psv_find_node): Likewise.
+ (pragma_simd_acceptable_vlength_p): Likewise.
+ (check_off_reduction_var): Likewise.
+ (find_linear_step_size): Likewise.
+ (all_reductions_satisfied_p): Likewise.
+ (pragma_simd_is_private_var_p): Renamed from pragma_simd_is_private_var.
+ (p_simd_nodes_clear): New function.
+ (p_simd_head_insert): Likewise.
+ (pragma_simd_is_linear_var_p): Likewise.
+ (dump_pragma_simd_values_vec): Likewise.
+ (psv_head_insert): Remove.
+ (insert_reduction_values): Likewise.
+ (same_var_in_multiple_lists_p): Likewise.
+ * tree-vectorizer.c (vectorize_loops): Removed function call
+ pragma_simd_vectorize_loop_p.
+ * tree.h (struct pragma_simd_values): Replaced dynamic arrays with
+ vecs.
+ (tree_label_decl): Made pragma_simd_index unsigned instead of signed.
+ * cfgloop.h (struct loop): Likewise.
+ * tree-vect-loop.c (vect_analyze_scalar_cycles_1): Added a check for
+ verbosity of vectorizer, and if so then emit debug information.
+ (vect_create_epilog_for_reduction): Added a call to remove reduction
+ var when a reduction has occurred.
+ * gimple.h (struct gimple_statement): Likewise.
+ * c/c-pragma-simd.c: New file.
+
2013-04-05 Balaji V. Iyer <balaji.v.iyer@intel.com>
* c/c-array-notation.c (build_array_notation_expr): Added support to
diff --git a/gcc/basic-block.h b/gcc/basic-block.h
index 5cd95cf86be..15daaef045c 100644
--- a/gcc/basic-block.h
+++ b/gcc/basic-block.h
@@ -220,7 +220,7 @@ struct GTY((chain_next ("%h.next_bb"), chain_prev ("%h.prev_bb"))) basic_block_d
int discriminator;
/* Index to the pragma simd data structure. */
- int pragma_simd_index;
+ unsigned int pragma_simd_index;
};
diff --git a/gcc/c-family/ChangeLog.cilkplus b/gcc/c-family/ChangeLog.cilkplus
index 7a630b76b22..fc1e7604f8c 100644
--- a/gcc/c-family/ChangeLog.cilkplus
+++ b/gcc/c-family/ChangeLog.cilkplus
@@ -1,3 +1,9 @@
+2013-04-19 Balaji V. Iyer <balaji.v.iyer@intel.com>
+
+ * c-pragma.c (init_pragma): Added "simd" as a deferred pragma instead
+ of it being a namespace. Removed all definition of pragma simd's
+ optional sub-clauses.
+
2013-02-05 Balaji V. Iyer <balaji.v.iyer@intel.com>
* c-cilk.c (extract_for_fields): Added a check if the increment value
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index d008834c62e..4543711bbbe 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -546,6 +546,7 @@ extern tree build_array_notation_expr (location_t, tree, tree, enum tree_code,
location_t, tree, tree);
extern tree build_array_notation_ref (location_t, tree, tree, tree, tree, tree);
extern void find_rank (tree, bool, size_t *);
+extern bool p_simd_valid_stmts_in_body_p (tree);
extern tree build_indirect_ref (location_t, tree, ref_operator);
extern int field_decl_cmp (const void *, const void *);
diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c
index da098d4ecba..f944a08a45a 100644
--- a/gcc/c-family/c-pragma.c
+++ b/gcc/c-family/c-pragma.c
@@ -1343,27 +1343,13 @@ init_pragma (void)
cpp_register_deferred_pragma (parse_in, "omp", omp_pragmas[i].name,
omp_pragmas[i].id, true, true);
}
-
if (flag_enable_cilk && !flag_preprocess_only)
{
cpp_register_deferred_pragma (parse_in, "cilk", "grainsize",
- PRAGMA_CILK_GRAINSIZE, true, false);
- cpp_register_deferred_pragma (parse_in, "simd", "",
- PRAGMA_SIMD_EMPTY, true, false);
- cpp_register_deferred_pragma (parse_in, "simd", "assert",
- PRAGMA_SIMD_ASSERT, true, false);
- cpp_register_deferred_pragma (parse_in, "simd", "noassert",
- PRAGMA_SIMD_NOASSERT, true, false);
- cpp_register_deferred_pragma (parse_in, "simd", "vectorlength",
- PRAGMA_SIMD_VECTORLENGTH, true, false);
- cpp_register_deferred_pragma (parse_in, "simd", "private",
- PRAGMA_SIMD_PRIVATE, true, false);
- cpp_register_deferred_pragma (parse_in, "simd", "reduction",
- PRAGMA_SIMD_REDUCTION, true, false);
- cpp_register_deferred_pragma (parse_in, "simd", "linear",
- PRAGMA_SIMD_LINEAR, true, false);
- }
-
+ PRAGMA_CILK_GRAINSIZE, true, false);
+ cpp_register_deferred_pragma (parse_in, NULL, "simd",
+ CILKPLUS_PRAGMA_SIMD, true, false);
+ }
if (!flag_preprocess_only)
cpp_register_deferred_pragma (parse_in, "GCC", "pch_preprocess",
PRAGMA_GCC_PCH_PREPROCESS, false, false);
diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h
index 07ede5bfcb3..0be522eded3 100644
--- a/gcc/c-family/c-pragma.h
+++ b/gcc/c-family/c-pragma.h
@@ -48,14 +48,8 @@ typedef enum pragma_kind {
/* This pragma allows you to get the grainsize of a Cilk for. */
PRAGMA_CILK_GRAINSIZE,
- /* Here are all the pragma simd clauses. */
- PRAGMA_SIMD_VECTORLENGTH,
- PRAGMA_SIMD_PRIVATE,
- PRAGMA_SIMD_LINEAR,
- PRAGMA_SIMD_REDUCTION,
- PRAGMA_SIMD_NOASSERT,
- PRAGMA_SIMD_ASSERT,
- PRAGMA_SIMD_EMPTY,
+ /* Top level clause to handle all pragma simd [sub]clauses. */
+ CILKPLUS_PRAGMA_SIMD,
PRAGMA_GCC_PCH_PREPROCESS,
PRAGMA_FIRST_EXTERNAL
diff --git a/gcc/c/Make-lang.in b/gcc/c/Make-lang.in
index 79523420f93..587a0263c0d 100644
--- a/gcc/c/Make-lang.in
+++ b/gcc/c/Make-lang.in
@@ -56,7 +56,7 @@ c/gccspec.o: c/gccspec.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(GCC_H) \
# Language-specific object files for C and Objective C.
C_AND_OBJC_OBJS = attribs.o c/c-errors.o c/c-decl.o c/c-typeck.o \
c/c-convert.o c/c-aux-info.o c/c-objc-common.o c/c-parser.o \
- c/c-array-notation.o $(C_COMMON_OBJS) $(C_TARGET_OBJS)
+ c/c-array-notation.o c/c-pragma-simd.o $(C_COMMON_OBJS) $(C_TARGET_OBJS)
# Language-specific object files for C.
C_OBJS = c/c-lang.o c-family/stub-objc.o $(C_AND_OBJC_OBJS)
diff --git a/gcc/c/c-array-notation.c b/gcc/c/c-array-notation.c
index d4bcdb67e0a..941cc682ef7 100644
--- a/gcc/c/c-array-notation.c
+++ b/gcc/c/c-array-notation.c
@@ -51,6 +51,47 @@ struct inv_list
vec<tree, va_gc> *replacement;
};
+/* Returns false if there is a length mismatch among expressions
+ on the same dimension AND the same side of the equal sign. The exprs are
+ passed in through 2-D array **LIST where X and Y indicate first and
+ second dimension sizes of LIST, respectively. */
+static bool
+length_mismatch_in_expr_p (location_t loc, tree **list, size_t x, size_t y)
+{
+ size_t ii, jj;
+ tree start = NULL_TREE;
+ HOST_WIDE_INT l_start, l_node;
+ for (jj = 0; jj < y; jj++)
+ {
+ start = NULL_TREE;
+ for (ii = 0; ii < x; ii++)
+ {
+ if (!start)
+ start = list[ii][jj];
+ else if (TREE_CODE (start) == INTEGER_CST)
+ {
+ /* If start is a INTEGER, and list[ii][jj] is an integer then
+ check if they are equal. If they are not equal then return
+ true. */
+ if (TREE_CODE (list[ii][jj]) == INTEGER_CST)
+ {
+ l_node = int_cst_value (list[ii][jj]);
+ l_start = int_cst_value (start);
+ if (abs (l_start) != abs (l_node))
+ {
+ error_at (loc, "length mismatch in expression");
+ return true;
+ }
+ }
+ }
+ else
+ /* We set the start node as the current node just in case it turns
+ out to be an integer. */
+ start = list[ii][jj];
+ }
+ }
+ return false;
+}
/* Returns the rank of ARRAY through the *RANK. The user can specify whether
(s)he wants to step into array_notation-specific builtin functions
@@ -69,10 +110,20 @@ find_rank (tree array, bool ignore_builtin_fn, size_t *rank)
return;
else if (TREE_CODE (array) == ARRAY_NOTATION_REF)
{
- for (ii_tree = array;
- ii_tree && TREE_CODE (ii_tree) == ARRAY_NOTATION_REF;
- ii_tree = ARRAY_NOTATION_ARRAY (ii_tree))
- current_rank++;
+ ii_tree = array;
+ while (ii_tree)
+ {
+ if (TREE_CODE (ii_tree) == ARRAY_NOTATION_REF)
+ {
+ current_rank++;
+ ii_tree = ARRAY_NOTATION_ARRAY (ii_tree);
+ }
+ else if (TREE_CODE (ii_tree) == ARRAY_REF)
+ ii_tree = TREE_OPERAND (ii_tree, 0);
+ else if (TREE_CODE (ii_tree) == PARM_DECL
+ || TREE_CODE (ii_tree) == VAR_DECL)
+ break;
+ }
if (*rank == 0)
*rank = current_rank;
}
@@ -415,7 +466,10 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
{
builtin_loop = fix_builtin_array_notation_fn (rhs_node, &new_var);
if (builtin_loop == error_mark_node)
- return error_mark_node;
+ {
+ pop_stmt_list (loop);
+ return error_mark_node;
+ }
else if (builtin_loop)
{
add_stmt (builtin_loop);
@@ -490,7 +544,7 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
rhs_base);
return error_mark_node;
}
-
+
/* Here we assign the array notation components to variable so that we can
satisfy the exec once rule. */
for (ii = 0; ii < lhs_list_size; ii++)
@@ -499,62 +553,79 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
tree array_begin = ARRAY_NOTATION_START (array_node);
tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
-
- begin_var = build_decl (location, VAR_DECL, NULL_TREE,
- integer_type_node);
- lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
- integer_type_node);
- strde_var = build_decl (location, VAR_DECL, NULL_TREE,
- integer_type_node);
-
- add_stmt (build_modify_expr (location, begin_var, TREE_TYPE (begin_var),
- NOP_EXPR, location, array_begin,
- TREE_TYPE (array_begin)));
- add_stmt (build_modify_expr (location, lngth_var, TREE_TYPE (lngth_var),
- NOP_EXPR, location, array_lngth,
- TREE_TYPE (array_lngth)));
- add_stmt (build_modify_expr (location, strde_var, TREE_TYPE (strde_var),
- NOP_EXPR, location, array_strde,
- TREE_TYPE (array_strde)));
-
- ARRAY_NOTATION_START (array_node) = begin_var;
- ARRAY_NOTATION_LENGTH (array_node) = lngth_var;
- ARRAY_NOTATION_STRIDE (array_node) = strde_var;
- }
- for (ii = 0; ii < rhs_list_size; ii++)
- {
- tree array_node = (*rhs_list)[ii];
- if (array_node && TREE_CODE (array_node) == ARRAY_NOTATION_REF)
+
+ if (TREE_CODE (array_begin) != INTEGER_CST)
{
- tree array_begin = ARRAY_NOTATION_START (array_node);
- tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
- tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
-
begin_var = build_decl (location, VAR_DECL, NULL_TREE,
integer_type_node);
- lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
- integer_type_node);
- strde_var = build_decl (location, VAR_DECL, NULL_TREE,
- integer_type_node);
-
add_stmt (build_modify_expr (location, begin_var,
TREE_TYPE (begin_var),
NOP_EXPR, location, array_begin,
TREE_TYPE (array_begin)));
+ ARRAY_NOTATION_START (array_node) = begin_var;
+ }
+ if (TREE_CODE (array_lngth) != INTEGER_CST)
+ {
+ lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
+ integer_type_node);
add_stmt (build_modify_expr (location, lngth_var,
TREE_TYPE (lngth_var),
NOP_EXPR, location, array_lngth,
TREE_TYPE (array_lngth)));
+ ARRAY_NOTATION_LENGTH (array_node) = lngth_var;
+ }
+ if (TREE_CODE (array_strde) != INTEGER_CST)
+ {
+ strde_var = build_decl (location, VAR_DECL, NULL_TREE,
+ integer_type_node);
+
add_stmt (build_modify_expr (location, strde_var,
TREE_TYPE (strde_var),
NOP_EXPR, location, array_strde,
- TREE_TYPE (array_strde)));
-
- ARRAY_NOTATION_START (array_node) = begin_var;
- ARRAY_NOTATION_LENGTH (array_node) = lngth_var;
+ TREE_TYPE (array_strde)));
ARRAY_NOTATION_STRIDE (array_node) = strde_var;
}
}
+ for (ii = 0; ii < rhs_list_size; ii++)
+ {
+ tree array_node = (*rhs_list)[ii];
+ if (array_node && TREE_CODE (array_node) == ARRAY_NOTATION_REF)
+ {
+ tree array_begin = ARRAY_NOTATION_START (array_node);
+ tree array_lngth = ARRAY_NOTATION_LENGTH (array_node);
+ tree array_strde = ARRAY_NOTATION_STRIDE (array_node);
+ if (TREE_CODE (array_begin) != INTEGER_CST)
+ {
+ begin_var = build_decl (location, VAR_DECL, NULL_TREE,
+ integer_type_node);
+ add_stmt (build_modify_expr (location, begin_var,
+ TREE_TYPE (begin_var),
+ NOP_EXPR, location, array_begin,
+ TREE_TYPE (array_begin)));
+ ARRAY_NOTATION_START (array_node) = begin_var;
+ }
+ if (TREE_CODE (array_lngth) != INTEGER_CST)
+ {
+ lngth_var = build_decl (location, VAR_DECL, NULL_TREE,
+ integer_type_node);
+ add_stmt (build_modify_expr (location, lngth_var,
+ TREE_TYPE (lngth_var),
+ NOP_EXPR, location, array_lngth,
+ TREE_TYPE (array_lngth)));
+ ARRAY_NOTATION_LENGTH (array_node) = lngth_var;
+ }
+ if (TREE_CODE (array_strde) != INTEGER_CST)
+ {
+ strde_var = build_decl (location, VAR_DECL, NULL_TREE,
+ integer_type_node);
+ add_stmt (build_modify_expr (location, strde_var,
+ TREE_TYPE (strde_var),
+ NOP_EXPR, location, array_strde,
+ TREE_TYPE (array_strde)));
+ ARRAY_NOTATION_STRIDE (array_node) = strde_var;
+ }
+ }
+ }
lhs_vector = XNEWVEC (bool *, lhs_list_size);
for (ii = 0; ii < lhs_list_size; ii++)
@@ -642,14 +713,26 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
if (lhs_rank)
{
for (ii = 0; ii < lhs_list_size; ii++)
+ for (jj = 0; jj < lhs_rank; jj++)
+ lhs_array[ii][jj] = NULL_TREE;
+
+ for (ii = 0; ii < lhs_list_size; ii++)
{
jj = 0;
- for (ii_tree = (*lhs_list)[ii];
- ii_tree && TREE_CODE (ii_tree) == ARRAY_NOTATION_REF;
- ii_tree = ARRAY_NOTATION_ARRAY (ii_tree))
+ ii_tree = (*lhs_list)[ii];
+ while (ii_tree)
{
- lhs_array[ii][jj] = ii_tree;
- jj++;
+ if (TREE_CODE (ii_tree) == ARRAY_NOTATION_REF)
+ {
+ lhs_array[ii][jj] = ii_tree;
+ jj++;
+ ii_tree = ARRAY_NOTATION_ARRAY (ii_tree);
+ }
+ else if (TREE_CODE (ii_tree) == ARRAY_REF)
+ ii_tree = TREE_OPERAND (ii_tree, 0);
+ else if (TREE_CODE (ii_tree) == VAR_DECL
+ || TREE_CODE (ii_tree) == PARM_DECL)
+ break;
}
}
}
@@ -659,18 +742,31 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
if (rhs_rank)
{
for (ii = 0; ii < rhs_list_size; ii++)
+ for (jj = 0; jj < rhs_rank; jj++)
+ rhs_array[ii][jj] = NULL_TREE;
+ for (ii = 0; ii < rhs_list_size; ii++)
{
- jj = 0;
- for (ii_tree = (*rhs_list)[ii];
- ii_tree && TREE_CODE (ii_tree) == ARRAY_NOTATION_REF;
- ii_tree = ARRAY_NOTATION_ARRAY (ii_tree))
+ jj = 0;
+ ii_tree = (*rhs_list)[ii];
+ while (ii_tree)
{
- rhs_array[ii][jj] = ii_tree;
- jj++;
+ if (TREE_CODE (ii_tree) == ARRAY_NOTATION_REF)
+ {
+ rhs_array[ii][jj] = ii_tree;
+ jj++;
+ ii_tree = ARRAY_NOTATION_ARRAY (ii_tree);
+ }
+ else if (TREE_CODE (ii_tree) == ARRAY_REF)
+ ii_tree = TREE_OPERAND (ii_tree, 0);
+ else if (TREE_CODE (ii_tree) == VAR_DECL
+ || TREE_CODE (ii_tree) == PARM_DECL)
+ break;
+ else if (TREE_CODE (ii_tree) == CALL_EXPR)
+ break;
}
}
}
-
+
for (ii = 0; ii < lhs_list_size; ii++)
{
tree lhs_node = (*lhs_list)[ii];
@@ -743,8 +839,31 @@ build_array_notation_expr (location_t location, tree lhs, tree lhs_origtype,
rhs_vector[ii][jj] = false;
}
-
-
+ if (length_mismatch_in_expr_p (EXPR_LOCATION (lhs), lhs_length,
+ lhs_list_size, lhs_rank)
+ || length_mismatch_in_expr_p (EXPR_LOCATION (rhs), rhs_length,
+ rhs_list_size, rhs_rank))
+ {
+ pop_stmt_list (loop);
+ return error_mark_node;
+ }
+
+ if (lhs_list_size > 0 && rhs_list_size > 0)
+ if (TREE_CODE (lhs_length[0][0]) == INTEGER_CST
+ && TREE_CODE (rhs_length[0][0]) == INTEGER_CST)
+ {
+ HOST_WIDE_INT l_length = int_cst_value (lhs_length[0][0]);
+ HOST_WIDE_INT r_length = int_cst_value (rhs_length[0][0]);
+ /* The length can be negative or positive. As long as the
+ magnitude is OK, then the array notation is valid. */
+ if (abs (l_length) != abs (r_length))
+ {
+ error_at (location, "length mismatch between LHS and RHS");
+ pop_stmt_list (loop);
+ return error_mark_node;
+ }
+ }
+
for (ii = 0; ii < lhs_rank; ii++)
{
if (lhs_vector[0][ii])
@@ -1768,12 +1887,26 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
|| TREE_CODE (func_parm) == NOP_EXPR)
func_parm = TREE_OPERAND (func_parm, 0);
- find_rank (an_builtin_fn, true, &rank);
+ find_rank (func_parm, false, &rank);
location = EXPR_LOCATION (an_builtin_fn);
if (rank == 0)
- return an_builtin_fn;
+ {
+ if (an_type == REDUCE_ADD || an_type == REDUCE_MUL
+ || an_type == REDUCE_MAX || an_type == REDUCE_MIN
+ || an_type == REDUCE_ALL_ZEROS || an_type == REDUCE_ANY_ZEROS
+ || an_type == REDUCE_ANY_NONZEROS || an_type == REDUCE_ALL_NONZEROS
+ || an_type == REDUCE_MAX_INDEX || an_type == REDUCE_MIN_INDEX
+ || an_type == REDUCE_CUSTOM || an_type == REDUCE_MUTATING)
+ {
+ error_at (location, "array notation builtin functions cannot have"
+ " array notation parameter with zero rank");
+ return error_mark_node;
+ }
+ else
+ return an_builtin_fn;
+ }
else if (rank > 1
&& (an_type == REDUCE_MAX_INDEX || an_type == REDUCE_MIN_INDEX))
{
@@ -2109,9 +2242,14 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
TREE_TYPE (new_yes_expr), new_no_expr, TREE_TYPE (new_no_expr));
break;
case REDUCE_MAX:
- new_var_init = build_modify_expr
- (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
- location, func_parm, new_var_type);
+ if (TYPE_MIN_VALUE (new_var_type))
+ new_var_init = build_modify_expr
+ (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+ location, TYPE_MIN_VALUE (new_var_type), new_var_type);
+ else
+ new_var_init = build_modify_expr
+ (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+ location, func_parm, new_var_type);
new_no_expr = build_modify_expr
(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
location, *new_var, TREE_TYPE (*new_var));
@@ -2124,9 +2262,14 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
new_yes_expr, TREE_TYPE (*new_var), new_no_expr, TREE_TYPE (*new_var));
break;
case REDUCE_MIN:
- new_var_init = build_modify_expr
- (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
- location, func_parm, new_var_type);
+ if (TYPE_MAX_VALUE (new_var_type))
+ new_var_init = build_modify_expr
+ (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+ location, TYPE_MAX_VALUE (new_var_type), new_var_type);
+ else
+ new_var_init = build_modify_expr
+ (location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
+ location, func_parm, new_var_type);
new_no_expr = build_modify_expr
(location, *new_var, TREE_TYPE (*new_var), NOP_EXPR,
location, *new_var, TREE_TYPE (*new_var));
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index f00d28d50c7..c761e4e3b82 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -116,29 +116,8 @@ c_parse_init (void)
C_IS_RESERVED_WORD (id) = 1;
ridpointers [(int) c_common_reswords[i].rid] = id;
}
-
- /* Here we initialize the simd_values structure. We only need it
- initialized the first time, after each consumptions, for-loop will
- automatically consume the values and delete the information. */
- cilkplus_local_simd_values.index = 0;
- cilkplus_local_simd_values.pragma_encountered = false;
- cilkplus_local_simd_values.types = P_SIMD_NOASSERT;
- cilkplus_local_simd_values.vectorlength = NULL_TREE;
- cilkplus_local_simd_values.vec_length_list = NULL;
- cilkplus_local_simd_values.vec_length_size = 0;
- cilkplus_local_simd_values.private_vars = NULL_TREE;
- cilkplus_local_simd_values.priv_var_list = NULL;
- cilkplus_local_simd_values.priv_var_size = 0;
- cilkplus_local_simd_values.linear_vars = NULL_TREE;
- cilkplus_local_simd_values.linear_var_size = 0;
- cilkplus_local_simd_values.linear_var_list = NULL;
- cilkplus_local_simd_values.linear_steps = NULL_TREE;
- cilkplus_local_simd_values.linear_steps_list = NULL;
- cilkplus_local_simd_values.linear_steps_size = 0;
- cilkplus_local_simd_values.reduction_vals = NULL;
- cilkplus_local_simd_values.ptr_next = NULL;
-
- clear_pragma_simd_list ();
+ if (flag_enable_cilk)
+ p_simd_nodes_clear ();
}
/* The C lexer intermediates between the lexer in cpplib and c-lex.c
@@ -1186,7 +1165,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 *, struct pragma_simd_values *);
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 *);
@@ -1252,11 +1231,13 @@ static void c_parser_objc_at_dynamic_declaration (c_parser *);
static bool c_parser_objc_diagnose_bad_element_prefix
(c_parser *, struct c_declspecs *);
static void c_parser_cilk_for_statement (c_parser *, tree);
-void c_parser_simd_linear (c_parser *);
-void c_parser_simd_private (c_parser *);
-void c_parser_simd_assert (c_parser *, bool);
-void c_parser_simd_vectorlength (c_parser *);
-void c_parser_simd_reduction (c_parser *);
+static void c_parser_simd_linear (c_parser *, struct pragma_simd_values *);
+static void c_parser_simd_private (c_parser *, struct pragma_simd_values *);
+static void c_parser_simd_assert (c_parser *, bool,
+ struct pragma_simd_values *);
+static void c_parser_simd_vectorlength (c_parser *,
+ struct pragma_simd_values *);
+static void c_parser_simd_reduction (c_parser *, struct pragma_simd_values *);
static tree c_parser_array_notation (location_t, c_parser *, tree, tree);
/* Parse a translation unit (C90 6.7, C99 6.9).
@@ -4573,7 +4554,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, NULL);
break;
case RID_CILK_FOR:
if (!flag_enable_cilk)
@@ -4938,8 +4919,8 @@ c_parser_while_statement (c_parser *parser)
save_cont = c_cont_label;
c_cont_label = NULL_TREE;
body = c_parser_c99_block_statement (parser);
- c_finish_loop (loc, cond, NULL, body, c_break_label, c_cont_label,
- &cilkplus_local_simd_values, true);
+ c_finish_loop (loc, cond, NULL, body, c_break_label, c_cont_label, NULL,
+ true);
add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
c_break_label = save_break;
c_cont_label = save_cont;
@@ -4983,8 +4964,7 @@ c_parser_do_statement (c_parser *parser)
}
if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
c_parser_skip_to_end_of_block_or_statement (parser);
- c_finish_loop (loc, cond, NULL, body, new_break, new_cont,
- &cilkplus_local_simd_values, false);
+ c_finish_loop (loc, cond, NULL, body, new_break, new_cont, NULL, false);
add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
}
@@ -5045,7 +5025,7 @@ c_parser_do_statement (c_parser *parser)
*/
static void
-c_parser_for_statement (c_parser *parser)
+c_parser_for_statement (c_parser *parser, struct pragma_simd_values *p_simd_val)
{
tree block, cond, incr, save_break, save_cont, body;
/* The following are only used when parsing an ObjC foreach statement. */
@@ -5200,8 +5180,7 @@ c_parser_for_statement (c_parser *parser)
objc_finish_foreach_loop (loc, object_expression, collection_expression, body, c_break_label, c_cont_label);
else
c_finish_loop (loc, cond, incr, body, c_break_label, c_cont_label,
- &cilkplus_local_simd_values,
- true);
+ p_simd_val, true);
add_stmt (c_end_compound_stmt (loc, block, flag_isoc99 || c_dialect_objc ()));
c_break_label = save_break;
c_cont_label = save_cont;
@@ -8793,513 +8772,556 @@ c_parser_objc_at_dynamic_declaration (c_parser *parser)
objc_add_dynamic_declaration (loc, list);
}
+/* Returns true of a same variable is found in sub-field vectors
+ linear_var_list, priv_var_list and reduction_list of P_SIMD_VALUES. */
-/* This function will parse the pragma simd assert in the Cilkplus
- language extension. The proper syntax are:
- #pragma simd assert
- #pragma simd noassert
- */
-void
-c_parser_simd_assert (c_parser *parser, bool is_assert)
+static bool
+same_var_in_multiple_lists_p (struct pragma_simd_values *p_simd_values)
{
- c_token *token;
+ size_t ii, jj, kk;
+ if (!p_simd_values)
+ return false;
- if (cilkplus_local_simd_values.types == 1)
- c_parser_error (parser, "multiple simd assert/noassert pragmas found");
+ /* First check linear and private lists. */
+ for (ii = 0; ii < vec_safe_length (p_simd_values->linear_var_list); ii++)
+ for (jj = 0; jj < vec_safe_length (p_simd_values->priv_var_list); jj++)
+ {
+ tree linear_var = (*(p_simd_values->linear_var_list))[ii];
+ tree priv_var = (*(p_simd_values->priv_var_list))[jj];
+ if (simple_cst_equal (linear_var, priv_var) == 1)
+ {
+ error_at (p_simd_values->loc, "ill-formed pragma: variable %qE"
+ " listed in both linear and private pragma simd clause",
+ priv_var);
+ return true;
+ }
+ }
+
+ /* Now check linear and reduction lists. */
+ for (ii = 0; ii < vec_safe_length (p_simd_values->linear_var_list); ii++)
+ for (jj = 0; jj < vec_safe_length (p_simd_values->reduction_list); jj++)
+ {
+ struct reduction_node r_node = (*(p_simd_values->reduction_list))[jj];
+ for (kk = 0; kk < vec_safe_length (r_node.reduction_vars); kk++)
+ {
+ tree linear_var = (*(p_simd_values->linear_var_list))[ii];
+ tree red_var = (*(r_node.reduction_vars))[kk];
+ if (simple_cst_equal (linear_var, red_var) == 1)
+ {
+ error_at (p_simd_values->loc,
+ "ill-formed pragma: variable %qE listed in both "
+ "reduction and linear pragma simd clause", red_var);
+ return true;
+ }
+ }
+ }
+
+ /* Finally check private and reduction lists. */
+ for (ii = 0; ii < vec_safe_length (p_simd_values->priv_var_list); ii++)
+ for (jj = 0; jj < vec_safe_length (p_simd_values->reduction_list); jj++)
+ {
+ struct reduction_node r_node = (*(p_simd_values->reduction_list))[jj];
+ for (kk = 0; kk < vec_safe_length (r_node.reduction_vars); kk++)
+ {
+ tree priv_var = (*(p_simd_values->priv_var_list))[ii];
+ tree red_var = (*(r_node.reduction_vars))[kk];
+ if (simple_cst_equal (priv_var, red_var) == 1)
+ {
+ error_at (p_simd_values->loc,
+ "ill-formed pragma: variable %qE listed in both "
+ "reduction and private pragma simd clause", red_var);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+/* Main entry point to parsing all PRAGMA SIMD (or SIMD Loops) pragmas. */
+
+static void
+c_parser_simd_construct (c_parser *parser,
+ struct pragma_simd_values *p_simd_values)
+{
+ c_token *token = c_parser_peek_token (parser);
+
+ if (token->type != CPP_PRAGMA_EOL)
+ c_parser_consume_token (parser);
+ if (!token->value
+ || !strcmp (IDENTIFIER_POINTER (token->value), "noassert"))
+ c_parser_simd_assert (parser, false, p_simd_values);
+ else if (!strcmp (IDENTIFIER_POINTER (token->value), "assert"))
+ c_parser_simd_assert (parser, false, p_simd_values);
+ else if (!strcmp (IDENTIFIER_POINTER (token->value), "vectorlength"))
+ c_parser_simd_vectorlength (parser, p_simd_values);
+ else if (!strcmp (IDENTIFIER_POINTER (token->value), "linear"))
+ c_parser_simd_linear (parser, p_simd_values);
+ else if (!strcmp (IDENTIFIER_POINTER (token->value), "private"))
+ c_parser_simd_private (parser, p_simd_values);
+ else if (!strcmp (IDENTIFIER_POINTER (token->value), "reduction"))
+ c_parser_simd_reduction (parser, p_simd_values);
else
{
- if (is_assert == true)
- cilkplus_local_simd_values.types |= P_SIMD_ASSERT;
- else
- cilkplus_local_simd_values.types |= P_SIMD_NOASSERT;
+ error_at (input_location, "pragma simd clause %s not implemented",
+ IDENTIFIER_POINTER (token->value));
+ c_parser_skip_to_pragma_eol (parser);
+ }
+}
+
+/* Parses the pragma simd assert clause of CilkPlus language extension. The
+ proper syntax are:
+ #pragma simd assert
+ #pragma simd noassert
+
+*/
+
+static void
+c_parser_simd_assert (c_parser *parser, bool is_assert,
+ struct pragma_simd_values *p_simd_values)
+{
+ c_token *token;
+
+ if (is_assert)
+ {
+ if (p_simd_values->assert_requested == P_SIMD_NOASSERT)
+ {
+ error_at (input_location, "assert and noassert cannot be used in the"
+ " same pragma");
+ c_parser_skip_to_pragma_eol (parser);
+ return;
+ }
+ p_simd_values->assert_requested = P_SIMD_ASSERT;
+ }
+ else
+ {
+ if (p_simd_values->assert_requested == P_SIMD_ASSERT)
+ {
+ error_at (input_location, "assert and noassert cannot be used in the"
+ " same pragma");
+ c_parser_skip_to_pragma_eol (parser);
+ return;
+ }
+ p_simd_values->assert_requested = P_SIMD_NOASSERT;
}
- cilkplus_local_simd_values.pragma_encountered = true;
if (c_parser_next_token_is (parser, CPP_NAME))
{
token = c_parser_peek_token (parser);
c_parser_consume_token (parser);
- if (strcmp (IDENTIFIER_POINTER (token->value), "linear") == 0)
- c_parser_simd_linear (parser);
- else if (strcmp (IDENTIFIER_POINTER (token->value), "private") == 0)
- c_parser_simd_private (parser);
- else if (strcmp (IDENTIFIER_POINTER (token->value), "vectorlength") == 0)
- c_parser_simd_vectorlength (parser);
- else if (strcmp (IDENTIFIER_POINTER (token->value), "reduction") == 0)
- c_parser_simd_reduction (parser);
- else if (strcmp (IDENTIFIER_POINTER (token->value), "assert") == 0)
- c_parser_simd_assert (parser, true);
- else if (strcmp (IDENTIFIER_POINTER (token->value), "noassert") == 0)
- c_parser_simd_assert (parser, false);
+
+ if (!strcmp (IDENTIFIER_POINTER (token->value), "linear"))
+ c_parser_simd_linear (parser, p_simd_values);
+ else if (!strcmp (IDENTIFIER_POINTER (token->value), "private"))
+ c_parser_simd_private (parser, p_simd_values);
+ else if (!strcmp (IDENTIFIER_POINTER (token->value), "reduction"))
+ c_parser_simd_reduction (parser, p_simd_values);
+ else if (!strcmp (IDENTIFIER_POINTER (token->value), "assert"))
+ c_parser_simd_assert (parser, true, p_simd_values);
+ else if (!strcmp (IDENTIFIER_POINTER (token->value), "noassert"))
+ c_parser_simd_assert (parser, false, p_simd_values);
+ else if (!strcmp (IDENTIFIER_POINTER (token->value), "vectorlength"))
+ c_parser_simd_vectorlength (parser, p_simd_values);
else
- c_parser_error (parser, "Unknown identifier");
+ {
+ error_at (input_location, "unknown pragma simd clause");
+ c_parser_skip_to_pragma_eol (parser);
+ }
}
else
{
c_parser_skip_to_pragma_eol (parser);
- if (!c_parser_next_token_is_keyword (parser, RID_FOR))
- c_parser_error (parser, "for statement expected");
- else
+ if (c_parser_next_token_is_keyword (parser, RID_FOR))
{
- if (same_var_in_multiple_lists_p (&cilkplus_local_simd_values))
- c_parser_error (parser, "ill-formed pragma: Found same variable in"
- " multiple clauses");
- /* If the pragma simd found is true, it means that we should use the
- values given in the local_pragma_simd variable. */
- c_parser_for_statement (parser);
+ if (!same_var_in_multiple_lists_p (p_simd_values))
+ c_parser_for_statement (parser, p_simd_values);
}
+ else
+ error_at (input_location, "for statement expected after pragma simd");
}
}
-/* This function will parse the pragma simd linear in the Cilkplus language
- extension. The syntax is:
- #pragma simd linear (<variable>:[<steps>], ...)
- */
+/* Parses the pragma simd linear clause in Cilk Plus language extension.
+ The syntax is:
+ #pragma simd linear (<variable>:[<steps], ... )
+*/
-void
-c_parser_simd_linear (c_parser *parser)
+static void
+c_parser_simd_linear (c_parser *parser,
+ struct pragma_simd_values *p_simd_values)
{
- tree linear_var_list = NULL_TREE, linear_steps_list = NULL_TREE;
- tree linear_var = NULL_TREE, linear_step = NULL_TREE;
+ tree linear_var, linear_step;
c_token *token;
- int ii = 0;
-
- cilkplus_local_simd_values.types |= P_SIMD_LINEAR;
- if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+
+ if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ {
+ c_parser_skip_to_pragma_eol (parser);
+ return;
+ }
+ else
{
while (true)
{
if (c_parser_next_token_is_not (parser, CPP_NAME))
{
c_parser_error (parser, "expected variable");
- c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
- linear_var_list = NULL_TREE;
- linear_steps_list = NULL_TREE;
+ c_parser_skip_to_pragma_eol (parser);
+ vec_safe_truncate (p_simd_values->linear_var_list, 0);
+ vec_safe_truncate (p_simd_values->linear_steps_list, 0);
break;
}
linear_var = c_parser_peek_token (parser)->value;
c_parser_consume_token (parser);
- linear_var_list = tree_cons (NULL_TREE, linear_var, linear_var_list);
-
+ vec_safe_push (p_simd_values->linear_var_list, linear_var);
+
if (c_parser_next_token_is (parser, CPP_COLON))
{
- c_parser_consume_token (parser);
+ c_parser_consume_token (parser);
if (c_parser_next_token_is_not (parser, CPP_NUMBER))
{
c_parser_error (parser, "expected step-size");
+ vec_safe_truncate (p_simd_values->linear_steps_list, 0);
+ vec_safe_truncate (p_simd_values->linear_var_list, 0);
c_parser_skip_to_pragma_eol (parser);
return;
}
-
linear_step = c_parser_peek_token (parser)->value;
c_parser_consume_token (parser);
-
}
else if (c_parser_next_token_is (parser, CPP_COMMA)
- || c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
+ || c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
linear_step = integer_one_node;
else
{
- c_parser_error (parser, "expected : or , after variable name");
+ c_parser_error (parser, "expected ':' or ',' after variable "
+ "name");
c_parser_skip_to_pragma_eol (parser);
return;
}
+ vec_safe_push (p_simd_values->linear_steps_list, linear_step);
+
if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
{
c_parser_consume_token (parser);
- linear_steps_list = tree_cons (NULL_TREE, linear_step,
- linear_steps_list);
break;
}
-
if (c_parser_next_token_is (parser, CPP_COMMA))
- {
- c_parser_consume_token (parser);
- linear_steps_list = tree_cons (NULL_TREE, linear_step,
- linear_steps_list);
- }
+ c_parser_consume_token (parser);
}
}
- else
- {
- c_parser_error (parser, "expected %<(%>");
- return;
- }
-
- gcc_assert (list_length (linear_steps_list) == list_length (linear_var_list));
-
- cilkplus_local_simd_values.linear_steps_size = ii;
- cilkplus_local_simd_values.linear_var_size = ii;
-
if (c_parser_next_token_is (parser, CPP_NAME))
{
token = c_parser_peek_token (parser);
c_parser_consume_token (parser);
- if (strcmp (IDENTIFIER_POINTER (token->value), "linear") == 0)
- c_parser_simd_linear (parser);
- else if (strcmp (IDENTIFIER_POINTER (token->value), "private") == 0)
- c_parser_simd_private (parser);
- else if (strcmp (IDENTIFIER_POINTER (token->value), "vectorlength") == 0)
- c_parser_simd_vectorlength (parser);
- else if (strcmp (IDENTIFIER_POINTER (token->value), "reduction") == 0)
- c_parser_simd_reduction (parser);
- else if (strcmp (IDENTIFIER_POINTER (token->value), "assert") == 0)
- c_parser_simd_assert (parser, true);
- else if (strcmp (IDENTIFIER_POINTER (token->value), "noassert") == 0)
- c_parser_simd_assert (parser, false);
+
+ if (!strcmp (IDENTIFIER_POINTER (token->value), "linear"))
+ c_parser_simd_linear (parser, p_simd_values);
+ else if (!strcmp (IDENTIFIER_POINTER (token->value), "private"))
+ c_parser_simd_private (parser, p_simd_values);
+ else if (!strcmp (IDENTIFIER_POINTER (token->value), "reduction"))
+ c_parser_simd_reduction (parser, p_simd_values);
+ else if (!strcmp (IDENTIFIER_POINTER (token->value), "assert"))
+ c_parser_simd_assert (parser, true, p_simd_values);
+ else if (!strcmp (IDENTIFIER_POINTER (token->value), "noassert"))
+ c_parser_simd_assert (parser, false, p_simd_values);
+ else if (!strcmp (IDENTIFIER_POINTER (token->value), "vectorlength"))
+ c_parser_simd_vectorlength (parser, p_simd_values);
else
- c_parser_error (parser, "Unknown identifier");
+ {
+ error_at (input_location, "unknown pragma simd clause");
+ c_parser_skip_to_pragma_eol (parser);
+ }
}
else
{
c_parser_skip_to_pragma_eol (parser);
- if (!c_parser_next_token_is_keyword (parser, RID_FOR))
- c_parser_error (parser, "for statement expected");
- else
+ if (c_parser_next_token_is_keyword (parser, RID_FOR))
{
- if (same_var_in_multiple_lists_p (&cilkplus_local_simd_values))
- c_parser_error (parser, "ill-formed pragma: Found same variable "
- "in multiple clauses ");
- /* If the pragma simd found is true, it means that we should use the
- values given in the local_pragma_simd variable. */
- c_parser_for_statement (parser);
+ if (!same_var_in_multiple_lists_p (p_simd_values))
+ c_parser_for_statement (parser, p_simd_values);
}
+ else
+ error_at (input_location, "for statement expected after pragma simd");
}
- cilkplus_local_simd_values.pragma_encountered = true;
- return;
}
-/* This function will parse the pragma simd private in the Cilkplus
- language extension. The correct syntax is:
- #pragma simd private (<variable> [, <variable>])
- */
-void
-c_parser_simd_private (c_parser *parser)
+/* Parses the private clause of simd pragma that is part of Cilk Plus language
+ extension.
+ The correct syntax is:
+ #pragma simd private (<variable> [, <variable])
+*/
+
+static void
+c_parser_simd_private (c_parser *parser,
+ struct pragma_simd_values *p_simd_values)
{
tree private_var = NULL_TREE;
- tree private_var_list = NULL_TREE;
- int ii = 0;
- tree p = NULL_TREE;
c_token *token;
-
- cilkplus_local_simd_values.types |= P_SIMD_PRIVATE;
-
- cilkplus_local_simd_values.pragma_encountered = true;
- if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ {
+ c_parser_skip_to_pragma_eol (parser);
+ vec_safe_truncate (p_simd_values->priv_var_list, 0);
+ return;
+ }
+ else
{
while (true)
{
if (c_parser_next_token_is_not (parser, CPP_NAME))
{
- c_parser_error (parser, "expected variable!");
- c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
- private_var_list = NULL_TREE;
+ error_at (input_location, "expected variable name");
+ c_parser_skip_to_pragma_eol (parser);
+ vec_safe_truncate (p_simd_values->priv_var_list, 0);
break;
}
private_var = c_parser_peek_token (parser)->value;
c_parser_consume_token (parser);
-
- private_var_list = tree_cons (NULL_TREE, private_var,
- private_var_list);
+ vec_safe_push (p_simd_values->priv_var_list, private_var);
if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
{
c_parser_consume_token (parser);
break;
}
- if (c_parser_next_token_is (parser, CPP_COMMA))
+ else if (c_parser_next_token_is (parser, CPP_COMMA))
c_parser_consume_token (parser);
}
}
- else
- c_parser_error (parser, "expected %<(%>");
- cilkplus_local_simd_values.private_vars = private_var_list;
-
- cilkplus_local_simd_values.priv_var_size = list_length (private_var_list);
- cilkplus_local_simd_values.priv_var_list = (char **)
- xmalloc (sizeof (char *) * cilkplus_local_simd_values.priv_var_size);
-
- ii = 0;
-
- for (p = private_var_list; p != NULL_TREE; p = TREE_CHAIN (p))
- {
- cilkplus_local_simd_values.priv_var_list[ii] =
- xstrdup (IDENTIFIER_POINTER (TREE_VALUE (p)));
- ii++;
- }
-
- cilkplus_local_simd_values.priv_var_size = ii;
-
if (c_parser_next_token_is (parser, CPP_NAME))
{
token = c_parser_peek_token (parser);
c_parser_consume_token (parser);
- if (strcmp (IDENTIFIER_POINTER (token->value), "linear") == 0)
- c_parser_simd_linear (parser);
- else if (strcmp (IDENTIFIER_POINTER (token->value), "private") == 0)
- c_parser_simd_private (parser);
- else if (strcmp (IDENTIFIER_POINTER (token->value), "vectorlength") == 0)
- c_parser_simd_vectorlength (parser);
- else if (strcmp (IDENTIFIER_POINTER (token->value), "reduction") == 0)
- c_parser_simd_reduction (parser);
- else if (strcmp (IDENTIFIER_POINTER (token->value), "assert") == 0)
- c_parser_simd_assert (parser, true);
- else if (strcmp (IDENTIFIER_POINTER (token->value), "noassert") == 0)
- c_parser_simd_assert (parser, false);
+
+ if (!strcmp (IDENTIFIER_POINTER (token->value), "linear"))
+ c_parser_simd_linear (parser, p_simd_values);
+ else if (!strcmp (IDENTIFIER_POINTER (token->value), "private"))
+ c_parser_simd_private (parser, p_simd_values);
+ else if (!strcmp (IDENTIFIER_POINTER (token->value), "reduction"))
+ c_parser_simd_reduction (parser, p_simd_values);
+ else if (!strcmp (IDENTIFIER_POINTER (token->value), "assert"))
+ c_parser_simd_assert (parser, true, p_simd_values);
+ else if (!strcmp (IDENTIFIER_POINTER (token->value), "noassert"))
+ c_parser_simd_assert (parser, false, p_simd_values);
+ else if (!strcmp (IDENTIFIER_POINTER (token->value), "vectorlength"))
+ c_parser_simd_vectorlength (parser, p_simd_values);
else
- c_parser_error (parser, "Unknown identifier");
+ {
+ error_at (input_location, "unknown pragma simd clause");
+ c_parser_skip_to_pragma_eol (parser);
+ }
}
else
{
c_parser_skip_to_pragma_eol (parser);
- if (!c_parser_next_token_is_keyword (parser, RID_FOR))
- c_parser_error (parser, "for statement expected");
- else
+ if (c_parser_next_token_is_keyword (parser, RID_FOR))
{
-
- if (same_var_in_multiple_lists_p(&cilkplus_local_simd_values))
- c_parser_error (parser, "ill-formed pragma: Found same variable"
- " in multiple clauses ");
-
- /* If the pragma simd found is true, it means that we should use the
- values given in the local_pragma_simd variable. */
- c_parser_for_statement (parser);
+ if (!same_var_in_multiple_lists_p (p_simd_values))
+ c_parser_for_statement (parser, p_simd_values);
}
+ else
+ error_at (input_location, "for statement expected after pragma simd");
}
-
- return;
}
-/* This function will parse the pragma simd vectorlength in the Cilkplus
- language extension. The correct syntax is:
- #pragma simd vectorlength (<INTEGER> [, <INTEGER>]*)
- */
-void
-c_parser_simd_vectorlength (c_parser *parser)
+/* Parses the vectorlength clause of SIMD pragmas that is part of Cilk Plus
+ language extension.
+
+ The correct syntax is:
+ #pragma simd vectorlength (<INTEGER> [, <INTEGER])
+*/
+
+static void
+c_parser_simd_vectorlength (c_parser *parser,
+ struct pragma_simd_values *p_simd_values)
{
- tree vec_length_list = NULL_TREE, v_length_value = NULL_TREE;
- tree p = NULL_TREE;
- int ii = 0;
- c_token *token;
- cilkplus_local_simd_values.pragma_encountered = true;
-
- if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ {
+ c_parser_skip_to_pragma_eol (parser);
+ return;
+ }
+ else
{
while (true)
{
- tree token_value = NULL_TREE;
- token_value = c_parser_expr_no_commas (parser, NULL).value;
- if (!TREE_TYPE (token_value) || !TREE_CONSTANT (token_value)
- || !INTEGRAL_TYPE_P (TREE_TYPE (token_value)))
+ tree vlength_value = c_parser_expr_no_commas (parser, NULL).value;
+ if (!TREE_TYPE (vlength_value) || !TREE_CONSTANT (vlength_value)
+ || !INTEGRAL_TYPE_P (TREE_TYPE (vlength_value)))
{
- c_parser_error (parser, "expected number");
- c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
- vec_length_list = NULL_TREE;
+ error_at (input_location, "vectorlength must be an integral "
+ "constant");
+ c_parser_skip_to_pragma_eol (parser);
+ vec_safe_truncate (p_simd_values->vec_length_list, 0);
break;
}
+ else
+ vec_safe_push (p_simd_values->vec_length_list, vlength_value);
- v_length_value = token_value;
- vec_length_list = tree_cons (NULL_TREE, v_length_value,
- vec_length_list);
if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
{
c_parser_consume_token (parser);
break;
}
- if (c_parser_next_token_is (parser, CPP_COMMA))
+ if (c_parser_next_token_is (parser, CPP_COMMA))
c_parser_consume_token (parser);
}
}
- else
- c_parser_error (parser, "expected %<(%>");
-
- cilkplus_local_simd_values.vec_length_size = list_length (vec_length_list);
-
- cilkplus_local_simd_values.vec_length_list =
- (int *)xmalloc (sizeof (int) * cilkplus_local_simd_values.vec_length_size);
-
- ii = 0;
- for (p = vec_length_list; p != NULL_TREE; p = TREE_CHAIN (p))
- {
- cilkplus_local_simd_values.vec_length_list[ii] =
- int_cst_value (TREE_VALUE (p));
- ii++;
- }
-
-
- cilkplus_local_simd_values.vectorlength = vec_length_list;
- cilkplus_local_simd_values.pragma_encountered = true;
-
if (c_parser_next_token_is (parser, CPP_NAME))
{
- token = c_parser_peek_token (parser);
+ c_token *token = c_parser_peek_token (parser);
c_parser_consume_token (parser);
- if (strcmp (IDENTIFIER_POINTER (token->value), "linear") == 0)
- c_parser_simd_linear (parser);
- else if (strcmp (IDENTIFIER_POINTER (token->value), "private") == 0)
- c_parser_simd_private (parser);
- else if (strcmp (IDENTIFIER_POINTER (token->value), "vectorlength") == 0)
- c_parser_simd_vectorlength (parser);
- else if (strcmp (IDENTIFIER_POINTER (token->value), "reduction") == 0)
- c_parser_simd_reduction (parser);
- else if (strcmp (IDENTIFIER_POINTER (token->value), "assert") == 0)
- c_parser_simd_assert (parser, true);
- else if (strcmp (IDENTIFIER_POINTER (token->value), "noassert") == 0)
- c_parser_simd_assert (parser, false);
+
+ if (!strcmp (IDENTIFIER_POINTER (token->value), "linear"))
+ c_parser_simd_linear (parser, p_simd_values);
+ else if (!strcmp (IDENTIFIER_POINTER (token->value), "private"))
+ c_parser_simd_private (parser, p_simd_values);
+ else if (!strcmp (IDENTIFIER_POINTER (token->value), "reduction"))
+ c_parser_simd_reduction (parser, p_simd_values);
+ else if (!strcmp (IDENTIFIER_POINTER (token->value), "assert"))
+ c_parser_simd_assert (parser, true, p_simd_values);
+ else if (!strcmp (IDENTIFIER_POINTER (token->value), "noassert"))
+ c_parser_simd_assert (parser, false, p_simd_values);
else
- c_parser_error (parser, "Unknown identifier");
+ {
+ error_at (input_location, "unknown pragma simd clause");
+ c_parser_skip_to_pragma_eol (parser);
+ }
}
else
{
c_parser_skip_to_pragma_eol (parser);
- if (!c_parser_next_token_is_keyword (parser, RID_FOR))
- c_parser_error (parser, "for statement expected");
- else
+ if (c_parser_next_token_is_keyword (parser, RID_FOR))
{
-
- if (same_var_in_multiple_lists_p (&cilkplus_local_simd_values))
- c_parser_error (parser, "ill-formed pragma: Found same variable in"
- " multiple clauses ");
-
- /* If the pragma simd found is true, it means that we should use the
- values given in the local_pragma_simd variable. */
- c_parser_for_statement (parser);
+ if (!same_var_in_multiple_lists_p (p_simd_values))
+ c_parser_for_statement (parser, p_simd_values);
}
+ else
+ error_at (input_location, "for statement expected after pragma simd");
}
-
- return;
}
-/* This function will parser the Pragma SIMD Reduction in the Cilkplus language
- extension. The correct syntax is:
- #pragma simd reduction (<operator>:<variable> [, <variable>]*)
- */
+/* Parses the reduction clause of SIMD pragma that is part of the Cilk Plus
+ language specification:
+ The correct syntax is:
+ #pragma simd reduction (<operator>:<variable> [, <variable>])
+*/
-void
-c_parser_simd_reduction (c_parser *parser)
+static void
+c_parser_simd_reduction (c_parser *parser,
+ struct pragma_simd_values *p_simd_values)
{
- c_token *token;
- tree var_list = NULL_TREE;
tree vars = NULL_TREE;
enum tree_code op_code = PLUS_EXPR;
+ struct reduction_node red_node;
-
- if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ memset (&red_node, 0, sizeof (struct reduction_node));
+
+ if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
{
- switch (c_parser_peek_token (parser)->type) {
- case CPP_PLUS:
- op_code = PLUS_EXPR;
- break;
- case CPP_MINUS:
- op_code = MINUS_EXPR;
- break;
- case CPP_MULT:
- op_code = MULT_EXPR;
- break;
- case CPP_AND:
- op_code = BIT_AND_EXPR;
- break;
- case CPP_OR:
- op_code = BIT_IOR_EXPR;
- break;
- case CPP_XOR:
- op_code = BIT_XOR_EXPR;
- break;
- case CPP_OR_OR:
- op_code = TRUTH_ORIF_EXPR;
- break;
- case CPP_AND_AND:
- op_code = TRUTH_ANDIF_EXPR;
- break;
- default:
- c_parser_error (parser, "expected one of the following"
- "%<+%> %<-%> %<*%> %<&%> %<|%> %<^%> %<||%> %<&&%>");
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
- var_list = NULL_TREE;
- vars = NULL_TREE;
- return;
- }
+ c_parser_skip_to_pragma_eol (parser);
+ return;
+ }
+ else
+ {
+ switch (c_parser_peek_token (parser)->type)
+ {
+ case CPP_PLUS:
+ op_code = PLUS_EXPR;
+ break;
+ case CPP_MINUS:
+ op_code = MINUS_EXPR;
+ break;
+ case CPP_MULT:
+ op_code = MULT_EXPR;
+ break;
+ case CPP_AND:
+ op_code = BIT_AND_EXPR;
+ break;
+ case CPP_OR:
+ op_code = BIT_IOR_EXPR;
+ break;
+ case CPP_XOR:
+ op_code = BIT_XOR_EXPR;
+ break;
+ case CPP_OR_OR:
+ op_code = TRUTH_ORIF_EXPR;
+ break;
+ case CPP_AND_AND:
+ op_code = TRUTH_ANDIF_EXPR;
+ break;
+ default:
+ error_at (input_location, "pragma simd reduction operators must be"
+ " one of the following: "
+ "%<+%> %<-%> %<*%> %<&%> %<|%> %<^%> %<||%> %<&&%>");
+ c_parser_skip_to_pragma_eol (parser);
+ return;
+ }
c_parser_consume_token (parser);
if (c_parser_next_token_is_not (parser, CPP_COLON))
{
c_parser_error (parser, "expected %<:%>");
- c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
- var_list = NULL_TREE;
- vars = NULL_TREE;
+ c_parser_skip_to_pragma_eol (parser);
return;
}
c_parser_consume_token (parser);
+
+ red_node.reduction_type = op_code;
while (true)
{
if (c_parser_next_token_is_not (parser, CPP_NAME))
{
c_parser_error (parser, "expected variable name");
- c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
- var_list = NULL_TREE;
- vars = NULL_TREE;
+ c_parser_skip_to_pragma_eol (parser);
break;
}
vars = c_parser_peek_token (parser)->value;
c_parser_consume_token (parser);
- var_list = tree_cons (NULL_TREE, vars, var_list);
-
+ vec_safe_push (red_node.reduction_vars, vars);
+
if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
{
c_parser_consume_token (parser);
+ vec_safe_push (p_simd_values->reduction_list, red_node);
break;
}
- if (c_parser_next_token_is (parser, CPP_COMMA))
+ if (c_parser_next_token_is (parser, CPP_COMMA))
c_parser_consume_token (parser);
}
}
- else
- c_parser_error (parser, "expected %<(%>");
-
- insert_reduction_values (&cilkplus_local_simd_values.reduction_vals, op_code,
- var_list);
- cilkplus_local_simd_values.types |= P_SIMD_REDUCTION;
- cilkplus_local_simd_values.pragma_encountered = true;
-
-
if (c_parser_next_token_is (parser, CPP_NAME))
{
- token = c_parser_peek_token (parser);
+ c_token *token = c_parser_peek_token (parser);
c_parser_consume_token (parser);
- if (strcmp (IDENTIFIER_POINTER (token->value), "linear") == 0)
- c_parser_simd_linear (parser);
- else if (strcmp (IDENTIFIER_POINTER (token->value), "private") == 0)
- c_parser_simd_private (parser);
- else if (strcmp (IDENTIFIER_POINTER (token->value), "vectorlength") == 0)
- c_parser_simd_vectorlength (parser);
- else if (strcmp (IDENTIFIER_POINTER (token->value), "reduction") == 0)
- c_parser_simd_reduction (parser);
- else if (strcmp (IDENTIFIER_POINTER (token->value), "assert") == 0)
- c_parser_simd_assert (parser, true);
- else if (strcmp (IDENTIFIER_POINTER (token->value), "noassert") == 0)
- c_parser_simd_assert (parser, false);
+
+ if (!strcmp (IDENTIFIER_POINTER (token->value), "linear"))
+ c_parser_simd_linear (parser, p_simd_values);
+ else if (!strcmp (IDENTIFIER_POINTER (token->value), "private"))
+ c_parser_simd_private (parser, p_simd_values);
+ else if (!strcmp (IDENTIFIER_POINTER (token->value), "reduction"))
+ c_parser_simd_reduction (parser, p_simd_values);
+ else if (!strcmp (IDENTIFIER_POINTER (token->value), "assert"))
+ c_parser_simd_assert (parser, true, p_simd_values);
+ else if (!strcmp (IDENTIFIER_POINTER (token->value), "noassert"))
+ c_parser_simd_assert (parser, false, p_simd_values);
else
- c_parser_error (parser, "Unknown identifier");
+ {
+ error_at (input_location, "unknown/unimplemented pragma simd clause");
+ c_parser_skip_to_pragma_eol (parser);
+ }
}
else
{
c_parser_skip_to_pragma_eol (parser);
- if (!c_parser_next_token_is_keyword (parser, RID_FOR))
+ if (c_parser_next_token_is_keyword (parser, RID_FOR))
{
- c_parser_error (parser, "for statement expected");
+ if (!same_var_in_multiple_lists_p (p_simd_values))
+ c_parser_for_statement (parser, p_simd_values);
}
- else if (same_var_in_multiple_lists_p (&cilkplus_local_simd_values))
- c_parser_error (parser, " pragma error: Found same variable in"
- " multiple clauses");
- else
- /* If the pragma simd found is true, it means that we should use the
- values given in the local_pragma_simd variable. */
- c_parser_for_statement (parser);
+ else
+ error_at (input_location, "for statement expected after pragma simd");
}
- return;
}
/* This function helps parse the grainsize pragma available in the Cilkplus
@@ -9355,7 +9377,35 @@ c_parser_cilk_grainsize (c_parser *parser)
c_parser_skip_to_pragma_eol (parser);
return;
}
-
+
+/* Helper function for c_parser_pragma. Perform some sanity checking
+ for <#pragma simd> constructs. Returns FALSE if there was a
+ problem. */
+
+static bool
+c_parser_pragma_simd_ok_p (c_parser *parser, enum pragma_context context)
+{
+ if (!flag_enable_cilk)
+ {
+ warning (0, "pragma simd ignored because -fcilkplus is not enabled");
+ c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
+ return false;
+ }
+ if (!flag_tree_vectorize)
+ {
+ warning (0, "pragma simd is useless without -ftree-vectorize");
+ c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
+ return false;
+ }
+ if (context == pragma_external)
+ {
+ c_parser_error (parser, "pragma simd must be inside a function");
+ return false;
+ }
+ return true;
+}
+
+
/* Handle pragmas. Some OpenMP pragmas are associated with, and therefore
should be considered, statements. ALLOW_STMT is true if we're within
the context of a function and such pragmas are to be allowed. Returns
@@ -9365,6 +9415,7 @@ static bool
c_parser_pragma (c_parser *parser, enum pragma_context context)
{
unsigned int id;
+ struct pragma_simd_values p_simd_values;
id = c_parser_peek_token (parser)->pragma_kind;
gcc_assert (id != PRAGMA_NONE);
@@ -9447,152 +9498,15 @@ c_parser_pragma (c_parser *parser, enum pragma_context context)
return false;
break;
- case PRAGMA_SIMD_ASSERT:
- flag_tree_vectorize = 1;
-
- if (context == pragma_external)
- {
- c_parser_error (parser,
- "pragma simd assert must be inside a function");
- return false;
- }
- if (flag_enable_cilk)
- {
- c_parser_consume_pragma (parser);
- c_parser_simd_assert (parser, true);
- }
- else
- {
- warning (0, "pragma grainsize ignored");
- c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
- }
+ case CILKPLUS_PRAGMA_SIMD:
+ if (!c_parser_pragma_simd_ok_p (parser, context))
+ return false;
+ memset (&p_simd_values, 0, sizeof (struct pragma_simd_values));
+ p_simd_values.loc = c_parser_peek_token (parser)->location;
+ c_parser_consume_pragma (parser);
+ c_parser_simd_construct (parser, &p_simd_values);
return false;
- case PRAGMA_SIMD_NOASSERT:
- flag_tree_vectorize = 1;
- if (context == pragma_external)
- {
- c_parser_error (parser,
- "pragma simd assert should be inside a function");
- return false;
- }
- if (flag_enable_cilk)
- {
- c_parser_consume_pragma (parser);
- c_parser_simd_assert (parser, false);
- }
- else
- {
- warning (0, "pragma grainsize ignored");
- c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
- }
- return false;
-
- case PRAGMA_SIMD_VECTORLENGTH:
- flag_tree_vectorize = 1;
-
- if (context == pragma_external)
- {
- c_parser_error (parser,
- "pragma simd assert should be inside a function");
- return false;
- }
- if (flag_enable_cilk)
- {
- c_parser_consume_pragma (parser);
- c_parser_simd_vectorlength (parser);
- }
- else
- {
- warning (0, "pragma grainsize ignored");
- c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
- }
- return false;
-
- case PRAGMA_SIMD_PRIVATE:
- flag_tree_vectorize = 1;
-
- if (context == pragma_external)
- {
- c_parser_error (parser,
- "pragma simd assert should be inside a function");
- return false;
- }
- if (flag_enable_cilk)
- {
- c_parser_consume_pragma (parser);
- c_parser_simd_private (parser);
- }
- else
- {
- warning (0, "pragma grainsize ignored");
- c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
- }
-
- return false;
-
- case PRAGMA_SIMD_LINEAR:
-
- flag_tree_vectorize = 1;
- if (context == pragma_external)
- {
- c_parser_error (parser,
- "pragma simd assert should be inside a function");
- return false;
- }
- if (flag_enable_cilk)
- {
- c_parser_consume_pragma (parser);
- c_parser_simd_linear (parser);
- }
- else
- {
- warning (0, "pragma grainsize ignored");
- c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
- }
- return false;
-
- case PRAGMA_SIMD_REDUCTION:
-
- flag_tree_vectorize = 1;
- if (context == pragma_external)
- {
- c_parser_error (parser,
- "pragma simd assert should be inside a function");
- return false;
- }
- if (flag_enable_cilk)
- {
- c_parser_consume_pragma (parser);
- c_parser_simd_reduction (parser);
- }
- else
- {
- warning (0, "pragma grainsize ignored");
- c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
- }
- return false;
-
- case PRAGMA_SIMD_EMPTY:
- flag_tree_vectorize = 1;
- optimize = 2;
- if (context == pragma_external)
- {
- c_parser_error (parser, "pragma simd should be inside a function");
- return false;
- }
- if (flag_enable_cilk)
- {
- c_parser_consume_pragma (parser);
- c_parser_simd_assert (parser, false);
- }
- else
- {
- warning (0, "pragma grainsize ignored");
- c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
- }
- return false;
-
default:
if (id < PRAGMA_FIRST_EXTERNAL)
{
diff --git a/gcc/c/c-pragma-simd.c b/gcc/c/c-pragma-simd.c
new file mode 100755
index 00000000000..b47a656e818
--- /dev/null
+++ b/gcc/c/c-pragma-simd.c
@@ -0,0 +1,82 @@
+/* This file is part of the Intel(R) Cilk(TM) Plus support
+ This file contains routines to handle Pragma SIMD expression
+ handling routines in the C Compiler.
+ Copyright (C) 2013 Free Software Foundation, Inc.
+ Contributed by Balaji V. Iyer <balaji.v.iyer@intel.com>,
+ Intel Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GCC is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "diagnostic-core.h"
+#include "cilk.h"
+
+/* This function is passed in as a function pointer to walk_tree. *TP is
+ the current tree pointer, *WALK_SUBTREES is set to 0 by this function if
+ recursing into TP's subtrees is unnecessary. *DATA is a bool variable that
+ is set to false if an error has occured. */
+
+static tree
+find_invalid_stmts (tree *tp, int *walk_subtrees, void *data)
+{
+ bool *valid = (bool *) data;
+ location_t loc = EXPR_HAS_LOCATION (*tp) ? EXPR_LOCATION (*tp) :
+ UNKNOWN_LOCATION;
+ if (!tp || !*tp)
+ return NULL_TREE;
+ else if (TREE_CODE (*tp) == GOTO_EXPR)
+ {
+ error_at (loc, "goto/break/continue statments are not allowed inside "
+ "loops marked with #pragma simd");
+ *valid = false;
+ *walk_subtrees = 0;
+ }
+ else if (TREE_CODE (*tp) == CALL_EXPR)
+ {
+ tree fndecl = CALL_EXPR_FN (*tp);
+
+ if (TREE_CODE (fndecl) == ADDR_EXPR)
+ fndecl = TREE_OPERAND (fndecl, 0);
+ if (TREE_CODE (fndecl) == FUNCTION_DECL)
+ {
+ if (setjmp_call_p (fndecl))
+ {
+ error_at (loc, "setjmps are not allowed inside loops marked with"
+ " #pragma simd");
+ *valid = false;
+ *walk_subtrees = 0;
+ }
+ }
+ }
+ return NULL_TREE;
+}
+
+/* Walks through all the subtrees of BODY using walk_tree to make sure invalid
+ statements/expressions are not found inside BODY. Returns false if any
+ invalid statements are found. */
+
+bool
+p_simd_valid_stmts_in_body_p (tree body)
+{
+ bool valid = true;
+ walk_tree (&body, find_invalid_stmts, (void *) &valid, NULL);
+ return valid;
+}
+
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 5c7e6ccbe61..1b101e33b73 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -9051,8 +9051,7 @@ c_finish_if_stmt (location_t if_locus, tree cond, tree then_block,
void
c_finish_loop (location_t start_locus, tree cond, tree incr, tree body,
- tree blab, tree clab,
- struct pragma_simd_values *cilkplus_ps_values,
+ tree blab, tree clab, struct pragma_simd_values *p_simd_val,
bool cond_is_first)
{
tree entry = NULL, exit = NULL, t;
@@ -9108,24 +9107,14 @@ c_finish_loop (location_t start_locus, tree cond, tree incr, tree body,
exit = fold_build3_loc (input_location,
COND_EXPR, void_type_node, cond, exit, t);
}
- if (cilkplus_ps_values)
+ if (flag_enable_cilk && p_simd_val)
{
- if (cilkplus_ps_values->pragma_encountered == true)
- LABEL_EXPR_PRAGMA_SIMD_INDEX (top) =
- psv_head_insert (*cilkplus_ps_values);
- else
+ if (!p_simd_valid_stmts_in_body_p (body))
LABEL_EXPR_PRAGMA_SIMD_INDEX (top) = INVALID_PRAGMA_SIMD_SLOT;
-
- /* Now we initialize them all to zeros. */
- cilkplus_ps_values->pragma_encountered = false;
- cilkplus_ps_values->types = P_SIMD_NOASSERT;
- cilkplus_ps_values->vectorlength = NULL_TREE;
- cilkplus_ps_values->private_vars = NULL_TREE;
- cilkplus_ps_values->linear_vars = NULL_TREE;
- cilkplus_ps_values->linear_steps = NULL_TREE;
- cilkplus_ps_values->reduction_vals = NULL;
- }
-
+ else
+ LABEL_EXPR_PRAGMA_SIMD_INDEX (top) =
+ p_simd_head_insert (p_simd_val);
+ }
add_stmt (top);
}
diff --git a/gcc/cfgloop.h b/gcc/cfgloop.h
index f24c143a203..826c26ea946 100644
--- a/gcc/cfgloop.h
+++ b/gcc/cfgloop.h
@@ -106,7 +106,7 @@ struct GTY ((chain_next ("%h.next"))) loop {
int num;
/* This holds the pragma simd index. */
- int pragma_simd_index;
+ unsigned int pragma_simd_index;
/* Number of loop insns. */
unsigned ninsns;
diff --git a/gcc/cilk.h b/gcc/cilk.h
index 7cfdd526c8b..a6ad5272c29 100644
--- a/gcc/cilk.h
+++ b/gcc/cilk.h
@@ -322,11 +322,16 @@ extern void array_notation_init_builtins (void);
extern bool is_cilk_must_expand_fn (enum built_in_function);
extern bool is_elem_fn_attribute_p (tree);
extern bool is_cilk_function_decl (tree, tree);
-extern void clear_pragma_simd_list (void);
extern tree set_cilk_except_flag (tree);
extern tree clear_cilk_except_flag (tree);
extern tree set_cilk_except_data (tree);
extern void c_install_body_with_frame_cleanup (tree, tree);
tree build_cilk_catch_sync (void);
-extern bool pragma_simd_is_private_var (int, tree);
+extern void p_simd_nodes_clear (void);
+extern unsigned int p_simd_head_insert (struct pragma_simd_values *);
+extern bool pragma_simd_is_private_var_p (unsigned int, tree);
+extern bool pragma_simd_is_linear_var_p (unsigned int, tree);
+extern void set_OK_for_certain_clause (enum pragma_simd_kind, bool,
+ unsigned int);
+extern bool pragma_simd_acceptable_vlength_p (unsigned int, int, tree);
#endif /* GCC_CILK_H */
diff --git a/gcc/cp/ChangeLog.cilkplus b/gcc/cp/ChangeLog.cilkplus
index d2cbd5440ce..1da5e1a3c91 100644
--- a/gcc/cp/ChangeLog.cilkplus
+++ b/gcc/cp/ChangeLog.cilkplus
@@ -1,3 +1,37 @@
+2013-04-19 Balaji V. Iyer <balaji.v.iyer@intel.com>
+
+ * cp-array-notation.c (fix_builtin_array_notation_fn): Fixed a bug of
+ switching the true and false condition in array notation reduction
+ functions.
+ (fix_unary_array_notation_exprs): Replaced appending to statement lists
+ with pushing and popping of statements along with add statement.
+ (build_x_array_notation_expr): Added a check for array notation length
+ mismatch. Also added a check for CALL_EXPR.
+ (length_mismatch_in_expr_p): New function.
+ (fix_builtin_array_notation_fn): Added a check to see if max/min value
+ is available for the type. If so, set it as the starting point for
+ min and max reduction function.
+ * parser.c (cp_parser_array_notation): Added a new location parameter.
+ * Make-lang.in (CXX_AND_OBJCXX_OBJS): Added cp/cp-pragma-simd.o.
+ * parser.c (cp_lexer_new_main): Removed cilkplus_local_simd_values
+ global variable.
+ (cp_parser_for): Likewise.
+ (cp_parser_simd_handle_next_clause): New function.
+ (cp_parser_simd_construct): Likewise.
+ (same_var_in_multiple_lists_p): Likewise.
+ (cp_parser_pragma): Added CILKPLUS_PRAGMA_SIMD case. Removed the
+ following cases: PRAGMA_SIMD_ASSERT, PRAGMA_SIMD_EMPTY,
+ PRAGMA_SIMD_NOASSERT, PRAGMA_SIMD_VECTORLENGTH, PRAGMA_SIMD_PRIVATE,
+ and PRAGMA_SIMD_LINEAR.
+ (cp_parser_simd_assert): Changed the function to use vecs instead of
+ mallocs, TREE_LIST and arrays. Also, added a new parameter to pass in
+ pragma simd information.
+ (cp_parser_simd_vectorlength): Likewise.
+ (cp_parser_simd_linear): Likewise.
+ (cp_parser_simd_private): Likewise.
+ (cp_parser_simd_reduction): Likewise.
+ * cp-pragma-simd.c: New file.
+
2013-04-05 Balaji V. Iyer <balaji.v.iyer@intel.com>
* cp-array-notation.c (build_x_array_notation_expr): Made checking for
diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in
index 12e3800673c..488315135c5 100644
--- a/gcc/cp/Make-lang.in
+++ b/gcc/cp/Make-lang.in
@@ -85,7 +85,8 @@ CXX_AND_OBJCXX_OBJS = cp/call.o cp/decl.o cp/expr.o cp/pt.o cp/typeck2.o \
cp/typeck.o cp/cvt.o cp/except.o cp/friend.o cp/init.o cp/method.o \
cp/search.o cp/semantics.o cp/tree.o cp/repo.o cp/dump.o cp/optimize.o \
cp/mangle.o cp/cp-objcp-common.o cp/name-lookup.o cp/cxx-pretty-print.o \
- cp/cp-gimplify.o cp/cp-cilk.o cp/cp-array-notation.o $(CXX_C_OBJS)
+ cp/cp-gimplify.o cp/cp-cilk.o cp/cp-array-notation.o cp/cp-pragma-simd.o \
+ $(CXX_C_OBJS)
# Language-specific object files for C++.
CXX_OBJS = cp/cp-lang.o c-family/stub-objc.o $(CXX_AND_OBJCXX_OBJS)
@@ -275,6 +276,9 @@ cp/cp-array-notation.o: cp/cp-array-notation.c $(CXX_TREE_H) $(TM_H) \
$(FLAGS_H) toplev.h $(DIAGNOSTIC_H) convert.h $(C_COMMON_H) $(TARGET_H) \
output.h c-family/c-objc.h
+cp/cp-pragma-simd.o: cp/cp-pragma-simd.c $(CXX_TREE_H) $(FLAGS_H) \
+ $(DIAGNOSTIC_H) $(CILK_H)
+
cp/lex.o: cp/lex.c $(CXX_TREE_H) $(TM_H) $(FLAGS_H) \
$(C_PRAGMA_H) input.h cp/operators.def $(TM_P_H) \
c-family/c-objc.h
diff --git a/gcc/cp/cp-array-notation.c b/gcc/cp/cp-array-notation.c
index d25c3a60bf3..d71397833b9 100644
--- a/gcc/cp/cp-array-notation.c
+++ b/gcc/cp/cp-array-notation.c
@@ -55,6 +55,52 @@ struct inv_list
int array_notation_label_no;
+/* Returns false if there is a length mismatch among expressions
+ on the same dimension AND the same side of the equal sign. The exprs are
+ passed in through 2-D array **LIST where X and Y indicate first and
+ second dimension sizes of LIST, respectively. */
+static bool
+length_mismatch_in_expr_p (location_t loc, tree **list, size_t x, size_t y)
+{
+ size_t ii, jj;
+ tree start = NULL_TREE;
+ HOST_WIDE_INT l_start, l_node;
+ for (jj = 0; jj < y; jj++)
+ {
+ start = NULL_TREE;
+ for (ii = 0; ii < x; ii++)
+ {
+ if (!start)
+ start = list[ii][jj];
+ else if (TREE_CODE (start) == INTEGER_CST)
+ {
+ /* If start is a INTEGER, and list[ii][jj] is an integer then
+ check if they are equal. If they are not equal then return
+ true. */
+ if (TREE_CODE (list[ii][jj]) == INTEGER_CST)
+ {
+ l_node = int_cst_value (list[ii][jj]);
+ l_start = int_cst_value (start);
+ if (abs (l_start) != abs (l_node))
+ {
+ if (!loc && EXPR_HAS_LOCATION (start))
+ loc = EXPR_LOCATION (start);
+ if (!loc && EXPR_HAS_LOCATION (list[ii][jj]))
+ loc = EXPR_LOCATION (list[ii][jj]);
+ error_at (loc, "length mismatch in expression");
+ return true;
+ }
+ }
+ }
+ else
+ /* We set the start node as the current node just in case it turns
+ out to be an integer. */
+ start = list[ii][jj];
+ }
+ }
+ return false;
+}
+
/* Returns the rank of ARRAY through the *RANK. The user can specify whether
(s)he wants to step into array_notation-specific builtin functions
(specified by the IGNORE_BUILTIN_FN).
@@ -437,6 +483,8 @@ build_x_array_notation_expr (location_t location, tree lhs,
char label_name[50];
int s_jj = 0;
+ if (!location && EXPR_HAS_LOCATION (lhs))
+ location = EXPR_LOCATION (lhs);
/* In the first part, we try to break up the builtin functions for array
notations. */
find_rank (rhs, false, &rhs_rank);
@@ -517,7 +565,7 @@ build_x_array_notation_expr (location_t location, tree lhs,
{
new_modify_expr = build_x_modify_expr (location, lhs,
modifycode, rhs, complain);
- add_stmt (finish_expr_stmt (new_modify_expr));
+ finish_expr_stmt (new_modify_expr);
pop_stmt_list (loop);
return loop;
}
@@ -705,6 +753,8 @@ build_x_array_notation_expr (location_t location, tree lhs,
else if (TREE_CODE (ii_tree) == VAR_DECL
|| TREE_CODE (ii_tree) == PARM_DECL)
break;
+ else if (TREE_CODE (ii_tree) == CALL_EXPR)
+ break;
}
}
}
@@ -778,6 +828,30 @@ build_x_array_notation_expr (location_t location, tree lhs,
else
rhs_vector[ii][0] = false;
}
+ if (length_mismatch_in_expr_p (location ? location : EXPR_LOCATION (lhs),
+ lhs_length, lhs_list_size, lhs_rank)
+ || length_mismatch_in_expr_p (location ? location : EXPR_LOCATION (rhs),
+ rhs_length, rhs_list_size, rhs_rank))
+ {
+ pop_stmt_list (loop);
+ return error_mark_node;
+ }
+ if (lhs_list_size > 0 && rhs_list_size > 0)
+ if (TREE_CODE (lhs_length[0][0]) == INTEGER_CST
+ && TREE_CODE (rhs_length[0][0]) == INTEGER_CST)
+ {
+ HOST_WIDE_INT l_length = int_cst_value (lhs_length[0][0]);
+ HOST_WIDE_INT r_length = int_cst_value (rhs_length[0][0]);
+ /* The length can be negative or positive. As long as the
+ magnitude is OK, then the array notation is valid. */
+ if (abs (l_length) != abs (r_length))
+ {
+ error_at (location, "length mismatch between LHS and RHS");
+ pop_stmt_list (loop);
+ return error_mark_node;
+ }
+ }
+
for (ii = 0; ii < lhs_rank; ii++)
if (lhs_start[0][ii] && TREE_TYPE (lhs_start[0][ii]))
lhs_var[ii] = build_decl (location, VAR_DECL, NULL_TREE,
@@ -964,7 +1038,7 @@ build_x_array_notation_expr (location_t location, tree lhs,
(location, lhs_array_opr,
build2 (MINUS_EXPR, TREE_TYPE (var), start,
build2 (MULT_EXPR, TREE_TYPE (var), var,
- stride)));
+ stride)));
else
/* Array[start_index + (induction_var * stride)] */
lhs_array_opr = grok_array_decl
@@ -1046,7 +1120,7 @@ build_x_array_notation_expr (location_t location, tree lhs,
(location, rhs_array_opr,
build2 (MINUS_EXPR, TREE_TYPE (var), start,
build2 (MULT_EXPR, TREE_TYPE (var), var,
- stride)));
+ stride)));
else
/* Array[start_index + (induction_var * stride)] */
rhs_array_opr = grok_array_decl
@@ -1803,9 +1877,9 @@ fix_array_notation_exprs (tree t)
case STATEMENT_LIST:
{
tree_stmt_iterator i;
+
for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i))
- *tsi_stmt_ptr (i) =
- fix_array_notation_exprs (*tsi_stmt_ptr (i));
+ *tsi_stmt_ptr (i) = fix_array_notation_exprs (*tsi_stmt_ptr (i));
return t;
}
@@ -2018,12 +2092,26 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
|| TREE_CODE (func_parm) == NOP_EXPR)
func_parm = TREE_OPERAND (func_parm, 0);
- find_rank (an_builtin_fn, false, &rank);
+ find_rank (func_parm, true, &rank);
location = EXPR_LOCATION (an_builtin_fn);
if (rank == 0)
- return an_builtin_fn;
+ {
+ if (an_type == REDUCE_ADD || an_type == REDUCE_MUL
+ || an_type == REDUCE_MAX || an_type == REDUCE_MIN
+ || an_type == REDUCE_ALL_ZEROS || an_type == REDUCE_ANY_ZEROS
+ || an_type == REDUCE_ANY_NONZEROS || an_type == REDUCE_ALL_NONZEROS
+ || an_type == REDUCE_MAX_INDEX || an_type == REDUCE_MIN_INDEX
+ || an_type == REDUCE_CUSTOM || an_type == REDUCE_MUTATING)
+ {
+ error_at (location, "array notation builtin functions cannot have"
+ " array notation parameter with zero rank");
+ return error_mark_node;
+ }
+ else
+ return an_builtin_fn;
+ }
else if (rank > 1
&& (an_type == REDUCE_MAX_INDEX || an_type == REDUCE_MIN_INDEX))
{
@@ -2383,10 +2471,10 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
/* Initially we assume there are NO zeros in the list. When we find a
non-zero, we keep the previous value. If we find a zero, we set the
value to true. */
- new_no_expr = build_x_modify_expr
+ new_yes_expr = build_x_modify_expr
(location, *new_var, NOP_EXPR,
build_one_cst (TREE_TYPE (*new_var)), 1);
- new_yes_expr = build_x_modify_expr (location, *new_var, NOP_EXPR,
+ new_no_expr = build_x_modify_expr (location, *new_var, NOP_EXPR,
*new_var, 1);
if (ARITHMETIC_TYPE_P (TREE_TYPE (func_parm)))
comp_node = build_zero_cst (TREE_TYPE (func_parm));
@@ -2407,10 +2495,10 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
/* Initially we assume there are NO non-zeros in the list. When we find a
zero, we keep the previous value. If we find a zero, we set the value
to true. */
- new_no_expr = build_x_modify_expr
+ new_yes_expr = build_x_modify_expr
(location, *new_var, NOP_EXPR,
build_one_cst (TREE_TYPE (*new_var)), 1);
- new_yes_expr = build_x_modify_expr (location, *new_var, NOP_EXPR,
+ new_no_expr = build_x_modify_expr (location, *new_var, NOP_EXPR,
*new_var, 1);
if (ARITHMETIC_TYPE_P (TREE_TYPE (func_parm)))
comp_node = build_zero_cst (TREE_TYPE (func_parm));
@@ -2425,9 +2513,16 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
}
else if (an_type == REDUCE_MAX)
{
- /* Set initial value as the first element in the list. */
- new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR,
- func_parm, 1);
+ if (TYPE_MIN_VALUE (TREE_TYPE (*new_var)))
+ new_var_init =
+ build_x_modify_expr (location, *new_var, NOP_EXPR,
+ TYPE_MIN_VALUE (TREE_TYPE (*new_var)), 1);
+ else
+ /* Set initial value as the first element in the list if a MIN Value is
+ not defined. */
+ new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR,
+ func_parm, 1);
+
new_no_expr = build_x_modify_expr (location, *new_var, NOP_EXPR,
*new_var, 1);
new_yes_expr = build_x_modify_expr (location, *new_var, NOP_EXPR,
@@ -2442,8 +2537,15 @@ fix_builtin_array_notation_fn (tree an_builtin_fn, tree *new_var)
}
else if (an_type == REDUCE_MIN)
{
- new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR,
- func_parm, 1);
+ if (TYPE_MAX_VALUE (TREE_TYPE (*new_var)))
+ new_var_init =
+ build_x_modify_expr (location, *new_var, NOP_EXPR,
+ TYPE_MAX_VALUE (TREE_TYPE (*new_var)), 1);
+ else
+ /* Set initial value as the first element in the list if a MIN Value is
+ not defined. */
+ new_var_init = build_x_modify_expr (location, *new_var, NOP_EXPR,
+ func_parm, 1);
new_no_expr = build_x_modify_expr (location, *new_var, NOP_EXPR,
*new_var, 1);
new_yes_expr = build_x_modify_expr (location, *new_var, NOP_EXPR,
@@ -2642,11 +2744,25 @@ fix_unary_array_notation_exprs (tree orig_stmt)
bool **count_down, **array_vector;
tree builtin_loop, stmt = NULL_TREE, new_var = NULL_TREE;
char label_name[50];
+ array_notation_reduce_type dummy;
location_t location = UNKNOWN_LOCATION;
find_rank (orig_stmt, false, &rank);
if (rank == 0)
- return orig_stmt;
+ {
+ if (TREE_CODE (orig_stmt) == CALL_EXPR
+ && is_builtin_array_notation_fn (CALL_EXPR_FN (orig_stmt), &dummy))
+ {
+ /* If we are here, it is almost 100% that there is an error. We
+ let the function to handle array notation function to emit the
+ error. */
+ builtin_loop = fix_builtin_array_notation_fn (orig_stmt, &new_var);
+ if (builtin_loop == error_mark_node)
+ return builtin_loop;
+ }
+ else
+ return orig_stmt;
+ }
extract_array_notation_exprs (orig_stmt, false, &array_list);
list_size = vec_safe_length (array_list);
@@ -2665,8 +2781,8 @@ fix_unary_array_notation_exprs (tree orig_stmt)
else if (builtin_loop)
{
vec<tree, va_gc> *sub_list = NULL, *new_var_list = NULL;
- stmt = alloc_stmt_list ();
- append_to_statement_list_force (builtin_loop, &stmt);
+ stmt = push_stmt_list ();
+ add_stmt (builtin_loop);
vec_safe_push (sub_list, list_node);
vec_safe_push (new_var_list, new_var);
replace_array_notations (&orig_stmt, false, sub_list,
@@ -2675,7 +2791,10 @@ fix_unary_array_notation_exprs (tree orig_stmt)
}
}
if (stmt != NULL_TREE)
- append_to_statement_list_force (finish_expr_stmt (orig_stmt), &stmt);
+ {
+ finish_expr_stmt (orig_stmt);
+ stmt = pop_stmt_list (stmt);
+ }
else
stmt = orig_stmt;
rank = 0;
@@ -2869,7 +2988,7 @@ fix_unary_array_notation_exprs (tree orig_stmt)
array_opr = grok_array_decl
(location, array_opr,
build2 (MINUS_EXPR, TREE_TYPE (var), start,
- build2 (MULT_EXPR, TREE_TYPE (var), var, stride)));
+ build2 (MULT_EXPR, TREE_TYPE (var), var, stride)));
else
/* Array[start_index + (induction_var * stride)] */
array_opr = grok_array_decl
diff --git a/gcc/cp/cp-pragma-simd.c b/gcc/cp/cp-pragma-simd.c
new file mode 100755
index 00000000000..347d6a5dc7a
--- /dev/null
+++ b/gcc/cp/cp-pragma-simd.c
@@ -0,0 +1,118 @@
+
+/* This file is part of the Intel(R) Cilk(TM) Plus support
+ This file contains routines to handle Pragma SIMD expression
+ handling routines in the C Compiler.
+ Copyright (C) 2013 Free Software Foundation, Inc.
+ Contributed by Balaji V. Iyer <balaji.v.iyer@intel.com>,
+ Intel Corporation.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GCC is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "cp-tree.h"
+#include "diagnostic-core.h"
+
+
+/* This function is passed in as a function pointer to walk_tree. *TP is
+ the current tree pointer, *WALK_SUBTREES is set to 0 by this function if
+ recursing into TP's subtrees is unnecessary. *DATA is a bool variable that
+ is set to false if an error has occured. */
+
+static tree
+find_invalid_stmts (tree *tp, int *walk_subtrees, void *data)
+{
+ bool *valid = (bool *) data;
+ location_t loc = EXPR_HAS_LOCATION (*tp) ? EXPR_LOCATION (*tp) :
+ UNKNOWN_LOCATION;
+ if (!tp || !*tp)
+ return NULL_TREE;
+ else if (TREE_CODE (*tp) == GOTO_EXPR)
+ {
+ error_at (loc, "goto statements are not allowed inside "
+ "loops marked with #pragma simd");
+ *valid = false;
+ *walk_subtrees = 0;
+ }
+ else if (TREE_CODE (*tp) == BREAK_STMT)
+ {
+ error_at (loc, "break statements are not allowed inside loop marked "
+ "with pragma simd");
+ *valid = false;
+ *walk_subtrees = 0;
+ }
+ else if (TREE_CODE (*tp) == CONTINUE_STMT)
+ {
+ error_at (loc, "continue statements are not allowed inside the loop "
+ "marked with pragma simd");
+ *walk_subtrees = 0;
+ *valid = false;
+ }
+ else if (TREE_CODE (*tp) == THROW_EXPR)
+ {
+ error_at (loc, "throw expressions are not allowed inside the loop "
+ "marked with pragma simd");
+ *walk_subtrees = 0;
+ *valid = false;
+ }
+ else if (TREE_CODE (*tp) == TRY_BLOCK)
+ {
+ error_at (loc, "try statements are not allowed inside loop marked with "
+ "#pragma simd");
+ *valid = false;
+ *walk_subtrees = 0;
+ }
+ else if (TREE_CODE (*tp) == CILK_FOR_STMT)
+ {
+ error_at (loc, "_Cilk_for statements are not allowed inside loop marked "
+ "with #pragma simd");
+ *valid = false;
+ *walk_subtrees = 0;
+ }
+ else if (TREE_CODE (*tp) == CALL_EXPR)
+ {
+ tree fndecl = CALL_EXPR_FN (*tp);
+
+ if (TREE_CODE (fndecl) == ADDR_EXPR)
+ fndecl = TREE_OPERAND (fndecl, 0);
+ if (TREE_CODE (fndecl) == FUNCTION_DECL)
+ {
+ if (setjmp_call_p (fndecl))
+ {
+ error_at (loc, "setjmps are not allowed inside loops marked with"
+ " #pragma simd");
+ *valid = false;
+ *walk_subtrees = 0;
+ }
+ }
+ }
+ return NULL_TREE;
+}
+
+
+/* Walks through all the subtrees of BODY using walk_tree to make sure invalid
+ statements/expressions are not found inside BODY. Returns false if any
+ invalid statements are found. */
+
+bool
+p_simd_valid_stmts_in_body_p (tree body)
+{
+ bool valid = true;
+ cp_walk_tree (&body, find_invalid_stmts, (void *) &valid, NULL);
+ return valid;
+}
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 6f3b4a583a6..774f51612e3 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -44,7 +44,7 @@ extern int array_notation_label_no;
extern void extract_array_notation_exprs (tree, bool, tree **, int *);
extern tree fix_unary_array_notation_exprs (tree);
extern bool contains_array_notation_expr (tree);
-struct pragma_simd_values cilkplus_local_simd_values;
+
/* The lexer. */
@@ -238,7 +238,7 @@ static tree cp_literal_operator_id
(const char *);
static tree cp_parser_array_notation
- (cp_parser *, tree, tree);
+ (location_t, cp_parser *, tree, tree);
static vec<tree, va_gc> *cp_parser_elem_fn_expression_list
(cp_parser *);
@@ -621,30 +621,7 @@ cp_lexer_new_main (void)
gcc_assert (!lexer->next_token->purged_p);
- /* Here we initialize the cilkplus_local_simd_values structure. We only need
- it initialized the first time, after each consumptions, for-loop will
- automatically consume the values and delete the information. */
- cilkplus_local_simd_values.index = 0;
- cilkplus_local_simd_values.pragma_encountered = false;
- cilkplus_local_simd_values.types = P_SIMD_NOASSERT;
- cilkplus_local_simd_values.vectorlength = NULL_TREE;
- cilkplus_local_simd_values.vec_length_list = NULL;
- cilkplus_local_simd_values.vec_length_size = 0;
- cilkplus_local_simd_values.private_vars = NULL_TREE;
- cilkplus_local_simd_values.priv_var_list = NULL;
- cilkplus_local_simd_values.priv_var_size = 0;
-
- cilkplus_local_simd_values.linear_vars = NULL_TREE;
- cilkplus_local_simd_values.linear_var_size = 0;
- cilkplus_local_simd_values.linear_var_list = NULL;
- cilkplus_local_simd_values.linear_steps = NULL_TREE;
- cilkplus_local_simd_values.linear_steps_list = NULL;
- cilkplus_local_simd_values.linear_steps_size = 0;
- cilkplus_local_simd_values.reduction_vals = NULL;
- cilkplus_local_simd_values.ptr_next = NULL;
-
- clear_pragma_simd_list ();
-
+
array_notation_label_no = 0;
return lexer;
@@ -2393,15 +2370,16 @@ static tree cp_parser_cilk_for_condition
static tree cp_parser_cilk_for_expression_iterator
(cp_parser *parser);
static void cp_parser_simd_vectorlength
- (cp_parser *parser, cp_token *pragma_token);
+ (cp_parser *parser, cp_token *pragma_token, struct pragma_simd_values *);
static void cp_parser_simd_private
- (cp_parser *parser, cp_token *pragma_token);
+ (cp_parser *parser, cp_token *pragma_token, struct pragma_simd_values *);
static void cp_parser_simd_reduction
- (cp_parser *parser, cp_token *pragma_token);
+ (cp_parser *parser, cp_token *pragma_token, struct pragma_simd_values *);
static void cp_parser_simd_linear
- (cp_parser *parser, cp_token *pragma_token);
+ (cp_parser *parser, cp_token *pragma_token, struct pragma_simd_values *);
static void cp_parser_simd_assert
- (cp_parser *parser, cp_token *pragma_token, bool is_assert);
+ (cp_parser *parser, cp_token *pragma_token, bool is_assert,
+ struct pragma_simd_values *);
/* Returns nonzero if we are parsing tentatively. */
@@ -6093,7 +6071,7 @@ cp_parser_postfix_open_square_expression (cp_parser *parser,
/* If we reach here, then we have something like this:
ARRAY [:]
*/
- postfix_expression = cp_parser_array_notation (parser, NULL_TREE,
+ postfix_expression = cp_parser_array_notation (loc, parser, NULL_TREE,
postfix_expression);
else
{
@@ -6132,7 +6110,7 @@ cp_parser_postfix_open_square_expression (cp_parser *parser,
}
if (flag_enable_cilk
&& cp_lexer_peek_token (parser->lexer)->type == CPP_COLON)
- postfix_expression = cp_parser_array_notation (parser, index,
+ postfix_expression = cp_parser_array_notation (loc, parser, index,
postfix_expression);
else
{
@@ -9749,24 +9727,13 @@ cp_parser_for (cp_parser *parser, struct pragma_simd_values *cilkplus_ps_values)
if (!is_range_for && statement != error_mark_node)
{
- if (cilkplus_ps_values != NULL)
- {
- FOR_STMT_PRAGMA_SIMD_INDEX (statement) =
- psv_head_insert (*cilkplus_ps_values);
- /* Now we initialize them all to zeros. */
- cilkplus_ps_values->pragma_encountered = false;
- cilkplus_ps_values->types = P_SIMD_NOASSERT;
- cilkplus_ps_values->vectorlength = NULL_TREE;
- cilkplus_ps_values->private_vars = NULL_TREE;
- cilkplus_ps_values->linear_vars = NULL_TREE;
- cilkplus_ps_values->linear_steps = NULL_TREE;
- cilkplus_ps_values->reduction_vals = NULL;
- }
+ if (flag_enable_cilk && cilkplus_ps_values
+ && p_simd_valid_stmts_in_body_p (FOR_BODY (statement)))
+ FOR_STMT_PRAGMA_SIMD_INDEX (statement) =
+ p_simd_head_insert (cilkplus_ps_values);
else
FOR_STMT_PRAGMA_SIMD_INDEX (statement) = INVALID_PRAGMA_SIMD_SLOT;
}
-
-
return statement;
}
@@ -28851,12 +28818,59 @@ cp_parser_initial_pragma (cp_token *first_token)
cp_lexer_get_preprocessor_token (NULL, first_token);
}
+/* Handles the parsing of next clause for pragma simd. */
+
+static void
+cp_parser_simd_handle_next_clause (cp_parser *parser, const char *token_name,
+ cp_token *pragma_token,
+ struct pragma_simd_values *p_simd_values)
+{
+ if (!strcmp (token_name, "linear"))
+ cp_parser_simd_linear (parser, pragma_token, p_simd_values);
+ else if (!strcmp (token_name, "private"))
+ cp_parser_simd_private (parser, pragma_token, p_simd_values);
+ else if (!strcmp (token_name, "reduction"))
+ cp_parser_simd_reduction (parser, pragma_token, p_simd_values);
+ else if (!strcmp (token_name, "assert"))
+ cp_parser_simd_assert (parser, pragma_token, true, p_simd_values);
+ else if (!strcmp (token_name, "noassert"))
+ cp_parser_simd_assert (parser, pragma_token, false, p_simd_values);
+ else if (!strcmp (token_name, "vectorlength"))
+ cp_parser_simd_vectorlength (parser, pragma_token, p_simd_values);
+ else
+ {
+ error_at (input_location, "unknown pragma simd clause: %s",
+ token_name);
+ cp_parser_skip_to_pragma_eol (parser, pragma_token);
+ }
+}
+
+static void
+cp_parser_simd_construct (cp_parser *parser, cp_token *pragma_token,
+ struct pragma_simd_values *p_simd_values)
+{
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+
+ if (token->type != CPP_PRAGMA_EOL)
+ cp_lexer_consume_token (parser->lexer);
+
+ /* This would mean that it has reached CPP_PRAGMA_EOL. */
+ if (!token->u.value || token->type == CPP_PRAGMA_EOL)
+ cp_parser_simd_assert (parser, pragma_token, false, p_simd_values);
+ else
+ cp_parser_simd_handle_next_clause (parser,
+ IDENTIFIER_POINTER (token->u.value),
+ pragma_token, p_simd_values);
+}
+
+
/* Normal parsing of a pragma token. Here we can (and must) use the
regular lexer. */
static bool
cp_parser_pragma (cp_parser *parser, enum pragma_context context)
{
+ struct pragma_simd_values p_simd_values;
cp_token *pragma_tok;
unsigned int id;
@@ -28966,59 +28980,12 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
}
cp_parser_cilk_grainsize (parser, pragma_tok);
return true;
-
- case PRAGMA_SIMD_ASSERT:
- if (context == pragma_external)
- {
- error("%<#pragma simd assert%> may only be used inside a function");
- break;
- }
- cp_parser_simd_assert (parser, pragma_tok, true);
- return true;
- case PRAGMA_SIMD_NOASSERT:
- if (context == pragma_external)
- {
- error("%<#pragma simd assert%> may only be used inside a function");
- break;
- }
- cp_parser_simd_assert (parser, pragma_tok, false);
- return true;
-
- case PRAGMA_SIMD_VECTORLENGTH:
- if (context == pragma_external)
- {
- error("%<#pragma simd vectorlength%> may only be used inside a function");
- break;
- }
- cp_parser_simd_vectorlength (parser, pragma_tok);
- return true;
-
- case PRAGMA_SIMD_PRIVATE:
- if (context == pragma_external)
- {
- error("%<#pragma simd private%> may only be used inside a function");
- break;
- }
- cp_parser_simd_private (parser, pragma_tok);
- return true;
-
- case PRAGMA_SIMD_LINEAR:
+ case CILKPLUS_PRAGMA_SIMD:
if (context == pragma_external)
- {
- error("%<#pragma simd linear%> may only be used inside a function");
- break;
- }
- cp_parser_simd_linear (parser, pragma_tok);
- return true;
-
- case PRAGMA_SIMD_REDUCTION:
- if (context == pragma_external)
- {
- error("%<#pragma simd reduction%> may only be used inside a function");
- break;
- }
- cp_parser_simd_reduction (parser, pragma_tok);
+ goto bad_stmt;
+ memset (&p_simd_values, 0, sizeof (struct pragma_simd_values));
+ cp_parser_simd_construct (parser, pragma_tok, &p_simd_values);
return true;
default:
@@ -29382,510 +29349,458 @@ cp_parser_cilk_for_expression_iterator (cp_parser *parser)
build2 (t_code, TREE_TYPE (name), name, expr));
}
-/* This function will parse the pragma simd vectorlength. */
+/* Returns true of a same variable is found in sub-field vectors
+ linear_var_list, priv_var_list and reduction_list of P_SIMD_VALUES. */
+
+static bool
+same_var_in_multiple_lists_p (struct pragma_simd_values *p_simd_values)
+{
+ size_t ii, jj, kk;
+ if (!p_simd_values)
+ return false;
+
+ /* First check linear and private lists. */
+ for (ii = 0; ii < vec_safe_length (p_simd_values->linear_var_list); ii++)
+ for (jj = 0; jj < vec_safe_length (p_simd_values->priv_var_list); jj++)
+ {
+ tree linear_var = (*(p_simd_values->linear_var_list))[ii];
+ tree priv_var = (*(p_simd_values->priv_var_list))[jj];
+ if (simple_cst_equal (linear_var, priv_var) == 1)
+ {
+ error_at (p_simd_values->loc, "ill-formed pragma: variable %qE"
+ " listed in both linear and private pragma simd clause",
+ priv_var);
+ return true;
+ }
+ }
+
+ /* Now check linear and reduction lists. */
+ for (ii = 0; ii < vec_safe_length (p_simd_values->linear_var_list); ii++)
+ for (jj = 0; jj < vec_safe_length (p_simd_values->reduction_list); jj++)
+ {
+ struct reduction_node r_node = (*(p_simd_values->reduction_list))[jj];
+ for (kk = 0; kk < vec_safe_length (r_node.reduction_vars); kk++)
+ {
+ tree linear_var = (*(p_simd_values->linear_var_list))[ii];
+ tree red_var = (*(r_node.reduction_vars))[kk];
+ if (simple_cst_equal (linear_var, red_var) == 1)
+ {
+ error_at (p_simd_values->loc,
+ "ill-formed pragma: variable %qE listed in both "
+ "reduction and linear pragma simd clause", red_var);
+ return true;
+ }
+ }
+ }
+
+ /* Finally check private and reduction lists. */
+ for (ii = 0; ii < vec_safe_length (p_simd_values->priv_var_list); ii++)
+ for (jj = 0; jj < vec_safe_length (p_simd_values->reduction_list); jj++)
+ {
+ struct reduction_node r_node = (*(p_simd_values->reduction_list))[jj];
+ for (kk = 0; kk < vec_safe_length (r_node.reduction_vars); kk++)
+ {
+ tree priv_var = (*(p_simd_values->priv_var_list))[ii];
+ tree red_var = (*(r_node.reduction_vars))[kk];
+ if (simple_cst_equal (priv_var, red_var) == 1)
+ {
+ error_at (p_simd_values->loc,
+ "ill-formed pragma: variable %qE listed in both "
+ "reduction and private pragma simd clause", red_var);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+/* This function will parse the pragma simd assert clause. */
static void
-cp_parser_simd_vectorlength (cp_parser *parser, cp_token *pragma_token)
+cp_parser_simd_assert (cp_parser *parser, cp_token *pragma_token,
+ bool is_assert, struct pragma_simd_values *p_simd_values)
{
- cp_token *token = NULL;
- tree vec_length_list = NULL_TREE, v_length_value = NULL_TREE;
-
- cilkplus_local_simd_values.pragma_encountered = true;
- cilkplus_local_simd_values.types |= P_SIMD_VECTORLENGTH;
+ cp_token *token;
- if (cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ if (is_assert)
{
- while (true)
+ if (p_simd_values->assert_requested == P_SIMD_NOASSERT)
{
- if (cp_lexer_next_token_is_not (parser->lexer, CPP_NUMBER))
- {
- cp_parser_error (parser, "expected number");
- cp_parser_skip_to_pragma_eol (parser, pragma_token);
- vec_length_list = NULL_TREE;
- break;
- }
- else
- {
- token = cp_lexer_peek_token (parser->lexer);
- if (token != NULL)
- v_length_value = token->u.value;
- cp_lexer_consume_token (parser->lexer);
- vec_length_list = tree_cons (NULL_TREE, v_length_value,
- vec_length_list);
- }
- if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
- {
- cp_lexer_consume_token (parser->lexer);
- break;
- }
- if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
- cp_lexer_consume_token (parser->lexer);
+ error_at (input_location, "assert and noassert cannot be used in the"
+ " same pragma");
+ cp_parser_skip_to_pragma_eol (parser, pragma_token);
+ return;
}
+ p_simd_values->assert_requested = P_SIMD_ASSERT;
}
- else
- cp_parser_error (parser, "expected %<(%>");
-
- cilkplus_local_simd_values.vectorlength = vec_length_list;
- cilkplus_local_simd_values.pragma_encountered = true;
-
-
- if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)
- || cp_lexer_next_token_is (parser->lexer, CPP_KEYWORD))
+ else
+ {
+ if (p_simd_values->assert_requested == P_SIMD_ASSERT)
+ {
+ error_at (input_location, "assert and noassert cannot be used in the"
+ "same pragma");
+ cp_parser_skip_to_pragma_eol (parser, pragma_token);
+ return;
+ }
+ p_simd_values->assert_requested = P_SIMD_NOASSERT;
+ }
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
{
token = cp_lexer_peek_token (parser->lexer);
cp_lexer_consume_token (parser->lexer);
- if (strcmp (IDENTIFIER_POINTER (token->u.value), "linear") == 0)
- cp_parser_simd_linear (parser, pragma_token);
- else if (strcmp (IDENTIFIER_POINTER (token->u.value), "private") == 0)
- cp_parser_simd_private (parser, pragma_token);
- else if (strcmp (IDENTIFIER_POINTER (token->u.value),
- "vectorlength") == 0)
- cp_parser_simd_vectorlength (parser, pragma_token);
- else if (strcmp (IDENTIFIER_POINTER (token->u.value), "assert") == 0)
- cp_parser_simd_assert (parser, pragma_token, true);
- else if (strcmp (IDENTIFIER_POINTER (token->u.value), "noassert") == 0)
- cp_parser_simd_assert (parser, pragma_token, false);
- else if (strcmp (IDENTIFIER_POINTER (token->u.value), "reduction") == 0)
- cp_parser_simd_reduction (parser, pragma_token);
- else
- cp_parser_error (parser, "Unknown identifier");
+ cp_parser_simd_handle_next_clause (parser,
+ IDENTIFIER_POINTER (token->u.value),
+ pragma_token, p_simd_values);
}
else
{
cp_parser_skip_to_pragma_eol (parser, pragma_token);
if (cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR))
- {
- if (same_var_in_multiple_lists_p (&cilkplus_local_simd_values))
- cp_parser_error (parser,
- "ill-formed pragma: Same variable in multiple "
- "clause");
- cp_lexer_consume_token (parser->lexer);
- cp_parser_for (parser, &cilkplus_local_simd_values);
+ {
+ if (!same_var_in_multiple_lists_p (p_simd_values))
+ {
+ cp_lexer_consume_token (parser->lexer);
+ cp_parser_for (parser, p_simd_values);
+ }
}
- else
- cp_parser_error (parser, "for statement expected");
- }
- return;
+ else
+ error_at (input_location, "for statement expression after pragma simd");
+ }
}
-/* This function will parse the pragma simd private clause. */
+/* Parses the pragma simd linear clause in Cilk Plus language extension.
+ The syntax is:
+ #pragma simd linear (<variable>:[<steps], ... )
+*/
static void
-cp_parser_simd_private (cp_parser *parser, cp_token *pragma_token)
+cp_parser_simd_linear (cp_parser *parser, cp_token *pragma_token,
+ struct pragma_simd_values *p_simd_values)
{
- cp_token *token = NULL;
- tree private_var = NULL_TREE, private_var_list = NULL_TREE;
-
- cilkplus_local_simd_values.types |= P_SIMD_PRIVATE;
- cilkplus_local_simd_values.pragma_encountered = true;
+ tree linear_var, linear_step;
+ cp_token *token;
- if (cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
{
- while (true)
+ cp_parser_skip_to_pragma_eol (parser, pragma_token);
+ return;
+ }
+
+ while (true)
+ {
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
+ {
+ cp_parser_error (parser, "expected variable-name");
+ cp_parser_skip_to_pragma_eol (parser, pragma_token);
+ vec_safe_truncate (p_simd_values->linear_var_list, 0);
+ vec_safe_truncate (p_simd_values->linear_steps_list, 0);
+ break;
+ }
+ linear_var = cp_lexer_peek_token (parser->lexer)->u.value;
+ cp_lexer_consume_token (parser->lexer);
+ vec_safe_push (p_simd_values->linear_var_list, linear_var);
+
+ if (cp_lexer_next_token_is (parser->lexer, CPP_COLON))
{
- if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
+ cp_lexer_consume_token (parser->lexer);
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_NUMBER))
{
- cp_parser_error (parser, "expected variable");
+ cp_parser_error (parser, "expected step-size");
+ vec_safe_truncate (p_simd_values->linear_steps_list, 0);
+ vec_safe_truncate (p_simd_values->linear_var_list, 0);
cp_parser_skip_to_pragma_eol (parser, pragma_token);
- break;
- }
- else
- {
- token = cp_lexer_peek_token (parser->lexer);
- if (token != NULL)
- private_var = token->u.value;
- else
- {
- cp_parser_error (parser, "expected variable");
- cp_parser_skip_to_pragma_eol (parser, pragma_token);
- /* you exit here because this should NEVER happen. If it does
- something very bad is going on */
- exit (-1);
- }
- cp_lexer_consume_token (parser->lexer);
- private_var_list = tree_cons (NULL_TREE, private_var,
- private_var_list);
- }
- if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
- {
- cp_lexer_consume_token (parser->lexer);
- break;
+ return;
}
- if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
- cp_lexer_consume_token (parser->lexer);
+ linear_step = cp_lexer_peek_token (parser->lexer)->u.value;
+ cp_lexer_consume_token (parser->lexer);
+ }
+ else if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)
+ || cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
+ linear_step = integer_one_node;
+ else
+ {
+ cp_parser_error (parser, "expected %<:%> or %<,%> after variable-"
+ "name");
+ vec_safe_truncate (p_simd_values->linear_steps_list, 0);
+ vec_safe_truncate (p_simd_values->linear_var_list, 0);
+ cp_parser_skip_to_pragma_eol (parser, pragma_token);
+ return;
}
+ vec_safe_push (p_simd_values->linear_steps_list, linear_step);
+ if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
+ {
+ cp_lexer_consume_token (parser->lexer);
+ break;
+ }
+ if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+ cp_lexer_consume_token (parser->lexer);
}
- else
- cp_parser_error (parser, "expected %<(%>");
- cilkplus_local_simd_values.pragma_encountered = true;
- cilkplus_local_simd_values.types |= P_SIMD_PRIVATE;
- cilkplus_local_simd_values.private_vars = private_var_list;
-
- if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)
- || cp_lexer_next_token_is (parser->lexer, CPP_KEYWORD))
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
{
token = cp_lexer_peek_token (parser->lexer);
cp_lexer_consume_token (parser->lexer);
- if (strcmp (IDENTIFIER_POINTER (token->u.value), "linear") == 0)
- cp_parser_simd_linear (parser, pragma_token);
- else if (strcmp (IDENTIFIER_POINTER (token->u.value), "private") == 0)
- cp_parser_simd_private (parser, pragma_token);
- else if (strcmp (IDENTIFIER_POINTER (token->u.value),
- "vectorlength") == 0)
- cp_parser_simd_vectorlength (parser, pragma_token);
- else if (strcmp (IDENTIFIER_POINTER (token->u.value), "assert") == 0)
- cp_parser_simd_assert (parser, pragma_token, true);
- else if (strcmp (IDENTIFIER_POINTER (token->u.value), "noassert") == 0)
- cp_parser_simd_assert (parser, pragma_token, false);
- else if (strcmp (IDENTIFIER_POINTER (token->u.value), "reduction") == 0)
- cp_parser_simd_reduction (parser, pragma_token);
- else
- cp_parser_error (parser, "Unknown identifier");
+ cp_parser_simd_handle_next_clause (parser,
+ IDENTIFIER_POINTER (token->u.value),
+ pragma_token, p_simd_values);
}
else
{
cp_parser_skip_to_pragma_eol (parser, pragma_token);
if (cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR))
- {
- if (same_var_in_multiple_lists_p (&cilkplus_local_simd_values))
- cp_parser_error (parser, "ill-formed pragma: Same variable in "
- "multiple clause");
- cp_lexer_consume_token (parser->lexer);
- cp_parser_for (parser, &cilkplus_local_simd_values);
+ {
+ if (!same_var_in_multiple_lists_p (p_simd_values))
+ {
+ cp_lexer_consume_token (parser->lexer);
+ cp_parser_for (parser, p_simd_values);
+ }
}
- else
- cp_parser_error (parser, "for statement expected");
- }
- return;
+ else
+ error_at (input_location, "for statement expression after pragma simd");
+ }
}
-/* This function will handle the pragma simd reduction clause. */
+/* Parses the private clause of simd pragma that is part of Cilk Plus language
+ extension.
+ The correct syntax is:
+ #pragma simd private (<variable> [, <variable])
+*/
static void
-cp_parser_simd_reduction (cp_parser *parser, cp_token *pragma_token)
+cp_parser_simd_private (cp_parser *parser, cp_token *pragma_token,
+ struct pragma_simd_values *p_simd_values)
{
- cp_token *token = NULL;
- tree var_list = NULL_TREE, vars = NULL_TREE;
- enum tree_code op_code = PLUS_EXPR;
+ tree private_var;
+ cp_token *token;
- if (cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
{
- token = cp_lexer_peek_token (parser->lexer);
-
- switch (token->type)
- {
- case CPP_PLUS:
- op_code = PLUS_EXPR;
- break;
- case CPP_MINUS:
- op_code = MINUS_EXPR;
- break;
- case CPP_MULT:
- op_code = MULT_EXPR;
- break;
- case CPP_AND:
- op_code = BIT_AND_EXPR;
- break;
- case CPP_OR:
- op_code = BIT_IOR_EXPR;
- break;
- case CPP_XOR:
- op_code = BIT_XOR_EXPR;
- break;
- case CPP_OR_OR:
- op_code = TRUTH_ORIF_EXPR;
- break;
- case CPP_AND_AND:
- op_code = TRUTH_ANDIF_EXPR;
- break;
- default:
- cp_parser_error (parser, "expected one of the following: "
- "%<+%> %<-%> %<*%> %<&%> %<|%> %<^%> %<||%> %<&&%>");
- cp_parser_skip_to_pragma_eol (parser, pragma_token);
- var_list = NULL_TREE;
- vars = NULL_TREE;
- return;
- }
- cp_lexer_consume_token (parser->lexer);
+ cp_parser_skip_to_pragma_eol (parser, pragma_token);
+ vec_safe_truncate (p_simd_values->priv_var_list, 0);
+ return;
+ }
- if (cp_lexer_next_token_is_not (parser->lexer, CPP_COLON))
+ while (true)
+ {
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
{
- cp_parser_error (parser, "expected %<:%>");
+ error_at (input_location, "expected variable-name");
cp_parser_skip_to_pragma_eol (parser, pragma_token);
- var_list = NULL_TREE;
- vars = NULL_TREE;
- return;
+ vec_safe_truncate (p_simd_values->priv_var_list, 0);
+ break;
}
-
+ private_var = cp_lexer_peek_token (parser->lexer)->u.value;
cp_lexer_consume_token (parser->lexer);
-
- while (true)
+ vec_safe_push (p_simd_values->priv_var_list, private_var);
+ if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
{
- if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
- {
- cp_parser_error (parser, "expected variable name");
- cp_parser_skip_to_pragma_eol (parser, pragma_token);
- break;
- }
- token = cp_lexer_peek_token (parser->lexer);
cp_lexer_consume_token (parser->lexer);
- if (token != NULL)
- vars = token->u.value;
- else
- {
- cp_parser_error (parser, "expected variable name");
- cp_parser_skip_to_pragma_eol (parser, pragma_token);
- exit (-1);
- }
- var_list = tree_cons (NULL_TREE, vars, var_list);
-
- if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
- {
- cp_lexer_consume_token (parser->lexer);
- break;
- }
-
- if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
- cp_lexer_consume_token (parser->lexer);
+ break;
}
+ else if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+ cp_lexer_consume_token (parser->lexer);
}
- else
- cp_parser_error (parser, "expected %<(%>");
-
- insert_reduction_values (&cilkplus_local_simd_values.reduction_vals, op_code,
- var_list);
- cilkplus_local_simd_values.types |= P_SIMD_REDUCTION;
- cilkplus_local_simd_values.pragma_encountered = true;
-
- if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)
- || cp_lexer_next_token_is (parser->lexer, CPP_KEYWORD))
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
{
token = cp_lexer_peek_token (parser->lexer);
cp_lexer_consume_token (parser->lexer);
- if (strcmp (IDENTIFIER_POINTER (token->u.value), "linear") == 0)
- cp_parser_simd_linear (parser, pragma_token);
- else if (strcmp (IDENTIFIER_POINTER (token->u.value), "private") == 0)
- cp_parser_simd_private (parser, pragma_token);
- else if (strcmp (IDENTIFIER_POINTER (token->u.value),
- "vectorlength") == 0)
- cp_parser_simd_vectorlength (parser, pragma_token);
- else if (strcmp (IDENTIFIER_POINTER (token->u.value), "assert") == 0)
- cp_parser_simd_assert (parser, pragma_token, true);
- else if (strcmp (IDENTIFIER_POINTER (token->u.value), "noassert") == 0)
- cp_parser_simd_assert (parser, pragma_token, false);
- else if (strcmp (IDENTIFIER_POINTER (token->u.value), "reduction") == 0)
- cp_parser_simd_reduction (parser, pragma_token);
- else
- cp_parser_error (parser, "Unknown identifier");
+ cp_parser_simd_handle_next_clause (parser,
+ IDENTIFIER_POINTER (token->u.value),
+ pragma_token, p_simd_values);
}
else
{
cp_parser_skip_to_pragma_eol (parser, pragma_token);
if (cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR))
- {
- if (same_var_in_multiple_lists_p (&cilkplus_local_simd_values))
- cp_parser_error (parser,
- "ill-formed pragma: Same variable in multiple "
- "clause");
- cp_lexer_consume_token (parser->lexer);
- cp_parser_for (parser, &cilkplus_local_simd_values);
+ {
+ if (!same_var_in_multiple_lists_p (p_simd_values))
+ {
+ cp_lexer_consume_token (parser->lexer);
+ cp_parser_for (parser, p_simd_values);
+ }
}
- else
- cp_parser_error (parser, "for statement expected");
- }
- return;
+ else
+ error_at (input_location, "for statement expression after pragma simd");
+ }
}
-/* This function handles the linear clause of pragma simd of Cilk Plus. */
+/* Parses the vectorlength clause of SIMD pragmas that is part of Cilk Plus
+ language extension.
+
+ The correct syntax is:
+ #pragma simd vectorlength (<INTEGER> [, <INTEGER])
+*/
static void
-cp_parser_simd_linear (cp_parser *parser, cp_token *pragma_token)
+cp_parser_simd_vectorlength (cp_parser *parser, cp_token *pragma_token,
+ struct pragma_simd_values *p_simd_values)
{
- cp_token *token = NULL;
- tree linear_var = NULL_TREE, linear_var_list = NULL_TREE;
- tree linear_step = NULL_TREE, linear_steps_list = NULL_TREE;
- cilkplus_local_simd_values.types |= P_SIMD_LINEAR;
- cilkplus_local_simd_values.pragma_encountered = true;
- if (cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+ if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
{
- while (true)
- {
- if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
- {
- cp_parser_error (parser, "expected variable");
- cp_parser_skip_to_pragma_eol (parser, pragma_token);
- linear_var_list = NULL_TREE;
- linear_steps_list = NULL_TREE;
- break;
- }
- token = cp_lexer_peek_token (parser->lexer);
- if (token)
- linear_var = token->u.value;
+ cp_parser_skip_to_pragma_eol (parser, pragma_token);
+ return;
+ }
+ while (true)
+ {
+ tree vlength_value = cp_parser_expression (parser, false, false, NULL);
+ if (!TREE_TYPE (vlength_value) || !TREE_CONSTANT (vlength_value)
+ || !INTEGRAL_TYPE_P (TREE_TYPE (vlength_value)))
+ {
+ error_at (input_location, "vectorlength must be an integral"
+ " constant");
+ cp_parser_skip_to_pragma_eol (parser, pragma_token);
+ vec_safe_truncate (p_simd_values->vec_length_list, 0);
+ break;
+ }
+ else
+ vec_safe_push (p_simd_values->vec_length_list, vlength_value);
+ if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
+ {
cp_lexer_consume_token (parser->lexer);
- linear_var_list = tree_cons (NULL_TREE, linear_var, linear_var_list);
- if (cp_lexer_next_token_is (parser->lexer, CPP_COLON))
- {
- cp_lexer_consume_token (parser->lexer);
- if (cp_lexer_next_token_is_not (parser->lexer, CPP_NUMBER))
- {
- cp_parser_error (parser, "expected step-size");
- cp_parser_skip_to_pragma_eol (parser, pragma_token);
- linear_var = NULL_TREE;
- linear_var_list = NULL_TREE;
- break;
- }
- else
- {
- token = cp_lexer_peek_token (parser->lexer);
- if (token)
- linear_step = token->u.value;
- cp_lexer_consume_token (parser->lexer);
- }
- }
- else if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)
- || cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
- linear_step = integer_one_node;
- else
- {
- cp_parser_error (parser, "expected : or , after variable name");
- cp_parser_skip_to_pragma_eol (parser, pragma_token);
- return;
- }
- if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
- {
- cp_lexer_consume_token (parser->lexer);
- linear_steps_list = tree_cons (NULL_TREE, linear_step,
- linear_steps_list);
- break;
- }
- if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
- {
- cp_lexer_consume_token (parser->lexer);
- linear_steps_list = tree_cons (NULL_TREE, linear_step,
- linear_steps_list);
- }
+ break;
}
+ if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+ break;
}
- else
- {
- cp_parser_error (parser, "expected %<(%>");
- return;
- }
-
- gcc_assert (list_length (linear_steps_list) ==
- list_length (linear_var_list));
-
- cilkplus_local_simd_values.linear_vars = linear_var_list;
- cilkplus_local_simd_values.linear_var_size = list_length (linear_var_list);
- cilkplus_local_simd_values.linear_steps = linear_steps_list;
- cilkplus_local_simd_values.linear_steps_size =
- list_length (linear_steps_list);
-
- if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)
- || cp_lexer_next_token_is (parser->lexer, CPP_KEYWORD))
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
{
- token = cp_lexer_peek_token (parser->lexer);
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
cp_lexer_consume_token (parser->lexer);
- if (strcmp (IDENTIFIER_POINTER (token->u.value), "linear") == 0)
- cp_parser_simd_linear (parser, pragma_token);
- else if (strcmp (IDENTIFIER_POINTER (token->u.value), "private") == 0)
- cp_parser_simd_private (parser, pragma_token);
- else if (strcmp (IDENTIFIER_POINTER (token->u.value),
- "vectorlength") == 0)
- cp_parser_simd_vectorlength (parser, pragma_token);
- else if (strcmp (IDENTIFIER_POINTER (token->u.value), "assert") == 0)
- cp_parser_simd_assert (parser, pragma_token, true);
- else if (strcmp (IDENTIFIER_POINTER (token->u.value), "noassert") == 0)
- cp_parser_simd_assert (parser, pragma_token, false);
- else if (strcmp (IDENTIFIER_POINTER (token->u.value), "reduction") == 0)
- cp_parser_simd_reduction (parser, pragma_token);
- else
- cp_parser_error (parser, "Unknown identifier");
+ cp_parser_simd_handle_next_clause (parser,
+ IDENTIFIER_POINTER (token->u.value),
+ pragma_token, p_simd_values);
}
else
{
cp_parser_skip_to_pragma_eol (parser, pragma_token);
if (cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR))
- {
- if (same_var_in_multiple_lists_p (&cilkplus_local_simd_values))
- cp_parser_error (parser, "ill-formed pragma: Same variable in "
- "multiple clause");
- cp_lexer_consume_token (parser->lexer);
- cp_parser_for (parser, &cilkplus_local_simd_values);
+ {
+ if (!same_var_in_multiple_lists_p (p_simd_values))
+ {
+ cp_lexer_consume_token (parser->lexer);
+ cp_parser_for (parser, p_simd_values);
+ }
}
- else
- cp_parser_error (parser, "for statement expected");
- }
- return;
+ else
+ error_at (input_location, "for statement expression after pragma simd");
+ }
}
-/* This function will parse the pragma simd assert clause. */
+/* Parses the reduction clause of SIMD pragma that is part of the Cilk Plus
+ language specification:
+ The correct syntax is:
+ #pragma simd reduction (<operator>:<variable> [, <variable>])
+*/
static void
-cp_parser_simd_assert (cp_parser *parser, cp_token *pragma_token,
- bool is_assert)
+cp_parser_simd_reduction (cp_parser *parser, cp_token *pragma_token,
+ struct pragma_simd_values *p_simd_values)
{
- cp_token *token;
+ tree vars = NULL_TREE;
+ enum tree_code op_code = PLUS_EXPR;
+ struct reduction_node red_node;
+
+ memset (&red_node, 0, sizeof (struct reduction_node));
- if ((cilkplus_local_simd_values.types == P_SIMD_ASSERT) && is_assert)
+ if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
{
- cp_parser_error (parser, "multiple simd assert/noassert pragmas found");
+ cp_parser_skip_to_pragma_eol (parser, pragma_token);
return;
}
- else
+
+ switch (cp_lexer_peek_token (parser->lexer)->type)
{
- if (is_assert)
- cilkplus_local_simd_values.types |= P_SIMD_ASSERT;
- else
- cilkplus_local_simd_values.types |= P_SIMD_NOASSERT;
+ case CPP_PLUS:
+ op_code = PLUS_EXPR;
+ break;
+ case CPP_MINUS:
+ op_code = MINUS_EXPR;
+ break;
+ case CPP_MULT:
+ op_code = MULT_EXPR;
+ break;
+ case CPP_AND:
+ op_code = BIT_AND_EXPR;
+ break;
+ case CPP_OR:
+ op_code = BIT_IOR_EXPR;
+ break;
+ case CPP_XOR:
+ op_code = BIT_XOR_EXPR;
+ break;
+ case CPP_OR_OR:
+ op_code = TRUTH_ORIF_EXPR;
+ break;
+ case CPP_AND_AND:
+ op_code = TRUTH_ANDIF_EXPR;
+ break;
+ default:
+ error_at (input_location, "pragma simd reduction operators must be one"
+ " of the following: "
+ "%<+%> %<-%> %<*%> %<&%> %<|%> %<^%> %<||%> %<&&%>");
+ cp_parser_skip_to_pragma_eol (parser, pragma_token);
+ return;
}
-
- cilkplus_local_simd_values.pragma_encountered = true;
+ cp_lexer_consume_token (parser->lexer);
+ red_node.reduction_type = op_code;
+
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_COLON))
+ {
+ cp_parser_error (parser, "expected %<:%>");
+ cp_parser_skip_to_pragma_eol (parser, pragma_token);
+ return;
+ }
+ cp_lexer_consume_token (parser->lexer);
- if (cp_lexer_next_token_is (parser->lexer, CPP_NAME)
- || cp_lexer_next_token_is (parser->lexer, CPP_KEYWORD))
+ while (true)
{
- token = cp_lexer_peek_token (parser->lexer);
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
+ {
+ cp_parser_error (parser, "expected variable-name");
+ cp_parser_skip_to_pragma_eol (parser, pragma_token);
+ break;
+ }
+ vars = cp_lexer_peek_token (parser->lexer)->u.value;
cp_lexer_consume_token (parser->lexer);
+ vec_safe_push (red_node.reduction_vars, vars);
- if (strcmp (IDENTIFIER_POINTER (token->u.value), "linear") == 0)
- cp_parser_simd_linear (parser, pragma_token);
- else if (strcmp (IDENTIFIER_POINTER (token->u.value), "private") == 0)
- cp_parser_simd_private (parser, pragma_token);
- else if (strcmp (IDENTIFIER_POINTER (token->u.value),
- "vectorlength") == 0)
- cp_parser_simd_vectorlength (parser, pragma_token);
- else if (strcmp (IDENTIFIER_POINTER (token->u.value), "assert") == 0)
- cp_parser_simd_assert (parser, pragma_token, true);
- else if (strcmp (IDENTIFIER_POINTER (token->u.value), "noassert") == 0)
- cp_parser_simd_assert (parser, pragma_token, false);
- else if (strcmp (IDENTIFIER_POINTER (token->u.value), "reduction") == 0)
- cp_parser_simd_reduction (parser, pragma_token);
- else
- cp_parser_error (parser, "Unknown identifier");
+ if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
+ {
+ cp_lexer_consume_token (parser->lexer);
+ vec_safe_push (p_simd_values->reduction_list, red_node);
+ break;
+ }
+ if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+ cp_lexer_consume_token (parser->lexer);
+ }
+ if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+ {
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+ cp_lexer_consume_token (parser->lexer);
+
+ cp_parser_simd_handle_next_clause (parser,
+ IDENTIFIER_POINTER (token->u.value),
+ pragma_token, p_simd_values);
}
else
{
cp_parser_skip_to_pragma_eol (parser, pragma_token);
if (cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR))
- {
- if (same_var_in_multiple_lists_p (&cilkplus_local_simd_values))
- cp_parser_error (parser,
- "ill-formed pragma: Same variable in multiple "
- "clause");
- cp_lexer_consume_token (parser->lexer);
- cp_parser_for (parser, &cilkplus_local_simd_values);
+ {
+ if (!same_var_in_multiple_lists_p (p_simd_values))
+ {
+ cp_lexer_consume_token (parser->lexer);
+ cp_parser_for (parser, p_simd_values);
+ }
}
- else
- cp_parser_error (parser, "for statement expected");
- }
- return;
+ else
+ error_at (input_location, "for statement expression after pragma simd");
+ }
}
@@ -30010,7 +29925,8 @@ cp_parser_cilk_for_init_statement (cp_parser *parser, tree *init)
ARRAY_NOTATION_REF. If some error occurred it returns NULL_TREE. */
static tree
-cp_parser_array_notation (cp_parser *parser, tree init_index, tree array_value)
+cp_parser_array_notation (location_t loc, cp_parser *parser, tree init_index,
+ tree array_value)
{
cp_token *token = NULL;
tree start_index = NULL_TREE, length_index = NULL_TREE, stride = NULL_TREE;
@@ -30026,7 +29942,15 @@ cp_parser_array_notation (cp_parser *parser, tree init_index, tree array_value)
if (processing_template_decl)
{
array_type = TREE_TYPE (array_value);
- type = TREE_TYPE (array_type);
+ if (array_type)
+ type = TREE_TYPE (array_type);
+ else if (TREE_CODE (array_value) == ARRAY_REF)
+ {
+ array_type = TREE_TYPE (TREE_OPERAND (array_value, 0));
+ type = TREE_TYPE (array_type);
+ }
+ else
+ type = array_type;
}
else
{
@@ -30116,6 +30040,8 @@ cp_parser_array_notation (cp_parser *parser, tree init_index, tree array_value)
value_tree = build_array_notation_ref (input_location, array_value,
start_index, length_index, stride,
type);
+ if (value_tree != error_mark_node)
+ SET_EXPR_LOCATION (value_tree, loc);
return value_tree;
}
diff --git a/gcc/gimple.h b/gcc/gimple.h
index b9e0b161d4e..896bb74824e 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -210,7 +210,7 @@ struct GTY((chain_next ("%h.next"))) gimple_statement_base {
gimple GTY((skip)) prev;
/* Index to the PRAGMA simd internal structure. */
- int pragma_simd_index;
+ unsigned int pragma_simd_index;
};
diff --git a/gcc/pragma_simd.c b/gcc/pragma_simd.c
index c39fd626aa1..58775028e86 100644
--- a/gcc/pragma_simd.c
+++ b/gcc/pragma_simd.c
@@ -24,623 +24,334 @@ along with GCC; see the file COPYING3. If not see
#include "config.h"
#include "system.h"
#include "coretypes.h"
-#include "tm.h"
#include "tree.h"
-#include "langhooks.h"
-#include "c/c-tree.h"
-#include "c/c-lang.h"
-#include "flags.h"
-#include "output.h"
-#include "intl.h"
-#include "target.h"
-#include "tree-iterator.h"
-#include "bitmap.h"
#include "gimple.h"
+#include "diagnostic-core.h"
#include "cilk.h"
-#include "c-family/c-objc.h"
-
-struct pragma_simd_values *psv_head;
+vec<struct pragma_simd_values, va_gc> *p_simd_info_list;
-/* This function Empties the pragma simd data structure. */
-void
-clear_pragma_simd_list (void)
+/* Traverses the global vector P_SIMD_INFO_LIST and returns the node whose
+ field "INDEX" as PRAGMA_SIMD_INDEX. If no match is found, returns NULL. */
+
+static struct pragma_simd_values *
+psv_find_node (unsigned int pragma_simd_index)
{
- psv_head = NULL;
- return;
+ unsigned int ii = 0;
+ struct pragma_simd_values *return_value = NULL;
+ for (ii = 0; ii < vec_safe_length (p_simd_info_list); ii++)
+ if (pragma_simd_index == (*p_simd_info_list)[ii].index)
+ return_value = &(*p_simd_info_list)[ii];
+ return return_value;
}
-/* this function will check and see if a certain clause is resolved
- (i.e. checked OK). */
-
-bool
-clause_resolved_p (enum pragma_simd_kind clause_type, int pragma_simd_index)
+static vec<struct reduction_node, va_gc> *
+psv_find_reduction_list (unsigned int pragma_simd_index)
{
- struct pragma_simd_values *ps_iter = NULL;
-
- if (pragma_simd_index <= INVALID_PRAGMA_SIMD_SLOT)
- return true;
-
- if (psv_head == NULL)
- return true;
+ unsigned int ii = 0;
+ vec<struct reduction_node, va_gc> *return_value = NULL;
- for (ps_iter = psv_head; ps_iter != NULL; ps_iter = ps_iter->ptr_next)
- {
- if (ps_iter->pragma_encountered && (ps_iter->index == pragma_simd_index))
- {
- switch (clause_type)
- {
- case P_SIMD_VECTORLENGTH:
- return ps_iter->vlength_OK;
- case P_SIMD_PRIVATE:
- return ps_iter->pvars_OK;
- case P_SIMD_LINEAR:
- return ps_iter->lvars_OK;
- case P_SIMD_REDUCTION:
- return ps_iter->rvars_OK;
- default:
- return false;
- }
- }
- }
-
- /* if we can't find the certain pragma, then just return true to make sure
- we do not assert/halt and continue */
- return true;
+ for (ii = 0; ii < vec_safe_length (p_simd_info_list); ii++)
+ if (pragma_simd_index == (*p_simd_info_list)[ii].index)
+ return_value = ((*p_simd_info_list)[ii].reduction_list);
+ return return_value;
}
-/* this function will go through and check off all the clauses we have
- satisfied. */
+/* Returns true of all the clauses of KIND in the node with the matching 'index'
+ field to PRAGMA_SIMD_INDEX. */
-void
-set_OK_for_certain_clause (enum pragma_simd_kind clause_type, bool set_value,
- int pragma_simd_index)
+static bool
+clause_resolved_p (enum pragma_simd_kind kind, unsigned int pragma_simd_index)
{
- struct pragma_simd_values *ps_iter = NULL;
-
+ struct pragma_simd_values *p_simd_node;
if (pragma_simd_index <= INVALID_PRAGMA_SIMD_SLOT)
- return;
-
- if (!psv_head)
- return;
-
- for (ps_iter = psv_head; ps_iter != NULL; ps_iter = ps_iter->ptr_next)
- {
- if (ps_iter->pragma_encountered && (ps_iter->index == pragma_simd_index))
- break;
- }
- if (!ps_iter)
- return;
+ return true;
- switch (clause_type)
+ p_simd_node = psv_find_node (pragma_simd_index);
+ if (!p_simd_node)
+ return true;
+
+ switch (kind)
{
case P_SIMD_VECTORLENGTH:
- ps_iter->vlength_OK = set_value;
+ if (!vec_safe_is_empty (p_simd_node->vec_length_list))
+ return p_simd_node->vlength_OK;
+ else
+ return true;
case P_SIMD_PRIVATE:
- ps_iter->pvars_OK = set_value;
+ if (!vec_safe_is_empty (p_simd_node->priv_var_list))
+ return p_simd_node->private_OK;
+ else
+ return true;
case P_SIMD_LINEAR:
- ps_iter->lvars_OK = set_value;
+ if (!vec_safe_is_empty (p_simd_node->linear_var_list))
+ return p_simd_node->linear_OK;
+ else
+ return true;
case P_SIMD_REDUCTION:
- ps_iter->rvars_OK = set_value;
+ if (!vec_safe_is_empty (p_simd_node->reduction_list))
+ return p_simd_node->reduction_OK;
+ else
+ return true;
default:
- break;
+ return false;
}
- return;
+ /* If we can't find a certain pragma, then just return tur to make sure we
+ do not assert/halt. */
+ return true;
}
-/* this function will make srue all the reductions given by pragma simd
- reduction clauses are satisfied. */
+/* Returns true of the node whose field 'index' matches PRAGMA_SIMD_INDEX
+ has the assert clause. */
bool
-all_reductions_satisfied_p (int pragma_simd_index)
-{
- struct pragma_simd_values *ps_iter = NULL;
- struct reduction_values *rv_iter = NULL;
-
- if (psv_head == NULL)
- return true;
-
- if (pragma_simd_index <= INVALID_PRAGMA_SIMD_SLOT)
- return true;
-
- for (ps_iter = psv_head; ps_iter != NULL; ps_iter = ps_iter->ptr_next)
- {
- for (rv_iter = ps_iter->reduction_vals; rv_iter != NULL;
- rv_iter = rv_iter->ptr_next)
- {
- if (rv_iter->not_reduced != 0)
- return false;
- }
- }
- return true;
-}
-
-/* This function will search the pragma simd list to see if a node for a
- certain loop exist (based on an index). */
-
-struct pragma_simd_values *
-psv_find_node (int psv_index)
+pragma_simd_assert_requested_p (unsigned int pragma_simd_index)
{
- struct pragma_simd_values *ps_iter = NULL;
-
- if (psv_index <= INVALID_PRAGMA_SIMD_SLOT)
- return NULL;
-
- if (psv_head == NULL)
- return NULL;
-
- for (ps_iter = psv_head; ps_iter != NULL; ps_iter = ps_iter->ptr_next)
- {
- if ((ps_iter->index == psv_index) && ps_iter->pragma_encountered)
- return ps_iter;
- }
-
- /* We should not get here. */
- return NULL;
+ if (!psv_find_node (pragma_simd_index))
+ return false;
+ else
+ return psv_find_node (pragma_simd_index)->assert_requested;
}
-/* this function will insert a value at the head of the list that holds
- pragma simd information for the loops. */
+/* Verify that the <#pragma simd> clauses have been properly resolved.
+ INDEX is the pragma_simd_index into the global table. */
-int
-psv_head_insert (struct pragma_simd_values local_simd_values)
+void
+pragma_simd_verify_clauses (unsigned int index)
{
- struct pragma_simd_values *ps_iter = NULL;
-
- struct reduction_values *rv_iter = NULL;
+ struct pragma_simd_values *vals = psv_find_node (index);
+ location_t loc = vals ? vals->loc : UNKNOWN_LOCATION;
- gcc_assert (local_simd_values.pragma_encountered == true);
- if (psv_head == NULL)
+ if ((!clause_resolved_p (P_SIMD_VECTORLENGTH, index)))
{
- psv_head = (struct pragma_simd_values *)
- xmalloc (sizeof (struct pragma_simd_values));
- gcc_assert (psv_head != NULL);
- psv_head->pragma_encountered = local_simd_values.pragma_encountered;
- /* We keep the head pointer index to be invalid pragma simd slot + 1.
- * This is done before fi we want to debug then we can set invalid pragma
- * simd_slot value to some arbitary number and then see if we are
- * catching the pragmas correctly. */
- psv_head->index = INVALID_PRAGMA_SIMD_SLOT + 1;
- psv_head->types = local_simd_values.types;
-
- psv_head->vectorlength = local_simd_values.vectorlength;
- if (local_simd_values.vectorlength != NULL_TREE)
- psv_head->vlength_OK = false;
- else
- psv_head->vlength_OK = true;
-
- psv_head->private_vars = local_simd_values.private_vars;
- if (local_simd_values.private_vars != NULL_TREE)
- psv_head->pvars_OK = false;
- else
- psv_head->pvars_OK = true;
-
- psv_head->linear_vars = local_simd_values.linear_vars;
- if (local_simd_values.linear_vars != NULL_TREE)
- psv_head->lvars_OK = false;
- else
- psv_head->lvars_OK = true;
-
- psv_head->linear_steps = local_simd_values.linear_steps;
- if (local_simd_values.reduction_vals == NULL)
- psv_head->reduction_vals = NULL;
-
- psv_head->reduction_vals = NULL;
- for (rv_iter = local_simd_values.reduction_vals; rv_iter != NULL;
- rv_iter = rv_iter->ptr_next)
- insert_reduction_values (&psv_head->reduction_vals,
- rv_iter->reduction_operator,
- rv_iter->tree_reduction_var_list);
-
- if (local_simd_values.reduction_vals != NULL)
- psv_head->rvars_OK = false;
- else
- psv_head->rvars_OK = true;
-
- psv_head->ptr_next = NULL;
- return psv_head->index;
+ if (pragma_simd_assert_requested_p (index))
+ error_at (loc, "vectorlength in pragma simd not picked from list");
+ else
+ warning_at (loc, 0,
+ "vectorlength in pragma simd not picked from list");
}
-
- for (ps_iter = psv_head; ps_iter->ptr_next != NULL;
- ps_iter = ps_iter->ptr_next)
+ if (!clause_resolved_p (P_SIMD_PRIVATE, index))
+ {
+ if (pragma_simd_assert_requested_p (index))
+ error_at (loc, "unable to make all variables private");
+ else
+ warning_at (loc, 0,
+ "unable to make all variables private in pragma simd");
+ }
+ if (!clause_resolved_p (P_SIMD_LINEAR, index))
{
- ;
+ if (pragma_simd_assert_requested_p (index))
+ error_at (loc, "unable to pick requested step-size in pragma simd");
+ else
+ warning (loc, "unable to pick requested step-size in pragma simd");
}
-
- ps_iter->ptr_next = (struct pragma_simd_values *)
- xmalloc (sizeof (struct pragma_simd_values));
- gcc_assert (ps_iter->ptr_next != NULL);
-
- ps_iter->ptr_next->pragma_encountered = local_simd_values.pragma_encountered;
- ps_iter->ptr_next->index = ps_iter->index + 1;
- ps_iter->ptr_next->types = local_simd_values.types;
- ps_iter->ptr_next->vectorlength = local_simd_values.vectorlength;
- ps_iter->ptr_next->private_vars = local_simd_values.private_vars;
- ps_iter->ptr_next->linear_vars = local_simd_values.linear_vars;
- ps_iter->ptr_next->linear_steps = local_simd_values.linear_steps;
- ps_iter->ptr_next->ptr_next = NULL;
-
- ps_iter->ptr_next->reduction_vals = NULL;
- for (rv_iter = local_simd_values.reduction_vals; rv_iter;
- rv_iter = rv_iter->ptr_next)
- insert_reduction_values (&ps_iter->ptr_next->reduction_vals,
- rv_iter->reduction_operator,
- rv_iter->tree_reduction_var_list);
-
- return ps_iter->ptr_next->index;
-}
-
-/* this function wil check if the user requsted the assert command. That is,
- the user requested the compiler to halt if the loop is not vectorized. */
-
-bool
-pragma_simd_assert_requested_p (int ps_index)
-{
- struct pragma_simd_values *ps_iter = NULL;
-
- if (ps_index == 0)
- return 0;
-
- for (ps_iter = psv_head; ps_iter; ps_iter = ps_iter->ptr_next)
+ if (!clause_resolved_p (P_SIMD_REDUCTION, index))
{
- if ((ps_iter->pragma_encountered == true) && (ps_iter->index == ps_index))
- {
- if ((ps_iter->types & P_SIMD_ASSERT))
- return true;
- else
- return false;
- }
+ if (pragma_simd_assert_requested_p (index))
+ error_at (loc, "unable to satisfy all reductions in pragma simd");
+ else
+ warning_at (loc, 0, "unable to satisfy all reductions in pragma simd");
}
- return false;
}
-/* This function will check to see if the vectorlength found by the
- vectorizer falls in the list of acceptable vectorlengths provided by the
- user. */
-bool
-pragma_simd_acceptable_vlength_p (int ps_index,
- int possible_vectorization_factor,
- tree scalar_type)
+/* Assigns the "OK" field of a certain clause (indicated by KIND) in a node
+ whose 'index' field matches pragma_simd_index to SET_VALUE. */
+
+void
+set_OK_for_certain_clause (enum pragma_simd_kind kind, bool set_value,
+ unsigned int pragma_simd_index)
{
- tree size = NULL_TREE;
- struct pragma_simd_values *ps_iter = NULL;
- int possible_vector_length = 0;
- tree ii_tree = NULL_TREE;
- tree ii_value = NULL_TREE;
- tree vl_tree = NULL_TREE;
- size = size_in_bytes (scalar_type);
-
- if (ps_index <= INVALID_PRAGMA_SIMD_SLOT)
- return true;
- if (TREE_CODE (size) == INTEGER_CST)
- ;
- else
- error ("Unable to determine size of scalar type!");
-
- possible_vector_length = possible_vectorization_factor;
-
- vl_tree = build_int_cst (integer_type_node, possible_vector_length);
+ unsigned int ii = 0;
+ if (pragma_simd_index <= INVALID_PRAGMA_SIMD_SLOT)
+ return;
- for (ps_iter = psv_head; ps_iter != NULL; ps_iter = ps_iter->ptr_next)
- {
- if ((ps_iter->pragma_encountered == true) && (ps_iter->index == ps_index))
+ for (ii = 0; ii < vec_safe_length (p_simd_info_list); ii++)
+ if ((*p_simd_info_list)[ii].index == pragma_simd_index)
+ {
+ if (kind == P_SIMD_VECTORLENGTH)
+ (*p_simd_info_list)[ii].vlength_OK = set_value;
+ else if (kind == P_SIMD_PRIVATE)
+ (*p_simd_info_list)[ii].private_OK = set_value;
+ else if (kind == P_SIMD_REDUCTION)
+ (*p_simd_info_list)[ii].reduction_OK = set_value;
+ else if (kind == P_SIMD_LINEAR)
+ (*p_simd_info_list)[ii].linear_OK = set_value;
+ else
+ gcc_unreachable ();
break;
- }
-
- gcc_assert (ps_iter != NULL);
-
- if (list_length (ps_iter->vectorlength) == 0)
- /* the user has not given any vectorlength, so whatever the vectorizer
- the vectorizer found is good enough for us. */
- return true;
-
- for (ii_tree = ps_iter->vectorlength; ii_tree; ii_tree = TREE_CHAIN (ii_tree))
- {
- ii_value = TREE_VALUE (ii_tree);
- if ((TREE_CODE (ii_value) == INTEGER_CST)
- && tree_int_cst_equal ((const_tree) ii_value, (const_tree) vl_tree))
- /* We found a match, so we return TRUE. */
- return true;
- }
-
- /* A match was not found, hence we return a false. */
- return false;
+ }
}
+
-/* this function will check if we wanted a loop to be vectorized. */
+/* Clears all the node in *p_simd_info_list. */
-bool
-pragma_simd_vectorize_loop_p (int ps_index)
+void
+p_simd_nodes_clear (void)
{
- struct pragma_simd_values *ps_iter = NULL;
-
- if (ps_index <= INVALID_PRAGMA_SIMD_SLOT)
- return false;
-
- for (ps_iter = psv_head; ps_iter != NULL; ps_iter = ps_iter->ptr_next)
- if (ps_iter->index == ps_index)
- return ps_iter->pragma_encountered;
-
- return false;
+ vec_free (p_simd_info_list);
}
-/* This function will insert the appropriate reduction values asked by pragma
- simd reduction into the internal pragma simd list. */
+/* Inserts *P_SIMD_NODE into P_SIMD_INFO_LIST and assigns index of P_SIMD_NODE
+ to the P_SIMD_INFO_LIST->head->index + 1. Returns the P_SIMD_NODE->index of
+ type unsigned int. */
-void
-insert_reduction_values (struct reduction_values **reduction_val_head,
- enum tree_code reduction_op, tree var_list)
+unsigned int
+p_simd_head_insert (struct pragma_simd_values *p_simd_node)
{
- struct reduction_values *red_iter = NULL;
- bool found = false;
- if (reduction_val_head == NULL)
- {
- reduction_val_head = (struct reduction_values **)
- xmalloc (sizeof (struct reduction_values *));
- gcc_assert (reduction_val_head != NULL);
- }
- if (*reduction_val_head == NULL)
- {
- *reduction_val_head = (struct reduction_values *)
- xmalloc (sizeof (struct reduction_values));
- gcc_assert (*reduction_val_head != NULL);
-
- (*reduction_val_head)->reduction_operator = reduction_op;
- (*reduction_val_head)->tree_reduction_var_list = var_list;
- (*reduction_val_head)->not_reduced = list_length (var_list);
- (*reduction_val_head)->ptr_next = NULL;
- return;
- }
- else
+ if (p_simd_node)
{
- for (red_iter = *reduction_val_head; red_iter->ptr_next != NULL;
- red_iter = red_iter->ptr_next)
- {
- if (red_iter->reduction_operator == reduction_op)
- {
- found = true;
- break;
- }
- }
-
- if (found)
- {
- red_iter->tree_reduction_var_list =
- tree_cons (NULL_TREE, var_list, red_iter->tree_reduction_var_list);
- red_iter->not_reduced +=
- list_length (red_iter->tree_reduction_var_list);
- }
+ if (vec_safe_is_empty (p_simd_info_list))
+ p_simd_node->index = INVALID_PRAGMA_SIMD_SLOT + 1;
else
{
- red_iter->ptr_next = (struct reduction_values *)
- xmalloc (sizeof (struct reduction_values));
- gcc_assert (red_iter->ptr_next != NULL);
-
- red_iter->ptr_next->reduction_operator = reduction_op;
- red_iter->ptr_next->tree_reduction_var_list = var_list;
- red_iter->ptr_next->not_reduced =
- list_length (red_iter->tree_reduction_var_list);
- red_iter->ptr_next->ptr_next = NULL;
+ unsigned int vec_length = vec_safe_length (p_simd_info_list);
+ p_simd_node->index = (*p_simd_info_list)[vec_length-1].index + 1;
}
- return;
- }
-}
-
-/* this function will check if a same variable is in multiple pragma clause
- for example, the following pragma is illegal and this function should flag
- them as true:
- #pragma simd reduction (+:p) linear(p:1)
- */
-bool
-same_var_in_multiple_lists_p (struct pragma_simd_values *ps_values)
-{
- tree vl_tree = NULL_TREE, vl_value = NULL_TREE;
- tree pr_tree = NULL_TREE, pr_value = NULL_TREE;
- tree rd_tree = NULL_TREE, rd_value = NULL_TREE;
- struct reduction_values *rd_list = NULL;
+ vec_safe_push (p_simd_info_list, *p_simd_node);
- if (ps_values->reduction_vals != NULL)
- {
- for (rd_list = ps_values->reduction_vals; rd_list != NULL;
- rd_list = rd_list->ptr_next)
- {
- rd_tree = rd_list->tree_reduction_var_list;
- vl_tree = ps_values->vectorlength;
- pr_tree = ps_values->private_vars;
-
- while ((vl_tree != NULL_TREE) || (rd_tree != NULL_TREE)
- || (pr_tree != NULL_TREE))
- {
- if (vl_tree != NULL_TREE)
- vl_value = TREE_VALUE (vl_tree);
- else
- vl_value = NULL_TREE;
-
- if (pr_tree != NULL_TREE)
- pr_value = TREE_VALUE (pr_tree);
- else
- pr_value = NULL_TREE;
-
- if (rd_tree != NULL_TREE)
- rd_value = TREE_VALUE (rd_tree);
- else
- rd_value = NULL_TREE;
-
- if (((vl_value != NULL_TREE || pr_value != NULL_TREE)
- && (simple_cst_equal (vl_value, pr_value) == 1))
- || ((vl_value != NULL_TREE || rd_value != NULL_TREE)
- && (simple_cst_equal (vl_value, rd_value) == 1))
- || ((pr_value != NULL_TREE || rd_value != NULL_TREE)
- && (simple_cst_equal (pr_value, rd_value) == 1)))
- return true;
+ return p_simd_node->index;
+ }
+ return INVALID_PRAGMA_SIMD_SLOT;
+}
- if (vl_tree != NULL_TREE)
- vl_tree = TREE_CHAIN (vl_tree);
- if (pr_tree != NULL_TREE)
- pr_tree = TREE_CHAIN (pr_tree);
- if (rd_tree != NULL_TREE)
- rd_tree = TREE_CHAIN (rd_tree);
- }
- }
- }
- else
- {
- while ((vl_tree != NULL_TREE) || (rd_tree != NULL_TREE)
- || (pr_tree != NULL_TREE))
- {
- if (vl_tree != NULL_TREE)
- vl_value = TREE_VALUE (vl_tree);
- else
- vl_value = NULL_TREE;
-
- if (pr_tree != NULL_TREE)
- pr_value = TREE_VALUE (pr_tree);
- else
- pr_value = NULL_TREE;
-
- if (rd_tree != NULL_TREE)
- rd_value = TREE_VALUE (rd_tree);
- else
- rd_value = NULL_TREE;
-
- /* If either one is not NULL and the trees are equal, then we
- say we have found a duplicate. */
- if (((vl_value != NULL_TREE || pr_value != NULL_TREE)
- && (simple_cst_equal (vl_value, pr_value) == 1))
- || ((vl_value != NULL_TREE || rd_value != NULL_TREE)
- && (simple_cst_equal (vl_value, rd_value) == 1))
- || ((pr_value != NULL_TREE || rd_value != NULL_TREE)
- && (simple_cst_equal (pr_value, rd_value) == 1)))
- return true;
- if (vl_tree != NULL_TREE)
- vl_tree = TREE_CHAIN (vl_tree);
+/* Finds the pragma_simd_node whose index matches the pragma_simd_index and
+ goes through all the vectorlengths specified and returns TRUE if there is
+ a match. Otherwise, the function returns false. */
- if (pr_tree != NULL_TREE)
- pr_tree = TREE_CHAIN (pr_tree);
+bool
+pragma_simd_acceptable_vlength_p (unsigned int pragma_simd_index,
+ int possible_vect_factor,
+ tree scalar_type ATTRIBUTE_UNUSED)
+{
+ unsigned int ii = 0, jj = 0;
+ tree vl_value;
- if (rd_tree != NULL_TREE)
- rd_tree = TREE_CHAIN (rd_tree);
- }
- }
- return false;
+ if (pragma_simd_index <= INVALID_PRAGMA_SIMD_SLOT)
+ return true;
+ vl_value = build_int_cst (integer_type_node, possible_vect_factor);
+
+ for (ii = 0; ii < vec_safe_length (p_simd_info_list); ii++)
+ if (pragma_simd_index == (*p_simd_info_list)[ii].index)
+ {
+ vec<tree, va_gc> *vl_vec = (*p_simd_info_list)[ii].vec_length_list;
+ if (vec_safe_length (vl_vec) == 0)
+ return true;
+ for (jj = 0; jj < vec_safe_length (vl_vec); jj++)
+ {
+ if (tree_int_cst_equal ((const_tree) (*vl_vec)[jj],
+ (const_tree) (vl_value)))
+ return true;
+ }
+ }
+
+ /* A match was not found, hence return false. */
+ return false;
}
-/* This function will check to see if a variable is reduced, if so then it will
- mark it as being reduced. */
+/* Goes through the private vars of pragma simd structure pointed by PS_INDEX
+ and checks of DEF_VAR is in the list and if so returns true. */
-void
-check_off_reduction_var (gimple reduc_stmt, int pragma_simd_index)
+bool
+pragma_simd_is_private_var_p (unsigned int ps_index, tree def_var)
{
- struct pragma_simd_values *ps_iter = NULL;
- struct reduction_values *rv_iter = NULL;
- enum tree_code op_code = NOP_EXPR;
- tree def = NULL_TREE;
- tree ii_iter = NULL_TREE;
- tree ii_value = NULL_TREE;
-
+ struct pragma_simd_values *ps_node = NULL;
+ tree variable;
+ unsigned int ii = 0, jj = 0;
- if (pragma_simd_index <= INVALID_PRAGMA_SIMD_SLOT)
- return;
-
- if (psv_head == NULL)
- return;
-
- if (!reduc_stmt || gimple_code (reduc_stmt) != GIMPLE_ASSIGN)
- return;
- else
- {
- def = gimple_assign_lhs (reduc_stmt);
- gcc_assert (def != NULL_TREE);
-
- if (TREE_CODE (def) == SSA_NAME)
- def = SSA_NAME_VAR (def);
- op_code = gimple_assign_rhs_code (reduc_stmt);
- }
-
-
- for (ps_iter = psv_head; ps_iter != NULL; ps_iter = ps_iter->ptr_next)
- if (ps_iter->pragma_encountered && (ps_iter->index == pragma_simd_index))
- break;
+ if (def_var == NULL_TREE)
+ return false;
- gcc_assert (ps_iter != NULL);
+ ps_node = psv_find_node (ps_index);
+ if (!ps_node)
+ return false;
- for (rv_iter = ps_iter->reduction_vals; rv_iter != NULL;
- rv_iter = rv_iter->ptr_next)
+ /* If it is a SSA_NAME, then this will extract the original variable name. */
+ if (TREE_CODE (def_var) == SSA_NAME)
{
- if (rv_iter->reduction_operator == op_code)
+ if (SSA_NAME_VAR (def_var) != NULL_TREE)
{
- for (ii_iter = rv_iter->tree_reduction_var_list; ii_iter != NULL_TREE;
- ii_iter = TREE_CHAIN (ii_iter))
+ def_var = SSA_NAME_VAR (def_var);
+ if (TREE_CODE (def_var) == VAR_DECL
+ || TREE_CODE (def_var) == PARM_DECL)
{
- ii_value = TREE_VALUE (ii_iter);
- if (simple_cst_equal (ii_value, DECL_NAME (def)))
- rv_iter->not_reduced--;
+ tree variable = DECL_NAME (def_var);
+ if (variable == NULL_TREE)
+ return false;
+ for (ii = 0; ii < vec_safe_length (ps_node->priv_var_list); ii++)
+ {
+ tree priv_value = (*(ps_node->priv_var_list))[ii];
+ if (simple_cst_equal (priv_value, variable) == 1)
+ return true;
+ }
}
}
- }
- return;
-}
-
-/* This function will find the step size from the pragma simd linear clause. */
-
-HOST_WIDE_INT
-find_linear_step_size (int pragma_simd_index, tree var)
-{
- tree ii_var_iter = NULL_TREE;
- tree ii_var_value = NULL_TREE;
- tree ii_step_iter = NULL_TREE;
- tree ii_step_value = NULL_TREE;
- tree real_var = NULL_TREE;
- HOST_WIDE_INT step = 0;
- struct pragma_simd_values *ps_iter = NULL;
-
- if (psv_head == NULL)
- return 0;
-
- if (pragma_simd_index <= INVALID_PRAGMA_SIMD_SLOT)
- return 0;
-
- for (ps_iter = psv_head; ps_iter != NULL; ps_iter = ps_iter->ptr_next)
- {
- if (ps_iter->pragma_encountered && (ps_iter->index == pragma_simd_index))
+ else if (SSA_NAME_DEF_STMT (def_var))
{
- ii_var_iter = ps_iter->linear_vars;
- ii_step_iter = ps_iter->linear_steps;
+ bool found = false;
+ gimple def_stmt = SSA_NAME_DEF_STMT (def_var);
- while ((ii_var_iter != NULL_TREE) && (ii_step_iter != NULL_TREE))
+ /* We go through all the ops in the def_stmt's RHS. */
+ for (size_t ii = 1; ii < gimple_num_ops (def_stmt); ii++)
{
- ii_var_value = TREE_VALUE (ii_var_iter);
- ii_step_value = TREE_VALUE (ii_step_iter);
- if (TREE_CODE (var) == SSA_NAME)
- real_var = SSA_NAME_VAR (var);
+ tree var_name, var = gimple_op (def_stmt, ii);
+ if (!var)
+ continue;
+ else if (TREE_CODE (var) == SSA_NAME && SSA_NAME_VAR (var))
+ var = SSA_NAME_VAR (var);
+
+ if (TREE_CODE (var) == VAR_DECL || TREE_CODE (var) == PARM_DECL)
+ var_name = DECL_NAME (var);
else
- real_var = var;
+ var_name = var; /* It should not get here. */
- if (simple_cst_equal (ii_var_value, DECL_NAME (real_var)))
+ /* Here we go through all the variables in the private list.
+ If we have a match, then we set found to true. If we didn't
+ have a match, then found will be false and then we return that.
+ This means that the variable we are looking in def is dependent
+ on variables that are not on the private list. */
+ for (jj = 0; jj < vec_safe_length (ps_node->priv_var_list); jj++)
{
- step = int_cst_value (ii_step_value);
- return step;
+ tree priv_value = (*(ps_node->priv_var_list))[jj];
+ if (simple_cst_equal (priv_value, var_name) == 1)
+ found = true;
}
+ if (found == false)
+ return false;
}
+ return found;
}
}
- return 0;
+ else if (TREE_CODE (def_var) == VAR_DECL || TREE_CODE (def_var) == PARM_DECL)
+ {
+ variable = DECL_NAME (def_var);
+ if (variable == NULL_TREE)
+ return false;
+
+ for (ii = 0; ii < vec_safe_length (ps_node->priv_var_list); ii++)
+ {
+ tree priv_value = (*(ps_node->priv_var_list))[ii];
+ if (simple_cst_equal (priv_value, variable) == 1)
+ return true;
+ }
+ }
+ return false;
}
-/* Goes through the private vars of pragma simd structure pointed by PS_INDEX
+/* Goes through the linear vars of pragma simd structure pointed by PS_INDEX
and checks of DEF_VAR is in the list and if so returns true. */
bool
-pragma_simd_is_private_var (int ps_index, tree def_var)
+pragma_simd_is_linear_var_p (unsigned int ps_index, tree def_var)
{
struct pragma_simd_values *ps_node = NULL;
- tree variable, ii_priv_list;
+ tree variable;
+ unsigned int ii = 0, jj = 0;
if (def_var == NULL_TREE)
return false;
@@ -661,11 +372,11 @@ pragma_simd_is_private_var (int ps_index, tree def_var)
tree variable = DECL_NAME (def_var);
if (variable == NULL_TREE)
return false;
- for (ii_priv_list = ps_node->private_vars; ii_priv_list;
- ii_priv_list = TREE_CHAIN (ii_priv_list))
+ for (ii = 0; ii < vec_safe_length (ps_node->linear_var_list);
+ ii++)
{
- tree ii_priv_value = TREE_VALUE (ii_priv_list);
- if (simple_cst_equal (ii_priv_value, variable) == 1)
+ tree priv_value = (*(ps_node->linear_var_list))[ii];
+ if (simple_cst_equal (priv_value, variable) == 1)
return true;
}
}
@@ -694,11 +405,11 @@ pragma_simd_is_private_var (int ps_index, tree def_var)
have a match, then found will be false and then we return that.
This means that the variable we are looking in def is dependent
on variables that are not on the private list. */
- for (ii_priv_list = ps_node->private_vars; ii_priv_list;
- ii_priv_list = TREE_CHAIN (ii_priv_list))
+ for (jj = 0; jj < vec_safe_length (ps_node->linear_var_list);
+ jj++)
{
- tree ii_priv_value = TREE_VALUE (ii_priv_list);
- if (simple_cst_equal (ii_priv_value, var_name) == 1)
+ tree priv_value = (*(ps_node->linear_var_list))[jj];
+ if (simple_cst_equal (priv_value, var_name) == 1)
found = true;
}
if (found == false)
@@ -713,13 +424,126 @@ pragma_simd_is_private_var (int ps_index, tree def_var)
if (variable == NULL_TREE)
return false;
- for (ii_priv_list = ps_node->private_vars; ii_priv_list;
- ii_priv_list = TREE_CHAIN (ii_priv_list))
+ for (ii = 0; ii < vec_safe_length (ps_node->priv_var_list); ii++)
{
- tree ii_priv_value = TREE_VALUE (ii_priv_list);
- if (simple_cst_equal (ii_priv_value, variable) == 1)
+ tree priv_value = (*(ps_node->priv_var_list))[ii];
+ if (simple_cst_equal (priv_value, variable) == 1)
return true;
}
}
return false;
}
+
+/* Outputs all the index fields in P_SIMD_INFO_LIST global vector to the
+ file pointed by *FPTR. */
+
+void
+dump_pragma_simd_values_vec (FILE *fptr)
+{
+ unsigned int ii = 0;
+
+ if (!fptr)
+ fptr = stderr;
+ for (ii = 0; ii < vec_safe_length (p_simd_info_list); ii++)
+ {
+ fprintf (fptr, "index = %2d\n", (*p_simd_info_list)[ii].index);
+ fprintf (fptr, "assert_requested = %s\n",
+ (*p_simd_info_list)[ii].assert_requested ? "true" : "false");
+ }
+ return;
+}
+
+/* Returns the step size for VAR that is in the linear clause stored in the
+ pragma_simd_index data vector pointed by pragma_simd_index. */
+
+HOST_WIDE_INT
+find_linear_step_size (unsigned int pragma_simd_index, tree var)
+{
+ unsigned int ii = 0;
+ tree real_var = NULL_TREE;
+ struct pragma_simd_values *ps_node = psv_find_node (pragma_simd_index);
+
+ if (!ps_node)
+ return 0;
+
+ if (TREE_CODE (var) == SSA_NAME)
+ real_var = SSA_NAME_VAR (var);
+ else
+ real_var = var;
+
+ for (ii = 0; ii < vec_safe_length (ps_node->linear_var_list); ii++)
+ if (real_var
+ && simple_cst_equal (DECL_NAME (real_var),
+ (*(ps_node->linear_var_list))[ii]))
+ return int_cst_value ((*(ps_node->linear_steps_list))[ii]);
+
+ return 0;
+}
+
+/* Returns true when all the reductions_var in the pragma simd data structure
+ with index field matching PRAGMA_SIMD_INDEX is NULL or has a length of 0. */
+
+bool
+all_reductions_satisfied_p (unsigned int pragma_simd_index)
+{
+ unsigned int ii;
+ bool satisfied = true;
+ vec <struct reduction_node, va_gc> *red_list =
+ psv_find_reduction_list (pragma_simd_index);
+
+ if (!red_list || vec_safe_length (red_list) == 0)
+ return true;
+
+ for (ii = 0; ii < vec_safe_length (red_list); ii++)
+ if (vec_safe_length ((*red_list)[ii].reduction_vars) != 0)
+ satisfied = false;
+
+ return satisfied;
+}
+
+/* If definition variable of REDUC_STMT is marked as a reduction variable
+ in the pragma simd data structure whose index field matches PS_INDEX, the
+ variable is removed from the list. */
+
+void
+check_off_reduction_var (gimple reduc_stmt, unsigned int ps_index)
+{
+ enum tree_code op_code = NOP_EXPR;
+ tree def;
+ bool found = false;
+ unsigned int ii, jj;
+ vec<struct reduction_node, va_gc> *red_list =
+ psv_find_reduction_list (ps_index);
+
+ if (!red_list || vec_safe_length (red_list) == 0)
+ return;
+
+ if (!reduc_stmt || gimple_code (reduc_stmt) != GIMPLE_ASSIGN)
+ return;
+
+ def = gimple_assign_lhs (reduc_stmt);
+ gcc_assert (def != NULL_TREE);
+
+ if (TREE_CODE (def) == SSA_NAME)
+ def = SSA_NAME_VAR (def);
+ if (TREE_CODE (def) == VAR_DECL || TREE_CODE (def) == PARM_DECL)
+ def = DECL_NAME (def);
+ op_code = gimple_assign_rhs_code (reduc_stmt);
+
+ for (ii = 0; ii < vec_safe_length (red_list); ii++)
+ if ((*red_list)[ii].reduction_type == (int) op_code)
+ {
+ unsigned int length = vec_safe_length ((*red_list)[ii].reduction_vars);
+ for (jj = 0; jj < length; jj++)
+ {
+ tree var = (*((*red_list)[ii].reduction_vars))[jj];
+ if (simple_cst_equal (var, def))
+ {
+ found = true;
+ break;
+ }
+ }
+ if (found)
+ (*red_list)[ii].reduction_vars->unordered_remove (jj);
+ }
+}
diff --git a/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/errors/cilkplus_AN_cpp_errors.exp b/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/errors/cilkplus_AN_cpp_errors.exp
new file mode 100644
index 00000000000..7a2360c5a28
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/errors/cilkplus_AN_cpp_errors.exp
@@ -0,0 +1,25 @@
+# Copyright (C) 2012-2013 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# Written by Balaji V. Iyer <balaji.v.iyer@intel.com>
+
+
+load_lib gcc-dg.exp
+
+dg-init
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.cc]] " -fcilkplus" " "
+dg-finish
+
diff --git a/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/errors/fp_triplet_values.cc b/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/errors/fp_triplet_values.cc
index d664c03e439..31dbaf83c04 100644
--- a/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/errors/fp_triplet_values.cc
+++ b/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/errors/fp_triplet_values.cc
@@ -1,5 +1,5 @@
-/* {dg-do compile } */
-/* {dg-options } */
+/* { dg-do compile } */
+/* { dg-options } */
#include <cstdlib>
float q;
#if 1
diff --git a/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/errors/parser_errors.cc b/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/errors/parser_errors.cc
index d3fc2a6e5ab..760565e42b3 100644
--- a/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/errors/parser_errors.cc
+++ b/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/errors/parser_errors.cc
@@ -1,5 +1,5 @@
-/* {dg-do compile } */
-/* {dg-options } */
+/* { dg-do compile } */
+/* { dg-options } */
int main (int argc, char **argv)
{
diff --git a/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/errors/sec_implicit.cc b/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/errors/sec_implicit.cc
index 70d38f0e6af..b2a1d7b4a27 100644
--- a/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/errors/sec_implicit.cc
+++ b/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/errors/sec_implicit.cc
@@ -1,5 +1,5 @@
-/* {dg-do compile } */
-/* {dg-options } */
+/* { dg-do compile } */
+/* { dg-options } */
int main (int argc, char **argv)
{
diff --git a/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/errors/sec_implicit2.cc b/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/errors/sec_implicit2.cc
index f37aa4e27ca..db08c994ffb 100644
--- a/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/errors/sec_implicit2.cc
+++ b/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/errors/sec_implicit2.cc
@@ -1,5 +1,5 @@
-/* {dg-do compile } */
-/* {dg-options } */
+/* { dg-do compile } */
+/* { dg-options } */
int main (int argc, char **argv)
{
diff --git a/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/errors/sec_inside_sec.cc b/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/errors/sec_inside_sec.cc
new file mode 100644
index 00000000000..ebad022df97
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/errors/sec_inside_sec.cc
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-fcilkplus" } */
+
+int main ()
+{
+ int a;
+ a = __sec_reduce_add(__sec_reduce_add(1)); /* { dg-error "parameter with zero rank" } */
+ a = __sec_reduce_mul(__sec_reduce_add(1)); /* { dg-error "parameter with zero rank" } */
+ a = __sec_reduce_max(__sec_reduce_add(1)); /* { dg-error "parameter with zero rank" } */
+ a = __sec_reduce_min(__sec_reduce_add(1)); /* { dg-error "parameter with zero rank" } */
+ a = __sec_reduce_any_zero(__sec_reduce_add(1)); /* { dg-error "parameter with zero rank" } */
+ a = __sec_reduce_any_nonzero(__sec_reduce_add(1)); /* { dg-error "parameter with zero rank" } */
+ a = __sec_reduce_all_zero(__sec_reduce_add(1)); /* { dg-error "parameter with zero rank" } */
+ a = __sec_reduce_all_nonzero(__sec_reduce_add(1)); /* { dg-error "parameter with zero rank" } */
+ a = __sec_reduce_max_ind(__sec_reduce_add(1)); /* { dg-error "parameter with zero rank" } */
+ a = __sec_reduce_min_ind(__sec_reduce_add(1)); /* { dg-error "parameter with zero rank" } */
+ a = __sec_reduce(0, __sec_reduce_add(1), __sec_reduce_add); /* { dg-error "parameter with zero rank" } */
+ __sec_reduce_mutating (&a, __sec_reduce_add(1), __sec_reduce_add); /* { dg-error "parameter with zero rank" } */
+ return 0;
+}
+
+
diff --git a/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/errors/sec_inside_sec2.cc b/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/errors/sec_inside_sec2.cc
new file mode 100644
index 00000000000..05e00ef2188
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/errors/sec_inside_sec2.cc
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-fcilkplus" } */
+int A[256];
+
+int add( int x, int y)
+{
+ return x+y;
+}
+
+void
+check () {
+ int a;
+ a = __sec_reduce_min_ind (__sec_reduce_min_ind (A[:])); /* { dg-error "cannot have array notation parameter with zero" } */
+ a = __sec_reduce_max_ind (__sec_reduce_min_ind (A[:])); /* { dg-error "cannot have array notation parameter with zero" } */
+ a = __sec_reduce_any_zero (__sec_reduce_min_ind (A[:])); /* { dg-error "cannot have array notation parameter with zero" } */
+ a = __sec_reduce_any_nonzero (__sec_reduce_min_ind (A[:])); /* { dg-error "cannot have array notation parameter with zero" } */
+ a = __sec_reduce_all_nonzero (__sec_reduce_min_ind (A[:])); /* { dg-error "cannot have array notation parameter with zero" } */
+ a = __sec_reduce_max (__sec_reduce_min_ind (A[:])); /* { dg-error "cannot have array notation parameter with zero" } */
+ a = __sec_reduce_min (__sec_reduce_min_ind (A[:])); /* { dg-error "cannot have array notation parameter with zero" } */
+ a = __sec_reduce_mul (__sec_reduce_min_ind (A[:])); /* { dg-error "cannot have array notation parameter with zero" } */
+ a = __sec_reduce_add (__sec_reduce_min_ind (A[:])); /* { dg-error "cannot have array notation parameter with zero" } */
+ a = __sec_reduce (0, __sec_reduce_min_ind (A[:]), add); /* { dg-error "cannot have array notation parameter with zero" } */
+ __sec_reduce_mutating (&a, __sec_reduce_min_ind (A[:]), add); /* { dg-error "cannot have array notation parameter with zero" } */
+}
+
diff --git a/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/errors/sec_reduce_max_min_ind.cc b/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/errors/sec_reduce_max_min_ind.cc
index fb41ba3f669..d4a5b773719 100644
--- a/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/errors/sec_reduce_max_min_ind.cc
+++ b/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/errors/sec_reduce_max_min_ind.cc
@@ -1,5 +1,5 @@
-/* {dg-do compile } */
-/* {dg-options } */
+/* { dg-do compile } */
+/* { dg-options } */
int main (int argc, char **argv)
{
diff --git a/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/errors/tst_lngth.cc b/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/errors/tst_lngth.cc
new file mode 100644
index 00000000000..68ac452e6f4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/errors/tst_lngth.cc
@@ -0,0 +1,39 @@
+/* { dg-do compile } */
+/* { dg-options "-fcilkplus" } */
+
+#if HAVE_IO
+#include <stdio.h>
+#endif
+
+#define N 256
+
+template <class T>
+int
+main2 (int argc, char **argv)
+{
+ T A[N], B[N];
+ T A2[N][N], B2[N][N];
+ T A3[N][N][N], B3[N][N][N];
+ T A4[N][N][N][N], B4[N][N][N][N];
+ A[0:(N / 4)] = A[4]+ B[0:(N / 2):2]; /* { dg-error "length mismatch between" } */
+ A[0:(N / 4)] = B[0:(N / 2):2] + N; /* { dg-error "length mismatch between" } */
+ A[0:(N / 4)] = B[0:(N / 2):2] + A[4]; /* { dg-error "length mismatch between" } */
+ A[0:10:1] = B[0:10:1] + A[0:5:1]; /* { dg-error "length mismatch in " } */
+ A[0:10:1] = B[0:5:1] + A[0:10:1]; /* { dg-error "length mismatch in " } */
+ A2[:][:] = B2[:][0:5] + B2[:][0:10]; /* { dg-error "length mismatch in " } */
+ A2[5][:] = B2[5][0:5] + B2[3][0:10]; /* { dg-error "length mismatch in " } */
+ A3[:][5][:] = B3[:][5][0:5] + B3[:][3][0:10]; /* { dg-error "length mismatch in " } */
+ A3[:][5][:] = B3[5][:][0:5] + B3[:][3][0:10]; /* { dg-error "length mismatch in " } */
+ A4[:][:][:][:] = B4[:][:][0:5][:] + B4[:][:][:][0:5:1]; /* { dg-error "length mismatch in " } */
+ return 0;
+}
+
+int main (int argc, char **argv)
+{
+ main2 <char> (argc, argv);
+ main2 <short> (argc, argv);
+ main2 <int> (argc, argv);
+ main2 <long> (argc, argv);
+ main2 <long long> (argc, argv);
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/execute/multiple_insert_check.cc b/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/execute/multiple_insert_check.cc
new file mode 100644
index 00000000000..edd3a93052e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/execute/multiple_insert_check.cc
@@ -0,0 +1,17 @@
+int A[256];
+int func (int x) {
+ return x;
+}
+
+/* There was an error that some call exprs were inserted twice. This will
+ check that issue. */
+int main (int argc, char **argv)
+{
+ int x = 0;
+ A[:] = 4;
+ x = func (__sec_reduce_add(A[0:5:2])) + x;
+ if (x != 20)
+ return 1;
+ else
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/execute/sec_red_zero_test.cc b/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/execute/sec_red_zero_test.cc
new file mode 100644
index 00000000000..0b264fecace
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/execute/sec_red_zero_test.cc
@@ -0,0 +1,26 @@
+/* { dg-do run } */
+/* { dg-options "-fcilkplus" } */
+
+#if HAVE_IO
+#include <iostream>
+#endif
+int A[16];
+
+int main () {
+ A[:] = 5;
+#if HAVE_IO
+ std::cout << __sec_reduce_any_zero(A[:]) << "\n";
+#else
+ if (__sec_reduce_any_zero (A[:]))
+ return 1;
+#endif
+ A[:] = 0;
+#if HAVE_IO
+ std::cout << __sec_reduce_any_nonzero(A[:]) << "\n";
+#else
+ if (__sec_reduce_any_nonzero (A[:]))
+ return 1;
+#endif
+ return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/execute/test_sec_limits.cc b/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/execute/test_sec_limits.cc
new file mode 100644
index 00000000000..f8dd4e49413
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/array_notation_tests/execute/test_sec_limits.cc
@@ -0,0 +1,28 @@
+/* { dg-do run } */
+/* { dg-options "-fcilkplus" } */
+
+#if HAVE_IO
+#include <iostream>
+#endif
+#include <limits.h>
+int A[16];
+int a = 0;
+
+int main () {
+ if (__sec_reduce_max(A[0:0:2]) != INT_MIN) {
+#if HAVE_IO
+ std::cout << __sec_reduce_max(A[0:0:2]) << std::endl;
+#endif
+ a++;
+ }
+ if (__sec_reduce_min(A[0:0:2]) != INT_MAX) {
+#if HAVE_IO
+ std::cout << __sec_reduce_min(A[0:0:2]) << std::endl;
+#endif
+ a++;
+ }
+
+ return a;
+}
+
+
diff --git a/gcc/testsuite/g++.dg/cilk-plus/pragma_simd_tests/compile/cilkplus_PS_cpp_compile.exp b/gcc/testsuite/g++.dg/cilk-plus/pragma_simd_tests/compile/cilkplus_PS_cpp_compile.exp
new file mode 100644
index 00000000000..c956054d45b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/pragma_simd_tests/compile/cilkplus_PS_cpp_compile.exp
@@ -0,0 +1,24 @@
+# Copyright (C) 2012-2013 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# Written by Balaji V. Iyer <balaji.v.iyer@intel.com>
+
+
+load_lib gcc-dg.exp
+
+dg-init
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.cc]] " -O3 -ftree-vectorize -fcilkplus" " "
+dg-finish
diff --git a/gcc/testsuite/g++.dg/cilk-plus/pragma_simd_tests/compile/tst1.cc b/gcc/testsuite/g++.dg/cilk-plus/pragma_simd_tests/compile/tst1.cc
new file mode 100644
index 00000000000..b726af792da
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/pragma_simd_tests/compile/tst1.cc
@@ -0,0 +1,52 @@
+/* { dg-do compile } */
+/* { dg-options "-fcilkplus -O3 -w" } */
+
+#define VLEN 4
+
+/* The clauses really doesn't make sense in this, the main thing this code
+ is checking is to see if it can catch the for-loop correctly after
+ the clauses, and compile successfully. */
+int main (void)
+{
+ int array[1000];
+ int i, nphi = 100, w;
+
+
+#pragma simd vectorlength(VLEN) reduction(+:w)
+for (i = 0; i < nphi; i++)
+{
+ w += array[i];
+}
+
+#pragma simd reduction(+:w) vectorlength (VLEN)
+for (i = 0; i < nphi; i++)
+{
+ w += array[i];
+}
+
+#pragma simd vectorlength (VLEN) private(array)
+for (i = 0; i < nphi; i++)
+{
+ w += array[i];
+}
+
+#pragma simd reduction(+:w) noassert
+for (i = 0; i < nphi; i++)
+{
+ w += array[i];
+}
+
+#pragma simd vectorlength(VLEN) linear(nphi:1)
+for (i = 0; i < nphi; i++)
+{
+ w += array[i];
+}
+
+#pragma simd linear(nphi) vectorlength(VLEN) linear(nphi:1)
+for (i = 0; i < nphi; i++)
+{
+ w += array[i];
+}
+return w;
+}
+
diff --git a/gcc/testsuite/g++.dg/cilk-plus/pragma_simd_tests/errors/cilkplus_PS_cpp_errors.exp b/gcc/testsuite/g++.dg/cilk-plus/pragma_simd_tests/errors/cilkplus_PS_cpp_errors.exp
new file mode 100644
index 00000000000..578c3672606
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/pragma_simd_tests/errors/cilkplus_PS_cpp_errors.exp
@@ -0,0 +1,24 @@
+# Copyright (C) 2012-2013 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# Written by Balaji V. Iyer <balaji.v.iyer@intel.com>
+
+
+load_lib gcc-dg.exp
+
+dg-init
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.cc]] " " " "
+dg-finish
diff --git a/gcc/testsuite/g++.dg/cilk-plus/pragma_simd_tests/errors/for_body_errors.cc b/gcc/testsuite/g++.dg/cilk-plus/pragma_simd_tests/errors/for_body_errors.cc
new file mode 100644
index 00000000000..0165327dc23
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cilk-plus/pragma_simd_tests/errors/for_body_errors.cc
@@ -0,0 +1,54 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fcilkplus" } */
+
+#include <setjmp.h>
+int main(void)
+{
+ int ii = 0;
+
+#pragma simd
+ for (ii = 0; ii < 1000; ii++)
+ break; /* { dg-error "break statements are not allowed" } */
+
+#pragma simd linear (ii)
+ for (ii = 0; ii < 1000; ii++)
+ if (ii)
+ continue; /* { dg-error "continue statements are not allowed" } */
+
+#pragma simd
+ for (ii = 0; ii < 1000; ii++)
+ {
+L5:
+ goto L5; /* { dg-error "goto statements are not allowed" } */
+ }
+
+#pragma simd
+ for (ii = 0; ii < 1000; ii++)
+ {
+ try { /* { dg-error "try statements are not allowed" } */
+ ii = ii %2;
+ }
+ catch (...)
+ {
+ }
+ }
+
+#pragma simd
+ for (ii = 0; ii < 1000; ii++)
+ {
+ jmp_buf x;
+ if (!setjmp (x)) /* { dg-error "setjmps are not allowed inside" } */
+ return 5;
+ }
+
+ for (ii = 0; ii < 1000; ii++)
+ {
+ try { /* This is OK! */
+ ii = ii %2;
+ }
+ catch (...)
+ {
+ }
+ }
+ return 5;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation_tests/errors/sec_inside_sec2.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation_tests/errors/sec_inside_sec2.c
new file mode 100644
index 00000000000..33fd8b525d6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation_tests/errors/sec_inside_sec2.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-fcilkplus" } */
+int A[256];
+
+int add( int x, int y)
+{
+ return x+y;
+}
+
+void
+check () {
+ int a;
+ a = __sec_reduce_min_ind (__sec_reduce_min_ind (A[:])); /* { dg-error "cannot have array notation parameter with zero" } */
+ a = __sec_reduce_max_ind (__sec_reduce_min_ind (A[:])); /* { dg-error "cannot have array notation parameter with zero" } */
+ a = __sec_reduce_any_zero (__sec_reduce_min_ind (A[:])); /* { dg-error "cannot have array notation parameter with zero" } */
+ a = __sec_reduce_any_nonzero (__sec_reduce_min_ind (A[:])); /* { dg-error "cannot have array notation parameter with zero" } */
+ a = __sec_reduce_all_nonzero (__sec_reduce_min_ind (A[:])); /* { dg-error "cannot have array notation parameter with zero" } */
+ a = __sec_reduce_max (__sec_reduce_min_ind (A[:])); /* { dg-error "cannot have array notation parameter with zero" } */
+ a = __sec_reduce_min (__sec_reduce_min_ind (A[:])); /* { dg-error "cannot have array notation parameter with zero" } */
+ a = __sec_reduce_mul (__sec_reduce_min_ind (A[:])); /* { dg-error "cannot have array notation parameter with zero" } */
+ a = __sec_reduce_add (__sec_reduce_min_ind (A[:])); /* { dg-error "cannot have array notation parameter with zero" } */
+ a = __sec_reduce (0, __sec_reduce_min_ind (A[:]), add); /* { dg-error "cannot have array notation parameter with zero" } */
+ __sec_reduce_mutating (&a, __sec_reduce_min_ind (A[:]), add); /* { dg-error "cannot have array notation parameter with zero" } */
+}
+
+
+
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation_tests/errors/tst_lngth.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation_tests/errors/tst_lngth.c
new file mode 100644
index 00000000000..015a7eb7370
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation_tests/errors/tst_lngth.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options " -fcilkplus " } */
+
+#if HAVE_IO
+#include <stdio.h>
+#endif
+
+#define N 256
+int A[N], B[N];
+
+int
+main ()
+{
+ A[0:(N / 4)] = A[4]+ B[0:(N / 2):2]; /* { dg-error "length mismatch between" } */
+ A[0:(N / 4)] = B[0:(N / 2):2] + N; /* { dg-error "length mismatch between" } */
+ A[0:(N / 4)] = B[0:(N / 2):2] + A[4]; /* { dg-error "length mismatch between" } */
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/array_notation_tests/execute/test_sec_limits.c b/gcc/testsuite/gcc.dg/cilk-plus/array_notation_tests/execute/test_sec_limits.c
new file mode 100644
index 00000000000..f4f3ca5a6bb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/array_notation_tests/execute/test_sec_limits.c
@@ -0,0 +1,18 @@
+/* { dg-do run } */
+/* { dg-options "-fcilkplus" } */
+
+#include <limits.h>
+int A[16];
+int a = 0;
+
+int main () {
+ if (__sec_reduce_max(A[0:0:2]) != INT_MIN)
+ a++;
+
+ if (__sec_reduce_min(A[0:0:2]) != INT_MAX)
+ a++;
+
+ return a;
+}
+
+
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/compile/assert1.c b/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/compile/assert1.c
new file mode 100644
index 00000000000..85c6373b9bb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/compile/assert1.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fcilkplus" } */
+
+struct stuff {
+ char asdf;
+ float f;
+};
+
+void add_floats(struct stuff *a, struct stuff *b, int n)
+{
+ int i;
+#pragma simd assert
+ for (i=0; i<n; i++) // { dg-error "loop not vectorized" }
+ {
+ a[i].f = a[i].f + b[i].f;
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/compile/assert2.c b/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/compile/assert2.c
new file mode 100644
index 00000000000..e82308edd22
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/compile/assert2.c
@@ -0,0 +1,12 @@
+// { dg-do compile }
+// { dg-options "-O3" }
+
+void addf(float *a, float *b, float *c, int n)
+{
+ int i;
+#pragma simd assert vectorlength(1) /* { dg-error "vectorlength in pragma" } */
+ for (i=0; i<10; i++)
+ {
+ a[i] = b[i] + c[i];
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/compile/cilkplus_PS_c_compile.exp b/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/compile/cilkplus_PS_c_compile.exp
index 400a033fde7..b6a149f4c7d 100644
--- a/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/compile/cilkplus_PS_c_compile.exp
+++ b/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/compile/cilkplus_PS_c_compile.exp
@@ -21,45 +21,14 @@ load_lib gcc-dg.exp
dg-init
dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -fcilkplus" " "
-dg-finish
-
-dg-init
dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O0 -fcilkplus" " "
-dg-finish
-
-dg-init
dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O1 -fcilkplus" " "
-dg-finish
-
-dg-init
dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O2 -ftree-vectorize -fcilkplus" " "
-dg-finish
-
-dg-init
dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -O3 -fcilkplus" " "
-dg-finish
-
-
-dg-init
dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -fcilkplus" " "
-dg-finish
-
-dg-init
dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O0 -fcilkplus" " "
-dg-finish
-
-dg-init
dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O1 -fcilkplus" " "
-dg-finish
-
-dg-init
dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O2 -ftree-vectorize -fcilkplus" " "
-dg-finish
-
-dg-init
dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " -g -O3 -fcilkplus" " "
-dg-finish
-
-dg-init
dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/array_notation_tests/errors/*.c]] " -O3 -ftree-vectorize -fcilkplus -g" " "
dg-finish
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/compile/cond_vlength.c b/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/compile/cond_vlength.c
index a52e9ed8ac4..904032c8547 100644
--- a/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/compile/cond_vlength.c
+++ b/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/compile/cond_vlength.c
@@ -1,13 +1,12 @@
/* { dg-do run } */
-/* { dg-options " -w" } */
+/* { dg-options " -w " } */
int main ()
{
int i;
float a[256];
- /* The line below should be OK! We are looking to make sure sizeof expression
- is folded into a integer. Not checking if it accepts the vectorlength. */
+ // The line below should be OK!
#pragma simd vectorlength(sizeof (a) == sizeof (float) ? 4 : 8)
for (i = 0; i < 256; i++)
{
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/errors/cilkplus_PS_c_errors.exp b/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/errors/cilkplus_PS_c_errors.exp
new file mode 100644
index 00000000000..e923a8047f1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/errors/cilkplus_PS_c_errors.exp
@@ -0,0 +1,24 @@
+# Copyright (C) 2012-2013 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# Written by Balaji V. Iyer <balaji.v.iyer@intel.com>
+
+
+load_lib gcc-dg.exp
+
+dg-init
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " " " "
+dg-finish
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/errors/for_body_errors.c b/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/errors/for_body_errors.c
new file mode 100644
index 00000000000..7d1563b030b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/errors/for_body_errors.c
@@ -0,0 +1,34 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fcilkplus" } */
+
+#include <setjmp.h>
+
+int main(void)
+{
+ int ii = 0;
+
+#pragma simd
+ for (ii = 0; ii < 1000; ii++)
+ break; /* { dg-error "goto/break/continue statments are" } */
+
+#pragma simd linear (ii)
+ for (ii = 0; ii < 1000; ii++)
+ if (ii)
+ continue; /* { dg-error "goto/break/continue statments are" } */
+
+#pragma simd
+ for (ii = 0; ii < 1000; ii++)
+ {
+L5:
+ goto L5; /* { dg-error "goto/break/continue statments are" } */
+ }
+
+#pragma simd
+ for (ii = 0; ii < 1000; ii++)
+ {
+ jmp_buf x;
+ if (!setjmp (x)) /* { dg-error "setjmps are not allowed inside" } */
+ return 5;
+ }
+ return 5;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/errors/opt_error.c b/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/errors/opt_error.c
new file mode 100644
index 00000000000..39c5377ce5a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/errors/opt_error.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-fcilkplus -O2" } */
+
+int main(void)
+{
+ int ii, A[1000];
+#pragma simd /* { dg-warning "pragma simd is useless without" } */
+ for (ii = 0; ii < 1000; ii++)
+ {
+ A[ii] = ii;
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/errors/opt_error2.c b/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/errors/opt_error2.c
new file mode 100644
index 00000000000..36709bcf57d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/errors/opt_error2.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -Wunknown-pragmas" } */
+
+int main(void)
+{
+ int ii, A[1000];
+#pragma simd /* { dg-warning "ignoring" } */
+ for (ii = 0; ii < 1000; ii++)
+ {
+ A[ii] = ii;
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/errors/same_var_multiple_clauses.c b/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/errors/same_var_multiple_clauses.c
new file mode 100644
index 00000000000..7acde445d90
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/errors/same_var_multiple_clauses.c
@@ -0,0 +1,48 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fcilkplus" } */
+
+#define N 1000
+
+int A[N], B[N], C[N];
+int main (void)
+{
+ int ii = 0;
+
+#pragma simd private (B) linear(B:1) /* { dg-error "listed in both linear and private pragma simd " } */
+ for (ii = 0; ii < N; ii++)
+ {
+ A[ii] = B[ii] + C[ii];
+ }
+
+#pragma simd private (B, C) linear(B:1) /* { dg-error "listed in both linear and private pragma simd " } */
+ for (ii = 0; ii < N; ii++)
+ {
+ A[ii] = B[ii] + C[ii];
+ }
+
+#pragma simd private (B) linear(C:2, B:1) /* { dg-error "listed in both linear and private pragma simd " } */
+ for (ii = 0; ii < N; ii++)
+ {
+ A[ii] = B[ii] + C[ii];
+ }
+
+#pragma simd reduction (+:B) linear(B:1) /* { dg-error "listed in both reduction and linear pragma simd" } */
+ for (ii = 0; ii < N; ii++)
+ {
+ A[ii] = B[ii] + C[ii];
+ }
+
+#pragma simd reduction (+:B) linear(B) /* { dg-error "listed in both reduction and linear pragma simd" } */
+ for (ii = 0; ii < N; ii++)
+ {
+ A[ii] = B[ii] + C[ii];
+ }
+
+#pragma simd private (B) reduction (+:A) reduction (+:B) /* { dg-error "listed in both reduction and private pragma simd" } */
+ for (ii = 0; ii < N; ii++)
+ {
+ A[ii] = B[ii] + C[ii];
+ }
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/execute/cilkplus_PS_c_execute.exp b/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/execute/cilkplus_PS_c_execute.exp
index 99c5bc0aa1c..509acbb44c5 100644
--- a/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/execute/cilkplus_PS_c_execute.exp
+++ b/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/execute/cilkplus_PS_c_execute.exp
@@ -20,47 +20,7 @@
verbose "$tool $libdir" 1
-set library_var [get_multilibs]
dg-init
-set CILK_TORTURE_OPTIONS [list \
- { -O0 -fcilkplus -lcilkrts -std=c99} \
- { -O1 -fcilkplus -lcilkrts -std=c99} \
- { -O2 -fcilkplus -lcilkrts -std=c99} \
- { -O3 -fcilkplus -lcilkrts -fomit-frame-pointer -funroll-loops -std=c99} \
- { -O3 -fcilkplus -lcilkrts -fomit-frame-pointer -funroll-all-loops -finline-functions -std=c99 } \
- { -O3 -g -fcilkplus -lcilkrts -std=c99} \
- { -Os -fcilkplus -lcilkrts -std=c99} \
- { -O0 -fcilkplus -lcilkrts -std=c99 -flto} \
- { -O1 -fcilkplus -lcilkrts -std=c99 -flto} \
- { -O2 -fcilkplus -lcilkrts -std=c99 -flto} \
- { -O3 -fcilkplus -lcilkrts -fomit-frame-pointer -funroll-loops -std=c99 -flto } \
- { -O3 -fcilkplus -lcilkrts -fomit-frame-pointer -funroll-all-loops -finline-functions -std=c99 -flto} \
- { -O3 -g -fcilkplus -lcilkrts -std=c99 -flto} \
- { -Os -fcilkplus -lcilkrts -std=c99 -flto} ]
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.c]] " " " "
+dg-finish
-
-if $tracelevel then {
- strace $tracelevel
-}
-
-# load support procs
-load_lib torture-options.exp
-load_lib c-torture.exp
-
-torture-init
-set-torture-options $CILK_TORTURE_OPTIONS {{}} $CILK_TORTURE_OPTIONS
-
-#
-# main test loop
-#
-
-foreach src [lsort [glob -nocomplain $srcdir/$subdir/*.c]] {
- # If we're only testing specific files and this isn't one of them, skip it.
- if ![runtest_file_p $runtests $src] then {
- continue
- }
-
- c-torture-execute $src
-}
-
-torture-finish
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/execute/p_simd_test1.c b/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/execute/p_simd_test1.c
index 5423d9aca21..4a250cb3f3d 100644
--- a/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/execute/p_simd_test1.c
+++ b/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/execute/p_simd_test1.c
@@ -1,5 +1,5 @@
/* { dg-do run } */
-/* { dg-options "-O3 -ftree-vectorize -fcilkplus" } */
+/* { dg-options "-O3 -ftree-vectorize -fcilkplus -w" } */
#define ARRAY_SIZE (256)
#if HAVE_IO
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/execute/p_simd_test2.c b/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/execute/p_simd_test2.c
index a3c54364062..14d53f64308 100644
--- a/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/execute/p_simd_test2.c
+++ b/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/execute/p_simd_test2.c
@@ -1,3 +1,7 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -ftree-vectorize -fcilkplus -w" } */
+
+
#define N 256
#if HAVE_IO
#include <stdio.h>
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/execute/reduction_ex.c b/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/execute/reduction_ex.c
new file mode 100644
index 00000000000..5acf7c0c54b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/execute/reduction_ex.c
@@ -0,0 +1,36 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -fcilkplus" } */
+
+
+/* This is a simple vectorization, it checks if check_off_reduction_var works
+ and it also checks if it can vectorize this loop in func correctly. */
+#define N 1000
+
+int func (int *p, int *q) {
+ int ii;
+ int x = 0;
+#pragma simd reduction (+:x)
+ for (ii = 0; ii < N; ii++) {
+ x += (q[ii] + p[ii]);
+ }
+ return x;
+
+}
+
+int main (int argc, char **argv)
+{
+ int ii = 0, x;
+ int Array[N], Array2[N];
+
+ for (ii = 0; ii < N; ii++)
+ {
+ Array[ii] = 5 + argc;
+ Array2[ii] = argc;
+ }
+ x = func (Array, Array2);
+
+ if (x != N * 7)
+ return 1;
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/execute/vlength_comma.c b/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/execute/vlength_comma.c
index 2f62bae660e..9d870d73369 100644
--- a/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/execute/vlength_comma.c
+++ b/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/execute/vlength_comma.c
@@ -1,3 +1,7 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -ftree-vectorize -fcilkplus -w" } */
+
+
int a[100];
int
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/execute/vlength_comma2.c b/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/execute/vlength_comma2.c
index b049c507d92..f2b2ef96de2 100644
--- a/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/execute/vlength_comma2.c
+++ b/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/execute/vlength_comma2.c
@@ -1,3 +1,6 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -ftree-vectorize -fcilkplus -w" } */
+
int a[100];
int
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/execute/vlength_comma3.c b/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/execute/vlength_comma3.c
index 014005b7b25..d39aa340a58 100644
--- a/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/execute/vlength_comma3.c
+++ b/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/execute/vlength_comma3.c
@@ -1,3 +1,7 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -ftree-vectorize -fcilkplus -w" } */
+
+
int a[100];
int
diff --git a/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/pragma-simd-for.c b/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/pragma-simd-for.c
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/gcc/testsuite/gcc.dg/cilk-plus/pragma_simd_tests/pragma-simd-for.c
+++ /dev/null
diff --git a/gcc/tree-loop-distribution.c b/gcc/tree-loop-distribution.c
index 192dbad0936..6ea0b8f47c8 100644
--- a/gcc/tree-loop-distribution.c
+++ b/gcc/tree-loop-distribution.c
@@ -128,7 +128,7 @@ ssa_name_has_uses_outside_loop_p (tree def, loop_p loop)
{
gimple use_stmt = USE_STMT (use_p);
if (flag_enable_cilk
- && pragma_simd_is_private_var (loop->pragma_simd_index, def))
+ && pragma_simd_is_private_var_p (loop->pragma_simd_index, def))
/* Don't do any more checks for this value. The user has indicated that
this variable is private to the loop. */
;
diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c
index 0065b463bbf..562782565b3 100644
--- a/gcc/tree-vect-loop.c
+++ b/gcc/tree-vect-loop.c
@@ -746,7 +746,23 @@ vect_analyze_scalar_cycles_1 (loop_vec_info loop_vinfo, struct loop *loop)
nested_cycle = (loop != LOOP_VINFO_LOOP (loop_vinfo));
reduc_stmt = vect_force_simple_reduction (loop_vinfo, phi, !nested_cycle,
&double_reduc);
- check_off_reduction_var (reduc_stmt, loop->pragma_simd_index);
+ if (flag_enable_cilk && reduc_stmt)
+ {
+ check_off_reduction_var (reduc_stmt, loop->pragma_simd_index);
+ if (dump_enabled_p ())
+ {
+ tree lhs = gimple_get_lhs (reduc_stmt);
+ if (TREE_CODE (lhs) == SSA_NAME)
+ lhs = SSA_NAME_VAR (lhs);
+ if (TREE_CODE (lhs) == VAR_DECL || TREE_CODE (lhs) == PARM_DECL)
+ {
+ lhs = DECL_NAME (lhs);
+ dump_printf_loc (MSG_NOTE, vect_location, "%s is reduced as "
+ "requested by pragma simd",
+ IDENTIFIER_POINTER (lhs));
+ }
+ }
+ }
if (reduc_stmt)
{
if (double_reduc)
diff --git a/gcc/tree-vectorizer.c b/gcc/tree-vectorizer.c
index a367bb8f1bf..376d4ce0155 100644
--- a/gcc/tree-vectorizer.c
+++ b/gcc/tree-vectorizer.c
@@ -102,10 +102,7 @@ vectorize_loops (void)
than all previously defined loops. This fact allows us to run
only over initial loops skipping newly generated ones. */
FOR_EACH_LOOP (li, loop, 0)
- if (((!flag_enable_cilk) && (optimize_loop_nest_for_speed_p (loop)))
- || (flag_enable_cilk
- && (optimize_loop_nest_for_speed_p (loop)
- || pragma_simd_vectorize_loop_p (loop->pragma_simd_index))))
+ if (optimize_loop_nest_for_speed_p (loop))
{
loop_vec_info loop_vinfo;
vect_location = find_loop_location (loop);
@@ -130,63 +127,10 @@ vectorize_loops (void)
vect_location = UNKNOWN_LOC;
- FOR_EACH_LOOP (li, loop, 0)
+ if (flag_enable_cilk)
{
- if (flag_enable_cilk)
- {
- if ((!clause_resolved_p (P_SIMD_VECTORLENGTH,
- loop->pragma_simd_index)))
- {
- if (pragma_simd_assert_requested_p (loop->pragma_simd_index))
- {
- error ("Vectorlength not picked from the list."
- " ASSERT REQUESTED");
- exit (ICE_EXIT_CODE);
- }
- else
- {
- warning (0, "Vectorlength not picked from list.");
- }
- }
- if (!clause_resolved_p (P_SIMD_PRIVATE, loop->pragma_simd_index))
- {
- if (pragma_simd_assert_requested_p (loop->pragma_simd_index))
- {
- error ("Unable to make all variables private. "
- "ASSERT REQUESTED");
- exit(ICE_EXIT_CODE);
- }
- else
- {
- warning (0, "Unable to make all variables private.");
- }
- }
- if (!clause_resolved_p (P_SIMD_LINEAR, loop->pragma_simd_index))
- {
- if (pragma_simd_assert_requested_p (loop->pragma_simd_index))
- {
- error ("Unable to pick requested step-size. "
- "ASSERT REQUESTED");
- exit(ICE_EXIT_CODE);
- }
- else
- {
- warning (0, "Unable to pick requested step-size.");
- }
- }
- if (!clause_resolved_p (P_SIMD_REDUCTION, loop->pragma_simd_index))
- {
- if (pragma_simd_assert_requested_p (loop->pragma_simd_index))
- {
- error ("Unable to satisfy all reductions.\nASSERT REQUESTED");
- exit(ICE_EXIT_CODE);
- }
- else
- {
- warning (0, "Unable to satisfy all reductions...continuing");
- }
- }
- }
+ FOR_EACH_LOOP (li, loop, 0)
+ pragma_simd_verify_clauses (loop->pragma_simd_index);
}
statistics_counter_event (cfun, "Vectorized loops", num_vectorized_loops);
diff --git a/gcc/tree.h b/gcc/tree.h
index fea5384eda9..173bca42962 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -46,56 +46,46 @@ MAX_TREE_CODES
#define INVALID_PRAGMA_SIMD_SLOT 35
-typedef enum pragma_simd_kind
-{
- P_SIMD_NOASSERT = 0, /* Default is just to noassert. */
- P_SIMD_ASSERT = 1,
- P_SIMD_VECTORLENGTH = 2,
- P_SIMD_PRIVATE = 4,
- P_SIMD_LINEAR = 8,
- P_SIMD_REDUCTION = 16
-} pragma_simd_kind;
-struct reduction_values
-{
- enum tree_code reduction_operator;
- char **reduction_var_list;
- tree tree_reduction_var_list;
- int not_reduced;
- struct reduction_values *ptr_next;
-};
-/* Since we can have multiple pragma simd, this will hold the values of
- each of the pragma simd and then as soon as it finds a for loop
- it will transfer those values into the loop tree structure. */
-struct pragma_simd_values
-{
- int index;
- bool pragma_encountered;
- unsigned int types;
- tree vectorlength;
- bool vlength_OK;
- int *vec_length_list;
- int vec_length_size;
- tree private_vars;
- bool pvars_OK;
- char **priv_var_list;
- int priv_var_size;
- tree linear_vars;
- bool lvars_OK;
- char **linear_var_list;
- int linear_var_size;
- tree linear_steps;
- int *linear_steps_list;
- int linear_steps_size;
- struct reduction_values *reduction_vals;
- bool rvars_OK;
- struct pragma_simd_values *ptr_next;
+enum pragma_simd_assert_types {
+ P_SIMD_ASSERT = 1,
+ P_SIMD_NOASSERT = 2
};
-extern struct pragma_simd_values *psv_head;
+enum pragma_simd_kind {
+ P_SIMD_VECTORLENGTH = 0,
+ P_SIMD_PRIVATE,
+ P_SIMD_LINEAR,
+ P_SIMD_REDUCTION
+};
+struct reduction_node {
+ int reduction_type;
+ vec<tree, va_gc> *reduction_vars;
+};
+/* Since we can have multiple pragma simds, this holds the values of
+ each of the pragma simds as we are parsing them. An index into
+ this table gets propagated to the tree structure for LABEL_DECL's
+ (as for loops are being parsed), then to the gimple structure for
+ GIMPLE_LABEL's, then to the BB structure, and finally to the loop
+ structure. */
+
+struct pragma_simd_values {
+ location_t loc;
+ unsigned int index;
+ enum pragma_simd_assert_types assert_requested;
+ vec<tree, va_gc> *linear_var_list;
+ vec<tree, va_gc> *linear_steps_list;
+ vec<tree, va_gc> *priv_var_list;
+ vec<tree, va_gc> *vec_length_list;
+ bool vlength_OK;
+ bool linear_OK;
+ bool private_OK;
+ bool reduction_OK;
+ vec<struct reduction_node, va_gc> *reduction_list;
+};
#undef DEFTREECODE
#undef END_OF_BASE_TREE_CODES
@@ -6613,25 +6603,24 @@ extern bool block_may_fallthru (const_tree);
/* Here are the pragma simd specific files used by the parser and vectorizer
available in pragma_simd.c. */
-extern struct pragma_simd_values *psv_find_node (int psv_index);
-extern int psv_head_insert (struct pragma_simd_values local_simd_values);
-extern bool pragma_simd_acceptable_vlength_p (int ps_index,
+extern void pragma_simd_verify_clauses (unsigned int);
+
+extern unsigned int p_simd_head_insert (struct pragma_simd_values *);
+extern bool pragma_simd_acceptable_vlength_p (unsigned int ps_index,
int possible_vectorization_factor,
tree scalar_type);
-extern bool pragma_simd_assert_requested_p (int ps_index);
+extern bool pragma_simd_assert_requested_p (unsigned int ps_index);
extern bool pragma_simd_vectorize_loop_p (int ps_index);
extern void insert_reduction_values (struct reduction_values **,
enum tree_code, tree);
-extern bool same_var_in_multiple_lists_p (struct pragma_simd_values *ps_values);
-extern void check_off_reduction_var (gimple reduc_stmt, int pragma_simd_index);
-extern bool all_reductions_satisfied_p (int pragma_simd_index);
-extern bool clause_resolved_p (enum pragma_simd_kind clause_type,
- int pragma_simd_index);
+extern void check_off_reduction_var (gimple reduc_stmt,
+ unsigned int pragma_simd_index);
+extern bool all_reductions_satisfied_p (unsigned int pragma_simd_index);
extern void set_OK_for_certain_clause (enum pragma_simd_kind clause_type,
bool set_value,
- int pragma_simd_index);
-extern HOST_WIDE_INT find_linear_step_size (int pragma_simd_index, tree var);
+ unsigned int pragma_simd_index);
+extern HOST_WIDE_INT find_linear_step_size (unsigned int, tree);
tree build_call_list (tree return_type, tree fn, tree arglist);
bool is_elem_fn (tree);