diff options
author | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-02-10 17:20:51 +0000 |
---|---|---|
committer | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2016-02-10 17:20:51 +0000 |
commit | 2d9d01985a7a7866916fafa19c5c296702e69714 (patch) | |
tree | 259c095c65fc0c6279b7a17755b3f851f51babb3 /gcc | |
parent | c8ebeb0e3c6b093e649592be7d51d1c0032a1dc7 (diff) | |
download | gcc-2d9d01985a7a7866916fafa19c5c296702e69714.tar.gz |
2016-02-10 Basile Starynkevitch <basile@starynkevitch.net>
{{merging with even more of GCC 6, using subversion 1.9
svn merge -r227001:227400 ^/trunk ;
there is some gengtype issue before svn r228000... }}
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@233281 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
543 files changed, 10314 insertions, 6066 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 39e392e61c6..e686783f232 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,1466 @@ +2015-09-02 Alan Modra <amodra@gmail.com> + + * config/rs6000/sysv4le.h (LINK_TARGET_SPEC): Don't define. + * config/rs6000/sysv4.h (LINK_TARGET_SPEC): Likewise. + (LINK_SPEC, SUBTARGET_EXTRA_SPECS): Delete link_target. + +2015-09-02 Alan Modra <amodra@gmail.com> + + PR target/67417 + * config/rs6000/predicates.md (current_file_function_operand): Don't + return true for weak symbols. + * config/rs6000/rs6000.c (rs6000_function_ok_for_sibcall): Likewise. + +2015-09-01 Matthew Fortune <matthew.fortune@imgtec.com> + Andrew Bennett <andrew.bennett@imgtec.com> + + * config/mips/mips-opts.h (mips_cb_setting): New enum. + * config/mips/mips-protos.h: Add definitions for + mips_output_jump and mips_output_equal_conditional_branch + * gcc/config/mips/mips.c (MIPS_JR): Change to support the + JIC instruction. + (mips_emit_compare): Add support for the MIPS R6 conditional + compact branches. + (mips_process_sync_loop): Likewise. + (mips_output_order_conditional_branch): Likewise. + (mips16_build_call_stub): Change MIPS_CALL to + mips_output_jump. + (mips_print_operand_punctuation): Update 's' case to only + apply to micromips r2. + (mips_adjust_insn_length): Add support for forbidden slot + hazards. + (mips_avoid_hazard): Likewise. + (mips_reorg_process_insns): Likewise. + (mips_output_jump): New function. + (mips_output_equal_conditional_branch): Likewise. + (mips_output_conditional_branch): Use jrc/bc if compact + branch support is enabled. Ensure the forbidden slots + between the two branch instructions is filled with a nop. + (mips_option_override): Add support to process the compact + branch option and set the correct defaults. Prevent + non-explict relocs being using for MIPS R6. + (mips_trampoline_init): Add compact branch support. + (mips_mult_zero_zero_cost): Allow zero initialisation of + accumulators with TARGET_DSP. + * gcc/config/mips/mips.h (TARGET_CB_NEVER): New define. + (TARGET_CB_MAYBE): New define. + (TARGET_CB_ALWAYS): New define. + (ISA_HAS_DELAY_SLOTS): New define. + (ISA_HAS_COMPACT_BRANCHES): New define. + (ISA_HAS_JRC): New define. + (MIPS_BRANCH_C): New define. + (MIPS_CALL): Removed. + (MICROMIPS_J): Removed. + * config/mips/mips.md (compact_form): New attr. + (hazard): Add support for forbidden slots. + (define_delay): Add support for compact branches. + (*branch_order<mode>): Likewise. + (*branch_order<mode>_inverted): Likewise. + (*branch_equality<mode>): Likewise. + (*branch_equality<mode>_inverted): Likewise. + (*jump_absolute): Likewise. + (*jump_pic): Likewise. + (indirect_jump): Use mips_output_jump to produce assembly output. + (tablejump_<mode>"): Likewise. + (*<optab>"): Likewise. + (<optab>_internal): Likewise. + (sibcall_internal): Likewise. + (sibcall_value_internal): Likewise. + (sibcall_value_multiple_internal): Likewise. + (call_internal): Likewise. + (call_split): Likewise. + (call_internal_direct): Likewise. + (call_direct_split): Likewise. + (call_value_internal): Likewise. + (call_value_split): Likewise. + (call_value_internal_direct): Likewise. + (call_value_direct_split): Likewise. + (call_value_multiple_internal): Likewise. + (call_value_multiple_split): Likewise. + (mips_get_fcsr_mips16_<mode>): Likewise. + (mips_set_fcsr_mips16_<mode>): Likewise. + (tls_get_tp_mips16_<mode>): Likewise. + * config/mips/mips.opt: Add -mcompact-branches option. + * config/mips/predicates.md (order_operator): Ensure the + conditional compact branches are only used if the ISA them. + * doc/invoke.texi: Document -mcompact-branches option. + +2015-09-01 Vladimir Makarov <vmakarov@redhat.com> + + PR target/61578 + * lra-lives.c (process_bb_lives): Process move pseudos with the + same value for copies and preferences + * lra-constraints.c (match_reload): Create match reload pseudo + with the same value from single dying input pseudo. + +2015-09-01 Ilya Enkovich <enkovich.gnu@gmail.com> + + PR target/67405 + * tree-chkp.c (chkp_find_bound_slots_1): Add NULL check. + +2015-09-01 Aldy Hernandez <aldyh@redhat.com> + + * trans-mem.c: Add contributed-by. + * trans-mem.h: Same. + +2015-09-01 Richard Biener <rguenther@suse.de> + + * expr.c (expand_expr_real_1): For expanding TERed defs + set the current location to that of the def if not UNKNOWN. + +2015-09-01 David Sherwood <david.sherwood@arm.com> + + * genmodes.c: Add CONST_MODE_UNIT_SIZE modifier. + +2015-09-01 Kyrylo Tkachov <kyrylo.tkachov@arm.com> + + * ifcvt.c (struct noce_if_info): Add then_simple, else_simple, + then_cost, else_cost fields. Change branch_cost field to unsigned + int. + (end_ifcvt_sequence): Call set_used_flags on each insn in the + sequence. + Include rtl-iter.h. + (noce_simple_bbs): New function. + (noce_try_move): Bail if basic blocks are not simple. + (noce_try_store_flag): Likewise. + (noce_try_store_flag_constants): Likewise. + (noce_try_addcc): Likewise. + (noce_try_store_flag_mask): Likewise. + (noce_try_cmove): Likewise. + (noce_try_minmax): Likewise. + (noce_try_abs): Likewise. + (noce_try_sign_mask): Likewise. + (noce_try_bitop): Likewise. + (bbs_ok_for_cmove_arith): New function. + (noce_emit_all_but_last): Likewise. + (noce_emit_insn): Likewise. + (noce_emit_bb): Likewise. + (noce_try_cmove_arith): Handle non-simple basic blocks. + (insn_valid_noce_process_p): New function. + (contains_mem_rtx_p): Likewise. + (bb_valid_for_noce_process_p): Likewise. + (noce_process_if_block): Allow non-simple basic blocks + where appropriate. + +2015-08-31 Alan Lawrence <alan.lawrence@arm.com> + + * tree-ssa-dom.c (record_equivalences_from_phis, + record_equivalences_from_stmt, optimize_stmt): Use dom_valueize. + (lookup_avail_expr): Likewise, and remove comment and unused temp. + +2015-09-01 Nick Clifton <nickc@redhat.com> + + * config/msp430/msp430.opt (mcpu): Fix typo. + +2015-09-01 Kyrylo Tkachov <kyrylo.tkachov@arm.com> + + * config/aarch64/aarch64.c (aarch64_set_current_function): + Re-layout any vector parameters have non-simd layout. + * config/aarch64/aarch64-builtins.c (aarch64_relayout_simd_param): + Delete. + (aarch64_simd_expand_args): Delete call to the above. + +2015-08-31 Mike Frysinger <vapier@gentoo.org> + + * doc/invoke.texi (asan-stack): Add space before option. + +2015-08-31 Marc Glisse <marc.glisse@inria.fr> + + * tree.h (zerop): New function. + * tree.c (zerop): Likewise. + (element_precision): Handle expressions. + * match.pd (define_predicates): Add zerop. + (x <= +Inf): Fix comment. + (abs (x) == 0, A & C == C, A & C != 0): Converted from ... + * fold-const.c (fold_binary_loc): ... here. Remove. + +2015-08-31 Richard Biener <rguenther@suse.de> + + PR middle-end/67381 + * genmatch.c (dt_node::gen_kids): Also treat matches as barrier. + +2015-08-31 Marc Glisse <marc.glisse@inria.fr> + + * match.pd (SIN, COS, TAN, COSH): Reorder for consistency. + (CEXPI): New operator list. + (real (conj (x)), imag (conj (x)), real (x +- y), real (cexpi (x)), + imag (cexpi (x)), conj (conj (x)), conj (complex (x, y))): + Converted from ... + * fold-const.c (fold_unary_loc, fold_binary_loc): ... here. Remove. + +2015-08-31 Tom de Vries <tom@codesourcery.com> + + * tree-ssa-loop-manip.c (find_uses_to_rename_stmt) + (find_uses_to_rename_bb, find_uses_to_rename): Add and handle use_flags + parameter. + (find_uses_to_rename_def, find_uses_to_rename_in_loop): New function. + (rewrite_into_loop_closed_ssa_1): New function, factored out of ... + (rewrite_into_loop_closed_ssa): ... here. + (replace_uses_in_dominated_bbs): Remove function. + (rewrite_virtuals_into_loop_closed_ssa): Reimplement using + rewrite_into_loop_closed_ssa_1. + +2015-08-31 Michael Matz <matz@suse.de> + + * cfganal.c (pre_and_rev_post_order_compute_fn): Correctly + enter entry and exit blocks for reverse post order. + +2015-08-31 Richard Biener <rguenther@suse.de> + + * lto-streamer.h (lto_location_cache::cached_location::sysp): Add. + (lto_location_cache::current_sysp): Likewise. + (output_block::current_sysp): Likewise. + * lto-streamer-in.c (lto_location_cache::cmp_loc): Compare sysp. + (lto_location_cache::apply_location_cache): Properly record + system header locations. + (lto_location_cache::input_location): Input whether a file + is a system header. + * lto-streamer-out.c (lto_output_location): Stream whether a file + is a system header. + +2015-08-31 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + PR bootstrap/67363 + * gcc.c (env_manager::xput): Replace strndup by xstrndup. + +2015-08-31 Tom de Vries <tom@codesourcery.com> + + * tree-ssa-loop-manip.c (find_uses_to_rename_use) + (find_uses_to_rename_stmt, find_uses_to_rename_bb, find_uses_to_rename): + Improve function header comments. + +2015-08-30 Michael Collison <michael.collison@linaro.org> + + PR other/67320 + * doc.md.texi: Rename [su]sum_widen to widen_[su]sum to reflect correct + standard names + +2015-08-30 Bill Schmidt <wschmidt@linux.vnet.ibm.com> + + * config/rs6000/rs6000.c (swap_web_entry): Enlarge + special_handling bitfield. + (special_handling_values): Add SH_XXPERMDI and SH_CONCAT. + (rtx_is_swappable_p): Add handling for vec_select/vec_concat form + that represents a general xxpermdi. + (insn_is_swappable_p): Add handling for vec_concat of two + doublewords, which maps to a specific xxpermdi. + (adjust_xxpermdi): New function. + (adjust_concat): Likewise. + (handle_special_swappables): Call adjust_xxpermdi and + adjust_concat. + (dump_swap_insn_table): Handle SH_XXPERMDI and SH_CONCAT. + +2015-08-30 Rich Felker <dalias@libc.org> + + * config.gcc (supported_defaults): Handle sh[123456ble]*-*-* + case instead of sh[123456ble]-*-*. + +2015-08-29 Anatoly Sokolov <aesok@post.ru> + + * ira.c (print_unform_and_important_classes, + print_translated_classes): Remove reg_class_names static array. + (print_unform_and_important_classes): Rename to ... + (print_uniform_and_important_classes): ... this. + (ira_debug_allocno_classes): Update accordingly. + +2015-08-29 Tom de Vries <tom@codesourcery.com> + + PR tree-optimization/46193 + * omp-low.c (omp_reduction_init): Handle pointer type for min or max + clause. + +2015-08-28 Jeff Law <law@redhat.com> + + PR lto/66752 + * tree-ssa-threadedge.c (simplify_conrol_stmt_condition): If we are + unable to find X NE 0 in the tables, return X as the simplified + condition. + (fsm_find_control_statement_thread_paths): If nodes in NEXT_PATH are + in VISISTED_BBS, then return failure. Else add nodes from NEXT_PATH + to VISISTED_BBS. + * tree-ssa-threadupdate.c (duplicate_thread_path): Fix up edge flags + after removing the control flow statement and unnecessary edges. + +2015-08-28 Alan Lawrence <alan.lawrence@arm.com> + + Revert: + 2015-08-27 Alan Lawrence <alan.lawrence@arm.com> + PR tree-optimization/67283 + * tree-sra.c (type_consists_of_records_p): Rename to... + (scalarizable_type_p): ...this, add case for ARRAY_TYPE. + + (completely_scalarize_record): Rename to... + (completely_scalarize): ...this, add ARRAY_TYPE case, move some + code to: + (scalarize_elem): New. + +2015-08-28 Jiong Wang <jiong.wang@arm.com> + + * config/aarch64/aarch64-protos.h (aarch64_symbol_context): Rename + SYMBOL_SMALL_GOTTPREL to SYMBOL_SMALL_TLSIE. + (aarch64_symbol_type): Likewise. + * config/aarch64/aarch64.c (aarch64_load_symref_appropriately): + Likewise. + (aarch64_expand_mov_immediate): Likewise. + (aarch64_print_operand): Likewise. + (aarch64_classify_tls_symbol): Likewise. + +2015-08-28 Richard Biener <rguenther@suse.de> + + * cgraphunit.c (symbol_table::compile): Move early debug generation + and finish... + (symbol_table::finalize_compilation_unit): ... back here and + add a !seen_error () guard. + +2015-08-27 Sebastian Pop <s.pop@samsung.com> + + * toplev.c (process_options): Do not use flag_loop_block, + flag_loop_interchange, and flag_loop_strip_mine. Add check for + flag_loop_optimize_isl. + +2015-08-27 Sebastian Pop <s.pop@samsung.com> + + * Makefile.in (OBJS): Remove graphite-blocking.o and + graphite-interchange.o. + * common.opt (floop-strip-mine, floop-interchange, floop-block): + Alias of floop-nest-optimize. + * doc/invoke.texi (floop-strip-mine, floop-interchange, floop-block): + Document as alias of -floop-nest-optimize. + * graphite-blocking.c: Remove. + * graphite-interchange.c: Remove. + * graphite-optimize-isl.c: Include dumpfile.h. + (getScheduleForBand): Add dump for tiled loops. Use + PARAM_LOOP_BLOCK_TILE_SIZE instead of hard coded constant. + * graphite-poly.c (scop_max_loop_depth): Remove. + (print_scattering_function_1): Remove. + (print_scattering_function): Remove. + (print_scattering_functions): Remove. + (debug_scattering_function): Remove. + (debug_scattering_functions): Remove. + (apply_poly_transforms): Remove use of flag_loop_block, + flag_loop_strip_mine, and flag_loop_interchange. + (new_poly_bb): Remove use of PBB_TRANSFORMED, PBB_SAVED, and + PBB_ORIGINAL. + (print_pdr_access_layout): Remove. + (print_pdr): Print ISL representation. + (new_scop): Remove use of SCOP_ORIGINAL_SCHEDULE, + SCOP_TRANSFORMED_SCHEDULE, and SCOP_SAVED_SCHEDULE. + (free_scop): Same. + (openscop_print_pbb_domain): Remove. + (print_pbb): Remove call to print_scattering_function. + (openscop_print_scop_context): Remove. + (print_scop_context): Do not print matrices anymore. + (print_scop): Do not print SCOP_ORIGINAL_SCHEDULE and + SCOP_TRANSFORMED_SCHEDULE. + (print_isl_set): Add printing of a new line. + (print_isl_map): Same. + (print_isl_aff): Same. + (print_isl_constraint): Same. + (loop_to_lst): Remove. + (scop_to_lst): Remove. + (lst_indent_to): Remove. + (print_lst): Remove. + (debug_lst): Remove. + (dot_lst_1): Remove. + (dot_lst): Remove. + (reverse_loop_at_level): Remove. + (reverse_loop_for_pbbs): Remove. + * graphite-poly.h (pdr_dim_iter_domain): Remove. + (pdr_nb_params): Remove. + (pdr_alias_set_dim): Remove. + (pdr_subscript_dim): Remove. + (pdr_iterator_dim): Remove. + (pdr_parameter_dim): Remove. + (same_pdr_p): Remove. + (struct poly_scattering): Remove. + (struct poly_bb): Remove _original, _transformed, _saved. + (PBB_DOMAIN, PBB_ORIGINAL, PBB_ORIGINAL_SCATTERING): Remove. + (PBB_TRANSFORMED, PBB_TRANSFORMED_SCATTERING, PBB_SAVED): Remove. + (PBB_NB_LOCAL_VARIABLES): Remove. + (PBB_NB_SCATTERING_TRANSFORM): Remove. + (schedule_to_scattering): Remove. + (number_of_write_pdrs): Remove. + (pbb_dim_iter_domain): Remove. + (pbb_nb_params): Remove. + (pbb_nb_scattering_orig): Remove. + (pbb_nb_scattering_transform): Remove. + (pbb_nb_dynamic_scattering_transform): Remove. + (pbb_nb_local_vars): Remove. + (pbb_iterator_dim): Remove. + (pbb_parameter_dim): Remove. + (psco_scattering_dim): Remove. + (psct_scattering_dim): Remove. + (psct_local_var_dim): Remove. + (psco_iterator_dim): Remove. + (psct_iterator_dim): Remove. + (psco_parameter_dim): Remove. + (psct_parameter_dim): Remove. + (psct_dynamic_dim): Remove. + (psct_static_dim): Remove. + (psct_add_local_variable): Remove. + (new_lst_loop): Remove. + (new_lst_stmt): Remove. + (free_lst): Remove. + (copy_lst): Remove. + (lst_add_loop_under_loop): Remove. + (lst_depth): Remove. + (lst_dewey_number): Remove. + (lst_dewey_number_at_depth): Remove. + (lst_pred): Remove. + (lst_succ): Remove. + (lst_find_pbb): Remove. + (find_lst_loop): Remove. + (lst_find_first_pbb): Remove. + (lst_empty_p): Remove. + (lst_find_last_pbb): Remove. + (lst_contains_p): Remove. + (lst_contains_pbb): Remove. + (lst_create_nest): Remove. + (lst_remove_from_sequence): Remove. + (lst_remove_loop_and_inline_stmts_in_loop_father): Remove. + (lst_niter_for_loop): Remove. + (pbb_update_scattering): Remove. + (lst_update_scattering_under): Remove. + (lst_update_scattering): Remove. + (lst_insert_in_sequence): Remove. + (lst_replace): Remove. + (lst_substitute_3): Remove. + (lst_distribute_lst): Remove. + (lst_remove_all_before_including_pbb): Remove. + (lst_remove_all_before_excluding_pbb): Remove. + (struct scop): Remove original_schedule, transformed_schedule, and + saved_schedule. + (SCOP_ORIGINAL_SCHEDULE, SCOP_TRANSFORMED_SCHEDULE): Remove. + (SCOP_SAVED_SCHEDULE): Remove. + (poly_scattering_new): Remove. + (poly_scattering_free): Remove. + (poly_scattering_copy): Remove. + (store_scattering_pbb): Remove. + (store_lst_schedule): Remove. + (restore_lst_schedule): Remove. + (store_scattering): Remove. + (restore_scattering_pbb): Remove. + (restore_scattering): Remove. + * graphite-sese-to-poly.c (build_pbb_scattering_polyhedrons): + Remove scattering_dimensions. Do not use pbb_dim_iter_domain: + compute the scattering polyhedron dimension from the dimension of + pbb->domain. + (build_scop_scattering): Update call to + build_pbb_scattering_polyhedrons. + (build_poly_scop): Remove call to scop_to_lst. + * graphite.c (graphite_transform_loops): Add call to print_scop. + (gate_graphite_transforms): Remove use of flag_loop_block, + flag_loop_interchange, and flag_loop_strip_mine. + +2015-08-27 Sebastian Pop <s.pop@samsung.com> + + * common.opt (floop-unroll-and-jam): Make alias of floop-nest-optimize. + * doc/invoke.texi (-floop-unroll-and-jam): Document as alias of + -floop-nest-optimize. + * graphite-isl-ast-to-gimple.c (generate_luj_sepclass_opt): Remove. + (generate_luj_sepclass): Remove. + (generate_luj_options): Remove. + (set_options): Remove opt_luj. + (scop_to_isl_ast): Remove opt_luj. + * graphite-optimize-isl.c (getScheduleForBand): Remove check for + flag_loop_unroll_jam. + (getPrevectorMap_full): Remove. + (getScheduleForBandList): Remove map_sepcl. + (getScheduleMap): Same. + (apply_schedule_map_to_scop): Remove sepcl. + (optimize_isl): Same. + * graphite-poly.c (apply_poly_transforms): Remove check for + flag_loop_unroll_jam. + (new_poly_bb): Remove map_sepclass. + * graphite-poly.h (struct poly_bb): Same. + * graphite.c (gate_graphite_transforms): Remove flag_loop_unroll_jam. + * params.def (PARAM_LOOP_UNROLL_JAM_SIZE) + (PARAM_LOOP_UNROLL_JAM_DEPTH): Remove. + * toplev.c (process_options): Remove flag_loop_unroll_jam. + +2015-08-27 Uros Bizjak <ubizjak@gmail.com> + + PR target/67317 + * config/i386/i386.md (*add<mode>3_cc): Remove insn pattern. + (addqi3_cc): Ditto. + (UNSPEC_ADD_CARRY): Remove. + (addqi3_cconly_overflow): New expander. + (*add<dwi>3_doubleword): Split to add<mode>3_cconly_overflow. + Adjust for changed add<mode>3_carry. + (*neg<dwi>2_doubleword): Adjust for changed add<mode>3_carry. + (*sub<dwi>3_doubleword): Adjust for changed sub<mode>3_carry. + (<plusminus_insn><mode>3_carry): Remove expander. + (*<plusminus_insn><mode>3_carry): Split insn pattern to + add<mode>3_carry and sub<mode>3_carry. + (plusminus_carry_mnemonic): Remove code attribute. + (add<mode>3_carry): Canonicalize insn pattern. + (*addsi3_carry_zext): Ditto. + (sub<mode>3_carry): Ditto. + (*subsi3_carry_zext): Ditto. + (adcx<mode>3): Remove insn pattern. + (addcarry<mode>): New insn pattern. + (subborrow<mode>): Ditto. + * config/i386/i386.c (ix86_expand_strlensi_unroll_1): Use + gen_addqi3_cconly_overflow instead of gen_addqi3_cc. + (ix86_expand_builtin) <case IX86_BUILTIN_SBB32, + case IX86_BUILTIN_SBB64, case IX86_BUILTIN_ADDCARRY32, + case IX86_BUILTIN_ADDCARRY64>: Use CODE_FOR_subborrowsi, + CODE_FOR_subborrowdi, CODE_FOR_addcarrysi and CODE_FOR_addcarrydi. + Rewrite expander to not clobber carry flag chains. + +2015-08-27 Pat Haugen <pthaugen@us.ibm.com> + + * config/rs6000/vector.md (vec_shr_<mode>): Fix to do a shift + instead of a rotate. + +2015-08-27 Marek Polacek <polacek@redhat.com> + + PR middle-end/67005 + * tree-ssa-dce.c (remove_dead_stmt): Also schedule fixup if removing + an entry into an irreducible region. + +2015-08-27 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> + + * configure: Regenerate. + +2015-08-27 Alan Lawrence <alan.lawrence@arm.com> + + PR tree-optimization/67283 + * tree-sra.c (type_consists_of_records_p): Rename to... + (scalarizable_type_p): ...this, add case for ARRAY_TYPE. + + (completely_scalarize_record): Rename to... + (completely_scalarize): ...this, add ARRAY_TYPE case, move some code to: + (scalarize_elem): New. + +2015-08-27 Alan Lawrence <alan.lawrence@arm.com> + + * tree-sra.c (completely_scalarize_var): Rename to... + (create_total_scalarization_access): ... Here. Drop call to + completely_scalarize_record. + + (analyze_all_variable_accesses): Replace completely_scalarize_var + with create_total_scalarization_access and completely_scalarize_record. + +2015-08-27 Alan Modra <amodra@gmail.com> + + PR target/67356 + * config/rs6000/rs6000.md (ior<mode>_mask): Use constraint "0" + for operand 1. + +2015-08-27 Richard Biener <rguenther@suse.de> + + * passes.c (rest_of_decl_compilation): Guard early_global_decl + call with !seen_error (). + * cgraphunit.c (symbol_table::finalize_compilation_unit): Move + early debug generation and finish... + (symbol_table::compile): ... here to put it after a !seen_error () + guard. + +2015-08-27 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + * config.gcc (*-*-solaris2*): Enable default_use_cxa_atexit on + Solaris 12+. + +2015-08-27 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com> + Andre Vieira <andre.simoesdiasvieira@arm.com> + + * config/aarch64/aarch64.md (*condjump): Handle functions > 1 MiB. + (*cb<optab><mode>1): Likewise. + (*tb<optab><mode>1): Likewise. + (*cb<optab><mode>1): Likewise. + * config/aarch64/iterators.md (inv_cb): New code attribute. + (inv_tb): Likewise. + * config/aarch64/aarch64.c (aarch64_gen_far_branch): New. + * config/aarch64/aarch64-protos.h (aarch64_gen_far_branch): New. + +2015-08-27 Richard Biener <rguenther@suse.de> + + * ipa.c (cgraph_build_static_cdtor_1): Set DECL_IGNORED_P. + +2015-08-27 Dominik Vogt <vogt@linux.vnet.ibm.com> + + * config/s390/s390.c (s390_emit_prologue): Add emit_barrier() after + trap to fix ICE. + +2015-08-26 Michael Meissner <meissner@linux.vnet.ibm.com> + + * config/rs6000/rs6000-protos.h (rs6000_expand_float128_convert): + Add declaration. + + * config/rs6000/rs6000.c (rs6000_emit_le_vsx_store): Fix a + comment. + (rs6000_cannot_change_mode_class): Add support for IEEE 128-bit + floating point in VSX registers. + (rs6000_output_move_128bit): Always print out the set insn if we + can't generate an appropriate 128-bit move. + (rs6000_generate_compare): Add support for IEEE 128-bit floating + point in VSX registers comparisons. + (rs6000_expand_float128_convert): Likewise. + + * config/rs6000/predicates.md (int_reg_operand_not_pseudo): New + predicate for only GPR hard registers. + + * config/rs6000/rs6000.md (FP): Add IEEE 128-bit floating point + modes to iterators. Add new iterators for moving 128-bit values in + scalar FPR registers and VSX registers. + (FMOVE128): Likewise. + (FMOVE128_FPR): Likewise. + (FMOVE128_GPR): Likewise. + (FMOVE128_VSX): Likewise. + (FLOAT128_SFDFTF): New iterators for IEEE 128-bit floating point + in VSX registers. + (IFKF): Likewise. + (IBM128): Likewise. + (TFIFKF): Likewise. + (RELOAD): Add IEEE 128-bit floating point modes. + (signbittf2): Convert TF insns to add support for new IEEE 128-bit + floating point in VSX registers modes. + (signbit<mode>2, IBM128 iterator): Likewise. + (mov<mode>_64bit_dm, FMOVE128_FPR iterator): Likewise. + (mov<mode>_32bit, FMOVE128_FPR iterator): Likewise. + (negtf2): Likewise. + (neg<mode>2, TFIFKF iterator): Likewise. + (negtf2_internal): Likewise. + (abstf2): Likewise. + (abs<mode>2, TFIFKF iterator): Likewise. + (ieee_128bit_negative_zero): New IEEE 128-bit floating point in + VSX insn support for negate, absolute value, and negative absolute + value. + (ieee_128bit_vsx_neg<mode>2): Likewise. + (ieee_128bit_vsx_neg<mode>2_internal): Likewise. + (ieee_128bit_vsx_abs<mode>2): Likewise. + (ieee_128bit_vsx_abs<mode>2_internal): Likewise. + (ieee_128bit_vsx_nabs<mode>2): Likewise. + (ieee_128bit_vsx_nabs<mode>2_internal): Likewise. + (FP128_64): Update pack/unpack 128-bit insns for IEEE 128-bit + floating point in VSX registers. + (unpack<mode>_dm): Likewise. + (unpack<mode>_nodm): Likewise. + (pack<mode>): Likewise. + (unpackv1ti): Likewise. + (unpack<mode>, FMOVE128_VSX iterator): Likewise. + (packv1ti): Likewise. + (pack<mode>, FMOVE128_VSX iterator): Likewise. + (extenddftf2): Add support for IEEE 128-bit floating point in VSX + registers. + (extenddftf2_internal): Likewise. + (trunctfdf2): Likewise. + (trunctfdf2_internal2): Likewise. + (fix_trunc_helper): Likewise. + (fix_trunctfdi2"): Likewise. + (floatditf2): Likewise. + (floatuns<mode>tf2): Likewise. + (extend<FLOAT128_SFDFTF:mode><IFKF:mode>2): Likewise. + (trunc<IFKF:mode><FLOAT128_SFDFTF:mode>2): Likewise. + (fix_trunc<IFKF:mode><SDI:mode>2): Likewise. + (fixuns_trunc<IFKF:mode><SDI:mode>2): Likewise. + (float<SDI:mode><IFKF:mode>2): Likewise. + (floatuns<SDI:mode><IFKF:mode>2): Likewise. + +2015-08-26 Renlin Li <renlin.li@arm.com> + + * config/aarch64/aarch64.md (*aarch64_bfi<GPI:mode><ALLX:mode>4): New. + +2015-08-26 Marcus Shawcroft <marcus.shawcroft@arm.com> + Jiong Wang <jiong.wang@arm.com> + + * config/aarch64/aarch64.md (UNSPEC_GOTTINYTLS): New UNSPEC. + (tlsie_tiny_<mode>): New define_insn. + (tlsie_tiny_sidi): Likewise. + * config/aarch64/aarch64-protos.h (aarch64_symbol_type): Define + SYMBOL_TINY_TLSIE. + (aarch64_symbol_context): New comment for SYMBOL_TINY_TLSIE. + * config/aarch64/aarch64.c (aarch64_load_symref_appropriately): Support + SYMBOL_TINY_TLSIE. + (aarch64_expand_mov_immediate): Likewise. + (aarch64_print_operand): Likewise. + (arch64_classify_tls_symbol): Likewise. + +2015-08-26 Matthew Wahab <matthew.wahab@arm.com> + + * config/arm/arm-arches.def: Replace single value flags with + an initializer built from ARM_FSET_MAKE_CPU1. + * config/arm/arm-cores.def: Likewise. + * config/arm/arm.c: (all_cores): Remove ARM_FSET_MAKE_CPU1 + derivation from the ARM_CORE macro definition, use the given value + instead. + (all_architectures): Remove ARM_FSET_MAKE_CPU1 derivation from the + ARM_ARCH macro definition, use the given value instead. + +2015-08-26 Matthew Wahab <matthew.wahab@arm.com> + + * config/arm/arm-builtins.c (def_mbuiltin): Test all flags in a + feature set. + (struct builtin_description): Replace field mask with field + features. + (IWMMXT_BUILTIN): Use ARM_FSET macros for feature flags. + (IWMMXT2_BUILTIN): Likewise. + (IWMMXT2_BUILTIN2): Likewise. + (FP_BUILTIN): Likewise. + (CRC32_BUILTIN): Likewise. + (CRYPTO_BUILTIN): Likewise. + (iwmmx_mbuiltin): Likewise. + (iwmmx2_mbuiltin): Likewise. + (arm_init_iwmmxt_builtins): Likewise. Also, update for change to + struct builtin_description. + +2015-08-26 Matthew Wahab <matthew.wahab@arm.com> + + * config/arm/arm-builtins.c (def_mbuiltin): Use ARM_FSET macro. + (struct builtin_description): Change type of mask to unsigned + long. + * config/arm/arm-protos.h (insn_flags): Declare as type + arm_feature_set. + (tune_flags): Likewise. + * config/arm/arm.c (feature_count): New. + (insn_flags): Define as type arm_feature_set. + (tune_flags): Likewise. + (struct processors): Define field flags as type arm_feature_set. + (all_cores): Update for change to struct processors. + (all_architectures): Likewise. + (arm_option_check_internal): Use arm_feature_set and ARM_FSET + macros. + (arm_option_override_internal): Likewise. + (arm_option_override): Likewise. + +2015-08-26 Marcus Shawcroft <marcus.shawcroft@arm.com> + Jiong Wang <jiong.wang@arm.com> + + * config/aarch64/aarch64.c (initialize_aarch64_tls_size): Set default + tls size for tiny, small, large memory model. + (aarch64_load_symref_appropriately): Support new symbol types. + (aarch64_expand_mov_immediate): Likewise. + (aarch64_print_operand): Likewise. + (aarch64_classify_tls_symbol): Likewise. + * config/aarch64/aarch64-protos.h (aarch64_symbol_context): Likewise. + (aarch64_symbol_type): Likewise. + * config/aarch64/aarch64.md (tlsle): Deleted. + (tlsle12_<mode>): New define_insn. + (tlsle24_<mode>): Likewise. + (tlsle32_<mode>): Likewise. + (tlsle48_<mode>): Likewise. + * doc/sourcebuild.texi (AArch64-specific attributes): Document + "aarch64_tlsle32". + +2015-08-26 Matthew Wahab <matthew.wahab@arm.com> + + * config/arm/arm-protos.h (FL_NONE): New. + (FL_ANY): New. + (arm_feature_set): New. + (ARM_FSET_MAKE): New. + (ARM_FSET_MAKE_CPU1): New. + (ARM_FSET_MAKE_CPU2): New. + (ARM_FSET_CPU1): New. + (ARM_FSET_CPU2): New. + (ARM_FSET_EMPTY): New. + (ARM_FSET_ANY): New. + (ARM_FSET_HAS_CPU1): New. + (ARM_FSET_HAS_CPU2): New. + (ARM_FSET_HAS_CPU): New. + (ARM_FSET_ADD_CPU1): New. + (ARM_FSET_ADD_CPU2): New. + (ARM_FSET_DEL_CPU1): New. + (ARM_FSET_DEL_CPU2): New. + (ARM_FSET_UNION): New. + (ARM_FSET_INTER): New. + (ARM_FSET_XOR): New. + (ARM_FSET_EXCLUDE): New. + (AFM_FSET_IS_EMPTY): New. + (ARM_FSET_CPU_SUBSET): New. + +2015-08-26 Jiong Wang <jiong.wang@arm.com> + + * config/aarch64/aarch64-protos.h (aarch64_symbol_type): Rename + SYMBOL_TLSLE to SYMBOL_TLSLE24. + * config/aarch64/aarch64.c (aarch64_load_symref_appropriately): + Likewise. + (aarch64_expand_mov_immediate): Likewise. + (aarch64_print_operand): Likewise. + (aarch64_classify_symbol): Likewise. + +2015-08-26 Jiong Wang <jiong.wang@arm.com> + + * config/aarch64/aarch64.opt (mtls-size): New entry. + * config/aarch64/aarch64.c (initialize_aarch64_tls_size): New function. + (aarch64_override_options_internal): Call initialize_aarch64_tls_size. + * doc/invoke.texi (AArch64 Options): Document -mtls-size. + +2015-08-26 Matthew Wahab <matthew.wahab@arm.com> + + * gcc/config/arm/arm-cores.def: Add FL_FOR_ARCH flag for each + ARM_CORE entry. Fix some white-space. + * gcc/config/arm/arm.c: Remove FL_FOR_ARCH derivation from + ARM_CORE definition. + +2015-08-26 Naveen H.S <Naveen.Hurugalawadi@caviumnetworks.com> + + * fold-const.c (fold_binary_loc) : Move Optimize + root(x)*root(y) as root(x*y) to match.pd. + Move Optimize expN(x)*expN(y) as expN(x+y) to match.pd. + Move Optimize pow(x,y)*pow(x,z) as pow(x,y+z) to match.pd. + Move Optimize a/root(b/c) into a*root(c/b) to match.pd. + Move Optimize x/expN(y) into x*expN(-y) to match.pd. + * match.pd (mult (root:s @0) (root:s @1)): New simplifier. + (mult (POW:s @0 @1) (POW:s @0 @2)) : New simplifier. + (mult (exps:s @0) (exps:s @1)) : New simplifier. + (rdiv @0 (root:s (rdiv:s @1 @2))) : New simplifier. + (rdiv @0 (exps:s @1)) : New simplifier. + +2015-08-25 Joseph Myers <joseph@codesourcery.com> + + * gcc.c (driver::finalize): Only assign to extra_specs if + [EXTRA_SPECS]. + +2015-08-25 Marek Polacek <polacek@redhat.com> + + PR middle-end/67330 + * varasm.c (declare_weak): Return after giving an error. + +2015-08-25 David Malcolm <dmalcolm@redhat.com> + + * gcc-main.c (main): Add params to driver ctor. + * gcc.c (class env_manager): New. + (env): New global. + (env_manager::init): New. + (env_manager::get): New. + (env_manager::xput): New. + (env_manager::restore): New. + Poison getenv and putenv. + (DEFAULT_TARGET_SYSTEM_ROOT): New. + (target_system_root): Update initialization to use + DEFAULT_TARGET_SYSTEM_ROOT. + (struct spec_list): Add field "default_ptr". + (INIT_STATIC_SPEC): Initialize new field "default_ptr". + (init_spec): Likewise. + (set_spec): Clear field "default_ptr". + (read_specs): Free "spec" and "buffer". + (xputenv): Reimplement in terms of env_manager. + (process_command): Replace ::getenv calls with calls to the + env_manager singleton. + (process_brace_body): Free string in three places. + (driver::driver): New. + (driver::~driver): New. + (used_arg): Convert from a function to... + (class used_arg_t): ...this class, and... + (used_arg): ...this new global instance. + (used_arg_t::finalize): New function. + (getenv_spec_function): Add "const" to local "value". Replace + ::getenv call with call to the env_manager singleton. + (path_prefix_reset): New function. + (driver::finalize): New function. + * gcc.h (driver::driver): New. + (driver::~driver): New. + (driver::finalize): New. + +2015-08-25 Nathan Sidwell <nathan@acm.org> + + * optabs.c (emit_indirect_jump): Don't try an emit a jump if the + target doesn't have one. + +2015-08-25 Segher Boessenkool <segher@kernel.crashing.org> + + PR target/67346 + * config/rs6000/rs6000.md (*ior<mode>_mask): Use a match_scratch. + +2015-08-25 Segher Boessenkool <segher@kernel.crashing.org> + + PR target/67344 + * config/rs6000/rs6000.md (*and<mode>3_imm_dot_shifted): Change to + a define_insn, remove second alternative. + +2015-08-25 Thomas Schwinge <thomas@codesourcery.com> + Joseph Myers <joseph@codesourcery.com> + + * gcc.c (struct switchstr): Expand comment. + +2015-08-25 Nathan Sidwell <nathan@acm.org> + + * config/nvptx/nvptx.c (nvptx_write_function_decl): Reformat. + (nvptx_reorg_subreg): Pass insn pattern to asm_operands. + +2015-08-25 Richard Biener <rguenther@suse.de> + + PR middle-end/67306 + * genmatch.c (expr::gen_transform): Verify the result of + builtin_decl_implicit. + (dt_simplify::gen_1): Likewise. + +2015-08-25 Thomas Preud'homme <thomas.preudhomme@arm.com> + + * config/arm/constraints.md: Also list Cs and US ARM-specific + constraints as used. + +2015-08-24 Kaz Kojima <kkojima@gcc.gnu.org> + + PR target/66609 + * config/sh/sh.c (sh_asm_output_addr_const_extra): Handle + UNSPEC_PCREL. + (nonpic_symbol_mentioned_p): Likewise. + (sh_delegitimize_address): Likewise. + (sh_function_ok_for_sibcall): Take into account weak symbols. + (sh_expand_sym_label2reg): New. + * config/sh/sh-protos.h (sh_expand_sym_label2reg): Declare. + * config/sh/sh.md (UNSPEC_PCREL): New enum. + (call_pcrel): Use sh_expand_sym_label2reg. + (call_value_pcrel, sibcall_pcrel, sibcall_value_pcrel): Likewise. + (symPCREL_label2reg) New expand. + +2015-08-24 Aditya Kumar <aditya.k7@samsung.com> + + * graphite-poly.c: Change type of region from void* to sese. + * graphite-poly.h (struct scop): Changing the type of scop::region + from void* to sese. Change accessor macro accordingly. + * graphite-sese-to-poly.c (extract_affine_chrec): Use accessor macro. + +2015-08-24 Aditya Kumar <aditya.k7@samsung.com> + + * graphite-scop-detection.c (stmt_simple_for_scop_p): + Constrain only on INTEGER_TYPE. + +2015-08-24 Michael Meissner <meissner@linux.vnet.ibm.com> + + PR target/67211 + * config/rs6000/rs6000-cpus.def (ISA_2_7_MASKS_SERVER): Set + -mefficient-unaligned-vsx on ISA 2.7. + + * config/rs6000/rs6000.opt (-mefficient-unaligned-vsx): Convert + option to a masked option. + + * config/rs6000/rs6000.c (rs6000_option_override_internal): Rework + logic for -mefficient-unaligned-vsx so that it is set via an arch + ISA option, instead of being set if -mtune=power8 is set. Move + -mefficient-unaligned-vsx and -mallow-movmisalign handling to be + near other default option handling. + +2015-08-24 Richard Sandiford <richard.sandiford@arm.com> + + * genflags.c (gen_macro): Delete. + (gen_proto): Don't create GEN.*CALL.* macros. + * gensupport.h (get_file_location): Declare. + * gensupport.c (rtx_locs): New variable. + (read_md_rtx): Record rtx locations. + (get_file_location): New function. + * target-insns.def (call, call_pop, call_value, call_value_pop) + (sibcall, sibcall_value): New patterns. + * gentarget-def.c (parse_argument): New function. + (def_target_insn): Use it. Handle optional operands. Raise an + error if an .md pattern has the wrong number of operands for the + pattern name. Remove the names of unused operands from the prototype. + * builtins.c (expand_builtin_apply): Use targetm functions + instead of HAVE_call_value and GEN_CALL_VALUE. + * calls.c (emit_call_1): Likewise. Remove support for sibcall_pop + and sibcall_value_pop. + * config/aarch64/aarch64.md (untyped_call): Use gen_call instead + of GEN_CALL. + * config/alpha/alpha.md (untyped_call): Likewise. + * config/iq2000/iq2000.md (untyped_call): Likewise. + * config/m68k/m68k.md (untyped_call): Likewise. + * config/mips/mips.md (untyped_call): Likewise. + * config/pa/pa.md (untyped_call): Likewise. + * config/rs6000/rs6000.md (untyped_call): Likewise. + * config/sparc/sparc.md (untyped_call): Likewise. + * config/tilegx/tilegx.md (untyped_call): Likewise. + * config/tilepro/tilepro.md (untyped_call): Likewise. + * config/visium/visium.md (untyped_call): Likewise. + * config/alpha/alpha.c (alpha_emit_xfloating_libcall): Use + gen_call_value instead of GEN_CALL_VALUE. + * config/arm/arm.md (untyped_call): Likewise. + * config/cr16/cr16.c (cr16_function_arg): Remove reference to + GEN_CALL. + +2015-08-24 Richard Sandiford <richard.sandiford@arm.com> + + * ifcvt.c (HAVE_incscc, HAVE_decscc, HAVE_cbranchcc4): Delete. + (have_cbranchcc4): New variable. + (cc_in_cond, noce_emit_cmove, noce_get_alt_condition) + (noce_get_condition): Use it instead of HAVE_cbranchcc4. + (if_convert): Initialize have_cbranchcc4. + +2015-08-24 Richard Sandiford <richard.sandiford@arm.com> + + * builtins.c (expand_cmpstrn): Rename to... + (expand_cmpstrn_or_cmpmem): ...this. + (expand_builtin_strcmp, expand_builtin_strncmp): Update accordingly. + (expand_builtin_memcmp): Use optabs instead of HAVE_cmpmem/gen_cmpmem. + Remove mode argument. + (expand_builtin): Update accordingly. + +2015-08-24 Richard Sandiford <richard.sandiford@arm.com> + + * builtins.c (expand_cmpstr, expand_cmpstrn): New functions. + (expand_builtin_strcmp, expand_builtin_strncmp): Use them. Remove + references to HAVE_cmpstr{,n}si and CODE_FOR_cmpstr{,n}si. + * config/m32c/blkmov.md (cmpstrsi): Fix predicates of operands 1 and 2. + Add predicates for operands 0 and 3. + * config/rx/rx.md (cmpstrnsi): Remove force_operand for the length + operand. + * config/sh/sh.md (cmpstrnsi): Change the length predicate from + immediate_operand to nonmemory_operand. + +2015-08-24 Richard Sandiford <richard.sandiford@arm.com> + + * df-scan.c (df_insn_info_init_fields): New function, split out + from... + (df_insn_create_insn_record): ...here. + (df_insn_info_free_fields): New function, split out from... + (df_insn_info_delete): ...here. + (df_insn_rescan): Use the new functions instead of freeing and + reallocating the df_insn_info. + +2015-08-24 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> + + * doc/install.texi (Binaries): Remove links no longer valid. + +2015-08-24 Nathan Sidwell <nathan@codesourcery.com> + + * config/nvptx/mkoffload.c (process): Replace + GOMP_offload_{,un}register with GOMP_offload_{,un}register_ver. + +2015-08-24 H.J. Lu <hongjiu.lu@intel.com> + + PR target/67329 + * config/i386/i386.c (iamcu_cost): Set MOVE_RATIO cost to 9. + +2015-08-24 Renlin Li <renlin.li@arm.com> + + * config/arm/arm-protos.h (arm_valid_symbolic_address_p): Declare. + * config/arm/arm.c (arm_valid_symbolic_address_p): Define. + * config/arm/arm.md (arm_movt): Use arm_valid_symbolic_address_p. + * config/arm/constraints.md ("j"): Add check for high code. + +2015-08-24 Tom de Vries <tom@codesourcery.com> + + PR tree-optimization/65468 + * omp-low.c (expand_omp_for_static_chunk): Remove inner loop if + chunk_size is one. + +2015-08-24 Nathan Sidwell <nathan@acm.org> + + * config/nvptx/nvptx.c (walk_args_for_param): Revert previous + change to nvptx_type_from_mode call. Use arg_promotion for both + split and non-split args. + +2015-08-24 Richard Sandiford <richard.sandiford@arm.com> + + * target-insns.def (movstr): New pattern. + * builtins.c (HAVE_movstr, CODE_FOR_movstr): Delete. + (expand_movstr): Use targetm rather than HAVE_movstr/ + CODE_FOR_movstr. + +2015-08-24 Richard Sandiford <richard.sandiford@arm.com> + + * config/microblaze/microblaze.c (microblaze_classify_unspec): Fix + cast syntax. + +2015-08-24 Andrew Pinski <apinski@cavium.com> + + * config/aarch64/aarch64-tuning-flags.def: Remove all index to + AARCH64_EXTRA_TUNING_OPTION. + * config/aarch64/aarch64-protos.h (aarch64_extra_tuning_flags_index): New enum. + (aarch64_extra_tuning_flags): Base the shifted value on the index instead + of the argument to AARCH64_EXTRA_TUNING_OPTION. + * config/aarch64/aarch64.c: Remove the last argument to + AARCH64_EXTRA_TUNING_OPTION. + +2015-08-23 Nathan Sidwell <nathan@acm.org> + + * config/nvptx/nvptx.c (walk_args_for_param): Promote arg reg + decls. + (nvptx_declare_function_name): Insert formatting tabs for + consistency. + +2015-08-23 Tom de Vries <tom@codesourcery.com> + + * omp-low.c (expand_omp_taskreg): If in ssa, set rhs of parcopy stmt to + parm_decl, rather than generating a dummy default def in cfun. + * tree-cfg.c (replace_ssa_name): Assume no default defs. Make sure + ssa_name from cfun and child_fn do not share a stmt as def stmt. + (move_stmt_op): Handle PARM_DECl. + (gather_ssa_name_hash_map_from): New function. + (move_sese_region_to_fn): Add default defs for function params, and add + them to vars_map. Release copied ssa names. + * tree-cfg.h (gather_ssa_name_hash_map_from): Declare. + +2015-08-23 Tom de Vries <tom@codesourcery.com> + + * doc/sourcebuild.texi: Rename vect_no_int_max with + vect_no_int_min_max. Update description. + +2015-08-22 Andrew Pinski <apinski@cavium.com> + + * aarch64-fusion-pairs.def: Remove all index to AARCH64_FUSION_PAIR. + * config/aarch64/aarch64-protos.h + (aarch64_fusion_pairs_index): New enum. + (aarch64_fusion_pairs): Base the shifted value on the index instead + Rewrite AARCH64_FUSE_ALL to be based on the end index. + of the argument to AARCH64_FUSION_PAIR. + * config/aarch64/aarch64.c: Remove the last argument to + AARCH64_FUSION_PAIR. + +2015-08-22 Mikhail Maltsev <maltsevm@gmail.com> + + * dominance.c (new_zero_array): Define. + (dom_info): Redefine as class with proper encapsulation. + (dom_info::m_n_basic_blocks, m_reverse, m_start_block, m_end_block): + Add new members. + (dom_info::dom_info, ~dom_info): Define. Use new/delete for memory + allocations/deallocations. Pass function as parameter (instead of + using cfun). + (dom_info::get_idom): Define accessor method. + (dom_info::calc_dfs_tree_nonrec, calc_dfs_tree, compress, eval, + link_roots, calc_idoms): Redefine as class members. Do not use cfun. + (calculate_dominance_info): Adjust to use dom_info class. + (verify_dominators): Likewise. + +2015-08-21 Alexandre Oliva <aoliva@redhat.com> + + * print-rtl.c (print_rtx): Check the correct range for + flag_dump_unnumbered_links to behave as documented. + + PR rtl-optimization/67227 + PR rtl-optimization/64164 + * alias.c (memrefs_conflict_p): Handle VALUEs in PLUS better. + (nonoverlapping_memrefs_p): Test offsets and sizes when given + identical gimple_reg exprs. + +2015-08-21 Nathan Sidwell <nathan@acm.org> + + * config/nvptx/nvptx.md (allocate_stack): Emit sorry during + expansion. + * config/nvptx/nvptx.c (nvptx_declare_function_name): Look at + crtl->stack_alignment_needed to determine alignment. + (nvptx_get_drap_rtx): New. + (TARGET_GET_DRAP_RTX): Override. + * config/nvptx/nvptx.h (MAX_STACK_ALIGNMENT): Set. + +2015-08-21 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> + + * config.build: Remove case for m68000-hp-hpux* | m68k-hp-hpux*. + +2015-08-21 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> + + * configure.ac: Remove uwin* cases. + * config.build: Remove cases for i370-*-opened*, i370-*-mvs*, + i[34567]86-*-sco3.2v5*, i[34567]86-sequent-ptx4*, + i[34567]86-sequent-sysv4*, i[34567]86-*-sysv4*, + i[34567]86-*-udk*, i[34567]86-*-uwin*, i386-*-vsta. + * config.host: Remove cases for i370-*-opened*, i370-*-mvs*, + i[34567]86-*-uwin*, powerpc-*-beos*. + +2015-08-21 Richard Sandiford <richard.sandiford@arm.com> + + * gencodes.c (gencodes): Print the comma for the preceding + enum value rather than the current one. Use aliased enum values + rather than #defines for compiled-out patterns. + (main): Update accordingly. Replace LAST_INSN_CODE with + NUM_INSN_CODES. + * lra.c (insn_code_data): Update accordingly. + (finish_insn_code_data_once, get_static_insn_data): Likewise. + * recog.h (target_recog): Likewise. + (preprocess_insn_constraints): Change parameter to unsigned int. + * recog.c (preprocess_insn_constraints): Likewise. + (recog_init): Replace LAST_INSN_CODE with NUM_INSN_CODES. + * tree-vect-stmts.c (vectorizable_operation): Simplify. + +2015-08-21 Markus Trippelsdorf <markus@trippelsdorf.de> + + PR rtl-optimization/61657 + * loop-iv.c (iv_number_of_iterations): Declare up and down as + unsigned. Remove superflous uint64_t cast. + +2014-08-21 Felix Yang <felix.yang@huawei.com> + Jiji Jiang <jiangjiji@huawei.com> + + * value-prof.c (interesting_stringop_to_profile_p): Removed FNDECL argument + and get builtin function code directly from CALL. + (gimple_stringop_fixed_value): Modified accordingly. + (gimple_stringops_transform, gimple_stringops_values_to_profile): Modified + accordingly and only accept BUILT_IN_NORMAL string operations. + +2015-08-21 Dominik Vogt <vogt@linux.vnet.ibm.com> + + * config/s390/s390-builtins.def: Fix value range of vec_load_bndry. + +2015-08-21 Naveen H.S <Naveen.Hurugalawadi@caviumnetworks.com> + + * fold-const.c (fold_binary_loc) : Move sqrt(x)*sqrt(x) as x + to match.pd. + Move Optimize pow(x,y)*pow(z,y) as pow(x*z,y)to match.pd. + Move Optimize tan(x)*cos(x) as sin(x) to match.pd. + Move Optimize x*pow(x,c) as pow(x,c+1) to match.pd. + Move Optimize pow(x,c)*x as pow(x,c+1) to match.pd. + Move Optimize sin(x)/cos(x) as tan(x) to match.pd. + Move Optimize cos(x)/sin(x) as 1.0/tan(x) to match.pd. + Move Optimize sin(x)/tan(x) as cos(x) to match.pd. + Move Optimize tan(x)/sin(x) as 1.0/cos(x) to match.pd. + Move Optimize pow(x,c)/x as pow(x,c-1) to match.pd. + Move Optimize x/pow(y,z) into x*pow(y,-z) to match.pd. + + * match.pd (SIN ) : New Operator. + (TAN) : New Operator. + (mult (SQRT@1 @0) @1) : New simplifier. + (mult (POW:s @0 @1) (POW:s @2 @1)) : New simplifier. + (mult:c (TAN:s @0) (COS:s @0)) : New simplifier. + (mult:c (TAN:s @0) (COS:s @0)) : New simplifier. + (rdiv (SIN:s @0) (COS:s @0)) : New simplifier. + (rdiv (COS:s @0) (SIN:s @0)) : New simplifier. + (rdiv (SIN:s @0) (TAN:s @0)) : New simplifier. + (rdiv (TAN:s @0) (SIN:s @0)) : New simplifier. + (rdiv (POW:s @0 REAL_CST@1) @0) : New simplifier. + (rdiv @0 (SQRT:s (rdiv:s @1 @2))) : New simplifier. + (rdiv @0 (POW:s @1 @2)) : New simplifier. + +2015-08-21 Bin Cheng <bin.cheng@arm.com> + + * tree-ssa-loop-niter.c (simplify_using_initial_conditions): Break + loop if EXPR is simplified to const value. + +2015-08-21 Yury Gribov <y.gribov@samsung.com> + + * sanitizer.def (BUILT_IN_UBSAN_HANDLE_NONNULL_ARG, + BUILT_IN_UBSAN_HANDLE_NONNULL_ARG): Fix builtin types. + +2015-08-21 Richard Biener <rguenther@suse.de> + + PR middle-end/67285 + * gimple-fold.c (replace_stmt_with_simplification): Assert + seq is empty when replacing a call with itself but different + arguments. + * gimple-match-head.c (maybe_push_res_to_seq): When pushing + a call require that it is const. + +2015-08-20 Trevor Saunders <tbsaunde+gcc@tbsaunde.org> + + * defaults.h (CONSTANT_ALIGNMENT): New macro definition. + * builtins.c (get_object_alignment_2): Adjust. + * varasm.c (align_variable): Likewise. + (get_variable_align): Likewise. + (build_constant_desc): Likewise. + (force_const_mem): Likewise. + * doc/tm.texi.in: Likewise. + * doc/tm.texi: Regenerate. + +2015-08-20 Trevor Saunders <tbsaunde+gcc@tbsaunde.org> + + * genconfig.c (main): Always define HAVE_cc0. + * recog.c (rest_of_handle_peephole2): Adjust. + +2015-08-20 Trevor Saunders <tbsaunde+gcc@tbsaunde.org> + + * reorg.c (relax_delay_slots): Don't use #if to check value of + HAVE_cc0. + +2015-08-20 Trevor Saunders <tbsaunde+gcc@tbsaunde.org> + + * genconfig.c (main): Always define HAVE_CONDITIONAL_EXECUTION. + * targhooks.c (default_have_conditional_execution): Adjust. + +2015-08-20 Richard Sandiford <richard.sandiford@arm.com> + + * rtl.h (rtvec_all_equal_p): Declare. + (const_vec_duplicate_p, unwrap_const_vec_duplicate): New functions. + * rtl.c (rtvec_all_equal_p): New function. + * expmed.c (expand_mult): Use unwrap_const_vec_duplicate. + * config/aarch64/aarch64.c (aarch64_vect_float_const_representable_p) + (aarch64_simd_dup_constant): Use const_vec_duplicate_p. + * config/arm/arm.c (neon_vdup_constant): Likewise. + * config/s390/s390.c (s390_contiguous_bitmask_vector_p): Likewise. + * config/tilegx/constraints.md (W, Y): Likewise. + * config/tilepro/constraints.md (W, Y): Likewise. + * config/spu/spu.c (spu_legitimate_constant_p): Likewise. + (classify_immediate): Use unwrap_const_vec_duplicate. + * config/tilepro/predicates.md (reg_or_v4s8bit_operand): Likewise. + (reg_or_v2s8bit_operand): Likewise. + * config/tilegx/predicates.md (reg_or_v8s8bit_operand): Likewise. + (reg_or_v4s8bit_operand): Likewise. + +2015-08-20 Bill Schmidt <wschmidt@linux.vnet.ibm.com> + + * config/rs6000/altivec.h (vec_pmsum_be): New #define. + (vec_shasigma_be): New #define. + * config/rs6000/rs6000-builtin.def (VPMSUMB): New BU_P8V_AV2_2. + (VPMSUMH): Likewise. + (VPMSUMW): Likewise. + (VPMSUMD): Likewise. + (VPMSUM): New BU_P8V_OVERLOAD_2. + * config/rs6000/rs6000-c.c (altivec_overloaded_builtins): New + entries for VEC_MADD and VEC_VPMSUM. + +2015-08-20 Georg-Johann Lay <avr@gjlay.de> + + * config/avr/avr.c (avr_insert_attributes): In diagnostic essage: + Multiply argument avr_n_flash by 64 to match unit of "KiB". + (avr_pgm_check_var_decl): Same. + +2015-08-20 Alan Lawrence <alan.lawrence@arm.com> + + * config/arm/arm-builtins.c (arm_init_simd_builtin_types): Move + initialization of HFmode scalar type (float16_t) to... + (arm_init_fp16_builtins): ... Here. Combine with __fp16 initialization + code. + + (arm_init_builtins): Call arm_init_fp16_builtins earlier and always. + + * config/arm/arm_neon.h (vcvt_f16_f32, vcvt_f32_f16): Condition on + having an -mfp16-format. + +2015-08-20 Richard Sandiford <richard.sandiford@arm.com> + + * config/i386/predicates.md (vector_all_ones_operand): Use + CONSTM1_RTX to simplify definition. + +2015-08-20 Richard Biener <rguenther@suse.de> + + * toplev.c (compile_file): Remove loop calling late_global_decl + on all symbols. + * varpool.c (varpool_node::assemble_decl): Call late_global_decl + on decls we assembled. + +2015-08-20 James Greenhalgh <james.greenhalgh@arm.com> + + * common/config/aarch64/aarch64-common.c + (AARCH64_CPU_NAME_LENGTH): Delete. + (aarch64_option_extension): New. + (all_extensions): Likewise. + (processor_name_to_arch): Likewise. + (arch_to_arch_name): Likewise. + (all_cores): New. + (all_architectures): Likewise. + (aarch64_get_extension_string_for_isa_flags): Likewise. + (aarch64_rewrite_selected_cpu): Change to rewrite CPU names to + architecture names. + * config/aarch64/aarch64-protos.h + (aarch64_get_extension_string_for_isa_flags): New. + * config/aarch64/aarch64.c (aarch64_print_extension): Delete. + (aarch64_option_print): Get the string to print from + aarch64_get_extension_string_for_isa_flags. + (aarch64_declare_function_name): Likewise. + * config/aarch64/aarch64.h (BIG_LITTLE_SPEC): Rename to... + (MCPU_TO_MARCH_SPEC): This. + (ASM_CPU_SPEC): Use it. + (BIG_LITTLE_SPEC_FUNCTIONS): Rename to... + (MCPU_TO_MARCH_SPEC_FUNCTIONS): ...This. + (EXTRA_SPEC_FUNCTIONS): Use it. + +2015-08-20 Simon Dardis <simon.dardis@imgtec.com> + + * config/mips/mips.c (mips_expand_block_move): Enable inline memcpy + expansion when !ISA_HAS_LWL_LWR. + (mips_block_move_straight): Update the size of elements copied to + account for alignment when !ISA_HAS_LWL_LWR. + * config/mips/mips.h (MIPS_MIN_MOVE_MEM_ALIGN): New macro. + +2015-08-19 Jiong Wang <jiong.wang@arm.com> + + * expr.c (expand_expr_real_2): Check gimple statement during + LSHIFT_EXPR expand. + +2015-08-19 Magnus Granberg <zorry@gentoo.org> + + * common.opt (fstack-protector): Initialize to -1. + (fstack-protector-all): Likewise. + (fstack-protector-strong): Likewise. + (fstack-protector-explicit): Likewise. + * configure.ac: Add --enable-default-ssp. + * defaults.h (DEFAULT_FLAG_SSP): New. Default SSP to strong. + * opts.c (finish_options): Update opts->x_flag_stack_protect if it is + -1. + * doc/install.texi: Document --enable-default-ssp. + * config.in: Regenerated. + * configure: Likewise. + +2015-08-19 Alexandre Oliva <aoliva@redhat.com> + + PR rtl-optimization/64164 + * cfgexpand.c (parm_maybe_byref_p): Renamed to... + (parm_in_stack_slot_p): ... this. Disregard mode, what + matters is whether the parm will live in a pseudo or a stack + slot. + (expand_one_ssa_partition): Deal with params without a default + def. Disregard mode. + * cfgexpand.h: Renamed function declaration. + * tree-ssa-coalesce.c: Adjust. + * function.c (split_complex_args): Allocate stack slot for + unassigned parms before splitting. + (parm_in_unassigned_mem_p): New. Use it instead of + parm_maybe_byref_p throughout this file. + (assign_parm_setup_block): Use it. Accept pseudos in the + expand-assigned rtl. + (assign_parm_setup_reg): Drop BLKmode requirement. + (assign_parm_setup_stack): Allocate and fill in the address of + unassigned MEM parms. + +2015-08-19 David Sherwood <david.sherwood@arm.com> + + * genmodes.c (emit_mode_unit_size_inline): New function. + (emit_mode_unit_precision_inline): New function. + (emit_insn_modes_h): Emit new #define. Emit new functions. + (emit_mode_unit_size): New function. + (emit_mode_unit_precision): New function. + (emit_mode_adjustments): Add mode_unit_size adjustments. + (emit_insn_modes_c): Emit new arrays. + * machmode.h (GET_MODE_UNIT_SIZE, GET_MODE_UNIT_PRECISION): Update to + use new inline methods. + +2015-08-19 Kyrylo Tkachov <kyrylo.tkachov@arm.com> + + * config/aarch64/aarch64.c (bit_count): Delete prototype + and definition. + (aarch64_print_operand): Use popcount_hwi instead of the above. + +2015-08-19 Kyrylo Tkachov <kyrylo.tkachov@arm.com> + + * config/aarch64/aarch64-option-extensions.def: Delete obsolete + comment. + +2015-08-19 Marek Polacek <polacek@redhat.com> + + PR middle-end/67133 + * gimple-ssa-isolate-paths.c + (insert_trap_and_remove_trailing_statements): Rename to ... + (insert_trap): ... this. Don't remove trailing statements; split + block instead. + (find_explicit_erroneous_behaviour): Don't remove all outgoing edges. + +2015-08-19 Mikael Morin <mikael@gcc.gnu.org> + + PR other/67042 + * hwint.h (sext_hwi): Switch to unsigned for the left shift, and + conditionalize the whole on __GNUC__. Add fallback code + depending neither on undefined nor implementation-defined behaviour. + +2015-08-19 Jiong Wang <jiong.wang@arm.com> + + * config/aarch64/aarch64.c (aarch64_load_symref_appropriately): Replace + whitespaces with tab. + +2015-08-19 Florian Weimer <fweimer@redhat.com> + + * prj.adb (For_Every_Project_Imported_Context.Recursive_Check_Context): + Move Name_Id_Set instantiation to the Prj package, to avoid trampolines. + * prj-proc.adb (Process.Process_Expression_Variable_Decl): + Move Name_Ids instantiation to the Prj.Proc package, to avoid + trampolines. + +2015-08-19 Kyrylo Tkachov <kyrylo.tkachov@arm.com> + + * config/arm/arm.c (bounds_check): Use %wd print format + for HOST_WIDE_INT arguments. + +2015-08-18 Trevor Saunders <tbsaunde@tbsaunde.org> + + * bb-reorder.c, cfgloop.h, collect2.c, combine.c, dse.c, + dwarf2cfi.c, gcse-common.h, genopinit.c, ggc-page.c, machmode.h, + mcf.c, modulo-sched.c, omp-low.c, read-rtl.c, sched-rgn.c, + signop.h, tree-call-cdce.c, tree-dfa.c, tree-diagnostic.c, + tree-inline.h, tree-scalar-evolution.c, tree-ssa-address.c, + tree-ssa-loop-niter.c, tree-ssa-loop.h, tree-ssa-pre.c, + tree-ssa-reassoc.c, tree-ssa-sccvn.h, tree-ssa-structalias.c, + tree-ssa-uninit.c, tree-ssa.h, tree-vect-loop-manip.c, + tree-vectorizer.h, tree-vrp.c, var-tracking.c: Remove useless + typedefs. + 2015-08-18 trevor Saunders <tbsaunde@tbsaunde.org> * bt-load.c, cgraph.h, dwarf2out.c, dwarf2out.h, final.c, @@ -710,8 +2173,8 @@ * configure.ac: Define LIBICONV_DEP with in-tree libiconv. * configure: Regenerate. -2015-08-06 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com> - Jiong Wang <jiong.wang@arm.com> +2015-08-06 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com> + Jiong Wang <jiong.wang@arm.com> * config/aarch64/aarch64.d (tlsdesc_small_pseudo_<mode>): New pattern. * config/aarch64/aarch64.h (reg_class): New enumeration FIXED_REG0. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index cb5a946ff7d..4c97cf77e19 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20150819 +20150902 diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 087491dbe22..191cdf177ec 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1279,10 +1279,8 @@ OBJS = \ graph.o \ graphds.o \ graphite.o \ - graphite-blocking.o \ graphite-isl-ast-to-gimple.o \ graphite-dependences.o \ - graphite-interchange.o \ graphite-optimize-isl.o \ graphite-poly.o \ graphite-scop-detection.o \ diff --git a/gcc/ada/prj-proc.adb b/gcc/ada/prj-proc.adb index 57b88c651bf..3a014f1f6b3 100644 --- a/gcc/ada/prj-proc.adb +++ b/gcc/ada/prj-proc.adb @@ -72,6 +72,8 @@ package body Prj.Proc is Equal => "="); -- Stores the default values of 'Runtime names for the various languages + package Name_Ids is new Ada.Containers.Vectors (Positive, Name_Id); + procedure Add (To_Exp : in out Name_Id; Str : Name_Id); -- Concatenate two strings and returns another string if both -- arguments are not null string. @@ -2193,8 +2195,6 @@ package body Prj.Proc is if Is_Attribute and then Name = Snames.Name_Project_Path then if In_Tree.Is_Root_Tree then declare - package Name_Ids is - new Ada.Containers.Vectors (Positive, Name_Id); Val : String_List_Id := New_Value.Values; List : Name_Ids.Vector; begin diff --git a/gcc/ada/prj.adb b/gcc/ada/prj.adb index 9da0f448564..0deb39beb29 100644 --- a/gcc/ada/prj.adb +++ b/gcc/ada/prj.adb @@ -76,6 +76,9 @@ package body Prj is All_Upper_Case => All_Upper_Case_Image'Access, Mixed_Case => Mixed_Case_Image'Access); + package Name_Id_Set is + new Ada.Containers.Ordered_Sets (Element_Type => Name_Id); + procedure Free (Project : in out Project_Id); -- Free memory allocated for Project @@ -589,9 +592,6 @@ package body Prj is In_Aggregate_Lib : Boolean; From_Encapsulated_Lib : Boolean) is - package Name_Id_Set is - new Ada.Containers.Ordered_Sets (Element_Type => Name_Id); - Seen_Name : Name_Id_Set.Set; -- This set is needed to ensure that we do not handle the same -- project twice in the context of aggregate libraries. diff --git a/gcc/alias.c b/gcc/alias.c index 4681e3f8b96..f12d9d12a2b 100644 --- a/gcc/alias.c +++ b/gcc/alias.c @@ -2228,6 +2228,13 @@ memrefs_conflict_p (int xsize, rtx x, int ysize, rtx y, HOST_WIDE_INT c) rtx x0 = XEXP (x, 0); rtx x1 = XEXP (x, 1); + /* However, VALUEs might end up in different positions even in + canonical PLUSes. Comparing their addresses is enough. */ + if (x0 == y) + return memrefs_conflict_p (xsize, x1, ysize, const0_rtx, c); + else if (x1 == y) + return memrefs_conflict_p (xsize, x0, ysize, const0_rtx, c); + if (GET_CODE (y) == PLUS) { /* The fact that Y is canonicalized means that this @@ -2235,6 +2242,11 @@ memrefs_conflict_p (int xsize, rtx x, int ysize, rtx y, HOST_WIDE_INT c) rtx y0 = XEXP (y, 0); rtx y1 = XEXP (y, 1); + if (x0 == y1) + return memrefs_conflict_p (xsize, x1, ysize, y0, c); + if (x1 == y0) + return memrefs_conflict_p (xsize, x0, ysize, y1, c); + if (rtx_equal_for_memref_p (x1, y1)) return memrefs_conflict_p (xsize, x0, ysize, y0, c); if (rtx_equal_for_memref_p (x0, y0)) @@ -2263,6 +2275,11 @@ memrefs_conflict_p (int xsize, rtx x, int ysize, rtx y, HOST_WIDE_INT c) rtx y0 = XEXP (y, 0); rtx y1 = XEXP (y, 1); + if (x == y0) + return memrefs_conflict_p (xsize, const0_rtx, ysize, y1, c); + if (x == y1) + return memrefs_conflict_p (xsize, const0_rtx, ysize, y0, c); + if (CONST_INT_P (y1)) return memrefs_conflict_p (xsize, x, ysize, y0, c + INTVAL (y1)); else @@ -2518,7 +2535,11 @@ nonoverlapping_memrefs_p (const_rtx x, const_rtx y, bool loop_invariant) able to do anything about them since no SSA information will have remained to guide it. */ if (is_gimple_reg (exprx) || is_gimple_reg (expry)) - return exprx != expry; + return exprx != expry + || (moffsetx_known_p && moffsety_known_p + && MEM_SIZE_KNOWN_P (x) && MEM_SIZE_KNOWN_P (y) + && !offset_overlap_p (moffsety - moffsetx, + MEM_SIZE (x), MEM_SIZE (y))); /* With invalid code we can end up storing into the constant pool. Bail out to avoid ICEing when creating RTL for this. diff --git a/gcc/builtins.c b/gcc/builtins.c index 31969ca3e53..d79372cf268 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -119,7 +119,6 @@ static rtx expand_builtin_next_arg (void); static rtx expand_builtin_va_start (tree); static rtx expand_builtin_va_end (tree); static rtx expand_builtin_va_copy (tree); -static rtx expand_builtin_memcmp (tree, rtx, machine_mode); static rtx expand_builtin_strcmp (tree, rtx); static rtx expand_builtin_strncmp (tree, rtx, machine_mode); static rtx builtin_memcpy_read_str (void *, HOST_WIDE_INT, machine_mode); @@ -314,10 +313,9 @@ get_object_alignment_2 (tree exp, unsigned int *alignp, /* The alignment of a CONST_DECL is determined by its initializer. */ exp = DECL_INITIAL (exp); align = TYPE_ALIGN (TREE_TYPE (exp)); -#ifdef CONSTANT_ALIGNMENT if (CONSTANT_CLASS_P (exp)) align = (unsigned) CONSTANT_ALIGNMENT (exp, align); -#endif + known_alignment = true; } else if (DECL_P (exp)) @@ -393,10 +391,9 @@ get_object_alignment_2 (tree exp, unsigned int *alignp, /* STRING_CST are the only constant objects we allow to be not wrapped inside a CONST_DECL. */ align = TYPE_ALIGN (TREE_TYPE (exp)); -#ifdef CONSTANT_ALIGNMENT if (CONSTANT_CLASS_P (exp)) align = (unsigned) CONSTANT_ALIGNMENT (exp, align); -#endif + known_alignment = true; } @@ -1689,9 +1686,7 @@ expand_builtin_apply (rtx function, rtx arguments, rtx argsize) emit_call_insn (targetm.gen_untyped_call (mem, result, result_vector (1, result))); } - else -#ifdef HAVE_call_value - if (HAVE_call_value) + else if (targetm.have_call_value ()) { rtx valreg = 0; @@ -1702,19 +1697,18 @@ expand_builtin_apply (rtx function, rtx arguments, rtx argsize) for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) if ((mode = apply_result_mode[regno]) != VOIDmode) { - gcc_assert (!valreg); /* HAVE_untyped_call required. */ + gcc_assert (!valreg); /* have_untyped_call required. */ valreg = gen_rtx_REG (mode, regno); } - emit_call_insn (GEN_CALL_VALUE (valreg, - gen_rtx_MEM (FUNCTION_MODE, function), - const0_rtx, NULL_RTX, const0_rtx)); + emit_insn (targetm.gen_call_value (valreg, + gen_rtx_MEM (FUNCTION_MODE, function), + const0_rtx, NULL_RTX, const0_rtx)); emit_move_insn (adjust_address (result, GET_MODE (valreg), 0), valreg); } else -#endif gcc_unreachable (); /* Find the CALL insn we just emitted, and attach the register usage @@ -3440,11 +3434,6 @@ expand_builtin_mempcpy_args (tree dest, tree src, tree len, } } -#ifndef HAVE_movstr -# define HAVE_movstr 0 -# define CODE_FOR_movstr CODE_FOR_nothing -#endif - /* Expand into a movstr instruction, if one is available. Return NULL_RTX if we failed, the caller should emit a normal call, otherwise try to get the result in TARGET, if convenient. If ENDP is 0 return the @@ -3459,7 +3448,7 @@ expand_movstr (tree dest, tree src, rtx target, int endp) rtx dest_mem; rtx src_mem; - if (!HAVE_movstr) + if (!targetm.have_movstr ()) return NULL_RTX; dest_mem = get_memory_rtx (dest, NULL); @@ -3473,7 +3462,7 @@ expand_movstr (tree dest, tree src, rtx target, int endp) create_output_operand (&ops[0], endp ? target : NULL_RTX, Pmode); create_fixed_operand (&ops[1], dest_mem); create_fixed_operand (&ops[2], src_mem); - if (!maybe_expand_insn (CODE_FOR_movstr, 3, ops)) + if (!maybe_expand_insn (targetm.code_for_movstr, 3, ops)) return NULL_RTX; if (endp && target != const0_rtx) @@ -3924,17 +3913,61 @@ expand_builtin_bzero (tree exp) const0_rtx, VOIDmode, exp); } +/* Try to expand cmpstr operation ICODE with the given operands. + Return the result rtx on success, otherwise return null. */ + +static rtx +expand_cmpstr (insn_code icode, rtx target, rtx arg1_rtx, rtx arg2_rtx, + HOST_WIDE_INT align) +{ + machine_mode insn_mode = insn_data[icode].operand[0].mode; + + if (target && (!REG_P (target) || HARD_REGISTER_P (target))) + target = NULL_RTX; + + struct expand_operand ops[4]; + create_output_operand (&ops[0], target, insn_mode); + create_fixed_operand (&ops[1], arg1_rtx); + create_fixed_operand (&ops[2], arg2_rtx); + create_integer_operand (&ops[3], align); + if (maybe_expand_insn (icode, 4, ops)) + return ops[0].value; + return NULL_RTX; +} + +/* Try to expand cmpstrn or cmpmem operation ICODE with the given operands. + ARG3_TYPE is the type of ARG3_RTX. Return the result rtx on success, + otherwise return null. */ + +static rtx +expand_cmpstrn_or_cmpmem (insn_code icode, rtx target, rtx arg1_rtx, + rtx arg2_rtx, tree arg3_type, rtx arg3_rtx, + HOST_WIDE_INT align) +{ + machine_mode insn_mode = insn_data[icode].operand[0].mode; + + if (target && (!REG_P (target) || HARD_REGISTER_P (target))) + target = NULL_RTX; + + struct expand_operand ops[5]; + create_output_operand (&ops[0], target, insn_mode); + create_fixed_operand (&ops[1], arg1_rtx); + create_fixed_operand (&ops[2], arg2_rtx); + create_convert_operand_from (&ops[3], arg3_rtx, TYPE_MODE (arg3_type), + TYPE_UNSIGNED (arg3_type)); + create_integer_operand (&ops[4], align); + if (maybe_expand_insn (icode, 5, ops)) + return ops[0].value; + return NULL_RTX; +} + /* Expand expression EXP, which is a call to the memcmp built-in function. Return NULL_RTX if we failed and the caller should emit a normal call, - otherwise try to get the result in TARGET, if convenient (and in mode - MODE, if that's convenient). */ + otherwise try to get the result in TARGET, if convenient. */ static rtx -expand_builtin_memcmp (tree exp, ATTRIBUTE_UNUSED rtx target, - ATTRIBUTE_UNUSED machine_mode mode) +expand_builtin_memcmp (tree exp, rtx target) { - location_t loc ATTRIBUTE_UNUSED = EXPR_LOCATION (exp); - if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE, VOID_TYPE)) return NULL_RTX; @@ -3942,78 +3975,66 @@ expand_builtin_memcmp (tree exp, ATTRIBUTE_UNUSED rtx target, /* Note: The cmpstrnsi pattern, if it exists, is not suitable for implementing memcmp because it will stop if it encounters two zero bytes. */ -#if defined HAVE_cmpmemsi - { - rtx arg1_rtx, arg2_rtx, arg3_rtx; - rtx result; - rtx insn; - tree arg1 = CALL_EXPR_ARG (exp, 0); - tree arg2 = CALL_EXPR_ARG (exp, 1); - tree len = CALL_EXPR_ARG (exp, 2); + insn_code icode = direct_optab_handler (cmpmem_optab, SImode); + if (icode == CODE_FOR_nothing) + return NULL_RTX; - unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT; - unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT; - machine_mode insn_mode; + tree arg1 = CALL_EXPR_ARG (exp, 0); + tree arg2 = CALL_EXPR_ARG (exp, 1); + tree len = CALL_EXPR_ARG (exp, 2); - if (HAVE_cmpmemsi) - insn_mode = insn_data[(int) CODE_FOR_cmpmemsi].operand[0].mode; - else - return NULL_RTX; + unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT; + unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT; - /* If we don't have POINTER_TYPE, call the function. */ - if (arg1_align == 0 || arg2_align == 0) - return NULL_RTX; + /* If we don't have POINTER_TYPE, call the function. */ + if (arg1_align == 0 || arg2_align == 0) + return NULL_RTX; - /* Make a place to write the result of the instruction. */ - result = target; - if (! (result != 0 - && REG_P (result) && GET_MODE (result) == insn_mode - && REGNO (result) >= FIRST_PSEUDO_REGISTER)) - result = gen_reg_rtx (insn_mode); + machine_mode mode = TYPE_MODE (TREE_TYPE (exp)); + location_t loc = EXPR_LOCATION (exp); + rtx arg1_rtx = get_memory_rtx (arg1, len); + rtx arg2_rtx = get_memory_rtx (arg2, len); + rtx arg3_rtx = expand_normal (fold_convert_loc (loc, sizetype, len)); - arg1_rtx = get_memory_rtx (arg1, len); - arg2_rtx = get_memory_rtx (arg2, len); - arg3_rtx = expand_normal (fold_convert_loc (loc, sizetype, len)); + /* Set MEM_SIZE as appropriate. */ + if (CONST_INT_P (arg3_rtx)) + { + set_mem_size (arg1_rtx, INTVAL (arg3_rtx)); + set_mem_size (arg2_rtx, INTVAL (arg3_rtx)); + } - /* Set MEM_SIZE as appropriate. */ - if (CONST_INT_P (arg3_rtx)) - { - set_mem_size (arg1_rtx, INTVAL (arg3_rtx)); - set_mem_size (arg2_rtx, INTVAL (arg3_rtx)); - } + rtx result = expand_cmpstrn_or_cmpmem (icode, target, arg1_rtx, arg2_rtx, + TREE_TYPE (len), arg3_rtx, + MIN (arg1_align, arg2_align)); + if (result) + { + /* Return the value in the proper mode for this function. */ + if (GET_MODE (result) == mode) + return result; - if (HAVE_cmpmemsi) - insn = gen_cmpmemsi (result, arg1_rtx, arg2_rtx, arg3_rtx, - GEN_INT (MIN (arg1_align, arg2_align))); - else - gcc_unreachable (); + if (target != 0) + { + convert_move (target, result, 0); + return target; + } - if (insn) - emit_insn (insn); - else - emit_library_call_value (memcmp_libfunc, result, LCT_PURE, - TYPE_MODE (integer_type_node), 3, - XEXP (arg1_rtx, 0), Pmode, - XEXP (arg2_rtx, 0), Pmode, - convert_to_mode (TYPE_MODE (sizetype), arg3_rtx, - TYPE_UNSIGNED (sizetype)), - TYPE_MODE (sizetype)); - - /* Return the value in the proper mode for this function. */ - mode = TYPE_MODE (TREE_TYPE (exp)); - if (GET_MODE (result) == mode) - return result; - else if (target != 0) - { - convert_move (target, result, 0); - return target; - } - else return convert_to_mode (mode, result, 0); - } -#endif /* HAVE_cmpmemsi. */ + } - return NULL_RTX; + result = target; + if (! (result != 0 + && REG_P (result) && GET_MODE (result) == mode + && REGNO (result) >= FIRST_PSEUDO_REGISTER)) + result = gen_reg_rtx (mode); + + emit_library_call_value (memcmp_libfunc, result, LCT_PURE, + TYPE_MODE (integer_type_node), 3, + XEXP (arg1_rtx, 0), Pmode, + XEXP (arg2_rtx, 0), Pmode, + convert_to_mode (TYPE_MODE (sizetype), arg3_rtx, + TYPE_UNSIGNED (sizetype)), + TYPE_MODE (sizetype)); + return result; } /* Expand expression EXP, which is a call to the strcmp builtin. Return NULL_RTX @@ -4026,15 +4047,15 @@ expand_builtin_strcmp (tree exp, ATTRIBUTE_UNUSED rtx target) if (!validate_arglist (exp, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) return NULL_RTX; -#if defined HAVE_cmpstrsi || defined HAVE_cmpstrnsi - if (direct_optab_handler (cmpstr_optab, SImode) != CODE_FOR_nothing - || direct_optab_handler (cmpstrn_optab, SImode) != CODE_FOR_nothing) + insn_code cmpstr_icode = direct_optab_handler (cmpstr_optab, SImode); + insn_code cmpstrn_icode = direct_optab_handler (cmpstrn_optab, SImode); + if (cmpstr_icode != CODE_FOR_nothing || cmpstrn_icode != CODE_FOR_nothing) { rtx arg1_rtx, arg2_rtx; - rtx result, insn = NULL_RTX; tree fndecl, fn; tree arg1 = CALL_EXPR_ARG (exp, 0); tree arg2 = CALL_EXPR_ARG (exp, 1); + rtx result = NULL_RTX; unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT; unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT; @@ -4050,33 +4071,17 @@ expand_builtin_strcmp (tree exp, ATTRIBUTE_UNUSED rtx target) arg1_rtx = get_memory_rtx (arg1, NULL); arg2_rtx = get_memory_rtx (arg2, NULL); -#ifdef HAVE_cmpstrsi /* Try to call cmpstrsi. */ - if (HAVE_cmpstrsi) - { - machine_mode insn_mode - = insn_data[(int) CODE_FOR_cmpstrsi].operand[0].mode; - - /* Make a place to write the result of the instruction. */ - result = target; - if (! (result != 0 - && REG_P (result) && GET_MODE (result) == insn_mode - && REGNO (result) >= FIRST_PSEUDO_REGISTER)) - result = gen_reg_rtx (insn_mode); - - insn = gen_cmpstrsi (result, arg1_rtx, arg2_rtx, - GEN_INT (MIN (arg1_align, arg2_align))); - } -#endif -#ifdef HAVE_cmpstrnsi + if (cmpstr_icode != CODE_FOR_nothing) + result = expand_cmpstr (cmpstr_icode, target, arg1_rtx, arg2_rtx, + MIN (arg1_align, arg2_align)); + /* Try to determine at least one length and call cmpstrnsi. */ - if (!insn && HAVE_cmpstrnsi) + if (!result && cmpstrn_icode != CODE_FOR_nothing) { tree len; rtx arg3_rtx; - machine_mode insn_mode - = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode; tree len1 = c_strlen (arg1, 1); tree len2 = c_strlen (arg2, 1); @@ -4110,30 +4115,19 @@ expand_builtin_strcmp (tree exp, ATTRIBUTE_UNUSED rtx target) len = len2; /* If both arguments have side effects, we cannot optimize. */ - if (!len || TREE_SIDE_EFFECTS (len)) - goto do_libcall; - - arg3_rtx = expand_normal (len); - - /* Make a place to write the result of the instruction. */ - result = target; - if (! (result != 0 - && REG_P (result) && GET_MODE (result) == insn_mode - && REGNO (result) >= FIRST_PSEUDO_REGISTER)) - result = gen_reg_rtx (insn_mode); - - insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx, - GEN_INT (MIN (arg1_align, arg2_align))); + if (len && !TREE_SIDE_EFFECTS (len)) + { + arg3_rtx = expand_normal (len); + result = expand_cmpstrn_or_cmpmem + (cmpstrn_icode, target, arg1_rtx, arg2_rtx, TREE_TYPE (len), + arg3_rtx, MIN (arg1_align, arg2_align)); + } } -#endif - if (insn) + if (result) { - machine_mode mode; - emit_insn (insn); - /* Return the value in the proper mode for this function. */ - mode = TYPE_MODE (TREE_TYPE (exp)); + machine_mode mode = TYPE_MODE (TREE_TYPE (exp)); if (GET_MODE (result) == mode) return result; if (target == 0) @@ -4144,16 +4138,12 @@ expand_builtin_strcmp (tree exp, ATTRIBUTE_UNUSED rtx target) /* Expand the library call ourselves using a stabilized argument list to avoid re-evaluating the function's arguments twice. */ -#ifdef HAVE_cmpstrnsi - do_libcall: -#endif fndecl = get_callee_fndecl (exp); fn = build_call_nofold_loc (EXPR_LOCATION (exp), fndecl, 2, arg1, arg2); gcc_assert (TREE_CODE (fn) == CALL_EXPR); CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp); return expand_call (fn, target, target == const0_rtx); } -#endif return NULL_RTX; } @@ -4174,12 +4164,12 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target, /* If c_strlen can determine an expression for one of the string lengths, and it doesn't have side effects, then emit cmpstrnsi using length MIN(strlen(string)+1, arg3). */ -#ifdef HAVE_cmpstrnsi - if (HAVE_cmpstrnsi) + insn_code cmpstrn_icode = direct_optab_handler (cmpstrn_optab, SImode); + if (cmpstrn_icode != CODE_FOR_nothing) { tree len, len1, len2; rtx arg1_rtx, arg2_rtx, arg3_rtx; - rtx result, insn; + rtx result; tree fndecl, fn; tree arg1 = CALL_EXPR_ARG (exp, 0); tree arg2 = CALL_EXPR_ARG (exp, 1); @@ -4187,8 +4177,6 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target, unsigned int arg1_align = get_pointer_alignment (arg1) / BITS_PER_UNIT; unsigned int arg2_align = get_pointer_alignment (arg2) / BITS_PER_UNIT; - machine_mode insn_mode - = insn_data[(int) CODE_FOR_cmpstrnsi].operand[0].mode; len1 = c_strlen (arg1, 1); len2 = c_strlen (arg2, 1); @@ -4234,13 +4222,6 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target, if (arg1_align == 0 || arg2_align == 0) return NULL_RTX; - /* Make a place to write the result of the instruction. */ - result = target; - if (! (result != 0 - && REG_P (result) && GET_MODE (result) == insn_mode - && REGNO (result) >= FIRST_PSEUDO_REGISTER)) - result = gen_reg_rtx (insn_mode); - /* Stabilize the arguments in case gen_cmpstrnsi fails. */ arg1 = builtin_save_expr (arg1); arg2 = builtin_save_expr (arg2); @@ -4249,12 +4230,11 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target, arg1_rtx = get_memory_rtx (arg1, len); arg2_rtx = get_memory_rtx (arg2, len); arg3_rtx = expand_normal (len); - insn = gen_cmpstrnsi (result, arg1_rtx, arg2_rtx, arg3_rtx, - GEN_INT (MIN (arg1_align, arg2_align))); - if (insn) + result = expand_cmpstrn_or_cmpmem (cmpstrn_icode, target, arg1_rtx, + arg2_rtx, TREE_TYPE (len), arg3_rtx, + MIN (arg1_align, arg2_align)); + if (result) { - emit_insn (insn); - /* Return the value in the proper mode for this function. */ mode = TYPE_MODE (TREE_TYPE (exp)); if (GET_MODE (result) == mode) @@ -4274,7 +4254,6 @@ expand_builtin_strncmp (tree exp, ATTRIBUTE_UNUSED rtx target, CALL_EXPR_TAILCALL (fn) = CALL_EXPR_TAILCALL (exp); return expand_call (fn, target, target == const0_rtx); } -#endif return NULL_RTX; } @@ -6348,7 +6327,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode, case BUILT_IN_BCMP: case BUILT_IN_MEMCMP: - target = expand_builtin_memcmp (exp, target, mode); + target = expand_builtin_memcmp (exp, target); if (target) return target; break; diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 7a25c399e22..8b4009e85fd 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,18 @@ +2015-08-25 Marek Polacek <polacek@redhat.com> + + PR middle-end/67330 + * c-common.c (handle_weak_attribute): Don't check whether the + visibility can be changed here. + +2015-08-22 Manuel López-Ibáñez <manu@gcc.gnu.org> + + * c-lex.c (c_lex_with_flags): Use explicit locations. + +2015-08-18 Trevor Saunders <tbsaunde@tbsaunde.org> + + * c-ada-spec.h, c-common.c, c-common.h, c-format.c, c-format.h, + c-objc.h, c-ppoutput.c, c-pragma.c, c-pragma.h: Remove useless + 2015-08-18 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> PR middle-end/36757 diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index f081dadd6b6..adfd1e6c301 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -8328,12 +8328,7 @@ handle_weak_attribute (tree *node, tree name, return NULL_TREE; } else if (VAR_OR_FUNCTION_DECL_P (*node)) - { - struct symtab_node *n = symtab_node::get (*node); - if (n && n->refuse_visibility_changes) - error ("%+D declared weak after being used", *node); - declare_weak (*node); - } + declare_weak (*node); else warning (OPT_Wattributes, "%qE attribute ignored", name); diff --git a/gcc/c-family/c-lex.c b/gcc/c-family/c-lex.c index e9937163609..55ceb20a01f 100644 --- a/gcc/c-family/c-lex.c +++ b/gcc/c-family/c-lex.c @@ -523,11 +523,11 @@ c_lex_with_flags (tree *value, location_t *loc, unsigned char *cpp_flags, cppchar_t c = tok->val.str.text[0]; if (c == '"' || c == '\'') - error ("missing terminating %c character", (int) c); + error_at (*loc, "missing terminating %c character", (int) c); else if (ISGRAPH (c)) - error ("stray %qc in program", (int) c); + error_at (*loc, "stray %qc in program", (int) c); else - error ("stray %<\\%o%> in program", (int) c); + error_at (*loc, "stray %<\\%o%> in program", (int) c); } goto retry; diff --git a/gcc/calls.c b/gcc/calls.c index 563672512be..026cb53eed9 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -291,7 +291,7 @@ emit_call_1 (rtx funexp, tree fntree ATTRIBUTE_UNUSED, tree fndecl ATTRIBUTE_UNU cumulative_args_t args_so_far ATTRIBUTE_UNUSED) { rtx rounded_stack_size_rtx = GEN_INT (rounded_stack_size); - rtx call, funmem; + rtx call, funmem, pat; int already_popped = 0; HOST_WIDE_INT n_popped = targetm.calls.return_pops_args (fndecl, funtype, stack_size); @@ -330,90 +330,50 @@ emit_call_1 (rtx funexp, tree fntree ATTRIBUTE_UNUSED, tree fndecl ATTRIBUTE_UNU else if (fntree) set_mem_expr (funmem, build_simple_mem_ref (CALL_EXPR_FN (fntree))); -#if defined (HAVE_sibcall_pop) && defined (HAVE_sibcall_value_pop) - if ((ecf_flags & ECF_SIBCALL) - && HAVE_sibcall_pop && HAVE_sibcall_value_pop - && (n_popped > 0 || stack_size == 0)) + if (ecf_flags & ECF_SIBCALL) { - rtx n_pop = GEN_INT (n_popped); - rtx pat; - - /* If this subroutine pops its own args, record that in the call insn - if possible, for the sake of frame pointer elimination. */ - if (valreg) - pat = GEN_SIBCALL_VALUE_POP (valreg, funmem, rounded_stack_size_rtx, - next_arg_reg, n_pop); + pat = targetm.gen_sibcall_value (valreg, funmem, + rounded_stack_size_rtx, + next_arg_reg, NULL_RTX); else - pat = GEN_SIBCALL_POP (funmem, rounded_stack_size_rtx, next_arg_reg, - n_pop); - - emit_call_insn (pat); - already_popped = 1; + pat = targetm.gen_sibcall (funmem, rounded_stack_size_rtx, + next_arg_reg, GEN_INT (struct_value_size)); } - else -#endif - -#if defined (HAVE_call_pop) && defined (HAVE_call_value_pop) /* If the target has "call" or "call_value" insns, then prefer them if no arguments are actually popped. If the target does not have "call" or "call_value" insns, then we must use the popping versions even if the call has no arguments to pop. */ -#if defined (HAVE_call) && defined (HAVE_call_value) - if (HAVE_call && HAVE_call_value && HAVE_call_pop && HAVE_call_value_pop - && n_popped > 0) -#else - if (HAVE_call_pop && HAVE_call_value_pop) -#endif + else if (n_popped > 0 + || !(valreg + ? targetm.have_call_value () + : targetm.have_call ())) { rtx n_pop = GEN_INT (n_popped); - rtx pat; /* If this subroutine pops its own args, record that in the call insn if possible, for the sake of frame pointer elimination. */ if (valreg) - pat = GEN_CALL_VALUE_POP (valreg, funmem, rounded_stack_size_rtx, - next_arg_reg, n_pop); + pat = targetm.gen_call_value_pop (valreg, funmem, + rounded_stack_size_rtx, + next_arg_reg, n_pop); else - pat = GEN_CALL_POP (funmem, rounded_stack_size_rtx, next_arg_reg, - n_pop); + pat = targetm.gen_call_pop (funmem, rounded_stack_size_rtx, + next_arg_reg, n_pop); - emit_call_insn (pat); already_popped = 1; } else -#endif - -#if defined (HAVE_sibcall) && defined (HAVE_sibcall_value) - if ((ecf_flags & ECF_SIBCALL) - && HAVE_sibcall && HAVE_sibcall_value) - { - if (valreg) - emit_call_insn (GEN_SIBCALL_VALUE (valreg, funmem, - rounded_stack_size_rtx, - next_arg_reg, NULL_RTX)); - else - emit_call_insn (GEN_SIBCALL (funmem, rounded_stack_size_rtx, - next_arg_reg, - GEN_INT (struct_value_size))); - } - else -#endif - -#if defined (HAVE_call) && defined (HAVE_call_value) - if (HAVE_call && HAVE_call_value) { if (valreg) - emit_call_insn (GEN_CALL_VALUE (valreg, funmem, rounded_stack_size_rtx, - next_arg_reg, NULL_RTX)); + pat = targetm.gen_call_value (valreg, funmem, rounded_stack_size_rtx, + next_arg_reg, NULL_RTX); else - emit_call_insn (GEN_CALL (funmem, rounded_stack_size_rtx, next_arg_reg, - GEN_INT (struct_value_size))); + pat = targetm.gen_call (funmem, rounded_stack_size_rtx, next_arg_reg, + GEN_INT (struct_value_size)); } - else -#endif - gcc_unreachable (); + emit_insn (pat); /* Find the call we just emitted. */ rtx_call_insn *call_insn = last_call_insn (); diff --git a/gcc/cfganal.c b/gcc/cfganal.c index 7676bd8d6cc..3a9174c60bb 100644 --- a/gcc/cfganal.c +++ b/gcc/cfganal.c @@ -925,7 +925,7 @@ pre_and_rev_post_order_compute_fn (struct function *fn, pre_order[pre_order_num] = ENTRY_BLOCK; pre_order_num++; if (rev_post_order) - rev_post_order[rev_post_order_num--] = ENTRY_BLOCK; + rev_post_order[rev_post_order_num--] = EXIT_BLOCK; } else rev_post_order_num -= NUM_FIXED_BLOCKS; @@ -996,7 +996,7 @@ pre_and_rev_post_order_compute_fn (struct function *fn, pre_order[pre_order_num] = EXIT_BLOCK; pre_order_num++; if (rev_post_order) - rev_post_order[rev_post_order_num--] = EXIT_BLOCK; + rev_post_order[rev_post_order_num--] = ENTRY_BLOCK; } return pre_order_num; diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index 0bc20f6816c..d567a875dff 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -172,17 +172,23 @@ leader_merge (tree cur, tree next) return cur; } -/* Return true if VAR is a PARM_DECL or a RESULT_DECL of type BLKmode. +/* Return true if VAR is a PARM_DECL or a RESULT_DECL that ought to be + assigned to a stack slot. We can't have expand_one_ssa_partition + choose their address: the pseudo holding the address would be set + up too late for assign_params to copy the parameter if needed. + Such parameters are likely passed as a pointer to the value, rather than as a value, and so we must not coalesce them, nor allocate stack space for them before determining the calling conventions for - them. For their SSA_NAMEs, expand_one_ssa_partition emits RTL as - MEMs with pc_rtx as the address, and then it replaces the pc_rtx - with NULL so as to make sure the MEM is not used before it is - adjusted in assign_parm_setup_reg. */ + them. + + For their SSA_NAMEs, expand_one_ssa_partition emits RTL as MEMs + with pc_rtx as the address, and then it replaces the pc_rtx with + NULL so as to make sure the MEM is not used before it is adjusted + in assign_parm_setup_reg. */ bool -parm_maybe_byref_p (tree var) +parm_in_stack_slot_p (tree var) { if (!var || VAR_P (var)) return false; @@ -190,7 +196,7 @@ parm_maybe_byref_p (tree var) gcc_assert (TREE_CODE (var) == PARM_DECL || TREE_CODE (var) == RESULT_DECL); - return TYPE_MODE (TREE_TYPE (var)) == BLKmode; + return !use_register_for_decl (var); } /* Return the partition of the default SSA_DEF for decl VAR. */ @@ -1343,17 +1349,35 @@ expand_one_ssa_partition (tree var) if (!use_register_for_decl (var)) { - if (parm_maybe_byref_p (SSA_NAME_VAR (var)) - && ssa_default_def_partition (SSA_NAME_VAR (var)) == part) + /* We can't risk having the parm assigned to a MEM location + whose address references a pseudo, for the pseudo will only + be set up after arguments are copied to the stack slot. + + If the parm doesn't have a default def (e.g., because its + incoming value is unused), then we want to let assign_params + do the allocation, too. In this case we want to make sure + SSA_NAMEs associated with the parm don't get assigned to more + than one partition, lest we'd create two unassigned stac + slots for the same parm, thus the assert at the end of the + block. */ + if (parm_in_stack_slot_p (SSA_NAME_VAR (var)) + && (ssa_default_def_partition (SSA_NAME_VAR (var)) == part + || !ssa_default_def (cfun, SSA_NAME_VAR (var)))) { expand_one_stack_var_at (var, pc_rtx, 0, 0); rtx x = SA.partition_to_pseudo[part]; gcc_assert (GET_CODE (x) == MEM); - gcc_assert (GET_MODE (x) == BLKmode); gcc_assert (XEXP (x, 0) == pc_rtx); /* Reset the address, so that any attempt to use it will ICE. It will be adjusted in assign_parm_setup_reg. */ XEXP (x, 0) = NULL_RTX; + /* If the RTL associated with the parm is not what we have + just created, the parm has been split over multiple + partitions. In order for this to work, we must have a + default def for the parm, otherwise assign_params won't + know what to do. */ + gcc_assert (DECL_RTL_IF_SET (SSA_NAME_VAR (var)) == x + || ssa_default_def (cfun, SSA_NAME_VAR (var))); } else if (defer_stack_allocation (var, true)) add_stack_var (var); diff --git a/gcc/cfgexpand.h b/gcc/cfgexpand.h index 987cf356a40..d1686724083 100644 --- a/gcc/cfgexpand.h +++ b/gcc/cfgexpand.h @@ -22,7 +22,7 @@ along with GCC; see the file COPYING3. If not see extern tree gimple_assign_rhs_to_tree (gimple); extern HOST_WIDE_INT estimated_stack_frame_size (struct cgraph_node *); -extern bool parm_maybe_byref_p (tree); +extern bool parm_in_stack_slot_p (tree); extern rtx get_rtl_for_parm_ssa_default_def (tree var); diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index a95ce9ee1fc..be16f5d0d04 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -2482,15 +2482,18 @@ symbol_table::finalize_compilation_unit (void) /* Gimplify and lower thunks. */ analyze_functions (/*first_time=*/false); - /* Emit early debug for reachable functions, and by consequence, - locally scoped symbols. */ - struct cgraph_node *cnode; - FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (cnode) - (*debug_hooks->early_global_decl) (cnode->decl); - - /* Clean up anything that needs cleaning up after initial debug - generation. */ - (*debug_hooks->early_finish) (); + if (!seen_error ()) + { + /* Emit early debug for reachable functions, and by consequence, + locally scoped symbols. */ + struct cgraph_node *cnode; + FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (cnode) + (*debug_hooks->early_global_decl) (cnode->decl); + + /* Clean up anything that needs cleaning up after initial debug + generation. */ + (*debug_hooks->early_finish) (); + } /* Finally drive the pass manager. */ compile (); diff --git a/gcc/common.opt b/gcc/common.opt index dd59ff337e6..94d1d884833 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -1341,20 +1341,20 @@ Common Report Var(flag_loop_parallelize_all) Optimization Mark all loops as parallel floop-strip-mine -Common Report Var(flag_loop_strip_mine) Optimization -Enable Loop Strip Mining transformation +Common Alias(floop-nest-optimize) +Enable loop nest transforms. Same as -floop-nest-optimize floop-interchange -Common Report Var(flag_loop_interchange) Optimization -Enable Loop Interchange transformation +Common Alias(floop-nest-optimize) +Enable loop nest transforms. Same as -floop-nest-optimize floop-block -Common Report Var(flag_loop_block) Optimization -Enable Loop Blocking transformation +Common Alias(floop-nest-optimize) +Enable loop nest transforms. Same as -floop-nest-optimize floop-unroll-and-jam -Common Report Var(flag_loop_unroll_jam) Optimization -Enable Loop Unroll Jam transformation +Common Alias(floop-nest-optimize) +Enable loop nest transforms. Same as -floop-nest-optimize fgnu-tm Common Report Var(flag_tm) @@ -2124,15 +2124,15 @@ Common RejectNegative Joined Var(common_deferred_options) Defer -fstack-limit-symbol=<name> Trap if the stack goes past symbol <name> fstack-protector -Common Report Var(flag_stack_protect, 1) +Common Report Var(flag_stack_protect, 1) Init(-1) Use propolice as a stack protection method fstack-protector-all -Common Report RejectNegative Var(flag_stack_protect, 2) +Common Report RejectNegative Var(flag_stack_protect, 2) Init(-1) Use a stack protection method for every function fstack-protector-strong -Common Report RejectNegative Var(flag_stack_protect, 3) +Common Report RejectNegative Var(flag_stack_protect, 3) Init(-1) Use a smart stack protection method for certain functions fstack-protector-explicit @@ -2315,8 +2315,8 @@ Common Report Var(flag_tree_loop_im) Init(1) Optimization Enable loop invariant motion on trees ftree-loop-linear -Common Alias(floop-interchange) -Enable loop interchange transforms. Same as -floop-interchange +Common Alias(floop-nest-optimize) +Enable loop nest transforms. Same as -floop-nest-optimize ftree-loop-ivcanon Common Report Var(flag_tree_loop_ivcanon) Init(1) Optimization diff --git a/gcc/common/config/aarch64/aarch64-common.c b/gcc/common/config/aarch64/aarch64-common.c index 726c62531d9..07c6bba4519 100644 --- a/gcc/common/config/aarch64/aarch64-common.c +++ b/gcc/common/config/aarch64/aarch64-common.c @@ -27,7 +27,7 @@ #include "common/common-target-def.h" #include "opts.h" #include "flags.h" -#include "errors.h" +#include "diagnostic.h" #ifdef TARGET_BIG_ENDIAN_DEFAULT #undef TARGET_DEFAULT_TARGET_FLAGS @@ -107,36 +107,134 @@ aarch64_handle_option (struct gcc_options *opts, struct gcc_targetm_common targetm_common = TARGETM_COMMON_INITIALIZER; -#define AARCH64_CPU_NAME_LENGTH 128 +/* An ISA extension in the co-processor and main instruction set space. */ +struct aarch64_option_extension +{ + const char *const name; + const unsigned long flags_on; + const unsigned long flags_off; +}; + +/* ISA extensions in AArch64. */ +static const struct aarch64_option_extension all_extensions[] = +{ +#define AARCH64_OPT_EXTENSION(NAME, FLAGS_ON, FLAGS_OFF, FEATURE_STRING) \ + {NAME, FLAGS_ON, FLAGS_OFF}, +#include "config/aarch64/aarch64-option-extensions.def" +#undef AARCH64_OPT_EXTENSION + {NULL, 0, 0} +}; + +struct processor_name_to_arch +{ + const std::string processor_name; + const enum aarch64_arch arch; + const unsigned long flags; +}; + +struct arch_to_arch_name +{ + const enum aarch64_arch arch; + const std::string arch_name; +}; + +/* Map processor names to the architecture revision they implement and + the default set of architectural feature flags they support. */ +static const struct processor_name_to_arch all_cores[] = +{ +#define AARCH64_CORE(NAME, X, IDENT, ARCH_IDENT, FLAGS, COSTS, IMP, PART) \ + {NAME, AARCH64_ARCH_##ARCH_IDENT, FLAGS}, +#include "config/aarch64/aarch64-cores.def" +#undef AARCH64_CORE + {"generic", AARCH64_ARCH_8A, AARCH64_FL_FOR_ARCH8}, + {"", aarch64_no_arch, 0} +}; + +/* Map architecture revisions to their string representation. */ +static const struct arch_to_arch_name all_architectures[] = +{ +#define AARCH64_ARCH(NAME, CORE, ARCH_IDENT, ARCH, FLAGS) \ + {AARCH64_ARCH_##ARCH_IDENT, NAME}, +#include "config/aarch64/aarch64-arches.def" +#undef AARCH64_ARCH + {aarch64_no_arch, ""} +}; + +/* Return a string representation of ISA_FLAGS. */ + +std::string +aarch64_get_extension_string_for_isa_flags (unsigned long isa_flags) +{ + const struct aarch64_option_extension *opt = NULL; + std::string outstr = ""; + + for (opt = all_extensions; opt->name != NULL; opt++) + if ((isa_flags & opt->flags_on) == opt->flags_on) + { + outstr += "+"; + outstr += opt->name; + } + return outstr; +} -/* Truncate NAME at the first '.' character seen up to the first '+' - or return NAME unmodified. */ +/* Attempt to rewrite NAME, which has been passed on the command line + as a -mcpu option to an equivalent -march value. If we can do so, + return the new string, otherwise return an error. */ const char * aarch64_rewrite_selected_cpu (const char *name) { - static char output_buf[AARCH64_CPU_NAME_LENGTH + 1] = {0}; - const char *bL_sep; - const char *feats; - size_t pref_size; - size_t feat_size; - - bL_sep = strchr (name, '.'); - if (!bL_sep) - return name; + std::string original_string (name); + std::string extensions; + std::string processor; + size_t extension_pos = original_string.find_first_of ('+'); - feats = strchr (name, '+'); - feat_size = feats ? strnlen (feats, AARCH64_CPU_NAME_LENGTH) : 0; - pref_size = bL_sep - name; + /* Strip and save the extension string. */ + if (extension_pos != std::string::npos) + { + processor = original_string.substr (0, extension_pos); + extensions = original_string.substr (extension_pos, + std::string::npos); + } + else + { + /* No extensions. */ + processor = original_string; + } - if ((feat_size + pref_size) > AARCH64_CPU_NAME_LENGTH) - internal_error ("-mcpu string too large"); + const struct processor_name_to_arch* p_to_a; + for (p_to_a = all_cores; + p_to_a->arch != aarch64_no_arch; + p_to_a++) + { + if (p_to_a->processor_name == processor) + break; + } - strncpy (output_buf, name, pref_size); - if (feats) - strncpy (output_buf + pref_size, feats, feat_size); + const struct arch_to_arch_name* a_to_an; + for (a_to_an = all_architectures; + a_to_an->arch != aarch64_no_arch; + a_to_an++) + { + if (a_to_an->arch == p_to_a->arch) + break; + } - return output_buf; + /* We couldn't find that proceesor name, or the processor name we + found does not map to an architecture we understand. */ + if (p_to_a->arch == aarch64_no_arch + || a_to_an->arch == aarch64_no_arch) + fatal_error (input_location, "unknown value %qs for -mcpu", name); + + std::string outstr = a_to_an->arch_name + + aarch64_get_extension_string_for_isa_flags (p_to_a->flags) + + extensions; + + /* We are going to memory leak here, nobody elsewhere + in the callchain is going to clean up after us. The alternative is + to allocate a static buffer, and assert that it is big enough for our + modified string, which seems much worse! */ + return xstrdup (outstr.c_str ()); } /* Called by the driver to rewrite a name passed to the -mcpu diff --git a/gcc/config.build b/gcc/config.build index 6ea7484f2ff..b59d0ea7fd5 100644 --- a/gcc/config.build +++ b/gcc/config.build @@ -56,10 +56,6 @@ case $build in hppa2*-*-hpux11* ) build_install_headers_dir=install-headers-cpio ;; - i370-*-opened* | i370-*-mvs* ) - # IBM 360/370/390 Architecture - build_xm_defines='FATAL_EXIT_CODE=12' - ;; i[34567]86-*-cygwin* | x86_64-*-cygwin* ) build_xm_file=i386/xm-cygwin.h build_exeext=.exe @@ -77,31 +73,6 @@ case $build in build_xm_file=i386/xm-djgpp.h build_exeext=.exe ;; - i[34567]86-*-sco3.2v5*) - # 80386 running SCO Open Server 5 - build_install_headers_dir=install-headers-cpio - ;; - i[34567]86-sequent-ptx4* | i[34567]86-sequent-sysv4* ) - build_install_headers_dir=install-headers-cpio - ;; - i[34567]86-*-sysv4*) - # Intel x86 running system V r4 - build_install_headers_dir=install-headers-cpio - ;; - i[34567]86-*-udk*) - # Intel x86 on SCO UW/OSR5 Dev Kit - build_install_headers_dir=install-headers-cpio - ;; - i[34567]86-*-uwin*) - build_exeext=.exe - ;; - i386-*-vsta) - # Intel 80386's running VSTa kernel - ;; - m68000-hp-hpux* | m68k-hp-hpux*) - # HP 9000 series 300 - build_install_headers_dir=install-headers-cpio - ;; *-*-sysv*) # All other System V variants. build_install_headers_dir=install-headers-cpio diff --git a/gcc/config.gcc b/gcc/config.gcc index 24f6d35d5cb..5712547ed10 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -835,6 +835,12 @@ case ${target} in sol2_tm_file_head="dbxelf.h elfos.h ${cpu_type}/sysv4.h" sol2_tm_file_tail="${cpu_type}/sol2.h sol2.h" sol2_tm_file="${sol2_tm_file_head} ${sol2_tm_file_tail}" + case ${target} in + *-*-solaris2.1[2-9]*) + # __cxa_atexit was introduced in Solaris 12. + default_use_cxa_atexit=yes + ;; + esac use_gcc_stdint=wrap if test x$gnu_ld = xyes; then tm_file="usegld.h ${tm_file}" @@ -4194,7 +4200,7 @@ case "${target}" in esac ;; - sh[123456ble]-*-* | sh-*-*) + sh[123456ble]*-*-* | sh-*-*) supported_defaults="cpu" case "`echo $with_cpu | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ_ abcdefghijklmnopqrstuvwxyz- | sed s/sh/m/`" in "" | m1 | m2 | m2e | m3 | m3e | m4 | m4-single | m4-single-only | m4-nofpu ) diff --git a/gcc/config.host b/gcc/config.host index 3f7d5947f7c..8b7e16dd06b 100644 --- a/gcc/config.host +++ b/gcc/config.host @@ -213,9 +213,6 @@ case ${host} in out_host_hook_obj=host-hpux.o host_xmake_file="${host_xmake_file} x-hpux" ;; - i370-*-opened* | i370-*-mvs* ) # IBM 360/370/390 Architecture - host_xm_defines='FATAL_EXIT_CODE=12' - ;; i[34567]86-*-solaris2* | x86_64-*-solaris2.1[0-9]*) out_host_hook_obj=host-solaris.o host_xmake_file="${host_xmake_file} x-solaris" @@ -252,18 +249,10 @@ case ${host} in out_host_hook_obj=host-mingw32.o host_lto_plugin_soname=liblto_plugin-0.dll ;; - i[34567]86-*-uwin*) - echo "*** UWIN may not be used as a host platform because" - echo "*** linking with posix.dll is not allowed by the GNU GPL." - exit 1 - ;; i[34567]86-*-darwin* | x86_64-*-darwin*) out_host_hook_obj="${out_host_hook_obj} host-i386-darwin.o" host_xmake_file="${host_xmake_file} i386/x-darwin" ;; - powerpc-*-beos*) - host_can_use_collect2=no - ;; powerpc-*-darwin*) out_host_hook_obj="${out_host_hook_obj} host-ppc-darwin.o" host_xmake_file="${host_xmake_file} rs6000/x-darwin" diff --git a/gcc/config.in b/gcc/config.in index 541963a727a..22a4e6b7cb2 100644 --- a/gcc/config.in +++ b/gcc/config.in @@ -95,6 +95,13 @@ #endif +/* Define if your target supports default stack protector and it is enabled. + */ +#ifndef USED_FOR_TARGET +#undef ENABLE_DEFAULT_SSP +#endif + + /* Define if you want more run-time sanity checks for dataflow. */ #ifndef USED_FOR_TARGET #undef ENABLE_DF_CHECKING diff --git a/gcc/config/aarch64/aarch64-builtins.c b/gcc/config/aarch64/aarch64-builtins.c index 0f4f2b97022..e3a90b5e4dd 100644 --- a/gcc/config/aarch64/aarch64-builtins.c +++ b/gcc/config/aarch64/aarch64-builtins.c @@ -886,30 +886,6 @@ typedef enum SIMD_ARG_STOP } builtin_simd_arg; -/* Relayout the decl of a function arg. Keep the RTL component the same, - as varasm.c ICEs. It doesn't like reinitializing the RTL - on PARM decls. Something like this needs to be done when compiling a - file without SIMD and then tagging a function with +simd and using SIMD - intrinsics in there. The types will have been laid out assuming no SIMD, - so we want to re-lay them out. */ - -static void -aarch64_relayout_simd_param (tree arg) -{ - tree argdecl = arg; - if (TREE_CODE (argdecl) == SSA_NAME) - argdecl = SSA_NAME_VAR (argdecl); - - if (argdecl - && (TREE_CODE (argdecl) == PARM_DECL - || TREE_CODE (argdecl) == VAR_DECL)) - { - rtx rtl = NULL_RTX; - rtl = DECL_RTL_IF_SET (argdecl); - relayout_decl (argdecl); - SET_DECL_RTL (argdecl, rtl); - } -} static rtx aarch64_simd_expand_args (rtx target, int icode, int have_retval, @@ -940,7 +916,6 @@ aarch64_simd_expand_args (rtx target, int icode, int have_retval, { tree arg = CALL_EXPR_ARG (exp, opc - have_retval); enum machine_mode mode = insn_data[icode].operand[opc].mode; - aarch64_relayout_simd_param (arg); op[opc] = expand_normal (arg); switch (thisarg) diff --git a/gcc/config/aarch64/aarch64-fusion-pairs.def b/gcc/config/aarch64/aarch64-fusion-pairs.def index a7b00f6975d..53bbef46eb2 100644 --- a/gcc/config/aarch64/aarch64-fusion-pairs.def +++ b/gcc/config/aarch64/aarch64-fusion-pairs.def @@ -20,19 +20,17 @@ /* Pairs of instructions which can be fused. before including this file, define a macro: - AARCH64_FUSION_PAIR (name, internal_name, index_bit) + AARCH64_FUSION_PAIR (name, internal_name) Where: NAME is a string giving a friendly name for the instructions to fuse. INTERNAL_NAME gives the internal name suitable for appending to - AARCH64_FUSE_ to give an enum name. - INDEX_BIT is the bit to set in the bitmask of supported fusion - operations. */ - -AARCH64_FUSION_PAIR ("mov+movk", MOV_MOVK, 0) -AARCH64_FUSION_PAIR ("adrp+add", ADRP_ADD, 1) -AARCH64_FUSION_PAIR ("movk+movk", MOVK_MOVK, 2) -AARCH64_FUSION_PAIR ("adrp+ldr", ADRP_LDR, 3) -AARCH64_FUSION_PAIR ("cmp+branch", CMP_BRANCH, 4) + AARCH64_FUSE_ to give an enum name. */ + +AARCH64_FUSION_PAIR ("mov+movk", MOV_MOVK) +AARCH64_FUSION_PAIR ("adrp+add", ADRP_ADD) +AARCH64_FUSION_PAIR ("movk+movk", MOVK_MOVK) +AARCH64_FUSION_PAIR ("adrp+ldr", ADRP_LDR) +AARCH64_FUSION_PAIR ("cmp+branch", CMP_BRANCH) diff --git a/gcc/config/aarch64/aarch64-option-extensions.def b/gcc/config/aarch64/aarch64-option-extensions.def index 1762cc8d58f..b261a0f7c3c 100644 --- a/gcc/config/aarch64/aarch64-option-extensions.def +++ b/gcc/config/aarch64/aarch64-option-extensions.def @@ -34,11 +34,6 @@ should contain a whitespace-separated list of the strings in 'Features' that are required. Their order is not important. */ -/* V8 Architecture Extensions. - This list currently contains example extensions for CPUs that implement - AArch64, and therefore serves as a template for adding more CPUs in the - future. */ - AARCH64_OPT_EXTENSION("fp", AARCH64_FL_FP, AARCH64_FL_FPSIMD | AARCH64_FL_CRYPTO | AARCH64_FL_RDMA, "fp") AARCH64_OPT_EXTENSION("simd", AARCH64_FL_FPSIMD, AARCH64_FL_SIMD | AARCH64_FL_CRYPTO | AARCH64_FL_RDMA, "asimd") AARCH64_OPT_EXTENSION("crypto", AARCH64_FL_CRYPTO | AARCH64_FL_FPSIMD, AARCH64_FL_CRYPTO, "aes pmull sha1 sha2") diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h index 0b09d49f670..ff1985137b3 100644 --- a/gcc/config/aarch64/aarch64-protos.h +++ b/gcc/config/aarch64/aarch64-protos.h @@ -73,8 +73,12 @@ enum aarch64_symbol_context SYMBOL_SMALL_TLSGD SYMBOL_SMALL_TLSDESC - SYMBOL_SMALL_GOTTPREL - SYMBOL_TLSLE + SYMBOL_SMALL_TLSIE + SYMBOL_TINY_TLSIE + SYMBOL_TLSLE12 + SYMBOL_TLSLE24 + SYMBOL_TLSLE32 + SYMBOL_TLSLE48 Each of these represents a thread-local symbol, and corresponds to the thread local storage relocation operator for the symbol being referred to. @@ -108,10 +112,14 @@ enum aarch64_symbol_type SYMBOL_SMALL_GOT_4G, SYMBOL_SMALL_TLSGD, SYMBOL_SMALL_TLSDESC, - SYMBOL_SMALL_GOTTPREL, + SYMBOL_SMALL_TLSIE, SYMBOL_TINY_ABSOLUTE, SYMBOL_TINY_GOT, - SYMBOL_TLSLE, + SYMBOL_TINY_TLSIE, + SYMBOL_TLSLE12, + SYMBOL_TLSLE24, + SYMBOL_TLSLE32, + SYMBOL_TLSLE48, SYMBOL_FORCE_TO_MEM }; @@ -201,41 +209,46 @@ struct tune_params unsigned int extra_tuning_flags; }; -#define AARCH64_FUSION_PAIR(x, name, index) \ - AARCH64_FUSE_##name = (1 << index), +#define AARCH64_FUSION_PAIR(x, name) \ + AARCH64_FUSE_##name##_index, /* Supported fusion operations. */ -enum aarch64_fusion_pairs +enum aarch64_fusion_pairs_index { - AARCH64_FUSE_NOTHING = 0, #include "aarch64-fusion-pairs.def" - -/* Hacky macro to build AARCH64_FUSE_ALL. The sequence below expands - to: - AARCH64_FUSE_ALL = 0 | AARCH64_FUSE_index1 | AARCH64_FUSE_index2 ... */ + AARCH64_FUSE_index_END +}; #undef AARCH64_FUSION_PAIR -#define AARCH64_FUSION_PAIR(x, name, y) \ - | AARCH64_FUSE_##name - AARCH64_FUSE_ALL = 0 +#define AARCH64_FUSION_PAIR(x, name) \ + AARCH64_FUSE_##name = (1u << AARCH64_FUSE_##name##_index), +/* Supported fusion operations. */ +enum aarch64_fusion_pairs +{ + AARCH64_FUSE_NOTHING = 0, #include "aarch64-fusion-pairs.def" + AARCH64_FUSE_ALL = (1u << AARCH64_FUSE_index_END) - 1 }; #undef AARCH64_FUSION_PAIR -#define AARCH64_EXTRA_TUNING_OPTION(x, name, index) \ - AARCH64_EXTRA_TUNE_##name = (1 << index), +#define AARCH64_EXTRA_TUNING_OPTION(x, name) \ + AARCH64_EXTRA_TUNE_##name##_index, +/* Supported tuning flags indexes. */ +enum aarch64_extra_tuning_flags_index +{ +#include "aarch64-tuning-flags.def" + AARCH64_EXTRA_TUNE_index_END +}; +#undef AARCH64_EXTRA_TUNING_OPTION + + +#define AARCH64_EXTRA_TUNING_OPTION(x, name) \ + AARCH64_EXTRA_TUNE_##name = (1u << AARCH64_EXTRA_TUNE_##name##_index), /* Supported tuning flags. */ enum aarch64_extra_tuning_flags { AARCH64_EXTRA_TUNE_NONE = 0, #include "aarch64-tuning-flags.def" - -/* Hacky macro to build the "all" flag mask. - Expands to 0 | AARCH64_TUNE_index0 | AARCH64_TUNE_index1 , etc. */ -#undef AARCH64_EXTRA_TUNING_OPTION -#define AARCH64_EXTRA_TUNING_OPTION(x, name, y) \ - | AARCH64_EXTRA_TUNE_##name - AARCH64_EXTRA_TUNE_ALL = 0 -#include "aarch64-tuning-flags.def" + AARCH64_EXTRA_TUNE_ALL = (1u << AARCH64_EXTRA_TUNE_index_END) - 1 }; #undef AARCH64_EXTRA_TUNING_OPTION @@ -310,12 +323,14 @@ rtx aarch64_simd_gen_const_vector_dup (machine_mode, int); bool aarch64_simd_mem_operand_p (rtx); rtx aarch64_simd_vect_par_cnst_half (machine_mode, bool); rtx aarch64_tls_get_addr (void); +std::string aarch64_get_extension_string_for_isa_flags (unsigned long); tree aarch64_fold_builtin (tree, int, tree *, bool); unsigned aarch64_dbx_register_number (unsigned); unsigned aarch64_trampoline_size (void); void aarch64_asm_output_labelref (FILE *, const char *); void aarch64_cpu_cpp_builtins (cpp_reader *); void aarch64_elf_asm_named_section (const char *, unsigned, tree); +const char * aarch64_gen_far_branch (rtx *, int, const char *, const char *); void aarch64_err_no_fpadvsimd (machine_mode, const char *); void aarch64_expand_epilogue (bool); void aarch64_expand_mov_immediate (rtx, rtx); diff --git a/gcc/config/aarch64/aarch64-tuning-flags.def b/gcc/config/aarch64/aarch64-tuning-flags.def index 01aaca83594..628386b5a1d 100644 --- a/gcc/config/aarch64/aarch64-tuning-flags.def +++ b/gcc/config/aarch64/aarch64-tuning-flags.def @@ -20,15 +20,13 @@ /* Additional control over certain tuning parameters. Before including this file, define a macro: - AARCH64_EXTRA_TUNING_OPTION (name, internal_name, index_bit) + AARCH64_EXTRA_TUNING_OPTION (name, internal_name) Where: NAME is a string giving a friendly name for the tuning flag. INTERNAL_NAME gives the internal name suitable for appending to - AARCH64_TUNE_ to give an enum name. - INDEX_BIT is the bit to set in the bitmask of supported tuning - flags. */ + AARCH64_TUNE_ to give an enum name. */ -AARCH64_EXTRA_TUNING_OPTION ("rename_fma_regs", RENAME_FMA_REGS, 0) +AARCH64_EXTRA_TUNING_OPTION ("rename_fma_regs", RENAME_FMA_REGS) diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index aa268aeff4d..bc612e47d4f 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -150,7 +150,6 @@ static void aarch64_elf_asm_constructor (rtx, int) ATTRIBUTE_UNUSED; static void aarch64_elf_asm_destructor (rtx, int) ATTRIBUTE_UNUSED; static void aarch64_override_options_after_change (void); static bool aarch64_vector_mode_supported_p (machine_mode); -static unsigned bit_count (unsigned HOST_WIDE_INT); static bool aarch64_vectorize_vec_perm_const_ok (machine_mode vmode, const unsigned char *sel); static int aarch64_address_cost (rtx, machine_mode, addr_space_t, bool); @@ -172,7 +171,7 @@ struct aarch64_flag_desc unsigned int flag; }; -#define AARCH64_FUSION_PAIR(name, internal_name, y) \ +#define AARCH64_FUSION_PAIR(name, internal_name) \ { name, AARCH64_FUSE_##internal_name }, static const struct aarch64_flag_desc aarch64_fusible_pairs[] = { @@ -183,7 +182,7 @@ static const struct aarch64_flag_desc aarch64_fusible_pairs[] = }; #undef AARCH64_FUION_PAIR -#define AARCH64_EXTRA_TUNING_OPTION(name, internal_name, y) \ +#define AARCH64_EXTRA_TUNING_OPTION(name, internal_name) \ { name, AARCH64_EXTRA_TUNE_##internal_name }, static const struct aarch64_flag_desc aarch64_tuning_flags[] = { @@ -587,6 +586,29 @@ static const char * const aarch64_condition_codes[] = "hi", "ls", "ge", "lt", "gt", "le", "al", "nv" }; +/* Generate code to enable conditional branches in functions over 1 MiB. */ +const char * +aarch64_gen_far_branch (rtx * operands, int pos_label, const char * dest, + const char * branch_format) +{ + rtx_code_label * tmp_label = gen_label_rtx (); + char label_buf[256]; + char buffer[128]; + ASM_GENERATE_INTERNAL_LABEL (label_buf, dest, + CODE_LABEL_NUMBER (tmp_label)); + const char *label_ptr = targetm.strip_name_encoding (label_buf); + rtx dest_label = operands[pos_label]; + operands[pos_label] = tmp_label; + + snprintf (buffer, sizeof (buffer), "%s%s", branch_format, label_ptr); + output_asm_insn (buffer, operands); + + snprintf (buffer, sizeof (buffer), "b\t%%l%d\n%s:", pos_label, label_ptr); + operands[pos_label] = dest_label; + output_asm_insn (buffer, operands); + return ""; +} + void aarch64_err_no_fpadvsimd (machine_mode mode, const char *msg) { @@ -931,7 +953,7 @@ aarch64_load_symref_appropriately (rtx dest, rtx imm, The generate instruction sequence for accessing global variable is: - ldr reg, [pic_offset_table_rtx, #:gotpage_lo15:sym] + ldr reg, [pic_offset_table_rtx, #:gotpage_lo15:sym] Only one instruction needed. But we must initialize pic_offset_table_rtx properly. We generate initialize insn for @@ -940,12 +962,12 @@ aarch64_load_symref_appropriately (rtx dest, rtx imm, The final instruction sequences will look like the following for multiply global variables access. - adrp pic_offset_table_rtx, _GLOBAL_OFFSET_TABLE_ + adrp pic_offset_table_rtx, _GLOBAL_OFFSET_TABLE_ - ldr reg, [pic_offset_table_rtx, #:gotpage_lo15:sym1] - ldr reg, [pic_offset_table_rtx, #:gotpage_lo15:sym2] - ldr reg, [pic_offset_table_rtx, #:gotpage_lo15:sym3] - ... */ + ldr reg, [pic_offset_table_rtx, #:gotpage_lo15:sym1] + ldr reg, [pic_offset_table_rtx, #:gotpage_lo15:sym2] + ldr reg, [pic_offset_table_rtx, #:gotpage_lo15:sym3] + ... */ rtx s = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_"); crtl->uses_pic_offset_table = 1; @@ -1081,7 +1103,7 @@ aarch64_load_symref_appropriately (rtx dest, rtx imm, return; } - case SYMBOL_SMALL_GOTTPREL: + case SYMBOL_SMALL_TLSIE: { /* In ILP32, the mode of dest can be either SImode or DImode, while the got entry is always of SImode size. The mode of @@ -1115,14 +1137,43 @@ aarch64_load_symref_appropriately (rtx dest, rtx imm, return; } - case SYMBOL_TLSLE: + case SYMBOL_TLSLE12: + case SYMBOL_TLSLE24: + case SYMBOL_TLSLE32: + case SYMBOL_TLSLE48: { + machine_mode mode = GET_MODE (dest); rtx tp = aarch64_load_tp (NULL); - if (GET_MODE (dest) != Pmode) - tp = gen_lowpart (GET_MODE (dest), tp); + if (mode != Pmode) + tp = gen_lowpart (mode, tp); + + switch (type) + { + case SYMBOL_TLSLE12: + emit_insn ((mode == DImode ? gen_tlsle12_di : gen_tlsle12_si) + (dest, tp, imm)); + break; + case SYMBOL_TLSLE24: + emit_insn ((mode == DImode ? gen_tlsle24_di : gen_tlsle24_si) + (dest, tp, imm)); + break; + case SYMBOL_TLSLE32: + emit_insn ((mode == DImode ? gen_tlsle32_di : gen_tlsle32_si) + (dest, imm)); + emit_insn ((mode == DImode ? gen_adddi3 : gen_addsi3) + (dest, dest, tp)); + break; + case SYMBOL_TLSLE48: + emit_insn ((mode == DImode ? gen_tlsle48_di : gen_tlsle48_si) + (dest, imm)); + emit_insn ((mode == DImode ? gen_adddi3 : gen_addsi3) + (dest, dest, tp)); + break; + default: + gcc_unreachable (); + } - emit_insn (gen_tlsle (dest, tp, imm)); set_unique_reg_note (get_last_insn (), REG_EQUIV, imm); return; } @@ -1131,6 +1182,31 @@ aarch64_load_symref_appropriately (rtx dest, rtx imm, emit_insn (gen_ldr_got_tiny (dest, imm)); return; + case SYMBOL_TINY_TLSIE: + { + machine_mode mode = GET_MODE (dest); + rtx tp = aarch64_load_tp (NULL); + + if (mode == ptr_mode) + { + if (mode == DImode) + emit_insn (gen_tlsie_tiny_di (dest, imm, tp)); + else + { + tp = gen_lowpart (mode, tp); + emit_insn (gen_tlsie_tiny_si (dest, imm, tp)); + } + } + else + { + gcc_assert (mode == Pmode); + emit_insn (gen_tlsie_tiny_sidi (dest, imm, tp)); + } + + set_unique_reg_note (get_last_insn (), REG_EQUIV, imm); + return; + } + default: gcc_unreachable (); } @@ -1661,10 +1737,11 @@ aarch64_expand_mov_immediate (rtx dest, rtx imm) case SYMBOL_SMALL_TLSGD: case SYMBOL_SMALL_TLSDESC: - case SYMBOL_SMALL_GOTTPREL: + case SYMBOL_SMALL_TLSIE: case SYMBOL_SMALL_GOT_28K: case SYMBOL_SMALL_GOT_4G: case SYMBOL_TINY_GOT: + case SYMBOL_TINY_TLSIE: if (offset != const0_rtx) { gcc_assert(can_create_pseudo_p ()); @@ -1677,7 +1754,10 @@ aarch64_expand_mov_immediate (rtx dest, rtx imm) case SYMBOL_SMALL_ABSOLUTE: case SYMBOL_TINY_ABSOLUTE: - case SYMBOL_TLSLE: + case SYMBOL_TLSLE12: + case SYMBOL_TLSLE24: + case SYMBOL_TLSLE32: + case SYMBOL_TLSLE48: aarch64_load_symref_appropriately (dest, imm, sty); return; @@ -4163,19 +4243,6 @@ aarch64_const_vec_all_same_int_p (rtx x, HOST_WIDE_INT val) return aarch64_const_vec_all_same_in_range_p (x, val, val); } -static unsigned -bit_count (unsigned HOST_WIDE_INT value) -{ - unsigned count = 0; - - while (value) - { - count++; - value &= value - 1; - } - - return count; -} /* N Z C V. */ #define AARCH64_CC_V 1 @@ -4330,7 +4397,7 @@ aarch64_print_operand (FILE *f, rtx x, char code) return; } - asm_fprintf (f, "%u", bit_count (INTVAL (x))); + asm_fprintf (f, "%u", popcount_hwi (INTVAL (x))); break; case 'H': @@ -4556,11 +4623,11 @@ aarch64_print_operand (FILE *f, rtx x, char code) asm_fprintf (asm_out_file, ":tlsdesc:"); break; - case SYMBOL_SMALL_GOTTPREL: + case SYMBOL_SMALL_TLSIE: asm_fprintf (asm_out_file, ":gottprel:"); break; - case SYMBOL_TLSLE: + case SYMBOL_TLSLE24: asm_fprintf (asm_out_file, ":tprel:"); break; @@ -4589,11 +4656,15 @@ aarch64_print_operand (FILE *f, rtx x, char code) asm_fprintf (asm_out_file, ":tlsdesc_lo12:"); break; - case SYMBOL_SMALL_GOTTPREL: + case SYMBOL_SMALL_TLSIE: asm_fprintf (asm_out_file, ":gottprel_lo12:"); break; - case SYMBOL_TLSLE: + case SYMBOL_TLSLE12: + asm_fprintf (asm_out_file, ":tprel_lo12:"); + break; + + case SYMBOL_TLSLE24: asm_fprintf (asm_out_file, ":tprel_lo12_nc:"); break; @@ -4601,6 +4672,10 @@ aarch64_print_operand (FILE *f, rtx x, char code) asm_fprintf (asm_out_file, ":got:"); break; + case SYMBOL_TINY_TLSIE: + asm_fprintf (asm_out_file, ":gottprel:"); + break; + default: break; } @@ -4611,7 +4686,7 @@ aarch64_print_operand (FILE *f, rtx x, char code) switch (aarch64_classify_symbolic_expression (x, SYMBOL_CONTEXT_ADR)) { - case SYMBOL_TLSLE: + case SYMBOL_TLSLE24: asm_fprintf (asm_out_file, ":tprel_hi12:"); break; default: @@ -7506,6 +7581,40 @@ aarch64_parse_one_override_token (const char* token, return; } +/* A checking mechanism for the implementation of the tls size. */ + +static void +initialize_aarch64_tls_size (struct gcc_options *opts) +{ + if (aarch64_tls_size == 0) + aarch64_tls_size = 24; + + switch (opts->x_aarch64_cmodel_var) + { + case AARCH64_CMODEL_TINY: + /* Both the default and maximum TLS size allowed under tiny is 1M which + needs two instructions to address, so we clamp the size to 24. */ + if (aarch64_tls_size > 24) + aarch64_tls_size = 24; + break; + case AARCH64_CMODEL_SMALL: + /* The maximum TLS size allowed under small is 4G. */ + if (aarch64_tls_size > 32) + aarch64_tls_size = 32; + break; + case AARCH64_CMODEL_LARGE: + /* The maximum TLS size allowed under large is 16E. + FIXME: 16E should be 64bit, we only support 48bit offset now. */ + if (aarch64_tls_size > 48) + aarch64_tls_size = 48; + break; + default: + gcc_unreachable (); + } + + return; +} + /* Parse STRING looking for options in the format: string :: option:string option :: name=substring @@ -7598,6 +7707,7 @@ aarch64_override_options_internal (struct gcc_options *opts) } initialize_aarch64_code_model (opts); + initialize_aarch64_tls_size (opts); aarch64_override_options_after_change_1 (opts); } @@ -7904,20 +8014,6 @@ initialize_aarch64_code_model (struct gcc_options *opts) aarch64_cmodel = opts->x_aarch64_cmodel_var; } -/* Print to F the architecture features specified by ISA_FLAGS. */ - -static void -aarch64_print_extension (FILE *f, unsigned long isa_flags) -{ - const struct aarch64_option_extension *opt = NULL; - - for (opt = all_extensions; opt->name != NULL; opt++) - if ((isa_flags & opt->flags_on) == opt->flags_on) - asm_fprintf (f, "+%s", opt->name); - - asm_fprintf (f, "\n"); -} - /* Implement TARGET_OPTION_SAVE. */ static void @@ -7950,10 +8046,12 @@ aarch64_option_print (FILE *file, int indent, struct cl_target_option *ptr) = aarch64_get_tune_cpu (ptr->x_explicit_tune_core); unsigned long isa_flags = ptr->x_aarch64_isa_flags; const struct processor *arch = aarch64_get_arch (ptr->x_explicit_arch); + std::string extension + = aarch64_get_extension_string_for_isa_flags (isa_flags); fprintf (file, "%*sselected tune = %s\n", indent, "", cpu->name); - fprintf (file, "%*sselected arch = %s", indent, "", arch->name); - aarch64_print_extension (file, isa_flags); + fprintf (file, "%*sselected arch = %s%s\n", indent, "", + arch->name, extension.c_str ()); } static GTY(()) tree aarch64_previous_fndecl; @@ -8013,6 +8111,23 @@ aarch64_set_current_function (tree fndecl) = save_target_globals_default_opts (); } } + + if (!fndecl) + return; + + /* If we turned on SIMD make sure that any vector parameters are re-laid out + so that they use proper vector modes. */ + if (TARGET_SIMD) + { + tree parms = DECL_ARGUMENTS (fndecl); + for (; parms && parms != void_list_node; parms = TREE_CHAIN (parms)) + { + if (TREE_CODE (parms) == PARM_DECL + && VECTOR_TYPE_P (TREE_TYPE (parms)) + && DECL_MODE (parms) != TYPE_MODE (TREE_TYPE (parms))) + relayout_decl (parms); + } + } } /* Enum describing the various ways we can handle attributes. @@ -8683,10 +8798,26 @@ aarch64_classify_tls_symbol (rtx x) return TARGET_TLS_DESC ? SYMBOL_SMALL_TLSDESC : SYMBOL_SMALL_TLSGD; case TLS_MODEL_INITIAL_EXEC: - return SYMBOL_SMALL_GOTTPREL; + switch (aarch64_cmodel) + { + case AARCH64_CMODEL_TINY: + case AARCH64_CMODEL_TINY_PIC: + return SYMBOL_TINY_TLSIE; + default: + return SYMBOL_SMALL_TLSIE; + } case TLS_MODEL_LOCAL_EXEC: - return SYMBOL_TLSLE; + if (aarch64_tls_size == 12) + return SYMBOL_TLSLE12; + else if (aarch64_tls_size == 24) + return SYMBOL_TLSLE24; + else if (aarch64_tls_size == 32) + return SYMBOL_TLSLE32; + else if (aarch64_tls_size == 48) + return SYMBOL_TLSLE48; + else + gcc_unreachable (); case TLS_MODEL_EMULATED: case TLS_MODEL_NONE: @@ -9893,31 +10024,10 @@ sizetochar (int size) static bool aarch64_vect_float_const_representable_p (rtx x) { - int i = 0; - REAL_VALUE_TYPE r0, ri; - rtx x0, xi; - - if (GET_MODE_CLASS (GET_MODE (x)) != MODE_VECTOR_FLOAT) - return false; - - x0 = CONST_VECTOR_ELT (x, 0); - if (!CONST_DOUBLE_P (x0)) - return false; - - REAL_VALUE_FROM_CONST_DOUBLE (r0, x0); - - for (i = 1; i < CONST_VECTOR_NUNITS (x); i++) - { - xi = CONST_VECTOR_ELT (x, i); - if (!CONST_DOUBLE_P (xi)) - return false; - - REAL_VALUE_FROM_CONST_DOUBLE (ri, xi); - if (!REAL_VALUES_EQUAL (r0, ri)) - return false; - } - - return aarch64_float_const_representable_p (x0); + rtx elt; + return (GET_MODE_CLASS (GET_MODE (x)) == MODE_VECTOR_FLOAT + && const_vec_duplicate_p (x, &elt) + && aarch64_float_const_representable_p (elt)); } /* Return true for valid and false for invalid. */ @@ -10380,28 +10490,15 @@ aarch64_simd_dup_constant (rtx vals) { machine_mode mode = GET_MODE (vals); machine_mode inner_mode = GET_MODE_INNER (mode); - int n_elts = GET_MODE_NUNITS (mode); - bool all_same = true; rtx x; - int i; - - if (GET_CODE (vals) != CONST_VECTOR) - return NULL_RTX; - - for (i = 1; i < n_elts; ++i) - { - x = CONST_VECTOR_ELT (vals, i); - if (!rtx_equal_p (x, CONST_VECTOR_ELT (vals, 0))) - all_same = false; - } - if (!all_same) + if (!const_vec_duplicate_p (vals, &x)) return NULL_RTX; /* We can load this constant by using DUP and a constant in a single ARM register. This will be cheaper than a vector load. */ - x = copy_to_mode_reg (inner_mode, CONST_VECTOR_ELT (vals, 0)); + x = copy_to_mode_reg (inner_mode, x); return gen_rtx_VEC_DUPLICATE (mode, x); } @@ -10677,8 +10774,11 @@ aarch64_declare_function_name (FILE *stream, const char* name, const struct processor *this_arch = aarch64_get_arch (targ_options->x_explicit_arch); - asm_fprintf (asm_out_file, "\t.arch %s", this_arch->name); - aarch64_print_extension (asm_out_file, targ_options->x_aarch64_isa_flags); + unsigned long isa_flags = targ_options->x_aarch64_isa_flags; + std::string extension + = aarch64_get_extension_string_for_isa_flags (isa_flags); + asm_fprintf (asm_out_file, "\t.arch %s%s\n", + this_arch->name, extension.c_str ()); /* Print the cpu name we're tuning for in the comments, might be useful to readers of the generated asm. */ diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h index 1be78fc16dd..1e5f5dbd4fa 100644 --- a/gcc/config/aarch64/aarch64.h +++ b/gcc/config/aarch64/aarch64.h @@ -887,18 +887,18 @@ extern enum aarch64_code_model aarch64_cmodel; {"arch", "%{!march=*:%{!mcpu=*:-march=%(VALUE)}}" }, \ {"cpu", "%{!march=*:%{!mcpu=*:-mcpu=%(VALUE)}}" }, -#define BIG_LITTLE_SPEC \ - " %{mcpu=*:-mcpu=%:rewrite_mcpu(%{mcpu=*:%*})}" +#define MCPU_TO_MARCH_SPEC \ + " %{mcpu=*:-march=%:rewrite_mcpu(%{mcpu=*:%*})}" extern const char *aarch64_rewrite_mcpu (int argc, const char **argv); -#define BIG_LITTLE_CPU_SPEC_FUNCTIONS \ +#define MCPU_TO_MARCH_SPEC_FUNCTIONS \ { "rewrite_mcpu", aarch64_rewrite_mcpu }, #if defined(__aarch64__) extern const char *host_detect_local_cpu (int argc, const char **argv); # define EXTRA_SPEC_FUNCTIONS \ { "local_cpu_detect", host_detect_local_cpu }, \ - BIG_LITTLE_CPU_SPEC_FUNCTIONS + MCPU_TO_MARCH_SPEC_FUNCTIONS # define MCPU_MTUNE_NATIVE_SPECS \ " %{march=native:%<march=native %:local_cpu_detect(arch)}" \ @@ -906,11 +906,11 @@ extern const char *host_detect_local_cpu (int argc, const char **argv); " %{mtune=native:%<mtune=native %:local_cpu_detect(tune)}" #else # define MCPU_MTUNE_NATIVE_SPECS "" -# define EXTRA_SPEC_FUNCTIONS BIG_LITTLE_CPU_SPEC_FUNCTIONS +# define EXTRA_SPEC_FUNCTIONS MCPU_TO_MARCH_SPEC_FUNCTIONS #endif #define ASM_CPU_SPEC \ - BIG_LITTLE_SPEC + MCPU_TO_MARCH_SPEC #define EXTRA_SPECS \ { "asm_cpu_spec", ASM_CPU_SPEC } diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index 35255e91a95..25229824fb5 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -90,6 +90,7 @@ UNSPEC_GOTSMALLPIC28K UNSPEC_GOTSMALLTLS UNSPEC_GOTTINYPIC + UNSPEC_GOTTINYTLS UNSPEC_LD1 UNSPEC_LD2 UNSPEC_LD2_DUP @@ -117,7 +118,10 @@ UNSPEC_ST4_LANE UNSPEC_TLS UNSPEC_TLSDESC - UNSPEC_TLSLE + UNSPEC_TLSLE12 + UNSPEC_TLSLE24 + UNSPEC_TLSLE32 + UNSPEC_TLSLE48 UNSPEC_USHL_2S UNSPEC_VSTRUCTDUMMY UNSPEC_SP_SET @@ -181,6 +185,13 @@ (const_string "no") ] (const_string "yes"))) +;; Attribute that specifies whether we are dealing with a branch to a +;; label that is far away, i.e. further away than the maximum/minimum +;; representable in a signed 21-bits number. +;; 0 :=: no +;; 1 :=: yes +(define_attr "far_branch" "" (const_int 0)) + ;; ------------------------------------------------------------------- ;; Pipeline descriptions and scheduling ;; ------------------------------------------------------------------- @@ -308,8 +319,23 @@ (label_ref (match_operand 2 "" "")) (pc)))] "" - "b%m0\\t%l2" - [(set_attr "type" "branch")] + { + if (get_attr_length (insn) == 8) + return aarch64_gen_far_branch (operands, 2, "Lbcond", "b%M0\\t"); + else + return "b%m0\\t%l2"; + } + [(set_attr "type" "branch") + (set (attr "length") + (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576)) + (lt (minus (match_dup 2) (pc)) (const_int 1048572))) + (const_int 4) + (const_int 8))) + (set (attr "far_branch") + (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576)) + (lt (minus (match_dup 2) (pc)) (const_int 1048572))) + (const_int 0) + (const_int 1)))] ) (define_expand "casesi" @@ -488,9 +514,23 @@ (label_ref (match_operand 1 "" "")) (pc)))] "" - "<cbz>\\t%<w>0, %l1" - [(set_attr "type" "branch")] - + { + if (get_attr_length (insn) == 8) + return aarch64_gen_far_branch (operands, 1, "Lcb", "<inv_cb>\\t%<w>0, "); + else + return "<cbz>\\t%<w>0, %l1"; + } + [(set_attr "type" "branch") + (set (attr "length") + (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576)) + (lt (minus (match_dup 1) (pc)) (const_int 1048572))) + (const_int 4) + (const_int 8))) + (set (attr "far_branch") + (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576)) + (lt (minus (match_dup 2) (pc)) (const_int 1048572))) + (const_int 0) + (const_int 1)))] ) (define_insn "*tb<optab><mode>1" @@ -506,8 +546,14 @@ { if (get_attr_length (insn) == 8) { - operands[1] = GEN_INT (HOST_WIDE_INT_1U << UINTVAL (operands[1])); - return "tst\t%<w>0, %1\;<bcond>\t%l2"; + if (get_attr_far_branch (insn) == 1) + return aarch64_gen_far_branch (operands, 2, "Ltb", + "<inv_tb>\\t%<w>0, %1, "); + else + { + operands[1] = GEN_INT (HOST_WIDE_INT_1U << UINTVAL (operands[1])); + return "tst\t%<w>0, %1\;<bcond>\t%l2"; + } } else return "<tbz>\t%<w>0, %1, %l2"; @@ -517,7 +563,13 @@ (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -32768)) (lt (minus (match_dup 2) (pc)) (const_int 32764))) (const_int 4) - (const_int 8)))] + (const_int 8))) + (set (attr "far_branch") + (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -1048576)) + (lt (minus (match_dup 2) (pc)) (const_int 1048572))) + (const_int 0) + (const_int 1)))] + ) (define_insn "*cb<optab><mode>1" @@ -530,12 +582,18 @@ { if (get_attr_length (insn) == 8) { - char buf[64]; - uint64_t val = ((uint64_t ) 1) - << (GET_MODE_SIZE (<MODE>mode) * BITS_PER_UNIT - 1); - sprintf (buf, "tst\t%%<w>0, %" PRId64, val); - output_asm_insn (buf, operands); - return "<bcond>\t%l1"; + if (get_attr_far_branch (insn) == 1) + return aarch64_gen_far_branch (operands, 1, "Ltb", + "<inv_tb>\\t%<w>0, <sizem1>, "); + else + { + char buf[64]; + uint64_t val = ((uint64_t) 1) + << (GET_MODE_SIZE (<MODE>mode) * BITS_PER_UNIT - 1); + sprintf (buf, "tst\t%%<w>0, %" PRId64, val); + output_asm_insn (buf, operands); + return "<bcond>\t%l1"; + } } else return "<tbz>\t%<w>0, <sizem1>, %l1"; @@ -545,7 +603,12 @@ (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -32768)) (lt (minus (match_dup 1) (pc)) (const_int 32764))) (const_int 4) - (const_int 8)))] + (const_int 8))) + (set (attr "far_branch") + (if_then_else (and (ge (minus (match_dup 1) (pc)) (const_int -1048576)) + (lt (minus (match_dup 1) (pc)) (const_int 1048572))) + (const_int 0) + (const_int 1)))] ) ;; ------------------------------------------------------------------- @@ -768,7 +831,7 @@ { int i; - emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx)); + emit_call_insn (gen_call (operands[0], const0_rtx, NULL)); for (i = 0; i < XVECLEN (operands[2], 0); i++) { @@ -3923,6 +3986,16 @@ [(set_attr "type" "bfm")] ) +(define_insn "*aarch64_bfi<GPI:mode><ALLX:mode>4" + [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r") + (match_operand 1 "const_int_operand" "n") + (match_operand 2 "const_int_operand" "n")) + (zero_extend:GPI (match_operand:ALLX 3 "register_operand" "r")))] + "UINTVAL (operands[1]) <= <ALLX:sizen>" + "bfi\\t%<GPI:w>0, %<GPI:w>3, %2, %1" + [(set_attr "type" "bfm")] +) + (define_insn "*extr_insv_lower_reg<mode>" [(set (zero_extract:GPI (match_operand:GPI 0 "register_operand" "+r") (match_operand 1 "const_int_operand" "n") @@ -4512,31 +4585,72 @@ (set_attr "length" "8")] ) -(define_expand "tlsle" - [(set (match_operand 0 "register_operand" "=r") - (unspec [(match_operand 1 "register_operand" "r") - (match_operand 2 "aarch64_tls_le_symref" "S")] - UNSPEC_TLSLE))] +(define_insn "tlsie_tiny_<mode>" + [(set (match_operand:PTR 0 "register_operand" "=&r") + (unspec:PTR [(match_operand 1 "aarch64_tls_ie_symref" "S") + (match_operand:PTR 2 "register_operand" "r")] + UNSPEC_GOTTINYTLS))] "" -{ - machine_mode mode = GET_MODE (operands[0]); - emit_insn ((mode == DImode - ? gen_tlsle_di - : gen_tlsle_si) (operands[0], operands[1], operands[2])); - DONE; -}) + "ldr\\t%<w>0, %L1\;add\\t%<w>0, %<w>0, %<w>2" + [(set_attr "type" "multiple") + (set_attr "length" "8")] +) -(define_insn "tlsle_<mode>" +(define_insn "tlsie_tiny_sidi" + [(set (match_operand:DI 0 "register_operand" "=&r") + (zero_extend:DI + (unspec:SI [(match_operand 1 "aarch64_tls_ie_symref" "S") + (match_operand:DI 2 "register_operand" "r") + ] + UNSPEC_GOTTINYTLS)))] + "" + "ldr\\t%w0, %L1\;add\\t%<w>0, %<w>0, %<w>2" + [(set_attr "type" "multiple") + (set_attr "length" "8")] +) + +(define_insn "tlsle12_<mode>" [(set (match_operand:P 0 "register_operand" "=r") - (unspec:P [(match_operand:P 1 "register_operand" "r") - (match_operand 2 "aarch64_tls_le_symref" "S")] - UNSPEC_TLSLE))] + (unspec:P [(match_operand:P 1 "register_operand" "r") + (match_operand 2 "aarch64_tls_le_symref" "S")] + UNSPEC_TLSLE12))] "" - "add\\t%<w>0, %<w>1, #%G2, lsl #12\;add\\t%<w>0, %<w>0, #%L2" + "add\\t%<w>0, %<w>1, #%L2"; [(set_attr "type" "alu_sreg") + (set_attr "length" "4")] +) + +(define_insn "tlsle24_<mode>" + [(set (match_operand:P 0 "register_operand" "=r") + (unspec:P [(match_operand:P 1 "register_operand" "r") + (match_operand 2 "aarch64_tls_le_symref" "S")] + UNSPEC_TLSLE24))] + "" + "add\\t%<w>0, %<w>1, #%G2, lsl #12\;add\\t%<w>0, %<w>0, #%L2" + [(set_attr "type" "multiple") (set_attr "length" "8")] ) +(define_insn "tlsle32_<mode>" + [(set (match_operand:P 0 "register_operand" "=r") + (unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")] + UNSPEC_TLSLE32))] + "" + "movz\\t%<w>0, #:tprel_g1:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1" + [(set_attr "type" "multiple") + (set_attr "length" "8")] +) + +(define_insn "tlsle48_<mode>" + [(set (match_operand:P 0 "register_operand" "=r") + (unspec:P [(match_operand 1 "aarch64_tls_le_symref" "S")] + UNSPEC_TLSLE48))] + "" + "movz\\t%<w>0, #:tprel_g2:%1\;movk\\t%<w>0, #:tprel_g1_nc:%1\;movk\\t%<w>0, #:tprel_g0_nc:%1" + [(set_attr "type" "multiple") + (set_attr "length" "12")] +) + (define_insn "tlsdesc_small_<mode>" [(set (reg:PTR R0_REGNUM) (unspec:PTR [(match_operand 0 "aarch64_valid_symref" "S")] diff --git a/gcc/config/aarch64/aarch64.opt b/gcc/config/aarch64/aarch64.opt index 37c2c509fe2..8642bdb74f3 100644 --- a/gcc/config/aarch64/aarch64.opt +++ b/gcc/config/aarch64/aarch64.opt @@ -96,6 +96,25 @@ mtls-dialect= Target RejectNegative Joined Enum(tls_type) Var(aarch64_tls_dialect) Init(TLS_DESCRIPTORS) Save Specify TLS dialect +mtls-size= +Target RejectNegative Joined Var(aarch64_tls_size) Enum(aarch64_tls_size) +Specifies bit size of immediate TLS offsets. Valid values are 12, 24, 32, 48. + +Enum +Name(aarch64_tls_size) Type(int) + +EnumValue +Enum(aarch64_tls_size) String(12) Value(12) + +EnumValue +Enum(aarch64_tls_size) String(24) Value(24) + +EnumValue +Enum(aarch64_tls_size) String(32) Value(32) + +EnumValue +Enum(aarch64_tls_size) String(48) Value(48) + march= Target RejectNegative ToLower Joined Var(aarch64_arch_string) -march=ARCH Use features of architecture ARCH diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md index b8a45d1d6ed..475aa6e6d37 100644 --- a/gcc/config/aarch64/iterators.md +++ b/gcc/config/aarch64/iterators.md @@ -817,9 +817,15 @@ ;; Emit cbz/cbnz depending on comparison type. (define_code_attr cbz [(eq "cbz") (ne "cbnz") (lt "cbnz") (ge "cbz")]) +;; Emit inverted cbz/cbnz depending on comparison type. +(define_code_attr inv_cb [(eq "cbnz") (ne "cbz") (lt "cbz") (ge "cbnz")]) + ;; Emit tbz/tbnz depending on comparison type. (define_code_attr tbz [(eq "tbz") (ne "tbnz") (lt "tbnz") (ge "tbz")]) +;; Emit inverted tbz/tbnz depending on comparison type. +(define_code_attr inv_tb [(eq "tbnz") (ne "tbz") (lt "tbz") (ge "tbnz")]) + ;; Max/min attributes. (define_code_attr maxmin [(smax "max") (smin "min") diff --git a/gcc/config/aarch64/thunderx.md b/gcc/config/aarch64/thunderx.md index 914daf33a5a..cf9636862f2 100644 --- a/gcc/config/aarch64/thunderx.md +++ b/gcc/config/aarch64/thunderx.md @@ -39,7 +39,7 @@ (define_insn_reservation "thunderx_shift" 1 (and (eq_attr "tune" "thunderx") - (eq_attr "type" "bfm,extend,shift_imm,shift_reg")) + (eq_attr "type" "bfm,extend,shift_imm,shift_reg,rbit,rev")) "thunderx_pipe0 | thunderx_pipe1") @@ -66,12 +66,18 @@ (eq_attr "type" "mul,muls,mla,mlas,clz,smull,umull,smlal,umlal")) "thunderx_pipe1 + thunderx_mult") -;; Multiply high instructions take an extra cycle and cause the muliply unit to -;; be busy for an extra cycle. +;; crcb,crch,crcw is 4 cycles and can only happen on pipe 1 -;(define_insn_reservation "thunderx_mul_high" 5 +(define_insn_reservation "thunderx_crc32" 4 + (and (eq_attr "tune" "thunderx") + (eq_attr "type" "crc")) + "thunderx_pipe1 + thunderx_mult") + +;; crcx is 5 cycles and only happen on pipe 1 +;(define_insn_reservation "thunderx_crc64" 5 ; (and (eq_attr "tune" "thunderx") -; (eq_attr "type" "smull,umull")) +; (eq_attr "type" "crc") +; (eq_attr "mode" "DI")) ; "thunderx_pipe1 + thunderx_mult") (define_insn_reservation "thunderx_div32" 22 @@ -97,6 +103,11 @@ (eq_attr "type" "store2")) "thunderx_pipe0 + thunderx_pipe1") +;; Prefetch are single issued +;(define_insn_reservation "thunderx_prefetch" 1 +; (and (eq_attr "tune" "thunderx") +; (eq_attr "type" "prefetch")) +; "thunderx_pipe0 + thunderx_pipe1") ;; loads (and load pairs) from L1 take 3 cycles in pipe 0 (define_insn_reservation "thunderx_load" 3 @@ -121,10 +132,21 @@ (eq_attr "type" "fconsts,fconstd")) "thunderx_pipe1") -;; Moves between fp are 2 cycles including min/max/select/abs/neg +;; Moves between fp are 2 cycles including min/max (define_insn_reservation "thunderx_fmov" 2 (and (eq_attr "tune" "thunderx") - (eq_attr "type" "fmov,f_minmaxs,f_minmaxd,fcsel,ffarithd,ffariths")) + (eq_attr "type" "fmov,f_minmaxs,f_minmaxd")) + "thunderx_pipe1") + +;; ABS, and NEG are 1 cycle +(define_insn_reservation "thunderx_fabs" 1 + (and (eq_attr "tune" "thunderx") + (eq_attr "type" "ffariths,ffarithd")) + "thunderx_pipe1") + +(define_insn_reservation "thunderx_fcsel" 3 + (and (eq_attr "tune" "thunderx") + (eq_attr "type" "fcsel")) "thunderx_pipe1") (define_insn_reservation "thunderx_fmovgpr" 2 @@ -132,6 +154,11 @@ (eq_attr "type" "f_mrc, f_mcr")) "thunderx_pipe1") +(define_insn_reservation "thunderx_fcmp" 3 + (and (eq_attr "tune" "thunderx") + (eq_attr "type" "fcmps,fcmpd")) + "thunderx_pipe1") + (define_insn_reservation "thunderx_fmul" 6 (and (eq_attr "tune" "thunderx") (eq_attr "type" "fmacs,fmacd,fmuls,fmuld")) @@ -152,21 +179,21 @@ (eq_attr "type" "fsqrts")) "thunderx_pipe1 + thunderx_divide, thunderx_divide*13") -(define_insn_reservation "thunderx_fsqrtd" 28 +(define_insn_reservation "thunderx_fsqrtd" 31 (and (eq_attr "tune" "thunderx") (eq_attr "type" "fsqrtd")) - "thunderx_pipe1 + thunderx_divide, thunderx_divide*31") + "thunderx_pipe1 + thunderx_divide, thunderx_divide*27") ;; The rounding conversion inside fp is 4 cycles (define_insn_reservation "thunderx_frint" 4 (and (eq_attr "tune" "thunderx") - (eq_attr "type" "f_rints,f_rintd")) + (eq_attr "type" "f_cvt,f_rints,f_rintd")) "thunderx_pipe1") ;; Float to integer with a move from int to/from float is 6 cycles (define_insn_reservation "thunderx_f_cvt" 6 (and (eq_attr "tune" "thunderx") - (eq_attr "type" "f_cvt,f_cvtf2i,f_cvti2f")) + (eq_attr "type" "f_cvtf2i,f_cvti2f")) "thunderx_pipe1") ;; FP/SIMD load/stores happen in pipe 0 @@ -184,9 +211,12 @@ "thunderx_pipe0+thunderx_pipe1") ;; FP/SIMD Stores takes one cycle in pipe 0 +;; ST1 with one registers either multiple structures or single structure is +;; also one cycle. (define_insn_reservation "thunderx_simd_fp_store" 1 (and (eq_attr "tune" "thunderx") - (eq_attr "type" "f_stored,f_stores,neon_store1_1reg,neon_store1_1reg_q")) + (eq_attr "type" "f_stored,f_stores,neon_store1_1reg,neon_store1_1reg_q, \ + neon_store1_one_lane, neon_store1_one_lane_q")) "thunderx_pipe0") ;; 64bit neon store pairs are single issue for one cycle @@ -201,24 +231,38 @@ (eq_attr "type" "neon_store1_2reg_q")) "(thunderx_pipe0 + thunderx_pipe1)*2") +;; LD1R/LD1 (with a single struct) takes 6 cycles and issued in pipe0 +(define_insn_reservation "thunderx_neon_ld1" 6 + (and (eq_attr "tune" "thunderx") + (eq_attr "type" "neon_load1_all_lanes")) + "thunderx_pipe0") ;; SIMD/NEON (q forms take an extra cycle) +;; SIMD For ThunderX is 64bit wide, -;; Thunder simd move instruction types - 2/3 cycles +;; ThunderX simd move instruction types - 2/3 cycles +;; ThunderX dup, ins is the same +;; ThunderX SIMD fabs/fneg instruction types (define_insn_reservation "thunderx_neon_move" 2 (and (eq_attr "tune" "thunderx") (eq_attr "type" "neon_logic, neon_bsl, neon_fp_compare_s, \ - neon_fp_compare_d, neon_move")) + neon_fp_compare_d, neon_move, neon_dup, \ + neon_ins, neon_from_gp, neon_to_gp, \ + neon_abs, neon_neg, \ + neon_fp_neg_s, neon_fp_abs_s")) "thunderx_pipe1 + thunderx_simd") (define_insn_reservation "thunderx_neon_move_q" 3 (and (eq_attr "tune" "thunderx") (eq_attr "type" "neon_logic_q, neon_bsl_q, neon_fp_compare_s_q, \ - neon_fp_compare_d_q, neon_move_q")) + neon_fp_compare_d_q, neon_move_q, neon_dup_q, \ + neon_ins_q, neon_from_gp_q, neon_to_gp_q, \ + neon_abs_q, neon_neg_q, \ + neon_fp_neg_s_q, neon_fp_neg_d_q, \ + neon_fp_abs_s_q, neon_fp_abs_d_q")) "thunderx_pipe1 + thunderx_simd, thunderx_simd") - -;; Thunder simd simple/add instruction types - 4/5 cycles +;; ThunderX simd simple/add instruction types - 4/5 cycles (define_insn_reservation "thunderx_neon_add" 4 (and (eq_attr "tune" "thunderx") @@ -227,7 +271,9 @@ neon_add_halve, neon_sub_halve, neon_qadd, neon_compare, \ neon_compare_zero, neon_minmax, neon_abd, neon_add, neon_sub, \ neon_fp_minmax_s, neon_fp_minmax_d, neon_reduc_add, neon_cls, \ - neon_qabs, neon_qneg, neon_fp_addsub_s, neon_fp_addsub_d")) + neon_qabs, neon_qneg, neon_fp_addsub_s, neon_fp_addsub_d, \ + neon_arith_acc, neon_rev, neon_fp_abd_s, neon_fp_abd_d, \ + neon_fp_reduc_minmax_s")) "thunderx_pipe1 + thunderx_simd") ;; BIG NOTE: neon_add_long/neon_sub_long don't have a q form which is incorrect @@ -240,13 +286,74 @@ neon_compare_zero_q, neon_minmax_q, neon_abd_q, neon_add_q, neon_sub_q, \ neon_fp_minmax_s_q, neon_fp_minmax_d_q, neon_reduc_add_q, neon_cls_q, \ neon_qabs_q, neon_qneg_q, neon_fp_addsub_s_q, neon_fp_addsub_d_q, \ - neon_add_long, neon_sub_long")) + neon_add_long, neon_sub_long, neon_fp_abd_s_q, neon_fp_abd_d_q, \ + neon_arith_acc_q, neon_rev_q, \ + neon_fp_reduc_minmax_s_q, neon_fp_reduc_minmax_d_q")) "thunderx_pipe1 + thunderx_simd, thunderx_simd") +;; Multiplies (float and integer) and shifts and permutes (except for TBL) and float conversions +;; are 6/7 cycles +(define_insn_reservation "thunderx_neon_mult" 6 + (and (eq_attr "tune" "thunderx") + (eq_attr "type" "neon_fp_mul_s, neon_fp_mul_d, neon_fp_mla_s, neon_fp_mla_d, \ + neon_mla_b, neon_mla_h, neon_mla_s, \ + neon_mla_h_scalar, neon_mla_s_scalar, \ + neon_ext, neon_shift_imm, neon_permute, \ + neon_int_to_fp_s, neon_int_to_fp_d, neon_shift_reg, \ + neon_sat_shift_reg, neon_shift_acc, \ + neon_mul_b, neon_mul_h, neon_mul_s, \ + neon_mul_h_scalar, neon_mul_s_scalar, \ + neon_fp_mul_s_scalar, \ + neon_fp_mla_s_scalar")) + "thunderx_pipe1 + thunderx_simd") + +(define_insn_reservation "thunderx_neon_mult_q" 7 + (and (eq_attr "tune" "thunderx") + (eq_attr "type" "neon_fp_mul_s_q, neon_fp_mul_d_q, neon_fp_mla_s_q, neon_fp_mla_d_q, \ + neon_mla_b_q, neon_mla_h_q, neon_mla_s_q, \ + neon_mla_h_scalar_q, neon_mla_s_scalar_q, \ + neon_ext_q, neon_shift_imm_q, neon_permute_q, \ + neon_int_to_fp_s_q, neon_int_to_fp_d_q, neon_shift_reg_q, \ + neon_sat_shift_reg_q, neon_shift_acc_q, \ + neon_shift_imm_long, \ + neon_mul_b_q, neon_mul_h_q, neon_mul_s_q, \ + neon_mul_h_scalar_q, neon_mul_s_scalar_q, \ + neon_fp_mul_s_scalar_q, neon_fp_mul_d_scalar_q, \ + neon_mul_b_long, neon_mul_h_long, neon_mul_s_long, \ + neon_shift_imm_narrow_q, neon_fp_cvt_widen_s, neon_fp_cvt_narrow_d_q, \ + neon_fp_mla_s_scalar_q, neon_fp_mla_d_scalar_q")) + "thunderx_pipe1 + thunderx_simd, thunderx_simd") + + +;; AES[ED] is 5 cycles +(define_insn_reservation "thunderx_crypto_aese" 5 + (and (eq_attr "tune" "thunderx") + (eq_attr "type" "crypto_aese")) + "thunderx_pipe1 + thunderx_simd, thunderx_simd") -;; Thunder 128bit SIMD reads the upper halve in cycle 2 and writes in the last cycle -(define_bypass 2 "thunderx_neon_move_q" "thunderx_neon_move_q, thunderx_neon_add_q") -(define_bypass 4 "thunderx_neon_add_q" "thunderx_neon_move_q, thunderx_neon_add_q") +;; AES{,I}MC is 3 cycles +(define_insn_reservation "thunderx_crypto_aesmc" 3 + (and (eq_attr "tune" "thunderx") + (eq_attr "type" "crypto_aesmc")) + "thunderx_pipe1 + thunderx_simd, thunderx_simd") + + +;; Thunder 128bit SIMD reads the upper halve in cycle 2 and writes upper halve in the last cycle +(define_bypass 2 "thunderx_neon_move_q" "thunderx_neon_move_q, thunderx_neon_add_q, thunderx_neon_mult_q") +(define_bypass 4 "thunderx_neon_add_q" "thunderx_neon_move_q, thunderx_neon_add_q, thunderx_neon_mult_q") +(define_bypass 6 "thunderx_neon_mult_q" "thunderx_neon_move_q, thunderx_neon_add_q, thunderx_neon_mult_q") + +;; 64bit TBL is emulated and takes 160 cycles +(define_insn_reservation "thunderx_tbl" 160 + (and (eq_attr "tune" "thunderx") + (eq_attr "type" "neon_tbl1")) + "(thunderx_pipe1+thunderx_pipe0)*160") + +;; 128bit TBL is emulated and takes 320 cycles +(define_insn_reservation "thunderx_tblq" 320 + (and (eq_attr "tune" "thunderx") + (eq_attr "type" "neon_tbl1_q")) + "(thunderx_pipe1+thunderx_pipe0)*320") ;; Assume both pipes are needed for unknown and multiple-instruction ;; patterns. diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c index ca07cc7052b..32bb36eec33 100644 --- a/gcc/config/alpha/alpha.c +++ b/gcc/config/alpha/alpha.c @@ -3110,7 +3110,7 @@ alpha_emit_xfloating_libcall (rtx func, rtx target, rtx operands[], } tmp = gen_rtx_MEM (QImode, func); - tmp = emit_call_insn (GEN_CALL_VALUE (reg, tmp, const0_rtx, + tmp = emit_call_insn (gen_call_value (reg, tmp, const0_rtx, const0_rtx, const0_rtx)); CALL_INSN_FUNCTION_USAGE (tmp) = usage; RTL_CONST_CALL_P (tmp) = 1; diff --git a/gcc/config/alpha/alpha.md b/gcc/config/alpha/alpha.md index 7626d3f0233..5068f60ad6c 100644 --- a/gcc/config/alpha/alpha.md +++ b/gcc/config/alpha/alpha.md @@ -3646,7 +3646,7 @@ { int i; - emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx)); + emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx)); for (i = 0; i < XVECLEN (operands[2], 0); i++) { diff --git a/gcc/config/arm/arm-arches.def b/gcc/config/arm/arm-arches.def index 3dafaa5fbc8..ddf6c3c330f 100644 --- a/gcc/config/arm/arm-arches.def +++ b/gcc/config/arm/arm-arches.def @@ -23,39 +23,40 @@ The NAME is the name of the architecture, represented as a string constant. The CORE is the identifier for a core representative of - this architecture. ARCH is the architecture revision. FLAGS are - the flags implied by the architecture. + this architecture. ARCH is the architecture revision. FLAGS is + the set of feature flags implied by the architecture. genopt.sh assumes no whitespace up to the first "," in each entry. */ -ARM_ARCH("armv2", arm2, 2, FL_CO_PROC | FL_MODE26 | FL_FOR_ARCH2) -ARM_ARCH("armv2a", arm2, 2, FL_CO_PROC | FL_MODE26 | FL_FOR_ARCH2) -ARM_ARCH("armv3", arm6, 3, FL_CO_PROC | FL_MODE26 | FL_FOR_ARCH3) -ARM_ARCH("armv3m", arm7m, 3M, FL_CO_PROC | FL_MODE26 | FL_FOR_ARCH3M) -ARM_ARCH("armv4", arm7tdmi, 4, FL_CO_PROC | FL_MODE26 | FL_FOR_ARCH4) +ARM_ARCH("armv2", arm2, 2, ARM_FSET_MAKE_CPU1 (FL_CO_PROC | FL_MODE26 | FL_FOR_ARCH2)) +ARM_ARCH("armv2a", arm2, 2, ARM_FSET_MAKE_CPU1 (FL_CO_PROC | FL_MODE26 | FL_FOR_ARCH2)) +ARM_ARCH("armv3", arm6, 3, ARM_FSET_MAKE_CPU1 (FL_CO_PROC | FL_MODE26 | FL_FOR_ARCH3)) +ARM_ARCH("armv3m", arm7m, 3M, ARM_FSET_MAKE_CPU1 (FL_CO_PROC | FL_MODE26 | FL_FOR_ARCH3M)) +ARM_ARCH("armv4", arm7tdmi, 4, ARM_FSET_MAKE_CPU1 (FL_CO_PROC | FL_MODE26 | FL_FOR_ARCH4)) /* Strictly, FL_MODE26 is a permitted option for v4t, but there are no implementations that support it, so we will leave it out for now. */ -ARM_ARCH("armv4t", arm7tdmi, 4T, FL_CO_PROC | FL_FOR_ARCH4T) -ARM_ARCH("armv5", arm10tdmi, 5, FL_CO_PROC | FL_FOR_ARCH5) -ARM_ARCH("armv5t", arm10tdmi, 5T, FL_CO_PROC | FL_FOR_ARCH5T) -ARM_ARCH("armv5e", arm1026ejs, 5E, FL_CO_PROC | FL_FOR_ARCH5E) -ARM_ARCH("armv5te", arm1026ejs, 5TE, FL_CO_PROC | FL_FOR_ARCH5TE) -ARM_ARCH("armv6", arm1136js, 6, FL_CO_PROC | FL_FOR_ARCH6) -ARM_ARCH("armv6j", arm1136js, 6J, FL_CO_PROC | FL_FOR_ARCH6J) -ARM_ARCH("armv6k", mpcore, 6K, FL_CO_PROC | FL_FOR_ARCH6K) -ARM_ARCH("armv6z", arm1176jzs, 6Z, FL_CO_PROC | FL_FOR_ARCH6Z) -ARM_ARCH("armv6kz", arm1176jzs, 6KZ, FL_CO_PROC | FL_FOR_ARCH6KZ) -ARM_ARCH("armv6zk", arm1176jzs, 6KZ, FL_CO_PROC | FL_FOR_ARCH6KZ) -ARM_ARCH("armv6t2", arm1156t2s, 6T2, FL_CO_PROC | FL_FOR_ARCH6T2) -ARM_ARCH("armv6-m", cortexm1, 6M, FL_FOR_ARCH6M) -ARM_ARCH("armv6s-m", cortexm1, 6M, FL_FOR_ARCH6M) -ARM_ARCH("armv7", cortexa8, 7, FL_CO_PROC | FL_FOR_ARCH7) -ARM_ARCH("armv7-a", cortexa8, 7A, FL_CO_PROC | FL_FOR_ARCH7A) -ARM_ARCH("armv7ve", cortexa8, 7A, FL_CO_PROC | FL_FOR_ARCH7VE) -ARM_ARCH("armv7-r", cortexr4, 7R, FL_CO_PROC | FL_FOR_ARCH7R) -ARM_ARCH("armv7-m", cortexm3, 7M, FL_CO_PROC | FL_FOR_ARCH7M) -ARM_ARCH("armv7e-m", cortexm4, 7EM, FL_CO_PROC | FL_FOR_ARCH7EM) -ARM_ARCH("armv8-a", cortexa53, 8A, FL_CO_PROC | FL_FOR_ARCH8A) -ARM_ARCH("armv8-a+crc",cortexa53, 8A,FL_CO_PROC | FL_CRC32 | FL_FOR_ARCH8A) -ARM_ARCH("iwmmxt", iwmmxt, 5TE, FL_LDSCHED | FL_STRONG | FL_FOR_ARCH5TE | FL_XSCALE | FL_IWMMXT) -ARM_ARCH("iwmmxt2", iwmmxt2, 5TE, FL_LDSCHED | FL_STRONG | FL_FOR_ARCH5TE | FL_XSCALE | FL_IWMMXT | FL_IWMMXT2) +ARM_ARCH("armv4t", arm7tdmi, 4T, ARM_FSET_MAKE_CPU1 (FL_CO_PROC | FL_FOR_ARCH4T)) +ARM_ARCH("armv5", arm10tdmi, 5, ARM_FSET_MAKE_CPU1 (FL_CO_PROC | FL_FOR_ARCH5)) +ARM_ARCH("armv5t", arm10tdmi, 5T, ARM_FSET_MAKE_CPU1 (FL_CO_PROC | FL_FOR_ARCH5T)) +ARM_ARCH("armv5e", arm1026ejs, 5E, ARM_FSET_MAKE_CPU1 (FL_CO_PROC | FL_FOR_ARCH5E)) +ARM_ARCH("armv5te", arm1026ejs, 5TE, ARM_FSET_MAKE_CPU1 (FL_CO_PROC | FL_FOR_ARCH5TE)) +ARM_ARCH("armv6", arm1136js, 6, ARM_FSET_MAKE_CPU1 (FL_CO_PROC | FL_FOR_ARCH6)) +ARM_ARCH("armv6j", arm1136js, 6J, ARM_FSET_MAKE_CPU1 (FL_CO_PROC | FL_FOR_ARCH6J)) +ARM_ARCH("armv6k", mpcore, 6K, ARM_FSET_MAKE_CPU1 (FL_CO_PROC | FL_FOR_ARCH6K)) +ARM_ARCH("armv6z", arm1176jzs, 6Z, ARM_FSET_MAKE_CPU1 (FL_CO_PROC | FL_FOR_ARCH6Z)) +ARM_ARCH("armv6kz", arm1176jzs, 6KZ, ARM_FSET_MAKE_CPU1 (FL_CO_PROC | FL_FOR_ARCH6KZ)) +ARM_ARCH("armv6zk", arm1176jzs, 6KZ, ARM_FSET_MAKE_CPU1 (FL_CO_PROC | FL_FOR_ARCH6KZ)) +ARM_ARCH("armv6t2", arm1156t2s, 6T2, ARM_FSET_MAKE_CPU1 (FL_CO_PROC | FL_FOR_ARCH6T2)) +ARM_ARCH("armv6-m", cortexm1, 6M, ARM_FSET_MAKE_CPU1 (FL_FOR_ARCH6M)) +ARM_ARCH("armv6s-m", cortexm1, 6M, ARM_FSET_MAKE_CPU1 (FL_FOR_ARCH6M)) +ARM_ARCH("armv7", cortexa8, 7, ARM_FSET_MAKE_CPU1 (FL_CO_PROC | FL_FOR_ARCH7)) +ARM_ARCH("armv7-a", cortexa8, 7A, ARM_FSET_MAKE_CPU1 (FL_CO_PROC | FL_FOR_ARCH7A)) +ARM_ARCH("armv7ve", cortexa8, 7A, ARM_FSET_MAKE_CPU1 (FL_CO_PROC | FL_FOR_ARCH7VE)) +ARM_ARCH("armv7-r", cortexr4, 7R, ARM_FSET_MAKE_CPU1 (FL_CO_PROC | FL_FOR_ARCH7R)) +ARM_ARCH("armv7-m", cortexm3, 7M, ARM_FSET_MAKE_CPU1 (FL_CO_PROC | FL_FOR_ARCH7M)) +ARM_ARCH("armv7e-m", cortexm4, 7EM, ARM_FSET_MAKE_CPU1 (FL_CO_PROC | FL_FOR_ARCH7EM)) +ARM_ARCH("armv8-a", cortexa53, 8A, ARM_FSET_MAKE_CPU1 (FL_CO_PROC | FL_FOR_ARCH8A)) +ARM_ARCH("armv8-a+crc",cortexa53, 8A, ARM_FSET_MAKE_CPU1 (FL_CO_PROC | FL_CRC32 | FL_FOR_ARCH8A)) +ARM_ARCH("iwmmxt", iwmmxt, 5TE, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_STRONG | FL_FOR_ARCH5TE | FL_XSCALE | FL_IWMMXT)) +ARM_ARCH("iwmmxt2", iwmmxt2, 5TE, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_STRONG | FL_FOR_ARCH5TE | FL_XSCALE | FL_IWMMXT | FL_IWMMXT2)) + diff --git a/gcc/config/arm/arm-builtins.c b/gcc/config/arm/arm-builtins.c index 030d8d19441..4391f17c655 100644 --- a/gcc/config/arm/arm-builtins.c +++ b/gcc/config/arm/arm-builtins.c @@ -769,13 +769,6 @@ arm_init_simd_builtin_types (void) int nelts = sizeof (arm_simd_types) / sizeof (arm_simd_types[0]); tree tdecl; - /* Initialize the HFmode scalar type. */ - arm_simd_floatHF_type_node = make_node (REAL_TYPE); - TYPE_PRECISION (arm_simd_floatHF_type_node) = GET_MODE_PRECISION (HFmode); - layout_type (arm_simd_floatHF_type_node); - (*lang_hooks.types.register_builtin_type) (arm_simd_floatHF_type_node, - "__builtin_neon_hf"); - /* Poly types are a world of their own. In order to maintain legacy ABI, they get initialized using the old interface, and don't get an entry in our mangling table, consequently, they get default @@ -823,6 +816,8 @@ arm_init_simd_builtin_types (void) mangling. */ /* Continue with standard types. */ + /* The __builtin_simd{64,128}_float16 types are kept private unless + we have a scalar __fp16 type. */ arm_simd_types[Float16x4_t].eltype = arm_simd_floatHF_type_node; arm_simd_types[Float32x2_t].eltype = float_type_node; arm_simd_types[Float32x4_t].eltype = float_type_node; @@ -1106,10 +1101,11 @@ arm_init_neon_builtins (void) #undef NUM_DREG_TYPES #undef NUM_QREG_TYPES -#define def_mbuiltin(MASK, NAME, TYPE, CODE) \ +#define def_mbuiltin(FLAGS, NAME, TYPE, CODE) \ do \ { \ - if ((MASK) & insn_flags) \ + const arm_feature_set flags = FLAGS; \ + if (ARM_FSET_CPU_SUBSET (flags, insn_flags)) \ { \ tree bdecl; \ bdecl = add_builtin_function ((NAME), (TYPE), (CODE), \ @@ -1121,7 +1117,7 @@ arm_init_neon_builtins (void) struct builtin_description { - const unsigned int mask; + const arm_feature_set features; const enum insn_code icode; const char * const name; const enum arm_builtins code; @@ -1132,11 +1128,13 @@ struct builtin_description static const struct builtin_description bdesc_2arg[] = { #define IWMMXT_BUILTIN(code, string, builtin) \ - { FL_IWMMXT, CODE_FOR_##code, "__builtin_arm_" string, \ + { ARM_FSET_MAKE_CPU1 (FL_IWMMXT), CODE_FOR_##code, \ + "__builtin_arm_" string, \ ARM_BUILTIN_##builtin, UNKNOWN, 0 }, #define IWMMXT2_BUILTIN(code, string, builtin) \ - { FL_IWMMXT2, CODE_FOR_##code, "__builtin_arm_" string, \ + { ARM_FSET_MAKE_CPU1 (FL_IWMMXT2), CODE_FOR_##code, \ + "__builtin_arm_" string, \ ARM_BUILTIN_##builtin, UNKNOWN, 0 }, IWMMXT_BUILTIN (addv8qi3, "waddb", WADDB) @@ -1219,10 +1217,12 @@ static const struct builtin_description bdesc_2arg[] = IWMMXT_BUILTIN (iwmmxt_walignr3, "walignr3", WALIGNR3) #define IWMMXT_BUILTIN2(code, builtin) \ - { FL_IWMMXT, CODE_FOR_##code, NULL, ARM_BUILTIN_##builtin, UNKNOWN, 0 }, + { ARM_FSET_MAKE_CPU1 (FL_IWMMXT), CODE_FOR_##code, NULL, \ + ARM_BUILTIN_##builtin, UNKNOWN, 0 }, #define IWMMXT2_BUILTIN2(code, builtin) \ - { FL_IWMMXT2, CODE_FOR_##code, NULL, ARM_BUILTIN_##builtin, UNKNOWN, 0 }, + { ARM_FSET_MAKE_CPU2 (FL_IWMMXT2), CODE_FOR_##code, NULL, \ + ARM_BUILTIN_##builtin, UNKNOWN, 0 }, IWMMXT2_BUILTIN2 (iwmmxt_waddbhusm, WADDBHUSM) IWMMXT2_BUILTIN2 (iwmmxt_waddbhusl, WADDBHUSL) @@ -1237,7 +1237,7 @@ static const struct builtin_description bdesc_2arg[] = #define FP_BUILTIN(L, U) \ - {0, CODE_FOR_##L, "__builtin_arm_"#L, ARM_BUILTIN_##U, \ + {ARM_FSET_EMPTY, CODE_FOR_##L, "__builtin_arm_"#L, ARM_BUILTIN_##U, \ UNKNOWN, 0}, FP_BUILTIN (get_fpscr, GET_FPSCR) @@ -1245,8 +1245,8 @@ static const struct builtin_description bdesc_2arg[] = #undef FP_BUILTIN #define CRC32_BUILTIN(L, U) \ - {0, CODE_FOR_##L, "__builtin_arm_"#L, ARM_BUILTIN_##U, \ - UNKNOWN, 0}, + {ARM_FSET_EMPTY, CODE_FOR_##L, "__builtin_arm_"#L, \ + ARM_BUILTIN_##U, UNKNOWN, 0}, CRC32_BUILTIN (crc32b, CRC32B) CRC32_BUILTIN (crc32h, CRC32H) CRC32_BUILTIN (crc32w, CRC32W) @@ -1256,9 +1256,9 @@ static const struct builtin_description bdesc_2arg[] = #undef CRC32_BUILTIN -#define CRYPTO_BUILTIN(L, U) \ - {0, CODE_FOR_crypto_##L, "__builtin_arm_crypto_"#L, ARM_BUILTIN_CRYPTO_##U, \ - UNKNOWN, 0}, +#define CRYPTO_BUILTIN(L, U) \ + {ARM_FSET_EMPTY, CODE_FOR_crypto_##L, "__builtin_arm_crypto_"#L, \ + ARM_BUILTIN_CRYPTO_##U, UNKNOWN, 0}, #undef CRYPTO1 #undef CRYPTO2 #undef CRYPTO3 @@ -1514,7 +1514,9 @@ arm_init_iwmmxt_builtins (void) machine_mode mode; tree type; - if (d->name == 0 || !(d->mask == FL_IWMMXT || d->mask == FL_IWMMXT2)) + if (d->name == 0 || + !(ARM_FSET_HAS_CPU1 (d->features, FL_IWMMXT) || + ARM_FSET_HAS_CPU1 (d->features, FL_IWMMXT2))) continue; mode = insn_data[d->icode].operand[1].mode; @@ -1538,17 +1540,17 @@ arm_init_iwmmxt_builtins (void) gcc_unreachable (); } - def_mbuiltin (d->mask, d->name, type, d->code); + def_mbuiltin (d->features, d->name, type, d->code); } /* Add the remaining MMX insns with somewhat more complicated types. */ #define iwmmx_mbuiltin(NAME, TYPE, CODE) \ - def_mbuiltin (FL_IWMMXT, "__builtin_arm_" NAME, (TYPE), \ - ARM_BUILTIN_ ## CODE) + def_mbuiltin (ARM_FSET_MAKE_CPU1 (FL_IWMMXT), "__builtin_arm_" NAME, \ + (TYPE), ARM_BUILTIN_ ## CODE) #define iwmmx2_mbuiltin(NAME, TYPE, CODE) \ - def_mbuiltin (FL_IWMMXT2, "__builtin_arm_" NAME, (TYPE), \ - ARM_BUILTIN_ ## CODE) + def_mbuiltin (ARM_FSET_MAKE_CPU1 (FL_IWMMXT2), "__builtin_arm_" NAME, \ + (TYPE), ARM_BUILTIN_ ## CODE) iwmmx_mbuiltin ("wzero", di_ftype_void, WZERO); iwmmx_mbuiltin ("setwcgr0", void_ftype_int, SETWCGR0); @@ -1702,10 +1704,12 @@ arm_init_iwmmxt_builtins (void) static void arm_init_fp16_builtins (void) { - tree fp16_type = make_node (REAL_TYPE); - TYPE_PRECISION (fp16_type) = 16; - layout_type (fp16_type); - (*lang_hooks.types.register_builtin_type) (fp16_type, "__fp16"); + arm_simd_floatHF_type_node = make_node (REAL_TYPE); + TYPE_PRECISION (arm_simd_floatHF_type_node) = GET_MODE_PRECISION (HFmode); + layout_type (arm_simd_floatHF_type_node); + if (arm_fp16_format) + (*lang_hooks.types.register_builtin_type) (arm_simd_floatHF_type_node, + "__fp16"); } static void @@ -1750,12 +1754,13 @@ arm_init_builtins (void) if (TARGET_REALLY_IWMMXT) arm_init_iwmmxt_builtins (); + /* This creates the arm_simd_floatHF_type_node so must come before + arm_init_neon_builtins which uses it. */ + arm_init_fp16_builtins (); + if (TARGET_NEON) arm_init_neon_builtins (); - if (arm_fp16_format) - arm_init_fp16_builtins (); - if (TARGET_CRC32) arm_init_crc32_builtins (); diff --git a/gcc/config/arm/arm-cores.def b/gcc/config/arm/arm-cores.def index 9d47fcfbcd7..4c35200b3f8 100644 --- a/gcc/config/arm/arm-cores.def +++ b/gcc/config/arm/arm-cores.def @@ -33,7 +33,7 @@ The TUNE_IDENT is the name of the core for which scheduling decisions should be made, represented as an identifier. ARCH is the architecture revision implemented by the chip. - FLAGS are the bitwise-or of the traits that apply to that core. + FLAGS is the set of feature flags of that core. This need not include flags implied by the architecture. COSTS is the name of the rtx_costs routine to use. @@ -43,134 +43,134 @@ Some tools assume no whitespace up to the first "," in each entry. */ /* V2/V2A Architecture Processors */ -ARM_CORE("arm2", arm2, arm2, 2, FL_CO_PROC | FL_MODE26, slowmul) -ARM_CORE("arm250", arm250, arm250, 2, FL_CO_PROC | FL_MODE26, slowmul) -ARM_CORE("arm3", arm3, arm3, 2, FL_CO_PROC | FL_MODE26, slowmul) +ARM_CORE("arm2", arm2, arm2, 2, ARM_FSET_MAKE_CPU1 (FL_CO_PROC | FL_MODE26 | FL_FOR_ARCH2), slowmul) +ARM_CORE("arm250", arm250, arm250, 2, ARM_FSET_MAKE_CPU1 (FL_CO_PROC | FL_MODE26 | FL_FOR_ARCH2), slowmul) +ARM_CORE("arm3", arm3, arm3, 2, ARM_FSET_MAKE_CPU1 (FL_CO_PROC | FL_MODE26 | FL_FOR_ARCH2), slowmul) /* V3 Architecture Processors */ -ARM_CORE("arm6", arm6, arm6, 3, FL_CO_PROC | FL_MODE26, slowmul) -ARM_CORE("arm60", arm60, arm60, 3, FL_CO_PROC | FL_MODE26, slowmul) -ARM_CORE("arm600", arm600, arm600, 3, FL_CO_PROC | FL_MODE26 | FL_WBUF, slowmul) -ARM_CORE("arm610", arm610, arm610, 3, FL_MODE26 | FL_WBUF, slowmul) -ARM_CORE("arm620", arm620, arm620, 3, FL_CO_PROC | FL_MODE26 | FL_WBUF, slowmul) -ARM_CORE("arm7", arm7, arm7, 3, FL_CO_PROC | FL_MODE26, slowmul) -ARM_CORE("arm7d", arm7d, arm7d, 3, FL_CO_PROC | FL_MODE26, slowmul) -ARM_CORE("arm7di", arm7di, arm7di, 3, FL_CO_PROC | FL_MODE26, slowmul) -ARM_CORE("arm70", arm70, arm70, 3, FL_CO_PROC | FL_MODE26, slowmul) -ARM_CORE("arm700", arm700, arm700, 3, FL_CO_PROC | FL_MODE26 | FL_WBUF, slowmul) -ARM_CORE("arm700i", arm700i, arm700i, 3, FL_CO_PROC | FL_MODE26 | FL_WBUF, slowmul) -ARM_CORE("arm710", arm710, arm710, 3, FL_MODE26 | FL_WBUF, slowmul) -ARM_CORE("arm720", arm720, arm720, 3, FL_MODE26 | FL_WBUF, slowmul) -ARM_CORE("arm710c", arm710c, arm710c, 3, FL_MODE26 | FL_WBUF, slowmul) -ARM_CORE("arm7100", arm7100, arm7100, 3, FL_MODE26 | FL_WBUF, slowmul) -ARM_CORE("arm7500", arm7500, arm7500, 3, FL_MODE26 | FL_WBUF, slowmul) +ARM_CORE("arm6", arm6, arm6, 3, ARM_FSET_MAKE_CPU1 (FL_CO_PROC | FL_MODE26 | FL_FOR_ARCH3), slowmul) +ARM_CORE("arm60", arm60, arm60, 3, ARM_FSET_MAKE_CPU1 (FL_CO_PROC | FL_MODE26 | FL_FOR_ARCH3), slowmul) +ARM_CORE("arm600", arm600, arm600, 3, ARM_FSET_MAKE_CPU1 (FL_CO_PROC | FL_MODE26 | FL_WBUF | FL_FOR_ARCH3), slowmul) +ARM_CORE("arm610", arm610, arm610, 3, ARM_FSET_MAKE_CPU1 (FL_MODE26 | FL_WBUF | FL_FOR_ARCH3), slowmul) +ARM_CORE("arm620", arm620, arm620, 3, ARM_FSET_MAKE_CPU1 (FL_CO_PROC | FL_MODE26 | FL_WBUF | FL_FOR_ARCH3), slowmul) +ARM_CORE("arm7", arm7, arm7, 3, ARM_FSET_MAKE_CPU1 (FL_CO_PROC | FL_MODE26 | FL_FOR_ARCH3), slowmul) +ARM_CORE("arm7d", arm7d, arm7d, 3, ARM_FSET_MAKE_CPU1 (FL_CO_PROC | FL_MODE26 | FL_FOR_ARCH3), slowmul) +ARM_CORE("arm7di", arm7di, arm7di, 3, ARM_FSET_MAKE_CPU1 (FL_CO_PROC | FL_MODE26 | FL_FOR_ARCH3), slowmul) +ARM_CORE("arm70", arm70, arm70, 3, ARM_FSET_MAKE_CPU1 (FL_CO_PROC | FL_MODE26 | FL_FOR_ARCH3), slowmul) +ARM_CORE("arm700", arm700, arm700, 3, ARM_FSET_MAKE_CPU1 (FL_CO_PROC | FL_MODE26 | FL_WBUF | FL_FOR_ARCH3), slowmul) +ARM_CORE("arm700i", arm700i, arm700i, 3, ARM_FSET_MAKE_CPU1 (FL_CO_PROC | FL_MODE26 | FL_WBUF | FL_FOR_ARCH3), slowmul) +ARM_CORE("arm710", arm710, arm710, 3, ARM_FSET_MAKE_CPU1 (FL_MODE26 | FL_WBUF | FL_FOR_ARCH3), slowmul) +ARM_CORE("arm720", arm720, arm720, 3, ARM_FSET_MAKE_CPU1 (FL_MODE26 | FL_WBUF | FL_FOR_ARCH3), slowmul) +ARM_CORE("arm710c", arm710c, arm710c, 3, ARM_FSET_MAKE_CPU1 (FL_MODE26 | FL_WBUF | FL_FOR_ARCH3), slowmul) +ARM_CORE("arm7100", arm7100, arm7100, 3, ARM_FSET_MAKE_CPU1 (FL_MODE26 | FL_WBUF | FL_FOR_ARCH3), slowmul) +ARM_CORE("arm7500", arm7500, arm7500, 3, ARM_FSET_MAKE_CPU1 (FL_MODE26 | FL_WBUF | FL_FOR_ARCH3), slowmul) /* Doesn't have an external co-proc, but does have embedded fpa. */ -ARM_CORE("arm7500fe", arm7500fe, arm7500fe, 3, FL_CO_PROC | FL_MODE26 | FL_WBUF, slowmul) +ARM_CORE("arm7500fe", arm7500fe, arm7500fe, 3, ARM_FSET_MAKE_CPU1 (FL_CO_PROC | FL_MODE26 | FL_WBUF | FL_FOR_ARCH3), slowmul) /* V3M Architecture Processors */ /* arm7m doesn't exist on its own, but only with D, ("and", and I), but those don't alter the code, so arm7m is sometimes used. */ -ARM_CORE("arm7m", arm7m, arm7m, 3M, FL_CO_PROC | FL_MODE26, fastmul) -ARM_CORE("arm7dm", arm7dm, arm7dm, 3M, FL_CO_PROC | FL_MODE26, fastmul) -ARM_CORE("arm7dmi", arm7dmi, arm7dmi, 3M, FL_CO_PROC | FL_MODE26, fastmul) +ARM_CORE("arm7m", arm7m, arm7m, 3M, ARM_FSET_MAKE_CPU1 (FL_CO_PROC | FL_MODE26 | FL_FOR_ARCH3M), fastmul) +ARM_CORE("arm7dm", arm7dm, arm7dm, 3M, ARM_FSET_MAKE_CPU1 (FL_CO_PROC | FL_MODE26 | FL_FOR_ARCH3M), fastmul) +ARM_CORE("arm7dmi", arm7dmi, arm7dmi, 3M, ARM_FSET_MAKE_CPU1 (FL_CO_PROC | FL_MODE26 | FL_FOR_ARCH3M), fastmul) /* V4 Architecture Processors */ -ARM_CORE("arm8", arm8, arm8, 4, FL_MODE26 | FL_LDSCHED, fastmul) -ARM_CORE("arm810", arm810, arm810, 4, FL_MODE26 | FL_LDSCHED, fastmul) -ARM_CORE("strongarm", strongarm, strongarm, 4, FL_MODE26 | FL_LDSCHED | FL_STRONG, strongarm) -ARM_CORE("strongarm110", strongarm110, strongarm110, 4, FL_MODE26 | FL_LDSCHED | FL_STRONG, strongarm) -ARM_CORE("strongarm1100", strongarm1100, strongarm1100, 4, FL_MODE26 | FL_LDSCHED | FL_STRONG, strongarm) -ARM_CORE("strongarm1110", strongarm1110, strongarm1110, 4, FL_MODE26 | FL_LDSCHED | FL_STRONG, strongarm) -ARM_CORE("fa526", fa526, fa526, 4, FL_LDSCHED, fastmul) -ARM_CORE("fa626", fa626, fa626, 4, FL_LDSCHED, fastmul) +ARM_CORE("arm8", arm8, arm8, 4, ARM_FSET_MAKE_CPU1 (FL_MODE26 | FL_LDSCHED | FL_FOR_ARCH4), fastmul) +ARM_CORE("arm810", arm810, arm810, 4, ARM_FSET_MAKE_CPU1 (FL_MODE26 | FL_LDSCHED | FL_FOR_ARCH4), fastmul) +ARM_CORE("strongarm", strongarm, strongarm, 4, ARM_FSET_MAKE_CPU1 (FL_MODE26 | FL_LDSCHED | FL_STRONG | FL_FOR_ARCH4), strongarm) +ARM_CORE("strongarm110", strongarm110, strongarm110, 4, ARM_FSET_MAKE_CPU1 (FL_MODE26 | FL_LDSCHED | FL_STRONG | FL_FOR_ARCH4), strongarm) +ARM_CORE("strongarm1100", strongarm1100, strongarm1100, 4, ARM_FSET_MAKE_CPU1 (FL_MODE26 | FL_LDSCHED | FL_STRONG | FL_FOR_ARCH4), strongarm) +ARM_CORE("strongarm1110", strongarm1110, strongarm1110, 4, ARM_FSET_MAKE_CPU1 (FL_MODE26 | FL_LDSCHED | FL_STRONG | FL_FOR_ARCH4), strongarm) +ARM_CORE("fa526", fa526, fa526, 4, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_FOR_ARCH4), fastmul) +ARM_CORE("fa626", fa626, fa626, 4, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_FOR_ARCH4), fastmul) /* V4T Architecture Processors */ -ARM_CORE("arm7tdmi", arm7tdmi, arm7tdmi, 4T, FL_CO_PROC, fastmul) -ARM_CORE("arm7tdmi-s", arm7tdmis, arm7tdmis, 4T, FL_CO_PROC, fastmul) -ARM_CORE("arm710t", arm710t, arm710t, 4T, FL_WBUF, fastmul) -ARM_CORE("arm720t", arm720t, arm720t, 4T, FL_WBUF, fastmul) -ARM_CORE("arm740t", arm740t, arm740t, 4T, FL_WBUF, fastmul) -ARM_CORE("arm9", arm9, arm9, 4T, FL_LDSCHED, fastmul) -ARM_CORE("arm9tdmi", arm9tdmi, arm9tdmi, 4T, FL_LDSCHED, fastmul) -ARM_CORE("arm920", arm920, arm920, 4T, FL_LDSCHED, fastmul) -ARM_CORE("arm920t", arm920t, arm920t, 4T, FL_LDSCHED, fastmul) -ARM_CORE("arm922t", arm922t, arm922t, 4T, FL_LDSCHED, fastmul) -ARM_CORE("arm940t", arm940t, arm940t, 4T, FL_LDSCHED, fastmul) -ARM_CORE("ep9312", ep9312, ep9312, 4T, FL_LDSCHED, fastmul) +ARM_CORE("arm7tdmi", arm7tdmi, arm7tdmi, 4T, ARM_FSET_MAKE_CPU1 (FL_CO_PROC | FL_FOR_ARCH4T), fastmul) +ARM_CORE("arm7tdmi-s", arm7tdmis, arm7tdmis, 4T, ARM_FSET_MAKE_CPU1 (FL_CO_PROC | FL_FOR_ARCH4T), fastmul) +ARM_CORE("arm710t", arm710t, arm710t, 4T, ARM_FSET_MAKE_CPU1 (FL_WBUF | FL_FOR_ARCH4T), fastmul) +ARM_CORE("arm720t", arm720t, arm720t, 4T, ARM_FSET_MAKE_CPU1 (FL_WBUF | FL_FOR_ARCH4T), fastmul) +ARM_CORE("arm740t", arm740t, arm740t, 4T, ARM_FSET_MAKE_CPU1 (FL_WBUF | FL_FOR_ARCH4T), fastmul) +ARM_CORE("arm9", arm9, arm9, 4T, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_FOR_ARCH4T), fastmul) +ARM_CORE("arm9tdmi", arm9tdmi, arm9tdmi, 4T, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_FOR_ARCH4T), fastmul) +ARM_CORE("arm920", arm920, arm920, 4T, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_FOR_ARCH4T), fastmul) +ARM_CORE("arm920t", arm920t, arm920t, 4T, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_FOR_ARCH4T), fastmul) +ARM_CORE("arm922t", arm922t, arm922t, 4T, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_FOR_ARCH4T), fastmul) +ARM_CORE("arm940t", arm940t, arm940t, 4T, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_FOR_ARCH4T), fastmul) +ARM_CORE("ep9312", ep9312, ep9312, 4T, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_FOR_ARCH4T), fastmul) /* V5T Architecture Processors */ -ARM_CORE("arm10tdmi", arm10tdmi, arm10tdmi, 5T, FL_LDSCHED, fastmul) -ARM_CORE("arm1020t", arm1020t, arm1020t, 5T, FL_LDSCHED, fastmul) +ARM_CORE("arm10tdmi", arm10tdmi, arm10tdmi, 5T, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_FOR_ARCH5T), fastmul) +ARM_CORE("arm1020t", arm1020t, arm1020t, 5T, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_FOR_ARCH5T), fastmul) /* V5TE Architecture Processors */ -ARM_CORE("arm9e", arm9e, arm9e, 5TE, FL_LDSCHED, 9e) -ARM_CORE("arm946e-s", arm946es, arm946es, 5TE, FL_LDSCHED, 9e) -ARM_CORE("arm966e-s", arm966es, arm966es, 5TE, FL_LDSCHED, 9e) -ARM_CORE("arm968e-s", arm968es, arm968es, 5TE, FL_LDSCHED, 9e) -ARM_CORE("arm10e", arm10e, arm10e, 5TE, FL_LDSCHED, fastmul) -ARM_CORE("arm1020e", arm1020e, arm1020e, 5TE, FL_LDSCHED, fastmul) -ARM_CORE("arm1022e", arm1022e, arm1022e, 5TE, FL_LDSCHED, fastmul) -ARM_CORE("xscale", xscale, xscale, 5TE, FL_LDSCHED | FL_STRONG | FL_XSCALE, xscale) -ARM_CORE("iwmmxt", iwmmxt, iwmmxt, 5TE, FL_LDSCHED | FL_STRONG | FL_XSCALE | FL_IWMMXT, xscale) -ARM_CORE("iwmmxt2", iwmmxt2, iwmmxt2, 5TE, FL_LDSCHED | FL_STRONG | FL_XSCALE | FL_IWMMXT | FL_IWMMXT2, xscale) -ARM_CORE("fa606te", fa606te, fa606te, 5TE, FL_LDSCHED, 9e) -ARM_CORE("fa626te", fa626te, fa626te, 5TE, FL_LDSCHED, 9e) -ARM_CORE("fmp626", fmp626, fmp626, 5TE, FL_LDSCHED, 9e) -ARM_CORE("fa726te", fa726te, fa726te, 5TE, FL_LDSCHED, fa726te) +ARM_CORE("arm9e", arm9e, arm9e, 5TE, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_FOR_ARCH5TE), 9e) +ARM_CORE("arm946e-s", arm946es, arm946es, 5TE, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_FOR_ARCH5TE), 9e) +ARM_CORE("arm966e-s", arm966es, arm966es, 5TE, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_FOR_ARCH5TE), 9e) +ARM_CORE("arm968e-s", arm968es, arm968es, 5TE, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_FOR_ARCH5TE), 9e) +ARM_CORE("arm10e", arm10e, arm10e, 5TE, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_FOR_ARCH5TE), fastmul) +ARM_CORE("arm1020e", arm1020e, arm1020e, 5TE, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_FOR_ARCH5TE), fastmul) +ARM_CORE("arm1022e", arm1022e, arm1022e, 5TE, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_FOR_ARCH5TE), fastmul) +ARM_CORE("xscale", xscale, xscale, 5TE, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_STRONG | FL_XSCALE | FL_FOR_ARCH5TE), xscale) +ARM_CORE("iwmmxt", iwmmxt, iwmmxt, 5TE, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_STRONG | FL_XSCALE | FL_IWMMXT | FL_FOR_ARCH5TE), xscale) +ARM_CORE("iwmmxt2", iwmmxt2, iwmmxt2, 5TE, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_STRONG | FL_XSCALE | FL_IWMMXT | FL_IWMMXT2 | FL_FOR_ARCH5TE), xscale) +ARM_CORE("fa606te", fa606te, fa606te, 5TE, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_FOR_ARCH5TE), 9e) +ARM_CORE("fa626te", fa626te, fa626te, 5TE, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_FOR_ARCH5TE), 9e) +ARM_CORE("fmp626", fmp626, fmp626, 5TE, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_FOR_ARCH5TE), 9e) +ARM_CORE("fa726te", fa726te, fa726te, 5TE, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_FOR_ARCH5TE), fa726te) /* V5TEJ Architecture Processors */ -ARM_CORE("arm926ej-s", arm926ejs, arm926ejs, 5TEJ, FL_LDSCHED, 9e) -ARM_CORE("arm1026ej-s", arm1026ejs, arm1026ejs, 5TEJ, FL_LDSCHED, 9e) +ARM_CORE("arm926ej-s", arm926ejs, arm926ejs, 5TEJ, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_FOR_ARCH5TEJ), 9e) +ARM_CORE("arm1026ej-s", arm1026ejs, arm1026ejs, 5TEJ, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_FOR_ARCH5TEJ), 9e) /* V6 Architecture Processors */ -ARM_CORE("arm1136j-s", arm1136js, arm1136js, 6J, FL_LDSCHED, 9e) -ARM_CORE("arm1136jf-s", arm1136jfs, arm1136jfs, 6J, FL_LDSCHED | FL_VFPV2, 9e) -ARM_CORE("arm1176jz-s", arm1176jzs, arm1176jzs, 6KZ, FL_LDSCHED, 9e) -ARM_CORE("arm1176jzf-s", arm1176jzfs, arm1176jzfs, 6KZ, FL_LDSCHED | FL_VFPV2, 9e) -ARM_CORE("mpcorenovfp", mpcorenovfp, mpcorenovfp, 6K, FL_LDSCHED, 9e) -ARM_CORE("mpcore", mpcore, mpcore, 6K, FL_LDSCHED | FL_VFPV2, 9e) -ARM_CORE("arm1156t2-s", arm1156t2s, arm1156t2s, 6T2, FL_LDSCHED, v6t2) -ARM_CORE("arm1156t2f-s", arm1156t2fs, arm1156t2fs, 6T2, FL_LDSCHED | FL_VFPV2, v6t2) +ARM_CORE("arm1136j-s", arm1136js, arm1136js, 6J, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_FOR_ARCH6J), 9e) +ARM_CORE("arm1136jf-s", arm1136jfs, arm1136jfs, 6J, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_VFPV2 | FL_FOR_ARCH6J), 9e) +ARM_CORE("arm1176jz-s", arm1176jzs, arm1176jzs, 6KZ, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_FOR_ARCH6KZ), 9e) +ARM_CORE("arm1176jzf-s", arm1176jzfs, arm1176jzfs, 6KZ, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_VFPV2 | FL_FOR_ARCH6KZ), 9e) +ARM_CORE("mpcorenovfp", mpcorenovfp, mpcorenovfp, 6K, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_FOR_ARCH6K), 9e) +ARM_CORE("mpcore", mpcore, mpcore, 6K, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_VFPV2 | FL_FOR_ARCH6K), 9e) +ARM_CORE("arm1156t2-s", arm1156t2s, arm1156t2s, 6T2, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_FOR_ARCH6T2), v6t2) +ARM_CORE("arm1156t2f-s", arm1156t2fs, arm1156t2fs, 6T2, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_VFPV2 | FL_FOR_ARCH6T2), v6t2) /* V6M Architecture Processors */ -ARM_CORE("cortex-m1", cortexm1, cortexm1, 6M, FL_LDSCHED, v6m) -ARM_CORE("cortex-m0", cortexm0, cortexm0, 6M, FL_LDSCHED, v6m) -ARM_CORE("cortex-m0plus", cortexm0plus, cortexm0plus, 6M, FL_LDSCHED, v6m) +ARM_CORE("cortex-m1", cortexm1, cortexm1, 6M, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_FOR_ARCH6M), v6m) +ARM_CORE("cortex-m0", cortexm0, cortexm0, 6M, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_FOR_ARCH6M), v6m) +ARM_CORE("cortex-m0plus", cortexm0plus, cortexm0plus, 6M, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_FOR_ARCH6M), v6m) /* V6M Architecture Processors for small-multiply implementations. */ -ARM_CORE("cortex-m1.small-multiply", cortexm1smallmultiply, cortexm1, 6M, FL_LDSCHED | FL_SMALLMUL, v6m) -ARM_CORE("cortex-m0.small-multiply", cortexm0smallmultiply, cortexm0, 6M, FL_LDSCHED | FL_SMALLMUL, v6m) -ARM_CORE("cortex-m0plus.small-multiply",cortexm0plussmallmultiply, cortexm0plus,6M, FL_LDSCHED | FL_SMALLMUL, v6m) +ARM_CORE("cortex-m1.small-multiply", cortexm1smallmultiply, cortexm1, 6M, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_SMALLMUL | FL_FOR_ARCH6M), v6m) +ARM_CORE("cortex-m0.small-multiply", cortexm0smallmultiply, cortexm0, 6M, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_SMALLMUL | FL_FOR_ARCH6M), v6m) +ARM_CORE("cortex-m0plus.small-multiply",cortexm0plussmallmultiply, cortexm0plus,6M, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_SMALLMUL | FL_FOR_ARCH6M), v6m) /* V7 Architecture Processors */ -ARM_CORE("generic-armv7-a", genericv7a, genericv7a, 7A, FL_LDSCHED, cortex) -ARM_CORE("cortex-a5", cortexa5, cortexa5, 7A, FL_LDSCHED, cortex_a5) -ARM_CORE("cortex-a7", cortexa7, cortexa7, 7A, FL_LDSCHED | FL_THUMB_DIV | FL_ARM_DIV, cortex_a7) -ARM_CORE("cortex-a8", cortexa8, cortexa8, 7A, FL_LDSCHED, cortex_a8) -ARM_CORE("cortex-a9", cortexa9, cortexa9, 7A, FL_LDSCHED, cortex_a9) -ARM_CORE("cortex-a12", cortexa12, cortexa17, 7A, FL_LDSCHED | FL_THUMB_DIV | FL_ARM_DIV, cortex_a12) -ARM_CORE("cortex-a15", cortexa15, cortexa15, 7A, FL_LDSCHED | FL_THUMB_DIV | FL_ARM_DIV, cortex_a15) -ARM_CORE("cortex-a17", cortexa17, cortexa17, 7A, FL_LDSCHED | FL_THUMB_DIV | FL_ARM_DIV, cortex_a12) -ARM_CORE("cortex-r4", cortexr4, cortexr4, 7R, FL_LDSCHED, cortex) -ARM_CORE("cortex-r4f", cortexr4f, cortexr4f, 7R, FL_LDSCHED, cortex) -ARM_CORE("cortex-r5", cortexr5, cortexr5, 7R, FL_LDSCHED | FL_ARM_DIV, cortex) -ARM_CORE("cortex-r7", cortexr7, cortexr7, 7R, FL_LDSCHED | FL_ARM_DIV, cortex) -ARM_CORE("cortex-m7", cortexm7, cortexm7, 7EM, FL_LDSCHED | FL_NO_VOLATILE_CE, cortex_m7) -ARM_CORE("cortex-m4", cortexm4, cortexm4, 7EM, FL_LDSCHED, v7m) -ARM_CORE("cortex-m3", cortexm3, cortexm3, 7M, FL_LDSCHED, v7m) -ARM_CORE("marvell-pj4", marvell_pj4, marvell_pj4, 7A, FL_LDSCHED, marvell_pj4) +ARM_CORE("generic-armv7-a", genericv7a, genericv7a, 7A, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_FOR_ARCH7A), cortex) +ARM_CORE("cortex-a5", cortexa5, cortexa5, 7A, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_FOR_ARCH7A), cortex_a5) +ARM_CORE("cortex-a7", cortexa7, cortexa7, 7A, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_THUMB_DIV | FL_ARM_DIV | FL_FOR_ARCH7A), cortex_a7) +ARM_CORE("cortex-a8", cortexa8, cortexa8, 7A, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_FOR_ARCH7A), cortex_a8) +ARM_CORE("cortex-a9", cortexa9, cortexa9, 7A, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_FOR_ARCH7A), cortex_a9) +ARM_CORE("cortex-a12", cortexa12, cortexa17, 7A, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_THUMB_DIV | FL_ARM_DIV | FL_FOR_ARCH7A), cortex_a12) +ARM_CORE("cortex-a15", cortexa15, cortexa15, 7A, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_THUMB_DIV | FL_ARM_DIV | FL_FOR_ARCH7A), cortex_a15) +ARM_CORE("cortex-a17", cortexa17, cortexa17, 7A, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_THUMB_DIV | FL_ARM_DIV | FL_FOR_ARCH7A), cortex_a12) +ARM_CORE("cortex-r4", cortexr4, cortexr4, 7R, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_FOR_ARCH7R), cortex) +ARM_CORE("cortex-r4f", cortexr4f, cortexr4f, 7R, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_FOR_ARCH7R), cortex) +ARM_CORE("cortex-r5", cortexr5, cortexr5, 7R, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_ARM_DIV | FL_FOR_ARCH7R), cortex) +ARM_CORE("cortex-r7", cortexr7, cortexr7, 7R, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_ARM_DIV | FL_FOR_ARCH7R), cortex) +ARM_CORE("cortex-m7", cortexm7, cortexm7, 7EM, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_NO_VOLATILE_CE | FL_FOR_ARCH7EM), cortex_m7) +ARM_CORE("cortex-m4", cortexm4, cortexm4, 7EM, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_FOR_ARCH7EM), v7m) +ARM_CORE("cortex-m3", cortexm3, cortexm3, 7M, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_FOR_ARCH7M), v7m) +ARM_CORE("marvell-pj4", marvell_pj4, marvell_pj4, 7A, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_FOR_ARCH7A), marvell_pj4) /* V7 big.LITTLE implementations */ -ARM_CORE("cortex-a15.cortex-a7", cortexa15cortexa7, cortexa7, 7A, FL_LDSCHED | FL_THUMB_DIV | FL_ARM_DIV, cortex_a15) -ARM_CORE("cortex-a17.cortex-a7", cortexa17cortexa7, cortexa7, 7A, FL_LDSCHED | FL_THUMB_DIV | FL_ARM_DIV, cortex_a12) +ARM_CORE("cortex-a15.cortex-a7", cortexa15cortexa7, cortexa7, 7A, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_THUMB_DIV | FL_ARM_DIV | FL_FOR_ARCH7A), cortex_a15) +ARM_CORE("cortex-a17.cortex-a7", cortexa17cortexa7, cortexa7, 7A, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_THUMB_DIV | FL_ARM_DIV | FL_FOR_ARCH7A), cortex_a12) /* V8 Architecture Processors */ -ARM_CORE("cortex-a53", cortexa53, cortexa53, 8A, FL_LDSCHED | FL_CRC32, cortex_a53) -ARM_CORE("cortex-a57", cortexa57, cortexa57, 8A, FL_LDSCHED | FL_CRC32, cortex_a57) -ARM_CORE("cortex-a72", cortexa72, cortexa57, 8A, FL_LDSCHED | FL_CRC32, cortex_a57) -ARM_CORE("exynos-m1", exynosm1, cortexa57, 8A, FL_LDSCHED | FL_CRC32, cortex_a57) -ARM_CORE("xgene1", xgene1, xgene1, 8A, FL_LDSCHED, xgene1) +ARM_CORE("cortex-a53", cortexa53, cortexa53, 8A, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_CRC32 | FL_FOR_ARCH8A), cortex_a53) +ARM_CORE("cortex-a57", cortexa57, cortexa57, 8A, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_CRC32 | FL_FOR_ARCH8A), cortex_a57) +ARM_CORE("cortex-a72", cortexa72, cortexa57, 8A, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_CRC32 | FL_FOR_ARCH8A), cortex_a57) +ARM_CORE("exynos-m1", exynosm1, cortexa57, 8A, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_CRC32 | FL_FOR_ARCH8A), cortex_a57) +ARM_CORE("xgene1", xgene1, xgene1, 8A, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_FOR_ARCH8A), xgene1) /* V8 big.LITTLE implementations */ -ARM_CORE("cortex-a57.cortex-a53", cortexa57cortexa53, cortexa53, 8A, FL_LDSCHED | FL_CRC32, cortex_a57) -ARM_CORE("cortex-a72.cortex-a53", cortexa72cortexa53, cortexa53, 8A, FL_LDSCHED | FL_CRC32, cortex_a57) +ARM_CORE("cortex-a57.cortex-a53", cortexa57cortexa53, cortexa53, 8A, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_CRC32 | FL_FOR_ARCH8A), cortex_a57) +ARM_CORE("cortex-a72.cortex-a53", cortexa72cortexa53, cortexa53, 8A, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_CRC32 | FL_FOR_ARCH8A), cortex_a57) diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h index cef9eec277d..8df312f3c67 100644 --- a/gcc/config/arm/arm-protos.h +++ b/gcc/config/arm/arm-protos.h @@ -319,6 +319,7 @@ extern int vfp3_const_double_for_bits (rtx); extern void arm_emit_coreregs_64bit_shift (enum rtx_code, rtx, rtx, rtx, rtx, rtx); +extern bool arm_valid_symbolic_address_p (rtx); extern bool arm_validize_comparison (rtx *, rtx *, rtx *); #endif /* RTX_CODE */ @@ -346,6 +347,8 @@ extern bool arm_is_constant_pool_ref (rtx); /* Flags used to identify the presence of processor capabilities. */ /* Bit values used to identify processor capabilities. */ +#define FL_NONE (0) /* No flags. */ +#define FL_ANY (0xffffffff) /* All flags. */ #define FL_CO_PROC (1 << 0) /* Has external co-processor bus */ #define FL_ARCH3M (1 << 1) /* Extended multiply */ #define FL_MODE26 (1 << 2) /* 26-bit mode support */ @@ -413,13 +416,116 @@ extern bool arm_is_constant_pool_ref (rtx); #define FL_FOR_ARCH7EM (FL_FOR_ARCH7M | FL_ARCH7EM) #define FL_FOR_ARCH8A (FL_FOR_ARCH7VE | FL_ARCH8) +/* There are too many feature bits to fit in a single word so the set of cpu and + fpu capabilities is a structure. A feature set is created and manipulated + with the ARM_FSET macros. */ + +typedef struct +{ + unsigned long cpu[2]; +} arm_feature_set; + + +/* Initialize a feature set. */ + +#define ARM_FSET_MAKE(CPU1,CPU2) { { (CPU1), (CPU2) } } + +#define ARM_FSET_MAKE_CPU1(CPU1) ARM_FSET_MAKE ((CPU1), (FL_NONE)) +#define ARM_FSET_MAKE_CPU2(CPU2) ARM_FSET_MAKE ((FL_NONE), (CPU2)) + +/* Accessors. */ + +#define ARM_FSET_CPU1(S) ((S).cpu[0]) +#define ARM_FSET_CPU2(S) ((S).cpu[1]) + +/* Useful combinations. */ + +#define ARM_FSET_EMPTY ARM_FSET_MAKE (FL_NONE, FL_NONE) +#define ARM_FSET_ANY ARM_FSET_MAKE (FL_ANY, FL_ANY) + +/* Tests for a specific CPU feature. */ + +#define ARM_FSET_HAS_CPU1(A, F) \ + (((A).cpu[0] & ((unsigned long)(F))) == ((unsigned long)(F))) +#define ARM_FSET_HAS_CPU2(A, F) \ + (((A).cpu[1] & ((unsigned long)(F))) == ((unsigned long)(F))) +#define ARM_FSET_HAS_CPU(A, F1, F2) \ + (ARM_FSET_HAS_CPU1 ((A), (F1)) && ARM_FSET_HAS_CPU2 ((A), (F2))) + +/* Add a feature to a feature set. */ + +#define ARM_FSET_ADD_CPU1(DST, F) \ + do { \ + (DST).cpu[0] |= (F); \ + } while (0) + +#define ARM_FSET_ADD_CPU2(DST, F) \ + do { \ + (DST).cpu[1] |= (F); \ + } while (0) + +/* Remove a feature from a feature set. */ + +#define ARM_FSET_DEL_CPU1(DST, F) \ + do { \ + (DST).cpu[0] &= ~(F); \ + } while (0) + +#define ARM_FSET_DEL_CPU2(DST, F) \ + do { \ + (DST).cpu[1] &= ~(F); \ + } while (0) + +/* Union of feature sets. */ + +#define ARM_FSET_UNION(DST,F1,F2) \ + do { \ + (DST).cpu[0] = (F1).cpu[0] | (F2).cpu[0]; \ + (DST).cpu[1] = (F1).cpu[1] | (F2).cpu[1]; \ + } while (0) + +/* Intersection of feature sets. */ + +#define ARM_FSET_INTER(DST,F1,F2) \ + do { \ + (DST).cpu[0] = (F1).cpu[0] & (F2).cpu[0]; \ + (DST).cpu[1] = (F1).cpu[1] & (F2).cpu[1]; \ + } while (0) + +/* Exclusive disjunction. */ + +#define ARM_FSET_XOR(DST,F1,F2) \ + do { \ + (DST).cpu[0] = (F1).cpu[0] ^ (F2).cpu[0]; \ + (DST).cpu[1] = (F1).cpu[1] ^ (F2).cpu[1]; \ + } while (0) + +/* Difference of feature sets: F1 excluding the elements of F2. */ + +#define ARM_FSET_EXCLUDE(DST,F1,F2) \ + do { \ + (DST).cpu[0] = (F1).cpu[0] & ~(F2).cpu[0]; \ + (DST).cpu[1] = (F1).cpu[1] & ~(F2).cpu[1]; \ + } while (0) + +/* Test for an empty feature set. */ + +#define ARM_FSET_IS_EMPTY(A) \ + (!((A).cpu[0]) && !((A).cpu[1])) + +/* Tests whether the cpu features of A are a subset of B. */ + +#define ARM_FSET_CPU_SUBSET(A,B) \ + ((((A).cpu[0] & (B).cpu[0]) == (A).cpu[0]) \ + && (((A).cpu[1] & (B).cpu[1]) == (A).cpu[1])) + /* The bits in this mask specify which instructions we are allowed to generate. */ -extern unsigned long insn_flags; +extern arm_feature_set insn_flags; /* The bits in this mask specify which instruction scheduling options should be used. */ -extern unsigned long tune_flags; +extern arm_feature_set tune_flags; /* Nonzero if this chip supports the ARM Architecture 3M extensions. */ extern int arm_arch3m; diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 57702cbc8de..fa4e083adfe 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -97,6 +97,7 @@ static void arm_add_gc_roots (void); static int arm_gen_constant (enum rtx_code, machine_mode, rtx, HOST_WIDE_INT, rtx, rtx, int, int); static unsigned bit_count (unsigned long); +static unsigned feature_count (const arm_feature_set*); static int arm_address_register_rtx_p (rtx, int); static int arm_legitimate_index_p (machine_mode, rtx, RTX_CODE, int); static bool is_called_in_ARM_mode (tree); @@ -767,11 +768,11 @@ static int thumb_call_reg_needed; /* The bits in this mask specify which instructions we are allowed to generate. */ -unsigned long insn_flags = 0; +arm_feature_set insn_flags = ARM_FSET_EMPTY; /* The bits in this mask specify which instruction scheduling options should be used. */ -unsigned long tune_flags = 0; +arm_feature_set tune_flags = ARM_FSET_EMPTY; /* The highest ARM architecture version supported by the target. */ @@ -927,7 +928,7 @@ struct processors enum processor_type core; const char *arch; enum base_architecture base_arch; - const unsigned long flags; + const arm_feature_set flags; const struct tune_params *const tune; }; @@ -2196,10 +2197,10 @@ static const struct processors all_cores[] = /* ARM Cores */ #define ARM_CORE(NAME, X, IDENT, ARCH, FLAGS, COSTS) \ {NAME, IDENT, #ARCH, BASE_ARCH_##ARCH, \ - FLAGS | FL_FOR_ARCH##ARCH, &arm_##COSTS##_tune}, + FLAGS, &arm_##COSTS##_tune}, #include "arm-cores.def" #undef ARM_CORE - {NULL, arm_none, NULL, BASE_ARCH_0, 0, NULL} + {NULL, arm_none, NULL, BASE_ARCH_0, ARM_FSET_EMPTY, NULL} }; static const struct processors all_architectures[] = @@ -2212,7 +2213,7 @@ static const struct processors all_architectures[] = {NAME, CORE, #ARCH, BASE_ARCH_##ARCH, FLAGS, NULL}, #include "arm-arches.def" #undef ARM_ARCH - {NULL, arm_none, NULL, BASE_ARCH_0, 0, NULL} + {NULL, arm_none, NULL, BASE_ARCH_0, ARM_FSET_EMPTY, NULL} }; @@ -2278,6 +2279,14 @@ bit_count (unsigned long value) return count; } +/* Return the number of features in feature-set SET. */ +static unsigned +feature_count (const arm_feature_set * set) +{ + return (bit_count (ARM_FSET_CPU1 (*set)) + + bit_count (ARM_FSET_CPU2 (*set))); +} + typedef struct { machine_mode mode; @@ -2703,7 +2712,7 @@ arm_option_check_internal (struct gcc_options *opts) /* Make sure that the processor choice does not conflict with any of the other command line choices. */ - if (TARGET_ARM_P (flags) && !(insn_flags & FL_NOTM)) + if (TARGET_ARM_P (flags) && !ARM_FSET_HAS_CPU1 (insn_flags, FL_NOTM)) error ("target CPU does not support ARM mode"); /* TARGET_BACKTRACE calls leaf_function_p, which causes a crash if done @@ -2803,7 +2812,8 @@ static void arm_option_override_internal (struct gcc_options *opts, struct gcc_options *opts_set) { - if (TARGET_THUMB_P (opts->x_target_flags) && !(insn_flags & FL_THUMB)) + if (TARGET_THUMB_P (opts->x_target_flags) + && !(ARM_FSET_HAS_CPU1 (insn_flags, FL_THUMB))) { warning (0, "target CPU does not support THUMB instructions"); opts->x_target_flags &= ~MASK_THUMB; @@ -2890,8 +2900,13 @@ arm_option_override (void) { if (arm_selected_cpu) { + const arm_feature_set tuning_flags = ARM_FSET_MAKE_CPU1 (FL_TUNE); + arm_feature_set selected_flags; + ARM_FSET_XOR (selected_flags, arm_selected_cpu->flags, + arm_selected_arch->flags); + ARM_FSET_EXCLUDE (selected_flags, selected_flags, tuning_flags); /* Check for conflict between mcpu and march. */ - if ((arm_selected_cpu->flags ^ arm_selected_arch->flags) & ~FL_TUNE) + if (!ARM_FSET_IS_EMPTY (selected_flags)) { warning (0, "switch -mcpu=%s conflicts with -march=%s switch", arm_selected_cpu->name, arm_selected_arch->name); @@ -2915,7 +2930,7 @@ arm_option_override (void) if (!arm_selected_cpu) { const struct processors * sel; - unsigned int sought; + arm_feature_set sought = ARM_FSET_EMPTY;; arm_selected_cpu = &all_cores[TARGET_CPU_DEFAULT]; if (!arm_selected_cpu->name) @@ -2935,26 +2950,27 @@ arm_option_override (void) /* Now check to see if the user has specified some command line switch that require certain abilities from the cpu. */ - sought = 0; if (TARGET_INTERWORK || TARGET_THUMB) { - sought |= (FL_THUMB | FL_MODE32); + ARM_FSET_ADD_CPU1 (sought, FL_THUMB); + ARM_FSET_ADD_CPU1 (sought, FL_MODE32); /* There are no ARM processors that support both APCS-26 and interworking. Therefore we force FL_MODE26 to be removed from insn_flags here (if it was set), so that the search below will always be able to find a compatible processor. */ - insn_flags &= ~FL_MODE26; + ARM_FSET_DEL_CPU1 (insn_flags, FL_MODE26); } - if (sought != 0 && ((sought & insn_flags) != sought)) + if (!ARM_FSET_IS_EMPTY (sought) + && !(ARM_FSET_CPU_SUBSET (sought, insn_flags))) { /* Try to locate a CPU type that supports all of the abilities of the default CPU, plus the extra abilities requested by the user. */ for (sel = all_cores; sel->name != NULL; sel++) - if ((sel->flags & sought) == (sought | insn_flags)) + if (ARM_FSET_CPU_SUBSET (sought, sel->flags)) break; if (sel->name == NULL) @@ -2974,19 +2990,23 @@ arm_option_override (void) command line options we scan the array again looking for a best match. */ for (sel = all_cores; sel->name != NULL; sel++) - if ((sel->flags & sought) == sought) - { - unsigned count; - - count = bit_count (sel->flags & insn_flags); - - if (count >= current_bit_count) - { - best_fit = sel; - current_bit_count = count; - } - } + { + arm_feature_set required = ARM_FSET_EMPTY; + ARM_FSET_UNION (required, sought, insn_flags); + if (ARM_FSET_CPU_SUBSET (required, sel->flags)) + { + unsigned count; + arm_feature_set flags; + ARM_FSET_INTER (flags, sel->flags, insn_flags); + count = feature_count (&flags); + if (count >= current_bit_count) + { + best_fit = sel; + current_bit_count = count; + } + } + } gcc_assert (best_fit); sel = best_fit; } @@ -3014,7 +3034,8 @@ arm_option_override (void) /* BPABI targets use linker tricks to allow interworking on cores without thumb support. */ - if (TARGET_INTERWORK && !((insn_flags & FL_THUMB) || TARGET_BPABI)) + if (TARGET_INTERWORK + && !(ARM_FSET_HAS_CPU1 (insn_flags, FL_THUMB) || TARGET_BPABI)) { warning (0, "target CPU does not support interworking" ); target_flags &= ~MASK_INTERWORK; @@ -3039,34 +3060,34 @@ arm_option_override (void) warning (0, "passing floating point arguments in fp regs not yet supported"); /* Initialize boolean versions of the flags, for use in the arm.md file. */ - arm_arch3m = (insn_flags & FL_ARCH3M) != 0; - arm_arch4 = (insn_flags & FL_ARCH4) != 0; - arm_arch4t = arm_arch4 & ((insn_flags & FL_THUMB) != 0); - arm_arch5 = (insn_flags & FL_ARCH5) != 0; - arm_arch5e = (insn_flags & FL_ARCH5E) != 0; - arm_arch6 = (insn_flags & FL_ARCH6) != 0; - arm_arch6k = (insn_flags & FL_ARCH6K) != 0; - arm_arch6kz = arm_arch6k && (insn_flags & FL_ARCH6KZ); - arm_arch_notm = (insn_flags & FL_NOTM) != 0; + arm_arch3m = ARM_FSET_HAS_CPU1 (insn_flags, FL_ARCH3M); + arm_arch4 = ARM_FSET_HAS_CPU1 (insn_flags, FL_ARCH4); + arm_arch4t = arm_arch4 && (ARM_FSET_HAS_CPU1 (insn_flags, FL_THUMB)); + arm_arch5 = ARM_FSET_HAS_CPU1 (insn_flags, FL_ARCH5); + arm_arch5e = ARM_FSET_HAS_CPU1 (insn_flags, FL_ARCH5E); + arm_arch6 = ARM_FSET_HAS_CPU1 (insn_flags, FL_ARCH6); + arm_arch6k = ARM_FSET_HAS_CPU1 (insn_flags, FL_ARCH6K); + arm_arch6kz = arm_arch6k && ARM_FSET_HAS_CPU1 (insn_flags, FL_ARCH6KZ); + arm_arch_notm = ARM_FSET_HAS_CPU1 (insn_flags, FL_NOTM); arm_arch6m = arm_arch6 && !arm_arch_notm; - arm_arch7 = (insn_flags & FL_ARCH7) != 0; - arm_arch7em = (insn_flags & FL_ARCH7EM) != 0; - arm_arch8 = (insn_flags & FL_ARCH8) != 0; - arm_arch_thumb2 = (insn_flags & FL_THUMB2) != 0; - arm_arch_xscale = (insn_flags & FL_XSCALE) != 0; - - arm_ld_sched = (tune_flags & FL_LDSCHED) != 0; - arm_tune_strongarm = (tune_flags & FL_STRONG) != 0; - arm_tune_wbuf = (tune_flags & FL_WBUF) != 0; - arm_tune_xscale = (tune_flags & FL_XSCALE) != 0; - arm_arch_iwmmxt = (insn_flags & FL_IWMMXT) != 0; - arm_arch_iwmmxt2 = (insn_flags & FL_IWMMXT2) != 0; - arm_arch_thumb_hwdiv = (insn_flags & FL_THUMB_DIV) != 0; - arm_arch_arm_hwdiv = (insn_flags & FL_ARM_DIV) != 0; - arm_arch_no_volatile_ce = (insn_flags & FL_NO_VOLATILE_CE) != 0; + arm_arch7 = ARM_FSET_HAS_CPU1 (insn_flags, FL_ARCH7); + arm_arch7em = ARM_FSET_HAS_CPU1 (insn_flags, FL_ARCH7EM); + arm_arch8 = ARM_FSET_HAS_CPU1 (insn_flags, FL_ARCH8); + arm_arch_thumb2 = ARM_FSET_HAS_CPU1 (insn_flags, FL_THUMB2); + arm_arch_xscale = ARM_FSET_HAS_CPU1 (insn_flags, FL_XSCALE); + + arm_ld_sched = ARM_FSET_HAS_CPU1 (tune_flags, FL_LDSCHED); + arm_tune_strongarm = ARM_FSET_HAS_CPU1 (tune_flags, FL_STRONG); + arm_tune_wbuf = ARM_FSET_HAS_CPU1 (tune_flags, FL_WBUF); + arm_tune_xscale = ARM_FSET_HAS_CPU1 (tune_flags, FL_XSCALE); + arm_arch_iwmmxt = ARM_FSET_HAS_CPU1 (insn_flags, FL_IWMMXT); + arm_arch_iwmmxt2 = ARM_FSET_HAS_CPU1 (insn_flags, FL_IWMMXT2); + arm_arch_thumb_hwdiv = ARM_FSET_HAS_CPU1 (insn_flags, FL_THUMB_DIV); + arm_arch_arm_hwdiv = ARM_FSET_HAS_CPU1 (insn_flags, FL_ARM_DIV); + arm_arch_no_volatile_ce = ARM_FSET_HAS_CPU1 (insn_flags, FL_NO_VOLATILE_CE); arm_tune_cortex_a9 = (arm_tune == cortexa9) != 0; - arm_arch_crc = (insn_flags & FL_CRC32) != 0; - arm_m_profile_small_mul = (insn_flags & FL_SMALLMUL) != 0; + arm_arch_crc = ARM_FSET_HAS_CPU1 (insn_flags, FL_CRC32); + arm_m_profile_small_mul = ARM_FSET_HAS_CPU1 (insn_flags, FL_SMALLMUL); /* V5 code we generate is completely interworking capable, so we turn off TARGET_INTERWORK here to avoid many tests later on. */ @@ -3158,7 +3179,7 @@ arm_option_override (void) /* For arm2/3 there is no need to do any scheduling if we are doing software floating-point. */ - if (TARGET_SOFT_FLOAT && (tune_flags & FL_MODE32) == 0) + if (TARGET_SOFT_FLOAT && !ARM_FSET_HAS_CPU1 (tune_flags, FL_MODE32)) flag_schedule_insns = flag_schedule_insns_after_reload = 0; /* Use the cp15 method if it is available. */ @@ -12607,22 +12628,12 @@ neon_vdup_constant (rtx vals) { machine_mode mode = GET_MODE (vals); machine_mode inner_mode = GET_MODE_INNER (mode); - int n_elts = GET_MODE_NUNITS (mode); - bool all_same = true; rtx x; - int i; if (GET_CODE (vals) != CONST_VECTOR || GET_MODE_SIZE (inner_mode) > 4) return NULL_RTX; - for (i = 0; i < n_elts; ++i) - { - x = XVECEXP (vals, 0, i); - if (i > 0 && !rtx_equal_p (x, XVECEXP (vals, 0, 0))) - all_same = false; - } - - if (!all_same) + if (!const_vec_duplicate_p (vals, &x)) /* The elements are not all the same. We could handle repeating patterns of a mode larger than INNER_MODE here (e.g. int8x8_t {0, C, 0, C, 0, C, 0, C} which can be loaded using @@ -12633,7 +12644,7 @@ neon_vdup_constant (rtx vals) single ARM register. This will be cheaper than a vector load. */ - x = copy_to_mode_reg (inner_mode, XVECEXP (vals, 0, 0)); + x = copy_to_mode_reg (inner_mode, x); return gen_rtx_VEC_DUPLICATE (mode, x); } @@ -12809,10 +12820,10 @@ bounds_check (rtx operand, HOST_WIDE_INT low, HOST_WIDE_INT high, if (lane < low || lane >= high) { if (exp) - error ("%K%s %lld out of range %lld - %lld", + error ("%K%s %wd out of range %wd - %wd", exp, desc, lane, low, high - 1); else - error ("%s %lld out of range %lld - %lld", desc, lane, low, high - 1); + error ("%s %wd out of range %wd - %wd", desc, lane, low, high - 1); } } @@ -28674,6 +28685,38 @@ arm_emit_coreregs_64bit_shift (enum rtx_code code, rtx out, rtx in, #undef BRANCH } +/* Returns true if the pattern is a valid symbolic address, which is either a + symbol_ref or (symbol_ref + addend). + + According to the ARM ELF ABI, the initial addend of REL-type relocations + processing MOVW and MOVT instructions is formed by interpreting the 16-bit + literal field of the instruction as a 16-bit signed value in the range + -32768 <= A < 32768. */ + +bool +arm_valid_symbolic_address_p (rtx addr) +{ + rtx xop0, xop1 = NULL_RTX; + rtx tmp = addr; + + if (GET_CODE (tmp) == SYMBOL_REF || GET_CODE (tmp) == LABEL_REF) + return true; + + /* (const (plus: symbol_ref const_int)) */ + if (GET_CODE (addr) == CONST) + tmp = XEXP (addr, 0); + + if (GET_CODE (tmp) == PLUS) + { + xop0 = XEXP (tmp, 0); + xop1 = XEXP (tmp, 1); + + if (GET_CODE (xop0) == SYMBOL_REF && CONST_INT_P (xop1)) + return IN_RANGE (INTVAL (xop1), -0x8000, 0x7fff); + } + + return false; +} /* Returns true if a valid comparison operation and makes the operands in a form that is valid. */ diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index 288bbb9f836..b6c20478f9c 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -5774,7 +5774,7 @@ [(set (match_operand:SI 0 "nonimmediate_operand" "=r") (lo_sum:SI (match_operand:SI 1 "nonimmediate_operand" "0") (match_operand:SI 2 "general_operand" "i")))] - "arm_arch_thumb2" + "arm_arch_thumb2 && arm_valid_symbolic_address_p (operands[2])" "movt%?\t%0, #:upper16:%c2" [(set_attr "predicable" "yes") (set_attr "predicable_short_it" "no") @@ -8162,8 +8162,7 @@ size += GET_MODE_SIZE (GET_MODE (src)); } - emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL, - const0_rtx)); + emit_call_insn (gen_call_value (par, operands[0], const0_rtx, NULL)); size = 0; diff --git a/gcc/config/arm/arm_neon.h b/gcc/config/arm/arm_neon.h index c923e294cda..2b30be61a46 100644 --- a/gcc/config/arm/arm_neon.h +++ b/gcc/config/arm/arm_neon.h @@ -41,7 +41,9 @@ typedef __simd64_int8_t int8x8_t; typedef __simd64_int16_t int16x4_t; typedef __simd64_int32_t int32x2_t; typedef __builtin_neon_di int64x1_t; +#if defined (__ARM_FP16_FORMAT_IEEE) || defined (__ARM_FP16_FORMAT_ALTERNATIVE) typedef __simd64_float16_t float16x4_t; +#endif typedef __simd64_float32_t float32x2_t; typedef __simd64_poly8_t poly8x8_t; typedef __simd64_poly16_t poly16x4_t; @@ -6220,21 +6222,25 @@ vcvtq_u32_f32 (float32x4_t __a) } #if ((__ARM_FP & 0x2) != 0) +#if defined (__ARM_FP16_FORMAT_IEEE) || defined (__ARM_FP16_FORMAT_ALTERNATIVE) __extension__ static __inline float16x4_t __attribute__ ((__always_inline__)) vcvt_f16_f32 (float32x4_t __a) { return (float16x4_t)__builtin_neon_vcvtv4hfv4sf (__a); } - #endif +#endif + #if ((__ARM_FP & 0x2) != 0) +#if defined (__ARM_FP16_FORMAT_IEEE) || defined (__ARM_FP16_FORMAT_ALTERNATIVE) __extension__ static __inline float32x4_t __attribute__ ((__always_inline__)) vcvt_f32_f16 (float16x4_t __a) { return (float32x4_t)__builtin_neon_vcvtv4sfv4hf (__a); } - #endif +#endif + __extension__ static __inline int32x2_t __attribute__ ((__always_inline__)) vcvt_n_s32_f32 (float32x2_t __a, const int __b) { diff --git a/gcc/config/arm/constraints.md b/gcc/config/arm/constraints.md index 42935a4ca6d..e24858fe45e 100644 --- a/gcc/config/arm/constraints.md +++ b/gcc/config/arm/constraints.md @@ -21,7 +21,7 @@ ;; The following register constraints have been used: ;; - in ARM/Thumb-2 state: t, w, x, y, z ;; - in Thumb state: h, b -;; - in both states: l, c, k, q, US +;; - in both states: l, c, k, q, Cs, Ts, US ;; In ARM state, 'l' is an alias for 'r' ;; 'f' and 'v' were previously used for FPA and MAVERICK registers. @@ -67,7 +67,8 @@ (define_constraint "j" "A constant suitable for a MOVW instruction. (ARM/Thumb-2)" (and (match_test "TARGET_32BIT && arm_arch_thumb2") - (ior (match_code "high") + (ior (and (match_code "high") + (match_test "arm_valid_symbolic_address_p (XEXP (op, 0))")) (and (match_code "const_int") (match_test "(ival & 0xffff0000) == 0"))))) diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c index 3c477bc8eee..bec9a8bb788 100644 --- a/gcc/config/avr/avr.c +++ b/gcc/config/avr/avr.c @@ -9255,10 +9255,10 @@ avr_pgm_check_var_decl (tree node) { if (TYPE_P (node)) error ("%qT uses address space %qs beyond flash of %d KiB", - node, avr_addrspace[as].name, avr_n_flash); + node, avr_addrspace[as].name, 64 * avr_n_flash); else error ("%s %q+D uses address space %qs beyond flash of %d KiB", - reason, node, avr_addrspace[as].name, avr_n_flash); + reason, node, avr_addrspace[as].name, 64 * avr_n_flash); } else { @@ -9305,7 +9305,7 @@ avr_insert_attributes (tree node, tree *attributes) if (avr_addrspace[as].segment >= avr_n_flash) { error ("variable %q+D located in address space %qs beyond flash " - "of %d KiB", node, avr_addrspace[as].name, avr_n_flash); + "of %d KiB", node, avr_addrspace[as].name, 64 * avr_n_flash); } else if (!AVR_HAVE_LPM && avr_addrspace[as].pointer_size > 2) { diff --git a/gcc/config/cr16/cr16.c b/gcc/config/cr16/cr16.c index 8185b59b282..7b3b6efd3db 100644 --- a/gcc/config/cr16/cr16.c +++ b/gcc/config/cr16/cr16.c @@ -583,7 +583,7 @@ cr16_function_arg (cumulative_args_t cum_v, machine_mode mode, /* function_arg () is called with this type just after all the args have had their registers assigned. The rtx that function_arg returns from this type is supposed to pass to 'gen_call' but currently it is not - implemented (see macro GEN_CALL). */ + implemented. */ if (type == void_type_node) return NULL_RTX; diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 05fa5e10ebf..c69c738caa0 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -436,7 +436,7 @@ struct processor_costs iamcu_cost = { COSTS_N_INSNS (3), /* cost of movsx */ COSTS_N_INSNS (2), /* cost of movzx */ 8, /* "large" insn */ - 6, /* MOVE_RATIO */ + 9, /* MOVE_RATIO */ 6, /* cost for loading QImode using movzbl */ {2, 4, 2}, /* cost of loading integer registers in QImode, HImode and SImode. @@ -25531,7 +25531,7 @@ ix86_expand_strlensi_unroll_1 (rtx out, rtx src, rtx align_rtx) /* Avoid branch in fixing the byte. */ tmpreg = gen_lowpart (QImode, tmpreg); - emit_insn (gen_addqi3_cc (tmpreg, tmpreg, tmpreg)); + emit_insn (gen_addqi3_cconly_overflow (tmpreg, tmpreg)); tmp = gen_rtx_REG (CCmode, FLAGS_REG); cmp = gen_rtx_LTU (VOIDmode, tmp, const0_rtx); emit_insn (ix86_gen_sub3_carry (out, out, GEN_INT (3), tmp, cmp)); @@ -39510,60 +39510,57 @@ rdseed_step: return target; case IX86_BUILTIN_SBB32: - icode = CODE_FOR_subsi3_carry; + icode = CODE_FOR_subborrowsi; mode0 = SImode; - goto addcarryx; + goto handlecarry; case IX86_BUILTIN_SBB64: - icode = CODE_FOR_subdi3_carry; + icode = CODE_FOR_subborrowdi; mode0 = DImode; - goto addcarryx; + goto handlecarry; case IX86_BUILTIN_ADDCARRYX32: - icode = TARGET_ADX ? CODE_FOR_adcxsi3 : CODE_FOR_addsi3_carry; + icode = CODE_FOR_addcarrysi; mode0 = SImode; - goto addcarryx; + goto handlecarry; case IX86_BUILTIN_ADDCARRYX64: - icode = TARGET_ADX ? CODE_FOR_adcxdi3 : CODE_FOR_adddi3_carry; + icode = CODE_FOR_addcarrydi; mode0 = DImode; -addcarryx: + handlecarry: arg0 = CALL_EXPR_ARG (exp, 0); /* unsigned char c_in. */ arg1 = CALL_EXPR_ARG (exp, 1); /* unsigned int src1. */ arg2 = CALL_EXPR_ARG (exp, 2); /* unsigned int src2. */ arg3 = CALL_EXPR_ARG (exp, 3); /* unsigned int *sum_out. */ - op0 = gen_reg_rtx (QImode); - - /* Generate CF from input operand. */ op1 = expand_normal (arg0); op1 = copy_to_mode_reg (QImode, convert_to_mode (QImode, op1, 1)); - emit_insn (gen_addqi3_cc (op0, op1, constm1_rtx)); - /* Gen ADCX instruction to compute X+Y+CF. */ op2 = expand_normal (arg1); - op3 = expand_normal (arg2); - - if (!REG_P (op2)) + if (!register_operand (op2, mode0)) op2 = copy_to_mode_reg (mode0, op2); - if (!REG_P (op3)) - op3 = copy_to_mode_reg (mode0, op3); - - op0 = gen_reg_rtx (mode0); - op4 = gen_rtx_REG (CCCmode, FLAGS_REG); - pat = gen_rtx_LTU (VOIDmode, op4, const0_rtx); - emit_insn (GEN_FCN (icode) (op0, op2, op3, op4, pat)); + op3 = expand_normal (arg2); + if (!register_operand (op3, mode0)) + op3 = copy_to_mode_reg (mode0, op3); - /* Store the result. */ op4 = expand_normal (arg3); if (!address_operand (op4, VOIDmode)) { op4 = convert_memory_address (Pmode, op4); op4 = copy_addr_to_reg (op4); } - emit_move_insn (gen_rtx_MEM (mode0, op4), op0); + + /* Generate CF from input operand. */ + emit_insn (gen_addqi3_cconly_overflow (op1, constm1_rtx)); + + /* Generate instruction that consumes CF. */ + op0 = gen_reg_rtx (mode0); + + op1 = gen_rtx_REG (CCCmode, FLAGS_REG); + pat = gen_rtx_LTU (mode0, op1, const0_rtx); + emit_insn (GEN_FCN (icode) (op0, op2, op3, op1, pat)); /* Return current CF value. */ if (target == 0) @@ -39571,6 +39568,10 @@ addcarryx: PUT_MODE (pat, QImode); emit_insn (gen_rtx_SET (target, pat)); + + /* Store the result. */ + emit_move_insn (gen_rtx_MEM (mode0, op4), op0); + return target; case IX86_BUILTIN_READ_FLAGS: diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index e6c2d30e507..7017913afe2 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -102,7 +102,6 @@ UNSPEC_SAHF UNSPEC_PARITY UNSPEC_FSTCW - UNSPEC_ADD_CARRY UNSPEC_FLDCW UNSPEC_REP UNSPEC_LD_MPIC ; load_macho_picbase @@ -848,8 +847,6 @@ (define_code_attr plusminus_mnemonic [(plus "add") (ss_plus "adds") (us_plus "addus") (minus "sub") (ss_minus "subs") (us_minus "subus")]) -(define_code_attr plusminus_carry_mnemonic - [(plus "adc") (minus "sbb")]) (define_code_attr multdiv_mnemonic [(mult "mul") (div "div")]) @@ -5317,46 +5314,21 @@ "ix86_binary_operator_ok (PLUS, <DWI>mode, operands)" "#" "reload_completed" - [(parallel [(set (reg:CC FLAGS_REG) - (unspec:CC [(match_dup 1) (match_dup 2)] - UNSPEC_ADD_CARRY)) + [(parallel [(set (reg:CCC FLAGS_REG) + (compare:CCC + (plus:DWIH (match_dup 1) (match_dup 2)) + (match_dup 1))) (set (match_dup 0) (plus:DWIH (match_dup 1) (match_dup 2)))]) (parallel [(set (match_dup 3) (plus:DWIH - (match_dup 4) (plus:DWIH (ltu:DWIH (reg:CC FLAGS_REG) (const_int 0)) - (match_dup 5)))) + (match_dup 4)) + (match_dup 5))) (clobber (reg:CC FLAGS_REG))])] "split_double_mode (<DWI>mode, &operands[0], 3, &operands[0], &operands[3]);") -(define_insn "*add<mode>3_cc" - [(set (reg:CC FLAGS_REG) - (unspec:CC - [(match_operand:SWI48 1 "nonimmediate_operand" "%0,0") - (match_operand:SWI48 2 "<general_operand>" "r<i>,rm")] - UNSPEC_ADD_CARRY)) - (set (match_operand:SWI48 0 "nonimmediate_operand" "=rm,r") - (plus:SWI48 (match_dup 1) (match_dup 2)))] - "ix86_binary_operator_ok (PLUS, <MODE>mode, operands)" - "add{<imodesuffix>}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "mode" "<MODE>")]) - -(define_insn "addqi3_cc" - [(set (reg:CC FLAGS_REG) - (unspec:CC - [(match_operand:QI 1 "nonimmediate_operand" "%0,0") - (match_operand:QI 2 "general_operand" "qn,qm")] - UNSPEC_ADD_CARRY)) - (set (match_operand:QI 0 "nonimmediate_operand" "=qm,q") - (plus:QI (match_dup 1) (match_dup 2)))] - "ix86_binary_operator_ok (PLUS, QImode, operands)" - "add{b}\t{%2, %0|%0, %2}" - [(set_attr "type" "alu") - (set_attr "mode" "QI")]) - (define_insn "*add<mode>_1" [(set (match_operand:SWI48 0 "nonimmediate_operand" "=r,rm,r,r") (plus:SWI48 @@ -6264,10 +6236,10 @@ (minus:DWIH (match_dup 1) (match_dup 2)))]) (parallel [(set (match_dup 3) (minus:DWIH - (match_dup 4) - (plus:DWIH - (ltu:DWIH (reg:CC FLAGS_REG) (const_int 0)) - (match_dup 5)))) + (minus:DWIH + (match_dup 4) + (ltu:DWIH (reg:CC FLAGS_REG) (const_int 0))) + (match_dup 5))) (clobber (reg:CC FLAGS_REG))])] "split_double_mode (<DWI>mode, &operands[0], 3, &operands[0], &operands[3]);") @@ -6431,29 +6403,17 @@ ;; Add with carry and subtract with borrow -(define_expand "<plusminus_insn><mode>3_carry" - [(parallel - [(set (match_operand:SWI 0 "nonimmediate_operand") - (plusminus:SWI - (match_operand:SWI 1 "nonimmediate_operand") - (plus:SWI (match_operator:SWI 4 "ix86_carry_flag_operator" - [(match_operand 3 "flags_reg_operand") - (const_int 0)]) - (match_operand:SWI 2 "<general_operand>")))) - (clobber (reg:CC FLAGS_REG))])] - "ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)") - -(define_insn "*<plusminus_insn><mode>3_carry" +(define_insn "add<mode>3_carry" [(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>") - (plusminus:SWI - (match_operand:SWI 1 "nonimmediate_operand" "<comm>0,0") + (plus:SWI (plus:SWI - (match_operator 3 "ix86_carry_flag_operator" - [(reg FLAGS_REG) (const_int 0)]) - (match_operand:SWI 2 "<general_operand>" "<r><i>,<r>m")))) + (match_operator:SWI 4 "ix86_carry_flag_operator" + [(match_operand 3 "flags_reg_operand") (const_int 0)]) + (match_operand:SWI 1 "nonimmediate_operand" "%0,0")) + (match_operand:SWI 2 "<general_operand>" "<r><i>,<r>m"))) (clobber (reg:CC FLAGS_REG))] "ix86_binary_operator_ok (PLUS, <MODE>mode, operands)" - "<plusminus_carry_mnemonic>{<imodesuffix>}\t{%2, %0|%0, %2}" + "adc{<imodesuffix>}\t{%2, %0|%0, %2}" [(set_attr "type" "alu") (set_attr "use_carry" "1") (set_attr "pent_pair" "pu") @@ -6462,10 +6422,11 @@ (define_insn "*addsi3_carry_zext" [(set (match_operand:DI 0 "register_operand" "=r") (zero_extend:DI - (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0") - (plus:SI (match_operator 3 "ix86_carry_flag_operator" - [(reg FLAGS_REG) (const_int 0)]) - (match_operand:SI 2 "x86_64_general_operand" "rme"))))) + (plus:SI + (plus:SI (match_operator:SI 3 "ix86_carry_flag_operator" + [(reg FLAGS_REG) (const_int 0)]) + (match_operand:SI 1 "register_operand" "%0")) + (match_operand:SI 2 "x86_64_general_operand" "rme")))) (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)" "adc{l}\t{%2, %k0|%k0, %2}" @@ -6474,45 +6435,96 @@ (set_attr "pent_pair" "pu") (set_attr "mode" "SI")]) +;; There is no point to generate ADCX instruction. ADC is shorter and faster. + +(define_insn "addcarry<mode>" + [(set (reg:CCC FLAGS_REG) + (compare:CCC + (plus:SWI48 + (plus:SWI48 + (match_operator:SWI48 4 "ix86_carry_flag_operator" + [(match_operand 3 "flags_reg_operand") (const_int 0)]) + (match_operand:SWI48 1 "nonimmediate_operand" "%0")) + (match_operand:SWI48 2 "nonimmediate_operand" "rm")) + (match_dup 1))) + (set (match_operand:SWI48 0 "register_operand" "=r") + (plus:SWI48 (plus:SWI48 (match_op_dup 4 + [(match_dup 3) (const_int 0)]) + (match_dup 1)) + (match_dup 2)))] + "ix86_binary_operator_ok (PLUS, <MODE>mode, operands)" + "adc{<imodesuffix>}\t{%2, %0|%0, %2}" + [(set_attr "type" "alu") + (set_attr "use_carry" "1") + (set_attr "pent_pair" "pu") + (set_attr "mode" "<MODE>")]) + +(define_insn "sub<mode>3_carry" + [(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>") + (minus:SWI + (minus:SWI + (match_operand:SWI 1 "nonimmediate_operand" "0,0") + (match_operator:SWI 4 "ix86_carry_flag_operator" + [(match_operand 3 "flags_reg_operand") (const_int 0)])) + (match_operand:SWI 2 "<general_operand>" "<r><i>,<r>m"))) + (clobber (reg:CC FLAGS_REG))] + "ix86_binary_operator_ok (MINUS, <MODE>mode, operands)" + "sbb{<imodesuffix>}\t{%2, %0|%0, %2}" + [(set_attr "type" "alu") + (set_attr "use_carry" "1") + (set_attr "pent_pair" "pu") + (set_attr "mode" "<MODE>")]) + (define_insn "*subsi3_carry_zext" [(set (match_operand:DI 0 "register_operand" "=r") (zero_extend:DI - (minus:SI (match_operand:SI 1 "register_operand" "0") - (plus:SI (match_operator 3 "ix86_carry_flag_operator" - [(reg FLAGS_REG) (const_int 0)]) - (match_operand:SI 2 "x86_64_general_operand" "rme"))))) + (minus:SI + (minus:SI + (match_operand:SI 1 "register_operand" "0") + (match_operator:SI 3 "ix86_carry_flag_operator" + [(reg FLAGS_REG) (const_int 0)])) + (match_operand:SI 2 "x86_64_general_operand" "rme")))) (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT && ix86_binary_operator_ok (MINUS, SImode, operands)" "sbb{l}\t{%2, %k0|%k0, %2}" [(set_attr "type" "alu") + (set_attr "use_carry" "1") (set_attr "pent_pair" "pu") (set_attr "mode" "SI")]) - -;; ADCX instruction -(define_insn "adcx<mode>3" +(define_insn "subborrow<mode>" [(set (reg:CCC FLAGS_REG) (compare:CCC + (match_operand:SWI48 1 "nonimmediate_operand" "0") (plus:SWI48 - (match_operand:SWI48 1 "nonimmediate_operand" "%0") - (plus:SWI48 - (match_operator 4 "ix86_carry_flag_operator" - [(match_operand 3 "flags_reg_operand") (const_int 0)]) - (match_operand:SWI48 2 "nonimmediate_operand" "rm"))) - (const_int 0))) + (match_operator:SWI48 4 "ix86_carry_flag_operator" + [(match_operand 3 "flags_reg_operand") (const_int 0)]) + (match_operand:SWI48 2 "nonimmediate_operand" "rm")))) (set (match_operand:SWI48 0 "register_operand" "=r") - (plus:SWI48 (match_dup 1) - (plus:SWI48 (match_op_dup 4 - [(match_dup 3) (const_int 0)]) - (match_dup 2))))] - "TARGET_ADX && ix86_binary_operator_ok (PLUS, <MODE>mode, operands)" - "adcx\t{%2, %0|%0, %2}" + (minus:SWI48 (minus:SWI48 (match_dup 1) + (match_op_dup 4 + [(match_dup 3) (const_int 0)])) + (match_dup 2)))] + "ix86_binary_operator_ok (MINUS, <MODE>mode, operands)" + "sbb{<imodesuffix>}\t{%2, %0|%0, %2}" [(set_attr "type" "alu") (set_attr "use_carry" "1") + (set_attr "pent_pair" "pu") (set_attr "mode" "<MODE>")]) ;; Overflow setting add instructions +(define_expand "addqi3_cconly_overflow" + [(parallel + [(set (reg:CCC FLAGS_REG) + (compare:CCC + (plus:QI + (match_operand:QI 0 "nonimmediate_operand") + (match_operand:QI 1 "general_operand")) + (match_dup 0))) + (clobber (match_scratch:QI 2))])] + "!(MEM_P (operands[0]) && MEM_P (operands[1]))") + (define_insn "*add<mode>3_cconly_overflow" [(set (reg:CCC FLAGS_REG) (compare:CCC @@ -8842,9 +8854,9 @@ (set (match_dup 0) (neg:DWIH (match_dup 1)))]) (parallel [(set (match_dup 2) - (plus:DWIH (match_dup 3) - (plus:DWIH (ltu:DWIH (reg:CC FLAGS_REG) (const_int 0)) - (const_int 0)))) + (plus:DWIH (plus:DWIH (ltu:DWIH (reg:CC FLAGS_REG) (const_int 0)) + (match_dup 3)) + (const_int 0))) (clobber (reg:CC FLAGS_REG))]) (parallel [(set (match_dup 2) diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md index a9c8623ada2..bc76a5b7cee 100644 --- a/gcc/config/i386/predicates.md +++ b/gcc/config/i386/predicates.md @@ -912,25 +912,9 @@ /* Return true if operand is a vector constant that is all ones. */ (define_predicate "vector_all_ones_operand" - (match_code "const_vector") -{ - int nunits = GET_MODE_NUNITS (mode); - - if (GET_CODE (op) == CONST_VECTOR - && CONST_VECTOR_NUNITS (op) == nunits) - { - int i; - for (i = 0; i < nunits; ++i) - { - rtx x = CONST_VECTOR_ELT (op, i); - if (x != constm1_rtx) - return false; - } - return true; - } - - return false; -}) + (and (match_code "const_vector") + (match_test "INTEGRAL_MODE_P (GET_MODE (op))") + (match_test "op == CONSTM1_RTX (GET_MODE (op))"))) ; Return true when OP is operand acceptable for standard SSE move. (define_predicate "vector_move_operand" diff --git a/gcc/config/iq2000/iq2000.md b/gcc/config/iq2000/iq2000.md index e87cb6802e3..bba67600d96 100644 --- a/gcc/config/iq2000/iq2000.md +++ b/gcc/config/iq2000/iq2000.md @@ -1708,7 +1708,7 @@ { int i; - emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx)); + emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx)); for (i = 0; i < XVECLEN (operands[2], 0); i++) { diff --git a/gcc/config/m32c/blkmov.md b/gcc/config/m32c/blkmov.md index 88d04066d16..02ad3455bd1 100644 --- a/gcc/config/m32c/blkmov.md +++ b/gcc/config/m32c/blkmov.md @@ -178,10 +178,10 @@ ;; 3 = alignment (define_expand "cmpstrsi" - [(match_operand:HI 0 "" "") - (match_operand 1 "ap_operand" "") - (match_operand 2 "ap_operand" "") - (match_operand 3 "" "") + [(match_operand:HI 0 "register_operand" "") + (match_operand 1 "memory_operand" "") + (match_operand 2 "memory_operand" "") + (match_operand 3 "const_int_operand" "") ] "TARGET_A24" "if (m32c_expand_cmpstr(operands)) DONE; FAIL;" diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md index 7f4195a9f2f..463c8277b43 100644 --- a/gcc/config/m68k/m68k.md +++ b/gcc/config/m68k/m68k.md @@ -6908,7 +6908,7 @@ { int i; - emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx)); + emit_call_insn (gen_call (operands[0], const0_rtx)); for (i = 0; i < XVECLEN (operands[2], 0); i++) { diff --git a/gcc/config/microblaze/microblaze.c b/gcc/config/microblaze/microblaze.c index 40a659a8d7b..6e7745ad137 100644 --- a/gcc/config/microblaze/microblaze.c +++ b/gcc/config/microblaze/microblaze.c @@ -661,7 +661,7 @@ microblaze_classify_unspec (struct microblaze_address_info *info, rtx x) else if (XINT (x, 1) == UNSPEC_TLS) { info->type = ADDRESS_TLS; - info->tls_type = tls_reloc INTVAL(XVECEXP(x, 0, 1)); + info->tls_type = tls_reloc (INTVAL (XVECEXP (x, 0, 1))); } else { diff --git a/gcc/config/mips/mips-opts.h b/gcc/config/mips/mips-opts.h index 79882051595..3c2c6590e3d 100644 --- a/gcc/config/mips/mips-opts.h +++ b/gcc/config/mips/mips-opts.h @@ -47,4 +47,10 @@ enum mips_r10k_cache_barrier_setting { #define MIPS_ARCH_OPTION_FROM_ABI -1 #define MIPS_ARCH_OPTION_NATIVE -2 +/* Enumerates the setting of the -mcompact-branches= option. */ +enum mips_cb_setting { + MIPS_CB_NEVER, + MIPS_CB_OPTIMAL, + MIPS_CB_ALWAYS +}; #endif diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h index d9ad9100f99..8a9ae0147ed 100644 --- a/gcc/config/mips/mips-protos.h +++ b/gcc/config/mips/mips-protos.h @@ -298,6 +298,9 @@ extern const char *mips_output_conditional_branch (rtx_insn *, rtx *, const char *, const char *); extern const char *mips_output_order_conditional_branch (rtx_insn *, rtx *, bool); +extern const char *mips_output_equal_conditional_branch (rtx_insn *, rtx *, + bool); +extern const char *mips_output_jump (rtx *, int, int, bool); extern const char *mips_output_sync (void); extern const char *mips_output_sync_loop (rtx_insn *, rtx *); extern unsigned int mips_sync_loop_insns (rtx_insn *, rtx *); diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 401d73bfeaa..0e0ecf232d9 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -176,7 +176,8 @@ along with GCC; see the file COPYING3. If not see /* Return the opcode to jump to register DEST. When the JR opcode is not available use JALR $0, DEST. */ #define MIPS_JR(DEST) \ - (((DEST) << 21) | (ISA_HAS_JR ? 0x8 : 0x9)) + (TARGET_CB_ALWAYS ? ((0x1b << 27) | ((DEST) << 16)) \ + : (((DEST) << 21) | (ISA_HAS_JR ? 0x8 : 0x9))) /* Return the opcode for: @@ -5181,7 +5182,8 @@ mips_allocate_fcc (machine_mode mode) conditions are: - EQ or NE between two registers. - - any comparison between a register and zero. */ + - any comparison between a register and zero. + - if compact branches are available then any condition is valid. */ static void mips_emit_compare (enum rtx_code *code, rtx *op0, rtx *op1, bool need_eq_ne_p) @@ -5203,6 +5205,44 @@ mips_emit_compare (enum rtx_code *code, rtx *op0, rtx *op1, bool need_eq_ne_p) else *op1 = force_reg (GET_MODE (cmp_op0), cmp_op1); } + else if (!need_eq_ne_p && TARGET_CB_MAYBE) + { + bool swap = false; + switch (*code) + { + case LE: + swap = true; + *code = GE; + break; + case GT: + swap = true; + *code = LT; + break; + case LEU: + swap = true; + *code = GEU; + break; + case GTU: + swap = true; + *code = LTU; + break; + case GE: + case LT: + case GEU: + case LTU: + /* Do nothing. */ + break; + default: + gcc_unreachable (); + } + *op1 = force_reg (GET_MODE (cmp_op0), cmp_op1); + if (swap) + { + rtx tmp = *op1; + *op1 = *op0; + *op0 = tmp; + } + } else { /* The comparison needs a separate scc instruction. Store the @@ -7260,7 +7300,7 @@ mips16_build_call_stub (rtx retval, rtx *fn_ptr, rtx args_size, int fp_code) if (fp_ret_p) { /* Now call the non-MIPS16 function. */ - output_asm_insn (MIPS_CALL ("jal", &fn, 0, -1), &fn); + output_asm_insn (mips_output_jump (&fn, 0, -1, true), &fn); fprintf (asm_out_file, "\t.cfi_register 31,18\n"); /* Move the result from floating-point registers to @@ -7630,12 +7670,22 @@ mips_block_move_straight (rtx dest, rtx src, HOST_WIDE_INT length) half-word alignment, it is usually better to move in half words. For instance, lh/lh/sh/sh is usually better than lwl/lwr/swl/swr and lw/lw/sw/sw is usually better than ldl/ldr/sdl/sdr. - Otherwise move word-sized chunks. */ - if (MEM_ALIGN (src) == BITS_PER_WORD / 2 - && MEM_ALIGN (dest) == BITS_PER_WORD / 2) - bits = BITS_PER_WORD / 2; + Otherwise move word-sized chunks. + + For ISA_HAS_LWL_LWR we rely on the lwl/lwr & swl/swr load. Otherwise + picking the minimum of alignment or BITS_PER_WORD gets us the + desired size for bits. */ + + if (!ISA_HAS_LWL_LWR) + bits = MIN (BITS_PER_WORD, MIN (MEM_ALIGN (src), MEM_ALIGN (dest))); else - bits = BITS_PER_WORD; + { + if (MEM_ALIGN (src) == BITS_PER_WORD / 2 + && MEM_ALIGN (dest) == BITS_PER_WORD / 2) + bits = BITS_PER_WORD / 2; + else + bits = BITS_PER_WORD; + } mode = mode_for_size (bits, MODE_INT, 0); delta = bits / BITS_PER_UNIT; @@ -7754,8 +7804,9 @@ mips_block_move_loop (rtx dest, rtx src, HOST_WIDE_INT length, bool mips_expand_block_move (rtx dest, rtx src, rtx length) { - /* Disable entirely for R6 initially. */ - if (!ISA_HAS_LWL_LWR) + if (!ISA_HAS_LWL_LWR + && (MEM_ALIGN (src) < MIPS_MIN_MOVE_MEM_ALIGN + || MEM_ALIGN (dest) < MIPS_MIN_MOVE_MEM_ALIGN)) return false; if (CONST_INT_P (length)) @@ -8367,7 +8418,7 @@ mips_pop_asm_switch (struct mips_asm_switch *asm_switch) '!' Print "s" to use the short version if the delay slot contains a 16-bit instruction. - See also mips_init_print_operand_pucnt. */ + See also mips_init_print_operand_punct. */ static void mips_print_operand_punctuation (FILE *file, int ch) @@ -8451,7 +8502,8 @@ mips_print_operand_punctuation (FILE *file, int ch) case ':': /* When final_sequence is 0, the delay slot will be a nop. We can - use the compact version for microMIPS. */ + use the compact version where available. The %: formatter will + only be present if a compact form of the branch is available. */ if (final_sequence == 0) putc ('c', file); break; @@ -8459,8 +8511,9 @@ mips_print_operand_punctuation (FILE *file, int ch) case '!': /* If the delay slot instruction is short, then use the compact version. */ - if (final_sequence == 0 - || get_attr_length (final_sequence->insn (1)) == 2) + if (TARGET_MICROMIPS && !TARGET_INTERLINK_COMPRESSED && mips_isa_rev <= 5 + && (final_sequence == 0 + || get_attr_length (final_sequence->insn (1)) == 2)) putc ('s', file); break; @@ -12958,6 +13011,7 @@ mips_adjust_insn_length (rtx_insn *insn, int length) break; case HAZARD_DELAY: + case HAZARD_FORBIDDEN_SLOT: length += NOP_INSN_LENGTH; break; @@ -12969,6 +13023,78 @@ mips_adjust_insn_length (rtx_insn *insn, int length) return length; } +/* Return the asm template for a call. OPERANDS are the operands, TARGET_OPNO + is the operand number of the target. SIZE_OPNO is the operand number of + the argument size operand that can optionally hold the call attributes. If + SIZE_OPNO is not -1 and the call is indirect, use the function symbol from + the call attributes to attach a R_MIPS_JALR relocation to the call. LINK_P + indicates whether the jump is a call and needs to set the link register. + + When generating GOT code without explicit relocation operators, all calls + should use assembly macros. Otherwise, all indirect calls should use "jr" + or "jalr"; we will arrange to restore $gp afterwards if necessary. Finally, + we can only generate direct calls for -mabicalls by temporarily switching + to non-PIC mode. + + For microMIPS jal(r), we try to generate jal(r)s when a 16-bit + instruction is in the delay slot of jal(r). + + Where compact branches are available, we try to use them if the delay slot + has a NOP (or equivalently delay slots were not enabled for the instruction + anyway). */ + +const char * +mips_output_jump (rtx *operands, int target_opno, int size_opno, bool link_p) +{ + static char buffer[300]; + char *s = buffer; + bool reg_p = REG_P (operands[target_opno]); + + const char *and_link = link_p ? "al" : ""; + const char *reg = reg_p ? "r" : ""; + const char *compact = ""; + const char *nop = "%/"; + const char *short_delay = link_p ? "%!" : ""; + const char *insn_name = TARGET_CB_NEVER || reg_p ? "j" : "b"; + + /* Compact branches can only be described when the ISA has support for them + as both the compact formatter '%:' and the delay slot NOP formatter '%/' + work as a mutually exclusive pair. I.e. a NOP is never required if a + compact form is available. */ + if (!final_sequence + && (TARGET_CB_MAYBE + || (ISA_HAS_JRC && !link_p && reg_p))) + { + compact = "c"; + nop = ""; + } + + if (TARGET_USE_GOT && !TARGET_EXPLICIT_RELOCS) + sprintf (s, "%%*%s%s\t%%%d%%/", insn_name, and_link, target_opno); + else + { + if (!reg_p && TARGET_ABICALLS_PIC2) + s += sprintf (s, ".option\tpic0\n\t"); + + if (reg_p && mips_get_pic_call_symbol (operands, size_opno)) + { + s += sprintf (s, "%%*.reloc\t1f,R_MIPS_JALR,%%%d\n1:\t", size_opno); + /* Not sure why this shouldn't permit a short delay but it did not + allow it before so we still don't allow it. */ + short_delay = ""; + } + else + s += sprintf (s, "%%*"); + + s += sprintf (s, "%s%s%s%s%s\t%%%d%s", insn_name, and_link, reg, compact, short_delay, + target_opno, nop); + + if (!reg_p && TARGET_ABICALLS_PIC2) + s += sprintf (s, "\n\t.option\tpic2"); + } + return buffer; +} + /* Return the assembly code for INSN, which has the operands given by OPERANDS, and which branches to OPERANDS[0] if some condition is true. BRANCH_IF_TRUE is the asm template that should be used if OPERANDS[0] @@ -13022,12 +13148,25 @@ mips_output_conditional_branch (rtx_insn *insn, rtx *operands, } /* Output the unconditional branch to TAKEN. */ - if (TARGET_ABSOLUTE_JUMPS) + if (TARGET_ABSOLUTE_JUMPS && TARGET_CB_MAYBE) + { + /* Add a hazard nop. */ + if (!final_sequence) + { + output_asm_insn ("nop\t\t# hazard nop", 0); + fprintf (asm_out_file, "\n"); + } + output_asm_insn (MIPS_ABSOLUTE_JUMP ("bc\t%0"), &taken); + } + else if (TARGET_ABSOLUTE_JUMPS) output_asm_insn (MIPS_ABSOLUTE_JUMP ("j\t%0%/"), &taken); else { mips_output_load_label (taken); - output_asm_insn ("jr\t%@%]%/", 0); + if (TARGET_CB_MAYBE) + output_asm_insn ("jrc\t%@%]", 0); + else + output_asm_insn ("jr\t%@%]%/", 0); } /* Now deal with its delay slot; see above. */ @@ -13041,7 +13180,7 @@ mips_output_conditional_branch (rtx_insn *insn, rtx *operands, asm_out_file, optimize, 1, NULL); final_sequence->insn (1)->set_deleted (); } - else + else if (TARGET_CB_NEVER) output_asm_insn ("nop", 0); fprintf (asm_out_file, "\n"); } @@ -13053,42 +13192,155 @@ mips_output_conditional_branch (rtx_insn *insn, rtx *operands, } /* Return the assembly code for INSN, which branches to OPERANDS[0] + if some equality condition is true. The condition is given by + OPERANDS[1] if !INVERTED_P, otherwise it is the inverse of + OPERANDS[1]. OPERANDS[2] is the comparison's first operand; + OPERANDS[3] is the second operand and may be zero or a register. */ + +const char * +mips_output_equal_conditional_branch (rtx_insn* insn, rtx *operands, + bool inverted_p) +{ + const char *branch[2]; + /* For a simple BNEZ or BEQZ microMIPSr3 branch. */ + if (TARGET_MICROMIPS + && mips_isa_rev <= 5 + && operands[3] == const0_rtx + && get_attr_length (insn) <= 8) + { + if (mips_cb == MIPS_CB_OPTIMAL) + { + branch[!inverted_p] = "%*b%C1z%:\t%2,%0"; + branch[inverted_p] = "%*b%N1z%:\t%2,%0"; + } + else + { + branch[!inverted_p] = "%*b%C1z\t%2,%0%/"; + branch[inverted_p] = "%*b%N1z\t%2,%0%/"; + } + } + else if (TARGET_CB_MAYBE) + { + if (operands[3] == const0_rtx) + { + branch[!inverted_p] = MIPS_BRANCH_C ("b%C1z", "%2,%0"); + branch[inverted_p] = MIPS_BRANCH_C ("b%N1z", "%2,%0"); + } + else if (REGNO (operands[2]) != REGNO (operands[3])) + { + branch[!inverted_p] = MIPS_BRANCH_C ("b%C1", "%2,%3,%0"); + branch[inverted_p] = MIPS_BRANCH_C ("b%N1", "%2,%3,%0"); + } + else + { + /* This case is degenerate. It should not happen, but does. */ + if (GET_CODE (operands[1]) == NE) + inverted_p = !inverted_p; + + branch[!inverted_p] = MIPS_BRANCH_C ("b", "%0"); + branch[inverted_p] = "%*\t\t# branch never"; + } + } + else + { + branch[!inverted_p] = MIPS_BRANCH ("b%C1", "%2,%z3,%0"); + branch[inverted_p] = MIPS_BRANCH ("b%N1", "%2,%z3,%0"); + } + + return mips_output_conditional_branch (insn, operands, branch[1], branch[0]); +} + +/* Return the assembly code for INSN, which branches to OPERANDS[0] if some ordering condition is true. The condition is given by OPERANDS[1] if !INVERTED_P, otherwise it is the inverse of OPERANDS[1]. OPERANDS[2] is the comparison's first operand; - its second is always zero. */ + OPERANDS[3] is the second operand and may be zero or a register. */ const char * -mips_output_order_conditional_branch (rtx_insn *insn, rtx *operands, bool inverted_p) +mips_output_order_conditional_branch (rtx_insn *insn, rtx *operands, + bool inverted_p) { const char *branch[2]; /* Make BRANCH[1] branch to OPERANDS[0] when the condition is true. Make BRANCH[0] branch on the inverse condition. */ - switch (GET_CODE (operands[1])) + if (operands[3] != const0_rtx) { - /* These cases are equivalent to comparisons against zero. */ - case LEU: - inverted_p = !inverted_p; - /* Fall through. */ - case GTU: - branch[!inverted_p] = MIPS_BRANCH ("bne", "%2,%.,%0"); - branch[inverted_p] = MIPS_BRANCH ("beq", "%2,%.,%0"); - break; + /* Handle degenerate cases that should not, but do, occur. */ + if (REGNO (operands[2]) == REGNO (operands[3])) + { + switch (GET_CODE (operands[1])) + { + case LT: + case LTU: + inverted_p = !inverted_p; + /* Fall through. */ + case GE: + case GEU: + branch[!inverted_p] = MIPS_BRANCH_C ("b", "%0"); + branch[inverted_p] = "%*\t\t# branch never"; + break; + default: + gcc_unreachable (); + } + } + else + { + branch[!inverted_p] = MIPS_BRANCH_C ("b%C1", "%2,%3,%0"); + branch[inverted_p] = MIPS_BRANCH_C ("b%N1", "%2,%3,%0"); + } + } + else + { + switch (GET_CODE (operands[1])) + { + /* These cases are equivalent to comparisons against zero. */ + case LEU: + inverted_p = !inverted_p; + /* Fall through. */ + case GTU: + if (TARGET_CB_MAYBE) + { + branch[!inverted_p] = MIPS_BRANCH_C ("bnez", "%2,%0"); + branch[inverted_p] = MIPS_BRANCH_C ("beqz", "%2,%0"); + } + else + { + branch[!inverted_p] = MIPS_BRANCH ("bne", "%2,%.,%0"); + branch[inverted_p] = MIPS_BRANCH ("beq", "%2,%.,%0"); + } + break; - /* These cases are always true or always false. */ - case LTU: - inverted_p = !inverted_p; - /* Fall through. */ - case GEU: - branch[!inverted_p] = MIPS_BRANCH ("beq", "%.,%.,%0"); - branch[inverted_p] = MIPS_BRANCH ("bne", "%.,%.,%0"); - break; + /* These cases are always true or always false. */ + case LTU: + inverted_p = !inverted_p; + /* Fall through. */ + case GEU: + if (TARGET_CB_MAYBE) + { + branch[!inverted_p] = MIPS_BRANCH_C ("b", "%0"); + branch[inverted_p] = "%*\t\t# branch never"; + } + else + { + branch[!inverted_p] = MIPS_BRANCH ("beq", "%.,%.,%0"); + branch[inverted_p] = MIPS_BRANCH ("bne", "%.,%.,%0"); + } + break; - default: - branch[!inverted_p] = MIPS_BRANCH ("b%C1z", "%2,%0"); - branch[inverted_p] = MIPS_BRANCH ("b%N1z", "%2,%0"); - break; + default: + if (TARGET_CB_MAYBE) + { + branch[!inverted_p] = MIPS_BRANCH_C ("b%C1z", "%2,%0"); + branch[inverted_p] = MIPS_BRANCH_C ("b%N1z", "%2,%0"); + } + else + { + branch[!inverted_p] = MIPS_BRANCH ("b%C1z", "%2,%0"); + branch[inverted_p] = MIPS_BRANCH ("b%N1z", "%2,%0"); + } + break; + } } return mips_output_conditional_branch (insn, operands, branch[1], branch[0]); } @@ -13291,11 +13543,18 @@ mips_process_sync_loop (rtx_insn *insn, rtx *operands) at, oldval, inclusive_mask, NULL); tmp1 = at; } - mips_multi_add_insn ("bne\t%0,%z1,2f", tmp1, required_oldval, NULL); + if (TARGET_CB_NEVER) + mips_multi_add_insn ("bne\t%0,%z1,2f", tmp1, required_oldval, NULL); /* CMP = 0 [delay slot]. */ if (cmp) mips_multi_add_insn ("li\t%0,0", cmp, NULL); + + if (TARGET_CB_MAYBE && required_oldval == const0_rtx) + mips_multi_add_insn ("bnezc\t%0,2f", tmp1, NULL); + else if (TARGET_CB_MAYBE) + mips_multi_add_insn ("bnec\t%0,%1,2f", tmp1, required_oldval, NULL); + } /* $TMP1 = OLDVAL & EXCLUSIVE_MASK. */ @@ -13358,7 +13617,10 @@ mips_process_sync_loop (rtx_insn *insn, rtx *operands) be annulled. To ensure this behaviour unconditionally use a NOP in the delay slot for the branch likely case. */ - mips_multi_add_insn ("beq%?\t%0,%.,1b%~", at, NULL); + if (TARGET_CB_MAYBE) + mips_multi_add_insn ("beqzc\t%0,1b", at, NULL); + else + mips_multi_add_insn ("beq%?\t%0,%.,1b%~", at, NULL); /* if (INSN1 != MOVE && INSN1 != LI) NEWVAL = $TMP3 [delay slot]. */ if (insn1 != SYNC_INSN1_MOVE && insn1 != SYNC_INSN1_LI && tmp3 != newval) @@ -16640,7 +16902,7 @@ mips_orphaned_high_part_p (mips_offset_table *htab, rtx_insn *insn) static void mips_avoid_hazard (rtx_insn *after, rtx_insn *insn, int *hilo_delay, - rtx *delayed_reg, rtx lo_reg) + rtx *delayed_reg, rtx lo_reg, bool *fs_delay) { rtx pattern, set; int nops, ninsns; @@ -16666,6 +16928,15 @@ mips_avoid_hazard (rtx_insn *after, rtx_insn *insn, int *hilo_delay, nops = 2 - *hilo_delay; else if (*delayed_reg != 0 && reg_referenced_p (*delayed_reg, pattern)) nops = 1; + /* If processing a forbidden slot hazard then a NOP is required if the + branch instruction was not in a sequence (as the sequence would + imply it is not actually a compact branch anyway) and the current + insn is not an inline asm, and can't go in a delay slot. */ + else if (*fs_delay && get_attr_can_delay (insn) == CAN_DELAY_NO + && GET_CODE (PATTERN (after)) != SEQUENCE + && GET_CODE (pattern) != ASM_INPUT + && asm_noperands (pattern) < 0) + nops = 1; else nops = 0; @@ -16678,12 +16949,18 @@ mips_avoid_hazard (rtx_insn *after, rtx_insn *insn, int *hilo_delay, /* Set up the state for the next instruction. */ *hilo_delay += ninsns; *delayed_reg = 0; + *fs_delay = false; if (INSN_CODE (insn) >= 0) switch (get_attr_hazard (insn)) { case HAZARD_NONE: break; + case HAZARD_FORBIDDEN_SLOT: + if (TARGET_CB_MAYBE) + *fs_delay = true; + break; + case HAZARD_HILO: *hilo_delay = 0; break; @@ -16707,6 +16984,7 @@ mips_reorg_process_insns (void) rtx_insn *insn, *last_insn, *subinsn, *next_insn; rtx lo_reg, delayed_reg; int hilo_delay; + bool fs_delay; /* Force all instructions to be split into their final form. */ split_all_insns_noflow (); @@ -16775,6 +17053,7 @@ mips_reorg_process_insns (void) hilo_delay = 2; delayed_reg = 0; lo_reg = gen_rtx_REG (SImode, LO_REGNUM); + fs_delay = false; /* Make a second pass over the instructions. Delete orphaned high-part relocations or turn them into NOPs. Avoid hazards @@ -16798,7 +17077,7 @@ mips_reorg_process_insns (void) INSN_CODE (subinsn) = CODE_FOR_nop; } mips_avoid_hazard (last_insn, subinsn, &hilo_delay, - &delayed_reg, lo_reg); + &delayed_reg, lo_reg, &fs_delay); } last_insn = insn; } @@ -16819,7 +17098,7 @@ mips_reorg_process_insns (void) else { mips_avoid_hazard (last_insn, insn, &hilo_delay, - &delayed_reg, lo_reg); + &delayed_reg, lo_reg, &fs_delay); last_insn = insn; } } @@ -17684,6 +17963,27 @@ mips_option_override (void) target_flags |= MASK_ODD_SPREG; } + if (!ISA_HAS_COMPACT_BRANCHES && mips_cb == MIPS_CB_ALWAYS) + { + error ("unsupported combination: %qs%s %s", + mips_arch_info->name, TARGET_MICROMIPS ? " -mmicromips" : "", + "-mcompact-branches=always"); + } + else if (!ISA_HAS_DELAY_SLOTS && mips_cb == MIPS_CB_NEVER) + { + error ("unsupported combination: %qs%s %s", + mips_arch_info->name, TARGET_MICROMIPS ? " -mmicromips" : "", + "-mcompact-branches=never"); + } + + /* Require explicit relocs for MIPS R6 onwards. This enables simplification + of the compact branch and jump support through the backend. */ + if (!TARGET_EXPLICIT_RELOCS && mips_isa_rev >= 6) + { + error ("unsupported combination: %qs %s", + mips_arch_info->name, "-mno-explicit-relocs"); + } + /* The effect of -mabicalls isn't defined for the EABI. */ if (mips_abi == ABI_EABI && TARGET_ABICALLS) { @@ -18703,6 +19003,18 @@ mips_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value) #undef OP + /* If we are using compact branches we don't have delay slots so + place the instruction that was in the delay slot before the JRC + instruction. */ + + if (TARGET_CB_ALWAYS) + { + rtx temp; + temp = trampoline[i-2]; + trampoline[i-2] = trampoline[i-1]; + trampoline[i-1] = temp; + } + /* Copy the trampoline code. Leave any padding uninitialized. */ for (j = 0; j < i; j++) { diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index da1de011fc9..25a1e0622cd 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -92,6 +92,33 @@ struct mips_cpu_info { /* True if we are generating position-independent VxWorks RTP code. */ #define TARGET_RTP_PIC (TARGET_VXWORKS_RTP && flag_pic) +/* Compact branches must not be used if the user either selects the + 'never' policy or the 'optimal' policy on a core that lacks + compact branch instructions. */ +#define TARGET_CB_NEVER (mips_cb == MIPS_CB_NEVER \ + || (mips_cb == MIPS_CB_OPTIMAL \ + && !ISA_HAS_COMPACT_BRANCHES)) + +/* Compact branches may be used if the user either selects the + 'always' policy or the 'optimal' policy on a core that supports + compact branch instructions. */ +#define TARGET_CB_MAYBE (TARGET_CB_ALWAYS \ + || (mips_cb == MIPS_CB_OPTIMAL \ + && ISA_HAS_COMPACT_BRANCHES)) + +/* Compact branches must always be generated if the user selects + the 'always' policy or the 'optimal' policy om a core that + lacks delay slot branch instructions. */ +#define TARGET_CB_ALWAYS (mips_cb == MIPS_CB_ALWAYS \ + || (mips_cb == MIPS_CB_OPTIMAL \ + && !ISA_HAS_DELAY_SLOTS)) + +/* Special handling for JRC that exists in microMIPSR3 as well as R6 + ISAs with full compact branch support. */ +#define ISA_HAS_JRC ((ISA_HAS_COMPACT_BRANCHES \ + || TARGET_MICROMIPS) \ + && mips_cb != MIPS_CB_NEVER) + /* True if the output file is marked as ".abicalls; .option pic0" (-call_nonpic). */ #define TARGET_ABICALLS_PIC0 \ @@ -872,6 +899,10 @@ struct mips_cpu_info { #define ISA_HAS_JR (mips_isa_rev <= 5) +#define ISA_HAS_DELAY_SLOTS 1 + +#define ISA_HAS_COMPACT_BRANCHES (mips_isa_rev >= 6) + /* ISA has branch likely instructions (e.g. mips2). */ /* Disable branchlikely for tx39 until compare rewrite. They haven't been generated up to this point. */ @@ -2645,6 +2676,9 @@ typedef struct mips_args { #define MIPS_BRANCH(OPCODE, OPERANDS) \ "%*" OPCODE "%?\t" OPERANDS "%/" +#define MIPS_BRANCH_C(OPCODE, OPERANDS) \ + "%*" OPCODE "%:\t" OPERANDS + /* Return an asm string that forces INSN to be treated as an absolute J or JAL instruction instead of an assembler macro. */ #define MIPS_ABSOLUTE_JUMP(INSN) \ @@ -2652,45 +2686,6 @@ typedef struct mips_args { ? ".option\tpic0\n\t" INSN "\n\t.option\tpic2" \ : INSN) -/* Return the asm template for a call. INSN is the instruction's mnemonic - ("j" or "jal"), OPERANDS are its operands, TARGET_OPNO is the operand - number of the target. SIZE_OPNO is the operand number of the argument size - operand that can optionally hold the call attributes. If SIZE_OPNO is not - -1 and the call is indirect, use the function symbol from the call - attributes to attach a R_MIPS_JALR relocation to the call. - - When generating GOT code without explicit relocation operators, - all calls should use assembly macros. Otherwise, all indirect - calls should use "jr" or "jalr"; we will arrange to restore $gp - afterwards if necessary. Finally, we can only generate direct - calls for -mabicalls by temporarily switching to non-PIC mode. - - For microMIPS jal(r), we try to generate jal(r)s when a 16-bit - instruction is in the delay slot of jal(r). */ -#define MIPS_CALL(INSN, OPERANDS, TARGET_OPNO, SIZE_OPNO) \ - (TARGET_USE_GOT && !TARGET_EXPLICIT_RELOCS \ - ? "%*" INSN "\t%" #TARGET_OPNO "%/" \ - : REG_P (OPERANDS[TARGET_OPNO]) \ - ? (mips_get_pic_call_symbol (OPERANDS, SIZE_OPNO) \ - ? ("%*.reloc\t1f,R_MIPS_JALR,%" #SIZE_OPNO "\n" \ - "1:\t" INSN "r\t%" #TARGET_OPNO "%/") \ - : TARGET_MICROMIPS && !TARGET_INTERLINK_COMPRESSED \ - ? "%*" INSN "r%!\t%" #TARGET_OPNO "%/" \ - : "%*" INSN "r\t%" #TARGET_OPNO "%/") \ - : TARGET_MICROMIPS && !TARGET_INTERLINK_COMPRESSED \ - ? MIPS_ABSOLUTE_JUMP ("%*" INSN "%!\t%" #TARGET_OPNO "%/") \ - : MIPS_ABSOLUTE_JUMP ("%*" INSN "\t%" #TARGET_OPNO "%/")) \ - -/* Similar to MIPS_CALL, but this is for MICROMIPS "j" to generate - "jrc" when nop is in the delay slot of "jr". */ - -#define MICROMIPS_J(INSN, OPERANDS, OPNO) \ - (TARGET_USE_GOT && !TARGET_EXPLICIT_RELOCS \ - ? "%*j\t%" #OPNO "%/" \ - : REG_P (OPERANDS[OPNO]) \ - ? "%*jr%:\t%" #OPNO \ - : MIPS_ABSOLUTE_JUMP ("%*" INSN "\t%" #OPNO "%/")) - /* Control the assembler format that we output. */ @@ -2981,6 +2976,9 @@ while (0) #undef PTRDIFF_TYPE #define PTRDIFF_TYPE (POINTER_SIZE == 64 ? "long int" : "int") +/* The minimum alignment of any expanded block move. */ +#define MIPS_MIN_MOVE_MEM_ALIGN 16 + /* The maximum number of bytes that can be copied by one iteration of a movmemsi loop; see mips_block_move_loop. */ #define MIPS_MAX_MOVE_BYTES_PER_LOOP_ITER \ diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index a0079d5c974..1d1c42bf5f5 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -409,6 +409,15 @@ (eq_attr "sync_mem" "!none") (const_string "syncloop")] (const_string "unknown"))) +(define_attr "compact_form" "always,maybe,never" + (cond [(eq_attr "jal" "direct") + (const_string "always") + (eq_attr "jal" "indirect") + (const_string "maybe") + (eq_attr "type" "jump") + (const_string "maybe")] + (const_string "never"))) + ;; Mode for conversion types (fcvt) ;; I2S integer to float single (SI/DI to SF) ;; I2D integer to float double (SI/DI to DF) @@ -694,7 +703,7 @@ ;; DELAY means that the next instruction cannot read the result ;; of this one. HILO means that the next two instructions cannot ;; write to HI or LO. -(define_attr "hazard" "none,delay,hilo" +(define_attr "hazard" "none,delay,hilo,forbidden_slot" (cond [(and (eq_attr "type" "load,fpload,fpidxload") (match_test "ISA_HAS_LOAD_DELAY")) (const_string "delay") @@ -1045,21 +1054,37 @@ (nil) (eq_attr "can_delay" "yes")]) -;; Branches that don't have likely variants do not annul on false. +;; Branches that have delay slots and don't have likely variants do +;; not annul on false. (define_delay (and (eq_attr "type" "branch") (not (match_test "TARGET_MIPS16")) + (ior (match_test "TARGET_CB_NEVER") + (and (eq_attr "compact_form" "maybe") + (not (match_test "TARGET_CB_ALWAYS"))) + (eq_attr "compact_form" "never")) (eq_attr "branch_likely" "no")) [(eq_attr "can_delay" "yes") (nil) (nil)]) -(define_delay (eq_attr "type" "jump") +(define_delay (and (eq_attr "type" "jump") + (ior (match_test "TARGET_CB_NEVER") + (and (eq_attr "compact_form" "maybe") + (not (match_test "TARGET_CB_ALWAYS"))) + (eq_attr "compact_form" "never"))) [(eq_attr "can_delay" "yes") (nil) (nil)]) +;; Call type instructions should never have a compact form as the +;; type is only used for MIPS16 patterns. For safety put the compact +;; branch detection condition in anyway. (define_delay (and (eq_attr "type" "call") - (eq_attr "jal_macro" "no")) + (eq_attr "jal_macro" "no") + (ior (match_test "TARGET_CB_NEVER") + (and (eq_attr "compact_form" "maybe") + (not (match_test "TARGET_CB_ALWAYS"))) + (eq_attr "compact_form" "never"))) [(eq_attr "can_delay" "yes") (nil) (nil)]) @@ -5813,25 +5838,29 @@ [(set (pc) (if_then_else (match_operator 1 "order_operator" - [(match_operand:GPR 2 "register_operand" "d") - (const_int 0)]) + [(match_operand:GPR 2 "register_operand" "d,d") + (match_operand:GPR 3 "reg_or_0_operand" "J,d")]) (label_ref (match_operand 0 "" "")) (pc)))] "!TARGET_MIPS16" { return mips_output_order_conditional_branch (insn, operands, false); } - [(set_attr "type" "branch")]) + [(set_attr "type" "branch") + (set_attr "compact_form" "maybe,always") + (set_attr "hazard" "forbidden_slot")]) (define_insn "*branch_order<mode>_inverted" [(set (pc) (if_then_else (match_operator 1 "order_operator" - [(match_operand:GPR 2 "register_operand" "d") - (const_int 0)]) + [(match_operand:GPR 2 "register_operand" "d,d") + (match_operand:GPR 3 "reg_or_0_operand" "J,d")]) (pc) (label_ref (match_operand 0 "" ""))))] "!TARGET_MIPS16" { return mips_output_order_conditional_branch (insn, operands, true); } - [(set_attr "type" "branch")]) + [(set_attr "type" "branch") + (set_attr "compact_form" "maybe,always") + (set_attr "hazard" "forbidden_slot")]) ;; Conditional branch on equality comparison. @@ -5844,20 +5873,10 @@ (label_ref (match_operand 0 "" "")) (pc)))] "!TARGET_MIPS16" -{ - /* For a simple BNEZ or BEQZ microMIPS branch. */ - if (TARGET_MICROMIPS - && operands[3] == const0_rtx - && get_attr_length (insn) <= 8) - return mips_output_conditional_branch (insn, operands, - "%*b%C1z%:\t%2,%0", - "%*b%N1z%:\t%2,%0"); - - return mips_output_conditional_branch (insn, operands, - MIPS_BRANCH ("b%C1", "%2,%z3,%0"), - MIPS_BRANCH ("b%N1", "%2,%z3,%0")); -} - [(set_attr "type" "branch")]) + { return mips_output_equal_conditional_branch (insn, operands, false); } + [(set_attr "type" "branch") + (set_attr "compact_form" "maybe") + (set_attr "hazard" "forbidden_slot")]) (define_insn "*branch_equality<mode>_inverted" [(set (pc) @@ -5868,20 +5887,10 @@ (pc) (label_ref (match_operand 0 "" ""))))] "!TARGET_MIPS16" -{ - /* For a simple BNEZ or BEQZ microMIPS branch. */ - if (TARGET_MICROMIPS - && operands[3] == const0_rtx - && get_attr_length (insn) <= 8) - return mips_output_conditional_branch (insn, operands, - "%*b%N0z%:\t%2,%1", - "%*b%C0z%:\t%2,%1"); - - return mips_output_conditional_branch (insn, operands, - MIPS_BRANCH ("b%N1", "%2,%z3,%0"), - MIPS_BRANCH ("b%C1", "%2,%z3,%0")); -} - [(set_attr "type" "branch")]) + { return mips_output_equal_conditional_branch (insn, operands, true); } + [(set_attr "type" "branch") + (set_attr "compact_form" "maybe") + (set_attr "hazard" "forbidden_slot")]) ;; MIPS16 branches @@ -6176,11 +6185,22 @@ "!TARGET_MIPS16 && TARGET_ABSOLUTE_JUMPS" { if (get_attr_length (insn) <= 8) - return "%*b\t%l0%/"; + { + if (TARGET_CB_MAYBE) + return MIPS_ABSOLUTE_JUMP ("%*b%:\t%l0"); + else + return MIPS_ABSOLUTE_JUMP ("%*b\t%l0%/"); + } else - return MIPS_ABSOLUTE_JUMP ("%*j\t%l0%/"); + { + if (TARGET_CB_MAYBE && !final_sequence) + return MIPS_ABSOLUTE_JUMP ("%*bc\t%l0"); + else + return MIPS_ABSOLUTE_JUMP ("%*j\t%l0%/"); + } } - [(set_attr "type" "branch")]) + [(set_attr "type" "branch") + (set_attr "compact_form" "maybe")]) (define_insn "*jump_pic" [(set (pc) @@ -6188,14 +6208,23 @@ "!TARGET_MIPS16 && !TARGET_ABSOLUTE_JUMPS" { if (get_attr_length (insn) <= 8) - return "%*b\t%l0%/"; + { + if (TARGET_CB_MAYBE) + return "%*b%:\t%l0"; + else + return "%*b\t%l0%/"; + } else { mips_output_load_label (operands[0]); - return "%*jr\t%@%/%]"; + if (TARGET_CB_MAYBE) + return "%*jr%:\t%@%]"; + else + return "%*jr\t%@%/%]"; } } - [(set_attr "type" "branch")]) + [(set_attr "type" "branch") + (set_attr "compact_form" "maybe")]) ;; We need a different insn for the mips16, because a mips16 branch ;; does not have a delay slot. @@ -6242,12 +6271,9 @@ (define_insn "indirect_jump_<mode>" [(set (pc) (match_operand:P 0 "register_operand" "d"))] "" -{ - if (TARGET_MICROMIPS) - return "%*jr%:\t%0"; - else - return "%*j\t%0%/"; -} + { + return mips_output_jump (operands, 0, -1, false); + } [(set_attr "type" "jump") (set_attr "mode" "none")]) @@ -6291,12 +6317,9 @@ (match_operand:P 0 "register_operand" "d")) (use (label_ref (match_operand 1 "" "")))] "" -{ - if (TARGET_MICROMIPS) - return "%*jr%:\t%0"; - else - return "%*j\t%0%/"; -} + { + return mips_output_jump (operands, 0, -1, false); + } [(set_attr "type" "jump") (set_attr "mode" "none")]) @@ -6508,10 +6531,8 @@ [(any_return)] "" { - if (TARGET_MICROMIPS) - return "%*jr%:\t$31"; - else - return "%*j\t$31%/"; + operands[0] = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM); + return mips_output_jump (operands, 0, -1, false); } [(set_attr "type" "jump") (set_attr "mode" "none")]) @@ -6522,12 +6543,10 @@ [(any_return) (use (match_operand 0 "pmode_register_operand" ""))] "" -{ - if (TARGET_MICROMIPS) - return "%*jr%:\t%0"; - else - return "%*j\t%0%/"; -} + { + operands[0] = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM); + return mips_output_jump (operands, 0, -1, false); + } [(set_attr "type" "jump") (set_attr "mode" "none")]) @@ -6783,12 +6802,7 @@ [(call (mem:SI (match_operand 0 "call_insn_operand" "j,S")) (match_operand 1 "" ""))] "TARGET_SIBCALLS && SIBLING_CALL_P (insn)" -{ - if (TARGET_MICROMIPS) - return MICROMIPS_J ("j", operands, 0); - else - return MIPS_CALL ("j", operands, 0, 1); -} + { return mips_output_jump (operands, 0, 1, false); } [(set_attr "jal" "indirect,direct") (set_attr "jal_macro" "no")]) @@ -6809,12 +6823,7 @@ (call (mem:SI (match_operand 1 "call_insn_operand" "j,S")) (match_operand 2 "" "")))] "TARGET_SIBCALLS && SIBLING_CALL_P (insn)" -{ - if (TARGET_MICROMIPS) - return MICROMIPS_J ("j", operands, 1); - else - return MIPS_CALL ("j", operands, 1, 2); -} + { return mips_output_jump (operands, 1, 2, false); } [(set_attr "jal" "indirect,direct") (set_attr "jal_macro" "no")]) @@ -6826,12 +6835,7 @@ (call (mem:SI (match_dup 1)) (match_dup 2)))] "TARGET_SIBCALLS && SIBLING_CALL_P (insn)" -{ - if (TARGET_MICROMIPS) - return MICROMIPS_J ("j", operands, 1); - else - return MIPS_CALL ("j", operands, 1, 2); -} + { return mips_output_jump (operands, 1, 2, false); } [(set_attr "jal" "indirect,direct") (set_attr "jal_macro" "no")]) @@ -6887,7 +6891,10 @@ (match_operand 1 "" "")) (clobber (reg:SI RETURN_ADDR_REGNUM))] "" - { return TARGET_SPLIT_CALLS ? "#" : MIPS_CALL ("jal", operands, 0, 1); } + { + return (TARGET_SPLIT_CALLS ? "#" + : mips_output_jump (operands, 0, 1, true)); + } "reload_completed && TARGET_SPLIT_CALLS" [(const_int 0)] { @@ -6902,7 +6909,7 @@ (clobber (reg:SI RETURN_ADDR_REGNUM)) (clobber (reg:SI 28))] "TARGET_SPLIT_CALLS" - { return MIPS_CALL ("jal", operands, 0, 1); } + { return mips_output_jump (operands, 0, 1, true); } [(set_attr "jal" "indirect,direct") (set_attr "jal_macro" "no")]) @@ -6916,7 +6923,10 @@ (const_int 1) (clobber (reg:SI RETURN_ADDR_REGNUM))] "" - { return TARGET_SPLIT_CALLS ? "#" : MIPS_CALL ("jal", operands, 0, -1); } + { + return (TARGET_SPLIT_CALLS ? "#" + : mips_output_jump (operands, 0, -1, true)); + } "reload_completed && TARGET_SPLIT_CALLS" [(const_int 0)] { @@ -6933,7 +6943,7 @@ (clobber (reg:SI RETURN_ADDR_REGNUM)) (clobber (reg:SI 28))] "TARGET_SPLIT_CALLS" - { return MIPS_CALL ("jal", operands, 0, -1); } + { return mips_output_jump (operands, 0, -1, true); } [(set_attr "jal" "direct") (set_attr "jal_macro" "no")]) @@ -6956,7 +6966,10 @@ (match_operand 2 "" ""))) (clobber (reg:SI RETURN_ADDR_REGNUM))] "" - { return TARGET_SPLIT_CALLS ? "#" : MIPS_CALL ("jal", operands, 1, 2); } + { + return (TARGET_SPLIT_CALLS ? "#" + : mips_output_jump (operands, 1, 2, true)); + } "reload_completed && TARGET_SPLIT_CALLS" [(const_int 0)] { @@ -6974,7 +6987,7 @@ (clobber (reg:SI RETURN_ADDR_REGNUM)) (clobber (reg:SI 28))] "TARGET_SPLIT_CALLS" - { return MIPS_CALL ("jal", operands, 1, 2); } + { return mips_output_jump (operands, 1, 2, true); } [(set_attr "jal" "indirect,direct") (set_attr "jal_macro" "no")]) @@ -6986,7 +6999,10 @@ (const_int 1) (clobber (reg:SI RETURN_ADDR_REGNUM))] "" - { return TARGET_SPLIT_CALLS ? "#" : MIPS_CALL ("jal", operands, 1, -1); } + { + return (TARGET_SPLIT_CALLS ? "#" + : mips_output_jump (operands, 1, -1, true)); + } "reload_completed && TARGET_SPLIT_CALLS" [(const_int 0)] { @@ -7005,7 +7021,7 @@ (clobber (reg:SI RETURN_ADDR_REGNUM)) (clobber (reg:SI 28))] "TARGET_SPLIT_CALLS" - { return MIPS_CALL ("jal", operands, 1, -1); } + { return mips_output_jump (operands, 1, -1, true); } [(set_attr "jal" "direct") (set_attr "jal_macro" "no")]) @@ -7019,7 +7035,10 @@ (match_dup 2))) (clobber (reg:SI RETURN_ADDR_REGNUM))] "" - { return TARGET_SPLIT_CALLS ? "#" : MIPS_CALL ("jal", operands, 1, 2); } + { + return (TARGET_SPLIT_CALLS ? "#" + : mips_output_jump (operands, 1, 2, true)); + } "reload_completed && TARGET_SPLIT_CALLS" [(const_int 0)] { @@ -7040,7 +7059,7 @@ (clobber (reg:SI RETURN_ADDR_REGNUM)) (clobber (reg:SI 28))] "TARGET_SPLIT_CALLS" - { return MIPS_CALL ("jal", operands, 1, 2); } + { return mips_output_jump (operands, 1, 2, true); } [(set_attr "jal" "indirect,direct") (set_attr "jal_macro" "no")]) @@ -7055,7 +7074,7 @@ { int i; - emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx)); + emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx)); for (i = 0; i < XVECLEN (operands[2], 0); i++) { @@ -7411,7 +7430,7 @@ (clobber (reg:P PIC_FUNCTION_ADDR_REGNUM)) (clobber (reg:P RETURN_ADDR_REGNUM))] "HAVE_AS_TLS && TARGET_MIPS16" - { return MIPS_CALL ("jal", operands, 0, -1); } + { return mips_output_jump (operands, 0, -1, true); } [(set_attr "type" "call") (set_attr "insn_count" "3") (set_attr "mode" "<MODE>")]) @@ -7452,7 +7471,7 @@ (clobber (reg:P PIC_FUNCTION_ADDR_REGNUM)) (clobber (reg:P RETURN_ADDR_REGNUM))] "TARGET_HARD_FLOAT_ABI && TARGET_MIPS16" - { return MIPS_CALL ("jal", operands, 0, -1); } + { return mips_output_jump (operands, 0, -1, true); } [(set_attr "type" "call") (set_attr "insn_count" "3")]) @@ -7482,7 +7501,7 @@ (clobber (reg:P PIC_FUNCTION_ADDR_REGNUM)) (clobber (reg:P RETURN_ADDR_REGNUM))] "TARGET_HARD_FLOAT_ABI && TARGET_MIPS16" - { return MIPS_CALL ("jal", operands, 0, -1); } + { return mips_output_jump (operands, 0, -1, true); } [(set_attr "type" "call") (set_attr "insn_count" "3")]) diff --git a/gcc/config/mips/mips.opt b/gcc/config/mips/mips.opt index 348c6e03f1e..84887d11623 100644 --- a/gcc/config/mips/mips.opt +++ b/gcc/config/mips/mips.opt @@ -418,3 +418,20 @@ Driver mload-store-pairs Target Report Var(TARGET_LOAD_STORE_PAIRS) Init(1) Enable load/store bonding. + +mcompact-branches= +Target RejectNegative JoinedOrMissing Var(mips_cb) Report Enum(mips_cb_setting) Init(MIPS_CB_OPTIMAL) +Specify the compact branch usage policy + +Enum +Name(mips_cb_setting) Type(enum mips_cb_setting) +Policies available for use with -mcompact-branches=: + +EnumValue +Enum(mips_cb_setting) String(never) Value(MIPS_CB_NEVER) + +EnumValue +Enum(mips_cb_setting) String(optimal) Value(MIPS_CB_OPTIMAL) + +EnumValue +Enum(mips_cb_setting) String(always) Value(MIPS_CB_ALWAYS) diff --git a/gcc/config/mips/predicates.md b/gcc/config/mips/predicates.md index 4929c3dc27e..3259232bb89 100644 --- a/gcc/config/mips/predicates.md +++ b/gcc/config/mips/predicates.md @@ -475,7 +475,18 @@ (match_code "eq,ne,lt,ltu,ge,geu")) (define_predicate "order_operator" - (match_code "lt,ltu,le,leu,ge,geu,gt,gtu")) + (match_code "lt,ltu,le,leu,ge,geu,gt,gtu") +{ + if (XEXP (op, 1) == const0_rtx) + return true; + + if (TARGET_CB_MAYBE + && (GET_CODE (op) == LT || GET_CODE (op) == LTU + || GET_CODE (op) == GE || GET_CODE (op) == GEU)) + return true; + + return false; +}) ;; For NE, cstore uses sltu instructions in which the first operand is $0. ;; This isn't possible in mips16 code. diff --git a/gcc/config/msp430/msp430.opt b/gcc/config/msp430/msp430.opt index 3fed8799822..e055f61069d 100644 --- a/gcc/config/msp430/msp430.opt +++ b/gcc/config/msp430/msp430.opt @@ -12,7 +12,7 @@ Specify the MCU to build for. mcpu= Target Report Joined RejectNegative Var(target_cpu) -Specify the ISA to build for: msp430, mdsp430x, msp430xv2 +Specify the ISA to build for: msp430, msp430x, msp430xv2 mlarge Target Report Mask(LARGE) RejectNegative diff --git a/gcc/config/nvptx/mkoffload.c b/gcc/config/nvptx/mkoffload.c index 1e154c8412c..ba0454e537a 100644 --- a/gcc/config/nvptx/mkoffload.c +++ b/gcc/config/nvptx/mkoffload.c @@ -881,10 +881,10 @@ process (FILE *in, FILE *out) "extern \"C\" {\n" "#endif\n"); - fprintf (out, "extern void GOMP_offload_register" - " (const void *, int, const void *);\n"); - fprintf (out, "extern void GOMP_offload_unregister" - " (const void *, int, const void *);\n"); + fprintf (out, "extern void GOMP_offload_register_ver" + " (unsigned, const void *, int, const void *);\n"); + fprintf (out, "extern void GOMP_offload_unregister_ver" + " (unsigned, const void *, int, const void *);\n"); fprintf (out, "#ifdef __cplusplus\n" "}\n" @@ -894,15 +894,19 @@ process (FILE *in, FILE *out) fprintf (out, "static __attribute__((constructor)) void init (void)\n" "{\n" - " GOMP_offload_register (__OFFLOAD_TABLE__, %d/*NVIDIA_PTX*/,\n" - " &target_data);\n" - "};\n", GOMP_DEVICE_NVIDIA_PTX); + " GOMP_offload_register_ver (%#x, __OFFLOAD_TABLE__," + "%d/*NVIDIA_PTX*/, &target_data);\n" + "};\n", + GOMP_VERSION_PACK (GOMP_VERSION, GOMP_VERSION_NVIDIA_PTX), + GOMP_DEVICE_NVIDIA_PTX); fprintf (out, "static __attribute__((destructor)) void fini (void)\n" "{\n" - " GOMP_offload_unregister (__OFFLOAD_TABLE__, %d/*NVIDIA_PTX*/,\n" - " &target_data);\n" - "};\n", GOMP_DEVICE_NVIDIA_PTX); + " GOMP_offload_unregister_ver (%#x, __OFFLOAD_TABLE__," + "%d/*NVIDIA_PTX*/, &target_data);\n" + "};\n", + GOMP_VERSION_PACK (GOMP_VERSION, GOMP_VERSION_NVIDIA_PTX), + GOMP_DEVICE_NVIDIA_PTX); } static void diff --git a/gcc/config/nvptx/nvptx.c b/gcc/config/nvptx/nvptx.c index a3569670d62..e6853680078 100644 --- a/gcc/config/nvptx/nvptx.c +++ b/gcc/config/nvptx/nvptx.c @@ -1,4 +1,3 @@ - /* Target code for NVPTX. Copyright (C) 2014-2015 Free Software Foundation, Inc. Contributed by Bernd Schmidt <bernds@codesourcery.com> @@ -322,7 +321,8 @@ nvptx_write_function_decl (std::stringstream &s, const char *name, const_tree de /* Declare argument types. */ if ((args != NULL_TREE - && !(TREE_CODE (args) == TREE_LIST && TREE_VALUE (args) == void_type_node)) + && !(TREE_CODE (args) == TREE_LIST + && TREE_VALUE (args) == void_type_node)) || is_main || return_in_mem || DECL_STATIC_CHAIN (decl)) @@ -406,8 +406,8 @@ walk_args_for_param (FILE *file, tree argtypes, tree args, bool write_copy, mode = DFmode; } - mode = arg_promotion (mode); } + mode = arg_promotion (mode); while (count-- > 0) { i++; @@ -546,7 +546,7 @@ nvptx_declare_function_name (FILE *file, const char *name, const_tree decl) else if (TYPE_MODE (result_type) != VOIDmode) { machine_mode mode = arg_promotion (TYPE_MODE (result_type)); - fprintf (file, ".reg%s %%retval;\n", + fprintf (file, "\t.reg%s %%retval;\n", nvptx_ptx_type_from_mode (mode, false)); } @@ -598,9 +598,11 @@ nvptx_declare_function_name (FILE *file, const char *name, const_tree decl) sz = get_frame_size (); if (sz > 0 || cfun->machine->has_call_with_sc) { + int alignment = crtl->stack_alignment_needed / BITS_PER_UNIT; + fprintf (file, "\t.reg.u%d %%frame;\n" - "\t.local.align 8 .b8 %%farray[" HOST_WIDE_INT_PRINT_DEC"];\n", - BITS_PER_WORD, sz == 0 ? 1 : sz); + "\t.local.align %d .b8 %%farray[" HOST_WIDE_INT_PRINT_DEC"];\n", + BITS_PER_WORD, alignment, sz == 0 ? 1 : sz); fprintf (file, "\tcvta.local.u%d %%frame, %%farray;\n", BITS_PER_WORD); } @@ -616,10 +618,10 @@ nvptx_declare_function_name (FILE *file, const char *name, const_tree decl) walk_args_for_param (file, TYPE_ARG_TYPES (fntype), DECL_ARGUMENTS (decl), true, return_in_mem); if (return_in_mem) - fprintf (file, "ld.param.u%d %%ar1, [%%in_ar1];\n", + fprintf (file, "\tld.param.u%d %%ar1, [%%in_ar1];\n", GET_MODE_BITSIZE (Pmode)); if (stdarg_p (fntype)) - fprintf (file, "ld.param.u%d %%argp, [%%in_argp];\n", + fprintf (file, "\tld.param.u%d %%argp, [%%in_argp];\n", GET_MODE_BITSIZE (Pmode)); } @@ -726,6 +728,14 @@ nvptx_function_ok_for_sibcall (tree, tree) return false; } +/* Return Dynamic ReAlignment Pointer RTX. For PTX there isn't any. */ + +static rtx +nvptx_get_drap_rtx (void) +{ + return NULL_RTX; +} + /* Implement the TARGET_CALL_ARGS hook. Record information about one argument to the next call. */ @@ -1908,7 +1918,7 @@ nvptx_reorg_subreg (void) { next = NEXT_INSN (insn); if (!NONDEBUG_INSN_P (insn) - || asm_noperands (insn) >= 0 + || asm_noperands (PATTERN (insn)) >= 0 || GET_CODE (PATTERN (insn)) == USE || GET_CODE (PATTERN (insn)) == CLOBBER) continue; @@ -2118,6 +2128,8 @@ nvptx_file_end (void) #define TARGET_LIBCALL_VALUE nvptx_libcall_value #undef TARGET_FUNCTION_OK_FOR_SIBCALL #define TARGET_FUNCTION_OK_FOR_SIBCALL nvptx_function_ok_for_sibcall +#undef TARGET_GET_DRAP_RTX +#define TARGET_GET_DRAP_RTX nvptx_get_drap_rtx #undef TARGET_SPLIT_COMPLEX_ARG #define TARGET_SPLIT_COMPLEX_ARG hook_bool_const_tree_true #undef TARGET_RETURN_IN_MEMORY diff --git a/gcc/config/nvptx/nvptx.h b/gcc/config/nvptx/nvptx.h index afe4fcdd361..60a922af93f 100644 --- a/gcc/config/nvptx/nvptx.h +++ b/gcc/config/nvptx/nvptx.h @@ -52,6 +52,8 @@ #define BIGGEST_ALIGNMENT 64 #define STRICT_ALIGNMENT 1 +#define MAX_STACK_ALIGNMENT (1024 * 8) + /* Copied from elf.h and other places. We'd otherwise use BIGGEST_ALIGNMENT and fail a number of testcases. */ #define MAX_OFILE_ALIGNMENT (32768 * 8) diff --git a/gcc/config/nvptx/nvptx.md b/gcc/config/nvptx/nvptx.md index 7c2cb9c15bc..b857e53bb22 100644 --- a/gcc/config/nvptx/nvptx.md +++ b/gcc/config/nvptx/nvptx.md @@ -1241,6 +1241,12 @@ (match_operand 1 "nvptx_register_operand")] "" { + /* The ptx documentation specifies an alloca intrinsic (for 32 bit + only) but notes it is not implemented. The assembler emits a + confused error message. Issue a blunt one now instead. */ + sorry ("target cannot support alloca."); + emit_insn (gen_nop ()); + DONE; if (TARGET_ABI64) emit_insn (gen_allocate_stack_di (operands[0], operands[1])); else diff --git a/gcc/config/pa/pa.md b/gcc/config/pa/pa.md index ad9289236ff..46fc0f5719c 100644 --- a/gcc/config/pa/pa.md +++ b/gcc/config/pa/pa.md @@ -8248,7 +8248,7 @@ add,l %2,%3,%3\;bv,n %%r0(%3)" { int i; - emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx)); + emit_call_insn (gen_call (operands[0], const0_rtx)); for (i = 0; i < XVECLEN (operands[2], 0); i++) { diff --git a/gcc/config/rs6000/altivec.h b/gcc/config/rs6000/altivec.h index 3ef6bc85ecd..1c00099c78d 100644 --- a/gcc/config/rs6000/altivec.h +++ b/gcc/config/rs6000/altivec.h @@ -208,6 +208,8 @@ #define vec_lvebx __builtin_vec_lvebx #define vec_lvehx __builtin_vec_lvehx #define vec_lvewx __builtin_vec_lvewx +#define vec_pmsum_be __builtin_vec_vpmsum +#define vec_shasigma_be __builtin_crypto_vshasigma /* Cell only intrinsics. */ #ifdef __PPU__ #define vec_lvlx __builtin_vec_lvlx diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md index ae74796849d..3edb4774e75 100644 --- a/gcc/config/rs6000/predicates.md +++ b/gcc/config/rs6000/predicates.md @@ -239,6 +239,25 @@ return INT_REGNO_P (REGNO (op)); }) +;; Like int_reg_operand, but don't return true for pseudo registers +(define_predicate "int_reg_operand_not_pseudo" + (match_operand 0 "register_operand") +{ + if ((TARGET_E500_DOUBLE || TARGET_SPE) && invalid_e500_subreg (op, mode)) + return 0; + + if (GET_CODE (op) == SUBREG) + op = SUBREG_REG (op); + + if (!REG_P (op)) + return 0; + + if (REGNO (op) >= FIRST_PSEUDO_REGISTER) + return 0; + + return INT_REGNO_P (REGNO (op)); +}) + ;; Like int_reg_operand, but only return true for base registers (define_predicate "base_reg_operand" (match_operand 0 "int_reg_operand") @@ -883,12 +902,12 @@ (define_predicate "current_file_function_operand" (and (match_code "symbol_ref") (match_test "(DEFAULT_ABI != ABI_AIX || SYMBOL_REF_FUNCTION_P (op)) - && ((SYMBOL_REF_LOCAL_P (op) - && ((DEFAULT_ABI != ABI_AIX - && DEFAULT_ABI != ABI_ELFv2) - || !SYMBOL_REF_EXTERNAL_P (op))) - || (op == XEXP (DECL_RTL (current_function_decl), - 0)))"))) + && (SYMBOL_REF_LOCAL_P (op) + || op == XEXP (DECL_RTL (current_function_decl), 0)) + && !((DEFAULT_ABI == ABI_AIX + || DEFAULT_ABI == ABI_ELFv2) + && (SYMBOL_REF_EXTERNAL_P (op) + || SYMBOL_REF_WEAK (op)))"))) ;; Return 1 if this operand is a valid input for a move insn. (define_predicate "input_operand" diff --git a/gcc/config/rs6000/rs6000-builtin.def b/gcc/config/rs6000/rs6000-builtin.def index 7beddf64d1b..85082ec0ee2 100644 --- a/gcc/config/rs6000/rs6000-builtin.def +++ b/gcc/config/rs6000/rs6000-builtin.def @@ -1489,6 +1489,10 @@ BU_P8V_AV_2 (VPKUDUM, "vpkudum", CONST, altivec_vpkudum) BU_P8V_AV_2 (VPKSDSS, "vpksdss", CONST, altivec_vpksdss) BU_P8V_AV_2 (VPKUDUS, "vpkudus", CONST, altivec_vpkudus) BU_P8V_AV_2 (VPKSDUS, "vpksdus", CONST, altivec_vpksdus) +BU_P8V_AV_2 (VPMSUMB, "vpmsumb", CONST, crypto_vpmsumb) +BU_P8V_AV_2 (VPMSUMH, "vpmsumh", CONST, crypto_vpmsumh) +BU_P8V_AV_2 (VPMSUMW, "vpmsumw", CONST, crypto_vpmsumw) +BU_P8V_AV_2 (VPMSUMD, "vpmsumd", CONST, crypto_vpmsumd) BU_P8V_AV_2 (VRLD, "vrld", CONST, vrotlv2di3) BU_P8V_AV_2 (VSLD, "vsld", CONST, vashlv2di3) BU_P8V_AV_2 (VSRD, "vsrd", CONST, vlshrv2di3) @@ -1570,6 +1574,7 @@ BU_P8V_OVERLOAD_2 (VPKSDSS, "vpksdss") BU_P8V_OVERLOAD_2 (VPKSDUS, "vpksdus") BU_P8V_OVERLOAD_2 (VPKUDUM, "vpkudum") BU_P8V_OVERLOAD_2 (VPKUDUS, "vpkudus") +BU_P8V_OVERLOAD_2 (VPMSUM, "vpmsum") BU_P8V_OVERLOAD_2 (VRLD, "vrld") BU_P8V_OVERLOAD_2 (VSLD, "vsld") BU_P8V_OVERLOAD_2 (VSRAD, "vsrad") diff --git a/gcc/config/rs6000/rs6000-c.c b/gcc/config/rs6000/rs6000-c.c index d45bc93b10a..5fc2b53adfe 100644 --- a/gcc/config/rs6000/rs6000-c.c +++ b/gcc/config/rs6000/rs6000-c.c @@ -2937,6 +2937,14 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = { RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF }, { ALTIVEC_BUILTIN_VEC_MADD, VSX_BUILTIN_XVMADDDP, RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF }, + { ALTIVEC_BUILTIN_VEC_MADD, ALTIVEC_BUILTIN_VMLADDUHM, + RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI }, + { ALTIVEC_BUILTIN_VEC_MADD, ALTIVEC_BUILTIN_VMLADDUHM, + RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI }, + { ALTIVEC_BUILTIN_VEC_MADD, ALTIVEC_BUILTIN_VMLADDUHM, + RS6000_BTI_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI }, + { ALTIVEC_BUILTIN_VEC_MADD, ALTIVEC_BUILTIN_VMLADDUHM, + RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI }, { ALTIVEC_BUILTIN_VEC_MADDS, ALTIVEC_BUILTIN_VMHADDSHS, RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI }, { ALTIVEC_BUILTIN_VEC_MLADD, ALTIVEC_BUILTIN_VMLADDUHM, @@ -4171,6 +4179,19 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = { { P8V_BUILTIN_VEC_VMRGOW, P8V_BUILTIN_VMRGOW, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, 0 }, + { P8V_BUILTIN_VEC_VPMSUM, P8V_BUILTIN_VPMSUMB, + RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V16QI, + RS6000_BTI_unsigned_V16QI, 0 }, + { P8V_BUILTIN_VEC_VPMSUM, P8V_BUILTIN_VPMSUMH, + RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V8HI, + RS6000_BTI_unsigned_V8HI, 0 }, + { P8V_BUILTIN_VEC_VPMSUM, P8V_BUILTIN_VPMSUMW, + RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V4SI, + RS6000_BTI_unsigned_V4SI, 0 }, + { P8V_BUILTIN_VEC_VPMSUM, P8V_BUILTIN_VPMSUMD, + RS6000_BTI_unsigned_V1TI, RS6000_BTI_unsigned_V2DI, + RS6000_BTI_unsigned_V2DI, 0 }, + { P8V_BUILTIN_VEC_VPOPCNT, P8V_BUILTIN_VPOPCNTB, RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0, 0 }, { P8V_BUILTIN_VEC_VPOPCNT, P8V_BUILTIN_VPOPCNTB, diff --git a/gcc/config/rs6000/rs6000-cpus.def b/gcc/config/rs6000/rs6000-cpus.def index 9fd565286f2..03764aef740 100644 --- a/gcc/config/rs6000/rs6000-cpus.def +++ b/gcc/config/rs6000/rs6000-cpus.def @@ -53,6 +53,7 @@ | OPTION_MASK_P8_VECTOR \ | OPTION_MASK_CRYPTO \ | OPTION_MASK_DIRECT_MOVE \ + | OPTION_MASK_EFFICIENT_UNALIGNED_VSX \ | OPTION_MASK_HTM \ | OPTION_MASK_QUAD_MEMORY \ | OPTION_MASK_QUAD_MEMORY_ATOMIC \ @@ -78,6 +79,7 @@ | OPTION_MASK_DFP \ | OPTION_MASK_DIRECT_MOVE \ | OPTION_MASK_DLMZB \ + | OPTION_MASK_EFFICIENT_UNALIGNED_VSX \ | OPTION_MASK_FPRND \ | OPTION_MASK_HTM \ | OPTION_MASK_ISEL \ diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index 7262a151438..7be529fab49 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -54,6 +54,7 @@ extern const char *output_vec_const_move (rtx *); extern const char *rs6000_output_move_128bit (rtx *); extern bool rs6000_move_128bit_ok_p (rtx []); extern bool rs6000_split_128bit_ok_p (rtx []); +extern void rs6000_expand_float128_convert (rtx, rtx, bool); extern void rs6000_expand_vector_init (rtx, rtx); extern void paired_expand_vector_init (rtx, rtx); extern void rs6000_expand_vector_set (rtx, rtx, int); diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 2a969782f26..8107bec8e6e 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -3716,6 +3716,45 @@ rs6000_option_override_internal (bool global_init_p) else if (TARGET_FLOAT128 == FLOAT128_SW && !TARGET_VSX) error ("-mfloat128-software requires VSX support"); + /* Set -mallow-movmisalign to explicitly on if we have full ISA 2.07 + support. If we only have ISA 2.06 support, and the user did not specify + the switch, leave it set to -1 so the movmisalign patterns are enabled, + but we don't enable the full vectorization support */ + if (TARGET_ALLOW_MOVMISALIGN == -1 && TARGET_P8_VECTOR && TARGET_DIRECT_MOVE) + TARGET_ALLOW_MOVMISALIGN = 1; + + else if (TARGET_ALLOW_MOVMISALIGN && !TARGET_VSX) + { + if (TARGET_ALLOW_MOVMISALIGN > 0) + error ("-mallow-movmisalign requires -mvsx"); + + TARGET_ALLOW_MOVMISALIGN = 0; + } + + /* Determine when unaligned vector accesses are permitted, and when + they are preferred over masked Altivec loads. Note that if + TARGET_ALLOW_MOVMISALIGN has been disabled by the user, then + TARGET_EFFICIENT_UNALIGNED_VSX must be as well. The converse is + not true. */ + if (TARGET_EFFICIENT_UNALIGNED_VSX) + { + if (!TARGET_VSX) + { + if (rs6000_isa_flags_explicit & OPTION_MASK_EFFICIENT_UNALIGNED_VSX) + error ("-mefficient-unaligned-vsx requires -mvsx"); + + rs6000_isa_flags &= ~OPTION_MASK_EFFICIENT_UNALIGNED_VSX; + } + + else if (!TARGET_ALLOW_MOVMISALIGN) + { + if (rs6000_isa_flags_explicit & OPTION_MASK_EFFICIENT_UNALIGNED_VSX) + error ("-mefficient-unaligned-vsx requires -mallow-movmisalign"); + + rs6000_isa_flags &= ~OPTION_MASK_EFFICIENT_UNALIGNED_VSX; + } + } + if (TARGET_DEBUG_REG || TARGET_DEBUG_TARGET) rs6000_print_isa_options (stderr, 0, "after defaults", rs6000_isa_flags); @@ -4275,22 +4314,6 @@ rs6000_option_override_internal (bool global_init_p) } } - /* Determine when unaligned vector accesses are permitted, and when - they are preferred over masked Altivec loads. Note that if - TARGET_ALLOW_MOVMISALIGN has been disabled by the user, then - TARGET_EFFICIENT_UNALIGNED_VSX must be as well. The converse is - not true. */ - if (TARGET_EFFICIENT_UNALIGNED_VSX == -1) { - if (TARGET_VSX && rs6000_cpu == PROCESSOR_POWER8 - && TARGET_ALLOW_MOVMISALIGN != 0) - TARGET_EFFICIENT_UNALIGNED_VSX = 1; - else - TARGET_EFFICIENT_UNALIGNED_VSX = 0; - } - - if (TARGET_ALLOW_MOVMISALIGN == -1 && rs6000_cpu == PROCESSOR_POWER8) - TARGET_ALLOW_MOVMISALIGN = 1; - /* Set the builtin mask of the various options used that could affect which builtins were used. In the past we used target_flags, but we've run out of bits, and some options like SPE and PAIRED are no longer in @@ -8462,7 +8485,7 @@ rs6000_emit_le_vsx_store (rtx dest, rtx source, machine_mode mode) during expand. */ gcc_assert (!reload_in_progress && !lra_in_progress && !reload_completed); - /* Use V2DImode to do swaps of types with 128-bit scalare parts (TImode, + /* Use V2DImode to do swaps of types with 128-bit scalar parts (TImode, V1TImode). */ if (mode == TImode || mode == V1TImode) { @@ -18519,6 +18542,8 @@ rs6000_cannot_change_mode_class (machine_mode from, { unsigned to_nregs = hard_regno_nregs[FIRST_FPR_REGNO][to]; unsigned from_nregs = hard_regno_nregs[FIRST_FPR_REGNO][from]; + bool to_float128_vector_p = FLOAT128_VECTOR_P (to); + bool from_float128_vector_p = FLOAT128_VECTOR_P (from); /* Don't allow 64-bit types to overlap with 128-bit types that take a single register under VSX because the scalar part of the register @@ -18527,7 +18552,10 @@ rs6000_cannot_change_mode_class (machine_mode from, IEEE floating point can't overlap, and neither can small values. */ - if (TARGET_IEEEQUAD && (to == TFmode || from == TFmode)) + if (to_float128_vector_p && from_float128_vector_p) + return false; + + else if (to_float128_vector_p || from_float128_vector_p) return true; /* TDmode in floating-mode registers must always go into a register @@ -18555,6 +18583,8 @@ rs6000_cannot_change_mode_class (machine_mode from, if (TARGET_E500_DOUBLE && ((((to) == DFmode) + ((from) == DFmode)) == 1 || (((to) == TFmode) + ((from) == TFmode)) == 1 + || (((to) == IFmode) + ((from) == IFmode)) == 1 + || (((to) == KFmode) + ((from) == KFmode)) == 1 || (((to) == DDmode) + ((from) == DDmode)) == 1 || (((to) == TDmode) + ((from) == TDmode)) == 1 || (((to) == DImode) + ((from) == DImode)) == 1)) @@ -18751,13 +18781,7 @@ rs6000_output_move_128bit (rtx operands[]) return output_vec_const_move (operands); } - if (TARGET_DEBUG_ADDR) - { - fprintf (stderr, "\n===== Bad 128 bit move:\n"); - debug_rtx (gen_rtx_SET (dest, src)); - } - - gcc_unreachable (); + fatal_insn ("Bad 128-bit move", gen_rtx_SET (dest, src)); } /* Validate a 128-bit move. */ @@ -19801,6 +19825,8 @@ rs6000_generate_compare (rtx cmp, machine_mode mode) break; case TFmode: + case IFmode: + case KFmode: cmp = (flag_finite_math_only && !flag_trapping_math) ? gen_tsttfeq_gpr (compare_result, op0, op1) : gen_cmptfeq_gpr (compare_result, op0, op1); @@ -19828,6 +19854,8 @@ rs6000_generate_compare (rtx cmp, machine_mode mode) break; case TFmode: + case IFmode: + case KFmode: cmp = (flag_finite_math_only && !flag_trapping_math) ? gen_tsttfgt_gpr (compare_result, op0, op1) : gen_cmptfgt_gpr (compare_result, op0, op1); @@ -19855,6 +19883,8 @@ rs6000_generate_compare (rtx cmp, machine_mode mode) break; case TFmode: + case IFmode: + case KFmode: cmp = (flag_finite_math_only && !flag_trapping_math) ? gen_tsttflt_gpr (compare_result, op0, op1) : gen_cmptflt_gpr (compare_result, op0, op1); @@ -19892,6 +19922,8 @@ rs6000_generate_compare (rtx cmp, machine_mode mode) break; case TFmode: + case IFmode: + case KFmode: cmp = (flag_finite_math_only && !flag_trapping_math) ? gen_tsttfeq_gpr (compare_result2, op0, op1) : gen_cmptfeq_gpr (compare_result2, op0, op1); @@ -19914,14 +19946,117 @@ rs6000_generate_compare (rtx cmp, machine_mode mode) emit_insn (cmp); } + + /* IEEE 128-bit support in VSX registers. The comparison function (__cmpkf2) + returns 0..15 that is laid out the same way as the PowerPC CR register + would for a normal floating point comparison. */ + else if (FLOAT128_IEEE_P (mode)) + { + rtx and_reg = gen_reg_rtx (SImode); + rtx dest = gen_reg_rtx (SImode); + rtx libfunc = optab_libfunc (cmp_optab, mode); + HOST_WIDE_INT mask_value = 0; + + /* Values that __cmpkf2 returns. */ +#define PPC_CMP_UNORDERED 0x1 /* isnan (a) || isnan (b). */ +#define PPC_CMP_EQUAL 0x2 /* a == b. */ +#define PPC_CMP_GREATER_THEN 0x4 /* a > b. */ +#define PPC_CMP_LESS_THEN 0x8 /* a < b. */ + + switch (code) + { + case EQ: + mask_value = PPC_CMP_EQUAL; + code = NE; + break; + + case NE: + mask_value = PPC_CMP_EQUAL; + code = EQ; + break; + + case GT: + mask_value = PPC_CMP_GREATER_THEN; + code = NE; + break; + + case GE: + mask_value = PPC_CMP_GREATER_THEN | PPC_CMP_EQUAL; + code = NE; + break; + + case LT: + mask_value = PPC_CMP_LESS_THEN; + code = NE; + break; + + case LE: + mask_value = PPC_CMP_LESS_THEN | PPC_CMP_EQUAL; + code = NE; + break; + + case UNLE: + mask_value = PPC_CMP_GREATER_THEN; + code = EQ; + break; + + case UNLT: + mask_value = PPC_CMP_GREATER_THEN | PPC_CMP_EQUAL; + code = EQ; + break; + + case UNGE: + mask_value = PPC_CMP_LESS_THEN; + code = EQ; + break; + + case UNGT: + mask_value = PPC_CMP_LESS_THEN | PPC_CMP_EQUAL; + code = EQ; + break; + + case UNEQ: + mask_value = PPC_CMP_EQUAL | PPC_CMP_UNORDERED; + code = NE; + + case LTGT: + mask_value = PPC_CMP_EQUAL | PPC_CMP_UNORDERED; + code = EQ; + break; + + case UNORDERED: + mask_value = PPC_CMP_UNORDERED; + code = NE; + break; + + case ORDERED: + mask_value = PPC_CMP_UNORDERED; + code = EQ; + break; + + default: + gcc_unreachable (); + } + + gcc_assert (mask_value != 0); + and_reg = emit_library_call_value (libfunc, and_reg, LCT_CONST, SImode, 2, + op0, mode, op1, mode); + + emit_insn (gen_andsi3 (dest, and_reg, GEN_INT (mask_value))); + compare_result = gen_reg_rtx (CCmode); + comp_mode = CCmode; + + emit_insn (gen_rtx_SET (compare_result, + gen_rtx_COMPARE (comp_mode, dest, const0_rtx))); + } + else { /* Generate XLC-compatible TFmode compare as PARALLEL with extra CLOBBERs to match cmptf_internal2 pattern. */ if (comp_mode == CCFPmode && TARGET_XL_COMPAT - && GET_MODE (op0) == TFmode - && !TARGET_IEEEQUAD - && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128) + && FLOAT128_IBM_P (GET_MODE (op0)) + && TARGET_HARD_FLOAT && TARGET_FPRS) emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (10, gen_rtx_SET (compare_result, @@ -19954,6 +20089,7 @@ rs6000_generate_compare (rtx cmp, machine_mode mode) /* Some kinds of FP comparisons need an OR operation; under flag_finite_math_only we don't bother. */ if (FLOAT_MODE_P (mode) + && !FLOAT128_IEEE_P (mode) && !flag_finite_math_only && !(TARGET_HARD_FLOAT && !TARGET_FPRS) && (code == LE || code == GE @@ -19993,6 +20129,68 @@ rs6000_generate_compare (rtx cmp, machine_mode mode) } +/* Expand floating point conversion to/from __float128 and __ibm128. */ + +void +rs6000_expand_float128_convert (rtx dest, rtx src, bool unsigned_p) +{ + machine_mode dest_mode = GET_MODE (dest); + machine_mode src_mode = GET_MODE (src); + convert_optab cvt = unknown_optab; + rtx libfunc = NULL_RTX; + rtx dest2; + + if (dest_mode == src_mode) + gcc_unreachable (); + + if (FLOAT128_IEEE_P (dest_mode)) + { + if (src_mode == SFmode + || src_mode == DFmode + || FLOAT128_IBM_P (src_mode)) + cvt = sext_optab; + + else if (GET_MODE_CLASS (src_mode) == MODE_INT) + cvt = (unsigned_p) ? ufloat_optab : sfloat_optab; + + else if (FLOAT128_IEEE_P (src_mode)) + emit_move_insn (dest, gen_lowpart (dest_mode, src)); + + else + gcc_unreachable (); + } + + else if (FLOAT128_IEEE_P (src_mode)) + { + if (dest_mode == SFmode + || dest_mode == DFmode + || FLOAT128_IBM_P (dest_mode)) + cvt = trunc_optab; + + else if (GET_MODE_CLASS (dest_mode) == MODE_INT) + cvt = (unsigned_p) ? ufix_optab : sfix_optab; + + else + gcc_unreachable (); + } + + else + gcc_unreachable (); + + gcc_assert (cvt != unknown_optab); + libfunc = convert_optab_libfunc (cvt, dest_mode, src_mode); + gcc_assert (libfunc != NULL_RTX); + + dest2 = emit_library_call_value (libfunc, dest, LCT_CONST, dest_mode, 1, src, + src_mode); + + gcc_assert (dest != NULL_RTX); + if (!rtx_equal_p (dest, dest2)) + emit_move_insn (dest, dest2); + + return; +} + /* Emit the RTL for an sISEL pattern. */ void @@ -22635,6 +22833,7 @@ rs6000_function_ok_for_sibcall (tree decl, tree exp) || ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_ELFv2) && decl && !DECL_EXTERNAL (decl) + && !DECL_WEAK (decl) && (*targetm.binds_local_p) (decl)) || (DEFAULT_ABI == ABI_V4 && (!TARGET_SECURE_PLT @@ -32921,6 +33120,8 @@ static struct rs6000_opt_mask const rs6000_opt_masks[] = { "crypto", OPTION_MASK_CRYPTO, false, true }, { "direct-move", OPTION_MASK_DIRECT_MOVE, false, true }, { "dlmzb", OPTION_MASK_DLMZB, false, true }, + { "efficient-unaligned-vsx", OPTION_MASK_EFFICIENT_UNALIGNED_VSX, + false, true }, { "fprnd", OPTION_MASK_FPRND, false, true }, { "hard-dfp", OPTION_MASK_DFP, false, true }, { "htm", OPTION_MASK_HTM, false, true }, @@ -34786,7 +34987,7 @@ class swap_web_entry : public web_entry_base /* A nonzero value indicates what kind of special handling for this insn is required if doublewords are swapped. Undefined if is_swappable is not set. */ - unsigned int special_handling : 3; + unsigned int special_handling : 4; /* Set if the web represented by this entry cannot be optimized. */ unsigned int web_not_optimizable : 1; /* Set if this insn should be deleted. */ @@ -34800,7 +35001,9 @@ enum special_handling_values { SH_NOSWAP_LD, SH_NOSWAP_ST, SH_EXTRACT, - SH_SPLAT + SH_SPLAT, + SH_XXPERMDI, + SH_CONCAT }; /* Union INSN with all insns containing definitions that reach USE. @@ -34992,6 +35195,20 @@ rtx_is_swappable_p (rtx op, unsigned int *special) *special = SH_EXTRACT; return 1; } + /* An XXPERMDI is ok if we adjust the lanes. Note that if the + XXPERMDI is a swap operation, it will be identified by + insn_is_swap_p and therefore we won't get here. */ + else if (GET_CODE (XEXP (op, 0)) == VEC_CONCAT + && (GET_MODE (XEXP (op, 0)) == V4DFmode + || GET_MODE (XEXP (op, 0)) == V4DImode) + && GET_CODE ((parallel = XEXP (op, 1))) == PARALLEL + && XVECLEN (parallel, 0) == 2 + && GET_CODE (XVECEXP (parallel, 0, 0)) == CONST_INT + && GET_CODE (XVECEXP (parallel, 0, 1)) == CONST_INT) + { + *special = SH_XXPERMDI; + return 1; + } else return 0; @@ -35169,6 +35386,17 @@ insn_is_swappable_p (swap_web_entry *insn_entry, rtx insn, return 1; } + /* A concatenation of two doublewords is ok if we reverse the + order of the inputs. */ + if (GET_CODE (body) == SET + && GET_CODE (SET_SRC (body)) == VEC_CONCAT + && (GET_MODE (SET_SRC (body)) == V2DFmode + || GET_MODE (SET_SRC (body)) == V2DImode)) + { + *special = SH_CONCAT; + return 1; + } + /* Otherwise check the operands for vector lane violations. */ return rtx_is_swappable_p (body, special); } @@ -35458,6 +35686,49 @@ adjust_splat (rtx_insn *insn) fprintf (dump_file, "Changing lane for splat %d\n", INSN_UID (insn)); } +/* Given OP that contains an XXPERMDI operation (that is not a doubleword + swap), reverse the order of the source operands and adjust the indices + of the source lanes to account for doubleword reversal. */ +static void +adjust_xxpermdi (rtx_insn *insn) +{ + rtx set = PATTERN (insn); + rtx select = XEXP (set, 1); + rtx concat = XEXP (select, 0); + rtx src0 = XEXP (concat, 0); + XEXP (concat, 0) = XEXP (concat, 1); + XEXP (concat, 1) = src0; + rtx parallel = XEXP (select, 1); + int lane0 = INTVAL (XVECEXP (parallel, 0, 0)); + int lane1 = INTVAL (XVECEXP (parallel, 0, 1)); + int new_lane0 = 3 - lane1; + int new_lane1 = 3 - lane0; + XVECEXP (parallel, 0, 0) = GEN_INT (new_lane0); + XVECEXP (parallel, 0, 1) = GEN_INT (new_lane1); + INSN_CODE (insn) = -1; /* Force re-recognition. */ + df_insn_rescan (insn); + + if (dump_file) + fprintf (dump_file, "Changing lanes for xxpermdi %d\n", INSN_UID (insn)); +} + +/* Given OP that contains a VEC_CONCAT operation of two doublewords, + reverse the order of those inputs. */ +static void +adjust_concat (rtx_insn *insn) +{ + rtx set = PATTERN (insn); + rtx concat = XEXP (set, 1); + rtx src0 = XEXP (concat, 0); + XEXP (concat, 0) = XEXP (concat, 1); + XEXP (concat, 1) = src0; + INSN_CODE (insn) = -1; /* Force re-recognition. */ + df_insn_rescan (insn); + + if (dump_file) + fprintf (dump_file, "Reversing inputs for concat %d\n", INSN_UID (insn)); +} + /* The insn described by INSN_ENTRY[I] can be swapped, but only with special handling. Take care of that here. */ static void @@ -35504,6 +35775,14 @@ handle_special_swappables (swap_web_entry *insn_entry, unsigned i) /* Change the lane on a direct-splat operation. */ adjust_splat (insn); break; + case SH_XXPERMDI: + /* Change the lanes on an XXPERMDI operation. */ + adjust_xxpermdi (insn); + break; + case SH_CONCAT: + /* Reverse the order of a concatenation operation. */ + adjust_concat (insn); + break; } } @@ -35576,6 +35855,10 @@ dump_swap_insn_table (swap_web_entry *insn_entry) fputs ("special:extract ", dump_file); else if (insn_entry[i].special_handling == SH_SPLAT) fputs ("special:splat ", dump_file); + else if (insn_entry[i].special_handling == SH_XXPERMDI) + fputs ("special:xxpermdi ", dump_file); + else if (insn_entry[i].special_handling == SH_CONCAT) + fputs ("special:concat ", dump_file); } if (insn_entry[i].web_not_optimizable) fputs ("unoptimizable ", dump_file); diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 527ad985423..cfdb286a2cb 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -348,6 +348,8 @@ && TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE) && TARGET_LONG_DOUBLE_128") + (IF "TARGET_FLOAT128") + (KF "TARGET_FLOAT128") (DD "TARGET_DFP") (TD "TARGET_DFP")]) @@ -365,9 +367,14 @@ (define_mode_iterator FMOVE32 [SF SD]) (define_mode_iterator FMOVE64 [DF DD]) (define_mode_iterator FMOVE64X [DI DF DD]) -(define_mode_iterator FMOVE128 [(TF "!TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128") +(define_mode_iterator FMOVE128 [(TF "TARGET_LONG_DOUBLE_128") + (IF "TARGET_LONG_DOUBLE_128") (TD "TARGET_HARD_FLOAT && TARGET_FPRS")]) +(define_mode_iterator FMOVE128_FPR [(TF "FLOAT128_2REG_P (TFmode)") + (IF "FLOAT128_2REG_P (IFmode)") + (TD "TARGET_HARD_FLOAT && TARGET_FPRS")]) + ; Iterators for 128 bit types for direct move (define_mode_iterator FMOVE128_GPR [(TI "TARGET_VSX_TIMODE") (V16QI "") @@ -376,7 +383,13 @@ (V4SF "") (V2DI "") (V2DF "") - (V1TI "")]) + (V1TI "") + (KF "") + (TF "") + (IF "")]) + +; Iterator for 128-bit VSX types for pack/unpack +(define_mode_iterator FMOVE128_VSX [V1TI KF]) ; Whether a floating point move is ok, don't allow SD without hardware FP (define_mode_attr fmove_ok [(SF "") @@ -432,6 +445,25 @@ ; Iterator for just SF/DF (define_mode_iterator SFDF [SF DF]) +; Iterator for float128 floating conversions +(define_mode_iterator FLOAT128_SFDFTF [ + (SF "TARGET_FLOAT128") + (DF "TARGET_FLOAT128") + (TF "FLOAT128_IBM_P (TFmode)") + (IF "TARGET_FLOAT128")]) + +; Iterator for special 128-bit floating point. This is for non-default +; conversions, so TFmode is not used here. +(define_mode_iterator IFKF [IF KF]) + +; Iterator for 128-bit floating point that uses the IBM double-double format +(define_mode_iterator IBM128 [IF TF]) + +; Iterator for 128-bit floating point +(define_mode_iterator TFIFKF [(KF "TARGET_FLOAT128") + (IF "TARGET_FLOAT128") + (TF "TARGET_LONG_DOUBLE_128")]) + ; SF/DF suffix for traditional floating instructions (define_mode_attr Ftrad [(SF "s") (DF "")]) @@ -596,7 +628,7 @@ ;; Reload iterator for creating the function to allocate a base register to ;; supplement addressing modes. (define_mode_iterator RELOAD [V16QI V8HI V4SI V2DI V4SF V2DF V1TI - SF SD SI DF DD DI TI PTI]) + SF SD SI DF DD DI TI PTI KF IF TF]) ;; Start with fixed-point load and store insns. Here we put only the more @@ -3037,15 +3069,15 @@ (set_attr "dot" "yes") (set_attr "length" "4,8")]) -(define_insn_and_split "*and<mode>3_imm_dot_shifted" - [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y") +(define_insn "*and<mode>3_imm_dot_shifted" + [(set (match_operand:CC 3 "cc_reg_operand" "=x") (compare:CC (and:GPR - (lshiftrt:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,r") - (match_operand:SI 4 "const_int_operand" "n,n")) - (match_operand:GPR 2 "const_int_operand" "n,n")) + (lshiftrt:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r") + (match_operand:SI 4 "const_int_operand" "n")) + (match_operand:GPR 2 "const_int_operand" "n")) (const_int 0))) - (clobber (match_scratch:GPR 0 "=r,r"))] + (clobber (match_scratch:GPR 0 "=r"))] "logical_const_operand (GEN_INT (UINTVAL (operands[2]) << INTVAL (operands[4])), DImode) @@ -3054,23 +3086,10 @@ && rs6000_gen_cell_microcode" { operands[2] = GEN_INT (UINTVAL (operands[2]) << INTVAL (operands[4])); - if (which_alternative == 0) - return "andi%e2. %0,%1,%u2"; - else - return "#"; + return "andi%e2. %0,%1,%u2"; } - "&& reload_completed && cc_reg_not_cr0_operand (operands[3], CCmode)" - [(set (match_dup 0) - (and:GPR (lshiftrt:GPR (match_dup 1) - (match_dup 4)) - (match_dup 2))) - (set (match_dup 3) - (compare:CC (match_dup 0) - (const_int 0)))] - "" [(set_attr "type" "logical") - (set_attr "dot" "yes") - (set_attr "length" "4,8")]) + (set_attr "dot" "yes")]) (define_insn "and<mode>3_mask" @@ -3664,10 +3683,10 @@ ; an insert instruction, in many cases. (define_insn_and_split "*ior<mode>_mask" [(set (match_operand:GPR 0 "gpc_reg_operand" "=r") - (ior:GPR (match_operand:GPR 1 "gpc_reg_operand" "r") - (match_operand:GPR 2 "const_int_operand" "n")))] - "can_create_pseudo_p () - && !logical_const_operand (operands[2], <MODE>mode) + (ior:GPR (match_operand:GPR 1 "gpc_reg_operand" "0") + (match_operand:GPR 2 "const_int_operand" "n"))) + (clobber (match_scratch:GPR 3 "=r"))] + "!logical_const_operand (operands[2], <MODE>mode) && rs6000_is_valid_mask (operands[2], NULL, NULL, <MODE>mode)" "#" "&& 1" @@ -3682,7 +3701,8 @@ { int nb, ne; rs6000_is_valid_mask (operands[2], &nb, &ne, <MODE>mode); - operands[3] = gen_reg_rtx (<MODE>mode); + if (GET_CODE (operands[3]) == SCRATCH) + operands[3] = gen_reg_rtx (<MODE>mode); operands[4] = GEN_INT (ne); operands[5] = GEN_INT (~UINTVAL (operands[2])); } @@ -4216,19 +4236,18 @@ ;; This expander is here to avoid FLOAT_WORDS_BIGENDIAN tests in ;; builtins.c and optabs.c that are not correct for IBM long double ;; when little-endian. -(define_expand "signbittf2" +(define_expand "signbit<mode>2" [(set (match_dup 2) - (float_truncate:DF (match_operand:TF 1 "gpc_reg_operand" ""))) + (float_truncate:DF (match_operand:IBM128 1 "gpc_reg_operand" ""))) (set (match_dup 3) (subreg:DI (match_dup 2) 0)) (set (match_dup 4) (match_dup 5)) (set (match_operand:SI 0 "gpc_reg_operand" "") (match_dup 6))] - "!TARGET_IEEEQUAD + "FLOAT128_IBM_P (<MODE>mode) && TARGET_HARD_FLOAT - && (TARGET_FPRS || TARGET_E500_DOUBLE) - && TARGET_LONG_DOUBLE_128" + && (TARGET_FPRS || TARGET_E500_DOUBLE)" { operands[2] = gen_reg_rtx (DFmode); operands[3] = gen_reg_rtx (DImode); @@ -6402,9 +6421,10 @@ ;; problematical. Don't allow direct move for this case. (define_insn_and_split "*mov<mode>_64bit_dm" - [(set (match_operand:FMOVE128 0 "nonimmediate_operand" "=m,d,d,ws,Y,r,r,r,wm") - (match_operand:FMOVE128 1 "input_operand" "d,m,d,j,r,jY,r,wm,r"))] + [(set (match_operand:FMOVE128_FPR 0 "nonimmediate_operand" "=m,d,d,ws,Y,r,r,r,wm") + (match_operand:FMOVE128_FPR 1 "input_operand" "d,m,d,j,r,jY,r,wm,r"))] "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_POWERPC64 + && FLOAT128_2REG_P (<MODE>mode) && (<MODE>mode != TDmode || WORDS_BIG_ENDIAN) && (gpc_reg_operand (operands[0], <MODE>mode) || gpc_reg_operand (operands[1], <MODE>mode))" @@ -6427,9 +6447,12 @@ [(set_attr "length" "8,8,8,8,12,12,8")]) (define_insn_and_split "*mov<mode>_32bit" - [(set (match_operand:FMOVE128 0 "nonimmediate_operand" "=m,d,d,ws,Y,r,r") - (match_operand:FMOVE128 1 "input_operand" "d,m,d,j,r,jY,r"))] + [(set (match_operand:FMOVE128_FPR 0 "nonimmediate_operand" "=m,d,d,ws,Y,r,r") + (match_operand:FMOVE128_FPR 1 "input_operand" "d,m,d,j,r,jY,r"))] "TARGET_HARD_FLOAT && TARGET_FPRS && !TARGET_POWERPC64 + && (FLOAT128_2REG_P (<MODE>mode) + || int_reg_operand_not_pseudo (operands[0], <MODE>mode) + || int_reg_operand_not_pseudo (operands[1], <MODE>mode)) && (gpc_reg_operand (operands[0], <MODE>mode) || gpc_reg_operand (operands[1], <MODE>mode))" "#" @@ -6453,12 +6476,12 @@ (define_expand "extenddftf2" [(set (match_operand:TF 0 "nonimmediate_operand" "") (float_extend:TF (match_operand:DF 1 "input_operand" "")))] - "!TARGET_IEEEQUAD - && TARGET_HARD_FLOAT - && (TARGET_FPRS || TARGET_E500_DOUBLE) + "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE) && TARGET_LONG_DOUBLE_128" { - if (TARGET_E500_DOUBLE) + if (TARGET_IEEEQUAD) + rs6000_expand_float128_convert (operands[0], operands[1], false); + else if (TARGET_E500_DOUBLE) emit_insn (gen_spe_extenddftf2 (operands[0], operands[1])); else emit_insn (gen_extenddftf2_fprs (operands[0], operands[1])); @@ -6507,25 +6530,34 @@ (define_expand "extendsftf2" [(set (match_operand:TF 0 "nonimmediate_operand" "") (float_extend:TF (match_operand:SF 1 "gpc_reg_operand" "")))] - "!TARGET_IEEEQUAD - && TARGET_HARD_FLOAT + "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE) && TARGET_LONG_DOUBLE_128" { - rtx tmp = gen_reg_rtx (DFmode); - emit_insn (gen_extendsfdf2 (tmp, operands[1])); - emit_insn (gen_extenddftf2 (operands[0], tmp)); + if (TARGET_IEEEQUAD) + rs6000_expand_float128_convert (operands[0], operands[1], false); + else + { + rtx tmp = gen_reg_rtx (DFmode); + emit_insn (gen_extendsfdf2 (tmp, operands[1])); + emit_insn (gen_extenddftf2 (operands[0], tmp)); + } DONE; }) (define_expand "trunctfdf2" [(set (match_operand:DF 0 "gpc_reg_operand" "") (float_truncate:DF (match_operand:TF 1 "gpc_reg_operand" "")))] - "!TARGET_IEEEQUAD - && TARGET_HARD_FLOAT + "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE) && TARGET_LONG_DOUBLE_128" - "") +{ + if (TARGET_IEEEQUAD) + { + rs6000_expand_float128_convert (operands[0], operands[1], false); + DONE; + } +}) (define_insn_and_split "trunctfdf2_internal1" [(set (match_operand:DF 0 "gpc_reg_operand" "=d,?d") @@ -6556,12 +6588,13 @@ (define_expand "trunctfsf2" [(set (match_operand:SF 0 "gpc_reg_operand" "") (float_truncate:SF (match_operand:TF 1 "gpc_reg_operand" "")))] - "!TARGET_IEEEQUAD - && TARGET_HARD_FLOAT + "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE) && TARGET_LONG_DOUBLE_128" { - if (TARGET_E500_DOUBLE) + if (TARGET_IEEEQUAD) + rs6000_expand_float128_convert (operands[0], operands[1], false); + else if (TARGET_E500_DOUBLE) emit_insn (gen_spe_trunctfsf2 (operands[0], operands[1])); else emit_insn (gen_trunctfsf2_fprs (operands[0], operands[1])); @@ -6612,10 +6645,12 @@ (define_expand "fix_trunctfsi2" [(set (match_operand:SI 0 "gpc_reg_operand" "") (fix:SI (match_operand:TF 1 "gpc_reg_operand" "")))] - "!TARGET_IEEEQUAD && TARGET_HARD_FLOAT + "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE) && TARGET_LONG_DOUBLE_128" { - if (TARGET_E500_DOUBLE) + if (TARGET_IEEEQUAD) + rs6000_expand_float128_convert (operands[0], operands[1], false); + else if (TARGET_E500_DOUBLE) emit_insn (gen_spe_fix_trunctfsi2 (operands[0], operands[1])); else emit_insn (gen_fix_trunctfsi2_fprs (operands[0], operands[1])); @@ -6663,20 +6698,73 @@ DONE; }) -(define_expand "negtf2" - [(set (match_operand:TF 0 "gpc_reg_operand" "") - (neg:TF (match_operand:TF 1 "gpc_reg_operand" "")))] - "!TARGET_IEEEQUAD - && TARGET_HARD_FLOAT - && (TARGET_FPRS || TARGET_E500_DOUBLE) - && TARGET_LONG_DOUBLE_128" - "") +(define_expand "fix_trunctfdi2" + [(set (match_operand:DI 0 "nonimmediate_operand" "") + (fix:DI (match_operand:TF 1 "gpc_reg_operand" "")))] + "TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128" +{ + rs6000_expand_float128_convert (operands[0], operands[1], false); + DONE; +}) + +(define_expand "fixuns_trunctf<mode>2" + [(set (match_operand:SDI 0 "nonimmediate_operand" "") + (unsigned_fix:SDI (match_operand:TF 1 "gpc_reg_operand" "")))] + "TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128" +{ + rs6000_expand_float128_convert (operands[0], operands[1], true); + DONE; +}) + +(define_expand "floatditf2" + [(set (match_operand:TF 0 "nonimmediate_operand" "") + (float:TF (match_operand:DI 1 "gpc_reg_operand" "")))] + "TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128" +{ + rs6000_expand_float128_convert (operands[0], operands[1], false); + DONE; +}) + +(define_expand "floatuns<mode>tf2" + [(set (match_operand:TF 0 "nonimmediate_operand" "") + (unsigned_float:TF (match_operand:SDI 1 "gpc_reg_operand" "")))] + "TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128" +{ + rs6000_expand_float128_convert (operands[0], operands[1], true); + DONE; +}) + +(define_expand "neg<mode>2" + [(set (match_operand:TFIFKF 0 "gpc_reg_operand" "") + (neg:TFIFKF (match_operand:TFIFKF 1 "gpc_reg_operand" "")))] + "FLOAT128_IEEE_P (<MODE>mode) + || (FLOAT128_IBM_P (<MODE>mode) + && TARGET_HARD_FLOAT + && (TARGET_FPRS || TARGET_E500_DOUBLE))" + " +{ + if (FLOAT128_IEEE_P (<MODE>mode)) + { + if (TARGET_FLOAT128) + emit_insn (gen_ieee_128bit_vsx_neg<mode>2 (operands[0], operands[1])); + else + { + rtx libfunc = optab_libfunc (neg_optab, <MODE>mode); + rtx target = emit_library_call_value (libfunc, operands[0], LCT_CONST, + <MODE>mode, 1, + operands[1], <MODE>mode); + + if (target && !rtx_equal_p (target, operands[0])) + emit_move_insn (operands[0], target); + } + DONE; + } +}") (define_insn "negtf2_internal" [(set (match_operand:TF 0 "gpc_reg_operand" "=d") (neg:TF (match_operand:TF 1 "gpc_reg_operand" "d")))] - "!TARGET_IEEEQUAD - && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128" + "TARGET_HARD_FLOAT && TARGET_FPRS && FLOAT128_IBM_P (TFmode)" "* { if (REGNO (operands[0]) == REGNO (operands[1]) + 1) @@ -6687,16 +6775,29 @@ [(set_attr "type" "fp") (set_attr "length" "8")]) -(define_expand "abstf2" - [(set (match_operand:TF 0 "gpc_reg_operand" "") - (abs:TF (match_operand:TF 1 "gpc_reg_operand" "")))] - "!TARGET_IEEEQUAD - && TARGET_HARD_FLOAT - && (TARGET_FPRS || TARGET_E500_DOUBLE) - && TARGET_LONG_DOUBLE_128" +(define_expand "abs<mode>2" + [(set (match_operand:TFIFKF 0 "gpc_reg_operand" "") + (abs:TFIFKF (match_operand:TFIFKF 1 "gpc_reg_operand" "")))] + "FLOAT128_IEEE_P (<MODE>mode) + || (FLOAT128_IBM_P (<MODE>mode) + && TARGET_HARD_FLOAT + && (TARGET_FPRS || TARGET_E500_DOUBLE))" " { - rtx label = gen_label_rtx (); + rtx label; + + if (FLOAT128_IEEE_P (<MODE>mode)) + { + if (TARGET_FLOAT128) + { + emit_insn (gen_ieee_128bit_vsx_abs<mode>2 (operands[0], operands[1])); + DONE; + } + else + FAIL; + } + + label = gen_label_rtx (); if (TARGET_E500_DOUBLE) { if (flag_finite_math_only && !flag_trapping_math) @@ -6732,6 +6833,184 @@ operands[5] = simplify_gen_subreg (DFmode, operands[0], TFmode, hi_word); operands[6] = simplify_gen_subreg (DFmode, operands[0], TFmode, lo_word); }") + + +;; Generate IEEE 128-bit -0.0 (0x80000000000000000000000000000000) in a vector +;; register + +(define_expand "ieee_128bit_negative_zero" + [(set (match_operand:V16QI 0 "register_operand" "") (match_dup 1))] + "TARGET_FLOAT128" +{ + rtvec v = rtvec_alloc (16); + int i, high; + + for (i = 0; i < 16; i++) + RTVEC_ELT (v, i) = const0_rtx; + + high = (BYTES_BIG_ENDIAN) ? 0 : 15; + RTVEC_ELT (v, high) = GEN_INT (0x80); + + rs6000_expand_vector_init (operands[0], gen_rtx_PARALLEL (V16QImode, v)); + DONE; +}) + +;; IEEE 128-bit negate + +;; We have 2 insns here for negate and absolute value. The first uses +;; match_scratch so that phases like combine can recognize neg/abs as generic +;; insns, and second insn after the first split pass loads up the bit to +;; twiddle the sign bit. Later GCSE passes can then combine multiple uses of +;; neg/abs to create the constant just once. + +(define_insn_and_split "ieee_128bit_vsx_neg<mode>2" + [(set (match_operand:TFIFKF 0 "register_operand" "=wa") + (neg:TFIFKF (match_operand:TFIFKF 1 "register_operand" "wa"))) + (clobber (match_scratch:V16QI 2 "=v"))] + "TARGET_FLOAT128 && FLOAT128_IEEE_P (<MODE>mode)" + "#" + "&& 1" + [(parallel [(set (match_dup 0) + (neg:TFIFKF (match_dup 1))) + (use (match_dup 2))])] +{ + if (GET_CODE (operands[2]) == SCRATCH) + operands[2] = gen_reg_rtx (V16QImode); + + operands[3] = gen_reg_rtx (V16QImode); + emit_insn (gen_ieee_128bit_negative_zero (operands[2])); +} + [(set_attr "length" "8") + (set_attr "type" "vecsimple")]) + +(define_insn "*ieee_128bit_vsx_neg<mode>2_internal" + [(set (match_operand:TFIFKF 0 "register_operand" "=wa") + (neg:TFIFKF (match_operand:TFIFKF 1 "register_operand" "wa"))) + (use (match_operand:V16QI 2 "register_operand" "=v"))] + "TARGET_FLOAT128" + "xxlxor %x0,%x1,%x2" + [(set_attr "type" "vecsimple")]) + +;; IEEE 128-bit absolute value +(define_insn_and_split "ieee_128bit_vsx_abs<mode>2" + [(set (match_operand:TFIFKF 0 "register_operand" "=wa") + (abs:TFIFKF (match_operand:TFIFKF 1 "register_operand" "wa"))) + (clobber (match_scratch:V16QI 2 "=v"))] + "TARGET_FLOAT128 && FLOAT128_IEEE_P (<MODE>mode)" + "#" + "&& 1" + [(parallel [(set (match_dup 0) + (abs:TFIFKF (match_dup 1))) + (use (match_dup 2))])] +{ + if (GET_CODE (operands[2]) == SCRATCH) + operands[2] = gen_reg_rtx (V16QImode); + + operands[3] = gen_reg_rtx (V16QImode); + emit_insn (gen_ieee_128bit_negative_zero (operands[2])); +} + [(set_attr "length" "8") + (set_attr "type" "vecsimple")]) + +(define_insn "*ieee_128bit_vsx_abs<mode>2_internal" + [(set (match_operand:TFIFKF 0 "register_operand" "=wa") + (abs:TFIFKF (match_operand:TFIFKF 1 "register_operand" "wa"))) + (use (match_operand:V16QI 2 "register_operand" "=v"))] + "TARGET_FLOAT128" + "xxlandc %x0,%x1,%x2" + [(set_attr "type" "vecsimple")]) + +;; IEEE 128-bit negative absolute value +(define_insn_and_split "*ieee_128bit_vsx_nabs<mode>2" + [(set (match_operand:TFIFKF 0 "register_operand" "=wa") + (neg:TFIFKF + (abs:TFIFKF + (match_operand:TFIFKF 1 "register_operand" "wa")))) + (clobber (match_scratch:V16QI 2 "=v"))] + "TARGET_FLOAT128 && FLOAT128_IEEE_P (<MODE>mode)" + "#" + "&& 1" + [(parallel [(set (match_dup 0) + (abs:TFIFKF (match_dup 1))) + (use (match_dup 2))])] +{ + if (GET_CODE (operands[2]) == SCRATCH) + operands[2] = gen_reg_rtx (V16QImode); + + operands[3] = gen_reg_rtx (V16QImode); + emit_insn (gen_ieee_128bit_negative_zero (operands[2])); +} + [(set_attr "length" "8") + (set_attr "type" "vecsimple")]) + +(define_insn "*ieee_128bit_vsx_nabs<mode>2_internal" + [(set (match_operand:TFIFKF 0 "register_operand" "=wa") + (neg:TFIFKF + (abs:TFIFKF + (match_operand:TFIFKF 1 "register_operand" "wa")))) + (use (match_operand:V16QI 2 "register_operand" "=v"))] + "TARGET_FLOAT128" + "xxlor %x0,%x1,%x2" + [(set_attr "type" "vecsimple")]) + +;; Float128 conversion functions. These expand to library function calls. + +(define_expand "extend<FLOAT128_SFDFTF:mode><IFKF:mode>2" + [(set (match_operand:IFKF 0 "nonimmediate_operand" "") + (float_extend:IFKF + (match_operand:FLOAT128_SFDFTF 1 "gpc_reg_operand" "")))] + "TARGET_FLOAT128" +{ + rs6000_expand_float128_convert (operands[0], operands[1], false); + DONE; +}) + +(define_expand "trunc<IFKF:mode><FLOAT128_SFDFTF:mode>2" + [(set (match_operand:FLOAT128_SFDFTF 0 "nonimmediate_operand" "") + (float_truncate:FLOAT128_SFDFTF + (match_operand:IFKF 1 "gpc_reg_operand" "")))] + "TARGET_FLOAT128" +{ + rs6000_expand_float128_convert (operands[0], operands[1], false); + DONE; +}) + +(define_expand "fix_trunc<IFKF:mode><SDI:mode>2" + [(set (match_operand:SDI 0 "nonimmediate_operand" "") + (fix:SDI (match_operand:IFKF 1 "gpc_reg_operand" "")))] + "TARGET_FLOAT128" +{ + rs6000_expand_float128_convert (operands[0], operands[1], false); + DONE; +}) + +(define_expand "fixuns_trunc<IFKF:mode><SDI:mode>2" + [(set (match_operand:SDI 0 "nonimmediate_operand" "") + (unsigned_fix:SDI (match_operand:IFKF 1 "gpc_reg_operand" "")))] + "TARGET_FLOAT128" +{ + rs6000_expand_float128_convert (operands[0], operands[1], true); + DONE; +}) + +(define_expand "float<SDI:mode><IFKF:mode>2" + [(set (match_operand:IFKF 0 "nonimmediate_operand" "") + (float:KF (match_operand:SDI 1 "gpc_reg_operand" "")))] + "TARGET_FLOAT128" +{ + rs6000_expand_float128_convert (operands[0], operands[1], false); + DONE; +}) + +(define_expand "floatuns<SDI:mode><IFKF:mode>2" + [(set (match_operand:IFKF 0 "nonimmediate_operand" "") + (unsigned_float:IFKF (match_operand:SDI 1 "gpc_reg_operand" "")))] + "TARGET_FLOAT128" +{ + rs6000_expand_float128_convert (operands[0], operands[1], true); + DONE; +}) + ;; Reload helper functions used by rs6000_secondary_reload. The patterns all ;; must have 3 arguments, and scratch register constraint must be a single @@ -9516,7 +9795,7 @@ { int i; - emit_call_insn (GEN_CALL (operands[0], const0_rtx, const0_rtx, const0_rtx)); + emit_call_insn (gen_call (operands[0], const0_rtx, const0_rtx)); for (i = 0; i < XVECLEN (operands[2], 0); i++) { @@ -12134,7 +12413,10 @@ ;; Pack/unpack 128-bit floating point types that take 2 scalar registers ; Type of the 64-bit part when packing/unpacking 128-bit floating point types -(define_mode_attr FP128_64 [(TF "DF") (TD "DI")]) +(define_mode_attr FP128_64 [(TF "DF") + (IF "DF") + (TD "DI") + (KF "DI")]) (define_expand "unpack<mode>" [(set (match_operand:<FP128_64> 0 "nonimmediate_operand" "") @@ -12142,7 +12424,7 @@ [(match_operand:FMOVE128 1 "register_operand" "") (match_operand:QI 2 "const_0_to_1_operand" "")] UNSPEC_UNPACK_128BIT))] - "" + "FLOAT128_2REG_P (<MODE>mode)" "") (define_insn_and_split "unpack<mode>_dm" @@ -12151,7 +12433,7 @@ [(match_operand:FMOVE128 1 "register_operand" "d,d,r,d,r") (match_operand:QI 2 "const_0_to_1_operand" "i,i,i,i,i")] UNSPEC_UNPACK_128BIT))] - "TARGET_POWERPC64 && TARGET_DIRECT_MOVE" + "TARGET_POWERPC64 && TARGET_DIRECT_MOVE && FLOAT128_2REG_P (<MODE>mode)" "#" "&& reload_completed" [(set (match_dup 0) (match_dup 3))] @@ -12175,7 +12457,7 @@ [(match_operand:FMOVE128 1 "register_operand" "d,d") (match_operand:QI 2 "const_0_to_1_operand" "i,i")] UNSPEC_UNPACK_128BIT))] - "!TARGET_POWERPC64 || !TARGET_DIRECT_MOVE" + "(!TARGET_POWERPC64 || !TARGET_DIRECT_MOVE) && FLOAT128_2REG_P (<MODE>mode)" "#" "&& reload_completed" [(set (match_dup 0) (match_dup 3))] @@ -12199,7 +12481,7 @@ [(match_operand:<FP128_64> 1 "register_operand" "0,d") (match_operand:<FP128_64> 2 "register_operand" "d,d")] UNSPEC_PACK_128BIT))] - "" + "FLOAT128_2REG_P (<MODE>mode)" "@ fmr %L0,%2 #" @@ -12219,12 +12501,12 @@ [(set_attr "type" "fp,fp") (set_attr "length" "4,8")]) -(define_insn "unpackv1ti" +(define_insn "unpack<mode>" [(set (match_operand:DI 0 "register_operand" "=d,d") - (unspec:DI [(match_operand:V1TI 1 "register_operand" "0,wa") + (unspec:DI [(match_operand:FMOVE128_VSX 1 "register_operand" "0,wa") (match_operand:QI 2 "const_0_to_1_operand" "O,i")] UNSPEC_UNPACK_128BIT))] - "TARGET_VSX" + "VECTOR_MEM_ALTIVEC_OR_VSX_P (<MODE>mode)" { if (REGNO (operands[0]) == REGNO (operands[1]) && INTVAL (operands[2]) == 0) return ASM_COMMENT_START " xxpermdi to same register"; @@ -12232,19 +12514,17 @@ operands[3] = GEN_INT (INTVAL (operands[2]) == 0 ? 0 : 3); return "xxpermdi %x0,%x1,%x1,%3"; } - [(set_attr "type" "vecperm") - (set_attr "length" "4")]) + [(set_attr "type" "vecperm")]) -(define_insn "packv1ti" - [(set (match_operand:V1TI 0 "register_operand" "=wa") - (unspec:V1TI +(define_insn "pack<mode>" + [(set (match_operand:FMOVE128_VSX 0 "register_operand" "=wa") + (unspec:FMOVE128_VSX [(match_operand:DI 1 "register_operand" "d") (match_operand:DI 2 "register_operand" "d")] UNSPEC_PACK_128BIT))] "TARGET_VSX" "xxpermdi %x0,%x1,%x2,0" - [(set_attr "type" "vecperm") - (set_attr "length" "4")]) + [(set_attr "type" "vecperm")]) diff --git a/gcc/config/rs6000/rs6000.opt b/gcc/config/rs6000/rs6000.opt index 18ea27a3d90..6d11ff7dfdb 100644 --- a/gcc/config/rs6000/rs6000.opt +++ b/gcc/config/rs6000/rs6000.opt @@ -212,7 +212,7 @@ Target Undocumented Var(TARGET_ALLOW_MOVMISALIGN) Init(-1) Save ; Allow/disallow the movmisalign in DF/DI vectors mefficient-unaligned-vector -Target Undocumented Report Var(TARGET_EFFICIENT_UNALIGNED_VSX) Init(-1) +Target Undocumented Report Mask(EFFICIENT_UNALIGNED_VSX) Var(rs6000_isa_flags) ; Consider unaligned VSX accesses to be efficient/inefficient mallow-df-permute diff --git a/gcc/config/rs6000/sysv4.h b/gcc/config/rs6000/sysv4.h index 24618e309f1..f48af43e7c5 100644 --- a/gcc/config/rs6000/sysv4.h +++ b/gcc/config/rs6000/sysv4.h @@ -574,7 +574,6 @@ ENDIAN_SELECT(" -mbig", " -mlittle", DEFAULT_ASM_ENDIAN) %{R*} \ %(link_shlib) \ %{!T*: %(link_start) } \ -%(link_target) \ %(link_os)" /* Shared libraries are not default. */ @@ -584,10 +583,6 @@ ENDIAN_SELECT(" -mbig", " -mlittle", DEFAULT_ASM_ENDIAN) %{shared:-G -dy -z text } \ %{symbolic:-Bsymbolic -G -dy -z text }" -/* Override the default target of the linker. */ -#define LINK_TARGET_SPEC \ - ENDIAN_SELECT("", " --oformat elf32-powerpcle", "") - /* Any specific OS flags. */ #define LINK_OS_SPEC "\ %{mads : %(link_os_ads) ; \ @@ -873,7 +868,6 @@ ncrtn.o%s" { "endfile_openbsd", ENDFILE_OPENBSD_SPEC }, \ { "endfile_default", ENDFILE_DEFAULT_SPEC }, \ { "link_shlib", LINK_SHLIB_SPEC }, \ - { "link_target", LINK_TARGET_SPEC }, \ { "link_start", LINK_START_SPEC }, \ { "link_start_ads", LINK_START_ADS_SPEC }, \ { "link_start_yellowknife", LINK_START_YELLOWKNIFE_SPEC }, \ diff --git a/gcc/config/rs6000/sysv4le.h b/gcc/config/rs6000/sysv4le.h index 7b1d6a1b4de..66ee7cadfe4 100644 --- a/gcc/config/rs6000/sysv4le.h +++ b/gcc/config/rs6000/sysv4le.h @@ -25,10 +25,6 @@ #undef DEFAULT_ASM_ENDIAN #define DEFAULT_ASM_ENDIAN " -mlittle" -#undef LINK_TARGET_SPEC -#define LINK_TARGET_SPEC \ - ENDIAN_SELECT(" --oformat elf32-powerpc", "", "") - #undef MULTILIB_DEFAULTS #define MULTILIB_DEFAULTS { "mlittle", "mcall-sysv" } diff --git a/gcc/config/rs6000/vector.md b/gcc/config/rs6000/vector.md index 4a62fbbbdd4..8821dec5989 100644 --- a/gcc/config/rs6000/vector.md +++ b/gcc/config/rs6000/vector.md @@ -977,6 +977,8 @@ ;; General shift amounts can be supported using vsro + vsr. We're ;; not expecting to see these yet (the vectorizer currently ;; generates only shifts by a whole number of vector elements). +;; Note that the vec_shr operation is actually defined as +;; 'shift toward element 0' so is a shr for LE and shl for BE. (define_expand "vec_shr_<mode>" [(match_operand:VEC_L 0 "vlogical_operand" "") (match_operand:VEC_L 1 "vlogical_operand" "") @@ -987,6 +989,7 @@ rtx bitshift = operands[2]; rtx shift; rtx insn; + rtx zero_reg, op1, op2; HOST_WIDE_INT bitshift_val; HOST_WIDE_INT byteshift_val; @@ -996,19 +999,29 @@ if (bitshift_val & 0x7) FAIL; byteshift_val = (bitshift_val >> 3); + zero_reg = gen_reg_rtx (<MODE>mode); + emit_move_insn (zero_reg, CONST0_RTX (<MODE>mode)); if (!BYTES_BIG_ENDIAN) - byteshift_val = 16 - byteshift_val; + { + byteshift_val = 16 - byteshift_val; + op1 = zero_reg; + op2 = operands[1]; + } + else + { + op1 = operands[1]; + op2 = zero_reg; + } + if (TARGET_VSX && (byteshift_val & 0x3) == 0) { shift = gen_rtx_CONST_INT (QImode, byteshift_val >> 2); - insn = gen_vsx_xxsldwi_<mode> (operands[0], operands[1], operands[1], - shift); + insn = gen_vsx_xxsldwi_<mode> (operands[0], op1, op2, shift); } else { shift = gen_rtx_CONST_INT (QImode, byteshift_val); - insn = gen_altivec_vsldoi_<mode> (operands[0], operands[1], operands[1], - shift); + insn = gen_altivec_vsldoi_<mode> (operands[0], op1, op2, shift); } emit_insn (insn); diff --git a/gcc/config/rx/rx.md b/gcc/config/rx/rx.md index 8b124759b0b..6faf7719a9a 100644 --- a/gcc/config/rx/rx.md +++ b/gcc/config/rx/rx.md @@ -2315,7 +2315,7 @@ emit_move_insn (str1, force_operand (XEXP (operands[1], 0), NULL_RTX)); emit_move_insn (str2, force_operand (XEXP (operands[2], 0), NULL_RTX)); - emit_move_insn (len, force_operand (operands[3], NULL_RTX)); + emit_move_insn (len, operands[3]); emit_insn (gen_rx_cmpstrn (operands[0], operands[1], operands[2])); DONE; diff --git a/gcc/config/s390/s390-builtins.def b/gcc/config/s390/s390-builtins.def index 0a24da9bcb1..b267b04e2a7 100644 --- a/gcc/config/s390/s390-builtins.def +++ b/gcc/config/s390/s390-builtins.def @@ -438,15 +438,15 @@ B_DEF (s390_vllezf, vec_insert_and_zerov4si,0, B_DEF (s390_vllezg, vec_insert_and_zerov2di,0, B_VX, 0, BT_FN_UV2DI_ULONGLONGCONSTPTR) OB_DEF (s390_vec_load_bndry, s390_vec_load_bndry_s8,s390_vec_load_bndry_dbl,B_VX, BT_FN_OV4SI_INTCONSTPTR_INT) -OB_DEF_VAR (s390_vec_load_bndry_s8, s390_vlbb, O2_U3, BT_OV_V16QI_SCHARCONSTPTR_USHORT) -OB_DEF_VAR (s390_vec_load_bndry_u8, s390_vlbb, O2_U3, BT_OV_UV16QI_UCHARCONSTPTR_USHORT) -OB_DEF_VAR (s390_vec_load_bndry_s16, s390_vlbb, O2_U3, BT_OV_V8HI_SHORTCONSTPTR_USHORT) -OB_DEF_VAR (s390_vec_load_bndry_u16, s390_vlbb, O2_U3, BT_OV_UV8HI_USHORTCONSTPTR_USHORT) -OB_DEF_VAR (s390_vec_load_bndry_s32, s390_vlbb, O2_U3, BT_OV_V4SI_INTCONSTPTR_USHORT) -OB_DEF_VAR (s390_vec_load_bndry_u32, s390_vlbb, O2_U3, BT_OV_UV4SI_UINTCONSTPTR_USHORT) -OB_DEF_VAR (s390_vec_load_bndry_s64, s390_vlbb, O2_U3, BT_OV_V2DI_LONGLONGCONSTPTR_USHORT) -OB_DEF_VAR (s390_vec_load_bndry_u64, s390_vlbb, O2_U3, BT_OV_UV2DI_ULONGLONGCONSTPTR_USHORT) -OB_DEF_VAR (s390_vec_load_bndry_dbl, s390_vlbb, O2_U3, BT_OV_V2DF_DBLCONSTPTR_USHORT) +OB_DEF_VAR (s390_vec_load_bndry_s8, s390_vlbb, O2_U16, BT_OV_V16QI_SCHARCONSTPTR_USHORT) +OB_DEF_VAR (s390_vec_load_bndry_u8, s390_vlbb, O2_U16, BT_OV_UV16QI_UCHARCONSTPTR_USHORT) +OB_DEF_VAR (s390_vec_load_bndry_s16, s390_vlbb, O2_U16, BT_OV_V8HI_SHORTCONSTPTR_USHORT) +OB_DEF_VAR (s390_vec_load_bndry_u16, s390_vlbb, O2_U16, BT_OV_UV8HI_USHORTCONSTPTR_USHORT) +OB_DEF_VAR (s390_vec_load_bndry_s32, s390_vlbb, O2_U16, BT_OV_V4SI_INTCONSTPTR_USHORT) +OB_DEF_VAR (s390_vec_load_bndry_u32, s390_vlbb, O2_U16, BT_OV_UV4SI_UINTCONSTPTR_USHORT) +OB_DEF_VAR (s390_vec_load_bndry_s64, s390_vlbb, O2_U16, BT_OV_V2DI_LONGLONGCONSTPTR_USHORT) +OB_DEF_VAR (s390_vec_load_bndry_u64, s390_vlbb, O2_U16, BT_OV_UV2DI_ULONGLONGCONSTPTR_USHORT) +OB_DEF_VAR (s390_vec_load_bndry_dbl, s390_vlbb, O2_U16, BT_OV_V2DF_DBLCONSTPTR_USHORT) B_DEF (s390_vlbb, vlbb, 0, B_VX, O2_U3, BT_FN_UV16QI_UCHARCONSTPTR_USHORT) diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index 5814694adbc..cbfc80073c9 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -2258,23 +2258,14 @@ s390_contiguous_bitmask_vector_p (rtx op, int *start, int *end) { unsigned HOST_WIDE_INT mask; int length, size; + rtx elt; - if (!VECTOR_MODE_P (GET_MODE (op)) - || GET_CODE (op) != CONST_VECTOR - || !CONST_INT_P (XVECEXP (op, 0, 0))) + if (!const_vec_duplicate_p (op, &elt) + || !CONST_INT_P (elt)) return false; - if (GET_MODE_NUNITS (GET_MODE (op)) > 1) - { - int i; - - for (i = 1; i < GET_MODE_NUNITS (GET_MODE (op)); ++i) - if (!rtx_equal_p (XVECEXP (op, 0, i), XVECEXP (op, 0, 0))) - return false; - } - size = GET_MODE_UNIT_BITSIZE (GET_MODE (op)); - mask = UINTVAL (XVECEXP (op, 0, 0)); + mask = UINTVAL (elt); if (s390_contiguous_bitmask_p (mask, size, start, end != NULL ? &length : NULL)) { @@ -10360,6 +10351,7 @@ s390_emit_prologue (void) current_function_name(), cfun_frame_layout.frame_size, s390_stack_size); emit_insn (gen_trap ()); + emit_barrier (); } else { diff --git a/gcc/config/sh/sh-protos.h b/gcc/config/sh/sh-protos.h index 5a552e2be81..3e4211be4de 100644 --- a/gcc/config/sh/sh-protos.h +++ b/gcc/config/sh/sh-protos.h @@ -159,6 +159,7 @@ extern int sh_eval_treg_value (rtx op); extern HOST_WIDE_INT sh_disp_addr_displacement (rtx mem_op); extern int sh_max_mov_insn_displacement (machine_mode mode, bool consider_sh2a); extern bool sh_movsf_ie_ra_split_p (rtx, rtx, rtx); +extern void sh_expand_sym_label2reg (rtx, rtx, rtx, bool); /* Result value of sh_find_set_of_reg. */ struct set_of_reg diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index 450d634e246..1442b7fc790 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -1604,6 +1604,10 @@ sh_asm_output_addr_const_extra (FILE *file, rtx x) output_addr_const (file, XVECEXP (x, 0, 0)); fputs ("@GOTPLT", file); break; + case UNSPEC_PCREL: + output_addr_const (file, XVECEXP (x, 0, 0)); + fputs ("@PCREL", file); + break; case UNSPEC_DTPOFF: output_addr_const (file, XVECEXP (x, 0, 0)); fputs ("@DTPOFF", file); @@ -10441,6 +10445,7 @@ nonpic_symbol_mentioned_p (rtx x) || XINT (x, 1) == UNSPEC_DTPOFF || XINT (x, 1) == UNSPEC_TPOFF || XINT (x, 1) == UNSPEC_PLT + || XINT (x, 1) == UNSPEC_PCREL || XINT (x, 1) == UNSPEC_SYMOFF || XINT (x, 1) == UNSPEC_PCREL_SYMOFF)) return false; @@ -10714,7 +10719,8 @@ sh_delegitimize_address (rtx orig_x) rtx symplt = XEXP (XVECEXP (y, 0, 0), 0); if (GET_CODE (symplt) == UNSPEC - && XINT (symplt, 1) == UNSPEC_PLT) + && (XINT (symplt, 1) == UNSPEC_PLT + || XINT (symplt, 1) == UNSPEC_PCREL)) return XVECEXP (symplt, 0, 0); } } @@ -11702,9 +11708,24 @@ sh_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED) || crtl->args.info.stack_regs == 0) && ! sh_cfun_interrupt_handler_p () && (! flag_pic - || (decl && ! TREE_PUBLIC (decl)) + || (decl && ! (TREE_PUBLIC (decl) || DECL_WEAK (decl))) || (decl && DECL_VISIBILITY (decl) != VISIBILITY_DEFAULT))); } + +/* Expand to appropriate sym*_label2reg for SYM and SIBCALL_P. */ +void +sh_expand_sym_label2reg (rtx reg, rtx sym, rtx lab, bool sibcall_p) +{ + const_tree decl = SYMBOL_REF_DECL (sym); + bool is_weak = (decl && DECL_P (decl) && DECL_WEAK (decl)); + + if (!is_weak && SYMBOL_REF_LOCAL_P (sym)) + emit_insn (gen_sym_label2reg (reg, sym, lab)); + else if (sibcall_p) + emit_insn (gen_symPCREL_label2reg (reg, sym, lab)); + else + emit_insn (gen_symPLT_label2reg (reg, sym, lab)); +} /* Machine specific built-in functions. */ diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md index ad49f72c68d..4e7cd169f84 100644 --- a/gcc/config/sh/sh.md +++ b/gcc/config/sh/sh.md @@ -135,6 +135,7 @@ UNSPEC_PLT UNSPEC_CALLER UNSPEC_GOTPLT + UNSPEC_PCREL UNSPEC_ICACHE UNSPEC_INIT_TRAMP UNSPEC_FCOSA @@ -9470,11 +9471,8 @@ label: [(const_int 0)] { rtx lab = PATTERN (gen_call_site ()); - - if (SYMBOL_REF_LOCAL_P (operands[0])) - emit_insn (gen_sym_label2reg (operands[2], operands[0], lab)); - else - emit_insn (gen_symPLT_label2reg (operands[2], operands[0], lab)); + + sh_expand_sym_label2reg (operands[2], operands[0], lab, false); emit_call_insn (gen_calli_pcrel (operands[2], operands[1], copy_rtx (lab))); DONE; } @@ -9605,10 +9603,7 @@ label: { rtx lab = PATTERN (gen_call_site ()); - if (SYMBOL_REF_LOCAL_P (operands[1])) - emit_insn (gen_sym_label2reg (operands[3], operands[1], lab)); - else - emit_insn (gen_symPLT_label2reg (operands[3], operands[1], lab)); + sh_expand_sym_label2reg (operands[3], operands[1], lab, false); emit_call_insn (gen_call_valuei_pcrel (operands[0], operands[3], operands[2], copy_rtx (lab))); DONE; @@ -10008,7 +10003,7 @@ label: rtx lab = PATTERN (gen_call_site ()); rtx call_insn; - emit_insn (gen_sym_label2reg (operands[2], operands[0], lab)); + sh_expand_sym_label2reg (operands[2], operands[0], lab, true); call_insn = emit_call_insn (gen_sibcalli_pcrel (operands[2], operands[1], copy_rtx (lab))); SIBLING_CALL_P (call_insn) = 1; @@ -10200,7 +10195,7 @@ label: rtx lab = PATTERN (gen_call_site ()); rtx call_insn; - emit_insn (gen_sym_label2reg (operands[3], operands[1], lab)); + sh_expand_sym_label2reg (operands[3], operands[1], lab, true); call_insn = emit_call_insn (gen_sibcall_valuei_pcrel (operands[0], operands[3], operands[2], @@ -10748,6 +10743,16 @@ label: UNSPEC_SYMOFF)))] "TARGET_SH1" "") +(define_expand "symPCREL_label2reg" + [(set (match_operand:SI 0 "" "") + (const:SI + (unspec:SI + [(const:SI (unspec:SI [(match_operand:SI 1 "" "")] UNSPEC_PCREL)) + (const:SI (plus:SI (match_operand:SI 2 "" "") + (const_int 2)))] UNSPEC_PCREL_SYMOFF)))] + "TARGET_SH1" + "") + (define_expand "symGOT_load" [(set (match_dup 2) (match_operand 1 "" "")) (set (match_dup 3) (plus (match_dup 2) (reg PIC_REG))) @@ -12731,7 +12736,7 @@ label: [(set (match_operand:SI 0 "register_operand") (compare:SI (match_operand:BLK 1 "memory_operand") (match_operand:BLK 2 "memory_operand"))) - (use (match_operand:SI 3 "immediate_operand")) + (use (match_operand:SI 3 "nonmemory_operand")) (use (match_operand:SI 4 "immediate_operand"))] "TARGET_SH1 && optimize" { diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md index 9665ee6da9b..5b9f0517b90 100644 --- a/gcc/config/sparc/sparc.md +++ b/gcc/config/sparc/sparc.md @@ -6403,7 +6403,7 @@ /* Pass constm1 to indicate that it may expect a structure value, but we don't know what size it is. */ - emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, constm1_rtx)); + emit_call_insn (gen_call (operands[0], const0_rtx, NULL, constm1_rtx)); /* Save the function value registers. */ emit_move_insn (adjust_address (result, DImode, 0), valreg1); diff --git a/gcc/config/spu/spu.c b/gcc/config/spu/spu.c index ca762877a0f..05c81f5ed73 100644 --- a/gcc/config/spu/spu.c +++ b/gcc/config/spu/spu.c @@ -3185,11 +3185,8 @@ classify_immediate (rtx op, machine_mode mode) && mode == V4SImode && GET_CODE (op) == CONST_VECTOR && GET_CODE (CONST_VECTOR_ELT (op, 0)) != CONST_INT - && GET_CODE (CONST_VECTOR_ELT (op, 0)) != CONST_DOUBLE - && CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 1) - && CONST_VECTOR_ELT (op, 1) == CONST_VECTOR_ELT (op, 2) - && CONST_VECTOR_ELT (op, 2) == CONST_VECTOR_ELT (op, 3)) - op = CONST_VECTOR_ELT (op, 0); + && GET_CODE (CONST_VECTOR_ELT (op, 0)) != CONST_DOUBLE) + op = unwrap_const_vec_duplicate (op); switch (GET_CODE (op)) { @@ -3507,9 +3504,7 @@ spu_legitimate_constant_p (machine_mode mode, rtx x) && (GET_CODE (CONST_VECTOR_ELT (x, 0)) == SYMBOL_REF || GET_CODE (CONST_VECTOR_ELT (x, 0)) == LABEL_REF || GET_CODE (CONST_VECTOR_ELT (x, 0)) == CONST)) - return CONST_VECTOR_ELT (x, 0) == CONST_VECTOR_ELT (x, 1) - && CONST_VECTOR_ELT (x, 1) == CONST_VECTOR_ELT (x, 2) - && CONST_VECTOR_ELT (x, 2) == CONST_VECTOR_ELT (x, 3); + return const_vec_duplicate_p (x); if (GET_CODE (x) == CONST_VECTOR && !const_vector_immediate_p (x)) diff --git a/gcc/config/tilegx/constraints.md b/gcc/config/tilegx/constraints.md index 783e1ca98fe..f47d0f68296 100644 --- a/gcc/config/tilegx/constraints.md +++ b/gcc/config/tilegx/constraints.md @@ -96,21 +96,14 @@ "An 8-element vector constant with identical elements" (and (match_code "const_vector") (match_test "CONST_VECTOR_NUNITS (op) == 8") - (match_test "CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 1)") - (match_test "CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 2)") - (match_test "CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 3)") - (match_test "CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 4)") - (match_test "CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 5)") - (match_test "CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 6)") - (match_test "CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 7)"))) + (match_test "const_vec_duplicate_p (op)"))) (define_constraint "Y" "A 4-element vector constant with identical elements" (and (match_code "const_vector") (match_test "CONST_VECTOR_NUNITS (op) == 4") - (match_test "CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 1)") - (match_test "CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 2)") - (match_test "CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 3)"))) + (match_test "const_vec_duplicate_p (op)"))) + (define_constraint "Z0" "The integer constant 0xffffffff" (and (match_code "const_int") diff --git a/gcc/config/tilegx/predicates.md b/gcc/config/tilegx/predicates.md index 4cbebf18a91..ce04660f9ed 100644 --- a/gcc/config/tilegx/predicates.md +++ b/gcc/config/tilegx/predicates.md @@ -112,14 +112,8 @@ (ior (match_operand 0 "register_operand") (and (match_code "const_vector") (match_test "CONST_VECTOR_NUNITS (op) == 8 - && satisfies_constraint_I (CONST_VECTOR_ELT (op, 0)) - && CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 1) - && CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 2) - && CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 3) - && CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 4) - && CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 5) - && CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 6) - && CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 7)")))) + && (satisfies_constraint_I + (unwrap_const_vec_duplicate (op)))")))) ;; Return 1 if OP is a 4-element vector constant with identical signed ;; 8-bit elements or any register. @@ -127,10 +121,8 @@ (ior (match_operand 0 "register_operand") (and (match_code "const_vector") (match_test "CONST_VECTOR_NUNITS (op) == 4 - && satisfies_constraint_I (CONST_VECTOR_ELT (op, 0)) - && CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 1) - && CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 2) - && CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 3)")))) + && (satisfies_constraint_I + (unwrap_const_vec_duplicate (op)))")))) ;; Return 1 if the operand is a valid second operand to an add insn. (define_predicate "add_operand" diff --git a/gcc/config/tilegx/tilegx.md b/gcc/config/tilegx/tilegx.md index 75322e16721..944953c34b2 100644 --- a/gcc/config/tilegx/tilegx.md +++ b/gcc/config/tilegx/tilegx.md @@ -2670,7 +2670,7 @@ { int i; - emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx)); + emit_call_insn (gen_call (operands[0], const0_rtx)); for (i = 0; i < XVECLEN (operands[2], 0); i++) { diff --git a/gcc/config/tilepro/constraints.md b/gcc/config/tilepro/constraints.md index 4d13fb0640a..3ab9ab75650 100644 --- a/gcc/config/tilepro/constraints.md +++ b/gcc/config/tilepro/constraints.md @@ -90,12 +90,10 @@ "A 4-element vector constant with identical elements" (and (match_code "const_vector") (match_test "CONST_VECTOR_NUNITS (op) == 4") - (match_test "CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 1)") - (match_test "CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 2)") - (match_test "CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 3)"))) + (match_test "const_vec_duplicate_p (op)"))) (define_constraint "Y" "A 2-element vector constant with identical elements" (and (match_code "const_vector") (match_test "CONST_VECTOR_NUNITS (op) == 2") - (match_test "CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 1)"))) + (match_test "const_vec_duplicate_p (op)"))) diff --git a/gcc/config/tilepro/predicates.md b/gcc/config/tilepro/predicates.md index 00d2bb989cd..ab62d20731a 100644 --- a/gcc/config/tilepro/predicates.md +++ b/gcc/config/tilepro/predicates.md @@ -75,10 +75,8 @@ (ior (match_operand 0 "register_operand") (and (match_code "const_vector") (match_test "CONST_VECTOR_NUNITS (op) == 4 - && satisfies_constraint_I (CONST_VECTOR_ELT (op, 0)) - && CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 1) - && CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 2) - && CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 3)")))) + && (satisfies_constraint_I + (unwrap_const_vec_duplicate (op)))")))) ;; Return 1 if OP is a 2-element vector constant with identical signed ;; 8-bit elements or any register. @@ -86,8 +84,8 @@ (ior (match_operand 0 "register_operand") (and (match_code "const_vector") (match_test "CONST_VECTOR_NUNITS (op) == 2 - && satisfies_constraint_I (CONST_VECTOR_ELT (op, 0)) - && CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 1)")))) + && (satisfies_constraint_I + (unwrap_const_vec_duplicate (op)))")))) ;; Return 1 if the operand is a valid second operand to an add insn. (define_predicate "add_operand" diff --git a/gcc/config/tilepro/tilepro.md b/gcc/config/tilepro/tilepro.md index a97ebf9eb22..b1e6b81e71f 100644 --- a/gcc/config/tilepro/tilepro.md +++ b/gcc/config/tilepro/tilepro.md @@ -1516,7 +1516,7 @@ { int i; - emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx)); + emit_call_insn (gen_call (operands[0], const0_rtx)); for (i = 0; i < XVECLEN (operands[2], 0); i++) { diff --git a/gcc/config/visium/visium.md b/gcc/config/visium/visium.md index 969cb887a6c..370b6a4b5b2 100644 --- a/gcc/config/visium/visium.md +++ b/gcc/config/visium/visium.md @@ -2375,7 +2375,7 @@ { int i; - emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx)); + emit_call_insn (gen_call (operands[0], const0_rtx, NULL)); for (i = 0; i < XVECLEN (operands[2], 0); i++) { diff --git a/gcc/configure b/gcc/configure index 8e89dd9c6eb..0d313831aac 100755 --- a/gcc/configure +++ b/gcc/configure @@ -678,6 +678,7 @@ MAINT zlibinc zlibdir HOST_LIBS +enable_default_ssp libgcc_visibility gcc_cv_readelf gcc_cv_objdump @@ -930,6 +931,7 @@ enable_fix_cortex_a53_843419 with_glibc_version enable_gnu_unique_object enable_linker_build_id +enable_default_ssp with_long_double_128 with_gc with_system_zlib @@ -1666,6 +1668,7 @@ Optional Features: extension on glibc systems --enable-linker-build-id compiler will always pass --build-id to linker + --enable-default-ssp enable Stack Smashing Protection as default --enable-maintainer-mode enable make rules and dependencies not useful (and sometimes confusing) to the casual installer @@ -10611,31 +10614,6 @@ fi - am_save_CPPFLAGS="$CPPFLAGS" - - for element in $INCICONV; do - haveit= - for x in $CPPFLAGS; do - - acl_save_prefix="$prefix" - prefix="$acl_final_prefix" - acl_save_exec_prefix="$exec_prefix" - exec_prefix="$acl_final_exec_prefix" - eval x=\"$x\" - exec_prefix="$acl_save_exec_prefix" - prefix="$acl_save_prefix" - - if test "X$x" = "X$element"; then - haveit=yes - break - fi - done - if test -z "$haveit"; then - CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element" - fi - done - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for iconv" >&5 $as_echo_n "checking for iconv... " >&6; } if test "${am_cv_func_iconv+set}" = set; then : @@ -10644,6 +10622,8 @@ else am_cv_func_iconv="no, consider installing GNU libiconv" am_cv_lib_iconv=no + am_save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $INCICONV" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <stdlib.h> @@ -10663,8 +10643,49 @@ if ac_fn_cxx_try_link "$LINENO"; then : fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext + CPPFLAGS="$am_save_CPPFLAGS" + + if test "$am_cv_func_iconv" != yes && test -d ../libiconv; then + for _libs in .libs _libs; do + am_save_CPPFLAGS="$CPPFLAGS" + am_save_LIBS="$LIBS" + CPPFLAGS="$CPPFLAGS -I../libiconv/include" + LIBS="$LIBS ../libiconv/lib/$_libs/libiconv.a" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <stdlib.h> +#include <iconv.h> +int +main () +{ +iconv_t cd = iconv_open("",""); + iconv(cd,NULL,NULL,NULL,NULL); + iconv_close(cd); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + INCICONV="-I../libiconv/include" + LIBICONV='${top_builddir}'/../libiconv/lib/$_libs/libiconv.a + LTLIBICONV='${top_builddir}'/../libiconv/lib/libiconv.la + am_cv_lib_iconv=yes + am_cv_func_iconv=yes +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + CPPFLAGS="$am_save_CPPFLAGS" + LIBS="$am_save_LIBS" + if test "$am_cv_func_iconv" = "yes"; then + break + fi + done + fi + if test "$am_cv_func_iconv" != yes; then + am_save_CPPFLAGS="$CPPFLAGS" am_save_LIBS="$LIBS" + CPPFLAGS="$LIBS $INCICONV" LIBS="$LIBS $LIBICONV" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ @@ -10686,6 +10707,7 @@ if ac_fn_cxx_try_link "$LINENO"; then : fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext + CPPFLAGS="$am_save_CPPFLAGS" LIBS="$am_save_LIBS" fi @@ -10698,12 +10720,34 @@ $as_echo "#define HAVE_ICONV 1" >>confdefs.h fi if test "$am_cv_lib_iconv" = yes; then + + for element in $INCICONV; do + haveit= + for x in $CPPFLAGS; do + + acl_save_prefix="$prefix" + prefix="$acl_final_prefix" + acl_save_exec_prefix="$exec_prefix" + exec_prefix="$acl_final_exec_prefix" + eval x=\"$x\" + exec_prefix="$acl_save_exec_prefix" + prefix="$acl_save_prefix" + + if test "X$x" = "X$element"; then + haveit=yes + break + fi + done + if test -z "$haveit"; then + CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }$element" + fi + done + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libiconv" >&5 $as_echo_n "checking how to link with libiconv... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIBICONV" >&5 $as_echo "$LIBICONV" >&6; } else - CPPFLAGS="$am_save_CPPFLAGS" LIBICONV= LTLIBICONV= fi @@ -11906,7 +11950,7 @@ fi case $host_os in - win32 | pe | cygwin* | mingw32* | uwin*) + win32 | pe | cygwin* | mingw32*) if test "x$enable_win32_registry" != xno; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing RegOpenKeyExA" >&5 $as_echo_n "checking for library containing RegOpenKeyExA... " >&6; } @@ -18341,7 +18385,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 18344 "configure" +#line 18388 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -18447,7 +18491,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 18450 "configure" +#line 18494 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -23153,7 +23197,7 @@ else test $ac_status = 0; }; } then case $target_os in - win32 | pe | cygwin* | mingw32* | uwin*) + win32 | pe | cygwin* | mingw32*) # Need to check that we generated the correct relocation for the # .debug_frame section. This was fixed for binutils 2.21. gcc_cv_as_cfi_sections_directive=no @@ -28047,6 +28091,29 @@ $as_echo "#define TARGET_LIBC_PROVIDES_SSP 1" >>confdefs.h fi +# Check whether --enable-default-ssp was given. +# Check whether --enable-default-ssp was given. +if test "${enable_default_ssp+set}" = set; then : + enableval=$enable_default_ssp; +if test x$gcc_cv_libc_provides_ssp = xyes; then + case "$target" in + ia64*-*-*) enable_default_ssp=no ;; + *) enable_default_ssp=$enableval ;; + esac +else + enable_default_ssp=no +fi +else + enable_default_ssp=no +fi + +if test x$enable_default_ssp == xyes ; then + +$as_echo "#define ENABLE_DEFAULT_SSP 1" >>confdefs.h + +fi + + # Test for <sys/sdt.h> on the target. { $as_echo "$as_me:${as_lineno-$LINENO}: checking sys/sdt.h in the target C library" >&5 diff --git a/gcc/configure.ac b/gcc/configure.ac index c7d5d327a2e..846651d01f9 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -1795,7 +1795,7 @@ AS_HELP_STRING([--enable-win32-registry=KEY], of the registry key])],,) case $host_os in - win32 | pe | cygwin* | mingw32* | uwin*) + win32 | pe | cygwin* | mingw32*) if test "x$enable_win32_registry" != xno; then AC_SEARCH_LIBS(RegOpenKeyExA, advapi32,, [enable_win32_registry=no]) fi @@ -2752,7 +2752,7 @@ gcc_GAS_CHECK_FEATURE([cfi sections directive], .cfi_startproc .cfi_endproc], [case $target_os in - win32 | pe | cygwin* | mingw32* | uwin*) + win32 | pe | cygwin* | mingw32*) # Need to check that we generated the correct relocation for the # .debug_frame section. This was fixed for binutils 2.21. gcc_cv_as_cfi_sections_directive=no @@ -5329,6 +5329,25 @@ if test x$gcc_cv_libc_provides_ssp = xyes; then [Define if your target C library provides stack protector support]) fi +# Check whether --enable-default-ssp was given. +AC_ARG_ENABLE(default-ssp, +[AS_HELP_STRING([--enable-default-ssp], + [enable Stack Smashing Protection as default])],[ +if test x$gcc_cv_libc_provides_ssp = xyes; then + case "$target" in + ia64*-*-*) enable_default_ssp=no ;; + *) enable_default_ssp=$enableval ;; + esac +else + enable_default_ssp=no +fi], +enable_default_ssp=no) +if test x$enable_default_ssp == xyes ; then + AC_DEFINE(ENABLE_DEFAULT_SSP, 1, + [Define if your target supports default stack protector and it is enabled.]) +fi +AC_SUBST([enable_default_ssp]) + # Test for <sys/sdt.h> on the target. GCC_TARGET_TEMPLATE([HAVE_SYS_SDT_H]) AC_MSG_CHECKING(sys/sdt.h in the target C library) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 2c2cb6d5535..477bb209388 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,70 @@ +2015-09-01 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/61753 + * decl.c (smallest_type_quals_location): New. + (check_special_function_return_type): Use the latter; add int and + const location_t* parameters. + (grokdeclarator): Adjust check_special_function_return_type call. + +2015-08-29 Markus Trippelsdorf <markus@trippelsdorf.de> + + PR c++/67371 + * constexpr.c (potential_constant_expression_1): Remove IF_STMT + case. Move label to COND_EXPR case. Remove checking of + SWITCH_STMT_BODY. + +2015-08-22 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/63693 + * pt.c (resolve_typename_type): Use CLASSTYPE_PRIMARY_TEMPLATE_TYPE + only on class types. + +2015-08-21 Jason Merrill <jason@redhat.com> + + PR c++/67240 + * constraint.cc (satisfy_implicit_conversion_constraint): Also + check for NULL_TREE. + +2015-08-21 Paolo Carlini <paolo.carlini@oracle.com> + + * decl.c (grokvardecl): Simplify the latter. + +2015-08-21 Paolo Carlini <paolo.carlini@oracle.com> + + * decl.c (grokvardecl): Complete check added for c++/67065. + +2015-08-20 Jason Merrill <jason@redhat.com> + + * name-lookup.c (hidden_name_p): Handle OVERLOAD. + +2015-08-20 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/67065 + * decl.c (grokvardecl): Reject 'main' as global variable. + +2015-08-19 Jason Merrill <jason@redhat.com> + + PR c++/66957 + * search.c (protected_accessible_p): Remove redundant access_in_type. + Add otype parm instead of walking binfo. + (friend_accessible_p): Check SCOPE itself. Handle class + templates. Pass through otype. + (dfs_accessible_post): Handle all accessibility cases. + (dfs_accessible_pre): New. + (accessible_p): Use it. Don't check protected access here. Pass + decl and otype to dfs_walk. + (member_declared_in_type, dfs_access_in_type_pre): New. + (access_in_type): Use dfs_access_in_type_pre. + * friend.c (add_friend): Fix multiple friends with the same name. + + * lambda.c (current_nonlambda_scope): New. + +2015-08-18 Trevor Saunders <tbsaunde@tbsaunde.org> + + * call.c, class.c, cp-tree.h, decl.c, except.c, mangle.c, + method.c, name-lookup.h, parser.c, parser.h, rtti.c, + semantics.c, typeck2.c: Remove useless typedefs. + 2015-08-18 Jason Merrill <jason@redhat.com> DR 1155 diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 1eacb8be9a4..0ff9b088cc2 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -4273,15 +4273,6 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, return false; return true; - case IF_STMT: - if (!RECUR (IF_COND (t), rval)) - return false; - if (!RECUR (THEN_CLAUSE (t), any)) - return false; - if (!RECUR (ELSE_CLAUSE (t), any)) - return false; - return true; - case DO_STMT: if (!RECUR (DO_COND (t), rval)) return false; @@ -4310,8 +4301,8 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, case SWITCH_STMT: if (!RECUR (SWITCH_STMT_COND (t), rval)) return false; - if (!RECUR (SWITCH_STMT_BODY (t), any)) - return false; + /* FIXME we don't check SWITCH_STMT_BODY currently, because even + unreachable labels would be checked. */ return true; case STMT_EXPR: @@ -4592,6 +4583,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, return false; return true; + case IF_STMT: case COND_EXPR: case VEC_COND_EXPR: /* If the condition is a known constant, we know which of the legs we diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc index c981212271d..cb82535af49 100644 --- a/gcc/cp/constraint.cc +++ b/gcc/cp/constraint.cc @@ -1775,7 +1775,7 @@ satisfy_implicit_conversion_constraint (tree t, tree args, of the form TYPE <unspecified> = EXPR. */ tree conv = perform_direct_initialization_if_possible (type, expr, false, complain); - if (conv == error_mark_node) + if (conv == NULL_TREE || conv == error_mark_node) return boolean_false_node; else return boolean_true_node; diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index ab6b3ec6206..529eeeca9c0 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -6309,6 +6309,7 @@ extern tree lambda_expr_this_capture (tree, bool); extern tree maybe_resolve_dummy (tree, bool); extern tree current_nonlambda_function (void); extern tree nonlambda_method_basetype (void); +extern tree current_nonlambda_scope (void); extern void maybe_add_lambda_conv_op (tree); extern bool is_lambda_ignored_entity (tree); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index e8ed472293b..d1772673708 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -113,7 +113,7 @@ static void end_cleanup_fn (void); static tree cp_make_fname_decl (location_t, tree, int); static void initialize_predefined_identifiers (void); static tree check_special_function_return_type - (special_function_kind, tree, tree); + (special_function_kind, tree, tree, int, const location_t*); static tree push_cp_library_fn (enum tree_code, tree, int); static tree build_cp_library_fn (tree, enum tree_code, tree, int); static void store_parm_decls (tree); @@ -8355,6 +8355,11 @@ grokvardecl (tree type, else DECL_INTERFACE_KNOWN (decl) = 1; + if (DECL_NAME (decl) + && MAIN_NAME_P (DECL_NAME (decl)) + && scope == global_namespace) + error ("cannot declare %<::main%> to be a global variable"); + /* Check that the variable can be safely declared as a concept. Note that this also forbids explicit specializations. */ if (conceptp) @@ -8919,24 +8924,51 @@ create_array_type_for_decl (tree name, tree type, tree size) return build_cplus_array_type (type, itype); } -/* Check that it's OK to declare a function with the indicated TYPE. - SFK indicates the kind of special function (if any) that this - function is. OPTYPE is the type given in a conversion operator - declaration, or the class type for a constructor/destructor. - Returns the actual return type of the function; that - may be different than TYPE if an error occurs, or for certain - special functions. */ +/* Returns the smallest location != UNKNOWN_LOCATION among the + three stored in LOCATIONS[ds_const], LOCATIONS[ds_volatile], + and LOCATIONS[ds_restrict]. */ + +static location_t +smallest_type_quals_location (int type_quals, const location_t* locations) +{ + location_t loc = UNKNOWN_LOCATION; + + if (type_quals & TYPE_QUAL_CONST) + loc = locations[ds_const]; + + if ((type_quals & TYPE_QUAL_VOLATILE) + && (loc == UNKNOWN_LOCATION || locations[ds_volatile] < loc)) + loc = locations[ds_volatile]; + + if ((type_quals & TYPE_QUAL_RESTRICT) + && (loc == UNKNOWN_LOCATION || locations[ds_restrict] < loc)) + loc = locations[ds_restrict]; + + return loc; +} + +/* Check that it's OK to declare a function with the indicated TYPE + and TYPE_QUALS. SFK indicates the kind of special function (if any) + that this function is. OPTYPE is the type given in a conversion + operator declaration, or the class type for a constructor/destructor. + Returns the actual return type of the function; that may be different + than TYPE if an error occurs, or for certain special functions. */ static tree check_special_function_return_type (special_function_kind sfk, tree type, - tree optype) + tree optype, + int type_quals, + const location_t* locations) { switch (sfk) { case sfk_constructor: if (type) error ("return type specification for constructor invalid"); + else if (type_quals != TYPE_UNQUALIFIED) + error_at (smallest_type_quals_location (type_quals, locations), + "qualifiers are not allowed on constructor declaration"); if (targetm.cxx.cdtor_returns_this () && !TYPE_FOR_JAVA (optype)) type = build_pointer_type (optype); @@ -8947,6 +8979,10 @@ check_special_function_return_type (special_function_kind sfk, case sfk_destructor: if (type) error ("return type specification for destructor invalid"); + else if (type_quals != TYPE_UNQUALIFIED) + error_at (smallest_type_quals_location (type_quals, locations), + "qualifiers are not allowed on destructor declaration"); + /* We can't use the proper return type here because we run into problems with ambiguous bases and covariant returns. Java classes are left unchanged because (void *) isn't a valid @@ -8959,7 +8995,12 @@ check_special_function_return_type (special_function_kind sfk, case sfk_conversion: if (type) - error ("return type specified for %<operator %T%>", optype); + error ("return type specified for %<operator %T%>", optype); + else if (type_quals != TYPE_UNQUALIFIED) + error_at (smallest_type_quals_location (type_quals, locations), + "qualifiers are not allowed on declaration of " + "%<operator %T%>", optype); + type = optype; break; @@ -9085,7 +9126,7 @@ grokdeclarator (const cp_declarator *declarator, a member function. */ cp_ref_qualifier rqual = REF_QUAL_NONE; /* cv-qualifiers that apply to the type specified by the DECLSPECS. */ - int type_quals; + int type_quals = TYPE_UNQUALIFIED; tree raises = NULL_TREE; int template_count = 0; tree returned_attrs = NULL_TREE; @@ -9132,6 +9173,13 @@ grokdeclarator (const cp_declarator *declarator, if (concept_p) constexpr_p = true; + if (decl_spec_seq_has_spec_p (declspecs, ds_const)) + type_quals |= TYPE_QUAL_CONST; + if (decl_spec_seq_has_spec_p (declspecs, ds_volatile)) + type_quals |= TYPE_QUAL_VOLATILE; + if (decl_spec_seq_has_spec_p (declspecs, ds_restrict)) + type_quals |= TYPE_QUAL_RESTRICT; + if (decl_context == FUNCDEF) funcdef_flag = true, decl_context = NORMAL; else if (decl_context == MEMFUNCDEF) @@ -9457,8 +9505,13 @@ grokdeclarator (const cp_declarator *declarator, ctor_return_type = ctype; if (sfk != sfk_none) - type = check_special_function_return_type (sfk, type, - ctor_return_type); + { + type = check_special_function_return_type (sfk, type, + ctor_return_type, + type_quals, + declspecs->locations); + type_quals = TYPE_UNQUALIFIED; + } else if (type == NULL_TREE) { int is_main; @@ -9643,17 +9696,6 @@ grokdeclarator (const cp_declarator *declarator, type = build_complex_type (type); } - type_quals = TYPE_UNQUALIFIED; - if (decl_spec_seq_has_spec_p (declspecs, ds_const)) - type_quals |= TYPE_QUAL_CONST; - if (decl_spec_seq_has_spec_p (declspecs, ds_volatile)) - type_quals |= TYPE_QUAL_VOLATILE; - if (decl_spec_seq_has_spec_p (declspecs, ds_restrict)) - type_quals |= TYPE_QUAL_RESTRICT; - if (sfk == sfk_conversion && type_quals != TYPE_UNQUALIFIED) - error ("qualifiers are not allowed on declaration of %<operator %T%>", - ctor_return_type); - /* If we're using the injected-class-name to form a compound type or a declaration, replace it with the underlying class so we don't get redundant typedefs in the debug output. But if we are returning the diff --git a/gcc/cp/friend.c b/gcc/cp/friend.c index e107ceea494..f53ce27f19d 100644 --- a/gcc/cp/friend.c +++ b/gcc/cp/friend.c @@ -156,11 +156,9 @@ add_friend (tree type, tree decl, bool complain) } } - maybe_add_class_template_decl_list (type, decl, /*friend_p=*/1); - TREE_VALUE (list) = tree_cons (NULL_TREE, decl, TREE_VALUE (list)); - return; + break; } list = TREE_CHAIN (list); } @@ -172,9 +170,10 @@ add_friend (tree type, tree decl, bool complain) maybe_add_class_template_decl_list (type, decl, /*friend_p=*/1); - DECL_FRIENDLIST (typedecl) - = tree_cons (DECL_NAME (decl), build_tree_list (NULL_TREE, decl), - DECL_FRIENDLIST (typedecl)); + if (!list) + DECL_FRIENDLIST (typedecl) + = tree_cons (DECL_NAME (decl), build_tree_list (NULL_TREE, decl), + DECL_FRIENDLIST (typedecl)); if (!uses_template_parms (type)) DECL_BEFRIENDING_CLASSES (decl) = tree_cons (NULL_TREE, type, diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c index dcd3bb92ca0..ea9dba05227 100644 --- a/gcc/cp/lambda.c +++ b/gcc/cp/lambda.c @@ -817,6 +817,30 @@ nonlambda_method_basetype (void) return TYPE_METHOD_BASETYPE (TREE_TYPE (fn)); } +/* Like current_scope, but looking through lambdas. */ + +tree +current_nonlambda_scope (void) +{ + tree scope = current_scope (); + for (;;) + { + if (TREE_CODE (scope) == FUNCTION_DECL + && LAMBDA_FUNCTION_P (scope)) + { + scope = CP_TYPE_CONTEXT (DECL_CONTEXT (scope)); + continue; + } + else if (LAMBDA_TYPE_P (scope)) + { + scope = CP_TYPE_CONTEXT (scope); + continue; + } + break; + } + return scope; +} + /* Helper function for maybe_add_lambda_conv_op; build a CALL_EXPR with indicated FN and NARGS, but do not initialize the return type or any of the argument slots. */ diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 79e28637cae..baaf3e7ca98 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -4346,6 +4346,13 @@ hidden_name_p (tree val) && TYPE_FUNCTION_OR_TEMPLATE_DECL_P (val) && DECL_ANTICIPATED (val)) return true; + if (TREE_CODE (val) == OVERLOAD) + { + for (tree o = val; o; o = OVL_CHAIN (o)) + if (!hidden_name_p (OVL_FUNCTION (o))) + return false; + return true; + } return false; } diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index eaafaeff569..fb7b9d21056 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -22673,7 +22673,8 @@ resolve_typename_type (tree type, bool only_current_p) return type; /* If SCOPE isn't the template itself, it will not have a valid TYPE_FIELDS list. */ - if (same_type_p (scope, CLASSTYPE_PRIMARY_TEMPLATE_TYPE (scope))) + if (CLASS_TYPE_P (scope) + && same_type_p (scope, CLASSTYPE_PRIMARY_TEMPLATE_TYPE (scope))) /* scope is either the template itself or a compatible instantiation like X<T>, so look up the name in the original template. */ scope = CLASSTYPE_PRIMARY_TEMPLATE_TYPE (scope); diff --git a/gcc/cp/search.c b/gcc/cp/search.c index 90cd2438b36..42db122e98c 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -58,8 +58,6 @@ static tree dfs_walk_once_accessible (tree, bool, void *data); static tree dfs_access_in_type (tree, void *); static access_kind access_in_type (tree, tree); -static int protected_accessible_p (tree, tree, tree); -static int friend_accessible_p (tree, tree, tree); static tree dfs_get_pure_virtuals (tree, void *); @@ -582,9 +580,36 @@ context_for_name_lookup (tree decl) return context; } +/* Returns true iff DECL is declared in TYPE. */ + +static bool +member_declared_in_type (tree decl, tree type) +{ + /* A normal declaration obviously counts. */ + if (context_for_name_lookup (decl) == type) + return true; + /* So does a using or access declaration. */ + if (DECL_LANG_SPECIFIC (decl) && !DECL_DISCRIMINATOR_P (decl) + && purpose_member (type, DECL_ACCESS (decl))) + return true; + return false; +} + /* The accessibility routines use BINFO_ACCESS for scratch space during the computation of the accessibility of some declaration. */ +/* Avoid walking up past a declaration of the member. */ + +static tree +dfs_access_in_type_pre (tree binfo, void *data) +{ + tree decl = (tree) data; + tree type = BINFO_TYPE (binfo); + if (member_declared_in_type (decl, type)) + return dfs_skip_bases; + return NULL_TREE; +} + #define BINFO_ACCESS(NODE) \ ((access_kind) ((TREE_PUBLIC (NODE) << 1) | TREE_PRIVATE (NODE))) @@ -705,19 +730,17 @@ access_in_type (tree type, tree decl) The algorithm we use is to make a post-order depth-first traversal of the base-class hierarchy. As we come up the tree, we annotate each node with the most lenient access. */ - dfs_walk_once (binfo, NULL, dfs_access_in_type, decl); + dfs_walk_once (binfo, dfs_access_in_type_pre, dfs_access_in_type, decl); return BINFO_ACCESS (binfo); } -/* Returns nonzero if it is OK to access DECL through an object - indicated by BINFO in the context of DERIVED. */ +/* Returns nonzero if it is OK to access DECL named in TYPE through an object + of OTYPE in the context of DERIVED. */ static int -protected_accessible_p (tree decl, tree derived, tree binfo) +protected_accessible_p (tree decl, tree derived, tree type, tree otype) { - access_kind access; - /* We're checking this clause from [class.access.base] m as a member of N is protected, and the reference occurs in a @@ -725,16 +748,10 @@ protected_accessible_p (tree decl, tree derived, tree binfo) class P derived from N, where m as a member of P is public, private or protected. - Here DERIVED is a possible P, DECL is m and BINFO_TYPE (binfo) is N. */ + Here DERIVED is a possible P, DECL is m and TYPE is N. */ /* If DERIVED isn't derived from N, then it can't be a P. */ - if (!DERIVED_FROM_P (BINFO_TYPE (binfo), derived)) - return 0; - - access = access_in_type (derived, decl); - - /* If m is inaccessible in DERIVED, then it's not a P. */ - if (access == ak_none) + if (!DERIVED_FROM_P (type, derived)) return 0; /* [class.protected] @@ -748,33 +765,38 @@ protected_accessible_p (tree decl, tree derived, tree binfo) derived from that class) (_expr.ref_). If the access is to form a pointer to member, the nested-name-specifier shall name the derived class (or any class derived from that class). */ - if (DECL_NONSTATIC_MEMBER_P (decl)) - { - /* We can tell through what the reference is occurring by - chasing BINFO up to the root. */ - tree t = binfo; - while (BINFO_INHERITANCE_CHAIN (t)) - t = BINFO_INHERITANCE_CHAIN (t); - - if (!DERIVED_FROM_P (derived, BINFO_TYPE (t))) - return 0; - } + if (DECL_NONSTATIC_MEMBER_P (decl) + && !DERIVED_FROM_P (derived, otype)) + return 0; return 1; } -/* Returns nonzero if SCOPE is a friend of a type which would be able - to access DECL through the object indicated by BINFO. */ +/* Returns nonzero if SCOPE is a type or a friend of a type which would be able + to access DECL through TYPE. OTYPE is the type of the object. */ static int -friend_accessible_p (tree scope, tree decl, tree binfo) +friend_accessible_p (tree scope, tree decl, tree type, tree otype) { + /* We're checking this clause from [class.access.base] + + m as a member of N is protected, and the reference occurs in a + member or friend of class N, or in a member or friend of a + class P derived from N, where m as a member of P is public, private + or protected. + + Here DECL is m and TYPE is N. SCOPE is the current context, + and we check all its possible Ps. */ tree befriending_classes; tree t; if (!scope) return 0; + /* Is SCOPE itself a suitable P? */ + if (TYPE_P (scope) && protected_accessible_p (decl, scope, type, otype)) + return 1; + if (DECL_DECLARES_FUNCTION_P (scope)) befriending_classes = DECL_BEFRIENDING_CLASSES (scope); else if (TYPE_P (scope)) @@ -783,54 +805,113 @@ friend_accessible_p (tree scope, tree decl, tree binfo) return 0; for (t = befriending_classes; t; t = TREE_CHAIN (t)) - if (protected_accessible_p (decl, TREE_VALUE (t), binfo)) + if (protected_accessible_p (decl, TREE_VALUE (t), type, otype)) return 1; /* Nested classes have the same access as their enclosing types, as - per DR 45 (this is a change from the standard). */ + per DR 45 (this is a change from C++98). */ if (TYPE_P (scope)) - for (t = TYPE_CONTEXT (scope); t && TYPE_P (t); t = TYPE_CONTEXT (t)) - if (protected_accessible_p (decl, t, binfo)) - return 1; + if (friend_accessible_p (TYPE_CONTEXT (scope), decl, type, otype)) + return 1; if (DECL_DECLARES_FUNCTION_P (scope)) { /* Perhaps this SCOPE is a member of a class which is a friend. */ if (DECL_CLASS_SCOPE_P (scope) - && friend_accessible_p (DECL_CONTEXT (scope), decl, binfo)) + && friend_accessible_p (DECL_CONTEXT (scope), decl, type, otype)) return 1; + } - /* Or an instantiation of something which is a friend. */ - if (DECL_TEMPLATE_INFO (scope)) + /* Maybe scope's template is a friend. */ + if (tree tinfo = get_template_info (scope)) + { + tree tmpl = TI_TEMPLATE (tinfo); + if (DECL_CLASS_TEMPLATE_P (tmpl)) + tmpl = TREE_TYPE (tmpl); + else + tmpl = DECL_TEMPLATE_RESULT (tmpl); + if (tmpl != scope) { - int ret; /* Increment processing_template_decl to make sure that dependent_type_p works correctly. */ ++processing_template_decl; - ret = friend_accessible_p (DECL_TI_TEMPLATE (scope), decl, binfo); + int ret = friend_accessible_p (tmpl, decl, type, otype); --processing_template_decl; - return ret; + if (ret) + return 1; } } + /* If is_friend is true, we should have found a befriending class. */ + gcc_checking_assert (!is_friend (type, scope)); + return 0; } +struct dfs_accessible_data +{ + tree decl; + tree object_type; +}; + +/* Avoid walking up past a declaration of the member. */ + +static tree +dfs_accessible_pre (tree binfo, void *data) +{ + dfs_accessible_data *d = (dfs_accessible_data *)data; + tree type = BINFO_TYPE (binfo); + if (member_declared_in_type (d->decl, type)) + return dfs_skip_bases; + return NULL_TREE; +} + /* Called via dfs_walk_once_accessible from accessible_p */ static tree -dfs_accessible_post (tree binfo, void * /*data*/) +dfs_accessible_post (tree binfo, void *data) { - if (BINFO_ACCESS (binfo) != ak_none) + /* access_in_type already set BINFO_ACCESS for us. */ + access_kind access = BINFO_ACCESS (binfo); + tree N = BINFO_TYPE (binfo); + dfs_accessible_data *d = (dfs_accessible_data *)data; + tree decl = d->decl; + tree scope = current_nonlambda_scope (); + + /* A member m is accessible at the point R when named in class N if */ + switch (access) { - tree scope = current_scope (); - if (scope && TREE_CODE (scope) != NAMESPACE_DECL - && is_friend (BINFO_TYPE (binfo), scope)) - return binfo; - } + case ak_none: + return NULL_TREE; - return NULL_TREE; + case ak_public: + /* m as a member of N is public, or */ + return binfo; + + case ak_private: + { + /* m as a member of N is private, and R occurs in a member or friend of + class N, or */ + if (scope && TREE_CODE (scope) != NAMESPACE_DECL + && is_friend (N, scope)) + return binfo; + return NULL_TREE; + } + + case ak_protected: + { + /* m as a member of N is protected, and R occurs in a member or friend + of class N, or in a member or friend of a class P derived from N, + where m as a member of P is public, private, or protected */ + if (friend_accessible_p (scope, decl, N, d->object_type)) + return binfo; + return NULL_TREE; + } + + default: + gcc_unreachable (); + } } /* Like accessible_p below, but within a template returns true iff DECL is @@ -858,21 +939,15 @@ int accessible_p (tree type, tree decl, bool consider_local_p) { tree binfo; - tree scope; access_kind access; - /* Nonzero if it's OK to access DECL if it has protected - accessibility in TYPE. */ - int protected_ok = 0; - /* If this declaration is in a block or namespace scope, there's no access control. */ if (!TYPE_P (context_for_name_lookup (decl))) return 1; /* There is no need to perform access checks inside a thunk. */ - scope = current_scope (); - if (scope && DECL_THUNK_P (scope)) + if (current_function_decl && DECL_THUNK_P (current_function_decl)) return 1; /* In a template declaration, we cannot be sure whether the @@ -886,13 +961,18 @@ accessible_p (tree type, tree decl, bool consider_local_p) && (!processing_template_parmlist || processing_template_decl > 1)) return 1; + tree otype; if (!TYPE_P (type)) { - binfo = type; + /* When accessing a non-static member, the most derived type in the + binfo chain is the type of the object; remember that type for + protected_accessible_p. */ + for (tree b = type; b; b = BINFO_INHERITANCE_CHAIN (b)) + otype = BINFO_TYPE (b); type = BINFO_TYPE (type); } else - binfo = TYPE_BINFO (type); + otype = type; /* [class.access.base] @@ -905,7 +985,7 @@ accessible_p (tree type, tree decl, bool consider_local_p) --m as a member of N is protected, and the reference occurs in a member or friend of class N, or in a member or friend of a - class P derived from N, where m as a member of P is private or + class P derived from N, where m as a member of P is public, private or protected, or --there exists a base class B of N that is accessible at the point @@ -913,40 +993,28 @@ accessible_p (tree type, tree decl, bool consider_local_p) We walk the base class hierarchy, checking these conditions. */ - if (consider_local_p) - { - /* Figure out where the reference is occurring. Check to see if - DECL is private or protected in this scope, since that will - determine whether protected access is allowed. */ - tree ct = current_nonlambda_class_type (); - if (ct) - protected_ok = protected_accessible_p (decl, - ct, - binfo); - - /* Now, loop through the classes of which we are a friend. */ - if (!protected_ok) - protected_ok = friend_accessible_p (scope, decl, binfo); - } - - /* Standardize the binfo that access_in_type will use. We don't - need to know what path was chosen from this point onwards. */ + /* We walk using TYPE_BINFO (type) because access_in_type will set + BINFO_ACCESS on it and its bases. */ binfo = TYPE_BINFO (type); /* Compute the accessibility of DECL in the class hierarchy dominated by type. */ access = access_in_type (type, decl); - if (access == ak_public - || (access == ak_protected && protected_ok)) + if (access == ak_public) return 1; + /* If we aren't considering the point of reference, only the first bullet + applies. */ if (!consider_local_p) return 0; + dfs_accessible_data d = { decl, otype }; + /* Walk the hierarchy again, looking for a base class that allows access. */ return dfs_walk_once_accessible (binfo, /*friends=*/true, - NULL, dfs_accessible_post, NULL) + dfs_accessible_pre, + dfs_accessible_post, &d) != NULL_TREE; } diff --git a/gcc/defaults.h b/gcc/defaults.h index 713ca077c79..d4d3a565c17 100644 --- a/gcc/defaults.h +++ b/gcc/defaults.h @@ -1273,6 +1273,10 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #define WORD_REGISTER_OPERATIONS 0 #endif +#ifndef CONSTANT_ALIGNMENT +#define CONSTANT_ALIGNMENT(EXP, ALIGN) ALIGN +#endif + #ifdef GCC_INSN_FLAGS_H /* Dependent default target macro definitions @@ -1359,6 +1363,18 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #define STACK_SIZE_MODE word_mode #endif +/* Default value for flag_stack_protect when flag_stack_protect is initialized to -1: + --enable-default-ssp: Default flag_stack_protect to -fstack-protector-strong. + --disable-default-ssp: Default flag_stack_protect to 0. + */ +#ifdef ENABLE_DEFAULT_SSP +# ifndef DEFAULT_FLAG_SSP +# define DEFAULT_FLAG_SSP 3 +# endif +#else +# define DEFAULT_FLAG_SSP 0 +#endif + /* Provide default values for the macros controlling stack checking. */ /* The default is neither full builtin stack checking... */ diff --git a/gcc/df-scan.c b/gcc/df-scan.c index 93c2eae3e02..259c9591307 100644 --- a/gcc/df-scan.c +++ b/gcc/df-scan.c @@ -809,6 +809,14 @@ df_reg_chain_unlink (df_ref ref) df_free_ref (ref); } +/* Initialize INSN_INFO to describe INSN. */ + +static void +df_insn_info_init_fields (df_insn_info *insn_info, rtx_insn *insn) +{ + memset (insn_info, 0, sizeof (struct df_insn_info)); + insn_info->insn = insn; +} /* Create the insn record for INSN. If there was one there, zero it out. */ @@ -827,8 +835,7 @@ df_insn_create_insn_record (rtx_insn *insn) insn_rec = problem_data->insn_pool->allocate (); DF_INSN_INFO_SET (insn, insn_rec); } - memset (insn_rec, 0, sizeof (struct df_insn_info)); - insn_rec->insn = insn; + df_insn_info_init_fields (insn_rec, insn); return insn_rec; } @@ -876,6 +883,29 @@ df_mw_hardreg_chain_delete (struct df_mw_hardreg *hardregs) } } +/* Remove the contents of INSN_INFO (but don't free INSN_INFO itself). */ + +static void +df_insn_info_free_fields (df_insn_info *insn_info) +{ + /* In general, notes do not have the insn_info fields + initialized. However, combine deletes insns by changing them + to notes. How clever. So we cannot just check if it is a + valid insn before short circuiting this code, we need to see + if we actually initialized it. */ + df_mw_hardreg_chain_delete (insn_info->mw_hardregs); + + if (df_chain) + { + df_ref_chain_delete_du_chain (insn_info->defs); + df_ref_chain_delete_du_chain (insn_info->uses); + df_ref_chain_delete_du_chain (insn_info->eq_uses); + } + + df_ref_chain_delete (insn_info->defs); + df_ref_chain_delete (insn_info->uses); + df_ref_chain_delete (insn_info->eq_uses); +} /* Delete all of the refs information from the insn with UID. Internal helper for df_insn_delete, df_insn_rescan, and other @@ -895,24 +925,7 @@ df_insn_info_delete (unsigned int uid) struct df_scan_problem_data *problem_data = (struct df_scan_problem_data *) df_scan->problem_data; - /* In general, notes do not have the insn_info fields - initialized. However, combine deletes insns by changing them - to notes. How clever. So we cannot just check if it is a - valid insn before short circuiting this code, we need to see - if we actually initialized it. */ - df_mw_hardreg_chain_delete (insn_info->mw_hardregs); - - if (df_chain) - { - df_ref_chain_delete_du_chain (insn_info->defs); - df_ref_chain_delete_du_chain (insn_info->uses); - df_ref_chain_delete_du_chain (insn_info->eq_uses); - } - - df_ref_chain_delete (insn_info->defs); - df_ref_chain_delete (insn_info->uses); - df_ref_chain_delete (insn_info->eq_uses); - + df_insn_info_free_fields (insn_info); problem_data->insn_pool->remove (insn_info); DF_INSN_UID_SET (uid, NULL); } @@ -1075,8 +1088,8 @@ df_insn_rescan (rtx_insn *insn) /* There's change - we need to delete the existing info. Since the insn isn't moved, we can salvage its LUID. */ luid = DF_INSN_LUID (insn); - df_insn_info_delete (uid); - df_insn_create_insn_record (insn); + df_insn_info_free_fields (insn_info); + df_insn_info_init_fields (insn_info, insn); DF_INSN_LUID (insn) = luid; } else diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi index 360b0666b69..24e7eed1380 100644 --- a/gcc/doc/install.texi +++ b/gcc/doc/install.texi @@ -1642,6 +1642,9 @@ Using the GNU Compiler Collection (GCC)}, See ``RS/6000 and PowerPC Options'' in the main manual @end ifhtml +@item --enable-default-ssp +Turn on @option{-fstack-protector-strong} by default. + @item --enable-cld This option enables @option{-mcld} by default for 32-bit x86 targets. @ifnothtml @@ -3150,37 +3153,25 @@ contact their makers. AIX: @itemize @item -@uref{http://www.bullfreeware.com,,Bull's Freeware and Shareware Archive for AIX}; - -@item -@uref{http://pware.hvcc.edu,,Hudson Valley Community College Open Source Software for IBM System p}; +@uref{http://www.bullfreeware.com,,Bull's Open Source Software Archive for +for AIX 5L and AIX 6}; @item -@uref{http://www.perzl.org/aix/,,AIX 5L and 6 Open Source Packages}. +@uref{http://www.perzl.org/aix/,,AIX Open Source Packages (AIX5L AIX 6.1 +AIX 7.1)}. @end itemize @item DOS---@uref{http://www.delorie.com/djgpp/,,DJGPP}. @item -Renesas H8/300[HS]---@uref{http://h8300-hms.sourceforge.net/,,GNU -Development Tools for the Renesas H8/300[HS] Series}. - -@item HP-UX: @itemize @item @uref{http://hpux.connect.org.uk/,,HP-UX Porting Center}; - -@item -@uref{ftp://sunsite.informatik.rwth-aachen.de/pub/packages/gcc_hpux/,,Binaries for HP-UX 11.00 at Aachen University of Technology}. @end itemize @item -@uref{http://www.sco.com/skunkware/devtools/index.html#gcc,,SCO -OpenServer/Unixware}. - -@item Solaris 2 (SPARC, Intel): @itemize @item @@ -3196,18 +3187,11 @@ Microsoft Windows: @item The @uref{http://sourceware.org/cygwin/,,Cygwin} project; @item -The @uref{http://www.mingw.org/,,MinGW} project. +The @uref{http://www.mingw.org/,,MinGW} and +@uref{http://mingw-w64.org/,,mingw-w64} projects. @end itemize @item -@uref{ftp://ftp.thewrittenword.com/packages/by-name/,,The -Written Word} offers binaries for -AIX 4.3.3, 5.1 and 5.2, -GNU/Linux (i386), -HP-UX 10.20, 11.00, and 11.11, and -Solaris/SPARC 2.5.1, 2.6, 7, 8, 9 and 10. - -@item @uref{http://www.openpkg.org/,,OpenPKG} offers binaries for quite a number of platforms. diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index ef0f1f30436..7726368da60 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -514,6 +514,7 @@ Objective-C and Objective-C++ Dialects}. -mstrict-align @gol -momit-leaf-frame-pointer -mno-omit-leaf-frame-pointer @gol -mtls-dialect=desc -mtls-dialect=traditional @gol +-mtls-size=@var{size} @gol -mfix-cortex-a53-835769 -mno-fix-cortex-a53-835769 @gol -mfix-cortex-a53-843419 -mno-fix-cortex-a53-843419 @gol -march=@var{name} -mcpu=@var{name} -mtune=@var{name}} @@ -781,6 +782,7 @@ Objective-C and Objective-C++ Dialects}. -mgp32 -mgp64 -mfp32 -mfpxx -mfp64 -mhard-float -msoft-float @gol -mno-float -msingle-float -mdouble-float @gol -modd-spreg -mno-odd-spreg @gol +-mcompact-branches=@var{policy} @gol -mabs=@var{mode} -mnan=@var{encoding} @gol -mdsp -mno-dsp -mdspr2 -mno-dspr2 @gol -mmcu -mmno-mcu @gol @@ -8738,102 +8740,19 @@ Perform loop optimizations on trees. This flag is enabled by default at @option{-O} and higher. @item -ftree-loop-linear +@itemx -floop-interchange +@itemx -floop-strip-mine +@itemx -floop-block +@itemx -floop-unroll-and-jam @opindex ftree-loop-linear -Perform loop interchange transformations on tree. Same as -@option{-floop-interchange}. To use this code transformation, GCC has -to be configured with @option{--with-isl} to enable the Graphite loop -transformation infrastructure. - -@item -floop-interchange @opindex floop-interchange -Perform loop interchange transformations on loops. Interchanging two -nested loops switches the inner and outer loops. For example, given a -loop like: -@smallexample -DO J = 1, M - DO I = 1, N - A(J, I) = A(J, I) * C - ENDDO -ENDDO -@end smallexample -@noindent -loop interchange transforms the loop as if it were written: -@smallexample -DO I = 1, N - DO J = 1, M - A(J, I) = A(J, I) * C - ENDDO -ENDDO -@end smallexample -which can be beneficial when @code{N} is larger than the caches, -because in Fortran, the elements of an array are stored in memory -contiguously by column, and the original loop iterates over rows, -potentially creating at each access a cache miss. This optimization -applies to all the languages supported by GCC and is not limited to -Fortran. To use this code transformation, GCC has to be configured -with @option{--with-isl} to enable the Graphite loop transformation -infrastructure. - -@item -floop-strip-mine @opindex floop-strip-mine -Perform loop strip mining transformations on loops. Strip mining -splits a loop into two nested loops. The outer loop has strides -equal to the strip size and the inner loop has strides of the -original loop within a strip. The strip length can be changed -using the @option{loop-block-tile-size} parameter. For example, -given a loop like: -@smallexample -DO I = 1, N - A(I) = A(I) + C -ENDDO -@end smallexample -@noindent -loop strip mining transforms the loop as if it were written: -@smallexample -DO II = 1, N, 51 - DO I = II, min (II + 50, N) - A(I) = A(I) + C - ENDDO -ENDDO -@end smallexample -This optimization applies to all the languages supported by GCC and is -not limited to Fortran. To use this code transformation, GCC has to -be configured with @option{--with-isl} to enable the Graphite loop -transformation infrastructure. - -@item -floop-block @opindex floop-block -Perform loop blocking transformations on loops. Blocking strip mines -each loop in the loop nest such that the memory accesses of the -element loops fit inside caches. The strip length can be changed -using the @option{loop-block-tile-size} parameter. For example, given -a loop like: -@smallexample -DO I = 1, N - DO J = 1, M - A(J, I) = B(I) + C(J) - ENDDO -ENDDO -@end smallexample -@noindent -loop blocking transforms the loop as if it were written: -@smallexample -DO II = 1, N, 51 - DO JJ = 1, M, 51 - DO I = II, min (II + 50, N) - DO J = JJ, min (JJ + 50, M) - A(J, I) = B(I) + C(J) - ENDDO - ENDDO - ENDDO -ENDDO -@end smallexample -which can be beneficial when @code{M} is larger than the caches, -because the innermost loop iterates over a smaller amount of data -which can be kept in the caches. This optimization applies to all the -languages supported by GCC and is not limited to Fortran. To use this -code transformation, GCC has to be configured with @option{--with-isl} -to enable the Graphite loop transformation infrastructure. +@opindex floop-unroll-and-jam +Perform loop nest optimizations. Same as +@option{-floop-nest-optimize}. To use this code transformation, GCC has +to be configured with @option{--with-isl} to enable the Graphite loop +transformation infrastructure. @item -fgraphite-identity @opindex fgraphite-identity @@ -8851,13 +8770,6 @@ optimizer based on the Pluto optimization algorithms. It calculates a loop structure optimized for data-locality and parallelism. This option is experimental. -@item -floop-unroll-and-jam -@opindex floop-unroll-and-jam -Enable unroll and jam for the ISL based loop nest optimizer. The unroll -factor can be changed using the @option{loop-unroll-jam-size} parameter. -The unrolled dimension (counting from the most inner one) can be changed -using the @option{loop-unroll-jam-depth} parameter. . - @item -floop-parallelize-all @opindex floop-parallelize-all Use the Graphite data dependence analysis to identify loops that can @@ -11043,7 +10955,7 @@ To disable global objects protection use @option{--param asan-globals=0}. @item asan-stack Enable buffer overflow detection for stack objects. This kind of -protection is enabled by default when using@option{-fsanitize=address}. +protection is enabled by default when using @option{-fsanitize=address}. To disable stack protection use @option{--param asan-stack=0} option. @item asan-instrument-reads @@ -12414,6 +12326,11 @@ of TLS variables. This is the default. Use traditional TLS as the thread-local storage mechanism for dynamic accesses of TLS variables. +@item -mtls-size=@var{size} +@opindex mtls-size +Specify bit size of immediate TLS offsets. Valid values are 12, 24, 32, 48. +This option depends on binutils higher than 2.25. + @item -mfix-cortex-a53-835769 @itemx -mno-fix-cortex-a53-835769 @opindex mfix-cortex-a53-835769 @@ -17392,6 +17309,30 @@ for the o32 ABI. This is the default for processors that are known to support these registers. When using the o32 FPXX ABI, @option{-mno-odd-spreg} is set by default. +@item -mcompact-branches=never +@itemx -mcompact-branches=optimal +@itemx -mcompact-branches=always +@opindex mcompact-branches=never +@opindex mcompact-branches=optimal +@opindex mcompact-branches=always +These options control which form of branches will be generated. The +default is @option{-mcompact-branches=optimal}. + +The @option{-mcompact-branches=never} option ensures that compact branch +instructions will never be generated. + +The @option{-mcompact-branches=always} option ensures that a compact +branch instruction will be generated if available. If a compact branch +instruction is not available, a delay slot form of the branch will be +used instead. + +This option is supported from MIPS Release 6 onwards. + +The @option{-mcompact-branches=optimal} option will cause a delay slot +branch to be used if one is available in the current ISA and the delay +slot is successfully filled. If the delay slot is not filled, a compact +branch will be chosen if one is available. + @item -mabs=2008 @itemx -mabs=legacy @opindex mabs=2008 diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index 0bffdc63388..619259fc393 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -4946,10 +4946,10 @@ is of a wider mode, is computed and added to operand 3. Operand 3 is of a mode equal or wider than the mode of the absolute difference. The result is placed in operand 0, which is of the same mode as operand 3. -@cindex @code{ssum_widen@var{m3}} instruction pattern -@item @samp{ssum_widen@var{m3}} -@cindex @code{usum_widen@var{m3}} instruction pattern -@itemx @samp{usum_widen@var{m3}} +@cindex @code{widen_ssum@var{m3}} instruction pattern +@item @samp{widen_ssum@var{m3}} +@cindex @code{widen_usum@var{m3}} instruction pattern +@itemx @samp{widen_usum@var{m3}} Operands 0 and 2 are of the same mode, which is wider than the mode of operand 1. Add operand 1 to operand 2 and place the widened result in operand 0. (This is used express accumulation of elements into an accumulator diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi index d339d1e5d8a..7aa9c9dfa03 100644 --- a/gcc/doc/sourcebuild.texi +++ b/gcc/doc/sourcebuild.texi @@ -1366,8 +1366,8 @@ Target supports a vector misalign access. @item vect_no_align Target does not support a vector alignment mechanism. -@item vect_no_int_max -Target does not support a vector max instruction on @code{int}. +@item vect_no_int_min_max +Target does not support a vector min and max instruction on @code{int}. @item vect_no_int_add Target does not support a vector add instruction on @code{int}. diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index f95646c4798..f5a1f84793e 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -1098,7 +1098,7 @@ that is being placed in memory. @var{constant} is the constant and have. The value of this macro is used instead of that alignment to align the object. -If this macro is not defined, then @var{basic-align} is used. +The default definition just returns @var{basic-align}. The typical use of this macro is to increase alignment for string constants to be word aligned so that @code{strcpy} calls that copy diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index 2383fb97a96..9d5ac0a10e4 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -1048,7 +1048,7 @@ that is being placed in memory. @var{constant} is the constant and have. The value of this macro is used instead of that alignment to align the object. -If this macro is not defined, then @var{basic-align} is used. +The default definition just returns @var{basic-align}. The typical use of this macro is to increase alignment for string constants to be word aligned so that @code{strcpy} calls that copy diff --git a/gcc/dominance.c b/gcc/dominance.c index d8d87ca09d2..09645be1a61 100644 --- a/gcc/dominance.c +++ b/gcc/dominance.c @@ -53,222 +53,234 @@ /* Type of Basic Block aka. TBB */ typedef unsigned int TBB; -/* We work in a poor-mans object oriented fashion, and carry an instance of - this structure through all our 'methods'. It holds various arrays - reflecting the (sub)structure of the flowgraph. Most of them are of type - TBB and are also indexed by TBB. */ +namespace { -struct dom_info +/* This class holds various arrays reflecting the (sub)structure of the + flowgraph. Most of them are of type TBB and are also indexed by TBB. */ + +class dom_info { +public: + dom_info (function *, cdi_direction); + ~dom_info (); + void calc_dfs_tree (); + void calc_idoms (); + + inline basic_block get_idom (basic_block); +private: + void calc_dfs_tree_nonrec (basic_block); + void compress (TBB); + TBB eval (TBB); + void link_roots (TBB, TBB); + /* The parent of a node in the DFS tree. */ - TBB *dfs_parent; - /* For a node x key[x] is roughly the node nearest to the root from which + TBB *m_dfs_parent; + /* For a node x m_key[x] is roughly the node nearest to the root from which exists a way to x only over nodes behind x. Such a node is also called semidominator. */ - TBB *key; - /* The value in path_min[x] is the node y on the path from x to the root of - the tree x is in with the smallest key[y]. */ - TBB *path_min; - /* bucket[x] points to the first node of the set of nodes having x as key. */ - TBB *bucket; - /* And next_bucket[x] points to the next node. */ - TBB *next_bucket; - /* After the algorithm is done, dom[x] contains the immediate dominator + TBB *m_key; + /* The value in m_path_min[x] is the node y on the path from x to the root of + the tree x is in with the smallest m_key[y]. */ + TBB *m_path_min; + /* m_bucket[x] points to the first node of the set of nodes having x as + key. */ + TBB *m_bucket; + /* And m_next_bucket[x] points to the next node. */ + TBB *m_next_bucket; + /* After the algorithm is done, m_dom[x] contains the immediate dominator of x. */ - TBB *dom; + TBB *m_dom; /* The following few fields implement the structures needed for disjoint sets. */ - /* set_chain[x] is the next node on the path from x to the representative - of the set containing x. If set_chain[x]==0 then x is a root. */ - TBB *set_chain; - /* set_size[x] is the number of elements in the set named by x. */ - unsigned int *set_size; - /* set_child[x] is used for balancing the tree representing a set. It can + /* m_set_chain[x] is the next node on the path from x to the representative + of the set containing x. If m_set_chain[x]==0 then x is a root. */ + TBB *m_set_chain; + /* m_set_size[x] is the number of elements in the set named by x. */ + unsigned int *m_set_size; + /* m_set_child[x] is used for balancing the tree representing a set. It can be understood as the next sibling of x. */ - TBB *set_child; + TBB *m_set_child; - /* If b is the number of a basic block (BB->index), dfs_order[b] is the + /* If b is the number of a basic block (BB->index), m_dfs_order[b] is the number of that node in DFS order counted from 1. This is an index into most of the other arrays in this structure. */ - TBB *dfs_order; + TBB *m_dfs_order; + /* Points to last element in m_dfs_order array. */ + TBB *m_dfs_last; /* If x is the DFS-index of a node which corresponds with a basic block, - dfs_to_bb[x] is that basic block. Note, that in our structure there are - more nodes that basic blocks, so only dfs_to_bb[dfs_order[bb->index]]==bb - is true for every basic block bb, but not the opposite. */ - basic_block *dfs_to_bb; + m_dfs_to_bb[x] is that basic block. Note, that in our structure there are + more nodes that basic blocks, so only + m_dfs_to_bb[m_dfs_order[bb->index]]==bb is true for every basic block bb, + but not the opposite. */ + basic_block *m_dfs_to_bb; /* This is the next free DFS number when creating the DFS tree. */ - unsigned int dfsnum; - /* The number of nodes in the DFS tree (==dfsnum-1). */ - unsigned int nodes; + unsigned int m_dfsnum; + /* The number of nodes in the DFS tree (==m_dfsnum-1). */ + unsigned int m_nodes; /* Blocks with bits set here have a fake edge to EXIT. These are used to turn a DFS forest into a proper tree. */ - bitmap fake_exit_edge; + bitmap m_fake_exit_edge; + + /* Number of basic blocks in the function being compiled. */ + size_t m_n_basic_blocks; + + /* True, if we are computing postdominators (rather than dominators). */ + bool m_reverse; + + /* Start block (the entry block for forward problem, exit block for backward + problem). */ + basic_block m_start_block; + /* Ending block. */ + basic_block m_end_block; }; -static void init_dom_info (struct dom_info *, enum cdi_direction); -static void free_dom_info (struct dom_info *); -static void calc_dfs_tree_nonrec (struct dom_info *, basic_block, bool); -static void calc_dfs_tree (struct dom_info *, bool); -static void compress (struct dom_info *, TBB); -static TBB eval (struct dom_info *, TBB); -static void link_roots (struct dom_info *, TBB, TBB); -static void calc_idoms (struct dom_info *, bool); -void debug_dominance_info (enum cdi_direction); -void debug_dominance_tree (enum cdi_direction, basic_block); - -/* Helper macro for allocating and initializing an array, - for aesthetic reasons. */ -#define init_ar(var, type, num, content) \ - do \ - { \ - unsigned int i = 1; /* Catch content == i. */ \ - if (! (content)) \ - (var) = XCNEWVEC (type, num); \ - else \ - { \ - (var) = XNEWVEC (type, (num)); \ - for (i = 0; i < num; i++) \ - (var)[i] = (content); \ - } \ - } \ - while (0) - -/* Allocate all needed memory in a pessimistic fashion (so we round up). - This initializes the contents of DI, which already must be allocated. */ +} // anonymous namespace -static void -init_dom_info (struct dom_info *di, enum cdi_direction dir) +void debug_dominance_info (cdi_direction); +void debug_dominance_tree (cdi_direction, basic_block); + +/* Allocate and zero-initialize NUM elements of type T (T must be a + POD-type). Note: after transition to C++11 or later, + `x = new_zero_array <T> (num);' can be replaced with + `x = new T[num] {};'. */ + +template<typename T> +inline T *new_zero_array (size_t num) +{ + T *result = new T[num]; + memset (result, 0, sizeof (T) * num); + return result; +} + +/* Allocate all needed memory in a pessimistic fashion (so we round up). */ + +dom_info::dom_info (function *fn, cdi_direction dir) { /* We need memory for n_basic_blocks nodes. */ - unsigned int num = n_basic_blocks_for_fn (cfun); - init_ar (di->dfs_parent, TBB, num, 0); - init_ar (di->path_min, TBB, num, i); - init_ar (di->key, TBB, num, i); - init_ar (di->dom, TBB, num, 0); + size_t num = m_n_basic_blocks = n_basic_blocks_for_fn (fn); + m_dfs_parent = new_zero_array <TBB> (num); + m_dom = new_zero_array <TBB> (num); + + m_path_min = new TBB[num]; + m_key = new TBB[num]; + m_set_size = new unsigned int[num]; + for (size_t i = 0; i < num; i++) + { + m_path_min[i] = m_key[i] = i; + m_set_size[i] = 1; + } - init_ar (di->bucket, TBB, num, 0); - init_ar (di->next_bucket, TBB, num, 0); + m_bucket = new_zero_array <TBB> (num); + m_next_bucket = new_zero_array <TBB> (num); - init_ar (di->set_chain, TBB, num, 0); - init_ar (di->set_size, unsigned int, num, 1); - init_ar (di->set_child, TBB, num, 0); + m_set_chain = new_zero_array <TBB> (num); + m_set_child = new_zero_array <TBB> (num); - init_ar (di->dfs_order, TBB, - (unsigned int) last_basic_block_for_fn (cfun) + 1, 0); - init_ar (di->dfs_to_bb, basic_block, num, 0); + unsigned last_bb_index = last_basic_block_for_fn (fn); + m_dfs_order = new_zero_array <TBB> (last_bb_index + 1); + m_dfs_last = &m_dfs_order[last_bb_index]; + m_dfs_to_bb = new_zero_array <basic_block> (num); - di->dfsnum = 1; - di->nodes = 0; + m_dfsnum = 1; + m_nodes = 0; switch (dir) { case CDI_DOMINATORS: - di->fake_exit_edge = NULL; + m_reverse = false; + m_fake_exit_edge = NULL; + m_start_block = ENTRY_BLOCK_PTR_FOR_FN (fn); + m_end_block = EXIT_BLOCK_PTR_FOR_FN (fn); break; case CDI_POST_DOMINATORS: - di->fake_exit_edge = BITMAP_ALLOC (NULL); + m_reverse = true; + m_fake_exit_edge = BITMAP_ALLOC (NULL); + m_start_block = EXIT_BLOCK_PTR_FOR_FN (fn); + m_end_block = ENTRY_BLOCK_PTR_FOR_FN (fn); break; default: gcc_unreachable (); - break; } } -#undef init_ar +inline basic_block +dom_info::get_idom (basic_block bb) +{ + TBB d = m_dom[m_dfs_order[bb->index]]; + return m_dfs_to_bb[d]; +} /* Map dominance calculation type to array index used for various dominance information arrays. This version is simple -- it will need to be modified, obviously, if additional values are added to cdi_direction. */ -static unsigned int -dom_convert_dir_to_idx (enum cdi_direction dir) +static inline unsigned int +dom_convert_dir_to_idx (cdi_direction dir) { gcc_checking_assert (dir == CDI_DOMINATORS || dir == CDI_POST_DOMINATORS); return dir - 1; } -/* Free all allocated memory in DI, but not DI itself. */ +/* Free all allocated memory in dom_info. */ -static void -free_dom_info (struct dom_info *di) +dom_info::~dom_info () { - free (di->dfs_parent); - free (di->path_min); - free (di->key); - free (di->dom); - free (di->bucket); - free (di->next_bucket); - free (di->set_chain); - free (di->set_size); - free (di->set_child); - free (di->dfs_order); - free (di->dfs_to_bb); - BITMAP_FREE (di->fake_exit_edge); + delete[] m_dfs_parent; + delete[] m_path_min; + delete[] m_key; + delete[] m_dom; + delete[] m_bucket; + delete[] m_next_bucket; + delete[] m_set_chain; + delete[] m_set_size; + delete[] m_set_child; + delete[] m_dfs_order; + delete[] m_dfs_to_bb; + BITMAP_FREE (m_fake_exit_edge); } -/* The nonrecursive variant of creating a DFS tree. DI is our working - structure, BB the starting basic block for this tree and REVERSE - is true, if predecessors should be visited instead of successors of a - node. After this is done all nodes reachable from BB were visited, have - assigned their dfs number and are linked together to form a tree. */ +/* The nonrecursive variant of creating a DFS tree. BB is the starting basic + block for this tree and m_reverse is true, if predecessors should be visited + instead of successors of a node. After this is done all nodes reachable + from BB were visited, have assigned their dfs number and are linked together + to form a tree. */ -static void -calc_dfs_tree_nonrec (struct dom_info *di, basic_block bb, bool reverse) +void +dom_info::calc_dfs_tree_nonrec (basic_block bb) { - /* We call this _only_ if bb is not already visited. */ - edge e; - TBB child_i, my_i = 0; - edge_iterator *stack; - edge_iterator ei, einext; - int sp; - /* Start block (the entry block for forward problem, exit block for backward - problem). */ - basic_block en_block; - /* Ending block. */ - basic_block ex_block; - - stack = XNEWVEC (edge_iterator, n_basic_blocks_for_fn (cfun) + 1); - sp = 0; + edge_iterator *stack = new edge_iterator[m_n_basic_blocks + 1]; + int sp = 0; - /* Initialize our border blocks, and the first edge. */ - if (reverse) - { - ei = ei_start (bb->preds); - en_block = EXIT_BLOCK_PTR_FOR_FN (cfun); - ex_block = ENTRY_BLOCK_PTR_FOR_FN (cfun); - } - else - { - ei = ei_start (bb->succs); - en_block = ENTRY_BLOCK_PTR_FOR_FN (cfun); - ex_block = EXIT_BLOCK_PTR_FOR_FN (cfun); - } + /* Initialize the first edge. */ + edge_iterator ei = m_reverse ? ei_start (bb->preds) + : ei_start (bb->succs); /* When the stack is empty we break out of this loop. */ while (1) { basic_block bn; + edge_iterator einext; /* This loop traverses edges e in depth first manner, and fills the stack. */ while (!ei_end_p (ei)) { - e = ei_edge (ei); + edge e = ei_edge (ei); /* Deduce from E the current and the next block (BB and BN), and the next edge. */ - if (reverse) + if (m_reverse) { bn = e->src; /* If the next node BN is either already visited or a border block the current edge is useless, and simply overwritten with the next edge out of the current node. */ - if (bn == ex_block || di->dfs_order[bn->index]) + if (bn == m_end_block || m_dfs_order[bn->index]) { ei_next (&ei); continue; @@ -279,7 +291,7 @@ calc_dfs_tree_nonrec (struct dom_info *di, basic_block bb, bool reverse) else { bn = e->dest; - if (bn == ex_block || di->dfs_order[bn->index]) + if (bn == m_end_block || m_dfs_order[bn->index]) { ei_next (&ei); continue; @@ -288,16 +300,17 @@ calc_dfs_tree_nonrec (struct dom_info *di, basic_block bb, bool reverse) einext = ei_start (bn->succs); } - gcc_assert (bn != en_block); + gcc_assert (bn != m_start_block); /* Fill the DFS tree info calculatable _before_ recursing. */ - if (bb != en_block) - my_i = di->dfs_order[bb->index]; + TBB my_i; + if (bb != m_start_block) + my_i = m_dfs_order[bb->index]; else - my_i = di->dfs_order[last_basic_block_for_fn (cfun)]; - child_i = di->dfs_order[bn->index] = di->dfsnum++; - di->dfs_to_bb[child_i] = bn; - di->dfs_parent[child_i] = my_i; + my_i = *m_dfs_last; + TBB child_i = m_dfs_order[bn->index] = m_dfsnum++; + m_dfs_to_bb[child_i] = bn; + m_dfs_parent[child_i] = my_i; /* Save the current point in the CFG on the stack, and recurse. */ stack[sp++] = ei; @@ -319,27 +332,24 @@ calc_dfs_tree_nonrec (struct dom_info *di, basic_block bb, bool reverse) descendants or the tree depth. */ ei_next (&ei); } - free (stack); + delete[] stack; } -/* The main entry for calculating the DFS tree or forest. DI is our working - structure and REVERSE is true, if we are interested in the reverse flow - graph. In that case the result is not necessarily a tree but a forest, - because there may be nodes from which the EXIT_BLOCK is unreachable. */ +/* The main entry for calculating the DFS tree or forest. m_reverse is true, + if we are interested in the reverse flow graph. In that case the result is + not necessarily a tree but a forest, because there may be nodes from which + the EXIT_BLOCK is unreachable. */ -static void -calc_dfs_tree (struct dom_info *di, bool reverse) +void +dom_info::calc_dfs_tree () { - /* The first block is the ENTRY_BLOCK (or EXIT_BLOCK if REVERSE). */ - basic_block begin = (reverse - ? EXIT_BLOCK_PTR_FOR_FN (cfun) : ENTRY_BLOCK_PTR_FOR_FN (cfun)); - di->dfs_order[last_basic_block_for_fn (cfun)] = di->dfsnum; - di->dfs_to_bb[di->dfsnum] = begin; - di->dfsnum++; + *m_dfs_last = m_dfsnum; + m_dfs_to_bb[m_dfsnum] = m_start_block; + m_dfsnum++; - calc_dfs_tree_nonrec (di, begin, reverse); + calc_dfs_tree_nonrec (m_start_block); - if (reverse) + if (m_reverse) { /* In the post-dom case we may have nodes without a path to EXIT_BLOCK. They are reverse-unreachable. In the dom-case we disallow such @@ -354,48 +364,45 @@ calc_dfs_tree (struct dom_info *di, bool reverse) basic_block b; bool saw_unconnected = false; - FOR_EACH_BB_REVERSE_FN (b, cfun) + FOR_BB_BETWEEN (b, m_start_block->prev_bb, m_end_block, prev_bb) { if (EDGE_COUNT (b->succs) > 0) { - if (di->dfs_order[b->index] == 0) + if (m_dfs_order[b->index] == 0) saw_unconnected = true; continue; } - bitmap_set_bit (di->fake_exit_edge, b->index); - di->dfs_order[b->index] = di->dfsnum; - di->dfs_to_bb[di->dfsnum] = b; - di->dfs_parent[di->dfsnum] = - di->dfs_order[last_basic_block_for_fn (cfun)]; - di->dfsnum++; - calc_dfs_tree_nonrec (di, b, reverse); + bitmap_set_bit (m_fake_exit_edge, b->index); + m_dfs_order[b->index] = m_dfsnum; + m_dfs_to_bb[m_dfsnum] = b; + m_dfs_parent[m_dfsnum] = *m_dfs_last; + m_dfsnum++; + calc_dfs_tree_nonrec (b); } if (saw_unconnected) { - FOR_EACH_BB_REVERSE_FN (b, cfun) + FOR_BB_BETWEEN (b, m_start_block->prev_bb, m_end_block, prev_bb) { - basic_block b2; - if (di->dfs_order[b->index]) + if (m_dfs_order[b->index]) continue; - b2 = dfs_find_deadend (b); - gcc_checking_assert (di->dfs_order[b2->index] == 0); - bitmap_set_bit (di->fake_exit_edge, b2->index); - di->dfs_order[b2->index] = di->dfsnum; - di->dfs_to_bb[di->dfsnum] = b2; - di->dfs_parent[di->dfsnum] = - di->dfs_order[last_basic_block_for_fn (cfun)]; - di->dfsnum++; - calc_dfs_tree_nonrec (di, b2, reverse); - gcc_checking_assert (di->dfs_order[b->index]); + basic_block b2 = dfs_find_deadend (b); + gcc_checking_assert (m_dfs_order[b2->index] == 0); + bitmap_set_bit (m_fake_exit_edge, b2->index); + m_dfs_order[b2->index] = m_dfsnum; + m_dfs_to_bb[m_dfsnum] = b2; + m_dfs_parent[m_dfsnum] = *m_dfs_last; + m_dfsnum++; + calc_dfs_tree_nonrec (b2); + gcc_checking_assert (m_dfs_order[b->index]); } } } - di->nodes = di->dfsnum - 1; + m_nodes = m_dfsnum - 1; /* This aborts e.g. when there is _no_ path from ENTRY to EXIT at all. */ - gcc_assert (di->nodes == (unsigned int) n_basic_blocks_for_fn (cfun) - 1); + gcc_assert (m_nodes == (unsigned int) m_n_basic_blocks - 1); } /* Compress the path from V to the root of its set and update path_min at the @@ -403,19 +410,19 @@ calc_dfs_tree (struct dom_info *di, bool reverse) in and path_min[V] is the node with the smallest key[] value on the path from V to that root. */ -static void -compress (struct dom_info *di, TBB v) +void +dom_info::compress (TBB v) { /* Btw. It's not worth to unrecurse compress() as the depth is usually not greater than 5 even for huge graphs (I've not seen call depth > 4). Also performance wise compress() ranges _far_ behind eval(). */ - TBB parent = di->set_chain[v]; - if (di->set_chain[parent]) + TBB parent = m_set_chain[v]; + if (m_set_chain[parent]) { - compress (di, parent); - if (di->key[di->path_min[parent]] < di->key[di->path_min[v]]) - di->path_min[v] = di->path_min[parent]; - di->set_chain[v] = di->set_chain[parent]; + compress (parent); + if (m_key[m_path_min[parent]] < m_key[m_path_min[v]]) + m_path_min[v] = m_path_min[parent]; + m_set_chain[v] = m_set_chain[parent]; } } @@ -423,28 +430,28 @@ compress (struct dom_info *di, TBB v) changed since the last call). Returns the node with the smallest key[] value on the path from V to the root. */ -static inline TBB -eval (struct dom_info *di, TBB v) +inline TBB +dom_info::eval (TBB v) { /* The representative of the set V is in, also called root (as the set representation is a tree). */ - TBB rep = di->set_chain[v]; + TBB rep = m_set_chain[v]; /* V itself is the root. */ if (!rep) - return di->path_min[v]; + return m_path_min[v]; /* Compress only if necessary. */ - if (di->set_chain[rep]) + if (m_set_chain[rep]) { - compress (di, v); - rep = di->set_chain[v]; + compress (v); + rep = m_set_chain[v]; } - if (di->key[di->path_min[rep]] >= di->key[di->path_min[v]]) - return di->path_min[v]; + if (m_key[m_path_min[rep]] >= m_key[m_path_min[v]]) + return m_path_min[v]; else - return di->path_min[rep]; + return m_path_min[rep]; } /* This essentially merges the two sets of V and W, giving a single set with @@ -452,72 +459,64 @@ eval (struct dom_info *di, TBB v) balanced tree. Currently link(V,W) is only used with V being the parent of W. */ -static void -link_roots (struct dom_info *di, TBB v, TBB w) +void +dom_info::link_roots (TBB v, TBB w) { TBB s = w; /* Rebalance the tree. */ - while (di->key[di->path_min[w]] < di->key[di->path_min[di->set_child[s]]]) + while (m_key[m_path_min[w]] < m_key[m_path_min[m_set_child[s]]]) { - if (di->set_size[s] + di->set_size[di->set_child[di->set_child[s]]] - >= 2 * di->set_size[di->set_child[s]]) + if (m_set_size[s] + m_set_size[m_set_child[m_set_child[s]]] + >= 2 * m_set_size[m_set_child[s]]) { - di->set_chain[di->set_child[s]] = s; - di->set_child[s] = di->set_child[di->set_child[s]]; + m_set_chain[m_set_child[s]] = s; + m_set_child[s] = m_set_child[m_set_child[s]]; } else { - di->set_size[di->set_child[s]] = di->set_size[s]; - s = di->set_chain[s] = di->set_child[s]; + m_set_size[m_set_child[s]] = m_set_size[s]; + s = m_set_chain[s] = m_set_child[s]; } } - di->path_min[s] = di->path_min[w]; - di->set_size[v] += di->set_size[w]; - if (di->set_size[v] < 2 * di->set_size[w]) - std::swap (di->set_child[v], s); + m_path_min[s] = m_path_min[w]; + m_set_size[v] += m_set_size[w]; + if (m_set_size[v] < 2 * m_set_size[w]) + std::swap (m_set_child[v], s); /* Merge all subtrees. */ while (s) { - di->set_chain[s] = v; - s = di->set_child[s]; + m_set_chain[s] = v; + s = m_set_child[s]; } } -/* This calculates the immediate dominators (or post-dominators if REVERSE is - true). DI is our working structure and should hold the DFS forest. - On return the immediate dominator to node V is in di->dom[V]. */ +/* This calculates the immediate dominators (or post-dominators). THIS is our + working structure and should hold the DFS forest. + On return the immediate dominator to node V is in m_dom[V]. */ -static void -calc_idoms (struct dom_info *di, bool reverse) +void +dom_info::calc_idoms () { - TBB v, w, k, par; - basic_block en_block; - edge_iterator ei, einext; - - if (reverse) - en_block = EXIT_BLOCK_PTR_FOR_FN (cfun); - else - en_block = ENTRY_BLOCK_PTR_FOR_FN (cfun); - /* Go backwards in DFS order, to first look at the leafs. */ - v = di->nodes; - while (v > 1) + for (TBB v = m_nodes; v > 1; v--) { - basic_block bb = di->dfs_to_bb[v]; + basic_block bb = m_dfs_to_bb[v]; edge e; - par = di->dfs_parent[v]; - k = v; + TBB par = m_dfs_parent[v]; + TBB k = v; - ei = (reverse) ? ei_start (bb->succs) : ei_start (bb->preds); + edge_iterator ei = m_reverse ? ei_start (bb->succs) + : ei_start (bb->preds); + edge_iterator einext; - if (reverse) + if (m_reverse) { /* If this block has a fake edge to exit, process that first. */ - if (bitmap_bit_p (di->fake_exit_edge, bb->index)) + if (bitmap_bit_p (m_fake_exit_edge, bb->index)) { einext = ei; einext.index = 0; @@ -531,56 +530,55 @@ calc_idoms (struct dom_info *di, bool reverse) semidominator. */ while (!ei_end_p (ei)) { - TBB k1; basic_block b; + TBB k1; e = ei_edge (ei); - b = (reverse) ? e->dest : e->src; + b = m_reverse ? e->dest : e->src; einext = ei; ei_next (&einext); - if (b == en_block) + if (b == m_start_block) { do_fake_exit_edge: - k1 = di->dfs_order[last_basic_block_for_fn (cfun)]; + k1 = *m_dfs_last; } else - k1 = di->dfs_order[b->index]; + k1 = m_dfs_order[b->index]; /* Call eval() only if really needed. If k1 is above V in DFS tree, then we know, that eval(k1) == k1 and key[k1] == k1. */ if (k1 > v) - k1 = di->key[eval (di, k1)]; + k1 = m_key[eval (k1)]; if (k1 < k) k = k1; ei = einext; } - di->key[v] = k; - link_roots (di, par, v); - di->next_bucket[v] = di->bucket[k]; - di->bucket[k] = v; + m_key[v] = k; + link_roots (par, v); + m_next_bucket[v] = m_bucket[k]; + m_bucket[k] = v; /* Transform semidominators into dominators. */ - for (w = di->bucket[par]; w; w = di->next_bucket[w]) + for (TBB w = m_bucket[par]; w; w = m_next_bucket[w]) { - k = eval (di, w); - if (di->key[k] < di->key[w]) - di->dom[w] = k; + k = eval (w); + if (m_key[k] < m_key[w]) + m_dom[w] = k; else - di->dom[w] = par; + m_dom[w] = par; } /* We don't need to cleanup next_bucket[]. */ - di->bucket[par] = 0; - v--; + m_bucket[par] = 0; } /* Explicitly define the dominators. */ - di->dom[1] = 0; - for (v = 2; v <= di->nodes; v++) - if (di->dom[v] != di->key[v]) - di->dom[v] = di->dom[di->dom[v]]; + m_dom[1] = 0; + for (TBB v = 2; v <= m_nodes; v++) + if (m_dom[v] != m_key[v]) + m_dom[v] = m_dom[m_dom[v]]; } /* Assign dfs numbers starting from NUM to NODE and its sons. */ @@ -630,12 +628,9 @@ compute_dom_fast_query (enum cdi_direction dir) we want to compute dominators or postdominators. */ void -calculate_dominance_info (enum cdi_direction dir) +calculate_dominance_info (cdi_direction dir) { - struct dom_info di; - basic_block b; unsigned int dir_index = dom_convert_dir_to_idx (dir); - bool reverse = (dir == CDI_POST_DOMINATORS) ? true : false; if (dom_computed[dir_index] == DOM_OK) { @@ -650,25 +645,23 @@ calculate_dominance_info (enum cdi_direction dir) { gcc_assert (!n_bbs_in_dom_tree[dir_index]); + basic_block b; FOR_ALL_BB_FN (b, cfun) { b->dom[dir_index] = et_new_tree (b); } n_bbs_in_dom_tree[dir_index] = n_basic_blocks_for_fn (cfun); - init_dom_info (&di, dir); - calc_dfs_tree (&di, reverse); - calc_idoms (&di, reverse); + dom_info di (cfun, dir); + di.calc_dfs_tree (); + di.calc_idoms (); FOR_EACH_BB_FN (b, cfun) { - TBB d = di.dom[di.dfs_order[b->index]]; - - if (di.dfs_to_bb[d]) - et_set_father (b->dom[dir_index], di.dfs_to_bb[d]->dom[dir_index]); + if (basic_block d = di.get_idom (b)) + et_set_father (b->dom[dir_index], d->dom[dir_index]); } - free_dom_info (&di); dom_computed[dir_index] = DOM_NO_FAST_QUERY; } else @@ -1022,38 +1015,34 @@ bb_dom_dfs_out (enum cdi_direction dir, basic_block bb) /* Verify invariants of dominator structure. */ DEBUG_FUNCTION void -verify_dominators (enum cdi_direction dir) +verify_dominators (cdi_direction dir) { - int err = 0; - basic_block bb, imm_bb, imm_bb_correct; - struct dom_info di; - bool reverse = (dir == CDI_POST_DOMINATORS) ? true : false; - gcc_assert (dom_info_available_p (dir)); - init_dom_info (&di, dir); - calc_dfs_tree (&di, reverse); - calc_idoms (&di, reverse); + dom_info di (cfun, dir); + di.calc_dfs_tree (); + di.calc_idoms (); + bool err = false; + basic_block bb; FOR_EACH_BB_FN (bb, cfun) { - imm_bb = get_immediate_dominator (dir, bb); + basic_block imm_bb = get_immediate_dominator (dir, bb); if (!imm_bb) { error ("dominator of %d status unknown", bb->index); - err = 1; + err = true; } - imm_bb_correct = di.dfs_to_bb[di.dom[di.dfs_order[bb->index]]]; + basic_block imm_bb_correct = di.get_idom (bb); if (imm_bb != imm_bb_correct) { error ("dominator of %d should be %d, not %d", bb->index, imm_bb_correct->index, imm_bb->index); - err = 1; + err = true; } } - free_dom_info (&di); gcc_assert (!err); } diff --git a/gcc/expmed.c b/gcc/expmed.c index 59b2919ee3a..604a957a07b 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -3117,15 +3117,7 @@ expand_mult (machine_mode mode, rtx op0, rtx op1, rtx target, /* For vectors, there are several simplifications that can be made if all elements of the vector constant are identical. */ - scalar_op1 = op1; - if (GET_CODE (op1) == CONST_VECTOR) - { - int i, n = CONST_VECTOR_NUNITS (op1); - scalar_op1 = CONST_VECTOR_ELT (op1, 0); - for (i = 1; i < n; ++i) - if (!rtx_equal_p (scalar_op1, CONST_VECTOR_ELT (op1, i))) - goto skip_scalar; - } + scalar_op1 = unwrap_const_vec_duplicate (op1); if (INTEGRAL_MODE_P (mode)) { @@ -3254,7 +3246,6 @@ expand_mult (machine_mode mode, rtx op0, rtx op1, rtx target, target, unsignedp, OPTAB_LIB_WIDEN); } } - skip_scalar: /* This used to use umul_optab if unsigned, but for non-widening multiply there is no difference between signed and unsigned. */ diff --git a/gcc/expr.c b/gcc/expr.c index 3202f555838..ee0c1f93249 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -8836,23 +8836,112 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode, case LSHIFT_EXPR: case RSHIFT_EXPR: - /* If this is a fixed-point operation, then we cannot use the code - below because "expand_shift" doesn't support sat/no-sat fixed-point - shifts. */ - if (ALL_FIXED_POINT_MODE_P (mode)) - goto binop; + { + /* If this is a fixed-point operation, then we cannot use the code + below because "expand_shift" doesn't support sat/no-sat fixed-point + shifts. */ + if (ALL_FIXED_POINT_MODE_P (mode)) + goto binop; + + if (! safe_from_p (subtarget, treeop1, 1)) + subtarget = 0; + if (modifier == EXPAND_STACK_PARM) + target = 0; + op0 = expand_expr (treeop0, subtarget, + VOIDmode, EXPAND_NORMAL); + + /* Left shift optimization when shifting across word_size boundary. + + If mode == GET_MODE_WIDER_MODE (word_mode), then normally there isn't + native instruction to support this wide mode left shift. Given below + scenario: + + Type A = (Type) B << C + + |< T >| + | dest_high | dest_low | + + | word_size | + + If the shift amount C caused we shift B to across the word size + boundary, i.e part of B shifted into high half of destination + register, and part of B remains in the low half, then GCC will use + the following left shift expand logic: + + 1. Initialize dest_low to B. + 2. Initialize every bit of dest_high to the sign bit of B. + 3. Logic left shift dest_low by C bit to finalize dest_low. + The value of dest_low before this shift is kept in a temp D. + 4. Logic left shift dest_high by C. + 5. Logic right shift D by (word_size - C). + 6. Or the result of 4 and 5 to finalize dest_high. + + While, by checking gimple statements, if operand B is coming from + signed extension, then we can simplify above expand logic into: + + 1. dest_high = src_low >> (word_size - C). + 2. dest_low = src_low << C. + + We can use one arithmetic right shift to finish all the purpose of + steps 2, 4, 5, 6, thus we reduce the steps needed from 6 into 2. */ + + temp = NULL_RTX; + if (code == LSHIFT_EXPR + && target + && REG_P (target) + && ! unsignedp + && mode == GET_MODE_WIDER_MODE (word_mode) + && GET_MODE_SIZE (mode) == 2 * GET_MODE_SIZE (word_mode) + && ! have_insn_for (ASHIFT, mode) + && TREE_CONSTANT (treeop1) + && TREE_CODE (treeop0) == SSA_NAME) + { + gimple def = SSA_NAME_DEF_STMT (treeop0); + if (is_gimple_assign (def) + && gimple_assign_rhs_code (def) == NOP_EXPR) + { + machine_mode rmode = TYPE_MODE + (TREE_TYPE (gimple_assign_rhs1 (def))); - if (! safe_from_p (subtarget, treeop1, 1)) - subtarget = 0; - if (modifier == EXPAND_STACK_PARM) - target = 0; - op0 = expand_expr (treeop0, subtarget, - VOIDmode, EXPAND_NORMAL); - temp = expand_variable_shift (code, mode, op0, treeop1, target, - unsignedp); - if (code == LSHIFT_EXPR) - temp = REDUCE_BIT_FIELD (temp); - return temp; + if (GET_MODE_SIZE (rmode) < GET_MODE_SIZE (mode) + && TREE_INT_CST_LOW (treeop1) < GET_MODE_BITSIZE (word_mode) + && ((TREE_INT_CST_LOW (treeop1) + GET_MODE_BITSIZE (rmode)) + >= GET_MODE_BITSIZE (word_mode))) + { + unsigned int high_off = subreg_highpart_offset (word_mode, + mode); + rtx low = lowpart_subreg (word_mode, op0, mode); + rtx dest_low = lowpart_subreg (word_mode, target, mode); + rtx dest_high = simplify_gen_subreg (word_mode, target, + mode, high_off); + HOST_WIDE_INT ramount = (BITS_PER_WORD + - TREE_INT_CST_LOW (treeop1)); + tree rshift = build_int_cst (TREE_TYPE (treeop1), ramount); + + /* dest_high = src_low >> (word_size - C). */ + temp = expand_variable_shift (RSHIFT_EXPR, word_mode, low, + rshift, dest_high, unsignedp); + if (temp != dest_high) + emit_move_insn (dest_high, temp); + + /* dest_low = src_low << C. */ + temp = expand_variable_shift (LSHIFT_EXPR, word_mode, low, + treeop1, dest_low, unsignedp); + if (temp != dest_low) + emit_move_insn (dest_low, temp); + + temp = target ; + } + } + } + + if (temp == NULL_RTX) + temp = expand_variable_shift (code, mode, op0, treeop1, target, + unsignedp); + if (code == LSHIFT_EXPR) + temp = REDUCE_BIT_FIELD (temp); + return temp; + } /* Could determine the answer when only additive constants differ. Also, the addition of one can be handled by changing the condition. */ @@ -9374,6 +9463,10 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, if (g) { rtx r; + location_t saved_loc = curr_insn_location (); + location_t loc = gimple_location (g); + if (loc != UNKNOWN_LOCATION) + set_curr_insn_location (loc); ops.code = gimple_assign_rhs_code (g); switch (get_gimple_rhs_class (ops.code)) { @@ -9395,21 +9488,19 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode, case GIMPLE_UNARY_RHS: ops.op0 = gimple_assign_rhs1 (g); ops.type = TREE_TYPE (gimple_assign_lhs (g)); - ops.location = gimple_location (g); + ops.location = loc; r = expand_expr_real_2 (&ops, target, tmode, modifier); break; case GIMPLE_SINGLE_RHS: { - location_t saved_loc = curr_insn_location (); - set_curr_insn_location (gimple_location (g)); r = expand_expr_real (gimple_assign_rhs1 (g), target, tmode, modifier, NULL, inner_reference_p); - set_curr_insn_location (saved_loc); break; } default: gcc_unreachable (); } + set_curr_insn_location (saved_loc); if (REG_P (r) && !REG_EXPR (r)) set_reg_attrs_for_decl_rtl (SSA_NAME_VAR (exp), r); return r; diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 93d65147dd1..d478c4dc1c2 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -7732,21 +7732,6 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0) } return NULL_TREE; - case CONJ_EXPR: - if (TREE_CODE (TREE_TYPE (arg0)) != COMPLEX_TYPE) - return fold_convert_loc (loc, type, arg0); - if (TREE_CODE (arg0) == COMPLEX_EXPR) - { - tree itype = TREE_TYPE (type); - tree rpart = fold_convert_loc (loc, itype, TREE_OPERAND (arg0, 0)); - tree ipart = fold_convert_loc (loc, itype, TREE_OPERAND (arg0, 1)); - return fold_build2_loc (loc, COMPLEX_EXPR, type, rpart, - negate_expr (ipart)); - } - if (TREE_CODE (arg0) == CONJ_EXPR) - return fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0)); - return NULL_TREE; - case BIT_NOT_EXPR: /* Convert ~(X ^ Y) to ~X ^ Y or X ^ ~Y if ~X or ~Y simplify. */ if (TREE_CODE (arg0) == BIT_XOR_EXPR @@ -7776,81 +7761,6 @@ fold_unary_loc (location_t loc, enum tree_code code, tree type, tree op0) return NULL_TREE; return fold_convert_loc (loc, type, tem); - case REALPART_EXPR: - if (TREE_CODE (TREE_TYPE (arg0)) != COMPLEX_TYPE) - return fold_convert_loc (loc, type, arg0); - if (TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR) - { - tree itype = TREE_TYPE (TREE_TYPE (arg0)); - tem = fold_build2_loc (loc, TREE_CODE (arg0), itype, - fold_build1_loc (loc, REALPART_EXPR, itype, - TREE_OPERAND (arg0, 0)), - fold_build1_loc (loc, REALPART_EXPR, itype, - TREE_OPERAND (arg0, 1))); - return fold_convert_loc (loc, type, tem); - } - if (TREE_CODE (arg0) == CONJ_EXPR) - { - tree itype = TREE_TYPE (TREE_TYPE (arg0)); - tem = fold_build1_loc (loc, REALPART_EXPR, itype, - TREE_OPERAND (arg0, 0)); - return fold_convert_loc (loc, type, tem); - } - if (TREE_CODE (arg0) == CALL_EXPR) - { - tree fn = get_callee_fndecl (arg0); - if (fn && DECL_BUILT_IN_CLASS (fn) == BUILT_IN_NORMAL) - switch (DECL_FUNCTION_CODE (fn)) - { - CASE_FLT_FN (BUILT_IN_CEXPI): - fn = mathfn_built_in (type, BUILT_IN_COS); - if (fn) - return build_call_expr_loc (loc, fn, 1, CALL_EXPR_ARG (arg0, 0)); - break; - - default: - break; - } - } - return NULL_TREE; - - case IMAGPART_EXPR: - if (TREE_CODE (TREE_TYPE (arg0)) != COMPLEX_TYPE) - return build_zero_cst (type); - if (TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR) - { - tree itype = TREE_TYPE (TREE_TYPE (arg0)); - tem = fold_build2_loc (loc, TREE_CODE (arg0), itype, - fold_build1_loc (loc, IMAGPART_EXPR, itype, - TREE_OPERAND (arg0, 0)), - fold_build1_loc (loc, IMAGPART_EXPR, itype, - TREE_OPERAND (arg0, 1))); - return fold_convert_loc (loc, type, tem); - } - if (TREE_CODE (arg0) == CONJ_EXPR) - { - tree itype = TREE_TYPE (TREE_TYPE (arg0)); - tem = fold_build1_loc (loc, IMAGPART_EXPR, itype, TREE_OPERAND (arg0, 0)); - return fold_convert_loc (loc, type, negate_expr (tem)); - } - if (TREE_CODE (arg0) == CALL_EXPR) - { - tree fn = get_callee_fndecl (arg0); - if (fn && DECL_BUILT_IN_CLASS (fn) == BUILT_IN_NORMAL) - switch (DECL_FUNCTION_CODE (fn)) - { - CASE_FLT_FN (BUILT_IN_CEXPI): - fn = mathfn_built_in (type, BUILT_IN_SIN); - if (fn) - return build_call_expr_loc (loc, fn, 1, CALL_EXPR_ARG (arg0, 0)); - break; - - default: - break; - } - } - return NULL_TREE; - case INDIRECT_REF: /* Fold *&X to X if X is an lvalue. */ if (TREE_CODE (op0) == ADDR_EXPR) @@ -9947,127 +9857,6 @@ fold_binary_loc (location_t loc, if (flag_unsafe_math_optimizations) { - enum built_in_function fcode0 = builtin_mathfn_code (arg0); - enum built_in_function fcode1 = builtin_mathfn_code (arg1); - - /* Optimizations of root(...)*root(...). */ - if (fcode0 == fcode1 && BUILTIN_ROOT_P (fcode0)) - { - tree rootfn, arg; - tree arg00 = CALL_EXPR_ARG (arg0, 0); - tree arg10 = CALL_EXPR_ARG (arg1, 0); - - /* Optimize sqrt(x)*sqrt(x) as x. */ - if (BUILTIN_SQRT_P (fcode0) - && operand_equal_p (arg00, arg10, 0) - && ! HONOR_SNANS (element_mode (type))) - return arg00; - - /* Optimize root(x)*root(y) as root(x*y). */ - rootfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0); - arg = fold_build2_loc (loc, MULT_EXPR, type, arg00, arg10); - return build_call_expr_loc (loc, rootfn, 1, arg); - } - - /* Optimize expN(x)*expN(y) as expN(x+y). */ - if (fcode0 == fcode1 && BUILTIN_EXPONENT_P (fcode0)) - { - tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0); - tree arg = fold_build2_loc (loc, PLUS_EXPR, type, - CALL_EXPR_ARG (arg0, 0), - CALL_EXPR_ARG (arg1, 0)); - return build_call_expr_loc (loc, expfn, 1, arg); - } - - /* Optimizations of pow(...)*pow(...). */ - if ((fcode0 == BUILT_IN_POW && fcode1 == BUILT_IN_POW) - || (fcode0 == BUILT_IN_POWF && fcode1 == BUILT_IN_POWF) - || (fcode0 == BUILT_IN_POWL && fcode1 == BUILT_IN_POWL)) - { - tree arg00 = CALL_EXPR_ARG (arg0, 0); - tree arg01 = CALL_EXPR_ARG (arg0, 1); - tree arg10 = CALL_EXPR_ARG (arg1, 0); - tree arg11 = CALL_EXPR_ARG (arg1, 1); - - /* Optimize pow(x,y)*pow(z,y) as pow(x*z,y). */ - if (operand_equal_p (arg01, arg11, 0)) - { - tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0); - tree arg = fold_build2_loc (loc, MULT_EXPR, type, - arg00, arg10); - return build_call_expr_loc (loc, powfn, 2, arg, arg01); - } - - /* Optimize pow(x,y)*pow(x,z) as pow(x,y+z). */ - if (operand_equal_p (arg00, arg10, 0)) - { - tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0); - tree arg = fold_build2_loc (loc, PLUS_EXPR, type, - arg01, arg11); - return build_call_expr_loc (loc, powfn, 2, arg00, arg); - } - } - - /* Optimize tan(x)*cos(x) as sin(x). */ - if (((fcode0 == BUILT_IN_TAN && fcode1 == BUILT_IN_COS) - || (fcode0 == BUILT_IN_TANF && fcode1 == BUILT_IN_COSF) - || (fcode0 == BUILT_IN_TANL && fcode1 == BUILT_IN_COSL) - || (fcode0 == BUILT_IN_COS && fcode1 == BUILT_IN_TAN) - || (fcode0 == BUILT_IN_COSF && fcode1 == BUILT_IN_TANF) - || (fcode0 == BUILT_IN_COSL && fcode1 == BUILT_IN_TANL)) - && operand_equal_p (CALL_EXPR_ARG (arg0, 0), - CALL_EXPR_ARG (arg1, 0), 0)) - { - tree sinfn = mathfn_built_in (type, BUILT_IN_SIN); - - if (sinfn != NULL_TREE) - return build_call_expr_loc (loc, sinfn, 1, - CALL_EXPR_ARG (arg0, 0)); - } - - /* Optimize x*pow(x,c) as pow(x,c+1). */ - if (fcode1 == BUILT_IN_POW - || fcode1 == BUILT_IN_POWF - || fcode1 == BUILT_IN_POWL) - { - tree arg10 = CALL_EXPR_ARG (arg1, 0); - tree arg11 = CALL_EXPR_ARG (arg1, 1); - if (TREE_CODE (arg11) == REAL_CST - && !TREE_OVERFLOW (arg11) - && operand_equal_p (arg0, arg10, 0)) - { - tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg1), 0); - REAL_VALUE_TYPE c; - tree arg; - - c = TREE_REAL_CST (arg11); - real_arithmetic (&c, PLUS_EXPR, &c, &dconst1); - arg = build_real (type, c); - return build_call_expr_loc (loc, powfn, 2, arg0, arg); - } - } - - /* Optimize pow(x,c)*x as pow(x,c+1). */ - if (fcode0 == BUILT_IN_POW - || fcode0 == BUILT_IN_POWF - || fcode0 == BUILT_IN_POWL) - { - tree arg00 = CALL_EXPR_ARG (arg0, 0); - tree arg01 = CALL_EXPR_ARG (arg0, 1); - if (TREE_CODE (arg01) == REAL_CST - && !TREE_OVERFLOW (arg01) - && operand_equal_p (arg1, arg00, 0)) - { - tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0); - REAL_VALUE_TYPE c; - tree arg; - - c = TREE_REAL_CST (arg01); - real_arithmetic (&c, PLUS_EXPR, &c, &dconst1); - arg = build_real (type, c); - return build_call_expr_loc (loc, powfn, 2, arg1, arg); - } - } /* Canonicalize x*x as pow(x,2.0), which is expanded as x*x. */ if (!in_gimple_form @@ -10479,152 +10268,6 @@ fold_binary_loc (location_t loc, TREE_OPERAND (arg1, 0)); } - if (flag_unsafe_math_optimizations) - { - enum built_in_function fcode0 = builtin_mathfn_code (arg0); - enum built_in_function fcode1 = builtin_mathfn_code (arg1); - - /* Optimize sin(x)/cos(x) as tan(x). */ - if (((fcode0 == BUILT_IN_SIN && fcode1 == BUILT_IN_COS) - || (fcode0 == BUILT_IN_SINF && fcode1 == BUILT_IN_COSF) - || (fcode0 == BUILT_IN_SINL && fcode1 == BUILT_IN_COSL)) - && operand_equal_p (CALL_EXPR_ARG (arg0, 0), - CALL_EXPR_ARG (arg1, 0), 0)) - { - tree tanfn = mathfn_built_in (type, BUILT_IN_TAN); - - if (tanfn != NULL_TREE) - return build_call_expr_loc (loc, tanfn, 1, CALL_EXPR_ARG (arg0, 0)); - } - - /* Optimize cos(x)/sin(x) as 1.0/tan(x). */ - if (((fcode0 == BUILT_IN_COS && fcode1 == BUILT_IN_SIN) - || (fcode0 == BUILT_IN_COSF && fcode1 == BUILT_IN_SINF) - || (fcode0 == BUILT_IN_COSL && fcode1 == BUILT_IN_SINL)) - && operand_equal_p (CALL_EXPR_ARG (arg0, 0), - CALL_EXPR_ARG (arg1, 0), 0)) - { - tree tanfn = mathfn_built_in (type, BUILT_IN_TAN); - - if (tanfn != NULL_TREE) - { - tree tmp = build_call_expr_loc (loc, tanfn, 1, - CALL_EXPR_ARG (arg0, 0)); - return fold_build2_loc (loc, RDIV_EXPR, type, - build_real (type, dconst1), tmp); - } - } - - /* Optimize sin(x)/tan(x) as cos(x) if we don't care about - NaNs or Infinities. */ - if (((fcode0 == BUILT_IN_SIN && fcode1 == BUILT_IN_TAN) - || (fcode0 == BUILT_IN_SINF && fcode1 == BUILT_IN_TANF) - || (fcode0 == BUILT_IN_SINL && fcode1 == BUILT_IN_TANL))) - { - tree arg00 = CALL_EXPR_ARG (arg0, 0); - tree arg01 = CALL_EXPR_ARG (arg1, 0); - - if (! HONOR_NANS (arg00) - && ! HONOR_INFINITIES (element_mode (arg00)) - && operand_equal_p (arg00, arg01, 0)) - { - tree cosfn = mathfn_built_in (type, BUILT_IN_COS); - - if (cosfn != NULL_TREE) - return build_call_expr_loc (loc, cosfn, 1, arg00); - } - } - - /* Optimize tan(x)/sin(x) as 1.0/cos(x) if we don't care about - NaNs or Infinities. */ - if (((fcode0 == BUILT_IN_TAN && fcode1 == BUILT_IN_SIN) - || (fcode0 == BUILT_IN_TANF && fcode1 == BUILT_IN_SINF) - || (fcode0 == BUILT_IN_TANL && fcode1 == BUILT_IN_SINL))) - { - tree arg00 = CALL_EXPR_ARG (arg0, 0); - tree arg01 = CALL_EXPR_ARG (arg1, 0); - - if (! HONOR_NANS (arg00) - && ! HONOR_INFINITIES (element_mode (arg00)) - && operand_equal_p (arg00, arg01, 0)) - { - tree cosfn = mathfn_built_in (type, BUILT_IN_COS); - - if (cosfn != NULL_TREE) - { - tree tmp = build_call_expr_loc (loc, cosfn, 1, arg00); - return fold_build2_loc (loc, RDIV_EXPR, type, - build_real (type, dconst1), - tmp); - } - } - } - - /* Optimize pow(x,c)/x as pow(x,c-1). */ - if (fcode0 == BUILT_IN_POW - || fcode0 == BUILT_IN_POWF - || fcode0 == BUILT_IN_POWL) - { - tree arg00 = CALL_EXPR_ARG (arg0, 0); - tree arg01 = CALL_EXPR_ARG (arg0, 1); - if (TREE_CODE (arg01) == REAL_CST - && !TREE_OVERFLOW (arg01) - && operand_equal_p (arg1, arg00, 0)) - { - tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg0), 0); - REAL_VALUE_TYPE c; - tree arg; - - c = TREE_REAL_CST (arg01); - real_arithmetic (&c, MINUS_EXPR, &c, &dconst1); - arg = build_real (type, c); - return build_call_expr_loc (loc, powfn, 2, arg1, arg); - } - } - - /* Optimize a/root(b/c) into a*root(c/b). */ - if (BUILTIN_ROOT_P (fcode1)) - { - tree rootarg = CALL_EXPR_ARG (arg1, 0); - - if (TREE_CODE (rootarg) == RDIV_EXPR) - { - tree rootfn = TREE_OPERAND (CALL_EXPR_FN (arg1), 0); - tree b = TREE_OPERAND (rootarg, 0); - tree c = TREE_OPERAND (rootarg, 1); - - tree tmp = fold_build2_loc (loc, RDIV_EXPR, type, c, b); - - tmp = build_call_expr_loc (loc, rootfn, 1, tmp); - return fold_build2_loc (loc, MULT_EXPR, type, arg0, tmp); - } - } - - /* Optimize x/expN(y) into x*expN(-y). */ - if (BUILTIN_EXPONENT_P (fcode1)) - { - tree expfn = TREE_OPERAND (CALL_EXPR_FN (arg1), 0); - tree arg = negate_expr (CALL_EXPR_ARG (arg1, 0)); - arg1 = build_call_expr_loc (loc, - expfn, 1, - fold_convert_loc (loc, type, arg)); - return fold_build2_loc (loc, MULT_EXPR, type, arg0, arg1); - } - - /* Optimize x/pow(y,z) into x*pow(y,-z). */ - if (fcode1 == BUILT_IN_POW - || fcode1 == BUILT_IN_POWF - || fcode1 == BUILT_IN_POWL) - { - tree powfn = TREE_OPERAND (CALL_EXPR_FN (arg1), 0); - tree arg10 = CALL_EXPR_ARG (arg1, 0); - tree arg11 = CALL_EXPR_ARG (arg1, 1); - tree neg11 = fold_convert_loc (loc, type, - negate_expr (arg11)); - arg1 = build_call_expr_loc (loc, powfn, 2, arg10, neg11); - return fold_build2_loc (loc, MULT_EXPR, type, arg0, arg1); - } - } return NULL_TREE; case TRUNC_DIV_EXPR: @@ -11035,11 +10678,6 @@ fold_binary_loc (location_t loc, TREE_OPERAND (arg0, 1), arg1); } - /* Convert ABS_EXPR<x> == 0 or ABS_EXPR<x> != 0 to x == 0 or x != 0. */ - if (TREE_CODE (arg0) == ABS_EXPR - && (integer_zerop (arg1) || real_zerop (arg1))) - return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0), arg1); - /* If this is an EQ or NE comparison with zero and ARG0 is (1 << foo) & bar, convert it to (bar >> foo) & 1. Both require two operations, but the latter can be done in one less insn @@ -11142,21 +10780,6 @@ fold_binary_loc (location_t loc, } } - /* If we have (A & C) == C where C is a power of 2, convert this into - (A & C) != 0. Similarly for NE_EXPR. */ - if (TREE_CODE (arg0) == BIT_AND_EXPR - && integer_pow2p (TREE_OPERAND (arg0, 1)) - && operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0)) - return fold_build2_loc (loc, code == EQ_EXPR ? NE_EXPR : EQ_EXPR, type, - arg0, fold_convert_loc (loc, TREE_TYPE (arg0), - integer_zero_node)); - - /* If we have (A & C) != 0 or (A & C) == 0 and C is the sign - bit, then fold the expression into A < 0 or A >= 0. */ - tem = fold_single_bit_test_into_sign_test (loc, code, arg0, arg1, type); - if (tem) - return tem; - /* If we have (A & C) == D where D & ~C != 0, convert this into 0. Similarly for NE_EXPR. */ if (TREE_CODE (arg0) == BIT_AND_EXPR diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 3a638751747..88c1a117caa 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,49 @@ +2015-08-31 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> + + PR fortran/54833 + * trans.c (gfc_call_free): Don't check if pointer is NULL. + * trans.h (gfc_call_free): Adjust comment. + +2015-08-29 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> + + * trans.c (gfc_call_malloc, gfc_allocate_using_malloc, + gfc_allocate_using_lib, gfc_allocate_allocatable, + gfc_call_realloc): Simplify code. + * trans-array.c (gfc_trans_allocate_array_storage, + gfc_trans_auto_array_allocation, gfc_conv_array_parameter): Do not + convert gfc_call_free() argument. + * trans-expr.c (gfc_conv_string_tmp, gfc_conv_procedure_call, + fcncall_realloc_result): Likewise. + * trans-intrinsic.c (gfc_conv_intrinsic_transfer): Likewise. + +2015-08-28 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> + + PR fortran/53668 + * intrinsic.c (add_functions, add_subroutines): Remove resolution + functions for FREE and MALLOC. + * intrinsic.h (gfc_resolve_malloc, gfc_resolve_free): Remove. + * iresolve.c (gfc_resolve_malloc, gfc_resolve_free): Remove. + * trans-intrinsic.c (conv_intrinsic_free, + gfc_conv_intrinsic_malloc): New functions. + +2015-08-24 Louis Krupp <louis.krupp@zoho.com> + + PR fortran/62536 + PR fortran/66175 + * decl.c (gfc_match_end): Clean up nested BLOCKs. + * parse.c (parse_block_construct): Deal gracefully with cleaned-up + BLOCKs. + +2015-08-23 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> + + PR libfortran/54572 + * config-lang.in: Add libbacktrace to target_libs. + +2015-08-18 Trevor Saunders <tbsaunde@tbsaunde.org> + + * dependency.c, dependency.h, gfortran.h, io.c, module.c, + parse.h, resolve.c, trans-types.h, trans.h: remove useless typedefs. + 2015-08-16 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> PR fortran/54656 diff --git a/gcc/fortran/config-lang.in b/gcc/fortran/config-lang.in index de8a499646a..a6c6b92e252 100644 --- a/gcc/fortran/config-lang.in +++ b/gcc/fortran/config-lang.in @@ -27,7 +27,7 @@ language="fortran" compilers="f951\$(exeext)" -target_libs=target-libgfortran +target_libs="target-libgfortran target-libbacktrace" gtfiles="\$(srcdir)/fortran/f95-lang.c \$(srcdir)/fortran/trans-decl.c \$(srcdir)/fortran/trans-intrinsic.c \$(srcdir)/fortran/trans-io.c \$(srcdir)/fortran/trans-stmt.c \$(srcdir)/fortran/trans-types.c \$(srcdir)/fortran/trans-types.h \$(srcdir)/fortran/trans.h \$(srcdir)/fortran/trans-const.h" diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c index ebc88eaa5dd..6829d178c92 100644 --- a/gcc/fortran/decl.c +++ b/gcc/fortran/decl.c @@ -6483,7 +6483,7 @@ cleanup: /* If we are missing an END BLOCK, we created a half-ready namespace. Remove it from the parent namespace's sibling list. */ - if (state == COMP_BLOCK) + while (state == COMP_BLOCK) { parent_ns = gfc_current_ns->parent; @@ -6506,6 +6506,8 @@ cleanup: gfc_free_namespace (gfc_current_ns); gfc_current_ns = parent_ns; + gfc_state_stack = gfc_state_stack->previous; + state = gfc_current_state (); } return MATCH_ERROR; diff --git a/gcc/fortran/intrinsic.c b/gcc/fortran/intrinsic.c index a80b16e68b4..b46a5b21b79 100644 --- a/gcc/fortran/intrinsic.c +++ b/gcc/fortran/intrinsic.c @@ -2298,7 +2298,7 @@ add_functions (void) make_generic ("lstat", GFC_ISYM_LSTAT, GFC_STD_GNU); add_sym_1 ("malloc", GFC_ISYM_MALLOC, CLASS_IMPURE, ACTUAL_NO, BT_INTEGER, ii, - GFC_STD_GNU, gfc_check_malloc, NULL, gfc_resolve_malloc, + GFC_STD_GNU, gfc_check_malloc, NULL, NULL, sz, BT_INTEGER, di, REQUIRED); make_generic ("malloc", GFC_ISYM_MALLOC, GFC_STD_GNU); @@ -3433,7 +3433,7 @@ add_subroutines (void) st, BT_INTEGER, di, OPTIONAL, INTENT_OUT); add_sym_1s ("free", GFC_ISYM_FREE, CLASS_IMPURE, BT_UNKNOWN, 0, GFC_STD_GNU, - gfc_check_free, NULL, gfc_resolve_free, + gfc_check_free, NULL, NULL, ptr, BT_INTEGER, ii, REQUIRED, INTENT_INOUT); add_sym_4s ("fseek", GFC_ISYM_FSEEK, CLASS_IMPURE, BT_UNKNOWN, 0, GFC_STD_GNU, diff --git a/gcc/fortran/intrinsic.h b/gcc/fortran/intrinsic.h index a9f16f52743..4e91b822b22 100644 --- a/gcc/fortran/intrinsic.h +++ b/gcc/fortran/intrinsic.h @@ -522,7 +522,6 @@ void gfc_resolve_log (gfc_expr *, gfc_expr *); void gfc_resolve_log10 (gfc_expr *, gfc_expr *); void gfc_resolve_logical (gfc_expr *, gfc_expr *, gfc_expr *); void gfc_resolve_lstat (gfc_expr *, gfc_expr *, gfc_expr *); -void gfc_resolve_malloc (gfc_expr *, gfc_expr *); void gfc_resolve_matmul (gfc_expr *, gfc_expr *, gfc_expr *); void gfc_resolve_max (gfc_expr *, gfc_actual_arglist *); void gfc_resolve_maxloc (gfc_expr *, gfc_expr *, gfc_expr *, gfc_expr *); @@ -605,7 +604,6 @@ void gfc_resolve_exit (gfc_code *); void gfc_resolve_fdate_sub (gfc_code *); void gfc_resolve_fe_runtime_error (gfc_code *); void gfc_resolve_flush (gfc_code *); -void gfc_resolve_free (gfc_code *); void gfc_resolve_fseek_sub (gfc_code *); void gfc_resolve_fstat_sub (gfc_code *); void gfc_resolve_ftell_sub (gfc_code *); diff --git a/gcc/fortran/iresolve.c b/gcc/fortran/iresolve.c index cf79256b14e..7503f183749 100644 --- a/gcc/fortran/iresolve.c +++ b/gcc/fortran/iresolve.c @@ -1505,25 +1505,6 @@ gfc_resolve_logical (gfc_expr *f, gfc_expr *a, gfc_expr *kind) void -gfc_resolve_malloc (gfc_expr *f, gfc_expr *size) -{ - if (size->ts.kind < gfc_index_integer_kind) - { - gfc_typespec ts; - gfc_clear_ts (&ts); - - ts.type = BT_INTEGER; - ts.kind = gfc_index_integer_kind; - gfc_convert_type_warn (size, &ts, 2, 0); - } - - f->ts.type = BT_INTEGER; - f->ts.kind = gfc_index_integer_kind; - f->value.function.name = gfc_get_string (PREFIX ("malloc")); -} - - -void gfc_resolve_matmul (gfc_expr *f, gfc_expr *a, gfc_expr *b) { gfc_expr temp; @@ -3386,23 +3367,6 @@ gfc_resolve_flush (gfc_code *c) void -gfc_resolve_free (gfc_code *c) -{ - gfc_typespec ts; - gfc_expr *n; - gfc_clear_ts (&ts); - - ts.type = BT_INTEGER; - ts.kind = gfc_index_integer_kind; - n = c->ext.actual->expr; - if (n->ts.kind != ts.kind) - gfc_convert_type (n, &ts, 2); - - c->resolved_sym = gfc_get_intrinsic_sub_symbol (PREFIX ("free")); -} - - -void gfc_resolve_ctime_sub (gfc_code *c) { gfc_typespec ts; diff --git a/gcc/fortran/parse.c b/gcc/fortran/parse.c index 04b4c80d0e6..62bcb61e96e 100644 --- a/gcc/fortran/parse.c +++ b/gcc/fortran/parse.c @@ -3935,6 +3935,7 @@ static void parse_block_construct (void) { gfc_namespace* my_ns; + gfc_namespace* my_parent; gfc_state_data s; gfc_notify_std (GFC_STD_F2008, "BLOCK construct at %C"); @@ -3948,10 +3949,14 @@ parse_block_construct (void) push_state (&s, COMP_BLOCK, my_ns->proc_name); gfc_current_ns = my_ns; + my_parent = my_ns->parent; parse_progunit (ST_NONE); - gfc_current_ns = gfc_current_ns->parent; + /* Don't depend on the value of gfc_current_ns; it might have been + reset if the block had errors and was cleaned up. */ + gfc_current_ns = my_parent; + pop_state (); } diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c index 16577392763..a6b761baba8 100644 --- a/gcc/fortran/trans-array.c +++ b/gcc/fortran/trans-array.c @@ -922,7 +922,7 @@ gfc_trans_allocate_array_storage (stmtblock_t * pre, stmtblock_t * post, { /* Free the temporary. */ tmp = gfc_conv_descriptor_data_get (desc); - tmp = gfc_call_free (fold_convert (pvoid_type_node, tmp)); + tmp = gfc_call_free (tmp); gfc_add_expr_to_block (post, tmp); } } @@ -5885,7 +5885,7 @@ gfc_trans_auto_array_allocation (tree decl, gfc_symbol * sym, gfc_add_modify (&init, decl, tmp); /* Free the temporary. */ - tmp = gfc_call_free (convert (pvoid_type_node, decl)); + tmp = gfc_call_free (decl); space = NULL_TREE; } @@ -7542,7 +7542,7 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, bool g77, } /* Free the temporary. */ - tmp = gfc_call_free (convert (pvoid_type_node, ptr)); + tmp = gfc_call_free (ptr); gfc_add_expr_to_block (&block, tmp); stmt = gfc_finish_block (&block); diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c index 16ebd206bac..cfa1a71fc8d 100644 --- a/gcc/fortran/trans-expr.c +++ b/gcc/fortran/trans-expr.c @@ -3035,7 +3035,7 @@ gfc_conv_string_tmp (gfc_se * se, tree type, tree len) gfc_add_modify (&se->pre, var, tmp); /* Free the temporary afterwards. */ - tmp = gfc_call_free (convert (pvoid_type_node, var)); + tmp = gfc_call_free (var); gfc_add_expr_to_block (&se->post, tmp); } @@ -5880,7 +5880,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, gfc_add_modify (&se->pre, var, fold_convert (TREE_TYPE (var), null_pointer_node)); - tmp = gfc_call_free (convert (pvoid_type_node, var)); + tmp = gfc_call_free (var); gfc_add_expr_to_block (&se->post, tmp); } @@ -6140,14 +6140,14 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, if (se->ss && se->ss->loop) { gfc_add_expr_to_block (&se->ss->loop->post, tmp); - tmp = gfc_call_free (convert (pvoid_type_node, info->data)); + tmp = gfc_call_free (info->data); gfc_add_expr_to_block (&se->ss->loop->post, tmp); } else { gfc_add_expr_to_block (&se->post, tmp); tmp = gfc_class_data_get (se->expr); - tmp = gfc_call_free (convert (pvoid_type_node, tmp)); + tmp = gfc_call_free (tmp); gfc_add_expr_to_block (&se->post, tmp); } expr->must_finalize = 0; @@ -8453,7 +8453,7 @@ fcncall_realloc_result (gfc_se *se, int rank) boolean_type_node, tmp, build_int_cst (TREE_TYPE (tmp), 0)); zero_cond = gfc_evaluate_now (zero_cond, &se->post); - tmp = gfc_call_free (fold_convert (pvoid_type_node, tmp)); + tmp = gfc_call_free (tmp); gfc_add_expr_to_block (&se->post, tmp); tmp = gfc_conv_descriptor_data_get (res_desc); diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c index f5b270f4bf7..35052bebb8e 100644 --- a/gcc/fortran/trans-intrinsic.c +++ b/gcc/fortran/trans-intrinsic.c @@ -2657,6 +2657,27 @@ gfc_conv_intrinsic_fdate (gfc_se * se, gfc_expr * expr) } +/* Generate a direct call to free() for the FREE subroutine. */ + +static tree +conv_intrinsic_free (gfc_code *code) +{ + stmtblock_t block; + gfc_se argse; + tree arg, call; + + gfc_init_se (&argse, NULL); + gfc_conv_expr (&argse, code->ext.actual->expr); + arg = fold_convert (ptr_type_node, argse.expr); + + gfc_init_block (&block); + call = build_call_expr_loc (input_location, + builtin_decl_explicit (BUILT_IN_FREE), 1, arg); + gfc_add_expr_to_block (&block, call); + return gfc_finish_block (&block); +} + + /* Call the SYSTEM_CLOCK library functions, handling the type and kind conversions. */ @@ -6238,7 +6259,7 @@ gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr) /* Free the temporary. */ gfc_start_block (&block); - tmp = gfc_call_free (convert (pvoid_type_node, source)); + tmp = gfc_call_free (source); gfc_add_expr_to_block (&block, tmp); stmt = gfc_finish_block (&block); @@ -7648,6 +7669,22 @@ gfc_conv_ieee_arithmetic_function (gfc_se * se, gfc_expr * expr) } +/* Generate a direct call to malloc() for the MALLOC intrinsic. */ + +static void +gfc_conv_intrinsic_malloc (gfc_se * se, gfc_expr * expr) +{ + tree arg, res, restype; + + gfc_conv_intrinsic_function_args (se, expr, &arg, 1); + arg = fold_convert (size_type_node, arg); + res = build_call_expr_loc (input_location, + builtin_decl_explicit (BUILT_IN_MALLOC), 1, arg); + restype = gfc_typenode_for_spec (&expr->ts); + se->expr = fold_convert (restype, res); +} + + /* Generate code for an intrinsic function. Some map directly to library calls, others get special handling. In some cases the name of the function used depends on the type specifiers. */ @@ -8078,6 +8115,10 @@ gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr) gfc_conv_intrinsic_strcmp (se, expr, LT_EXPR); break; + case GFC_ISYM_MALLOC: + gfc_conv_intrinsic_malloc (se, expr); + break; + case GFC_ISYM_MASKL: gfc_conv_intrinsic_mask (se, expr, 1); break; @@ -8267,7 +8308,6 @@ gfc_conv_intrinsic_function (gfc_se * se, gfc_expr * expr) case GFC_ISYM_JN2: case GFC_ISYM_LINK: case GFC_ISYM_LSTAT: - case GFC_ISYM_MALLOC: case GFC_ISYM_MATMUL: case GFC_ISYM_MCLOCK: case GFC_ISYM_MCLOCK8: @@ -9536,6 +9576,10 @@ gfc_conv_intrinsic_subroutine (gfc_code *code) res = conv_co_collective (code); break; + case GFC_ISYM_FREE: + res = conv_intrinsic_free (code); + break; + case GFC_ISYM_SYSTEM_CLOCK: res = conv_intrinsic_system_clock (code); break; diff --git a/gcc/fortran/trans.c b/gcc/fortran/trans.c index aece77ab5cd..f30809a9fda 100644 --- a/gcc/fortran/trans.c +++ b/gcc/fortran/trans.c @@ -567,17 +567,13 @@ gfc_call_malloc (stmtblock_t * block, tree type, tree size) tree tmp, msg, malloc_result, null_result, res, malloc_tree; stmtblock_t block2; - size = gfc_evaluate_now (size, block); - - if (TREE_TYPE (size) != TREE_TYPE (size_type_node)) - size = fold_convert (size_type_node, size); - /* Create a variable to hold the result. */ res = gfc_create_var (prvoid_type_node, NULL); /* Call malloc. */ gfc_start_block (&block2); + size = fold_convert (size_type_node, size); size = fold_build2_loc (input_location, MAX_EXPR, size_type_node, size, build_int_cst (size_type_node, 1)); @@ -604,7 +600,6 @@ gfc_call_malloc (stmtblock_t * block, tree type, tree size) } malloc_result = gfc_finish_block (&block2); - gfc_add_expr_to_block (block, malloc_result); if (type != NULL) @@ -643,11 +638,6 @@ gfc_allocate_using_malloc (stmtblock_t * block, tree pointer, stmtblock_t on_error; tree status_type = status ? TREE_TYPE (status) : NULL_TREE; - /* Evaluate size only once, and make sure it has the right type. */ - size = gfc_evaluate_now (size, block); - if (TREE_TYPE (size) != TREE_TYPE (size_type_node)) - size = fold_convert (size_type_node, size); - /* If successful and stat= is given, set status to 0. */ if (status != NULL_TREE) gfc_add_expr_to_block (block, @@ -655,6 +645,7 @@ gfc_allocate_using_malloc (stmtblock_t * block, tree pointer, status, build_int_cst (status_type, 0))); /* The allocation itself. */ + size = fold_convert (size_type_node, size); gfc_add_modify (block, pointer, fold_convert (TREE_TYPE (pointer), build_call_expr_loc (input_location, @@ -716,11 +707,6 @@ gfc_allocate_using_lib (stmtblock_t * block, tree pointer, tree size, gcc_assert (token != NULL_TREE); - /* Evaluate size only once, and make sure it has the right type. */ - size = gfc_evaluate_now (size, block); - if (TREE_TYPE (size) != TREE_TYPE (size_type_node)) - size = fold_convert (size_type_node, size); - /* The allocation itself. */ if (status == NULL_TREE) pstat = null_pointer_node; @@ -734,6 +720,7 @@ gfc_allocate_using_lib (stmtblock_t * block, tree pointer, tree size, errlen = build_int_cst (integer_type_node, 0); } + size = fold_convert (size_type_node, size); tmp = build_call_expr_loc (input_location, gfor_fndecl_caf_register, 6, fold_build2_loc (input_location, @@ -782,9 +769,7 @@ gfc_allocate_allocatable (stmtblock_t * block, tree mem, tree size, tree token, tree tmp, null_mem, alloc, error; tree type = TREE_TYPE (mem); - if (TREE_TYPE (size) != TREE_TYPE (size_type_node)) - size = fold_convert (size_type_node, size); - + size = fold_convert (size_type_node, size); null_mem = gfc_unlikely (fold_build2_loc (input_location, NE_EXPR, boolean_type_node, mem, build_int_cst (type, 0)), @@ -865,28 +850,14 @@ gfc_allocate_allocatable (stmtblock_t * block, tree mem, tree size, tree token, } -/* Free a given variable, if it's not NULL. */ +/* Free a given variable. */ + tree gfc_call_free (tree var) { - stmtblock_t block; - tree tmp, cond, call; - - if (TREE_TYPE (var) != TREE_TYPE (pvoid_type_node)) - var = fold_convert (pvoid_type_node, var); - - gfc_start_block (&block); - var = gfc_evaluate_now (var, &block); - cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, var, - build_int_cst (pvoid_type_node, 0)); - call = build_call_expr_loc (input_location, + return build_call_expr_loc (input_location, builtin_decl_explicit (BUILT_IN_FREE), - 1, var); - tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, call, - build_empty_stmt (input_location)); - gfc_add_expr_to_block (&block, tmp); - - return gfc_finish_block (&block); + 1, fold_convert (pvoid_type_node, var)); } @@ -1499,10 +1470,8 @@ gfc_call_realloc (stmtblock_t * block, tree mem, tree size) tree msg, res, nonzero, null_result, tmp; tree type = TREE_TYPE (mem); - size = gfc_evaluate_now (size, block); - - if (TREE_TYPE (size) != TREE_TYPE (size_type_node)) - size = fold_convert (size_type_node, size); + /* Only evaluate the size once. */ + size = save_expr (fold_convert (size_type_node, size)); /* Create a variable to hold the result. */ res = gfc_create_var (type, NULL); diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h index 6a9ba602531..222f8ddb665 100644 --- a/gcc/fortran/trans.h +++ b/gcc/fortran/trans.h @@ -644,7 +644,7 @@ void gfc_trans_runtime_check (bool, bool, tree, stmtblock_t *, locus *, void gfc_trans_same_strlen_check (const char*, locus*, tree, tree, stmtblock_t*); -/* Generate a call to free() after checking that its arg is non-NULL. */ +/* Generate a call to free(). */ tree gfc_call_free (tree); /* Allocate memory after performing a few checks. */ diff --git a/gcc/function.c b/gcc/function.c index 5a3c7bcbb38..2c5a6d484f6 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -153,6 +153,7 @@ static void do_clobber_return_reg (rtx, void *); static void do_use_return_reg (rtx, void *); static rtx rtl_for_parm (struct assign_parm_data_all *, tree); static void maybe_reset_rtl_for_parm (tree); +static bool parm_in_unassigned_mem_p (tree, rtx); /* Stack of nested functions. */ @@ -2326,6 +2327,22 @@ split_complex_args (struct assign_parm_data_all *all, vec<tree> *args) rtx rtl = rtl_for_parm (all, cparm); if (rtl) { + /* If this is parm is unassigned, assign it now: the + newly-created decls wouldn't expect the need for + assignment, and if they were assigned + independently, they might not end up in adjacent + slots, so unsplit wouldn't be able to fill in the + unassigned address of the complex MEM. */ + if (parm_in_unassigned_mem_p (cparm, rtl)) + { + int align = STACK_SLOT_ALIGNMENT + (TREE_TYPE (cparm), GET_MODE (rtl), MEM_ALIGN (rtl)); + rtx loc = assign_stack_local + (GET_MODE (rtl), GET_MODE_SIZE (GET_MODE (rtl)), + align); + XEXP (rtl, 0) = XEXP (loc, 0); + } + SET_DECL_RTL (p, read_complex_part (rtl, false)); SET_DECL_RTL (decl, read_complex_part (rtl, true)); @@ -2934,6 +2951,27 @@ assign_parm_setup_block_p (struct assign_parm_data_one *data) return false; } +/* Return true if FROM_EXPAND is a MEM with an address to be filled in + by assign_params. This should be the case if, and only if, + parm_in_stack_slot_p holds for the parm DECL that expanded to + FROM_EXPAND, so we check that, too. */ + +static bool +parm_in_unassigned_mem_p (tree decl, rtx from_expand) +{ + bool result = MEM_P (from_expand) && !XEXP (from_expand, 0); + + gcc_assert (result == parm_in_stack_slot_p (decl) + /* Maybe it was already assigned. That's ok, especially + for split complex args. */ + || (!result && MEM_P (from_expand) + && (XEXP (from_expand, 0) == virtual_stack_vars_rtx + || (GET_CODE (XEXP (from_expand, 0)) == PLUS + && XEXP (XEXP (from_expand, 0), 0) == virtual_stack_vars_rtx)))); + + return result; +} + /* A subroutine of assign_parms. Arrange for the parameter to be present and valid in DATA->STACK_RTL. */ @@ -2956,8 +2994,7 @@ assign_parm_setup_block (struct assign_parm_data_all *all, { DECL_ALIGN (parm) = MAX (DECL_ALIGN (parm), BITS_PER_WORD); rtx from_expand = rtl_for_parm (all, parm); - if (from_expand && (!parm_maybe_byref_p (parm) - || XEXP (from_expand, 0) != NULL_RTX)) + if (from_expand && !parm_in_unassigned_mem_p (parm, from_expand)) stack_parm = copy_rtx (from_expand); else { @@ -2968,8 +3005,7 @@ assign_parm_setup_block (struct assign_parm_data_all *all, if (from_expand) { gcc_assert (GET_CODE (stack_parm) == MEM); - gcc_assert (GET_CODE (from_expand) == MEM); - gcc_assert (XEXP (from_expand, 0) == NULL_RTX); + gcc_assert (parm_in_unassigned_mem_p (parm, from_expand)); XEXP (from_expand, 0) = XEXP (stack_parm, 0); PUT_MODE (from_expand, GET_MODE (stack_parm)); stack_parm = copy_rtx (from_expand); @@ -3017,6 +3053,11 @@ assign_parm_setup_block (struct assign_parm_data_all *all, else if (size == 0) ; + /* MEM may be a REG if coalescing assigns the param's partition + to a pseudo. */ + else if (REG_P (mem)) + emit_move_insn (mem, entry_parm); + /* If SIZE is that of a mode no bigger than a word, just use that mode's store operation. */ else if (size <= UNITS_PER_WORD) @@ -3121,7 +3162,7 @@ assign_parm_setup_reg (struct assign_parm_data_all *all, tree parm, if (GET_MODE (parmreg) != promoted_nominal_mode) parmreg = gen_lowpart (promoted_nominal_mode, parmreg); } - else if (!from_expand || parm_maybe_byref_p (parm)) + else if (!from_expand || parm_in_unassigned_mem_p (parm, from_expand)) { parmreg = gen_reg_rtx (promoted_nominal_mode); if (!DECL_ARTIFICIAL (parm)) @@ -3131,7 +3172,6 @@ assign_parm_setup_reg (struct assign_parm_data_all *all, tree parm, { gcc_assert (data->passed_pointer); gcc_assert (GET_CODE (from_expand) == MEM - && GET_MODE (from_expand) == BLKmode && XEXP (from_expand, 0) == NULL_RTX); XEXP (from_expand, 0) = parmreg; } @@ -3349,7 +3389,7 @@ assign_parm_setup_reg (struct assign_parm_data_all *all, tree parm, did_conversion = true; } else if (GET_MODE (parmreg) == BLKmode) - gcc_assert (parm_maybe_byref_p (parm)); + gcc_assert (parm_in_stack_slot_p (parm)); else emit_move_insn (parmreg, src); @@ -3455,12 +3495,15 @@ assign_parm_setup_stack (struct assign_parm_data_all *all, tree parm, if (data->entry_parm != data->stack_parm) { rtx src, dest; + rtx from_expand = NULL_RTX; if (data->stack_parm == 0) { - rtx x = data->stack_parm = rtl_for_parm (all, parm); - if (x) - gcc_assert (GET_MODE (x) == GET_MODE (data->entry_parm)); + from_expand = rtl_for_parm (all, parm); + if (from_expand) + gcc_assert (GET_MODE (from_expand) == GET_MODE (data->entry_parm)); + if (from_expand && !parm_in_unassigned_mem_p (parm, from_expand)) + data->stack_parm = from_expand; } if (data->stack_parm == 0) @@ -3472,7 +3515,16 @@ assign_parm_setup_stack (struct assign_parm_data_all *all, tree parm, = assign_stack_local (GET_MODE (data->entry_parm), GET_MODE_SIZE (GET_MODE (data->entry_parm)), align); - set_mem_attributes (data->stack_parm, parm, 1); + if (!from_expand) + set_mem_attributes (data->stack_parm, parm, 1); + else + { + gcc_assert (GET_CODE (data->stack_parm) == MEM); + gcc_assert (parm_in_unassigned_mem_p (parm, from_expand)); + XEXP (from_expand, 0) = XEXP (data->stack_parm, 0); + PUT_MODE (from_expand, GET_MODE (data->stack_parm)); + data->stack_parm = copy_rtx (from_expand); + } } dest = validize_mem (copy_rtx (data->stack_parm)); diff --git a/gcc/gcc-main.c b/gcc/gcc-main.c index 230ba4846cd..a0aaa3c7fc7 100644 --- a/gcc/gcc-main.c +++ b/gcc/gcc-main.c @@ -40,7 +40,8 @@ extern int main (int, char **); int main (int argc, char **argv) { - driver d; + driver d (false, /* can_finalize */ + false); /* debug */ return d.main (argc, argv); } diff --git a/gcc/gcc.c b/gcc/gcc.c index 290ec78d088..757bfc988eb 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -43,6 +43,131 @@ compilation is specified by a string called a "spec". */ #include "params.h" #include "filenames.h" + + +/* Manage the manipulation of env vars. + + We poison "getenv" and "putenv", so that all enviroment-handling is + done through this class. Note that poisoning happens in the + preprocessor at the identifier level, and doesn't distinguish between + env.getenv (); + and + getenv (); + Hence we need to use "get" for the accessor method, not "getenv". */ + +class env_manager +{ + public: + void init (bool can_restore, bool debug); + const char *get (const char *name); + void xput (const char *string); + void restore (); + + private: + bool m_can_restore; + bool m_debug; + struct kv + { + char *m_key; + char *m_value; + }; + vec<kv> m_keys; + +}; + +/* The singleton instance of class env_manager. */ + +static env_manager env; + +/* Initializer for class env_manager. + + We can't do this as a constructor since we have a statically + allocated instance ("env" above). */ + +void +env_manager::init (bool can_restore, bool debug) +{ + m_can_restore = can_restore; + m_debug = debug; +} + +/* Get the value of NAME within the environment. Essentially + a wrapper for ::getenv, but adding logging, and the possibility + of caching results. */ + +const char * +env_manager::get (const char *name) +{ + const char *result = ::getenv (name); + if (m_debug) + fprintf (stderr, "env_manager::getenv (%s) -> %s\n", name, result); + return result; +} + +/* Put the given KEY=VALUE entry STRING into the environment. + If the env_manager was initialized with CAN_RESTORE set, then + also record the old value of KEY within the environment, so that it + can be later restored. */ + +void +env_manager::xput (const char *string) +{ + if (m_debug) + fprintf (stderr, "env_manager::xput (%s)\n", string); + if (verbose_flag) + fnotice (stderr, "%s\n", string); + + if (m_can_restore) + { + char *equals = strchr (const_cast <char *> (string), '='); + gcc_assert (equals); + + struct kv kv; + kv.m_key = xstrndup (string, equals - string); + const char *cur_value = ::getenv (kv.m_key); + if (m_debug) + fprintf (stderr, "saving old value: %s\n",cur_value); + kv.m_value = cur_value ? xstrdup (cur_value) : NULL; + m_keys.safe_push (kv); + } + + ::putenv (CONST_CAST (char *, string)); +} + +/* Undo any xputenv changes made since last restore. + Can only be called if the env_manager was initialized with + CAN_RESTORE enabled. */ + +void +env_manager::restore () +{ + unsigned int i; + struct kv *item; + + gcc_assert (m_can_restore); + + FOR_EACH_VEC_ELT_REVERSE (m_keys, i, item) + { + if (m_debug) + printf ("restoring saved key: %s value: %s\n", item->m_key, item->m_value); + if (item->m_value) + ::setenv (item->m_key, item->m_value, 1); + else + ::unsetenv (item->m_key); + free (item->m_key); + free (item->m_value); + } + + m_keys.truncate (0); +} + +/* Forbid other uses of getenv and putenv. */ +#if (GCC_VERSION >= 3000) +#pragma GCC poison getenv putenv +#endif + + + /* By default there is no special suffix for target executables. */ /* FIXME: when autoconf is fixed, remove the host check - dj */ #if defined(TARGET_EXECUTABLE_SUFFIX) && defined(HOST_EXECUTABLE_SUFFIX) @@ -115,10 +240,11 @@ FILE *report_times_to_file = NULL; and library files can be found in an alternate location. */ #ifdef TARGET_SYSTEM_ROOT -static const char *target_system_root = TARGET_SYSTEM_ROOT; +#define DEFAULT_TARGET_SYSTEM_ROOT (TARGET_SYSTEM_ROOT) #else -static const char *target_system_root = 0; +#define DEFAULT_TARGET_SYSTEM_ROOT (0) #endif +static const char *target_system_root = DEFAULT_TARGET_SYSTEM_ROOT; /* Nonzero means pass the updated target_system_root to the compiler. */ @@ -235,7 +361,6 @@ static const char *validate_switches (const char *, bool); static void validate_all_switches (void); static inline void validate_switches_from_spec (const char *, bool); static void give_switch (int, int); -static int used_arg (const char *, int); static int default_arg (const char *, int); static void set_multilib_dir (void); static void print_multilib_info (void); @@ -1395,10 +1520,12 @@ struct spec_list int name_len; /* length of the name */ bool user_p; /* whether string come from file spec. */ bool alloc_p; /* whether string was allocated */ + const char *default_ptr; /* The default value of *ptr_spec. */ }; #define INIT_STATIC_SPEC(NAME,PTR) \ - { NAME, NULL, PTR, (struct spec_list *) 0, sizeof (NAME) - 1, false, false } + { NAME, NULL, PTR, (struct spec_list *) 0, sizeof (NAME) - 1, false, false, \ + *PTR } /* List of statically defined specs. */ static struct spec_list static_specs[] = @@ -1566,6 +1693,8 @@ init_spec (void) sl->next = next; sl->name_len = strlen (sl->name); sl->ptr_spec = &sl->ptr; + gcc_assert (sl->ptr_spec != NULL); + sl->default_ptr = sl->ptr; next = sl; } #endif @@ -1740,6 +1869,7 @@ set_spec (const char *name, const char *spec, bool user_p) sl->alloc_p = 0; *(sl->ptr_spec) = ""; sl->next = specs; + sl->default_ptr = NULL; specs = sl; } @@ -2132,7 +2262,10 @@ read_specs (const char *filename, bool main_p, bool user_p) if (! strcmp (suffix, "*link_command")) link_command_spec = spec; else - set_spec (suffix + 1, spec, user_p); + { + set_spec (suffix + 1, spec, user_p); + free (spec); + } } else { @@ -2152,6 +2285,8 @@ read_specs (const char *filename, bool main_p, bool user_p) if (link_command_spec == 0) fatal_error (input_location, "spec file has no spec for linking"); + + XDELETEVEC (buffer); } /* Record the names of temporary files we tell compilers to write, @@ -2494,9 +2629,7 @@ add_to_obstack (char *path, void *data) static void xputenv (const char *string) { - if (verbose_flag) - fnotice (stderr, "%s\n", string); - putenv (CONST_CAST (char *, string)); + env.xput (string); } /* Build a list of search directories from PATHS. @@ -3068,10 +3201,15 @@ execute (void) SWITCH_LIVE to indicate this switch is true in a conditional spec. SWITCH_FALSE to indicate this switch is overridden by a later switch. SWITCH_IGNORE to indicate this switch should be ignored (used in %<S). - SWITCH_IGNORE_PERMANENTLY to indicate this switch should be ignored + SWITCH_IGNORE_PERMANENTLY to indicate this switch should be ignored. + SWITCH_KEEP_FOR_GCC to indicate that this switch, otherwise ignored, + should be included in COLLECT_GCC_OPTIONS. in all do_spec calls afterwards. Used for %<S from self specs. - The `validated' field is nonzero if any spec has looked at this switch; - if it remains zero at the end of the run, it must be meaningless. */ + The `known' field describes whether this is an internal switch. + The `validated' field describes whether any spec has looked at this switch; + if it remains false at the end of the run, the switch must be meaningless. + The `ordering' field is used to temporarily mark switches that have to be + kept in a specific order. */ #define SWITCH_LIVE (1 << 0) #define SWITCH_FALSE (1 << 1) @@ -3965,7 +4103,7 @@ process_command (unsigned int decoded_options_count, struct cl_option_handlers handlers; unsigned int j; - gcc_exec_prefix = getenv ("GCC_EXEC_PREFIX"); + gcc_exec_prefix = env.get ("GCC_EXEC_PREFIX"); n_switches = 0; n_infiles = 0; @@ -4070,7 +4208,7 @@ process_command (unsigned int decoded_options_count, /* COMPILER_PATH and LIBRARY_PATH have values that are lists of directory names with colons. */ - temp = getenv ("COMPILER_PATH"); + temp = env.get ("COMPILER_PATH"); if (temp) { const char *startp, *endp; @@ -4104,7 +4242,7 @@ process_command (unsigned int decoded_options_count, } } - temp = getenv (LIBRARY_PATH_ENV); + temp = env.get (LIBRARY_PATH_ENV); if (temp && *cross_compile == '0') { const char *startp, *endp; @@ -4137,7 +4275,7 @@ process_command (unsigned int decoded_options_count, } /* Use LPATH like LIBRARY_PATH (for the CMU build program). */ - temp = getenv ("LPATH"); + temp = env.get ("LPATH"); if (temp && *cross_compile == '0') { const char *startp, *endp; @@ -4280,7 +4418,7 @@ process_command (unsigned int decoded_options_count, if (!compare_debug) { - const char *gcd = getenv ("GCC_COMPARE_DEBUG"); + const char *gcd = env.get ("GCC_COMPARE_DEBUG"); if (gcd && gcd[0] == '-') { @@ -6212,7 +6350,10 @@ process_brace_body (const char *p, const char *atom, const char *end_atom, if (!have_subst) { if (do_spec_1 (string, 0, NULL) < 0) - return 0; + { + free (string); + return 0; + } } else { @@ -6228,12 +6369,16 @@ process_brace_body (const char *p, const char *atom, const char *end_atom, { if (do_spec_1 (string, 0, &switches[i].part1[hard_match_len]) < 0) - return 0; + { + free (string); + return 0; + } /* Pass any arguments this switch has. */ give_switch (i, 1); suffix_subst = NULL; } } + free (string); } return p; @@ -6942,6 +7087,19 @@ compare_files (char *cmpfile[]) return ret; } +driver::driver (bool can_finalize, bool debug) : + explicit_link_files (NULL), + decoded_options (NULL) +{ + env.init (can_finalize, debug); +} + +driver::~driver () +{ + XDELETEVEC (explicit_link_files); + XDELETEVEC (decoded_options); +} + /* driver::main is implemented as a series of driver:: method calls. */ int @@ -8155,9 +8313,13 @@ static int n_mdswitches; /* Check whether a particular argument was used. The first time we canonicalize the switches to keep only the ones we care about. */ -static int -used_arg (const char *p, int len) +class used_arg_t { + public: + int operator () (const char *p, int len); + void finalize (); + + private: struct mswitchstr { const char *str; @@ -8166,8 +8328,16 @@ used_arg (const char *p, int len) int rep_len; }; - static struct mswitchstr *mswitches; - static int n_mswitches; + mswitchstr *mswitches; + int n_mswitches; + +}; + +used_arg_t used_arg; + +int +used_arg_t::operator () (const char *p, int len) +{ int i, j; if (!mswitches) @@ -8296,6 +8466,14 @@ used_arg (const char *p, int len) return 0; } +void used_arg_t::finalize () +{ + XDELETEVEC (mswitches); + mswitches = NULL; + n_mswitches = 0; +} + + static int default_arg (const char *p, int len) { @@ -8850,7 +9028,7 @@ print_multilib_info (void) static const char * getenv_spec_function (int argc, const char **argv) { - char *value; + const char *value; char *result; char *ptr; size_t len; @@ -8858,7 +9036,7 @@ getenv_spec_function (int argc, const char **argv) if (argc != 2) return NULL; - value = getenv (argv[0]); + value = env.get (argv[0]); if (!value) fatal_error (input_location, "environment variable %qs not defined", argv[0]); @@ -9521,6 +9699,193 @@ convert_white_space (char *orig) return orig; } +static void +path_prefix_reset (path_prefix *prefix) +{ + struct prefix_list *iter, *next; + iter = prefix->plist; + while (iter) + { + next = iter->next; + free (const_cast <char *> (iter->prefix)); + XDELETE (iter); + iter = next; + } + prefix->plist = 0; + prefix->max_len = 0; +} + +/* Restore all state within gcc.c to the initial state, so that the driver + code can be safely re-run in-process. + + Many const char * variables are referenced by static specs (see + INIT_STATIC_SPEC above). These variables are restored to their default + values by a simple loop over the static specs. + + For other variables, we directly restore them all to their initial + values (often implicitly 0). + + Free the various obstacks in this file, along with "opts_obstack" + from opts.c. + + This function also restores any environment variables that were changed. */ + +void +driver::finalize () +{ + env.restore (); + params_c_finalize (); + diagnostic_finish (global_dc); + + is_cpp_driver = 0; + at_file_supplied = 0; + print_help_list = 0; + print_version = 0; + verbose_only_flag = 0; + print_subprocess_help = 0; + use_ld = NULL; + report_times_to_file = NULL; + target_system_root = DEFAULT_TARGET_SYSTEM_ROOT; + target_system_root_changed = 0; + target_sysroot_suffix = 0; + target_sysroot_hdrs_suffix = 0; + save_temps_flag = SAVE_TEMPS_NONE; + save_temps_prefix = 0; + save_temps_length = 0; + spec_machine = DEFAULT_TARGET_MACHINE; + greatest_status = 1; + + finalize_options_struct (&global_options); + finalize_options_struct (&global_options_set); + + obstack_free (&obstack, NULL); + obstack_free (&opts_obstack, NULL); /* in opts.c */ + obstack_free (&collect_obstack, NULL); + + link_command_spec = LINK_COMMAND_SPEC; + + obstack_free (&multilib_obstack, NULL); + + user_specs_head = NULL; + user_specs_tail = NULL; + + /* Within the "compilers" vec, the fields "suffix" and "spec" were + statically allocated for the default compilers, but dynamically + allocated for additional compilers. Delete them for the latter. */ + for (int i = n_default_compilers; i < n_compilers; i++) + { + free (const_cast <char *> (compilers[i].suffix)); + free (const_cast <char *> (compilers[i].spec)); + } + XDELETEVEC (compilers); + compilers = NULL; + n_compilers = 0; + + linker_options.truncate (0); + assembler_options.truncate (0); + preprocessor_options.truncate (0); + + path_prefix_reset (&exec_prefixes); + path_prefix_reset (&startfile_prefixes); + path_prefix_reset (&include_prefixes); + + machine_suffix = 0; + just_machine_suffix = 0; + gcc_exec_prefix = 0; + gcc_libexec_prefix = 0; + md_exec_prefix = MD_EXEC_PREFIX; + md_startfile_prefix = MD_STARTFILE_PREFIX; + md_startfile_prefix_1 = MD_STARTFILE_PREFIX_1; + multilib_dir = 0; + multilib_os_dir = 0; + multiarch_dir = 0; + + XDELETEVEC (specs); + specs = 0; + for (unsigned i = 0; i < ARRAY_SIZE (static_specs); i++) + { + spec_list *sl = &static_specs[i]; + if (sl->alloc_p) + { + if (0) + free (const_cast <char *> (*(sl->ptr_spec))); + sl->alloc_p = false; + } + *(sl->ptr_spec) = sl->default_ptr; + } +#ifdef EXTRA_SPECS + extra_specs = NULL; +#endif + + processing_spec_function = 0; + + argbuf.truncate (0); + + have_c = 0; + have_o = 0; + + temp_names = NULL; + execution_count = 0; + signal_count = 0; + + temp_filename = NULL; + temp_filename_length = 0; + always_delete_queue = NULL; + failure_delete_queue = NULL; + + XDELETEVEC (switches); + switches = NULL; + n_switches = 0; + n_switches_alloc = 0; + + compare_debug = 0; + compare_debug_second = 0; + compare_debug_opt = NULL; + for (int i = 0; i < 2; i++) + { + switches_debug_check[i] = NULL; + n_switches_debug_check[i] = 0; + n_switches_alloc_debug_check[i] = 0; + debug_check_temp_file[i] = NULL; + } + + XDELETEVEC (infiles); + infiles = NULL; + n_infiles = 0; + n_infiles_alloc = 0; + + combine_inputs = false; + added_libraries = 0; + XDELETEVEC (outfiles); + outfiles = NULL; + spec_lang = 0; + last_language_n_infiles = 0; + gcc_input_filename = NULL; + input_file_number = 0; + input_filename_length = 0; + basename_length = 0; + suffixed_basename_length = 0; + input_basename = NULL; + input_suffix = NULL; + /* We don't need to purge "input_stat", just to unset "input_stat_set". */ + input_stat_set = 0; + input_file_compiler = NULL; + arg_going = 0; + delete_this_arg = 0; + this_is_output_file = 0; + this_is_library_file = 0; + this_is_linker_script = 0; + input_from_pipe = 0; + suffix_subst = NULL; + + mdswitches = NULL; + n_mdswitches = 0; + + debug_auxbase_opt = NULL; + + used_arg.finalize (); +} + /* PR jit/64810. Targets can provide configure-time default options in OPTION_DEFAULT_SPECS. The jit needs to access these, but diff --git a/gcc/gcc.h b/gcc/gcc.h index f10a103cd5b..e1abe43b15f 100644 --- a/gcc/gcc.h +++ b/gcc/gcc.h @@ -30,7 +30,10 @@ along with GCC; see the file COPYING3. If not see class driver { public: + driver (bool can_finalize, bool debug); + ~driver (); int main (int argc, char **argv); + void finalize (); private: void set_progname (const char *argv0) const; diff --git a/gcc/gencodes.c b/gcc/gencodes.c index c7478912e9b..d4560b4abf4 100644 --- a/gcc/gencodes.c +++ b/gcc/gencodes.c @@ -40,9 +40,9 @@ gen_insn (md_rtx_info *info) if (name[0] != 0 && name[0] != '*') { if (truth == 0) - printf ("#define CODE_FOR_%s CODE_FOR_nothing\n", name); + printf (",\n CODE_FOR_%s = CODE_FOR_nothing", name); else - printf (" CODE_FOR_%s = %d,\n", name, info->index); + printf (",\n CODE_FOR_%s = %d", name, info->index); } } @@ -58,7 +58,7 @@ main (int argc, char **argv) if (!init_rtx_reader_args (argc, argv)) return (FATAL_EXIT_CODE); - puts ("\ + printf ("\ /* Generated automatically by the program `gencodes'\n\ from the machine description file `md'. */\n\ \n\ @@ -66,7 +66,7 @@ main (int argc, char **argv) #define GCC_INSN_CODES_H\n\ \n\ enum insn_code {\n\ - CODE_FOR_nothing = 0,\n"); + CODE_FOR_nothing = 0"); /* Read the machine description. */ @@ -83,10 +83,10 @@ enum insn_code {\n\ break; } - printf (" LAST_INSN_CODE = %d\n\ -};\n\ + printf ("\n};\n\ \n\ -#endif /* GCC_INSN_CODES_H */\n", get_num_insn_codes () - 1); +const unsigned int NUM_INSN_CODES = %d;\n\ +#endif /* GCC_INSN_CODES_H */\n", get_num_insn_codes ()); if (ferror (stdout) || fflush (stdout) || fclose (stdout)) return FATAL_EXIT_CODE; diff --git a/gcc/genconfig.c b/gcc/genconfig.c index ac16c5ba8b2..fc3c1eb6fd9 100644 --- a/gcc/genconfig.c +++ b/gcc/genconfig.c @@ -348,6 +348,8 @@ main (int argc, char **argv) if (have_cond_exec_flag) printf ("#define HAVE_conditional_execution 1\n"); + else + printf ("#define HAVE_conditional_execution 0\n"); if (have_lo_sum_flag) printf ("#define HAVE_lo_sum 1\n"); @@ -370,6 +372,11 @@ main (int argc, char **argv) printf ("#define HAVE_peephole2 1\n"); printf ("#define MAX_INSNS_PER_PEEP2 %d\n", max_insns_per_peep2); } + else + { + printf ("#define HAVE_peephole2 0\n"); + printf ("#define MAX_INSNS_PER_PEEP2 0\n"); + } puts ("\n#endif /* GCC_INSN_CONFIG_H */"); diff --git a/gcc/genflags.c b/gcc/genflags.c index e67a48ba83f..0dedc8dc2aa 100644 --- a/gcc/genflags.c +++ b/gcc/genflags.c @@ -42,7 +42,6 @@ static int max_opno; static void max_operand_1 (rtx); static int num_operands (rtx); static void gen_proto (rtx); -static void gen_macro (const char *, int, int); /* Count the number of match_operand's found. */ @@ -92,32 +91,6 @@ num_operands (rtx insn) return max_opno + 1; } -/* Print out a wrapper macro for a function which corrects the number - of arguments it takes. Any missing arguments are assumed to be at - the end. */ -static void -gen_macro (const char *name, int real, int expect) -{ - int i; - - gcc_assert (real <= expect); - gcc_assert (real); - - /* #define GEN_CALL(A, B, C, D) gen_call((A), (B)) */ - fputs ("#define GEN_", stdout); - for (i = 0; name[i]; i++) - putchar (TOUPPER (name[i])); - - putchar ('('); - for (i = 0; i < expect - 1; i++) - printf ("%c, ", i + 'A'); - printf ("%c) gen_%s (", i + 'A', name); - - for (i = 0; i < real - 1; i++) - printf ("(%c), ", i + 'A'); - printf ("(%c))\n", i + 'A'); -} - /* Print out prototype information for a generator function. If the insn pattern has been elided, print out a dummy generator that does nothing. */ @@ -130,25 +103,6 @@ gen_proto (rtx insn) const char *name = XSTR (insn, 0); int truth = maybe_eval_c_test (XSTR (insn, 2)); - /* Many md files don't refer to the last two operands passed to the - call patterns. This means their generator functions will be two - arguments too short. Instead of changing every md file to touch - those operands, we wrap the prototypes in macros that take the - correct number of arguments. */ - if (name[0] == 'c' || name[0] == 's') - { - if (!strcmp (name, "call") - || !strcmp (name, "call_pop") - || !strcmp (name, "sibcall") - || !strcmp (name, "sibcall_pop")) - gen_macro (name, num, 4); - else if (!strcmp (name, "call_value") - || !strcmp (name, "call_value_pop") - || !strcmp (name, "sibcall_value") - || !strcmp (name, "sibcall_value_pop")) - gen_macro (name, num, 5); - } - if (truth != 0) printf ("extern rtx gen_%-*s (", max_id_len, name); else diff --git a/gcc/genmatch.c b/gcc/genmatch.c index f48e79d0b95..72666373740 100644 --- a/gcc/genmatch.c +++ b/gcc/genmatch.c @@ -2177,11 +2177,19 @@ expr::gen_transform (FILE *f, int indent, const char *dest, bool gimple, fprintf_indent (f, indent, "res = fold_build%d_loc (loc, %s, %s", ops.length(), opr_name, type); else - fprintf_indent (f, indent, "res = build_call_expr_loc (loc, " - "builtin_decl_implicit (%s), %d", opr_name, ops.length()); + { + fprintf_indent (f, indent, "{\n"); + fprintf_indent (f, indent, " tree decl = builtin_decl_implicit (%s);\n", + opr_name); + fprintf_indent (f, indent, " if (!decl) return NULL_TREE;\n"); + fprintf_indent (f, indent, " res = build_call_expr_loc (loc, " + "decl, %d", ops.length()); + } for (unsigned i = 0; i < ops.length (); ++i) fprintf (f, ", ops%d[%u]", depth, i); fprintf (f, ");\n"); + if (opr->kind != id_base::CODE) + fprintf_indent (f, indent, "}\n"); if (*opr == CONVERT_EXPR) { indent -= 2; @@ -2521,12 +2529,15 @@ dt_node::gen_kids (FILE *f, int indent, bool gimple) else gcc_unreachable (); } - else if (kids[i]->type == dt_node::DT_MATCH - || kids[i]->type == dt_node::DT_SIMPLIFY) + else if (kids[i]->type == dt_node::DT_SIMPLIFY) others.safe_push (kids[i]); - else if (kids[i]->type == dt_node::DT_TRUE) + else if (kids[i]->type == dt_node::DT_MATCH + || kids[i]->type == dt_node::DT_TRUE) { /* A DT_TRUE operand serves as a barrier - generate code now + for what we have collected sofar. + Like DT_TRUE, DT_MATCH serves as a barrier as it can cause + dependent matches to get out-of-order. Generate code now for what we have collected sofar. */ gen_kids_1 (f, indent, gimple, gimple_exprs, generic_exprs, fns, generic_fns, preds, others); @@ -3069,13 +3080,24 @@ dt_simplify::gen_1 (FILE *f, int indent, bool gimple, operand *result) *e->operation == CONVERT_EXPR ? "NOP_EXPR" : e->operation->id); else - fprintf_indent (f, indent, - "res = build_call_expr_loc " - "(loc, builtin_decl_implicit (%s), %d", - e->operation->id, e->ops.length()); + { + fprintf_indent (f, indent, + "{\n"); + fprintf_indent (f, indent, + " tree decl = builtin_decl_implicit (%s);\n", + e->operation->id); + fprintf_indent (f, indent, + " if (!decl) return NULL_TREE;\n"); + fprintf_indent (f, indent, + " res = build_call_expr_loc " + "(loc, decl, %d", + e->ops.length()); + } for (unsigned j = 0; j < e->ops.length (); ++j) fprintf (f, ", res_op%d", j); fprintf (f, ");\n"); + if (!is_a <operator_id *> (opr)) + fprintf_indent (f, indent, "}\n"); } } } diff --git a/gcc/genmodes.c b/gcc/genmodes.c index f4db427ffe3..15d62a0f405 100644 --- a/gcc/genmodes.c +++ b/gcc/genmodes.c @@ -1047,6 +1047,80 @@ mode_inner_inline (machine_mode mode)\n\ }\n"); } +/* Emit mode_unit_size_inline routine into insn-modes.h header. */ +static void +emit_mode_unit_size_inline (void) +{ + int c; + struct mode_data *m; + + puts ("\ +#ifdef __cplusplus\n\ +inline __attribute__((__always_inline__))\n\ +#else\n\ +extern __inline__ __attribute__((__always_inline__, __gnu_inline__))\n\ +#endif\n\ +unsigned char\n\ +mode_unit_size_inline (machine_mode mode)\n\ +{\n\ + extern CONST_MODE_UNIT_SIZE unsigned char mode_unit_size[NUM_MACHINE_MODES];\ +\n\ + switch (mode)\n\ + {"); + + for_all_modes (c, m) + { + const char *name = m->name; + struct mode_data *m2 = m; + if (c != MODE_PARTIAL_INT && m2->component) + m2 = m2->component; + if (!m2->need_bytesize_adj) + printf (" case %smode: return %u;\n", name, m2->bytesize); + } + + puts ("\ + default: return mode_unit_size[mode];\n\ + }\n\ +}\n"); +} + +/* Emit mode_unit_precision_inline routine into insn-modes.h header. */ +static void +emit_mode_unit_precision_inline (void) +{ + int c; + struct mode_data *m; + + puts ("\ +#ifdef __cplusplus\n\ +inline __attribute__((__always_inline__))\n\ +#else\n\ +extern __inline__ __attribute__((__always_inline__, __gnu_inline__))\n\ +#endif\n\ +unsigned short\n\ +mode_unit_precision_inline (machine_mode mode)\n\ +{\n\ + extern const unsigned short mode_unit_precision[NUM_MACHINE_MODES];\n\ + switch (mode)\n\ + {"); + + for_all_modes (c, m) + { + struct mode_data *m2 + = (c != MODE_PARTIAL_INT && m->component) ? m->component : m; + if (m2->precision != (unsigned int)-1) + printf (" case %smode: return %u;\n", m->name, m2->precision); + else + printf (" case %smode: return %u*BITS_PER_UNIT;\n", + m->name, m2->bytesize); + } + + puts ("\ + default: return mode_unit_precision[mode];\n\ + }\n\ +}\n"); +} + static void emit_insn_modes_h (void) { @@ -1107,6 +1181,7 @@ enum machine_mode\n{"); /* I can't think of a better idea, can you? */ printf ("#define CONST_MODE_SIZE%s\n", adj_bytesize ? "" : " const"); + printf ("#define CONST_MODE_UNIT_SIZE%s\n", adj_bytesize ? "" : " const"); printf ("#define CONST_MODE_BASE_ALIGN%s\n", adj_alignment ? "" : " const"); #if 0 /* disabled for backward compatibility, temporary */ printf ("#define CONST_REAL_FORMAT_FOR_MODE%s\n", adj_format ? "" :" const"); @@ -1125,6 +1200,8 @@ enum machine_mode\n{"); emit_mode_size_inline (); emit_mode_nunits_inline (); emit_mode_inner_inline (); + emit_mode_unit_size_inline (); + emit_mode_unit_precision_inline (); puts ("#endif /* GCC_VERSION >= 4001 */"); puts ("\ @@ -1344,6 +1421,47 @@ emit_mode_inner (void) print_closer (); } +/* Emit mode_unit_size array into insn-modes.c file. */ +static void +emit_mode_unit_size (void) +{ + int c; + struct mode_data *m; + + print_maybe_const_decl ("%sunsigned char", "mode_unit_size", + "NUM_MACHINE_MODES", bytesize); + + for_all_modes (c, m) + tagged_printf ("%u", + c != MODE_PARTIAL_INT && m->component + ? m->component->bytesize : m->bytesize, m->name); + + print_closer (); +} + +/* Emit mode_unit_precision array into insn-modes.c file. */ +static void +emit_mode_unit_precision (void) +{ + int c; + struct mode_data *m; + + print_decl ("unsigned short", "mode_unit_precision", "NUM_MACHINE_MODES"); + + for_all_modes (c, m) + { + struct mode_data *m2 = (c != MODE_PARTIAL_INT && m->component) ? + m->component : m; + if (m2->precision != (unsigned int)-1) + tagged_printf ("%u", m2->precision, m->name); + else + tagged_printf ("%u*BITS_PER_UNIT", m2->bytesize, m->name); + } + + print_closer (); +} + + static void emit_mode_base_align (void) { @@ -1439,6 +1557,7 @@ emit_mode_adjustments (void) printf ("\n /* %s:%d */\n s = %s;\n", a->file, a->line, a->adjustment); printf (" mode_size[%smode] = s;\n", a->mode->name); + printf (" mode_unit_size[%smode] = s;\n", a->mode->name); printf (" mode_base_align[%smode] = s & (~s + 1);\n", a->mode->name); @@ -1449,6 +1568,7 @@ emit_mode_adjustments (void) case MODE_COMPLEX_INT: case MODE_COMPLEX_FLOAT: printf (" mode_size[%smode] = 2*s;\n", m->name); + printf (" mode_unit_size[%smode] = s;\n", m->name); printf (" mode_base_align[%smode] = s & (~s + 1);\n", m->name); break; @@ -1461,6 +1581,7 @@ emit_mode_adjustments (void) case MODE_VECTOR_UACCUM: printf (" mode_size[%smode] = %d*s;\n", m->name, m->ncomponents); + printf (" mode_unit_size[%smode] = s;\n", m->name); printf (" mode_base_align[%smode] = (%d*s) & (~(%d*s)+1);\n", m->name, m->ncomponents, m->ncomponents); break; @@ -1626,6 +1747,8 @@ emit_insn_modes_c (void) emit_mode_wider (); emit_mode_mask (); emit_mode_inner (); + emit_mode_unit_size (); + emit_mode_unit_precision (); emit_mode_base_align (); emit_class_narrowest_mode (); emit_real_format_for_mode (); diff --git a/gcc/gensupport.c b/gcc/gensupport.c index 9e00f13a2f9..0480e17fac3 100644 --- a/gcc/gensupport.c +++ b/gcc/gensupport.c @@ -93,6 +93,9 @@ static struct queue_elem **other_tail = &other_queue; static struct queue_elem *define_subst_attr_queue; static struct queue_elem **define_subst_attr_tail = &define_subst_attr_queue; +/* Mapping from DEFINE_* rtxes to their location in the source file. */ +static hash_map <rtx, file_location> *rtx_locs; + static void remove_constraints (rtx); static int is_predicable (struct queue_elem *); @@ -2619,9 +2622,24 @@ read_md_rtx (md_rtx_info *info) else info->index = -1; + if (!rtx_locs) + rtx_locs = new hash_map <rtx, file_location>; + rtx_locs->put (info->def, info->loc); + return true; } +/* Return the file location of DEFINE_* rtx X, which was previously + returned by read_md_rtx. */ +file_location +get_file_location (rtx x) +{ + gcc_assert (rtx_locs); + file_location *entry = rtx_locs->get (x); + gcc_assert (entry); + return *entry; +} + /* Return the number of possible INSN_CODEs. Only meaningful once the whole file has been processed. */ unsigned int diff --git a/gcc/gensupport.h b/gcc/gensupport.h index a15c36a1016..0199e398034 100644 --- a/gcc/gensupport.h +++ b/gcc/gensupport.h @@ -132,6 +132,7 @@ struct pattern_stats extern void get_pattern_stats (struct pattern_stats *ranges, rtvec vec); extern void compute_test_codes (rtx, file_location, char *); +extern file_location get_file_location (rtx); extern const char *get_emit_function (rtx); extern bool needs_barrier_p (rtx); diff --git a/gcc/gentarget-def.c b/gcc/gentarget-def.c index e5e291ecfd7..9c8a2503ee2 100644 --- a/gcc/gentarget-def.c +++ b/gcc/gentarget-def.c @@ -60,6 +60,43 @@ static hash_table <nofree_string_hash> *stubs; from the C condition to the function name. */ static hash_map <nofree_string_hash, const char *> *have_funcs; +/* Return true if the part of the prototype at P is for an argument + name. If so, point *END_OUT to the first character after the name. + If OPNO_OUT is nonnull, set *OPNO_OUT to the number of the associated + operand. If REQUIRED_OUT is nonnull, set *REQUIRED_OUT to whether the + .md pattern is required to match the operand. */ + +static bool +parse_argument (const char *p, const char **end_out, + unsigned int *opno_out = 0, + bool *required_out = 0) +{ + while (ISSPACE (*p)) + p++; + if (p[0] == 'x' && ISDIGIT (p[1])) + { + p += 1; + if (required_out) + *required_out = true; + } + else if (p[0] == 'o' && p[1] == 'p' && p[2] == 't' && ISDIGIT (p[3])) + { + p += 3; + if (required_out) + *required_out = false; + } + else + return false; + + char *endptr; + unsigned int opno = strtol (p, &endptr, 10); + if (opno_out) + *opno_out = opno; + *end_out = endptr; + return true; +} + + /* Output hook definitions for pattern NAME, which has target-insns.def prototype PROTOTYPE. */ @@ -78,21 +115,27 @@ def_target_insn (const char *name, const char *prototype) char *suffix = XALLOCAVEC (char, strlen (prototype) + 1); i = 0; unsigned int opno = 0; + unsigned int required_ops = 0; + unsigned int this_opno; + bool required_p; for (const char *p = prototype; *p; ++p) - if (*p == 'x' && ISDIGIT (p[1])) + if (parse_argument (p, &p, &this_opno, &required_p)) { - /* This should be a parameter name of the form "x<OPNO>". - That doesn't contribute to the suffix, so skip ahead and - process the following character. */ - char *endptr; - if ((unsigned int) strtol (p + 1, &endptr, 10) != opno - || (*endptr != ',' && *endptr != ')')) + if (this_opno != opno || (*p != ',' && *p != ')')) { error ("invalid prototype for '%s'", name); exit (FATAL_EXIT_CODE); } + if (required_p && required_ops < opno) + { + error ("prototype for '%s' has required operands after" + " optional operands", name); + exit (FATAL_EXIT_CODE); + } opno += 1; - p = endptr; + if (required_p) + required_ops = opno; + /* Skip over ')'s. */ if (*p == ',') suffix[i++] = '_'; } @@ -117,6 +160,22 @@ def_target_insn (const char *name, const char *prototype) const char *have_name = name; if (rtx insn = insns->find_with_hash (name, hash)) { + pattern_stats stats; + get_pattern_stats (&stats, XVEC (insn, 1)); + unsigned int actual_ops = stats.num_generator_args; + if (opno == required_ops && opno != actual_ops) + error_at (get_file_location (insn), + "'%s' must have %d operands (excluding match_dups)", + name, required_ops); + else if (actual_ops < required_ops) + error_at (get_file_location (insn), + "'%s' must have at least %d operands (excluding match_dups)", + name, required_ops); + else if (actual_ops > opno) + error_at (get_file_location (insn), + "'%s' must have no more than %d operands" + " (excluding match_dups)", name, opno); + const char *test = XSTR (insn, 2); truth = maybe_eval_c_test (test); gcc_assert (truth != 0); @@ -139,13 +198,23 @@ def_target_insn (const char *name, const char *prototype) have_name = entry; } printf ("\nstatic rtx_insn *\n"); - printf ("target_gen_%s %s\n", name, prototype); - printf ("{\n"); + printf ("target_gen_%s ", name); + /* Print the prototype with the argument names after ACTUAL_OPS + removed. */ + const char *p = prototype, *end; + while (*p) + if (parse_argument (p, &end, &this_opno) && this_opno >= actual_ops) + p = end; + else + fputc (*p++, stdout); + + printf ("\n{\n"); if (truth < 0) printf (" gcc_checking_assert (targetm.have_%s ());\n", name); printf (" return insnify (gen_%s (", name); - for (i = 0; i < opno; ++i) - printf ("%sx%d", i == 0 ? "" : ", ", i); + for (i = 0; i < actual_ops; ++i) + printf ("%s%s%d", i == 0 ? "" : ", ", + i < required_ops ? "x" : "opt", i); printf ("));\n"); printf ("}\n"); } @@ -157,18 +226,11 @@ def_target_insn (const char *name, const char *prototype) *slot = xstrdup (suffix); printf ("\nstatic rtx_insn *\n"); printf ("invalid_%s ", suffix); + /* Print the prototype with the argument names removed. */ const char *p = prototype; while (*p) - { - if (p[0] == 'x' && ISDIGIT (p[1])) - { - char *endptr; - strtol (p + 1, &endptr, 10); - p = endptr; - } - else - fputc (*p++, stdout); - } + if (!parse_argument (p, &p)) + fputc (*p++, stdout); printf ("\n{\n"); printf (" gcc_unreachable ();\n"); printf ("}\n"); diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index de64c053f3a..c79f9b3f436 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -3308,6 +3308,7 @@ replace_stmt_with_simplification (gimple_stmt_iterator *gsi, } if (i < 3) gcc_assert (ops[i] == NULL_TREE); + gcc_assert (gimple_seq_empty_p (*seq)); return true; } else if (!inplace) diff --git a/gcc/gimple-match-head.c b/gcc/gimple-match-head.c index 17bd9926144..90f2486e15c 100644 --- a/gcc/gimple-match-head.c +++ b/gcc/gimple-match-head.c @@ -338,6 +338,9 @@ maybe_push_res_to_seq (code_helper rcode, tree type, tree *ops, tree decl = builtin_decl_implicit (rcode); if (!decl) return NULL_TREE; + /* We can't and should not emit calls to non-const functions. */ + if (!(flags_from_decl_or_type (decl) & ECF_CONST)) + return NULL_TREE; /* Play safe and do not allow abnormals to be mentioned in newly created statements. */ unsigned nargs; diff --git a/gcc/gimple-ssa-isolate-paths.c b/gcc/gimple-ssa-isolate-paths.c index 6f84f85856b..ca2322d1346 100644 --- a/gcc/gimple-ssa-isolate-paths.c +++ b/gcc/gimple-ssa-isolate-paths.c @@ -66,10 +66,10 @@ check_loadstore (gimple stmt, tree op, tree, void *data) return false; } -/* Insert a trap after SI and remove SI and all statements after the trap. */ +/* Insert a trap after SI and split the block after the trap. */ static void -insert_trap_and_remove_trailing_statements (gimple_stmt_iterator *si_p, tree op) +insert_trap (gimple_stmt_iterator *si_p, tree op) { /* We want the NULL pointer dereference to actually occur so that code that wishes to catch the signal can do so. @@ -115,18 +115,8 @@ insert_trap_and_remove_trailing_statements (gimple_stmt_iterator *si_p, tree op) else gsi_insert_before (si_p, seq, GSI_NEW_STMT); - /* We must remove statements from the end of the block so that we - never reference a released SSA_NAME. */ - basic_block bb = gimple_bb (gsi_stmt (*si_p)); - for (gimple_stmt_iterator si = gsi_last_bb (bb); - gsi_stmt (si) != gsi_stmt (*si_p); - si = gsi_last_bb (bb)) - { - stmt = gsi_stmt (si); - unlink_stmt_vdef (stmt); - gsi_remove (&si, true); - release_defs (stmt); - } + split_block (gimple_bb (new_stmt), new_stmt); + *si_p = gsi_for_stmt (stmt); } /* BB when reached via incoming edge E will exhibit undefined behaviour @@ -215,7 +205,7 @@ isolate_path (basic_block bb, basic_block duplicate, update_stmt (ret); } else - insert_trap_and_remove_trailing_statements (&si2, op); + insert_trap (&si2, op); } return duplicate; @@ -422,14 +412,8 @@ find_explicit_erroneous_behaviour (void) continue; } - insert_trap_and_remove_trailing_statements (&si, - null_pointer_node); - - /* And finally, remove all outgoing edges from BB. */ - edge e; - for (edge_iterator ei = ei_start (bb->succs); - (e = ei_safe_edge (ei)); ) - remove_edge (e); + insert_trap (&si, null_pointer_node); + bb = gimple_bb (gsi_stmt (si)); /* Ignore any more operands on this statement and continue the statement iterator (which should diff --git a/gcc/go/ChangeLog b/gcc/go/ChangeLog index 53ae16ba522..90520ded455 100644 --- a/gcc/go/ChangeLog +++ b/gcc/go/ChangeLog @@ -1,3 +1,11 @@ +2015-08-24 Marek Polacek <polacek@redhat.com> + + PR tree-optimization/67284 + * go-gcc.cc (Gcc_backend::define_builtin): Add NORETURN_P parameter. + Set TREE_THIS_VOLATILE. + (Gcc_backend::Gcc_backend): Mark __builtin_trap as a noreturn call. + Pass false to the rest of define_builtin calls. + 2015-07-31 Andreas Schwab <schwab@linux-m68k.org> * go-lang.c (go_langhook_init_options_struct): Don't set diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc index 6f274fcd8b4..cb4c2e5c73a 100644 --- a/gcc/go/go-gcc.cc +++ b/gcc/go/go-gcc.cc @@ -498,7 +498,7 @@ class Gcc_backend : public Backend private: void define_builtin(built_in_function bcode, const char* name, const char* libname, - tree fntype, bool const_p); + tree fntype, bool const_p, bool noreturn_p); // A mapping of the GCC built-ins exposed to GCCGo. std::map<std::string, Bfunction*> builtin_functions_; @@ -522,25 +522,25 @@ Gcc_backend::Gcc_backend() tree p = build_pointer_type(build_qualified_type(t, TYPE_QUAL_VOLATILE)); this->define_builtin(BUILT_IN_SYNC_ADD_AND_FETCH_1, "__sync_fetch_and_add_1", NULL, build_function_type_list(t, p, t, NULL_TREE), - false); + false, false); t = this->integer_type(BITS_PER_UNIT * 2, 1)->get_tree(); p = build_pointer_type(build_qualified_type(t, TYPE_QUAL_VOLATILE)); this->define_builtin(BUILT_IN_SYNC_ADD_AND_FETCH_2, "__sync_fetch_and_add_2", NULL, build_function_type_list(t, p, t, NULL_TREE), - false); + false, false); t = this->integer_type(BITS_PER_UNIT * 4, 1)->get_tree(); p = build_pointer_type(build_qualified_type(t, TYPE_QUAL_VOLATILE)); this->define_builtin(BUILT_IN_SYNC_ADD_AND_FETCH_4, "__sync_fetch_and_add_4", NULL, build_function_type_list(t, p, t, NULL_TREE), - false); + false, false); t = this->integer_type(BITS_PER_UNIT * 8, 1)->get_tree(); p = build_pointer_type(build_qualified_type(t, TYPE_QUAL_VOLATILE)); this->define_builtin(BUILT_IN_SYNC_ADD_AND_FETCH_8, "__sync_fetch_and_add_8", NULL, build_function_type_list(t, p, t, NULL_TREE), - false); + false, false); // We use __builtin_expect for magic import functions. this->define_builtin(BUILT_IN_EXPECT, "__builtin_expect", NULL, @@ -548,7 +548,7 @@ Gcc_backend::Gcc_backend() long_integer_type_node, long_integer_type_node, NULL_TREE), - true); + true, false); // We use __builtin_memcmp for struct comparisons. this->define_builtin(BUILT_IN_MEMCMP, "__builtin_memcmp", "memcmp", @@ -557,7 +557,7 @@ Gcc_backend::Gcc_backend() const_ptr_type_node, size_type_node, NULL_TREE), - false); + false, false); // We provide some functions for the math library. tree math_function_type = build_function_type_list(double_type_node, @@ -574,93 +574,93 @@ Gcc_backend::Gcc_backend() build_function_type_list(long_double_type_node, long_double_type_node, long_double_type_node, NULL_TREE); this->define_builtin(BUILT_IN_ACOS, "__builtin_acos", "acos", - math_function_type, true); + math_function_type, true, false); this->define_builtin(BUILT_IN_ACOSL, "__builtin_acosl", "acosl", - math_function_type_long, true); + math_function_type_long, true, false); this->define_builtin(BUILT_IN_ASIN, "__builtin_asin", "asin", - math_function_type, true); + math_function_type, true, false); this->define_builtin(BUILT_IN_ASINL, "__builtin_asinl", "asinl", - math_function_type_long, true); + math_function_type_long, true, false); this->define_builtin(BUILT_IN_ATAN, "__builtin_atan", "atan", - math_function_type, true); + math_function_type, true, false); this->define_builtin(BUILT_IN_ATANL, "__builtin_atanl", "atanl", - math_function_type_long, true); + math_function_type_long, true, false); this->define_builtin(BUILT_IN_ATAN2, "__builtin_atan2", "atan2", - math_function_type_two, true); + math_function_type_two, true, false); this->define_builtin(BUILT_IN_ATAN2L, "__builtin_atan2l", "atan2l", - math_function_type_long_two, true); + math_function_type_long_two, true, false); this->define_builtin(BUILT_IN_CEIL, "__builtin_ceil", "ceil", - math_function_type, true); + math_function_type, true, false); this->define_builtin(BUILT_IN_CEILL, "__builtin_ceill", "ceill", - math_function_type_long, true); + math_function_type_long, true, false); this->define_builtin(BUILT_IN_COS, "__builtin_cos", "cos", - math_function_type, true); + math_function_type, true, false); this->define_builtin(BUILT_IN_COSL, "__builtin_cosl", "cosl", - math_function_type_long, true); + math_function_type_long, true, false); this->define_builtin(BUILT_IN_EXP, "__builtin_exp", "exp", - math_function_type, true); + math_function_type, true, false); this->define_builtin(BUILT_IN_EXPL, "__builtin_expl", "expl", - math_function_type_long, true); + math_function_type_long, true, false); this->define_builtin(BUILT_IN_EXPM1, "__builtin_expm1", "expm1", - math_function_type, true); + math_function_type, true, false); this->define_builtin(BUILT_IN_EXPM1L, "__builtin_expm1l", "expm1l", - math_function_type_long, true); + math_function_type_long, true, false); this->define_builtin(BUILT_IN_FABS, "__builtin_fabs", "fabs", - math_function_type, true); + math_function_type, true, false); this->define_builtin(BUILT_IN_FABSL, "__builtin_fabsl", "fabsl", - math_function_type_long, true); + math_function_type_long, true, false); this->define_builtin(BUILT_IN_FLOOR, "__builtin_floor", "floor", - math_function_type, true); + math_function_type, true, false); this->define_builtin(BUILT_IN_FLOORL, "__builtin_floorl", "floorl", - math_function_type_long, true); + math_function_type_long, true, false); this->define_builtin(BUILT_IN_FMOD, "__builtin_fmod", "fmod", - math_function_type_two, true); + math_function_type_two, true, false); this->define_builtin(BUILT_IN_FMODL, "__builtin_fmodl", "fmodl", - math_function_type_long_two, true); + math_function_type_long_two, true, false); this->define_builtin(BUILT_IN_LDEXP, "__builtin_ldexp", "ldexp", build_function_type_list(double_type_node, double_type_node, integer_type_node, NULL_TREE), - true); + true, false); this->define_builtin(BUILT_IN_LDEXPL, "__builtin_ldexpl", "ldexpl", build_function_type_list(long_double_type_node, long_double_type_node, integer_type_node, NULL_TREE), - true); + true, false); this->define_builtin(BUILT_IN_LOG, "__builtin_log", "log", - math_function_type, true); + math_function_type, true, false); this->define_builtin(BUILT_IN_LOGL, "__builtin_logl", "logl", - math_function_type_long, true); + math_function_type_long, true, false); this->define_builtin(BUILT_IN_LOG1P, "__builtin_log1p", "log1p", - math_function_type, true); + math_function_type, true, false); this->define_builtin(BUILT_IN_LOG1PL, "__builtin_log1pl", "log1pl", - math_function_type_long, true); + math_function_type_long, true, false); this->define_builtin(BUILT_IN_LOG10, "__builtin_log10", "log10", - math_function_type, true); + math_function_type, true, false); this->define_builtin(BUILT_IN_LOG10L, "__builtin_log10l", "log10l", - math_function_type_long, true); + math_function_type_long, true, false); this->define_builtin(BUILT_IN_LOG2, "__builtin_log2", "log2", - math_function_type, true); + math_function_type, true, false); this->define_builtin(BUILT_IN_LOG2L, "__builtin_log2l", "log2l", - math_function_type_long, true); + math_function_type_long, true, false); this->define_builtin(BUILT_IN_SIN, "__builtin_sin", "sin", - math_function_type, true); + math_function_type, true, false); this->define_builtin(BUILT_IN_SINL, "__builtin_sinl", "sinl", - math_function_type_long, true); + math_function_type_long, true, false); this->define_builtin(BUILT_IN_SQRT, "__builtin_sqrt", "sqrt", - math_function_type, true); + math_function_type, true, false); this->define_builtin(BUILT_IN_SQRTL, "__builtin_sqrtl", "sqrtl", - math_function_type_long, true); + math_function_type_long, true, false); this->define_builtin(BUILT_IN_TAN, "__builtin_tan", "tan", - math_function_type, true); + math_function_type, true, false); this->define_builtin(BUILT_IN_TANL, "__builtin_tanl", "tanl", - math_function_type_long, true); + math_function_type_long, true, false); this->define_builtin(BUILT_IN_TRUNC, "__builtin_trunc", "trunc", - math_function_type, true); + math_function_type, true, false); this->define_builtin(BUILT_IN_TRUNCL, "__builtin_truncl", "truncl", - math_function_type_long, true); + math_function_type_long, true, false); // We use __builtin_return_address in the thunk we build for // functions which call recover. @@ -669,13 +669,13 @@ Gcc_backend::Gcc_backend() build_function_type_list(ptr_type_node, unsigned_type_node, NULL_TREE), - false); + false, false); // The compiler uses __builtin_trap for some exception handling // cases. this->define_builtin(BUILT_IN_TRAP, "__builtin_trap", NULL, build_function_type(void_type_node, void_list_node), - false); + false, true); } // Get an unnamed integer type. @@ -3095,15 +3095,19 @@ Gcc_backend::write_global_definitions( // LIBNAME is the name of the corresponding library function, and is // NULL if there isn't one. FNTYPE is the type of the function. // CONST_P is true if the function has the const attribute. +// NORETURN_P is true if the function has the noreturn attribute. void Gcc_backend::define_builtin(built_in_function bcode, const char* name, - const char* libname, tree fntype, bool const_p) + const char* libname, tree fntype, bool const_p, + bool noreturn_p) { tree decl = add_builtin_function(name, fntype, bcode, BUILT_IN_NORMAL, libname, NULL_TREE); if (const_p) TREE_READONLY(decl) = 1; + if (noreturn_p) + TREE_THIS_VOLATILE(decl) = 1; set_builtin_decl(bcode, decl, true); this->builtin_functions_[name] = this->make_function(decl); if (libname != NULL) @@ -3112,6 +3116,8 @@ Gcc_backend::define_builtin(built_in_function bcode, const char* name, NULL, NULL_TREE); if (const_p) TREE_READONLY(decl) = 1; + if (noreturn_p) + TREE_THIS_VOLATILE(decl) = 1; this->builtin_functions_[libname] = this->make_function(decl); } } diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 10f8b043e06..5fcf1bd7961 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -448d30b696461a39870d1b8beb1195e411300bfd +a63e173b20baa1a48470dd31a1fb1f2704b37011 The first line of this file holds the git revision number of the last merge done from the gofrontend repository. diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index 9f757a2aa26..1df9f326561 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -3039,6 +3039,25 @@ Type_conversion_expression::do_lower(Gogo*, Named_object*, } } + // According to the language specification on string conversions + // (http://golang.org/ref/spec#Conversions_to_and_from_a_string_type): + // When converting an integer into a string, the string will be a UTF-8 + // representation of the integer and integers "outside the range of valid + // Unicode code points are converted to '\uFFFD'." + if (type->is_string_type()) + { + Numeric_constant nc; + if (val->numeric_constant_value(&nc) && nc.is_int()) + { + // An integer value doesn't fit in the Unicode code point range if it + // overflows the Go "int" type or is negative. + unsigned long ul; + if (!nc.set_type(Type::lookup_integer_type("int"), false, location) + || nc.to_unsigned_long(&ul) == Numeric_constant::NC_UL_NEGATIVE) + return Expression::make_string("\ufffd", location); + } + } + if (type->is_slice_type()) { Type* element_type = type->array_type()->element_type()->forwarded(); @@ -3943,9 +3962,8 @@ Unary_expression::do_check_types(Gogo*) break; case OPERATOR_XOR: - if (type->integer_type() == NULL - && !type->is_boolean_type()) - this->report_error(_("expected integer or boolean type")); + if (type->integer_type() == NULL) + this->report_error(_("expected integer")); break; case OPERATOR_AND: @@ -6589,7 +6607,11 @@ Builtin_call_expression::Builtin_call_expression(Gogo* gogo, recover_arg_is_set_(false) { Func_expression* fnexp = this->fn()->func_expression(); - go_assert(fnexp != NULL); + if (fnexp == NULL) + { + this->code_ = BUILTIN_INVALID; + return; + } const std::string& name(fnexp->named_object()->name()); if (name == "append") this->code_ = BUILTIN_APPEND; @@ -6662,7 +6684,7 @@ Expression* Builtin_call_expression::do_lower(Gogo* gogo, Named_object* function, Statement_inserter* inserter, int) { - if (this->classification() == EXPRESSION_ERROR) + if (this->is_error_expression()) return this; Location loc = this->location(); @@ -7501,11 +7523,13 @@ Builtin_call_expression::do_discarding_value() Type* Builtin_call_expression::do_type() { + if (this->is_error_expression()) + return Type::make_error_type(); switch (this->code_) { case BUILTIN_INVALID: default: - go_unreachable(); + return Type::make_error_type(); case BUILTIN_NEW: case BUILTIN_MAKE: @@ -8177,6 +8201,12 @@ Builtin_call_expression::do_get_backend(Translate_context* context) location); } + // There aren't any arguments to the print builtin. The compiler + // issues a warning for this so we should avoid getting the backend + // representation for this call. Instead, perform a no-op. + if (print_stmts == NULL) + return context->backend()->boolean_constant_expression(false); + return print_stmts->get_backend(context); } @@ -10335,7 +10365,10 @@ String_index_expression::do_check_types(Gogo*) { ival_valid = true; if (mpz_sgn(ival) < 0 - || (sval_valid && mpz_cmp_ui(ival, sval.length()) >= 0)) + || (sval_valid + && (this->end_ == NULL + ? mpz_cmp_ui(ival, sval.length()) >= 0 + : mpz_cmp_ui(ival, sval.length()) > 0))) { error_at(this->start_->location(), "string index out of bounds"); this->set_is_error(); @@ -15142,7 +15175,11 @@ Numeric_constant::set_type(Type* type, bool issue_error, Location loc) else if (type->complex_type() != NULL) ret = this->check_complex_type(type->complex_type(), issue_error, loc); else - go_unreachable(); + { + ret = false; + if (issue_error) + go_assert(saw_errors()); + } if (ret) this->type_ = type; return ret; diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc index 134e0379461..233ee274cf0 100644 --- a/gcc/go/gofrontend/gogo.cc +++ b/gcc/go/gofrontend/gogo.cc @@ -3156,6 +3156,7 @@ Check_types_traverse::variable(Named_object* named_object) error_at(var->location(), "incompatible type in initialization (%s)", reason.c_str()); + init = Expression::make_error(named_object->location()); var->clear_init(); } else if (init != NULL @@ -3180,13 +3181,13 @@ Check_types_traverse::variable(Named_object* named_object) no->message_name().c_str()); } } - else if (!var->is_used() - && !var->is_global() - && !var->is_parameter() - && !var->is_receiver() - && !var->type()->is_error() - && (init == NULL || !init->is_error_expression()) - && !Lex::is_invalid_identifier(named_object->name())) + if (!var->is_used() + && !var->is_global() + && !var->is_parameter() + && !var->is_receiver() + && !var->type()->is_error() + && (init == NULL || !init->is_error_expression()) + && !Lex::is_invalid_identifier(named_object->name())) error_at(var->location(), "%qs declared and not used", named_object->message_name().c_str()); } @@ -6753,7 +6754,8 @@ Unknown_name::set_real_named_object(Named_object* no) Named_object::Named_object(const std::string& name, const Package* package, Classification classification) - : name_(name), package_(package), classification_(classification) + : name_(name), package_(package), classification_(classification), + is_redefinition_(false) { if (Gogo::is_sink_name(name)) go_assert(classification == NAMED_OBJECT_SINK); @@ -7439,6 +7441,8 @@ Bindings::new_definition(Named_object* old_object, Named_object* new_object) else error_at(new_object->location(), "redefinition of %qs: %s", n.c_str(), reason.c_str()); + old_object->set_is_redefinition(); + new_object->set_is_redefinition(); inform(old_object->location(), "previous definition of %qs was here", n.c_str()); diff --git a/gcc/go/gofrontend/gogo.h b/gcc/go/gofrontend/gogo.h index ece7e0f2e1c..3af2af745fb 100644 --- a/gcc/go/gofrontend/gogo.h +++ b/gcc/go/gofrontend/gogo.h @@ -2389,6 +2389,17 @@ class Named_object void export_named_object(Export*) const; + // Mark this named object as an invalid redefinition of another object. + void + set_is_redefinition() + { this->is_redefinition_ = true; } + + // Return whether or not this object is a invalid redefinition of another + // object. + bool + is_redefinition() const + { return this->is_redefinition_; } + private: Named_object(const std::string&, const Package*, Classification); @@ -2412,6 +2423,8 @@ class Named_object Function_declaration* func_declaration_value; Package* package_value; } u_; + // True if this object is an invalid redefinition of another object. + bool is_redefinition_; }; // A binding contour. This binds names to objects. @@ -2676,6 +2689,8 @@ class Label void define(Location location, Bindings_snapshot* snapshot) { + if (this->is_dummy_label()) + return; go_assert(Linemap::is_unknown_location(this->location_) && this->snapshot_ == NULL); this->location_ = location; @@ -2696,6 +2711,11 @@ class Label static Label* create_dummy_label(); + // Return TRUE if this is a dummy label. + bool + is_dummy_label() const + { return this->name_ == "_"; } + private: // The name of the label. std::string name_; diff --git a/gcc/go/gofrontend/lex.cc b/gcc/go/gofrontend/lex.cc index 8de94c5114b..67f78034266 100644 --- a/gcc/go/gofrontend/lex.cc +++ b/gcc/go/gofrontend/lex.cc @@ -1047,7 +1047,7 @@ Lex::gather_number() pnum = p; while (p < pend) { - if (*p < '0' || *p > '7') + if (*p < '0' || *p > '9') break; ++p; } @@ -1060,7 +1060,13 @@ Lex::gather_number() std::string s(pnum, p - pnum); mpz_t val; int r = mpz_init_set_str(val, s.c_str(), base); - go_assert(r == 0); + if (r != 0) + { + if (base == 8) + error_at(this->location(), "invalid octal literal"); + else + error_at(this->location(), "invalid hex literal"); + } if (neg) mpz_neg(val, val); @@ -1683,6 +1689,16 @@ Lex::skip_cpp_comment() && memcmp(p, "line ", 5) == 0) { p += 5; + + // Before finding FILE:LINENO, make sure line has valid characters. + const char* pcheck = p; + while (pcheck < pend) + { + unsigned int c; + bool issued_error; + pcheck = this->advance_one_utf8_char(pcheck, &c, &issued_error); + } + while (p < pend && *p == ' ') ++p; const char* pcolon = static_cast<const char*>(memchr(p, ':', pend - p)); diff --git a/gcc/go/gofrontend/parse.cc b/gcc/go/gofrontend/parse.cc index 211fd73b3c5..cc4377627e9 100644 --- a/gcc/go/gofrontend/parse.cc +++ b/gcc/go/gofrontend/parse.cc @@ -1741,6 +1741,14 @@ Parse::init_vars_from_call(const Typed_identifier_list* vars, Type* type, first_var = no; else { + // If the current object is a redefinition of another object, we + // might have already recorded the dependency relationship between + // it and the first variable. Either way, an error will be + // reported for the redefinition and we don't need to properly + // record dependency information for an invalid program. + if (no->is_redefinition()) + continue; + // The subsequent vars have an implicit dependency on // the first one, so that everything gets initialized in // the right order and so that we detect cycles @@ -2305,8 +2313,20 @@ Parse::function_decl(bool saw_nointerface) if (!this->peek_token()->is_op(OPERATOR_LCURLY)) { - if (named_object == NULL && !Gogo::is_sink_name(name)) + if (named_object == NULL) { + // Function declarations with the blank identifier as a name are + // mostly ignored since they cannot be called. We make an object + // for this declaration for type-checking purposes. + if (Gogo::is_sink_name(name)) + { + static int count; + char buf[30]; + snprintf(buf, sizeof buf, ".$sinkfndecl%d", count); + ++count; + name = std::string(buf); + } + if (fntype == NULL || (expected_receiver && rec == NULL)) this->gogo_->add_erroneous_name(name); diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc index 72b41cb09a3..5d102bf2e17 100644 --- a/gcc/go/gofrontend/statements.cc +++ b/gcc/go/gofrontend/statements.cc @@ -3080,6 +3080,11 @@ Label_statement::do_traverse(Traverse*) Bstatement* Label_statement::do_get_backend(Translate_context* context) { + if (this->label_->is_dummy_label()) + { + Bexpression* bce = context->backend()->boolean_constant_expression(false); + return context->backend()->expression_statement(bce); + } Blabel* blabel = this->label_->get_backend_label(context); return context->backend()->label_definition_statement(blabel); } diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc index 5418313aea2..8331678578d 100644 --- a/gcc/go/gofrontend/types.cc +++ b/gcc/go/gofrontend/types.cc @@ -5781,6 +5781,8 @@ Array_type::verify_length() bool Array_type::do_verify() { + if (this->element_type()->is_error_type()) + return false; if (!this->verify_length()) this->length_ = Expression::make_error(this->length_->location()); return true; diff --git a/gcc/graphite-blocking.c b/gcc/graphite-blocking.c deleted file mode 100644 index 34342948409..00000000000 --- a/gcc/graphite-blocking.c +++ /dev/null @@ -1,270 +0,0 @@ -/* Heuristics and transform for loop blocking and strip mining on - polyhedral representation. - - Copyright (C) 2009-2015 Free Software Foundation, Inc. - Contributed by Sebastian Pop <sebastian.pop@amd.com> and - Pranav Garg <pranav.garg2107@gmail.com>. - -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" - -#ifdef HAVE_isl -/* Workaround for GMP 5.1.3 bug, see PR56019. */ -#include <stddef.h> - -#include <isl/constraint.h> -#include <isl/set.h> -#include <isl/map.h> -#include <isl/union_map.h> -#include <isl/constraint.h> - -#include "system.h" -#include "coretypes.h" -#include "backend.h" -#include "cfghooks.h" -#include "tree.h" -#include "gimple.h" -#include "params.h" -#include "fold-const.h" -#include "gimple-iterator.h" -#include "tree-ssa-loop.h" -#include "dumpfile.h" -#include "cfgloop.h" -#include "tree-data-ref.h" -#include "graphite-poly.h" - -/* Strip mines with a factor STRIDE the scattering (time) dimension - around PBB at depth TIME_DEPTH. - - The following example comes from the wiki page: - http://gcc.gnu.org/wiki/Graphite/Strip_mine - - The strip mine of a loop with a tile of 64 can be obtained with a - scattering function as follows: - - $ cat ./albert_strip_mine.cloog - # language: C - c - - # parameter {n | n >= 0} - 1 3 - # n 1 - 1 1 0 - 1 - n - - 1 # Number of statements: - - 1 - # {i | 0 <= i <= n} - 2 4 - # i n 1 - 1 1 0 0 - 1 -1 1 0 - - 0 0 0 - 1 - i - - 1 # Scattering functions - - 3 6 - # NEW OLD i n 1 - 1 -64 0 1 0 0 - 1 64 0 -1 0 63 - 0 0 1 -1 0 0 - - 1 - NEW OLD - - #the output of CLooG is like this: - #$ cloog ./albert_strip_mine.cloog - # for (NEW=0;NEW<=floord(n,64);NEW++) { - # for (OLD=max(64*NEW,0);OLD<=min(64*NEW+63,n);OLD++) { - # S1(i = OLD) ; - # } - # } -*/ - -static void -pbb_strip_mine_time_depth (poly_bb_p pbb, int time_depth, int stride) -{ - isl_space *d; - isl_constraint *c; - int iter, strip; - /* STRIP is the dimension that iterates with stride STRIDE. */ - /* ITER is the dimension that enumerates single iterations inside - one strip that has at most STRIDE iterations. */ - strip = time_depth; - iter = strip + 2; - - pbb->transformed = isl_map_insert_dims (pbb->transformed, isl_dim_out, - strip, 2); - - /* Lower bound of the striped loop. */ - d = isl_map_get_space (pbb->transformed); - c = isl_inequality_alloc (isl_local_space_from_space (d)); - c = isl_constraint_set_coefficient_si (c, isl_dim_out, strip, -stride); - c = isl_constraint_set_coefficient_si (c, isl_dim_out, iter, 1); - pbb->transformed = isl_map_add_constraint (pbb->transformed, c); - - /* Upper bound of the striped loop. */ - d = isl_map_get_space (pbb->transformed); - c = isl_inequality_alloc (isl_local_space_from_space (d)); - c = isl_constraint_set_coefficient_si (c, isl_dim_out, strip, stride); - c = isl_constraint_set_coefficient_si (c, isl_dim_out, iter, -1); - c = isl_constraint_set_constant_si (c, stride - 1); - pbb->transformed = isl_map_add_constraint (pbb->transformed, c); - - /* Static scheduling for ITER level. - This is mandatory to keep the 2d + 1 canonical scheduling format. */ - d = isl_map_get_space (pbb->transformed); - c = isl_equality_alloc (isl_local_space_from_space (d)); - c = isl_constraint_set_coefficient_si (c, isl_dim_out, strip + 1, 1); - pbb->transformed = isl_map_add_constraint (pbb->transformed, c); -} - -/* Returns true when strip mining with STRIDE of the loop LST is - profitable. */ - -static bool -lst_strip_mine_profitable_p (lst_p lst, int stride) -{ - mpz_t niter, strip_stride; - bool res; - - gcc_assert (LST_LOOP_P (lst)); - mpz_init (strip_stride); - mpz_init (niter); - - mpz_set_si (strip_stride, stride); - lst_niter_for_loop (lst, niter); - res = (mpz_cmp (niter, strip_stride) > 0); - - mpz_clear (strip_stride); - mpz_clear (niter); - return res; -} - -/* Strip-mines all the loops of LST with STRIDE. Return the number of - loops strip-mined. */ - -static int -lst_do_strip_mine_loop (lst_p lst, int depth, int stride) -{ - int i; - lst_p l; - poly_bb_p pbb; - - if (!lst) - return 0; - - if (LST_LOOP_P (lst)) - { - int res = 0; - - FOR_EACH_VEC_ELT (LST_SEQ (lst), i, l) - res += lst_do_strip_mine_loop (l, depth, stride); - - return res; - } - - pbb = LST_PBB (lst); - pbb_strip_mine_time_depth (pbb, psct_dynamic_dim (pbb, depth), stride); - return 1; -} - -/* Strip-mines all the loops of LST with STRIDE. When STRIDE is zero, - read the stride from the PARAM_LOOP_BLOCK_TILE_SIZE. Return the - number of strip-mined loops. - - Strip mining transforms a loop - - | for (i = 0; i < N; i++) - | S (i); - - into the following loop nest: - - | for (k = 0; k < N; k += STRIDE) - | for (j = 0; j < STRIDE; j++) - | S (i = k + j); -*/ - -static int -lst_do_strip_mine (lst_p lst, int stride) -{ - int i; - lst_p l; - int res = 0; - int depth; - - if (!stride) - stride = PARAM_VALUE (PARAM_LOOP_BLOCK_TILE_SIZE); - - if (!lst - || !LST_LOOP_P (lst)) - return false; - - FOR_EACH_VEC_ELT (LST_SEQ (lst), i, l) - res += lst_do_strip_mine (l, stride); - - depth = lst_depth (lst); - if (depth >= 0 - && lst_strip_mine_profitable_p (lst, stride)) - { - res += lst_do_strip_mine_loop (lst, lst_depth (lst), stride); - lst_add_loop_under_loop (lst); - } - - return res; -} - -/* Strip mines all the loops in SCOP. Returns the number of - strip-mined loops. */ - -int -scop_do_strip_mine (scop_p scop, int stride) -{ - return lst_do_strip_mine (SCOP_TRANSFORMED_SCHEDULE (scop), stride); -} - -/* Loop blocks all the loops in SCOP. Returns true when we manage to - block some loops. */ - -bool -scop_do_block (scop_p scop) -{ - store_scattering (scop); - - /* If we don't strip mine at least two loops, or not interchange - loops, the strip mine alone will not be profitable, and the - transform is not a loop blocking: so revert the transform. */ - if (lst_do_strip_mine (SCOP_TRANSFORMED_SCHEDULE (scop), 0) < 2 - || scop_do_interchange (scop) == 0) - { - restore_scattering (scop); - return false; - } - - if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, "SCoP will be loop blocked.\n"); - - return true; -} - -#endif diff --git a/gcc/graphite-interchange.c b/gcc/graphite-interchange.c deleted file mode 100644 index 6b14955ced7..00000000000 --- a/gcc/graphite-interchange.c +++ /dev/null @@ -1,656 +0,0 @@ -/* Interchange heuristics and transform for loop interchange on - polyhedral representation. - - Copyright (C) 2009-2015 Free Software Foundation, Inc. - Contributed by Sebastian Pop <sebastian.pop@amd.com> and - Harsha Jagasia <harsha.jagasia@amd.com>. - -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" - -#ifdef HAVE_isl -/* Workaround for GMP 5.1.3 bug, see PR56019. */ -#include <stddef.h> - -#include <isl/constraint.h> -#include <isl/aff.h> -#include <isl/set.h> -#include <isl/map.h> -#include <isl/union_map.h> -#include <isl/ilp.h> -#include <isl/val.h> - -/* Since ISL-0.13, the extern is in val_gmp.h. */ -#if !defined(HAVE_ISL_SCHED_CONSTRAINTS_COMPUTE_SCHEDULE) && defined(__cplusplus) -extern "C" { -#endif -#include <isl/val_gmp.h> -#if !defined(HAVE_ISL_SCHED_CONSTRAINTS_COMPUTE_SCHEDULE) && defined(__cplusplus) -} -#endif - -#include "system.h" -#include "coretypes.h" -#include "backend.h" -#include "cfghooks.h" -#include "tree.h" -#include "gimple.h" -#include "fold-const.h" -#include "gimple-iterator.h" -#include "tree-ssa-loop.h" -#include "dumpfile.h" -#include "cfgloop.h" -#include "tree-data-ref.h" -#include "graphite-poly.h" - - -/* XXX isl rewrite following comment */ -/* Builds a linear expression, of dimension DIM, representing PDR's - memory access: - - L = r_{n}*r_{n-1}*...*r_{1}*s_{0} + ... + r_{n}*s_{n-1} + s_{n}. - - For an array A[10][20] with two subscript locations s0 and s1, the - linear memory access is 20 * s0 + s1: a stride of 1 in subscript s0 - corresponds to a memory stride of 20. - - OFFSET is a number of dimensions to prepend before the - subscript dimensions: s_0, s_1, ..., s_n. - - Thus, the final linear expression has the following format: - 0 .. 0_{offset} | 0 .. 0_{nit} | 0 .. 0_{gd} | 0 | c_0 c_1 ... c_n - where the expression itself is: - c_0 * s_0 + c_1 * s_1 + ... c_n * s_n. */ - -static isl_constraint * -build_linearized_memory_access (isl_map *map, poly_dr_p pdr) -{ - isl_local_space *ls = isl_local_space_from_space (isl_map_get_space (map)); - isl_constraint *res = isl_equality_alloc (ls); - isl_val *size = isl_val_int_from_ui (isl_map_get_ctx (map), 1); - - unsigned nsubs = isl_set_dim (pdr->subscript_sizes, isl_dim_set); - /* -1 for the already included L dimension. */ - unsigned offset = isl_map_dim (map, isl_dim_out) - 1 - nsubs; - res = isl_constraint_set_coefficient_si (res, isl_dim_out, offset + nsubs, -1); - /* Go through all subscripts from last to first. The dimension "i=0" - is the alias set, ignore it. */ - for (int i = nsubs - 1; i >= 1; i--) - { - isl_aff *extract_dim; - res = isl_constraint_set_coefficient_val (res, isl_dim_out, offset + i, - isl_val_copy (size)); - isl_space *dc = isl_set_get_space (pdr->subscript_sizes); - extract_dim = isl_aff_zero_on_domain (isl_local_space_from_space (dc)); - extract_dim = isl_aff_set_coefficient_si (extract_dim, isl_dim_in, i, 1); - isl_val *max = isl_set_max_val (pdr->subscript_sizes, extract_dim); - isl_aff_free (extract_dim); - - /* The result is NULL in case of an error, the optimal value in case there - is one, negative infinity or infinity if the problem is unbounded and - NaN if the problem is empty. */ - gcc_assert (max); - - /* When one of the dimensions cannot be computed, we cannot build the size - of the array for any outer dimensions. */ - if (!isl_val_is_int (max)) - { - isl_val_free (max); - break; - } - size = isl_val_mul (size, max); - } - - isl_val_free (size); - - return res; -} - -/* Set STRIDE to the stride of PDR in memory by advancing by one in - the loop at DEPTH. */ - -static void -pdr_stride_in_loop (mpz_t stride, graphite_dim_t depth, poly_dr_p pdr) -{ - poly_bb_p pbb = PDR_PBB (pdr); - isl_map *map; - isl_set *set; - isl_aff *aff; - isl_space *dc; - isl_constraint *lma, *c; - isl_val *islstride; - graphite_dim_t time_depth; - unsigned offset, nt; - unsigned i; - /* XXX isl rewrite following comments. */ - /* Builds a partial difference equations and inserts them - into pointset powerset polyhedron P. Polyhedron is assumed - to have the format: T|I|T'|I'|G|S|S'|l1|l2. - - TIME_DEPTH is the time dimension w.r.t. which we are - differentiating. - OFFSET represents the number of dimensions between - columns t_{time_depth} and t'_{time_depth}. - DIM_SCTR is the number of scattering dimensions. It is - essentially the dimensionality of the T vector. - - The following equations are inserted into the polyhedron P: - | t_1 = t_1' - | ... - | t_{time_depth-1} = t'_{time_depth-1} - | t_{time_depth} = t'_{time_depth} + 1 - | t_{time_depth+1} = t'_{time_depth + 1} - | ... - | t_{dim_sctr} = t'_{dim_sctr}. */ - - /* Add the equality: t_{time_depth} = t'_{time_depth} + 1. - This is the core part of this alogrithm, since this - constraint asks for the memory access stride (difference) - between two consecutive points in time dimensions. */ - - /* Add equalities: - | t1 = t1' - | ... - | t_{time_depth-1} = t'_{time_depth-1} - | t_{time_depth+1} = t'_{time_depth+1} - | ... - | t_{dim_sctr} = t'_{dim_sctr} - - This means that all the time dimensions are equal except for - time_depth, where the constraint is t_{depth} = t'_{depth} + 1 - step. More to this: we should be careful not to add equalities - to the 'coupled' dimensions, which happens when the one dimension - is stripmined dimension, and the other dimension corresponds - to the point loop inside stripmined dimension. */ - - /* pdr->accesses: [P1..nb_param,I1..nb_domain]->[a,S1..nb_subscript] - ??? [P] not used for PDRs? - pdr->subscript_sizes: [a,S1..nb_subscript] - pbb->domain: [P1..nb_param,I1..nb_domain] - pbb->transformed: [P1..nb_param,I1..nb_domain]->[T1..Tnb_sctr] - [T] includes local vars (currently unused) - - First we create [P,I] -> [T,a,S]. */ - - map = isl_map_flat_range_product (isl_map_copy (pbb->transformed), - isl_map_copy (pdr->accesses)); - /* Add a dimension for L: [P,I] -> [T,a,S,L].*/ - map = isl_map_add_dims (map, isl_dim_out, 1); - /* Build a constraint for "lma[S] - L == 0", effectively calculating - L in terms of subscripts. */ - lma = build_linearized_memory_access (map, pdr); - /* And add it to the map, so we now have: - [P,I] -> [T,a,S,L] : lma([S]) == L. */ - map = isl_map_add_constraint (map, lma); - - /* Then we create [P,I,P',I'] -> [T,a,S,L,T',a',S',L']. */ - map = isl_map_flat_product (map, isl_map_copy (map)); - - /* Now add the equality T[time_depth] == T'[time_depth]+1. This will - force L' to be the linear address at T[time_depth] + 1. */ - time_depth = psct_dynamic_dim (pbb, depth); - /* Length of [a,S] plus [L] ... */ - offset = 1 + isl_map_dim (pdr->accesses, isl_dim_out); - /* ... plus [T]. */ - offset += isl_map_dim (pbb->transformed, isl_dim_out); - - c = isl_equality_alloc (isl_local_space_from_space (isl_map_get_space (map))); - c = isl_constraint_set_coefficient_si (c, isl_dim_out, time_depth, 1); - c = isl_constraint_set_coefficient_si (c, isl_dim_out, - offset + time_depth, -1); - c = isl_constraint_set_constant_si (c, 1); - map = isl_map_add_constraint (map, c); - - /* Now we equate most of the T/T' elements (making PITaSL nearly - the same is (PITaSL)', except for one dimension, namely for 'depth' - (an index into [I]), after translating to index into [T]. Take care - to not produce an empty map, which indicates we wanted to equate - two dimensions that are already coupled via the above time_depth - dimension. Happens with strip mining where several scatter dimension - are interdependend. */ - /* Length of [T]. */ - nt = pbb_nb_scattering_transform (pbb) + pbb_nb_local_vars (pbb); - for (i = 0; i < nt; i++) - if (i != time_depth) - { - isl_map *temp = isl_map_equate (isl_map_copy (map), - isl_dim_out, i, - isl_dim_out, offset + i); - if (isl_map_is_empty (temp)) - isl_map_free (temp); - else - { - isl_map_free (map); - map = temp; - } - } - - /* Now maximize the expression L' - L. */ - set = isl_map_range (map); - dc = isl_set_get_space (set); - aff = isl_aff_zero_on_domain (isl_local_space_from_space (dc)); - aff = isl_aff_set_coefficient_si (aff, isl_dim_in, offset - 1, -1); - aff = isl_aff_set_coefficient_si (aff, isl_dim_in, offset + offset - 1, 1); - islstride = isl_set_max_val (set, aff); - isl_val_get_num_gmp (islstride, stride); - isl_val_free (islstride); - isl_aff_free (aff); - isl_set_free (set); - - if (dump_file && (dump_flags & TDF_DETAILS)) - { - gmp_fprintf (dump_file, "\nStride in BB_%d, DR_%d, depth %d: %Zd ", - pbb_index (pbb), PDR_ID (pdr), (int) depth, stride); - } -} - -/* Sets STRIDES to the sum of all the strides of the data references - accessed in LOOP at DEPTH. */ - -static void -memory_strides_in_loop_1 (lst_p loop, graphite_dim_t depth, mpz_t strides) -{ - int i, j; - lst_p l; - poly_dr_p pdr; - mpz_t s, n; - - mpz_init (s); - mpz_init (n); - - FOR_EACH_VEC_ELT (LST_SEQ (loop), j, l) - if (LST_LOOP_P (l)) - memory_strides_in_loop_1 (l, depth, strides); - else - FOR_EACH_VEC_ELT (PBB_DRS (LST_PBB (l)), i, pdr) - { - pdr_stride_in_loop (s, depth, pdr); - mpz_set_si (n, PDR_NB_REFS (pdr)); - mpz_mul (s, s, n); - mpz_add (strides, strides, s); - } - - mpz_clear (s); - mpz_clear (n); -} - -/* Sets STRIDES to the sum of all the strides of the data references - accessed in LOOP at DEPTH. */ - -static void -memory_strides_in_loop (lst_p loop, graphite_dim_t depth, mpz_t strides) -{ - if (mpz_cmp_si (loop->memory_strides, -1) == 0) - { - mpz_set_si (strides, 0); - memory_strides_in_loop_1 (loop, depth, strides); - } - else - mpz_set (strides, loop->memory_strides); -} - -/* Return true when the interchange of loops LOOP1 and LOOP2 is - profitable. - - Example: - - | int a[100][100]; - | - | int - | foo (int N) - | { - | int j; - | int i; - | - | for (i = 0; i < N; i++) - | for (j = 0; j < N; j++) - | a[j][2 * i] += 1; - | - | return a[N][12]; - | } - - The data access A[j][i] is described like this: - - | i j N a s0 s1 1 - | 0 0 0 1 0 0 -5 = 0 - | 0 -1 0 0 1 0 0 = 0 - |-2 0 0 0 0 1 0 = 0 - | 0 0 0 0 1 0 0 >= 0 - | 0 0 0 0 0 1 0 >= 0 - | 0 0 0 0 -1 0 100 >= 0 - | 0 0 0 0 0 -1 100 >= 0 - - The linearized memory access L to A[100][100] is: - - | i j N a s0 s1 1 - | 0 0 0 0 100 1 0 - - TODO: the shown format is not valid as it does not show the fact - that the iteration domain "i j" is transformed using the scattering. - - Next, to measure the impact of iterating once in loop "i", we build - a maximization problem: first, we add to DR accesses the dimensions - k, s2, s3, L1 = 100 * s0 + s1, L2, and D1: this is the polyhedron P1. - L1 and L2 are the linearized memory access functions. - - | i j N a s0 s1 k s2 s3 L1 L2 D1 1 - | 0 0 0 1 0 0 0 0 0 0 0 0 -5 = 0 alias = 5 - | 0 -1 0 0 1 0 0 0 0 0 0 0 0 = 0 s0 = j - |-2 0 0 0 0 1 0 0 0 0 0 0 0 = 0 s1 = 2 * i - | 0 0 0 0 1 0 0 0 0 0 0 0 0 >= 0 - | 0 0 0 0 0 1 0 0 0 0 0 0 0 >= 0 - | 0 0 0 0 -1 0 0 0 0 0 0 0 100 >= 0 - | 0 0 0 0 0 -1 0 0 0 0 0 0 100 >= 0 - | 0 0 0 0 100 1 0 0 0 -1 0 0 0 = 0 L1 = 100 * s0 + s1 - - Then, we generate the polyhedron P2 by interchanging the dimensions - (s0, s2), (s1, s3), (L1, L2), (k, i) - - | i j N a s0 s1 k s2 s3 L1 L2 D1 1 - | 0 0 0 1 0 0 0 0 0 0 0 0 -5 = 0 alias = 5 - | 0 -1 0 0 0 0 0 1 0 0 0 0 0 = 0 s2 = j - | 0 0 0 0 0 0 -2 0 1 0 0 0 0 = 0 s3 = 2 * k - | 0 0 0 0 0 0 0 1 0 0 0 0 0 >= 0 - | 0 0 0 0 0 0 0 0 1 0 0 0 0 >= 0 - | 0 0 0 0 0 0 0 -1 0 0 0 0 100 >= 0 - | 0 0 0 0 0 0 0 0 -1 0 0 0 100 >= 0 - | 0 0 0 0 0 0 0 100 1 0 -1 0 0 = 0 L2 = 100 * s2 + s3 - - then we add to P2 the equality k = i + 1: - - |-1 0 0 0 0 0 1 0 0 0 0 0 -1 = 0 k = i + 1 - - and finally we maximize the expression "D1 = max (P1 inter P2, L2 - L1)". - - Similarly, to determine the impact of one iteration on loop "j", we - interchange (k, j), we add "k = j + 1", and we compute D2 the - maximal value of the difference. - - Finally, the profitability test is D1 < D2: if in the outer loop - the strides are smaller than in the inner loop, then it is - profitable to interchange the loops at DEPTH1 and DEPTH2. */ - -static bool -lst_interchange_profitable_p (lst_p nest, int depth1, int depth2) -{ - mpz_t d1, d2; - bool res; - - gcc_assert (depth1 < depth2); - - mpz_init (d1); - mpz_init (d2); - - memory_strides_in_loop (nest, depth1, d1); - memory_strides_in_loop (nest, depth2, d2); - - res = mpz_cmp (d1, d2) < 0; - - mpz_clear (d1); - mpz_clear (d2); - - return res; -} - -/* Interchanges the loops at DEPTH1 and DEPTH2 of the original - scattering and assigns the resulting polyhedron to the transformed - scattering. */ - -static void -pbb_interchange_loop_depths (graphite_dim_t depth1, graphite_dim_t depth2, - poly_bb_p pbb) -{ - unsigned i; - unsigned dim1 = psct_dynamic_dim (pbb, depth1); - unsigned dim2 = psct_dynamic_dim (pbb, depth2); - isl_space *d = isl_map_get_space (pbb->transformed); - isl_space *d1 = isl_space_range (d); - unsigned n = isl_space_dim (d1, isl_dim_out); - isl_space *d2 = isl_space_add_dims (d1, isl_dim_in, n); - isl_map *x = isl_map_universe (d2); - - x = isl_map_equate (x, isl_dim_in, dim1, isl_dim_out, dim2); - x = isl_map_equate (x, isl_dim_in, dim2, isl_dim_out, dim1); - - for (i = 0; i < n; i++) - if (i != dim1 && i != dim2) - x = isl_map_equate (x, isl_dim_in, i, isl_dim_out, i); - - pbb->transformed = isl_map_apply_range (pbb->transformed, x); -} - -/* Apply the interchange of loops at depths DEPTH1 and DEPTH2 to all - the statements below LST. */ - -static void -lst_apply_interchange (lst_p lst, int depth1, int depth2) -{ - if (!lst) - return; - - if (LST_LOOP_P (lst)) - { - int i; - lst_p l; - - FOR_EACH_VEC_ELT (LST_SEQ (lst), i, l) - lst_apply_interchange (l, depth1, depth2); - } - else - pbb_interchange_loop_depths (depth1, depth2, LST_PBB (lst)); -} - -/* Return true when the nest starting at LOOP1 and ending on LOOP2 is - perfect: i.e. there are no sequence of statements. */ - -static bool -lst_perfectly_nested_p (lst_p loop1, lst_p loop2) -{ - if (loop1 == loop2) - return true; - - if (!LST_LOOP_P (loop1)) - return false; - - return LST_SEQ (loop1).length () == 1 - && lst_perfectly_nested_p (LST_SEQ (loop1)[0], loop2); -} - -/* Transform the loop nest between LOOP1 and LOOP2 into a perfect - nest. To continue the naming tradition, this function is called - after perfect_nestify. NEST is set to the perfectly nested loop - that is created. BEFORE/AFTER are set to the loops distributed - before/after the loop NEST. */ - -static void -lst_perfect_nestify (lst_p loop1, lst_p loop2, lst_p *before, - lst_p *nest, lst_p *after) -{ - poly_bb_p first, last; - - gcc_assert (loop1 && loop2 - && loop1 != loop2 - && LST_LOOP_P (loop1) && LST_LOOP_P (loop2)); - - first = LST_PBB (lst_find_first_pbb (loop2)); - last = LST_PBB (lst_find_last_pbb (loop2)); - - *before = copy_lst (loop1); - *nest = copy_lst (loop1); - *after = copy_lst (loop1); - - lst_remove_all_before_including_pbb (*before, first, false); - lst_remove_all_before_including_pbb (*after, last, true); - - lst_remove_all_before_excluding_pbb (*nest, first, true); - lst_remove_all_before_excluding_pbb (*nest, last, false); - - if (lst_empty_p (*before)) - { - free_lst (*before); - *before = NULL; - } - if (lst_empty_p (*after)) - { - free_lst (*after); - *after = NULL; - } - if (lst_empty_p (*nest)) - { - free_lst (*nest); - *nest = NULL; - } -} - -/* Try to interchange LOOP1 with LOOP2 for all the statements of the - body of LOOP2. LOOP1 contains LOOP2. Return true if it did the - interchange. */ - -static bool -lst_try_interchange_loops (scop_p scop, lst_p loop1, lst_p loop2) -{ - int depth1 = lst_depth (loop1); - int depth2 = lst_depth (loop2); - lst_p transformed; - - lst_p before = NULL, nest = NULL, after = NULL; - - if (!lst_perfectly_nested_p (loop1, loop2)) - lst_perfect_nestify (loop1, loop2, &before, &nest, &after); - - if (!lst_interchange_profitable_p (loop2, depth1, depth2)) - return false; - - lst_apply_interchange (loop2, depth1, depth2); - - /* Sync the transformed LST information and the PBB scatterings - before using the scatterings in the data dependence analysis. */ - if (before || nest || after) - { - transformed = lst_substitute_3 (SCOP_TRANSFORMED_SCHEDULE (scop), loop1, - before, nest, after); - lst_update_scattering (transformed); - free_lst (transformed); - } - - if (graphite_legal_transform (scop)) - { - if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, - "Loops at depths %d and %d will be interchanged.\n", - depth1, depth2); - - /* Transform the SCOP_TRANSFORMED_SCHEDULE of the SCOP. */ - lst_insert_in_sequence (before, loop1, true); - lst_insert_in_sequence (after, loop1, false); - - if (nest) - { - lst_replace (loop1, nest); - free_lst (loop1); - } - - return true; - } - - /* Undo the transform. */ - free_lst (before); - free_lst (nest); - free_lst (after); - lst_apply_interchange (loop2, depth2, depth1); - return false; -} - -/* Selects the inner loop in LST_SEQ (INNER_FATHER) to be interchanged - with the loop OUTER in LST_SEQ (OUTER_FATHER). */ - -static bool -lst_interchange_select_inner (scop_p scop, lst_p outer_father, int outer, - lst_p inner_father) -{ - int inner; - lst_p loop1, loop2; - - gcc_assert (outer_father - && LST_LOOP_P (outer_father) - && LST_LOOP_P (LST_SEQ (outer_father)[outer]) - && inner_father - && LST_LOOP_P (inner_father)); - - loop1 = LST_SEQ (outer_father)[outer]; - - FOR_EACH_VEC_ELT (LST_SEQ (inner_father), inner, loop2) - if (LST_LOOP_P (loop2) - && (lst_try_interchange_loops (scop, loop1, loop2) - || lst_interchange_select_inner (scop, outer_father, outer, loop2))) - return true; - - return false; -} - -/* Interchanges all the loops of LOOP and the loops of its body that - are considered profitable to interchange. Return the number of - interchanged loops. OUTER is the index in LST_SEQ (LOOP) that - points to the next outer loop to be considered for interchange. */ - -static int -lst_interchange_select_outer (scop_p scop, lst_p loop, int outer) -{ - lst_p l; - int res = 0; - int i = 0; - lst_p father; - - if (!loop || !LST_LOOP_P (loop)) - return 0; - - father = LST_LOOP_FATHER (loop); - if (father) - { - while (lst_interchange_select_inner (scop, father, outer, loop)) - { - res++; - loop = LST_SEQ (father)[outer]; - } - } - - if (LST_LOOP_P (loop)) - FOR_EACH_VEC_ELT (LST_SEQ (loop), i, l) - if (LST_LOOP_P (l)) - res += lst_interchange_select_outer (scop, l, i); - - return res; -} - -/* Interchanges all the loop depths that are considered profitable for - SCOP. Return the number of interchanged loops. */ - -int -scop_do_interchange (scop_p scop) -{ - int res = lst_interchange_select_outer - (scop, SCOP_TRANSFORMED_SCHEDULE (scop), 0); - - lst_update_scattering (SCOP_TRANSFORMED_SCHEDULE (scop)); - - return res; -} - - -#endif /* HAVE_isl */ - diff --git a/gcc/graphite-isl-ast-to-gimple.c b/gcc/graphite-isl-ast-to-gimple.c index dfb012f75b1..5434bfdeb6f 100644 --- a/gcc/graphite-isl-ast-to-gimple.c +++ b/gcc/graphite-isl-ast-to-gimple.c @@ -968,92 +968,6 @@ extend_schedule (__isl_take isl_map *schedule, int nb_schedule_dims) return schedule; } -/* Set the separation_class option for unroll and jam. */ - -static __isl_give isl_union_map * -generate_luj_sepclass_opt (scop_p scop, __isl_take isl_union_set *domain, - int dim, int cl) -{ - isl_map *map; - isl_space *space, *space_sep; - isl_ctx *ctx; - isl_union_map *mapu; - int nsched = get_max_schedule_dimensions (scop); - - ctx = scop->ctx; - space_sep = isl_space_alloc (ctx, 0, 1, 1); - space_sep = isl_space_wrap (space_sep); - space_sep = isl_space_set_tuple_name (space_sep, isl_dim_set, - "separation_class"); - space = isl_set_get_space (scop->context); - space_sep = isl_space_align_params (space_sep, isl_space_copy(space)); - space = isl_space_map_from_domain_and_range (space, space_sep); - space = isl_space_add_dims (space,isl_dim_in, nsched); - map = isl_map_universe (space); - isl_map_fix_si (map,isl_dim_out,0,dim); - isl_map_fix_si (map,isl_dim_out,1,cl); - - mapu = isl_union_map_intersect_domain (isl_union_map_from_map (map), - domain); - return (mapu); -} - -/* Compute the separation class for loop unroll and jam. */ - -static __isl_give isl_union_set * -generate_luj_sepclass (scop_p scop) -{ - int i; - poly_bb_p pbb; - isl_union_set *domain_isl; - - domain_isl = isl_union_set_empty (isl_set_get_space (scop->context)); - - FOR_EACH_VEC_ELT (SCOP_BBS (scop), i, pbb) - { - isl_set *bb_domain; - isl_set *bb_domain_s; - - if (pbb->map_sepclass == NULL) - continue; - - if (isl_set_is_empty (pbb->domain)) - continue; - - bb_domain = isl_set_copy (pbb->domain); - bb_domain_s = isl_set_apply (bb_domain, pbb->map_sepclass); - pbb->map_sepclass = NULL; - - domain_isl = - isl_union_set_union (domain_isl, isl_union_set_from_set (bb_domain_s)); - } - - return domain_isl; -} - -/* Set the AST built options for loop unroll and jam. */ - -static __isl_give isl_union_map * -generate_luj_options (scop_p scop) -{ - isl_union_set *domain_isl; - isl_union_map *options_isl_ss; - isl_union_map *options_isl = - isl_union_map_empty (isl_set_get_space (scop->context)); - int dim = get_max_schedule_dimensions (scop) - 1; - int dim1 = dim - PARAM_VALUE (PARAM_LOOP_UNROLL_JAM_DEPTH); - - if (!flag_loop_unroll_jam) - return options_isl; - - domain_isl = generate_luj_sepclass (scop); - - options_isl_ss = generate_luj_sepclass_opt (scop, domain_isl, dim1, 0); - options_isl = isl_union_map_union (options_isl, options_isl_ss); - - return options_isl; -} - /* Generates a schedule, which specifies an order used to visit elements in a domain. */ @@ -1102,13 +1016,11 @@ ast_build_before_for (__isl_keep isl_ast_build *build, void *user) } /* Set the separate option for all dimensions. - This helps to reduce control overhead. - Set the options for unroll and jam. */ + This helps to reduce control overhead. */ static __isl_give isl_ast_build * set_options (__isl_take isl_ast_build *control, - __isl_keep isl_union_map *schedule, - __isl_take isl_union_map *opt_luj) + __isl_keep isl_union_map *schedule) { isl_ctx *ctx = isl_union_map_get_ctx (schedule); isl_space *range_space = isl_space_set_alloc (ctx, 0, 1); @@ -1119,9 +1031,6 @@ set_options (__isl_take isl_ast_build *control, isl_union_set *domain = isl_union_map_range (isl_union_map_copy (schedule)); domain = isl_union_set_universe (domain); isl_union_map *options = isl_union_map_from_domain_and_range (domain, range); - - options = isl_union_map_union (options, opt_luj); - return isl_ast_build_set_options (control, options); } @@ -1135,14 +1044,9 @@ scop_to_isl_ast (scop_p scop, ivs_params &ip) isl_options_set_ast_build_atomic_upper_bound (scop->ctx, true); add_parameters_to_ivs_params (scop, ip); - - isl_union_map *options_luj = generate_luj_options (scop); - isl_union_map *schedule_isl = generate_isl_schedule (scop); isl_ast_build *context_isl = generate_isl_context (scop); - - context_isl = set_options (context_isl, schedule_isl, options_luj); - + context_isl = set_options (context_isl, schedule_isl); isl_union_map *dependences = NULL; if (flag_loop_parallelize_all) { diff --git a/gcc/graphite-optimize-isl.c b/gcc/graphite-optimize-isl.c index 1b57c6cc6d2..ffa44652f63 100644 --- a/gcc/graphite-optimize-isl.c +++ b/gcc/graphite-optimize-isl.c @@ -47,6 +47,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-data-ref.h" #include "graphite-poly.h" #include "params.h" +#include "dumpfile.h" static isl_union_set * scop_get_domains (scop_p scop ATTRIBUTE_UNUSED) @@ -172,17 +173,26 @@ getScheduleForBand (isl_band *Band, int *Dimensions) PartialSchedule = isl_band_get_partial_schedule (Band); *Dimensions = isl_band_n_member (Band); - if (DisableTiling || flag_loop_unroll_jam) + if (DisableTiling) return PartialSchedule; /* It does not make any sense to tile a band with just one dimension. */ if (*Dimensions == 1) - return PartialSchedule; + { + if (dump_file && dump_flags) + fprintf (dump_file, "not tiled\n"); + return PartialSchedule; + } + + if (dump_file && dump_flags) + fprintf (dump_file, "tiled by %d\n", + PARAM_VALUE (PARAM_LOOP_BLOCK_TILE_SIZE)); ctx = isl_union_map_get_ctx (PartialSchedule); Space = isl_union_map_get_space (PartialSchedule); - TileMap = getTileMap (ctx, *Dimensions, 32); + TileMap = getTileMap (ctx, *Dimensions, + PARAM_VALUE (PARAM_LOOP_BLOCK_TILE_SIZE)); TileUMap = isl_union_map_from_map (isl_map_from_basic_map (TileMap)); TileUMap = isl_union_map_align_params (TileUMap, Space); *Dimensions = 2 * *Dimensions; @@ -227,9 +237,7 @@ getScheduleForBand (isl_band *Band, int *Dimensions) constant number of iterations, if the number of loop iterations at DimToVectorize can be devided by VectorWidth. The default VectorWidth is currently constant and not yet target specific. This function does not reason - about parallelism. - - */ + about parallelism. */ static isl_map * getPrevectorMap (isl_ctx *ctx, int DimToVectorize, int ScheduleDimensions, @@ -296,109 +304,15 @@ getPrevectorMap (isl_ctx *ctx, int DimToVectorize, return TilingMap; } -/* Compute an auxiliary map to getPrevectorMap, for computing the separating - class defined by full tiles. Used in graphite_isl_ast_to_gimple.c to set the - corresponding option for AST build. - - The map (for VectorWidth=4): - - [i,j] -> [it,j,ip] : it % 4 = 0 and it <= ip <= it + 3 and it + 3 = i and - ip >= 0 - - The image of this map is the separation class. The range of this map includes - all the i multiple of 4 in the domain such as i + 3 is in the domain too. - - */ -static isl_map * -getPrevectorMap_full (isl_ctx *ctx, int DimToVectorize, - int ScheduleDimensions, - int VectorWidth) -{ - isl_space *Space; - isl_local_space *LocalSpace, *LocalSpaceRange; - isl_set *Modulo; - isl_map *TilingMap; - isl_constraint *c; - isl_aff *Aff; - int PointDimension; /* ip */ - int TileDimension; /* it */ - isl_val *VectorWidthMP; - int i; - - /* assert (0 <= DimToVectorize && DimToVectorize < ScheduleDimensions);*/ - - Space = isl_space_alloc (ctx, 0, ScheduleDimensions, ScheduleDimensions + 1); - TilingMap = isl_map_universe (isl_space_copy (Space)); - LocalSpace = isl_local_space_from_space (Space); - PointDimension = ScheduleDimensions; - TileDimension = DimToVectorize; - - /* Create an identity map for everything except DimToVectorize and the - point loop. */ - for (i = 0; i < ScheduleDimensions; i++) - { - if (i == DimToVectorize) - continue; - - c = isl_equality_alloc (isl_local_space_copy (LocalSpace)); - - isl_constraint_set_coefficient_si (c, isl_dim_in, i, -1); - isl_constraint_set_coefficient_si (c, isl_dim_out, i, 1); - - TilingMap = isl_map_add_constraint (TilingMap, c); - } - - /* it % 'VectorWidth' = 0 */ - LocalSpaceRange = isl_local_space_range (isl_local_space_copy (LocalSpace)); - Aff = isl_aff_zero_on_domain (LocalSpaceRange); - Aff = isl_aff_set_constant_si (Aff, VectorWidth); - Aff = isl_aff_set_coefficient_si (Aff, isl_dim_in, TileDimension, 1); - - VectorWidthMP = isl_val_int_from_si (ctx, VectorWidth); - Aff = isl_aff_mod_val (Aff, VectorWidthMP); - Modulo = isl_pw_aff_zero_set (isl_pw_aff_from_aff (Aff)); - TilingMap = isl_map_intersect_range (TilingMap, Modulo); - - /* it + ('VectorWidth' - 1) = i0 */ - c = isl_equality_alloc (isl_local_space_copy(LocalSpace)); - isl_constraint_set_coefficient_si (c, isl_dim_out, TileDimension,-1); - isl_constraint_set_coefficient_si (c, isl_dim_in, TileDimension, 1); - isl_constraint_set_constant_si (c, -VectorWidth + 1); - TilingMap = isl_map_add_constraint (TilingMap, c); - - /* ip >= 0 */ - c = isl_inequality_alloc (isl_local_space_copy (LocalSpace)); - isl_constraint_set_coefficient_si (c, isl_dim_out, PointDimension, 1); - isl_constraint_set_constant_si (c, 0); - TilingMap = isl_map_add_constraint (TilingMap, c); - - /* it <= ip */ - c = isl_inequality_alloc (isl_local_space_copy (LocalSpace)); - isl_constraint_set_coefficient_si (c, isl_dim_out, TileDimension, -1); - isl_constraint_set_coefficient_si (c, isl_dim_out, PointDimension, 1); - TilingMap = isl_map_add_constraint (TilingMap, c); - - /* ip <= it + ('VectorWidth' - 1) */ - c = isl_inequality_alloc (LocalSpace); - isl_constraint_set_coefficient_si (c, isl_dim_out, TileDimension, 1); - isl_constraint_set_coefficient_si (c, isl_dim_out, PointDimension, -1); - isl_constraint_set_constant_si (c, VectorWidth - 1); - TilingMap = isl_map_add_constraint (TilingMap, c); - - return TilingMap; -} - static bool EnablePollyVector = false; /* getScheduleForBandList - Get the scheduling map for a list of bands. - + We walk recursively the forest of bands to combine the schedules of the individual bands to the overall schedule. In case tiling is requested, - the individual bands are tiled. - For unroll and jam the map the schedule for full tiles of the unrolled - dimnesion is computed. */ + the individual bands are tiled. */ static isl_union_map * -getScheduleForBandList (isl_band_list *BandList, isl_union_map **map_sepcl) +getScheduleForBandList (isl_band_list *BandList) { int NumBands, i; isl_union_map *Schedule; @@ -415,37 +329,25 @@ getScheduleForBandList (isl_band_list *BandList, isl_union_map **map_sepcl) int ScheduleDimensions; isl_space *Space; - isl_union_map *PartialSchedule_f; - Band = isl_band_list_get_band (BandList, i); PartialSchedule = getScheduleForBand (Band, &ScheduleDimensions); Space = isl_union_map_get_space (PartialSchedule); - PartialSchedule_f = NULL; - if (isl_band_has_children (Band)) { isl_band_list *Children; isl_union_map *SuffixSchedule; Children = isl_band_get_children (Band); - SuffixSchedule = getScheduleForBandList (Children, map_sepcl); + SuffixSchedule = getScheduleForBandList (Children); PartialSchedule = isl_union_map_flat_range_product (PartialSchedule, SuffixSchedule); isl_band_list_free (Children); } - else if (EnablePollyVector || flag_loop_unroll_jam) + else if (EnablePollyVector) { - int i; - int depth; - - depth = PARAM_VALUE (PARAM_LOOP_UNROLL_JAM_DEPTH); - for (i = ScheduleDimensions - 1 ; i >= 0 ; i--) { - if (flag_loop_unroll_jam && (i != (ScheduleDimensions - depth))) - continue; - #ifdef HAVE_ISL_SCHED_CONSTRAINTS_COMPUTE_SCHEDULE if (isl_band_member_is_coincident (Band, i)) #else @@ -454,19 +356,8 @@ getScheduleForBandList (isl_band_list *BandList, isl_union_map **map_sepcl) { isl_map *TileMap; isl_union_map *TileUMap; - int stride; - - stride = PARAM_VALUE (PARAM_LOOP_UNROLL_JAM_SIZE); - - TileMap = getPrevectorMap_full (ctx, i, ScheduleDimensions, - stride); - TileUMap = isl_union_map_from_map (TileMap); - TileUMap = isl_union_map_align_params - (TileUMap, isl_space_copy (Space)); - PartialSchedule_f = isl_union_map_apply_range - (isl_union_map_copy (PartialSchedule), TileUMap); - TileMap = getPrevectorMap (ctx, i, ScheduleDimensions, stride); + TileMap = getPrevectorMap (ctx, i, ScheduleDimensions, 4); TileUMap = isl_union_map_from_map (TileMap); TileUMap = isl_union_map_align_params (TileUMap, isl_space_copy (Space)); @@ -476,35 +367,21 @@ getScheduleForBandList (isl_band_list *BandList, isl_union_map **map_sepcl) } } } - Schedule = isl_union_map_union (Schedule, - isl_union_map_copy(PartialSchedule)); + + Schedule = isl_union_map_union (Schedule, PartialSchedule); isl_band_free (Band); isl_space_free (Space); - - if (!flag_loop_unroll_jam) - { - isl_union_map_free (PartialSchedule); - continue; - } - - if (PartialSchedule_f) - { - *map_sepcl = isl_union_map_union (*map_sepcl, PartialSchedule_f); - isl_union_map_free (PartialSchedule); - } - else - *map_sepcl = isl_union_map_union (*map_sepcl, PartialSchedule); } return Schedule; } static isl_union_map * -getScheduleMap (isl_schedule *Schedule, isl_union_map **map_sepcl) +getScheduleMap (isl_schedule *Schedule) { isl_band_list *BandList = isl_schedule_get_band_forest (Schedule); - isl_union_map *ScheduleMap = getScheduleForBandList (BandList, map_sepcl); + isl_union_map *ScheduleMap = getScheduleForBandList (BandList); isl_band_list_free (BandList); return ScheduleMap; } @@ -519,7 +396,7 @@ getSingleMap (__isl_take isl_map *map, void *user) } static void -apply_schedule_map_to_scop (scop_p scop, isl_union_map *schedule_map, bool sepcl) +apply_schedule_map_to_scop (scop_p scop, isl_union_map *schedule_map) { int i; poly_bb_p pbb; @@ -534,15 +411,8 @@ apply_schedule_map_to_scop (scop_p scop, isl_union_map *schedule_map, bool sepcl (isl_union_map_copy (schedule_map), isl_union_set_from_set (domain)); isl_union_map_foreach_map (stmtBand, getSingleMap, &stmtSchedule); - - if (!sepcl) - { - isl_map_free (pbb->transformed); - pbb->transformed = stmtSchedule; - } - else - pbb->map_sepclass = stmtSchedule; - + isl_map_free (pbb->transformed); + pbb->transformed = stmtSchedule; isl_union_map_free (stmtBand); } } @@ -560,7 +430,6 @@ optimize_isl (scop_p scop) isl_union_set *domain; isl_union_map *validity, *proximity, *dependences; isl_union_map *schedule_map; - isl_union_map *schedule_map_f; domain = scop_get_domains (scop); dependences = scop_get_dependences (scop); @@ -605,13 +474,9 @@ optimize_isl (scop_p scop) if (!schedule) return false; - schedule_map_f = isl_union_map_empty (isl_space_params_alloc (scop->ctx, 0)); - schedule_map = getScheduleMap (schedule, &schedule_map_f); + schedule_map = getScheduleMap (schedule); - apply_schedule_map_to_scop (scop, schedule_map, false); - if (!isl_union_map_is_empty (schedule_map_f)) - apply_schedule_map_to_scop (scop, schedule_map_f, true); - isl_union_map_free (schedule_map_f); + apply_schedule_map_to_scop (scop, schedule_map); isl_schedule_free (schedule); isl_union_map_free (schedule_map); diff --git a/gcc/graphite-poly.c b/gcc/graphite-poly.c index dd4fcee1522..98e8ab01cdc 100644 --- a/gcc/graphite-poly.c +++ b/gcc/graphite-poly.c @@ -69,94 +69,6 @@ debug_gmp_value (mpz_t val) gmp_fprintf (stderr, "%Zd", val); } -/* Return the maximal loop depth in SCOP. */ - -int -scop_max_loop_depth (scop_p scop) -{ - int i; - poly_bb_p pbb; - int max_nb_loops = 0; - - FOR_EACH_VEC_ELT (SCOP_BBS (scop), i, pbb) - { - int nb_loops = pbb_dim_iter_domain (pbb); - if (max_nb_loops < nb_loops) - max_nb_loops = nb_loops; - } - - return max_nb_loops; -} - -/* Prints to FILE the scattering function of PBB, at some VERBOSITY - level. */ - -static void -print_scattering_function_1 (FILE *file, poly_bb_p pbb, int verbosity) -{ - graphite_dim_t i; - - if (verbosity > 0) - { - fprintf (file, "# scattering bb_%d (\n", pbb_index (pbb)); - fprintf (file, "#eq"); - - for (i = 0; i < pbb_nb_scattering_transform (pbb); i++) - fprintf (file, " s%d", (int) i); - - for (i = 0; i < pbb_nb_local_vars (pbb); i++) - fprintf (file, " lv%d", (int) i); - - for (i = 0; i < pbb_dim_iter_domain (pbb); i++) - fprintf (file, " i%d", (int) i); - - for (i = 0; i < pbb_nb_params (pbb); i++) - fprintf (file, " p%d", (int) i); - - fprintf (file, " cst\n"); - } - - fprintf (file, "isl\n"); - print_isl_map (file, pbb->transformed ? pbb->transformed : pbb->schedule); - - if (verbosity > 0) - fprintf (file, "#)\n"); -} - -/* Prints to FILE the scattering function of PBB, at some VERBOSITY - level. */ - -void -print_scattering_function (FILE *file, poly_bb_p pbb, int verbosity) -{ - if (!PBB_TRANSFORMED (pbb)) - return; - - if (pbb->schedule || pbb->transformed) - { - if (verbosity > 0) - fprintf (file, "# Scattering function is provided\n"); - - fprintf (file, "1\n"); - } - else - { - if (verbosity > 0) - fprintf (file, "# Scattering function is not provided\n"); - - fprintf (file, "0\n"); - return; - } - - print_scattering_function_1 (file, pbb, verbosity); - - if (verbosity > 0) - fprintf (file, "# Scattering names are not provided\n"); - - fprintf (file, "0\n"); - -} - /* Prints to FILE the iteration domain of PBB, at some VERBOSITY level. */ @@ -166,18 +78,6 @@ print_iteration_domain (FILE *file, poly_bb_p pbb, int verbosity) print_pbb_domain (file, pbb, verbosity); } -/* Prints to FILE the scattering functions of every PBB of SCOP. */ - -void -print_scattering_functions (FILE *file, scop_p scop, int verbosity) -{ - int i; - poly_bb_p pbb; - - FOR_EACH_VEC_ELT (SCOP_BBS (scop), i, pbb) - print_scattering_function (file, pbb, verbosity); -} - /* Prints to FILE the iteration domains of every PBB of SCOP, at some VERBOSITY level. */ @@ -191,15 +91,6 @@ print_iteration_domains (FILE *file, scop_p scop, int verbosity) print_iteration_domain (file, pbb, verbosity); } -/* Prints to STDERR the scattering function of PBB, at some VERBOSITY - level. */ - -DEBUG_FUNCTION void -debug_scattering_function (poly_bb_p pbb, int verbosity) -{ - print_scattering_function (stderr, pbb, verbosity); -} - /* Prints to STDERR the iteration domain of PBB, at some VERBOSITY level. */ @@ -209,15 +100,6 @@ debug_iteration_domain (poly_bb_p pbb, int verbosity) print_iteration_domain (stderr, pbb, verbosity); } -/* Prints to STDERR the scattering functions of every PBB of SCOP, at - some VERBOSITY level. */ - -DEBUG_FUNCTION void -debug_scattering_functions (scop_p scop, int verbosity) -{ - print_scattering_functions (stderr, scop, verbosity); -} - /* Prints to STDERR the iteration domains of every PBB of SCOP, at some VERBOSITY level. */ @@ -236,29 +118,14 @@ apply_poly_transforms (scop_p scop) /* Generate code even if we did not apply any real transformation. This also allows to check the performance for the identity - transformation: GIMPLE -> GRAPHITE -> GIMPLE - Keep in mind that CLooG optimizes in control, so the loop structure - may change, even if we only use -fgraphite-identity. */ + transformation: GIMPLE -> GRAPHITE -> GIMPLE. */ if (flag_graphite_identity) transform_done = true; if (flag_loop_parallelize_all) transform_done = true; - if (flag_loop_block) - transform_done |= scop_do_block (scop); - else - { - if (flag_loop_strip_mine) - transform_done |= scop_do_strip_mine (scop, 0); - - if (flag_loop_interchange) - transform_done |= scop_do_interchange (scop); - } - - /* This pass needs to be run at the final stage, as it does not - update the lst. */ - if (flag_loop_optimize_isl || flag_loop_unroll_jam) + if (flag_loop_optimize_isl) transform_done |= optimize_isl (scop); return transform_done; @@ -309,12 +176,8 @@ new_poly_bb (scop_p scop, void *black_box) pbb->schedule = NULL; pbb->transformed = NULL; pbb->saved = NULL; - pbb->map_sepclass = NULL; PBB_SCOP (pbb) = scop; pbb_set_black_box (pbb, black_box); - PBB_TRANSFORMED (pbb) = NULL; - PBB_SAVED (pbb) = NULL; - PBB_ORIGINAL (pbb) = NULL; PBB_DRS (pbb).create (3); PBB_IS_REDUCTION (pbb) = false; GBB_PBB ((gimple_bb_p) black_box) = pbb; @@ -343,27 +206,6 @@ free_poly_bb (poly_bb_p pbb) XDELETE (pbb); } -static void -print_pdr_access_layout (FILE *file, poly_bb_p pbb, poly_dr_p pdr) -{ - graphite_dim_t i; - - fprintf (file, "# eq"); - - fprintf (file, " alias"); - - for (i = 0; i < PDR_NB_SUBSCRIPTS (pdr); i++) - fprintf (file, " sub%d", (int) i); - - for (i = 0; i < pbb_dim_iter_domain (pbb); i++) - fprintf (file, " i%d", (int) i); - - for (i = 0; i < pbb_nb_params (pbb); i++) - fprintf (file, " p%d", (int) i); - - fprintf (file, " cst\n"); -} - /* Prints to FILE the polyhedral data reference PDR, at some VERBOSITY level. */ @@ -398,14 +240,10 @@ print_pdr (FILE *file, poly_dr_p pdr, int verbosity) if (verbosity > 0) { fprintf (file, "# data accesses (\n"); - print_pdr_access_layout (file, PDR_PBB (pdr), pdr); + print_isl_map (file, pdr->accesses); + print_isl_set (file, pdr->subscript_sizes); + fprintf (file, "#)\n"); } - - /* XXX isl dump accesses/subscripts */ - - if (verbosity > 0) - fprintf (file, "#)\n"); - if (verbosity > 1) fprintf (file, "#)\n"); } @@ -422,7 +260,7 @@ debug_pdr (poly_dr_p pdr, int verbosity) /* Creates a new SCOP containing REGION. */ scop_p -new_scop (void *region) +new_scop (sese region) { scop_p scop = XNEW (struct scop); @@ -441,9 +279,6 @@ new_scop (void *region) scop->may_waw_no_source = NULL; scop_set_region (scop, region); SCOP_BBS (scop).create (3); - SCOP_ORIGINAL_SCHEDULE (scop) = NULL; - SCOP_TRANSFORMED_SCHEDULE (scop) = NULL; - SCOP_SAVED_SCHEDULE (scop) = NULL; POLY_SCOP_P (scop) = false; return scop; @@ -475,44 +310,9 @@ free_scop (scop_p scop) isl_union_map_free (scop->may_waw); isl_union_map_free (scop->must_waw_no_source); isl_union_map_free (scop->may_waw_no_source); - free_lst (SCOP_ORIGINAL_SCHEDULE (scop)); - free_lst (SCOP_TRANSFORMED_SCHEDULE (scop)); - free_lst (SCOP_SAVED_SCHEDULE (scop)); XDELETE (scop); } -/* Print to FILE the domain of PBB in OpenScop format, at some VERBOSITY - level. */ - -static void -openscop_print_pbb_domain (FILE *file, poly_bb_p pbb, int verbosity) -{ - graphite_dim_t i; - gimple_bb_p gbb = PBB_BLACK_BOX (pbb); - - if (!pbb->domain) - return; - - if (verbosity > 0) - { - fprintf (file, "\n# Iteration domain of bb_%d (\n", GBB_BB (gbb)->index); - fprintf (file, "#eq"); - - for (i = 0; i < pbb_dim_iter_domain (pbb); i++) - fprintf (file, " i%d", (int) i); - - for (i = 0; i < pbb_nb_params (pbb); i++) - fprintf (file, " p%d", (int) i); - - fprintf (file, " cst\n"); - } - - fprintf (file, "XXX isl\n"); - - if (verbosity > 0) - fprintf (file, "#)\n"); -} - /* Print to FILE the domain of PBB, at some VERBOSITY level. */ void @@ -700,8 +500,7 @@ print_pbb (FILE *file, poly_bb_p pbb, int verbosity) dump_gbb_cases (file, PBB_BLACK_BOX (pbb)); } - openscop_print_pbb_domain (file, pbb, verbosity); - print_scattering_function (file, pbb, verbosity); + print_pbb_domain (file, pbb, verbosity); print_pdrs (file, pbb, verbosity); print_pbb_body (file, pbb, verbosity, false); @@ -749,58 +548,16 @@ print_scop_params (FILE *file, scop_p scop, int verbosity) fprintf (file, "#)\n"); } -/* Print to FILE the context of SCoP in OpenScop format, at some VERBOSITY - level. */ - -static void -openscop_print_scop_context (FILE *file, scop_p scop, int verbosity) -{ - graphite_dim_t i; - - if (verbosity > 0) - { - fprintf (file, "# Context (\n"); - fprintf (file, "#eq"); - - for (i = 0; i < scop_nb_params (scop); i++) - fprintf (file, " p%d", (int) i); - - fprintf (file, " cst\n"); - } - - if (scop->context) - /* XXX isl print context */ - fprintf (file, "XXX isl\n"); - else - fprintf (file, "0 %d 0 0 0 %d\n", (int) scop_nb_params (scop) + 2, - (int) scop_nb_params (scop)); - - if (verbosity > 0) - fprintf (file, "# )\n"); -} - /* Print to FILE the context of SCoP, at some VERBOSITY level. */ void print_scop_context (FILE *file, scop_p scop, int verbosity) { - graphite_dim_t i; - if (verbosity > 0) - { - fprintf (file, "# Context (\n"); - fprintf (file, "#eq"); - - for (i = 0; i < scop_nb_params (scop); i++) - fprintf (file, " p%d", (int) i); - - fprintf (file, " cst\n"); - } + fprintf (file, "# Context (\n"); if (scop->context) print_isl_set (file, scop->context); - else - fprintf (file, "no isl context %d\n", (int) scop_nb_params (scop) + 2); if (verbosity > 0) fprintf (file, "# )\n"); @@ -816,7 +573,7 @@ print_scop (FILE *file, scop_p scop, int verbosity) fprintf (file, "SCoP 1\n#(\n"); fprintf (file, "# Language\nGimple\n"); - openscop_print_scop_context (file, scop, verbosity); + print_scop_context (file, scop, verbosity); print_scop_params (file, scop, verbosity); if (verbosity > 0) @@ -827,17 +584,6 @@ print_scop (FILE *file, scop_p scop, int verbosity) FOR_EACH_VEC_ELT (SCOP_BBS (scop), i, pbb) print_pbb (file, pbb, verbosity); - if (verbosity > 1) - { - fprintf (file, "# original_lst (\n"); - print_lst (file, SCOP_ORIGINAL_SCHEDULE (scop), 0); - fprintf (file, "\n#)\n"); - - fprintf (file, "# transformed_lst (\n"); - print_lst (file, SCOP_TRANSFORMED_SCHEDULE (scop), 0); - fprintf (file, "\n#)\n"); - } - fprintf (file, "#)\n"); } @@ -889,6 +635,7 @@ print_isl_set (FILE *f, isl_set *set) { isl_printer *p = isl_printer_to_file (the_isl_ctx, f); p = isl_printer_print_set (p, set); + p = isl_printer_print_str (p, "\n"); isl_printer_free (p); } @@ -903,6 +650,7 @@ print_isl_map (FILE *f, isl_map *map) { isl_printer *p = isl_printer_to_file (the_isl_ctx, f); p = isl_printer_print_map (p, map); + p = isl_printer_print_str (p, "\n"); isl_printer_free (p); } @@ -917,6 +665,7 @@ print_isl_aff (FILE *f, isl_aff *aff) { isl_printer *p = isl_printer_to_file (the_isl_ctx, f); p = isl_printer_print_aff (p, aff); + p = isl_printer_print_str (p, "\n"); isl_printer_free (p); } @@ -931,6 +680,7 @@ print_isl_constraint (FILE *f, isl_constraint *c) { isl_printer *p = isl_printer_to_file (the_isl_ctx, f); p = isl_printer_print_constraint (p, c); + p = isl_printer_print_str (p, "\n"); isl_printer_free (p); } @@ -977,224 +727,5 @@ pbb_number_of_iterations_at_time (poly_bb_p pbb, isl_set_free (transdomain); } -/* Translates LOOP to LST. */ - -static lst_p -loop_to_lst (loop_p loop, vec<poly_bb_p> bbs, int *i) -{ - poly_bb_p pbb; - vec<lst_p> seq; - seq.create (5); - - for (; bbs.iterate (*i, &pbb); (*i)++) - { - lst_p stmt; - basic_block bb = GBB_BB (PBB_BLACK_BOX (pbb)); - - if (bb->loop_father == loop) - stmt = new_lst_stmt (pbb); - else if (flow_bb_inside_loop_p (loop, bb)) - { - loop_p next = loop->inner; - - while (next && !flow_bb_inside_loop_p (next, bb)) - next = next->next; - - stmt = loop_to_lst (next, bbs, i); - } - else - { - (*i)--; - return new_lst_loop (seq); - } - - seq.safe_push (stmt); - } - - return new_lst_loop (seq); -} - -/* Reads the original scattering of the SCOP and returns an LST - representing it. */ - -void -scop_to_lst (scop_p scop) -{ - lst_p res; - int i, n = SCOP_BBS (scop).length (); - vec<lst_p> seq; - seq.create (5); - sese region = SCOP_REGION (scop); - - for (i = 0; i < n; i++) - { - poly_bb_p pbb = SCOP_BBS (scop)[i]; - loop_p loop = outermost_loop_in_sese (region, GBB_BB (PBB_BLACK_BOX (pbb))); - - if (loop_in_sese_p (loop, region)) - res = loop_to_lst (loop, SCOP_BBS (scop), &i); - else - res = new_lst_stmt (pbb); - - seq.safe_push (res); - } - - res = new_lst_loop (seq); - SCOP_ORIGINAL_SCHEDULE (scop) = res; - SCOP_TRANSFORMED_SCHEDULE (scop) = copy_lst (res); -} - -/* Print to FILE on a new line COLUMN white spaces. */ - -static void -lst_indent_to (FILE *file, int column) -{ - int i; - - if (column > 0) - fprintf (file, "\n#"); - - for (i = 0; i < column; i++) - fprintf (file, " "); -} - -/* Print LST to FILE with INDENT spaces of indentation. */ - -void -print_lst (FILE *file, lst_p lst, int indent) -{ - if (!lst) - return; - - lst_indent_to (file, indent); - - if (LST_LOOP_P (lst)) - { - int i; - lst_p l; - - if (LST_LOOP_FATHER (lst)) - fprintf (file, "%d (loop", lst_dewey_number (lst)); - else - fprintf (file, "#(root"); - - FOR_EACH_VEC_ELT (LST_SEQ (lst), i, l) - print_lst (file, l, indent + 2); - - fprintf (file, ")"); - } - else - fprintf (file, "%d stmt_%d", lst_dewey_number (lst), pbb_index (LST_PBB (lst))); -} - -/* Print LST to STDERR. */ - -DEBUG_FUNCTION void -debug_lst (lst_p lst) -{ - print_lst (stderr, lst, 0); -} - -/* Pretty print to FILE the loop statement tree LST in DOT format. */ - -static void -dot_lst_1 (FILE *file, lst_p lst) -{ - if (!lst) - return; - - if (LST_LOOP_P (lst)) - { - int i; - lst_p l; - - if (!LST_LOOP_FATHER (lst)) - fprintf (file, "L -> L_%d_%d\n", - lst_depth (lst), - lst_dewey_number (lst)); - else - fprintf (file, "L_%d_%d -> L_%d_%d\n", - lst_depth (LST_LOOP_FATHER (lst)), - lst_dewey_number (LST_LOOP_FATHER (lst)), - lst_depth (lst), - lst_dewey_number (lst)); - - FOR_EACH_VEC_ELT (LST_SEQ (lst), i, l) - dot_lst_1 (file, l); - } - - else - fprintf (file, "L_%d_%d -> S_%d\n", - lst_depth (LST_LOOP_FATHER (lst)), - lst_dewey_number (LST_LOOP_FATHER (lst)), - pbb_index (LST_PBB (lst))); - -} - -/* Display the LST using dotty. */ - -DEBUG_FUNCTION void -dot_lst (lst_p lst) -{ - /* When debugging, enable the following code. This cannot be used - in production compilers because it calls "system". */ -#if 0 - FILE *stream = fopen ("/tmp/lst.dot", "w"); - gcc_assert (stream); - - fputs ("digraph all {\n", stream); - dot_lst_1 (stream, lst); - fputs ("}\n\n", stream); - fclose (stream); - - system ("dotty /tmp/lst.dot &"); -#else - fputs ("digraph all {\n", stderr); - dot_lst_1 (stderr, lst); - fputs ("}\n\n", stderr); - -#endif -} - -/* Reverse the loop around PBB at level DEPTH. */ - -isl_map * -reverse_loop_at_level (poly_bb_p pbb, int depth) -{ - unsigned i, depth_dim = psct_dynamic_dim (pbb, depth); - isl_space *d = isl_map_get_space (pbb->transformed); - isl_space *d1 = isl_space_range (d); - unsigned n = isl_space_dim (d1, isl_dim_out); - isl_space *d2 = isl_space_add_dims (d1, isl_dim_in, n); - isl_map *x = isl_map_universe (isl_space_copy (d2)); - isl_constraint *c = isl_equality_alloc (isl_local_space_from_space (d2)); - - for (i = 0; i < n; i++) - if (i != depth_dim) - x = isl_map_equate (x, isl_dim_in, i, isl_dim_out, i); - - c = isl_constraint_set_coefficient_si (c, isl_dim_in, depth_dim, 1); - c = isl_constraint_set_coefficient_si (c, isl_dim_out, depth_dim, 1); - x = isl_map_add_constraint (x, c); - return x; -} - -/* Reverse the loop at level DEPTH for all the PBBS. */ - -isl_union_map * -reverse_loop_for_pbbs (scop_p scop, vec<poly_bb_p> pbbs, int depth) -{ - poly_bb_p pbb; - int i; - isl_space *space = isl_space_from_domain (isl_set_get_space (scop->context)); - isl_union_map *res = isl_union_map_empty (space); - - for (i = 0; pbbs.iterate (i, &pbb); i++) - res = isl_union_map_add_map (res, reverse_loop_at_level (pbb, depth)); - - return res; -} - - #endif /* HAVE_isl */ diff --git a/gcc/graphite-poly.h b/gcc/graphite-poly.h index 062d927411e..3bd22f05ae8 100644 --- a/gcc/graphite-poly.h +++ b/gcc/graphite-poly.h @@ -37,8 +37,6 @@ typedef struct scop *scop_p; typedef unsigned graphite_dim_t; -static inline graphite_dim_t pbb_dim_iter_domain (const struct poly_bb *); -static inline graphite_dim_t pbb_nb_params (const struct poly_bb *); static inline graphite_dim_t scop_nb_params (scop_p); /* A data reference can write or read some memory or we @@ -206,63 +204,6 @@ void new_poly_dr (poly_bb_p, int, enum poly_dr_type, void *, void free_poly_dr (poly_dr_p); void debug_pdr (poly_dr_p, int); void print_pdr (FILE *, poly_dr_p, int); -static inline scop_p pdr_scop (poly_dr_p pdr); - -/* The dimension of the iteration domain of the scop of PDR. */ - -static inline graphite_dim_t -pdr_dim_iter_domain (poly_dr_p pdr) -{ - return pbb_dim_iter_domain (PDR_PBB (pdr)); -} - -/* The number of parameters of the scop of PDR. */ - -static inline graphite_dim_t -pdr_nb_params (poly_dr_p pdr) -{ - return scop_nb_params (pdr_scop (pdr)); -} - -/* The dimension of the alias set in PDR. */ - -static inline graphite_dim_t -pdr_alias_set_dim (poly_dr_p pdr) -{ - poly_bb_p pbb = PDR_PBB (pdr); - - return pbb_dim_iter_domain (pbb) + pbb_nb_params (pbb); -} - -/* The dimension in PDR containing subscript S. */ - -static inline graphite_dim_t -pdr_subscript_dim (poly_dr_p pdr, graphite_dim_t s) -{ - poly_bb_p pbb = PDR_PBB (pdr); - - return pbb_dim_iter_domain (pbb) + pbb_nb_params (pbb) + 1 + s; -} - -/* The dimension in PDR containing the loop iterator ITER. */ - -static inline graphite_dim_t -pdr_iterator_dim (poly_dr_p pdr ATTRIBUTE_UNUSED, graphite_dim_t iter) -{ - return iter; -} - -/* The dimension in PDR containing parameter PARAM. */ - -static inline graphite_dim_t -pdr_parameter_dim (poly_dr_p pdr, graphite_dim_t param) -{ - poly_bb_p pbb = PDR_PBB (pdr); - - return pbb_dim_iter_domain (pbb) + param; -} - -/* Returns true when PDR is a "read". */ static inline bool pdr_read_p (poly_dr_p pdr) @@ -286,27 +227,6 @@ pdr_may_write_p (poly_dr_p pdr) return PDR_TYPE (pdr) == PDR_MAY_WRITE; } -/* Return true when PDR1 and PDR2 are similar data accesses: they have - the same base array, and the same access functions. */ - -static inline bool -same_pdr_p (poly_dr_p pdr1, poly_dr_p pdr2) -{ - return PDR_NB_SUBSCRIPTS (pdr1) == PDR_NB_SUBSCRIPTS (pdr2) - && PDR_BASE_OBJECT_SET (pdr1) == PDR_BASE_OBJECT_SET (pdr2); -} - -typedef struct poly_scattering *poly_scattering_p; - -struct poly_scattering -{ - /* The number of local variables. */ - int nb_local_variables; - - /* The number of scattering dimensions. */ - int nb_scattering; -}; - /* POLY_BB represents a blackbox in the polyhedral model. */ struct poly_bb @@ -345,44 +265,26 @@ struct poly_bb vec<poly_dr_p> drs; /* The original scattering. */ - poly_scattering_p _original; isl_map *schedule; /* The transformed scattering. */ - poly_scattering_p _transformed; isl_map *transformed; /* A copy of the transformed scattering. */ - poly_scattering_p _saved; isl_map *saved; - /* For tiling, the map for computing the separating class. */ - isl_map *map_sepclass; - /* True when this PBB contains only a reduction statement. */ bool is_reduction; }; #define PBB_BLACK_BOX(PBB) ((gimple_bb_p) PBB->black_box) #define PBB_SCOP(PBB) (PBB->scop) -#define PBB_DOMAIN(PBB) (NULL) #define PBB_DRS(PBB) (PBB->drs) -#define PBB_ORIGINAL(PBB) (PBB->_original) -#define PBB_ORIGINAL_SCATTERING(PBB) (NULL) -#define PBB_TRANSFORMED(PBB) (PBB->_transformed) -#define PBB_TRANSFORMED_SCATTERING(PBB) (NULL) -#define PBB_SAVED(PBB) (PBB->_saved) -/* XXX isl if we ever need local vars in the scatter, we can't use the - out dimension of transformed to count the scatterting transform dimension. - */ -#define PBB_NB_LOCAL_VARIABLES(PBB) (0) -#define PBB_NB_SCATTERING_TRANSFORM(PBB) (isl_map_n_out (PBB->transformed)) #define PBB_IS_REDUCTION(PBB) (PBB->is_reduction) extern poly_bb_p new_poly_bb (scop_p, void *); extern void free_poly_bb (poly_bb_p); extern void debug_loop_vec (poly_bb_p); -extern void schedule_to_scattering (poly_bb_p, int); extern void print_pbb_domain (FILE *, poly_bb_p, int); extern void print_pbb (FILE *, poly_bb_p, int); extern void print_scop_context (FILE *, scop_p, int); @@ -415,22 +317,6 @@ extern bool optimize_isl (scop_p); extern void pbb_number_of_iterations_at_time (poly_bb_p, graphite_dim_t, mpz_t); extern void debug_gmp_value (mpz_t); -/* Return the number of write data references in PBB. */ - -static inline int -number_of_write_pdrs (poly_bb_p pbb) -{ - int res = 0; - int i; - poly_dr_p pdr; - - for (i = 0; PBB_DRS (pbb).iterate (i, &pdr); i++) - if (PDR_TYPE (pdr) == PDR_WRITE) - res++; - - return res; -} - /* Returns a gimple_bb from BB. */ static inline gimple_bb_p @@ -455,8 +341,6 @@ pbb_bb (poly_bb_p pbb) return GBB_BB (PBB_BLACK_BOX (pbb)); } -/* The index of the PBB. */ - static inline int pbb_index (poly_bb_p pbb) { @@ -487,865 +371,12 @@ pbb_set_black_box (poly_bb_p pbb, void *black_box) pbb->black_box = black_box; } -/* The number of loops around PBB: the dimension of the iteration - domain. */ - -static inline graphite_dim_t -pbb_dim_iter_domain (const struct poly_bb *pbb) -{ - return isl_set_dim (pbb->domain, isl_dim_set); -} - -/* The number of params defined in PBB. */ - -static inline graphite_dim_t -pbb_nb_params (const struct poly_bb *pbb) -{ - scop_p scop = PBB_SCOP (pbb); - - return scop_nb_params (scop); -} - -/* The number of scattering dimensions in the SCATTERING polyhedron - of a PBB for a given SCOP. */ - -static inline graphite_dim_t -pbb_nb_scattering_orig (const struct poly_bb *pbb) -{ - return 2 * pbb_dim_iter_domain (pbb) + 1; -} - -/* The number of scattering dimensions in PBB. */ - -static inline graphite_dim_t -pbb_nb_scattering_transform (const struct poly_bb *pbb) -{ - return PBB_NB_SCATTERING_TRANSFORM (pbb); -} - -/* The number of dynamic scattering dimensions in PBB. */ - -static inline graphite_dim_t -pbb_nb_dynamic_scattering_transform (const struct poly_bb *pbb) -{ - /* This function requires the 2d + 1 scattering format to be - invariant during all transformations. */ - gcc_assert (PBB_NB_SCATTERING_TRANSFORM (pbb) % 2); - return PBB_NB_SCATTERING_TRANSFORM (pbb) / 2; -} - -/* Returns the number of local variables used in the transformed - scattering polyhedron of PBB. */ - -static inline graphite_dim_t -pbb_nb_local_vars (const struct poly_bb *pbb ATTRIBUTE_UNUSED) -{ - /* For now we do not have any local variables, as we do not do strip - mining for example. */ - return PBB_NB_LOCAL_VARIABLES (pbb); -} - -/* The dimension in the domain of PBB containing the iterator ITER. */ - -static inline graphite_dim_t -pbb_iterator_dim (poly_bb_p pbb ATTRIBUTE_UNUSED, graphite_dim_t iter) -{ - return iter; -} - -/* The dimension in the domain of PBB containing the iterator ITER. */ - -static inline graphite_dim_t -pbb_parameter_dim (poly_bb_p pbb, graphite_dim_t param) -{ - return param - + pbb_dim_iter_domain (pbb); -} - -/* The dimension in the original scattering polyhedron of PBB - containing the scattering iterator SCATTER. */ - -static inline graphite_dim_t -psco_scattering_dim (poly_bb_p pbb ATTRIBUTE_UNUSED, graphite_dim_t scatter) -{ - gcc_assert (scatter < pbb_nb_scattering_orig (pbb)); - return scatter; -} - -/* The dimension in the transformed scattering polyhedron of PBB - containing the scattering iterator SCATTER. */ - -static inline graphite_dim_t -psct_scattering_dim (poly_bb_p pbb ATTRIBUTE_UNUSED, graphite_dim_t scatter) -{ - gcc_assert (scatter <= pbb_nb_scattering_transform (pbb)); - return scatter; -} - -/* The dimension in the transformed scattering polyhedron of PBB of - the local variable LV. */ - -static inline graphite_dim_t -psct_local_var_dim (poly_bb_p pbb, graphite_dim_t lv) -{ - gcc_assert (lv <= pbb_nb_local_vars (pbb)); - return lv + pbb_nb_scattering_transform (pbb); -} - -/* The dimension in the original scattering polyhedron of PBB - containing the loop iterator ITER. */ - -static inline graphite_dim_t -psco_iterator_dim (poly_bb_p pbb, graphite_dim_t iter) -{ - gcc_assert (iter < pbb_dim_iter_domain (pbb)); - return iter + pbb_nb_scattering_orig (pbb); -} - -/* The dimension in the transformed scattering polyhedron of PBB - containing the loop iterator ITER. */ - -static inline graphite_dim_t -psct_iterator_dim (poly_bb_p pbb, graphite_dim_t iter) -{ - gcc_assert (iter < pbb_dim_iter_domain (pbb)); - return iter - + pbb_nb_scattering_transform (pbb) - + pbb_nb_local_vars (pbb); -} - -/* The dimension in the original scattering polyhedron of PBB - containing parameter PARAM. */ - -static inline graphite_dim_t -psco_parameter_dim (poly_bb_p pbb, graphite_dim_t param) -{ - gcc_assert (param < pbb_nb_params (pbb)); - return param - + pbb_nb_scattering_orig (pbb) - + pbb_dim_iter_domain (pbb); -} - -/* The dimension in the transformed scattering polyhedron of PBB - containing parameter PARAM. */ - -static inline graphite_dim_t -psct_parameter_dim (poly_bb_p pbb, graphite_dim_t param) -{ - gcc_assert (param < pbb_nb_params (pbb)); - return param - + pbb_nb_scattering_transform (pbb) - + pbb_nb_local_vars (pbb) - + pbb_dim_iter_domain (pbb); -} - -/* The scattering dimension of PBB corresponding to the dynamic level - LEVEL. */ - -static inline graphite_dim_t -psct_dynamic_dim (poly_bb_p pbb, graphite_dim_t level) -{ - graphite_dim_t result = 1 + 2 * level; - - gcc_assert (result < pbb_nb_scattering_transform (pbb)); - return result; -} - -/* The scattering dimension of PBB corresponding to the static - sequence of the loop level LEVEL. */ - -static inline graphite_dim_t -psct_static_dim (poly_bb_p pbb, graphite_dim_t level) -{ - graphite_dim_t result = 2 * level; - - gcc_assert (result < pbb_nb_scattering_transform (pbb)); - return result; -} - -/* Adds to the transformed scattering polyhedron of PBB a new local - variable and returns its index. */ - -static inline graphite_dim_t -psct_add_local_variable (poly_bb_p pbb ATTRIBUTE_UNUSED) -{ - gcc_unreachable (); - return 0; -} - -typedef struct lst *lst_p; - -/* Loops and Statements Tree. */ -struct lst { - - /* LOOP_P is true when an LST node is a loop. */ - bool loop_p; - - /* A pointer to the loop that contains this node. */ - lst_p loop_father; - - /* The sum of all the memory strides for an LST loop. */ - mpz_t memory_strides; - - /* Loop nodes contain a sequence SEQ of LST nodes, statements - contain a pointer to their polyhedral representation PBB. */ - union { - poly_bb_p pbb; - vec<lst_p> seq; - } node; -}; - -#define LST_LOOP_P(LST) ((LST)->loop_p) -#define LST_LOOP_FATHER(LST) ((LST)->loop_father) -#define LST_PBB(LST) ((LST)->node.pbb) -#define LST_SEQ(LST) ((LST)->node.seq) -#define LST_LOOP_MEMORY_STRIDES(LST) ((LST)->memory_strides) - -void scop_to_lst (scop_p); -void print_lst (FILE *, lst_p, int); -void debug_lst (lst_p); -void dot_lst (lst_p); - -/* Creates a new LST loop with SEQ. */ - -static inline lst_p -new_lst_loop (vec<lst_p> seq) -{ - lst_p lst = XNEW (struct lst); - int i; - lst_p l; - - LST_LOOP_P (lst) = true; - LST_SEQ (lst) = seq; - LST_LOOP_FATHER (lst) = NULL; - mpz_init (LST_LOOP_MEMORY_STRIDES (lst)); - mpz_set_si (LST_LOOP_MEMORY_STRIDES (lst), -1); - - for (i = 0; seq.iterate (i, &l); i++) - LST_LOOP_FATHER (l) = lst; - - return lst; -} - -/* Creates a new LST statement with PBB. */ - -static inline lst_p -new_lst_stmt (poly_bb_p pbb) -{ - lst_p lst = XNEW (struct lst); - - LST_LOOP_P (lst) = false; - LST_PBB (lst) = pbb; - LST_LOOP_FATHER (lst) = NULL; - return lst; -} - -/* Frees the memory used by LST. */ - -static inline void -free_lst (lst_p lst) -{ - if (!lst) - return; - - if (LST_LOOP_P (lst)) - { - int i; - lst_p l; - - for (i = 0; LST_SEQ (lst).iterate (i, &l); i++) - free_lst (l); - - mpz_clear (LST_LOOP_MEMORY_STRIDES (lst)); - LST_SEQ (lst).release (); - } - - free (lst); -} - -/* Returns a copy of LST. */ - -static inline lst_p -copy_lst (lst_p lst) -{ - if (!lst) - return NULL; - - if (LST_LOOP_P (lst)) - { - int i; - lst_p l; - vec<lst_p> seq; - seq.create (5); - - for (i = 0; LST_SEQ (lst).iterate (i, &l); i++) - seq.safe_push (copy_lst (l)); - - return new_lst_loop (seq); - } - - return new_lst_stmt (LST_PBB (lst)); -} - -/* Adds a new loop under the loop LST. */ - -static inline void -lst_add_loop_under_loop (lst_p lst) -{ - vec<lst_p> seq; - seq.create (1); - lst_p l = new_lst_loop (LST_SEQ (lst)); - - gcc_assert (LST_LOOP_P (lst)); - - LST_LOOP_FATHER (l) = lst; - seq.quick_push (l); - LST_SEQ (lst) = seq; -} - -/* Returns the loop depth of LST. */ - -static inline int -lst_depth (lst_p lst) -{ - if (!lst) - return -2; - - /* The depth of the outermost "fake" loop is -1. This outermost - loop does not have a loop father and it is just a container, as - in the loop representation of GCC. */ - if (!LST_LOOP_FATHER (lst)) - return -1; - - return lst_depth (LST_LOOP_FATHER (lst)) + 1; -} - -/* Returns the Dewey number for LST. */ - -static inline int -lst_dewey_number (lst_p lst) -{ - int i; - lst_p l; - - if (!lst) - return -1; - - if (!LST_LOOP_FATHER (lst)) - return 0; - - FOR_EACH_VEC_ELT (LST_SEQ (LST_LOOP_FATHER (lst)), i, l) - if (l == lst) - return i; - - return -1; -} - -/* Returns the Dewey number of LST at depth DEPTH. */ - -static inline int -lst_dewey_number_at_depth (lst_p lst, int depth) -{ - gcc_assert (lst && depth >= 0 && lst_depth (lst) <= depth); - - if (lst_depth (lst) == depth) - return lst_dewey_number (lst); - - return lst_dewey_number_at_depth (LST_LOOP_FATHER (lst), depth); -} - -/* Returns the predecessor of LST in the sequence of its loop father. - Returns NULL if LST is the first statement in the sequence. */ - -static inline lst_p -lst_pred (lst_p lst) -{ - int dewey; - lst_p father; - - if (!lst || !LST_LOOP_FATHER (lst)) - return NULL; - - dewey = lst_dewey_number (lst); - if (dewey == 0) - return NULL; - - father = LST_LOOP_FATHER (lst); - return LST_SEQ (father)[dewey - 1]; -} - -/* Returns the successor of LST in the sequence of its loop father. - Returns NULL if there is none. */ - -static inline lst_p -lst_succ (lst_p lst) -{ - int dewey; - lst_p father; - - if (!lst || !LST_LOOP_FATHER (lst)) - return NULL; - - dewey = lst_dewey_number (lst); - father = LST_LOOP_FATHER (lst); - - if (LST_SEQ (father).length () == (unsigned) dewey + 1) - return NULL; - - return LST_SEQ (father)[dewey + 1]; -} - - -/* Return the LST node corresponding to PBB. */ - -static inline lst_p -lst_find_pbb (lst_p lst, poly_bb_p pbb) -{ - int i; - lst_p l; - - if (!lst) - return NULL; - - if (!LST_LOOP_P (lst)) - return (pbb == LST_PBB (lst)) ? lst : NULL; - - for (i = 0; LST_SEQ (lst).iterate (i, &l); i++) - { - lst_p res = lst_find_pbb (l, pbb); - if (res) - return res; - } - - return NULL; -} - -/* Return the LST node corresponding to the loop around STMT at depth - LOOP_DEPTH. */ - -static inline lst_p -find_lst_loop (lst_p stmt, int loop_depth) -{ - lst_p loop = LST_LOOP_FATHER (stmt); - - gcc_assert (loop_depth >= 0); - - while (loop_depth < lst_depth (loop)) - loop = LST_LOOP_FATHER (loop); - - return loop; -} - -/* Return the first LST representing a PBB statement in LST. */ - -static inline lst_p -lst_find_first_pbb (lst_p lst) -{ - int i; - lst_p l; - - if (!lst) - return NULL; - - if (!LST_LOOP_P (lst)) - return lst; - - for (i = 0; LST_SEQ (lst).iterate (i, &l); i++) - { - lst_p res = lst_find_first_pbb (l); - if (res) - return res; - } - - return NULL; -} - -/* Returns true when LST is a loop that does not contain - statements. */ - -static inline bool -lst_empty_p (lst_p lst) -{ - return !lst_find_first_pbb (lst); -} - -/* Return the last LST representing a PBB statement in LST. */ - -static inline lst_p -lst_find_last_pbb (lst_p lst) -{ - int i; - lst_p l, res = NULL; - - if (!lst) - return NULL; - - if (!LST_LOOP_P (lst)) - return lst; - - for (i = 0; LST_SEQ (lst).iterate (i, &l); i++) - { - lst_p last = lst_find_last_pbb (l); - - if (last) - res = last; - } - - gcc_assert (res); - return res; -} - -/* Returns true if LOOP contains LST, in other words, if LST is nested - in LOOP. */ - -static inline bool -lst_contains_p (lst_p loop, lst_p lst) -{ - if (!loop || !lst || !LST_LOOP_P (loop)) - return false; - - if (loop == lst) - return true; - - return lst_contains_p (loop, LST_LOOP_FATHER (lst)); -} - -/* Returns true if LOOP contains PBB, in other words, if PBB is nested - in LOOP. */ - -static inline bool -lst_contains_pbb (lst_p loop, poly_bb_p pbb) -{ - return lst_find_pbb (loop, pbb) ? true : false; -} - -/* Creates a loop nest of depth NB_LOOPS containing LST. */ - -static inline lst_p -lst_create_nest (int nb_loops, lst_p lst) -{ - lst_p res, loop; - vec<lst_p> seq; - - if (nb_loops == 0) - return lst; - - seq.create (1); - loop = lst_create_nest (nb_loops - 1, lst); - seq.quick_push (loop); - res = new_lst_loop (seq); - LST_LOOP_FATHER (loop) = res; - - return res; -} - -/* Removes LST from the sequence of statements of its loop father. */ - -static inline void -lst_remove_from_sequence (lst_p lst) -{ - lst_p father = LST_LOOP_FATHER (lst); - int dewey = lst_dewey_number (lst); - - gcc_assert (lst && father && dewey >= 0); - - LST_SEQ (father).ordered_remove (dewey); - LST_LOOP_FATHER (lst) = NULL; -} - -/* Removes the loop LST and inline its body in the father loop. */ - -static inline void -lst_remove_loop_and_inline_stmts_in_loop_father (lst_p lst) -{ - lst_p l, father = LST_LOOP_FATHER (lst); - int i, dewey = lst_dewey_number (lst); - - gcc_assert (lst && father && dewey >= 0); - - LST_SEQ (father).ordered_remove (dewey); - LST_LOOP_FATHER (lst) = NULL; - - FOR_EACH_VEC_ELT (LST_SEQ (lst), i, l) - { - LST_SEQ (father).safe_insert (dewey + i, l); - LST_LOOP_FATHER (l) = father; - } -} - -/* Sets NITER to the upper bound approximation of the number of - iterations of loop LST. */ - -static inline void -lst_niter_for_loop (lst_p lst, mpz_t niter) -{ - int depth = lst_depth (lst); - poly_bb_p pbb = LST_PBB (lst_find_first_pbb (lst)); - - gcc_assert (LST_LOOP_P (lst)); - pbb_number_of_iterations_at_time (pbb, psct_dynamic_dim (pbb, depth), niter); -} - -/* Updates the scattering of PBB to be at the DEWEY number in the loop - at depth LEVEL. */ - -static inline void -pbb_update_scattering (poly_bb_p pbb, graphite_dim_t level, int dewey) -{ - graphite_dim_t sched = psct_static_dim (pbb, level); - isl_space *d = isl_map_get_space (pbb->transformed); - isl_space *d1 = isl_space_range (d); - unsigned i, n = isl_space_dim (d1, isl_dim_out); - isl_space *d2 = isl_space_add_dims (d1, isl_dim_in, n); - isl_map *x = isl_map_universe (d2); - - x = isl_map_fix_si (x, isl_dim_out, sched, dewey); - - for (i = 0; i < n; i++) - if (i != sched) - x = isl_map_equate (x, isl_dim_in, i, isl_dim_out, i); - - pbb->transformed = isl_map_apply_range (pbb->transformed, x); -} - -/* Updates the scattering of all the PBBs under LST to be at the DEWEY - number in the loop at depth LEVEL. */ - -static inline void -lst_update_scattering_under (lst_p lst, int level, int dewey) -{ - int i; - lst_p l; - - gcc_assert (lst && level >= 0 && dewey >= 0); - - if (LST_LOOP_P (lst)) - for (i = 0; LST_SEQ (lst).iterate (i, &l); i++) - lst_update_scattering_under (l, level, dewey); - else - pbb_update_scattering (LST_PBB (lst), level, dewey); -} - -/* Updates the all the scattering levels of all the PBBs under - LST. */ - -static inline void -lst_update_scattering (lst_p lst) -{ - int i; - lst_p l; - - if (!lst) - return; - - if (LST_LOOP_FATHER (lst)) - { - lst_p father = LST_LOOP_FATHER (lst); - int dewey = lst_dewey_number (lst); - int level = lst_depth (lst); - - gcc_assert (lst && father && dewey >= 0 && level >= 0); - - for (i = dewey; LST_SEQ (father).iterate (i, &l); i++) - lst_update_scattering_under (l, level, i); - } - - if (LST_LOOP_P (lst)) - for (i = 0; LST_SEQ (lst).iterate (i, &l); i++) - lst_update_scattering (l); -} - -/* Inserts LST1 before LST2 if BEFORE is true; inserts LST1 after LST2 - if BEFORE is false. */ - -static inline void -lst_insert_in_sequence (lst_p lst1, lst_p lst2, bool before) -{ - lst_p father; - int dewey; - - /* Do not insert empty loops. */ - if (!lst1 || lst_empty_p (lst1)) - return; - - father = LST_LOOP_FATHER (lst2); - dewey = lst_dewey_number (lst2); - - gcc_assert (lst2 && father && dewey >= 0); - - LST_SEQ (father).safe_insert (before ? dewey : dewey + 1, lst1); - LST_LOOP_FATHER (lst1) = father; -} - -/* Replaces LST1 with LST2. */ - -static inline void -lst_replace (lst_p lst1, lst_p lst2) -{ - lst_p father; - int dewey; - - if (!lst2 || lst_empty_p (lst2)) - return; - - father = LST_LOOP_FATHER (lst1); - dewey = lst_dewey_number (lst1); - LST_LOOP_FATHER (lst2) = father; - LST_SEQ (father)[dewey] = lst2; -} - -/* Returns a copy of ROOT where LST has been replaced by a copy of the - LSTs A B C in this sequence. */ - -static inline lst_p -lst_substitute_3 (lst_p root, lst_p lst, lst_p a, lst_p b, lst_p c) -{ - int i; - lst_p l; - vec<lst_p> seq; - - if (!root) - return NULL; - - gcc_assert (lst && root != lst); - - if (!LST_LOOP_P (root)) - return new_lst_stmt (LST_PBB (root)); - - seq.create (5); - - for (i = 0; LST_SEQ (root).iterate (i, &l); i++) - if (l != lst) - seq.safe_push (lst_substitute_3 (l, lst, a, b, c)); - else - { - if (!lst_empty_p (a)) - seq.safe_push (copy_lst (a)); - if (!lst_empty_p (b)) - seq.safe_push (copy_lst (b)); - if (!lst_empty_p (c)) - seq.safe_push (copy_lst (c)); - } - - return new_lst_loop (seq); -} - -/* Moves LST before LOOP if BEFORE is true, and after the LOOP if - BEFORE is false. */ - -static inline void -lst_distribute_lst (lst_p loop, lst_p lst, bool before) -{ - int loop_depth = lst_depth (loop); - int depth = lst_depth (lst); - int nb_loops = depth - loop_depth; - - gcc_assert (lst && loop && LST_LOOP_P (loop) && nb_loops > 0); - - lst_remove_from_sequence (lst); - lst_insert_in_sequence (lst_create_nest (nb_loops, lst), loop, before); -} - -/* Removes from LOOP all the statements before/after and including PBB - if BEFORE is true/false. Returns the negation of BEFORE when the - statement PBB has been found. */ - -static inline bool -lst_remove_all_before_including_pbb (lst_p loop, poly_bb_p pbb, bool before) -{ - int i; - lst_p l; - - if (!loop || !LST_LOOP_P (loop)) - return before; - - for (i = 0; LST_SEQ (loop).iterate (i, &l);) - if (LST_LOOP_P (l)) - { - before = lst_remove_all_before_including_pbb (l, pbb, before); - - if (LST_SEQ (l).length () == 0) - { - LST_SEQ (loop).ordered_remove (i); - free_lst (l); - } - else - i++; - } - else - { - if (before) - { - if (LST_PBB (l) == pbb) - before = false; - - LST_SEQ (loop).ordered_remove (i); - free_lst (l); - } - else if (LST_PBB (l) == pbb) - { - before = true; - LST_SEQ (loop).ordered_remove (i); - free_lst (l); - } - else - i++; - } - - return before; -} - -/* Removes from LOOP all the statements before/after and excluding PBB - if BEFORE is true/false; Returns the negation of BEFORE when the - statement PBB has been found. */ - -static inline bool -lst_remove_all_before_excluding_pbb (lst_p loop, poly_bb_p pbb, bool before) -{ - int i; - lst_p l; - - if (!loop || !LST_LOOP_P (loop)) - return before; - - for (i = 0; LST_SEQ (loop).iterate (i, &l);) - if (LST_LOOP_P (l)) - { - before = lst_remove_all_before_excluding_pbb (l, pbb, before); - - if (LST_SEQ (l).length () == 0) - { - LST_SEQ (loop).ordered_remove (i); - free_lst (l); - continue; - } - - i++; - } - else - { - if (before && LST_PBB (l) != pbb) - { - LST_SEQ (loop).ordered_remove (i); - free_lst (l); - continue; - } - - i++; - - if (LST_PBB (l) == pbb) - before = before ? false : true; - } - - return before; -} - /* A SCOP is a Static Control Part of the program, simple enough to be represented in polyhedral form. */ struct scop { /* A SCOP is defined as a SESE region. */ - void *region; + sese region; /* Number of parameters in SCoP. */ graphite_dim_t nb_params; @@ -1355,9 +386,6 @@ struct scop representation. */ vec<poly_bb_p> bbs; - /* Original, transformed and saved schedules. */ - lst_p original_schedule, transformed_schedule, saved_schedule; - /* The context describes known restrictions concerning the parameters and relations in between the parameters. @@ -1390,23 +418,15 @@ struct scop }; #define SCOP_BBS(S) (S->bbs) -#define SCOP_REGION(S) ((sese) S->region) +#define SCOP_REGION(S) (S->region) #define SCOP_CONTEXT(S) (NULL) -#define SCOP_ORIGINAL_SCHEDULE(S) (S->original_schedule) -#define SCOP_TRANSFORMED_SCHEDULE(S) (S->transformed_schedule) -#define SCOP_SAVED_SCHEDULE(S) (S->saved_schedule) #define POLY_SCOP_P(S) (S->poly_scop_p) -extern scop_p new_scop (void *); +extern scop_p new_scop (sese); extern void free_scop (scop_p); extern void free_scops (vec<scop_p> ); extern void print_generated_program (FILE *, scop_p); extern void debug_generated_program (scop_p); -extern void print_scattering_function (FILE *, poly_bb_p, int); -extern void print_scattering_functions (FILE *, scop_p, int); -extern void debug_scattering_function (poly_bb_p, int); -extern void debug_scattering_functions (scop_p, int); -extern int scop_max_loop_depth (scop_p); extern int unify_scattering_dimensions (scop_p); extern bool apply_poly_transforms (scop_p); extern bool graphite_legal_transform (scop_p); @@ -1414,7 +434,7 @@ extern bool graphite_legal_transform (scop_p); /* Set the region of SCOP to REGION. */ static inline void -scop_set_region (scop_p scop, void *region) +scop_set_region (scop_p scop, sese region) { scop->region = region; } @@ -1435,114 +455,9 @@ scop_set_nb_params (scop_p scop, graphite_dim_t nb_params) scop->nb_params = nb_params; } -/* Allocates a new empty poly_scattering structure. */ - -static inline poly_scattering_p -poly_scattering_new (void) -{ - poly_scattering_p res = XNEW (struct poly_scattering); - - res->nb_local_variables = 0; - res->nb_scattering = 0; - return res; -} - -/* Free a poly_scattering structure. */ - -static inline void -poly_scattering_free (poly_scattering_p s) -{ - free (s); -} - -/* Copies S and return a new scattering. */ - -static inline poly_scattering_p -poly_scattering_copy (poly_scattering_p s) -{ - poly_scattering_p res = poly_scattering_new (); - - res->nb_local_variables = s->nb_local_variables; - res->nb_scattering = s->nb_scattering; - return res; -} - -/* Saves the transformed scattering of PBB. */ - -static inline void -store_scattering_pbb (poly_bb_p pbb) -{ - isl_map_free (pbb->saved); - pbb->saved = isl_map_copy (pbb->transformed); -} - -/* Stores the SCOP_TRANSFORMED_SCHEDULE to SCOP_SAVED_SCHEDULE. */ - -static inline void -store_lst_schedule (scop_p scop) -{ - if (SCOP_SAVED_SCHEDULE (scop)) - free_lst (SCOP_SAVED_SCHEDULE (scop)); - - SCOP_SAVED_SCHEDULE (scop) = copy_lst (SCOP_TRANSFORMED_SCHEDULE (scop)); -} - -/* Restores the SCOP_TRANSFORMED_SCHEDULE from SCOP_SAVED_SCHEDULE. */ - -static inline void -restore_lst_schedule (scop_p scop) -{ - if (SCOP_TRANSFORMED_SCHEDULE (scop)) - free_lst (SCOP_TRANSFORMED_SCHEDULE (scop)); - - SCOP_TRANSFORMED_SCHEDULE (scop) = copy_lst (SCOP_SAVED_SCHEDULE (scop)); -} - -/* Saves the scattering for all the pbbs in the SCOP. */ - -static inline void -store_scattering (scop_p scop) -{ - int i; - poly_bb_p pbb; - - for (i = 0; SCOP_BBS (scop).iterate (i, &pbb); i++) - store_scattering_pbb (pbb); - - store_lst_schedule (scop); -} - -/* Restores the scattering of PBB. */ - -static inline void -restore_scattering_pbb (poly_bb_p pbb) -{ - gcc_assert (pbb->saved); - - isl_map_free (pbb->transformed); - pbb->transformed = isl_map_copy (pbb->saved); -} - -/* Restores the scattering for all the pbbs in the SCOP. */ - -static inline void -restore_scattering (scop_p scop) -{ - int i; - poly_bb_p pbb; - - for (i = 0; SCOP_BBS (scop).iterate (i, &pbb); i++) - restore_scattering_pbb (pbb); - - restore_lst_schedule (scop); -} - bool graphite_legal_transform (scop_p); -isl_map *reverse_loop_at_level (poly_bb_p, int); -isl_union_map *reverse_loop_for_pbbs (scop_p, vec<poly_bb_p> , int); __isl_give isl_union_map *extend_schedule (__isl_take isl_union_map *); - void compute_deps (scop_p scop, vec<poly_bb_p> pbbs, isl_union_map **must_raw, diff --git a/gcc/graphite-scop-detection.c b/gcc/graphite-scop-detection.c index b2a4aafdaa0..dbd98428265 100644 --- a/gcc/graphite-scop-detection.c +++ b/gcc/graphite-scop-detection.c @@ -409,8 +409,8 @@ stmt_simple_for_scop_p (basic_block scop_entry, loop_p outermost_loop, { tree op = gimple_op (stmt, i); if (!graphite_can_represent_expr (scop_entry, loop, op) - /* We can not handle REAL_TYPE. Failed for pr39260. */ - || TREE_CODE (TREE_TYPE (op)) == REAL_TYPE) + /* We can only constrain on integer type. */ + || (TREE_CODE (TREE_TYPE (op)) != INTEGER_TYPE)) { if (dump_file && (dump_flags & TDF_DETAILS)) { diff --git a/gcc/graphite-sese-to-poly.c b/gcc/graphite-sese-to-poly.c index fdcc790336c..e64a6fce45f 100644 --- a/gcc/graphite-sese-to-poly.c +++ b/gcc/graphite-sese-to-poly.c @@ -443,18 +443,12 @@ isl_id_for_pbb (scop_p s, poly_bb_p pbb) /* Converts the STATIC_SCHEDULE of PBB into a scattering polyhedron. We generate SCATTERING_DIMENSIONS scattering dimensions. - CLooG 0.15.0 and previous versions require, that all - scattering functions of one CloogProgram have the same number of - scattering dimensions, therefore we allow to specify it. This - should be removed in future versions of CLooG. - The scattering polyhedron consists of these dimensions: scattering, loop_iterators, parameters. Example: | scattering_dimensions = 5 - | used_scattering_dimensions = 3 | nb_iterators = 1 | scop_nb_params = 2 | @@ -475,15 +469,13 @@ isl_id_for_pbb (scop_p s, poly_bb_p pbb) static void build_pbb_scattering_polyhedrons (isl_aff *static_sched, - poly_bb_p pbb, int scattering_dimensions) + poly_bb_p pbb) { int i; - int nb_iterators = pbb_dim_iter_domain (pbb); - int used_scattering_dimensions = nb_iterators * 2 + 1; isl_val *val; isl_space *dc, *dm; - gcc_assert (scattering_dimensions >= used_scattering_dimensions); + int scattering_dimensions = isl_set_dim (pbb->domain, isl_dim_set) * 2 + 1; dc = isl_set_get_space (pbb->domain); dm = isl_space_add_dims (isl_space_from_domain (dc), @@ -577,7 +569,6 @@ build_scop_scattering (scop_p scop) { gimple_bb_p gbb = PBB_BLACK_BOX (pbb); int prefix; - int nb_scat_dims = pbb_dim_iter_domain (pbb) * 2 + 1; if (previous_gbb) prefix = nb_common_loops (SCOP_REGION (scop), previous_gbb, gbb); @@ -588,7 +579,7 @@ build_scop_scattering (scop_p scop) static_sched = isl_aff_add_coefficient_si (static_sched, isl_dim_in, prefix, 1); - build_pbb_scattering_polyhedrons (static_sched, pbb, nb_scat_dims); + build_pbb_scattering_polyhedrons (static_sched, pbb); } isl_aff_free (static_sched); @@ -604,7 +595,7 @@ extract_affine_chrec (scop_p s, tree e, __isl_take isl_space *space) isl_pw_aff *lhs = extract_affine (s, CHREC_LEFT (e), isl_space_copy (space)); isl_pw_aff *rhs = extract_affine (s, CHREC_RIGHT (e), isl_space_copy (space)); isl_local_space *ls = isl_local_space_from_space (space); - unsigned pos = sese_loop_depth ((sese) s->region, get_chrec_loop (e)) - 1; + unsigned pos = sese_loop_depth (SCOP_REGION (s), get_chrec_loop (e)) - 1; isl_aff *loop = isl_aff_set_coefficient_si (isl_aff_zero_on_domain (ls), isl_dim_in, pos, 1); isl_pw_aff *l = isl_pw_aff_from_aff (loop); @@ -3103,7 +3094,7 @@ rewrite_commutative_reductions_out_of_ssa (scop_p scop) } /* Can all ivs be represented by a signed integer? - As CLooG might generate negative values in its expressions, signed loop ivs + As ISL might generate negative values in its expressions, signed loop ivs are required in the backend. */ static bool @@ -3149,9 +3140,7 @@ build_poly_scop (scop_p scop) build_scop_bbs (scop); - /* FIXME: This restriction is needed to avoid a problem in CLooG. - Once CLooG is fixed, remove this guard. Anyways, it makes no - sense to optimize a scop containing only PBBs that do not belong + /* Do not optimize a scop containing only PBBs that do not belong to any loops. */ if (nb_pbbs_in_loops (scop) == 0) return; @@ -3182,7 +3171,6 @@ build_poly_scop (scop_p scop) rewrite_cross_bb_scalar_deps_out_of_ssa (scop); build_scop_drs (scop); - scop_to_lst (scop); build_scop_scattering (scop); /* This SCoP has been translated to the polyhedral diff --git a/gcc/graphite.c b/gcc/graphite.c index 9b9ab887287..36b97a71e3f 100644 --- a/gcc/graphite.c +++ b/gcc/graphite.c @@ -25,12 +25,7 @@ along with GCC; see the file COPYING3. If not see An early description of this pass can be found in the GCC Summit'06 paper "GRAPHITE: Polyhedral Analyses and Optimizations for GCC". The wiki page http://gcc.gnu.org/wiki/Graphite contains pointers to - the related work. - - One important document to read is CLooG's internal manual: - http://repo.or.cz/w/cloog-ppl.git?a=blob_plain;f=doc/cloog.texi;hb=HEAD - that describes the data structure of loops used in this file, and - the functions that are used for transforming the code. */ + the related work. */ #include "config.h" @@ -286,6 +281,9 @@ graphite_transform_loops (void) scop->ctx = ctx; build_poly_scop (scop); + if (dump_file && dump_flags) + print_scop (dump_file, scop, 3); + if (POLY_SCOP_P (scop) && apply_poly_transforms (scop) && graphite_regenerate_ast_isl (scop)) @@ -326,13 +324,9 @@ gate_graphite_transforms (void) { /* Enable -fgraphite pass if any one of the graphite optimization flags is turned on. */ - if (flag_loop_block - || flag_loop_interchange - || flag_loop_strip_mine - || flag_graphite_identity + if (flag_graphite_identity || flag_loop_parallelize_all - || flag_loop_optimize_isl - || flag_loop_unroll_jam) + || flag_loop_optimize_isl) flag_graphite = 1; return flag_graphite != 0; diff --git a/gcc/hwint.h b/gcc/hwint.h index 3793986cf6c..4acbf8e79ca 100644 --- a/gcc/hwint.h +++ b/gcc/hwint.h @@ -244,11 +244,27 @@ sext_hwi (HOST_WIDE_INT src, unsigned int prec) if (prec == HOST_BITS_PER_WIDE_INT) return src; else +#if defined (__GNUC__) { + /* Take the faster path if the implementation-defined bits it's relying + on are implemented the way we expect them to be. Namely, conversion + from unsigned to signed preserves bit pattern, and right shift of + a signed value propagates the sign bit. + We have to convert from signed to unsigned and back, because when left + shifting signed values, any overflow is undefined behaviour. */ gcc_checking_assert (prec < HOST_BITS_PER_WIDE_INT); int shift = HOST_BITS_PER_WIDE_INT - prec; - return (src << shift) >> shift; + return ((HOST_WIDE_INT) ((unsigned HOST_WIDE_INT) src << shift)) >> shift; } +#else + { + /* Fall back to the slower, well defined path otherwise. */ + gcc_checking_assert (prec < HOST_BITS_PER_WIDE_INT); + HOST_WIDE_INT sign_mask = HOST_WIDE_INT_1 << (prec - 1); + HOST_WIDE_INT value_mask = (HOST_WIDE_INT_1U << prec) - HOST_WIDE_INT_1U; + return (((src & value_mask) ^ sign_mask) - sign_mask); + } +#endif } /* Zero extend SRC starting from PREC. */ diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c index a46efec6059..157a716ff6e 100644 --- a/gcc/ifcvt.c +++ b/gcc/ifcvt.c @@ -53,25 +53,15 @@ #include "tree-pass.h" #include "dbgcnt.h" #include "shrink-wrap.h" +#include "rtl-iter.h" #include "ifcvt.h" -#ifndef HAVE_incscc -#define HAVE_incscc 0 -#endif -#ifndef HAVE_decscc -#define HAVE_decscc 0 -#endif - #ifndef MAX_CONDITIONAL_EXECUTE #define MAX_CONDITIONAL_EXECUTE \ (BRANCH_COST (optimize_function_for_speed_p (cfun), false) \ + 1) #endif -#ifndef HAVE_cbranchcc4 -#define HAVE_cbranchcc4 0 -#endif - #define IFCVT_MULTIPLE_DUMPS 1 #define NULL_BLOCK ((basic_block) NULL) @@ -79,6 +69,9 @@ /* True if after combine pass. */ static bool ifcvt_after_combine; +/* True if the target has the cbranchcc4 optab. */ +static bool have_cbranchcc4; + /* # of IF-THEN or IF-THEN-ELSE blocks we looked at */ static int num_possible_if_blocks; @@ -816,8 +809,17 @@ struct noce_if_info form as well. */ bool then_else_reversed; + /* True if the contents of then_bb and else_bb are a + simple single set instruction. */ + bool then_simple; + bool else_simple; + + /* The total rtx cost of the instructions in then_bb and else_bb. */ + unsigned int then_cost; + unsigned int else_cost; + /* Estimated cost of the particular branch instruction. */ - int branch_cost; + unsigned int branch_cost; }; static rtx noce_emit_store_flag (struct noce_if_info *, rtx, int, int); @@ -1014,7 +1016,7 @@ noce_emit_move_insn (rtx x, rtx y) static rtx cc_in_cond (rtx cond) { - if (HAVE_cbranchcc4 && cond + if (have_cbranchcc4 && cond && GET_MODE_CLASS (GET_MODE (XEXP (cond, 0))) == MODE_CC) return XEXP (cond, 0); @@ -1037,6 +1039,10 @@ end_ifcvt_sequence (struct noce_if_info *if_info) set_used_flags (if_info->cond); set_used_flags (if_info->a); set_used_flags (if_info->b); + + for (insn = seq; insn; insn = NEXT_INSN (insn)) + set_used_flags (insn); + unshare_all_rtl_in_chain (seq); end_sequence (); @@ -1054,6 +1060,21 @@ end_ifcvt_sequence (struct noce_if_info *if_info) return seq; } +/* Return true iff the then and else basic block (if it exists) + consist of a single simple set instruction. */ + +static bool +noce_simple_bbs (struct noce_if_info *if_info) +{ + if (!if_info->then_simple) + return false; + + if (if_info->else_bb) + return if_info->else_simple; + + return true; +} + /* Convert "if (a != b) x = a; else x = b" into "x = a" and "if (a == b) x = a; else x = b" into "x = b". */ @@ -1068,6 +1089,9 @@ noce_try_move (struct noce_if_info *if_info) if (code != NE && code != EQ) return FALSE; + if (!noce_simple_bbs (if_info)) + return FALSE; + /* This optimization isn't valid if either A or B could be a NaN or a signed zero. */ if (HONOR_NANS (if_info->x) @@ -1116,6 +1140,9 @@ noce_try_store_flag (struct noce_if_info *if_info) rtx target; rtx_insn *seq; + if (!noce_simple_bbs (if_info)) + return FALSE; + if (CONST_INT_P (if_info->b) && INTVAL (if_info->b) == STORE_FLAG_VALUE && if_info->a == const0_rtx) @@ -1185,6 +1212,9 @@ noce_try_store_flag_constants (struct noce_if_info *if_info) b = XEXP (b, 1); } + if (!noce_simple_bbs (if_info)) + return FALSE; + if (CONST_INT_P (a) && CONST_INT_P (b)) { @@ -1373,6 +1403,9 @@ noce_try_addcc (struct noce_if_info *if_info) rtx_insn *seq; int subtract, normalize; + if (!noce_simple_bbs (if_info)) + return FALSE; + if (GET_CODE (if_info->a) == PLUS && rtx_equal_p (XEXP (if_info->a, 0), if_info->b) && (reversed_comparison_code (if_info->cond, if_info->jump) @@ -1464,6 +1497,9 @@ noce_try_store_flag_mask (struct noce_if_info *if_info) rtx_insn *seq; int reversep; + if (!noce_simple_bbs (if_info)) + return FALSE; + reversep = 0; if ((if_info->branch_cost >= 2 || STORE_FLAG_VALUE == -1) @@ -1557,7 +1593,7 @@ noce_emit_cmove (struct noce_if_info *if_info, rtx x, enum rtx_code code, if (! general_operand (cmp_a, GET_MODE (cmp_a)) || ! general_operand (cmp_b, GET_MODE (cmp_b))) { - if (!(HAVE_cbranchcc4) + if (!have_cbranchcc4 || GET_MODE_CLASS (GET_MODE (cmp_a)) != MODE_CC || cmp_b != const0_rtx) return NULL_RTX; @@ -1632,6 +1668,9 @@ noce_try_cmove (struct noce_if_info *if_info) rtx target; rtx_insn *seq; + if (!noce_simple_bbs (if_info)) + return FALSE; + if ((CONSTANT_P (if_info->a) || register_operand (if_info->a, VOIDmode)) && (CONSTANT_P (if_info->b) || register_operand (if_info->b, VOIDmode))) { @@ -1722,6 +1761,152 @@ noce_try_cmove (struct noce_if_info *if_info) return FALSE; } +/* Helper for bb_valid_for_noce_process_p. Validate that + the rtx insn INSN is a single set that does not set + the conditional register CC and is in general valid for + if-conversion. */ + +static bool +insn_valid_noce_process_p (rtx_insn *insn, rtx cc) +{ + if (!insn + || !NONJUMP_INSN_P (insn) + || (cc && set_of (cc, insn))) + return false; + + rtx sset = single_set (insn); + + /* Currently support only simple single sets in test_bb. */ + if (!sset + || !noce_operand_ok (SET_DEST (sset)) + || !noce_operand_ok (SET_SRC (sset))) + return false; + + return true; +} + + +/* Return true iff the registers that the insns in BB_A set do not + get used in BB_B. */ + +static bool +bbs_ok_for_cmove_arith (basic_block bb_a, basic_block bb_b) +{ + rtx_insn *a_insn; + bitmap bba_sets = BITMAP_ALLOC (®_obstack); + + df_ref def; + df_ref use; + + FOR_BB_INSNS (bb_a, a_insn) + { + if (!active_insn_p (a_insn)) + continue; + + rtx sset_a = single_set (a_insn); + + if (!sset_a) + { + BITMAP_FREE (bba_sets); + return false; + } + + /* Record all registers that BB_A sets. */ + FOR_EACH_INSN_DEF (def, a_insn) + bitmap_set_bit (bba_sets, DF_REF_REGNO (def)); + } + + rtx_insn *b_insn; + + FOR_BB_INSNS (bb_b, b_insn) + { + if (!active_insn_p (b_insn)) + continue; + + rtx sset_b = single_set (b_insn); + + if (!sset_b) + { + BITMAP_FREE (bba_sets); + return false; + } + + /* Make sure this is a REG and not some instance + of ZERO_EXTRACT or SUBREG or other dangerous stuff. */ + if (!REG_P (SET_DEST (sset_b))) + { + BITMAP_FREE (bba_sets); + return false; + } + + /* If the insn uses a reg set in BB_A return false. */ + FOR_EACH_INSN_USE (use, b_insn) + { + if (bitmap_bit_p (bba_sets, DF_REF_REGNO (use))) + { + BITMAP_FREE (bba_sets); + return false; + } + } + + } + + BITMAP_FREE (bba_sets); + return true; +} + +/* Emit copies of all the active instructions in BB except the last. + This is a helper for noce_try_cmove_arith. */ + +static void +noce_emit_all_but_last (basic_block bb) +{ + rtx_insn *last = last_active_insn (bb, FALSE); + rtx_insn *insn; + FOR_BB_INSNS (bb, insn) + { + if (insn != last && active_insn_p (insn)) + { + rtx_insn *to_emit = as_a <rtx_insn *> (copy_rtx (insn)); + + emit_insn (PATTERN (to_emit)); + } + } +} + +/* Helper for noce_try_cmove_arith. Emit the pattern TO_EMIT and return + the resulting insn or NULL if it's not a valid insn. */ + +static rtx_insn * +noce_emit_insn (rtx to_emit) +{ + gcc_assert (to_emit); + rtx_insn *insn = emit_insn (to_emit); + + if (recog_memoized (insn) < 0) + return NULL; + + return insn; +} + +/* Helper for noce_try_cmove_arith. Emit a copy of the insns up to + and including the penultimate one in BB if it is not simple + (as indicated by SIMPLE). Then emit LAST_INSN as the last + insn in the block. The reason for that is that LAST_INSN may + have been modified by the preparation in noce_try_cmove_arith. */ + +static bool +noce_emit_bb (rtx last_insn, basic_block bb, bool simple) +{ + if (bb && !simple) + noce_emit_all_but_last (bb); + + if (last_insn && !noce_emit_insn (last_insn)) + return false; + + return true; +} + /* Try more complex cases involving conditional_move. */ static int @@ -1732,9 +1917,12 @@ noce_try_cmove_arith (struct noce_if_info *if_info) rtx x = if_info->x; rtx orig_a, orig_b; rtx_insn *insn_a, *insn_b; + bool a_simple = if_info->then_simple; + bool b_simple = if_info->else_simple; + basic_block then_bb = if_info->then_bb; + basic_block else_bb = if_info->else_bb; rtx target; int is_mem = 0; - int insn_cost; enum rtx_code code; rtx_insn *ifcvt_seq; @@ -1773,27 +1961,22 @@ noce_try_cmove_arith (struct noce_if_info *if_info) insn_a = if_info->insn_a; insn_b = if_info->insn_b; - /* Total insn_rtx_cost should be smaller than branch cost. Exit - if insn_rtx_cost can't be estimated. */ + unsigned int then_cost; + unsigned int else_cost; if (insn_a) - { - insn_cost - = insn_rtx_cost (PATTERN (insn_a), - optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn_a))); - if (insn_cost == 0 || insn_cost > COSTS_N_INSNS (if_info->branch_cost)) - return FALSE; - } + then_cost = if_info->then_cost; else - insn_cost = 0; + then_cost = 0; if (insn_b) - { - insn_cost - += insn_rtx_cost (PATTERN (insn_b), - optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn_b))); - if (insn_cost == 0 || insn_cost > COSTS_N_INSNS (if_info->branch_cost)) - return FALSE; - } + else_cost = if_info->else_cost; + else + else_cost = 0; + + /* We're going to execute one of the basic blocks anyway, so + bail out if the most expensive of the two blocks is unacceptable. */ + if (MAX (then_cost, else_cost) > COSTS_N_INSNS (if_info->branch_cost)) + return FALSE; /* Possibly rearrange operands to make things come out more natural. */ if (reversed_comparison_code (if_info->cond, if_info->jump) != UNKNOWN) @@ -1809,26 +1992,36 @@ noce_try_cmove_arith (struct noce_if_info *if_info) code = reversed_comparison_code (if_info->cond, if_info->jump); std::swap (a, b); std::swap (insn_a, insn_b); + std::swap (a_simple, b_simple); + std::swap (then_bb, else_bb); } } + if (!a_simple && then_bb && !b_simple && else_bb + && (!bbs_ok_for_cmove_arith (then_bb, else_bb) + || !bbs_ok_for_cmove_arith (else_bb, then_bb))) + return FALSE; + start_sequence (); orig_a = a; orig_b = b; + rtx emit_a = NULL_RTX; + rtx emit_b = NULL_RTX; + /* If either operand is complex, load it into a register first. The best way to do this is to copy the original insn. In this way we preserve any clobbers etc that the insn may have had. This is of course not possible in the IS_MEM case. */ + if (! general_operand (a, GET_MODE (a))) { - rtx_insn *insn; if (is_mem) { rtx reg = gen_reg_rtx (GET_MODE (a)); - insn = emit_insn (gen_rtx_SET (reg, a)); + emit_a = gen_rtx_SET (reg, a); } else if (! insn_a) goto end_seq_and_fail; @@ -1838,49 +2031,58 @@ noce_try_cmove_arith (struct noce_if_info *if_info) rtx_insn *copy_of_a = as_a <rtx_insn *> (copy_rtx (insn_a)); rtx set = single_set (copy_of_a); SET_DEST (set) = a; - insn = emit_insn (PATTERN (copy_of_a)); + + emit_a = PATTERN (copy_of_a); } - if (recog_memoized (insn) < 0) - goto end_seq_and_fail; } + if (! general_operand (b, GET_MODE (b))) { - rtx pat; - rtx_insn *last; - rtx_insn *new_insn; - if (is_mem) { rtx reg = gen_reg_rtx (GET_MODE (b)); - pat = gen_rtx_SET (reg, b); + emit_b = gen_rtx_SET (reg, b); } else if (! insn_b) goto end_seq_and_fail; else { b = gen_reg_rtx (GET_MODE (b)); - rtx_insn *copy_of_insn_b = as_a <rtx_insn *> (copy_rtx (insn_b)); - rtx set = single_set (copy_of_insn_b); + rtx_insn *copy_of_b = as_a <rtx_insn *> (copy_rtx (insn_b)); + rtx set = single_set (copy_of_b); + SET_DEST (set) = b; - pat = PATTERN (copy_of_insn_b); + emit_b = PATTERN (copy_of_b); } + } - /* If insn to set up A clobbers any registers B depends on, try to - swap insn that sets up A with the one that sets up B. If even - that doesn't help, punt. */ - last = get_last_insn (); - if (last && modified_in_p (orig_b, last)) - { - new_insn = emit_insn_before (pat, get_insns ()); - if (modified_in_p (orig_a, new_insn)) - goto end_seq_and_fail; - } - else - new_insn = emit_insn (pat); + /* If insn to set up A clobbers any registers B depends on, try to + swap insn that sets up A with the one that sets up B. If even + that doesn't help, punt. */ - if (recog_memoized (new_insn) < 0) - goto end_seq_and_fail; - } + if (emit_a && modified_in_p (orig_b, emit_a)) + { + if (modified_in_p (orig_a, emit_b)) + goto end_seq_and_fail; + + if (else_bb && !b_simple) + { + if (!noce_emit_bb (emit_b, else_bb, b_simple)) + goto end_seq_and_fail; + } + + if (!noce_emit_bb (emit_a, then_bb, a_simple)) + goto end_seq_and_fail; + } + else + { + if (!noce_emit_bb (emit_a, then_bb, a_simple)) + goto end_seq_and_fail; + + if (!noce_emit_bb (emit_b, else_bb, b_simple)) + goto end_seq_and_fail; + + } target = noce_emit_cmove (if_info, x, code, XEXP (if_info->cond, 0), XEXP (if_info->cond, 1), a, b); @@ -2052,7 +2254,7 @@ noce_get_alt_condition (struct noce_if_info *if_info, rtx target, } cond = canonicalize_condition (if_info->jump, cond, reverse, - earliest, target, HAVE_cbranchcc4, true); + earliest, target, have_cbranchcc4, true); if (! cond || ! reg_mentioned_p (target, cond)) return NULL; @@ -2084,6 +2286,9 @@ noce_try_minmax (struct noce_if_info *if_info) enum rtx_code code, op; int unsignedp; + if (!noce_simple_bbs (if_info)) + return FALSE; + /* ??? Reject modes with NaNs or signed zeros since we don't know how they will be resolved with an SMIN/SMAX. It wouldn't be too hard to get the target to tell us... */ @@ -2180,6 +2385,9 @@ noce_try_abs (struct noce_if_info *if_info) int negate; bool one_cmpl = false; + if (!noce_simple_bbs (if_info)) + return FALSE; + /* Reject modes with signed zeros. */ if (HONOR_SIGNED_ZEROS (if_info->x)) return FALSE; @@ -2328,6 +2536,9 @@ noce_try_sign_mask (struct noce_if_info *if_info) enum rtx_code code; bool t_unconditional; + if (!noce_simple_bbs (if_info)) + return FALSE; + cond = if_info->cond; code = GET_CODE (cond); m = XEXP (cond, 0); @@ -2411,6 +2622,9 @@ noce_try_bitop (struct noce_if_info *if_info) cond = if_info->cond; code = GET_CODE (cond); + if (!noce_simple_bbs (if_info)) + return FALSE; + /* Check for no else condition. */ if (! rtx_equal_p (x, if_info->b)) return FALSE; @@ -2544,7 +2758,7 @@ noce_get_condition (rtx_insn *jump, rtx_insn **earliest, bool then_else_reversed /* Otherwise, fall back on canonicalize_condition to do the dirty work of manipulating MODE_CC values and COMPARE rtx codes. */ tmp = canonicalize_condition (jump, cond, reverse, earliest, - NULL_RTX, HAVE_cbranchcc4, true); + NULL_RTX, have_cbranchcc4, true); /* We don't handle side-effects in the condition, like handling REG_INC notes and making sure no duplicate conditions are emitted. */ @@ -2661,6 +2875,113 @@ noce_can_store_speculate_p (basic_block top_bb, const_rtx mem) return false; } +/* Return true if X contains a MEM subrtx. */ + +static bool +contains_mem_rtx_p (rtx x) +{ + subrtx_iterator::array_type array; + FOR_EACH_SUBRTX (iter, array, x, ALL) + if (MEM_P (*iter)) + return true; + + return false; +} + +/* Return true iff basic block TEST_BB is valid for noce if-conversion. + The condition used in this if-conversion is in COND. + In practice, check that TEST_BB ends with a single set + x := a and all previous computations + in TEST_BB don't produce any values that are live after TEST_BB. + In other words, all the insns in TEST_BB are there only + to compute a value for x. Put the rtx cost of the insns + in TEST_BB into COST. Record whether TEST_BB is a single simple + set instruction in SIMPLE_P. */ + +static bool +bb_valid_for_noce_process_p (basic_block test_bb, rtx cond, + unsigned int *cost, bool *simple_p) +{ + if (!test_bb) + return false; + + rtx_insn *last_insn = last_active_insn (test_bb, FALSE); + rtx last_set = NULL_RTX; + + rtx cc = cc_in_cond (cond); + + if (!insn_valid_noce_process_p (last_insn, cc)) + return false; + last_set = single_set (last_insn); + + rtx x = SET_DEST (last_set); + rtx_insn *first_insn = first_active_insn (test_bb); + rtx first_set = single_set (first_insn); + + if (!first_set) + return false; + + /* We have a single simple set, that's okay. */ + bool speed_p = optimize_bb_for_speed_p (test_bb); + + if (first_insn == last_insn) + { + *simple_p = noce_operand_ok (SET_DEST (first_set)); + *cost = insn_rtx_cost (first_set, speed_p); + return *simple_p; + } + + rtx_insn *prev_last_insn = PREV_INSN (last_insn); + gcc_assert (prev_last_insn); + + /* For now, disallow setting x multiple times in test_bb. */ + if (REG_P (x) && reg_set_between_p (x, first_insn, prev_last_insn)) + return false; + + bitmap test_bb_temps = BITMAP_ALLOC (®_obstack); + + /* The regs that are live out of test_bb. */ + bitmap test_bb_live_out = df_get_live_out (test_bb); + + int potential_cost = insn_rtx_cost (last_set, speed_p); + rtx_insn *insn; + FOR_BB_INSNS (test_bb, insn) + { + if (insn != last_insn) + { + if (!active_insn_p (insn)) + continue; + + if (!insn_valid_noce_process_p (insn, cc)) + goto free_bitmap_and_fail; + + rtx sset = single_set (insn); + gcc_assert (sset); + + if (contains_mem_rtx_p (SET_SRC (sset)) + || !REG_P (SET_DEST (sset))) + goto free_bitmap_and_fail; + + potential_cost += insn_rtx_cost (sset, speed_p); + bitmap_set_bit (test_bb_temps, REGNO (SET_DEST (sset))); + } + } + + /* If any of the intermediate results in test_bb are live after test_bb + then fail. */ + if (bitmap_intersect_p (test_bb_live_out, test_bb_temps)) + goto free_bitmap_and_fail; + + BITMAP_FREE (test_bb_temps); + *cost = potential_cost; + *simple_p = false; + return true; + + free_bitmap_and_fail: + BITMAP_FREE (test_bb_temps); + return false; +} + /* Given a simple IF-THEN-JOIN or IF-THEN-ELSE-JOIN block, attempt to convert it without using conditional execution. Return TRUE if we were successful at converting the block. */ @@ -2677,7 +2998,6 @@ noce_process_if_block (struct noce_if_info *if_info) rtx_insn *insn_a, *insn_b; rtx set_a, set_b; rtx orig_x, x, a, b; - rtx cc; /* We're looking for patterns of the form @@ -2686,15 +3006,23 @@ noce_process_if_block (struct noce_if_info *if_info) (3) if (...) x = a; // as if with an initial x = x. The later patterns require jumps to be more expensive. - + For the if (...) x = a; else x = b; case we allow multiple insns + inside the then and else blocks as long as their only effect is + to calculate a value for x. ??? For future expansion, look for multiple X in such patterns. */ - /* Look for one of the potential sets. */ - insn_a = first_active_insn (then_bb); - if (! insn_a - || insn_a != last_active_insn (then_bb, FALSE) - || (set_a = single_set (insn_a)) == NULL_RTX) - return FALSE; + if (! bb_valid_for_noce_process_p (then_bb, cond, &if_info->then_cost, + &if_info->then_simple)) + return false; + + if (else_bb + && ! bb_valid_for_noce_process_p (else_bb, cond, &if_info->else_cost, + &if_info->else_simple)) + return false; + + insn_a = last_active_insn (then_bb, FALSE); + set_a = single_set (insn_a); + gcc_assert (set_a); x = SET_DEST (set_a); a = SET_SRC (set_a); @@ -2709,11 +3037,11 @@ noce_process_if_block (struct noce_if_info *if_info) set_b = NULL_RTX; if (else_bb) { - insn_b = first_active_insn (else_bb); - if (! insn_b - || insn_b != last_active_insn (else_bb, FALSE) - || (set_b = single_set (insn_b)) == NULL_RTX - || ! rtx_interchangeable_p (x, SET_DEST (set_b))) + insn_b = last_active_insn (else_bb, FALSE); + set_b = single_set (insn_b); + gcc_assert (set_b); + + if (!rtx_interchangeable_p (x, SET_DEST (set_b))) return FALSE; } else @@ -2789,20 +3117,14 @@ noce_process_if_block (struct noce_if_info *if_info) if_info->a = a; if_info->b = b; - /* Skip it if the instruction to be moved might clobber CC. */ - cc = cc_in_cond (cond); - if (cc - && (set_of (cc, insn_a) - || (insn_b && set_of (cc, insn_b)))) - return FALSE; - /* Try optimizations in some approximation of a useful order. */ /* ??? Should first look to see if X is live incoming at all. If it isn't, we don't need anything but an unconditional set. */ /* Look and see if A and B are really the same. Avoid creating silly cmove constructs that no one will fix up later. */ - if (rtx_interchangeable_p (a, b)) + if (noce_simple_bbs (if_info) + && rtx_interchangeable_p (a, b)) { /* If we have an INSN_B, we don't have to create any new rtl. Just move the instruction that we already have. If we don't have an @@ -4645,6 +4967,8 @@ if_convert (bool after_combine) /* Record whether we are after combine pass. */ ifcvt_after_combine = after_combine; + have_cbranchcc4 = (direct_optab_handler (cbranch_optab, CCmode) + != CODE_FOR_nothing); num_possible_if_blocks = 0; num_updated_if_blocks = 0; num_true_changes = 0; diff --git a/gcc/ipa.c b/gcc/ipa.c index 75e367f0115..6847305536c 100644 --- a/gcc/ipa.c +++ b/gcc/ipa.c @@ -917,6 +917,7 @@ cgraph_build_static_cdtor_1 (char which, tree body, int priority, bool final) TREE_STATIC (decl) = 1; TREE_USED (decl) = 1; DECL_ARTIFICIAL (decl) = 1; + DECL_IGNORED_P (decl) = 1; DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl) = 1; DECL_SAVED_TREE (decl) = body; if (!targetm.have_ctors_dtors && final) diff --git a/gcc/ira.c b/gcc/ira.c index 79827eb6f71..28517c1c3bc 100644 --- a/gcc/ira.c +++ b/gcc/ira.c @@ -1376,9 +1376,8 @@ setup_reg_class_relations (void) /* Output all uniform and important classes into file F. */ static void -print_unform_and_important_classes (FILE *f) +print_uniform_and_important_classes (FILE *f) { - static const char *const reg_class_names[] = REG_CLASS_NAMES; int i, cl; fprintf (f, "Uniform classes:\n"); @@ -1403,7 +1402,6 @@ print_translated_classes (FILE *f, bool pressure_p) enum reg_class *class_translate = (pressure_p ? ira_pressure_class_translate : ira_allocno_class_translate); - static const char *const reg_class_names[] = REG_CLASS_NAMES; int i; fprintf (f, "%s classes:\n", pressure_p ? "Pressure" : "Allocno"); @@ -1420,7 +1418,7 @@ print_translated_classes (FILE *f, bool pressure_p) void ira_debug_allocno_classes (void) { - print_unform_and_important_classes (stderr); + print_uniform_and_important_classes (stderr); print_translated_classes (stderr, false); print_translated_classes (stderr, true); } diff --git a/gcc/jit/ChangeLog b/gcc/jit/ChangeLog index efa0d889203..fae643686f7 100644 --- a/gcc/jit/ChangeLog +++ b/gcc/jit/ChangeLog @@ -1,3 +1,36 @@ +2015-08-25 David Malcolm <dmalcolm@redhat.com> + + * docs/cp/topics/contexts.rst + (gccjit::context::set_bool_use_external_driver): New. + * docs/internals/test-hello-world.exe.log.txt: Update. + * docs/topics/compatibility.rst (LIBGCCJIT_ABI_5): New. + * docs/topics/contexts.rst + (gcc_jit_context_set_bool_use_external_driver): New. + * jit-common.h (enum inner_bool_option): Add + INNER_BOOL_OPTION_USE_EXTERNAL_DRIVER. + * jit-playback.c (gcc_driver_name): New global. + (gcc:jit::playback::context::invoke_driver): Split out second + half into... + (gcc::jit::playback::context::invoke_embedded_driver): ...this new + function, and... + (gcc::jit::playback::context::invoke_external_driver): ...this new + function. + * jit-playback.h + (gcc::jit::playback::context::get_inner_bool_option): New. + (gcc::jit::playback::context::invoke_embedded_driver): New. + (gcc::jit::playback::context::invoke_external_driver): New. + * jit-recording.c (inner_bool_option_reproducer_strings): + Add entry for INNER_BOOL_OPTION_USE_EXTERNAL_DRIVER. + * libgccjit++.h + (gccjit::context::set_bool_use_external_driver): New. + * libgccjit.c (gcc_jit_context_set_bool_use_external_driver): New. + * libgccjit.h (gcc_jit_context_set_bool_use_external_driver): New. + (LIBGCCJIT_HAVE_gcc_jit_context_set_bool_use_external_driver): + New. + * libgccjit.map (LIBGCCJIT_ABI_5): New. + * notes.txt: Show invocation of embedded copy of driver. + * docs/internals/test-hello-world.exe.log.txt: Update + 2015-08-13 David Malcolm <dmalcolm@redhat.com> * jit-playback.c (invoke_driver): On OS X, add diff --git a/gcc/jit/docs/cp/topics/contexts.rst b/gcc/jit/docs/cp/topics/contexts.rst index 162e4aec8f3..05ce2308624 100644 --- a/gcc/jit/docs/cp/topics/contexts.rst +++ b/gcc/jit/docs/cp/topics/contexts.rst @@ -201,6 +201,26 @@ Boolean options #ifdef LIBGCCJIT_HAVE_gcc_jit_context_set_bool_allow_unreachable_blocks +.. function:: void \ + gccjit::context::set_bool_use_external_driver (int bool_value) + + libgccjit internally generates assembler, and uses "driver" code + for converting it to other formats (e.g. shared libraries). + + By default, libgccjit will use an embedded copy of the driver + code. + + This option can be used to instead invoke an external driver executable + as a subprocess; it is a thin wrapper around the C API + :c:func:`gcc_jit_context_set_bool_use_external_driver`. + + This entrypoint was added in :ref:`LIBGCCJIT_ABI_5`; you can test for + its presence using + + .. code-block:: c + + #ifdef LIBGCCJIT_HAVE_gcc_jit_context_set_bool_use_external_driver + Integer options *************** diff --git a/gcc/jit/docs/internals/test-hello-world.exe.log.txt b/gcc/jit/docs/internals/test-hello-world.exe.log.txt index d82038be864..0bab86c25d7 100644 --- a/gcc/jit/docs/internals/test-hello-world.exe.log.txt +++ b/gcc/jit/docs/internals/test-hello-world.exe.log.txt @@ -1,4 +1,4 @@ -JIT: libgccjit (GCC) version 6.0.0 20150723 (experimental) (x86_64-unknown-linux-gnu) +JIT: libgccjit (GCC) version 6.0.0 20150803 (experimental) (x86_64-pc-linux-gnu) JIT: compiled by GNU C version 4.8.3 20140911 (Red Hat 4.8.3-7), GMP version 5.1.2, MPFR version 3.1.2, MPC version 1.0.1 JIT: entering: gcc_jit_context_set_str_option JIT: GCC_JIT_STR_OPTION_PROGNAME: "./test-hello-world.c.exe" @@ -65,6 +65,7 @@ JIT: GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING: false JIT: GCC_JIT_BOOL_OPTION_SELFCHECK_GC: true JIT: GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES: false JIT: gcc_jit_context_set_bool_allow_unreachable_blocks: false +JIT: gcc_jit_context_set_bool_use_external_driver: false JIT: entering: void gcc::jit::recording::context::validate() JIT: exiting: void gcc::jit::recording::context::validate() JIT: entering: gcc::jit::playback::context::context(gcc::jit::recording::context*) @@ -133,7 +134,8 @@ JIT: argv[3]: /tmp/libgccjit-CKq1M9/fake.s JIT: argv[4]: -o JIT: argv[5]: /tmp/libgccjit-CKq1M9/fake.so JIT: argv[6]: -fno-use-linker-plugin -JIT: argv[7]: (null) +JIT: entering: void gcc::jit::playback::context::invoke_embedded_driver(const vec<char*>*) +JIT: exiting: void gcc::jit::playback::context::invoke_embedded_driver(const vec<char*>*) JIT: exiting: void gcc::jit::playback::context::invoke_driver(const char*, const char*, const char*, timevar_id_t, bool, bool) JIT: exiting: void gcc::jit::playback::context::convert_to_dso(const char*) JIT: entering: gcc::jit::result* gcc::jit::playback::context::dlopen_built_dso() diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst index 0a4b4533f7e..e947cad4320 100644 --- a/gcc/jit/docs/topics/compatibility.rst +++ b/gcc/jit/docs/topics/compatibility.rst @@ -128,3 +128,10 @@ entrypoints: * :func:`gcc_jit_timer_pop` * :func:`gcc_jit_timer_print` + +.. _LIBGCCJIT_ABI_5: + +``LIBGCCJIT_ABI_5`` +------------------- +``LIBGCCJIT_ABI_5`` covers the addition of +:func:`gcc_jit_context_set_bool_use_external_driver` diff --git a/gcc/jit/docs/topics/contexts.rst b/gcc/jit/docs/topics/contexts.rst index 1aa319a9a3f..53ceffb6ded 100644 --- a/gcc/jit/docs/topics/contexts.rst +++ b/gcc/jit/docs/topics/contexts.rst @@ -469,6 +469,26 @@ Boolean options #ifdef LIBGCCJIT_HAVE_gcc_jit_context_set_bool_allow_unreachable_blocks +.. function:: void \ + gcc_jit_context_set_bool_use_external_driver (gcc_jit_context *ctxt, \ + int bool_value) + + libgccjit internally generates assembler, and uses "driver" code + for converting it to other formats (e.g. shared libraries). + + By default, libgccjit will use an embedded copy of the driver + code. + + This option can be used to instead invoke an external driver executable + as a subprocess. + + This entrypoint was added in :ref:`LIBGCCJIT_ABI_5`; you can test for + its presence using + + .. code-block:: c + + #ifdef LIBGCCJIT_HAVE_gcc_jit_context_set_bool_use_external_driver + Integer options *************** diff --git a/gcc/jit/jit-common.h b/gcc/jit/jit-common.h index e6fc132c6c2..6400f307d4b 100644 --- a/gcc/jit/jit-common.h +++ b/gcc/jit/jit-common.h @@ -191,6 +191,7 @@ private: enum inner_bool_option { INNER_BOOL_OPTION_ALLOW_UNREACHABLE_BLOCKS, + INNER_BOOL_OPTION_USE_EXTERNAL_DRIVER, NUM_INNER_BOOL_OPTIONS }; diff --git a/gcc/jit/jit-playback.c b/gcc/jit/jit-playback.c index 01cfd4baf13..44c3ce00d98 100644 --- a/gcc/jit/jit-playback.c +++ b/gcc/jit/jit-playback.c @@ -2373,6 +2373,8 @@ convert_to_dso (const char *ctxt_progname) true);/* bool run_linker */ } +static const char * const gcc_driver_name = GCC_DRIVER_NAME; + void playback::context:: invoke_driver (const char *ctxt_progname, @@ -2383,15 +2385,15 @@ invoke_driver (const char *ctxt_progname, bool run_linker) { JIT_LOG_SCOPE (get_logger ()); + + bool embedded_driver + = !get_inner_bool_option (INNER_BOOL_OPTION_USE_EXTERNAL_DRIVER); + /* Currently this lumps together both assembling and linking into TV_ASSEMBLE. */ auto_timevar assemble_timevar (get_timer (), tv_id); - const char *errmsg; auto_argvec argvec; #define ADD_ARG(arg) argvec.safe_push (xstrdup (arg)) - int exit_status = 0; - int err = 0; - const char *gcc_driver_name = GCC_DRIVER_NAME; ADD_ARG (gcc_driver_name); @@ -2425,8 +2427,10 @@ invoke_driver (const char *ctxt_progname, ADD_ARG ("-Wl,-undefined,dynamic_lookup"); #endif - /* pex argv arrays are NULL-terminated. */ - argvec.safe_push (NULL); + if (0) + ADD_ARG ("-v"); + +#undef ADD_ARG /* pex_one's error-handling requires pname to be non-NULL. */ gcc_assert (ctxt_progname); @@ -2435,9 +2439,42 @@ invoke_driver (const char *ctxt_progname, for (unsigned i = 0; i < argvec.length (); i++) get_logger ()->log ("argv[%i]: %s", i, argvec[i]); + if (embedded_driver) + invoke_embedded_driver (&argvec); + else + invoke_external_driver (ctxt_progname, &argvec); +} + +void +playback::context:: +invoke_embedded_driver (const vec <char *> *argvec) +{ + JIT_LOG_SCOPE (get_logger ()); + driver d (true, /* can_finalize */ + false); /* debug */ + int result = d.main (argvec->length (), + const_cast <char **> (argvec->address ())); + d.finalize (); + if (result) + add_error (NULL, "error invoking gcc driver"); +} + +void +playback::context:: +invoke_external_driver (const char *ctxt_progname, + vec <char *> *argvec) +{ + JIT_LOG_SCOPE (get_logger ()); + const char *errmsg; + int exit_status = 0; + int err = 0; + + /* pex argv arrays are NULL-terminated. */ + argvec->safe_push (NULL); + errmsg = pex_one (PEX_SEARCH, /* int flags, */ gcc_driver_name, - const_cast <char *const *> (argvec.address ()), + const_cast <char *const *> (argvec->address ()), ctxt_progname, /* const char *pname */ NULL, /* const char *outname */ NULL, /* const char *errname */ @@ -2464,7 +2501,6 @@ invoke_driver (const char *ctxt_progname, getenv ("PATH")); return; } -#undef ADD_ARG } /* Extract the target-specific MULTILIB_DEFAULTS to diff --git a/gcc/jit/jit-playback.h b/gcc/jit/jit-playback.h index 52e402f9eec..d99db542021 100644 --- a/gcc/jit/jit-playback.h +++ b/gcc/jit/jit-playback.h @@ -177,6 +177,12 @@ public: return m_recording_ctxt->get_bool_option (opt); } + int + get_inner_bool_option (enum inner_bool_option opt) const + { + return m_recording_ctxt->get_inner_bool_option (opt); + } + builtins_manager *get_builtins_manager () const { return m_recording_ctxt->get_builtins_manager (); @@ -280,6 +286,14 @@ protected: result * dlopen_built_dso (); + private: + void + invoke_embedded_driver (const vec <char *> *argvec); + + void + invoke_external_driver (const char *ctxt_progname, + vec <char *> *argvec); + private: ::gcc::jit::recording::context *m_recording_ctxt; diff --git a/gcc/jit/jit-recording.c b/gcc/jit/jit-recording.c index 811d7c03544..70bd171a892 100644 --- a/gcc/jit/jit-recording.c +++ b/gcc/jit/jit-recording.c @@ -1452,7 +1452,8 @@ static const char * const static const char * const inner_bool_option_reproducer_strings[NUM_INNER_BOOL_OPTIONS] = { - "gcc_jit_context_set_bool_allow_unreachable_blocks" + "gcc_jit_context_set_bool_allow_unreachable_blocks", + "gcc_jit_context_set_bool_use_external_driver" }; /* Write the current value of all options to the log file (if any). */ diff --git a/gcc/jit/libgccjit++.h b/gcc/jit/libgccjit++.h index d7e491bbfdc..ef9bef1af47 100644 --- a/gcc/jit/libgccjit++.h +++ b/gcc/jit/libgccjit++.h @@ -124,6 +124,7 @@ namespace gccjit int value); void set_bool_allow_unreachable_blocks (int bool_value); + void set_bool_use_external_driver (int bool_value); void add_command_line_option (const char *optname); @@ -666,6 +667,13 @@ context::set_bool_allow_unreachable_blocks (int bool_value) } inline void +context::set_bool_use_external_driver (int bool_value) +{ + gcc_jit_context_set_bool_use_external_driver (m_inner_ctxt, + bool_value); +} + +inline void context::add_command_line_option (const char *optname) { gcc_jit_context_add_command_line_option (m_inner_ctxt, optname); diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c index eb9200cef5f..55cda6bf890 100644 --- a/gcc/jit/libgccjit.c +++ b/gcc/jit/libgccjit.c @@ -2611,6 +2611,23 @@ gcc_jit_context_set_bool_allow_unreachable_blocks (gcc_jit_context *ctxt, /* Public entrypoint. See description in libgccjit.h. After error-checking, the real work is done by the + gcc::jit::recording::context::set_inner_bool_option method in + jit-recording.c. */ + +extern void +gcc_jit_context_set_bool_use_external_driver (gcc_jit_context *ctxt, + int bool_value) +{ + RETURN_IF_FAIL (ctxt, NULL, NULL, "NULL context"); + JIT_LOG_FUNC (ctxt->get_logger ()); + ctxt->set_inner_bool_option ( + gcc::jit::INNER_BOOL_OPTION_USE_EXTERNAL_DRIVER, + bool_value); +} + +/* Public entrypoint. See description in libgccjit.h. + + After error-checking, the real work is done by the gcc::jit::recording::context::add_command_line_option method in jit-recording.c. */ diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h index 88e4ff31a28..442ad0a62ac 100644 --- a/gcc/jit/libgccjit.h +++ b/gcc/jit/libgccjit.h @@ -278,6 +278,30 @@ gcc_jit_context_set_bool_allow_unreachable_blocks (gcc_jit_context *ctxt, tested for with #ifdef. */ #define LIBGCCJIT_HAVE_gcc_jit_context_set_bool_allow_unreachable_blocks +/* Implementation detail: + libgccjit internally generates assembler, and uses "driver" code + for converting it to other formats (e.g. shared libraries). + + By default, libgccjit will use an embedded copy of the driver + code. + + This option can be used to instead invoke an external driver executable + as a subprocess. + + This entrypoint was added in LIBGCCJIT_ABI_5; you can test for + its presence using + #ifdef LIBGCCJIT_HAVE_gcc_jit_context_set_bool_use_external_driver +*/ + +extern void +gcc_jit_context_set_bool_use_external_driver (gcc_jit_context *ctxt, + int bool_value); + +/* Pre-canned feature macro to indicate the presence of + gcc_jit_context_set_bool_use_external_driver. This can be + tested for with #ifdef. */ +#define LIBGCCJIT_HAVE_gcc_jit_context_set_bool_use_external_driver + /* Add an arbitrary gcc command-line option to the context. The context takes a copy of the string, so the (const char *) optname is not needed anymore after the call diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map index e4302c6d379..a3ced26a562 100644 --- a/gcc/jit/libgccjit.map +++ b/gcc/jit/libgccjit.map @@ -140,3 +140,8 @@ LIBGCCJIT_ABI_4 { gcc_jit_timer_pop; gcc_jit_timer_print; }; + +LIBGCCJIT_ABI_5 { + global: + gcc_jit_context_set_bool_use_external_driver; +} LIBGCCJIT_ABI_4; diff --git a/gcc/jit/notes.txt b/gcc/jit/notes.txt index e92c6651f00..36e05cb7f23 100644 --- a/gcc/jit/notes.txt +++ b/gcc/jit/notes.txt @@ -78,7 +78,13 @@ Client Code . Generated . libgccjit.so . . │ . . . . │ (assuming an in-memory compile): . . │ . . - . . │ . Convert assembler to DSO ("fake.so") + . . --> Convert assembler to DSO, via embedded + . . copy of driver: + . . driver::main () + . . invocation of "as" + . . invocation of "ld" + . . driver::finalize () + . . <---- . . │ . . . . │ . Load DSO (dlopen "fake.so") . . │ . . diff --git a/gcc/loop-iv.c b/gcc/loop-iv.c index 7ad84540938..183f7593838 100644 --- a/gcc/loop-iv.c +++ b/gcc/loop-iv.c @@ -2383,8 +2383,8 @@ iv_number_of_iterations (struct loop *loop, rtx_insn *insn, rtx condition, enum rtx_code cond; machine_mode mode, comp_mode; rtx mmin, mmax, mode_mmin, mode_mmax; - uint64_t s, size, d, inv, max; - int64_t up, down, inc, step_val; + uint64_t s, size, d, inv, max, up, down; + int64_t inc, step_val; int was_sharp = false; rtx old_niter; bool step_is_pow2; @@ -2674,7 +2674,7 @@ iv_number_of_iterations (struct loop *loop, rtx_insn *insn, rtx condition, down = INTVAL (CONST_INT_P (iv0.base) ? iv0.base : mode_mmin); - max = (uint64_t) (up - down) / inc + 1; + max = (up - down) / inc + 1; if (!desc->infinite && !desc->assumptions) record_niter_bound (loop, max, false, true); diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c index ddb91dd49cf..cdb2695acfa 100644 --- a/gcc/lra-constraints.c +++ b/gcc/lra-constraints.c @@ -928,10 +928,12 @@ match_reload (signed char out, signed char *ins, enum reg_class goal_class, they live in the same place. When we create a pseudo we assign value of original pseudo (if any) from which we created the new pseudo. If we create the pseudo from the - input pseudo, the new pseudo will no conflict with the input - pseudo which is wrong when the input pseudo lives after the - insn and as the new pseudo value is changed by the insn - output. Therefore we create the new pseudo from the output. + input pseudo, the new pseudo will have no conflict with the + input pseudo which is wrong when the input pseudo lives after + the insn and as the new pseudo value is changed by the insn + output. Therefore we create the new pseudo from the output + except the case when we have single matched dying input + pseudo. We cannot reuse the current output register because we might have a situation like "a <- a op b", where the constraints @@ -940,8 +942,12 @@ match_reload (signed char out, signed char *ins, enum reg_class goal_class, so that it doesn't clobber the current value of "a". */ new_in_reg = new_out_reg - = lra_create_new_reg_with_unique_value (outmode, out_rtx, - goal_class, ""); + = (ins[1] < 0 && REG_P (in_rtx) + && (int) REGNO (in_rtx) < lra_new_regno_start + && find_regno_note (curr_insn, REG_DEAD, REGNO (in_rtx)) + ? lra_create_new_reg (inmode, in_rtx, goal_class, "") + : lra_create_new_reg_with_unique_value (outmode, out_rtx, + goal_class, "")); } /* In operand can be got from transformations before processing insn constraints. One example of such transformations is subreg diff --git a/gcc/lra-lives.c b/gcc/lra-lives.c index e1398460a77..1da5204da45 100644 --- a/gcc/lra-lives.c +++ b/gcc/lra-lives.c @@ -726,28 +726,33 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p) lra_hard_reg_usage[reg->regno] += freq; call_p = CALL_P (curr_insn); + src_regno = (set != NULL_RTX && REG_P (SET_SRC (set)) + ? REGNO (SET_SRC (set)) : -1); + dst_regno = (set != NULL_RTX && REG_P (SET_DEST (set)) + ? REGNO (SET_DEST (set)) : -1); if (complete_info_p - && set != NULL_RTX - && REG_P (SET_DEST (set)) && REG_P (SET_SRC (set)) + && src_regno >= 0 && dst_regno >= 0 /* Check that source regno does not conflict with destination regno to exclude most impossible preferences. */ - && ((((src_regno = REGNO (SET_SRC (set))) >= FIRST_PSEUDO_REGISTER - && ! sparseset_bit_p (pseudos_live, src_regno)) + && (((src_regno >= FIRST_PSEUDO_REGISTER + && (! sparseset_bit_p (pseudos_live, src_regno) + || (dst_regno >= FIRST_PSEUDO_REGISTER + && lra_reg_val_equal_p (src_regno, + lra_reg_info[dst_regno].val, + lra_reg_info[dst_regno].offset)))) || (src_regno < FIRST_PSEUDO_REGISTER && ! TEST_HARD_REG_BIT (hard_regs_live, src_regno))) /* It might be 'inheritance pseudo <- reload pseudo'. */ || (src_regno >= lra_constraint_new_regno_start - && ((int) REGNO (SET_DEST (set)) - >= lra_constraint_new_regno_start) + && dst_regno >= lra_constraint_new_regno_start /* Remember to skip special cases where src/dest regnos are the same, e.g. insn SET pattern has matching constraints like =r,0. */ - && src_regno != (int) REGNO (SET_DEST (set))))) + && src_regno != dst_regno))) { int hard_regno = -1, regno = -1; - dst_regno = REGNO (SET_DEST (set)); if (dst_regno >= lra_constraint_new_regno_start && src_regno >= lra_constraint_new_regno_start) { diff --git a/gcc/lra.c b/gcc/lra.c index 8ced164f646..a836cab630f 100644 --- a/gcc/lra.c +++ b/gcc/lra.c @@ -585,7 +585,7 @@ finish_insn_regs (void) /* Map INSN_CODE -> the static insn data. This info is valid during all translation unit. */ -struct lra_static_insn_data *insn_code_data[LAST_INSN_CODE]; +struct lra_static_insn_data *insn_code_data[NUM_INSN_CODES]; /* Debug insns are represented as a special insn with one input operand which is RTL expression in var_location. */ @@ -631,9 +631,7 @@ init_insn_code_data_once (void) static void finish_insn_code_data_once (void) { - int i; - - for (i = 0; i < LAST_INSN_CODE; i++) + for (unsigned int i = 0; i < NUM_INSN_CODES; i++) { if (insn_code_data[i] != NULL) free (insn_code_data[i]); @@ -650,7 +648,7 @@ get_static_insn_data (int icode, int nop, int ndup, int nalt) struct lra_static_insn_data *data; size_t n_bytes; - lra_assert (icode < LAST_INSN_CODE); + lra_assert (icode < (int) NUM_INSN_CODES); if (icode >= 0 && (data = insn_code_data[icode]) != NULL) return data; lra_assert (nop >= 0 && ndup >= 0 && nalt >= 0); diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c index 2eb80511b91..07018ecb904 100644 --- a/gcc/lto-streamer-in.c +++ b/gcc/lto-streamer-in.c @@ -171,6 +171,8 @@ lto_location_cache::cmp_loc (const void *pa, const void *pb) } if (a->file != b->file) return strcmp (a->file, b->file); + if (a->sysp != b->sysp) + return a->sysp ? 1 : -1; if (a->line != b->line) return a->line - b->line; return a->col - b->col; @@ -194,7 +196,7 @@ lto_location_cache::apply_location_cache () if (current_file != loc.file) linemap_add (line_table, prev_file ? LC_RENAME : LC_ENTER, - false, loc.file, loc.line); + loc.sysp, loc.file, loc.line); else if (current_line != loc.line) { int max = loc.col; @@ -251,6 +253,7 @@ lto_location_cache::input_location (location_t *loc, struct bitpack_d *bp, static const char *stream_file; static int stream_line; static int stream_col; + static bool stream_sysp; bool file_change, line_change, column_change; gcc_assert (current_cache == this); @@ -268,7 +271,10 @@ lto_location_cache::input_location (location_t *loc, struct bitpack_d *bp, column_change = bp_unpack_value (bp, 1); if (file_change) - stream_file = canon_file_name (bp_unpack_string (data_in, bp)); + { + stream_file = canon_file_name (bp_unpack_string (data_in, bp)); + stream_sysp = bp_unpack_value (bp, 1); + } if (line_change) stream_line = bp_unpack_var_len_unsigned (bp); @@ -280,13 +286,14 @@ lto_location_cache::input_location (location_t *loc, struct bitpack_d *bp, streaming. */ if (current_file == stream_file && current_line == stream_line - && current_col == stream_col) + && current_col == stream_col && current_sysp == stream_sysp) { *loc = current_loc; return; } - struct cached_location entry = {stream_file, loc, stream_line, stream_col}; + struct cached_location entry + = {stream_file, loc, stream_line, stream_col, stream_sysp}; loc_cache.safe_push (entry); } diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c index 3ca88556638..b6bc515201d 100644 --- a/gcc/lto-streamer-out.c +++ b/gcc/lto-streamer-out.c @@ -191,8 +191,12 @@ lto_output_location (struct output_block *ob, struct bitpack_d *bp, bp_pack_value (bp, ob->current_col != xloc.column, 1); if (ob->current_file != xloc.file) - bp_pack_string (ob, bp, xloc.file, true); + { + bp_pack_string (ob, bp, xloc.file, true); + bp_pack_value (bp, xloc.sysp, 1); + } ob->current_file = xloc.file; + ob->current_sysp = xloc.sysp; if (ob->current_line != xloc.line) bp_pack_var_len_unsigned (bp, xloc.line); diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h index 66a824e19b2..21c41c5a621 100644 --- a/gcc/lto-streamer.h +++ b/gcc/lto-streamer.h @@ -345,6 +345,7 @@ private: const char *file; location_t *loc; int line, col; + bool sysp; }; /* The location cache. */ @@ -364,6 +365,7 @@ private: const char *current_file; int current_line; int current_col; + bool current_sysp; location_t current_loc; }; @@ -711,6 +713,7 @@ struct output_block const char *current_file; int current_line; int current_col; + bool current_sysp; /* Cache of nodes written in this section. */ struct streamer_tree_cache_d *writer_cache; diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog index bce03464fec..8d3c83f2226 100644 --- a/gcc/lto/ChangeLog +++ b/gcc/lto/ChangeLog @@ -1,3 +1,21 @@ +2015-08-31 Richard Biener <rguenther@suse.de> + + * lto.c (compare_tree_sccs_1): Compare DECL_ABSTRACT_ORIGIN. + * lto-symtab.c (lto_symtab_merge): Merge DECL_POSSIBLY_INLINED flag. + (lto_symtab_prevailing_decl): Do not replace a decl that didn't + participate in merging with something else. + +2015-08-31 Richard Biener <rguenther@suse.de> + + * lto-symtab.c (lto_symtab_prevailing_decl): Remove redundant + test, do not replace a non-builtin with a builtin. + * lto.c (compare_tree_sccs_1): Do not merge things we stream + as builtins vs. non-builtins. + +2015-08-18 Trevor Saunders <tbsaunde@tbsaunde.org> + + * lto.h: Remove useless typedefs. + 2015-07-15 Andrew MacLeod <amacleod@redhat.com> * lto.c: Remove redundant includes. diff --git a/gcc/lto/lto-symtab.c b/gcc/lto/lto-symtab.c index 979579f4f16..c77ae947c32 100644 --- a/gcc/lto/lto-symtab.c +++ b/gcc/lto/lto-symtab.c @@ -312,6 +312,11 @@ lto_symtab_merge (symtab_node *prevailing, symtab_node *entry) if (TREE_CODE (decl) == FUNCTION_DECL) { + /* Merge decl state in both directions, we may still end up using + the new decl. */ + DECL_POSSIBLY_INLINED (prevailing_decl) |= DECL_POSSIBLY_INLINED (decl); + DECL_POSSIBLY_INLINED (decl) |= DECL_POSSIBLY_INLINED (prevailing_decl); + if (warn_type_compatibility_p (TREE_TYPE (prevailing_decl), TREE_TYPE (decl))) return false; @@ -798,9 +803,16 @@ lto_symtab_prevailing_decl (tree decl) if (TREE_CODE (decl) == FUNCTION_DECL && DECL_ABSTRACT_P (decl)) return decl; - /* Likewise builtins are their own prevailing decl. This preserves - non-builtin vs. builtin uses from compile-time. */ - if (TREE_CODE (decl) == FUNCTION_DECL && DECL_BUILT_IN (decl)) + /* When decl did not participate in symbol resolution leave it alone. + This can happen when we streamed the decl as abstract origin + from the block tree of inlining a partially inlined function. + If all, the split function and the original function end up + optimized away early we do not put the abstract origin into the + ltrans boundary and we'll end up ICEing in + dwarf2out.c:gen_inlined_subroutine_die because we eventually + replace a decl with DECL_POSSIBLY_INLINED set with one without. */ + if (TREE_CODE (decl) == FUNCTION_DECL + && ! cgraph_node::get (decl)) return decl; /* Ensure DECL_ASSEMBLER_NAME will not set assembler name. */ @@ -811,5 +823,9 @@ lto_symtab_prevailing_decl (tree decl) if (!ret) return decl; + /* Do not replace a non-builtin with a builtin. */ + if (is_builtin_fn (ret->decl)) + return decl; + return ret->decl; } diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c index 7ec4c08a39e..4bb0aafcb7d 100644 --- a/gcc/lto/lto.c +++ b/gcc/lto/lto.c @@ -1054,8 +1054,10 @@ compare_tree_sccs_1 (tree t1, tree t2, tree **map) return false; - /* We don't want to compare locations, so there is nothing do compare - for TS_DECL_MINIMAL. */ + /* We want to compare locations up to the point where it makes + a difference for streaming - thus whether the decl is builtin or not. */ + if (CODE_CONTAINS_STRUCT (code, TS_DECL_MINIMAL)) + compare_values (streamer_handle_as_builtin_p); if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON)) { @@ -1303,6 +1305,7 @@ compare_tree_sccs_1 (tree t1, tree t2, tree **map) compare_tree_edges (DECL_SIZE (t1), DECL_SIZE (t2)); compare_tree_edges (DECL_SIZE_UNIT (t1), DECL_SIZE_UNIT (t2)); compare_tree_edges (DECL_ATTRIBUTES (t1), DECL_ATTRIBUTES (t2)); + compare_tree_edges (DECL_ABSTRACT_ORIGIN (t1), DECL_ABSTRACT_ORIGIN (t2)); if ((code == VAR_DECL || code == PARM_DECL) && DECL_HAS_VALUE_EXPR_P (t1)) diff --git a/gcc/machmode.h b/gcc/machmode.h index 6575517d132..d51f115c3d5 100644 --- a/gcc/machmode.h +++ b/gcc/machmode.h @@ -225,12 +225,28 @@ extern const unsigned char mode_inner[NUM_MACHINE_MODES]; /* Get the size in bytes or bits of the basic parts of an object of mode MODE. */ -#define GET_MODE_UNIT_SIZE(MODE) GET_MODE_SIZE (GET_MODE_INNER (MODE)) +extern CONST_MODE_UNIT_SIZE unsigned char mode_unit_size[NUM_MACHINE_MODES]; +#if GCC_VERSION >= 4001 +#define GET_MODE_UNIT_SIZE(MODE) \ + ((unsigned char) (__builtin_constant_p (MODE) \ + ? mode_unit_size_inline (MODE) : mode_unit_size[MODE])) +#else +#define GET_MODE_UNIT_SIZE(MODE) mode_unit_size[MODE] +#endif #define GET_MODE_UNIT_BITSIZE(MODE) \ ((unsigned short) (GET_MODE_UNIT_SIZE (MODE) * BITS_PER_UNIT)) -#define GET_MODE_UNIT_PRECISION(MODE) GET_MODE_PRECISION (GET_MODE_INNER (MODE)) +extern const unsigned short mode_unit_precision[NUM_MACHINE_MODES]; +#if GCC_VERSION >= 4001 +#define GET_MODE_UNIT_PRECISION(MODE) \ + ((unsigned short) (__builtin_constant_p (MODE) \ + ? mode_unit_precision_inline (MODE)\ + : mode_unit_precision[MODE])) +#else +#define GET_MODE_UNIT_PRECISION(MODE) mode_unit_precision[MODE] +#endif + /* Get the number of units in the object. */ diff --git a/gcc/match.pd b/gcc/match.pd index 71f4127e300..fb4b342d31d 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -28,6 +28,7 @@ along with GCC; see the file COPYING3. If not see integer_onep integer_zerop integer_all_onesp integer_minus_onep integer_each_onep integer_truep integer_nonzerop real_zerop real_onep real_minus_onep + zerop CONSTANT_CLASS_P tree_expr_nonnegative_p integer_pow2p @@ -55,9 +56,11 @@ along with GCC; see the file COPYING3. If not see (define_operator_list POW10 BUILT_IN_POW10F BUILT_IN_POW10 BUILT_IN_POW10L) (define_operator_list SQRT BUILT_IN_SQRTF BUILT_IN_SQRT BUILT_IN_SQRTL) (define_operator_list CBRT BUILT_IN_CBRTF BUILT_IN_CBRT BUILT_IN_CBRTL) -(define_operator_list COS BUILT_IN_COS BUILT_IN_COSL BUILT_IN_COSF) -(define_operator_list COSH BUILT_IN_COSH BUILT_IN_COSHL BUILT_IN_COSHF) - +(define_operator_list SIN BUILT_IN_SINF BUILT_IN_SIN BUILT_IN_SINL) +(define_operator_list COS BUILT_IN_COSF BUILT_IN_COS BUILT_IN_COSL) +(define_operator_list TAN BUILT_IN_TANF BUILT_IN_TAN BUILT_IN_TANL) +(define_operator_list COSH BUILT_IN_COSHF BUILT_IN_COSH BUILT_IN_COSHL) +(define_operator_list CEXPI BUILT_IN_CEXPIF BUILT_IN_CEXPI BUILT_IN_CEXPIL) /* Simplifications of operations with one constant operand and simplifications to constants or single values. */ @@ -1311,6 +1314,36 @@ along with GCC; see the file COPYING3. If not see (imagpart (complex @0 @1)) @1) +/* Sometimes we only care about half of a complex expression. */ +(simplify + (realpart (convert?:s (conj:s @0))) + (convert (realpart @0))) +(simplify + (imagpart (convert?:s (conj:s @0))) + (convert (negate (imagpart @0)))) +(for part (realpart imagpart) + (for op (plus minus) + (simplify + (part (convert?:s@2 (op:s @0 @1))) + (convert (op (part @0) (part @1)))))) +(simplify + (realpart (convert?:s (CEXPI:s @0))) + (convert (COS @0))) +(simplify + (imagpart (convert?:s (CEXPI:s @0))) + (convert (SIN @0))) + +/* conj(conj(x)) -> x */ +(simplify + (conj (convert? (conj @0))) + (if (tree_nop_conversion_p (TREE_TYPE (@0), type)) + (convert @0))) + +/* conj({x,y}) -> {x,-y} */ +(simplify + (conj (convert?:s (complex:s @0 @1))) + (with { tree itype = TREE_TYPE (type); } + (complex (convert:itype @0) (negate (convert:itype @1))))) /* BSWAP simplifications, transforms checked by gcc.dg/builtin-bswap-8.c. */ (for bswap (BUILT_IN_BSWAP16 BUILT_IN_BSWAP32 BUILT_IN_BSWAP64) @@ -1576,7 +1609,7 @@ along with GCC; see the file COPYING3. If not see /* x <= +Inf is always true, if we don't case about NaNs. */ (if (! HONOR_NANS (@0)) { constant_boolean_node (true, type); } - /* x <= +Inf is the same as x == x, i.e. isfinite(x). */ + /* x <= +Inf is the same as x == x, i.e. !isnan(x). */ (eq @0 @0))) /* x == +Inf and x >= +Inf are always equal to x > DBL_MAX. */ (if (code == EQ_EXPR || code == GE_EXPR) @@ -1733,6 +1766,12 @@ along with GCC; see the file COPYING3. If not see (if (tem && !TREE_OVERFLOW (tem)) (scmp @0 { tem; })))))) +/* Convert ABS_EXPR<x> == 0 or ABS_EXPR<x> != 0 to x == 0 or x != 0. */ +(for op (eq ne) + (simplify + (op (abs @0) zerop@1) + (op @0 @1))) + /* From fold_sign_changed_comparison and fold_widened_comparison. */ (for cmp (simple_comparison) (simplify @@ -1839,6 +1878,28 @@ along with GCC; see the file COPYING3. If not see (if (tree_single_nonzero_warnv_p (@0, NULL)) { constant_boolean_node (cmp == NE_EXPR, type); }))) +/* If we have (A & C) == C where C is a power of 2, convert this into + (A & C) != 0. Similarly for NE_EXPR. */ +(for cmp (eq ne) + icmp (ne eq) + (simplify + (cmp (bit_and@2 @0 integer_pow2p@1) @1) + (icmp @2 { build_zero_cst (TREE_TYPE (@0)); }))) + +/* If we have (A & C) != 0 where C is the sign bit of A, convert + this into A < 0. Similarly for (A & C) == 0 into A >= 0. */ +(for cmp (eq ne) + ncmp (ge lt) + (simplify + (cmp (bit_and (convert?@2 @0) integer_pow2p@1) integer_zerop) + (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) + && (TYPE_PRECISION (TREE_TYPE (@0)) + == GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (@0)))) + && element_precision (@2) >= element_precision (@0) + && wi::only_sign_bit_p (@1, element_precision (@0))) + (with { tree stype = signed_type_for (TREE_TYPE (@0)); } + (ncmp (convert:stype @0) { build_zero_cst (stype); }))))) + /* When the addresses are not directly of decls compare base and offset. This implements some remaining parts of fold_comparison address comparisons but still no complete part of it. Still it is good @@ -2006,6 +2067,93 @@ along with GCC; see the file COPYING3. If not see /* fold_builtin_logarithm */ (if (flag_unsafe_math_optimizations) + + /* Simplify sqrt(x) * sqrt(x) -> x. */ + (simplify + (mult (SQRT@1 @0) @1) + (if (!HONOR_SNANS (type)) + @0)) + + /* Simplify sqrt(x) * sqrt(y) -> sqrt(x*y). */ + (for root (SQRT CBRT) + (simplify + (mult (root:s @0) (root:s @1)) + (root (mult @0 @1)))) + + /* Simplify pow(x,y) * pow(x,z) -> pow(x,y+z). */ + (simplify + (mult (POW:s @0 @1) (POW:s @0 @2)) + (POW @0 (plus @1 @2))) + + /* Simplify pow(x,y) * pow(z,y) -> pow(x*z,y). */ + (simplify + (mult (POW:s @0 @1) (POW:s @2 @1)) + (POW (mult @0 @2) @1)) + + /* Simplify expN(x) * expN(y) -> expN(x+y). */ + (for exps (EXP EXP2 EXP10 POW10) + (simplify + (mult (exps:s @0) (exps:s @1)) + (exps (plus @0 @1)))) + + /* Simplify tan(x) * cos(x) -> sin(x). */ + (simplify + (mult:c (TAN:s @0) (COS:s @0)) + (SIN @0)) + + /* Simplify x * pow(x,c) -> pow(x,c+1). */ + (simplify + (mult @0 (POW:s @0 REAL_CST@1)) + (if (!TREE_OVERFLOW (@1)) + (POW @0 (plus @1 { build_one_cst (type); })))) + + /* Simplify sin(x) / cos(x) -> tan(x). */ + (simplify + (rdiv (SIN:s @0) (COS:s @0)) + (TAN @0)) + + /* Simplify cos(x) / sin(x) -> 1 / tan(x). */ + (simplify + (rdiv (COS:s @0) (SIN:s @0)) + (rdiv { build_one_cst (type); } (TAN @0))) + + /* Simplify sin(x) / tan(x) -> cos(x). */ + (simplify + (rdiv (SIN:s @0) (TAN:s @0)) + (if (! HONOR_NANS (@0) + && ! HONOR_INFINITIES (@0)) + (cos @0))) + + /* Simplify tan(x) / sin(x) -> 1.0 / cos(x). */ + (simplify + (rdiv (TAN:s @0) (SIN:s @0)) + (if (! HONOR_NANS (@0) + && ! HONOR_INFINITIES (@0)) + (rdiv { build_one_cst (type); } (COS @0)))) + + /* Simplify pow(x,c) / x -> pow(x,c-1). */ + (simplify + (rdiv (POW:s @0 REAL_CST@1) @0) + (if (!TREE_OVERFLOW (@1)) + (POW @0 (minus @1 { build_one_cst (type); })))) + + /* Simplify a/root(b/c) into a*root(c/b). */ + (for root (SQRT CBRT) + (simplify + (rdiv @0 (root:s (rdiv:s @1 @2))) + (mult @0 (root (rdiv @2 @1))))) + + /* Simplify x/expN(y) into x*expN(-y). */ + (for exps (EXP EXP2 EXP10 POW10) + (simplify + (rdiv @0 (exps:s @1)) + (mult @0 (exps (negate @1))))) + + /* Simplify x / pow (y,z) -> x * pow(y,-z). */ + (simplify + (rdiv @0 (POW:s @1 @2)) + (mult @0 (POW @1 (negate @2)))) + /* Special case, optimize logN(expN(x)) = x. */ (for logs (LOG LOG2 LOG10) exps (EXP EXP2 EXP10) diff --git a/gcc/omp-low.c b/gcc/omp-low.c index c1dc9191c42..36d81288c83 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -3412,6 +3412,12 @@ omp_reduction_init (tree clause, tree type) real_maxval (&min, 1, TYPE_MODE (type)); return build_real (type, min); } + else if (POINTER_TYPE_P (type)) + { + wide_int min + = wi::min_value (TYPE_PRECISION (type), TYPE_SIGN (type)); + return wide_int_to_tree (type, min); + } else { gcc_assert (INTEGRAL_TYPE_P (type)); @@ -3428,6 +3434,12 @@ omp_reduction_init (tree clause, tree type) real_maxval (&max, 0, TYPE_MODE (type)); return build_real (type, max); } + else if (POINTER_TYPE_P (type)) + { + wide_int max + = wi::max_value (TYPE_PRECISION (type), TYPE_SIGN (type)); + return wide_int_to_tree (type, max); + } else { gcc_assert (INTEGRAL_TYPE_P (type)); @@ -5417,7 +5429,7 @@ expand_omp_taskreg (struct omp_region *region) basic_block entry_succ_bb = single_succ_p (entry_bb) ? single_succ (entry_bb) : FALLTHRU_EDGE (entry_bb)->dest; - tree arg, narg; + tree arg; gimple parcopy_stmt = NULL; for (gsi = gsi_start_bb (entry_succ_bb); ; gsi_next (&gsi)) @@ -5462,15 +5474,15 @@ expand_omp_taskreg (struct omp_region *region) } else { - /* If we are in ssa form, we must load the value from the default - definition of the argument. That should not be defined now, - since the argument is not used uninitialized. */ - gcc_assert (ssa_default_def (cfun, arg) == NULL); - narg = make_ssa_name (arg, gimple_build_nop ()); - set_ssa_default_def (cfun, arg, narg); - /* ?? Is setting the subcode really necessary ?? */ - gimple_omp_set_subcode (parcopy_stmt, TREE_CODE (narg)); - gimple_assign_set_rhs1 (parcopy_stmt, narg); + tree lhs = gimple_assign_lhs (parcopy_stmt); + gcc_assert (SSA_NAME_VAR (lhs) == arg); + /* We'd like to set the rhs to the default def in the child_fn, + but it's too early to create ssa names in the child_fn. + Instead, we set the rhs to the parm. In + move_sese_region_to_fn, we introduce a default def for the + parm, map the parm to it's default def, and once we encounter + this stmt, replace the parm with the default def. */ + gimple_assign_set_rhs1 (parcopy_stmt, arg); update_stmt (parcopy_stmt); } } @@ -7204,9 +7216,14 @@ expand_omp_for_static_chunk (struct omp_region *region, assign_stmt = gimple_build_assign (vback, t); gsi_insert_before (&gsi, assign_stmt, GSI_SAME_STMT); - t = build2 (fd->loop.cond_code, boolean_type_node, - DECL_P (vback) && TREE_ADDRESSABLE (vback) - ? t : vback, e); + if (tree_int_cst_equal (fd->chunk_size, integer_one_node)) + t = build2 (EQ_EXPR, boolean_type_node, + build_int_cst (itype, 0), + build_int_cst (itype, 1)); + else + t = build2 (fd->loop.cond_code, boolean_type_node, + DECL_P (vback) && TREE_ADDRESSABLE (vback) + ? t : vback, e); gsi_insert_before (&gsi, gimple_build_cond_empty (t), GSI_SAME_STMT); } diff --git a/gcc/optabs.c b/gcc/optabs.c index 97c1d387672..e533e6efb36 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -4488,11 +4488,13 @@ emit_indirect_jump (rtx loc) { if (!targetm.have_indirect_jump ()) sorry ("indirect jumps are not available on this target"); - - struct expand_operand ops[1]; - create_address_operand (&ops[0], loc); - expand_jump_insn (targetm.code_for_indirect_jump, 1, ops); - emit_barrier (); + else + { + struct expand_operand ops[1]; + create_address_operand (&ops[0], loc); + expand_jump_insn (targetm.code_for_indirect_jump, 1, ops); + emit_barrier (); + } } diff --git a/gcc/opts.c b/gcc/opts.c index 32de605314f..f1a9acd7ba0 100644 --- a/gcc/opts.c +++ b/gcc/opts.c @@ -754,6 +754,11 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set, opts->x_flag_opts_finished = true; } + /* We initialize opts->x_flag_stack_protect to -1 so that targets + can set a default value. */ + if (opts->x_flag_stack_protect == -1) + opts->x_flag_stack_protect = DEFAULT_FLAG_SSP; + if (opts->x_optimize == 0) { /* Inlining does not work if not optimizing, diff --git a/gcc/params.def b/gcc/params.def index 4cfe7678760..a7291feb2b6 100644 --- a/gcc/params.def +++ b/gcc/params.def @@ -854,21 +854,6 @@ DEFPARAM (PARAM_LOOP_BLOCK_TILE_SIZE, "size of tiles for loop blocking", 51, 0, 0) -/* Size of unrolling factor for unroll-and-jam. */ - -DEFPARAM (PARAM_LOOP_UNROLL_JAM_SIZE, - "loop-unroll-jam-size", - "size of unrolling factor for unroll-and-jam", - 4, 0, 0) - -/* Size of the band formed by the strip mined dimension and the most inner one for unroll-and-jam. */ - -DEFPARAM (PARAM_LOOP_UNROLL_JAM_DEPTH, - "loop-unroll-jam-depth", - "depth of unrolled loop for unroll-and-jam", - 2, 0, 0) - - /* Maximal number of parameters that we allow in a SCoP. */ DEFPARAM (PARAM_GRAPHITE_MAX_NB_SCOP_PARAMS, diff --git a/gcc/passes.c b/gcc/passes.c index a17a9490650..bd6829ef671 100644 --- a/gcc/passes.c +++ b/gcc/passes.c @@ -318,7 +318,10 @@ rest_of_decl_compilation (tree decl, && !decl_function_context (decl) && !current_function_decl && DECL_SOURCE_LOCATION (decl) != BUILTINS_LOCATION - && !decl_type_context (decl)) + && !decl_type_context (decl) + /* Avoid confusing the debug information machinery when there are + errors. */ + && !seen_error ()) (*debug_hooks->early_global_decl) (decl); } diff --git a/gcc/print-rtl.c b/gcc/print-rtl.c index aacadbb9b44..b541d838057 100644 --- a/gcc/print-rtl.c +++ b/gcc/print-rtl.c @@ -550,7 +550,7 @@ print_rtx (const_rtx in_rtx) } if (flag_dump_unnumbered - || (flag_dump_unnumbered_links && (i == 1 || i == 2) + || (flag_dump_unnumbered_links && i <= 1 && (INSN_P (in_rtx) || NOTE_P (in_rtx) || LABEL_P (in_rtx) || BARRIER_P (in_rtx)))) fputs (" #", outfile); diff --git a/gcc/recog.c b/gcc/recog.c index c595bbdea5c..c032424e06b 100644 --- a/gcc/recog.c +++ b/gcc/recog.c @@ -2441,9 +2441,9 @@ preprocess_constraints (int n_operands, int n_alternatives, instruction ICODE. */ const operand_alternative * -preprocess_insn_constraints (int icode) +preprocess_insn_constraints (unsigned int icode) { - gcc_checking_assert (IN_RANGE (icode, 0, LAST_INSN_CODE)); + gcc_checking_assert (IN_RANGE (icode, 0, NUM_INSN_CODES - 1)); if (this_target_recog->x_op_alt[icode]) return this_target_recog->x_op_alt[icode]; @@ -3018,7 +3018,6 @@ split_all_insns_noflow (void) return 0; } -#ifdef HAVE_peephole2 struct peep2_insn_data { rtx_insn *insn; @@ -3651,7 +3650,6 @@ peephole2_optimize (void) if (peep2_do_cleanup_cfg) cleanup_cfg (CLEANUP_CFG_CHANGED); } -#endif /* HAVE_peephole2 */ /* Common predicates for use with define_bypass. */ @@ -3804,9 +3802,9 @@ if_test_bypass_p (rtx_insn *out_insn, rtx_insn *in_insn) static unsigned int rest_of_handle_peephole2 (void) { -#ifdef HAVE_peephole2 - peephole2_optimize (); -#endif + if (HAVE_peephole2) + peephole2_optimize (); + return 0; } @@ -4120,7 +4118,7 @@ recog_init () } memset (this_target_recog->x_bool_attr_masks, 0, sizeof (this_target_recog->x_bool_attr_masks)); - for (int i = 0; i < LAST_INSN_CODE; ++i) + for (unsigned int i = 0; i < NUM_INSN_CODES; ++i) if (this_target_recog->x_op_alt[i]) { free (this_target_recog->x_op_alt[i]); diff --git a/gcc/recog.h b/gcc/recog.h index ce931ebdf5a..327d6c07494 100644 --- a/gcc/recog.h +++ b/gcc/recog.h @@ -137,7 +137,7 @@ extern void extract_constrain_insn_cached (rtx_insn *); extern void extract_insn_cached (rtx_insn *); extern void preprocess_constraints (int, int, const char **, operand_alternative *); -extern const operand_alternative *preprocess_insn_constraints (int); +extern const operand_alternative *preprocess_insn_constraints (unsigned int); extern void preprocess_constraints (rtx_insn *); extern rtx_insn *peep2_next_insn (int); extern int peep2_regno_dead_p (int, int); @@ -393,8 +393,8 @@ enum bool_attr { /* Target-dependent globals. */ struct target_recog { bool x_initialized; - alternative_mask x_bool_attr_masks[LAST_INSN_CODE][BA_LAST + 1]; - operand_alternative *x_op_alt[LAST_INSN_CODE]; + alternative_mask x_bool_attr_masks[NUM_INSN_CODES][BA_LAST + 1]; + operand_alternative *x_op_alt[NUM_INSN_CODES]; }; extern struct target_recog default_target_recog; diff --git a/gcc/reorg.c b/gcc/reorg.c index 1c60e13167e..cdaa60cda9e 100644 --- a/gcc/reorg.c +++ b/gcc/reorg.c @@ -3445,15 +3445,13 @@ relax_delay_slots (rtx_insn *first) && ! condjump_in_parallel_p (delay_jump_insn) && prev_active_insn (target_label) == insn && ! BARRIER_P (prev_nonnote_insn (target_label)) -#if HAVE_cc0 /* If the last insn in the delay slot sets CC0 for some insn, various code assumes that it is in a delay slot. We could put it back where it belonged and delete the register notes, but it doesn't seem worthwhile in this uncommon case. */ - && ! find_reg_note (XVECEXP (pat, 0, XVECLEN (pat, 0) - 1), - REG_CC_USER, NULL_RTX) -#endif - ) + && (!HAVE_cc0 + || ! find_reg_note (XVECEXP (pat, 0, XVECLEN (pat, 0) - 1), + REG_CC_USER, NULL_RTX))) { rtx_insn *after; int i; diff --git a/gcc/rtl.c b/gcc/rtl.c index b1b485ed60f..3c8bdc10b68 100644 --- a/gcc/rtl.c +++ b/gcc/rtl.c @@ -657,6 +657,31 @@ rtx_equal_p (const_rtx x, const_rtx y) return 1; } +/* Return true if all elements of VEC are equal. */ + +bool +rtvec_all_equal_p (const_rtvec vec) +{ + const_rtx first = RTVEC_ELT (vec, 0); + /* Optimize the important special case of a vector of constants. + The main use of this function is to detect whether every element + of CONST_VECTOR is the same. */ + switch (GET_CODE (first)) + { + CASE_CONST_UNIQUE: + for (int i = 1, n = GET_NUM_ELEM (vec); i < n; ++i) + if (first != RTVEC_ELT (vec, i)) + return false; + return true; + + default: + for (int i = 1, n = GET_NUM_ELEM (vec); i < n; ++i) + if (!rtx_equal_p (first, RTVEC_ELT (vec, i))) + return false; + return true; + } +} + /* Return an indication of which type of insn should have X as a body. In generator files, this can be UNKNOWN if the answer is only known at (GCC) runtime. Otherwise the value is CODE_LABEL, INSN, CALL_INSN diff --git a/gcc/rtl.h b/gcc/rtl.h index 5e0239740a5..ac56133b7e1 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -2678,6 +2678,42 @@ extern unsigned int rtx_size (const_rtx); extern rtx shallow_copy_rtx_stat (const_rtx MEM_STAT_DECL); #define shallow_copy_rtx(a) shallow_copy_rtx_stat (a MEM_STAT_INFO) extern int rtx_equal_p (const_rtx, const_rtx); +extern bool rtvec_all_equal_p (const_rtvec); + +/* Return true if X is a vector constant with a duplicated element value. */ + +inline bool +const_vec_duplicate_p (const_rtx x) +{ + return GET_CODE (x) == CONST_VECTOR && rtvec_all_equal_p (XVEC (x, 0)); +} + +/* Return true if X is a vector constant with a duplicated element value. + Store the duplicated element in *ELT if so. */ + +template <typename T> +inline bool +const_vec_duplicate_p (T x, T *elt) +{ + if (const_vec_duplicate_p (x)) + { + *elt = CONST_VECTOR_ELT (x, 0); + return true; + } + return false; +} + +/* If X is a vector constant with a duplicated element value, return that + element value, otherwise return X. */ + +template <typename T> +inline T +unwrap_const_vec_duplicate (T x) +{ + if (const_vec_duplicate_p (x)) + x = CONST_VECTOR_ELT (x, 0); + return x; +} /* In emit-rtl.c */ extern rtvec gen_rtvec_v (int, rtx *); diff --git a/gcc/sanitizer.def b/gcc/sanitizer.def index 7d149105b99..123b0110536 100644 --- a/gcc/sanitizer.def +++ b/gcc/sanitizer.def @@ -485,11 +485,11 @@ DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_OUT_OF_BOUNDS_ABORT, ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST) DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_NONNULL_ARG, "__ubsan_handle_nonnull_arg", - BT_FN_VOID_PTR_PTRMODE, + BT_FN_VOID_PTR, ATTR_COLD_NOTHROW_LEAF_LIST) DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_NONNULL_ARG_ABORT, "__ubsan_handle_nonnull_arg_abort", - BT_FN_VOID_PTR_PTRMODE, + BT_FN_VOID_PTR, ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST) DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN, "__ubsan_handle_nonnull_return", diff --git a/gcc/target-insns.def b/gcc/target-insns.def index ef8e6b0327c..00e00273cd0 100644 --- a/gcc/target-insns.def +++ b/gcc/target-insns.def @@ -27,15 +27,23 @@ where NAME is the name of the pattern and PROTOTYPE is its C prototype. The prototype should use parameter names of the form "x0", "x1", etc. - Patterns that take no operands should have a prototype "(void)". + for the operands that the .md pattern is required to have, followed by + parameter names of the form "optN" for operands that the .md pattern + may choose to ignore. Patterns that never take operands should have + a prototype "(void)". - Instructions should be documented in md.texi rather than here. */ + Pattern names should be documented in md.texi rather than here. */ DEF_TARGET_INSN (allocate_stack, (rtx x0, rtx x1)) DEF_TARGET_INSN (atomic_test_and_set, (rtx x0, rtx x1, rtx x2)) DEF_TARGET_INSN (builtin_longjmp, (rtx x0)) DEF_TARGET_INSN (builtin_setjmp_receiver, (rtx x0)) DEF_TARGET_INSN (builtin_setjmp_setup, (rtx x0)) DEF_TARGET_INSN (canonicalize_funcptr_for_compare, (rtx x0, rtx x1)) +DEF_TARGET_INSN (call, (rtx x0, rtx opt1, rtx opt2, rtx opt3)) +DEF_TARGET_INSN (call_pop, (rtx x0, rtx opt1, rtx opt2, rtx opt3)) +DEF_TARGET_INSN (call_value, (rtx x0, rtx x1, rtx opt2, rtx opt3, rtx opt4)) +DEF_TARGET_INSN (call_value_pop, (rtx x0, rtx x1, rtx opt2, rtx opt3, + rtx opt4)) DEF_TARGET_INSN (casesi, (rtx x0, rtx x1, rtx x2, rtx x3, rtx x4)) DEF_TARGET_INSN (check_stack, (rtx x0)) DEF_TARGET_INSN (clear_cache, (rtx x0, rtx x1)) @@ -53,6 +61,7 @@ DEF_TARGET_INSN (load_multiple, (rtx x0, rtx x1, rtx x2)) DEF_TARGET_INSN (mem_signal_fence, (rtx x0)) DEF_TARGET_INSN (mem_thread_fence, (rtx x0)) DEF_TARGET_INSN (memory_barrier, (void)) +DEF_TARGET_INSN (movstr, (rtx x0, rtx x1, rtx x2)) DEF_TARGET_INSN (nonlocal_goto, (rtx x0, rtx x1, rtx x2, rtx x3)) DEF_TARGET_INSN (nonlocal_goto_receiver, (void)) DEF_TARGET_INSN (prefetch, (rtx x0, rtx x1, rtx x2)) @@ -68,7 +77,10 @@ DEF_TARGET_INSN (return, (void)) DEF_TARGET_INSN (save_stack_block, (rtx x0, rtx x1)) DEF_TARGET_INSN (save_stack_function, (rtx x0, rtx x1)) DEF_TARGET_INSN (save_stack_nonlocal, (rtx x0, rtx x1)) +DEF_TARGET_INSN (sibcall, (rtx x0, rtx opt1, rtx opt2, rtx opt3)) DEF_TARGET_INSN (sibcall_epilogue, (void)) +DEF_TARGET_INSN (sibcall_value, (rtx x0, rtx x1, rtx opt2, rtx opt3, + rtx opt4)) DEF_TARGET_INSN (simple_return, (void)) DEF_TARGET_INSN (split_stack_prologue, (void)) DEF_TARGET_INSN (split_stack_space_check, (rtx x0, rtx x1)) diff --git a/gcc/targhooks.c b/gcc/targhooks.c index 3eca47e9888..7238c8f8013 100644 --- a/gcc/targhooks.c +++ b/gcc/targhooks.c @@ -1350,11 +1350,7 @@ default_case_values_threshold (void) bool default_have_conditional_execution (void) { -#ifdef HAVE_conditional_execution return HAVE_conditional_execution; -#else - return false; -#endif } /* By default we assume that c99 functions are present at the runtime, diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5ed17b92ecd..1e4de51f671 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,577 @@ +2015-09-01 Kenneth Zadeck <zadeck@naturalbridge.com> + * gcc.c-torture/execute/ieee/20000320-1.c Fixed misplaced test case. + +2015-09-01 Matthew Fortune <matthew.fortune@imgtec.com> + Andrew Bennett <andrew.bennett@imgtec.com> + + * gcc.target/mips/mips.exp (mips-dg-options): Handle the + dependencies between ISA level and compact-branches. + * gcc.target/mips/branch-10.c: Update expected output to allow + compact forms of b/bal. + * gcc.target/mips/branch-11.c: Likewise. + * gcc.target/mips/branch-12.c: Likewise. + * gcc.target/mips/branch-13.c: Likewise. + * gcc.target/mips/branch-3.c: Likewise. + * gcc.target/mips/branch-4.c: Likewise. + * gcc.target/mips/branch-5.c: Likewise. + * gcc.target/mips/branch-6.c: Likewise. + * gcc.target/mips/branch-7.c: Likewise. + * gcc.target/mips/branch-8.c: Likewise. + * gcc.target/mips/branch-9.c: Likewise. + * gcc.target/mips/branch-cost-1.c: Likewise. + * gcc.target/mips/call-1.c: Likewise. + * gcc.target/mips/call-2.c: Likewise. + * gcc.target/mips/call-3.c: Likewise. + * gcc.target/mips/call-4.c: Likewise. + * gcc.target/mips/call-5.c: Likewise. + * gcc.target/mips/call-6.c: Likewise. + * gcc.target/mips/lazy-binding-1.c: Likewise. + * gcc.target/mips/near-far-1.c: Likewise. + * gcc.target/mips/near-far-2.c: Likewise. + * gcc.target/mips/near-far-3.c: Likewise. + * gcc.target/mips/near-far-4.c: Likewise. + * gcc.target/mips/umips-branch-3.c: Ensure the test is + run with compact branches allowed. + * gcc.target/mips/compact-branches-1.c: New file. + * gcc.target/mips/compact-branches-2.c: Likewise. + * gcc.target/mips/compact-branches-3.c: Likewise. + * gcc.target/mips/compact-branches-4.c: Likewise. + * gcc.target/mips/compact-branches-5.c: Likewise. + * gcc.target/mips/compact-branches-6.c: Likewise. + * gcc.target/mips/compact-branches-7.c: Likewise. + +2015-09-01 Steven G. Kargl <kargl@gcc.gnu.org> + + * gfortran.dg/read_dir.f90: XFAIL this testcase on FreeBSD. + Clean-up a created directory if testcase fails. + +2015-09-01 Ilya Enkovich <enkovich.gnu@gmail.com> + + PR target/67405 + * g++.dg/pr67405.C: New test. + +2015-09-01 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + * gcc.dg/vect/no-scevccp-outer-11.c: Don't xfail scan-tree-dump-times. + +2015-09-01 Kyrylo Tkachov <kyrylo.tkachov@arm.com> + + * gcc.dg/ifcvt-1.c: New test. + * gcc.dg/ifcvt-2.c: Likewise. + * gcc.dg/ifcvt-3.c: Likewise. + +2015-09-01 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + PR libfortran/67412 + * gfortran.dg/execute_command_line_2.f90: XFAIL execution on + *-*-solaris2.10. + +2015-09-01 Kyrylo Tkachov <kyrylo.tkachov@arm.com> + + * gcc.target/aarch64/target_attr_crypto_ice_2.c: New test. + +2015-09-01 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/61753 + * g++.dg/other/pr61753.C: New. + +2015-08-31 Marc Glisse <marc.glisse@inria.fr> + + * gcc.dg/tree-ssa/cmp-1.c: New file. + +2015-08-31 Marc Glisse <marc.glisse@inria.fr> + + * gcc.dg/tree-ssa/complex-7.c: New file. + +2015-08-30 Bill Schmidt <wschmidt@linux.vnet.ibm.com> + + * gcc.target/powerpc/swaps-p8-19.c: New test. + +2015-08-29 Jerry DeLisle <jvdelisle@gcc.gnu.org> + + PR fortran/67367 + * gfortran.dg/read_dir.f90: New test. May fail on some platforms. + +2015-08-29 Tom de Vries <tom@codesourcery.com> + + PR tree-optimization/46193 + * gcc.dg/autopar/pr46193.c: New test. + +2015-08-28 Nathan Sidwell <nathan@acm.org> + + * gcc/testsuite/gcc.dg/compat/struct-layout-1_generate.c: Simply + use exit code for failure. + + * gcc/testsuite/gcc.dg/torture/matrix-1.c: Use plain printf. + * gcc/testsuite/gcc.dg/torture/matrix-2.c: Likewise. + * gcc/testsuite/gcc.dg/torture/matrix-5.c: Likewise. + * gcc/testsuite/gcc.dg/torture/matrix-6.c: Likewise. + * gcc/testsuite/gcc.dg/torture/transpose-1.c: Likewise. + * gcc/testsuite/gcc.dg/torture/transpose-2.c: Likewise. + * gcc/testsuite/gcc.dg/torture/transpose-3.c: Likewise. + * gcc/testsuite/gcc.dg/torture/transpose-4.c: Likewise. + * gcc/testsuite/gcc.dg/torture/transpose-5.c: Likewise. + * gcc/testsuite/gcc.dg/torture/transpose-6.c: Likewise. + +2015-08-28 Jeff Law <law@redhat.com> + + PR lto/66752 + * gcc.dg/tree-ssa/pr66752-2.c: New test. + * gcc.dg/torture/pr66752-1.c: New test + * g++.dg/torture/pr66752-2.C: New test. + +2015-08-28 Alan Lawrence <alan.lawrence@arm.com> + Revert: + 2015-08-27 Alan Lawrence <alan.lawrence@arm.com> + + * gcc.dg/tree-ssa/sra-15.c: New. + +2015-08-28 Andrew Bennett <andrew.bennett@imgtec.com> + + * gcc.target/mips/madd-8.c: Add lo register to clobber list. + * gcc.target/mips/msub-8.c: Ditto + +2015-08-27 Bill Schmidt <wschmidt@linux.vnet.ibm.com> + + * lib/target-supports.exp (check-effective_target_vect_double): + Enable for Power targets with VSX hardware available. + * gfortran.dg/vect/O3-pr49957.f: Replace vect_no_align with + vect_no_align && { ! vect_hw_misalign }. + +2015-08-27 Sebastian Pop <s.pop@samsung.com> + + * gcc.dg/graphite/graphite.exp (interchange_files, block_files): + Replaced by opt_files, compile with -floop-nest-optimize. + * g++.dg/graphite/graphite.exp: Same. + * gfortran.dg/graphite/graphite.exp: Same. + * gcc.dg/graphite/block-0.c: Adjust pattern. + * gcc.dg/graphite/block-1.c: Same. + * gcc.dg/graphite/block-3.c: Same. + * gcc.dg/graphite/block-4.c: Same. + * gcc.dg/graphite/block-5.c: Same. + * gcc.dg/graphite/block-6.c: Same. + * gcc.dg/graphite/block-7.c: Same. + * gcc.dg/graphite/block-8.c: Same. + * gcc.dg/graphite/block-pr47654.c: Same. + * gcc.dg/graphite/interchange-0.c: Same. + * gcc.dg/graphite/interchange-1.c: Same. + * gcc.dg/graphite/interchange-10.c: Same. + * gcc.dg/graphite/interchange-11.c: Same. + * gcc.dg/graphite/interchange-12.c: Same. + * gcc.dg/graphite/interchange-13.c: Same. + * gcc.dg/graphite/interchange-14.c: Same. + * gcc.dg/graphite/interchange-15.c: Same. + * gcc.dg/graphite/interchange-3.c: Same. + * gcc.dg/graphite/interchange-4.c: Same. + * gcc.dg/graphite/interchange-5.c: Same. + * gcc.dg/graphite/interchange-6.c: Same. + * gcc.dg/graphite/interchange-7.c: Same. + * gcc.dg/graphite/interchange-8.c: Same. + * gcc.dg/graphite/interchange-9.c: Same. + * gcc.dg/graphite/interchange-mvt.c: Same. + * gcc.dg/graphite/pr37485.c: Same. + * gcc.dg/graphite/uns-block-1.c: Same. + * gcc.dg/graphite/uns-interchange-12.c: Same. + * gcc.dg/graphite/uns-interchange-14.c: Same. + * gcc.dg/graphite/uns-interchange-15.c: Same. + * gcc.dg/graphite/uns-interchange-9.c: Same. + * gcc.dg/graphite/uns-interchange-mvt.c: Same. + * gfortran.dg/graphite/interchange-3.f90: Same. + +2015-08-27 Uros Bizjak <ubizjak@gmail.com> + + PR target/67317 + * gcc.target/i386/pr67317-1.c: New test. + * gcc.target/i386/pr67317-2.c: Ditto. + * gcc.target/i386/pr67317-3.c: Ditto. + * gcc.target/i386/pr67317-4.c: Ditto. + * gcc.target/i386/adx-addcarryx32-1.c: Also scan for adcl. + * gcc.target/i386/adx-addcarryx32-2.c: Also scan for adcq. + +2015-08-27 Pat Haugen <pthaugen@us.ibm.com> + + * gcc.target/powerpc/vec-shr.c: New. + +2015-08-27 Marek Polacek <polacek@redhat.com> + + PR middle-end/67005 + * gcc.dg/torture/pr67005.c: New test. + +2015-08-27 Alan Lawrence <alan.lawrence@arm.com> + + * gcc.dg/tree-ssa/sra-15.c: New. + +2015-08-27 Andre Vieira <andre.simoesdiasvieira@arm.com> + + * gcc.target/aarch64/long_branch_1.c: New test. + +2015-08-27 Dominik Vogt <vogt@linux.vnet.ibm.com> + + * gcc.target/s390/20150826-1.c: New test. + +2015-08-26 Renlin Li <renlin.li@arm.com> + + * gcc.target/aarch64/combine_bfi_1.c: New testcase. + +2015-08-26 Jiong Wang <jiong.wang@arm.com> + + * gcc.target/aarch64/tlsie_tiny_1.c: New testcase. + +2015-08-26 Jiong Wang <jiong.wang@arm.com> + + * gcc.target/aarch64/tlsle_1.x: Rename to tls_1.x + * gcc.target/aarch64/aarch64/tlsle12_1.c: Update source file name. + * gcc.target/aarch64/aarch64/tlsle24_1.c: Likewise. + * gcc.target/aarch64/aarch64/tlsle32_1.c: Likewise. + +2015-08-26 Jiong Wang <jiong.wang@arm.com> + + * lib/target-supports.exp (check_effective_target_aarch64_tlsle32): + New test directive. + * gcc.target/aarch64/tlsle_1.x: New test source. + * gcc.target/aarch64/tlsle12_1.c: New testcase. + * gcc.target/aarch64/tlsle24_1.c: Likewise. + * gcc.target/aarch64/tlsle32_1.c: Likewise. + +2015-08-26 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> + + PR fortran/29600 + * gfortran.dg/shape_8.f90: New test. + +2015-08-25 Marek Polacek <polacek@redhat.com> + + PR middle-end/67330 + * gcc.dg/weak/weak-18.c: New test. + +2015-08-25 David Malcolm <dmalcolm@redhat.com> + + * jit.dg/test-error-pr63969-missing-driver.c: Add call to + gcc_jit_context_set_bool_use_external_driver. + +2015-08-25 Nathan Sidwell <nathan@acm.org> + + * gcc.c-torture/execute/builtins/20010124-1.x: New. + + * gcc.dg/20001117-1.c: Needs return_address. + * gcc.dg/20020415-1.c: Needs alloca. + * gcc.dg/graphite/id-pr44676.c: Needs profiling. + * gcc.dg/graphite/pr60979.c: Needs nonlocal_goto + * gcc.dg/pr63186.c: Needs label_values. + * gcc.dg/torture/pr33848.c: Likwise. + + * lib/target-supports.exp (check_effective_target_fopenacc, + check_effective_target_fopenmp): Disable for nvptx. + * gcc.dg/graphite/run-id-pr47653.c: Disable for nvptx. + * gcc.dg/stack-usage-1.c: Likewise. + * gcc.dg/stack-usage-2.c: Likewise. + * gcc.dg/unused-5.c: Likewise. + * gcc.dg/unwind-1.c: Likewise. + +2015-08-25 Christian Bruel <christian.bruel@st.com> + + * gcc.dg/Wno-frame-address.c: Skip for ARM. + * g++.dg/Wno-frame-address.C: Ditto. + +2015-08-24 Michael Meissner <meissner@linux.vnet.ibm.com> + + PR target/67211 + * g++.dg/pr67211.C: New test. + +2015-08-24 Louis Krupp <louis.krupp@zoho.com> + + PR fortran/62536 + PR fortran/66175 + * gfortran.dg/block_end_error_1.f90: New test. + * gfortran.dg/blocks_nested_incomplete_1.f90: New test. + +2015-08-24 H.J. Lu <hongjiu.lu@intel.com> + + PR target/66821 + * gcc.target/i386/pr66821.c: New test. + +2015-08-24 H.J. Lu <hongjiu.lu@intel.com> + + PR target/67329 + * gcc.target/i386/pr67329.c: New test. + +2015-08-24 Nathan Sidwell <nathan@acm.org> + + * gcc/testsuite/gcc.dg/pr49551.c: Needs -fdata-sections. + + * gcc/testsuite/gcc.dg/pr64935-2.c: Needs scheduling. + + * gcc/testsuite/gcc.dg/torture/pr66101.c: Needs nonlocal goto. + * gcc/testsuite/gcc.dg/torture/pr63738.c: Likewise. + * gcc/testsuite/gcc.dg/torture/pr64728.c: Likewise. + * gcc/testsuite/gcc.dg/pr63748.c: Likewise. + * gcc/testsuite/gcc.dg/20020312-2.c: Likewise. + + * gcc/testsuite/gcc.dg/torture/pr66123.c: Needs label_values. + + * gcc/testsuite/gcc.dg/torture/pr41261.c: Needs profiling. + * gcc/testsuite/gcc.dg/pr26570.c: Likewise. + * gcc/testsuite/gcc.dg/pr61776.c: Likewise. + * gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-11.c: Likewise. + * gcc/testsuite/gcc.dg/gomp/pr34610.c: Likewise. + * gcc/testsuite/gcc.dg/pr54121.c: Likewise. + * gcc/testsuite/gcc.dg/20050325-1.c: Likewise. + * gcc/testsuite/gcc.dg/pr66899.c: Likewise. + * gcc/testsuite/gcc.dg/pr48770.c: Likewise. + * gcc/testsuite/gcc.dg/pr24225.c: Likewise. + + * gcc/testsuite/gcc.dg/pr27531-1.c: Needs io. + * gcc/testsuite/gcc.dg/pr44606.c: Likewise. + + * gcc/testsuite/gcc.dg/tree-ssa/nonzero-1.c: Needs weak. + + * gcc/testsuite/gcc.dg/pr51990.c: Needs alloca. + + * gcc/testsuite/gcc.misc-tests/options.exp: Disable profiling + check for nvptx. + +2015-08-24 Tom de Vries <tom@codesourcery.com> + + PR tree-optimization/65468 + * gcc.dg/gomp/static-chunk-size-one.c: New test. + +2015-08-23 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> + + PR libfortran/54572 + * gfortran.dg/backtrace_1.f90: New test. + +2015-08-23 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> + + PR libfortran/62296 + * gfortran.dg/execute_command_line_2.f90: New test. + +2015-08-23 Tom de Vries <tom@codesourcery.com> + + * gcc.dg/vect/trapv-vect-reduc-4.c: Use vect_no_int_min_max. + * gcc.dg/vect/costmodel/i386/costmodel-vect-reduc-1char.c: Rename + vect_no_int_max to vect_no_int_min_max. + * gcc.dg/vect/costmodel/ppc/costmodel-vect-reduc-1char.c: Same. + * gcc.dg/vect/costmodel/x86_64/costmodel-vect-reduc-1char.c: Same. + * gcc.dg/vect/no-scevccp-noreassoc-slp-reduc-7.c: Same. + * gcc.dg/vect/slp-reduc-4.c: Same. + * gcc.dg/vect/slp-reduc-5.c: Same. + * gcc.dg/vect/vect-125.c: Same. + * gcc.dg/vect/vect-13.c: Same. + * gcc.dg/vect/vect-double-reduc-3.c: Same. + * gcc.dg/vect/vect-reduc-1.c: Same. + * gcc.dg/vect/vect-reduc-1char-big-array.c: Same. + * gcc.dg/vect/vect-reduc-1char.c:Same. + * gcc.dg/vect/vect-reduc-1short.c: Same. + * gcc.dg/vect/vect-reduc-2.c: Same. + * gcc.dg/vect/wrapv-vect-reduc-2char.c: Same. + * gcc.dg/vect/wrapv-vect-reduc-2short.c: Same. + * lib/target-supports.exp: Same. + +2015-08-22 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/63693 + * g++.dg/cpp0x/decltype63.C: New. + +2015-08-22 Nathan Sidwell <nathan@acm.org> + + * c-c++-common/Wsizeof-pointer-memaccess1.c: Require alloca. + * c-c++-common/Wsizeof-pointer-memaccess2.c: Likewise. + * c-c++-common/Wunused-var-8.c: Likewise. + * c-c++-common/gomp/pr61486-2.c: Likewise. + * c-c++-common/Wunused-var-6.c: Likewise. + * c-c++-common/goacc/reduction-1.c: Likewise. + * c-c++-common/goacc/reduction-2.c: Likewise. + * c-c++-common/goacc/reduction-3.c: Likewise. + * c-c++-common/goacc/reduction-4.c: Likewise. + * gcc.dg/builtins-64.c: Likewise. + * gcc.dg/pr59523.c: Likewise. + * gcc.dg/tree-ssa/20080530.c: Likewise. + * gcc.dg/tree-ssa/pr23848-2.c: Likewise. + * gcc.dg/tree-ssa/pr23848-4.c: Likewise. + * gcc.dg/tree-ssa/pr23848-1.c: Likewise. + * gcc.dg/tree-ssa/pr23848-3.c: Likewise. + * gcc.dg/tree-ssa/20030807-2.c: Likewise. + * gcc.dg/pr59011.c: Likewise. + * gcc.dg/uninit-9.c: Likewise. + * gcc.dg/pr61561.c: Likewise. + * gcc.dg/vla-4.c: Likewise. + * gcc.dg/20101010-1.c: Likewise. + * gcc.dg/pr49120.c: Likewise. + * gcc.dg/20030331-2.c: Likewise. + * gcc.dg/compat/struct-by-value-22_main.c: Likewise. + * gcc.dg/pr25682.c: Likewise. + * gcc.dg/guality/guality.c: Likewise. + * gcc.dg/pr27301.c: Likewise. + * gcc.dg/uninit-9-O0.c: Likewise. + * gcc.dg/fold-alloca-1.c: Likewise. + * gcc.dg/pr41470.c: Likewise. + * gcc.dg/pr51491-2.c: Likewise. + * gcc.dg/winline-7.c: Likewise. + * gcc.dg/vla-2.c: Likewise. + * gcc.dg/pr50764.c: Likewise. + * gcc.dg/c99-vla-1.c: Likewise. + * gcc.dg/pr33238.c: Likewise. + * gcc.dg/c99-const-expr-13.c: Likewise. + * gcc.dg/builtin-return-1.c: Likewise. + * gcc.dg/vla-3.c: Likewise. + * gcc.dg/20020415-1.c: Likewise. + * gcc.dg/Wsizeof-pointer-memaccess1.c: Likewise. + * gcc.dg/shrink-wrap-alloca.c: Likewise. + * gcc.dg/Wstrict-aliasing-bogus-vla-1.c: Likewise. + * gcc.dg/torture/calleesave-sse.c: Likewise. + * gcc.dg/torture/Wsizeof-pointer-memaccess1.c: Likewise. + * gcc.dg/gomp/vla-2.c: Likewise. + * gcc.dg/gomp/vla-3.c: Likewise. + * gcc.dg/gomp/vla-4.c: Likewise. + * gcc.dg/gomp/pr30494.c: Likewise. + * gcc.dg/gomp/vla-5.c: Likewise. + * gcc.dg/pr51990-2.c: Likewise. + * gcc.dg/vla-22.c: Likewise. + +2015-08-22 Manuel López-Ibáñez <manu@gcc.gnu.org> + + * gcc.dg/cpp/multiline-2.c: Add column numbers. + * gcc.dg/dollar.c: Likewise. + * gcc.dg/pragma-message.c: Likewise. + * g++.dg/cpp1y/digit-sep-neg.C: Likewise. + * c-c++-common/raw-string-14.c: Likewise. + +2015-08-21 Patrick Palka <ppalka@gcc.gnu.org> + + * g++.old-deja/g++.jason/overload.C: Adjust to preserve original + property that instantiation here is a compile-time error. + +2015-08-21 Paolo Carlini <paolo.carlini@oracle.com> + + * g++.dg/other/pr67065.C: Extend. + +2015-08-21 Nathan Sidwell <nathan@acm.org> + + * lib/target-supports.exp (check_effective_target_freestanding): nvptx + is freestanding. + (check_effective_target_global_constructor): New. + * lib/gcc.exp (gcc_target_compile): Set SIGNAL_SUPPRESS if needed. + * gcc.dg/debug/debug.exp: Skip for nvptx. + * gcc.dg/debug/dwarf2/dwarf2.exp: Likewise. + + * gcc.c-torture/execute/981019-1.c: Ptx assembler bug. + * gcc.c-torture/compile/limits-externdecl.c: Likewise. + * gcc.c-torture/compile/pr33855.c: Likewise. + * gcc.c-torture/compile/920723-1.c: Likewise. + * gcc.c-torture/compile/pr35468.c: Ptx assembler objects to + writing a const. + * gcc.c-torture/compile/mangle-1.c: Ptx assembler objects to . in + label. + * gcc.c-torture/compile/callind.c: Ptx assembler objects to label + 'call'. + + * gcc.c-torture/execute/ieee/mul-subnormal-single-1.c: Make main + prototype normal. + * gcc.c-torture/execute/switch-1.c: Likewise. + + * gcc.c-torture/execute/pr34456.c: Require not freestanding + * gcc.c-torture/execute/printf-1.c: Likewise. + * gcc.c-torture/execute/printf-chk-1.c: Likewise. + * gcc.c-torture/execute/fprintf-1.c: Likewise. + * gcc.c-torture/execute/fprintf-chk-1.c: Likewise. + * gcc.c-torture/execute/vprintf-1.c: Likewise. + * gcc.c-torture/execute/vprintf-chk-1.c: Likewise. + * gcc.c-torture/execute/vfprintf-1.c: Likewise. + * gcc.c-torture/execute/vfprintf-chk-1.c: Likewise. + * gcc.c-torture/execute/builtins/fputs.x: Likewise. + * gcc.c-torture/execute/gofast.c: Likewise. + * gcc.c-torture/execute/complex-6.c: Likewise. + + * gcc.c-torture/execute/builtins/memcpy-chk.x: Require nonlocal goto. + * gcc.c-torture/execute/builtins/memmove-chk.x: Likewise. + * gcc.c-torture/execute/builtins/mempcpy-chk.x: Likewise. + * gcc.c-torture/execute/builtins/memset-chk.x: Likewise. + * gcc.c-torture/execute/builtins/snprintf-chk.x: Likewise. + * gcc.c-torture/execute/builtins/sprintf-chk.x: Likewise. + * gcc.c-torture/execute/builtins/stpcpy-chk.x: Likewise. + * gcc.c-torture/execute/builtins/stpncpy-chk.x: Likewise. + * gcc.c-torture/execute/builtins/strcat-chk.x: Likewise. + * gcc.c-torture/execute/builtins/strcpy-chk.x: Likewise. + * gcc.c-torture/execute/builtins/strncat-chk.x: Likewise. + * gcc.c-torture/execute/builtins/strncpy-chk.x: Likewise. + * gcc.c-torture/execute/builtins/vsnprintf-chk.x: Likewise. + * gcc.c-torture/execute/builtins/vsprintf-chk.x: Likewise. + * gcc.c-torture/execute/builtins/pr23484-chk.x: Likewise. + * gcc.dg/setjmp-1.c: Likewise. + * gcc.dg/cleanup-5.c: Likewise. + * gcc.dg/cleanup-12.c: Likewise. + * gcc.dg/cleanup-13.c: Likewise. + + * gcc.dg/constructor-1.c: Require global ctor. + + * gcc.dg/fork-instrumentation.c: Require profiling. + * gcc.dg/20030107-1.c: Likewise. + * gcc.dg/20030702-1.c: Likewise. + + * gcc.dg/cpp/lexstrng.c: Avoid IO unless debugging. + * gcc.dg/cpp/paste2.c: Likewise. + * gcc.dg/cpp/strify3.c: Likewise. + * gcc.dg/cpp/strify4.c: Likewise. + * gcc.dg/cpp/lexnum.c: Likewise. + * gcc.dg/cpp/digraphs.c: Likewise. + * gcc.dg/cpp/macro1.c: Likewise. + +2015-08-21 Dominik Vogt <vogt@linux.vnet.ibm.com> + + * gcc.target/s390/zvector/vec-load_bndry-1.c: New test. + +2015-08-21 Dominik Vogt <vogt@linux.vnet.ibm.com> + + * lib/gcc-dg.exp: Add extra options for db-final to the command line + only once. + +2015-08-20 Bill Schmidt <wschmidt@linux.vnet.ibm.com> + + * gcc.target/powerpc/altivec-35.c (foo): Add tests for vec_madd. + * gcc.target/powerpc/p8vector-builtin-8.c (foo): Add tests for + vec_vpmsum_be and vec_shasigma_be. + +2015-08-20 Alan Lawrence <alan.lawrence@arm.com> + + * lib/target-supports.exp + (check_effective_target_arm_neon_fp16_ok_nocache): Add flag variants + with -mfp16-format=ieee. + +2015-08-20 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/67065 + * g++.dg/other/pr67065.C: New. + +2015-08-20 Simon Dardis <simon.dardis@imgtec.com> + + * gcc.target/mips/inline-memcpy-1.c: Test for inline expansion of + memcpy. + * gcc.target/mips/inline-memcpy-2.c: Ditto. + * gcc.target/mips/inline-memcpy-3.c: Ditto. + * gcc.target/mips/inline-memcpy-4.c: Ditto. + * gcc.target/mips/inline-memcpy-5.c: Ditto. + +2015-08-19 Jiong Wang <jiong.wang@arm.com> + + * gcc.dg/wide_shift_64_1.c: New testcase. + * gcc.dg/wide_shift_128_1.c: Likewise. + * gcc.target/aarch64/ashlti3_1.c: Likewise. + +2015-08-19 Magnus Granberg <zorry@gentoo.org> + + * lib/target-supports.exp + (check_effective_target_fstack_protector_enabled): New test. + * gcc.target/i386/ssp-default.c: New test. + +2015-08-19 Mikael Morin <mikael@gcc.gnu.org> + + PR fortran/66929 + * gfortran.dg/generic_31.f90: New. + +2015-08-19 Marek Polacek <polacek@redhat.com> + + PR middle-end/67133 + * g++.dg/torture/pr67133.C: New test. + 2015-08-18 Bill Schmidt <wschmidt@vnet.linux.ibm.com> * gcc.target/powerpc/altivec-35.c: New test. @@ -253,7 +827,7 @@ * gcc.target/i386/avx2-vect-shift.c: New test. -2015-08-11 Manuel López-Ibáñez <manu@gcc.gnu.org> +2015-08-11 Manuel López-Ibáñez <manu@gcc.gnu.org> PR c/66098 PR c/66711 @@ -357,7 +931,7 @@ PR fortran/64022 * gfortran.dg/ieee/large_1.f90: Adjust test. -2015-08-05 Manuel López-Ibáñez <manu@gcc.gnu.org> +2015-08-05 Manuel López-Ibáñez <manu@gcc.gnu.org> Jeff Law <law@redhat.com> PR c/16351 @@ -631,7 +1205,7 @@ outer loop. 2015-07-28 Luis Felipe Strano Moraes <luis.strano@gmail.com> - Manuel López-Ibáñez <manu@gcc.gnu.org> + Manuel López-Ibáñez <manu@gcc.gnu.org> * gcc.dg/parm-incomplete-1.c: Update. * gcc.dg/pr18809-1.c: Update. @@ -740,7 +1314,7 @@ * gcc.dg/graphite/uns-interchange-9.c: New test. * gcc.dg/graphite/uns-interchange-mvt.c: New test. -2015-07-24 Manuel López-Ibáñez <manu@gcc.gnu.org> +2015-07-24 Manuel López-Ibáñez <manu@gcc.gnu.org> PR c++/64079 * c-c++-common/Wunused-function-1.c: New. @@ -1629,7 +2203,7 @@ PR tree-optimization/66718 * gcc.dg/vect/vect-126.c: New test. -2015-07-08 Carlos Sánchez de La Lama <csanchezdll@gmail.com> +2015-07-08 Carlos Sánchez de La Lama <csanchezdll@gmail.com> * g++.dg/debug/dwarf2/*.C: generate dwarf-2 debug information even when dwarf-2 is not the default. @@ -2128,7 +2702,7 @@ * g++.dg/cpp0x/constexpr-friend-3.C: New. * g++.dg/cpp0x/constexpr-friend-2.C: Adjust. -2015-06-29 Manuel López-Ibáñez <manu@gcc.gnu.org> +2015-06-29 Manuel López-Ibáñez <manu@gcc.gnu.org> PR fortran/66605 * gfortran.dg/wunused-parameter.f90: New test. @@ -2203,7 +2777,7 @@ * gcc.dg/stack-usage-1.c: Add SIZE values for V850, MN10300, H8300 and M32R targets. -2015-06-24 Manuel López-Ibáñez <manu@gcc.gnu.org> +2015-06-24 Manuel López-Ibáñez <manu@gcc.gnu.org> PR fortran/66528 * gfortran.dg/maxerrors.f90: New test. @@ -3026,7 +3600,7 @@ PR c/66341 * gcc.dg/lvalue-8.c: New test. -2015-06-03 Manuel López-Ibáñez <manu@gcc.gnu.org> +2015-06-03 Manuel López-Ibáñez <manu@gcc.gnu.org> Paolo Carlini <paolo.carlini@oracle.com> PR c++/66130 @@ -3381,7 +3955,7 @@ PR tree-optimization/66142 * gcc.dg/tree-ssa/ssa-fre-44.c: Fixup. -2015-05-28 Lawrence Velázquez <vq@larryv.me> +2015-05-28 Lawrence Velázquez <vq@larryv.me> PR target/63810 * gcc.dg/darwin-minversion-3.c: Update testcase. @@ -3775,7 +4349,7 @@ * gcc.dg/lto/pr66221_0.c: New test. * gcc.dg/lto/pr66221_1.c: New test. -2015-05-21 Manuel López-Ibáñez <manu@gcc.gnu.org> +2015-05-21 Manuel López-Ibáñez <manu@gcc.gnu.org> PR c/52952 * gcc.dg/redecl-4.c: Update column numbers. @@ -4080,7 +4654,7 @@ PR fortran/66113 * gfortran.dg/block_14.f90: New test. -2015-05-16 Manuel López-Ibáñez <manu@gcc.gnu.org> +2015-05-16 Manuel López-Ibáñez <manu@gcc.gnu.org> PR fortran/44054 * lib/gfortran-dg.exp: Update regex to handle two locations for diff --git a/gcc/testsuite/c-c++-common/Wsizeof-pointer-memaccess1.c b/gcc/testsuite/c-c++-common/Wsizeof-pointer-memaccess1.c index 27c5da426bd..7861bb082cd 100644 --- a/gcc/testsuite/c-c++-common/Wsizeof-pointer-memaccess1.c +++ b/gcc/testsuite/c-c++-common/Wsizeof-pointer-memaccess1.c @@ -2,6 +2,7 @@ /* { dg-do compile } */ /* { dg-options "-Wall -Wno-sizeof-array-argument" } */ /* { dg-options "-Wall -Wno-sizeof-array-argument -Wno-c++-compat" { target c } } */ +/* { dg-require-effective-target alloca } */ typedef __SIZE_TYPE__ size_t; #ifdef __cplusplus diff --git a/gcc/testsuite/c-c++-common/Wsizeof-pointer-memaccess2.c b/gcc/testsuite/c-c++-common/Wsizeof-pointer-memaccess2.c index e067d7d44e9..d9ec7e2cace 100644 --- a/gcc/testsuite/c-c++-common/Wsizeof-pointer-memaccess2.c +++ b/gcc/testsuite/c-c++-common/Wsizeof-pointer-memaccess2.c @@ -2,6 +2,7 @@ /* { dg-do compile } */ /* { dg-options "-Wall -O2 -Wno-sizeof-array-argument" } */ /* { dg-options "-Wall -O2 -Wno-sizeof-array-argument -Wno-c++-compat" {target c} } */ +/* { dg-require-effective-target alloca } */ #define bos(ptr) __builtin_object_size (ptr, 1) #define bos0(ptr) __builtin_object_size (ptr, 0) diff --git a/gcc/testsuite/c-c++-common/Wunused-var-6.c b/gcc/testsuite/c-c++-common/Wunused-var-6.c index 1217719a298..12a7dddc00d 100644 --- a/gcc/testsuite/c-c++-common/Wunused-var-6.c +++ b/gcc/testsuite/c-c++-common/Wunused-var-6.c @@ -1,6 +1,7 @@ /* PR c/43981 */ /* { dg-do compile } */ /* { dg-options "-Wunused" } */ +/* { dg-require-effective-target alloca } */ void g (char *); diff --git a/gcc/testsuite/c-c++-common/Wunused-var-8.c b/gcc/testsuite/c-c++-common/Wunused-var-8.c index 0923b355662..8c49ed2fa5c 100644 --- a/gcc/testsuite/c-c++-common/Wunused-var-8.c +++ b/gcc/testsuite/c-c++-common/Wunused-var-8.c @@ -1,6 +1,7 @@ /* Origin: PR c++/44108 */ /* { dg-options "-Wunused" } */ /* { dg-do compile } */ +/* { dg-require-effective-target alloca } */ int foo () diff --git a/gcc/testsuite/c-c++-common/goacc/reduction-1.c b/gcc/testsuite/c-c++-common/goacc/reduction-1.c index 0f500829831..de97125b4cf 100644 --- a/gcc/testsuite/c-c++-common/goacc/reduction-1.c +++ b/gcc/testsuite/c-c++-common/goacc/reduction-1.c @@ -1,3 +1,4 @@ +/* { dg-require-effective-target alloca } */ /* Integer reductions. */ #define vl 32 diff --git a/gcc/testsuite/c-c++-common/goacc/reduction-2.c b/gcc/testsuite/c-c++-common/goacc/reduction-2.c index 1f95138ff0b..2964236f6c6 100644 --- a/gcc/testsuite/c-c++-common/goacc/reduction-2.c +++ b/gcc/testsuite/c-c++-common/goacc/reduction-2.c @@ -1,3 +1,4 @@ +/* { dg-require-effective-target alloca } */ /* float reductions. */ #define vl 32 diff --git a/gcc/testsuite/c-c++-common/goacc/reduction-3.c b/gcc/testsuite/c-c++-common/goacc/reduction-3.c index 476e375c654..34c51c2505a 100644 --- a/gcc/testsuite/c-c++-common/goacc/reduction-3.c +++ b/gcc/testsuite/c-c++-common/goacc/reduction-3.c @@ -1,3 +1,4 @@ +/* { dg-require-effective-target alloca } */ /* double reductions. */ #define vl 32 diff --git a/gcc/testsuite/c-c++-common/goacc/reduction-4.c b/gcc/testsuite/c-c++-common/goacc/reduction-4.c index 73dde869a9d..328c0d4e27b 100644 --- a/gcc/testsuite/c-c++-common/goacc/reduction-4.c +++ b/gcc/testsuite/c-c++-common/goacc/reduction-4.c @@ -1,3 +1,4 @@ +/* { dg-require-effective-target alloca } */ /* complex reductions. */ #define vl 32 diff --git a/gcc/testsuite/c-c++-common/gomp/pr61486-2.c b/gcc/testsuite/c-c++-common/gomp/pr61486-2.c index 729438101e2..55332717246 100644 --- a/gcc/testsuite/c-c++-common/gomp/pr61486-2.c +++ b/gcc/testsuite/c-c++-common/gomp/pr61486-2.c @@ -1,6 +1,7 @@ /* PR middle-end/61486 */ /* { dg-do compile } */ /* { dg-options "-fopenmp" } */ +/* { dg-require-effective-target alloca } */ #pragma omp declare target void dosomething (int *a, int n, int m); diff --git a/gcc/testsuite/c-c++-common/raw-string-14.c b/gcc/testsuite/c-c++-common/raw-string-14.c index 2eeb7258f49..2253ffea3cc 100644 --- a/gcc/testsuite/c-c++-common/raw-string-14.c +++ b/gcc/testsuite/c-c++-common/raw-string-14.c @@ -12,7 +12,7 @@ const void *s1 = R"??/ // { dg-error "invalid new-line" "invalid" { target *-*-* } 10 } // { dg-error "stray" "stray" { target *-*-* } 10 } // { dg-warning "missing terminating" "missing" { target *-*-* } 10 } - // { dg-error "missing terminating" "missing" { target *-*-* } 10 } + // { dg-error "19:missing terminating" "missing" { target *-*-* } 10 } const void *s2 = R"abcdefghijklmn??/(a)abcdefghijklmn???"; // { dg-error "raw string delimiter longer" "longer" { target *-*-* } 16 } // { dg-error "stray" "stray" { target *-*-* } 16 } diff --git a/gcc/testsuite/g++.dg/Wno-frame-address.C b/gcc/testsuite/g++.dg/Wno-frame-address.C index b19cb4334e1..affcf9c9e16 100644 --- a/gcc/testsuite/g++.dg/Wno-frame-address.C +++ b/gcc/testsuite/g++.dg/Wno-frame-address.C @@ -1,4 +1,5 @@ // { dg-do compile } +// { dg-skip-if "Cannot access arbitrary stack frames." { arm*-*-* } } // { dg-options "-Werror" } // Verify that -Wframe-address is not enabled by default by enabling diff --git a/gcc/testsuite/g++.dg/concepts/iconv1.C b/gcc/testsuite/g++.dg/concepts/iconv1.C new file mode 100644 index 00000000000..c4dd38fe5b4 --- /dev/null +++ b/gcc/testsuite/g++.dg/concepts/iconv1.C @@ -0,0 +1,20 @@ +// PR c++/67240 +// { dg-options -std=c++1z } + +int foo(int x) +{ + return x; +} + +template <typename T> +concept bool C1 = requires (T x) { + {foo(x)} -> int&; +}; + +template <typename T> +concept bool C2 = requires (T x) { + {foo(x)} -> void; +}; + +static_assert( C1<int> ); // { dg-error "assert" } +static_assert( C2<int> ); // { dg-error "assert" } diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype63.C b/gcc/testsuite/g++.dg/cpp0x/decltype63.C new file mode 100644 index 00000000000..60dfec47a41 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/decltype63.C @@ -0,0 +1,7 @@ +// PR c++/63693 +// { dg-do compile { target c++11 } } + +template<typename T> +class C{ + T t; + decltype(t)::a:: // { dg-error "expected" } diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-new.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-new.C new file mode 100644 index 00000000000..7241fefc41e --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-new.C @@ -0,0 +1,11 @@ +// { dg-do compile { target c++14 } } + +constexpr int *f4(bool b) { + if (b) { + return nullptr; + } else { + return new int{42}; // { dg-error "call to non-constexpr" } + } +} +static_assert(f4(true) == nullptr, ""); +static_assert(f4(false) == nullptr, ""); // { dg-error "non-constant condition" } diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-throw.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-throw.C new file mode 100644 index 00000000000..ac90051d5e9 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-throw.C @@ -0,0 +1,34 @@ +// { dg-do compile { target c++14 } } + +constexpr void f1() { + if (false) + throw; +} + +constexpr void f2() { + if (true) + throw; +} // { dg-error "not a constant-expression" } + +constexpr void f3() { + if (false) + ; + else + throw; +}// { dg-error "not a constant-expression" } + +constexpr void f4() { + throw; +}// { dg-error "not a constant-expression" } + +constexpr int fun(int n) { + switch (n) { + case 0: + return 1; + default: + throw; // { dg-error "not a constant-expression" } + } +} + +static_assert(fun(0), ""); +static_assert(fun(1), ""); // { dg-error "non-constant" } diff --git a/gcc/testsuite/g++.dg/cpp1y/digit-sep-neg.C b/gcc/testsuite/g++.dg/cpp1y/digit-sep-neg.C index 54e5ed19cdc..833fab7c50b 100644 --- a/gcc/testsuite/g++.dg/cpp1y/digit-sep-neg.C +++ b/gcc/testsuite/g++.dg/cpp1y/digit-sep-neg.C @@ -10,7 +10,7 @@ main() i = 0004''000'000; // { dg-error "adjacent digit separators" } i = 0B1'0'0'0'0'0'0'0'0'0'0'0'0'0'0'0'0'0'0'0'0; // OK i = 0b'0001'0000'0000'0000'0000'0000; // { dg-error "digit separator after base indicator" } - i = 0b0001'0000'0000'0000'0000'0000'; // { dg-error "missing terminating" } + i = 0b0001'0000'0000'0000'0000'0000'; // { dg-error "38:missing terminating" } unsigned u = 0b0001'0000'0000'0000'0000'0000'U; // { dg-error "digit separator outside digit sequence" } double d = 0.0; @@ -18,10 +18,10 @@ main() d = 1.'602'176'565e-19; // { dg-error "digit separator adjacent to decimal point" } d = 1.602''176'565e-19; // { dg-error "adjacent digit separators" } d = 1.602'176'565'e-19; // { dg-error "digit separator adjacent to exponent" } - d = 1.602'176'565e'-19; // { dg-error "missing terminating" } + d = 1.602'176'565e'-19; // { dg-error "21:missing terminating" } d = 1.602'176'565e-'19; // { dg-error "digit separator adjacent to exponent" } d = 1.602'176'565e-1'9; // OK - d = 1.602'176'565e-19'; // { dg-error "missing terminating" } + d = 1.602'176'565e-19'; // { dg-error "24:missing terminating" } float f = 1.602'176'565e-19'F; // { dg-error "digit separator outside digit sequence" } } diff --git a/gcc/testsuite/g++.dg/graphite/graphite.exp b/gcc/testsuite/g++.dg/graphite/graphite.exp index 594d065af82..2d85cf7442f 100644 --- a/gcc/testsuite/g++.dg/graphite/graphite.exp +++ b/gcc/testsuite/g++.dg/graphite/graphite.exp @@ -41,8 +41,8 @@ set wait_to_run_files [lsort [glob -nocomplain $srcdir/$subdir/*.C ] ] set scop_files [lsort [glob -nocomplain $srcdir/$subdir/scop-*.C ] ] set id_files [lsort [glob -nocomplain $srcdir/$subdir/id-*.C ] ] set run_id_files [lsort [glob -nocomplain $srcdir/$subdir/run-id-*.C ] ] -set interchange_files [lsort [glob -nocomplain $srcdir/$subdir/interchange-*.C ] ] -set block_files [lsort [glob -nocomplain $srcdir/$subdir/block-*.C ] ] +set opt_files [lsort [glob -nocomplain $srcdir/$subdir/interchange-*.C \ + $srcdir/$subdir/block-*.C ] ] # Tests to be compiled. set dg-do-what-default compile @@ -52,16 +52,14 @@ g++-dg-runtest $id_files "" "-O2 -fgraphite-identity -ffast-math" # Tests to be run. set dg-do-what-default run g++-dg-runtest $run_id_files "" "-O2 -fgraphite-identity" -g++-dg-runtest $interchange_files "" "-O2 -floop-interchange -fno-loop-block -fno-loop-strip-mine -ffast-math -fdump-tree-graphite-all" -g++-dg-runtest $block_files "" "-O2 -floop-block -fno-loop-strip-mine -fno-loop-interchange -ffast-math -fdump-tree-graphite-all" +g++-dg-runtest $opt_files "" "-O2 -floop-nest-optimize -ffast-math -fdump-tree-graphite-all" # The default action for the rest of the files is 'compile'. set dg-do-what-default compile foreach f $scop_files {lremove wait_to_run_files $f} foreach f $id_files {lremove wait_to_run_files $f} foreach f $run_id_files {lremove wait_to_run_files $f} -foreach f $interchange_files {lremove wait_to_run_files $f} -foreach f $block_files {lremove wait_to_run_files $f} +foreach f $opt_files {lremove wait_to_run_files $f} g++-dg-runtest $wait_to_run_files "" "-pedantic-errors" # Clean up. diff --git a/gcc/testsuite/g++.dg/inherit/access9.C b/gcc/testsuite/g++.dg/inherit/access9.C new file mode 100644 index 00000000000..cdbc6404393 --- /dev/null +++ b/gcc/testsuite/g++.dg/inherit/access9.C @@ -0,0 +1,14 @@ +// PR c++/66957 + +class BaseClass { +protected: + static int x; +}; + +struct DerivedA : BaseClass { }; + +struct DerivedB : BaseClass { + DerivedB() { + (void) DerivedA::x; + } +}; diff --git a/gcc/testsuite/g++.dg/lookup/friend16.C b/gcc/testsuite/g++.dg/lookup/friend16.C new file mode 100644 index 00000000000..bb27773d7be --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/friend16.C @@ -0,0 +1,24 @@ +namespace std { + class ostream; +} + +namespace N2 { + class C0 {}; +} + +std::ostream& operator<<( std::ostream& os_, const N2::C0& m_); + +namespace N1 { + class C1 { + friend std::ostream& operator<<(std::ostream& os, const C1& what); + }; + + class C2 { + friend std::ostream& operator<<(std::ostream& os, const C2& what); + }; + + void foo(std::ostream & os, const N2::C0& m) + { + os << m; // Is this line valid? + } +} diff --git a/gcc/testsuite/g++.dg/other/pr61753.C b/gcc/testsuite/g++.dg/other/pr61753.C new file mode 100644 index 00000000000..6c6a738e07e --- /dev/null +++ b/gcc/testsuite/g++.dg/other/pr61753.C @@ -0,0 +1,31 @@ +// PR c++/61753 + +class Rulec { + Rulec(); +}; + +const Rulec::Rulec() { } // { dg-error "1:qualifiers" } + +class Rulev { + Rulev(); +}; + +volatile Rulev::Rulev() { } // { dg-error "1:qualifiers" } + +class Ruler { + Ruler(); +}; + +__restrict Ruler::Ruler() { } // { dg-error "1:qualifiers" } + +class Rulecvr { + Rulecvr(); +}; + +const volatile __restrict Rulecvr::Rulecvr() { } // { dg-error "1:qualifiers" } + +class Rulervc { + Rulervc(); +}; + +__restrict volatile const Rulervc::Rulervc() { } // { dg-error "1:qualifiers" } diff --git a/gcc/testsuite/g++.dg/other/pr67065.C b/gcc/testsuite/g++.dg/other/pr67065.C new file mode 100644 index 00000000000..790bde414df --- /dev/null +++ b/gcc/testsuite/g++.dg/other/pr67065.C @@ -0,0 +1,5 @@ +// PR c++/67065 + +int main; // { dg-error "cannot declare" } + +void foo() { int main; } diff --git a/gcc/testsuite/g++.dg/pr67211.C b/gcc/testsuite/g++.dg/pr67211.C new file mode 100644 index 00000000000..4afc69f4538 --- /dev/null +++ b/gcc/testsuite/g++.dg/pr67211.C @@ -0,0 +1,50 @@ +/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */ +/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ +/* { dg-require-effective-target powerpc_p8vector_ok } */ +/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power7" } } */ +/* { dg-options "-mcpu=power7 -mtune=power8 -O3 -w" } */ + +/* target/67211, compiler got a 'insn does not satisfy its constraints' error. */ + +template <typename _InputIterator, typename _ForwardIterator> +void find_first_of(_InputIterator, _InputIterator, _ForwardIterator p3, + _ForwardIterator p4) { + for (; p3 != p4; ++p3) + ; +} + +template <typename, typename, typename> struct A { + int _S_buffer_size; + int *_M_cur; + int *_M_first; + int *_M_last; + int **_M_node; + void operator++() { + if (_M_cur == _M_last) + m_fn1(_M_node + 1); + } + void m_fn1(int **p1) { + _M_node = p1; + _M_first = *p1; + _M_last = _M_first + _S_buffer_size; + } +}; + +template <typename _Tp, typename _Ref, typename _Ptr> +bool operator==(A<_Tp, _Ref, _Ptr>, A<_Tp, _Ref, _Ptr>); +template <typename _Tp, typename _Ref, typename _Ptr> +bool operator!=(A<_Tp, _Ref, _Ptr> p1, A<_Tp, _Ref, _Ptr> p2) { + return p1 == p2; +} + +class B { +public: + A<int, int, int> m_fn2(); +}; +struct { + B j; +} a; +void Linked() { + A<int, int, int> b, c, d; + find_first_of(d, c, b, a.j.m_fn2()); +} diff --git a/gcc/testsuite/g++.dg/pr67405.C b/gcc/testsuite/g++.dg/pr67405.C new file mode 100644 index 00000000000..505592190e1 --- /dev/null +++ b/gcc/testsuite/g++.dg/pr67405.C @@ -0,0 +1,11 @@ +// { dg-do compile } + +struct S +{ + S f; // { dg-error "incomplete type" } +}; + +void +fn1 (S p1) +{ +} diff --git a/gcc/testsuite/g++.dg/template/friend15.C b/gcc/testsuite/g++.dg/template/friend15.C index 4acbf2d1a56..15ba1c27182 100644 --- a/gcc/testsuite/g++.dg/template/friend15.C +++ b/gcc/testsuite/g++.dg/template/friend15.C @@ -10,10 +10,11 @@ template <typename> class X { struct Inner; template <typename R> - friend typename X<R>::Inner * foo () { return 0; } + friend typename X<R>::Inner * foo (X<R>*) { return 0; } }; template class X<void>; +X<void>* p; struct U { - void bar () { foo<void> (); } + void bar () { foo (p); } }; diff --git a/gcc/testsuite/g++.dg/template/friend18.C b/gcc/testsuite/g++.dg/template/friend18.C index 04ba26e9830..712d4889fea 100644 --- a/gcc/testsuite/g++.dg/template/friend18.C +++ b/gcc/testsuite/g++.dg/template/friend18.C @@ -7,13 +7,14 @@ template <int N> struct X { - template <int M> friend int foo(X const &) + template <int M> friend int foo(X const &, X<M> const&) { return N * 10000 + M; } }; X<1234> bring; +X<5678> brung; int main() { - return foo<5678> (bring) != 12345678; + return foo (bring, brung) != 12345678; } diff --git a/gcc/testsuite/g++.dg/torture/pr66752-2.C b/gcc/testsuite/g++.dg/torture/pr66752-2.C new file mode 100644 index 00000000000..96d3fe9db4b --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr66752-2.C @@ -0,0 +1,60 @@ +/* { dg-do compile } */ +extern "C" +{ + typedef struct _IO_FILE FILE; + extern int fprintf (FILE * __restrict __stream, + const char *__restrict __format, ...); +} +typedef union tree_node *tree; +class ipa_polymorphic_call_context +{ +}; +class ipcp_value_base +{ +}; +template < typename valtype > class ipcp_value:public ipcp_value_base +{ +public:valtype value; + ipcp_value *next; +}; + +template < typename valtype > class ipcp_lattice +{ +public:ipcp_value < valtype > *values; + void print (FILE * f, bool dump_sources, bool dump_benefits); +}; + +class ipcp_param_lattices +{ +public:ipcp_lattice < tree > itself; + ipcp_lattice < ipa_polymorphic_call_context > ctxlat; +}; +template < typename valtype > void ipcp_lattice < valtype >::print (FILE * f, + bool + dump_sources, + bool + dump_benefits) +{ + ipcp_value < valtype > *val; + bool prev = false; + for (val = values; val; val = val->next) + { + if (dump_benefits && prev) + fprintf (f, " "); + else if (!dump_benefits && prev) + fprintf (f, ", "); + else + prev = true; + if (dump_sources) + fprintf (f, "]"); + if (dump_benefits) + fprintf (f, "shit"); + } +} + +void +print_all_lattices (FILE * f, bool dump_sources, bool dump_benefits) +{ + struct ipcp_param_lattices *plats; + plats->ctxlat.print (f, dump_sources, dump_benefits); +} diff --git a/gcc/testsuite/g++.dg/torture/pr67133.C b/gcc/testsuite/g++.dg/torture/pr67133.C new file mode 100644 index 00000000000..0f235728bc8 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr67133.C @@ -0,0 +1,46 @@ +// { dg-do compile } +// { dg-additional-options "-fisolate-erroneous-paths-attribute" } + +class A; +struct B { + typedef A type; +}; +template <typename> struct I : B {}; +class C { +public: + C(char *); + int size(); +}; +template <typename> struct D; +template <typename _Tp, typename = D<_Tp>> class F { + class G { + template <typename> static _Tp *__test(); + typedef int _Del; + + public: + typedef decltype(__test<_Del>()) type; + }; + +public: + typename I<_Tp>::type operator*() { + typename G::type a = 0; + return *a; + } +}; +class H { + F<A> Out; + H(); +}; +void fn1(void *, void *, int) __attribute__((__nonnull__)); +class A { + int OutBufEnd, OutBufCur; + +public: + void operator<<(C p1) { + int b, c = p1.size(); + if (OutBufEnd) + fn1(&OutBufCur, &b, c); + } +}; +char* a; +H::H() { *Out << a; } diff --git a/gcc/testsuite/g++.old-deja/g++.jason/overload.C b/gcc/testsuite/g++.old-deja/g++.jason/overload.C index 28b029f48be..5d27713d770 100644 --- a/gcc/testsuite/g++.old-deja/g++.jason/overload.C +++ b/gcc/testsuite/g++.old-deja/g++.jason/overload.C @@ -5,7 +5,7 @@ enum bar {}; void operator+ (int, int);// { dg-error "" } .* void operator+ (bar&, int); -template <class T> void operator+ (int b, T& t) { return; } +template <class T> void operator+ (int b, T& t) { (void) T::bogus; } void operator+ (int, bar&); template <class T> class foo diff --git a/gcc/testsuite/g++.old-deja/g++.pt/friend32.C b/gcc/testsuite/g++.old-deja/g++.pt/friend32.C index 512a69a09a4..db8b724635c 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/friend32.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/friend32.C @@ -7,8 +7,8 @@ struct S { }; template class S<int, double>; -template char f(char, long, short); -template char* f(char*, long*, short*); +template char f(char, long, short); // { dg-error "f" } +template char* f(char*, long*, short*); // { dg-error "f" } template <class X, class Y, class Z> X f(X x, Y, Z) { diff --git a/gcc/testsuite/gcc.c-torture/compile/920723-1.c b/gcc/testsuite/gcc.c-torture/compile/920723-1.c index d8734a6796e..26b83f6f8f7 100644 --- a/gcc/testsuite/gcc.c-torture/compile/920723-1.c +++ b/gcc/testsuite/gcc.c-torture/compile/920723-1.c @@ -1,3 +1,5 @@ +/* { dg-skip-if "ptxas seg faults" { nvptx-*-* } { "-O2" } { "" } } */ + #if defined(STACK_SIZE) && STACK_SIZE < 65536 # define GITT_SIZE 75 #endif diff --git a/gcc/testsuite/gcc.c-torture/compile/callind.c b/gcc/testsuite/gcc.c-torture/compile/callind.c index 74c0f1f9cef..5938d1b88fc 100644 --- a/gcc/testsuite/gcc.c-torture/compile/callind.c +++ b/gcc/testsuite/gcc.c-torture/compile/callind.c @@ -1,8 +1,8 @@ -call (foo, a) +bar (foo, a) int (**foo) (); { - (foo)[1] = call; + (foo)[1] = bar; foo[a] (1); } diff --git a/gcc/testsuite/gcc.c-torture/compile/limits-externdecl.c b/gcc/testsuite/gcc.c-torture/compile/limits-externdecl.c index 17afe730883..f131eea3cf1 100644 --- a/gcc/testsuite/gcc.c-torture/compile/limits-externdecl.c +++ b/gcc/testsuite/gcc.c-torture/compile/limits-externdecl.c @@ -1,3 +1,5 @@ +/* { dg-skip-if "ptxas runs out of memory" { nvptx-*-* } { "*" } { "" } } */ + /* { dg-require-effective-target int32plus } */ /* Inspired by the test case for PR middle-end/52640. */ diff --git a/gcc/testsuite/gcc.c-torture/compile/mangle-1.c b/gcc/testsuite/gcc.c-torture/compile/mangle-1.c index 7abc934e75c..6797bc2436f 100644 --- a/gcc/testsuite/gcc.c-torture/compile/mangle-1.c +++ b/gcc/testsuite/gcc.c-torture/compile/mangle-1.c @@ -1,9 +1,17 @@ + +#if __nvptx__ +/* Doesn't like . in labels. */ +#define SEP "$" +#else +#define SEP "." +#endif + int foo(void) { static int x asm ("x") = 3; return x++; } -int X2 asm ("x.0") = 4; -int X3 asm ("_x.0") = 5; +int X2 asm ("x" SEP "0") = 4; +int X3 asm ("_x" SEP "0") = 5; diff --git a/gcc/testsuite/gcc.c-torture/compile/pr33855.c b/gcc/testsuite/gcc.c-torture/compile/pr33855.c index e678cb34105..7e0d5ef0d73 100644 --- a/gcc/testsuite/gcc.c-torture/compile/pr33855.c +++ b/gcc/testsuite/gcc.c-torture/compile/pr33855.c @@ -1,3 +1,4 @@ +/* { dg-skip-if "ptxas seg faults" { nvptx-*-* } { "-O1" } { "" } } */ /* Testcase by Martin Michlmayr <tbm@cyrius.com> */ /* Used to segfault due to cselim not marking the complex temp var as GIMPLE reg. */ diff --git a/gcc/testsuite/gcc.c-torture/compile/pr35468.c b/gcc/testsuite/gcc.c-torture/compile/pr35468.c index 16d064b6222..68f55654f69 100644 --- a/gcc/testsuite/gcc.c-torture/compile/pr35468.c +++ b/gcc/testsuite/gcc.c-torture/compile/pr35468.c @@ -1,4 +1,5 @@ /* PR tree-optimization/35468 */ +/* { dg-do compile } */ void foo (void) diff --git a/gcc/testsuite/gcc.c-torture/execute/981019-1.c b/gcc/testsuite/gcc.c-torture/execute/981019-1.c index 5d1f009009b..a093dff41b0 100644 --- a/gcc/testsuite/gcc.c-torture/execute/981019-1.c +++ b/gcc/testsuite/gcc.c-torture/execute/981019-1.c @@ -1,3 +1,5 @@ +/* { dg-skip-if "ptxas seg faults" { nvptx-*-* } { "-O2" "-O3*" } { "" } } */ + extern int f2(void); extern int f3(void); extern void f1(void); diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/20010124-1.x b/gcc/testsuite/gcc.c-torture/execute/builtins/20010124-1.x new file mode 100644 index 00000000000..c38970d40c0 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/builtins/20010124-1.x @@ -0,0 +1,10 @@ +load_lib target-supports.exp + +if [istarget "nvptx-*-*"] { + # This test uses memcpy for block move in the same file as it + # defines it. The two decls are not the same, by design, and we + # end up emitting a definition of memcpy, along with a .extern + # declaration. This confuses the ptx assembler. + return 1 +} +return 0 diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/fputs.x b/gcc/testsuite/gcc.c-torture/execute/builtins/fputs.x new file mode 100644 index 00000000000..c8fdaf5b254 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/builtins/fputs.x @@ -0,0 +1,7 @@ +load_lib target-supports.exp + +if { [check_effective_target_freestanding] } { + return 1; +} + +return 0; diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/memcpy-chk.x b/gcc/testsuite/gcc.c-torture/execute/builtins/memcpy-chk.x index e976a755ba0..61ec1640a10 100644 --- a/gcc/testsuite/gcc.c-torture/execute/builtins/memcpy-chk.x +++ b/gcc/testsuite/gcc.c-torture/execute/builtins/memcpy-chk.x @@ -1,3 +1,9 @@ +load_lib target-supports.exp + +if { ! [check_effective_target_nonlocal_goto] } { + return 1 +} + if [istarget "epiphany-*-*"] { # This test assumes the absence of struct padding. # to make this true for test4 struct A on epiphany would require diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/memmove-chk.x b/gcc/testsuite/gcc.c-torture/execute/builtins/memmove-chk.x index acf2132367b..c34ebb1f78a 100644 --- a/gcc/testsuite/gcc.c-torture/execute/builtins/memmove-chk.x +++ b/gcc/testsuite/gcc.c-torture/execute/builtins/memmove-chk.x @@ -1,3 +1,9 @@ +load_lib target-supports.exp + +if { ! [check_effective_target_nonlocal_goto] } { + return 1 +} + if [istarget "epiphany-*-*"] { # This test assumes the absence of struct padding. # to make this true for test5 struct A on epiphany would require diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/mempcpy-chk.x b/gcc/testsuite/gcc.c-torture/execute/builtins/mempcpy-chk.x index e976a755ba0..61ec1640a10 100644 --- a/gcc/testsuite/gcc.c-torture/execute/builtins/mempcpy-chk.x +++ b/gcc/testsuite/gcc.c-torture/execute/builtins/mempcpy-chk.x @@ -1,3 +1,9 @@ +load_lib target-supports.exp + +if { ! [check_effective_target_nonlocal_goto] } { + return 1 +} + if [istarget "epiphany-*-*"] { # This test assumes the absence of struct padding. # to make this true for test4 struct A on epiphany would require diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/memset-chk.x b/gcc/testsuite/gcc.c-torture/execute/builtins/memset-chk.x index 9b8363459c2..3019199fefd 100644 --- a/gcc/testsuite/gcc.c-torture/execute/builtins/memset-chk.x +++ b/gcc/testsuite/gcc.c-torture/execute/builtins/memset-chk.x @@ -1,3 +1,9 @@ +load_lib target-supports.exp + +if { ! [check_effective_target_nonlocal_goto] } { + return 1 +} + if [istarget "epiphany-*-*"] { # This test assumes the absence of struct padding. # to make this true for test3 struct A on epiphany would require diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/pr23484-chk.x b/gcc/testsuite/gcc.c-torture/execute/builtins/pr23484-chk.x new file mode 100644 index 00000000000..6f4746d43fb --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/builtins/pr23484-chk.x @@ -0,0 +1,7 @@ +load_lib target-supports.exp + +if { ! [check_effective_target_nonlocal_goto] } { + return 1 +} + +return 0 diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/snprintf-chk.x b/gcc/testsuite/gcc.c-torture/execute/builtins/snprintf-chk.x index 9b8363459c2..3019199fefd 100644 --- a/gcc/testsuite/gcc.c-torture/execute/builtins/snprintf-chk.x +++ b/gcc/testsuite/gcc.c-torture/execute/builtins/snprintf-chk.x @@ -1,3 +1,9 @@ +load_lib target-supports.exp + +if { ! [check_effective_target_nonlocal_goto] } { + return 1 +} + if [istarget "epiphany-*-*"] { # This test assumes the absence of struct padding. # to make this true for test3 struct A on epiphany would require diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/sprintf-chk.x b/gcc/testsuite/gcc.c-torture/execute/builtins/sprintf-chk.x index 9b8363459c2..3019199fefd 100644 --- a/gcc/testsuite/gcc.c-torture/execute/builtins/sprintf-chk.x +++ b/gcc/testsuite/gcc.c-torture/execute/builtins/sprintf-chk.x @@ -1,3 +1,9 @@ +load_lib target-supports.exp + +if { ! [check_effective_target_nonlocal_goto] } { + return 1 +} + if [istarget "epiphany-*-*"] { # This test assumes the absence of struct padding. # to make this true for test3 struct A on epiphany would require diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/stpcpy-chk.x b/gcc/testsuite/gcc.c-torture/execute/builtins/stpcpy-chk.x index e976a755ba0..61ec1640a10 100644 --- a/gcc/testsuite/gcc.c-torture/execute/builtins/stpcpy-chk.x +++ b/gcc/testsuite/gcc.c-torture/execute/builtins/stpcpy-chk.x @@ -1,3 +1,9 @@ +load_lib target-supports.exp + +if { ! [check_effective_target_nonlocal_goto] } { + return 1 +} + if [istarget "epiphany-*-*"] { # This test assumes the absence of struct padding. # to make this true for test4 struct A on epiphany would require diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/stpncpy-chk.x b/gcc/testsuite/gcc.c-torture/execute/builtins/stpncpy-chk.x index e976a755ba0..61ec1640a10 100644 --- a/gcc/testsuite/gcc.c-torture/execute/builtins/stpncpy-chk.x +++ b/gcc/testsuite/gcc.c-torture/execute/builtins/stpncpy-chk.x @@ -1,3 +1,9 @@ +load_lib target-supports.exp + +if { ! [check_effective_target_nonlocal_goto] } { + return 1 +} + if [istarget "epiphany-*-*"] { # This test assumes the absence of struct padding. # to make this true for test4 struct A on epiphany would require diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strcat-chk.x b/gcc/testsuite/gcc.c-torture/execute/builtins/strcat-chk.x index 9b8363459c2..3019199fefd 100644 --- a/gcc/testsuite/gcc.c-torture/execute/builtins/strcat-chk.x +++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strcat-chk.x @@ -1,3 +1,9 @@ +load_lib target-supports.exp + +if { ! [check_effective_target_nonlocal_goto] } { + return 1 +} + if [istarget "epiphany-*-*"] { # This test assumes the absence of struct padding. # to make this true for test3 struct A on epiphany would require diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strcpy-chk.x b/gcc/testsuite/gcc.c-torture/execute/builtins/strcpy-chk.x index e976a755ba0..61ec1640a10 100644 --- a/gcc/testsuite/gcc.c-torture/execute/builtins/strcpy-chk.x +++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strcpy-chk.x @@ -1,3 +1,9 @@ +load_lib target-supports.exp + +if { ! [check_effective_target_nonlocal_goto] } { + return 1 +} + if [istarget "epiphany-*-*"] { # This test assumes the absence of struct padding. # to make this true for test4 struct A on epiphany would require diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strncat-chk.x b/gcc/testsuite/gcc.c-torture/execute/builtins/strncat-chk.x index 9b8363459c2..3019199fefd 100644 --- a/gcc/testsuite/gcc.c-torture/execute/builtins/strncat-chk.x +++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strncat-chk.x @@ -1,3 +1,9 @@ +load_lib target-supports.exp + +if { ! [check_effective_target_nonlocal_goto] } { + return 1 +} + if [istarget "epiphany-*-*"] { # This test assumes the absence of struct padding. # to make this true for test3 struct A on epiphany would require diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strncpy-chk.x b/gcc/testsuite/gcc.c-torture/execute/builtins/strncpy-chk.x index e976a755ba0..61ec1640a10 100644 --- a/gcc/testsuite/gcc.c-torture/execute/builtins/strncpy-chk.x +++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strncpy-chk.x @@ -1,3 +1,9 @@ +load_lib target-supports.exp + +if { ! [check_effective_target_nonlocal_goto] } { + return 1 +} + if [istarget "epiphany-*-*"] { # This test assumes the absence of struct padding. # to make this true for test4 struct A on epiphany would require diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/vsnprintf-chk.x b/gcc/testsuite/gcc.c-torture/execute/builtins/vsnprintf-chk.x index 0d6e85c9711..1decd1468e7 100644 --- a/gcc/testsuite/gcc.c-torture/execute/builtins/vsnprintf-chk.x +++ b/gcc/testsuite/gcc.c-torture/execute/builtins/vsnprintf-chk.x @@ -1,3 +1,9 @@ +load_lib target-supports.exp + +if { ! [check_effective_target_nonlocal_goto] } { + return 1 +} + if [istarget "epiphany-*-*"] { # This test assumes the absence of struct padding. # to make this true for test3_sub struct A on epiphany would require diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/vsprintf-chk.x b/gcc/testsuite/gcc.c-torture/execute/builtins/vsprintf-chk.x index 0d6e85c9711..1decd1468e7 100644 --- a/gcc/testsuite/gcc.c-torture/execute/builtins/vsprintf-chk.x +++ b/gcc/testsuite/gcc.c-torture/execute/builtins/vsprintf-chk.x @@ -1,3 +1,9 @@ +load_lib target-supports.exp + +if { ! [check_effective_target_nonlocal_goto] } { + return 1 +} + if [istarget "epiphany-*-*"] { # This test assumes the absence of struct padding. # to make this true for test3_sub struct A on epiphany would require diff --git a/gcc/testsuite/gcc.c-torture/execute/complex-6.c b/gcc/testsuite/gcc.c-torture/execute/complex-6.c index bbb8c8d40aa..2e7a6cdd71b 100644 --- a/gcc/testsuite/gcc.c-torture/execute/complex-6.c +++ b/gcc/testsuite/gcc.c-torture/execute/complex-6.c @@ -1,3 +1,5 @@ +/* { dg-skip-if "requires io" { freestanding } { "*" } { "" } } */ + /* This test tests complex conjugate and passing/returning of complex parameter. */ diff --git a/gcc/testsuite/gcc.c-torture/execute/fprintf-1.c b/gcc/testsuite/gcc.c-torture/execute/fprintf-1.c index f16252b1e8e..bd3069f5383 100644 --- a/gcc/testsuite/gcc.c-torture/execute/fprintf-1.c +++ b/gcc/testsuite/gcc.c-torture/execute/fprintf-1.c @@ -1,3 +1,5 @@ +/* { dg-skip-if "requires io" { freestanding } { "*" } { "" } } */ + #include <stdio.h> #include <stdlib.h> diff --git a/gcc/testsuite/gcc.c-torture/execute/fprintf-chk-1.c b/gcc/testsuite/gcc.c-torture/execute/fprintf-chk-1.c index 918ff8e5689..caad0a4bb3d 100644 --- a/gcc/testsuite/gcc.c-torture/execute/fprintf-chk-1.c +++ b/gcc/testsuite/gcc.c-torture/execute/fprintf-chk-1.c @@ -1,3 +1,5 @@ +/* { dg-skip-if "requires io" { freestanding } { "*" } { "" } } */ + #include <stdio.h> #include <stdlib.h> #include <stdarg.h> diff --git a/gcc/testsuite/gcc.c-torture/execute/gofast.c b/gcc/testsuite/gcc.c-torture/execute/gofast.c index f55ced22073..a0b6e04465a 100644 --- a/gcc/testsuite/gcc.c-torture/execute/gofast.c +++ b/gcc/testsuite/gcc.c-torture/execute/gofast.c @@ -1,3 +1,5 @@ +/* { dg-skip-if "requires io" { freestanding } { "*" } { "" } } */ + /* Program to test gcc's usage of the gofast library. */ /* The main guiding themes are to make it trivial to add test cases over time diff --git a/gcc/testsuite/gcc.c-torture/execute/ieee/20000320-1.c b/gcc/testsuite/gcc.c-torture/execute/ieee/20000320-1.c index d750e1f37db..790cadc3199 100644 --- a/gcc/testsuite/gcc.c-torture/execute/ieee/20000320-1.c +++ b/gcc/testsuite/gcc.c-torture/execute/ieee/20000320-1.c @@ -35,10 +35,10 @@ int main() || sizeof (double) != sizeof (ull)) exit (0); - c(0x3690000000000000ULL, 0x00000000U); #if (defined __arm__ || defined __thumb__) && ! (defined __ARMEB__ || defined __VFP_FP__) /* The ARM always stores FP numbers in big-wordian format, even when running in little-byteian mode. */ + c(0x0000000036900000ULL, 0x00000000U); c(0x0000000136900000ULL, 0x00000001U); c(0xffffffff369fffffULL, 0x00000001U); c(0x0000000036A00000ULL, 0x00000001U); @@ -61,6 +61,7 @@ int main() c(0x5000000038100000ULL, 0x00800002U); c(0x5000000138100000ULL, 0x00800003U); #else + c(0x3690000000000000ULL, 0x00000000U); c(0x3690000000000001ULL, 0x00000001U); c(0x369fffffffffffffULL, 0x00000001U); c(0x36A0000000000000ULL, 0x00000001U); diff --git a/gcc/testsuite/gcc.c-torture/execute/ieee/mul-subnormal-single-1.c b/gcc/testsuite/gcc.c-torture/execute/ieee/mul-subnormal-single-1.c index d5f3fb45b6e..f4212146cd1 100644 --- a/gcc/testsuite/gcc.c-torture/execute/ieee/mul-subnormal-single-1.c +++ b/gcc/testsuite/gcc.c-torture/execute/ieee/mul-subnormal-single-1.c @@ -57,7 +57,7 @@ struct }; int -main (int argc, char *argv[], char *envp[]) +main () { unsigned int i; diff --git a/gcc/testsuite/gcc.c-torture/execute/pr34456.c b/gcc/testsuite/gcc.c-torture/execute/pr34456.c index 526c954e55a..53e46ed26a2 100644 --- a/gcc/testsuite/gcc.c-torture/execute/pr34456.c +++ b/gcc/testsuite/gcc.c-torture/execute/pr34456.c @@ -1,3 +1,5 @@ +/* { dg-skip-if "requires qsort" { freestanding } { "*" } { "" } } */ + #include <stdlib.h> int __attribute__ ((noinline)) debug (void) { return 1; } diff --git a/gcc/testsuite/gcc.c-torture/execute/printf-1.c b/gcc/testsuite/gcc.c-torture/execute/printf-1.c index 0ffcd5d443b..13e331d3e57 100644 --- a/gcc/testsuite/gcc.c-torture/execute/printf-1.c +++ b/gcc/testsuite/gcc.c-torture/execute/printf-1.c @@ -1,3 +1,5 @@ +/* { dg-skip-if "requires io" { freestanding } { "*" } { "" } } */ + #include <stdio.h> #include <stdlib.h> diff --git a/gcc/testsuite/gcc.c-torture/execute/printf-chk-1.c b/gcc/testsuite/gcc.c-torture/execute/printf-chk-1.c index 8f9a79c5c57..fde85f99442 100644 --- a/gcc/testsuite/gcc.c-torture/execute/printf-chk-1.c +++ b/gcc/testsuite/gcc.c-torture/execute/printf-chk-1.c @@ -1,3 +1,5 @@ +/* { dg-skip-if "requires io" { freestanding } { "*" } { "" } } */ + #include <stdio.h> #include <stdlib.h> #include <stdarg.h> diff --git a/gcc/testsuite/gcc.c-torture/execute/switch-1.c b/gcc/testsuite/gcc.c-torture/execute/switch-1.c index 30cffed7b85..22565576413 100644 --- a/gcc/testsuite/gcc.c-torture/execute/switch-1.c +++ b/gcc/testsuite/gcc.c-torture/execute/switch-1.c @@ -22,7 +22,7 @@ foo (int x) } int -main (int argc) +main () { int i, r; diff --git a/gcc/testsuite/gcc.c-torture/execute/vfprintf-1.c b/gcc/testsuite/gcc.c-torture/execute/vfprintf-1.c index c0038042542..c9ce492e8b9 100644 --- a/gcc/testsuite/gcc.c-torture/execute/vfprintf-1.c +++ b/gcc/testsuite/gcc.c-torture/execute/vfprintf-1.c @@ -1,3 +1,5 @@ +/* { dg-skip-if "requires io" { freestanding } { "*" } { "" } } */ + #ifndef test #include <stdio.h> #include <stdlib.h> diff --git a/gcc/testsuite/gcc.c-torture/execute/vfprintf-chk-1.c b/gcc/testsuite/gcc.c-torture/execute/vfprintf-chk-1.c index f8f964c7e9a..a642209c19b 100644 --- a/gcc/testsuite/gcc.c-torture/execute/vfprintf-chk-1.c +++ b/gcc/testsuite/gcc.c-torture/execute/vfprintf-chk-1.c @@ -1,3 +1,5 @@ +/* { dg-skip-if "requires io" { freestanding } { "*" } { "" } } */ + #ifndef test #include <stdio.h> #include <stdlib.h> diff --git a/gcc/testsuite/gcc.c-torture/execute/vprintf-1.c b/gcc/testsuite/gcc.c-torture/execute/vprintf-1.c index 9f1b8bf67aa..8b7038fd7bf 100644 --- a/gcc/testsuite/gcc.c-torture/execute/vprintf-1.c +++ b/gcc/testsuite/gcc.c-torture/execute/vprintf-1.c @@ -1,3 +1,5 @@ +/* { dg-skip-if "requires io" { freestanding } { "*" } { "" } } */ + #ifndef test #include <stdio.h> #include <stdlib.h> diff --git a/gcc/testsuite/gcc.c-torture/execute/vprintf-chk-1.c b/gcc/testsuite/gcc.c-torture/execute/vprintf-chk-1.c index ca62f8b9fe2..f9bda6ed856 100644 --- a/gcc/testsuite/gcc.c-torture/execute/vprintf-chk-1.c +++ b/gcc/testsuite/gcc.c-torture/execute/vprintf-chk-1.c @@ -1,3 +1,5 @@ +/* { dg-skip-if "requires io" { freestanding } { "*" } { "" } } */ + #ifndef test #include <stdio.h> #include <stdlib.h> diff --git a/gcc/testsuite/gcc.dg/20001117-1.c b/gcc/testsuite/gcc.dg/20001117-1.c index a9de496e276..1b24300da8e 100644 --- a/gcc/testsuite/gcc.dg/20001117-1.c +++ b/gcc/testsuite/gcc.dg/20001117-1.c @@ -1,5 +1,6 @@ /* { dg-do run } */ /* { dg-options "-O2 -finstrument-functions" } */ +/* { dg-require-effective-target return_address } */ extern void abort (void); extern void exit (int); diff --git a/gcc/testsuite/gcc.dg/20020312-2.c b/gcc/testsuite/gcc.dg/20020312-2.c index 71201fee26b..5fce50dfaf2 100644 --- a/gcc/testsuite/gcc.dg/20020312-2.c +++ b/gcc/testsuite/gcc.dg/20020312-2.c @@ -7,6 +7,7 @@ /* { dg-do run } */ /* { dg-options "-O -fno-pic" } */ +/* { dg-require-effective-target nonlocal_goto } */ extern void abort (void); diff --git a/gcc/testsuite/gcc.dg/20020415-1.c b/gcc/testsuite/gcc.dg/20020415-1.c index 7d5b5aebdea..46a1bbddc30 100644 --- a/gcc/testsuite/gcc.dg/20020415-1.c +++ b/gcc/testsuite/gcc.dg/20020415-1.c @@ -3,6 +3,7 @@ ASM_SIMPLIFY_DWARF_ADDR hook. */ /* { dg-do compile { target fpic } } */ /* { dg-options "-O2 -fpic -g" } */ +/* { dg-require-effective-target alloca } */ static inline char * bar (unsigned long x, char *y) diff --git a/gcc/testsuite/gcc.dg/20030107-1.c b/gcc/testsuite/gcc.dg/20030107-1.c index 9264eba701e..91640807efd 100644 --- a/gcc/testsuite/gcc.dg/20030107-1.c +++ b/gcc/testsuite/gcc.dg/20030107-1.c @@ -1,5 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-fprofile-arcs" } */ +/* { dg-require-profiling "-fprofile-generate" } */ extern void bar(void) __attribute__((noreturn)); int foo (void) { bar(); } diff --git a/gcc/testsuite/gcc.dg/20030331-2.c b/gcc/testsuite/gcc.dg/20030331-2.c index 2fce78ea97c..5dc164fc4fe 100644 --- a/gcc/testsuite/gcc.dg/20030331-2.c +++ b/gcc/testsuite/gcc.dg/20030331-2.c @@ -1,4 +1,5 @@ // { dg-options "" } +/* { dg-require-effective-target alloca } */ extern int printf (const char *, ...); diff --git a/gcc/testsuite/gcc.dg/20030702-1.c b/gcc/testsuite/gcc.dg/20030702-1.c index 1516a5a471d..0bc1b1c88e1 100644 --- a/gcc/testsuite/gcc.dg/20030702-1.c +++ b/gcc/testsuite/gcc.dg/20030702-1.c @@ -3,6 +3,7 @@ /* { dg-do compile { target fpic } } */ /* { dg-options "-O2 -fpic -fprofile-arcs" } */ /* { dg-skip-if "requires unsupported run-time relocation" { spu-*-* } { "*" } { "" } } */ +/* { dg-require-profiling "-fprofile-generate" } */ int fork (void); diff --git a/gcc/testsuite/gcc.dg/20050325-1.c b/gcc/testsuite/gcc.dg/20050325-1.c index 5760e387a22..db288ee8f69 100644 --- a/gcc/testsuite/gcc.dg/20050325-1.c +++ b/gcc/testsuite/gcc.dg/20050325-1.c @@ -2,6 +2,7 @@ /* { dg-do compile } */ /* { dg-options "-O2 -fprofile-arcs" } */ +/* { dg-require-profiling "-fprofile-generate" } */ extern int *g (int x, void* y); extern void fg (long long x, int y); diff --git a/gcc/testsuite/gcc.dg/20101010-1.c b/gcc/testsuite/gcc.dg/20101010-1.c index cd8fddf62d2..2067012ebcd 100644 --- a/gcc/testsuite/gcc.dg/20101010-1.c +++ b/gcc/testsuite/gcc.dg/20101010-1.c @@ -1,5 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O2 -fno-crossjumping" } */ +/* { dg-require-effective-target alloca } */ int bar1 (); int bar2 (); diff --git a/gcc/testsuite/gcc.dg/Wno-frame-address.c b/gcc/testsuite/gcc.dg/Wno-frame-address.c index f48b91a2bcb..cef924ea0a3 100644 --- a/gcc/testsuite/gcc.dg/Wno-frame-address.c +++ b/gcc/testsuite/gcc.dg/Wno-frame-address.c @@ -1,4 +1,5 @@ /* { dg-do compile } */ +/* { dg-skip-if "Cannot access arbitrary stack frames." { arm*-*-* } } */ /* { dg-options "-Werror" } */ /* Verify that -Wframe-address is not enabled by default by enabling diff --git a/gcc/testsuite/gcc.dg/Wsizeof-pointer-memaccess1.c b/gcc/testsuite/gcc.dg/Wsizeof-pointer-memaccess1.c index 66be5a5c4b2..ebdef690879 100644 --- a/gcc/testsuite/gcc.dg/Wsizeof-pointer-memaccess1.c +++ b/gcc/testsuite/gcc.dg/Wsizeof-pointer-memaccess1.c @@ -1,6 +1,7 @@ /* Test -Wsizeof-pointer-memaccess warnings. */ /* { dg-do compile } */ /* { dg-options "-Wall -Wno-sizeof-array-argument" } */ +/* { dg-require-effective-target alloca } */ typedef __SIZE_TYPE__ size_t; extern void bzero (void *, size_t); diff --git a/gcc/testsuite/gcc.dg/Wstrict-aliasing-bogus-vla-1.c b/gcc/testsuite/gcc.dg/Wstrict-aliasing-bogus-vla-1.c index e9f63d36872..87f5ef9d171 100644 --- a/gcc/testsuite/gcc.dg/Wstrict-aliasing-bogus-vla-1.c +++ b/gcc/testsuite/gcc.dg/Wstrict-aliasing-bogus-vla-1.c @@ -1,6 +1,7 @@ /* PR 41673: bogus -Wstrict-aliasing warning from VLA dereference. */ /* { dg-do compile } */ /* { dg-options "-std=gnu99 -O2 -Wall" } */ +/* { dg-require-effective-target alloca } */ int main(int argc, char *argv[]) { diff --git a/gcc/testsuite/gcc.dg/autopar/pr46193.c b/gcc/testsuite/gcc.dg/autopar/pr46193.c new file mode 100644 index 00000000000..544a5dabcec --- /dev/null +++ b/gcc/testsuite/gcc.dg/autopar/pr46193.c @@ -0,0 +1,38 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-parallelize-loops=2 -fdump-tree-parloops-details" } */ + +extern void abort (void); + +char * +foo (int count, char **list) +{ + char *minaddr = list[0]; + int i; + + for (i = 0; i < count; i++) + { + char *addr = list[i]; + if (addr < minaddr) + minaddr = addr; + } + + return minaddr; +} + +char * +foo2 (int count, char **list) +{ + char *maxaddr = list[0]; + int i; + + for (i = 0; i < count; i++) + { + char *addr = list[i]; + if (addr > maxaddr) + maxaddr = addr; + } + + return maxaddr; +} + +/* { dg-final { scan-tree-dump-times "parallelizing inner loop" 2 "parloops" } } */ diff --git a/gcc/testsuite/gcc.dg/builtin-return-1.c b/gcc/testsuite/gcc.dg/builtin-return-1.c index 68fd0556b3d..0aa0afd88a7 100644 --- a/gcc/testsuite/gcc.dg/builtin-return-1.c +++ b/gcc/testsuite/gcc.dg/builtin-return-1.c @@ -2,6 +2,7 @@ /* Originator: Andrew Church <gcczilla@achurch.org> */ /* { dg-do run } */ /* { dg-xfail-run-if "PR36571 untyped return is char register" { "avr-*-*" } { "*" } { "" } } */ +/* { dg-require-effective-target alloca } */ /* This used to fail on SPARC because the (undefined) return value of 'bar' was overwriting that of 'foo'. */ diff --git a/gcc/testsuite/gcc.dg/builtins-64.c b/gcc/testsuite/gcc.dg/builtins-64.c index 6e84633d591..3c04c44a677 100644 --- a/gcc/testsuite/gcc.dg/builtins-64.c +++ b/gcc/testsuite/gcc.dg/builtins-64.c @@ -1,4 +1,5 @@ /* { dg-do run } */ +/* { dg-require-effective-target alloca } */ int main () { diff --git a/gcc/testsuite/gcc.dg/c99-const-expr-13.c b/gcc/testsuite/gcc.dg/c99-const-expr-13.c index 0ee525bec61..e477e5d162d 100644 --- a/gcc/testsuite/gcc.dg/c99-const-expr-13.c +++ b/gcc/testsuite/gcc.dg/c99-const-expr-13.c @@ -3,6 +3,7 @@ /* Origin: Joseph Myers <joseph@codesourcery.com> */ /* { dg-do compile } */ /* { dg-options "-std=iso9899:1999 -pedantic-errors -frounding-math" } */ +/* { dg-require-effective-target alloca } */ void f (void) diff --git a/gcc/testsuite/gcc.dg/c99-vla-1.c b/gcc/testsuite/gcc.dg/c99-vla-1.c index 4a3a0f8e238..4501852066c 100644 --- a/gcc/testsuite/gcc.dg/c99-vla-1.c +++ b/gcc/testsuite/gcc.dg/c99-vla-1.c @@ -1,6 +1,7 @@ /* Origin: PR 3467 */ /* { dg-do compile } */ /* { dg-options "-std=iso9899:1999 -pedantic-errors" } */ +/* { dg-require-effective-target alloca } */ void tdef (int n) diff --git a/gcc/testsuite/gcc.dg/cleanup-12.c b/gcc/testsuite/gcc.dg/cleanup-12.c index 90de90ac831..15c079f63fb 100644 --- a/gcc/testsuite/gcc.dg/cleanup-12.c +++ b/gcc/testsuite/gcc.dg/cleanup-12.c @@ -3,6 +3,7 @@ /* { dg-do run } */ /* { dg-options "-O2 -fexceptions" } */ /* { dg-skip-if "" { "ia64-*-hpux11.*" } { "*" } { "" } } */ +/* { dg-skip-if "" { ! nonlocal_goto } { "*" } { "" } } */ /* Verify unwind info in presence of alloca. */ #include <unwind.h> diff --git a/gcc/testsuite/gcc.dg/cleanup-13.c b/gcc/testsuite/gcc.dg/cleanup-13.c index 5a0d4c69f5a..0ab1ca27650 100644 --- a/gcc/testsuite/gcc.dg/cleanup-13.c +++ b/gcc/testsuite/gcc.dg/cleanup-13.c @@ -2,6 +2,7 @@ /* { dg-do run } */ /* { dg-options "-fexceptions" } */ /* { dg-skip-if "" { "ia64-*-hpux11.*" } { "*" } { "" } } */ +/* { dg-skip-if "" { ! nonlocal_goto } { "*" } { "" } } */ /* Verify DW_OP_* handling in the unwinder. */ #include <unwind.h> diff --git a/gcc/testsuite/gcc.dg/cleanup-5.c b/gcc/testsuite/gcc.dg/cleanup-5.c index c335c1e4492..816d4cef0c1 100644 --- a/gcc/testsuite/gcc.dg/cleanup-5.c +++ b/gcc/testsuite/gcc.dg/cleanup-5.c @@ -2,6 +2,7 @@ /* { dg-do run } */ /* { dg-options "-fexceptions" } */ /* { dg-skip-if "" { "ia64-*-hpux11.*" } { "*" } { "" } } */ +/* { dg-skip-if "" { ! nonlocal_goto } { "*" } { "" } } */ /* Verify that cleanups work with exception handling. */ #include <unwind.h> diff --git a/gcc/testsuite/gcc.dg/compat/struct-by-value-22_main.c b/gcc/testsuite/gcc.dg/compat/struct-by-value-22_main.c index 1fd2eba1c7f..db6ab56ab7d 100644 --- a/gcc/testsuite/gcc.dg/compat/struct-by-value-22_main.c +++ b/gcc/testsuite/gcc.dg/compat/struct-by-value-22_main.c @@ -1,3 +1,4 @@ +/* { dg-require-effective-target alloca } */ /* Test variable sized function argument passing. GCC 3.2 and earlier is incompatible with GCC 3.3+ on x86-64, the latter passes variable sized arguments by reference while diff --git a/gcc/testsuite/gcc.dg/compat/struct-layout-1_generate.c b/gcc/testsuite/gcc.dg/compat/struct-layout-1_generate.c index b6ae34e0003..80c7355a50e 100644 --- a/gcc/testsuite/gcc.dg/compat/struct-layout-1_generate.c +++ b/gcc/testsuite/gcc.dg/compat/struct-layout-1_generate.c @@ -805,12 +805,7 @@ int main (void)\n\ #define TX(n, type, attrs, fields, ops) test##n ();\n\ #include \"t%03d_test.h\"\n\ #undef TX\n\ - if (fails)\n\ - {\n\ - fflush (stdout);\n\ - abort ();\n\ - }\n\ - exit (0);\n\ + exit (fails != 0);\n\ }\n", filecnt, filecnt); fclose (outfile); sprintf (destptr, "t%03d_x.c", filecnt); diff --git a/gcc/testsuite/gcc.dg/constructor-1.c b/gcc/testsuite/gcc.dg/constructor-1.c index 1095a455cfa..73e9fc32007 100644 --- a/gcc/testsuite/gcc.dg/constructor-1.c +++ b/gcc/testsuite/gcc.dg/constructor-1.c @@ -1,5 +1,6 @@ /* { dg-do run } */ /* { dg-options "-O2" } */ +/* { dg-skip-if "" { ! global_constructor } { "*" } { "" } } */ /* The ipa-split pass pulls the body of the if(!x) block into a separate function to make foo a better inlining diff --git a/gcc/testsuite/gcc.dg/cpp/digraphs.c b/gcc/testsuite/gcc.dg/cpp/digraphs.c index 49a1bcd8604..55bc46b061f 100644 --- a/gcc/testsuite/gcc.dg/cpp/digraphs.c +++ b/gcc/testsuite/gcc.dg/cpp/digraphs.c @@ -8,7 +8,11 @@ extern int strcmp (const char *, const char *); extern void abort (void); +#if DEBUG extern int puts (const char *); +#else +#define puts(X) +#endif #define err(str) do { puts(str); abort(); } while (0) %:define glue(x, y) x %:%: y /* #define glue(x, y) x ## y. */ diff --git a/gcc/testsuite/gcc.dg/cpp/lexnum.c b/gcc/testsuite/gcc.dg/cpp/lexnum.c index 7df15540833..3d7a9a8ddf8 100644 --- a/gcc/testsuite/gcc.dg/cpp/lexnum.c +++ b/gcc/testsuite/gcc.dg/cpp/lexnum.c @@ -5,7 +5,11 @@ /* Test lexing of numbers. */ +#if DEBUG extern int puts (const char *); +#else +#define puts(X) +#endif extern void abort (void); #define err(str) do { puts(str); abort(); } while (0) diff --git a/gcc/testsuite/gcc.dg/cpp/lexstrng.c b/gcc/testsuite/gcc.dg/cpp/lexstrng.c index b0353300395..9e13cd5fa33 100644 --- a/gcc/testsuite/gcc.dg/cpp/lexstrng.c +++ b/gcc/testsuite/gcc.dg/cpp/lexstrng.c @@ -11,7 +11,11 @@ typedef __WCHAR_TYPE__ wchar_t; extern int strcmp (const char *, const char *); +#if DEBUG extern int puts (const char *); +#else +#define puts(X) +#endif extern void abort (void); #define err(str) do { puts(str); abort(); } while (0) diff --git a/gcc/testsuite/gcc.dg/cpp/macro1.c b/gcc/testsuite/gcc.dg/cpp/macro1.c index e7235f577c2..a2b1a38e295 100644 --- a/gcc/testsuite/gcc.dg/cpp/macro1.c +++ b/gcc/testsuite/gcc.dg/cpp/macro1.c @@ -4,7 +4,11 @@ /* Tests various macro abuse is correctly expanded. */ +#if DEBUG extern int puts (const char *); +#else +#define puts(X) +#endif extern void abort (void); extern int strcmp(const char *s1, const char *s2); diff --git a/gcc/testsuite/gcc.dg/cpp/multiline-2.c b/gcc/testsuite/gcc.dg/cpp/multiline-2.c index 6a674b4dcd1..2841e00fb3b 100644 --- a/gcc/testsuite/gcc.dg/cpp/multiline-2.c +++ b/gcc/testsuite/gcc.dg/cpp/multiline-2.c @@ -9,6 +9,6 @@ const char *p = "line 1 " ""; /* The compiler front end sees this. */ -/* { dg-error "missing term" "multiline strings" { target *-*-* } 8 } */ +/* { dg-error "17:missing term" "multiline strings" { target *-*-* } 8 } */ /* { dg-error "missing term" "multiline strings" { target *-*-* } 9 } */ diff --git a/gcc/testsuite/gcc.dg/cpp/paste2.c b/gcc/testsuite/gcc.dg/cpp/paste2.c index 788e4eb51d3..b9bc7c2a8d0 100644 --- a/gcc/testsuite/gcc.dg/cpp/paste2.c +++ b/gcc/testsuite/gcc.dg/cpp/paste2.c @@ -12,7 +12,11 @@ typedef __WCHAR_TYPE__ wchar_t; extern int strcmp (const char *, const char *); +#if DEBUG extern int puts (const char *); +#else +#define puts(X) +#endif extern void abort (void); #define err(str) do { puts(str); abort(); } while (0) diff --git a/gcc/testsuite/gcc.dg/cpp/strify3.c b/gcc/testsuite/gcc.dg/cpp/strify3.c index 5d76b5e750f..b2ee4ab5562 100644 --- a/gcc/testsuite/gcc.dg/cpp/strify3.c +++ b/gcc/testsuite/gcc.dg/cpp/strify3.c @@ -9,7 +9,11 @@ Neil Booth, 24 Sep 2001. */ extern int strcmp (const char *, const char *); +#if DEBUG extern int puts (const char *); +#else +#define puts(X) +#endif extern void abort (void); #define err(str) do { puts(str); abort(); } while (0) diff --git a/gcc/testsuite/gcc.dg/cpp/strify4.c b/gcc/testsuite/gcc.dg/cpp/strify4.c index b8b2f11e9d1..9b4c0ddf4f1 100644 --- a/gcc/testsuite/gcc.dg/cpp/strify4.c +++ b/gcc/testsuite/gcc.dg/cpp/strify4.c @@ -4,7 +4,11 @@ Andrew Pinski */ extern int strcmp (const char *, const char *); +#if DEBUG extern int puts (const char *); +#else +#define puts(X) +#endif extern void abort (void); #define err(str) do { puts(str); abort(); } while (0) diff --git a/gcc/testsuite/gcc.dg/debug/debug.exp b/gcc/testsuite/gcc.dg/debug/debug.exp index 908deb16a8d..ac162ae64b4 100644 --- a/gcc/testsuite/gcc.dg/debug/debug.exp +++ b/gcc/testsuite/gcc.dg/debug/debug.exp @@ -19,6 +19,11 @@ # Load support procs. load_lib gcc-dg.exp +# Disable on ptx +if { [istarget nvptx-*-*] } { + return +} + # Initialize `dg'. dg-init diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf2.exp b/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf2.exp index d17bb5ee448..9063eb1d3a5 100644 --- a/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf2.exp +++ b/gcc/testsuite/gcc.dg/debug/dwarf2/dwarf2.exp @@ -19,6 +19,11 @@ # Load support procs. load_lib gcc-dg.exp +# Disable on ptx +if { [istarget nvptx-*-*] } { + return +} + # If a testcase doesn't have special options, use these. global DEFAULT_CFLAGS if ![info exists DEFAULT_CFLAGS] then { diff --git a/gcc/testsuite/gcc.dg/dollar.c b/gcc/testsuite/gcc.dg/dollar.c index 43407f227ed..e69c4e2ec83 100644 --- a/gcc/testsuite/gcc.dg/dollar.c +++ b/gcc/testsuite/gcc.dg/dollar.c @@ -6,4 +6,4 @@ /* Test that -fno-dollars-in-identifiers is honoured. Neil Booth, 17 May 2003. */ -int foobar$; /* { dg-error "stray '\\$'" } */ +int foobar$; /* { dg-error "11:stray '\\$'" } */ diff --git a/gcc/testsuite/gcc.dg/fold-alloca-1.c b/gcc/testsuite/gcc.dg/fold-alloca-1.c index 9cace17c500..733aeecca30 100644 --- a/gcc/testsuite/gcc.dg/fold-alloca-1.c +++ b/gcc/testsuite/gcc.dg/fold-alloca-1.c @@ -1,5 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-fdump-tree-cfg" } */ +/* { dg-require-effective-target alloca } */ void *alloca (__SIZE_TYPE__); void link_error (); diff --git a/gcc/testsuite/gcc.dg/fork-instrumentation.c b/gcc/testsuite/gcc.dg/fork-instrumentation.c index f875e180882..aedb9ee797e 100644 --- a/gcc/testsuite/gcc.dg/fork-instrumentation.c +++ b/gcc/testsuite/gcc.dg/fork-instrumentation.c @@ -1,5 +1,7 @@ /* { dg-do compile } */ /* { dg-options "-O0 -fprofile-generate" } */ +/* { dg-require-profiling "-fprofile-generate" } */ + int fork(void); int t() diff --git a/gcc/testsuite/gcc.dg/gomp/pr30494.c b/gcc/testsuite/gcc.dg/gomp/pr30494.c index 6a042ce6974..fa6d7ffc696 100644 --- a/gcc/testsuite/gcc.dg/gomp/pr30494.c +++ b/gcc/testsuite/gcc.dg/gomp/pr30494.c @@ -1,5 +1,6 @@ /* PR middle-end/30494 */ /* { dg-do compile } */ +/* { dg-require-effective-target alloca } */ int foo (int n) diff --git a/gcc/testsuite/gcc.dg/gomp/pr34610.c b/gcc/testsuite/gcc.dg/gomp/pr34610.c index 85db164b529..232fa18323b 100644 --- a/gcc/testsuite/gcc.dg/gomp/pr34610.c +++ b/gcc/testsuite/gcc.dg/gomp/pr34610.c @@ -1,6 +1,7 @@ /* PR gcov-profile/34610 */ /* { dg-do compile } */ /* { dg-options "-O2 -fprofile-arcs -fopenmp" } */ +/* { dg-require-profiling "-fprofile-generate" } */ extern void bar (int); extern void baz (int) __attribute__((noreturn)); diff --git a/gcc/testsuite/gcc.dg/gomp/static-chunk-size-one.c b/gcc/testsuite/gcc.dg/gomp/static-chunk-size-one.c new file mode 100644 index 00000000000..e82de772deb --- /dev/null +++ b/gcc/testsuite/gcc.dg/gomp/static-chunk-size-one.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-fopenmp -O2 -fdump-tree-optimized -fno-tree-pre" } */ + +int +bar () +{ + int a = 0, i; + +#pragma omp parallel for num_threads (3) reduction (+:a) schedule(static, 1) + for (i = 0; i < 10; i++) + a += i; + + return a; +} + +/* Two phis for reduction, one in loop header, one in loop exit. One phi for iv + in loop header. */ +/* { dg-final { scan-tree-dump-times "PHI" 3 "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/gomp/vla-2.c b/gcc/testsuite/gcc.dg/gomp/vla-2.c index fc18ffc5743..ea7c652553a 100644 --- a/gcc/testsuite/gcc.dg/gomp/vla-2.c +++ b/gcc/testsuite/gcc.dg/gomp/vla-2.c @@ -1,4 +1,5 @@ // { dg-do compile } +/* { dg-require-effective-target alloca } */ void foo(int n, int i) { diff --git a/gcc/testsuite/gcc.dg/gomp/vla-3.c b/gcc/testsuite/gcc.dg/gomp/vla-3.c index b1677b833ef..5070907f1e7 100644 --- a/gcc/testsuite/gcc.dg/gomp/vla-3.c +++ b/gcc/testsuite/gcc.dg/gomp/vla-3.c @@ -1,4 +1,5 @@ // { dg-do compile } +/* { dg-require-effective-target alloca } */ void foo(int n, int i) { diff --git a/gcc/testsuite/gcc.dg/gomp/vla-4.c b/gcc/testsuite/gcc.dg/gomp/vla-4.c index 2c3c0aa43b7..e784c74058c 100644 --- a/gcc/testsuite/gcc.dg/gomp/vla-4.c +++ b/gcc/testsuite/gcc.dg/gomp/vla-4.c @@ -1,4 +1,5 @@ // { dg-do compile } +/* { dg-require-effective-target alloca } */ void foo(int n, int i) { diff --git a/gcc/testsuite/gcc.dg/gomp/vla-5.c b/gcc/testsuite/gcc.dg/gomp/vla-5.c index 6c6d5517af8..20be204a5e1 100644 --- a/gcc/testsuite/gcc.dg/gomp/vla-5.c +++ b/gcc/testsuite/gcc.dg/gomp/vla-5.c @@ -1,4 +1,5 @@ // { dg-do compile } +/* { dg-require-effective-target alloca } */ void foo(int n, int i) { diff --git a/gcc/testsuite/gcc.dg/graphite/block-0.c b/gcc/testsuite/gcc.dg/graphite/block-0.c index 45a1d17eac2..cb08a5fe56f 100644 --- a/gcc/testsuite/gcc.dg/graphite/block-0.c +++ b/gcc/testsuite/gcc.dg/graphite/block-0.c @@ -42,4 +42,4 @@ main (void) return 0; } -/* { dg-final { scan-tree-dump-not "will be loop blocked" "graphite" } } */ +/* { dg-final { scan-tree-dump-times "not tiled" 3 "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/graphite/block-1.c b/gcc/testsuite/gcc.dg/graphite/block-1.c index 2208eb9d16b..19f9f20c3bc 100644 --- a/gcc/testsuite/gcc.dg/graphite/block-1.c +++ b/gcc/testsuite/gcc.dg/graphite/block-1.c @@ -45,4 +45,4 @@ main (void) return 0; } -/* { dg-final { scan-tree-dump-times "will be loop blocked" 3 "graphite" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump-times "tiled by" 5 "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/graphite/block-3.c b/gcc/testsuite/gcc.dg/graphite/block-3.c index d4fd62db7eb..fd0e661696a 100644 --- a/gcc/testsuite/gcc.dg/graphite/block-3.c +++ b/gcc/testsuite/gcc.dg/graphite/block-3.c @@ -17,7 +17,7 @@ foo (void) { int i, j, k; - /* These loops contain too few iterations to be blocked by 64. */ + /* These loops contain too few iterations to be blocked. */ for (i = 0; i < 24; i++) for (j = 0; j < 24; j++) for (k = 0; k < 24; k++) @@ -58,4 +58,4 @@ main (void) return 0; } -/* { dg-final { scan-tree-dump-times "will be loop blocked" 1 "graphite" } } */ +/* { dg-final { scan-tree-dump-times "tiled by" 3 "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/graphite/block-4.c b/gcc/testsuite/gcc.dg/graphite/block-4.c index e383a66e582..744b481eaf0 100644 --- a/gcc/testsuite/gcc.dg/graphite/block-4.c +++ b/gcc/testsuite/gcc.dg/graphite/block-4.c @@ -16,7 +16,7 @@ foo (void) { int i, j, k; - /* This should NOT be blocked: each loop iterates only 24 times. */ + /* This should NOT be blocked. */ for (i = 0; i < 24; i++) for (j = 0; j < 24; j++) for (k = 0; k < 24; k++) @@ -57,4 +57,4 @@ main (void) return 0; } -/* { dg-final { scan-tree-dump-times "will be loop blocked" 1 "graphite" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump-times "tiled by" 7 "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/graphite/block-5.c b/gcc/testsuite/gcc.dg/graphite/block-5.c index 60b7d0968c1..d30abf80fda 100644 --- a/gcc/testsuite/gcc.dg/graphite/block-5.c +++ b/gcc/testsuite/gcc.dg/graphite/block-5.c @@ -53,4 +53,4 @@ main (void) return 0; } -/* { dg-final { scan-tree-dump-times "will be loop blocked" 1 "graphite" } } */ +/* { dg-final { scan-tree-dump-times "tiled by" 3 "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/graphite/block-6.c b/gcc/testsuite/gcc.dg/graphite/block-6.c index 47fee896095..9f03448b957 100644 --- a/gcc/testsuite/gcc.dg/graphite/block-6.c +++ b/gcc/testsuite/gcc.dg/graphite/block-6.c @@ -48,4 +48,4 @@ main (void) return 0; } -/* { dg-final { scan-tree-dump-times "will be loop blocked" 0 "graphite" } } */ +/* { dg-final { scan-tree-dump-times "tiled by" 3 "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/graphite/block-7.c b/gcc/testsuite/gcc.dg/graphite/block-7.c index c07bae0652d..8b54e267078 100644 --- a/gcc/testsuite/gcc.dg/graphite/block-7.c +++ b/gcc/testsuite/gcc.dg/graphite/block-7.c @@ -54,4 +54,4 @@ main (void) return 0; } -/* { dg-final { scan-tree-dump-times "will be loop blocked" 1 "graphite" } } */ +/* { dg-final { scan-tree-dump-times "tiled by" 6 "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/graphite/block-8.c b/gcc/testsuite/gcc.dg/graphite/block-8.c index 0e9b02c52ae..d3fdf849d59 100644 --- a/gcc/testsuite/gcc.dg/graphite/block-8.c +++ b/gcc/testsuite/gcc.dg/graphite/block-8.c @@ -55,4 +55,4 @@ main (void) return 0; } -/* { dg-final { scan-tree-dump-times "will be loop blocked" 1 "graphite" } } */ +/* { dg-final { scan-tree-dump-times "tiled by" 7 "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/graphite/block-pr47654.c b/gcc/testsuite/gcc.dg/graphite/block-pr47654.c index 358c49a64d0..a7453c5e9a6 100644 --- a/gcc/testsuite/gcc.dg/graphite/block-pr47654.c +++ b/gcc/testsuite/gcc.dg/graphite/block-pr47654.c @@ -21,4 +21,4 @@ main () return 0; } -/* { dg-final { scan-tree-dump-not "will be loop blocked" "graphite" } } */ +/* { dg-final { scan-tree-dump-times "tiled by" 1 "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/graphite/graphite.exp b/gcc/testsuite/gcc.dg/graphite/graphite.exp index 9e7ede69253..f2d1417d87e 100644 --- a/gcc/testsuite/gcc.dg/graphite/graphite.exp +++ b/gcc/testsuite/gcc.dg/graphite/graphite.exp @@ -41,10 +41,10 @@ set wait_to_run_files [lsort [glob -nocomplain $srcdir/$subdir/*.c ] ] set scop_files [lsort [glob -nocomplain $srcdir/$subdir/scop-*.c ] ] set id_files [lsort [glob -nocomplain $srcdir/$subdir/id-*.c ] ] set run_id_files [lsort [glob -nocomplain $srcdir/$subdir/run-id-*.c ] ] -set interchange_files [lsort [glob -nocomplain $srcdir/$subdir/interchange-*.c \ - $srcdir/$subdir/uns-interchange-*.c ] ] -set block_files [lsort [glob -nocomplain $srcdir/$subdir/block-*.c \ - $srcdir/$subdir/uns-block-*.c ] ] +set opt_files [lsort [glob -nocomplain $srcdir/$subdir/interchange-*.c \ + $srcdir/$subdir/uns-interchange-*.c \ + $srcdir/$subdir/block-*.c \ + $srcdir/$subdir/uns-block-*.c ] ] set vect_files [lsort [glob -nocomplain $srcdir/$subdir/vect-*.c ] ] # Tests to be compiled. @@ -55,8 +55,7 @@ dg-runtest $id_files "" "-O2 -fgraphite-identity -ffast-math" # Tests to be run. set dg-do-what-default run dg-runtest $run_id_files "" "-O2 -fgraphite-identity" -dg-runtest $interchange_files "" "-O2 -floop-interchange -fno-loop-block -fno-loop-strip-mine -ffast-math -fdump-tree-graphite-all" -dg-runtest $block_files "" "-O2 -floop-block -fno-loop-strip-mine -fno-loop-interchange -ffast-math -fdump-tree-graphite-all" +dg-runtest $opt_files "" "-O2 -ffast-math -floop-nest-optimize -fdump-tree-graphite-all" # Vectorizer tests, to be run or compiled, depending on target capabilities. global DEFAULT_VECTCFLAGS @@ -71,8 +70,7 @@ set dg-do-what-default compile foreach f $scop_files {lremove wait_to_run_files $f} foreach f $id_files {lremove wait_to_run_files $f} foreach f $run_id_files {lremove wait_to_run_files $f} -foreach f $interchange_files {lremove wait_to_run_files $f} -foreach f $block_files {lremove wait_to_run_files $f} +foreach f $opt_files {lremove wait_to_run_files $f} foreach f $vect_files {lremove wait_to_run_files $f} dg-runtest $wait_to_run_files "" "-ansi -pedantic-errors" diff --git a/gcc/testsuite/gcc.dg/graphite/id-pr44676.c b/gcc/testsuite/gcc.dg/graphite/id-pr44676.c index 65821edba2a..ad22cdec8a7 100644 --- a/gcc/testsuite/gcc.dg/graphite/id-pr44676.c +++ b/gcc/testsuite/gcc.dg/graphite/id-pr44676.c @@ -1,4 +1,5 @@ /* { dg-options "-O2 -fgraphite-identity -fprofile-generate" } */ +/* { dg-require-profiling "-fprofile-generate" } */ int extend_options (int h, int map, int x, int y, int dx) diff --git a/gcc/testsuite/gcc.dg/graphite/interchange-0.c b/gcc/testsuite/gcc.dg/graphite/interchange-0.c index 5d0406853fb..2ea8f017b8e 100644 --- a/gcc/testsuite/gcc.dg/graphite/interchange-0.c +++ b/gcc/testsuite/gcc.dg/graphite/interchange-0.c @@ -46,4 +46,4 @@ main (void) return 0; } -/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" } } */ +/* { dg-final { scan-tree-dump-times "tiled by" 2 "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/graphite/interchange-1.c b/gcc/testsuite/gcc.dg/graphite/interchange-1.c index c480e83c3a3..b9f12c7d20d 100644 --- a/gcc/testsuite/gcc.dg/graphite/interchange-1.c +++ b/gcc/testsuite/gcc.dg/graphite/interchange-1.c @@ -49,4 +49,4 @@ main (void) return 0; } -/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" } } */ +/* { dg-final { scan-tree-dump-times "tiled by" 2 "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/graphite/interchange-10.c b/gcc/testsuite/gcc.dg/graphite/interchange-10.c index cbb15bde65b..29e11c72257 100644 --- a/gcc/testsuite/gcc.dg/graphite/interchange-10.c +++ b/gcc/testsuite/gcc.dg/graphite/interchange-10.c @@ -46,4 +46,4 @@ main (void) return 0; } -/* { dg-final { scan-tree-dump-times "will be interchanged" 2 "graphite" } } */ +/* { dg-final { scan-tree-dump-times "tiled by" 4 "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/graphite/interchange-11.c b/gcc/testsuite/gcc.dg/graphite/interchange-11.c index f779fbdfd80..afd71230a63 100644 --- a/gcc/testsuite/gcc.dg/graphite/interchange-11.c +++ b/gcc/testsuite/gcc.dg/graphite/interchange-11.c @@ -46,4 +46,4 @@ main (void) return 0; } -/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" } } */ +/* { dg-final { scan-tree-dump-times "tiled by" 2 "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/graphite/interchange-12.c b/gcc/testsuite/gcc.dg/graphite/interchange-12.c index bf95fdd98ad..9d5e04c882b 100644 --- a/gcc/testsuite/gcc.dg/graphite/interchange-12.c +++ b/gcc/testsuite/gcc.dg/graphite/interchange-12.c @@ -53,4 +53,4 @@ main (void) return 0; } -/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump-times "tiled by" 5 "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/graphite/interchange-13.c b/gcc/testsuite/gcc.dg/graphite/interchange-13.c index 69f6b60e3e0..0e722e2632e 100644 --- a/gcc/testsuite/gcc.dg/graphite/interchange-13.c +++ b/gcc/testsuite/gcc.dg/graphite/interchange-13.c @@ -50,4 +50,4 @@ main (void) } -/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" } } */ +/* { dg-final { scan-tree-dump-times "tiled by" 2 "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/graphite/interchange-14.c b/gcc/testsuite/gcc.dg/graphite/interchange-14.c index 46f6a6deb23..55c600247c0 100644 --- a/gcc/testsuite/gcc.dg/graphite/interchange-14.c +++ b/gcc/testsuite/gcc.dg/graphite/interchange-14.c @@ -54,5 +54,4 @@ main (void) return 0; } -/* PRE destroys the perfect nest and we can't cope with that yet. */ -/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump-times "tiled by" 7 "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/graphite/interchange-15.c b/gcc/testsuite/gcc.dg/graphite/interchange-15.c index 9f6b7aeda44..0b6829f14cf 100644 --- a/gcc/testsuite/gcc.dg/graphite/interchange-15.c +++ b/gcc/testsuite/gcc.dg/graphite/interchange-15.c @@ -48,6 +48,4 @@ main (void) return 0; } -/* PRE destroys the perfect nest and we can't cope with that yet. */ -/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" { xfail *-*-* } } } */ - +/* { dg-final { scan-tree-dump-times "tiled by" 4 "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/graphite/interchange-3.c b/gcc/testsuite/gcc.dg/graphite/interchange-3.c index 33320889af8..cdc02020197 100644 --- a/gcc/testsuite/gcc.dg/graphite/interchange-3.c +++ b/gcc/testsuite/gcc.dg/graphite/interchange-3.c @@ -47,4 +47,4 @@ main (void) return 0; } -/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" } } */ +/* { dg-final { scan-tree-dump-times "tiled by" 2 "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/graphite/interchange-4.c b/gcc/testsuite/gcc.dg/graphite/interchange-4.c index 678c0ed2bde..67125658286 100644 --- a/gcc/testsuite/gcc.dg/graphite/interchange-4.c +++ b/gcc/testsuite/gcc.dg/graphite/interchange-4.c @@ -46,4 +46,4 @@ main (void) return 0; } -/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" } } */ +/* { dg-final { scan-tree-dump-times "tiled by" 2 "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/graphite/interchange-5.c b/gcc/testsuite/gcc.dg/graphite/interchange-5.c index 16cadc83b2c..339e3b75f94 100644 --- a/gcc/testsuite/gcc.dg/graphite/interchange-5.c +++ b/gcc/testsuite/gcc.dg/graphite/interchange-5.c @@ -46,4 +46,4 @@ main (void) return 0; } -/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" } } */ +/* { dg-final { scan-tree-dump-times "tiled by" 2 "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/graphite/interchange-6.c b/gcc/testsuite/gcc.dg/graphite/interchange-6.c index 708c739aaeb..78f358e9ed2 100644 --- a/gcc/testsuite/gcc.dg/graphite/interchange-6.c +++ b/gcc/testsuite/gcc.dg/graphite/interchange-6.c @@ -47,4 +47,4 @@ main (void) return 0; } -/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" } } */ +/* { dg-final { scan-tree-dump-times "tiled by" 2 "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/graphite/interchange-7.c b/gcc/testsuite/gcc.dg/graphite/interchange-7.c index 3281e7e83bf..d99a16a291a 100644 --- a/gcc/testsuite/gcc.dg/graphite/interchange-7.c +++ b/gcc/testsuite/gcc.dg/graphite/interchange-7.c @@ -46,4 +46,4 @@ main (void) return 0; } -/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" } } */ +/* { dg-final { scan-tree-dump-times "tiled by" 2 "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/graphite/interchange-8.c b/gcc/testsuite/gcc.dg/graphite/interchange-8.c index 49cfbc88e58..123106bb475 100644 --- a/gcc/testsuite/gcc.dg/graphite/interchange-8.c +++ b/gcc/testsuite/gcc.dg/graphite/interchange-8.c @@ -82,4 +82,4 @@ main (void) return 0; } -/* { dg-final { scan-tree-dump-times "will be interchanged" 2 "graphite" } } */ +/* { dg-final { scan-tree-dump-times "tiled by" 5 "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/graphite/interchange-9.c b/gcc/testsuite/gcc.dg/graphite/interchange-9.c index b023ea8a907..e4c54ae181d 100644 --- a/gcc/testsuite/gcc.dg/graphite/interchange-9.c +++ b/gcc/testsuite/gcc.dg/graphite/interchange-9.c @@ -44,4 +44,4 @@ main (void) return 0; } -/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump-times "tiled by" 3 "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/graphite/interchange-mvt.c b/gcc/testsuite/gcc.dg/graphite/interchange-mvt.c index 8c00f8073ef..bfa5c63b9d1 100644 --- a/gcc/testsuite/gcc.dg/graphite/interchange-mvt.c +++ b/gcc/testsuite/gcc.dg/graphite/interchange-mvt.c @@ -58,6 +58,4 @@ main (void) return 0; } -/* PRE destroys the perfect nest and we can't cope with that yet. */ -/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" { xfail *-*-* } } } */ - +/* { dg-final { scan-tree-dump-times "tiled by" 7 "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/graphite/pr37485.c b/gcc/testsuite/gcc.dg/graphite/pr37485.c index 9543ce4fd54..0a6dfbceefc 100644 --- a/gcc/testsuite/gcc.dg/graphite/pr37485.c +++ b/gcc/testsuite/gcc.dg/graphite/pr37485.c @@ -1,4 +1,4 @@ -/* { dg-options "-O2 -floop-block -fno-loop-strip-mine -fno-loop-interchange -ffast-math -fdump-tree-graphite-all" } */ +/* { dg-options "-O2 -floop-block -ffast-math -fdump-tree-graphite-all" } */ typedef unsigned char UChar; typedef int Int32; @@ -30,4 +30,5 @@ void fallbackSort ( UInt32* fmap, } AssertH ( j < 256, 1005 ); } -/* { dg-final { scan-tree-dump-times "Loop blocked" 1 "graphite" { xfail *-*-* }} } */ + +/* { dg-final { scan-tree-dump-times "tiled by" 1 "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/graphite/pr60979.c b/gcc/testsuite/gcc.dg/graphite/pr60979.c index 66fffa5395d..ab8aa654d19 100644 --- a/gcc/testsuite/gcc.dg/graphite/pr60979.c +++ b/gcc/testsuite/gcc.dg/graphite/pr60979.c @@ -1,4 +1,5 @@ /* { dg-options "-O -fgraphite-identity" } */ +/* { dg-require-effective-target nonlocal_goto } */ #include <setjmp.h> diff --git a/gcc/testsuite/gcc.dg/graphite/run-id-pr47653.c b/gcc/testsuite/gcc.dg/graphite/run-id-pr47653.c index b62b891d996..20fdf87565e 100644 --- a/gcc/testsuite/gcc.dg/graphite/run-id-pr47653.c +++ b/gcc/testsuite/gcc.dg/graphite/run-id-pr47653.c @@ -1,4 +1,6 @@ /* { dg-options "-O -fstack-check=generic -ftree-pre -fgraphite-identity" } */ +/* nvptx doesn't expose a stack. */ +/* { dg-skip-if "" { nvptx-*-* } { "*" } { "" } } */ int main () { diff --git a/gcc/testsuite/gcc.dg/graphite/uns-block-1.c b/gcc/testsuite/gcc.dg/graphite/uns-block-1.c index c50b7708ef7..12a62919b5f 100644 --- a/gcc/testsuite/gcc.dg/graphite/uns-block-1.c +++ b/gcc/testsuite/gcc.dg/graphite/uns-block-1.c @@ -45,4 +45,4 @@ main (void) return 0; } -/* { dg-final { scan-tree-dump-times "will be loop blocked" 3 "graphite" } } */ +/* { dg-final { scan-tree-dump-times "tiled by" 4 "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/graphite/uns-interchange-12.c b/gcc/testsuite/gcc.dg/graphite/uns-interchange-12.c index bd21ba9bc4b..d9c07e2fe21 100644 --- a/gcc/testsuite/gcc.dg/graphite/uns-interchange-12.c +++ b/gcc/testsuite/gcc.dg/graphite/uns-interchange-12.c @@ -54,4 +54,4 @@ main (void) return 0; } -/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" } } */ +/* { dg-final { scan-tree-dump-times "tiled by" 4 "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/graphite/uns-interchange-14.c b/gcc/testsuite/gcc.dg/graphite/uns-interchange-14.c index b1abd13c02e..7ef575b667d 100644 --- a/gcc/testsuite/gcc.dg/graphite/uns-interchange-14.c +++ b/gcc/testsuite/gcc.dg/graphite/uns-interchange-14.c @@ -55,5 +55,4 @@ main (void) return 0; } -/* PRE destroys the perfect nest and we can't cope with that yet. */ -/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" } } */ +/* { dg-final { scan-tree-dump-times "tiled by" 6 "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/graphite/uns-interchange-15.c b/gcc/testsuite/gcc.dg/graphite/uns-interchange-15.c index a5a2e2781b6..0e32fd61456 100644 --- a/gcc/testsuite/gcc.dg/graphite/uns-interchange-15.c +++ b/gcc/testsuite/gcc.dg/graphite/uns-interchange-15.c @@ -49,6 +49,4 @@ main (void) return 0; } -/* PRE destroys the perfect nest and we can't cope with that yet. */ -/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" } } */ - +/* { dg-final { scan-tree-dump-times "tiled by" 2 "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/graphite/uns-interchange-9.c b/gcc/testsuite/gcc.dg/graphite/uns-interchange-9.c index 6bfd3d61f23..31b132253c6 100644 --- a/gcc/testsuite/gcc.dg/graphite/uns-interchange-9.c +++ b/gcc/testsuite/gcc.dg/graphite/uns-interchange-9.c @@ -45,4 +45,4 @@ main (void) return 0; } -/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" } } */ +/* { dg-final { scan-tree-dump-times "tiled by" 2 "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/graphite/uns-interchange-mvt.c b/gcc/testsuite/gcc.dg/graphite/uns-interchange-mvt.c index 80f67897f92..eebece38698 100644 --- a/gcc/testsuite/gcc.dg/graphite/uns-interchange-mvt.c +++ b/gcc/testsuite/gcc.dg/graphite/uns-interchange-mvt.c @@ -59,6 +59,4 @@ main (void) return 0; } -/* PRE destroys the perfect nest and we can't cope with that yet. */ -/* { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" } } */ - +/* { dg-final { scan-tree-dump-times "tiled by" 3 "graphite" } } */ diff --git a/gcc/testsuite/gcc.dg/guality/guality.c b/gcc/testsuite/gcc.dg/guality/guality.c index d5d950fcdac..db015e6a558 100644 --- a/gcc/testsuite/gcc.dg/guality/guality.c +++ b/gcc/testsuite/gcc.dg/guality/guality.c @@ -1,5 +1,6 @@ /* { dg-do run { xfail *-*-* } } */ /* { dg-options "-g" } */ +/* { dg-require-effective-target alloca } */ #include "guality.h" diff --git a/gcc/testsuite/gcc.dg/ifcvt-1.c b/gcc/testsuite/gcc.dg/ifcvt-1.c new file mode 100644 index 00000000000..92bc17a9285 --- /dev/null +++ b/gcc/testsuite/gcc.dg/ifcvt-1.c @@ -0,0 +1,10 @@ +/* { dg-do compile { target aarch64*-*-* x86_64-*-* } } */ +/* { dg-options "-fdump-rtl-ce1 -O2" } */ + +int +foo (int x) +{ + return x > 100 ? x - 2 : x - 1; +} + +/* { dg-final { scan-rtl-dump "3 true changes made" "ce1" } } */ diff --git a/gcc/testsuite/gcc.dg/ifcvt-2.c b/gcc/testsuite/gcc.dg/ifcvt-2.c new file mode 100644 index 00000000000..e0e1728a34c --- /dev/null +++ b/gcc/testsuite/gcc.dg/ifcvt-2.c @@ -0,0 +1,17 @@ +/* { dg-do compile { target aarch64*-*-* x86_64-*-* } } */ +/* { dg-options "-fdump-rtl-ce1 -O2" } */ + + +typedef unsigned char uint8_t; +typedef unsigned int uint16_t; + +uint8_t +_xtime (const uint8_t byte, const uint16_t generator) +{ + if (byte & 0x80) + return byte ^ generator; + else + return byte << 1; +} + +/* { dg-final { scan-rtl-dump "3 true changes made" "ce1" } } */ diff --git a/gcc/testsuite/gcc.dg/ifcvt-3.c b/gcc/testsuite/gcc.dg/ifcvt-3.c new file mode 100644 index 00000000000..2e104a4ffd5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/ifcvt-3.c @@ -0,0 +1,19 @@ +/* { dg-do compile { target aarch64*-*-* x86_64-*-* } } */ +/* { dg-options "-fdump-rtl-ce1 -O2" } */ + +typedef long long s64; + +int +foo (s64 a, s64 b, s64 c) +{ + s64 d = a - b; + + if (d == 0) + return a + c; + else + return b + d + c; +} + +/* This test can be reduced to just return a + c; */ +/* { dg-final { scan-rtl-dump "3 true changes made" "ce1" } } */ +/* { dg-final { scan-assembler-not "sub\.*\tx\[0-9\]+, x\[0-9\]+, x\[0-9\]+\.*" { target { aarch64*-*-* } } } } */ diff --git a/gcc/testsuite/gcc.dg/pr24225.c b/gcc/testsuite/gcc.dg/pr24225.c index 4161c31bf73..576802ba589 100644 --- a/gcc/testsuite/gcc.dg/pr24225.c +++ b/gcc/testsuite/gcc.dg/pr24225.c @@ -2,6 +2,7 @@ statements around s[b]. */ /* { dg-do compile } */ /* { dg-options "-O1 -fprofile-arcs" } */ +/* { dg-require-profiling "-fprofile-generate" } */ int foo (int a, int b) diff --git a/gcc/testsuite/gcc.dg/pr25682.c b/gcc/testsuite/gcc.dg/pr25682.c index e8cab1d05e5..ecf5669403d 100644 --- a/gcc/testsuite/gcc.dg/pr25682.c +++ b/gcc/testsuite/gcc.dg/pr25682.c @@ -1,6 +1,7 @@ /* PR c/25682 */ /* { dg-do compile } */ /* { dg-options "-ansi" } */ +/* { dg-require-effective-target alloca } */ /* Test whether we don't ICE on questionable constructs where offsetof should have been used instead. */ diff --git a/gcc/testsuite/gcc.dg/pr26570.c b/gcc/testsuite/gcc.dg/pr26570.c index 71c16f20744..8ce8a4465e8 100644 --- a/gcc/testsuite/gcc.dg/pr26570.c +++ b/gcc/testsuite/gcc.dg/pr26570.c @@ -1,5 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O2 -fprofile-generate -fprofile-use -fopt-info" } */ +/* { dg-require-profiling "-fprofile-generate" } */ unsigned test (unsigned a, unsigned b) { diff --git a/gcc/testsuite/gcc.dg/pr27301.c b/gcc/testsuite/gcc.dg/pr27301.c index 3b5a8f55b5d..cc55c745a03 100644 --- a/gcc/testsuite/gcc.dg/pr27301.c +++ b/gcc/testsuite/gcc.dg/pr27301.c @@ -1,6 +1,7 @@ /* PR c/27301 */ /* { dg-do compile } */ /* { dg-options "-O2 -std=gnu89" } */ +/* { dg-require-effective-target alloca } */ void foo (void *ptr, long n) diff --git a/gcc/testsuite/gcc.dg/pr27531-1.c b/gcc/testsuite/gcc.dg/pr27531-1.c index 08e3f5ea245..990c183fe41 100644 --- a/gcc/testsuite/gcc.dg/pr27531-1.c +++ b/gcc/testsuite/gcc.dg/pr27531-1.c @@ -4,6 +4,8 @@ output to reference a label that had been eliminated. */ /* { dg-do link } */ /* { dg-options "-O2" } */ +/* { dg-skip-if "requires io" { freestanding } { "*" } { "" } } */ + typedef struct _IO_FILE FILE; char const *RCSname; void *Locks; diff --git a/gcc/testsuite/gcc.dg/pr33238.c b/gcc/testsuite/gcc.dg/pr33238.c index 0b399041a86..993384a186d 100644 --- a/gcc/testsuite/gcc.dg/pr33238.c +++ b/gcc/testsuite/gcc.dg/pr33238.c @@ -1,6 +1,7 @@ /* PR c/33238 */ /* { dg-do compile } */ /* { dg-options "-std=gnu89" } */ +/* { dg-require-effective-target alloca } */ void reverse (void *x, int y, int z) diff --git a/gcc/testsuite/gcc.dg/pr41470.c b/gcc/testsuite/gcc.dg/pr41470.c index ddbe66e903b..7ef00861523 100644 --- a/gcc/testsuite/gcc.dg/pr41470.c +++ b/gcc/testsuite/gcc.dg/pr41470.c @@ -1,5 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-fexceptions" } */ +/* { dg-require-effective-target alloca } */ void cf (void *); diff --git a/gcc/testsuite/gcc.dg/pr44606.c b/gcc/testsuite/gcc.dg/pr44606.c index 3929775535e..1d0848e9c30 100644 --- a/gcc/testsuite/gcc.dg/pr44606.c +++ b/gcc/testsuite/gcc.dg/pr44606.c @@ -1,6 +1,7 @@ /* PR target/44606 */ /* { dg-do run } */ /* { dg-options "-O2" } */ +/* { dg-skip-if "requires io" { freestanding } { "*" } { "" } } */ #include <stdio.h> diff --git a/gcc/testsuite/gcc.dg/pr48770.c b/gcc/testsuite/gcc.dg/pr48770.c index 446389d4914..2ebe97063e3 100644 --- a/gcc/testsuite/gcc.dg/pr48770.c +++ b/gcc/testsuite/gcc.dg/pr48770.c @@ -1,6 +1,7 @@ /* { dg-do run } */ /* { dg-require-effective-target fpic } */ /* { dg-options "-O -fprofile-arcs -fPIC -fno-dce -fno-forward-propagate" } */ +/* { dg-require-profiling "-fprofile-generate" } */ int test_goto2 (int f) { diff --git a/gcc/testsuite/gcc.dg/pr49120.c b/gcc/testsuite/gcc.dg/pr49120.c index 1a65222cfec..50993e69dfd 100644 --- a/gcc/testsuite/gcc.dg/pr49120.c +++ b/gcc/testsuite/gcc.dg/pr49120.c @@ -1,6 +1,7 @@ /* PR c/49120 */ /* { dg-do compile } */ /* { dg-options "-Wall" } */ +/* { dg-require-effective-target alloca } */ int main () diff --git a/gcc/testsuite/gcc.dg/pr49551.c b/gcc/testsuite/gcc.dg/pr49551.c index 204f06deb4e..719a99d2def 100644 --- a/gcc/testsuite/gcc.dg/pr49551.c +++ b/gcc/testsuite/gcc.dg/pr49551.c @@ -1,5 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O -fdata-sections" } */ +/* { dg-skip-if "-fdata-sections not supported" { nvptx-*-* } { "*" } { "" } } */ int x = 1; int x; diff --git a/gcc/testsuite/gcc.dg/pr50764.c b/gcc/testsuite/gcc.dg/pr50764.c index e3b8da8670f..e0cd320db03 100644 --- a/gcc/testsuite/gcc.dg/pr50764.c +++ b/gcc/testsuite/gcc.dg/pr50764.c @@ -1,5 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O2 -fsched2-use-superblocks -ftree-tail-merge" } */ +/* { dg-require-effective-target alloca } */ typedef int aligned __attribute__ ((aligned (64))); extern void abort (void); diff --git a/gcc/testsuite/gcc.dg/pr51491-2.c b/gcc/testsuite/gcc.dg/pr51491-2.c index f2dc8df028d..429ee4e5914 100644 --- a/gcc/testsuite/gcc.dg/pr51491-2.c +++ b/gcc/testsuite/gcc.dg/pr51491-2.c @@ -1,5 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O2 -fdump-tree-ccp1" } */ +/* { dg-require-effective-target alloca } */ int g (int *); diff --git a/gcc/testsuite/gcc.dg/pr51990-2.c b/gcc/testsuite/gcc.dg/pr51990-2.c index 1ced0a833a8..702bab91357 100644 --- a/gcc/testsuite/gcc.dg/pr51990-2.c +++ b/gcc/testsuite/gcc.dg/pr51990-2.c @@ -1,5 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O2" } */ +/* { dg-require-effective-target alloca } */ int y; extern int foo (int, ...) __attribute__((pure)); diff --git a/gcc/testsuite/gcc.dg/pr51990.c b/gcc/testsuite/gcc.dg/pr51990.c index c7d1b537985..4f7e0e4fd37 100644 --- a/gcc/testsuite/gcc.dg/pr51990.c +++ b/gcc/testsuite/gcc.dg/pr51990.c @@ -1,5 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O2" } */ +/* { dg-require-effective-target alloca } */ int zzz (char *s1, char *s2, int len, int *q) diff --git a/gcc/testsuite/gcc.dg/pr54121.c b/gcc/testsuite/gcc.dg/pr54121.c index b9a208ea84e..3e2c0e9bb65 100644 --- a/gcc/testsuite/gcc.dg/pr54121.c +++ b/gcc/testsuite/gcc.dg/pr54121.c @@ -3,6 +3,7 @@ /* { dg-do compile { target fpic } } */ /* { dg-options "-std=gnu99 -O -fPIC -fprofile-generate" } */ +/* { dg-require-profiling "-fprofile-generate" } */ typedef __SIZE_TYPE__ size_t; typedef unsigned char uint8_t; diff --git a/gcc/testsuite/gcc.dg/pr59011.c b/gcc/testsuite/gcc.dg/pr59011.c index 2fb8187ad55..b0d6c0f30a1 100644 --- a/gcc/testsuite/gcc.dg/pr59011.c +++ b/gcc/testsuite/gcc.dg/pr59011.c @@ -1,6 +1,7 @@ /* PR middle-end/59011 */ /* { dg-do compile } */ /* { dg-options "-std=gnu99" } */ +/* { dg-require-effective-target alloca } */ void foo (int m) diff --git a/gcc/testsuite/gcc.dg/pr59523.c b/gcc/testsuite/gcc.dg/pr59523.c index b523eaea8a1..a6c3302a683 100644 --- a/gcc/testsuite/gcc.dg/pr59523.c +++ b/gcc/testsuite/gcc.dg/pr59523.c @@ -2,6 +2,7 @@ /* { dg-do compile } */ /* { dg-options "-O3" } */ /* { dg-additional-options "-mavx2" { target { i?86-*-* x86_64-*-* } } } */ +/* { dg-require-effective-target alloca } */ int * foo (int a, int *b, int *c, int *d) diff --git a/gcc/testsuite/gcc.dg/pr61561.c b/gcc/testsuite/gcc.dg/pr61561.c index 1512f20e3d0..47d0ff0b818 100644 --- a/gcc/testsuite/gcc.dg/pr61561.c +++ b/gcc/testsuite/gcc.dg/pr61561.c @@ -1,6 +1,7 @@ /* PR c/61561. */ /* { dg-do assemble } */ /* { dg-options " -w -O2" } */ +/* { dg-require-effective-target alloca } */ int dummy (int a); diff --git a/gcc/testsuite/gcc.dg/pr61776.c b/gcc/testsuite/gcc.dg/pr61776.c index 8768c546bda..8deec9e9934 100644 --- a/gcc/testsuite/gcc.dg/pr61776.c +++ b/gcc/testsuite/gcc.dg/pr61776.c @@ -1,5 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O2 -fprofile-generate" } */ +/* { dg-require-profiling "-fprofile-generate" } */ #include <setjmp.h> diff --git a/gcc/testsuite/gcc.dg/pr63186.c b/gcc/testsuite/gcc.dg/pr63186.c index 8efb750a9b2..32aa2afda9b 100644 --- a/gcc/testsuite/gcc.dg/pr63186.c +++ b/gcc/testsuite/gcc.dg/pr63186.c @@ -1,5 +1,7 @@ /* { dg-do link } */ /* { dg-options "-O2" } */ +/* { dg-require-effective-target label_values } */ + void *a; int b, c, d; diff --git a/gcc/testsuite/gcc.dg/pr63748.c b/gcc/testsuite/gcc.dg/pr63748.c index 2e5044584a6..cc353a7e5c3 100644 --- a/gcc/testsuite/gcc.dg/pr63748.c +++ b/gcc/testsuite/gcc.dg/pr63748.c @@ -1,5 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O2 -Wall" } */ +/* { dg-require-effective-target nonlocal_goto } */ #include <setjmp.h> diff --git a/gcc/testsuite/gcc.dg/pr64935-2.c b/gcc/testsuite/gcc.dg/pr64935-2.c index 6921a21d76a..3b45382a825 100644 --- a/gcc/testsuite/gcc.dg/pr64935-2.c +++ b/gcc/testsuite/gcc.dg/pr64935-2.c @@ -1,6 +1,7 @@ /* PR rtl-optimization/64935 */ /* { dg-do compile } */ /* { dg-options "-O -fschedule-insns --param=max-sched-ready-insns=0 -fcompare-debug" } */ +/* { dg-require-effective-target scheduling } */ void foo (int *data, unsigned len, const int qlp_coeff[], diff --git a/gcc/testsuite/gcc.dg/pr66899.c b/gcc/testsuite/gcc.dg/pr66899.c index 1fff18153aa..23ecc539c06 100644 --- a/gcc/testsuite/gcc.dg/pr66899.c +++ b/gcc/testsuite/gcc.dg/pr66899.c @@ -1,5 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-Os -fprofile-arcs" } */ +/* { dg-require-profiling "-fprofile-generate" } */ struct { diff --git a/gcc/testsuite/gcc.dg/pragma-message.c b/gcc/testsuite/gcc.dg/pragma-message.c index 0f9c6bf447b..d4d1009fdef 100644 --- a/gcc/testsuite/gcc.dg/pragma-message.c +++ b/gcc/testsuite/gcc.dg/pragma-message.c @@ -16,13 +16,13 @@ matching dg-message), dejagnu will report these as excess errors. */ #pragma message " -/* { dg-error "missing terminating" "" { target *-*-* } 18 } */ +/* { dg-error "17:missing terminating" "" { target *-*-* } 18 } */ /* { dg-warning "expected a string" "" { target *-*-* } 18 } */ #pragma message "Bad 1 -/* { dg-error "missing terminating" "" { target *-*-* } 21 } */ +/* { dg-error "17:missing terminating" "" { target *-*-* } 21 } */ /* { dg-warning "expected a string" "" { target *-*-* } 21 } */ #pragma message ("Bad 2 -/* { dg-error "missing terminating" "" { target *-*-* } 24 } */ +/* { dg-error "18:missing terminating" "" { target *-*-* } 24 } */ /* { dg-warning "expected a string" "" { target *-*-* } 24 } */ #pragma message ("Bad 3" /* { dg-warning "malformed '#pragma message" "" { target *-*-* } 27 } */ diff --git a/gcc/testsuite/gcc.dg/setjmp-1.c b/gcc/testsuite/gcc.dg/setjmp-1.c index b5c84fc8792..c5dcef24934 100644 --- a/gcc/testsuite/gcc.dg/setjmp-1.c +++ b/gcc/testsuite/gcc.dg/setjmp-1.c @@ -3,6 +3,7 @@ /* { dg-do compile } */ /* { dg-options "-O -Wclobbered -Wextra -Wall" } */ +/* { dg-skip-if "" { ! nonlocal_goto } { "*" } { "" } } */ #include <setjmp.h> diff --git a/gcc/testsuite/gcc.dg/shrink-wrap-alloca.c b/gcc/testsuite/gcc.dg/shrink-wrap-alloca.c index fbe6f4fd20d..b9a2af1c51b 100644 --- a/gcc/testsuite/gcc.dg/shrink-wrap-alloca.c +++ b/gcc/testsuite/gcc.dg/shrink-wrap-alloca.c @@ -1,5 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O2 -g" } */ +/* { dg-require-effective-target alloca } */ int *p; diff --git a/gcc/testsuite/gcc.dg/stack-usage-1.c b/gcc/testsuite/gcc.dg/stack-usage-1.c index 55edc7ec61f..7864c6a282b 100644 --- a/gcc/testsuite/gcc.dg/stack-usage-1.c +++ b/gcc/testsuite/gcc.dg/stack-usage-1.c @@ -1,5 +1,7 @@ /* { dg-do compile } */ /* { dg-options "-fstack-usage" } */ +/* nvptx doesn't have a reg allocator, and hence no stack usage data. */ +/* { dg-skip-if "" { nvptx-*-* } { "*" } { "" } } */ /* This is aimed at testing basic support for -fstack-usage in the back-ends. See the SPARC back-end for example (grep flag_stack_usage_info in sparc.c). diff --git a/gcc/testsuite/gcc.dg/stack-usage-2.c b/gcc/testsuite/gcc.dg/stack-usage-2.c index df7e55f0560..c2527d27c18 100644 --- a/gcc/testsuite/gcc.dg/stack-usage-2.c +++ b/gcc/testsuite/gcc.dg/stack-usage-2.c @@ -1,5 +1,7 @@ /* { dg-do compile } */ /* { dg-options "-Wstack-usage=512" } */ +/* nvptx gets very upset with mismatched function types. */ +/* { dg-skip-if "" { nvptx-*-* } { "*" } { "" } } */ int foo1 (void) /* { dg-bogus "stack usage" } */ { diff --git a/gcc/testsuite/gcc.dg/torture/Wsizeof-pointer-memaccess1.c b/gcc/testsuite/gcc.dg/torture/Wsizeof-pointer-memaccess1.c index a82f4efbdaf..7ce9eaeb261 100644 --- a/gcc/testsuite/gcc.dg/torture/Wsizeof-pointer-memaccess1.c +++ b/gcc/testsuite/gcc.dg/torture/Wsizeof-pointer-memaccess1.c @@ -4,6 +4,7 @@ /* Test just twice, once with -O0 non-fortified, once with -O2 fortified. */ /* { dg-skip-if "" { *-*-* } { "*" } { "-O0" "-O2" } } */ /* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */ +/* { dg-require-effective-target alloca } */ typedef __SIZE_TYPE__ size_t; extern void *memset (void *, int, size_t); diff --git a/gcc/testsuite/gcc.dg/torture/calleesave-sse.c b/gcc/testsuite/gcc.dg/torture/calleesave-sse.c index 292791c7259..76db20ef67c 100644 --- a/gcc/testsuite/gcc.dg/torture/calleesave-sse.c +++ b/gcc/testsuite/gcc.dg/torture/calleesave-sse.c @@ -1,5 +1,6 @@ /* { dg-do run } */ /* { dg-options "-fno-omit-frame-pointer" } */ +/* { dg-require-effective-target alloca } */ #define alloca __builtin_alloca extern void abort (void); diff --git a/gcc/testsuite/gcc.dg/torture/matrix-1.c b/gcc/testsuite/gcc.dg/torture/matrix-1.c index 1b88599bdcd..7be912e356d 100644 --- a/gcc/testsuite/gcc.dg/torture/matrix-1.c +++ b/gcc/testsuite/gcc.dg/torture/matrix-1.c @@ -62,8 +62,7 @@ mem_init (void) vel[i] = (int **) malloc (3 * sizeof (int *)); if (vel[i] == (int **) NULL) { - fprintf (stderr, "malloc failed for vel[%d]\n", i); - fflush (stderr); + printf ("malloc failed for vel[%d]\n", i); exit (0); } } diff --git a/gcc/testsuite/gcc.dg/torture/matrix-2.c b/gcc/testsuite/gcc.dg/torture/matrix-2.c index 5013671af5c..8aaf7c60f75 100644 --- a/gcc/testsuite/gcc.dg/torture/matrix-2.c +++ b/gcc/testsuite/gcc.dg/torture/matrix-2.c @@ -73,8 +73,7 @@ mem_init (void) vel[i] = (int **) malloc (3 * sizeof (int *)); if (vel[i] == (int **) NULL) { - fprintf (stderr, "malloc failed for vel[%d]\n", i); - fflush (stderr); + printf ("malloc failed for vel[%d]\n", i); exit (0); } } diff --git a/gcc/testsuite/gcc.dg/torture/matrix-5.c b/gcc/testsuite/gcc.dg/torture/matrix-5.c index 9b17567f442..e8f2deb6ae6 100644 --- a/gcc/testsuite/gcc.dg/torture/matrix-5.c +++ b/gcc/testsuite/gcc.dg/torture/matrix-5.c @@ -67,8 +67,7 @@ mem_init (void) vel[i] = (int **) malloc (3 * sizeof (int *)); if (vel[i] == (int **) NULL) { - fprintf (stderr, "malloc failed for vel[%d]\n", i); - fflush (stderr); + printf ("malloc failed for vel[%d]\n", i); exit (0); } } diff --git a/gcc/testsuite/gcc.dg/torture/matrix-6.c b/gcc/testsuite/gcc.dg/torture/matrix-6.c index cad63ddabfc..e01e5311cd8 100644 --- a/gcc/testsuite/gcc.dg/torture/matrix-6.c +++ b/gcc/testsuite/gcc.dg/torture/matrix-6.c @@ -68,8 +68,7 @@ mem_init (void) vel[i] = (int **) malloc (3 * sizeof (int *)); if (vel[i] == (int **) NULL) { - fprintf (stderr, "malloc failed for vel[%d]\n", i); - fflush (stderr); + printf ("malloc failed for vel[%d]\n", i); exit (0); } } diff --git a/gcc/testsuite/gcc.dg/torture/pr33848.c b/gcc/testsuite/gcc.dg/torture/pr33848.c index 5d71d2c933c..db6060253eb 100644 --- a/gcc/testsuite/gcc.dg/torture/pr33848.c +++ b/gcc/testsuite/gcc.dg/torture/pr33848.c @@ -1,4 +1,3 @@ -/* { dg-require-effective-target label_values } */ /* &&foo should be hoisted, but on most targets, excess register pressure forces it to be rematerialized before "data != &&foo". On targets that have a "branch if registers are equal" instruction, this leads to the @@ -7,6 +6,7 @@ say that &&foo was the target of the branch, and the real target would then be removed as dead. */ /* { dg-do link } */ +/* { dg-require-effective-target label_values } */ #define NVARS 30 #define MULTI(X) \ X( 0), X( 1), X( 2), X( 3), X( 4), X( 5), X( 6), X( 7), X( 8), X( 9), \ diff --git a/gcc/testsuite/gcc.dg/torture/pr41261.c b/gcc/testsuite/gcc.dg/torture/pr41261.c index 8e601555cb5..448fc0146e1 100644 --- a/gcc/testsuite/gcc.dg/torture/pr41261.c +++ b/gcc/testsuite/gcc.dg/torture/pr41261.c @@ -1,5 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-fprofile-arcs" } */ +/* { dg-require-profiling "-fprofile-generate" } */ extern void relocate_kernel(); void machine_kexec(void *control_page) diff --git a/gcc/testsuite/gcc.dg/torture/pr63738.c b/gcc/testsuite/gcc.dg/torture/pr63738.c index 06ede546192..82ac4ff2a63 100644 --- a/gcc/testsuite/gcc.dg/torture/pr63738.c +++ b/gcc/testsuite/gcc.dg/torture/pr63738.c @@ -1,4 +1,5 @@ /* { dg-do compile } */ +/* { dg-require-effective-target nonlocal_goto } */ #include <setjmp.h> diff --git a/gcc/testsuite/gcc.dg/torture/pr64728.c b/gcc/testsuite/gcc.dg/torture/pr64728.c index 65c8508fc84..7384d85a928 100644 --- a/gcc/testsuite/gcc.dg/torture/pr64728.c +++ b/gcc/testsuite/gcc.dg/torture/pr64728.c @@ -1,4 +1,5 @@ /* { dg-do compile } */ +/* { dg-require-effective-target nonlocal_goto } */ #include <setjmp.h> diff --git a/gcc/testsuite/gcc.dg/torture/pr66101.c b/gcc/testsuite/gcc.dg/torture/pr66101.c index f3ef5e55bfd..39d380722b4 100644 --- a/gcc/testsuite/gcc.dg/torture/pr66101.c +++ b/gcc/testsuite/gcc.dg/torture/pr66101.c @@ -1,4 +1,5 @@ /* { dg-do compile } */ +/* { dg-require-effective-target nonlocal_goto } */ #include <setjmp.h> diff --git a/gcc/testsuite/gcc.dg/torture/pr66123.c b/gcc/testsuite/gcc.dg/torture/pr66123.c index 848f8fedcee..5fc0c1c4291 100644 --- a/gcc/testsuite/gcc.dg/torture/pr66123.c +++ b/gcc/testsuite/gcc.dg/torture/pr66123.c @@ -1,4 +1,5 @@ /* { dg-do compile } */ +/* { dg-require-effective-target label_values } */ int test (int foo) diff --git a/gcc/testsuite/gcc.dg/torture/pr66752-1.c b/gcc/testsuite/gcc.dg/torture/pr66752-1.c new file mode 100644 index 00000000000..a7425554ba9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr66752-1.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ + +typedef unsigned int size_t; +struct fde_vector +{ + size_t count; + const struct dwarf_fde *array[]; +}; +struct object; +typedef struct dwarf_fde fde; +typedef int (*fde_compare_t) (struct object *, const fde *, const fde *); +void +fde_merge (struct object *ob, fde_compare_t fde_compare, + struct fde_vector *v1, struct fde_vector *v2) +{ + size_t i1, i2; + const fde *fde2; + do + { + i2--; + while (i1 > 0 && fde_compare (ob, v1->array[i1 - 1], fde2) > 0) + { + i1--; + } + } + while (i2 > 0); +} diff --git a/gcc/testsuite/gcc.dg/torture/pr67005.c b/gcc/testsuite/gcc.dg/torture/pr67005.c new file mode 100644 index 00000000000..922c5c475e8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr67005.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ + +int a; +void +f (void) +{ + if (!a); + else + lbl: + a = a; + + if (a) + a = 8; + goto lbl; +} diff --git a/gcc/testsuite/gcc.dg/torture/transpose-1.c b/gcc/testsuite/gcc.dg/torture/transpose-1.c index 188f3b51b13..20651be0795 100644 --- a/gcc/testsuite/gcc.dg/torture/transpose-1.c +++ b/gcc/testsuite/gcc.dg/torture/transpose-1.c @@ -69,8 +69,7 @@ mem_init (void) vel[i] = (int **) malloc (3 * sizeof (int *)); if (vel[i] == (int **) NULL) { - fprintf (stderr, "malloc failed for vel[%d]\n", i); - fflush (stderr); + printf ("malloc failed for vel[%d]\n", i); exit (0); } } diff --git a/gcc/testsuite/gcc.dg/torture/transpose-2.c b/gcc/testsuite/gcc.dg/torture/transpose-2.c index bff6a3ababc..0e08feaa500 100644 --- a/gcc/testsuite/gcc.dg/torture/transpose-2.c +++ b/gcc/testsuite/gcc.dg/torture/transpose-2.c @@ -66,8 +66,7 @@ mem_init (void) vel[i] = (int **) malloc (3 * sizeof (int *)); if (vel[i] == (int **) NULL) { - fprintf (stderr, "malloc failed for vel[%d]\n", i); - fflush (stderr); + printf ("malloc failed for vel[%d]\n", i); exit (0); } } diff --git a/gcc/testsuite/gcc.dg/torture/transpose-3.c b/gcc/testsuite/gcc.dg/torture/transpose-3.c index da7e887013c..8b55a2efbcd 100644 --- a/gcc/testsuite/gcc.dg/torture/transpose-3.c +++ b/gcc/testsuite/gcc.dg/torture/transpose-3.c @@ -71,8 +71,7 @@ mem_init (void) vel[i] = (int **) malloc (3 * sizeof (int *)); if (vel[i] == (int **) NULL) { - fprintf (stderr, "malloc failed for vel[%d]\n", i); - fflush (stderr); + printf ("malloc failed for vel[%d]\n", i); exit (0); } } diff --git a/gcc/testsuite/gcc.dg/torture/transpose-4.c b/gcc/testsuite/gcc.dg/torture/transpose-4.c index 5a96a5163fd..0d9c1df02b2 100644 --- a/gcc/testsuite/gcc.dg/torture/transpose-4.c +++ b/gcc/testsuite/gcc.dg/torture/transpose-4.c @@ -69,8 +69,7 @@ mem_init (void) vel[i] = (int **) malloc (3 * sizeof (int *)); if (vel[i] == (int **) NULL) { - fprintf (stderr, "malloc failed for vel[%d]\n", i); - fflush (stderr); + printf ("malloc failed for vel[%d]\n", i); exit (0); } } diff --git a/gcc/testsuite/gcc.dg/torture/transpose-5.c b/gcc/testsuite/gcc.dg/torture/transpose-5.c index 049d7b03e23..8ed39534598 100644 --- a/gcc/testsuite/gcc.dg/torture/transpose-5.c +++ b/gcc/testsuite/gcc.dg/torture/transpose-5.c @@ -66,8 +66,7 @@ mem_init (void) vel[i] = (int **) malloc (3 * sizeof (int *)); if (vel[i] == (int **) NULL) { - fprintf (stderr, "malloc failed for vel[%d]\n", i); - fflush (stderr); + printf ("malloc failed for vel[%d]\n", i); exit (0); } } diff --git a/gcc/testsuite/gcc.dg/torture/transpose-6.c b/gcc/testsuite/gcc.dg/torture/transpose-6.c index 9b3329b5361..0ef6aa9ae9a 100644 --- a/gcc/testsuite/gcc.dg/torture/transpose-6.c +++ b/gcc/testsuite/gcc.dg/torture/transpose-6.c @@ -66,8 +66,7 @@ mem_init (void) vel[i] = (int **) malloc (3 * sizeof (int *)); if (vel[i] == (int **) NULL) { - fprintf (stderr, "malloc failed for vel[%d]\n", i); - fflush (stderr); + printf ("malloc failed for vel[%d]\n", i); exit (0); } } diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030807-2.c b/gcc/testsuite/gcc.dg/tree-ssa/20030807-2.c index 259932480a1..0712922b363 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/20030807-2.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030807-2.c @@ -1,5 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O1 -ftree-vrp -fdump-tree-dom2" } */ +/* { dg-require-effective-target alloca } */ extern void abort (void); extern void bitmap_clear (int *); diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20080530.c b/gcc/testsuite/gcc.dg/tree-ssa/20080530.c index 8583574266e..c472f8167a0 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/20080530.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/20080530.c @@ -1,5 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O2 -fdump-tree-einline" } */ +/* { dg-require-effective-target alloca } */ void bar (char *); int i; diff --git a/gcc/testsuite/gcc.dg/tree-ssa/cmp-1.c b/gcc/testsuite/gcc.dg/tree-ssa/cmp-1.c new file mode 100644 index 00000000000..6faa70c8df3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/cmp-1.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-gimple -fdump-tree-optimized" } */ + +int f(int a){ + int b = -__INT_MAX__-1; + a &= b; + return a == b; +} +int g(int x){ + x = x < 0 ? -x : x; + return x == 0; +} + +/* This should work even if int is not 32 bits, it is just not meaningful in + that case. */ +/* { dg-final { scan-tree-dump-not "-2147483648" "optimized"} } */ +/* { dg-final { scan-tree-dump " < 0" "optimized"} } */ +/* { dg-final { scan-tree-dump "ABS_EXPR" "gimple"} } */ +/* { dg-final { scan-tree-dump-not "ABS_EXPR" "optimized"} } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/complex-7.c b/gcc/testsuite/gcc.dg/tree-ssa/complex-7.c new file mode 100644 index 00000000000..20a2a3785f6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/complex-7.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-forwprop1" } */ + +float f(_Complex float x, _Complex float y){ + x += y; + return __builtin_cimagf (x); +} + +double g(double x){ + _Complex double c = __builtin_cexpi (x); + return __builtin_creal (c); +} + +/* { dg-final { scan-tree-dump "__builtin_cos" "forwprop1"} } */ +/* { dg-final { scan-tree-dump-times "IMAGPART_EXPR" 2 "forwprop1"} } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/nonzero-1.c b/gcc/testsuite/gcc.dg/tree-ssa/nonzero-1.c index 18ccc604838..c9d438e9374 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/nonzero-1.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/nonzero-1.c @@ -1,5 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O2 -fdelete-null-pointer-checks" } */ +/* { dg-require-weak "" } */ /* { dg-skip-if "" keeps_null_pointer_checks } */ extern int a; /* { dg-error "declared weak after being used" } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr23848-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr23848-1.c index c80ed85e830..8836ab22972 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr23848-1.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr23848-1.c @@ -1,6 +1,7 @@ /* PR middle-end/23848 */ /* { dg-do compile } */ /* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-require-effective-target alloca } */ void bar1 (char *, int); void foo1 (int size) diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr23848-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr23848-2.c index cdbf7b00031..7b5be75bf83 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr23848-2.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr23848-2.c @@ -1,6 +1,7 @@ /* PR middle-end/23848 */ /* { dg-do compile } */ /* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-require-effective-target alloca } */ void bar (char *, char *, char *, char *, int); void foo (int size) diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr23848-3.c b/gcc/testsuite/gcc.dg/tree-ssa/pr23848-3.c index 3232f3447f9..ed3541e22e0 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr23848-3.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr23848-3.c @@ -1,6 +1,7 @@ /* PR middle-end/23848 */ /* { dg-do compile } */ /* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-require-effective-target alloca } */ void bar (int, char *, char *, char *, char *, int); void foo (int size) diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr23848-4.c b/gcc/testsuite/gcc.dg/tree-ssa/pr23848-4.c index f32e8fab861..0f7948c3e14 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr23848-4.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr23848-4.c @@ -1,6 +1,7 @@ /* PR middle-end/23848 */ /* { dg-do compile } */ /* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-require-effective-target alloca } */ void bar (char *, char *, char *, char *, int); void foo (int size) diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr66752-3.c b/gcc/testsuite/gcc.dg/tree-ssa/pr66752-3.c new file mode 100644 index 00000000000..f15b5986166 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr66752-3.c @@ -0,0 +1,39 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-dom1-details -fdump-tree-optimized" } */ + +extern int status, pt; +extern int count; +void +foo (int N, int c, int b, int *a) +{ + int i, flag; + i = b -1; + flag = 1; + if (status && i < N && a[i] == b) { + N--; + flag = 0; + if (pt) + count++; + } + else + for (i = -1, flag = 1; ++i < N && flag;) + if (a[i] == b) + { + --N; + flag = 0; + if (i < N) + a[i] = a[N]; + else + a[i] = 0; + if (pt) + count++; + } + if(status && flag) + pt--; +} + +/* There are 3 FSM jump threading opportunities. */ +/* { dg-final { scan-tree-dump-times "FSM" 3 "dom1"} } */ + +/* There should be no assignments or references to FLAG. */ +/* { dg-final { scan-tree-dump-not "flag" "optimized"} } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-11.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-11.c index 64e71eb620d..eadf71c19f7 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-11.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-11.c @@ -1,5 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O -fprofile-arcs -fdump-tree-lim1-details" } */ +/* { dg-require-profiling "-fprofile-generate" } */ struct thread_param { diff --git a/gcc/testsuite/gcc.dg/uninit-9-O0.c b/gcc/testsuite/gcc.dg/uninit-9-O0.c index 493dd68d908..ac24e7a8362 100644 --- a/gcc/testsuite/gcc.dg/uninit-9-O0.c +++ b/gcc/testsuite/gcc.dg/uninit-9-O0.c @@ -3,6 +3,7 @@ /* { dg-do compile } */ /* { dg-options "-Wuninitialized" } */ +/* { dg-require-effective-target alloca } */ struct foo { diff --git a/gcc/testsuite/gcc.dg/uninit-9.c b/gcc/testsuite/gcc.dg/uninit-9.c index 2a8ccb69f32..d1af7328a96 100644 --- a/gcc/testsuite/gcc.dg/uninit-9.c +++ b/gcc/testsuite/gcc.dg/uninit-9.c @@ -3,6 +3,7 @@ /* { dg-do compile } */ /* { dg-options "-O -Wuninitialized" } */ +/* { dg-require-effective-target alloca } */ struct foo { diff --git a/gcc/testsuite/gcc.dg/unused-5.c b/gcc/testsuite/gcc.dg/unused-5.c index 5ccc3f3beae..1b8e100d249 100644 --- a/gcc/testsuite/gcc.dg/unused-5.c +++ b/gcc/testsuite/gcc.dg/unused-5.c @@ -1,6 +1,8 @@ /* { dg-do compile } */ /* { dg-options "-Wunused" } */ /* { dg-final { scan-assembler "string_to_look_for" } } */ +/* nvptx outputs strings as array of ints. */ +/* { dg-skip-if "" { nvptx-*-* } { "*" } { "" } } */ /* 'volatile' variables get output and don't produce a warning about being unused. */ diff --git a/gcc/testsuite/gcc.dg/unwind-1.c b/gcc/testsuite/gcc.dg/unwind-1.c index 95bbb2daa50..a035af1f2c2 100644 --- a/gcc/testsuite/gcc.dg/unwind-1.c +++ b/gcc/testsuite/gcc.dg/unwind-1.c @@ -1,4 +1,4 @@ -/* { dg-do assemble { target { ! { powerpc-ibm-aix* } } } } */ +/* { dg-do assemble { target { ! { powerpc-ibm-aix* nvptx-*-* } } } } */ /* { dg-options "-fleading-underscore -funwind-tables" } */ void func(void) __asm("_func"); diff --git a/gcc/testsuite/gcc.dg/vect/costmodel/i386/costmodel-vect-reduc-1char.c b/gcc/testsuite/gcc.dg/vect/costmodel/i386/costmodel-vect-reduc-1char.c index 29bb6c705b7..ff955afb90a 100644 --- a/gcc/testsuite/gcc.dg/vect/costmodel/i386/costmodel-vect-reduc-1char.c +++ b/gcc/testsuite/gcc.dg/vect/costmodel/i386/costmodel-vect-reduc-1char.c @@ -47,5 +47,5 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" { xfail vect_no_int_max } } } */ +/* { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" { xfail vect_no_int_min_max } } } */ /* { dg-final { scan-tree-dump-times "vectorization not profitable" 0 "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-vect-reduc-1char.c b/gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-vect-reduc-1char.c index 318346a00f1..82b614bc4ae 100644 --- a/gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-vect-reduc-1char.c +++ b/gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-vect-reduc-1char.c @@ -46,5 +46,5 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" { xfail vect_no_int_max } } } */ +/* { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" { xfail vect_no_int_min_max } } } */ /* { dg-final { scan-tree-dump-times "vectorization not profitable" 0 "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/costmodel/x86_64/costmodel-vect-reduc-1char.c b/gcc/testsuite/gcc.dg/vect/costmodel/x86_64/costmodel-vect-reduc-1char.c index 29bb6c705b7..ff955afb90a 100644 --- a/gcc/testsuite/gcc.dg/vect/costmodel/x86_64/costmodel-vect-reduc-1char.c +++ b/gcc/testsuite/gcc.dg/vect/costmodel/x86_64/costmodel-vect-reduc-1char.c @@ -47,5 +47,5 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" { xfail vect_no_int_max } } } */ +/* { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" { xfail vect_no_int_min_max } } } */ /* { dg-final { scan-tree-dump-times "vectorization not profitable" 0 "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/no-scevccp-noreassoc-slp-reduc-7.c b/gcc/testsuite/gcc.dg/vect/no-scevccp-noreassoc-slp-reduc-7.c index bbaf964eab0..1d674504e2c 100644 --- a/gcc/testsuite/gcc.dg/vect/no-scevccp-noreassoc-slp-reduc-7.c +++ b/gcc/testsuite/gcc.dg/vect/no-scevccp-noreassoc-slp-reduc-7.c @@ -36,6 +36,6 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail vect_no_int_max } } } */ -/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { xfail vect_no_int_max } } } */ +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail vect_no_int_min_max } } } */ +/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { xfail vect_no_int_min_max } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/no-scevccp-outer-11.c b/gcc/testsuite/gcc.dg/vect/no-scevccp-outer-11.c index a25001b57bf..f5aeac98187 100644 --- a/gcc/testsuite/gcc.dg/vect/no-scevccp-outer-11.c +++ b/gcc/testsuite/gcc.dg/vect/no-scevccp-outer-11.c @@ -46,4 +46,4 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "OUTER LOOP VECTORIZED." 1 "vect" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump-times "OUTER LOOP VECTORIZED." 1 "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/slp-reduc-4.c b/gcc/testsuite/gcc.dg/vect/slp-reduc-4.c index 3572dfc9fbf..c41d322445a 100644 --- a/gcc/testsuite/gcc.dg/vect/slp-reduc-4.c +++ b/gcc/testsuite/gcc.dg/vect/slp-reduc-4.c @@ -56,6 +56,6 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail vect_no_int_max } } } */ -/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { xfail vect_no_int_max } } } */ +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail vect_no_int_min_max } } } */ +/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { xfail vect_no_int_min_max } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/slp-reduc-5.c b/gcc/testsuite/gcc.dg/vect/slp-reduc-5.c index b1590d825e6..fc689e46ba1 100644 --- a/gcc/testsuite/gcc.dg/vect/slp-reduc-5.c +++ b/gcc/testsuite/gcc.dg/vect/slp-reduc-5.c @@ -42,6 +42,6 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 2 "vect" { xfail vect_no_int_max } } } */ -/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { xfail vect_no_int_max } } } */ +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 2 "vect" { xfail vect_no_int_min_max } } } */ +/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "vect" { xfail vect_no_int_min_max } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/trapv-vect-reduc-4.c b/gcc/testsuite/gcc.dg/vect/trapv-vect-reduc-4.c index 8fd353c623d..f801e763f92 100644 --- a/gcc/testsuite/gcc.dg/vect/trapv-vect-reduc-4.c +++ b/gcc/testsuite/gcc.dg/vect/trapv-vect-reduc-4.c @@ -47,4 +47,4 @@ int main (void) } /* { dg-final { scan-tree-dump-times "Detected reduction\\." 2 "vect" } } */ -/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" { target { ! { sparc*-*-* } } } } } */ +/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" { target { ! vect_no_int_min_max } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-125.c b/gcc/testsuite/gcc.dg/vect/vect-125.c index 0b3623ed06d..4a3c0dc7a3a 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-125.c +++ b/gcc/testsuite/gcc.dg/vect/vect-125.c @@ -16,4 +16,4 @@ void train(short *t, short *w, int n, int err) } } -/* { dg-final { scan-tree-dump "vectorized 1 loops" "vect" { xfail vect_no_int_max } } } */ +/* { dg-final { scan-tree-dump "vectorized 1 loops" "vect" { xfail vect_no_int_min_max } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-13.c b/gcc/testsuite/gcc.dg/vect/vect-13.c index 752fea822d7..5d902924ec2 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-13.c +++ b/gcc/testsuite/gcc.dg/vect/vect-13.c @@ -38,5 +38,5 @@ int main (void) return main1 (); } -/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail vect_no_int_max } } } */ +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail vect_no_int_min_max } } } */ /* { dg-final { scan-tree-dump-times "Vectorizing an unaligned access" 0 "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-double-reduc-3.c b/gcc/testsuite/gcc.dg/vect/vect-double-reduc-3.c index f2becfa8b4a..3bdf9efe947 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-double-reduc-3.c +++ b/gcc/testsuite/gcc.dg/vect/vect-double-reduc-3.c @@ -61,5 +61,5 @@ int main () return 0; } -/* { dg-final { scan-tree-dump-times "OUTER LOOP VECTORIZED" 1 "vect" { xfail vect_no_int_max } } } */ +/* { dg-final { scan-tree-dump-times "OUTER LOOP VECTORIZED" 1 "vect" { xfail vect_no_int_min_max } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-reduc-1.c b/gcc/testsuite/gcc.dg/vect/vect-reduc-1.c index 99abe06901e..aafa9a2c96d 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-reduc-1.c +++ b/gcc/testsuite/gcc.dg/vect/vect-reduc-1.c @@ -52,4 +52,4 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" { xfail { vect_no_int_add || vect_no_int_max } } } } */ +/* { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" { xfail { vect_no_int_add || vect_no_int_min_max } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-reduc-1char-big-array.c b/gcc/testsuite/gcc.dg/vect/vect-reduc-1char-big-array.c index a25b6cbfc90..660e0fdf5fb 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-reduc-1char-big-array.c +++ b/gcc/testsuite/gcc.dg/vect/vect-reduc-1char-big-array.c @@ -67,4 +67,4 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" { xfail vect_no_int_max } } } */ +/* { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" { xfail vect_no_int_min_max } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-reduc-1char.c b/gcc/testsuite/gcc.dg/vect/vect-reduc-1char.c index 644b474f57e..d5c62211d9f 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-reduc-1char.c +++ b/gcc/testsuite/gcc.dg/vect/vect-reduc-1char.c @@ -47,4 +47,4 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" { xfail vect_no_int_max } } } */ +/* { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" { xfail vect_no_int_min_max } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-reduc-1short.c b/gcc/testsuite/gcc.dg/vect/vect-reduc-1short.c index 32eb324ae5a..8bbc68c201a 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-reduc-1short.c +++ b/gcc/testsuite/gcc.dg/vect/vect-reduc-1short.c @@ -47,4 +47,4 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" { xfail vect_no_int_max } } } */ +/* { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" { xfail vect_no_int_min_max } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-reduc-2.c b/gcc/testsuite/gcc.dg/vect/vect-reduc-2.c index 44f0fc701b8..656e5719491 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-reduc-2.c +++ b/gcc/testsuite/gcc.dg/vect/vect-reduc-2.c @@ -49,4 +49,4 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" { xfail { vect_no_int_add || vect_no_int_max } } } } */ +/* { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" { xfail { vect_no_int_add || vect_no_int_min_max } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/wrapv-vect-reduc-2char.c b/gcc/testsuite/gcc.dg/vect/wrapv-vect-reduc-2char.c index 6b3cd09e116..556c2a06dc5 100644 --- a/gcc/testsuite/gcc.dg/vect/wrapv-vect-reduc-2char.c +++ b/gcc/testsuite/gcc.dg/vect/wrapv-vect-reduc-2char.c @@ -47,4 +47,4 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" { xfail vect_no_int_max } } } */ +/* { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" { xfail vect_no_int_min_max } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/wrapv-vect-reduc-2short.c b/gcc/testsuite/gcc.dg/vect/wrapv-vect-reduc-2short.c index 0a4df48abb3..f9142173b25 100644 --- a/gcc/testsuite/gcc.dg/vect/wrapv-vect-reduc-2short.c +++ b/gcc/testsuite/gcc.dg/vect/wrapv-vect-reduc-2short.c @@ -46,4 +46,4 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" { xfail vect_no_int_max } } } */ +/* { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" { xfail vect_no_int_min_max } } } */ diff --git a/gcc/testsuite/gcc.dg/vla-2.c b/gcc/testsuite/gcc.dg/vla-2.c index 72c64659030..e6ddcccfb4b 100644 --- a/gcc/testsuite/gcc.dg/vla-2.c +++ b/gcc/testsuite/gcc.dg/vla-2.c @@ -1,5 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-std=gnu99" } */ +/* { dg-require-effective-target alloca } */ /* These are crash tests related to PR middle-end/6994; see also g++.dg/ext/vla1.C. Note that at present A and C cannot be inlined. */ diff --git a/gcc/testsuite/gcc.dg/vla-22.c b/gcc/testsuite/gcc.dg/vla-22.c index f924650af03..8025bae8f6f 100644 --- a/gcc/testsuite/gcc.dg/vla-22.c +++ b/gcc/testsuite/gcc.dg/vla-22.c @@ -1,5 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O2" } */ +/* { dg-require-effective-target alloca } */ extern void bar (int *); diff --git a/gcc/testsuite/gcc.dg/vla-3.c b/gcc/testsuite/gcc.dg/vla-3.c index 619c0422a4d..51dae42f7ec 100644 --- a/gcc/testsuite/gcc.dg/vla-3.c +++ b/gcc/testsuite/gcc.dg/vla-3.c @@ -1,5 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-std=gnu99" } */ +/* { dg-require-effective-target alloca } */ /* This used to crash as we did not preserve the correct type for __SIZE_TYPE__. See PR22439. */ diff --git a/gcc/testsuite/gcc.dg/vla-4.c b/gcc/testsuite/gcc.dg/vla-4.c index 7ffbfb31b8e..c4a68fea9d9 100644 --- a/gcc/testsuite/gcc.dg/vla-4.c +++ b/gcc/testsuite/gcc.dg/vla-4.c @@ -1,5 +1,6 @@ /* { dg-do run } */ /* { dg-options "-std=c99 -pedantic-errors" } */ +/* { dg-require-effective-target alloca } */ /* PR c/18740 */ static int i; diff --git a/gcc/testsuite/gcc.dg/weak/weak-18.c b/gcc/testsuite/gcc.dg/weak/weak-18.c new file mode 100644 index 00000000000..ebeb4d5ba8a --- /dev/null +++ b/gcc/testsuite/gcc.dg/weak/weak-18.c @@ -0,0 +1,9 @@ +/* PR middle-end/67330 */ +/* { dg-do compile } */ +/* { dg-require-weak "" } */ + +void +f (void) +{ + __attribute__ ((weak)) int a; /* { dg-error "weak declaration of .a. must be public" } */ +} diff --git a/gcc/testsuite/gcc.dg/wide-shift-128.c b/gcc/testsuite/gcc.dg/wide-shift-128.c new file mode 100644 index 00000000000..d769833af04 --- /dev/null +++ b/gcc/testsuite/gcc.dg/wide-shift-128.c @@ -0,0 +1,11 @@ +/* { dg-do compile { target aarch64*-*-* mips64*-*-* sparc64*-*-* } } */ +/* { dg-require-effective-target int128 } */ +/* { dg-options "-O2 -fdump-rtl-combine" } */ + +__int128_t +load2 (int data) +{ + return (__int128_t) data << 50; +} + +/* { dg-final { scan-rtl-dump-not "ior" "combine" } } */ diff --git a/gcc/testsuite/gcc.dg/wide-shift-64.c b/gcc/testsuite/gcc.dg/wide-shift-64.c new file mode 100644 index 00000000000..c1624c5cdbf --- /dev/null +++ b/gcc/testsuite/gcc.dg/wide-shift-64.c @@ -0,0 +1,10 @@ +/* { dg-do compile { target mips*-*-* sparc*-*-* } } */ +/* { dg-options "-O2 -fdump-rtl-combine" } */ + +long long +load1 (int data) +{ + return (long long) data << 12; +} + +/* { dg-final { scan-rtl-dump-not "ior" "combine" } } */ diff --git a/gcc/testsuite/gcc.dg/winline-7.c b/gcc/testsuite/gcc.dg/winline-7.c index 33ad74b43c1..e3ac1296583 100644 --- a/gcc/testsuite/gcc.dg/winline-7.c +++ b/gcc/testsuite/gcc.dg/winline-7.c @@ -1,5 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-Winline -O2 -fgnu89-inline" } */ +/* { dg-require-effective-target alloca } */ extern void *alloca (__SIZE_TYPE__); diff --git a/gcc/testsuite/gcc.misc-tests/options.exp b/gcc/testsuite/gcc.misc-tests/options.exp index 258c9f4c3c4..384c3de03b7 100644 --- a/gcc/testsuite/gcc.misc-tests/options.exp +++ b/gcc/testsuite/gcc.misc-tests/options.exp @@ -21,6 +21,12 @@ load_lib gcc-defs.exp +# disable for non-profile targets explitly, rather than +# rely on check-effective target. We're explicitly trying to check +# profiling works, and if it doesn't check-effective-target will +# simply skip the tests, rather than have this test shout at us. +if [ istarget "nvptx-*-*" ] { return 0 } + # These tests don't run runtest_file_p consistently if it # doesn't return the same values, so disable parallelization # of this *.exp file. The first parallel runtest to reach diff --git a/gcc/testsuite/gcc.target/aarch64/ashltidisi.c b/gcc/testsuite/gcc.target/aarch64/ashltidisi.c new file mode 100644 index 00000000000..293a0f2563b --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/ashltidisi.c @@ -0,0 +1,49 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -save-temps" } */ + +extern void abort (void); + +#define GEN_TEST_CASE(x, y, z)\ +__uint128_t __attribute__ ((noinline))\ +ushift_##x##_##z (unsigned y data)\ +{\ + return (__uint128_t) data << x;\ +}\ +__int128_t __attribute__ ((noinline)) \ +shift_##x##_##z (y data) \ +{\ + return (__int128_t) data << x;\ +} + +GEN_TEST_CASE (53, int, i) +GEN_TEST_CASE (3, long long, ll) +GEN_TEST_CASE (13, long long, ll) +GEN_TEST_CASE (53, long long, ll) + +int +main (int argc, char **argv) +{ + +#define SHIFT_CHECK(x, y, z, p) \ + if (ushift_##y##_##p (x)\ + != ((__uint128_t) (unsigned z) x << y)) \ + abort ();\ + if (shift_##y##_##p (x)\ + != ((__uint128_t) (signed z) x << y)) \ + abort (); + + SHIFT_CHECK (0x12345678, 53, int, i) + SHIFT_CHECK (0xcafecafe, 53, int, i) + + SHIFT_CHECK (0x1234567890abcdefLL, 3, long long, ll) + SHIFT_CHECK (0x1234567890abcdefLL, 13, long long, ll) + SHIFT_CHECK (0x1234567890abcdefLL, 53, long long, ll) + SHIFT_CHECK (0xcafecafedeaddeadLL, 3, long long, ll) + SHIFT_CHECK (0xcafecafedeaddeadLL, 13, long long, ll) + SHIFT_CHECK (0xcafecafedeaddeadLL, 53, long long, ll) + + return 0; +} + +/* { dg-final { scan-assembler-times "asr" 4 } } */ +/* { dg-final { scan-assembler-not "extr\t" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/combine_bfi_1.c b/gcc/testsuite/gcc.target/aarch64/combine_bfi_1.c new file mode 100644 index 00000000000..accf1441093 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/combine_bfi_1.c @@ -0,0 +1,34 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-rtl-combine" } */ + +int +f1 (int x, int y) +{ + return (x & ~0x0ffff00) | ((y << 8) & 0x0ffff00); +} + +int +f2 (int x, int y) +{ + return (x & ~0x0ff000) | ((y & 0x0ff) << 12); +} + +int +f3 (int x, int y) +{ + return (x & ~0xffff) | (y & 0xffff); +} + +int +f4 (int x, int y) +{ + return (x & ~0xff) | (y & 0xff); +} + +long +f5 (long x, long y) +{ + return (x & ~0xffffffffull) | (y & 0xffffffff); +} + +/* { dg-final { scan-rtl-dump-times "\\*aarch64_bfi" 5 "combine" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/long_branch_1.c b/gcc/testsuite/gcc.target/aarch64/long_branch_1.c new file mode 100644 index 00000000000..46f500d36a2 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/long_branch_1.c @@ -0,0 +1,91 @@ +/* { dg-do assemble } */ +/* { dg-timeout-factor 2.0 } */ +/* { dg-options "-O1 -fno-reorder-blocks -fno-tree-cselim --save-temps" } */ + + +__attribute__((noinline, noclone)) int +restore (int a, int b) +{ + return a * b; +} + +__attribute__((noinline, noclone)) void +do_nothing (int *input) +{ + *input = restore (*input, 1); + return; +} +#define ENTRY_SUM(n, x) \ + sum = sum / ((n) + (x)); \ + sum = restore (sum, (n) + (x)); + +#define ENTRY_SUM2(n, x) ENTRY_SUM ((n), (x)) ENTRY_SUM ((n), (x)+1) +#define ENTRY_SUM4(n, x) ENTRY_SUM2 ((n), (x)) ENTRY_SUM2 ((n), (x)+2) +#define ENTRY_SUM8(n, x) ENTRY_SUM4 ((n), (x)) ENTRY_SUM4 ((n), (x)+4) +#define ENTRY_SUM16(n, x) ENTRY_SUM8 ((n), (x)) ENTRY_SUM8 ((n), (x)+8) +#define ENTRY_SUM32(n, x) ENTRY_SUM16 ((n), (x)) ENTRY_SUM16 ((n), (x)+16) +#define ENTRY_SUM64(n, x) ENTRY_SUM32 ((n), (x)) ENTRY_SUM32 ((n), (x)+32) +#define ENTRY_SUM128(n, x) ENTRY_SUM64 ((n), (x)) ENTRY_SUM64 ((n), (x)+64) + +#define CASE_ENTRY(n) \ + case n: \ + sum = sum / (n + 1); \ + sum = restore (sum, n + 1); \ + if (sum == (n + addend)) \ + break;\ + ENTRY_SUM128 ((n), 2) \ + ENTRY_SUM16 ((n), 130) \ + break; + +#define CASE_ENTRY2(n) CASE_ENTRY ((n)) CASE_ENTRY ((n)+1) +#define CASE_ENTRY4(n) CASE_ENTRY2 ((n)) CASE_ENTRY2 ((n)+2) +#define CASE_ENTRY8(n) CASE_ENTRY4 ((n)) CASE_ENTRY4 ((n)+4) +#define CASE_ENTRY16(n) CASE_ENTRY8 ((n)) CASE_ENTRY8 ((n)+8) +#define CASE_ENTRY32(n) CASE_ENTRY16 ((n)) CASE_ENTRY16 ((n)+16) +#define CASE_ENTRY64(n) CASE_ENTRY32 ((n)) CASE_ENTRY32 ((n)+32) +#define CASE_ENTRY128(n) CASE_ENTRY64 ((n)) CASE_ENTRY64 ((n)+64) + +__attribute__((noinline, noclone)) long long +test_and_branch (int selector, int addend, int cond) +{ + long long sum = selector + 1; + + if (selector > 200) + { +start0: + return sum - 1; +start1: + return sum + 1; +start2: + return sum; +start3: + return sum - 2; + } + else + { + switch (selector) + { + CASE_ENTRY128 (1) + CASE_ENTRY64 (129) + CASE_ENTRY16 (193) + } + + do_nothing ((int *)&sum); + + if (cond == 0) + goto start0; + else if (cond < 0) + goto start1; + else if ((cond & 0x010) != 0) + goto start2; + else if (cond >= 14) + goto start3; + + } + + return -1; +} + +/* { dg-final { scan-assembler "Lbcond" } } */ +/* { dg-final { scan-assembler "Lcb" } } */ +/* { dg-final { scan-assembler "Ltb" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/target_attr_crypto_ice_2.c b/gcc/testsuite/gcc.target/aarch64/target_attr_crypto_ice_2.c new file mode 100644 index 00000000000..d6e7b681832 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/target_attr_crypto_ice_2.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mcpu=thunderx+nofp" } */ + +/* Make sure that we don't ICE when dealing with vector parameters + in a simd-tagged function within a non-simd translation unit. */ + +#pragma GCC push_options +#pragma GCC target ("+nothing+simd") +typedef unsigned int __uint32_t; +typedef __uint32_t uint32_t ; +typedef __Uint32x4_t uint32x4_t; +#pragma GCC pop_options + + +__attribute__ ((target ("cpu=cortex-a57"))) +uint32x4_t +foo (uint32x4_t a, uint32_t b, uint32x4_t c) +{ + return c; +} diff --git a/gcc/testsuite/gcc.target/aarch64/tls_1.x b/gcc/testsuite/gcc.target/aarch64/tls_1.x new file mode 100644 index 00000000000..d92281b6de2 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/tls_1.x @@ -0,0 +1,14 @@ +void abort (void); + +__thread int t0 = 0x10; +__thread int t1 = 0x10; + +int +main (int argc, char **argv) +{ + if (t0 != t1) + abort (); + + return 0; +} + diff --git a/gcc/testsuite/gcc.target/aarch64/tlsie_tiny_1.c b/gcc/testsuite/gcc.target/aarch64/tlsie_tiny_1.c new file mode 100644 index 00000000000..7477fa60661 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/tlsie_tiny_1.c @@ -0,0 +1,7 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target tls_native } */ +/* { dg-options "-O2 -fpic -ftls-model=initial-exec -mcmodel=tiny" } */ + +#include "tls_1.x" + +/* { dg-final { scan-assembler-times ":gottprel:" 2 } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/tlsle12_1.c b/gcc/testsuite/gcc.target/aarch64/tlsle12_1.c new file mode 100644 index 00000000000..c0bf488b3b6 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/tlsle12_1.c @@ -0,0 +1,8 @@ +/* { dg-do run } */ +/* { dg-require-effective-target tls_native } */ +/* { dg-options "-O2 -fpic -ftls-model=local-exec -mtls-size=12 --save-temps" } */ + +#include "tls_1.x" + +/* { dg-final { scan-assembler-times "#:tprel_lo12" 2 } } */ +/* { dg-final { cleanup-saved-temps } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/tlsle24_1.c b/gcc/testsuite/gcc.target/aarch64/tlsle24_1.c new file mode 100644 index 00000000000..9acc4c85a76 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/tlsle24_1.c @@ -0,0 +1,9 @@ +/* { dg-do run } */ +/* { dg-require-effective-target tls_native } */ +/* { dg-options "-O2 -fpic -ftls-model=local-exec -mtls-size=24 --save-temps" } */ + +#include "tls_1.x" + +/* { dg-final { scan-assembler-times "#:tprel_lo12_nc" 2 } } */ +/* { dg-final { scan-assembler-times "#:tprel_hi12" 2 } } */ +/* { dg-final { cleanup-saved-temps } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/tlsle32_1.c b/gcc/testsuite/gcc.target/aarch64/tlsle32_1.c new file mode 100644 index 00000000000..0610d2ac15c --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/tlsle32_1.c @@ -0,0 +1,10 @@ +/* { dg-do run } */ +/* { dg-require-effective-target tls_native } */ +/* { dg-require-effective-target aarch64_tlsle32 } */ +/* { dg-options "-O2 -fpic -ftls-model=local-exec -mtls-size=32 --save-temps" } */ + +#include "tls_1.x" + +/* { dg-final { scan-assembler-times "#:tprel_g1" 2 } } */ +/* { dg-final { scan-assembler-times "#:tprel_g0_nc" 2 } } */ +/* { dg-final { cleanup-saved-temps } } */ diff --git a/gcc/testsuite/gcc.target/i386/adx-addcarryx32-1.c b/gcc/testsuite/gcc.target/i386/adx-addcarryx32-1.c index 9fff611b6c0..b0ba6e253df 100644 --- a/gcc/testsuite/gcc.target/i386/adx-addcarryx32-1.c +++ b/gcc/testsuite/gcc.target/i386/adx-addcarryx32-1.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-madx -O2" } */ -/* { dg-final { scan-assembler-times "adcx" 2 } } */ +/* { dg-final { scan-assembler-times "adc\[xl\]" 2 } } */ /* { dg-final { scan-assembler-times "sbbl" 1 } } */ #include <x86intrin.h> diff --git a/gcc/testsuite/gcc.target/i386/adx-addcarryx64-1.c b/gcc/testsuite/gcc.target/i386/adx-addcarryx64-1.c index 3608dea79b9..cbe19856c6f 100644 --- a/gcc/testsuite/gcc.target/i386/adx-addcarryx64-1.c +++ b/gcc/testsuite/gcc.target/i386/adx-addcarryx64-1.c @@ -1,6 +1,6 @@ /* { dg-do compile { target { ! ia32 } } } */ /* { dg-options "-madx -O2" } */ -/* { dg-final { scan-assembler-times "adcx" 2 } } */ +/* { dg-final { scan-assembler-times "adc\[xq\]" 2 } } */ /* { dg-final { scan-assembler-times "sbbq" 1 } } */ #include <x86intrin.h> diff --git a/gcc/testsuite/gcc.target/i386/pr66821.c b/gcc/testsuite/gcc.target/i386/pr66821.c new file mode 100644 index 00000000000..d32f03d5a96 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr66821.c @@ -0,0 +1,15 @@ +/* { dg-do compile { target ia32 } } */ +/* { dg-options "-O2 -fdump-tree-optimized -mtune=iamcu" } */ + +void bar (void); + +void +foo (int x) +{ + if (x != 2 && x != 3 && x != 10 && x != 11 && x != 17 && x != 18 && x != 23) + bar (); +} + +/* Check if the tests have been folded into a bit test. */ +/* { dg-final { scan-tree-dump "(8784908|0x0*860c0c)" "optimized" } } */ +/* { dg-final { scan-tree-dump "(<<|>>)" "optimized" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr67317-1.c b/gcc/testsuite/gcc.target/i386/pr67317-1.c new file mode 100644 index 00000000000..7db4e5f31a7 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr67317-1.c @@ -0,0 +1,18 @@ +/* PR target/67317 */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +typedef unsigned int u32; + +u32 testcarry_u32 (u32 a, u32 b, u32 c, u32 d) +{ + u32 result0, result1; + + __builtin_ia32_addcarryx_u32 + (__builtin_ia32_addcarryx_u32 (0, a, c, &result0), b, d, &result1); + + return result0 ^ result1; +} + +/* { dg-final { scan-assembler-not "addb" } } */ +/* { dg-final { scan-assembler-not "setn?c" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr67317-2.c b/gcc/testsuite/gcc.target/i386/pr67317-2.c new file mode 100644 index 00000000000..97b2eff88dc --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr67317-2.c @@ -0,0 +1,18 @@ +/* PR target/67317 */ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-O2" } */ + +typedef unsigned long long u64; + +u64 testcarry_u64 (u64 a, u64 b, u64 c, u64 d) +{ + u64 result0, result1; + + __builtin_ia32_addcarryx_u64 + (__builtin_ia32_addcarryx_u64 (0, a, c, &result0), b, d, &result1); + + return result0 ^ result1; +} + +/* { dg-final { scan-assembler-not "addb" } } */ +/* { dg-final { scan-assembler-not "setn?c" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr67317-3.c b/gcc/testsuite/gcc.target/i386/pr67317-3.c new file mode 100644 index 00000000000..c141d098108 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr67317-3.c @@ -0,0 +1,18 @@ +/* PR target/67317 */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +typedef unsigned int u32; + +u32 testcarry_u32 (u32 a, u32 b, u32 c, u32 d) +{ + u32 result0, result1; + + __builtin_ia32_sbb_u32 + (__builtin_ia32_sbb_u32 (0, a, c, &result0), b, d, &result1); + + return result0 ^ result1; +} + +/* { dg-final { scan-assembler-not "addb" } } */ +/* { dg-final { scan-assembler-not "setn?c" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr67317-4.c b/gcc/testsuite/gcc.target/i386/pr67317-4.c new file mode 100644 index 00000000000..2f95dbc16f3 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr67317-4.c @@ -0,0 +1,18 @@ +/* PR target/67317 */ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-O2" } */ + +typedef unsigned long long u64; + +u64 testcarry_u64 (u64 a, u64 b, u64 c, u64 d) +{ + u64 result0, result1; + + __builtin_ia32_sbb_u64 + (__builtin_ia32_sbb_u64 (0, a, c, &result0), b, d, &result1); + + return result0 ^ result1; +} + +/* { dg-final { scan-assembler-not "addb" } } */ +/* { dg-final { scan-assembler-not "setn?c" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr67329.c b/gcc/testsuite/gcc.target/i386/pr67329.c new file mode 100644 index 00000000000..a29dd5b4f8d --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr67329.c @@ -0,0 +1,20 @@ +/* { dg-do compile { target ia32 } } */ +/* { dg-options "-O3 -fno-tree-fre -fno-tree-pre -fdump-tree-optimized -mtune=iamcu" } */ + +int +foo () +{ + const int a[8] = { 0, 1, 2, 3, 4, 5, 6, 7 }; + int i, sum; + + sum = 0; + for (i = 0; i < sizeof (a) / sizeof (*a); i++) + sum += a[i]; + + return sum; +} + +/* After late unrolling the above loop completely DOM should be + able to optimize this to return 28. */ + +/* { dg-final { scan-tree-dump "return 28;" "optimized" } } */ diff --git a/gcc/testsuite/gcc.target/i386/ssp-default.c b/gcc/testsuite/gcc.target/i386/ssp-default.c new file mode 100644 index 00000000000..3f65ed8a80d --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/ssp-default.c @@ -0,0 +1,22 @@ +/* { dg-do run { target native } } */ +/* { dg-require-effective-target fstack_protector_enabled } */ + +#include <stdlib.h> + +void +__stack_chk_fail (void) +{ + exit (0); /* pass */ +} + +int main () +{ + int i; + char foo[255]; + + /* smash stack */ + for (i = 0; i <= 400; i++) + foo[i] = 42; + + return 1; /* fail */ +} diff --git a/gcc/testsuite/gcc.target/mips/branch-10.c b/gcc/testsuite/gcc.target/mips/branch-10.c index eb21c165462..9428254f0df 100644 --- a/gcc/testsuite/gcc.target/mips/branch-10.c +++ b/gcc/testsuite/gcc.target/mips/branch-10.c @@ -1,6 +1,6 @@ /* { dg-options "-mshared -mabi=n32" } */ /* { dg-final { scan-assembler-not "(\\\$28|%gp_rel|%got)" } } */ -/* { dg-final { scan-assembler-not "\tjr\t\\\$1\n" } } */ +/* { dg-final { scan-assembler-not "\tjrc?\t\\\$1\n" } } */ #include "branch-helper.h" diff --git a/gcc/testsuite/gcc.target/mips/branch-11.c b/gcc/testsuite/gcc.target/mips/branch-11.c index bd8e83418c0..9238d9ca1eb 100644 --- a/gcc/testsuite/gcc.target/mips/branch-11.c +++ b/gcc/testsuite/gcc.target/mips/branch-11.c @@ -4,7 +4,7 @@ /* { dg-final { scan-assembler "\taddiu\t\\\$28,\\\$28,%lo\\(%neg\\(%gp_rel\\(foo\\)\\)\\)\n" } } */ /* { dg-final { scan-assembler "\tlw\t\\\$1,%got_page\\(\[^)\]*\\)\\(\\\$28\\)\n" } } */ /* { dg-final { scan-assembler "\taddiu\t\\\$1,\\\$1,%got_ofst\\(\[^)\]*\\)\n" } } */ -/* { dg-final { scan-assembler "\tjr\t\\\$1\n" } } */ +/* { dg-final { scan-assembler "\tjrc?\t\\\$1\n" } } */ #include "branch-helper.h" diff --git a/gcc/testsuite/gcc.target/mips/branch-12.c b/gcc/testsuite/gcc.target/mips/branch-12.c index 49446341ad2..97261acea60 100644 --- a/gcc/testsuite/gcc.target/mips/branch-12.c +++ b/gcc/testsuite/gcc.target/mips/branch-12.c @@ -1,6 +1,6 @@ /* { dg-options "-mshared -mabi=64" } */ /* { dg-final { scan-assembler-not "(\\\$28|%gp_rel|%got)" } } */ -/* { dg-final { scan-assembler-not "\tjr\t\\\$1\n" } } */ +/* { dg-final { scan-assembler-not "\tjrc?\t\\\$1\n" } } */ #include "branch-helper.h" diff --git a/gcc/testsuite/gcc.target/mips/branch-13.c b/gcc/testsuite/gcc.target/mips/branch-13.c index f5269b9b33b..5ea5f1b64fe 100644 --- a/gcc/testsuite/gcc.target/mips/branch-13.c +++ b/gcc/testsuite/gcc.target/mips/branch-13.c @@ -4,7 +4,7 @@ /* { dg-final { scan-assembler "\tdaddiu\t\\\$28,\\\$28,%lo\\(%neg\\(%gp_rel\\(foo\\)\\)\\)\n" } } */ /* { dg-final { scan-assembler "\tld\t\\\$1,%got_page\\(\[^)\]*\\)\\(\\\$28\\)\n" } } */ /* { dg-final { scan-assembler "\tdaddiu\t\\\$1,\\\$1,%got_ofst\\(\[^)\]*\\)\n" } } */ -/* { dg-final { scan-assembler "\tjr\t\\\$1\n" } } */ +/* { dg-final { scan-assembler "\tjrc?\t\\\$1\n" } } */ #include "branch-helper.h" diff --git a/gcc/testsuite/gcc.target/mips/branch-3.c b/gcc/testsuite/gcc.target/mips/branch-3.c index 69300f6417c..310812aa4da 100644 --- a/gcc/testsuite/gcc.target/mips/branch-3.c +++ b/gcc/testsuite/gcc.target/mips/branch-3.c @@ -1,6 +1,6 @@ /* { dg-options "-mshared -mabi=32" } */ /* { dg-final { scan-assembler "\t\\.cpload\t\\\$25\n" } } */ -/* { dg-final { scan-assembler "\tjr\t\\\$1\n" } } */ +/* { dg-final { scan-assembler "\tjrc?\t\\\$1\n" } } */ /* { dg-final { scan-assembler-not "\\.cprestore" } } */ #include "branch-helper.h" diff --git a/gcc/testsuite/gcc.target/mips/branch-4.c b/gcc/testsuite/gcc.target/mips/branch-4.c index 29f5c9f2be3..9dec90469f5 100644 --- a/gcc/testsuite/gcc.target/mips/branch-4.c +++ b/gcc/testsuite/gcc.target/mips/branch-4.c @@ -1,6 +1,6 @@ /* { dg-options "-mshared -mabi=n32" } */ /* { dg-final { scan-assembler-not "(\\\$25|\\\$28|%gp_rel|%got)" } } */ -/* { dg-final { scan-assembler-not "\tjr\t\\\$1\n" } } */ +/* { dg-final { scan-assembler-not "\tjrc?\t\\\$1\n" } } */ #include "branch-helper.h" diff --git a/gcc/testsuite/gcc.target/mips/branch-5.c b/gcc/testsuite/gcc.target/mips/branch-5.c index 0538646210a..60daf27d06b 100644 --- a/gcc/testsuite/gcc.target/mips/branch-5.c +++ b/gcc/testsuite/gcc.target/mips/branch-5.c @@ -1,7 +1,7 @@ /* { dg-options "-mshared -mabi=n32" } */ /* { dg-final { scan-assembler "\taddiu\t\\\$3,\\\$3,%lo\\(%neg\\(%gp_rel\\(foo\\)\\)\\)\n" } } */ /* { dg-final { scan-assembler "\tlw\t\\\$1,%got_page\\(\[^)\]*\\)\\(\\\$3\\)\\n" } } */ -/* { dg-final { scan-assembler "\tjr\t\\\$1\n" } } */ +/* { dg-final { scan-assembler "\tjrc?\t\\\$1\n" } } */ /* { dg-final { scan-assembler-not "\\\$28" } } */ #include "branch-helper.h" diff --git a/gcc/testsuite/gcc.target/mips/branch-6.c b/gcc/testsuite/gcc.target/mips/branch-6.c index 19baee1db9f..4262ba7e849 100644 --- a/gcc/testsuite/gcc.target/mips/branch-6.c +++ b/gcc/testsuite/gcc.target/mips/branch-6.c @@ -1,6 +1,6 @@ /* { dg-options "-mshared -mabi=64" } */ /* { dg-final { scan-assembler-not "(\\\$25|\\\$28|%gp_rel|%got)" } } */ -/* { dg-final { scan-assembler-not "\tjr\t\\\$1\n" } } */ +/* { dg-final { scan-assembler-not "\tjrc?\t\\\$1\n" } } */ #include "branch-helper.h" diff --git a/gcc/testsuite/gcc.target/mips/branch-7.c b/gcc/testsuite/gcc.target/mips/branch-7.c index 16c6d8e1ac6..a0c28a2bb65 100644 --- a/gcc/testsuite/gcc.target/mips/branch-7.c +++ b/gcc/testsuite/gcc.target/mips/branch-7.c @@ -1,7 +1,7 @@ /* { dg-options "-mshared -mabi=64" } */ /* { dg-final { scan-assembler "\tdaddiu\t\\\$3,\\\$3,%lo\\(%neg\\(%gp_rel\\(foo\\)\\)\\)\n" } } */ /* { dg-final { scan-assembler "\tld\t\\\$1,%got_page\\(\[^)\]*\\)\\(\\\$3\\)\\n" } } */ -/* { dg-final { scan-assembler "\tjr\t\\\$1\n" } } */ +/* { dg-final { scan-assembler "\tjrc?\t\\\$1\n" } } */ /* { dg-final { scan-assembler-not "\\\$28" } } */ #include "branch-helper.h" diff --git a/gcc/testsuite/gcc.target/mips/branch-8.c b/gcc/testsuite/gcc.target/mips/branch-8.c index 2e468448fe9..5a5494e0bd1 100644 --- a/gcc/testsuite/gcc.target/mips/branch-8.c +++ b/gcc/testsuite/gcc.target/mips/branch-8.c @@ -1,6 +1,6 @@ /* { dg-options "-mshared -mabi=32" } */ /* { dg-final { scan-assembler-not "(\\\$28|cpload|cprestore)" } } */ -/* { dg-final { scan-assembler-not "\tjr\t\\\$1\n" } } */ +/* { dg-final { scan-assembler-not "\tjrc?\t\\\$1\n" } } */ #include "branch-helper.h" diff --git a/gcc/testsuite/gcc.target/mips/branch-9.c b/gcc/testsuite/gcc.target/mips/branch-9.c index b87f2ba675b..88a6d9a063f 100644 --- a/gcc/testsuite/gcc.target/mips/branch-9.c +++ b/gcc/testsuite/gcc.target/mips/branch-9.c @@ -4,7 +4,7 @@ /* { dg-final { scan-assembler "\tlw\t\\\$1,16\\(\\\$(fp|sp)\\)\n" } } */ /* { dg-final { scan-assembler "\tlw\t\\\$1,%got\\(\[^)\]*\\)\\(\\\$1\\)\n" } } */ /* { dg-final { scan-assembler "\taddiu\t\\\$1,\\\$1,%lo\\(\[^)\]*\\)\n" } } */ -/* { dg-final { scan-assembler "\tjr\t\\\$1\n" } } */ +/* { dg-final { scan-assembler "\tjrc?\t\\\$1\n" } } */ /* { dg-final { scan-assembler-not "\\\$28" } } */ #include "branch-helper.h" diff --git a/gcc/testsuite/gcc.target/mips/branch-cost-1.c b/gcc/testsuite/gcc.target/mips/branch-cost-1.c index f72f2acfb3a..61c3029dd77 100644 --- a/gcc/testsuite/gcc.target/mips/branch-cost-1.c +++ b/gcc/testsuite/gcc.target/mips/branch-cost-1.c @@ -6,4 +6,4 @@ foo (int x, int y, int z, int k) return x == k ? x + y : z - x; } /* { dg-final { scan-assembler-not "\t(movz|movn)\t" } } */ -/* { dg-final { scan-assembler "\t(bne|beq)\t" } } */ +/* { dg-final { scan-assembler "\t(bnec?|beqc?)\t" } } */ diff --git a/gcc/testsuite/gcc.target/mips/call-1.c b/gcc/testsuite/gcc.target/mips/call-1.c index a00126eb693..46a2536754b 100644 --- a/gcc/testsuite/gcc.target/mips/call-1.c +++ b/gcc/testsuite/gcc.target/mips/call-1.c @@ -1,12 +1,12 @@ /* { dg-options "-mrelax-pic-calls -mshared -foptimize-sibling-calls -mabi=32" } */ /* { dg-skip-if "requires -foptimize-sibling-calls" { *-*-* } { "-O0" } { "" } } */ -/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,normal\n1:\tjalrs?\t" } } */ -/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,normal2\n1:\tjalrs?\t" } } */ -/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,staticfunc\n1:\tjalrs?\t" } } */ -/* { dg-final { scan-assembler "(\\.reloc\t1f,R_MIPS_JALR,tail\n1:)?\tjrc?\t" } } */ -/* { dg-final { scan-assembler "(\\.reloc\t1f,R_MIPS_JALR,tail2\n1:)?\tjrc?\t" } } */ -/* { dg-final { scan-assembler "(\\.reloc\t1f,R_MIPS_JALR,tail3\n1:)?\tjrc?\t" } } */ -/* { dg-final { scan-assembler "(\\.reloc\t1f,R_MIPS_JALR,tail4\n1:)?\tjrc?\t" } } */ +/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,normal\n1:\tjalrc?s?\t" } } */ +/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,normal2\n1:\tjalrc?s?\t" } } */ +/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,staticfunc\n1:\tjalrc?s?\t" } } */ +/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail\n1:\tjrc?\t" } } */ +/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail2\n1:\tjrc?\t" } } */ +/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail3\n1:\tjrc?\t" } } */ +/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail4\n1:\tjrc?\t" } } */ __attribute__ ((noinline)) static void staticfunc () { asm (""); } int normal (); diff --git a/gcc/testsuite/gcc.target/mips/call-2.c b/gcc/testsuite/gcc.target/mips/call-2.c index 58cc2c6b03c..175933cbe77 100644 --- a/gcc/testsuite/gcc.target/mips/call-2.c +++ b/gcc/testsuite/gcc.target/mips/call-2.c @@ -1,6 +1,6 @@ /* See through some simple data-flow. */ /* { dg-options "-mrelax-pic-calls" } */ -/* { dg-final { scan-assembler-times "\\.reloc\t1f,R_MIPS_JALR,g\n1:\tjalrs?\t" 2 } } */ +/* { dg-final { scan-assembler-times "\\.reloc\t1f,R_MIPS_JALR,g\n1:\tjalrc?s?\t" 2 } } */ extern void g (void); diff --git a/gcc/testsuite/gcc.target/mips/call-3.c b/gcc/testsuite/gcc.target/mips/call-3.c index 4a662e300ec..08cf336a424 100644 --- a/gcc/testsuite/gcc.target/mips/call-3.c +++ b/gcc/testsuite/gcc.target/mips/call-3.c @@ -1,5 +1,5 @@ /* { dg-options "-mrelax-pic-calls -mno-shared" } */ -/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,g\n1:\tjalrs?\t" } } */ +/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,g\n1:\tjalrc?s?\t" } } */ /* { dg-require-visibility "" } */ __attribute__ ((visibility ("hidden"))) void g (); diff --git a/gcc/testsuite/gcc.target/mips/call-4.c b/gcc/testsuite/gcc.target/mips/call-4.c index a343c429a6a..bf357c7a5b0 100644 --- a/gcc/testsuite/gcc.target/mips/call-4.c +++ b/gcc/testsuite/gcc.target/mips/call-4.c @@ -1,6 +1,6 @@ /* See through some simple data-flow. */ /* { dg-options "-mrelax-pic-calls" } */ -/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,g\n1:\tjalr\t" } } */ +/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,g\n1:\tjalrc?\t" } } */ extern void g (void); diff --git a/gcc/testsuite/gcc.target/mips/call-5.c b/gcc/testsuite/gcc.target/mips/call-5.c index d8d84d3782e..f6ebae9db79 100644 --- a/gcc/testsuite/gcc.target/mips/call-5.c +++ b/gcc/testsuite/gcc.target/mips/call-5.c @@ -2,13 +2,13 @@ in this case (PR target/57260). */ /* { dg-options "-mrelax-pic-calls -mshared -foptimize-sibling-calls -mabi=n32" } */ /* { dg-skip-if "requires -foptimize-sibling-calls" { *-*-* } { "-O0" } { "" } } */ -/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,normal\n1:\tjalr\t" } } */ -/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,normal2\n1:\tjalr\t" } } */ -/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,staticfunc\n1:\tjalr\t" } } */ -/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail\n1:\tjalr\t" } } */ -/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail2\n1:\tjalr\t" } } */ -/* { dg-final { scan-assembler "(\\.reloc\t1f,R_MIPS_JALR,tail3\n1:)?\tjrc?\t" } } */ -/* { dg-final { scan-assembler "(\\.reloc\t1f,R_MIPS_JALR,tail4\n1:)?\tjrc?\t" } } */ +/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,normal\n1:\tjalrc?\t" } } */ +/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,normal2\n1:\tjalrc?\t" } } */ +/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,staticfunc\n1:\tjalrc?\t" } } */ +/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail\n1:\tjalrc?\t" } } */ +/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail2\n1:\tjalrc?\t" } } */ +/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail3\n1:\tjrc?\t" } } */ +/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail4\n1:\tjrc?\t" } } */ __attribute__ ((noinline)) static void staticfunc () { asm (""); } int normal (); diff --git a/gcc/testsuite/gcc.target/mips/call-6.c b/gcc/testsuite/gcc.target/mips/call-6.c index e6c90d7b5a3..00f4a1ef353 100644 --- a/gcc/testsuite/gcc.target/mips/call-6.c +++ b/gcc/testsuite/gcc.target/mips/call-6.c @@ -1,13 +1,13 @@ /* Like call-5.c, but for n64. */ /* { dg-options "-mrelax-pic-calls -mshared -foptimize-sibling-calls -mabi=64" } */ /* { dg-skip-if "requires -foptimize-sibling-calls" { *-*-* } { "-O0" } { "" } } */ -/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,normal\n1:\tjalr\t" } } */ -/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,normal2\n1:\tjalr\t" } } */ -/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,staticfunc\n1:\tjalr\t" } } */ -/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail\n1:\tjalr\t" } } */ -/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail2\n1:\tjalr\t" } } */ -/* { dg-final { scan-assembler "(\\.reloc\t1f,R_MIPS_JALR,tail3\n1:)?\tjrc?\t" } } */ -/* { dg-final { scan-assembler "(\\.reloc\t1f,R_MIPS_JALR,tail4\n1:)?\tjrc?\t" } } */ +/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,normal\n1:\tjalrc?\t" } } */ +/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,normal2\n1:\tjalrc?\t" } } */ +/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,staticfunc\n1:\tjalrc?\t" } } */ +/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail\n1:\tjalrc?\t" } } */ +/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail2\n1:\tjalrc?\t" } } */ +/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail3\n1:\tjrc?\t" } } */ +/* { dg-final { scan-assembler "\\.reloc\t1f,R_MIPS_JALR,tail4\n1:\tjrc?\t" } } */ __attribute__ ((noinline)) static void staticfunc () { asm (""); } int normal (); diff --git a/gcc/testsuite/gcc.target/mips/compact-branches-1.c b/gcc/testsuite/gcc.target/mips/compact-branches-1.c new file mode 100644 index 00000000000..9c7365e2659 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/compact-branches-1.c @@ -0,0 +1,12 @@ +/* { dg-options "-mcompact-branches=always -mno-micromips" } */ +int glob; + +void +foo (int a, int b) +{ + if (a < b) + glob = 1; +} + +/* { dg-final { scan-assembler "\tbgec\t\\\$\[0-9\]*,\\\$\[0-9\]*" } } */ +/* { dg-final { scan-assembler "\tjrc\t\\\$31" } } */ diff --git a/gcc/testsuite/gcc.target/mips/compact-branches-2.c b/gcc/testsuite/gcc.target/mips/compact-branches-2.c new file mode 100644 index 00000000000..0f8064f5d88 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/compact-branches-2.c @@ -0,0 +1,12 @@ +/* { dg-options "-mcompact-branches=never" } */ +int glob; + +void +foo (int a, int b) +{ + if (a < b) + glob = 1; +} + +/* { dg-final { scan-assembler-not "\tb\[^ \t\]*c" } } */ +/* { dg-final { scan-assembler-not "\tj\[^ \t\]*c" } } */ diff --git a/gcc/testsuite/gcc.target/mips/compact-branches-3.c b/gcc/testsuite/gcc.target/mips/compact-branches-3.c new file mode 100644 index 00000000000..d6becb10eee --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/compact-branches-3.c @@ -0,0 +1,13 @@ +/* { dg-options "-mcompact-branches=never isa_rev>=6" } */ +int glob; + +void +foo (int a, int b, volatile int * bar) +{ + if (a < b) + glob = *bar; +} + +/* { dg-final { scan-assembler "\tnop" } } */ +/* { dg-final { scan-assembler-not "\tb\[^ \t\]*c" } } */ +/* { dg-final { scan-assembler-not "\tj\[^ \t\]*c" } } */ diff --git a/gcc/testsuite/gcc.target/mips/compact-branches-4.c b/gcc/testsuite/gcc.target/mips/compact-branches-4.c new file mode 100644 index 00000000000..fd99ad64f6d --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/compact-branches-4.c @@ -0,0 +1,11 @@ +/* { dg-options "-mcompact-branches=optimal isa_rev>=6" } */ +int glob; + +void +foo (int a, int b, volatile int * bar) +{ + if (a < b) + glob = *bar; +} + +/* { dg-final { scan-assembler "\tb\[^ \t\]*c" } } */ diff --git a/gcc/testsuite/gcc.target/mips/compact-branches-5.c b/gcc/testsuite/gcc.target/mips/compact-branches-5.c new file mode 100644 index 00000000000..90d312c614d --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/compact-branches-5.c @@ -0,0 +1,10 @@ +/* { dg-options "-mno-abicalls -mcompact-branches=never isa_rev>=6" } */ +void bar (int); + +void +foo () +{ + bar (1); +} + +/* { dg-final { scan-assembler "\t(j|jal)\t" } } */ diff --git a/gcc/testsuite/gcc.target/mips/compact-branches-6.c b/gcc/testsuite/gcc.target/mips/compact-branches-6.c new file mode 100644 index 00000000000..dd35a5581bd --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/compact-branches-6.c @@ -0,0 +1,10 @@ +/* { dg-options "-mno-abicalls -mcompact-branches=optimal isa_rev>=6" } */ +void bar (int); + +void +foo () +{ + bar (1); +} + +/* { dg-final { scan-assembler "\t(bc|balc)\t" } } */ diff --git a/gcc/testsuite/gcc.target/mips/compact-branches-7.c b/gcc/testsuite/gcc.target/mips/compact-branches-7.c new file mode 100644 index 00000000000..36700c9a2ce --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/compact-branches-7.c @@ -0,0 +1,12 @@ +/* { dg-options "-mhard-float -mcompact-branches=always isa_rev>=6 -mno-micromips" } */ +int bar; + +void +foo (float a, volatile int * b) +{ + if (a < 0.1) + bar = *b; +} + +/* { dg-final { scan-assembler "\t(bc1eqz|bc1nez)\t" } } */ +/* { dg-final { scan-assembler "\tnop" } } */ diff --git a/gcc/testsuite/gcc.target/mips/inline-memcpy-1.c b/gcc/testsuite/gcc.target/mips/inline-memcpy-1.c new file mode 100644 index 00000000000..5a254b1eaa9 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/inline-memcpy-1.c @@ -0,0 +1,16 @@ +/* { dg-options "-fno-common isa_rev>=6" } */ +/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-Os" } { "" } } */ +/* { dg-final { scan-assembler-not "\tmemcpy" } } */ + +/* Test that memcpy is inline for target hardware + without swl, swr. */ + +#include <string.h> + +char c[40] __attribute__ ((aligned(8))); + +void +f1 () +{ + memcpy (c, "1234567890QWERTYUIOPASDFGHJKLZXCVBNM", 32); +} diff --git a/gcc/testsuite/gcc.target/mips/inline-memcpy-2.c b/gcc/testsuite/gcc.target/mips/inline-memcpy-2.c new file mode 100644 index 00000000000..e144e61a800 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/inline-memcpy-2.c @@ -0,0 +1,17 @@ +/* { dg-options "-fno-common isa_rev>=6" } */ +/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-Os"} { "" } } */ +/* { dg-final { scan-assembler-not "\tmemcpy" } } */ +/* { dg-final { scan-assembler-times "\tsh\t" 16 } } */ + +/* Test that inline memcpy is expanded for target hardware without + swl, swr when alignment is halfword and sufficent shs are produced. */ + +#include <string.h> + +char c[40] __attribute__ ((aligned(2))); + +void +f1 () +{ + memcpy (c, "1234567890QWERTYUIOPASDFGHJKLZXCVBNM", 32); +} diff --git a/gcc/testsuite/gcc.target/mips/inline-memcpy-3.c b/gcc/testsuite/gcc.target/mips/inline-memcpy-3.c new file mode 100644 index 00000000000..96a0387fce5 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/inline-memcpy-3.c @@ -0,0 +1,18 @@ +/* { dg-options "-fno-common isa_rev<=5" } */ +/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-Os"} { "" } } */ +/* { dg-final { scan-assembler-not "\tmemcpy" } } */ +/* { dg-final { scan-assembler-times "swl" 8 } } */ +/* { dg-final { scan-assembler-times "swr" 8 } } */ + +/* Test that inline memcpy for hardware with swl, swr handles subword + alignment and produces enough swl/swrs for mips32. */ + +#include <string.h> + +char c[40] __attribute__ ((aligned(2))); + +void +f1 () +{ + memcpy (c, "1234567890QWERTYUIOPASDFGHJKLZXCVBNM", 32); +} diff --git a/gcc/testsuite/gcc.target/mips/inline-memcpy-4.c b/gcc/testsuite/gcc.target/mips/inline-memcpy-4.c new file mode 100644 index 00000000000..0e7a22e8a33 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/inline-memcpy-4.c @@ -0,0 +1,18 @@ +/* { dg-options "-fno-common isa_rev<=5 -mabi=64" } */ +/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-Os"} { "" } } */ +/* { dg-final { scan-assembler-not "\tmemcpy" } } */ +/* { dg-final { scan-assembler-times "sdl" 4 } } */ +/* { dg-final { scan-assembler-times "sdr" 4 } } */ + +/* Test that inline memcpy for hardware with sdl, sdr handles subword + alignment and produces enough sdl/sdrs on n64. */ + +#include <string.h> + +char c[40] __attribute__ ((aligned(2))); + +void +f1 () +{ + memcpy (c, "1234567890QWERTYUIOPASDFGHJKLZXCVBNM", 32); +} diff --git a/gcc/testsuite/gcc.target/mips/inline-memcpy-5.c b/gcc/testsuite/gcc.target/mips/inline-memcpy-5.c new file mode 100644 index 00000000000..1b9fa16b2a7 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/inline-memcpy-5.c @@ -0,0 +1,18 @@ +/* { dg-options "-fno-common isa_rev<=5 -mabi=n32" } */ +/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-Os"} { "" } } */ +/* { dg-final { scan-assembler-not "\tmemcpy" } } */ +/* { dg-final { scan-assembler-times "sdl" 4 } } */ +/* { dg-final { scan-assembler-times "sdr" 4 } } */ + +/* Test that inline memcpy for hardware with sdl, sdr handles subword + alignment and produces enough sdr/sdls on n32. */ + +#include <string.h> + +char c[40] __attribute__ ((aligned(2))); + +void +f1 () +{ + memcpy (c, "1234567890QWERTYUIOPASDFGHJKLZXCVBNM", 32); +} diff --git a/gcc/testsuite/gcc.target/mips/lazy-binding-1.c b/gcc/testsuite/gcc.target/mips/lazy-binding-1.c index a30594840dd..a112781a99e 100644 --- a/gcc/testsuite/gcc.target/mips/lazy-binding-1.c +++ b/gcc/testsuite/gcc.target/mips/lazy-binding-1.c @@ -19,6 +19,6 @@ foo (int n) /* There should be exactly five uses of $25: one to set up $gp, two to load the address of bar (), and two to call it. */ /* { dg-final { scan-assembler-times "\tl.\t\\\$25,%call16\\\(bar\\\)" 2 } } */ -/* { dg-final { scan-assembler-times "\tjalrs?\t\\\$25" 2 } } */ +/* { dg-final { scan-assembler-times "\tjalrc?s?\t\\\$25" 2 } } */ /* { dg-final { scan-assembler "(\\\$28,|\t.cpload\t)\\\$25" } } */ /* { dg-final { scan-assembler-times "\\\$25" 5 } } */ diff --git a/gcc/testsuite/gcc.target/mips/madd-8.c b/gcc/testsuite/gcc.target/mips/madd-8.c index 794a6ff1727..56c194788a1 100644 --- a/gcc/testsuite/gcc.target/mips/madd-8.c +++ b/gcc/testsuite/gcc.target/mips/madd-8.c @@ -11,6 +11,6 @@ f2 (int x, int y, int z) asm volatile ("" ::: "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23", "$24", "$25", - "$31"); + "$31", "lo"); return x * y + z; } diff --git a/gcc/testsuite/gcc.target/mips/mips.exp b/gcc/testsuite/gcc.target/mips/mips.exp index 55e4223d7fd..42e7fff0de5 100644 --- a/gcc/testsuite/gcc.target/mips/mips.exp +++ b/gcc/testsuite/gcc.target/mips/mips.exp @@ -243,6 +243,7 @@ set mips_option_groups { mips16 "-mips16|-mno-mips16|-mflip-mips16" mips3d "-mips3d|-mno-mips3d" pic "-f(no-|)(pic|PIC)" + cb "-mcompact-branches=.*" profiling "-pg" small-data "-G[0-9]+" warnings "-w" @@ -1068,8 +1069,10 @@ proc mips-dg-options { args } { # We need a revision 6 or better ISA for: # # - When the LSA instruction is required + # - When only using compact branches if { $isa_rev < 6 - && ([mips_have_test_option_p options "HAS_LSA"]) } { + && ([mips_have_test_option_p options "HAS_LSA"] + || [mips_have_test_option_p options "-mcompact-branches=always"]) } { if { $gp_size == 32 } { mips_make_test_option options "-mips32r6" } else { @@ -1164,6 +1167,9 @@ proc mips-dg-options { args } { mips_make_test_option options "-mips64r5" } mips_make_test_option options "-mnan=2008" + if { [mips_have_option_p options "-mcompact-branches=always"] } { + mips_make_test_option options "-mcompact-branches=optimal" + } # Check whether we need to switch from a 32-bit processor to the # "nearest" 64-bit processor. } elseif { $gp_size == 64 && [mips_32bit_arch_p $arch] } { @@ -1308,6 +1314,11 @@ proc mips-dg-options { args } { mips_make_test_option options "-mno-micromips" mips_make_test_option options "-mnan=legacy" } + if { $isa_rev < 6 } { + if { [mips_have_option_p options "-mcompact-branches=always"] } { + mips_make_test_option options "-mcompact-branches=optimal" + } + } if { $isa_rev > 5 } { mips_make_test_option options "-mno-dsp" mips_make_test_option options "-mno-mips16" diff --git a/gcc/testsuite/gcc.target/mips/msub-8.c b/gcc/testsuite/gcc.target/mips/msub-8.c index a66307f1041..b0f1523cf31 100644 --- a/gcc/testsuite/gcc.target/mips/msub-8.c +++ b/gcc/testsuite/gcc.target/mips/msub-8.c @@ -11,6 +11,6 @@ f2 (int x, int y, int z) asm volatile ("" ::: "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23", "$24", "$25", - "$31"); + "$31", "lo"); return x - y * z; } diff --git a/gcc/testsuite/gcc.target/mips/near-far-1.c b/gcc/testsuite/gcc.target/mips/near-far-1.c index 8806e930fc3..b746cf6030c 100644 --- a/gcc/testsuite/gcc.target/mips/near-far-1.c +++ b/gcc/testsuite/gcc.target/mips/near-far-1.c @@ -16,5 +16,5 @@ int test () /* { dg-final { scan-assembler-not "\tjal\tlong_call_func\n" } } */ /* { dg-final { scan-assembler-not "\tjal\tfar_func\n" } } */ -/* { dg-final { scan-assembler "\tjal(|s)\tnear_func\n" } } */ +/* { dg-final { scan-assembler "\t(jal(|s)|balc)\tnear_func\n" } } */ /* { dg-final { scan-assembler-not "\tjal\tnormal_func\n" } } */ diff --git a/gcc/testsuite/gcc.target/mips/near-far-2.c b/gcc/testsuite/gcc.target/mips/near-far-2.c index b4062a744cf..2c140e2ceb2 100644 --- a/gcc/testsuite/gcc.target/mips/near-far-2.c +++ b/gcc/testsuite/gcc.target/mips/near-far-2.c @@ -16,5 +16,5 @@ int test () /* { dg-final { scan-assembler-not "\tjal(|s)\tlong_call_func\n" } } */ /* { dg-final { scan-assembler-not "\tjal(|s)\tfar_func\n" } } */ -/* { dg-final { scan-assembler "\tjal(|s)\tnear_func\n" } } */ -/* { dg-final { scan-assembler "\tjal(|s)\tnormal_func\n" } } */ +/* { dg-final { scan-assembler "\t(jal(|s)|balc)\tnear_func\n" } } */ +/* { dg-final { scan-assembler "\t(jal(|s)|balc)\tnormal_func\n" } } */ diff --git a/gcc/testsuite/gcc.target/mips/near-far-3.c b/gcc/testsuite/gcc.target/mips/near-far-3.c index e6af939e081..7bf3e14bc80 100644 --- a/gcc/testsuite/gcc.target/mips/near-far-3.c +++ b/gcc/testsuite/gcc.target/mips/near-far-3.c @@ -13,5 +13,5 @@ NOMIPS16 int test4 () { return normal_func (); } /* { dg-final { scan-assembler-not "\tj\tlong_call_func\n" } } */ /* { dg-final { scan-assembler-not "\tj\tfar_func\n" } } */ -/* { dg-final { scan-assembler "\tj(|al|als)\tnear_func\n" } } */ +/* { dg-final { scan-assembler "\t(j(|al|als)|b(|al)c)\tnear_func\n" } } */ /* { dg-final { scan-assembler-not "\tj\tnormal_func\n" } } */ diff --git a/gcc/testsuite/gcc.target/mips/near-far-4.c b/gcc/testsuite/gcc.target/mips/near-far-4.c index 969f68f3811..cd12a1dbcbb 100644 --- a/gcc/testsuite/gcc.target/mips/near-far-4.c +++ b/gcc/testsuite/gcc.target/mips/near-far-4.c @@ -13,5 +13,5 @@ NOMIPS16 int test4 () { return normal_func (); } /* { dg-final { scan-assembler-not "\tj\tlong_call_func\n" } } */ /* { dg-final { scan-assembler-not "\tj\tfar_func\n" } } */ -/* { dg-final { scan-assembler "\tj(|al|als)\tnear_func\n" } } */ -/* { dg-final { scan-assembler "\tj(|al|als)\tnormal_func\n" } } */ +/* { dg-final { scan-assembler "\t(j(|al|als)|b(|al)c)\tnear_func\n" } } */ +/* { dg-final { scan-assembler "\t(j(|al|als)|b(|al)c)\tnormal_func\n" } } */ diff --git a/gcc/testsuite/gcc.target/mips/umips-branch-3.c b/gcc/testsuite/gcc.target/mips/umips-branch-3.c index 8717362e044..74465c9f808 100644 --- a/gcc/testsuite/gcc.target/mips/umips-branch-3.c +++ b/gcc/testsuite/gcc.target/mips/umips-branch-3.c @@ -1,4 +1,4 @@ -/* { dg-options "(-mmicromips)" } */ +/* { dg-options "(-mmicromips) -mcompact-branches=optimal" } */ /* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */ void MICROMIPS diff --git a/gcc/testsuite/gcc.target/powerpc/altivec-35.c b/gcc/testsuite/gcc.target/powerpc/altivec-35.c index 6217c9f966b..46e8eed7fea 100644 --- a/gcc/testsuite/gcc.target/powerpc/altivec-35.c +++ b/gcc/testsuite/gcc.target/powerpc/altivec-35.c @@ -7,10 +7,19 @@ /* Test Altivec built-ins added for version 1.1 of ELFv2 ABI. */ vector signed int vsia, vsib; +vector signed short vssa, vssb, vssc; +vector unsigned short vusa, vusb, vusc; -void foo (vector signed int *vsir) +void foo (vector signed int *vsir, + vector signed short *vssr, + vector unsigned short *vusr) { *vsir++ = vec_addc (vsia, vsib); + *vssr++ = vec_madd (vssa, vssb, vssc); + *vssr++ = vec_madd (vssa, vusb, vusc); + *vssr++ = vec_madd (vusa, vssb, vssc); + *vusr++ = vec_madd (vusa, vusb, vusc); } /* { dg-final { scan-assembler-times "vaddcuw" 1 } } */ +/* { dg-final { scan-assembler-times "vmladduhm" 4 } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-8.c b/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-8.c index 4554099b6a7..bb5e182832e 100644 --- a/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-8.c +++ b/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-8.c @@ -8,7 +8,9 @@ vector unsigned char vuca, vucb, vucc; vector bool char vbca, vbcb; +vector unsigned short vusa, vusb; vector bool short vbsa, vbsb; +vector unsigned int vuia, vuib; vector bool int vbia, vbib; vector signed long long vsla, vslb; vector unsigned long long vula, vulb, vulc; @@ -19,7 +21,9 @@ vector double vda, vdb; void foo (vector unsigned char *vucr, vector bool char *vbcr, + vector unsigned short *vusr, vector bool short *vbsr, + vector unsigned int *vuir, vector bool int *vbir, vector unsigned long long *vulr, vector bool long long *vblr, @@ -48,6 +52,12 @@ void foo (vector unsigned char *vucr, *vblr++ = vec_orc (vbla, vblb); *vbsr++ = vec_orc (vbsa, vbsb); *vblr++ = vec_perm (vbla, vblb, vucc); + *vusr++ = vec_pmsum_be (vuca, vucb); + *vuir++ = vec_pmsum_be (vusa, vusb); + *vulr++ = vec_pmsum_be (vuia, vuib); + *vuxr++ = vec_pmsum_be (vula, vulb); + *vuir++ = vec_shasigma_be (vuia, 0, 1); + *vulr++ = vec_shasigma_be (vula, 0, 1); } /* { dg-final { scan-assembler-times "vaddcuq" 2 } } */ @@ -59,4 +69,10 @@ void foo (vector unsigned char *vucr, /* { dg-final { scan-assembler-times "xxlnand" 4 } } */ /* { dg-final { scan-assembler-times "xxlorc" 4 } } */ /* { dg-final { scan-assembler-times "vperm" 1 } } */ +/* { dg-final { scan-assembler-times "vpmsumb" 1 } } */ +/* { dg-final { scan-assembler-times "vpmsumh" 1 } } */ +/* { dg-final { scan-assembler-times "vpmsumw" 1 } } */ +/* { dg-final { scan-assembler-times "vpmsumd" 1 } } */ +/* { dg-final { scan-assembler-times "vshasigmaw" 1 } } */ +/* { dg-final { scan-assembler-times "vshasigmad" 1 } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/swaps-p8-19.c b/gcc/testsuite/gcc.target/powerpc/swaps-p8-19.c new file mode 100644 index 00000000000..6dffbb9b892 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/swaps-p8-19.c @@ -0,0 +1,20 @@ +/* { dg-do compile { target { powerpc64le-*-* } } } */ +/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */ +/* { dg-options "-O2 -ftree-vectorize -mcpu=power8 -ffast-math -fvect-cost-model=unlimited" } */ + +/* This tests special handling for various uses of xxpermdi, other than + to perform doubleword swaps. */ + +void foo (_Complex double *self, _Complex double *a, _Complex double *b, + int a1, int a2) +{ + int i, j; + for (i = 0; i < a1; ++i) + for (j = 0; j < a2; ++j) + self[i] = self[i] + a[i,j] * b[j]; +} + +/* { dg-final { scan-assembler-times "xxpermdi .*,.*,.*,0" 1 } } */ +/* { dg-final { scan-assembler-times "xxpermdi .*,.*,.*,1" 1 } } */ +/* { dg-final { scan-assembler-times "xxpermdi .*,.*,.*,2" 1 } } */ +/* { dg-final { scan-assembler-times "xxpermdi .*,.*,.*,3" 1 } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/vec-shr.c b/gcc/testsuite/gcc.target/powerpc/vec-shr.c new file mode 100644 index 00000000000..31a27c8832d --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/vec-shr.c @@ -0,0 +1,34 @@ +/* { dg-do run } */ +/* { dg-options "-O3 -fno-inline" } */ + +#include <stdlib.h> + +typedef struct { double r, i; } complex; +#define LEN 30 +complex c[LEN]; +double d[LEN]; + +void +foo (complex *c, double *d, int len1) +{ + int i; + for (i = 0; i < len1; i++) + { + c[i].r = d[i]; + c[i].i = 0.0; + } +} + +int +main (void) +{ + int i; + for (i = 0; i < LEN; i++) + d[i] = (double) i; + foo (c, d, LEN); + for (i=0;i<LEN;i++) + if ((c[i].r != (double) i) || (c[i].i != 0.0)) + abort (); + return 0; +} + diff --git a/gcc/testsuite/gcc.target/s390/20150826-1.c b/gcc/testsuite/gcc.target/s390/20150826-1.c new file mode 100644 index 00000000000..1567ced42e1 --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/20150826-1.c @@ -0,0 +1,12 @@ +/* Check that emitting a dynamic stack check for sizes below the + current frame size work. */ + +/* { dg-do compile } */ +/* { dg-options "-O3 -mstack-size=32" } */ + +extern int bar(char *); +int foo(void) +{ + char b[100]; + return bar(b); +} /* { dg-warning "An unconditional trap is added" } */ diff --git a/gcc/testsuite/gcc.target/s390/zvector/vec-load_bndry-1.c b/gcc/testsuite/gcc.target/s390/zvector/vec-load_bndry-1.c new file mode 100644 index 00000000000..9ebf6c7064f --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/zvector/vec-load_bndry-1.c @@ -0,0 +1,80 @@ +/* { dg-do compile { target { s390*-*-* } } } */ +/* { dg-options "-O0 -mzarch -march=z13 -mzvector" } */ + +#include <vecintrin.h> + +signed char +foo64 (signed char *p) +{ + return vec_load_bndry (p, 64)[0]; + /* { dg-final { scan-assembler-times "\tvlbb\t%v..?,0\\(%r..?\\),0" 1 } } */ +} + +signed char +foo128 (signed char *p) +{ + return + vec_load_bndry (p, 128)[0] + + vec_load_bndry (p + 16, 128)[0]; + /* { dg-final { scan-assembler-times "\tvlbb\t%v..?,0\\(%r..?\\),1" 2 } } */ +} + +signed char +foo256 (signed char *p) +{ + return + vec_load_bndry (p, 256)[0] + + vec_load_bndry (p + 16, 256)[0] + + vec_load_bndry (p + 32, 256)[0]; + /* { dg-final { scan-assembler-times "\tvlbb\t%v..?,0\\(%r..?\\),2" 3 } } */ +} + +signed char +foo512 (signed char *p) +{ + return + vec_load_bndry (p, 512)[0] + + vec_load_bndry (p + 16, 512)[0] + + vec_load_bndry (p + 32, 512)[0] + + vec_load_bndry (p + 48, 512)[0]; + /* { dg-final { scan-assembler-times "\tvlbb\t%v..?,0\\(%r..?\\),3" 4 } } */ +} + +signed char +foo1024 (signed char *p) +{ + return + vec_load_bndry (p, 1024)[0] + + vec_load_bndry (p + 16, 1024)[0] + + vec_load_bndry (p + 32, 1024)[0] + + vec_load_bndry (p + 48, 1024)[0] + + vec_load_bndry (p + 64, 1024)[0]; + /* { dg-final { scan-assembler-times "\tvlbb\t%v..?,0\\(%r..?\\),4" 5 } } */ +} + +signed char +foo2048 (signed char *p) +{ + return + vec_load_bndry (p, 2048)[0] + + vec_load_bndry (p + 16, 2048)[0] + + vec_load_bndry (p + 32, 2048)[0] + + vec_load_bndry (p + 48, 2048)[0] + + vec_load_bndry (p + 64, 2048)[0] + + vec_load_bndry (p + 80, 2048)[0]; + /* { dg-final { scan-assembler-times "\tvlbb\t%v..?,0\\(%r..?\\),5" 6 } } */ +} + +signed char +foo4096 (signed char *p) +{ + return + vec_load_bndry (p, 4096)[0] + + vec_load_bndry (p + 16, 4096)[0] + + vec_load_bndry (p + 32, 4096)[0] + + vec_load_bndry (p + 48, 4096)[0] + + vec_load_bndry (p + 64, 4096)[0] + + vec_load_bndry (p + 80, 4096)[0] + + vec_load_bndry (p + 96, 4096)[0]; + /* { dg-final { scan-assembler-times "\tvlbb\t%v..?,0\\(%r..?\\),6" 7 } } */ +} diff --git a/gcc/testsuite/gfortran.dg/backtrace_1.f90 b/gcc/testsuite/gfortran.dg/backtrace_1.f90 new file mode 100644 index 00000000000..fdde832d238 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/backtrace_1.f90 @@ -0,0 +1,10 @@ +! { dg-do run } +! +! Check that BACKTRACE is available on all targets. We cannot actually +! check its output, but we should at least be able to call it, then exit +! normally. +! +program test + call backtrace + stop +end program test diff --git a/gcc/testsuite/gfortran.dg/block_end_error_1.f90 b/gcc/testsuite/gfortran.dg/block_end_error_1.f90 new file mode 100644 index 00000000000..e7dcdfa966d --- /dev/null +++ b/gcc/testsuite/gfortran.dg/block_end_error_1.f90 @@ -0,0 +1,10 @@ +! { dg-do compile } +! +! PR fortran/62536 +! Bad "end block" causes ICE. +subroutine s + block + end block named ! { dg-error "Syntax error in END BLOCK statement" } + return +endsubroutine +! { dg-prune-output "Unexpected end of file" } diff --git a/gcc/testsuite/gfortran.dg/blocks_nested_incomplete_1.f90 b/gcc/testsuite/gfortran.dg/blocks_nested_incomplete_1.f90 new file mode 100644 index 00000000000..ccf6c3fa1ac --- /dev/null +++ b/gcc/testsuite/gfortran.dg/blocks_nested_incomplete_1.f90 @@ -0,0 +1,9 @@ +! { dg-do compile } +! +! PR fortran/66175 +! Nested incomplete blocks cause ICE. +program main + block + block +end program ! { dg-error "Expecting END BLOCK statement" } +! { dg-prune-output "Unexpected end of file" } diff --git a/gcc/testsuite/gfortran.dg/execute_command_line_2.f90 b/gcc/testsuite/gfortran.dg/execute_command_line_2.f90 new file mode 100644 index 00000000000..3e34f322f07 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/execute_command_line_2.f90 @@ -0,0 +1,15 @@ +! { dg-do run } +! { dg-xfail-run-if "PR libfortran/67412" { *-*-solaris2.10 } } +! +! Check that EXECUTE_COMMAND_LINE handles invalid command lines appropriately +! + integer :: s = 0, c = 0 + character(len=255) :: msg = "" + + ! This should fail, set CMDSTAT to nonzero value, and an error message + ! in CMDMSG. + call execute_command_line ("/nosuchfile", exitstat=s, cmdstat=c, cmdmsg=msg) + if (c == 0) call abort + if (len_trim(msg) == 0) call abort + +end diff --git a/gcc/testsuite/gfortran.dg/generic_31.f90 b/gcc/testsuite/gfortran.dg/generic_31.f90 new file mode 100644 index 00000000000..2c0d0299005 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/generic_31.f90 @@ -0,0 +1,35 @@ +! { dg-do run } +! +! PR fortran/66929 +! Check that the specific FIRST symbol is used for the call to FOO, +! so that the J argument is not assumed to be present + +module m + interface foo + module procedure first + end interface foo +contains + elemental function bar(j) result(r) + integer, intent(in), optional :: j + integer :: r, s(2) + ! We used to have NULL dereference here, in case of a missing J argument + s = foo(j, [3, 7]) + r = sum(s) + end function bar + elemental function first(i, j) result(r) + integer, intent(in), optional :: i + integer, intent(in) :: j + integer :: r + if (present(i)) then + r = i + else + r = -5 + end if + end function first +end module m +program p + use m + integer :: i + i = bar() + if (i /= -10) call abort +end program p diff --git a/gcc/testsuite/gfortran.dg/graphite/graphite.exp b/gcc/testsuite/gfortran.dg/graphite/graphite.exp index 1df46ead2c1..93863c32922 100644 --- a/gcc/testsuite/gfortran.dg/graphite/graphite.exp +++ b/gcc/testsuite/gfortran.dg/graphite/graphite.exp @@ -38,9 +38,9 @@ set save-dg-do-what-default ${dg-do-what-default} dg-init set wait_to_run_files [lsort [glob -nocomplain $srcdir/$subdir/*.\[fF\]{,90,95,03,08} ] ] -set block_files [lsort [glob -nocomplain $srcdir/$subdir/block-*.\[fF\]{,90,95,03,08} ] ] set id_files [lsort [glob -nocomplain $srcdir/$subdir/id-*.\[fF\]{,90,95,03,08} ] ] -set interchange_files [lsort [glob -nocomplain $srcdir/$subdir/interchange-*.\[fF\]{,90,95,03,08} ] ] +set opt_files [lsort [glob -nocomplain $srcdir/$subdir/interchange-*.\[fF\]{,90,95,03,08} \ + $srcdir/$subdir/block-*.\[fF\]{,90,95,03,08} ] ] set scop_files [lsort [glob -nocomplain $srcdir/$subdir/scop-*.\[fF\]{,90,95,03,08} ] ] set run_id_files [lsort [glob -nocomplain $srcdir/$subdir/run-id-*.\[fF\]{,90,95,03,08} ] ] set vect_files [lsort [glob -nocomplain $srcdir/$subdir/vect-*.\[fF\]{,90,95,03,08} ] ] @@ -49,8 +49,7 @@ set vect_files [lsort [glob -nocomplain $srcdir/$subdir/vect-*.\[fF\]{,90 set dg-do-what-default compile gfortran-dg-runtest $scop_files "" "-O2 -fgraphite -fdump-tree-graphite-all" gfortran-dg-runtest $id_files "" "-O2 -fgraphite-identity -ffast-math" -gfortran-dg-runtest $interchange_files "" "-O2 -floop-interchange -fno-loop-block -fno-loop-strip-mine -ffast-math -fdump-tree-graphite-all" -gfortran-dg-runtest $block_files "" "-O2 -floop-block -fno-loop-strip-mine -fno-loop-interchange -ffast-math -fdump-tree-graphite-all" +gfortran-dg-runtest $opt_files "" "-O2 -floop-nest-optimize -ffast-math -fdump-tree-graphite-all" # Vectorizer tests, to be run or compiled, depending on target capabilities. if [check_vect_support_and_set_flags] { @@ -63,9 +62,8 @@ gfortran-dg-runtest $run_id_files "" "-O2 -fgraphite-identity" # The default action for the rest of the files is 'compile'. set dg-do-what-default compile -foreach f $block_files {lremove wait_to_run_files $f} foreach f $id_files {lremove wait_to_run_files $f} -foreach f $interchange_files {lremove wait_to_run_files $f} +foreach f $opt_files {lremove wait_to_run_files $f} foreach f $scop_files {lremove wait_to_run_files $f} foreach f $run_id_files {lremove wait_to_run_files $f} foreach f $vect_files {lremove wait_to_run_files $f} diff --git a/gcc/testsuite/gfortran.dg/graphite/interchange-3.f90 b/gcc/testsuite/gfortran.dg/graphite/interchange-3.f90 index ffc84b60703..a99cf153d9e 100644 --- a/gcc/testsuite/gfortran.dg/graphite/interchange-3.f90 +++ b/gcc/testsuite/gfortran.dg/graphite/interchange-3.f90 @@ -24,4 +24,4 @@ Program FOO end Program FOO -! { dg-final { scan-tree-dump-times "will be interchanged" 1 "graphite" } } +! { dg-final { scan-tree-dump-times "tiled by" 2 "graphite" } } diff --git a/gcc/testsuite/gfortran.dg/read_dir.f90 b/gcc/testsuite/gfortran.dg/read_dir.f90 new file mode 100644 index 00000000000..0e28f9f497e --- /dev/null +++ b/gcc/testsuite/gfortran.dg/read_dir.f90 @@ -0,0 +1,19 @@ +! { dg-do run { xfail *-*-freebsd* } } +! PR67367 +program bug + implicit none + character(len=1) :: c + character(len=256) :: message + integer ios + call system('[ -d junko.dir ] || mkdir junko.dir') + open(unit=10, file='junko.dir',iostat=ios,action='read',access='stream') + if (ios.ne.0) call abort + read(10, iostat=ios) c + if (ios.ne.21) then + close(10) + call system('rmdir junko.dir') + call abort + end if + close(10) + call system('rmdir junko.dir') +end program bug diff --git a/gcc/testsuite/gfortran.dg/shape_8.f90 b/gcc/testsuite/gfortran.dg/shape_8.f90 new file mode 100644 index 00000000000..51c6e552b51 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/shape_8.f90 @@ -0,0 +1,15 @@ +! { dg-do run } +! +! Check that we can use SHAPE with optional kind argument +! +program test + implicit none + real, allocatable :: x(:,:) + + allocate(x(2,5)) + if (any(shape(x) /= [ 2, 5 ])) call abort + if (any(shape(x,kind=1) /= [ 2, 5 ])) call abort + if (any(shape(x,kind=2) /= [ 2, 5 ])) call abort + if (any(shape(x,kind=4) /= [ 2, 5 ])) call abort + if (any(shape(x,kind=8) /= [ 2, 5 ])) call abort +end diff --git a/gcc/testsuite/gfortran.dg/vect/O3-pr49957.f b/gcc/testsuite/gfortran.dg/vect/O3-pr49957.f index a9735677e73..778b4a010b6 100644 --- a/gcc/testsuite/gfortran.dg/vect/O3-pr49957.f +++ b/gcc/testsuite/gfortran.dg/vect/O3-pr49957.f @@ -13,4 +13,4 @@ enddo return end -! { dg-final { scan-tree-dump "vectorized 1 loops" "vect" { xfail vect_no_align } } } +! { dg-final { scan-tree-dump "vectorized 1 loops" "vect" { xfail { vect_no_align && { ! vect_hw_misalign } } } } } diff --git a/gcc/testsuite/jit.dg/test-error-pr63969-missing-driver.c b/gcc/testsuite/jit.dg/test-error-pr63969-missing-driver.c index 13f5e3b5b83..733522310de 100644 --- a/gcc/testsuite/jit.dg/test-error-pr63969-missing-driver.c +++ b/gcc/testsuite/jit.dg/test-error-pr63969-missing-driver.c @@ -21,6 +21,10 @@ create_code (gcc_jit_context *ctxt, void *user_data) Unset it. */ gcc_jit_context_set_str_option (ctxt, GCC_JIT_STR_OPTION_PROGNAME, NULL); + /* By default, we use an embedded copy of the driver. + Opt-in to using an external copy of the driver. */ + gcc_jit_context_set_bool_use_external_driver (ctxt, 1); + /* Break PATH, so that the driver can't be found by gcc::jit::playback::context::compile () within gcc_jit_context_compile. */ diff --git a/gcc/testsuite/lib/gcc-dg.exp b/gcc/testsuite/lib/gcc-dg.exp index 7ce71df488b..7c1ab85f32e 100644 --- a/gcc/testsuite/lib/gcc-dg.exp +++ b/gcc/testsuite/lib/gcc-dg.exp @@ -270,7 +270,7 @@ proc gcc-dg-test-1 { target_compile prog do_what extra_tool_flags } { set finalcmd [lindex $x 0] if { [info procs ${finalcmd}_required_options] != "" } { set req [${finalcmd}_required_options] - if { $req != "" } { + if { $req != "" && [lsearch -exact $extra_tool_flags $req] == -1 } { lappend extra_tool_flags $req } } diff --git a/gcc/testsuite/lib/gcc.exp b/gcc/testsuite/lib/gcc.exp index 3ba8d3e5747..55e1c4fc22e 100644 --- a/gcc/testsuite/lib/gcc.exp +++ b/gcc/testsuite/lib/gcc.exp @@ -150,6 +150,9 @@ proc gcc_target_compile { source dest type options } { if [target_info exists gcc,no_label_values] { lappend options "additional_flags=-DNO_LABEL_VALUES" } + if [target_info exists gcc,signal_suppress] { + lappend options "additional_flags=-DSIGNAL_SUPPRESS" + } # TEST_ALWAYS_FLAGS are flags that should be passed to every # compilation. They are passed first to allow individual diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index 1988301045b..363f7fe3877 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -580,7 +580,10 @@ proc check_profiling_available { test_what } { # in Section 4 of C99 standard. Effectively, it is a target which supports no # extra headers or libraries other than what is considered essential. proc check_effective_target_freestanding { } { - return 0 + if { [istarget nvptx-*-*] } { + return 1 + } + return 0 } # Return 1 if target has packed layout of structure members by @@ -644,6 +647,15 @@ proc check_effective_target_nonlocal_goto {} { return 1 } +# Return 1 if global constructors are supported, 0 otherwise. + +proc check_effective_target_global_constructor {} { + if { [istarget nvptx-*-*] } { + return 0 + } + return 1 +} + # Return 1 if taking label values is supported, 0 otherwise. proc check_effective_target_label_values {} { @@ -807,6 +819,10 @@ proc check_effective_target_fgraphite {} { # code, 0 otherwise. proc check_effective_target_fopenacc {} { + # nvptx can be built with the device-side bits of openacc, but it + # does not make sense to test it as an openacc host. + if [istarget nvptx-*-*] { return 0 } + return [check_no_compiler_messages fopenacc object { void foo (void) { } } "-fopenacc"] @@ -816,6 +832,10 @@ proc check_effective_target_fopenacc {} { # code, 0 otherwise. proc check_effective_target_fopenmp {} { + # nvptx can be built with the device-side bits of libgomp, but it + # does not make sense to test it as an openmp host. + if [istarget nvptx-*-*] { return 0 } + return [check_no_compiler_messages fopenmp object { void foo (void) { } } "-fopenmp"] @@ -957,6 +977,23 @@ proc check_effective_target_aarch64_small_fpic { } { } } +# On AArch64, instruction sequence for TLS LE under -mtls-size=32 will utilize +# the relocation modifier "tprel_g0_nc" together with MOVK, it's only supported +# in binutils since 2015-03-04 as PR gas/17843. +# +# This test directive make sure binutils support all features needed by TLS LE +# under -mtls-size=32 on AArch64. + +proc check_effective_target_aarch64_tlsle32 { } { + if { [istarget aarch64*-*-*] } { + return [check_no_compiler_messages aarch64_tlsle32 object { + void foo (void) { asm ("movk x1,#:tprel_g0_nc:t1"); } + }] + } else { + return 0 + } +} + # Return 1 if -shared is supported, as in no warnings or errors # emitted, 0 otherwise. @@ -1145,6 +1182,17 @@ proc check_effective_target_pie_enabled { } { }] } +# Return 1 if the target generates -fstack-protector by default. + +proc check_effective_target_fstack_protector_enabled {} { + return [ check_no_compiler_messages fstack_protector_enabled assembly { + #if !defined(__SSP__) && !defined(__SSP_ALL__) && \ + !defined(__SSP_STRONG__) && !defined(__SSP_EXPICIT__) + #error unsupported + #endif + }] +} + # Return 1 if the target does not use a status wrapper. proc check_effective_target_unwrapped { } { @@ -2703,7 +2751,11 @@ proc check_effective_target_arm_neon_fp16_ok_nocache { } { set et_arm_neon_fp16_flags "" if { [check_effective_target_arm32] } { foreach flags {"" "-mfloat-abi=softfp" "-mfpu=neon-fp16" - "-mfpu=neon-fp16 -mfloat-abi=softfp"} { + "-mfpu=neon-fp16 -mfloat-abi=softfp" + "-mfp16-format=ieee" + "-mfloat-abi=softfp -mfp16-format=ieee" + "-mfpu=neon-fp16 -mfp16-format=ieee" + "-mfpu=neon-fp16 -mfloat-abi=softfp -mfp16-format=ieee"} { if { [check_no_compiler_messages_nocache arm_neon_fp_16_ok object { #include "arm_neon.h" float16x4_t @@ -3659,6 +3711,8 @@ proc check_effective_target_vect_double { } { } } elseif { [istarget spu-*-*] } { set et_vect_double_saved 1 + } elseif { [istarget powerpc*-*-*] && [check_vsx_hw_available] } { + set et_vect_double_saved 1 } } @@ -3692,23 +3746,23 @@ proc check_effective_target_vect_long_long { } { # # This won't change for different subtargets so cache the result. -proc check_effective_target_vect_no_int_max { } { - global et_vect_no_int_max_saved +proc check_effective_target_vect_no_int_min_max { } { + global et_vect_no_int_min_max_saved - if [info exists et_vect_no_int_max_saved] { - verbose "check_effective_target_vect_no_int_max: using cached result" 2 + if [info exists et_vect_no_int_min_max_saved] { + verbose "check_effective_target_vect_no_int_min_max: using cached result" 2 } else { - set et_vect_no_int_max_saved 0 + set et_vect_no_int_min_max_saved 0 if { [istarget sparc*-*-*] || [istarget spu-*-*] || [istarget alpha*-*-*] || ([istarget mips*-*-*] && [check_effective_target_mips_loongson]) } { - set et_vect_no_int_max_saved 1 + set et_vect_no_int_min_max_saved 1 } } - verbose "check_effective_target_vect_no_int_max: returning $et_vect_no_int_max_saved" 2 - return $et_vect_no_int_max_saved + verbose "check_effective_target_vect_no_int_min_max: returning $et_vect_no_int_min_max_saved" 2 + return $et_vect_no_int_min_max_saved } # Return 1 if the target plus current options does not support a vector diff --git a/gcc/toplev.c b/gcc/toplev.c index 40fffe797c0..981a7cc107c 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -604,15 +604,6 @@ compile_file (void) if (seen_error ()) return; - /* After the parser has generated debugging information, augment - this information with any new location/etc information that may - have become available after the compilation proper. */ - timevar_start (TV_PHASE_DBGINFO); - symtab_node *node; - FOR_EACH_DEFINED_SYMBOL (node) - debug_hooks->late_global_decl (node->decl); - timevar_stop (TV_PHASE_DBGINFO); - timevar_start (TV_PHASE_LATE_ASM); /* Compilation unit is finalized. When producing non-fat LTO object, we are @@ -1363,12 +1354,9 @@ process_options (void) #ifndef HAVE_isl if (flag_graphite + || flag_loop_optimize_isl || flag_graphite_identity - || flag_loop_block - || flag_loop_interchange - || flag_loop_strip_mine - || flag_loop_parallelize_all - || flag_loop_unroll_jam) + || flag_loop_parallelize_all) sorry ("Graphite loop optimizations cannot be used (ISL is not available)" "(-fgraphite, -fgraphite-identity, -floop-block, " "-floop-interchange, -floop-strip-mine, -floop-parallelize-all, " diff --git a/gcc/trans-mem.c b/gcc/trans-mem.c index 891e6388cc4..e7707acce68 100644 --- a/gcc/trans-mem.c +++ b/gcc/trans-mem.c @@ -1,5 +1,7 @@ /* Passes for transactional memory support. Copyright (C) 2008-2015 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com> + and Aldy Hernandez <aldyh@redhat.com>. This file is part of GCC. diff --git a/gcc/trans-mem.h b/gcc/trans-mem.h index f19b83cfb32..585b22ad7b1 100644 --- a/gcc/trans-mem.h +++ b/gcc/trans-mem.h @@ -1,5 +1,7 @@ /* Miscellaneous transactional memory support definitions. Copyright (C) 2009-2015 Free Software Foundation, Inc. + Contributed by Richard Henderson <rth@redhat.com> + and Aldy Hernandez <aldyh@redhat.com>. This file is part of GCC. diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index 416c816fb5f..5ac73b3266d 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -6420,17 +6420,19 @@ replace_ssa_name (tree name, hash_map<tree, tree> *vars_map, tree decl = SSA_NAME_VAR (name); if (decl) { + gcc_assert (!SSA_NAME_IS_DEFAULT_DEF (name)); replace_by_duplicate_decl (&decl, vars_map, to_context); new_name = make_ssa_name_fn (DECL_STRUCT_FUNCTION (to_context), decl, SSA_NAME_DEF_STMT (name)); - if (SSA_NAME_IS_DEFAULT_DEF (name)) - set_ssa_default_def (DECL_STRUCT_FUNCTION (to_context), - decl, new_name); } else new_name = copy_ssa_name_fn (DECL_STRUCT_FUNCTION (to_context), name, SSA_NAME_DEF_STMT (name)); + /* Now that we've used the def stmt to define new_name, make sure it + doesn't define name anymore. */ + SSA_NAME_DEF_STMT (name) = NULL; + vars_map->put (name, new_name); } else @@ -6482,6 +6484,9 @@ move_stmt_op (tree *tp, int *walk_subtrees, void *data) { if (TREE_CODE (t) == SSA_NAME) *tp = replace_ssa_name (t, p->vars_map, p->to_context); + else if (TREE_CODE (t) == PARM_DECL + && gimple_in_ssa_p (cfun)) + *tp = *(p->vars_map->get (t)); else if (TREE_CODE (t) == LABEL_DECL) { if (p->new_label_map) @@ -6992,6 +6997,19 @@ verify_sese (basic_block entry, basic_block exit, vec<basic_block> *bbs_p) BITMAP_FREE (bbs); } +/* If FROM is an SSA_NAME, mark the version in bitmap DATA. */ + +bool +gather_ssa_name_hash_map_from (tree const &from, tree const &, void *data) +{ + bitmap release_names = (bitmap)data; + + if (TREE_CODE (from) != SSA_NAME) + return true; + + bitmap_set_bit (release_names, SSA_NAME_VERSION (from)); + return true; +} /* Move a single-entry, single-exit region delimited by ENTRY_BB and EXIT_BB to function DEST_CFUN. The whole region is replaced by a @@ -7189,6 +7207,14 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb, d.eh_map = eh_map; d.remap_decls_p = true; + if (gimple_in_ssa_p (cfun)) + for (tree arg = DECL_ARGUMENTS (d.to_context); arg; arg = DECL_CHAIN (arg)) + { + tree narg = make_ssa_name_fn (dest_cfun, arg, gimple_build_nop ()); + set_ssa_default_def (dest_cfun, arg, narg); + vars_map.put (arg, narg); + } + FOR_EACH_VEC_ELT (bbs, i, bb) { /* No need to update edge counts on the last block. It has @@ -7246,6 +7272,19 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb, if (eh_map) delete eh_map; + if (gimple_in_ssa_p (cfun)) + { + /* We need to release ssa-names in a defined order, so first find them, + and then iterate in ascending version order. */ + bitmap release_names = BITMAP_ALLOC (NULL); + vars_map.traverse<void *, gather_ssa_name_hash_map_from> (release_names); + bitmap_iterator bi; + unsigned i; + EXECUTE_IF_SET_IN_BITMAP (release_names, 0, i, bi) + release_ssa_name (ssa_name (i)); + BITMAP_FREE (release_names); + } + /* Rewire the entry and exit blocks. The successor to the entry block turns into the successor of DEST_FN's ENTRY_BLOCK_PTR in the child function. Similarly, the predecessor of DEST_FN's diff --git a/gcc/tree-cfg.h b/gcc/tree-cfg.h index 6c4b1d9b241..4bd6fcf361f 100644 --- a/gcc/tree-cfg.h +++ b/gcc/tree-cfg.h @@ -75,6 +75,7 @@ extern bool gimple_duplicate_sese_tail (edge, edge, basic_block *, unsigned, extern void gather_blocks_in_sese_region (basic_block entry, basic_block exit, vec<basic_block> *bbs_p); extern void verify_sese (basic_block, basic_block, vec<basic_block> *); +extern bool gather_ssa_name_hash_map_from (tree const &, tree const &, void *); extern basic_block move_sese_region_to_fn (struct function *, basic_block, basic_block, tree); extern void dump_function_to_file (tree, FILE *, int); diff --git a/gcc/tree-chkp.c b/gcc/tree-chkp.c index 8c1b48cf45c..2489abb2cb0 100644 --- a/gcc/tree-chkp.c +++ b/gcc/tree-chkp.c @@ -1667,8 +1667,9 @@ chkp_find_bound_slots_1 (const_tree type, bitmap have_bound, for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) if (TREE_CODE (field) == FIELD_DECL) { - HOST_WIDE_INT field_offs - = TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field)); + HOST_WIDE_INT field_offs = 0; + if (DECL_FIELD_BIT_OFFSET (field)) + field_offs += TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field)); if (DECL_FIELD_OFFSET (field)) field_offs += TREE_INT_CST_LOW (DECL_FIELD_OFFSET (field)) * 8; chkp_find_bound_slots_1 (TREE_TYPE (field), have_bound, diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c index 818c2907855..8b3a0adf7cc 100644 --- a/gcc/tree-sra.c +++ b/gcc/tree-sra.c @@ -980,12 +980,11 @@ completely_scalarize_record (tree base, tree decl, HOST_WIDE_INT offset, } } -/* Create total_scalarization accesses for all scalar type fields in VAR and - for VAR as a whole. VAR must be of a RECORD_TYPE conforming to - type_consists_of_records_p. */ +/* Create a total_scalarization access for VAR as a whole. VAR must be of a + RECORD_TYPE conforming to type_consists_of_records_p. */ static void -completely_scalarize_var (tree var) +create_total_scalarization_access (tree var) { HOST_WIDE_INT size = tree_to_uhwi (DECL_SIZE (var)); struct access *access; @@ -994,8 +993,6 @@ completely_scalarize_var (tree var) access->expr = var; access->type = TREE_TYPE (var); access->grp_total_scalarization = 1; - - completely_scalarize_record (var, var, 0, var); } /* Return true if REF has an VIEW_CONVERT_EXPR somewhere in it. */ @@ -2529,7 +2526,8 @@ analyze_all_variable_accesses (void) if (tree_to_uhwi (TYPE_SIZE (TREE_TYPE (var))) <= max_scalarization_size) { - completely_scalarize_var (var); + create_total_scalarization_access (var); + completely_scalarize_record (var, var, 0, var); if (dump_file && (dump_flags & TDF_DETAILS)) { fprintf (dump_file, "Will attempt to totally scalarize "); diff --git a/gcc/tree-ssa-coalesce.c b/gcc/tree-ssa-coalesce.c index 08ce72c79c0..6468012aa00 100644 --- a/gcc/tree-ssa-coalesce.c +++ b/gcc/tree-ssa-coalesce.c @@ -1386,8 +1386,8 @@ gimple_can_coalesce_p (tree name1, tree name2) because it may be passed by reference. */ return ((!var1 || VAR_P (var1)) && (!var2 || VAR_P (var2))) || (/* The case var1 == var2 is already covered above. */ - !parm_maybe_byref_p (var1) - && !parm_maybe_byref_p (var2) + !parm_in_stack_slot_p (var1) + && !parm_in_stack_slot_p (var2) && promote_ssa_mode (name1, NULL) == promote_ssa_mode (name2, NULL)); } diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c index 2d2edc80116..50dfdedff85 100644 --- a/gcc/tree-ssa-dce.c +++ b/gcc/tree-ssa-dce.c @@ -1125,10 +1125,11 @@ remove_dead_stmt (gimple_stmt_iterator *i, basic_block bb) if (e != e2) { cfg_altered = true; - /* If we made a BB unconditionally exit a loop then this - transform alters the set of BBs in the loop. Schedule - a fixup. */ - if (loop_exit_edge_p (bb->loop_father, e)) + /* If we made a BB unconditionally exit a loop or removed + an entry into an irreducible region, then this transform + alters the set of BBs in the loop. Schedule a fixup. */ + if (loop_exit_edge_p (bb->loop_father, e) + || (e2->dest->flags & BB_IRREDUCIBLE_LOOP)) loops_state_set (LOOPS_NEED_FIXUP); remove_edge (e2); } diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c index ea0a956270e..9be65de0cd2 100644 --- a/gcc/tree-ssa-dom.c +++ b/gcc/tree-ssa-dom.c @@ -1577,12 +1577,7 @@ record_equivalences_from_phis (basic_block bb) if (lhs == t) continue; - /* Valueize t. */ - if (TREE_CODE (t) == SSA_NAME) - { - tree tmp = SSA_NAME_VALUE (t); - t = tmp ? tmp : t; - } + t = dom_valueize (t); /* If we have not processed an alternative yet, then set RHS to this alternative. */ @@ -2340,12 +2335,7 @@ record_equivalences_from_stmt (gimple stmt, int may_optimize_p) && (TREE_CODE (rhs) == SSA_NAME || is_gimple_min_invariant (rhs))) { - /* Valueize rhs. */ - if (TREE_CODE (rhs) == SSA_NAME) - { - tree tmp = SSA_NAME_VALUE (rhs); - rhs = tmp ? tmp : rhs; - } + rhs = dom_valueize (rhs); if (dump_file && (dump_flags & TDF_DETAILS)) { @@ -2622,12 +2612,7 @@ optimize_stmt (basic_block bb, gimple_stmt_iterator si) tree rhs = gimple_assign_rhs1 (stmt); tree cached_lhs; gassign *new_stmt; - if (TREE_CODE (rhs) == SSA_NAME) - { - tree tem = SSA_NAME_VALUE (rhs); - if (tem) - rhs = tem; - } + rhs = dom_valueize (rhs); /* Build a new statement with the RHS and LHS exchanged. */ if (TREE_CODE (rhs) == SSA_NAME) { @@ -2749,7 +2734,6 @@ lookup_avail_expr (gimple stmt, bool insert) { expr_hash_elt **slot; tree lhs; - tree temp; struct expr_hash_elt element; /* Get LHS of phi, assignment, or call; else NULL_TREE. */ @@ -2844,14 +2828,7 @@ lookup_avail_expr (gimple stmt, bool insert) definition of another variable. */ lhs = (*slot)->lhs; - /* See if the LHS appears in the CONST_AND_COPIES table. If it does, then - use the value from the const_and_copies table. */ - if (TREE_CODE (lhs) == SSA_NAME) - { - temp = SSA_NAME_VALUE (lhs); - if (temp) - lhs = temp; - } + lhs = dom_valueize (lhs); if (dump_file && (dump_flags & TDF_DETAILS)) { diff --git a/gcc/tree-ssa-loop-manip.c b/gcc/tree-ssa-loop-manip.c index cb762df4524..fb7ba4810c8 100644 --- a/gcc/tree-ssa-loop-manip.c +++ b/gcc/tree-ssa-loop-manip.c @@ -366,7 +366,9 @@ get_loops_exits (bitmap *loop_exits) /* For USE in BB, if it is used outside of the loop it is defined in, mark it for rewrite. Record basic block BB where it is used - to USE_BLOCKS. Record the ssa name index to NEED_PHIS bitmap. */ + to USE_BLOCKS. Record the ssa name index to NEED_PHIS bitmap. + Note that for USEs in phis, BB should be the src of the edge corresponding to + the use, rather than the bb containing the phi. */ static void find_uses_to_rename_use (basic_block bb, tree use, bitmap *use_blocks, @@ -401,13 +403,13 @@ find_uses_to_rename_use (basic_block bb, tree use, bitmap *use_blocks, bitmap_set_bit (use_blocks[ver], bb->index); } -/* For uses in STMT, mark names that are used outside of the loop they are - defined to rewrite. Record the set of blocks in that the ssa - names are defined to USE_BLOCKS and the ssa names themselves to - NEED_PHIS. */ +/* For uses matching USE_FLAGS in STMT, mark names that are used outside of the + loop they are defined to rewrite. Record the set of blocks in which the ssa + names are used to USE_BLOCKS, and the ssa names themselves to NEED_PHIS. */ static void -find_uses_to_rename_stmt (gimple stmt, bitmap *use_blocks, bitmap need_phis) +find_uses_to_rename_stmt (gimple stmt, bitmap *use_blocks, bitmap need_phis, + int use_flags) { ssa_op_iter iter; tree var; @@ -416,43 +418,59 @@ find_uses_to_rename_stmt (gimple stmt, bitmap *use_blocks, bitmap need_phis) if (is_gimple_debug (stmt)) return; - FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_USE) - find_uses_to_rename_use (bb, var, use_blocks, need_phis); + /* FOR_EACH_SSA_TREE_OPERAND iterator does not allows SSA_OP_VIRTUAL_USES + only. */ + if (use_flags == SSA_OP_VIRTUAL_USES) + { + tree vuse = gimple_vuse (stmt); + if (vuse != NULL_TREE) + find_uses_to_rename_use (bb, gimple_vuse (stmt), use_blocks, need_phis); + } + else + FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, use_flags) + find_uses_to_rename_use (bb, var, use_blocks, need_phis); } -/* Marks names that are used in BB and outside of the loop they are - defined in for rewrite. Records the set of blocks in that the ssa - names are defined to USE_BLOCKS. Record the SSA names that will +/* Marks names matching USE_FLAGS that are used in BB and outside of the loop + they are defined in for rewrite. Records the set of blocks in which the ssa + names are used to USE_BLOCKS. Record the SSA names that will need exit PHIs in NEED_PHIS. */ static void -find_uses_to_rename_bb (basic_block bb, bitmap *use_blocks, bitmap need_phis) +find_uses_to_rename_bb (basic_block bb, bitmap *use_blocks, bitmap need_phis, + int use_flags) { edge e; edge_iterator ei; + bool do_virtuals = (use_flags & SSA_OP_VIRTUAL_USES) != 0; + bool do_nonvirtuals = (use_flags & SSA_OP_USE) != 0; FOR_EACH_EDGE (e, ei, bb->succs) for (gphi_iterator bsi = gsi_start_phis (e->dest); !gsi_end_p (bsi); gsi_next (&bsi)) { gphi *phi = bsi.phi (); - if (! virtual_operand_p (gimple_phi_result (phi))) + bool virtual_p = virtual_operand_p (gimple_phi_result (phi)); + if ((virtual_p && do_virtuals) + || (!virtual_p && do_nonvirtuals)) find_uses_to_rename_use (bb, PHI_ARG_DEF_FROM_EDGE (phi, e), use_blocks, need_phis); } for (gimple_stmt_iterator bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi)) - find_uses_to_rename_stmt (gsi_stmt (bsi), use_blocks, need_phis); + find_uses_to_rename_stmt (gsi_stmt (bsi), use_blocks, need_phis, + use_flags); } -/* Marks names that are used outside of the loop they are defined in - for rewrite. Records the set of blocks in that the ssa - names are defined to USE_BLOCKS. If CHANGED_BBS is not NULL, - scan only blocks in this set. */ +/* Marks names matching USE_FLAGS that are used outside of the loop they are + defined in for rewrite. Records the set of blocks in which the ssa names are + used to USE_BLOCKS. Record the SSA names that will need exit PHIs in + NEED_PHIS. If CHANGED_BBS is not NULL, scan only blocks in this set. */ static void -find_uses_to_rename (bitmap changed_bbs, bitmap *use_blocks, bitmap need_phis) +find_uses_to_rename (bitmap changed_bbs, bitmap *use_blocks, bitmap need_phis, + int use_flags) { basic_block bb; unsigned index; @@ -460,10 +478,96 @@ find_uses_to_rename (bitmap changed_bbs, bitmap *use_blocks, bitmap need_phis) if (changed_bbs) EXECUTE_IF_SET_IN_BITMAP (changed_bbs, 0, index, bi) - find_uses_to_rename_bb (BASIC_BLOCK_FOR_FN (cfun, index), use_blocks, need_phis); + find_uses_to_rename_bb (BASIC_BLOCK_FOR_FN (cfun, index), use_blocks, + need_phis, use_flags); else FOR_EACH_BB_FN (bb, cfun) - find_uses_to_rename_bb (bb, use_blocks, need_phis); + find_uses_to_rename_bb (bb, use_blocks, need_phis, use_flags); +} + +/* Mark uses of DEF that are used outside of the loop they are defined in for + rewrite. Record the set of blocks in which the ssa names are used to + USE_BLOCKS. Record the SSA names that will need exit PHIs in NEED_PHIS. */ + +static void +find_uses_to_rename_def (tree def, bitmap *use_blocks, bitmap need_phis) +{ + gimple use_stmt; + imm_use_iterator imm_iter; + + FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter, def) + { + basic_block use_bb = gimple_bb (use_stmt); + + use_operand_p use_p; + FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter) + { + if (gimple_code (use_stmt) == GIMPLE_PHI) + { + edge e = gimple_phi_arg_edge (as_a <gphi *> (use_stmt), + PHI_ARG_INDEX_FROM_USE (use_p)); + use_bb = e->src; + } + find_uses_to_rename_use (use_bb, USE_FROM_PTR (use_p), use_blocks, + need_phis); + } + } +} + +/* Marks names matching USE_FLAGS that are defined in LOOP and used outside of + it for rewrite. Records the set of blocks in which the ssa names are used to + USE_BLOCKS. Record the SSA names that will need exit PHIs in NEED_PHIS. */ + +static void +find_uses_to_rename_in_loop (struct loop *loop, bitmap *use_blocks, + bitmap need_phis, int use_flags) +{ + bool do_virtuals = (use_flags & SSA_OP_VIRTUAL_USES) != 0; + bool do_nonvirtuals = (use_flags & SSA_OP_USE) != 0; + int def_flags = ((do_virtuals ? SSA_OP_VIRTUAL_DEFS : 0) + | (do_nonvirtuals ? SSA_OP_DEF : 0)); + + + basic_block *bbs = get_loop_body (loop); + + for (unsigned int i = 0; i < loop->num_nodes; i++) + { + basic_block bb = bbs[i]; + + for (gphi_iterator bsi = gsi_start_phis (bb); !gsi_end_p (bsi); + gsi_next (&bsi)) + { + gphi *phi = bsi.phi (); + tree res = gimple_phi_result (phi); + bool virtual_p = virtual_operand_p (res); + if ((virtual_p && do_virtuals) + || (!virtual_p && do_nonvirtuals)) + find_uses_to_rename_def (res, use_blocks, need_phis); + } + + for (gimple_stmt_iterator bsi = gsi_start_bb (bb); !gsi_end_p (bsi); + gsi_next (&bsi)) + { + gimple stmt = gsi_stmt (bsi); + /* FOR_EACH_SSA_TREE_OPERAND iterator does not allows + SSA_OP_VIRTUAL_DEFS only. */ + if (def_flags == SSA_OP_VIRTUAL_DEFS) + { + tree vdef = gimple_vdef (stmt); + if (vdef != NULL) + find_uses_to_rename_def (vdef, use_blocks, need_phis); + } + else + { + tree var; + ssa_op_iter iter; + FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, def_flags) + find_uses_to_rename_def (var, use_blocks, need_phis); + } + } + } + + XDELETEVEC (bbs); } /* Rewrites the program into a loop closed ssa form -- i.e. inserts extra @@ -495,14 +599,19 @@ find_uses_to_rename (bitmap changed_bbs, bitmap *use_blocks, bitmap need_phis) is not well-behaved, while the second one is an induction variable with base 99 and step 1. - If CHANGED_BBS is not NULL, we look for uses outside loops only in - the basic blocks in this set. + If LOOP is non-null, only rewrite uses that have defs in LOOP. Otherwise, + if CHANGED_BBS is not NULL, we look for uses outside loops only in the + basic blocks in this set. + + USE_FLAGS allows us to specify whether we want virtual, non-virtual or + both variables rewritten. UPDATE_FLAG is used in the call to update_ssa. See TODO_update_ssa* for documentation. */ void -rewrite_into_loop_closed_ssa (bitmap changed_bbs, unsigned update_flag) +rewrite_into_loop_closed_ssa_1 (bitmap changed_bbs, unsigned update_flag, + int use_flags, struct loop *loop) { bitmap *use_blocks; bitmap names_to_rename; @@ -513,7 +622,14 @@ rewrite_into_loop_closed_ssa (bitmap changed_bbs, unsigned update_flag) /* If the pass has caused the SSA form to be out-of-date, update it now. */ - update_ssa (update_flag); + if (update_flag == 0) + { +#ifdef ENABLE_CHECKING + verify_ssa (true, true); +#endif + } + else + update_ssa (update_flag); bitmap_obstack_initialize (&loop_renamer_obstack); @@ -524,8 +640,17 @@ rewrite_into_loop_closed_ssa (bitmap changed_bbs, unsigned update_flag) in NAMES_TO_RENAME. */ use_blocks = XNEWVEC (bitmap, num_ssa_names); - /* Find the uses outside loops. */ - find_uses_to_rename (changed_bbs, use_blocks, names_to_rename); + if (loop != NULL) + { + gcc_assert (changed_bbs == NULL); + find_uses_to_rename_in_loop (loop, use_blocks, names_to_rename, + use_flags); + } + else + { + gcc_assert (loop == NULL); + find_uses_to_rename (changed_bbs, use_blocks, names_to_rename, use_flags); + } if (!bitmap_empty_p (names_to_rename)) { @@ -549,55 +674,24 @@ rewrite_into_loop_closed_ssa (bitmap changed_bbs, unsigned update_flag) free (use_blocks); } -/* Replace uses of OLD_VAL with NEW_VAL in bbs dominated by BB. */ +/* Rewrites the non-virtual defs and uses into a loop closed ssa form. If + CHANGED_BBS is not NULL, we look for uses outside loops only in the basic + blocks in this set. UPDATE_FLAG is used in the call to update_ssa. See + TODO_update_ssa* for documentation. */ -static void -replace_uses_in_dominated_bbs (tree old_val, tree new_val, basic_block bb) +void +rewrite_into_loop_closed_ssa (bitmap changed_bbs, unsigned update_flag) { - gimple use_stmt; - imm_use_iterator imm_iter; - - FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter, old_val) - { - if (!dominated_by_p (CDI_DOMINATORS, gimple_bb (use_stmt), bb)) - continue; - - use_operand_p use_p; - FOR_EACH_IMM_USE_ON_STMT (use_p, imm_iter) - SET_USE (use_p, new_val); - } + rewrite_into_loop_closed_ssa_1 (changed_bbs, update_flag, SSA_OP_USE, NULL); } -/* Ensure a virtual phi is present in the exit block, if LOOP contains a vdef. - In other words, ensure loop-closed ssa normal form for virtuals. Handles - only loops with a single exit that dominates the latch. */ +/* Rewrites virtual defs and uses with def in LOOP into loop closed ssa + form. */ void rewrite_virtuals_into_loop_closed_ssa (struct loop *loop) { - gphi *phi; - /* TODO: Handle !single_dom_exit loops. */ - edge exit = single_dom_exit (loop); - gcc_assert (exit != NULL); - - phi = get_virtual_phi (loop->header); - if (phi == NULL) - return; - - tree final_loop = PHI_ARG_DEF_FROM_EDGE (phi, single_succ_edge (loop->latch)); - - phi = get_virtual_phi (exit->dest); - if (phi != NULL) - { - tree final_exit = PHI_ARG_DEF_FROM_EDGE (phi, exit); - gcc_assert (operand_equal_p (final_loop, final_exit, 0)); - return; - } - - tree res_new = copy_ssa_name (final_loop, NULL); - gphi *nphi = create_phi_node (res_new, exit->dest); - replace_uses_in_dominated_bbs (final_loop, res_new, exit->dest); - add_phi_arg (nphi, final_loop, exit, UNKNOWN_LOCATION); + rewrite_into_loop_closed_ssa_1 (NULL, 0, SSA_OP_VIRTUAL_USES, loop); } /* Check invariants of the loop closed ssa form for the USE in BB. */ diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c index d46e6c2a6ff..8da0bcc1012 100644 --- a/gcc/tree-ssa-loop-niter.c +++ b/gcc/tree-ssa-loop-niter.c @@ -2083,6 +2083,10 @@ simplify_using_initial_conditions (struct loop *loop, tree expr) if (e->flags & EDGE_FALSE_VALUE) cond = invert_truthvalue (cond); expr = tree_simplify_using_condition (cond, expr); + /* Break if EXPR is simplified to const values. */ + if (expr && (integer_zerop (expr) || integer_nonzerop (expr))) + break; + ++cnt; } diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c index 71641228237..451dc2e1c2e 100644 --- a/gcc/tree-ssa-threadedge.c +++ b/gcc/tree-ssa-threadedge.c @@ -553,6 +553,24 @@ simplify_control_stmt_condition (edge e, || !is_gimple_min_invariant (cached_lhs)) cached_lhs = (*simplify) (dummy_cond, stmt); + /* If we were just testing that an integral type was != 0, and that + failed, just return the first operand. This gives the FSM code a + chance to optimize the path. */ + if (cached_lhs == NULL + && cond_code == NE_EXPR) + { + /* Recover the original operands. They may have been simplified + using context sensitive equivalences. Those context sensitive + equivalences may not be valid on paths found by the FSM optimizer. */ + tree op0 = gimple_cond_lhs (stmt); + tree op1 = gimple_cond_rhs (stmt); + + if (INTEGRAL_TYPE_P (TREE_TYPE (op0)) + && TREE_CODE (op0) == SSA_NAME + && integer_zerop (op1)) + return op0; + } + return cached_lhs; } @@ -974,6 +992,21 @@ fsm_find_control_statement_thread_paths (tree expr, return; } + /* Make sure we haven't already visited any of the nodes in + NEXT_PATH. Don't add them here to avoid pollution. */ + for (unsigned int i = 0; i < next_path->length () - 1; i++) + { + if (visited_bbs->contains ((*next_path)[i])) + { + vec_free (next_path); + return; + } + } + + /* Now add the nodes to VISISTED_BBS. */ + for (unsigned int i = 0; i < next_path->length () - 1; i++) + visited_bbs->add ((*next_path)[i]); + /* Append all the nodes from NEXT_PATH to PATH. */ vec_safe_splice (path, next_path); next_path_length = next_path->length (); diff --git a/gcc/tree-ssa-threadupdate.c b/gcc/tree-ssa-threadupdate.c index 5a5f8df172f..f4d3fdcdde5 100644 --- a/gcc/tree-ssa-threadupdate.c +++ b/gcc/tree-ssa-threadupdate.c @@ -2493,6 +2493,12 @@ duplicate_thread_path (edge entry, edge exit, /* Remove the last branch in the jump thread path. */ remove_ctrl_stmt_and_useless_edges (region_copy[n_region - 1], exit->dest); + + /* And fixup the flags on the single remaining edge. */ + edge fix_e = find_edge (region_copy[n_region - 1], exit->dest); + fix_e->flags &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE | EDGE_ABNORMAL); + fix_e->flags |= EDGE_FALLTHRU; + edge e = make_edge (region_copy[n_region - 1], exit->dest, EDGE_FALLTHRU); if (e) { diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c index 2ddd4343a2a..f87c0664e5b 100644 --- a/gcc/tree-vect-stmts.c +++ b/gcc/tree-vect-stmts.c @@ -4719,7 +4719,7 @@ vectorizable_operation (gimple stmt, gimple_stmt_iterator *gsi, tree new_temp; int op_type; optab optab; - int icode; + bool target_support_p; tree def; gimple def_stmt; enum vect_def_type dt[3] @@ -4870,12 +4870,7 @@ vectorizable_operation (gimple stmt, gimple_stmt_iterator *gsi, vec_mode = TYPE_MODE (vectype); if (code == MULT_HIGHPART_EXPR) - { - if (can_mult_highpart_p (vec_mode, TYPE_UNSIGNED (vectype))) - icode = LAST_INSN_CODE; - else - icode = CODE_FOR_nothing; - } + target_support_p = can_mult_highpart_p (vec_mode, TYPE_UNSIGNED (vectype)); else { optab = optab_for_tree_code (code, vectype, optab_default); @@ -4886,10 +4881,11 @@ vectorizable_operation (gimple stmt, gimple_stmt_iterator *gsi, "no optab.\n"); return false; } - icode = (int) optab_handler (optab, vec_mode); + target_support_p = (optab_handler (optab, vec_mode) + != CODE_FOR_nothing); } - if (icode == CODE_FOR_nothing) + if (!target_support_p) { if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, diff --git a/gcc/tree.c b/gcc/tree.c index af3a6a340e4..ed64fe7d273 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -2215,6 +2215,17 @@ grow_tree_vec_stat (tree v, int len MEM_STAT_DECL) return v; } +/* Return 1 if EXPR is the constant zero, whether it is integral, float or + fixed, and scalar, complex or vector. */ + +int +zerop (const_tree expr) +{ + return (integer_zerop (expr) + || real_zerop (expr) + || fixed_zerop (expr)); +} + /* Return 1 if EXPR is the integer constant zero or a complex constant of zero. */ @@ -7512,6 +7523,8 @@ valid_constant_size_p (const_tree size) unsigned int element_precision (const_tree type) { + if (!TYPE_P (type)) + type = TREE_TYPE (type); enum tree_code code = TREE_CODE (type); if (code == COMPLEX_TYPE || code == VECTOR_TYPE) type = TREE_TYPE (type); diff --git a/gcc/tree.h b/gcc/tree.h index 2cd6ec475a8..e5001510bdc 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -4109,6 +4109,10 @@ extern tree uniform_vector_p (const_tree); extern vec<tree, va_gc> *ctor_to_vec (tree); +/* zerop (tree x) is nonzero if X is a constant of value 0. */ + +extern int zerop (const_tree); + /* integer_zerop (tree x) is nonzero if X is an integer constant of value 0. */ extern int integer_zerop (const_tree); diff --git a/gcc/value-prof.c b/gcc/value-prof.c index 8aace8c872c..324f3c8a817 100644 --- a/gcc/value-prof.c +++ b/gcc/value-prof.c @@ -212,7 +212,6 @@ gimple_add_histogram_value (struct function *fun, gimple stmt, hist->fun = fun; } - /* Remove histogram HIST from STMT's histogram list. */ void @@ -237,7 +236,6 @@ gimple_remove_histogram_value (struct function *fun, gimple stmt, free (hist); } - /* Lookup histogram of type TYPE in the STMT. */ histogram_value @@ -408,6 +406,7 @@ stream_out_histogram_value (struct output_block *ob, histogram_value hist) if (hist->hvalue.next) stream_out_histogram_value (ob, hist->hvalue.next); } + /* Dump information about HIST to DUMP_FILE. */ void @@ -512,7 +511,6 @@ gimple_duplicate_stmt_histograms (struct function *fun, gimple stmt, } } - /* Move all histograms associated with OSTMT to STMT. */ void @@ -553,7 +551,6 @@ visit_hist (void **slot, void *data) return 1; } - /* Verify sanity of the histograms. */ DEBUG_FUNCTION void @@ -616,7 +613,6 @@ free_histograms (void) } } - /* The overall number of invocations of the counter should match execution count of basic block. Report it as error rather than internal error as it might mean that user has misused the profile @@ -660,7 +656,6 @@ check_counter (gimple stmt, const char * name, return false; } - /* GIMPLE based transformations. */ bool @@ -669,7 +664,6 @@ gimple_value_profile_transformations (void) basic_block bb; gimple_stmt_iterator gsi; bool changed = false; - FOR_EACH_BB_FN (bb, cfun) { for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) @@ -719,7 +713,6 @@ gimple_value_profile_transformations (void) return changed; } - /* Generate code for transformation 1 (with parent gimple assignment STMT and probability of taking the optimal path PROB, which is equivalent to COUNT/ALL within roundoff error). This generates the @@ -802,7 +795,6 @@ gimple_divmod_fixed_value (gassign *stmt, tree value, int prob, return tmp2; } - /* Do transform 1) on INSN if applicable. */ static bool @@ -888,6 +880,7 @@ gimple_divmod_fixed_value_transform (gimple_stmt_iterator *si) probability of taking the optimal path PROB, which is equivalent to COUNT/ALL within roundoff error). This generates the result into a temp and returns the temp; it does not replace or alter the original STMT. */ + static tree gimple_mod_pow2 (gassign *stmt, int prob, gcov_type count, gcov_type all) { @@ -968,6 +961,7 @@ gimple_mod_pow2 (gassign *stmt, int prob, gcov_type count, gcov_type all) } /* Do transform 2) on INSN if applicable. */ + static bool gimple_mod_pow2_value_transform (gimple_stmt_iterator *si) { @@ -1137,7 +1131,6 @@ gimple_mod_subtract (gassign *stmt, int prob1, int prob2, int ncounts, return result; } - /* Do transforms 3) and 4) on the statement pointed-to by SI if applicable. */ static bool @@ -1151,7 +1144,6 @@ gimple_mod_subtract_transform (gimple_stmt_iterator *si) unsigned int i, steps; gcov_type count1, count2; gassign *stmt; - stmt = dyn_cast <gassign *> (gsi_stmt (*si)); if (!stmt) return false; @@ -1632,15 +1624,15 @@ gimple_ic_transform (gimple_stmt_iterator *gsi) return true; } -/* Return true if the stringop CALL with FNDECL shall be profiled. - SIZE_ARG be set to the argument index for the size of the string - operation. -*/ +/* Return true if the stringop CALL shall be profiled. SIZE_ARG be + set to the argument index for the size of the string operation. */ + static bool -interesting_stringop_to_profile_p (tree fndecl, gcall *call, int *size_arg) +interesting_stringop_to_profile_p (gcall *call, int *size_arg) { - enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl); + enum built_in_function fcode; + fcode = DECL_FUNCTION_CODE (gimple_call_fndecl (call)); if (fcode != BUILT_IN_MEMCPY && fcode != BUILT_IN_MEMPCPY && fcode != BUILT_IN_MEMSET && fcode != BUILT_IN_BZERO) return false; @@ -1665,7 +1657,7 @@ interesting_stringop_to_profile_p (tree fndecl, gcall *call, int *size_arg) } } -/* Convert stringop (..., vcall_size) +/* Convert stringop (..., vcall_size) into if (vcall_size == icall_size) stringop (..., icall_size); @@ -1684,11 +1676,9 @@ gimple_stringop_fixed_value (gcall *vcall_stmt, tree icall_size, int prob, basic_block cond_bb, icall_bb, vcall_bb, join_bb; edge e_ci, e_cv, e_iv, e_ij, e_vj; gimple_stmt_iterator gsi; - tree fndecl; int size_arg; - fndecl = gimple_call_fndecl (vcall_stmt); - if (!interesting_stringop_to_profile_p (fndecl, vcall_stmt, &size_arg)) + if (!interesting_stringop_to_profile_p (vcall_stmt, &size_arg)) gcc_unreachable (); cond_bb = gimple_bb (vcall_stmt); @@ -1767,11 +1757,11 @@ gimple_stringop_fixed_value (gcall *vcall_stmt, tree icall_size, int prob, /* Find values inside STMT for that we want to measure histograms for division/modulo optimization. */ + static bool gimple_stringops_transform (gimple_stmt_iterator *gsi) { gcall *stmt; - tree fndecl; tree blck_size; enum built_in_function fcode; histogram_value histogram; @@ -1785,11 +1775,11 @@ gimple_stringops_transform (gimple_stmt_iterator *gsi) stmt = dyn_cast <gcall *> (gsi_stmt (*gsi)); if (!stmt) return false; - fndecl = gimple_call_fndecl (stmt); - if (!fndecl) + + if (!gimple_call_builtin_p (gsi_stmt (*gsi), BUILT_IN_NORMAL)) return false; - fcode = DECL_FUNCTION_CODE (fndecl); - if (!interesting_stringop_to_profile_p (fndecl, stmt, &size_arg)) + + if (!interesting_stringop_to_profile_p (stmt, &size_arg)) return false; blck_size = gimple_call_arg (stmt, size_arg); @@ -1799,10 +1789,12 @@ gimple_stringops_transform (gimple_stmt_iterator *gsi) histogram = gimple_histogram_value_of_type (cfun, stmt, HIST_TYPE_SINGLE_VALUE); if (!histogram) return false; + val = histogram->hvalue.counters[0]; count = histogram->hvalue.counters[1]; all = histogram->hvalue.counters[2]; gimple_remove_histogram_value (cfun, stmt, histogram); + /* We require that count is at least half of all; this means that for the transformation to fire the value must be constant at least 80% of time. */ @@ -1814,8 +1806,10 @@ gimple_stringops_transform (gimple_stmt_iterator *gsi) prob = GCOV_COMPUTE_SCALE (count, all); else prob = 0; + dest = gimple_call_arg (stmt, 0); dest_align = get_pointer_alignment (dest); + fcode = DECL_FUNCTION_CODE (gimple_call_fndecl (stmt)); switch (fcode) { case BUILT_IN_MEMCPY: @@ -1840,6 +1834,7 @@ gimple_stringops_transform (gimple_stmt_iterator *gsi) default: gcc_unreachable (); } + if (sizeof (gcov_type) == sizeof (HOST_WIDE_INT)) tree_val = build_int_cst (get_gcov_type (), val); else @@ -1858,6 +1853,7 @@ gimple_stringops_transform (gimple_stmt_iterator *gsi) (int)val); print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM); } + gimple_stringop_fixed_value (stmt, tree_val, prob, count, all); return true; @@ -1869,6 +1865,7 @@ stringop_block_profile (gimple stmt, unsigned int *expected_align, { histogram_value histogram; histogram = gimple_histogram_value_of_type (cfun, stmt, HIST_TYPE_AVERAGE); + if (!histogram) *expected_size = -1; else if (!histogram->hvalue.counters[1]) @@ -1889,7 +1886,9 @@ stringop_block_profile (gimple stmt, unsigned int *expected_align, *expected_size = size; gimple_remove_histogram_value (cfun, stmt, histogram); } + histogram = gimple_histogram_value_of_type (cfun, stmt, HIST_TYPE_IOR); + if (!histogram) *expected_align = 0; else if (!histogram->hvalue.counters[0]) @@ -1915,6 +1914,7 @@ stringop_block_profile (gimple stmt, unsigned int *expected_align, /* Find values inside STMT for that we want to measure histograms for division/modulo optimization. */ + static void gimple_divmod_values_to_profile (gimple stmt, histogram_values *values) { @@ -1999,11 +1999,11 @@ gimple_indirect_call_to_profile (gimple stmt, histogram_values *values) /* Find values inside STMT for that we want to measure histograms for string operations. */ + static void gimple_stringops_values_to_profile (gimple gs, histogram_values *values) { gcall *stmt; - tree fndecl; tree blck_size; tree dest; int size_arg; @@ -2011,11 +2011,11 @@ gimple_stringops_values_to_profile (gimple gs, histogram_values *values) stmt = dyn_cast <gcall *> (gs); if (!stmt) return; - fndecl = gimple_call_fndecl (stmt); - if (!fndecl) + + if (!gimple_call_builtin_p (gs, BUILT_IN_NORMAL)) return; - if (!interesting_stringop_to_profile_p (fndecl, stmt, &size_arg)) + if (!interesting_stringop_to_profile_p (stmt, &size_arg)) return; dest = gimple_call_arg (stmt, 0); @@ -2029,6 +2029,7 @@ gimple_stringops_values_to_profile (gimple gs, histogram_values *values) values->safe_push (gimple_alloc_histogram_value (cfun, HIST_TYPE_AVERAGE, stmt, blck_size)); } + if (TREE_CODE (blck_size) != INTEGER_CST) values->safe_push (gimple_alloc_histogram_value (cfun, HIST_TYPE_IOR, stmt, dest)); diff --git a/gcc/varasm.c b/gcc/varasm.c index 2ebac89f99e..d9290a17cbb 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -1043,7 +1043,6 @@ align_variable (tree decl, bool dont_output_data) if (! DECL_THREAD_LOCAL_P (decl) || data_align <= BITS_PER_WORD) align = data_align; #endif -#ifdef CONSTANT_ALIGNMENT if (DECL_INITIAL (decl) != 0 /* In LTO we have no errors in program; error_mark_node is used to mark offlined constructors. */ @@ -1056,7 +1055,6 @@ align_variable (tree decl, bool dont_output_data) if (! DECL_THREAD_LOCAL_P (decl) || const_align <= BITS_PER_WORD) align = const_align; } -#endif } } @@ -1097,7 +1095,6 @@ get_variable_align (tree decl) if (! DECL_THREAD_LOCAL_P (decl) || data_align <= BITS_PER_WORD) align = data_align; #endif -#ifdef CONSTANT_ALIGNMENT if (DECL_INITIAL (decl) != 0 /* In LTO we have no errors in program; error_mark_node is used to mark offlined constructors. */ @@ -1110,7 +1107,6 @@ get_variable_align (tree decl) if (! DECL_THREAD_LOCAL_P (decl) || const_align <= BITS_PER_WORD) align = const_align; } -#endif } return align; @@ -3286,9 +3282,7 @@ build_constant_desc (tree exp) architectures so use DATA_ALIGNMENT as well, except for strings. */ if (TREE_CODE (exp) == STRING_CST) { -#ifdef CONSTANT_ALIGNMENT DECL_ALIGN (decl) = CONSTANT_ALIGNMENT (exp, DECL_ALIGN (decl)); -#endif } else align_variable (decl, 0); @@ -3743,13 +3737,10 @@ force_const_mem (machine_mode mode, rtx x) /* Align the location counter as required by EXP's data type. */ align = GET_MODE_ALIGNMENT (mode == VOIDmode ? word_mode : mode); -#ifdef CONSTANT_ALIGNMENT - { - tree type = lang_hooks.types.type_for_mode (mode, 0); - if (type != NULL_TREE) - align = CONSTANT_ALIGNMENT (make_tree (type, x), align); - } -#endif + + tree type = lang_hooks.types.type_for_mode (mode, 0); + if (type != NULL_TREE) + align = CONSTANT_ALIGNMENT (make_tree (type, x), align); pool->offset += (align / BITS_PER_UNIT) - 1; pool->offset &= ~ ((align / BITS_PER_UNIT) - 1); @@ -5412,7 +5403,10 @@ declare_weak (tree decl) { gcc_assert (TREE_CODE (decl) != FUNCTION_DECL || !TREE_ASM_WRITTEN (decl)); if (! TREE_PUBLIC (decl)) - error ("weak declaration of %q+D must be public", decl); + { + error ("weak declaration of %q+D must be public", decl); + return; + } else if (!TARGET_SUPPORTS_WEAK) warning (0, "weak declaration of %q+D not supported", decl); diff --git a/gcc/varpool.c b/gcc/varpool.c index 10fa93c9ef8..7d11e20e116 100644 --- a/gcc/varpool.c +++ b/gcc/varpool.c @@ -586,6 +586,12 @@ varpool_node::assemble_decl (void) gcc_assert (TREE_ASM_WRITTEN (decl)); gcc_assert (definition); assemble_aliases (); + /* After the parser has generated debugging information, augment + this information with any new location/etc information that may + have become available after the compilation proper. */ + timevar_start (TV_PHASE_DBGINFO); + debug_hooks->late_global_decl (decl); + timevar_stop (TV_PHASE_DBGINFO); return true; } |