summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2016-04-25 07:30:20 +0000
committerbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2016-04-25 07:30:20 +0000
commit02c1fcdcb78e34694a4e5b4604477677473d7804 (patch)
tree3240e6af53f9de7f6a778c1b9dcc2f90bc5d5b6c
parent3b2ef6864dbb5abe099620f432bb650e84617af3 (diff)
downloadgcc-02c1fcdcb78e34694a4e5b4604477677473d7804.tar.gz
2016-04-25 Basile Starynkevitch <basile@starynkevitch.net>
{{merging with even more of GCC 6, using subversion 1.9 svn merge -r235003:235034 ^/trunk NB: GCC 7 starts at svn rev 235035 }} git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@235405 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--ChangeLog.MELT6
-rw-r--r--gcc/ChangeLog72
-rw-r--r--gcc/Makefile.in1
-rw-r--r--gcc/c-family/ChangeLog6
-rw-r--r--gcc/c-family/c-common.c14
-rw-r--r--gcc/c/ChangeLog32
-rw-r--r--gcc/c/c-parser.c244
-rw-r--r--gcc/c/c-typeck.c13
-rw-r--r--gcc/config/i386/i386-protos.h2
-rw-r--r--gcc/config/i386/i386.c2
-rw-r--r--gcc/config/i386/i386.md12
-rw-r--r--gcc/config/i386/sse.md7
-rw-r--r--gcc/config/nvptx/nvptx.opt2
-rw-r--r--gcc/cp/ChangeLog24
-rw-r--r--gcc/cp/constexpr.c68
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/decl2.c2
-rw-r--r--gcc/cp/parser.c229
-rw-r--r--gcc/doc/invoke.texi2
-rw-r--r--gcc/omp-low.c1606
-rw-r--r--gcc/omp-simd-clone.c1654
-rw-r--r--gcc/testsuite/ChangeLog50
-rw-r--r--gcc/testsuite/c-c++-common/Wparentheses-1.c39
-rw-r--r--gcc/testsuite/c-c++-common/cilk-plus/CK/Wparentheses-1.c69
-rw-r--r--gcc/testsuite/c-c++-common/cilk-plus/PS/Wparentheses-1.c41
-rw-r--r--gcc/testsuite/c-c++-common/goacc/Wparentheses-1.c174
-rw-r--r--gcc/testsuite/c-c++-common/gomp/Wparentheses-1.c338
-rw-r--r--gcc/testsuite/c-c++-common/gomp/Wparentheses-2.c452
-rw-r--r--gcc/testsuite/c-c++-common/gomp/Wparentheses-3.c338
-rw-r--r--gcc/testsuite/c-c++-common/gomp/Wparentheses-4.c452
-rw-r--r--gcc/testsuite/c-c++-common/pr70651.c9
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/vla11.C712
-rw-r--r--gcc/testsuite/gcc.dg/bitfld-22.c18
-rw-r--r--gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-2.c3
-rw-r--r--gcc/testsuite/gcc.dg/pr10474.c3
-rw-r--r--gcc/testsuite/gcc.dg/vect/O3-pr70130.c94
-rw-r--r--gcc/testsuite/gcc.target/i386/pr46470.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/pr70662.c19
-rw-r--r--gcc/tree-pretty-print.c8
-rw-r--r--gcc/tree-vect-data-refs.c17
40 files changed, 4246 insertions, 2591 deletions
diff --git a/ChangeLog.MELT b/ChangeLog.MELT
index 6c877b6b43f..69ebd6a6aec 100644
--- a/ChangeLog.MELT
+++ b/ChangeLog.MELT
@@ -1,6 +1,12 @@
2016-04-25 Basile Starynkevitch <basile@starynkevitch.net>
{{merging with even more of GCC 6, using subversion 1.9
+ svn merge -r235003:235034 ^/trunk
+ NB: GCC 7 starts at svn rev 235035
+ }}
+
+2016-04-25 Basile Starynkevitch <basile@starynkevitch.net>
+ {{merging with even more of GCC 6, using subversion 1.9
svn merge -r234651:235002 ^/trunk
}}
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f6fdeffcc53..a73fa882e9e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,75 @@
+2016-04-15 Jason Merrill <jason@redhat.com>
+ Nathan Sidwell <nathan@acm.org>
+
+ PR c++/70594
+ * constexpr.c (constexpr_call_table): Preserve in GC.
+ (struct fundef_copy, struct fundef_copies_table_t): Delete.
+ (fundef_copies_table): Preserve in GC. Change to pointer to
+ tree->tree hash.
+ (maybe_initialize_fundef_copies_table): Adjust.
+ (get_fundef_copy): Return a TREE_LIST. Use non-inserting search.
+ (save_fundef_copy): Adjust for a TREE_LIST.
+ (cxx_eval_call_expression): Adjust for a fundef_copy TREE_LIST.
+ (fini_constexpr): New.
+ * cp-tree.h (fini_constexpr): Declare.
+ * decl2.c (c_parse_final_cleanups): Call fini_constexpr.
+
+2016-04-15 Alexander Monakov <amonakov@ispras.ru>
+
+ * config/nvptx/nvptx.opt (moptimize): Add a period at end of help text.
+
+2016-04-15 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * doc/invoke.texi (ARM Options): Add note on deprecation of pre-ARMv4T
+ architecture revisions.
+
+2016-04-15 Bernd Schmidt <bschmidt@redhat.com>
+
+ * config/i386/i386-protos.h (ix86_using_red_zone): Declare.
+ * config/i386/i386.c (ix86_using_red_zone): No longer static.
+ * config/i386/i386.md (stack decrement to push peepholes): Guard
+ with !x86_using_red_zone ().
+
+2016-04-15 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/70675
+ * tree-pretty-print.c (do_niy): Add FLAGS argument, pass it down
+ to dump_generic_node.
+ (NIY): Pass also flags to do_niy.
+
+2016-04-15 Thomas Schwinge <thomas@codesourcery.com>
+
+ * omp-low.c (simd_clone_struct_alloc, simd_clone_struct_copy)
+ (simd_clone_vector_of_formal_parm_types)
+ (simd_clone_clauses_extract, simd_clone_compute_base_data_type)
+ (simd_clone_mangle, simd_clone_create)
+ (simd_clone_adjust_return_type, create_tmp_simd_array)
+ (simd_clone_adjust_argument_types, simd_clone_init_simd_arrays)
+ (struct modify_stmt_info, ipa_simd_modify_stmt_ops)
+ (ipa_simd_modify_function_body, simd_clone_linear_addend)
+ (simd_clone_adjust, expand_simd_clones, ipa_omp_simd_clone)
+ (pass_data_omp_simd_clone, class pass_omp_simd_clone)
+ (pass_omp_simd_clone::gate, make_pass_omp_simd_clone): Move
+ into...
+ * omp-simd-clone.c: ... this new file.
+ (simd_clone_vector_of_formal_parm_types): Make it static.
+ * Makefile.in (OBJS): Add omp-simd-clone.o.
+
+2016-04-15 Kirill Yukhin <kirill.yukhin@intel.com>
+
+ PR target/70662
+ * config/i386/sse.md: Use proper memory operand
+ modifiers.
+
+
+2016-04-15 Richard Biener <rguenther@suse.de>
+ Alan Modra <amodra@gmail.com>
+
+ PR tree-optimization/70130
+ * tree-vect-data-refs.c (vect_supportable_dr_alignment): Detect
+ when alignment stays not the same and no not use the realign
+ scheme then.
+
2016-04-14 Michael Meissner <meissner@linux.vnet.ibm.com>
PR target/70669
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 7045460c77d..a8ffe504898 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1371,6 +1371,7 @@ OBJS = \
modulo-sched.o \
multiple_target.o \
omp-low.o \
+ omp-simd-clone.o \
optabs.o \
optabs-libfuncs.o \
optabs-query.o \
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index f842efc8d4e..ec79edbaa93 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,9 @@
+2016-04-15 Marek Polacek <polacek@redhat.com>
+
+ PR c/70651
+ * c-common.c (build_va_arg): Change two asserts into errors and return
+ error_mark_node.
+
2016-04-13 Marek Polacek <polacek@redhat.com>
PR c++/70639
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 30c815d5381..f2846bb26e7 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -5725,7 +5725,12 @@ build_va_arg (location_t loc, tree expr, tree type)
/* Verify that &ap is still recognized as having va_list type. */
tree canon_expr_type
= targetm.canonical_va_list_type (TREE_TYPE (expr));
- gcc_assert (canon_expr_type != NULL_TREE);
+ if (canon_expr_type == NULL_TREE)
+ {
+ error_at (loc,
+ "first argument to %<va_arg%> not of type %<va_list%>");
+ return error_mark_node;
+ }
return build_va_arg_1 (loc, type, expr);
}
@@ -5793,7 +5798,12 @@ build_va_arg (location_t loc, tree expr, tree type)
/* Verify that &ap is still recognized as having va_list type. */
tree canon_expr_type
= targetm.canonical_va_list_type (TREE_TYPE (expr));
- gcc_assert (canon_expr_type != NULL_TREE);
+ if (canon_expr_type == NULL_TREE)
+ {
+ error_at (loc,
+ "first argument to %<va_arg%> not of type %<va_list%>");
+ return error_mark_node;
+ }
}
else
{
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 4b21d528f80..7257f79e0b2 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,35 @@
+2016-04-15 Marek Polacek <polacek@redhat.com>
+
+ PR c/70671
+ * c-typeck.c (build_unary_op): Pass location down to error and
+ warning call.
+
+2016-04-15 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/70436
+ * c-parser.c (c_parser_pragma): Add IF_P argument, pass it down
+ where needed.
+ (c_parser_external_declaration, c_parser_struct_or_union_specifier,
+ c_parser_parameter_declaration, c_parser_compound_statement_nostart,
+ c_parser_objc_class_instance_variables, c_parser_objc_methodprotolist):
+ Adjust c_parser_pragma callers.
+ (c_parser_statement_after_labels): Likewise. Adjust c_parser_cilk_for
+ caller.
+ (c_parser_omp_structured_block): Add IF_P argument, pass it down to
+ c_parser_statement.
+ (c_parser_oacc_data, c_parser_oacc_host_data, c_parser_oacc_loop,
+ c_parser_oacc_kernels_parallel, c_parser_omp_critical,
+ c_parser_omp_simd, c_parser_omp_for, c_parser_omp_master,
+ c_parser_omp_ordered, c_parser_omp_parallel, c_parser_omp_single,
+ c_parser_omp_task, c_parser_omp_taskgroup, c_parser_omp_distribute,
+ c_parser_omp_teams, c_parser_omp_target_data, c_parser_omp_target,
+ c_parser_omp_taskloop, c_parser_omp_construct, c_parser_cilk_grainsize,
+ c_parser_cilk_simd, c_parser_cilk_for): Add IF_P argument, pass it
+ down where needed.
+ (c_parser_omp_for_loop): Likewise. Clear IF_P if nbraces.
+ (c_parser_omp_sections_scope): Adjust c_parser_omp_structured_block
+ calls.
+
2016-04-13 Marek Polacek <polacek@redhat.com>
PR c/70436
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index d37c6917b32..1b6bacd7498 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -1342,12 +1342,12 @@ static vec<tree, va_gc> *c_parser_expr_list (c_parser *, bool, bool,
static void c_parser_oacc_declare (c_parser *);
static void c_parser_oacc_enter_exit_data (c_parser *, bool);
static void c_parser_oacc_update (c_parser *);
-static void c_parser_omp_construct (c_parser *);
+static void c_parser_omp_construct (c_parser *, bool *);
static void c_parser_omp_threadprivate (c_parser *);
static void c_parser_omp_barrier (c_parser *);
static void c_parser_omp_flush (c_parser *);
static tree c_parser_omp_for_loop (location_t, c_parser *, enum tree_code,
- tree, tree *);
+ tree, tree *, bool *);
static void c_parser_omp_taskwait (c_parser *);
static void c_parser_omp_taskyield (c_parser *);
static void c_parser_omp_cancel (c_parser *);
@@ -1355,11 +1355,11 @@ static void c_parser_omp_cancellation_point (c_parser *);
enum pragma_context { pragma_external, pragma_struct, pragma_param,
pragma_stmt, pragma_compound };
-static bool c_parser_pragma (c_parser *, enum pragma_context);
-static bool c_parser_omp_target (c_parser *, enum pragma_context);
+static bool c_parser_pragma (c_parser *, enum pragma_context, bool *);
+static bool c_parser_omp_target (c_parser *, enum pragma_context, bool *);
static void c_parser_omp_end_declare_target (c_parser *);
static void c_parser_omp_declare (c_parser *, enum pragma_context);
-static bool c_parser_omp_ordered (c_parser *, enum pragma_context);
+static bool c_parser_omp_ordered (c_parser *, enum pragma_context, bool *);
static void c_parser_oacc_routine (c_parser *parser, enum pragma_context);
/* These Objective-C parser functions are only ever called when
@@ -1390,12 +1390,12 @@ static bool c_parser_objc_diagnose_bad_element_prefix
(c_parser *, struct c_declspecs *);
/* Cilk Plus supporting routines. */
-static void c_parser_cilk_simd (c_parser *);
-static void c_parser_cilk_for (c_parser *, tree);
+static void c_parser_cilk_simd (c_parser *, bool *);
+static void c_parser_cilk_for (c_parser *, tree, bool *);
static bool c_parser_cilk_verify_simd (c_parser *, enum pragma_context);
static tree c_parser_array_notation (location_t, c_parser *, tree, tree);
static tree c_parser_cilk_clause_vectorlength (c_parser *, tree, bool);
-static void c_parser_cilk_grainsize (c_parser *);
+static void c_parser_cilk_grainsize (c_parser *, bool *);
/* Parse a translation unit (C90 6.7, C99 6.9).
@@ -1527,7 +1527,7 @@ c_parser_external_declaration (c_parser *parser)
break;
case CPP_PRAGMA:
mark_valid_location_for_stdc_pragma (true);
- c_parser_pragma (parser, pragma_external);
+ c_parser_pragma (parser, pragma_external, NULL);
mark_valid_location_for_stdc_pragma (false);
break;
case CPP_PLUS:
@@ -2927,7 +2927,7 @@ c_parser_struct_or_union_specifier (c_parser *parser)
/* Accept #pragmas at struct scope. */
if (c_parser_next_token_is (parser, CPP_PRAGMA))
{
- c_parser_pragma (parser, pragma_struct);
+ c_parser_pragma (parser, pragma_struct, NULL);
continue;
}
/* Parse some comma-separated declarations, but not the
@@ -3796,7 +3796,7 @@ c_parser_parameter_declaration (c_parser *parser, tree attrs)
/* Accept #pragmas between parameter declarations. */
while (c_parser_next_token_is (parser, CPP_PRAGMA))
- c_parser_pragma (parser, pragma_param);
+ c_parser_pragma (parser, pragma_param, NULL);
if (!c_parser_next_token_starts_declspecs (parser))
{
@@ -4824,7 +4824,8 @@ c_parser_compound_statement_nostart (c_parser *parser)
places that would turn into syntax errors if the directive
were ignored. */
if (c_parser_pragma (parser,
- last_label ? pragma_stmt : pragma_compound))
+ last_label ? pragma_stmt : pragma_compound,
+ NULL))
last_label = false, last_stmt = true;
}
else if (c_parser_next_token_is (parser, CPP_EOF))
@@ -5156,7 +5157,7 @@ c_parser_statement_after_labels (c_parser *parser, bool *if_p,
c_parser_skip_to_end_of_block_or_statement (parser);
}
else
- c_parser_cilk_for (parser, integer_zero_node);
+ c_parser_cilk_for (parser, integer_zero_node, if_p);
break;
case RID_CILK_SYNC:
c_parser_consume_token (parser);
@@ -5276,7 +5277,7 @@ c_parser_statement_after_labels (c_parser *parser, bool *if_p,
c_parser_consume_token (parser);
break;
case CPP_PRAGMA:
- c_parser_pragma (parser, pragma_stmt);
+ c_parser_pragma (parser, pragma_stmt, if_p);
break;
default:
expr_stmt:
@@ -8787,7 +8788,7 @@ c_parser_objc_class_instance_variables (c_parser *parser)
}
else if (c_parser_next_token_is (parser, CPP_PRAGMA))
{
- c_parser_pragma (parser, pragma_external);
+ c_parser_pragma (parser, pragma_external, NULL);
continue;
}
@@ -9058,7 +9059,7 @@ c_parser_objc_methodprotolist (c_parser *parser)
c_parser_objc_methodproto (parser);
break;
case CPP_PRAGMA:
- c_parser_pragma (parser, pragma_external);
+ c_parser_pragma (parser, pragma_external, NULL);
break;
case CPP_EOF:
return;
@@ -10019,7 +10020,7 @@ c_parser_objc_at_dynamic_declaration (c_parser *parser)
true if we actually parsed such a pragma. */
static bool
-c_parser_pragma (c_parser *parser, enum pragma_context context)
+c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p)
{
unsigned int id;
@@ -10126,7 +10127,7 @@ c_parser_pragma (c_parser *parser, enum pragma_context context)
return false;
case PRAGMA_OMP_TARGET:
- return c_parser_omp_target (parser, context);
+ return c_parser_omp_target (parser, context, if_p);
case PRAGMA_OMP_END_DECLARE_TARGET:
c_parser_omp_end_declare_target (parser);
@@ -10144,7 +10145,7 @@ c_parser_pragma (c_parser *parser, enum pragma_context context)
return false;
case PRAGMA_OMP_ORDERED:
- return c_parser_omp_ordered (parser, context);
+ return c_parser_omp_ordered (parser, context, if_p);
case PRAGMA_IVDEP:
c_parser_consume_pragma (parser);
@@ -10157,9 +10158,9 @@ c_parser_pragma (c_parser *parser, enum pragma_context context)
return false;
}
if (c_parser_next_token_is_keyword (parser, RID_FOR))
- c_parser_for_statement (parser, true, NULL);
+ c_parser_for_statement (parser, true, if_p);
else if (c_parser_next_token_is_keyword (parser, RID_WHILE))
- c_parser_while_statement (parser, true, NULL);
+ c_parser_while_statement (parser, true, if_p);
else
c_parser_do_statement (parser, true);
return false;
@@ -10173,7 +10174,7 @@ c_parser_pragma (c_parser *parser, enum pragma_context context)
if (!c_parser_cilk_verify_simd (parser, context))
return false;
c_parser_consume_pragma (parser);
- c_parser_cilk_simd (parser);
+ c_parser_cilk_simd (parser, if_p);
return false;
case PRAGMA_CILK_GRAINSIZE:
if (!flag_cilkplus)
@@ -10190,7 +10191,7 @@ c_parser_pragma (c_parser *parser, enum pragma_context context)
c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
return false;
}
- c_parser_cilk_grainsize (parser);
+ c_parser_cilk_grainsize (parser, if_p);
return false;
default:
@@ -10203,7 +10204,7 @@ c_parser_pragma (c_parser *parser, enum pragma_context context)
c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
return false;
}
- c_parser_omp_construct (parser);
+ c_parser_omp_construct (parser, if_p);
return true;
}
break;
@@ -13477,10 +13478,10 @@ c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask,
c_parser_statement calls add_stmt. */
static tree
-c_parser_omp_structured_block (c_parser *parser)
+c_parser_omp_structured_block (c_parser *parser, bool *if_p)
{
tree stmt = push_stmt_list ();
- c_parser_statement (parser, NULL);
+ c_parser_statement (parser, if_p);
return pop_stmt_list (stmt);
}
@@ -13530,7 +13531,7 @@ c_parser_oacc_cache (location_t loc, c_parser *parser)
| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_CREATE) )
static tree
-c_parser_oacc_data (location_t loc, c_parser *parser)
+c_parser_oacc_data (location_t loc, c_parser *parser, bool *if_p)
{
tree stmt, clauses, block;
@@ -13538,7 +13539,7 @@ c_parser_oacc_data (location_t loc, c_parser *parser)
"#pragma acc data");
block = c_begin_omp_parallel ();
- add_stmt (c_parser_omp_structured_block (parser));
+ add_stmt (c_parser_omp_structured_block (parser, if_p));
stmt = c_finish_oacc_data (loc, clauses, block);
@@ -13784,7 +13785,7 @@ c_parser_oacc_enter_exit_data (c_parser *parser, bool enter)
( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_USE_DEVICE) )
static tree
-c_parser_oacc_host_data (location_t loc, c_parser *parser)
+c_parser_oacc_host_data (location_t loc, c_parser *parser, bool *if_p)
{
tree stmt, clauses, block;
@@ -13792,7 +13793,7 @@ c_parser_oacc_host_data (location_t loc, c_parser *parser)
"#pragma acc host_data");
block = c_begin_omp_parallel ();
- add_stmt (c_parser_omp_structured_block (parser));
+ add_stmt (c_parser_omp_structured_block (parser, if_p));
stmt = c_finish_oacc_host_data (loc, clauses, block);
return stmt;
}
@@ -13819,7 +13820,7 @@ c_parser_oacc_host_data (location_t loc, c_parser *parser)
| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_TILE) )
static tree
c_parser_oacc_loop (location_t loc, c_parser *parser, char *p_name,
- omp_clause_mask mask, tree *cclauses)
+ omp_clause_mask mask, tree *cclauses, bool *if_p)
{
strcat (p_name, " loop");
mask |= OACC_LOOP_CLAUSE_MASK;
@@ -13836,7 +13837,8 @@ c_parser_oacc_loop (location_t loc, c_parser *parser, char *p_name,
}
tree block = c_begin_compound_stmt (true);
- tree stmt = c_parser_omp_for_loop (loc, parser, OACC_LOOP, clauses, NULL);
+ tree stmt = c_parser_omp_for_loop (loc, parser, OACC_LOOP, clauses, NULL,
+ if_p);
block = c_end_compound_stmt (loc, block, true);
add_stmt (block);
@@ -13895,7 +13897,8 @@ c_parser_oacc_loop (location_t loc, c_parser *parser, char *p_name,
static tree
c_parser_oacc_kernels_parallel (location_t loc, c_parser *parser,
- enum pragma_kind p_kind, char *p_name)
+ enum pragma_kind p_kind, char *p_name,
+ bool *if_p)
{
omp_clause_mask mask;
enum tree_code code;
@@ -13925,7 +13928,7 @@ c_parser_oacc_kernels_parallel (location_t loc, c_parser *parser,
tree block = c_begin_omp_parallel ();
tree clauses;
- c_parser_oacc_loop (loc, parser, p_name, mask, &clauses);
+ c_parser_oacc_loop (loc, parser, p_name, mask, &clauses, if_p);
return c_finish_omp_construct (loc, code, block, clauses);
}
}
@@ -13933,7 +13936,7 @@ c_parser_oacc_kernels_parallel (location_t loc, c_parser *parser,
tree clauses = c_parser_oacc_all_clauses (parser, mask, p_name);
tree block = c_begin_omp_parallel ();
- add_stmt (c_parser_omp_structured_block (parser));
+ add_stmt (c_parser_omp_structured_block (parser, if_p));
return c_finish_omp_construct (loc, code, block, clauses);
}
@@ -14576,7 +14579,7 @@ c_parser_omp_barrier (c_parser *parser)
( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_HINT) )
static tree
-c_parser_omp_critical (location_t loc, c_parser *parser)
+c_parser_omp_critical (location_t loc, c_parser *parser, bool *if_p)
{
tree stmt, name = NULL_TREE, clauses = NULL_TREE;
@@ -14603,7 +14606,7 @@ c_parser_omp_critical (location_t loc, c_parser *parser)
c_parser_skip_to_pragma_eol (parser);
}
- stmt = c_parser_omp_structured_block (parser);
+ stmt = c_parser_omp_structured_block (parser, if_p);
return c_finish_omp_critical (loc, stmt, name, clauses);
}
@@ -14635,7 +14638,7 @@ c_parser_omp_flush (c_parser *parser)
static tree
c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
- tree clauses, tree *cclauses)
+ tree clauses, tree *cclauses, bool *if_p)
{
tree decl, cond, incr, save_break, save_cont, body, init, stmt, cl;
tree declv, condv, incrv, initv, ret = NULL_TREE;
@@ -14865,6 +14868,9 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
nbraces += bracecount;
}
+ if (nbraces)
+ if_p = NULL;
+
save_break = c_break_label;
if (code == CILK_SIMD)
c_break_label = build_int_cst (size_type_node, 2);
@@ -14882,7 +14888,7 @@ c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
add_stmt (c_end_compound_stmt (here, stmt, true));
}
else
- add_stmt (c_parser_c99_block_statement (parser, NULL));
+ add_stmt (c_parser_c99_block_statement (parser, if_p));
if (c_cont_label)
{
tree t = build1 (LABEL_EXPR, void_type_node, c_cont_label);
@@ -15025,7 +15031,8 @@ omp_split_clauses (location_t loc, enum tree_code code,
static tree
c_parser_omp_simd (location_t loc, c_parser *parser,
- char *p_name, omp_clause_mask mask, tree *cclauses)
+ char *p_name, omp_clause_mask mask, tree *cclauses,
+ bool *if_p)
{
tree block, clauses, ret;
@@ -15049,7 +15056,7 @@ c_parser_omp_simd (location_t loc, c_parser *parser,
}
block = c_begin_compound_stmt (true);
- ret = c_parser_omp_for_loop (loc, parser, OMP_SIMD, clauses, cclauses);
+ ret = c_parser_omp_for_loop (loc, parser, OMP_SIMD, clauses, cclauses, if_p);
block = c_end_compound_stmt (loc, block, true);
add_stmt (block);
@@ -15080,7 +15087,8 @@ c_parser_omp_simd (location_t loc, c_parser *parser,
static tree
c_parser_omp_for (location_t loc, c_parser *parser,
- char *p_name, omp_clause_mask mask, tree *cclauses)
+ char *p_name, omp_clause_mask mask, tree *cclauses,
+ bool *if_p)
{
tree block, clauses, ret;
@@ -15104,9 +15112,10 @@ c_parser_omp_for (location_t loc, c_parser *parser,
c_parser_consume_token (parser);
if (!flag_openmp) /* flag_openmp_simd */
- return c_parser_omp_simd (loc, parser, p_name, mask, cclauses);
+ return c_parser_omp_simd (loc, parser, p_name, mask, cclauses,
+ if_p);
block = c_begin_compound_stmt (true);
- ret = c_parser_omp_simd (loc, parser, p_name, mask, cclauses);
+ ret = c_parser_omp_simd (loc, parser, p_name, mask, cclauses, if_p);
block = c_end_compound_stmt (loc, block, true);
if (ret == NULL_TREE)
return ret;
@@ -15137,7 +15146,7 @@ c_parser_omp_for (location_t loc, c_parser *parser,
}
block = c_begin_compound_stmt (true);
- ret = c_parser_omp_for_loop (loc, parser, OMP_FOR, clauses, cclauses);
+ ret = c_parser_omp_for_loop (loc, parser, OMP_FOR, clauses, cclauses, if_p);
block = c_end_compound_stmt (loc, block, true);
add_stmt (block);
@@ -15152,10 +15161,11 @@ c_parser_omp_for (location_t loc, c_parser *parser,
*/
static tree
-c_parser_omp_master (location_t loc, c_parser *parser)
+c_parser_omp_master (location_t loc, c_parser *parser, bool *if_p)
{
c_parser_skip_to_pragma_eol (parser);
- return c_finish_omp_master (loc, c_parser_omp_structured_block (parser));
+ return c_finish_omp_master (loc, c_parser_omp_structured_block (parser,
+ if_p));
}
/* OpenMP 2.5:
@@ -15176,7 +15186,8 @@ c_parser_omp_master (location_t loc, c_parser *parser)
(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND)
static bool
-c_parser_omp_ordered (c_parser *parser, enum pragma_context context)
+c_parser_omp_ordered (c_parser *parser, enum pragma_context context,
+ bool *if_p)
{
location_t loc = c_parser_peek_token (parser)->location;
c_parser_consume_pragma (parser);
@@ -15215,7 +15226,7 @@ c_parser_omp_ordered (c_parser *parser, enum pragma_context context)
tree clauses = c_parser_omp_all_clauses (parser, OMP_ORDERED_CLAUSE_MASK,
"#pragma omp ordered");
c_finish_omp_ordered (loc, clauses,
- c_parser_omp_structured_block (parser));
+ c_parser_omp_structured_block (parser, if_p));
return true;
}
@@ -15249,7 +15260,7 @@ c_parser_omp_sections_scope (location_t sections_loc, c_parser *parser)
if (c_parser_peek_token (parser)->pragma_kind != PRAGMA_OMP_SECTION)
{
- substmt = c_parser_omp_structured_block (parser);
+ substmt = c_parser_omp_structured_block (parser, NULL);
substmt = build1 (OMP_SECTION, void_type_node, substmt);
SET_EXPR_LOCATION (substmt, loc);
add_stmt (substmt);
@@ -15275,7 +15286,7 @@ c_parser_omp_sections_scope (location_t sections_loc, c_parser *parser)
error_suppress = true;
}
- substmt = c_parser_omp_structured_block (parser);
+ substmt = c_parser_omp_structured_block (parser, NULL);
substmt = build1 (OMP_SECTION, void_type_node, substmt);
SET_EXPR_LOCATION (substmt, loc);
add_stmt (substmt);
@@ -15363,7 +15374,8 @@ c_parser_omp_sections (location_t loc, c_parser *parser,
static tree
c_parser_omp_parallel (location_t loc, c_parser *parser,
- char *p_name, omp_clause_mask mask, tree *cclauses)
+ char *p_name, omp_clause_mask mask, tree *cclauses,
+ bool *if_p)
{
tree stmt, clauses, block;
@@ -15382,9 +15394,9 @@ c_parser_omp_parallel (location_t loc, c_parser *parser,
c_parser_consume_token (parser);
if (!flag_openmp) /* flag_openmp_simd */
- return c_parser_omp_for (loc, parser, p_name, mask, cclauses);
+ return c_parser_omp_for (loc, parser, p_name, mask, cclauses, if_p);
block = c_begin_omp_parallel ();
- tree ret = c_parser_omp_for (loc, parser, p_name, mask, cclauses);
+ tree ret = c_parser_omp_for (loc, parser, p_name, mask, cclauses, if_p);
stmt
= c_finish_omp_parallel (loc, cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
block);
@@ -15436,7 +15448,7 @@ c_parser_omp_parallel (location_t loc, c_parser *parser,
}
block = c_begin_omp_parallel ();
- c_parser_statement (parser, NULL);
+ c_parser_statement (parser, if_p);
stmt = c_finish_omp_parallel (loc, clauses, block);
return stmt;
@@ -15456,7 +15468,7 @@ c_parser_omp_parallel (location_t loc, c_parser *parser,
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
static tree
-c_parser_omp_single (location_t loc, c_parser *parser)
+c_parser_omp_single (location_t loc, c_parser *parser, bool *if_p)
{
tree stmt = make_node (OMP_SINGLE);
SET_EXPR_LOCATION (stmt, loc);
@@ -15465,7 +15477,7 @@ c_parser_omp_single (location_t loc, c_parser *parser)
OMP_SINGLE_CLAUSES (stmt)
= c_parser_omp_all_clauses (parser, OMP_SINGLE_CLAUSE_MASK,
"#pragma omp single");
- OMP_SINGLE_BODY (stmt) = c_parser_omp_structured_block (parser);
+ OMP_SINGLE_BODY (stmt) = c_parser_omp_structured_block (parser, if_p);
return add_stmt (stmt);
}
@@ -15489,7 +15501,7 @@ c_parser_omp_single (location_t loc, c_parser *parser)
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY))
static tree
-c_parser_omp_task (location_t loc, c_parser *parser)
+c_parser_omp_task (location_t loc, c_parser *parser, bool *if_p)
{
tree clauses, block;
@@ -15497,7 +15509,7 @@ c_parser_omp_task (location_t loc, c_parser *parser)
"#pragma omp task");
block = c_begin_omp_task ();
- c_parser_statement (parser, NULL);
+ c_parser_statement (parser, if_p);
return c_finish_omp_task (loc, clauses, block);
}
@@ -15534,11 +15546,12 @@ c_parser_omp_taskyield (c_parser *parser)
*/
static tree
-c_parser_omp_taskgroup (c_parser *parser)
+c_parser_omp_taskgroup (c_parser *parser, bool *if_p)
{
location_t loc = c_parser_peek_token (parser)->location;
c_parser_skip_to_pragma_eol (parser);
- return c_finish_omp_taskgroup (loc, c_parser_omp_structured_block (parser));
+ return c_finish_omp_taskgroup (loc, c_parser_omp_structured_block (parser,
+ if_p));
}
/* OpenMP 4.0:
@@ -15622,7 +15635,8 @@ c_parser_omp_cancellation_point (c_parser *parser)
static tree
c_parser_omp_distribute (location_t loc, c_parser *parser,
- char *p_name, omp_clause_mask mask, tree *cclauses)
+ char *p_name, omp_clause_mask mask, tree *cclauses,
+ bool *if_p)
{
tree clauses, block, ret;
@@ -15648,16 +15662,19 @@ c_parser_omp_distribute (location_t loc, c_parser *parser,
if (!flag_openmp) /* flag_openmp_simd */
{
if (simd)
- return c_parser_omp_simd (loc, parser, p_name, mask, cclauses);
+ return c_parser_omp_simd (loc, parser, p_name, mask, cclauses,
+ if_p);
else
return c_parser_omp_parallel (loc, parser, p_name, mask,
- cclauses);
+ cclauses, if_p);
}
block = c_begin_compound_stmt (true);
if (simd)
- ret = c_parser_omp_simd (loc, parser, p_name, mask, cclauses);
+ ret = c_parser_omp_simd (loc, parser, p_name, mask, cclauses,
+ if_p);
else
- ret = c_parser_omp_parallel (loc, parser, p_name, mask, cclauses);
+ ret = c_parser_omp_parallel (loc, parser, p_name, mask, cclauses,
+ if_p);
block = c_end_compound_stmt (loc, block, true);
if (ret == NULL)
return ret;
@@ -15684,7 +15701,8 @@ c_parser_omp_distribute (location_t loc, c_parser *parser,
}
block = c_begin_compound_stmt (true);
- ret = c_parser_omp_for_loop (loc, parser, OMP_DISTRIBUTE, clauses, NULL);
+ ret = c_parser_omp_for_loop (loc, parser, OMP_DISTRIBUTE, clauses, NULL,
+ if_p);
block = c_end_compound_stmt (loc, block, true);
add_stmt (block);
@@ -15706,7 +15724,8 @@ c_parser_omp_distribute (location_t loc, c_parser *parser,
static tree
c_parser_omp_teams (location_t loc, c_parser *parser,
- char *p_name, omp_clause_mask mask, tree *cclauses)
+ char *p_name, omp_clause_mask mask, tree *cclauses,
+ bool *if_p)
{
tree clauses, block, ret;
@@ -15724,9 +15743,11 @@ c_parser_omp_teams (location_t loc, c_parser *parser,
c_parser_consume_token (parser);
if (!flag_openmp) /* flag_openmp_simd */
- return c_parser_omp_distribute (loc, parser, p_name, mask, cclauses);
+ return c_parser_omp_distribute (loc, parser, p_name, mask,
+ cclauses, if_p);
block = c_begin_compound_stmt (true);
- ret = c_parser_omp_distribute (loc, parser, p_name, mask, cclauses);
+ ret = c_parser_omp_distribute (loc, parser, p_name, mask, cclauses,
+ if_p);
block = c_end_compound_stmt (loc, block, true);
if (ret == NULL)
return ret;
@@ -15755,7 +15776,7 @@ c_parser_omp_teams (location_t loc, c_parser *parser,
tree stmt = make_node (OMP_TEAMS);
TREE_TYPE (stmt) = void_type_node;
OMP_TEAMS_CLAUSES (stmt) = clauses;
- OMP_TEAMS_BODY (stmt) = c_parser_omp_structured_block (parser);
+ OMP_TEAMS_BODY (stmt) = c_parser_omp_structured_block (parser, if_p);
return add_stmt (stmt);
}
@@ -15771,7 +15792,7 @@ c_parser_omp_teams (location_t loc, c_parser *parser,
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR))
static tree
-c_parser_omp_target_data (location_t loc, c_parser *parser)
+c_parser_omp_target_data (location_t loc, c_parser *parser, bool *if_p)
{
tree clauses
= c_parser_omp_all_clauses (parser, OMP_TARGET_DATA_CLAUSE_MASK,
@@ -15820,7 +15841,7 @@ c_parser_omp_target_data (location_t loc, c_parser *parser)
OMP_TARGET_DATA_CLAUSES (stmt) = clauses;
keep_next_level ();
tree block = c_begin_compound_stmt (true);
- add_stmt (c_parser_omp_structured_block (parser));
+ add_stmt (c_parser_omp_structured_block (parser, if_p));
OMP_TARGET_DATA_BODY (stmt) = c_end_compound_stmt (loc, block, true);
SET_EXPR_LOCATION (stmt, loc);
@@ -16060,7 +16081,7 @@ c_parser_omp_target_exit_data (location_t loc, c_parser *parser,
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR))
static bool
-c_parser_omp_target (c_parser *parser, enum pragma_context context)
+c_parser_omp_target (c_parser *parser, enum pragma_context context, bool *if_p)
{
location_t loc = c_parser_peek_token (parser)->location;
c_parser_consume_pragma (parser);
@@ -16100,17 +16121,17 @@ c_parser_omp_target (c_parser *parser, enum pragma_context context)
case OMP_TEAMS:
stmt = c_parser_omp_teams (loc, parser, p_name,
OMP_TARGET_CLAUSE_MASK,
- cclauses);
+ cclauses, if_p);
break;
case OMP_PARALLEL:
stmt = c_parser_omp_parallel (loc, parser, p_name,
OMP_TARGET_CLAUSE_MASK,
- cclauses);
+ cclauses, if_p);
break;
case OMP_SIMD:
stmt = c_parser_omp_simd (loc, parser, p_name,
OMP_TARGET_CLAUSE_MASK,
- cclauses);
+ cclauses, if_p);
break;
default:
gcc_unreachable ();
@@ -16123,15 +16144,18 @@ c_parser_omp_target (c_parser *parser, enum pragma_context context)
{
case OMP_TEAMS:
ret = c_parser_omp_teams (loc, parser, p_name,
- OMP_TARGET_CLAUSE_MASK, cclauses);
+ OMP_TARGET_CLAUSE_MASK, cclauses,
+ if_p);
break;
case OMP_PARALLEL:
ret = c_parser_omp_parallel (loc, parser, p_name,
- OMP_TARGET_CLAUSE_MASK, cclauses);
+ OMP_TARGET_CLAUSE_MASK, cclauses,
+ if_p);
break;
case OMP_SIMD:
ret = c_parser_omp_simd (loc, parser, p_name,
- OMP_TARGET_CLAUSE_MASK, cclauses);
+ OMP_TARGET_CLAUSE_MASK, cclauses,
+ if_p);
break;
default:
gcc_unreachable ();
@@ -16182,7 +16206,7 @@ c_parser_omp_target (c_parser *parser, enum pragma_context context)
else if (strcmp (p, "data") == 0)
{
c_parser_consume_token (parser);
- c_parser_omp_target_data (loc, parser);
+ c_parser_omp_target_data (loc, parser, if_p);
return true;
}
else if (strcmp (p, "enter") == 0)
@@ -16213,7 +16237,7 @@ c_parser_omp_target (c_parser *parser, enum pragma_context context)
pc = &OMP_TARGET_CLAUSES (stmt);
keep_next_level ();
block = c_begin_compound_stmt (true);
- add_stmt (c_parser_omp_structured_block (parser));
+ add_stmt (c_parser_omp_structured_block (parser, if_p));
OMP_TARGET_BODY (stmt) = c_end_compound_stmt (loc, block, true);
SET_EXPR_LOCATION (stmt, loc);
@@ -17022,7 +17046,8 @@ c_parser_omp_declare (c_parser *parser, enum pragma_context context)
static tree
c_parser_omp_taskloop (location_t loc, c_parser *parser,
- char *p_name, omp_clause_mask mask, tree *cclauses)
+ char *p_name, omp_clause_mask mask, tree *cclauses,
+ bool *if_p)
{
tree clauses, block, ret;
@@ -17041,9 +17066,10 @@ c_parser_omp_taskloop (location_t loc, c_parser *parser,
mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION);
c_parser_consume_token (parser);
if (!flag_openmp) /* flag_openmp_simd */
- return c_parser_omp_simd (loc, parser, p_name, mask, cclauses);
+ return c_parser_omp_simd (loc, parser, p_name, mask, cclauses,
+ if_p);
block = c_begin_compound_stmt (true);
- ret = c_parser_omp_simd (loc, parser, p_name, mask, cclauses);
+ ret = c_parser_omp_simd (loc, parser, p_name, mask, cclauses, if_p);
block = c_end_compound_stmt (loc, block, true);
if (ret == NULL)
return ret;
@@ -17070,7 +17096,7 @@ c_parser_omp_taskloop (location_t loc, c_parser *parser,
}
block = c_begin_compound_stmt (true);
- ret = c_parser_omp_for_loop (loc, parser, OMP_TASKLOOP, clauses, NULL);
+ ret = c_parser_omp_for_loop (loc, parser, OMP_TASKLOOP, clauses, NULL, if_p);
block = c_end_compound_stmt (loc, block, true);
add_stmt (block);
@@ -17080,7 +17106,7 @@ c_parser_omp_taskloop (location_t loc, c_parser *parser,
/* Main entry point to parsing most OpenMP pragmas. */
static void
-c_parser_omp_construct (c_parser *parser)
+c_parser_omp_construct (c_parser *parser, bool *if_p)
{
enum pragma_kind p_kind;
location_t loc;
@@ -17102,19 +17128,20 @@ c_parser_omp_construct (c_parser *parser)
stmt = c_parser_oacc_cache (loc, parser);
break;
case PRAGMA_OACC_DATA:
- stmt = c_parser_oacc_data (loc, parser);
+ stmt = c_parser_oacc_data (loc, parser, if_p);
break;
case PRAGMA_OACC_HOST_DATA:
- stmt = c_parser_oacc_host_data (loc, parser);
+ stmt = c_parser_oacc_host_data (loc, parser, if_p);
break;
case PRAGMA_OACC_KERNELS:
case PRAGMA_OACC_PARALLEL:
strcpy (p_name, "#pragma acc");
- stmt = c_parser_oacc_kernels_parallel (loc, parser, p_kind, p_name);
+ stmt = c_parser_oacc_kernels_parallel (loc, parser, p_kind, p_name,
+ if_p);
break;
case PRAGMA_OACC_LOOP:
strcpy (p_name, "#pragma acc");
- stmt = c_parser_oacc_loop (loc, parser, p_name, mask, NULL);
+ stmt = c_parser_oacc_loop (loc, parser, p_name, mask, NULL, if_p);
break;
case PRAGMA_OACC_WAIT:
strcpy (p_name, "#pragma wait");
@@ -17124,22 +17151,22 @@ c_parser_omp_construct (c_parser *parser)
c_parser_omp_atomic (loc, parser);
return;
case PRAGMA_OMP_CRITICAL:
- stmt = c_parser_omp_critical (loc, parser);
+ stmt = c_parser_omp_critical (loc, parser, if_p);
break;
case PRAGMA_OMP_DISTRIBUTE:
strcpy (p_name, "#pragma omp");
- stmt = c_parser_omp_distribute (loc, parser, p_name, mask, NULL);
+ stmt = c_parser_omp_distribute (loc, parser, p_name, mask, NULL, if_p);
break;
case PRAGMA_OMP_FOR:
strcpy (p_name, "#pragma omp");
- stmt = c_parser_omp_for (loc, parser, p_name, mask, NULL);
+ stmt = c_parser_omp_for (loc, parser, p_name, mask, NULL, if_p);
break;
case PRAGMA_OMP_MASTER:
- stmt = c_parser_omp_master (loc, parser);
+ stmt = c_parser_omp_master (loc, parser, if_p);
break;
case PRAGMA_OMP_PARALLEL:
strcpy (p_name, "#pragma omp");
- stmt = c_parser_omp_parallel (loc, parser, p_name, mask, NULL);
+ stmt = c_parser_omp_parallel (loc, parser, p_name, mask, NULL, if_p);
break;
case PRAGMA_OMP_SECTIONS:
strcpy (p_name, "#pragma omp");
@@ -17147,24 +17174,24 @@ c_parser_omp_construct (c_parser *parser)
break;
case PRAGMA_OMP_SIMD:
strcpy (p_name, "#pragma omp");
- stmt = c_parser_omp_simd (loc, parser, p_name, mask, NULL);
+ stmt = c_parser_omp_simd (loc, parser, p_name, mask, NULL, if_p);
break;
case PRAGMA_OMP_SINGLE:
- stmt = c_parser_omp_single (loc, parser);
+ stmt = c_parser_omp_single (loc, parser, if_p);
break;
case PRAGMA_OMP_TASK:
- stmt = c_parser_omp_task (loc, parser);
+ stmt = c_parser_omp_task (loc, parser, if_p);
break;
case PRAGMA_OMP_TASKGROUP:
- stmt = c_parser_omp_taskgroup (parser);
+ stmt = c_parser_omp_taskgroup (parser, if_p);
break;
case PRAGMA_OMP_TASKLOOP:
strcpy (p_name, "#pragma omp");
- stmt = c_parser_omp_taskloop (loc, parser, p_name, mask, NULL);
+ stmt = c_parser_omp_taskloop (loc, parser, p_name, mask, NULL, if_p);
break;
case PRAGMA_OMP_TEAMS:
strcpy (p_name, "#pragma omp");
- stmt = c_parser_omp_teams (loc, parser, p_name, mask, NULL);
+ stmt = c_parser_omp_teams (loc, parser, p_name, mask, NULL, if_p);
break;
default:
gcc_unreachable ();
@@ -17491,7 +17518,7 @@ c_parser_cilk_all_clauses (c_parser *parser)
*/
static void
-c_parser_cilk_grainsize (c_parser *parser)
+c_parser_cilk_grainsize (c_parser *parser, bool *if_p)
{
extern tree convert_to_integer (tree, tree);
@@ -17516,7 +17543,7 @@ c_parser_cilk_grainsize (c_parser *parser)
{
if (grain == NULL_TREE || grain == error_mark_node)
grain = integer_zero_node;
- c_parser_cilk_for (parser, grain);
+ c_parser_cilk_for (parser, grain, if_p);
}
else
warning (0, "%<#pragma cilk grainsize%> is not followed by "
@@ -17529,12 +17556,12 @@ c_parser_cilk_grainsize (c_parser *parser)
/* Main entry point for parsing Cilk Plus <#pragma simd> for loops. */
static void
-c_parser_cilk_simd (c_parser *parser)
+c_parser_cilk_simd (c_parser *parser, bool *if_p)
{
tree clauses = c_parser_cilk_all_clauses (parser);
tree block = c_begin_compound_stmt (true);
location_t loc = c_parser_peek_token (parser)->location;
- c_parser_omp_for_loop (loc, parser, CILK_SIMD, clauses, NULL);
+ c_parser_omp_for_loop (loc, parser, CILK_SIMD, clauses, NULL, if_p);
block = c_end_compound_stmt (loc, block, true);
add_stmt (block);
}
@@ -17559,7 +17586,7 @@ c_get_temp_regvar (tree type, tree init)
GRAIN is the grain value passed in through pragma or 0. */
static void
-c_parser_cilk_for (c_parser *parser, tree grain)
+c_parser_cilk_for (c_parser *parser, tree grain, bool *if_p)
{
tree clauses = build_omp_clause (EXPR_LOCATION (grain), OMP_CLAUSE_SCHEDULE);
OMP_CLAUSE_SCHEDULE_KIND (clauses) = OMP_CLAUSE_SCHEDULE_CILKFOR;
@@ -17569,7 +17596,8 @@ c_parser_cilk_for (c_parser *parser, tree grain)
tree block = c_begin_compound_stmt (true);
tree sb = push_stmt_list ();
location_t loc = c_parser_peek_token (parser)->location;
- tree omp_for = c_parser_omp_for_loop (loc, parser, CILK_FOR, clauses, NULL);
+ tree omp_for = c_parser_omp_for_loop (loc, parser, CILK_FOR, clauses, NULL,
+ if_p);
sb = pop_stmt_list (sb);
if (omp_for)
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 9a1499428d4..59a3c6153b7 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -4436,8 +4436,8 @@ build_unary_op (location_t location,
case COMPONENT_REF:
if (DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1)))
{
- error ("cannot take address of bit-field %qD",
- TREE_OPERAND (arg, 1));
+ error_at (location, "cannot take address of bit-field %qD",
+ TREE_OPERAND (arg, 1));
return error_mark_node;
}
@@ -4449,15 +4449,16 @@ build_unary_op (location_t location,
if (!AGGREGATE_TYPE_P (TREE_TYPE (arg))
&& !VECTOR_TYPE_P (TREE_TYPE (arg)))
{
- error ("cannot take address of scalar with reverse storage "
- "order");
+ error_at (location, "cannot take address of scalar with "
+ "reverse storage order");
return error_mark_node;
}
if (TREE_CODE (TREE_TYPE (arg)) == ARRAY_TYPE
&& TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (arg)))
- warning (OPT_Wscalar_storage_order, "address of array with "
- "reverse scalar storage order requested");
+ warning_at (location, OPT_Wscalar_storage_order,
+ "address of array with reverse scalar storage "
+ "order requested");
}
default:
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index e4652f37ea6..ff47bc15600 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -44,6 +44,8 @@ extern bool ix86_use_pseudo_pic_reg (void);
extern void ix86_reset_previous_fndecl (void);
+extern bool ix86_using_red_zone (void);
+
#ifdef RTX_CODE
extern int standard_80387_constant_p (rtx);
extern const char *standard_80387_constant_opcode (rtx);
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 1fa007efdc3..3d044e8bd68 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -3709,7 +3709,7 @@ make_pass_stv (gcc::context *ctxt)
/* Return true if a red-zone is in use. */
-static inline bool
+bool
ix86_using_red_zone (void)
{
return TARGET_RED_ZONE && !TARGET_64BIT_MS_ABI;
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 56a30502d41..cf29e5d39d5 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -18240,7 +18240,8 @@
(clobber (reg:CC FLAGS_REG))
(clobber (mem:BLK (scratch)))])]
"(TARGET_SINGLE_PUSH || optimize_insn_for_size_p ())
- && INTVAL (operands[0]) == -GET_MODE_SIZE (word_mode)"
+ && INTVAL (operands[0]) == -GET_MODE_SIZE (word_mode)
+ && !ix86_using_red_zone ()"
[(clobber (match_dup 1))
(parallel [(set (mem:W (pre_dec:P (reg:P SP_REG))) (match_dup 1))
(clobber (mem:BLK (scratch)))])])
@@ -18253,7 +18254,8 @@
(clobber (reg:CC FLAGS_REG))
(clobber (mem:BLK (scratch)))])]
"(TARGET_DOUBLE_PUSH || optimize_insn_for_size_p ())
- && INTVAL (operands[0]) == -2*GET_MODE_SIZE (word_mode)"
+ && INTVAL (operands[0]) == -2*GET_MODE_SIZE (word_mode)
+ && !ix86_using_red_zone ()"
[(clobber (match_dup 1))
(set (mem:W (pre_dec:P (reg:P SP_REG))) (match_dup 1))
(parallel [(set (mem:W (pre_dec:P (reg:P SP_REG))) (match_dup 1))
@@ -18267,7 +18269,8 @@
(match_operand:P 0 "const_int_operand")))
(clobber (reg:CC FLAGS_REG))])]
"(TARGET_SINGLE_PUSH || optimize_insn_for_size_p ())
- && INTVAL (operands[0]) == -GET_MODE_SIZE (word_mode)"
+ && INTVAL (operands[0]) == -GET_MODE_SIZE (word_mode)
+ && !ix86_using_red_zone ()"
[(clobber (match_dup 1))
(set (mem:W (pre_dec:P (reg:P SP_REG))) (match_dup 1))])
@@ -18278,7 +18281,8 @@
(match_operand:P 0 "const_int_operand")))
(clobber (reg:CC FLAGS_REG))])]
"(TARGET_DOUBLE_PUSH || optimize_insn_for_size_p ())
- && INTVAL (operands[0]) == -2*GET_MODE_SIZE (word_mode)"
+ && INTVAL (operands[0]) == -2*GET_MODE_SIZE (word_mode)
+ && !ix86_using_red_zone ()"
[(clobber (match_dup 1))
(set (mem:W (pre_dec:P (reg:P SP_REG))) (match_dup 1))
(set (mem:W (pre_dec:P (reg:P SP_REG))) (match_dup 1))])
diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index b64457edab0..4d2927e5c29 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -17262,9 +17262,12 @@
/* There is no DF broadcast (in AVX-512*) to 128b register.
Mimic it with integer variant. */
if (<MODE>mode == V2DFmode)
- return "vpbroadcastq\t{%1, %0<mask_operand2>|%0<mask_operand2>, %1}";
+ return "vpbroadcastq\t{%1, %0<mask_operand2>|%0<mask_operand2>, %q1}";
+
+ if (GET_MODE_SIZE (GET_MODE_INNER (<MODE>mode)) == 32)
+ return "v<sseintprefix>broadcast<bcstscalarsuff>\t{%1, %0<mask_operand2>|%0<mask_operand2>, %k1}";
else
- return "v<sseintprefix>broadcast<bcstscalarsuff>\t{%1, %0<mask_operand2>|%0<mask_operand2>, %1}";
+ return "v<sseintprefix>broadcast<bcstscalarsuff>\t{%1, %0<mask_operand2>|%0<mask_operand2>, %q1}";
}
[(set_attr "type" "ssemov")
(set_attr "prefix" "evex")
diff --git a/gcc/config/nvptx/nvptx.opt b/gcc/config/nvptx/nvptx.opt
index 056b9b2d003..601cf124e36 100644
--- a/gcc/config/nvptx/nvptx.opt
+++ b/gcc/config/nvptx/nvptx.opt
@@ -31,4 +31,4 @@ Link in code for a __main kernel.
moptimize
Target Report Var(nvptx_optimize) Init(-1)
-Optimize partition neutering
+Optimize partition neutering.
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 12900d3cd45..9d806847b13 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,27 @@
+2016-04-15 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/70436
+ * parser.c (cp_parser_pragma): Add IF_P argument, pass it down
+ where needed.
+ (cp_parser_declaration_seq_opt, cp_parser_member_specification_opt,
+ cp_parser_objc_interstitial_code, cp_parser_omp_declare_simd,
+ cp_parser_oacc_routine): Adjust cp_parser_pragma callers.
+ (cp_parser_statement): Likewise. Adjust cp_parser_cilk_for caller.
+ (cp_parser_omp_structured_block): Add IF_P argument, pass it down to
+ cp_parser_statement.
+ (cp_parser_oacc_data, cp_parser_oacc_host_data, cp_parser_oacc_loop,
+ cp_parser_oacc_kernels_parallel, cp_parser_omp_critical,
+ cp_parser_omp_simd, cp_parser_omp_for, cp_parser_omp_master,
+ cp_parser_omp_ordered, cp_parser_omp_parallel, cp_parser_omp_single,
+ cp_parser_omp_task, cp_parser_omp_taskgroup, cp_parser_omp_distribute,
+ cp_parser_omp_teams, cp_parser_omp_target_data, cp_parser_omp_target,
+ cp_parser_omp_taskloop, cp_parser_omp_construct,
+ cp_parser_cilk_grainsize, cp_parser_cilk_simd, cp_parser_cilk_for):
+ Add IF_P argument, pass it down where needed.
+ (cp_parser_omp_for_loop): Likewise. Clear IF_P if nbraces.
+ (cp_parser_omp_sections_scope): Adjust cp_parser_omp_structured_block
+ calls.
+
2016-04-14 Jason Merrill <jason@redhat.com>
PR c++/70528
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 4abff2011f2..d9b9a2888f9 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -915,7 +915,7 @@ struct constexpr_ctx {
/* A table of all constexpr calls that have been evaluated by the
compiler in this translation unit. */
-static GTY ((deletable)) hash_table<constexpr_call_hasher> *constexpr_call_table;
+static GTY (()) hash_table<constexpr_call_hasher> *constexpr_call_table;
static tree cxx_eval_constant_expression (const constexpr_ctx *, tree,
bool, bool *, bool *, tree * = NULL);
@@ -965,17 +965,6 @@ maybe_initialize_constexpr_call_table (void)
constexpr_call_table = hash_table<constexpr_call_hasher>::create_ggc (101);
}
-/* The representation of a single node in the per-function freelist maintained
- by FUNDEF_COPIES_TABLE. */
-
-struct fundef_copy
-{
- tree body;
- tree parms;
- tree res;
- fundef_copy *prev;
-};
-
/* During constexpr CALL_EXPR evaluation, to avoid issues with sharing when
a function happens to get called recursively, we unshare the callee
function's body and evaluate this unshared copy instead of evaluating the
@@ -983,45 +972,42 @@ struct fundef_copy
FUNDEF_COPIES_TABLE is a per-function freelist of these unshared function
copies. The underlying data structure of FUNDEF_COPIES_TABLE is a hash_map
- that's keyed off of the original FUNCTION_DECL and whose value is the chain
- of this function's unused copies awaiting reuse. */
+ that's keyed off of the original FUNCTION_DECL and whose value is a
+ TREE_LIST of this function's unused copies awaiting reuse.
-struct fundef_copies_table_t
-{
- hash_map<tree, fundef_copy *> *map;
-};
+ This is not GC-deletable to avoid GC affecting UID generation. */
-static GTY((deletable)) fundef_copies_table_t fundef_copies_table;
+static GTY(()) hash_map<tree, tree> *fundef_copies_table;
/* Initialize FUNDEF_COPIES_TABLE if it's not initialized. */
static void
maybe_initialize_fundef_copies_table ()
{
- if (fundef_copies_table.map == NULL)
- fundef_copies_table.map = hash_map<tree, fundef_copy *>::create_ggc (101);
+ if (fundef_copies_table == NULL)
+ fundef_copies_table = hash_map<tree,tree>::create_ggc (101);
}
/* Reuse a copy or create a new unshared copy of the function FUN.
Return this copy. */
-static fundef_copy *
+static tree
get_fundef_copy (tree fun)
{
maybe_initialize_fundef_copies_table ();
- fundef_copy *copy;
- fundef_copy **slot = &fundef_copies_table.map->get_or_insert (fun, NULL);
- if (*slot == NULL)
+ tree copy;
+ tree *slot = fundef_copies_table->get (fun);
+ if (slot == NULL)
{
- copy = ggc_alloc<fundef_copy> ();
- copy->body = copy_fn (fun, copy->parms, copy->res);
- copy->prev = NULL;
+ copy = build_tree_list (NULL, NULL);
+ /* PURPOSE is body, VALUE is parms, TYPE is result. */
+ TREE_PURPOSE (copy) = copy_fn (fun, TREE_VALUE (copy), TREE_TYPE (copy));
}
else
{
copy = *slot;
- *slot = (*slot)->prev;
+ *slot = TREE_CHAIN (copy);
}
return copy;
@@ -1030,10 +1016,10 @@ get_fundef_copy (tree fun)
/* Save the copy COPY of function FUN for later reuse by get_fundef_copy(). */
static void
-save_fundef_copy (tree fun, fundef_copy *copy)
+save_fundef_copy (tree fun, tree copy)
{
- fundef_copy **slot = &fundef_copies_table.map->get_or_insert (fun, NULL);
- copy->prev = *slot;
+ tree *slot = &fundef_copies_table->get_or_insert (fun, NULL);
+ TREE_CHAIN (copy) = *slot;
*slot = copy;
}
@@ -1464,10 +1450,10 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
tree body, parms, res;
/* Reuse or create a new unshared copy of this function's body. */
- fundef_copy *copy = get_fundef_copy (fun);
- body = copy->body;
- parms = copy->parms;
- res = copy->res;
+ tree copy = get_fundef_copy (fun);
+ body = TREE_PURPOSE (copy);
+ parms = TREE_VALUE (copy);
+ res = TREE_TYPE (copy);
/* Associate the bindings with the remapped parms. */
tree bound = new_call.bindings;
@@ -5223,4 +5209,14 @@ potential_nondependent_static_init_expression (tree t)
&& !instantiation_dependent_expression_p (t));
}
+/* Finalize constexpr processing after parsing. */
+
+void
+fini_constexpr (void)
+{
+ /* The contexpr call and fundef copies tables are no longer needed. */
+ constexpr_call_table = NULL;
+ fundef_copies_table = NULL;
+}
+
#include "gt-cp-constexpr.h"
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index a3cd834a105..0df84707f88 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6880,6 +6880,7 @@ bool cilkplus_an_triplet_types_ok_p (location_t, tree, tree, tree,
tree);
/* In constexpr.c */
+extern void fini_constexpr (void);
extern bool literal_type_p (tree);
extern tree register_constexpr_fundef (tree, tree);
extern bool check_constexpr_ctor_body (tree, tree, bool);
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index b3cc99a7dc1..0ea326d7699 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -4904,6 +4904,8 @@ c_parse_final_cleanups (void)
finish_repo ();
+ fini_constexpr ();
+
/* The entire file is now complete. If requested, dump everything
to a file. */
dump_tu ();
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index cba2d6598a7..54861298c84 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -249,9 +249,9 @@ static tree cp_literal_operator_id
(const char *);
static void cp_parser_cilk_simd
- (cp_parser *, cp_token *);
+ (cp_parser *, cp_token *, bool *);
static tree cp_parser_cilk_for
- (cp_parser *, tree);
+ (cp_parser *, tree, bool *);
static bool cp_parser_omp_declare_reduction_exprs
(tree, cp_parser *);
static tree cp_parser_cilk_simd_vectorlength
@@ -2434,7 +2434,7 @@ enum pragma_context {
pragma_compound
};
static bool cp_parser_pragma
- (cp_parser *, enum pragma_context);
+ (cp_parser *, enum pragma_context, bool *);
/* Objective-C++ Productions */
@@ -10404,7 +10404,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
statement = error_mark_node;
}
else
- statement = cp_parser_cilk_for (parser, integer_zero_node);
+ statement = cp_parser_cilk_for (parser, integer_zero_node, if_p);
break;
case RID_BREAK:
@@ -10496,8 +10496,8 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
return so that we can check for a close brace. Otherwise we
require a real statement and must go back and read one. */
if (in_compound)
- cp_parser_pragma (parser, pragma_compound);
- else if (!cp_parser_pragma (parser, pragma_stmt))
+ cp_parser_pragma (parser, pragma_compound, if_p);
+ else if (!cp_parser_pragma (parser, pragma_stmt, if_p))
goto restart;
return;
}
@@ -12016,7 +12016,7 @@ cp_parser_declaration_seq_opt (cp_parser* parser)
A nested declaration cannot, so this is done here and not
in cp_parser_declaration. (A #pragma at block scope is
handled in cp_parser_statement.) */
- cp_parser_pragma (parser, pragma_external);
+ cp_parser_pragma (parser, pragma_external, NULL);
continue;
}
@@ -22145,7 +22145,7 @@ cp_parser_member_specification_opt (cp_parser* parser)
/* Accept #pragmas at class scope. */
if (token->type == CPP_PRAGMA)
{
- cp_parser_pragma (parser, pragma_member);
+ cp_parser_pragma (parser, pragma_member, NULL);
break;
}
@@ -28481,7 +28481,7 @@ cp_parser_objc_interstitial_code (cp_parser* parser)
cp_parser_linkage_specification (parser);
/* Handle #pragma, if any. */
else if (token->type == CPP_PRAGMA)
- cp_parser_pragma (parser, pragma_objc_icode);
+ cp_parser_pragma (parser, pragma_objc_icode, NULL);
/* Allow stray semicolons. */
else if (token->type == CPP_SEMICOLON)
cp_lexer_consume_token (parser->lexer);
@@ -32609,12 +32609,12 @@ cp_parser_end_omp_structured_block (cp_parser *parser, unsigned save)
}
static tree
-cp_parser_omp_structured_block (cp_parser *parser)
+cp_parser_omp_structured_block (cp_parser *parser, bool *if_p)
{
tree stmt = begin_omp_structured_block ();
unsigned int save = cp_parser_begin_omp_structured_block (parser);
- cp_parser_statement (parser, NULL_TREE, false, NULL);
+ cp_parser_statement (parser, NULL_TREE, false, if_p);
cp_parser_end_omp_structured_block (parser, save);
return finish_omp_structured_block (stmt);
@@ -33074,7 +33074,7 @@ cp_parser_omp_barrier (cp_parser *parser, cp_token *pragma_tok)
( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_HINT) )
static tree
-cp_parser_omp_critical (cp_parser *parser, cp_token *pragma_tok)
+cp_parser_omp_critical (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
{
tree stmt, name = NULL_TREE, clauses = NULL_TREE;
@@ -33099,7 +33099,7 @@ cp_parser_omp_critical (cp_parser *parser, cp_token *pragma_tok)
else
cp_parser_require_pragma_eol (parser, pragma_tok);
- stmt = cp_parser_omp_structured_block (parser);
+ stmt = cp_parser_omp_structured_block (parser, if_p);
return c_finish_omp_critical (input_location, stmt, name, clauses);
}
@@ -33475,7 +33475,7 @@ cp_parser_omp_for_loop_init (cp_parser *parser,
static tree
cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
- tree *cclauses)
+ tree *cclauses, bool *if_p)
{
tree init, orig_init, cond, incr, body, decl, pre_body = NULL_TREE, ret;
tree real_decl, initv, condv, incrv, declv;
@@ -33734,6 +33734,9 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
}
}
+ if (nbraces)
+ if_p = NULL;
+
/* Note that we saved the original contents of this flag when we entered
the structured block, and so we don't need to re-save it here. */
if (code == CILK_SIMD || code == CILK_FOR)
@@ -33744,7 +33747,7 @@ cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
/* Note that the grammar doesn't call for a structured block here,
though the loop as a whole is a structured block. */
body = push_stmt_list ();
- cp_parser_statement (parser, NULL_TREE, false, NULL);
+ cp_parser_statement (parser, NULL_TREE, false, if_p);
body = pop_stmt_list (body);
if (declv == NULL_TREE)
@@ -33813,7 +33816,8 @@ cp_omp_split_clauses (location_t loc, enum tree_code code,
static tree
cp_parser_omp_simd (cp_parser *parser, cp_token *pragma_tok,
- char *p_name, omp_clause_mask mask, tree *cclauses)
+ char *p_name, omp_clause_mask mask, tree *cclauses,
+ bool *if_p)
{
tree clauses, sb, ret;
unsigned int save;
@@ -33842,7 +33846,7 @@ cp_parser_omp_simd (cp_parser *parser, cp_token *pragma_tok,
sb = begin_omp_structured_block ();
save = cp_parser_begin_omp_structured_block (parser);
- ret = cp_parser_omp_for_loop (parser, OMP_SIMD, clauses, cclauses);
+ ret = cp_parser_omp_for_loop (parser, OMP_SIMD, clauses, cclauses, if_p);
cp_parser_end_omp_structured_block (parser, save);
add_stmt (finish_omp_structured_block (sb));
@@ -33871,7 +33875,8 @@ cp_parser_omp_simd (cp_parser *parser, cp_token *pragma_tok,
static tree
cp_parser_omp_for (cp_parser *parser, cp_token *pragma_tok,
- char *p_name, omp_clause_mask mask, tree *cclauses)
+ char *p_name, omp_clause_mask mask, tree *cclauses,
+ bool *if_p)
{
tree clauses, sb, ret;
unsigned int save;
@@ -33899,11 +33904,11 @@ cp_parser_omp_for (cp_parser *parser, cp_token *pragma_tok,
cp_lexer_consume_token (parser->lexer);
if (!flag_openmp) /* flag_openmp_simd */
return cp_parser_omp_simd (parser, pragma_tok, p_name, mask,
- cclauses);
+ cclauses, if_p);
sb = begin_omp_structured_block ();
save = cp_parser_begin_omp_structured_block (parser);
ret = cp_parser_omp_simd (parser, pragma_tok, p_name, mask,
- cclauses);
+ cclauses, if_p);
cp_parser_end_omp_structured_block (parser, save);
tree body = finish_omp_structured_block (sb);
if (ret == NULL)
@@ -33938,7 +33943,7 @@ cp_parser_omp_for (cp_parser *parser, cp_token *pragma_tok,
sb = begin_omp_structured_block ();
save = cp_parser_begin_omp_structured_block (parser);
- ret = cp_parser_omp_for_loop (parser, OMP_FOR, clauses, cclauses);
+ ret = cp_parser_omp_for_loop (parser, OMP_FOR, clauses, cclauses, if_p);
cp_parser_end_omp_structured_block (parser, save);
add_stmt (finish_omp_structured_block (sb));
@@ -33951,11 +33956,11 @@ cp_parser_omp_for (cp_parser *parser, cp_token *pragma_tok,
structured-block */
static tree
-cp_parser_omp_master (cp_parser *parser, cp_token *pragma_tok)
+cp_parser_omp_master (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
{
cp_parser_require_pragma_eol (parser, pragma_tok);
return c_finish_omp_master (input_location,
- cp_parser_omp_structured_block (parser));
+ cp_parser_omp_structured_block (parser, if_p));
}
/* OpenMP 2.5:
@@ -33975,7 +33980,7 @@ cp_parser_omp_master (cp_parser *parser, cp_token *pragma_tok)
static bool
cp_parser_omp_ordered (cp_parser *parser, cp_token *pragma_tok,
- enum pragma_context context)
+ enum pragma_context context, bool *if_p)
{
location_t loc = pragma_tok->location;
@@ -34014,7 +34019,7 @@ cp_parser_omp_ordered (cp_parser *parser, cp_token *pragma_tok,
= cp_parser_omp_all_clauses (parser, OMP_ORDERED_CLAUSE_MASK,
"#pragma omp ordered", pragma_tok);
c_finish_omp_ordered (loc, clauses,
- cp_parser_omp_structured_block (parser));
+ cp_parser_omp_structured_block (parser, if_p));
return true;
}
@@ -34042,7 +34047,7 @@ cp_parser_omp_sections_scope (cp_parser *parser)
if (cp_parser_pragma_kind (cp_lexer_peek_token (parser->lexer))
!= PRAGMA_OMP_SECTION)
{
- substmt = cp_parser_omp_structured_block (parser);
+ substmt = cp_parser_omp_structured_block (parser, NULL);
substmt = build1 (OMP_SECTION, void_type_node, substmt);
add_stmt (substmt);
}
@@ -34067,7 +34072,7 @@ cp_parser_omp_sections_scope (cp_parser *parser)
error_suppress = true;
}
- substmt = cp_parser_omp_structured_block (parser);
+ substmt = cp_parser_omp_structured_block (parser, NULL);
substmt = build1 (OMP_SECTION, void_type_node, substmt);
add_stmt (substmt);
}
@@ -34146,7 +34151,8 @@ cp_parser_omp_sections (cp_parser *parser, cp_token *pragma_tok,
static tree
cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok,
- char *p_name, omp_clause_mask mask, tree *cclauses)
+ char *p_name, omp_clause_mask mask, tree *cclauses,
+ bool *if_p)
{
tree stmt, clauses, block;
unsigned int save;
@@ -34167,10 +34173,12 @@ cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok,
cp_lexer_consume_token (parser->lexer);
if (!flag_openmp) /* flag_openmp_simd */
- return cp_parser_omp_for (parser, pragma_tok, p_name, mask, cclauses);
+ return cp_parser_omp_for (parser, pragma_tok, p_name, mask, cclauses,
+ if_p);
block = begin_omp_parallel ();
save = cp_parser_begin_omp_structured_block (parser);
- tree ret = cp_parser_omp_for (parser, pragma_tok, p_name, mask, cclauses);
+ tree ret = cp_parser_omp_for (parser, pragma_tok, p_name, mask, cclauses,
+ if_p);
cp_parser_end_omp_structured_block (parser, save);
stmt = finish_omp_parallel (cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
block);
@@ -34224,7 +34232,7 @@ cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok,
block = begin_omp_parallel ();
save = cp_parser_begin_omp_structured_block (parser);
- cp_parser_statement (parser, NULL_TREE, false, NULL);
+ cp_parser_statement (parser, NULL_TREE, false, if_p);
cp_parser_end_omp_structured_block (parser, save);
stmt = finish_omp_parallel (clauses, block);
return stmt;
@@ -34241,7 +34249,7 @@ cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok,
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
static tree
-cp_parser_omp_single (cp_parser *parser, cp_token *pragma_tok)
+cp_parser_omp_single (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
{
tree stmt = make_node (OMP_SINGLE);
TREE_TYPE (stmt) = void_type_node;
@@ -34249,7 +34257,7 @@ cp_parser_omp_single (cp_parser *parser, cp_token *pragma_tok)
OMP_SINGLE_CLAUSES (stmt)
= cp_parser_omp_all_clauses (parser, OMP_SINGLE_CLAUSE_MASK,
"#pragma omp single", pragma_tok);
- OMP_SINGLE_BODY (stmt) = cp_parser_omp_structured_block (parser);
+ OMP_SINGLE_BODY (stmt) = cp_parser_omp_structured_block (parser, if_p);
return add_stmt (stmt);
}
@@ -34271,7 +34279,7 @@ cp_parser_omp_single (cp_parser *parser, cp_token *pragma_tok)
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY))
static tree
-cp_parser_omp_task (cp_parser *parser, cp_token *pragma_tok)
+cp_parser_omp_task (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
{
tree clauses, block;
unsigned int save;
@@ -34280,7 +34288,7 @@ cp_parser_omp_task (cp_parser *parser, cp_token *pragma_tok)
"#pragma omp task", pragma_tok);
block = begin_omp_task ();
save = cp_parser_begin_omp_structured_block (parser);
- cp_parser_statement (parser, NULL_TREE, false, NULL);
+ cp_parser_statement (parser, NULL_TREE, false, if_p);
cp_parser_end_omp_structured_block (parser, save);
return finish_omp_task (clauses, block);
}
@@ -34310,11 +34318,12 @@ cp_parser_omp_taskyield (cp_parser *parser, cp_token *pragma_tok)
structured-block */
static tree
-cp_parser_omp_taskgroup (cp_parser *parser, cp_token *pragma_tok)
+cp_parser_omp_taskgroup (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
{
cp_parser_require_pragma_eol (parser, pragma_tok);
return c_finish_omp_taskgroup (input_location,
- cp_parser_omp_structured_block (parser));
+ cp_parser_omp_structured_block (parser,
+ if_p));
}
@@ -34403,7 +34412,8 @@ cp_parser_omp_cancellation_point (cp_parser *parser, cp_token *pragma_tok)
static tree
cp_parser_omp_distribute (cp_parser *parser, cp_token *pragma_tok,
- char *p_name, omp_clause_mask mask, tree *cclauses)
+ char *p_name, omp_clause_mask mask, tree *cclauses,
+ bool *if_p)
{
tree clauses, sb, ret;
unsigned int save;
@@ -34433,19 +34443,19 @@ cp_parser_omp_distribute (cp_parser *parser, cp_token *pragma_tok,
{
if (simd)
return cp_parser_omp_simd (parser, pragma_tok, p_name, mask,
- cclauses);
+ cclauses, if_p);
else
return cp_parser_omp_parallel (parser, pragma_tok, p_name, mask,
- cclauses);
+ cclauses, if_p);
}
sb = begin_omp_structured_block ();
save = cp_parser_begin_omp_structured_block (parser);
if (simd)
ret = cp_parser_omp_simd (parser, pragma_tok, p_name, mask,
- cclauses);
+ cclauses, if_p);
else
ret = cp_parser_omp_parallel (parser, pragma_tok, p_name, mask,
- cclauses);
+ cclauses, if_p);
cp_parser_end_omp_structured_block (parser, save);
tree body = finish_omp_structured_block (sb);
if (ret == NULL)
@@ -34476,7 +34486,7 @@ cp_parser_omp_distribute (cp_parser *parser, cp_token *pragma_tok,
sb = begin_omp_structured_block ();
save = cp_parser_begin_omp_structured_block (parser);
- ret = cp_parser_omp_for_loop (parser, OMP_DISTRIBUTE, clauses, NULL);
+ ret = cp_parser_omp_for_loop (parser, OMP_DISTRIBUTE, clauses, NULL, if_p);
cp_parser_end_omp_structured_block (parser, save);
add_stmt (finish_omp_structured_block (sb));
@@ -34499,7 +34509,8 @@ cp_parser_omp_distribute (cp_parser *parser, cp_token *pragma_tok,
static tree
cp_parser_omp_teams (cp_parser *parser, cp_token *pragma_tok,
- char *p_name, omp_clause_mask mask, tree *cclauses)
+ char *p_name, omp_clause_mask mask, tree *cclauses,
+ bool *if_p)
{
tree clauses, sb, ret;
unsigned int save;
@@ -34521,11 +34532,11 @@ cp_parser_omp_teams (cp_parser *parser, cp_token *pragma_tok,
cp_lexer_consume_token (parser->lexer);
if (!flag_openmp) /* flag_openmp_simd */
return cp_parser_omp_distribute (parser, pragma_tok, p_name, mask,
- cclauses);
+ cclauses, if_p);
sb = begin_omp_structured_block ();
save = cp_parser_begin_omp_structured_block (parser);
ret = cp_parser_omp_distribute (parser, pragma_tok, p_name, mask,
- cclauses);
+ cclauses, if_p);
cp_parser_end_omp_structured_block (parser, save);
tree body = finish_omp_structured_block (sb);
if (ret == NULL)
@@ -34556,7 +34567,7 @@ cp_parser_omp_teams (cp_parser *parser, cp_token *pragma_tok,
tree stmt = make_node (OMP_TEAMS);
TREE_TYPE (stmt) = void_type_node;
OMP_TEAMS_CLAUSES (stmt) = clauses;
- OMP_TEAMS_BODY (stmt) = cp_parser_omp_structured_block (parser);
+ OMP_TEAMS_BODY (stmt) = cp_parser_omp_structured_block (parser, if_p);
return add_stmt (stmt);
}
@@ -34572,7 +34583,7 @@ cp_parser_omp_teams (cp_parser *parser, cp_token *pragma_tok,
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR))
static tree
-cp_parser_omp_target_data (cp_parser *parser, cp_token *pragma_tok)
+cp_parser_omp_target_data (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
{
tree clauses
= cp_parser_omp_all_clauses (parser, OMP_TARGET_DATA_CLAUSE_MASK,
@@ -34622,7 +34633,7 @@ cp_parser_omp_target_data (cp_parser *parser, cp_token *pragma_tok)
OMP_TARGET_DATA_CLAUSES (stmt) = clauses;
keep_next_level (true);
- OMP_TARGET_DATA_BODY (stmt) = cp_parser_omp_structured_block (parser);
+ OMP_TARGET_DATA_BODY (stmt) = cp_parser_omp_structured_block (parser, if_p);
SET_EXPR_LOCATION (stmt, pragma_tok->location);
return add_stmt (stmt);
@@ -34867,7 +34878,7 @@ cp_parser_omp_target_update (cp_parser *parser, cp_token *pragma_tok,
static bool
cp_parser_omp_target (cp_parser *parser, cp_token *pragma_tok,
- enum pragma_context context)
+ enum pragma_context context, bool *if_p)
{
tree *pc = NULL, stmt;
@@ -34906,17 +34917,17 @@ cp_parser_omp_target (cp_parser *parser, cp_token *pragma_tok,
case OMP_TEAMS:
stmt = cp_parser_omp_teams (parser, pragma_tok, p_name,
OMP_TARGET_CLAUSE_MASK,
- cclauses);
+ cclauses, if_p);
break;
case OMP_PARALLEL:
stmt = cp_parser_omp_parallel (parser, pragma_tok, p_name,
OMP_TARGET_CLAUSE_MASK,
- cclauses);
+ cclauses, if_p);
break;
case OMP_SIMD:
stmt = cp_parser_omp_simd (parser, pragma_tok, p_name,
OMP_TARGET_CLAUSE_MASK,
- cclauses);
+ cclauses, if_p);
break;
default:
gcc_unreachable ();
@@ -34930,15 +34941,18 @@ cp_parser_omp_target (cp_parser *parser, cp_token *pragma_tok,
{
case OMP_TEAMS:
ret = cp_parser_omp_teams (parser, pragma_tok, p_name,
- OMP_TARGET_CLAUSE_MASK, cclauses);
+ OMP_TARGET_CLAUSE_MASK, cclauses,
+ if_p);
break;
case OMP_PARALLEL:
ret = cp_parser_omp_parallel (parser, pragma_tok, p_name,
- OMP_TARGET_CLAUSE_MASK, cclauses);
+ OMP_TARGET_CLAUSE_MASK, cclauses,
+ if_p);
break;
case OMP_SIMD:
ret = cp_parser_omp_simd (parser, pragma_tok, p_name,
- OMP_TARGET_CLAUSE_MASK, cclauses);
+ OMP_TARGET_CLAUSE_MASK, cclauses,
+ if_p);
break;
default:
gcc_unreachable ();
@@ -34991,7 +35005,7 @@ cp_parser_omp_target (cp_parser *parser, cp_token *pragma_tok,
else if (strcmp (p, "data") == 0)
{
cp_lexer_consume_token (parser->lexer);
- cp_parser_omp_target_data (parser, pragma_tok);
+ cp_parser_omp_target_data (parser, pragma_tok, if_p);
return true;
}
else if (strcmp (p, "enter") == 0)
@@ -35021,7 +35035,7 @@ cp_parser_omp_target (cp_parser *parser, cp_token *pragma_tok,
"#pragma omp target", pragma_tok);
pc = &OMP_TARGET_CLAUSES (stmt);
keep_next_level (true);
- OMP_TARGET_BODY (stmt) = cp_parser_omp_structured_block (parser);
+ OMP_TARGET_BODY (stmt) = cp_parser_omp_structured_block (parser, if_p);
SET_EXPR_LOCATION (stmt, pragma_tok->location);
add_stmt (stmt);
@@ -35097,7 +35111,7 @@ cp_parser_oacc_cache (cp_parser *parser, cp_token *pragma_tok)
| (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT_OR_CREATE))
static tree
-cp_parser_oacc_data (cp_parser *parser, cp_token *pragma_tok)
+cp_parser_oacc_data (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
{
tree stmt, clauses, block;
unsigned int save;
@@ -35107,7 +35121,7 @@ cp_parser_oacc_data (cp_parser *parser, cp_token *pragma_tok)
block = begin_omp_parallel ();
save = cp_parser_begin_omp_structured_block (parser);
- cp_parser_statement (parser, NULL_TREE, false, NULL);
+ cp_parser_statement (parser, NULL_TREE, false, if_p);
cp_parser_end_omp_structured_block (parser, save);
stmt = finish_oacc_data (clauses, block);
return stmt;
@@ -35121,7 +35135,7 @@ cp_parser_oacc_data (cp_parser *parser, cp_token *pragma_tok)
( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_USE_DEVICE) )
static tree
-cp_parser_oacc_host_data (cp_parser *parser, cp_token *pragma_tok)
+cp_parser_oacc_host_data (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
{
tree stmt, clauses, block;
unsigned int save;
@@ -35131,7 +35145,7 @@ cp_parser_oacc_host_data (cp_parser *parser, cp_token *pragma_tok)
block = begin_omp_parallel ();
save = cp_parser_begin_omp_structured_block (parser);
- cp_parser_statement (parser, NULL_TREE, false, NULL);
+ cp_parser_statement (parser, NULL_TREE, false, if_p);
cp_parser_end_omp_structured_block (parser, save);
stmt = finish_oacc_host_data (clauses, block);
return stmt;
@@ -35380,7 +35394,7 @@ cp_parser_oacc_enter_exit_data (cp_parser *parser, cp_token *pragma_tok,
static tree
cp_parser_oacc_loop (cp_parser *parser, cp_token *pragma_tok, char *p_name,
- omp_clause_mask mask, tree *cclauses)
+ omp_clause_mask mask, tree *cclauses, bool *if_p)
{
strcat (p_name, " loop");
mask |= OACC_LOOP_CLAUSE_MASK;
@@ -35398,7 +35412,7 @@ cp_parser_oacc_loop (cp_parser *parser, cp_token *pragma_tok, char *p_name,
tree block = begin_omp_structured_block ();
int save = cp_parser_begin_omp_structured_block (parser);
- tree stmt = cp_parser_omp_for_loop (parser, OACC_LOOP, clauses, NULL);
+ tree stmt = cp_parser_omp_for_loop (parser, OACC_LOOP, clauses, NULL, if_p);
cp_parser_end_omp_structured_block (parser, save);
add_stmt (finish_omp_structured_block (block));
@@ -35455,7 +35469,7 @@ cp_parser_oacc_loop (cp_parser *parser, cp_token *pragma_tok, char *p_name,
static tree
cp_parser_oacc_kernels_parallel (cp_parser *parser, cp_token *pragma_tok,
- char *p_name)
+ char *p_name, bool *if_p)
{
omp_clause_mask mask;
enum tree_code code;
@@ -35486,7 +35500,8 @@ cp_parser_oacc_kernels_parallel (cp_parser *parser, cp_token *pragma_tok,
tree block = begin_omp_parallel ();
tree clauses;
- cp_parser_oacc_loop (parser, pragma_tok, p_name, mask, &clauses);
+ cp_parser_oacc_loop (parser, pragma_tok, p_name, mask, &clauses,
+ if_p);
return finish_omp_construct (code, block, clauses);
}
}
@@ -35495,7 +35510,7 @@ cp_parser_oacc_kernels_parallel (cp_parser *parser, cp_token *pragma_tok,
tree block = begin_omp_parallel ();
unsigned int save = cp_parser_begin_omp_structured_block (parser);
- cp_parser_statement (parser, NULL_TREE, false, NULL);
+ cp_parser_statement (parser, NULL_TREE, false, if_p);
cp_parser_end_omp_structured_block (parser, save);
return finish_omp_construct (code, block, clauses);
}
@@ -35599,7 +35614,7 @@ cp_parser_omp_declare_simd (cp_parser *parser, cp_token *pragma_tok,
if (first_p)
{
while (cp_lexer_next_token_is (parser->lexer, CPP_PRAGMA))
- cp_parser_pragma (parser, context);
+ cp_parser_pragma (parser, context, NULL);
switch (context)
{
case pragma_external:
@@ -36322,7 +36337,8 @@ cp_parser_omp_declare (cp_parser *parser, cp_token *pragma_tok,
static tree
cp_parser_omp_taskloop (cp_parser *parser, cp_token *pragma_tok,
- char *p_name, omp_clause_mask mask, tree *cclauses)
+ char *p_name, omp_clause_mask mask, tree *cclauses,
+ bool *if_p)
{
tree clauses, sb, ret;
unsigned int save;
@@ -36345,11 +36361,11 @@ cp_parser_omp_taskloop (cp_parser *parser, cp_token *pragma_tok,
cp_lexer_consume_token (parser->lexer);
if (!flag_openmp) /* flag_openmp_simd */
return cp_parser_omp_simd (parser, pragma_tok, p_name, mask,
- cclauses);
+ cclauses, if_p);
sb = begin_omp_structured_block ();
save = cp_parser_begin_omp_structured_block (parser);
ret = cp_parser_omp_simd (parser, pragma_tok, p_name, mask,
- cclauses);
+ cclauses, if_p);
cp_parser_end_omp_structured_block (parser, save);
tree body = finish_omp_structured_block (sb);
if (ret == NULL)
@@ -36380,7 +36396,8 @@ cp_parser_omp_taskloop (cp_parser *parser, cp_token *pragma_tok,
sb = begin_omp_structured_block ();
save = cp_parser_begin_omp_structured_block (parser);
- ret = cp_parser_omp_for_loop (parser, OMP_TASKLOOP, clauses, cclauses);
+ ret = cp_parser_omp_for_loop (parser, OMP_TASKLOOP, clauses, cclauses,
+ if_p);
cp_parser_end_omp_structured_block (parser, save);
add_stmt (finish_omp_structured_block (sb));
@@ -36543,7 +36560,7 @@ cp_parser_oacc_routine (cp_parser *parser, cp_token *pragma_tok,
parser->oacc_routine->clauses = c_head;
while (cp_lexer_next_token_is (parser->lexer, CPP_PRAGMA))
- cp_parser_pragma (parser, context);
+ cp_parser_pragma (parser, context, NULL);
if (first_p)
{
@@ -36670,7 +36687,7 @@ cp_finalize_oacc_routine (cp_parser *parser, tree fndecl, bool is_defn)
/* Main entry point to OpenMP statement pragmas. */
static void
-cp_parser_omp_construct (cp_parser *parser, cp_token *pragma_tok)
+cp_parser_omp_construct (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
{
tree stmt;
char p_name[sizeof "#pragma omp teams distribute parallel for simd"];
@@ -36685,7 +36702,7 @@ cp_parser_omp_construct (cp_parser *parser, cp_token *pragma_tok)
stmt = cp_parser_oacc_cache (parser, pragma_tok);
break;
case PRAGMA_OACC_DATA:
- stmt = cp_parser_oacc_data (parser, pragma_tok);
+ stmt = cp_parser_oacc_data (parser, pragma_tok, if_p);
break;
case PRAGMA_OACC_ENTER_DATA:
stmt = cp_parser_oacc_enter_exit_data (parser, pragma_tok, true);
@@ -36694,16 +36711,18 @@ cp_parser_omp_construct (cp_parser *parser, cp_token *pragma_tok)
stmt = cp_parser_oacc_enter_exit_data (parser, pragma_tok, false);
break;
case PRAGMA_OACC_HOST_DATA:
- stmt = cp_parser_oacc_host_data (parser, pragma_tok);
+ stmt = cp_parser_oacc_host_data (parser, pragma_tok, if_p);
break;
case PRAGMA_OACC_KERNELS:
case PRAGMA_OACC_PARALLEL:
strcpy (p_name, "#pragma acc");
- stmt = cp_parser_oacc_kernels_parallel (parser, pragma_tok, p_name);
+ stmt = cp_parser_oacc_kernels_parallel (parser, pragma_tok, p_name,
+ if_p);
break;
case PRAGMA_OACC_LOOP:
strcpy (p_name, "#pragma acc");
- stmt = cp_parser_oacc_loop (parser, pragma_tok, p_name, mask, NULL);
+ stmt = cp_parser_oacc_loop (parser, pragma_tok, p_name, mask, NULL,
+ if_p);
break;
case PRAGMA_OACC_UPDATE:
stmt = cp_parser_oacc_update (parser, pragma_tok);
@@ -36715,22 +36734,25 @@ cp_parser_omp_construct (cp_parser *parser, cp_token *pragma_tok)
cp_parser_omp_atomic (parser, pragma_tok);
return;
case PRAGMA_OMP_CRITICAL:
- stmt = cp_parser_omp_critical (parser, pragma_tok);
+ stmt = cp_parser_omp_critical (parser, pragma_tok, if_p);
break;
case PRAGMA_OMP_DISTRIBUTE:
strcpy (p_name, "#pragma omp");
- stmt = cp_parser_omp_distribute (parser, pragma_tok, p_name, mask, NULL);
+ stmt = cp_parser_omp_distribute (parser, pragma_tok, p_name, mask, NULL,
+ if_p);
break;
case PRAGMA_OMP_FOR:
strcpy (p_name, "#pragma omp");
- stmt = cp_parser_omp_for (parser, pragma_tok, p_name, mask, NULL);
+ stmt = cp_parser_omp_for (parser, pragma_tok, p_name, mask, NULL,
+ if_p);
break;
case PRAGMA_OMP_MASTER:
- stmt = cp_parser_omp_master (parser, pragma_tok);
+ stmt = cp_parser_omp_master (parser, pragma_tok, if_p);
break;
case PRAGMA_OMP_PARALLEL:
strcpy (p_name, "#pragma omp");
- stmt = cp_parser_omp_parallel (parser, pragma_tok, p_name, mask, NULL);
+ stmt = cp_parser_omp_parallel (parser, pragma_tok, p_name, mask, NULL,
+ if_p);
break;
case PRAGMA_OMP_SECTIONS:
strcpy (p_name, "#pragma omp");
@@ -36738,24 +36760,27 @@ cp_parser_omp_construct (cp_parser *parser, cp_token *pragma_tok)
break;
case PRAGMA_OMP_SIMD:
strcpy (p_name, "#pragma omp");
- stmt = cp_parser_omp_simd (parser, pragma_tok, p_name, mask, NULL);
+ stmt = cp_parser_omp_simd (parser, pragma_tok, p_name, mask, NULL,
+ if_p);
break;
case PRAGMA_OMP_SINGLE:
- stmt = cp_parser_omp_single (parser, pragma_tok);
+ stmt = cp_parser_omp_single (parser, pragma_tok, if_p);
break;
case PRAGMA_OMP_TASK:
- stmt = cp_parser_omp_task (parser, pragma_tok);
+ stmt = cp_parser_omp_task (parser, pragma_tok, if_p);
break;
case PRAGMA_OMP_TASKGROUP:
- stmt = cp_parser_omp_taskgroup (parser, pragma_tok);
+ stmt = cp_parser_omp_taskgroup (parser, pragma_tok, if_p);
break;
case PRAGMA_OMP_TASKLOOP:
strcpy (p_name, "#pragma omp");
- stmt = cp_parser_omp_taskloop (parser, pragma_tok, p_name, mask, NULL);
+ stmt = cp_parser_omp_taskloop (parser, pragma_tok, p_name, mask, NULL,
+ if_p);
break;
case PRAGMA_OMP_TEAMS:
strcpy (p_name, "#pragma omp");
- stmt = cp_parser_omp_teams (parser, pragma_tok, p_name, mask, NULL);
+ stmt = cp_parser_omp_teams (parser, pragma_tok, p_name, mask, NULL,
+ if_p);
break;
default:
gcc_unreachable ();
@@ -37110,7 +37135,7 @@ cp_parser_initial_pragma (cp_token *first_token)
#pragma cilk grainsize = <VALUE>. */
static void
-cp_parser_cilk_grainsize (cp_parser *parser, cp_token *pragma_tok)
+cp_parser_cilk_grainsize (cp_parser *parser, cp_token *pragma_tok, bool *if_p)
{
if (cp_parser_require (parser, CPP_EQ, RT_EQ))
{
@@ -37125,7 +37150,7 @@ cp_parser_cilk_grainsize (cp_parser *parser, cp_token *pragma_tok)
/* Make sure the next token is _Cilk_for, it is invalid otherwise. */
if (cp_lexer_next_token_is_keyword (parser->lexer, RID_CILK_FOR))
- cp_parser_cilk_for (parser, exp);
+ cp_parser_cilk_for (parser, exp, if_p);
else
warning_at (cp_lexer_peek_token (parser->lexer)->location, 0,
"%<#pragma cilk grainsize%> is not followed by "
@@ -37139,7 +37164,7 @@ cp_parser_cilk_grainsize (cp_parser *parser, cp_token *pragma_tok)
regular lexer. */
static bool
-cp_parser_pragma (cp_parser *parser, enum pragma_context context)
+cp_parser_pragma (cp_parser *parser, enum pragma_context context, bool *if_p)
{
cp_token *pragma_tok;
unsigned int id;
@@ -37297,19 +37322,19 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
if (context != pragma_stmt && context != pragma_compound)
goto bad_stmt;
stmt = push_omp_privatization_clauses (false);
- cp_parser_omp_construct (parser, pragma_tok);
+ cp_parser_omp_construct (parser, pragma_tok, if_p);
pop_omp_privatization_clauses (stmt);
return true;
case PRAGMA_OMP_ORDERED:
stmt = push_omp_privatization_clauses (false);
- ret = cp_parser_omp_ordered (parser, pragma_tok, context);
+ ret = cp_parser_omp_ordered (parser, pragma_tok, context, if_p);
pop_omp_privatization_clauses (stmt);
return ret;
case PRAGMA_OMP_TARGET:
stmt = push_omp_privatization_clauses (false);
- ret = cp_parser_omp_target (parser, pragma_tok, context);
+ ret = cp_parser_omp_target (parser, pragma_tok, context, if_p);
pop_omp_privatization_clauses (stmt);
return ret;
@@ -37341,7 +37366,7 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
cp_parser_error (parser, "for, while or do statement expected");
return false;
}
- cp_parser_iteration_statement (parser, NULL, true);
+ cp_parser_iteration_statement (parser, if_p, true);
return true;
}
@@ -37353,7 +37378,7 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
break;
}
stmt = push_omp_privatization_clauses (false);
- cp_parser_cilk_simd (parser, pragma_tok);
+ cp_parser_cilk_simd (parser, pragma_tok, if_p);
pop_omp_privatization_clauses (stmt);
return true;
@@ -37368,7 +37393,7 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
/* Ignore the pragma if Cilk Plus is not enabled. */
if (flag_cilkplus)
{
- cp_parser_cilk_grainsize (parser, pragma_tok);
+ cp_parser_cilk_grainsize (parser, pragma_tok, if_p);
return true;
}
else
@@ -37695,7 +37720,7 @@ cp_parser_cilk_simd_all_clauses (cp_parser *parser, cp_token *pragma_token)
/* Main entry-point for parsing Cilk Plus <#pragma simd> for loops. */
static void
-cp_parser_cilk_simd (cp_parser *parser, cp_token *pragma_token)
+cp_parser_cilk_simd (cp_parser *parser, cp_token *pragma_token, bool *if_p)
{
tree clauses = cp_parser_cilk_simd_all_clauses (parser, pragma_token);
@@ -37711,7 +37736,7 @@ cp_parser_cilk_simd (cp_parser *parser, cp_token *pragma_token)
tree sb = begin_omp_structured_block ();
int save = cp_parser_begin_omp_structured_block (parser);
- tree ret = cp_parser_omp_for_loop (parser, CILK_SIMD, clauses, NULL);
+ tree ret = cp_parser_omp_for_loop (parser, CILK_SIMD, clauses, NULL, if_p);
if (ret)
cpp_validate_cilk_plus_loop (OMP_FOR_BODY (ret));
cp_parser_end_omp_structured_block (parser, save);
@@ -37723,7 +37748,7 @@ cp_parser_cilk_simd (cp_parser *parser, cp_token *pragma_token)
when errors happen and CILK_FOR tree on success. */
static tree
-cp_parser_cilk_for (cp_parser *parser, tree grain)
+cp_parser_cilk_for (cp_parser *parser, tree grain, bool *if_p)
{
if (cp_lexer_next_token_is_not_keyword (parser->lexer, RID_CILK_FOR))
gcc_unreachable ();
@@ -37736,7 +37761,7 @@ cp_parser_cilk_for (cp_parser *parser, tree grain)
OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (clauses) = grain;
clauses = finish_omp_clauses (clauses, false);
- tree ret = cp_parser_omp_for_loop (parser, CILK_FOR, clauses, NULL);
+ tree ret = cp_parser_omp_for_loop (parser, CILK_FOR, clauses, NULL, if_p);
if (ret)
cpp_validate_cilk_plus_loop (ret);
else
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index e9763d44d8d..8ec6b092be5 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -13974,6 +13974,8 @@ of the @option{-mcpu=} option. Permissible names are: @samp{armv2},
@samp{armv7ve}, @samp{armv8-a}, @samp{armv8-a+crc}, @samp{armv8.1-a},
@samp{armv8.1-a+crc}, @samp{iwmmxt}, @samp{iwmmxt2}, @samp{ep9312}.
+Architecture revisions older than @option{armv4t} are deprecated.
+
@option{-march=armv7ve} is the armv7-a architecture with virtualization
extensions.
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index aa3721edc9d..7282cc8a382 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -18409,1612 +18409,6 @@ make_pass_diagnose_omp_blocks (gcc::context *ctxt)
return new pass_diagnose_omp_blocks (ctxt);
}
-/* SIMD clone supporting code. */
-
-/* Allocate a fresh `simd_clone' and return it. NARGS is the number
- of arguments to reserve space for. */
-
-static struct cgraph_simd_clone *
-simd_clone_struct_alloc (int nargs)
-{
- struct cgraph_simd_clone *clone_info;
- size_t len = (sizeof (struct cgraph_simd_clone)
- + nargs * sizeof (struct cgraph_simd_clone_arg));
- clone_info = (struct cgraph_simd_clone *)
- ggc_internal_cleared_alloc (len);
- return clone_info;
-}
-
-/* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
-
-static inline void
-simd_clone_struct_copy (struct cgraph_simd_clone *to,
- struct cgraph_simd_clone *from)
-{
- memcpy (to, from, (sizeof (struct cgraph_simd_clone)
- + ((from->nargs - from->inbranch)
- * sizeof (struct cgraph_simd_clone_arg))));
-}
-
-/* Return vector of parameter types of function FNDECL. This uses
- TYPE_ARG_TYPES if available, otherwise falls back to types of
- DECL_ARGUMENTS types. */
-
-vec<tree>
-simd_clone_vector_of_formal_parm_types (tree fndecl)
-{
- if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
- return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
- vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
- unsigned int i;
- tree arg;
- FOR_EACH_VEC_ELT (args, i, arg)
- args[i] = TREE_TYPE (args[i]);
- return args;
-}
-
-/* Given a simd function in NODE, extract the simd specific
- information from the OMP clauses passed in CLAUSES, and return
- the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
- is set to TRUE if the `inbranch' or `notinbranch' clause specified,
- otherwise set to FALSE. */
-
-static struct cgraph_simd_clone *
-simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
- bool *inbranch_specified)
-{
- vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
- tree t;
- int n;
- *inbranch_specified = false;
-
- n = args.length ();
- if (n > 0 && args.last () == void_type_node)
- n--;
-
- /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
- be cloned have a distinctive artificial label in addition to "omp
- declare simd". */
- bool cilk_clone
- = (flag_cilkplus
- && lookup_attribute ("cilk simd function",
- DECL_ATTRIBUTES (node->decl)));
-
- /* Allocate one more than needed just in case this is an in-branch
- clone which will require a mask argument. */
- struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
- clone_info->nargs = n;
- clone_info->cilk_elemental = cilk_clone;
-
- if (!clauses)
- {
- args.release ();
- return clone_info;
- }
- clauses = TREE_VALUE (clauses);
- if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
- return clone_info;
-
- for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
- {
- switch (OMP_CLAUSE_CODE (t))
- {
- case OMP_CLAUSE_INBRANCH:
- clone_info->inbranch = 1;
- *inbranch_specified = true;
- break;
- case OMP_CLAUSE_NOTINBRANCH:
- clone_info->inbranch = 0;
- *inbranch_specified = true;
- break;
- case OMP_CLAUSE_SIMDLEN:
- clone_info->simdlen
- = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
- break;
- case OMP_CLAUSE_LINEAR:
- {
- tree decl = OMP_CLAUSE_DECL (t);
- tree step = OMP_CLAUSE_LINEAR_STEP (t);
- int argno = TREE_INT_CST_LOW (decl);
- if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
- {
- enum cgraph_simd_clone_arg_type arg_type;
- if (TREE_CODE (args[argno]) == REFERENCE_TYPE)
- switch (OMP_CLAUSE_LINEAR_KIND (t))
- {
- case OMP_CLAUSE_LINEAR_REF:
- arg_type
- = SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP;
- break;
- case OMP_CLAUSE_LINEAR_UVAL:
- arg_type
- = SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP;
- break;
- case OMP_CLAUSE_LINEAR_VAL:
- case OMP_CLAUSE_LINEAR_DEFAULT:
- arg_type
- = SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP;
- break;
- default:
- gcc_unreachable ();
- }
- else
- arg_type = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
- clone_info->args[argno].arg_type = arg_type;
- clone_info->args[argno].linear_step = tree_to_shwi (step);
- gcc_assert (clone_info->args[argno].linear_step >= 0
- && clone_info->args[argno].linear_step < n);
- }
- else
- {
- if (POINTER_TYPE_P (args[argno]))
- step = fold_convert (ssizetype, step);
- if (!tree_fits_shwi_p (step))
- {
- warning_at (OMP_CLAUSE_LOCATION (t), 0,
- "ignoring large linear step");
- args.release ();
- return NULL;
- }
- else if (integer_zerop (step))
- {
- warning_at (OMP_CLAUSE_LOCATION (t), 0,
- "ignoring zero linear step");
- args.release ();
- return NULL;
- }
- else
- {
- enum cgraph_simd_clone_arg_type arg_type;
- if (TREE_CODE (args[argno]) == REFERENCE_TYPE)
- switch (OMP_CLAUSE_LINEAR_KIND (t))
- {
- case OMP_CLAUSE_LINEAR_REF:
- arg_type
- = SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP;
- break;
- case OMP_CLAUSE_LINEAR_UVAL:
- arg_type
- = SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP;
- break;
- case OMP_CLAUSE_LINEAR_VAL:
- case OMP_CLAUSE_LINEAR_DEFAULT:
- arg_type
- = SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP;
- break;
- default:
- gcc_unreachable ();
- }
- else
- arg_type = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
- clone_info->args[argno].arg_type = arg_type;
- clone_info->args[argno].linear_step = tree_to_shwi (step);
- }
- }
- break;
- }
- case OMP_CLAUSE_UNIFORM:
- {
- tree decl = OMP_CLAUSE_DECL (t);
- int argno = tree_to_uhwi (decl);
- clone_info->args[argno].arg_type
- = SIMD_CLONE_ARG_TYPE_UNIFORM;
- break;
- }
- case OMP_CLAUSE_ALIGNED:
- {
- tree decl = OMP_CLAUSE_DECL (t);
- int argno = tree_to_uhwi (decl);
- clone_info->args[argno].alignment
- = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
- break;
- }
- default:
- break;
- }
- }
- args.release ();
- return clone_info;
-}
-
-/* Given a SIMD clone in NODE, calculate the characteristic data
- type and return the coresponding type. The characteristic data
- type is computed as described in the Intel Vector ABI. */
-
-static tree
-simd_clone_compute_base_data_type (struct cgraph_node *node,
- struct cgraph_simd_clone *clone_info)
-{
- tree type = integer_type_node;
- tree fndecl = node->decl;
-
- /* a) For non-void function, the characteristic data type is the
- return type. */
- if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
- type = TREE_TYPE (TREE_TYPE (fndecl));
-
- /* b) If the function has any non-uniform, non-linear parameters,
- then the characteristic data type is the type of the first
- such parameter. */
- else
- {
- vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
- for (unsigned int i = 0; i < clone_info->nargs; ++i)
- if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
- {
- type = map[i];
- break;
- }
- map.release ();
- }
-
- /* c) If the characteristic data type determined by a) or b) above
- is struct, union, or class type which is pass-by-value (except
- for the type that maps to the built-in complex data type), the
- characteristic data type is int. */
- if (RECORD_OR_UNION_TYPE_P (type)
- && !aggregate_value_p (type, NULL)
- && TREE_CODE (type) != COMPLEX_TYPE)
- return integer_type_node;
-
- /* d) If none of the above three classes is applicable, the
- characteristic data type is int. */
-
- return type;
-
- /* e) For Intel Xeon Phi native and offload compilation, if the
- resulting characteristic data type is 8-bit or 16-bit integer
- data type, the characteristic data type is int. */
- /* Well, we don't handle Xeon Phi yet. */
-}
-
-static tree
-simd_clone_mangle (struct cgraph_node *node,
- struct cgraph_simd_clone *clone_info)
-{
- char vecsize_mangle = clone_info->vecsize_mangle;
- char mask = clone_info->inbranch ? 'M' : 'N';
- unsigned int simdlen = clone_info->simdlen;
- unsigned int n;
- pretty_printer pp;
-
- gcc_assert (vecsize_mangle && simdlen);
-
- pp_string (&pp, "_ZGV");
- pp_character (&pp, vecsize_mangle);
- pp_character (&pp, mask);
- pp_decimal_int (&pp, simdlen);
-
- for (n = 0; n < clone_info->nargs; ++n)
- {
- struct cgraph_simd_clone_arg arg = clone_info->args[n];
-
- switch (arg.arg_type)
- {
- case SIMD_CLONE_ARG_TYPE_UNIFORM:
- pp_character (&pp, 'u');
- break;
- case SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP:
- pp_character (&pp, 'l');
- goto mangle_linear;
- case SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP:
- pp_character (&pp, 'R');
- goto mangle_linear;
- case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
- pp_character (&pp, 'L');
- goto mangle_linear;
- case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
- pp_character (&pp, 'U');
- goto mangle_linear;
- mangle_linear:
- gcc_assert (arg.linear_step != 0);
- if (arg.linear_step > 1)
- pp_unsigned_wide_integer (&pp, arg.linear_step);
- else if (arg.linear_step < 0)
- {
- pp_character (&pp, 'n');
- pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
- arg.linear_step));
- }
- break;
- case SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP:
- pp_string (&pp, "ls");
- pp_unsigned_wide_integer (&pp, arg.linear_step);
- break;
- case SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP:
- pp_string (&pp, "Rs");
- pp_unsigned_wide_integer (&pp, arg.linear_step);
- break;
- case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP:
- pp_string (&pp, "Ls");
- pp_unsigned_wide_integer (&pp, arg.linear_step);
- break;
- case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP:
- pp_string (&pp, "Us");
- pp_unsigned_wide_integer (&pp, arg.linear_step);
- break;
- default:
- pp_character (&pp, 'v');
- }
- if (arg.alignment)
- {
- pp_character (&pp, 'a');
- pp_decimal_int (&pp, arg.alignment);
- }
- }
-
- pp_underscore (&pp);
- const char *str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl));
- if (*str == '*')
- ++str;
- pp_string (&pp, str);
- str = pp_formatted_text (&pp);
-
- /* If there already is a SIMD clone with the same mangled name, don't
- add another one. This can happen e.g. for
- #pragma omp declare simd
- #pragma omp declare simd simdlen(8)
- int foo (int, int);
- if the simdlen is assumed to be 8 for the first one, etc. */
- for (struct cgraph_node *clone = node->simd_clones; clone;
- clone = clone->simdclone->next_clone)
- if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
- str) == 0)
- return NULL_TREE;
-
- return get_identifier (str);
-}
-
-/* Create a simd clone of OLD_NODE and return it. */
-
-static struct cgraph_node *
-simd_clone_create (struct cgraph_node *old_node)
-{
- struct cgraph_node *new_node;
- if (old_node->definition)
- {
- if (!old_node->has_gimple_body_p ())
- return NULL;
- old_node->get_body ();
- new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
- false, NULL, NULL,
- "simdclone");
- }
- else
- {
- tree old_decl = old_node->decl;
- tree new_decl = copy_node (old_node->decl);
- DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
- SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
- SET_DECL_RTL (new_decl, NULL);
- DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
- DECL_STATIC_DESTRUCTOR (new_decl) = 0;
- new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
- if (old_node->in_other_partition)
- new_node->in_other_partition = 1;
- }
- if (new_node == NULL)
- return new_node;
-
- TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
-
- /* The function cgraph_function_versioning () will force the new
- symbol local. Undo this, and inherit external visability from
- the old node. */
- new_node->local.local = old_node->local.local;
- new_node->externally_visible = old_node->externally_visible;
-
- return new_node;
-}
-
-/* Adjust the return type of the given function to its appropriate
- vector counterpart. Returns a simd array to be used throughout the
- function as a return value. */
-
-static tree
-simd_clone_adjust_return_type (struct cgraph_node *node)
-{
- tree fndecl = node->decl;
- tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
- unsigned int veclen;
- tree t;
-
- /* Adjust the function return type. */
- if (orig_rettype == void_type_node)
- return NULL_TREE;
- TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
- t = TREE_TYPE (TREE_TYPE (fndecl));
- if (INTEGRAL_TYPE_P (t) || POINTER_TYPE_P (t))
- veclen = node->simdclone->vecsize_int;
- else
- veclen = node->simdclone->vecsize_float;
- veclen /= GET_MODE_BITSIZE (TYPE_MODE (t));
- if (veclen > node->simdclone->simdlen)
- veclen = node->simdclone->simdlen;
- if (POINTER_TYPE_P (t))
- t = pointer_sized_int_node;
- if (veclen == node->simdclone->simdlen)
- t = build_vector_type (t, node->simdclone->simdlen);
- else
- {
- t = build_vector_type (t, veclen);
- t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
- }
- TREE_TYPE (TREE_TYPE (fndecl)) = t;
- if (!node->definition)
- return NULL_TREE;
-
- t = DECL_RESULT (fndecl);
- /* Adjust the DECL_RESULT. */
- gcc_assert (TREE_TYPE (t) != void_type_node);
- TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
- relayout_decl (t);
-
- tree atype = build_array_type_nelts (orig_rettype,
- node->simdclone->simdlen);
- if (veclen != node->simdclone->simdlen)
- return build1 (VIEW_CONVERT_EXPR, atype, t);
-
- /* Set up a SIMD array to use as the return value. */
- tree retval = create_tmp_var_raw (atype, "retval");
- gimple_add_tmp_var (retval);
- return retval;
-}
-
-/* Each vector argument has a corresponding array to be used locally
- as part of the eventual loop. Create such temporary array and
- return it.
-
- PREFIX is the prefix to be used for the temporary.
-
- TYPE is the inner element type.
-
- SIMDLEN is the number of elements. */
-
-static tree
-create_tmp_simd_array (const char *prefix, tree type, int simdlen)
-{
- tree atype = build_array_type_nelts (type, simdlen);
- tree avar = create_tmp_var_raw (atype, prefix);
- gimple_add_tmp_var (avar);
- return avar;
-}
-
-/* Modify the function argument types to their corresponding vector
- counterparts if appropriate. Also, create one array for each simd
- argument to be used locally when using the function arguments as
- part of the loop.
-
- NODE is the function whose arguments are to be adjusted.
-
- Returns an adjustment vector that will be filled describing how the
- argument types will be adjusted. */
-
-static ipa_parm_adjustment_vec
-simd_clone_adjust_argument_types (struct cgraph_node *node)
-{
- vec<tree> args;
- ipa_parm_adjustment_vec adjustments;
-
- if (node->definition)
- args = ipa_get_vector_of_formal_parms (node->decl);
- else
- args = simd_clone_vector_of_formal_parm_types (node->decl);
- adjustments.create (args.length ());
- unsigned i, j, veclen;
- struct ipa_parm_adjustment adj;
- struct cgraph_simd_clone *sc = node->simdclone;
-
- for (i = 0; i < sc->nargs; ++i)
- {
- memset (&adj, 0, sizeof (adj));
- tree parm = args[i];
- tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
- adj.base_index = i;
- adj.base = parm;
-
- sc->args[i].orig_arg = node->definition ? parm : NULL_TREE;
- sc->args[i].orig_type = parm_type;
-
- switch (sc->args[i].arg_type)
- {
- default:
- /* No adjustment necessary for scalar arguments. */
- adj.op = IPA_PARM_OP_COPY;
- break;
- case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
- case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP:
- if (node->definition)
- sc->args[i].simd_array
- = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
- TREE_TYPE (parm_type),
- sc->simdlen);
- adj.op = IPA_PARM_OP_COPY;
- break;
- case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
- case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP:
- case SIMD_CLONE_ARG_TYPE_VECTOR:
- if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
- veclen = sc->vecsize_int;
- else
- veclen = sc->vecsize_float;
- veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
- if (veclen > sc->simdlen)
- veclen = sc->simdlen;
- adj.arg_prefix = "simd";
- if (POINTER_TYPE_P (parm_type))
- adj.type = build_vector_type (pointer_sized_int_node, veclen);
- else
- adj.type = build_vector_type (parm_type, veclen);
- sc->args[i].vector_type = adj.type;
- for (j = veclen; j < sc->simdlen; j += veclen)
- {
- adjustments.safe_push (adj);
- if (j == veclen)
- {
- memset (&adj, 0, sizeof (adj));
- adj.op = IPA_PARM_OP_NEW;
- adj.arg_prefix = "simd";
- adj.base_index = i;
- adj.type = sc->args[i].vector_type;
- }
- }
-
- if (node->definition)
- sc->args[i].simd_array
- = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
- parm_type, sc->simdlen);
- }
- adjustments.safe_push (adj);
- }
-
- if (sc->inbranch)
- {
- tree base_type = simd_clone_compute_base_data_type (sc->origin, sc);
-
- memset (&adj, 0, sizeof (adj));
- adj.op = IPA_PARM_OP_NEW;
- adj.arg_prefix = "mask";
-
- adj.base_index = i;
- if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
- veclen = sc->vecsize_int;
- else
- veclen = sc->vecsize_float;
- veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
- if (veclen > sc->simdlen)
- veclen = sc->simdlen;
- if (sc->mask_mode != VOIDmode)
- adj.type
- = lang_hooks.types.type_for_mode (sc->mask_mode, 1);
- else if (POINTER_TYPE_P (base_type))
- adj.type = build_vector_type (pointer_sized_int_node, veclen);
- else
- adj.type = build_vector_type (base_type, veclen);
- adjustments.safe_push (adj);
-
- for (j = veclen; j < sc->simdlen; j += veclen)
- adjustments.safe_push (adj);
-
- /* We have previously allocated one extra entry for the mask. Use
- it and fill it. */
- sc->nargs++;
- if (sc->mask_mode != VOIDmode)
- base_type = boolean_type_node;
- if (node->definition)
- {
- sc->args[i].orig_arg
- = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
- if (sc->mask_mode == VOIDmode)
- sc->args[i].simd_array
- = create_tmp_simd_array ("mask", base_type, sc->simdlen);
- else if (veclen < sc->simdlen)
- sc->args[i].simd_array
- = create_tmp_simd_array ("mask", adj.type, sc->simdlen / veclen);
- else
- sc->args[i].simd_array = NULL_TREE;
- }
- sc->args[i].orig_type = base_type;
- sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
- }
-
- if (node->definition)
- ipa_modify_formal_parameters (node->decl, adjustments);
- else
- {
- tree new_arg_types = NULL_TREE, new_reversed;
- bool last_parm_void = false;
- if (args.length () > 0 && args.last () == void_type_node)
- last_parm_void = true;
-
- gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
- j = adjustments.length ();
- for (i = 0; i < j; i++)
- {
- struct ipa_parm_adjustment *adj = &adjustments[i];
- tree ptype;
- if (adj->op == IPA_PARM_OP_COPY)
- ptype = args[adj->base_index];
- else
- ptype = adj->type;
- new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
- }
- new_reversed = nreverse (new_arg_types);
- if (last_parm_void)
- {
- if (new_reversed)
- TREE_CHAIN (new_arg_types) = void_list_node;
- else
- new_reversed = void_list_node;
- }
-
- tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
- TYPE_ARG_TYPES (new_type) = new_reversed;
- TREE_TYPE (node->decl) = new_type;
-
- adjustments.release ();
- }
- args.release ();
- return adjustments;
-}
-
-/* Initialize and copy the function arguments in NODE to their
- corresponding local simd arrays. Returns a fresh gimple_seq with
- the instruction sequence generated. */
-
-static gimple_seq
-simd_clone_init_simd_arrays (struct cgraph_node *node,
- ipa_parm_adjustment_vec adjustments)
-{
- gimple_seq seq = NULL;
- unsigned i = 0, j = 0, k;
-
- for (tree arg = DECL_ARGUMENTS (node->decl);
- arg;
- arg = DECL_CHAIN (arg), i++, j++)
- {
- if (adjustments[j].op == IPA_PARM_OP_COPY
- || POINTER_TYPE_P (TREE_TYPE (arg)))
- continue;
-
- node->simdclone->args[i].vector_arg = arg;
-
- tree array = node->simdclone->args[i].simd_array;
- if (node->simdclone->mask_mode != VOIDmode
- && node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_MASK)
- {
- if (array == NULL_TREE)
- continue;
- unsigned int l
- = tree_to_uhwi (TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (array))));
- for (k = 0; k <= l; k++)
- {
- if (k)
- {
- arg = DECL_CHAIN (arg);
- j++;
- }
- tree t = build4 (ARRAY_REF, TREE_TYPE (TREE_TYPE (array)),
- array, size_int (k), NULL, NULL);
- t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
- gimplify_and_add (t, &seq);
- }
- continue;
- }
- if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
- {
- tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
- tree ptr = build_fold_addr_expr (array);
- tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
- build_int_cst (ptype, 0));
- t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
- gimplify_and_add (t, &seq);
- }
- else
- {
- unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
- tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
- for (k = 0; k < node->simdclone->simdlen; k += simdlen)
- {
- tree ptr = build_fold_addr_expr (array);
- int elemsize;
- if (k)
- {
- arg = DECL_CHAIN (arg);
- j++;
- }
- elemsize
- = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
- tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
- build_int_cst (ptype, k * elemsize));
- t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
- gimplify_and_add (t, &seq);
- }
- }
- }
- return seq;
-}
-
-/* Callback info for ipa_simd_modify_stmt_ops below. */
-
-struct modify_stmt_info {
- ipa_parm_adjustment_vec adjustments;
- gimple *stmt;
- /* True if the parent statement was modified by
- ipa_simd_modify_stmt_ops. */
- bool modified;
-};
-
-/* Callback for walk_gimple_op.
-
- Adjust operands from a given statement as specified in the
- adjustments vector in the callback data. */
-
-static tree
-ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
-{
- struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
- struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
- tree *orig_tp = tp;
- if (TREE_CODE (*tp) == ADDR_EXPR)
- tp = &TREE_OPERAND (*tp, 0);
- struct ipa_parm_adjustment *cand = NULL;
- if (TREE_CODE (*tp) == PARM_DECL)
- cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
- else
- {
- if (TYPE_P (*tp))
- *walk_subtrees = 0;
- }
-
- tree repl = NULL_TREE;
- if (cand)
- repl = unshare_expr (cand->new_decl);
- else
- {
- if (tp != orig_tp)
- {
- *walk_subtrees = 0;
- bool modified = info->modified;
- info->modified = false;
- walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
- if (!info->modified)
- {
- info->modified = modified;
- return NULL_TREE;
- }
- info->modified = modified;
- repl = *tp;
- }
- else
- return NULL_TREE;
- }
-
- if (tp != orig_tp)
- {
- repl = build_fold_addr_expr (repl);
- gimple *stmt;
- if (is_gimple_debug (info->stmt))
- {
- tree vexpr = make_node (DEBUG_EXPR_DECL);
- stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
- DECL_ARTIFICIAL (vexpr) = 1;
- TREE_TYPE (vexpr) = TREE_TYPE (repl);
- DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
- repl = vexpr;
- }
- else
- {
- stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl)), repl);
- repl = gimple_assign_lhs (stmt);
- }
- gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
- gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
- *orig_tp = repl;
- }
- else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
- {
- tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
- *tp = vce;
- }
- else
- *tp = repl;
-
- info->modified = true;
- return NULL_TREE;
-}
-
-/* Traverse the function body and perform all modifications as
- described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
- modified such that the replacement/reduction value will now be an
- offset into the corresponding simd_array.
-
- This function will replace all function argument uses with their
- corresponding simd array elements, and ajust the return values
- accordingly. */
-
-static void
-ipa_simd_modify_function_body (struct cgraph_node *node,
- ipa_parm_adjustment_vec adjustments,
- tree retval_array, tree iter)
-{
- basic_block bb;
- unsigned int i, j, l;
-
- /* Re-use the adjustments array, but this time use it to replace
- every function argument use to an offset into the corresponding
- simd_array. */
- for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
- {
- if (!node->simdclone->args[i].vector_arg)
- continue;
-
- tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
- tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
- adjustments[j].new_decl
- = build4 (ARRAY_REF,
- basetype,
- node->simdclone->args[i].simd_array,
- iter,
- NULL_TREE, NULL_TREE);
- if (adjustments[j].op == IPA_PARM_OP_NONE
- && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
- j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
- }
-
- l = adjustments.length ();
- for (i = 1; i < num_ssa_names; i++)
- {
- tree name = ssa_name (i);
- if (name
- && SSA_NAME_VAR (name)
- && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
- {
- for (j = 0; j < l; j++)
- if (SSA_NAME_VAR (name) == adjustments[j].base
- && adjustments[j].new_decl)
- {
- tree base_var;
- if (adjustments[j].new_ssa_base == NULL_TREE)
- {
- base_var
- = copy_var_decl (adjustments[j].base,
- DECL_NAME (adjustments[j].base),
- TREE_TYPE (adjustments[j].base));
- adjustments[j].new_ssa_base = base_var;
- }
- else
- base_var = adjustments[j].new_ssa_base;
- if (SSA_NAME_IS_DEFAULT_DEF (name))
- {
- bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
- gimple_stmt_iterator gsi = gsi_after_labels (bb);
- tree new_decl = unshare_expr (adjustments[j].new_decl);
- set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
- SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
- SSA_NAME_IS_DEFAULT_DEF (name) = 0;
- gimple *stmt = gimple_build_assign (name, new_decl);
- gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
- }
- else
- SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
- }
- }
- }
-
- struct modify_stmt_info info;
- info.adjustments = adjustments;
-
- FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
- {
- gimple_stmt_iterator gsi;
-
- gsi = gsi_start_bb (bb);
- while (!gsi_end_p (gsi))
- {
- gimple *stmt = gsi_stmt (gsi);
- info.stmt = stmt;
- struct walk_stmt_info wi;
-
- memset (&wi, 0, sizeof (wi));
- info.modified = false;
- wi.info = &info;
- walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
-
- if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
- {
- tree retval = gimple_return_retval (return_stmt);
- if (!retval)
- {
- gsi_remove (&gsi, true);
- continue;
- }
-
- /* Replace `return foo' with `retval_array[iter] = foo'. */
- tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
- retval_array, iter, NULL, NULL);
- stmt = gimple_build_assign (ref, retval);
- gsi_replace (&gsi, stmt, true);
- info.modified = true;
- }
-
- if (info.modified)
- {
- update_stmt (stmt);
- if (maybe_clean_eh_stmt (stmt))
- gimple_purge_dead_eh_edges (gimple_bb (stmt));
- }
- gsi_next (&gsi);
- }
- }
-}
-
-/* Helper function of simd_clone_adjust, return linear step addend
- of Ith argument. */
-
-static tree
-simd_clone_linear_addend (struct cgraph_node *node, unsigned int i,
- tree addtype, basic_block entry_bb)
-{
- tree ptype = NULL_TREE;
- switch (node->simdclone->args[i].arg_type)
- {
- case SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP:
- case SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP:
- case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
- case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
- return build_int_cst (addtype, node->simdclone->args[i].linear_step);
- case SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP:
- case SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP:
- ptype = TREE_TYPE (node->simdclone->args[i].orig_arg);
- break;
- case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP:
- case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP:
- ptype = TREE_TYPE (TREE_TYPE (node->simdclone->args[i].orig_arg));
- break;
- default:
- gcc_unreachable ();
- }
-
- unsigned int idx = node->simdclone->args[i].linear_step;
- tree arg = node->simdclone->args[idx].orig_arg;
- gcc_assert (is_gimple_reg_type (TREE_TYPE (arg)));
- gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
- gimple *g;
- tree ret;
- if (is_gimple_reg (arg))
- ret = get_or_create_ssa_default_def (cfun, arg);
- else
- {
- g = gimple_build_assign (make_ssa_name (TREE_TYPE (arg)), arg);
- gsi_insert_before (&gsi, g, GSI_SAME_STMT);
- ret = gimple_assign_lhs (g);
- }
- if (TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE)
- {
- g = gimple_build_assign (make_ssa_name (TREE_TYPE (TREE_TYPE (arg))),
- build_simple_mem_ref (ret));
- gsi_insert_before (&gsi, g, GSI_SAME_STMT);
- ret = gimple_assign_lhs (g);
- }
- if (!useless_type_conversion_p (addtype, TREE_TYPE (ret)))
- {
- g = gimple_build_assign (make_ssa_name (addtype), NOP_EXPR, ret);
- gsi_insert_before (&gsi, g, GSI_SAME_STMT);
- ret = gimple_assign_lhs (g);
- }
- if (POINTER_TYPE_P (ptype))
- {
- tree size = TYPE_SIZE_UNIT (TREE_TYPE (ptype));
- if (size && TREE_CODE (size) == INTEGER_CST)
- {
- g = gimple_build_assign (make_ssa_name (addtype), MULT_EXPR,
- ret, fold_convert (addtype, size));
- gsi_insert_before (&gsi, g, GSI_SAME_STMT);
- ret = gimple_assign_lhs (g);
- }
- }
- return ret;
-}
-
-/* Adjust the argument types in NODE to their appropriate vector
- counterparts. */
-
-static void
-simd_clone_adjust (struct cgraph_node *node)
-{
- push_cfun (DECL_STRUCT_FUNCTION (node->decl));
-
- targetm.simd_clone.adjust (node);
-
- tree retval = simd_clone_adjust_return_type (node);
- ipa_parm_adjustment_vec adjustments
- = simd_clone_adjust_argument_types (node);
-
- push_gimplify_context ();
-
- gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
-
- /* Adjust all uses of vector arguments accordingly. Adjust all
- return values accordingly. */
- tree iter = create_tmp_var (unsigned_type_node, "iter");
- tree iter1 = make_ssa_name (iter);
- tree iter2 = make_ssa_name (iter);
- ipa_simd_modify_function_body (node, adjustments, retval, iter1);
-
- /* Initialize the iteration variable. */
- basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
- basic_block body_bb = split_block_after_labels (entry_bb)->dest;
- gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
- /* Insert the SIMD array and iv initialization at function
- entry. */
- gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
-
- pop_gimplify_context (NULL);
-
- /* Create a new BB right before the original exit BB, to hold the
- iteration increment and the condition/branch. */
- basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
- basic_block incr_bb = create_empty_bb (orig_exit);
- add_bb_to_loop (incr_bb, body_bb->loop_father);
- /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
- flag. Set it now to be a FALLTHRU_EDGE. */
- gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
- EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
- for (unsigned i = 0;
- i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
- {
- edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
- redirect_edge_succ (e, incr_bb);
- }
- edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
- e->probability = REG_BR_PROB_BASE;
- gsi = gsi_last_bb (incr_bb);
- gimple *g = gimple_build_assign (iter2, PLUS_EXPR, iter1,
- build_int_cst (unsigned_type_node, 1));
- gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
-
- /* Mostly annotate the loop for the vectorizer (the rest is done below). */
- struct loop *loop = alloc_loop ();
- cfun->has_force_vectorize_loops = true;
- loop->safelen = node->simdclone->simdlen;
- loop->force_vectorize = true;
- loop->header = body_bb;
-
- /* Branch around the body if the mask applies. */
- if (node->simdclone->inbranch)
- {
- gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
- tree mask_array
- = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
- tree mask;
- if (node->simdclone->mask_mode != VOIDmode)
- {
- tree shift_cnt;
- if (mask_array == NULL_TREE)
- {
- tree arg = node->simdclone->args[node->simdclone->nargs
- - 1].vector_arg;
- mask = get_or_create_ssa_default_def (cfun, arg);
- shift_cnt = iter1;
- }
- else
- {
- tree maskt = TREE_TYPE (mask_array);
- int c = tree_to_uhwi (TYPE_MAX_VALUE (TYPE_DOMAIN (maskt)));
- c = node->simdclone->simdlen / (c + 1);
- int s = exact_log2 (c);
- gcc_assert (s > 0);
- c--;
- tree idx = make_ssa_name (TREE_TYPE (iter1));
- g = gimple_build_assign (idx, RSHIFT_EXPR, iter1,
- build_int_cst (NULL_TREE, s));
- gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
- mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)));
- tree aref = build4 (ARRAY_REF,
- TREE_TYPE (TREE_TYPE (mask_array)),
- mask_array, idx, NULL, NULL);
- g = gimple_build_assign (mask, aref);
- gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
- shift_cnt = make_ssa_name (TREE_TYPE (iter1));
- g = gimple_build_assign (shift_cnt, BIT_AND_EXPR, iter1,
- build_int_cst (TREE_TYPE (iter1), c));
- gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
- }
- g = gimple_build_assign (make_ssa_name (TREE_TYPE (mask)),
- RSHIFT_EXPR, mask, shift_cnt);
- gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
- mask = gimple_assign_lhs (g);
- g = gimple_build_assign (make_ssa_name (TREE_TYPE (mask)),
- BIT_AND_EXPR, mask,
- build_int_cst (TREE_TYPE (mask), 1));
- gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
- mask = gimple_assign_lhs (g);
- }
- else
- {
- mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)));
- tree aref = build4 (ARRAY_REF,
- TREE_TYPE (TREE_TYPE (mask_array)),
- mask_array, iter1, NULL, NULL);
- g = gimple_build_assign (mask, aref);
- gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
- int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
- if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
- {
- aref = build1 (VIEW_CONVERT_EXPR,
- build_nonstandard_integer_type (bitsize, 0),
- mask);
- mask = make_ssa_name (TREE_TYPE (aref));
- g = gimple_build_assign (mask, aref);
- gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
- }
- }
-
- g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
- NULL, NULL);
- gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
- make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
- FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
- }
-
- /* Generate the condition. */
- g = gimple_build_cond (LT_EXPR,
- iter2,
- build_int_cst (unsigned_type_node,
- node->simdclone->simdlen),
- NULL, NULL);
- gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
- e = split_block (incr_bb, gsi_stmt (gsi));
- basic_block latch_bb = e->dest;
- basic_block new_exit_bb;
- new_exit_bb = split_block_after_labels (latch_bb)->dest;
- loop->latch = latch_bb;
-
- redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
-
- make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
- /* The successor of incr_bb is already pointing to latch_bb; just
- change the flags.
- make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
- FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
-
- gphi *phi = create_phi_node (iter1, body_bb);
- edge preheader_edge = find_edge (entry_bb, body_bb);
- edge latch_edge = single_succ_edge (latch_bb);
- add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
- UNKNOWN_LOCATION);
- add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
-
- /* Generate the new return. */
- gsi = gsi_last_bb (new_exit_bb);
- if (retval
- && TREE_CODE (retval) == VIEW_CONVERT_EXPR
- && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
- retval = TREE_OPERAND (retval, 0);
- else if (retval)
- {
- retval = build1 (VIEW_CONVERT_EXPR,
- TREE_TYPE (TREE_TYPE (node->decl)),
- retval);
- retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
- false, GSI_CONTINUE_LINKING);
- }
- g = gimple_build_return (retval);
- gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
-
- /* Handle aligned clauses by replacing default defs of the aligned
- uniform args with __builtin_assume_aligned (arg_N(D), alignment)
- lhs. Handle linear by adding PHIs. */
- for (unsigned i = 0; i < node->simdclone->nargs; i++)
- if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
- && (TREE_ADDRESSABLE (node->simdclone->args[i].orig_arg)
- || !is_gimple_reg_type
- (TREE_TYPE (node->simdclone->args[i].orig_arg))))
- {
- tree orig_arg = node->simdclone->args[i].orig_arg;
- if (is_gimple_reg_type (TREE_TYPE (orig_arg)))
- iter1 = make_ssa_name (TREE_TYPE (orig_arg));
- else
- {
- iter1 = create_tmp_var_raw (TREE_TYPE (orig_arg));
- gimple_add_tmp_var (iter1);
- }
- gsi = gsi_after_labels (entry_bb);
- g = gimple_build_assign (iter1, orig_arg);
- gsi_insert_before (&gsi, g, GSI_NEW_STMT);
- gsi = gsi_after_labels (body_bb);
- g = gimple_build_assign (orig_arg, iter1);
- gsi_insert_before (&gsi, g, GSI_NEW_STMT);
- }
- else if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
- && DECL_BY_REFERENCE (node->simdclone->args[i].orig_arg)
- && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
- == REFERENCE_TYPE
- && TREE_ADDRESSABLE
- (TREE_TYPE (TREE_TYPE (node->simdclone->args[i].orig_arg))))
- {
- tree orig_arg = node->simdclone->args[i].orig_arg;
- tree def = ssa_default_def (cfun, orig_arg);
- if (def && !has_zero_uses (def))
- {
- iter1 = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (orig_arg)));
- gimple_add_tmp_var (iter1);
- gsi = gsi_after_labels (entry_bb);
- g = gimple_build_assign (iter1, build_simple_mem_ref (def));
- gsi_insert_before (&gsi, g, GSI_NEW_STMT);
- gsi = gsi_after_labels (body_bb);
- g = gimple_build_assign (build_simple_mem_ref (def), iter1);
- gsi_insert_before (&gsi, g, GSI_NEW_STMT);
- }
- }
- else if (node->simdclone->args[i].alignment
- && node->simdclone->args[i].arg_type
- == SIMD_CLONE_ARG_TYPE_UNIFORM
- && (node->simdclone->args[i].alignment
- & (node->simdclone->args[i].alignment - 1)) == 0
- && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
- == POINTER_TYPE)
- {
- unsigned int alignment = node->simdclone->args[i].alignment;
- tree orig_arg = node->simdclone->args[i].orig_arg;
- tree def = ssa_default_def (cfun, orig_arg);
- if (def && !has_zero_uses (def))
- {
- tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
- gimple_seq seq = NULL;
- bool need_cvt = false;
- gcall *call
- = gimple_build_call (fn, 2, def, size_int (alignment));
- g = call;
- if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
- ptr_type_node))
- need_cvt = true;
- tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg);
- gimple_call_set_lhs (g, t);
- gimple_seq_add_stmt_without_update (&seq, g);
- if (need_cvt)
- {
- t = make_ssa_name (orig_arg);
- g = gimple_build_assign (t, NOP_EXPR, gimple_call_lhs (g));
- gimple_seq_add_stmt_without_update (&seq, g);
- }
- gsi_insert_seq_on_edge_immediate
- (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
-
- entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
- int freq = compute_call_stmt_bb_frequency (current_function_decl,
- entry_bb);
- node->create_edge (cgraph_node::get_create (fn),
- call, entry_bb->count, freq);
-
- imm_use_iterator iter;
- use_operand_p use_p;
- gimple *use_stmt;
- tree repl = gimple_get_lhs (g);
- FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
- if (is_gimple_debug (use_stmt) || use_stmt == call)
- continue;
- else
- FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
- SET_USE (use_p, repl);
- }
- }
- else if ((node->simdclone->args[i].arg_type
- == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
- || (node->simdclone->args[i].arg_type
- == SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP)
- || (node->simdclone->args[i].arg_type
- == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
- || (node->simdclone->args[i].arg_type
- == SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP))
- {
- tree orig_arg = node->simdclone->args[i].orig_arg;
- gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
- || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
- tree def = NULL_TREE;
- if (TREE_ADDRESSABLE (orig_arg))
- {
- def = make_ssa_name (TREE_TYPE (orig_arg));
- iter1 = make_ssa_name (TREE_TYPE (orig_arg));
- iter2 = make_ssa_name (TREE_TYPE (orig_arg));
- gsi = gsi_after_labels (entry_bb);
- g = gimple_build_assign (def, orig_arg);
- gsi_insert_before (&gsi, g, GSI_NEW_STMT);
- }
- else
- {
- def = ssa_default_def (cfun, orig_arg);
- if (!def || has_zero_uses (def))
- def = NULL_TREE;
- else
- {
- iter1 = make_ssa_name (orig_arg);
- iter2 = make_ssa_name (orig_arg);
- }
- }
- if (def)
- {
- phi = create_phi_node (iter1, body_bb);
- add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
- add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
- enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
- ? PLUS_EXPR : POINTER_PLUS_EXPR;
- tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
- ? TREE_TYPE (orig_arg) : sizetype;
- tree addcst = simd_clone_linear_addend (node, i, addtype,
- entry_bb);
- gsi = gsi_last_bb (incr_bb);
- g = gimple_build_assign (iter2, code, iter1, addcst);
- gsi_insert_before (&gsi, g, GSI_SAME_STMT);
-
- imm_use_iterator iter;
- use_operand_p use_p;
- gimple *use_stmt;
- if (TREE_ADDRESSABLE (orig_arg))
- {
- gsi = gsi_after_labels (body_bb);
- g = gimple_build_assign (orig_arg, iter1);
- gsi_insert_before (&gsi, g, GSI_NEW_STMT);
- }
- else
- FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
- if (use_stmt == phi)
- continue;
- else
- FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
- SET_USE (use_p, iter1);
- }
- }
- else if (node->simdclone->args[i].arg_type
- == SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP
- || (node->simdclone->args[i].arg_type
- == SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP))
- {
- tree orig_arg = node->simdclone->args[i].orig_arg;
- tree def = ssa_default_def (cfun, orig_arg);
- gcc_assert (!TREE_ADDRESSABLE (orig_arg)
- && TREE_CODE (TREE_TYPE (orig_arg)) == REFERENCE_TYPE);
- if (def && !has_zero_uses (def))
- {
- tree rtype = TREE_TYPE (TREE_TYPE (orig_arg));
- iter1 = make_ssa_name (orig_arg);
- iter2 = make_ssa_name (orig_arg);
- tree iter3 = make_ssa_name (rtype);
- tree iter4 = make_ssa_name (rtype);
- tree iter5 = make_ssa_name (rtype);
- gsi = gsi_after_labels (entry_bb);
- gimple *load
- = gimple_build_assign (iter3, build_simple_mem_ref (def));
- gsi_insert_before (&gsi, load, GSI_NEW_STMT);
-
- tree array = node->simdclone->args[i].simd_array;
- TREE_ADDRESSABLE (array) = 1;
- tree ptr = build_fold_addr_expr (array);
- phi = create_phi_node (iter1, body_bb);
- add_phi_arg (phi, ptr, preheader_edge, UNKNOWN_LOCATION);
- add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
- g = gimple_build_assign (iter2, POINTER_PLUS_EXPR, iter1,
- TYPE_SIZE_UNIT (TREE_TYPE (iter3)));
- gsi = gsi_last_bb (incr_bb);
- gsi_insert_before (&gsi, g, GSI_SAME_STMT);
-
- phi = create_phi_node (iter4, body_bb);
- add_phi_arg (phi, iter3, preheader_edge, UNKNOWN_LOCATION);
- add_phi_arg (phi, iter5, latch_edge, UNKNOWN_LOCATION);
- enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (iter3))
- ? PLUS_EXPR : POINTER_PLUS_EXPR;
- tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (iter3))
- ? TREE_TYPE (iter3) : sizetype;
- tree addcst = simd_clone_linear_addend (node, i, addtype,
- entry_bb);
- g = gimple_build_assign (iter5, code, iter4, addcst);
- gsi = gsi_last_bb (incr_bb);
- gsi_insert_before (&gsi, g, GSI_SAME_STMT);
-
- g = gimple_build_assign (build_simple_mem_ref (iter1), iter4);
- gsi = gsi_after_labels (body_bb);
- gsi_insert_before (&gsi, g, GSI_SAME_STMT);
-
- imm_use_iterator iter;
- use_operand_p use_p;
- gimple *use_stmt;
- FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
- if (use_stmt == load)
- continue;
- else
- FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
- SET_USE (use_p, iter1);
-
- if (!TYPE_READONLY (rtype))
- {
- tree v = make_ssa_name (rtype);
- tree aref = build4 (ARRAY_REF, rtype, array,
- size_zero_node, NULL_TREE,
- NULL_TREE);
- gsi = gsi_after_labels (new_exit_bb);
- g = gimple_build_assign (v, aref);
- gsi_insert_before (&gsi, g, GSI_SAME_STMT);
- g = gimple_build_assign (build_simple_mem_ref (def), v);
- gsi_insert_before (&gsi, g, GSI_SAME_STMT);
- }
- }
- }
-
- calculate_dominance_info (CDI_DOMINATORS);
- add_loop (loop, loop->header->loop_father);
- update_ssa (TODO_update_ssa);
-
- pop_cfun ();
-}
-
-/* If the function in NODE is tagged as an elemental SIMD function,
- create the appropriate SIMD clones. */
-
-static void
-expand_simd_clones (struct cgraph_node *node)
-{
- tree attr = lookup_attribute ("omp declare simd",
- DECL_ATTRIBUTES (node->decl));
- if (attr == NULL_TREE
- || node->global.inlined_to
- || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
- return;
-
- /* Ignore
- #pragma omp declare simd
- extern int foo ();
- in C, there we don't know the argument types at all. */
- if (!node->definition
- && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
- return;
-
- /* Call this before creating clone_info, as it might ggc_collect. */
- if (node->definition && node->has_gimple_body_p ())
- node->get_body ();
-
- do
- {
- /* Start with parsing the "omp declare simd" attribute(s). */
- bool inbranch_clause_specified;
- struct cgraph_simd_clone *clone_info
- = simd_clone_clauses_extract (node, TREE_VALUE (attr),
- &inbranch_clause_specified);
- if (clone_info == NULL)
- continue;
-
- int orig_simdlen = clone_info->simdlen;
- tree base_type = simd_clone_compute_base_data_type (node, clone_info);
- /* The target can return 0 (no simd clones should be created),
- 1 (just one ISA of simd clones should be created) or higher
- count of ISA variants. In that case, clone_info is initialized
- for the first ISA variant. */
- int count
- = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
- base_type, 0);
- if (count == 0)
- continue;
-
- /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
- also create one inbranch and one !inbranch clone of it. */
- for (int i = 0; i < count * 2; i++)
- {
- struct cgraph_simd_clone *clone = clone_info;
- if (inbranch_clause_specified && (i & 1) != 0)
- continue;
-
- if (i != 0)
- {
- clone = simd_clone_struct_alloc (clone_info->nargs
- + ((i & 1) != 0));
- simd_clone_struct_copy (clone, clone_info);
- /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
- and simd_clone_adjust_argument_types did to the first
- clone's info. */
- clone->nargs -= clone_info->inbranch;
- clone->simdlen = orig_simdlen;
- /* And call the target hook again to get the right ISA. */
- targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
- base_type,
- i / 2);
- if ((i & 1) != 0)
- clone->inbranch = 1;
- }
-
- /* simd_clone_mangle might fail if such a clone has been created
- already. */
- tree id = simd_clone_mangle (node, clone);
- if (id == NULL_TREE)
- continue;
-
- /* Only when we are sure we want to create the clone actually
- clone the function (or definitions) or create another
- extern FUNCTION_DECL (for prototypes without definitions). */
- struct cgraph_node *n = simd_clone_create (node);
- if (n == NULL)
- continue;
-
- n->simdclone = clone;
- clone->origin = node;
- clone->next_clone = NULL;
- if (node->simd_clones == NULL)
- {
- clone->prev_clone = n;
- node->simd_clones = n;
- }
- else
- {
- clone->prev_clone = node->simd_clones->simdclone->prev_clone;
- clone->prev_clone->simdclone->next_clone = n;
- node->simd_clones->simdclone->prev_clone = n;
- }
- symtab->change_decl_assembler_name (n->decl, id);
- /* And finally adjust the return type, parameters and for
- definitions also function body. */
- if (node->definition)
- simd_clone_adjust (n);
- else
- {
- simd_clone_adjust_return_type (n);
- simd_clone_adjust_argument_types (n);
- }
- }
- }
- while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
-}
-
-/* Entry point for IPA simd clone creation pass. */
-
-static unsigned int
-ipa_omp_simd_clone (void)
-{
- struct cgraph_node *node;
- FOR_EACH_FUNCTION (node)
- expand_simd_clones (node);
- return 0;
-}
-
-namespace {
-
-const pass_data pass_data_omp_simd_clone =
-{
- SIMPLE_IPA_PASS, /* type */
- "simdclone", /* name */
- OPTGROUP_NONE, /* optinfo_flags */
- TV_NONE, /* tv_id */
- ( PROP_ssa | PROP_cfg ), /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- 0, /* todo_flags_finish */
-};
-
-class pass_omp_simd_clone : public simple_ipa_opt_pass
-{
-public:
- pass_omp_simd_clone(gcc::context *ctxt)
- : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
- {}
-
- /* opt_pass methods: */
- virtual bool gate (function *);
- virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
-};
-
-bool
-pass_omp_simd_clone::gate (function *)
-{
- return targetm.simd_clone.compute_vecsize_and_simdlen != NULL;
-}
-
-} // anon namespace
-
-simple_ipa_opt_pass *
-make_pass_omp_simd_clone (gcc::context *ctxt)
-{
- return new pass_omp_simd_clone (ctxt);
-}
-
/* Helper function for omp_finish_file routine. Takes decls from V_DECLS and
adds their addresses and sizes to constructor-vector V_CTOR. */
static void
diff --git a/gcc/omp-simd-clone.c b/gcc/omp-simd-clone.c
new file mode 100644
index 00000000000..fa6ffecb4c2
--- /dev/null
+++ b/gcc/omp-simd-clone.c
@@ -0,0 +1,1654 @@
+/* OMP constructs' SIMD clone supporting code.
+
+Copyright (C) 2005-2016 Free Software Foundation, Inc.
+
+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 "backend.h"
+#include "target.h"
+#include "tree.h"
+#include "gimple.h"
+#include "cfghooks.h"
+#include "alloc-pool.h"
+#include "tree-pass.h"
+#include "ssa.h"
+#include "cgraph.h"
+#include "pretty-print.h"
+#include "diagnostic-core.h"
+#include "fold-const.h"
+#include "stor-layout.h"
+#include "cfganal.h"
+#include "gimplify.h"
+#include "gimple-iterator.h"
+#include "gimplify-me.h"
+#include "gimple-walk.h"
+#include "langhooks.h"
+#include "tree-cfg.h"
+#include "tree-into-ssa.h"
+#include "tree-dfa.h"
+#include "cfgloop.h"
+#include "symbol-summary.h"
+#include "ipa-prop.h"
+#include "tree-eh.h"
+
+
+/* Allocate a fresh `simd_clone' and return it. NARGS is the number
+ of arguments to reserve space for. */
+
+static struct cgraph_simd_clone *
+simd_clone_struct_alloc (int nargs)
+{
+ struct cgraph_simd_clone *clone_info;
+ size_t len = (sizeof (struct cgraph_simd_clone)
+ + nargs * sizeof (struct cgraph_simd_clone_arg));
+ clone_info = (struct cgraph_simd_clone *)
+ ggc_internal_cleared_alloc (len);
+ return clone_info;
+}
+
+/* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */
+
+static inline void
+simd_clone_struct_copy (struct cgraph_simd_clone *to,
+ struct cgraph_simd_clone *from)
+{
+ memcpy (to, from, (sizeof (struct cgraph_simd_clone)
+ + ((from->nargs - from->inbranch)
+ * sizeof (struct cgraph_simd_clone_arg))));
+}
+
+/* Return vector of parameter types of function FNDECL. This uses
+ TYPE_ARG_TYPES if available, otherwise falls back to types of
+ DECL_ARGUMENTS types. */
+
+static vec<tree>
+simd_clone_vector_of_formal_parm_types (tree fndecl)
+{
+ if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
+ return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl));
+ vec<tree> args = ipa_get_vector_of_formal_parms (fndecl);
+ unsigned int i;
+ tree arg;
+ FOR_EACH_VEC_ELT (args, i, arg)
+ args[i] = TREE_TYPE (args[i]);
+ return args;
+}
+
+/* Given a simd function in NODE, extract the simd specific
+ information from the OMP clauses passed in CLAUSES, and return
+ the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED
+ is set to TRUE if the `inbranch' or `notinbranch' clause specified,
+ otherwise set to FALSE. */
+
+static struct cgraph_simd_clone *
+simd_clone_clauses_extract (struct cgraph_node *node, tree clauses,
+ bool *inbranch_specified)
+{
+ vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl);
+ tree t;
+ int n;
+ *inbranch_specified = false;
+
+ n = args.length ();
+ if (n > 0 && args.last () == void_type_node)
+ n--;
+
+ /* To distinguish from an OpenMP simd clone, Cilk Plus functions to
+ be cloned have a distinctive artificial label in addition to "omp
+ declare simd". */
+ bool cilk_clone
+ = (flag_cilkplus
+ && lookup_attribute ("cilk simd function",
+ DECL_ATTRIBUTES (node->decl)));
+
+ /* Allocate one more than needed just in case this is an in-branch
+ clone which will require a mask argument. */
+ struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1);
+ clone_info->nargs = n;
+ clone_info->cilk_elemental = cilk_clone;
+
+ if (!clauses)
+ {
+ args.release ();
+ return clone_info;
+ }
+ clauses = TREE_VALUE (clauses);
+ if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE)
+ return clone_info;
+
+ for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
+ {
+ switch (OMP_CLAUSE_CODE (t))
+ {
+ case OMP_CLAUSE_INBRANCH:
+ clone_info->inbranch = 1;
+ *inbranch_specified = true;
+ break;
+ case OMP_CLAUSE_NOTINBRANCH:
+ clone_info->inbranch = 0;
+ *inbranch_specified = true;
+ break;
+ case OMP_CLAUSE_SIMDLEN:
+ clone_info->simdlen
+ = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t));
+ break;
+ case OMP_CLAUSE_LINEAR:
+ {
+ tree decl = OMP_CLAUSE_DECL (t);
+ tree step = OMP_CLAUSE_LINEAR_STEP (t);
+ int argno = TREE_INT_CST_LOW (decl);
+ if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t))
+ {
+ enum cgraph_simd_clone_arg_type arg_type;
+ if (TREE_CODE (args[argno]) == REFERENCE_TYPE)
+ switch (OMP_CLAUSE_LINEAR_KIND (t))
+ {
+ case OMP_CLAUSE_LINEAR_REF:
+ arg_type
+ = SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP;
+ break;
+ case OMP_CLAUSE_LINEAR_UVAL:
+ arg_type
+ = SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP;
+ break;
+ case OMP_CLAUSE_LINEAR_VAL:
+ case OMP_CLAUSE_LINEAR_DEFAULT:
+ arg_type
+ = SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ else
+ arg_type = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP;
+ clone_info->args[argno].arg_type = arg_type;
+ clone_info->args[argno].linear_step = tree_to_shwi (step);
+ gcc_assert (clone_info->args[argno].linear_step >= 0
+ && clone_info->args[argno].linear_step < n);
+ }
+ else
+ {
+ if (POINTER_TYPE_P (args[argno]))
+ step = fold_convert (ssizetype, step);
+ if (!tree_fits_shwi_p (step))
+ {
+ warning_at (OMP_CLAUSE_LOCATION (t), 0,
+ "ignoring large linear step");
+ args.release ();
+ return NULL;
+ }
+ else if (integer_zerop (step))
+ {
+ warning_at (OMP_CLAUSE_LOCATION (t), 0,
+ "ignoring zero linear step");
+ args.release ();
+ return NULL;
+ }
+ else
+ {
+ enum cgraph_simd_clone_arg_type arg_type;
+ if (TREE_CODE (args[argno]) == REFERENCE_TYPE)
+ switch (OMP_CLAUSE_LINEAR_KIND (t))
+ {
+ case OMP_CLAUSE_LINEAR_REF:
+ arg_type
+ = SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP;
+ break;
+ case OMP_CLAUSE_LINEAR_UVAL:
+ arg_type
+ = SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP;
+ break;
+ case OMP_CLAUSE_LINEAR_VAL:
+ case OMP_CLAUSE_LINEAR_DEFAULT:
+ arg_type
+ = SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ else
+ arg_type = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP;
+ clone_info->args[argno].arg_type = arg_type;
+ clone_info->args[argno].linear_step = tree_to_shwi (step);
+ }
+ }
+ break;
+ }
+ case OMP_CLAUSE_UNIFORM:
+ {
+ tree decl = OMP_CLAUSE_DECL (t);
+ int argno = tree_to_uhwi (decl);
+ clone_info->args[argno].arg_type
+ = SIMD_CLONE_ARG_TYPE_UNIFORM;
+ break;
+ }
+ case OMP_CLAUSE_ALIGNED:
+ {
+ tree decl = OMP_CLAUSE_DECL (t);
+ int argno = tree_to_uhwi (decl);
+ clone_info->args[argno].alignment
+ = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t));
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ args.release ();
+ return clone_info;
+}
+
+/* Given a SIMD clone in NODE, calculate the characteristic data
+ type and return the coresponding type. The characteristic data
+ type is computed as described in the Intel Vector ABI. */
+
+static tree
+simd_clone_compute_base_data_type (struct cgraph_node *node,
+ struct cgraph_simd_clone *clone_info)
+{
+ tree type = integer_type_node;
+ tree fndecl = node->decl;
+
+ /* a) For non-void function, the characteristic data type is the
+ return type. */
+ if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE)
+ type = TREE_TYPE (TREE_TYPE (fndecl));
+
+ /* b) If the function has any non-uniform, non-linear parameters,
+ then the characteristic data type is the type of the first
+ such parameter. */
+ else
+ {
+ vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl);
+ for (unsigned int i = 0; i < clone_info->nargs; ++i)
+ if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR)
+ {
+ type = map[i];
+ break;
+ }
+ map.release ();
+ }
+
+ /* c) If the characteristic data type determined by a) or b) above
+ is struct, union, or class type which is pass-by-value (except
+ for the type that maps to the built-in complex data type), the
+ characteristic data type is int. */
+ if (RECORD_OR_UNION_TYPE_P (type)
+ && !aggregate_value_p (type, NULL)
+ && TREE_CODE (type) != COMPLEX_TYPE)
+ return integer_type_node;
+
+ /* d) If none of the above three classes is applicable, the
+ characteristic data type is int. */
+
+ return type;
+
+ /* e) For Intel Xeon Phi native and offload compilation, if the
+ resulting characteristic data type is 8-bit or 16-bit integer
+ data type, the characteristic data type is int. */
+ /* Well, we don't handle Xeon Phi yet. */
+}
+
+static tree
+simd_clone_mangle (struct cgraph_node *node,
+ struct cgraph_simd_clone *clone_info)
+{
+ char vecsize_mangle = clone_info->vecsize_mangle;
+ char mask = clone_info->inbranch ? 'M' : 'N';
+ unsigned int simdlen = clone_info->simdlen;
+ unsigned int n;
+ pretty_printer pp;
+
+ gcc_assert (vecsize_mangle && simdlen);
+
+ pp_string (&pp, "_ZGV");
+ pp_character (&pp, vecsize_mangle);
+ pp_character (&pp, mask);
+ pp_decimal_int (&pp, simdlen);
+
+ for (n = 0; n < clone_info->nargs; ++n)
+ {
+ struct cgraph_simd_clone_arg arg = clone_info->args[n];
+
+ switch (arg.arg_type)
+ {
+ case SIMD_CLONE_ARG_TYPE_UNIFORM:
+ pp_character (&pp, 'u');
+ break;
+ case SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP:
+ pp_character (&pp, 'l');
+ goto mangle_linear;
+ case SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP:
+ pp_character (&pp, 'R');
+ goto mangle_linear;
+ case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
+ pp_character (&pp, 'L');
+ goto mangle_linear;
+ case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
+ pp_character (&pp, 'U');
+ goto mangle_linear;
+ mangle_linear:
+ gcc_assert (arg.linear_step != 0);
+ if (arg.linear_step > 1)
+ pp_unsigned_wide_integer (&pp, arg.linear_step);
+ else if (arg.linear_step < 0)
+ {
+ pp_character (&pp, 'n');
+ pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT)
+ arg.linear_step));
+ }
+ break;
+ case SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP:
+ pp_string (&pp, "ls");
+ pp_unsigned_wide_integer (&pp, arg.linear_step);
+ break;
+ case SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP:
+ pp_string (&pp, "Rs");
+ pp_unsigned_wide_integer (&pp, arg.linear_step);
+ break;
+ case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP:
+ pp_string (&pp, "Ls");
+ pp_unsigned_wide_integer (&pp, arg.linear_step);
+ break;
+ case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP:
+ pp_string (&pp, "Us");
+ pp_unsigned_wide_integer (&pp, arg.linear_step);
+ break;
+ default:
+ pp_character (&pp, 'v');
+ }
+ if (arg.alignment)
+ {
+ pp_character (&pp, 'a');
+ pp_decimal_int (&pp, arg.alignment);
+ }
+ }
+
+ pp_underscore (&pp);
+ const char *str = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl));
+ if (*str == '*')
+ ++str;
+ pp_string (&pp, str);
+ str = pp_formatted_text (&pp);
+
+ /* If there already is a SIMD clone with the same mangled name, don't
+ add another one. This can happen e.g. for
+ #pragma omp declare simd
+ #pragma omp declare simd simdlen(8)
+ int foo (int, int);
+ if the simdlen is assumed to be 8 for the first one, etc. */
+ for (struct cgraph_node *clone = node->simd_clones; clone;
+ clone = clone->simdclone->next_clone)
+ if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)),
+ str) == 0)
+ return NULL_TREE;
+
+ return get_identifier (str);
+}
+
+/* Create a simd clone of OLD_NODE and return it. */
+
+static struct cgraph_node *
+simd_clone_create (struct cgraph_node *old_node)
+{
+ struct cgraph_node *new_node;
+ if (old_node->definition)
+ {
+ if (!old_node->has_gimple_body_p ())
+ return NULL;
+ old_node->get_body ();
+ new_node = old_node->create_version_clone_with_body (vNULL, NULL, NULL,
+ false, NULL, NULL,
+ "simdclone");
+ }
+ else
+ {
+ tree old_decl = old_node->decl;
+ tree new_decl = copy_node (old_node->decl);
+ DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone");
+ SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl));
+ SET_DECL_RTL (new_decl, NULL);
+ DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
+ DECL_STATIC_DESTRUCTOR (new_decl) = 0;
+ new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
+ if (old_node->in_other_partition)
+ new_node->in_other_partition = 1;
+ }
+ if (new_node == NULL)
+ return new_node;
+
+ TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl);
+
+ /* The function cgraph_function_versioning () will force the new
+ symbol local. Undo this, and inherit external visability from
+ the old node. */
+ new_node->local.local = old_node->local.local;
+ new_node->externally_visible = old_node->externally_visible;
+
+ return new_node;
+}
+
+/* Adjust the return type of the given function to its appropriate
+ vector counterpart. Returns a simd array to be used throughout the
+ function as a return value. */
+
+static tree
+simd_clone_adjust_return_type (struct cgraph_node *node)
+{
+ tree fndecl = node->decl;
+ tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl));
+ unsigned int veclen;
+ tree t;
+
+ /* Adjust the function return type. */
+ if (orig_rettype == void_type_node)
+ return NULL_TREE;
+ TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl));
+ t = TREE_TYPE (TREE_TYPE (fndecl));
+ if (INTEGRAL_TYPE_P (t) || POINTER_TYPE_P (t))
+ veclen = node->simdclone->vecsize_int;
+ else
+ veclen = node->simdclone->vecsize_float;
+ veclen /= GET_MODE_BITSIZE (TYPE_MODE (t));
+ if (veclen > node->simdclone->simdlen)
+ veclen = node->simdclone->simdlen;
+ if (POINTER_TYPE_P (t))
+ t = pointer_sized_int_node;
+ if (veclen == node->simdclone->simdlen)
+ t = build_vector_type (t, node->simdclone->simdlen);
+ else
+ {
+ t = build_vector_type (t, veclen);
+ t = build_array_type_nelts (t, node->simdclone->simdlen / veclen);
+ }
+ TREE_TYPE (TREE_TYPE (fndecl)) = t;
+ if (!node->definition)
+ return NULL_TREE;
+
+ t = DECL_RESULT (fndecl);
+ /* Adjust the DECL_RESULT. */
+ gcc_assert (TREE_TYPE (t) != void_type_node);
+ TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl));
+ relayout_decl (t);
+
+ tree atype = build_array_type_nelts (orig_rettype,
+ node->simdclone->simdlen);
+ if (veclen != node->simdclone->simdlen)
+ return build1 (VIEW_CONVERT_EXPR, atype, t);
+
+ /* Set up a SIMD array to use as the return value. */
+ tree retval = create_tmp_var_raw (atype, "retval");
+ gimple_add_tmp_var (retval);
+ return retval;
+}
+
+/* Each vector argument has a corresponding array to be used locally
+ as part of the eventual loop. Create such temporary array and
+ return it.
+
+ PREFIX is the prefix to be used for the temporary.
+
+ TYPE is the inner element type.
+
+ SIMDLEN is the number of elements. */
+
+static tree
+create_tmp_simd_array (const char *prefix, tree type, int simdlen)
+{
+ tree atype = build_array_type_nelts (type, simdlen);
+ tree avar = create_tmp_var_raw (atype, prefix);
+ gimple_add_tmp_var (avar);
+ return avar;
+}
+
+/* Modify the function argument types to their corresponding vector
+ counterparts if appropriate. Also, create one array for each simd
+ argument to be used locally when using the function arguments as
+ part of the loop.
+
+ NODE is the function whose arguments are to be adjusted.
+
+ Returns an adjustment vector that will be filled describing how the
+ argument types will be adjusted. */
+
+static ipa_parm_adjustment_vec
+simd_clone_adjust_argument_types (struct cgraph_node *node)
+{
+ vec<tree> args;
+ ipa_parm_adjustment_vec adjustments;
+
+ if (node->definition)
+ args = ipa_get_vector_of_formal_parms (node->decl);
+ else
+ args = simd_clone_vector_of_formal_parm_types (node->decl);
+ adjustments.create (args.length ());
+ unsigned i, j, veclen;
+ struct ipa_parm_adjustment adj;
+ struct cgraph_simd_clone *sc = node->simdclone;
+
+ for (i = 0; i < sc->nargs; ++i)
+ {
+ memset (&adj, 0, sizeof (adj));
+ tree parm = args[i];
+ tree parm_type = node->definition ? TREE_TYPE (parm) : parm;
+ adj.base_index = i;
+ adj.base = parm;
+
+ sc->args[i].orig_arg = node->definition ? parm : NULL_TREE;
+ sc->args[i].orig_type = parm_type;
+
+ switch (sc->args[i].arg_type)
+ {
+ default:
+ /* No adjustment necessary for scalar arguments. */
+ adj.op = IPA_PARM_OP_COPY;
+ break;
+ case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
+ case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP:
+ if (node->definition)
+ sc->args[i].simd_array
+ = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
+ TREE_TYPE (parm_type),
+ sc->simdlen);
+ adj.op = IPA_PARM_OP_COPY;
+ break;
+ case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
+ case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP:
+ case SIMD_CLONE_ARG_TYPE_VECTOR:
+ if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type))
+ veclen = sc->vecsize_int;
+ else
+ veclen = sc->vecsize_float;
+ veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type));
+ if (veclen > sc->simdlen)
+ veclen = sc->simdlen;
+ adj.arg_prefix = "simd";
+ if (POINTER_TYPE_P (parm_type))
+ adj.type = build_vector_type (pointer_sized_int_node, veclen);
+ else
+ adj.type = build_vector_type (parm_type, veclen);
+ sc->args[i].vector_type = adj.type;
+ for (j = veclen; j < sc->simdlen; j += veclen)
+ {
+ adjustments.safe_push (adj);
+ if (j == veclen)
+ {
+ memset (&adj, 0, sizeof (adj));
+ adj.op = IPA_PARM_OP_NEW;
+ adj.arg_prefix = "simd";
+ adj.base_index = i;
+ adj.type = sc->args[i].vector_type;
+ }
+ }
+
+ if (node->definition)
+ sc->args[i].simd_array
+ = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)),
+ parm_type, sc->simdlen);
+ }
+ adjustments.safe_push (adj);
+ }
+
+ if (sc->inbranch)
+ {
+ tree base_type = simd_clone_compute_base_data_type (sc->origin, sc);
+
+ memset (&adj, 0, sizeof (adj));
+ adj.op = IPA_PARM_OP_NEW;
+ adj.arg_prefix = "mask";
+
+ adj.base_index = i;
+ if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type))
+ veclen = sc->vecsize_int;
+ else
+ veclen = sc->vecsize_float;
+ veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type));
+ if (veclen > sc->simdlen)
+ veclen = sc->simdlen;
+ if (sc->mask_mode != VOIDmode)
+ adj.type
+ = lang_hooks.types.type_for_mode (sc->mask_mode, 1);
+ else if (POINTER_TYPE_P (base_type))
+ adj.type = build_vector_type (pointer_sized_int_node, veclen);
+ else
+ adj.type = build_vector_type (base_type, veclen);
+ adjustments.safe_push (adj);
+
+ for (j = veclen; j < sc->simdlen; j += veclen)
+ adjustments.safe_push (adj);
+
+ /* We have previously allocated one extra entry for the mask. Use
+ it and fill it. */
+ sc->nargs++;
+ if (sc->mask_mode != VOIDmode)
+ base_type = boolean_type_node;
+ if (node->definition)
+ {
+ sc->args[i].orig_arg
+ = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type);
+ if (sc->mask_mode == VOIDmode)
+ sc->args[i].simd_array
+ = create_tmp_simd_array ("mask", base_type, sc->simdlen);
+ else if (veclen < sc->simdlen)
+ sc->args[i].simd_array
+ = create_tmp_simd_array ("mask", adj.type, sc->simdlen / veclen);
+ else
+ sc->args[i].simd_array = NULL_TREE;
+ }
+ sc->args[i].orig_type = base_type;
+ sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK;
+ }
+
+ if (node->definition)
+ ipa_modify_formal_parameters (node->decl, adjustments);
+ else
+ {
+ tree new_arg_types = NULL_TREE, new_reversed;
+ bool last_parm_void = false;
+ if (args.length () > 0 && args.last () == void_type_node)
+ last_parm_void = true;
+
+ gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl)));
+ j = adjustments.length ();
+ for (i = 0; i < j; i++)
+ {
+ struct ipa_parm_adjustment *adj = &adjustments[i];
+ tree ptype;
+ if (adj->op == IPA_PARM_OP_COPY)
+ ptype = args[adj->base_index];
+ else
+ ptype = adj->type;
+ new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types);
+ }
+ new_reversed = nreverse (new_arg_types);
+ if (last_parm_void)
+ {
+ if (new_reversed)
+ TREE_CHAIN (new_arg_types) = void_list_node;
+ else
+ new_reversed = void_list_node;
+ }
+
+ tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl));
+ TYPE_ARG_TYPES (new_type) = new_reversed;
+ TREE_TYPE (node->decl) = new_type;
+
+ adjustments.release ();
+ }
+ args.release ();
+ return adjustments;
+}
+
+/* Initialize and copy the function arguments in NODE to their
+ corresponding local simd arrays. Returns a fresh gimple_seq with
+ the instruction sequence generated. */
+
+static gimple_seq
+simd_clone_init_simd_arrays (struct cgraph_node *node,
+ ipa_parm_adjustment_vec adjustments)
+{
+ gimple_seq seq = NULL;
+ unsigned i = 0, j = 0, k;
+
+ for (tree arg = DECL_ARGUMENTS (node->decl);
+ arg;
+ arg = DECL_CHAIN (arg), i++, j++)
+ {
+ if (adjustments[j].op == IPA_PARM_OP_COPY
+ || POINTER_TYPE_P (TREE_TYPE (arg)))
+ continue;
+
+ node->simdclone->args[i].vector_arg = arg;
+
+ tree array = node->simdclone->args[i].simd_array;
+ if (node->simdclone->mask_mode != VOIDmode
+ && node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_MASK)
+ {
+ if (array == NULL_TREE)
+ continue;
+ unsigned int l
+ = tree_to_uhwi (TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (array))));
+ for (k = 0; k <= l; k++)
+ {
+ if (k)
+ {
+ arg = DECL_CHAIN (arg);
+ j++;
+ }
+ tree t = build4 (ARRAY_REF, TREE_TYPE (TREE_TYPE (array)),
+ array, size_int (k), NULL, NULL);
+ t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
+ gimplify_and_add (t, &seq);
+ }
+ continue;
+ }
+ if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen)
+ {
+ tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
+ tree ptr = build_fold_addr_expr (array);
+ tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
+ build_int_cst (ptype, 0));
+ t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
+ gimplify_and_add (t, &seq);
+ }
+ else
+ {
+ unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg));
+ tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array)));
+ for (k = 0; k < node->simdclone->simdlen; k += simdlen)
+ {
+ tree ptr = build_fold_addr_expr (array);
+ int elemsize;
+ if (k)
+ {
+ arg = DECL_CHAIN (arg);
+ j++;
+ }
+ elemsize
+ = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg))));
+ tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr,
+ build_int_cst (ptype, k * elemsize));
+ t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg);
+ gimplify_and_add (t, &seq);
+ }
+ }
+ }
+ return seq;
+}
+
+/* Callback info for ipa_simd_modify_stmt_ops below. */
+
+struct modify_stmt_info {
+ ipa_parm_adjustment_vec adjustments;
+ gimple *stmt;
+ /* True if the parent statement was modified by
+ ipa_simd_modify_stmt_ops. */
+ bool modified;
+};
+
+/* Callback for walk_gimple_op.
+
+ Adjust operands from a given statement as specified in the
+ adjustments vector in the callback data. */
+
+static tree
+ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data)
+{
+ struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
+ struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info;
+ tree *orig_tp = tp;
+ if (TREE_CODE (*tp) == ADDR_EXPR)
+ tp = &TREE_OPERAND (*tp, 0);
+ struct ipa_parm_adjustment *cand = NULL;
+ if (TREE_CODE (*tp) == PARM_DECL)
+ cand = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true);
+ else
+ {
+ if (TYPE_P (*tp))
+ *walk_subtrees = 0;
+ }
+
+ tree repl = NULL_TREE;
+ if (cand)
+ repl = unshare_expr (cand->new_decl);
+ else
+ {
+ if (tp != orig_tp)
+ {
+ *walk_subtrees = 0;
+ bool modified = info->modified;
+ info->modified = false;
+ walk_tree (tp, ipa_simd_modify_stmt_ops, wi, wi->pset);
+ if (!info->modified)
+ {
+ info->modified = modified;
+ return NULL_TREE;
+ }
+ info->modified = modified;
+ repl = *tp;
+ }
+ else
+ return NULL_TREE;
+ }
+
+ if (tp != orig_tp)
+ {
+ repl = build_fold_addr_expr (repl);
+ gimple *stmt;
+ if (is_gimple_debug (info->stmt))
+ {
+ tree vexpr = make_node (DEBUG_EXPR_DECL);
+ stmt = gimple_build_debug_source_bind (vexpr, repl, NULL);
+ DECL_ARTIFICIAL (vexpr) = 1;
+ TREE_TYPE (vexpr) = TREE_TYPE (repl);
+ DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl));
+ repl = vexpr;
+ }
+ else
+ {
+ stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl)), repl);
+ repl = gimple_assign_lhs (stmt);
+ }
+ gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt);
+ gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
+ *orig_tp = repl;
+ }
+ else if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl)))
+ {
+ tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl);
+ *tp = vce;
+ }
+ else
+ *tp = repl;
+
+ info->modified = true;
+ return NULL_TREE;
+}
+
+/* Traverse the function body and perform all modifications as
+ described in ADJUSTMENTS. At function return, ADJUSTMENTS will be
+ modified such that the replacement/reduction value will now be an
+ offset into the corresponding simd_array.
+
+ This function will replace all function argument uses with their
+ corresponding simd array elements, and ajust the return values
+ accordingly. */
+
+static void
+ipa_simd_modify_function_body (struct cgraph_node *node,
+ ipa_parm_adjustment_vec adjustments,
+ tree retval_array, tree iter)
+{
+ basic_block bb;
+ unsigned int i, j, l;
+
+ /* Re-use the adjustments array, but this time use it to replace
+ every function argument use to an offset into the corresponding
+ simd_array. */
+ for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j)
+ {
+ if (!node->simdclone->args[i].vector_arg)
+ continue;
+
+ tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg);
+ tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg);
+ adjustments[j].new_decl
+ = build4 (ARRAY_REF,
+ basetype,
+ node->simdclone->args[i].simd_array,
+ iter,
+ NULL_TREE, NULL_TREE);
+ if (adjustments[j].op == IPA_PARM_OP_NONE
+ && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen)
+ j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1;
+ }
+
+ l = adjustments.length ();
+ for (i = 1; i < num_ssa_names; i++)
+ {
+ tree name = ssa_name (i);
+ if (name
+ && SSA_NAME_VAR (name)
+ && TREE_CODE (SSA_NAME_VAR (name)) == PARM_DECL)
+ {
+ for (j = 0; j < l; j++)
+ if (SSA_NAME_VAR (name) == adjustments[j].base
+ && adjustments[j].new_decl)
+ {
+ tree base_var;
+ if (adjustments[j].new_ssa_base == NULL_TREE)
+ {
+ base_var
+ = copy_var_decl (adjustments[j].base,
+ DECL_NAME (adjustments[j].base),
+ TREE_TYPE (adjustments[j].base));
+ adjustments[j].new_ssa_base = base_var;
+ }
+ else
+ base_var = adjustments[j].new_ssa_base;
+ if (SSA_NAME_IS_DEFAULT_DEF (name))
+ {
+ bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
+ gimple_stmt_iterator gsi = gsi_after_labels (bb);
+ tree new_decl = unshare_expr (adjustments[j].new_decl);
+ set_ssa_default_def (cfun, adjustments[j].base, NULL_TREE);
+ SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
+ SSA_NAME_IS_DEFAULT_DEF (name) = 0;
+ gimple *stmt = gimple_build_assign (name, new_decl);
+ gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
+ }
+ else
+ SET_SSA_NAME_VAR_OR_IDENTIFIER (name, base_var);
+ }
+ }
+ }
+
+ struct modify_stmt_info info;
+ info.adjustments = adjustments;
+
+ FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl))
+ {
+ gimple_stmt_iterator gsi;
+
+ gsi = gsi_start_bb (bb);
+ while (!gsi_end_p (gsi))
+ {
+ gimple *stmt = gsi_stmt (gsi);
+ info.stmt = stmt;
+ struct walk_stmt_info wi;
+
+ memset (&wi, 0, sizeof (wi));
+ info.modified = false;
+ wi.info = &info;
+ walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi);
+
+ if (greturn *return_stmt = dyn_cast <greturn *> (stmt))
+ {
+ tree retval = gimple_return_retval (return_stmt);
+ if (!retval)
+ {
+ gsi_remove (&gsi, true);
+ continue;
+ }
+
+ /* Replace `return foo' with `retval_array[iter] = foo'. */
+ tree ref = build4 (ARRAY_REF, TREE_TYPE (retval),
+ retval_array, iter, NULL, NULL);
+ stmt = gimple_build_assign (ref, retval);
+ gsi_replace (&gsi, stmt, true);
+ info.modified = true;
+ }
+
+ if (info.modified)
+ {
+ update_stmt (stmt);
+ if (maybe_clean_eh_stmt (stmt))
+ gimple_purge_dead_eh_edges (gimple_bb (stmt));
+ }
+ gsi_next (&gsi);
+ }
+ }
+}
+
+/* Helper function of simd_clone_adjust, return linear step addend
+ of Ith argument. */
+
+static tree
+simd_clone_linear_addend (struct cgraph_node *node, unsigned int i,
+ tree addtype, basic_block entry_bb)
+{
+ tree ptype = NULL_TREE;
+ switch (node->simdclone->args[i].arg_type)
+ {
+ case SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP:
+ case SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP:
+ case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_CONSTANT_STEP:
+ case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP:
+ return build_int_cst (addtype, node->simdclone->args[i].linear_step);
+ case SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP:
+ case SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP:
+ ptype = TREE_TYPE (node->simdclone->args[i].orig_arg);
+ break;
+ case SIMD_CLONE_ARG_TYPE_LINEAR_VAL_VARIABLE_STEP:
+ case SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP:
+ ptype = TREE_TYPE (TREE_TYPE (node->simdclone->args[i].orig_arg));
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ unsigned int idx = node->simdclone->args[i].linear_step;
+ tree arg = node->simdclone->args[idx].orig_arg;
+ gcc_assert (is_gimple_reg_type (TREE_TYPE (arg)));
+ gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
+ gimple *g;
+ tree ret;
+ if (is_gimple_reg (arg))
+ ret = get_or_create_ssa_default_def (cfun, arg);
+ else
+ {
+ g = gimple_build_assign (make_ssa_name (TREE_TYPE (arg)), arg);
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+ ret = gimple_assign_lhs (g);
+ }
+ if (TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE)
+ {
+ g = gimple_build_assign (make_ssa_name (TREE_TYPE (TREE_TYPE (arg))),
+ build_simple_mem_ref (ret));
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+ ret = gimple_assign_lhs (g);
+ }
+ if (!useless_type_conversion_p (addtype, TREE_TYPE (ret)))
+ {
+ g = gimple_build_assign (make_ssa_name (addtype), NOP_EXPR, ret);
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+ ret = gimple_assign_lhs (g);
+ }
+ if (POINTER_TYPE_P (ptype))
+ {
+ tree size = TYPE_SIZE_UNIT (TREE_TYPE (ptype));
+ if (size && TREE_CODE (size) == INTEGER_CST)
+ {
+ g = gimple_build_assign (make_ssa_name (addtype), MULT_EXPR,
+ ret, fold_convert (addtype, size));
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+ ret = gimple_assign_lhs (g);
+ }
+ }
+ return ret;
+}
+
+/* Adjust the argument types in NODE to their appropriate vector
+ counterparts. */
+
+static void
+simd_clone_adjust (struct cgraph_node *node)
+{
+ push_cfun (DECL_STRUCT_FUNCTION (node->decl));
+
+ targetm.simd_clone.adjust (node);
+
+ tree retval = simd_clone_adjust_return_type (node);
+ ipa_parm_adjustment_vec adjustments
+ = simd_clone_adjust_argument_types (node);
+
+ push_gimplify_context ();
+
+ gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments);
+
+ /* Adjust all uses of vector arguments accordingly. Adjust all
+ return values accordingly. */
+ tree iter = create_tmp_var (unsigned_type_node, "iter");
+ tree iter1 = make_ssa_name (iter);
+ tree iter2 = make_ssa_name (iter);
+ ipa_simd_modify_function_body (node, adjustments, retval, iter1);
+
+ /* Initialize the iteration variable. */
+ basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
+ basic_block body_bb = split_block_after_labels (entry_bb)->dest;
+ gimple_stmt_iterator gsi = gsi_after_labels (entry_bb);
+ /* Insert the SIMD array and iv initialization at function
+ entry. */
+ gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT);
+
+ pop_gimplify_context (NULL);
+
+ /* Create a new BB right before the original exit BB, to hold the
+ iteration increment and the condition/branch. */
+ basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src;
+ basic_block incr_bb = create_empty_bb (orig_exit);
+ add_bb_to_loop (incr_bb, body_bb->loop_father);
+ /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty
+ flag. Set it now to be a FALLTHRU_EDGE. */
+ gcc_assert (EDGE_COUNT (orig_exit->succs) == 1);
+ EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU;
+ for (unsigned i = 0;
+ i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i)
+ {
+ edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i);
+ redirect_edge_succ (e, incr_bb);
+ }
+ edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0);
+ e->probability = REG_BR_PROB_BASE;
+ gsi = gsi_last_bb (incr_bb);
+ gimple *g = gimple_build_assign (iter2, PLUS_EXPR, iter1,
+ build_int_cst (unsigned_type_node, 1));
+ gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
+
+ /* Mostly annotate the loop for the vectorizer (the rest is done below). */
+ struct loop *loop = alloc_loop ();
+ cfun->has_force_vectorize_loops = true;
+ loop->safelen = node->simdclone->simdlen;
+ loop->force_vectorize = true;
+ loop->header = body_bb;
+
+ /* Branch around the body if the mask applies. */
+ if (node->simdclone->inbranch)
+ {
+ gimple_stmt_iterator gsi = gsi_last_bb (loop->header);
+ tree mask_array
+ = node->simdclone->args[node->simdclone->nargs - 1].simd_array;
+ tree mask;
+ if (node->simdclone->mask_mode != VOIDmode)
+ {
+ tree shift_cnt;
+ if (mask_array == NULL_TREE)
+ {
+ tree arg = node->simdclone->args[node->simdclone->nargs
+ - 1].vector_arg;
+ mask = get_or_create_ssa_default_def (cfun, arg);
+ shift_cnt = iter1;
+ }
+ else
+ {
+ tree maskt = TREE_TYPE (mask_array);
+ int c = tree_to_uhwi (TYPE_MAX_VALUE (TYPE_DOMAIN (maskt)));
+ c = node->simdclone->simdlen / (c + 1);
+ int s = exact_log2 (c);
+ gcc_assert (s > 0);
+ c--;
+ tree idx = make_ssa_name (TREE_TYPE (iter1));
+ g = gimple_build_assign (idx, RSHIFT_EXPR, iter1,
+ build_int_cst (NULL_TREE, s));
+ gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
+ mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)));
+ tree aref = build4 (ARRAY_REF,
+ TREE_TYPE (TREE_TYPE (mask_array)),
+ mask_array, idx, NULL, NULL);
+ g = gimple_build_assign (mask, aref);
+ gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
+ shift_cnt = make_ssa_name (TREE_TYPE (iter1));
+ g = gimple_build_assign (shift_cnt, BIT_AND_EXPR, iter1,
+ build_int_cst (TREE_TYPE (iter1), c));
+ gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
+ }
+ g = gimple_build_assign (make_ssa_name (TREE_TYPE (mask)),
+ RSHIFT_EXPR, mask, shift_cnt);
+ gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
+ mask = gimple_assign_lhs (g);
+ g = gimple_build_assign (make_ssa_name (TREE_TYPE (mask)),
+ BIT_AND_EXPR, mask,
+ build_int_cst (TREE_TYPE (mask), 1));
+ gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
+ mask = gimple_assign_lhs (g);
+ }
+ else
+ {
+ mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)));
+ tree aref = build4 (ARRAY_REF,
+ TREE_TYPE (TREE_TYPE (mask_array)),
+ mask_array, iter1, NULL, NULL);
+ g = gimple_build_assign (mask, aref);
+ gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
+ int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref)));
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (aref)))
+ {
+ aref = build1 (VIEW_CONVERT_EXPR,
+ build_nonstandard_integer_type (bitsize, 0),
+ mask);
+ mask = make_ssa_name (TREE_TYPE (aref));
+ g = gimple_build_assign (mask, aref);
+ gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
+ }
+ }
+
+ g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)),
+ NULL, NULL);
+ gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
+ make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE);
+ FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE;
+ }
+
+ /* Generate the condition. */
+ g = gimple_build_cond (LT_EXPR,
+ iter2,
+ build_int_cst (unsigned_type_node,
+ node->simdclone->simdlen),
+ NULL, NULL);
+ gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
+ e = split_block (incr_bb, gsi_stmt (gsi));
+ basic_block latch_bb = e->dest;
+ basic_block new_exit_bb;
+ new_exit_bb = split_block_after_labels (latch_bb)->dest;
+ loop->latch = latch_bb;
+
+ redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb);
+
+ make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE);
+ /* The successor of incr_bb is already pointing to latch_bb; just
+ change the flags.
+ make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */
+ FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE;
+
+ gphi *phi = create_phi_node (iter1, body_bb);
+ edge preheader_edge = find_edge (entry_bb, body_bb);
+ edge latch_edge = single_succ_edge (latch_bb);
+ add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge,
+ UNKNOWN_LOCATION);
+ add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
+
+ /* Generate the new return. */
+ gsi = gsi_last_bb (new_exit_bb);
+ if (retval
+ && TREE_CODE (retval) == VIEW_CONVERT_EXPR
+ && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL)
+ retval = TREE_OPERAND (retval, 0);
+ else if (retval)
+ {
+ retval = build1 (VIEW_CONVERT_EXPR,
+ TREE_TYPE (TREE_TYPE (node->decl)),
+ retval);
+ retval = force_gimple_operand_gsi (&gsi, retval, true, NULL,
+ false, GSI_CONTINUE_LINKING);
+ }
+ g = gimple_build_return (retval);
+ gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING);
+
+ /* Handle aligned clauses by replacing default defs of the aligned
+ uniform args with __builtin_assume_aligned (arg_N(D), alignment)
+ lhs. Handle linear by adding PHIs. */
+ for (unsigned i = 0; i < node->simdclone->nargs; i++)
+ if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
+ && (TREE_ADDRESSABLE (node->simdclone->args[i].orig_arg)
+ || !is_gimple_reg_type
+ (TREE_TYPE (node->simdclone->args[i].orig_arg))))
+ {
+ tree orig_arg = node->simdclone->args[i].orig_arg;
+ if (is_gimple_reg_type (TREE_TYPE (orig_arg)))
+ iter1 = make_ssa_name (TREE_TYPE (orig_arg));
+ else
+ {
+ iter1 = create_tmp_var_raw (TREE_TYPE (orig_arg));
+ gimple_add_tmp_var (iter1);
+ }
+ gsi = gsi_after_labels (entry_bb);
+ g = gimple_build_assign (iter1, orig_arg);
+ gsi_insert_before (&gsi, g, GSI_NEW_STMT);
+ gsi = gsi_after_labels (body_bb);
+ g = gimple_build_assign (orig_arg, iter1);
+ gsi_insert_before (&gsi, g, GSI_NEW_STMT);
+ }
+ else if (node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM
+ && DECL_BY_REFERENCE (node->simdclone->args[i].orig_arg)
+ && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
+ == REFERENCE_TYPE
+ && TREE_ADDRESSABLE
+ (TREE_TYPE (TREE_TYPE (node->simdclone->args[i].orig_arg))))
+ {
+ tree orig_arg = node->simdclone->args[i].orig_arg;
+ tree def = ssa_default_def (cfun, orig_arg);
+ if (def && !has_zero_uses (def))
+ {
+ iter1 = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (orig_arg)));
+ gimple_add_tmp_var (iter1);
+ gsi = gsi_after_labels (entry_bb);
+ g = gimple_build_assign (iter1, build_simple_mem_ref (def));
+ gsi_insert_before (&gsi, g, GSI_NEW_STMT);
+ gsi = gsi_after_labels (body_bb);
+ g = gimple_build_assign (build_simple_mem_ref (def), iter1);
+ gsi_insert_before (&gsi, g, GSI_NEW_STMT);
+ }
+ }
+ else if (node->simdclone->args[i].alignment
+ && node->simdclone->args[i].arg_type
+ == SIMD_CLONE_ARG_TYPE_UNIFORM
+ && (node->simdclone->args[i].alignment
+ & (node->simdclone->args[i].alignment - 1)) == 0
+ && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg))
+ == POINTER_TYPE)
+ {
+ unsigned int alignment = node->simdclone->args[i].alignment;
+ tree orig_arg = node->simdclone->args[i].orig_arg;
+ tree def = ssa_default_def (cfun, orig_arg);
+ if (def && !has_zero_uses (def))
+ {
+ tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED);
+ gimple_seq seq = NULL;
+ bool need_cvt = false;
+ gcall *call
+ = gimple_build_call (fn, 2, def, size_int (alignment));
+ g = call;
+ if (!useless_type_conversion_p (TREE_TYPE (orig_arg),
+ ptr_type_node))
+ need_cvt = true;
+ tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg);
+ gimple_call_set_lhs (g, t);
+ gimple_seq_add_stmt_without_update (&seq, g);
+ if (need_cvt)
+ {
+ t = make_ssa_name (orig_arg);
+ g = gimple_build_assign (t, NOP_EXPR, gimple_call_lhs (g));
+ gimple_seq_add_stmt_without_update (&seq, g);
+ }
+ gsi_insert_seq_on_edge_immediate
+ (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq);
+
+ entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
+ int freq = compute_call_stmt_bb_frequency (current_function_decl,
+ entry_bb);
+ node->create_edge (cgraph_node::get_create (fn),
+ call, entry_bb->count, freq);
+
+ imm_use_iterator iter;
+ use_operand_p use_p;
+ gimple *use_stmt;
+ tree repl = gimple_get_lhs (g);
+ FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
+ if (is_gimple_debug (use_stmt) || use_stmt == call)
+ continue;
+ else
+ FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
+ SET_USE (use_p, repl);
+ }
+ }
+ else if ((node->simdclone->args[i].arg_type
+ == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP)
+ || (node->simdclone->args[i].arg_type
+ == SIMD_CLONE_ARG_TYPE_LINEAR_REF_CONSTANT_STEP)
+ || (node->simdclone->args[i].arg_type
+ == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP)
+ || (node->simdclone->args[i].arg_type
+ == SIMD_CLONE_ARG_TYPE_LINEAR_REF_VARIABLE_STEP))
+ {
+ tree orig_arg = node->simdclone->args[i].orig_arg;
+ gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
+ || POINTER_TYPE_P (TREE_TYPE (orig_arg)));
+ tree def = NULL_TREE;
+ if (TREE_ADDRESSABLE (orig_arg))
+ {
+ def = make_ssa_name (TREE_TYPE (orig_arg));
+ iter1 = make_ssa_name (TREE_TYPE (orig_arg));
+ iter2 = make_ssa_name (TREE_TYPE (orig_arg));
+ gsi = gsi_after_labels (entry_bb);
+ g = gimple_build_assign (def, orig_arg);
+ gsi_insert_before (&gsi, g, GSI_NEW_STMT);
+ }
+ else
+ {
+ def = ssa_default_def (cfun, orig_arg);
+ if (!def || has_zero_uses (def))
+ def = NULL_TREE;
+ else
+ {
+ iter1 = make_ssa_name (orig_arg);
+ iter2 = make_ssa_name (orig_arg);
+ }
+ }
+ if (def)
+ {
+ phi = create_phi_node (iter1, body_bb);
+ add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION);
+ add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
+ enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
+ ? PLUS_EXPR : POINTER_PLUS_EXPR;
+ tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg))
+ ? TREE_TYPE (orig_arg) : sizetype;
+ tree addcst = simd_clone_linear_addend (node, i, addtype,
+ entry_bb);
+ gsi = gsi_last_bb (incr_bb);
+ g = gimple_build_assign (iter2, code, iter1, addcst);
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+
+ imm_use_iterator iter;
+ use_operand_p use_p;
+ gimple *use_stmt;
+ if (TREE_ADDRESSABLE (orig_arg))
+ {
+ gsi = gsi_after_labels (body_bb);
+ g = gimple_build_assign (orig_arg, iter1);
+ gsi_insert_before (&gsi, g, GSI_NEW_STMT);
+ }
+ else
+ FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
+ if (use_stmt == phi)
+ continue;
+ else
+ FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
+ SET_USE (use_p, iter1);
+ }
+ }
+ else if (node->simdclone->args[i].arg_type
+ == SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_CONSTANT_STEP
+ || (node->simdclone->args[i].arg_type
+ == SIMD_CLONE_ARG_TYPE_LINEAR_UVAL_VARIABLE_STEP))
+ {
+ tree orig_arg = node->simdclone->args[i].orig_arg;
+ tree def = ssa_default_def (cfun, orig_arg);
+ gcc_assert (!TREE_ADDRESSABLE (orig_arg)
+ && TREE_CODE (TREE_TYPE (orig_arg)) == REFERENCE_TYPE);
+ if (def && !has_zero_uses (def))
+ {
+ tree rtype = TREE_TYPE (TREE_TYPE (orig_arg));
+ iter1 = make_ssa_name (orig_arg);
+ iter2 = make_ssa_name (orig_arg);
+ tree iter3 = make_ssa_name (rtype);
+ tree iter4 = make_ssa_name (rtype);
+ tree iter5 = make_ssa_name (rtype);
+ gsi = gsi_after_labels (entry_bb);
+ gimple *load
+ = gimple_build_assign (iter3, build_simple_mem_ref (def));
+ gsi_insert_before (&gsi, load, GSI_NEW_STMT);
+
+ tree array = node->simdclone->args[i].simd_array;
+ TREE_ADDRESSABLE (array) = 1;
+ tree ptr = build_fold_addr_expr (array);
+ phi = create_phi_node (iter1, body_bb);
+ add_phi_arg (phi, ptr, preheader_edge, UNKNOWN_LOCATION);
+ add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION);
+ g = gimple_build_assign (iter2, POINTER_PLUS_EXPR, iter1,
+ TYPE_SIZE_UNIT (TREE_TYPE (iter3)));
+ gsi = gsi_last_bb (incr_bb);
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+
+ phi = create_phi_node (iter4, body_bb);
+ add_phi_arg (phi, iter3, preheader_edge, UNKNOWN_LOCATION);
+ add_phi_arg (phi, iter5, latch_edge, UNKNOWN_LOCATION);
+ enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (iter3))
+ ? PLUS_EXPR : POINTER_PLUS_EXPR;
+ tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (iter3))
+ ? TREE_TYPE (iter3) : sizetype;
+ tree addcst = simd_clone_linear_addend (node, i, addtype,
+ entry_bb);
+ g = gimple_build_assign (iter5, code, iter4, addcst);
+ gsi = gsi_last_bb (incr_bb);
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+
+ g = gimple_build_assign (build_simple_mem_ref (iter1), iter4);
+ gsi = gsi_after_labels (body_bb);
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+
+ imm_use_iterator iter;
+ use_operand_p use_p;
+ gimple *use_stmt;
+ FOR_EACH_IMM_USE_STMT (use_stmt, iter, def)
+ if (use_stmt == load)
+ continue;
+ else
+ FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
+ SET_USE (use_p, iter1);
+
+ if (!TYPE_READONLY (rtype))
+ {
+ tree v = make_ssa_name (rtype);
+ tree aref = build4 (ARRAY_REF, rtype, array,
+ size_zero_node, NULL_TREE,
+ NULL_TREE);
+ gsi = gsi_after_labels (new_exit_bb);
+ g = gimple_build_assign (v, aref);
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+ g = gimple_build_assign (build_simple_mem_ref (def), v);
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+ }
+ }
+ }
+
+ calculate_dominance_info (CDI_DOMINATORS);
+ add_loop (loop, loop->header->loop_father);
+ update_ssa (TODO_update_ssa);
+
+ pop_cfun ();
+}
+
+/* If the function in NODE is tagged as an elemental SIMD function,
+ create the appropriate SIMD clones. */
+
+static void
+expand_simd_clones (struct cgraph_node *node)
+{
+ tree attr = lookup_attribute ("omp declare simd",
+ DECL_ATTRIBUTES (node->decl));
+ if (attr == NULL_TREE
+ || node->global.inlined_to
+ || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
+ return;
+
+ /* Ignore
+ #pragma omp declare simd
+ extern int foo ();
+ in C, there we don't know the argument types at all. */
+ if (!node->definition
+ && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE)
+ return;
+
+ /* Call this before creating clone_info, as it might ggc_collect. */
+ if (node->definition && node->has_gimple_body_p ())
+ node->get_body ();
+
+ do
+ {
+ /* Start with parsing the "omp declare simd" attribute(s). */
+ bool inbranch_clause_specified;
+ struct cgraph_simd_clone *clone_info
+ = simd_clone_clauses_extract (node, TREE_VALUE (attr),
+ &inbranch_clause_specified);
+ if (clone_info == NULL)
+ continue;
+
+ int orig_simdlen = clone_info->simdlen;
+ tree base_type = simd_clone_compute_base_data_type (node, clone_info);
+ /* The target can return 0 (no simd clones should be created),
+ 1 (just one ISA of simd clones should be created) or higher
+ count of ISA variants. In that case, clone_info is initialized
+ for the first ISA variant. */
+ int count
+ = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info,
+ base_type, 0);
+ if (count == 0)
+ continue;
+
+ /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED,
+ also create one inbranch and one !inbranch clone of it. */
+ for (int i = 0; i < count * 2; i++)
+ {
+ struct cgraph_simd_clone *clone = clone_info;
+ if (inbranch_clause_specified && (i & 1) != 0)
+ continue;
+
+ if (i != 0)
+ {
+ clone = simd_clone_struct_alloc (clone_info->nargs
+ + ((i & 1) != 0));
+ simd_clone_struct_copy (clone, clone_info);
+ /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen
+ and simd_clone_adjust_argument_types did to the first
+ clone's info. */
+ clone->nargs -= clone_info->inbranch;
+ clone->simdlen = orig_simdlen;
+ /* And call the target hook again to get the right ISA. */
+ targetm.simd_clone.compute_vecsize_and_simdlen (node, clone,
+ base_type,
+ i / 2);
+ if ((i & 1) != 0)
+ clone->inbranch = 1;
+ }
+
+ /* simd_clone_mangle might fail if such a clone has been created
+ already. */
+ tree id = simd_clone_mangle (node, clone);
+ if (id == NULL_TREE)
+ continue;
+
+ /* Only when we are sure we want to create the clone actually
+ clone the function (or definitions) or create another
+ extern FUNCTION_DECL (for prototypes without definitions). */
+ struct cgraph_node *n = simd_clone_create (node);
+ if (n == NULL)
+ continue;
+
+ n->simdclone = clone;
+ clone->origin = node;
+ clone->next_clone = NULL;
+ if (node->simd_clones == NULL)
+ {
+ clone->prev_clone = n;
+ node->simd_clones = n;
+ }
+ else
+ {
+ clone->prev_clone = node->simd_clones->simdclone->prev_clone;
+ clone->prev_clone->simdclone->next_clone = n;
+ node->simd_clones->simdclone->prev_clone = n;
+ }
+ symtab->change_decl_assembler_name (n->decl, id);
+ /* And finally adjust the return type, parameters and for
+ definitions also function body. */
+ if (node->definition)
+ simd_clone_adjust (n);
+ else
+ {
+ simd_clone_adjust_return_type (n);
+ simd_clone_adjust_argument_types (n);
+ }
+ }
+ }
+ while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr))));
+}
+
+/* Entry point for IPA simd clone creation pass. */
+
+static unsigned int
+ipa_omp_simd_clone (void)
+{
+ struct cgraph_node *node;
+ FOR_EACH_FUNCTION (node)
+ expand_simd_clones (node);
+ return 0;
+}
+
+namespace {
+
+const pass_data pass_data_omp_simd_clone =
+{
+ SIMPLE_IPA_PASS, /* type */
+ "simdclone", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
+ TV_NONE, /* tv_id */
+ ( PROP_ssa | PROP_cfg ), /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ 0, /* todo_flags_finish */
+};
+
+class pass_omp_simd_clone : public simple_ipa_opt_pass
+{
+public:
+ pass_omp_simd_clone(gcc::context *ctxt)
+ : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ virtual bool gate (function *);
+ virtual unsigned int execute (function *) { return ipa_omp_simd_clone (); }
+};
+
+bool
+pass_omp_simd_clone::gate (function *)
+{
+ return targetm.simd_clone.compute_vecsize_and_simdlen != NULL;
+}
+
+} // anon namespace
+
+simple_ipa_opt_pass *
+make_pass_omp_simd_clone (gcc::context *ctxt)
+{
+ return new pass_omp_simd_clone (ctxt);
+}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 4131b9fcfe4..0f2e861c5b3 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,53 @@
+2016-04-15 Marek Polacek <polacek@redhat.com>
+
+ PR c/70671
+ * gcc.dg/bitfld-22.c: New test.
+
+2016-04-15 Bernd Schmidt <bschmidt@redhat.com>
+
+ * gcc.target/i386/pr46470.c: Add -mno-red-zone to dg-options for
+ x86_64.
+
+2016-04-15 Marek Polacek <polacek@redhat.com>
+
+ PR c/70651
+ * c-c++-common/pr70651.c: New test.
+
+2016-04-15 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ PR rtl-optimization/70681
+ * gcc.dg/ira-shrinkwrap-prep-2.c: XFAIL shrinkwrapping
+ dump scan on arm and powerpc.
+ * gcc.dg/pr10474.c: Likewise.
+
+2016-04-15 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/69517
+ PR c++/70019
+ PR c++/70588
+ * g++.dg/cpp1y/vla11.C: Revert for real.
+
+ PR c/70436
+ * c-c++-common/Wparentheses-1.c: New test.
+ * c-c++-common/gomp/Wparentheses-1.c: New test.
+ * c-c++-common/gomp/Wparentheses-2.c: New test.
+ * c-c++-common/gomp/Wparentheses-3.c: New test.
+ * c-c++-common/gomp/Wparentheses-4.c: New test.
+ * c-c++-common/cilk-plus/PS/Wparentheses-1.c: New test.
+ * c-c++-common/cilk-plus/CK/Wparentheses-1.c: New test.
+ * c-c++-common/goacc/Wparentheses-1.c: New test.
+
+2016-04-15 Kirill Yukhin <kirill.yukhin@intel.com>
+
+ PR target/70662
+ * gcc.target/i386/pr70662.c: New test.
+
+2016-04-15 Richard Biener <rguenther@suse.de>
+ Alan Modra <amodra@gmail.com>
+
+ PR tree-optimization/70130
+ * gcc.dg/vect/O3-pr70130.c: New testcase.
+
2016-04-14 Michael Meissner <meissner@linux.vnet.ibm.com>
PR target/70669
diff --git a/gcc/testsuite/c-c++-common/Wparentheses-1.c b/gcc/testsuite/c-c++-common/Wparentheses-1.c
new file mode 100644
index 00000000000..ed506083829
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wparentheses-1.c
@@ -0,0 +1,39 @@
+/* PR c/70436 */
+/* { dg-do compile } */
+/* { dg-options "-Wparentheses" } */
+
+int a, b, c[101], d[101], e[101], f[101];
+
+void
+f1 (void)
+{
+ int i;
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma GCC ivdep
+ for (i = 0; i < 100; i++)
+ if (b)
+ c[i] = d[i] + e[i];
+ else
+ f[i] = d[i] * e[i];
+
+ if (a)
+ #pragma GCC ivdep
+ for (i = 0; i < 100; i++)
+ {
+ if (b)
+ c[i] = d[i] + e[i];
+ else
+ f[i] = d[i] * e[i];
+ }
+
+ if (a)
+ #pragma GCC ivdep
+ for (i = 0; i < 100; i++)
+ {
+ if (b)
+ c[i] = d[i] + e[i];
+ }
+ else
+ f[i] = d[i] * e[i];
+}
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/Wparentheses-1.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/Wparentheses-1.c
new file mode 100644
index 00000000000..f07b49a2775
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/Wparentheses-1.c
@@ -0,0 +1,69 @@
+/* PR c/70436 */
+/* { dg-do compile } */
+/* { dg-options "-fcilkplus -Wparentheses" } */
+/* { dg-additional-options "-std=gnu99" { target c } } */
+
+int a, b, c;
+void bar (void);
+void baz (void);
+
+void
+f1 (void)
+{
+ if (a) /* { dg-warning "ambiguous" } */
+ _Cilk_for (int i = 0; i < 10; i++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a)
+ _Cilk_for (int i = 0; i < 10; i++)
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ _Cilk_for (int i = 0; i < 10; i++)
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+}
+
+void
+f2 (void)
+{
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma cilk grainsize = 2
+ _Cilk_for (int i = 0; i < 10; i++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a)
+ #pragma cilk grainsize = 2
+ _Cilk_for (int i = 0; i < 10; i++)
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ #pragma cilk grainsize = 2
+ _Cilk_for (int i = 0; i < 10; i++)
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+}
diff --git a/gcc/testsuite/c-c++-common/cilk-plus/PS/Wparentheses-1.c b/gcc/testsuite/c-c++-common/cilk-plus/PS/Wparentheses-1.c
new file mode 100644
index 00000000000..d391d7b1eed
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cilk-plus/PS/Wparentheses-1.c
@@ -0,0 +1,41 @@
+/* PR c/70436 */
+/* { dg-do compile } */
+/* { dg-options "-fcilkplus -Wparentheses" } */
+
+int a, b, c;
+void bar (void);
+void baz (void);
+
+void
+f1 (void)
+{
+ int i;
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma simd
+ for (i = 0; i < 10; i++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a)
+ #pragma simd
+ for (i = 0; i < 10; i++)
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ #pragma simd
+ for (i = 0; i < 10; i++)
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+}
diff --git a/gcc/testsuite/c-c++-common/goacc/Wparentheses-1.c b/gcc/testsuite/c-c++-common/goacc/Wparentheses-1.c
new file mode 100644
index 00000000000..08265b65e0b
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/goacc/Wparentheses-1.c
@@ -0,0 +1,174 @@
+/* PR c/70436 */
+/* { dg-additional-options "-Wparentheses" } */
+
+int a, b, c;
+void bar (void);
+void baz (void);
+#pragma acc routine
+void bar2 (void);
+#pragma acc routine
+void baz2 (void);
+
+void
+f1 (void)
+{
+ int i, d[10] = { 0 };
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma acc data copyin (d[0:10])
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ #pragma acc data copyin (d[0:10])
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma acc host_data use_device (d)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma acc kernels
+ if (b)
+ bar2 ();
+ else
+ baz2 ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma acc kernels
+ for (i = 0; i < 10; i++)
+ if (b)
+ bar2 ();
+ else
+ baz2 ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma acc parallel
+ if (b)
+ bar2 ();
+ else
+ baz2 ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma acc parallel loop
+ for (i = 0; i < 10; i++)
+ if (b)
+ bar2 ();
+ else
+ baz2 ();
+
+ (void) d[0];
+
+ if (a)
+ #pragma acc data copyin (d[0:10])
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ #pragma acc data copyin (d[0:10])
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ #pragma acc data copyin (d[0:10])
+ if (a)
+ #pragma acc host_data use_device (d)
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ #pragma acc data copyin (d[0:10])
+ if (a)
+ #pragma acc host_data use_device (d)
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ #pragma acc kernels
+ {
+ if (b)
+ bar2 ();
+ else
+ baz2 ();
+ }
+
+ if (a)
+ #pragma acc kernels
+ for (i = 0; i < 10; i++)
+ {
+ if (b)
+ bar2 ();
+ else
+ baz2 ();
+ }
+
+ if (a)
+ #pragma acc parallel
+ {
+ if (b)
+ bar2 ();
+ else
+ baz2 ();
+ }
+
+ if (a)
+ #pragma acc parallel loop
+ for (i = 0; i < 10; i++)
+ {
+ if (b)
+ bar2 ();
+ else
+ baz2 ();
+ }
+
+ if (a)
+ {
+ #pragma acc parallel loop
+ for (i = 0; i < 10; i++)
+ if (b)
+ bar2 ();
+ else
+ baz2 ();
+ }
+}
+
+#pragma acc routine vector
+void
+f2 (int *a, int b, int c)
+{
+ int i;
+
+ if (b) /* { dg-warning "ambiguous" } */
+ #pragma acc loop vector
+ for (i = 0; i < 10; i++)
+ if (c)
+ a[i] = a[i] + 1;
+ else
+ a[i] = a[i] + 2;
+
+ if (b)
+ #pragma acc loop vector
+ for (i = 0; i < 10; i++)
+ {
+ if (c)
+ a[i] = a[i] + 1;
+ else
+ a[i] = a[i] + 2;
+ }
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/Wparentheses-1.c b/gcc/testsuite/c-c++-common/gomp/Wparentheses-1.c
new file mode 100644
index 00000000000..4420d670bde
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/Wparentheses-1.c
@@ -0,0 +1,338 @@
+/* PR c/70436 */
+/* { dg-additional-options "-Wparentheses" } */
+
+int a, b, c;
+void bar (void);
+void baz (void);
+
+void
+f1 (void)
+{
+ int i, j;
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp for
+ for (i = 0; i < 10; i++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ while (1)
+ #pragma omp for
+ for (i = 0; i < 10; i++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ for (i = 0; i < 10; i++)
+ #pragma omp for
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a)
+ #pragma omp for
+ for (i = 0; i < 10; i++)
+ if (b) /* { dg-warning "ambiguous" } */
+ #pragma omp parallel for
+ for (j = 0; j < 10; j++)
+ if (c)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp taskloop
+ for (i = 0; i < 10; i++)
+ if (b)
+ #pragma omp parallel for
+ for (j = 0; j < 10; j++)
+ if (c)
+ bar ();
+ else
+ baz ();
+ else
+ bar ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp taskloop simd
+ for (i = 0; i < 10; i++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp for collapse(2)
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp critical
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ for (i = 0; i < 10; i++)
+ #pragma omp simd
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp for simd schedule(runtime)
+ for (i = 0; i < 10; i++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp master
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp parallel
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ for (i = 0; i < 10; i++)
+ #pragma omp parallel for
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ for (i = 0; i < 10; i++)
+ #pragma omp parallel for simd
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp single
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp task
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp taskgroup
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a)
+ #pragma omp for
+ for (i = 0; i < 10; i++)
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ {
+ #pragma omp taskloop
+ for (i = 0; i < 10; ++i)
+ if (b)
+ bar ();
+ }
+ else baz ();
+
+ if (a)
+ #pragma omp for collapse(2)
+ for (i = 0; i < 10; i++)
+ {
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ #pragma omp critical
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ for (i = 0; i < 10; i++)
+ #pragma omp simd
+ for (j = 0; j < 10; j++)
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ #pragma omp for simd schedule(dynamic, 5)
+ for (i = 0; i < 10; i++)
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ #pragma omp master
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ #pragma omp parallel
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ {
+ #pragma omp parallel
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ for (i = 0; i < 10; i++)
+ #pragma omp parallel for
+ for (j = 0; j < 10; j++)
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ for (i = 0; i < 10; i++)
+ #pragma omp parallel for simd
+ for (j = 0; j < 10; j++)
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ #pragma omp single
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ #pragma omp task
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ #pragma omp taskgroup
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ #pragma omp taskloop simd
+ for (i = 0; i < 10; i++)
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+}
+
+void
+f2 (int d, int e, int f)
+{
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp ordered
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (d) /* { dg-warning "ambiguous" } */
+ #pragma omp ordered threads
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (e)
+ #pragma omp ordered
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (f)
+ #pragma omp ordered threads
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/Wparentheses-2.c b/gcc/testsuite/c-c++-common/gomp/Wparentheses-2.c
new file mode 100644
index 00000000000..4341b223236
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/Wparentheses-2.c
@@ -0,0 +1,452 @@
+/* PR c/70436 */
+/* { dg-additional-options "-Wparentheses" } */
+
+int a, b, c;
+void bar (void);
+void baz (void);
+void f1 (void);
+#pragma omp declare target to (bar, baz, f1, a, b, c)
+
+void
+f1 (void)
+{
+ int i, j;
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp distribute
+ for (i = 0; i < 10; i++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ for (i = 0; i < 10; i++)
+ #pragma omp distribute simd
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a)
+ #pragma omp distribute parallel for
+ for (i = 0; i < 10; i++)
+ if (b) /* { dg-warning "ambiguous" } */
+ #pragma omp parallel for
+ for (j = 0; j < 10; j++)
+ if (c)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp distribute parallel for simd collapse(2)
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a)
+ #pragma omp distribute
+ for (i = 0; i < 10; i++)
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ {
+ #pragma omp distribute simd
+ for (i = 0; i < 10; ++i)
+ if (b)
+ bar ();
+ }
+ else baz ();
+
+ if (a)
+ #pragma omp distribute parallel for collapse(2)
+ for (i = 0; i < 10; i++)
+ {
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ for (i = 0; i < 10; i++)
+ #pragma omp distribute parallel for simd
+ for (j = 0; j < 10; j++)
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+}
+
+void
+f2 (void)
+{
+ int i, j;
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target teams distribute
+ for (i = 0; i < 10; i++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ for (i = 0; i < 10; i++)
+ #pragma omp target teams distribute simd
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target teams distribute parallel for
+ for (i = 0; i < 10; i++)
+ if (b) /* { dg-warning "ambiguous" } */
+ #pragma omp parallel for
+ for (j = 0; j < 10; j++)
+ if (c)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target teams distribute parallel for simd collapse(2)
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target teams
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target
+ #pragma omp parallel
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target parallel
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target simd
+ for (i = 0; i < 10; i++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target simd collapse(2)
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target teams distribute
+ for (i = 0; i < 10; i++)
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ {
+ #pragma omp target teams distribute simd
+ for (i = 0; i < 10; ++i)
+ if (b)
+ bar ();
+ }
+ else baz ();
+
+ if (a)
+ #pragma omp target teams distribute parallel for collapse(2)
+ for (i = 0; i < 10; i++)
+ {
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ for (i = 0; i < 10; i++)
+ #pragma omp target teams distribute parallel for simd
+ for (j = 0; j < 10; j++)
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target teams
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target
+ #pragma omp parallel
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ #pragma omp target
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target parallel
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target simd
+ for (i = 0; i < 10; i++)
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ #pragma omp target simd
+ for (i = 0; i < 10; i++)
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target simd collapse(2)
+ for (i = 0; i < 10; i++)
+ { {
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+ } }
+
+ if (a)
+ #pragma omp target simd collapse(2)
+ for (i = 0; i < 10; i++)
+ { {
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ }
+ }
+ else
+ baz ();
+}
+
+void
+f3 (void)
+{
+ int i, j;
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target
+ #pragma omp teams distribute
+ for (i = 0; i < 10; i++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ for (i = 0; i < 10; i++)
+ #pragma omp target
+ #pragma omp teams distribute simd
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target
+ #pragma omp teams distribute parallel for
+ for (i = 0; i < 10; i++)
+ if (b) /* { dg-warning "ambiguous" } */
+ #pragma omp parallel for
+ for (j = 0; j < 10; j++)
+ if (c)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd collapse(2)
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target
+ #pragma omp teams
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target
+ #pragma omp teams
+ #pragma omp parallel
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target
+ #pragma omp teams distribute
+ for (i = 0; i < 10; i++)
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ {
+ #pragma omp target
+ #pragma omp teams distribute simd
+ for (i = 0; i < 10; ++i)
+ if (b)
+ bar ();
+ }
+ else baz ();
+
+ if (a)
+ #pragma omp target
+ #pragma omp teams distribute parallel for collapse(2)
+ for (i = 0; i < 10; i++)
+ {
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ for (i = 0; i < 10; i++)
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd
+ for (j = 0; j < 10; j++)
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target
+ #pragma omp teams
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target
+ #pragma omp teams
+ #pragma omp parallel
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+}
+
+void
+f4 (void)
+{
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target data map (tofrom: b)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target data map (tofrom: b)
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/Wparentheses-3.c b/gcc/testsuite/c-c++-common/gomp/Wparentheses-3.c
new file mode 100644
index 00000000000..1688d1062d4
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/Wparentheses-3.c
@@ -0,0 +1,338 @@
+/* PR c/70436 */
+/* { dg-additional-options "-Wparentheses -fno-openmp" } */
+
+int a, b, c;
+void bar (void);
+void baz (void);
+
+void
+f1 (void)
+{
+ int i, j;
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp for
+ for (i = 0; i < 10; i++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ while (1)
+ #pragma omp for
+ for (i = 0; i < 10; i++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ for (i = 0; i < 10; i++)
+ #pragma omp for
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a)
+ #pragma omp for
+ for (i = 0; i < 10; i++)
+ if (b) /* { dg-warning "ambiguous" } */
+ #pragma omp parallel for
+ for (j = 0; j < 10; j++)
+ if (c)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp taskloop
+ for (i = 0; i < 10; i++)
+ if (b)
+ #pragma omp parallel for
+ for (j = 0; j < 10; j++)
+ if (c)
+ bar ();
+ else
+ baz ();
+ else
+ bar ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp taskloop simd
+ for (i = 0; i < 10; i++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp for collapse(2)
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp critical
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ for (i = 0; i < 10; i++)
+ #pragma omp simd
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp for simd schedule(runtime)
+ for (i = 0; i < 10; i++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp master
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp parallel
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ for (i = 0; i < 10; i++)
+ #pragma omp parallel for
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ for (i = 0; i < 10; i++)
+ #pragma omp parallel for simd
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp single
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp task
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp taskgroup
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a)
+ #pragma omp for
+ for (i = 0; i < 10; i++)
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ {
+ #pragma omp taskloop
+ for (i = 0; i < 10; ++i)
+ if (b)
+ bar ();
+ }
+ else baz ();
+
+ if (a)
+ #pragma omp for collapse(2)
+ for (i = 0; i < 10; i++)
+ {
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ #pragma omp critical
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ for (i = 0; i < 10; i++)
+ #pragma omp simd
+ for (j = 0; j < 10; j++)
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ #pragma omp for simd schedule(dynamic, 5)
+ for (i = 0; i < 10; i++)
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ #pragma omp master
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ #pragma omp parallel
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ {
+ #pragma omp parallel
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ for (i = 0; i < 10; i++)
+ #pragma omp parallel for
+ for (j = 0; j < 10; j++)
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ for (i = 0; i < 10; i++)
+ #pragma omp parallel for simd
+ for (j = 0; j < 10; j++)
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ #pragma omp single
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ #pragma omp task
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ #pragma omp taskgroup
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ #pragma omp taskloop simd
+ for (i = 0; i < 10; i++)
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+}
+
+void
+f2 (int d, int e, int f)
+{
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp ordered
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (d) /* { dg-warning "ambiguous" } */
+ #pragma omp ordered threads
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (e)
+ #pragma omp ordered
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (f)
+ #pragma omp ordered threads
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/Wparentheses-4.c b/gcc/testsuite/c-c++-common/gomp/Wparentheses-4.c
new file mode 100644
index 00000000000..d44cdcd5756
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/Wparentheses-4.c
@@ -0,0 +1,452 @@
+/* PR c/70436 */
+/* { dg-additional-options "-Wparentheses -fno-openmp" } */
+
+int a, b, c;
+void bar (void);
+void baz (void);
+void f1 (void);
+#pragma omp declare target to (bar, baz, f1, a, b, c)
+
+void
+f1 (void)
+{
+ int i, j;
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp distribute
+ for (i = 0; i < 10; i++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ for (i = 0; i < 10; i++)
+ #pragma omp distribute simd
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a)
+ #pragma omp distribute parallel for
+ for (i = 0; i < 10; i++)
+ if (b) /* { dg-warning "ambiguous" } */
+ #pragma omp parallel for
+ for (j = 0; j < 10; j++)
+ if (c)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp distribute parallel for simd collapse(2)
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a)
+ #pragma omp distribute
+ for (i = 0; i < 10; i++)
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ {
+ #pragma omp distribute simd
+ for (i = 0; i < 10; ++i)
+ if (b)
+ bar ();
+ }
+ else baz ();
+
+ if (a)
+ #pragma omp distribute parallel for collapse(2)
+ for (i = 0; i < 10; i++)
+ {
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ for (i = 0; i < 10; i++)
+ #pragma omp distribute parallel for simd
+ for (j = 0; j < 10; j++)
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+}
+
+void
+f2 (void)
+{
+ int i, j;
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target teams distribute
+ for (i = 0; i < 10; i++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ for (i = 0; i < 10; i++)
+ #pragma omp target teams distribute simd
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target teams distribute parallel for
+ for (i = 0; i < 10; i++)
+ if (b) /* { dg-warning "ambiguous" } */
+ #pragma omp parallel for
+ for (j = 0; j < 10; j++)
+ if (c)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target teams distribute parallel for simd collapse(2)
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target teams
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target
+ #pragma omp parallel
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target parallel
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target simd
+ for (i = 0; i < 10; i++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target simd collapse(2)
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target teams distribute
+ for (i = 0; i < 10; i++)
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ {
+ #pragma omp target teams distribute simd
+ for (i = 0; i < 10; ++i)
+ if (b)
+ bar ();
+ }
+ else baz ();
+
+ if (a)
+ #pragma omp target teams distribute parallel for collapse(2)
+ for (i = 0; i < 10; i++)
+ {
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ for (i = 0; i < 10; i++)
+ #pragma omp target teams distribute parallel for simd
+ for (j = 0; j < 10; j++)
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target teams
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target
+ #pragma omp parallel
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ #pragma omp target
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target parallel
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target simd
+ for (i = 0; i < 10; i++)
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ #pragma omp target simd
+ for (i = 0; i < 10; i++)
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target simd collapse(2)
+ for (i = 0; i < 10; i++)
+ { {
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+ } }
+
+ if (a)
+ #pragma omp target simd collapse(2)
+ for (i = 0; i < 10; i++)
+ { {
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ }
+ }
+ else
+ baz ();
+}
+
+void
+f3 (void)
+{
+ int i, j;
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target
+ #pragma omp teams distribute
+ for (i = 0; i < 10; i++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ for (i = 0; i < 10; i++)
+ #pragma omp target
+ #pragma omp teams distribute simd
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target
+ #pragma omp teams distribute parallel for
+ for (i = 0; i < 10; i++)
+ if (b) /* { dg-warning "ambiguous" } */
+ #pragma omp parallel for
+ for (j = 0; j < 10; j++)
+ if (c)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd collapse(2)
+ for (i = 0; i < 10; i++)
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target
+ #pragma omp teams
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target
+ #pragma omp teams
+ #pragma omp parallel
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target
+ #pragma omp teams distribute
+ for (i = 0; i < 10; i++)
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ {
+ #pragma omp target
+ #pragma omp teams distribute simd
+ for (i = 0; i < 10; ++i)
+ if (b)
+ bar ();
+ }
+ else baz ();
+
+ if (a)
+ #pragma omp target
+ #pragma omp teams distribute parallel for collapse(2)
+ for (i = 0; i < 10; i++)
+ {
+ for (j = 0; j < 10; j++)
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+
+ if (a)
+ for (i = 0; i < 10; i++)
+ #pragma omp target
+ #pragma omp teams distribute parallel for simd
+ for (j = 0; j < 10; j++)
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target
+ #pragma omp teams
+ {
+ if (b)
+ bar ();
+ }
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target
+ #pragma omp teams
+ #pragma omp parallel
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+}
+
+void
+f4 (void)
+{
+ if (a) /* { dg-warning "ambiguous" } */
+ #pragma omp target data map (tofrom: b)
+ if (b)
+ bar ();
+ else
+ baz ();
+
+ if (a)
+ #pragma omp target data map (tofrom: b)
+ {
+ if (b)
+ bar ();
+ else
+ baz ();
+ }
+}
diff --git a/gcc/testsuite/c-c++-common/pr70651.c b/gcc/testsuite/c-c++-common/pr70651.c
new file mode 100644
index 00000000000..a91a2d8fc88
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr70651.c
@@ -0,0 +1,9 @@
+/* PR c/70651 */
+/* { dg-do compile } */
+/* { dg-prune-output "\[^\n\r\]*first argument to .va_arg. not of type .va_list.\[^\n\r\]*" } */
+
+void fn1 ()
+{
+ char **a = 0;
+ __builtin_va_arg (a, char **);
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/vla11.C b/gcc/testsuite/g++.dg/cpp1y/vla11.C
deleted file mode 100644
index 36609abe53b..00000000000
--- a/gcc/testsuite/g++.dg/cpp1y/vla11.C
+++ /dev/null
@@ -1,712 +0,0 @@
-// PR c++/69517 - [5/6 regression] SEGV on a VLA with excess initializer
-// elements
-// PR c++/70019 - VLA size overflow not detected
-//
-// Runtime test to verify that attempting to either construct a VLA with
-// erroneous bounds, or initialize one with an initializer-list that
-// contains more elements than the VLA's non-constant (runtime) bounds
-// causes an exception to be thrown. Test also verifies that valid
-// VLAs and their initializers don't cause such an exception.
-
-// { dg-do run { target c++11 } }
-// { dg-additional-options "-Wno-vla" }
-
-#pragma GCC diagnostic ignored "-Wvla"
-
-#define INT_MAX __INT_MAX__
-#define LONG_MAX __LONG_MAX__
-#define SIZE_MAX __SIZE_MAX__
-#define UINT_MAX (~0U)
-#define ULONG_MAX (~0LU)
-
-#define INT_MIN (-__INT_MAX__ - 1)
-#define LONG_MIN (-__LONG_MAX__ - 1)
-
-// The size of the largest allowed VLA in bytes. Bigger objects
-// cause an exception to be thrown. Unless the maximum size is
-// obscenely large, smaller objects should be successfully created
-// provided there's enough stack space. See TEST_NEAR_VLA_MAX_SIZE
-// below.
-#define MAX (__SIZE_MAX__ / 2)
-
-// Define to non-zero to exercise very large VLAs with size just
-// below the implementation-defined maximum.
-#define TEST_NEAR_VLA_MAX_SIZE 0
-
-// Define to zero to enable tests that cause an ICE due to c++/58646.
-#define BUG_58646 1
-
-// Helper macro to make it possible to pass as one multpile arguments
-// to another macro.
-#define Init(...) __VA_ARGS__
-
-typedef __SIZE_TYPE__ size_t;
-
-// Incremented for each test failure.
-int fail;
-
-// Used to convert a constant array dimension to a non-constant one.
-template <class T>
-T d (T n)
-{
- return n;
-}
-
-// Verify either that an expected exception has been thrown or that
-// one hasn't been thrown if one isn't expected.
-int __attribute__ ((noclone, noinline))
-sink (void *p, int line, bool expect, const char *expr)
-{
- if (!p != expect)
- {
- __builtin_printf ("line %i: Assertion failed: '%s': "
- "exception unexpectedly %sthrown\n",
- line, expr, !p ? "" : "not ");
- ++fail;
- }
- else
- {
-#if defined DEBUG && DEBUG
- __builtin_printf ("line %i: Assertion passed: '%s': "
- "exception %sthrown as expected\n",
- line, expr, !p ? "" : "not ");
-#endif
- }
- return 0;
-}
-
-#define _CAT(name, line) name ## line
-#define CAT(name, line) _CAT (name, line)
-
-#define STR(...) #__VA_ARGS__
-
-// Type to exercise VLA with. TYPESIZE is the size of the type in bytes.
-// Using a template serves two purposes. First, it makes it possible to
-// parameterize the test on VLAs of different size. Second, it verifies
-// that the checking code can deal with templates (i.e., completes
-// the element type of the VLA when necessary).
-template <unsigned TypeSize>
-union TestType
-{
- char data;
- char padding [TypeSize];
-};
-
-// Test function invoked with a pointer to each test case. Must
-// return a value though what value doesn't matter.
-int __attribute__ ((noclone, noinline))
-tester (int (*testcase)(const char*),
- const char *str, int line, bool expect)
-{
- try
- {
- return testcase (str);
- }
- catch (...)
- {
- return sink (0, line, expect, str);
- }
-}
-
-// Macro to define a unique specialization of a function template to
-// exercise a VLA of type T, rank N, with dimensions given by Dims
-// and initializer Init. Expect is true when the VLA initialization
-// is expected to trigger an exception.
-// The macro creates a unique global dummy int object and initializes
-// it with the result of the function. The dummy object servers no
-// other purpose but to call the function. The function verifies
-// the expected postconditions.
-#define TEST(TypeSize, Dims, Init, Expect) \
- static int CAT (testcase, __LINE__)(const char *str) \
- { \
- TestType<TypeSize> vla Dims Init; \
- static_assert (sizeof (TestType<TypeSize>) == TypeSize, \
- "wrong test type size"); \
- return sink (vla, __LINE__, Expect, str); \
- } \
- const int CAT (dummy, __LINE__) \
- = tester (CAT (testcase, __LINE__), \
- "T<" #TypeSize "> a" #Dims " " STR (Init) ";", \
- __LINE__, Expect)
-
-
-// Create and run a test function exercising a VLA definition
-// of one of the following forms:
-// TestType<Size> VLA Dims; // uninitialized (with Init ())
-// or:
-// TestType<Size> VLA Dims Init; // initialized (with = Init ({...})
-//
-// +-- Element Size (in Bytes)
-// | +-- VLA Dimensions (constant as in [3], otherwise d(3))
-// | | +-- VLA Initializer Expression (if any)
-// | | | +-- Expect Exception
-// | | | |
-// V V V V
-TEST (1, [d(0)], Init (/* none*/), true); // uninitialized
-
-#if !BUG_58646
-// The following causes an ICE due to c++/58646.
-TEST (1, [d(0)], Init ({}), true);
-#endif
-TEST (1, [d(0)], Init ({1}), true); // initialized with " {1}"
-TEST (1, [d(0)], = Init ({1}), true); // initialized with "= {1}"
-
-TEST (1, [d(1)], Init (), false);
-TEST (1, [d(1)], Init ({}), false);
-TEST (1, [d(1)], = Init ({}), false);
-TEST (1, [d(1)], Init ({1}), false);
-TEST (1, [d(1)], = Init ({1}), false);
-TEST (1, [d(1)], Init ({1, 2}), true);
-TEST (1, [d(1)], = Init ({1, 2}), true);
-
-TEST (1, [d(2)], Init (), false);
-TEST (1, [d(2)], Init ({}), false);
-TEST (1, [d(2)], Init ({1}), false);
-TEST (1, [d(2)], Init ({1, 2}), false);
-TEST (1, [d(2)], Init ({1, 2, 3}), true);
-
-#if TEST_NEAR_VLA_MAX_SIZE
-// Very large but not erroneous one dimensional VLAs.
-TEST (1, [d(MAX)], Init (), false);
-TEST (1, [d(MAX)], Init ({}), false);
-TEST (1, [d(MAX)], Init ({1}), false);
-TEST (1, [d(MAX)], Init ({1, 2}), false);
-TEST (1, [d(MAX)], Init ({1, 2, 3}), false);
-
-TEST ( 2, [d(MAX / 2)], Init (), false);
-TEST ( 4, [d(MAX / 4)], Init (), false);
-TEST ( 8, [d(MAX / 8)], Init (), false);
-TEST (16, [d(MAX / 16)], Init (), false);
-TEST (32, [d(MAX / 32)], Init (), false);
-TEST (64, [d(MAX / 64)], Init (), false);
-#endif // TEST_NEAR_VLA_MAX_SIZE
-
-// One dimensional VLAs with a negative upper bound.
-TEST (1, [d(LONG_MIN)], Init (), true);
-TEST (1, [d(INT_MIN)], Init (), true);
-TEST (1, [d(-1234)], Init (), true);
-TEST (1, [d(-1)], Init (), true);
-
-// Excessively large one dimensional VLAs.
-TEST ( 1, [d(MAX + 1)], Init (), true);
-TEST ( 2, [d(MAX)], Init (), true);
-TEST ( 4, [d(MAX / 2)], Init (), true);
-TEST ( 4, [d(MAX / 3)], Init (), true);
-TEST ( 8, [d(MAX / 2)], Init (), true);
-TEST ( 8, [d(MAX / 3)], Init (), true);
-TEST ( 8, [d(MAX / 4)], Init (), true);
-TEST ( 8, [d(MAX / 5)], Init (), true);
-TEST ( 8, [d(MAX / 6)], Init (), true);
-TEST ( 8, [d(MAX / 7)], Init (), true);
-TEST (16, [d(MAX / 15)], Init (), true);
-TEST (32, [d(MAX / 31)], Init (), true);
-TEST (64, [d(MAX / 63)], Init (), true);
-TEST ( 1, [d(SIZE_MAX)], Init (), true);
-
-TEST (1, [d(LONG_MIN)], Init ({}), true);
-TEST (1, [d(INT_MIN)], Init ({}), true);
-TEST (1, [d(-1)], Init ({}), true);
-
-TEST (1, [d(SIZE_MAX)], Init ({}), true);
-
-TEST (1, [d(LONG_MIN)], Init ({0}), true);
-TEST (1, [d(INT_MIN)], Init ({0}), true);
-TEST (1, [d(-1)], Init ({0}), true);
-
-TEST (1, [d(SIZE_MAX)], Init ({0}), true);
-
-TEST ( 1, [d(SIZE_MAX/2) + 1], Init (), true);
-TEST ( 2, [d(SIZE_MAX/4) + 1], Init (), true);
-TEST ( 4, [d(SIZE_MAX/8) + 1], Init (), true);
-TEST ( 8, [d(SIZE_MAX/16) + 1], Init (), true);
-TEST (16, [d(SIZE_MAX/32) + 1], Init (), true);
-
-TEST ( 1, [d(SIZE_MAX/2) + 1], Init ({1}), true);
-TEST ( 2, [d(SIZE_MAX/4) + 1], Init ({1, 2}), true);
-TEST ( 4, [d(SIZE_MAX/8) + 1], Init ({1, 2, 3}), true);
-TEST ( 8, [d(SIZE_MAX/16) + 1], Init ({1, 2, 3, 4}), true);
-TEST (16, [d(SIZE_MAX/32) + 1], Init ({1, 2, 3, 4, 5}), true);
-
-// Two dimensional VLAs with one constant bound.
-
-TEST (1, [1][d(0)], Init (), true);
-
-#if !BUG_58646
-// The following causes an ICE due to c++/58646.
-TEST (1, [1][d(0)], Init ({}), true);
-#endif
-TEST (1, [ ][d(0)], Init ({{1}}), true); // unspecified bound
-TEST (1, [1][d(0)], Init ({{1}}), true);
-
-TEST (1, [1][d(1)], Init (), false);
-TEST (1, [1][d(1)], Init ({{1}}), false);
-TEST (1, [1][d(1)], Init ({{1, 2}}), true);
-TEST (1, [ ][d(1)], Init ({{1, 2}}), true);
-
-TEST (1, [1][d(2)], Init (), false);
-TEST (1, [1][d(2)], Init ({{1}}), false);
-TEST (1, [1][d(2)], Init ({{1, 2}}), false);
-TEST (1, [ ][d(2)], Init ({{1, 2}}), false);
-TEST (1, [1][d(2)], Init ({{1, 2, 3}}), true);
-TEST (1, [ ][d(2)], Init ({{1, 2, 3}}), true);
-
-TEST (1, [2][d(1)], Init (), false);
-TEST (1, [2][d(1)], Init ({{1}}), false);
-TEST (1, [ ][d(1)], Init ({{1}}), false);
-TEST (1, [2][d(1)], Init ({{1}, {2}}), false);
-TEST (1, [ ][d(1)], Init ({{1}, {2}}), false);
-TEST (1, [2][d(1)], Init ({{1, 2}}), true);
-TEST (1, [ ][d(1)], Init ({{1, 2}}), true);
-TEST (1, [2][d(1)], Init ({{1}, {2, 3}}), true);
-TEST (1, [ ][d(1)], Init ({{1}, {2, 3}}), true);
-TEST (1, [2][d(1)], Init ({{1, 2, 3}}), true);
-TEST (1, [ ][d(1)], Init ({{1, 2, 3}}), true);
-TEST (1, [2][d(1)], Init ({{1, 2, 3}, {4}}), true);
-TEST (1, [ ][d(1)], Init ({{1, 2, 3}, {4}}), true);
-TEST (1, [2][d(1)], Init ({{1, 2}, {3, 4}}), true);
-TEST (1, [ ][d(1)], Init ({{1, 2}, {3, 4}}), true);
-
-TEST (1, [2][d(2)], Init (), false);
-TEST (1, [2][d(2)], Init ({{1}}), false);
-TEST (1, [2][d(2)], Init ({{1, 2}}), false);
-TEST (1, [2][d(2)], Init ({{1, 2}, {3}}), false);
-TEST (1, [2][d(2)], Init ({{1, 2}, {3, 4}}), false);
-TEST (1, [2][d(2)], Init ({{1}, {2, 3, 4}}), true);
-TEST (1, [2][d(2)], Init ({{1}, {2, 3, 4, 5}}), true);
-TEST (1, [2][d(2)], Init ({{1, 2}, {3, 4, 5}}), true);
-TEST (1, [2][d(2)], Init ({{1, 2, 3}, {4, 5}}), true);
-TEST (1, [2][d(2)], Init ({{1, 2, 3}, {4, 5, 6}}), true);
-
-TEST (1, [2][d(3)], Init (), false);
-TEST (1, [2][d(3)], Init ({{1}}), false);
-TEST (1, [2][d(3)], Init ({{1, 2}}), false);
-TEST (1, [2][d(3)], Init ({{1, 2}, {3}}), false);
-TEST (1, [2][d(3)], Init ({{1, 2}, {3, 4}}), false);
-TEST (1, [2][d(3)], Init ({{1}, {2, 3, 4}}), false);
-TEST (1, [2][d(3)], Init ({{1}, {2, 3, 4, 5}}), true);
-TEST (1, [2][d(3)], Init ({{1, 2}, {3, 4, 5}}), false);
-TEST (1, [2][d(3)], Init ({{1, 2, 3}, {4, 5}}), false);
-TEST (1, [2][d(3)], Init ({{1, 2, 3}, {4, 5, 6}}), false);
-TEST (1, [2][d(3)], Init ({{1, 2, 3}, {4, 5, 6, 7}}), true);
-TEST (1, [2][d(3)], Init ({{1, 2, 3, 4}, {5, 6, 7}}), true);
-TEST (1, [2][d(3)], Init ({{1, 2, 3, 4, 5}, {6, 7}}), true);
-TEST (1, [2][d(3)], Init ({{1, 2, 3, 4, 5, 6}, {7}}), true);
-TEST (1, [2][d(3)], Init ({{1, 2, 3, 4, 5, 6, 7}}), true);
-
-#if TEST_NEAR_VLA_MAX_SIZE
-TEST (1, [1][d(MAX)], Init (), false);
-# if !BUG_58646
-// The following causes an ICE due to c++/58646.
-TEST (1, [1][d(MAX)], Init ({}), false);
-# endif
-TEST (1, [1][d(MAX)], Init ({{1}}), false);
-TEST (1, [1][d(MAX)], Init ({{1, 2}}), false);
-TEST (1, [1][d(MAX)], Init ({{1, 2, 3}}), false);
-TEST (1, [1][d(MAX)], Init ({{1, 2, 3, 4}}), false);
-
-TEST (1, [2][d(MAX / 2)], Init (), false);
-TEST (1, [2][d(MAX / 2)], Init ({{1}}), false);
-TEST (1, [2][d(MAX / 2)], Init ({{1, 2}}), false);
-TEST (1, [2][d(MAX / 2)], Init ({{1, 2, 3}}), false);
-TEST (1, [2][d(MAX / 2)], Init ({{1, 2, 3, 4}}), false);
-TEST (1, [2][d(MAX / 2)], Init ({{1}, {2}}), false);
-TEST (1, [2][d(MAX / 2)], Init ({{1}, {2, 3}}), false);
-TEST (1, [2][d(MAX / 2)], Init ({{1, 2}, {3}}), false);
-TEST (1, [2][d(MAX / 2)], Init ({{1, 2}, {3, 4}}), false);
-TEST (1, [2][d(MAX / 2)], Init ({{1, 2, 3}, {4}}), false);
-TEST (1, [2][d(MAX / 2)], Init ({{1, 2, 3}, {4, 5}}), false);
-TEST (1, [2][d(MAX / 2)], Init ({{1, 2, 3}, {4, 5, 6}}), false);
-#endif // TEST_NEAR_VLA_MAX_SIZE
-
-// Excessively large two dimensional VLAs.
-TEST (1, [1][d(LONG_MIN)], Init (), true);
-TEST (1, [1][d(INT_MIN)], Init (), true);
-TEST (1, [1][d(-1)], Init (), true);
-
-TEST (1, [1][d(SIZE_MAX)], Init (), true);
-
-#if !BUG_58646
-// The following cause an ICE due to c++/58646.
-TEST (1, [1][d(LONG_MIN)], Init ({}), true);
-TEST (1, [1][d(INT_MIN)], Init ({}), true);
-TEST (1, [1][d(-1)], Init ({}), true);
-TEST (1, [1][d(SIZE_MAX)], Init ({}), true);
-#endif
-
-TEST (1, [1][d(LONG_MIN)], Init ({{0}}), true);
-TEST (1, [1][d(INT_MIN)], Init ({{0}}), true);
-TEST (1, [1][d(-1)], Init ({{0}}), true);
-TEST (1, [1][d(SIZE_MAX)], Init ({{0}}), true);
-
-TEST (1, [d(LONG_MIN)][1], Init (), true);
-TEST (1, [d(INT_MIN)][1], Init (), true);
-TEST (1, [d(-1)][1], Init (), true);
-TEST (1, [d(SIZE_MAX)][1], Init (), true);
-
-TEST (1, [d(LONG_MIN)][1], Init ({}), true);
-TEST (1, [d(INT_MIN)][1], Init ({}), true);
-TEST (1, [d(-1)][1], Init ({}), true);
-TEST (1, [d(SIZE_MAX)][1], Init ({}), true);
-
-TEST (1, [d(LONG_MIN)][1], Init ({{0}}), true);
-TEST (1, [d(INT_MIN)][1], Init ({{0}}), true);
-TEST (1, [d(-1)][1], Init ({{0}}), true);
-TEST (1, [d(SIZE_MAX)][1], Init ({{0}}), true);
-
-// Two dimensional VLAs with no constant bound.
-TEST (1, [d(0)][d(0)], Init (), true);
-TEST (1, [d(0)][d(0)], Init ({}), true);
-#if !BUG_58646
-// The following cause an ICE due to c++/58646.
-TEST (1, [d(0)][d(0)], Init ({{}}), true);
-TEST (1, [d(0)][d(0)], Init ({{}, {}}), true);
-#endif
-
-TEST (1, [d(0)][d(0)], Init ({{1}}), true);
-TEST (1, [d(0)][d(0)], Init ({{1, 2}}), true);
-#if !BUG_58646
-TEST (1, [d(0)][d(0)], Init ({{1}, {}}), true);
-TEST (1, [d(0)][d(0)], Init ({{}, {1}}), true);
-#endif
-
-TEST (1, [d(1)][d(0)], Init (), true);
-TEST (1, [d(1)][d(0)], Init ({}), true);
-TEST (1, [d(1)][d(0)], Init ({{1}}), true);
-
-TEST (1, [d(1)][d(1)], Init (), false);
-TEST (1, [d(1)][d(1)], Init ({{1}}), false);
-TEST (1, [d(1)][d(1)], Init ({{1, 2}}), true);
-
-TEST (1, [d(1)][d(2)], Init (), false);
-TEST (1, [d(1)][d(2)], Init ({{1}}), false);
-TEST (1, [d(1)][d(2)], Init ({{1, 2}}), false);
-TEST (1, [d(1)][d(2)], Init ({{1, 2, 3}}), true);
-
-TEST (1, [d(2)][d(1)], Init (), false);
-TEST (1, [d(2)][d(1)], Init ({{1}}), false);
-TEST (1, [d(2)][d(1)], Init ({{1}, {2}}), false);
-TEST (1, [d(2)][d(1)], Init ({{1, 2}}), true);
-TEST (1, [d(2)][d(1)], Init ({{1}, {2, 3}}), true);
-TEST (1, [d(2)][d(1)], Init ({{1, 2, 3}}), true);
-TEST (1, [d(2)][d(1)], Init ({{1, 2, 3}, {4}}), true);
-TEST (1, [d(2)][d(1)], Init ({{1, 2}, {3, 4}}), true);
-
-TEST (1, [d(2)][d(2)], Init (), false);
-TEST (1, [d(2)][d(2)], Init ({{1}}), false);
-TEST (1, [d(2)][d(2)], Init ({{1, 2}}), false);
-TEST (1, [d(2)][d(2)], Init ({{1, 2}, {3}}), false);
-TEST (1, [d(2)][d(2)], Init ({{1, 2}, {3, 4}}), false);
-TEST (1, [d(2)][d(2)], Init ({{1}, {2, 3, 4}}), true);
-TEST (1, [d(2)][d(2)], Init ({{1}, {2, 3, 4, 5}}), true);
-TEST (1, [d(2)][d(2)], Init ({{1, 2}, {3, 4, 5}}), true);
-TEST (1, [d(2)][d(2)], Init ({{1, 2, 3}, {4, 5}}), true);
-TEST (1, [d(2)][d(2)], Init ({{1, 2, 3}, {4, 5, 6}}), true);
-
-TEST (1, [d(2)][d(3)], Init (), false);
-TEST (1, [d(2)][d(3)], Init ({{1}}), false);
-TEST (1, [d(2)][d(3)], Init ({{1, 2}}), false);
-TEST (1, [d(2)][d(3)], Init ({{1, 2}, {3}}), false);
-TEST (1, [d(2)][d(3)], Init ({{1, 2}, {3, 4}}), false);
-TEST (1, [d(2)][d(3)], Init ({{1}, {2, 3, 4}}), false);
-TEST (1, [d(2)][d(3)], Init ({{1}, {2, 3, 4, 5}}), true);
-TEST (1, [d(2)][d(3)], Init ({{1, 2}, {3, 4, 5}}), false);
-TEST (1, [d(2)][d(3)], Init ({{1, 2, 3}, {4, 5}}), false);
-TEST (1, [d(2)][d(3)], Init ({{1, 2, 3}, {4, 5, 6}}), false);
-TEST (1, [d(2)][d(3)], Init ({{1, 2, 3}, {4, 5, 6, 7}}), true);
-TEST (1, [d(2)][d(3)], Init ({{1, 2, 3, 4}, {5, 6, 7}}), true);
-TEST (1, [d(2)][d(3)], Init ({{1, 2, 3, 4, 5}, {6, 7}}), true);
-TEST (1, [d(2)][d(3)], Init ({{1, 2, 3, 4, 5, 6}, {7}}), true);
-TEST (1, [d(2)][d(3)], Init ({{1, 2, 3, 4, 5, 6, 7}}), true);
-
-#if TEST_NEAR_VLA_MAX_SIZE
-TEST (1, [d(1)][d(MAX)], Init (), false);
-TEST (1, [d(1)][d(MAX)], Init ({}), false);
-TEST (1, [d(1)][d(MAX)], Init ({{1}}), false);
-TEST (1, [d(1)][d(MAX)], Init ({{1, 2}}), false);
-TEST (1, [d(1)][d(MAX)], Init ({{1, 2, 3}}), false);
-TEST (1, [d(1)][d(MAX)], Init ({{1, 2, 3, 4}}), false);
-TEST (1, [d(1)][d(MAX)], Init ({{1, 2, 3, 4, 5}}), false);
-TEST (1, [d(1)][d(MAX)], Init ({{1, 2, 3, 4, 5, 6}}), false);
-TEST (1, [d(1)][d(MAX)], Init ({{1, 2, 3, 4, 5, 6, 7}}), false);
-TEST (1, [d(1)][d(MAX)], Init ({{1, 2, 3, 4, 5, 6, 7, 8}}), false);
-TEST (1, [d(1)][d(MAX)], Init ({{1, 2, 3, 4, 5, 6, 7, 8, 9}}), false);
-
-TEST (1, [d(2)][d(MAX / 2)], Init (), false);
-TEST (1, [d(2)][d(MAX / 2)], Init ({{1}}), false);
-TEST (1, [d(2)][d(MAX / 2)], Init ({{1, 2}}), false);
-TEST (1, [d(2)][d(MAX / 2)], Init ({{1, 2, 3}}), false);
-TEST (1, [d(2)][d(MAX / 2)], Init ({{1, 2, 3, 4}}), false);
-TEST (1, [d(2)][d(MAX / 2)], Init ({{1, 2, 3, 4, 5}}), false);
-TEST (1, [d(2)][d(MAX / 2)], Init ({{1, 2, 3, 4, 5, 6}}), false);
-TEST (1, [d(2)][d(MAX / 2)], Init ({{1, 2, 3, 4, 5, 6, 7}}), false);
-TEST (1, [d(2)][d(MAX / 2)], Init ({{1, 2, 3, 4, 5, 6, 7, 8}}), false);
-TEST (1, [d(2)][d(MAX / 2)], Init ({{1, 2, 3, 4, 5, 6, 7, 8, 9}}), false);
-TEST (1, [d(2)][d(MAX / 2)], Init ({{1}, {2}}), false);
-TEST (1, [d(2)][d(MAX / 2)], Init ({{1}, {2, 3}}), false);
-TEST (1, [d(2)][d(MAX / 2)], Init ({{1, 2}, {3}}), false);
-TEST (1, [d(2)][d(MAX / 2)], Init ({{1, 2}, {3, 4}}), false);
-TEST (1, [d(2)][d(MAX / 2)], Init ({{1, 2, 3}, {4}}), false);
-TEST (1, [d(2)][d(MAX / 2)], Init ({{1, 2, 3}, {4, 5}}), false);
-TEST (1, [d(2)][d(MAX / 2)], Init ({{1, 2, 3}, {4, 5, 6}}), false);
-#endif
-
-TEST (1, [d(2)][d(MAX)], Init (), true);
-TEST (1, [d(2)][d(MAX)], Init ({{1}}), true);
-TEST (1, [d(MAX)][d(MAX)], Init ({{1, 2}}), true);
-TEST (1, [d(0)][d(MAX)], Init ({{1}, {2}}), true);
-TEST (1, [d(INT_MAX)][d(MAX)], Init ({{1}, {2, 3}}), true);
-TEST (1, [d(SIZE_MAX)][d(MAX)], Init ({{1, 2}, {3, 4}, {5}}), true);
-
-// Erroneous two-dimensional VLAs with size exceeding SIZE_MAX / 2
-// (those must be rejected because no object can be bigger than that,
-// otherwise pointer arithmetic breaks).
-TEST ( 1, [2][d(SIZE_MAX/2)], Init (), true);
-TEST ( 2, [2][d(SIZE_MAX/4)], Init (), true);
-TEST ( 4, [2][d(SIZE_MAX/8)], Init (), true);
-TEST ( 8, [2][d(SIZE_MAX/16)], Init (), true);
-TEST (16, [2][d(SIZE_MAX/32)], Init (), true);
-
-TEST ( 1, [d(SIZE_MAX/2)][2], Init (), true);
-TEST ( 2, [d(SIZE_MAX/4)][2], Init (), true);
-TEST ( 4, [d(SIZE_MAX/8)][2], Init (), true);
-TEST ( 8, [d(SIZE_MAX/16)][2], Init (), true);
-TEST (16, [d(SIZE_MAX/32)][2], Init (), true);
-
-// Verify that the unspecified bound is factored into the computation
-// of the total size.
-TEST ( 1, [][d(SIZE_MAX/2)], Init ({{1}, {2}}), true);
-TEST ( 2, [][d(SIZE_MAX/4)], Init ({{1}, {2}}), true);
-TEST ( 4, [][d(SIZE_MAX/8)], Init ({{1}, {2}}), true);
-TEST ( 8, [][d(SIZE_MAX/16)], Init ({{1}, {2}}), true);
-TEST (16, [][d(SIZE_MAX/32)], Init ({{1}, {2}}), true);
-TEST (16, [][d(SIZE_MAX/64)], Init ({{1}, {2}, {3}}), true);
-
-// Three dimensional VLAs with two constant bounds.
-
-TEST (1, [1][1][d(-1)], Init (), true);
-TEST (1, [1][1][d(0)], Init (), true);
-
-#if !BUG_58646
-// The following causes an ICE due to c++/58646.
-TEST (1, [1][1][d(0)], Init ({}), true);
-TEST (1, [1][1][d(-1)], Init ({{}}), true);
-TEST (1, [1][d(-1)][1], Init ({{}}), true);
-TEST (1, [d(-1)][1][1], Init ({{}}), true);
-
-TEST (1, [1][1][d(0)], Init ({{}}), true);
-TEST (1, [1][d(0)][1], Init ({{}}), true);
-TEST (1, [d(0)][1][1], Init ({{}}), true);
-#endif
-
-TEST (1, [1][1][d(1)], Init (), false);
-
-#if !BUG_58646
-TEST (1, [1][1][d(1)], Init ({{}}), false);
-TEST (1, [1][1][d(1)], Init ({{{}}}), false);
-TEST (1, [1][1][d(1)], Init ({{{1}}}), false);
-#endif
-
-TEST (1, [1][1][d(1)], Init ({{{1, 2}}}), true);
-TEST (1, [1][1][d(1)], Init ({{{1, 2, 3}}}), true);
-
-TEST (1, [1][d(1)][1], Init (), false);
-
-#if !BUG_58646
-TEST (1, [1][d(1)][1], Init ({{}}), false);
-TEST (1, [1][d(1)][1], Init ({{{}}}), false);
-#endif
-
-TEST (1, [1][d(1)][1], Init ({{{1}}}), false);
-TEST (1, [1][d(1)][1], Init ({{{1}, {2}}}), true);
-TEST (1, [1][d(1)][1], Init ({{{1}, {2}, {3}}}), true);
-
-TEST (1, [d(1)][1][1], Init (), false);
-
-#if !BUG_58646
-TEST (1, [d(1)][1][1], Init ({{}}), false);
-TEST (1, [d(1)][1][1], Init ({{{}}}), false);
-#endif
-
-TEST (1, [d(1)][1][1], Init ({{{1}}}), false);
-TEST (1, [d(1)][1][1], Init ({{{1}}, {{2}}}), true);
-TEST (1, [d(1)][1][1], Init ({{{1}}, {{2}}, {{3}}}), true);
-
-TEST (1, [1][1][d(2)], Init (), false);
-
-#if !BUG_58646
-TEST (1, [1][1][d(2)], Init ({{}}), false);
-TEST (1, [1][1][d(2)], Init ({{{}}}), false);
-#endif
-
-TEST (1, [1][1][d(2)], Init ({{{1}}}), false);
-TEST (1, [1][1][d(2)], Init ({{{1, 2}}}), false);
-TEST (1, [1][1][d(2)], Init ({{{1, 2, 3}}}), true);
-
-TEST (1, [1][d(2)][1], Init (), false);
-
-#if !BUG_58646
-TEST (1, [1][d(2)][1], Init ({{}}), false);
-TEST (1, [1][d(2)][1], Init ({{{}}}), false);
-#endif
-TEST (1, [1][d(2)][1], Init ({{{1}}}), false);
-TEST (1, [1][d(2)][1], Init ({{{1}, {2}}}), false);
-TEST (1, [1][d(2)][1], Init ({{{1}, {2}, {3}}}), true);
-
-TEST (1, [d(2)][1][1], Init (), false);
-
-#if !BUG_58646
-TEST (1, [d(2)][1][1], Init ({{}}), false);
-TEST (1, [d(2)][1][1], Init ({{{}}}), false);
-#endif
-TEST (1, [d(2)][1][1], Init ({{{1}}}), false);
-TEST (1, [d(2)][1][1], Init ({{{1}}, {{2}}}), false);
-TEST (1, [d(2)][1][1], Init ({{{1}}, {{2}}, {{3}}}), true);
-
-TEST (1, [1][2][d(2)], Init (), false);
-
-#if !BUG_58646
-TEST (1, [1][2][d(2)], Init ({{}}), false);
-TEST (1, [1][2][d(2)], Init ({{{}}}), false);
-#endif
-
-TEST (1, [1][2][d(2)], Init ({{{1}}}), false);
-TEST (1, [1][2][d(2)], Init ({{{1, 2}}}), false);
-TEST (1, [1][2][d(2)], Init ({{{1, 2, 3}}}), true);
-
-TEST (1, [1][2][d(2)], Init ({{{1}, {2}}}), false);
-TEST (1, [1][2][d(2)], Init ({{{1}, {2, 3}}}), false);
-TEST (1, [1][2][d(2)], Init ({{{1, 2}, {3}}}), false);
-TEST (1, [1][2][d(2)], Init ({{{1, 2}, {3, 4}}}), false);
-TEST (1, [1][2][d(2)], Init ({{{1}, {2, 3, 4}}}), true);
-TEST (1, [1][2][d(2)], Init ({{{1, 2, 3}, {}}}), true);
-TEST (1, [1][2][d(2)], Init ({{{1, 2, 3}, {4}}}), true);
-TEST (1, [1][2][d(2)], Init ({{{1, 2, 3, 4}}}), true);
-TEST (1, [1][2][d(2)], Init ({{{1, 2, 3, 4}, {}}}), true);
-TEST (1, [1][2][d(2)], Init ({{{1, 2, 3, 4}, {5}}}), true);
-
-TEST (1, [2][2][d(2)], Init ({{{1}, {2}}}), false);
-TEST (1, [2][2][d(2)], Init ({{{1}, {2, 3}}}), false);
-TEST (1, [2][2][d(2)], Init ({{{1, 2}}}), false);
-TEST (1, [2][2][d(2)], Init ({{{1, 2}, {3}}}), false);
-TEST (1, [2][2][d(2)], Init ({{{1, 2}, {3, 4}}}), false);
-TEST (1, [2][2][d(2)], Init ({{{1, 2}, {3, 4}}, {{5}}}), false);
-TEST (1, [2][2][d(2)], Init ({{{1, 2}, {3, 4}}, {{5, 6}}}), false);
-TEST (1, [2][2][d(2)], Init ({{{1, 2}, {3, 4}}, {{5, 6}, {7}}}), false);
-TEST (1, [2][2][d(2)], Init ({{{1, 2}, {3, 4}}, {{5, 6}, {7, 8}}}), false);
-
-TEST (1, [2][2][d(2)], Init ({{{1}, {2, 3, 4}}}), true);
-TEST (1, [2][2][d(2)], Init ({{{1, 2, 3}, {}}}), true);
-TEST (1, [2][2][d(2)], Init ({{{1, 2, 3}, {4}}}), true);
-TEST (1, [2][2][d(2)], Init ({{{1, 2, 3, 4}}}), true);
-TEST (1, [2][2][d(2)], Init ({{{1, 2, 3, 4}, {}}}), true);
-TEST (1, [2][2][d(2)], Init ({{{1, 2, 3, 4}, {5}}}), true);
-TEST (1, [2][2][d(2)], Init ({{{1, 2}, {3, 4}}, {{5, 6}, {7, 8, 9}}}), true);
-TEST (1, [2][2][d(2)], Init ({{{1, 2}, {3, 4}}, {{5, 6, 7}, {8, 9}}}), true);
-TEST (1, [2][2][d(2)], Init ({{{1, 2}, {3, 4, 5}}, {{6, 7}, {8, 9}}}), true);
-TEST (1, [2][2][d(2)], Init ({{{1, 2, 3}, {4, 5}}, {{6, 7}, {8, 9}}}), true);
-TEST (1, [2][2][d(2)], Init ({{{1}, {2}}, {{3}, {4, 5, 6}}}), true);
-TEST (1, [2][2][d(2)], Init ({{{1}}, {{2}, {3, 4, 5, 6}}}), true);
-
-// Three dimensional VLAs with one constant bound.
-TEST (1, [2][d(-1)][d(-1)], Init (), true);
-TEST (1, [2][d(-1)][d(0)], Init (), true);
-TEST (1, [2][d(0)][d(-1)], Init (), true);
-TEST (1, [2][d(1)][d(-1)], Init (), true);
-TEST (1, [2][d(1)][d(0)], Init (), true);
-TEST (1, [2][d(-1)][d(1)], Init (), true);
-TEST (1, [2][d(0)][d(1)], Init (), true);
-
-TEST (1, [2][d(2)][d(2)], Init (), false);
-TEST (1, [2][d(2)][d(2)], Init ({{{1}}}), false);
-TEST (1, [ ][d(2)][d(2)], Init ({{{1}}}), false);
-TEST (1, [2][d(2)][d(2)], Init ({{{1}, {2}}}), false);
-TEST (1, [ ][d(2)][d(2)], Init ({{{1}, {2}}}), false);
-TEST (1, [2][d(2)][d(2)], Init ({{{1}, {2, 3}}}), false);
-TEST (1, [ ][d(2)][d(2)], Init ({{{1}, {2, 3}}}), false);
-TEST (1, [2][d(2)][d(2)], Init ({{{1, 2}, {3}}}), false);
-TEST (1, [ ][d(2)][d(2)], Init ({{{1, 2}, {3}}}), false);
-TEST (1, [2][d(2)][d(2)], Init ({{{1, 2}, {3, 4}}}), false);
-TEST (1, [ ][d(2)][d(2)], Init ({{{1, 2}, {3, 4}}}), false);
-TEST (1, [2][d(2)][d(2)], Init ({{{1, 2}, {3, 4}}, {{5, 6}, {7, 8}}}), false);
-TEST (1, [ ][d(2)][d(2)], Init ({{{1, 2}, {3, 4}}, {{5, 6}, {7, 8}}}), false);
-TEST (1, [2][d(2)][d(2)], Init ({{{1}, {2, 3, 4}}}), true);
-TEST (1, [ ][d(2)][d(2)], Init ({{{1}, {2, 3, 4}}}), true);
-TEST (1, [2][d(2)][d(2)], Init ({{{1, 2, 3}, {}}}), true);
-TEST (1, [ ][d(2)][d(2)], Init ({{{1, 2, 3}, {}}}), true);
-TEST (1, [2][d(2)][d(2)], Init ({{{1, 2, 3}, {4}}}), true);
-TEST (1, [ ][d(2)][d(2)], Init ({{{1, 2, 3}, {4}}}), true);
-TEST (1, [2][d(2)][d(2)], Init ({{{1, 2, 3, 4}}}), true);
-TEST (1, [ ][d(2)][d(2)], Init ({{{1, 2, 3, 4}}}), true);
-TEST (1, [2][d(2)][d(2)], Init ({{{1, 2, 3, 4}, {}}}), true);
-TEST (1, [ ][d(2)][d(2)], Init ({{{1, 2, 3, 4}, {}}}), true);
-TEST (1, [2][d(2)][d(2)], Init ({{{1, 2, 3, 4}, {5}}}), true);
-TEST (1, [ ][d(2)][d(2)], Init ({{{1, 2, 3, 4}, {5}}}), true);
-TEST (1, [2][d(2)][d(2)], Init ({{{1}, {2, 3, 4}}}), true);
-TEST (1, [ ][d(2)][d(2)], Init ({{{1}, {2, 3, 4}}}), true);
-TEST (1, [2][d(2)][d(2)], Init ({{{1}, {2, 3}, {4}}}), true);
-TEST (1, [2][d(2)][d(2)], Init ({{{1, 2, 3}, {}}}), true);
-TEST (1, [2][d(2)][d(2)], Init ({{{1, 2, 3}, {4}}}), true);
-TEST (1, [2][d(2)][d(2)], Init ({{{1, 2, 3, 4}}}), true);
-TEST (1, [2][d(2)][d(2)], Init ({{{1, 2, 3, 4}, {}}}), true);
-TEST (1, [2][d(2)][d(2)], Init ({{{1, 2, 3, 4}, {5}}}), true);
-TEST (1, [2][d(2)][d(2)], Init ({{{1, 2}, {3, 4}}, {{5, 6}, {7, 8, 9}}}), true);
-TEST (1, [2][d(2)][d(2)], Init ({{{1, 2}, {3, 4}}, {{5, 6, 7}, {8, 9}}}), true);
-TEST (1, [2][d(2)][d(2)], Init ({{{1, 2}, {3, 4, 5}}, {{6, 7}, {8, 9}}}), true);
-TEST (1, [2][d(2)][d(2)], Init ({{{1, 2, 3}, {4, 5}}, {{6, 7}, {8, 9}}}), true);
-TEST (1, [2][d(2)][d(2)], Init ({{{1}, {2}}, {{3}, {4, 5, 6}}}), true);
-TEST (1, [2][d(2)][d(2)], Init ({{{1}}, {{2}, {3, 4, 5, 6}}}), true);
-TEST (1, [2][d(2)][d(2)], Init ({{{1}, {2}, {3}}}), true);
-TEST (1, [2][d(2)][d(2)], Init ({{{1}, {2, 3}, {4}}}), true);
-TEST (1, [2][d(2)][d(2)], Init ({{{1}, {2, 3, 4}, {5}}}), true);
-
-#if TEST_NEAR_VLA_MAX_SIZE
-// Very large but not erroneous three-dimensional VLAs.
-TEST ( 1, [2][d(1)][d(MAX/2)], Init (), false);
-TEST ( 2, [2][d(1)][d(MAX/4)], Init (), false);
-TEST ( 4, [2][d(1)][d(MAX/8)], Init (), false);
-TEST ( 8, [2][d(1)][d(MAX/16)], Init (), false);
-TEST (16, [2][d(1)][d(MAX/32)], Init (), false);
-
-TEST ( 1, [2][d(MAX/2)][d(1)], Init (), false);
-TEST ( 2, [2][d(MAX/4)][d(1)], Init (), false);
-TEST ( 4, [2][d(MAX/8)][d(1)], Init (), false);
-TEST ( 8, [2][d(MAX/16)][d(1)], Init (), false);
-TEST (16, [2][d(MAX/32)][d(1)], Init (), false);
-
-TEST ( 1, [d(MAX/2)][2][d(1)], Init (), false);
-TEST ( 2, [d(MAX/4)][2][d(1)], Init (), false);
-TEST ( 4, [d(MAX/8)][2][d(1)], Init (), false);
-TEST ( 8, [d(MAX/16)][2][d(1)], Init (), false);
-TEST (16, [d(MAX/32)][2][d(1)], Init (), false);
-#endif // TEST_NEAR_VLA_MAX_SIZE
-
-// Erroneous three-dimensional VLAs with size exceeding SIZE_MAX / 2
-// (those must be rejected because no object can be bigger than that,
-// otherwise pointer arithmetic breaks).
-TEST ( 1, [2][d(1)][d(SIZE_MAX/2)], Init (), true);
-TEST ( 2, [2][d(1)][d(SIZE_MAX/4)], Init (), true);
-TEST ( 4, [2][d(1)][d(SIZE_MAX/8)], Init (), true);
-TEST ( 8, [2][d(1)][d(SIZE_MAX/16)], Init (), true);
-TEST (16, [2][d(1)][d(SIZE_MAX/32)], Init (), true);
-
-TEST ( 1, [2][d(SIZE_MAX/2)][d(1)], Init (), true);
-TEST ( 2, [2][d(SIZE_MAX/4)][d(1)], Init (), true);
-TEST ( 4, [2][d(SIZE_MAX/8)][d(1)], Init (), true);
-TEST ( 8, [2][d(SIZE_MAX/16)][d(1)], Init (), true);
-TEST (16, [2][d(SIZE_MAX/32)][d(1)], Init (), true);
-
-TEST ( 1, [d(SIZE_MAX/2)][2][d(1)], Init (), true);
-TEST ( 2, [d(SIZE_MAX/4)][2][d(1)], Init (), true);
-TEST ( 4, [d(SIZE_MAX/8)][2][d(1)], Init (), true);
-TEST ( 8, [d(SIZE_MAX/16)][2][d(1)], Init (), true);
-TEST (16, [d(SIZE_MAX/32)][2][d(1)], Init (), true);
-
-TEST (16, [3][d(SIZE_MAX)][d(SIZE_MAX)], Init (), true);
-TEST (32, [d(SIZE_MAX)][5][d(SIZE_MAX)], Init (), true);
-TEST (64, [d(SIZE_MAX)][d(SIZE_MAX)][7], Init (), true);
-
-int main ()
-{
- if (fail)
- __builtin_abort ();
-}
diff --git a/gcc/testsuite/gcc.dg/bitfld-22.c b/gcc/testsuite/gcc.dg/bitfld-22.c
new file mode 100644
index 00000000000..2fb904bce24
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/bitfld-22.c
@@ -0,0 +1,18 @@
+/* PR c/70671 */
+/* { dg-do compile } */
+
+extern void bar (int *);
+
+struct S
+{
+ int x:2;
+} s, *r;
+
+void
+foo (void)
+{
+ int *p1 = &s.x; /* { dg-error "13:cannot take address of bit-field 'x'" } */
+ int *p2;
+ p2 = &s.x; /* { dg-error "8:cannot take address of bit-field 'x'" } */
+ bar (&s.x); /* { dg-error "8:cannot take address of bit-field 'x'" } */
+}
diff --git a/gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-2.c b/gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-2.c
index a7f846a1dcd..a23ac4efb1c 100644
--- a/gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-2.c
+++ b/gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-2.c
@@ -31,4 +31,5 @@ bar (long a)
/* { dg-final { scan-rtl-dump "Will split live ranges of parameters" "ira" } } */
/* { dg-final { scan-rtl-dump "Split live-range of register" "ira" } } */
-/* { dg-final { scan-rtl-dump "Performing shrink-wrapping" "pro_and_epilogue" } } */
+/* XFAIL due to PR70681. */
+/* { dg-final { scan-rtl-dump "Performing shrink-wrapping" "pro_and_epilogue" { xfail arm*-*-* powerpc*-*-* } } } */
diff --git a/gcc/testsuite/gcc.dg/pr10474.c b/gcc/testsuite/gcc.dg/pr10474.c
index ee9edd442c9..a4af536ec28 100644
--- a/gcc/testsuite/gcc.dg/pr10474.c
+++ b/gcc/testsuite/gcc.dg/pr10474.c
@@ -12,4 +12,5 @@ void f(int *i)
}
}
-/* { dg-final { scan-rtl-dump "Performing shrink-wrapping" "pro_and_epilogue" } } */
+/* XFAIL due to PR70681. */
+/* { dg-final { scan-rtl-dump "Performing shrink-wrapping" "pro_and_epilogue" { xfail arm*-*-* powerpc*-*-* } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/O3-pr70130.c b/gcc/testsuite/gcc.dg/vect/O3-pr70130.c
new file mode 100644
index 00000000000..e9938c21f41
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/O3-pr70130.c
@@ -0,0 +1,94 @@
+/* { dg-do run } */
+/* { dg-require-effective-target vsx_hw { target powerpc*-*-* } } */
+/* { dg-additional-options "-mcpu=power7" { target powerpc*-*-* } } */
+
+struct foo
+{
+ short a[3][16][16];
+ short pad;
+} images[8];
+
+void __attribute__ ((noinline, noclone))
+Loop_err (struct foo *img, const int s[16][2], int s0)
+{
+ int i, j;
+
+ for (j = 0; j < 16; j++)
+ {
+ for (i=0; i < 16; i++)
+ {
+ img->a[0][j][i] = s[i][0];
+ img->a[1][j][i] = s[j][1];
+ img->a[2][j][i] = s0;
+ }
+ }
+}
+
+const int s[16][2] = { { 1, 16 }, { 2, 15 }, { 3, 14 }, { 4, 13 },
+ { 5, 12 }, { 6, 11 }, { 7, 10 }, { 8, 9 },
+ { 9, 8 }, { 10, 7 }, { 11, 6 }, { 12, 5 },
+ { 13, 4 }, { 14, 3 }, { 15, 2 }, { 16, 1 } };
+const struct foo expected
+= { { { { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 },
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 } },
+ { { 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16 },
+ { 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15 },
+ { 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14 },
+ { 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13 },
+ { 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12 },
+ { 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11 },
+ { 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 },
+ { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 },
+ { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 },
+ { 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 },
+ { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 },
+ { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 },
+ { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 },
+ { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
+ { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
+ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } },
+ { { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } } },
+ 0 };
+
+int
+main (void)
+{
+ int i;
+
+ for (i = 0; i < 8; i++)
+ Loop_err (images + i, s, -1);
+
+ for (i = 0; i < 8; i++)
+ if (__builtin_memcmp (&expected, images + i, sizeof (expected)))
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr46470.c b/gcc/testsuite/gcc.target/i386/pr46470.c
index 11eb51a0394..8d6b5ca5d5e 100644
--- a/gcc/testsuite/gcc.target/i386/pr46470.c
+++ b/gcc/testsuite/gcc.target/i386/pr46470.c
@@ -4,7 +4,7 @@
/* These options are selected to ensure 1 word needs to be allocated
on the stack to maintain alignment for the call. This should be
transformed to push+pop. We also want to force unwind info updates. */
-/* { dg-options "-Os -fomit-frame-pointer -fasynchronous-unwind-tables" } */
+/* { dg-options "-Os -fomit-frame-pointer -fasynchronous-unwind-tables -mno-red-zone" } */
/* { dg-options "-Os -fomit-frame-pointer -mpreferred-stack-boundary=3 -fasynchronous-unwind-tables" { target ia32 } } */
/* ms_abi has reserved stack-region. */
/* { dg-skip-if "" { x86_64-*-mingw* } { "*" } { "" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr70662.c b/gcc/testsuite/gcc.target/i386/pr70662.c
new file mode 100644
index 00000000000..109e224d7b4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr70662.c
@@ -0,0 +1,19 @@
+/* { dg-do assemble { target { ! ia32 } } } */
+/* { dg-require-effective-target avx512vbmi } */
+/* { dg-require-effective-target masm_intel } */
+/* { dg-options "-Og -fschedule-insns -fno-tree-fre -mavx512vbmi --param=max-sched-ready-insns=1 -masm=intel" } */
+
+typedef char v64u8 __attribute__((vector_size(64)));
+typedef int v64u32 __attribute__((vector_size(64)));
+typedef long v64u64 __attribute__((vector_size(64)));
+typedef __int128 v64u128 __attribute__((vector_size(64)));
+
+v64u128
+foo(int u8_0, unsigned u128_0, v64u32 v64u32_1, v64u32 v64u32_0, v64u64 v64u64_0, v64u128 v64u128_0)
+{
+ v64u8 v64u8_0 = v64u8_0;
+ v64u32_0 = v64u32_0 >> (v64u32){0, 0, 0, 1, 0, ((v64u64)v64u64_0)[u8_0], ((v64u32)v64u128_0)[15], 0, 0, 0, 0, 4, ((v64u64)v64u64_0)[v64u32_0[0]] - 1};
+ v64u8_0 = v64u8_0 << ((v64u8)v64u32_1 & 1);
+ v64u64_0[0] >>= 0;
+ return u128_0 + (v64u128)v64u8_0 + (v64u128)v64u32_0 + (v64u128)v64u64_0;
+}
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index f8a6b43219d..c393d34b5ec 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -40,19 +40,19 @@ static void pretty_print_string (pretty_printer *, const char*);
static void newline_and_indent (pretty_printer *, int);
static void maybe_init_pretty_print (FILE *);
static void print_struct_decl (pretty_printer *, const_tree, int, int);
-static void do_niy (pretty_printer *, const_tree);
+static void do_niy (pretty_printer *, const_tree, int);
#define INDENT(SPACE) do { \
int i; for (i = 0; i<SPACE; i++) pp_space (pp); } while (0)
-#define NIY do_niy (pp, node)
+#define NIY do_niy (pp, node, flags)
static pretty_printer *tree_pp;
/* Try to print something for an unknown tree code. */
static void
-do_niy (pretty_printer *pp, const_tree node)
+do_niy (pretty_printer *pp, const_tree node, int flags)
{
int i, len;
@@ -65,7 +65,7 @@ do_niy (pretty_printer *pp, const_tree node)
for (i = 0; i < len; ++i)
{
newline_and_indent (pp, 2);
- dump_generic_node (pp, TREE_OPERAND (node, i), 2, 0, false);
+ dump_generic_node (pp, TREE_OPERAND (node, i), 2, flags, false);
}
}
diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c
index f8695b13d6d..7652e216eb6 100644
--- a/gcc/tree-vect-data-refs.c
+++ b/gcc/tree-vect-data-refs.c
@@ -5983,10 +5983,19 @@ vect_supportable_dr_alignment (struct data_reference *dr,
|| targetm.vectorize.builtin_mask_for_load ()))
{
tree vectype = STMT_VINFO_VECTYPE (stmt_info);
- if ((nested_in_vect_loop
- && (TREE_INT_CST_LOW (DR_STEP (dr))
- != GET_MODE_SIZE (TYPE_MODE (vectype))))
- || !loop_vinfo)
+
+ /* If we are doing SLP then the accesses need not have the
+ same alignment, instead it depends on the SLP group size. */
+ if (loop_vinfo
+ && STMT_SLP_TYPE (stmt_info)
+ && (LOOP_VINFO_VECT_FACTOR (loop_vinfo)
+ * GROUP_SIZE (vinfo_for_stmt (GROUP_FIRST_ELEMENT (stmt_info)))
+ % TYPE_VECTOR_SUBPARTS (vectype) != 0))
+ ;
+ else if (!loop_vinfo
+ || (nested_in_vect_loop
+ && (TREE_INT_CST_LOW (DR_STEP (dr))
+ != GET_MODE_SIZE (TYPE_MODE (vectype)))))
return dr_explicit_realign;
else
return dr_explicit_realign_optimized;