diff options
author | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-04-25 07:30:20 +0000 |
---|---|---|
committer | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-04-25 07:30:20 +0000 |
commit | 02c1fcdcb78e34694a4e5b4604477677473d7804 (patch) | |
tree | 3240e6af53f9de7f6a778c1b9dcc2f90bc5d5b6c | |
parent | 3b2ef6864dbb5abe099620f432bb650e84617af3 (diff) | |
download | gcc-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
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; |