diff options
author | mrs <mrs@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-11-04 21:29:11 +0000 |
---|---|---|
committer | mrs <mrs@138bc75d-0d04-0410-961f-82ee72b054a4> | 2013-11-04 21:29:11 +0000 |
commit | aeb682a27a580c32813c316b911b59b851f6f34e (patch) | |
tree | caef14d95e41d87b155a732aa16f18f483eea729 /gcc | |
parent | 8945e16bd0dc520c80b423cc0802c89ce551ff08 (diff) | |
parent | 8dd9f7ce09ba28909b069f5baa405ea4cc7b5c42 (diff) | |
download | gcc-aeb682a27a580c32813c316b911b59b851f6f34e.tar.gz |
Merge in trunk.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/wide-int@204366 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
1570 files changed, 36041 insertions, 10421 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 65fb879ea6a..7e0b752c3ed 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,2496 @@ +2013-11-04 Vladimir Makarov <vmakarov@redhat.com> + + PR rtl-optimization/58968 + * lra-spills.c (return_regno_p): New function. + (lra_final_code_change): Use it. + +2013-11-04 Joseph Myers <joseph@codesourcery.com> + + * doc/cpp.texi (__GCC_IEC_559, __GCC_IEC_559_COMPLEX): Document + macros. + * target.def (float_exceptions_rounding_supported_p): New hook. + * targhooks.c (default_float_exceptions_rounding_supported_p): New + function. + * targhooks.h (default_float_exceptions_rounding_supported_p): + Declare. + * doc/tm.texi.in (TARGET_FLOAT_EXCEPTIONS_ROUNDING_SUPPORTED_P): + New @hook. + * doc/tm.texi: Regenerate. + * config.gcc (powerpc*-*-linux*): Set extra_objs. + * config/rs6000/rs6000-linux.c: New file. + * config/rs6000/rs6000-protos.h + (rs6000_linux_float_exceptions_rounding_supported_p): Declare. + * config/rs6000/linux.h + (TARGET_FLOAT_EXCEPTIONS_ROUNDING_SUPPORTED_P): New macro. + * config/rs6000/linux64.h + (TARGET_FLOAT_EXCEPTIONS_ROUNDING_SUPPORTED_P): Likewise. + * config/rs6000/t-linux (rs6000-linux.o): New rule. + * config/rs6000/t-linux64 (rs6000-linux.o): Likewise. + +2013-11-04 Bill Schmidt <wschmidt@linux.vnet.ibm.com> + + * config/rs6000/vsx.md (*vsx_le_perm_store_<mode> for VSX_D): + Replace the define_insn_and_split with a define_insn and two + define_splits, with the split after reload re-permuting the source + register to its original value. + (*vsx_le_perm_store_<mode> for VSX_W): Likewise. + (*vsx_le_perm_store_v8hi): Likewise. + (*vsx_le_perm_store_v16qi): Likewise. + +2013-11-04 Bill Schmidt <wschmidt@linux.vnet.ibm.com> + + * config/rs6000/vector.md (vec_pack_trunc_v2df): Adjust for + little endian. + +2013-11-04 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/58946 + * tree-ssa-reassoc.c (maybe_optimize_range_tests): Update all + bbs with bbinfo[idx].op != NULL before all blocks with + bbinfo[idx].op == NULL. + +2013-11-04 Richard Sandiford <rdsandiford@googlemail.com> + + * config/avr/avr-log.c (avr_double_int_pop_digit): Delete. + (avr_dump_double_int_hex): Likewise. + (avr_log_vadump): Remove %D and %X handling. + * config/avr/avr.c (avr_double_int_push_digit): Delete. + (avr_map_op_t): Change map from double_int to unsigned int. + (avr_map_op): Update accordingly. + (avr_map, avr_map_metric, avr_has_nibble_0xf, avr_map_decompose) + (avr_move_bits, avr_out_insert_bits, avr_fold_builtin): Operate on + unsigned ints rather than double_ints. + +2013-11-03 Marek Polacek <polacek@redhat.com> + + Implement -fsanitize=vla-bound. + * opts.c (common_handle_option): Handle vla-bound. + * sanitizer.def (BUILT_IN_UBSAN_HANDLE_VLA_BOUND_NOT_POSITIVE): + Define. + * flag-types.h (enum sanitize_code): Add SANITIZE_VLA. + * asan.c (initialize_sanitizer_builtins): Build BT_FN_VOID_PTR_PTR. + +2013-11-02 Bill Schmidt <wschmidt@vnet.linux.ibm.com> + + * config/rs6000/rs6000.c (rs6000_expand_vector_set): Adjust for + little endian. + +2013-11-02 Uros Bizjak <ubizjak@gmail.com> + + * config/i386/constraints.md (Ts, Tv): New address constrains. + * config/i386/i386.md (*lea<mode>, *<mode>_<bndcheck>): Use Ts + constraint for address_no_seg_operand. + * config/i386/sse.md (*avx512pf_gatherpf<mode>_mask) + (*avx512pf_gatherpf<mode>, *avx512pf_scatterpf<mode>_mask) + (*avx512pf_scatterpf<mode>, *avx2_gathersi<mode>) + (*avx2_gathersi<mode>_2, *avx2_gatherdi<mode>, *avx2_gatherdi<mode>_2) + (*avx2_gatherdi<mode>_3, *avx2_gatherdi<mode>_4) + (*avx512f_gathersi<mode>, *avx512f_gathersi<mode>_2) + (*avx512f_gatherdi<mode>, *avx512f_gatherdi<mode>_2) + (*avx512f_scattersi<mode> *avx512f_scatterdi<mode>): Use Tv + constraint for vsib_address_operand. + +2013-11-02 Steven Bosscher <steven@gcc.gnu.org> + + * gcse.c (pre_delete): Remove references to regmove from comments. + * recog.c: (validate_replace_rtx_1): Likewise. + * config/rl78/rl78.c: Likewise. + * config/v850/v850.h: Likewise, and remove unused ENABLE_REGMOVE_PASS. + * common/config/m32r/m32r-common.c: Don't manipulate OPT_fregmove. + * common/config/mmix/mmix-common.c: Likewise. + +2013-11-01 Trevor Saunders <tsaunders@mozilla.com> + + * function.c (reorder_blocks): Convert block_stack to a stack_vec. + * gimplify.c (gimplify_compound_lval): Likewise. + * graphite-clast-to-gimple.c (gloog): Likewise. + * graphite-dependences.c (loop_is_parallel_p): Likewise. + * graphite-scop-detection.c (scopdet_basic_block_info): Likewise. + (limit_scop); Likewise. + (build_scops): Likewise. + (dot_scop): Likewise. + * graphite-sese-to-poly.c (sese_dom_walker): Likewise. + (build_scop_drs): Likewise. + (insert_stmts): Likewise. + (insert_out_of_ssa_copy): Likewise. + (remove_phi): Likewise. + (rewrite_commutative_reductions_out_of_ssa_close_phi): Likewise. + * hw-doloop.c (discover_loop): Likewise. + * tree-call-cdce.c (shrink_wrap_one_built_in_call): Likewise. + * tree-dfa.c (dump_enumerated_decls): Likewise. + * tree-if-conv.c (if_convertable_loop_p): Likewise. + * tree-inline.c (tree_function_versioning): Likewise. + * tree-loop-distribution.c (build_rdg): Likewise. + (rdg_flag_vertex_and_dependent): Likewise. + (distribute_loop): Likewise. + * tree-parloops.c (loop_parallel_p): Likewise. + (eliminate_local_variables): Likewise. + (separate_decls_in_region): Likewise. + * tree-predcom.c (tree_predictive_commoning_loop): Likewise. + * tree-ssa-phiopt.c (cond_if_else_store_replacement): Likewise. + * tree-ssa-uncprop.c (uncprop_dom_walker): Likewise. + * tree-vect-loop.c (vect_analyze_scaler_cycles_1): Likewise. + * tree-vect-patterns.c (vect_pattern_recog): Likewise. + * tree-vect-stmts.c (vect_mark_stmts_to_be_vectorized): Likewise. + (vectorizable_condition): Likewise. + +2013-11-01 Uros Bizjak <ubizjak@gmail.com> + + * configure.ac (HAVE_AS_IX86_INTERUNIT_MOVQ): Always define as 0/1. + * configure: Regenerate. + * config/i386/i386.md (*movdi_internal): Change + HAVE_AS_IX86_INTERUNIT_MOVQ to runtime check. + (*movdf_internal): Ditto. + * config/i386/mmx.md (*mov<mode>_internal): Ditto. + * config/i386/sse.md (vec_concatv2di): Output interunit movq + for HAVE_AS_IX86_INTERUNIT_MOVQ targets. + +2013-10-31 Robert Suchanek <Robert.Suchanek@imgtec.com> + + * lra-spills.c (assign_spill_hard_regs): Remove statement terminator + after comment. + +2013-10-31 David Malcolm <dmalcolm@redhat.com> + + Automated part of renaming of symtab_node_base to symtab_node. + + Patch autogenerated by rename_symtab.py from + https://github.com/davidmalcolm/gcc-refactoring-scripts + revision 58bb219cc090b2f4516a9297d868c245495ee622 + with ChangeLog entry fixed up by hand. + + * cgraph.c (x_cgraph_nodes_queue): Rename symtab_node_base to + symtab_node. + (cgraph_node_for_asm): Likewise. + * cgraph.h (symtab_node_base): Likewise. + (cgraph_node): Likewise. + (varpool_node): Likewise. + (is_a_helper <cgraph_node>::test): Likewise. + (is_a_helper <varpool_node>::test): Likewise. + (symtab_nodes): Likewise. + (symtab_register_node): Likewise. + (symtab_unregister_node): Likewise. + (symtab_remove_node): Likewise. + (symtab_get_node): Likewise. + (symtab_node_for_asm): Likewise. + (symtab_node_asm_name): Likewise. + (symtab_node_name): Likewise. + (symtab_insert_node_to_hashtable): Likewise. + (symtab_add_to_same_comdat_group): Likewise. + (symtab_dissolve_same_comdat_group_list): Likewise. + (dump_symtab_node): Likewise. + (debug_symtab_node): Likewise. + (dump_symtab_base): Likewise. + (verify_symtab_node): Likewise. + (verify_symtab_base): Likewise. + (symtab_used_from_object_file_p): Likewise. + (symtab_alias_ultimate_target): Likewise. + (symtab_resolve_alias): Likewise. + (fixup_same_cpp_alias_visibility): Likewise. + (symtab_for_node_and_aliases): Likewise. + (symtab_nonoverwritable_alias): Likewise. + (availability symtab_node_availability): Likewise. + (symtab_semantically_equivalent_p): Likewise. + (fixup_same_cpp_alias_visibility): Likewise. + (symtab_prevail_in_asm_name_hash): Likewise. + (cgraph): Likewise. + (varpool): Likewise. + (varpool_first_variable): Likewise. + (varpool_next_variable): Likewise. + (varpool_first_static_initializer): Likewise. + (varpool_next_static_initializer): Likewise. + (varpool_first_defined_variable): Likewise. + (varpool_next_defined_variable): Likewise. + (cgraph_first_defined_function): Likewise. + (cgraph_next_defined_function): Likewise. + (cgraph_first_function): Likewise. + (cgraph_next_function): Likewise. + (cgraph_first_function_with_gimple_body): Likewise. + (cgraph_next_function_with_gimple_body): Likewise. + (symtab_alias_target): Likewise. + (symtab_real_symbol_p): Likewise. + (symtab_can_be_discarded): Likewise. + * cgraphbuild.c (mark_address): Likewise. + (mark_load): Likewise. + (mark_store): Likewise. + * cgraphunit.c (decide_is_symbol_needed): Likewise. + (first): Likewise. + (enqueue_node): Likewise. + (referred_to_p): Likewise. + (cgraph_process_same_body_aliases): Likewise. + (analyze_functions): Likewise. + (handle_alias_pairs): Likewise. + (output_weakrefs): Likewise. + (compile): Likewise. + * gimple-fold.c (can_refer_decl_in_current_unit_p): Likewise. + * ipa-inline-analysis.c (inline_write_summary): Likewise. + * ipa-prop.c (remove_described_reference): Likewise. + (try_decrement_rdesc_refcount): Likewise. + (ipa_edge_duplication_hook): Likewise. + * ipa-ref.c (ipa_record_reference): Likewise. + (ipa_maybe_record_reference): Likewise. + (ipa_clone_ref): Likewise. + (ipa_clone_references): Likewise. + (ipa_clone_referring): Likewise. + (ipa_find_reference): Likewise. + (ipa_remove_stmt_references): Likewise. + (ipa_clear_stmts_in_references): Likewise. + * ipa-ref.h (symtab_node_base): Likewise. + (ipa_ref): Likewise. + (ipa_record_reference): Likewise. + (ipa_maybe_record_reference): Likewise. + (ipa_clone_references): Likewise. + (ipa_clone_referring): Likewise. + (ipa_clone_ref): Likewise. + (ipa_find_reference): Likewise. + (ipa_remove_stmt_references): Likewise. + (ipa_clear_stmts_in_references): Likewise. + * ipa-reference.c (ipa_reference_write_optimization_summary): + Likewise. + * ipa.c (enqueue_node): Likewise. + (process_references): Likewise. + (walk_polymorphic_call_targets): Likewise. + (symtab_remove_unreachable_nodes): Likewise. + (address_taken_from_non_vtable_p): Likewise. + (comdat_can_be_unshared_p_1): Likewise. + (comdat_can_be_unshared_p): Likewise. + (can_replace_by_local_alias): Likewise. + (function_and_variable_visibility): Likewise. + * is-a.h: Likewise (within example in comment). + * lto-cgraph.c (input_cgraph_opt_summary): Likewise. + (lto_symtab_encoder_encode): Likewise. + (lto_symtab_encoder_delete_node): Likewise. + (lto_symtab_encoder_in_partition_p): Likewise. + (lto_set_symtab_encoder_in_partition): Likewise. + (output_refs): Likewise. + (compute_ltrans_boundary): Likewise. + (output_symtab): Likewise. + (input_node): Likewise. + (input_ref): Likewise. + (input_edge): Likewise. + (input_cgraph_1): Likewise. + (input_refs): Likewise. + (output_cgraph_opt_summary): Likewise. + (input_node_opt_summary): Likewise. + (input_cgraph_opt_section): Likewise. + * lto-section-in.c (lto_free_function_in_decl_state_for_node): + Likewise. + * lto-streamer-out.c (lto_output): Likewise. + (output_symbol_p): Likewise. + (produce_symtab): Likewise. + * lto-streamer.h (lto_encoder_entry): Likewise. + (lto_free_function_in_decl_state_for_node): Likewise. + (lto_symtab_encoder_encode): Likewise. + (lto_symtab_encoder_delete_node): Likewise. + (lto_symtab_encoder_in_partition_p): Likewise. + (lto_set_symtab_encoder_in_partition): Likewise. + (lto_symtab_encoder_lookup): Likewise. + (lsei_node): Likewise. + (lto_symtab_encoder_deref): Likewise. + * symtab.c (symtab_hash): Likewise. + (assembler_name_hash): Likewise. + (symtab_nodes): Likewise. + (hash_node): Likewise. + (eq_node): Likewise. + (hash_node_by_assembler_name): Likewise. + (eq_assembler_name): Likewise. + (insert_to_assembler_name_hash): Likewise. + (unlink_from_assembler_name_hash): Likewise. + (symtab_prevail_in_asm_name_hash): Likewise. + (symtab_register_node): Likewise. + (symtab_insert_node_to_hashtable): Likewise. + (symtab_unregister_node): Likewise. + (symtab_get_node): Likewise. + (symtab_remove_node): Likewise. + (symtab_initialize_asm_name_hash): Likewise. + (symtab_node_for_asm): Likewise. + (symtab_add_to_same_comdat_group): Likewise. + (symtab_dissolve_same_comdat_group_list): Likewise. + (symtab_node_asm_name): Likewise. + (symtab_node_name): Likewise. + (dump_symtab_base): Likewise. + (dump_symtab_node): Likewise. + (dump_symtab): Likewise. + (debug_symtab_node): Likewise. + (verify_symtab_base): Likewise. + (verify_symtab_node): Likewise. + (verify_symtab): Likewise. + (symtab_used_from_object_file_p): Likewise. + (symtab_node_availability): Likewise. + (symtab_alias_ultimate_target): Likewise. + (fixup_same_cpp_alias_visibility): Likewise. + (symtab_resolve_alias): Likewise. + (symtab_for_node_and_aliases): Likewise. + (symtab_for_node_and_aliases): Likewise. + (symtab_nonoverwritable_alias_1): Likewise. + (symtab_nonoverwritable_alias): Likewise. + (symtab_semantically_equivalent_p): Likewise. + * value-prof.c (init_node_map): Likewise. + * varasm.c (find_decl): Likewise. + * varpool.c (varpool_node_for_asm): Likewise. + (varpool_remove_unreferenced_decls): Likewise. + +2013-10-31 David Malcolm <dmalcolm@redhat.com> + + Manual part of renaming of symtab_node_base to symtab_node. + + * ipa-ref.h (symtab_node): Remove typedef to pointer type, as it + clashes with the preferred name for the base class. + (const_symtab_node): Remove redundant typedef. + +2013-10-31 Jakub Jelinek <jakub@redhat.com> + + * optabs.c (expand_vec_perm): Avoid vector mode punning + SUBREGs in SET_DEST. + * expmed.c (store_bit_field_1): Likewise. + * config/i386/sse.md (movdi_to_sse, vec_pack_sfix_trunc_v2df, + vec_pack_sfix_v2df, vec_shl_<mode>, vec_shr_<mode>, + vec_interleave_high<mode>, vec_interleave_low<mode>): Likewise. + * config/i386/i386.c (ix86_expand_vector_move_misalign, + ix86_expand_sse_movcc, ix86_expand_int_vcond, ix86_expand_vec_perm, + ix86_expand_sse_unpack, ix86_expand_args_builtin, + ix86_expand_vector_init_duplicate, ix86_expand_vector_set, + emit_reduc_half, expand_vec_perm_blend, expand_vec_perm_pshufb, + expand_vec_perm_interleave2, expand_vec_perm_pshufb2, + expand_vec_perm_vpshufb2_vpermq, + expand_vec_perm_vpshufb2_vpermq_even_odd, expand_vec_perm_even_odd_1, + expand_vec_perm_broadcast_1, expand_vec_perm_vpshufb4_vpermq2, + ix86_expand_sse2_mulv4si3, ix86_expand_pinsr): Likewise. + (expand_vec_perm_palignr): Likewise. Modify a copy of *d rather + than *d itself. + +2013-10-31 Uros Bizjak <ubizjak@gmail.com> + + * config/i386/i386.c (ix86_expand_sse2_abs): Rename function arguments. + Use gcc_unreachable for unhandled modes. Do not check results of + expand_simple_binop. If not expanded to target, move the result. + +2013-10-31 Chung-Ju Wu <jasonwucj@gmail.com> + Shiva Chen <shiva0217@gmail.com> + + * config.gcc (nds32*-*-*): Add nds32 target. + * config/nds32/nds32.c: New file. + * config/nds32/nds32.h: New file. + * config/nds32/nds32.md: New file. + * config/nds32/constants.md: New file. + * config/nds32/constraints.md: New file. + * config/nds32/iterators.md: New file. + * config/nds32/nds32-doubleword.md: New file. + * config/nds32/nds32-intrinsic.md: New file. + * config/nds32/nds32_intrinsic.h: New file. + * config/nds32/nds32-modes.def: New file. + * config/nds32/nds32-multiple.md: New file. + * config/nds32/nds32.opt: New file. + * config/nds32/nds32-opts.h: New file. + * config/nds32/nds32-protos.h: New file. + * config/nds32/nds32-peephole2.md: New file. + * config/nds32/pipelines.md: New file. + * config/nds32/predicates.md: New file. + * config/nds32/t-mlibs: New file. + * common/config/nds32: New directory and files. + + * doc/invoke.texi (NDS32 options): Document nds32 specific options. + * doc/md.texi (NDS32 family): Document nds32 specific constraints. + * doc/install.texi (Cross-Compiler-Specific Options): Document + --with-nds32-lib for nds32 target. + * doc/extend.texi (Function Attributes, Target Builtins): Document + nds32 specific attributes. + +2013-10-31 Vladimir Makarov <vmakarov@redhat.com> + + * lra-constraints (process_alt_operands): Use the result + elimination register for operand when matching constraints. + +2013-10-31 Jakub Jelinek <jakub@redhat.com> + + * tree-vrp.c (maybe_set_nonzero_bits): New function. + (remove_range_assertions): Call it. + + * tree.c (tree_ctz): New function. + * tree.h (tree_ctz): New prototype. + * tree-ssanames.h (get_range_info, get_nonzero_bits): Change + first argument from tree to const_tree. + * tree-ssanames.c (get_range_info, get_nonzero_bits): Likewise. + * tree-vectorizer.h (vect_generate_tmps_on_preheader): New prototype. + * tree-vect-loop-manip.c (vect_generate_tmps_on_preheader): No longer + static. + * expr.c (highest_pow2_factor): Reimplemented using tree_ctz. + * tree-vect-loop.c (vect_analyze_loop_operations, + vect_transform_loop): Don't force scalar loop for bound just because + number of iterations is unknown, only do it if it is not known to be + a multiple of vectorization_factor. + * builtins.c (get_object_alignment_2): Use tree_ctz on offset. + + * gimple-pretty-print.c (dump_ssaname_info): Print newline also + in case of VR_VARYING. Print get_nonzero_bits if not all ones. + * tree-ssanames.h (struct range_info_def): Add nonzero_bits field. + (set_nonzero_bits, get_nonzero_bits): New prototypes. + * tree-ssa-ccp.c (get_default_value): Use get_range_info to see if + a default def isn't partially constant. + (ccp_finalize): If after IPA, set_range_info if integral SSA_NAME + is known to be partially zero. + (evaluate_stmt): If we'd return otherwise VARYING, use get_range_info + to see if a default def isn't partially constant. + * tree-ssanames.c (set_range_info): Initialize nonzero_bits upon + creation of a range, if VR_RANGE, try to improve nonzero_bits from + the range. + (set_nonzero_bits, get_nonzero_bits): New functions. + + * tree-cfg.c (assert_unreachable_fallthru_edge_p): New function. + * tree-cfg.h (assert_unreachable_fallthru_edge_p): New prototype. + * tree-vrp.c (all_imm_uses_in_stmt_or_feed_cond): New function. + (remove_range_assertions): If ASSERT_EXPR_VAR has no other immediate + uses but in the condition and ASSERT_EXPR and the other successor of + the predecessor bb is __builtin_unreachable (), set_range_info of the + ASSERT_EXPR_VAR to the range info of the ASSERT_EXPR's lhs. + +2013-10-31 Martin Jambor <mjambor@suse.cz> + + PR rtl-optimization/58934 + Revert: + 2013-10-30 Martin Jambor <mjambor@suse.cz> + PR rtl-optimization/10474 + * ira.c (find_moveable_pseudos): Do not calculate dominance info + nor df analysis. + (interesting_dest_for_shprep): New function. + (split_live_ranges_for_shrink_wrap): Likewise. + (ira): Calculate dominance info and df analysis. Call + split_live_ranges_for_shrink_wrap. + +2013-10-31 Richard Sandiford <rsandifo@linux.vnet.ibm.com> + Yury Gribov <y.gribov@samsung.com> + + PR sanitizer/58543 + * asan.c (asan_clear_shadow): Allocate a new vreg for temporary + shadow pointer to avoid clobbering the main one. + +2013-10-31 Zhenqiang Chen <zhenqiang.chen@linaro.org> + + * lower-subreg.c (resolve_simple_move): Copy REG_INC note. + +2013-10-30 Vladimir Makarov <vmakarov@redhat.com> + + PR bootstrap/58933 + * ira-color.c (update_costs_from_copies): Add new parameter. Use + it for calling update_costs_from_allocno. + (assign_hard_reg): Call restore_costs_from_copies only for + !retry_p. Pass new argument to update_costs_from_copies. + (color_pass): Pass new argument to update_costs_from_copies. + (ira_mark_allocation_change): Ditto. + +2013-10-30 Sharad Singhai <singhai@google.com> + + PR middle-end/58134 + * opts.c (common_handle_option): Remove deprecated option + -ftree-vectorizer-verbose. + * doc/invoke.texi (Debugging Options): Ditto. + * opts-global.c (handle_common_deferred_options): Ditto. + (dump_remap_tree_vectorizer_verbose): Delete. + * common.opt: Set -ftree-vectorizer-verbose as an ignored option. + +2013-10-30 DJ Delorie <dj@redhat.com> + + * config/rx/rx.c (ADD_RX_BUILTIN0): New macro, used for builtins + that take no arguments. + +2013-10-30 Joern Rennecke <joern.rennecke@embecosm.com> + + PR other/58545 + * reload1.c (update_eliminables_and_spill): New function, broken + out of reload. + (reload): Use it. Check for frame size change after frame size + alignment, and call update_eliminables_and_spill first if continue-ing. + +2013-10-30 Cong Hou <congh@google.com> + + PR target/58762 + * config/i386/i386-protos.h (ix86_expand_sse2_abs): New function. + * config/i386/i386.c (ix86_expand_sse2_abs): New function. + * config/i386/sse.md: Add SSE2 support to abs (8/16/32-bit-int). + +2013-10-18 Mikael Pettersson <mikpelinux@gmail.com> + + PR rtl-optimization/58369 + * reload1.c (compute_reload_subreg_offset): New function. + (choose_reload_regs): Use it to pass endian-correct + offset to subreg_regno_offset. + +2013-10-30 Tobias Burnus <burnus@net-b.de> + + PR other/33426 + * gcc/tree-cfg.c (replace_loop_annotate): Replace warning by + warning_at. + +2013-10-30 Jason Merrill <jason@redhat.com> + + * configure.ac (loose_warn): Add -Wno-format if + --disable-build-format-warnings. + +2013-10-30 David Malcolm <dmalcolm@redhat.com> + + * cgraphunit.c (analyze_functions): Split symtab_node declarations + onto multiple lines to make things easier for rename_symtab.py. + + * symtab.c (symtab_dissolve_same_comdat_group_list): Likewise. + (symtab_semantically_equivalent_p): Likewise. + +2013-10-30 Vladimir Makarov <vmakarov@redhat.com> + + PR target/58784 + * lra.c (check_rtl): Remove address check before LRA work. + +2013-10-30 Marc Glisse <marc.glisse@inria.fr> + + * tree-ssa-alias.c (ao_ref_init_from_ptr_and_size): Look for a + POINTER_PLUS_EXPR in the defining statement. + +2013-10-30 Vladimir Makarov <vmakarov@redhat.com> + + * regmove.c: Remove. + * tree-pass.h (make_pass_regmove): Remove. + * timevar.def (TV_REGMOVE): Remove. + * passes.def (pass_regmove): Remove. + * opts.c (default_options_table): Remove entry for regmove. + * doc/passes.texi: Remove regmove pass description. + * doc/invoke.texi (-foptimize-register-move, -fregmove): Remove + options. + (-fdump-rtl-regmove): Ditto. + * common.opt (foptimize-register-move, fregmove): Ignore. + * Makefile.in (OBJS): Remove regmove.o. + * regmove.c: Remove. + * ira-int.h (struct ira_allocno_pref, ira_pref_t): New structure + and type. + (struct ira_allocno) New member allocno_prefs. + (ALLOCNO_PREFS): New macro. + (ira_prefs, ira_prefs_num): New external vars. + (ira_setup_alts, ira_get_dup_out_num, ira_debug_pref): New prototypes. + (ira_debug_prefs, ira_debug_allocno_prefs, ira_create_pref): Ditto. + (ira_add_allocno_pref, ira_remove_pref, ira_remove_allocno_prefs): + Ditto. + (ira_add_allocno_copy_to_list): Remove prototype. + (ira_swap_allocno_copy_ends_if_necessary): Ditto. + (ira_pref_iterator): New type. + (ira_pref_iter_init, ira_pref_iter_cond): New functions. + (FOR_EACH_PREF): New macro. + * ira.c (commutative_constraint_p): Move from ira-conflicts.c. + (ira_get_dup_out_num): Ditto. Rename from get_dup_num. Modify the + code. + (ira_setup_alts): New function. + (decrease_live_ranges_number): New function. + (ira): Call the above function. + * ira-build.c (ira_prefs, ira_prefs_num): New global vars. + (ira_create_allocno): Initialize allocno prefs. + (pref_pool, pref_vec): New static vars. + (initiate_prefs, find_allocno_pref, ira_create_pref): New + functions. + (add_allocno_pref_to_list, ira_add_allocno_pref, print_pref): Ditto. + (ira_debug_pref, print_prefs, ira_debug_prefs): Ditto. + (print_allocno_prefs, ira_debug_allocno_prefs, finish_pref): Ditto. + (ira_remove_pref, ira_remove_allocno_prefs, finish_prefs): Ditto. + (ira_add_allocno_copy_to_list): Make static. Rename to + add_allocno_copy_to_list. + (ira_swap_allocno_copy_ends_if_necessary): Make static. Rename to + swap_allocno_copy_ends_if_necessary. + (remove_unnecessary_allocnos, remove_low_level_allocnos): Call + ira_remove_allocno_prefs. + (ira_flattening): Ditto. + (ira_build): Call initiate_prefs, print_prefs. + (ira_destroy): Call finish_prefs. + * ira-color.c (struct update_cost_record): New. + (struct allocno_color_data): Add new member update_cost_records. + (update_cost_record_pool): New static var. + (init_update_cost_records, get_update_cost_record): New functions. + (free_update_cost_record_list, finish_update_cost_records): Ditto. + (struct update_cost_queue_elem): Add member from. + (initiate_cost_update): Call init_update_cost_records. + (finish_cost_update): Call finish_update_cost_records. + (queue_update_cost, get_next_update_cost): Add new param from. + (Update_allocno_cost, update_costs_from_allocno): New functions. + (update_costs_from_prefs): Ditto. + (update_copy_costs): Rename to update_costs_from_copies. + (restore_costs_from_copies): New function. + (update_conflict_hard_regno_costs): Don't go back. + (assign_hard_reg): Call restore_costs_from_copies. Add printing + more debug info. + (pop_allocnos): Add priniting more debug info. + (color_allocnos): Remove prefs for conflicting hard regs. + Call update_costs_from_prefs. + * ira-conflicts.c (commutative_constraint_p): Move to ira.c + (get_dup_num): Rename, modify, and move to ira.c + (process_regs_for_copy): Add prefs. + (add_insn_allocno_copies): Put src as first arg of + process_regs_for_copy. Remove dead code. Call ira_setup_alts. + * ira-costs.c (record_reg_classes): Modify and move code into + record_operands_costs. + (find_costs_and_classes): Create prefs for the hard reg of small + reg class. + (process_bb_node_for_hard_reg_moves): Add prefs. + +2013-10-30 Richard Biener <rguenther@suse.de> + + PR middle-end/57100 + * basic-block.h (pre_and_rev_post_order_compute_fn): New function. + * cfganal.c (pre_and_rev_post_order_compute_fn): New function + as worker for ... + (pre_and_rev_post_order_compute): ... which now wraps it. + * graph.c (draw_cfg_nodes_no_loops): Use + pre_and_rev_post_order_compute_fn to avoid ICEing and dependence + on cfun. + +2013-10-30 Christian Bruel <christian.bruel@st.com> + + * gcc/config/sh/sh-mem.cc (sh_expand_cmpnstr): New function. + (sh_expand_cmpstr): Handle known align and schedule improvements. + * gcc/config/sh/sh-protos.h (sh_expand_cmpstrn): Declare. + * gcc/config/sh/sh.md (cmpstrnsi): New pattern. + +2013-10-30 Martin Jambor <mjambor@suse.cz> + + PR rtl-optimization/10474 + * ira.c (find_moveable_pseudos): Do not calculate dominance info + nor df analysis. + (interesting_dest_for_shprep): New function. + (split_live_ranges_for_shrink_wrap): Likewise. + (ira): Calculate dominance info and df analysis. Call + split_live_ranges_for_shrink_wrap. + +2013-10-30 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com> + + PR target/58854 + * config/arm/arm.c (arm_expand_epilogue_apcs_frame): Emit blockage. + +2013-10-30 Ilya Enkovich <ilya.enkovich@intel.com> + + * tree-core.h (tree_index): Add TI_POINTER_BOUNDS_TYPE. + * tree.h (POINTER_BOUNDS_P): New. + (BOUNDED_TYPE_P): New. + (BOUNDED_P): New. + (pointer_bounds_type_node): New. + * tree.c (build_common_tree_nodes): Initialize + pointer_bounds_type_node. + * gimple.h (gimple_call_get_nobnd_arg_index): New. + (gimple_call_num_nobnd_args): New. + (gimple_call_nobnd_arg): New. + (gimple_return_retbnd): New. + (gimple_return_set_retbnd): New + * gimple.c (gimple_build_return): Increase number of ops + for return statement. + (gimple_call_get_nobnd_arg_index): New. + * gimple-pretty-print.c (dump_gimple_return): Print second op. + +2013-10-30 Ilya Enkovich <ilya.enkovich@intel.com> + + * ipa.c (cgraph_build_static_cdtor_1): Support contructors + with "chkp ctor" and "bnd_legacy" attributes. + * gimplify.c (gimplify_init_constructor): Avoid infinite + loop during gimplification of bounds initializer. + +2013-10-30 Ilya Enkovich <ilya.enkovich@intel.com> + + * c-family/c-common.c (handle_bnd_variable_size_attribute): New. + (handle_bnd_legacy): New. + (c_common_attribute_table): Add bnd_variable_size and bnd_legacy. + * doc/extend.texi: Document bnd_variable_size and bnd_legacy + attributes. + +2013-10-29 Ilya Enkovich <ilya.enkovich@intel.com> + + * builtin-types.def (BT_FN_VOID_CONST_PTR): New. + (BT_FN_PTR_CONST_PTR): New. + (BT_FN_CONST_PTR_CONST_PTR): New. + (BT_FN_PTR_CONST_PTR_SIZE): New. + (BT_FN_PTR_CONST_PTR_CONST_PTR): New. + (BT_FN_VOID_PTRPTR_CONST_PTR): New. + (BT_FN_VOID_CONST_PTR_SIZE): New. + (BT_FN_PTR_CONST_PTR_CONST_PTR_SIZE): New. + * chkp-builtins.def: New. + * builtins.def: include chkp-builtins.def. + (DEF_CHKP_BUILTIN): New. + * builtins.c (expand_builtin): Support BUILT_IN_CHKP_INIT_PTR_BOUNDS, + BUILT_IN_CHKP_NULL_PTR_BOUNDS, BUILT_IN_CHKP_COPY_PTR_BOUNDS, + BUILT_IN_CHKP_CHECK_PTR_LBOUNDS, BUILT_IN_CHKP_CHECK_PTR_UBOUNDS, + BUILT_IN_CHKP_CHECK_PTR_BOUNDS, BUILT_IN_CHKP_SET_PTR_BOUNDS, + BUILT_IN_CHKP_NARROW_PTR_BOUNDS, BUILT_IN_CHKP_STORE_PTR_BOUNDS, + BUILT_IN_CHKP_GET_PTR_LBOUND, BUILT_IN_CHKP_GET_PTR_UBOUND, + BUILT_IN_CHKP_BNDMK, BUILT_IN_CHKP_BNDSTX, BUILT_IN_CHKP_BNDCL, + BUILT_IN_CHKP_BNDCU, BUILT_IN_CHKP_BNDLDX, BUILT_IN_CHKP_BNDRET, + BUILT_IN_CHKP_INTERSECT, BUILT_IN_CHKP_ARG_BND, BUILT_IN_CHKP_NARROW, + BUILT_IN_CHKP_EXTRACT_LOWER, BUILT_IN_CHKP_EXTRACT_UPPER. + * common.opt (fcheck-pointer-bounds): New. + * toplev.c (process_options): Check Pointer Bounds Checker is + supported. + * doc/extend.texi: Document Pointer Bounds Checker built-in functions. + +2013-10-30 Ilya Enkovich <ilya.enkovich@intel.com> + + * target.def (builtin_chkp_function): New. + (chkp_bound_type): New. + (chkp_bound_mode): New. + (fn_abi_va_list_bounds_size): New. + (load_bounds_for_arg): New. + (store_bounds_for_arg): New. + * targhooks.h (default_load_bounds_for_arg): New. + (default_store_bounds_for_arg): New. + (default_fn_abi_va_list_bounds_size): New. + (default_chkp_bound_type): New. + (default_chkp_bound_mode): New. + (default_builtin_chkp_function): New. + * targhooks.c (default_load_bounds_for_arg): New. + (default_store_bounds_for_arg): New. + (default_fn_abi_va_list_bounds_size): New. + (default_chkp_bound_type): New. + (default_chkp_bound_mode); New. + (default_builtin_chkp_function): New. + * doc/tm.texi.in (TARGET_FN_ABI_VA_LIST_BOUNDS_SIZE): New. + (TARGET_LOAD_BOUNDS_FOR_ARG): New. + (TARGET_STORE_BOUNDS_FOR_ARG): New. + (TARGET_BUILTIN_CHKP_FUNCTION): New. + (TARGET_CHKP_BOUND_TYPE): New. + (TARGET_CHKP_BOUND_MODE): New. + * doc/tm.texi: Regenerated. + * langhooks.h (lang_hooks): Add chkp_supported field. + * langhooks-def.h (LANG_HOOKS_CHKP_SUPPORTED): New. + (LANG_HOOKS_INITIALIZER); Add LANG_HOOKS_CHKP_SUPPORTED. + +2013-10-29 Andrew Pinski <apinski@cavium.com> + + * tree-ssa-ifcombine.c: Include rtl.h and tm_p.h. + (ifcombine_ifandif): Handle cases where maybe_fold_and_comparisons + fails, combining the branches anyways. + (tree_ssa_ifcombine): Inverse the order of the basic block walk, + increases the number of combinings. + * gimple.h (gsi_start_nondebug_after_labels_bb): New function. + +2013-10-29 Mike Stump <mikestump@comcast.net> + + * machmode.def (PARTIAL_INT_MODE): Add precision and name. + * genmodes.c (PARTIAL_INT_MODE): Add precision and name. + (make_vector_mode): Increase namebuf to 16. + (emit_insn_modes_h): When processing BImode, don't + also match partial int modes. + (emit_class_narrowest_mode): Likewise. + + * config/bfin/bfin-modes.def: Add precision to PDI. + * config/m32c/m32c-modes.def: Add precision to PSI. + * config/msp430/msp430-modes.def: Add precision to PSI. + * config/rs6000/rs6000-modes.def: Add precision to PTI. + * config/sh/sh-modes.def: Add precision to PSI and PDI. + +2013-10-29 Oleg Endo <olegendo@gcc.gnu.org> + + PR target/54236 + * config/sh/sh.md (*addc): Rename existing variations to ... + (*addc_r_r_1, *addc_2r_1, *addc_r_1): ... these. + (*addc_r_lsb, *addc_r_r_lsb, *addc_r_lsb_r, *addc_2r_lsb, *addc_r_msb, + *addc_r_r_msb, *addc_2r_msb): New insn_and_split patterns. + * config/sh/sh.c (addsubcosts): Handle some addc special cases. + +2013-10-29 Teresa Johnson <tejohnson@google.com> + + PR ipa/58862 + * tree-ssa-tail-merge.c (replace_block_by): Tolerate profile + insanities when updating probabilities. + +2013-10-29 David Malcolm <dmalcolm@redhat.com> + + * gdbhooks.py (CGraphNodePrinter.to_string): Update gdb + prettyprinter for cgraph_node to reflect the conversion of the + symtable types to a C++ class hierarchy: it now *is* a + symtab_node_base, rather than having one (named "symbol"). + +2013-10-29 Balaji V. Iyer <balaji.v.iyer@intel.com> + + * builtins.c (is_builtin_name): Added a check for __cilkrts_detach and + __cilkrts_pop_frame. If matched, then return true for built-in + function name. + (expand_builtin): Added BUILT_IN_CILK_DETACH and + BUILT_IN_CILK_POP_FRAME case. + * langhooks-def.h (lhd_install_body_with_frame_cleanup): New prototype. + (lhs_cilk_detect_spawn): Likewise. + (LANG_HOOKS_DECLS): Added LANG_HOOKS_CILKPLUS. + (LANG_HOOKS_CILKPLUS_DETECT_SPAWN_AND_UNWRAP): New #define. + (LANG_HOOKS_CILKPLUS_FRAME_CLEANUP): Likewise. + (LANG_HOOKS_CILKPLUS_GIMPLIFY_SPAWN): Likewise. + (LANG_HOOKS_CILKPLUS): Likewise. + * tree.h (CILK_SPAWN_FN): Likewise. + * builtin.def (DEF_CILK_BUILTIN_STUB): Likewise. + * Makefile.in (C_COMMON_OBJS): Added c-family/cilk.o. + (OBJS): Added cilk-common.o. + (BUILTINS_DEF): Added cilk-builtins.def. + * langhooks.c (lhd_install_body_with_frame_cleanup): New function. + (lhd_cilk_detect_spawn): Likewise. + * langhooks.h (lang_hooks_for_cilkplus): New struct. + (struct lang_hooks): Added new field called "cilkplus." + * cilk-common.c: New file. + * cilk.h: Likewise. + * cilk-builtins.def: Likewise. + * cppbuiltin.c (define_builtin_macros_for_compilation_flags): Added + "__cilk" macro and set it to 200. + * function.h (struct function::cilk_frame_decl): New field. + (struct function::is_cilk_function): Likewise. + (struct function::calls_cilk_spawn): Likewise. + * gimplify.c (gimplify_call_expr): Added a check if the function call + being gimplified is a spawn detach point. If so, then add pop_frame + and detach function calls. + (gimplify_expr): Added a CILK_SPAWN_STMT and CILK_SYNC_STMT case + for gimplifying _Cilk_spawn and _Cilk_sync statements. + (gimplify_return_expr): Added a check for _Cilk_spawn usage in + function. If so, added a _Cilk_sync and gimplified it. + (gimplify_modify_expr): Added a check for _Cilk_spawn in MODIFY and + INIT_EXPRs. If so, then call gimplify_cilk_spawn. + * ipa-inline-analysis (initialize_inline_failed): Prevent inlining of + spawner function. + (can_inline_edge_p): Prevent inling of spawnee function. + * ira.c (ira_setup_eliminable_regset): Force usage of frame pointer + for functions that use Cilk keywords. + * tree-inline.h (struct copy_body_data::remap_var_for_cilk): New field. + * tree-pretty-print.c (dump_generic_node): Added CILK_SPAWN_STMT and + CILK_SYNC_STMT cases. + * tree.def (DEFTREECODE): Added CILK_SPAWN_STMT and CILK_SYNC_STMT + trees. + * generic.texi (CILK_SPAWN_STMT): Added documentation for _Cilk_spawn. + (CILK_SYNC_STMT): Added documentation for _Cilk_sync. + * passes.texi (Cilk Keywords): New section that describes the compiler + code changes for handling Cilk Keywords. + +2013-10-29 David Malcolm <dmalcolm@redhat.com> + + Patch autogenerated by refactor_symtab.py from + https://github.com/davidmalcolm/gcc-refactoring-scripts + revision 58bb219cc090b2f4516a9297d868c245495ee622 + + * asan.c (asan_finish_file): Update for conversion of symtab types to + a true class hierarchy. + * cfgexpand.c (estimated_stack_frame_size): Likewise. + * cgraph.c (cgraph_get_body): Likewise. + (cgraph_get_create_real_symbol_node): Likewise. + (verify_cgraph_node): Likewise. + (verify_edge_corresponds_to_fndecl): Likewise. + (verify_edge_count_and_frequency): Likewise. + (cgraph_will_be_removed_from_program_if_no_direct_calls): Likewise. + (cgraph_can_remove_if_no_direct_calls_p): Likewise. + (cgraph_can_remove_if_no_direct_calls_and_refs_p): Likewise. + (cgraph_node_cannot_return): Likewise. + (cgraph_set_pure_flag_1): Likewise. + (cgraph_set_const_flag_1): Likewise. + (cgraph_set_nothrow_flag_1): Likewise. + (cgraph_make_node_local_1): Likewise. + (cgraph_for_node_and_aliases): Likewise. + (cgraph_for_node_thunks_and_aliases): Likewise. + (cgraph_node_can_be_local_p): Likewise. + (cgraph_node_cannot_be_local_p_1): Likewise. + (cgraph_function_body_availability): Likewise. + (dump_cgraph_node): Likewise. + (cgraph_rtl_info): Likewise. + (cgraph_mark_address_taken_node): Likewise. + (cgraph_remove_node): Likewise. + (cgraph_release_function_body): Likewise. + (cgraph_update_edges_for_call_stmt_node): Likewise. + (cgraph_redirect_edge_call_stmt_to_callee): Likewise. + (cgraph_make_edge_direct): Likewise. + (cgraph_resolve_speculation): Likewise. + (cgraph_speculative_call_info): Likewise. + (cgraph_turn_edge_to_speculative): Likewise. + (cgraph_create_edge_1): Likewise. + (cgraph_set_call_stmt): Likewise. + (cgraph_node_for_asm): Likewise. + (cgraph_add_thunk): Likewise. + (cgraph_same_body_alias): Likewise. + (cgraph_create_function_alias): Likewise. + (cgraph_create_node): Likewise. + (cgraph_create_empty_node): Likewise. + (record_function_versions): Likewise. + (used_from_object_file_p): Likewise. + * cgraph.h (symtab_can_be_discarded): Likewise. + (symtab_real_symbol_p): Likewise. + (cgraph_mark_force_output_node): Likewise. + (cgraph_edge_recursive_p): Likewise. + (symtab_alias_target): Likewise. + (varpool_all_refs_explicit_p): Likewise. + (varpool_can_remove_if_no_refs): Likewise. + (cgraph_only_called_directly_or_aliased_p): Likewise. + (cgraph_next_function_with_gimple_body): Likewise. + (cgraph_first_function_with_gimple_body): Likewise. + (cgraph_function_with_gimple_body_p): Likewise. + (cgraph_next_function): Likewise. + (cgraph_first_function): Likewise. + (cgraph_next_defined_function): Likewise. + (cgraph_first_defined_function): Likewise. + (varpool_next_defined_variable): Likewise. + (varpool_first_defined_variable): Likewise. + (varpool_next_static_initializer): Likewise. + (varpool_first_static_initializer): Likewise. + (varpool_next_variable): Likewise. + (varpool_first_variable): Likewise. + (varpool_node_name): Likewise. + (varpool): Likewise. + (cgraph): Likewise. + (is_a_helper <varpool_node>::test): Likewise. + (is_a_helper <cgraph_node>::test): Likewise. + (varpool_variable_node): Likewise. + (cgraph_function_or_thunk_node): Likewise. + (varpool_alias_target): Likewise. + (cgraph_alias_target): Likewise. + (cgraph_node_name): Likewise. + (varpool_node_asm_name): Likewise. + (cgraph_node_asm_name): Likewise. + * cgraphbuild.c (remove_cgraph_callee_edges): Likewise. + (cgraph_rebuild_references): Likewise. + (rebuild_cgraph_edges): Likewise. + (record_eh_tables): Likewise. + (build_cgraph_edges): Likewise. + (mark_store): Likewise. + (mark_load): Likewise. + (mark_address): Likewise. + (record_type_list): Likewise. + (record_reference): Likewise. + * cgraphclones.c (cgraph_materialize_all_clones): Likewise. + (cgraph_materialize_clone): Likewise. + (cgraph_function_versioning): Likewise. + (cgraph_copy_node_for_versioning): Likewise. + (update_call_expr): Likewise. + (cgraph_find_replacement_node): Likewise. + (cgraph_create_virtual_clone): Likewise. + (cgraph_clone_node): Likewise. + * cgraphunit.c (compile): Likewise. + (output_weakrefs): Likewise. + (output_in_order): Likewise. + (expand_function): Likewise. + (assemble_thunks_and_aliases): Likewise. + (expand_thunk): Likewise. + (mark_functions_to_output): Likewise. + (handle_alias_pairs): Likewise. + (analyze_functions): Likewise. + (walk_polymorphic_call_targets): Likewise. + (varpool_finalize_decl): Likewise. + (process_function_and_variable_attributes): Likewise. + (cgraph_process_same_body_aliases): Likewise. + (analyze_function): Likewise. + (cgraph_add_new_function): Likewise. + (cgraph_finalize_function): Likewise. + (referred_to_p): Likewise. + (cgraph_reset_node): Likewise. + (cgraph_process_new_functions): Likewise. + (enqueue_node): Likewise. + (decide_is_symbol_needed): Likewise. + * coverage.c (coverage_compute_profile_id): Likewise. + * dbxout.c (dbxout_expand_expr): Likewise. + * dwarf2out.c (premark_types_used_by_global_vars_helper): Likewise. + (reference_to_unused): Likewise. + * gimple-fold.c (can_refer_decl_in_current_unit_p): Likewise. + * gimplify.c (unvisit_body): Likewise. + (unshare_body): Likewise. + * ipa-cp.c (ipcp_generate_summary): Likewise. + (ipcp_decision_stage): Likewise. + (identify_dead_nodes): Likewise. + (decide_whether_version_node): Likewise. + (decide_about_value): Likewise. + (perhaps_add_new_callers): Likewise. + (create_specialized_node): Likewise. + (update_profiling_info): Likewise. + (ipcp_propagate_stage): Likewise. + (estimate_local_effects): Likewise. + (good_cloning_opportunity_p): Likewise. + (devirtualization_time_bonus): Likewise. + (propagate_constants_accross_call): Likewise. + (initialize_node_lattices): Likewise. + (ipcp_cloning_candidate_p): Likewise. + (determine_versionability): Likewise. + (print_all_lattices): Likewise. + (print_lattice): Likewise. + (ipcp_discover_new_direct_edges): Likewise. + * ipa-devirt.c (ipa_devirt): Likewise. + (likely_target_p): Likewise. + (update_type_inheritance_graph): Likewise. + (possible_polymorphic_call_target_p): Likewise. + (dump_possible_polymorphic_call_targets): Likewise. + (devirt_variable_node_removal_hook): Likewise. + (record_binfo): Likewise. + (maybe_record_node): Likewise. + (build_type_inheritance_graph): Likewise. + * ipa-inline-analysis.c (inline_write_summary): Likewise. + (inline_generate_summary): Likewise. + (inline_analyze_function): Likewise. + (do_estimate_growth): Likewise. + (simple_edge_hints): Likewise. + (estimate_node_size_and_time): Likewise. + (estimate_edge_devirt_benefit): Likewise. + (compute_inline_parameters): Likewise. + (estimate_function_body_sizes): Likewise. + (compute_bb_predicates): Likewise. + (initialize_inline_failed): Likewise. + (dump_inline_summary): Likewise. + (dump_inline_edge_summary): Likewise. + * ipa-inline-transform.c (inline_transform): Likewise. + (preserve_function_body_p): Likewise. + (save_inline_function_body): Likewise. + (inline_call): Likewise. + (clone_inlined_nodes): Likewise. + (can_remove_node_now_p): Likewise. + (can_remove_node_now_p_1): Likewise. + * ipa-inline.c (early_inliner): Likewise. + (early_inline_small_functions): Likewise. + (inline_always_inline_functions): Likewise. + (ipa_inline): Likewise. + (flatten_function): Likewise. + (inline_small_functions): Likewise. + (speculation_useful_p): Likewise. + (recursive_inlining): Likewise. + (update_caller_keys): Likewise. + (reset_edge_caches): Likewise. + (update_edge_key): Likewise. + (edge_badness): Likewise. + (relative_time_benefit): Likewise. + (want_inline_self_recursive_call_p): Likewise. + (want_inline_small_function_p): Likewise. + (want_early_inline_function_p): Likewise. + (num_calls): Likewise. + (can_early_inline_edge_p): Likewise. + (can_inline_edge_p): Likewise. + (report_inline_failed_reason): Likewise. + * ipa-profile.c (ipa_profile): Likewise. + (ipa_propagate_frequency): Likewise. + (ipa_propagate_frequency_1): Likewise. + (ipa_profile_generate_summary): Likewise. + * ipa-prop.c (ipcp_transform_function): Likewise. + (read_replacements_section): Likewise. + (ipa_prop_read_section): Likewise. + (ipa_modify_call_arguments): Likewise. + (ipa_print_node_params): Likewise. + (propagate_controlled_uses): Likewise. + (update_indirect_edges_after_inlining): Likewise. + (remove_described_reference): Likewise. + (ipa_make_edge_direct_to_target): Likewise. + (ipa_analyze_node): Likewise. + (ipa_analyze_params_uses): Likewise. + (ipa_compute_jump_functions): Likewise. + (ipa_get_callee_param_type): Likewise. + (ipa_print_node_jump_functions): Likewise. + (ipa_initialize_node_params): Likewise. + (ipa_populate_param_decls): Likewise. + (ipa_func_spec_opts_forbid_analysis_p): Likewise. + (write_agg_replacement_chain): Likewise. + (ipa_write_node_info): Likewise. + (ipa_edge_duplication_hook): Likewise. + (try_decrement_rdesc_refcount): Likewise. + * ipa-pure-const.c (propagate_nothrow): Likewise. + (propagate_pure_const): Likewise. + (pure_const_read_summary): Likewise. + (pure_const_write_summary): Likewise. + (analyze_function): Likewise. + * ipa-ref-inline.h (ipa_ref_referred_ref_list): Likewise. + (ipa_ref_referring_ref_list): Likewise. + * ipa-ref.c (ipa_clear_stmts_in_references): Likewise. + (ipa_remove_stmt_references): Likewise. + (ipa_find_reference): Likewise. + (ipa_dump_referring): Likewise. + (ipa_dump_references): Likewise. + (ipa_record_reference): Likewise. + * ipa-reference.c (ipa_reference_read_optimization_summary): Likewise. + (ipa_reference_write_optimization_summary): Likewise. + (write_node_summary_p): Likewise. + (propagate): Likewise. + (read_write_all_from_decl): Likewise. + (generate_summary): Likewise. + (analyze_function): Likewise. + (propagate_bits): Likewise. + (ipa_reference_get_not_written_global): Likewise. + (ipa_reference_get_not_read_global): Likewise. + * ipa-split.c (execute_split_functions): Likewise. + (split_function): Likewise. + * ipa-utils.c (ipa_merge_profiles): Likewise. + (dump_cgraph_node_set): Likewise. + (ipa_reverse_postorder): Likewise. + (ipa_edge_within_scc): Likewise. + (ipa_get_nodes_in_cycle): Likewise. + (ipa_free_postorder_info): Likewise. + (ipa_reduced_postorder): Likewise. + (searchc): Likewise. + (recursive_call_p): Likewise. + * ipa.c (ipa_cdtor_merge): Likewise. + (record_cdtor_fn): Likewise. + (function_and_variable_visibility): Likewise. + (varpool_externally_visible_p): Likewise. + (cgraph_externally_visible_p): Likewise. + (comdat_can_be_unshared_p): Likewise. + (comdat_can_be_unshared_p_1): Likewise. + (address_taken_from_non_vtable_p): Likewise. + (ipa_discover_readonly_nonaddressable_vars): Likewise. + (symtab_remove_unreachable_nodes): Likewise. + (walk_polymorphic_call_targets): Likewise. + (process_references): Likewise. + (enqueue_node): Likewise. + (has_addr_references_p): Likewise. + (cgraph_non_local_node_p_1): Likewise. + * is-a.h (varpool_analyze_node): Likewise. + * lto-cgraph.c (input_symtab): Likewise. + (merge_profile_summaries): Likewise. + (input_cgraph_1): Likewise. + (input_edge): Likewise. + (input_varpool_node): Likewise. + (input_node): Likewise. + (input_overwrite_node): Likewise. + (compute_ltrans_boundary): Likewise. + (output_refs): Likewise. + (lto_output_varpool_node): Likewise. + (lto_output_node): Likewise. + (reachable_from_other_partition_p): Likewise. + (referenced_from_other_partition_p): Likewise. + (lto_output_edge): Likewise. + (output_node_opt_summary): Likewise. + (add_node_to): Likewise. + (reachable_from_this_partition_p): Likewise. + (lto_set_symtab_encoder_in_partition): Likewise. + (lto_symtab_encoder_in_partition_p): Likewise. + (lto_set_symtab_encoder_encode_initializer): Likewise. + (lto_symtab_encoder_encode_initializer_p): Likewise. + (lto_set_symtab_encoder_encode_body): Likewise. + (lto_symtab_encoder_encode_body_p): Likewise. + * lto-section-in.c (lto_free_function_in_decl_state_for_node): + Likewise. + * lto-streamer-in.c (lto_read_body): Likewise. + (fixup_call_stmt_edges): Likewise. + (fixup_call_stmt_edges_1): Likewise. + * lto-streamer-out.c (produce_symtab): Likewise. + (output_symbol_p): Likewise. + (write_symbol): Likewise. + (lto_output): Likewise. + (copy_function): Likewise. + (output_function): Likewise. + * passes.c (function_called_by_processed_nodes_p): Likewise. + (ipa_write_optimization_summaries): Likewise. + (ipa_write_summaries): Likewise. + (do_per_function_toporder): Likewise. + (do_per_function): Likewise. + (dump_passes): Likewise. + * symtab.c (symtab_semantically_equivalent_p): Likewise. + (symtab_nonoverwritable_alias): Likewise. + (symtab_nonoverwritable_alias_1): Likewise. + (symtab_for_node_and_aliases): Likewise. + (symtab_resolve_alias): Likewise. + (fixup_same_cpp_alias_visibility): Likewise. + (symtab_alias_ultimate_target): Likewise. + (symtab_used_from_object_file_p): Likewise. + (verify_symtab_base): Likewise. + (dump_symtab_base): Likewise. + (symtab_node_name): Likewise. + (symtab_node_asm_name): Likewise. + (symtab_dissolve_same_comdat_group_list): Likewise. + (symtab_add_to_same_comdat_group): Likewise. + (symtab_unregister_node): Likewise. + (symtab_insert_node_to_hashtable): Likewise. + (symtab_register_node): Likewise. + (unlink_from_assembler_name_hash): Likewise. + (insert_to_assembler_name_hash): Likewise. + (eq_assembler_name): Likewise. + (hash_node_by_assembler_name): Likewise. + (eq_node): Likewise. + (hash_node): Likewise. + * toplev.c (wrapup_global_declaration_2): Likewise. + * trans-mem.c (ipa_tm_execute): Likewise. + (ipa_tm_transform_clone): Likewise. + (ipa_tm_transform_transaction): Likewise. + (ipa_tm_transform_calls_redirect): Likewise. + (ipa_tm_insert_gettmclone_call): Likewise. + (ipa_tm_insert_irr_call): Likewise. + (ipa_tm_create_version): Likewise. + (ipa_tm_create_version_alias): Likewise. + (ipa_tm_mark_forced_by_abi_node): Likewise. + (ipa_tm_mark_force_output_node): Likewise. + (ipa_tm_diagnose_tm_safe): Likewise. + (ipa_tm_mayenterirr_function): Likewise. + (ipa_tm_scan_irr_function): Likewise. + (ipa_tm_note_irrevocable): Likewise. + (ipa_tm_scan_calls_clone): Likewise. + (get_cg_data): Likewise. + * tree-eh.c (tree_could_trap_p): Likewise. + * tree-emutls.c (ipa_lower_emutls): Likewise. + (create_emultls_var): Likewise. + (lower_emutls_function_body): Likewise. + (gen_emutls_addr): Likewise. + (emutls_decl): Likewise. + (new_emutls_decl): Likewise. + * tree-inline.c (tree_function_versioning): Likewise. + (optimize_inline_calls): Likewise. + (expand_call_inline): Likewise. + (estimate_num_insns): Likewise. + (copy_bb): Likewise. + (delete_unreachable_blocks_update_callgraph): Likewise. + * tree-nested.c (gimplify_all_functions): Likewise. + (create_nesting_tree): Likewise. + (check_for_nested_with_variably_modified): Likewise. + * tree-pretty-print.c (dump_function_header): Likewise. + * tree-profile.c (tree_profiling): Likewise. + * tree-sra.c (ipa_sra_preliminary_function_checks): Likewise. + (modify_function): Likewise. + (convert_callers): Likewise. + (convert_callers_for_node): Likewise. + * tree-ssa-structalias.c (ipa_pta_execute): Likewise. + (associate_varinfo_to_alias): Likewise. + (create_variable_info_for): Likewise. + (get_constraint_for_ssa_var): Likewise. + * tree-vectorizer.c (increase_alignment): Likewise. + * tree.c (find_decls_types_in_var): Likewise. + (find_decls_types_in_node): Likewise. + (free_lang_data_in_decl): Likewise. + * value-prof.c (gimple_ic_transform): Likewise. + (gimple_ic): Likewise. + (check_ic_target): Likewise. + (init_node_map): Likewise. + * varasm.c (decl_binds_to_current_def_p): Likewise. + (default_binds_local_p_1): Likewise. + (dump_tm_clone_pairs): Likewise. + (assemble_alias): Likewise. + (find_decl): Likewise. + (mark_decl_referenced): Likewise. + * varpool.c (varpool_for_node_and_aliases): Likewise. + (varpool_extra_name_alias): Likewise. + (varpool_create_variable_alias): Likewise. + (add_new_static_var): Likewise. + (varpool_finalize_named_section_flags): Likewise. + (varpool_remove_unreferenced_decls): Likewise. + (enqueue_node): Likewise. + (varpool_assemble_decl): Likewise. + (assemble_aliases): Likewise. + (varpool_analyze_node): Likewise. + (cgraph_variable_initializer_availability): Likewise. + (varpool_add_new_variable): Likewise. + (ctor_for_folding): Likewise. + (dump_varpool_node): Likewise. + (varpool_remove_initializer): Likewise. + (varpool_remove_node): Likewise. + (varpool_node_for_decl): Likewise. + (varpool_create_empty_node): Likewise. + * config/i386/i386.c (ix86_generate_version_dispatcher_body): Likewise. + (ix86_get_function_versions_dispatcher): Likewise. + +2013-10-29 David Malcolm <dmalcolm@redhat.com> + + * cgraph.h (symtab_node_base): Convert to a class; + add GTY((desc ("%h.type"), tag ("SYMTAB_SYMBOL"))), and take + chain_next/prev from symtab_node_def. + (cgraph_node): Inherit from symtab_node; add GTY option + tag ("SYMTAB_FUNCTION"). + (varpool_node): Inherit from symtab_node; add GTY option + tag ("SYMTAB_VARIABLE"). + (symtab_node_def): Remove. + (is_a_helper <cgraph_node>::test (symtab_node_def *)): Convert to... + (is_a_helper <cgraph_node>::test (symtab_node_base *)): ...this. + (is_a_helper <varpool_node>::test (symtab_node_def *)): Convert to... + (is_a_helper <varpool_node>::test (symtab_node_base *)): ...this. + + * ipa-ref.h (symtab_node_def): Drop. + (symtab_node): Change underlying type from symtab_node_def to + symtab_node_base. + (const_symtab_node): Likwise. + + * is-a.h: Update examples in comment. + + * symtab.c (symtab_hash): Change symtab_node_def to symtab_node_base. + (assembler_name_hash): Likewise. + +2013-10-29 Martin Liska <marxin.liska@gmail.com> + + * doc/tree-ssa.texi (gimple_phi_result): Document. + (gimple_phi_num_args, gimple_phi_arg): Likewise. + (gimple_phi_arg_edge, gimple_phi_arg_def): Likewise. + (PHI_RESULT, PHI_NUM_ARGS): Remove. + (PHI_ARG_ELT, PHI_ARG_EDGE, PHI_ARG_DEF): Likewise. + +2013-10-29 Andrew MacLeod <amacleod@redhat.com> + + * expr.h: Revert change and include tree-core.h. + * rtl.h: Revert change and don't include tree-core.h. + +2013-10-29 Andrew MacLeod <amacleod@redhat.com> + + * config/darwin.c: Include gimple.h. + * config/i386/winnt.c: Likewise. + +2013-10-29 Marc Glisse <marc.glisse@inria.fr> + + PR tree-optimization/19831 + * tree-ssa-alias.c (stmt_kills_ref_p_1): Handle BUILT_IN_FREE. + +2013-10-29 Andrew MacLeod <amacleod@redhat.com> + + * tree-outof-ssa.h: Remove include files. + * tree-outof-ssa.c: Add required include files from tree-outof-ssa.h. + * expr.c: Likewise. + * tree-ssa-coalesce.c: Likewise. + * cfgexpand.c: Likewise. + * tree-ssa-ter.c: Likewise. + * ipa-prop.h: Remove gimple.h and tree-core.h from include list. + * lto-streamer.h: Likewise. + * cgraphbuild.c: Add gimple.h to include list. + * data-streamer-in.c: Likewise. + * ipa-cp.c: Likewise. + * tree-streamer.c: Likewise. + * lto-compress.c: Likewise. + * ipa-reference.c: Likewise. + * data-streamer-out.c: Likewise. + * lto-cgraph.c: Likewise. + * cgraphclones.c: Likewise. + * ipa-utils.c: Likewise. + * data-streamer.c: Likewise. + * ipa-split.c: Likewise. + * lto-section-in.c: Likewise. + * tree-streamer-out.c: Likewise. + * ipa-prop.c: Likewise. + * tree-streamer-in.c: Likewise. + * symtab.c: Likewise. + * opts-global.c: Likewise. + * lto-opts.c: Likewise. + * lto-section-out.c: Likewise. + * lto-streamer.c: Likewise. + * rtl.h: Add tree-core.h to include list. + * expr.h: Remove tree-core.h from include list. + * gimple.h: Likewise. + * ipa-utils.h: Likewise. + * streamer-hooks.h: Likewise. + * streamer-hooks.c: Include input.h. + +2013-10-29 Kyrylo Tkachov <kyrylo.tkachov@arm.com> + + * config/arm/arm.c (cortexa7_extra_costs): New table. + (arm_cortex_a7_tune): New. + * config/arm/arm-cores.def: Use cortex_a7 tuning for cortex-a7. + +2013-10-29 Eric Botcazou <ebotcazou@adacore.com> + + * expr.c (expand_expr_real_1) <MEM_EXPR>: Eliminate small redundancy. + +2013-10-29 David Malcolm <dmalcolm@redhat.com> + + * doc/gty.texi ("Inheritance and GTY"): Make it clear that + to use autogenerated markers for a class-hierarchy, every class + must have a GTY marker. + * gengtype.h (struct type): Add linked list of subclasses to + the "s" member of the union. + (add_subclass): New decl. + * gengtype-state.c (read_state_struct_type): Set up subclass + linked list. + * gengtype.c (get_ultimate_base_class): New. + (add_subclass): New. + (new_structure): Set up subclass linked list. + (set_gc_used_type): Propagate usage information to subclasses. + (output_mangled_typename): Use get_ultimate_base_class. + (walk_subclasses): Use the subclass linked list, avoiding an + O(N^2) when writing out all types. + (walk_type): Issue an error if the base class is missing a tag, + rather than generating bogus C code. Add a gcc_unreachable + default case, in case people omit tags from concrete subclasses, + or get the values wrong. + (write_func_for_structure): Issue an error for subclasses for + which the base doesn't have a "desc", since otherwise the + autogenerated routines for the base would silently fail to visit + any subclass fields. + (write_root): Use get_ultimate_base_class, tweaking constness of + tp to match that function's signature. + +2013-10-29 David Malcolm <dmalcolm@redhat.com> + + * doc/gty.texi (GTY Options): Add note about inheritance to + description of desc and tag. + (Inheritance and GTY): New. + +2013-10-29 David Malcolm <dmalcolm@redhat.com> + + * gengtype-parse.c (opts_have): Drop "static" so that + we can use this from gengtype.c. + * gengtype.c (set_gc_used_type): Mark any base class as used; + update field traversal to visit inherited fields. + (output_mangled_typename): Convert references to classes within + an inheritance hierarchy to reference the ultimate base class, + since only it will have gt_ functions. + (get_string_option): New. + (walk_subclasses): New. + (walk_type): Treat GTY structs that have a "desc" as being the + root of an inheritance hierarchy. Generate a switch on it + within the marking function which walks all subclasses, adding + cases for them via walk_subclasses. For subclasses, visit all + fields of the type (including inherited ones). + (write_func_for_structure): Don't write fns for subclasses, only + for the ultimate base class within an inheritance hierarchy. + Subclasses-marking will be handled by the base class marking functions. + (write_types): Likewise. + (write_local_func_for_structure): Likewise. + (USED_BY_TYPED_GC_P): Emit allocators for subclasses that have + a "tag" option (and are thus concrete subclasses). + (write_root): Use the marker function for the ultimate base class. + * gengtype.h (FOR_ALL_INHERITED_FIELDS): New. + (opts_have): Add declaration. + +2013-10-28 Vladimir Makarov <vmakarov@redhat.com> + + * lra-spills.c (lra_final_code_change): Remove useless move insns + originated from moves of pseudos. + +2013-10-28 Jeff Law <law@redhat.com> + + * lower-subreg.c (resolve_simple_move): Fix comment typo. + +2013-10-28 Trevor Saunders <tsaunders@mozilla.com> + + * df-scan.c (df_collection_rec): Adjust. + (copy_defs): New constant. + (copy_uses): Likewise. + (copy_eq_uses): Likewise. + (copy_mw): Likewise. + (copy_all): Likewise. + (df_insn_rescan): Adjust. + (df_notes_rescan): Likewise. + (df_swap_refs): Likewise. + (df_sort_and_compress_refs): Likewise. + (df_sort_and_compress_mws): Likewise. + (df_install_refs): Likewise. + (df_install_mws): Likewise. + (df_refs_add_to_chains): Add flags parameter controlling which vectors + are coppied. + (df_bb_refs_record): Adjust. + (df_record_entry_block_defs): Likewise. + (df_record_exit_block_defs): Likewise. + (df_refs_verify): Likewise. + (df_mws_verify): Likewise. + (df_insn_refs_verify): Likewise. + (df_bb_verify): Likewise. + * ipa-pure-const.c (finish_state): Remove. + (propagate): Adjust. + * tree-data-ref.c tree-ssa-alias.c tree-ssa-loop-ivcanon.c + tree-ssa-threadedge.c tree-vect-loop-manip.c tree-vect-slp.c + var-tracking.c: Adjust. + * vec.c (stack_vecs): Remove. + (register_stack_vec): Likewise. + (stack_vec_register_index): Likewise. + (unregister_stack_vec): Likewise. + * vec.h (struct va_stack): Remove. + (struct vec<T, A, vl_ptr>): Specialize as + struct vec<T, va_heap, vl_ptr> instead since va_heap is the only + allocation strategy compatable with the vl_ptr layout. + (struct vec<T, va_gc, vl_ptr>): Remove because it now gets an empty + specialization anyway. + (class stack_vec): New class. + (vec_stack_alloc): Remove. + (vec<T, va_heap, vl_ptr>::using_auto_storage): New method. + +2013-10-28 Alexander Ivchenko <alexander.ivchenko@intel.com> + Maxim Kuznetsov <maxim.kuznetsov@intel.com> + Sergey Lega <sergey.s.lega@intel.com> + Anna Tikhonova <anna.tikhonova@intel.com> + Ilya Tocar <ilya.tocar@intel.com> + Andrey Turetskiy <andrey.turetskiy@intel.com> + Ilya Verbin <ilya.verbin@intel.com> + Kirill Yukhin <kirill.yukhin@intel.com> + Michael Zolotukhin <michael.v.zolotukhin@intel.com> + + * config/i386/i386.md (prefetch): Allow TARGET_AVX512PF. + (*prefetch_avx512pf_<mode>): New. + * config/i386/sse.md (avx512f_vmcmp<mode>3): Ditto. + (avx512f_maskcmp<mode>3): Ditto. + (vashrv16si3): Ditto. + +2013-10-28 Alexander Ivchenko <alexander.ivchenko@intel.com> + Maxim Kuznetsov <maxim.kuznetsov@intel.com> + Sergey Lega <sergey.s.lega@intel.com> + Anna Tikhonova <anna.tikhonova@intel.com> + Ilya Tocar <ilya.tocar@intel.com> + Andrey Turetskiy <andrey.turetskiy@intel.com> + Ilya Verbin <ilya.verbin@intel.com> + Kirill Yukhin <kirill.yukhin@intel.com> + Michael Zolotukhin <michael.v.zolotukhin@intel.com> + + * config/i386/i386.md (any_truncate): New. + (trunsuffix): Ditto. + * config/i386/predicates.md (const_8_to_9_operand): New. + (const_10_to_11_operand): Ditto. + (const_12_to_13_operand): Ditto. + (const_14_to_15_operand): Ditto. + (const_16_to_19_operand): Ditto. + (const_20_to_23_operand): Ditto. + (const_24_to_27_operand): Ditto. + (const_28_to_31_operand): Ditto. + * config/i386/sse.md (unspec): Add UNSPEC_UNSIGNED_FIX_NOTRUNC. + (cvtusi2<ssescalarmodesuffix>32): New. + (cvtusi2<ssescalarmodesuffix>64): Ditto. + (ufloatv16siv16sf2): Ditto. + (avx512f_fix_notruncv16sfv16si): Ditto. + (avx512f_ufix_notruncv16sfv16si): Ditto. + (avx512f_vcvtss2usi): Ditto. + (avx512f_vcvtss2usiq): Ditto. + (avx512f_vcvttss2usi): Ditto. + (avx512f_vcvttss2usiq): Ditto. + (avx512f_vcvtsd2usi): Ditto. + (avx512f_vcvtsd2usiq): Ditto. + (avx512f_vcvttsd2usi): Ditto. + (avx512f_vcvttsd2usiq): Ditto. + (ufloatv8siv8df): Ditto. + (avx512f_cvtdq2pd512_2): Ditto. + (avx512f_cvtpd2dq512): Ditto. + (avx512f_ufix_notruncv8dfv8si): Ditto. + (avx512f_cvtpd2ps512): Ditto. + (vec_unpacks_lo_v16sf): Ditto. + (vec_unpacks_hi_v16sf): Ditto. + (vec_unpacks_float_hi_v16si): Ditto. + (vec_unpacks_float_lo_v16si): Ditto. + (avx512f_unpckhps512): Ditto. + (avx512f_unpcklps512): Ditto. + (avx512f_movshdup512): Ditto. + (avx512f_movsldup512): Ditto. + (vec_extract_lo_v32hi): Ditto. + (vec_extract_hi_v32hi): Ditto. + (vec_extract_lo_v64qi): Ditto. + (vec_extract_hi_v64qi): Ditto. + (avx512f_unpckhpd512): Ditto. + (avx512f_movddup512): Ditto. + (avx512f_unpcklpd512): Ditto. + (*avx512f_unpcklpd512): Ditto. + (avx512f_shufps512_1): Ditto. + (avx512f_shufpd512_1): Ditto. + (avx512f_interleave_highv8di): Ditto. + (avx512f_interleave_lowv8di): Ditto. + (PMOV_DST_MODE): Ditto. + (pmov_src_mode): Ditto. + (pmov_src_lower): Ditto. + (pmov_suff): Ditto. + (*avx512f_<code><pmov_src_lower><mode>2): Ditto. + (*avx512f_<code>v8div16qi2): Ditto. + (*avx512f_<code>v8div16qi2_store): Ditto. + (vec_widen_umult_even_v16si): Ditto. + (*vec_widen_umult_even_v16si): Ditto. + (vec_widen_smult_even_v16si): Ditto. + (*vec_widen_smult_even_v16si): Ditto. + (avx512f_interleave_highv16si): Ditto. + (avx512f_interleave_lowv16si): Ditto. + (avx512f_<code>v16qiv16si2): Ditto. + (avx512f_<code>v16hiv16si2): Ditto. + (avx512f_<code>v8qiv8di2): Ditto. + (avx512f_<code>v8hiv8di2): Ditto. + (avx512f_<code>v8siv8di2): Ditto. + (avx512cd_maskb_vec_dupv8di): Ditto. + (avx512cd_maskw_vec_dupv16si): Ditto. + (avx512f_vcvtph2ps512): Ditto. + (avx512f_vcvtps2ph512): Ditto. + (VEC_EXTRACT_MODE): Extened with wider modes. + (VEC_PERM_AVX2): Ditto. + (VEC_PERM_CONST): Ditto. + +2013-10-28 Joern Rennecke <joern.rennecke@embecosm.com> + + * config/arc/arc.c (arc_ccfsm_post_advance): + Add comment about TYPE_RETURN. + +2013-10-28 Bin Cheng <bin.cheng@arm.com> + + * tree-ssa-loop-ivopts.c (strip_offset_1): Change parameter type. + Count DECL_FIELD_BIT_OFFSET for COMPONENT_REF. + (strip_offset): Convert offset to unsigned number. + +2013-10-27 Tom de Vries <tom@codesourcery.com> + + * cfgexpand.c (gimple_expand_cfg): Remove test for parm_birth_insn. + Don't commit insertions after NOTE_INSN_FUNCTION_BEG. + +2013-10-27 Oleg Endo <olegendo@gcc.gnu.org> + + * config/sh/sh.c (MSW, LSW): Move and rename macros to... + * config/sh/sh.h (SH_REG_MSW_OFFSET, SH_REG_LSW_OFFSET): ... here. + (TARGET_BIG_ENDIAN): New macro. + * config/sh/sh.md: Use it instead of !TARGET_LITTLE_ENDIAN. + Use SH_REG_MSW_OFFSET and SH_REG_LSW_OFFSET. + * config/sh/sh.c: Likewise. + * config/sh/sh.h: Likewise. + +2013-10-27 Hans-Peter Nilsson <hp@axis.com> + + * config/cris/cris.c (cris_emit_trap_for_misalignment): Replace the + removed PRED_MUDFLAP with PRED_NORETURN. Correct file-path in comment. + +2013-10-26 Oleg Endo <olegendo@gcc.gnu.org> + + * config/sh/sh.md (movmemsi): Remove empty constraints and predicates. + Fix formatting. + (cmpstr_t, cmpstrsi): Fix formatting. + +2013-10-26 Oleg Endo <olegendo@gcc.gnu.org> + + PR target/52483 + * config/sh/predicates.md (general_movdst_operand): Allow reg+reg + addressing, do not use general_operand for memory operands. + +2013-10-26 Vladimir Makarov <vmakarov@redhat.com> + + Revert: + 2013-10-25 Vladimir Makarov <vmakarov@redhat.com> + * lra-spills.c (lra_final_code_change): Remove useless move insns. + +2013-10-26 Jeff Law <law@redhat.com> + + * predict.c (PRED_MUDFLAP): Remove. + * targhooks.c (build_va_arg_indirect_ref): Remove mudflap support. + + * Makefile.in (C_COMMON_OBJS): Remove tree-mudflap. + (OBJS): Remove tree-nomudflap.o + (GTFILES): Remove tree-mudflap.c + * builtins.c (expand_builtin_alloc): Remove mudflap support. + * gcc.c (MFWRAP_SPEC, MFLIB_SPEC): Likewise. + (mfwrap_spec, mflib_spec): Likewise. + (cpp_unique_options, cc1_options, static_specs): Likewise. + * gimplify (gimplify_vla_decl, build_va_arg_indirect_ref): Likewise. + * passes.def: Likewise. + * toplev.c (compile_file, process_options): Likewise. + * tree-inline.c (copy_tree_r): Likewise. + * tree-pass.,h (make_pass_mudflap_1, make_pass_mudflap_2): Likewise. + * varasm.c (make_decl_rtl, make_decl_rtl_for_debug): Likewise. + (build_constant_desc, output_constant_def_contents): Likewise. + (categorize_decl_for_section): Likewise. + * tree-mudflap.c: Removed. + * tree-mudflap.h: Removed. + * tree-nomudflap.c: Removed. + * bfin/uclinux.h (MFWRAP_SPEC): Remove. + * moxie/uclinux.h (MFWRAP_SPEC): Likewise. + * rs6000/aix.h (MFWRAP_SPEC, MFLIB_SPEC): Likewise. + * config/sol2.h (MFLIB_SPEC): Likewise. + * doc/install.texi: Remove mudflap references. + * doc/passes.texi: Similarly. + * doc/sourcebuild.texi: Similarly. + * doc/invoke.texi: Remove mudlfap related options. + +2013-10-25 Vladimir Makarov <vmakarov@redhat.com> + + PR rtl-optimization/58759 + * lra-constraints.c (lra_constraints): Remove wrong condition to + remove insn setting up an equivalent pseudo. + +2013-10-25 Vladimir Makarov <vmakarov@redhat.com> + + * config/rs6000/rs6000-protos.h + (rs6000_secondary_memory_needed_mode): New prototype. + * config/rs6000/rs6000.c: Include ira.h. + (TARGET_LRA_P): Redefine. + (rs6000_legitimate_offset_address_p): Call + legitimate_constant_pool_address_p in strict mode for LRA. + (rs6000_legitimate_address_p): Ditto. + (legitimate_lo_sum_address_p): Add code for LRA. Use lra_in_progress. + (rs6000_emit_move): Add LRA version of code to generate load/store + of SDmode values. + (rs6000_secondary_memory_needed_mode): New. + (rs6000_alloc_sdmode_stack_slot): Do nothing for LRA. + (rs6000_secondary_reload_class): Return NO_REGS for LRA for + constants, memory, and FP registers. + (rs6000_lra_p): New. + * config/rs6000/rs6000.h (SECONDARY_MEMORY_NEEDED_MODE): New macro. + * config/rs6000/rs6000.opt (mlra): New option. + * lra-spills.c (lra_final_code_change): Remove useless move insns. + +2013-10-25 Yufeng Zhang <yufeng.zhang@arm.com> + + * tree-ssa-math-opts.c (convert_plusminus_to_widen): Call + has_single_use () and not do the conversion if has_single_use () + returns false for the multiplication result. + +2013-10-25 David Malcolm <dmalcolm@redhat.com> + + * tree.h (EXCEPTIONAL_CLASS_P): Rename parameter from "CODE" + to "NODE", since this works on a "tree", not an + "enum tree_code". + (CONSTANT_CLASS_P): Likewise. + (TYPE_P): Likewise. + (DECL_P): Likewise. + (INDIRECT_REF_P): Likewise. + (REFERENCE_CLASS_P): Likewise. + (COMPARISON_CLASS_P): Likewise. + (UNARY_CLASS_P): Likewise. + (BINARY_CLASS_P): Likewise. + (STATEMENT_CLASS_P): Likewise. + (VL_EXP_CLASS_P): Likewise. + (EXPRESSION_CLASS_P): Likewise. + (IS_TYPE_OR_DECL_P): Likewise. + +2013-10-25 Marc Glisse <marc.glisse@inria.fr> + + * tree-ssa-alias.c (ao_ref_init_from_ptr_and_size): Look for an + ADDR_EXPR in the defining statement. + +2013-10-25 Richard Biener <rguenther@suse.de> + + PR tree-optimization/58626 + * tree-loop-distribution.c (enum rdg_dep_type): Remove + anti_dd, output_dd and input_dd. + (struct rdg_edge): Remove level and relation members. + (RDGE_LEVEL, RDGE_RELATION): Remove. + (dot_rdg_1): Adjust. + (create_rdg_edge_for_ddr): Remove. + (create_rdg_edges_for_scalar): Adjust. + (create_edge_for_control_dependence): Likewise. + (create_rdg_edges): Split into ... + (create_rdg_flow_edges): ... this + (create_rdg_cd_edges): ... and this. + (free_rdg): Adjust. + (build_rdg): Likewise, do not compute data dependences or + add edges for them. + (pg_add_dependence_edges): New function. + (pgcmp): Likewise. + (distribute_loop): First apply all non-dependence based + partition mergings. Then compute dependences between partitions + and merge and order partitions according to them. + +2013-10-25 Eric Botcazou <ebotcazou@adacore.com> + + PR rtl-optimization/58831 + * alias.c (init_alias_analysis): At the beginning of each iteration, + set the reg_seen[N] bit if static_reg_base_value[N] is non-null. + +2013-10-25 Eric Botcazou <ebotcazou@adacore.com> + + * recog.c (search_ofs): New static variable moved from... + (peep2_find_free_register): ...here. + (peephole2_optimize): Initialize it. + +2013-10-25 Tobias Burnus <burnus@net-b.de> + + * doc/invoke.texi (fopenmp): Change supported OpenMP version to 4.0. + +2013-10-25 Uros Bizjak <ubizjak@gmail.com> + + * config/i386/i386.h (TARGET_MPX): New define. + (TARGET_MPX_P): Ditto. + +2013-10-24 Ilya Enkovich <ilya.enkovich@intel.com> + + * config/i386/constraints.md (B): New. + (Ti): New. + (Tb): New. + * config/i386/i386-c.c (ix86_target_macros_internal): Add __MPX__. + * config/i386/i386-modes.def (BND32): New. + (BND64): New. + * config/i386/i386-protos.h (ix86_bnd_prefixed_insn_p): New. + * config/i386/i386.c (isa_opts): Add mmpx. + (regclass_map): Add bound registers. + (dbx_register_map): Likewise. + (dbx64_register_map): Likewise. + (svr4_dbx_register_map): Likewise. + (PTA_MPX): New. + (ix86_option_override_internal): Support MPX ISA. + (ix86_conditional_register_usage): Support bound registers. + (print_reg): Likewise. + (ix86_code_end): Add MPX bnd prefix. + (output_set_got): Likewise. + (ix86_output_call_insn): Likewise. + (ix86_print_operand): Add '!' (MPX bnd) print prefix support. + (ix86_print_operand_punct_valid_p): Likewise. + (ix86_print_operand_address): Support UNSPEC_BNDMK_ADDR and + UNSPEC_BNDMK_ADDR. + (ix86_class_likely_spilled_p): Add bound regs support. + (ix86_hard_regno_mode_ok): Likewise. + (x86_order_regs_for_local_alloc): Likewise. + (ix86_bnd_prefixed_insn_p): New. + * config/i386/i386.h (FIRST_PSEUDO_REGISTER): Fix to new value. + (FIXED_REGISTERS): Add bound registers. + (CALL_USED_REGISTERS): Likewise. + (REG_ALLOC_ORDER): Likewise. + (HARD_REGNO_NREGS): Likewise. + (TARGET_MPX): New. + (VALID_BND_REG_MODE): New. + (FIRST_BND_REG): New. + (LAST_BND_REG): New. + (reg_class): Add BND_REGS. + (REG_CLASS_NAMES): Likewise. + (REG_CLASS_CONTENTS): Likewise. + (BND_REGNO_P): New. + (ANY_BND_REG_P): New. + (BNDmode): New. + (HI_REGISTER_NAMES): Add bound registers. + * config/i386/i386.md (UNSPEC_BNDMK): New. + (UNSPEC_BNDMK_ADDR): New. + (UNSPEC_BNDSTX): New. + (UNSPEC_BNDLDX): New. + (UNSPEC_BNDLDX_ADDR): New. + (UNSPEC_BNDCL): New. + (UNSPEC_BNDCU): New. + (UNSPEC_BNDCN): New. + (UNSPEC_MPX_FENCE): New. + (BND0_REG): New. + (BND1_REG): New. + (type): Add mpxmov, mpxmk, mpxchk, mpxld, mpxst. + (length_immediate): Likewise. + (prefix_0f): Likewise. + (memory): Likewise. + (prefix_rep): Check for bnd prefix. + (length_nobnd): New. + (length): Use length_nobnd if specified. + (BND): New. + (bnd_ptr): New. + (BNDCHECK): New. + (bndcheck): New. + (*jcc_1): Add bnd prefix and rename length attr to length_nobnd. + (*jcc_2): Likewise. + (jump): Likewise. + (simple_return_internal): Likewise. + (simple_return_pop_internal): Likewise. + (*indirect_jump): Add MPX bnd prefix. + (*tablejump_1): Likewise. + (simple_return_internal_long): Likewise. + (simple_return_indirect_internal): Likewise. + (<mode>_mk): New. + (*<mode>_mk): New. + (mov<mode>): New. + (*mov<mode>_internal_mpx): New. + (<mode>_<bndcheck>): New. + (*<mode>_<bndcheck>): New. + (<mode>_ldx): New. + (*<mode>_ldx): New. + (<mode>_stx): New. + (*<mode>_stx): New. + * config/i386/predicates.md (lea_address_operand): Rename to... + (address_no_seg_operand): ... this. + (address_mpx_no_base_operand): New. + (address_mpx_no_index_operand): New. + (bnd_mem_operator): New. + * config/i386/i386.opt (mmpx): New. + * doc/invoke.texi: Add documentation for the flags -mmpx, -mno-mpx. + * doc/rtl.texi Add documentation for BND32mode and BND64mode. + +2013-10-24 Ilya Enkovich <ilya.enkovich@intel.com> + + * mode-classes.def (MODE_POINTER_BOUNDS): New. + * tree.def (POINTER_BOUNDS_TYPE): New. + * genmodes.c (complete_mode): Support MODE_POINTER_BOUNDS. + (POINTER_BOUNDS_MODE): New. + (make_pointer_bounds_mode): New. + * machmode.h (POINTER_BOUNDS_MODE_P): New. + * stor-layout.c (int_mode_for_mode): Support MODE_POINTER_BOUNDS. + (layout_type): Support POINTER_BOUNDS_TYPE. + * tree-pretty-print.c (dump_generic_node): Support POINTER_BOUNDS_TYPE. + * tree.c (build_int_cst_wide): Support POINTER_BOUNDS_TYPE. + (type_contains_placeholder_1): Likewise. + * tree.h (POINTER_BOUNDS_TYPE_P): New. + * varasm.c (output_constant): Support POINTER_BOUNDS_TYPE. + * doc/rtl.texi (MODE_POINTER_BOUNDS): New. + +2013-10-24 Igor Shevlyakov <igor.shevlyakov@gmail.com> + + * expr.c (expand_expr_real_1): Use mode of memory reference rather than + mode of address computation when calling memory_address_addr_space. + +2013-08-24 Richard Henderson <rth@twiddle.net> + + PR rtl/58542 + * optabs.c (maybe_emit_atomic_exchange): Use create_input_operand + instead of create_convert_operand_to. + (maybe_emit_sync_lock_test_and_set): Likewise. + (expand_atomic_compare_and_swap): Likewise. + (maybe_emit_compare_and_swap_exchange_loop): Don't convert_modes. + +2013-08-24 Sriraman Tallam <tmsriram@google.com> + + * cgraph.c (cgraph_fnver_htab): Move GTY((...)) to be before htab_t. + Change param_is to use the struct and not the pointer to the struct. + +2013-10-24 Andrew MacLeod <amacleod@redhat.com> + + * builtins.c (dummy_object, gimplify_va_arg_expr): Move to gimplify.c. + * gimplify.c (build_va_arg_indirect_ref, std_gimplify_va_arg_expr): + Move to targhooks.c. + (dummy_object, gimplify_va_arg_expr): Relocate from builtins.c. + * targhooks.c (build_va_arg_indirect_ref, std_gimplify_va_arg_expr): + Relocate from gimplify.c. + * targhooks.h: Add 2 prototypes. + * tree.h: Delete 2 prototypes. + +2013-10-24 Igor Shevlyakov <igor.shevlyakov@gmail.com> + + * tree-ssa-loop-ivopts.c (multiplier_allowed_in_address_p ): Check both + [reg+mult*reg] and [mult*reg] to determine if multiplier is allowed. + +2013-10-24 Cong Hou <congh@google.com> + + * convert.c (convert_to_real): Guard those unsafe math function + convertions with flag_unsafe_math_optimizations. Handle sqrt() + specially. + +2013-10-24 Markus Trippelsdorf <markus@trippelsdorf.de> + + PR ipa/58712 + * cgraph.c (cgraph_create_edge_1): Add indirect_unknown_callee + as argument. + (cgraph_create_edge): Use the new argument. + (cgraph_create_indirect_edge): Likewise. + +2013-10-24 Joern Rennecke <joern.rennecke@embecosm.com> + + * gcc/config/arc/arc.c (arc_ccfsm_post_advance): Also handle + TYPE_UNCOND_BRANCH. + (arc_ifcvt) <case 1 and 2>: Check that arc_ccfsm_post_advance + changes statep->state. + +2013-10-24 Tobias Burnus <burnus@net-b.de> + + PR other/33426 + * tree-cfg.c (replace_loop_annotate): New function. + (execute_build_cfg): Call it. + * gimplify.c (gimple_boolify, gimplify_expr): Handle ANNOTATE_EXPR. + * internal-fn.c (expand_ANNOTATE): New function. + * internal-fn.def (ANNOTATE): Define as new internal function. + * tree-core.h (tree_node_kind): Add annot_expr_ivdep_kind. + * tree-pretty-print.c (dump_generic_node): Handle ANNOTATE_EXPR. + * tree.def (ANNOTATE_EXPR): New DEFTREECODE. + * doc/extend.texi (Pragmas): Document #pragma ivdep. + * doc/generic.texi (Expressions): Document ANNOTATE_EXPR. + +2013-10-17 Ian Bolton <ian.bolton@arm.com> + Marcus Shawcroft <marcus.shawcroft@arm.com> + + * config/aarch64/aarch64.c (aarch64_preferred_reload_class): + Special case reload SP+C into none GENERAL_REGS. + +2013-10-24 Michael Matz <matz@suse.de> + + * gengtype.c (is_file_equal): Check that files will be same length. + +2013-10-25 Christian Bruel <christian.bruel@st.com> + + * config.gcc (sh-*): Add sh-mem.o to extra_obj. + * gcc/config/sh/t-sh (sh-mem.o): New rule. + * gcc/config/sh/sh-mem.cc (expand_block_move): Moved here. + (sh_expand_cmpstr): New function. + * gcc/config/sh/sh.c (force_into, expand_block_move): Move to sh-mem.c. + * gcc/config/sh/sh-protos.h (sh_expand_cmpstr): Declare. + * gcc/config/sh/sh.md (cmpstrsi, cmpstr_t): New patterns. + (rotlhi3_8): Rename. + +2013-10-24 Jan-Benedict Glaw <jbglaw@lug-owl.de> + + * configure.ac (ZW_PROG_COMPILER_DEPENDENCIES): Use CXX instead of CC. + * Makefile.in (CXXDEPMODE): Assign and change users. + (CCDEPMODE): Delete. + * configure: Regenerate. + +2013-10-23 David Malcolm <dmalcolm@redhat.com> + + * gengtype-parse.c (require_without_advance): New. + (type): For GTY-marked types that are not GTY((user)), parse any + base classes, requiring them to be single-inheritance, and not + be templates. For non-GTY-marked types and GTY((user)), + continue to skip over any C++ inheritance specification. + * gengtype-state.c (state_writer::write_state_struct_type): + Write base class of type (if any). + (read_state_struct_type): Read base class of type (if any). + * gengtype.c (new_structure): Add a "base_class" parameter. + (create_optional_field_): Update for new parameter to new_structure. + (adjust_field_rtx_def): Likewise. + (adjust_field_tree_exp): Likewise. + * gengtype.h (struct type): Add "base_class" field to the s + union field. + (new_structure): Add "base" parameter. + +2013-10-23 Sriraman Tallam <tmsriram@google.com> + + PR target/57756 + * config/i386/i386.c (ix86_option_override_internal): + Change TARGET_SSE2 to TARGET_SSE2_P (opts->...) + (ix86_valid_target_attribute_tree): + Change TARGET_64BIT to TARGET_64BIT_P (opts->...) + Change TARGET_SSE to TARGET_SSE_P (opts->...) + +2013-10-23 Andrew MacLeod <amacleod@redhat.com> + + * tree-ssa-loop.h: Remove include files. + * gengtype.c (open_base_files): Adjust include list for gtype-desc.c. + * cfgloopmanip.c: Move required includes from tree-ssa-loop.h. + * graphite-clast-to-gimple.c: Likewise. + * graphite-scop-detection.c: Likewise. + * graphite-sese-to-poly.c: Likewise. + * ipa-inline-analysis.c: Likewise. + * ipa-pure-const.c: Likewise. + * loop-init.c: Likewise. + * passes.c: Likewise. + * predict.c: Likewise. + * tree-cfg.c: Likewise. + * tree-cfgcleanup.c: Likewise. + * tree-chrec.c: Likewise. + * tree-data-ref.c: Likewise. + * tree-loop-distribution.c: Likewise. + * tree-parloops.c: Likewise. + * tree-predcom.c: Likewise. + * tree-scalar-evolution.c: Likewise. + * tree-ssa-address.c: Likewise. + * tree-ssa.c: Likewise. + * tree-ssa-dce.c: Likewise. + * tree-ssa-loop.c: Likewise. + * tree-ssa-loop-im.c: Likewise. + * tree-ssa-loop-ivcanon.c: Likewise. + * tree-ssa-loop-ivopts.c: Likewise. + * tree-ssa-loop-manip.c: Likewise. + * tree-ssa-loop-niter.c: Likewise. + * tree-ssa-loop-prefetch.c: Likewise. + * tree-ssa-loop-unswitch.c: Likewise. + * tree-ssa-reassoc.c: Likewise. + * tree-vect-data-refs.c: Likewise. + * tree-vect-loop.c: Likewise. + * tree-vect-loop-manip.c: Likewise. + * tree-vectorizer.c: Likewise. + * tree-vect-stmts.c: Likewise. + * tree-vrp.c: Likewise. + +2013-10-23 Bill Schmidt <wschmidt@linux.vnet.ibm.com> + + * config/rs6000/altivec.md (mulv8hi3): Adjust for little endian. + +2013-10-23 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/58775 + PR tree-optimization/58791 + * tree-ssa-reassoc.c (reassoc_stmt_dominates_stmt_p): New function. + (insert_stmt_after): Rewritten, don't move the stmt, but really + insert it. + (get_stmt_uid_with_default): Remove. + (build_and_add_sum): Use insert_stmt_after and + reassoc_stmt_dominates_stmt_p. Fix up uid if bb contains only labels. + (update_range_test): Set uid on stmts added by + force_gimple_operand_gsi. Don't immediately modify statements + in inter-bb optimization, just update oe->op values. + (optimize_range_tests): Return bool whether any changed have been made. + (update_ops): New function. + (struct inter_bb_range_test_entry): New type. + (maybe_optimize_range_tests): Perform statement changes here. + (not_dominated_by, appears_later_in_bb, get_def_stmt, + ensure_ops_are_available): Remove. + (find_insert_point): Rewritten. + (rewrite_expr_tree): Remove MOVED argument, add CHANGED argument, + return LHS of the (new resp. old) stmt. Don't call + ensure_ops_are_available, don't reuse SSA_NAMEs, recurse first + instead of last, move new stmt at the right place. + (linearize_expr, repropagate_negates): Don't reuse SSA_NAMEs. + (negate_value): Likewise. Set uids. + (break_up_subtract_bb): Initialize uids. + (reassociate_bb): Adjust rewrite_expr_tree caller. + (do_reassoc): Don't call renumber_gimple_stmt_uids. + +2013-10-23 David Edelsohn <dje.gcc@gmail.com> + + PR target/58838 + * config/rs6000/rs6000.md (mulsi3_internal1 and splitter): Add + TARGET_32BIT final condition. + (mulsi3_internal2 and splitter): Same. + +2013-10-23 Jeff Law <law@redhat.com> + + * tree-ssa-threadedge.c (thread_across_edge): Do not allow threading + through joiner blocks with abnormal outgoing edges. + + * tree-ssa-threadupdate.c (thread_block_1): Renamed from thread_block. + Add parameter JOINERS, to allow/disallow threading through joiner + blocks. + (thread_block): New. Call thread_block_1. + (mark_threaded_blocks): Remove code to filter out certain cases + of threading through joiner blocks. + (thread_through_all_blocks): Document how we can have a dangling + edge AUX field and clear it. + +2013-10-23 Ian Lance Taylor <iant@google.com> + + * doc/invoke.texi (Option Summary): Remove -fno-default-inline. + (C++ Dialect Options): Likewise. + (Optimize Options): Likewise. + +2013-10-23 Tom de Vries <tom@codesourcery.com> + + PR tree-optimization/58805 + * tree-ssa-tail-merge.c (stmt_local_def): Add gimple_vdef check. + +2013-10-23 Jakub Jelinek <jakub@redhat.com> + + * tree-vect-patterns.c (vect_recog_divmod_pattern): Optimize + sequence based on get_range_info returned range. + +2013-10-23 Andrew MacLeod <amacleod@redhat.com> + + * tree-ssa.h: Remove all #include's + * gengtype.c (open_base_files): Adjust include list for gtype-desc.c. + * alias.c: Move required includes from tree-ssa.h. + * asan.c: Likewise. + * builtins.c: Likewise. + * calls.c: Likewise. + * cfgexpand.c: Likewise. + * cfghooks.c: Likewise. + * cfgloop.c: Likewise. + * cfgloopmanip.c: Likewise. + * cgraph.c: Likewise. + * cgraphbuild.c: Likewise. + * cgraphclones.c: Likewise. + * cgraphunit.c: Likewise. + * dse.c: Likewise. + * except.c: Likewise. + * expr.c: Likewise. + * final.c: Likewise. + * fold-const.c: Likewise. + * ggc-page.c: Likewise. + * gimple-builder.c: Likewise. + * gimple-fold.c: Likewise. + * gimple-iterator.c: Likewise. + * gimple-low.c: Likewise. + * gimple-pretty-print.c: Likewise. + * gimple-ssa-strength-reduction.c: Likewise. + * gimple-streamer-in.c: Likewise. + * gimple-streamer-out.c: Likewise. + * gimplify.c: Likewise. + * graphite-blocking.c: Likewise. + * graphite-clast-to-gimple.c: Likewise. + * graphite-dependences.c: Likewise. + * graphite-interchange.c: Likewise. + * graphite-optimize-isl.c: Likewise. + * graphite-poly.c: Likewise. + * graphite-scop-detection.c: Likewise. + * graphite-sese-to-poly.c: Likewise. + * graphite.c: Likewise. + * ipa-cp.c: Likewise. + * ipa-inline-analysis.c: Likewise. + * ipa-inline-transform.c: Likewise. + * ipa-inline.c: Likewise. + * ipa-prop.c: Likewise. + * ipa-pure-const.c: Likewise. + * ipa-reference.c: Likewise. + * ipa-split.c: Likewise. + * ipa-utils.c: Likewise. + * loop-init.c: Likewise. + * lto-cgraph.c: Likewise. + * lto-section-in.c: Likewise. + * lto-section-out.c: Likewise. + * lto-streamer-in.c: Likewise. + * lto-streamer-out.c: Likewise. + * lto-streamer.c: Likewise. + * omp-low.c: Likewise. + * passes.c: Likewise. + * predict.c: Likewise. + * print-tree.c: Likewise. + * profile.c: Likewise. + * sese.c: Likewise. + * targhooks.c: Likewise. + * tracer.c: Likewise. + * trans-mem.c: Likewise. + * tree-call-cdce.c: Likewise. + * tree-cfg.c: Likewise. + * tree-cfgcleanup.c: Likewise. + * tree-chrec.c: Likewise. + * tree-complex.c: Likewise. + * tree-data-ref.c: Likewise. + * tree-dfa.c: Likewise. + * tree-eh.c: Likewise. + * tree-emutls.c: Likewise. + * tree-if-conv.c: Likewise. + * tree-inline.c: Likewise. + * tree-into-ssa.c: Likewise. + * tree-loop-distribution.c: Likewise. + * tree-mudflap.c: Likewise. + * tree-nested.c: Likewise. + * tree-nrv.c: Likewise. + * tree-object-size.c: Likewise. + * tree-outof-ssa.c: Likewise. + * tree-parloops.c: Likewise. + * tree-phinodes.c: Likewise. + * tree-predcom.c: Likewise. + * tree-pretty-print.c: Likewise. + * tree-profile.c: Likewise. + * tree-scalar-evolution.c: Likewise. + * tree-sra.c: Likewise. + * tree-ssa-address.c: Likewise. + * tree-ssa-alias.c: Likewise. + * tree-ssa-ccp.c: Likewise. + * tree-ssa-coalesce.c: Likewise. + * tree-ssa-copy.c: Likewise. + * tree-ssa-copyrename.c: Likewise. + * tree-ssa-dce.c: Likewise. + * tree-ssa-dom.c: Likewise. + * tree-ssa-dse.c: Likewise. + * tree-ssa-forwprop.c: Likewise. + * tree-ssa-ifcombine.c: Likewise. + * tree-ssa-live.c: Likewise. + * tree-ssa-loop-ch.c: Likewise. + * tree-ssa-loop-im.c: Likewise. + * tree-ssa-loop-ivcanon.c: Likewise. + * tree-ssa-loop-ivopts.c: Likewise. + * tree-ssa-loop-manip.c: Likewise. + * tree-ssa-loop-niter.c: Likewise. + * tree-ssa-loop-prefetch.c: Likewise. + * tree-ssa-loop-unswitch.c: Likewise. + * tree-ssa-loop.c: Likewise. + * tree-ssa-math-opts.c: Likewise. + * tree-ssa-operands.c: Likewise. + * tree-ssa-phiopt.c: Likewise. + * tree-ssa-phiprop.c: Likewise. + * tree-ssa-pre.c: Likewise. + * tree-ssa-propagate.c: Likewise. + * tree-ssa-reassoc.c: Likewise. + * tree-ssa-sccvn.c: Likewise. + * tree-ssa-sink.c: Likewise. + * tree-ssa-strlen.c: Likewise. + * tree-ssa-structalias.c: Likewise. + * tree-ssa-tail-merge.c: Likewise. + * tree-ssa-ter.c: Likewise. + * tree-ssa-threadedge.c: Likewise. + * tree-ssa-threadupdate.c: Likewise. + * tree-ssa-uncprop.c: Likewise. + * tree-ssa-uninit.c: Likewise. + * tree-ssa.c: Likewise. + * tree-ssanames.c: Likewise. + * tree-stdarg.c: Likewise. + * tree-streamer-in.c: Likewise. + * tree-switch-conversion.c: Likewise. + * tree-tailcall.c: Likewise. + * tree-vect-data-refs.c: Likewise. + * tree-vect-generic.c: Likewise. + * tree-vect-loop-manip.c: Likewise. + * tree-vect-loop.c: Likewise. + * tree-vect-patterns.c: Likewise. + * tree-vect-slp.c: Likewise. + * tree-vect-stmts.c: Likewise. + * tree-vectorizer.c: Likewise. + * tree-vrp.c: Likewise. + * tree.c: Likewise. + * tsan.c: Likewise. + * value-prof.c: Likewise. + * var-tracking.c: Likewise. + * varpool.c: Likewise. + * vtable-verify.c: Likewise. + +2013-10-23 Jan-Benedict Glaw <jbglaw@lug-owl.de> + + * config/tilegx/tilegx.c: Include "tree.h". + +2013-10-23 Jakub Jelinek <jakub@redhat.com> + + * gimple-pretty-print.c (dump_ssaname_info): Always print "# " before + the info, not after it. + (gump_gimple_phi): Add COMMENT argument, if true, print "# " after + dump_ssaname_info call. + (pp_gimple_stmt_1): Adjust caller. + (dump_phi_nodes): Likewise. Don't print "# " here. + +2013-10-22 Jan Hubicka <jh@suse.cz> + + * i386.h (TARGET_MISALIGNED_MOVE_STRING_PROLOGUES_EPILOGUES): New + tuning flag. + * x86-tune.def (TARGET_MISALIGNED_MOVE_STRING_PROLOGUES): Define it. + * i386.c (expand_small_movmem_or_setmem): New function. + (expand_set_or_movmem_prologue_epilogue_by_misaligned_moves): New + function. + (alg_usable_p): Add support for value ranges; cleanup. + (ix86_expand_set_or_movmem): Add support for misaligned moves. + +2013-10-22 Sterling Augustine <saugustine@google.com> + + * doc/invoke.texi: Document -ggnu-pubnames. + * common.opt: Add new option -ggnu-pubnames and modify -gpubnames + logic. + * dwarf2out.c: Include gdb/gdb-index.h. + (DEBUG_PUBNAMES_SECTION, DEBUG_PUBTYPES_SECTION): Handle + debug_generate_pub_sections. + (is_java, output_pubtables, output_pubname): New functions. + (include_pubname_in_output): Handle debug_generate_pub_sections at + level 2. + (size_of_pubnames): Use new local space_for_flags based on + debug_generate_pub_sections. + (output_pubnames): Unify pubnames and pubtypes output logic. + Genericize comments. Call output_pubname. + (dwarf2out_finish): Move logic to output_pubnames and call it. + +2013-10-22 Uros Bizjak <ubizjak@gmail.com> + + PR target/58779 + * config/i386/i386.c (put_condition_code) <case GTU, case LEU>: + Remove CCCmode handling. + <case LTU>: Return 'c' suffix for CCCmode. + <case GEU>: Return 'nc' suffix for CCCmode. + (ix86_cc_mode) <case GTU, case LEU>: Do not generate overflow checks. + * config/i386/i386.md (*sub<mode>3_cconly_overflow): Remove. + (*sub<mode>3_cc_overflow): Ditto. + (*subsi3_zext_cc_overflow): Ditto. + +2013-10-22 Steve Ellcey <sellcey@mips.com> + + * config/mips/mips.c (mips_rtx_costs): Fix cost estimate for nor + (AND (NOT OP1) (NOT OP2)). + +2013-10-22 Bill Schmidt <wschmidt@vnet.ibm.com> + + * config/rs6000/rs6000.c (altivec_expand_vec_perm_const): Reverse + meaning of merge-high and merge-low masks for little endian; avoid + use of vector-pack masks for little endian for mismatched modes. + +2013-10-22 Jan-Benedict Glaw <jbglaw@lug-owl.de> + + * config/tilepro/tilepro.c: Include "tree.h". + +2013-10-22 Andreas Schwab <schwab@suse.de> + + * config/m68k/m68k.c (notice_update_cc): Handle register conflict + with PRE_DEC. + +2013-10-22 Paolo Carlini <paolo.carlini@oracle.com> + + * doc/contrib.texi ([Fran@,{c}ois Dumont], [Tim Shen], + [Ed Smith-Rowland]): New entries. + ([Stephen M. Webb]): Update. + +2013-10-22 Andrew MacLeod <amacleod@redhat.com> + + * tree-ssa-ter.h: Remove duplicate copy of file contents. + +2013-10-21 Marek Polacek <polacek@redhat.com> + + PR middle-end/58809 + * fold-const.c (fold_range_test): Return 0 if the type is not + an integral type. + +2013-10-21 Richard Sandiford <rdsandiford@googlemail.com> + + * system.h: Move hwint.h include further down. + * hwint.h (sext_hwi, zext_hwi): Define unconditionally. Add + gcc_checking_asserts. + * hwint.c (sext_hwi, zext_hwi): Delete ENABLE_CHECKING versions. + +2013-10-21 Bernd Edlinger <bernd.edlinger@hotmail.de> + + Fix volatile issues in optimize_bit_field_compare. + * fold-const.c (optimize_bit_field_compare): Bail out if + lvolatilep or rvolatilep. + +2013-10-21 Bernd Edlinger <bernd.edlinger@hotmail.de> + + Fix DECL_BIT_FIELD depencency on flag_strict_volatile_bitfields + and get_inner_reference returning different pmode for non-volatile + bit-field members dependent on flag_strict_volatile_bitfields. + * stor-layout.c (layout_decl): Remove special handling of + flag_strict_volatile_bitfields. + * expr.c (get_inner_reference): Don't use DECL_BIT_FIELD + if flag_strict_volatile_bitfields > 0 and TREE_THIS_VOLATILE. + +2013-10-21 Paulo Matos <pmatos@broadcom.com> + + * ipa-inline.c (edge_badness): Cap edge->count at max_count for badness + calculations. + +2013-10-21 Jeff Law <law@redhat.com> + + * tree-ssa-threadedge.c (thread_through_normal_block): New + argument VISITED. Remove VISISTED as a local variable. When we + have a threadable jump, verify the destination of the jump has not + been visised. + (thread_across_edge): Allocate VISITED bitmap once at function + scope and use it throughout. Make sure to set appropriate bits in + VISITED for E (start of jump thread path). + * tree-ssa-threadupdate.c (mark_threaded_blocks): Reject threading + through a joiner if any edge on the path has a recorded jump thread. + +2013-10-21 Ian Lance Taylor <iant@google.com> + + * doc/invoke.texi (Optimize Options): For -fno-toplevel-reorder, + don't imply that attributes can solve all problems. + (Directory Options): Fix typo. + +2013-10-21 Kyrylo Tkachov <kyrylo.tkachov@arm.com> + + * config/arm/arm.c (cortexa9_extra_costs): Update mult costs for + extend and extend_add. + +2013-10-21 Richard Biener <rguenther@suse.de> + + PR tree-optimization/58794 + * fold-const.c (operand_equal_p): Compare FIELD_DECL operand + of COMPONENT_REFs with OEP_CONSTANT_ADDRESS_OF left in place. + +2013-10-21 Richard Biener <rguenther@suse.de> + + PR middle-end/58742 + * fold-const.c (fold_binary_loc): Fold ((T) (X /[ex] C)) * C + to (T) X for sign-changing conversions (or no conversion). + +2013-10-20 Uros Bizjak <ubizjak@gmail.com> + + * config/i386/i386.md (kxnor<mode>): Add FLAGS_REG clobber. + +2013-10-20 Jan Hubicka <jh@suse.cz> + + * config/i386/i386-tune.def: Add comment; organize into categories + +2013-10-21 Michael Zolotukhin <michael.v.zolotukhin@gmail.com> + + * config/i386/i386.c (expand_set_or_movmem_via_loop): Add issetmem + argument. Update function comment. + (expand_set_or_movmem_via_rep): New function combining + expand_movmem_via_rep_mov and expand_setmem_via_rep_stos. + (expand_movmem_via_rep_mov): Remove. + expand_setmem_via_rep_stos): Remove. + (expand_movmem_epilogue): Update calls correspondingly. + (expand_setmem_epilogue_via_loop): Likewise. + (emit_memset): New. + (expand_setmem_epilogue): Add VEC_VALUE argument, refactor. + (expand_set_or_movmem_prologue): New function combining + expand_movmem_prologue and expand_setmem_prologue. + (expand_movmem_prologue): Remove. + (expand_setmem_prologue): Remove. + (expand_set_or_movmem_constant_prologue): New function combining + expand_constant_movmem_prologue and expand_constant_setmem_prologue. + (expand_constant_movmem_prologue): Remove. + (expand_constant_setmem_prologue): Remove. + (promote_duplicated_reg): Allow vector-const0 value. + (ix86_expand_set_or_movmem): New function combining ix86_expand_movmem + and ix86_expand_setmem. + (ix86_expand_movmem): Call ix86_expand_set_or_movmem. + (ix86_expand_setmem): Call ix86_expand_set_or_movmem. + +2013-10-21 Diego Novillo <dnovillo@google.com> + + * asan.c: Include tree.h + * bb-reorder.c: Likewise. + * cfgcleanup.c: Likewise. + * cfgloopmanip.c: Likewise. + * data-streamer-in.c: Likewise. + * data-streamer-out.c: Likewise. + * data-streamer.c: Likewise. + * dwarf2cfi.c: Likewise. + * graphite-blocking.c: Likewise. + * graphite-clast-to-gimple.c: Likewise. + * graphite-dependences.c: Likewise. + * graphite-interchange.c: Likewise. + * graphite-optimize-isl.c: Likewise. + * graphite-poly.c: Likewise. + * graphite-scop-detection.c: Likewise. + * graphite-sese-to-poly.c: Likewise. + * graphite.c: Likewise. + * ipa-devirt.c: Likewise. + * ipa-profile.c: Likewise. + * ipa.c: Likewise. + * ira.c: Likewise. + * loop-init.c: Likewise. + * loop-unroll.c: Likewise. + * lower-subreg.c: Likewise. + * lto/lto-object.c: Likewise. + * recog.c: Likewise. + * reginfo.c: Likewise. + * tree-loop-distribution.c: Likewise. + * tree-parloops.c: Likewise. + * tree-ssa-strlen.c: Likewise. + * tree-streamer.c: Likewise. + * value-prof.c: Likewise. + * target-globals.c: Likewise. + * expr.h: Include tree-core.h instead of tree.h. + * gimple.h: Likewise. + * ipa-prop.h: Likewise. + * ipa-utils.h: Likewise. + * lto-streamer.h: Likewise. + * streamer-hooks.h: Likewise. + * ipa-reference.h: Include cgraph.h instead of tree.h. + * cgraph.h: Include basic-block.h instead of tree.h. + * tree-streamer.h: Do not include tree.h. + * genattrtab.c (write_header): Generate inclusion of + tree.h. + * genautomata.c (main): Likewise. + * genemit.c: Likewise. + * genopinit.c: Likewise. + * genoutput.c (output_prologue): Likewise. + * genpeep.c: Likewise. + 2013-10-20 Bill Schmidt <wschmidt@linux.vnet.ibm.com> * config/rs6000/altivec.md (vec_unpacku_hi_v16qi): Adjust for @@ -181,6 +2674,7 @@ 2013-10-17 Sriraman Tallam <tmsriram@google.com> + PR target/57756 * opth-gen.awk: Define target_flags_explicit. 2013-10-17 Michael Meissner <meissner@linux.vnet.ibm.com> @@ -4747,28 +7241,29 @@ (move_computations_stmt): Convert to method move_computations_dom_walker::before_dom_children. (move_computations, tree_ssa_lim): Adjust. - * tree-ssa-phiopt.c (nontrapping_dom_walker): new class - (nt_init_block): Make method + * tree-ssa-phiopt.c (nontrapping_dom_walker): New class. + (nt_init_block): Convert to method notrappping_dom_walker::before_dom_children. - (nt_fini_block): Make + (nt_fini_block): Convert to method method nontrapping_dom_walker::after_dom_children. (get_non_trapping): Adjust. * tree-ssa-pre.c (eliminate_dom_walker): New class. - (eliminate_bb): Make method eliminate_dom_walker::before_dom_children. - (eliminate_leave_block): Make method. + (eliminate_bb): Convert to method + eliminate_dom_walker::before_dom_children. + (eliminate_leave_block): Convert to method eliminate_dom_walker::after_dom_children. - (eliminate): Adjust + (eliminate): Adjust. * tree-ssa-strlen.c (strlen_dom_walker): New class. - (strlen_enter_block): Make method + (strlen_enter_block): Convert to method strlen_dom_walker::before_dom_children. - (strlen_leave_block): Make + (strlen_leave_block): Convert to method method strlen_dom_walker::after_dom_children. (tree_ssa_strlen): Adjust. * tree-ssa-uncprop.c (uncprop_dom_walker): New class. (tree_ssa_uncprop): Adjust. - (uncprop_leave_block): Make method + (uncprop_leave_block): Convert to method uncprop_dom_walker::after_dom_children. - (uncprop_leave_block): Make method + (uncprop_leave_block): Convert to method uncprop_dom_walker::before_dom_children. 2013-09-18 Bin Cheng <bin.cheng@arm.com> @@ -19245,7 +21740,7 @@ PR tree-optimization/57066 * builtins.c (fold_builtin_logb): Return +Inf for -Inf. -2013-04-25 James Greenhalgh <jame.greenhalgh@arm.com> +2013-04-25 James Greenhalgh <james.greenhalgh@arm.com> * config/aarch64/aarch64-simd.md (neg<mode>2): Use VDQ iterator. @@ -23185,7 +25680,7 @@ (udivsi3_i4_single, divsi3_i4_single): Use TARGET_FPU_SINGLE_ONLY || TARGET_FPU_DOUBLE instead of TARGET_HARD_SH4. -2013-03-13 Dave Korn <dave.korn.cygwin@....> +2013-03-13 Dave Korn <dave.korn.cygwin@gmail.com> * config/i386/cygwin.h (SHARED_LIBGCC_SPEC): Make shared libgcc the default setting. @@ -24232,7 +26727,7 @@ * target-globals.c (save_target_globals): For init_reg_sets and target_reinit remporarily set this_fn_optabs to this_target_optabs. -2013-02-22 James Grennahlgh <james.greenhalgh@arm.com> +2013-02-22 James Greenhalgh <james.greenhalgh@arm.com> * config/aarch64/aarch64-simd-builtins.def: Add copyright header. * config/aarch64/t-aarch64 @@ -24726,7 +27221,7 @@ equal to op0 or op1, and last_insn pattern is CODE operation with MEM dest and one of the operands matches that MEM. -2013-02-11 Sriraman Tallam <tmsriramgoogle.com> +2013-02-11 Sriraman Tallam <tmsriram@google.com> * doc/extend.texi: Document Function Multiversioning and "default" parameter string to target attribute. diff --git a/gcc/ChangeLog-2009 b/gcc/ChangeLog-2009 index 4167065b58d..c95c0ca129e 100644 --- a/gcc/ChangeLog-2009 +++ b/gcc/ChangeLog-2009 @@ -7030,7 +7030,7 @@ Ryan Mansfield <rmansfield@qnx.com> Diego Novillo <dnovillo@google.com> Ollie Wild <aaw@google.com> - Kenneth Zadeck <zadeck@naturalbridge.com> + Kenneth Zadeck <zadeck@naturalbridge.com> * lto-cgraph.c: New file. * lto-compress.c: New file. @@ -7091,7 +7091,7 @@ (cgraph_optimize): Make extern. 2009-10-03 Nathan Froyd <froydnj@codesourcery.com> - Kenneth Zadeck <zadeck@naturalbridge.com> + Kenneth Zadeck <zadeck@naturalbridge.com> * toplev.c (in_lto_p): Declare. * collect2.c (scan_prog_file): Read all the output when reading @@ -7142,7 +7142,7 @@ (gimple_eh_must_not_throw_set_fndecl): New. 2009-10-03 Jan Hubicka <jh@suse.cz> - Kenneth Zadeck <zadeck@naturalbridge.com> + Kenneth Zadeck <zadeck@naturalbridge.com> * ipa-pure-const.c: Include lto-streamer.h. (register_hooks): Factor out of ... diff --git a/gcc/ChangeLog-2011 b/gcc/ChangeLog-2011 index ce92ab2febb..75c04fca968 100644 --- a/gcc/ChangeLog-2011 +++ b/gcc/ChangeLog-2011 @@ -9270,7 +9270,7 @@ (sms_schedule): Adjust call to generate_reg_moves. Don't call free_undo_replace_buff. -2011-10-10 Matthias Klose <doko@ubuntu.com> +2011-10-10 Matthias Klose <doko@ubuntu.com> * common/config/m32c: Remove empty directory. @@ -13777,11 +13777,11 @@ * doc/extend.texi: Document AVX2 built-in functions. * doc/invoke.texi: Document -mavx2. -2011-08-22 Matthias Klose <doko@debian.org> +2011-08-22 Matthias Klose <doko@debian.org> Revert: 2011-07-11 Arthur Loiret <aloiret@debian.org> - Matthias Klose <doko@debian.org> + Matthias Klose <doko@debian.org> * config/mips/t-linux64 (MULTILIB_DIRNAMES): Set to 'n32 . 64' if tm_defines contains MIPS_ABI_DEFAULT ABI_32, to follow the glibc convention. @@ -18472,7 +18472,7 @@ PR middle-end/49736 * expr.c (all_zeros_p): Undo bogus part of last change. -2011-07-14 Matthias Klose <doko@ubuntu.com> +2011-07-14 Matthias Klose <doko@ubuntu.com> * doc/extend.texi (optimize attribute): Fix typo. @@ -18928,7 +18928,7 @@ --enable-targets=all. 2011-07-11 Arthur Loiret <aloiret@debian.org> - Matthias Klose <doko@debian.org> + Matthias Klose <doko@debian.org> * config.gcc (mips*-*-linux*): If 'enabled_targets' is 'all', build a tri-arch compiler defaulting to 32-bit (ABI o32). In this case: diff --git a/gcc/ChangeLog-2012 b/gcc/ChangeLog-2012 index ad72535e28d..900077783c9 100644 --- a/gcc/ChangeLog-2012 +++ b/gcc/ChangeLog-2012 @@ -4386,7 +4386,7 @@ * config/sh/sh.c (sh_can_use_simple_return_p): Enable with -freorder-blocks-and-partition. -2012-11-09 Kenneth Zadeck <zadeck@naturalbridge.com> +2012-11-09 Kenneth Zadeck <zadeck@naturalbridge.com> * rtl.h (CONST_SCALAR_INT_P): New macro. * cfgexpand.c (expand_debug_locations): Changed to use @@ -4712,7 +4712,7 @@ longer static. * tree-ssa-loop-ch.c (copy_loop_headers): Use it. -2012-11-06 Sterling Augustine <saugustine@google.com> +2012-11-06 Sterling Augustine <saugustine@google.com> * dwarf2out.c (output_comdat_type_unit): Check for OBJECT_FORMAT_ELF. @@ -4751,7 +4751,7 @@ * tree-ssa-tail-merge.c (find_duplicate): Do not consider is_tm_ending_fndecl calls as mergable. -2012-11-06 Sterling Augustine <saugustine@google.com> +2012-11-06 Sterling Augustine <saugustine@google.com> Cary Coutant <ccoutant@google.com> * common.opt (gno-split-dwarf, gsplit-dwarf): New switches. @@ -10738,7 +10738,7 @@ * config/i386/i386.c (ix86_rtx_costs): Limit > UNITS_PER_WORD AND/IOR/XOR cost calculation to MODE_INT class modes. -2012-09-18 Thomas Quinot <quinot@adacore.com> +2012-09-18 Thomas Quinot <quinot@adacore.com> * doc/invoke.texi: Document -fada-spec-parent. @@ -12749,7 +12749,7 @@ New constraints. * config/avr/avr.h (LONG_LONG_ACCUM_TYPE_SIZE): Define. -2012-08-23 Kenneth Zadeck <zadeck@naturalbridge.com> +2012-08-23 Kenneth Zadeck <zadeck@naturalbridge.com> * alias.c (rtx_equal_for_memref_p): Convert constant cases. * combine.c (find_single_use_1, mark_used_regs_combine): Convert @@ -15922,7 +15922,7 @@ alignment requirements given the known alignment of dynamic_offset. * function.c (instantiate_virtual_regs): Align dtnamic_offset. -2012-08-02 Kenneth Zadeck <zadeck@naturalbridge.com> +2012-08-02 Kenneth Zadeck <zadeck@naturalbridge.com> * cfgexpand.c (expand_debug_locations): Encapsulate test for CONST_DOUBLE in macro. @@ -20452,7 +20452,7 @@ * var-tracking.c (vt_add_function_parameter): Use a preserved VALUE for the MEM address of an incoming parameter. -2012-06-26 Sterling Augustine <saugustine@google.com> +2012-06-26 Sterling Augustine <saugustine@google.com> * dwarf2out.c (output_pubnames): Add check for DW_TAG_enumerator. (prune_unused_types): Likewise. @@ -22305,7 +22305,7 @@ Place new pass_jump2 after pass_stack_adjustments. * tree-pass.h (pass_jump): Declare. -2012-06-09 Kenneth Zadeck <zadeck@naturalbridge.com> +2012-06-09 Kenneth Zadeck <zadeck@naturalbridge.com> * simplify-rtx.c (simplify_const_binary_operation): Fixed shift count trucation. @@ -22716,7 +22716,7 @@ * config/sparc/sparc-protos.h (sparc_initial_elimination_offset): Prototype it. -2012-06-02 Kenneth Zadeck <zadeck@naturalbridge.com> +2012-06-02 Kenneth Zadeck <zadeck@naturalbridge.com> * expmed.c (expand_mult, choose_multiplier): Change "2 * HOST_BITS_PER_WIDE_INT" to "HOST_BITS_PER_DOUBLE_INT". diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index ab8590227a9..6e5286a0dd2 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20131020 +20131104 diff --git a/gcc/Makefile.in b/gcc/Makefile.in index add63e3e1cd..48c6be26246 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -311,7 +311,7 @@ write_entries_to_file = $(shell rm -f $(2) || :) $(shell touch $(2)) \ # -------- # Dependency tracking stuff. -CCDEPMODE = @CCDEPMODE@ +CXXDEPMODE = @CXXDEPMODE@ DEPDIR = @DEPDIR@ depcomp = $(SHELL) $(srcdir)/../depcomp @@ -872,7 +872,7 @@ RTL_H = $(RTL_BASE_H) $(FLAGS_H) genrtl.h wide-int.h READ_MD_H = $(OBSTACK_H) $(HASHTAB_H) read-md.h PARAMS_H = params.h params.def BUILTINS_DEF = builtins.def sync-builtins.def omp-builtins.def \ - gtm-builtins.def sanitizer.def cilkplus.def + gtm-builtins.def sanitizer.def cilkplus.def cilk-builtins.def INTERNAL_FN_DEF = internal-fn.def INTERNAL_FN_H = internal-fn.h $(INTERNAL_FN_DEF) TREE_CORE_H = tree-core.h coretypes.h all-tree.def tree.def \ @@ -1040,7 +1040,7 @@ INCLUDES = -I. -I$(@D) -I$(srcdir) -I$(srcdir)/$(@D) \ $(CLOOGINC) $(ISLINC) COMPILE.base = $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) -o $@ -ifeq ($(CCDEPMODE),depmode=gcc3) +ifeq ($(CXXDEPMODE),depmode=gcc3) # Note a subtlety here: we use $(@D) for the directory part, to make # things like the go/%.o rule work properly; but we use $(*F) for the # file part, as we just want the file part of the stem, not the entire @@ -1049,7 +1049,7 @@ COMPILE = $(COMPILE.base) -MT $@ -MMD -MP -MF $(@D)/$(DEPDIR)/$(*F).TPo POSTCOMPILE = @mv $(@D)/$(DEPDIR)/$(*F).TPo $(@D)/$(DEPDIR)/$(*F).Po else COMPILE = source='$<' object='$@' libtool=no \ - DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) $(COMPILE.base) + DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) $(COMPILE.base) POSTCOMPILE = endif @@ -1132,15 +1132,12 @@ GCC_OBJS = gcc.o ggc-none.o c-family-warn = $(STRICT_WARN) # Language-specific object files shared by all C-family front ends. -# FIXME: tree-mudflap is C-family only, but it is also part of the middle-end. -# The mudflap machinery should be properly separated from the front ends, and -# perhaps turned into a plugin. C_COMMON_OBJS = c-family/c-common.o c-family/c-cppbuiltin.o c-family/c-dump.o \ c-family/c-format.o c-family/c-gimplify.o c-family/c-lex.o \ c-family/c-omp.o c-family/c-opts.o c-family/c-pch.o \ c-family/c-ppoutput.o c-family/c-pragma.o c-family/c-pretty-print.o \ - c-family/c-semantics.o c-family/c-ada-spec.o tree-mudflap.o \ - c-family/array-notation-common.o c-family/c-ubsan.o + c-family/c-semantics.o c-family/c-ada-spec.o \ + c-family/array-notation-common.o c-family/cilk.o c-family/c-ubsan.o # Language-independent object files. # We put the insn-*.o files first so that a parallel make will build @@ -1185,6 +1182,7 @@ OBJS = \ cgraphbuild.o \ cgraphunit.o \ cgraphclones.o \ + cilk-common.o \ combine.o \ combine-stack-adj.o \ compare-elim.o \ @@ -1330,7 +1328,6 @@ OBJS = \ reg-stack.o \ regcprop.o \ reginfo.o \ - regmove.o \ regrename.o \ regstat.o \ reload.o \ @@ -1388,7 +1385,6 @@ OBJS = \ tree-iterator.o \ tree-loop-distribution.o \ tree-nested.o \ - tree-nomudflap.o \ tree-nrv.o \ tree-object-size.o \ tree-outof-ssa.o \ @@ -2255,7 +2251,7 @@ GTFILES = $(CPP_ID_DATA_H) $(srcdir)/input.h $(srcdir)/coretypes.h \ $(srcdir)/sdbout.c $(srcdir)/stor-layout.c \ $(srcdir)/stringpool.c $(srcdir)/tree.c $(srcdir)/varasm.c \ $(srcdir)/gimple.h \ - $(srcdir)/tree-mudflap.c $(srcdir)/gimple-ssa.h \ + $(srcdir)/gimple-ssa.h \ $(srcdir)/tree-ssanames.c $(srcdir)/tree-eh.c $(srcdir)/tree-ssa-address.c \ $(srcdir)/tree-cfg.c \ $(srcdir)/tree-dfa.c \ diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index cc462e9c4a7..44d04845b9e 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,21 @@ +2013-10-30 Sharad Singhai <singhai@google.com> + + * gnat_ugn.texi: Remove option description for PR middle-end/58134. + +2013-10-29 David Malcolm <dmalcolm@redhat.com> + + * gcc-interface/trans.c (finalize_nrv): Update for conversion of + symtab types to a true class hierarchy. + * gcc-interface/utils.c (gnat_write_global_declarations): Likewise. + +2013-10-28 Trevor Saunders <tsaunders@mozilla.com> + + * gcc-interface/decl.c (components_to_record): Adjust stack vector. + +2013-10-24 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + * gcc-interface/Make-lang.in (ADA_DEPS): Fix quoting. + 2013-10-19 Thomas Quinot <quinot@adacore.com> * gcc-interface/Makefile.in: Use canonical absolute path to refer to @@ -3657,7 +3675,7 @@ * gcc-interface/decl.c (gnat_to_gnu_entity) <E_Array_Subtype>: Use int_const_binop to shift bounds by 1 when they are integer constants. -2013-04-25 Arnaud Charlet <charlet@adacore.com>> +2013-04-25 Arnaud Charlet <charlet@adacore.com> * gcc-interface/Makefile.in (ADA_EXCLUDE_SRCS): Exclude s-init.ad{s,b} @@ -7343,7 +7361,7 @@ accept an aspect name followed by a comma, indicating a defaulted boolean aspect. -2013-01-04 Joel Brobecker <brobecker@adacore.com brobecker> +2013-01-04 Joel Brobecker <brobecker@adacore.com> * gnat_ugn.texi: Document procedure to codesign GDB on Darwin. Update doc on gnattest --separates switch. diff --git a/gcc/ada/ChangeLog-2010 b/gcc/ada/ChangeLog-2010 index 6c1aa5932a7..8b372f5acda 100644 --- a/gcc/ada/ChangeLog-2010 +++ b/gcc/ada/ChangeLog-2010 @@ -7983,7 +7983,7 @@ * freeze.adb: Minor reformatting. -2010-06-17 Joel Brobecker <brobecker@adacore.com brobecker> +2010-06-17 Joel Brobecker <brobecker@adacore.com> * gnat_ugn.texi: Add a section introducing gdbserver. @@ -8032,7 +8032,7 @@ * par-labl.adb (Try_Loop): Test whether the label and the goto are in the same list. -2010-06-17 Joel Brobecker <brobecker@adacore.com brobecker> +2010-06-17 Joel Brobecker <brobecker@adacore.com> * gnat_ugn.texi: Update the documentation about GDB re: exception catchpoints. diff --git a/gcc/ada/ChangeLog-2011 b/gcc/ada/ChangeLog-2011 index 7f5f6f9aa5f..d6dd46a2e79 100644 --- a/gcc/ada/ChangeLog-2011 +++ b/gcc/ada/ChangeLog-2011 @@ -11415,7 +11415,7 @@ * sem_ch8.adb (Is_Primitive_Operator_In_Use): Always check In_Use on the Base_Type. -2011-08-03 Joel Brobecker <brobecker@adacore.com brobecker> +2011-08-03 Joel Brobecker <brobecker@adacore.com> * g-sha256.ads, g-sha512.ads, g-sha1.ads, g-sha224.ads, g-sha384.ads, g-sehash.ads: Fix typo. Update header. diff --git a/gcc/ada/ChangeLog-2012 b/gcc/ada/ChangeLog-2012 index 2bb659a52de..4949e047dbf 100644 --- a/gcc/ada/ChangeLog-2012 +++ b/gcc/ada/ChangeLog-2012 @@ -4452,7 +4452,7 @@ return for unknown exceptions. * raise-gcc.c (__gnat_personality_seh0): Call __gnat_SEH_error_handler. -2012-07-09 Joel Brobecker <brobecker@adacore.com brobecker> +2012-07-09 Joel Brobecker <brobecker@adacore.com> * exp_dbug.ads (No_Dollar_In_Label): Delete. diff --git a/gcc/ada/gcc-interface/Make-lang.in b/gcc/ada/gcc-interface/Make-lang.in index 74eff664618..cd3676f9447 100644 --- a/gcc/ada/gcc-interface/Make-lang.in +++ b/gcc/ada/gcc-interface/Make-lang.in @@ -110,7 +110,7 @@ ADA_DEPS=case $@ in \ *sdefault.o);; \ *)a="`echo $@ | sed -e 's/.o$$/.ali/'`"; \ echo "$@: `cat $$a | \ - sed -ne "s;^D \([a-z0-9_\.-]*\).*;ada/\1;gp" | \ + sed -ne 's;^D \([a-z0-9_\.-]*\).*;ada/\1;gp' | \ tr -d '\015' | tr '\n' ' '`" > $(dir $@)/$(DEPDIR)/$(patsubst %.o,%.Po,$(notdir $@));; \ esac; diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c index fe64905adab..360d31b34c5 100644 --- a/gcc/ada/gcc-interface/decl.c +++ b/gcc/ada/gcc-interface/decl.c @@ -7003,13 +7003,11 @@ components_to_record (tree gnu_record_type, Node_Id gnat_component_list, tree gnu_union_type, gnu_union_name; tree this_first_free_pos, gnu_variant_list = NULL_TREE; bool union_field_needs_strict_alignment = false; - vec <vinfo_t, va_stack> variant_types; + stack_vec <vinfo_t, 16> variant_types; vinfo_t *gnu_variant; unsigned int variants_align = 0; unsigned int i; - vec_stack_alloc (vinfo_t, variant_types, 16); - if (TREE_CODE (gnu_name) == TYPE_DECL) gnu_name = DECL_NAME (gnu_name); @@ -7205,9 +7203,6 @@ components_to_record (tree gnu_record_type, Node_Id gnat_component_list, gnu_variant_list = gnu_field; } - /* We are done with the variants. */ - variant_types.release (); - /* Only make the QUAL_UNION_TYPE if there are non-empty variants. */ if (gnu_variant_list) { diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c index b283b561c38..118f9f223dc 100644 --- a/gcc/ada/gcc-interface/trans.c +++ b/gcc/ada/gcc-interface/trans.c @@ -3246,7 +3246,7 @@ finalize_nrv (tree fndecl, bitmap nrv, vec<tree, va_gc> *other, Node_Id gnat_ret /* Prune also the candidates that are referenced by nested functions. */ node = cgraph_get_create_node (fndecl); for (node = node->nested; node; node = node->next_nested) - walk_tree_without_duplicates (&DECL_SAVED_TREE (node->symbol.decl), prune_nrv_r, + walk_tree_without_duplicates (&DECL_SAVED_TREE (node->decl), prune_nrv_r, &data); if (bitmap_empty_p (nrv)) return; diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c index 0998c5b4a8c..0a65f369464 100644 --- a/gcc/ada/gcc-interface/utils.c +++ b/gcc/ada/gcc-interface/utils.c @@ -5633,7 +5633,7 @@ gnat_write_global_declarations (void) TREE_STATIC (dummy_global) = 1; TREE_ASM_WRITTEN (dummy_global) = 1; node = varpool_node_for_decl (dummy_global); - node->symbol.force_output = 1; + node->force_output = 1; while (!types_used_by_cur_var_decl->is_empty ()) { diff --git a/gcc/ada/gnat_ugn.texi b/gcc/ada/gnat_ugn.texi index a82f20b08c7..edb3886a03a 100644 --- a/gcc/ada/gnat_ugn.texi +++ b/gcc/ada/gnat_ugn.texi @@ -10696,11 +10696,6 @@ preferably to other optimizations by means of pragma @code{Loop_Optimize}: placed immediately within the loop will convey the appropriate hint to the compiler for this loop. -You can obtain information about the vectorization performed by the compiler -by specifying @option{-ftree-vectorizer-verbose=N}. For more details of -this switch, see @ref{Debugging Options,,Options for Debugging Your Program -or GCC, gcc, Using the GNU Compiler Collection (GCC)}. - @node Other Optimization Switches @subsection Other Optimization Switches @cindex Optimization Switches diff --git a/gcc/alias.c b/gcc/alias.c index 7af29b3b664..8a66d2baa44 100644 --- a/gcc/alias.c +++ b/gcc/alias.c @@ -40,11 +40,11 @@ along with GCC; see the file COPYING3. If not see #include "timevar.h" #include "dumpfile.h" #include "target.h" -#include "cgraph.h" #include "df.h" #include "tree-ssa-alias.h" #include "pointer-set.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "gimple-ssa.h" /* The aliasing API provided here solves related but different problems: @@ -2981,16 +2981,13 @@ init_alias_analysis (void) /* Wipe the reg_seen array clean. */ bitmap_clear (reg_seen); - /* Mark all hard registers which may contain an address. - The stack, frame and argument pointers may contain an address. - An argument register which can hold a Pmode value may contain - an address even if it is not in BASE_REGS. - - The address expression is VOIDmode for an argument and - Pmode for other registers. */ - - memcpy (new_reg_base_value, static_reg_base_value, - FIRST_PSEUDO_REGISTER * sizeof (rtx)); + /* Initialize the alias information for this pass. */ + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + if (static_reg_base_value[i]) + { + new_reg_base_value[i] = static_reg_base_value[i]; + bitmap_set_bit (reg_seen, i); + } /* Walk the insns adding values to the new_reg_base_value array. */ for (i = 0; i < rpo_cnt; i++) diff --git a/gcc/asan.c b/gcc/asan.c index 84c603ac521..5dcc981cd06 100644 --- a/gcc/asan.c +++ b/gcc/asan.c @@ -22,9 +22,11 @@ along with GCC; see the file COPYING3. If not see #include "config.h" #include "system.h" #include "coretypes.h" +#include "tree.h" #include "gimple.h" #include "tree-iterator.h" -#include "tree-ssa.h" +#include "cgraph.h" +#include "tree-ssanames.h" #include "tree-pass.h" #include "asan.h" #include "gimple-pretty-print.h" @@ -896,7 +898,7 @@ asan_clear_shadow (rtx shadow_mem, HOST_WIDE_INT len) gcc_assert ((len & 3) == 0); top_label = gen_label_rtx (); - addr = force_reg (Pmode, XEXP (shadow_mem, 0)); + addr = copy_to_mode_reg (Pmode, XEXP (shadow_mem, 0)); shadow_mem = adjust_automodify_address (shadow_mem, SImode, addr, 0); end = force_reg (Pmode, plus_constant (Pmode, addr, len)); emit_label (top_label); @@ -2019,6 +2021,9 @@ initialize_sanitizer_builtins (void) tree BT_FN_VOID = build_function_type_list (void_type_node, NULL_TREE); tree BT_FN_VOID_PTR = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE); + tree BT_FN_VOID_PTR_PTR + = build_function_type_list (void_type_node, ptr_type_node, + ptr_type_node, NULL_TREE); tree BT_FN_VOID_PTR_PTR_PTR = build_function_type_list (void_type_node, ptr_type_node, ptr_type_node, ptr_type_node, NULL_TREE); @@ -2173,8 +2178,8 @@ asan_finish_file (void) tree fn = builtin_decl_implicit (BUILT_IN_ASAN_INIT); append_to_statement_list (build_call_expr (fn, 0), &asan_ctor_statements); FOR_EACH_DEFINED_VARIABLE (vnode) - if (TREE_ASM_WRITTEN (vnode->symbol.decl) - && asan_protect_global (vnode->symbol.decl)) + if (TREE_ASM_WRITTEN (vnode->decl) + && asan_protect_global (vnode->decl)) ++gcount; htab_t const_desc_htab = constant_pool_htab (); htab_traverse (const_desc_htab, count_string_csts, &gcount); @@ -2195,9 +2200,9 @@ asan_finish_file (void) DECL_IGNORED_P (var) = 1; vec_alloc (v, gcount); FOR_EACH_DEFINED_VARIABLE (vnode) - if (TREE_ASM_WRITTEN (vnode->symbol.decl) - && asan_protect_global (vnode->symbol.decl)) - asan_add_global (vnode->symbol.decl, TREE_TYPE (type), v); + if (TREE_ASM_WRITTEN (vnode->decl) + && asan_protect_global (vnode->decl)) + asan_add_global (vnode->decl, TREE_TYPE (type), v); struct asan_add_string_csts_data aascd; aascd.type = TREE_TYPE (type); aascd.v = v; diff --git a/gcc/basic-block.h b/gcc/basic-block.h index f0820b297d0..c88a39de507 100644 --- a/gcc/basic-block.h +++ b/gcc/basic-block.h @@ -795,6 +795,8 @@ extern void connect_infinite_loops_to_exit (void); extern int post_order_compute (int *, bool, bool); extern basic_block dfs_find_deadend (basic_block); extern int inverted_post_order_compute (int *); +extern int pre_and_rev_post_order_compute_fn (struct function *, + int *, int *, bool); extern int pre_and_rev_post_order_compute (int *, int *, bool); extern int dfs_enumerate_from (basic_block, int, bool (*)(const_basic_block, const void *), diff --git a/gcc/bb-reorder.c b/gcc/bb-reorder.c index c5a42d359dc..8e2348f476c 100644 --- a/gcc/bb-reorder.c +++ b/gcc/bb-reorder.c @@ -82,6 +82,7 @@ #include "system.h" #include "coretypes.h" #include "tm.h" +#include "tree.h" #include "rtl.h" #include "regs.h" #include "flags.h" diff --git a/gcc/builtin-types.def b/gcc/builtin-types.def index 3deedba5b78..1f9ae4e2317 100644 --- a/gcc/builtin-types.def +++ b/gcc/builtin-types.def @@ -226,6 +226,7 @@ DEF_FUNCTION_TYPE_1 (BT_FN_DFLOAT64_DFLOAT64, BT_DFLOAT64, BT_DFLOAT64) DEF_FUNCTION_TYPE_1 (BT_FN_DFLOAT128_DFLOAT128, BT_DFLOAT128, BT_DFLOAT128) DEF_FUNCTION_TYPE_1 (BT_FN_VOID_VPTR, BT_VOID, BT_VOLATILE_PTR) DEF_FUNCTION_TYPE_1 (BT_FN_VOID_PTRPTR, BT_VOID, BT_PTR_PTR) +DEF_FUNCTION_TYPE_1 (BT_FN_VOID_CONST_PTR, BT_VOID, BT_CONST_PTR) DEF_FUNCTION_TYPE_1 (BT_FN_UINT_UINT, BT_UINT, BT_UINT) DEF_FUNCTION_TYPE_1 (BT_FN_ULONG_ULONG, BT_ULONG, BT_ULONG) DEF_FUNCTION_TYPE_1 (BT_FN_ULONGLONG_ULONGLONG, BT_ULONGLONG, BT_ULONGLONG) @@ -233,6 +234,8 @@ DEF_FUNCTION_TYPE_1 (BT_FN_UINT16_UINT16, BT_UINT16, BT_UINT16) DEF_FUNCTION_TYPE_1 (BT_FN_UINT32_UINT32, BT_UINT32, BT_UINT32) DEF_FUNCTION_TYPE_1 (BT_FN_UINT64_UINT64, BT_UINT64, BT_UINT64) DEF_FUNCTION_TYPE_1 (BT_FN_BOOL_INT, BT_BOOL, BT_INT) +DEF_FUNCTION_TYPE_1 (BT_FN_PTR_CONST_PTR, BT_PTR, BT_CONST_PTR) +DEF_FUNCTION_TYPE_1 (BT_FN_CONST_PTR_CONST_PTR, BT_CONST_PTR, BT_CONST_PTR) DEF_POINTER_TYPE (BT_PTR_FN_VOID_PTR, BT_FN_VOID_PTR) @@ -346,6 +349,10 @@ DEF_FUNCTION_TYPE_2 (BT_FN_BOOL_SIZE_CONST_VPTR, BT_BOOL, BT_SIZE, BT_CONST_VOLATILE_PTR) DEF_FUNCTION_TYPE_2 (BT_FN_BOOL_INT_BOOL, BT_BOOL, BT_INT, BT_BOOL) DEF_FUNCTION_TYPE_2 (BT_FN_VOID_UINT_UINT, BT_VOID, BT_UINT, BT_UINT) +DEF_FUNCTION_TYPE_2 (BT_FN_PTR_CONST_PTR_SIZE, BT_PTR, BT_CONST_PTR, BT_SIZE) +DEF_FUNCTION_TYPE_2 (BT_FN_PTR_CONST_PTR_CONST_PTR, BT_PTR, BT_CONST_PTR, BT_CONST_PTR) +DEF_FUNCTION_TYPE_2 (BT_FN_VOID_PTRPTR_CONST_PTR, BT_VOID, BT_PTR_PTR, BT_CONST_PTR) +DEF_FUNCTION_TYPE_2 (BT_FN_VOID_CONST_PTR_SIZE, BT_VOID, BT_CONST_PTR, BT_SIZE) DEF_POINTER_TYPE (BT_PTR_FN_VOID_PTR_PTR, BT_FN_VOID_PTR_PTR) @@ -428,6 +435,7 @@ DEF_FUNCTION_TYPE_3 (BT_FN_VOID_VPTR_I2_INT, BT_VOID, BT_VOLATILE_PTR, BT_I2, BT DEF_FUNCTION_TYPE_3 (BT_FN_VOID_VPTR_I4_INT, BT_VOID, BT_VOLATILE_PTR, BT_I4, BT_INT) DEF_FUNCTION_TYPE_3 (BT_FN_VOID_VPTR_I8_INT, BT_VOID, BT_VOLATILE_PTR, BT_I8, BT_INT) DEF_FUNCTION_TYPE_3 (BT_FN_VOID_VPTR_I16_INT, BT_VOID, BT_VOLATILE_PTR, BT_I16, BT_INT) +DEF_FUNCTION_TYPE_3 (BT_FN_PTR_CONST_PTR_CONST_PTR_SIZE, BT_PTR, BT_CONST_PTR, BT_CONST_PTR, BT_SIZE) DEF_FUNCTION_TYPE_4 (BT_FN_SIZE_CONST_PTR_SIZE_SIZE_FILEPTR, BT_SIZE, BT_CONST_PTR, BT_SIZE, BT_SIZE, BT_FILEPTR) diff --git a/gcc/builtins.c b/gcc/builtins.c index 77670f10fb1..1c3398353df 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -43,11 +43,13 @@ along with GCC; see the file COPYING3. If not see #include "target.h" #include "langhooks.h" #include "basic-block.h" -#include "tree-ssa.h" +#include "tree-ssanames.h" +#include "tree-dfa.h" #include "value-prof.h" #include "diagnostic-core.h" #include "builtins.h" #include "ubsan.h" +#include "cilk.h" static tree do_mpc_arg1 (tree, tree, int (*)(mpc_ptr, mpc_srcptr, mpc_rnd_t)); @@ -234,6 +236,10 @@ is_builtin_name (const char *name) return true; if (strncmp (name, "__atomic_", 9) == 0) return true; + if (flag_enable_cilkplus + && (!strcmp (name, "__cilkrts_detach") + || !strcmp (name, "__cilkrts_pop_frame"))) + return true; return false; } @@ -308,7 +314,7 @@ get_object_alignment_2 (tree exp, unsigned int *alignp, tree offset; enum machine_mode mode; int unsignedp, volatilep; - unsigned int inner, align = BITS_PER_UNIT; + unsigned int align = BITS_PER_UNIT; bool known_alignment = false; /* Get the innermost object and the constant (bitpos) and possibly @@ -417,50 +423,16 @@ get_object_alignment_2 (tree exp, unsigned int *alignp, /* If there is a non-constant offset part extract the maximum alignment that can prevail. */ - inner = ~0U; - while (offset) + if (offset) { - tree next_offset; - - if (TREE_CODE (offset) == PLUS_EXPR) - { - next_offset = TREE_OPERAND (offset, 0); - offset = TREE_OPERAND (offset, 1); - } - else - next_offset = NULL; - if (tree_fits_uhwi_p (offset)) + int trailing_zeros = tree_ctz (offset); + if (trailing_zeros < HOST_BITS_PER_INT) { - /* Any overflow in calculating offset_bits won't change - the alignment. */ - unsigned offset_bits - = ((unsigned) tree_to_uhwi (offset) * BITS_PER_UNIT); - - if (offset_bits) - inner = MIN (inner, (offset_bits & -offset_bits)); + unsigned int inner = (1U << trailing_zeros) * BITS_PER_UNIT; + if (inner) + align = MIN (align, inner); } - else if (TREE_CODE (offset) == MULT_EXPR - && tree_fits_uhwi_p (TREE_OPERAND (offset, 1))) - { - /* Any overflow in calculating offset_factor won't change - the alignment. */ - unsigned offset_factor - = ((unsigned) tree_to_uhwi (TREE_OPERAND (offset, 1)) - * BITS_PER_UNIT); - - if (offset_factor) - inner = MIN (inner, (offset_factor & -offset_factor)); - } - else - { - inner = MIN (inner, BITS_PER_UNIT); - break; - } - offset = next_offset; } - /* Alignment is innermost object alignment adjusted by the constant - and non-constant offset parts. */ - align = MIN (align, inner); *alignp = align; *bitposp = bitpos & (*alignp - 1); @@ -4239,110 +4211,6 @@ expand_builtin_va_start (tree exp) return const0_rtx; } - -/* Return a dummy expression of type TYPE in order to keep going after an - error. */ - -static tree -dummy_object (tree type) -{ - tree t = build_int_cst (build_pointer_type (type), 0); - return build2 (MEM_REF, type, t, t); -} - -/* Gimplify __builtin_va_arg, aka VA_ARG_EXPR, which is not really a - builtin function, but a very special sort of operator. */ - -enum gimplify_status -gimplify_va_arg_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) -{ - tree promoted_type, have_va_type; - tree valist = TREE_OPERAND (*expr_p, 0); - tree type = TREE_TYPE (*expr_p); - tree t; - location_t loc = EXPR_LOCATION (*expr_p); - - /* Verify that valist is of the proper type. */ - have_va_type = TREE_TYPE (valist); - if (have_va_type == error_mark_node) - return GS_ERROR; - have_va_type = targetm.canonical_va_list_type (have_va_type); - - if (have_va_type == NULL_TREE) - { - error_at (loc, "first argument to %<va_arg%> not of type %<va_list%>"); - return GS_ERROR; - } - - /* Generate a diagnostic for requesting data of a type that cannot - be passed through `...' due to type promotion at the call site. */ - if ((promoted_type = lang_hooks.types.type_promotes_to (type)) - != type) - { - static bool gave_help; - bool warned; - - /* Unfortunately, this is merely undefined, rather than a constraint - violation, so we cannot make this an error. If this call is never - executed, the program is still strictly conforming. */ - warned = warning_at (loc, 0, - "%qT is promoted to %qT when passed through %<...%>", - type, promoted_type); - if (!gave_help && warned) - { - gave_help = true; - inform (loc, "(so you should pass %qT not %qT to %<va_arg%>)", - promoted_type, type); - } - - /* We can, however, treat "undefined" any way we please. - Call abort to encourage the user to fix the program. */ - if (warned) - inform (loc, "if this code is reached, the program will abort"); - /* Before the abort, allow the evaluation of the va_list - expression to exit or longjmp. */ - gimplify_and_add (valist, pre_p); - t = build_call_expr_loc (loc, - builtin_decl_implicit (BUILT_IN_TRAP), 0); - gimplify_and_add (t, pre_p); - - /* This is dead code, but go ahead and finish so that the - mode of the result comes out right. */ - *expr_p = dummy_object (type); - return GS_ALL_DONE; - } - else - { - /* Make it easier for the backends by protecting the valist argument - from multiple evaluations. */ - if (TREE_CODE (have_va_type) == ARRAY_TYPE) - { - /* For this case, the backends will be expecting a pointer to - TREE_TYPE (abi), but it's possible we've - actually been given an array (an actual TARGET_FN_ABI_VA_LIST). - So fix it. */ - if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE) - { - tree p1 = build_pointer_type (TREE_TYPE (have_va_type)); - valist = fold_convert_loc (loc, p1, - build_fold_addr_expr_loc (loc, valist)); - } - - gimplify_expr (&valist, pre_p, post_p, is_gimple_val, fb_rvalue); - } - else - gimplify_expr (&valist, pre_p, post_p, is_gimple_min_lval, fb_lvalue); - - if (!targetm.gimplify_va_arg_expr) - /* FIXME: Once most targets are converted we should merely - assert this is non-null. */ - return GS_ALL_DONE; - - *expr_p = targetm.gimplify_va_arg_expr (valist, type, pre_p, post_p); - return GS_OK; - } -} - /* Expand EXP, a call to __builtin_va_end. */ static rtx @@ -4471,10 +4339,6 @@ expand_builtin_alloca (tree exp, bool cannot_accumulate) bool alloca_with_align = (DECL_FUNCTION_CODE (get_callee_fndecl (exp)) == BUILT_IN_ALLOCA_WITH_ALIGN); - /* Emit normal call if we use mudflap. */ - if (flag_mudflap) - return NULL_RTX; - valid_arglist = (alloca_with_align ? validate_arglist (exp, INTEGER_TYPE, INTEGER_TYPE, VOID_TYPE) @@ -5754,7 +5618,18 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, && fcode != BUILT_IN_EXECVE && fcode != BUILT_IN_ALLOCA && fcode != BUILT_IN_ALLOCA_WITH_ALIGN - && fcode != BUILT_IN_FREE) + && fcode != BUILT_IN_FREE + && fcode != BUILT_IN_CHKP_SET_PTR_BOUNDS + && fcode != BUILT_IN_CHKP_INIT_PTR_BOUNDS + && fcode != BUILT_IN_CHKP_NULL_PTR_BOUNDS + && fcode != BUILT_IN_CHKP_COPY_PTR_BOUNDS + && fcode != BUILT_IN_CHKP_NARROW_PTR_BOUNDS + && fcode != BUILT_IN_CHKP_STORE_PTR_BOUNDS + && fcode != BUILT_IN_CHKP_CHECK_PTR_LBOUNDS + && fcode != BUILT_IN_CHKP_CHECK_PTR_UBOUNDS + && fcode != BUILT_IN_CHKP_CHECK_PTR_BOUNDS + && fcode != BUILT_IN_CHKP_GET_PTR_LBOUND + && fcode != BUILT_IN_CHKP_GET_PTR_UBOUND) return expand_call (exp, target, ignore); /* The built-in function expanders test for target == const0_rtx @@ -6798,6 +6673,59 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, expand_builtin_set_thread_pointer (exp); return const0_rtx; + case BUILT_IN_CILK_DETACH: + expand_builtin_cilk_detach (exp); + return const0_rtx; + + case BUILT_IN_CILK_POP_FRAME: + expand_builtin_cilk_pop_frame (exp); + return const0_rtx; + + case BUILT_IN_CHKP_INIT_PTR_BOUNDS: + case BUILT_IN_CHKP_NULL_PTR_BOUNDS: + case BUILT_IN_CHKP_COPY_PTR_BOUNDS: + return expand_normal (CALL_EXPR_ARG (exp, 0)); + + case BUILT_IN_CHKP_CHECK_PTR_LBOUNDS: + case BUILT_IN_CHKP_CHECK_PTR_UBOUNDS: + case BUILT_IN_CHKP_CHECK_PTR_BOUNDS: + case BUILT_IN_CHKP_SET_PTR_BOUNDS: + case BUILT_IN_CHKP_NARROW_PTR_BOUNDS: + case BUILT_IN_CHKP_STORE_PTR_BOUNDS: + case BUILT_IN_CHKP_GET_PTR_LBOUND: + case BUILT_IN_CHKP_GET_PTR_UBOUND: + /* We allow user CHKP builtins if Pointer Bounds + Checker is off. */ + if (!flag_check_pointer_bounds) + { + if (fcode == BUILT_IN_CHKP_SET_PTR_BOUNDS + || fcode == BUILT_IN_CHKP_NARROW_PTR_BOUNDS) + return expand_normal (CALL_EXPR_ARG (exp, 0)); + else if (fcode == BUILT_IN_CHKP_GET_PTR_LBOUND) + return expand_normal (size_zero_node); + else if (fcode == BUILT_IN_CHKP_GET_PTR_UBOUND) + return expand_normal (size_int (-1)); + else + return const0_rtx; + } + /* FALLTHROUGH */ + + case BUILT_IN_CHKP_BNDMK: + case BUILT_IN_CHKP_BNDSTX: + case BUILT_IN_CHKP_BNDCL: + case BUILT_IN_CHKP_BNDCU: + case BUILT_IN_CHKP_BNDLDX: + case BUILT_IN_CHKP_BNDRET: + case BUILT_IN_CHKP_INTERSECT: + case BUILT_IN_CHKP_ARG_BND: + case BUILT_IN_CHKP_NARROW: + case BUILT_IN_CHKP_EXTRACT_LOWER: + case BUILT_IN_CHKP_EXTRACT_UPPER: + /* Software implementation of pointers checker is NYI. + Target support is required. */ + error ("Your target platform does not support -fcheck-pointers"); + break; + default: /* just do library call, if unknown builtin */ break; } diff --git a/gcc/builtins.def b/gcc/builtins.def index 8ccf3ae3578..e2d8849c768 100644 --- a/gcc/builtins.def +++ b/gcc/builtins.def @@ -147,6 +147,13 @@ along with GCC; see the file COPYING3. If not see false, true, true, ATTRS, false, \ (flag_openmp || flag_tree_parallelize_loops)) +/* Builtin used by implementation of Cilk Plus. Most of these are decomposed + by the compiler but a few are implemented in libcilkrts. */ +#undef DEF_CILK_BUILTIN_STUB +#define DEF_CILK_BUILTIN_STUB(ENUM, NAME) \ + DEF_BUILTIN (ENUM, NAME, BUILT_IN_NORMAL, BT_LAST, BT_LAST, false, false, \ + false, ATTR_LAST, false, false) + /* Builtin used by the implementation of GNU TM. These functions are mapped to the actual implementation of the STM library. */ #undef DEF_TM_BUILTIN @@ -169,6 +176,12 @@ along with GCC; see the file COPYING3. If not see DEF_BUILTIN (ENUM, NAME, BUILT_IN_NORMAL, BT_FN_INT_VAR, BT_LAST, \ false, false, false, ATTRS, false, flag_enable_cilkplus) +/* Builtin used by the implementation of Pointer Bounds Checker. */ +#undef DEF_CHKP_BUILTIN +#define DEF_CHKP_BUILTIN(ENUM, NAME, TYPE, ATTRS) \ + DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \ + true, true, false, ATTRS, true, true) + /* Define an attribute list for math functions that are normally "impure" because some of them may write into global memory for `errno'. If !flag_errno_math they are instead "const". */ @@ -846,6 +859,9 @@ DEF_GCC_BUILTIN (BUILT_IN_LINE, "LINE", BT_FN_INT, ATTR_NOTHROW_LEAF_LIST) /* OpenMP builtins. */ #include "omp-builtins.def" +/* Cilk keywords builtins. */ +#include "cilk-builtins.def" + /* GTM builtins. */ #include "gtm-builtins.def" @@ -854,3 +870,6 @@ DEF_GCC_BUILTIN (BUILT_IN_LINE, "LINE", BT_FN_INT, ATTR_NOTHROW_LEAF_LIST) /* Cilk Plus builtins. */ #include "cilkplus.def" + +/* Pointer Bounds Checker builtins. */ +#include "chkp-builtins.def" diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 106bfa8c8c8..067c1341180 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,120 @@ +2013-11-04 Marek Polacek <polacek@redhat.com> + + PR c++/58979 + * c-common.c (invalid_indirection_error): Handle RO_ARROW_STAR case. + +2013-11-04 Joseph Myers <joseph@codesourcery.com> + + * c-cppbuiltin.c (cpp_iec_559_value, cpp_iec_559_complex_value): + New functions. + (c_cpp_builtins): Define __GCC_IEC_559 and __GCC_IEC_559_COMPLEX. + +2013-11-04 Eric Botcazou <ebotcazou@adacore.com> + + * c-ada-spec.h (cpp_operation): Add IS_TRIVIAL. + (dump_ada_specs): Adjust prototype of second callback. + * c-ada-spec.c (cpp_check): New global variable. + (dump_ada_nodes): Remove cpp_check parameter and do not pass it down. + (print_generic_ada_decl): Likewise. + (has_static_fields): Change return type to bool and add guard. + (has_nontrivial_methods): New predicate. + (is_tagged_type): Change return type to bool. + (separate_class_package): Call has_nontrivial_methods. + (pp_ada_tree_identifier): Minor tweaks. + (dump_ada_function_declaration): Adjust calls to dump_generic_ada_node. + (dump_ada_array_domains): Likewise. + (dump_ada_array_type): Likewise. + (dump_template_types): Remove cpp_check parameter and do not pass it to + dump_generic_ada_node. + (dump_ada_template): Likewise. + (dump_generic_ada_node): Remove cpp_check parameter and do not pass it + recursively. + (print_ada_methods): Change return type to integer. Remove cpp_check + parameter and do not pass it down. + (dump_nested_types): Remove cpp_check parameter and do not pass it to + dump_generic_ada_node. + (print_ada_declaration): Likewise. Test RECORD_OR_UNION_TYPE_P before + accessing methods. + (print_ada_struct_decl): Remove cpp_check parameter and do not pass it + down. Use has_nontrivial_methods to recognize C++ classes. Use return + value of print_ada_methods. + (dump_ads): Rename cpp_check parameter to check and adjust prototype. + Set cpp_check to it before invoking dump_ada_nodes. + (dump_ada_specs): Likewise. + +2013-11-03 Marek Polacek <polacek@redhat.com> + + * c-ubsan.c: Don't include hash-table.h. + (ubsan_instrument_vla): New function. + * c-ubsan.h: Declare it. + +2013-10-31 David Malcolm <dmalcolm@redhat.com> + + Automated part of renaming of symtab_node_base to symtab_node. + + Patch autogenerated by rename_symtab.py from + https://github.com/davidmalcolm/gcc-refactoring-scripts + revision 58bb219cc090b2f4516a9297d868c245495ee622 + + * c-pragma.c (maybe_apply_pending_pragma_weaks): Rename + symtab_node_base to symtab_node. + +2013-10-31 Edward Smith-Rowland <3dw4rd@verizon.net> + + Implement C++14 digit separators. + * c-lex.c (interpret_float): Remove digit separators from scratch string + before building real literal. + +2013-10-30 Jakub Jelinek <jakub@redhat.com> + + * cilk.c (create_cilk_helper_decl): Use HOST_WIDE_INT_PRINT_DEC. + +2013-10-29 Balaji V. Iyer <balaji.v.iyer@intel.com> + + * c-common.c (c_common_reswords[]): Added _Cilk_spawn and _Cilk_sync + fields. + (c_define_builtins): Called cilk_init_builtins if Cilk Plus is + enabled. + * c-common.h (enum rid): Added RID_CILK_SPAWN and RID_CILK_SYNC. + (insert_cilk_frame): New prototype. + (cilk_init_builtins): Likewise. + (gimplify_cilk_spawn): Likewise. + (c_cilk_install_body_w_frame_cleanup): Likewise. + (cilk_detect_spawn_and_unwrap): Likewise. + (cilk_set_spawn_marker): Likewise. + (build_cilk_sync): Likewise. + (build_cilk_spawn): Likewise. + * cilk.c: New file. + +2013-10-29 David Malcolm <dmalcolm@redhat.com> + + Patch autogenerated by refactor_symtab.py from + https://github.com/davidmalcolm/gcc-refactoring-scripts + revision 58bb219cc090b2f4516a9297d868c245495ee622 + + * c-gimplify.c (c_genericize): Update for conversion of symtab types + to a true class hierarchy. + * c-pragma.c (maybe_apply_pending_pragma_weaks): Likewise. + +2013-10-27 Richard Sandiford <rdsandiford@googlemail.com> + + * c-lex.c (interpret_integer): Remove call to cpp_num_sign_extend. + +2013-10-26 Jeff Law <law@redhat.com> + + * c-family/c-common.c (c_define_builtins): Remove mudflap support. + * c-family/c.opt: Ignore and warn for mudflap options. + +2013-10-24 Tobias Burnus <burnus@net-b.de> + + PR other/33426 + * c-pragma.c (init_pragma) Add #pragma ivdep handling. + * c-pragma.h (pragma_kind): Add PRAGMA_IVDEP. + +2013-10-23 Jason Merrill <jason@redhat.com> + + * c-format.c (gcc_cxxdiag_char_table): Add %X. + 2013-10-11 Jakub Jelinek <jakub@redhat.com> * c-common.h (omp_clause_mask::operator !=): New method. @@ -390,7 +507,7 @@ * c-family/array-notation-common.c (length_mismatch_in_expr_p): Delete unused variables l_length and l_node. -2013-07-04 Joern Rennecke <joern.rennecke@embecosm.com> +2013-07-04 Joern Rennecke <joern.rennecke@embecosm.com> PR c/57821 * c-common.c (complete_array_type): Delay folding first index diff --git a/gcc/c-family/c-ada-spec.c b/gcc/c-family/c-ada-spec.c index 89379dbe4c8..bdba8f98ea1 100644 --- a/gcc/c-family/c-ada-spec.c +++ b/gcc/c-family/c-ada-spec.c @@ -32,32 +32,31 @@ along with GCC; see the file COPYING3. If not see #include "wide-int.h" /* Local functions, macros and variables. */ -static int dump_generic_ada_node (pretty_printer *, tree, tree, - int (*)(tree, cpp_operation), int, int, bool); -static int print_ada_declaration (pretty_printer *, tree, tree, - int (*cpp_check)(tree, cpp_operation), int); -static void print_ada_struct_decl (pretty_printer *, tree, tree, - int (*cpp_check)(tree, cpp_operation), int, - bool); +static int dump_generic_ada_node (pretty_printer *, tree, tree, int, int, + bool); +static int print_ada_declaration (pretty_printer *, tree, tree, int); +static void print_ada_struct_decl (pretty_printer *, tree, tree, int, bool); static void dump_sloc (pretty_printer *buffer, tree node); static void print_comment (pretty_printer *, const char *); -static void print_generic_ada_decl (pretty_printer *, tree, - int (*)(tree, cpp_operation), const char *); +static void print_generic_ada_decl (pretty_printer *, tree, const char *); static char *get_ada_package (const char *); -static void dump_ada_nodes (pretty_printer *, const char *, - int (*)(tree, cpp_operation)); +static void dump_ada_nodes (pretty_printer *, const char *); static void reset_ada_withs (void); static void dump_ada_withs (FILE *); static void dump_ads (const char *, void (*)(const char *), - int (*)(tree, cpp_operation)); + int (*)(const_tree, cpp_operation)); static char *to_ada_name (const char *, int *); static bool separate_class_package (tree); -#define INDENT(SPACE) do { \ - int i; for (i = 0; i<SPACE; i++) pp_space (buffer); } while (0) +#define INDENT(SPACE) \ + do { int i; for (i = 0; i<SPACE; i++) pp_space (buffer); } while (0) #define INDENT_INCR 3 +/* Global hook used to perform C++ queries on nodes. */ +static int (*cpp_check) (const_tree, cpp_operation) = NULL; + + /* Given a cpp MACRO, compute the max length BUFFER_LEN of the macro, as well as max length PARAM_LEN of arguments for fun_like macros, and also set SUPPORTED to 0 if the macro cannot be mapped to an Ada construct. */ @@ -622,11 +621,10 @@ unmark_visited_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, } /* Dump nodes into PP relevant to SOURCE_FILE, as collected by previous calls - to collect_ada_nodes. CPP_CHECK is used to perform C++ queries on nodes. */ + to collect_ada_nodes. */ static void -dump_ada_nodes (pretty_printer *pp, const char *source_file, - int (*cpp_check)(tree, cpp_operation)) +dump_ada_nodes (pretty_printer *pp, const char *source_file) { int i, j; cpp_comment_table *comments; @@ -662,7 +660,7 @@ dump_ada_nodes (pretty_printer *pp, const char *source_file, if (j == comments->count || LOCATION_LINE (decl_sloc (to_dump[i], false)) < LOCATION_LINE (comments->entries[j].sloc)) - print_generic_ada_decl (pp, to_dump[i++], cpp_check, source_file); + print_generic_ada_decl (pp, to_dump[i++], source_file); else break; } @@ -722,18 +720,15 @@ print_comment (pretty_printer *pp, const char *comment) pp_newline (pp); } -/* Prints declaration DECL to PP in Ada syntax. The current source file being - handled is SOURCE_FILE, and CPP_CHECK is used to perform C++ queries on - nodes. */ +/* Print declaration DECL to PP in Ada syntax. The current source file being + handled is SOURCE_FILE. */ static void -print_generic_ada_decl (pretty_printer *pp, tree decl, - int (*cpp_check)(tree, cpp_operation), - const char* source_file) +print_generic_ada_decl (pretty_printer *pp, tree decl, const char *source_file) { source_file_base = source_file; - if (print_ada_declaration (pp, decl, 0, cpp_check, INDENT_INCR)) + if (print_ada_declaration (pp, decl, 0, INDENT_INCR)) { pp_newline (pp); pp_newline (pp); @@ -927,23 +922,25 @@ get_underlying_decl (tree type) /* Return whether TYPE has static fields. */ -static int +static bool has_static_fields (const_tree type) { tree tmp; + if (!type || !RECORD_OR_UNION_TYPE_P (type)) + return false; + for (tmp = TYPE_FIELDS (type); tmp; tmp = TREE_CHAIN (tmp)) - { - if (DECL_NAME (tmp) && TREE_STATIC (tmp)) - return true; - } + if (DECL_NAME (tmp) && TREE_STATIC (tmp)) + return true; + return false; } /* Return whether TYPE corresponds to an Ada tagged type (has a dispatch table). */ -static int +static bool is_tagged_type (const_tree type) { tree tmp; @@ -958,6 +955,35 @@ is_tagged_type (const_tree type) return false; } +/* Return whether TYPE has non-trivial methods, i.e. methods that do something + for the objects of TYPE. In C++, all classes have implicit special methods, + e.g. constructors and destructors, but they can be trivial if the type is + sufficiently simple. */ + +static bool +has_nontrivial_methods (const_tree type) +{ + tree tmp; + + if (!type || !RECORD_OR_UNION_TYPE_P (type)) + return false; + + /* Only C++ types can have methods. */ + if (!cpp_check) + return false; + + /* A non-trivial type has non-trivial special methods. */ + if (!cpp_check (type, IS_TRIVIAL)) + return true; + + /* If there are user-defined methods, they are deemed non-trivial. */ + for (tmp = TYPE_METHODS (type); tmp; tmp = TREE_CHAIN (tmp)) + if (!DECL_ARTIFICIAL (tmp)) + return true; + + return false; +} + /* Generate a legal Ada name from a C NAME, returning a malloc'd string. SPACE_FOUND, if not NULL, is used to indicate whether a space was found in NAME. */ @@ -1179,15 +1205,8 @@ to_ada_name (const char *name, int *space_found) static bool separate_class_package (tree decl) { - if (decl) - { - tree type = TREE_TYPE (decl); - return type - && TREE_CODE (type) == RECORD_TYPE - && (TYPE_METHODS (type) || has_static_fields (type)); - } - else - return false; + tree type = TREE_TYPE (decl); + return has_nontrivial_methods (type) || has_static_fields (type); } static bool package_prefix = true; @@ -1207,7 +1226,6 @@ pp_ada_tree_identifier (pretty_printer *buffer, tree node, tree type, /* If the entity is a type and comes from another file, generate "package" prefix. */ - decl = get_underlying_decl (type); if (decl) @@ -1232,30 +1250,27 @@ pp_ada_tree_identifier (pretty_printer *buffer, tree node, tree type, case UNION_TYPE: case QUAL_UNION_TYPE: case TYPE_DECL: - { - char *s1 = get_ada_package (xloc.file); - - if (package_prefix) - { - append_withs (s1, limited_access); - pp_string (buffer, s1); - pp_dot (buffer); - } - free (s1); - } + if (package_prefix) + { + char *s1 = get_ada_package (xloc.file); + append_withs (s1, limited_access); + pp_string (buffer, s1); + pp_dot (buffer); + free (s1); + } break; default: break; } - - if (separate_class_package (decl)) - { - pp_string (buffer, "Class_"); - pp_string (buffer, s); - pp_dot (buffer); - } - - } + + /* Generate the additional package prefix for C++ classes. */ + if (separate_class_package (decl)) + { + pp_string (buffer, "Class_"); + pp_string (buffer, s); + pp_dot (buffer); + } + } } } @@ -1513,15 +1528,13 @@ dump_ada_function_declaration (pretty_printer *buffer, tree func, pp_string (buffer, buf); } - dump_generic_ada_node - (buffer, TREE_TYPE (arg), node, NULL, spc, 0, true); + dump_generic_ada_node (buffer, TREE_TYPE (arg), node, spc, 0, true); } else { sprintf (buf, "arg%d : ", num); pp_string (buffer, buf); - dump_generic_ada_node - (buffer, TREE_VALUE (arg), node, NULL, spc, 0, true); + dump_generic_ada_node (buffer, TREE_VALUE (arg), node, spc, 0, true); } if (TREE_TYPE (arg) && TREE_TYPE (TREE_TYPE (arg)) @@ -1579,13 +1592,13 @@ dump_ada_array_domains (pretty_printer *buffer, tree node, int spc) first = 0; if (min) - dump_generic_ada_node (buffer, min, NULL_TREE, NULL, spc, 0, true); + dump_generic_ada_node (buffer, min, NULL_TREE, spc, 0, true); pp_string (buffer, " .. "); /* If the upper bound is zero, gcc may generate a NULL_TREE for TYPE_MAX_VALUE rather than an integer_cst. */ if (max) - dump_generic_ada_node (buffer, max, NULL_TREE, NULL, spc, 0, true); + dump_generic_ada_node (buffer, max, NULL_TREE, spc, 0, true); else pp_string (buffer, "0"); } @@ -1673,18 +1686,16 @@ dump_ada_array_type (pretty_printer *buffer, tree t, int spc) pp_string (buffer, "aliased "); dump_generic_ada_node - (buffer, TREE_TYPE (tmp), TREE_TYPE (t), NULL, spc, false, true); + (buffer, TREE_TYPE (tmp), TREE_TYPE (t), spc, false, true); } } /* Dump in BUFFER type names associated with a template, each prepended with - '_'. TYPES is the TREE_PURPOSE of a DECL_TEMPLATE_INSTANTIATIONS. - CPP_CHECK is used to perform C++ queries on nodes. - SPC is the indentation level. */ + '_'. TYPES is the TREE_PURPOSE of a DECL_TEMPLATE_INSTANTIATIONS. SPC is + the indentation level. */ static void -dump_template_types (pretty_printer *buffer, tree types, - int (*cpp_check)(tree, cpp_operation), int spc) +dump_template_types (pretty_printer *buffer, tree types, int spc) { size_t i; size_t len = TREE_VEC_LENGTH (types); @@ -1693,7 +1704,7 @@ dump_template_types (pretty_printer *buffer, tree types, { tree elem = TREE_VEC_ELT (types, i); pp_underscore (buffer); - if (!dump_generic_ada_node (buffer, elem, 0, cpp_check, spc, false, true)) + if (!dump_generic_ada_node (buffer, elem, 0, spc, false, true)) { pp_string (buffer, "unknown"); pp_scalar (buffer, "%lu", (unsigned long) TREE_HASH (elem)); @@ -1702,12 +1713,10 @@ dump_template_types (pretty_printer *buffer, tree types, } /* Dump in BUFFER the contents of all class instantiations associated with - a given template T. CPP_CHECK is used to perform C++ queries on nodes. - SPC is the indentation level. */ + a given template T. SPC is the indentation level. */ static int -dump_ada_template (pretty_printer *buffer, tree t, - int (*cpp_check)(tree, cpp_operation), int spc) +dump_ada_template (pretty_printer *buffer, tree t, int spc) { /* DECL_VINDEX is DECL_TEMPLATE_INSTANTIATIONS in this context. */ tree inst = DECL_VINDEX (t); @@ -1736,15 +1745,15 @@ dump_ada_template (pretty_printer *buffer, tree t, INDENT (spc); pp_string (buffer, "package "); package_prefix = false; - dump_generic_ada_node (buffer, instance, t, cpp_check, spc, false, true); - dump_template_types (buffer, types, cpp_check, spc); + dump_generic_ada_node (buffer, instance, t, spc, false, true); + dump_template_types (buffer, types, spc); pp_string (buffer, " is"); spc += INDENT_INCR; newline_and_indent (buffer, spc); TREE_VISITED (get_underlying_decl (instance)) = 1; pp_string (buffer, "type "); - dump_generic_ada_node (buffer, instance, t, cpp_check, spc, false, true); + dump_generic_ada_node (buffer, instance, t, spc, false, true); package_prefix = true; if (is_tagged_type (instance)) @@ -1752,7 +1761,7 @@ dump_ada_template (pretty_printer *buffer, tree t, else pp_string (buffer, " is limited "); - dump_generic_ada_node (buffer, instance, t, cpp_check, spc, false, false); + dump_generic_ada_node (buffer, instance, t, spc, false, false); pp_newline (buffer); spc -= INDENT_INCR; newline_and_indent (buffer, spc); @@ -1761,8 +1770,8 @@ dump_ada_template (pretty_printer *buffer, tree t, newline_and_indent (buffer, spc); pp_string (buffer, "use "); package_prefix = false; - dump_generic_ada_node (buffer, instance, t, cpp_check, spc, false, true); - dump_template_types (buffer, types, cpp_check, spc); + dump_generic_ada_node (buffer, instance, t, spc, false, true); + dump_template_types (buffer, types, spc); package_prefix = true; pp_semicolon (buffer); pp_newline (buffer); @@ -1805,14 +1814,12 @@ static bool in_function = true; static bool bitfield_used = false; /* Recursively dump in BUFFER Ada declarations corresponding to NODE of type - TYPE. CPP_CHECK is used to perform C++ queries on nodes. SPC is the - indentation level. LIMITED_ACCESS indicates whether NODE can be referenced - via a "limited with" clause. NAME_ONLY indicates whether we should only - dump the name of NODE, instead of its full declaration. */ + TYPE. SPC is the indentation level. LIMITED_ACCESS indicates whether NODE + can be referenced via a "limited with" clause. NAME_ONLY indicates whether + we should only dump the name of NODE, instead of its full declaration. */ static int -dump_generic_ada_node (pretty_printer *buffer, tree node, tree type, - int (*cpp_check)(tree, cpp_operation), int spc, +dump_generic_ada_node (pretty_printer *buffer, tree node, tree type, int spc, int limited_access, bool name_only) { if (node == NULL_TREE) @@ -1834,8 +1841,7 @@ dump_generic_ada_node (pretty_printer *buffer, tree node, tree type, case TREE_BINFO: dump_generic_ada_node - (buffer, BINFO_TYPE (node), type, cpp_check, - spc, limited_access, name_only); + (buffer, BINFO_TYPE (node), type, spc, limited_access, name_only); case TREE_VEC: pp_string (buffer, "--- unexpected node: TREE_VEC"); @@ -1862,7 +1868,7 @@ dump_generic_ada_node (pretty_printer *buffer, tree node, tree type, case ENUMERAL_TYPE: if (name_only) dump_generic_ada_node - (buffer, TYPE_NAME (node), node, cpp_check, spc, 0, true); + (buffer, TYPE_NAME (node), node, spc, 0, true); else { tree value = TYPE_VALUES (node); @@ -1892,7 +1898,7 @@ dump_generic_ada_node (pretty_printer *buffer, tree node, tree type, pp_string (buffer, "pragma Convention (C, "); dump_generic_ada_node (buffer, DECL_NAME (type) ? type : TYPE_NAME (node), type, - cpp_check, spc, 0, true); + spc, 0, true); pp_right_paren (buffer); } else @@ -1909,14 +1915,14 @@ dump_generic_ada_node (pretty_printer *buffer, tree node, tree type, dump_generic_ada_node (buffer, DECL_NAME (type) ? type : TYPE_NAME (node), type, - cpp_check, spc, 0, true); + spc, 0, true); pp_string (buffer, " := "); dump_generic_ada_node (buffer, TREE_CODE (TREE_VALUE (value)) == INTEGER_CST ? TREE_VALUE (value) : DECL_INITIAL (TREE_VALUE (value)), - node, cpp_check, spc, false, true); + node, spc, false, true); } } } @@ -1977,8 +1983,7 @@ dump_generic_ada_node (pretty_printer *buffer, tree node, tree type, case REFERENCE_TYPE: if (name_only && TYPE_NAME (node)) dump_generic_ada_node - (buffer, TYPE_NAME (node), node, cpp_check, - spc, limited_access, true); + (buffer, TYPE_NAME (node), node, spc, limited_access, true); else if (TREE_CODE (TREE_TYPE (node)) == FUNCTION_TYPE) { @@ -2006,7 +2011,7 @@ dump_generic_ada_node (pretty_printer *buffer, tree node, tree type, { pp_string (buffer, " return "); dump_generic_ada_node - (buffer, TREE_TYPE (fnode), type, cpp_check, spc, 0, true); + (buffer, TREE_TYPE (fnode), type, spc, 0, true); } /* If we are dumping the full type, it means we are part of a @@ -2017,7 +2022,7 @@ dump_generic_ada_node (pretty_printer *buffer, tree node, tree type, newline_and_indent (buffer, spc); pp_string (buffer, "pragma Convention (C, "); dump_generic_ada_node - (buffer, type, 0, cpp_check, spc, false, true); + (buffer, type, 0, spc, false, true); pp_right_paren (buffer); } } @@ -2144,11 +2149,11 @@ dump_generic_ada_node (pretty_printer *buffer, tree node, tree type, && type_name != NULL_TREE) dump_generic_ada_node (buffer, type_name, - TREE_TYPE (node), cpp_check, spc, is_access, true); + TREE_TYPE (node), spc, is_access, true); else dump_generic_ada_node (buffer, TREE_TYPE (node), TREE_TYPE (node), - cpp_check, spc, 0, true); + spc, 0, true); } } } @@ -2157,8 +2162,7 @@ dump_generic_ada_node (pretty_printer *buffer, tree node, tree type, case ARRAY_TYPE: if (name_only) dump_generic_ada_node - (buffer, TYPE_NAME (node), node, cpp_check, - spc, limited_access, true); + (buffer, TYPE_NAME (node), node, spc, limited_access, true); else dump_ada_array_type (buffer, node, spc); break; @@ -2170,8 +2174,7 @@ dump_generic_ada_node (pretty_printer *buffer, tree node, tree type, { if (TYPE_NAME (node)) dump_generic_ada_node - (buffer, TYPE_NAME (node), node, cpp_check, - spc, limited_access, true); + (buffer, TYPE_NAME (node), node, spc, limited_access, true); else { pp_string (buffer, "anon_"); @@ -2179,8 +2182,7 @@ dump_generic_ada_node (pretty_printer *buffer, tree node, tree type, } } else - print_ada_struct_decl - (buffer, node, type, cpp_check, spc, true); + print_ada_struct_decl (buffer, node, type, spc, true); break; case INTEGER_CST: @@ -2272,12 +2274,11 @@ dump_generic_ada_node (pretty_printer *buffer, tree node, tree type, pp_string (buffer, first ? "tagged limited " : " with "); } - else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (node)) - && TYPE_METHODS (TREE_TYPE (node))) + else if (has_nontrivial_methods (TREE_TYPE (node))) pp_string (buffer, "limited "); dump_generic_ada_node - (buffer, TREE_TYPE (node), type, cpp_check, spc, false, false); + (buffer, TREE_TYPE (node), type, spc, false, false); } break; @@ -2296,41 +2297,41 @@ dump_generic_ada_node (pretty_printer *buffer, tree node, tree type, return 1; } -/* Dump in BUFFER NODE's methods. CPP_CHECK is used to perform C++ queries on - nodes. SPC is the indentation level. */ +/* Dump in BUFFER NODE's methods. SPC is the indentation level. Return 1 if + methods were printed, 0 otherwise. */ -static void -print_ada_methods (pretty_printer *buffer, tree node, - int (*cpp_check)(tree, cpp_operation), int spc) +static int +print_ada_methods (pretty_printer *buffer, tree node, int spc) { - tree tmp = TYPE_METHODS (node); int res = 1; + tree tmp; - if (tmp) - { - pp_semicolon (buffer); + if (!has_nontrivial_methods (node)) + return 0; - for (; tmp; tmp = TREE_CHAIN (tmp)) + pp_semicolon (buffer); + + for (tmp = TYPE_METHODS (node); tmp; tmp = TREE_CHAIN (tmp)) + { + if (res) { - if (res) - { - pp_newline (buffer); - pp_newline (buffer); - } - res = print_ada_declaration (buffer, tmp, node, cpp_check, spc); + pp_newline (buffer); + pp_newline (buffer); } + res = print_ada_declaration (buffer, tmp, node, spc); } + + return 1; } /* Dump in BUFFER anonymous types nested inside T's definition. PARENT is the parent node of T. FORWARD indicates whether a forward declaration of T should be generated. - CPP_CHECK is used to perform C++ queries on - nodes. SPC is the indentation level. */ + SPC is the indentation level. */ static void dump_nested_types (pretty_printer *buffer, tree t, tree parent, bool forward, - int (*cpp_check)(tree, cpp_operation), int spc) + int spc) { tree field, outer, decl; @@ -2348,8 +2349,7 @@ dump_nested_types (pretty_printer *buffer, tree t, tree parent, bool forward, if (forward) { pp_string (buffer, "type "); - dump_generic_ada_node - (buffer, t, t, cpp_check, spc, false, true); + dump_generic_ada_node (buffer, t, t, spc, false, true); pp_semicolon (buffer); newline_and_indent (buffer, spc); TREE_VISITED (t) = 1; @@ -2391,8 +2391,7 @@ dump_nested_types (pretty_printer *buffer, tree t, tree parent, bool forward, /* Generate forward declaration. */ pp_string (buffer, "type "); - dump_generic_ada_node - (buffer, decl, 0, cpp_check, spc, false, true); + dump_generic_ada_node (buffer, decl, 0, spc, false, true); pp_semicolon (buffer); newline_and_indent (buffer, spc); @@ -2416,30 +2415,28 @@ dump_nested_types (pretty_printer *buffer, tree t, tree parent, bool forward, case UNION_TYPE: TREE_VISITED (t) = 1; - dump_nested_types (buffer, field, t, false, cpp_check, spc); + dump_nested_types (buffer, field, t, false, spc); pp_string (buffer, "type "); if (TYPE_NAME (TREE_TYPE (field))) { dump_generic_ada_node - (buffer, TYPE_NAME (TREE_TYPE (field)), 0, cpp_check, - spc, false, true); + (buffer, TYPE_NAME (TREE_TYPE (field)), 0, spc, false, + true); pp_string (buffer, " (discr : unsigned := 0) is "); print_ada_struct_decl - (buffer, TREE_TYPE (field), t, cpp_check, spc, false); + (buffer, TREE_TYPE (field), t, spc, false); pp_string (buffer, "pragma Convention (C_Pass_By_Copy, "); dump_generic_ada_node - (buffer, TREE_TYPE (field), 0, cpp_check, - spc, false, true); + (buffer, TREE_TYPE (field), 0, spc, false, true); pp_string (buffer, ");"); newline_and_indent (buffer, spc); pp_string (buffer, "pragma Unchecked_Union ("); dump_generic_ada_node - (buffer, TREE_TYPE (field), 0, cpp_check, - spc, false, true); + (buffer, TREE_TYPE (field), 0, spc, false, true); pp_string (buffer, ");"); } else @@ -2448,7 +2445,7 @@ dump_nested_types (pretty_printer *buffer, tree t, tree parent, bool forward, (buffer, parent, field, "_union (discr : unsigned := 0) is "); print_ada_struct_decl - (buffer, TREE_TYPE (field), t, cpp_check, spc, false); + (buffer, TREE_TYPE (field), t, spc, false); pp_string (buffer, "pragma Convention (C_Pass_By_Copy, "); dump_ada_double_name (buffer, parent, field, "_union);"); newline_and_indent (buffer, spc); @@ -2465,27 +2462,25 @@ dump_nested_types (pretty_printer *buffer, tree t, tree parent, bool forward, { pp_string (buffer, "type "); dump_generic_ada_node - (buffer, t, parent, 0, spc, false, true); + (buffer, t, parent, spc, false, true); pp_semicolon (buffer); newline_and_indent (buffer, spc); } TREE_VISITED (t) = 1; - dump_nested_types (buffer, field, t, false, cpp_check, spc); + dump_nested_types (buffer, field, t, false, spc); pp_string (buffer, "type "); if (TYPE_NAME (TREE_TYPE (field))) { dump_generic_ada_node - (buffer, TREE_TYPE (field), 0, cpp_check, - spc, false, true); + (buffer, TREE_TYPE (field), 0, spc, false, true); pp_string (buffer, " is "); print_ada_struct_decl - (buffer, TREE_TYPE (field), t, cpp_check, spc, false); + (buffer, TREE_TYPE (field), t, spc, false); pp_string (buffer, "pragma Convention (C_Pass_By_Copy, "); dump_generic_ada_node - (buffer, TREE_TYPE (field), 0, cpp_check, - spc, false, true); + (buffer, TREE_TYPE (field), 0, spc, false, true); pp_string (buffer, ");"); } else @@ -2493,7 +2488,7 @@ dump_nested_types (pretty_printer *buffer, tree t, tree parent, bool forward, dump_ada_double_name (buffer, parent, field, "_struct is "); print_ada_struct_decl - (buffer, TREE_TYPE (field), t, cpp_check, spc, false); + (buffer, TREE_TYPE (field), t, spc, false); pp_string (buffer, "pragma Convention (C_Pass_By_Copy, "); dump_ada_double_name (buffer, parent, field, "_struct);"); } @@ -2542,12 +2537,11 @@ type_name (tree t) } /* Print in BUFFER the declaration of a variable T of type TYPE in Ada syntax. - CPP_CHECK is used to perform C++ queries on nodes. SPC is the indentation - level. Return 1 if a declaration was printed, 0 otherwise. */ + SPC is the indentation level. Return 1 if a declaration was printed, + 0 otherwise. */ static int -print_ada_declaration (pretty_printer *buffer, tree t, tree type, - int (*cpp_check)(tree, cpp_operation), int spc) +print_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc) { int is_var = 0, need_indent = 0; int is_class = false; @@ -2556,7 +2550,7 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type, tree orig = NULL_TREE; if (cpp_check && cpp_check (t, IS_TEMPLATE)) - return dump_ada_template (buffer, t, cpp_check, spc); + return dump_ada_template (buffer, t, spc); if (TREE_CODE (t) == CONST_DECL && TREE_CODE (TREE_TYPE (t)) == ENUMERAL_TYPE) /* Skip enumeral values: will be handled as part of the type itself. */ @@ -2584,20 +2578,18 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type, if (RECORD_OR_UNION_TYPE_P (typ) && !TYPE_FIELDS (typ)) { pp_string (buffer, "-- skipped empty struct "); - dump_generic_ada_node (buffer, t, type, 0, spc, false, true); + dump_generic_ada_node (buffer, t, type, spc, false, true); } else { if (!TREE_VISITED (stub) && DECL_SOURCE_FILE (stub) == source_file_base) - dump_nested_types - (buffer, stub, stub, true, cpp_check, spc); + dump_nested_types (buffer, stub, stub, true, spc); pp_string (buffer, "subtype "); - dump_generic_ada_node (buffer, t, type, 0, spc, false, true); + dump_generic_ada_node (buffer, t, type, spc, false, true); pp_string (buffer, " is "); - dump_generic_ada_node - (buffer, typ, type, 0, spc, false, true); + dump_generic_ada_node (buffer, typ, type, spc, false, true); pp_semicolon (buffer); } return 1; @@ -2656,7 +2648,7 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type, if (!TYPE_FIELDS (TREE_TYPE (t))) { pp_string (buffer, "-- skipped empty struct "); - dump_generic_ada_node (buffer, t, type, 0, spc, false, true); + dump_generic_ada_node (buffer, t, type, spc, false, true); return 1; } @@ -2665,7 +2657,7 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type, || *IDENTIFIER_POINTER (decl_name) == '$')) { pp_string (buffer, "-- skipped anonymous struct "); - dump_generic_ada_node (buffer, t, type, 0, spc, false, true); + dump_generic_ada_node (buffer, t, type, spc, false, true); TREE_VISITED (t) = 1; return 1; } @@ -2674,14 +2666,13 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type, pp_string (buffer, "subtype "); else { - dump_nested_types (buffer, t, t, false, cpp_check, spc); + dump_nested_types (buffer, t, t, false, spc); if (separate_class_package (t)) { is_class = true; pp_string (buffer, "package Class_"); - dump_generic_ada_node - (buffer, t, type, 0, spc, false, true); + dump_generic_ada_node (buffer, t, type, spc, false, true); pp_string (buffer, " is"); spc += INDENT_INCR; newline_and_indent (buffer, spc); @@ -2703,7 +2694,7 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type, case FUNCTION_TYPE: pp_string (buffer, "-- skipped function type "); - dump_generic_ada_node (buffer, t, type, 0, spc, false, true); + dump_generic_ada_node (buffer, t, type, spc, false, true); return 1; break; @@ -2737,7 +2728,7 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type, INDENT (spc); /* Print variable's name. */ - dump_generic_ada_node (buffer, t, type, cpp_check, spc, false, true); + dump_generic_ada_node (buffer, t, type, spc, false, true); if (TREE_CODE (t) == TYPE_DECL) { @@ -2745,8 +2736,7 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type, if (orig && TYPE_NAME (orig) && orig != TREE_TYPE (t)) dump_generic_ada_node - (buffer, TYPE_NAME (orig), type, - cpp_check, spc, false, true); + (buffer, TYPE_NAME (orig), type, spc, false, true); else dump_ada_array_type (buffer, t, spc); } @@ -2765,7 +2755,7 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type, && TREE_CODE (tmp) != INTEGER_TYPE) pp_string (buffer, "aliased "); - dump_generic_ada_node (buffer, tmp, type, 0, spc, false, true); + dump_generic_ada_node (buffer, tmp, type, spc, false, true); } else { @@ -2780,7 +2770,8 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type, } else if (TREE_CODE (t) == FUNCTION_DECL) { - bool is_function = true, is_method, is_abstract_class = false; + bool is_function = true, is_abstract_class = false; + bool is_method = TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE; tree decl_name = DECL_NAME (t); int prev_in_function = in_function; bool is_abstract = false; @@ -2837,7 +2828,6 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type, pp_string (buffer, "function "); in_function = is_function; - is_method = TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE; if (is_destructor) print_destructor (buffer, t); @@ -2859,18 +2849,17 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type, else { dump_generic_ada_node - (buffer, TREE_TYPE (TREE_TYPE (t)), type, cpp_check, - spc, false, true); + (buffer, TREE_TYPE (TREE_TYPE (t)), type, spc, false, true); } } - if (is_constructor && cpp_check && type - && AGGREGATE_TYPE_P (type) + if (is_constructor + && RECORD_OR_UNION_TYPE_P (type) && TYPE_METHODS (type)) { - tree tmp = TYPE_METHODS (type); + tree tmp; - for (; tmp; tmp = TREE_CHAIN (tmp)) + for (tmp = TYPE_METHODS (type); tmp; tmp = TREE_CHAIN (tmp)) if (cpp_check (tmp, IS_ABSTRACT)) { is_abstract_class = 1; @@ -2922,8 +2911,7 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type, INDENT (spc); /* Anonymous structs/unions */ - dump_generic_ada_node - (buffer, TREE_TYPE (t), t, cpp_check, spc, false, true); + dump_generic_ada_node (buffer, TREE_TYPE (t), t, spc, false, true); if (TREE_CODE (TREE_TYPE (t)) == UNION_TYPE || TREE_CODE (TREE_TYPE (t)) == QUAL_UNION_TYPE) @@ -2934,14 +2922,15 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type, pp_string (buffer, " is "); /* Check whether we have an Ada interface compatible class. */ - if (cpp_check && AGGREGATE_TYPE_P (TREE_TYPE (t)) + if (cpp_check + && RECORD_OR_UNION_TYPE_P (TREE_TYPE (t)) && TYPE_METHODS (TREE_TYPE (t))) { int num_fields = 0; - tree tmp = TYPE_FIELDS (TREE_TYPE (t)); + tree tmp; /* Check that there are no fields other than the virtual table. */ - for (; tmp; tmp = TREE_CHAIN (tmp)) + for (tmp = TYPE_FIELDS (TREE_TYPE (t)); tmp; tmp = TREE_CHAIN (tmp)) { if (TREE_CODE (tmp) == TYPE_DECL) continue; @@ -2969,17 +2958,16 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type, newline_and_indent (buffer, spc); pp_string (buffer, "pragma Import (CPP, "); dump_generic_ada_node - (buffer, TYPE_NAME (TREE_TYPE (t)), type, cpp_check, - spc, false, true); + (buffer, TYPE_NAME (TREE_TYPE (t)), type, spc, false, true); pp_right_paren (buffer); - print_ada_methods (buffer, TREE_TYPE (t), cpp_check, spc); + print_ada_methods (buffer, TREE_TYPE (t), spc); } else { if (is_abstract_record) pp_string (buffer, "abstract "); - dump_generic_ada_node (buffer, t, t, cpp_check, spc, false, false); + dump_generic_ada_node (buffer, t, t, spc, false, false); } } else @@ -2991,7 +2979,7 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type, check_name (buffer, t); /* Print variable/type's name. */ - dump_generic_ada_node (buffer, t, t, cpp_check, spc, false, true); + dump_generic_ada_node (buffer, t, t, spc, false, true); if (TREE_CODE (t) == TYPE_DECL) { @@ -3005,8 +2993,7 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type, pp_string (buffer, " is "); - dump_generic_ada_node - (buffer, orig, t, cpp_check, spc, false, is_subtype); + dump_generic_ada_node (buffer, orig, t, spc, false, is_subtype); } else { @@ -3028,7 +3015,7 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type, pp_string (buffer, "aliased "); dump_generic_ada_node - (buffer, TREE_TYPE (t), t, cpp_check, spc, false, true); + (buffer, TREE_TYPE (t), t, spc, false, true); } else { @@ -3038,8 +3025,7 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type, pp_string (buffer, "aliased "); dump_generic_ada_node - (buffer, TREE_TYPE (t), TREE_TYPE (t), cpp_check, - spc, false, true); + (buffer, TREE_TYPE (t), TREE_TYPE (t), spc, false, true); } } } @@ -3051,7 +3037,7 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type, pp_string (buffer, "end;"); newline_and_indent (buffer, spc); pp_string (buffer, "use Class_"); - dump_generic_ada_node (buffer, t, type, 0, spc, false, true); + dump_generic_ada_node (buffer, t, type, spc, false, true); pp_semicolon (buffer); pp_newline (buffer); @@ -3074,18 +3060,16 @@ print_ada_declaration (pretty_printer *buffer, tree t, tree type, } /* Prints in BUFFER a structure NODE of type TYPE: name, fields, and methods - with Ada syntax. CPP_CHECK is used to perform C++ queries on nodes. SPC - is the indentation level. If DISPLAY_CONVENTION is true, also print the - pragma Convention for NODE. */ + with Ada syntax. SPC is the indentation level. If DISPLAY_CONVENTION is + true, also print the pragma Convention for NODE. */ static void -print_ada_struct_decl (pretty_printer *buffer, tree node, tree type, - int (*cpp_check)(tree, cpp_operation), int spc, +print_ada_struct_decl (pretty_printer *buffer, tree node, tree type, int spc, bool display_convention) { tree tmp; - int is_union = - TREE_CODE (node) == UNION_TYPE || TREE_CODE (node) == QUAL_UNION_TYPE; + const bool is_union + = TREE_CODE (node) == UNION_TYPE || TREE_CODE (node) == QUAL_UNION_TYPE; char buf[32]; int field_num = 0; int field_spc = spc + INDENT_INCR; @@ -3119,8 +3103,7 @@ print_ada_struct_decl (pretty_printer *buffer, tree node, tree type, if (!is_tagged_type (TREE_TYPE (tmp))) { if (!TYPE_NAME (TREE_TYPE (tmp))) - print_ada_declaration - (buffer, tmp, type, cpp_check, field_spc); + print_ada_declaration (buffer, tmp, type, field_spc); else { INDENT (field_spc); @@ -3164,8 +3147,7 @@ print_ada_struct_decl (pretty_printer *buffer, tree node, tree type, pp_newline (buffer); } - if (print_ada_declaration (buffer, - tmp, type, cpp_check, field_spc)) + if (print_ada_declaration (buffer, tmp, type, field_spc)) { pp_newline (buffer); field_num++; @@ -3199,7 +3181,7 @@ print_ada_struct_decl (pretty_printer *buffer, tree node, tree type, if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type))) { - if (TYPE_METHODS (TREE_TYPE (type))) + if (has_nontrivial_methods (TREE_TYPE (type))) pp_string (buffer, "pragma Import (CPP, "); else pp_string (buffer, "pragma Convention (C_Pass_By_Copy, "); @@ -3208,8 +3190,7 @@ print_ada_struct_decl (pretty_printer *buffer, tree node, tree type, pp_string (buffer, "pragma Convention (C, "); package_prefix = false; - dump_generic_ada_node - (buffer, TREE_TYPE (type), type, cpp_check, spc, false, true); + dump_generic_ada_node (buffer, TREE_TYPE (type), type, spc, false, true); package_prefix = true; pp_right_paren (buffer); @@ -3219,8 +3200,7 @@ print_ada_struct_decl (pretty_printer *buffer, tree node, tree type, newline_and_indent (buffer, spc); pp_string (buffer, "pragma Unchecked_Union ("); - dump_generic_ada_node - (buffer, TREE_TYPE (type), type, cpp_check, spc, false, true); + dump_generic_ada_node (buffer, TREE_TYPE (type), type, spc, false, true); pp_right_paren (buffer); } @@ -3230,15 +3210,14 @@ print_ada_struct_decl (pretty_printer *buffer, tree node, tree type, newline_and_indent (buffer, spc); pp_string (buffer, "pragma Pack ("); dump_generic_ada_node - (buffer, TREE_TYPE (type), type, cpp_check, spc, false, true); + (buffer, TREE_TYPE (type), type, spc, false, true); pp_right_paren (buffer); bitfield_used = false; } - print_ada_methods (buffer, node, cpp_check, spc); + need_semicolon = !print_ada_methods (buffer, node, spc); /* Print the static fields of the structure, if any. */ - need_semicolon = TYPE_METHODS (node) == NULL_TREE; for (tmp = TYPE_FIELDS (node); tmp; tmp = TREE_CHAIN (tmp)) { if (DECL_NAME (tmp) && TREE_STATIC (tmp)) @@ -3250,20 +3229,19 @@ print_ada_struct_decl (pretty_printer *buffer, tree node, tree type, } pp_newline (buffer); pp_newline (buffer); - print_ada_declaration (buffer, tmp, type, cpp_check, spc); + print_ada_declaration (buffer, tmp, type, spc); } } } /* Dump all the declarations in SOURCE_FILE to an Ada spec. COLLECT_ALL_REFS is a front-end callback used to collect all relevant - nodes for SOURCE_FILE. CPP_CHECK is used to perform C++ queries on - nodes. */ + nodes for SOURCE_FILE. CHECK is used to perform C++ queries on nodes. */ static void dump_ads (const char *source_file, void (*collect_all_refs)(const char *), - int (*cpp_check)(tree, cpp_operation)) + int (*check)(const_tree, cpp_operation)) { char *ads_name; char *pkg_name; @@ -3301,7 +3279,8 @@ dump_ads (const char *source_file, (*collect_all_refs) (source_file); /* Dump all references. */ - dump_ada_nodes (&pp, source_file, cpp_check); + cpp_check = check; + dump_ada_nodes (&pp, source_file); /* Requires Ada 2005 syntax, so generate corresponding pragma. Also, disable style checks since this file is auto-generated. */ @@ -3355,21 +3334,21 @@ collect_source_ref (const char *filename) } /* Main entry point: dump all Ada specs corresponding to SOURCE_REFS - using callbacks COLLECT_ALL_REFS and CPP_CHECK. + using callbacks COLLECT_ALL_REFS and CHECK. COLLECT_ALL_REFS is a front-end callback used to collect all relevant nodes for a given source file. - CPP_CHECK is used to perform C++ queries on nodes, or NULL for the C + CHECK is used to perform C++ queries on nodes, or NULL for the C front-end. */ void dump_ada_specs (void (*collect_all_refs)(const char *), - int (*cpp_check)(tree, cpp_operation)) + int (*check)(const_tree, cpp_operation)) { int i; /* Iterate over the list of files to dump specs for */ for (i = 0; i < source_refs_used; i++) - dump_ads (source_refs[i], collect_all_refs, cpp_check); + dump_ads (source_refs[i], collect_all_refs, check); /* Free files table. */ free (source_refs); diff --git a/gcc/c-family/c-ada-spec.h b/gcc/c-family/c-ada-spec.h index 0bc249f8fe5..64f0ecd4b22 100644 --- a/gcc/c-family/c-ada-spec.h +++ b/gcc/c-family/c-ada-spec.h @@ -29,13 +29,14 @@ typedef enum { IS_CONSTRUCTOR, IS_DESTRUCTOR, IS_COPY_CONSTRUCTOR, - IS_TEMPLATE + IS_TEMPLATE, + IS_TRIVIAL } cpp_operation; extern location_t decl_sloc (const_tree, bool); extern void collect_ada_nodes (tree, const char *); extern void collect_source_ref (const char *); extern void dump_ada_specs (void (*)(const char *), - int (*)(tree, cpp_operation)); + int (*)(const_tree, cpp_operation)); #endif /* ! C_ADA_SPEC_H */ diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 6f6eeea4732..3496d3cdb12 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -39,7 +39,6 @@ along with GCC; see the file COPYING3. If not see #include "diagnostic.h" #include "tree-iterator.h" #include "hashtab.h" -#include "tree-mudflap.h" #include "opts.h" #include "cgraph.h" #include "target-def.h" @@ -377,6 +376,8 @@ static tree handle_omp_declare_simd_attribute (tree *, tree, tree, int, bool *); static tree handle_omp_declare_target_attribute (tree *, tree, tree, int, bool *); +static tree handle_bnd_variable_size_attribute (tree *, tree, tree, int, bool *); +static tree handle_bnd_legacy (tree *, tree, tree, int, bool *); static void check_function_nonnull (tree, int, tree *); static void check_nonnull_arg (void *, tree, unsigned HOST_WIDE_INT); @@ -411,6 +412,8 @@ const struct c_common_resword c_common_reswords[] = { "_Alignof", RID_ALIGNOF, D_CONLY }, { "_Bool", RID_BOOL, D_CONLY }, { "_Complex", RID_COMPLEX, 0 }, + { "_Cilk_spawn", RID_CILK_SPAWN, 0 }, + { "_Cilk_sync", RID_CILK_SYNC, 0 }, { "_Imaginary", RID_IMAGINARY, D_CONLY }, { "_Decimal32", RID_DFLOAT32, D_CONLY | D_EXT }, { "_Decimal64", RID_DFLOAT64, D_CONLY | D_EXT }, @@ -759,6 +762,10 @@ const struct attribute_spec c_common_attribute_table[] = handle_omp_declare_simd_attribute, false }, { "omp declare target", 0, 0, true, false, false, handle_omp_declare_target_attribute, false }, + { "bnd_variable_size", 0, 0, true, false, false, + handle_bnd_variable_size_attribute, false }, + { "bnd_legacy", 0, 0, true, false, false, + handle_bnd_legacy, false }, { NULL, 0, 0, false, false, false, NULL, false } }; @@ -5214,8 +5221,8 @@ c_define_builtins (tree va_list_ref_type_node, tree va_list_arg_type_node) build_common_builtin_nodes (); - if (flag_mudflap) - mudflap_init (); + if (flag_enable_cilkplus) + cilk_init_builtins (); } /* Like get_identifier, but avoid warnings about null arguments when @@ -8000,6 +8007,38 @@ handle_fnspec_attribute (tree *node ATTRIBUTE_UNUSED, tree ARG_UNUSED (name), return NULL_TREE; } +/* Handle a "bnd_variable_size" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_bnd_variable_size_attribute (tree *node, tree name, tree ARG_UNUSED (args), + int ARG_UNUSED (flags), bool *no_add_attrs) +{ + if (TREE_CODE (*node) != FIELD_DECL) + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "bnd_legacy" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_bnd_legacy (tree *node, tree name, tree ARG_UNUSED (args), + int ARG_UNUSED (flags), bool *no_add_attrs) +{ + if (TREE_CODE (*node) != FUNCTION_DECL) + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + + return NULL_TREE; +} + /* Handle a "warn_unused" attribute; arguments as in struct attribute_spec.handler. */ @@ -9877,6 +9916,11 @@ invalid_indirection_error (location_t loc, tree type, ref_operator errstring) "invalid type argument of %<->%> (have %qT)", type); break; + case RO_ARROW_STAR: + error_at (loc, + "invalid type argument of %<->*%> (have %qT)", + type); + break; case RO_IMPLICIT_CONVERSION: error_at (loc, "invalid type argument of implicit conversion (have %qT)", diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 1f8333e94a0..8dd40c83e01 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -148,6 +148,9 @@ enum rid /* C++11 */ RID_CONSTEXPR, RID_DECLTYPE, RID_NOEXCEPT, RID_NULLPTR, RID_STATIC_ASSERT, + /* Cilk Plus keywords. */ + RID_CILK_SPAWN, RID_CILK_SYNC, + /* Objective-C ("AT" reserved words - they are only keywords when they follow '@') */ RID_AT_ENCODE, RID_AT_END, @@ -1356,4 +1359,18 @@ extern void cilkplus_extract_an_triplets (vec<tree, va_gc> *, size_t, size_t, vec<vec<an_parts> > *); extern vec <tree, va_gc> *fix_sec_implicit_args (location_t, vec <tree, va_gc> *, vec<an_loop_parts>, size_t, tree); + +/* In cilk.c. */ +extern tree insert_cilk_frame (tree); +extern void cilk_init_builtins (void); +extern int gimplify_cilk_spawn (tree *, gimple_seq *, gimple_seq *); +extern void c_cilk_install_body_w_frame_cleanup (tree, tree); +extern bool cilk_detect_spawn_and_unwrap (tree *); +extern bool cilk_set_spawn_marker (location_t, tree); +extern tree build_cilk_sync (void); +extern tree build_cilk_spawn (location_t, tree); +extern tree make_cilk_frame (tree); +extern tree create_cilk_function_exit (tree, bool, bool); +extern tree cilk_install_body_pedigree_operations (tree); + #endif /* ! GCC_C_COMMON_H */ diff --git a/gcc/c-family/c-cppbuiltin.c b/gcc/c-family/c-cppbuiltin.c index d0327928326..94f72eceb2e 100644 --- a/gcc/c-family/c-cppbuiltin.c +++ b/gcc/c-family/c-cppbuiltin.c @@ -683,6 +683,92 @@ cpp_atomic_builtins (cpp_reader *pfile) (have_swap[psize]? 2 : 1)); } +/* Return the value for __GCC_IEC_559. */ +static int +cpp_iec_559_value (void) +{ + /* The default is support for IEEE 754-2008. */ + int ret = 2; + + /* float and double must be binary32 and binary64. If they are but + with reversed NaN convention, at most IEEE 754-1985 is + supported. */ + const struct real_format *ffmt + = REAL_MODE_FORMAT (TYPE_MODE (float_type_node)); + const struct real_format *dfmt + = REAL_MODE_FORMAT (TYPE_MODE (double_type_node)); + if (!ffmt->qnan_msb_set || !dfmt->qnan_msb_set) + ret = 1; + if (ffmt->b != 2 + || ffmt->p != 24 + || ffmt->pnan != 24 + || ffmt->emin != -125 + || ffmt->emax != 128 + || ffmt->signbit_rw != 31 + || ffmt->round_towards_zero + || !ffmt->has_sign_dependent_rounding + || !ffmt->has_nans + || !ffmt->has_inf + || !ffmt->has_denorm + || !ffmt->has_signed_zero + || dfmt->b != 2 + || dfmt->p != 53 + || dfmt->pnan != 53 + || dfmt->emin != -1021 + || dfmt->emax != 1024 + || dfmt->signbit_rw != 63 + || dfmt->round_towards_zero + || !dfmt->has_sign_dependent_rounding + || !dfmt->has_nans + || !dfmt->has_inf + || !dfmt->has_denorm + || !dfmt->has_signed_zero) + ret = 0; + + /* In strict C standards conformance mode, consider unpredictable + excess precision to mean lack of IEEE 754 support. ??? The same + should apply to unpredictable contraction, but at present + standards conformance options do not enable conforming + contraction. For C++, and outside strict conformance mode, do + not consider these options to mean lack of IEEE 754 support. */ + if (flag_iso + && !c_dialect_cxx () + && TARGET_FLT_EVAL_METHOD != 0 + && flag_excess_precision != EXCESS_PRECISION_STANDARD) + ret = 0; + + /* Various options are contrary to IEEE 754 semantics. */ + if (flag_unsafe_math_optimizations + || flag_associative_math + || flag_reciprocal_math + || flag_finite_math_only + || !flag_signed_zeros + || flag_single_precision_constant) + ret = 0; + + /* If the target does not support IEEE 754 exceptions and rounding + modes, consider IEEE 754 support to be absent. */ + if (!targetm.float_exceptions_rounding_supported_p ()) + ret = 0; + + return ret; +} + +/* Return the value for __GCC_IEC_559_COMPLEX. */ +static int +cpp_iec_559_complex_value (void) +{ + /* The value is no bigger than that of __GCC_IEC_559. */ + int ret = cpp_iec_559_value (); + + /* Some options are contrary to the required default state of the + CX_LIMITED_RANGE pragma. */ + if (flag_complex_method != 2) + ret = 0; + + return ret; +} + /* Hook that registers front end and target-specific built-ins. */ void c_cpp_builtins (cpp_reader *pfile) @@ -760,6 +846,13 @@ c_cpp_builtins (cpp_reader *pfile) /* stdint.h and the testsuite need to know these. */ builtin_define_stdint_macros (); + /* Provide information for library headers to determine whether to + define macros such as __STDC_IEC_559__ and + __STDC_IEC_559_COMPLEX__. */ + builtin_define_with_int_value ("__GCC_IEC_559", cpp_iec_559_value ()); + builtin_define_with_int_value ("__GCC_IEC_559_COMPLEX", + cpp_iec_559_complex_value ()); + /* float.h needs to know this. */ builtin_define_with_int_value ("__FLT_EVAL_METHOD__", TARGET_FLT_EVAL_METHOD); diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c index e5847021b83..0ba9085bcd1 100644 --- a/gcc/c-family/c-format.c +++ b/gcc/c-family/c-format.c @@ -721,7 +721,7 @@ static const format_char_info gcc_cxxdiag_char_table[] = /* Custom conversion specifiers. */ /* These will require a "tree" at runtime. */ - { "ADEFKSTV",0,STD_C89,{ T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+#", "", NULL }, + { "ADEFKSTVX",0,STD_C89,{ T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q+#", "", NULL }, { "v", 0,STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "q#", "", NULL }, diff --git a/gcc/c-family/c-gimplify.c b/gcc/c-family/c-gimplify.c index 3ff0a31cb23..2a4f633ad4f 100644 --- a/gcc/c-family/c-gimplify.c +++ b/gcc/c-family/c-gimplify.c @@ -98,7 +98,7 @@ c_genericize (tree fndecl) /* Dump all nested functions now. */ cgn = cgraph_get_create_node (fndecl); for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested) - c_genericize (cgn->symbol.decl); + c_genericize (cgn->decl); } static void diff --git a/gcc/c-family/c-lex.c b/gcc/c-family/c-lex.c index 367bed635a1..4aff46db238 100644 --- a/gcc/c-family/c-lex.c +++ b/gcc/c-family/c-lex.c @@ -773,8 +773,19 @@ interpret_float (const cpp_token *token, unsigned int flags, } copy = (char *) alloca (copylen + 1); - memcpy (copy, token->val.str.text, copylen); - copy[copylen] = '\0'; + if (cxx_dialect > cxx11) + { + size_t maxlen = 0; + for (size_t i = 0; i < copylen; ++i) + if (token->val.str.text[i] != '\'') + copy[maxlen++] = token->val.str.text[i]; + copy[maxlen] = '\0'; + } + else + { + memcpy (copy, token->val.str.text, copylen); + copy[copylen] = '\0'; + } real_from_string3 (&real, copy, TYPE_MODE (const_type)); if (const_type != type) diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c index abbb0cbaf6e..8915f441d7d 100644 --- a/gcc/c-family/c-pragma.c +++ b/gcc/c-family/c-pragma.c @@ -309,7 +309,7 @@ maybe_apply_pending_pragma_weaks (void) tree alias_id, id, decl; int i; pending_weak *pe; - symtab_node target; + symtab_node *target; if (!pending_weaks) return; @@ -324,7 +324,7 @@ maybe_apply_pending_pragma_weaks (void) target = symtab_node_for_asm (id); decl = build_decl (UNKNOWN_LOCATION, - target ? TREE_CODE (target->symbol.decl) : FUNCTION_DECL, + target ? TREE_CODE (target->decl) : FUNCTION_DECL, alias_id, default_function_type); DECL_ARTIFICIAL (decl) = 1; @@ -1364,6 +1364,8 @@ init_pragma (void) cpp_register_deferred_pragma (parse_in, "GCC", "pch_preprocess", PRAGMA_GCC_PCH_PREPROCESS, false, false); + cpp_register_deferred_pragma (parse_in, "GCC", "ivdep", PRAGMA_IVDEP, false, + false); #ifdef HANDLE_PRAGMA_PACK_WITH_EXPANSION c_register_pragma_with_expansion (0, "pack", handle_pragma_pack); #else diff --git a/gcc/c-family/c-pragma.h b/gcc/c-family/c-pragma.h index c421284a5c4..705bcb472a9 100644 --- a/gcc/c-family/c-pragma.h +++ b/gcc/c-family/c-pragma.h @@ -53,6 +53,7 @@ typedef enum pragma_kind { PRAGMA_OMP_TEAMS, PRAGMA_GCC_PCH_PREPROCESS, + PRAGMA_IVDEP, PRAGMA_FIRST_EXTERNAL } pragma_kind; diff --git a/gcc/c-family/c-ubsan.c b/gcc/c-family/c-ubsan.c index 0bfc660cdd5..c9896381db2 100644 --- a/gcc/c-family/c-ubsan.c +++ b/gcc/c-family/c-ubsan.c @@ -25,7 +25,6 @@ along with GCC; see the file COPYING3. If not see #include "alloc-pool.h" #include "cgraph.h" #include "gimple.h" -#include "hash-table.h" #include "output.h" #include "toplev.h" #include "ubsan.h" @@ -86,8 +85,7 @@ ubsan_instrument_division (location_t loc, tree op0, tree op1) return t; } -/* Instrument left and right shifts. If not instrumenting, return - NULL_TREE. */ +/* Instrument left and right shifts. */ tree ubsan_instrument_shift (location_t loc, enum tree_code code, @@ -158,3 +156,22 @@ ubsan_instrument_shift (location_t loc, enum tree_code code, return t; } + +/* Instrument variable length array bound. */ + +tree +ubsan_instrument_vla (location_t loc, tree size) +{ + tree type = TREE_TYPE (size); + tree t, tt; + + t = fold_build2 (LE_EXPR, boolean_type_node, size, build_int_cst (type, 0)); + tree data = ubsan_create_data ("__ubsan_vla_data", + loc, ubsan_type_descriptor (type), NULL_TREE); + data = build_fold_addr_expr_loc (loc, data); + tt = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_VLA_BOUND_NOT_POSITIVE); + tt = build_call_expr_loc (loc, tt, 2, data, ubsan_encode_value (size)); + t = fold_build3 (COND_EXPR, void_type_node, t, tt, void_zero_node); + + return t; +} diff --git a/gcc/c-family/c-ubsan.h b/gcc/c-family/c-ubsan.h index b032b707cc3..fdf27d9e21e 100644 --- a/gcc/c-family/c-ubsan.h +++ b/gcc/c-family/c-ubsan.h @@ -23,5 +23,6 @@ along with GCC; see the file COPYING3. If not see extern tree ubsan_instrument_division (location_t, tree, tree); extern tree ubsan_instrument_shift (location_t, enum tree_code, tree, tree); +extern tree ubsan_instrument_vla (location_t, tree); #endif /* GCC_C_UBSAN_H */ diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index e8dde935c16..b862eb9e276 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -538,8 +538,7 @@ C ObjC Var(warn_missing_prototypes) Warning Warn about global functions without prototypes Wmudflap -C ObjC C++ ObjC++ Var(warn_mudflap) Init(1) Warning -Warn about constructs not instrumented by -fmudflap +C ObjC C++ ObjC++ Ignore Warn(switch %qs is no longer supported) Wmultichar C ObjC C++ ObjC++ Warning @@ -997,16 +996,13 @@ C ObjC C++ ObjC++ Var(flag_ms_extensions) Don't warn about uses of Microsoft extensions fmudflap -C ObjC C++ ObjC++ RejectNegative Report Var(flag_mudflap) -Add mudflap bounds-checking instrumentation for single-threaded program +C ObjC C++ ObjC++ Ignore Warn(switch %qs is no longer supported) fmudflapth -C ObjC C++ ObjC++ RejectNegative Report Var(flag_mudflap,2) -Add mudflap bounds-checking instrumentation for multi-threaded program +C ObjC C++ ObjC++ Ignore Warn(switch %qs is no longer supported) fmudflapir -C ObjC C++ ObjC++ RejectNegative Report Var(flag_mudflap_ignore_reads) -Ignore read operations when inserting mudflap instrumentation +C ObjC C++ ObjC++ Ignore Warn(switch %qs is no longer supported) fname-mangling-version- C++ ObjC++ Joined Ignore Warn(switch %qs is no longer supported) diff --git a/gcc/c-family/cilk.c b/gcc/c-family/cilk.c new file mode 100644 index 00000000000..1fde1c549c2 --- /dev/null +++ b/gcc/c-family/cilk.c @@ -0,0 +1,1305 @@ +/* This file is part of the Intel(R) Cilk(TM) Plus support + This file contains the CilkPlus Intrinsics + Copyright (C) 2013 Free Software Foundation, Inc. + Contributed by Balaji V. Iyer <balaji.v.iyer@intel.com>, + Intel Corporation + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tree.h" +#include "langhooks.h" +#include "gimple.h" +#include "tree-iterator.h" +#include "tree-inline.h" +#include "c-family/c-common.h" +#include "toplev.h" +#include "cgraph.h" +#include "diagnostic.h" +#include "cilk.h" + +enum add_variable_type { + /* Reference to previously-defined variable. */ + ADD_READ, + /* Definition of a new variable in inner-scope. */ + ADD_BIND, + /* Write to possibly previously-defined variable. */ + ADD_WRITE +}; + +enum cilk_block_type { + /* Indicates a _Cilk_spawn block. 30 was an arbitary number picked for + ease of debugging. */ + CILK_BLOCK_SPAWN = 30, + /* Indicates _Cilk_for statement block. */ + CILK_BLOCK_FOR +}; + +struct wrapper_data +{ + /* Kind of function to be created. */ + enum cilk_block_type type; + /* Signature of helper function. */ + tree fntype; + /* Containing function. */ + tree context; + /* Disposition of all variables in the inner statement. */ + struct pointer_map_t *decl_map; + /* True if this function needs a static chain. */ + bool nested; + /* Arguments to be passed to wrapper function, currently a list. */ + tree arglist; + /* Argument types, a list. */ + tree argtypes; + /* Incoming parameters. */ + tree parms; + /* Outer BLOCK object. */ + tree block; +}; + +static void extract_free_variables (tree, struct wrapper_data *, + enum add_variable_type); +static HOST_WIDE_INT cilk_wrapper_count; + +/* Marks the CALL_EXPR or FUNCTION_DECL, FCALL, as a spawned function call + and the current function as a spawner. Emit error if the function call + is outside a function or if a non function-call is spawned. */ + +inline bool +cilk_set_spawn_marker (location_t loc, tree fcall) +{ + if (!current_function_decl) + { + error_at (loc, "%<_Cilk_spawn%> may only be used inside a function"); + return false; + } + else if (fcall == error_mark_node) + /* Error reporting here is not necessary here since if FCALL is an + error_mark_node, the function marking it as error would have reported + it. */ + return false; + else if (TREE_CODE (fcall) != CALL_EXPR + && TREE_CODE (fcall) != FUNCTION_DECL + /* In C++, TARGET_EXPR is generated when we have an overloaded + '=' operator. */ + && TREE_CODE (fcall) != TARGET_EXPR) + { + error_at (loc, "only function calls can be spawned"); + return false; + } + else + { + cfun->calls_cilk_spawn = true; + return true; + } +} + +/* This function will output the exit conditions for a spawn call. */ + +tree +create_cilk_function_exit (tree frame, bool detaches, bool needs_sync) +{ + tree epi = alloc_stmt_list (); + + if (needs_sync) + append_to_statement_list (build_cilk_sync (), &epi); + tree func_ptr = build1 (ADDR_EXPR, cilk_frame_ptr_type_decl, frame); + tree pop_frame = build_call_expr (cilk_pop_fndecl, 1, func_ptr); + tree worker = cilk_dot (frame, CILK_TI_FRAME_WORKER, 0); + tree current = cilk_arrow (worker, CILK_TI_WORKER_CUR, 0); + tree parent = cilk_dot (frame, CILK_TI_FRAME_PARENT, 0); + tree set_current = build2 (MODIFY_EXPR, void_type_node, current, parent); + append_to_statement_list (set_current, &epi); + append_to_statement_list (pop_frame, &epi); + tree call = build_call_expr (cilk_leave_fndecl, 1, func_ptr); + if (!detaches) + { + tree flags = cilk_dot (frame, CILK_TI_FRAME_FLAGS, false); + tree flags_cmp_expr = fold_build2 (NE_EXPR, TREE_TYPE (flags), flags, + build_int_cst (TREE_TYPE (flags), + CILK_FRAME_VERSION)); + call = fold_build3 (COND_EXPR, void_type_node, flags_cmp_expr, + call, build_empty_stmt (EXPR_LOCATION (flags))); + } + append_to_statement_list (call, &epi); + return epi; +} + +/* Trying to get the correct cfun for the FUNCTION_DECL indicated by OUTER. */ + +static void +pop_cfun_to (tree outer) +{ + pop_cfun (); + current_function_decl = outer; + gcc_assert (cfun == DECL_STRUCT_FUNCTION (current_function_decl)); + gcc_assert (cfun->decl == current_function_decl); +} + +/* This function does whatever is necessary to make the compiler emit a newly + generated function, FNDECL. */ + +static void +call_graph_add_fn (tree fndecl) +{ + const tree outer = current_function_decl; + struct function *f = DECL_STRUCT_FUNCTION (fndecl); + gcc_assert (TREE_CODE (fndecl) == FUNCTION_DECL); + + f->is_cilk_function = 1; + f->curr_properties = cfun->curr_properties; + gcc_assert (cfun == DECL_STRUCT_FUNCTION (outer)); + gcc_assert (cfun->decl == outer); + + push_cfun (f); + cgraph_create_node (fndecl); + pop_cfun_to (outer); +} + +/* Return true if this is a tree which is allowed to contain a spawn as + operand 0. + A spawn call may be wrapped in a series of unary operations such + as conversions. These conversions need not be "useless" + to be disregarded because they are retained in the spawned + statement. They are bypassed only to look for a spawn + within. + A comparison to constant is simple enough to allow, and + is used to convert to bool. */ + +static bool +cilk_ignorable_spawn_rhs_op (tree exp) +{ + enum tree_code code = TREE_CODE (exp); + switch (TREE_CODE_CLASS (code)) + { + case tcc_expression: + return code == ADDR_EXPR; + case tcc_comparison: + /* We need the spawn as operand 0 for now. That's where it + appears in the only case we really care about, conversion + to bool. */ + return (TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST); + case tcc_unary: + case tcc_reference: + return true; + default: + return false; + } +} + +/* Helper function for walk_tree. If *TP is a CILK_SPAWN_STMT, then unwrap + this "wrapper." The function returns NULL_TREE regardless. */ + +static tree +unwrap_cilk_spawn_stmt (tree *tp, int *walk_subtrees, void *) +{ + if (TREE_CODE (*tp) == CILK_SPAWN_STMT) + { + *tp = CILK_SPAWN_FN (*tp); + *walk_subtrees = 0; + } + return NULL_TREE; +} + +/* Returns true when EXP is a CALL_EXPR with _Cilk_spawn in front. Unwraps + CILK_SPAWN_STMT wrapper from the CALL_EXPR in *EXP0 statement. */ + +static bool +recognize_spawn (tree exp, tree *exp0) +{ + bool spawn_found = false; + if (TREE_CODE (exp) == CILK_SPAWN_STMT) + { + /* Remove the CALL_EXPR from CILK_SPAWN_STMT wrapper. */ + exp = CILK_SPAWN_FN (exp); + walk_tree (exp0, unwrap_cilk_spawn_stmt, NULL, NULL); + spawn_found = true; + } + return spawn_found; +} + +/* Returns true if *EXP0 is a recognized form of spawn. Recognized forms are, + after conversion to void, a call expression at outer level or an assignment + at outer level with the right hand side being a spawned call. + In addition to this, it also unwraps the CILK_SPAWN_STMT cover from the + CALL_EXPR that is being spawned. + Note that `=' in C++ may turn into a CALL_EXPR rather than a MODIFY_EXPR. */ + +bool +cilk_detect_spawn_and_unwrap (tree *exp0) +{ + tree exp = *exp0; + + if (!TREE_SIDE_EFFECTS (exp)) + return false; + + /* Strip off any conversion to void. It does not affect whether spawn + is supported here. */ + if (TREE_CODE (exp) == CONVERT_EXPR && VOID_TYPE_P (TREE_TYPE (exp))) + exp = TREE_OPERAND (exp, 0); + + if (TREE_CODE (exp) == MODIFY_EXPR || TREE_CODE (exp) == INIT_EXPR) + exp = TREE_OPERAND (exp, 1); + + while (cilk_ignorable_spawn_rhs_op (exp)) + exp = TREE_OPERAND (exp, 0); + + if (TREE_CODE (exp) == TARGET_EXPR) + if (TARGET_EXPR_INITIAL (exp) + && TREE_CODE (TARGET_EXPR_INITIAL (exp)) != AGGR_INIT_EXPR) + exp = TARGET_EXPR_INITIAL (exp); + + /* Happens with C++ TARGET_EXPR. */ + if (exp == NULL_TREE) + return false; + + while (TREE_CODE (exp) == CLEANUP_POINT_EXPR || TREE_CODE (exp) == EXPR_STMT) + exp = TREE_OPERAND (exp, 0); + + /* Now we should have a CALL_EXPR with a CILK_SPAWN_STMT wrapper around + it, or return false. */ + if (recognize_spawn (exp, exp0)) + return true; + return false; +} + +/* This function will build and return a FUNCTION_DECL using information + from *WD. */ + +static tree +create_cilk_helper_decl (struct wrapper_data *wd) +{ + char name[20]; + if (wd->type == CILK_BLOCK_FOR) + sprintf (name, "_cilk_for_" HOST_WIDE_INT_PRINT_DEC, cilk_wrapper_count++); + else if (wd->type == CILK_BLOCK_SPAWN) + sprintf (name, "_cilk_spn_" HOST_WIDE_INT_PRINT_DEC, cilk_wrapper_count++); + else + gcc_unreachable (); + + clean_symbol_name (name); + tree fndecl = build_decl (UNKNOWN_LOCATION, FUNCTION_DECL, + get_identifier (name), wd->fntype); + + TREE_PUBLIC (fndecl) = 0; + TREE_STATIC (fndecl) = 1; + TREE_USED (fndecl) = 1; + DECL_ARTIFICIAL (fndecl) = 0; + DECL_IGNORED_P (fndecl) = 0; + DECL_EXTERNAL (fndecl) = 0; + + DECL_CONTEXT (fndecl) = wd->context; + tree block = make_node (BLOCK); + DECL_INITIAL (fndecl) = block; + TREE_USED (block) = 1; + gcc_assert (!DECL_SAVED_TREE (fndecl)); + + /* Inlining would defeat the purpose of this wrapper. + Either it secretly switches stack frames or it allocates + a stable stack frame to hold function arguments even if + the parent stack frame is stolen. */ + DECL_UNINLINABLE (fndecl) = 1; + + tree result_decl = build_decl (UNKNOWN_LOCATION, RESULT_DECL, NULL_TREE, + void_type_node); + DECL_ARTIFICIAL (result_decl) = 0; + DECL_IGNORED_P (result_decl) = 1; + DECL_CONTEXT (result_decl) = fndecl; + DECL_RESULT (fndecl) = result_decl; + + return fndecl; +} + +/* A function used by walk tree to find wrapper parms. */ + +static bool +wrapper_parm_cb (const void *key0, void **val0, void *data) +{ + struct wrapper_data *wd = (struct wrapper_data *) data; + tree arg = * (tree *)&key0; + tree val = (tree)*val0; + tree parm; + + if (val == error_mark_node || val == arg) + return true; + + if (TREE_CODE (val) == PAREN_EXPR) + { + /* We should not reach here with a register receiver. + We may see a register variable modified in the + argument list. Because register variables are + worker-local we don't need to work hard to support + them in code that spawns. */ + if ((TREE_CODE (arg) == VAR_DECL) && DECL_HARD_REGISTER (arg)) + { + error_at (EXPR_LOCATION (arg), + "explicit register variable %qD may not be modified in " + "spawn", arg); + arg = null_pointer_node; + } + else + arg = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (arg)), arg); + + val = TREE_OPERAND (val, 0); + *val0 = val; + gcc_assert (TREE_CODE (val) == INDIRECT_REF); + parm = TREE_OPERAND (val, 0); + STRIP_NOPS (parm); + } + else + parm = val; + TREE_CHAIN (parm) = wd->parms; + wd->parms = parm; + wd->argtypes = tree_cons (NULL_TREE, TREE_TYPE (parm), wd->argtypes); + wd->arglist = tree_cons (NULL_TREE, arg, wd->arglist); + return true; +} + +/* This function is used to build a wrapper of a certain type. */ + +static void +build_wrapper_type (struct wrapper_data *wd) +{ + wd->arglist = NULL_TREE; + wd->parms = NULL_TREE; + wd->argtypes = void_list_node; + + pointer_map_traverse (wd->decl_map, wrapper_parm_cb, wd); + gcc_assert (wd->type != CILK_BLOCK_FOR); + + /* Now build a function. + Its return type is void (all side effects are via explicit parameters). + Its parameters are WRAPPER_PARMS with type WRAPPER_TYPES. + Actual arguments in the caller are WRAPPER_ARGS. */ + wd->fntype = build_function_type (void_type_node, wd->argtypes); +} + +/* This function checks all the CALL_EXPRs in *TP found by cilk_outline. */ + +static tree +check_outlined_calls (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED, + void *data) +{ + bool *throws = (bool *) data; + tree t = *tp; + int flags; + + if (TREE_CODE (t) != CALL_EXPR) + return 0; + flags = call_expr_flags (t); + + if (!(flags & ECF_NOTHROW) && flag_exceptions) + *throws = true; + if (flags & ECF_RETURNS_TWICE) + error_at (EXPR_LOCATION (t), + "cannot spawn call to function that returns twice"); + return 0; +} + +/* Each DECL in the source code (spawned statement) is passed to this function + once. Each instance of the DECL is replaced with the result of this + function. + + The parameters of the wrapper should have been entered into the map already. + This function only deals with variables with scope limited to the + spawned expression. */ + +static tree +copy_decl_for_cilk (tree decl, copy_body_data *id) +{ + switch (TREE_CODE (decl)) + { + case VAR_DECL: + return copy_decl_no_change (decl, id); + + case LABEL_DECL: + error_at (EXPR_LOCATION (decl), "invalid use of label %q+D in " + "%<_Cilk_spawn%>", + decl); + return error_mark_node; + + case RESULT_DECL: + case PARM_DECL: + /* RESULT_DECL and PARM_DECL has already been entered into the map. */ + default: + gcc_unreachable (); + return error_mark_node; + } +} + +/* Copy all local variables. */ + +static bool +for_local_cb (const void *k_v, void **vp, void *p) +{ + tree k = *(tree *) &k_v; + tree v = (tree) *vp; + + if (v == error_mark_node) + *vp = copy_decl_no_change (k, (copy_body_data *) p); + return true; +} + +/* Copy all local declarations from a _Cilk_spawned function's body. */ + +static bool +wrapper_local_cb (const void *k_v, void **vp, void *data) +{ + copy_body_data *id = (copy_body_data *) data; + tree key = *(tree *) &k_v; + tree val = (tree) *vp; + + if (val == error_mark_node) + *vp = copy_decl_for_cilk (key, id); + + return true; +} + +/* Alter a tree STMT from OUTER_FN to form the body of INNER_FN. */ + +static void +cilk_outline (tree inner_fn, tree *stmt_p, struct wrapper_data *wd) +{ + const tree outer_fn = wd->context; + const bool nested = (wd->type == CILK_BLOCK_FOR); + copy_body_data id; + bool throws; + + DECL_STATIC_CHAIN (outer_fn) = 1; + + memset (&id, 0, sizeof (id)); + /* Copy from the function containing the spawn... */ + id.src_fn = outer_fn; + + /* ...to the wrapper. */ + id.dst_fn = inner_fn; + id.src_cfun = DECL_STRUCT_FUNCTION (outer_fn); + + /* There shall be no RETURN in spawn helper. */ + id.retvar = 0; + id.decl_map = wd->decl_map; + id.copy_decl = nested ? copy_decl_no_change : copy_decl_for_cilk; + id.block = DECL_INITIAL (inner_fn); + id.transform_lang_insert_block = NULL; + + id.transform_new_cfg = true; + id.transform_call_graph_edges = CB_CGE_MOVE; + id.remap_var_for_cilk = true; + id.regimplify = true; /* unused? */ + + insert_decl_map (&id, wd->block, DECL_INITIAL (inner_fn)); + + /* We don't want the private variables any more. */ + pointer_map_traverse (wd->decl_map, nested ? for_local_cb : wrapper_local_cb, + &id); + + walk_tree (stmt_p, copy_tree_body_r, &id, NULL); + + /* See if this function can throw or calls something that should + not be spawned. The exception part is only necessary if + flag_exceptions && !flag_non_call_exceptions. */ + throws = false ; + (void) walk_tree_without_duplicates (stmt_p, check_outlined_calls, &throws); +} + +/* Generate the body of a wrapper function that assigns the + result of the expression RHS into RECEIVER. RECEIVER must + be NULL if this is not a spawn -- the wrapper will return + a value. If this is a spawn, the wrapper will return void. */ + +static tree +create_cilk_wrapper_body (tree stmt, struct wrapper_data *wd) +{ + const tree outer = current_function_decl; + tree fndecl; + tree p; + + /* Build the type of the wrapper and its argument list from the + variables that it requires. */ + build_wrapper_type (wd); + + /* Emit a function that takes WRAPPER_PARMS incoming and applies ARGS + (modified) to the wrapped function. Return the wrapper and modified ARGS + to the caller to generate a function call. */ + fndecl = create_cilk_helper_decl (wd); + push_struct_function (fndecl); + if (wd->nested && (wd->type == CILK_BLOCK_FOR)) + { + gcc_assert (TREE_VALUE (wd->arglist) == NULL_TREE); + TREE_VALUE (wd->arglist) = build2 (FDESC_EXPR, ptr_type_node, + fndecl, integer_one_node); + } + DECL_ARGUMENTS (fndecl) = wd->parms; + + for (p = wd->parms; p; p = TREE_CHAIN (p)) + DECL_CONTEXT (p) = fndecl; + + cilk_outline (fndecl, &stmt, wd); + stmt = fold_build_cleanup_point_expr (void_type_node, stmt); + gcc_assert (!DECL_SAVED_TREE (fndecl)); + lang_hooks.cilkplus.install_body_with_frame_cleanup (fndecl, stmt); + gcc_assert (DECL_SAVED_TREE (fndecl)); + + pop_cfun_to (outer); + + /* Recognize the new function. */ + call_graph_add_fn (fndecl); + return fndecl; +} + +/* Initializes the wrapper data structure. */ + +static void +init_wd (struct wrapper_data *wd, enum cilk_block_type type) +{ + wd->type = type; + wd->fntype = NULL_TREE; + wd->context = current_function_decl; + wd->decl_map = pointer_map_create (); + /* _Cilk_for bodies are always nested. Others start off as + normal functions. */ + wd->nested = (type == CILK_BLOCK_FOR); + wd->arglist = NULL_TREE; + wd->argtypes = NULL_TREE; + wd->block = NULL_TREE; +} + +/* Clears the wrapper data structure. */ + +static void +free_wd (struct wrapper_data *wd) +{ + pointer_map_destroy (wd->decl_map); + wd->nested = false; + wd->arglist = NULL_TREE; + wd->argtypes = NULL_TREE; + wd->parms = NULL_TREE; +} + + + /* Given a variable in an expression to be extracted into + a helper function, declare the helper function parameter + to receive it. + + On entry the value of the (key, value) pair may be + + (*, error_mark_node) -- Variable is private to helper function, + do nothing. + + (var, var) -- Reference to outer scope (function or global scope). + + (var, integer 0) -- Capture by value, save newly-declared PARM_DECL + for value in value slot. + + (var, integer 1) -- Capture by reference, declare pointer to type + as new PARM_DECL and store (spawn_stmt (indirect_ref (parm)). + + (var, ???) -- Pure output argument, handled similarly to above. +*/ + +static bool +declare_one_free_variable (const void *var0, void **map0, + void *data ATTRIBUTE_UNUSED) +{ + const_tree var = (const_tree) var0; + tree map = (tree)*map0; + tree var_type = TREE_TYPE (var), arg_type; + bool by_reference; + tree parm; + + gcc_assert (DECL_P (var)); + + /* Ignore truly local variables. */ + if (map == error_mark_node) + return true; + /* Ignore references to the parent function. */ + if (map == var) + return true; + + gcc_assert (TREE_CODE (map) == INTEGER_CST); + + /* A value is passed by reference if: + + 1. It is addressable, so that a copy may not be made. + 2. It is modified in the spawned statement. + In the future this function may want to arrange + a warning if the spawned statement is a loop body + because an output argument would indicate a race. + Note: Earlier passes must have marked the variable addressable. + 3. It is expensive to copy. */ + by_reference = + (TREE_ADDRESSABLE (var_type) + /* Arrays must be passed by reference. This is required for C + semantics -- arrays are not first class objects. Other + aggregate types can and should be passed by reference if + they are not passed to the spawned function. We aren't yet + distinguishing safe uses in argument calculation from unsafe + uses as outgoing function arguments, so we make a copy to + stabilize the value. */ + || TREE_CODE (var_type) == ARRAY_TYPE + || (tree) map == integer_one_node); + + if (by_reference) + var_type = build_qualified_type (build_pointer_type (var_type), + TYPE_QUAL_RESTRICT); + gcc_assert (!TREE_ADDRESSABLE (var_type)); + + /* Maybe promote to int. */ + if (INTEGRAL_TYPE_P (var_type) && COMPLETE_TYPE_P (var_type) + && INT_CST_LT (TYPE_SIZE (var_type), + TYPE_SIZE (integer_type_node))) + arg_type = integer_type_node; + else + arg_type = var_type; + + parm = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL_TREE, var_type); + DECL_ARG_TYPE (parm) = arg_type; + DECL_ARTIFICIAL (parm) = 0; + TREE_READONLY (parm) = 1; + + if (by_reference) + { + parm = build1 (INDIRECT_REF, TREE_TYPE (var_type), parm); + parm = build1 (PAREN_EXPR, void_type_node, parm); + } + *map0 = parm; + return true; +} + +/* Returns a wrapper function for a _Cilk_spawn. */ + +static tree +create_cilk_wrapper (tree exp, tree *args_out) +{ + struct wrapper_data wd; + tree fndecl; + + init_wd (&wd, CILK_BLOCK_SPAWN); + + if (TREE_CODE (exp) == CONVERT_EXPR) + exp = TREE_OPERAND (exp, 0); + + /* Special handling for top level INIT_EXPR. Usually INIT_EXPR means the + variable is defined in the spawned expression and can be private to the + spawn helper. A top level INIT_EXPR defines a variable to be initialized + by spawn and the variable must remain in the outer function. */ + if (TREE_CODE (exp) == INIT_EXPR) + { + extract_free_variables (TREE_OPERAND (exp, 0), &wd, ADD_WRITE); + extract_free_variables (TREE_OPERAND (exp, 1), &wd, ADD_READ); + /* TREE_TYPE should be void. Be defensive. */ + if (TREE_TYPE (exp) != void_type_node) + extract_free_variables (TREE_TYPE (exp), &wd, ADD_READ); + } + else + extract_free_variables (exp, &wd, ADD_READ); + pointer_map_traverse (wd.decl_map, declare_one_free_variable, &wd); + wd.block = TREE_BLOCK (exp); + if (!wd.block) + wd.block = DECL_INITIAL (current_function_decl); + + /* Now fvars maps the old variable to incoming variable. Update + the expression and arguments to refer to the new names. */ + fndecl = create_cilk_wrapper_body (exp, &wd); + *args_out = wd.arglist; + + free_wd (&wd); + + return fndecl; +} + +/* Transform *SPAWN_P, a spawned CALL_EXPR, to gimple. *SPAWN_P can be a + CALL_EXPR, INIT_EXPR or MODIFY_EXPR. Returns GS_OK if everything is fine, + and GS_UNHANDLED, otherwise. */ + +int +gimplify_cilk_spawn (tree *spawn_p, gimple_seq *before ATTRIBUTE_UNUSED, + gimple_seq *after ATTRIBUTE_UNUSED) +{ + tree expr = *spawn_p; + tree function, call1, call2, new_args; + tree ii_args = NULL_TREE; + int total_args = 0, ii = 0; + tree *arg_array; + tree setjmp_cond_expr = NULL_TREE; + tree setjmp_expr, spawn_expr, setjmp_value = NULL_TREE; + + cfun->calls_cilk_spawn = 1; + cfun->is_cilk_function = 1; + + /* Remove CLEANUP_POINT_EXPR and EXPR_STMT from *spawn_p. */ + while (TREE_CODE (expr) == CLEANUP_POINT_EXPR + || TREE_CODE (expr) == EXPR_STMT) + expr = TREE_OPERAND (expr, 0); + + new_args = NULL; + function = create_cilk_wrapper (expr, &new_args); + + /* This should give the number of parameters. */ + total_args = list_length (new_args); + arg_array = XNEWVEC (tree, total_args); + + ii_args = new_args; + for (ii = 0; ii < total_args; ii++) + { + arg_array[ii] = TREE_VALUE (ii_args); + ii_args = TREE_CHAIN (ii_args); + } + + TREE_USED (function) = 1; + rest_of_decl_compilation (function, 0, 0); + + call1 = cilk_call_setjmp (cfun->cilk_frame_decl); + + if (*arg_array == NULL_TREE) + call2 = build_call_expr (function, 0); + else + call2 = build_call_expr_loc_array (EXPR_LOCATION (*spawn_p), function, + total_args, arg_array); + *spawn_p = alloc_stmt_list (); + tree f_ptr_type = build_pointer_type (TREE_TYPE (cfun->cilk_frame_decl)); + tree frame_ptr = build1 (ADDR_EXPR, f_ptr_type, cfun->cilk_frame_decl); + tree save_fp = build_call_expr (cilk_save_fp_fndecl, 1, frame_ptr); + append_to_statement_list (save_fp, spawn_p); + setjmp_value = create_tmp_var (TREE_TYPE (call1), NULL); + setjmp_expr = fold_build2 (MODIFY_EXPR, void_type_node, setjmp_value, call1); + + append_to_statement_list_force (setjmp_expr, spawn_p); + + setjmp_cond_expr = fold_build2 (EQ_EXPR, TREE_TYPE (call1), setjmp_value, + build_int_cst (TREE_TYPE (call1), 0)); + spawn_expr = fold_build3 (COND_EXPR, void_type_node, setjmp_cond_expr, + call2, build_empty_stmt (EXPR_LOCATION (call1))); + append_to_statement_list (spawn_expr, spawn_p); + + return GS_OK; +} + +/* Make the frames necessary for a spawn call. */ + +tree +make_cilk_frame (tree fn) +{ + struct function *f = DECL_STRUCT_FUNCTION (fn); + tree decl; + + if (f->cilk_frame_decl) + return f->cilk_frame_decl; + + decl = build_decl (EXPR_LOCATION (fn), VAR_DECL, NULL_TREE, + cilk_frame_type_decl); + DECL_CONTEXT (decl) = fn; + DECL_SEEN_IN_BIND_EXPR_P (decl) = 1; + f->cilk_frame_decl = decl; + return decl; +} + +/* Returns a STATEMENT_LIST with all the pedigree operations required for + install body with frame cleanup functions. FRAME_PTR is the pointer to + __cilkrts_stack_frame created by make_cilk_frame. */ + +tree +cilk_install_body_pedigree_operations (tree frame_ptr) +{ + tree body_list = alloc_stmt_list (); + tree enter_frame = build_call_expr (cilk_enter_fast_fndecl, 1, frame_ptr); + append_to_statement_list (enter_frame, &body_list); + + tree parent = cilk_arrow (frame_ptr, CILK_TI_FRAME_PARENT, 0); + tree worker = cilk_arrow (frame_ptr, CILK_TI_FRAME_WORKER, 0); + + tree pedigree = cilk_arrow (frame_ptr, CILK_TI_FRAME_PEDIGREE, 0); + tree pedigree_rank = cilk_dot (pedigree, CILK_TI_PEDIGREE_RANK, 0); + tree parent_pedigree = cilk_dot (pedigree, CILK_TI_PEDIGREE_PARENT, 0); + tree pedigree_parent = cilk_arrow (parent, CILK_TI_FRAME_PEDIGREE, 0); + tree pedigree_parent_rank = cilk_dot (pedigree_parent, + CILK_TI_PEDIGREE_RANK, 0); + tree pedigree_parent_parent = cilk_dot (pedigree_parent, + CILK_TI_PEDIGREE_PARENT, 0); + tree worker_pedigree = cilk_arrow (worker, CILK_TI_WORKER_PEDIGREE, 1); + tree w_pedigree_rank = cilk_dot (worker_pedigree, CILK_TI_PEDIGREE_RANK, 0); + tree w_pedigree_parent = cilk_dot (worker_pedigree, + CILK_TI_PEDIGREE_PARENT, 0); + + /* sf.pedigree.rank = worker->pedigree.rank. */ + tree exp1 = build2 (MODIFY_EXPR, void_type_node, pedigree_rank, + w_pedigree_rank); + append_to_statement_list (exp1, &body_list); + + /* sf.pedigree.parent = worker->pedigree.parent. */ + exp1 = build2 (MODIFY_EXPR, void_type_node, parent_pedigree, + w_pedigree_parent); + append_to_statement_list (exp1, &body_list); + + /* sf.call_parent->pedigree.rank = worker->pedigree.rank. */ + exp1 = build2 (MODIFY_EXPR, void_type_node, pedigree_parent_rank, + w_pedigree_rank); + append_to_statement_list (exp1, &body_list); + + /* sf.call_parent->pedigree.parent = worker->pedigree.parent. */ + exp1 = build2 (MODIFY_EXPR, void_type_node, pedigree_parent_parent, + w_pedigree_parent); + append_to_statement_list (exp1, &body_list); + + /* sf->worker.pedigree.rank = 0. */ + exp1 = build2 (MODIFY_EXPR, void_type_node, w_pedigree_rank, + build_zero_cst (uint64_type_node)); + append_to_statement_list (exp1, &body_list); + + /* sf->pedigree.parent = &sf->pedigree. */ + exp1 = build2 (MODIFY_EXPR, void_type_node, w_pedigree_parent, + build1 (ADDR_EXPR, + build_pointer_type (cilk_pedigree_type_decl), + pedigree)); + append_to_statement_list (exp1, &body_list); + return body_list; +} + +/* Inserts "cleanup" functions after the function-body of FNDECL. FNDECL is a + spawn-helper and BODY is the newly created body for FNDECL. */ + +void +c_cilk_install_body_w_frame_cleanup (tree fndecl, tree body) +{ + tree list = alloc_stmt_list (); + tree frame = make_cilk_frame (fndecl); + tree dtor = create_cilk_function_exit (frame, false, true); + add_local_decl (cfun, frame); + + DECL_SAVED_TREE (fndecl) = list; + tree frame_ptr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (frame)), + frame); + tree body_list = cilk_install_body_pedigree_operations (frame_ptr); + gcc_assert (TREE_CODE (body_list) == STATEMENT_LIST); + + tree detach_expr = build_call_expr (cilk_detach_fndecl, 1, frame_ptr); + append_to_statement_list (detach_expr, &body_list); + append_to_statement_list (body, &body_list); + append_to_statement_list (build_stmt (EXPR_LOCATION (body), TRY_FINALLY_EXPR, + body_list, dtor), &list); +} + +/* Add a new variable, VAR to a variable list in WD->DECL_MAP. HOW indicates + whether the variable is previously defined, currently defined, or a variable + that is being written to. */ + +static void +add_variable (struct wrapper_data *wd, tree var, enum add_variable_type how) +{ + void **valp; + + valp = pointer_map_contains (wd->decl_map, (void *) var); + if (valp) + { + tree val = (tree) *valp; + /* If the variable is local, do nothing. */ + if (val == error_mark_node) + return; + /* If the variable was entered with itself as value, + meaning it belongs to an outer scope, do not alter + the value. */ + if (val == var) + return; + /* A statement expression may cause a variable to be + bound twice, once in BIND_EXPR and again in a + DECL_EXPR. That case caused a return in the + test above. Any other duplicate definition is + an error. */ + gcc_assert (how != ADD_BIND); + if (how != ADD_WRITE) + return; + /* This variable might have been entered as read but is now written. */ + *valp = (void *) var; + wd->nested = true; + return; + } + else + { + tree val = NULL_TREE; + + /* Nested function rewriting silently discards hard register + assignments for function scope variables, and they wouldn't + work anyway. Warn here. This misses one case: if the + register variable is used as the loop bound or increment it + has already been added to the map. */ + if ((how != ADD_BIND) && (TREE_CODE (var) == VAR_DECL) + && !DECL_EXTERNAL (var) && DECL_HARD_REGISTER (var)) + warning (0, "register assignment ignored for %qD used in Cilk block", + var); + + switch (how) + { + /* ADD_BIND means always make a fresh new variable. */ + case ADD_BIND: + val = error_mark_node; + break; + /* ADD_READ means + 1. For cilk_for, refer to the outer scope definition as-is + 2. For a spawned block, take a scalar in an rgument + and otherwise refer to the outer scope definition as-is. + 3. For a spawned call, take a scalar in an argument. */ + case ADD_READ: + switch (wd->type) + { + case CILK_BLOCK_FOR: + val = var; + break; + case CILK_BLOCK_SPAWN: + if (TREE_ADDRESSABLE (var)) + { + val = var; + wd->nested = true; + break; + } + val = integer_zero_node; + break; + } + break; + case ADD_WRITE: + switch (wd->type) + { + case CILK_BLOCK_FOR: + val = var; + wd->nested = true; + break; + case CILK_BLOCK_SPAWN: + if (TREE_ADDRESSABLE (var)) + val = integer_one_node; + else + { + val = var; + wd->nested = true; + } + break; + } + } + *pointer_map_insert (wd->decl_map, (void *) var) = val; + } +} + +/* Find the variables referenced in an expression T. This does not avoid + duplicates because a variable may be read in one context and written in + another. HOW describes the context in which the reference is seen. If + NESTED is true a nested function is being generated and variables in the + original context should not be remapped. */ + +static void +extract_free_variables (tree t, struct wrapper_data *wd, + enum add_variable_type how) +{ + if (t == NULL_TREE) + return; + + enum tree_code code = TREE_CODE (t); + bool is_expr = IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code)); + + if (is_expr) + extract_free_variables (TREE_TYPE (t), wd, ADD_READ); + + switch (code) + { + case ERROR_MARK: + case IDENTIFIER_NODE: + case INTEGER_CST: + case REAL_CST: + case FIXED_CST: + case STRING_CST: + case BLOCK: + case PLACEHOLDER_EXPR: + case FIELD_DECL: + case VOID_TYPE: + case REAL_TYPE: + /* These do not contain variable references. */ + return; + + case SSA_NAME: + /* Currently we don't see SSA_NAME. */ + extract_free_variables (SSA_NAME_VAR (t), wd, how); + return; + + case LABEL_DECL: + /* This might be a reference to a label outside the Cilk block, + which is an error, or a reference to a label in the Cilk block + that we haven't seen yet. We can't tell. Ignore it. An + invalid use will cause an error later in copy_decl_for_cilk. */ + return; + + case RESULT_DECL: + if (wd->type != CILK_BLOCK_SPAWN) + TREE_ADDRESSABLE (t) = 1; + case VAR_DECL: + case PARM_DECL: + if (!TREE_STATIC (t) && !DECL_EXTERNAL (t)) + add_variable (wd, t, how); + return; + + case NON_LVALUE_EXPR: + case CONVERT_EXPR: + case NOP_EXPR: + extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_READ); + return; + + case INIT_EXPR: + extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_BIND); + extract_free_variables (TREE_OPERAND (t, 1), wd, ADD_READ); + return; + + case MODIFY_EXPR: + case PREDECREMENT_EXPR: + case PREINCREMENT_EXPR: + case POSTDECREMENT_EXPR: + case POSTINCREMENT_EXPR: + /* These write their result. */ + extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_WRITE); + extract_free_variables (TREE_OPERAND (t, 1), wd, ADD_READ); + return; + + case ADDR_EXPR: + /* This might modify its argument, and the value needs to be + passed by reference in any case to preserve identity and + type if is a promoting type. In the case of a nested loop + just notice that we touch the variable. It will already + be addressable, and marking it modified will cause a spurious + warning about writing the control variable. */ + if (wd->type != CILK_BLOCK_SPAWN) + extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_READ); + else + extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_WRITE); + return; + + case ARRAY_REF: + /* Treating ARRAY_REF and BIT_FIELD_REF identically may + mark the array as written but the end result is correct + because the array is passed by pointer anyway. */ + case BIT_FIELD_REF: + /* Propagate the access type to the object part of which + is being accessed here. As for ADDR_EXPR, don't do this + in a nested loop, unless the access is to a fixed index. */ + if (wd->type != CILK_BLOCK_FOR || TREE_CONSTANT (TREE_OPERAND (t, 1))) + extract_free_variables (TREE_OPERAND (t, 0), wd, how); + else + extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_READ); + extract_free_variables (TREE_OPERAND (t, 1), wd, ADD_READ); + extract_free_variables (TREE_OPERAND (t, 2), wd, ADD_READ); + return; + + case TREE_LIST: + extract_free_variables (TREE_PURPOSE (t), wd, ADD_READ); + extract_free_variables (TREE_VALUE (t), wd, ADD_READ); + extract_free_variables (TREE_CHAIN (t), wd, ADD_READ); + return; + + case TREE_VEC: + { + int len = TREE_VEC_LENGTH (t); + int i; + for (i = 0; i < len; i++) + extract_free_variables (TREE_VEC_ELT (t, i), wd, ADD_READ); + return; + } + + case VECTOR_CST: + { + unsigned ii = 0; + for (ii = 0; ii < VECTOR_CST_NELTS (t); ii++) + extract_free_variables (VECTOR_CST_ELT (t, ii), wd, ADD_READ); + break; + } + + case COMPLEX_CST: + extract_free_variables (TREE_REALPART (t), wd, ADD_READ); + extract_free_variables (TREE_IMAGPART (t), wd, ADD_READ); + return; + + case BIND_EXPR: + { + tree decl; + for (decl = BIND_EXPR_VARS (t); decl; decl = TREE_CHAIN (decl)) + { + add_variable (wd, decl, ADD_BIND); + /* A self-referential initialization is no problem because + we already entered the variable into the map as local. */ + extract_free_variables (DECL_INITIAL (decl), wd, ADD_READ); + extract_free_variables (DECL_SIZE (decl), wd, ADD_READ); + extract_free_variables (DECL_SIZE_UNIT (decl), wd, ADD_READ); + } + extract_free_variables (BIND_EXPR_BODY (t), wd, ADD_READ); + return; + } + + case STATEMENT_LIST: + { + tree_stmt_iterator i; + for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i)) + extract_free_variables (*tsi_stmt_ptr (i), wd, ADD_READ); + return; + } + + case TARGET_EXPR: + { + extract_free_variables (TREE_OPERAND (t, 0), wd, ADD_BIND); + extract_free_variables (TREE_OPERAND (t, 1), wd, ADD_READ); + extract_free_variables (TREE_OPERAND (t, 2), wd, ADD_READ); + if (TREE_OPERAND (t, 3) != TREE_OPERAND (t, 1)) + extract_free_variables (TREE_OPERAND (t, 3), wd, ADD_READ); + return; + } + + case RETURN_EXPR: + if (TREE_NO_WARNING (t)) + { + gcc_assert (errorcount); + return; + } + return; + + case DECL_EXPR: + if (TREE_CODE (DECL_EXPR_DECL (t)) != TYPE_DECL) + extract_free_variables (DECL_EXPR_DECL (t), wd, ADD_BIND); + return; + + case INTEGER_TYPE: + case ENUMERAL_TYPE: + case BOOLEAN_TYPE: + extract_free_variables (TYPE_MIN_VALUE (t), wd, ADD_READ); + extract_free_variables (TYPE_MAX_VALUE (t), wd, ADD_READ); + return; + + case POINTER_TYPE: + extract_free_variables (TREE_TYPE (t), wd, ADD_READ); + break; + + case ARRAY_TYPE: + extract_free_variables (TREE_TYPE (t), wd, ADD_READ); + extract_free_variables (TYPE_DOMAIN (t), wd, ADD_READ); + return; + + case RECORD_TYPE: + extract_free_variables (TYPE_FIELDS (t), wd, ADD_READ); + return; + + case METHOD_TYPE: + extract_free_variables (TYPE_ARG_TYPES (t), wd, ADD_READ); + extract_free_variables (TYPE_METHOD_BASETYPE (t), wd, ADD_READ); + return; + + case AGGR_INIT_EXPR: + case CALL_EXPR: + { + int len = 0; + int ii = 0; + if (TREE_CODE (TREE_OPERAND (t, 0)) == INTEGER_CST) + { + len = tree_to_uhwi (TREE_OPERAND (t, 0)); + + for (ii = 0; ii < len; ii++) + extract_free_variables (TREE_OPERAND (t, ii), wd, ADD_READ); + extract_free_variables (TREE_TYPE (t), wd, ADD_READ); + } + break; + } + + default: + if (is_expr) + { + int i, len; + + /* Walk over all the sub-trees of this operand. */ + len = TREE_CODE_LENGTH (code); + + /* Go through the subtrees. We need to do this in forward order so + that the scope of a FOR_EXPR is handled properly. */ + for (i = 0; i < len; ++i) + extract_free_variables (TREE_OPERAND (t, i), wd, ADD_READ); + } + } +} + + +/* Add appropriate frames needed for a Cilk spawned function call, FNDECL. + Returns the __cilkrts_stack_frame * variable. */ + +tree +insert_cilk_frame (tree fndecl) +{ + tree addr, body, enter, out, orig_body; + location_t loc = EXPR_LOCATION (fndecl); + + if (!cfun || cfun->decl != fndecl) + push_cfun (DECL_STRUCT_FUNCTION (fndecl)); + + tree decl = cfun->cilk_frame_decl; + if (!decl) + { + tree *saved_tree = &DECL_SAVED_TREE (fndecl); + decl = make_cilk_frame (fndecl); + add_local_decl (cfun, decl); + + addr = build1 (ADDR_EXPR, cilk_frame_ptr_type_decl, decl); + enter = build_call_expr (cilk_enter_fndecl, 1, addr); + out = create_cilk_function_exit (cfun->cilk_frame_decl, false, true); + + /* The new body will be: + __cilkrts_enter_frame_1 (&sf); + try { + orig_body; + } + finally { + __cilkrts_pop_frame (&sf); + __cilkrts_leave_frame (&sf); + } */ + + body = alloc_stmt_list (); + orig_body = *saved_tree; + + if (TREE_CODE (orig_body) == BIND_EXPR) + orig_body = BIND_EXPR_BODY (orig_body); + + append_to_statement_list (enter, &body); + append_to_statement_list (build_stmt (loc, TRY_FINALLY_EXPR, orig_body, + out), &body); + if (TREE_CODE (*saved_tree) == BIND_EXPR) + BIND_EXPR_BODY (*saved_tree) = body; + else + *saved_tree = body; + } + return decl; +} + +/* Wraps CALL, a CALL_EXPR, into a CILK_SPAWN_STMT tree and returns it. */ + +tree +build_cilk_spawn (location_t loc, tree call) +{ + if (!cilk_set_spawn_marker (loc, call)) + return error_mark_node; + tree spawn_stmt = build1 (CILK_SPAWN_STMT, TREE_TYPE (call), call); + TREE_SIDE_EFFECTS (spawn_stmt) = 1; + return spawn_stmt; +} + +/* Returns a tree of type CILK_SYNC_STMT. */ + +tree +build_cilk_sync (void) +{ + tree sync = build0 (CILK_SYNC_STMT, void_type_node); + TREE_SIDE_EFFECTS (sync) = 1; + return sync; +} diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 0e2409aa182..efb4ba88c38 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,57 @@ +2013-11-03 Marek Polacek <polacek@redhat.com> + + * c-decl.c (grokdeclarator): Add VLA instrumentation. + +2013-11-01 Jakub Jelinek <jakub@redhat.com> + + * c-typeck.c (c_finish_omp_clauses) <case OMP_CLAUSE_UNIFORM>: Go to + check_dup_generic at the end, unless remove is true. + (c_finish_omp_clauses) <case OMP_CLAUSE_REDUCTION>: Add break; after + remove = true;. + (c_finish_omp_clauses) <case OMP_CLAUSE_COPYIN>: Likewise. + +2013-10-31 Jakub Jelinek <jakub@redhat.com> + + * c-typeck.c (c_finish_omp_clauses): Diagnose aligned clause + with decl that is not pointer nor array. + +2013-10-29 Balaji V. Iyer <balaji.v.iyer@intel.com> + + * c-decl.c (finish_function): Added a call for insert_cilk_frame when + a spawning function is found. + * c-objc-common.h (LANG_HOOKS_CILKPLUS_GIMPLIFY_SPAWN): New #define. + (LANG_HOOKS_CILKPLUS_FRAME_CLEANUP): Likewise. + (LANG_HOOKS_CILKPLUS_DETECT_SPAWN_AND_UNWRAP): Likewise. + * c-parser.c (c_parser_statement_after_labels): Added RID_CILK_SYNC + case. + (c_parser_postfix_expression): Added RID_CILK_SPAWN case. + * c-typeck.c (build_compound_expr): Reject _Cilk_spawn in a comma + expr. + (c_finish_return): Added a check to reject _Cilk_spawn in return + expression. + (build_cilk_spawn): New function. + (build_cilk_sync): Likewise. + * Makefile.in (c-decl.o): Added cilk.h in dependency list. + +2013-10-27 Tobias Burnus <burnus@net-b.de> + + PR other/33426 + * c-parser.c (c_parser_while_statement, c_parser_while_statement, + c_parser_pragma): Add GCC ivdep support to 'do' and 'while'. + (c_parser_statement_after_labels): Update calls. + +2013-10-24 Tobias Burnus <burnus@net-b.de> + + PR other/33426 + * c-parser.c (c_parser_pragma, c_parser_for_statement): + Handle PRAGMA_IVDEP. + (c_parser_statement_after_labels): Update call. + +2013-10-24 Marek Polacek <polacek@redhat.com> + + * c-parser.c (c_parser_struct_declaration): Add a comment. + (c_parser_declarator): Don't allow _Alignas here. + 2013-10-17 Andrew MacLeod <amacleod@redhat.com> * c-parser.c: Include omp-low.h. @@ -220,7 +274,7 @@ PR c++/57793 * c-decl.c (finish_struct): Check for too-large class. -2013-07-04 Joern Rennecke <joern.rennecke@embecosm.com> +2013-07-04 Joern Rennecke <joern.rennecke@embecosm.com> PR c/57821 * c-typeck.c (set_init_index): When folding, check for index overflow. diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index c99db13ff84..9b077f4fa92 100644 --- a/gcc/c/c-decl.c +++ b/gcc/c/c-decl.c @@ -45,6 +45,7 @@ along with GCC; see the file COPYING3. If not see #include "c-family/c-common.h" #include "c-family/c-objc.h" #include "c-family/c-pragma.h" +#include "c-family/c-ubsan.h" #include "c-lang.h" #include "langhooks.h" #include "tree-iterator.h" @@ -56,6 +57,7 @@ along with GCC; see the file COPYING3. If not see #include "pointer-set.h" #include "plugin.h" #include "c-family/c-ada-spec.h" +#include "cilk.h" /* In grokdeclarator, distinguish syntactic contexts of declarators. */ enum decl_context @@ -5410,6 +5412,16 @@ grokdeclarator (const struct c_declarator *declarator, with known value. */ this_size_varies = size_varies = true; warn_variable_length_array (name, size); + if (flag_sanitize & SANITIZE_VLA + && decl_context == NORMAL) + { + /* Evaluate the array size only once. */ + size = c_save_expr (size); + size = c_fully_fold (size, false, NULL); + size = fold_build2 (COMPOUND_EXPR, TREE_TYPE (size), + ubsan_instrument_vla (loc, size), + size); + } } if (integer_zerop (size) && !this_size_varies) @@ -8448,6 +8460,12 @@ finish_function (void) /* Tie off the statement tree for this function. */ DECL_SAVED_TREE (fndecl) = pop_stmt_list (DECL_SAVED_TREE (fndecl)); + /* If the function has _Cilk_spawn in front of a function call inside it + i.e. it is a spawning function, then add the appropriate Cilk plus + functions inside. */ + if (fn_contains_cilk_spawn_p (cfun)) + cfun->cilk_frame_decl = insert_cilk_frame (fndecl); + finish_fname_decls (); /* Complain if there's just no return statement. */ diff --git a/gcc/c/c-objc-common.h b/gcc/c/c-objc-common.h index e1448248cd6..6ae7b3e0fb7 100644 --- a/gcc/c/c-objc-common.h +++ b/gcc/c/c-objc-common.h @@ -105,4 +105,13 @@ along with GCC; see the file COPYING3. If not see #undef LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P #define LANG_HOOKS_TREE_INLINING_VAR_MOD_TYPE_P c_vla_unspec_p +#undef LANG_HOOKS_CILKPLUS_GIMPLIFY_SPAWN +#define LANG_HOOKS_CILKPLUS_GIMPLIFY_SPAWN gimplify_cilk_spawn + +#undef LANG_HOOKS_CILKPLUS_FRAME_CLEANUP +#define LANG_HOOKS_CILKPLUS_FRAME_CLEANUP c_cilk_install_body_w_frame_cleanup + +#undef LANG_HOOKS_CILKPLUS_DETECT_SPAWN_AND_UNWRAP +#define LANG_HOOKS_CILKPLUS_DETECT_SPAWN_AND_UNWRAP \ + cilk_detect_spawn_and_unwrap #endif /* GCC_C_OBJC_COMMON */ diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index f8b737b02fb..6f52ba94e77 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -1157,9 +1157,9 @@ static void c_parser_statement (c_parser *); static void c_parser_statement_after_labels (c_parser *); static void c_parser_if_statement (c_parser *); static void c_parser_switch_statement (c_parser *); -static void c_parser_while_statement (c_parser *); -static void c_parser_do_statement (c_parser *); -static void c_parser_for_statement (c_parser *); +static void c_parser_while_statement (c_parser *, bool); +static void c_parser_do_statement (c_parser *, bool); +static void c_parser_for_statement (c_parser *, bool); static tree c_parser_asm_statement (c_parser *); static tree c_parser_asm_operands (c_parser *); static tree c_parser_asm_goto_operands (c_parser *); @@ -2645,6 +2645,11 @@ c_parser_struct_declaration (c_parser *parser) } specs = build_null_declspecs (); decl_loc = c_parser_peek_token (parser)->location; + /* Strictly by the standard, we shouldn't allow _Alignas here, + but it appears to have been intended to allow it there, so + we're keeping it as it is until WG14 reaches a conclusion + of N1731. + <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1731.pdf> */ c_parser_declspecs (parser, specs, false, true, true, true, cla_nonabstract_decl); if (parser->error) @@ -2959,7 +2964,7 @@ c_parser_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind, struct c_declarator *inner; c_parser_consume_token (parser); c_parser_declspecs (parser, quals_attrs, false, false, true, - true, cla_prefer_id); + false, cla_prefer_id); inner = c_parser_declarator (parser, type_seen_p, kind, seen_id); if (inner == NULL) return NULL; @@ -4574,13 +4579,21 @@ c_parser_statement_after_labels (c_parser *parser) c_parser_switch_statement (parser); break; case RID_WHILE: - c_parser_while_statement (parser); + c_parser_while_statement (parser, false); break; case RID_DO: - c_parser_do_statement (parser); + c_parser_do_statement (parser, false); break; case RID_FOR: - c_parser_for_statement (parser); + c_parser_for_statement (parser, false); + break; + case RID_CILK_SYNC: + c_parser_consume_token (parser); + c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); + if (!flag_enable_cilkplus) + error_at (loc, "-fcilkplus must be enabled to use %<_Cilk_sync%>"); + else + add_stmt (build_cilk_sync ()); break; case RID_GOTO: c_parser_consume_token (parser); @@ -4907,7 +4920,7 @@ c_parser_switch_statement (c_parser *parser) */ static void -c_parser_while_statement (c_parser *parser) +c_parser_while_statement (c_parser *parser, bool ivdep) { tree block, cond, body, save_break, save_cont; location_t loc; @@ -4922,6 +4935,11 @@ c_parser_while_statement (c_parser *parser) "statement"); cond = error_mark_node; } + + if (ivdep && cond != error_mark_node) + cond = build2 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, + build_int_cst (integer_type_node, + annot_expr_ivdep_kind)); save_break = c_break_label; c_break_label = NULL_TREE; save_cont = c_cont_label; @@ -4940,7 +4958,7 @@ c_parser_while_statement (c_parser *parser) */ static void -c_parser_do_statement (c_parser *parser) +c_parser_do_statement (c_parser *parser, bool ivdep) { tree block, cond, body, save_break, save_cont, new_break, new_cont; location_t loc; @@ -4969,7 +4987,10 @@ c_parser_do_statement (c_parser *parser) "do-while statement"); cond = error_mark_node; } - + if (ivdep && cond != error_mark_node) + cond = build2 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, + build_int_cst (integer_type_node, + annot_expr_ivdep_kind)); if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>")) c_parser_skip_to_end_of_block_or_statement (parser); c_finish_loop (loc, cond, NULL, body, new_break, new_cont, false); @@ -5033,7 +5054,7 @@ c_parser_do_statement (c_parser *parser) */ static void -c_parser_for_statement (c_parser *parser) +c_parser_for_statement (c_parser *parser, bool ivdep) { tree block, cond, incr, save_break, save_cont, body; /* The following are only used when parsing an ObjC foreach statement. */ @@ -5139,8 +5160,17 @@ c_parser_for_statement (c_parser *parser) { if (c_parser_next_token_is (parser, CPP_SEMICOLON)) { - c_parser_consume_token (parser); - cond = NULL_TREE; + if (ivdep) + { + c_parser_error (parser, "missing loop condition in loop with " + "%<GCC ivdep%> pragma"); + cond = error_mark_node; + } + else + { + c_parser_consume_token (parser); + cond = NULL_TREE; + } } else { @@ -5154,6 +5184,10 @@ c_parser_for_statement (c_parser *parser) c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>"); } + if (ivdep && cond != error_mark_node) + cond = build2 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, + build_int_cst (integer_type_node, + annot_expr_ivdep_kind)); } /* Parse the increment expression (the third expression in a for-statement). In the case of a foreach-statement, this is @@ -7148,6 +7182,30 @@ c_parser_postfix_expression (c_parser *parser) case RID_GENERIC: expr = c_parser_generic_selection (parser); break; + case RID_CILK_SPAWN: + c_parser_consume_token (parser); + if (!flag_enable_cilkplus) + { + error_at (loc, "-fcilkplus must be enabled to use " + "%<_Cilk_spawn%>"); + expr = c_parser_postfix_expression (parser); + expr.value = error_mark_node; + } + if (c_parser_peek_token (parser)->keyword == RID_CILK_SPAWN) + { + error_at (loc, "consecutive %<_Cilk_spawn%> keywords " + "are not permitted"); + /* Now flush out all the _Cilk_spawns. */ + while (c_parser_peek_token (parser)->keyword == RID_CILK_SPAWN) + c_parser_consume_token (parser); + expr = c_parser_postfix_expression (parser); + } + else + { + expr = c_parser_postfix_expression (parser); + expr.value = build_cilk_spawn (loc, expr.value); + } + break; default: c_parser_error (parser, "expected expression"); expr.value = error_mark_node; @@ -9081,6 +9139,23 @@ c_parser_pragma (c_parser *parser, enum pragma_context context) case PRAGMA_OMP_DECLARE_REDUCTION: c_parser_omp_declare (parser, context); return false; + case PRAGMA_IVDEP: + c_parser_consume_pragma (parser); + c_parser_skip_to_pragma_eol (parser); + if (!c_parser_next_token_is_keyword (parser, RID_FOR) + && !c_parser_next_token_is_keyword (parser, RID_WHILE) + && !c_parser_next_token_is_keyword (parser, RID_DO)) + { + c_parser_error (parser, "for, while or do statement expected"); + return false; + } + if (c_parser_next_token_is_keyword (parser, RID_FOR)) + c_parser_for_statement (parser, true); + else if (c_parser_next_token_is_keyword (parser, RID_WHILE)) + c_parser_while_statement (parser, true); + else + c_parser_do_statement (parser, true); + return false; case PRAGMA_GCC_PCH_PREPROCESS: c_parser_error (parser, "%<#pragma GCC pch_preprocess%> must be first"); diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index 90318ba8ae4..38207593187 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -4388,6 +4388,14 @@ build_compound_expr (location_t loc, tree expr1, tree expr2) tree eptype = NULL_TREE; tree ret; + if (flag_enable_cilkplus + && (TREE_CODE (expr1) == CILK_SPAWN_STMT + || TREE_CODE (expr2) == CILK_SPAWN_STMT)) + { + error_at (loc, + "spawned function call cannot be part of a comma expression"); + return error_mark_node; + } expr1_int_operands = EXPR_INT_CONST_OPERANDS (expr1); if (expr1_int_operands) expr1 = remove_c_maybe_const_expr (expr1); @@ -8696,6 +8704,12 @@ c_finish_return (location_t loc, tree retval, tree origtype) return error_mark_node; } } + if (flag_enable_cilkplus && retval && TREE_CODE (retval) == CILK_SPAWN_STMT) + { + error_at (loc, "use of %<_Cilk_spawn%> in a return statement is not " + "allowed"); + return error_mark_node; + } if (retval) { tree semantic_type = NULL_TREE; @@ -11304,6 +11318,7 @@ c_finish_omp_clauses (tree clauses) "%qE has invalid type for %<reduction(%s)%>", t, r_name); remove = true; + break; } } else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) == error_mark_node) @@ -11311,6 +11326,7 @@ c_finish_omp_clauses (tree clauses) error_at (OMP_CLAUSE_LOCATION (c), "user defined reduction not found for %qD", t); remove = true; + break; } else if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)) { @@ -11394,6 +11410,7 @@ c_finish_omp_clauses (tree clauses) error_at (OMP_CLAUSE_LOCATION (c), "%qE must be %<threadprivate%> for %<copyin%>", t); remove = true; + break; } goto check_dup_generic; @@ -11492,6 +11509,14 @@ c_finish_omp_clauses (tree clauses) "%qE is not a variable in %<aligned%> clause", t); remove = true; } + else if (!POINTER_TYPE_P (TREE_TYPE (t)) + && TREE_CODE (TREE_TYPE (t)) != ARRAY_TYPE) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%qE in %<aligned%> clause is neither a pointer nor " + "an array", t); + remove = true; + } else if (bitmap_bit_p (&aligned_head, DECL_UID (t))) { error_at (OMP_CLAUSE_LOCATION (c), @@ -11595,8 +11620,9 @@ c_finish_omp_clauses (tree clauses) error_at (OMP_CLAUSE_LOCATION (c), "%qE is not an argument in %<uniform%> clause", t); remove = true; + break; } - break; + goto check_dup_generic; case OMP_CLAUSE_NOWAIT: if (copyprivate_seen) diff --git a/gcc/calls.c b/gcc/calls.c index e25f2ab74f0..c04ed32801f 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -40,7 +40,6 @@ along with GCC; see the file COPYING3. If not see #include "cgraph.h" #include "except.h" #include "dbgcnt.h" -#include "tree-ssa.h" /* Like PREFERRED_STACK_BOUNDARY but in units of bytes, not bits. */ #define STACK_BYTES (PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT) diff --git a/gcc/cfganal.c b/gcc/cfganal.c index 762eea4ca04..b2216117227 100644 --- a/gcc/cfganal.c +++ b/gcc/cfganal.c @@ -878,20 +878,22 @@ inverted_post_order_compute (int *post_order) return post_order_num; } -/* Compute the depth first search order and store in the array - PRE_ORDER if nonzero, marking the nodes visited in VISITED. If - REV_POST_ORDER is nonzero, return the reverse completion number for each - node. Returns the number of nodes visited. A depth first search - tries to get as far away from the starting point as quickly as - possible. +/* Compute the depth first search order of FN and store in the array + PRE_ORDER if nonzero. If REV_POST_ORDER is nonzero, return the + reverse completion number for each node. Returns the number of nodes + visited. A depth first search tries to get as far away from the starting + point as quickly as possible. - pre_order is a really a preorder numbering of the graph. - rev_post_order is really a reverse postorder numbering of the graph. - */ + In case the function has unreachable blocks the number of nodes + visited does not include them. + + pre_order is a really a preorder numbering of the graph. + rev_post_order is really a reverse postorder numbering of the graph. */ int -pre_and_rev_post_order_compute (int *pre_order, int *rev_post_order, - bool include_entry_exit) +pre_and_rev_post_order_compute_fn (struct function *fn, + int *pre_order, int *rev_post_order, + bool include_entry_exit) { edge_iterator *stack; int sp; @@ -921,7 +923,7 @@ pre_and_rev_post_order_compute (int *pre_order, int *rev_post_order, bitmap_clear (visited); /* Push the first edge on to the stack. */ - stack[sp++] = ei_start (ENTRY_BLOCK_PTR->succs); + stack[sp++] = ei_start (ENTRY_BLOCK_PTR_FOR_FUNCTION (fn)->succs); while (sp) { @@ -935,7 +937,8 @@ pre_and_rev_post_order_compute (int *pre_order, int *rev_post_order, dest = ei_edge (ei)->dest; /* Check if the edge destination has been visited yet. */ - if (dest != EXIT_BLOCK_PTR && ! bitmap_bit_p (visited, dest->index)) + if (dest != EXIT_BLOCK_PTR_FOR_FUNCTION (fn) + && ! bitmap_bit_p (visited, dest->index)) { /* Mark that we have visited the destination. */ bitmap_set_bit (visited, dest->index); @@ -956,7 +959,8 @@ pre_and_rev_post_order_compute (int *pre_order, int *rev_post_order, } else { - if (ei_one_before_end_p (ei) && src != ENTRY_BLOCK_PTR + if (ei_one_before_end_p (ei) + && src != ENTRY_BLOCK_PTR_FOR_FUNCTION (fn) && rev_post_order) /* There are no more successors for the SRC node so assign its reverse completion number. */ @@ -979,9 +983,24 @@ pre_and_rev_post_order_compute (int *pre_order, int *rev_post_order, pre_order_num++; if (rev_post_order) rev_post_order[rev_post_order_num--] = EXIT_BLOCK; - /* The number of nodes visited should be the number of blocks. */ - gcc_assert (pre_order_num == n_basic_blocks); } + + return pre_order_num; +} + +/* Like pre_and_rev_post_order_compute_fn but operating on the + current function and asserting that all nodes were visited. */ + +int +pre_and_rev_post_order_compute (int *pre_order, int *rev_post_order, + bool include_entry_exit) +{ + int pre_order_num + = pre_and_rev_post_order_compute_fn (cfun, pre_order, rev_post_order, + include_entry_exit); + if (include_entry_exit) + /* The number of nodes visited should be the number of blocks. */ + gcc_assert (pre_order_num == n_basic_blocks); else /* The number of nodes visited should be the number of blocks minus the entry and exit blocks which are not visited here. */ diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c index 53a99755010..51611907368 100644 --- a/gcc/cfgcleanup.c +++ b/gcc/cfgcleanup.c @@ -34,6 +34,7 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tm.h" #include "rtl.h" +#include "tree.h" #include "hard-reg-set.h" #include "regs.h" #include "insn-config.h" diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index 7531c2cf6c0..dbd77d89b16 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -28,6 +28,15 @@ along with GCC; see the file COPYING3. If not see #include "function.h" #include "expr.h" #include "langhooks.h" +#include "bitmap.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "cgraph.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" +#include "tree-dfa.h" #include "tree-ssa.h" #include "tree-pass.h" #include "except.h" @@ -40,8 +49,8 @@ along with GCC; see the file COPYING3. If not see #include "tree-inline.h" #include "value-prof.h" #include "target.h" +#include "tree-ssa-live.h" #include "tree-outof-ssa.h" -#include "bitmap.h" #include "sbitmap.h" #include "cfgloop.h" #include "regs.h" /* For reg_renumber. */ @@ -1500,7 +1509,7 @@ estimated_stack_frame_size (struct cgraph_node *node) HOST_WIDE_INT size = 0; size_t i; tree var; - struct function *fn = DECL_STRUCT_FUNCTION (node->symbol.decl); + struct function *fn = DECL_STRUCT_FUNCTION (node->decl); push_cfun (fn); @@ -4781,14 +4790,18 @@ gimple_expand_cfg (void) if (e->insns.r) { rebuild_jump_labels_chain (e->insns.r); - /* Avoid putting insns before parm_birth_insn. */ + /* Put insns after parm birth, but before + NOTE_INSNS_FUNCTION_BEG. */ if (e->src == ENTRY_BLOCK_PTR - && single_succ_p (ENTRY_BLOCK_PTR) - && parm_birth_insn) + && single_succ_p (ENTRY_BLOCK_PTR)) { rtx insns = e->insns.r; e->insns.r = NULL_RTX; - emit_insn_after_noloc (insns, parm_birth_insn, e->dest); + if (NOTE_P (parm_birth_insn) + && NOTE_KIND (parm_birth_insn) == NOTE_INSN_FUNCTION_BEG) + emit_insn_before_noloc (insns, parm_birth_insn, e->dest); + else + emit_insn_after_noloc (insns, parm_birth_insn, e->dest); } else commit_one_edge_insertion (e); diff --git a/gcc/cfgloop.c b/gcc/cfgloop.c index a894793b2f6..72441ceefe0 100644 --- a/gcc/cfgloop.c +++ b/gcc/cfgloop.c @@ -28,7 +28,8 @@ along with GCC; see the file COPYING3. If not see #include "diagnostic-core.h" #include "flags.h" #include "tree.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "gimple-ssa.h" #include "pointer-set.h" #include "ggc.h" #include "dumpfile.h" diff --git a/gcc/cfgloopmanip.c b/gcc/cfgloopmanip.c index b4840dcf014..be876db354f 100644 --- a/gcc/cfgloopmanip.c +++ b/gcc/cfgloopmanip.c @@ -24,7 +24,9 @@ along with GCC; see the file COPYING3. If not see #include "rtl.h" #include "basic-block.h" #include "cfgloop.h" -#include "tree-ssa.h" +#include "tree.h" +#include "gimple.h" +#include "tree-ssa-loop-manip.h" #include "dumpfile.h" static void copy_loops_to (struct loop **, int, diff --git a/gcc/cgraph.c b/gcc/cgraph.c index 8eedaa493aa..dccd6db3c56 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -42,6 +42,9 @@ along with GCC; see the file COPYING3. If not see #include "gimple.h" #include "timevar.h" #include "dumpfile.h" +#include "gimple-ssa.h" +#include "cgraph.h" +#include "tree-cfg.h" #include "tree-ssa.h" #include "value-prof.h" #include "except.h" @@ -61,7 +64,7 @@ static inline void cgraph_edge_remove_caller (struct cgraph_edge *e); static inline void cgraph_edge_remove_callee (struct cgraph_edge *e); /* Queue of cgraph nodes scheduled to be lowered. */ -symtab_node x_cgraph_nodes_queue; +symtab_node *x_cgraph_nodes_queue; #define cgraph_nodes_queue ((struct cgraph_node *)x_cgraph_nodes_queue) /* Number of nodes in existence. */ @@ -135,7 +138,7 @@ bool cpp_implicit_aliases_done; The cgraph_function_version_info has a THIS_NODE field that is the corresponding cgraph_node.. */ -static htab_t GTY((param_is (struct cgraph_function_version_info *))) +static GTY((param_is (struct cgraph_function_version_info))) htab_t cgraph_fnver_htab = NULL; /* Hash function for cgraph_fnver_htab. */ @@ -271,8 +274,8 @@ record_function_versions (tree decl1, tree decl2) /* Macros to access the next item in the list of free cgraph nodes and edges. */ -#define NEXT_FREE_NODE(NODE) cgraph ((NODE)->symbol.next) -#define SET_NEXT_FREE_NODE(NODE,NODE2) ((NODE))->symbol.next = (symtab_node)NODE2 +#define NEXT_FREE_NODE(NODE) cgraph ((NODE)->next) +#define SET_NEXT_FREE_NODE(NODE,NODE2) ((NODE))->next = NODE2 #define NEXT_FREE_EDGE(EDGE) (EDGE)->prev_caller /* Register HOOK to be called with DATA on each removed edge. */ @@ -510,7 +513,7 @@ cgraph_create_empty_node (void) { struct cgraph_node *node = cgraph_allocate_node (); - node->symbol.type = SYMTAB_FUNCTION; + node->type = SYMTAB_FUNCTION; node->frequency = NODE_FREQUENCY_NORMAL; node->count_materialization_scale = REG_BR_PROB_BASE; cgraph_n_nodes++; @@ -525,8 +528,8 @@ cgraph_create_node (tree decl) struct cgraph_node *node = cgraph_create_empty_node (); gcc_assert (TREE_CODE (decl) == FUNCTION_DECL); - node->symbol.decl = decl; - symtab_register_node ((symtab_node) node); + node->decl = decl; + symtab_register_node (node); if (DECL_CONTEXT (decl) && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL) { @@ -564,12 +567,12 @@ cgraph_create_function_alias (tree alias, tree target) || TREE_CODE (target) == IDENTIFIER_NODE); gcc_assert (TREE_CODE (alias) == FUNCTION_DECL); alias_node = cgraph_get_create_node (alias); - gcc_assert (!alias_node->symbol.definition); - alias_node->symbol.alias_target = target; - alias_node->symbol.definition = true; - alias_node->symbol.alias = true; + gcc_assert (!alias_node->definition); + alias_node->alias_target = target; + alias_node->definition = true; + alias_node->alias = true; if (lookup_attribute ("weakref", DECL_ATTRIBUTES (alias)) != NULL) - alias_node->symbol.weakref = true; + alias_node->weakref = true; return alias_node; } @@ -592,10 +595,10 @@ cgraph_same_body_alias (struct cgraph_node *decl_node ATTRIBUTE_UNUSED, tree ali return NULL; n = cgraph_create_function_alias (alias, decl); - n->symbol.cpp_implicit_alias = true; + n->cpp_implicit_alias = true; if (cpp_implicit_aliases_done) - symtab_resolve_alias ((symtab_node)n, - (symtab_node)cgraph_get_node (decl)); + symtab_resolve_alias (n, + cgraph_get_node (decl)); return n; } @@ -616,8 +619,8 @@ cgraph_add_thunk (struct cgraph_node *decl_node ATTRIBUTE_UNUSED, node = cgraph_get_node (alias); if (node) { - gcc_assert (node->symbol.definition); - gcc_assert (!node->symbol.alias); + gcc_assert (node->definition); + gcc_assert (!node->alias); gcc_assert (!node->thunk.thunk_p); cgraph_remove_node (node); } @@ -631,7 +634,7 @@ cgraph_add_thunk (struct cgraph_node *decl_node ATTRIBUTE_UNUSED, node->thunk.virtual_offset_p = virtual_offset != NULL; node->thunk.alias = real_alias; node->thunk.thunk_p = true; - node->symbol.definition = true; + node->definition = true; return node; } @@ -643,9 +646,9 @@ struct cgraph_node * cgraph_node_for_asm (tree asmname) { /* We do not want to look at inline clones. */ - for (symtab_node node = symtab_node_for_asm (asmname); + for (symtab_node *node = symtab_node_for_asm (asmname); node; - node = node->symbol.next_sharing_asm_name) + node = node->next_sharing_asm_name) { cgraph_node *cn = dyn_cast <cgraph_node> (node); if (cn && !cn->global.inlined_to) @@ -800,7 +803,7 @@ cgraph_set_call_stmt (struct cgraph_edge *e, gimple new_stmt, e = cgraph_make_edge_direct (e, new_callee); } - push_cfun (DECL_STRUCT_FUNCTION (e->caller->symbol.decl)); + push_cfun (DECL_STRUCT_FUNCTION (e->caller->decl)); e->can_throw_external = stmt_can_throw_external (new_stmt); pop_cfun (); if (e->caller->call_site_hash) @@ -813,7 +816,8 @@ cgraph_set_call_stmt (struct cgraph_edge *e, gimple new_stmt, static struct cgraph_edge * cgraph_create_edge_1 (struct cgraph_node *caller, struct cgraph_node *callee, - gimple call_stmt, gcov_type count, int freq) + gimple call_stmt, gcov_type count, int freq, + bool indir_unknown_callee) { struct cgraph_edge *edge; @@ -858,13 +862,13 @@ cgraph_create_edge_1 (struct cgraph_node *caller, struct cgraph_node *callee, gcc_assert (freq <= CGRAPH_FREQ_MAX); edge->call_stmt = call_stmt; - push_cfun (DECL_STRUCT_FUNCTION (caller->symbol.decl)); + push_cfun (DECL_STRUCT_FUNCTION (caller->decl)); edge->can_throw_external = call_stmt ? stmt_can_throw_external (call_stmt) : false; pop_cfun (); if (call_stmt - && callee && callee->symbol.decl - && !gimple_check_call_matching_types (call_stmt, callee->symbol.decl, + && callee && callee->decl + && !gimple_check_call_matching_types (call_stmt, callee->decl, false)) edge->call_stmt_cannot_inline_p = true; else @@ -873,6 +877,7 @@ cgraph_create_edge_1 (struct cgraph_node *caller, struct cgraph_node *callee, edge->indirect_info = NULL; edge->indirect_inlining_edge = 0; edge->speculative = false; + edge->indirect_unknown_callee = indir_unknown_callee; if (call_stmt && caller->call_site_hash) cgraph_add_edge_to_call_site_hash (edge); @@ -886,9 +891,8 @@ cgraph_create_edge (struct cgraph_node *caller, struct cgraph_node *callee, gimple call_stmt, gcov_type count, int freq) { struct cgraph_edge *edge = cgraph_create_edge_1 (caller, callee, call_stmt, - count, freq); + count, freq, false); - edge->indirect_unknown_callee = 0; initialize_inline_failed (edge); edge->next_caller = callee->callers; @@ -925,10 +929,9 @@ cgraph_create_indirect_edge (struct cgraph_node *caller, gimple call_stmt, gcov_type count, int freq) { struct cgraph_edge *edge = cgraph_create_edge_1 (caller, NULL, call_stmt, - count, freq); + count, freq, true); tree target; - edge->indirect_unknown_callee = 1; initialize_inline_failed (edge); edge->indirect_info = cgraph_allocate_init_indirect_info (); @@ -1077,14 +1080,14 @@ cgraph_turn_edge_to_speculative (struct cgraph_edge *e, { fprintf (dump_file, "Indirect call -> speculative call" " %s/%i => %s/%i\n", - xstrdup (cgraph_node_name (n)), n->symbol.order, - xstrdup (cgraph_node_name (n2)), n2->symbol.order); + xstrdup (cgraph_node_name (n)), n->order, + xstrdup (cgraph_node_name (n2)), n2->order); } e->speculative = true; e2 = cgraph_create_edge (n, n2, e->call_stmt, direct_count, direct_frequency); initialize_inline_failed (e2); e2->speculative = true; - if (TREE_NOTHROW (n2->symbol.decl)) + if (TREE_NOTHROW (n2->decl)) e2->can_throw_external = false; else e2->can_throw_external = e->can_throw_external; @@ -1092,7 +1095,7 @@ cgraph_turn_edge_to_speculative (struct cgraph_edge *e, e->count -= e2->count; e->frequency -= e2->frequency; cgraph_call_edge_duplication_hooks (e, e2); - ref = ipa_record_reference ((symtab_node)n, (symtab_node)n2, + ref = ipa_record_reference (n, n2, IPA_REF_ADDR, e->call_stmt); ref->lto_stmt_uid = e->lto_stmt_uid; ref->speculative = e->speculative; @@ -1146,7 +1149,7 @@ cgraph_speculative_call_info (struct cgraph_edge *e, indirect = e2; reference = NULL; - for (i = 0; ipa_ref_list_reference_iterate (&e->caller->symbol.ref_list, + for (i = 0; ipa_ref_list_reference_iterate (&e->caller->ref_list, i, ref); i++) if (ref->speculative && ((ref->stmt && ref->stmt == e->call_stmt) @@ -1188,7 +1191,7 @@ cgraph_resolve_speculation (struct cgraph_edge *edge, tree callee_decl) gcc_assert (edge->speculative); cgraph_speculative_call_info (edge, e2, edge, ref); if (!callee_decl - || !symtab_semantically_equivalent_p ((symtab_node) ref->referred, + || !symtab_semantically_equivalent_p (ref->referred, symtab_get_node (callee_decl))) { if (dump_file) @@ -1197,16 +1200,16 @@ cgraph_resolve_speculation (struct cgraph_edge *edge, tree callee_decl) { fprintf (dump_file, "Speculative indirect call %s/%i => %s/%i has " "turned out to have contradicting known target ", - xstrdup (cgraph_node_name (edge->caller)), edge->caller->symbol.order, - xstrdup (cgraph_node_name (e2->callee)), e2->callee->symbol.order); + xstrdup (cgraph_node_name (edge->caller)), edge->caller->order, + xstrdup (cgraph_node_name (e2->callee)), e2->callee->order); print_generic_expr (dump_file, callee_decl, 0); fprintf (dump_file, "\n"); } else { fprintf (dump_file, "Removing speculative call %s/%i => %s/%i\n", - xstrdup (cgraph_node_name (edge->caller)), edge->caller->symbol.order, - xstrdup (cgraph_node_name (e2->callee)), e2->callee->symbol.order); + xstrdup (cgraph_node_name (edge->caller)), edge->caller->order, + xstrdup (cgraph_node_name (e2->callee)), e2->callee->order); } } } @@ -1248,7 +1251,7 @@ cgraph_make_edge_direct (struct cgraph_edge *edge, struct cgraph_node *callee) /* If we are redirecting speculative call, make it non-speculative. */ if (edge->indirect_unknown_callee && edge->speculative) { - edge = cgraph_resolve_speculation (edge, callee->symbol.decl); + edge = cgraph_resolve_speculation (edge, callee->decl); /* On successful speculation just return the pre existing direct edge. */ if (!edge->indirect_unknown_callee) @@ -1279,7 +1282,7 @@ cgraph_make_edge_direct (struct cgraph_edge *edge, struct cgraph_node *callee) if (edge->call_stmt) edge->call_stmt_cannot_inline_p - = !gimple_check_call_matching_types (edge->call_stmt, callee->symbol.decl, + = !gimple_check_call_matching_types (edge->call_stmt, callee->decl, false); /* We need to re-determine the inlining status of the edge. */ @@ -1316,23 +1319,23 @@ cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *e) signature. We did not update the call statement yet, so compare it with the reference that still points to the proper type. */ else if (!gimple_check_call_matching_types (e->call_stmt, - ref->referred->symbol.decl, + ref->referred->decl, true)) { if (dump_file) fprintf (dump_file, "Not expanding speculative call of %s/%i -> %s/%i\n" "Type mismatch.\n", xstrdup (cgraph_node_name (e->caller)), - e->caller->symbol.order, + e->caller->order, xstrdup (cgraph_node_name (e->callee)), - e->callee->symbol.order); + e->callee->order); e = cgraph_resolve_speculation (e, NULL); /* We are producing the final function body and will throw away the callgraph edges really soon. Reset the counts/frequencies to keep verifier happy in the case of roundoff errors. */ e->count = gimple_bb (e->call_stmt)->count; e->frequency = compute_call_stmt_bb_frequency - (e->caller->symbol.decl, gimple_bb (e->call_stmt)); + (e->caller->decl, gimple_bb (e->call_stmt)); } /* Expand speculation into GIMPLE code. */ else @@ -1342,12 +1345,12 @@ cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *e) "Expanding speculative call of %s/%i -> %s/%i count:" HOST_WIDEST_INT_PRINT_DEC"\n", xstrdup (cgraph_node_name (e->caller)), - e->caller->symbol.order, + e->caller->order, xstrdup (cgraph_node_name (e->callee)), - e->callee->symbol.order, + e->callee->order, (HOST_WIDEST_INT)e->count); gcc_assert (e2->speculative); - push_cfun (DECL_STRUCT_FUNCTION (e->caller->symbol.decl)); + push_cfun (DECL_STRUCT_FUNCTION (e->caller->decl)); new_stmt = gimple_ic (e->call_stmt, cgraph (ref->referred), e->count || e2->count ? RDIV (e->count * REG_BR_PROB_BASE, @@ -1361,9 +1364,9 @@ cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *e) cgraph_set_call_stmt_including_clones (e->caller, e->call_stmt, new_stmt, false); e->frequency = compute_call_stmt_bb_frequency - (e->caller->symbol.decl, gimple_bb (e->call_stmt)); + (e->caller->decl, gimple_bb (e->call_stmt)); e2->frequency = compute_call_stmt_bb_frequency - (e2->caller->symbol.decl, gimple_bb (e2->call_stmt)); + (e2->caller->decl, gimple_bb (e2->call_stmt)); e2->speculative = false; ref->speculative = false; ref->stmt = NULL; @@ -1377,7 +1380,7 @@ cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *e) } if (e->indirect_unknown_callee - || decl == e->callee->symbol.decl) + || decl == e->callee->decl) return e->call_stmt; #ifdef ENABLE_CHECKING @@ -1391,8 +1394,8 @@ cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *e) if (cgraph_dump_file) { fprintf (cgraph_dump_file, "updating call of %s/%i -> %s/%i: ", - xstrdup (cgraph_node_name (e->caller)), e->caller->symbol.order, - xstrdup (cgraph_node_name (e->callee)), e->callee->symbol.order); + xstrdup (cgraph_node_name (e->caller)), e->caller->order, + xstrdup (cgraph_node_name (e->callee)), e->callee->order); print_gimple_stmt (cgraph_dump_file, e->call_stmt, 0, dump_flags); if (e->callee->clone.combined_args_to_skip) { @@ -1409,7 +1412,7 @@ cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *e) new_stmt = gimple_call_copy_skip_args (e->call_stmt, e->callee->clone.combined_args_to_skip); - gimple_call_set_fndecl (new_stmt, e->callee->symbol.decl); + gimple_call_set_fndecl (new_stmt, e->callee->decl); gimple_call_set_fntype (new_stmt, gimple_call_fntype (e->call_stmt)); if (gimple_vdef (new_stmt) @@ -1432,7 +1435,7 @@ cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *e) else { new_stmt = e->call_stmt; - gimple_call_set_fndecl (new_stmt, e->callee->symbol.decl); + gimple_call_set_fndecl (new_stmt, e->callee->decl); update_stmt (new_stmt); } @@ -1482,7 +1485,7 @@ cgraph_update_edges_for_call_stmt_node (struct cgraph_node *node, struct cgraph_node *callee = e->callee; while (callee) { - if (callee->symbol.decl == new_call + if (callee->decl == new_call || callee->former_clone_of == new_call) return; callee = callee->clone_of; @@ -1655,17 +1658,17 @@ cgraph_release_function_body (struct cgraph_node *node) node->ipa_transforms_to_apply.release (); if (!node->used_as_abstract_origin && cgraph_state != CGRAPH_STATE_PARSING) { - DECL_RESULT (node->symbol.decl) = NULL; - DECL_ARGUMENTS (node->symbol.decl) = NULL; + DECL_RESULT (node->decl) = NULL; + DECL_ARGUMENTS (node->decl) = NULL; } /* If the node is abstract and needed, then do not clear DECL_INITIAL of its associated function function declaration because it's needed to emit debug info later. */ - if (!node->used_as_abstract_origin && DECL_INITIAL (node->symbol.decl)) - DECL_INITIAL (node->symbol.decl) = error_mark_node; - release_function_body (node->symbol.decl); - if (node->symbol.lto_file_data) - lto_free_function_in_decl_state_for_node ((symtab_node) node); + if (!node->used_as_abstract_origin && DECL_INITIAL (node->decl)) + DECL_INITIAL (node->decl) = error_mark_node; + release_function_body (node->decl); + if (node->lto_file_data) + lto_free_function_in_decl_state_for_node (node); } /* Remove the node from cgraph. */ @@ -1683,8 +1686,8 @@ cgraph_remove_node (struct cgraph_node *node) /* Incremental inlining access removed nodes stored in the postorder list. */ - node->symbol.force_output = false; - node->symbol.forced_by_abi = false; + node->force_output = false; + node->forced_by_abi = false; for (n = node->nested; n; n = n->next_nested) n->origin = NULL; node->nested = NULL; @@ -1696,7 +1699,7 @@ cgraph_remove_node (struct cgraph_node *node) node2 = &(*node2)->next_nested; *node2 = node->next_nested; } - symtab_unregister_node ((symtab_node)node); + symtab_unregister_node (node); if (node->prev_sibling_clone) node->prev_sibling_clone->next_sibling_clone = node->next_sibling_clone; else if (node->clone_of) @@ -1740,18 +1743,18 @@ cgraph_remove_node (struct cgraph_node *node) */ if (cgraph_state != CGRAPH_LTO_STREAMING) { - n = cgraph_get_node (node->symbol.decl); + n = cgraph_get_node (node->decl); if (!n || (!n->clones && !n->clone_of && !n->global.inlined_to && (cgraph_global_info_ready - && (TREE_ASM_WRITTEN (n->symbol.decl) - || DECL_EXTERNAL (n->symbol.decl) - || !n->symbol.analyzed - || (!flag_wpa && n->symbol.in_other_partition))))) + && (TREE_ASM_WRITTEN (n->decl) + || DECL_EXTERNAL (n->decl) + || !n->analyzed + || (!flag_wpa && n->in_other_partition))))) cgraph_release_function_body (node); } - node->symbol.decl = NULL; + node->decl = NULL; if (node->call_site_hash) { htab_delete (node->call_site_hash); @@ -1762,7 +1765,7 @@ cgraph_remove_node (struct cgraph_node *node) /* Clear out the node to NULL all pointers and add the node to the free list. */ memset (node, 0, sizeof (*node)); - node->symbol.type = SYMTAB_FUNCTION; + node->type = SYMTAB_FUNCTION; node->uid = uid; SET_NEXT_FREE_NODE (node, free_nodes); free_nodes = node; @@ -1787,9 +1790,9 @@ cgraph_mark_address_taken_node (struct cgraph_node *node) of the object was taken (and thus it should be set on node alias is referring to). We should remove the first use and the remove the following set. */ - node->symbol.address_taken = 1; + node->address_taken = 1; node = cgraph_function_or_thunk_node (node, NULL); - node->symbol.address_taken = 1; + node->address_taken = 1; } /* Return local info for the compiled function. */ @@ -1831,7 +1834,7 @@ cgraph_rtl_info (tree decl) node = cgraph_get_node (decl); if (!node || (decl != current_function_decl - && !TREE_ASM_WRITTEN (node->symbol.decl))) + && !TREE_ASM_WRITTEN (node->decl))) return NULL; return &node->rtl; } @@ -1867,18 +1870,18 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node) struct cgraph_edge *edge; int indirect_calls_count = 0; - dump_symtab_base (f, (symtab_node) node); + dump_symtab_base (f, node); if (node->global.inlined_to) fprintf (f, " Function %s/%i is inline copy in %s/%i\n", xstrdup (cgraph_node_name (node)), - node->symbol.order, + node->order, xstrdup (cgraph_node_name (node->global.inlined_to)), - node->global.inlined_to->symbol.order); + node->global.inlined_to->order); if (node->clone_of) fprintf (f, " Clone of %s/%i\n", cgraph_node_asm_name (node->clone_of), - node->clone_of->symbol.order); + node->clone_of->order); if (cgraph_function_flags_ready) fprintf (f, " Availability: %s\n", cgraph_availability_names [cgraph_function_body_availability (node)]); @@ -1892,7 +1895,7 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node) (HOST_WIDEST_INT)node->count); if (node->origin) fprintf (f, " nested in: %s", cgraph_node_asm_name (node->origin)); - if (gimple_has_body_p (node->symbol.decl)) + if (gimple_has_body_p (node->decl)) fprintf (f, " body"); if (node->process) fprintf (f, " process"); @@ -1922,7 +1925,7 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node) (int)node->thunk.virtual_value, (int)node->thunk.virtual_offset_p); } - if (node->symbol.alias && node->thunk.alias + if (node->alias && node->thunk.alias && DECL_P (node->thunk.alias)) { fprintf (f, " Alias of %s", @@ -1938,7 +1941,7 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node) for (edge = node->callers; edge; edge = edge->next_caller) { fprintf (f, "%s/%i ", cgraph_node_asm_name (edge->caller), - edge->caller->symbol.order); + edge->caller->order); if (edge->count) fprintf (f, "("HOST_WIDEST_INT_PRINT_DEC"x) ", (HOST_WIDEST_INT)edge->count); @@ -1959,7 +1962,7 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node) for (edge = node->callees; edge; edge = edge->next_callee) { fprintf (f, "%s/%i ", cgraph_node_asm_name (edge->callee), - edge->callee->symbol.order); + edge->callee->order); if (edge->speculative) fprintf (f, "(speculative) "); if (!edge->inline_failed) @@ -2043,20 +2046,20 @@ enum availability cgraph_function_body_availability (struct cgraph_node *node) { enum availability avail; - if (!node->symbol.analyzed) + if (!node->analyzed) avail = AVAIL_NOT_AVAILABLE; else if (node->local.local) avail = AVAIL_LOCAL; - else if (node->symbol.alias && node->symbol.weakref) + else if (node->alias && node->weakref) cgraph_function_or_thunk_node (node, &avail); - else if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (node->symbol.decl))) + else if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (node->decl))) avail = AVAIL_OVERWRITABLE; - else if (!node->symbol.externally_visible) + else if (!node->externally_visible) avail = AVAIL_AVAILABLE; /* Inline functions are safe to be analyzed even if their symbol can be overwritten at runtime. It is not meaningful to enforce any sane behaviour on replacing inline function by different body. */ - else if (DECL_DECLARED_INLINE_P (node->symbol.decl)) + else if (DECL_DECLARED_INLINE_P (node->decl)) avail = AVAIL_AVAILABLE; /* If the function can be overwritten, return OVERWRITABLE. Take @@ -2069,8 +2072,8 @@ cgraph_function_body_availability (struct cgraph_node *node) AVAIL_AVAILABLE here? That would be good reason to preserve this bit. */ - else if (decl_replaceable_p (node->symbol.decl) - && !DECL_EXTERNAL (node->symbol.decl)) + else if (decl_replaceable_p (node->decl) + && !DECL_EXTERNAL (node->decl)) avail = AVAIL_OVERWRITABLE; else avail = AVAIL_AVAILABLE; @@ -2082,12 +2085,12 @@ static bool cgraph_node_cannot_be_local_p_1 (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED) { - return !(!node->symbol.force_output - && ((DECL_COMDAT (node->symbol.decl) - && !node->symbol.forced_by_abi - && !symtab_used_from_object_file_p ((symtab_node) node) - && !node->symbol.same_comdat_group) - || !node->symbol.externally_visible)); + return !(!node->force_output + && ((DECL_COMDAT (node->decl) + && !node->forced_by_abi + && !symtab_used_from_object_file_p (node) + && !node->same_comdat_group) + || !node->externally_visible)); } /* Return true if NODE can be made local for API change. @@ -2097,7 +2100,7 @@ cgraph_node_cannot_be_local_p_1 (struct cgraph_node *node, bool cgraph_node_can_be_local_p (struct cgraph_node *node) { - return (!node->symbol.address_taken + return (!node->address_taken && !cgraph_for_node_and_aliases (node, cgraph_node_cannot_be_local_p_1, NULL, true)); @@ -2126,7 +2129,7 @@ cgraph_for_node_thunks_and_aliases (struct cgraph_node *node, if (cgraph_for_node_thunks_and_aliases (e->caller, callback, data, include_overwritable)) return true; - for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list, i, ref); i++) + for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list, i, ref); i++) if (ref->use == IPA_REF_ALIAS) { struct cgraph_node *alias = ipa_ref_referring_node (ref); @@ -2154,7 +2157,7 @@ cgraph_for_node_and_aliases (struct cgraph_node *node, if (callback (node, data)) return true; - for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list, i, ref); i++) + for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list, i, ref); i++) if (ref->use == IPA_REF_ALIAS) { struct cgraph_node *alias = ipa_ref_referring_node (ref); @@ -2173,16 +2176,16 @@ static bool cgraph_make_node_local_1 (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED) { gcc_checking_assert (cgraph_node_can_be_local_p (node)); - if (DECL_COMDAT (node->symbol.decl) || DECL_EXTERNAL (node->symbol.decl)) + if (DECL_COMDAT (node->decl) || DECL_EXTERNAL (node->decl)) { - symtab_make_decl_local (node->symbol.decl); + symtab_make_decl_local (node->decl); - node->symbol.externally_visible = false; - node->symbol.forced_by_abi = false; + node->externally_visible = false; + node->forced_by_abi = false; node->local.local = true; - node->symbol.unique_name = (node->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY - || node->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY_EXP); - node->symbol.resolution = LDPR_PREVAILING_DEF_IRONLY; + node->unique_name = (node->resolution == LDPR_PREVAILING_DEF_IRONLY + || node->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP); + node->resolution = LDPR_PREVAILING_DEF_IRONLY; gcc_assert (cgraph_function_body_availability (node) == AVAIL_LOCAL); } return false; @@ -2204,7 +2207,7 @@ cgraph_set_nothrow_flag_1 (struct cgraph_node *node, void *data) { struct cgraph_edge *e; - TREE_NOTHROW (node->symbol.decl) = data != NULL; + TREE_NOTHROW (node->decl) = data != NULL; if (data != NULL) for (e = node->callers; e; e = e->next_caller) @@ -2231,13 +2234,13 @@ cgraph_set_const_flag_1 (struct cgraph_node *node, void *data) optimized out. */ if (data && !((size_t)data & 2)) { - if (DECL_STATIC_CONSTRUCTOR (node->symbol.decl)) - DECL_STATIC_CONSTRUCTOR (node->symbol.decl) = 0; - if (DECL_STATIC_DESTRUCTOR (node->symbol.decl)) - DECL_STATIC_DESTRUCTOR (node->symbol.decl) = 0; + if (DECL_STATIC_CONSTRUCTOR (node->decl)) + DECL_STATIC_CONSTRUCTOR (node->decl) = 0; + if (DECL_STATIC_DESTRUCTOR (node->decl)) + DECL_STATIC_DESTRUCTOR (node->decl) = 0; } - TREE_READONLY (node->symbol.decl) = data != NULL; - DECL_LOOPING_CONST_OR_PURE_P (node->symbol.decl) = ((size_t)data & 2) != 0; + TREE_READONLY (node->decl) = data != NULL; + DECL_LOOPING_CONST_OR_PURE_P (node->decl) = ((size_t)data & 2) != 0; return false; } @@ -2261,13 +2264,13 @@ cgraph_set_pure_flag_1 (struct cgraph_node *node, void *data) optimized out. */ if (data && !((size_t)data & 2)) { - if (DECL_STATIC_CONSTRUCTOR (node->symbol.decl)) - DECL_STATIC_CONSTRUCTOR (node->symbol.decl) = 0; - if (DECL_STATIC_DESTRUCTOR (node->symbol.decl)) - DECL_STATIC_DESTRUCTOR (node->symbol.decl) = 0; + if (DECL_STATIC_CONSTRUCTOR (node->decl)) + DECL_STATIC_CONSTRUCTOR (node->decl) = 0; + if (DECL_STATIC_DESTRUCTOR (node->decl)) + DECL_STATIC_DESTRUCTOR (node->decl) = 0; } - DECL_PURE_P (node->symbol.decl) = data != NULL; - DECL_LOOPING_CONST_OR_PURE_P (node->symbol.decl) = ((size_t)data & 2) != 0; + DECL_PURE_P (node->decl) = data != NULL; + DECL_LOOPING_CONST_OR_PURE_P (node->decl) = ((size_t)data & 2) != 0; return false; } @@ -2288,7 +2291,7 @@ cgraph_set_pure_flag (struct cgraph_node *node, bool pure, bool looping) bool cgraph_node_cannot_return (struct cgraph_node *node) { - int flags = flags_from_decl_or_type (node->symbol.decl); + int flags = flags_from_decl_or_type (node->decl); if (!flag_exceptions) return (flags & ECF_NORETURN) != 0; else @@ -2327,19 +2330,19 @@ cgraph_can_remove_if_no_direct_calls_and_refs_p (struct cgraph_node *node) { gcc_assert (!node->global.inlined_to); /* Extern inlines can always go, we will use the external definition. */ - if (DECL_EXTERNAL (node->symbol.decl)) + if (DECL_EXTERNAL (node->decl)) return true; /* When function is needed, we can not remove it. */ - if (node->symbol.force_output || node->symbol.used_from_other_partition) + if (node->force_output || node->used_from_other_partition) return false; - if (DECL_STATIC_CONSTRUCTOR (node->symbol.decl) - || DECL_STATIC_DESTRUCTOR (node->symbol.decl)) + if (DECL_STATIC_CONSTRUCTOR (node->decl) + || DECL_STATIC_DESTRUCTOR (node->decl)) return false; /* Only COMDAT functions can be removed if externally visible. */ - if (node->symbol.externally_visible - && (!DECL_COMDAT (node->symbol.decl) - || node->symbol.forced_by_abi - || symtab_used_from_object_file_p ((symtab_node) node))) + if (node->externally_visible + && (!DECL_COMDAT (node->decl) + || node->forced_by_abi + || symtab_used_from_object_file_p (node))) return false; return true; } @@ -2359,9 +2362,9 @@ bool cgraph_can_remove_if_no_direct_calls_p (struct cgraph_node *node) { /* Extern inlines can always go, we will use the external definition. */ - if (DECL_EXTERNAL (node->symbol.decl)) + if (DECL_EXTERNAL (node->decl)) return true; - if (node->symbol.address_taken) + if (node->address_taken) return false; return !cgraph_for_node_and_aliases (node, nonremovable_p, NULL, true); } @@ -2371,7 +2374,7 @@ cgraph_can_remove_if_no_direct_calls_p (struct cgraph_node *node) static bool used_from_object_file_p (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED) { - return symtab_used_from_object_file_p ((symtab_node) node); + return symtab_used_from_object_file_p (node); } /* Return true when function NODE can be expected to be removed @@ -2398,7 +2401,7 @@ cgraph_will_be_removed_from_program_if_no_direct_calls (struct cgraph_node *node return cgraph_only_called_directly_p (node); else { - if (DECL_EXTERNAL (node->symbol.decl)) + if (DECL_EXTERNAL (node->decl)) return true; return cgraph_can_remove_if_no_direct_calls_p (node); } @@ -2488,7 +2491,7 @@ verify_edge_count_and_frequency (struct cgraph_edge *e) error ("caller edge frequency is too large"); error_found = true; } - if (gimple_has_body_p (e->caller->symbol.decl) + if (gimple_has_body_p (e->caller->decl) && !e->caller->global.inlined_to && !e->speculative /* FIXME: Inline-analysis sets frequency to 0 when edge is optimized out. @@ -2498,12 +2501,12 @@ verify_edge_count_and_frequency (struct cgraph_edge *e) && ((inline_edge_summary_vec.length () <= (unsigned) e->uid) || !inline_edge_summary (e)->predicate))) && (e->frequency - != compute_call_stmt_bb_frequency (e->caller->symbol.decl, + != compute_call_stmt_bb_frequency (e->caller->decl, gimple_bb (e->call_stmt)))) { error ("caller edge frequency %i does not match BB frequency %i", e->frequency, - compute_call_stmt_bb_frequency (e->caller->symbol.decl, + compute_call_stmt_bb_frequency (e->caller->decl, gimple_bb (e->call_stmt))); error_found = true; } @@ -2545,11 +2548,11 @@ verify_edge_corresponds_to_fndecl (struct cgraph_edge *e, tree decl) /* We do not know if a node from a different partition is an alias or what it aliases and therefore cannot do the former_clone_of check reliably. */ - if (!node || node->symbol.in_other_partition || e->callee->symbol.in_other_partition) + if (!node || node->in_other_partition || e->callee->in_other_partition) return false; node = cgraph_function_or_thunk_node (node, NULL); - if (e->callee->former_clone_of != node->symbol.decl + if (e->callee->former_clone_of != node->decl /* IPA-CP sometimes redirect edge to clone and then back to the former function. This ping-pong has to go, eventually. */ && (node != cgraph_function_or_thunk_node (e->callee, NULL)) @@ -2564,7 +2567,7 @@ DEBUG_FUNCTION void verify_cgraph_node (struct cgraph_node *node) { struct cgraph_edge *e; - struct function *this_cfun = DECL_STRUCT_FUNCTION (node->symbol.decl); + struct function *this_cfun = DECL_STRUCT_FUNCTION (node->decl); basic_block this_block; gimple_stmt_iterator gsi; bool error_found = false; @@ -2573,7 +2576,7 @@ verify_cgraph_node (struct cgraph_node *node) return; timevar_push (TV_CGRAPH_VERIFY); - error_found |= verify_symtab_base ((symtab_node) node); + error_found |= verify_symtab_base (node); for (e = node->callees; e; e = e->next_callee) if (e->aux) { @@ -2587,27 +2590,27 @@ verify_cgraph_node (struct cgraph_node *node) error ("execution count is negative"); error_found = true; } - if (node->global.inlined_to && node->symbol.same_comdat_group) + if (node->global.inlined_to && node->same_comdat_group) { error ("inline clone in same comdat group list"); error_found = true; } - if (!node->symbol.definition && !node->symbol.in_other_partition && node->local.local) + if (!node->definition && !node->in_other_partition && node->local.local) { error ("local symbols must be defined"); error_found = true; } - if (node->global.inlined_to && node->symbol.externally_visible) + if (node->global.inlined_to && node->externally_visible) { error ("externally visible inline clone"); error_found = true; } - if (node->global.inlined_to && node->symbol.address_taken) + if (node->global.inlined_to && node->address_taken) { error ("inline clone with address taken"); error_found = true; } - if (node->global.inlined_to && node->symbol.force_output) + if (node->global.inlined_to && node->force_output) { error ("inline clone is forced to output"); error_found = true; @@ -2710,7 +2713,7 @@ verify_cgraph_node (struct cgraph_node *node) error_found = true; } - if (node->symbol.analyzed && node->symbol.alias) + if (node->analyzed && node->alias) { bool ref_found = false; int i; @@ -2721,7 +2724,7 @@ verify_cgraph_node (struct cgraph_node *node) error ("Alias has call edges"); error_found = true; } - for (i = 0; ipa_ref_list_reference_iterate (&node->symbol.ref_list, + for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list, i, ref); i++) if (ref->use != IPA_REF_ALIAS) { @@ -2741,7 +2744,7 @@ verify_cgraph_node (struct cgraph_node *node) error_found = true; } } - if (node->symbol.analyzed && node->thunk.thunk_p) + if (node->analyzed && node->thunk.thunk_p) { if (!node->callees) { @@ -2753,15 +2756,15 @@ verify_cgraph_node (struct cgraph_node *node) error ("More than one edge out of thunk node"); error_found = true; } - if (gimple_has_body_p (node->symbol.decl)) + if (gimple_has_body_p (node->decl)) { error ("Thunk is not supposed to have body"); error_found = true; } } - else if (node->symbol.analyzed && gimple_has_body_p (node->symbol.decl) - && !TREE_ASM_WRITTEN (node->symbol.decl) - && (!DECL_EXTERNAL (node->symbol.decl) || node->global.inlined_to) + else if (node->analyzed && gimple_has_body_p (node->decl) + && !TREE_ASM_WRITTEN (node->decl) + && (!DECL_EXTERNAL (node->decl) || node->global.inlined_to) && !flag_wpa) { if (this_cfun->cfg) @@ -2800,7 +2803,7 @@ verify_cgraph_node (struct cgraph_node *node) if (verify_edge_corresponds_to_fndecl (e, decl)) { error ("edge points to wrong declaration:"); - debug_tree (e->callee->symbol.decl); + debug_tree (e->callee->decl); fprintf (stderr," Instead of:"); debug_tree (decl); error_found = true; @@ -2826,7 +2829,7 @@ verify_cgraph_node (struct cgraph_node *node) } } for (i = 0; - ipa_ref_list_reference_iterate (&node->symbol.ref_list, i, ref); + ipa_ref_list_reference_iterate (&node->ref_list, i, ref); i++) if (ref->stmt && !pointer_set_contains (stmts, ref->stmt)) { @@ -2915,17 +2918,17 @@ cgraph_get_create_real_symbol_node (tree decl) { first_clone->clone_of = node; node->clones = first_clone; - symtab_prevail_in_asm_name_hash ((symtab_node) node); - symtab_insert_node_to_hashtable ((symtab_node) node); + symtab_prevail_in_asm_name_hash (node); + symtab_insert_node_to_hashtable (node); if (dump_file) fprintf (dump_file, "Introduced new external node " "(%s/%i) and turned into root of the clone tree.\n", - xstrdup (cgraph_node_name (node)), node->symbol.order); + xstrdup (cgraph_node_name (node)), node->order); } else if (dump_file) fprintf (dump_file, "Introduced new external node " "(%s/%i).\n", xstrdup (cgraph_node_name (node)), - node->symbol.order); + node->order); return node; } @@ -2964,14 +2967,14 @@ cgraph_get_body (struct cgraph_node *node) struct lto_file_decl_data *file_data; const char *data, *name; size_t len; - tree decl = node->symbol.decl; + tree decl = node->decl; if (DECL_RESULT (decl)) return false; gcc_assert (in_lto_p); - file_data = node->symbol.lto_file_data; + file_data = node->lto_file_data; name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); /* We may have renamed the declaration, e.g., a static function. */ @@ -2993,7 +2996,7 @@ cgraph_get_body (struct cgraph_node *node) lto_stats.num_function_bodies++; lto_free_section_data (file_data, LTO_section_function_body, name, data, len); - lto_free_function_in_decl_state_for_node ((symtab_node) node); + lto_free_function_in_decl_state_for_node (node); return true; } diff --git a/gcc/cgraph.h b/gcc/cgraph.h index 69adf4d1916..4f93713b889 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -24,7 +24,7 @@ along with GCC; see the file COPYING3. If not see #include "is-a.h" #include "plugin-api.h" #include "vec.h" -#include "tree.h" +#include "basic-block.h" #include "function.h" #include "ipa-ref.h" @@ -39,8 +39,11 @@ enum symtab_type /* Base of all entries in the symbol table. The symtab_node is inherited by cgraph and varpol nodes. */ -struct GTY(()) symtab_node_base +class GTY((desc ("%h.type"), tag ("SYMTAB_SYMBOL"), + chain_next ("%h.next"), chain_prev ("%h.previous"))) + symtab_node { +public: /* Type of the symbol. */ ENUM_BITFIELD (symtab_type) type : 8; @@ -110,8 +113,8 @@ struct GTY(()) symtab_node_base tree decl; /* Linked list of symbol table entries starting with symtab_nodes. */ - symtab_node next; - symtab_node previous; + symtab_node *next; + symtab_node *previous; /* Linked list of symbols with the same asm name. There may be multiple entries for single symbol name during LTO, because symbols are renamed @@ -122,11 +125,11 @@ struct GTY(()) symtab_node_base There are also several long standing bugs where frontends and builtin code produce duplicated decls. */ - symtab_node next_sharing_asm_name; - symtab_node previous_sharing_asm_name; + symtab_node *next_sharing_asm_name; + symtab_node *previous_sharing_asm_name; /* Circular list of nodes in the same comdat group if non-NULL. */ - symtab_node same_comdat_group; + symtab_node *same_comdat_group; /* Vectors of referring and referenced entities. */ struct ipa_ref_list ref_list; @@ -251,25 +254,19 @@ struct GTY(()) cgraph_clone_info /* The cgraph data structure. Each function decl has assigned cgraph_node listing callees and callers. */ -struct GTY(()) cgraph_node { - struct symtab_node_base symbol; +struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : public symtab_node { +public: struct cgraph_edge *callees; struct cgraph_edge *callers; /* List of edges representing indirect calls with a yet undetermined callee. */ struct cgraph_edge *indirect_calls; /* For nested functions points to function the node is nested in. */ - struct cgraph_node * - GTY ((nested_ptr (union symtab_node_def, "(struct cgraph_node *)(%h)", "(symtab_node)%h"))) - origin; + struct cgraph_node *origin; /* Points to first nested function, if any. */ - struct cgraph_node * - GTY ((nested_ptr (union symtab_node_def, "(struct cgraph_node *)(%h)", "(symtab_node)%h"))) - nested; + struct cgraph_node *nested; /* Pointer to the next function with same origin, if any. */ - struct cgraph_node * - GTY ((nested_ptr (union symtab_node_def, "(struct cgraph_node *)(%h)", "(symtab_node)%h"))) - next_nested; + struct cgraph_node *next_nested; /* Pointer to the next clone. */ struct cgraph_node *next_sibling_clone; struct cgraph_node *prev_sibling_clone; @@ -517,9 +514,8 @@ typedef struct cgraph_edge *cgraph_edge_p; /* The varpool data structure. Each static variable decl has assigned varpool_node. */ -struct GTY(()) varpool_node { - struct symtab_node_base symbol; - +class GTY((tag ("SYMTAB_VARIABLE"))) varpool_node : public symtab_node { +public: /* Set when variable is scheduled to be assembled. */ unsigned output : 1; }; @@ -535,24 +531,14 @@ struct GTY(()) asm_node { int order; }; -/* Symbol table entry. */ -union GTY((desc ("%h.symbol.type"), chain_next ("%h.symbol.next"), - chain_prev ("%h.symbol.previous"))) symtab_node_def { - struct symtab_node_base GTY ((tag ("SYMTAB_SYMBOL"))) symbol; - /* To access the following fields, - use the use dyn_cast or as_a to obtain the concrete type. */ - struct cgraph_node GTY ((tag ("SYMTAB_FUNCTION"))) x_function; - struct varpool_node GTY ((tag ("SYMTAB_VARIABLE"))) x_variable; -}; - /* Report whether or not THIS symtab node is a function, aka cgraph_node. */ template <> template <> inline bool -is_a_helper <cgraph_node>::test (symtab_node_def *p) +is_a_helper <cgraph_node>::test (symtab_node *p) { - return p->symbol.type == SYMTAB_FUNCTION; + return p->type == SYMTAB_FUNCTION; } /* Report whether or not THIS symtab node is a vriable, aka varpool_node. */ @@ -560,12 +546,12 @@ is_a_helper <cgraph_node>::test (symtab_node_def *p) template <> template <> inline bool -is_a_helper <varpool_node>::test (symtab_node_def *p) +is_a_helper <varpool_node>::test (symtab_node *p) { - return p->symbol.type == SYMTAB_VARIABLE; + return p->type == SYMTAB_VARIABLE; } -extern GTY(()) symtab_node symtab_nodes; +extern GTY(()) symtab_node *symtab_nodes; extern GTY(()) int cgraph_n_nodes; extern GTY(()) int cgraph_max_uid; extern GTY(()) int cgraph_edge_max_uid; @@ -596,37 +582,37 @@ extern GTY(()) int symtab_order; extern bool cpp_implicit_aliases_done; /* In symtab.c */ -void symtab_register_node (symtab_node); -void symtab_unregister_node (symtab_node); -void symtab_remove_node (symtab_node); -symtab_node symtab_get_node (const_tree); -symtab_node symtab_node_for_asm (const_tree asmname); -const char * symtab_node_asm_name (symtab_node); -const char * symtab_node_name (symtab_node); -void symtab_insert_node_to_hashtable (symtab_node); -void symtab_add_to_same_comdat_group (symtab_node, symtab_node); -void symtab_dissolve_same_comdat_group_list (symtab_node node); +void symtab_register_node (symtab_node *); +void symtab_unregister_node (symtab_node *); +void symtab_remove_node (symtab_node *); +symtab_node *symtab_get_node (const_tree); +symtab_node *symtab_node_for_asm (const_tree asmname); +const char * symtab_node_asm_name (symtab_node *); +const char * symtab_node_name (symtab_node *); +void symtab_insert_node_to_hashtable (symtab_node *); +void symtab_add_to_same_comdat_group (symtab_node *, symtab_node *); +void symtab_dissolve_same_comdat_group_list (symtab_node *node); void dump_symtab (FILE *); void debug_symtab (void); -void dump_symtab_node (FILE *, symtab_node); -void debug_symtab_node (symtab_node); -void dump_symtab_base (FILE *, symtab_node); +void dump_symtab_node (FILE *, symtab_node *); +void debug_symtab_node (symtab_node *); +void dump_symtab_base (FILE *, symtab_node *); void verify_symtab (void); -void verify_symtab_node (symtab_node); -bool verify_symtab_base (symtab_node); -bool symtab_used_from_object_file_p (symtab_node); +void verify_symtab_node (symtab_node *); +bool verify_symtab_base (symtab_node *); +bool symtab_used_from_object_file_p (symtab_node *); void symtab_make_decl_local (tree); -symtab_node symtab_alias_ultimate_target (symtab_node, +symtab_node *symtab_alias_ultimate_target (symtab_node *, enum availability *avail = NULL); -bool symtab_resolve_alias (symtab_node node, symtab_node target); -void fixup_same_cpp_alias_visibility (symtab_node node, symtab_node target); -bool symtab_for_node_and_aliases (symtab_node, - bool (*) (symtab_node, void *), +bool symtab_resolve_alias (symtab_node *node, symtab_node *target); +void fixup_same_cpp_alias_visibility (symtab_node *node, symtab_node *target); +bool symtab_for_node_and_aliases (symtab_node *, + bool (*) (symtab_node *, void *), void *, bool); -symtab_node symtab_nonoverwritable_alias (symtab_node); -enum availability symtab_node_availability (symtab_node); -bool symtab_semantically_equivalent_p (symtab_node, symtab_node); +symtab_node *symtab_nonoverwritable_alias (symtab_node *); +enum availability symtab_node_availability (symtab_node *); +bool symtab_semantically_equivalent_p (symtab_node *, symtab_node *); /* In cgraph.c */ void dump_cgraph (FILE *); @@ -752,7 +738,7 @@ void compile (void); void init_cgraph (void); bool cgraph_process_new_functions (void); void cgraph_process_same_body_aliases (void); -void fixup_same_cpp_alias_visibility (symtab_node, symtab_node target, tree); +void fixup_same_cpp_alias_visibility (symtab_node *, symtab_node *target, tree); /* Initialize datastructures so DECL is a function in lowered gimple form. IN_SSA is true if the gimple is in SSA. */ basic_block init_lowered_empty_function (tree, bool); @@ -856,23 +842,23 @@ bool varpool_for_node_and_aliases (struct varpool_node *, void *, bool); void varpool_add_new_variable (tree); void symtab_initialize_asm_name_hash (void); -void symtab_prevail_in_asm_name_hash (symtab_node node); +void symtab_prevail_in_asm_name_hash (symtab_node *node); void varpool_remove_initializer (struct varpool_node *); /* Return callgraph node for given symbol and check it is a function. */ static inline struct cgraph_node * -cgraph (symtab_node node) +cgraph (symtab_node *node) { - gcc_checking_assert (!node || node->symbol.type == SYMTAB_FUNCTION); + gcc_checking_assert (!node || node->type == SYMTAB_FUNCTION); return (struct cgraph_node *)node; } /* Return varpool node for given symbol and check it is a variable. */ static inline struct varpool_node * -varpool (symtab_node node) +varpool (symtab_node *node) { - gcc_checking_assert (!node || node->symbol.type == SYMTAB_VARIABLE); + gcc_checking_assert (!node || node->type == SYMTAB_VARIABLE); return (struct varpool_node *)node; } @@ -896,41 +882,41 @@ varpool_get_node (const_tree decl) static inline const char * cgraph_node_asm_name (struct cgraph_node *node) { - return symtab_node_asm_name ((symtab_node)node); + return symtab_node_asm_name (node); } /* Return asm name of varpool node. */ static inline const char * varpool_node_asm_name (struct varpool_node *node) { - return symtab_node_asm_name ((symtab_node)node); + return symtab_node_asm_name (node); } /* Return name of cgraph node. */ static inline const char * cgraph_node_name (struct cgraph_node *node) { - return symtab_node_name ((symtab_node)node); + return symtab_node_name (node); } /* Return name of varpool node. */ static inline const char * varpool_node_name (struct varpool_node *node) { - return symtab_node_name ((symtab_node)node); + return symtab_node_name (node); } /* Walk all symbols. */ #define FOR_EACH_SYMBOL(node) \ - for ((node) = symtab_nodes; (node); (node) = (node)->symbol.next) + for ((node) = symtab_nodes; (node); (node) = (node)->next) /* Return first variable. */ static inline struct varpool_node * varpool_first_variable (void) { - symtab_node node; - for (node = symtab_nodes; node; node = node->symbol.next) + symtab_node *node; + for (node = symtab_nodes; node; node = node->next) if (varpool_node *vnode = dyn_cast <varpool_node> (node)) return vnode; return NULL; @@ -940,8 +926,8 @@ varpool_first_variable (void) static inline struct varpool_node * varpool_next_variable (struct varpool_node *node) { - symtab_node node1 = (symtab_node) node->symbol.next; - for (; node1; node1 = node1->symbol.next) + symtab_node *node1 = node->next; + for (; node1; node1 = node1->next) if (varpool_node *vnode1 = dyn_cast <varpool_node> (node1)) return vnode1; return NULL; @@ -956,11 +942,11 @@ varpool_next_variable (struct varpool_node *node) static inline struct varpool_node * varpool_first_static_initializer (void) { - symtab_node node; - for (node = symtab_nodes; node; node = node->symbol.next) + symtab_node *node; + for (node = symtab_nodes; node; node = node->next) { varpool_node *vnode = dyn_cast <varpool_node> (node); - if (vnode && DECL_INITIAL (node->symbol.decl)) + if (vnode && DECL_INITIAL (node->decl)) return vnode; } return NULL; @@ -970,11 +956,11 @@ varpool_first_static_initializer (void) static inline struct varpool_node * varpool_next_static_initializer (struct varpool_node *node) { - symtab_node node1 = (symtab_node) node->symbol.next; - for (; node1; node1 = node1->symbol.next) + symtab_node *node1 = node->next; + for (; node1; node1 = node1->next) { varpool_node *vnode1 = dyn_cast <varpool_node> (node1); - if (vnode1 && DECL_INITIAL (node1->symbol.decl)) + if (vnode1 && DECL_INITIAL (node1->decl)) return vnode1; } return NULL; @@ -989,11 +975,11 @@ varpool_next_static_initializer (struct varpool_node *node) static inline struct varpool_node * varpool_first_defined_variable (void) { - symtab_node node; - for (node = symtab_nodes; node; node = node->symbol.next) + symtab_node *node; + for (node = symtab_nodes; node; node = node->next) { varpool_node *vnode = dyn_cast <varpool_node> (node); - if (vnode && vnode->symbol.definition) + if (vnode && vnode->definition) return vnode; } return NULL; @@ -1003,11 +989,11 @@ varpool_first_defined_variable (void) static inline struct varpool_node * varpool_next_defined_variable (struct varpool_node *node) { - symtab_node node1 = (symtab_node) node->symbol.next; - for (; node1; node1 = node1->symbol.next) + symtab_node *node1 = node->next; + for (; node1; node1 = node1->next) { varpool_node *vnode1 = dyn_cast <varpool_node> (node1); - if (vnode1 && vnode1->symbol.definition) + if (vnode1 && vnode1->definition) return vnode1; } return NULL; @@ -1021,11 +1007,11 @@ varpool_next_defined_variable (struct varpool_node *node) static inline struct cgraph_node * cgraph_first_defined_function (void) { - symtab_node node; - for (node = symtab_nodes; node; node = node->symbol.next) + symtab_node *node; + for (node = symtab_nodes; node; node = node->next) { cgraph_node *cn = dyn_cast <cgraph_node> (node); - if (cn && cn->symbol.definition) + if (cn && cn->definition) return cn; } return NULL; @@ -1035,11 +1021,11 @@ cgraph_first_defined_function (void) static inline struct cgraph_node * cgraph_next_defined_function (struct cgraph_node *node) { - symtab_node node1 = (symtab_node) node->symbol.next; - for (; node1; node1 = node1->symbol.next) + symtab_node *node1 = node->next; + for (; node1; node1 = node1->next) { cgraph_node *cn1 = dyn_cast <cgraph_node> (node1); - if (cn1 && cn1->symbol.definition) + if (cn1 && cn1->definition) return cn1; } return NULL; @@ -1054,8 +1040,8 @@ cgraph_next_defined_function (struct cgraph_node *node) static inline struct cgraph_node * cgraph_first_function (void) { - symtab_node node; - for (node = symtab_nodes; node; node = node->symbol.next) + symtab_node *node; + for (node = symtab_nodes; node; node = node->next) if (cgraph_node *cn = dyn_cast <cgraph_node> (node)) return cn; return NULL; @@ -1065,8 +1051,8 @@ cgraph_first_function (void) static inline struct cgraph_node * cgraph_next_function (struct cgraph_node *node) { - symtab_node node1 = (symtab_node) node->symbol.next; - for (; node1; node1 = node1->symbol.next) + symtab_node *node1 = node->next; + for (; node1; node1 = node1->next) if (cgraph_node *cn1 = dyn_cast <cgraph_node> (node1)) return cn1; return NULL; @@ -1085,15 +1071,15 @@ cgraph_next_function (struct cgraph_node *node) static inline bool cgraph_function_with_gimple_body_p (struct cgraph_node *node) { - return node->symbol.definition && !node->thunk.thunk_p && !node->symbol.alias; + return node->definition && !node->thunk.thunk_p && !node->alias; } /* Return first function with body defined. */ static inline struct cgraph_node * cgraph_first_function_with_gimple_body (void) { - symtab_node node; - for (node = symtab_nodes; node; node = node->symbol.next) + symtab_node *node; + for (node = symtab_nodes; node; node = node->next) { cgraph_node *cn = dyn_cast <cgraph_node> (node); if (cn && cgraph_function_with_gimple_body_p (cn)) @@ -1106,8 +1092,8 @@ cgraph_first_function_with_gimple_body (void) static inline struct cgraph_node * cgraph_next_function_with_gimple_body (struct cgraph_node *node) { - symtab_node node1 = node->symbol.next; - for (; node1; node1 = node1->symbol.next) + symtab_node *node1 = node->next; + for (; node1; node1 = node1->next) { cgraph_node *cn1 = dyn_cast <cgraph_node> (node1); if (cn1 && cgraph_function_with_gimple_body_p (cn1)) @@ -1259,12 +1245,12 @@ static inline bool cgraph_only_called_directly_or_aliased_p (struct cgraph_node *node) { gcc_assert (!node->global.inlined_to); - return (!node->symbol.force_output && !node->symbol.address_taken - && !node->symbol.used_from_other_partition - && !DECL_VIRTUAL_P (node->symbol.decl) - && !DECL_STATIC_CONSTRUCTOR (node->symbol.decl) - && !DECL_STATIC_DESTRUCTOR (node->symbol.decl) - && !node->symbol.externally_visible); + return (!node->force_output && !node->address_taken + && !node->used_from_other_partition + && !DECL_VIRTUAL_P (node->decl) + && !DECL_STATIC_CONSTRUCTOR (node->decl) + && !DECL_STATIC_DESTRUCTOR (node->decl) + && !node->externally_visible); } /* Return true when function NODE can be removed from callgraph @@ -1273,14 +1259,14 @@ cgraph_only_called_directly_or_aliased_p (struct cgraph_node *node) static inline bool varpool_can_remove_if_no_refs (struct varpool_node *node) { - if (DECL_EXTERNAL (node->symbol.decl)) + if (DECL_EXTERNAL (node->decl)) return true; - return (!node->symbol.force_output && !node->symbol.used_from_other_partition - && ((DECL_COMDAT (node->symbol.decl) - && !node->symbol.forced_by_abi - && !symtab_used_from_object_file_p ((symtab_node) node)) - || !node->symbol.externally_visible - || DECL_HAS_VALUE_EXPR_P (node->symbol.decl))); + return (!node->force_output && !node->used_from_other_partition + && ((DECL_COMDAT (node->decl) + && !node->forced_by_abi + && !symtab_used_from_object_file_p (node)) + || !node->externally_visible + || DECL_HAS_VALUE_EXPR_P (node->decl))); } /* Return true when all references to VNODE must be visible in ipa_ref_list. @@ -1291,10 +1277,10 @@ varpool_can_remove_if_no_refs (struct varpool_node *node) static inline bool varpool_all_refs_explicit_p (struct varpool_node *vnode) { - return (vnode->symbol.definition - && !vnode->symbol.externally_visible - && !vnode->symbol.used_from_other_partition - && !vnode->symbol.force_output); + return (vnode->definition + && !vnode->externally_visible + && !vnode->used_from_other_partition + && !vnode->force_output); } /* Constant pool accessor function. */ @@ -1305,11 +1291,11 @@ htab_t constant_pool_htab (void); /* Return node that alias N is aliasing. */ -static inline symtab_node -symtab_alias_target (symtab_node n) +static inline symtab_node * +symtab_alias_target (symtab_node *n) { struct ipa_ref *ref; - ipa_ref_list_reference_iterate (&n->symbol.ref_list, 0, ref); + ipa_ref_list_reference_iterate (&n->ref_list, 0, ref); gcc_checking_assert (ref->use == IPA_REF_ALIAS); return ref->referred; } @@ -1317,13 +1303,13 @@ symtab_alias_target (symtab_node n) static inline struct cgraph_node * cgraph_alias_target (struct cgraph_node *n) { - return dyn_cast <cgraph_node> (symtab_alias_target ((symtab_node) n)); + return dyn_cast <cgraph_node> (symtab_alias_target (n)); } static inline struct varpool_node * varpool_alias_target (struct varpool_node *n) { - return dyn_cast <varpool_node> (symtab_alias_target ((symtab_node) n)); + return dyn_cast <varpool_node> (symtab_alias_target (n)); } /* Given NODE, walk the alias chain to return the function NODE is alias of. @@ -1336,7 +1322,7 @@ cgraph_function_or_thunk_node (struct cgraph_node *node, { struct cgraph_node *n; - n = dyn_cast <cgraph_node> (symtab_alias_ultimate_target ((symtab_node)node, + n = dyn_cast <cgraph_node> (symtab_alias_ultimate_target (node, availability)); if (!n && availability) *availability = AVAIL_NOT_AVAILABLE; @@ -1352,7 +1338,7 @@ varpool_variable_node (struct varpool_node *node, { struct varpool_node *n; - n = dyn_cast <varpool_node> (symtab_alias_ultimate_target ((symtab_node)node, + n = dyn_cast <varpool_node> (symtab_alias_ultimate_target (node, availability)); if (!n && availability) *availability = AVAIL_NOT_AVAILABLE; @@ -1365,9 +1351,9 @@ cgraph_edge_recursive_p (struct cgraph_edge *e) { struct cgraph_node *callee = cgraph_function_or_thunk_node (e->callee, NULL); if (e->caller->global.inlined_to) - return e->caller->global.inlined_to->symbol.decl == callee->symbol.decl; + return e->caller->global.inlined_to->decl == callee->decl; else - return e->caller->symbol.decl == callee->symbol.decl; + return e->caller->decl == callee->decl; } /* Return true if the TM_CLONE bit is set for a given FNDECL. */ @@ -1386,7 +1372,7 @@ decl_is_tm_clone (const_tree fndecl) static inline void cgraph_mark_force_output_node (struct cgraph_node *node) { - node->symbol.force_output = 1; + node->force_output = 1; gcc_checking_assert (!node->global.inlined_to); } @@ -1394,11 +1380,11 @@ cgraph_mark_force_output_node (struct cgraph_node *node) or abstract function kept for debug info purposes only. */ static inline bool -symtab_real_symbol_p (symtab_node node) +symtab_real_symbol_p (symtab_node *node) { struct cgraph_node *cnode; - if (DECL_ABSTRACT (node->symbol.decl)) + if (DECL_ABSTRACT (node->decl)) return false; if (!is_a <cgraph_node> (node)) return true; @@ -1411,12 +1397,12 @@ symtab_real_symbol_p (symtab_node node) /* Return true if NODE can be discarded by linker from the binary. */ static inline bool -symtab_can_be_discarded (symtab_node node) +symtab_can_be_discarded (symtab_node *node) { - return (DECL_EXTERNAL (node->symbol.decl) - || (DECL_ONE_ONLY (node->symbol.decl) - && node->symbol.resolution != LDPR_PREVAILING_DEF - && node->symbol.resolution != LDPR_PREVAILING_DEF_IRONLY - && node->symbol.resolution != LDPR_PREVAILING_DEF_IRONLY_EXP)); + return (DECL_EXTERNAL (node->decl) + || (DECL_ONE_ONLY (node->decl) + && node->resolution != LDPR_PREVAILING_DEF + && node->resolution != LDPR_PREVAILING_DEF_IRONLY + && node->resolution != LDPR_PREVAILING_DEF_IRONLY_EXP)); } #endif /* GCC_CGRAPH_H */ diff --git a/gcc/cgraphbuild.c b/gcc/cgraphbuild.c index 1b73a144f08..87e06e37cbe 100644 --- a/gcc/cgraphbuild.c +++ b/gcc/cgraphbuild.c @@ -23,12 +23,10 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tm.h" #include "tree.h" -#include "tree-ssa.h" +#include "gimple.h" #include "langhooks.h" #include "pointer-set.h" -#include "cgraph.h" #include "intl.h" -#include "gimple.h" #include "tree-pass.h" #include "ipa-utils.h" #include "except.h" @@ -76,16 +74,16 @@ record_reference (tree *tp, int *walk_subtrees, void *data) struct cgraph_node *node = cgraph_get_create_real_symbol_node (decl); if (!ctx->only_vars) cgraph_mark_address_taken_node (node); - ipa_record_reference ((symtab_node)ctx->varpool_node, - (symtab_node)node, + ipa_record_reference (ctx->varpool_node, + node, IPA_REF_ADDR, NULL); } if (TREE_CODE (decl) == VAR_DECL) { struct varpool_node *vnode = varpool_node_for_decl (decl); - ipa_record_reference ((symtab_node)ctx->varpool_node, - (symtab_node)vnode, + ipa_record_reference (ctx->varpool_node, + vnode, IPA_REF_ADDR, NULL); } *walk_subtrees = 0; @@ -123,8 +121,8 @@ record_type_list (struct cgraph_node *node, tree list) if (TREE_CODE (type) == VAR_DECL) { struct varpool_node *vnode = varpool_node_for_decl (type); - ipa_record_reference ((symtab_node)node, - (symtab_node)vnode, + ipa_record_reference (node, + vnode, IPA_REF_ADDR, NULL); } } @@ -139,12 +137,12 @@ record_eh_tables (struct cgraph_node *node, struct function *fun) { eh_region i; - if (DECL_FUNCTION_PERSONALITY (node->symbol.decl)) + if (DECL_FUNCTION_PERSONALITY (node->decl)) { struct cgraph_node *per_node; - per_node = cgraph_get_create_real_symbol_node (DECL_FUNCTION_PERSONALITY (node->symbol.decl)); - ipa_record_reference ((symtab_node)node, (symtab_node)per_node, IPA_REF_ADDR, NULL); + per_node = cgraph_get_create_real_symbol_node (DECL_FUNCTION_PERSONALITY (node->decl)); + ipa_record_reference (node, per_node, IPA_REF_ADDR, NULL); cgraph_mark_address_taken_node (per_node); } @@ -225,8 +223,8 @@ mark_address (gimple stmt, tree addr, void *data) { struct cgraph_node *node = cgraph_get_create_real_symbol_node (addr); cgraph_mark_address_taken_node (node); - ipa_record_reference ((symtab_node)data, - (symtab_node)node, + ipa_record_reference ((symtab_node *)data, + node, IPA_REF_ADDR, stmt); } else if (addr && TREE_CODE (addr) == VAR_DECL @@ -234,8 +232,8 @@ mark_address (gimple stmt, tree addr, void *data) { struct varpool_node *vnode = varpool_node_for_decl (addr); - ipa_record_reference ((symtab_node)data, - (symtab_node)vnode, + ipa_record_reference ((symtab_node *)data, + vnode, IPA_REF_ADDR, stmt); } @@ -254,8 +252,8 @@ mark_load (gimple stmt, tree t, void *data) directly manipulated in the code. Pretend that it's an address. */ struct cgraph_node *node = cgraph_get_create_real_symbol_node (t); cgraph_mark_address_taken_node (node); - ipa_record_reference ((symtab_node)data, - (symtab_node)node, + ipa_record_reference ((symtab_node *)data, + node, IPA_REF_ADDR, stmt); } else if (t && TREE_CODE (t) == VAR_DECL @@ -263,8 +261,8 @@ mark_load (gimple stmt, tree t, void *data) { struct varpool_node *vnode = varpool_node_for_decl (t); - ipa_record_reference ((symtab_node)data, - (symtab_node)vnode, + ipa_record_reference ((symtab_node *)data, + vnode, IPA_REF_LOAD, stmt); } return false; @@ -281,8 +279,8 @@ mark_store (gimple stmt, tree t, void *data) { struct varpool_node *vnode = varpool_node_for_decl (t); - ipa_record_reference ((symtab_node)data, - (symtab_node)vnode, + ipa_record_reference ((symtab_node *)data, + vnode, IPA_REF_STORE, stmt); } return false; @@ -339,21 +337,21 @@ build_cgraph_edges (void) && gimple_omp_parallel_child_fn (stmt)) { tree fn = gimple_omp_parallel_child_fn (stmt); - ipa_record_reference ((symtab_node)node, - (symtab_node)cgraph_get_create_real_symbol_node (fn), + ipa_record_reference (node, + cgraph_get_create_real_symbol_node (fn), IPA_REF_ADDR, stmt); } if (gimple_code (stmt) == GIMPLE_OMP_TASK) { tree fn = gimple_omp_task_child_fn (stmt); if (fn) - ipa_record_reference ((symtab_node)node, - (symtab_node) cgraph_get_create_real_symbol_node (fn), + ipa_record_reference (node, + cgraph_get_create_real_symbol_node (fn), IPA_REF_ADDR, stmt); fn = gimple_omp_task_copy_fn (stmt); if (fn) - ipa_record_reference ((symtab_node)node, - (symtab_node)cgraph_get_create_real_symbol_node (fn), + ipa_record_reference (node, + cgraph_get_create_real_symbol_node (fn), IPA_REF_ADDR, stmt); } } @@ -439,7 +437,7 @@ rebuild_cgraph_edges (void) gimple_stmt_iterator gsi; cgraph_node_remove_callees (node); - ipa_remove_all_references (&node->symbol.ref_list); + ipa_remove_all_references (&node->ref_list); node->count = ENTRY_BLOCK_PTR->count; @@ -487,7 +485,7 @@ cgraph_rebuild_references (void) int i; /* Keep speculative references for further cgraph edge expansion. */ - for (i = 0; ipa_ref_list_reference_iterate (&node->symbol.ref_list, i, ref);) + for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list, i, ref);) if (!ref->speculative) ipa_remove_reference (ref); else @@ -549,7 +547,7 @@ remove_cgraph_callee_edges (void) { struct cgraph_node *node = cgraph_get_node (current_function_decl); cgraph_node_remove_callees (node); - ipa_remove_all_references (&node->symbol.ref_list); + ipa_remove_all_references (&node->ref_list); return 0; } diff --git a/gcc/cgraphclones.c b/gcc/cgraphclones.c index cad10a7dcb0..373f5013d26 100644 --- a/gcc/cgraphclones.c +++ b/gcc/cgraphclones.c @@ -69,8 +69,10 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tm.h" #include "tree.h" +#include "gimple.h" #include "rtl.h" -#include "tree-ssa.h" +#include "bitmap.h" +#include "tree-cfg.h" #include "tree-inline.h" #include "langhooks.h" #include "pointer-set.h" @@ -79,13 +81,11 @@ along with GCC; see the file COPYING3. If not see #include "ggc.h" #include "debug.h" #include "target.h" -#include "cgraph.h" #include "diagnostic.h" #include "params.h" #include "intl.h" #include "function.h" #include "ipa-prop.h" -#include "gimple.h" #include "tree-iterator.h" #include "tree-dump.h" #include "gimple-pretty-print.h" @@ -187,19 +187,19 @@ cgraph_clone_node (struct cgraph_node *n, tree decl, gcov_type count, int freq, gcov_type count_scale; unsigned i; - new_node->symbol.decl = decl; - symtab_register_node ((symtab_node)new_node); + new_node->decl = decl; + symtab_register_node (new_node); new_node->origin = n->origin; - new_node->symbol.lto_file_data = n->symbol.lto_file_data; + new_node->lto_file_data = n->lto_file_data; if (new_node->origin) { new_node->next_nested = new_node->origin->nested; new_node->origin->nested = new_node; } - new_node->symbol.analyzed = n->symbol.analyzed; - new_node->symbol.definition = n->symbol.definition; + new_node->analyzed = n->analyzed; + new_node->definition = n->definition; new_node->local = n->local; - new_node->symbol.externally_visible = false; + new_node->externally_visible = false; new_node->local.local = true; new_node->global = n->global; new_node->global.inlined_to = new_inlined_to; @@ -239,7 +239,7 @@ cgraph_clone_node (struct cgraph_node *n, tree decl, gcov_type count, int freq, for (e = n->indirect_calls; e; e = e->next_callee) cgraph_clone_edge (e, new_node, e->call_stmt, e->lto_stmt_uid, count_scale, freq, update_original); - ipa_clone_references ((symtab_node)new_node, &n->symbol.ref_list); + ipa_clone_references (new_node, &n->ref_list); new_node->next_sibling_clone = n->clones; if (n->clones) @@ -290,7 +290,7 @@ cgraph_create_virtual_clone (struct cgraph_node *old_node, bitmap args_to_skip, const char * suffix) { - tree old_decl = old_node->symbol.decl; + tree old_decl = old_node->decl; struct cgraph_node *new_node = NULL; tree new_decl; size_t len, i; @@ -336,16 +336,16 @@ cgraph_create_virtual_clone (struct cgraph_node *old_node, that is not weak also. ??? We cannot use COMDAT linkage because there is no ABI support for this. */ - DECL_EXTERNAL (new_node->symbol.decl) = 0; + DECL_EXTERNAL (new_node->decl) = 0; if (DECL_ONE_ONLY (old_decl)) - DECL_SECTION_NAME (new_node->symbol.decl) = NULL; - DECL_COMDAT_GROUP (new_node->symbol.decl) = 0; - TREE_PUBLIC (new_node->symbol.decl) = 0; - DECL_COMDAT (new_node->symbol.decl) = 0; - DECL_WEAK (new_node->symbol.decl) = 0; - DECL_VIRTUAL_P (new_node->symbol.decl) = 0; - DECL_STATIC_CONSTRUCTOR (new_node->symbol.decl) = 0; - DECL_STATIC_DESTRUCTOR (new_node->symbol.decl) = 0; + DECL_SECTION_NAME (new_node->decl) = NULL; + DECL_COMDAT_GROUP (new_node->decl) = 0; + TREE_PUBLIC (new_node->decl) = 0; + DECL_COMDAT (new_node->decl) = 0; + DECL_WEAK (new_node->decl) = 0; + DECL_VIRTUAL_P (new_node->decl) = 0; + DECL_STATIC_CONSTRUCTOR (new_node->decl) = 0; + DECL_STATIC_DESTRUCTOR (new_node->decl) = 0; new_node->clone.tree_map = tree_map; new_node->clone.args_to_skip = args_to_skip; @@ -355,9 +355,9 @@ cgraph_create_virtual_clone (struct cgraph_node *old_node, && !DECL_WEAK (old_decl) && !DECL_COMDAT (old_decl)) || in_lto_p) - new_node->symbol.unique_name = true; + new_node->unique_name = true; FOR_EACH_VEC_SAFE_ELT (tree_map, i, map) - ipa_maybe_record_reference ((symtab_node) new_node, map->new_tree, + ipa_maybe_record_reference (new_node, map->new_tree, IPA_REF_ADDR, NULL); if (!args_to_skip) new_node->clone.combined_args_to_skip = old_node->clone.combined_args_to_skip; @@ -369,7 +369,7 @@ cgraph_create_virtual_clone (struct cgraph_node *old_node, struct cgraph_node *orig_node; for (orig_node = old_node; orig_node->clone_of; orig_node = orig_node->clone_of) ; - for (arg = DECL_ARGUMENTS (orig_node->symbol.decl); + for (arg = DECL_ARGUMENTS (orig_node->decl); arg; arg = DECL_CHAIN (arg), oldi++) { if (bitmap_bit_p (old_node->clone.combined_args_to_skip, oldi)) @@ -385,7 +385,7 @@ cgraph_create_virtual_clone (struct cgraph_node *old_node, } else new_node->clone.combined_args_to_skip = args_to_skip; - new_node->symbol.externally_visible = 0; + new_node->externally_visible = 0; new_node->local.local = 1; new_node->lowered = true; @@ -404,7 +404,7 @@ cgraph_find_replacement_node (struct cgraph_node *node) for (next_inline_clone = node->clones; next_inline_clone - && next_inline_clone->symbol.decl != node->symbol.decl; + && next_inline_clone->decl != node->decl; next_inline_clone = next_inline_clone->next_sibling_clone) ; @@ -631,8 +631,8 @@ update_call_expr (struct cgraph_node *new_version) /* Update the call expr on the edges to call the new version. */ for (e = new_version->callers; e; e = e->next_caller) { - struct function *inner_function = DECL_STRUCT_FUNCTION (e->caller->symbol.decl); - gimple_call_set_fndecl (e->call_stmt, new_version->symbol.decl); + struct function *inner_function = DECL_STRUCT_FUNCTION (e->caller->decl); + gimple_call_set_fndecl (e->call_stmt, new_version->decl); maybe_clean_eh_stmt_fn (inner_function, e->call_stmt); } } @@ -663,11 +663,11 @@ cgraph_copy_node_for_versioning (struct cgraph_node *old_version, new_version = cgraph_create_node (new_decl); - new_version->symbol.analyzed = old_version->symbol.analyzed; - new_version->symbol.definition = old_version->symbol.definition; + new_version->analyzed = old_version->analyzed; + new_version->definition = old_version->definition; new_version->local = old_version->local; - new_version->symbol.externally_visible = false; - new_version->local.local = new_version->symbol.definition; + new_version->externally_visible = false; + new_version->local.local = new_version->definition; new_version->global = old_version->global; new_version->rtl = old_version->rtl; new_version->count = old_version->count; @@ -728,7 +728,7 @@ cgraph_function_versioning (struct cgraph_node *old_version_node, basic_block new_entry_block, const char *clone_name) { - tree old_decl = old_version_node->symbol.decl; + tree old_decl = old_version_node->decl; struct cgraph_node *new_version_node = NULL; tree new_decl; @@ -768,9 +768,9 @@ cgraph_function_versioning (struct cgraph_node *old_version_node, that is not weak also. ??? We cannot use COMDAT linkage because there is no ABI support for this. */ - symtab_make_decl_local (new_version_node->symbol.decl); - DECL_VIRTUAL_P (new_version_node->symbol.decl) = 0; - new_version_node->symbol.externally_visible = 0; + symtab_make_decl_local (new_version_node->decl); + DECL_VIRTUAL_P (new_version_node->decl) = 0; + new_version_node->externally_visible = 0; new_version_node->local.local = 1; new_version_node->lowered = true; /* Clones of global symbols or symbols with unique names are unique. */ @@ -779,7 +779,7 @@ cgraph_function_versioning (struct cgraph_node *old_version_node, && !DECL_WEAK (old_decl) && !DECL_COMDAT (old_decl)) || in_lto_p) - new_version_node->symbol.unique_name = true; + new_version_node->unique_name = true; /* Update the call_expr on the edges to call the new version node. */ update_call_expr (new_version_node); @@ -794,18 +794,18 @@ static void cgraph_materialize_clone (struct cgraph_node *node) { bitmap_obstack_initialize (NULL); - node->former_clone_of = node->clone_of->symbol.decl; + node->former_clone_of = node->clone_of->decl; if (node->clone_of->former_clone_of) node->former_clone_of = node->clone_of->former_clone_of; /* Copy the OLD_VERSION_NODE function tree to the new version. */ - tree_function_versioning (node->clone_of->symbol.decl, node->symbol.decl, + tree_function_versioning (node->clone_of->decl, node->decl, node->clone.tree_map, true, node->clone.args_to_skip, false, NULL, NULL); if (cgraph_dump_file) { - dump_function_to_file (node->clone_of->symbol.decl, cgraph_dump_file, dump_flags); - dump_function_to_file (node->symbol.decl, cgraph_dump_file, dump_flags); + dump_function_to_file (node->clone_of->decl, cgraph_dump_file, dump_flags); + dump_function_to_file (node->decl, cgraph_dump_file, dump_flags); } /* Function is no longer clone. */ @@ -817,11 +817,11 @@ cgraph_materialize_clone (struct cgraph_node *node) node->clone_of->clones = node->next_sibling_clone; node->next_sibling_clone = NULL; node->prev_sibling_clone = NULL; - if (!node->clone_of->symbol.analyzed && !node->clone_of->clones) + if (!node->clone_of->analyzed && !node->clone_of->clones) { cgraph_release_function_body (node->clone_of); cgraph_node_remove_callees (node->clone_of); - ipa_remove_all_references (&node->clone_of->symbol.ref_list); + ipa_remove_all_references (&node->clone_of->ref_list); } node->clone_of = NULL; bitmap_obstack_release (NULL); @@ -854,12 +854,12 @@ cgraph_materialize_all_clones (void) stabilized = true; FOR_EACH_FUNCTION (node) { - if (node->clone_of && node->symbol.decl != node->clone_of->symbol.decl - && !gimple_has_body_p (node->symbol.decl)) + if (node->clone_of && node->decl != node->clone_of->decl + && !gimple_has_body_p (node->decl)) { if (!node->clone_of->clone_of) cgraph_get_body (node->clone_of); - if (gimple_has_body_p (node->clone_of->symbol.decl)) + if (gimple_has_body_p (node->clone_of->decl)) { if (cgraph_dump_file) { @@ -903,13 +903,13 @@ cgraph_materialize_all_clones (void) } } FOR_EACH_FUNCTION (node) - if (!node->symbol.analyzed && node->callees) + if (!node->analyzed && node->callees) { cgraph_node_remove_callees (node); - ipa_remove_all_references (&node->symbol.ref_list); + ipa_remove_all_references (&node->ref_list); } else - ipa_clear_stmts_in_references ((symtab_node)node); + ipa_clear_stmts_in_references (node); if (cgraph_dump_file) fprintf (cgraph_dump_file, "Materialization Call site updates done.\n"); #ifdef ENABLE_CHECKING diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index 910d7978aea..4978d2aea1a 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -164,6 +164,10 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "output.h" #include "rtl.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-cfg.h" +#include "tree-into-ssa.h" #include "tree-ssa.h" #include "tree-inline.h" #include "langhooks.h" @@ -173,14 +177,12 @@ along with GCC; see the file COPYING3. If not see #include "ggc.h" #include "debug.h" #include "target.h" -#include "cgraph.h" #include "diagnostic.h" #include "params.h" #include "fibheap.h" #include "intl.h" #include "function.h" #include "ipa-prop.h" -#include "gimple.h" #include "tree-iterator.h" #include "tree-pass.h" #include "tree-dump.h" @@ -223,27 +225,27 @@ static GTY (()) tree vtable_entry_type; either outside this translation unit, something magic in the system configury */ bool -decide_is_symbol_needed (symtab_node node) +decide_is_symbol_needed (symtab_node *node) { - tree decl = node->symbol.decl; + tree decl = node->decl; /* Double check that no one output the function into assembly file early. */ gcc_checking_assert (!DECL_ASSEMBLER_NAME_SET_P (decl) || !TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))); - if (!node->symbol.definition) + if (!node->definition) return false; if (DECL_EXTERNAL (decl)) return false; /* If the user told us it is used, then it must be so. */ - if (node->symbol.force_output) + if (node->force_output) return true; /* ABI forced symbols are needed when they are external. */ - if (node->symbol.forced_by_abi && TREE_PUBLIC (decl)) + if (node->forced_by_abi && TREE_PUBLIC (decl)) return true; /* Keep constructors, destructors and virtual functions. */ @@ -261,18 +263,18 @@ decide_is_symbol_needed (symtab_node node) /* Head of the queue of nodes to be processed while building callgraph */ -static symtab_node first = (symtab_node)(void *)1; +static symtab_node *first = (symtab_node *)(void *)1; /* Add NODE to queue starting at FIRST. The queue is linked via AUX pointers and terminated by pointer to 1. */ static void -enqueue_node (symtab_node node) +enqueue_node (symtab_node *node) { - if (node->symbol.aux) + if (node->aux) return; gcc_checking_assert (first); - node->symbol.aux = first; + node->aux = first; first = node; } @@ -296,7 +298,7 @@ cgraph_process_new_functions (void) for (csi = csi_start (cgraph_new_nodes); !csi_end_p (csi); csi_next (&csi)) { node = csi_node (csi); - fndecl = node->symbol.decl; + fndecl = node->decl; switch (cgraph_state) { case CGRAPH_STATE_CONSTRUCTION: @@ -306,7 +308,7 @@ cgraph_process_new_functions (void) cgraph_finalize_function (fndecl, false); output = true; cgraph_call_function_insertion_hooks (node); - enqueue_node ((symtab_node) node); + enqueue_node (node); break; case CGRAPH_STATE_IPA: @@ -316,7 +318,7 @@ cgraph_process_new_functions (void) cgraph but not on this function. */ gimple_register_cfg_hooks (); - if (!node->symbol.analyzed) + if (!node->analyzed) analyze_function (node); push_cfun (DECL_STRUCT_FUNCTION (fndecl)); if (cgraph_state == CGRAPH_STATE_IPA_SSA @@ -372,25 +374,25 @@ cgraph_reset_node (struct cgraph_node *node) memset (&node->local, 0, sizeof (node->local)); memset (&node->global, 0, sizeof (node->global)); memset (&node->rtl, 0, sizeof (node->rtl)); - node->symbol.analyzed = false; - node->symbol.definition = false; - node->symbol.alias = false; - node->symbol.weakref = false; - node->symbol.cpp_implicit_alias = false; + node->analyzed = false; + node->definition = false; + node->alias = false; + node->weakref = false; + node->cpp_implicit_alias = false; cgraph_node_remove_callees (node); - ipa_remove_all_references (&node->symbol.ref_list); + ipa_remove_all_references (&node->ref_list); } /* Return true when there are references to NODE. */ static bool -referred_to_p (symtab_node node) +referred_to_p (symtab_node *node) { struct ipa_ref *ref; /* See if there are any references at all. */ - if (ipa_ref_list_referring_iterate (&node->symbol.ref_list, 0, ref)) + if (ipa_ref_list_referring_iterate (&node->ref_list, 0, ref)) return true; /* For functions check also calls. */ cgraph_node *cn = dyn_cast <cgraph_node> (node); @@ -409,7 +411,7 @@ cgraph_finalize_function (tree decl, bool no_collect) { struct cgraph_node *node = cgraph_get_create_node (decl); - if (node->symbol.definition) + if (node->definition) { /* Nested functions should only be defined once. */ gcc_assert (!DECL_CONTEXT (decl) @@ -419,7 +421,7 @@ cgraph_finalize_function (tree decl, bool no_collect) } notice_global_symbol (decl); - node->symbol.definition = true; + node->definition = true; node->lowered = DECL_STRUCT_FUNCTION (decl)->cfg != NULL; /* With -fkeep-inline-functions we are keeping all inline functions except @@ -428,7 +430,7 @@ cgraph_finalize_function (tree decl, bool no_collect) && DECL_DECLARED_INLINE_P (decl) && !DECL_EXTERNAL (decl) && !DECL_DISREGARD_INLINE_LIMITS (decl)) - node->symbol.force_output = 1; + node->force_output = 1; /* When not optimizing, also output the static functions. (see PR24561), but don't do so for always_inline functions, functions @@ -436,13 +438,13 @@ cgraph_finalize_function (tree decl, bool no_collect) in the original implementation and it is unclear whether we want to change the behavior here. */ if ((!optimize - && !node->symbol.cpp_implicit_alias + && !node->cpp_implicit_alias && !DECL_DISREGARD_INLINE_LIMITS (decl) && !DECL_DECLARED_INLINE_P (decl) && !(DECL_CONTEXT (decl) && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL)) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl)) - node->symbol.force_output = 1; + node->force_output = 1; /* If we've not yet emitted decl, tell the debug info about it. */ if (!TREE_ASM_WRITTEN (decl)) @@ -456,9 +458,9 @@ cgraph_finalize_function (tree decl, bool no_collect) ggc_collect (); if (cgraph_state == CGRAPH_STATE_CONSTRUCTION - && (decide_is_symbol_needed ((symtab_node) node) - || referred_to_p ((symtab_node)node))) - enqueue_node ((symtab_node)node); + && (decide_is_symbol_needed (node) + || referred_to_p (node))) + enqueue_node (node); } /* Add the function FNDECL to the call graph. @@ -500,8 +502,8 @@ cgraph_add_new_function (tree fndecl, bool lowered) analyzing and compilation. */ node = cgraph_get_create_node (fndecl); node->local.local = false; - node->symbol.definition = true; - node->symbol.force_output = true; + node->definition = true; + node->force_output = true; if (!lowered && cgraph_state == CGRAPH_STATE_EXPANSION) { push_cfun (DECL_STRUCT_FUNCTION (fndecl)); @@ -527,7 +529,7 @@ cgraph_add_new_function (tree fndecl, bool lowered) node = cgraph_create_node (fndecl); if (lowered) node->lowered = true; - node->symbol.definition = true; + node->definition = true; analyze_function (node); push_cfun (DECL_STRUCT_FUNCTION (fndecl)); gimple_register_cfg_hooks (); @@ -588,7 +590,7 @@ output_asm_statements (void) static void analyze_function (struct cgraph_node *node) { - tree decl = node->symbol.decl; + tree decl = node->decl; location_t saved_loc = input_location; input_location = DECL_SOURCE_LOCATION (decl); @@ -599,14 +601,14 @@ analyze_function (struct cgraph_node *node) if (!expand_thunk (node, false)) { node->thunk.alias = NULL; - node->symbol.analyzed = true; + node->analyzed = true; return; } node->thunk.alias = NULL; } - if (node->symbol.alias) + if (node->alias) symtab_resolve_alias - ((symtab_node) node, (symtab_node) cgraph_get_node (node->symbol.alias_target)); + (node, cgraph_get_node (node->alias_target)); else if (node->dispatcher_function) { /* Generate the dispatcher body of multi-versioned functions. */ @@ -626,7 +628,7 @@ analyze_function (struct cgraph_node *node) { push_cfun (DECL_STRUCT_FUNCTION (decl)); - assign_assembler_name_if_neeeded (node->symbol.decl); + assign_assembler_name_if_neeeded (node->decl); /* Make sure to gimplify bodies only once. During analyzing a function we lower it, which will require gimplified nested @@ -640,7 +642,7 @@ analyze_function (struct cgraph_node *node) if (!node->lowered) { if (node->nested) - lower_nested_functions (node->symbol.decl); + lower_nested_functions (node->decl); gcc_assert (!node->nested); gimple_register_cfg_hooks (); @@ -655,7 +657,7 @@ analyze_function (struct cgraph_node *node) pop_cfun (); } - node->symbol.analyzed = true; + node->analyzed = true; input_location = saved_loc; } @@ -669,14 +671,14 @@ analyze_function (struct cgraph_node *node) void cgraph_process_same_body_aliases (void) { - symtab_node node; + symtab_node *node; FOR_EACH_SYMBOL (node) - if (node->symbol.cpp_implicit_alias && !node->symbol.analyzed) + if (node->cpp_implicit_alias && !node->analyzed) symtab_resolve_alias (node, - TREE_CODE (node->symbol.alias_target) == VAR_DECL - ? (symtab_node)varpool_node_for_decl (node->symbol.alias_target) - : (symtab_node)cgraph_get_create_node (node->symbol.alias_target)); + TREE_CODE (node->alias_target) == VAR_DECL + ? (symtab_node *)varpool_node_for_decl (node->alias_target) + : (symtab_node *)cgraph_get_create_node (node->alias_target)); cpp_implicit_aliases_done = true; } @@ -732,20 +734,20 @@ process_function_and_variable_attributes (struct cgraph_node *first, for (node = cgraph_first_function (); node != first; node = cgraph_next_function (node)) { - tree decl = node->symbol.decl; + tree decl = node->decl; if (DECL_PRESERVE_P (decl)) cgraph_mark_force_output_node (node); else if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (decl))) { - if (! TREE_PUBLIC (node->symbol.decl)) - warning_at (DECL_SOURCE_LOCATION (node->symbol.decl), OPT_Wattributes, + if (! TREE_PUBLIC (node->decl)) + warning_at (DECL_SOURCE_LOCATION (node->decl), OPT_Wattributes, "%<externally_visible%>" " attribute have effect only on public objects"); } if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)) - && (node->symbol.definition && !node->symbol.alias)) + && (node->definition && !node->alias)) { - warning_at (DECL_SOURCE_LOCATION (node->symbol.decl), OPT_Wattributes, + warning_at (DECL_SOURCE_LOCATION (node->decl), OPT_Wattributes, "%<weakref%> attribute ignored" " because function is defined"); DECL_WEAK (decl) = 0; @@ -765,24 +767,24 @@ process_function_and_variable_attributes (struct cgraph_node *first, for (vnode = varpool_first_variable (); vnode != first_var; vnode = varpool_next_variable (vnode)) { - tree decl = vnode->symbol.decl; + tree decl = vnode->decl; if (DECL_EXTERNAL (decl) && DECL_INITIAL (decl)) varpool_finalize_decl (decl); if (DECL_PRESERVE_P (decl)) - vnode->symbol.force_output = true; + vnode->force_output = true; else if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (decl))) { - if (! TREE_PUBLIC (vnode->symbol.decl)) - warning_at (DECL_SOURCE_LOCATION (vnode->symbol.decl), OPT_Wattributes, + if (! TREE_PUBLIC (vnode->decl)) + warning_at (DECL_SOURCE_LOCATION (vnode->decl), OPT_Wattributes, "%<externally_visible%>" " attribute have effect only on public objects"); } if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)) - && vnode->symbol.definition + && vnode->definition && DECL_INITIAL (decl)) { - warning_at (DECL_SOURCE_LOCATION (vnode->symbol.decl), OPT_Wattributes, + warning_at (DECL_SOURCE_LOCATION (vnode->decl), OPT_Wattributes, "%<weakref%> attribute ignored" " because variable is initialized"); DECL_WEAK (decl) = 0; @@ -804,21 +806,21 @@ varpool_finalize_decl (tree decl) gcc_assert (TREE_STATIC (decl) || DECL_EXTERNAL (decl)); - if (node->symbol.definition) + if (node->definition) return; notice_global_symbol (decl); - node->symbol.definition = true; + node->definition = true; if (TREE_THIS_VOLATILE (decl) || DECL_PRESERVE_P (decl) /* Traditionally we do not eliminate static variables when not optimizing and when not doing toplevel reoder. */ - || (!flag_toplevel_reorder && !DECL_COMDAT (node->symbol.decl) - && !DECL_ARTIFICIAL (node->symbol.decl))) - node->symbol.force_output = true; + || (!flag_toplevel_reorder && !DECL_COMDAT (node->decl) + && !DECL_ARTIFICIAL (node->decl))) + node->force_output = true; if (cgraph_state == CGRAPH_STATE_CONSTRUCTION - && (decide_is_symbol_needed ((symtab_node) node) - || referred_to_p ((symtab_node)node))) - enqueue_node ((symtab_node)node); + && (decide_is_symbol_needed (node) + || referred_to_p (node))) + enqueue_node (node); if (cgraph_state >= CGRAPH_STATE_IPA_SSA) varpool_analyze_node (node); /* Some frontends produce various interface variables after compilation @@ -855,14 +857,14 @@ walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets, /* Do not bother to mark virtual methods in anonymous namespace; either we will find use of virtual table defining it, or it is unused. */ - if (targets[i]->symbol.definition + if (targets[i]->definition && TREE_CODE - (TREE_TYPE (targets[i]->symbol.decl)) + (TREE_TYPE (targets[i]->decl)) == METHOD_TYPE && !type_in_anonymous_namespace_p (method_class_type - (TREE_TYPE (targets[i]->symbol.decl)))) - enqueue_node ((symtab_node) targets[i]); + (TREE_TYPE (targets[i]->decl)))) + enqueue_node (targets[i]); } } @@ -918,7 +920,8 @@ analyze_functions (void) struct varpool_node *first_handled_var = first_analyzed_var; struct pointer_set_t *reachable_call_targets = pointer_set_create (); - symtab_node node, next; + symtab_node *node; + symtab_node *next; int i; struct ipa_ref *ref; bool changed = true; @@ -932,7 +935,7 @@ analyze_functions (void) C++ FE is confused about the COMDAT groups being right. */ if (cpp_implicit_aliases_done) FOR_EACH_SYMBOL (node) - if (node->symbol.cpp_implicit_alias) + if (node->cpp_implicit_alias) fixup_same_cpp_alias_visibility (node, symtab_alias_target (node)); if (optimize && flag_devirtualize) build_type_inheritance_graph (); @@ -947,8 +950,8 @@ analyze_functions (void) /* First identify the trivially needed symbols. */ for (node = symtab_nodes; - node != (symtab_node)first_analyzed - && node != (symtab_node)first_analyzed_var; node = node->symbol.next) + node != first_analyzed + && node != first_analyzed_var; node = node->next) { if (decide_is_symbol_needed (node)) { @@ -961,8 +964,8 @@ analyze_functions (void) if (!changed && cgraph_dump_file) fprintf (cgraph_dump_file, "\n"); } - if (node == (symtab_node)first_analyzed - || node == (symtab_node)first_analyzed_var) + if (node == first_analyzed + || node == first_analyzed_var) break; } cgraph_process_new_functions (); @@ -974,22 +977,22 @@ analyze_functions (void) /* Lower representation, build callgraph edges and references for all trivially needed symbols and all symbols referred by them. */ - while (first != (symtab_node)(void *)1) + while (first != (symtab_node *)(void *)1) { changed = true; node = first; - first = (symtab_node)first->symbol.aux; + first = (symtab_node *)first->aux; cgraph_node *cnode = dyn_cast <cgraph_node> (node); - if (cnode && cnode->symbol.definition) + if (cnode && cnode->definition) { struct cgraph_edge *edge; - tree decl = cnode->symbol.decl; + tree decl = cnode->decl; /* ??? It is possible to create extern inline function and later using weak alias attribute to kill its body. See gcc.c-torture/compile/20011119-1.c */ if (!DECL_STRUCT_FUNCTION (decl) - && !cnode->symbol.alias + && !cnode->alias && !cnode->thunk.thunk_p && !cnode->dispatcher_function) { @@ -998,12 +1001,12 @@ analyze_functions (void) continue; } - if (!cnode->symbol.analyzed) + if (!cnode->analyzed) analyze_function (cnode); for (edge = cnode->callees; edge; edge = edge->next_callee) - if (edge->callee->symbol.definition) - enqueue_node ((symtab_node)edge->callee); + if (edge->callee->definition) + enqueue_node (edge->callee); if (optimize && flag_devirtualize) { struct cgraph_edge *next; @@ -1031,20 +1034,20 @@ analyze_functions (void) else { varpool_node *vnode = dyn_cast <varpool_node> (node); - if (vnode && vnode->symbol.definition && !vnode->symbol.analyzed) + if (vnode && vnode->definition && !vnode->analyzed) varpool_analyze_node (vnode); } - if (node->symbol.same_comdat_group) + if (node->same_comdat_group) { - symtab_node next; - for (next = node->symbol.same_comdat_group; + symtab_node *next; + for (next = node->same_comdat_group; next != node; - next = next->symbol.same_comdat_group) + next = next->same_comdat_group) enqueue_node (next); } - for (i = 0; ipa_ref_list_reference_iterate (&node->symbol.ref_list, i, ref); i++) - if (ref->referred->symbol.definition) + for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list, i, ref); i++) + if (ref->referred->definition) enqueue_node (ref->referred); cgraph_process_new_functions (); } @@ -1063,11 +1066,11 @@ analyze_functions (void) fprintf (cgraph_dump_file, "\nRemoving unused symbols:"); for (node = symtab_nodes; - node != (symtab_node)first_handled - && node != (symtab_node)first_handled_var; node = next) + node != first_handled + && node != first_handled_var; node = next) { - next = node->symbol.next; - if (!node->symbol.aux && !referred_to_p (node)) + next = node->next; + if (!node->aux && !referred_to_p (node)) { if (cgraph_dump_file) fprintf (cgraph_dump_file, " %s", symtab_node_name (node)); @@ -1076,22 +1079,22 @@ analyze_functions (void) } if (cgraph_node *cnode = dyn_cast <cgraph_node> (node)) { - tree decl = node->symbol.decl; + tree decl = node->decl; - if (cnode->symbol.definition && !gimple_has_body_p (decl) - && !cnode->symbol.alias + if (cnode->definition && !gimple_has_body_p (decl) + && !cnode->alias && !cnode->thunk.thunk_p) cgraph_reset_node (cnode); - gcc_assert (!cnode->symbol.definition || cnode->thunk.thunk_p - || cnode->symbol.alias + gcc_assert (!cnode->definition || cnode->thunk.thunk_p + || cnode->alias || gimple_has_body_p (decl)); - gcc_assert (cnode->symbol.analyzed == cnode->symbol.definition); + gcc_assert (cnode->analyzed == cnode->definition); } - node->symbol.aux = NULL; + node->aux = NULL; } - for (;node; node = node->symbol.next) - node->symbol.aux = NULL; + for (;node; node = node->next) + node->aux = NULL; first_analyzed = cgraph_first_function (); first_analyzed_var = varpool_first_variable (); if (cgraph_dump_file) @@ -1123,7 +1126,7 @@ handle_alias_pairs (void) for (i = 0; alias_pairs && alias_pairs->iterate (i, &p);) { - symtab_node target_node = symtab_node_for_asm (p->target); + symtab_node *target_node = symtab_node_for_asm (p->target); /* Weakrefs with target not defined in current unit are easy to handle: they behave just as external variables except we need to note the @@ -1131,12 +1134,12 @@ handle_alias_pairs (void) if (!target_node && lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl)) != NULL) { - symtab_node node = symtab_get_node (p->decl); + symtab_node *node = symtab_get_node (p->decl); if (node) { - node->symbol.alias_target = p->target; - node->symbol.weakref = true; - node->symbol.alias = true; + node->alias_target = p->target; + node->weakref = true; + node->alias = true; } alias_pairs->unordered_remove (i); continue; @@ -1144,19 +1147,19 @@ handle_alias_pairs (void) else if (!target_node) { error ("%q+D aliased to undefined symbol %qE", p->decl, p->target); - symtab_node node = symtab_get_node (p->decl); + symtab_node *node = symtab_get_node (p->decl); if (node) - node->symbol.alias = false; + node->alias = false; alias_pairs->unordered_remove (i); continue; } - if (DECL_EXTERNAL (target_node->symbol.decl) + if (DECL_EXTERNAL (target_node->decl) /* We use local aliases for C++ thunks to force the tailcall to bind locally. This is a hack - to keep it working do the following (which is not strictly correct). */ - && (! TREE_CODE (target_node->symbol.decl) == FUNCTION_DECL - || ! DECL_VIRTUAL_P (target_node->symbol.decl)) + && (! TREE_CODE (target_node->decl) == FUNCTION_DECL + || ! DECL_VIRTUAL_P (target_node->decl)) && ! lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl))) { error ("%q+D aliased to external symbol %qE", @@ -1167,15 +1170,15 @@ handle_alias_pairs (void) && target_node && is_a <cgraph_node> (target_node)) { struct cgraph_node *src_node = cgraph_get_node (p->decl); - if (src_node && src_node->symbol.definition) + if (src_node && src_node->definition) cgraph_reset_node (src_node); - cgraph_create_function_alias (p->decl, target_node->symbol.decl); + cgraph_create_function_alias (p->decl, target_node->decl); alias_pairs->unordered_remove (i); } else if (TREE_CODE (p->decl) == VAR_DECL && target_node && is_a <varpool_node> (target_node)) { - varpool_create_variable_alias (p->decl, target_node->symbol.decl); + varpool_create_variable_alias (p->decl, target_node->decl); alias_pairs->unordered_remove (i); } else @@ -1183,7 +1186,7 @@ handle_alias_pairs (void) error ("%q+D alias in between function and variable is not supported", p->decl); warning (0, "%q+D aliased declaration", - target_node->symbol.decl); + target_node->decl); alias_pairs->unordered_remove (i); } } @@ -1206,34 +1209,34 @@ mark_functions_to_output (void) FOR_EACH_FUNCTION (node) { - tree decl = node->symbol.decl; + tree decl = node->decl; - gcc_assert (!node->process || node->symbol.same_comdat_group); + gcc_assert (!node->process || node->same_comdat_group); if (node->process) continue; /* We need to output all local functions that are used and not always inlined, as well as those that are reachable from outside the current compilation unit. */ - if (node->symbol.analyzed + if (node->analyzed && !node->thunk.thunk_p - && !node->symbol.alias + && !node->alias && !node->global.inlined_to && !TREE_ASM_WRITTEN (decl) && !DECL_EXTERNAL (decl)) { node->process = 1; - if (node->symbol.same_comdat_group) + if (node->same_comdat_group) { struct cgraph_node *next; - for (next = cgraph (node->symbol.same_comdat_group); + for (next = cgraph (node->same_comdat_group); next != node; - next = cgraph (next->symbol.same_comdat_group)) - if (!next->thunk.thunk_p && !next->symbol.alias) + next = cgraph (next->same_comdat_group)) + if (!next->thunk.thunk_p && !next->alias) next->process = 1; } } - else if (node->symbol.same_comdat_group) + else if (node->same_comdat_group) { #ifdef ENABLE_CHECKING check_same_comdat_groups = true; @@ -1248,8 +1251,8 @@ mark_functions_to_output (void) /* FIXME: in ltrans unit when offline copy is outside partition but inline copies are inside partition, we can end up not removing the body since we no longer have analyzed node pointing to it. */ - && !node->symbol.in_other_partition - && !node->symbol.alias + && !node->in_other_partition + && !node->alias && !node->clones && !DECL_EXTERNAL (decl)) { @@ -1259,7 +1262,7 @@ mark_functions_to_output (void) #endif gcc_assert (node->global.inlined_to || !gimple_has_body_p (decl) - || node->symbol.in_other_partition + || node->in_other_partition || node->clones || DECL_ARTIFICIAL (decl) || DECL_EXTERNAL (decl)); @@ -1270,16 +1273,16 @@ mark_functions_to_output (void) #ifdef ENABLE_CHECKING if (check_same_comdat_groups) FOR_EACH_FUNCTION (node) - if (node->symbol.same_comdat_group && !node->process) + if (node->same_comdat_group && !node->process) { - tree decl = node->symbol.decl; + tree decl = node->decl; if (!node->global.inlined_to && gimple_has_body_p (decl) /* FIXME: in an ltrans unit when the offline copy is outside a partition but inline copies are inside a partition, we can end up not removing the body since we no longer have an analyzed node pointing to it. */ - && !node->symbol.in_other_partition + && !node->in_other_partition && !node->clones && !DECL_EXTERNAL (decl)) { @@ -1449,8 +1452,8 @@ expand_thunk (struct cgraph_node *node, bool output_asm_thunks) HOST_WIDE_INT fixed_offset = node->thunk.fixed_offset; HOST_WIDE_INT virtual_value = node->thunk.virtual_value; tree virtual_offset = NULL; - tree alias = node->callees->callee->symbol.decl; - tree thunk_fndecl = node->symbol.decl; + tree alias = node->callees->callee->decl; + tree thunk_fndecl = node->decl; tree a; @@ -1502,7 +1505,7 @@ expand_thunk (struct cgraph_node *node, bool output_asm_thunks) set_cfun (NULL); TREE_ASM_WRITTEN (thunk_fndecl) = 1; node->thunk.thunk_p = false; - node->symbol.analyzed = false; + node->analyzed = false; } else { @@ -1688,20 +1691,20 @@ assemble_thunks_and_aliases (struct cgraph_node *node) } else e = e->next_caller; - for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list, + for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list, i, ref); i++) if (ref->use == IPA_REF_ALIAS) { struct cgraph_node *alias = ipa_ref_referring_node (ref); - bool saved_written = TREE_ASM_WRITTEN (node->symbol.decl); + bool saved_written = TREE_ASM_WRITTEN (node->decl); /* Force assemble_alias to really output the alias this time instead of buffering it in same alias pairs. */ - TREE_ASM_WRITTEN (node->symbol.decl) = 1; - do_assemble_alias (alias->symbol.decl, - DECL_ASSEMBLER_NAME (node->symbol.decl)); + TREE_ASM_WRITTEN (node->decl) = 1; + do_assemble_alias (alias->decl, + DECL_ASSEMBLER_NAME (node->decl)); assemble_thunks_and_aliases (alias); - TREE_ASM_WRITTEN (node->symbol.decl) = saved_written; + TREE_ASM_WRITTEN (node->decl) = saved_written; } } @@ -1710,7 +1713,7 @@ assemble_thunks_and_aliases (struct cgraph_node *node) static void expand_function (struct cgraph_node *node) { - tree decl = node->symbol.decl; + tree decl = node->decl; location_t saved_loc; /* We ought to not compile any inline clones. */ @@ -1815,7 +1818,7 @@ expand_function (struct cgraph_node *node) /* Eliminate all call edges. This is important so the GIMPLE_CALL no longer points to the dead function body. */ cgraph_node_remove_callees (node); - ipa_remove_all_references (&node->symbol.ref_list); + ipa_remove_all_references (&node->ref_list); } @@ -1903,9 +1906,9 @@ output_in_order (void) FOR_EACH_DEFINED_FUNCTION (pf) { - if (pf->process && !pf->thunk.thunk_p && !pf->symbol.alias) + if (pf->process && !pf->thunk.thunk_p && !pf->alias) { - i = pf->symbol.order; + i = pf->order; gcc_assert (nodes[i].kind == ORDER_UNDEFINED); nodes[i].kind = ORDER_FUNCTION; nodes[i].u.f = pf; @@ -1913,9 +1916,9 @@ output_in_order (void) } FOR_EACH_DEFINED_VARIABLE (pv) - if (!DECL_EXTERNAL (pv->symbol.decl)) + if (!DECL_EXTERNAL (pv->decl)) { - i = pv->symbol.order; + i = pv->order; gcc_assert (nodes[i].kind == ORDER_UNDEFINED); nodes[i].kind = ORDER_VAR; nodes[i].u.v = pv; @@ -2046,11 +2049,11 @@ get_alias_symbol (tree decl) static void output_weakrefs (void) { - symtab_node node; + symtab_node *node; FOR_EACH_SYMBOL (node) - if (node->symbol.alias - && !TREE_ASM_WRITTEN (node->symbol.decl) - && node->symbol.weakref) + if (node->alias + && !TREE_ASM_WRITTEN (node->decl) + && node->weakref) { tree target; @@ -2059,18 +2062,18 @@ output_weakrefs (void) alias. When alias target is defined, we need to fetch it from symtab reference, otherwise it is pointed to by alias_target. */ - if (node->symbol.alias_target) - target = (DECL_P (node->symbol.alias_target) - ? DECL_ASSEMBLER_NAME (node->symbol.alias_target) - : node->symbol.alias_target); - else if (node->symbol.analyzed) - target = DECL_ASSEMBLER_NAME (symtab_alias_target (node)->symbol.decl); + if (node->alias_target) + target = (DECL_P (node->alias_target) + ? DECL_ASSEMBLER_NAME (node->alias_target) + : node->alias_target); + else if (node->analyzed) + target = DECL_ASSEMBLER_NAME (symtab_alias_target (node)->decl); else { gcc_unreachable (); - target = get_alias_symbol (node->symbol.decl); + target = get_alias_symbol (node->decl); } - do_assemble_alias (node->symbol.decl, target); + do_assemble_alias (node->decl, target); } } @@ -2168,17 +2171,17 @@ compile (void) level by physically rewritting the IL. At the moment we can only redirect calls, so we need infrastructure for renaming references as well. */ #ifndef ASM_OUTPUT_WEAKREF - symtab_node node; + symtab_node *node; FOR_EACH_SYMBOL (node) - if (node->symbol.alias - && lookup_attribute ("weakref", DECL_ATTRIBUTES (node->symbol.decl))) + if (node->alias + && lookup_attribute ("weakref", DECL_ATTRIBUTES (node->decl))) { IDENTIFIER_TRANSPARENT_ALIAS - (DECL_ASSEMBLER_NAME (node->symbol.decl)) = 1; - TREE_CHAIN (DECL_ASSEMBLER_NAME (node->symbol.decl)) - = (node->symbol.alias_target ? node->symbol.alias_target - : DECL_ASSEMBLER_NAME (symtab_alias_target (node)->symbol.decl)); + (DECL_ASSEMBLER_NAME (node->decl)) = 1; + TREE_CHAIN (DECL_ASSEMBLER_NAME (node->decl)) + = (node->alias_target ? node->alias_target + : DECL_ASSEMBLER_NAME (symtab_alias_target (node)->decl)); } #endif @@ -2213,7 +2216,7 @@ compile (void) FOR_EACH_DEFINED_FUNCTION (node) if (node->global.inlined_to - || gimple_has_body_p (node->symbol.decl)) + || gimple_has_body_p (node->decl)) { error_found = true; dump_cgraph_node (stderr, node); diff --git a/gcc/chkp-builtins.def b/gcc/chkp-builtins.def new file mode 100644 index 00000000000..d19b5418a36 --- /dev/null +++ b/gcc/chkp-builtins.def @@ -0,0 +1,73 @@ +/* This file contains the definitions and documentation for the + builtins used in the GNU compiler. + Copyright (C) 2013 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +/* Before including this file, you should define macros: + + DEF_BUILTIN_STUB(ENUM, NAME) + DEF_CHKP_BUILTIN(ENUM, NAME, TYPE, ATTRS) + + See builtins.def for details. */ + +/* Following builtins are used by compiler for Pointer Bounds Checker + instrumentation. Currently these generic builtins are not + implemented and target has to provide his own version. See + builtin_chkp_function target hook documentation for more details. */ +DEF_BUILTIN_STUB (BUILT_IN_CHKP_BNDMK, "__chkp_bndmk") +DEF_BUILTIN_STUB (BUILT_IN_CHKP_BNDSTX, "__chkp_bndstx") +DEF_BUILTIN_STUB (BUILT_IN_CHKP_BNDCL, "__chkp_bndcl") +DEF_BUILTIN_STUB (BUILT_IN_CHKP_BNDCU, "__chkp_bndcu") +DEF_BUILTIN_STUB (BUILT_IN_CHKP_BNDLDX, "__chkp_bndldx") +DEF_BUILTIN_STUB (BUILT_IN_CHKP_BNDRET, "__chkp_bndret") +DEF_BUILTIN_STUB (BUILT_IN_CHKP_INTERSECT, "__chkp_intersect") +DEF_BUILTIN_STUB (BUILT_IN_CHKP_ARG_BND, "__chkp_arg_bnd") +DEF_BUILTIN_STUB (BUILT_IN_CHKP_SIZEOF, "__chkp_sizeof") +DEF_BUILTIN_STUB (BUILT_IN_CHKP_EXTRACT_LOWER, "__chkp_extract_lower") +DEF_BUILTIN_STUB (BUILT_IN_CHKP_EXTRACT_UPPER, "__chkp_extract_upper") +DEF_BUILTIN_STUB (BUILT_IN_CHKP_NARROW, "__chkp_narrow") + +/* Pointer Bounds Checker builtins for users. Only + BUILT_IN_CHKP_SET_PTR_BOUNDS may be redefined + by target. Other builtins calls are expanded + in the Pointer Bounds Checker pass. */ +DEF_CHKP_BUILTIN (BUILT_IN_CHKP_SET_PTR_BOUNDS, "__bnd_set_ptr_bounds", BT_FN_PTR_CONST_PTR_SIZE, ATTR_CONST_NOTHROW_LEAF_LIST) +DEF_CHKP_BUILTIN (BUILT_IN_CHKP_INIT_PTR_BOUNDS, "__bnd_init_ptr_bounds", BT_FN_PTR_CONST_PTR, ATTR_CONST_NOTHROW_LEAF_LIST) +DEF_CHKP_BUILTIN (BUILT_IN_CHKP_NULL_PTR_BOUNDS, "__bnd_null_ptr_bounds", BT_FN_PTR_CONST_PTR, ATTR_CONST_NOTHROW_LEAF_LIST) +DEF_CHKP_BUILTIN (BUILT_IN_CHKP_COPY_PTR_BOUNDS, "__bnd_copy_ptr_bounds", BT_FN_PTR_CONST_PTR_CONST_PTR, ATTR_CONST_NOTHROW_LEAF_LIST) +DEF_CHKP_BUILTIN (BUILT_IN_CHKP_NARROW_PTR_BOUNDS, "__bnd_narrow_ptr_bounds", BT_FN_PTR_CONST_PTR_CONST_PTR_SIZE, ATTR_CONST_NOTHROW_LEAF_LIST) +DEF_CHKP_BUILTIN (BUILT_IN_CHKP_STORE_PTR_BOUNDS, "__bnd_store_ptr_bounds", BT_FN_VOID_PTRPTR_CONST_PTR, ATTR_NOTHROW_LEAF_LIST) +DEF_CHKP_BUILTIN (BUILT_IN_CHKP_CHECK_PTR_LBOUNDS, "__bnd_chk_ptr_lbounds", BT_FN_VOID_CONST_PTR, ATTR_NOTHROW_LEAF_LIST) +DEF_CHKP_BUILTIN (BUILT_IN_CHKP_CHECK_PTR_UBOUNDS, "__bnd_chk_ptr_ubounds", BT_FN_VOID_CONST_PTR, ATTR_NOTHROW_LEAF_LIST) +DEF_CHKP_BUILTIN (BUILT_IN_CHKP_CHECK_PTR_BOUNDS, "__bnd_chk_ptr_bounds", BT_FN_VOID_CONST_PTR_SIZE, ATTR_NOTHROW_LEAF_LIST) +DEF_CHKP_BUILTIN (BUILT_IN_CHKP_GET_PTR_LBOUND, "__bnd_get_ptr_lbound", BT_FN_CONST_PTR_CONST_PTR, ATTR_CONST_NOTHROW_LEAF_LIST) +DEF_CHKP_BUILTIN (BUILT_IN_CHKP_GET_PTR_UBOUND, "__bnd_get_ptr_ubound", BT_FN_CONST_PTR_CONST_PTR, ATTR_CONST_NOTHROW_LEAF_LIST) + +/* Pointer Bounds Checker specific versions of string functions. */ +DEF_CHKP_BUILTIN (BUILT_IN_CHKP_MEMCPY_NOBND, "chkp_memcpy_nobnd", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_RET1_NOTHROW_NONNULL_LEAF) +DEF_CHKP_BUILTIN (BUILT_IN_CHKP_MEMCPY_NOCHK, "chkp_memcpy_nochk", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_RET1_NOTHROW_NONNULL_LEAF) +DEF_CHKP_BUILTIN (BUILT_IN_CHKP_MEMCPY_NOBND_NOCHK, "chkp_memcpy_nobnd_nochk", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_RET1_NOTHROW_NONNULL_LEAF) +DEF_CHKP_BUILTIN (BUILT_IN_CHKP_MEMMOVE_NOBND, "chkp_memmove_nobnd", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_RET1_NOTHROW_NONNULL_LEAF) +DEF_CHKP_BUILTIN (BUILT_IN_CHKP_MEMMOVE_NOCHK, "chkp_memmove_nochk", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_RET1_NOTHROW_NONNULL_LEAF) +DEF_CHKP_BUILTIN (BUILT_IN_CHKP_MEMMOVE_NOBND_NOCHK, "chkp_memmove_nobnd_nochk", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_RET1_NOTHROW_NONNULL_LEAF) +DEF_CHKP_BUILTIN (BUILT_IN_CHKP_MEMPCPY_NOBND, "chkp_mempcpy_nobnd", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_NOTHROW_NONNULL_LEAF) +DEF_CHKP_BUILTIN (BUILT_IN_CHKP_MEMPCPY_NOCHK, "chkp_mempcpy_nochk", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_NOTHROW_NONNULL_LEAF) +DEF_CHKP_BUILTIN (BUILT_IN_CHKP_MEMPCPY_NOBND_NOCHK, "chkp_mempcpy_nobnd_nochk", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_NOTHROW_NONNULL_LEAF) +DEF_CHKP_BUILTIN (BUILT_IN_CHKP_MEMSET_NOBND, "chkp_memset_nobnd", BT_FN_PTR_PTR_INT_SIZE, ATTR_RET1_NOTHROW_NONNULL_LEAF) +DEF_CHKP_BUILTIN (BUILT_IN_CHKP_MEMSET_NOCHK, "chkp_memset_nochk", BT_FN_PTR_PTR_INT_SIZE, ATTR_RET1_NOTHROW_NONNULL_LEAF) +DEF_CHKP_BUILTIN (BUILT_IN_CHKP_MEMSET_NOBND_NOCHK, "chkp_memset_nobnd_nochk", BT_FN_PTR_PTR_INT_SIZE, ATTR_RET1_NOTHROW_NONNULL_LEAF) diff --git a/gcc/cilk-builtins.def b/gcc/cilk-builtins.def new file mode 100644 index 00000000000..8634194d722 --- /dev/null +++ b/gcc/cilk-builtins.def @@ -0,0 +1,33 @@ +/* This file contains the definitions and documentation for the + Cilk Plus builtins used in the GNU compiler. + Copyright (C) 2013 Free Software Foundation, Inc. + + Contributed by Balaji V. Iyer <balaji.v.iyer@intel.com> + Intel Corporation. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 3, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +DEF_CILK_BUILTIN_STUB (BUILT_IN_CILK_ENTER_FRAME, "__cilkrts_enter_frame_1") +DEF_CILK_BUILTIN_STUB (BUILT_IN_CILK_ENTER_FRAME_FAST, + "__cilkrts_enter_frame_fast_1") +DEF_CILK_BUILTIN_STUB (BUILT_IN_CILK_DETACH, "__cilkrts_detach") +DEF_CILK_BUILTIN_STUB (BUILT_IN_CILK_RETHROW, "__cilkrts_rethrow") +DEF_CILK_BUILTIN_STUB (BUILT_IN_CILK_SYNCHED, "__cilkrts_synched") +DEF_CILK_BUILTIN_STUB (BUILT_IN_CILK_SYNC, "__cilkrts_sync") +DEF_CILK_BUILTIN_STUB (BUILT_IN_CILK_LEAVE_FRAME, "__cilkrts_leave_frame") +DEF_CILK_BUILTIN_STUB (BUILT_IN_CILK_POP_FRAME, "__cilkrts_pop_frame") +DEF_CILK_BUILTIN_STUB (BUILT_IN_CILK_SAVE_FP, "__cilkrts_save_fp_ctrl_state") diff --git a/gcc/cilk-common.c b/gcc/cilk-common.c new file mode 100644 index 00000000000..9be864d5a7e --- /dev/null +++ b/gcc/cilk-common.c @@ -0,0 +1,484 @@ +/* This file is part of the Intel(R) Cilk(TM) Plus support + This file contains the CilkPlus Intrinsics + Copyright (C) 2013 Free Software Foundation, Inc. + Contributed by Balaji V. Iyer <balaji.v.iyer@intel.com>, + Intel Corporation + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tree.h" +#include "langhooks.h" +#include "expr.h" +#include "optabs.h" +#include "recog.h" +#include "tree-iterator.h" +#include "gimple.h" +#include "cilk.h" + +/* This structure holds all the important fields of the internal structures, + internal built-in functions, and Cilk-specific data types. Explanation of + all the these fielsd are given in cilk.h. */ +tree cilk_trees[(int) CILK_TI_MAX]; + +/* Returns the value in structure FRAME pointed by the FIELD_NUMBER + (e.g. X.y). + FIELD_NUMBER is an index to the structure FRAME_PTR. For details + about these fields, refer to cilk_trees structure in cilk.h and + cilk_init_builtins function in this file. Returns a TREE that is the type + of the field represented by FIELD_NUMBER. If VOLATIL parameter is set + to true then the returning field is set as volatile. */ + +tree +cilk_dot (tree frame, int field_number, bool volatil) +{ + tree field = cilk_trees[field_number]; + field = fold_build3 (COMPONENT_REF, TREE_TYPE (field), frame, field, + NULL_TREE); + TREE_THIS_VOLATILE (field) = volatil; + return field; +} + +/* Returns the address of a field in FRAME_PTR, pointed by FIELD_NUMBER. + (e.g. (&X)->y). Please see cilk_dot function for explanation of the + FIELD_NUMBER. Returns a tree that is the type of the field represented + by FIELD_NUMBER. If VOLATIL parameter is set to true then the returning + field is set as volatile. */ + +tree +cilk_arrow (tree frame_ptr, int field_number, bool volatil) +{ + return cilk_dot (fold_build1 (INDIRECT_REF, + TREE_TYPE (TREE_TYPE (frame_ptr)), frame_ptr), + field_number, volatil); +} + + +/* This function will add FIELD of type TYPE to a defined built-in + structure. *NAME is the name of the field to be added. */ + +static tree +add_field (const char *name, tree type, tree fields) +{ + tree t = get_identifier (name); + tree field = build_decl (BUILTINS_LOCATION, FIELD_DECL, t, type); + TREE_CHAIN (field) = fields; + return field; +} + +/* This function will define a built-in function of NAME, of type FNTYPE and + register it under the built-in function code CODE. If PUBLISH is set then + the declaration is pushed into the declaration list. CODE is the index + to the cilk_trees array. *NAME is the name of the function to be added. */ + +static tree +install_builtin (const char *name, tree fntype, enum built_in_function code, + bool publish) +{ + tree fndecl = build_fn_decl (name, fntype); + DECL_BUILT_IN_CLASS (fndecl) = BUILT_IN_NORMAL; + DECL_FUNCTION_CODE (fndecl) = code; + if (publish) + { + tree t = lang_hooks.decls.pushdecl (fndecl); + if (t) + fndecl = t; + } + set_builtin_decl (code, fndecl, true); + return fndecl; +} + +/* Creates and initializes all the built-in Cilk keywords functions and three + structures: __cilkrts_stack_frame, __cilkrts_pedigree and __cilkrts_worker. + Detailed information about __cilkrts_stack_frame and + __cilkrts_worker structures are given in libcilkrts/include/internal/abi.h. + __cilkrts_pedigree is described in libcilkrts/include/cilk/common.h. */ + +void +cilk_init_builtins (void) +{ + /* Now build the following __cilkrts_pedigree struct: + struct __cilkrts_pedigree { + uint64_t rank; + struct __cilkrts_pedigree *parent; + } */ + + tree pedigree_type = lang_hooks.types.make_type (RECORD_TYPE); + tree pedigree_ptr = build_pointer_type (pedigree_type); + tree field = add_field ("rank", uint64_type_node, NULL_TREE); + cilk_trees[CILK_TI_PEDIGREE_RANK] = field; + field = add_field ("parent", pedigree_ptr, field); + cilk_trees[CILK_TI_PEDIGREE_PARENT] = field; + finish_builtin_struct (pedigree_type, "__cilkrts_pedigree_GCC", field, + NULL_TREE); + lang_hooks.types.register_builtin_type (pedigree_type, + "__cilkrts_pedigree_t"); + cilk_pedigree_type_decl = pedigree_type; + + /* Build the Cilk Stack Frame: + struct __cilkrts_stack_frame { + uint32_t flags; + uint32_t size; + struct __cilkrts_stack_frame *call_parent; + __cilkrts_worker *worker; + void *except_data; + void *ctx[4]; + uint32_t mxcsr; + uint16_t fpcsr; + uint16_t reserved; + __cilkrts_pedigree pedigree; + }; */ + + tree frame = lang_hooks.types.make_type (RECORD_TYPE); + tree frame_ptr = build_pointer_type (frame); + tree worker_type = lang_hooks.types.make_type (RECORD_TYPE); + tree worker_ptr = build_pointer_type (worker_type); + tree s_type_node = build_int_cst (size_type_node, 4); + + tree flags = add_field ("flags", uint32_type_node, NULL_TREE); + tree size = add_field ("size", uint32_type_node, flags); + tree parent = add_field ("call_parent", frame_ptr, size); + tree worker = add_field ("worker", worker_ptr, parent); + tree except = add_field ("except_data", frame_ptr, worker); + tree context = add_field ("ctx", + build_array_type (ptr_type_node, + build_index_type (s_type_node)), + except); + tree mxcsr = add_field ("mxcsr", uint32_type_node, context); + tree fpcsr = add_field ("fpcsr", uint16_type_node, mxcsr); + tree reserved = add_field ("reserved", uint16_type_node, fpcsr); + tree pedigree = add_field ("pedigree", pedigree_type, reserved); + + /* Now add them to a common structure whose fields are #defined to something + that is used at a later stage. */ + cilk_trees[CILK_TI_FRAME_FLAGS] = flags; + cilk_trees[CILK_TI_FRAME_PARENT] = parent; + cilk_trees[CILK_TI_FRAME_WORKER] = worker; + cilk_trees[CILK_TI_FRAME_EXCEPTION] = except; + cilk_trees[CILK_TI_FRAME_CONTEXT] = context; + /* We don't care about reserved, so no need to store it in cilk_trees. */ + cilk_trees[CILK_TI_FRAME_PEDIGREE] = pedigree; + TREE_ADDRESSABLE (frame) = 1; + + finish_builtin_struct (frame, "__cilkrts_st_frame_GCC", pedigree, NULL_TREE); + cilk_frame_type_decl = frame; + lang_hooks.types.register_builtin_type (frame, "__cilkrts_frame_t"); + + cilk_frame_ptr_type_decl = build_qualified_type (frame_ptr, + TYPE_QUAL_VOLATILE); + /* Now let's do the following worker struct: + + struct __cilkrts_worker { + __cilkrts_stack_frame *volatile *volatile tail; + __cilkrts_stack_frame *volatile *volatile head; + __cilkrts_stack_frame *volatile *volatile exc; + __cilkrts_stack_frame *volatile *volatile protected_tail; + __cilkrts_stack_frame *volatile *ltq_limit; + int32_t self; + global_state_t *g; + local_state *l; + cilkred_map *reducer_map; + __cilkrts_stack_frame *current_stack_frame; + void *reserved; + __cilkrts_worker_sysdep_state *sysdep; + __cilkrts_pedigree pedigree; + } */ + + tree fptr_volatil_type = build_qualified_type (frame_ptr, TYPE_QUAL_VOLATILE); + tree fptr_volatile_ptr = build_pointer_type (fptr_volatil_type); + tree fptr_vol_ptr_vol = build_qualified_type (fptr_volatile_ptr, + TYPE_QUAL_VOLATILE); + tree g = lang_hooks.types.make_type (RECORD_TYPE); + finish_builtin_struct (g, "__cilkrts_global_state", NULL_TREE, NULL_TREE); + tree l = lang_hooks.types.make_type (RECORD_TYPE); + finish_builtin_struct (l, "__cilkrts_local_state", NULL_TREE, NULL_TREE); + tree sysdep_t = lang_hooks.types.make_type (RECORD_TYPE); + finish_builtin_struct (sysdep_t, "__cilkrts_worker_sysdep_state", NULL_TREE, + NULL_TREE); + + field = add_field ("tail", fptr_vol_ptr_vol, NULL_TREE); + cilk_trees[CILK_TI_WORKER_TAIL] = field; + field = add_field ("head", fptr_vol_ptr_vol, field); + field = add_field ("exc", fptr_vol_ptr_vol, field); + field = add_field ("protected_tail", fptr_vol_ptr_vol, field); + field = add_field ("ltq_limit", fptr_volatile_ptr, field); + field = add_field ("self", integer_type_node, field); + field = add_field ("g", build_pointer_type (g), field); + field = add_field ("l", build_pointer_type (g), field); + field = add_field ("reducer_map", ptr_type_node, field); + field = add_field ("current_stack_frame", frame_ptr, field); + cilk_trees[CILK_TI_WORKER_CUR] = field; + field = add_field ("saved_protected_tail", fptr_volatile_ptr, field); + field = add_field ("sysdep", build_pointer_type (sysdep_t), field); + field = add_field ("pedigree", pedigree_type, field); + cilk_trees[CILK_TI_WORKER_PEDIGREE] = field; + finish_builtin_struct (worker_type, "__cilkrts_worker_GCC", field, + NULL_TREE); + + tree fptr_arglist = tree_cons (NULL_TREE, frame_ptr, void_list_node); + tree fptr_fun = build_function_type (void_type_node, fptr_arglist); + + /* void __cilkrts_enter_frame_1 (__cilkrts_stack_frame *); */ + cilk_enter_fndecl = install_builtin ("__cilkrts_enter_frame_1", fptr_fun, + BUILT_IN_CILK_ENTER_FRAME, false); + + /* void __cilkrts_enter_frame_fast_1 (__cilkrts_stack_frame *); */ + cilk_enter_fast_fndecl = + install_builtin ("__cilkrts_enter_frame_fast_1", fptr_fun, + BUILT_IN_CILK_ENTER_FRAME_FAST, false); + + /* void __cilkrts_pop_frame (__cilkrts_stack_frame *); */ + cilk_pop_fndecl = install_builtin ("__cilkrts_pop_frame", fptr_fun, + BUILT_IN_CILK_POP_FRAME, false); + + /* void __cilkrts_leave_frame (__cilkrts_stack_frame *); */ + cilk_leave_fndecl = install_builtin ("__cilkrts_leave_frame", fptr_fun, + BUILT_IN_CILK_LEAVE_FRAME, false); + + /* void __cilkrts_sync (__cilkrts_stack_frame *); */ + cilk_sync_fndecl = install_builtin ("__cilkrts_sync", fptr_fun, + BUILT_IN_CILK_SYNC, false); + + /* void __cilkrts_detach (__cilkrts_stack_frame *); */ + cilk_detach_fndecl = install_builtin ("__cilkrts_detach", fptr_fun, + BUILT_IN_CILK_DETACH, false); + + /* __cilkrts_rethrow (struct stack_frame *); */ + cilk_rethrow_fndecl = install_builtin ("__cilkrts_rethrow", fptr_fun, + BUILT_IN_CILK_RETHROW, false); + + /* __cilkrts_save_fp_ctrl_state (__cilkrts_stack_frame *); */ + cilk_save_fp_fndecl = install_builtin ("__cilkrts_save_fp_ctrl_state", + fptr_fun, BUILT_IN_CILK_SAVE_FP, + false); +} + +/* Get the appropriate frame arguments for CALL that is of type CALL_EXPR. */ + +static tree +get_frame_arg (tree call) +{ + tree arg, argtype; + + gcc_assert (call_expr_nargs (call) >= 1); + + arg = CALL_EXPR_ARG (call, 0); + argtype = TREE_TYPE (arg); + gcc_assert (TREE_CODE (argtype) == POINTER_TYPE); + + argtype = TREE_TYPE (argtype); + + gcc_assert (!lang_hooks.types_compatible_p + || lang_hooks.types_compatible_p (argtype, cilk_frame_type_decl)); + + /* If it is passed in as an address, then just use the value directly + since the function is inlined. */ + if (TREE_CODE (arg) == INDIRECT_REF || TREE_CODE (arg) == ADDR_EXPR) + return TREE_OPERAND (arg, 0); + return arg; +} + +/* Expands the __cilkrts_pop_frame function call stored in EXP. */ + +void +expand_builtin_cilk_pop_frame (tree exp) +{ + tree frame = get_frame_arg (exp); + tree parent = cilk_dot (frame, CILK_TI_FRAME_PARENT, 0); + + tree clear_parent = build2 (MODIFY_EXPR, void_type_node, parent, + build_int_cst (TREE_TYPE (parent), 0)); + expand_expr (clear_parent, const0_rtx, VOIDmode, EXPAND_NORMAL); + + /* During LTO, the is_cilk_function flag gets cleared. + If __cilkrts_pop_frame is called, then this definitely must be a + cilk function. */ + if (cfun) + cfun->is_cilk_function = 1; +} + +/* Expands the cilk_detach function call stored in EXP. */ + +void +expand_builtin_cilk_detach (tree exp) +{ + rtx insn; + tree fptr = get_frame_arg (exp); + + if (fptr == NULL_TREE) + return; + + tree parent = cilk_dot (fptr, CILK_TI_FRAME_PARENT, 0); + tree worker = cilk_dot (fptr, CILK_TI_FRAME_WORKER, 0); + tree tail = cilk_dot (worker, CILK_TI_WORKER_TAIL, 1); + + rtx wreg = expand_expr (worker, NULL_RTX, Pmode, EXPAND_NORMAL); + if (GET_CODE (wreg) != REG) + wreg = copy_to_reg (wreg); + rtx preg = expand_expr (parent, NULL_RTX, Pmode, EXPAND_NORMAL); + + /* TMP <- WORKER.TAIL + *TMP <- PARENT + TMP <- TMP + 1 + WORKER.TAIL <- TMP */ + + HOST_WIDE_INT worker_tail_offset = + tree_to_shwi (DECL_FIELD_OFFSET (cilk_trees[CILK_TI_WORKER_TAIL])) + + tree_to_shwi (DECL_FIELD_BIT_OFFSET (cilk_trees[CILK_TI_WORKER_TAIL])) / + BITS_PER_UNIT; + rtx tmem0 = gen_rtx_MEM (Pmode, + plus_constant (Pmode, wreg, worker_tail_offset)); + set_mem_attributes (tmem0, tail, 0); + MEM_NOTRAP_P (tmem0) = 1; + gcc_assert (MEM_VOLATILE_P (tmem0)); + rtx treg = copy_to_mode_reg (Pmode, tmem0); + rtx tmem1 = gen_rtx_MEM (Pmode, treg); + set_mem_attributes (tmem1, TREE_TYPE (TREE_TYPE (tail)), 0); + MEM_NOTRAP_P (tmem1) = 1; + emit_move_insn (tmem1, preg); + emit_move_insn (treg, plus_constant (Pmode, treg, GET_MODE_SIZE (Pmode))); + + /* There is a release barrier (st8.rel, membar #StoreStore, + sfence, lwsync, etc.) between the two stores. On x86 + normal volatile stores have proper semantics; the sfence + would only be needed for nontemporal stores (which we + could generate using the storent optab, for no benefit + in this case). + + The predicate may return false even for a REG if this is + the limited release operation that only stores 0. */ + enum insn_code icode = direct_optab_handler (sync_lock_release_optab, Pmode); + if (icode != CODE_FOR_nothing + && insn_data[icode].operand[1].predicate (treg, Pmode) + && (insn = GEN_FCN (icode) (tmem0, treg)) != NULL_RTX) + emit_insn (insn); + else + emit_move_insn (tmem0, treg); + + /* The memory barrier inserted above should not prevent + the load of flags from being moved before the stores, + but in practice it does because it is implemented with + unspec_volatile. In-order RISC machines should + explicitly load flags earlier. */ + + tree flags = cilk_dot (fptr, CILK_TI_FRAME_FLAGS, 0); + expand_expr (build2 (MODIFY_EXPR, void_type_node, flags, + build2 (BIT_IOR_EXPR, TREE_TYPE (flags), flags, + build_int_cst (TREE_TYPE (flags), + CILK_FRAME_DETACHED))), + const0_rtx, VOIDmode, EXPAND_NORMAL); +} + +/* Returns a setjmp CALL_EXPR with FRAME->context as its parameter. */ + +tree +cilk_call_setjmp (tree frame) +{ + tree c = cilk_dot (frame, CILK_TI_FRAME_CONTEXT, false); + c = build1 (ADDR_EXPR, build_pointer_type (ptr_type_node), c); + return build_call_expr (builtin_decl_implicit (BUILT_IN_SETJMP), 1, c); +} + +/* This function will expand the _Cilk_sync keyword. */ + +static tree +expand_cilk_sync (void) +{ + tree frame = cfun->cilk_frame_decl; + + /* Cilk_sync is converted to the following code: + + sf.pedigree = sf.worker->pedigree; + if (frame.flags & CILK_FRAME_UNSYNCHED) + { + __cilkrts_save_fp_state (&sf); + if (!builtin_setjmp (sf.ctx) + __cilkrts_sync (&sf); + else + if (sf.flags & CILK_FRAME_EXCEPTING) + __cilkrts_rethrow (&sf); + } + sf.worker->pedigree.rank = sf.worker->pedigree.rank + 1; */ + + tree flags = cilk_dot (frame, CILK_TI_FRAME_FLAGS, false); + + tree unsynched = fold_build2 (BIT_AND_EXPR, TREE_TYPE (flags), flags, + build_int_cst (TREE_TYPE (flags), + CILK_FRAME_UNSYNCHED)); + + unsynched = fold_build2 (NE_EXPR, TREE_TYPE (unsynched), unsynched, + build_int_cst (TREE_TYPE (unsynched), 0)); + + tree frame_addr = build1 (ADDR_EXPR, cilk_frame_ptr_type_decl, frame); + + /* Check if exception (0x10) bit is set in the sf->flags. */ + tree except_flag = fold_build2 (BIT_AND_EXPR, TREE_TYPE (flags), flags, + build_int_cst (TREE_TYPE (flags), + CILK_FRAME_EXCEPTING)); + except_flag = fold_build2 (NE_EXPR, TREE_TYPE (except_flag), except_flag, + build_int_cst (TREE_TYPE (except_flag), 0)); + + /* If the exception flag is set then call the __cilkrts_rethrow (&sf). */ + tree except_cond = fold_build3 (COND_EXPR, void_type_node, except_flag, + build_call_expr (cilk_rethrow_fndecl, 1, + frame_addr), + build_empty_stmt (EXPR_LOCATION (unsynched))); + + tree sync_expr = build_call_expr (cilk_sync_fndecl, 1, frame_addr); + tree setjmp_expr = cilk_call_setjmp (frame); + setjmp_expr = fold_build2 (EQ_EXPR, TREE_TYPE (setjmp_expr), setjmp_expr, + build_int_cst (TREE_TYPE (setjmp_expr), 0)); + + setjmp_expr = fold_build3 (COND_EXPR, void_type_node, setjmp_expr, + sync_expr, except_cond); + tree sync_list = alloc_stmt_list (); + append_to_statement_list (build_call_expr (cilk_save_fp_fndecl, 1, + frame_addr), &sync_list); + append_to_statement_list (setjmp_expr, &sync_list); + tree sync = fold_build3 (COND_EXPR, void_type_node, unsynched, sync_list, + build_empty_stmt (EXPR_LOCATION (unsynched))); + tree parent_pedigree = cilk_dot (frame, CILK_TI_FRAME_PEDIGREE, false); + tree worker = cilk_dot (frame, CILK_TI_FRAME_WORKER, false); + tree worker_pedigree = cilk_arrow (worker, CILK_TI_WORKER_PEDIGREE, false); + tree assign_pedigree = fold_build2 (MODIFY_EXPR, void_type_node, + parent_pedigree, worker_pedigree); + tree w_ped_rank = cilk_dot (unshare_expr (worker_pedigree), + CILK_TI_PEDIGREE_RANK, false); + tree incr_ped_rank = fold_build2 (PLUS_EXPR, TREE_TYPE (w_ped_rank), + w_ped_rank, + build_one_cst (TREE_TYPE (w_ped_rank))); + incr_ped_rank = fold_build2 (MODIFY_EXPR, void_type_node, w_ped_rank, + incr_ped_rank); + tree ret_sync_exp = alloc_stmt_list (); + append_to_statement_list (assign_pedigree, &ret_sync_exp); + append_to_statement_list (sync, &ret_sync_exp); + append_to_statement_list (incr_ped_rank, &ret_sync_exp); + return ret_sync_exp; +} + +/* Gimplifies the cilk_sync expression passed in *EXPR_P. Returns GS_ALL_DONE + when finished. */ + +void +gimplify_cilk_sync (tree *expr_p, gimple_seq *pre_p) +{ + tree sync_expr = expand_cilk_sync (); + *expr_p = NULL_TREE; + gimplify_and_add (sync_expr, pre_p); +} diff --git a/gcc/cilk.h b/gcc/cilk.h new file mode 100644 index 00000000000..99b4d782af4 --- /dev/null +++ b/gcc/cilk.h @@ -0,0 +1,102 @@ +/* This file is part of the Intel(R) Cilk(TM) Plus support + This file contains Cilk Support files. + Copyright (C) 2013 Free Software Foundation, Inc. + Contributed by Balaji V. Iyer <balaji.v.iyer@intel.com>, + Intel Corporation + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GCC is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +#ifndef GCC_CILK_H +#define GCC_CILK_H + +/* Frame status bits known to compiler. */ +#define CILK_FRAME_UNSYNCHED 0x02 +#define CILK_FRAME_DETACHED 0x04 +#define CILK_FRAME_EXCEPTING 0x10 +#define CILK_FRAME_VERSION (1 << 24) + +enum cilk_tree_index { +/* All the built-in functions for Cilk keywords. */ + CILK_TI_F_WORKER = 0, /* __cilkrts_get_worker (). */ + CILK_TI_F_SYNC, /* __cilkrts_sync (). */ + CILK_TI_F_DETACH, /* __cilkrts_detach (...). */ + CILK_TI_F_ENTER, /* __cilkrts_enter_frame (...). */ + CILK_TI_F_ENTER_FAST, /* __cilkrts_enter_frame_fast (.). */ + CILK_TI_F_LEAVE, /* __cilkrts_leave_frame (...). */ + CILK_TI_F_POP, /* __cilkrts_pop_frame (...). */ + CILK_TI_F_RETHROW, /* __cilkrts_rethrow (...). */ + CILK_TI_F_SAVE_FP, /* __cilkrts_save_fp_ctrl_state (...). */ + /* __cilkrts_stack_frame struct fields. */ + CILK_TI_FRAME_FLAGS, /* stack_frame->flags. */ + CILK_TI_FRAME_PARENT, /* stack_frame->parent. */ + CILK_TI_FRAME_WORKER, /* stack_frame->worker. */ + CILK_TI_FRAME_EXCEPTION, /* stack_frame->except_data. */ + CILK_TI_FRAME_CONTEXT, /* stack_frame->context[4]. */ + CILK_TI_FRAME_PEDIGREE, /* stack_frame->pedigree. */ + + /* __cilkrts_worker struct fields. */ + CILK_TI_WORKER_CUR, /* worker->current_stack_frame. */ + CILK_TI_WORKER_TAIL, /* worker->tail. */ + CILK_TI_WORKER_PEDIGREE, /* worker->pedigree. */ + + /* __cilkrts_pedigree struct fields. */ + CILK_TI_PEDIGREE_RANK, /* pedigree->rank. */ + CILK_TI_PEDIGREE_PARENT, /* pedigree->parent. */ + + /* Types. */ + CILK_TI_FRAME_TYPE, /* struct __cilkrts_stack_frame. */ + CILK_TI_FRAME_PTR, /* __cilkrts_stack_frame *. */ + CILK_TI_WORKER_TYPE, /* struct __cilkrts_worker. */ + CILK_TI_PEDIGREE_TYPE, /* struct __cilkrts_pedigree. */ + CILK_TI_MAX +}; + +extern GTY (()) tree cilk_trees[CILK_TI_MAX]; + +#define cilk_worker_fndecl cilk_trees[CILK_TI_F_WORKER] +#define cilk_sync_fndecl cilk_trees[CILK_TI_F_SYNC] +#define cilk_synched_fndecl cilk_trees[CILK_TI_F_SYNCED] +#define cilk_detach_fndecl cilk_trees[CILK_TI_F_DETACH] +#define cilk_enter_fndecl cilk_trees[CILK_TI_F_ENTER] +#define cilk_enter_fast_fndecl cilk_trees[CILK_TI_F_ENTER_FAST] +#define cilk_leave_fndecl cilk_trees[CILK_TI_F_LEAVE] +#define cilk_rethrow_fndecl cilk_trees[CILK_TI_F_RETHROW] +#define cilk_pop_fndecl cilk_trees[CILK_TI_F_POP] +#define cilk_save_fp_fndecl cilk_trees[CILK_TI_F_SAVE_FP] + +#define cilk_worker_type_fndecl cilk_trees[CILK_TI_WORKER_TYPE] +#define cilk_frame_type_decl cilk_trees[CILK_TI_FRAME_TYPE] +#define cilk_frame_ptr_type_decl cilk_trees[CILK_TI_FRAME_PTR] +#define cilk_pedigree_type_decl cilk_trees[CILK_TI_PEDIGREE_TYPE] + +extern void expand_builtin_cilk_detach (tree); +extern void expand_builtin_cilk_pop_frame (tree); +extern tree cilk_arrow (tree, int, bool); +extern tree cilk_dot (tree, int, bool); +extern void cilk_init_builtins (void); +extern void gimplify_cilk_sync (tree *, gimple_seq *); +extern tree cilk_call_setjmp (tree); +/* Returns true if Cilk Plus is enabled and if F->cilk_frame_decl is not + NULL_TREE. */ + +inline bool +fn_contains_cilk_spawn_p (function *f) +{ + return (flag_enable_cilkplus + && (f->calls_cilk_spawn || f->cilk_frame_decl != NULL_TREE)); +} +#endif diff --git a/gcc/common.opt b/gcc/common.opt index 1f11fcd4d5d..3a40db203fa 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -874,6 +874,11 @@ fbounds-check Common Report Var(flag_bounds_check) Generate code to check bounds before indexing arrays +fcheck-pointer-bounds +Common Report Var(flag_check_pointer_bounds) +Add Pointer Bounds Checker instrumentation. fchkp-* flags are used to +control instrumentation. Currently available for C, C++ and ObjC. + fbranch-count-reg Common Report Var(flag_branch_on_count_reg) Init(1) Optimization Replace add, compare, branch with branch on count register @@ -1592,8 +1597,8 @@ Common Joined RejectNegative Var(common_deferred_options) Defer -fopt-info[-<type>=filename] Dump compiler optimization details foptimize-register-move -Common Report Var(flag_regmove) Optimization -Do the full register move optimization pass +Common Ignore +Does nothing. Preserved for backward compatibility. foptimize-sibling-calls Common Report Var(flag_optimize_sibling_calls) Optimization @@ -1730,8 +1735,8 @@ Common Report Var(flag_pcc_struct_return,0) Optimization Return small aggregates in registers fregmove -Common Report Var(flag_regmove) Optimization -Enables a register move optimization +Common Ignore +Does nothing. Preserved for backward compatibility. frename-registers Common Report Var(flag_rename_registers) Init(2) Optimization @@ -2271,8 +2276,8 @@ Common Report Var(flag_tree_vectorize) Optimization Enable vectorization on trees ftree-vectorizer-verbose= -Common RejectNegative Joined UInteger Var(common_deferred_options) Defer --ftree-vectorizer-verbose=<number> This switch is deprecated. Use -fopt-info instead. +Common Joined RejectNegative Ignore +Does nothing. Preserved for backward compatibility. ftree-loop-vectorize Common Report Var(flag_tree_loop_vectorize) Optimization @@ -2412,13 +2417,17 @@ Common JoinedOrMissing Generate debug information in default extended format gno-pubnames -Common RejectNegative Var(debug_generate_pub_sections, 0) Init(-1) +Common Negative(gpubnames) Var(debug_generate_pub_sections, 0) Init(-1) Don't generate DWARF pubnames and pubtypes sections. gpubnames -Common RejectNegative Var(debug_generate_pub_sections, 1) +Common Negative(ggnu-pubnames) Var(debug_generate_pub_sections, 1) Generate DWARF pubnames and pubtypes sections. +ggnu-pubnames +Common Negative(gno-pubnames) Var(debug_generate_pub_sections, 2) +Generate DWARF pubnames and pubtypes sections with GNU extensions. + gno-record-gcc-switches Common RejectNegative Var(dwarf_record_gcc_switches,0) Init(1) Don't record gcc command line switches in DWARF DW_AT_producer. diff --git a/gcc/common/config/m32r/m32r-common.c b/gcc/common/config/m32r/m32r-common.c index 1a0df406306..f8df5a847fd 100644 --- a/gcc/common/config/m32r/m32r-common.c +++ b/gcc/common/config/m32r/m32r-common.c @@ -29,7 +29,6 @@ static const struct default_options m32r_option_optimization_table[] = { { OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 }, - { OPT_LEVELS_1_PLUS, OPT_fregmove, NULL, 1 }, { OPT_LEVELS_NONE, 0, NULL, 0 } }; diff --git a/gcc/common/config/mmix/mmix-common.c b/gcc/common/config/mmix/mmix-common.c index ebc89480240..54acb4d892b 100644 --- a/gcc/common/config/mmix/mmix-common.c +++ b/gcc/common/config/mmix/mmix-common.c @@ -28,7 +28,6 @@ along with GCC; see the file COPYING3. If not see static const struct default_options mmix_option_optimization_table[] = { - { OPT_LEVELS_1_PLUS, OPT_fregmove, NULL, 1 }, { OPT_LEVELS_2_PLUS, OPT_fomit_frame_pointer, NULL, 1 }, { OPT_LEVELS_NONE, 0, NULL, 0 } }; diff --git a/gcc/common/config/nds32/nds32-common.c b/gcc/common/config/nds32/nds32-common.c new file mode 100644 index 00000000000..f82f725af14 --- /dev/null +++ b/gcc/common/config/nds32/nds32-common.c @@ -0,0 +1,117 @@ +/* Common hooks of Andes NDS32 cpu for GNU compiler + Copyright (C) 2012-2013 Free Software Foundation, Inc. + Contributed by Andes Technology Corporation. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GCC is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "diagnostic-core.h" +#include "tm.h" +#include "common/common-target.h" +#include "common/common-target-def.h" +#include "opts.h" +#include "flags.h" + +/* ------------------------------------------------------------------------ */ + +/* Implement TARGET_HANDLE_OPTION. */ +static bool +nds32_handle_option (struct gcc_options *opts ATTRIBUTE_UNUSED, + struct gcc_options *opts_set ATTRIBUTE_UNUSED, + const struct cl_decoded_option *decoded, + location_t loc) +{ + size_t code = decoded->opt_index; + int value = decoded->value; + + switch (code) + { + case OPT_misr_vector_size_: + /* Check the valid vector size: 4 or 16. */ + if (value != 4 && value != 16) + { + error_at (loc, "for the option -misr-vector-size=X, the valid X " + "must be: 4 or 16"); + return false; + } + + return true; + + case OPT_mcache_block_size_: + /* Check valid value: 4 8 16 32 64 128 256 512. */ + if (exact_log2 (value) < 2 || exact_log2 (value) > 9) + { + error_at (loc, "for the option -mcache-block-size=X, the valid X " + "must be: 4, 8, 16, 32, 64, 128, 256, or 512"); + return false; + } + + return true; + + default: + return true; + } +} + +/* ------------------------------------------------------------------------ */ + +/* Implement TARGET_OPTION_OPTIMIZATION_TABLE. */ +static const struct default_options nds32_option_optimization_table[] = +{ + /* Enable -fomit-frame-pointer by default at -O1 or higher. */ + { OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 }, + /* Enable -mv3push by default at -Os, but it is useless under V2 ISA. */ + { OPT_LEVELS_SIZE, OPT_mv3push, NULL, 1 }, + + { OPT_LEVELS_NONE, 0, NULL, 0 } +}; + +/* ------------------------------------------------------------------------ */ + +/* Run-time Target Specification. */ + +/* Default enable + TARGET_GP_DIRECT: Generate gp-imply instruction. + TARGET_16_BIT : Generate 16/32 bit mixed length instruction. + TARGET_PERF_EXT : Generate performance extention instrcution. + TARGET_CMOV : Generate conditional move instruction. */ +#undef TARGET_DEFAULT_TARGET_FLAGS +#define TARGET_DEFAULT_TARGET_FLAGS \ + (MASK_GP_DIRECT \ + | MASK_16_BIT \ + | MASK_PERF_EXT \ + | MASK_CMOV) + +#undef TARGET_HANDLE_OPTION +#define TARGET_HANDLE_OPTION nds32_handle_option + +#undef TARGET_OPTION_OPTIMIZATION_TABLE +#define TARGET_OPTION_OPTIMIZATION_TABLE nds32_option_optimization_table + + +/* Defining the Output Assembler Language. */ + +#undef TARGET_EXCEPT_UNWIND_INFO +#define TARGET_EXCEPT_UNWIND_INFO sjlj_except_unwind_info + +/* ------------------------------------------------------------------------ */ + +struct gcc_targetm_common targetm_common = TARGETM_COMMON_INITIALIZER; + +/* ------------------------------------------------------------------------ */ diff --git a/gcc/config.gcc b/gcc/config.gcc index 022701df53f..6c62a64d25d 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -421,6 +421,10 @@ mips*-*-*) extra_headers="loongson.h" extra_options="${extra_options} g.opt mips/mips-tables.opt" ;; +nds32*) + cpu_type=nds32 + extra_headers="nds32_intrinsic.h" + ;; picochip-*-*) cpu_type=picochip ;; @@ -465,7 +469,7 @@ sh[123456789lbe]*-*-* | sh-*-*) cpu_type=sh need_64bit_hwint=yes extra_options="${extra_options} fused-madd.opt" - extra_objs="${extra_objs} sh_treg_combine.o" + extra_objs="${extra_objs} sh_treg_combine.o sh-mem.o" ;; v850*-*-*) cpu_type=v850 @@ -2091,6 +2095,18 @@ msp430*-*-*) target_has_targetm_common=no tmake_file="${tmake_file} msp430/t-msp430" ;; +nds32le-*-*) + target_cpu_default="0" + tm_defines="${tm_defines}" + tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file}" + tmake_file="nds32/t-mlibs" + ;; +nds32be-*-*) + target_cpu_default="0|MASK_BIG_ENDIAN" + tm_defines="${tm_defines} TARGET_BIG_ENDIAN_DEFAULT=1" + tm_file="dbxelf.h elfos.h newlib-stdint.h ${tm_file}" + tmake_file="nds32/t-mlibs" + ;; pdp11-*-*) tm_file="${tm_file} newlib-stdint.h" use_gcc_stdint=wrap @@ -2198,6 +2214,7 @@ powerpc*-*-linux*) tm_file="${tm_file} dbxelf.h elfos.h freebsd-spec.h rs6000/sysv4.h" extra_options="${extra_options} rs6000/sysv4.opt" tmake_file="rs6000/t-fprules rs6000/t-ppcos ${tmake_file} rs6000/t-ppccomm" + extra_objs="$extra_objs rs6000-linux.o" case ${target} in powerpc*le-*-*) tm_file="${tm_file} rs6000/sysv4le.h" ;; @@ -3754,6 +3771,39 @@ case "${target}" in esac ;; + nds32*-*-*) + supported_defaults="arch nds32_lib" + + # process --with-arch + case "${with_arch}" in + "" | v2 | v3 | v3m) + # OK + ;; + *) + echo "Cannot accept --with-arch=$with_arch, available values are: v2 v3 v3m" 1>&2 + exit 1 + ;; + esac + + # process --with-nds32-lib + case "${with_nds32_lib}" in + "") + # the default library is newlib + with_nds32_lib=newlib + ;; + newlib) + # OK + ;; + mculib) + # OK + ;; + *) + echo "Cannot accept --with-nds32-lib=$with_nds32_lib, available values are: newlib mculib" 1>&2 + exit 1 + ;; + esac + ;; + powerpc*-*-* | rs6000-*-*) supported_defaults="cpu cpu_32 cpu_64 float tune tune_32 tune_64" diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 33db421c964..704e872fc61 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -4263,6 +4263,24 @@ aarch64_preferred_reload_class (rtx x, reg_class_t regclass) && !aarch64_simd_imm_scalar_p (x, GET_MODE (x))) return NO_REGS; + /* Register eliminiation can result in a request for + SP+constant->FP_REGS. We cannot support such operations which + use SP as source and an FP_REG as destination, so reject out + right now. */ + if (! reg_class_subset_p (regclass, GENERAL_REGS) && GET_CODE (x) == PLUS) + { + rtx lhs = XEXP (x, 0); + + /* Look through a possible SUBREG introduced by ILP32. */ + if (GET_CODE (lhs) == SUBREG) + lhs = SUBREG_REG (lhs); + + gcc_assert (REG_P (lhs)); + gcc_assert (reg_class_subset_p (REGNO_REG_CLASS (REGNO (lhs)), + POINTER_REGS)); + return NO_REGS; + } + return regclass; } diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c index 83f92ebb7a9..6ddd48634c8 100644 --- a/gcc/config/arc/arc.c +++ b/gcc/config/arc/arc.c @@ -3711,12 +3711,18 @@ arc_ccfsm_record_condition (rtx cond, bool reverse, rtx jump, static void arc_ccfsm_post_advance (rtx insn, struct arc_ccfsm *state) { + enum attr_type type; + if (LABEL_P (insn)) arc_ccfsm_at_label ("L", CODE_LABEL_NUMBER (insn), state); else if (JUMP_P (insn) && GET_CODE (PATTERN (insn)) != ADDR_VEC && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC - && get_attr_type (insn) == TYPE_BRANCH) + && ((type = get_attr_type (insn)) == TYPE_BRANCH + || (type == TYPE_UNCOND_BRANCH + /* ??? Maybe should also handle TYPE_RETURN here, + but we don't have a testcase for that. */ + && ARC_CCFSM_BRANCH_DELETED_P (state)))) { if (ARC_CCFSM_BRANCH_DELETED_P (state)) ARC_CCFSM_RECORD_BRANCH_DELETED (state); @@ -8120,6 +8126,7 @@ arc_ifcvt (void) basic_block succ_bb = BLOCK_FOR_INSN (NEXT_INSN (NEXT_INSN (PREV_INSN (insn)))); arc_ccfsm_post_advance (insn, statep); + gcc_assert (!IN_RANGE (statep->state, 1, 2)); rtx seq = NEXT_INSN (PREV_INSN (insn)); if (seq != insn) { diff --git a/gcc/config/arm/arm-cores.def b/gcc/config/arm/arm-cores.def index 17c9bf3255a..79e2e87b72b 100644 --- a/gcc/config/arm/arm-cores.def +++ b/gcc/config/arm/arm-cores.def @@ -125,7 +125,7 @@ ARM_CORE("arm1156t2-s", arm1156t2s, 6T2, FL_LDSCHED, v6t2) ARM_CORE("arm1156t2f-s", arm1156t2fs, 6T2, FL_LDSCHED | FL_VFPV2, v6t2) ARM_CORE("generic-armv7-a", genericv7a, 7A, FL_LDSCHED, cortex) ARM_CORE("cortex-a5", cortexa5, 7A, FL_LDSCHED, cortex_a5) -ARM_CORE("cortex-a7", cortexa7, 7A, FL_LDSCHED | FL_THUMB_DIV | FL_ARM_DIV, cortex) +ARM_CORE("cortex-a7", cortexa7, 7A, FL_LDSCHED | FL_THUMB_DIV | FL_ARM_DIV, cortex_a7) ARM_CORE("cortex-a8", cortexa8, 7A, FL_LDSCHED, cortex) ARM_CORE("cortex-a9", cortexa9, 7A, FL_LDSCHED, cortex_a9) ARM_CORE("cortex-a15", cortexa15, 7A, FL_LDSCHED | FL_THUMB_DIV | FL_ARM_DIV, cortex_a15) diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 843fe97d5f8..0b79023e706 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -1076,18 +1076,18 @@ const struct cpu_cost_table cortexa9_extra_costs = { COSTS_N_INSNS (3), /* Simple. */ COSTS_N_INSNS (3), /* Flag_setting. */ - COSTS_N_INSNS (4), /* Extend. */ + COSTS_N_INSNS (2), /* Extend. */ COSTS_N_INSNS (3), /* Add. */ - COSTS_N_INSNS (4), /* Extend_add. */ + COSTS_N_INSNS (2), /* Extend_add. */ COSTS_N_INSNS (30) /* Idiv. No HW div on Cortex A9. */ }, /* MULT DImode */ { 0, /* Simple (N/A). */ 0, /* Flag_setting (N/A). */ - 0, /* Extend (N/A). */ + COSTS_N_INSNS (4), /* Extend. */ 0, /* Add (N/A). */ - 0, /* Extend_add (N/A). */ + COSTS_N_INSNS (4), /* Extend_add. */ 0 /* Idiv (N/A). */ } }, @@ -1152,6 +1152,107 @@ const struct cpu_cost_table cortexa9_extra_costs = }; +const struct cpu_cost_table cortexa7_extra_costs = +{ + /* ALU */ + { + 0, /* Arith. */ + 0, /* Logical. */ + COSTS_N_INSNS (1), /* Shift. */ + COSTS_N_INSNS (1), /* Shift_reg. */ + COSTS_N_INSNS (1), /* Arith_shift. */ + COSTS_N_INSNS (1), /* Arith_shift_reg. */ + COSTS_N_INSNS (1), /* Log_shift. */ + COSTS_N_INSNS (1), /* Log_shift_reg. */ + COSTS_N_INSNS (1), /* Extend. */ + COSTS_N_INSNS (1), /* Extend_arith. */ + COSTS_N_INSNS (1), /* Bfi. */ + COSTS_N_INSNS (1), /* Bfx. */ + COSTS_N_INSNS (1), /* Clz. */ + 0, /* non_exec. */ + true /* non_exec_costs_exec. */ + }, + + { + /* MULT SImode */ + { + 0, /* Simple. */ + COSTS_N_INSNS (1), /* Flag_setting. */ + COSTS_N_INSNS (1), /* Extend. */ + COSTS_N_INSNS (1), /* Add. */ + COSTS_N_INSNS (1), /* Extend_add. */ + COSTS_N_INSNS (7) /* Idiv. */ + }, + /* MULT DImode */ + { + 0, /* Simple (N/A). */ + 0, /* Flag_setting (N/A). */ + COSTS_N_INSNS (1), /* Extend. */ + 0, /* Add. */ + COSTS_N_INSNS (2), /* Extend_add. */ + 0 /* Idiv (N/A). */ + } + }, + /* LD/ST */ + { + COSTS_N_INSNS (1), /* Load. */ + COSTS_N_INSNS (1), /* Load_sign_extend. */ + COSTS_N_INSNS (3), /* Ldrd. */ + COSTS_N_INSNS (1), /* Ldm_1st. */ + 1, /* Ldm_regs_per_insn_1st. */ + 2, /* Ldm_regs_per_insn_subsequent. */ + COSTS_N_INSNS (2), /* Loadf. */ + COSTS_N_INSNS (2), /* Loadd. */ + COSTS_N_INSNS (1), /* Load_unaligned. */ + COSTS_N_INSNS (1), /* Store. */ + COSTS_N_INSNS (3), /* Strd. */ + COSTS_N_INSNS (1), /* Stm_1st. */ + 1, /* Stm_regs_per_insn_1st. */ + 2, /* Stm_regs_per_insn_subsequent. */ + COSTS_N_INSNS (2), /* Storef. */ + COSTS_N_INSNS (2), /* Stored. */ + COSTS_N_INSNS (1) /* Store_unaligned. */ + }, + { + /* FP SFmode */ + { + COSTS_N_INSNS (15), /* Div. */ + COSTS_N_INSNS (3), /* Mult. */ + COSTS_N_INSNS (7), /* Mult_addsub. */ + COSTS_N_INSNS (7), /* Fma. */ + COSTS_N_INSNS (3), /* Addsub. */ + COSTS_N_INSNS (3), /* Fpconst. */ + COSTS_N_INSNS (3), /* Neg. */ + COSTS_N_INSNS (3), /* Compare. */ + COSTS_N_INSNS (3), /* Widen. */ + COSTS_N_INSNS (3), /* Narrow. */ + COSTS_N_INSNS (3), /* Toint. */ + COSTS_N_INSNS (3), /* Fromint. */ + COSTS_N_INSNS (3) /* Roundint. */ + }, + /* FP DFmode */ + { + COSTS_N_INSNS (30), /* Div. */ + COSTS_N_INSNS (6), /* Mult. */ + COSTS_N_INSNS (10), /* Mult_addsub. */ + COSTS_N_INSNS (7), /* Fma. */ + COSTS_N_INSNS (3), /* Addsub. */ + COSTS_N_INSNS (3), /* Fpconst. */ + COSTS_N_INSNS (3), /* Neg. */ + COSTS_N_INSNS (3), /* Compare. */ + COSTS_N_INSNS (3), /* Widen. */ + COSTS_N_INSNS (3), /* Narrow. */ + COSTS_N_INSNS (3), /* Toint. */ + COSTS_N_INSNS (3), /* Fromint. */ + COSTS_N_INSNS (3) /* Roundint. */ + } + }, + /* Vector */ + { + COSTS_N_INSNS (1) /* Alu. */ + } +}; + const struct cpu_cost_table cortexa15_extra_costs = { /* ALU */ @@ -1368,6 +1469,22 @@ const struct tune_params arm_cortex_tune = false /* Prefer Neon for 64-bits bitops. */ }; +const struct tune_params arm_cortex_a7_tune = +{ + arm_9e_rtx_costs, + &cortexa7_extra_costs, + NULL, + 1, /* Constant limit. */ + 5, /* Max cond insns. */ + ARM_PREFETCH_NOT_BENEFICIAL, + false, /* Prefer constant pool. */ + arm_default_branch_cost, + false, /* Prefer LDRD/STRD. */ + {true, true}, /* Prefer non short circuit. */ + &arm_default_vec_cost, /* Vectorizer costs. */ + false /* Prefer Neon for 64-bits bitops. */ +}; + const struct tune_params arm_cortex_a15_tune = { arm_9e_rtx_costs, @@ -26424,6 +26541,7 @@ arm_expand_epilogue_apcs_frame (bool really_return) num_regs = bit_count (saved_regs_mask); if ((offsets->outgoing_args != (1 + num_regs)) || cfun->calls_alloca) { + emit_insn (gen_blockage ()); /* Unwind the stack to just below the saved registers. */ emit_insn (gen_addsi3 (stack_pointer_rtx, hard_frame_pointer_rtx, diff --git a/gcc/config/avr/avr-log.c b/gcc/config/avr/avr-log.c index 8a631bb1fef..87fa14d7006 100644 --- a/gcc/config/avr/avr-log.c +++ b/gcc/config/avr/avr-log.c @@ -49,8 +49,6 @@ C: enum rtx_code m: enum machine_mode R: enum reg_class - D: double_int (signed decimal) - X: double_int (unsigned hex) L: insn list H: location_t @@ -138,44 +136,6 @@ avr_log_set_caller_f (const char *caller) } -/* Copy-paste from double-int.c:double_int_split_digit (it's static there). - Splits last digit of *CST (taken as unsigned) in BASE and returns it. */ - -static unsigned -avr_wide_int_pop_digit (wide_int *cst, unsigned base) -{ - wide_int wrem; - - *cst = cst->udivmod_floor (base, &wrem); - - return (unsigned) wrem.to_uhwi(); -} - - -/* Dump VAL as hex value to FILE. */ - -static void -avr_dump_wide_int_hex (FILE *file, const wide_int &val) -{ - unsigned digit[4]; - - digit[0] = avr_wide_int_pop_digit (&val, 1 << 16); - digit[1] = avr_wide_int_pop_digit (&val, 1 << 16); - digit[2] = avr_wide_int_pop_digit (&val, 1 << 16); - digit[3] = avr_wide_int_pop_digit (&val, 1 << 16); - - fprintf (file, "0x"); - - if (digit[3] | digit[2]) - fprintf (file, "%04x%04x", digit[3], digit[2]); - - if (digit[3] | digit[2] | digit[1] | digit[0]) - fprintf (file, "%04x%04x", digit[1], digit[0]); - else - fprintf (file, "0"); -} - - /* Worker function implementing the %-codes and forwarding to respective print/dump function. */ @@ -230,14 +190,6 @@ avr_log_vadump (FILE *file, const char *fmt, va_list ap) fprintf (file, "%d", va_arg (ap, int)); break; - case 'D': - dump_double_int (file, va_arg (ap, double_int), false); - break; - - case 'X': - avr_dump_double_int_hex (file, va_arg (ap, double_int)); - break; - case 'x': fprintf (file, "%x", va_arg (ap, int)); break; diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c index 6a2750994f5..f0def13ae8f 100644 --- a/gcc/config/avr/avr.c +++ b/gcc/config/avr/avr.c @@ -11365,26 +11365,12 @@ avr_expand_delay_cycles (rtx operands0) } -/* Return VAL * BASE + DIGIT. BASE = 0 is shortcut for BASE = 2^{32} */ - -static wide_int -avr_wide_int_push_digit (const wide_int &val, int base, - unsigned HOST_WIDE_INT digit) -{ - val = 0 == base - ? val.llshift (32) - : val * base; - - return val + digit; -} - - /* Compute the image of x under f, i.e. perform x --> f(x) */ static int -avr_map (const wide_int &f, int x) +avr_map (unsigned int f, int x) { - return 0xf & f.lrshift (4*x).to_uhwi (); + return x < 8 ? (f >> (4 * x)) & 0xf : 0; } @@ -11409,7 +11395,7 @@ enum }; static unsigned -avr_map_metric (const wide_int &a, int mode) +avr_map_metric (unsigned int a, int mode) { unsigned i, metric = 0; @@ -11442,7 +11428,8 @@ avr_map_metric (const wide_int &a, int mode) bool avr_has_nibble_0xf (rtx ival) { - return 0 != avr_map_metric (wide_int::from_rtx (ival), MAP_MASK_PREIMAGE_F); + unsigned int map = UINTVAL (ival) & GET_MODE_MASK (SImode); + return 0 != avr_map_metric (map, MAP_MASK_PREIMAGE_F); } @@ -11476,7 +11463,7 @@ typedef struct int cost; /* The composition F o G^-1 (*, arg) for some function F */ - wide_int map; + unsigned int map; /* For debug purpose only */ const char *str; @@ -11484,21 +11471,21 @@ typedef struct static const avr_map_op_t avr_map_op[] = { - { LROTATE_EXPR, 0, 0x76543210, 0, { 0, 0 }, "id" }, - { LROTATE_EXPR, 1, 0x07654321, 2, { 0, 0 }, "<<<" }, - { LROTATE_EXPR, 2, 0x10765432, 4, { 0, 0 }, "<<<" }, - { LROTATE_EXPR, 3, 0x21076543, 4, { 0, 0 }, "<<<" }, - { LROTATE_EXPR, 4, 0x32107654, 1, { 0, 0 }, "<<<" }, - { LROTATE_EXPR, 5, 0x43210765, 3, { 0, 0 }, "<<<" }, - { LROTATE_EXPR, 6, 0x54321076, 5, { 0, 0 }, "<<<" }, - { LROTATE_EXPR, 7, 0x65432107, 3, { 0, 0 }, "<<<" }, - { RSHIFT_EXPR, 1, 0x6543210c, 1, { 0, 0 }, ">>" }, - { RSHIFT_EXPR, 1, 0x7543210c, 1, { 0, 0 }, ">>" }, - { RSHIFT_EXPR, 2, 0x543210cc, 2, { 0, 0 }, ">>" }, - { RSHIFT_EXPR, 2, 0x643210cc, 2, { 0, 0 }, ">>" }, - { RSHIFT_EXPR, 2, 0x743210cc, 2, { 0, 0 }, ">>" }, - { LSHIFT_EXPR, 1, 0xc7654321, 1, { 0, 0 }, "<<" }, - { LSHIFT_EXPR, 2, 0xcc765432, 2, { 0, 0 }, "<<" } + { LROTATE_EXPR, 0, 0x76543210, 0, 0, "id" }, + { LROTATE_EXPR, 1, 0x07654321, 2, 0, "<<<" }, + { LROTATE_EXPR, 2, 0x10765432, 4, 0, "<<<" }, + { LROTATE_EXPR, 3, 0x21076543, 4, 0, "<<<" }, + { LROTATE_EXPR, 4, 0x32107654, 1, 0, "<<<" }, + { LROTATE_EXPR, 5, 0x43210765, 3, 0, "<<<" }, + { LROTATE_EXPR, 6, 0x54321076, 5, 0, "<<<" }, + { LROTATE_EXPR, 7, 0x65432107, 3, 0, "<<<" }, + { RSHIFT_EXPR, 1, 0x6543210c, 1, 0, ">>" }, + { RSHIFT_EXPR, 1, 0x7543210c, 1, 0, ">>" }, + { RSHIFT_EXPR, 2, 0x543210cc, 2, 0, ">>" }, + { RSHIFT_EXPR, 2, 0x643210cc, 2, 0, ">>" }, + { RSHIFT_EXPR, 2, 0x743210cc, 2, 0, ">>" }, + { LSHIFT_EXPR, 1, 0xc7654321, 1, 0, "<<" }, + { LSHIFT_EXPR, 2, 0xcc765432, 2, 0, "<<" } }; @@ -11507,12 +11494,12 @@ static const avr_map_op_t avr_map_op[] = If result.cost < 0 then such a decomposition does not exist. */ static avr_map_op_t -avr_map_decompose (const wide_int &f, const avr_map_op_t *g, bool val_const_p) +avr_map_decompose (unsigned int f, const avr_map_op_t *g, bool val_const_p) { int i; bool val_used_p = 0 != avr_map_metric (f, MAP_MASK_PREIMAGE_F); avr_map_op_t f_ginv = *g; - wide_int ginv = wide_int::from_uhwi (g->ginv); + unsigned int ginv = g->ginv; f_ginv.cost = -1; @@ -11532,7 +11519,7 @@ avr_map_decompose (const wide_int &f, const avr_map_op_t *g, bool val_const_p) return f_ginv; } - f_ginv.map = avr_wide_int_push_digit (f_ginv.map, 16, x); + f_ginv.map = (f_ginv.map << 4) + x; } /* Step 2: Compute the cost of the operations. @@ -11557,7 +11544,7 @@ avr_map_decompose (const wide_int &f, const avr_map_op_t *g, bool val_const_p) are mapped to 0 and used operands are reloaded to xop[0]. */ xop[0] = all_regs_rtx[24]; - xop[1] = gen_int_mode (f_ginv.map.to_uhwi (), SImode); + xop[1] = gen_int_mode (f_ginv.map, SImode); xop[2] = all_regs_rtx[25]; xop[3] = val_used_p ? xop[0] : const0_rtx; @@ -11584,7 +11571,7 @@ avr_map_decompose (const wide_int &f, const avr_map_op_t *g, bool val_const_p) is different to its source position. */ static void -avr_move_bits (rtx *xop, const wide_int &map, bool fixp_p, int *plen) +avr_move_bits (rtx *xop, unsigned int map, bool fixp_p, int *plen) { int bit_dest, b; @@ -11637,7 +11624,7 @@ avr_move_bits (rtx *xop, const wide_int &map, bool fixp_p, int *plen) const char* avr_out_insert_bits (rtx *op, int *plen) { - wide_int map = wide_int::from_rtx (op[1]); + unsigned int map = UINTVAL (op[1]) & GET_MODE_MASK (SImode); unsigned mask_fixed; bool fixp_p = true; rtx xop[4]; @@ -11651,9 +11638,7 @@ avr_out_insert_bits (rtx *op, int *plen) if (plen) *plen = 0; else if (flag_print_asm_name) - fprintf (asm_out_file, - ASM_COMMENT_START "map = 0x%08" HOST_LONG_FORMAT "x\n", - map.to_uhwi () & GET_MODE_MASK (SImode)); + fprintf (asm_out_file, ASM_COMMENT_START "map = 0x%08x\n", map); /* If MAP has fixed points it might be better to initialize the result with the bits to be inserted instead of moving all bits by hand. */ @@ -12228,6 +12213,7 @@ avr_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED, tree *arg, tree tval = arg[2]; tree tmap; tree map_type = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl))); + unsigned int map; bool changed = false; unsigned i; avr_map_op_t best_g; @@ -12240,8 +12226,8 @@ avr_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED, tree *arg, break; } - wide_int map = wide_int::from_tree (arg[0]); - tmap = wide_int_to_tree (map_type, map); + tmap = wide_int_to_tree (map_type, widest_int (arg[0])); + map = TREE_INT_CST_LOW (tmap); if (TREE_CODE (tval) != INTEGER_CST && 0 == avr_map_metric (map, MAP_MASK_PREIMAGE_F)) @@ -12307,7 +12293,7 @@ avr_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED, tree *arg, /* Try to decomposing map to reduce overall cost. */ if (avr_log.builtin) - avr_edump ("\n%?: %X\n%?: ROL cost: ", map); + avr_edump ("\n%?: %x\n%?: ROL cost: ", map); best_g = avr_map_op[0]; best_g.cost = 1000; @@ -12332,7 +12318,7 @@ avr_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED, tree *arg, /* Apply operation G to the 2nd argument. */ if (avr_log.builtin) - avr_edump ("%?: using OP(%s%d, %X) cost %d\n", + avr_edump ("%?: using OP(%s%d, %x) cost %d\n", best_g.str, best_g.arg, best_g.map, best_g.cost); /* Do right-shifts arithmetically: They copy the MSB instead of @@ -12345,7 +12331,8 @@ avr_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED, tree *arg, /* Use map o G^-1 instead of original map to undo the effect of G. */ - tmap = wide_int_to_tree (map_type, best_g.map); + tmap = wide_int_to_tree (map_type, + widest_int (best_g.map)); return build_call_expr (fndecl, 3, tmap, tbits, tval); } /* AVR_BUILTIN_INSERT_BITS */ diff --git a/gcc/config/bfin/bfin-modes.def b/gcc/config/bfin/bfin-modes.def index cf03a1a7e0d..da0303c8446 100644 --- a/gcc/config/bfin/bfin-modes.def +++ b/gcc/config/bfin/bfin-modes.def @@ -19,7 +19,7 @@ <http://www.gnu.org/licenses/>. */ /* PDImode for the 40-bit accumulators. */ -PARTIAL_INT_MODE (DI); +PARTIAL_INT_MODE (DI, 40, PDI); /* Two of those - covering both accumulators for vector multiplications. */ VECTOR_MODE (INT, PDI, 2); diff --git a/gcc/config/bfin/uclinux.h b/gcc/config/bfin/uclinux.h index 63cba99cec6..848515c1bbc 100644 --- a/gcc/config/bfin/uclinux.h +++ b/gcc/config/bfin/uclinux.h @@ -32,14 +32,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see %{mfast-fp:-lbffastfp} %G %L %{mfast-fp:-lbffastfp} %G \ " -/* Like the definition in gcc.c, but for purposes of uClinux, every link is - static. */ -#define MFWRAP_SPEC " %{fmudflap|fmudflapth: \ - --wrap=malloc --wrap=free --wrap=calloc --wrap=realloc\ - --wrap=mmap --wrap=munmap --wrap=alloca\ - %{fmudflapth: --wrap=pthread_create\ -}} %{fmudflap|fmudflapth: --wrap=main}" - #undef TARGET_SUPPORTS_SYNC_CALLS #define TARGET_SUPPORTS_SYNC_CALLS 1 diff --git a/gcc/config/cris/cris.c b/gcc/config/cris/cris.c index a9117d76611..7432251b950 100644 --- a/gcc/config/cris/cris.c +++ b/gcc/config/cris/cris.c @@ -1989,17 +1989,14 @@ cris_emit_trap_for_misalignment (rtx mem) /* This will yield a btstq without a separate register used, usually - with the exception for PRE hoisting the "and" but not the branch - around the trap: see gcc.dg/target/cris/sync-3s.c. */ + around the trap: see testsuite/gcc.target/cris/sync-3s.c. */ andop = gen_rtx_AND (Pmode, reg, GEN_INT (natural_alignment - 1)); emit_cmp_and_jump_insns (force_reg (SImode, andop), const0_rtx, EQ, NULL_RTX, Pmode, 1, ok_label); jmp = get_last_insn (); gcc_assert (JUMP_P (jmp)); - /* While this isn't mudflap, it is a similar kind of assertion. - If PRED_MUDFLAP stops working, use something else or introduce a - more suitable assertion predication type. */ - predict_insn_def (jmp, PRED_MUDFLAP, TAKEN); + predict_insn_def (jmp, PRED_NORETURN, TAKEN); expand_builtin_trap (); emit_label (ok_label); } diff --git a/gcc/config/darwin.c b/gcc/config/darwin.c index 8d7c3cede89..661795dc9f0 100644 --- a/gcc/config/darwin.c +++ b/gcc/config/darwin.c @@ -45,6 +45,7 @@ along with GCC; see the file COPYING3. If not see #include "df.h" #include "debug.h" #include "obstack.h" +#include "gimple.h" #include "lto-streamer.h" /* Darwin supports a feature called fix-and-continue, which is used diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md index 92e0c053fac..7289ae493b0 100644 --- a/gcc/config/i386/constraints.md +++ b/gcc/config/i386/constraints.md @@ -18,7 +18,7 @@ ;; <http://www.gnu.org/licenses/>. ;;; Unused letters: -;;; B H T +;;; H ;;; h j ;; Integer register constraints. @@ -91,6 +91,9 @@ (define_register_constraint "x" "TARGET_SSE ? SSE_REGS : NO_REGS" "Any SSE register.") +(define_register_constraint "B" "TARGET_MPX ? BND_REGS : NO_REGS" + "@internal Any bound register.") + ;; We use the Y prefix to denote any number of conditional register sets: ;; z First SSE register. ;; i SSE2 inter-unit moves to SSE register enabled @@ -232,3 +235,25 @@ to fit that range (for immediate operands in zero-extending x86-64 instructions)." (match_operand 0 "x86_64_zext_immediate_operand")) + +;; T prefix is used for different address constraints +;; v - VSIB address +;; s - address with no segment register +;; i - address with no index and no rip +;; b - address with no base and no rip + +(define_address_constraint "Tv" + "VSIB address operand" + (match_operand 0 "vsib_address_operand")) + +(define_address_constraint "Ts" + "Address operand without segment register" + (match_operand 0 "address_no_seg_operand")) + +(define_address_constraint "Ti" + "MPX address operand without index" + (match_operand 0 "address_mpx_no_index_operand")) + +(define_address_constraint "Tb" + "MPX address operand without base" + (match_operand 0 "address_mpx_no_base_operand")) diff --git a/gcc/config/i386/i386-c.c b/gcc/config/i386/i386-c.c index 8a41fb0ddf7..a6eaf8ad34a 100644 --- a/gcc/config/i386/i386-c.c +++ b/gcc/config/i386/i386-c.c @@ -358,6 +358,8 @@ ix86_target_macros_internal (HOST_WIDE_INT isa_flag, def_or_undef (parse_in, "__SSE_MATH__"); if ((fpmath & FPMATH_SSE) && (isa_flag & OPTION_MASK_ISA_SSE2)) def_or_undef (parse_in, "__SSE2_MATH__"); + if (isa_flag & OPTION_MASK_ISA_MPX) + def_or_undef (parse_in, "__MPX__"); } diff --git a/gcc/config/i386/i386-modes.def b/gcc/config/i386/i386-modes.def index e0b8fc826ab..a73730e08e2 100644 --- a/gcc/config/i386/i386-modes.def +++ b/gcc/config/i386/i386-modes.def @@ -87,6 +87,9 @@ VECTOR_MODE (INT, DI, 1); /* V1DI */ VECTOR_MODE (INT, SI, 1); /* V1SI */ VECTOR_MODE (INT, QI, 2); /* V2QI */ +POINTER_BOUNDS_MODE (BND32, 8); +POINTER_BOUNDS_MODE (BND64, 16); + INT_MODE (OI, 32); INT_MODE (XI, 64); diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index df388765497..5799251404b 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -240,6 +240,9 @@ extern void ix86_expand_mul_widen_evenodd (rtx, rtx, rtx, bool, bool); extern void ix86_expand_mul_widen_hilo (rtx, rtx, rtx, bool, bool); extern void ix86_expand_sse2_mulv4si3 (rtx, rtx, rtx); extern void ix86_expand_sse2_mulvxdi3 (rtx, rtx, rtx); +extern void ix86_expand_sse2_abs (rtx, rtx); + +extern bool ix86_bnd_prefixed_insn_p (rtx); /* In i386-c.c */ extern void ix86_target_macros (void); diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 4b69d4bf026..bc93d7f849a 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -1944,6 +1944,8 @@ enum reg_class const regclass_map[FIRST_PSEUDO_REGISTER] = /* Mask registers. */ MASK_REGS, MASK_EVEX_REGS, MASK_EVEX_REGS, MASK_EVEX_REGS, MASK_EVEX_REGS, MASK_EVEX_REGS, MASK_EVEX_REGS, MASK_EVEX_REGS, + /* MPX bound registers */ + BND_REGS, BND_REGS, BND_REGS, BND_REGS, }; /* The "default" register map used in 32bit mode. */ @@ -1960,6 +1962,7 @@ int const dbx_register_map[FIRST_PSEUDO_REGISTER] = -1, -1, -1, -1, -1, -1, -1, -1, /* AVX-512 registers 16-23*/ -1, -1, -1, -1, -1, -1, -1, -1, /* AVX-512 registers 24-31*/ 93, 94, 95, 96, 97, 98, 99, 100, /* Mask registers */ + 101, 102, 103, 104, /* bound registers */ }; /* The "default" register map used in 64bit mode. */ @@ -1976,6 +1979,7 @@ int const dbx64_register_map[FIRST_PSEUDO_REGISTER] = 67, 68, 69, 70, 71, 72, 73, 74, /* AVX-512 registers 16-23 */ 75, 76, 77, 78, 79, 80, 81, 82, /* AVX-512 registers 24-31 */ 118, 119, 120, 121, 122, 123, 124, 125, /* Mask registers */ + 126, 127, 128, 129, /* bound registers */ }; /* Define the register numbers to be used in Dwarf debugging information. @@ -2044,6 +2048,7 @@ int const svr4_dbx_register_map[FIRST_PSEUDO_REGISTER] = -1, -1, -1, -1, -1, -1, -1, -1, /* AVX-512 registers 16-23*/ -1, -1, -1, -1, -1, -1, -1, -1, /* AVX-512 registers 24-31*/ 93, 94, 95, 96, 97, 98, 99, 100, /* Mask registers */ + -1, -1, -1, -1, /* bound registers */ }; /* Define parameter passing and return registers. */ @@ -2470,6 +2475,7 @@ ix86_target_string (HOST_WIDE_INT isa, int flags, const char *arch, { "-mrtm", OPTION_MASK_ISA_RTM }, { "-mxsave", OPTION_MASK_ISA_XSAVE }, { "-mxsaveopt", OPTION_MASK_ISA_XSAVEOPT }, + { "-mmpx", OPTION_MASK_ISA_MPX }, }; /* Flag options. */ @@ -2964,6 +2970,7 @@ ix86_option_override_internal (bool main_args_p, #define PTA_AVX512ER (HOST_WIDE_INT_1 << 41) #define PTA_AVX512PF (HOST_WIDE_INT_1 << 42) #define PTA_AVX512CD (HOST_WIDE_INT_1 << 43) +#define PTA_MPX (HOST_WIDE_INT_1 << 44) /* if this reaches 64, need to widen struct pta flags below */ @@ -3799,7 +3806,7 @@ ix86_option_override_internal (bool main_args_p, codegen. We may switch to 387 with -ffast-math for size optimized functions. */ else if (fast_math_flags_set_p (&global_options) - && TARGET_SSE2) + && TARGET_SSE2_P (opts->x_ix86_isa_flags)) ix86_fpmath = FPMATH_SSE; else opts->x_ix86_fpmath = TARGET_FPMATH_DEFAULT_P (opts->x_ix86_isa_flags); @@ -4149,6 +4156,11 @@ ix86_conditional_register_usage (void) for (i = FIRST_MASK_REG; i <= LAST_MASK_REG; i++) fixed_regs[i] = call_used_regs[i] = 1, reg_names[i] = ""; } + + /* If MPX is disabled, squash the registers. */ + if (! TARGET_MPX) + for (i = FIRST_BND_REG; i <= LAST_BND_REG; i++) + fixed_regs[i] = call_used_regs[i] = 1, reg_names[i] = ""; } @@ -4554,7 +4566,8 @@ ix86_valid_target_attribute_tree (tree args, /* If fpmath= is not set, and we now have sse2 on 32-bit, use it. */ if (enum_opts_set.x_ix86_fpmath) opts_set->x_ix86_fpmath = (enum fpmath_unit) 1; - else if (!TARGET_64BIT && TARGET_SSE) + else if (!TARGET_64BIT_P (opts->x_ix86_isa_flags) + && TARGET_SSE_P (opts->x_ix86_isa_flags)) { opts->x_ix86_fpmath = (enum fpmath_unit) (FPMATH_SSE | FPMATH_387); opts_set->x_ix86_fpmath = (enum fpmath_unit) 1; @@ -8870,7 +8883,7 @@ ix86_code_end (void) xops[0] = gen_rtx_REG (Pmode, regno); xops[1] = gen_rtx_MEM (Pmode, stack_pointer_rtx); output_asm_insn ("mov%z0\t{%1, %0|%0, %1}", xops); - fputs ("\tret\n", asm_out_file); + output_asm_insn ("%!ret", NULL); final_end_function (); init_insn_lengths (); free_after_compilation (cfun); @@ -8928,7 +8941,7 @@ output_set_got (rtx dest, rtx label) xops[2] = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (name)); xops[2] = gen_rtx_MEM (QImode, xops[2]); - output_asm_insn ("call\t%X2", xops); + output_asm_insn ("%!call\t%X2", xops); #if TARGET_MACHO /* Output the Mach-O "canonical" pic base label name ("Lxx$pb") here. @@ -14104,8 +14117,6 @@ put_condition_code (enum rtx_code code, enum machine_mode mode, bool reverse, Those same assemblers have the same but opposite lossage on cmov. */ if (mode == CCmode) suffix = fp ? "nbe" : "a"; - else if (mode == CCCmode) - suffix = "b"; else gcc_unreachable (); break; @@ -14127,8 +14138,12 @@ put_condition_code (enum rtx_code code, enum machine_mode mode, bool reverse, } break; case LTU: - gcc_assert (mode == CCmode || mode == CCCmode); - suffix = "b"; + if (mode == CCmode) + suffix = "b"; + else if (mode == CCCmode) + suffix = "c"; + else + gcc_unreachable (); break; case GE: switch (mode) @@ -14148,20 +14163,20 @@ put_condition_code (enum rtx_code code, enum machine_mode mode, bool reverse, } break; case GEU: - /* ??? As above. */ - gcc_assert (mode == CCmode || mode == CCCmode); - suffix = fp ? "nb" : "ae"; + if (mode == CCmode) + suffix = fp ? "nb" : "ae"; + else if (mode == CCCmode) + suffix = "nc"; + else + gcc_unreachable (); break; case LE: gcc_assert (mode == CCmode || mode == CCGCmode || mode == CCNOmode); suffix = "le"; break; case LEU: - /* ??? As above. */ if (mode == CCmode) suffix = "be"; - else if (mode == CCCmode) - suffix = fp ? "nb" : "ae"; else gcc_unreachable (); break; @@ -14279,7 +14294,7 @@ print_reg (rtx x, int code, FILE *file) case 8: case 4: case 12: - if (! ANY_FP_REG_P (x)) + if (! ANY_FP_REG_P (x) && ! ANY_BND_REG_P (x)) putc (code == 8 && TARGET_64BIT ? 'r' : 'e', file); /* FALLTHRU */ case 16: @@ -14402,6 +14417,7 @@ get_some_local_dynamic_name (void) ~ -- print "i" if TARGET_AVX2, "f" otherwise. @ -- print a segment register of thread base pointer load ^ -- print addr32 prefix if TARGET_64BIT and Pmode != word_mode + ! -- print MPX prefix for jxx/call/ret instructions if required. */ void @@ -14896,6 +14912,11 @@ ix86_print_operand (FILE *file, rtx x, int code) fputs ("addr32 ", file); return; + case '!': + if (ix86_bnd_prefixed_insn_p (NULL_RTX)) + fputs ("bnd ", file); + return; + default: output_operand_lossage ("invalid operand code '%c'", code); } @@ -15038,7 +15059,7 @@ static bool ix86_print_operand_punct_valid_p (unsigned char code) { return (code == '@' || code == '*' || code == '+' || code == '&' - || code == ';' || code == '~' || code == '^'); + || code == ';' || code == '~' || code == '^' || code == '!'); } /* Print a memory operand whose address is ADDR. */ @@ -15068,6 +15089,25 @@ ix86_print_operand_address (FILE *file, rtx addr) ok = ix86_decompose_address (XVECEXP (addr, 0, 0), &parts); code = 'q'; } + else if (GET_CODE (addr) == UNSPEC && XINT (addr, 1) == UNSPEC_BNDMK_ADDR) + { + ok = ix86_decompose_address (XVECEXP (addr, 0, 1), &parts); + gcc_assert (parts.base == NULL_RTX || parts.index == NULL_RTX); + if (parts.base != NULL_RTX) + { + parts.index = parts.base; + parts.scale = 1; + } + parts.base = XVECEXP (addr, 0, 0); + addr = XVECEXP (addr, 0, 0); + } + else if (GET_CODE (addr) == UNSPEC && XINT (addr, 1) == UNSPEC_BNDLDX_ADDR) + { + ok = ix86_decompose_address (XVECEXP (addr, 0, 0), &parts); + gcc_assert (parts.index == NULL_RTX); + parts.index = XVECEXP (addr, 0, 1); + addr = XVECEXP (addr, 0, 0); + } else ok = ix86_decompose_address (addr, &parts); @@ -16521,6 +16561,12 @@ ix86_avx256_split_vector_move_misalign (rtx op0, rtx op1) r = gen_rtx_VEC_CONCAT (GET_MODE (op0), r, m); emit_move_insn (op0, r); } + /* Normal *mov<mode>_internal pattern will handle + unaligned loads just fine if misaligned_operand + is true, and without the UNSPEC it can be combined + with arithmetic instructions. */ + else if (misaligned_operand (op1, GET_MODE (op1))) + emit_insn (gen_rtx_SET (VOIDmode, op0, op1)); else emit_insn (load_unaligned (op0, op1)); } @@ -16595,7 +16641,7 @@ ix86_avx256_split_vector_move_misalign (rtx op0, rtx op1) void ix86_expand_vector_move_misalign (enum machine_mode mode, rtx operands[]) { - rtx op0, op1, m; + rtx op0, op1, orig_op0 = NULL_RTX, m; rtx (*load_unaligned) (rtx, rtx); rtx (*store_unaligned) (rtx, rtx); @@ -16608,7 +16654,16 @@ ix86_expand_vector_move_misalign (enum machine_mode mode, rtx operands[]) { case MODE_VECTOR_INT: case MODE_INT: - op0 = gen_lowpart (V16SImode, op0); + if (GET_MODE (op0) != V16SImode) + { + if (!MEM_P (op0)) + { + orig_op0 = op0; + op0 = gen_reg_rtx (V16SImode); + } + else + op0 = gen_lowpart (V16SImode, op0); + } op1 = gen_lowpart (V16SImode, op1); /* FALLTHRU */ @@ -16637,6 +16692,8 @@ ix86_expand_vector_move_misalign (enum machine_mode mode, rtx operands[]) emit_insn (store_unaligned (op0, op1)); else gcc_unreachable (); + if (orig_op0) + emit_move_insn (orig_op0, gen_lowpart (GET_MODE (orig_op0), op0)); break; default: @@ -16653,12 +16710,23 @@ ix86_expand_vector_move_misalign (enum machine_mode mode, rtx operands[]) { case MODE_VECTOR_INT: case MODE_INT: - op0 = gen_lowpart (V32QImode, op0); + if (GET_MODE (op0) != V32QImode) + { + if (!MEM_P (op0)) + { + orig_op0 = op0; + op0 = gen_reg_rtx (V32QImode); + } + else + op0 = gen_lowpart (V32QImode, op0); + } op1 = gen_lowpart (V32QImode, op1); /* FALLTHRU */ case MODE_VECTOR_FLOAT: ix86_avx256_split_vector_move_misalign (op0, op1); + if (orig_op0) + emit_move_insn (orig_op0, gen_lowpart (GET_MODE (orig_op0), op0)); break; default: @@ -16670,15 +16738,30 @@ ix86_expand_vector_move_misalign (enum machine_mode mode, rtx operands[]) if (MEM_P (op1)) { + /* Normal *mov<mode>_internal pattern will handle + unaligned loads just fine if misaligned_operand + is true, and without the UNSPEC it can be combined + with arithmetic instructions. */ + if (TARGET_AVX + && (GET_MODE_CLASS (mode) == MODE_VECTOR_INT + || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT) + && misaligned_operand (op1, GET_MODE (op1))) + emit_insn (gen_rtx_SET (VOIDmode, op0, op1)); /* ??? If we have typed data, then it would appear that using movdqu is the only way to get unaligned data loaded with integer type. */ - if (TARGET_SSE2 && GET_MODE_CLASS (mode) == MODE_VECTOR_INT) + else if (TARGET_SSE2 && GET_MODE_CLASS (mode) == MODE_VECTOR_INT) { - op0 = gen_lowpart (V16QImode, op0); + if (GET_MODE (op0) != V16QImode) + { + orig_op0 = op0; + op0 = gen_reg_rtx (V16QImode); + } op1 = gen_lowpart (V16QImode, op1); /* We will eventually emit movups based on insn attributes. */ emit_insn (gen_sse2_loaddquv16qi (op0, op1)); + if (orig_op0) + emit_move_insn (orig_op0, gen_lowpart (GET_MODE (orig_op0), op0)); } else if (TARGET_SSE2 && mode == V2DFmode) { @@ -16721,29 +16804,42 @@ ix86_expand_vector_move_misalign (enum machine_mode mode, rtx operands[]) } else { + rtx t; + if (TARGET_AVX || TARGET_SSE_UNALIGNED_LOAD_OPTIMAL || TARGET_SSE_PACKED_SINGLE_INSN_OPTIMAL || optimize_insn_for_size_p ()) { - op0 = gen_lowpart (V4SFmode, op0); + if (GET_MODE (op0) != V4SFmode) + { + orig_op0 = op0; + op0 = gen_reg_rtx (V4SFmode); + } op1 = gen_lowpart (V4SFmode, op1); emit_insn (gen_sse_loadups (op0, op1)); + if (orig_op0) + emit_move_insn (orig_op0, + gen_lowpart (GET_MODE (orig_op0), op0)); return; } + if (mode != V4SFmode) + t = gen_reg_rtx (V4SFmode); + else + t = op0; + if (TARGET_SSE_PARTIAL_REG_DEPENDENCY) - emit_move_insn (op0, CONST0_RTX (mode)); + emit_move_insn (t, CONST0_RTX (V4SFmode)); else - emit_clobber (op0); - - if (mode != V4SFmode) - op0 = gen_lowpart (V4SFmode, op0); + emit_clobber (t); m = adjust_address (op1, V2SFmode, 0); - emit_insn (gen_sse_loadlps (op0, op0, m)); + emit_insn (gen_sse_loadlps (t, t, m)); m = adjust_address (op1, V2SFmode, 8); - emit_insn (gen_sse_loadhps (op0, op0, m)); + emit_insn (gen_sse_loadhps (t, t, m)); + if (mode != V4SFmode) + emit_move_insn (op0, gen_lowpart (mode, t)); } } else if (MEM_P (op0)) @@ -18863,12 +18959,7 @@ ix86_cc_mode (enum rtx_code code, rtx op0, rtx op1) return CCmode; case GTU: /* CF=0 & ZF=0 */ case LEU: /* CF=1 | ZF=1 */ - /* Detect overflow checks. They need just the carry flag. */ - if (GET_CODE (op0) == MINUS - && rtx_equal_p (op1, XEXP (op0, 0))) - return CCCmode; - else - return CCmode; + return CCmode; /* Codes possibly doable only with sign flag when comparing against zero. */ case GE: /* SF=OF or SF=0 */ @@ -20389,6 +20480,7 @@ ix86_expand_sse_movcc (rtx dest, rtx cmp, rtx op_true, rtx op_false) else { rtx (*gen) (rtx, rtx, rtx, rtx) = NULL; + rtx d = dest; if (!nonimmediate_operand (op_true, mode)) op_true = force_reg (mode, op_true); @@ -20412,7 +20504,8 @@ ix86_expand_sse_movcc (rtx dest, rtx cmp, rtx op_true, rtx op_false) if (TARGET_SSE4_1) { gen = gen_sse4_1_pblendvb; - dest = gen_lowpart (V16QImode, dest); + if (mode != V16QImode) + d = gen_reg_rtx (V16QImode); op_false = gen_lowpart (V16QImode, op_false); op_true = gen_lowpart (V16QImode, op_true); cmp = gen_lowpart (V16QImode, cmp); @@ -20433,7 +20526,8 @@ ix86_expand_sse_movcc (rtx dest, rtx cmp, rtx op_true, rtx op_false) if (TARGET_AVX2) { gen = gen_avx2_pblendvb; - dest = gen_lowpart (V32QImode, dest); + if (mode != V32QImode) + d = gen_reg_rtx (V32QImode); op_false = gen_lowpart (V32QImode, op_false); op_true = gen_lowpart (V32QImode, op_true); cmp = gen_lowpart (V32QImode, cmp); @@ -20444,7 +20538,11 @@ ix86_expand_sse_movcc (rtx dest, rtx cmp, rtx op_true, rtx op_false) } if (gen != NULL) - emit_insn (gen (dest, op_false, op_true, cmp)); + { + emit_insn (gen (d, op_false, op_true, cmp)); + if (d != dest) + emit_move_insn (dest, gen_lowpart (GET_MODE (dest), d)); + } else { op_true = force_reg (mode, op_true); @@ -20765,8 +20863,7 @@ ix86_expand_int_vcond (rtx operands[]) else { gcc_assert (GET_MODE_SIZE (data_mode) == GET_MODE_SIZE (mode)); - x = ix86_expand_sse_cmp (gen_lowpart (mode, operands[0]), - code, cop0, cop1, + x = ix86_expand_sse_cmp (gen_reg_rtx (mode), code, cop0, cop1, operands[1+negate], operands[2-negate]); x = gen_lowpart (data_mode, x); } @@ -20785,7 +20882,7 @@ ix86_expand_vec_perm (rtx operands[]) rtx op0 = operands[1]; rtx op1 = operands[2]; rtx mask = operands[3]; - rtx t1, t2, t3, t4, vt, vt2, vec[32]; + rtx t1, t2, t3, t4, t5, t6, t7, t8, vt, vt2, vec[32]; enum machine_mode mode = GET_MODE (op0); enum machine_mode maskmode = GET_MODE (mask); int w, e, i; @@ -20853,7 +20950,7 @@ ix86_expand_vec_perm (rtx operands[]) /* Continue as if V8SImode (resp. V32QImode) was used initially. */ operands[3] = mask = t1; - target = gen_lowpart (mode, target); + target = gen_reg_rtx (mode); op0 = gen_lowpart (mode, op0); op1 = gen_lowpart (mode, op1); } @@ -20865,7 +20962,12 @@ ix86_expand_vec_perm (rtx operands[]) the high bits of the shuffle elements. No need for us to perform an AND ourselves. */ if (one_operand_shuffle) - emit_insn (gen_avx2_permvarv8si (target, op0, mask)); + { + emit_insn (gen_avx2_permvarv8si (target, op0, mask)); + if (target != operands[0]) + emit_move_insn (operands[0], + gen_lowpart (GET_MODE (operands[0]), target)); + } else { t1 = gen_reg_rtx (V8SImode); @@ -20938,13 +21040,13 @@ ix86_expand_vec_perm (rtx operands[]) stands for other 12 bytes. */ /* The bit whether element is from the same lane or the other lane is bit 4, so shift it up by 3 to the MSB position. */ - emit_insn (gen_ashlv4di3 (gen_lowpart (V4DImode, t1), - gen_lowpart (V4DImode, mask), + t5 = gen_reg_rtx (V4DImode); + emit_insn (gen_ashlv4di3 (t5, gen_lowpart (V4DImode, mask), GEN_INT (3))); /* Clear MSB bits from the mask just in case it had them set. */ emit_insn (gen_avx2_andnotv32qi3 (t2, vt, mask)); /* After this t1 will have MSB set for elements from other lane. */ - emit_insn (gen_xorv32qi3 (t1, t1, vt2)); + emit_insn (gen_xorv32qi3 (t1, gen_lowpart (V32QImode, t5), vt2)); /* Clear bits other than MSB. */ emit_insn (gen_andv32qi3 (t1, t1, vt)); /* Or in the lower bits from mask into t3. */ @@ -20953,8 +21055,8 @@ ix86_expand_vec_perm (rtx operands[]) lane. */ emit_insn (gen_xorv32qi3 (t1, t1, vt)); /* Swap 128-bit lanes in t3. */ - emit_insn (gen_avx2_permv4di_1 (gen_lowpart (V4DImode, t3), - gen_lowpart (V4DImode, t3), + t6 = gen_reg_rtx (V4DImode); + emit_insn (gen_avx2_permv4di_1 (t6, gen_lowpart (V4DImode, t3), const2_rtx, GEN_INT (3), const0_rtx, const1_rtx)); /* And or in the lower bits from mask into t1. */ @@ -20964,15 +21066,20 @@ ix86_expand_vec_perm (rtx operands[]) /* Each of these shuffles will put 0s in places where element from the other 128-bit lane is needed, otherwise will shuffle in the requested value. */ - emit_insn (gen_avx2_pshufbv32qi3 (t3, op0, t3)); + emit_insn (gen_avx2_pshufbv32qi3 (t3, op0, + gen_lowpart (V32QImode, t6))); emit_insn (gen_avx2_pshufbv32qi3 (t1, op0, t1)); /* For t3 the 128-bit lanes are swapped again. */ - emit_insn (gen_avx2_permv4di_1 (gen_lowpart (V4DImode, t3), - gen_lowpart (V4DImode, t3), + t7 = gen_reg_rtx (V4DImode); + emit_insn (gen_avx2_permv4di_1 (t7, gen_lowpart (V4DImode, t3), const2_rtx, GEN_INT (3), const0_rtx, const1_rtx)); /* And oring both together leads to the result. */ - emit_insn (gen_iorv32qi3 (target, t1, t3)); + emit_insn (gen_iorv32qi3 (target, t1, + gen_lowpart (V32QImode, t7))); + if (target != operands[0]) + emit_move_insn (operands[0], + gen_lowpart (GET_MODE (operands[0]), target)); return; } @@ -20980,20 +21087,22 @@ ix86_expand_vec_perm (rtx operands[]) /* Similarly to the above one_operand_shuffle code, just for repeated twice for each operand. merge_two: code will merge the two results together. */ - emit_insn (gen_avx2_pshufbv32qi3 (t4, op0, t3)); - emit_insn (gen_avx2_pshufbv32qi3 (t3, op1, t3)); + emit_insn (gen_avx2_pshufbv32qi3 (t4, op0, + gen_lowpart (V32QImode, t6))); + emit_insn (gen_avx2_pshufbv32qi3 (t3, op1, + gen_lowpart (V32QImode, t6))); emit_insn (gen_avx2_pshufbv32qi3 (t2, op0, t1)); emit_insn (gen_avx2_pshufbv32qi3 (t1, op1, t1)); - emit_insn (gen_avx2_permv4di_1 (gen_lowpart (V4DImode, t4), - gen_lowpart (V4DImode, t4), + t7 = gen_reg_rtx (V4DImode); + emit_insn (gen_avx2_permv4di_1 (t7, gen_lowpart (V4DImode, t4), const2_rtx, GEN_INT (3), const0_rtx, const1_rtx)); - emit_insn (gen_avx2_permv4di_1 (gen_lowpart (V4DImode, t3), - gen_lowpart (V4DImode, t3), + t8 = gen_reg_rtx (V4DImode); + emit_insn (gen_avx2_permv4di_1 (t8, gen_lowpart (V4DImode, t3), const2_rtx, GEN_INT (3), const0_rtx, const1_rtx)); - emit_insn (gen_iorv32qi3 (t4, t2, t4)); - emit_insn (gen_iorv32qi3 (t3, t1, t3)); + emit_insn (gen_iorv32qi3 (t4, t2, gen_lowpart (V32QImode, t7))); + emit_insn (gen_iorv32qi3 (t3, t1, gen_lowpart (V32QImode, t8))); t1 = t4; t2 = t3; goto merge_two; @@ -21062,15 +21171,24 @@ ix86_expand_vec_perm (rtx operands[]) /* The actual shuffle operations all operate on V16QImode. */ op0 = gen_lowpart (V16QImode, op0); op1 = gen_lowpart (V16QImode, op1); - target = gen_lowpart (V16QImode, target); if (TARGET_XOP) { + if (GET_MODE (target) != V16QImode) + target = gen_reg_rtx (V16QImode); emit_insn (gen_xop_pperm (target, op0, op1, mask)); + if (target != operands[0]) + emit_move_insn (operands[0], + gen_lowpart (GET_MODE (operands[0]), target)); } else if (one_operand_shuffle) { + if (GET_MODE (target) != V16QImode) + target = gen_reg_rtx (V16QImode); emit_insn (gen_ssse3_pshufbv16qi3 (target, op0, mask)); + if (target != operands[0]) + emit_move_insn (operands[0], + gen_lowpart (GET_MODE (operands[0]), target)); } else { @@ -21110,7 +21228,9 @@ ix86_expand_vec_perm (rtx operands[]) mask = expand_simple_binop (maskmode, AND, mask, vt, NULL_RTX, 0, OPTAB_DIRECT); - xops[0] = gen_lowpart (mode, operands[0]); + if (GET_MODE (target) != mode) + target = gen_reg_rtx (mode); + xops[0] = target; xops[1] = gen_lowpart (mode, t2); xops[2] = gen_lowpart (mode, t1); xops[3] = gen_rtx_EQ (maskmode, mask, vt); @@ -21118,6 +21238,9 @@ ix86_expand_vec_perm (rtx operands[]) xops[5] = vt; ok = ix86_expand_int_vcond (xops); gcc_assert (ok); + if (target != operands[0]) + emit_move_insn (operands[0], + gen_lowpart (GET_MODE (operands[0]), target)); } } @@ -21196,10 +21319,10 @@ ix86_expand_sse_unpack (rtx dest, rtx src, bool unsigned_p, bool high_p) else if (high_p) { /* Shift higher 8 bytes to lower 8 bytes. */ - tmp = gen_reg_rtx (imode); - emit_insn (gen_sse2_lshrv1ti3 (gen_lowpart (V1TImode, tmp), - gen_lowpart (V1TImode, src), + tmp = gen_reg_rtx (V1TImode); + emit_insn (gen_sse2_lshrv1ti3 (tmp, gen_lowpart (V1TImode, src), GEN_INT (64))); + tmp = gen_lowpart (imode, tmp); } else tmp = src; @@ -21240,7 +21363,9 @@ ix86_expand_sse_unpack (rtx dest, rtx src, bool unsigned_p, bool high_p) tmp = ix86_expand_sse_cmp (gen_reg_rtx (imode), GT, CONST0_RTX (imode), src, pc_rtx, pc_rtx); - emit_insn (unpack (gen_lowpart (imode, dest), src, tmp)); + rtx tmp2 = gen_reg_rtx (imode); + emit_insn (unpack (tmp2, src, tmp)); + emit_move_insn (dest, gen_lowpart (GET_MODE (dest), tmp2)); } } @@ -22132,10 +22257,10 @@ ix86_copy_addr_to_reg (rtx addr) } } -/* When SRCPTR is non-NULL, output simple loop to move memory - pointer to SRCPTR to DESTPTR via chunks of MODE unrolled UNROLL times, - overall size is COUNT specified in bytes. When SRCPTR is NULL, output the - equivalent loop to set memory by VALUE (supposed to be in MODE). +/* When ISSETMEM is FALSE, output simple loop to move memory pointer to SRCPTR + to DESTPTR via chunks of MODE unrolled UNROLL times, overall size is COUNT + specified in bytes. When ISSETMEM is TRUE, output the equivalent loop to set + memory by VALUE (supposed to be in MODE). The size is rounded down to whole number of chunk size moved at once. SRCMEM and DESTMEM provide MEMrtx to feed proper aliasing info. */ @@ -22145,7 +22270,7 @@ static void expand_set_or_movmem_via_loop (rtx destmem, rtx srcmem, rtx destptr, rtx srcptr, rtx value, rtx count, enum machine_mode mode, int unroll, - int expected_size) + int expected_size, bool issetmem) { rtx out_label, top_label, iter, tmp; enum machine_mode iter_mode = counter_mode (count); @@ -22181,7 +22306,7 @@ expand_set_or_movmem_via_loop (rtx destmem, rtx srcmem, destmem = offset_address (destmem, tmp, piece_size_n); destmem = adjust_address (destmem, mode, 0); - if (srcmem) + if (!issetmem) { srcmem = offset_address (srcmem, copy_rtx (tmp), piece_size_n); srcmem = adjust_address (srcmem, mode, 0); @@ -22261,7 +22386,7 @@ expand_set_or_movmem_via_loop (rtx destmem, rtx srcmem, true, OPTAB_LIB_WIDEN); if (tmp != destptr) emit_move_insn (destptr, tmp); - if (srcptr) + if (!issetmem) { tmp = expand_simple_binop (Pmode, PLUS, srcptr, iter, srcptr, true, OPTAB_LIB_WIDEN); @@ -22271,96 +22396,85 @@ expand_set_or_movmem_via_loop (rtx destmem, rtx srcmem, emit_label (out_label); } -/* Output "rep; mov" instruction. - Arguments have same meaning as for previous function */ +/* Output "rep; mov" or "rep; stos" instruction depending on ISSETMEM argument. + When ISSETMEM is true, arguments SRCMEM and SRCPTR are ignored. + When ISSETMEM is false, arguments VALUE and ORIG_VALUE are ignored. + For setmem case, VALUE is a promoted to a wider size ORIG_VALUE. + ORIG_VALUE is the original value passed to memset to fill the memory with. + Other arguments have same meaning as for previous function. */ + static void -expand_movmem_via_rep_mov (rtx destmem, rtx srcmem, - rtx destptr, rtx srcptr, +expand_set_or_movmem_via_rep (rtx destmem, rtx srcmem, + rtx destptr, rtx srcptr, rtx value, rtx orig_value, rtx count, - enum machine_mode mode) + enum machine_mode mode, bool issetmem) { rtx destexp; rtx srcexp; rtx countreg; HOST_WIDE_INT rounded_count; - /* If the size is known, it is shorter to use rep movs. */ - if (mode == QImode && CONST_INT_P (count) - && !(INTVAL (count) & 3)) + /* If possible, it is shorter to use rep movs. + TODO: Maybe it is better to move this logic to decide_alg. */ + if (mode == QImode && CONST_INT_P (count) && !(INTVAL (count) & 3) + && (!issetmem || orig_value == const0_rtx)) mode = SImode; if (destptr != XEXP (destmem, 0) || GET_MODE (destmem) != BLKmode) destmem = adjust_automodify_address_nv (destmem, BLKmode, destptr, 0); - if (srcptr != XEXP (srcmem, 0) || GET_MODE (srcmem) != BLKmode) - srcmem = adjust_automodify_address_nv (srcmem, BLKmode, srcptr, 0); - countreg = ix86_zero_extend_to_Pmode (scale_counter (count, GET_MODE_SIZE (mode))); + + countreg = ix86_zero_extend_to_Pmode (scale_counter (count, + GET_MODE_SIZE (mode))); if (mode != QImode) { destexp = gen_rtx_ASHIFT (Pmode, countreg, GEN_INT (exact_log2 (GET_MODE_SIZE (mode)))); destexp = gen_rtx_PLUS (Pmode, destexp, destptr); - srcexp = gen_rtx_ASHIFT (Pmode, countreg, - GEN_INT (exact_log2 (GET_MODE_SIZE (mode)))); - srcexp = gen_rtx_PLUS (Pmode, srcexp, srcptr); } else - { - destexp = gen_rtx_PLUS (Pmode, destptr, countreg); - srcexp = gen_rtx_PLUS (Pmode, srcptr, countreg); - } - if (CONST_INT_P (count)) + destexp = gen_rtx_PLUS (Pmode, destptr, countreg); + if ((!issetmem || orig_value == const0_rtx) && CONST_INT_P (count)) { rounded_count = (INTVAL (count) & ~((HOST_WIDE_INT) GET_MODE_SIZE (mode) - 1)); destmem = shallow_copy_rtx (destmem); - srcmem = shallow_copy_rtx (srcmem); set_mem_size (destmem, rounded_count); - set_mem_size (srcmem, rounded_count); - } - else - { - if (MEM_SIZE_KNOWN_P (destmem)) - clear_mem_size (destmem); - if (MEM_SIZE_KNOWN_P (srcmem)) - clear_mem_size (srcmem); } - emit_insn (gen_rep_mov (destptr, destmem, srcptr, srcmem, countreg, - destexp, srcexp)); -} - -/* Output "rep; stos" instruction. - Arguments have same meaning as for previous function */ -static void -expand_setmem_via_rep_stos (rtx destmem, rtx destptr, rtx value, - rtx count, enum machine_mode mode, - rtx orig_value) -{ - rtx destexp; - rtx countreg; - HOST_WIDE_INT rounded_count; + else if (MEM_SIZE_KNOWN_P (destmem)) + clear_mem_size (destmem); - if (destptr != XEXP (destmem, 0) || GET_MODE (destmem) != BLKmode) - destmem = adjust_automodify_address_nv (destmem, BLKmode, destptr, 0); - value = force_reg (mode, gen_lowpart (mode, value)); - countreg = ix86_zero_extend_to_Pmode (scale_counter (count, GET_MODE_SIZE (mode))); - if (mode != QImode) + if (issetmem) { - destexp = gen_rtx_ASHIFT (Pmode, countreg, - GEN_INT (exact_log2 (GET_MODE_SIZE (mode)))); - destexp = gen_rtx_PLUS (Pmode, destexp, destptr); + value = force_reg (mode, gen_lowpart (mode, value)); + emit_insn (gen_rep_stos (destptr, countreg, destmem, value, destexp)); } else - destexp = gen_rtx_PLUS (Pmode, destptr, countreg); - if (orig_value == const0_rtx && CONST_INT_P (count)) { - rounded_count = (INTVAL (count) - & ~((HOST_WIDE_INT) GET_MODE_SIZE (mode) - 1)); - destmem = shallow_copy_rtx (destmem); - set_mem_size (destmem, rounded_count); + if (srcptr != XEXP (srcmem, 0) || GET_MODE (srcmem) != BLKmode) + srcmem = adjust_automodify_address_nv (srcmem, BLKmode, srcptr, 0); + if (mode != QImode) + { + srcexp = gen_rtx_ASHIFT (Pmode, countreg, + GEN_INT (exact_log2 (GET_MODE_SIZE (mode)))); + srcexp = gen_rtx_PLUS (Pmode, srcexp, srcptr); + } + else + srcexp = gen_rtx_PLUS (Pmode, srcptr, countreg); + if (CONST_INT_P (count)) + { + rounded_count = (INTVAL (count) + & ~((HOST_WIDE_INT) GET_MODE_SIZE (mode) - 1)); + srcmem = shallow_copy_rtx (srcmem); + set_mem_size (srcmem, rounded_count); + } + else + { + if (MEM_SIZE_KNOWN_P (srcmem)) + clear_mem_size (srcmem); + } + emit_insn (gen_rep_mov (destptr, destmem, srcptr, srcmem, countreg, + destexp, srcexp)); } - else if (MEM_SIZE_KNOWN_P (destmem)) - clear_mem_size (destmem); - emit_insn (gen_rep_stos (destptr, countreg, destmem, value, destexp)); } /* This function emits moves to copy SIZE_TO_MOVE bytes from SRCMEM to @@ -22463,7 +22577,7 @@ expand_movmem_epilogue (rtx destmem, rtx srcmem, count = expand_simple_binop (GET_MODE (count), AND, count, GEN_INT (max_size - 1), count, 1, OPTAB_DIRECT); expand_set_or_movmem_via_loop (destmem, srcmem, destptr, srcptr, NULL, - count, QImode, 1, 4); + count, QImode, 1, 4, false); return; } @@ -22548,6 +22662,59 @@ expand_movmem_epilogue (rtx destmem, rtx srcmem, } } +/* This function emits moves to fill SIZE_TO_MOVE bytes starting from DESTMEM + with value PROMOTED_VAL. + SRC is passed by pointer to be updated on return. + Return value is updated DST. */ +static rtx +emit_memset (rtx destmem, rtx destptr, rtx promoted_val, + HOST_WIDE_INT size_to_move) +{ + rtx dst = destmem, adjust; + enum insn_code code; + enum machine_mode move_mode; + int piece_size, i; + + /* Find the widest mode in which we could perform moves. + Start with the biggest power of 2 less than SIZE_TO_MOVE and half + it until move of such size is supported. */ + move_mode = GET_MODE (promoted_val); + if (move_mode == VOIDmode) + move_mode = QImode; + if (size_to_move < GET_MODE_SIZE (move_mode)) + { + move_mode = mode_for_size (size_to_move * BITS_PER_UNIT, MODE_INT, 0); + promoted_val = gen_lowpart (move_mode, promoted_val); + } + piece_size = GET_MODE_SIZE (move_mode); + code = optab_handler (mov_optab, move_mode); + gcc_assert (code != CODE_FOR_nothing && promoted_val != NULL_RTX); + + dst = adjust_automodify_address_nv (dst, move_mode, destptr, 0); + + /* Emit moves. We'll need SIZE_TO_MOVE/PIECE_SIZES moves. */ + gcc_assert (size_to_move % piece_size == 0); + adjust = GEN_INT (piece_size); + for (i = 0; i < size_to_move; i += piece_size) + { + if (piece_size <= GET_MODE_SIZE (word_mode)) + { + emit_insn (gen_strset (destptr, dst, promoted_val)); + continue; + } + + emit_insn (GEN_FCN (code) (dst, promoted_val)); + + emit_move_insn (destptr, + gen_rtx_PLUS (Pmode, copy_rtx (destptr), adjust)); + + dst = adjust_automodify_address_nv (dst, move_mode, destptr, + piece_size); + } + + /* Update DST rtx. */ + return dst; +} /* Output code to set at most count & (max_size - 1) bytes starting by DEST. */ static void expand_setmem_epilogue_via_loop (rtx destmem, rtx destptr, rtx value, @@ -22558,66 +22725,35 @@ expand_setmem_epilogue_via_loop (rtx destmem, rtx destptr, rtx value, GEN_INT (max_size - 1), count, 1, OPTAB_DIRECT); expand_set_or_movmem_via_loop (destmem, NULL, destptr, NULL, gen_lowpart (QImode, value), count, QImode, - 1, max_size / 2); + 1, max_size / 2, true); } /* Output code to set at most count & (max_size - 1) bytes starting by DEST. */ static void -expand_setmem_epilogue (rtx destmem, rtx destptr, rtx value, rtx count, int max_size) +expand_setmem_epilogue (rtx destmem, rtx destptr, rtx value, rtx vec_value, + rtx count, int max_size) { rtx dest; if (CONST_INT_P (count)) { HOST_WIDE_INT countval = INTVAL (count); - int offset = 0; + HOST_WIDE_INT epilogue_size = countval % max_size; + int i; - if ((countval & 0x10) && max_size > 16) - { - if (TARGET_64BIT) - { - dest = adjust_automodify_address_nv (destmem, DImode, destptr, offset); - emit_insn (gen_strset (destptr, dest, value)); - dest = adjust_automodify_address_nv (destmem, DImode, destptr, offset + 8); - emit_insn (gen_strset (destptr, dest, value)); - } - else - gcc_unreachable (); - offset += 16; - } - if ((countval & 0x08) && max_size > 8) + /* For now MAX_SIZE should be a power of 2. This assert could be + relaxed, but it'll require a bit more complicated epilogue + expanding. */ + gcc_assert ((max_size & (max_size - 1)) == 0); + for (i = max_size; i >= 1; i >>= 1) { - if (TARGET_64BIT) - { - dest = adjust_automodify_address_nv (destmem, DImode, destptr, offset); - emit_insn (gen_strset (destptr, dest, value)); - } - else + if (epilogue_size & i) { - dest = adjust_automodify_address_nv (destmem, SImode, destptr, offset); - emit_insn (gen_strset (destptr, dest, value)); - dest = adjust_automodify_address_nv (destmem, SImode, destptr, offset + 4); - emit_insn (gen_strset (destptr, dest, value)); + if (vec_value && i > GET_MODE_SIZE (GET_MODE (value))) + destmem = emit_memset (destmem, destptr, vec_value, i); + else + destmem = emit_memset (destmem, destptr, value, i); } - offset += 8; - } - if ((countval & 0x04) && max_size > 4) - { - dest = adjust_automodify_address_nv (destmem, SImode, destptr, offset); - emit_insn (gen_strset (destptr, dest, gen_lowpart (SImode, value))); - offset += 4; - } - if ((countval & 0x02) && max_size > 2) - { - dest = adjust_automodify_address_nv (destmem, HImode, destptr, offset); - emit_insn (gen_strset (destptr, dest, gen_lowpart (HImode, value))); - offset += 2; - } - if ((countval & 0x01) && max_size > 1) - { - dest = adjust_automodify_address_nv (destmem, QImode, destptr, offset); - emit_insn (gen_strset (destptr, dest, gen_lowpart (QImode, value))); - offset += 1; } return; } @@ -22689,13 +22825,16 @@ expand_setmem_epilogue (rtx destmem, rtx destptr, rtx value, rtx count, int max_ } } -/* Copy enough from DEST to SRC to align DEST known to by aligned by ALIGN to - DESIRED_ALIGNMENT. +/* Depending on ISSETMEM, copy enough from SRCMEM to DESTMEM or set enough to + DESTMEM to align it to DESIRED_ALIGNMENT. Original alignment is ALIGN. + Depending on ISSETMEM, either arguments SRCMEM/SRCPTR or VALUE/VEC_VALUE are + ignored. Return value is updated DESTMEM. */ static rtx -expand_movmem_prologue (rtx destmem, rtx srcmem, - rtx destptr, rtx srcptr, rtx count, - int align, int desired_alignment) +expand_set_or_movmem_prologue (rtx destmem, rtx srcmem, + rtx destptr, rtx srcptr, rtx value, + rtx vec_value, rtx count, int align, + int desired_alignment, bool issetmem) { int i; for (i = 1; i < desired_alignment; i <<= 1) @@ -22703,7 +22842,15 @@ expand_movmem_prologue (rtx destmem, rtx srcmem, if (align <= i) { rtx label = ix86_expand_aligntest (destptr, i, false); - destmem = emit_memmov (destmem, &srcmem, destptr, srcptr, i); + if (issetmem) + { + if (vec_value && i > GET_MODE_SIZE (GET_MODE (value))) + destmem = emit_memset (destmem, destptr, vec_value, i); + else + destmem = emit_memset (destmem, destptr, value, i); + } + else + destmem = emit_memmov (destmem, &srcmem, destptr, srcptr, i); ix86_adjust_counter (count, i); emit_label (label); LABEL_NUSES (label) = 1; @@ -22713,191 +22860,482 @@ expand_movmem_prologue (rtx destmem, rtx srcmem, return destmem; } -/* Copy enough from DST to SRC to align DST known to DESIRED_ALIGN. - ALIGN_BYTES is how many bytes need to be copied. - The function updates DST and SRC, namely, it sets proper alignment. - DST is returned via return value, SRC is updated via pointer SRCP. */ -static rtx -expand_constant_movmem_prologue (rtx dst, rtx *srcp, rtx destreg, rtx srcreg, - int desired_align, int align_bytes) -{ - rtx src = *srcp; - rtx orig_dst = dst; - rtx orig_src = src; - int piece_size = 1; - int copied_bytes = 0; - int src_align_bytes = get_mem_align_offset (src, desired_align * BITS_PER_UNIT); - if (src_align_bytes >= 0) - src_align_bytes = desired_align - src_align_bytes; +/* Test if COUNT&SIZE is nonzero and if so, expand movme + or setmem sequence that is valid for SIZE..2*SIZE-1 bytes + and jump to DONE_LABEL. */ +static void +expand_small_movmem_or_setmem (rtx destmem, rtx srcmem, + rtx destptr, rtx srcptr, + rtx value, rtx vec_value, + rtx count, int size, + rtx done_label, bool issetmem) +{ + rtx label = ix86_expand_aligntest (count, size, false); + enum machine_mode mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 1); + rtx modesize; + int n; - for (piece_size = 1; - piece_size <= desired_align && copied_bytes < align_bytes; - piece_size <<= 1) + /* If we do not have vector value to copy, we must reduce size. */ + if (issetmem) { - if (align_bytes & piece_size) + if (!vec_value) { - dst = emit_memmov (dst, &src, destreg, srcreg, piece_size); - copied_bytes += piece_size; + if (GET_MODE (value) == VOIDmode && size > 8) + mode = Pmode; + else if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (value))) + mode = GET_MODE (value); } + else + mode = GET_MODE (vec_value), value = vec_value; } - - if (MEM_ALIGN (dst) < (unsigned int) desired_align * BITS_PER_UNIT) - set_mem_align (dst, desired_align * BITS_PER_UNIT); - if (src_align_bytes >= 0) + else + { + /* Choose appropriate vector mode. */ + if (size >= 32) + mode = TARGET_AVX ? V32QImode : TARGET_SSE ? V16QImode : DImode; + else if (size >= 16) + mode = TARGET_SSE ? V16QImode : DImode; + srcmem = change_address (srcmem, mode, srcptr); + } + destmem = change_address (destmem, mode, destptr); + modesize = GEN_INT (GET_MODE_SIZE (mode)); + gcc_assert (GET_MODE_SIZE (mode) <= size); + for (n = 0; n * GET_MODE_SIZE (mode) < size; n++) { - unsigned int src_align; - for (src_align = desired_align; src_align >= 2; src_align >>= 1) + if (issetmem) + emit_move_insn (destmem, gen_lowpart (mode, value)); + else { - if ((src_align_bytes & (src_align - 1)) - == (align_bytes & (src_align - 1))) - break; + emit_move_insn (destmem, srcmem); + srcmem = offset_address (srcmem, modesize, GET_MODE_SIZE (mode)); } - if (src_align > (unsigned int) desired_align) - src_align = desired_align; - if (MEM_ALIGN (src) < src_align * BITS_PER_UNIT) - set_mem_align (src, src_align * BITS_PER_UNIT); + destmem = offset_address (destmem, modesize, GET_MODE_SIZE (mode)); } - if (MEM_SIZE_KNOWN_P (orig_dst)) - set_mem_size (dst, MEM_SIZE (orig_dst) - align_bytes); - if (MEM_SIZE_KNOWN_P (orig_src)) - set_mem_size (src, MEM_SIZE (orig_src) - align_bytes); - *srcp = src; - return dst; + + destmem = offset_address (destmem, count, 1); + destmem = offset_address (destmem, GEN_INT (-size - GET_MODE_SIZE (mode)), + GET_MODE_SIZE (mode)); + if (issetmem) + emit_move_insn (destmem, gen_lowpart (mode, value)); + else + { + srcmem = offset_address (srcmem, count, 1); + srcmem = offset_address (srcmem, GEN_INT (-size - GET_MODE_SIZE (mode)), + GET_MODE_SIZE (mode)); + emit_move_insn (destmem, srcmem); + } + emit_jump_insn (gen_jump (done_label)); + emit_barrier (); + + emit_label (label); + LABEL_NUSES (label) = 1; } -/* Set enough from DEST to align DEST known to by aligned by ALIGN to - DESIRED_ALIGNMENT. */ +/* Handle small memcpy (up to SIZE that is supposed to be small power of 2. + and get ready for the main memcpy loop by copying iniital DESIRED_ALIGN-ALIGN + bytes and last SIZE bytes adjusitng DESTPTR/SRCPTR/COUNT in a way we can + proceed with an loop copying SIZE bytes at once. Do moves in MODE. + DONE_LABEL is a label after the whole copying sequence. The label is created + on demand if *DONE_LABEL is NULL. + MIN_SIZE is minimal size of block copied. This value gets adjusted for new + bounds after the initial copies. + + DESTMEM/SRCMEM are memory expressions pointing to the copies block, + DESTPTR/SRCPTR are pointers to the block. DYNAMIC_CHECK indicate whether + we will dispatch to a library call for large blocks. + + In pseudocode we do: + + if (COUNT < SIZE) + { + Assume that SIZE is 4. Bigger sizes are handled analogously + if (COUNT & 4) + { + copy 4 bytes from SRCPTR to DESTPTR + copy 4 bytes from SRCPTR + COUNT - 4 to DESTPTR + COUNT - 4 + goto done_label + } + if (!COUNT) + goto done_label; + copy 1 byte from SRCPTR to DESTPTR + if (COUNT & 2) + { + copy 2 bytes from SRCPTR to DESTPTR + copy 2 bytes from SRCPTR + COUNT - 2 to DESTPTR + COUNT - 2 + } + } + else + { + copy at least DESIRED_ALIGN-ALIGN bytes from SRCPTR to DESTPTR + copy SIZE bytes from SRCPTR + COUNT - SIZE to DESTPTR + COUNT -SIZE + + OLD_DESPTR = DESTPTR; + Align DESTPTR up to DESIRED_ALIGN + SRCPTR += DESTPTR - OLD_DESTPTR + COUNT -= DEST_PTR - OLD_DESTPTR + if (DYNAMIC_CHECK) + Round COUNT down to multiple of SIZE + << optional caller supplied zero size guard is here >> + << optional caller suppplied dynamic check is here >> + << caller supplied main copy loop is here >> + } + done_label: + */ static void -expand_setmem_prologue (rtx destmem, rtx destptr, rtx value, rtx count, - int align, int desired_alignment) -{ - if (align <= 1 && desired_alignment > 1) - { - rtx label = ix86_expand_aligntest (destptr, 1, false); - destmem = change_address (destmem, QImode, destptr); - emit_insn (gen_strset (destptr, destmem, gen_lowpart (QImode, value))); - ix86_adjust_counter (count, 1); +expand_set_or_movmem_prologue_epilogue_by_misaligned_moves (rtx destmem, rtx srcmem, + rtx *destptr, rtx *srcptr, + enum machine_mode mode, + rtx value, rtx vec_value, + rtx *count, + rtx *done_label, + int size, + int desired_align, + int align, + unsigned HOST_WIDE_INT *min_size, + bool dynamic_check, + bool issetmem) +{ + rtx loop_label = NULL, label; + int n; + rtx modesize; + int prolog_size = 0; + rtx mode_value; + + /* Chose proper value to copy. */ + if (issetmem && VECTOR_MODE_P (mode)) + mode_value = vec_value; + else + mode_value = value; + gcc_assert (GET_MODE_SIZE (mode) <= size); + + /* See if block is big or small, handle small blocks. */ + if (!CONST_INT_P (*count) && *min_size < (unsigned HOST_WIDE_INT)size) + { + int size2 = size; + loop_label = gen_label_rtx (); + + if (!*done_label) + *done_label = gen_label_rtx (); + + emit_cmp_and_jump_insns (*count, GEN_INT (size2), GE, 0, GET_MODE (*count), + 1, loop_label); + size2 >>= 1; + + /* Handle sizes > 3. */ + for (;size2 > 2; size2 >>= 1) + expand_small_movmem_or_setmem (destmem, srcmem, + *destptr, *srcptr, + value, vec_value, + *count, + size2, *done_label, issetmem); + /* Nothing to copy? Jump to DONE_LABEL if so */ + emit_cmp_and_jump_insns (*count, const0_rtx, EQ, 0, GET_MODE (*count), + 1, *done_label); + + /* Do a byte copy. */ + destmem = change_address (destmem, QImode, *destptr); + if (issetmem) + emit_move_insn (destmem, gen_lowpart (QImode, value)); + else + { + srcmem = change_address (srcmem, QImode, *srcptr); + emit_move_insn (destmem, srcmem); + } + + /* Handle sizes 2 and 3. */ + label = ix86_expand_aligntest (*count, 2, false); + destmem = change_address (destmem, HImode, *destptr); + destmem = offset_address (destmem, *count, 1); + destmem = offset_address (destmem, GEN_INT (-2), 2); + if (issetmem) + emit_move_insn (destmem, gen_lowpart (HImode, value)); + else + { + srcmem = change_address (srcmem, HImode, *srcptr); + srcmem = offset_address (srcmem, *count, 1); + srcmem = offset_address (srcmem, GEN_INT (-2), 2); + emit_move_insn (destmem, srcmem); + } + emit_label (label); LABEL_NUSES (label) = 1; + emit_jump_insn (gen_jump (*done_label)); + emit_barrier (); } - if (align <= 2 && desired_alignment > 2) + else + gcc_assert (*min_size >= (unsigned HOST_WIDE_INT)size + || UINTVAL (*count) >= (unsigned HOST_WIDE_INT)size); + + /* Start memcpy for COUNT >= SIZE. */ + if (loop_label) { - rtx label = ix86_expand_aligntest (destptr, 2, false); - destmem = change_address (destmem, HImode, destptr); - emit_insn (gen_strset (destptr, destmem, gen_lowpart (HImode, value))); - ix86_adjust_counter (count, 2); - emit_label (label); - LABEL_NUSES (label) = 1; + emit_label (loop_label); + LABEL_NUSES (loop_label) = 1; } - if (align <= 4 && desired_alignment > 4) + + /* Copy first desired_align bytes. */ + if (!issetmem) + srcmem = change_address (srcmem, mode, *srcptr); + destmem = change_address (destmem, mode, *destptr); + modesize = GEN_INT (GET_MODE_SIZE (mode)); + for (n = 0; prolog_size < desired_align - align; n++) { - rtx label = ix86_expand_aligntest (destptr, 4, false); - destmem = change_address (destmem, SImode, destptr); - emit_insn (gen_strset (destptr, destmem, gen_lowpart (SImode, value))); - ix86_adjust_counter (count, 4); - emit_label (label); - LABEL_NUSES (label) = 1; + if (issetmem) + emit_move_insn (destmem, mode_value); + else + { + emit_move_insn (destmem, srcmem); + srcmem = offset_address (srcmem, modesize, GET_MODE_SIZE (mode)); + } + destmem = offset_address (destmem, modesize, GET_MODE_SIZE (mode)); + prolog_size += GET_MODE_SIZE (mode); + } + + + /* Copy last SIZE bytes. */ + destmem = offset_address (destmem, *count, 1); + destmem = offset_address (destmem, + GEN_INT (-size - prolog_size), + 1); + if (issetmem) + emit_move_insn (destmem, mode_value); + else + { + srcmem = offset_address (srcmem, *count, 1); + srcmem = offset_address (srcmem, + GEN_INT (-size - prolog_size), + 1); + emit_move_insn (destmem, srcmem); + } + for (n = 1; n * GET_MODE_SIZE (mode) < size; n++) + { + destmem = offset_address (destmem, modesize, 1); + if (issetmem) + emit_move_insn (destmem, mode_value); + else + { + srcmem = offset_address (srcmem, modesize, 1); + emit_move_insn (destmem, srcmem); + } + } + + /* Align destination. */ + if (desired_align > 1 && desired_align > align) + { + rtx saveddest = *destptr; + + gcc_assert (desired_align <= size); + /* Align destptr up, place it to new register. */ + *destptr = expand_simple_binop (GET_MODE (*destptr), PLUS, *destptr, + GEN_INT (prolog_size), + NULL_RTX, 1, OPTAB_DIRECT); + *destptr = expand_simple_binop (GET_MODE (*destptr), AND, *destptr, + GEN_INT (-desired_align), + *destptr, 1, OPTAB_DIRECT); + /* See how many bytes we skipped. */ + saveddest = expand_simple_binop (GET_MODE (*destptr), MINUS, saveddest, + *destptr, + saveddest, 1, OPTAB_DIRECT); + /* Adjust srcptr and count. */ + if (!issetmem) + *srcptr = expand_simple_binop (GET_MODE (*srcptr), MINUS, *srcptr, saveddest, + *srcptr, 1, OPTAB_DIRECT); + *count = expand_simple_binop (GET_MODE (*count), PLUS, *count, + saveddest, *count, 1, OPTAB_DIRECT); + /* We copied at most size + prolog_size. */ + if (*min_size > (unsigned HOST_WIDE_INT)(size + prolog_size)) + *min_size = (*min_size - size) & ~(unsigned HOST_WIDE_INT)(size - 1); + else + *min_size = 0; + + /* Our loops always round down the bock size, but for dispatch to library + we need precise value. */ + if (dynamic_check) + *count = expand_simple_binop (GET_MODE (*count), AND, *count, + GEN_INT (-size), *count, 1, OPTAB_DIRECT); + } + else + { + gcc_assert (prolog_size == 0); + /* Decrease count, so we won't end up copying last word twice. */ + if (!CONST_INT_P (*count)) + *count = expand_simple_binop (GET_MODE (*count), PLUS, *count, + constm1_rtx, *count, 1, OPTAB_DIRECT); + else + *count = GEN_INT ((UINTVAL (*count) - 1) & ~(unsigned HOST_WIDE_INT)(size - 1)); + if (*min_size) + *min_size = (*min_size - 1) & ~(unsigned HOST_WIDE_INT)(size - 1); } - gcc_assert (desired_alignment <= 8); } -/* Set enough from DST to align DST known to by aligned by ALIGN to - DESIRED_ALIGN. ALIGN_BYTES is how many bytes need to be stored. */ + +/* This function is like the previous one, except here we know how many bytes + need to be copied. That allows us to update alignment not only of DST, which + is returned, but also of SRC, which is passed as a pointer for that + reason. */ static rtx -expand_constant_setmem_prologue (rtx dst, rtx destreg, rtx value, - int desired_align, int align_bytes) +expand_set_or_movmem_constant_prologue (rtx dst, rtx *srcp, rtx destreg, + rtx srcreg, rtx value, rtx vec_value, + int desired_align, int align_bytes, + bool issetmem) { - int off = 0; + rtx src = NULL; rtx orig_dst = dst; - if (align_bytes & 1) - { - dst = adjust_automodify_address_nv (dst, QImode, destreg, 0); - off = 1; - emit_insn (gen_strset (destreg, dst, - gen_lowpart (QImode, value))); - } - if (align_bytes & 2) + rtx orig_src = NULL; + int piece_size = 1; + int copied_bytes = 0; + + if (!issetmem) { - dst = adjust_automodify_address_nv (dst, HImode, destreg, off); - if (MEM_ALIGN (dst) < 2 * BITS_PER_UNIT) - set_mem_align (dst, 2 * BITS_PER_UNIT); - off = 2; - emit_insn (gen_strset (destreg, dst, - gen_lowpart (HImode, value))); + gcc_assert (srcp != NULL); + src = *srcp; + orig_src = src; } - if (align_bytes & 4) + + for (piece_size = 1; + piece_size <= desired_align && copied_bytes < align_bytes; + piece_size <<= 1) { - dst = adjust_automodify_address_nv (dst, SImode, destreg, off); - if (MEM_ALIGN (dst) < 4 * BITS_PER_UNIT) - set_mem_align (dst, 4 * BITS_PER_UNIT); - off = 4; - emit_insn (gen_strset (destreg, dst, - gen_lowpart (SImode, value))); + if (align_bytes & piece_size) + { + if (issetmem) + { + if (vec_value && piece_size > GET_MODE_SIZE (GET_MODE (value))) + dst = emit_memset (dst, destreg, vec_value, piece_size); + else + dst = emit_memset (dst, destreg, value, piece_size); + } + else + dst = emit_memmov (dst, &src, destreg, srcreg, piece_size); + copied_bytes += piece_size; + } } - dst = adjust_automodify_address_nv (dst, BLKmode, destreg, off); if (MEM_ALIGN (dst) < (unsigned int) desired_align * BITS_PER_UNIT) set_mem_align (dst, desired_align * BITS_PER_UNIT); if (MEM_SIZE_KNOWN_P (orig_dst)) set_mem_size (dst, MEM_SIZE (orig_dst) - align_bytes); + + if (!issetmem) + { + int src_align_bytes = get_mem_align_offset (src, desired_align + * BITS_PER_UNIT); + if (src_align_bytes >= 0) + src_align_bytes = desired_align - src_align_bytes; + if (src_align_bytes >= 0) + { + unsigned int src_align; + for (src_align = desired_align; src_align >= 2; src_align >>= 1) + { + if ((src_align_bytes & (src_align - 1)) + == (align_bytes & (src_align - 1))) + break; + } + if (src_align > (unsigned int) desired_align) + src_align = desired_align; + if (MEM_ALIGN (src) < src_align * BITS_PER_UNIT) + set_mem_align (src, src_align * BITS_PER_UNIT); + } + if (MEM_SIZE_KNOWN_P (orig_src)) + set_mem_size (src, MEM_SIZE (orig_src) - align_bytes); + *srcp = src; + } + return dst; } -/* Given COUNT and EXPECTED_SIZE, decide on codegen of string operation. */ -static enum stringop_alg -decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, bool memset, - int *dynamic_check, bool *noalign) +/* Return true if ALG can be used in current context. + Assume we expand memset if MEMSET is true. */ +static bool +alg_usable_p (enum stringop_alg alg, bool memset) { - const struct stringop_algs * algs; - bool optimize_for_speed; + if (alg == no_stringop) + return false; + if (alg == vector_loop) + return TARGET_SSE || TARGET_AVX; /* Algorithms using the rep prefix want at least edi and ecx; additionally, memset wants eax and memcpy wants esi. Don't consider such algorithms if the user has appropriated those registers for their own purposes. */ - bool rep_prefix_usable = !(fixed_regs[CX_REG] || fixed_regs[DI_REG] - || (memset - ? fixed_regs[AX_REG] : fixed_regs[SI_REG])); - *noalign = false; + if (alg == rep_prefix_1_byte + || alg == rep_prefix_4_byte + || alg == rep_prefix_8_byte) + return !(fixed_regs[CX_REG] || fixed_regs[DI_REG] + || (memset ? fixed_regs[AX_REG] : fixed_regs[SI_REG])); + return true; +} -#define ALG_USABLE_P(alg) (rep_prefix_usable \ - || (alg != rep_prefix_1_byte \ - && alg != rep_prefix_4_byte \ - && alg != rep_prefix_8_byte)) +/* Given COUNT and EXPECTED_SIZE, decide on codegen of string operation. */ +static enum stringop_alg +decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, + unsigned HOST_WIDE_INT min_size, unsigned HOST_WIDE_INT max_size, + bool memset, bool zero_memset, int *dynamic_check, bool *noalign) +{ + const struct stringop_algs * algs; + bool optimize_for_speed; + int max = -1; const struct processor_costs *cost; + int i; + bool any_alg_usable_p = false; + + *noalign = false; + *dynamic_check = -1; /* Even if the string operation call is cold, we still might spend a lot of time processing large blocks. */ if (optimize_function_for_size_p (cfun) || (optimize_insn_for_size_p () - && expected_size != -1 && expected_size < 256)) + && (max_size < 256 + || (expected_size != -1 && expected_size < 256)))) optimize_for_speed = false; else optimize_for_speed = true; cost = optimize_for_speed ? ix86_cost : &ix86_size_cost; - - *dynamic_check = -1; if (memset) algs = &cost->memset[TARGET_64BIT != 0]; else algs = &cost->memcpy[TARGET_64BIT != 0]; - if (ix86_stringop_alg != no_stringop && ALG_USABLE_P (ix86_stringop_alg)) + + /* See maximal size for user defined algorithm. */ + for (i = 0; i < MAX_STRINGOP_ALGS; i++) + { + enum stringop_alg candidate = algs->size[i].alg; + bool usable = alg_usable_p (candidate, memset); + any_alg_usable_p |= usable; + + if (candidate != libcall && candidate && usable) + max = algs->size[i].max; + } + + /* If expected size is not known but max size is small enough + so inline version is a win, set expected size into + the range. */ + if (max > 1 && (unsigned HOST_WIDE_INT)max >= max_size && expected_size == -1) + expected_size = min_size / 2 + max_size / 2; + + /* If user specified the algorithm, honnor it if possible. */ + if (ix86_stringop_alg != no_stringop + && alg_usable_p (ix86_stringop_alg, memset)) return ix86_stringop_alg; /* rep; movq or rep; movl is the smallest variant. */ else if (!optimize_for_speed) { - if (!count || (count & 3)) - return rep_prefix_usable ? rep_prefix_1_byte : loop_1_byte; + *noalign = true; + if (!count || (count & 3) || (memset && !zero_memset)) + return alg_usable_p (rep_prefix_1_byte, memset) + ? rep_prefix_1_byte : loop_1_byte; else - return rep_prefix_usable ? rep_prefix_4_byte : loop; + return alg_usable_p (rep_prefix_4_byte, memset) + ? rep_prefix_4_byte : loop; } - /* Very tiny blocks are best handled via the loop, REP is expensive to setup. - */ + /* Very tiny blocks are best handled via the loop, REP is expensive to + setup. */ else if (expected_size != -1 && expected_size < 4) return loop_1_byte; else if (expected_size != -1) { - unsigned int i; enum stringop_alg alg = libcall; + bool alg_noalign = false; for (i = 0; i < MAX_STRINGOP_ALGS; i++) { /* We get here if the algorithms that were not libcall-based @@ -22910,8 +23348,11 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, bool memset, { enum stringop_alg candidate = algs->size[i].alg; - if (candidate != libcall && ALG_USABLE_P (candidate)) - alg = candidate; + if (candidate != libcall && alg_usable_p (candidate, memset)) + { + alg = candidate; + alg_noalign = algs->size[i].noalign; + } /* Honor TARGET_INLINE_ALL_STRINGOPS by picking last non-libcall inline algorithm. */ if (TARGET_INLINE_ALL_STRINGOPS) @@ -22920,17 +23361,19 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, bool memset, but we are still forced to inline, run the heuristic below that will pick code for medium sized blocks. */ if (alg != libcall) - return alg; + { + *noalign = alg_noalign; + return alg; + } break; } - else if (ALG_USABLE_P (candidate)) + else if (alg_usable_p (candidate, memset)) { *noalign = algs->size[i].noalign; return candidate; } } } - gcc_assert (TARGET_INLINE_ALL_STRINGOPS || !rep_prefix_usable); } /* When asked to inline the call anyway, try to pick meaningful choice. We look for maximal size of block that is faster to copy by hand and @@ -22940,22 +23383,11 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, bool memset, If this turns out to be bad, we might simply specify the preferred choice in ix86_costs. */ if ((TARGET_INLINE_ALL_STRINGOPS || TARGET_INLINE_STRINGOPS_DYNAMICALLY) - && (algs->unknown_size == libcall || !ALG_USABLE_P (algs->unknown_size))) + && (algs->unknown_size == libcall + || !alg_usable_p (algs->unknown_size, memset))) { - int max = -1; enum stringop_alg alg; - int i; - bool any_alg_usable_p = true; - for (i = 0; i < MAX_STRINGOP_ALGS; i++) - { - enum stringop_alg candidate = algs->size[i].alg; - any_alg_usable_p = any_alg_usable_p && ALG_USABLE_P (candidate); - - if (candidate != libcall && candidate - && ALG_USABLE_P (candidate)) - max = algs->size[i].max; - } /* If there aren't any usable algorithms, then recursing on smaller sizes isn't going to find anything. Just return the simple byte-at-a-time copy loop. */ @@ -22968,15 +23400,16 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, bool memset, } if (max == -1) max = 4096; - alg = decide_alg (count, max / 2, memset, dynamic_check, noalign); + alg = decide_alg (count, max / 2, min_size, max_size, memset, + zero_memset, dynamic_check, noalign); gcc_assert (*dynamic_check == -1); gcc_assert (alg != libcall); if (TARGET_INLINE_STRINGOPS_DYNAMICALLY) *dynamic_check = max; return alg; } - return ALG_USABLE_P (algs->unknown_size) ? algs->unknown_size : libcall; -#undef ALG_USABLE_P + return (alg_usable_p (algs->unknown_size, memset) + ? algs->unknown_size : libcall); } /* Decide on alignment. We know that the operand is already aligned to ALIGN @@ -23013,341 +23446,6 @@ decide_alignment (int align, return desired_align; } -/* Expand string move (memcpy) operation. Use i386 string operations - when profitable. expand_setmem contains similar code. The code - depends upon architecture, block size and alignment, but always has - the same overall structure: - - 1) Prologue guard: Conditional that jumps up to epilogues for small - blocks that can be handled by epilogue alone. This is faster - but also needed for correctness, since prologue assume the block - is larger than the desired alignment. - - Optional dynamic check for size and libcall for large - blocks is emitted here too, with -minline-stringops-dynamically. - - 2) Prologue: copy first few bytes in order to get destination - aligned to DESIRED_ALIGN. It is emitted only when ALIGN is less - than DESIRED_ALIGN and up to DESIRED_ALIGN - ALIGN bytes can be - copied. We emit either a jump tree on power of two sized - blocks, or a byte loop. - - 3) Main body: the copying loop itself, copying in SIZE_NEEDED chunks - with specified algorithm. - - 4) Epilogue: code copying tail of the block that is too small to be - handled by main body (or up to size guarded by prologue guard). */ - -bool -ix86_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp, - rtx expected_align_exp, rtx expected_size_exp) -{ - rtx destreg; - rtx srcreg; - rtx label = NULL; - rtx tmp; - rtx jump_around_label = NULL; - HOST_WIDE_INT align = 1; - unsigned HOST_WIDE_INT count = 0; - HOST_WIDE_INT expected_size = -1; - int size_needed = 0, epilogue_size_needed; - int desired_align = 0, align_bytes = 0; - enum stringop_alg alg; - int dynamic_check; - bool need_zero_guard = false; - bool noalign; - enum machine_mode move_mode = VOIDmode; - int unroll_factor = 1; - - if (CONST_INT_P (align_exp)) - align = INTVAL (align_exp); - /* i386 can do misaligned access on reasonably increased cost. */ - if (CONST_INT_P (expected_align_exp) - && INTVAL (expected_align_exp) > align) - align = INTVAL (expected_align_exp); - /* ALIGN is the minimum of destination and source alignment, but we care here - just about destination alignment. */ - else if (MEM_ALIGN (dst) > (unsigned HOST_WIDE_INT) align * BITS_PER_UNIT) - align = MEM_ALIGN (dst) / BITS_PER_UNIT; - - if (CONST_INT_P (count_exp)) - count = expected_size = INTVAL (count_exp); - if (CONST_INT_P (expected_size_exp) && count == 0) - expected_size = INTVAL (expected_size_exp); - - /* Make sure we don't need to care about overflow later on. */ - if (count > ((unsigned HOST_WIDE_INT) 1 << 30)) - return false; - - /* Step 0: Decide on preferred algorithm, desired alignment and - size of chunks to be copied by main loop. */ - alg = decide_alg (count, expected_size, false, &dynamic_check, &noalign); - if (alg == libcall) - return false; - gcc_assert (alg != no_stringop); - - if (!count) - count_exp = copy_to_mode_reg (GET_MODE (count_exp), count_exp); - destreg = ix86_copy_addr_to_reg (XEXP (dst, 0)); - srcreg = ix86_copy_addr_to_reg (XEXP (src, 0)); - - unroll_factor = 1; - move_mode = word_mode; - switch (alg) - { - case libcall: - case no_stringop: - case last_alg: - gcc_unreachable (); - case loop_1_byte: - need_zero_guard = true; - move_mode = QImode; - break; - case loop: - need_zero_guard = true; - break; - case unrolled_loop: - need_zero_guard = true; - unroll_factor = (TARGET_64BIT ? 4 : 2); - break; - case vector_loop: - need_zero_guard = true; - unroll_factor = 4; - /* Find the widest supported mode. */ - move_mode = word_mode; - while (optab_handler (mov_optab, GET_MODE_WIDER_MODE (move_mode)) - != CODE_FOR_nothing) - move_mode = GET_MODE_WIDER_MODE (move_mode); - - /* Find the corresponding vector mode with the same size as MOVE_MODE. - MOVE_MODE is an integer mode at the moment (SI, DI, TI, etc.). */ - if (GET_MODE_SIZE (move_mode) > GET_MODE_SIZE (word_mode)) - { - int nunits = GET_MODE_SIZE (move_mode) / GET_MODE_SIZE (word_mode); - move_mode = mode_for_vector (word_mode, nunits); - if (optab_handler (mov_optab, move_mode) == CODE_FOR_nothing) - move_mode = word_mode; - } - gcc_assert (optab_handler (mov_optab, move_mode) != CODE_FOR_nothing); - break; - case rep_prefix_8_byte: - move_mode = DImode; - break; - case rep_prefix_4_byte: - move_mode = SImode; - break; - case rep_prefix_1_byte: - move_mode = QImode; - break; - } - size_needed = GET_MODE_SIZE (move_mode) * unroll_factor; - epilogue_size_needed = size_needed; - - desired_align = decide_alignment (align, alg, expected_size, move_mode); - if (!TARGET_ALIGN_STRINGOPS || noalign) - align = desired_align; - - /* Step 1: Prologue guard. */ - - /* Alignment code needs count to be in register. */ - if (CONST_INT_P (count_exp) && desired_align > align) - { - if (INTVAL (count_exp) > desired_align - && INTVAL (count_exp) > size_needed) - { - align_bytes - = get_mem_align_offset (dst, desired_align * BITS_PER_UNIT); - if (align_bytes <= 0) - align_bytes = 0; - else - align_bytes = desired_align - align_bytes; - } - if (align_bytes == 0) - count_exp = force_reg (counter_mode (count_exp), count_exp); - } - gcc_assert (desired_align >= 1 && align >= 1); - - /* Ensure that alignment prologue won't copy past end of block. */ - if (size_needed > 1 || (desired_align > 1 && desired_align > align)) - { - epilogue_size_needed = MAX (size_needed - 1, desired_align - align); - /* Epilogue always copies COUNT_EXP & EPILOGUE_SIZE_NEEDED bytes. - Make sure it is power of 2. */ - epilogue_size_needed = 1 << (floor_log2 (epilogue_size_needed) + 1); - - if (count) - { - if (count < (unsigned HOST_WIDE_INT)epilogue_size_needed) - { - /* If main algorithm works on QImode, no epilogue is needed. - For small sizes just don't align anything. */ - if (size_needed == 1) - desired_align = align; - else - goto epilogue; - } - } - else - { - label = gen_label_rtx (); - emit_cmp_and_jump_insns (count_exp, - GEN_INT (epilogue_size_needed), - LTU, 0, counter_mode (count_exp), 1, label); - if (expected_size == -1 || expected_size < epilogue_size_needed) - predict_jump (REG_BR_PROB_BASE * 60 / 100); - else - predict_jump (REG_BR_PROB_BASE * 20 / 100); - } - } - - /* Emit code to decide on runtime whether library call or inline should be - used. */ - if (dynamic_check != -1) - { - if (CONST_INT_P (count_exp)) - { - if (UINTVAL (count_exp) >= (unsigned HOST_WIDE_INT)dynamic_check) - { - emit_block_move_via_libcall (dst, src, count_exp, false); - count_exp = const0_rtx; - goto epilogue; - } - } - else - { - rtx hot_label = gen_label_rtx (); - jump_around_label = gen_label_rtx (); - emit_cmp_and_jump_insns (count_exp, GEN_INT (dynamic_check - 1), - LEU, 0, GET_MODE (count_exp), 1, hot_label); - predict_jump (REG_BR_PROB_BASE * 90 / 100); - emit_block_move_via_libcall (dst, src, count_exp, false); - emit_jump (jump_around_label); - emit_label (hot_label); - } - } - - /* Step 2: Alignment prologue. */ - - if (desired_align > align) - { - if (align_bytes == 0) - { - /* Except for the first move in epilogue, we no longer know - constant offset in aliasing info. It don't seems to worth - the pain to maintain it for the first move, so throw away - the info early. */ - src = change_address (src, BLKmode, srcreg); - dst = change_address (dst, BLKmode, destreg); - dst = expand_movmem_prologue (dst, src, destreg, srcreg, count_exp, align, - desired_align); - } - else - { - /* If we know how many bytes need to be stored before dst is - sufficiently aligned, maintain aliasing info accurately. */ - dst = expand_constant_movmem_prologue (dst, &src, destreg, srcreg, - desired_align, align_bytes); - count_exp = plus_constant (counter_mode (count_exp), - count_exp, -align_bytes); - count -= align_bytes; - } - if (need_zero_guard - && (count < (unsigned HOST_WIDE_INT) size_needed - || (align_bytes == 0 - && count < ((unsigned HOST_WIDE_INT) size_needed - + desired_align - align)))) - { - /* It is possible that we copied enough so the main loop will not - execute. */ - gcc_assert (size_needed > 1); - if (label == NULL_RTX) - label = gen_label_rtx (); - emit_cmp_and_jump_insns (count_exp, - GEN_INT (size_needed), - LTU, 0, counter_mode (count_exp), 1, label); - if (expected_size == -1 - || expected_size < (desired_align - align) / 2 + size_needed) - predict_jump (REG_BR_PROB_BASE * 20 / 100); - else - predict_jump (REG_BR_PROB_BASE * 60 / 100); - } - } - if (label && size_needed == 1) - { - emit_label (label); - LABEL_NUSES (label) = 1; - label = NULL; - epilogue_size_needed = 1; - } - else if (label == NULL_RTX) - epilogue_size_needed = size_needed; - - /* Step 3: Main loop. */ - - switch (alg) - { - case libcall: - case no_stringop: - case last_alg: - gcc_unreachable (); - case loop_1_byte: - case loop: - case unrolled_loop: - case vector_loop: - expand_set_or_movmem_via_loop (dst, src, destreg, srcreg, NULL, - count_exp, move_mode, unroll_factor, - expected_size); - break; - case rep_prefix_8_byte: - case rep_prefix_4_byte: - case rep_prefix_1_byte: - expand_movmem_via_rep_mov (dst, src, destreg, srcreg, count_exp, - move_mode); - break; - } - /* Adjust properly the offset of src and dest memory for aliasing. */ - if (CONST_INT_P (count_exp)) - { - src = adjust_automodify_address_nv (src, BLKmode, srcreg, - (count / size_needed) * size_needed); - dst = adjust_automodify_address_nv (dst, BLKmode, destreg, - (count / size_needed) * size_needed); - } - else - { - src = change_address (src, BLKmode, srcreg); - dst = change_address (dst, BLKmode, destreg); - } - - /* Step 4: Epilogue to copy the remaining bytes. */ - epilogue: - if (label) - { - /* When the main loop is done, COUNT_EXP might hold original count, - while we want to copy only COUNT_EXP & SIZE_NEEDED bytes. - Epilogue code will actually copy COUNT_EXP & EPILOGUE_SIZE_NEEDED - bytes. Compensate if needed. */ - - if (size_needed < epilogue_size_needed) - { - tmp = - expand_simple_binop (counter_mode (count_exp), AND, count_exp, - GEN_INT (size_needed - 1), count_exp, 1, - OPTAB_DIRECT); - if (tmp != count_exp) - emit_move_insn (count_exp, tmp); - } - emit_label (label); - LABEL_NUSES (label) = 1; - } - - if (count_exp != const0_rtx && epilogue_size_needed > 1) - expand_movmem_epilogue (dst, src, destreg, srcreg, count_exp, - epilogue_size_needed); - if (jump_around_label) - emit_label (jump_around_label); - return true; -} /* Helper function for memcpy. For QImode value 0xXY produce 0xXYXYXYXY of wide specified by MODE. This is essentially @@ -23361,9 +23459,9 @@ promote_duplicated_reg (enum machine_mode mode, rtx val) rtx tmp; int nops = mode == DImode ? 3 : 2; - gcc_assert (mode == SImode || mode == DImode); + gcc_assert (mode == SImode || mode == DImode || val == const0_rtx); if (val == const0_rtx) - return copy_to_mode_reg (mode, const0_rtx); + return copy_to_mode_reg (mode, CONST0_RTX (mode)); if (CONST_INT_P (val)) { HOST_WIDE_INT v = INTVAL (val) & 255; @@ -23425,7 +23523,8 @@ promote_duplicated_reg (enum machine_mode mode, rtx val) be needed by main loop copying SIZE_NEEDED chunks and prologue getting alignment from ALIGN to DESIRED_ALIGN. */ static rtx -promote_duplicated_reg_to_size (rtx val, int size_needed, int desired_align, int align) +promote_duplicated_reg_to_size (rtx val, int size_needed, int desired_align, + int align) { rtx promoted_val; @@ -23442,14 +23541,55 @@ promote_duplicated_reg_to_size (rtx val, int size_needed, int desired_align, int return promoted_val; } -/* Expand string clear operation (bzero). Use i386 string operations when - profitable. See expand_movmem comment for explanation of individual - steps performed. */ -bool -ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp, - rtx expected_align_exp, rtx expected_size_exp) +/* Expand string move (memcpy) ot store (memset) operation. Use i386 string + operations when profitable. The code depends upon architecture, block size + and alignment, but always has one of the following overall structures: + + Aligned move sequence: + + 1) Prologue guard: Conditional that jumps up to epilogues for small + blocks that can be handled by epilogue alone. This is faster + but also needed for correctness, since prologue assume the block + is larger than the desired alignment. + + Optional dynamic check for size and libcall for large + blocks is emitted here too, with -minline-stringops-dynamically. + + 2) Prologue: copy first few bytes in order to get destination + aligned to DESIRED_ALIGN. It is emitted only when ALIGN is less + than DESIRED_ALIGN and up to DESIRED_ALIGN - ALIGN bytes can be + copied. We emit either a jump tree on power of two sized + blocks, or a byte loop. + + 3) Main body: the copying loop itself, copying in SIZE_NEEDED chunks + with specified algorithm. + + 4) Epilogue: code copying tail of the block that is too small to be + handled by main body (or up to size guarded by prologue guard). + + Misaligned move sequence + + 1) missaligned move prologue/epilogue containing: + a) Prologue handling small memory blocks and jumping to done_label + (skipped if blocks are known to be large enough) + b) Signle move copying first DESIRED_ALIGN-ALIGN bytes if alignment is + needed by single possibly misaligned move + (skipped if alignment is not needed) + c) Copy of last SIZE_NEEDED bytes by possibly misaligned moves + + 2) Zero size guard dispatching to done_label, if needed + + 3) dispatch to library call, if needed, + + 3) Main body: the copying loop itself, copying in SIZE_NEEDED chunks + with specified algorithm. */ +static bool +ix86_expand_set_or_movmem (rtx dst, rtx src, rtx count_exp, rtx val_exp, + rtx align_exp, rtx expected_align_exp, + rtx expected_size_exp, bool issetmem) { rtx destreg; + rtx srcreg = NULL; rtx label = NULL; rtx tmp; rtx jump_around_label = NULL; @@ -23460,12 +23600,17 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp, int desired_align = 0, align_bytes = 0; enum stringop_alg alg; rtx promoted_val = NULL; + rtx vec_promoted_val = NULL; bool force_loopy_epilogue = false; int dynamic_check; bool need_zero_guard = false; bool noalign; enum machine_mode move_mode = VOIDmode; - int unroll_factor; + int unroll_factor = 1; + /* TODO: Once vlaue ranges are available, fill in proper data. */ + unsigned HOST_WIDE_INT min_size = 0; + unsigned HOST_WIDE_INT max_size = -1; + bool misaligned_prologue_used = false; if (CONST_INT_P (align_exp)) align = INTVAL (align_exp); @@ -23473,8 +23618,14 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp, if (CONST_INT_P (expected_align_exp) && INTVAL (expected_align_exp) > align) align = INTVAL (expected_align_exp); + /* ALIGN is the minimum of destination and source alignment, but we care here + just about destination alignment. */ + else if (!issetmem + && MEM_ALIGN (dst) > (unsigned HOST_WIDE_INT) align * BITS_PER_UNIT) + align = MEM_ALIGN (dst) / BITS_PER_UNIT; + if (CONST_INT_P (count_exp)) - count = expected_size = INTVAL (count_exp); + min_size = max_size = count = expected_size = INTVAL (count_exp); if (CONST_INT_P (expected_size_exp) && count == 0) expected_size = INTVAL (expected_size_exp); @@ -23484,31 +23635,62 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp, /* Step 0: Decide on preferred algorithm, desired alignment and size of chunks to be copied by main loop. */ - - alg = decide_alg (count, expected_size, true, &dynamic_check, &noalign); + alg = decide_alg (count, expected_size, min_size, max_size, issetmem, + issetmem && val_exp == const0_rtx, + &dynamic_check, &noalign); if (alg == libcall) return false; gcc_assert (alg != no_stringop); + /* For now vector-version of memset is generated only for memory zeroing, as + creating of promoted vector value is very cheap in this case. */ + if (issetmem && alg == vector_loop && val_exp != const0_rtx) + alg = unrolled_loop; + if (!count) - count_exp = copy_to_mode_reg (counter_mode (count_exp), count_exp); + count_exp = copy_to_mode_reg (GET_MODE (count_exp), count_exp); destreg = ix86_copy_addr_to_reg (XEXP (dst, 0)); + if (!issetmem) + srcreg = ix86_copy_addr_to_reg (XEXP (src, 0)); - move_mode = word_mode; unroll_factor = 1; + move_mode = word_mode; switch (alg) { case libcall: case no_stringop: case last_alg: gcc_unreachable (); + case loop_1_byte: + need_zero_guard = true; + move_mode = QImode; + break; case loop: need_zero_guard = true; break; - case vector_loop: case unrolled_loop: need_zero_guard = true; + unroll_factor = (TARGET_64BIT ? 4 : 2); + break; + case vector_loop: + need_zero_guard = true; unroll_factor = 4; + /* Find the widest supported mode. */ + move_mode = word_mode; + while (optab_handler (mov_optab, GET_MODE_WIDER_MODE (move_mode)) + != CODE_FOR_nothing) + move_mode = GET_MODE_WIDER_MODE (move_mode); + + /* Find the corresponding vector mode with the same size as MOVE_MODE. + MOVE_MODE is an integer mode at the moment (SI, DI, TI, etc.). */ + if (GET_MODE_SIZE (move_mode) > GET_MODE_SIZE (word_mode)) + { + int nunits = GET_MODE_SIZE (move_mode) / GET_MODE_SIZE (word_mode); + move_mode = mode_for_vector (word_mode, nunits); + if (optab_handler (mov_optab, move_mode) == CODE_FOR_nothing) + move_mode = word_mode; + } + gcc_assert (optab_handler (mov_optab, move_mode) != CODE_FOR_nothing); break; case rep_prefix_8_byte: move_mode = DImode; @@ -23519,10 +23701,6 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp, case rep_prefix_1_byte: move_mode = QImode; break; - case loop_1_byte: - need_zero_guard = true; - move_mode = QImode; - break; } size_needed = GET_MODE_SIZE (move_mode) * unroll_factor; epilogue_size_needed = size_needed; @@ -23547,24 +23725,81 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp, align_bytes = desired_align - align_bytes; } if (align_bytes == 0) - { - enum machine_mode mode = SImode; - if (TARGET_64BIT && (count & ~0xffffffff)) - mode = DImode; - count_exp = force_reg (mode, count_exp); - } + count_exp = force_reg (counter_mode (count_exp), count_exp); } + gcc_assert (desired_align >= 1 && align >= 1); + + /* Misaligned move sequences handles both prologues and epilogues at once. + Default code generation results in smaller code for large alignments and + also avoids redundant job when sizes are known precisely. */ + misaligned_prologue_used = (TARGET_MISALIGNED_MOVE_STRING_PROLOGUES + && MAX (desired_align, epilogue_size_needed) <= 32 + && ((desired_align > align && !align_bytes) + || (!count && epilogue_size_needed > 1))); + /* Do the cheap promotion to allow better CSE across the main loop and epilogue (ie one load of the big constant in the - front of all code. */ - if (CONST_INT_P (val_exp)) - promoted_val = promote_duplicated_reg_to_size (val_exp, size_needed, - desired_align, align); + front of all code. + For now the misaligned move sequences do not have fast path + without broadcasting. */ + if (issetmem && ((CONST_INT_P (val_exp) || misaligned_prologue_used))) + { + if (alg == vector_loop) + { + gcc_assert (val_exp == const0_rtx); + vec_promoted_val = promote_duplicated_reg (move_mode, val_exp); + promoted_val = promote_duplicated_reg_to_size (val_exp, + GET_MODE_SIZE (word_mode), + desired_align, align); + } + else + { + promoted_val = promote_duplicated_reg_to_size (val_exp, size_needed, + desired_align, align); + } + } + /* Misaligned move sequences handles both prologues and epilogues at once. + Default code generation results in smaller code for large alignments and + also avoids redundant job when sizes are known precisely. */ + if (misaligned_prologue_used) + { + /* Misaligned move prologue handled small blocks by itself. */ + misaligned_prologue_used = true; + expand_set_or_movmem_prologue_epilogue_by_misaligned_moves + (dst, src, &destreg, &srcreg, + move_mode, promoted_val, vec_promoted_val, + &count_exp, + &jump_around_label, + desired_align < align + ? MAX (desired_align, epilogue_size_needed) : epilogue_size_needed, + desired_align, align, &min_size, dynamic_check, issetmem); + if (!issetmem) + src = change_address (src, BLKmode, srcreg); + dst = change_address (dst, BLKmode, destreg); + set_mem_align (dst, desired_align * BITS_PER_UNIT); + epilogue_size_needed = 0; + if (need_zero_guard && !min_size) + { + /* It is possible that we copied enough so the main loop will not + execute. */ + gcc_assert (size_needed > 1); + if (jump_around_label == NULL_RTX) + jump_around_label = gen_label_rtx (); + emit_cmp_and_jump_insns (count_exp, + GEN_INT (size_needed), + LTU, 0, counter_mode (count_exp), 1, jump_around_label); + if (expected_size == -1 + || expected_size < (desired_align - align) / 2 + size_needed) + predict_jump (REG_BR_PROB_BASE * 20 / 100); + else + predict_jump (REG_BR_PROB_BASE * 60 / 100); + } + } /* Ensure that alignment prologue won't copy past end of block. */ - if (size_needed > 1 || (desired_align > 1 && desired_align > align)) + else if (size_needed > 1 || (desired_align > 1 && desired_align > align)) { epilogue_size_needed = MAX (size_needed - 1, desired_align - align); - /* Epilogue always copies COUNT_EXP & (EPILOGUE_SIZE_NEEDED - 1) bytes. + /* Epilogue always copies COUNT_EXP & EPILOGUE_SIZE_NEEDED bytes. Make sure it is power of 2. */ epilogue_size_needed = 1 << (floor_log2 (epilogue_size_needed) + 1); @@ -23572,8 +23807,8 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp, promoting mode. This mean that if the promoted VAL is not constant, we might not use it in the epilogue and have to use byte loop variant. */ - if (epilogue_size_needed > 2 && !promoted_val) - force_loopy_epilogue = true; + if (issetmem && epilogue_size_needed > 2 && !promoted_val) + force_loopy_epilogue = true; if (count) { if (count < (unsigned HOST_WIDE_INT)epilogue_size_needed) @@ -23586,61 +23821,96 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp, goto epilogue; } } - else + else if (min_size < (unsigned HOST_WIDE_INT)epilogue_size_needed) { + gcc_assert (max_size >= (unsigned HOST_WIDE_INT)epilogue_size_needed); label = gen_label_rtx (); emit_cmp_and_jump_insns (count_exp, GEN_INT (epilogue_size_needed), LTU, 0, counter_mode (count_exp), 1, label); - if (expected_size == -1 || expected_size <= epilogue_size_needed) + if (expected_size == -1 || expected_size < epilogue_size_needed) predict_jump (REG_BR_PROB_BASE * 60 / 100); else predict_jump (REG_BR_PROB_BASE * 20 / 100); } } + + /* Emit code to decide on runtime whether library call or inline should be + used. */ if (dynamic_check != -1) { - rtx hot_label = gen_label_rtx (); - jump_around_label = gen_label_rtx (); - emit_cmp_and_jump_insns (count_exp, GEN_INT (dynamic_check - 1), - LEU, 0, counter_mode (count_exp), 1, hot_label); - predict_jump (REG_BR_PROB_BASE * 90 / 100); - set_storage_via_libcall (dst, count_exp, val_exp, false); - emit_jump (jump_around_label); - emit_label (hot_label); + if (!issetmem && CONST_INT_P (count_exp)) + { + if (UINTVAL (count_exp) >= (unsigned HOST_WIDE_INT)dynamic_check) + { + emit_block_move_via_libcall (dst, src, count_exp, false); + count_exp = const0_rtx; + goto epilogue; + } + } + else + { + rtx hot_label = gen_label_rtx (); + jump_around_label = gen_label_rtx (); + emit_cmp_and_jump_insns (count_exp, GEN_INT (dynamic_check - 1), + LEU, 0, GET_MODE (count_exp), 1, hot_label); + predict_jump (REG_BR_PROB_BASE * 90 / 100); + if (issetmem) + set_storage_via_libcall (dst, count_exp, val_exp, false); + else + emit_block_move_via_libcall (dst, src, count_exp, false); + emit_jump (jump_around_label); + emit_label (hot_label); + } } /* Step 2: Alignment prologue. */ - /* Do the expensive promotion once we branched off the small blocks. */ - if (!promoted_val) + if (issetmem && !promoted_val) promoted_val = promote_duplicated_reg_to_size (val_exp, size_needed, desired_align, align); - gcc_assert (desired_align >= 1 && align >= 1); - if (desired_align > align) + if (desired_align > align && !misaligned_prologue_used) { if (align_bytes == 0) { - /* Except for the first move in epilogue, we no longer know + /* Except for the first move in prologue, we no longer know constant offset in aliasing info. It don't seems to worth the pain to maintain it for the first move, so throw away the info early. */ dst = change_address (dst, BLKmode, destreg); - expand_setmem_prologue (dst, destreg, promoted_val, count_exp, align, - desired_align); + if (!issetmem) + src = change_address (src, BLKmode, srcreg); + dst = expand_set_or_movmem_prologue (dst, src, destreg, srcreg, + promoted_val, vec_promoted_val, + count_exp, align, desired_align, + issetmem); + /* At most desired_align - align bytes are copied. */ + if (min_size < (unsigned)(desired_align - align)) + min_size = 0; + else + min_size -= desired_align - align; } else { /* If we know how many bytes need to be stored before dst is sufficiently aligned, maintain aliasing info accurately. */ - dst = expand_constant_setmem_prologue (dst, destreg, promoted_val, - desired_align, align_bytes); + dst = expand_set_or_movmem_constant_prologue (dst, &src, destreg, + srcreg, + promoted_val, + vec_promoted_val, + desired_align, + align_bytes, + issetmem); + count_exp = plus_constant (counter_mode (count_exp), count_exp, -align_bytes); count -= align_bytes; + min_size -= align_bytes; + max_size -= align_bytes; } if (need_zero_guard + && !min_size && (count < (unsigned HOST_WIDE_INT) size_needed || (align_bytes == 0 && count < ((unsigned HOST_WIDE_INT) size_needed @@ -23666,10 +23936,11 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp, emit_label (label); LABEL_NUSES (label) = 1; label = NULL; - promoted_val = val_exp; epilogue_size_needed = 1; + if (issetmem) + promoted_val = val_exp; } - else if (label == NULL_RTX) + else if (label == NULL_RTX && !misaligned_prologue_used) epilogue_size_needed = size_needed; /* Step 3: Main loop. */ @@ -23682,38 +23953,45 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp, gcc_unreachable (); case loop_1_byte: case loop: - case vector_loop: case unrolled_loop: - expand_set_or_movmem_via_loop (dst, NULL, destreg, NULL, promoted_val, + expand_set_or_movmem_via_loop (dst, src, destreg, srcreg, promoted_val, count_exp, move_mode, unroll_factor, - expected_size); + expected_size, issetmem); break; - case rep_prefix_8_byte: - expand_setmem_via_rep_stos (dst, destreg, promoted_val, count_exp, - DImode, val_exp); + case vector_loop: + expand_set_or_movmem_via_loop (dst, src, destreg, srcreg, + vec_promoted_val, count_exp, move_mode, + unroll_factor, expected_size, issetmem); break; + case rep_prefix_8_byte: case rep_prefix_4_byte: - expand_setmem_via_rep_stos (dst, destreg, promoted_val, count_exp, - SImode, val_exp); - break; case rep_prefix_1_byte: - expand_setmem_via_rep_stos (dst, destreg, promoted_val, count_exp, - QImode, val_exp); + expand_set_or_movmem_via_rep (dst, src, destreg, srcreg, promoted_val, + val_exp, count_exp, move_mode, issetmem); break; } /* Adjust properly the offset of src and dest memory for aliasing. */ if (CONST_INT_P (count_exp)) - dst = adjust_automodify_address_nv (dst, BLKmode, destreg, - (count / size_needed) * size_needed); + { + if (!issetmem) + src = adjust_automodify_address_nv (src, BLKmode, srcreg, + (count / size_needed) * size_needed); + dst = adjust_automodify_address_nv (dst, BLKmode, destreg, + (count / size_needed) * size_needed); + } else - dst = change_address (dst, BLKmode, destreg); + { + if (!issetmem) + src = change_address (src, BLKmode, srcreg); + dst = change_address (dst, BLKmode, destreg); + } /* Step 4: Epilogue to copy the remaining bytes. */ - + epilogue: if (label) { /* When the main loop is done, COUNT_EXP might hold original count, - while we want to copy only COUNT_EXP & SIZE_NEEDED bytes. + while we want to copy only COUNT_EXP & SIZE_NEEDED bytes. Epilogue code will actually copy COUNT_EXP & EPILOGUE_SIZE_NEEDED bytes. Compensate if needed. */ @@ -23729,21 +24007,47 @@ ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp, emit_label (label); LABEL_NUSES (label) = 1; } - epilogue: + if (count_exp != const0_rtx && epilogue_size_needed > 1) { if (force_loopy_epilogue) expand_setmem_epilogue_via_loop (dst, destreg, val_exp, count_exp, epilogue_size_needed); else - expand_setmem_epilogue (dst, destreg, promoted_val, count_exp, - epilogue_size_needed); + { + if (issetmem) + expand_setmem_epilogue (dst, destreg, promoted_val, + vec_promoted_val, count_exp, + epilogue_size_needed); + else + expand_movmem_epilogue (dst, src, destreg, srcreg, count_exp, + epilogue_size_needed); + } } if (jump_around_label) emit_label (jump_around_label); return true; } +/* Wrapper for ix86_expand_set_or_movmem for memcpy case. */ +bool +ix86_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp, + rtx expected_align_exp, rtx expected_size_exp) +{ + return ix86_expand_set_or_movmem (dst, src, count_exp, NULL, align_exp, + expected_align_exp, expected_size_exp, false); +} + +/* Wrapper for ix86_expand_set_or_movmem for memset case. */ +bool +ix86_expand_setmem (rtx dst, rtx count_exp, rtx val_exp, rtx align_exp, + rtx expected_align_exp, rtx expected_size_exp) +{ + return ix86_expand_set_or_movmem (dst, NULL, count_exp, val_exp, align_exp, + expected_align_exp, expected_size_exp, true); +} + + /* Expand the appropriate insns for doing strlen if not just doing repnz; scasb @@ -24108,13 +24412,13 @@ ix86_output_call_insn (rtx insn, rtx call_op) if (SIBLING_CALL_P (insn)) { if (direct_p) - xasm = "jmp\t%P0"; + xasm = "%!jmp\t%P0"; /* SEH epilogue detection requires the indirect branch case to include REX.W. */ else if (TARGET_SEH) - xasm = "rex.W jmp %A0"; + xasm = "%!rex.W jmp %A0"; else - xasm = "jmp\t%A0"; + xasm = "%!jmp\t%A0"; output_asm_insn (xasm, &call_op); return ""; @@ -24151,9 +24455,9 @@ ix86_output_call_insn (rtx insn, rtx call_op) } if (direct_p) - xasm = "call\t%P0"; + xasm = "%!call\t%P0"; else - xasm = "call\t%A0"; + xasm = "%!call\t%A0"; output_asm_insn (xasm, &call_op); @@ -29940,7 +30244,7 @@ ix86_get_function_versions_dispatcher (void *decl) while (default_version_info != NULL) { if (is_function_default_version - (default_version_info->this_node->symbol.decl)) + (default_version_info->this_node->decl)) break; default_version_info = default_version_info->next; } @@ -29970,7 +30274,7 @@ ix86_get_function_versions_dispatcher (void *decl) struct cgraph_function_version_info *dispatcher_version_info = NULL; /* Right now, the dispatching is done via ifunc. */ - dispatch_decl = make_dispatcher_decl (default_node->symbol.decl); + dispatch_decl = make_dispatcher_decl (default_node->decl); dispatcher_node = cgraph_get_create_node (dispatch_decl); gcc_assert (dispatcher_node != NULL); @@ -29978,7 +30282,7 @@ ix86_get_function_versions_dispatcher (void *decl) dispatcher_version_info = insert_new_cgraph_node_version (dispatcher_node); dispatcher_version_info->next = default_version_info; - dispatcher_node->symbol.definition = 1; + dispatcher_node->definition = 1; /* Set the dispatcher for all the versions. */ it_v = default_version_info; @@ -29991,7 +30295,7 @@ ix86_get_function_versions_dispatcher (void *decl) else #endif { - error_at (DECL_SOURCE_LOCATION (default_node->symbol.decl), + error_at (DECL_SOURCE_LOCATION (default_node->decl), "multiversioning needs ifunc which is not supported " "on this target"); } @@ -30130,13 +30434,13 @@ ix86_generate_version_dispatcher_body (void *node_p) return node_version_info->dispatcher_resolver; /* The first version in the chain corresponds to the default version. */ - default_ver_decl = node_version_info->next->this_node->symbol.decl; + default_ver_decl = node_version_info->next->this_node->decl; /* node is going to be an alias, so remove the finalized bit. */ - node->symbol.definition = false; + node->definition = false; resolver_decl = make_resolver_func (default_ver_decl, - node->symbol.decl, &empty_bb); + node->decl, &empty_bb); node_version_info->dispatcher_resolver = resolver_decl; @@ -30153,10 +30457,10 @@ ix86_generate_version_dispatcher_body (void *node_p) not. This happens for methods in derived classes that override virtual methods in base classes but are not explicitly marked as virtual. */ - if (DECL_VINDEX (versn->symbol.decl)) + if (DECL_VINDEX (versn->decl)) sorry ("Virtual function multiversioning not supported"); - fn_ver_vec.safe_push (versn->symbol.decl); + fn_ver_vec.safe_push (versn->decl); } dispatch_function_versions (resolver_decl, &fn_ver_vec, &empty_bb); @@ -31703,8 +32007,8 @@ ix86_expand_args_builtin (const struct builtin_description *d, } else { - target = gen_reg_rtx (rmode); - real_target = simplify_gen_subreg (tmode, target, rmode, 0); + real_target = gen_reg_rtx (tmode); + target = simplify_gen_subreg (rmode, real_target, tmode, 0); } for (i = 0; i < nargs; i++) @@ -34143,6 +34447,7 @@ ix86_class_likely_spilled_p (reg_class_t rclass) case SSE_FIRST_REG: case FP_TOP_REG: case FP_SECOND_REG: + case BND_REGS: return true; default: @@ -34491,6 +34796,8 @@ ix86_hard_regno_mode_ok (int regno, enum machine_mode mode) return VALID_FP_MODE_P (mode); if (MASK_REGNO_P (regno)) return VALID_MASK_REG_MODE (mode); + if (BND_REGNO_P (regno)) + return VALID_BND_REG_MODE (mode); if (SSE_REGNO_P (regno)) { /* We implement the move patterns for all vector modes into and @@ -35304,6 +35611,10 @@ x86_order_regs_for_local_alloc (void) for (i = FIRST_MASK_REG; i <= LAST_MASK_REG; i++) reg_alloc_order [pos++] = i; + /* MPX bound registers. */ + for (i = FIRST_BND_REG; i <= LAST_BND_REG; i++) + reg_alloc_order [pos++] = i; + /* x87 registers. */ if (TARGET_SSE_MATH) for (i = FIRST_STACK_REG; i <= LAST_STACK_REG; i++) @@ -36420,8 +36731,9 @@ ix86_expand_vector_init_duplicate (bool mmx_ok, enum machine_mode mode, emit_move_insn (tmp1, gen_lowpart (SImode, val)); /* Insert the SImode value as low element of a V4SImode vector. */ - tmp2 = gen_lowpart (V4SImode, dperm.op0); + tmp2 = gen_reg_rtx (V4SImode); emit_insn (gen_vec_setv4si_0 (tmp2, CONST0_RTX (V4SImode), tmp1)); + emit_move_insn (dperm.op0, gen_lowpart (mode, tmp2)); ok = (expand_vec_perm_1 (&dperm) || expand_vec_perm_broadcast_1 (&dperm)); @@ -36451,9 +36763,10 @@ ix86_expand_vector_init_duplicate (bool mmx_ok, enum machine_mode mode, NULL_RTX, 1, OPTAB_LIB_WIDEN); val = expand_simple_binop (wsmode, IOR, val, x, x, 1, OPTAB_LIB_WIDEN); - x = gen_lowpart (wvmode, target); + x = gen_reg_rtx (wvmode); ok = ix86_expand_vector_init_duplicate (mmx_ok, wvmode, x, val); gcc_assert (ok); + emit_move_insn (target, gen_lowpart (GET_MODE (target), x)); return ok; } @@ -37328,8 +37641,9 @@ ix86_expand_vector_set (bool mmx_ok, rtx target, rtx val, int elt) else { /* For SSE1, we have to reuse the V4SF code. */ - ix86_expand_vector_set (false, gen_lowpart (V4SFmode, target), - gen_lowpart (SFmode, val), elt); + rtx t = gen_reg_rtx (V4SFmode); + ix86_expand_vector_set (false, t, gen_lowpart (SFmode, val), elt); + emit_move_insn (target, gen_lowpart (mode, t)); } return; @@ -37647,7 +37961,7 @@ ix86_expand_vector_extract (bool mmx_ok, rtx target, rtx vec, int elt) static void emit_reduc_half (rtx dest, rtx src, int i) { - rtx tem; + rtx tem, d = dest; switch (GET_MODE (src)) { case V4SFmode: @@ -37664,8 +37978,8 @@ emit_reduc_half (rtx dest, rtx src, int i) case V8HImode: case V4SImode: case V2DImode: - tem = gen_sse2_lshrv1ti3 (gen_lowpart (V1TImode, dest), - gen_lowpart (V1TImode, src), + d = gen_reg_rtx (V1TImode); + tem = gen_sse2_lshrv1ti3 (d, gen_lowpart (V1TImode, src), GEN_INT (i / 2)); break; case V8SFmode: @@ -37686,19 +38000,26 @@ emit_reduc_half (rtx dest, rtx src, int i) case V8SImode: case V4DImode: if (i == 256) - tem = gen_avx2_permv2ti (gen_lowpart (V4DImode, dest), - gen_lowpart (V4DImode, src), - gen_lowpart (V4DImode, src), - const1_rtx); + { + if (GET_MODE (dest) != V4DImode) + d = gen_reg_rtx (V4DImode); + tem = gen_avx2_permv2ti (d, gen_lowpart (V4DImode, src), + gen_lowpart (V4DImode, src), + const1_rtx); + } else - tem = gen_avx2_lshrv2ti3 (gen_lowpart (V2TImode, dest), - gen_lowpart (V2TImode, src), - GEN_INT (i / 2)); + { + d = gen_reg_rtx (V2TImode); + tem = gen_avx2_lshrv2ti3 (d, gen_lowpart (V2TImode, src), + GEN_INT (i / 2)); + } break; default: gcc_unreachable (); } emit_insn (tem); + if (d != dest) + emit_move_insn (dest, gen_lowpart (GET_MODE (dest), d)); } /* Expand a vector reduction. FN is the binary pattern to reduce; @@ -39191,6 +39512,8 @@ expand_vec_perm_blend (struct expand_vec_perm_d *d) emit_insn (gen_sse4_1_pblendvb (target, op0, op1, vperm)); else emit_insn (gen_avx2_pblendvb (target, op0, op1, vperm)); + if (target != d->target) + emit_move_insn (d->target, gen_lowpart (d->vmode, target)); return true; } @@ -39200,7 +39523,7 @@ expand_vec_perm_blend (struct expand_vec_perm_d *d) /* FALLTHRU */ do_subreg: - target = gen_lowpart (vmode, target); + target = gen_reg_rtx (vmode); op0 = gen_lowpart (vmode, op0); op1 = gen_lowpart (vmode, op1); break; @@ -39254,7 +39577,7 @@ expand_vec_perm_blend (struct expand_vec_perm_d *d) vmode = V32QImode; nelt = 32; - target = gen_lowpart (vmode, target); + target = gen_reg_rtx (vmode); op0 = gen_lowpart (vmode, op0); op1 = gen_lowpart (vmode, op1); goto finish_pblendvb; @@ -39287,6 +39610,8 @@ expand_vec_perm_blend (struct expand_vec_perm_d *d) x = gen_rtx_VEC_MERGE (vmode, op1, op0, GEN_INT (mask)); x = gen_rtx_SET (VOIDmode, target, x); emit_insn (x); + if (target != d->target) + emit_move_insn (d->target, gen_lowpart (d->vmode, target)); return true; } @@ -39392,13 +39717,17 @@ expand_vec_perm_pshufb (struct expand_vec_perm_d *d) /* Use vperm2i128 insn. The pattern uses V4DImode instead of V2TImode. */ - target = gen_lowpart (V4DImode, d->target); + target = d->target; + if (d->vmode != V4DImode) + target = gen_reg_rtx (V4DImode); op0 = gen_lowpart (V4DImode, d->op0); op1 = gen_lowpart (V4DImode, d->op1); rperm[0] = GEN_INT (((d->perm[0] & (nelt / 2)) ? 1 : 0) || ((d->perm[nelt / 2] & (nelt / 2)) ? 2 : 0)); emit_insn (gen_avx2_permv2ti (target, op0, op1, rperm[0])); + if (target != d->target) + emit_move_insn (d->target, gen_lowpart (d->vmode, target)); return true; } return false; @@ -39433,9 +39762,15 @@ expand_vec_perm_pshufb (struct expand_vec_perm_d *d) perm[i] = (d->perm[i * nelt / 4] * 4 / nelt) & 3; if (d->testing_p) return true; - return expand_vselect (gen_lowpart (V4DImode, d->target), - gen_lowpart (V4DImode, d->op0), - perm, 4, false); + target = gen_reg_rtx (V4DImode); + if (expand_vselect (target, gen_lowpart (V4DImode, d->op0), + perm, 4, false)) + { + emit_move_insn (d->target, + gen_lowpart (d->vmode, target)); + return true; + } + return false; } /* Next see if vpermd can be used. */ @@ -39487,7 +39822,9 @@ expand_vec_perm_pshufb (struct expand_vec_perm_d *d) gen_rtvec_v (GET_MODE_NUNITS (vmode), rperm)); vperm = force_reg (vmode, vperm); - target = gen_lowpart (vmode, d->target); + target = d->target; + if (d->vmode != vmode) + target = gen_reg_rtx (vmode); op0 = gen_lowpart (vmode, d->op0); if (d->one_operand_p) { @@ -39505,6 +39842,8 @@ expand_vec_perm_pshufb (struct expand_vec_perm_d *d) op1 = gen_lowpart (vmode, d->op1); emit_insn (gen_xop_pperm (target, op0, op1, vperm)); } + if (target != d->target) + emit_move_insn (d->target, gen_lowpart (d->vmode, target)); return true; } @@ -39704,7 +40043,8 @@ expand_vec_perm_palignr (struct expand_vec_perm_d *d) unsigned i, nelt = d->nelt; unsigned min, max; bool in_order, ok; - rtx shift; + rtx shift, target; + struct expand_vec_perm_d dcopy; /* Even with AVX, palignr only operates on 128-bit vectors. */ if (!TARGET_SSSE3 || GET_MODE_SIZE (d->vmode) != 16) @@ -39727,29 +40067,33 @@ expand_vec_perm_palignr (struct expand_vec_perm_d *d) if (d->testing_p) return true; + dcopy = *d; shift = GEN_INT (min * GET_MODE_BITSIZE (GET_MODE_INNER (d->vmode))); - emit_insn (gen_ssse3_palignrti (gen_lowpart (TImode, d->target), - gen_lowpart (TImode, d->op1), + target = gen_reg_rtx (TImode); + emit_insn (gen_ssse3_palignrti (target, gen_lowpart (TImode, d->op1), gen_lowpart (TImode, d->op0), shift)); - d->op0 = d->op1 = d->target; - d->one_operand_p = true; + dcopy.op0 = dcopy.op1 = gen_lowpart (d->vmode, target); + dcopy.one_operand_p = true; in_order = true; for (i = 0; i < nelt; ++i) { - unsigned e = d->perm[i] - min; + unsigned e = dcopy.perm[i] - min; if (e != i) in_order = false; - d->perm[i] = e; + dcopy.perm[i] = e; } /* Test for the degenerate case where the alignment by itself produces the desired permutation. */ if (in_order) - return true; + { + emit_move_insn (d->target, dcopy.op0); + return true; + } - ok = expand_vec_perm_1 (d); + ok = expand_vec_perm_1 (&dcopy); gcc_assert (ok); return ok; @@ -40003,10 +40347,10 @@ expand_vec_perm_interleave2 (struct expand_vec_perm_d *d) else dfinal.perm[i] = e; } - dfinal.op0 = gen_reg_rtx (dfinal.vmode); + dremap.target = gen_reg_rtx (dremap.vmode); + dfinal.op0 = gen_lowpart (dfinal.vmode, dremap.target); dfinal.op1 = dfinal.op0; dfinal.one_operand_p = true; - dremap.target = dfinal.op0; /* Test if the final remap can be done with a single insn. For V4SFmode or V4SImode this *will* succeed. For V8HImode or V16QImode it may not. */ @@ -40023,7 +40367,6 @@ expand_vec_perm_interleave2 (struct expand_vec_perm_d *d) if (dremap.vmode != dfinal.vmode) { - dremap.target = gen_lowpart (dremap.vmode, dremap.target); dremap.op0 = gen_lowpart (dremap.vmode, dremap.op0); dremap.op1 = gen_lowpart (dremap.vmode, dremap.op1); } @@ -40474,8 +40817,12 @@ expand_vec_perm_pshufb2 (struct expand_vec_perm_d *d) op = gen_lowpart (V16QImode, d->op1); emit_insn (gen_ssse3_pshufbv16qi3 (h, op, vperm)); - op = gen_lowpart (V16QImode, d->target); + op = d->target; + if (d->vmode != V16QImode) + op = gen_reg_rtx (V16QImode); emit_insn (gen_iorv16qi3 (op, l, h)); + if (op != d->target) + emit_move_insn (d->target, gen_lowpart (d->vmode, op)); return true; } @@ -40541,8 +40888,12 @@ expand_vec_perm_vpshufb2_vpermq (struct expand_vec_perm_d *d) op = gen_lowpart (V32QImode, d->op0); emit_insn (gen_avx2_pshufbv32qi3 (l, op, vperm)); - op = gen_lowpart (V32QImode, d->target); + op = d->target; + if (d->vmode != V32QImode) + op = gen_reg_rtx (V32QImode); emit_insn (gen_iorv32qi3 (op, l, gen_lowpart (V32QImode, hp))); + if (op != d->target) + emit_move_insn (d->target, gen_lowpart (d->vmode, op)); return true; } @@ -40618,10 +40969,11 @@ expand_vec_perm_vpshufb2_vpermq_even_odd (struct expand_vec_perm_d *d) emit_insn (gen_iorv32qi3 (ior, l, h)); /* Permute the V4DImode quarters using { 0, 2, 1, 3 } permutation. */ - op = gen_lowpart (V4DImode, d->target); + op = gen_reg_rtx (V4DImode); ior = gen_lowpart (V4DImode, ior); emit_insn (gen_avx2_permv4di_1 (op, ior, const0_rtx, const2_rtx, const1_rtx, GEN_INT (3))); + emit_move_insn (d->target, gen_lowpart (d->vmode, op)); return true; } @@ -40632,7 +40984,7 @@ expand_vec_perm_vpshufb2_vpermq_even_odd (struct expand_vec_perm_d *d) static bool expand_vec_perm_even_odd_1 (struct expand_vec_perm_d *d, unsigned odd) { - rtx t1, t2, t3; + rtx t1, t2, t3, t4, t5; switch (d->vmode) { @@ -40744,10 +41096,17 @@ expand_vec_perm_even_odd_1 (struct expand_vec_perm_d *d, unsigned odd) { struct expand_vec_perm_d d_copy = *d; d_copy.vmode = V4DFmode; - d_copy.target = gen_lowpart (V4DFmode, d->target); + d_copy.target = gen_reg_rtx (V4DFmode); d_copy.op0 = gen_lowpart (V4DFmode, d->op0); d_copy.op1 = gen_lowpart (V4DFmode, d->op1); - return expand_vec_perm_even_odd_1 (&d_copy, odd); + if (expand_vec_perm_even_odd_1 (&d_copy, odd)) + { + if (!d->testing_p) + emit_move_insn (d->target, + gen_lowpart (V4DImode, d_copy.target)); + return true; + } + return false; } t1 = gen_reg_rtx (V4DImode); @@ -40770,44 +41129,51 @@ expand_vec_perm_even_odd_1 (struct expand_vec_perm_d *d, unsigned odd) { struct expand_vec_perm_d d_copy = *d; d_copy.vmode = V8SFmode; - d_copy.target = gen_lowpart (V8SFmode, d->target); + d_copy.target = gen_reg_rtx (V8SFmode); d_copy.op0 = gen_lowpart (V8SFmode, d->op0); d_copy.op1 = gen_lowpart (V8SFmode, d->op1); - return expand_vec_perm_even_odd_1 (&d_copy, odd); + if (expand_vec_perm_even_odd_1 (&d_copy, odd)) + { + if (!d->testing_p) + emit_move_insn (d->target, + gen_lowpart (V8SImode, d_copy.target)); + return true; + } + return false; } t1 = gen_reg_rtx (V8SImode); t2 = gen_reg_rtx (V8SImode); + t3 = gen_reg_rtx (V4DImode); + t4 = gen_reg_rtx (V4DImode); + t5 = gen_reg_rtx (V4DImode); /* Shuffle the lanes around into { 0 1 2 3 8 9 a b } and { 4 5 6 7 c d e f }. */ - emit_insn (gen_avx2_permv2ti (gen_lowpart (V4DImode, t1), - gen_lowpart (V4DImode, d->op0), + emit_insn (gen_avx2_permv2ti (t3, gen_lowpart (V4DImode, d->op0), gen_lowpart (V4DImode, d->op1), GEN_INT (0x20))); - emit_insn (gen_avx2_permv2ti (gen_lowpart (V4DImode, t2), - gen_lowpart (V4DImode, d->op0), + emit_insn (gen_avx2_permv2ti (t4, gen_lowpart (V4DImode, d->op0), gen_lowpart (V4DImode, d->op1), GEN_INT (0x31))); /* Swap the 2nd and 3rd position in each lane into { 0 2 1 3 8 a 9 b } and { 4 6 5 7 c e d f }. */ - emit_insn (gen_avx2_pshufdv3 (t1, t1, + emit_insn (gen_avx2_pshufdv3 (t1, gen_lowpart (V8SImode, t3), GEN_INT (2 * 4 + 1 * 16 + 3 * 64))); - emit_insn (gen_avx2_pshufdv3 (t2, t2, + emit_insn (gen_avx2_pshufdv3 (t2, gen_lowpart (V8SImode, t4), GEN_INT (2 * 4 + 1 * 16 + 3 * 64))); /* Now an vpunpck[lh]qdq will produce { 0 2 4 6 8 a c e } resp. { 1 3 5 7 9 b d f }. */ if (odd) - t3 = gen_avx2_interleave_highv4di (gen_lowpart (V4DImode, d->target), - gen_lowpart (V4DImode, t1), + t3 = gen_avx2_interleave_highv4di (t5, gen_lowpart (V4DImode, t1), gen_lowpart (V4DImode, t2)); else - t3 = gen_avx2_interleave_lowv4di (gen_lowpart (V4DImode, d->target), - gen_lowpart (V4DImode, t1), + t3 = gen_avx2_interleave_lowv4di (t5, gen_lowpart (V4DImode, t1), gen_lowpart (V4DImode, t2)); emit_insn (t3); + emit_move_insn (d->target, gen_lowpart (V8SImode, t5)); break; default: @@ -40845,7 +41211,7 @@ expand_vec_perm_broadcast_1 (struct expand_vec_perm_d *d) unsigned elt = d->perm[0], nelt2 = d->nelt / 2; enum machine_mode vmode = d->vmode; unsigned char perm2[4]; - rtx op0 = d->op0; + rtx op0 = d->op0, dest; bool ok; switch (vmode) @@ -40891,9 +41257,11 @@ expand_vec_perm_broadcast_1 (struct expand_vec_perm_d *d) while (vmode != V4SImode); memset (perm2, elt, 4); - ok = expand_vselect (gen_lowpart (V4SImode, d->target), op0, perm2, 4, - d->testing_p); + dest = gen_reg_rtx (V4SImode); + ok = expand_vselect (dest, op0, perm2, 4, d->testing_p); gcc_assert (ok); + if (!d->testing_p) + emit_move_insn (d->target, gen_lowpart (d->vmode, dest)); return true; case V32QImode: @@ -41035,8 +41403,12 @@ expand_vec_perm_vpshufb4_vpermq2 (struct expand_vec_perm_d *d) } gcc_assert (l[0] && l[1]); - op = gen_lowpart (V32QImode, d->target); + op = d->target; + if (d->vmode != V32QImode) + op = gen_reg_rtx (V32QImode); emit_insn (gen_iorv32qi3 (op, l[0], l[1])); + if (op != d->target) + emit_move_insn (d->target, gen_lowpart (d->vmode, op)); return true; } @@ -41604,7 +41976,9 @@ ix86_expand_mul_widen_hilo (rtx dest, rtx op1, rtx op2, op1, op2, NULL_RTX, uns_p, OPTAB_DIRECT); gcc_assert (t1 && t2); - ix86_expand_vec_interleave (gen_lowpart (mode, dest), t1, t2, high_p); + t3 = gen_reg_rtx (mode); + ix86_expand_vec_interleave (t3, t1, t2, high_p); + emit_move_insn (dest, gen_lowpart (wmode, t3)); break; case V16QImode: @@ -41625,14 +41999,14 @@ ix86_expand_mul_widen_hilo (rtx dest, rtx op1, rtx op2, void ix86_expand_sse2_mulv4si3 (rtx op0, rtx op1, rtx op2) { - rtx res_1, res_2; + rtx res_1, res_2, res_3, res_4; res_1 = gen_reg_rtx (V4SImode); res_2 = gen_reg_rtx (V4SImode); - ix86_expand_mul_widen_evenodd (gen_lowpart (V2DImode, res_1), - op1, op2, true, false); - ix86_expand_mul_widen_evenodd (gen_lowpart (V2DImode, res_2), - op1, op2, true, true); + res_3 = gen_reg_rtx (V2DImode); + res_4 = gen_reg_rtx (V2DImode); + ix86_expand_mul_widen_evenodd (res_3, op1, op2, true, false); + ix86_expand_mul_widen_evenodd (res_4, op1, op2, true, true); /* Move the results in element 2 down to element 1; we don't care what goes in elements 2 and 3. Then we can merge the parts @@ -41646,9 +42020,11 @@ ix86_expand_sse2_mulv4si3 (rtx op0, rtx op1, rtx op2) In both cases the cost of the reformatting stall was too high and the overall sequence slower. */ - emit_insn (gen_sse2_pshufd_1 (res_1, res_1, const0_rtx, const2_rtx, + emit_insn (gen_sse2_pshufd_1 (res_1, gen_lowpart (V4SImode, res_3), + const0_rtx, const2_rtx, const0_rtx, const0_rtx)); - emit_insn (gen_sse2_pshufd_1 (res_2, res_2, const0_rtx, const2_rtx, + emit_insn (gen_sse2_pshufd_1 (res_2, gen_lowpart (V4SImode, res_4), + const0_rtx, const2_rtx, const0_rtx, const0_rtx)); res_1 = emit_insn (gen_vec_interleave_lowv4si (op0, res_1, res_2)); @@ -41737,6 +42113,68 @@ ix86_expand_sse2_mulvxdi3 (rtx op0, rtx op1, rtx op2) gen_rtx_MULT (mode, op1, op2)); } +/* Return 1 if control tansfer instruction INSN + should be encoded with bnd prefix. + If insn is NULL then return 1 when control + transfer instructions should be prefixed with + bnd by default for current function. */ + +bool +ix86_bnd_prefixed_insn_p (rtx insn ATTRIBUTE_UNUSED) +{ + return false; +} + +/* Calculate integer abs() using only SSE2 instructions. */ + +void +ix86_expand_sse2_abs (rtx target, rtx input) +{ + enum machine_mode mode = GET_MODE (target); + rtx tmp0, tmp1, x; + + switch (mode) + { + /* For 32-bit signed integer X, the best way to calculate the absolute + value of X is (((signed) X >> (W-1)) ^ X) - ((signed) X >> (W-1)). */ + case V4SImode: + tmp0 = expand_simple_binop (mode, ASHIFTRT, input, + GEN_INT (GET_MODE_BITSIZE + (GET_MODE_INNER (mode)) - 1), + NULL, 0, OPTAB_DIRECT); + tmp1 = expand_simple_binop (mode, XOR, tmp0, input, + NULL, 0, OPTAB_DIRECT); + x = expand_simple_binop (mode, MINUS, tmp1, tmp0, + target, 0, OPTAB_DIRECT); + break; + + /* For 16-bit signed integer X, the best way to calculate the absolute + value of X is max (X, -X), as SSE2 provides the PMAXSW insn. */ + case V8HImode: + tmp0 = expand_unop (mode, neg_optab, input, NULL_RTX, 0); + + x = expand_simple_binop (mode, SMAX, tmp0, input, + target, 0, OPTAB_DIRECT); + break; + + /* For 8-bit signed integer X, the best way to calculate the absolute + value of X is min ((unsigned char) X, (unsigned char) (-X)), + as SSE2 provides the PMINUB insn. */ + case V16QImode: + tmp0 = expand_unop (mode, neg_optab, input, NULL_RTX, 0); + + x = expand_simple_binop (V16QImode, UMIN, tmp0, input, + target, 0, OPTAB_DIRECT); + break; + + default: + gcc_unreachable (); + } + + if (x != target) + emit_move_insn (target, x); +} + /* Expand an insert into a vector register through pinsr insn. Return true if successful. */ @@ -41805,12 +42243,17 @@ ix86_expand_pinsr (rtx *operands) return false; } - dst = gen_lowpart (dstmode, dst); + rtx d = dst; + if (GET_MODE (dst) != dstmode) + d = gen_reg_rtx (dstmode); src = gen_lowpart (srcmode, src); pos /= size; - emit_insn (pinsr (dst, dst, src, GEN_INT (1 << pos))); + emit_insn (pinsr (d, gen_lowpart (dstmode, dst), src, + GEN_INT (1 << pos))); + if (d != dst) + emit_move_insn (dst, gen_lowpart (GET_MODE (dst), d)); return true; } diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index 63e49032748..c979ee534a8 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -63,14 +63,14 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #define TARGET_AVX_P(x) TARGET_ISA_AVX_P(x) #define TARGET_AVX2 TARGET_ISA_AVX2 #define TARGET_AVX2_P(x) TARGET_ISA_AVX2_P(x) -#define TARGET_AVX512F TARGET_ISA_AVX512F -#define TARGET_AVX512F_P(x) TARGET_ISA_AVX512F_P(x) -#define TARGET_AVX512PF TARGET_ISA_AVX512PF -#define TARGET_AVX512PF_P(x) TARGET_ISA_AVX512PF_P(x) -#define TARGET_AVX512ER TARGET_ISA_AVX512ER -#define TARGET_AVX512ER_P(x) TARGET_ISA_AVX512ER_P(x) -#define TARGET_AVX512CD TARGET_ISA_AVX512CD -#define TARGET_AVX512CD_P(x) TARGET_ISA_AVX512CD_P(x) +#define TARGET_AVX512F TARGET_ISA_AVX512F +#define TARGET_AVX512F_P(x) TARGET_ISA_AVX512F_P(x) +#define TARGET_AVX512PF TARGET_ISA_AVX512PF +#define TARGET_AVX512PF_P(x) TARGET_ISA_AVX512PF_P(x) +#define TARGET_AVX512ER TARGET_ISA_AVX512ER +#define TARGET_AVX512ER_P(x) TARGET_ISA_AVX512ER_P(x) +#define TARGET_AVX512CD TARGET_ISA_AVX512CD +#define TARGET_AVX512CD_P(x) TARGET_ISA_AVX512CD_P(x) #define TARGET_FMA TARGET_ISA_FMA #define TARGET_FMA_P(x) TARGET_ISA_FMA_P(x) #define TARGET_SSE4A TARGET_ISA_SSE4A @@ -104,16 +104,16 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #define TARGET_AES_P(x) TARGET_ISA_AES_P(x) #define TARGET_PCLMUL TARGET_ISA_PCLMUL #define TARGET_PCLMUL_P(x) TARGET_ISA_PCLMUL_P(x) -#define TARGET_CMPXCHG16B TARGET_ISA_CX16 -#define TARGET_CMPXCHG16B_P(x) TARGET_ISA_CX16_P(x) +#define TARGET_CMPXCHG16B TARGET_ISA_CX16 +#define TARGET_CMPXCHG16B_P(x) TARGET_ISA_CX16_P(x) #define TARGET_FSGSBASE TARGET_ISA_FSGSBASE #define TARGET_FSGSBASE_P(x) TARGET_ISA_FSGSBASE_P(x) #define TARGET_RDRND TARGET_ISA_RDRND #define TARGET_RDRND_P(x) TARGET_ISA_RDRND_P(x) #define TARGET_F16C TARGET_ISA_F16C #define TARGET_F16C_P(x) TARGET_ISA_F16C_P(x) -#define TARGET_RTM TARGET_ISA_RTM -#define TARGET_RTM_P(x) TARGET_ISA_RTM_P(x) +#define TARGET_RTM TARGET_ISA_RTM +#define TARGET_RTM_P(x) TARGET_ISA_RTM_P(x) #define TARGET_HLE TARGET_ISA_HLE #define TARGET_HLE_P(x) TARGET_ISA_HLE_P(x) #define TARGET_RDSEED TARGET_ISA_RDSEED @@ -128,6 +128,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #define TARGET_XSAVE_P(x) TARGET_ISA_XSAVE_P(x) #define TARGET_XSAVEOPT TARGET_ISA_XSAVEOPT #define TARGET_XSAVEOPT_P(x) TARGET_ISA_XSAVEOPT_P(x) +#define TARGET_MPX TARGET_ISA_MPX +#define TARGET_MPX_P(x) TARGET_ISA_MPX_P(x) #define TARGET_LP64 TARGET_ABI_64 #define TARGET_LP64_P(x) TARGET_ABI_64_P(x) @@ -350,6 +352,8 @@ extern unsigned char ix86_tune_features[X86_TUNE_LAST]; #define TARGET_PROMOTE_QImode ix86_tune_features[X86_TUNE_PROMOTE_QIMODE] #define TARGET_FAST_PREFIX ix86_tune_features[X86_TUNE_FAST_PREFIX] #define TARGET_SINGLE_STRINGOP ix86_tune_features[X86_TUNE_SINGLE_STRINGOP] +#define TARGET_MISALIGNED_MOVE_STRING_PROLOGUES_EPILOGUES \ + ix86_tune_features[TARGET_MISALIGNED_MOVE_STRING_PROLOGUES] #define TARGET_QIMODE_MATH ix86_tune_features[X86_TUNE_QIMODE_MATH] #define TARGET_HIMODE_MATH ix86_tune_features[X86_TUNE_HIMODE_MATH] #define TARGET_PROMOTE_QI_REGS ix86_tune_features[X86_TUNE_PROMOTE_QI_REGS] @@ -943,7 +947,7 @@ enum target_cpu_default eliminated during reloading in favor of either the stack or frame pointer. */ -#define FIRST_PSEUDO_REGISTER 77 +#define FIRST_PSEUDO_REGISTER 81 /* Number of hardware registers that go into the DWARF-2 unwind info. If not defined, equals FIRST_PSEUDO_REGISTER. */ @@ -975,7 +979,9 @@ enum target_cpu_default /*xmm24,xmm25,xmm26,xmm27,xmm28,xmm29,xmm30,xmm31*/ \ 0, 0, 0, 0, 0, 0, 0, 0, \ /* k0, k1, k2, k3, k4, k5, k6, k7*/ \ - 0, 0, 0, 0, 0, 0, 0, 0 } + 0, 0, 0, 0, 0, 0, 0, 0, \ +/* b0, b1, b2, b3*/ \ + 0, 0, 0, 0 } /* 1 for registers not available across function calls. These must include the FIXED_REGISTERS and also any @@ -1009,7 +1015,9 @@ enum target_cpu_default /*xmm24,xmm25,xmm26,xmm27,xmm28,xmm29,xmm30,xmm31*/ \ 6, 6, 6, 6, 6, 6, 6, 6, \ /* k0, k1, k2, k3, k4, k5, k6, k7*/ \ - 1, 1, 1, 1, 1, 1, 1, 1 } + 1, 1, 1, 1, 1, 1, 1, 1, \ +/* b0, b1, b2, b3*/ \ + 1, 1, 1, 1 } /* Order in which to allocate registers. Each register must be listed once, even those in FIXED_REGISTERS. List frame pointer @@ -1025,7 +1033,8 @@ enum target_cpu_default 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, \ 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, \ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, \ - 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76 } + 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, \ + 78, 79, 80 } /* ADJUST_REG_ALLOC_ORDER is a macro which permits reg_alloc_order to be rearranged based on a particular function. When using sse math, @@ -1047,6 +1056,7 @@ enum target_cpu_default #define HARD_REGNO_NREGS(REGNO, MODE) \ (STACK_REGNO_P (REGNO) || SSE_REGNO_P (REGNO) || MMX_REGNO_P (REGNO) \ + || BND_REGNO_P (REGNO) \ ? (COMPLEX_MODE_P (MODE) ? 2 : 1) \ : ((MODE) == XFmode \ ? (TARGET_64BIT ? 2 : 3) \ @@ -1096,6 +1106,9 @@ enum target_cpu_default || (MODE) == V2SImode || (MODE) == SImode \ || (MODE) == V4HImode || (MODE) == V8QImode) +#define VALID_BND_REG_MODE(MODE) \ + (TARGET_64BIT ? (MODE) == BND64mode : (MODE) == BND32mode) + #define VALID_DFP_MODE_P(MODE) \ ((MODE) == SDmode || (MODE) == DDmode || (MODE) == TDmode) @@ -1202,6 +1215,9 @@ enum target_cpu_default #define FIRST_MASK_REG (LAST_EXT_REX_SSE_REG + 1) /*69*/ #define LAST_MASK_REG (FIRST_MASK_REG + 7) /*76*/ +#define FIRST_BND_REG (LAST_MASK_REG + 1) /*77*/ +#define LAST_BND_REG (FIRST_BND_REG + 3) /*80*/ + /* Override this in other tm.h files to cope with various OS lossage requiring a frame pointer. */ #ifndef SUBTARGET_FRAME_POINTER_REQUIRED @@ -1282,6 +1298,7 @@ enum reg_class SSE_FIRST_REG, SSE_REGS, EVEX_SSE_REGS, + BND_REGS, ALL_SSE_REGS, MMX_REGS, FP_TOP_SSE_REGS, @@ -1339,6 +1356,7 @@ enum reg_class "SSE_FIRST_REG", \ "SSE_REGS", \ "EVEX_SSE_REGS", \ + "BND_REGS", \ "ALL_SSE_REGS", \ "MMX_REGS", \ "FP_TOP_SSE_REGS", \ @@ -1358,37 +1376,38 @@ enum reg_class TARGET_CONDITIONAL_REGISTER_USAGE. */ #define REG_CLASS_CONTENTS \ -{ { 0x00, 0x0, 0x0 }, \ - { 0x01, 0x0, 0x0 }, /* AREG */ \ - { 0x02, 0x0, 0x0 }, /* DREG */ \ - { 0x04, 0x0, 0x0 }, /* CREG */ \ - { 0x08, 0x0, 0x0 }, /* BREG */ \ - { 0x10, 0x0, 0x0 }, /* SIREG */ \ - { 0x20, 0x0, 0x0 }, /* DIREG */ \ - { 0x03, 0x0, 0x0 }, /* AD_REGS */ \ - { 0x0f, 0x0, 0x0 }, /* Q_REGS */ \ - { 0x1100f0, 0x1fe0, 0x0 }, /* NON_Q_REGS */ \ - { 0x7f, 0x1fe0, 0x0 }, /* INDEX_REGS */ \ - { 0x1100ff, 0x0, 0x0 }, /* LEGACY_REGS */ \ - { 0x07, 0x0, 0x0 }, /* CLOBBERED_REGS */ \ - { 0x1100ff, 0x1fe0, 0x0 }, /* GENERAL_REGS */ \ - { 0x100, 0x0, 0x0 }, /* FP_TOP_REG */ \ - { 0x0200, 0x0, 0x0 }, /* FP_SECOND_REG */ \ - { 0xff00, 0x0, 0x0 }, /* FLOAT_REGS */ \ - { 0x200000, 0x0, 0x0 }, /* SSE_FIRST_REG */ \ -{ 0x1fe00000, 0x1fe000, 0x0 }, /* SSE_REGS */ \ - { 0x0,0xffe00000, 0x1f }, /* EVEX_SSE_REGS */ \ -{ 0x1fe00000,0xffffe000, 0x1f }, /* ALL_SSE_REGS */ \ -{ 0xe0000000, 0x1f, 0x0 }, /* MMX_REGS */ \ -{ 0x1fe00100,0xffffe000, 0x1f }, /* FP_TOP_SSE_REG */ \ -{ 0x1fe00200,0xffffe000, 0x1f }, /* FP_SECOND_SSE_REG */ \ -{ 0x1fe0ff00,0xffffe000, 0x1f }, /* FLOAT_SSE_REGS */ \ -{ 0x11ffff, 0x1fe0, 0x0 }, /* FLOAT_INT_REGS */ \ -{ 0x1ff100ff,0xffffffe0, 0x1f }, /* INT_SSE_REGS */ \ -{ 0x1ff1ffff,0xffffffe0, 0x1f }, /* FLOAT_INT_SSE_REGS */ \ - { 0x0, 0x0,0x1fc0 }, /* MASK_EVEX_REGS */ \ - { 0x0, 0x0,0x1fe0 }, /* MASK_REGS */ \ -{ 0xffffffff,0xffffffff,0x1fff } \ +{ { 0x00, 0x0, 0x0 }, \ + { 0x01, 0x0, 0x0 }, /* AREG */ \ + { 0x02, 0x0, 0x0 }, /* DREG */ \ + { 0x04, 0x0, 0x0 }, /* CREG */ \ + { 0x08, 0x0, 0x0 }, /* BREG */ \ + { 0x10, 0x0, 0x0 }, /* SIREG */ \ + { 0x20, 0x0, 0x0 }, /* DIREG */ \ + { 0x03, 0x0, 0x0 }, /* AD_REGS */ \ + { 0x0f, 0x0, 0x0 }, /* Q_REGS */ \ + { 0x1100f0, 0x1fe0, 0x0 }, /* NON_Q_REGS */ \ + { 0x7f, 0x1fe0, 0x0 }, /* INDEX_REGS */ \ + { 0x1100ff, 0x0, 0x0 }, /* LEGACY_REGS */ \ + { 0x07, 0x0, 0x0 }, /* CLOBBERED_REGS */ \ + { 0x1100ff, 0x1fe0, 0x0 }, /* GENERAL_REGS */ \ + { 0x100, 0x0, 0x0 }, /* FP_TOP_REG */ \ + { 0x0200, 0x0, 0x0 }, /* FP_SECOND_REG */ \ + { 0xff00, 0x0, 0x0 }, /* FLOAT_REGS */ \ + { 0x200000, 0x0, 0x0 }, /* SSE_FIRST_REG */ \ +{ 0x1fe00000, 0x1fe000, 0x0 }, /* SSE_REGS */ \ + { 0x0,0xffe00000, 0x1f }, /* EVEX_SSE_REGS */ \ + { 0x0, 0x0,0x1e000 }, /* BND_REGS */ \ +{ 0x1fe00000,0xffffe000, 0x1f }, /* ALL_SSE_REGS */ \ +{ 0xe0000000, 0x1f, 0x0 }, /* MMX_REGS */ \ +{ 0x1fe00100,0xffffe000, 0x1f }, /* FP_TOP_SSE_REG */ \ +{ 0x1fe00200,0xffffe000, 0x1f }, /* FP_SECOND_SSE_REG */ \ +{ 0x1fe0ff00,0xffffe000, 0x1f }, /* FLOAT_SSE_REGS */ \ +{ 0x11ffff, 0x1fe0, 0x0 }, /* FLOAT_INT_REGS */ \ +{ 0x1ff100ff,0xffffffe0, 0x1f }, /* INT_SSE_REGS */ \ +{ 0x1ff1ffff,0xffffffe0, 0x1f }, /* FLOAT_INT_SSE_REGS */ \ + { 0x0, 0x0, 0x1fc0 }, /* MASK_EVEX_REGS */ \ + { 0x0, 0x0, 0x1fe0 }, /* MASK_REGS */ \ +{ 0xffffffff,0xffffffff, 0x1fff } \ } /* The same information, inverted: @@ -1464,6 +1483,9 @@ enum reg_class #define CC_REG_P(X) (REG_P (X) && CC_REGNO_P (REGNO (X))) #define CC_REGNO_P(X) ((X) == FLAGS_REG || (X) == FPSR_REG) +#define BND_REGNO_P(N) IN_RANGE ((N), FIRST_BND_REG, LAST_BND_REG) +#define ANY_BND_REG_P(X) (REG_P (X) && BND_REGNO_P (REGNO (X))) + /* The class value for index registers, and the one for base regs. */ #define INDEX_REG_CLASS INDEX_REGS @@ -1908,6 +1930,9 @@ do { \ between pointers and any other objects of this machine mode. */ #define Pmode (ix86_pmode == PMODE_DI ? DImode : SImode) +/* Specify the machine mode that bounds have. */ +#define BNDmode (ix86_pmode == PMODE_DI ? BND64mode : BND32mode) + /* A C expression whose value is zero if pointers that need to be extended from being `POINTER_SIZE' bits wide to `Pmode' are sign-extended and greater then zero if they are zero-extended and less then zero if the @@ -2018,7 +2043,8 @@ do { \ "xmm20", "xmm21", "xmm22", "xmm23", \ "xmm24", "xmm25", "xmm26", "xmm27", \ "xmm28", "xmm29", "xmm30", "xmm31", \ - "k0", "k1", "k2", "k3", "k4", "k5", "k6", "k7" } + "k0", "k1", "k2", "k3", "k4", "k5", "k6", "k7", \ + "bnd0", "bnd1", "bnd2", "bnd3" } #define REGISTER_NAMES HI_REGISTER_NAMES diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index ad79589c0c7..c7ec0c1385b 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -63,6 +63,7 @@ ;; ~ -- print "i" if TARGET_AVX2, "f" otherwise. ;; @ -- print a segment register of thread base pointer load ;; ^ -- print addr32 prefix if TARGET_64BIT and Pmode != word_mode +;; ! -- print MPX prefix for jxx/call/ret instructions if required. (define_c_enum "unspec" [ ;; Relocation specifiers @@ -178,6 +179,16 @@ ;; For BMI2 support UNSPEC_PDEP UNSPEC_PEXT + + UNSPEC_BNDMK + UNSPEC_BNDMK_ADDR + UNSPEC_BNDSTX + UNSPEC_BNDLDX + UNSPEC_BNDLDX_ADDR + UNSPEC_BNDCL + UNSPEC_BNDCU + UNSPEC_BNDCN + UNSPEC_MPX_FENCE ]) (define_c_enum "unspecv" [ @@ -336,6 +347,8 @@ (MASK5_REG 74) (MASK6_REG 75) (MASK7_REG 76) + (BND0_REG 77) + (BND1_REG 78) ]) ;; Insns whose names begin with "x86_" are emitted by gen_FOO calls @@ -369,7 +382,8 @@ ssecvt,ssecvt1,sseicvt,sseins, sseshuf,sseshuf1,ssemuladd,sse4arg, lwp,mskmov,msklog, - mmx,mmxmov,mmxadd,mmxmul,mmxcmp,mmxcvt,mmxshft" + mmx,mmxmov,mmxadd,mmxmul,mmxcmp,mmxcvt,mmxshft, + mpxmov,mpxmk,mpxchk,mpxld,mpxst" (const_string "other")) ;; Main data type used by the insn @@ -398,7 +412,8 @@ ;; The (bounding maximum) length of an instruction immediate. (define_attr "length_immediate" "" (cond [(eq_attr "type" "incdec,setcc,icmov,str,lea,other,multi,idiv,leave, - bitmanip,imulx,msklog,mskmov") + bitmanip,imulx,msklog,mskmov,mpxmk,mpxmov,mpxchk, + mpxld,mpxst") (const_int 0) (eq_attr "unit" "i387,sse,mmx") (const_int 0) @@ -453,13 +468,17 @@ (const_int 0) (and (eq_attr "unit" "sse") (eq_attr "mode" "SF,DF")) (const_int 1) + (and (eq_attr "type" "ibr,call,callv") + (match_test "ix86_bnd_prefixed_insn_p (insn)")) + (const_int 1) ] (const_int 0))) ;; Set when 0f opcode prefix is used. (define_attr "prefix_0f" "" (if_then_else - (ior (eq_attr "type" "imovx,setcc,icmov,bitmanip,msklog,mskmov") + (ior (eq_attr "type" "imovx,setcc,icmov,bitmanip,msklog,mskmov, + mpxmk,mpxmov,mpxchk,mpxld,mpxst") (eq_attr "unit" "sse,mmx")) (const_int 1) (const_int 0))) @@ -562,12 +581,19 @@ ] (const_int 1))) +;; When this attribute is set, calculate total insn length from +;; length_nobnd attribute, prefixed with eventual bnd prefix byte +(define_attr "length_nobnd" "" (const_int 0)) + ;; The (bounding maximum) length of an instruction in bytes. ;; ??? fistp and frndint are in fact fldcw/{fistp,frndint}/fldcw sequences. ;; Later we may want to split them and compute proper length as for ;; other insns. (define_attr "length" "" - (cond [(eq_attr "type" "other,multi,fistp,frndint") + (cond [(eq_attr "length_nobnd" "!0") + (plus (symbol_ref ("ix86_bnd_prefixed_insn_p (insn)")) + (attr "length_nobnd")) + (eq_attr "type" "other,multi,fistp,frndint") (const_int 16) (eq_attr "type" "fcmp") (const_int 4) @@ -608,12 +634,16 @@ (define_attr "memory" "none,load,store,both,unknown" (cond [(eq_attr "type" "other,multi,str,lwp") (const_string "unknown") - (eq_attr "type" "lea,fcmov,fpspc") + (eq_attr "type" "lea,fcmov,fpspc,mpxmk,mpxchk") (const_string "none") (eq_attr "type" "fistp,leave") (const_string "both") (eq_attr "type" "frndint") (const_string "load") + (eq_attr "type" "mpxld") + (const_string "load") + (eq_attr "type" "mpxst") + (const_string "store") (eq_attr "type" "push") (if_then_else (match_operand 1 "memory_operand") (const_string "both") @@ -659,7 +689,7 @@ fmov,fcmp,fsgn, sse,ssemov,ssecmp,ssecomi,ssecvt,ssecvt1,sseicvt, sselog1,sseshuf1,sseadd1,sseiadd1,sseishft1, - mmx,mmxmov,mmxcmp,mmxcvt,mskmov,msklog") + mmx,mmxmov,mmxcmp,mmxcvt,mskmov,msklog,mpxmov") (match_operand 2 "memory_operand")) (const_string "load") (and (eq_attr "type" "icmov,ssemuladd,sse4arg") @@ -831,6 +861,11 @@ (define_code_attr s [(sign_extend "s") (zero_extend "u")]) (define_code_attr u_bool [(sign_extend "false") (zero_extend "true")]) +;; Used in signed and unsigned truncations. +(define_code_iterator any_truncate [ss_truncate truncate us_truncate]) +;; Instruction suffix for truncations. +(define_code_attr trunsuffix [(ss_truncate "s") (truncate "") (us_truncate "us")]) + ;; Used in signed and unsigned fix. (define_code_iterator any_fix [fix unsigned_fix]) (define_code_attr fixsuffix [(fix "") (unsigned_fix "u")]) @@ -893,6 +928,21 @@ (define_mode_iterator DWIH [(SI "!TARGET_64BIT") (DI "TARGET_64BIT")]) +;; Bound modes. +(define_mode_iterator BND [(BND32 "!TARGET_LP64") + (BND64 "TARGET_LP64")]) + +;; Pointer mode corresponding to bound mode. +(define_mode_attr bnd_ptr [(BND32 "SI") (BND64 "DI")]) + +;; MPX check types +(define_int_iterator BNDCHECK [UNSPEC_BNDCL UNSPEC_BNDCU UNSPEC_BNDCN]) + +;; Check name +(define_int_attr bndcheck [(UNSPEC_BNDCL "cl") + (UNSPEC_BNDCU "cu") + (UNSPEC_BNDCN "cn")]) + ;; Instruction suffix for integer modes. (define_mode_attr imodesuffix [(QI "b") (HI "w") (SI "l") (DI "q")]) @@ -1957,11 +2007,10 @@ return "pxor\t%0, %0"; case TYPE_MMXMOV: -#ifndef HAVE_AS_IX86_INTERUNIT_MOVQ /* Handle broken assemblers that require movd instead of movq. */ - if (GENERAL_REG_P (operands[0]) || GENERAL_REG_P (operands[1])) + if (!HAVE_AS_IX86_INTERUNIT_MOVQ + && (GENERAL_REG_P (operands[0]) || GENERAL_REG_P (operands[1]))) return "movd\t{%1, %0|%0, %1}"; -#endif return "movq\t{%1, %0|%0, %1}"; case TYPE_SSELOG1: @@ -1974,11 +2023,10 @@ switch (get_attr_mode (insn)) { case MODE_DI: -#ifndef HAVE_AS_IX86_INTERUNIT_MOVQ /* Handle broken assemblers that require movd instead of movq. */ - if (GENERAL_REG_P (operands[0]) || GENERAL_REG_P (operands[1])) + if (!HAVE_AS_IX86_INTERUNIT_MOVQ + && (GENERAL_REG_P (operands[0]) || GENERAL_REG_P (operands[1]))) return "%vmovd\t{%1, %0|%0, %1}"; -#endif return "%vmovq\t{%1, %0|%0, %1}"; case MODE_TI: return "%vmovdqa\t{%1, %0|%0, %1}"; @@ -2302,9 +2350,12 @@ ;; For loads of Q_REG to NONQ_REG we use full sized moves except for partial ;; register stall machines with, where we use QImode instructions, since ;; partial register stall can be caused there. Then we use movzx. + (define_insn "*movqi_internal" - [(set (match_operand:QI 0 "nonimmediate_operand" "=q,q ,q ,r,r ,?r,m ,Yk,Yk,r") - (match_operand:QI 1 "general_operand" "q ,qn,qm,q,rn,qm,qn,r ,Yk,Yk"))] + [(set (match_operand:QI 0 "nonimmediate_operand" + "=q,q ,q ,r,r ,?r,m ,Yk,Yk,r") + (match_operand:QI 1 "general_operand" + "q ,qn,qm,q,rn,qm,qn,r ,Yk,Yk"))] "!(MEM_P (operands[0]) && MEM_P (operands[1]))" { switch (get_attr_type (insn)) @@ -2891,12 +2942,11 @@ return "movlpd\t{%1, %0|%0, %1}"; case MODE_DI: -#ifndef HAVE_AS_IX86_INTERUNIT_MOVQ /* Handle broken assemblers that require movd instead of movq. */ - if (GENERAL_REG_P (operands[0]) || GENERAL_REG_P (operands[1])) + if (!HAVE_AS_IX86_INTERUNIT_MOVQ + && (GENERAL_REG_P (operands[0]) || GENERAL_REG_P (operands[1]))) return "%vmovd\t{%1, %0|%0, %1}"; -#endif - return "%vmovq\t{%1, %0|%0, %1}"; + return "%vmovq\t{%1, %0|%0, %1}"; default: gcc_unreachable (); @@ -5344,7 +5394,7 @@ (define_insn_and_split "*lea<mode>" [(set (match_operand:SWI48 0 "register_operand" "=r") - (match_operand:SWI48 1 "lea_address_operand" "p"))] + (match_operand:SWI48 1 "address_no_seg_operand" "Ts"))] "" { if (SImode_address_operand (operands[1], VOIDmode)) @@ -6486,7 +6536,7 @@ (set_attr "use_carry" "1") (set_attr "mode" "<MODE>")]) -;; Overflow setting add and subtract instructions +;; Overflow setting add instructions (define_insn "*add<mode>3_cconly_overflow" [(set (reg:CCC FLAGS_REG) @@ -6501,43 +6551,31 @@ [(set_attr "type" "alu") (set_attr "mode" "<MODE>")]) -(define_insn "*sub<mode>3_cconly_overflow" +(define_insn "*add<mode>3_cc_overflow" [(set (reg:CCC FLAGS_REG) (compare:CCC - (minus:SWI - (match_operand:SWI 0 "nonimmediate_operand" "<r>m,<r>") - (match_operand:SWI 1 "<general_operand>" "<r><i>,<r>m")) - (match_dup 0)))] - "" - "cmp{<imodesuffix>}\t{%1, %0|%0, %1}" - [(set_attr "type" "icmp") - (set_attr "mode" "<MODE>")]) - -(define_insn "*<plusminus_insn><mode>3_cc_overflow" - [(set (reg:CCC FLAGS_REG) - (compare:CCC - (plusminus:SWI - (match_operand:SWI 1 "nonimmediate_operand" "<comm>0,0") + (plus:SWI + (match_operand:SWI 1 "nonimmediate_operand" "%0,0") (match_operand:SWI 2 "<general_operand>" "<r><i>,<r>m")) (match_dup 1))) (set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>") - (plusminus:SWI (match_dup 1) (match_dup 2)))] - "ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)" - "<plusminus_mnemonic>{<imodesuffix>}\t{%2, %0|%0, %2}" + (plus:SWI (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 "*<plusminus_insn>si3_zext_cc_overflow" +(define_insn "*addsi3_zext_cc_overflow" [(set (reg:CCC FLAGS_REG) (compare:CCC - (plusminus:SI - (match_operand:SI 1 "nonimmediate_operand" "<comm>0") + (plus:SI + (match_operand:SI 1 "nonimmediate_operand" "%0") (match_operand:SI 2 "x86_64_general_operand" "rme")) (match_dup 1))) (set (match_operand:DI 0 "register_operand" "=r") - (zero_extend:DI (plusminus:SI (match_dup 1) (match_dup 2))))] - "TARGET_64BIT && ix86_binary_operator_ok (<CODE>, SImode, operands)" - "<plusminus_mnemonic>{l}\t{%2, %k0|%k0, %2}" + (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))] + "TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)" + "add{l}\t{%2, %k0|%k0, %2}" [(set_attr "type" "alu") (set_attr "mode" "SI")]) @@ -7828,8 +7866,7 @@ (parallel [(set (match_dup 0) (and:HI (match_dup 0) (match_dup 1))) - (clobber (reg:CC FLAGS_REG))])] - "") + (clobber (reg:CC FLAGS_REG))])]) ;; Turn *anddi_1 into *andsi_1_zext if possible. (define_split @@ -8254,7 +8291,8 @@ (not:SWI12 (xor:SWI12 (match_operand:SWI12 1 "register_operand" "0,Yk") - (match_operand:SWI12 2 "register_operand" "r,Yk"))))] + (match_operand:SWI12 2 "register_operand" "r,Yk")))) + (clobber (reg:CC FLAGS_REG))] "TARGET_AVX512F" "@ # @@ -8268,15 +8306,15 @@ (not:SWI12 (xor:SWI12 (match_dup 0) - (match_operand:SWI12 1 "general_reg_operand"))))] + (match_operand:SWI12 1 "general_reg_operand")))) + (clobber (reg:CC FLAGS_REG))] "TARGET_AVX512F && reload_completed" [(parallel [(set (match_dup 0) (xor:HI (match_dup 0) (match_dup 1))) (clobber (reg:CC FLAGS_REG))]) (set (match_dup 0) - (not:HI (match_dup 0)))] - "") + (not:HI (match_dup 0)))]) (define_insn "kortestzhi" [(set (reg:CCZ FLAGS_REG) @@ -10743,10 +10781,10 @@ (label_ref (match_operand 0)) (pc)))] "" - "%+j%C1\t%l0" + "%!%+j%C1\t%l0" [(set_attr "type" "ibr") (set_attr "modrm" "0") - (set (attr "length") + (set (attr "length_nobnd") (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -126)) (lt (minus (match_dup 0) (pc)) @@ -10761,10 +10799,10 @@ (pc) (label_ref (match_operand 0))))] "" - "%+j%c1\t%l0" + "%!%+j%c1\t%l0" [(set_attr "type" "ibr") (set_attr "modrm" "0") - (set (attr "length") + (set (attr "length_nobnd") (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -126)) (lt (minus (match_dup 0) (pc)) @@ -11227,9 +11265,9 @@ [(set (pc) (label_ref (match_operand 0)))] "" - "jmp\t%l0" + "%!jmp\t%l0" [(set_attr "type" "ibr") - (set (attr "length") + (set (attr "length_nobnd") (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -126)) (lt (minus (match_dup 0) (pc)) @@ -11249,7 +11287,7 @@ (define_insn "*indirect_jump" [(set (pc) (match_operand:W 0 "indirect_branch_operand" "rw"))] "" - "jmp\t%A0" + "%!jmp\t%A0" [(set_attr "type" "ibr") (set_attr "length_immediate" "0")]) @@ -11298,7 +11336,7 @@ [(set (pc) (match_operand:W 0 "indirect_branch_operand" "rw")) (use (label_ref (match_operand 1)))] "" - "jmp\t%A0" + "%!jmp\t%A0" [(set_attr "type" "ibr") (set_attr "length_immediate" "0")]) @@ -11685,8 +11723,8 @@ (define_insn "simple_return_internal" [(simple_return)] "reload_completed" - "ret" - [(set_attr "length" "1") + "%!ret" + [(set_attr "length_nobnd" "1") (set_attr "atom_unit" "jeu") (set_attr "length_immediate" "0") (set_attr "modrm" "0")]) @@ -11698,7 +11736,12 @@ [(simple_return) (unspec [(const_int 0)] UNSPEC_REP)] "reload_completed" - "rep%; ret" +{ + if (ix86_bnd_prefixed_insn_p (insn)) + return "%!ret"; + + return "rep%; ret"; +} [(set_attr "length" "2") (set_attr "atom_unit" "jeu") (set_attr "length_immediate" "0") @@ -11709,8 +11752,8 @@ [(simple_return) (use (match_operand:SI 0 "const_int_operand"))] "reload_completed" - "ret\t%0" - [(set_attr "length" "3") + "%!ret\t%0" + [(set_attr "length_nobnd" "3") (set_attr "atom_unit" "jeu") (set_attr "length_immediate" "2") (set_attr "modrm" "0")]) @@ -11719,7 +11762,7 @@ [(simple_return) (use (match_operand:SI 0 "register_operand" "r"))] "reload_completed" - "jmp\t%A0" + "%!jmp\t%A0" [(set_attr "type" "ibr") (set_attr "length_immediate" "0")]) @@ -17581,7 +17624,7 @@ [(prefetch (match_operand 0 "address_operand") (match_operand:SI 1 "const_int_operand") (match_operand:SI 2 "const_int_operand"))] - "TARGET_PREFETCH_SSE || TARGET_PRFCHW" + "TARGET_PREFETCH_SSE || TARGET_PRFCHW || TARGET_AVX512PF" { bool write = INTVAL (operands[1]) != 0; int locality = INTVAL (operands[2]); @@ -17592,7 +17635,9 @@ supported by SSE counterpart or the SSE prefetch is not available (K6 machines). Otherwise use SSE prefetch as it allows specifying of locality. */ - if (TARGET_PRFCHW && (write || !TARGET_PREFETCH_SSE)) + if (TARGET_AVX512PF && write) + operands[2] = const1_rtx; + else if (TARGET_PRFCHW && (write || !TARGET_PREFETCH_SSE)) operands[2] = GEN_INT (3); else operands[1] = const0_rtx; @@ -17635,6 +17680,18 @@ (symbol_ref "memory_address_length (operands[0], false)")) (set_attr "memory" "none")]) +(define_insn "*prefetch_avx512pf_<mode>" + [(prefetch (match_operand:P 0 "address_operand" "p") + (const_int 1) + (const_int 1))] + "TARGET_AVX512PF" + "prefetchwt1\t%a0"; + [(set_attr "type" "sse") + (set_attr "prefix" "evex") + (set (attr "length_address") + (symbol_ref "memory_address_length (operands[0], false)")) + (set_attr "memory" "none")]) + (define_expand "stack_protect_set" [(match_operand 0 "memory_operand") (match_operand 1 "memory_operand")] @@ -18182,6 +18239,131 @@ [(set_attr "type" "other") (set_attr "length" "3")]) +;; MPX instructions + +(define_expand "<mode>_mk" + [(set (match_operand:BND 0 "register_operand") + (unspec:BND + [(mem:<bnd_ptr> + (match_par_dup 3 + [(match_operand:<bnd_ptr> 1 "register_operand") + (match_operand:<bnd_ptr> 2 "address_mpx_no_base_operand")]))] + UNSPEC_BNDMK))] + "TARGET_MPX" +{ + operands[3] = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, operands[1], + operands[2]), + UNSPEC_BNDMK_ADDR); +}) + +(define_insn "*<mode>_mk" + [(set (match_operand:BND 0 "register_operand" "=B") + (unspec:BND + [(match_operator:<bnd_ptr> 3 "bnd_mem_operator" + [(unspec:<bnd_ptr> + [(match_operand:<bnd_ptr> 1 "register_operand" "r") + (match_operand:<bnd_ptr> 2 "address_mpx_no_base_operand" "Tb")] + UNSPEC_BNDMK_ADDR)])] + UNSPEC_BNDMK))] + "TARGET_MPX" + "bndmk\t{%3, %0|%0, %3}" + [(set_attr "type" "mpxmk")]) + +(define_expand "mov<mode>" + [(set (match_operand:BND 0 "general_operand") + (match_operand:BND 1 "general_operand"))] + "TARGET_MPX" +{ + ix86_expand_move (<MODE>mode, operands);DONE; +}) + +(define_insn "*mov<mode>_internal_mpx" + [(set (match_operand:BND 0 "nonimmediate_operand" "=B,m") + (match_operand:BND 1 "general_operand" "Bm,B"))] + "TARGET_MPX" + "bndmov\t{%1, %0|%0, %1}" + [(set_attr "type" "mpxmov")]) + +(define_expand "<mode>_<bndcheck>" + [(parallel [(unspec [(match_operand:BND 0 "register_operand") + (match_operand:<bnd_ptr> 1 "address_no_seg_operand")] BNDCHECK) + (set (match_dup 2) + (unspec:BLK [(match_dup 2)] UNSPEC_MPX_FENCE))])] + "TARGET_MPX" +{ + operands[2] = gen_rtx_MEM (BLKmode, operands[1]); + MEM_VOLATILE_P (operands[2]) = 1; +}) + +(define_insn "*<mode>_<bndcheck>" + [(parallel [(unspec [(match_operand:BND 0 "register_operand" "B") + (match_operand:<bnd_ptr> 1 "address_no_seg_operand" "Ts")] BNDCHECK) + (set (match_operand:BLK 2 "bnd_mem_operator") + (unspec:BLK [(match_dup 2)] UNSPEC_MPX_FENCE))])] + "TARGET_MPX" + "bnd<bndcheck>\t{%a1, %0|%0, %a1}" + [(set_attr "type" "mpxchk")]) + +(define_expand "<mode>_ldx" + [(parallel [(set:BND (match_operand:BND 0 "register_operand") + (unspec:BND + [(mem:<bnd_ptr> + (match_par_dup 3 + [(match_operand:<bnd_ptr> 1 "address_mpx_no_index_operand") + (match_operand:<bnd_ptr> 2 "register_operand")]))] + UNSPEC_BNDLDX)) + (use (mem:BLK (match_dup 1)))])] + "TARGET_MPX" +{ + operands[3] = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, operands[1], + operands[2]), + UNSPEC_BNDLDX_ADDR); +}) + +(define_insn "*<mode>_ldx" + [(parallel [(set:BND (match_operand:BND 0 "register_operand" "=B") + (unspec:BND + [(match_operator:<bnd_ptr> 3 "bnd_mem_operator" + [(unspec:<bnd_ptr> + [(match_operand:<bnd_ptr> 1 "address_mpx_no_index_operand" "Ti") + (match_operand:<bnd_ptr> 2 "register_operand" "l")] + UNSPEC_BNDLDX_ADDR)])] + UNSPEC_BNDLDX)) + (use (mem:BLK (match_dup 1)))])] + "TARGET_MPX" + "bndldx\t{%3, %0|%0, %3}" + [(set_attr "type" "mpxld")]) + +(define_expand "<mode>_stx" + [(parallel [(unspec [(mem:<bnd_ptr> + (match_par_dup 3 + [(match_operand:<bnd_ptr> 0 "address_mpx_no_index_operand") + (match_operand:<bnd_ptr> 1 "register_operand")])) + (match_operand:BND 2 "register_operand")] UNSPEC_BNDSTX) + (set (match_dup 4) + (unspec:BLK [(match_dup 4)] UNSPEC_MPX_FENCE))])] + "TARGET_MPX" +{ + operands[3] = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, operands[0], + operands[1]), + UNSPEC_BNDLDX_ADDR); + operands[4] = gen_rtx_MEM (BLKmode, operands[0]); + MEM_VOLATILE_P (operands[4]) = 1; +}) + +(define_insn "*<mode>_stx" + [(parallel [(unspec [(match_operator:<bnd_ptr> 3 "bnd_mem_operator" + [(unspec:<bnd_ptr> + [(match_operand:<bnd_ptr> 0 "address_mpx_no_index_operand" "Ti") + (match_operand:<bnd_ptr> 1 "register_operand" "l")] + UNSPEC_BNDLDX_ADDR)]) + (match_operand:BND 2 "register_operand" "B")] UNSPEC_BNDSTX) + (set (match_operand:BLK 4 "bnd_mem_operator") + (unspec:BLK [(match_dup 4)] UNSPEC_MPX_FENCE))])] + "TARGET_MPX" + "bndstx\t{%2, %3|%3, %2}" + [(set_attr "type" "mpxst")]) + (include "mmx.md") (include "sse.md") (include "sync.md") diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt index 1e624ab0222..1a1b8abefdc 100644 --- a/gcc/config/i386/i386.opt +++ b/gcc/config/i386/i386.opt @@ -669,6 +669,10 @@ mrtm Target Report Mask(ISA_RTM) Var(ix86_isa_flags) Save Support RTM built-in functions and code generation +mmpx +Target Report Mask(ISA_MPX) Var(ix86_isa_flags) Save +Support MPX code generation + mstack-protector-guard= Target RejectNegative Joined Enum(stack_protector_guard) Var(ix86_stack_protector_guard) Init(SSP_TLS) Use given stack-protector guard diff --git a/gcc/config/i386/mmx.md b/gcc/config/i386/mmx.md index 17e24999258..cc0db3a9d06 100644 --- a/gcc/config/i386/mmx.md +++ b/gcc/config/i386/mmx.md @@ -99,11 +99,10 @@ return "pxor\t%0, %0"; case TYPE_MMXMOV: -#ifndef HAVE_AS_IX86_INTERUNIT_MOVQ /* Handle broken assemblers that require movd instead of movq. */ - if (GENERAL_REG_P (operands[0]) || GENERAL_REG_P (operands[1])) + if (!HAVE_AS_IX86_INTERUNIT_MOVQ + && (GENERAL_REG_P (operands[0]) || GENERAL_REG_P (operands[1]))) return "movd\t{%1, %0|%0, %1}"; -#endif return "movq\t{%1, %0|%0, %1}"; case TYPE_SSECVT: @@ -119,15 +118,13 @@ switch (get_attr_mode (insn)) { case MODE_DI: -#ifndef HAVE_AS_IX86_INTERUNIT_MOVQ /* Handle broken assemblers that require movd instead of movq. */ - if (GENERAL_REG_P (operands[0]) || GENERAL_REG_P (operands[1])) + if (!HAVE_AS_IX86_INTERUNIT_MOVQ + && (GENERAL_REG_P (operands[0]) || GENERAL_REG_P (operands[1]))) return "%vmovd\t{%1, %0|%0, %1}"; -#endif return "%vmovq\t{%1, %0|%0, %1}"; case MODE_TI: return "%vmovdqa\t{%1, %0|%0, %1}"; - case MODE_XI: return "vmovdqa64\t{%g1, %g0|%g0, %g1}"; diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md index 06b291445a9..e5dd90cfad2 100644 --- a/gcc/config/i386/predicates.md +++ b/gcc/config/i386/predicates.md @@ -752,6 +752,11 @@ (and (match_code "const_int") (match_test "IN_RANGE (INTVAL (op), 6, 7)"))) +;; Match 8 to 9. +(define_predicate "const_8_to_9_operand" + (and (match_code "const_int") + (match_test "IN_RANGE (INTVAL (op), 8, 9)"))) + ;; Match 8 to 11. (define_predicate "const_8_to_11_operand" (and (match_code "const_int") @@ -762,16 +767,51 @@ (and (match_code "const_int") (match_test "IN_RANGE (INTVAL (op), 8, 15)"))) +;; Match 10 to 11. +(define_predicate "const_10_to_11_operand" + (and (match_code "const_int") + (match_test "IN_RANGE (INTVAL (op), 10, 11)"))) + +;; Match 12 to 13. +(define_predicate "const_12_to_13_operand" + (and (match_code "const_int") + (match_test "IN_RANGE (INTVAL (op), 12, 13)"))) + ;; Match 12 to 15. (define_predicate "const_12_to_15_operand" (and (match_code "const_int") (match_test "IN_RANGE (INTVAL (op), 12, 15)"))) +;; Match 14 to 15. +(define_predicate "const_14_to_15_operand" + (and (match_code "const_int") + (match_test "IN_RANGE (INTVAL (op), 14, 15)"))) + +;; Match 16 to 19. +(define_predicate "const_16_to_19_operand" + (and (match_code "const_int") + (match_test "IN_RANGE (INTVAL (op), 16, 19)"))) + ;; Match 16 to 31. (define_predicate "const_16_to_31_operand" (and (match_code "const_int") (match_test "IN_RANGE (INTVAL (op), 16, 31)"))) +;; Match 20 to 23. +(define_predicate "const_20_to_23_operand" + (and (match_code "const_int") + (match_test "IN_RANGE (INTVAL (op), 20, 23)"))) + +;; Match 24 to 27. +(define_predicate "const_24_to_27_operand" + (and (match_code "const_int") + (match_test "IN_RANGE (INTVAL (op), 24, 27)"))) + +;; Match 28 to 31. +(define_predicate "const_28_to_31_operand" + (and (match_code "const_int") + (match_test "IN_RANGE (INTVAL (op), 28, 31)"))) + ;; True if this is a constant appropriate for an increment or decrement. (define_predicate "incdec_operand" (match_code "const_int") @@ -872,10 +912,14 @@ (ior (match_operand 0 "register_operand") (match_operand 0 "const0_operand"))) +;; Return true for RTX codes that force SImode address. +(define_predicate "SImode_address_operand" + (match_code "subreg,zero_extend,and")) + ;; Return true if op if a valid address for LEA, and does not contain ;; a segment override. Defined as a special predicate to allow ;; mode-less const_int operands pass to address_operand. -(define_special_predicate "lea_address_operand" +(define_special_predicate "address_no_seg_operand" (match_operand 0 "address_operand") { struct ix86_address parts; @@ -886,10 +930,6 @@ return parts.seg == SEG_DEFAULT; }) -;; Return true for RTX codes that force SImode address. -(define_predicate "SImode_address_operand" - (match_code "subreg,zero_extend,and")) - ;; Return true if op if a valid base register, displacement or ;; sum of base register and displacement for VSIB addressing. (define_predicate "vsib_address_operand" @@ -932,9 +972,74 @@ return true; }) +;; Return true if op is valid MPX address operand without base +(define_predicate "address_mpx_no_base_operand" + (match_operand 0 "address_operand") +{ + struct ix86_address parts; + int ok; + + ok = ix86_decompose_address (op, &parts); + gcc_assert (ok); + + if (parts.index && parts.base) + return false; + + if (parts.seg != SEG_DEFAULT) + return false; + + /* Do not support (%rip). */ + if (parts.disp && flag_pic && TARGET_64BIT + && SYMBOLIC_CONST (parts.disp)) + { + if (GET_CODE (parts.disp) != CONST + || GET_CODE (XEXP (parts.disp, 0)) != PLUS + || GET_CODE (XEXP (XEXP (parts.disp, 0), 0)) != UNSPEC + || !CONST_INT_P (XEXP (XEXP (parts.disp, 0), 1)) + || (XINT (XEXP (XEXP (parts.disp, 0), 0), 1) != UNSPEC_DTPOFF + && XINT (XEXP (XEXP (parts.disp, 0), 0), 1) != UNSPEC_NTPOFF)) + return false; + } + + return true; +}) + +;; Return true if op is valid MPX address operand without index +(define_predicate "address_mpx_no_index_operand" + (match_operand 0 "address_operand") +{ + struct ix86_address parts; + int ok; + + ok = ix86_decompose_address (op, &parts); + gcc_assert (ok); + + if (parts.index) + return false; + + if (parts.seg != SEG_DEFAULT) + return false; + + /* Do not support (%rip). */ + if (parts.disp && flag_pic && TARGET_64BIT + && SYMBOLIC_CONST (parts.disp) + && (GET_CODE (parts.disp) != CONST + || GET_CODE (XEXP (parts.disp, 0)) != PLUS + || GET_CODE (XEXP (XEXP (parts.disp, 0), 0)) != UNSPEC + || !CONST_INT_P (XEXP (XEXP (parts.disp, 0), 1)) + || (XINT (XEXP (XEXP (parts.disp, 0), 0), 1) != UNSPEC_DTPOFF + && XINT (XEXP (XEXP (parts.disp, 0), 0), 1) != UNSPEC_NTPOFF))) + return false; + + return true; +}) + (define_predicate "vsib_mem_operator" (match_code "mem")) +(define_predicate "bnd_mem_operator" + (match_code "mem")) + ;; Return true if the rtx is known to be at least 32 bits aligned. (define_predicate "aligned_operand" (match_operand 0 "general_operand") diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md index 0c52e884eb7..7bb2d7795f6 100644 --- a/gcc/config/i386/sse.md +++ b/gcc/config/i386/sse.md @@ -87,6 +87,7 @@ ;; For AVX512F support UNSPEC_VPERMI2 UNSPEC_VPERMT2 + UNSPEC_UNSIGNED_FIX_NOTRUNC UNSPEC_UNSIGNED_PCMP UNSPEC_TESTM UNSPEC_TESTNM @@ -799,10 +800,13 @@ gen_rtx_SUBREG (SImode, operands[1], 4))); emit_insn (gen_vec_interleave_lowv4si (operands[0], operands[0], operands[2])); - } + } else if (memory_operand (operands[1], DImode)) - emit_insn (gen_vec_concatv2di (gen_lowpart (V2DImode, operands[0]), - operands[1], const0_rtx)); + { + rtx tmp = gen_reg_rtx (V2DImode); + emit_insn (gen_vec_concatv2di (tmp, operands[1], const0_rtx)); + emit_move_insn (operands[0], gen_lowpart (V4SImode, tmp)); + } else gcc_unreachable (); }) @@ -2009,6 +2013,34 @@ (set_attr "prefix" "evex") (set_attr "mode" "<sseinsnmode>")]) +(define_insn "avx512f_vmcmp<mode>3" + [(set (match_operand:<avx512fmaskmode> 0 "register_operand" "=k") + (and:<avx512fmaskmode> + (unspec:<avx512fmaskmode> + [(match_operand:VF_128 1 "register_operand" "v") + (match_operand:VF_128 2 "nonimmediate_operand" "vm") + (match_operand:SI 3 "const_0_to_31_operand" "n")] + UNSPEC_PCMP) + (const_int 1)))] + "TARGET_AVX512F" + "vcmp<ssescalarmodesuffix>\t{%3, %2, %1, %0|%0, %1, %2, %3}" + [(set_attr "type" "ssecmp") + (set_attr "length_immediate" "1") + (set_attr "prefix" "evex") + (set_attr "mode" "<ssescalarmode>")]) + +(define_insn "avx512f_maskcmp<mode>3" + [(set (match_operand:<avx512fmaskmode> 0 "register_operand" "=k") + (match_operator:<avx512fmaskmode> 3 "sse_comparison_operator" + [(match_operand:VF 1 "register_operand" "v") + (match_operand:VF 2 "nonimmediate_operand" "vm")]))] + "TARGET_SSE" + "vcmp%D3<ssemodesuffix>\t{%2, %1, %0|%0, %1, %2}" + [(set_attr "type" "ssecmp") + (set_attr "length_immediate" "1") + (set_attr "prefix" "evex") + (set_attr "mode" "<sseinsnmode>")]) + (define_insn "<sse>_comi" [(set (reg:CCFP FLAGS_REG) (compare:CCFP @@ -2998,6 +3030,34 @@ (set_attr "prefix" "maybe_vex") (set_attr "mode" "DI")]) +(define_insn "cvtusi2<ssescalarmodesuffix>32" + [(set (match_operand:VF_128 0 "register_operand" "=v") + (vec_merge:VF_128 + (vec_duplicate:VF_128 + (unsigned_float:<ssescalarmode> + (match_operand:SI 2 "nonimmediate_operand" "rm"))) + (match_operand:VF_128 1 "register_operand" "v") + (const_int 1)))] + "TARGET_AVX512F" + "vcvtusi2<ssescalarmodesuffix>\t{%2, %1, %0|%0, %1, %2}" + [(set_attr "type" "sseicvt") + (set_attr "prefix" "evex") + (set_attr "mode" "<ssescalarmode>")]) + +(define_insn "cvtusi2<ssescalarmodesuffix>64" + [(set (match_operand:VF_128 0 "register_operand" "=v") + (vec_merge:VF_128 + (vec_duplicate:VF_128 + (unsigned_float:<ssescalarmode> + (match_operand:DI 2 "nonimmediate_operand" "rm"))) + (match_operand:VF_128 1 "register_operand" "v") + (const_int 1)))] + "TARGET_AVX512F && TARGET_64BIT" + "vcvtusi2<ssescalarmodesuffix>\t{%2, %1, %0|%0, %1, %2}" + [(set_attr "type" "sseicvt") + (set_attr "prefix" "evex") + (set_attr "mode" "<ssescalarmode>")]) + (define_insn "float<sseintvecmodelower><mode>2" [(set (match_operand:VF1 0 "register_operand" "=v") (float:VF1 @@ -3008,6 +3068,16 @@ (set_attr "prefix" "maybe_vex") (set_attr "mode" "<sseinsnmode>")]) +(define_insn "ufloatv16siv16sf2" + [(set (match_operand:V16SF 0 "register_operand" "=v") + (unsigned_float:V16SF + (match_operand:V16SI 1 "nonimmediate_operand" "vm")))] + "TARGET_AVX512F" + "vcvtudq2ps\t{%1, %0|%0, %1}" + [(set_attr "type" "ssecvt") + (set_attr "prefix" "evex") + (set_attr "mode" "V16SF")]) + (define_expand "floatuns<sseintvecmodelower><mode>2" [(match_operand:VF1 0 "register_operand") (match_operand:<sseintvecmode> 1 "register_operand")] @@ -3038,6 +3108,28 @@ (set_attr "prefix" "maybe_vex") (set_attr "mode" "<sseinsnmode>")]) +(define_insn "avx512f_fix_notruncv16sfv16si" + [(set (match_operand:V16SI 0 "register_operand" "=v") + (unspec:V16SI + [(match_operand:V16SF 1 "nonimmediate_operand" "vm")] + UNSPEC_FIX_NOTRUNC))] + "TARGET_AVX512F" + "vcvtps2dq\t{%1, %0|%0, %1}" + [(set_attr "type" "ssecvt") + (set_attr "prefix" "evex") + (set_attr "mode" "XI")]) + +(define_insn "avx512f_ufix_notruncv16sfv16si" + [(set (match_operand:V16SI 0 "register_operand" "=v") + (unspec:V16SI + [(match_operand:V16SF 1 "nonimmediate_operand" "vm")] + UNSPEC_UNSIGNED_FIX_NOTRUNC))] + "TARGET_AVX512F" + "vcvtps2udq\t{%1, %0|%0, %1}" + [(set_attr "type" "ssecvt") + (set_attr "prefix" "evex") + (set_attr "mode" "XI")]) + (define_insn "<fixsuffix>fix_truncv16sfv16si2" [(set (match_operand:V16SI 0 "register_operand" "=v") (any_fix:V16SI @@ -3173,6 +3265,106 @@ (set_attr "prefix" "orig,orig,maybe_evex") (set_attr "mode" "DF")]) +(define_insn "avx512f_vcvtss2usi" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI + [(vec_select:SF + (match_operand:V4SF 1 "nonimmediate_operand" "vm") + (parallel [(const_int 0)]))] + UNSPEC_UNSIGNED_FIX_NOTRUNC))] + "TARGET_AVX512F" + "vcvtss2usi\t{%1, %0|%0, %1}" + [(set_attr "type" "sseicvt") + (set_attr "prefix" "evex") + (set_attr "mode" "SI")]) + +(define_insn "avx512f_vcvtss2usiq" + [(set (match_operand:DI 0 "register_operand" "=r") + (unspec:DI + [(vec_select:SF + (match_operand:V4SF 1 "nonimmediate_operand" "vm") + (parallel [(const_int 0)]))] + UNSPEC_UNSIGNED_FIX_NOTRUNC))] + "TARGET_AVX512F && TARGET_64BIT" + "vcvtss2usi\t{%1, %0|%0, %1}" + [(set_attr "type" "sseicvt") + (set_attr "prefix" "evex") + (set_attr "mode" "DI")]) + +(define_insn "avx512f_vcvttss2usi" + [(set (match_operand:SI 0 "register_operand" "=r") + (unsigned_fix:SI + (vec_select:SF + (match_operand:V4SF 1 "nonimmediate_operand" "vm") + (parallel [(const_int 0)]))))] + "TARGET_AVX512F" + "vcvttss2usi\t{%1, %0|%0, %1}" + [(set_attr "type" "sseicvt") + (set_attr "prefix" "evex") + (set_attr "mode" "SI")]) + +(define_insn "avx512f_vcvttss2usiq" + [(set (match_operand:DI 0 "register_operand" "=r") + (unsigned_fix:DI + (vec_select:SF + (match_operand:V4SF 1 "nonimmediate_operand" "vm") + (parallel [(const_int 0)]))))] + "TARGET_AVX512F && TARGET_64BIT" + "vcvttss2usi\t{%1, %0|%0, %1}" + [(set_attr "type" "sseicvt") + (set_attr "prefix" "evex") + (set_attr "mode" "DI")]) + +(define_insn "avx512f_vcvtsd2usi" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI + [(vec_select:DF + (match_operand:V2DF 1 "nonimmediate_operand" "vm") + (parallel [(const_int 0)]))] + UNSPEC_UNSIGNED_FIX_NOTRUNC))] + "TARGET_AVX512F" + "vcvtsd2usi\t{%1, %0|%0, %1}" + [(set_attr "type" "sseicvt") + (set_attr "prefix" "evex") + (set_attr "mode" "SI")]) + +(define_insn "avx512f_vcvtsd2usiq" + [(set (match_operand:DI 0 "register_operand" "=r") + (unspec:DI + [(vec_select:DF + (match_operand:V2DF 1 "nonimmediate_operand" "vm") + (parallel [(const_int 0)]))] + UNSPEC_UNSIGNED_FIX_NOTRUNC))] + "TARGET_AVX512F && TARGET_64BIT" + "vcvtsd2usi\t{%1, %0|%0, %1}" + [(set_attr "type" "sseicvt") + (set_attr "prefix" "evex") + (set_attr "mode" "DI")]) + +(define_insn "avx512f_vcvttsd2usi" + [(set (match_operand:SI 0 "register_operand" "=r") + (unsigned_fix:SI + (vec_select:DF + (match_operand:V2DF 1 "nonimmediate_operand" "vm") + (parallel [(const_int 0)]))))] + "TARGET_AVX512F" + "vcvttsd2usi\t{%1, %0|%0, %1}" + [(set_attr "type" "sseicvt") + (set_attr "prefix" "evex") + (set_attr "mode" "SI")]) + +(define_insn "avx512f_vcvttsd2usiq" + [(set (match_operand:DI 0 "register_operand" "=r") + (unsigned_fix:DI + (vec_select:DF + (match_operand:V2DF 1 "nonimmediate_operand" "vm") + (parallel [(const_int 0)]))))] + "TARGET_AVX512F && TARGET_64BIT" + "vcvttsd2usi\t{%1, %0|%0, %1}" + [(set_attr "type" "sseicvt") + (set_attr "prefix" "evex") + (set_attr "mode" "DI")]) + (define_insn "sse2_cvtsd2si" [(set (match_operand:SI 0 "register_operand" "=r,r") (unspec:SI @@ -3282,6 +3474,30 @@ (set_attr "prefix" "maybe_vex") (set_attr "mode" "<MODE>")]) +(define_insn "ufloatv8siv8df" + [(set (match_operand:V8DF 0 "register_operand" "=v") + (unsigned_float:V8DF (match_operand:V8SI 1 "nonimmediate_operand" "vm")))] + "TARGET_AVX512F" + "vcvtudq2pd\t{%1, %0|%0, %1}" + [(set_attr "type" "ssecvt") + (set_attr "prefix" "evex") + (set_attr "mode" "V8DF")]) + +(define_insn "avx512f_cvtdq2pd512_2" + [(set (match_operand:V8DF 0 "register_operand" "=v") + (float:V8DF + (vec_select:V8SI + (match_operand:V16SI 1 "nonimmediate_operand" "vm") + (parallel [(const_int 0) (const_int 1) + (const_int 2) (const_int 3) + (const_int 4) (const_int 5) + (const_int 6) (const_int 7)]))))] + "TARGET_AVX" + "vcvtdq2pd\t{%t1, %0|%0, %t1}" + [(set_attr "type" "ssecvt") + (set_attr "prefix" "evex") + (set_attr "mode" "V8DF")]) + (define_insn "avx_cvtdq2pd256_2" [(set (match_operand:V4DF 0 "register_operand" "=x") (float:V4DF @@ -3307,6 +3523,16 @@ (set_attr "prefix" "maybe_vex") (set_attr "mode" "V2DF")]) +(define_insn "avx512f_cvtpd2dq512" + [(set (match_operand:V8SI 0 "register_operand" "=v") + (unspec:V8SI [(match_operand:V8DF 1 "nonimmediate_operand" "vm")] + UNSPEC_FIX_NOTRUNC))] + "TARGET_AVX512F" + "vcvtpd2dq\t{%1, %0|%0, %1}" + [(set_attr "type" "ssecvt") + (set_attr "prefix" "evex") + (set_attr "mode" "OI")]) + (define_insn "avx_cvtpd2dq256" [(set (match_operand:V4SI 0 "register_operand" "=x") (unspec:V4SI [(match_operand:V4DF 1 "nonimmediate_operand" "xm")] @@ -3370,6 +3596,17 @@ (set_attr "athlon_decode" "vector") (set_attr "bdver1_decode" "double")]) +(define_insn "avx512f_ufix_notruncv8dfv8si" + [(set (match_operand:V8SI 0 "register_operand" "=v") + (unspec:V8SI + [(match_operand:V8DF 1 "nonimmediate_operand" "vm")] + UNSPEC_UNSIGNED_FIX_NOTRUNC))] + "TARGET_AVX512F" + "vcvtpd2udq\t{%1, %0|%0, %1}" + [(set_attr "type" "ssecvt") + (set_attr "prefix" "evex") + (set_attr "mode" "OI")]) + (define_insn "<fixsuffix>fix_truncv8dfv8si2" [(set (match_operand:V8SI 0 "register_operand" "=v") (any_fix:V8SI (match_operand:V8DF 1 "nonimmediate_operand" "vm")))] @@ -3480,6 +3717,16 @@ (set_attr "prefix" "orig,orig,vex") (set_attr "mode" "DF")]) +(define_insn "avx512f_cvtpd2ps512" + [(set (match_operand:V8SF 0 "register_operand" "=v") + (float_truncate:V8SF + (match_operand:V8DF 1 "nonimmediate_operand" "vm")))] + "TARGET_AVX512F" + "vcvtpd2ps\t{%1, %0|%0, %1}" + [(set_attr "type" "ssecvt") + (set_attr "prefix" "evex") + (set_attr "mode" "V8SF")]) + (define_insn "avx_cvtpd2ps256" [(set (match_operand:V4SF 0 "register_operand" "=x") (float_truncate:V4SF @@ -3548,6 +3795,21 @@ (set_attr "prefix" "vex") (set_attr "mode" "V4DF")]) +(define_insn "vec_unpacks_lo_v16sf" + [(set (match_operand:V8DF 0 "register_operand" "=v") + (float_extend:V8DF + (vec_select:V8SF + (match_operand:V16SF 1 "nonimmediate_operand" "vm") + (parallel [(const_int 0) (const_int 1) + (const_int 2) (const_int 3) + (const_int 4) (const_int 5) + (const_int 6) (const_int 7)]))))] + "TARGET_AVX512F" + "vcvtps2pd\t{%t1, %0|%0, %t1}" + [(set_attr "type" "ssecvt") + (set_attr "prefix" "evex") + (set_attr "mode" "V8DF")]) + (define_insn "sse2_cvtps2pd" [(set (match_operand:V2DF 0 "register_operand" "=x") (float_extend:V2DF @@ -3592,6 +3854,20 @@ "TARGET_AVX" "operands[2] = gen_reg_rtx (V4SFmode);") +(define_expand "vec_unpacks_hi_v16sf" + [(set (match_dup 2) + (vec_select:V8SF + (match_operand:V16SF 1 "nonimmediate_operand") + (parallel [(const_int 8) (const_int 9) + (const_int 10) (const_int 11) + (const_int 12) (const_int 13) + (const_int 14) (const_int 15)]))) + (set (match_operand:V8DF 0 "register_operand") + (float_extend:V8DF + (match_dup 2)))] +"TARGET_AVX512F" +"operands[2] = gen_reg_rtx (V8SFmode);") + (define_expand "vec_unpacks_lo_v4sf" [(set (match_operand:V2DF 0 "register_operand") (float_extend:V2DF @@ -3708,6 +3984,31 @@ (const_int 2) (const_int 3)]))))] "TARGET_AVX") +(define_expand "vec_unpacks_float_hi_v16si" + [(set (match_dup 2) + (vec_select:V8SI + (match_operand:V16SI 1 "nonimmediate_operand") + (parallel [(const_int 8) (const_int 9) + (const_int 10) (const_int 11) + (const_int 12) (const_int 13) + (const_int 14) (const_int 15)]))) + (set (match_operand:V8DF 0 "register_operand") + (float:V8DF + (match_dup 2)))] + "TARGET_AVX512F" + "operands[2] = gen_reg_rtx (V8SImode);") + +(define_expand "vec_unpacks_float_lo_v16si" + [(set (match_operand:V8DF 0 "register_operand") + (float:V8DF + (vec_select:V8SI + (match_operand:V16SI 1 "nonimmediate_operand") + (parallel [(const_int 0) (const_int 1) + (const_int 2) (const_int 3) + (const_int 4) (const_int 5) + (const_int 6) (const_int 7)]))))] + "TARGET_AVX512F") + (define_expand "vec_unpacku_float_hi_v4si" [(set (match_dup 5) (vec_select:V4SI @@ -3910,7 +4211,7 @@ (match_operand:V2DF 2 "nonimmediate_operand")] "TARGET_SSE2" { - rtx tmp0, tmp1; + rtx tmp0, tmp1, tmp2; if (TARGET_AVX && !TARGET_PREFER_AVX128) { @@ -3924,13 +4225,14 @@ { tmp0 = gen_reg_rtx (V4SImode); tmp1 = gen_reg_rtx (V4SImode); + tmp2 = gen_reg_rtx (V2DImode); emit_insn (gen_sse2_cvttpd2dq (tmp0, operands[1])); emit_insn (gen_sse2_cvttpd2dq (tmp1, operands[2])); - emit_insn - (gen_vec_interleave_lowv2di (gen_lowpart (V2DImode, operands[0]), - gen_lowpart (V2DImode, tmp0), - gen_lowpart (V2DImode, tmp1))); + emit_insn (gen_vec_interleave_lowv2di (tmp2, + gen_lowpart (V2DImode, tmp0), + gen_lowpart (V2DImode, tmp1))); + emit_move_insn (operands[0], gen_lowpart (V4SImode, tmp2)); } DONE; }) @@ -3991,7 +4293,7 @@ (match_operand:V2DF 2 "nonimmediate_operand")] "TARGET_SSE2" { - rtx tmp0, tmp1; + rtx tmp0, tmp1, tmp2; if (TARGET_AVX && !TARGET_PREFER_AVX128) { @@ -4005,13 +4307,14 @@ { tmp0 = gen_reg_rtx (V4SImode); tmp1 = gen_reg_rtx (V4SImode); + tmp2 = gen_reg_rtx (V2DImode); emit_insn (gen_sse2_cvtpd2dq (tmp0, operands[1])); emit_insn (gen_sse2_cvtpd2dq (tmp1, operands[2])); - emit_insn - (gen_vec_interleave_lowv2di (gen_lowpart (V2DImode, operands[0]), - gen_lowpart (V2DImode, tmp0), - gen_lowpart (V2DImode, tmp1))); + emit_insn (gen_vec_interleave_lowv2di (tmp2, + gen_lowpart (V2DImode, tmp0), + gen_lowpart (V2DImode, tmp1))); + emit_move_insn (operands[0], gen_lowpart (V4SImode, tmp2)); } DONE; }) @@ -4112,6 +4415,26 @@ (set_attr "prefix" "orig,vex,orig,vex,maybe_vex") (set_attr "mode" "V4SF,V4SF,V2SF,V2SF,V2SF")]) +(define_insn "avx512f_unpckhps512" + [(set (match_operand:V16SF 0 "register_operand" "=v") + (vec_select:V16SF + (vec_concat:V32SF + (match_operand:V16SF 1 "register_operand" "v") + (match_operand:V16SF 2 "nonimmediate_operand" "vm")) + (parallel [(const_int 2) (const_int 18) + (const_int 3) (const_int 19) + (const_int 6) (const_int 22) + (const_int 7) (const_int 23) + (const_int 10) (const_int 26) + (const_int 11) (const_int 27) + (const_int 14) (const_int 30) + (const_int 15) (const_int 31)])))] + "TARGET_AVX512F" + "vunpckhps\t{%2, %1, %0|%0, %1, %2}" + [(set_attr "type" "sselog") + (set_attr "prefix" "evex") + (set_attr "mode" "V16SF")]) + ;; Recall that the 256-bit unpck insns only shuffle within their lanes. (define_insn "avx_unpckhps256" [(set (match_operand:V8SF 0 "register_operand" "=x") @@ -4180,6 +4503,26 @@ (set_attr "prefix" "orig,vex") (set_attr "mode" "V4SF")]) +(define_insn "avx512f_unpcklps512" + [(set (match_operand:V16SF 0 "register_operand" "=v") + (vec_select:V16SF + (vec_concat:V32SF + (match_operand:V16SF 1 "register_operand" "v") + (match_operand:V16SF 2 "nonimmediate_operand" "vm")) + (parallel [(const_int 0) (const_int 16) + (const_int 1) (const_int 17) + (const_int 4) (const_int 20) + (const_int 5) (const_int 21) + (const_int 8) (const_int 24) + (const_int 9) (const_int 25) + (const_int 12) (const_int 28) + (const_int 13) (const_int 29)])))] + "TARGET_AVX512F" + "vunpcklps\t{%2, %1, %0|%0, %1, %2}" + [(set_attr "type" "sselog") + (set_attr "prefix" "evex") + (set_attr "mode" "V16SF")]) + ;; Recall that the 256-bit unpck insns only shuffle within their lanes. (define_insn "avx_unpcklps256" [(set (match_operand:V8SF 0 "register_operand" "=x") @@ -4283,6 +4626,26 @@ (set_attr "prefix" "maybe_vex") (set_attr "mode" "V4SF")]) +(define_insn "avx512f_movshdup512" + [(set (match_operand:V16SF 0 "register_operand" "=v") + (vec_select:V16SF + (vec_concat:V32SF + (match_operand:V16SF 1 "nonimmediate_operand" "vm") + (match_dup 1)) + (parallel [(const_int 1) (const_int 1) + (const_int 3) (const_int 3) + (const_int 5) (const_int 5) + (const_int 7) (const_int 7) + (const_int 9) (const_int 9) + (const_int 11) (const_int 11) + (const_int 13) (const_int 13) + (const_int 15) (const_int 15)])))] + "TARGET_AVX512F" + "vmovshdup\t{%1, %0|%0, %1}" + [(set_attr "type" "sse") + (set_attr "prefix" "evex") + (set_attr "mode" "V16SF")]) + (define_insn "avx_movsldup256" [(set (match_operand:V8SF 0 "register_operand" "=x") (vec_select:V8SF @@ -4316,6 +4679,26 @@ (set_attr "prefix" "maybe_vex") (set_attr "mode" "V4SF")]) +(define_insn "avx512f_movsldup512" + [(set (match_operand:V16SF 0 "register_operand" "=v") + (vec_select:V16SF + (vec_concat:V32SF + (match_operand:V16SF 1 "nonimmediate_operand" "vm") + (match_dup 1)) + (parallel [(const_int 0) (const_int 0) + (const_int 2) (const_int 2) + (const_int 4) (const_int 4) + (const_int 6) (const_int 6) + (const_int 8) (const_int 8) + (const_int 10) (const_int 10) + (const_int 12) (const_int 12) + (const_int 14) (const_int 14)])))] + "TARGET_AVX512F" + "vmovsldup\t{%1, %0|%0, %1}" + [(set_attr "type" "sse") + (set_attr "prefix" "evex") + (set_attr "mode" "V16SF")]) + (define_expand "avx_shufps256" [(match_operand:V8SF 0 "register_operand") (match_operand:V8SF 1 "register_operand") @@ -5050,6 +5433,50 @@ (set_attr "prefix" "vex") (set_attr "mode" "<sseinsnmode>")]) +(define_insn_and_split "vec_extract_lo_v32hi" + [(set (match_operand:V16HI 0 "nonimmediate_operand" "=v,m") + (vec_select:V16HI + (match_operand:V32HI 1 "nonimmediate_operand" "vm,v") + (parallel [(const_int 0) (const_int 1) + (const_int 2) (const_int 3) + (const_int 4) (const_int 5) + (const_int 6) (const_int 7) + (const_int 8) (const_int 9) + (const_int 10) (const_int 11) + (const_int 12) (const_int 13) + (const_int 14) (const_int 15)])))] + "TARGET_AVX512F && !(MEM_P (operands[0]) && MEM_P (operands[1]))" + "#" + "&& reload_completed" + [(set (match_dup 0) (match_dup 1))] +{ + if (REG_P (operands[1])) + operands[1] = gen_rtx_REG (V16HImode, REGNO (operands[1])); + else + operands[1] = adjust_address (operands[1], V16HImode, 0); +}) + +(define_insn "vec_extract_hi_v32hi" + [(set (match_operand:V16HI 0 "nonimmediate_operand" "=v,m") + (vec_select:V16HI + (match_operand:V32HI 1 "nonimmediate_operand" "v,v") + (parallel [(const_int 16) (const_int 17) + (const_int 18) (const_int 19) + (const_int 20) (const_int 21) + (const_int 22) (const_int 23) + (const_int 24) (const_int 25) + (const_int 26) (const_int 27) + (const_int 28) (const_int 29) + (const_int 30) (const_int 31)])))] + "TARGET_AVX512F" + "vextracti64x4\t{$0x1, %1, %0|%0, %1, 0x1}" + [(set_attr "type" "sselog") + (set_attr "prefix_extra" "1") + (set_attr "length_immediate" "1") + (set_attr "memory" "none,store") + (set_attr "prefix" "evex") + (set_attr "mode" "XI")]) + (define_insn_and_split "vec_extract_lo_v16hi" [(set (match_operand:V8HI 0 "nonimmediate_operand" "=x,m") (vec_select:V8HI @@ -5086,6 +5513,66 @@ (set_attr "prefix" "vex") (set_attr "mode" "OI")]) +(define_insn_and_split "vec_extract_lo_v64qi" + [(set (match_operand:V32QI 0 "nonimmediate_operand" "=v,m") + (vec_select:V32QI + (match_operand:V64QI 1 "nonimmediate_operand" "vm,v") + (parallel [(const_int 0) (const_int 1) + (const_int 2) (const_int 3) + (const_int 4) (const_int 5) + (const_int 6) (const_int 7) + (const_int 8) (const_int 9) + (const_int 10) (const_int 11) + (const_int 12) (const_int 13) + (const_int 14) (const_int 15) + (const_int 16) (const_int 17) + (const_int 18) (const_int 19) + (const_int 20) (const_int 21) + (const_int 22) (const_int 23) + (const_int 24) (const_int 25) + (const_int 26) (const_int 27) + (const_int 28) (const_int 29) + (const_int 30) (const_int 31)])))] + "TARGET_AVX512F && !(MEM_P (operands[0]) && MEM_P (operands[1]))" + "#" + "&& reload_completed" + [(set (match_dup 0) (match_dup 1))] +{ + if (REG_P (operands[1])) + operands[1] = gen_rtx_REG (V32QImode, REGNO (operands[1])); + else + operands[1] = adjust_address (operands[1], V32QImode, 0); +}) + +(define_insn "vec_extract_hi_v64qi" + [(set (match_operand:V32QI 0 "nonimmediate_operand" "=v,m") + (vec_select:V32QI + (match_operand:V64QI 1 "nonimmediate_operand" "v,v") + (parallel [(const_int 32) (const_int 33) + (const_int 34) (const_int 35) + (const_int 36) (const_int 37) + (const_int 38) (const_int 39) + (const_int 40) (const_int 41) + (const_int 42) (const_int 43) + (const_int 44) (const_int 45) + (const_int 46) (const_int 47) + (const_int 48) (const_int 49) + (const_int 50) (const_int 51) + (const_int 52) (const_int 53) + (const_int 54) (const_int 55) + (const_int 56) (const_int 57) + (const_int 58) (const_int 59) + (const_int 60) (const_int 61) + (const_int 62) (const_int 63)])))] + "TARGET_AVX512F" + "vextracti64x4\t{$0x1, %1, %0|%0, %1, 0x1}" + [(set_attr "type" "sselog") + (set_attr "prefix_extra" "1") + (set_attr "length_immediate" "1") + (set_attr "memory" "none,store") + (set_attr "prefix" "evex") + (set_attr "mode" "XI")]) + (define_insn_and_split "vec_extract_lo_v32qi" [(set (match_operand:V16QI 0 "nonimmediate_operand" "=x,m") (vec_select:V16QI @@ -5134,10 +5621,10 @@ (define_mode_iterator VEC_EXTRACT_MODE [(V32QI "TARGET_AVX") V16QI (V16HI "TARGET_AVX") V8HI - (V8SI "TARGET_AVX") V4SI - (V4DI "TARGET_AVX") V2DI - (V8SF "TARGET_AVX") V4SF - (V4DF "TARGET_AVX") V2DF]) + (V16SI "TARGET_AVX512F") (V8SI "TARGET_AVX") V4SI + (V8DI "TARGET_AVX512F") (V4DI "TARGET_AVX") V2DI + (V16SF "TARGET_AVX512F") (V8SF "TARGET_AVX") V4SF + (V8DF "TARGET_AVX512F") (V4DF "TARGET_AVX") V2DF]) (define_expand "vec_extract<mode>" [(match_operand:<ssescalarmode> 0 "register_operand") @@ -5156,6 +5643,22 @@ ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +(define_insn "avx512f_unpckhpd512" + [(set (match_operand:V8DF 0 "register_operand" "=v") + (vec_select:V8DF + (vec_concat:V16DF + (match_operand:V8DF 1 "nonimmediate_operand" "v") + (match_operand:V8DF 2 "nonimmediate_operand" "vm")) + (parallel [(const_int 1) (const_int 9) + (const_int 3) (const_int 11) + (const_int 5) (const_int 13) + (const_int 7) (const_int 15)])))] + "TARGET_AVX512F" + "vunpckhpd\t{%2, %1, %0|%0, %1, %2}" + [(set_attr "type" "sselog") + (set_attr "prefix" "evex") + (set_attr "mode" "V8DF")]) + ;; Recall that the 256-bit unpck insns only shuffle within their lanes. (define_insn "avx_unpckhpd256" [(set (match_operand:V4DF 0 "register_operand" "=x") @@ -5236,6 +5739,48 @@ (set_attr "prefix" "orig,vex,maybe_vex,orig,vex,maybe_vex") (set_attr "mode" "V2DF,V2DF,DF,V1DF,V1DF,V1DF")]) +(define_expand "avx512f_movddup512" + [(set (match_operand:V8DF 0 "register_operand") + (vec_select:V8DF + (vec_concat:V16DF + (match_operand:V8DF 1 "nonimmediate_operand") + (match_dup 1)) + (parallel [(const_int 0) (const_int 8) + (const_int 2) (const_int 10) + (const_int 4) (const_int 12) + (const_int 6) (const_int 14)])))] + "TARGET_AVX512F") + +(define_expand "avx512f_unpcklpd512" + [(set (match_operand:V8DF 0 "register_operand") + (vec_select:V8DF + (vec_concat:V16DF + (match_operand:V8DF 1 "register_operand") + (match_operand:V8DF 2 "nonimmediate_operand")) + (parallel [(const_int 0) (const_int 8) + (const_int 2) (const_int 10) + (const_int 4) (const_int 12) + (const_int 6) (const_int 14)])))] + "TARGET_AVX512F") + +(define_insn "*avx512f_unpcklpd512" + [(set (match_operand:V8DF 0 "register_operand" "=v,v") + (vec_select:V8DF + (vec_concat:V16DF + (match_operand:V8DF 1 "nonimmediate_operand" "vm, v") + (match_operand:V8DF 2 "nonimmediate_operand" "1 ,vm")) + (parallel [(const_int 0) (const_int 8) + (const_int 2) (const_int 10) + (const_int 4) (const_int 12) + (const_int 6) (const_int 14)])))] + "TARGET_AVX512F" + "@ + vmovddup\t{%1, %0|%0, %1} + vunpcklpd\t{%2, %1, %0|%0, %1, %2}" + [(set_attr "type" "sselog") + (set_attr "prefix" "evex") + (set_attr "mode" "V8DF")]) + ;; Recall that the 256-bit unpck insns only shuffle within their lanes. (define_expand "avx_movddup256" [(set (match_operand:V4DF 0 "register_operand") @@ -5495,6 +6040,91 @@ (set_attr "prefix" "evex") (set_attr "mode" "<MODE>")]) +;; One bit in mask selects 2 elements. +(define_insn "avx512f_shufps512_1" + [(set (match_operand:V16SF 0 "register_operand" "=v") + (vec_select:V16SF + (vec_concat:V32SF + (match_operand:V16SF 1 "register_operand" "v") + (match_operand:V16SF 2 "nonimmediate_operand" "vm")) + (parallel [(match_operand 3 "const_0_to_3_operand") + (match_operand 4 "const_0_to_3_operand") + (match_operand 5 "const_16_to_19_operand") + (match_operand 6 "const_16_to_19_operand") + (match_operand 7 "const_4_to_7_operand") + (match_operand 8 "const_4_to_7_operand") + (match_operand 9 "const_20_to_23_operand") + (match_operand 10 "const_20_to_23_operand") + (match_operand 11 "const_8_to_11_operand") + (match_operand 12 "const_8_to_11_operand") + (match_operand 13 "const_24_to_27_operand") + (match_operand 14 "const_24_to_27_operand") + (match_operand 15 "const_12_to_15_operand") + (match_operand 16 "const_12_to_15_operand") + (match_operand 17 "const_28_to_31_operand") + (match_operand 18 "const_28_to_31_operand")])))] + "TARGET_AVX512F + && (INTVAL (operands[3]) == (INTVAL (operands[7]) - 4) + && INTVAL (operands[4]) == (INTVAL (operands[8]) - 4) + && INTVAL (operands[5]) == (INTVAL (operands[9]) - 4) + && INTVAL (operands[6]) == (INTVAL (operands[10]) - 4) + && INTVAL (operands[3]) == (INTVAL (operands[11]) - 8) + && INTVAL (operands[4]) == (INTVAL (operands[12]) - 8) + && INTVAL (operands[5]) == (INTVAL (operands[13]) - 8) + && INTVAL (operands[6]) == (INTVAL (operands[14]) - 8) + && INTVAL (operands[3]) == (INTVAL (operands[15]) - 12) + && INTVAL (operands[4]) == (INTVAL (operands[16]) - 12) + && INTVAL (operands[5]) == (INTVAL (operands[17]) - 12) + && INTVAL (operands[6]) == (INTVAL (operands[18]) - 12))" +{ + int mask; + mask = INTVAL (operands[3]); + mask |= INTVAL (operands[4]) << 2; + mask |= (INTVAL (operands[5]) - 16) << 4; + mask |= (INTVAL (operands[6]) - 16) << 6; + operands[3] = GEN_INT (mask); + + return "vshufps\t{%3, %2, %1, %0|%0, %1, %2, %3}"; +} + [(set_attr "type" "sselog") + (set_attr "length_immediate" "1") + (set_attr "prefix" "evex") + (set_attr "mode" "V16SF")]) + +(define_insn "avx512f_shufpd512_1" + [(set (match_operand:V8DF 0 "register_operand" "=v") + (vec_select:V8DF + (vec_concat:V16DF + (match_operand:V8DF 1 "register_operand" "v") + (match_operand:V8DF 2 "nonimmediate_operand" "vm")) + (parallel [(match_operand 3 "const_0_to_1_operand") + (match_operand 4 "const_8_to_9_operand") + (match_operand 5 "const_2_to_3_operand") + (match_operand 6 "const_10_to_11_operand") + (match_operand 7 "const_4_to_5_operand") + (match_operand 8 "const_12_to_13_operand") + (match_operand 9 "const_6_to_7_operand") + (match_operand 10 "const_14_to_15_operand")])))] + "TARGET_AVX512F" +{ + int mask; + mask = INTVAL (operands[3]); + mask |= (INTVAL (operands[4]) - 8) << 1; + mask |= (INTVAL (operands[5]) - 2) << 2; + mask |= (INTVAL (operands[6]) - 10) << 3; + mask |= (INTVAL (operands[7]) - 4) << 4; + mask |= (INTVAL (operands[8]) - 12) << 5; + mask |= (INTVAL (operands[9]) - 6) << 6; + mask |= (INTVAL (operands[10]) - 14) << 7; + operands[3] = GEN_INT (mask); + + return "vshufpd\t{%3, %2, %1, %0|%0, %1, %2, %3}"; +} + [(set_attr "type" "sselog") + (set_attr "length_immediate" "1") + (set_attr "prefix" "evex") + (set_attr "mode" "V8DF")]) + (define_expand "avx_shufpd256" [(match_operand:V4DF 0 "register_operand") (match_operand:V4DF 1 "register_operand") @@ -5568,6 +6198,22 @@ (set_attr "prefix" "vex") (set_attr "mode" "OI")]) +(define_insn "avx512f_interleave_highv8di" + [(set (match_operand:V8DI 0 "register_operand" "=v") + (vec_select:V8DI + (vec_concat:V16DI + (match_operand:V8DI 1 "register_operand" "v") + (match_operand:V8DI 2 "nonimmediate_operand" "vm")) + (parallel [(const_int 1) (const_int 9) + (const_int 3) (const_int 11) + (const_int 5) (const_int 13) + (const_int 7) (const_int 15)])))] + "TARGET_AVX512F" + "vpunpckhqdq\t{%2, %1, %0|%0, %1, %2}" + [(set_attr "type" "sselog") + (set_attr "prefix" "evex") + (set_attr "mode" "XI")]) + (define_insn "vec_interleave_highv2di" [(set (match_operand:V2DI 0 "register_operand" "=x,x") (vec_select:V2DI @@ -5602,6 +6248,22 @@ (set_attr "prefix" "vex") (set_attr "mode" "OI")]) +(define_insn "avx512f_interleave_lowv8di" + [(set (match_operand:V8DI 0 "register_operand" "=v") + (vec_select:V8DI + (vec_concat:V16DI + (match_operand:V8DI 1 "register_operand" "v") + (match_operand:V8DI 2 "nonimmediate_operand" "vm")) + (parallel [(const_int 0) (const_int 8) + (const_int 2) (const_int 10) + (const_int 4) (const_int 12) + (const_int 6) (const_int 14)])))] + "TARGET_AVX512F" + "vpunpcklqdq\t{%2, %1, %0|%0, %1, %2}" + [(set_attr "type" "sselog") + (set_attr "prefix" "evex") + (set_attr "mode" "XI")]) + (define_insn "vec_interleave_lowv2di" [(set (match_operand:V2DI 0 "register_operand" "=x,x") (vec_select:V2DI @@ -5945,6 +6607,64 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; +;; Parallel integer down-conversion operations +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(define_mode_iterator PMOV_DST_MODE [V16QI V16HI V8SI V8HI]) +(define_mode_attr pmov_src_mode + [(V16QI "V16SI") (V16HI "V16SI") (V8SI "V8DI") (V8HI "V8DI")]) +(define_mode_attr pmov_src_lower + [(V16QI "v16si") (V16HI "v16si") (V8SI "v8di") (V8HI "v8di")]) +(define_mode_attr pmov_suff + [(V16QI "db") (V16HI "dw") (V8SI "qd") (V8HI "qw")]) + +(define_insn "*avx512f_<code><pmov_src_lower><mode>2" + [(set (match_operand:PMOV_DST_MODE 0 "nonimmediate_operand" "=v,m") + (any_truncate:PMOV_DST_MODE + (match_operand:<pmov_src_mode> 1 "register_operand" "v,v")))] + "TARGET_AVX512F" + "vpmov<trunsuffix><pmov_suff>\t{%1, %0|%0, %1}" + [(set_attr "type" "ssemov") + (set_attr "memory" "none,store") + (set_attr "prefix" "evex") + (set_attr "mode" "<sseinsnmode>")]) + +(define_insn "*avx512f_<code>v8div16qi2" + [(set (match_operand:V16QI 0 "register_operand" "=v") + (vec_concat:V16QI + (any_truncate:V8QI + (match_operand:V8DI 1 "register_operand" "v")) + (const_vector:V8QI [(const_int 0) (const_int 0) + (const_int 0) (const_int 0) + (const_int 0) (const_int 0) + (const_int 0) (const_int 0)])))] + "TARGET_AVX512F" + "vpmov<trunsuffix>qb\t{%1, %0|%0, %1}" + [(set_attr "type" "ssemov") + (set_attr "prefix" "evex") + (set_attr "mode" "TI")]) + +(define_insn "*avx512f_<code>v8div16qi2_store" + [(set (match_operand:V16QI 0 "memory_operand" "=m") + (vec_concat:V16QI + (any_truncate:V8QI + (match_operand:V8DI 1 "register_operand" "v")) + (vec_select:V8QI + (match_dup 0) + (parallel [(const_int 8) (const_int 9) + (const_int 10) (const_int 11) + (const_int 12) (const_int 13) + (const_int 14) (const_int 15)]))))] + "TARGET_AVX512F" + "vpmov<trunsuffix>qb\t{%1, %0|%0, %1}" + [(set_attr "type" "ssemov") + (set_attr "memory" "store") + (set_attr "prefix" "evex") + (set_attr "mode" "TI")]) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; Parallel integral arithmetic ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -6067,6 +6787,51 @@ (set_attr "prefix" "orig,vex") (set_attr "mode" "<sseinsnmode>")]) +(define_expand "vec_widen_umult_even_v16si" + [(set (match_operand:V8DI 0 "register_operand") + (mult:V8DI + (zero_extend:V8DI + (vec_select:V8SI + (match_operand:V16SI 1 "nonimmediate_operand") + (parallel [(const_int 0) (const_int 2) + (const_int 4) (const_int 6) + (const_int 8) (const_int 10) + (const_int 12) (const_int 14)]))) + (zero_extend:V8DI + (vec_select:V8SI + (match_operand:V16SI 2 "nonimmediate_operand") + (parallel [(const_int 0) (const_int 2) + (const_int 4) (const_int 6) + (const_int 8) (const_int 10) + (const_int 12) (const_int 14)])))))] + "TARGET_AVX512F" + "ix86_fixup_binary_operands_no_copy (MULT, V16SImode, operands);") + +(define_insn "*vec_widen_umult_even_v16si" + [(set (match_operand:V8DI 0 "register_operand" "=v") + (mult:V8DI + (zero_extend:V8DI + (vec_select:V8SI + (match_operand:V16SI 1 "nonimmediate_operand" "%v") + (parallel [(const_int 0) (const_int 2) + (const_int 4) (const_int 6) + (const_int 8) (const_int 10) + (const_int 12) (const_int 14)]))) + (zero_extend:V8DI + (vec_select:V8SI + (match_operand:V16SI 2 "nonimmediate_operand" "vm") + (parallel [(const_int 0) (const_int 2) + (const_int 4) (const_int 6) + (const_int 8) (const_int 10) + (const_int 12) (const_int 14)])))))] + "TARGET_AVX512F && ix86_binary_operator_ok (MULT, V16SImode, operands)" + "vpmuludq\t{%2, %1, %0|%0, %1, %2}" + [(set_attr "isa" "avx512f") + (set_attr "type" "sseimul") + (set_attr "prefix_extra" "1") + (set_attr "prefix" "evex") + (set_attr "mode" "XI")]) + (define_expand "vec_widen_umult_even_v8si" [(set (match_operand:V4DI 0 "register_operand") (mult:V4DI @@ -6137,6 +6902,51 @@ (set_attr "prefix" "orig,vex") (set_attr "mode" "TI")]) +(define_expand "vec_widen_smult_even_v16si" + [(set (match_operand:V8DI 0 "register_operand") + (mult:V8DI + (sign_extend:V8DI + (vec_select:V8SI + (match_operand:V16SI 1 "nonimmediate_operand") + (parallel [(const_int 0) (const_int 2) + (const_int 4) (const_int 6) + (const_int 8) (const_int 10) + (const_int 12) (const_int 14)]))) + (sign_extend:V8DI + (vec_select:V8SI + (match_operand:V16SI 2 "nonimmediate_operand") + (parallel [(const_int 0) (const_int 2) + (const_int 4) (const_int 6) + (const_int 8) (const_int 10) + (const_int 12) (const_int 14)])))))] + "TARGET_AVX512F" + "ix86_fixup_binary_operands_no_copy (MULT, V16SImode, operands);") + +(define_insn "*vec_widen_smult_even_v16si" + [(set (match_operand:V8DI 0 "register_operand" "=v") + (mult:V8DI + (sign_extend:V8DI + (vec_select:V8SI + (match_operand:V16SI 1 "nonimmediate_operand" "%v") + (parallel [(const_int 0) (const_int 2) + (const_int 4) (const_int 6) + (const_int 8) (const_int 10) + (const_int 12) (const_int 14)]))) + (sign_extend:V8DI + (vec_select:V8SI + (match_operand:V16SI 2 "nonimmediate_operand" "vm") + (parallel [(const_int 0) (const_int 2) + (const_int 4) (const_int 6) + (const_int 8) (const_int 10) + (const_int 12) (const_int 14)])))))] + "TARGET_AVX512F && ix86_binary_operator_ok (MULT, V16SImode, operands)" + "vpmuldq\t{%2, %1, %0|%0, %1, %2}" + [(set_attr "isa" "avx512f") + (set_attr "type" "sseimul") + (set_attr "prefix_extra" "1") + (set_attr "prefix" "evex") + (set_attr "mode" "XI")]) + (define_expand "vec_widen_smult_even_v8si" [(set (match_operand:V4DI 0 "register_operand") (mult:V4DI @@ -6523,14 +7333,16 @@ (set_attr "mode" "<sseinsnmode>")]) (define_expand "vec_shl_<mode>" - [(set (match_operand:VI_128 0 "register_operand") + [(set (match_dup 3) (ashift:V1TI (match_operand:VI_128 1 "register_operand") - (match_operand:SI 2 "const_0_to_255_mul_8_operand")))] + (match_operand:SI 2 "const_0_to_255_mul_8_operand"))) + (set (match_operand:VI_128 0 "register_operand") (match_dup 4))] "TARGET_SSE2" { - operands[0] = gen_lowpart (V1TImode, operands[0]); operands[1] = gen_lowpart (V1TImode, operands[1]); + operands[3] = gen_reg_rtx (V1TImode); + operands[4] = gen_lowpart (<MODE>mode, operands[3]); }) (define_insn "<sse2_avx2>_ashl<mode>3" @@ -6560,14 +7372,16 @@ (set_attr "mode" "<sseinsnmode>")]) (define_expand "vec_shr_<mode>" - [(set (match_operand:VI_128 0 "register_operand") + [(set (match_dup 3) (lshiftrt:V1TI (match_operand:VI_128 1 "register_operand") - (match_operand:SI 2 "const_0_to_255_mul_8_operand")))] + (match_operand:SI 2 "const_0_to_255_mul_8_operand"))) + (set (match_operand:VI_128 0 "register_operand") (match_dup 4))] "TARGET_SSE2" { - operands[0] = gen_lowpart (V1TImode, operands[0]); operands[1] = gen_lowpart (V1TImode, operands[1]); + operands[3] = gen_reg_rtx (V1TImode); + operands[4] = gen_lowpart (<MODE>mode, operands[3]); }) (define_insn "<sse2_avx2>_lshr<mode>3" @@ -7108,7 +7922,9 @@ [V16QI V8HI V4SI V2DI V4SF V2DF (V32QI "TARGET_AVX2") (V16HI "TARGET_AVX2") (V8SI "TARGET_AVX2") (V4DI "TARGET_AVX2") - (V8SF "TARGET_AVX2") (V4DF "TARGET_AVX2")]) + (V8SF "TARGET_AVX2") (V4DF "TARGET_AVX2") + (V16SF "TARGET_AVX512F") (V8DF "TARGET_AVX512F") + (V16SI "TARGET_AVX512F") (V8DI "TARGET_AVX512F")]) (define_expand "vec_perm<mode>" [(match_operand:VEC_PERM_AVX2 0 "register_operand") @@ -7127,7 +7943,9 @@ (V16QI "TARGET_SSE2") (V8HI "TARGET_SSE2") (V8SF "TARGET_AVX") (V4DF "TARGET_AVX") (V8SI "TARGET_AVX") (V4DI "TARGET_AVX") - (V32QI "TARGET_AVX2") (V16HI "TARGET_AVX2")]) + (V32QI "TARGET_AVX2") (V16HI "TARGET_AVX2") + (V16SI "TARGET_AVX512F") (V8DI "TARGET_AVX512F") + (V16SF "TARGET_AVX512F") (V8DF "TARGET_AVX512F")]) (define_expand "vec_perm_const<mode>" [(match_operand:VEC_PERM_CONST 0 "register_operand") @@ -7632,6 +8450,27 @@ (set_attr "prefix" "vex") (set_attr "mode" "OI")]) +(define_insn "avx512f_interleave_highv16si" + [(set (match_operand:V16SI 0 "register_operand" "=v") + (vec_select:V16SI + (vec_concat:V32SI + (match_operand:V16SI 1 "register_operand" "v") + (match_operand:V16SI 2 "nonimmediate_operand" "vm")) + (parallel [(const_int 2) (const_int 18) + (const_int 3) (const_int 19) + (const_int 6) (const_int 22) + (const_int 7) (const_int 23) + (const_int 10) (const_int 26) + (const_int 11) (const_int 27) + (const_int 14) (const_int 30) + (const_int 15) (const_int 31)])))] + "TARGET_AVX512F" + "vpunpckhdq\t{%2, %1, %0|%0, %1, %2}" + [(set_attr "type" "sselog") + (set_attr "prefix" "evex") + (set_attr "mode" "XI")]) + + (define_insn "vec_interleave_highv4si" [(set (match_operand:V4SI 0 "register_operand" "=x,x") (vec_select:V4SI @@ -7666,6 +8505,26 @@ (set_attr "prefix" "vex") (set_attr "mode" "OI")]) +(define_insn "avx512f_interleave_lowv16si" + [(set (match_operand:V16SI 0 "register_operand" "=v") + (vec_select:V16SI + (vec_concat:V32SI + (match_operand:V16SI 1 "register_operand" "v") + (match_operand:V16SI 2 "nonimmediate_operand" "vm")) + (parallel [(const_int 0) (const_int 16) + (const_int 1) (const_int 17) + (const_int 4) (const_int 20) + (const_int 5) (const_int 21) + (const_int 8) (const_int 24) + (const_int 9) (const_int 25) + (const_int 12) (const_int 28) + (const_int 13) (const_int 29)])))] + "TARGET_AVX512F" + "vpunpckldq\t{%2, %1, %0|%0, %1, %2}" + [(set_attr "type" "sselog") + (set_attr "prefix" "evex") + (set_attr "mode" "XI")]) + (define_insn "vec_interleave_lowv4si" [(set (match_operand:V4SI 0 "register_operand" "=x,x") (vec_select:V4SI @@ -7692,12 +8551,13 @@ { rtx t1 = gen_reg_rtx (<MODE>mode); rtx t2 = gen_reg_rtx (<MODE>mode); + rtx t3 = gen_reg_rtx (V4DImode); emit_insn (gen_avx2_interleave_low<mode> (t1, operands[1], operands[2])); emit_insn (gen_avx2_interleave_high<mode> (t2, operands[1], operands[2])); - emit_insn (gen_avx2_permv2ti - (gen_lowpart (V4DImode, operands[0]), - gen_lowpart (V4DImode, t1), - gen_lowpart (V4DImode, t2), GEN_INT (1 + (3 << 4)))); + emit_insn (gen_avx2_permv2ti (t3, gen_lowpart (V4DImode, t1), + gen_lowpart (V4DImode, t2), + GEN_INT (1 + (3 << 4)))); + emit_move_insn (operands[0], gen_lowpart (<MODE>mode, t3)); DONE; }) @@ -7709,12 +8569,13 @@ { rtx t1 = gen_reg_rtx (<MODE>mode); rtx t2 = gen_reg_rtx (<MODE>mode); + rtx t3 = gen_reg_rtx (V4DImode); emit_insn (gen_avx2_interleave_low<mode> (t1, operands[1], operands[2])); emit_insn (gen_avx2_interleave_high<mode> (t2, operands[1], operands[2])); - emit_insn (gen_avx2_permv2ti - (gen_lowpart (V4DImode, operands[0]), - gen_lowpart (V4DImode, t1), - gen_lowpart (V4DImode, t2), GEN_INT (0 + (2 << 4)))); + emit_insn (gen_avx2_permv2ti (t3, gen_lowpart (V4DImode, t1), + gen_lowpart (V4DImode, t2), + GEN_INT (0 + (2 << 4)))); + emit_move_insn (operands[0], gen_lowpart (<MODE>mode, t3)); DONE; }) @@ -8628,7 +9489,7 @@ "@ pinsrq\t{$1, %2, %0|%0, %2, 1} vpinsrq\t{$1, %2, %1, %0|%0, %1, %2, 1} - %vmovd\t{%1, %0|%0, %1} + * return HAVE_AS_IX86_INTERUNIT_MOVQ ? \"%vmovq\t{%1, %0|%0, %1}\" : \"%vmovd\t{%1, %0|%0, %1}\"; %vmovq\t{%1, %0|%0, %1} movq2dq\t{%1, %0|%0, %1} punpcklqdq\t{%2, %0|%0, %2} @@ -9420,7 +10281,7 @@ (set (attr "prefix_rex") (symbol_ref "x86_extended_reg_mentioned_p (insn)")) (set_attr "mode" "DI")]) -(define_insn "abs<mode>2" +(define_insn "*abs<mode>2" [(set (match_operand:VI124_AVX2_48_AVX512F 0 "register_operand" "=v") (abs:VI124_AVX2_48_AVX512F (match_operand:VI124_AVX2_48_AVX512F 1 "nonimmediate_operand" "vm")))] @@ -9432,6 +10293,19 @@ (set_attr "prefix" "maybe_vex") (set_attr "mode" "<sseinsnmode>")]) +(define_expand "abs<mode>2" + [(set (match_operand:VI124_AVX2_48_AVX512F 0 "register_operand") + (abs:VI124_AVX2_48_AVX512F + (match_operand:VI124_AVX2_48_AVX512F 1 "nonimmediate_operand")))] + "TARGET_SSE2" +{ + if (!TARGET_SSSE3) + { + ix86_expand_sse2_abs (operands[0], operands[1]); + DONE; + } +}) + (define_insn "abs<mode>2" [(set (match_operand:MMXMODEI 0 "register_operand" "=y") (abs:MMXMODEI @@ -9766,6 +10640,16 @@ (set_attr "prefix" "maybe_vex") (set_attr "mode" "TI")]) +(define_insn "avx512f_<code>v16qiv16si2" + [(set (match_operand:V16SI 0 "register_operand" "=v") + (any_extend:V16SI + (match_operand:V16QI 1 "nonimmediate_operand" "vm")))] + "TARGET_AVX512F" + "vpmov<extsuffix>bd\t{%1, %0|%0, %q1}" + [(set_attr "type" "ssemov") + (set_attr "prefix" "evex") + (set_attr "mode" "XI")]) + (define_insn "avx2_<code>v8qiv8si2" [(set (match_operand:V8SI 0 "register_operand" "=x") (any_extend:V8SI @@ -9796,6 +10680,16 @@ (set_attr "prefix" "maybe_vex") (set_attr "mode" "TI")]) +(define_insn "avx512f_<code>v16hiv16si2" + [(set (match_operand:V16SI 0 "register_operand" "=v") + (any_extend:V16SI + (match_operand:V16HI 1 "nonimmediate_operand" "vm")))] + "TARGET_AVX512F" + "vpmov<extsuffix>wd\t{%1, %0|%0, %1}" + [(set_attr "type" "ssemov") + (set_attr "prefix" "evex") + (set_attr "mode" "XI")]) + (define_insn "avx2_<code>v8hiv8si2" [(set (match_operand:V8SI 0 "register_operand" "=x") (any_extend:V8SI @@ -9821,6 +10715,21 @@ (set_attr "prefix" "maybe_vex") (set_attr "mode" "TI")]) +(define_insn "avx512f_<code>v8qiv8di2" + [(set (match_operand:V8DI 0 "register_operand" "=v") + (any_extend:V8DI + (vec_select:V8QI + (match_operand:V16QI 1 "nonimmediate_operand" "vm") + (parallel [(const_int 0) (const_int 1) + (const_int 2) (const_int 3) + (const_int 4) (const_int 5) + (const_int 6) (const_int 7)]))))] + "TARGET_AVX512F" + "vpmov<extsuffix>bq\t{%1, %0|%0, %k1}" + [(set_attr "type" "ssemov") + (set_attr "prefix" "evex") + (set_attr "mode" "XI")]) + (define_insn "avx2_<code>v4qiv4di2" [(set (match_operand:V4DI 0 "register_operand" "=x") (any_extend:V4DI @@ -9848,6 +10757,16 @@ (set_attr "prefix" "maybe_vex") (set_attr "mode" "TI")]) +(define_insn "avx512f_<code>v8hiv8di2" + [(set (match_operand:V8DI 0 "register_operand" "=v") + (any_extend:V8DI + (match_operand:V8HI 1 "nonimmediate_operand" "vm")))] + "TARGET_AVX512F" + "vpmov<extsuffix>wq\t{%1, %0|%0, %q1}" + [(set_attr "type" "ssemov") + (set_attr "prefix" "evex") + (set_attr "mode" "XI")]) + (define_insn "avx2_<code>v4hiv4di2" [(set (match_operand:V4DI 0 "register_operand" "=x") (any_extend:V4DI @@ -9875,6 +10794,16 @@ (set_attr "prefix" "maybe_vex") (set_attr "mode" "TI")]) +(define_insn "avx512f_<code>v8siv8di2" + [(set (match_operand:V8DI 0 "register_operand" "=v") + (any_extend:V8DI + (match_operand:V8SI 1 "nonimmediate_operand" "vm")))] + "TARGET_AVX512F" + "vpmov<extsuffix>dq\t{%1, %0|%0, %1}" + [(set_attr "type" "ssemov") + (set_attr "prefix" "evex") + (set_attr "mode" "XI")]) + (define_insn "avx2_<code>v4siv4di2" [(set (match_operand:V4DI 0 "register_operand" "=x") (any_extend:V4DI @@ -10533,7 +11462,7 @@ [(match_operand:<avx512fmaskmode> 0 "register_operand" "k") (match_operator:<ssescalarmode> 5 "vsib_mem_operator" [(unspec:P - [(match_operand:P 2 "vsib_address_operand" "p") + [(match_operand:P 2 "vsib_address_operand" "Tv") (match_operand:VI48_512 1 "register_operand" "v") (match_operand:SI 3 "const1248_operand" "n")] UNSPEC_VSIBADDR)]) @@ -10560,7 +11489,7 @@ [(const_int -1) (match_operator:<ssescalarmode> 4 "vsib_mem_operator" [(unspec:P - [(match_operand:P 1 "vsib_address_operand" "p") + [(match_operand:P 1 "vsib_address_operand" "Tv") (match_operand:VI48_512 0 "register_operand" "v") (match_operand:SI 2 "const1248_operand" "n")] UNSPEC_VSIBADDR)]) @@ -10604,7 +11533,7 @@ [(match_operand:<avx512fmaskmode> 0 "register_operand" "k") (match_operator:<ssescalarmode> 5 "vsib_mem_operator" [(unspec:P - [(match_operand:P 2 "vsib_address_operand" "p") + [(match_operand:P 2 "vsib_address_operand" "Tv") (match_operand:VI48_512 1 "register_operand" "v") (match_operand:SI 3 "const1248_operand" "n")] UNSPEC_VSIBADDR)]) @@ -10631,7 +11560,7 @@ [(const_int -1) (match_operator:<ssescalarmode> 4 "vsib_mem_operator" [(unspec:P - [(match_operand:P 1 "vsib_address_operand" "p") + [(match_operand:P 1 "vsib_address_operand" "Tv") (match_operand:VI48_512 0 "register_operand" "v") (match_operand:SI 2 "const1248_operand" "n")] UNSPEC_VSIBADDR)]) @@ -11271,6 +12200,12 @@ } }) +(define_expand "vashrv16si3" + [(set (match_operand:V16SI 0 "register_operand") + (ashiftrt:V16SI (match_operand:V16SI 1 "register_operand") + (match_operand:V16SI 2 "nonimmediate_operand")))] + "TARGET_AVX512F") + (define_expand "vashrv8si3" [(set (match_operand:V8SI 0 "register_operand") (ashiftrt:V8SI (match_operand:V8SI 1 "register_operand") @@ -11911,6 +12846,28 @@ (set_attr "prefix" "vex") (set_attr "mode" "<sseinsnmode>")]) +(define_insn "avx512cd_maskb_vec_dupv8di" + [(set (match_operand:V8DI 0 "register_operand" "=v") + (vec_duplicate:V8DI + (zero_extend:DI + (match_operand:QI 1 "register_operand" "k"))))] + "TARGET_AVX512CD" + "vpbroadcastmb2q\t{%1, %0|%0, %1}" + [(set_attr "type" "mskmov") + (set_attr "prefix" "evex") + (set_attr "mode" "XI")]) + +(define_insn "avx512cd_maskw_vec_dupv16si" + [(set (match_operand:V16SI 0 "register_operand" "=v") + (vec_duplicate:V16SI + (zero_extend:SI + (match_operand:HI 1 "register_operand" "k"))))] + "TARGET_AVX512CD" + "vpbroadcastmw2d\t{%1, %0|%0, %1}" + [(set_attr "type" "mskmov") + (set_attr "prefix" "evex") + (set_attr "mode" "XI")]) + ;; Recognize broadcast as a vec_select as produced by builtin_vec_perm. ;; If it so happens that the input is in memory, use vbroadcast. ;; Otherwise use vpermilp (and in the case of 256-bit modes, vperm2f128). @@ -12578,6 +13535,16 @@ (set_attr "btver2_decode" "double") (set_attr "mode" "V8SF")]) +(define_insn "avx512f_vcvtph2ps512" + [(set (match_operand:V16SF 0 "register_operand" "=v") + (unspec:V16SF [(match_operand:V16HI 1 "nonimmediate_operand" "vm")] + UNSPEC_VCVTPH2PS))] + "TARGET_AVX512F" + "vcvtph2ps\t{%1, %0|%0, %1}" + [(set_attr "type" "ssecvt") + (set_attr "prefix" "evex") + (set_attr "mode" "V16SF")]) + (define_expand "vcvtps2ph" [(set (match_operand:V8HI 0 "register_operand") (vec_concat:V8HI @@ -12624,6 +13591,17 @@ (set_attr "btver2_decode" "vector") (set_attr "mode" "V8SF")]) +(define_insn "avx512f_vcvtps2ph512" + [(set (match_operand:V16HI 0 "nonimmediate_operand" "=vm") + (unspec:V16HI [(match_operand:V16SF 1 "register_operand" "v") + (match_operand:SI 2 "const_0_to_255_operand" "N")] + UNSPEC_VCVTPS2PH))] + "TARGET_AVX512F" + "vcvtps2ph\t{%2, %1, %0|%0, %1, %2}" + [(set_attr "type" "ssecvt") + (set_attr "prefix" "evex") + (set_attr "mode" "V16SF")]) + ;; For gather* insn patterns (define_mode_iterator VEC_GATHER_MODE [V2DI V2DF V4DI V4DF V4SI V4SF V8SI V8SF]) @@ -12672,7 +13650,7 @@ [(match_operand:VEC_GATHER_MODE 2 "register_operand" "0") (match_operator:<ssescalarmode> 7 "vsib_mem_operator" [(unspec:P - [(match_operand:P 3 "vsib_address_operand" "p") + [(match_operand:P 3 "vsib_address_operand" "Tv") (match_operand:<VEC_GATHER_IDXSI> 4 "register_operand" "x") (match_operand:SI 6 "const1248_operand" "n")] UNSPEC_VSIBADDR)]) @@ -12692,7 +13670,7 @@ [(pc) (match_operator:<ssescalarmode> 6 "vsib_mem_operator" [(unspec:P - [(match_operand:P 2 "vsib_address_operand" "p") + [(match_operand:P 2 "vsib_address_operand" "Tv") (match_operand:<VEC_GATHER_IDXSI> 3 "register_operand" "x") (match_operand:SI 5 "const1248_operand" "n")] UNSPEC_VSIBADDR)]) @@ -12734,7 +13712,7 @@ [(match_operand:<VEC_GATHER_SRCDI> 2 "register_operand" "0") (match_operator:<ssescalarmode> 7 "vsib_mem_operator" [(unspec:P - [(match_operand:P 3 "vsib_address_operand" "p") + [(match_operand:P 3 "vsib_address_operand" "Tv") (match_operand:<VEC_GATHER_IDXDI> 4 "register_operand" "x") (match_operand:SI 6 "const1248_operand" "n")] UNSPEC_VSIBADDR)]) @@ -12754,7 +13732,7 @@ [(pc) (match_operator:<ssescalarmode> 6 "vsib_mem_operator" [(unspec:P - [(match_operand:P 2 "vsib_address_operand" "p") + [(match_operand:P 2 "vsib_address_operand" "Tv") (match_operand:<VEC_GATHER_IDXDI> 3 "register_operand" "x") (match_operand:SI 5 "const1248_operand" "n")] UNSPEC_VSIBADDR)]) @@ -12779,7 +13757,7 @@ [(match_operand:<VEC_GATHER_SRCDI> 2 "register_operand" "0") (match_operator:<ssescalarmode> 7 "vsib_mem_operator" [(unspec:P - [(match_operand:P 3 "vsib_address_operand" "p") + [(match_operand:P 3 "vsib_address_operand" "Tv") (match_operand:<VEC_GATHER_IDXDI> 4 "register_operand" "x") (match_operand:SI 6 "const1248_operand" "n")] UNSPEC_VSIBADDR)]) @@ -12802,7 +13780,7 @@ [(pc) (match_operator:<ssescalarmode> 6 "vsib_mem_operator" [(unspec:P - [(match_operand:P 2 "vsib_address_operand" "p") + [(match_operand:P 2 "vsib_address_operand" "Tv") (match_operand:<VEC_GATHER_IDXDI> 3 "register_operand" "x") (match_operand:SI 5 "const1248_operand" "n")] UNSPEC_VSIBADDR)]) @@ -12844,7 +13822,7 @@ (match_operand:<avx512fmaskmode> 7 "register_operand" "2") (match_operator:<ssescalarmode> 6 "vsib_mem_operator" [(unspec:P - [(match_operand:P 4 "vsib_address_operand" "p") + [(match_operand:P 4 "vsib_address_operand" "Tv") (match_operand:<VEC_GATHER_IDXSI> 3 "register_operand" "v") (match_operand:SI 5 "const1248_operand" "n")] UNSPEC_VSIBADDR)])] @@ -12863,7 +13841,7 @@ (match_operand:<avx512fmaskmode> 6 "register_operand" "1") (match_operator:<ssescalarmode> 5 "vsib_mem_operator" [(unspec:P - [(match_operand:P 3 "vsib_address_operand" "p") + [(match_operand:P 3 "vsib_address_operand" "Tv") (match_operand:<VEC_GATHER_IDXSI> 2 "register_operand" "v") (match_operand:SI 4 "const1248_operand" "n")] UNSPEC_VSIBADDR)])] @@ -12902,7 +13880,7 @@ (match_operand:QI 7 "register_operand" "2") (match_operator:<ssescalarmode> 6 "vsib_mem_operator" [(unspec:P - [(match_operand:P 4 "vsib_address_operand" "p") + [(match_operand:P 4 "vsib_address_operand" "Tv") (match_operand:<VEC_GATHER_IDXDI> 3 "register_operand" "v") (match_operand:SI 5 "const1248_operand" "n")] UNSPEC_VSIBADDR)])] @@ -12921,7 +13899,7 @@ (match_operand:QI 6 "register_operand" "1") (match_operator:<ssescalarmode> 5 "vsib_mem_operator" [(unspec:P - [(match_operand:P 3 "vsib_address_operand" "p") + [(match_operand:P 3 "vsib_address_operand" "Tv") (match_operand:<VEC_GATHER_IDXDI> 2 "register_operand" "v") (match_operand:SI 4 "const1248_operand" "n")] UNSPEC_VSIBADDR)])] @@ -12958,7 +13936,7 @@ (define_insn "*avx512f_scattersi<mode>" [(set (match_operator:VI48F_512 5 "vsib_mem_operator" [(unspec:P - [(match_operand:P 0 "vsib_address_operand" "p") + [(match_operand:P 0 "vsib_address_operand" "Tv") (match_operand:<VEC_GATHER_IDXSI> 2 "register_operand" "v") (match_operand:SI 4 "const1248_operand" "n")] UNSPEC_VSIBADDR)]) @@ -12994,7 +13972,7 @@ (define_insn "*avx512f_scatterdi<mode>" [(set (match_operator:VI48F_512 5 "vsib_mem_operator" [(unspec:P - [(match_operand:P 0 "vsib_address_operand" "p") + [(match_operand:P 0 "vsib_address_operand" "Tv") (match_operand:V8DI 2 "register_operand" "v") (match_operand:SI 4 "const1248_operand" "n")] UNSPEC_VSIBADDR)]) diff --git a/gcc/config/i386/winnt.c b/gcc/config/i386/winnt.c index 58e95a3790b..94155d89a7f 100644 --- a/gcc/config/i386/winnt.c +++ b/gcc/config/i386/winnt.c @@ -35,6 +35,7 @@ along with GCC; see the file COPYING3. If not see #include "ggc.h" #include "target.h" #include "except.h" +#include "gimple.h" #include "lto-streamer.h" /* i386/PE specific attribute support. diff --git a/gcc/config/i386/x86-tune.def b/gcc/config/i386/x86-tune.def index 4d238af212d..6e5d2fe0aff 100644 --- a/gcc/config/i386/x86-tune.def +++ b/gcc/config/i386/x86-tune.def @@ -18,61 +18,54 @@ a copy of the GCC Runtime Library Exception along with this program; see the files COPYING3 and COPYING.RUNTIME respectively. If not, see <http://www.gnu.org/licenses/>. */ -/* X86_TUNE_USE_LEAVE: Use "leave" instruction in epilogues where it fits. */ -DEF_TUNE (X86_TUNE_USE_LEAVE, "use_leave", - m_386 | m_CORE_ALL | m_K6_GEODE | m_AMD_MULTIPLE | m_GENERIC) - -/* X86_TUNE_PUSH_MEMORY: Enable generation of "push mem" instructions. - Some chips, like 486 and Pentium works faster with separate load - and push instructions. */ -DEF_TUNE (X86_TUNE_PUSH_MEMORY, "push_memory", - m_386 | m_P4_NOCONA | m_CORE_ALL | m_K6_GEODE | m_AMD_MULTIPLE - | m_GENERIC) - -/* X86_TUNE_ZERO_EXTEND_WITH_AND: Use AND instruction instead - of mozbl/movwl. */ -DEF_TUNE (X86_TUNE_ZERO_EXTEND_WITH_AND, "zero_extend_with_and", m_486 | m_PENT) +/* Tuning for a given CPU XXXX consists of: + - adding new CPU into: + - adding PROCESSOR_XXX to processor_type (in i386.h) + - possibly adding XXX into CPU attribute in i386.md + - adding XXX to processor_alias_table (in i386.c) + - introducing ix86_XXX_cost in i386.c + - Stringop generation table can be build based on test_stringop + - script (once rest of tuning is complete) + - designing a scheduler model in + - XXXX.md file + - Updating ix86_issue_rate and ix86_adjust_cost in i386.md + - possibly updating ia32_multipass_dfa_lookahead, ix86_sched_reorder + and ix86_sched_init_global if those tricks are needed. + - Tunning the flags bellow. Those are split into sections and each + section is very roughly ordered by importance. */ + +/*****************************************************************************/ +/* Scheduling flags. */ +/*****************************************************************************/ -/* X86_TUNE_UNROLL_STRLEN: Produce (quite lame) unrolled sequence for - inline strlen. This affects only -minline-all-stringops mode. By - default we always dispatch to a library since our internal strlen - is bad. */ -DEF_TUNE (X86_TUNE_UNROLL_STRLEN, "unroll_strlen", - m_486 | m_PENT | m_PPRO | m_ATOM | m_SLM | m_CORE_ALL | m_K6 - | m_AMD_MULTIPLE | m_GENERIC) - -/* X86_TUNE_BRANCH_PREDICTION_HINTS: Branch hints were put in P4 based - on simulation result. But after P4 was made, no performance benefit - was observed with branch hints. It also increases the code size. - As a result, icc never generates branch hints. */ -DEF_TUNE (X86_TUNE_BRANCH_PREDICTION_HINTS, "branch_prediction_hints", 0) - -/* X86_TUNE_DOUBLE_WITH_ADD: Use add instead of sal to double value in - an integer register. */ -DEF_TUNE (X86_TUNE_DOUBLE_WITH_ADD, "double_with_add", ~m_386) - -/* X86_TUNE_USE_SAHF: Controls use of SAHF. */ -DEF_TUNE (X86_TUNE_USE_SAHF, "use_sahf", - m_PPRO | m_P4_NOCONA | m_CORE_ALL | m_ATOM | m_SLM | m_K6_GEODE - | m_K8 | m_AMDFAM10 | m_BDVER | m_BTVER | m_GENERIC) +/* X86_TUNE_SCHEDULE: Enable scheduling. */ +DEF_TUNE (X86_TUNE_SCHEDULE, "schedule", + m_PENT | m_PPRO | m_CORE_ALL | m_ATOM | m_SLM | m_K6_GEODE + | m_AMD_MULTIPLE | m_GENERIC) -/* X86_TUNE_MOVX: Enable to zero extend integer registers to avoid - partial dependencies. */ -DEF_TUNE (X86_TUNE_MOVX, "movx", - m_PPRO | m_P4_NOCONA | m_CORE_ALL | m_ATOM | m_SLM | m_GEODE - | m_AMD_MULTIPLE | m_GENERIC) +/* X86_TUNE_PARTIAL_REG_DEPENDENCY: Enable more register renaming + on modern chips. Preffer stores affecting whole integer register + over partial stores. For example preffer MOVZBL or MOVQ to load 8bit + value over movb. */ +DEF_TUNE (X86_TUNE_PARTIAL_REG_DEPENDENCY, "partial_reg_dependency", + m_P4_NOCONA | m_CORE_ALL | m_ATOM | m_SLM | m_AMD_MULTIPLE + | m_GENERIC) -/* X86_TUNE_PARTIAL_REG_STALL: Pentium pro, unlike later chips, handled - use of partial registers by renaming. This improved performance of 16bit - code where upper halves of registers are not used. It also leads to - an penalty whenever a 16bit store is followed by 32bit use. This flag - disables production of such sequences in common cases. - See also X86_TUNE_HIMODE_MATH. +/* X86_TUNE_SSE_PARTIAL_REG_DEPENDENCY: This knob promotes all store + destinations to be 128bit to allow register renaming on 128bit SSE units, + but usually results in one extra microop on 64bit SSE units. + Experimental results shows that disabling this option on P4 brings over 20% + SPECfp regression, while enabling it on K8 brings roughly 2.4% regression + that can be partly masked by careful scheduling of moves. */ +DEF_TUNE (X86_TUNE_SSE_PARTIAL_REG_DEPENDENCY, "sse_partial_reg_dependency", + m_PPRO | m_P4_NOCONA | m_CORE_ALL | m_ATOM | m_SLM | m_AMDFAM10 + | m_BDVER | m_GENERIC) - In current implementation the partial register stalls are not eliminated - very well - they can be introduced via subregs synthesized by combine - and can happen in caller/callee saving sequences. */ -DEF_TUNE (X86_TUNE_PARTIAL_REG_STALL, "partial_reg_stall", m_PPRO) +/* X86_TUNE_SSE_SPLIT_REGS: Set for machines where the type and dependencies + are resolved on SSE register parts instead of whole registers, so we may + maintain just lower part of scalar values in proper format leaving the + upper part undefined. */ +DEF_TUNE (X86_TUNE_SSE_SPLIT_REGS, "sse_split_regs", m_ATHLON_K8) /* X86_TUNE_PARTIAL_FLAG_REG_STALL: this flag disables use of of flags set by instructions affecting just some flags (in particular shifts). @@ -88,74 +81,81 @@ DEF_TUNE (X86_TUNE_PARTIAL_REG_STALL, "partial_reg_stall", m_PPRO) DEF_TUNE (X86_TUNE_PARTIAL_FLAG_REG_STALL, "partial_flag_reg_stall", m_CORE2 | m_GENERIC) -/* X86_TUNE_LCP_STALL: Avoid an expensive length-changing prefix stall - on 16-bit immediate moves into memory on Core2 and Corei7. */ -DEF_TUNE (X86_TUNE_LCP_STALL, "lcp_stall", m_CORE_ALL | m_GENERIC) - -/* X86_TUNE_USE_HIMODE_FIOP: Enables use of x87 instructions with 16bit - integer operand. - FIXME: Why this is disabled for modern chips? */ -DEF_TUNE (X86_TUNE_USE_HIMODE_FIOP, "use_himode_fiop", - m_386 | m_486 | m_K6_GEODE) - -/* X86_TUNE_USE_SIMODE_FIOP: Enables use of x87 instructions with 32bit - integer operand. */ -DEF_TUNE (X86_TUNE_USE_SIMODE_FIOP, "use_simode_fiop", - ~(m_PENT | m_PPRO | m_CORE_ALL | m_ATOM - | m_SLM | m_AMD_MULTIPLE | m_GENERIC)) +/* X86_TUNE_MOVX: Enable to zero extend integer registers to avoid + partial dependencies. */ +DEF_TUNE (X86_TUNE_MOVX, "movx", + m_PPRO | m_P4_NOCONA | m_CORE_ALL | m_ATOM | m_SLM | m_GEODE + | m_AMD_MULTIPLE | m_GENERIC) -/* X86_TUNE_USE_MOV0: Use "mov $0, reg" instead of "xor reg, reg" to clear - integer register. */ -DEF_TUNE (X86_TUNE_USE_MOV0, "use_mov0", m_K6) +/* X86_TUNE_MEMORY_MISMATCH_STALL: Avoid partial stores that are followed by + full sized loads. */ +DEF_TUNE (X86_TUNE_MEMORY_MISMATCH_STALL, "memory_mismatch_stall", + m_P4_NOCONA | m_CORE_ALL | m_ATOM | m_SLM | m_AMD_MULTIPLE | m_GENERIC) -/* X86_TUNE_USE_CLTD: Controls use of CLTD and CTQO instructions. */ -DEF_TUNE (X86_TUNE_USE_CLTD, "use_cltd", ~(m_PENT | m_ATOM | m_SLM | m_K6)) +/* X86_TUNE_FUSE_CMP_AND_BRANCH: Fuse a compare or test instruction + with a subsequent conditional jump instruction into a single + compare-and-branch uop. + FIXME: revisit for generic. */ +DEF_TUNE (X86_TUNE_FUSE_CMP_AND_BRANCH, "fuse_cmp_and_branch", m_BDVER | m_CORE_ALL) -/* X86_TUNE_USE_XCHGB: Use xchgb %rh,%rl instead of rolw/rorw $8,rx. */ -DEF_TUNE (X86_TUNE_USE_XCHGB, "use_xchgb", m_PENT4) +/* X86_TUNE_REASSOC_INT_TO_PARALLEL: Try to produce parallel computations + during reassociation of integer computation. */ +DEF_TUNE (X86_TUNE_REASSOC_INT_TO_PARALLEL, "reassoc_int_to_parallel", + m_ATOM) -/* X86_TUNE_SPLIT_LONG_MOVES: Avoid instructions moving immediates - directly to memory. */ -DEF_TUNE (X86_TUNE_SPLIT_LONG_MOVES, "split_long_moves", m_PPRO) +/* X86_TUNE_REASSOC_FP_TO_PARALLEL: Try to produce parallel computations + during reassociation of fp computation. */ +DEF_TUNE (X86_TUNE_REASSOC_FP_TO_PARALLEL, "reassoc_fp_to_parallel", + m_ATOM | m_SLM | m_HASWELL | m_BDVER1 | m_BDVER2 | m_GENERIC) -/* X86_TUNE_READ_MODIFY_WRITE: Enable use of read modify write instructions - such as "add $1, mem". */ -DEF_TUNE (X86_TUNE_READ_MODIFY_WRITE, "read_modify_write", ~m_PENT) +/*****************************************************************************/ +/* Function prologue, epilogue and function calling sequences. */ +/*****************************************************************************/ -/* X86_TUNE_READ_MODIFY: Enable use of read-modify instructions such - as "add mem, reg". */ -DEF_TUNE (X86_TUNE_READ_MODIFY, "read_modify", ~(m_PENT | m_PPRO)) +/* X86_TUNE_ACCUMULATE_OUTGOING_ARGS: Allocate stack space for outgoing + arguments in prologue/epilogue instead of separately for each call + by push/pop instructions. + This increase code size by about 5% in 32bit mode, less so in 64bit mode + because parameters are passed in registers. It is considerable + win for targets without stack engine that prevents multple push operations + to happen in parallel. -/* X86_TUNE_PROMOTE_QIMODE: When it is cheap, turn 8bit arithmetic to - corresponding 32bit arithmetic. */ -DEF_TUNE (X86_TUNE_PROMOTE_QIMODE, "promote_qimode", - m_386 | m_486 | m_PENT | m_CORE_ALL | m_ATOM | m_SLM - | m_K6_GEODE | m_AMD_MULTIPLE | m_GENERIC) + FIXME: the flags is incorrectly enabled for amdfam10, Bulldozer, + Bobcat and Generic. This is because disabling it causes large + regression on mgrid due to IRA limitation leading to unecessary + use of the frame pointer in 32bit mode. */ +DEF_TUNE (X86_TUNE_ACCUMULATE_OUTGOING_ARGS, "accumulate_outgoing_args", + m_PPRO | m_P4_NOCONA | m_ATOM | m_SLM | m_AMD_MULTIPLE | m_GENERIC) -/* X86_TUNE_FAST_PREFIX: Enable demoting some 32bit or 64bit arithmetic - into 16bit/8bit when resulting sequence is shorter. For example - for "and $-65536, reg" to 16bit store of 0. */ -DEF_TUNE (X86_TUNE_FAST_PREFIX, "fast_prefix", ~(m_386 | m_486 | m_PENT)) +/* X86_TUNE_PROLOGUE_USING_MOVE: Do not use push/pop in prologues that are + considered on critical path. */ +DEF_TUNE (X86_TUNE_PROLOGUE_USING_MOVE, "prologue_using_move", + m_PPRO | m_ATHLON_K8) -/* X86_TUNE_SINGLE_STRINGOP: Enable use of single string operations, such - as MOVS and STOS (without a REP prefix) to move/set sequences of bytes. */ -DEF_TUNE (X86_TUNE_SINGLE_STRINGOP, "single_stringop", m_386 | m_P4_NOCONA) +/* X86_TUNE_PROLOGUE_USING_MOVE: Do not use push/pop in epilogues that are + considered on critical path. */ +DEF_TUNE (X86_TUNE_EPILOGUE_USING_MOVE, "epilogue_using_move", + m_PPRO | m_ATHLON_K8) -/* X86_TUNE_QIMODE_MATH: Enable use of 8bit arithmetic. */ -DEF_TUNE (X86_TUNE_QIMODE_MATH, "qimode_math", ~0) +/* X86_TUNE_USE_LEAVE: Use "leave" instruction in epilogues where it fits. */ +DEF_TUNE (X86_TUNE_USE_LEAVE, "use_leave", + m_386 | m_CORE_ALL | m_K6_GEODE | m_AMD_MULTIPLE | m_GENERIC) -/* X86_TUNE_HIMODE_MATH: Enable use of 16bit arithmetic. - On PPro this flag is meant to avoid partial register stalls. */ -DEF_TUNE (X86_TUNE_HIMODE_MATH, "himode_math", ~m_PPRO) +/* X86_TUNE_PUSH_MEMORY: Enable generation of "push mem" instructions. + Some chips, like 486 and Pentium works faster with separate load + and push instructions. */ +DEF_TUNE (X86_TUNE_PUSH_MEMORY, "push_memory", + m_386 | m_P4_NOCONA | m_CORE_ALL | m_K6_GEODE | m_AMD_MULTIPLE + | m_GENERIC) -/* X86_TUNE_PROMOTE_QI_REGS: This enables generic code that promotes all 8bit - arithmetic to 32bit via PROMOTE_MODE macro. This code generation scheme - is usually used for RISC targets. */ -DEF_TUNE (X86_TUNE_PROMOTE_QI_REGS, "promote_qi_regs", 0) +/* X86_TUNE_SINGLE_PUSH: Enable if single push insn is preferred + over esp subtraction. */ +DEF_TUNE (X86_TUNE_SINGLE_PUSH, "single_push", m_386 | m_486 | m_PENT + | m_K6_GEODE) -/* X86_TUNE_PROMOTE_HI_REGS: Same, but for 16bit artihmetic. Again we avoid - partial register stalls on PentiumPro targets. */ -DEF_TUNE (X86_TUNE_PROMOTE_HI_REGS, "promote_hi_regs", m_PPRO) +/* X86_TUNE_DOUBLE_PUSH. Enable if double push insn is preferred + over esp subtraction. */ +DEF_TUNE (X86_TUNE_DOUBLE_PUSH, "double_push", m_PENT | m_K6_GEODE) /* X86_TUNE_SINGLE_POP: Enable if single pop insn is preferred over esp addition. */ @@ -165,14 +165,48 @@ DEF_TUNE (X86_TUNE_SINGLE_POP, "single_pop", m_386 | m_486 | m_PENT | m_PPRO) over esp addition. */ DEF_TUNE (X86_TUNE_DOUBLE_POP, "double_pop", m_PENT) -/* X86_TUNE_SINGLE_PUSH: Enable if single push insn is preferred - over esp subtraction. */ -DEF_TUNE (X86_TUNE_SINGLE_PUSH, "single_push", m_386 | m_486 | m_PENT - | m_K6_GEODE) +/*****************************************************************************/ +/* Branch predictor tuning */ +/*****************************************************************************/ -/* X86_TUNE_DOUBLE_PUSH. Enable if double push insn is preferred - over esp subtraction. */ -DEF_TUNE (X86_TUNE_DOUBLE_PUSH, "double_push", m_PENT | m_K6_GEODE) +/* X86_TUNE_PAD_SHORT_FUNCTION: Make every function to be at least 4 + instructions long. */ +DEF_TUNE (X86_TUNE_PAD_SHORT_FUNCTION, "pad_short_function", m_ATOM) + +/* X86_TUNE_PAD_RETURNS: Place NOP before every RET that is a destination + of conditional jump or directly preceded by other jump instruction. + This is important for AND K8-AMDFAM10 because the branch prediction + architecture expect at most one jump per 2 byte window. Failing to + pad returns leads to misaligned return stack. */ +DEF_TUNE (X86_TUNE_PAD_RETURNS, "pad_returns", + m_ATHLON_K8 | m_AMDFAM10 | m_GENERIC) + +/* X86_TUNE_FOUR_JUMP_LIMIT: Some CPU cores are not able to predict more + than 4 branch instructions in the 16 byte window. */ +DEF_TUNE (X86_TUNE_FOUR_JUMP_LIMIT, "four_jump_limit", + m_PPRO | m_P4_NOCONA | m_ATOM | m_SLM | m_ATHLON_K8 | m_AMDFAM10) + +/*****************************************************************************/ +/* Integer instruction selection tuning */ +/*****************************************************************************/ + +/* X86_TUNE_SOFTWARE_PREFETCHING_BENEFICIAL: Enable software prefetching + at -O3. For the moment, the prefetching seems badly tuned for Intel + chips. */ +DEF_TUNE (X86_TUNE_SOFTWARE_PREFETCHING_BENEFICIAL, "software_prefetching_beneficial", + m_K6_GEODE | m_AMD_MULTIPLE) + +/* X86_TUNE_LCP_STALL: Avoid an expensive length-changing prefix stall + on 16-bit immediate moves into memory on Core2 and Corei7. */ +DEF_TUNE (X86_TUNE_LCP_STALL, "lcp_stall", m_CORE_ALL | m_GENERIC) + +/* X86_TUNE_READ_MODIFY: Enable use of read-modify instructions such + as "add mem, reg". */ +DEF_TUNE (X86_TUNE_READ_MODIFY, "read_modify", ~(m_PENT | m_PPRO)) + +/* X86_TUNE_USE_INCDEC: Enable use of inc/dec instructions. */ +DEF_TUNE (X86_TUNE_USE_INCDEC, "use_incdec", + ~(m_P4_NOCONA | m_CORE_ALL | m_ATOM | m_SLM | m_GENERIC)) /* X86_TUNE_INTEGER_DFMODE_MOVES: Enable if integer moves are preferred for DFmode copies */ @@ -180,23 +214,88 @@ DEF_TUNE (X86_TUNE_INTEGER_DFMODE_MOVES, "integer_dfmode_moves", ~(m_PPRO | m_P4_NOCONA | m_CORE_ALL | m_ATOM | m_SLM | m_GEODE | m_AMD_MULTIPLE | m_GENERIC)) -/* X86_TUNE_PARTIAL_REG_DEPENDENCY: Enable more register renaming - on modern chips. Preffer stores affecting whole integer register - over partial stores. For example preffer MOVZBL or MOVQ to load 8bit - value over movb. */ -DEF_TUNE (X86_TUNE_PARTIAL_REG_DEPENDENCY, "partial_reg_dependency", - m_P4_NOCONA | m_CORE_ALL | m_ATOM | m_SLM | m_AMD_MULTIPLE - | m_GENERIC) +/* X86_TUNE_OPT_AGU: Optimize for Address Generation Unit. This flag + will impact LEA instruction selection. */ +DEF_TUNE (X86_TUNE_OPT_AGU, "opt_agu", m_ATOM | m_SLM) -/* X86_TUNE_SSE_PARTIAL_REG_DEPENDENCY: This knob promotes all store - destinations to be 128bit to allow register renaming on 128bit SSE units, - but usually results in one extra microop on 64bit SSE units. - Experimental results shows that disabling this option on P4 brings over 20% - SPECfp regression, while enabling it on K8 brings roughly 2.4% regression - that can be partly masked by careful scheduling of moves. */ -DEF_TUNE (X86_TUNE_SSE_PARTIAL_REG_DEPENDENCY, "sse_partial_reg_dependency", - m_PPRO | m_P4_NOCONA | m_CORE_ALL | m_ATOM | m_SLM | m_AMDFAM10 - | m_BDVER | m_GENERIC) +/* X86_TUNE_SLOW_IMUL_IMM32_MEM: Imul of 32-bit constant and memory is + vector path on AMD machines. + FIXME: Do we need to enable this for core? */ +DEF_TUNE (X86_TUNE_SLOW_IMUL_IMM32_MEM, "slow_imul_imm32_mem", + m_K8 | m_AMDFAM10) + +/* X86_TUNE_SLOW_IMUL_IMM8: Imul of 8-bit constant is vector path on AMD + machines. + FIXME: Do we need to enable this for core? */ +DEF_TUNE (X86_TUNE_SLOW_IMUL_IMM8, "slow_imul_imm8", + m_K8 | m_AMDFAM10) + +/* X86_TUNE_AVOID_MEM_OPND_FOR_CMOVE: Try to avoid memory operands for + a conditional move. */ +DEF_TUNE (X86_TUNE_AVOID_MEM_OPND_FOR_CMOVE, "avoid_mem_opnd_for_cmove", + m_ATOM | m_SLM) + +/* X86_TUNE_SINGLE_STRINGOP: Enable use of single string operations, such + as MOVS and STOS (without a REP prefix) to move/set sequences of bytes. */ +DEF_TUNE (X86_TUNE_SINGLE_STRINGOP, "single_stringop", m_386 | m_P4_NOCONA) + +/* TARGET_MISALIGNED_MOVE_STRING_PROLOGUES: Enable generation of compace + prologues and epilogues by issuing a misaligned moves. This require + target to handle misaligned moves and partial memory stalls resonably + well. + FIXME: This actualy may be a win on more targets than listed here. */ +DEF_TUNE (TARGET_MISALIGNED_MOVE_STRING_PROLOGUES, + "misaligned_move_string_prologues", + m_386 | m_486 | m_CORE_ALL | m_AMD_MULTIPLE | m_GENERIC) + +/* X86_TUNE_USE_SAHF: Controls use of SAHF. */ +DEF_TUNE (X86_TUNE_USE_SAHF, "use_sahf", + m_PPRO | m_P4_NOCONA | m_CORE_ALL | m_ATOM | m_SLM | m_K6_GEODE + | m_K8 | m_AMDFAM10 | m_BDVER | m_BTVER | m_GENERIC) + +/* X86_TUNE_USE_CLTD: Controls use of CLTD and CTQO instructions. */ +DEF_TUNE (X86_TUNE_USE_CLTD, "use_cltd", ~(m_PENT | m_ATOM | m_SLM | m_K6)) + +/* X86_TUNE_USE_BT: Enable use of BT (bit test) instructions. */ +DEF_TUNE (X86_TUNE_USE_BT, "use_bt", + m_CORE_ALL | m_ATOM | m_SLM | m_AMD_MULTIPLE | m_GENERIC) + +/*****************************************************************************/ +/* 387 instruction selection tuning */ +/*****************************************************************************/ + +/* X86_TUNE_USE_HIMODE_FIOP: Enables use of x87 instructions with 16bit + integer operand. + FIXME: Why this is disabled for modern chips? */ +DEF_TUNE (X86_TUNE_USE_HIMODE_FIOP, "use_himode_fiop", + m_386 | m_486 | m_K6_GEODE) + +/* X86_TUNE_USE_SIMODE_FIOP: Enables use of x87 instructions with 32bit + integer operand. */ +DEF_TUNE (X86_TUNE_USE_SIMODE_FIOP, "use_simode_fiop", + ~(m_PENT | m_PPRO | m_CORE_ALL | m_ATOM + | m_SLM | m_AMD_MULTIPLE | m_GENERIC)) + +/* X86_TUNE_USE_FFREEP: Use freep instruction instead of fstp. */ +DEF_TUNE (X86_TUNE_USE_FFREEP, "use_ffreep", m_AMD_MULTIPLE) + +/* X86_TUNE_EXT_80387_CONSTANTS: Use fancy 80387 constants, such as PI. */ +DEF_TUNE (X86_TUNE_EXT_80387_CONSTANTS, "ext_80387_constants", + m_PPRO | m_P4_NOCONA | m_CORE_ALL | m_ATOM | m_SLM | m_K6_GEODE + | m_ATHLON_K8 | m_GENERIC) + +/*****************************************************************************/ +/* SSE instruction selection tuning */ +/*****************************************************************************/ + +/* X86_TUNE_VECTORIZE_DOUBLE: Enable double precision vector + instructions. */ +DEF_TUNE (X86_TUNE_VECTORIZE_DOUBLE, "vectorize_double", ~m_ATOM) + +/* X86_TUNE_GENERAL_REGS_SSE_SPILL: Try to spill general regs to SSE + regs instead of memory. */ +DEF_TUNE (X86_TUNE_GENERAL_REGS_SSE_SPILL, "general_regs_sse_spill", + m_CORE_ALL) /* X86_TUNE_SSE_UNALIGNED_LOAD_OPTIMAL: Use movups for misaligned loads instead of a sequence loading registers by parts. */ @@ -208,27 +307,11 @@ DEF_TUNE (X86_TUNE_SSE_UNALIGNED_LOAD_OPTIMAL, "sse_unaligned_load_optimal", DEF_TUNE (X86_TUNE_SSE_UNALIGNED_STORE_OPTIMAL, "sse_unaligned_store_optimal", m_COREI7 | m_BDVER | m_SLM | m_GENERIC) -/* X86_TUNE_AVX256_UNALIGNED_LOAD_OPTIMAL: if true, unaligned loads are - split. */ -DEF_TUNE (X86_TUNE_AVX256_UNALIGNED_LOAD_OPTIMAL, "256_unaligned_load_optimal", - ~(m_COREI7 | m_GENERIC)) - -/* X86_TUNE_AVX256_UNALIGNED_STORE_OPTIMAL: if true, unaligned loads are - split. */ -DEF_TUNE (X86_TUNE_AVX256_UNALIGNED_STORE_OPTIMAL, "256_unaligned_load_optimal", - ~(m_COREI7 | m_BDVER | m_GENERIC)) - /* Use packed single precision instructions where posisble. I.e. movups instead of movupd. */ DEF_TUNE (X86_TUNE_SSE_PACKED_SINGLE_INSN_OPTIMAL, "sse_packed_single_insn_optimal", m_BDVER) -/* X86_TUNE_SSE_SPLIT_REGS: Set for machines where the type and dependencies - are resolved on SSE register parts instead of whole registers, so we may - maintain just lower part of scalar values in proper format leaving the - upper part undefined. */ -DEF_TUNE (X86_TUNE_SSE_SPLIT_REGS, "sse_split_regs", m_ATHLON_K8) - /* X86_TUNE_SSE_TYPELESS_STORES: Always movaps/movups for 128bit stores. */ DEF_TUNE (X86_TUNE_SSE_TYPELESS_STORES, "sse_typeless_stores", m_AMD_MULTIPLE | m_CORE_ALL | m_GENERIC) @@ -238,28 +321,6 @@ DEF_TUNE (X86_TUNE_SSE_TYPELESS_STORES, "sse_typeless_stores", DEF_TUNE (X86_TUNE_SSE_LOAD0_BY_PXOR, "sse_load0_by_pxor", m_PPRO | m_P4_NOCONA | m_CORE_ALL | m_BDVER | m_BTVER | m_GENERIC) -/* X86_TUNE_MEMORY_MISMATCH_STALL: Avoid partial stores that are followed by - full sized loads. */ -DEF_TUNE (X86_TUNE_MEMORY_MISMATCH_STALL, "memory_mismatch_stall", - m_P4_NOCONA | m_CORE_ALL | m_ATOM | m_SLM | m_AMD_MULTIPLE | m_GENERIC) - -/* X86_TUNE_PROLOGUE_USING_MOVE: Do not use push/pop in prologues that are - considered on critical path. */ -DEF_TUNE (X86_TUNE_PROLOGUE_USING_MOVE, "prologue_using_move", - m_PPRO | m_ATHLON_K8) - -/* X86_TUNE_PROLOGUE_USING_MOVE: Do not use push/pop in epilogues that are - considered on critical path. */ -DEF_TUNE (X86_TUNE_EPILOGUE_USING_MOVE, "epilogue_using_move", - m_PPRO | m_ATHLON_K8) - -/* X86_TUNE_SHIFT1: Enables use of short encoding of "sal reg" instead of - longer "sal $1, reg". */ -DEF_TUNE (X86_TUNE_SHIFT1, "shift1", ~m_486) - -/* X86_TUNE_USE_FFREEP: Use freep instruction instead of fstp. */ -DEF_TUNE (X86_TUNE_USE_FFREEP, "use_ffreep", m_AMD_MULTIPLE) - /* X86_TUNE_INTER_UNIT_MOVES_TO_VEC: Enable moves in from integer to SSE registers. If disabled, the moves will be done by storing the value to memory and reloading. */ @@ -278,62 +339,80 @@ DEF_TUNE (X86_TUNE_INTER_UNIT_MOVES_FROM_VEC, "inter_unit_moves_from_vec", DEF_TUNE (X86_TUNE_INTER_UNIT_CONVERSIONS, "inter_unit_conversions", ~(m_AMDFAM10 | m_BDVER)) -/* X86_TUNE_FOUR_JUMP_LIMIT: Some CPU cores are not able to predict more - than 4 branch instructions in the 16 byte window. */ -DEF_TUNE (X86_TUNE_FOUR_JUMP_LIMIT, "four_jump_limit", - m_PPRO | m_P4_NOCONA | m_ATOM | m_SLM | m_ATHLON_K8 | m_AMDFAM10) +/* X86_TUNE_SPLIT_MEM_OPND_FOR_FP_CONVERTS: Try to split memory operand for + fp converts to destination register. */ +DEF_TUNE (X86_TUNE_SPLIT_MEM_OPND_FOR_FP_CONVERTS, "split_mem_opnd_for_fp_converts", + m_SLM) -/* X86_TUNE_SCHEDULE: Enable scheduling. */ -DEF_TUNE (X86_TUNE_SCHEDULE, "schedule", - m_PENT | m_PPRO | m_CORE_ALL | m_ATOM | m_SLM | m_K6_GEODE - | m_AMD_MULTIPLE | m_GENERIC) +/* X86_TUNE_USE_VECTOR_FP_CONVERTS: Prefer vector packed SSE conversion + from FP to FP. This form of instructions avoids partial write to the + destination. */ +DEF_TUNE (X86_TUNE_USE_VECTOR_FP_CONVERTS, "use_vector_fp_converts", + m_AMDFAM10) -/* X86_TUNE_USE_BT: Enable use of BT (bit test) instructions. */ -DEF_TUNE (X86_TUNE_USE_BT, "use_bt", - m_CORE_ALL | m_ATOM | m_SLM | m_AMD_MULTIPLE | m_GENERIC) +/* X86_TUNE_USE_VECTOR_CONVERTS: Prefer vector packed SSE conversion + from integer to FP. */ +DEF_TUNE (X86_TUNE_USE_VECTOR_CONVERTS, "use_vector_converts", m_AMDFAM10) -/* X86_TUNE_USE_INCDEC: Enable use of inc/dec instructions. */ -DEF_TUNE (X86_TUNE_USE_INCDEC, "use_incdec", - ~(m_P4_NOCONA | m_CORE_ALL | m_ATOM | m_SLM | m_GENERIC)) +/*****************************************************************************/ +/* AVX instruction selection tuning (some of SSE flags affects AVX, too) */ +/*****************************************************************************/ -/* X86_TUNE_PAD_RETURNS: Place NOP before every RET that is a destination - of conditional jump or directly preceded by other jump instruction. - This is important for AND K8-AMDFAM10 because the branch prediction - architecture expect at most one jump per 2 byte window. Failing to - pad returns leads to misaligned return stack. */ -DEF_TUNE (X86_TUNE_PAD_RETURNS, "pad_returns", - m_ATHLON_K8 | m_AMDFAM10 | m_GENERIC) +/* X86_TUNE_AVX256_UNALIGNED_LOAD_OPTIMAL: if true, unaligned loads are + split. */ +DEF_TUNE (X86_TUNE_AVX256_UNALIGNED_LOAD_OPTIMAL, "256_unaligned_load_optimal", + ~(m_COREI7 | m_GENERIC)) -/* X86_TUNE_PAD_SHORT_FUNCTION: Make every function to be at least 4 - instructions long. */ -DEF_TUNE (X86_TUNE_PAD_SHORT_FUNCTION, "pad_short_function", m_ATOM) +/* X86_TUNE_AVX256_UNALIGNED_STORE_OPTIMAL: if true, unaligned loads are + split. */ +DEF_TUNE (X86_TUNE_AVX256_UNALIGNED_STORE_OPTIMAL, "256_unaligned_load_optimal", + ~(m_COREI7 | m_BDVER | m_GENERIC)) -/* X86_TUNE_EXT_80387_CONSTANTS: Use fancy 80387 constants, such as PI. */ -DEF_TUNE (X86_TUNE_EXT_80387_CONSTANTS, "ext_80387_constants", - m_PPRO | m_P4_NOCONA | m_CORE_ALL | m_ATOM | m_SLM | m_K6_GEODE - | m_ATHLON_K8 | m_GENERIC) +/* X86_TUNE_AVX128_OPTIMAL: Enable 128-bit AVX instruction generation for + the auto-vectorizer. */ +DEF_TUNE (X86_TUNE_AVX128_OPTIMAL, "avx128_optimal", m_BDVER | m_BTVER2) -/* X86_TUNE_AVOID_VECTOR_DECODE: Enable splitters that avoid vector decoded - forms of instructions on K8 targets. */ -DEF_TUNE (X86_TUNE_AVOID_VECTOR_DECODE, "avoid_vector_decode", - m_K8) +/*****************************************************************************/ +/* Historical relics: tuning flags that helps a specific old CPU designs */ +/*****************************************************************************/ + +/* X86_TUNE_DOUBLE_WITH_ADD: Use add instead of sal to double value in + an integer register. */ +DEF_TUNE (X86_TUNE_DOUBLE_WITH_ADD, "double_with_add", ~m_386) + +/* X86_TUNE_ALWAYS_FANCY_MATH_387: controls use of fancy 387 operations, + such as fsqrt, fprem, fsin, fcos, fsincos etc. + Should be enabled for all targets that always has coprocesor. */ +DEF_TUNE (X86_TUNE_ALWAYS_FANCY_MATH_387, "always_fancy_math_387", + ~(m_386 | m_486)) + +/* X86_TUNE_UNROLL_STRLEN: Produce (quite lame) unrolled sequence for + inline strlen. This affects only -minline-all-stringops mode. By + default we always dispatch to a library since our internal strlen + is bad. */ +DEF_TUNE (X86_TUNE_UNROLL_STRLEN, "unroll_strlen", ~m_386) + +/* X86_TUNE_SHIFT1: Enables use of short encoding of "sal reg" instead of + longer "sal $1, reg". */ +DEF_TUNE (X86_TUNE_SHIFT1, "shift1", ~m_486) + +/* X86_TUNE_ZERO_EXTEND_WITH_AND: Use AND instruction instead + of mozbl/movwl. */ +DEF_TUNE (X86_TUNE_ZERO_EXTEND_WITH_AND, "zero_extend_with_and", m_486 | m_PENT) /* X86_TUNE_PROMOTE_HIMODE_IMUL: Modern CPUs have same latency for HImode and SImode multiply, but 386 and 486 do HImode multiply faster. */ DEF_TUNE (X86_TUNE_PROMOTE_HIMODE_IMUL, "promote_himode_imul", ~(m_386 | m_486)) -/* X86_TUNE_SLOW_IMUL_IMM32_MEM: Imul of 32-bit constant and memory is - vector path on AMD machines. - FIXME: Do we need to enable this for core? */ -DEF_TUNE (X86_TUNE_SLOW_IMUL_IMM32_MEM, "slow_imul_imm32_mem", - m_K8 | m_AMDFAM10) +/* X86_TUNE_FAST_PREFIX: Enable demoting some 32bit or 64bit arithmetic + into 16bit/8bit when resulting sequence is shorter. For example + for "and $-65536, reg" to 16bit store of 0. */ +DEF_TUNE (X86_TUNE_FAST_PREFIX, "fast_prefix", ~(m_386 | m_486 | m_PENT)) -/* X86_TUNE_SLOW_IMUL_IMM8: Imul of 8-bit constant is vector path on AMD - machines. - FIXME: Do we need to enable this for core? */ -DEF_TUNE (X86_TUNE_SLOW_IMUL_IMM8, "slow_imul_imm8", - m_K8 | m_AMDFAM10) +/* X86_TUNE_READ_MODIFY_WRITE: Enable use of read modify write instructions + such as "add $1, mem". */ +DEF_TUNE (X86_TUNE_READ_MODIFY_WRITE, "read_modify_write", ~m_PENT) /* X86_TUNE_MOVE_M1_VIA_OR: On pentiums, it is faster to load -1 via OR than a MOV. */ @@ -343,87 +422,66 @@ DEF_TUNE (X86_TUNE_MOVE_M1_VIA_OR, "move_m1_via_or", m_PENT) but one byte longer. */ DEF_TUNE (X86_TUNE_NOT_UNPAIRABLE, "not_unpairable", m_PENT) -/* X86_TUNE_NOT_VECTORMODE: On AMD K6, NOT is vector decoded with memory - operand that cannot be represented using a modRM byte. The XOR - replacement is long decoded, so this split helps here as well. */ -DEF_TUNE (X86_TUNE_NOT_VECTORMODE, "not_vectormode", m_K6) - -/* X86_TUNE_USE_VECTOR_FP_CONVERTS: Prefer vector packed SSE conversion - from FP to FP. This form of instructions avoids partial write to the - destination. */ -DEF_TUNE (X86_TUNE_USE_VECTOR_FP_CONVERTS, "use_vector_fp_converts", - m_AMDFAM10) - -/* X86_TUNE_USE_VECTOR_CONVERTS: Prefer vector packed SSE conversion - from integer to FP. */ -DEF_TUNE (X86_TUNE_USE_VECTOR_CONVERTS, "use_vector_converts", m_AMDFAM10) +/* X86_TUNE_PARTIAL_REG_STALL: Pentium pro, unlike later chips, handled + use of partial registers by renaming. This improved performance of 16bit + code where upper halves of registers are not used. It also leads to + an penalty whenever a 16bit store is followed by 32bit use. This flag + disables production of such sequences in common cases. + See also X86_TUNE_HIMODE_MATH. -/* X86_TUNE_FUSE_CMP_AND_BRANCH: Fuse a compare or test instruction - with a subsequent conditional jump instruction into a single - compare-and-branch uop. - FIXME: revisit for generic. */ -DEF_TUNE (X86_TUNE_FUSE_CMP_AND_BRANCH, "fuse_cmp_and_branch", m_BDVER | m_CORE_ALL) + In current implementation the partial register stalls are not eliminated + very well - they can be introduced via subregs synthesized by combine + and can happen in caller/callee saving sequences. */ +DEF_TUNE (X86_TUNE_PARTIAL_REG_STALL, "partial_reg_stall", m_PPRO) -/* X86_TUNE_OPT_AGU: Optimize for Address Generation Unit. This flag - will impact LEA instruction selection. */ -DEF_TUNE (X86_TUNE_OPT_AGU, "opt_agu", m_ATOM | m_SLM) +/* X86_TUNE_PROMOTE_QIMODE: When it is cheap, turn 8bit arithmetic to + corresponding 32bit arithmetic. */ +DEF_TUNE (X86_TUNE_PROMOTE_QIMODE, "promote_qimode", + ~m_PPRO) -/* X86_TUNE_VECTORIZE_DOUBLE: Enable double precision vector - instructions. */ -DEF_TUNE (X86_TUNE_VECTORIZE_DOUBLE, "vectorize_double", ~m_ATOM) +/* X86_TUNE_PROMOTE_HI_REGS: Same, but for 16bit artihmetic. Again we avoid + partial register stalls on PentiumPro targets. */ +DEF_TUNE (X86_TUNE_PROMOTE_HI_REGS, "promote_hi_regs", m_PPRO) -/* X86_TUNE_SOFTWARE_PREFETCHING_BENEFICIAL: Enable software prefetching - at -O3. For the moment, the prefetching seems badly tuned for Intel - chips. */ -DEF_TUNE (X86_TUNE_SOFTWARE_PREFETCHING_BENEFICIAL, "software_prefetching_beneficial", - m_K6_GEODE | m_AMD_MULTIPLE) +/* X86_TUNE_HIMODE_MATH: Enable use of 16bit arithmetic. + On PPro this flag is meant to avoid partial register stalls. */ +DEF_TUNE (X86_TUNE_HIMODE_MATH, "himode_math", ~m_PPRO) -/* X86_TUNE_AVX128_OPTIMAL: Enable 128-bit AVX instruction generation for - the auto-vectorizer. */ -DEF_TUNE (X86_TUNE_AVX128_OPTIMAL, "avx128_optimal", m_BDVER | m_BTVER2) +/* X86_TUNE_SPLIT_LONG_MOVES: Avoid instructions moving immediates + directly to memory. */ +DEF_TUNE (X86_TUNE_SPLIT_LONG_MOVES, "split_long_moves", m_PPRO) -/* X86_TUNE_REASSOC_INT_TO_PARALLEL: Try to produce parallel computations - during reassociation of integer computation. */ -DEF_TUNE (X86_TUNE_REASSOC_INT_TO_PARALLEL, "reassoc_int_to_parallel", - m_ATOM) +/* X86_TUNE_USE_XCHGB: Use xchgb %rh,%rl instead of rolw/rorw $8,rx. */ +DEF_TUNE (X86_TUNE_USE_XCHGB, "use_xchgb", m_PENT4) -/* X86_TUNE_REASSOC_FP_TO_PARALLEL: Try to produce parallel computations - during reassociation of fp computation. */ -DEF_TUNE (X86_TUNE_REASSOC_FP_TO_PARALLEL, "reassoc_fp_to_parallel", - m_ATOM | m_SLM | m_HASWELL | m_BDVER1 | m_BDVER2 | m_GENERIC) +/* X86_TUNE_USE_MOV0: Use "mov $0, reg" instead of "xor reg, reg" to clear + integer register. */ +DEF_TUNE (X86_TUNE_USE_MOV0, "use_mov0", m_K6) -/* X86_TUNE_GENERAL_REGS_SSE_SPILL: Try to spill general regs to SSE - regs instead of memory. */ -DEF_TUNE (X86_TUNE_GENERAL_REGS_SSE_SPILL, "general_regs_sse_spill", - m_CORE_ALL) +/* X86_TUNE_NOT_VECTORMODE: On AMD K6, NOT is vector decoded with memory + operand that cannot be represented using a modRM byte. The XOR + replacement is long decoded, so this split helps here as well. */ +DEF_TUNE (X86_TUNE_NOT_VECTORMODE, "not_vectormode", m_K6) -/* X86_TUNE_AVOID_MEM_OPND_FOR_CMOVE: Try to avoid memory operands for - a conditional move. */ -DEF_TUNE (X86_TUNE_AVOID_MEM_OPND_FOR_CMOVE, "avoid_mem_opnd_for_cmove", - m_ATOM | m_SLM) +/* X86_TUNE_AVOID_VECTOR_DECODE: Enable splitters that avoid vector decoded + forms of instructions on K8 targets. */ +DEF_TUNE (X86_TUNE_AVOID_VECTOR_DECODE, "avoid_vector_decode", + m_K8) -/* X86_TUNE_SPLIT_MEM_OPND_FOR_FP_CONVERTS: Try to split memory operand for - fp converts to destination register. */ -DEF_TUNE (X86_TUNE_SPLIT_MEM_OPND_FOR_FP_CONVERTS, "split_mem_opnd_for_fp_converts", - m_SLM) +/*****************************************************************************/ +/* This never worked well before. */ +/*****************************************************************************/ -/* X86_TUNE_ACCUMULATE_OUTGOING_ARGS: Allocate stack space for outgoing - arguments in prologue/epilogue instead of separately for each call - by push/pop instructions. - This increase code size by about 5% in 32bit mode, less so in 64bit mode - because parameters are passed in registers. It is considerable - win for targets without stack engine that prevents multple push operations - to happen in parallel. +/* X86_TUNE_BRANCH_PREDICTION_HINTS: Branch hints were put in P4 based + on simulation result. But after P4 was made, no performance benefit + was observed with branch hints. It also increases the code size. + As a result, icc never generates branch hints. */ +DEF_TUNE (X86_TUNE_BRANCH_PREDICTION_HINTS, "branch_prediction_hints", 0) - FIXME: the flags is incorrectly enabled for amdfam10, Bulldozer, - Bobcat and Generic. This is because disabling it causes large - regression on mgrid due to IRA limitation leading to unecessary - use of the frame pointer in 32bit mode. */ -DEF_TUNE (X86_TUNE_ACCUMULATE_OUTGOING_ARGS, "accumulate_outgoing_args", - m_PPRO | m_P4_NOCONA | m_ATOM | m_SLM | m_AMD_MULTIPLE | m_GENERIC) +/* X86_TUNE_QIMODE_MATH: Enable use of 8bit arithmetic. */ +DEF_TUNE (X86_TUNE_QIMODE_MATH, "qimode_math", ~0) -/* X86_TUNE_ALWAYS_FANCY_MATH_387: controls use of fancy 387 operations, - such as fsqrt, fprem, fsin, fcos, fsincos etc. - Should be enabled for all targets that always has coprocesor. */ -DEF_TUNE (X86_TUNE_ALWAYS_FANCY_MATH_387, "always_fancy_math_387", - ~(m_386 | m_486)) +/* X86_TUNE_PROMOTE_QI_REGS: This enables generic code that promotes all 8bit + arithmetic to 32bit via PROMOTE_MODE macro. This code generation scheme + is usually used for RISC targets. */ +DEF_TUNE (X86_TUNE_PROMOTE_QI_REGS, "promote_qi_regs", 0) diff --git a/gcc/config/m32c/m32c-modes.def b/gcc/config/m32c/m32c-modes.def index 2050c91a009..ad266fbc851 100644 --- a/gcc/config/m32c/m32c-modes.def +++ b/gcc/config/m32c/m32c-modes.def @@ -22,7 +22,7 @@ /*INT_MODE (PI, 3);*/ /* 24-bit pointers, in 32-bit units */ -PARTIAL_INT_MODE (SI); +PARTIAL_INT_MODE (SI, 24, PSI); /* 48-bit MULEX result */ /* INT_MODE (MI, 6); */ diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c index 5e3236fa8de..7035504bfe3 100644 --- a/gcc/config/m68k/m68k.c +++ b/gcc/config/m68k/m68k.c @@ -4209,6 +4209,13 @@ notice_update_cc (rtx exp, rtx insn) && cc_status.value2 && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2)) cc_status.value2 = 0; + /* Check for PRE_DEC in dest modifying a register used in src. */ + if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM + && GET_CODE (XEXP (cc_status.value1, 0)) == PRE_DEC + && cc_status.value2 + && reg_overlap_mentioned_p (XEXP (XEXP (cc_status.value1, 0), 0), + cc_status.value2)) + cc_status.value2 = 0; if (((cc_status.value1 && FP_REG_P (cc_status.value1)) || (cc_status.value2 && FP_REG_P (cc_status.value2)))) cc_status.flags = CC_IN_68881; diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 5040b40def5..510204203e1 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -3796,6 +3796,18 @@ mips_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED, return true; } } + /* (AND (NOT op0) (NOT op1) is a nor operation that can be done in + a single instruction. */ + if (!TARGET_MIPS16 + && GET_CODE (XEXP (x, 0)) == NOT + && GET_CODE (XEXP (x, 1)) == NOT) + { + cost = GET_MODE_SIZE (mode) > UNITS_PER_WORD ? 2 : 1; + *total = (COSTS_N_INSNS (cost) + + set_src_cost (XEXP (XEXP (x, 0), 0), speed) + + set_src_cost (XEXP (XEXP (x, 1), 0), speed)); + return true; + } /* Fall through. */ diff --git a/gcc/config/moxie/uclinux.h b/gcc/config/moxie/uclinux.h index 85c65f257ce..fb8c92542b5 100644 --- a/gcc/config/moxie/uclinux.h +++ b/gcc/config/moxie/uclinux.h @@ -30,13 +30,5 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #define TARGET_OS_CPP_BUILTINS() GNU_USER_TARGET_OS_CPP_BUILTINS() -/* Like the definition in gcc.c, but for purposes of uClinux, every link is - static. */ -#define MFWRAP_SPEC " %{fmudflap|fmudflapth: \ - --wrap=malloc --wrap=free --wrap=calloc --wrap=realloc\ - --wrap=mmap --wrap=munmap --wrap=alloca\ - %{fmudflapth: --wrap=pthread_create\ -}} %{fmudflap|fmudflapth: --wrap=main}" - #undef TARGET_LIBC_HAS_FUNCTION #define TARGET_LIBC_HAS_FUNCTION no_c99_libc_has_function diff --git a/gcc/config/msp430/msp430-modes.def b/gcc/config/msp430/msp430-modes.def index 9e7b70127fd..4e94a6df597 100644 --- a/gcc/config/msp430/msp430-modes.def +++ b/gcc/config/msp430/msp430-modes.def @@ -1,3 +1,3 @@ /* 20-bit address */ -PARTIAL_INT_MODE (SI); +PARTIAL_INT_MODE (SI, 20, PSI); diff --git a/gcc/config/nds32/constants.md b/gcc/config/nds32/constants.md new file mode 100644 index 00000000000..03a21dba1b2 --- /dev/null +++ b/gcc/config/nds32/constants.md @@ -0,0 +1,46 @@ +;; Constant defintions of Andes NDS32 cpu for GNU compiler +;; Copyright (C) 2012-2013 Free Software Foundation, Inc. +;; Contributed by Andes Technology Corporation. +;; +;; This file is part of GCC. +;; +;; GCC is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published +;; by the Free Software Foundation; either version 3, or (at your +;; option) any later version. +;; +;; GCC is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with GCC; see the file COPYING3. If not see +;; <http://www.gnu.org/licenses/>. + + +;; Register numbers. +(define_constants + [(R8_REGNUM 8) + (TA_REGNUM 15) + (FP_REGNUM 28) + (GP_REGNUM 29) + (LP_REGNUM 30) + (SP_REGNUM 31) + ]) + + +;; The unspec_volatile operation index. +(define_c_enum "unspec_volatile_element" [ + UNSPEC_VOLATILE_FUNC_RETURN + UNSPEC_VOLATILE_ISYNC + UNSPEC_VOLATILE_ISB + UNSPEC_VOLATILE_MFSR + UNSPEC_VOLATILE_MFUSR + UNSPEC_VOLATILE_MTSR + UNSPEC_VOLATILE_MTUSR + UNSPEC_VOLATILE_SETGIE_EN + UNSPEC_VOLATILE_SETGIE_DIS +]) + +;; ------------------------------------------------------------------------ diff --git a/gcc/config/nds32/constraints.md b/gcc/config/nds32/constraints.md new file mode 100644 index 00000000000..b4ae6c7258c --- /dev/null +++ b/gcc/config/nds32/constraints.md @@ -0,0 +1,254 @@ +;; Constraint definitions of Andes NDS32 cpu for GNU compiler +;; Copyright (C) 2012-2013 Free Software Foundation, Inc. +;; Contributed by Andes Technology Corporation. +;; +;; This file is part of GCC. +;; +;; GCC is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published +;; by the Free Software Foundation; either version 3, or (at your +;; option) any later version. +;; +;; GCC is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with GCC; see the file COPYING3. If not see +;; <http://www.gnu.org/licenses/>. + +;; Check 16.8.7 Defining Machine-Specific Constraints for detail. + +;; NO contrains can be prefixed with: E F V X g i m n o p r s +;; Machine-dependent integer: I J K L M N O P +;; Machine-dependent floating: G H + + +(define_register_constraint "w" "(TARGET_ISA_V3 || TARGET_ISA_V3M) ? LOW_REGS : NO_REGS" + "LOW register class $r0 ~ $r7 constraint for V3/V3M ISA") + +(define_register_constraint "l" "LOW_REGS" + "LOW register class $r0 ~ $r7") + +(define_register_constraint "d" "MIDDLE_REGS" + "MIDDLE register class $r0 ~ $r11, $r16 ~ $r19") + +(define_register_constraint "h" "HIGH_REGS" + "HIGH register class $r12 ~ $r14, $r20 ~ $r31") + + +(define_register_constraint "t" "R15_TA_REG" + "Temporary Assist register $ta (i.e. $r15)") + +(define_register_constraint "k" "STACK_REG" + "Stack register $sp") + + +(define_constraint "Iu03" + "Unsigned immediate 3-bit value" + (and (match_code "const_int") + (match_test "ival < (1 << 3) && ival >= 0"))) + +(define_constraint "In03" + "Negative immediate 3-bit value in the range of -7 to 0" + (and (match_code "const_int") + (match_test "IN_RANGE (ival, -7, 0)"))) + +(define_constraint "Iu04" + "Unsigned immediate 4-bit value" + (and (match_code "const_int") + (match_test "ival < (1 << 4) && ival >= 0"))) + +(define_constraint "Is05" + "Signed immediate 5-bit value" + (and (match_code "const_int") + (match_test "ival < (1 << 4) && ival >= -(1 << 4)"))) + +(define_constraint "Iu05" + "Unsigned immediate 5-bit value" + (and (match_code "const_int") + (match_test "ival < (1 << 5) && ival >= 0"))) + +(define_constraint "In05" + "Negative immediate 5-bit value in the range of -31 to 0" + (and (match_code "const_int") + (match_test "IN_RANGE (ival, -31, 0)"))) + +;; Ip05 is special and dedicated for v3 movpi45 instruction. +;; movpi45 has imm5u field but the range is 16 ~ 47. +(define_constraint "Ip05" + "Unsigned immediate 5-bit value for movpi45 instruction with range 16-47" + (and (match_code "const_int") + (match_test "ival < ((1 << 5) + 16) + && ival >= (0 + 16) + && (TARGET_ISA_V3 || TARGET_ISA_V3M)"))) + +(define_constraint "Iu06" + "Unsigned immediate 6-bit value constraint for addri36.sp instruction" + (and (match_code "const_int") + (match_test "ival < (1 << 6) + && ival >= 0 + && (ival % 4 == 0) + && (TARGET_ISA_V3 || TARGET_ISA_V3M)"))) + +(define_constraint "Iu08" + "Unsigned immediate 8-bit value" + (and (match_code "const_int") + (match_test "ival < (1 << 8) && ival >= 0"))) + +(define_constraint "Iu09" + "Unsigned immediate 9-bit value" + (and (match_code "const_int") + (match_test "ival < (1 << 9) && ival >= 0"))) + + +(define_constraint "Is10" + "Signed immediate 10-bit value" + (and (match_code "const_int") + (match_test "ival < (1 << 9) && ival >= -(1 << 9)"))) + +(define_constraint "Is11" + "Signed immediate 11-bit value" + (and (match_code "const_int") + (match_test "ival < (1 << 10) && ival >= -(1 << 10)"))) + + +(define_constraint "Is15" + "Signed immediate 15-bit value" + (and (match_code "const_int") + (match_test "ival < (1 << 14) && ival >= -(1 << 14)"))) + +(define_constraint "Iu15" + "Unsigned immediate 15-bit value" + (and (match_code "const_int") + (match_test "ival < (1 << 15) && ival >= 0"))) + + +;; Ic15 is special and dedicated for performance extension +;; 'bclr' (single-bit-clear) instruction. +;; It is used in andsi3 pattern and recognized for the immediate +;; which is NOT in the range of imm15u but OK for 'bclr' instruction. +;; (If the immediate value IS in the range of imm15u, +;; we can directly use 'andi' instruction.) +(define_constraint "Ic15" + "A constant which is not in the range of imm15u but ok for bclr instruction" + (and (match_code "const_int") + (match_test "(ival & 0xffff8000) && nds32_can_use_bclr_p (ival)"))) + +;; Ie15 is special and dedicated for performance extension +;; 'bset' (single-bit-set) instruction. +;; It is used in iorsi3 pattern and recognized for the immediate +;; which is NOT in the range of imm15u but OK for 'bset' instruction. +;; (If the immediate value IS in the range of imm15u, +;; we can directly use 'ori' instruction.) +(define_constraint "Ie15" + "A constant which is not in the range of imm15u but ok for bset instruction" + (and (match_code "const_int") + (match_test "(ival & 0xffff8000) && nds32_can_use_bset_p (ival)"))) + +;; It15 is special and dedicated for performance extension +;; 'btgl' (single-bit-toggle) instruction. +;; It is used in xorsi3 pattern and recognized for the immediate +;; which is NOT in the range of imm15u but OK for 'btgl' instruction. +;; (If the immediate value IS in the range of imm15u, +;; we can directly use 'xori' instruction.) +(define_constraint "It15" + "A constant which is not in the range of imm15u but ok for btgl instruction" + (and (match_code "const_int") + (match_test "(ival & 0xffff8000) && nds32_can_use_btgl_p (ival)"))) + + +;; Ii15 is special and dedicated for v3 isa +;; 'bitci' (bit-clear-immediate) instruction. +;; It is used in andsi3 pattern and recognized for the immediate whose +;; (~ival) value is in the range of imm15u and OK for 'bitci' instruction. +;; For example, 'andi $r0,$r0,0xfffffffc' can be presented +; with 'bitci $r0,$r0,3'. +(define_constraint "Ii15" + "A constant whose compliment value is in the range of imm15u + and ok for bitci instruction" + (and (match_code "const_int") + (match_test "nds32_can_use_bitci_p (ival)"))) + + +(define_constraint "Is16" + "Signed immediate 16-bit value" + (and (match_code "const_int") + (match_test "ival < (1 << 15) && ival >= -(1 << 15)"))) + +(define_constraint "Is17" + "Signed immediate 17-bit value" + (and (match_code "const_int") + (match_test "ival < (1 << 16) && ival >= -(1 << 16)"))) + + +(define_constraint "Is19" + "Signed immediate 19-bit value" + (and (match_code "const_int") + (match_test "ival < (1 << 18) && ival >= -(1 << 18)"))) + + +(define_constraint "Is20" + "Signed immediate 20-bit value" + (and (match_code "const_int") + (match_test "ival < (1 << 19) && ival >= -(1 << 19)"))) + + +(define_constraint "Ihig" + "The immediate value that can be simply set high 20-bit" + (and (match_code "const_int") + (match_test "(ival != 0) && ((ival & 0xfff) == 0)"))) + +(define_constraint "Izeb" + "The immediate value 0xff" + (and (match_code "const_int") + (match_test "(ival == 0xff)"))) + +(define_constraint "Izeh" + "The immediate value 0xffff" + (and (match_code "const_int") + (match_test "(ival == 0xffff)"))) + +(define_constraint "Ixls" + "The immediate value 0x01" + (and (match_code "const_int") + (match_test "TARGET_PERF_EXT && (ival == 0x1)"))) + +(define_constraint "Ix11" + "The immediate value 0x7ff" + (and (match_code "const_int") + (match_test "TARGET_PERF_EXT && (ival == 0x7ff)"))) + +(define_constraint "Ibms" + "The immediate value with power of 2" + (and (match_code "const_int") + (match_test "(TARGET_ISA_V3 || TARGET_ISA_V3M) + && (IN_RANGE (exact_log2 (ival), 0, 7))"))) + +(define_constraint "Ifex" + "The immediate value with power of 2 minus 1" + (and (match_code "const_int") + (match_test "(TARGET_ISA_V3 || TARGET_ISA_V3M) + && (IN_RANGE (exact_log2 (ival + 1), 1, 8))"))) + + +(define_memory_constraint "U33" + "Memory constraint for 333 format" + (and (match_code "mem") + (match_test "nds32_mem_format (op) == ADDRESS_LO_REG_IMM3U"))) + +(define_memory_constraint "U45" + "Memory constraint for 45 format" + (and (match_code "mem") + (match_test "(nds32_mem_format (op) == ADDRESS_REG) + && (GET_MODE (op) == SImode)"))) + +(define_memory_constraint "U37" + "Memory constraint for 37 format" + (and (match_code "mem") + (match_test "(nds32_mem_format (op) == ADDRESS_SP_IMM7U + || nds32_mem_format (op) == ADDRESS_FP_IMM7U) + && (GET_MODE (op) == SImode)"))) + +;; ------------------------------------------------------------------------ diff --git a/gcc/config/nds32/iterators.md b/gcc/config/nds32/iterators.md new file mode 100644 index 00000000000..6ec519618a9 --- /dev/null +++ b/gcc/config/nds32/iterators.md @@ -0,0 +1,55 @@ +;; Code and mode itertator and attribute definitions +;; of Andes NDS32 cpu for GNU compiler +;; Copyright (C) 2012-2013 Free Software Foundation, Inc. +;; Contributed by Andes Technology Corporation. +;; +;; This file is part of GCC. +;; +;; GCC is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published +;; by the Free Software Foundation; either version 3, or (at your +;; option) any later version. +;; +;; GCC is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with GCC; see the file COPYING3. If not see +;; <http://www.gnu.org/licenses/>. + +;;---------------------------------------------------------------------------- +;; Mode iterators. +;;---------------------------------------------------------------------------- + +;; A list of integer modes that are up to one word long. +(define_mode_iterator QIHISI [QI HI SI]) + +;; A list of integer modes that are up to one half-word long. +(define_mode_iterator QIHI [QI HI]) + +;; A list of the modes that are up to double-word long. +(define_mode_iterator DIDF [DI DF]) + + +;;---------------------------------------------------------------------------- +;; Mode attributes. +;;---------------------------------------------------------------------------- + +(define_mode_attr size [(QI "b") (HI "h") (SI "w")]) + +(define_mode_attr byte [(QI "1") (HI "2") (SI "4")]) + + +;;---------------------------------------------------------------------------- +;; Code iterators. +;;---------------------------------------------------------------------------- + + +;;---------------------------------------------------------------------------- +;; Code attributes. +;;---------------------------------------------------------------------------- + + +;;---------------------------------------------------------------------------- diff --git a/gcc/config/nds32/nds32-doubleword.md b/gcc/config/nds32/nds32-doubleword.md new file mode 100644 index 00000000000..4bfede4236a --- /dev/null +++ b/gcc/config/nds32/nds32-doubleword.md @@ -0,0 +1,251 @@ +;; DImode/DFmode patterns description of Andes NDS32 cpu for GNU compiler +;; Copyright (C) 2012-2013 Free Software Foundation, Inc. +;; Contributed by Andes Technology Corporation. +;; +;; This file is part of GCC. +;; +;; GCC is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published +;; by the Free Software Foundation; either version 3, or (at your +;; option) any later version. +;; +;; GCC is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with GCC; see the file COPYING3. If not see +;; <http://www.gnu.org/licenses/>. + + +;; ------------------------------------------------------------- +;; Move DImode/DFmode instructions. +;; ------------------------------------------------------------- + + +(define_expand "movdi" + [(set (match_operand:DI 0 "general_operand" "") + (match_operand:DI 1 "general_operand" ""))] + "" +{ + /* Need to force register if mem <- !reg. */ + if (MEM_P (operands[0]) && !REG_P (operands[1])) + operands[1] = force_reg (DImode, operands[1]); +}) + +(define_expand "movdf" + [(set (match_operand:DF 0 "general_operand" "") + (match_operand:DF 1 "general_operand" ""))] + "" +{ + /* Need to force register if mem <- !reg. */ + if (MEM_P (operands[0]) && !REG_P (operands[1])) + operands[1] = force_reg (DFmode, operands[1]); +}) + + +(define_insn "move_<mode>" + [(set (match_operand:DIDF 0 "nonimmediate_operand" "=r, r, r, m") + (match_operand:DIDF 1 "general_operand" " r, i, m, r"))] + "" +{ + rtx addr; + rtx otherops[5]; + + switch (which_alternative) + { + case 0: + return "movd44\t%0, %1"; + + case 1: + /* reg <- const_int, we ask gcc to split instruction. */ + return "#"; + + case 2: + /* Refer to nds32_legitimate_address_p() in nds32.c, + we only allow "reg", "symbol_ref", "const", and "reg + const_int" + as address rtx for DImode/DFmode memory access. */ + addr = XEXP (operands[1], 0); + + otherops[0] = gen_rtx_REG (SImode, REGNO (operands[0])); + otherops[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1); + otherops[2] = addr; + + if (REG_P (addr)) + { + /* (reg) <- (mem (reg)) */ + output_asm_insn ("lmw.bi\t%0, [%2], %1, 0", otherops); + } + else if (GET_CODE (addr) == PLUS) + { + /* (reg) <- (mem (plus (reg) (const_int))) */ + rtx op0 = XEXP (addr, 0); + rtx op1 = XEXP (addr, 1); + + if (REG_P (op0)) + { + otherops[2] = op0; + otherops[3] = op1; + otherops[4] = gen_int_mode (INTVAL (op1) + 4, SImode); + } + else + { + otherops[2] = op1; + otherops[3] = op0; + otherops[4] = gen_int_mode (INTVAL (op0) + 4, SImode); + } + + /* To avoid base overwrite when REGNO(%0) == REGNO(%2). */ + if (REGNO (otherops[0]) != REGNO (otherops[2])) + { + output_asm_insn ("lwi\t%0, [%2 + (%3)]", otherops); + output_asm_insn ("lwi\t%1, [%2 + (%4)]", otherops); + } + else + { + output_asm_insn ("lwi\t%1, [%2 + (%4)]", otherops); + output_asm_insn ("lwi\t%0,[ %2 + (%3)]", otherops); + } + } + else + { + /* (reg) <- (mem (symbol_ref ...)) + (reg) <- (mem (const ...)) */ + output_asm_insn ("lwi.gp\t%0, [ + %2]", otherops); + output_asm_insn ("lwi.gp\t%1, [ + %2 + 4]", otherops); + } + + /* We have already used output_asm_insn() by ourself, + so return an empty string. */ + return ""; + + case 3: + /* Refer to nds32_legitimate_address_p() in nds32.c, + we only allow "reg", "symbol_ref", "const", and "reg + const_int" + as address rtx for DImode/DFmode memory access. */ + addr = XEXP (operands[0], 0); + + otherops[0] = gen_rtx_REG (SImode, REGNO (operands[1])); + otherops[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1); + otherops[2] = addr; + + if (REG_P (addr)) + { + /* (mem (reg)) <- (reg) */ + output_asm_insn ("smw.bi\t%0, [%2], %1, 0", otherops); + } + else if (GET_CODE (addr) == PLUS) + { + /* (mem (plus (reg) (const_int))) <- (reg) */ + rtx op0 = XEXP (addr, 0); + rtx op1 = XEXP (addr, 1); + + if (REG_P (op0)) + { + otherops[2] = op0; + otherops[3] = op1; + otherops[4] = gen_int_mode (INTVAL (op1) + 4, SImode); + } + else + { + otherops[2] = op1; + otherops[3] = op0; + otherops[4] = gen_int_mode (INTVAL (op0) + 4, SImode); + } + + /* To avoid base overwrite when REGNO(%0) == REGNO(%2). */ + if (REGNO (otherops[0]) != REGNO (otherops[2])) + { + output_asm_insn ("swi\t%0, [%2 + (%3)]", otherops); + output_asm_insn ("swi\t%1, [%2 + (%4)]", otherops); + } + else + { + output_asm_insn ("swi\t%1, [%2 + (%4)]", otherops); + output_asm_insn ("swi\t%0, [%2 + (%3)]", otherops); + } + } + else + { + /* (mem (symbol_ref ...)) <- (reg) + (mem (const ...)) <- (reg) */ + output_asm_insn ("swi.gp\t%0, [ + %2]", otherops); + output_asm_insn ("swi.gp\t%1, [ + %2 + 4]", otherops); + } + + /* We have already used output_asm_insn() by ourself, + so return an empty string. */ + return ""; + + default: + gcc_unreachable (); + } +} + [(set_attr "type" "move,move,move,move") + (set_attr "length" " 4, 16, 8, 8")]) + +(define_split + [(set (match_operand:DIDF 0 "register_operand" "") + (match_operand:DIDF 1 "const_double_operand" ""))] + "reload_completed" + [(set (match_dup 2) (match_dup 3)) + (set (match_dup 4) (match_dup 5))] +{ + /* Construct lowpart rtx. */ + operands[2] = gen_lowpart (SImode, operands[0]); + operands[3] = gen_lowpart (SImode, operands[1]); + + /* Construct highpart rtx. */ + /* Note that operands[1] can be VOIDmode constant, + so we need to use gen_highpart_mode(). + Refer to gcc/emit-rtl.c for more information. */ + operands[4] = gen_highpart (SImode, operands[0]); + operands[5] = gen_highpart_mode (SImode, + GET_MODE (operands[0]), operands[1]); + + /* Actually we would like to create move behavior by ourself. + So that movsi expander could have chance to split large constant. */ + emit_move_insn (operands[2], operands[3]); + emit_move_insn (operands[4], operands[5]); + DONE; +}) + +;; There is 'movd44' instruction for DImode/DFmode movement under V3/V3M ISA. +;; We only need to split it under V2 ISA or none-16-bit code generation. +(define_split + [(set (match_operand:DIDF 0 "register_operand" "") + (match_operand:DIDF 1 "register_operand" ""))] + "reload_completed + && (TARGET_ISA_V2 || !TARGET_16_BIT)" + [(set (match_dup 0) (match_dup 1)) + (set (match_dup 2) (match_dup 3))] +{ + operands[2] = gen_highpart (SImode, operands[0]); + operands[3] = gen_highpart (SImode, operands[1]); + operands[0] = gen_lowpart (SImode, operands[0]); + operands[1] = gen_lowpart (SImode, operands[1]); + + /* Handle a partial overlap. */ + if (rtx_equal_p (operands[0], operands[3])) + { + rtx tmp0 = operands[0]; + rtx tmp1 = operands[1]; + + operands[0] = operands[2]; + operands[1] = operands[3]; + operands[2] = tmp0; + operands[3] = tmp1; + } +}) + +;; ------------------------------------------------------------- +;; Boolean DImode instructions. +;; ------------------------------------------------------------- + +;; Nowadays, the generic code is supposed to split the DImode +;; boolean operations and have good code generation. +;; Unless we find out some bad cases, there is no need to +;; define DImode boolean operations by ourself. + +;; ------------------------------------------------------------- diff --git a/gcc/config/nds32/nds32-intrinsic.md b/gcc/config/nds32/nds32-intrinsic.md new file mode 100644 index 00000000000..4ee2d851023 --- /dev/null +++ b/gcc/config/nds32/nds32-intrinsic.md @@ -0,0 +1,97 @@ +;; Intrinsic patterns description of Andes NDS32 cpu for GNU compiler +;; Copyright (C) 2012-2013 Free Software Foundation, Inc. +;; Contributed by Andes Technology Corporation. +;; +;; This file is part of GCC. +;; +;; GCC is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published +;; by the Free Software Foundation; either version 3, or (at your +;; option) any later version. +;; +;; GCC is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with GCC; see the file COPYING3. If not see +;; <http://www.gnu.org/licenses/>. + +;; ------------------------------------------------------------------------ + +;; Register Transfer. + +(define_insn "unspec_volatile_mfsr" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "i")] UNSPEC_VOLATILE_MFSR))] + "" + "mfsr\t%0, %V1" + [(set_attr "type" "misc") + (set_attr "length" "4")] +) + +(define_insn "unspec_volatile_mfusr" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec_volatile:SI [(match_operand:SI 1 "immediate_operand" "i")] UNSPEC_VOLATILE_MFUSR))] + "" + "mfusr\t%0, %V1" + [(set_attr "type" "misc") + (set_attr "length" "4")] +) + +(define_insn "unspec_volatile_mtsr" + [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") + (match_operand:SI 1 "immediate_operand" "i")] UNSPEC_VOLATILE_MTSR)] + "" + "mtsr\t%0, %V1" + [(set_attr "type" "misc") + (set_attr "length" "4")] +) + +(define_insn "unspec_volatile_mtusr" + [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r") + (match_operand:SI 1 "immediate_operand" "i")] UNSPEC_VOLATILE_MTUSR)] + "" + "mtusr\t%0, %V1" + [(set_attr "type" "misc") + (set_attr "length" "4")] +) + +;; ------------------------------------------------------------------------ + +;; Interrupt Instructions. + +(define_insn "unspec_volatile_setgie_en" + [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_SETGIE_EN)] + "" + "setgie.e" + [(set_attr "type" "misc")] +) + +(define_insn "unspec_volatile_setgie_dis" + [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_SETGIE_DIS)] + "" + "setgie.d" + [(set_attr "type" "misc")] +) + +;; ------------------------------------------------------------------------ + +;; Cache Synchronization Instructions + +(define_insn "unspec_volatile_isync" + [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "r")] UNSPEC_VOLATILE_ISYNC)] + "" + "isync\t%0" + [(set_attr "type" "misc")] +) + +(define_insn "unspec_volatile_isb" + [(unspec_volatile:SI [(const_int 0)] UNSPEC_VOLATILE_ISB)] + "" + "isb" + [(set_attr "type" "misc")] +) + +;; ------------------------------------------------------------------------ diff --git a/gcc/config/nds32/nds32-modes.def b/gcc/config/nds32/nds32-modes.def new file mode 100644 index 00000000000..9d32ada0ce8 --- /dev/null +++ b/gcc/config/nds32/nds32-modes.def @@ -0,0 +1,21 @@ +/* Extra machine modes of Andes NDS32 cpu for GNU compiler + Copyright (C) 2012-2013 Free Software Foundation, Inc. + Contributed by Andes Technology Corporation. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GCC is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +/* So far, there is no need to define any modes for nds32 target. */ diff --git a/gcc/config/nds32/nds32-multiple.md b/gcc/config/nds32/nds32-multiple.md new file mode 100644 index 00000000000..da89a490d3a --- /dev/null +++ b/gcc/config/nds32/nds32-multiple.md @@ -0,0 +1,410 @@ +;; Load/Store Multiple patterns description of Andes NDS32 cpu for GNU compiler +;; Copyright (C) 2012-2013 Free Software Foundation, Inc. +;; Contributed by Andes Technology Corporation.for NDS32. +;; +;; 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/>. + + +;; Load Multiple Insns. +;; +;; operands[0] is the first of the consecutive registers. +;; operands[1] is the first memory location. +;; operands[2] is the number of consecutive registers. + +(define_expand "load_multiple" + [(match_par_dup 3 [(set (match_operand:SI 0 "" "") + (match_operand:SI 1 "" "")) + (use (match_operand:SI 2 "" ""))])] + "" +{ + int maximum; + + /* Because reduced-set regsiters has few registers + (r0~r5, r6~10, r15, r28~r31, where 'r15' and 'r28~r31' cannot + be used for register allocation), + using 8 registers for load_multiple may easily consume all of them. + It makes register allocation/spilling hard to work. + So we only allow maximum=4 registers for load_multiple + under reduced-set registers. */ + if (TARGET_REDUCED_REGS) + maximum = 4; + else + maximum = 8; + + /* Here are the conditions that must be all passed, + otherwise we have to FAIL this rtx generation: + 1. The number of consecutive registers must be integer. + 2. Maximum 4 or 8 registers for lmw.bi instruction + (based on this nds32-multiple.md design). + 3. Minimum 2 registers for lmw.bi instruction + (based on this nds32-multiple.md design). + 4. operands[0] must be register for sure. + 5. operands[1] must be memory for sure. + 6. Do not cross $r15 register because it is not allocatable. */ + if (GET_CODE (operands[2]) != CONST_INT + || INTVAL (operands[2]) > maximum + || INTVAL (operands[2]) < 2 + || GET_CODE (operands[0]) != REG + || GET_CODE (operands[1]) != MEM + || REGNO (operands[0]) + INTVAL (operands[2]) > TA_REGNUM) + FAIL; + + /* For (mem addr), we force_reg on addr here, + so that nds32_expand_load_multiple can easily use it. */ + operands[3] = nds32_expand_load_multiple (REGNO (operands[0]), + INTVAL (operands[2]), + force_reg (SImode, + XEXP (operands[1], 0)), + operands[1]); +}) + +;; Ordinary Load Multiple. + +(define_insn "*lmwsi8" + [(match_parallel 0 "nds32_load_multiple_operation" + [(set (match_operand:SI 2 "register_operand" "") + (mem:SI (match_operand:SI 1 "register_operand" "r"))) + (set (match_operand:SI 3 "register_operand" "") + (mem:SI (plus:SI (match_dup 1) (const_int 4)))) + (set (match_operand:SI 4 "register_operand" "") + (mem:SI (plus:SI (match_dup 1) (const_int 8)))) + (set (match_operand:SI 5 "register_operand" "") + (mem:SI (plus:SI (match_dup 1) (const_int 12)))) + (set (match_operand:SI 6 "register_operand" "") + (mem:SI (plus:SI (match_dup 1) (const_int 16)))) + (set (match_operand:SI 7 "register_operand" "") + (mem:SI (plus:SI (match_dup 1) (const_int 20)))) + (set (match_operand:SI 8 "register_operand" "") + (mem:SI (plus:SI (match_dup 1) (const_int 24)))) + (set (match_operand:SI 9 "register_operand" "") + (mem:SI (plus:SI (match_dup 1) (const_int 28))))])] + "(XVECLEN (operands[0], 0) == 8)" + "lmw.bi\t%2, [%1], %9, 0x0" + [(set_attr "type" "load") + (set_attr "length" "4")] +) + +(define_insn "*lmwsi7" + [(match_parallel 0 "nds32_load_multiple_operation" + [(set (match_operand:SI 2 "register_operand" "") + (mem:SI (match_operand:SI 1 "register_operand" "r"))) + (set (match_operand:SI 3 "register_operand" "") + (mem:SI (plus:SI (match_dup 1) (const_int 4)))) + (set (match_operand:SI 4 "register_operand" "") + (mem:SI (plus:SI (match_dup 1) (const_int 8)))) + (set (match_operand:SI 5 "register_operand" "") + (mem:SI (plus:SI (match_dup 1) (const_int 12)))) + (set (match_operand:SI 6 "register_operand" "") + (mem:SI (plus:SI (match_dup 1) (const_int 16)))) + (set (match_operand:SI 7 "register_operand" "") + (mem:SI (plus:SI (match_dup 1) (const_int 20)))) + (set (match_operand:SI 8 "register_operand" "") + (mem:SI (plus:SI (match_dup 1) (const_int 24))))])] + "(XVECLEN (operands[0], 0) == 7)" + "lmw.bi\t%2, [%1], %8, 0x0" + [(set_attr "type" "load") + (set_attr "length" "4")] +) + +(define_insn "*lmwsi6" + [(match_parallel 0 "nds32_load_multiple_operation" + [(set (match_operand:SI 2 "register_operand" "") + (mem:SI (match_operand:SI 1 "register_operand" "r"))) + (set (match_operand:SI 3 "register_operand" "") + (mem:SI (plus:SI (match_dup 1) (const_int 4)))) + (set (match_operand:SI 4 "register_operand" "") + (mem:SI (plus:SI (match_dup 1) (const_int 8)))) + (set (match_operand:SI 5 "register_operand" "") + (mem:SI (plus:SI (match_dup 1) (const_int 12)))) + (set (match_operand:SI 6 "register_operand" "") + (mem:SI (plus:SI (match_dup 1) (const_int 16)))) + (set (match_operand:SI 7 "register_operand" "") + (mem:SI (plus:SI (match_dup 1) (const_int 20))))])] + "(XVECLEN (operands[0], 0) == 6)" + "lmw.bi\t%2, [%1], %7, 0x0" + [(set_attr "type" "load") + (set_attr "length" "4")] +) + +(define_insn "*lmwsi5" + [(match_parallel 0 "nds32_load_multiple_operation" + [(set (match_operand:SI 2 "register_operand" "") + (mem:SI (match_operand:SI 1 "register_operand" "r"))) + (set (match_operand:SI 3 "register_operand" "") + (mem:SI (plus:SI (match_dup 1) (const_int 4)))) + (set (match_operand:SI 4 "register_operand" "") + (mem:SI (plus:SI (match_dup 1) (const_int 8)))) + (set (match_operand:SI 5 "register_operand" "") + (mem:SI (plus:SI (match_dup 1) (const_int 12)))) + (set (match_operand:SI 6 "register_operand" "") + (mem:SI (plus:SI (match_dup 1) (const_int 16))))])] + "(XVECLEN (operands[0], 0) == 5)" + "lmw.bi\t%2, [%1], %6, 0x0" + [(set_attr "type" "load") + (set_attr "length" "4")] +) + +(define_insn "*lmwsi4" + [(match_parallel 0 "nds32_load_multiple_operation" + [(set (match_operand:SI 2 "register_operand" "") + (mem:SI (match_operand:SI 1 "register_operand" "r"))) + (set (match_operand:SI 3 "register_operand" "") + (mem:SI (plus:SI (match_dup 1) (const_int 4)))) + (set (match_operand:SI 4 "register_operand" "") + (mem:SI (plus:SI (match_dup 1) (const_int 8)))) + (set (match_operand:SI 5 "register_operand" "") + (mem:SI (plus:SI (match_dup 1) (const_int 12))))])] + "(XVECLEN (operands[0], 0) == 4)" + "lmw.bi\t%2, [%1], %5, 0x0" + [(set_attr "type" "load") + (set_attr "length" "4")] +) + +(define_insn "*lmwsi3" + [(match_parallel 0 "nds32_load_multiple_operation" + [(set (match_operand:SI 2 "register_operand" "") + (mem:SI (match_operand:SI 1 "register_operand" "r"))) + (set (match_operand:SI 3 "register_operand" "") + (mem:SI (plus:SI (match_dup 1) (const_int 4)))) + (set (match_operand:SI 4 "register_operand" "") + (mem:SI (plus:SI (match_dup 1) (const_int 8))))])] + "(XVECLEN (operands[0], 0) == 3)" + "lmw.bi\t%2, [%1], %4, 0x0" + [(set_attr "type" "load") + (set_attr "length" "4")] +) + +(define_insn "*lmwsi2" + [(match_parallel 0 "nds32_load_multiple_operation" + [(set (match_operand:SI 2 "register_operand" "") + (mem:SI (match_operand:SI 1 "register_operand" "r"))) + (set (match_operand:SI 3 "register_operand" "") + (mem:SI (plus:SI (match_dup 1) (const_int 4))))])] + "(XVECLEN (operands[0], 0) == 2)" + "lmw.bi\t%2, [%1], %3, 0x0" + [(set_attr "type" "load") + (set_attr "length" "4")] +) + + +;; Store Multiple Insns. +;; +;; operands[0] is the first memory location. +;; opernads[1] is the first of the consecutive registers. +;; operands[2] is the number of consecutive registers. + +(define_expand "store_multiple" + [(match_par_dup 3 [(set (match_operand:SI 0 "" "") + (match_operand:SI 1 "" "")) + (use (match_operand:SI 2 "" ""))])] + "" +{ + int maximum; + + /* Because reduced-set regsiters has few registers + (r0~r5, r6~10, r15, r28~r31, where 'r15' and 'r28~r31' cannot + be used for register allocation), + using 8 registers for store_multiple may easily consume all of them. + It makes register allocation/spilling hard to work. + So we only allow maximum=4 registers for store_multiple + under reduced-set registers. */ + if (TARGET_REDUCED_REGS) + maximum = 4; + else + maximum = 8; + + /* Here are the conditions that must be all passed, + otherwise we have to FAIL this rtx generation: + 1. The number of consecutive registers must be integer. + 2. Maximum 4 or 8 registers for smw.bi instruction + (based on this nds32-multiple.md design). + 3. Minimum 2 registers for smw.bi instruction + (based on this nds32-multiple.md design). + 4. operands[0] must be memory for sure. + 5. operands[1] must be register for sure. + 6. Do not cross $r15 register because it is not allocatable. */ + if (GET_CODE (operands[2]) != CONST_INT + || INTVAL (operands[2]) > maximum + || INTVAL (operands[2]) < 2 + || GET_CODE (operands[0]) != MEM + || GET_CODE (operands[1]) != REG + || REGNO (operands[1]) + INTVAL (operands[2]) > TA_REGNUM) + FAIL; + + /* For (mem addr), we force_reg on addr here, + so that nds32_expand_store_multiple can easily use it. */ + operands[3] = nds32_expand_store_multiple (REGNO (operands[1]), + INTVAL (operands[2]), + force_reg (SImode, + XEXP (operands[0], 0)), + operands[0]); +}) + +;; Ordinary Store Multiple. + +(define_insn "*stmsi8" + [(match_parallel 0 "nds32_store_multiple_operation" + [(set (mem:SI (match_operand:SI 1 "register_operand" "r")) + (match_operand:SI 2 "register_operand" "")) + (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) + (match_operand:SI 3 "register_operand" "")) + (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) + (match_operand:SI 4 "register_operand" "")) + (set (mem:SI (plus:SI (match_dup 1) (const_int 12))) + (match_operand:SI 5 "register_operand" "")) + (set (mem:SI (plus:SI (match_dup 1) (const_int 16))) + (match_operand:SI 6 "register_operand" "")) + (set (mem:SI (plus:SI (match_dup 1) (const_int 20))) + (match_operand:SI 7 "register_operand" "")) + (set (mem:SI (plus:SI (match_dup 1) (const_int 24))) + (match_operand:SI 8 "register_operand" "")) + (set (mem:SI (plus:SI (match_dup 1) (const_int 28))) + (match_operand:SI 9 "register_operand" ""))])] + "(XVECLEN (operands[0], 0) == 8)" + "smw.bi\t%2, [%1], %9, 0x0" + [(set_attr "type" "store") + (set_attr "length" "4")] +) + +(define_insn "*stmsi7" + [(match_parallel 0 "nds32_store_multiple_operation" + [(set (mem:SI (match_operand:SI 1 "register_operand" "r")) + (match_operand:SI 2 "register_operand" "")) + (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) + (match_operand:SI 3 "register_operand" "")) + (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) + (match_operand:SI 4 "register_operand" "")) + (set (mem:SI (plus:SI (match_dup 1) (const_int 12))) + (match_operand:SI 5 "register_operand" "")) + (set (mem:SI (plus:SI (match_dup 1) (const_int 16))) + (match_operand:SI 6 "register_operand" "")) + (set (mem:SI (plus:SI (match_dup 1) (const_int 20))) + (match_operand:SI 7 "register_operand" "")) + (set (mem:SI (plus:SI (match_dup 1) (const_int 24))) + (match_operand:SI 8 "register_operand" ""))])] + "(XVECLEN (operands[0], 0) == 7)" + "smw.bi\t%2, [%1], %8, 0x0" + [(set_attr "type" "store") + (set_attr "length" "4")] +) + +(define_insn "*stmsi6" + [(match_parallel 0 "nds32_store_multiple_operation" + [(set (mem:SI (match_operand:SI 1 "register_operand" "r")) + (match_operand:SI 2 "register_operand" "")) + (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) + (match_operand:SI 3 "register_operand" "")) + (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) + (match_operand:SI 4 "register_operand" "")) + (set (mem:SI (plus:SI (match_dup 1) (const_int 12))) + (match_operand:SI 5 "register_operand" "")) + (set (mem:SI (plus:SI (match_dup 1) (const_int 16))) + (match_operand:SI 6 "register_operand" "")) + (set (mem:SI (plus:SI (match_dup 1) (const_int 20))) + (match_operand:SI 7 "register_operand" ""))])] + "(XVECLEN (operands[0], 0) == 6)" + "smw.bi\t%2, [%1], %7, 0x0" + [(set_attr "type" "store") + (set_attr "length" "4")] +) + +(define_insn "*stmsi5" + [(match_parallel 0 "nds32_store_multiple_operation" + [(set (mem:SI (match_operand:SI 1 "register_operand" "r")) + (match_operand:SI 2 "register_operand" "")) + (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) + (match_operand:SI 3 "register_operand" "")) + (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) + (match_operand:SI 4 "register_operand" "")) + (set (mem:SI (plus:SI (match_dup 1) (const_int 12))) + (match_operand:SI 5 "register_operand" "")) + (set (mem:SI (plus:SI (match_dup 1) (const_int 16))) + (match_operand:SI 6 "register_operand" ""))])] + "(XVECLEN (operands[0], 0) == 5)" + "smw.bi\t%2, [%1], %6, 0x0" + [(set_attr "type" "store") + (set_attr "length" "4")] +) + +(define_insn "*stmsi4" + [(match_parallel 0 "nds32_store_multiple_operation" + [(set (mem:SI (match_operand:SI 1 "register_operand" "r")) + (match_operand:SI 2 "register_operand" "")) + (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) + (match_operand:SI 3 "register_operand" "")) + (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) + (match_operand:SI 4 "register_operand" "")) + (set (mem:SI (plus:SI (match_dup 1) (const_int 12))) + (match_operand:SI 5 "register_operand" ""))])] + "(XVECLEN (operands[0], 0) == 4)" + "smw.bi\t%2, [%1], %5, 0x0" + [(set_attr "type" "store") + (set_attr "length" "4")] +) + +(define_insn "*stmsi3" + [(match_parallel 0 "nds32_store_multiple_operation" + [(set (mem:SI (match_operand:SI 1 "register_operand" "r")) + (match_operand:SI 2 "register_operand" "")) + (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) + (match_operand:SI 3 "register_operand" "")) + (set (mem:SI (plus:SI (match_dup 1) (const_int 8))) + (match_operand:SI 4 "register_operand" ""))])] + "(XVECLEN (operands[0], 0) == 3)" + "smw.bi\t%2, [%1], %4, 0x0" + [(set_attr "type" "store") + (set_attr "length" "4")] +) + +(define_insn "*stmsi2" + [(match_parallel 0 "nds32_store_multiple_operation" + [(set (mem:SI (match_operand:SI 1 "register_operand" "r")) + (match_operand:SI 2 "register_operand" "")) + (set (mem:SI (plus:SI (match_dup 1) (const_int 4))) + (match_operand:SI 3 "register_operand" ""))])] + "(XVECLEN (operands[0], 0) == 2)" + "smw.bi\t%2, [%1], %3, 0x0" + [(set_attr "type" "store") + (set_attr "length" "4")] +) + +;; Move a block of memory if it is word aligned and MORE than 2 words long. +;; We could let this apply for blocks of less than this, but it clobbers so +;; many registers that there is then probably a better way. +;; +;; operands[0] is the destination block of memory. +;; operands[1] is the source block of memory. +;; operands[2] is the number of bytes to move. +;; operands[3] is the known shared alignment. + +(define_expand "movmemqi" + [(match_operand:BLK 0 "general_operand" "") + (match_operand:BLK 1 "general_operand" "") + (match_operand:SI 2 "const_int_operand" "") + (match_operand:SI 3 "const_int_operand" "")] + "" +{ + if (nds32_expand_movmemqi (operands[0], + operands[1], + operands[2], + operands[3])) + DONE; + + FAIL; +}) + +;; ------------------------------------------------------------------------ diff --git a/gcc/config/nds32/nds32-opts.h b/gcc/config/nds32/nds32-opts.h new file mode 100644 index 00000000000..b38672f0e2f --- /dev/null +++ b/gcc/config/nds32/nds32-opts.h @@ -0,0 +1,35 @@ +/* Definitions for option handling of Andes NDS32 cpu for GNU compiler + Copyright (C) 2012-2013 Free Software Foundation, Inc. + Contributed by Andes Technology Corporation. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GCC is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + +#ifndef NDS32_OPTS_H +#define NDS32_OPTS_H + +#define NDS32_DEFAULT_CACHE_BLOCK_SIZE 16 +#define NDS32_DEFAULT_ISR_VECTOR_SIZE (TARGET_ISA_V3 ? 4 : 16) + +/* The various ANDES ISA. */ +enum nds32_arch_type +{ + ARCH_V2, + ARCH_V3, + ARCH_V3M +}; + +#endif diff --git a/gcc/config/nds32/nds32-peephole2.md b/gcc/config/nds32/nds32-peephole2.md new file mode 100644 index 00000000000..dbe2d6c8a62 --- /dev/null +++ b/gcc/config/nds32/nds32-peephole2.md @@ -0,0 +1,25 @@ +;; define_peephole2 optimization patterns of Andes NDS32 cpu for GNU compiler +;; Copyright (C) 2012-2013 Free Software Foundation, Inc. +;; Contributed by Andes Technology Corporation. +;; +;; This file is part of GCC. +;; +;; GCC is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published +;; by the Free Software Foundation; either version 3, or (at your +;; option) any later version. +;; +;; GCC is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with GCC; see the file COPYING3. If not see +;; <http://www.gnu.org/licenses/>. + + +;; Use define_peephole and define_peephole2 to handle possible +;; target-specific optimization in this file. + +;; ------------------------------------------------------------------------ diff --git a/gcc/config/nds32/nds32-protos.h b/gcc/config/nds32/nds32-protos.h new file mode 100644 index 00000000000..2bc405db0f4 --- /dev/null +++ b/gcc/config/nds32/nds32-protos.h @@ -0,0 +1,128 @@ +/* Prototypes for exported functions of Andes NDS32 cpu for GNU compiler + Copyright (C) 2012-2013 Free Software Foundation, Inc. + Contributed by Andes Technology Corporation. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GCC is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + + +/* ------------------------------------------------------------------------ */ + +/* Defining Data Structures for Per-function Information. */ + +extern void nds32_init_expanders (void); + + +/* Register Usage. */ + +/* -- How Values Fit in Registers. */ + +extern int nds32_hard_regno_nregs (int, enum machine_mode); +extern int nds32_hard_regno_mode_ok (int, enum machine_mode); + + +/* Register Classes. */ + +extern enum reg_class nds32_regno_reg_class (int); + + +/* Stack Layout and Calling Conventions. */ + +/* -- Basic Stack Layout. */ + +extern rtx nds32_return_addr_rtx (int, rtx); + +/* -- Eliminating Frame Pointer and Arg Pointer. */ + +extern HOST_WIDE_INT nds32_initial_elimination_offset (unsigned int, + unsigned int); + +/* -- Passing Arguments in Registers. */ + +extern void nds32_init_cumulative_args (CUMULATIVE_ARGS *, + tree, rtx, tree, int); + +/* -- Function Entry and Exit. */ + +extern void nds32_expand_prologue (void); +extern void nds32_expand_epilogue (void); +extern void nds32_expand_prologue_v3push (void); +extern void nds32_expand_epilogue_v3pop (void); + +/* ------------------------------------------------------------------------ */ + +/* Auxiliary functions for auxiliary macros in nds32.h. */ + +extern bool nds32_ls_333_p (rtx, rtx, rtx, enum machine_mode); + +/* Auxiliary functions for expanding rtl used in nds32-multiple.md. */ + +extern rtx nds32_expand_load_multiple (int, int, rtx, rtx); +extern rtx nds32_expand_store_multiple (int, int, rtx, rtx); +extern int nds32_expand_movmemqi (rtx, rtx, rtx, rtx); + +/* Auxiliary functions for multiple load/store predicate checking. */ + +extern bool nds32_valid_multiple_load_store (rtx, bool); + +/* Auxiliary functions for stack operation predicate checking. */ + +extern bool nds32_valid_stack_push_pop (rtx, bool); + +/* Auxiliary functions for bit operation detection. */ + +extern int nds32_can_use_bclr_p (int); +extern int nds32_can_use_bset_p (int); +extern int nds32_can_use_btgl_p (int); + +extern int nds32_can_use_bitci_p (int); + +/* Auxiliary function for 'Computing the Length of an Insn'. */ + +extern int nds32_adjust_insn_length (rtx, int); + +/* Auxiliary functions for FP_AS_GP detection. */ + +extern bool nds32_symbol_load_store_p (rtx); +extern int nds32_fp_as_gp_check_available (void); + +/* Auxiliary functions for jump table generation. */ + +extern const char *nds32_output_casesi_pc_relative (rtx *); +extern const char *nds32_output_casesi (rtx *); + +/* Auxiliary functions to identify 16 bit addresing mode. */ + +extern enum nds32_16bit_address_type nds32_mem_format (rtx); + +/* Auxiliary functions to output assembly code. */ + +extern const char *nds32_output_16bit_store (rtx *, int); +extern const char *nds32_output_16bit_load (rtx *, int); +extern const char *nds32_output_32bit_store (rtx *, int); +extern const char *nds32_output_32bit_load (rtx *, int); +extern const char *nds32_output_32bit_load_s (rtx *, int); + +/* Auxiliary functions to output stack push/pop instruction. */ + +extern const char *nds32_output_stack_push (void); +extern const char *nds32_output_stack_pop (void); + +/* Auxiliary functions to decide output alignment or not. */ + +extern int nds32_target_alignment (rtx); + +/* ------------------------------------------------------------------------ */ diff --git a/gcc/config/nds32/nds32.c b/gcc/config/nds32/nds32.c new file mode 100644 index 00000000000..2700a872360 --- /dev/null +++ b/gcc/config/nds32/nds32.c @@ -0,0 +1,5721 @@ +/* Subroutines used for code generation of Andes NDS32 cpu for GNU compiler + Copyright (C) 2012-2013 Free Software Foundation, Inc. + Contributed by Andes Technology Corporation. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GCC is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + + + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" +#include "tree.h" +#include "rtl.h" +#include "regs.h" +#include "hard-reg-set.h" +#include "insn-config.h" /* Required by recog.h. */ +#include "conditions.h" +#include "output.h" +#include "insn-attr.h" /* For DFA state_t. */ +#include "insn-codes.h" /* For CODE_FOR_xxx. */ +#include "reload.h" /* For push_reload(). */ +#include "flags.h" +#include "function.h" +#include "expr.h" +#include "recog.h" +#include "diagnostic-core.h" +#include "df.h" +#include "tm_p.h" +#include "tm-constrs.h" +#include "optabs.h" /* For GEN_FCN. */ +#include "target.h" +#include "target-def.h" +#include "langhooks.h" /* For add_builtin_function(). */ +#include "ggc.h" + +/* ------------------------------------------------------------------------ */ + +/* This file is divided into five parts: + + PART 1: Auxiliary static variable definitions and + target hook static variable definitions. + + PART 2: Auxiliary static function definitions. + + PART 3: Implement target hook stuff definitions. + + PART 4: Implemet extern function definitions, + the prototype is in nds32-protos.h. + + PART 5: Initialize target hook structure and definitions. */ + +/* ------------------------------------------------------------------------ */ + +/* PART 1: Auxiliary static variable definitions and + target hook static variable definitions. */ + +/* Refer to nds32.h, there are maximum 73 isr vectors in nds32 architecture. + 0 for reset handler with __attribute__((reset())), + 1-8 for exception handler with __attribute__((exception(1,...,8))), + and 9-72 for interrupt handler with __attribute__((interrupt(0,...,63))). + We use an array to record essential information for each vector. */ +static struct nds32_isr_info nds32_isr_vectors[NDS32_N_ISR_VECTORS]; + +/* Define intrinsic register names. + Please refer to nds32_intrinsic.h file, the index is corresponding to + 'enum nds32_intrinsic_registers' data type values. + NOTE that the base value starting from 1024. */ +static const char * const nds32_intrinsic_register_names[] = +{ + "$PSW", "$IPSW", "$ITYPE", "$IPC" +}; + +/* Defining target-specific uses of __attribute__. */ +static const struct attribute_spec nds32_attribute_table[] = +{ + /* Syntax: { name, min_len, max_len, decl_required, type_required, + function_type_required, handler, affects_type_identity } */ + + /* The interrupt vid: [0-63]+ (actual vector number starts from 9 to 72). */ + { "interrupt", 1, 64, false, false, false, NULL, false }, + /* The exception vid: [1-8]+ (actual vector number starts from 1 to 8). */ + { "exception", 1, 8, false, false, false, NULL, false }, + /* Argument is user's interrupt numbers. The vector number is always 0. */ + { "reset", 1, 1, false, false, false, NULL, false }, + + /* The attributes describing isr nested type. */ + { "nested", 0, 0, false, false, false, NULL, false }, + { "not_nested", 0, 0, false, false, false, NULL, false }, + { "nested_ready", 0, 0, false, false, false, NULL, false }, + + /* The attributes describing isr register save scheme. */ + { "save_all", 0, 0, false, false, false, NULL, false }, + { "partial_save", 0, 0, false, false, false, NULL, false }, + + /* The attributes used by reset attribute. */ + { "nmi", 1, 1, false, false, false, NULL, false }, + { "warm", 1, 1, false, false, false, NULL, false }, + + /* The attribute telling no prologue/epilogue. */ + { "naked", 0, 0, false, false, false, NULL, false }, + + /* The last attribute spec is set to be NULL. */ + { NULL, 0, 0, false, false, false, NULL, false } +}; + + +/* ------------------------------------------------------------------------ */ + +/* PART 2: Auxiliary static function definitions. */ + +/* Function to save and restore machine-specific function data. */ +static struct machine_function * +nds32_init_machine_status (void) +{ + struct machine_function *machine; + machine = ggc_alloc_cleared_machine_function (); + + /* Initially assume this function needs prologue/epilogue. */ + machine->naked_p = 0; + + /* Initially assume this function does NOT use fp_as_gp optimization. */ + machine->fp_as_gp_p = 0; + + return machine; +} + +/* Function to compute stack frame size and + store into cfun->machine structure. */ +static void +nds32_compute_stack_frame (void) +{ + int r; + int block_size; + + /* Because nds32_compute_stack_frame() will be called from different place, + everytime we enter this function, we have to assume this function + needs prologue/epilogue. */ + cfun->machine->naked_p = 0; + + /* Get variadic arguments size to prepare pretend arguments and + push them into stack at prologue. + Currently, we do not push variadic arguments by ourself. + We have GCC handle all the works. + The caller will push all corresponding nameless arguments into stack, + and the callee is able to retrieve them without problems. + These variables are still preserved in case one day + we would like caller passing arguments with registers. */ + cfun->machine->va_args_size = 0; + cfun->machine->va_args_first_regno = SP_REGNUM; + cfun->machine->va_args_last_regno = SP_REGNUM; + + /* Get local variables, incoming variables, and temporary variables size. + Note that we need to make sure it is 8-byte alignment because + there may be no padding bytes if we are using LRA. */ + cfun->machine->local_size = NDS32_ROUND_UP_DOUBLE_WORD (get_frame_size ()); + + /* Get outgoing arguments size. */ + cfun->machine->out_args_size = crtl->outgoing_args_size; + + /* If $fp value is required to be saved on stack, it needs 4 bytes space. + Check whether $fp is ever live. */ + cfun->machine->fp_size = (df_regs_ever_live_p (FP_REGNUM)) ? 4 : 0; + + /* If $gp value is required to be saved on stack, it needs 4 bytes space. + Check whether we are using PIC code genration. */ + cfun->machine->gp_size = (flag_pic) ? 4 : 0; + + /* If $lp value is required to be saved on stack, it needs 4 bytes space. + Check whether $lp is ever live. */ + cfun->machine->lp_size = (df_regs_ever_live_p (LP_REGNUM)) ? 4 : 0; + + /* Initially there is no padding bytes. */ + cfun->machine->callee_saved_area_padding_bytes = 0; + + /* Calculate the bytes of saving callee-saved registers on stack. */ + cfun->machine->callee_saved_regs_size = 0; + cfun->machine->callee_saved_regs_first_regno = SP_REGNUM; + cfun->machine->callee_saved_regs_last_regno = SP_REGNUM; + /* Currently, there is no need to check $r28~$r31 + because we will save them in another way. */ + for (r = 0; r < 28; r++) + { + if (NDS32_REQUIRED_CALLEE_SAVED_P (r)) + { + /* Mark the first required callee-saved register + (only need to set it once). + If first regno == SP_REGNUM, we can tell that + it is the first time to be here. */ + if (cfun->machine->callee_saved_regs_first_regno == SP_REGNUM) + cfun->machine->callee_saved_regs_first_regno = r; + /* Mark the last required callee-saved register. */ + cfun->machine->callee_saved_regs_last_regno = r; + } + } + + /* Check if this function can omit prologue/epilogue code fragment. + If there is 'naked' attribute in this function, + we can set 'naked_p' flag to indicate that + we do not have to generate prologue/epilogue. + Or, if all the following conditions succeed, + we can set this function 'naked_p' as well: + condition 1: first_regno == last_regno == SP_REGNUM, + which means we do not have to save + any callee-saved registers. + condition 2: Both $lp and $fp are NOT live in this function, + which means we do not need to save them. + condition 3: There is no local_size, which means + we do not need to adjust $sp. */ + if (lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl)) + || (cfun->machine->callee_saved_regs_first_regno == SP_REGNUM + && cfun->machine->callee_saved_regs_last_regno == SP_REGNUM + && !df_regs_ever_live_p (FP_REGNUM) + && !df_regs_ever_live_p (LP_REGNUM) + && cfun->machine->local_size == 0)) + { + /* Set this function 'naked_p' and + other functions can check this flag. */ + cfun->machine->naked_p = 1; + + /* No need to save $fp, $gp, and $lp. + We should set these value to be zero + so that nds32_initial_elimination_offset() can work properly. */ + cfun->machine->fp_size = 0; + cfun->machine->gp_size = 0; + cfun->machine->lp_size = 0; + + /* If stack usage computation is required, + we need to provide the static stack size. */ + if (flag_stack_usage_info) + current_function_static_stack_size = 0; + + /* No need to do following adjustment, return immediately. */ + return; + } + + /* Adjustment for v3push instructions: + If we are using v3push (push25/pop25) instructions, + we need to make sure Rb is $r6 and Re is + located on $r6, $r8, $r10, or $r14. + Some results above will be discarded and recomputed. + Note that it is only available under V3/V3M ISA. */ + if (TARGET_V3PUSH) + { + /* Recompute: + cfun->machine->fp_size + cfun->machine->gp_size + cfun->machine->lp_size + cfun->machine->callee_saved_regs_first_regno + cfun->machine->callee_saved_regs_last_regno */ + + /* For v3push instructions, $fp, $gp, and $lp are always saved. */ + cfun->machine->fp_size = 4; + cfun->machine->gp_size = 4; + cfun->machine->lp_size = 4; + + /* Remember to set Rb = $r6. */ + cfun->machine->callee_saved_regs_first_regno = 6; + + if (cfun->machine->callee_saved_regs_last_regno <= 6) + { + /* Re = $r6 */ + cfun->machine->callee_saved_regs_last_regno = 6; + } + else if (cfun->machine->callee_saved_regs_last_regno <= 8) + { + /* Re = $r8 */ + cfun->machine->callee_saved_regs_last_regno = 8; + } + else if (cfun->machine->callee_saved_regs_last_regno <= 10) + { + /* Re = $r10 */ + cfun->machine->callee_saved_regs_last_regno = 10; + } + else if (cfun->machine->callee_saved_regs_last_regno <= 14) + { + /* Re = $r14 */ + cfun->machine->callee_saved_regs_last_regno = 14; + } + else if (cfun->machine->callee_saved_regs_last_regno == SP_REGNUM) + { + /* If last_regno is SP_REGNUM, which means + it is never changed, so set it to Re = $r6. */ + cfun->machine->callee_saved_regs_last_regno = 6; + } + else + { + /* The program flow should not go here. */ + gcc_unreachable (); + } + } + + /* We have correctly set callee_saved_regs_first_regno + and callee_saved_regs_last_regno. + Initially, the callee_saved_regs_size is supposed to be 0. + As long as callee_saved_regs_last_regno is not SP_REGNUM, + we can update callee_saved_regs_size with new size. */ + if (cfun->machine->callee_saved_regs_last_regno != SP_REGNUM) + { + /* Compute pushed size of callee-saved registers. */ + cfun->machine->callee_saved_regs_size + = 4 * (cfun->machine->callee_saved_regs_last_regno + - cfun->machine->callee_saved_regs_first_regno + + 1); + } + + /* Important: We need to make sure that + (va_args_size + fp_size + gp_size + + lp_size + callee_saved_regs_size) + is 8-byte alignment. + If it is not, calculate the padding bytes. */ + block_size = cfun->machine->va_args_size + + cfun->machine->fp_size + + cfun->machine->gp_size + + cfun->machine->lp_size + + cfun->machine->callee_saved_regs_size; + if (!NDS32_DOUBLE_WORD_ALIGN_P (block_size)) + { + cfun->machine->callee_saved_area_padding_bytes + = NDS32_ROUND_UP_DOUBLE_WORD (block_size) - block_size; + } + + /* If stack usage computation is required, + we need to provide the static stack size. */ + if (flag_stack_usage_info) + { + current_function_static_stack_size + = NDS32_ROUND_UP_DOUBLE_WORD (block_size) + + cfun->machine->local_size + + cfun->machine->out_args_size; + } +} + +/* Function to create a parallel rtx pattern + which presents stack push multiple behavior. + The overall concept are: + "push registers to memory", + "adjust stack pointer". */ +static rtx +nds32_gen_stack_push_multiple (rtx Rb, rtx Re, + rtx En4 ATTRIBUTE_UNUSED) +{ + int regno; + int extra_count; + int num_use_regs; + int par_index; + int offset; + + rtx reg; + rtx mem; + rtx push_rtx; + rtx adjust_sp_rtx; + rtx parallel_insn; + + /* We need to provide a customized rtx which contains + necessary information for data analysis, + so we create a parallel rtx like this: + (parallel [(set (mem (plus (reg:SI SP_REGNUM) (const_int -32))) + (reg:SI Rb)) + (set (mem (plus (reg:SI SP_REGNUM) (const_int -28))) + (reg:SI Rb+1)) + ... + (set (mem (plus (reg:SI SP_REGNUM) (const_int -16))) + (reg:SI Re)) + (set (mem (plus (reg:SI SP_REGNUM) (const_int -12))) + (reg:SI FP_REGNUM)) + (set (mem (plus (reg:SI SP_REGNUM) (const_int -8))) + (reg:SI GP_REGNUM)) + (set (mem (plus (reg:SI SP_REGNUM) (const_int -4))) + (reg:SI LP_REGNUM)) + (set (reg:SI SP_REGNUM) + (plus (reg:SI SP_REGNUM) (const_int -32)))]) */ + + /* Calculate the number of registers that will be pushed. */ + extra_count = 0; + if (cfun->machine->fp_size) + extra_count++; + if (cfun->machine->gp_size) + extra_count++; + if (cfun->machine->lp_size) + extra_count++; + /* Note that Rb and Re may be SP_REGNUM. DO NOT count it in. */ + if (REGNO (Rb) == SP_REGNUM && REGNO (Re) == SP_REGNUM) + num_use_regs = extra_count; + else + num_use_regs = REGNO (Re) - REGNO (Rb) + 1 + extra_count; + + /* In addition to used registers, + we need one more space for (set sp sp-x) rtx. */ + parallel_insn = gen_rtx_PARALLEL (VOIDmode, + rtvec_alloc (num_use_regs + 1)); + par_index = 0; + + /* Initialize offset and start to create push behavior. */ + offset = -(num_use_regs * 4); + + /* Create (set mem regX) from Rb, Rb+1 up to Re. */ + for (regno = REGNO (Rb); regno <= (int) REGNO (Re); regno++) + { + /* Rb and Re may be SP_REGNUM. + We need to break this loop immediately. */ + if (regno == SP_REGNUM) + break; + + reg = gen_rtx_REG (SImode, regno); + mem = gen_frame_mem (SImode, plus_constant (Pmode, + stack_pointer_rtx, + offset)); + push_rtx = gen_rtx_SET (VOIDmode, mem, reg); + XVECEXP (parallel_insn, 0, par_index) = push_rtx; + RTX_FRAME_RELATED_P (push_rtx) = 1; + offset = offset + 4; + par_index++; + } + + /* Create (set mem fp), (set mem gp), and (set mem lp) if necessary. */ + if (cfun->machine->fp_size) + { + reg = gen_rtx_REG (SImode, FP_REGNUM); + mem = gen_frame_mem (SImode, plus_constant (Pmode, + stack_pointer_rtx, + offset)); + push_rtx = gen_rtx_SET (VOIDmode, mem, reg); + XVECEXP (parallel_insn, 0, par_index) = push_rtx; + RTX_FRAME_RELATED_P (push_rtx) = 1; + offset = offset + 4; + par_index++; + } + if (cfun->machine->gp_size) + { + reg = gen_rtx_REG (SImode, GP_REGNUM); + mem = gen_frame_mem (SImode, plus_constant (Pmode, + stack_pointer_rtx, + offset)); + push_rtx = gen_rtx_SET (VOIDmode, mem, reg); + XVECEXP (parallel_insn, 0, par_index) = push_rtx; + RTX_FRAME_RELATED_P (push_rtx) = 1; + offset = offset + 4; + par_index++; + } + if (cfun->machine->lp_size) + { + reg = gen_rtx_REG (SImode, LP_REGNUM); + mem = gen_frame_mem (SImode, plus_constant (Pmode, + stack_pointer_rtx, + offset)); + push_rtx = gen_rtx_SET (VOIDmode, mem, reg); + XVECEXP (parallel_insn, 0, par_index) = push_rtx; + RTX_FRAME_RELATED_P (push_rtx) = 1; + offset = offset + 4; + par_index++; + } + + /* Create (set sp sp-x). */ + + /* We need to re-calculate the offset value again for adjustment. */ + offset = -(num_use_regs * 4); + adjust_sp_rtx + = gen_rtx_SET (VOIDmode, + stack_pointer_rtx, + plus_constant (Pmode, stack_pointer_rtx, offset)); + XVECEXP (parallel_insn, 0, par_index) = adjust_sp_rtx; + RTX_FRAME_RELATED_P (adjust_sp_rtx) = 1; + + return parallel_insn; +} + +/* Function to create a parallel rtx pattern + which presents stack pop multiple behavior. + The overall concept are: + "pop registers from memory", + "adjust stack pointer". */ +static rtx +nds32_gen_stack_pop_multiple (rtx Rb, rtx Re, + rtx En4 ATTRIBUTE_UNUSED) +{ + int regno; + int extra_count; + int num_use_regs; + int par_index; + int offset; + + rtx reg; + rtx mem; + rtx pop_rtx; + rtx adjust_sp_rtx; + rtx parallel_insn; + + /* We need to provide a customized rtx which contains + necessary information for data analysis, + so we create a parallel rtx like this: + (parallel [(set (reg:SI Rb) + (mem (reg:SI SP_REGNUM))) + (set (reg:SI Rb+1) + (mem (plus (reg:SI SP_REGNUM) (const_int 4)))) + ... + (set (reg:SI Re) + (mem (plus (reg:SI SP_REGNUM) (const_int 16)))) + (set (reg:SI FP_REGNUM) + (mem (plus (reg:SI SP_REGNUM) (const_int 20)))) + (set (reg:SI GP_REGNUM) + (mem (plus (reg:SI SP_REGNUM) (const_int 24)))) + (set (reg:SI LP_REGNUM) + (mem (plus (reg:SI SP_REGNUM) (const_int 28)))) + (set (reg:SI SP_REGNUM) + (plus (reg:SI SP_REGNUM) (const_int 32)))]) */ + + /* Calculate the number of registers that will be poped. */ + extra_count = 0; + if (cfun->machine->fp_size) + extra_count++; + if (cfun->machine->gp_size) + extra_count++; + if (cfun->machine->lp_size) + extra_count++; + /* Note that Rb and Re may be SP_REGNUM. DO NOT count it in. */ + if (REGNO (Rb) == SP_REGNUM && REGNO (Re) == SP_REGNUM) + num_use_regs = extra_count; + else + num_use_regs = REGNO (Re) - REGNO (Rb) + 1 + extra_count; + + /* In addition to used registers, + we need one more space for (set sp sp+x) rtx. */ + parallel_insn = gen_rtx_PARALLEL (VOIDmode, + rtvec_alloc (num_use_regs + 1)); + par_index = 0; + + /* Initialize offset and start to create pop behavior. */ + offset = 0; + + /* Create (set regX mem) from Rb, Rb+1 up to Re. */ + for (regno = REGNO (Rb); regno <= (int) REGNO (Re); regno++) + { + /* Rb and Re may be SP_REGNUM. + We need to break this loop immediately. */ + if (regno == SP_REGNUM) + break; + + reg = gen_rtx_REG (SImode, regno); + mem = gen_frame_mem (SImode, plus_constant (Pmode, + stack_pointer_rtx, + offset)); + pop_rtx = gen_rtx_SET (VOIDmode, reg, mem); + XVECEXP (parallel_insn, 0, par_index) = pop_rtx; + RTX_FRAME_RELATED_P (pop_rtx) = 1; + offset = offset + 4; + par_index++; + } + + /* Create (set fp mem), (set gp mem), and (set lp mem) if necessary. */ + if (cfun->machine->fp_size) + { + reg = gen_rtx_REG (SImode, FP_REGNUM); + mem = gen_frame_mem (SImode, plus_constant (Pmode, + stack_pointer_rtx, + offset)); + pop_rtx = gen_rtx_SET (VOIDmode, reg, mem); + XVECEXP (parallel_insn, 0, par_index) = pop_rtx; + RTX_FRAME_RELATED_P (pop_rtx) = 1; + offset = offset + 4; + par_index++; + } + if (cfun->machine->gp_size) + { + reg = gen_rtx_REG (SImode, GP_REGNUM); + mem = gen_frame_mem (SImode, plus_constant (Pmode, + stack_pointer_rtx, + offset)); + pop_rtx = gen_rtx_SET (VOIDmode, reg, mem); + XVECEXP (parallel_insn, 0, par_index) = pop_rtx; + RTX_FRAME_RELATED_P (pop_rtx) = 1; + offset = offset + 4; + par_index++; + } + if (cfun->machine->lp_size) + { + reg = gen_rtx_REG (SImode, LP_REGNUM); + mem = gen_frame_mem (SImode, plus_constant (Pmode, + stack_pointer_rtx, + offset)); + pop_rtx = gen_rtx_SET (VOIDmode, reg, mem); + XVECEXP (parallel_insn, 0, par_index) = pop_rtx; + RTX_FRAME_RELATED_P (pop_rtx) = 1; + offset = offset + 4; + par_index++; + } + + /* Create (set sp sp+x). */ + + /* The offset value is already in place. No need to re-calculate it. */ + adjust_sp_rtx + = gen_rtx_SET (VOIDmode, + stack_pointer_rtx, + plus_constant (Pmode, stack_pointer_rtx, offset)); + XVECEXP (parallel_insn, 0, par_index) = adjust_sp_rtx; + RTX_FRAME_RELATED_P (adjust_sp_rtx) = 1; + + return parallel_insn; +} + +/* Function to create a parallel rtx pattern + which presents stack v3push behavior. + The overall concept are: + "push registers to memory", + "adjust stack pointer". */ +static rtx +nds32_gen_stack_v3push (rtx Rb, + rtx Re, + rtx En4 ATTRIBUTE_UNUSED, + rtx imm8u) +{ + int regno; + int num_use_regs; + int par_index; + int offset; + + rtx reg; + rtx mem; + rtx push_rtx; + rtx adjust_sp_rtx; + rtx parallel_insn; + + /* We need to provide a customized rtx which contains + necessary information for data analysis, + so we create a parallel rtx like this: + (parallel [ + (set (mem (plus (reg:SI SP_REGNUM) (const_int -32))) + (reg:SI Rb)) + (set (mem (plus (reg:SI SP_REGNUM) (const_int -28))) + (reg:SI Rb+1)) + ... + (set (mem (plus (reg:SI SP_REGNUM) (const_int -16))) + (reg:SI Re)) + (set (mem (plus (reg:SI SP_REGNUM) (const_int -12))) + (reg:SI FP_REGNUM)) + (set (mem (plus (reg:SI SP_REGNUM) (const_int -8))) + (reg:SI GP_REGNUM)) + (set (mem (plus (reg:SI SP_REGNUM) (const_int -4))) + (reg:SI LP_REGNUM)) + (set (reg:SI SP_REGNUM) + (plus (reg:SI SP_REGNUM) (const_int -32-imm8u)))]) */ + + /* Calculate the number of registers that will be pushed. + Since $fp, $gp, and $lp is always pushed with v3push instruction, + we need to count these three registers. + Under v3push, Rb is $r6, while Re is $r6, $r8, $r10, or $r14. + So there is no need to worry about Rb=Re=SP_REGNUM case. */ + num_use_regs = REGNO (Re) - REGNO (Rb) + 1 + 3; + + /* In addition to used registers, + we need one more space for (set sp sp-x-imm8u) rtx. */ + parallel_insn = gen_rtx_PARALLEL (VOIDmode, + rtvec_alloc (num_use_regs + 1)); + par_index = 0; + + /* Initialize offset and start to create push behavior. */ + offset = -(num_use_regs * 4); + + /* Create (set mem regX) from Rb, Rb+1 up to Re. + Under v3push, Rb is $r6, while Re is $r6, $r8, $r10, or $r14. + So there is no need to worry about Rb=Re=SP_REGNUM case. */ + for (regno = REGNO (Rb); regno <= (int) REGNO (Re); regno++) + { + reg = gen_rtx_REG (SImode, regno); + mem = gen_frame_mem (SImode, plus_constant (Pmode, + stack_pointer_rtx, + offset)); + push_rtx = gen_rtx_SET (VOIDmode, mem, reg); + XVECEXP (parallel_insn, 0, par_index) = push_rtx; + RTX_FRAME_RELATED_P (push_rtx) = 1; + offset = offset + 4; + par_index++; + } + + /* Create (set mem fp). */ + reg = gen_rtx_REG (SImode, FP_REGNUM); + mem = gen_frame_mem (SImode, plus_constant (Pmode, + stack_pointer_rtx, + offset)); + push_rtx = gen_rtx_SET (VOIDmode, mem, reg); + XVECEXP (parallel_insn, 0, par_index) = push_rtx; + RTX_FRAME_RELATED_P (push_rtx) = 1; + offset = offset + 4; + par_index++; + /* Create (set mem gp). */ + reg = gen_rtx_REG (SImode, GP_REGNUM); + mem = gen_frame_mem (SImode, plus_constant (Pmode, + stack_pointer_rtx, + offset)); + push_rtx = gen_rtx_SET (VOIDmode, mem, reg); + XVECEXP (parallel_insn, 0, par_index) = push_rtx; + RTX_FRAME_RELATED_P (push_rtx) = 1; + offset = offset + 4; + par_index++; + /* Create (set mem lp). */ + reg = gen_rtx_REG (SImode, LP_REGNUM); + mem = gen_frame_mem (SImode, plus_constant (Pmode, + stack_pointer_rtx, + offset)); + push_rtx = gen_rtx_SET (VOIDmode, mem, reg); + XVECEXP (parallel_insn, 0, par_index) = push_rtx; + RTX_FRAME_RELATED_P (push_rtx) = 1; + offset = offset + 4; + par_index++; + + /* Create (set sp sp-x-imm8u). */ + + /* We need to re-calculate the offset value again for adjustment. */ + offset = -(num_use_regs * 4); + adjust_sp_rtx + = gen_rtx_SET (VOIDmode, + stack_pointer_rtx, + plus_constant (Pmode, + stack_pointer_rtx, + offset - INTVAL (imm8u))); + XVECEXP (parallel_insn, 0, par_index) = adjust_sp_rtx; + RTX_FRAME_RELATED_P (adjust_sp_rtx) = 1; + + return parallel_insn; +} + +/* Function to create a parallel rtx pattern + which presents stack v3pop behavior. + The overall concept are: + "pop registers from memory", + "adjust stack pointer". */ +static rtx +nds32_gen_stack_v3pop (rtx Rb, + rtx Re, + rtx En4 ATTRIBUTE_UNUSED, + rtx imm8u) +{ + int regno; + int num_use_regs; + int par_index; + int offset; + + rtx reg; + rtx mem; + rtx pop_rtx; + rtx adjust_sp_rtx; + rtx parallel_insn; + + /* We need to provide a customized rtx which contains + necessary information for data analysis, + so we create a parallel rtx like this: + (parallel [(set (reg:SI Rb) + (mem (reg:SI SP_REGNUM))) + (set (reg:SI Rb+1) + (mem (plus (reg:SI SP_REGNUM) (const_int 4)))) + ... + (set (reg:SI Re) + (mem (plus (reg:SI SP_REGNUM) (const_int 16)))) + (set (reg:SI FP_REGNUM) + (mem (plus (reg:SI SP_REGNUM) (const_int 20)))) + (set (reg:SI GP_REGNUM) + (mem (plus (reg:SI SP_REGNUM) (const_int 24)))) + (set (reg:SI LP_REGNUM) + (mem (plus (reg:SI SP_REGNUM) (const_int 28)))) + (set (reg:SI SP_REGNUM) + (plus (reg:SI SP_REGNUM) (const_int 32+imm8u)))]) */ + + /* Calculate the number of registers that will be poped. + Since $fp, $gp, and $lp is always poped with v3pop instruction, + we need to count these three registers. + Under v3push, Rb is $r6, while Re is $r6, $r8, $r10, or $r14. + So there is no need to worry about Rb=Re=SP_REGNUM case. */ + num_use_regs = REGNO (Re) - REGNO (Rb) + 1 + 3; + + /* In addition to used registers, + we need one more space for (set sp sp+x+imm8u) rtx. */ + parallel_insn = gen_rtx_PARALLEL (VOIDmode, + rtvec_alloc (num_use_regs + 1)); + par_index = 0; + + /* Initialize offset and start to create pop behavior. */ + offset = 0; + + /* Create (set regX mem) from Rb, Rb+1 up to Re. + Under v3pop, Rb is $r6, while Re is $r6, $r8, $r10, or $r14. + So there is no need to worry about Rb=Re=SP_REGNUM case. */ + for (regno = REGNO (Rb); regno <= (int) REGNO (Re); regno++) + { + reg = gen_rtx_REG (SImode, regno); + mem = gen_frame_mem (SImode, plus_constant (Pmode, + stack_pointer_rtx, + offset)); + pop_rtx = gen_rtx_SET (VOIDmode, reg, mem); + XVECEXP (parallel_insn, 0, par_index) = pop_rtx; + RTX_FRAME_RELATED_P (pop_rtx) = 1; + offset = offset + 4; + par_index++; + } + + /* Create (set fp mem). */ + reg = gen_rtx_REG (SImode, FP_REGNUM); + mem = gen_frame_mem (SImode, plus_constant (Pmode, + stack_pointer_rtx, + offset)); + pop_rtx = gen_rtx_SET (VOIDmode, reg, mem); + XVECEXP (parallel_insn, 0, par_index) = pop_rtx; + RTX_FRAME_RELATED_P (pop_rtx) = 1; + offset = offset + 4; + par_index++; + /* Create (set gp mem). */ + reg = gen_rtx_REG (SImode, GP_REGNUM); + mem = gen_frame_mem (SImode, plus_constant (Pmode, + stack_pointer_rtx, + offset)); + pop_rtx = gen_rtx_SET (VOIDmode, reg, mem); + XVECEXP (parallel_insn, 0, par_index) = pop_rtx; + RTX_FRAME_RELATED_P (pop_rtx) = 1; + offset = offset + 4; + par_index++; + /* Create (set lp mem ). */ + reg = gen_rtx_REG (SImode, LP_REGNUM); + mem = gen_frame_mem (SImode, plus_constant (Pmode, + stack_pointer_rtx, + offset)); + pop_rtx = gen_rtx_SET (VOIDmode, reg, mem); + XVECEXP (parallel_insn, 0, par_index) = pop_rtx; + RTX_FRAME_RELATED_P (pop_rtx) = 1; + offset = offset + 4; + par_index++; + + /* Create (set sp sp+x+imm8u). */ + + /* The offset value is already in place. No need to re-calculate it. */ + adjust_sp_rtx + = gen_rtx_SET (VOIDmode, + stack_pointer_rtx, + plus_constant (Pmode, + stack_pointer_rtx, + offset + INTVAL (imm8u))); + XVECEXP (parallel_insn, 0, par_index) = adjust_sp_rtx; + RTX_FRAME_RELATED_P (adjust_sp_rtx) = 1; + + return parallel_insn; +} + +/* A subroutine that checks multiple load and store + using consecutive registers. + OP is a parallel rtx we would like to check. + LOAD_P indicates whether we are checking load operation. + PAR_INDEX is starting element of parallel rtx. + FIRST_ELT_REGNO is used to tell starting register number. + COUNT helps us to check consecutive register numbers. */ +static bool +nds32_consecutive_registers_load_store_p (rtx op, + bool load_p, + int par_index, + int first_elt_regno, + int count) +{ + int i; + int check_regno; + rtx elt; + rtx elt_reg; + rtx elt_mem; + + for (i = 0; i < count; i++) + { + /* Pick up each element from parallel rtx. */ + elt = XVECEXP (op, 0, i + par_index); + + /* If this element is not a 'set' rtx, return false immediately. */ + if (GET_CODE (elt) != SET) + return false; + + /* Pick up reg and mem of this element. */ + elt_reg = load_p ? SET_DEST (elt) : SET_SRC (elt); + elt_mem = load_p ? SET_SRC (elt) : SET_DEST (elt); + + /* If elt_reg is not a expected reg rtx, return false. */ + if (GET_CODE (elt_reg) != REG || GET_MODE (elt_reg) != SImode) + return false; + /* If elt_mem is not a expected mem rtx, return false. */ + if (GET_CODE (elt_mem) != MEM || GET_MODE (elt_mem) != SImode) + return false; + + /* The consecutive registers should be in (Rb,Rb+1...Re) order. */ + check_regno = first_elt_regno + i; + + /* If the register number is not continuous, return false. */ + if (REGNO (elt_reg) != (unsigned int) check_regno) + return false; + } + + return true; +} + +/* A helper function to emit section head template. */ +static void +nds32_emit_section_head_template (char section_name[], + char symbol_name[], + int align_value, + bool object_p) +{ + const char *flags_str; + const char *type_str; + + flags_str = (object_p) ? "\"a\"" : "\"ax\""; + type_str = (object_p) ? "@object" : "@function"; + + fprintf (asm_out_file, "\t.section\t%s, %s\n", section_name, flags_str); + fprintf (asm_out_file, "\t.align\t%d\n", align_value); + fprintf (asm_out_file, "\t.global\t%s\n", symbol_name); + fprintf (asm_out_file, "\t.type\t%s, %s\n", symbol_name, type_str); + fprintf (asm_out_file, "%s:\n", symbol_name); +} + +/* A helper function to emit section tail template. */ +static void +nds32_emit_section_tail_template (char symbol_name[]) +{ + fprintf (asm_out_file, "\t.size\t%s, .-%s\n", symbol_name, symbol_name); +} + +/* Function to emit isr jump table section. */ +static void +nds32_emit_isr_jmptbl_section (int vector_id) +{ + char section_name[100]; + char symbol_name[100]; + + /* Prepare jmptbl section and symbol name. */ + snprintf (section_name, sizeof (section_name), + ".nds32_jmptbl.%02d", vector_id); + snprintf (symbol_name, sizeof (symbol_name), + "_nds32_jmptbl_%02d", vector_id); + + nds32_emit_section_head_template (section_name, symbol_name, 2, true); + fprintf (asm_out_file, "\t.word\t%s\n", + nds32_isr_vectors[vector_id].func_name); + nds32_emit_section_tail_template (symbol_name); +} + +/* Function to emit isr vector section. */ +static void +nds32_emit_isr_vector_section (int vector_id) +{ + unsigned int vector_number_offset = 0; + const char *c_str = "CATEGORY"; + const char *sr_str = "SR"; + const char *nt_str = "NT"; + const char *vs_str = "VS"; + char first_level_handler_name[100]; + char section_name[100]; + char symbol_name[100]; + + /* Set the vector number offset so that we can calculate + the value that user specifies in the attribute. + We also prepare the category string for first level handler name. */ + switch (nds32_isr_vectors[vector_id].category) + { + case NDS32_ISR_INTERRUPT: + vector_number_offset = 9; + c_str = "i"; + break; + case NDS32_ISR_EXCEPTION: + vector_number_offset = 0; + c_str = "e"; + break; + case NDS32_ISR_NONE: + case NDS32_ISR_RESET: + /* Normally it should not be here. */ + gcc_unreachable (); + break; + } + + /* Prepare save reg string for first level handler name. */ + switch (nds32_isr_vectors[vector_id].save_reg) + { + case NDS32_SAVE_ALL: + sr_str = "sa"; + break; + case NDS32_PARTIAL_SAVE: + sr_str = "ps"; + break; + } + + /* Prepare nested type string for first level handler name. */ + switch (nds32_isr_vectors[vector_id].nested_type) + { + case NDS32_NESTED: + nt_str = "ns"; + break; + case NDS32_NOT_NESTED: + nt_str = "nn"; + break; + case NDS32_NESTED_READY: + nt_str = "nr"; + break; + } + + /* Currently we have 4-byte or 16-byte size for each vector. + If it is 4-byte, the first level handler name has suffix string "_4b". */ + vs_str = (nds32_isr_vector_size == 4) ? "_4b" : ""; + + /* Now we can create first level handler name. */ + snprintf (first_level_handler_name, sizeof (first_level_handler_name), + "_nds32_%s_%s_%s%s", c_str, sr_str, nt_str, vs_str); + + /* Prepare vector section and symbol name. */ + snprintf (section_name, sizeof (section_name), + ".nds32_vector.%02d", vector_id); + snprintf (symbol_name, sizeof (symbol_name), + "_nds32_vector_%02d%s", vector_id, vs_str); + + + /* Everything is ready. We can start emit vector section content. */ + nds32_emit_section_head_template (section_name, symbol_name, + floor_log2 (nds32_isr_vector_size), false); + + /* According to the vector size, the instructions in the + vector section may be different. */ + if (nds32_isr_vector_size == 4) + { + /* This block is for 4-byte vector size. + Hardware $VID support is necessary and only one instruction + is needed in vector section. */ + fprintf (asm_out_file, "\tj\t%s ! jump to first level handler\n", + first_level_handler_name); + } + else + { + /* This block is for 16-byte vector size. + There is NO hardware $VID so that we need several instructions + such as pushing GPRs and preparing software vid at vector section. + For pushing GPRs, there are four variations for + 16-byte vector content and we have to handle each combination. + For preparing software vid, note that the vid need to + be substracted vector_number_offset. */ + if (TARGET_REDUCED_REGS) + { + if (nds32_isr_vectors[vector_id].save_reg == NDS32_SAVE_ALL) + { + /* Case of reduced set registers and save_all attribute. */ + fprintf (asm_out_file, "\t! reduced set regs + save_all\n"); + fprintf (asm_out_file, "\tsmw.adm\t$r15, [$sp], $r15, 0xf\n"); + fprintf (asm_out_file, "\tsmw.adm\t$r0, [$sp], $r10, 0x0\n"); + + } + else + { + /* Case of reduced set registers and partial_save attribute. */ + fprintf (asm_out_file, "\t! reduced set regs + partial_save\n"); + fprintf (asm_out_file, "\tsmw.adm\t$r15, [$sp], $r15, 0x2\n"); + fprintf (asm_out_file, "\tsmw.adm\t$r0, [$sp], $r5, 0x0\n"); + } + } + else + { + if (nds32_isr_vectors[vector_id].save_reg == NDS32_SAVE_ALL) + { + /* Case of full set registers and save_all attribute. */ + fprintf (asm_out_file, "\t! full set regs + save_all\n"); + fprintf (asm_out_file, "\tsmw.adm\t$r0, [$sp], $r27, 0xf\n"); + } + else + { + /* Case of full set registers and partial_save attribute. */ + fprintf (asm_out_file, "\t! full set regs + partial_save\n"); + fprintf (asm_out_file, "\tsmw.adm\t$r15, [$sp], $r27, 0x2\n"); + fprintf (asm_out_file, "\tsmw.adm\t$r0, [$sp], $r5, 0x0\n"); + } + } + + fprintf (asm_out_file, "\tmovi\t$r0, %d ! preparing software vid\n", + vector_id - vector_number_offset); + fprintf (asm_out_file, "\tj\t%s ! jump to first level handler\n", + first_level_handler_name); + } + + nds32_emit_section_tail_template (symbol_name); +} + +/* Function to emit isr reset handler content. + Including all jmptbl/vector references, jmptbl section, + vector section, nmi handler section, and warm handler section. */ +static void +nds32_emit_isr_reset_content (void) +{ + unsigned int i; + unsigned int total_n_vectors; + const char *vs_str; + char reset_handler_name[100]; + char section_name[100]; + char symbol_name[100]; + + total_n_vectors = nds32_isr_vectors[0].total_n_vectors; + vs_str = (nds32_isr_vector_size == 4) ? "_4b" : ""; + + fprintf (asm_out_file, "\t! RESET HANDLER CONTENT - BEGIN !\n"); + + /* Create references in .rodata according to total number of vectors. */ + fprintf (asm_out_file, "\t.section\t.rodata\n"); + fprintf (asm_out_file, "\t.align\t2\n"); + + /* Emit jmptbl references. */ + fprintf (asm_out_file, "\t ! references to jmptbl section entries\n"); + for (i = 0; i < total_n_vectors; i++) + fprintf (asm_out_file, "\t.word\t_nds32_jmptbl_%02d\n", i); + + /* Emit vector references. */ + fprintf (asm_out_file, "\t ! references to vector section entries\n"); + for (i = 0; i < total_n_vectors; i++) + fprintf (asm_out_file, "\t.word\t_nds32_vector_%02d%s\n", i, vs_str); + + /* Emit jmptbl_00 section. */ + snprintf (section_name, sizeof (section_name), ".nds32_jmptbl.00"); + snprintf (symbol_name, sizeof (symbol_name), "_nds32_jmptbl_00"); + + fprintf (asm_out_file, "\t! ....................................\n"); + nds32_emit_section_head_template (section_name, symbol_name, 2, true); + fprintf (asm_out_file, "\t.word\t%s\n", + nds32_isr_vectors[0].func_name); + nds32_emit_section_tail_template (symbol_name); + + /* Emit vector_00 section. */ + snprintf (section_name, sizeof (section_name), ".nds32_vector.00"); + snprintf (symbol_name, sizeof (symbol_name), "_nds32_vector_00%s", vs_str); + snprintf (reset_handler_name, sizeof (reset_handler_name), + "_nds32_reset%s", vs_str); + + fprintf (asm_out_file, "\t! ....................................\n"); + nds32_emit_section_head_template (section_name, symbol_name, + floor_log2 (nds32_isr_vector_size), false); + fprintf (asm_out_file, "\tj\t%s ! jump to reset handler\n", + reset_handler_name); + nds32_emit_section_tail_template (symbol_name); + + /* Emit nmi handler section. */ + snprintf (section_name, sizeof (section_name), ".nds32_nmih"); + snprintf (symbol_name, sizeof (symbol_name), "_nds32_nmih"); + + fprintf (asm_out_file, "\t! ....................................\n"); + nds32_emit_section_head_template (section_name, symbol_name, 2, true); + fprintf (asm_out_file, "\t.word\t%s\n", + (strlen (nds32_isr_vectors[0].nmi_name) == 0) + ? "0" + : nds32_isr_vectors[0].nmi_name); + nds32_emit_section_tail_template (symbol_name); + + /* Emit warm handler section. */ + snprintf (section_name, sizeof (section_name), ".nds32_wrh"); + snprintf (symbol_name, sizeof (symbol_name), "_nds32_wrh"); + + fprintf (asm_out_file, "\t! ....................................\n"); + nds32_emit_section_head_template (section_name, symbol_name, 2, true); + fprintf (asm_out_file, "\t.word\t%s\n", + (strlen (nds32_isr_vectors[0].warm_name) == 0) + ? "0" + : nds32_isr_vectors[0].warm_name); + nds32_emit_section_tail_template (symbol_name); + + fprintf (asm_out_file, "\t! RESET HANDLER CONTENT - END !\n"); +} + +/* Function for nds32_merge_decl_attributes() and nds32_insert_attributes() + to check if there are any conflict isr-specific attributes being set. + We need to check: + 1. Only 'save_all' or 'partial_save' in the attributes. + 2. Only 'nested', 'not_nested', or 'nested_ready' in the attributes. + 3. Only 'interrupt', 'exception', or 'reset' in the attributes. */ +static void +nds32_check_isr_attrs_conflict (tree func_decl, tree func_attrs) +{ + int save_all_p, partial_save_p; + int nested_p, not_nested_p, nested_ready_p; + int intr_p, excp_p, reset_p; + + /* Initialize variables. */ + save_all_p = partial_save_p = 0; + nested_p = not_nested_p = nested_ready_p = 0; + intr_p = excp_p = reset_p = 0; + + /* We must check at MOST one attribute to set save-reg. */ + if (lookup_attribute ("save_all", func_attrs)) + save_all_p = 1; + if (lookup_attribute ("partial_save", func_attrs)) + partial_save_p = 1; + + if ((save_all_p + partial_save_p) > 1) + error ("multiple save reg attributes to function %qD", func_decl); + + /* We must check at MOST one attribute to set nested-type. */ + if (lookup_attribute ("nested", func_attrs)) + nested_p = 1; + if (lookup_attribute ("not_nested", func_attrs)) + not_nested_p = 1; + if (lookup_attribute ("nested_ready", func_attrs)) + nested_ready_p = 1; + + if ((nested_p + not_nested_p + nested_ready_p) > 1) + error ("multiple nested types attributes to function %qD", func_decl); + + /* We must check at MOST one attribute to + set interrupt/exception/reset. */ + if (lookup_attribute ("interrupt", func_attrs)) + intr_p = 1; + if (lookup_attribute ("exception", func_attrs)) + excp_p = 1; + if (lookup_attribute ("reset", func_attrs)) + reset_p = 1; + + if ((intr_p + excp_p + reset_p) > 1) + error ("multiple interrupt attributes to function %qD", func_decl); +} + +/* Function to construct isr vectors information array. + We DO NOT HAVE TO check if the attributes are valid + because those works are supposed to be done on + nds32_merge_decl_attributes() and nds32_insert_attributes(). */ +static void +nds32_construct_isr_vectors_information (tree func_attrs, + const char *func_name) +{ + tree save_all, partial_save; + tree nested, not_nested, nested_ready; + tree intr, excp, reset; + + save_all = lookup_attribute ("save_all", func_attrs); + partial_save = lookup_attribute ("partial_save", func_attrs); + + nested = lookup_attribute ("nested", func_attrs); + not_nested = lookup_attribute ("not_nested", func_attrs); + nested_ready = lookup_attribute ("nested_ready", func_attrs); + + intr = lookup_attribute ("interrupt", func_attrs); + excp = lookup_attribute ("exception", func_attrs); + reset = lookup_attribute ("reset", func_attrs); + + /* If there is no interrupt/exception/reset, we can return immediately. */ + if (!intr && !excp && !reset) + return; + + /* If we are here, either we have interrupt/exception, + or reset attribute. */ + if (intr || excp) + { + tree id_list; + + /* Prepare id list so that we can traverse and set vector id. */ + id_list = (intr) ? (TREE_VALUE (intr)) : (TREE_VALUE (excp)); + + while (id_list) + { + tree id; + int vector_id; + unsigned int vector_number_offset; + + /* The way to handle interrupt or exception is the same, + we just need to take care of actual vector number. + For interrupt(0..63), the actual vector number is (9..72). + For exception(1..8), the actual vector number is (1..8). */ + vector_number_offset = (intr) ? (9) : (0); + + /* Pick up each vector id value. */ + id = TREE_VALUE (id_list); + /* Add vector_number_offset to get actual vector number. */ + vector_id = TREE_INT_CST_LOW (id) + vector_number_offset; + + /* Enable corresponding vector and set function name. */ + nds32_isr_vectors[vector_id].category = (intr) + ? (NDS32_ISR_INTERRUPT) + : (NDS32_ISR_EXCEPTION); + strcpy (nds32_isr_vectors[vector_id].func_name, func_name); + + /* Set register saving scheme. */ + if (save_all) + nds32_isr_vectors[vector_id].save_reg = NDS32_SAVE_ALL; + else if (partial_save) + nds32_isr_vectors[vector_id].save_reg = NDS32_PARTIAL_SAVE; + + /* Set nested type. */ + if (nested) + nds32_isr_vectors[vector_id].nested_type = NDS32_NESTED; + else if (not_nested) + nds32_isr_vectors[vector_id].nested_type = NDS32_NOT_NESTED; + else if (nested_ready) + nds32_isr_vectors[vector_id].nested_type = NDS32_NESTED_READY; + + /* Advance to next id. */ + id_list = TREE_CHAIN (id_list); + } + } + else + { + tree id_list; + tree id; + tree nmi, warm; + + /* Deal with reset attribute. Its vector number is always 0. */ + nds32_isr_vectors[0].category = NDS32_ISR_RESET; + + /* Prepare id_list and identify id value so that + we can set total number of vectors. */ + id_list = TREE_VALUE (reset); + id = TREE_VALUE (id_list); + + /* The total vectors = interrupt + exception numbers + reset. + There are 8 exception and 1 reset in nds32 architecture. */ + nds32_isr_vectors[0].total_n_vectors = TREE_INT_CST_LOW (id) + 8 + 1; + strcpy (nds32_isr_vectors[0].func_name, func_name); + + /* Retrieve nmi and warm function. */ + nmi = lookup_attribute ("nmi", func_attrs); + warm = lookup_attribute ("warm", func_attrs); + + if (nmi != NULL_TREE) + { + tree nmi_func_list; + tree nmi_func; + + nmi_func_list = TREE_VALUE (nmi); + nmi_func = TREE_VALUE (nmi_func_list); + + /* Record nmi function name. */ + strcpy (nds32_isr_vectors[0].nmi_name, + IDENTIFIER_POINTER (nmi_func)); + } + + if (warm != NULL_TREE) + { + tree warm_func_list; + tree warm_func; + + warm_func_list = TREE_VALUE (warm); + warm_func = TREE_VALUE (warm_func_list); + + /* Record warm function name. */ + strcpy (nds32_isr_vectors[0].warm_name, + IDENTIFIER_POINTER (warm_func)); + } + } +} + +/* Function that may creates more instructions + for large value on adjusting stack pointer. + + In nds32 target, 'addi' can be used for stack pointer + adjustment in prologue/epilogue stage. + However, sometimes there are too many local variables so that + the adjustment value is not able to be fit in the 'addi' instruction. + One solution is to move value into a register + and then use 'add' instruction. + In practice, we use TA_REGNUM ($r15) to accomplish this purpose. + Also, we need to return zero for sp adjustment so that + proglogue/epilogue knows there is no need to create 'addi' instruction. */ +static int +nds32_force_addi_stack_int (int full_value) +{ + int adjust_value; + + rtx tmp_reg; + rtx sp_adjust_insn; + + if (!satisfies_constraint_Is15 (GEN_INT (full_value))) + { + /* The value is not able to fit in single addi instruction. + Create more instructions of moving value into a register + and then add stack pointer with it. */ + + /* $r15 is going to be temporary register to hold the value. */ + tmp_reg = gen_rtx_REG (SImode, TA_REGNUM); + + /* Create one more instruction to move value + into the temporary register. */ + emit_move_insn (tmp_reg, GEN_INT (full_value)); + + /* Create new 'add' rtx. */ + sp_adjust_insn = gen_addsi3 (stack_pointer_rtx, + stack_pointer_rtx, + tmp_reg); + /* Emit rtx into insn list and receive its transformed insn rtx. */ + sp_adjust_insn = emit_insn (sp_adjust_insn); + + /* At prologue, we need to tell GCC that this is frame related insn, + so that we can consider this instruction to output debug information. + If full_value is NEGATIVE, it means this function + is invoked by expand_prologue. */ + if (full_value < 0) + { + /* Because (tmp_reg <- full_value) may be split into two + rtl patterns, we can not set its RTX_FRAME_RELATED_P. + We need to construct another (sp <- sp + full_value) + and then insert it into sp_adjust_insn's reg note to + represent a frame related expression. + GCC knows how to refer it and output debug information. */ + + rtx plus_rtx; + rtx set_rtx; + + plus_rtx = plus_constant (Pmode, stack_pointer_rtx, full_value); + set_rtx = gen_rtx_SET (VOIDmode, stack_pointer_rtx, plus_rtx); + add_reg_note (sp_adjust_insn, REG_FRAME_RELATED_EXPR, set_rtx); + + RTX_FRAME_RELATED_P (sp_adjust_insn) = 1; + } + + /* We have used alternative way to adjust stack pointer value. + Return zero so that prologue/epilogue + will not generate other instructions. */ + return 0; + } + else + { + /* The value is able to fit in addi instruction. + However, remember to make it to be positive value + because we want to return 'adjustment' result. */ + adjust_value = (full_value < 0) ? (-full_value) : (full_value); + + return adjust_value; + } +} + +/* Return true if MODE/TYPE need double word alignment. */ +static bool +nds32_needs_double_word_align (enum machine_mode mode, const_tree type) +{ + unsigned int align; + + /* When 'type' is nonnull, there is no need to look at 'mode'. */ + align = (type ? TYPE_ALIGN (type) : GET_MODE_ALIGNMENT (mode)); + + return (align > PARM_BOUNDARY); +} + +/* Return true if FUNC is a naked function. */ +static bool nds32_naked_function_p (tree func) +{ + tree t; + + if (TREE_CODE (func) != FUNCTION_DECL) + abort (); + + t = lookup_attribute ("naked", DECL_ATTRIBUTES (func)); + + return (t != NULL_TREE); +} + +/* Function that check if 'X' is a valid address register. + The variable 'STRICT' is very important to + make decision for register number. + + STRICT : true + => We are in reload pass or after reload pass. + The register number should be strictly limited in general registers. + + STRICT : false + => Before reload pass, we are free to use any register number. */ +static bool +nds32_address_register_rtx_p (rtx x, bool strict) +{ + int regno; + + if (GET_CODE (x) != REG) + return false; + + regno = REGNO (x); + + if (strict) + return REGNO_OK_FOR_BASE_P (regno); + else + return true; +} + +/* Function that check if 'INDEX' is valid to be a index rtx for address. + + OUTER_MODE : Machine mode of outer address rtx. + INDEX : Check if this rtx is valid to be a index for address. + STRICT : If it is true, we are in reload pass or after reload pass. */ +static bool +nds32_legitimate_index_p (enum machine_mode outer_mode, + rtx index, + bool strict) +{ + int regno; + rtx op0; + rtx op1; + + switch (GET_CODE (index)) + { + case REG: + regno = REGNO (index); + /* If we are in reload pass or after reload pass, + we need to limit it to general register. */ + if (strict) + return REGNO_OK_FOR_INDEX_P (regno); + else + return true; + + case CONST_INT: + /* The alignment of the integer value is determined by 'outer_mode'. */ + if (GET_MODE_SIZE (outer_mode) == 1) + { + /* Further check if the value is legal for the 'outer_mode'. */ + if (!satisfies_constraint_Is15 (index)) + return false; + + /* Pass all test, the value is valid, return true. */ + return true; + } + if (GET_MODE_SIZE (outer_mode) == 2 + && NDS32_HALF_WORD_ALIGN_P (INTVAL (index))) + { + /* Further check if the value is legal for the 'outer_mode'. */ + if (!satisfies_constraint_Is16 (index)) + return false; + + /* Pass all test, the value is valid, return true. */ + return true; + } + if (GET_MODE_SIZE (outer_mode) == 4 + && NDS32_SINGLE_WORD_ALIGN_P (INTVAL (index))) + { + /* Further check if the value is legal for the 'outer_mode'. */ + if (!satisfies_constraint_Is17 (index)) + return false; + + /* Pass all test, the value is valid, return true. */ + return true; + } + if (GET_MODE_SIZE (outer_mode) == 8 + && NDS32_SINGLE_WORD_ALIGN_P (INTVAL (index))) + { + /* Further check if the value is legal for the 'outer_mode'. */ + if (!satisfies_constraint_Is17 (gen_int_mode (INTVAL (index) + 4, + SImode))) + return false; + + /* Pass all test, the value is valid, return true. */ + return true; + } + + return false; + + case MULT: + op0 = XEXP (index, 0); + op1 = XEXP (index, 1); + + if (REG_P (op0) && CONST_INT_P (op1)) + { + int multiplier; + multiplier = INTVAL (op1); + + /* We only allow (mult reg const_int_1) + or (mult reg const_int_2) or (mult reg const_int_4). */ + if (multiplier != 1 && multiplier != 2 && multiplier != 4) + return false; + + regno = REGNO (op0); + /* Limit it in general registers if we are + in reload pass or after reload pass. */ + if(strict) + return REGNO_OK_FOR_INDEX_P (regno); + else + return true; + } + + return false; + + case ASHIFT: + op0 = XEXP (index, 0); + op1 = XEXP (index, 1); + + if (REG_P (op0) && CONST_INT_P (op1)) + { + int sv; + /* op1 is already the sv value for use to do left shift. */ + sv = INTVAL (op1); + + /* We only allow (ashift reg const_int_0) + or (ashift reg const_int_1) or (ashift reg const_int_2). */ + if (sv != 0 && sv != 1 && sv !=2) + return false; + + regno = REGNO (op0); + /* Limit it in general registers if we are + in reload pass or after reload pass. */ + if(strict) + return REGNO_OK_FOR_INDEX_P (regno); + else + return true; + } + + return false; + + default: + return false; + } +} + +/* Function to expand builtin function for + '[(unspec_volatile [(reg)])]'. */ +static rtx +nds32_expand_builtin_null_ftype_reg (enum insn_code icode, + tree exp, rtx target) +{ + /* Mapping: + ops[0] <--> value0 <--> arg0 */ + struct expand_operand ops[1]; + tree arg0; + rtx value0; + + /* Grab the incoming arguments and extract its rtx. */ + arg0 = CALL_EXPR_ARG (exp, 0); + value0 = expand_normal (arg0); + + /* Create operands. */ + create_input_operand (&ops[0], value0, TYPE_MODE (TREE_TYPE (arg0))); + + /* Emit new instruction. */ + if (!maybe_expand_insn (icode, 1, ops)) + error ("invalid argument to built-in function"); + + return target; +} + +/* Function to expand builtin function for + '[(set (reg) (unspec_volatile [(imm)]))]'. */ +static rtx +nds32_expand_builtin_reg_ftype_imm (enum insn_code icode, + tree exp, rtx target) +{ + /* Mapping: + ops[0] <--> target <--> exp + ops[1] <--> value0 <--> arg0 */ + struct expand_operand ops[2]; + tree arg0; + rtx value0; + + /* Grab the incoming arguments and extract its rtx. */ + arg0 = CALL_EXPR_ARG (exp, 0); + value0 = expand_normal (arg0); + + /* Create operands. */ + create_output_operand (&ops[0], target, TYPE_MODE (TREE_TYPE (exp))); + create_input_operand (&ops[1], value0, TYPE_MODE (TREE_TYPE (arg0))); + + /* Emit new instruction. */ + if (!maybe_expand_insn (icode, 2, ops)) + error ("invalid argument to built-in function"); + + return target; +} + +/* Function to expand builtin function for + '[(unspec_volatile [(reg) (imm)])]' pattern. */ +static rtx +nds32_expand_builtin_null_ftype_reg_imm (enum insn_code icode, + tree exp, rtx target) +{ + /* Mapping: + ops[0] <--> value0 <--> arg0 + ops[1] <--> value1 <--> arg1 */ + struct expand_operand ops[2]; + tree arg0, arg1; + rtx value0, value1; + + /* Grab the incoming arguments and extract its rtx. */ + arg0 = CALL_EXPR_ARG (exp, 0); + arg1 = CALL_EXPR_ARG (exp, 1); + value0 = expand_normal (arg0); + value1 = expand_normal (arg1); + + /* Create operands. */ + create_input_operand (&ops[0], value0, TYPE_MODE (TREE_TYPE (arg0))); + create_input_operand (&ops[1], value1, TYPE_MODE (TREE_TYPE (arg1))); + + /* Emit new instruction. */ + if (!maybe_expand_insn (icode, 2, ops)) + error ("invalid argument to built-in function"); + + return target; +} + +/* A helper function to return character based on byte size. */ +static char +nds32_byte_to_size (int byte) +{ + switch (byte) + { + case 4: + return 'w'; + case 2: + return 'h'; + case 1: + return 'b'; + default: + /* Normally it should not be here. */ + gcc_unreachable (); + } +} + +/* A helper function to check if this function should contain prologue. */ +static int +nds32_have_prologue_p (void) +{ + int i; + + for (i = 0; i < 28; i++) + if (NDS32_REQUIRED_CALLEE_SAVED_P (i)) + return 1; + + return (flag_pic + || NDS32_REQUIRED_CALLEE_SAVED_P (FP_REGNUM) + || NDS32_REQUIRED_CALLEE_SAVED_P (LP_REGNUM)); +} + +/* ------------------------------------------------------------------------ */ + +/* PART 3: Implement target hook stuff definitions. */ + +/* Register Classes. */ + +static unsigned char +nds32_class_max_nregs (reg_class_t rclass ATTRIBUTE_UNUSED, + enum machine_mode mode) +{ + /* Return the maximum number of consecutive registers + needed to represent "mode" in a register of "rclass". */ + return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD); +} + +static int +nds32_register_priority (int hard_regno) +{ + /* Encourage to use r0-r7 for LRA when optimize for size. */ + if (optimize_size && hard_regno < 8) + return 4; + return 3; +} + + +/* Stack Layout and Calling Conventions. */ + +/* There are three kinds of pointer concepts using in GCC compiler: + + frame pointer: A pointer to the first location of local variables. + stack pointer: A pointer to the top of a stack frame. + argument pointer: A pointer to the incoming arguments. + + In nds32 target calling convention, we are using 8-byte alignment. + Besides, we would like to have each stack frame of a function includes: + + [Block A] + 1. previous hard frame pointer + 2. return address + 3. callee-saved registers + 4. <padding bytes> (we will calculte in nds32_compute_stack_frame() + and save it at + cfun->machine->callee_saved_area_padding_bytes) + + [Block B] + 1. local variables + 2. spilling location + 3. <padding bytes> (it will be calculated by GCC itself) + 4. incoming arguments + 5. <padding bytes> (it will be calculated by GCC itself) + + [Block C] + 1. <padding bytes> (it will be calculated by GCC itself) + 2. outgoing arguments + + We 'wrap' these blocks together with + hard frame pointer ($r28) and stack pointer ($r31). + By applying the basic frame/stack/argument pointers concept, + the layout of a stack frame shoule be like this: + + | | + old stack pointer -> ---- + | | \ + | | saved arguments for + | | vararg functions + | | / + hard frame pointer -> -- + & argument pointer | | \ + | | previous hardware frame pointer + | | return address + | | callee-saved registers + | | / + frame pointer -> -- + | | \ + | | local variables + | | and incoming arguments + | | / + -- + | | \ + | | outgoing + | | arguments + | | / + stack pointer -> ---- + + $SFP and $AP are used to represent frame pointer and arguments pointer, + which will be both eliminated as hard frame pointer. */ + +/* -- Eliminating Frame Pointer and Arg Pointer. */ + +static bool nds32_can_eliminate (const int from_reg, const int to_reg) +{ + if (from_reg == ARG_POINTER_REGNUM && to_reg == STACK_POINTER_REGNUM) + return true; + + if (from_reg == ARG_POINTER_REGNUM && to_reg == HARD_FRAME_POINTER_REGNUM) + return true; + + if (from_reg == FRAME_POINTER_REGNUM && to_reg == STACK_POINTER_REGNUM) + return true; + + if (from_reg == FRAME_POINTER_REGNUM && to_reg == HARD_FRAME_POINTER_REGNUM) + return true; + + return false; +} + +/* -- Passing Arguments in Registers. */ + +static rtx +nds32_function_arg (cumulative_args_t ca, enum machine_mode mode, + const_tree type, bool named) +{ + CUMULATIVE_ARGS *cum = get_cumulative_args (ca); + + /* The last time this hook is called, + it is called with MODE == VOIDmode. */ + if (mode == VOIDmode) + return NULL_RTX; + + /* For nameless arguments, they are passed on the stack. */ + if (!named) + return NULL_RTX; + + /* If there are still registers available, return it. */ + if (NDS32_ARG_PASS_IN_REG_P (cum->reg_offset, mode, type)) + { + /* Pick up the next available register number. */ + return gen_rtx_REG (mode, + NDS32_AVAILABLE_REGNUM_FOR_ARG (cum->reg_offset, + mode, + type)); + } + else + { + /* No register available, return NULL_RTX. + The compiler will use stack to pass argument instead. */ + return NULL_RTX; + } +} + +static void +nds32_function_arg_advance (cumulative_args_t ca, enum machine_mode mode, + const_tree type, bool named) +{ + CUMULATIVE_ARGS *cum = get_cumulative_args (ca); + + /* Advance next register for use. + Only named argument could be advanced. */ + if (named) + { + cum->reg_offset + = NDS32_AVAILABLE_REGNUM_FOR_ARG (cum->reg_offset, mode, type) + - NDS32_GPR_ARG_FIRST_REGNUM + + NDS32_NEED_N_REGS_FOR_ARG (mode, type); + } +} + +static unsigned int +nds32_function_arg_boundary (enum machine_mode mode, const_tree type) +{ + return (nds32_needs_double_word_align (mode, type) + ? NDS32_DOUBLE_WORD_ALIGNMENT + : PARM_BOUNDARY); +} + +/* -- How Scalar Function Values Are Returned. */ + +static rtx +nds32_function_value (const_tree ret_type, + const_tree fn_decl_or_type ATTRIBUTE_UNUSED, + bool outgoing ATTRIBUTE_UNUSED) +{ + enum machine_mode mode; + int unsignedp; + + mode = TYPE_MODE (ret_type); + unsignedp = TYPE_UNSIGNED (ret_type); + + mode = promote_mode (ret_type, mode, &unsignedp); + + return gen_rtx_REG (mode, NDS32_GPR_RET_FIRST_REGNUM); +} + +static rtx +nds32_libcall_value (enum machine_mode mode, + const_rtx fun ATTRIBUTE_UNUSED) +{ + return gen_rtx_REG (mode, NDS32_GPR_RET_FIRST_REGNUM); +} + +static bool +nds32_function_value_regno_p (const unsigned int regno) +{ + return (regno == NDS32_GPR_RET_FIRST_REGNUM); +} + +/* -- Function Entry and Exit. */ + +/* The content produced from this function + will be placed before prologue body. */ +static void +nds32_asm_function_prologue (FILE *file, + HOST_WIDE_INT size ATTRIBUTE_UNUSED) +{ + int r; + const char *func_name; + tree attrs; + tree name; + + /* All stack frame information is supposed to be + already computed when expanding prologue. + The result is in cfun->machine. + DO NOT call nds32_compute_stack_frame() here + because it may corrupt the essential information. */ + + fprintf (file, "\t! BEGIN PROLOGUE\n"); + fprintf (file, "\t! fp needed: %d\n", frame_pointer_needed); + fprintf (file, "\t! pretend_args: %d\n", cfun->machine->va_args_size); + fprintf (file, "\t! local_size: %d\n", cfun->machine->local_size); + fprintf (file, "\t! out_args_size: %d\n", cfun->machine->out_args_size); + + /* Use df_regs_ever_live_p() to detect if the register + is ever used in the current function. */ + fprintf (file, "\t! registers ever_live: "); + for (r = 0; r < 32; r++) + { + if (df_regs_ever_live_p (r)) + fprintf (file, "%s, ", reg_names[r]); + } + fputc ('\n', file); + + /* Display the attributes of this function. */ + fprintf (file, "\t! function attributes: "); + /* GCC build attributes list with reverse order, + so we use nreverse() to make it looks like + the order that user specifies. */ + attrs = nreverse (DECL_ATTRIBUTES (current_function_decl)); + + /* If there is no any attribute, print out "None". */ + if (!attrs) + fprintf (file, "None"); + + /* If there are some attributes, try if we need to + construct isr vector information. */ + func_name = IDENTIFIER_POINTER (DECL_NAME (current_function_decl)); + nds32_construct_isr_vectors_information (attrs, func_name); + + /* Display all attributes of this function. */ + while (attrs) + { + name = TREE_PURPOSE (attrs); + fprintf (file, "%s ", IDENTIFIER_POINTER (name)); + + /* Pick up the next attribute. */ + attrs = TREE_CHAIN (attrs); + } + fputc ('\n', file); +} + +/* After rtl prologue has been expanded, this function is used. */ +static void +nds32_asm_function_end_prologue (FILE *file) +{ + fprintf (file, "\t! END PROLOGUE\n"); + + /* If frame pointer is NOT needed and -mfp-as-gp is issued, + we can generate special directive: ".omit_fp_begin" + to guide linker doing fp-as-gp optimization. + However, for a naked function, which means + it should not have prologue/epilogue, + using fp-as-gp still requires saving $fp by push/pop behavior and + there is no benefit to use fp-as-gp on such small function. + So we need to make sure this function is NOT naked as well. */ + if (!frame_pointer_needed + && !cfun->machine->naked_p + && cfun->machine->fp_as_gp_p) + { + fprintf (file, "\t! ----------------------------------------\n"); + fprintf (file, "\t! Guide linker to do " + "link time optimization: fp-as-gp\n"); + fprintf (file, "\t! We add one more instruction to " + "initialize $fp near to $gp location.\n"); + fprintf (file, "\t! If linker fails to use fp-as-gp transformation,\n"); + fprintf (file, "\t! this extra instruction should be " + "eliminated at link stage.\n"); + fprintf (file, "\t.omit_fp_begin\n"); + fprintf (file, "\tla\t$fp,_FP_BASE_\n"); + fprintf (file, "\t! ----------------------------------------\n"); + } +} + +/* Before rtl epilogue has been expanded, this function is used. */ +static void +nds32_asm_function_begin_epilogue (FILE *file) +{ + /* If frame pointer is NOT needed and -mfp-as-gp is issued, + we can generate special directive: ".omit_fp_end" + to claim fp-as-gp optimization range. + However, for a naked function, + which means it should not have prologue/epilogue, + using fp-as-gp still requires saving $fp by push/pop behavior and + there is no benefit to use fp-as-gp on such small function. + So we need to make sure this function is NOT naked as well. */ + if (!frame_pointer_needed + && !cfun->machine->naked_p + && cfun->machine->fp_as_gp_p) + { + fprintf (file, "\t! ----------------------------------------\n"); + fprintf (file, "\t! Claim the range of fp-as-gp " + "link time optimization\n"); + fprintf (file, "\t.omit_fp_end\n"); + fprintf (file, "\t! ----------------------------------------\n"); + } + + fprintf (file, "\t! BEGIN EPILOGUE\n"); +} + +/* The content produced from this function + will be placed after epilogue body. */ +static void +nds32_asm_function_epilogue (FILE *file, + HOST_WIDE_INT size ATTRIBUTE_UNUSED) +{ + fprintf (file, "\t! END EPILOGUE\n"); +} + +static void +nds32_asm_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED, + HOST_WIDE_INT delta, + HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED, + tree function) +{ + int this_regno; + + /* Make sure unwind info is emitted for the thunk if needed. */ + final_start_function (emit_barrier (), file, 1); + + this_regno = (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function) + ? 1 + : 0); + + if (delta != 0) + { + if (satisfies_constraint_Is15 (GEN_INT (delta))) + { + fprintf (file, "\taddi\t$r%d, $r%d, %ld\n", + this_regno, this_regno, delta); + } + else if (satisfies_constraint_Is20 (GEN_INT (delta))) + { + fprintf (file, "\tmovi\t$ta, %ld\n", delta); + fprintf (file, "\tadd\t$r%d, $r%d, $ta\n", this_regno, this_regno); + } + else + { + fprintf (file, "\tsethi\t$ta, hi20(%ld)\n", delta); + fprintf (file, "\tori\t$ta, $ta, lo12(%ld)\n", delta); + fprintf (file, "\tadd\t$r%d, $r%d, $ta\n", this_regno, this_regno); + } + } + + fprintf (file, "\tb\t"); + assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0)); + fprintf (file, "\n"); + + final_end_function (); +} + +/* -- Permitting tail calls. */ + +/* Determine whether we need to enable warning for function return check. */ +static bool +nds32_warn_func_return (tree decl) +{ +/* Naked functions are implemented entirely in assembly, including the + return sequence, so suppress warnings about this. */ + return !nds32_naked_function_p (decl); +} + + +/* Implementing the Varargs Macros. */ + +static bool +nds32_strict_argument_naming (cumulative_args_t ca ATTRIBUTE_UNUSED) +{ + /* Return true so that all the named arguments for FUNCTION_ARG have named=1. + If return false, for the variadic function, all named arguments EXCEPT + the last are treated as named. */ + return true; +} + + +/* Trampolines for Nested Functions. */ + +static void +nds32_asm_trampoline_template (FILE *f) +{ + if (TARGET_REDUCED_REGS) + { + /* Trampoline is not supported on reduced-set registers yet. */ + sorry ("a nested function is not supported for reduced registers"); + } + else + { + asm_fprintf (f, "\t! Trampoline code template\n"); + asm_fprintf (f, "\t! This code fragment will be copied " + "into stack on demand\n"); + + asm_fprintf (f, "\tmfusr\t$r16,$pc\n"); + asm_fprintf (f, "\tlwi\t$r15,[$r16 + 20] " + "! load nested function address\n"); + asm_fprintf (f, "\tlwi\t$r16,[$r16 + 16] " + "! load chain_value\n"); + asm_fprintf (f, "\tjr\t$r15\n"); + } + + /* Preserve space ($pc + 16) for saving chain_value, + nds32_trampoline_init will fill the value in this slot. */ + asm_fprintf (f, "\t! space for saving chain_value\n"); + assemble_aligned_integer (UNITS_PER_WORD, const0_rtx); + + /* Preserve space ($pc + 20) for saving nested function address, + nds32_trampoline_init will fill the value in this slot. */ + asm_fprintf (f, "\t! space for saving nested function address\n"); + assemble_aligned_integer (UNITS_PER_WORD, const0_rtx); +} + +/* Emit RTL insns to initialize the variable parts of a trampoline. */ +static void +nds32_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value) +{ + int i; + + /* Nested function address. */ + rtx fnaddr; + /* The memory rtx that is going to + be filled with chain_value. */ + rtx chain_value_mem; + /* The memory rtx that is going to + be filled with nested function address. */ + rtx nested_func_mem; + + /* Start address of trampoline code in stack, for doing cache sync. */ + rtx sync_cache_addr; + /* Temporary register for sync instruction. */ + rtx tmp_reg; + /* Instruction-cache sync instruction, + requesting an argument as starting address. */ + rtx isync_insn; + /* For convenience reason of doing comparison. */ + int tramp_align_in_bytes; + + /* Trampoline is not supported on reduced-set registers yet. */ + if (TARGET_REDUCED_REGS) + sorry ("a nested function is not supported for reduced registers"); + + /* STEP 1: Copy trampoline code template into stack, + fill up essential data into stack. */ + + /* Extract nested function address rtx. */ + fnaddr = XEXP (DECL_RTL (fndecl), 0); + + /* m_tramp is memory rtx that is going to be filled with trampoline code. + We have nds32_asm_trampoline_template() to emit template pattern. */ + emit_block_move (m_tramp, assemble_trampoline_template (), + GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL); + + /* After copying trampoline code into stack, + fill chain_value into stack. */ + chain_value_mem = adjust_address (m_tramp, SImode, 16); + emit_move_insn (chain_value_mem, chain_value); + /* After copying trampoline code int stack, + fill nested function address into stack. */ + nested_func_mem = adjust_address (m_tramp, SImode, 20); + emit_move_insn (nested_func_mem, fnaddr); + + /* STEP 2: Sync instruction-cache. */ + + /* We have successfully filled trampoline code into stack. + However, in order to execute code in stack correctly, + we must sync instruction cache. */ + sync_cache_addr = XEXP (m_tramp, 0); + tmp_reg = gen_reg_rtx (SImode); + isync_insn = gen_unspec_volatile_isync (tmp_reg); + + /* Because nds32_cache_block_size is in bytes, + we get trampoline alignment in bytes for convenient comparison. */ + tramp_align_in_bytes = TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT; + + if (tramp_align_in_bytes >= nds32_cache_block_size + && (tramp_align_in_bytes % nds32_cache_block_size) == 0) + { + /* Under this condition, the starting address of trampoline + must be aligned to the starting address of each cache block + and we do not have to worry about cross-boundary issue. */ + for (i = 0; + i < (TRAMPOLINE_SIZE + nds32_cache_block_size - 1) + / nds32_cache_block_size; + i++) + { + emit_move_insn (tmp_reg, + plus_constant (Pmode, sync_cache_addr, + nds32_cache_block_size * i)); + emit_insn (isync_insn); + } + } + else if (TRAMPOLINE_SIZE > nds32_cache_block_size) + { + /* The starting address of trampoline code + may not be aligned to the cache block, + so the trampoline code may be across two cache block. + We need to sync the last element, which is 4-byte size, + of trampoline template. */ + for (i = 0; + i < (TRAMPOLINE_SIZE + nds32_cache_block_size - 1) + / nds32_cache_block_size; + i++) + { + emit_move_insn (tmp_reg, + plus_constant (Pmode, sync_cache_addr, + nds32_cache_block_size * i)); + emit_insn (isync_insn); + } + + /* The last element of trampoline template is 4-byte size. */ + emit_move_insn (tmp_reg, + plus_constant (Pmode, sync_cache_addr, + TRAMPOLINE_SIZE - 4)); + emit_insn (isync_insn); + } + else + { + /* This is the simplest case. + Because TRAMPOLINE_SIZE is less than or + equal to nds32_cache_block_size, + we can just sync start address and + the last element of trampoline code. */ + + /* Sync starting address of tampoline code. */ + emit_move_insn (tmp_reg, sync_cache_addr); + emit_insn (isync_insn); + /* Sync the last element, which is 4-byte size, + of trampoline template. */ + emit_move_insn (tmp_reg, + plus_constant (Pmode, sync_cache_addr, + TRAMPOLINE_SIZE - 4)); + emit_insn (isync_insn); + } + + /* Set instruction serialization barrier + to guarantee the correct operations. */ + emit_insn (gen_unspec_volatile_isb ()); +} + + +/* Addressing Modes. */ + +static bool +nds32_legitimate_address_p (enum machine_mode mode, rtx x, bool strict) +{ + /* For (mem:DI addr) or (mem:DF addr) case, + we only allow 'addr' to be [reg], [symbol_ref], + [const], or [reg + const_int] pattern. */ + if (mode == DImode || mode == DFmode) + { + /* Allow [Reg + const_int] addressing mode. */ + if (GET_CODE (x) == PLUS) + { + if (nds32_address_register_rtx_p (XEXP (x, 0), strict) + && nds32_legitimate_index_p (mode, XEXP (x, 1), strict) + && CONST_INT_P (XEXP (x, 1))) + return true; + + else if (nds32_address_register_rtx_p (XEXP (x, 1), strict) + && nds32_legitimate_index_p (mode, XEXP (x, 0), strict) + && CONST_INT_P (XEXP (x, 0))) + return true; + } + + /* Now check [reg], [symbol_ref], and [const]. */ + if (GET_CODE (x) != REG + && GET_CODE (x) != SYMBOL_REF + && GET_CODE (x) != CONST) + return false; + } + + /* Check if 'x' is a valid address. */ + switch (GET_CODE (x)) + { + case REG: + /* (mem (reg A)) => [Ra] */ + return nds32_address_register_rtx_p (x, strict); + + case SYMBOL_REF: + + if (!TARGET_GP_DIRECT + && (reload_completed + || reload_in_progress + || lra_in_progress)) + return false; + + /* (mem (symbol_ref A)) => [symbol_ref] */ + return !currently_expanding_to_rtl; + + case CONST: + + if (!TARGET_GP_DIRECT + && (reload_completed + || reload_in_progress + || lra_in_progress)) + return false; + + /* (mem (const (...))) + => [ + const_addr ], where const_addr = symbol_ref + const_int */ + if (GET_CODE (XEXP (x, 0)) == PLUS) + { + rtx plus_op = XEXP (x, 0); + + rtx op0 = XEXP (plus_op, 0); + rtx op1 = XEXP (plus_op, 1); + + if (GET_CODE (op0) == SYMBOL_REF && CONST_INT_P (op1)) + return true; + else + return false; + } + + return false; + + case POST_MODIFY: + /* (mem (post_modify (reg) (plus (reg) (reg)))) + => [Ra], Rb */ + /* (mem (post_modify (reg) (plus (reg) (const_int)))) + => [Ra], const_int */ + if (GET_CODE (XEXP (x, 0)) == REG + && GET_CODE (XEXP (x, 1)) == PLUS) + { + rtx plus_op = XEXP (x, 1); + + rtx op0 = XEXP (plus_op, 0); + rtx op1 = XEXP (plus_op, 1); + + if (nds32_address_register_rtx_p (op0, strict) + && nds32_legitimate_index_p (mode, op1, strict)) + return true; + else + return false; + } + + return false; + + case POST_INC: + case POST_DEC: + /* (mem (post_inc reg)) => [Ra], 1/2/4 */ + /* (mem (post_dec reg)) => [Ra], -1/-2/-4 */ + /* The 1/2/4 or -1/-2/-4 have been displayed in nds32.md. + We only need to deal with register Ra. */ + if (nds32_address_register_rtx_p (XEXP (x, 0), strict)) + return true; + else + return false; + + case PLUS: + /* (mem (plus reg const_int)) + => [Ra + imm] */ + /* (mem (plus reg reg)) + => [Ra + Rb] */ + /* (mem (plus (mult reg const_int) reg)) + => [Ra + Rb << sv] */ + if (nds32_address_register_rtx_p (XEXP (x, 0), strict) + && nds32_legitimate_index_p (mode, XEXP (x, 1), strict)) + return true; + else if (nds32_address_register_rtx_p (XEXP (x, 1), strict) + && nds32_legitimate_index_p (mode, XEXP (x, 0), strict)) + return true; + else + return false; + + case LO_SUM: + if (!TARGET_GP_DIRECT) + return true; + + default: + return false; + } +} + + +/* Describing Relative Costs of Operations. */ + +static int nds32_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED, + reg_class_t from, + reg_class_t to) +{ + if (from == HIGH_REGS || to == HIGH_REGS) + return 6; + + return 2; +} + +static int nds32_memory_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED, + reg_class_t rclass ATTRIBUTE_UNUSED, + bool in ATTRIBUTE_UNUSED) +{ + return 8; +} + +/* This target hook describes the relative costs of RTL expressions. + Return 'true' when all subexpressions of x have been processed. + Return 'false' to sum the costs of sub-rtx, plus cost of this operation. + Refer to gcc/rtlanal.c for more information. */ +static bool +nds32_rtx_costs (rtx x, + int code, + int outer_code, + int opno ATTRIBUTE_UNUSED, + int *total, + bool speed) +{ + /* According to 'speed', goto suitable cost model section. */ + if (speed) + goto performance_cost; + else + goto size_cost; + + +performance_cost: + /* This is section for performance cost model. */ + + /* In gcc/rtl.h, the default value of COSTS_N_INSNS(N) is N*4. + We treat it as 4-cycle cost for each instruction + under performance consideration. */ + switch (code) + { + case SET: + /* For 'SET' rtx, we need to return false + so that it can recursively calculate costs. */ + return false; + + case USE: + /* Used in combine.c as a marker. */ + *total = 0; + break; + + case MULT: + *total = COSTS_N_INSNS (5); + break; + + case DIV: + case UDIV: + case MOD: + case UMOD: + *total = COSTS_N_INSNS (7); + break; + + default: + *total = COSTS_N_INSNS (1); + break; + } + + return true; + + +size_cost: + /* This is section for size cost model. */ + + /* In gcc/rtl.h, the default value of COSTS_N_INSNS(N) is N*4. + We treat it as 4-byte cost for each instruction + under code size consideration. */ + switch (code) + { + case SET: + /* For 'SET' rtx, we need to return false + so that it can recursively calculate costs. */ + return false; + + case USE: + /* Used in combine.c as a marker. */ + *total = 0; + break; + + case CONST_INT: + /* All instructions involving constant operation + need to be considered for cost evaluation. */ + if (outer_code == SET) + { + /* (set X imm5s), use movi55, 2-byte cost. + (set X imm20s), use movi, 4-byte cost. + (set X BIG_INT), use sethi/ori, 8-byte cost. */ + if (satisfies_constraint_Is05 (x)) + *total = COSTS_N_INSNS (1) - 2; + else if (satisfies_constraint_Is20 (x)) + *total = COSTS_N_INSNS (1); + else + *total = COSTS_N_INSNS (2); + } + else if (outer_code == PLUS || outer_code == MINUS) + { + /* Possible addi333/subi333 or subi45/addi45, 2-byte cost. + General case, cost 1 instruction with 4-byte. */ + if (satisfies_constraint_Iu05 (x)) + *total = COSTS_N_INSNS (1) - 2; + else + *total = COSTS_N_INSNS (1); + } + else if (outer_code == ASHIFT) + { + /* Possible slli333, 2-byte cost. + General case, cost 1 instruction with 4-byte. */ + if (satisfies_constraint_Iu03 (x)) + *total = COSTS_N_INSNS (1) - 2; + else + *total = COSTS_N_INSNS (1); + } + else if (outer_code == ASHIFTRT || outer_code == LSHIFTRT) + { + /* Possible srai45 or srli45, 2-byte cost. + General case, cost 1 instruction with 4-byte. */ + if (satisfies_constraint_Iu05 (x)) + *total = COSTS_N_INSNS (1) - 2; + else + *total = COSTS_N_INSNS (1); + } + else + { + /* For other cases, simply set it 4-byte cost. */ + *total = COSTS_N_INSNS (1); + } + break; + + case CONST_DOUBLE: + /* It requires high part and low part processing, set it 8-byte cost. */ + *total = COSTS_N_INSNS (2); + break; + + default: + /* For other cases, generally we set it 4-byte cost + and stop resurively traversing. */ + *total = COSTS_N_INSNS (1); + break; + } + + return true; +} + +static int nds32_address_cost (rtx address, + enum machine_mode mode ATTRIBUTE_UNUSED, + addr_space_t as ATTRIBUTE_UNUSED, + bool speed) +{ + rtx plus0, plus1; + enum rtx_code code; + + code = GET_CODE (address); + + /* According to 'speed', goto suitable cost model section. */ + if (speed) + goto performance_cost; + else + goto size_cost; + +performance_cost: + /* This is section for performance cost model. */ + + /* FALLTHRU, currently we use same cost model as size_cost. */ + +size_cost: + /* This is section for size cost model. */ + + switch (code) + { + case POST_MODIFY: + case POST_INC: + case POST_DEC: + /* We encourage that rtx contains + POST_MODIFY/POST_INC/POST_DEC behavior. */ + return 0; + + case SYMBOL_REF: + /* We can have gp-relative load/store for symbol_ref. + Have it 4-byte cost. */ + return COSTS_N_INSNS (1); + + case CONST: + /* It is supposed to be the pattern (const (plus symbol_ref const_int)). + Have it 4-byte cost. */ + return COSTS_N_INSNS (1); + + case REG: + /* Simply return 4-byte costs. */ + return COSTS_N_INSNS (1); + + case PLUS: + /* We do not need to check if the address is a legitimate address, + because this hook is never called with an invalid address. + But we better check the range of + const_int value for cost, if it exists. */ + plus0 = XEXP (address, 0); + plus1 = XEXP (address, 1); + + if (REG_P (plus0) && CONST_INT_P (plus1)) + { + /* If it is possible to be lwi333/swi333 form, + make it 2-byte cost. */ + if (satisfies_constraint_Iu05 (plus1)) + return (COSTS_N_INSNS (1) - 2); + else + return COSTS_N_INSNS (1); + } + + /* For other 'plus' situation, make it cost 4-byte. */ + return COSTS_N_INSNS (1); + + default: + break; + } + + return COSTS_N_INSNS (4); +} + + +/* Defining the Output Assembler Language. */ + +/* -- The Overall Framework of an Assembler File. */ + +static void +nds32_asm_file_start (void) +{ + int i; + + default_file_start (); + + /* Tell assembler which ABI we are using. */ + fprintf (asm_out_file, "\t! ABI version\n"); + fprintf (asm_out_file, "\t.abi_2\n"); + + /* Tell assembler that this asm code is generated by compiler. */ + fprintf (asm_out_file, "\t! This asm file is generated by compiler\n"); + fprintf (asm_out_file, "\t.flag\tverbatim\n"); + /* Give assembler the size of each vector for interrupt handler. */ + fprintf (asm_out_file, "\t! This vector size directive is required " + "for checking inconsistency on interrupt handler\n"); + fprintf (asm_out_file, "\t.vec_size\t%d\n", nds32_isr_vector_size); + + /* If user enables '-mforce-fp-as-gp' or compiles programs with -Os, + the compiler may produce 'la $fp,_FP_BASE_' instruction + at prologue for fp-as-gp optimization. + We should emit weak reference of _FP_BASE_ to avoid undefined reference + in case user does not pass '--relax' option to linker. */ + if (TARGET_FORCE_FP_AS_GP || optimize_size) + { + fprintf (asm_out_file, "\t! This weak reference is required to do " + "fp-as-gp link time optimization\n"); + fprintf (asm_out_file, "\t.weak\t_FP_BASE_\n"); + } + /* If user enables '-mex9', we should emit relaxation directive + to tell linker that this file is allowed to do ex9 optimization. */ + if (TARGET_EX9) + { + fprintf (asm_out_file, "\t! This relaxation directive is required " + "to do ex9 link time optimization\n"); + fprintf (asm_out_file, "\t.relax\tex9\n"); + } + + fprintf (asm_out_file, "\t! ------------------------------------\n"); + + if (TARGET_ISA_V2) + fprintf (asm_out_file, "\t! ISA family\t\t: %s\n", "V2"); + if (TARGET_ISA_V3) + fprintf (asm_out_file, "\t! ISA family\t\t: %s\n", "V3"); + if (TARGET_ISA_V3M) + fprintf (asm_out_file, "\t! ISA family\t\t: %s\n", "V3M"); + + fprintf (asm_out_file, "\t! Endian setting\t: %s\n", + ((TARGET_BIG_ENDIAN) ? "big-endian" + : "little-endian")); + + fprintf (asm_out_file, "\t! ------------------------------------\n"); + + fprintf (asm_out_file, "\t! Use conditional move\t\t: %s\n", + ((TARGET_CMOV) ? "Yes" + : "No")); + fprintf (asm_out_file, "\t! Use performance extension\t: %s\n", + ((TARGET_PERF_EXT) ? "Yes" + : "No")); + + fprintf (asm_out_file, "\t! ------------------------------------\n"); + + fprintf (asm_out_file, "\t! V3PUSH instructions\t: %s\n", + ((TARGET_V3PUSH) ? "Yes" + : "No")); + fprintf (asm_out_file, "\t! 16-bit instructions\t: %s\n", + ((TARGET_16_BIT) ? "Yes" + : "No")); + fprintf (asm_out_file, "\t! GP base access\t: %s\n", + ((TARGET_GP_DIRECT) ? "Yes" + : "No")); + fprintf (asm_out_file, "\t! Reduced registers set\t: %s\n", + ((TARGET_REDUCED_REGS) ? "Yes" + : "No")); + + fprintf (asm_out_file, "\t! ------------------------------------\n"); + + if (optimize_size) + fprintf (asm_out_file, "\t! Optimization level\t: -Os\n"); + else + fprintf (asm_out_file, "\t! Optimization level\t: -O%d\n", optimize); + + fprintf (asm_out_file, "\t! ------------------------------------\n"); + + fprintf (asm_out_file, "\t! Cache block size\t: %d\n", + nds32_cache_block_size); + + fprintf (asm_out_file, "\t! ------------------------------------\n"); + + /* Initialize isr vector information array before compiling functions. */ + for (i = 0; i < NDS32_N_ISR_VECTORS; i++) + { + nds32_isr_vectors[i].category = NDS32_ISR_NONE; + strcpy (nds32_isr_vectors[i].func_name, ""); + nds32_isr_vectors[i].save_reg = NDS32_PARTIAL_SAVE; + nds32_isr_vectors[i].nested_type = NDS32_NOT_NESTED; + nds32_isr_vectors[i].total_n_vectors = 0; + strcpy (nds32_isr_vectors[i].nmi_name, ""); + strcpy (nds32_isr_vectors[i].warm_name, ""); + } +} + +static void +nds32_asm_file_end (void) +{ + int i; + + /* If all the vectors are NDS32_ISR_NONE, we can return immediately. */ + for (i = 0; i < NDS32_N_ISR_VECTORS; i++) + if (nds32_isr_vectors[i].category != NDS32_ISR_NONE) + break; + + if (i == NDS32_N_ISR_VECTORS) + return; + + /* At least one vector is NOT NDS32_ISR_NONE, + we should output isr vector information. */ + fprintf (asm_out_file, "\t! ------------------------------------\n"); + fprintf (asm_out_file, "\t! The isr vector information:\n"); + fprintf (asm_out_file, "\t! ------------------------------------\n"); + + /* Check reset handler first. Its vector number is always 0. */ + if (nds32_isr_vectors[0].category == NDS32_ISR_RESET) + { + nds32_emit_isr_reset_content (); + fprintf (asm_out_file, "\t! ------------------------------------\n"); + } + + /* Check other vectors, starting from vector number 1. */ + for (i = 1; i < NDS32_N_ISR_VECTORS; i++) + { + if (nds32_isr_vectors[i].category == NDS32_ISR_INTERRUPT + || nds32_isr_vectors[i].category == NDS32_ISR_EXCEPTION) + { + /* Found one vector which is interupt or exception. + Output its jmptbl and vector section content. */ + fprintf (asm_out_file, "\t! interrupt/exception vector %02d\n", i); + fprintf (asm_out_file, "\t! ------------------------------------\n"); + nds32_emit_isr_jmptbl_section (i); + fprintf (asm_out_file, "\t! ....................................\n"); + nds32_emit_isr_vector_section (i); + fprintf (asm_out_file, "\t! ------------------------------------\n"); + } + } + + fprintf (asm_out_file, "\t! ------------------------------------\n"); +} + +/* -- Output and Generation of Labels. */ + +static void +nds32_asm_globalize_label (FILE *stream, const char *name) +{ + fputs ("\t.global\t", stream); + assemble_name (stream, name); + fputs ("\n", stream); +} + +/* -- Output of Assembler Instructions. */ + +static void +nds32_print_operand (FILE *stream, rtx x, int code) +{ + int op_value; + + switch (code) + { + case 0 : + /* Do nothing special. */ + break; + + case 'V': + /* 'x' is supposed to be CONST_INT, get the value. */ + gcc_assert (CONST_INT_P (x)); + op_value = INTVAL (x); + + /* According to the Andes architecture, + the system/user register index range is 0 ~ 1023. + In order to avoid conflict between user-specified-integer value + and enum-specified-register value, + the 'enum nds32_intrinsic_registers' value + in nds32_intrinsic.h starts from 1024. */ + if (op_value < 1024 && op_value >= 0) + { + /* If user gives integer value directly (0~1023), + we just print out the value. */ + fprintf (stream, "%d", op_value); + } + else if (op_value < 0 + || op_value >= ((int) ARRAY_SIZE (nds32_intrinsic_register_names) + + 1024)) + { + /* The enum index value for array size is out of range. */ + error ("intrinsic register index is out of range"); + } + else + { + /* If user applies normal way with __NDS32_REG_XXX__ enum data, + we can print out register name. Remember to substract 1024. */ + fprintf (stream, "%s", + nds32_intrinsic_register_names[op_value - 1024]); + } + + /* No need to handle following process, so return immediately. */ + return; + + default : + /* Unknown flag. */ + output_operand_lossage ("invalid operand output code"); + break; + } + + switch (GET_CODE (x)) + { + case LABEL_REF: + case SYMBOL_REF: + output_addr_const (stream, x); + break; + + case REG: + /* Forbid using static chain register ($r16) + on reduced-set registers configuration. */ + if (TARGET_REDUCED_REGS + && REGNO (x) == STATIC_CHAIN_REGNUM) + sorry ("a nested function is not supported for reduced registers"); + + /* Normal cases, print out register name. */ + fputs (reg_names[REGNO (x)], stream); + break; + + case MEM: + output_address (XEXP (x, 0)); + break; + + case CODE_LABEL: + case CONST_INT: + case CONST: + output_addr_const (stream, x); + break; + + default: + /* Generally, output_addr_const () is able to handle most cases. + We want to see what CODE could appear, + so we use gcc_unreachable() to stop it. */ + debug_rtx (x); + gcc_unreachable (); + break; + } +} + +static void +nds32_print_operand_address (FILE *stream, rtx x) +{ + rtx op0, op1; + + switch (GET_CODE (x)) + { + case SYMBOL_REF: + case CONST: + /* [ + symbol_ref] */ + /* [ + const_addr], where const_addr = symbol_ref + const_int */ + fputs ("[ + ", stream); + output_addr_const (stream, x); + fputs ("]", stream); + break; + + case REG: + /* Forbid using static chain register ($r16) + on reduced-set registers configuration. */ + if (TARGET_REDUCED_REGS + && REGNO (x) == STATIC_CHAIN_REGNUM) + sorry ("a nested function is not supported for reduced registers"); + + /* [Ra] */ + fprintf (stream, "[%s]", reg_names[REGNO (x)]); + break; + + case PLUS: + op0 = XEXP (x, 0); + op1 = XEXP (x, 1); + + /* Checking op0, forbid using static chain register ($r16) + on reduced-set registers configuration. */ + if (TARGET_REDUCED_REGS + && REG_P (op0) + && REGNO (op0) == STATIC_CHAIN_REGNUM) + sorry ("a nested function is not supported for reduced registers"); + /* Checking op1, forbid using static chain register ($r16) + on reduced-set registers configuration. */ + if (TARGET_REDUCED_REGS + && REG_P (op1) + && REGNO (op1) == STATIC_CHAIN_REGNUM) + sorry ("a nested function is not supported for reduced registers"); + + if (REG_P (op0) && CONST_INT_P (op1)) + { + /* [Ra + imm] */ + fprintf (stream, "[%s + (%d)]", + reg_names[REGNO (op0)], (int)INTVAL (op1)); + } + else if (REG_P (op0) && REG_P (op1)) + { + /* [Ra + Rb] */ + fprintf (stream, "[%s + %s]", + reg_names[REGNO (op0)], reg_names[REGNO (op1)]); + } + else if (GET_CODE (op0) == MULT && REG_P (op1)) + { + /* [Ra + Rb << sv] + From observation, the pattern looks like: + (plus:SI (mult:SI (reg:SI 58) + (const_int 4 [0x4])) + (reg/f:SI 57)) */ + int sv; + + /* We need to set sv to output shift value. */ + if (INTVAL (XEXP (op0, 1)) == 1) + sv = 0; + else if (INTVAL (XEXP (op0, 1)) == 2) + sv = 1; + else if (INTVAL (XEXP (op0, 1)) == 4) + sv = 2; + else + gcc_unreachable (); + + fprintf (stream, "[%s + %s << %d]", + reg_names[REGNO (op1)], + reg_names[REGNO (XEXP (op0, 0))], + sv); + } + else + { + /* The control flow is not supposed to be here. */ + debug_rtx (x); + gcc_unreachable (); + } + + break; + + case POST_MODIFY: + /* (post_modify (regA) (plus (regA) (regB))) + (post_modify (regA) (plus (regA) (const_int))) + We would like to extract + regA and regB (or const_int) from plus rtx. */ + op0 = XEXP (XEXP (x, 1), 0); + op1 = XEXP (XEXP (x, 1), 1); + + /* Checking op0, forbid using static chain register ($r16) + on reduced-set registers configuration. */ + if (TARGET_REDUCED_REGS + && REG_P (op0) + && REGNO (op0) == STATIC_CHAIN_REGNUM) + sorry ("a nested function is not supported for reduced registers"); + /* Checking op1, forbid using static chain register ($r16) + on reduced-set registers configuration. */ + if (TARGET_REDUCED_REGS + && REG_P (op1) + && REGNO (op1) == STATIC_CHAIN_REGNUM) + sorry ("a nested function is not supported for reduced registers"); + + if (REG_P (op0) && REG_P (op1)) + { + /* [Ra], Rb */ + fprintf (stream, "[%s], %s", + reg_names[REGNO (op0)], reg_names[REGNO (op1)]); + } + else if (REG_P (op0) && CONST_INT_P (op1)) + { + /* [Ra], imm */ + fprintf (stream, "[%s], %d", + reg_names[REGNO (op0)], (int)INTVAL (op1)); + } + else + { + /* The control flow is not supposed to be here. */ + debug_rtx (x); + gcc_unreachable (); + } + + break; + + case POST_INC: + case POST_DEC: + op0 = XEXP (x, 0); + + /* Checking op0, forbid using static chain register ($r16) + on reduced-set registers configuration. */ + if (TARGET_REDUCED_REGS + && REG_P (op0) + && REGNO (op0) == STATIC_CHAIN_REGNUM) + sorry ("a nested function is not supported for reduced registers"); + + if (REG_P (op0)) + { + /* "[Ra], 1/2/4" or "[Ra], -1/-2/-4" + The 1/2/4 or -1/-2/-4 have been displayed in nds32.md. + We only need to deal with register Ra. */ + fprintf (stream, "[%s]", reg_names[REGNO (op0)]); + } + else + { + /* The control flow is not supposed to be here. */ + debug_rtx (x); + gcc_unreachable (); + } + + break; + + default : + /* Generally, output_addr_const () is able to handle most cases. + We want to see what CODE could appear, + so we use gcc_unreachable() to stop it. */ + debug_rtx (x); + gcc_unreachable (); + break; + } +} + + +/* Defining target-specific uses of __attribute__. */ + +/* Add some checking after merging attributes. */ +static tree +nds32_merge_decl_attributes (tree olddecl, tree newdecl) +{ + tree combined_attrs; + + /* Create combined attributes. */ + combined_attrs = merge_attributes (DECL_ATTRIBUTES (olddecl), + DECL_ATTRIBUTES (newdecl)); + + /* Sinc newdecl is acutally a duplicate of olddecl, + we can take olddecl for some operations. */ + if (TREE_CODE (olddecl) == FUNCTION_DECL) + { + /* Check isr-specific attributes conflict. */ + nds32_check_isr_attrs_conflict (olddecl, combined_attrs); + } + + return combined_attrs; +} + +/* Add some checking when inserting attributes. */ +static void +nds32_insert_attributes (tree decl, tree *attributes) +{ + /* For function declaration, we need to check isr-specific attributes: + 1. Call nds32_check_isr_attrs_conflict() to check any conflict. + 2. Check valid integer value for interrupt/exception. + 3. Check valid integer value for reset. + 4. Check valid function for nmi/warm. */ + if (TREE_CODE (decl) == FUNCTION_DECL) + { + tree func_attrs; + tree intr, excp, reset; + + /* Pick up function attributes. */ + func_attrs = *attributes; + + /* 1. Call nds32_check_isr_attrs_conflict() to check any conflict. */ + nds32_check_isr_attrs_conflict (decl, func_attrs); + + /* Now we are starting to check valid id value + for interrupt/exception/reset. + Note that we ONLY check its validity here. + To construct isr vector information, it is still performed + by nds32_construct_isr_vectors_information(). */ + intr = lookup_attribute ("interrupt", func_attrs); + excp = lookup_attribute ("exception", func_attrs); + reset = lookup_attribute ("reset", func_attrs); + + if (intr || excp) + { + /* Deal with interrupt/exception. */ + tree id_list; + unsigned int lower_bound, upper_bound; + + /* The way to handle interrupt or exception is the same, + we just need to take care of actual vector number. + For interrupt(0..63), the actual vector number is (9..72). + For exception(1..8), the actual vector number is (1..8). */ + lower_bound = (intr) ? (0) : (1); + upper_bound = (intr) ? (63) : (8); + + /* Prepare id list so that we can traverse id value. */ + id_list = (intr) ? (TREE_VALUE (intr)) : (TREE_VALUE (excp)); + + /* 2. Check valid integer value for interrupt/exception. */ + while (id_list) + { + tree id; + + /* Pick up each vector id value. */ + id = TREE_VALUE (id_list); + /* Issue error if it is not a valid integer value. */ + if (TREE_CODE (id) != INTEGER_CST + || TREE_INT_CST_LOW (id) < lower_bound + || TREE_INT_CST_LOW (id) > upper_bound) + error ("invalid id value for interrupt/exception attribute"); + + /* Advance to next id. */ + id_list = TREE_CHAIN (id_list); + } + } + else if (reset) + { + /* Deal with reset. */ + tree id_list; + tree id; + tree nmi, warm; + unsigned int lower_bound; + unsigned int upper_bound; + + /* Prepare id_list and identify id value so that + we can check if total number of vectors is valid. */ + id_list = TREE_VALUE (reset); + id = TREE_VALUE (id_list); + + /* The maximum numbers for user's interrupt is 64. */ + lower_bound = 0; + upper_bound = 64; + + /* 3. Check valid integer value for reset. */ + if (TREE_CODE (id) != INTEGER_CST + || TREE_INT_CST_LOW (id) < lower_bound + || TREE_INT_CST_LOW (id) > upper_bound) + error ("invalid id value for reset attribute"); + + /* 4. Check valid function for nmi/warm. */ + nmi = lookup_attribute ("nmi", func_attrs); + warm = lookup_attribute ("warm", func_attrs); + + if (nmi != NULL_TREE) + { + tree nmi_func_list; + tree nmi_func; + + nmi_func_list = TREE_VALUE (nmi); + nmi_func = TREE_VALUE (nmi_func_list); + + /* Issue error if it is not a valid nmi function. */ + if (TREE_CODE (nmi_func) != IDENTIFIER_NODE) + error ("invalid nmi function for reset attribute"); + } + + if (warm != NULL_TREE) + { + tree warm_func_list; + tree warm_func; + + warm_func_list = TREE_VALUE (warm); + warm_func = TREE_VALUE (warm_func_list); + + /* Issue error if it is not a valid warm function. */ + if (TREE_CODE (warm_func) != IDENTIFIER_NODE) + error ("invalid warm function for reset attribute"); + } + } + else + { + /* No interrupt, exception, or reset attribute is set. */ + return; + } + } +} + +static bool +nds32_option_pragma_parse (tree args ATTRIBUTE_UNUSED, + tree pop_target ATTRIBUTE_UNUSED) +{ + /* Currently, we do not parse any pragma target by ourself, + so just simply return false. */ + return false; +} + +static void +nds32_option_override (void) +{ + /* After all the command options have been parsed, + we shall deal with some flags for changing compiler settings. */ + + /* At first, we check if we have to strictly + set some flags based on ISA family. */ + if (TARGET_ISA_V2) + { + /* Under V2 ISA, we need to strictly disable TARGET_V3PUSH. */ + target_flags &= ~MASK_V3PUSH; + } + if (TARGET_ISA_V3) + { + /* Under V3 ISA, currently nothing should be strictly set. */ + } + if (TARGET_ISA_V3M) + { + /* Under V3M ISA, we need to strictly enable TARGET_REDUCED_REGS. */ + target_flags |= MASK_REDUCED_REGS; + /* Under V3M ISA, we need to strictly disable TARGET_PERF_EXT. */ + target_flags &= ~MASK_PERF_EXT; + } + + /* See if we are using reduced-set registers: + $r0~$r5, $r6~$r10, $r15, $r28, $r29, $r30, $r31 + If so, we must forbid using $r11~$r14, $r16~$r27. */ + if (TARGET_REDUCED_REGS) + { + int r; + + /* Prevent register allocator from + choosing it as doing register allocation. */ + for (r = 11; r <= 14; r++) + fixed_regs[r] = call_used_regs[r] = 1; + for (r = 16; r <= 27; r++) + fixed_regs[r] = call_used_regs[r] = 1; + } + + /* See if user explicitly would like to use fp-as-gp optimization. + If so, we must prevent $fp from being allocated + during register allocation. */ + if (TARGET_FORCE_FP_AS_GP) + fixed_regs[FP_REGNUM] = call_used_regs[FP_REGNUM] = 1; + + if (!TARGET_16_BIT) + { + /* Under no 16 bit ISA, we need to strictly disable TARGET_V3PUSH. */ + target_flags &= ~MASK_V3PUSH; + } + + /* Currently, we don't support PIC code generation yet. */ + if (flag_pic) + sorry ("not support -fpic"); +} + + +/* Miscellaneous Parameters. */ + +static void +nds32_init_builtins (void) +{ + tree pointer_type_node = build_pointer_type (integer_type_node); + + tree void_ftype_void = build_function_type (void_type_node, + void_list_node); + + tree void_ftype_pint = build_function_type_list (void_type_node, + pointer_type_node, + NULL_TREE); + + tree int_ftype_int = build_function_type_list (integer_type_node, + integer_type_node, + NULL_TREE); + + tree void_ftype_int_int = build_function_type_list (void_type_node, + integer_type_node, + integer_type_node, + NULL_TREE); + + /* Cache. */ + add_builtin_function ("__builtin_nds32_isync", void_ftype_pint, + NDS32_BUILTIN_ISYNC, + BUILT_IN_MD, NULL, NULL_TREE); + add_builtin_function ("__builtin_nds32_isb", void_ftype_void, + NDS32_BUILTIN_ISB, + BUILT_IN_MD, NULL, NULL_TREE); + + /* Register Transfer. */ + add_builtin_function ("__builtin_nds32_mfsr", int_ftype_int, + NDS32_BUILTIN_MFSR, + BUILT_IN_MD, NULL, NULL_TREE); + add_builtin_function ("__builtin_nds32_mfusr", int_ftype_int, + NDS32_BUILTIN_MFUSR, + BUILT_IN_MD, NULL, NULL_TREE); + add_builtin_function ("__builtin_nds32_mtsr", void_ftype_int_int, + NDS32_BUILTIN_MTSR, + BUILT_IN_MD, NULL, NULL_TREE); + add_builtin_function ("__builtin_nds32_mtusr", void_ftype_int_int, + NDS32_BUILTIN_MTUSR, + BUILT_IN_MD, NULL, NULL_TREE); + + /* Interrupt. */ + add_builtin_function ("__builtin_nds32_setgie_en", void_ftype_void, + NDS32_BUILTIN_SETGIE_EN, + BUILT_IN_MD, NULL, NULL_TREE); + add_builtin_function ("__builtin_nds32_setgie_dis", void_ftype_void, + NDS32_BUILTIN_SETGIE_DIS, + BUILT_IN_MD, NULL, NULL_TREE); +} + +static rtx +nds32_expand_builtin (tree exp, + rtx target, + rtx subtarget ATTRIBUTE_UNUSED, + enum machine_mode mode ATTRIBUTE_UNUSED, + int ignore ATTRIBUTE_UNUSED) +{ + tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); + + int fcode = DECL_FUNCTION_CODE (fndecl); + + switch (fcode) + { + /* Cache. */ + case NDS32_BUILTIN_ISYNC: + return nds32_expand_builtin_null_ftype_reg + (CODE_FOR_unspec_volatile_isync, exp, target); + case NDS32_BUILTIN_ISB: + /* Since there are no result and operands for isb instruciton, + we can simply emit this rtx. */ + emit_insn (gen_unspec_volatile_isb ()); + return target; + + /* Register Transfer. */ + case NDS32_BUILTIN_MFSR: + return nds32_expand_builtin_reg_ftype_imm + (CODE_FOR_unspec_volatile_mfsr, exp, target); + case NDS32_BUILTIN_MFUSR: + return nds32_expand_builtin_reg_ftype_imm + (CODE_FOR_unspec_volatile_mfusr, exp, target); + case NDS32_BUILTIN_MTSR: + return nds32_expand_builtin_null_ftype_reg_imm + (CODE_FOR_unspec_volatile_mtsr, exp, target); + case NDS32_BUILTIN_MTUSR: + return nds32_expand_builtin_null_ftype_reg_imm + (CODE_FOR_unspec_volatile_mtusr, exp, target); + + /* Interrupt. */ + case NDS32_BUILTIN_SETGIE_EN: + /* Since there are no result and operands for setgie.e instruciton, + we can simply emit this rtx. */ + emit_insn (gen_unspec_volatile_setgie_en ()); + return target; + case NDS32_BUILTIN_SETGIE_DIS: + /* Since there are no result and operands for setgie.d instruciton, + we can simply emit this rtx. */ + emit_insn (gen_unspec_volatile_setgie_dis ()); + return target; + + default: + gcc_unreachable (); + } + + return NULL_RTX; +} + + +/* ------------------------------------------------------------------------ */ + +/* PART 4: Implemet extern function definitions, + the prototype is in nds32-protos.h. */ + +/* Defining Data Structures for Per-function Information. */ + +void +nds32_init_expanders (void) +{ + /* Arrange to initialize and mark the machine per-function status. */ + init_machine_status = nds32_init_machine_status; +} + + +/* Register Usage. */ + +/* -- How Values Fit in Registers. */ + +int +nds32_hard_regno_nregs (int regno ATTRIBUTE_UNUSED, + enum machine_mode mode) +{ + return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD); +} + +int +nds32_hard_regno_mode_ok (int regno, enum machine_mode mode) +{ + /* Restrict double-word quantities to even register pairs. */ + if (HARD_REGNO_NREGS (regno, mode) == 1 + || !((regno) & 1)) + return 1; + + return 0; +} + + +/* Register Classes. */ + +enum reg_class +nds32_regno_reg_class (int regno) +{ + /* Refer to nds32.h for more register class details. */ + + if (regno >= 0 && regno <= 7) + return LOW_REGS; + else if (regno >= 8 && regno <= 11) + return MIDDLE_REGS; + else if (regno >= 12 && regno <= 14) + return HIGH_REGS; + else if (regno == 15) + return R15_TA_REG; + else if (regno >= 16 && regno <= 19) + return MIDDLE_REGS; + else if (regno >= 20 && regno <= 31) + return HIGH_REGS; + else if (regno == 32 || regno == 33) + return FRAME_REGS; + else + return NO_REGS; +} + + +/* Stack Layout and Calling Conventions. */ + +/* -- Basic Stack Layout. */ + +rtx +nds32_return_addr_rtx (int count, + rtx frameaddr ATTRIBUTE_UNUSED) +{ + /* There is no way to determine the return address + if frameaddr is the frame that has 'count' steps + up from current frame. */ + if (count != 0) + return NULL_RTX; + + /* If count == 0, it means we are at current frame, + the return address is $r30 ($lp). */ + return get_hard_reg_initial_val (Pmode, LP_REGNUM); +} + +/* -- Eliminating Frame Pointer and Arg Pointer. */ + +HOST_WIDE_INT +nds32_initial_elimination_offset (unsigned int from_reg, unsigned int to_reg) +{ + HOST_WIDE_INT offset; + + /* Compute and setup stack frame size. + The result will be in cfun->machine. */ + nds32_compute_stack_frame (); + + /* Remember to consider + cfun->machine->callee_saved_area_padding_bytes + when calculating offset. */ + if (from_reg == ARG_POINTER_REGNUM && to_reg == STACK_POINTER_REGNUM) + { + offset = (cfun->machine->fp_size + + cfun->machine->gp_size + + cfun->machine->lp_size + + cfun->machine->callee_saved_regs_size + + cfun->machine->callee_saved_area_padding_bytes + + cfun->machine->local_size + + cfun->machine->out_args_size); + } + else if (from_reg == ARG_POINTER_REGNUM + && to_reg == HARD_FRAME_POINTER_REGNUM) + { + offset = 0; + } + else if (from_reg == FRAME_POINTER_REGNUM + && to_reg == STACK_POINTER_REGNUM) + { + offset = (cfun->machine->local_size + cfun->machine->out_args_size); + } + else if (from_reg == FRAME_POINTER_REGNUM + && to_reg == HARD_FRAME_POINTER_REGNUM) + { + offset = (-1) * (cfun->machine->fp_size + + cfun->machine->gp_size + + cfun->machine->lp_size + + cfun->machine->callee_saved_regs_size + + cfun->machine->callee_saved_area_padding_bytes); + } + else + { + gcc_unreachable (); + } + + return offset; +} + +/* -- Passing Arguments in Registers. */ + +void +nds32_init_cumulative_args (CUMULATIVE_ARGS *cum, + tree fntype ATTRIBUTE_UNUSED, + rtx libname ATTRIBUTE_UNUSED, + tree fndecl ATTRIBUTE_UNUSED, + int n_named_args ATTRIBUTE_UNUSED) +{ + /* Initial available registers + (in offset, corresponding to NDS32_GPR_ARG_FIRST_REGNUM) + for passing arguments. */ + cum->reg_offset = 0; +} + +/* -- Function Entry and Exit. */ + +/* Function for normal multiple push prologue. */ +void +nds32_expand_prologue (void) +{ + int fp_adjust; + int sp_adjust; + int en4_const; + + rtx Rb, Re; + rtx push_insn; + rtx fp_adjust_insn, sp_adjust_insn; + + /* Before computing everything for stack frame size, + we check if it is still worth to use fp_as_gp optimization. + If it is, the 'df_regs_ever_live_p (FP_REGNUM)' will be set + so that $fp will be saved on stack. */ + cfun->machine->fp_as_gp_p = nds32_fp_as_gp_check_available (); + + /* Compute and setup stack frame size. + The result will be in cfun->machine. */ + nds32_compute_stack_frame (); + + /* If the function is 'naked', + we do not have to generate prologue code fragment. */ + if (cfun->machine->naked_p) + return; + + /* Get callee_first_regno and callee_last_regno. */ + Rb = gen_rtx_REG (SImode, cfun->machine->callee_saved_regs_first_regno); + Re = gen_rtx_REG (SImode, cfun->machine->callee_saved_regs_last_regno); + + /* push_insn = gen_stack_push_multiple(first_regno, last_regno), + the pattern 'stack_push_multiple' is implemented in nds32.md. + For En4 field, we have to calculate its constant value. + Refer to Andes ISA for more information. */ + en4_const = 0; + if (cfun->machine->fp_size) + en4_const += 8; + if (cfun->machine->gp_size) + en4_const += 4; + if (cfun->machine->lp_size) + en4_const += 2; + + /* If $fp, $gp, $lp, and all callee-save registers are NOT required + to be saved, we don't have to create multiple push instruction. + Otherwise, a multiple push instruction is needed. */ + if (!(REGNO (Rb) == SP_REGNUM && REGNO (Re) == SP_REGNUM && en4_const == 0)) + { + /* Create multiple push instruction rtx. */ + push_insn = nds32_gen_stack_push_multiple (Rb, Re, GEN_INT (en4_const)); + /* Emit rtx into instructions list and receive INSN rtx form. */ + push_insn = emit_insn (push_insn); + + /* The insn rtx 'push_insn' will change frame layout. + We need to use RTX_FRAME_RELATED_P so that GCC is able to + generate CFI (Call Frame Information) stuff. */ + RTX_FRAME_RELATED_P (push_insn) = 1; + } + + /* Check frame_pointer_needed to see + if we shall emit fp adjustment instruction. */ + if (frame_pointer_needed) + { + /* adjust $fp = $sp + ($fp size) + ($gp size) + ($lp size) + + (4 * callee-saved-registers) + Note: No need to adjust + cfun->machine->callee_saved_area_padding_bytes, + because, at this point, stack pointer is just + at the position after push instruction. */ + fp_adjust = cfun->machine->fp_size + + cfun->machine->gp_size + + cfun->machine->lp_size + + cfun->machine->callee_saved_regs_size; + fp_adjust_insn = gen_addsi3 (hard_frame_pointer_rtx, + stack_pointer_rtx, + GEN_INT (fp_adjust)); + /* Emit rtx into instructions list and receive INSN rtx form. */ + fp_adjust_insn = emit_insn (fp_adjust_insn); + } + + /* Adjust $sp = $sp - local_size - out_args_size + - callee_saved_area_padding_bytes. */ + sp_adjust = cfun->machine->local_size + + cfun->machine->out_args_size + + cfun->machine->callee_saved_area_padding_bytes; + /* sp_adjust value may be out of range of the addi instruction, + create alternative add behavior with TA_REGNUM if necessary, + using NEGATIVE value to tell that we are decreasing address. */ + sp_adjust = nds32_force_addi_stack_int ( (-1) * sp_adjust); + if (sp_adjust) + { + /* Generate sp adjustment instruction if and only if sp_adjust != 0. */ + sp_adjust_insn = gen_addsi3 (stack_pointer_rtx, + stack_pointer_rtx, + GEN_INT (-1 * sp_adjust)); + /* Emit rtx into instructions list and receive INSN rtx form. */ + sp_adjust_insn = emit_insn (sp_adjust_insn); + + /* The insn rtx 'sp_adjust_insn' will change frame layout. + We need to use RTX_FRAME_RELATED_P so that GCC is able to + generate CFI (Call Frame Information) stuff. */ + RTX_FRAME_RELATED_P (sp_adjust_insn) = 1; + } + + /* Prevent the instruction scheduler from + moving instructions across the boundary. */ + emit_insn (gen_blockage ()); +} + +/* Function for normal multiple pop epilogue. */ +void +nds32_expand_epilogue (void) +{ + int sp_adjust; + int en4_const; + + rtx Rb, Re; + rtx pop_insn; + rtx sp_adjust_insn; + + /* Compute and setup stack frame size. + The result will be in cfun->machine. */ + nds32_compute_stack_frame (); + + /* Prevent the instruction scheduler from + moving instructions across the boundary. */ + emit_insn (gen_blockage ()); + + /* If the function is 'naked', we do not have to generate + epilogue code fragment BUT 'ret' instruction. */ + if (cfun->machine->naked_p) + { + /* Generate return instruction by using + unspec_volatile_func_return pattern. + Make sure this instruction is after gen_blockage(). + NOTE that $lp will become 'live' + after this instruction has been emitted. */ + emit_insn (gen_unspec_volatile_func_return ()); + return; + } + + if (frame_pointer_needed) + { + /* adjust $sp = $fp - ($fp size) - ($gp size) - ($lp size) + - (4 * callee-saved-registers) + Note: No need to adjust + cfun->machine->callee_saved_area_padding_bytes, + because we want to adjust stack pointer + to the position for pop instruction. */ + sp_adjust = cfun->machine->fp_size + + cfun->machine->gp_size + + cfun->machine->lp_size + + cfun->machine->callee_saved_regs_size; + sp_adjust_insn = gen_addsi3 (stack_pointer_rtx, + hard_frame_pointer_rtx, + GEN_INT (-1 * sp_adjust)); + /* Emit rtx into instructions list and receive INSN rtx form. */ + sp_adjust_insn = emit_insn (sp_adjust_insn); + } + else + { + /* If frame pointer is NOT needed, + we cannot calculate the sp adjustment from frame pointer. + Instead, we calculate the adjustment by local_size, + out_args_size, and callee_saved_area_padding_bytes. + Notice that such sp adjustment value may be out of range, + so we have to deal with it as well. */ + + /* Adjust $sp = $sp + local_size + out_args_size + + callee_saved_area_padding_bytes. */ + sp_adjust = cfun->machine->local_size + + cfun->machine->out_args_size + + cfun->machine->callee_saved_area_padding_bytes; + /* sp_adjust value may be out of range of the addi instruction, + create alternative add behavior with TA_REGNUM if necessary, + using POSITIVE value to tell that we are increasing address. */ + sp_adjust = nds32_force_addi_stack_int (sp_adjust); + if (sp_adjust) + { + /* Generate sp adjustment instruction + if and only if sp_adjust != 0. */ + sp_adjust_insn = gen_addsi3 (stack_pointer_rtx, + stack_pointer_rtx, + GEN_INT (sp_adjust)); + /* Emit rtx into instructions list and receive INSN rtx form. */ + sp_adjust_insn = emit_insn (sp_adjust_insn); + } + } + + /* Get callee_first_regno and callee_last_regno. */ + Rb = gen_rtx_REG (SImode, cfun->machine->callee_saved_regs_first_regno); + Re = gen_rtx_REG (SImode, cfun->machine->callee_saved_regs_last_regno); + + /* pop_insn = gen_stack_pop_multiple(first_regno, last_regno), + the pattern 'stack_pop_multiple' is implementad in nds32.md. + For En4 field, we have to calculate its constant value. + Refer to Andes ISA for more information. */ + en4_const = 0; + if (cfun->machine->fp_size) + en4_const += 8; + if (cfun->machine->gp_size) + en4_const += 4; + if (cfun->machine->lp_size) + en4_const += 2; + + /* If $fp, $gp, $lp, and all callee-save registers are NOT required + to be saved, we don't have to create multiple pop instruction. + Otherwise, a multiple pop instruction is needed. */ + if (!(REGNO (Rb) == SP_REGNUM && REGNO (Re) == SP_REGNUM && en4_const == 0)) + { + /* Create multiple pop instruction rtx. */ + pop_insn = nds32_gen_stack_pop_multiple (Rb, Re, GEN_INT (en4_const)); + /* Emit pop instruction. */ + emit_insn (pop_insn); + } + + /* Generate return instruction by using + unspec_volatile_func_return pattern. */ + emit_insn (gen_unspec_volatile_func_return ()); +} + +/* Function for v3push prologue. */ +void +nds32_expand_prologue_v3push (void) +{ + int fp_adjust; + int sp_adjust; + + rtx Rb, Re; + rtx push_insn; + rtx fp_adjust_insn, sp_adjust_insn; + + /* Before computing everything for stack frame size, + we check if it is still worth to use fp_as_gp optimization. + If it is, the 'df_regs_ever_live_p (FP_REGNUM)' will be set + so that $fp will be saved on stack. */ + cfun->machine->fp_as_gp_p = nds32_fp_as_gp_check_available (); + + /* Compute and setup stack frame size. + The result will be in cfun->machine. */ + nds32_compute_stack_frame (); + + /* If the function is 'naked', + we do not have to generate prologue code fragment. */ + if (cfun->machine->naked_p) + return; + + /* Get callee_first_regno and callee_last_regno. */ + Rb = gen_rtx_REG (SImode, cfun->machine->callee_saved_regs_first_regno); + Re = gen_rtx_REG (SImode, cfun->machine->callee_saved_regs_last_regno); + + /* Calculate sp_adjust first to test if 'push25 Re,imm8u' is available, + where imm8u has to be 8-byte alignment. */ + sp_adjust = cfun->machine->local_size + + cfun->machine->out_args_size + + cfun->machine->callee_saved_area_padding_bytes; + + if (satisfies_constraint_Iu08 (GEN_INT (sp_adjust)) + && NDS32_DOUBLE_WORD_ALIGN_P (sp_adjust)) + { + /* We can use 'push25 Re,imm8u'. */ + + /* push_insn = gen_stack_v3push(last_regno, sp_adjust), + the pattern 'stack_v3push' is implemented in nds32.md. + The (const_int 14) means v3push always push { $fp $gp $lp }. */ + push_insn = nds32_gen_stack_v3push (Rb, Re, + GEN_INT (14), GEN_INT (sp_adjust)); + /* emit rtx into instructions list and receive INSN rtx form */ + push_insn = emit_insn (push_insn); + + /* The insn rtx 'push_insn' will change frame layout. + We need to use RTX_FRAME_RELATED_P so that GCC is able to + generate CFI (Call Frame Information) stuff. */ + RTX_FRAME_RELATED_P (push_insn) = 1; + + /* Check frame_pointer_needed to see + if we shall emit fp adjustment instruction. */ + if (frame_pointer_needed) + { + /* adjust $fp = $sp + 4 ($fp size) + + 4 ($gp size) + + 4 ($lp size) + + (4 * n) (callee-saved registers) + + sp_adjust ('push25 Re,imm8u') + Note: Since we use 'push25 Re,imm8u', + the position of stack pointer is further + changed after push instruction. + Hence, we need to take sp_adjust value + into consideration. */ + fp_adjust = cfun->machine->fp_size + + cfun->machine->gp_size + + cfun->machine->lp_size + + cfun->machine->callee_saved_regs_size + + sp_adjust; + fp_adjust_insn = gen_addsi3 (hard_frame_pointer_rtx, + stack_pointer_rtx, + GEN_INT (fp_adjust)); + /* Emit rtx into instructions list and receive INSN rtx form. */ + fp_adjust_insn = emit_insn (fp_adjust_insn); + } + } + else + { + /* We have to use 'push25 Re,0' and + expand one more instruction to adjust $sp later. */ + + /* push_insn = gen_stack_v3push(last_regno, sp_adjust), + the pattern 'stack_v3push' is implemented in nds32.md. + The (const_int 14) means v3push always push { $fp $gp $lp }. */ + push_insn = nds32_gen_stack_v3push (Rb, Re, + GEN_INT (14), GEN_INT (0)); + /* Emit rtx into instructions list and receive INSN rtx form. */ + push_insn = emit_insn (push_insn); + + /* The insn rtx 'push_insn' will change frame layout. + We need to use RTX_FRAME_RELATED_P so that GCC is able to + generate CFI (Call Frame Information) stuff. */ + RTX_FRAME_RELATED_P (push_insn) = 1; + + /* Check frame_pointer_needed to see + if we shall emit fp adjustment instruction. */ + if (frame_pointer_needed) + { + /* adjust $fp = $sp + 4 ($fp size) + + 4 ($gp size) + + 4 ($lp size) + + (4 * n) (callee-saved registers) + Note: Since we use 'push25 Re,0', + the stack pointer is just at the position + after push instruction. + No need to take sp_adjust into consideration. */ + fp_adjust = cfun->machine->fp_size + + cfun->machine->gp_size + + cfun->machine->lp_size + + cfun->machine->callee_saved_regs_size; + fp_adjust_insn = gen_addsi3 (hard_frame_pointer_rtx, + stack_pointer_rtx, + GEN_INT (fp_adjust)); + /* Emit rtx into instructions list and receive INSN rtx form. */ + fp_adjust_insn = emit_insn (fp_adjust_insn); + } + + /* Because we use 'push25 Re,0', + we need to expand one more instruction to adjust $sp. + However, sp_adjust value may be out of range of the addi instruction, + create alternative add behavior with TA_REGNUM if necessary, + using NEGATIVE value to tell that we are decreasing address. */ + sp_adjust = nds32_force_addi_stack_int ( (-1) * sp_adjust); + if (sp_adjust) + { + /* Generate sp adjustment instruction + if and only if sp_adjust != 0. */ + sp_adjust_insn = gen_addsi3 (stack_pointer_rtx, + stack_pointer_rtx, + GEN_INT (-1 * sp_adjust)); + /* Emit rtx into instructions list and receive INSN rtx form. */ + sp_adjust_insn = emit_insn (sp_adjust_insn); + + /* The insn rtx 'sp_adjust_insn' will change frame layout. + We need to use RTX_FRAME_RELATED_P so that GCC is able to + generate CFI (Call Frame Information) stuff. */ + RTX_FRAME_RELATED_P (sp_adjust_insn) = 1; + } + } + + /* Prevent the instruction scheduler from + moving instructions across the boundary. */ + emit_insn (gen_blockage ()); +} + +/* Function for v3pop epilogue. */ +void +nds32_expand_epilogue_v3pop (void) +{ + int sp_adjust; + + rtx Rb, Re; + rtx pop_insn; + rtx sp_adjust_insn; + + /* Compute and setup stack frame size. + The result will be in cfun->machine. */ + nds32_compute_stack_frame (); + + /* Prevent the instruction scheduler from + moving instructions across the boundary. */ + emit_insn (gen_blockage ()); + + /* If the function is 'naked', we do not have to generate + epilogue code fragment BUT 'ret' instruction. */ + if (cfun->machine->naked_p) + { + /* Generate return instruction by using + unspec_volatile_func_return pattern. + Make sure this instruction is after gen_blockage(). + NOTE that $lp will become 'live' + after this instruction has been emitted. */ + emit_insn (gen_unspec_volatile_func_return ()); + return; + } + + /* Get callee_first_regno and callee_last_regno. */ + Rb = gen_rtx_REG (SImode, cfun->machine->callee_saved_regs_first_regno); + Re = gen_rtx_REG (SImode, cfun->machine->callee_saved_regs_last_regno); + + /* Calculate sp_adjust first to test if 'pop25 Re,imm8u' is available, + where imm8u has to be 8-byte alignment. */ + sp_adjust = cfun->machine->local_size + + cfun->machine->out_args_size + + cfun->machine->callee_saved_area_padding_bytes; + + /* We have to consider alloca issue as well. + If the function does call alloca(), the stack pointer is not fixed. + In that case, we cannot use 'pop25 Re,imm8u' directly. + We have to caculate stack pointer from frame pointer + and then use 'pop25 Re,0'. + Of course, the frame_pointer_needed should be nonzero + if the function calls alloca(). */ + if (satisfies_constraint_Iu08 (GEN_INT (sp_adjust)) + && NDS32_DOUBLE_WORD_ALIGN_P (sp_adjust) + && !cfun->calls_alloca) + { + /* We can use 'pop25 Re,imm8u'. */ + + /* pop_insn = gen_stack_v3pop(last_regno, sp_adjust), + the pattern 'stack_v3pop' is implementad in nds32.md. + The (const_int 14) means v3pop always pop { $fp $gp $lp }. */ + pop_insn = nds32_gen_stack_v3pop (Rb, Re, + GEN_INT (14), GEN_INT (sp_adjust)); + + /* Emit pop instruction. */ + emit_insn (pop_insn); + } + else + { + /* We have to use 'pop25 Re,0', and prior to it, + we must expand one more instruction to adjust $sp. */ + + if (frame_pointer_needed) + { + /* adjust $sp = $fp - 4 ($fp size) + - 4 ($gp size) + - 4 ($lp size) + - (4 * n) (callee-saved registers) + Note: No need to adjust + cfun->machine->callee_saved_area_padding_bytes, + because we want to adjust stack pointer + to the position for pop instruction. */ + sp_adjust = cfun->machine->fp_size + + cfun->machine->gp_size + + cfun->machine->lp_size + + cfun->machine->callee_saved_regs_size; + sp_adjust_insn = gen_addsi3 (stack_pointer_rtx, + hard_frame_pointer_rtx, + GEN_INT (-1 * sp_adjust)); + /* Emit rtx into instructions list and receive INSN rtx form. */ + sp_adjust_insn = emit_insn (sp_adjust_insn); + } + else + { + /* If frame pointer is NOT needed, + we cannot calculate the sp adjustment from frame pointer. + Instead, we calculate the adjustment by local_size, + out_args_size, and callee_saved_area_padding_bytes. + Notice that such sp adjustment value may be out of range, + so we have to deal with it as well. */ + + /* Adjust $sp = $sp + local_size + out_args_size + + callee_saved_area_padding_bytes. */ + sp_adjust = cfun->machine->local_size + + cfun->machine->out_args_size + + cfun->machine->callee_saved_area_padding_bytes; + /* sp_adjust value may be out of range of the addi instruction, + create alternative add behavior with TA_REGNUM if necessary, + using POSITIVE value to tell that we are increasing address. */ + sp_adjust = nds32_force_addi_stack_int (sp_adjust); + if (sp_adjust) + { + /* Generate sp adjustment instruction + if and only if sp_adjust != 0. */ + sp_adjust_insn = gen_addsi3 (stack_pointer_rtx, + stack_pointer_rtx, + GEN_INT (sp_adjust)); + /* Emit rtx into instructions list and receive INSN rtx form. */ + sp_adjust_insn = emit_insn (sp_adjust_insn); + } + } + + /* pop_insn = gen_stack_v3pop(last_regno, sp_adjust), + the pattern 'stack_v3pop' is implementad in nds32.md. */ + /* The (const_int 14) means v3pop always pop { $fp $gp $lp }. */ + pop_insn = nds32_gen_stack_v3pop (Rb, Re, + GEN_INT (14), GEN_INT (0)); + + /* Emit pop instruction. */ + emit_insn (pop_insn); + } +} + +/* ------------------------------------------------------------------------ */ + +/* Function to test 333-form for load/store instructions. + This is auxiliary extern function for auxiliary macro in nds32.h. + Because it is a little complicated, we use function instead of macro. */ +bool +nds32_ls_333_p (rtx rt, rtx ra, rtx imm, enum machine_mode mode) +{ + if (REGNO_REG_CLASS (REGNO (rt)) == LOW_REGS + && REGNO_REG_CLASS (REGNO (ra)) == LOW_REGS) + { + if (GET_MODE_SIZE (mode) == 4) + return satisfies_constraint_Iu05 (imm); + + if (GET_MODE_SIZE (mode) == 2) + return satisfies_constraint_Iu04 (imm); + + if (GET_MODE_SIZE (mode) == 1) + return satisfies_constraint_Iu03 (imm); + } + + return false; +} + + +/* Functions to expand load_multiple and store_multiple. + They are auxiliary extern functions to help create rtx template. + Check nds32-multiple.md file for the patterns. */ +rtx +nds32_expand_load_multiple (int base_regno, int count, + rtx base_addr, rtx basemem) +{ + int par_index; + int offset; + rtx result; + rtx new_addr, mem, reg; + + /* Create the pattern that is presented in nds32-multiple.md. */ + + result = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count)); + + for (par_index = 0; par_index < count; par_index++) + { + offset = par_index * 4; + /* 4-byte for loading data to each register. */ + new_addr = plus_constant (Pmode, base_addr, offset); + mem = adjust_automodify_address_nv (basemem, SImode, + new_addr, offset); + reg = gen_rtx_REG (SImode, base_regno + par_index); + + XVECEXP (result, 0, par_index) = gen_rtx_SET (VOIDmode, reg, mem); + } + + return result; +} + +rtx +nds32_expand_store_multiple (int base_regno, int count, + rtx base_addr, rtx basemem) +{ + int par_index; + int offset; + rtx result; + rtx new_addr, mem, reg; + + /* Create the pattern that is presented in nds32-multiple.md. */ + + result = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count)); + + for (par_index = 0; par_index < count; par_index++) + { + offset = par_index * 4; + /* 4-byte for storing data to memory. */ + new_addr = plus_constant (Pmode, base_addr, offset); + mem = adjust_automodify_address_nv (basemem, SImode, + new_addr, offset); + reg = gen_rtx_REG (SImode, base_regno + par_index); + + XVECEXP (result, 0, par_index) = gen_rtx_SET (VOIDmode, mem, reg); + } + + return result; +} + +/* Function to move block memory content by + using load_multiple and store_multiple. + This is auxiliary extern function to help create rtx template. + Check nds32-multiple.md file for the patterns. */ +int +nds32_expand_movmemqi (rtx dstmem, rtx srcmem, rtx total_bytes, rtx alignment) +{ + HOST_WIDE_INT in_words, out_words; + rtx dst_base_reg, src_base_reg; + int maximum_bytes; + + /* Because reduced-set regsiters has few registers + (r0~r5, r6~10, r15, r28~r31, where 'r15' and 'r28~r31' + cannot be used for register allocation), + using 8 registers (32 bytes) for moving memory block + may easily consume all of them. + It makes register allocation/spilling hard to work. + So we only allow maximum=4 registers (16 bytes) for + moving memory block under reduced-set registers. */ + if (TARGET_REDUCED_REGS) + maximum_bytes = 16; + else + maximum_bytes = 32; + + /* 1. Total_bytes is integer for sure. + 2. Alignment is integer for sure. + 3. Maximum 4 or 8 registers, 4 * 4 = 16 bytes, 8 * 4 = 32 bytes. + 4. Requires (n * 4) block size. + 5. Requires 4-byte alignment. */ + if (GET_CODE (total_bytes) != CONST_INT + || GET_CODE (alignment) != CONST_INT + || INTVAL (total_bytes) > maximum_bytes + || INTVAL (total_bytes) & 3 + || INTVAL (alignment) & 3) + return 0; + + dst_base_reg = copy_to_mode_reg (SImode, XEXP (dstmem, 0)); + src_base_reg = copy_to_mode_reg (SImode, XEXP (srcmem, 0)); + + out_words = in_words = INTVAL (total_bytes) / UNITS_PER_WORD; + + emit_insn (nds32_expand_load_multiple (0, in_words, src_base_reg, srcmem)); + emit_insn (nds32_expand_store_multiple (0, out_words, dst_base_reg, dstmem)); + + /* Successfully create patterns, return 1. */ + return 1; +} + +/* Function to check whether the OP is a valid load/store operation. + This is a helper function for the predicates: + 'nds32_load_multiple_operation' and 'nds32_store_multiple_operation' + in predicates.md file. + + The OP is supposed to be a parallel rtx. + For each element within this parallel rtx: + (set (reg) (mem addr)) is the form for load operation. + (set (mem addr) (reg)) is the form for store operation. + We have to extract reg and mem of every element and + check if the information is valid for multiple load/store operation. */ +bool +nds32_valid_multiple_load_store (rtx op, bool load_p) +{ + int count; + int first_elt_regno; + rtx elt; + + /* Get the counts of elements in the parallel rtx. */ + count = XVECLEN (op, 0); + /* Pick up the first element. */ + elt = XVECEXP (op, 0, 0); + + /* Perform some quick check for the first element in the parallel rtx. */ + if (GET_CODE (elt) != SET + || count <= 1 + || count > 8) + return false; + + /* Pick up regno of first element for further detail checking. + Note that the form is different between load and store operation. */ + if (load_p) + { + if (GET_CODE (SET_DEST (elt)) != REG + || GET_CODE (SET_SRC (elt)) != MEM) + return false; + + first_elt_regno = REGNO (SET_DEST (elt)); + } + else + { + if (GET_CODE (SET_SRC (elt)) != REG + || GET_CODE (SET_DEST (elt)) != MEM) + return false; + + first_elt_regno = REGNO (SET_SRC (elt)); + } + + /* Perform detail check for each element. + Refer to nds32-multiple.md for more information + about following checking. + The starting element of parallel rtx is index 0. */ + if (!nds32_consecutive_registers_load_store_p (op, load_p, 0, + first_elt_regno, + count)) + return false; + + /* Pass all test, this is a valid rtx. */ + return true; +} + +/* Function to check whether the OP is a valid stack push/pop operation. + For a valid stack operation, it must satisfy following conditions: + 1. Consecutive registers push/pop operations. + 2. Valid $fp/$gp/$lp push/pop operations. + 3. The last element must be stack adjustment rtx. + See the prologue/epilogue implementation for details. */ +bool +nds32_valid_stack_push_pop (rtx op, bool push_p) +{ + int index; + int total_count; + int rest_count; + int first_regno; + rtx elt; + rtx elt_reg; + rtx elt_mem; + rtx elt_plus; + + /* Get the counts of elements in the parallel rtx. */ + total_count = XVECLEN (op, 0); + + /* Perform some quick check for that every element should be 'set'. */ + for (index = 0; index < total_count; index++) + { + elt = XVECEXP (op, 0, index); + if (GET_CODE (elt) != SET) + return false; + } + + /* For push operation, the parallel rtx looks like: + (parallel [(set (mem (plus (reg:SI SP_REGNUM) (const_int -32))) + (reg:SI Rb)) + (set (mem (plus (reg:SI SP_REGNUM) (const_int -28))) + (reg:SI Rb+1)) + ... + (set (mem (plus (reg:SI SP_REGNUM) (const_int -16))) + (reg:SI Re)) + (set (mem (plus (reg:SI SP_REGNUM) (const_int -12))) + (reg:SI FP_REGNUM)) + (set (mem (plus (reg:SI SP_REGNUM) (const_int -8))) + (reg:SI GP_REGNUM)) + (set (mem (plus (reg:SI SP_REGNUM) (const_int -4))) + (reg:SI LP_REGNUM)) + (set (reg:SI SP_REGNUM) + (plus (reg:SI SP_REGNUM) (const_int -32)))]) + + For pop operation, the parallel rtx looks like: + (parallel [(set (reg:SI Rb) + (mem (reg:SI SP_REGNUM))) + (set (reg:SI Rb+1) + (mem (plus (reg:SI SP_REGNUM) (const_int 4)))) + ... + (set (reg:SI Re) + (mem (plus (reg:SI SP_REGNUM) (const_int 16)))) + (set (reg:SI FP_REGNUM) + (mem (plus (reg:SI SP_REGNUM) (const_int 20)))) + (set (reg:SI GP_REGNUM) + (mem (plus (reg:SI SP_REGNUM) (const_int 24)))) + (set (reg:SI LP_REGNUM) + (mem (plus (reg:SI SP_REGNUM) (const_int 28)))) + (set (reg:SI SP_REGNUM) + (plus (reg:SI SP_REGNUM) (const_int 32)))]) */ + + /* 1. Consecutive registers push/pop operations. + We need to calculate how many registers should be consecutive. + The $sp adjustment rtx, $fp push rtx, $gp push rtx, + and $lp push rtx are excluded. */ + + /* Exclude last $sp adjustment rtx. */ + rest_count = total_count - 1; + /* Exclude $fp, $gp, and $lp if they are in the parallel rtx. */ + if (cfun->machine->fp_size) + rest_count--; + if (cfun->machine->gp_size) + rest_count--; + if (cfun->machine->lp_size) + rest_count--; + + if (rest_count > 0) + { + elt = XVECEXP (op, 0, 0); + /* Pick up register element. */ + elt_reg = push_p ? SET_SRC (elt) : SET_DEST (elt); + first_regno = REGNO (elt_reg); + + /* The 'push' operation is a kind of store operation. + The 'pop' operation is a kind of load operation. + Pass corresponding false/true as second argument (bool load_p). + The par_index is supposed to start with index 0. */ + if (!nds32_consecutive_registers_load_store_p (op, + !push_p ? true : false, + 0, + first_regno, + rest_count)) + return false; + } + + /* 2. Valid $fp/$gp/$lp push/pop operations. + Remember to set start index for checking them. */ + + /* The rest_count is the start index for checking $fp/$gp/$lp. */ + index = rest_count; + /* If index < 0, this parallel rtx is definitely + not a valid stack push/pop operation. */ + if (index < 0) + return false; + + /* Check $fp/$gp/$lp one by one. + We use 'push_p' to pick up reg rtx and mem rtx. */ + if (cfun->machine->fp_size) + { + elt = XVECEXP (op, 0, index); + elt_mem = push_p ? SET_DEST (elt) : SET_SRC (elt); + elt_reg = push_p ? SET_SRC (elt) : SET_DEST (elt); + index++; + + if (GET_CODE (elt_mem) != MEM + || GET_CODE (elt_reg) != REG + || REGNO (elt_reg) != FP_REGNUM) + return false; + } + if (cfun->machine->gp_size) + { + elt = XVECEXP (op, 0, index); + elt_mem = push_p ? SET_DEST (elt) : SET_SRC (elt); + elt_reg = push_p ? SET_SRC (elt) : SET_DEST (elt); + index++; + + if (GET_CODE (elt_mem) != MEM + || GET_CODE (elt_reg) != REG + || REGNO (elt_reg) != GP_REGNUM) + return false; + } + if (cfun->machine->lp_size) + { + elt = XVECEXP (op, 0, index); + elt_mem = push_p ? SET_DEST (elt) : SET_SRC (elt); + elt_reg = push_p ? SET_SRC (elt) : SET_DEST (elt); + index++; + + if (GET_CODE (elt_mem) != MEM + || GET_CODE (elt_reg) != REG + || REGNO (elt_reg) != LP_REGNUM) + return false; + } + + /* 3. The last element must be stack adjustment rtx. + Its form of rtx should be: + (set (reg:SI SP_REGNUM) + (plus (reg:SI SP_REGNUM) (const_int X))) + The X could be positive or negative value. */ + + /* Pick up the last element. */ + elt = XVECEXP (op, 0, total_count - 1); + + /* Extract its destination and source rtx. */ + elt_reg = SET_DEST (elt); + elt_plus = SET_SRC (elt); + + /* Check this is (set (stack_reg) (plus stack_reg const)) pattern. */ + if (GET_CODE (elt_reg) != REG + || GET_CODE (elt_plus) != PLUS + || REGNO (elt_reg) != SP_REGNUM) + return false; + + /* Pass all test, this is a valid rtx. */ + return true; +} + +/* Computing the Length of an Insn. + Modifies the length assigned to instruction INSN. + LEN is the initially computed length of the insn. */ +int +nds32_adjust_insn_length (rtx insn, int length) +{ + rtx src, dst; + + switch (recog_memoized (insn)) + { + case CODE_FOR_move_df: + case CODE_FOR_move_di: + /* Adjust length of movd44 to 2. */ + src = XEXP (PATTERN (insn), 1); + dst = XEXP (PATTERN (insn), 0); + + if (REG_P (src) + && REG_P (dst) + && (REGNO (src) % 2) == 0 + && (REGNO (dst) % 2) == 0) + length = 2; + break; + + default: + break; + } + + return length; +} + + +/* Function to check if 'bclr' instruction can be used with IVAL. */ +int +nds32_can_use_bclr_p (int ival) +{ + int one_bit_count; + + /* Calculate the number of 1-bit of (~ival), if there is only one 1-bit, + it means the original ival has only one 0-bit, + So it is ok to perform 'bclr' operation. */ + + one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (~ival)); + + /* 'bclr' is a performance extension instruction. */ + return (TARGET_PERF_EXT && (one_bit_count == 1)); +} + +/* Function to check if 'bset' instruction can be used with IVAL. */ +int +nds32_can_use_bset_p (int ival) +{ + int one_bit_count; + + /* Caculate the number of 1-bit of ival, if there is only one 1-bit, + it is ok to perform 'bset' operation. */ + + one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (ival)); + + /* 'bset' is a performance extension instruction. */ + return (TARGET_PERF_EXT && (one_bit_count == 1)); +} + +/* Function to check if 'btgl' instruction can be used with IVAL. */ +int +nds32_can_use_btgl_p (int ival) +{ + int one_bit_count; + + /* Caculate the number of 1-bit of ival, if there is only one 1-bit, + it is ok to perform 'btgl' operation. */ + + one_bit_count = popcount_hwi ((unsigned HOST_WIDE_INT) (ival)); + + /* 'btgl' is a performance extension instruction. */ + return (TARGET_PERF_EXT && (one_bit_count == 1)); +} + +/* Function to check if 'bitci' instruction can be used with IVAL. */ +int +nds32_can_use_bitci_p (int ival) +{ + /* If we are using V3 ISA, we have 'bitci' instruction. + Try to see if we can present 'andi' semantic with + such 'bit-clear-immediate' operation. + For example, 'andi $r0,$r0,0xfffffffc' can be + presented with 'bitci $r0,$r0,3'. */ + return (TARGET_ISA_V3 + && (ival < 0) + && satisfies_constraint_Iu15 (gen_int_mode (~ival, SImode))); +} + + +/* Return true if is load/store with SYMBOL_REF addressing mode + and memory mode is SImode. */ +bool +nds32_symbol_load_store_p (rtx insn) +{ + rtx mem_src = NULL_RTX; + + switch (get_attr_type (insn)) + { + case TYPE_LOAD: + mem_src = SET_SRC (PATTERN (insn)); + break; + case TYPE_STORE: + mem_src = SET_DEST (PATTERN (insn)); + break; + default: + break; + } + + /* Find load/store insn with addressing mode is SYMBOL_REF. */ + if (mem_src != NULL_RTX) + { + if ((GET_CODE (mem_src) == ZERO_EXTEND) + || (GET_CODE (mem_src) == SIGN_EXTEND)) + mem_src = XEXP (mem_src, 0); + + if ((GET_CODE (XEXP (mem_src, 0)) == SYMBOL_REF) + || (GET_CODE (XEXP (mem_src, 0)) == LO_SUM)) + return true; + } + + return false; +} + +/* Function to determine whether it is worth to do fp_as_gp optimization. + Return 0: It is NOT worth to do fp_as_gp optimization. + Return 1: It is APPROXIMATELY worth to do fp_as_gp optimization. + Note that if it is worth to do fp_as_gp optimization, + we MUST set FP_REGNUM ever live in this function. */ +int +nds32_fp_as_gp_check_available (void) +{ + /* If there exists ANY of following conditions, + we DO NOT perform fp_as_gp optimization: + 1. TARGET_FORBID_FP_AS_GP is set + regardless of the TARGET_FORCE_FP_AS_GP. + 2. User explicitly uses 'naked' attribute. + 3. Not optimize for size. + 4. Need frame pointer. + 5. If $fp is already required to be saved, + it means $fp is already choosen by register allocator. + Thus we better not to use it for fp_as_gp optimization. + 6. This function is a vararg function. + DO NOT apply fp_as_gp optimization on this function + because it may change and break stack frame. + 7. The epilogue is empty. + This happens when the function uses exit() + or its attribute is no_return. + In that case, compiler will not expand epilogue + so that we have no chance to output .omit_fp_end directive. */ + if (TARGET_FORBID_FP_AS_GP + || lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl)) + || !optimize_size + || frame_pointer_needed + || NDS32_REQUIRED_CALLEE_SAVED_P (FP_REGNUM) + || (cfun->stdarg == 1) + || (find_fallthru_edge (EXIT_BLOCK_PTR->preds) == NULL)) + return 0; + + /* Now we can check the possibility of using fp_as_gp optimization. */ + if (TARGET_FORCE_FP_AS_GP) + { + /* User explicitly issues -mforce-fp-as-gp option. */ + df_set_regs_ever_live (FP_REGNUM, 1); + return 1; + } + else + { + /* In the following we are going to evaluate whether + it is worth to do fp_as_gp optimization. */ + int good_gain = 0; + int symbol_count = 0; + + int threshold; + rtx insn; + + /* We check if there already requires prologue. + Note that $gp will be saved in prologue for PIC code generation. + After that, we can set threshold by the existence of prologue. + Each fp-implied instruction will gain 2-byte code size + from gp-aware instruction, so we have following heuristics. */ + if (flag_pic + || nds32_have_prologue_p ()) + { + /* Have-prologue: + Compiler already intends to generate prologue content, + so the fp_as_gp optimization will only insert + 'la $fp,_FP_BASE_' instruction, which will be + converted into 4-byte instruction at link time. + The threshold is "3" symbol accesses, 2 + 2 + 2 > 4. */ + threshold = 3; + } + else + { + /* None-prologue: + Compiler originally does not generate prologue content, + so the fp_as_gp optimization will NOT ONLY insert + 'la $fp,_FP_BASE' instruction, but also causes + push/pop instructions. + If we are using v3push (push25/pop25), + the threshold is "5" symbol accesses, 5*2 > 4 + 2 + 2; + If we are using normal push (smw/lmw), + the threshold is "5+2" symbol accesses 7*2 > 4 + 4 + 4. */ + threshold = 5 + (TARGET_V3PUSH ? 0 : 2); + } + + /* We would like to traverse every instruction in this function. + So we need to have push_topmost_sequence()/pop_topmost_sequence() + surrounding our for-loop evaluation. */ + push_topmost_sequence (); + /* Counting the insn number which the addressing mode is symbol. */ + for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) + { + if (single_set (insn) && nds32_symbol_load_store_p (insn)) + symbol_count++; + + if (symbol_count == threshold) + { + good_gain = 1; + break; + } + } + pop_topmost_sequence (); + + /* Enable fp_as_gp optimization when potential gain is good enough. */ + if (good_gain) + { + df_set_regs_ever_live (FP_REGNUM, 1); + return 1; + } + } + + /* By default we return 0. */ + return 0; +} + + +/* Function to generate PC relative jump table. + Refer to nds32.md for more details. + + The following is the sample for the case that diff value + can be presented in '.short' size. + + addi $r1, $r1, -(case_lower_bound) + slti $ta, $r1, (case_number) + beqz $ta, .L_skip_label + + la $ta, .L35 ! get jump table address + lh $r1, [$ta + $r1 << 1] ! load symbol diff from jump table entry + addi $ta, $r1, $ta + jr5 $ta + + ! jump table entry + L35: + .short .L25-.L35 + .short .L26-.L35 + .short .L27-.L35 + .short .L28-.L35 + .short .L29-.L35 + .short .L30-.L35 + .short .L31-.L35 + .short .L32-.L35 + .short .L33-.L35 + .short .L34-.L35 */ +const char * +nds32_output_casesi_pc_relative (rtx *operands) +{ + enum machine_mode mode; + rtx diff_vec; + + diff_vec = PATTERN (next_active_insn (operands[1])); + + gcc_assert (GET_CODE (diff_vec) == ADDR_DIFF_VEC); + + /* Step C: "t <-- operands[1]". */ + output_asm_insn ("la\t$ta, %l1", operands); + + /* Get the mode of each element in the difference vector. */ + mode = GET_MODE (diff_vec); + + /* Step D: "z <-- (mem (plus (operands[0] << m) t))", + where m is 0, 1, or 2 to load address-diff value from table. */ + switch (mode) + { + case QImode: + output_asm_insn ("lb\t%2, [$ta + %0 << 0]", operands); + break; + case HImode: + output_asm_insn ("lh\t%2, [$ta + %0 << 1]", operands); + break; + case SImode: + output_asm_insn ("lw\t%2, [$ta + %0 << 2]", operands); + break; + default: + gcc_unreachable (); + } + + /* Step E: "t <-- z + t". + Add table label_ref with address-diff value to + obtain target case address. */ + output_asm_insn ("add\t$ta, %2, $ta", operands); + + /* Step F: jump to target with register t. */ + if (TARGET_16_BIT) + return "jr5\t$ta"; + else + return "jr\t$ta"; +} + +/* Function to generate normal jump table. */ +const char * +nds32_output_casesi (rtx *operands) +{ + /* Step C: "t <-- operands[1]". */ + output_asm_insn ("la\t$ta, %l1", operands); + + /* Step D: "z <-- (mem (plus (operands[0] << 2) t))". */ + output_asm_insn ("lw\t%2, [$ta + %0 << 2]", operands); + + /* No need to perform Step E, which is only used for + pc relative jump table. */ + + /* Step F: jump to target with register z. */ + if (TARGET_16_BIT) + return "jr5\t%2"; + else + return "jr\t%2"; +} + + +/* Function to return memory format. */ +enum nds32_16bit_address_type +nds32_mem_format (rtx op) +{ + enum machine_mode mode_test; + int val; + int regno; + + if (!TARGET_16_BIT) + return ADDRESS_NOT_16BIT_FORMAT; + + mode_test = GET_MODE (op); + + op = XEXP (op, 0); + + /* 45 format. */ + if (GET_CODE (op) == REG && (mode_test == SImode)) + return ADDRESS_REG; + + /* 333 format for QI/HImode. */ + if (GET_CODE (op) == REG && (REGNO (op) < R8_REGNUM)) + return ADDRESS_LO_REG_IMM3U; + + /* post_inc 333 format. */ + if ((GET_CODE (op) == POST_INC) && (mode_test == SImode)) + { + regno = REGNO(XEXP (op, 0)); + + if (regno < 8) + return ADDRESS_POST_INC_LO_REG_IMM3U; + } + + /* post_inc 333 format. */ + if ((GET_CODE (op) == POST_MODIFY) + && (mode_test == SImode) + && (REG_P (XEXP (XEXP (op, 1), 0))) + && (CONST_INT_P (XEXP (XEXP (op, 1), 1)))) + { + regno = REGNO (XEXP (XEXP (op, 1), 0)); + val = INTVAL (XEXP (XEXP (op, 1), 1)); + if (regno < 8 && val < 32) + return ADDRESS_POST_INC_LO_REG_IMM3U; + } + + if ((GET_CODE (op) == PLUS) + && (GET_CODE (XEXP (op, 0)) == REG) + && (GET_CODE (XEXP (op, 1)) == CONST_INT)) + { + val = INTVAL (XEXP (op, 1)); + + regno = REGNO(XEXP (op, 0)); + + if (regno > 7 + && regno != SP_REGNUM + && regno != FP_REGNUM) + return ADDRESS_NOT_16BIT_FORMAT; + + switch (mode_test) + { + case QImode: + /* 333 format. */ + if (val >= 0 && val < 8 && regno < 8) + return ADDRESS_LO_REG_IMM3U; + break; + + case HImode: + /* 333 format. */ + if (val >= 0 && val < 16 && (val % 2 == 0) && regno < 8) + return ADDRESS_LO_REG_IMM3U; + break; + + case SImode: + case SFmode: + case DFmode: + /* fp imply 37 format. */ + if ((regno == FP_REGNUM) && + (val >= 0 && val < 512 && (val % 4 == 0))) + return ADDRESS_FP_IMM7U; + /* sp imply 37 format. */ + else if ((regno == SP_REGNUM) && + (val >= 0 && val < 512 && (val % 4 == 0))) + return ADDRESS_SP_IMM7U; + /* 333 format. */ + else if (val >= 0 && val < 32 && (val % 4 == 0) && regno < 8) + return ADDRESS_LO_REG_IMM3U; + break; + + default: + break; + } + } + + return ADDRESS_NOT_16BIT_FORMAT; +} + +/* Output 16-bit store. */ +const char * +nds32_output_16bit_store (rtx *operands, int byte) +{ + char pattern[100]; + char size; + rtx code = XEXP (operands[0], 0); + + size = nds32_byte_to_size (byte); + + switch (nds32_mem_format (operands[0])) + { + case ADDRESS_REG: + operands[0] = code; + output_asm_insn ("swi450\t%1, [%0]", operands); + break; + case ADDRESS_LO_REG_IMM3U: + snprintf (pattern, sizeof (pattern), "s%ci333\t%%1, %%0", size); + output_asm_insn (pattern, operands); + break; + case ADDRESS_POST_INC_LO_REG_IMM3U: + snprintf (pattern, sizeof (pattern), "s%ci333.bi\t%%1, %%0", size); + output_asm_insn (pattern, operands); + break; + case ADDRESS_FP_IMM7U: + output_asm_insn ("swi37\t%1, %0", operands); + break; + case ADDRESS_SP_IMM7U: + /* Get immediate value and set back to operands[1]. */ + operands[0] = XEXP (code, 1); + output_asm_insn ("swi37.sp\t%1, [ + (%0)]", operands); + break; + default: + break; + } + + return ""; +} + +/* Output 16-bit load. */ +const char * +nds32_output_16bit_load (rtx *operands, int byte) +{ + char pattern[100]; + unsigned char size; + rtx code = XEXP (operands[1], 0); + + size = nds32_byte_to_size (byte); + + switch (nds32_mem_format (operands[1])) + { + case ADDRESS_REG: + operands[1] = code; + output_asm_insn ("lwi450\t%0, [%1]", operands); + break; + case ADDRESS_LO_REG_IMM3U: + snprintf (pattern, sizeof (pattern), "l%ci333\t%%0, %%1", size); + output_asm_insn (pattern, operands); + break; + case ADDRESS_POST_INC_LO_REG_IMM3U: + snprintf (pattern, sizeof (pattern), "l%ci333.bi\t%%0, %%1", size); + output_asm_insn (pattern, operands); + break; + case ADDRESS_FP_IMM7U: + output_asm_insn ("lwi37\t%0, %1", operands); + break; + case ADDRESS_SP_IMM7U: + /* Get immediate value and set back to operands[0]. */ + operands[1] = XEXP (code, 1); + output_asm_insn ("lwi37.sp\t%0, [ + (%1)]", operands); + break; + default: + break; + } + + return ""; +} + +/* Output 32-bit store. */ +const char * +nds32_output_32bit_store (rtx *operands, int byte) +{ + char pattern[100]; + unsigned char size; + rtx code = XEXP (operands[0], 0); + + size = nds32_byte_to_size (byte); + + switch (GET_CODE (code)) + { + case REG: + /* (mem (reg X)) + => access location by using register, + use "sbi / shi / swi" */ + snprintf (pattern, sizeof (pattern), "s%ci\t%%1, %%0", size); + break; + + case SYMBOL_REF: + case CONST: + /* (mem (symbol_ref X)) + (mem (const (...))) + => access global variables, + use "sbi.gp / shi.gp / swi.gp" */ + operands[0] = XEXP (operands[0], 0); + snprintf (pattern, sizeof (pattern), "s%ci.gp\t%%1, [ + %%0]", size); + break; + + case POST_INC: + /* (mem (post_inc reg)) + => access location by using register which will be post increment, + use "sbi.bi / shi.bi / swi.bi" */ + snprintf (pattern, sizeof (pattern), + "s%ci.bi\t%%1, %%0, %d", size, byte); + break; + + case POST_DEC: + /* (mem (post_dec reg)) + => access location by using register which will be post decrement, + use "sbi.bi / shi.bi / swi.bi" */ + snprintf (pattern, sizeof (pattern), + "s%ci.bi\t%%1, %%0, -%d", size, byte); + break; + + case POST_MODIFY: + switch (GET_CODE (XEXP (XEXP (code, 1), 1))) + { + case REG: + case SUBREG: + /* (mem (post_modify (reg) (plus (reg) (reg)))) + => access location by using register which will be + post modified with reg, + use "sb.bi/ sh.bi / sw.bi" */ + snprintf (pattern, sizeof (pattern), "s%c.bi\t%%1, %%0", size); + break; + case CONST_INT: + /* (mem (post_modify (reg) (plus (reg) (const_int)))) + => access location by using register which will be + post modified with const_int, + use "sbi.bi/ shi.bi / swi.bi" */ + snprintf (pattern, sizeof (pattern), "s%ci.bi\t%%1, %%0", size); + break; + default: + abort (); + } + break; + + case PLUS: + switch (GET_CODE (XEXP (code, 1))) + { + case REG: + case SUBREG: + /* (mem (plus reg reg)) or (mem (plus (mult reg const_int) reg)) + => access location by adding two registers, + use "sb / sh / sw" */ + snprintf (pattern, sizeof (pattern), "s%c\t%%1, %%0", size); + break; + case CONST_INT: + /* (mem (plus reg const_int)) + => access location by adding one register with const_int, + use "sbi / shi / swi" */ + snprintf (pattern, sizeof (pattern), "s%ci\t%%1, %%0", size); + break; + default: + abort (); + } + break; + + case LO_SUM: + operands[2] = XEXP (code, 1); + operands[0] = XEXP (code, 0); + snprintf (pattern, sizeof (pattern), + "s%ci\t%%1, [%%0 + lo12(%%2)]", size); + break; + + default: + abort (); + } + + output_asm_insn (pattern, operands); + return ""; +} + +/* Output 32-bit load. */ +const char * +nds32_output_32bit_load (rtx *operands, int byte) +{ + char pattern[100]; + unsigned char size; + rtx code; + + code = XEXP (operands[1], 0); + + size = nds32_byte_to_size (byte); + + switch (GET_CODE (code)) + { + case REG: + /* (mem (reg X)) + => access location by using register, + use "lbi / lhi / lwi" */ + snprintf (pattern, sizeof (pattern), "l%ci\t%%0, %%1", size); + break; + + case SYMBOL_REF: + case CONST: + /* (mem (symbol_ref X)) + (mem (const (...))) + => access global variables, + use "lbi.gp / lhi.gp / lwi.gp" */ + operands[1] = XEXP (operands[1], 0); + snprintf (pattern, sizeof (pattern), "l%ci.gp\t%%0, [ + %%1]", size); + break; + + case POST_INC: + /* (mem (post_inc reg)) + => access location by using register which will be post increment, + use "lbi.bi / lhi.bi / lwi.bi" */ + snprintf (pattern, sizeof (pattern), + "l%ci.bi\t%%0, %%1, %d", size, byte); + break; + + case POST_DEC: + /* (mem (post_dec reg)) + => access location by using register which will be post decrement, + use "lbi.bi / lhi.bi / lwi.bi" */ + snprintf (pattern, sizeof (pattern), + "l%ci.bi\t%%0, %%1, -%d", size, byte); + break; + + case POST_MODIFY: + switch (GET_CODE (XEXP (XEXP (code, 1), 1))) + { + case REG: + case SUBREG: + /* (mem (post_modify (reg) (plus (reg) (reg)))) + => access location by using register which will be + post modified with reg, + use "lb.bi/ lh.bi / lw.bi" */ + snprintf (pattern, sizeof (pattern), "l%c.bi\t%%0, %%1", size); + break; + case CONST_INT: + /* (mem (post_modify (reg) (plus (reg) (const_int)))) + => access location by using register which will be + post modified with const_int, + use "lbi.bi/ lhi.bi / lwi.bi" */ + snprintf (pattern, sizeof (pattern), "l%ci.bi\t%%0, %%1", size); + break; + default: + abort (); + } + break; + + case PLUS: + switch (GET_CODE (XEXP (code, 1))) + { + case REG: + case SUBREG: + /* (mem (plus reg reg)) or (mem (plus (mult reg const_int) reg)) + use "lb / lh / lw" */ + snprintf (pattern, sizeof (pattern), "l%c\t%%0, %%1", size); + break; + case CONST_INT: + /* (mem (plus reg const_int)) + => access location by adding one register with const_int, + use "lbi / lhi / lwi" */ + snprintf (pattern, sizeof (pattern), "l%ci\t%%0, %%1", size); + break; + default: + abort (); + } + break; + + case LO_SUM: + operands[2] = XEXP (code, 1); + operands[1] = XEXP (code, 0); + snprintf (pattern, sizeof (pattern), + "l%ci\t%%0, [%%1 + lo12(%%2)]", size); + break; + + default: + abort (); + } + + output_asm_insn (pattern, operands); + return ""; +} + +/* Output 32-bit load with signed extension. */ +const char * +nds32_output_32bit_load_s (rtx *operands, int byte) +{ + char pattern[100]; + unsigned char size; + rtx code; + + code = XEXP (operands[1], 0); + + size = nds32_byte_to_size (byte); + + switch (GET_CODE (code)) + { + case REG: + /* (mem (reg X)) + => access location by using register, + use "lbsi / lhsi" */ + snprintf (pattern, sizeof (pattern), "l%csi\t%%0, %%1", size); + break; + + case SYMBOL_REF: + case CONST: + /* (mem (symbol_ref X)) + (mem (const (...))) + => access global variables, + use "lbsi.gp / lhsi.gp" */ + operands[1] = XEXP (operands[1], 0); + snprintf (pattern, sizeof (pattern), "l%csi.gp\t%%0, [ + %%1]", size); + break; + + case POST_INC: + /* (mem (post_inc reg)) + => access location by using register which will be post increment, + use "lbsi.bi / lhsi.bi" */ + snprintf (pattern, sizeof (pattern), + "l%csi.bi\t%%0, %%1, %d", size, byte); + break; + + case POST_DEC: + /* (mem (post_dec reg)) + => access location by using register which will be post decrement, + use "lbsi.bi / lhsi.bi" */ + snprintf (pattern, sizeof (pattern), + "l%csi.bi\t%%0, %%1, -%d", size, byte); + break; + + case POST_MODIFY: + switch (GET_CODE (XEXP (XEXP (code, 1), 1))) + { + case REG: + case SUBREG: + /* (mem (post_modify (reg) (plus (reg) (reg)))) + => access location by using register which will be + post modified with reg, + use "lbs.bi/ lhs.bi" */ + snprintf (pattern, sizeof (pattern), "l%cs.bi\t%%0, %%1", size); + break; + case CONST_INT: + /* (mem (post_modify (reg) (plus (reg) (const_int)))) + => access location by using register which will be + post modified with const_int, + use "lbsi.bi/ lhsi.bi" */ + snprintf (pattern, sizeof (pattern), "l%csi.bi\t%%0, %%1", size); + break; + default: + abort (); + } + break; + + case PLUS: + switch (GET_CODE (XEXP (code, 1))) + { + case REG: + case SUBREG: + /* (mem (plus reg reg)) or (mem (plus (mult reg const_int) reg)) + use "lbs / lhs" */ + snprintf (pattern, sizeof (pattern), "l%cs\t%%0, %%1", size); + break; + case CONST_INT: + /* (mem (plus reg const_int)) + => access location by adding one register with const_int, + use "lbsi / lhsi" */ + snprintf (pattern, sizeof (pattern), "l%csi\t%%0, %%1", size); + break; + default: + abort (); + } + break; + + case LO_SUM: + operands[2] = XEXP (code, 1); + operands[1] = XEXP (code, 0); + snprintf (pattern, sizeof (pattern), + "l%csi\t%%0, [%%1 + lo12(%%2)]", size); + break; + + default: + abort (); + } + + output_asm_insn (pattern, operands); + return ""; +} + +/* Function to output stack push operation. + We need to deal with normal stack push multiple or stack v3push. */ +const char * +nds32_output_stack_push (void) +{ + /* A string pattern for output_asm_insn(). */ + char pattern[100]; + /* The operands array which will be used in output_asm_insn(). */ + rtx operands[3]; + /* Pick up callee-saved first regno and last regno for further use. */ + int rb_regno = cfun->machine->callee_saved_regs_first_regno; + int re_regno = cfun->machine->callee_saved_regs_last_regno; + + if (TARGET_V3PUSH) + { + /* For stack v3push: + operands[0]: Re + operands[1]: imm8u */ + + /* This variable is to check if 'push25 Re,imm8u' is available. */ + int sp_adjust; + + /* Set operands[0]. */ + operands[0] = gen_rtx_REG (SImode, re_regno); + + /* Check if we can generate 'push25 Re,imm8u', + otherwise, generate 'push25 Re,0'. */ + sp_adjust = cfun->machine->local_size + + cfun->machine->out_args_size + + cfun->machine->callee_saved_area_padding_bytes; + if (satisfies_constraint_Iu08 (GEN_INT (sp_adjust)) + && NDS32_DOUBLE_WORD_ALIGN_P (sp_adjust)) + operands[1] = GEN_INT (sp_adjust); + else + operands[1] = GEN_INT (0); + + /* Create assembly code pattern. */ + snprintf (pattern, sizeof (pattern), "push25\t%%0, %%1"); + } + else + { + /* For normal stack push multiple: + operands[0]: Rb + operands[1]: Re + operands[2]: En4 */ + + /* This variable is used to check if we only need to generate En4 field. + As long as Rb==Re=SP_REGNUM, we set this variable to 1. */ + int push_en4_only_p = 0; + + /* Set operands[0] and operands[1]. */ + operands[0] = gen_rtx_REG (SImode, rb_regno); + operands[1] = gen_rtx_REG (SImode, re_regno); + + /* 'smw.adm $sp,[$sp],$sp,0' means push nothing. */ + if (!cfun->machine->fp_size + && !cfun->machine->gp_size + && !cfun->machine->lp_size + && REGNO (operands[0]) == SP_REGNUM + && REGNO (operands[1]) == SP_REGNUM) + { + /* No need to generate instruction. */ + return ""; + } + else + { + /* If Rb==Re=SP_REGNUM, we only need to generate En4 field. */ + if (REGNO (operands[0]) == SP_REGNUM + && REGNO (operands[1]) == SP_REGNUM) + push_en4_only_p = 1; + + /* Create assembly code pattern. + We need to handle the form: "Rb, Re, { $fp $gp $lp }". */ + snprintf (pattern, sizeof (pattern), + "push.s\t%s{%s%s%s }", + push_en4_only_p ? "" : "%0, %1, ", + cfun->machine->fp_size ? " $fp" : "", + cfun->machine->gp_size ? " $gp" : "", + cfun->machine->lp_size ? " $lp" : ""); + } + } + + /* We use output_asm_insn() to output assembly code by ourself. */ + output_asm_insn (pattern, operands); + return ""; +} + +/* Function to output stack pop operation. + We need to deal with normal stack pop multiple or stack v3pop. */ +const char * +nds32_output_stack_pop (void) +{ + /* A string pattern for output_asm_insn(). */ + char pattern[100]; + /* The operands array which will be used in output_asm_insn(). */ + rtx operands[3]; + /* Pick up callee-saved first regno and last regno for further use. */ + int rb_regno = cfun->machine->callee_saved_regs_first_regno; + int re_regno = cfun->machine->callee_saved_regs_last_regno; + + if (TARGET_V3PUSH) + { + /* For stack v3pop: + operands[0]: Re + operands[1]: imm8u */ + + /* This variable is to check if 'pop25 Re,imm8u' is available. */ + int sp_adjust; + + /* Set operands[0]. */ + operands[0] = gen_rtx_REG (SImode, re_regno); + + /* Check if we can generate 'pop25 Re,imm8u', + otherwise, generate 'pop25 Re,0'. + We have to consider alloca issue as well. + If the function does call alloca(), the stack pointer is not fixed. + In that case, we cannot use 'pop25 Re,imm8u' directly. + We have to caculate stack pointer from frame pointer + and then use 'pop25 Re,0'. */ + sp_adjust = cfun->machine->local_size + + cfun->machine->out_args_size + + cfun->machine->callee_saved_area_padding_bytes; + if (satisfies_constraint_Iu08 (GEN_INT (sp_adjust)) + && NDS32_DOUBLE_WORD_ALIGN_P (sp_adjust) + && !cfun->calls_alloca) + operands[1] = GEN_INT (sp_adjust); + else + operands[1] = GEN_INT (0); + + /* Create assembly code pattern. */ + snprintf (pattern, sizeof (pattern), "pop25\t%%0, %%1"); + } + else + { + /* For normal stack pop multiple: + operands[0]: Rb + operands[1]: Re + operands[2]: En4 */ + + /* This variable is used to check if we only need to generate En4 field. + As long as Rb==Re=SP_REGNUM, we set this variable to 1. */ + int pop_en4_only_p = 0; + + /* Set operands[0] and operands[1]. */ + operands[0] = gen_rtx_REG (SImode, rb_regno); + operands[1] = gen_rtx_REG (SImode, re_regno); + + /* 'lmw.bim $sp,[$sp],$sp,0' means pop nothing. */ + if (!cfun->machine->fp_size + && !cfun->machine->gp_size + && !cfun->machine->lp_size + && REGNO (operands[0]) == SP_REGNUM + && REGNO (operands[1]) == SP_REGNUM) + { + /* No need to generate instruction. */ + return ""; + } + else + { + /* If Rb==Re=SP_REGNUM, we only need to generate En4 field. */ + if (REGNO (operands[0]) == SP_REGNUM + && REGNO (operands[1]) == SP_REGNUM) + pop_en4_only_p = 1; + + /* Create assembly code pattern. + We need to handle the form: "Rb, Re, { $fp $gp $lp }". */ + snprintf (pattern, sizeof (pattern), + "pop.s\t%s{%s%s%s }", + pop_en4_only_p ? "" : "%0, %1, ", + cfun->machine->fp_size ? " $fp" : "", + cfun->machine->gp_size ? " $gp" : "", + cfun->machine->lp_size ? " $lp" : ""); + } + } + + /* We use output_asm_insn() to output assembly code by ourself. */ + output_asm_insn (pattern, operands); + return ""; +} + +/* Return align 2 (log base 2) if the next instruction of LABEL is 4 byte. */ +int +nds32_target_alignment (rtx label) +{ + rtx insn; + + if (optimize_size) + return 0; + + insn = next_active_insn (label); + + if (insn == 0) + return 0; + else if ((get_attr_length (insn) % 4) == 0) + return 2; + else + return 0; +} + +/* ------------------------------------------------------------------------ */ + +/* PART 5: Initialize target hook structure and definitions. */ + +/* Controlling the Compilation Driver. */ + + +/* Run-time Target Specification. */ + + +/* Defining Data Structures for Per-function Information. */ + + +/* Storage Layout. */ + +#undef TARGET_PROMOTE_FUNCTION_MODE +#define TARGET_PROMOTE_FUNCTION_MODE \ + default_promote_function_mode_always_promote + + +/* Layout of Source Language Data Types. */ + + +/* Register Usage. */ + +/* -- Basic Characteristics of Registers. */ + +/* -- Order of Allocation of Registers. */ + +/* -- How Values Fit in Registers. */ + +/* -- Handling Leaf Functions. */ + +/* -- Registers That Form a Stack. */ + + +/* Register Classes. */ + +#undef TARGET_CLASS_MAX_NREGS +#define TARGET_CLASS_MAX_NREGS nds32_class_max_nregs + +#undef TARGET_LRA_P +#define TARGET_LRA_P hook_bool_void_true + +#undef TARGET_REGISTER_PRIORITY +#define TARGET_REGISTER_PRIORITY nds32_register_priority + + +/* Obsolete Macros for Defining Constraints. */ + + +/* Stack Layout and Calling Conventions. */ + +/* -- Basic Stack Layout. */ + +/* -- Exception Handling Support. */ + +/* -- Specifying How Stack Checking is Done. */ + +/* -- Registers That Address the Stack Frame. */ + +/* -- Eliminating Frame Pointer and Arg Pointer. */ + +#undef TARGET_CAN_ELIMINATE +#define TARGET_CAN_ELIMINATE nds32_can_eliminate + +/* -- Passing Function Arguments on the Stack. */ + +/* -- Passing Arguments in Registers. */ + +#undef TARGET_FUNCTION_ARG +#define TARGET_FUNCTION_ARG nds32_function_arg + +#undef TARGET_FUNCTION_ARG_ADVANCE +#define TARGET_FUNCTION_ARG_ADVANCE nds32_function_arg_advance + +#undef TARGET_FUNCTION_ARG_BOUNDARY +#define TARGET_FUNCTION_ARG_BOUNDARY nds32_function_arg_boundary + +/* -- How Scalar Function Values Are Returned. */ + +#undef TARGET_FUNCTION_VALUE +#define TARGET_FUNCTION_VALUE nds32_function_value + +#undef TARGET_LIBCALL_VALUE +#define TARGET_LIBCALL_VALUE nds32_libcall_value + +#undef TARGET_FUNCTION_VALUE_REGNO_P +#define TARGET_FUNCTION_VALUE_REGNO_P nds32_function_value_regno_p + +/* -- How Large Values Are Returned. */ + +/* -- Caller-Saves Register Allocation. */ + +/* -- Function Entry and Exit. */ + +#undef TARGET_ASM_FUNCTION_PROLOGUE +#define TARGET_ASM_FUNCTION_PROLOGUE nds32_asm_function_prologue + +#undef TARGET_ASM_FUNCTION_END_PROLOGUE +#define TARGET_ASM_FUNCTION_END_PROLOGUE nds32_asm_function_end_prologue + +#undef TARGET_ASM_FUNCTION_BEGIN_EPILOGUE +#define TARGET_ASM_FUNCTION_BEGIN_EPILOGUE nds32_asm_function_begin_epilogue + +#undef TARGET_ASM_FUNCTION_EPILOGUE +#define TARGET_ASM_FUNCTION_EPILOGUE nds32_asm_function_epilogue + +#undef TARGET_ASM_OUTPUT_MI_THUNK +#define TARGET_ASM_OUTPUT_MI_THUNK nds32_asm_output_mi_thunk + +#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK +#define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall + +/* -- Generating Code for Profiling. */ + +/* -- Permitting tail calls. */ + +#undef TARGET_WARN_FUNC_RETURN +#define TARGET_WARN_FUNC_RETURN nds32_warn_func_return + +/* Stack smashing protection. */ + + +/* Implementing the Varargs Macros. */ + +#undef TARGET_STRICT_ARGUMENT_NAMING +#define TARGET_STRICT_ARGUMENT_NAMING nds32_strict_argument_naming + + +/* Trampolines for Nested Functions. */ + +#undef TARGET_ASM_TRAMPOLINE_TEMPLATE +#define TARGET_ASM_TRAMPOLINE_TEMPLATE nds32_asm_trampoline_template + +#undef TARGET_TRAMPOLINE_INIT +#define TARGET_TRAMPOLINE_INIT nds32_trampoline_init + + +/* Implicit Calls to Library Routines. */ + + +/* Addressing Modes. */ + +#undef TARGET_LEGITIMATE_ADDRESS_P +#define TARGET_LEGITIMATE_ADDRESS_P nds32_legitimate_address_p + + +/* Anchored Addresses. */ + + +/* Condition Code Status. */ + +/* -- Representation of condition codes using (cc0). */ + +/* -- Representation of condition codes using registers. */ + +/* -- Macros to control conditional execution. */ + + +/* Describing Relative Costs of Operations. */ + +#undef TARGET_REGISTER_MOVE_COST +#define TARGET_REGISTER_MOVE_COST nds32_register_move_cost + +#undef TARGET_MEMORY_MOVE_COST +#define TARGET_MEMORY_MOVE_COST nds32_memory_move_cost + +#undef TARGET_RTX_COSTS +#define TARGET_RTX_COSTS nds32_rtx_costs + +#undef TARGET_ADDRESS_COST +#define TARGET_ADDRESS_COST nds32_address_cost + + +/* Adjusting the Instruction Scheduler. */ + + +/* Dividing the Output into Sections (Texts, Data, . . . ). */ + + +/* Position Independent Code. */ + + +/* Defining the Output Assembler Language. */ + +/* -- The Overall Framework of an Assembler File. */ + +#undef TARGET_ASM_FILE_START +#define TARGET_ASM_FILE_START nds32_asm_file_start +#undef TARGET_ASM_FILE_END +#define TARGET_ASM_FILE_END nds32_asm_file_end + +/* -- Output of Data. */ + +#undef TARGET_ASM_ALIGNED_HI_OP +#define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t" + +#undef TARGET_ASM_ALIGNED_SI_OP +#define TARGET_ASM_ALIGNED_SI_OP "\t.word\t" + +/* -- Output of Uninitialized Variables. */ + +/* -- Output and Generation of Labels. */ + +#undef TARGET_ASM_GLOBALIZE_LABEL +#define TARGET_ASM_GLOBALIZE_LABEL nds32_asm_globalize_label + +/* -- How Initialization Functions Are Handled. */ + +/* -- Macros Controlling Initialization Routines. */ + +/* -- Output of Assembler Instructions. */ + +#undef TARGET_PRINT_OPERAND +#define TARGET_PRINT_OPERAND nds32_print_operand +#undef TARGET_PRINT_OPERAND_ADDRESS +#define TARGET_PRINT_OPERAND_ADDRESS nds32_print_operand_address + +/* -- Output of Dispatch Tables. */ + +/* -- Assembler Commands for Exception Regions. */ + +/* -- Assembler Commands for Alignment. */ + + +/* Controlling Debugging Information Format. */ + +/* -- Macros Affecting All Debugging Formats. */ + +/* -- Specific Options for DBX Output. */ + +/* -- Open-Ended Hooks for DBX Format. */ + +/* -- File Names in DBX Format. */ + +/* -- Macros for SDB and DWARF Output. */ + +/* -- Macros for VMS Debug Format. */ + + +/* Cross Compilation and Floating Point. */ + + +/* Mode Switching Instructions. */ + + +/* Defining target-specific uses of __attribute__. */ + +#undef TARGET_ATTRIBUTE_TABLE +#define TARGET_ATTRIBUTE_TABLE nds32_attribute_table + +#undef TARGET_MERGE_DECL_ATTRIBUTES +#define TARGET_MERGE_DECL_ATTRIBUTES nds32_merge_decl_attributes + +#undef TARGET_INSERT_ATTRIBUTES +#define TARGET_INSERT_ATTRIBUTES nds32_insert_attributes + +#undef TARGET_OPTION_PRAGMA_PARSE +#define TARGET_OPTION_PRAGMA_PARSE nds32_option_pragma_parse + +#undef TARGET_OPTION_OVERRIDE +#define TARGET_OPTION_OVERRIDE nds32_option_override + + +/* Emulating TLS. */ + + +/* Defining coprocessor specifics for MIPS targets. */ + + +/* Parameters for Precompiled Header Validity Checking. */ + + +/* C++ ABI parameters. */ + + +/* Adding support for named address spaces. */ + + +/* Miscellaneous Parameters. */ + +#undef TARGET_INIT_BUILTINS +#define TARGET_INIT_BUILTINS nds32_init_builtins + +#undef TARGET_EXPAND_BUILTIN +#define TARGET_EXPAND_BUILTIN nds32_expand_builtin + + +/* ------------------------------------------------------------------------ */ + +/* Initialize the GCC target structure. */ + +struct gcc_target targetm = TARGET_INITIALIZER; + +/* ------------------------------------------------------------------------ */ diff --git a/gcc/config/nds32/nds32.h b/gcc/config/nds32/nds32.h new file mode 100644 index 00000000000..74f126cecc4 --- /dev/null +++ b/gcc/config/nds32/nds32.h @@ -0,0 +1,982 @@ +/* Definitions of target machine of Andes NDS32 cpu for GNU compiler + Copyright (C) 2012-2013 Free Software Foundation, Inc. + Contributed by Andes Technology Corporation. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GCC is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with GCC; see the file COPYING3. If not see + <http://www.gnu.org/licenses/>. */ + + +/* ------------------------------------------------------------------------ */ + +/* The following are auxiliary macros or structure declarations + that are used all over the nds32.c and nds32.h. */ + + +/* Computing the Length of an Insn. */ +#define ADJUST_INSN_LENGTH(INSN, LENGTH) \ + (LENGTH = nds32_adjust_insn_length (INSN, LENGTH)) + +/* Check instruction LS-37-FP-implied form. + Note: actually its immediate range is imm9u + since it is used for lwi37/swi37 instructions. */ +#define NDS32_LS_37_FP_P(rt, ra, imm) \ + (REGNO_REG_CLASS (REGNO (rt)) == LOW_REGS \ + && REGNO (ra) == FP_REGNUM \ + && satisfies_constraint_Iu09 (imm)) + +/* Check instruction LS-37-SP-implied form. + Note: actually its immediate range is imm9u + since it is used for lwi37/swi37 instructions. */ +#define NDS32_LS_37_SP_P(rt, ra, imm) \ + (REGNO_REG_CLASS (REGNO (rt)) == LOW_REGS \ + && REGNO (ra) == SP_REGNUM \ + && satisfies_constraint_Iu09 (imm)) + + +/* Check load/store instruction form : Rt3, Ra3, imm3u. */ +#define NDS32_LS_333_P(rt, ra, imm, mode) nds32_ls_333_p (rt, ra, imm, mode) + +/* Check load/store instruction form : Rt4, Ra5, const_int_0. + Note: no need to check ra because Ra5 means it covers all registers. */ +#define NDS32_LS_450_P(rt, ra, imm) \ + ((imm == const0_rtx) \ + && (REGNO_REG_CLASS (REGNO (rt)) == LOW_REGS \ + || REGNO_REG_CLASS (REGNO (rt)) == MIDDLE_REGS)) + +/* Check instruction RRI-333-form. */ +#define NDS32_RRI_333_P(rt, ra, imm) \ + (REGNO_REG_CLASS (REGNO (rt)) == LOW_REGS \ + && REGNO_REG_CLASS (REGNO (ra)) == LOW_REGS \ + && satisfies_constraint_Iu03 (imm)) + +/* Check instruction RI-45-form. */ +#define NDS32_RI_45_P(rt, ra, imm) \ + (REGNO (rt) == REGNO (ra) \ + && (REGNO_REG_CLASS (REGNO (rt)) == LOW_REGS \ + || REGNO_REG_CLASS (REGNO (rt)) == MIDDLE_REGS) \ + && satisfies_constraint_Iu05 (imm)) + + +/* Check instruction RR-33-form. */ +#define NDS32_RR_33_P(rt, ra) \ + (REGNO_REG_CLASS (REGNO (rt)) == LOW_REGS \ + && REGNO_REG_CLASS (REGNO (ra)) == LOW_REGS) + +/* Check instruction RRR-333-form. */ +#define NDS32_RRR_333_P(rt, ra, rb) \ + (REGNO_REG_CLASS (REGNO (rt)) == LOW_REGS \ + && REGNO_REG_CLASS (REGNO (ra)) == LOW_REGS \ + && REGNO_REG_CLASS (REGNO (rb)) == LOW_REGS) + +/* Check instruction RR-45-form. + Note: no need to check rb because Rb5 means it covers all registers. */ +#define NDS32_RR_45_P(rt, ra, rb) \ + (REGNO (rt) == REGNO (ra) \ + && (REGNO_REG_CLASS (REGNO (rt)) == LOW_REGS \ + || REGNO_REG_CLASS (REGNO (rt)) == MIDDLE_REGS)) + +/* Classifies address type to distinguish 16-bit/32-bit format. */ +enum nds32_16bit_address_type +{ + /* [reg]: 45 format address. */ + ADDRESS_REG, + /* [lo_reg + imm3u]: 333 format address. */ + ADDRESS_LO_REG_IMM3U, + /* post_inc [lo_reg + imm3u]: 333 format address. */ + ADDRESS_POST_INC_LO_REG_IMM3U, + /* [$fp + imm7u]: fp imply address. */ + ADDRESS_FP_IMM7U, + /* [$sp + imm7u]: sp imply address. */ + ADDRESS_SP_IMM7U, + /* Other address format. */ + ADDRESS_NOT_16BIT_FORMAT +}; + + +/* ------------------------------------------------------------------------ */ + +/* Define maximum numbers of registers for passing arguments. */ +#define NDS32_MAX_REGS_FOR_ARGS 6 + +/* Define the register number for first argument. */ +#define NDS32_GPR_ARG_FIRST_REGNUM 0 + +/* Define the register number for return value. */ +#define NDS32_GPR_RET_FIRST_REGNUM 0 + + +/* Define double word alignment bits. */ +#define NDS32_DOUBLE_WORD_ALIGNMENT 64 + +/* Define alignment checking macros for convenience. */ +#define NDS32_HALF_WORD_ALIGN_P(value) (((value) & 0x01) == 0) +#define NDS32_SINGLE_WORD_ALIGN_P(value) (((value) & 0x03) == 0) +#define NDS32_DOUBLE_WORD_ALIGN_P(value) (((value) & 0x07) == 0) + +/* Round X up to the nearest double word. */ +#define NDS32_ROUND_UP_DOUBLE_WORD(value) (((value) + 7) & ~7) + + +/* This macro is used to calculate the numbers of registers for + containing 'size' bytes of the argument. + The size of a register is a word in nds32 target. + So we use UNITS_PER_WORD to do the calculation. */ +#define NDS32_NEED_N_REGS_FOR_ARG(mode, type) \ + ((mode == BLKmode) \ + ? ((int_size_in_bytes (type) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) \ + : ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)) + +/* This macro is used to return the register number for passing argument. + We need to obey the following rules: + 1. If it is required MORE THAN one register, + make sure the register number is a even value. + 2. If it is required ONLY one register, + the register number can be odd or even value. */ +#define NDS32_AVAILABLE_REGNUM_FOR_ARG(reg_offset, mode, type) \ + ((NDS32_NEED_N_REGS_FOR_ARG (mode, type) > 1) \ + ? (((reg_offset) + NDS32_GPR_ARG_FIRST_REGNUM + 1) & ~1) \ + : ((reg_offset) + NDS32_GPR_ARG_FIRST_REGNUM)) + +/* This macro is to check if there are still available registers + for passing argument. */ +#define NDS32_ARG_PASS_IN_REG_P(reg_offset, mode, type) \ + (((reg_offset) < NDS32_MAX_REGS_FOR_ARGS) \ + && ((reg_offset) + NDS32_NEED_N_REGS_FOR_ARG (mode, type) \ + <= NDS32_MAX_REGS_FOR_ARGS)) + +/* This macro is to check if the register is required to be saved on stack. + If call_used_regs[regno] == 0, regno is the callee-saved register. + If df_regs_ever_live_p(regno) == true, it is used in the current function. + As long as the register satisfies both criteria above, + it is required to be saved. */ +#define NDS32_REQUIRED_CALLEE_SAVED_P(regno) \ + ((!call_used_regs[regno]) && (df_regs_ever_live_p (regno))) + +/* ------------------------------------------------------------------------ */ + +/* A C structure for machine-specific, per-function data. + This is added to the cfun structure. */ +struct GTY(()) machine_function +{ + /* Number of bytes allocated on the stack for variadic args + if we want to push them into stack as pretend arguments by ourself. */ + int va_args_size; + /* Number of bytes reserved on the stack for + local and temporary variables. */ + int local_size; + /* Number of bytes allocated on the stack for outgoing arguments. */ + int out_args_size; + + /* Number of bytes on the stack for saving $fp. */ + int fp_size; + /* Number of bytes on the stack for saving $gp. */ + int gp_size; + /* Number of bytes on the stack for saving $lp. */ + int lp_size; + + /* Number of bytes on the stack for saving callee-saved registers. */ + int callee_saved_regs_size; + /* The padding bytes in callee-saved area may be required. */ + int callee_saved_area_padding_bytes; + + /* The first required register that should be saved on stack + for va_args (one named argument + nameless arguments). */ + int va_args_first_regno; + /* The last required register that should be saved on stack + for va_args (one named argument + nameless arguments). */ + int va_args_last_regno; + + /* The first required callee-saved register. */ + int callee_saved_regs_first_regno; + /* The last required callee-saved register. */ + int callee_saved_regs_last_regno; + + /* Indicate that whether this function needs + prologue/epilogue code generation. */ + int naked_p; + /* Indicate that whether this function + uses fp_as_gp optimization. */ + int fp_as_gp_p; +}; + +/* A C structure that contains the arguments information. */ +typedef struct +{ + unsigned int reg_offset; +} nds32_cumulative_args; + +/* ------------------------------------------------------------------------ */ + +/* The following we define C-ISR related stuff. + In nds32 architecture, we have 73 vectors for interrupt/exception. + For each vector (except for vector 0, which is used for reset behavior), + we allow users to set its register saving scheme and interrupt level. */ + +/* There are 73 vectors in nds32 architecture. + 0 for reset handler, + 1-8 for exception handler, + and 9-72 for interrupt handler. + We use an array, which is defined in nds32.c, to record + essential information for each vector. */ +#define NDS32_N_ISR_VECTORS 73 + +/* Define possible isr category. */ +enum nds32_isr_category +{ + NDS32_ISR_NONE, + NDS32_ISR_INTERRUPT, + NDS32_ISR_EXCEPTION, + NDS32_ISR_RESET +}; + +/* Define isr register saving scheme. */ +enum nds32_isr_save_reg +{ + NDS32_SAVE_ALL, + NDS32_PARTIAL_SAVE +}; + +/* Define isr nested type. */ +enum nds32_isr_nested_type +{ + NDS32_NESTED, + NDS32_NOT_NESTED, + NDS32_NESTED_READY +}; + +/* Define structure to record isr information. + The isr vector array 'isr_vectors[]' with this structure + is defined in nds32.c. */ +struct nds32_isr_info +{ + /* The field to identify isr category. + It should be set to NDS32_ISR_NONE by default. + If user specifies a function as isr by using attribute, + this field will be set accordingly. */ + enum nds32_isr_category category; + + /* A string for the applied function name. + It should be set to empty string by default. */ + char func_name[100]; + + /* The register saving scheme. + It should be set to NDS32_PARTIAL_SAVE by default + unless user specifies attribute to change it. */ + enum nds32_isr_save_reg save_reg; + + /* The nested type. + It should be set to NDS32_NOT_NESTED by default + unless user specifies attribute to change it. */ + enum nds32_isr_nested_type nested_type; + + /* Total vectors. + The total vectors = interrupt + exception numbers + reset. + It should be set to 0 by default. + This field is ONLY used in NDS32_ISR_RESET category. */ + unsigned int total_n_vectors; + + /* A string for nmi handler name. + It should be set to empty string by default. + This field is ONLY used in NDS32_ISR_RESET category. */ + char nmi_name[100]; + + /* A string for warm handler name. + It should be set to empty string by default. + This field is ONLY used in NDS32_ISR_RESET category. */ + char warm_name[100]; +}; + +/* ------------------------------------------------------------------------ */ + +/* Define code for all nds32 builtins. */ +enum nds32_builtins +{ + NDS32_BUILTIN_ISYNC, + NDS32_BUILTIN_ISB, + NDS32_BUILTIN_MFSR, + NDS32_BUILTIN_MFUSR, + NDS32_BUILTIN_MTSR, + NDS32_BUILTIN_MTUSR, + NDS32_BUILTIN_SETGIE_EN, + NDS32_BUILTIN_SETGIE_DIS +}; + +/* ------------------------------------------------------------------------ */ + +#define TARGET_ISA_V2 (nds32_arch_option == ARCH_V2) +#define TARGET_ISA_V3 (nds32_arch_option == ARCH_V3) +#define TARGET_ISA_V3M (nds32_arch_option == ARCH_V3M) + +/* ------------------------------------------------------------------------ */ + +/* Controlling the Compilation Driver. */ + +#define OPTION_DEFAULT_SPECS \ + {"arch", "%{!march=*:-march=%(VALUE)}" } + +#define CC1_SPEC \ + "" + +#define ASM_SPEC \ + " %{mbig-endian:-EB} %{mlittle-endian:-EL}" + +/* If user issues -mrelax, -mforce-fp-as-gp, or -mex9, + we need to pass '--relax' to linker. + Besides, for -mex9, we need to further pass '--mex9'. */ +#define LINK_SPEC \ + " %{mbig-endian:-EB} %{mlittle-endian:-EL}" \ + " %{mrelax|mforce-fp-as-gp|mex9:--relax}" \ + " %{mex9:--mex9}" + +#define LIB_SPEC \ + " -lc -lgloss" + +/* The option -mno-ctor-dtor can disable constructor/destructor feature + by applying different crt stuff. In the convention, crt0.o is the + startup file without constructor/destructor; + crt1.o, crti.o, crtbegin.o, crtend.o, and crtn.o are the + startup files with constructor/destructor. + Note that crt0.o, crt1.o, crti.o, and crtn.o are provided + by newlib/mculib/glibc/ublic, while crtbegin.o and crtend.o are + currently provided by GCC for nds32 target. + + For nds32 target so far: + If -mno-ctor-dtor, we are going to link + "crt0.o [user objects]". + If general cases, we are going to link + "crt1.o crtbegin1.o [user objects] crtend1.o". */ +#define STARTFILE_SPEC \ + " %{!mno-ctor-dtor:crt1.o%s;:crt0.o%s}" \ + " %{!mno-ctor-dtor:crtbegin1.o%s}" +#define ENDFILE_SPEC \ + " %{!mno-ctor-dtor:crtend1.o%s}" + +/* The TARGET_BIG_ENDIAN_DEFAULT is defined if we configure gcc + with --target=nds32be-* setting. + Check gcc/config.gcc for more information. + In addition, currently we only have elf toolchain, + where mgp-direct is always the default. */ +#ifdef TARGET_BIG_ENDIAN_DEFAULT +#define MULTILIB_DEFAULTS { "mbig-endian", "mgp-direct" } +#else +#define MULTILIB_DEFAULTS { "mlittle-endian", "mgp-direct" } +#endif + + +/* Run-time Target Specification. */ + +#define TARGET_CPU_CPP_BUILTINS() \ + do \ + { \ + builtin_define ("__nds32__"); \ + \ + if (TARGET_ISA_V2) \ + builtin_define ("__NDS32_ISA_V2__"); \ + if (TARGET_ISA_V3) \ + builtin_define ("__NDS32_ISA_V3__"); \ + if (TARGET_ISA_V3M) \ + builtin_define ("__NDS32_ISA_V3M__"); \ + \ + if (TARGET_BIG_ENDIAN) \ + builtin_define ("__big_endian__"); \ + if (TARGET_REDUCED_REGS) \ + builtin_define ("__NDS32_REDUCED_REGS__"); \ + if (TARGET_CMOV) \ + builtin_define ("__NDS32_CMOV__"); \ + if (TARGET_PERF_EXT) \ + builtin_define ("__NDS32_PERF_EXT__"); \ + if (TARGET_16_BIT) \ + builtin_define ("__NDS32_16_BIT__"); \ + if (TARGET_GP_DIRECT) \ + builtin_define ("__NDS32_GP_DIRECT__"); \ + \ + builtin_assert ("cpu=nds32"); \ + builtin_assert ("machine=nds32"); \ + } while (0) + + +/* Defining Data Structures for Per-function Information. */ + +/* This macro is called once per function, + before generation of any RTL has begun. */ +#define INIT_EXPANDERS nds32_init_expanders () + + +/* Storage Layout. */ + +#define BITS_BIG_ENDIAN 0 + +#define BYTES_BIG_ENDIAN (TARGET_BIG_ENDIAN) + +#define WORDS_BIG_ENDIAN (TARGET_BIG_ENDIAN) + +#define UNITS_PER_WORD 4 + +#define PROMOTE_MODE(m, unsignedp, type) \ + if (GET_MODE_CLASS (m) == MODE_INT && GET_MODE_SIZE (m) < UNITS_PER_WORD) \ + { \ + (m) = SImode; \ + } + +#define PARM_BOUNDARY 32 + +#define STACK_BOUNDARY 64 + +#define FUNCTION_BOUNDARY 32 + +#define BIGGEST_ALIGNMENT 64 + +#define EMPTY_FIELD_BOUNDARY 32 + +#define STRUCTURE_SIZE_BOUNDARY 8 + +#define STRICT_ALIGNMENT 1 + +#define PCC_BITFIELD_TYPE_MATTERS 1 + + +/* Layout of Source Language Data Types. */ + +#define INT_TYPE_SIZE 32 +#define SHORT_TYPE_SIZE 16 +#define LONG_TYPE_SIZE 32 +#define LONG_LONG_TYPE_SIZE 64 + +#define FLOAT_TYPE_SIZE 32 +#define DOUBLE_TYPE_SIZE 64 +#define LONG_DOUBLE_TYPE_SIZE 64 + +#define DEFAULT_SIGNED_CHAR 1 + +#define SIZE_TYPE "long unsigned int" +#define PTRDIFF_TYPE "long int" +#define WCHAR_TYPE "short unsigned int" +#define WCHAR_TYPE_SIZE 16 + + +/* Register Usage. */ + +/* Number of actual hardware registers. + The hardware registers are assigned numbers for the compiler + from 0 to just below FIRST_PSEUDO_REGISTER. + All registers that the compiler knows about must be given numbers, + even those that are not normally considered general registers. */ +#define FIRST_PSEUDO_REGISTER 34 + +/* An initializer that says which registers are used for fixed + purposes all throughout the compiled code and are therefore + not available for general allocation. + + $r28 : $fp + $r29 : $gp + $r30 : $lp + $r31 : $sp + + caller-save registers: $r0 ~ $r5, $r16 ~ $r23 + callee-save registers: $r6 ~ $r10, $r11 ~ $r14 + + reserved for assembler : $r15 + reserved for other use : $r24, $r25, $r26, $r27 */ +#define FIXED_REGISTERS \ +{ /* r0 r1 r2 r3 r4 r5 r6 r7 */ \ + 0, 0, 0, 0, 0, 0, 0, 0, \ + /* r8 r9 r10 r11 r12 r13 r14 r15 */ \ + 0, 0, 0, 0, 0, 0, 0, 1, \ + /* r16 r17 r18 r19 r20 r21 r22 r23 */ \ + 0, 0, 0, 0, 0, 0, 0, 0, \ + /* r24 r25 r26 r27 r28 r29 r30 r31 */ \ + 1, 1, 1, 1, 0, 1, 0, 1, \ + /* ARG_POINTER:32 */ \ + 1, \ + /* FRAME_POINTER:33 */ \ + 1 \ +} + +/* Identifies the registers that are not available for + general allocation of values that must live across + function calls -- so they are caller-save registers. + + 0 : callee-save registers + 1 : caller-save registers */ +#define CALL_USED_REGISTERS \ +{ /* r0 r1 r2 r3 r4 r5 r6 r7 */ \ + 1, 1, 1, 1, 1, 1, 0, 0, \ + /* r8 r9 r10 r11 r12 r13 r14 r15 */ \ + 0, 0, 0, 0, 0, 0, 0, 1, \ + /* r16 r17 r18 r19 r20 r21 r22 r23 */ \ + 1, 1, 1, 1, 1, 1, 1, 1, \ + /* r24 r25 r26 r27 r28 r29 r30 r31 */ \ + 1, 1, 1, 1, 0, 1, 0, 1, \ + /* ARG_POINTER:32 */ \ + 1, \ + /* FRAME_POINTER:33 */ \ + 1 \ +} + +/* In nds32 target, we have three levels of registers: + LOW_COST_REGS : $r0 ~ $r7 + MIDDLE_COST_REGS : $r8 ~ $r11, $r16 ~ $r19 + HIGH_COST_REGS : $r12 ~ $r14, $r20 ~ $r31 */ +#define REG_ALLOC_ORDER \ +{ \ + 0, 1, 2, 3, 4, 5, 6, 7, \ + 8, 9, 10, 11, 16, 17, 18, 19, \ + 12, 13, 14, 15, 20, 21, 22, 23, \ + 24, 25, 26, 27, 28, 29, 30, 31, \ + 32, \ + 33 \ +} + +/* Tell IRA to use the order we define rather than messing it up with its + own cost calculations. */ +#define HONOR_REG_ALLOC_ORDER + +/* The number of consecutive hard regs needed starting at + reg "regno" for holding a value of mode "mode". */ +#define HARD_REGNO_NREGS(regno, mode) nds32_hard_regno_nregs (regno, mode) + +/* Value is 1 if hard register "regno" can hold a value + of machine-mode "mode". */ +#define HARD_REGNO_MODE_OK(regno, mode) nds32_hard_regno_mode_ok (regno, mode) + +/* A C expression that is nonzero if a value of mode1 + is accessible in mode2 without copying. + Define this macro to return nonzero in as many cases as possible + since doing so will allow GCC to perform better register allocation. + We can use general registers to tie QI/HI/SI modes together. */ +#define MODES_TIEABLE_P(mode1, mode2) \ + (GET_MODE_CLASS (mode1) == MODE_INT \ + && GET_MODE_CLASS (mode2) == MODE_INT \ + && GET_MODE_SIZE (mode1) <= UNITS_PER_WORD \ + && GET_MODE_SIZE (mode2) <= UNITS_PER_WORD) + + +/* Register Classes. */ + +/* In nds32 target, we have three levels of registers: + Low cost regsiters : $r0 ~ $r7 + Middle cost registers : $r8 ~ $r11, $r16 ~ $r19 + High cost registers : $r12 ~ $r14, $r20 ~ $r31 + + In practice, we have MIDDLE_REGS cover LOW_REGS register class contents + so that it provides more chance to use low cost registers. */ +enum reg_class +{ + NO_REGS, + R15_TA_REG, + STACK_REG, + LOW_REGS, + MIDDLE_REGS, + HIGH_REGS, + GENERAL_REGS, + FRAME_REGS, + ALL_REGS, + LIM_REG_CLASSES +}; + +#define N_REG_CLASSES (int) LIM_REG_CLASSES + +#define REG_CLASS_NAMES \ +{ \ + "NO_REGS", \ + "R15_TA_REG", \ + "STACK_REG", \ + "LOW_REGS", \ + "MIDDLE_REGS", \ + "HIGH_REGS", \ + "GENERAL_REGS", \ + "FRAME_REGS", \ + "ALL_REGS" \ +} + +#define REG_CLASS_CONTENTS \ +{ \ + {0x00000000, 0x00000000}, /* NO_REGS : */ \ + {0x00008000, 0x00000000}, /* R15_TA_REG : 15 */ \ + {0x80000000, 0x00000000}, /* STACK_REG : 31 */ \ + {0x000000ff, 0x00000000}, /* LOW_REGS : 0-7 */ \ + {0x000f0fff, 0x00000000}, /* MIDDLE_REGS : 0-11, 16-19 */ \ + {0xfff07000, 0x00000000}, /* HIGH_REGS : 12-14, 20-31 */ \ + {0xffffffff, 0x00000000}, /* GENERAL_REGS: 0-31 */ \ + {0x00000000, 0x00000003}, /* FRAME_REGS : 32, 33 */ \ + {0xffffffff, 0x00000003} /* ALL_REGS : 0-31, 32, 33 */ \ +} + +#define REGNO_REG_CLASS(regno) nds32_regno_reg_class (regno) + +#define BASE_REG_CLASS GENERAL_REGS +#define INDEX_REG_CLASS GENERAL_REGS + +/* Return nonzero if it is suitable for use as a + base register in operand addresses. + So far, we return nonzero only if "num" is a hard reg + of the suitable class or a pseudo register which is + allocated to a suitable hard reg. */ +#define REGNO_OK_FOR_BASE_P(num) \ + ((num) < 32 || (unsigned) reg_renumber[num] < 32) + +/* Return nonzero if it is suitable for use as a + index register in operand addresses. + So far, we return nonzero only if "num" is a hard reg + of the suitable class or a pseudo register which is + allocated to a suitable hard reg. + The difference between an index register and a base register is that + the index register may be scaled. */ +#define REGNO_OK_FOR_INDEX_P(num) \ + ((num) < 32 || (unsigned) reg_renumber[num] < 32) + + +/* Obsolete Macros for Defining Constraints. */ + + +/* Stack Layout and Calling Conventions. */ + +#define STACK_GROWS_DOWNWARD + +#define FRAME_GROWS_DOWNWARD 1 + +#define STARTING_FRAME_OFFSET 0 + +#define STACK_POINTER_OFFSET 0 + +#define FIRST_PARM_OFFSET(fundecl) 0 + +#define RETURN_ADDR_RTX(count, frameaddr) \ + nds32_return_addr_rtx (count, frameaddr) + +/* A C expression whose value is RTL representing the location + of the incoming return address at the beginning of any function + before the prologue. + If this RTL is REG, you should also define + DWARF_FRAME_RETURN_COLUMN to DWARF_FRAME_REGNUM (REGNO). */ +#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (Pmode, LP_REGNUM) +#define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGNUM (LP_REGNUM) + +#define STACK_POINTER_REGNUM SP_REGNUM + +#define FRAME_POINTER_REGNUM 33 + +#define HARD_FRAME_POINTER_REGNUM FP_REGNUM + +#define ARG_POINTER_REGNUM 32 + +#define STATIC_CHAIN_REGNUM 16 + +#define ELIMINABLE_REGS \ +{ { ARG_POINTER_REGNUM, STACK_POINTER_REGNUM }, \ + { ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM }, \ + { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM }, \ + { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM } } + +#define INITIAL_ELIMINATION_OFFSET(from_reg, to_reg, offset_var) \ + (offset_var) = nds32_initial_elimination_offset (from_reg, to_reg) + +#define ACCUMULATE_OUTGOING_ARGS 1 + +#define OUTGOING_REG_PARM_STACK_SPACE(fntype) 1 + +#define CUMULATIVE_ARGS nds32_cumulative_args + +#define INIT_CUMULATIVE_ARGS(cum, fntype, libname, fndecl, n_named_args) \ + nds32_init_cumulative_args (&cum, fntype, libname, fndecl, n_named_args) + +/* The REGNO is an unsigned integer but NDS32_GPR_ARG_FIRST_REGNUM may be 0. + We better cast REGNO into signed integer so that we can avoid + 'comparison of unsigned expression >= 0 is always true' warning. */ +#define FUNCTION_ARG_REGNO_P(regno) \ + (((int) regno - NDS32_GPR_ARG_FIRST_REGNUM >= 0) \ + && ((int) regno - NDS32_GPR_ARG_FIRST_REGNUM < NDS32_MAX_REGS_FOR_ARGS)) + +#define DEFAULT_PCC_STRUCT_RETURN 0 + +/* EXIT_IGNORE_STACK should be nonzero if, when returning + from a function, the stack pointer does not matter. + The value is tested only in functions that have frame pointers. + In nds32 target, the function epilogue recovers the + stack pointer from the frame. */ +#define EXIT_IGNORE_STACK 1 + +#define FUNCTION_PROFILER(file, labelno) \ + fprintf (file, "/* profiler %d */", (labelno)) + + +/* Implementing the Varargs Macros. */ + + +/* Trampolines for Nested Functions. */ + +/* Giving A-function and B-function, + if B-function wants to call A-function's nested function, + we need to fill trampoline code into A-function's stack + so that B-function can execute the code in stack to indirectly + jump to (like 'trampoline' action) desired nested function. + + The trampoline code for nds32 target must contains following parts: + + 1. instructions (4 * 4 = 16 bytes): + get $pc first + load chain_value to static chain register via $pc + load nested function address to $r15 via $pc + jump to desired nested function via $r15 + 2. data (4 * 2 = 8 bytes): + chain_value + nested function address + + Please check nds32.c implementation for more information. */ +#define TRAMPOLINE_SIZE 24 + +/* Because all instructions/data in trampoline template are 4-byte size, + we set trampoline alignment 8*4=32 bits. */ +#define TRAMPOLINE_ALIGNMENT 32 + + +/* Implicit Calls to Library Routines. */ + + +/* Addressing Modes. */ + +/* We can use "LWI.bi Rt, [Ra], 4" to support post increment. */ +#define HAVE_POST_INCREMENT 1 +/* We can use "LWI.bi Rt, [Ra], -4" to support post decrement. */ +#define HAVE_POST_DECREMENT 1 + +/* We have "LWI.bi Rt, [Ra], imm" instruction form. */ +#define HAVE_POST_MODIFY_DISP 1 +/* We have "LW.bi Rt, [Ra], Rb" instruction form. */ +#define HAVE_POST_MODIFY_REG 1 + +#define CONSTANT_ADDRESS_P(x) (CONSTANT_P (x) && GET_CODE (x) != CONST_DOUBLE) + +#define MAX_REGS_PER_ADDRESS 2 + + +/* Anchored Addresses. */ + + +/* Condition Code Status. */ + + +/* Describing Relative Costs of Operations. */ + +/* A C expression for the cost of a branch instruction. + A value of 1 is the default; + other values are interpreted relative to that. */ +#define BRANCH_COST(speed_p, predictable_p) ((speed_p) ? 2 : 0) + +#define SLOW_BYTE_ACCESS 1 + +#define NO_FUNCTION_CSE + + +/* Adjusting the Instruction Scheduler. */ + + +/* Dividing the Output into Sections (Texts, Data, . . . ). */ + +#define TEXT_SECTION_ASM_OP "\t.text" +#define DATA_SECTION_ASM_OP "\t.data" + +/* Currently, nds32 assembler does NOT handle '.bss' pseudo-op. + So we use '.section .bss' alternatively. */ +#define BSS_SECTION_ASM_OP "\t.section\t.bss" + +/* Define this macro to be an expression with a nonzero value if jump tables + (for tablejump insns) should be output in the text section, + along with the assembler instructions. + Otherwise, the readonly data section is used. */ +#define JUMP_TABLES_IN_TEXT_SECTION 1 + + +/* Position Independent Code. */ + + +/* Defining the Output Assembler Language. */ + +#define ASM_COMMENT_START "!" + +#define ASM_APP_ON "! #APP" + +#define ASM_APP_OFF "! #NO_APP\n" + +#define ASM_OUTPUT_LABELREF(stream, name) \ + asm_fprintf (stream, "%U%s", (*targetm.strip_name_encoding) (name)) + +#define ASM_OUTPUT_SYMBOL_REF(stream, sym) \ + assemble_name (stream, XSTR (sym, 0)) + +#define ASM_OUTPUT_LABEL_REF(stream, buf) \ + assemble_name (stream, buf) + +#define LOCAL_LABEL_PREFIX "." + +#define REGISTER_NAMES \ +{ \ + "$r0", "$r1", "$r2", "$r3", "$r4", "$r5", "$r6", "$r7", \ + "$r8", "$r9", "$r10", "$r11", "$r12", "$r13", "$r14", "$ta", \ + "$r16", "$r17", "$r18", "$r19", "$r20", "$r21", "$r22", "$r23", \ + "$r24", "$r25", "$r26", "$r27", "$fp", "$gp", "$lp", "$sp", \ + "$AP", \ + "$SFP" \ +} + +/* Output normal jump table entry. */ +#define ASM_OUTPUT_ADDR_VEC_ELT(stream, value) \ + asm_fprintf (stream, "\t.word\t%LL%d\n", value) + +/* Output pc relative jump table entry. */ +#define ASM_OUTPUT_ADDR_DIFF_ELT(stream, body, value, rel) \ + do \ + { \ + switch (GET_MODE (body)) \ + { \ + case QImode: \ + asm_fprintf (stream, "\t.byte\t.L%d-.L%d\n", value, rel); \ + break; \ + case HImode: \ + asm_fprintf (stream, "\t.short\t.L%d-.L%d\n", value, rel); \ + break; \ + case SImode: \ + asm_fprintf (stream, "\t.word\t.L%d-.L%d\n", value, rel); \ + break; \ + default: \ + gcc_unreachable(); \ + } \ + } while (0) + +/* We have to undef it first because elfos.h formerly define it + check gcc/config.gcc and gcc/config/elfos.h for more information. */ +#undef ASM_OUTPUT_CASE_LABEL +#define ASM_OUTPUT_CASE_LABEL(stream, prefix, num, table) \ + do \ + { \ + asm_fprintf (stream, "\t! Jump Table Begin\n"); \ + (*targetm.asm_out.internal_label) (stream, prefix, num); \ + } while (0) + +#define ASM_OUTPUT_CASE_END(stream, num, table) \ + do \ + { \ + /* Because our jump table is in text section, \ + we need to make sure 2-byte alignment after \ + the jump table for instructions fetch. */ \ + if (GET_MODE (PATTERN (table)) == QImode) \ + ASM_OUTPUT_ALIGN (stream, 1); \ + asm_fprintf (stream, "\t! Jump Table End\n"); \ + } while (0) + +/* This macro is not documented yet. + But we do need it to make jump table vector aligned. */ +#define ADDR_VEC_ALIGN(JUMPTABLE) 2 + +#define DWARF2_UNWIND_INFO 1 + +#define JUMP_ALIGN(x) \ + (align_jumps_log ? align_jumps_log : nds32_target_alignment (x)) + +#define LOOP_ALIGN(x) \ + (align_loops_log ? align_loops_log : nds32_target_alignment (x)) + +#define LABEL_ALIGN(x) \ + (align_labels_log ? align_labels_log : nds32_target_alignment (x)) + +#define ASM_OUTPUT_ALIGN(stream, power) \ + fprintf (stream, "\t.align\t%d\n", power) + + +/* Controlling Debugging Information Format. */ + +#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG + +#define DWARF2_DEBUGGING_INFO 1 + +#define DWARF2_ASM_LINE_DEBUG_INFO 1 + + +/* Cross Compilation and Floating Point. */ + + +/* Mode Switching Instructions. */ + + +/* Defining target-specific uses of __attribute__. */ + + +/* Emulating TLS. */ + + +/* Defining coprocessor specifics for MIPS targets. */ + + +/* Parameters for Precompiled Header Validity Checking. */ + + +/* C++ ABI parameters. */ + + +/* Adding support for named address spaces. */ + + +/* Miscellaneous Parameters. */ + +/* This is the machine mode that elements of a jump-table should have. */ +#define CASE_VECTOR_MODE Pmode + +/* Return the preferred mode for and addr_diff_vec when the mininum + and maximum offset are known. */ +#define CASE_VECTOR_SHORTEN_MODE(min_offset, max_offset, body) \ + ((min_offset < 0 || max_offset >= 0x2000 ) ? SImode \ + : (max_offset >= 100) ? HImode \ + : QImode) + +/* Generate pc relative jump table when -fpic or -Os. */ +#define CASE_VECTOR_PC_RELATIVE (flag_pic || optimize_size) + +/* Define this macro if operations between registers with integral mode + smaller than a word are always performed on the entire register. */ +#define WORD_REGISTER_OPERATIONS + +/* A C expression indicating when insns that read memory in mem_mode, + an integral mode narrower than a word, set the bits outside of mem_mode + to be either the sign-extension or the zero-extension of the data read. */ +#define LOAD_EXTEND_OP(MODE) ZERO_EXTEND + +/* The maximum number of bytes that a single instruction can move quickly + between memory and registers or between two memory locations. */ +#define MOVE_MAX 4 + +/* A C expression that is nonzero if on this machine the number of bits + actually used for the count of a shift operation is equal to the number + of bits needed to represent the size of the object being shifted. */ +#define SHIFT_COUNT_TRUNCATED 1 + +/* A C expression which is nonzero if on this machine it is safe to "convert" + an integer of 'inprec' bits to one of 'outprec' bits by merely operating + on it as if it had only 'outprec' bits. */ +#define TRULY_NOOP_TRUNCATION(outprec, inprec) 1 + +/* A C expression describing the value returned by a comparison operator with + an integral mode and stored by a store-flag instruction ('cstoremode4') + when the condition is true. */ +#define STORE_FLAG_VALUE 1 + +/* An alias for the machine mode for pointers. */ +#define Pmode SImode + +/* An alias for the machine mode used for memory references to functions + being called, in call RTL expressions. */ +#define FUNCTION_MODE SImode + +/* ------------------------------------------------------------------------ */ diff --git a/gcc/config/nds32/nds32.md b/gcc/config/nds32/nds32.md new file mode 100644 index 00000000000..4a832eaf86b --- /dev/null +++ b/gcc/config/nds32/nds32.md @@ -0,0 +1,2221 @@ +;; Machine description of Andes NDS32 cpu for GNU compiler +;; Copyright (C) 2012-2013 Free Software Foundation, Inc. +;; Contributed by Andes Technology Corporation. +;; +;; This file is part of GCC. +;; +;; GCC is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published +;; by the Free Software Foundation; either version 3, or (at your +;; option) any later version. +;; +;; GCC is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with GCC; see the file COPYING3. If not see +;; <http://www.gnu.org/licenses/>. + +;; See file "rtl.def" for documentation on define_insn, match_*, et. al. + +;; Include predicates definition. +(include "predicates.md") + +;; Include constraints definition. +(include "constraints.md") + +;; Include iterators definition. +(include "iterators.md") + +;; Include pipelines definition. +(include "pipelines.md") + + +;; Include constants definition. +(include "constants.md") + + +;; Include intrinsic functions definition. +(include "nds32-intrinsic.md") + +;; Include block move for nds32 multiple load/store behavior. +(include "nds32-multiple.md") + +;; Include DImode/DFmode operations. +(include "nds32-doubleword.md") + +;; Include peephole patterns. +(include "nds32-peephole2.md") + + +;; Insn type, it is used to default other attribute values. +(define_attr "type" + "unknown,move,load,store,alu,compare,branch,call,misc" + (const_string "unknown")) + + +;; Length, in bytes, default is 4-bytes. +(define_attr "length" "" (const_int 4)) + + +;; Enabled, which is used to enable/disable insn alternatives. +;; Note that we use length and TARGET_16_BIT here as criteria. +;; If the instruction pattern already check TARGET_16_BIT to +;; determine the length by itself, its enabled attribute should be +;; always 1 to avoid the conflict with the settings here. +(define_attr "enabled" "" + (cond [(and (eq_attr "length" "2") + (match_test "!TARGET_16_BIT")) + (const_int 0)] + (const_int 1))) + + +;; ---------------------------------------------------------------------------- + + +;; Move instructions. + +;; For QImode and HImode, the immediate value can be fit in imm20s. +;; So there is no need to split rtx for QI and HI patterns. + +(define_expand "movqi" + [(set (match_operand:QI 0 "general_operand" "") + (match_operand:QI 1 "general_operand" ""))] + "" +{ + /* Need to force register if mem <- !reg. */ + if (MEM_P (operands[0]) && !REG_P (operands[1])) + operands[1] = force_reg (QImode, operands[1]); +}) + +(define_expand "movhi" + [(set (match_operand:HI 0 "general_operand" "") + (match_operand:HI 1 "general_operand" ""))] + "" +{ + /* Need to force register if mem <- !reg. */ + if (MEM_P (operands[0]) && !REG_P (operands[1])) + operands[1] = force_reg (HImode, operands[1]); +}) + +(define_expand "movsi" + [(set (match_operand:SI 0 "general_operand" "") + (match_operand:SI 1 "general_operand" ""))] + "" +{ + /* Need to force register if mem <- !reg. */ + if (MEM_P (operands[0]) && !REG_P (operands[1])) + operands[1] = force_reg (SImode, operands[1]); + + /* If operands[1] is a large constant and cannot be performed + by a single instruction, we need to split it. */ + if (CONST_INT_P (operands[1]) + && !satisfies_constraint_Is20 (operands[1]) + && !satisfies_constraint_Ihig (operands[1])) + { + rtx high20_rtx; + HOST_WIDE_INT low12_int; + rtx tmp_rtx; + + tmp_rtx = can_create_pseudo_p () ? gen_reg_rtx (SImode) : operands[0]; + + high20_rtx = gen_int_mode ((INTVAL (operands[1]) >> 12) << 12, SImode); + low12_int = INTVAL (operands[1]) & 0xfff; + + emit_move_insn (tmp_rtx, high20_rtx); + emit_move_insn (operands[0], plus_constant (SImode, + tmp_rtx, + low12_int)); + DONE; + } +}) + +(define_insn "*mov<mode>" + [(set (match_operand:QIHISI 0 "nonimmediate_operand" "=r, r, U45, U33, U37, U45, m, l, l, l, d, r, d, r, r, r") + (match_operand:QIHISI 1 "nds32_move_operand" " r, r, l, l, l, d, r, U45, U33, U37, U45, m, Ip05, Is05, Is20, Ihig"))] + "" +{ + switch (which_alternative) + { + case 0: + return "mov55\t%0, %1"; + case 1: + return "ori\t%0, %1, 0"; + case 2: + case 3: + case 4: + case 5: + return nds32_output_16bit_store (operands, <byte>); + case 6: + return nds32_output_32bit_store (operands, <byte>); + case 7: + case 8: + case 9: + case 10: + return nds32_output_16bit_load (operands, <byte>); + case 11: + return nds32_output_32bit_load (operands, <byte>); + case 12: + return "movpi45\t%0, %1"; + case 13: + return "movi55\t%0, %1"; + case 14: + return "movi\t%0, %1"; + case 15: + return "sethi\t%0, hi20(%1)"; + default: + gcc_unreachable (); + } +} + [(set_attr "type" "alu,alu,store,store,store,store,store,load,load,load,load,load,alu,alu,alu,alu") + (set_attr "length" " 2, 4, 2, 2, 2, 2, 4, 2, 2, 2, 2, 4, 2, 2, 4, 4")]) + + +;; We use nds32_symbolic_operand to limit that only CONST/SYMBOL_REF/LABEL_REF +;; are able to match such instruction template. +(define_insn "*move_addr" + [(set (match_operand:SI 0 "register_operand" "=l, r") + (match_operand:SI 1 "nds32_symbolic_operand" " i, i"))] + "" + "la\t%0, %1" + [(set_attr "type" "move") + (set_attr "length" "8")]) + + +(define_insn "*sethi" + [(set (match_operand:SI 0 "register_operand" "=r") + (high:SI (match_operand:SI 1 "nds32_symbolic_operand" " i")))] + "" + "sethi\t%0, hi20(%1)" + [(set_attr "type" "alu") + (set_attr "length" "4")]) + + +(define_insn "*lo_sum" + [(set (match_operand:SI 0 "register_operand" "=r") + (lo_sum:SI (match_operand:SI 1 "register_operand" " r") + (match_operand:SI 2 "nds32_symbolic_operand" " i")))] + "" + "ori\t%0, %1, lo12(%2)" + [(set_attr "type" "alu") + (set_attr "length" "4")]) + + +;; ---------------------------------------------------------------------------- + +;; Zero extension instructions. + +(define_insn "zero_extend<mode>si2" + [(set (match_operand:SI 0 "register_operand" "=l, r, l, *r") + (zero_extend:SI (match_operand:QIHI 1 "nonimmediate_operand" " l, r, U33, m")))] + "" +{ + switch (which_alternative) + { + case 0: + return "ze<size>33\t%0, %1"; + case 1: + return "ze<size>\t%0, %1"; + case 2: + return nds32_output_16bit_load (operands, <byte>); + case 3: + return nds32_output_32bit_load (operands, <byte>); + + default: + gcc_unreachable (); + } +} + [(set_attr "type" "alu,alu,load,load") + (set_attr "length" " 2, 4, 2, 4")]) + + +;; Sign extension instructions. + +(define_insn "extend<mode>si2" + [(set (match_operand:SI 0 "register_operand" "=l, r, r") + (sign_extend:SI (match_operand:QIHI 1 "nonimmediate_operand" " l, r, m")))] + "" +{ + switch (which_alternative) + { + case 0: + return "se<size>33\t%0, %1"; + case 1: + return "se<size>\t%0, %1"; + case 2: + return nds32_output_32bit_load_s (operands, <byte>); + + default: + gcc_unreachable (); + } +} + [(set_attr "type" "alu,alu,load") + (set_attr "length" " 2, 4, 4")]) + + +;; ---------------------------------------------------------------------------- + +;; Arithmetic instructions. + +(define_insn "add<mode>3" + [(set (match_operand:QIHISI 0 "register_operand" "= d, l, d, l, d, l, k, l, r, r") + (plus:QIHISI (match_operand:QIHISI 1 "register_operand" " 0, l, 0, l, %0, l, 0, k, r, r") + (match_operand:QIHISI 2 "nds32_rimm15s_operand" " In05, In03, Iu05, Iu03, r, l, Is10, Iu06, Is15, r")))] + "" +{ + switch (which_alternative) + { + case 0: + /* addi Rt4,Rt4,-x ==> subi45 Rt4,x + where 0 <= x <= 31 */ + operands[2] = gen_int_mode (-INTVAL (operands[2]), SImode); + return "subi45\t%0, %2"; + case 1: + /* addi Rt3,Ra3,-x ==> subi333 Rt3,Ra3,x + where 0 <= x <= 7 */ + operands[2] = gen_int_mode (-INTVAL (operands[2]), SImode); + return "subi333\t%0, %1, %2"; + case 2: + return "addi45\t%0, %2"; + case 3: + return "addi333\t%0, %1, %2"; + case 4: + return "add45\t%0, %2"; + case 5: + return "add333\t%0, %1, %2"; + case 6: + return "addi10.sp\t%2"; + case 7: + return "addri36.sp\t%0, %2"; + case 8: + return "addi\t%0, %1, %2"; + case 9: + return "add\t%0, %1, %2"; + + default: + gcc_unreachable (); + } +} + [(set_attr "type" "alu,alu,alu,alu,alu,alu,alu,alu,alu,alu") + (set_attr "length" " 2, 2, 2, 2, 2, 2, 2, 2, 4, 4")]) + +(define_insn "sub<mode>3" + [(set (match_operand:QIHISI 0 "register_operand" "=d, l, r, r") + (minus:QIHISI (match_operand:QIHISI 1 "nds32_rimm15s_operand" " 0, l, Is15, r") + (match_operand:QIHISI 2 "register_operand" " r, l, r, r")))] + "" + "@ + sub45\t%0, %2 + sub333\t%0, %1, %2 + subri\t%0, %2, %1 + sub\t%0, %1, %2" + [(set_attr "type" "alu,alu,alu,alu") + (set_attr "length" " 2, 2, 4, 4")]) + + +;; GCC intends to simplify (plus (ashift ...) (reg)) +;; into (plus (mult ...) (reg)), so our matching pattern takes 'mult' +;; and needs to ensure it is exact_log2 value. +(define_insn "*add_slli" + [(set (match_operand:SI 0 "register_operand" "=r") + (plus:SI (mult:SI (match_operand:SI 1 "register_operand" " r") + (match_operand:SI 2 "immediate_operand" " i")) + (match_operand:SI 3 "register_operand" " r")))] + "TARGET_ISA_V3 + && (exact_log2 (INTVAL (operands[2])) != -1) + && (exact_log2 (INTVAL (operands[2])) <= 31)" +{ + /* Get floor_log2 of the immediate value + so that we can generate 'add_slli' instruction. */ + operands[2] = GEN_INT (floor_log2 (INTVAL (operands[2]))); + + return "add_slli\t%0, %3, %1, %2"; +} + [(set_attr "type" "alu") + (set_attr "length" "4")]) + +(define_insn "*add_srli" + [(set (match_operand:SI 0 "register_operand" "= r") + (plus:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" " r") + (match_operand:SI 2 "immediate_operand" " Iu05")) + (match_operand:SI 3 "register_operand" " r")))] + "TARGET_ISA_V3" + "add_srli\t%0, %3, %1, %2" + [(set_attr "type" "alu") + (set_attr "length" "4")]) + + +;; GCC intends to simplify (minus (reg) (ashift ...)) +;; into (minus (reg) (mult ...)), so our matching pattern takes 'mult' +;; and needs to ensure it is exact_log2 value. +(define_insn "*sub_slli" + [(set (match_operand:SI 0 "register_operand" "=r") + (minus:SI (match_operand:SI 1 "register_operand" " r") + (mult:SI (match_operand:SI 2 "register_operand" " r") + (match_operand:SI 3 "immediate_operand" " i"))))] + "TARGET_ISA_V3 + && (exact_log2 (INTVAL (operands[3])) != -1) + && (exact_log2 (INTVAL (operands[3])) <= 31)" +{ + /* Get floor_log2 of the immediate value + so that we can generate 'sub_slli' instruction. */ + operands[3] = GEN_INT (floor_log2 (INTVAL (operands[3]))); + + return "sub_slli\t%0, %1, %2, %3"; +} + [(set_attr "type" "alu") + (set_attr "length" "4")]) + +(define_insn "*sub_srli" + [(set (match_operand:SI 0 "register_operand" "= r") + (minus:SI (match_operand:SI 1 "register_operand" " r") + (lshiftrt:SI (match_operand:SI 2 "register_operand" " r") + (match_operand:SI 3 "immediate_operand" " Iu05"))))] + "TARGET_ISA_V3" + "sub_srli\t%0, %1, %2, %3" + [(set_attr "type" "alu") + (set_attr "length" "4")]) + + +;; Multiplication instructions. + +(define_insn "mulsi3" + [(set (match_operand:SI 0 "register_operand" "= w, r") + (mult:SI (match_operand:SI 1 "register_operand" " %0, r") + (match_operand:SI 2 "register_operand" " w, r")))] + "" + "@ + mul33\t%0, %2 + mul\t%0, %1, %2" + [(set_attr "type" "alu,alu") + (set_attr "length" " 2, 4")]) + +(define_insn "mulsidi3" + [(set (match_operand:DI 0 "register_operand" "=r") + (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" " r")) + (sign_extend:DI (match_operand:SI 2 "register_operand" " r"))))] + "TARGET_ISA_V2 || TARGET_ISA_V3" + "mulsr64\t%0, %1, %2" + [(set_attr "type" "alu") + (set_attr "length" "4")]) + +(define_insn "umulsidi3" + [(set (match_operand:DI 0 "register_operand" "=r") + (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" " r")) + (zero_extend:DI (match_operand:SI 2 "register_operand" " r"))))] + "TARGET_ISA_V2 || TARGET_ISA_V3" + "mulr64\t%0, %1, %2" + [(set_attr "type" "alu") + (set_attr "length" "4")]) + + +;; Multiply-accumulate instructions. + +(define_insn "*maddr32_0" + [(set (match_operand:SI 0 "register_operand" "=r") + (plus:SI (match_operand:SI 3 "register_operand" " 0") + (mult:SI (match_operand:SI 1 "register_operand" " r") + (match_operand:SI 2 "register_operand" " r"))))] + "" + "maddr32\t%0, %1, %2" + [(set_attr "type" "alu") + (set_attr "length" "4")]) + +(define_insn "*maddr32_1" + [(set (match_operand:SI 0 "register_operand" "=r") + (plus:SI (mult:SI (match_operand:SI 1 "register_operand" " r") + (match_operand:SI 2 "register_operand" " r")) + (match_operand:SI 3 "register_operand" " 0")))] + "" + "maddr32\t%0, %1, %2" + [(set_attr "type" "alu") + (set_attr "length" "4")]) + +(define_insn "*msubr32" + [(set (match_operand:SI 0 "register_operand" "=r") + (minus:SI (match_operand:SI 3 "register_operand" " 0") + (mult:SI (match_operand:SI 1 "register_operand" " r") + (match_operand:SI 2 "register_operand" " r"))))] + "" + "msubr32\t%0, %1, %2" + [(set_attr "type" "alu") + (set_attr "length" "4")]) + + +;; Div Instructions. + +(define_insn "divmodsi4" + [(set (match_operand:SI 0 "register_operand" "=r") + (div:SI (match_operand:SI 1 "register_operand" " r") + (match_operand:SI 2 "register_operand" " r"))) + (set (match_operand:SI 3 "register_operand" "=r") + (mod:SI (match_dup 1) (match_dup 2)))] + "" + "divsr\t%0, %3, %1, %2" + [(set_attr "type" "alu") + (set_attr "length" "4")]) + +(define_insn "udivmodsi4" + [(set (match_operand:SI 0 "register_operand" "=r") + (udiv:SI (match_operand:SI 1 "register_operand" " r") + (match_operand:SI 2 "register_operand" " r"))) + (set (match_operand:SI 3 "register_operand" "=r") + (umod:SI (match_dup 1) (match_dup 2)))] + "" + "divr\t%0, %3, %1, %2" + [(set_attr "type" "alu") + (set_attr "length" "4")]) + + +;; ---------------------------------------------------------------------------- + +;; Boolean instructions. +;; Note: We define the DImode versions in nds32-doubleword.md. + +;; ---------------------------------------------------------------------------- +;; 'AND' operation +;; ---------------------------------------------------------------------------- + +(define_insn "bitc" + [(set (match_operand:SI 0 "register_operand" "=r") + (and:SI (not:SI (match_operand:SI 1 "register_operand" " r")) + (match_operand:SI 2 "register_operand" " r")))] + "TARGET_ISA_V3" + "bitc\t%0, %2, %1" + [(set_attr "type" "alu") + (set_attr "length" "4")] +) + +(define_insn "andsi3" + [(set (match_operand:SI 0 "register_operand" "= w, r, l, l, l, l, l, l, r, r, r, r, r") + (and:SI (match_operand:SI 1 "register_operand" " %0, r, l, l, l, l, 0, 0, r, r, r, r, r") + (match_operand:SI 2 "general_operand" " w, r, Izeb, Izeh, Ixls, Ix11, Ibms, Ifex, Izeb, Izeh, Iu15, Ii15, Ic15")))] + "" +{ + HOST_WIDE_INT mask = INTVAL (operands[2]); + int zero_position; + + /* 16-bit andi instructions: + andi Rt3,Ra3,0xff -> zeb33 Rt3,Ra3 + andi Rt3,Ra3,0xffff -> zeh33 Rt3,Ra3 + andi Rt3,Ra3,0x01 -> xlsb33 Rt3,Ra3 + andi Rt3,Ra3,0x7ff -> x11b33 Rt3,Ra3 + andi Rt3,Rt3,2^imm3u -> bmski33 Rt3,imm3u + andi Rt3,Rt3,(2^(imm3u+1))-1 -> fexti33 Rt3,imm3u. */ + + switch (which_alternative) + { + case 0: + return "and33\t%0, %2"; + case 1: + return "and\t%0, %1, %2"; + case 2: + return "zeb33\t%0, %1"; + case 3: + return "zeh33\t%0, %1"; + case 4: + return "xlsb33\t%0, %1"; + case 5: + return "x11b33\t%0, %1"; + case 6: + operands[2] = GEN_INT (floor_log2 (mask)); + return "bmski33\t%0, %2"; + case 7: + operands[2] = GEN_INT (floor_log2 (mask + 1) - 1); + return "fexti33\t%0, %2"; + case 8: + return "zeb\t%0, %1"; + case 9: + return "zeh\t%0, %1"; + case 10: + return "andi\t%0, %1, %2"; + case 11: + operands[2] = GEN_INT (~mask); + return "bitci\t%0, %1, %2"; + case 12: + /* If we reach this alternative, + it must pass the nds32_can_use_bclr_p() test, + so that we can guarantee there is only one 0-bit + within the immediate value. */ + for (zero_position = 31; zero_position >= 0; zero_position--) + { + if ((INTVAL (operands[2]) & (1 << zero_position)) == 0) + { + /* Found the 0-bit position. */ + operands[2] = GEN_INT (zero_position); + break; + } + } + return "bclr\t%0, %1, %2"; + + default: + gcc_unreachable (); + } +} + [(set_attr "type" "alu,alu,alu,alu,alu,alu,alu,alu,alu,alu,alu,alu,alu") + (set_attr "length" " 2, 4, 2, 2, 2, 2, 2, 2, 4, 4, 4, 4, 4")]) + +(define_insn "*and_slli" + [(set (match_operand:SI 0 "register_operand" "= r") + (and:SI (ashift:SI (match_operand:SI 1 "register_operand" " r") + (match_operand:SI 2 "immediate_operand" " Iu05")) + (match_operand:SI 3 "register_operand" " r")))] + "TARGET_ISA_V3" + "and_slli\t%0, %3, %1, %2" + [(set_attr "type" "alu") + (set_attr "length" "4")]) + +(define_insn "*and_srli" + [(set (match_operand:SI 0 "register_operand" "= r") + (and:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" " r") + (match_operand:SI 2 "immediate_operand" " Iu05")) + (match_operand:SI 3 "register_operand" " r")))] + "TARGET_ISA_V3" + "and_srli\t%0, %3, %1, %2" + [(set_attr "type" "alu") + (set_attr "length" "4")]) + + +;; ---------------------------------------------------------------------------- +;; 'OR' operation +;; ---------------------------------------------------------------------------- + +;; For V3/V3M ISA, we have 'or33' instruction. +;; So we can identify 'or Rt3,Rt3,Ra3' case and set its length to be 2. +(define_insn "iorsi3" + [(set (match_operand:SI 0 "register_operand" "= w, r, r, r") + (ior:SI (match_operand:SI 1 "register_operand" " %0, r, r, r") + (match_operand:SI 2 "general_operand" " w, r, Iu15, Ie15")))] + "" +{ + int one_position; + + switch (which_alternative) + { + case 0: + return "or33\t%0, %2"; + case 1: + return "or\t%0, %1, %2"; + case 2: + return "ori\t%0, %1, %2"; + case 3: + /* If we reach this alternative, + it must pass the nds32_can_use_bset_p() test, + so that we can guarantee there is only one 1-bit + within the immediate value. */ + /* Use exact_log2() to search the 1-bit position. */ + one_position = exact_log2 (INTVAL (operands[2])); + operands[2] = GEN_INT (one_position); + return "bset\t%0, %1, %2"; + + default: + gcc_unreachable (); + } +} + [(set_attr "type" "alu,alu,alu,alu") + (set_attr "length" " 2, 4, 4, 4")]) + +(define_insn "*or_slli" + [(set (match_operand:SI 0 "register_operand" "= r") + (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" " r") + (match_operand:SI 2 "immediate_operand" " Iu05")) + (match_operand:SI 3 "register_operand" " r")))] + "TARGET_ISA_V3" + "or_slli\t%0, %3, %1, %2" + [(set_attr "type" "alu") + (set_attr "length" "4")]) + +(define_insn "*or_srli" + [(set (match_operand:SI 0 "register_operand" "= r") + (ior:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" " r") + (match_operand:SI 2 "immediate_operand" " Iu05")) + (match_operand:SI 3 "register_operand" " r")))] + "TARGET_ISA_V3" + "or_srli\t%0, %3, %1, %2" + [(set_attr "type" "alu") + (set_attr "length" "4")]) + + +;; ---------------------------------------------------------------------------- +;; 'XOR' operation +;; ---------------------------------------------------------------------------- + +;; For V3/V3M ISA, we have 'xor33' instruction. +;; So we can identify 'xor Rt3,Rt3,Ra3' case and set its length to be 2. +(define_insn "xorsi3" + [(set (match_operand:SI 0 "register_operand" "= w, r, r, r") + (xor:SI (match_operand:SI 1 "register_operand" " %0, r, r, r") + (match_operand:SI 2 "general_operand" " w, r, Iu15, It15")))] + "" +{ + int one_position; + + switch (which_alternative) + { + case 0: + return "xor33\t%0, %2"; + case 1: + return "xor\t%0, %1, %2"; + case 2: + return "xori\t%0, %1, %2"; + case 3: + /* If we reach this alternative, + it must pass the nds32_can_use_btgl_p() test, + so that we can guarantee there is only one 1-bit + within the immediate value. */ + /* Use exact_log2() to search the 1-bit position. */ + one_position = exact_log2 (INTVAL (operands[2])); + operands[2] = GEN_INT (one_position); + return "btgl\t%0, %1, %2"; + + default: + gcc_unreachable (); + } +} + [(set_attr "type" "alu,alu,alu,alu") + (set_attr "length" " 2, 4, 4, 4")]) + +(define_insn "*xor_slli" + [(set (match_operand:SI 0 "register_operand" "= r") + (xor:SI (ashift:SI (match_operand:SI 1 "register_operand" " r") + (match_operand:SI 2 "immediate_operand" " Iu05")) + (match_operand:SI 3 "register_operand" " r")))] + "TARGET_ISA_V3" + "xor_slli\t%0, %3, %1, %2" + [(set_attr "type" "alu") + (set_attr "length" "4")]) + +(define_insn "*xor_srli" + [(set (match_operand:SI 0 "register_operand" "= r") + (xor:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" " r") + (match_operand:SI 2 "immediate_operand" " Iu05")) + (match_operand:SI 3 "register_operand" " r")))] + "TARGET_ISA_V3" + "xor_srli\t%0, %3, %1, %2" + [(set_attr "type" "alu") + (set_attr "length" "4")]) + +;; Rotate Right Instructions. + +(define_insn "rotrsi3" + [(set (match_operand:SI 0 "register_operand" "= r, r") + (rotatert:SI (match_operand:SI 1 "register_operand" " r, r") + (match_operand:SI 2 "nonmemory_operand" " Iu05, r")))] + "" + "@ + rotri\t%0, %1, %2 + rotr\t%0, %1, %2" + [(set_attr "type" "alu,alu") + (set_attr "length" " 4, 4")]) + + +;; ---------------------------------------------------------------------------- +;; 'NEG' operation +;; ---------------------------------------------------------------------------- + +;; For V3/V3M ISA, we have 'neg33' instruction. +;; So we can identify 'xor Rt3,Ra3' case and set its length to be 2. +;; And for V2 ISA, there is NO 'neg33' instruction. +;; The only option is to use 'subri A,B,0' (its semantic is 'A = 0 - B'). +(define_insn "negsi2" + [(set (match_operand:SI 0 "register_operand" "=w, r") + (neg:SI (match_operand:SI 1 "register_operand" " w, r")))] + "" + "@ + neg33\t%0, %1 + subri\t%0, %1, 0" + [(set_attr "type" "alu,alu") + (set_attr "length" " 2, 4")]) + + +;; ---------------------------------------------------------------------------- +;; 'ONE_COMPLIMENT' operation +;; ---------------------------------------------------------------------------- + +;; For V3/V3M ISA, we have 'not33' instruction. +;; So we can identify 'not Rt3,Ra3' case and set its length to be 2. +(define_insn "one_cmplsi2" + [(set (match_operand:SI 0 "register_operand" "=w, r") + (not:SI (match_operand:SI 1 "register_operand" " w, r")))] + "" + "@ + not33\t%0, %1 + nor\t%0, %1, %1" + [(set_attr "type" "alu,alu") + (set_attr "length" " 2, 4")]) + + +;; ---------------------------------------------------------------------------- + +;; Shift instructions. + +(define_insn "ashlsi3" + [(set (match_operand:SI 0 "register_operand" "= l, r, r") + (ashift:SI (match_operand:SI 1 "register_operand" " l, r, r") + (match_operand:SI 2 "nonmemory_operand" " Iu03, Iu05, r")))] + "" + "@ + slli333\t%0, %1, %2 + slli\t%0, %1, %2 + sll\t%0, %1, %2" + [(set_attr "type" "alu,alu,alu") + (set_attr "length" " 2, 4, 4")]) + +(define_insn "ashrsi3" + [(set (match_operand:SI 0 "register_operand" "= d, r, r") + (ashiftrt:SI (match_operand:SI 1 "register_operand" " 0, r, r") + (match_operand:SI 2 "nonmemory_operand" " Iu05, Iu05, r")))] + "" + "@ + srai45\t%0, %2 + srai\t%0, %1, %2 + sra\t%0, %1, %2" + [(set_attr "type" "alu,alu,alu") + (set_attr "length" " 2, 4, 4")]) + +(define_insn "lshrsi3" + [(set (match_operand:SI 0 "register_operand" "= d, r, r") + (lshiftrt:SI (match_operand:SI 1 "register_operand" " 0, r, r") + (match_operand:SI 2 "nonmemory_operand" " Iu05, Iu05, r")))] + "" + "@ + srli45\t%0, %2 + srli\t%0, %1, %2 + srl\t%0, %1, %2" + [(set_attr "type" "alu,alu,alu") + (set_attr "length" " 2, 4, 4")]) + + +;; ---------------------------------------------------------------------------- + +;; ---------------------------------------------------------------------------- +;; Conditional Move patterns +;; ---------------------------------------------------------------------------- + +(define_expand "movsicc" + [(set (match_operand:SI 0 "register_operand" "") + (if_then_else:SI (match_operand 1 "comparison_operator" "") + (match_operand:SI 2 "register_operand" "") + (match_operand:SI 3 "register_operand" "")))] + "TARGET_CMOV" +{ + if ((GET_CODE (operands[1]) == EQ || GET_CODE (operands[1]) == NE) + && GET_MODE (XEXP (operands[1], 0)) == SImode + && XEXP (operands[1], 1) == const0_rtx) + { + /* If the operands[1] rtx is already (eq X 0) or (ne X 0), + we have gcc generate original template rtx. */ + goto create_template; + } + else + { + /* Since there is only 'slt'(Set when Less Than) instruction for + comparison in Andes ISA, the major strategy we use here is to + convert conditional move into 'LT + EQ' or 'LT + NE' rtx combination. + We design constraints properly so that the reload phase will assist + to make one source operand to use same register as result operand. + Then we can use cmovz/cmovn to catch the other source operand + which has different register. */ + enum rtx_code code = GET_CODE (operands[1]); + enum rtx_code new_code = code; + rtx cmp_op0 = XEXP (operands[1], 0); + rtx cmp_op1 = XEXP (operands[1], 1); + rtx tmp; + int reverse = 0; + + /* Main Goal: Use 'LT + EQ' or 'LT + NE' to target "then" part + Strategy : Reverse condition and swap comparison operands + + For example: + + a <= b ? P : Q (LE or LEU) + --> a > b ? Q : P (reverse condition) + --> b < a ? Q : P (swap comparison operands to achieve 'LT/LTU') + + a >= b ? P : Q (GE or GEU) + --> a < b ? Q : P (reverse condition to achieve 'LT/LTU') + + a < b ? P : Q (LT or LTU) + --> (NO NEED TO CHANGE, it is already 'LT/LTU') + + a > b ? P : Q (GT or GTU) + --> b < a ? P : Q (swap comparison operands to achieve 'LT/LTU') */ + switch (code) + { + case NE: + /* (a != b ? P : Q) + can be expressed as + (a == b ? Q : P) + so, fall through to reverse condition */ + case GE: case GEU: case LE: case LEU: + new_code = reverse_condition (code); + reverse = 1; + break; + case EQ: case GT: case GTU: case LT: case LTU: + /* no need to reverse condition */ + break; + default: + FAIL; + } + + /* For '>' comparison operator, we swap operands + so that we can have 'LT/LTU' operator. */ + if (new_code == GT || new_code == GTU) + { + tmp = cmp_op0; + cmp_op0 = cmp_op1; + cmp_op1 = tmp; + + new_code = swap_condition (new_code); + } + + /* Use a temporary register to store slt/slts result. */ + tmp = gen_reg_rtx (SImode); + + /* Split EQ and NE because we don't have direct comparison of EQ and NE. + If we don't split it, the conditional move transformation will fail + when producing (SET A (EQ B C)) or (SET A (NE B C)). */ + if (new_code == EQ) + { + emit_insn (gen_xorsi3 (tmp, cmp_op0, cmp_op1)); + emit_insn (gen_slt_compare (tmp, tmp, GEN_INT (1))); + } + else if (new_code == NE) + { + emit_insn (gen_xorsi3 (tmp, cmp_op0, cmp_op1)); + emit_insn (gen_slt_compare (tmp, GEN_INT (0), tmp)); + } + else + /* This emit_insn will create corresponding 'slt/slts' insturction. */ + emit_insn (gen_rtx_SET (VOIDmode, tmp, + gen_rtx_fmt_ee (new_code, SImode, + cmp_op0, cmp_op1))); + + /* Change comparison semantic into (eq X 0) or (ne X 0) behavior + so that cmovz or cmovn will be matched later. + + For reverse condition cases, we want to create a semantic that: + (eq X 0) --> pick up "else" part + For normal cases, we want to create a semantic that: + (ne X 0) --> pick up "then" part + + Later we will have cmovz/cmovn instruction pattern to + match corresponding behavior and output instruction. */ + operands[1] = gen_rtx_fmt_ee (reverse ? EQ : NE, + VOIDmode, tmp, const0_rtx); + } + +create_template: + do {} while(0); /* dummy line */ +}) + +(define_insn "cmovz" + [(set (match_operand:SI 0 "register_operand" "=r, r") + (if_then_else:SI (eq (match_operand:SI 1 "register_operand" " r, r") + (const_int 0)) + (match_operand:SI 2 "register_operand" " r, 0") + (match_operand:SI 3 "register_operand" " 0, r")))] + "TARGET_CMOV" + "@ + cmovz\t%0, %2, %1 + cmovn\t%0, %3, %1" + [(set_attr "type" "move") + (set_attr "length" "4")]) + +(define_insn "cmovn" + [(set (match_operand:SI 0 "register_operand" "=r, r") + (if_then_else:SI (ne (match_operand:SI 1 "register_operand" " r, r") + (const_int 0)) + (match_operand:SI 2 "register_operand" " r, 0") + (match_operand:SI 3 "register_operand" " 0, r")))] + "TARGET_CMOV" + "@ + cmovn\t%0, %2, %1 + cmovz\t%0, %3, %1" + [(set_attr "type" "move") + (set_attr "length" "4")]) + + +;; ---------------------------------------------------------------------------- +;; Conditional Branch patterns +;; ---------------------------------------------------------------------------- + +(define_expand "cbranchsi4" + [(set (pc) + (if_then_else (match_operator 0 "comparison_operator" + [(match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "nds32_reg_constant_operand" "")]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "" +{ + rtx tmp_reg; + enum rtx_code code; + + code = GET_CODE (operands[0]); + + /* If operands[2] is (const_int 0), + we can use beqz,bnez,bgtz,bgez,bltz,or blez instructions. + So we have gcc generate original template rtx. */ + if (GET_CODE (operands[2]) == CONST_INT) + if (INTVAL (operands[2]) == 0) + if ((code != GTU) + && (code != GEU) + && (code != LTU) + && (code != LEU)) + goto create_template; + + /* For other comparison, NDS32 ISA only has slt (Set-on-Less-Than) + behavior for the comparison, we might need to generate other + rtx patterns to achieve same semantic. */ + switch (code) + { + case GT: + case GTU: + if (GET_CODE (operands[2]) == CONST_INT) + { + /* GT reg_A, const_int => !(LT reg_A, const_int + 1) */ + tmp_reg = gen_rtx_REG (SImode, TA_REGNUM); + + /* We want to plus 1 into the integer value + of operands[2] to create 'slt' instruction. + This caculation is performed on the host machine, + which may be 64-bit integer. + So the meaning of caculation result may be + different from the 32-bit nds32 target. + + For example: + 0x7fffffff + 0x1 -> 0x80000000, + this value is POSITIVE on 64-bit machine, + but the expected value on 32-bit nds32 target + should be NEGATIVE value. + + Hence, instead of using GEN_INT(), we use gen_int_mode() to + explicitly create SImode constant rtx. */ + operands[2] = gen_int_mode (INTVAL (operands[2]) + 1, SImode); + + if (code == GT) + { + /* GT, use slts instruction */ + emit_insn (gen_slts_compare (tmp_reg, operands[1], operands[2])); + } + else + { + /* GTU, use slt instruction */ + emit_insn (gen_slt_compare (tmp_reg, operands[1], operands[2])); + } + + PUT_CODE (operands[0], EQ); + operands[1] = tmp_reg; + operands[2] = const0_rtx; + emit_insn (gen_cbranchsi4 (operands[0], operands[1], + operands[2], operands[3])); + + DONE; + } + else + { + /* GT reg_A, reg_B => LT reg_B, reg_A */ + tmp_reg = gen_rtx_REG (SImode, TA_REGNUM); + + if (code == GT) + { + /* GT, use slts instruction */ + emit_insn (gen_slts_compare (tmp_reg, operands[2], operands[1])); + } + else + { + /* GTU, use slt instruction */ + emit_insn (gen_slt_compare (tmp_reg, operands[2], operands[1])); + } + + PUT_CODE (operands[0], NE); + operands[1] = tmp_reg; + operands[2] = const0_rtx; + emit_insn (gen_cbranchsi4 (operands[0], operands[1], + operands[2], operands[3])); + + DONE; + } + + case GE: + case GEU: + /* GE reg_A, reg_B => !(LT reg_A, reg_B) */ + /* GE reg_A, const_int => !(LT reg_A, const_int) */ + tmp_reg = gen_rtx_REG (SImode, TA_REGNUM); + + if (code == GE) + { + /* GE, use slts instruction */ + emit_insn (gen_slts_compare (tmp_reg, operands[1], operands[2])); + } + else + { + /* GEU, use slt instruction */ + emit_insn (gen_slt_compare (tmp_reg, operands[1], operands[2])); + } + + PUT_CODE (operands[0], EQ); + operands[1] = tmp_reg; + operands[2] = const0_rtx; + emit_insn (gen_cbranchsi4 (operands[0], operands[1], + operands[2], operands[3])); + + DONE; + + case LT: + case LTU: + /* LT reg_A, reg_B => LT reg_A, reg_B */ + /* LT reg_A, const_int => LT reg_A, const_int */ + tmp_reg = gen_rtx_REG (SImode, TA_REGNUM); + + if (code == LT) + { + /* LT, use slts instruction */ + emit_insn (gen_slts_compare (tmp_reg, operands[1], operands[2])); + } + else + { + /* LTU, use slt instruction */ + emit_insn (gen_slt_compare (tmp_reg, operands[1], operands[2])); + } + + PUT_CODE (operands[0], NE); + operands[1] = tmp_reg; + operands[2] = const0_rtx; + emit_insn (gen_cbranchsi4 (operands[0], operands[1], + operands[2], operands[3])); + + DONE; + + case LE: + case LEU: + if (GET_CODE (operands[2]) == CONST_INT) + { + /* LE reg_A, const_int => LT reg_A, const_int + 1 */ + tmp_reg = gen_rtx_REG (SImode, TA_REGNUM); + + /* Note that (le:SI X INT_MAX) is not the same as (lt:SI X INT_MIN). + We better have an assert here in case GCC does not properly + optimize it away. The INT_MAX here is 0x7fffffff for target. */ + gcc_assert (code != LE || INTVAL (operands[2]) != 0x7fffffff); + operands[2] = gen_int_mode (INTVAL (operands[2]) + 1, SImode); + + if (code == LE) + { + /* LE, use slts instruction */ + emit_insn (gen_slts_compare (tmp_reg, operands[1], operands[2])); + } + else + { + /* LEU, use slt instruction */ + emit_insn (gen_slt_compare (tmp_reg, operands[1], operands[2])); + } + + PUT_CODE (operands[0], NE); + operands[1] = tmp_reg; + operands[2] = const0_rtx; + emit_insn (gen_cbranchsi4 (operands[0], operands[1], + operands[2], operands[3])); + + DONE; + } + else + { + /* LE reg_A, reg_B => !(LT reg_B, reg_A) */ + tmp_reg = gen_rtx_REG (SImode, TA_REGNUM); + + if (code == LE) + { + /* LE, use slts instruction */ + emit_insn (gen_slts_compare (tmp_reg, operands[2], operands[1])); + } + else + { + /* LEU, use slt instruction */ + emit_insn (gen_slt_compare (tmp_reg, operands[2], operands[1])); + } + + PUT_CODE (operands[0], EQ); + operands[1] = tmp_reg; + operands[2] = const0_rtx; + emit_insn (gen_cbranchsi4 (operands[0], operands[1], + operands[2], operands[3])); + + DONE; + } + + case EQ: + case NE: + /* NDS32 ISA has various form for eq/ne behavior no matter + what kind of the operand is. + So just generate original template rtx. */ + goto create_template; + + default: + FAIL; + } + +create_template: + do {} while(0); /* dummy line */ +}) + + +(define_insn "*cbranchsi4_equality_zero" + [(set (pc) + (if_then_else (match_operator 0 "nds32_equality_comparison_operator" + [(match_operand:SI 1 "register_operand" "t, l, r") + (const_int 0)]) + (label_ref (match_operand 2 "" "")) + (pc)))] + "" +{ + enum rtx_code code; + + code = GET_CODE (operands[0]); + + /* This zero-comparison conditional branch has two forms: + 32-bit instruction => beqz/bnez imm16s << 1 + 16-bit instruction => beqzs8/bnezs8/beqz38/bnez38 imm8s << 1 + + For 32-bit case, + we assume it is always reachable. (but check range -65500 ~ 65500) + + For 16-bit case, + it must satisfy { 255 >= (label - pc) >= -256 } condition. + However, since the $pc for nds32 is at the beginning of the instruction, + we should leave some length space for current insn. + So we use range -250 ~ 250. */ + + switch (get_attr_length (insn)) + { + case 2: + if (which_alternative == 0) + { + /* constraint: t */ + return (code == EQ) ? "beqzs8\t%2" : "bnezs8\t%2"; + } + else if (which_alternative == 1) + { + /* constraint: l */ + return (code == EQ) ? "beqz38\t%1, %2" : "bnez38\t%1, %2"; + } + else + { + /* constraint: r */ + /* For which_alternative==2, it should not be here. */ + gcc_unreachable (); + } + case 4: + /* including constraints: t, l, and r */ + return (code == EQ) ? "beqz\t%1, %2" : "bnez\t%1, %2"; + case 6: + if (which_alternative == 0) + { + /* constraint: t */ + if (code == EQ) + { + /* beqzs8 .L0 + => + bnezs8 .LCB0 + j .L0 + .LCB0: + */ + return "bnezs8\t.LCB%=\;j\t%2\n.LCB%=:"; + } + else + { + /* bnezs8 .L0 + => + beqzs8 .LCB0 + j .L0 + .LCB0: + */ + return "beqzs8\t.LCB%=\;j\t%2\n.LCB%=:"; + } + } + else if (which_alternative == 1) + { + /* constraint: l */ + if (code == EQ) + { + /* beqz38 $r0, .L0 + => + bnez38 $r0, .LCB0 + j .L0 + .LCB0: + */ + return "bnez38\t%1, .LCB%=\;j\t%2\n.LCB%=:"; + } + else + { + /* bnez38 $r0, .L0 + => + beqz38 $r0, .LCB0 + j .L0 + .LCB0: + */ + return "beqz38\t%1, .LCB%=\;j\t%2\n.LCB%=:"; + } + } + else + { + /* constraint: r */ + /* For which_alternative==2, it should not be here. */ + gcc_unreachable (); + } + case 8: + /* constraint: t, l, r. */ + if (code == EQ) + { + /* beqz $r8, .L0 + => + bnez $r8, .LCB0 + j .L0 + .LCB0: + */ + return "bnez\t%1, .LCB%=\;j\t%2\n.LCB%=:"; + } + else + { + /* bnez $r8, .L0 + => + beqz $r8, .LCB0 + j .L0 + .LCB0: + */ + return "beqz\t%1, .LCB%=\;j\t%2\n.LCB%=:"; + } + default: + gcc_unreachable (); + } +} + [(set_attr "type" "branch") + (set_attr "enabled" "1") + (set_attr_alternative "length" + [ + ;; Alternative 0 + (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -250)) + (le (minus (match_dup 2) (pc)) (const_int 250))) + (if_then_else (match_test "TARGET_16_BIT") + (const_int 2) + (const_int 4)) + (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -65500)) + (le (minus (match_dup 2) (pc)) (const_int 65500))) + (const_int 4) + (if_then_else (match_test "TARGET_16_BIT") + (const_int 6) + (const_int 8)))) + ;; Alternative 1 + (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -250)) + (le (minus (match_dup 2) (pc)) (const_int 250))) + (if_then_else (match_test "TARGET_16_BIT") + (const_int 2) + (const_int 4)) + (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -65500)) + (le (minus (match_dup 2) (pc)) (const_int 65500))) + (const_int 4) + (if_then_else (match_test "TARGET_16_BIT") + (const_int 6) + (const_int 8)))) + ;; Alternative 2 + (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -65500)) + (le (minus (match_dup 2) (pc)) (const_int 65500))) + (const_int 4) + (const_int 8)) + ])]) + + +;; This pattern is dedicated to V2 ISA, +;; because V2 DOES NOT HAVE beqc/bnec instruction. +(define_insn "*cbranchsi4_equality_reg" + [(set (pc) + (if_then_else (match_operator 0 "nds32_equality_comparison_operator" + [(match_operand:SI 1 "register_operand" "r") + (match_operand:SI 2 "nds32_reg_constant_operand" "r")]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "TARGET_ISA_V2" +{ + enum rtx_code code; + + code = GET_CODE (operands[0]); + + /* This register-comparison conditional branch has one form: + 32-bit instruction => beq/bne imm14s << 1 + + For 32-bit case, + we assume it is always reachable. (but check range -16350 ~ 16350). */ + + switch (code) + { + case EQ: + /* r, r */ + switch (get_attr_length (insn)) + { + case 4: + return "beq\t%1, %2, %3"; + case 8: + /* beq $r0, $r1, .L0 + => + bne $r0, $r1, .LCB0 + j .L0 + .LCB0: + */ + return "bne\t%1, %2, .LCB%=\;j\t%3\n.LCB%=:"; + default: + gcc_unreachable (); + } + + case NE: + /* r, r */ + switch (get_attr_length (insn)) + { + case 4: + return "bne\t%1, %2, %3"; + case 8: + /* bne $r0, $r1, .L0 + => + beq $r0, $r1, .LCB0 + j .L0 + .LCB0: + */ + return "beq\t%1, %2, .LCB%=\;j\t%3\n.LCB%=:"; + default: + gcc_unreachable (); + } + + default: + gcc_unreachable (); + } +} + [(set_attr "type" "branch") + (set (attr "length") + (if_then_else (and (ge (minus (match_dup 3) (pc)) (const_int -16350)) + (le (minus (match_dup 3) (pc)) (const_int 16350))) + (const_int 4) + (const_int 8)))]) + + +;; This pattern is dedicated to V3/V3M, +;; because V3/V3M DO HAVE beqc/bnec instruction. +(define_insn "*cbranchsi4_equality_reg_or_const_int" + [(set (pc) + (if_then_else (match_operator 0 "nds32_equality_comparison_operator" + [(match_operand:SI 1 "register_operand" "r, r") + (match_operand:SI 2 "nds32_reg_constant_operand" "r, Is11")]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "TARGET_ISA_V3 || TARGET_ISA_V3M" +{ + enum rtx_code code; + + code = GET_CODE (operands[0]); + + /* This register-comparison conditional branch has one form: + 32-bit instruction => beq/bne imm14s << 1 + 32-bit instruction => beqc/bnec imm8s << 1 + + For 32-bit case, we assume it is always reachable. + (but check range -16350 ~ 16350 and -250 ~ 250). */ + + switch (code) + { + case EQ: + if (which_alternative == 0) + { + /* r, r */ + switch (get_attr_length (insn)) + { + case 4: + return "beq\t%1, %2, %3"; + case 8: + /* beq $r0, $r1, .L0 + => + bne $r0, $r1, .LCB0 + j .L0 + .LCB0: + */ + return "bne\t%1, %2, .LCB%=\;j\t%3\n.LCB%=:"; + default: + gcc_unreachable (); + } + } + else + { + /* r, Is11 */ + switch (get_attr_length (insn)) + { + case 4: + return "beqc\t%1, %2, %3"; + case 8: + /* beqc $r0, constant, .L0 + => + bnec $r0, constant, .LCB0 + j .L0 + .LCB0: + */ + return "bnec\t%1, %2, .LCB%=\;j\t%3\n.LCB%=:"; + default: + gcc_unreachable (); + } + } + case NE: + if (which_alternative == 0) + { + /* r, r */ + switch (get_attr_length (insn)) + { + case 4: + return "bne\t%1, %2, %3"; + case 8: + /* bne $r0, $r1, .L0 + => + beq $r0, $r1, .LCB0 + j .L0 + .LCB0: + */ + return "beq\t%1, %2, .LCB%=\;j\t%3\n.LCB%=:"; + default: + gcc_unreachable (); + } + } + else + { + /* r, Is11 */ + switch (get_attr_length (insn)) + { + case 4: + return "bnec\t%1, %2, %3"; + case 8: + /* bnec $r0, constant, .L0 + => + beqc $r0, constant, .LCB0 + j .L0 + .LCB0: + */ + return "beqc\t%1, %2, .LCB%=\;j\t%3\n.LCB%=:"; + default: + gcc_unreachable (); + } + } + default: + gcc_unreachable (); + } +} + [(set_attr "type" "branch") + (set_attr_alternative "length" + [ + ;; Alternative 0 + (if_then_else (and (ge (minus (match_dup 3) (pc)) (const_int -16350)) + (le (minus (match_dup 3) (pc)) (const_int 16350))) + (const_int 4) + (const_int 8)) + ;; Alternative 1 + (if_then_else (and (ge (minus (match_dup 3) (pc)) (const_int -250)) + (le (minus (match_dup 3) (pc)) (const_int 250))) + (const_int 4) + (const_int 8)) + ])]) + + +(define_insn "*cbranchsi4_greater_less_zero" + [(set (pc) + (if_then_else (match_operator 0 "nds32_greater_less_comparison_operator" + [(match_operand:SI 1 "register_operand" "r") + (const_int 0)]) + (label_ref (match_operand 2 "" "")) + (pc)))] + "" +{ + enum rtx_code code; + + code = GET_CODE (operands[0]); + + /* This zero-greater-less-comparison conditional branch has one form: + 32-bit instruction => bgtz/bgez/bltz/blez imm16s << 1 + + For 32-bit case, we assume it is always reachable. + (but check range -65500 ~ 65500). */ + + if (get_attr_length (insn) == 8) + { + /* The branch target is too far to simply use one + bgtz/bgez/bltz/blez instruction. + We need to reverse condition and use 'j' to jump to the target. */ + switch (code) + { + case GT: + /* bgtz $r8, .L0 + => + blez $r8, .LCB0 + j .L0 + .LCB0: + */ + return "blez\t%1, .LCB%=\;j\t%2\n.LCB%=:"; + case GE: + /* bgez $r8, .L0 + => + bltz $r8, .LCB0 + j .L0 + .LCB0: + */ + return "bltz\t%1, .LCB%=\;j\t%2\n.LCB%=:"; + case LT: + /* bltz $r8, .L0 + => + bgez $r8, .LCB0 + j .L0 + .LCB0: + */ + return "bgez\t%1, .LCB%=\;j\t%2\n.LCB%=:"; + case LE: + /* blez $r8, .L0 + => + bgtz $r8, .LCB0 + j .L0 + .LCB0: + */ + return "bgtz\t%1, .LCB%=\;j\t%2\n.LCB%=:"; + default: + gcc_unreachable (); + } + } + + switch (code) + { + case GT: + return "bgtz\t%1, %2"; + case GE: + return "bgez\t%1, %2"; + case LT: + return "bltz\t%1, %2"; + case LE: + return "blez\t%1, %2"; + default: + gcc_unreachable (); + } +} + [(set_attr "type" "branch") + (set (attr "length") + (if_then_else (and (ge (minus (match_dup 2) (pc)) (const_int -65500)) + (le (minus (match_dup 2) (pc)) (const_int 65500))) + (const_int 4) + (const_int 8)))]) + + +(define_expand "cstoresi4" + [(set (match_operand:SI 0 "register_operand" "") + (match_operator:SI 1 "comparison_operator" + [(match_operand:SI 2 "register_operand" "") + (match_operand:SI 3 "nonmemory_operand" "")]))] + "" +{ + rtx tmp_reg; + enum rtx_code code; + + code = GET_CODE (operands[1]); + + switch (code) + { + case EQ: + if (GET_CODE (operands[3]) == CONST_INT) + { + /* reg_R = (reg_A == const_int_B) + --> addi reg_C, reg_A, -const_int_B + slti reg_R, reg_C, const_int_1 */ + tmp_reg = gen_reg_rtx (SImode); + operands[3] = gen_int_mode (-INTVAL (operands[3]), SImode); + /* If the integer value is not in the range of imm15s, + we need to force register first because our addsi3 pattern + only accept nds32_rimm15s_operand predicate. */ + if (!satisfies_constraint_Is15 (operands[3])) + operands[3] = force_reg (SImode, operands[3]); + emit_insn (gen_addsi3 (tmp_reg, operands[2], operands[3])); + emit_insn (gen_slt_compare (operands[0], tmp_reg, const1_rtx)); + + DONE; + } + else + { + /* reg_R = (reg_A == reg_B) + --> xor reg_C, reg_A, reg_B + slti reg_R, reg_C, const_int_1 */ + tmp_reg = gen_reg_rtx (SImode); + emit_insn (gen_xorsi3 (tmp_reg, operands[2], operands[3])); + emit_insn (gen_slt_compare (operands[0], tmp_reg, const1_rtx)); + + DONE; + } + + case NE: + if (GET_CODE (operands[3]) == CONST_INT) + { + /* reg_R = (reg_A != const_int_B) + --> addi reg_C, reg_A, -const_int_B + slti reg_R, const_int_0, reg_C */ + tmp_reg = gen_reg_rtx (SImode); + operands[3] = gen_int_mode (-INTVAL (operands[3]), SImode); + /* If the integer value is not in the range of imm15s, + we need to force register first because our addsi3 pattern + only accept nds32_rimm15s_operand predicate. */ + if (!satisfies_constraint_Is15 (operands[3])) + operands[3] = force_reg (SImode, operands[3]); + emit_insn (gen_addsi3 (tmp_reg, operands[2], operands[3])); + emit_insn (gen_slt_compare (operands[0], const0_rtx, tmp_reg)); + + DONE; + } + else + { + /* reg_R = (reg_A != reg_B) + --> xor reg_C, reg_A, reg_B + slti reg_R, const_int_0, reg_C */ + tmp_reg = gen_reg_rtx (SImode); + emit_insn (gen_xorsi3 (tmp_reg, operands[2], operands[3])); + emit_insn (gen_slt_compare (operands[0], const0_rtx, tmp_reg)); + + DONE; + } + + case GT: + case GTU: + /* reg_R = (reg_A > reg_B) --> slt reg_R, reg_B, reg_A */ + /* reg_R = (reg_A > const_int_B) --> slt reg_R, const_int_B, reg_A */ + if (code == GT) + { + /* GT, use slts instruction */ + emit_insn (gen_slts_compare (operands[0], operands[3], operands[2])); + } + else + { + /* GTU, use slt instruction */ + emit_insn (gen_slt_compare (operands[0], operands[3], operands[2])); + } + + DONE; + + case GE: + case GEU: + if (GET_CODE (operands[3]) == CONST_INT) + { + /* reg_R = (reg_A >= const_int_B) + --> movi reg_C, const_int_B - 1 + slt reg_R, reg_C, reg_A */ + tmp_reg = gen_reg_rtx (SImode); + + emit_insn (gen_movsi (tmp_reg, + gen_int_mode (INTVAL (operands[3]) - 1, + SImode))); + if (code == GE) + { + /* GE, use slts instruction */ + emit_insn (gen_slts_compare (operands[0], tmp_reg, operands[2])); + } + else + { + /* GEU, use slt instruction */ + emit_insn (gen_slt_compare (operands[0], tmp_reg, operands[2])); + } + + DONE; + } + else + { + /* reg_R = (reg_A >= reg_B) + --> slt reg_R, reg_A, reg_B + xori reg_R, reg_R, const_int_1 */ + if (code == GE) + { + /* GE, use slts instruction */ + emit_insn (gen_slts_compare (operands[0], + operands[2], operands[3])); + } + else + { + /* GEU, use slt instruction */ + emit_insn (gen_slt_compare (operands[0], + operands[2], operands[3])); + } + + /* perform 'not' behavior */ + emit_insn (gen_xorsi3 (operands[0], operands[0], const1_rtx)); + + DONE; + } + + case LT: + case LTU: + /* reg_R = (reg_A < reg_B) --> slt reg_R, reg_A, reg_B */ + /* reg_R = (reg_A < const_int_B) --> slt reg_R, reg_A, const_int_B */ + if (code == LT) + { + /* LT, use slts instruction */ + emit_insn (gen_slts_compare (operands[0], operands[2], operands[3])); + } + else + { + /* LTU, use slt instruction */ + emit_insn (gen_slt_compare (operands[0], operands[2], operands[3])); + } + + DONE; + + case LE: + case LEU: + if (GET_CODE (operands[3]) == CONST_INT) + { + /* reg_R = (reg_A <= const_int_B) + --> movi reg_C, const_int_B + 1 + slt reg_R, reg_A, reg_C */ + tmp_reg = gen_reg_rtx (SImode); + + emit_insn (gen_movsi (tmp_reg, + gen_int_mode (INTVAL (operands[3]) + 1, + SImode))); + if (code == LE) + { + /* LE, use slts instruction */ + emit_insn (gen_slts_compare (operands[0], operands[2], tmp_reg)); + } + else + { + /* LEU, use slt instruction */ + emit_insn (gen_slt_compare (operands[0], operands[2], tmp_reg)); + } + + DONE; + } + else + { + /* reg_R = (reg_A <= reg_B) --> slt reg_R, reg_B, reg_A + xori reg_R, reg_R, const_int_1 */ + if (code == LE) + { + /* LE, use slts instruction */ + emit_insn (gen_slts_compare (operands[0], + operands[3], operands[2])); + } + else + { + /* LEU, use slt instruction */ + emit_insn (gen_slt_compare (operands[0], + operands[3], operands[2])); + } + + /* perform 'not' behavior */ + emit_insn (gen_xorsi3 (operands[0], operands[0], const1_rtx)); + + DONE; + } + + + default: + gcc_unreachable (); + } +}) + + +(define_insn "slts_compare" + [(set (match_operand:SI 0 "register_operand" "=t, t, r, r") + (lt:SI (match_operand:SI 1 "nonmemory_operand" " d, d, r, r") + (match_operand:SI 2 "nonmemory_operand" " r, Iu05, r, Is15")))] + "" + "@ + slts45\t%1, %2 + sltsi45\t%1, %2 + slts\t%0, %1, %2 + sltsi\t%0, %1, %2" + [(set_attr "type" "compare,compare,compare,compare") + (set_attr "length" " 2, 2, 4, 4")]) + +(define_insn "slt_compare" + [(set (match_operand:SI 0 "register_operand" "=t, t, r, r") + (ltu:SI (match_operand:SI 1 "nonmemory_operand" " d, d, r, r") + (match_operand:SI 2 "nonmemory_operand" " r, Iu05, r, Is15")))] + "" + "@ + slt45\t%1, %2 + slti45\t%1, %2 + slt\t%0, %1, %2 + slti\t%0, %1, %2" + [(set_attr "type" "compare,compare,compare,compare") + (set_attr "length" " 2, 2, 4, 4")]) + + +;; ---------------------------------------------------------------------------- + +;; Unconditional and other jump instructions. + +(define_insn "jump" + [(set (pc) (label_ref (match_operand 0 "" "")))] + "" +{ + /* This unconditional jump has two forms: + 32-bit instruction => j imm24s << 1 + 16-bit instruction => j8 imm8s << 1 + + For 32-bit case, + we assume it is always reachable. + For 16-bit case, + it must satisfy { 255 >= (label - pc) >= -256 } condition. + However, since the $pc for nds32 is at the beginning of the instruction, + we should leave some length space for current insn. + So we use range -250 ~ 250. */ + switch (get_attr_length (insn)) + { + case 2: + return "j8\t%0"; + case 4: + return "j\t%0"; + default: + gcc_unreachable (); + } +} + [(set_attr "type" "branch") + (set_attr "enabled" "1") + (set (attr "length") + (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -250)) + (le (minus (match_dup 0) (pc)) (const_int 250))) + (if_then_else (match_test "TARGET_16_BIT") + (const_int 2) + (const_int 4)) + (const_int 4)))]) + +(define_insn "indirect_jump" + [(set (pc) (match_operand:SI 0 "register_operand" "r, r"))] + "" + "@ + jr5\t%0 + jr\t%0" + [(set_attr "type" "branch,branch") + (set_attr "length" " 2, 4")]) + +;; Subroutine call instruction returning no value. +;; operands[0]: It should be a mem RTX whose address is +;; the the address of the function. +;; operands[1]: It is the number of bytes of arguments pushed as a const_int. +;; operands[2]: It is the number of registers used as operands. + +(define_expand "call" + [(parallel [(call (match_operand 0 "memory_operand" "") + (match_operand 1)) + (clobber (reg:SI LP_REGNUM))])] + "" + "" +) + +(define_insn "*call_register" + [(parallel [(call (mem (match_operand:SI 0 "register_operand" "r, r")) + (match_operand 1)) + (clobber (reg:SI LP_REGNUM))])] + "" + "@ + jral5\t%0 + jral\t%0" + [(set_attr "type" "branch,branch") + (set_attr "length" " 2, 4")]) + +(define_insn "*call_immediate" + [(parallel [(call (mem (match_operand:SI 0 "immediate_operand" "i")) + (match_operand 1)) + (clobber (reg:SI LP_REGNUM))])] + "" + "jal\t%0" + [(set_attr "type" "branch") + (set_attr "length" "4")]) + + +;; Subroutine call instruction returning a value. +;; operands[0]: It is the hard regiser in which the value is returned. +;; The rest three operands are the same as the +;; three operands of the 'call' instruction. +;; (but with numbers increased by one) + +(define_expand "call_value" + [(parallel [(set (match_operand 0) + (call (match_operand 1 "memory_operand" "") + (match_operand 2))) + (clobber (reg:SI LP_REGNUM))])] + "" + "" +) + +(define_insn "*call_value_register" + [(parallel [(set (match_operand 0) + (call (mem (match_operand:SI 1 "register_operand" "r, r")) + (match_operand 2))) + (clobber (reg:SI LP_REGNUM))])] + "" + "@ + jral5\t%1 + jral\t%1" + [(set_attr "type" "branch,branch") + (set_attr "length" " 2, 4")]) + +(define_insn "*call_value_immediate" + [(parallel [(set (match_operand 0) + (call (mem (match_operand:SI 1 "immediate_operand" "i")) + (match_operand 2))) + (clobber (reg:SI LP_REGNUM))])] + "" + "jal\t%1" + [(set_attr "type" "branch") + (set_attr "length" "4")]) + + +;; prologue and epilogue. + +(define_expand "prologue" [(const_int 0)] + "" +{ + /* Note that only under V3/V3M ISA, we could use v3push prologue. */ + if (TARGET_V3PUSH) + nds32_expand_prologue_v3push (); + else + nds32_expand_prologue (); + DONE; +}) + +(define_expand "epilogue" [(const_int 0)] + "" +{ + /* Note that only under V3/V3M ISA, we could use v3pop epilogue. */ + if (TARGET_V3PUSH) + nds32_expand_epilogue_v3pop (); + else + nds32_expand_epilogue (); + DONE; +}) + + +;; nop instruction. + +(define_insn "nop" + [(const_int 0)] + "" +{ + if (TARGET_16_BIT) + return "nop16"; + else + return "nop"; +} + [(set_attr "type" "misc") + (set_attr "enabled" "1") + (set (attr "length") + (if_then_else (match_test "TARGET_16_BIT") + (const_int 2) + (const_int 4)))]) + + +;; ---------------------------------------------------------------------------- +;; Stack push/pop operations +;; ---------------------------------------------------------------------------- + +;; The pattern for stack push. +;; Both stack_push_multiple and stack_v3push use the following pattern. +;; So we need to use TARGET_V3PUSH to determine the instruction length. +(define_insn "*stack_push" + [(match_parallel 0 "nds32_stack_push_operation" + [(set (mem:SI (plus:SI (reg:SI SP_REGNUM) + (match_operand:SI 1 "const_int_operand" ""))) + (match_operand:SI 2 "register_operand" "")) + ])] + "" +{ + return nds32_output_stack_push (); +} + [(set_attr "type" "misc") + (set_attr "enabled" "1") + (set (attr "length") + (if_then_else (match_test "TARGET_V3PUSH") + (const_int 2) + (const_int 4)))]) + + +;; The pattern for stack pop. +;; Both stack_pop_multiple and stack_v3pop use the following pattern. +;; So we need to use TARGET_V3PUSH to determine the instruction length. +(define_insn "*stack_pop" + [(match_parallel 0 "nds32_stack_pop_operation" + [(set (match_operand:SI 1 "register_operand" "") + (mem:SI (reg:SI SP_REGNUM))) + ])] + "" +{ + return nds32_output_stack_pop (); +} + [(set_attr "type" "misc") + (set_attr "enabled" "1") + (set (attr "length") + (if_then_else (match_test "TARGET_V3PUSH") + (const_int 2) + (const_int 4)))]) + + +;; ---------------------------------------------------------------------------- +;; unspec operation patterns +;; ---------------------------------------------------------------------------- + +;; In nds32 target, the 'ret5' instuction is actually 'jr5 $lp'. +;; This pattern is designed to distinguish function return +;; from general indirect_jump pattern so that we can directly +;; generate 'ret5' for readability. + +(define_insn "unspec_volatile_func_return" + [(set (pc) + (unspec_volatile:SI [(reg:SI LP_REGNUM)] UNSPEC_VOLATILE_FUNC_RETURN))] + "" +{ + if (TARGET_16_BIT) + return "ret5"; + else + return "ret"; +} + [(set_attr "type" "misc") + (set_attr "enabled" "1") + (set (attr "length") + (if_then_else (match_test "TARGET_16_BIT") + (const_int 2) + (const_int 4)))]) + + +;; ---------------------------------------------------------------------------- +;; Jump Table patterns +;; ---------------------------------------------------------------------------- +;; Need to implement ASM_OUTPUT_ADDR_VEC_ELT (for normal jump table) +;; or ASM_OUTPUT_ADDR_DIFF_ELT (for pc relative jump table) as well. +;; +;; operands[0]: The index to dispatch on. +;; operands[1]: The lower bound for indices in the table. +;; operands[2]: The total range of indices int the table. +;; i.e. The largest index minus the smallest one. +;; operands[3]: A label that precedes the table itself. +;; operands[4]: A label to jump to if the index has a value outside the bounds. +;; +;; We need to create following sequences for jump table code generation: +;; A) k <-- (plus (operands[0]) (-operands[1])) +;; B) if (gtu k operands[2]) then goto operands[4] +;; C) t <-- operands[3] +;; D) z <-- (mem (plus (k << 0 or 1 or 2) t)) +;; E) z <-- t + z (NOTE: This is only required for pc relative jump table.) +;; F) jump to target with register t or z +;; +;; The steps C, D, E, and F are performed by casesi_internal pattern. +(define_expand "casesi" + [(match_operand:SI 0 "register_operand" "r") ; index to jump on + (match_operand:SI 1 "immediate_operand" "i") ; lower bound + (match_operand:SI 2 "immediate_operand" "i") ; total range + (match_operand:SI 3 "" "") ; table label + (match_operand:SI 4 "" "")] ; Out of range label + "" +{ + rtx add_tmp; + rtx reg, test; + + /* Step A: "k <-- (plus (operands[0]) (-operands[1]))". */ + if (operands[1] != const0_rtx) + { + reg = gen_reg_rtx (SImode); + add_tmp = gen_int_mode (-INTVAL (operands[1]), SImode); + + /* If the integer value is not in the range of imm15s, + we need to force register first because our addsi3 pattern + only accept nds32_rimm15s_operand predicate. */ + add_tmp = force_reg (SImode, add_tmp); + + emit_insn (gen_addsi3 (reg, operands[0], add_tmp)); + operands[0] = reg; + } + + /* Step B: "if (gtu k operands[2]) then goto operands[4]". */ + test = gen_rtx_GTU (VOIDmode, operands[0], operands[2]); + emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[2], + operands[4])); + + operands[5] = gen_reg_rtx (SImode); + /* Step C, D, E, and F, using another temporary register operands[5]. */ + emit_jump_insn (gen_casesi_internal (operands[0], + operands[3], + operands[5])); + DONE; +}) + +;; We are receiving operands from casesi pattern: +;; +;; operands[0]: The index that have been substracted with lower bound. +;; operands[1]: A label that precedes the table itself. +;; operands[2]: A temporary register to retrieve value in table. +;; +;; We need to perform steps C, D, E, and F: +;; +;; C) t <-- operands[1] +;; D) z <-- (mem (plus (operands[0] << m) t)) +;; m is 2 for normal jump table. +;; m is 0, 1, or 2 for pc relative jump table based on diff size. +;; E) t <-- z + t (NOTE: This is only required for pc relative jump table.) +;; F) Jump to target with register t or z. +;; +;; The USE in this pattern is needed to tell flow analysis that this is +;; a CASESI insn. It has no other purpose. +(define_insn "casesi_internal" + [(parallel [(set (pc) + (mem:SI (plus:SI (mult:SI (match_operand:SI 0 "register_operand" "r") + (const_int 4)) + (label_ref (match_operand 1 "" ""))))) + (use (label_ref (match_dup 1))) + (clobber (match_operand:SI 2 "register_operand" "")) + (clobber (reg:SI TA_REGNUM))])] + "" +{ + if (CASE_VECTOR_PC_RELATIVE) + return nds32_output_casesi_pc_relative (operands); + else + return nds32_output_casesi (operands); +} + [(set_attr "length" "20") + (set_attr "type" "alu")]) + +;; ---------------------------------------------------------------------------- + +;; Performance Extension + +(define_insn "clzsi2" + [(set (match_operand:SI 0 "register_operand" "=r") + (clz:SI (match_operand:SI 1 "register_operand" " r")))] + "TARGET_PERF_EXT" + "clz\t%0, %1" + [(set_attr "type" "alu") + (set_attr "length" "4")]) + +(define_insn "smaxsi3" + [(set (match_operand:SI 0 "register_operand" "=r") + (smax:SI (match_operand:SI 1 "register_operand" " r") + (match_operand:SI 2 "register_operand" " r")))] + "TARGET_PERF_EXT" + "max\t%0, %1, %2" + [(set_attr "type" "alu") + (set_attr "length" "4")]) + +(define_insn "sminsi3" + [(set (match_operand:SI 0 "register_operand" "=r") + (smin:SI (match_operand:SI 1 "register_operand" " r") + (match_operand:SI 2 "register_operand" " r")))] + "TARGET_PERF_EXT" + "min\t%0, %1, %2" + [(set_attr "type" "alu") + (set_attr "length" "4")]) + +(define_insn "*btst" + [(set (match_operand:SI 0 "register_operand" "= r") + (zero_extract:SI (match_operand:SI 1 "register_operand" " r") + (const_int 1) + (match_operand:SI 2 "immediate_operand" " Iu05")))] + "TARGET_PERF_EXT" + "btst\t%0, %1, %2" + [(set_attr "type" "alu") + (set_attr "length" "4")]) + +;; ---------------------------------------------------------------------------- diff --git a/gcc/config/nds32/nds32.opt b/gcc/config/nds32/nds32.opt new file mode 100644 index 00000000000..b2b45bb3e02 --- /dev/null +++ b/gcc/config/nds32/nds32.opt @@ -0,0 +1,102 @@ +; Options of Andes NDS32 cpu for GNU compiler +; Copyright (C) 2012-2013 Free Software Foundation, Inc. +; Contributed by Andes Technology Corporation. +; +; This file is part of GCC. +; +; GCC is free software; you can redistribute it and/or modify it +; under the terms of the GNU General Public License as published +; by the Free Software Foundation; either version 3, or (at your +; option) any later version. +; +; GCC is distributed in the hope that it will be useful, but WITHOUT +; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +; License for more details. +; +; You should have received a copy of the GNU General Public License +; along with GCC; see the file COPYING3. If not see +; <http://www.gnu.org/licenses/>. + +HeaderInclude +config/nds32/nds32-opts.h + +mbig-endian +Target Report RejectNegative Negative(mlittle-endian) Mask(BIG_ENDIAN) +Generate code in big-endian mode. + +mlittle-endian +Target Report RejectNegative Negative(mbig-endian) InverseMask(BIG_ENDIAN) +Generate code in little-endian mode. + +mreduced-regs +Target Report RejectNegative Negative(mfull-regs) Mask(REDUCED_REGS) +Use reduced-set registers for register allocation. + +mfull-regs +Target Report RejectNegative Negative(mreduced-regs) InverseMask(REDUCED_REGS) +Use full-set registers for register allocation. + +mcmov +Target Report Mask(CMOV) +Generate conditional move instructions. + +mperf-ext +Target Report Mask(PERF_EXT) +Generate performance extension instructions. + +mv3push +Target Report Mask(V3PUSH) +Generate v3 push25/pop25 instructions. + +m16-bit +Target Report Mask(16_BIT) +Generate 16-bit instructions. + +mgp-direct +Target Report Mask(GP_DIRECT) +Generate GP base instructions directly. + +misr-vector-size= +Target RejectNegative Joined UInteger Var(nds32_isr_vector_size) Init(NDS32_DEFAULT_ISR_VECTOR_SIZE) +Specify the size of each interrupt vector, which must be 4 or 16. + +mcache-block-size= +Target RejectNegative Joined UInteger Var(nds32_cache_block_size) Init(NDS32_DEFAULT_CACHE_BLOCK_SIZE) +Specify the size of each cache block, which must be a power of 2 between 4 and 512. + +march= +Target RejectNegative Joined Enum(nds32_arch_type) Var(nds32_arch_option) Init(ARCH_V3) +Specify the name of the target architecture. + +Enum +Name(nds32_arch_type) Type(enum nds32_arch_type) + +EnumValue +Enum(nds32_arch_type) String(v2) Value(ARCH_V2) + +EnumValue +Enum(nds32_arch_type) String(v3) Value(ARCH_V3) + +EnumValue +Enum(nds32_arch_type) String(v3m) Value(ARCH_V3M) + +mforce-fp-as-gp +Target Report Mask(FORCE_FP_AS_GP) +Prevent $fp being allocated during register allocation so that compiler is able to force performing fp-as-gp optimization. + +mforbid-fp-as-gp +Target Report Mask(FORBID_FP_AS_GP) +Forbid using $fp to access static and global variables. This option strictly forbids fp-as-gp optimization regardless of '-mforce-fp-as-gp'. + +mex9 +Target Report Mask(EX9) +Use special directives to guide linker doing ex9 optimization. + +mctor-dtor +Target Report +Enable constructor/destructor feature. + +mrelax +Target Report +Guide linker to relax instructions. diff --git a/gcc/config/nds32/nds32_intrinsic.h b/gcc/config/nds32/nds32_intrinsic.h new file mode 100644 index 00000000000..33064a966ed --- /dev/null +++ b/gcc/config/nds32/nds32_intrinsic.h @@ -0,0 +1,37 @@ +/* Intrinsic definitions of Andes NDS32 cpu for GNU compiler + Copyright (C) 2012-2013 Free Software Foundation, Inc. + Contributed by Andes Technology Corporation. + + This file is part of GCC. + + GCC is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 3, or (at your + option) any later version. + + GCC is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef _NDS32_INTRINSIC_H +#define _NDS32_INTRINSIC_H + +enum nds32_intrinsic_registers +{ + __NDS32_REG_PSW__ = 1024, + __NDS32_REG_IPSW__, + __NDS32_REG_ITYPE__, + __NDS32_REG_IPC__ +}; + +#endif /* nds32_intrinsic.h */ diff --git a/gcc/config/nds32/pipelines.md b/gcc/config/nds32/pipelines.md new file mode 100644 index 00000000000..9c8c56bab83 --- /dev/null +++ b/gcc/config/nds32/pipelines.md @@ -0,0 +1,29 @@ +;; Pipeline descriptions of Andes NDS32 cpu for GNU compiler +;; Copyright (C) 2012-2013 Free Software Foundation, Inc. +;; Contributed by Andes Technology Corporation. +;; +;; This file is part of GCC. +;; +;; GCC is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published +;; by the Free Software Foundation; either version 3, or (at your +;; option) any later version. +;; +;; GCC is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with GCC; see the file COPYING3. If not see +;; <http://www.gnu.org/licenses/>. + +(define_automaton "nds32_machine") + +(define_cpu_unit "general_unit" "nds32_machine") + +(define_insn_reservation "simple_insn" 1 + (eq_attr "type" "unknown,load,store,move,alu,compare,branch,call,misc") + "general_unit") + +;; ------------------------------------------------------------------------ diff --git a/gcc/config/nds32/predicates.md b/gcc/config/nds32/predicates.md new file mode 100644 index 00000000000..df4eccdb891 --- /dev/null +++ b/gcc/config/nds32/predicates.md @@ -0,0 +1,92 @@ +;; Predicate definitions of Andes NDS32 cpu for GNU compiler +;; Copyright (C) 2012-2013 Free Software Foundation, Inc. +;; Contributed by Andes Technology Corporation. +;; +;; This file is part of GCC. +;; +;; GCC is free software; you can redistribute it and/or modify it +;; under the terms of the GNU General Public License as published +;; by the Free Software Foundation; either version 3, or (at your +;; option) any later version. +;; +;; GCC is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +;; License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with GCC; see the file COPYING3. If not see +;; <http://www.gnu.org/licenses/>. + +(define_predicate "nds32_equality_comparison_operator" + (match_code "eq,ne")) + +(define_predicate "nds32_greater_less_comparison_operator" + (match_code "gt,ge,lt,le")) + +(define_special_predicate "nds32_logical_binary_operator" + (match_code "and,ior,xor")) + +(define_predicate "nds32_symbolic_operand" + (match_code "const,symbol_ref,label_ref")) + +(define_predicate "nds32_reg_constant_operand" + (ior (match_operand 0 "register_operand") + (match_operand 0 "const_int_operand"))) + +(define_predicate "nds32_rimm15s_operand" + (ior (match_operand 0 "register_operand") + (and (match_operand 0 "const_int_operand") + (match_test "satisfies_constraint_Is15 (op)")))) + +(define_predicate "nds32_imm5u_operand" + (and (match_operand 0 "const_int_operand") + (match_test "satisfies_constraint_Iu05 (op)"))) + +(define_predicate "nds32_move_operand" + (and (match_operand 0 "general_operand") + (not (match_code "high,const,symbol_ref,label_ref"))) +{ + /* If the constant op does NOT satisfy Is20 nor Ihig, + we can not perform move behavior by a single instruction. */ + if (CONST_INT_P (op) + && !satisfies_constraint_Is20 (op) + && !satisfies_constraint_Ihig (op)) + return false; + + return true; +}) + +(define_special_predicate "nds32_load_multiple_operation" + (match_code "parallel") +{ + /* To verify 'load' operation, pass 'true' for the second argument. + See the implementation in nds32.c for details. */ + return nds32_valid_multiple_load_store (op, true); +}) + +(define_special_predicate "nds32_store_multiple_operation" + (match_code "parallel") +{ + /* To verify 'store' operation, pass 'false' for the second argument. + See the implementation in nds32.c for details. */ + return nds32_valid_multiple_load_store (op, false); +}) + +(define_special_predicate "nds32_stack_push_operation" + (match_code "parallel") +{ + /* To verify 'push' operation, pass 'true' for the second argument. + See the implementation in nds32.c for details. */ + return nds32_valid_stack_push_pop (op, true); +}) + +(define_special_predicate "nds32_stack_pop_operation" + (match_code "parallel") +{ + /* To verify 'pop' operation, pass 'false' for the second argument. + See the implementation in nds32.c for details. */ + return nds32_valid_stack_push_pop (op, false); +}) + +;; ------------------------------------------------------------------------ diff --git a/gcc/config/nds32/t-mlibs b/gcc/config/nds32/t-mlibs new file mode 100644 index 00000000000..ec546e48c1b --- /dev/null +++ b/gcc/config/nds32/t-mlibs @@ -0,0 +1,38 @@ +# The multilib settings of Andes NDS32 cpu for GNU compiler +# Copyright (C) 2012-2013 Free Software Foundation, Inc. +# Contributed by Andes Technology Corporation. +# +# This file is part of GCC. +# +# GCC is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published +# by the Free Software Foundation; either version 3, or (at your +# option) any later version. +# +# GCC is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +# License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# <http://www.gnu.org/licenses/>. + +# We need to build following multilibs combinations: +# +# 1. <None multilibs> +# 2. -mlittle-endian +# 3. -mbig-endian +# 4. -mgp-direct +# 5. -mno-gp-direct +# 6. -mlittle-endian -mgp-direct +# 7. -mlittle-endian -mno-gp-direct +# 8. -mbig-endian -mgp-direct +# 9. -mlittle-endian -mno-gp-direct +# +# We also define a macro MULTILIB_DEFAULTS in nds32.h that tells the +# driver program which options are defaults for this target and thus +# do not need to be handled specially. +MULTILIB_OPTIONS = mlittle-endian/mbig-endian mgp-direct/mno-gp-direct + +# ------------------------------------------------------------------------ diff --git a/gcc/config/rl78/rl78.c b/gcc/config/rl78/rl78.c index 995f3b1754d..f071e31daf2 100644 --- a/gcc/config/rl78/rl78.c +++ b/gcc/config/rl78/rl78.c @@ -1894,8 +1894,8 @@ post-reload optimizers could operate on the real registers, but when I tried that there were some issues building the target libraries. During devirtualization, a simple register move optimizer is run. It -would be better to run a full CSE/propogation pass on it through, or -re-run regmove, but that has not yet been attempted. +would be better to run a full CSE/propogation pass on it though, but +that has not yet been attempted. */ #define DEBUG_ALLOC 0 diff --git a/gcc/config/rs6000/aix.h b/gcc/config/rs6000/aix.h index f81666a3b11..a11bd57284d 100644 --- a/gcc/config/rs6000/aix.h +++ b/gcc/config/rs6000/aix.h @@ -66,30 +66,6 @@ /* Because of the above, we must have gcc search itself to find libgcc.a. */ #define LINK_LIBGCC_SPECIAL_1 -#define MFWRAP_SPEC " %{static: %{fmudflap|fmudflapth: \ - -brename:malloc,__wrap_malloc -brename:__real_malloc,malloc \ - -brename:free,__wrap_free -brename:__real_free,free \ - -brename:calloc,__wrap_calloc -brename:__real_calloc,calloc \ - -brename:realloc,__wrap_realloc -brename:__real_realloc,realloc \ - -brename:mmap,__wrap_mmap -brename:__real_mmap,mmap \ - -brename:munmap,__wrap_munmap -brename:__real_munmap,munmap \ - -brename:alloca,__wrap_alloca -brename:__real_alloca,alloca \ -} %{fmudflapth: \ - -brename:pthread_create,__wrap_pthread_create \ - -brename:__real_pthread_create,pthread_create \ - -brename:pthread_join,__wrap_pthread_join \ - -brename:__real_pthread_join,pthread_join \ - -brename:pthread_exit,__wrap_pthread_exit \ - -brename:__real_pthread_exit,pthread_exit \ -}} %{fmudflap|fmudflapth: \ - -brename:main,__wrap_main -brename:__real_main,main \ -}" - -#define MFLIB_SPEC " %{fmudflap: -lmudflap \ - %{static:%(link_gcc_c_sequence) -lmudflap}} \ - %{fmudflapth: -lmudflapth -lpthread \ - %{static:%(link_gcc_c_sequence) -lmudflapth}} " - /* Names to predefine in the preprocessor for this target machine. */ #define TARGET_OS_AIX_CPP_BUILTINS() \ do \ diff --git a/gcc/config/rs6000/altivec.md b/gcc/config/rs6000/altivec.md index 93aaa12076b..37c59980ecf 100644 --- a/gcc/config/rs6000/altivec.md +++ b/gcc/config/rs6000/altivec.md @@ -681,7 +681,10 @@ emit_insn (gen_altivec_vmrghw (high, even, odd)); emit_insn (gen_altivec_vmrglw (low, even, odd)); - emit_insn (gen_altivec_vpkuwum (operands[0], high, low)); + if (BYTES_BIG_ENDIAN) + emit_insn (gen_altivec_vpkuwum (operands[0], high, low)); + else + emit_insn (gen_altivec_vpkuwum (operands[0], low, high)); DONE; }") diff --git a/gcc/config/rs6000/linux.h b/gcc/config/rs6000/linux.h index 2e5a56b3929..f7df111b57e 100644 --- a/gcc/config/rs6000/linux.h +++ b/gcc/config/rs6000/linux.h @@ -145,3 +145,9 @@ /* Static stack checking is supported by means of probes. */ #define STACK_CHECK_STATIC_BUILTIN 1 + +/* Software floating point support for exceptions and rounding modes + depends on the C library in use. */ +#undef TARGET_FLOAT_EXCEPTIONS_ROUNDING_SUPPORTED_P +#define TARGET_FLOAT_EXCEPTIONS_ROUNDING_SUPPORTED_P \ + rs6000_linux_float_exceptions_rounding_supported_p diff --git a/gcc/config/rs6000/linux64.h b/gcc/config/rs6000/linux64.h index 439f53f2d23..c1adbd78a4d 100644 --- a/gcc/config/rs6000/linux64.h +++ b/gcc/config/rs6000/linux64.h @@ -558,3 +558,9 @@ extern int dot_symbols; /* The default value isn't sufficient in 64-bit mode. */ #define STACK_CHECK_PROTECT (TARGET_64BIT ? 16 * 1024 : 12 * 1024) + +/* Software floating point support for exceptions and rounding modes + depends on the C library in use. */ +#undef TARGET_FLOAT_EXCEPTIONS_ROUNDING_SUPPORTED_P +#define TARGET_FLOAT_EXCEPTIONS_ROUNDING_SUPPORTED_P \ + rs6000_linux_float_exceptions_rounding_supported_p diff --git a/gcc/config/rs6000/rs6000-linux.c b/gcc/config/rs6000/rs6000-linux.c new file mode 100644 index 00000000000..17b51af7ead --- /dev/null +++ b/gcc/config/rs6000/rs6000-linux.c @@ -0,0 +1,38 @@ +/* Functions for Linux on PowerPC. + Copyright (C) 2013 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" +#include "rtl.h" +#include "tm_p.h" + +/* Implement TARGET_FLOAT_EXCEPTIONS_ROUNDING_SUPPORTED_P. */ + +bool +rs6000_linux_float_exceptions_rounding_supported_p (void) +{ + /* glibc has support for exceptions and rounding modes for software + floating point. */ + if (OPTION_GLIBC) + return true; + else + return TARGET_DF_INSN; +} diff --git a/gcc/config/rs6000/rs6000-modes.def b/gcc/config/rs6000/rs6000-modes.def index 5124e1665d4..a77aa26e850 100644 --- a/gcc/config/rs6000/rs6000-modes.def +++ b/gcc/config/rs6000/rs6000-modes.def @@ -45,4 +45,4 @@ VECTOR_MODES (FLOAT, 32); /* V16HF V8SF V4DF */ /* Replacement for TImode that only is allowed in GPRs. We also use PTImode for quad memory atomic operations to force getting an even/odd register combination. */ -PARTIAL_INT_MODE (TI); +PARTIAL_INT_MODE (TI, 128, PTI); diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index 1fc89034094..d1d1737dca1 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -126,6 +126,8 @@ extern void rs6000_split_multireg_move (rtx, rtx); extern void rs6000_emit_le_vsx_move (rtx, rtx, enum machine_mode); extern void rs6000_emit_move (rtx, rtx, enum machine_mode); extern rtx rs6000_secondary_memory_needed_rtx (enum machine_mode); +extern enum machine_mode rs6000_secondary_memory_needed_mode (enum + machine_mode); extern rtx (*rs6000_legitimize_reload_address_ptr) (rtx, enum machine_mode, int, int, int, int *); extern bool rs6000_legitimate_offset_address_p (enum machine_mode, rtx, @@ -210,4 +212,6 @@ void rs6000_final_prescan_insn (rtx, rtx *operand, int num_operands); extern bool rs6000_hard_regno_mode_ok_p[][FIRST_PSEUDO_REGISTER]; extern unsigned char rs6000_class_max_nregs[][LIM_REG_CLASSES]; extern unsigned char rs6000_hard_regno_nregs[][FIRST_PSEUDO_REGISTER]; + +extern bool rs6000_linux_float_exceptions_rounding_supported_p (void); #endif /* rs6000-protos.h */ diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index c3a91891f11..1deb3e5c3e7 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -55,6 +55,7 @@ #include "intl.h" #include "params.h" #include "tm-constrs.h" +#include "ira.h" #include "opts.h" #include "tree-vectorizer.h" #include "dumpfile.h" @@ -1554,6 +1555,9 @@ static const struct attribute_spec rs6000_attribute_table[] = #undef TARGET_MODE_DEPENDENT_ADDRESS_P #define TARGET_MODE_DEPENDENT_ADDRESS_P rs6000_mode_dependent_address_p +#undef TARGET_LRA_P +#define TARGET_LRA_P rs6000_lra_p + #undef TARGET_CAN_ELIMINATE #define TARGET_CAN_ELIMINATE rs6000_can_eliminate @@ -5530,10 +5534,27 @@ rs6000_expand_vector_set (rtx target, rtx val, int elt) XVECEXP (mask, 0, elt*width + i) = GEN_INT (i + 0x10); x = gen_rtx_CONST_VECTOR (V16QImode, XVEC (mask, 0)); - x = gen_rtx_UNSPEC (mode, - gen_rtvec (3, target, reg, - force_reg (V16QImode, x)), - UNSPEC_VPERM); + + if (BYTES_BIG_ENDIAN) + x = gen_rtx_UNSPEC (mode, + gen_rtvec (3, target, reg, + force_reg (V16QImode, x)), + UNSPEC_VPERM); + else + { + /* Invert selector. */ + rtx splat = gen_rtx_VEC_DUPLICATE (V16QImode, + gen_rtx_CONST_INT (QImode, -1)); + rtx tmp = gen_reg_rtx (V16QImode); + emit_move_insn (tmp, splat); + x = gen_rtx_MINUS (V16QImode, tmp, force_reg (V16QImode, x)); + emit_move_insn (tmp, x); + + /* Permute with operands reversed and adjusted selector. */ + x = gen_rtx_UNSPEC (mode, gen_rtvec (3, reg, target, tmp), + UNSPEC_VPERM); + } + emit_insn (gen_rtx_SET (VOIDmode, target, x)); } @@ -6231,7 +6252,7 @@ rs6000_legitimate_offset_address_p (enum machine_mode mode, rtx x, return false; if (!reg_offset_addressing_ok_p (mode)) return virtual_stack_registers_memory_p (x); - if (legitimate_constant_pool_address_p (x, mode, strict)) + if (legitimate_constant_pool_address_p (x, mode, strict || lra_in_progress)) return true; if (GET_CODE (XEXP (x, 1)) != CONST_INT) return false; @@ -6371,19 +6392,31 @@ legitimate_lo_sum_address_p (enum machine_mode mode, rtx x, int strict) if (TARGET_ELF || TARGET_MACHO) { + bool large_toc_ok; + if (DEFAULT_ABI != ABI_AIX && DEFAULT_ABI != ABI_DARWIN && flag_pic) return false; - if (TARGET_TOC) + /* LRA don't use LEGITIMIZE_RELOAD_ADDRESS as it usually calls + push_reload from reload pass code. LEGITIMIZE_RELOAD_ADDRESS + recognizes some LO_SUM addresses as valid although this + function says opposite. In most cases, LRA through different + transformations can generate correct code for address reloads. + It can not manage only some LO_SUM cases. So we need to add + code analogous to one in rs6000_legitimize_reload_address for + LOW_SUM here saying that some addresses are still valid. */ + large_toc_ok = (lra_in_progress && TARGET_CMODEL != CMODEL_SMALL + && small_toc_ref (x, VOIDmode)); + if (TARGET_TOC && ! large_toc_ok) return false; if (GET_MODE_NUNITS (mode) != 1) return false; - if (GET_MODE_SIZE (mode) > UNITS_PER_WORD + if (! lra_in_progress && GET_MODE_SIZE (mode) > UNITS_PER_WORD && !(/* ??? Assume floating point reg based on mode? */ TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && (mode == DFmode || mode == DDmode))) return false; - return CONSTANT_P (x); + return CONSTANT_P (x) || large_toc_ok; } return false; @@ -7374,7 +7407,8 @@ rs6000_legitimate_address_p (enum machine_mode mode, rtx x, bool reg_ok_strict) if (reg_offset_p && legitimate_small_data_p (mode, x)) return 1; if (reg_offset_p - && legitimate_constant_pool_address_p (x, mode, reg_ok_strict)) + && legitimate_constant_pool_address_p (x, mode, + reg_ok_strict || lra_in_progress)) return 1; /* For TImode, if we have load/store quad and TImode in VSX registers, only allow register indirect addresses. This will allow the values to go in @@ -7660,6 +7694,7 @@ rs6000_conditional_register_usage (void) fixed_regs[i] = call_used_regs[i] = call_really_used_regs[i] = 1; } } + /* Try to output insns to set TARGET equal to the constant C if it can be done in less than N insns. Do all computations in MODE. @@ -8055,6 +8090,68 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode) cfun->machine->sdmode_stack_slot = eliminate_regs (cfun->machine->sdmode_stack_slot, VOIDmode, NULL_RTX); + + if (lra_in_progress + && mode == SDmode + && REG_P (operands[0]) && REGNO (operands[0]) >= FIRST_PSEUDO_REGISTER + && reg_preferred_class (REGNO (operands[0])) == NO_REGS + && (REG_P (operands[1]) + || (GET_CODE (operands[1]) == SUBREG + && REG_P (SUBREG_REG (operands[1]))))) + { + int regno = REGNO (GET_CODE (operands[1]) == SUBREG + ? SUBREG_REG (operands[1]) : operands[1]); + enum reg_class cl; + + if (regno >= FIRST_PSEUDO_REGISTER) + { + cl = reg_preferred_class (regno); + gcc_assert (cl != NO_REGS); + regno = ira_class_hard_regs[cl][0]; + } + if (FP_REGNO_P (regno)) + { + if (GET_MODE (operands[0]) != DDmode) + operands[0] = gen_rtx_SUBREG (DDmode, operands[0], 0); + emit_insn (gen_movsd_store (operands[0], operands[1])); + } + else if (INT_REGNO_P (regno)) + emit_insn (gen_movsd_hardfloat (operands[0], operands[1])); + else + gcc_unreachable(); + return; + } + if (lra_in_progress + && mode == SDmode + && (REG_P (operands[0]) + || (GET_CODE (operands[0]) == SUBREG + && REG_P (SUBREG_REG (operands[0])))) + && REG_P (operands[1]) && REGNO (operands[1]) >= FIRST_PSEUDO_REGISTER + && reg_preferred_class (REGNO (operands[1])) == NO_REGS) + { + int regno = REGNO (GET_CODE (operands[0]) == SUBREG + ? SUBREG_REG (operands[0]) : operands[0]); + enum reg_class cl; + + if (regno >= FIRST_PSEUDO_REGISTER) + { + cl = reg_preferred_class (regno); + gcc_assert (cl != NO_REGS); + regno = ira_class_hard_regs[cl][0]; + } + if (FP_REGNO_P (regno)) + { + if (GET_MODE (operands[1]) != DDmode) + operands[1] = gen_rtx_SUBREG (DDmode, operands[1], 0); + emit_insn (gen_movsd_load (operands[0], operands[1])); + } + else if (INT_REGNO_P (regno)) + emit_insn (gen_movsd_hardfloat (operands[0], operands[1])); + else + gcc_unreachable(); + return; + } + if (reload_in_progress && mode == SDmode && cfun->machine->sdmode_stack_slot != NULL_RTX @@ -14902,6 +14999,17 @@ rs6000_secondary_memory_needed_rtx (enum machine_mode mode) return ret; } +/* Return the mode to be used for memory when a secondary memory + location is needed. For SDmode values we need to use DDmode, in + all other cases we can use the same mode. */ +enum machine_mode +rs6000_secondary_memory_needed_mode (enum machine_mode mode) +{ + if (mode == SDmode) + return DDmode; + return mode; +} + static tree rs6000_check_sdmode (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED) { @@ -15795,6 +15903,10 @@ rs6000_alloc_sdmode_stack_slot (void) gimple_stmt_iterator gsi; gcc_assert (cfun->machine->sdmode_stack_slot == NULL_RTX); + /* We use a different approach for dealing with the secondary + memory in LRA. */ + if (ira_use_lra_p) + return; if (TARGET_NO_SDMODE_STACK) return; @@ -16016,7 +16128,7 @@ rs6000_secondary_reload_class (enum reg_class rclass, enum machine_mode mode, /* Constants, memory, and FP registers can go into FP registers. */ if ((regno == -1 || FP_REGNO_P (regno)) && (rclass == FLOAT_REGS || rclass == NON_SPECIAL_REGS)) - return (mode != SDmode) ? NO_REGS : GENERAL_REGS; + return (mode != SDmode || lra_in_progress) ? NO_REGS : GENERAL_REGS; /* Memory, and FP/altivec registers can go into fp/altivec registers under VSX. However, for scalar variables, use the traditional floating point @@ -28845,17 +28957,23 @@ altivec_expand_vec_perm_const (rtx operands[4]) { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31 } }, { OPTION_MASK_ALTIVEC, CODE_FOR_altivec_vpkuwum, { 2, 3, 6, 7, 10, 11, 14, 15, 18, 19, 22, 23, 26, 27, 30, 31 } }, - { OPTION_MASK_ALTIVEC, CODE_FOR_altivec_vmrghb, + { OPTION_MASK_ALTIVEC, + BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrghb : CODE_FOR_altivec_vmrglb, { 0, 16, 1, 17, 2, 18, 3, 19, 4, 20, 5, 21, 6, 22, 7, 23 } }, - { OPTION_MASK_ALTIVEC, CODE_FOR_altivec_vmrghh, + { OPTION_MASK_ALTIVEC, + BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrghh : CODE_FOR_altivec_vmrglh, { 0, 1, 16, 17, 2, 3, 18, 19, 4, 5, 20, 21, 6, 7, 22, 23 } }, - { OPTION_MASK_ALTIVEC, CODE_FOR_altivec_vmrghw, + { OPTION_MASK_ALTIVEC, + BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrghw : CODE_FOR_altivec_vmrglw, { 0, 1, 2, 3, 16, 17, 18, 19, 4, 5, 6, 7, 20, 21, 22, 23 } }, - { OPTION_MASK_ALTIVEC, CODE_FOR_altivec_vmrglb, + { OPTION_MASK_ALTIVEC, + BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrglb : CODE_FOR_altivec_vmrghb, { 8, 24, 9, 25, 10, 26, 11, 27, 12, 28, 13, 29, 14, 30, 15, 31 } }, - { OPTION_MASK_ALTIVEC, CODE_FOR_altivec_vmrglh, + { OPTION_MASK_ALTIVEC, + BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrglh : CODE_FOR_altivec_vmrghh, { 8, 9, 24, 25, 10, 11, 26, 27, 12, 13, 28, 29, 14, 15, 30, 31 } }, - { OPTION_MASK_ALTIVEC, CODE_FOR_altivec_vmrglw, + { OPTION_MASK_ALTIVEC, + BYTES_BIG_ENDIAN ? CODE_FOR_altivec_vmrglw : CODE_FOR_altivec_vmrghw, { 8, 9, 10, 11, 24, 25, 26, 27, 12, 13, 14, 15, 28, 29, 30, 31 } }, { OPTION_MASK_P8_VECTOR, CODE_FOR_p8_vmrgew, { 0, 1, 2, 3, 16, 17, 18, 19, 8, 9, 10, 11, 24, 25, 26, 27 } }, @@ -28988,6 +29106,26 @@ altivec_expand_vec_perm_const (rtx operands[4]) enum machine_mode omode = insn_data[icode].operand[0].mode; enum machine_mode imode = insn_data[icode].operand[1].mode; + /* For little-endian, don't use vpkuwum and vpkuhum if the + underlying vector type is not V4SI and V8HI, respectively. + For example, using vpkuwum with a V8HI picks up the even + halfwords (BE numbering) when the even halfwords (LE + numbering) are what we need. */ + if (!BYTES_BIG_ENDIAN + && icode == CODE_FOR_altivec_vpkuwum + && ((GET_CODE (op0) == REG + && GET_MODE (op0) != V4SImode) + || (GET_CODE (op0) == SUBREG + && GET_MODE (XEXP (op0, 0)) != V4SImode))) + continue; + if (!BYTES_BIG_ENDIAN + && icode == CODE_FOR_altivec_vpkuhum + && ((GET_CODE (op0) == REG + && GET_MODE (op0) != V8HImode) + || (GET_CODE (op0) == SUBREG + && GET_MODE (XEXP (op0, 0)) != V8HImode))) + continue; + /* For little-endian, the two input operands must be swapped (or swapped back) to ensure proper right-to-left numbering from 0 to 2N-1. */ @@ -29345,6 +29483,13 @@ rs6000_libcall_value (enum machine_mode mode) } +/* Return true if we use LRA instead of reload pass. */ +static bool +rs6000_lra_p (void) +{ + return rs6000_lra_flag; +} + /* Given FROM and TO register numbers, say whether this elimination is allowed. Frame pointer elimination is automatically handled. diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index 387d8c99ac1..9b167b7399e 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -1488,6 +1488,13 @@ extern enum reg_class rs6000_constraints[RS6000_CONSTRAINT_MAX]; #define SECONDARY_MEMORY_NEEDED_RTX(MODE) \ rs6000_secondary_memory_needed_rtx (MODE) +/* Specify the mode to be used for memory when a secondary memory + location is needed. For cpus that cannot load/store SDmode values + from the 64-bit FP registers without using a full 64-bit + load/store, we need a wider mode. */ +#define SECONDARY_MEMORY_NEEDED_MODE(MODE) \ + rs6000_secondary_memory_needed_mode (MODE) + /* Return the maximum number of consecutive registers needed to represent mode MODE in a register of class CLASS. diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 9961c1e9c23..11829189eb6 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -2699,7 +2699,7 @@ (match_operand:SI 2 "gpc_reg_operand" "r,r")) (const_int 0))) (clobber (match_scratch:SI 3 "=r,r"))] - "" + "TARGET_32BIT" "@ mullw. %3,%1,%2 #" @@ -2712,7 +2712,7 @@ (match_operand:SI 2 "gpc_reg_operand" "")) (const_int 0))) (clobber (match_scratch:SI 3 ""))] - "reload_completed" + "TARGET_32BIT && reload_completed" [(set (match_dup 3) (mult:SI (match_dup 1) (match_dup 2))) (set (match_dup 0) @@ -2727,7 +2727,7 @@ (const_int 0))) (set (match_operand:SI 0 "gpc_reg_operand" "=r,r") (mult:SI (match_dup 1) (match_dup 2)))] - "" + "TARGET_32BIT" "@ mullw. %0,%1,%2 #" @@ -2741,7 +2741,7 @@ (const_int 0))) (set (match_operand:SI 0 "gpc_reg_operand" "") (mult:SI (match_dup 1) (match_dup 2)))] - "reload_completed" + "TARGET_32BIT && reload_completed" [(set (match_dup 0) (mult:SI (match_dup 1) (match_dup 2))) (set (match_dup 3) diff --git a/gcc/config/rs6000/rs6000.opt b/gcc/config/rs6000/rs6000.opt index c3f9c2d44a3..94e4b3883dc 100644 --- a/gcc/config/rs6000/rs6000.opt +++ b/gcc/config/rs6000/rs6000.opt @@ -449,6 +449,10 @@ mlong-double- Target RejectNegative Joined UInteger Var(rs6000_long_double_type_size) Save -mlong-double-<n> Specify size of long double (64 or 128 bits) +mlra +Target Report Var(rs6000_lra_flag) Init(0) Save +Use LRA instead of reload + msched-costly-dep= Target RejectNegative Joined Var(rs6000_sched_costly_dep_str) Determine which dependences between insns are considered costly diff --git a/gcc/config/rs6000/t-linux b/gcc/config/rs6000/t-linux index 62a5b941389..0b92eba4617 100644 --- a/gcc/config/rs6000/t-linux +++ b/gcc/config/rs6000/t-linux @@ -7,3 +7,7 @@ else MULTIARCH_DIRNAME = powerpc-linux-gnu endif endif + +rs6000-linux.o: $(srcdir)/config/rs6000/rs6000-linux.c + $(COMPILE) $< + $(POSTCOMPILE) diff --git a/gcc/config/rs6000/t-linux64 b/gcc/config/rs6000/t-linux64 index 70e928dd7cd..0b17ed6a5cf 100644 --- a/gcc/config/rs6000/t-linux64 +++ b/gcc/config/rs6000/t-linux64 @@ -30,3 +30,7 @@ MULTILIB_DIRNAMES := 64 32 MULTILIB_EXTRA_OPTS := MULTILIB_OSDIRNAMES := m64=../lib64$(call if_multiarch,:powerpc64-linux-gnu) MULTILIB_OSDIRNAMES += m32=$(if $(wildcard $(shell echo $(SYSTEM_HEADER_DIR))/../../usr/lib32),../lib32,../lib)$(call if_multiarch,:powerpc-linux-gnu) + +rs6000-linux.o: $(srcdir)/config/rs6000/rs6000-linux.c + $(COMPILE) $< + $(POSTCOMPILE) diff --git a/gcc/config/rs6000/vector.md b/gcc/config/rs6000/vector.md index 8b067b19729..0a1130f7bff 100644 --- a/gcc/config/rs6000/vector.md +++ b/gcc/config/rs6000/vector.md @@ -830,7 +830,12 @@ emit_insn (gen_vsx_xvcvdpsp (r1, operands[1])); emit_insn (gen_vsx_xvcvdpsp (r2, operands[2])); - rs6000_expand_extract_even (operands[0], r1, r2); + + if (BYTES_BIG_ENDIAN) + rs6000_expand_extract_even (operands[0], r1, r2); + else + rs6000_expand_extract_even (operands[0], r2, r1); + DONE; }) diff --git a/gcc/config/rs6000/vsx.md b/gcc/config/rs6000/vsx.md index df87c196754..8a51afb3c86 100644 --- a/gcc/config/rs6000/vsx.md +++ b/gcc/config/rs6000/vsx.md @@ -333,12 +333,18 @@ [(set_attr "type" "vecload") (set_attr "length" "8")]) -(define_insn_and_split "*vsx_le_perm_store_<mode>" +(define_insn "*vsx_le_perm_store_<mode>" [(set (match_operand:VSX_D 0 "memory_operand" "=Z") (match_operand:VSX_D 1 "vsx_register_operand" "+wa"))] "!BYTES_BIG_ENDIAN && TARGET_VSX" "#" - "!BYTES_BIG_ENDIAN && TARGET_VSX" + [(set_attr "type" "vecstore") + (set_attr "length" "12")]) + +(define_split + [(set (match_operand:VSX_D 0 "memory_operand" "") + (match_operand:VSX_D 1 "vsx_register_operand" ""))] + "!BYTES_BIG_ENDIAN && TARGET_VSX && !reload_completed" [(set (match_dup 2) (vec_select:<MODE> (match_dup 1) @@ -347,21 +353,43 @@ (vec_select:<MODE> (match_dup 2) (parallel [(const_int 1) (const_int 0)])))] - " { operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[1]) : operands[1]; -} - " - [(set_attr "type" "vecstore") - (set_attr "length" "8")]) +}) + +;; The post-reload split requires that we re-permute the source +;; register in case it is still live. +(define_split + [(set (match_operand:VSX_D 0 "memory_operand" "") + (match_operand:VSX_D 1 "vsx_register_operand" ""))] + "!BYTES_BIG_ENDIAN && TARGET_VSX && reload_completed" + [(set (match_dup 1) + (vec_select:<MODE> + (match_dup 1) + (parallel [(const_int 1) (const_int 0)]))) + (set (match_dup 0) + (vec_select:<MODE> + (match_dup 1) + (parallel [(const_int 1) (const_int 0)]))) + (set (match_dup 1) + (vec_select:<MODE> + (match_dup 1) + (parallel [(const_int 1) (const_int 0)])))] + "") -(define_insn_and_split "*vsx_le_perm_store_<mode>" +(define_insn "*vsx_le_perm_store_<mode>" [(set (match_operand:VSX_W 0 "memory_operand" "=Z") (match_operand:VSX_W 1 "vsx_register_operand" "+wa"))] "!BYTES_BIG_ENDIAN && TARGET_VSX" "#" - "!BYTES_BIG_ENDIAN && TARGET_VSX" + [(set_attr "type" "vecstore") + (set_attr "length" "12")]) + +(define_split + [(set (match_operand:VSX_W 0 "memory_operand" "") + (match_operand:VSX_W 1 "vsx_register_operand" ""))] + "!BYTES_BIG_ENDIAN && TARGET_VSX && !reload_completed" [(set (match_dup 2) (vec_select:<MODE> (match_dup 1) @@ -372,21 +400,46 @@ (match_dup 2) (parallel [(const_int 2) (const_int 3) (const_int 0) (const_int 1)])))] - " { operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[1]) : operands[1]; -} - " - [(set_attr "type" "vecstore") - (set_attr "length" "8")]) +}) -(define_insn_and_split "*vsx_le_perm_store_v8hi" +;; The post-reload split requires that we re-permute the source +;; register in case it is still live. +(define_split + [(set (match_operand:VSX_W 0 "memory_operand" "") + (match_operand:VSX_W 1 "vsx_register_operand" ""))] + "!BYTES_BIG_ENDIAN && TARGET_VSX && reload_completed" + [(set (match_dup 1) + (vec_select:<MODE> + (match_dup 1) + (parallel [(const_int 2) (const_int 3) + (const_int 0) (const_int 1)]))) + (set (match_dup 0) + (vec_select:<MODE> + (match_dup 1) + (parallel [(const_int 2) (const_int 3) + (const_int 0) (const_int 1)]))) + (set (match_dup 1) + (vec_select:<MODE> + (match_dup 1) + (parallel [(const_int 2) (const_int 3) + (const_int 0) (const_int 1)])))] + "") + +(define_insn "*vsx_le_perm_store_v8hi" [(set (match_operand:V8HI 0 "memory_operand" "=Z") (match_operand:V8HI 1 "vsx_register_operand" "+wa"))] "!BYTES_BIG_ENDIAN && TARGET_VSX" "#" - "!BYTES_BIG_ENDIAN && TARGET_VSX" + [(set_attr "type" "vecstore") + (set_attr "length" "12")]) + +(define_split + [(set (match_operand:V8HI 0 "memory_operand" "") + (match_operand:V8HI 1 "vsx_register_operand" ""))] + "!BYTES_BIG_ENDIAN && TARGET_VSX && !reload_completed" [(set (match_dup 2) (vec_select:V8HI (match_dup 1) @@ -401,21 +454,52 @@ (const_int 6) (const_int 7) (const_int 0) (const_int 1) (const_int 2) (const_int 3)])))] - " { operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[1]) : operands[1]; -} - " - [(set_attr "type" "vecstore") - (set_attr "length" "8")]) +}) -(define_insn_and_split "*vsx_le_perm_store_v16qi" +;; The post-reload split requires that we re-permute the source +;; register in case it is still live. +(define_split + [(set (match_operand:V8HI 0 "memory_operand" "") + (match_operand:V8HI 1 "vsx_register_operand" ""))] + "!BYTES_BIG_ENDIAN && TARGET_VSX && reload_completed" + [(set (match_dup 1) + (vec_select:V8HI + (match_dup 1) + (parallel [(const_int 4) (const_int 5) + (const_int 6) (const_int 7) + (const_int 0) (const_int 1) + (const_int 2) (const_int 3)]))) + (set (match_dup 0) + (vec_select:V8HI + (match_dup 1) + (parallel [(const_int 4) (const_int 5) + (const_int 6) (const_int 7) + (const_int 0) (const_int 1) + (const_int 2) (const_int 3)]))) + (set (match_dup 1) + (vec_select:V8HI + (match_dup 1) + (parallel [(const_int 4) (const_int 5) + (const_int 6) (const_int 7) + (const_int 0) (const_int 1) + (const_int 2) (const_int 3)])))] + "") + +(define_insn "*vsx_le_perm_store_v16qi" [(set (match_operand:V16QI 0 "memory_operand" "=Z") (match_operand:V16QI 1 "vsx_register_operand" "+wa"))] "!BYTES_BIG_ENDIAN && TARGET_VSX" "#" - "!BYTES_BIG_ENDIAN && TARGET_VSX" + [(set_attr "type" "vecstore") + (set_attr "length" "12")]) + +(define_split + [(set (match_operand:V16QI 0 "memory_operand" "") + (match_operand:V16QI 1 "vsx_register_operand" ""))] + "!BYTES_BIG_ENDIAN && TARGET_VSX && !reload_completed" [(set (match_dup 2) (vec_select:V16QI (match_dup 1) @@ -438,14 +522,51 @@ (const_int 2) (const_int 3) (const_int 4) (const_int 5) (const_int 6) (const_int 7)])))] - " { operands[2] = can_create_pseudo_p () ? gen_reg_rtx_and_attrs (operands[1]) : operands[1]; -} - " - [(set_attr "type" "vecstore") - (set_attr "length" "8")]) +}) + +;; The post-reload split requires that we re-permute the source +;; register in case it is still live. +(define_split + [(set (match_operand:V16QI 0 "memory_operand" "") + (match_operand:V16QI 1 "vsx_register_operand" ""))] + "!BYTES_BIG_ENDIAN && TARGET_VSX && reload_completed" + [(set (match_dup 1) + (vec_select:V16QI + (match_dup 1) + (parallel [(const_int 8) (const_int 9) + (const_int 10) (const_int 11) + (const_int 12) (const_int 13) + (const_int 14) (const_int 15) + (const_int 0) (const_int 1) + (const_int 2) (const_int 3) + (const_int 4) (const_int 5) + (const_int 6) (const_int 7)]))) + (set (match_dup 0) + (vec_select:V16QI + (match_dup 1) + (parallel [(const_int 8) (const_int 9) + (const_int 10) (const_int 11) + (const_int 12) (const_int 13) + (const_int 14) (const_int 15) + (const_int 0) (const_int 1) + (const_int 2) (const_int 3) + (const_int 4) (const_int 5) + (const_int 6) (const_int 7)]))) + (set (match_dup 1) + (vec_select:V16QI + (match_dup 1) + (parallel [(const_int 8) (const_int 9) + (const_int 10) (const_int 11) + (const_int 12) (const_int 13) + (const_int 14) (const_int 15) + (const_int 0) (const_int 1) + (const_int 2) (const_int 3) + (const_int 4) (const_int 5) + (const_int 6) (const_int 7)])))] + "") (define_insn "*vsx_mov<mode>" diff --git a/gcc/config/rx/rx.c b/gcc/config/rx/rx.c index 93b5de69365..756cd061614 100644 --- a/gcc/config/rx/rx.c +++ b/gcc/config/rx/rx.c @@ -2273,6 +2273,14 @@ static GTY(()) tree rx_builtins[(int) RX_BUILTIN_max]; static void rx_init_builtins (void) { +#define ADD_RX_BUILTIN0(UC_NAME, LC_NAME, RET_TYPE) \ + rx_builtins[RX_BUILTIN_##UC_NAME] = \ + add_builtin_function ("__builtin_rx_" LC_NAME, \ + build_function_type_list (RET_TYPE##_type_node, \ + NULL_TREE), \ + RX_BUILTIN_##UC_NAME, \ + BUILT_IN_MD, NULL, NULL_TREE) + #define ADD_RX_BUILTIN1(UC_NAME, LC_NAME, RET_TYPE, ARG_TYPE) \ rx_builtins[RX_BUILTIN_##UC_NAME] = \ add_builtin_function ("__builtin_rx_" LC_NAME, \ @@ -2303,7 +2311,7 @@ rx_init_builtins (void) RX_BUILTIN_##UC_NAME, \ BUILT_IN_MD, NULL, NULL_TREE) - ADD_RX_BUILTIN1 (BRK, "brk", void, void); + ADD_RX_BUILTIN0 (BRK, "brk", void); ADD_RX_BUILTIN1 (CLRPSW, "clrpsw", void, integer); ADD_RX_BUILTIN1 (SETPSW, "setpsw", void, integer); ADD_RX_BUILTIN1 (INT, "int", void, integer); @@ -2311,18 +2319,18 @@ rx_init_builtins (void) ADD_RX_BUILTIN2 (MACLO, "maclo", void, intSI, intSI); ADD_RX_BUILTIN2 (MULHI, "mulhi", void, intSI, intSI); ADD_RX_BUILTIN2 (MULLO, "mullo", void, intSI, intSI); - ADD_RX_BUILTIN1 (MVFACHI, "mvfachi", intSI, void); - ADD_RX_BUILTIN1 (MVFACMI, "mvfacmi", intSI, void); + ADD_RX_BUILTIN0 (MVFACHI, "mvfachi", intSI); + ADD_RX_BUILTIN0 (MVFACMI, "mvfacmi", intSI); ADD_RX_BUILTIN1 (MVTACHI, "mvtachi", void, intSI); ADD_RX_BUILTIN1 (MVTACLO, "mvtaclo", void, intSI); - ADD_RX_BUILTIN1 (RMPA, "rmpa", void, void); + ADD_RX_BUILTIN0 (RMPA, "rmpa", void); ADD_RX_BUILTIN1 (MVFC, "mvfc", intSI, integer); ADD_RX_BUILTIN2 (MVTC, "mvtc", void, integer, integer); ADD_RX_BUILTIN1 (MVTIPL, "mvtipl", void, integer); ADD_RX_BUILTIN1 (RACW, "racw", void, integer); ADD_RX_BUILTIN1 (ROUND, "round", intSI, float); ADD_RX_BUILTIN1 (REVW, "revw", intSI, intSI); - ADD_RX_BUILTIN1 (WAIT, "wait", void, void); + ADD_RX_BUILTIN0 (WAIT, "wait", void); } /* Return the RX builtin for CODE. */ diff --git a/gcc/config/sh/predicates.md b/gcc/config/sh/predicates.md index 10d741abc46..2643481a827 100644 --- a/gcc/config/sh/predicates.md +++ b/gcc/config/sh/predicates.md @@ -550,17 +550,36 @@ && ! (reload_in_progress || reload_completed)) return 0; - if ((mode == QImode || mode == HImode) - && mode == GET_MODE (op) - && (MEM_P (op) - || (GET_CODE (op) == SUBREG && MEM_P (SUBREG_REG (op))))) + if (mode == GET_MODE (op) + && (MEM_P (op) || (GET_CODE (op) == SUBREG && MEM_P (SUBREG_REG (op))))) { - rtx x = XEXP ((MEM_P (op) ? op : SUBREG_REG (op)), 0); + rtx mem_rtx = MEM_P (op) ? op : SUBREG_REG (op); + rtx x = XEXP (mem_rtx, 0); - if (GET_CODE (x) == PLUS + if ((mode == QImode || mode == HImode) + && GET_CODE (x) == PLUS && REG_P (XEXP (x, 0)) && CONST_INT_P (XEXP (x, 1))) return sh_legitimate_index_p (mode, XEXP (x, 1), TARGET_SH2A, false); + + /* Allow reg+reg addressing here without validating the register + numbers. Usually one of the regs must be R0 or a pseudo reg. + In some cases it can happen that arguments from hard regs are + propagated directly into address expressions. In this cases reload + will have to fix it up later. However, allow this only for native + 1, 2 or 4 byte addresses. */ + if (can_create_pseudo_p () && GET_CODE (x) == PLUS + && GET_MODE_SIZE (mode) <= 4 + && REG_P (XEXP (x, 0)) && REG_P (XEXP (x, 1))) + return true; + + /* 'general_operand' does not allow volatile mems during RTL expansion to + avoid matching arithmetic that operates on mems, it seems. + On SH this leads to redundant sign extensions for QImode or HImode + stores. Thus we mimic the behavior but allow volatile mems. */ + if (memory_address_addr_space_p (GET_MODE (mem_rtx), x, + MEM_ADDR_SPACE (mem_rtx))) + return true; } return general_operand (op, mode); diff --git a/gcc/config/sh/sh-mem.cc b/gcc/config/sh/sh-mem.cc new file mode 100644 index 00000000000..eabf6871173 --- /dev/null +++ b/gcc/config/sh/sh-mem.cc @@ -0,0 +1,476 @@ +/* Helper routines for memory move and comparison insns. + Copyright (C) 2013 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3, or (at your option) +any later version. + +GCC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" +#include "machmode.h" +#include "rtl.h" +#include "tree.h" +#include "expr.h" +#include "tm_p.h" +#include "basic-block.h" + +/* Like force_operand, but guarantees that VALUE ends up in TARGET. */ +static void +force_into (rtx value, rtx target) +{ + value = force_operand (value, target); + if (! rtx_equal_p (value, target)) + emit_insn (gen_move_insn (target, value)); +} + +/* Emit code to perform a block move. Choose the best method. + + OPERANDS[0] is the destination. + OPERANDS[1] is the source. + OPERANDS[2] is the size. + OPERANDS[3] is the alignment safe to use. */ +bool +expand_block_move (rtx *operands) +{ + int align = INTVAL (operands[3]); + int constp = (CONST_INT_P (operands[2])); + int bytes = (constp ? INTVAL (operands[2]) : 0); + + if (! constp) + return false; + + /* If we could use mov.l to move words and dest is word-aligned, we + can use movua.l for loads and still generate a relatively short + and efficient sequence. */ + if (TARGET_SH4A_ARCH && align < 4 + && MEM_ALIGN (operands[0]) >= 32 + && can_move_by_pieces (bytes, 32)) + { + rtx dest = copy_rtx (operands[0]); + rtx src = copy_rtx (operands[1]); + /* We could use different pseudos for each copied word, but + since movua can only load into r0, it's kind of + pointless. */ + rtx temp = gen_reg_rtx (SImode); + rtx src_addr = copy_addr_to_reg (XEXP (src, 0)); + int copied = 0; + + while (copied + 4 <= bytes) + { + rtx to = adjust_address (dest, SImode, copied); + rtx from = adjust_automodify_address (src, BLKmode, + src_addr, copied); + + set_mem_size (from, 4); + emit_insn (gen_movua (temp, from)); + emit_move_insn (src_addr, plus_constant (Pmode, src_addr, 4)); + emit_move_insn (to, temp); + copied += 4; + } + + if (copied < bytes) + move_by_pieces (adjust_address (dest, BLKmode, copied), + adjust_automodify_address (src, BLKmode, + src_addr, copied), + bytes - copied, align, 0); + + return true; + } + + /* If it isn't a constant number of bytes, or if it doesn't have 4 byte + alignment, or if it isn't a multiple of 4 bytes, then fail. */ + if (align < 4 || (bytes % 4 != 0)) + return false; + + if (TARGET_HARD_SH4) + { + if (bytes < 12) + return false; + else if (bytes == 12) + { + rtx func_addr_rtx = gen_reg_rtx (Pmode); + rtx r4 = gen_rtx_REG (SImode, 4); + rtx r5 = gen_rtx_REG (SImode, 5); + + function_symbol (func_addr_rtx, "__movmemSI12_i4", SFUNC_STATIC); + force_into (XEXP (operands[0], 0), r4); + force_into (XEXP (operands[1], 0), r5); + emit_insn (gen_block_move_real_i4 (func_addr_rtx)); + return true; + } + else if (! optimize_size) + { + const char *entry_name; + rtx func_addr_rtx = gen_reg_rtx (Pmode); + int dwords; + rtx r4 = gen_rtx_REG (SImode, 4); + rtx r5 = gen_rtx_REG (SImode, 5); + rtx r6 = gen_rtx_REG (SImode, 6); + + entry_name = (bytes & 4 ? "__movmem_i4_odd" : "__movmem_i4_even"); + function_symbol (func_addr_rtx, entry_name, SFUNC_STATIC); + force_into (XEXP (operands[0], 0), r4); + force_into (XEXP (operands[1], 0), r5); + + dwords = bytes >> 3; + emit_insn (gen_move_insn (r6, GEN_INT (dwords - 1))); + emit_insn (gen_block_lump_real_i4 (func_addr_rtx)); + return true; + } + else + return false; + } + if (bytes < 64) + { + char entry[30]; + rtx func_addr_rtx = gen_reg_rtx (Pmode); + rtx r4 = gen_rtx_REG (SImode, 4); + rtx r5 = gen_rtx_REG (SImode, 5); + + sprintf (entry, "__movmemSI%d", bytes); + function_symbol (func_addr_rtx, entry, SFUNC_STATIC); + force_into (XEXP (operands[0], 0), r4); + force_into (XEXP (operands[1], 0), r5); + emit_insn (gen_block_move_real (func_addr_rtx)); + return true; + } + + /* This is the same number of bytes as a memcpy call, but to a different + less common function name, so this will occasionally use more space. */ + if (! optimize_size) + { + rtx func_addr_rtx = gen_reg_rtx (Pmode); + int final_switch, while_loop; + rtx r4 = gen_rtx_REG (SImode, 4); + rtx r5 = gen_rtx_REG (SImode, 5); + rtx r6 = gen_rtx_REG (SImode, 6); + + function_symbol (func_addr_rtx, "__movmem", SFUNC_STATIC); + force_into (XEXP (operands[0], 0), r4); + force_into (XEXP (operands[1], 0), r5); + + /* r6 controls the size of the move. 16 is decremented from it + for each 64 bytes moved. Then the negative bit left over is used + as an index into a list of move instructions. e.g., a 72 byte move + would be set up with size(r6) = 14, for one iteration through the + big while loop, and a switch of -2 for the last part. */ + + final_switch = 16 - ((bytes / 4) % 16); + while_loop = ((bytes / 4) / 16 - 1) * 16; + emit_insn (gen_move_insn (r6, GEN_INT (while_loop + final_switch))); + emit_insn (gen_block_lump_real (func_addr_rtx)); + return true; + } + + return false; +} + +/* Emit code to perform a strcmp. + + OPERANDS[0] is the destination. + OPERANDS[1] is the first string. + OPERANDS[2] is the second string. + OPERANDS[3] is the align. */ +bool +sh_expand_cmpstr (rtx *operands) +{ + rtx s1 = copy_rtx (operands[1]); + rtx s2 = copy_rtx (operands[2]); + rtx s1_addr = copy_addr_to_reg (XEXP (s1, 0)); + rtx s2_addr = copy_addr_to_reg (XEXP (s2, 0)); + rtx tmp0 = gen_reg_rtx (SImode); + rtx tmp1 = gen_reg_rtx (SImode); + rtx tmp2 = gen_reg_rtx (SImode); + rtx tmp3 = gen_reg_rtx (SImode); + + rtx L_return = gen_label_rtx (); + rtx L_loop_byte = gen_label_rtx (); + rtx L_end_loop_byte = gen_label_rtx (); + + rtx jump, addr1, addr2; + int prob_unlikely = REG_BR_PROB_BASE / 10; + int prob_likely = REG_BR_PROB_BASE / 4; + + rtx L_loop_long = gen_label_rtx (); + rtx L_end_loop_long = gen_label_rtx (); + + int align = INTVAL (operands[3]); + + emit_move_insn (tmp0, const0_rtx); + + if (align < 4) + { + emit_insn (gen_iorsi3 (tmp1, s1_addr, s2_addr)); + emit_insn (gen_tstsi_t (GEN_INT (3), tmp1)); + jump = emit_jump_insn (gen_branch_false (L_loop_byte)); + add_int_reg_note (jump, REG_BR_PROB, prob_likely); + } + + addr1 = adjust_automodify_address (s1, SImode, s1_addr, 0); + addr2 = adjust_automodify_address (s2, SImode, s2_addr, 0); + + /* tmp2 is aligned, OK to load. */ + emit_move_insn (tmp3, addr2); + emit_move_insn (s2_addr, plus_constant (Pmode, s2_addr, 4)); + + /*start long loop. */ + emit_label (L_loop_long); + + emit_move_insn (tmp2, tmp3); + + /* tmp1 is aligned, OK to load. */ + emit_move_insn (tmp1, addr1); + emit_move_insn (s1_addr, plus_constant (Pmode, s1_addr, 4)); + + /* Is there a 0 byte ? */ + emit_insn (gen_andsi3 (tmp3, tmp3, tmp1)); + + emit_insn (gen_cmpstr_t (tmp0, tmp3)); + jump = emit_jump_insn (gen_branch_true (L_end_loop_long)); + add_int_reg_note (jump, REG_BR_PROB, prob_unlikely); + + emit_insn (gen_cmpeqsi_t (tmp1, tmp2)); + + /* tmp2 is aligned, OK to load. */ + emit_move_insn (tmp3, addr2); + emit_move_insn (s2_addr, plus_constant (Pmode, s2_addr, 4)); + + jump = emit_jump_insn (gen_branch_true (L_loop_long)); + add_int_reg_note (jump, REG_BR_PROB, prob_likely); + /* end loop. */ + + /* Fallthu, substract words. */ + if (TARGET_LITTLE_ENDIAN) + { + rtx low_1 = gen_lowpart (HImode, tmp1); + rtx low_2 = gen_lowpart (HImode, tmp2); + + emit_insn (gen_rotlhi3_8 (low_1, low_1)); + emit_insn (gen_rotlhi3_8 (low_2, low_2)); + emit_insn (gen_rotlsi3_16 (tmp1, tmp1)); + emit_insn (gen_rotlsi3_16 (tmp2, tmp2)); + emit_insn (gen_rotlhi3_8 (low_1, low_1)); + emit_insn (gen_rotlhi3_8 (low_2, low_2)); + } + + jump = emit_jump_insn (gen_jump_compact (L_return)); + emit_barrier_after (jump); + + emit_label (L_end_loop_long); + + emit_move_insn (s1_addr, plus_constant (Pmode, s1_addr, -4)); + emit_move_insn (s2_addr, plus_constant (Pmode, s2_addr, -4)); + + /* start byte loop. */ + addr1 = adjust_automodify_address (s1, QImode, s1_addr, 0); + addr2 = adjust_automodify_address (s2, QImode, s2_addr, 0); + + emit_label (L_loop_byte); + + emit_insn (gen_extendqisi2 (tmp2, addr2)); + emit_move_insn (s2_addr, plus_constant (Pmode, s2_addr, 1)); + + emit_insn (gen_extendqisi2 (tmp1, addr1)); + emit_move_insn (s1_addr, plus_constant (Pmode, s1_addr, 1)); + + emit_insn (gen_cmpeqsi_t (tmp2, const0_rtx)); + jump = emit_jump_insn (gen_branch_true (L_end_loop_byte)); + add_int_reg_note (jump, REG_BR_PROB, prob_unlikely); + + emit_insn (gen_cmpeqsi_t (tmp1, tmp2)); + if (flag_delayed_branch) + emit_insn (gen_zero_extendqisi2 (tmp2, gen_lowpart (QImode, tmp2))); + jump = emit_jump_insn (gen_branch_true (L_loop_byte)); + add_int_reg_note (jump, REG_BR_PROB, prob_likely); + /* end loop. */ + + emit_label (L_end_loop_byte); + + if (! flag_delayed_branch) + emit_insn (gen_zero_extendqisi2 (tmp2, gen_lowpart (QImode, tmp2))); + emit_insn (gen_zero_extendqisi2 (tmp1, gen_lowpart (QImode, tmp1))); + + emit_label (L_return); + + emit_insn (gen_subsi3 (operands[0], tmp1, tmp2)); + + return true; +} + +/* Emit code to perform a strncmp. + + OPERANDS[0] is the destination. + OPERANDS[1] is the first string. + OPERANDS[2] is the second string. + OPERANDS[3] is the length. + OPERANDS[4] is the align. */ +bool +sh_expand_cmpnstr (rtx *operands) +{ + rtx s1 = copy_rtx (operands[1]); + rtx s2 = copy_rtx (operands[2]); + + rtx s1_addr = copy_addr_to_reg (XEXP (s1, 0)); + rtx s2_addr = copy_addr_to_reg (XEXP (s2, 0)); + rtx tmp0 = gen_reg_rtx (SImode); + rtx tmp1 = gen_reg_rtx (SImode); + rtx tmp2 = gen_reg_rtx (SImode); + + rtx L_return = gen_label_rtx (); + rtx L_loop_byte = gen_label_rtx (); + rtx L_end_loop_byte = gen_label_rtx (); + + rtx jump, addr1, addr2; + int prob_unlikely = REG_BR_PROB_BASE / 10; + int prob_likely = REG_BR_PROB_BASE / 4; + + rtx len = force_reg (SImode, operands[3]); + int constp = (CONST_INT_P (operands[3])); + int bytes = (constp ? INTVAL (operands[3]) : 0); + int witers = bytes / 4; + + /* We could still loop on a register count. Not found very + convincing to optimize yet. */ + if (! constp) + return false; + + if (witers > 1) + { + rtx L_loop_long = gen_label_rtx (); + rtx L_end_loop_long = gen_label_rtx (); + rtx tmp3 = gen_reg_rtx (SImode); + rtx lenw = gen_reg_rtx (SImode); + int align = INTVAL (operands[4]); + + emit_move_insn (tmp0, const0_rtx); + + if (align < 4) + { + emit_insn (gen_iorsi3 (tmp1, s1_addr, s2_addr)); + emit_insn (gen_tstsi_t (GEN_INT (3), tmp1)); + jump = emit_jump_insn (gen_branch_false (L_loop_byte)); + add_int_reg_note (jump, REG_BR_PROB, prob_likely); + } + + addr1 = adjust_automodify_address (s1, SImode, s1_addr, 0); + addr2 = adjust_automodify_address (s2, SImode, s2_addr, 0); + + /* words count. */ + emit_insn (gen_lshrsi3 (lenw, len, GEN_INT (2))); + + /*start long loop. */ + emit_label (L_loop_long); + + /* tmp2 is aligned, OK to load. */ + emit_move_insn (tmp2, addr2); + emit_move_insn (s2_addr, plus_constant (Pmode, s2_addr, 4)); + + /* tmp1 is aligned, OK to load. */ + emit_move_insn (tmp1, addr1); + emit_move_insn (s1_addr, plus_constant (Pmode, s1_addr, 4)); + + /* Is there a 0 byte ? */ + emit_insn (gen_andsi3 (tmp3, tmp2, tmp1)); + + emit_insn (gen_cmpstr_t (tmp0, tmp3)); + jump = emit_jump_insn (gen_branch_true (L_end_loop_long)); + add_int_reg_note (jump, REG_BR_PROB, prob_unlikely); + + emit_insn (gen_cmpeqsi_t (tmp1, tmp2)); + jump = emit_jump_insn (gen_branch_false (L_end_loop_long)); + add_int_reg_note (jump, REG_BR_PROB, prob_unlikely); + + if (TARGET_SH2) + emit_insn (gen_dect (lenw, lenw)); + else + { + emit_insn (gen_addsi3 (lenw, lenw, GEN_INT (-1))); + emit_insn (gen_tstsi_t (lenw, lenw)); + } + jump = emit_jump_insn (gen_branch_false (L_loop_long)); + add_int_reg_note (jump, REG_BR_PROB, prob_likely); + + /* end loop. Reached max iterations. */ + if (bytes % 4 == 0) + { + /* Done. */ + jump = emit_jump_insn (gen_jump_compact (L_return)); + emit_barrier_after (jump); + } + else + { + /* Remaining bytes to read. */ + emit_move_insn (len, GEN_INT (bytes % 4)); + jump = emit_jump_insn (gen_jump_compact (L_loop_byte)); + emit_barrier_after (jump); + } + + emit_label (L_end_loop_long); + + /* Remaining bytes to read. */ + emit_move_insn (len, GEN_INT (4)); + + /* Found last word. Restart it byte per byte. */ + emit_move_insn (s1_addr, plus_constant (Pmode, s1_addr, -4)); + emit_move_insn (s2_addr, plus_constant (Pmode, s2_addr, -4)); + } + + addr1 = adjust_automodify_address (s1, QImode, s1_addr, 0); + addr2 = adjust_automodify_address (s2, QImode, s2_addr, 0); + + emit_label (L_loop_byte); + + emit_insn (gen_extendqisi2 (tmp2, addr2)); + emit_move_insn (s2_addr, plus_constant (Pmode, s2_addr, 1)); + + emit_insn (gen_extendqisi2 (tmp1, addr1)); + emit_move_insn (s1_addr, plus_constant (Pmode, s1_addr, 1)); + + emit_insn (gen_cmpeqsi_t (tmp2, const0_rtx)); + jump = emit_jump_insn (gen_branch_true (L_end_loop_byte)); + add_int_reg_note (jump, REG_BR_PROB, prob_unlikely); + + emit_insn (gen_cmpeqsi_t (tmp1, tmp2)); + if (flag_delayed_branch) + emit_insn (gen_zero_extendqisi2 (tmp2, gen_lowpart (QImode, tmp2))); + jump = emit_jump_insn (gen_branch_false (L_end_loop_byte)); + add_int_reg_note (jump, REG_BR_PROB, prob_unlikely); + + if (TARGET_SH2) + emit_insn (gen_dect (len, len)); + else + { + emit_insn (gen_addsi3 (len, len, GEN_INT (-1))); + emit_insn (gen_tstsi_t (len, len)); + } + + jump = emit_jump_insn (gen_branch_false (L_loop_byte)); + add_int_reg_note (jump, REG_BR_PROB, prob_likely); + /* end byte loop. */ + + emit_label (L_end_loop_byte); + + if (! flag_delayed_branch) + emit_insn (gen_zero_extendqisi2 (tmp2, gen_lowpart (QImode, tmp2))); + emit_insn (gen_zero_extendqisi2 (tmp1, gen_lowpart (QImode, tmp1))); + + emit_label (L_return); + + emit_insn (gen_subsi3 (operands[0], tmp1, tmp2)); + + return true; +} diff --git a/gcc/config/sh/sh-modes.def b/gcc/config/sh/sh-modes.def index aec007986ef..aa56038d614 100644 --- a/gcc/config/sh/sh-modes.def +++ b/gcc/config/sh/sh-modes.def @@ -18,9 +18,9 @@ along with GCC; see the file COPYING3. If not see <http://www.gnu.org/licenses/>. */ /* The SH uses a partial integer mode to represent the FPSCR register. */ -PARTIAL_INT_MODE (SI); +PARTIAL_INT_MODE (SI, 22, PSI); /* PDI mode is used to represent a function address in a target register. */ -PARTIAL_INT_MODE (DI); +PARTIAL_INT_MODE (DI, 64, PDI); /* Vector modes. */ VECTOR_MODE (INT, QI, 2); /* V2QI */ diff --git a/gcc/config/sh/sh-protos.h b/gcc/config/sh/sh-protos.h index 4671c5499cc..e7dfce366ab 100644 --- a/gcc/config/sh/sh-protos.h +++ b/gcc/config/sh/sh-protos.h @@ -116,6 +116,8 @@ extern void emit_df_insn (rtx); extern void output_pic_addr_const (FILE *, rtx); extern bool expand_block_move (rtx *); extern void prepare_move_operands (rtx[], enum machine_mode mode); +extern bool sh_expand_cmpstr (rtx *); +extern bool sh_expand_cmpnstr (rtx *); extern enum rtx_code prepare_cbranch_operands (rtx *, enum machine_mode mode, enum rtx_code comparison); extern void expand_cbranchsi4 (rtx *operands, enum rtx_code comparison, int); diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index 5a8a236d25f..215d4cec6e5 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -63,9 +63,6 @@ along with GCC; see the file COPYING3. If not see int code_for_indirect_jump_scratch = CODE_FOR_indirect_jump_scratch; -#define MSW (TARGET_LITTLE_ENDIAN ? 1 : 0) -#define LSW (TARGET_LITTLE_ENDIAN ? 0 : 1) - /* These are some macros to abstract register modes. */ #define CONST_OK_FOR_I10(VALUE) (((HOST_WIDE_INT)(VALUE)) >= -512 \ && ((HOST_WIDE_INT)(VALUE)) <= 511) @@ -174,7 +171,6 @@ static bool shmedia_space_reserved_for_target_registers; static void split_branches (rtx); static int branch_dest (rtx); -static void force_into (rtx, rtx); static void print_slot (rtx); static rtx add_constant (rtx, enum machine_mode, rtx); static void dump_table (rtx, rtx); @@ -1209,12 +1205,12 @@ sh_print_operand (FILE *stream, rtx x, int code) if (REG_P (x) || GET_CODE (x) == SUBREG) { regno = true_regnum (x); - regno += FP_REGISTER_P (regno) ? 1 : LSW; + regno += FP_REGISTER_P (regno) ? 1 : SH_REG_LSW_OFFSET; fputs (reg_names[regno], (stream)); } else if (MEM_P (x)) { - x = adjust_address (x, SImode, 4 * LSW); + x = adjust_address (x, SImode, 4 * SH_REG_LSW_OFFSET); sh_print_operand_address (stream, XEXP (x, 0)); } else @@ -1225,7 +1221,7 @@ sh_print_operand (FILE *stream, rtx x, int code) if (mode == VOIDmode) mode = DImode; if (GET_MODE_SIZE (mode) >= 8) - sub = simplify_subreg (SImode, x, mode, 4 * LSW); + sub = simplify_subreg (SImode, x, mode, 4 * SH_REG_LSW_OFFSET); if (sub) sh_print_operand (stream, sub, 0); else @@ -1236,12 +1232,12 @@ sh_print_operand (FILE *stream, rtx x, int code) if (REG_P (x) || GET_CODE (x) == SUBREG) { regno = true_regnum (x); - regno += FP_REGISTER_P (regno) ? 0 : MSW; + regno += FP_REGISTER_P (regno) ? 0 : SH_REG_MSW_OFFSET; fputs (reg_names[regno], (stream)); } else if (MEM_P (x)) { - x = adjust_address (x, SImode, 4 * MSW); + x = adjust_address (x, SImode, 4 * SH_REG_MSW_OFFSET); sh_print_operand_address (stream, XEXP (x, 0)); } else @@ -1252,7 +1248,7 @@ sh_print_operand (FILE *stream, rtx x, int code) if (mode == VOIDmode) mode = DImode; if (GET_MODE_SIZE (mode) >= 8) - sub = simplify_subreg (SImode, x, mode, 4 * MSW); + sub = simplify_subreg (SImode, x, mode, 4 * SH_REG_MSW_OFFSET); if (sub) sh_print_operand (stream, sub, 0); else @@ -1621,157 +1617,6 @@ sh_encode_section_info (tree decl, rtx rtl, int first) SYMBOL_REF_FLAGS (XEXP (rtl, 0)) |= SYMBOL_FLAG_FUNCVEC_FUNCTION; } -/* Like force_operand, but guarantees that VALUE ends up in TARGET. */ -static void -force_into (rtx value, rtx target) -{ - value = force_operand (value, target); - if (! rtx_equal_p (value, target)) - emit_insn (gen_move_insn (target, value)); -} - -/* Emit code to perform a block move. Choose the best method. - - OPERANDS[0] is the destination. - OPERANDS[1] is the source. - OPERANDS[2] is the size. - OPERANDS[3] is the alignment safe to use. */ -bool -expand_block_move (rtx *operands) -{ - int align = INTVAL (operands[3]); - int constp = (CONST_INT_P (operands[2])); - int bytes = (constp ? INTVAL (operands[2]) : 0); - - if (! constp) - return false; - - /* If we could use mov.l to move words and dest is word-aligned, we - can use movua.l for loads and still generate a relatively short - and efficient sequence. */ - if (TARGET_SH4A_ARCH && align < 4 - && MEM_ALIGN (operands[0]) >= 32 - && can_move_by_pieces (bytes, 32)) - { - rtx dest = copy_rtx (operands[0]); - rtx src = copy_rtx (operands[1]); - /* We could use different pseudos for each copied word, but - since movua can only load into r0, it's kind of - pointless. */ - rtx temp = gen_reg_rtx (SImode); - rtx src_addr = copy_addr_to_reg (XEXP (src, 0)); - int copied = 0; - - while (copied + 4 <= bytes) - { - rtx to = adjust_address (dest, SImode, copied); - rtx from = adjust_automodify_address (src, BLKmode, - src_addr, copied); - - set_mem_size (from, 4); - emit_insn (gen_movua (temp, from)); - emit_move_insn (src_addr, plus_constant (Pmode, src_addr, 4)); - emit_move_insn (to, temp); - copied += 4; - } - - if (copied < bytes) - move_by_pieces (adjust_address (dest, BLKmode, copied), - adjust_automodify_address (src, BLKmode, - src_addr, copied), - bytes - copied, align, 0); - - return true; - } - - /* If it isn't a constant number of bytes, or if it doesn't have 4 byte - alignment, or if it isn't a multiple of 4 bytes, then fail. */ - if (align < 4 || (bytes % 4 != 0)) - return false; - - if (TARGET_HARD_SH4) - { - if (bytes < 12) - return false; - else if (bytes == 12) - { - rtx func_addr_rtx = gen_reg_rtx (Pmode); - rtx r4 = gen_rtx_REG (SImode, 4); - rtx r5 = gen_rtx_REG (SImode, 5); - - function_symbol (func_addr_rtx, "__movmemSI12_i4", SFUNC_STATIC); - force_into (XEXP (operands[0], 0), r4); - force_into (XEXP (operands[1], 0), r5); - emit_insn (gen_block_move_real_i4 (func_addr_rtx)); - return true; - } - else if (! optimize_size) - { - const char *entry_name; - rtx func_addr_rtx = gen_reg_rtx (Pmode); - int dwords; - rtx r4 = gen_rtx_REG (SImode, 4); - rtx r5 = gen_rtx_REG (SImode, 5); - rtx r6 = gen_rtx_REG (SImode, 6); - - entry_name = (bytes & 4 ? "__movmem_i4_odd" : "__movmem_i4_even"); - function_symbol (func_addr_rtx, entry_name, SFUNC_STATIC); - force_into (XEXP (operands[0], 0), r4); - force_into (XEXP (operands[1], 0), r5); - - dwords = bytes >> 3; - emit_insn (gen_move_insn (r6, GEN_INT (dwords - 1))); - emit_insn (gen_block_lump_real_i4 (func_addr_rtx)); - return true; - } - else - return false; - } - if (bytes < 64) - { - char entry[30]; - rtx func_addr_rtx = gen_reg_rtx (Pmode); - rtx r4 = gen_rtx_REG (SImode, 4); - rtx r5 = gen_rtx_REG (SImode, 5); - - sprintf (entry, "__movmemSI%d", bytes); - function_symbol (func_addr_rtx, entry, SFUNC_STATIC); - force_into (XEXP (operands[0], 0), r4); - force_into (XEXP (operands[1], 0), r5); - emit_insn (gen_block_move_real (func_addr_rtx)); - return true; - } - - /* This is the same number of bytes as a memcpy call, but to a different - less common function name, so this will occasionally use more space. */ - if (! optimize_size) - { - rtx func_addr_rtx = gen_reg_rtx (Pmode); - int final_switch, while_loop; - rtx r4 = gen_rtx_REG (SImode, 4); - rtx r5 = gen_rtx_REG (SImode, 5); - rtx r6 = gen_rtx_REG (SImode, 6); - - function_symbol (func_addr_rtx, "__movmem", SFUNC_STATIC); - force_into (XEXP (operands[0], 0), r4); - force_into (XEXP (operands[1], 0), r5); - - /* r6 controls the size of the move. 16 is decremented from it - for each 64 bytes moved. Then the negative bit left over is used - as an index into a list of move instructions. e.g., a 72 byte move - would be set up with size(r6) = 14, for one iteration through the - big while loop, and a switch of -2 for the last part. */ - - final_switch = 16 - ((bytes / 4) % 16); - while_loop = ((bytes / 4) / 16 - 1) * 16; - emit_insn (gen_move_insn (r6, GEN_INT (while_loop + final_switch))); - emit_insn (gen_block_lump_real (func_addr_rtx)); - return true; - } - - return false; -} - /* Prepare operands for a move define_expand; specifically, one of the operands must be in a register. */ void @@ -3314,6 +3159,35 @@ and_xor_ior_costs (rtx x, int code) static inline int addsubcosts (rtx x) { + if (GET_MODE (x) == SImode) + { + /* The addc or subc patterns will eventually become one or two + instructions. Below are some costs for some of the patterns + which combine would reject because the costs of the individual + insns in the patterns are lower. + + FIXME: It would be much easier if we had something like insn cost + attributes and the cost calculation machinery used those attributes + in the first place. This would eliminate redundant recog-like C + code to calculate costs of complex patterns. */ + rtx op0 = XEXP (x, 0); + rtx op1 = XEXP (x, 1); + + if (GET_CODE (x) == PLUS) + { + if (GET_CODE (op0) == AND + && XEXP (op0, 1) == const1_rtx + && (GET_CODE (op1) == PLUS + || (GET_CODE (op1) == MULT && XEXP (op1, 1) == const2_rtx))) + return 1; + + if (GET_CODE (op0) == MULT && XEXP (op0, 1) == const2_rtx + && GET_CODE (op1) == LSHIFTRT + && CONST_INT_P (XEXP (op1, 1)) && INTVAL (XEXP (op1, 1)) == 31) + return 1; + } + } + /* On SH1-4 we have only max. SImode operations. Double the cost for modes > SImode. */ const int cost_scale = !TARGET_SHMEDIA @@ -8413,8 +8287,8 @@ sh_builtin_saveregs (void) emit_insn (gen_addsi3 (fpregs, fpregs, GEN_INT (-UNITS_PER_WORD))); mem = change_address (regbuf, SFmode, fpregs); emit_move_insn (mem, - gen_rtx_REG (SFmode, BASE_ARG_REG (SFmode) + regno - - (TARGET_LITTLE_ENDIAN != 0))); + gen_rtx_REG (SFmode, BASE_ARG_REG (SFmode) + + regno - SH_REG_MSW_OFFSET)); } } else diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h index 8e27030c6a0..9f07012941c 100644 --- a/gcc/config/sh/sh.h +++ b/gcc/config/sh/sh.h @@ -405,16 +405,21 @@ extern enum sh_divide_strategy_e sh_div_strategy; /* Target machine storage layout. */ +#define TARGET_BIG_ENDIAN (!TARGET_LITTLE_ENDIAN) + +#define SH_REG_MSW_OFFSET (TARGET_LITTLE_ENDIAN ? 1 : 0) +#define SH_REG_LSW_OFFSET (TARGET_LITTLE_ENDIAN ? 0 : 1) + /* Define this if most significant bit is lowest numbered in instructions that operate on numbered bit-fields. */ #define BITS_BIG_ENDIAN 0 /* Define this if most significant byte of a word is the lowest numbered. */ -#define BYTES_BIG_ENDIAN (TARGET_LITTLE_ENDIAN == 0) +#define BYTES_BIG_ENDIAN TARGET_BIG_ENDIAN /* Define this if most significant word of a multiword number is the lowest numbered. */ -#define WORDS_BIG_ENDIAN (TARGET_LITTLE_ENDIAN == 0) +#define WORDS_BIG_ENDIAN TARGET_BIG_ENDIAN #define MAX_BITS_PER_WORD 64 @@ -1437,7 +1442,7 @@ struct sh_args { #define SHCOMPACT_FORCE_ON_STACK(MODE,TYPE) \ ((MODE) == BLKmode \ && TARGET_SHCOMPACT \ - && ! TARGET_LITTLE_ENDIAN \ + && TARGET_BIG_ENDIAN \ && int_size_in_bytes (TYPE) > 4 \ && int_size_in_bytes (TYPE) < 8) diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md index d8480cdfe6f..b8109e62c44 100644 --- a/gcc/config/sh/sh.md +++ b/gcc/config/sh/sh.md @@ -31,9 +31,6 @@ ;; ??? The MAC.W and MAC.L instructions are not supported. There is no ;; way to generate them. -;; ??? The cmp/str instruction is not supported. Perhaps it can be used -;; for a str* inline function. - ;; BSR is not generated by the compiler proper, but when relaxing, it ;; generates .uses pseudo-ops that allow linker relaxation to create ;; BSR. This is actually implemented in bfd/{coff,elf32}-sh.c @@ -673,7 +670,7 @@ (and:SI (match_operand:SI 0 "arith_reg_operand" "%r") (match_operand:SI 1 "arith_reg_operand" "r")) <lowpart_be>) (const_int 0)))] - "TARGET_SH1 && !TARGET_LITTLE_ENDIAN" + "TARGET_SH1 && TARGET_BIG_ENDIAN" "tst %0,%1" [(set_attr "type" "mt_group")]) @@ -764,7 +761,7 @@ (match_operand:SI 3 "const_int_operand")) 3) (match_operand:SI 1 "const_int_operand") (match_operand:SI 2 "const_int_operand")))] - "TARGET_SH1 && ! TARGET_LITTLE_ENDIAN + "TARGET_SH1 && TARGET_BIG_ENDIAN && ZERO_EXTRACT_ANDMASK (operands[1], operands[2]) == (INTVAL (operands[3]) & 255) && CONST_OK_FOR_K08 (INTVAL (operands[3]) & 255)" @@ -1844,7 +1841,7 @@ ;; Split 'reg + reg + 1' into a sett addc sequence, as it can be scheduled ;; better, if the sett insn can be done early. -(define_insn_and_split "*addc" +(define_insn_and_split "*addc_r_r_1" [(set (match_operand:SI 0 "arith_reg_dest" "") (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand" "") (match_operand:SI 2 "arith_reg_operand" "")) @@ -1860,7 +1857,7 @@ ;; Left shifts by one are usually done with an add insn to avoid T_REG ;; clobbers. Thus addc can also be used to do something like '(x << 1) + 1'. -(define_insn_and_split "*addc" +(define_insn_and_split "*addc_2r_1" [(set (match_operand:SI 0 "arith_reg_dest") (plus:SI (mult:SI (match_operand:SI 1 "arith_reg_operand") (const_int 2)) @@ -1900,7 +1897,7 @@ ;; can be scheduled much better since the load of the constant can be ;; done earlier, before any comparison insns that store the result in ;; the T bit. -(define_insn_and_split "*addc" +(define_insn_and_split "*addc_r_1" [(set (match_operand:SI 0 "arith_reg_dest" "") (plus:SI (match_operand:SI 1 "t_reg_operand" "") (match_operand:SI 2 "arith_reg_operand" ""))) @@ -1913,6 +1910,126 @@ (match_dup 1))) (clobber (reg:SI T_REG))])]) +;; Use shlr-addc to do 'reg + (reg & 1)'. +(define_insn_and_split "*addc_r_lsb" + [(set (match_operand:SI 0 "arith_reg_dest") + (plus:SI (and:SI (match_operand:SI 1 "arith_reg_operand") + (const_int 1)) + (match_operand:SI 2 "arith_reg_operand"))) + (clobber (reg:SI T_REG))] + "TARGET_SH1" + "#" + "&& can_create_pseudo_p ()" + [(parallel [(set (match_dup 0) (plus:SI (reg:SI T_REG) (match_dup 2))) + (clobber (reg:SI T_REG))])] +{ + emit_insn (gen_shlr (gen_reg_rtx (SImode), operands[1])); +}) + +;; Use shlr-addc to do 'reg + reg + (reg & 1)'. +(define_insn_and_split "*addc_r_r_lsb" + [(set (match_operand:SI 0 "arith_reg_dest") + (plus:SI (plus:SI (and:SI (match_operand:SI 1 "arith_reg_operand") + (const_int 1)) + (match_operand:SI 2 "arith_reg_operand")) + (match_operand:SI 3 "arith_reg_operand"))) + (clobber (reg:SI T_REG))] + "TARGET_SH1" + "#" + "&& can_create_pseudo_p ()" + [(parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 2) (match_dup 3)) + (reg:SI T_REG))) + (clobber (reg:SI T_REG))])] +{ + emit_insn (gen_shlr (gen_reg_rtx (SImode), operands[1])); +}) + +;; Canonicalize 'reg + (reg & 1) + reg' into 'reg + reg + (reg & 1)'. +(define_insn_and_split "*addc_r_lsb_r" + [(set (match_operand:SI 0 "arith_reg_dest") + (plus:SI (and:SI (match_operand:SI 1 "arith_reg_operand") + (const_int 1)) + (plus:SI (match_operand:SI 2 "arith_reg_operand") + (match_operand:SI 3 "arith_reg_operand")))) + (clobber (reg:SI T_REG))] + "TARGET_SH1" + "#" + "&& can_create_pseudo_p ()" + [(parallel [(set (match_dup 0) + (plus:SI (plus:SI (and:SI (match_dup 1) (const_int 1)) + (match_dup 2)) + (match_dup 3))) + (clobber (reg:SI T_REG))])]) + +;; Canonicalize '2 * reg + (reg & 1)' into 'reg + reg + (reg & 1)'. +(define_insn_and_split "*addc_2r_lsb" + [(set (match_operand:SI 0 "arith_reg_dest") + (plus:SI (and:SI (match_operand:SI 1 "arith_reg_operand") + (const_int 1)) + (mult:SI (match_operand:SI 2 "arith_reg_operand") + (const_int 2)))) + (clobber (reg:SI T_REG))] + "TARGET_SH1" + "#" + "&& can_create_pseudo_p ()" + [(parallel [(set (match_dup 0) + (plus:SI (plus:SI (and:SI (match_dup 1) (const_int 1)) + (match_dup 2)) + (match_dup 2))) + (clobber (reg:SI T_REG))])]) + +;; Use shll-addc to do 'reg + ((unsigned int)reg >> 31)'. +(define_insn_and_split "*addc_r_msb" + [(set (match_operand:SI 0 "arith_reg_dest") + (plus:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand") + (const_int 31)) + (match_operand:SI 2 "arith_reg_operand"))) + (clobber (reg:SI T_REG))] + "TARGET_SH1" + "#" + "&& can_create_pseudo_p ()" + [(parallel [(set (match_dup 0) (plus:SI (reg:SI T_REG) (match_dup 2))) + (clobber (reg:SI T_REG))])] +{ + emit_insn (gen_shll (gen_reg_rtx (SImode), operands[1])); +}) + +;; Use shll-addc to do 'reg + reg + ((unsigned int)reg >> 31)'. +(define_insn_and_split "*addc_r_r_msb" + [(set (match_operand:SI 0 "arith_reg_dest") + (plus:SI (plus:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand") + (const_int 31)) + (match_operand:SI 2 "arith_reg_operand")) + (match_operand:SI 3 "arith_reg_operand"))) + (clobber (reg:SI T_REG))] + "TARGET_SH1" + "#" + "&& can_create_pseudo_p ()" + [(parallel [(set (match_dup 0) (plus:SI (plus:SI (match_dup 2) (match_dup 3)) + (reg:SI T_REG))) + (clobber (reg:SI T_REG))])] +{ + emit_insn (gen_shll (gen_reg_rtx (SImode), operands[1])); +}) + +;; Canonicalize '2 * reg + ((unsigned int)reg >> 31)' +;; into 'reg + reg + (reg & 1)'. +(define_insn_and_split "*addc_2r_msb" + [(set (match_operand:SI 0 "arith_reg_dest") + (plus:SI (mult:SI (match_operand:SI 1 "arith_reg_operand") + (const_int 2)) + (lshiftrt:SI (match_operand:SI 2 "arith_reg_operand") + (const_int 31)))) + (clobber (reg:SI T_REG))] + "TARGET_SH1" + "#" + "&& can_create_pseudo_p ()" + [(parallel [(set (match_dup 0) + (plus:SI (plus:SI (lshiftrt:SI (match_dup 2) (const_int 31)) + (match_dup 1)) + (match_dup 1))) + (clobber (reg:SI T_REG))])]) + (define_expand "addsi3" [(set (match_operand:SI 0 "arith_reg_operand" "") (plus:SI (match_operand:SI 1 "arith_operand" "") @@ -2118,7 +2235,7 @@ (zero_extend:SI (subreg:QI (not:SI (subreg:SI (match_operand:QI 1 "general_extend_operand" "") 0)) 3)))] - "TARGET_SHMEDIA && ! TARGET_LITTLE_ENDIAN" + "TARGET_SHMEDIA && TARGET_BIG_ENDIAN" [(set (match_dup 0) (zero_extend:SI (match_dup 1))) (set (match_dup 0) (xor:SI (match_dup 0) (const_int 255)))] "") @@ -3843,7 +3960,7 @@ label: operands[0] = SUBREG_REG (operands[0]); } gcc_assert (REG_P (operands[0])); - if (! TARGET_LITTLE_ENDIAN) + if (TARGET_BIG_ENDIAN) offset += 8 - GET_MODE_SIZE (inmode); operands[5] = gen_rtx_SUBREG (inmode, operands[0], offset); }) @@ -4037,7 +4154,7 @@ label: DONE; }) -(define_insn "*rotlhi3_8" +(define_insn "rotlhi3_8" [(set (match_operand:HI 0 "arith_reg_dest" "=r") (rotate:HI (match_operand:HI 1 "arith_reg_operand" "r") (const_int 8)))] @@ -7736,11 +7853,11 @@ label: rtx mem2 = change_address (mem, SFmode, gen_rtx_POST_INC (Pmode, operands[1])); insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, - regno + !! TARGET_LITTLE_ENDIAN), + regno + SH_REG_MSW_OFFSET), mem2, operands[2])); add_reg_note (insn, REG_INC, operands[1]); insn = emit_insn (gen_movsf_ie (gen_rtx_REG (SFmode, - regno + ! TARGET_LITTLE_ENDIAN), + regno + SH_REG_LSW_OFFSET), change_address (mem, SFmode, NULL_RTX), operands[2])); DONE; @@ -7758,8 +7875,8 @@ label: int regno = true_regnum (operands[0]); rtx addr, insn; rtx mem2 = change_address (operands[1], SFmode, NULL_RTX); - rtx reg0 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 1 : 0)); - rtx reg1 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 0 : 1)); + rtx reg0 = gen_rtx_REG (SFmode, regno + SH_REG_MSW_OFFSET); + rtx reg1 = gen_rtx_REG (SFmode, regno + SH_REG_LSW_OFFSET); operands[1] = copy_rtx (mem2); addr = XEXP (mem2, 0); @@ -7824,8 +7941,8 @@ label: { int regno = true_regnum (operands[1]); rtx insn, addr; - rtx reg0 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 1 : 0)); - rtx reg1 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 0 : 1)); + rtx reg0 = gen_rtx_REG (SFmode, regno + SH_REG_MSW_OFFSET); + rtx reg1 = gen_rtx_REG (SFmode, regno + SH_REG_LSW_OFFSET); operands[0] = copy_rtx (operands[0]); PUT_MODE (operands[0], SFmode); @@ -11839,19 +11956,20 @@ label: ;; String/block move insn. (define_expand "movmemsi" - [(parallel [(set (mem:BLK (match_operand:BLK 0 "" "")) - (mem:BLK (match_operand:BLK 1 "" ""))) - (use (match_operand:SI 2 "nonmemory_operand" "")) - (use (match_operand:SI 3 "immediate_operand" "")) + [(parallel [(set (mem:BLK (match_operand:BLK 0)) + (mem:BLK (match_operand:BLK 1))) + (use (match_operand:SI 2 "nonmemory_operand")) + (use (match_operand:SI 3 "immediate_operand")) (clobber (reg:SI PR_REG)) (clobber (reg:SI R4_REG)) (clobber (reg:SI R5_REG)) (clobber (reg:SI R0_REG))])] "TARGET_SH1 && ! TARGET_SH5" { - if(expand_block_move (operands)) - DONE; - else FAIL; + if (expand_block_move (operands)) + DONE; + else + FAIL; }) (define_insn "block_move_real" @@ -11912,6 +12030,57 @@ label: "jsr @%0%#" [(set_attr "type" "sfunc") (set_attr "needs_delay_slot" "yes")]) + +;; byte compare pattern +;; temp = a ^ b; +;; !((temp & 0xF000) && (temp & 0x0F00) && (temp & 0x00F0) && (temp & 0x000F)) +(define_insn "cmpstr_t" + [(set (reg:SI T_REG) + (eq:SI (and:SI + (and:SI + (and:SI + (zero_extract:SI + (xor:SI (match_operand:SI 0 "arith_reg_operand" "r") + (match_operand:SI 1 "arith_reg_operand" "r")) + (const_int 8) (const_int 0)) + (zero_extract:SI (xor:SI (match_dup 0) (match_dup 1)) + (const_int 8) (const_int 8))) + (zero_extract:SI (xor:SI (match_dup 0) (match_dup 1)) + (const_int 8) (const_int 16))) + (zero_extract:SI (xor:SI (match_dup 0) (match_dup 1)) + (const_int 8) (const_int 24))) + (const_int 0)))] + "TARGET_SH1" + "cmp/str %0,%1" + [(set_attr "type" "mt_group")]) + +(define_expand "cmpstrsi" + [(set (match_operand:SI 0 "register_operand") + (compare:SI (match_operand:BLK 1 "memory_operand") + (match_operand:BLK 2 "memory_operand"))) + (use (match_operand 3 "immediate_operand"))] + "TARGET_SH1" +{ + if (! optimize_insn_for_size_p () && sh_expand_cmpstr (operands)) + DONE; + else + FAIL; +}) + +(define_expand "cmpstrnsi" + [(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 4 "immediate_operand"))] + "TARGET_SH1" +{ + if (! optimize_insn_for_size_p () && sh_expand_cmpnstr (operands)) + DONE; + else + FAIL; +}) + ;; ------------------------------------------------------------------------- ;; Floating point instructions. @@ -13125,7 +13294,7 @@ label: (match_operand:SI 1 "immediate_operand" "") (match_operand:SI 2 "immediate_operand" "")) (match_operand:SI 3 "general_operand" ""))] - "TARGET_SH1 && ! TARGET_LITTLE_ENDIAN" + "TARGET_SH1 && TARGET_BIG_ENDIAN" { rtx addr_target, orig_address, shift_reg, qi_val; HOST_WIDE_INT bitsize, size, v = 0; @@ -14487,7 +14656,7 @@ label: (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 4)) (zero_extract:QI (not:QI (match_dup 2)) (const_int 2) (const_int 6))])))] - "TARGET_SHMEDIA && ! TARGET_LITTLE_ENDIAN" + "TARGET_SHMEDIA && TARGET_BIG_ENDIAN" "mperm.w %1, %N2, %0" [(set_attr "type" "arith_media")]) diff --git a/gcc/config/sh/t-sh b/gcc/config/sh/t-sh index 081ba3cc6ba..710bc873e75 100644 --- a/gcc/config/sh/t-sh +++ b/gcc/config/sh/t-sh @@ -16,6 +16,10 @@ # along with GCC; see the file COPYING3. If not see # <http://www.gnu.org/licenses/>. +sh-mem.o: $(srcdir)/config/sh/sh-mem.cc \ + $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(TM_H) $(TM_P_H) + $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< + sh-c.o: $(srcdir)/config/sh/sh-c.c \ $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(TM_H) $(TM_P_H) coretypes.h $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ diff --git a/gcc/config/sol2.h b/gcc/config/sol2.h index b606595dfe9..749e16830e3 100644 --- a/gcc/config/sol2.h +++ b/gcc/config/sol2.h @@ -194,11 +194,6 @@ along with GCC; see the file COPYING3. If not see #endif /* HAVE_LD_EH_FRAME && TARGET_DL_ITERATE_PHDR */ #endif -#ifndef USE_GLD -/* The default MFLIB_SPEC is GNU ld specific. */ -#define MFLIB_SPEC "" -#endif - /* collect2.c can only parse GNU nm -n output. Solaris nm needs -png to produce the same format. */ #define NM_FLAGS "-png" diff --git a/gcc/config/tilegx/tilegx.c b/gcc/config/tilegx/tilegx.c index e15755e5cf4..f5944bc65d1 100644 --- a/gcc/config/tilegx/tilegx.c +++ b/gcc/config/tilegx/tilegx.c @@ -39,6 +39,7 @@ #include "function.h" #include "dwarf2.h" #include "timevar.h" +#include "tree.h" #include "gimple.h" #include "cfgloop.h" #include "tilegx-builtins.h" diff --git a/gcc/config/tilepro/tilepro.c b/gcc/config/tilepro/tilepro.c index 99ce5a06857..12adda30e57 100644 --- a/gcc/config/tilepro/tilepro.c +++ b/gcc/config/tilepro/tilepro.c @@ -40,6 +40,7 @@ #include "function.h" #include "dwarf2.h" #include "timevar.h" +#include "tree.h" #include "gimple.h" #include "cfgloop.h" #include "tilepro-builtins.h" diff --git a/gcc/config/v850/v850.h b/gcc/config/v850/v850.h index e08c6220eac..9b5053337f5 100644 --- a/gcc/config/v850/v850.h +++ b/gcc/config/v850/v850.h @@ -954,10 +954,6 @@ extern tree GHS_current_section_names [(int) COUNT_OF_GHS_SECTION_KINDS]; #define FILE_ASM_OP "\t.file\n" -/* Enable the register move pass to improve code. */ -#define ENABLE_REGMOVE_PASS - - /* Implement ZDA, TDA, and SDA */ #define EP_REGNUM 30 /* ep register number */ diff --git a/gcc/configure b/gcc/configure index bedf3b14817..759862c00f7 100755 --- a/gcc/configure +++ b/gcc/configure @@ -737,7 +737,7 @@ LDEXP_LIB EXTRA_GCC_LIBS GNAT_LIBEXC COLLECT2_LIBS -CCDEPMODE +CXXDEPMODE DEPDIR am__leading_dot CXXCPP @@ -875,6 +875,7 @@ with_demangler_in_ld with_gnu_as with_as enable_largefile +enable_build_format_warnings enable_werror_always enable_checking enable_coverage @@ -1569,6 +1570,8 @@ Optional Features: for creating source tarballs for users without texinfo bison or flex --disable-largefile omit support for large files + --disable-build-format-warnings + don't use -Wformat while building GCC --enable-werror-always enable -Werror despite compiler version --enable-checking[=LIST] enable expensive run-time checks. With LIST, enable @@ -6270,9 +6273,22 @@ fi # * C++11 narrowing conversions in { } # So, we only use -pedantic if we can disable those warnings. +# In stage 1, disable -Wformat warnings from old GCCs about new % codes +# Check whether --enable-build-format-warnings was given. +if test "${enable_build_format_warnings+set}" = set; then : + enableval=$enable_build_format_warnings; +else + enable_build_format_warnings=yes +fi + +if test $enable_build_format_warnings = no; then : + wf_opt=-Wno-format +else + wf_opt= +fi loose_warn= save_CFLAGS="$CFLAGS" -for real_option in -W -Wall -Wno-narrowing -Wwrite-strings -Wcast-qual; do +for real_option in -W -Wall -Wno-narrowing -Wwrite-strings -Wcast-qual $wf_opt; do # Do the check with the no- prefix removed since gcc silently # accepts any -Wno-* option on purpose case $real_option in @@ -8766,12 +8782,12 @@ ac_config_commands="$ac_config_commands depdir" ac_config_commands="$ac_config_commands gccdepdir" -depcc="$CC" am_compiler_list= +depcc="$CXX" am_compiler_list= am_depcomp=$ac_aux_dir/depcomp { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } -if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then : +if test "${am_cv_CXX_dependencies_compiler_type+set}" = set; then : $as_echo_n "(cached) " >&6 else if test -f "$am_depcomp"; then @@ -8793,7 +8809,7 @@ else # directory. mkdir sub - am_cv_CC_dependencies_compiler_type=none + am_cv_CXX_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi @@ -8838,7 +8854,7 @@ else # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else - am_cv_CC_dependencies_compiler_type=$depmode + am_cv_CXX_dependencies_compiler_type=$depmode $as_echo "$as_me:$LINENO: success" >&5 break fi @@ -8850,15 +8866,15 @@ else cd .. rm -rf conftest.dir else - am_cv_CC_dependencies_compiler_type=none + am_cv_CXX_dependencies_compiler_type=none fi fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 -$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } -if test x${am_cv_CC_dependencies_compiler_type-none} = xnone +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CXX_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CXX_dependencies_compiler_type" >&6; } +if test x${am_cv_CXX_dependencies_compiler_type-none} = xnone then as_fn_error "no usable dependency style found" "$LINENO" 5 -else CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type +else CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type fi @@ -17897,7 +17913,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 17900 "configure" +#line 17916 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -18003,7 +18019,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 18006 "configure" +#line 18022 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -24786,11 +24802,12 @@ else fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_ix86_interunit_movq" >&5 $as_echo "$gcc_cv_as_ix86_interunit_movq" >&6; } -if test $gcc_cv_as_ix86_interunit_movq = yes; then -$as_echo "#define HAVE_AS_IX86_INTERUNIT_MOVQ 1" >>confdefs.h -fi +cat >>confdefs.h <<_ACEOF +#define HAVE_AS_IX86_INTERUNIT_MOVQ `if test $gcc_cv_as_ix86_interunit_movq = yes; then echo 1; else echo 0; fi` +_ACEOF + { $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for hle prefixes" >&5 $as_echo_n "checking assembler for hle prefixes... " >&6; } diff --git a/gcc/configure.ac b/gcc/configure.ac index 5111109af48..8670c7b7cee 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -326,8 +326,14 @@ GCC_STDINT_TYPES # * C++11 narrowing conversions in { } # So, we only use -pedantic if we can disable those warnings. +# In stage 1, disable -Wformat warnings from old GCCs about new % codes +AC_ARG_ENABLE(build-format-warnings, + AS_HELP_STRING([--disable-build-format-warnings],[don't use -Wformat while building GCC]), + [],[enable_build_format_warnings=yes]) +AS_IF([test $enable_build_format_warnings = no], + [wf_opt=-Wno-format],[wf_opt=]) ACX_PROG_CC_WARNING_OPTS( - m4_quote(m4_do([-W -Wall -Wno-narrowing -Wwrite-strings -Wcast-qual])), [loose_warn]) + m4_quote(m4_do([-W -Wall -Wno-narrowing -Wwrite-strings -Wcast-qual $wf_opt])), [loose_warn]) ACX_PROG_CC_WARNING_OPTS( m4_quote(m4_do([-Wstrict-prototypes -Wmissing-prototypes])), [c_loose_warn]) @@ -974,7 +980,7 @@ AC_CONFIG_COMMANDS([gccdepdir],[ ${CONFIG_SHELL-/bin/sh} $ac_aux_dir/mkinstalldirs $lang/$DEPDIR done], [subdirs="$subdirs" ac_aux_dir=$ac_aux_dir DEPDIR=$DEPDIR]) -ZW_PROG_COMPILER_DEPENDENCIES([CC]) +ZW_PROG_COMPILER_DEPENDENCIES([CXX]) AC_LANG_POP(C++) # -------- @@ -3748,9 +3754,10 @@ foo: nop gcc_cv_as_ix86_interunit_movq,,, [.code64 movq %mm0, %rax - movq %rax, %xmm0],, - [AC_DEFINE(HAVE_AS_IX86_INTERUNIT_MOVQ, 1, - [Define if your assembler supports interunit movq mnemonic.])]) + movq %rax, %xmm0]) + AC_DEFINE_UNQUOTED(HAVE_AS_IX86_INTERUNIT_MOVQ, + [`if test $gcc_cv_as_ix86_interunit_movq = yes; then echo 1; else echo 0; fi`], + [Define if your assembler supports interunit movq mnemonic.]) gcc_GAS_CHECK_FEATURE([hle prefixes], gcc_cv_as_ix86_hle,,, diff --git a/gcc/convert.c b/gcc/convert.c index b07f0efe820..a2f2a334dbf 100644 --- a/gcc/convert.c +++ b/gcc/convert.c @@ -135,16 +135,19 @@ convert_to_real (tree type, tree expr) CASE_MATHFN (COS) CASE_MATHFN (ERF) CASE_MATHFN (ERFC) - CASE_MATHFN (FABS) CASE_MATHFN (LOG) CASE_MATHFN (LOG10) CASE_MATHFN (LOG2) CASE_MATHFN (LOG1P) - CASE_MATHFN (LOGB) CASE_MATHFN (SIN) - CASE_MATHFN (SQRT) CASE_MATHFN (TAN) CASE_MATHFN (TANH) + /* The above functions are not safe to do this conversion. */ + if (!flag_unsafe_math_optimizations) + break; + CASE_MATHFN (SQRT) + CASE_MATHFN (FABS) + CASE_MATHFN (LOGB) #undef CASE_MATHFN { tree arg0 = strip_float_extensions (CALL_EXPR_ARG (expr, 0)); @@ -155,13 +158,44 @@ convert_to_real (tree type, tree expr) if (TYPE_PRECISION (TREE_TYPE (arg0)) > TYPE_PRECISION (type)) newtype = TREE_TYPE (arg0); + /* We consider to convert + + (T1) sqrtT2 ((T2) exprT3) + to + (T1) sqrtT4 ((T4) exprT3) + + , where T1 is TYPE, T2 is ITYPE, T3 is TREE_TYPE (ARG0), + and T4 is NEWTYPE. All those types are of floating point types. + T4 (NEWTYPE) should be narrower than T2 (ITYPE). This conversion + is safe only if P1 >= P2*2+2, where P1 and P2 are precisions of + T2 and T4. See the following URL for a reference: + http://stackoverflow.com/questions/9235456/determining- + floating-point-square-root + */ + if ((fcode == BUILT_IN_SQRT || fcode == BUILT_IN_SQRTL) + && !flag_unsafe_math_optimizations) + { + /* The following conversion is unsafe even the precision condition + below is satisfied: + + (float) sqrtl ((long double) double_val) -> (float) sqrt (double_val) + */ + if (TYPE_MODE (type) != TYPE_MODE (newtype)) + break; + + int p1 = REAL_MODE_FORMAT (TYPE_MODE (itype))->p; + int p2 = REAL_MODE_FORMAT (TYPE_MODE (newtype))->p; + if (p1 < p2 * 2 + 2) + break; + } + /* Be careful about integer to fp conversions. These may overflow still. */ if (FLOAT_TYPE_P (TREE_TYPE (arg0)) && TYPE_PRECISION (newtype) < TYPE_PRECISION (itype) && (TYPE_MODE (newtype) == TYPE_MODE (double_type_node) || TYPE_MODE (newtype) == TYPE_MODE (float_type_node))) - { + { tree fn = mathfn_built_in (newtype, fcode); if (fn) diff --git a/gcc/coverage.c b/gcc/coverage.c index 9c91f641953..43f9c0cb6f1 100644 --- a/gcc/coverage.c +++ b/gcc/coverage.c @@ -554,12 +554,12 @@ unsigned coverage_compute_profile_id (struct cgraph_node *n) { expanded_location xloc - = expand_location (DECL_SOURCE_LOCATION (n->symbol.decl)); + = expand_location (DECL_SOURCE_LOCATION (n->decl)); unsigned chksum = xloc.line; chksum = coverage_checksum_string (chksum, xloc.file); chksum = coverage_checksum_string - (chksum, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (n->symbol.decl))); + (chksum, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (n->decl))); if (first_global_object_name) chksum = coverage_checksum_string (chksum, first_global_object_name); diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 1da821b7275..8a3df56e63f 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,207 @@ +2013-11-04 Eric Botcazou <ebotcazou@adacore.com> + + * decl2.c (cpp_check): Change type of first parameter and deal with + IS_TRIVIAL. + +2013-11-03 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/38313 + * parser.c (cp_parser_constructor_declarator_p): Check that the + class-name matches current_class_type. + +2013-11-03 Marek Polacek <polacek@redhat.com> + + * decl.c (cp_finish_decl): Move C++1y bounds checking... + (compute_array_index_type): ...here. Add VLA instrumentation. + Call stabilize_vla_size. + (grokdeclarator): Don't call stabilize_vla_size here. + +2013-11-02 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/29234 + PR c++/56037 + * parser.c (cp_parser_cast_expression): If we aren't looking at + a cast-expression don't call cp_parser_type_id. + (cp_parser_postfix_expression): Likewise for compound-literal. + (cp_parser_tokens_start_cast_expression): Adjust. + +2013-11-01 Edward Smith-Rowland <3dw4rd@verizon.net> + + PR c++/58708 + * parser.c (make_string_pack): Discover non-const type and size + of character and build parm pack with correct type and chars. + +2013-11-01 Trevor Saunders <tsaunders@mozilla.com> + + * semantics.c (build_anon_member_initialization): Convert fields to be + a stack_vec. + +2013-11-01 Marc Glisse <marc.glisse@inria.fr> + + PR c++/58834 + * pt.c (type_dependent_expression_p): Handle null argument. + +2013-11-01 Jakub Jelinek <jakub@redhat.com> + + * semantics.c (finish_omp_clauses) <case OMP_CLAUSE_UNIFORM>: Go to + check_dup_generic at the end, unless remove is true. + (finish_omp_clauses) <case OMP_CLAUSE_LINEAR>: Add break; after + remove = true;. + +2013-10-31 Jakub Jelinek <jakub@redhat.com> + + * semantics.c (finish_omp_clauses): Diagnose aligned clause + with decl that is not pointer nor array nor reference to those. + +2013-10-31 Jason Merrill <jason@redhat.com> + + * semantics.c (cxx_eval_call_expression): Handle trivial + value-initialization. + * typeck2.c (store_init_value): Call maybe_constant_init after + cxx_constant_value. + + * decl.c (cxx_maybe_build_cleanup): Always set LOOKUP_NONVIRTUAL. + * decl2.c (build_cleanup): Just call cxx_maybe_build_cleanup. + + PR c++/58162 + * parser.c (cp_parser_late_parse_one_default_arg): Set + TARGET_EXPR_DIRECT_INIT_P. + + * class.c (type_build_ctor_call): Return early in C++98 mode. + (type_build_dtor_call): Likewise. + +2013-10-31 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/58932 + Revert: + 2013-10-18 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/58466 + * pt.c (most_specialized_class): Bump processing_template_decl for + get_class_bindings. + +2013-10-30 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/58581 + * call.c (build_over_call): Check return value of mark_used. + +2013-10-30 Jason Merrill <jason@redhat.com> + + * semantics.c (finish_compound_literal): Don't create a static variable + inside cp_unevaluated_operand. + + * init.c (push_base_cleanups): Check ANON_AGGR_TYPE_P. + +2013-10-30 Tobias Burnus <burnus@net-b.de> + + PR other/33426 + * cp-tree.h (RANGE_FOR_IVDEP): Define. + (cp_convert_range_for, finish_while_stmt_cond, finish_do_stmt, + finish_for_cond): Take 'bool ivdep' parameter. + * cp-array-notation.c (create_an_loop): Update call. + * init.c (build_vec_init): Ditto. + * pt.c (tsubst_expr): Ditto. + * parser.c (cp_parser_iteration_statement, cp_parser_for, + cp_parser_range_for, cp_convert_range_for): Update calls. + (cp_parser_pragma): Accept GCC ivdep for 'while' and 'do'. + * semantics.c (finish_while_stmt_cond, finish_do_stmt, + finish_for_cond): Optionally build ivdep annotation. + +2013-10-30 Jason Merrill <jason@redhat.com> + + * decl.c (cp_finish_decl): Never throw for VLA bound == 0. + +2013-10-29 David Malcolm <dmalcolm@redhat.com> + + Patch autogenerated by refactor_symtab.py from + https://github.com/davidmalcolm/gcc-refactoring-scripts + revision 58bb219cc090b2f4516a9297d868c245495ee622 + + * call.c (mark_versions_used): Update for conversion of symtab types + to a true class hierarchy. + * decl2.c (cp_write_global_declarations): Likewise. + (clear_decl_external): Likewise. + (build_java_method_aliases): Likewise. + (collect_candidates_for_java_method_aliases): Likewise. + (mark_needed): Likewise. + (var_finalized_p): Likewise. + (maybe_make_one_only): Likewise. + (maybe_emit_vtables): Likewise. + * lambda.c (maybe_add_lambda_conv_op): Likewise. + * method.c (use_thunk): Likewise. + * optimize.c (maybe_clone_body): Likewise. + * tree.c (cp_fix_function_decl_p): Likewise. + +2013-10-29 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/58888 + * decl2.c (grokfield): Handle auto like NSDMI. + +2013-10-25 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/58878 + * pt.c (check_template_shadow): Don't skip declarations in inline + member templates. + +2013-10-25 Tobias Burnus <burnus@net-b.de> + + PR other/33426 + * parser.c (cp_parser_iteration_statement, + cp_parser_for, cp_parser_c_for, cp_parser_pragma): Handle + IVDEP pragma. + +2013-10-24 Marek Polacek <polacek@redhat.com> + + PR c++/58705 + * typeck2.c (check_narrowing): Don't check narrowing when the scalar + initializer is empty. + +2013-10-23 Jason Merrill <jason@redhat.com> + + LWG 2165 + * method.c (defaulted_late_check): Delete on eh-spec mismatch. + (maybe_explain_implicit_delete): Explain it. + + * error.c (eh_spec_to_string): New. + (cp_printer): Use it for %X. + + In C++11 a trivial [cd]tor might not be callable. + * class.c (user_provided_p): A function deleted on its declation + in the class is not user-provided. + (type_build_ctor_call): Also force a ctor call if we + might have a deleted or private trivial ctor. + (type_build_dtor_call): New. + (deduce_noexcept_on_destructors): Remove obsolete code. + * cp-tree.h: Declare type_build_dtor_call. + * decl.c (expand_static_init): Make sure trivial dtors are callable. + (cxx_maybe_build_cleanup): Likewise. + * except.c (build_throw): Likewise. + * init.c (build_value_init): Handle trivial but not callable ctors. + (perform_target_ctor): Make sure trivial dtor is callable. + (perform_member_init): Likewise. + (expand_cleanup_for_base): Likewise. + (build_vec_delete_1): Likewise. + (build_delete): Likewise. + (push_base_cleanups): Likewise. + (build_new_1): Avoid redundant error. + * method.c (synthesized_method_walk): Can't ever exit early in C++11. + Always process the subobject destructor. + * semantics.c (finish_compound_literal): Make sure trivial dtor is + callable. + * typeck2.c (split_nonconstant_init): Likewise. + +2013-10-23 Edward Smith-Rowland <3dw4rd@verizon.net> + + Implement C++14 [[deprecated]] modulo [[gnu::deprecated]] bugs. + * parser.c (cp_parser_std_attribute): Interpret [[deprecated]] + as [[gnu::deprecated]]. + +2013-10-22 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/58816 + * pt.c (apply_late_template_attributes): Use get_attribute_name, + not TREE_PURPOSE. + 2013-10-18 Paolo Carlini <paolo.carlini@oracle.com> PR c++/58466 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index c0eb1d6b824..e2907badc3a 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -6629,7 +6629,7 @@ mark_versions_used (tree fn) it_v = node_v->next; while (it_v != NULL) { - mark_used (it_v->this_node->symbol.decl); + mark_used (it_v->this_node->decl); it_v = it_v->next; } } @@ -7111,8 +7111,9 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) mark_versions_used (fn); } - if (!already_used) - mark_used (fn); + if (!already_used + && !mark_used (fn)) + return error_mark_node; if (DECL_VINDEX (fn) && (flags & LOOKUP_NONVIRTUAL) == 0 /* Don't mess with virtual lookup in fold_non_dependent_expr; virtual @@ -9272,6 +9273,9 @@ set_up_extended_ref_temp (tree decl, tree expr, vec<tree, va_gc> **cleanups, static_aggregates = tree_cons (NULL_TREE, var, static_aggregates); } + else + /* Check whether the dtor is callable. */ + cxx_maybe_build_cleanup (var, tf_warning_or_error); } *initp = init; diff --git a/gcc/cp/class.c b/gcc/cp/class.c index b90ef3fb8ed..a0c3ab7e72b 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -4675,15 +4675,8 @@ deduce_noexcept_on_destructors (tree t) if (!CLASSTYPE_METHOD_VEC (t)) return; - bool saved_nontrivial_dtor = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t); - - /* Avoid early exit from synthesized_method_walk (c++/57645). */ - TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) = true; - for (tree fns = CLASSTYPE_DESTRUCTORS (t); fns; fns = OVL_NEXT (fns)) deduce_noexcept_on_destructor (OVL_CURRENT (fns)); - - TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) = saved_nontrivial_dtor; } /* Subroutine of set_one_vmethod_tm_attributes. Search base classes @@ -4885,7 +4878,8 @@ user_provided_p (tree fn) return true; else return (!DECL_ARTIFICIAL (fn) - && !DECL_DEFAULTED_IN_CLASS_P (fn)); + && !(DECL_INITIALIZED_IN_CLASS_P (fn) + && (DECL_DEFAULTED_FN (fn) || DECL_DELETED_FN (fn)))); } /* Returns true iff class T has a user-provided constructor. */ @@ -5150,7 +5144,7 @@ type_has_user_declared_move_assign (tree t) } /* Nonzero if we need to build up a constructor call when initializing an - object of this class, either because it has a user-provided constructor + object of this class, either because it has a user-declared constructor or because it doesn't have a default constructor (so we need to give an error if no initializer is provided). Use TYPE_NEEDS_CONSTRUCTING when what you care about is whether or not an object can be produced by a @@ -5166,8 +5160,50 @@ type_build_ctor_call (tree t) if (TYPE_NEEDS_CONSTRUCTING (t)) return true; inner = strip_array_types (t); - return (CLASS_TYPE_P (inner) && !TYPE_HAS_DEFAULT_CONSTRUCTOR (inner) - && !ANON_AGGR_TYPE_P (inner)); + if (!CLASS_TYPE_P (inner) || ANON_AGGR_TYPE_P (inner)) + return false; + if (!TYPE_HAS_DEFAULT_CONSTRUCTOR (inner)) + return true; + if (cxx_dialect < cxx11) + return false; + /* A user-declared constructor might be private, and a constructor might + be trivial but deleted. */ + for (tree fns = lookup_fnfields_slot (inner, complete_ctor_identifier); + fns; fns = OVL_NEXT (fns)) + { + tree fn = OVL_CURRENT (fns); + if (!DECL_ARTIFICIAL (fn) + || DECL_DELETED_FN (fn)) + return true; + } + return false; +} + +/* Like type_build_ctor_call, but for destructors. */ + +bool +type_build_dtor_call (tree t) +{ + tree inner; + if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)) + return true; + inner = strip_array_types (t); + if (!CLASS_TYPE_P (inner) || ANON_AGGR_TYPE_P (inner) + || !COMPLETE_TYPE_P (inner)) + return false; + if (cxx_dialect < cxx11) + return false; + /* A user-declared destructor might be private, and a destructor might + be trivial but deleted. */ + for (tree fns = lookup_fnfields_slot (inner, complete_dtor_identifier); + fns; fns = OVL_NEXT (fns)) + { + tree fn = OVL_CURRENT (fns); + if (!DECL_ARTIFICIAL (fn) + || DECL_DELETED_FN (fn)) + return true; + } + return false; } /* Remove all zero-width bit-fields from T. */ diff --git a/gcc/cp/cp-array-notation.c b/gcc/cp/cp-array-notation.c index c700f58f69f..e1fb0ee99ad 100644 --- a/gcc/cp/cp-array-notation.c +++ b/gcc/cp/cp-array-notation.c @@ -71,7 +71,7 @@ create_an_loop (tree init, tree cond, tree incr, tree body) finish_expr_stmt (init); for_stmt = begin_for_stmt (NULL_TREE, NULL_TREE); finish_for_init_stmt (for_stmt); - finish_for_cond (cond, for_stmt); + finish_for_cond (cond, for_stmt, false); finish_for_expr (incr, for_stmt); finish_expr_stmt (body); finish_for_stmt (for_stmt); diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 713e001730c..7a1c900193a 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -116,6 +116,7 @@ c-common.h, not after. 6: IDENTIFIER_REPO_CHOSEN (in IDENTIFIER_NODE) DECL_CONSTRUCTION_VTABLE_P (in VAR_DECL) TYPE_MARKED_P (in _TYPE) + RANGE_FOR_IVDEP (in RANGE_FOR_STMT) Usage of TYPE_LANG_FLAG_?: 0: TYPE_DEPENDENT_P @@ -4088,6 +4089,7 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) #define RANGE_FOR_EXPR(NODE) TREE_OPERAND (RANGE_FOR_STMT_CHECK (NODE), 1) #define RANGE_FOR_BODY(NODE) TREE_OPERAND (RANGE_FOR_STMT_CHECK (NODE), 2) #define RANGE_FOR_SCOPE(NODE) TREE_OPERAND (RANGE_FOR_STMT_CHECK (NODE), 3) +#define RANGE_FOR_IVDEP(NODE) TREE_LANG_FLAG_6 (RANGE_FOR_STMT_CHECK (NODE)) #define SWITCH_STMT_COND(NODE) TREE_OPERAND (SWITCH_STMT_CHECK (NODE), 0) #define SWITCH_STMT_BODY(NODE) TREE_OPERAND (SWITCH_STMT_CHECK (NODE), 1) @@ -4321,7 +4323,7 @@ extern int comparing_specializations; sizeof can be nested. */ extern int cp_unevaluated_operand; -extern tree cp_convert_range_for (tree, tree, tree); +extern tree cp_convert_range_for (tree, tree, tree, bool); extern bool parsing_nsdmi (void); /* in pt.c */ @@ -5115,6 +5117,7 @@ extern bool type_has_move_assign (tree); extern bool type_has_user_declared_move_constructor (tree); extern bool type_has_user_declared_move_assign(tree); extern bool type_build_ctor_call (tree); +extern bool type_build_dtor_call (tree); extern void explain_non_literal_class (tree); extern void defaulted_late_check (tree); extern bool defaultable_fn_check (tree); @@ -5670,16 +5673,16 @@ extern void begin_else_clause (tree); extern void finish_else_clause (tree); extern void finish_if_stmt (tree); extern tree begin_while_stmt (void); -extern void finish_while_stmt_cond (tree, tree); +extern void finish_while_stmt_cond (tree, tree, bool); extern void finish_while_stmt (tree); extern tree begin_do_stmt (void); extern void finish_do_body (tree); -extern void finish_do_stmt (tree, tree); +extern void finish_do_stmt (tree, tree, bool); extern tree finish_return_stmt (tree); extern tree begin_for_scope (tree *); extern tree begin_for_stmt (tree, tree); extern void finish_for_init_stmt (tree); -extern void finish_for_cond (tree, tree); +extern void finish_for_cond (tree, tree, bool); extern void finish_for_expr (tree, tree); extern void finish_for_stmt (tree); extern tree begin_range_for_stmt (tree, tree); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 84271fef4dd..81a35004730 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -45,6 +45,7 @@ along with GCC; see the file COPYING3. If not see #include "c-family/c-objc.h" #include "c-family/c-pragma.h" #include "c-family/c-target.h" +#include "c-family/c-ubsan.h" #include "diagnostic.h" #include "intl.h" #include "debug.h" @@ -6400,21 +6401,6 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, && TYPE_FOR_JAVA (type) && MAYBE_CLASS_TYPE_P (type)) error ("non-static data member %qD has Java class type", decl); - if (cxx_dialect >= cxx1y && array_of_runtime_bound_p (type)) - { - /* If the VLA bound is larger than half the address space, or less - than zero, throw std::bad_array_length. */ - tree max = convert (ssizetype, TYPE_MAX_VALUE (TYPE_DOMAIN (type))); - /* C++1y says we should throw for length <= 0, but we have - historically supported zero-length arrays. Let's treat that as an - extension to be disabled by -std=c++NN. */ - int lower = flag_iso ? 0 : -1; - tree comp = build2 (LT_EXPR, boolean_type_node, max, ssize_int (lower)); - comp = build3 (COND_EXPR, void_type_node, comp, - throw_bad_array_length (), void_zero_node); - finish_expr_stmt (comp); - } - /* Add this declaration to the statement-tree. This needs to happen after the call to check_initializer so that the DECL_EXPR for a reference temp is added before the DECL_EXPR for the reference itself. */ @@ -6898,7 +6884,11 @@ expand_static_init (tree decl, tree init) /* Some variables require no dynamic initialization. */ if (!init && TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl))) - return; + { + /* Make sure the destructor is callable. */ + cxx_maybe_build_cleanup (decl, tf_warning_or_error); + return; + } if (DECL_THREAD_LOCAL_P (decl) && DECL_GNU_TLS_P (decl) && !DECL_FUNCTION_SCOPE_P (decl)) @@ -8380,6 +8370,7 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain) { /* A variable sized array. */ itype = variable_size (itype); + if (TREE_CODE (itype) != SAVE_EXPR) { /* Look for SIZEOF_EXPRs in itype and fold them, otherwise @@ -8391,6 +8382,32 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain) if (found) itype = variable_size (fold (newitype)); } + + stabilize_vla_size (itype); + + if (cxx_dialect >= cxx1y) + { + /* If the VLA bound is larger than half the address space, + or less than zero, throw std::bad_array_length. */ + tree comp = build2 (LT_EXPR, boolean_type_node, itype, + ssize_int (-1)); + comp = build3 (COND_EXPR, void_type_node, comp, + throw_bad_array_length (), void_zero_node); + finish_expr_stmt (comp); + } + else if (flag_sanitize & SANITIZE_VLA) + { + /* From C++1y onwards, we throw an exception on a negative + length size of an array; see above. */ + + /* We have to add 1 -- in the ubsan routine we generate + LE_EXPR rather than LT_EXPR. */ + tree t = fold_build2 (PLUS_EXPR, TREE_TYPE (itype), itype, + build_one_cst (TREE_TYPE (itype))); + t = fold_build2 (COMPOUND_EXPR, TREE_TYPE (t), + ubsan_instrument_vla (input_location, t), t); + finish_expr_stmt (t); + } } /* Make sure that there was no overflow when creating to a signed index type. (For example, on a 32-bit machine, an array with @@ -9791,12 +9808,8 @@ grokdeclarator (const cp_declarator *declarator, && (decl_context == NORMAL || decl_context == FIELD) && at_function_scope_p () && variably_modified_type_p (type, NULL_TREE)) - { - /* First break out any side-effects. */ - stabilize_vla_size (TYPE_SIZE (type)); - /* And then force evaluation of the SAVE_EXPR. */ - finish_expr_stmt (TYPE_SIZE (type)); - } + /* Force evaluation of the SAVE_EXPR. */ + finish_expr_stmt (TYPE_SIZE (type)); if (declarator->kind == cdk_reference) { @@ -9887,14 +9900,6 @@ grokdeclarator (const cp_declarator *declarator, } } - /* We need to stabilize side-effects in VLA sizes for regular array - declarations too, not just pointers to arrays. */ - if (type != error_mark_node && !TYPE_NAME (type) - && (decl_context == NORMAL || decl_context == FIELD) - && at_function_scope_p () - && variably_modified_type_p (type, NULL_TREE)) - stabilize_vla_size (TYPE_SIZE (type)); - /* A `constexpr' specifier used in an object declaration declares the object as `const'. */ if (constexpr_p && innermost_code != cdk_function) @@ -14296,11 +14301,9 @@ cxx_maybe_build_cleanup (tree decl, tsubst_flags_t complain) } /* Handle ordinary C++ destructors. */ type = TREE_TYPE (decl); - if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)) + if (type_build_dtor_call (type)) { - int flags = LOOKUP_NORMAL|LOOKUP_DESTRUCTOR; - bool has_vbases = (TREE_CODE (type) == RECORD_TYPE - && CLASSTYPE_VBASECLASSES (type)); + int flags = LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR; tree addr; tree call; @@ -14309,14 +14312,12 @@ cxx_maybe_build_cleanup (tree decl, tsubst_flags_t complain) else addr = build_address (decl); - /* Optimize for space over speed here. */ - if (!has_vbases || flag_expensive_optimizations) - flags |= LOOKUP_NONVIRTUAL; - call = build_delete (TREE_TYPE (addr), addr, sfk_complete_destructor, flags, 0, complain); if (call == error_mark_node) cleanup = error_mark_node; + else if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type)) + /* Discard the call. */; else if (cleanup) cleanup = cp_build_compound_expr (cleanup, call, complain); else diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 5e5f5e82919..a094ff3b546 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -955,26 +955,6 @@ grokfield (const cp_declarator *declarator, /* C++11 NSDMI, keep going. */; else if (!VAR_P (value)) gcc_unreachable (); - else if (!processing_template_decl) - { - if (TREE_CODE (init) == CONSTRUCTOR) - init = digest_init (TREE_TYPE (value), init, tf_warning_or_error); - init = maybe_constant_init (init); - - if (init != error_mark_node && !TREE_CONSTANT (init)) - { - /* We can allow references to things that are effectively - static, since references are initialized with the - address. */ - if (TREE_CODE (TREE_TYPE (value)) != REFERENCE_TYPE - || (TREE_STATIC (init) == 0 - && (!DECL_P (init) || DECL_EXTERNAL (init) == 0))) - { - error ("field initializer is not constant"); - init = error_mark_node; - } - } - } } if (processing_template_decl && VAR_OR_FUNCTION_DECL_P (value)) @@ -1767,7 +1747,7 @@ maybe_make_one_only (tree decl) struct varpool_node *node = varpool_node_for_decl (decl); DECL_COMDAT (decl) = 1; /* Mark it needed so we don't forget to emit it. */ - node->symbol.forced_by_abi = true; + node->forced_by_abi = true; TREE_USED (decl) = 1; } } @@ -1865,7 +1845,7 @@ import_export_class (tree ctype) static bool var_finalized_p (tree var) { - return varpool_node_for_decl (var)->symbol.definition; + return varpool_node_for_decl (var)->definition; } /* DECL is a VAR_DECL or FUNCTION_DECL which, for whatever reason, @@ -1882,14 +1862,14 @@ mark_needed (tree decl) functions can be marked reachable, just use the external definition. */ struct cgraph_node *node = cgraph_get_create_node (decl); - node->symbol.forced_by_abi = true; + node->forced_by_abi = true; } else if (TREE_CODE (decl) == VAR_DECL) { struct varpool_node *node = varpool_node_for_decl (decl); /* C++ frontend use mark_decl_references to force COMDAT variables to be output that might appear dead otherwise. */ - node->symbol.forced_by_abi = true; + node->forced_by_abi = true; } } @@ -1999,7 +1979,7 @@ maybe_emit_vtables (tree ctype) { current = varpool_node_for_decl (vtbl); if (last) - symtab_add_to_same_comdat_group ((symtab_node) current, (symtab_node) last); + symtab_add_to_same_comdat_group (current, last); last = current; } } @@ -2742,26 +2722,9 @@ import_export_decl (tree decl) tree build_cleanup (tree decl) { - tree temp; - tree type = TREE_TYPE (decl); - - /* This function should only be called for declarations that really - require cleanups. */ - gcc_assert (!TYPE_HAS_TRIVIAL_DESTRUCTOR (type)); - - /* Treat all objects with destructors as used; the destructor may do - something substantive. */ - mark_used (decl); - - if (TREE_CODE (type) == ARRAY_TYPE) - temp = decl; - else - temp = build_address (decl); - temp = build_delete (TREE_TYPE (temp), temp, - sfk_complete_destructor, - LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0, - tf_warning_or_error); - return temp; + tree clean = cxx_maybe_build_cleanup (decl, tf_warning_or_error); + gcc_assert (clean != NULL_TREE); + return clean; } /* Returns the initialization guard variable for the variable DECL, @@ -3764,7 +3727,7 @@ collect_candidates_for_java_method_aliases (void) FOR_EACH_FUNCTION (node) { - tree fndecl = node->symbol.decl; + tree fndecl = node->decl; if (DECL_CLASS_SCOPE_P (fndecl) && TYPE_FOR_JAVA (DECL_CONTEXT (fndecl)) @@ -3797,7 +3760,7 @@ build_java_method_aliases (struct pointer_set_t *candidates) FOR_EACH_FUNCTION (node) { - tree fndecl = node->symbol.decl; + tree fndecl = node->decl; if (TREE_ASM_WRITTEN (fndecl) && pointer_set_contains (candidates, fndecl)) @@ -3826,7 +3789,7 @@ build_java_method_aliases (struct pointer_set_t *candidates) /* Return C++ property of T, based on given operation OP. */ static int -cpp_check (tree t, cpp_operation op) +cpp_check (const_tree t, cpp_operation op) { switch (op) { @@ -3840,6 +3803,8 @@ cpp_check (tree t, cpp_operation op) return DECL_COPY_CONSTRUCTOR_P (t); case IS_TEMPLATE: return TREE_CODE (t) == TEMPLATE_DECL; + case IS_TRIVIAL: + return trivial_type_p (t); default: return 0; } @@ -3978,7 +3943,7 @@ collect_all_refs (const char *source_file) static bool clear_decl_external (struct cgraph_node *node, void * /*data*/) { - DECL_EXTERNAL (node->symbol.decl) = 0; + DECL_EXTERNAL (node->decl) = 0; return false; } @@ -4296,7 +4261,7 @@ cp_write_global_declarations (void) struct cgraph_node *node, *next; node = cgraph_get_node (decl); - if (node->symbol.cpp_implicit_alias) + if (node->cpp_implicit_alias) node = cgraph_alias_target (node); cgraph_for_node_and_aliases (node, clear_decl_external, @@ -4304,10 +4269,10 @@ cp_write_global_declarations (void) /* If we mark !DECL_EXTERNAL one of the symbols in some comdat group, we need to mark all symbols in the same comdat group that way. */ - if (node->symbol.same_comdat_group) - for (next = cgraph (node->symbol.same_comdat_group); + if (node->same_comdat_group) + for (next = cgraph (node->same_comdat_group); next != node; - next = cgraph (next->symbol.same_comdat_group)) + next = cgraph (next->same_comdat_group)) cgraph_for_node_and_aliases (next, clear_decl_external, NULL, true); } @@ -4319,7 +4284,7 @@ cp_write_global_declarations (void) if (!DECL_EXTERNAL (decl) && decl_needed_p (decl) && !TREE_ASM_WRITTEN (decl) - && !cgraph_get_node (decl)->symbol.definition) + && !cgraph_get_node (decl)->definition) { /* We will output the function; no longer consider it in this loop. */ diff --git a/gcc/cp/error.c b/gcc/cp/error.c index 1627afab95d..0ad9f0722db 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -2998,6 +2998,15 @@ cv_to_string (tree p, int v) return pp_ggc_formatted_text (cxx_pp); } +static const char * +eh_spec_to_string (tree p, int /*v*/) +{ + int flags = 0; + reinit_cxx_pp (); + dump_exception_spec (cxx_pp, p, flags); + return pp_ggc_formatted_text (cxx_pp); +} + /* Langhook for print_error_function. */ void cxx_print_error_function (diagnostic_context *context, const char *file, @@ -3379,8 +3388,10 @@ maybe_print_constexpr_context (diagnostic_context *context) %O binary operator. %P function parameter whose position is indicated by an integer. %Q assignment operator. + %S substitution (template + args) %T type. - %V cv-qualifier. */ + %V cv-qualifier. + %X exception-specification. */ static bool cp_printer (pretty_printer *pp, text_info *text, const char *spec, int precision, bool wide, bool set_locus, bool verbose) @@ -3427,6 +3438,7 @@ cp_printer (pretty_printer *pp, text_info *text, const char *spec, case 'S': result = subst_to_string (next_tree); break; case 'T': result = type_to_string (next_tree, verbose); break; case 'V': result = cv_to_string (next_tree, verbose); break; + case 'X': result = eh_spec_to_string (next_tree, verbose); break; case 'K': percent_K_format (text); diff --git a/gcc/cp/except.c b/gcc/cp/except.c index c76d9440aa9..daac0fde7e6 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -868,17 +868,21 @@ build_throw (tree exp) throw_type = build_eh_type_type (prepare_eh_type (TREE_TYPE (object))); - if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (object))) + cleanup = NULL_TREE; + if (type_build_dtor_call (TREE_TYPE (object))) { - cleanup = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)), + tree fn = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)), complete_dtor_identifier, 0); - cleanup = BASELINK_FUNCTIONS (cleanup); - mark_used (cleanup); - cxx_mark_addressable (cleanup); - /* Pretend it's a normal function. */ - cleanup = build1 (ADDR_EXPR, cleanup_type, cleanup); + fn = BASELINK_FUNCTIONS (fn); + mark_used (fn); + if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (object))) + { + cxx_mark_addressable (fn); + /* Pretend it's a normal function. */ + cleanup = build1 (ADDR_EXPR, cleanup_type, fn); + } } - else + if (cleanup == NULL_TREE) cleanup = build_int_cst (cleanup_type, 0); /* ??? Indicate that this function call throws throw_type. */ diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 17d320db072..23c449ea85d 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -313,60 +313,55 @@ build_value_init (tree type, tsubst_flags_t complain) To value-initialize an object of type T means: - - if T is a class type (clause 9) with a user-provided constructor - (12.1), then the default constructor for T is called (and the - initialization is ill-formed if T has no accessible default - constructor); + - if T is a class type (clause 9) with either no default constructor + (12.1) or a default constructor that is user-provided or deleted, + then then the object is default-initialized; - - if T is a non-union class type without a user-provided constructor, - then every non-static data member and base-class component of T is - value-initialized;92) + - if T is a (possibly cv-qualified) class type without a user-provided + or deleted default constructor, then the object is zero-initialized + and the semantic constraints for default-initialization are checked, + and if T has a non-trivial default constructor, the object is + default-initialized; - if T is an array type, then each element is value-initialized; - otherwise, the object is zero-initialized. A program that calls for default-initialization or - value-initialization of an entity of reference type is ill-formed. - - 92) Value-initialization for such a class object may be implemented by - zero-initializing the object and then calling the default - constructor. */ + value-initialization of an entity of reference type is ill-formed. */ /* The AGGR_INIT_EXPR tweaking below breaks in templates. */ gcc_assert (!processing_template_decl || (SCALAR_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE)); - if (CLASS_TYPE_P (type)) + if (type_build_ctor_call (type)) { - /* Instead of the above, only consider the user-providedness of the - default constructor itself so value-initializing a class with an - explicitly defaulted default constructor and another user-provided - constructor works properly (c++std-core-19883). */ - if (type_has_user_provided_default_constructor (type) - || (!TYPE_HAS_DEFAULT_CONSTRUCTOR (type) - && type_has_user_provided_constructor (type))) - return build_aggr_init_expr - (type, - build_special_member_call (NULL_TREE, complete_ctor_identifier, - NULL, type, LOOKUP_NORMAL, - complain)); + tree ctor = build_aggr_init_expr + (type, + build_special_member_call (NULL_TREE, complete_ctor_identifier, + NULL, type, LOOKUP_NORMAL, + complain)); + if (ctor == error_mark_node + || type_has_user_provided_default_constructor (type)) + return ctor; else if (TYPE_HAS_COMPLEX_DFLT (type)) { /* This is a class that needs constructing, but doesn't have a user-provided constructor. So we need to zero-initialize the object and then call the implicitly defined ctor. This will be handled in simplify_aggr_init_expr. */ - tree ctor = build_special_member_call - (NULL_TREE, complete_ctor_identifier, - NULL, type, LOOKUP_NORMAL, complain); - ctor = build_aggr_init_expr (type, ctor); - if (ctor != error_mark_node) - AGGR_INIT_ZERO_FIRST (ctor) = 1; + AGGR_INIT_ZERO_FIRST (ctor) = 1; return ctor; } } - return build_value_init_noctor (type, complain); + + /* Discard any access checking during subobject initialization; + the checks are implied by the call to the ctor which we have + verified is OK (cpp0x/defaulted46.C). */ + push_deferring_access_checks (dk_deferred); + tree r = build_value_init_noctor (type, complain); + pop_deferring_access_checks (); + return r; } /* Like build_value_init, but don't call the constructor for TYPE. Used @@ -504,14 +499,15 @@ perform_target_ctor (tree init) finish_expr_stmt (build_aggr_init (decl, init, LOOKUP_NORMAL|LOOKUP_DELEGATING_CONS, tf_warning_or_error)); - if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)) + if (type_build_dtor_call (type)) { tree expr = build_delete (type, decl, sfk_complete_destructor, LOOKUP_NORMAL |LOOKUP_NONVIRTUAL |LOOKUP_DESTRUCTOR, 0, tf_warning_or_error); - if (expr != error_mark_node) + if (expr != error_mark_node + && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)) finish_eh_cleanup (expr); } } @@ -733,7 +729,7 @@ perform_member_init (tree member, tree init) tf_warning_or_error)); } - if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)) + if (type_build_dtor_call (type)) { tree expr; @@ -745,7 +741,8 @@ perform_member_init (tree member, tree init) LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0, tf_warning_or_error); - if (expr != error_mark_node) + if (expr != error_mark_node + && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)) finish_eh_cleanup (expr); } } @@ -1193,7 +1190,7 @@ expand_cleanup_for_base (tree binfo, tree flag) { tree expr; - if (TYPE_HAS_TRIVIAL_DESTRUCTOR (BINFO_TYPE (binfo))) + if (!type_build_dtor_call (BINFO_TYPE (binfo))) return; /* Call the destructor. */ @@ -1203,6 +1200,10 @@ expand_cleanup_for_base (tree binfo, tree flag) binfo, LOOKUP_NORMAL | LOOKUP_NONVIRTUAL, tf_warning_or_error); + + if (TYPE_HAS_TRIVIAL_DESTRUCTOR (BINFO_TYPE (binfo))) + return; + if (flag) expr = fold_build3_loc (input_location, COND_EXPR, void_type_node, @@ -2360,7 +2361,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts, is_initialized = (type_build_ctor_call (elt_type) || *init != NULL); - if (*init == NULL) + if (*init == NULL && cxx_dialect < cxx11) { bool maybe_uninitialized_error = false; /* A program that calls for default-initialization [...] of an @@ -3150,8 +3151,21 @@ build_vec_delete_1 (tree base, tree maxindex, tree type, size_exp = size_in_bytes (type); - if (! MAYBE_CLASS_TYPE_P (type) || TYPE_HAS_TRIVIAL_DESTRUCTOR (type)) + if (! MAYBE_CLASS_TYPE_P (type)) goto no_destructor; + else if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type)) + { + /* Make sure the destructor is callable. */ + if (type_build_dtor_call (type)) + { + tmp = build_delete (ptype, base, sfk_complete_destructor, + LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 1, + complain); + if (tmp == error_mark_node) + return error_mark_node; + } + goto no_destructor; + } /* The below is short by the cookie size. */ virtual_size = size_binop (MULT_EXPR, size_exp, @@ -3651,7 +3665,7 @@ build_vec_init (tree base, tree maxindex, tree init, finish_for_init_stmt (for_stmt); finish_for_cond (build2 (NE_EXPR, boolean_type_node, iterator, build_int_cst (TREE_TYPE (iterator), -1)), - for_stmt); + for_stmt, false); elt_init = cp_build_unary_op (PREDECREMENT_EXPR, iterator, 0, complain); if (elt_init == error_mark_node) @@ -3827,7 +3841,7 @@ build_dtor_call (tree exp, special_function_kind dtor_kind, int flags, flags. See cp-tree.h for more info. */ tree -build_delete (tree type, tree addr, special_function_kind auto_delete, +build_delete (tree otype, tree addr, special_function_kind auto_delete, int flags, int use_global_delete, tsubst_flags_t complain) { tree expr; @@ -3835,22 +3849,33 @@ build_delete (tree type, tree addr, special_function_kind auto_delete, if (addr == error_mark_node) return error_mark_node; + tree type = TYPE_MAIN_VARIANT (otype); + /* Can happen when CURRENT_EXCEPTION_OBJECT gets its type set to `error_mark_node' before it gets properly cleaned up. */ if (type == error_mark_node) return error_mark_node; - type = TYPE_MAIN_VARIANT (type); + if (TREE_CODE (type) == POINTER_TYPE) + type = TYPE_MAIN_VARIANT (TREE_TYPE (type)); - addr = mark_rvalue_use (addr); + if (TREE_CODE (type) == ARRAY_TYPE) + { + if (TYPE_DOMAIN (type) == NULL_TREE) + { + if (complain & tf_error) + error ("unknown array size in delete"); + return error_mark_node; + } + return build_vec_delete (addr, array_type_nelts (type), + auto_delete, use_global_delete, complain); + } - if (TYPE_PTR_P (type)) + if (TYPE_PTR_P (otype)) { bool complete_p = true; - type = TYPE_MAIN_VARIANT (TREE_TYPE (type)); - if (TREE_CODE (type) == ARRAY_TYPE) - goto handle_array; + addr = mark_rvalue_use (addr); /* We don't want to warn about delete of void*, only other incomplete types. Deleting other incomplete types @@ -3906,19 +3931,6 @@ build_delete (tree type, tree addr, special_function_kind auto_delete, /* Throw away const and volatile on target type of addr. */ addr = convert_force (build_pointer_type (type), addr, 0, complain); } - else if (TREE_CODE (type) == ARRAY_TYPE) - { - handle_array: - - if (TYPE_DOMAIN (type) == NULL_TREE) - { - if (complain & tf_error) - error ("unknown array size in delete"); - return error_mark_node; - } - return build_vec_delete (addr, array_type_nelts (type), - auto_delete, use_global_delete, complain); - } else { /* Don't check PROTECT here; leave that decision to the @@ -3933,10 +3945,18 @@ build_delete (tree type, tree addr, special_function_kind auto_delete, addr = convert_force (build_pointer_type (type), addr, 0, complain); } - gcc_assert (MAYBE_CLASS_TYPE_P (type)); - if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type)) { + /* Make sure the destructor is callable. */ + if (type_build_dtor_call (type)) + { + expr = build_dtor_call (cp_build_indirect_ref (addr, RO_NULL, + complain), + sfk_complete_destructor, flags, complain); + if (expr == error_mark_node) + return error_mark_node; + } + if (auto_delete != sfk_deleting_destructor) return void_zero_node; @@ -4060,7 +4080,7 @@ push_base_cleanups (void) for (vbases = CLASSTYPE_VBASECLASSES (current_class_type), i = 0; vec_safe_iterate (vbases, i, &base_binfo); i++) { - if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo))) + if (type_build_dtor_call (BINFO_TYPE (base_binfo))) { expr = build_special_member_call (current_class_ref, base_dtor_identifier, @@ -4068,10 +4088,13 @@ push_base_cleanups (void) base_binfo, (LOOKUP_NORMAL | LOOKUP_NONVIRTUAL), - tf_warning_or_error); - expr = build3 (COND_EXPR, void_type_node, cond, - expr, void_zero_node); - finish_decl_cleanup (NULL_TREE, expr); + tf_warning_or_error); + if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo))) + { + expr = build3 (COND_EXPR, void_type_node, cond, + expr, void_zero_node); + finish_decl_cleanup (NULL_TREE, expr); + } } } } @@ -4080,8 +4103,8 @@ push_base_cleanups (void) for (binfo = TYPE_BINFO (current_class_type), i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) { - if (TYPE_HAS_TRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo)) - || BINFO_VIRTUAL_P (base_binfo)) + if (BINFO_VIRTUAL_P (base_binfo) + || !type_build_dtor_call (BINFO_TYPE (base_binfo))) continue; expr = build_special_member_call (current_class_ref, @@ -4089,7 +4112,8 @@ push_base_cleanups (void) NULL, base_binfo, LOOKUP_NORMAL | LOOKUP_NONVIRTUAL, tf_warning_or_error); - finish_decl_cleanup (NULL_TREE, expr); + if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo))) + finish_decl_cleanup (NULL_TREE, expr); } /* Don't automatically destroy union members. */ @@ -4104,9 +4128,9 @@ push_base_cleanups (void) || TREE_CODE (member) != FIELD_DECL || DECL_ARTIFICIAL (member)) continue; - if (ANON_UNION_TYPE_P (this_type)) + if (ANON_AGGR_TYPE_P (this_type)) continue; - if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (this_type)) + if (type_build_dtor_call (this_type)) { tree this_member = (build_class_member_access_expr (current_class_ref, member, @@ -4117,7 +4141,8 @@ push_base_cleanups (void) sfk_complete_destructor, LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_NORMAL, 0, tf_warning_or_error); - finish_decl_cleanup (NULL_TREE, expr); + if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (this_type)) + finish_decl_cleanup (NULL_TREE, expr); } } } diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c index 62812a50c85..f39ce1a5ea6 100644 --- a/gcc/cp/lambda.c +++ b/gcc/cp/lambda.c @@ -1020,8 +1020,8 @@ maybe_add_lambda_conv_op (tree type) { /* Put the thunk in the same comdat group as the call op. */ symtab_add_to_same_comdat_group - ((symtab_node) cgraph_get_create_node (statfn), - (symtab_node) cgraph_get_create_node (callop)); + (cgraph_get_create_node (statfn), + cgraph_get_create_node (callop)); } tree body = begin_function_body (); tree compound_stmt = begin_compound_stmt (0); diff --git a/gcc/cp/method.c b/gcc/cp/method.c index adef81c576e..fa3f083542b 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -386,8 +386,8 @@ use_thunk (tree thunk_fndecl, bool emit_p) this_adjusting, fixed_offset, virtual_value, virtual_offset, alias); if (DECL_ONE_ONLY (function)) - symtab_add_to_same_comdat_group ((symtab_node) thunk_node, - (symtab_node) funcn); + symtab_add_to_same_comdat_group (thunk_node, + funcn); if (!this_adjusting || !targetm.asm_out.can_output_mi_thunk (thunk_fndecl, fixed_offset, @@ -1265,8 +1265,9 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, class versions and other properties of the type. But a subobject class can be trivially copyable and yet have overload resolution choose a template constructor for initialization, depending on - rvalueness and cv-quals. So we can't exit early for copy/move - methods in C++0x. The same considerations apply in C++98/03, but + rvalueness and cv-quals. And furthermore, a member in a base might + be trivial but deleted or otherwise not callable. So we can't exit + early in C++0x. The same considerations apply in C++98/03, but there the definition of triviality does not consider overload resolution, so a constructor can be trivial even if it would otherwise call a non-trivial constructor. */ @@ -1282,7 +1283,7 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, inform (input_location, "defaulted default constructor does " "not initialize any non-static data member"); } - if (!diag) + if (!diag && cxx_dialect < cxx11) return; } @@ -1323,7 +1324,7 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, process_subob_fn (rval, spec_p, trivial_p, deleted_p, constexpr_p, diag, basetype); - if (ctor_p && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (basetype)) + if (ctor_p) { /* In a constructor we also need to check the subobject destructors for cleanup of partially constructed objects. */ @@ -1465,13 +1466,34 @@ maybe_explain_implicit_delete (tree decl) tree parms = FUNCTION_FIRST_USER_PARMTYPE (decl); tree parm_type = TREE_VALUE (parms); bool const_p = CP_TYPE_CONST_P (non_reference (parm_type)); + tree raises = NULL_TREE; + bool deleted_p = false; tree scope = push_scope (ctype); - inform (0, "%q+#D is implicitly deleted because the default " - "definition would be ill-formed:", decl); - pop_scope (scope); + synthesized_method_walk (ctype, sfk, const_p, - NULL, NULL, NULL, NULL, true, + &raises, NULL, &deleted_p, NULL, false, DECL_INHERITED_CTOR_BASE (decl), parms); + if (deleted_p) + { + inform (0, "%q+#D is implicitly deleted because the default " + "definition would be ill-formed:", decl); + synthesized_method_walk (ctype, sfk, const_p, + NULL, NULL, NULL, NULL, true, + DECL_INHERITED_CTOR_BASE (decl), parms); + } + else if (!comp_except_specs + (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (decl)), + raises, ce_normal)) + inform (DECL_SOURCE_LOCATION (decl), "%q#F is implicitly " + "deleted because its exception-specification does not " + "match the implicit exception-specification %qX", + decl, raises); +#ifdef ENABLE_CHECKING + else + gcc_unreachable (); +#endif + + pop_scope (scope); } input_location = loc; @@ -1781,9 +1803,10 @@ defaulted_late_check (tree fn) eh_spec, ce_normal)) { if (DECL_DEFAULTED_IN_CLASS_P (fn)) - error ("function %q+D defaulted on its first declaration " - "with an exception-specification that differs from " - "the implicit declaration %q#D", fn, implicit_fn); + { + DECL_DELETED_FN (fn) = true; + eh_spec = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)); + } else error ("function %q+D defaulted on its redeclaration " "with an exception-specification that differs from " diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c index 1b524c3561e..c4ee8484bb9 100644 --- a/gcc/cp/optimize.c +++ b/gcc/cp/optimize.c @@ -339,7 +339,7 @@ maybe_clone_body (tree fn) virtual, it goes into the same comdat group as well. */ if (comdat_group) symtab_add_to_same_comdat_group - ((symtab_node) cgraph_get_create_node (clone), + (cgraph_get_create_node (clone), symtab_get_node (fns[0])); } else if (alias) diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 383ea46b7b5..06d779698f4 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -1970,15 +1970,15 @@ static tree cp_parser_selection_statement static tree cp_parser_condition (cp_parser *); static tree cp_parser_iteration_statement - (cp_parser *); + (cp_parser *, bool); static bool cp_parser_for_init_statement (cp_parser *, tree *decl); static tree cp_parser_for - (cp_parser *); + (cp_parser *, bool); static tree cp_parser_c_for - (cp_parser *, tree, tree); + (cp_parser *, tree, tree, bool); static tree cp_parser_range_for - (cp_parser *, tree, tree, tree); + (cp_parser *, tree, tree, tree, bool); static void do_range_for_auto_deduction (tree, tree); static tree cp_parser_perform_range_for_lookup @@ -3793,22 +3793,39 @@ make_string_pack (tree value) tree charvec; tree argpack = make_node (NONTYPE_ARGUMENT_PACK); const char *str = TREE_STRING_POINTER (value); - int i, len = TREE_STRING_LENGTH (value) - 1; + int sz = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (value)))); + int len = TREE_STRING_LENGTH (value) / sz - 1; tree argvec = make_tree_vec (2); - tree string_char_type_node = TREE_TYPE (TREE_TYPE (value)); + tree str_char_type_node = TREE_TYPE (TREE_TYPE (value)); + str_char_type_node = TYPE_MAIN_VARIANT (str_char_type_node); /* First template parm is character type. */ - TREE_VEC_ELT (argvec, 0) = string_char_type_node; + TREE_VEC_ELT (argvec, 0) = str_char_type_node; /* Fill in CHARVEC with all of the parameters. */ charvec = make_tree_vec (len); - for (i = 0; i < len; ++i) - TREE_VEC_ELT (charvec, i) = build_int_cst (string_char_type_node, str[i]); + if (sz == 1) + { + for (int i = 0; i < len; ++i) + TREE_VEC_ELT (charvec, i) = build_int_cst (str_char_type_node, str[i]); + } + else if (sz == 2) + { + const uint16_t *num = (const uint16_t *)str; + for (int i = 0; i < len; ++i) + TREE_VEC_ELT (charvec, i) = build_int_cst (str_char_type_node, num[i]); + } + else if (sz == 4) + { + const uint32_t *num = (const uint32_t *)str; + for (int i = 0; i < len; ++i) + TREE_VEC_ELT (charvec, i) = build_int_cst (str_char_type_node, num[i]); + } /* Build the argument packs. */ SET_ARGUMENT_PACK_ARGS (argpack, charvec); - TREE_TYPE (argpack) = string_char_type_node; + TREE_TYPE (argpack) = str_char_type_node; TREE_VEC_ELT (argvec, 1) = argpack; @@ -5800,31 +5817,45 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)) { tree initializer = NULL_TREE; - bool saved_in_type_id_in_expr_p; + bool compound_literal_p; cp_parser_parse_tentatively (parser); /* Consume the `('. */ cp_lexer_consume_token (parser->lexer); - /* Parse the type. */ - saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p; - parser->in_type_id_in_expr_p = true; - type = cp_parser_type_id (parser); - parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p; - /* Look for the `)'. */ - cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); + + /* Avoid calling cp_parser_type_id pointlessly, see comment + in cp_parser_cast_expression about c++/29234. */ + cp_lexer_save_tokens (parser->lexer); + + compound_literal_p + = (cp_parser_skip_to_closing_parenthesis (parser, false, false, + /*consume_paren=*/true) + && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)); + + /* Roll back the tokens we skipped. */ + cp_lexer_rollback_tokens (parser->lexer); + + if (!compound_literal_p) + cp_parser_simulate_error (parser); + else + { + /* Parse the type. */ + bool saved_in_type_id_in_expr_p = parser->in_type_id_in_expr_p; + parser->in_type_id_in_expr_p = true; + type = cp_parser_type_id (parser); + parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p; + /* Look for the `)'. */ + cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); + } + /* If things aren't going well, there's no need to keep going. */ if (!cp_parser_error_occurred (parser)) { - if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) - { - bool non_constant_p; - /* Parse the brace-enclosed initializer list. */ - initializer = cp_parser_braced_list (parser, - &non_constant_p); - } - else - cp_parser_simulate_error (parser); + bool non_constant_p; + /* Parse the brace-enclosed initializer list. */ + initializer = cp_parser_braced_list (parser, + &non_constant_p); } /* If that worked, we're definitely looking at a compound-literal expression. */ @@ -7492,6 +7523,7 @@ cp_parser_tokens_start_cast_expression (cp_parser *parser) case CPP_CLOSE_SQUARE: case CPP_CLOSE_PAREN: case CPP_CLOSE_BRACE: + case CPP_OPEN_BRACE: case CPP_DOT: case CPP_DOT_STAR: case CPP_DEREF: @@ -7559,7 +7591,7 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p, { tree type = NULL_TREE; tree expr = NULL_TREE; - bool compound_literal_p; + bool cast_expression_p; const char *saved_message; /* There's no way to know yet whether or not this is a cast. @@ -7582,26 +7614,38 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p, will commit to the parse at that point, because we cannot undo the action that is done when creating a new class. So, then we cannot back up and do a postfix-expression. + Another tricky case is the following (c++/29234): + + struct S { void operator () (); }; + + void foo () + { + ( S()() ); + } + + As a type-id we parse the parenthesized S()() as a function + returning a function, groktypename complains and we cannot + back up in this case either. Therefore, we scan ahead to the closing `)', and check to see - if the token after the `)' is a `{'. If so, we are not - looking at a cast-expression. + if the tokens after the `)' can start a cast-expression. Otherwise + we are dealing with an unary-expression, a postfix-expression + or something else. Save tokens so that we can put them back. */ cp_lexer_save_tokens (parser->lexer); - /* Skip tokens until the next token is a closing parenthesis. - If we find the closing `)', and the next token is a `{', then - we are looking at a compound-literal. */ - compound_literal_p + + /* We may be looking at a cast-expression. */ + cast_expression_p = (cp_parser_skip_to_closing_parenthesis (parser, false, false, /*consume_paren=*/true) - && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)); + && cp_parser_tokens_start_cast_expression (parser)); + /* Roll back the tokens we skipped. */ cp_lexer_rollback_tokens (parser->lexer); - /* If we were looking at a compound-literal, simulate an error - so that the call to cp_parser_parse_definitely below will - fail. */ - if (compound_literal_p) + /* If we aren't looking at a cast-expression, simulate an error so + that the call to cp_parser_parse_definitely below will fail. */ + if (!cast_expression_p) cp_parser_simulate_error (parser); else { @@ -7620,8 +7664,7 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p, /* At this point this can only be either a cast or a parenthesized ctor such as `(T ())' that looks like a cast to function returning T. */ - if (!cp_parser_error_occurred (parser) - && cp_parser_tokens_start_cast_expression (parser)) + if (!cp_parser_error_occurred (parser)) { cp_parser_parse_definitely (parser); expr = cp_parser_cast_expression (parser, @@ -9231,7 +9274,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr, case RID_WHILE: case RID_DO: case RID_FOR: - statement = cp_parser_iteration_statement (parser); + statement = cp_parser_iteration_statement (parser, false); break; case RID_BREAK: @@ -9892,7 +9935,7 @@ cp_parser_condition (cp_parser* parser) not included. */ static tree -cp_parser_for (cp_parser *parser) +cp_parser_for (cp_parser *parser, bool ivdep) { tree init, scope, decl; bool is_range_for; @@ -9904,13 +9947,13 @@ cp_parser_for (cp_parser *parser) is_range_for = cp_parser_for_init_statement (parser, &decl); if (is_range_for) - return cp_parser_range_for (parser, scope, init, decl); + return cp_parser_range_for (parser, scope, init, decl, ivdep); else - return cp_parser_c_for (parser, scope, init); + return cp_parser_c_for (parser, scope, init, ivdep); } static tree -cp_parser_c_for (cp_parser *parser, tree scope, tree init) +cp_parser_c_for (cp_parser *parser, tree scope, tree init, bool ivdep) { /* Normal for loop */ tree condition = NULL_TREE; @@ -9925,7 +9968,13 @@ cp_parser_c_for (cp_parser *parser, tree scope, tree init) /* If there's a condition, process it. */ if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)) condition = cp_parser_condition (parser); - finish_for_cond (condition, stmt); + else if (ivdep) + { + cp_parser_error (parser, "missing loop condition in loop with " + "%<GCC ivdep%> pragma"); + condition = error_mark_node; + } + finish_for_cond (condition, stmt, ivdep); /* Look for the `;'. */ cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); @@ -9948,7 +9997,8 @@ cp_parser_c_for (cp_parser *parser, tree scope, tree init) regular FOR_STMT. */ static tree -cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl) +cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl, + bool ivdep) { tree stmt, range_expr; @@ -9967,6 +10017,8 @@ cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl) if (check_for_bare_parameter_packs (range_expr)) range_expr = error_mark_node; stmt = begin_range_for_stmt (scope, init); + if (ivdep) + RANGE_FOR_IVDEP (stmt) = 1; finish_range_for_decl (stmt, range_decl, range_expr); if (!type_dependent_expression_p (range_expr) /* do_auto_deduction doesn't mess with template init-lists. */ @@ -9976,7 +10028,7 @@ cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl) else { stmt = begin_for_stmt (scope, init); - stmt = cp_convert_range_for (stmt, range_decl, range_expr); + stmt = cp_convert_range_for (stmt, range_decl, range_expr, ivdep); } return stmt; } @@ -10067,7 +10119,8 @@ do_range_for_auto_deduction (tree decl, tree range_expr) namespace. */ tree -cp_convert_range_for (tree statement, tree range_decl, tree range_expr) +cp_convert_range_for (tree statement, tree range_decl, tree range_expr, + bool ivdep) { tree begin, end; tree iter_type, begin_expr, end_expr; @@ -10124,7 +10177,7 @@ cp_convert_range_for (tree statement, tree range_decl, tree range_expr) begin, ERROR_MARK, end, ERROR_MARK, NULL, tf_warning_or_error); - finish_for_cond (condition, statement); + finish_for_cond (condition, statement, ivdep); /* The new increment expression. */ expression = finish_unary_op_expr (input_location, @@ -10287,7 +10340,7 @@ cp_parser_range_for_member_function (tree range, tree identifier) Returns the new WHILE_STMT, DO_STMT, FOR_STMT or RANGE_FOR_STMT. */ static tree -cp_parser_iteration_statement (cp_parser* parser) +cp_parser_iteration_statement (cp_parser* parser, bool ivdep) { cp_token *token; enum rid keyword; @@ -10317,7 +10370,7 @@ cp_parser_iteration_statement (cp_parser* parser) cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN); /* Parse the condition. */ condition = cp_parser_condition (parser); - finish_while_stmt_cond (condition, statement); + finish_while_stmt_cond (condition, statement, ivdep); /* Look for the `)'. */ cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); /* Parse the dependent statement. */ @@ -10347,7 +10400,7 @@ cp_parser_iteration_statement (cp_parser* parser) /* Parse the expression. */ expression = cp_parser_expression (parser, /*cast_p=*/false, NULL); /* We're done with the do-statement. */ - finish_do_stmt (expression, statement); + finish_do_stmt (expression, statement, ivdep); /* Look for the `)'. */ cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); /* Look for the `;'. */ @@ -10360,7 +10413,7 @@ cp_parser_iteration_statement (cp_parser* parser) /* Look for the `('. */ cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN); - statement = cp_parser_for (parser); + statement = cp_parser_for (parser, ivdep); /* Look for the `)'. */ cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN); @@ -21426,6 +21479,9 @@ cp_parser_std_attribute (cp_parser *parser) /* C++11 noreturn attribute is equivalent to GNU's. */ if (is_attribute_p ("noreturn", attr_id)) TREE_PURPOSE (TREE_PURPOSE (attribute)) = get_identifier ("gnu"); + /* C++14 deprecated attribute is equivalent to GNU's. */ + else if (cxx_dialect >= cxx1y && is_attribute_p ("deprecated", attr_id)) + TREE_PURPOSE (TREE_PURPOSE (attribute)) = get_identifier ("gnu"); } /* Now parse the optional argument clause of the attribute. */ @@ -22155,6 +22211,7 @@ static bool cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p) { bool constructor_p; + bool outside_class_specifier_p; tree nested_name_specifier; cp_token *next_token; @@ -22187,11 +22244,14 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p) /*check_dependency_p=*/false, /*type_p=*/false, /*is_declaration=*/false)); + + outside_class_specifier_p = (!at_class_scope_p () + || !TYPE_BEING_DEFINED (current_class_type) + || friend_p); + /* Outside of a class-specifier, there must be a nested-name-specifier. */ - if (!nested_name_specifier && - (!at_class_scope_p () || !TYPE_BEING_DEFINED (current_class_type) - || friend_p)) + if (!nested_name_specifier && outside_class_specifier_p) constructor_p = false; else if (nested_name_specifier == error_mark_node) constructor_p = false; @@ -22230,8 +22290,16 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p) /*check_dependency_p=*/false, /*class_head_p=*/false, /*is_declaration=*/false); - /* If there was no class-name, then this is not a constructor. */ - constructor_p = !cp_parser_error_occurred (parser); + /* If there was no class-name, then this is not a constructor. + Otherwise, if we are in a class-specifier and we aren't + handling a friend declaration, check that its type matches + current_class_type (c++/38313). Note: error_mark_node + is left alone for error recovery purposes. */ + constructor_p = (!cp_parser_error_occurred (parser) + && (outside_class_specifier_p + || type_decl == error_mark_node + || same_type_p (current_class_type, + TREE_TYPE (type_decl)))); /* If we're still considering a constructor, we have to see a `(', to begin the parameter-declaration-clause, followed by either a @@ -23199,6 +23267,9 @@ cp_parser_late_parse_one_default_arg (cp_parser *parser, tree decl, && CONSTRUCTOR_IS_DIRECT_INIT (parsed_arg)) flags = LOOKUP_NORMAL; parsed_arg = digest_init_flags (TREE_TYPE (decl), parsed_arg, flags); + if (TREE_CODE (parsed_arg) == TARGET_EXPR) + /* This represents the whole initialization. */ + TARGET_EXPR_DIRECT_INIT_P (parsed_arg) = true; } } @@ -30906,6 +30977,22 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context) "%<#pragma omp sections%> construct"); break; + case PRAGMA_IVDEP: + { + cp_parser_skip_to_pragma_eol (parser, pragma_tok); + cp_token *tok; + tok = cp_lexer_peek_token (the_parser->lexer); + if (tok->type != CPP_KEYWORD + || (tok->keyword != RID_FOR && tok->keyword != RID_WHILE + && tok->keyword != RID_DO)) + { + cp_parser_error (parser, "for, while or do statement expected"); + return false; + } + cp_parser_iteration_statement (parser, true); + return true; + } + default: gcc_assert (id >= PRAGMA_FIRST_EXTERNAL); c_invoke_pragma_handler (id); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index e04bdcc81cb..8c1553feca2 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -3511,7 +3511,8 @@ check_template_shadow (tree decl) name inside a class. We check TPFI to avoid duplicate errors for inline member templates. */ if (decl == olddecl - || TEMPLATE_PARMS_FOR_INLINE (current_template_parms)) + || (DECL_TEMPLATE_PARM_P (decl) + && TEMPLATE_PARMS_FOR_INLINE (current_template_parms))) return true; error ("declaration of %q+#D", decl); @@ -8610,7 +8611,7 @@ apply_late_template_attributes (tree *decl_p, tree attributes, int attr_flags, pass it through tsubst. Attributes like mode, format, cleanup and several target specific attributes expect it unmodified. */ - else if (attribute_takes_identifier_p (TREE_PURPOSE (t))) + else if (attribute_takes_identifier_p (get_attribute_name (t))) { tree chain = tsubst_expr (TREE_CHAIN (TREE_VALUE (t)), args, complain, @@ -13317,7 +13318,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, RECUR (FOR_INIT_STMT (t)); finish_for_init_stmt (stmt); tmp = RECUR (FOR_COND (t)); - finish_for_cond (tmp, stmt); + finish_for_cond (tmp, stmt, false); tmp = RECUR (FOR_EXPR (t)); finish_for_expr (tmp, stmt); RECUR (FOR_BODY (t)); @@ -13332,7 +13333,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, decl = tsubst (decl, args, complain, in_decl); maybe_push_decl (decl); expr = RECUR (RANGE_FOR_EXPR (t)); - stmt = cp_convert_range_for (stmt, decl, expr); + stmt = cp_convert_range_for (stmt, decl, expr, RANGE_FOR_IVDEP (t)); RECUR (RANGE_FOR_BODY (t)); finish_for_stmt (stmt); } @@ -13341,7 +13342,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, case WHILE_STMT: stmt = begin_while_stmt (); tmp = RECUR (WHILE_COND (t)); - finish_while_stmt_cond (tmp, stmt); + finish_while_stmt_cond (tmp, stmt, false); RECUR (WHILE_BODY (t)); finish_while_stmt (stmt); break; @@ -13351,7 +13352,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, RECUR (DO_BODY (t)); finish_do_body (stmt); tmp = RECUR (DO_COND (t)); - finish_do_stmt (tmp, stmt); + finish_do_stmt (tmp, stmt, false); break; case IF_STMT: @@ -18615,15 +18616,10 @@ most_specialized_class (tree type, tree tmpl, tsubst_flags_t complain) if (spec_tmpl == error_mark_node) return error_mark_node; - ++processing_template_decl; - tree parms = DECL_INNERMOST_TEMPLATE_PARMS (spec_tmpl); spec_args = get_class_bindings (tmpl, parms, partial_spec_args, args); - - --processing_template_decl; - if (spec_args) { if (outer_args) @@ -20510,7 +20506,7 @@ type_dependent_expression_p (tree expression) if (!processing_template_decl) return false; - if (expression == error_mark_node) + if (expression == NULL_TREE || expression == error_mark_node) return false; /* An unresolved name is always dependent. */ diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index b30794c183e..2ebc00d243a 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -726,9 +726,15 @@ begin_while_stmt (void) WHILE_STMT. */ void -finish_while_stmt_cond (tree cond, tree while_stmt) +finish_while_stmt_cond (tree cond, tree while_stmt, bool ivdep) { finish_cond (&WHILE_COND (while_stmt), maybe_convert_cond (cond)); + if (ivdep && cond != error_mark_node) + WHILE_COND (while_stmt) = build2 (ANNOTATE_EXPR, + TREE_TYPE (WHILE_COND (while_stmt)), + WHILE_COND (while_stmt), + build_int_cst (integer_type_node, + annot_expr_ivdep_kind)); simplify_loop_decl_cond (&WHILE_COND (while_stmt), WHILE_BODY (while_stmt)); } @@ -771,9 +777,12 @@ finish_do_body (tree do_stmt) COND is as indicated. */ void -finish_do_stmt (tree cond, tree do_stmt) +finish_do_stmt (tree cond, tree do_stmt, bool ivdep) { cond = maybe_convert_cond (cond); + if (ivdep && cond != error_mark_node) + cond = build2 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, + build_int_cst (integer_type_node, annot_expr_ivdep_kind)); DO_COND (do_stmt) = cond; } @@ -876,9 +885,15 @@ finish_for_init_stmt (tree for_stmt) FOR_STMT. */ void -finish_for_cond (tree cond, tree for_stmt) +finish_for_cond (tree cond, tree for_stmt, bool ivdep) { finish_cond (&FOR_COND (for_stmt), maybe_convert_cond (cond)); + if (ivdep && cond != error_mark_node) + FOR_COND (for_stmt) = build2 (ANNOTATE_EXPR, + TREE_TYPE (FOR_COND (for_stmt)), + FOR_COND (for_stmt), + build_int_cst (integer_type_node, + annot_expr_ivdep_kind)); simplify_loop_decl_cond (&FOR_COND (for_stmt), FOR_BODY (for_stmt)); } @@ -2501,6 +2516,7 @@ finish_compound_literal (tree type, tree compound_literal, if ((!at_function_scope_p () || CP_TYPE_CONST_P (type)) && TREE_CODE (type) == ARRAY_TYPE && !TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type) + && !cp_unevaluated_operand && initializer_constant_valid_p (compound_literal, type)) { tree decl = create_temporary_var (type); @@ -2521,6 +2537,10 @@ finish_compound_literal (tree type, tree compound_literal, decl = pushdecl_top_level (decl); DECL_NAME (decl) = make_anon_name (); SET_DECL_ASSEMBLER_NAME (decl, DECL_NAME (decl)); + /* Make sure the destructor is callable. */ + tree clean = cxx_maybe_build_cleanup (decl, complain); + if (clean == error_mark_node) + return error_mark_node; return decl; } else @@ -5168,12 +5188,16 @@ finish_omp_clauses (tree clauses) if (t == NULL_TREE) t = integer_one_node; if (t == error_mark_node) - remove = true; + { + remove = true; + break; + } else if (!type_dependent_expression_p (t) && !INTEGRAL_TYPE_P (TREE_TYPE (t))) { error ("linear step expression must be integral"); remove = true; + break; } else { @@ -5190,7 +5214,10 @@ finish_omp_clauses (tree clauses) MINUS_EXPR, sizetype, t, OMP_CLAUSE_DECL (c)); if (t == error_mark_node) - remove = true; + { + remove = true; + break; + } } } OMP_CLAUSE_LINEAR_STEP (c) = t; @@ -5447,6 +5474,19 @@ finish_omp_clauses (tree clauses) error ("%qE is not a variable in %<aligned%> clause", t); remove = true; } + else if (!type_dependent_expression_p (t) + && TREE_CODE (TREE_TYPE (t)) != POINTER_TYPE + && TREE_CODE (TREE_TYPE (t)) != ARRAY_TYPE + && (TREE_CODE (TREE_TYPE (t)) != REFERENCE_TYPE + || (!POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (t))) + && (TREE_CODE (TREE_TYPE (TREE_TYPE (t))) + != ARRAY_TYPE)))) + { + error_at (OMP_CLAUSE_LOCATION (c), + "%qE in %<aligned%> clause is neither a pointer nor " + "an array nor a reference to pointer or array", t); + remove = true; + } else if (bitmap_bit_p (&aligned_head, DECL_UID (t))) { error ("%qD appears more than once in %<aligned%> clauses", t); @@ -5593,8 +5633,9 @@ finish_omp_clauses (tree clauses) else error ("%qE is not an argument in %<uniform%> clause", t); remove = true; + break; } - break; + goto check_dup_generic; case OMP_CLAUSE_NOWAIT: case OMP_CLAUSE_ORDERED: @@ -7398,8 +7439,7 @@ build_anon_member_initialization (tree member, tree init, to build up the initializer from the outside in so that we can reuse previously built CONSTRUCTORs if this is, say, the second field in an anonymous struct. So we use a vec as a stack. */ - vec<tree> fields; - fields.create (2); + stack_vec<tree, 2> fields; do { fields.safe_push (TREE_OPERAND (member, 1)); @@ -7431,7 +7471,6 @@ build_anon_member_initialization (tree member, tree init, /* Now we're at the innermost field, the one that isn't an anonymous aggregate. Add its initializer to the CONSTRUCTOR and we're done. */ gcc_assert (fields.is_empty()); - fields.release (); CONSTRUCTOR_APPEND_ELT (*vec, field, init); return true; @@ -8269,12 +8308,18 @@ cxx_eval_call_expression (const constexpr_call *old_call, tree t, return t; } - /* Shortcut trivial copy constructor/op=. */ - if (call_expr_nargs (t) == 2 && trivial_fn_p (fun)) + /* Shortcut trivial constructor/op=. */ + if (trivial_fn_p (fun)) { - tree arg = convert_from_reference (get_nth_callarg (t, 1)); - return cxx_eval_constant_expression (old_call, arg, allow_non_constant, - addr, non_constant_p, overflow_p); + if (call_expr_nargs (t) == 2) + { + tree arg = convert_from_reference (get_nth_callarg (t, 1)); + return cxx_eval_constant_expression (old_call, arg, allow_non_constant, + addr, non_constant_p, overflow_p); + } + else if (TREE_CODE (t) == AGGR_INIT_EXPR + && AGGR_INIT_ZERO_FIRST (t)) + return build_zero_init (DECL_CONTEXT (fun), NULL_TREE, false); } /* If in direct recursive call, optimize definition search. */ diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 273131fccae..14b69921a51 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -3983,8 +3983,8 @@ cp_fix_function_decl_p (tree decl) /* Don't fix same_body aliases. Although they don't have their own CFG, they share it with what they alias to. */ - if (!node || !node->symbol.alias - || !vec_safe_length (node->symbol.ref_list.references)) + if (!node || !node->alias + || !vec_safe_length (node->ref_list.references)) return true; } diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 3fc046619bc..cb5f715f650 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -641,12 +641,13 @@ split_nonconstant_init_1 (tree dest, tree init) code = build_stmt (input_location, EXPR_STMT, code); code = maybe_cleanup_point_expr_void (code); add_stmt (code); - if (!TYPE_HAS_TRIVIAL_DESTRUCTOR (inner_type)) + if (type_build_dtor_call (inner_type)) { code = (build_special_member_call (sub, complete_dtor_identifier, NULL, inner_type, LOOKUP_NORMAL, tf_warning_or_error)); - finish_eh_cleanup (code); + if (!TYPE_HAS_TRIVIAL_DESTRUCTOR (inner_type)) + finish_eh_cleanup (code); } num_split_elts++; @@ -775,7 +776,6 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags) { bool const_init; value = fold_non_dependent_expr (value); - value = maybe_constant_init (value); if (DECL_DECLARED_CONSTEXPR_P (decl) || DECL_IN_AGGR_P (decl)) { @@ -786,6 +786,7 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags) else value = cxx_constant_value (value); } + value = maybe_constant_init (value); const_init = (reduced_constant_expression_p (value) || error_operand_p (value)); DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = const_init; @@ -834,7 +835,8 @@ check_narrowing (tree type, tree init) && TREE_CODE (type) == COMPLEX_TYPE) { tree elttype = TREE_TYPE (type); - check_narrowing (elttype, CONSTRUCTOR_ELT (init, 0)->value); + if (CONSTRUCTOR_NELTS (init) > 0) + check_narrowing (elttype, CONSTRUCTOR_ELT (init, 0)->value); if (CONSTRUCTOR_NELTS (init) > 1) check_narrowing (elttype, CONSTRUCTOR_ELT (init, 1)->value); return; diff --git a/gcc/cppbuiltin.c b/gcc/cppbuiltin.c index 86ef5cbd2ca..0c112654cd5 100644 --- a/gcc/cppbuiltin.c +++ b/gcc/cppbuiltin.c @@ -105,6 +105,8 @@ define_builtin_macros_for_compilation_flags (cpp_reader *pfile) cpp_define_formatted (pfile, "__FINITE_MATH_ONLY__=%d", flag_finite_math_only); + if (flag_enable_cilkplus) + cpp_define (pfile, "__cilk=200"); } diff --git a/gcc/data-streamer-in.c b/gcc/data-streamer-in.c index 93fe2ff4c3b..84242486941 100644 --- a/gcc/data-streamer-in.c +++ b/gcc/data-streamer-in.c @@ -24,6 +24,8 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "diagnostic.h" +#include "tree.h" +#include "gimple.h" #include "data-streamer.h" /* Read a string from the string table in DATA_IN using input block diff --git a/gcc/data-streamer-out.c b/gcc/data-streamer-out.c index 247ff636e49..fbbe0db2759 100644 --- a/gcc/data-streamer-out.c +++ b/gcc/data-streamer-out.c @@ -23,6 +23,8 @@ along with GCC; see the file COPYING3. If not see #include "config.h" #include "system.h" #include "coretypes.h" +#include "tree.h" +#include "gimple.h" #include "data-streamer.h" /* Return index used to reference STRING of LEN characters in the string table diff --git a/gcc/data-streamer.c b/gcc/data-streamer.c index cbd1cb9f9dd..675b5093314 100644 --- a/gcc/data-streamer.c +++ b/gcc/data-streamer.c @@ -22,6 +22,8 @@ along with GCC; see the file COPYING3. If not see #include "config.h" #include "system.h" #include "coretypes.h" +#include "tree.h" +#include "gimple.h" #include "data-streamer.h" /* Pack WORK into BP in a variant of uleb format. */ diff --git a/gcc/dbxout.c b/gcc/dbxout.c index e87e6eebd2f..d110a9475f6 100644 --- a/gcc/dbxout.c +++ b/gcc/dbxout.c @@ -2428,7 +2428,7 @@ dbxout_expand_expr (tree expr) return NULL, otherwise stabs might reference an undefined symbol. */ struct varpool_node *node = varpool_get_node (expr); - if (!node || !node->symbol.definition) + if (!node || !node->definition) return NULL; } /* FALLTHRU */ diff --git a/gcc/df-scan.c b/gcc/df-scan.c index f2e8ab27136..aace96d4536 100644 --- a/gcc/df-scan.c +++ b/gcc/df-scan.c @@ -86,10 +86,10 @@ static HARD_REG_SET elim_reg_set; struct df_collection_rec { - vec<df_ref, va_stack> def_vec; - vec<df_ref, va_stack> use_vec; - vec<df_ref, va_stack> eq_use_vec; - vec<df_mw_hardreg_ptr, va_stack> mw_vec; + stack_vec<df_ref, 128> def_vec; + stack_vec<df_ref, 32> use_vec; + stack_vec<df_ref, 32> eq_use_vec; + stack_vec<df_mw_hardreg_ptr, 32> mw_vec; }; static df_ref df_null_ref_rec[1]; @@ -131,7 +131,7 @@ static void df_ref_chain_delete_du_chain (df_ref *); static void df_ref_chain_delete (df_ref *); static void df_refs_add_to_chains (struct df_collection_rec *, - basic_block, rtx); + basic_block, rtx, unsigned int); static bool df_insn_refs_verify (struct df_collection_rec *, basic_block, rtx, bool); static void df_entry_block_defs_collect (struct df_collection_rec *, bitmap); @@ -153,6 +153,14 @@ static void df_insn_info_delete (unsigned int); and epilogue to save and restore registers as needed. */ static bool regs_ever_live[FIRST_PSEUDO_REGISTER]; + +/* Flags used to tell df_refs_add_to_chains() which vectors it should copy. */ +static const unsigned int copy_defs = 0x1; +static const unsigned int copy_uses = 0x2; +static const unsigned int copy_eq_uses = 0x4; +static const unsigned int copy_mw = 0x8; +static const unsigned int copy_all = copy_defs | copy_uses | copy_eq_uses +| copy_mw; /*---------------------------------------------------------------------------- SCANNING DATAFLOW PROBLEM @@ -1268,11 +1276,6 @@ df_insn_rescan (rtx insn) return false; } - vec_stack_alloc (df_ref, collection_rec.def_vec, 128); - vec_stack_alloc (df_ref, collection_rec.use_vec, 32); - vec_stack_alloc (df_ref, collection_rec.eq_use_vec, 32); - vec_stack_alloc (df_mw_hardreg_ptr, collection_rec.mw_vec, 32); - bitmap_clear_bit (&df->insns_to_delete, uid); bitmap_clear_bit (&df->insns_to_rescan, uid); bitmap_clear_bit (&df->insns_to_notes_rescan, uid); @@ -1306,15 +1309,10 @@ df_insn_rescan (rtx insn) fprintf (dump_file, "scanning new insn with uid = %d.\n", uid); } - df_refs_add_to_chains (&collection_rec, bb, insn); + df_refs_add_to_chains (&collection_rec, bb, insn, copy_all); if (!DEBUG_INSN_P (insn)) df_set_bb_dirty (bb); - collection_rec.def_vec.release (); - collection_rec.use_vec.release (); - collection_rec.eq_use_vec.release (); - collection_rec.mw_vec.release (); - return true; } @@ -2221,10 +2219,6 @@ df_notes_rescan (rtx insn) unsigned int num_deleted; unsigned int mw_len; - memset (&collection_rec, 0, sizeof (struct df_collection_rec)); - vec_stack_alloc (df_ref, collection_rec.eq_use_vec, 32); - vec_stack_alloc (df_mw_hardreg_ptr, collection_rec.mw_vec, 32); - num_deleted = df_mw_hardreg_chain_delete_eq_uses (insn_info); df_ref_chain_delete (insn_info->eq_uses); insn_info->eq_uses = NULL; @@ -2287,11 +2281,7 @@ df_notes_rescan (rtx insn) insn_info->mw_hardregs[mw_len] = NULL; } } - /* Get rid of the mw_rec so that df_refs_add_to_chains will - ignore it. */ - collection_rec.mw_vec.release (); - df_refs_add_to_chains (&collection_rec, bb, insn); - collection_rec.eq_use_vec.release (); + df_refs_add_to_chains (&collection_rec, bb, insn, copy_eq_uses); } else df_insn_rescan (insn); @@ -2391,7 +2381,7 @@ df_ref_compare (const void *r1, const void *r2) } static void -df_swap_refs (vec<df_ref, va_stack> *ref_vec, int i, int j) +df_swap_refs (vec<df_ref, va_heap> *ref_vec, int i, int j) { df_ref tmp = (*ref_vec)[i]; (*ref_vec)[i] = (*ref_vec)[j]; @@ -2401,7 +2391,7 @@ df_swap_refs (vec<df_ref, va_stack> *ref_vec, int i, int j) /* Sort and compress a set of refs. */ static void -df_sort_and_compress_refs (vec<df_ref, va_stack> *ref_vec) +df_sort_and_compress_refs (vec<df_ref, va_heap> *ref_vec) { unsigned int count; unsigned int i; @@ -2510,7 +2500,7 @@ df_mw_compare (const void *m1, const void *m2) /* Sort and compress a set of refs. */ static void -df_sort_and_compress_mws (vec<df_mw_hardreg_ptr, va_stack> *mw_vec) +df_sort_and_compress_mws (vec<df_mw_hardreg_ptr, va_heap> *mw_vec) { unsigned int count; struct df_scan_problem_data *problem_data @@ -2621,14 +2611,12 @@ df_install_ref (df_ref this_ref, static df_ref * df_install_refs (basic_block bb, - vec<df_ref, va_stack> old_vec, + const vec<df_ref, va_heap> *old_vec, struct df_reg_info **reg_info, struct df_ref_info *ref_info, bool is_notes) { - unsigned int count; - - count = old_vec.length (); + unsigned int count = old_vec->length (); if (count) { df_ref *new_vec = XNEWVEC (df_ref, count + 1); @@ -2659,7 +2647,7 @@ df_install_refs (basic_block bb, if (add_to_table && df->analyze_subset) add_to_table = bitmap_bit_p (df->blocks_to_analyze, bb->index); - FOR_EACH_VEC_ELT (old_vec, ix, this_ref) + FOR_EACH_VEC_ELT (*old_vec, ix, this_ref) { new_vec[ix] = this_ref; df_install_ref (this_ref, reg_info[DF_REF_REGNO (this_ref)], @@ -2678,16 +2666,14 @@ df_install_refs (basic_block bb, insn. */ static struct df_mw_hardreg ** -df_install_mws (vec<df_mw_hardreg_ptr, va_stack> old_vec) +df_install_mws (const vec<df_mw_hardreg_ptr, va_heap> *old_vec) { - unsigned int count; - - count = old_vec.length (); + unsigned int count = old_vec->length (); if (count) { struct df_mw_hardreg **new_vec = XNEWVEC (struct df_mw_hardreg*, count + 1); - memcpy (new_vec, old_vec.address (), + memcpy (new_vec, old_vec->address (), sizeof (struct df_mw_hardreg*) * count); new_vec[count] = NULL; return new_vec; @@ -2702,7 +2688,7 @@ df_install_mws (vec<df_mw_hardreg_ptr, va_stack> old_vec) static void df_refs_add_to_chains (struct df_collection_rec *collection_rec, - basic_block bb, rtx insn) + basic_block bb, rtx insn, unsigned int flags) { if (insn) { @@ -2710,35 +2696,35 @@ df_refs_add_to_chains (struct df_collection_rec *collection_rec, /* If there is a vector in the collection rec, add it to the insn. A null rec is a signal that the caller will handle the chain specially. */ - if (collection_rec->def_vec.exists ()) + if (flags & copy_defs) { df_scan_free_ref_vec (insn_rec->defs); insn_rec->defs - = df_install_refs (bb, collection_rec->def_vec, + = df_install_refs (bb, &collection_rec->def_vec, df->def_regs, &df->def_info, false); } - if (collection_rec->use_vec.exists ()) + if (flags & copy_uses) { df_scan_free_ref_vec (insn_rec->uses); insn_rec->uses - = df_install_refs (bb, collection_rec->use_vec, + = df_install_refs (bb, &collection_rec->use_vec, df->use_regs, &df->use_info, false); } - if (collection_rec->eq_use_vec.exists ()) + if (flags & copy_eq_uses) { df_scan_free_ref_vec (insn_rec->eq_uses); insn_rec->eq_uses - = df_install_refs (bb, collection_rec->eq_use_vec, + = df_install_refs (bb, &collection_rec->eq_use_vec, df->eq_use_regs, &df->use_info, true); } - if (collection_rec->mw_vec.exists ()) + if (flags & copy_mw) { df_scan_free_mws_vec (insn_rec->mw_hardregs); insn_rec->mw_hardregs - = df_install_mws (collection_rec->mw_vec); + = df_install_mws (&collection_rec->mw_vec); } } else @@ -2747,12 +2733,12 @@ df_refs_add_to_chains (struct df_collection_rec *collection_rec, df_scan_free_ref_vec (bb_info->artificial_defs); bb_info->artificial_defs - = df_install_refs (bb, collection_rec->def_vec, + = df_install_refs (bb, &collection_rec->def_vec, df->def_regs, &df->def_info, false); df_scan_free_ref_vec (bb_info->artificial_uses); bb_info->artificial_uses - = df_install_refs (bb, collection_rec->use_vec, + = df_install_refs (bb, &collection_rec->use_vec, df->use_regs, &df->use_info, false); } @@ -3633,17 +3619,12 @@ df_bb_refs_record (int bb_index, bool scan_insns) basic_block bb = BASIC_BLOCK (bb_index); rtx insn; int luid = 0; - struct df_collection_rec collection_rec; if (!df) return; + df_collection_rec collection_rec; df_grow_bb_info (df_scan); - vec_stack_alloc (df_ref, collection_rec.def_vec, 128); - vec_stack_alloc (df_ref, collection_rec.use_vec, 32); - vec_stack_alloc (df_ref, collection_rec.eq_use_vec, 32); - vec_stack_alloc (df_mw_hardreg_ptr, collection_rec.mw_vec, 32); - if (scan_insns) /* Scan the block an insn at a time from beginning to end. */ FOR_BB_INSNS (bb, insn) @@ -3657,19 +3638,14 @@ df_bb_refs_record (int bb_index, bool scan_insns) /* Record refs within INSN. */ DF_INSN_INFO_LUID (insn_info) = luid++; df_insn_refs_collect (&collection_rec, bb, DF_INSN_INFO_GET (insn)); - df_refs_add_to_chains (&collection_rec, bb, insn); + df_refs_add_to_chains (&collection_rec, bb, insn, copy_all); } DF_INSN_INFO_LUID (insn_info) = luid; } /* Other block level artificial refs */ df_bb_refs_collect (&collection_rec, bb); - df_refs_add_to_chains (&collection_rec, bb, NULL); - - collection_rec.def_vec.release (); - collection_rec.use_vec.release (); - collection_rec.eq_use_vec.release (); - collection_rec.mw_vec.release (); + df_refs_add_to_chains (&collection_rec, bb, NULL, copy_all); /* Now that the block has been processed, set the block as dirty so LR and LIVE will get it processed. */ @@ -3911,13 +3887,11 @@ static void df_record_entry_block_defs (bitmap entry_block_defs) { struct df_collection_rec collection_rec; - memset (&collection_rec, 0, sizeof (struct df_collection_rec)); - vec_stack_alloc (df_ref, collection_rec.def_vec, FIRST_PSEUDO_REGISTER); df_entry_block_defs_collect (&collection_rec, entry_block_defs); /* Process bb_refs chain */ - df_refs_add_to_chains (&collection_rec, BASIC_BLOCK (ENTRY_BLOCK), NULL); - collection_rec.def_vec.release (); + df_refs_add_to_chains (&collection_rec, BASIC_BLOCK (ENTRY_BLOCK), NULL, + copy_defs); } @@ -4084,13 +4058,11 @@ static void df_record_exit_block_uses (bitmap exit_block_uses) { struct df_collection_rec collection_rec; - memset (&collection_rec, 0, sizeof (struct df_collection_rec)); - vec_stack_alloc (df_ref, collection_rec.use_vec, FIRST_PSEUDO_REGISTER); df_exit_block_uses_collect (&collection_rec, exit_block_uses); /* Process bb_refs chain */ - df_refs_add_to_chains (&collection_rec, BASIC_BLOCK (EXIT_BLOCK), NULL); - collection_rec.use_vec.release (); + df_refs_add_to_chains (&collection_rec, BASIC_BLOCK (EXIT_BLOCK), NULL, + copy_uses); } @@ -4331,13 +4303,13 @@ df_reg_chain_verify_unmarked (df_ref refs) /* Verify that NEW_REC and OLD_REC have exactly the same members. */ static bool -df_refs_verify (vec<df_ref, va_stack> new_rec, df_ref *old_rec, +df_refs_verify (const vec<df_ref, va_heap> *new_rec, df_ref *old_rec, bool abort_if_fail) { unsigned int ix; df_ref new_ref; - FOR_EACH_VEC_ELT (new_rec, ix, new_ref) + FOR_EACH_VEC_ELT (*new_rec, ix, new_ref) { if (*old_rec == NULL || !df_ref_equal_p (new_ref, *old_rec)) { @@ -4369,14 +4341,14 @@ df_refs_verify (vec<df_ref, va_stack> new_rec, df_ref *old_rec, /* Verify that NEW_REC and OLD_REC have exactly the same members. */ static bool -df_mws_verify (vec<df_mw_hardreg_ptr, va_stack> new_rec, +df_mws_verify (const vec<df_mw_hardreg_ptr, va_heap> *new_rec, struct df_mw_hardreg **old_rec, bool abort_if_fail) { unsigned int ix; struct df_mw_hardreg *new_reg; - FOR_EACH_VEC_ELT (new_rec, ix, new_reg) + FOR_EACH_VEC_ELT (*new_rec, ix, new_reg) { if (*old_rec == NULL || !df_mw_equal_p (new_reg, *old_rec)) { @@ -4430,13 +4402,13 @@ df_insn_refs_verify (struct df_collection_rec *collection_rec, /* Unfortunately we cannot opt out early if one of these is not right because the marks will not get cleared. */ - ret1 = df_refs_verify (collection_rec->def_vec, DF_INSN_UID_DEFS (uid), + ret1 = df_refs_verify (&collection_rec->def_vec, DF_INSN_UID_DEFS (uid), abort_if_fail); - ret2 = df_refs_verify (collection_rec->use_vec, DF_INSN_UID_USES (uid), + ret2 = df_refs_verify (&collection_rec->use_vec, DF_INSN_UID_USES (uid), abort_if_fail); - ret3 = df_refs_verify (collection_rec->eq_use_vec, DF_INSN_UID_EQ_USES (uid), + ret3 = df_refs_verify (&collection_rec->eq_use_vec, DF_INSN_UID_EQ_USES (uid), abort_if_fail); - ret4 = df_mws_verify (collection_rec->mw_vec, DF_INSN_UID_MWS (uid), + ret4 = df_mws_verify (&collection_rec->mw_vec, DF_INSN_UID_MWS (uid), abort_if_fail); return (ret1 && ret2 && ret3 && ret4); } @@ -4453,12 +4425,6 @@ df_bb_verify (basic_block bb) struct df_scan_bb_info *bb_info = df_scan_get_bb_info (bb->index); struct df_collection_rec collection_rec; - memset (&collection_rec, 0, sizeof (struct df_collection_rec)); - vec_stack_alloc (df_ref, collection_rec.def_vec, 128); - vec_stack_alloc (df_ref, collection_rec.use_vec, 32); - vec_stack_alloc (df_ref, collection_rec.eq_use_vec, 32); - vec_stack_alloc (df_mw_hardreg_ptr, collection_rec.mw_vec, 32); - gcc_assert (bb_info); /* Scan the block, one insn at a time, from beginning to end. */ @@ -4472,8 +4438,8 @@ df_bb_verify (basic_block bb) /* Do the artificial defs and uses. */ df_bb_refs_collect (&collection_rec, bb); - df_refs_verify (collection_rec.def_vec, df_get_artificial_defs (bb->index), true); - df_refs_verify (collection_rec.use_vec, df_get_artificial_uses (bb->index), true); + df_refs_verify (&collection_rec.def_vec, df_get_artificial_defs (bb->index), true); + df_refs_verify (&collection_rec.use_vec, df_get_artificial_uses (bb->index), true); df_free_collection_rec (&collection_rec); return true; diff --git a/gcc/doc/contrib.texi b/gcc/doc/contrib.texi index 9dd2c26287c..32a85634eb8 100644 --- a/gcc/doc/contrib.texi +++ b/gcc/doc/contrib.texi @@ -238,6 +238,10 @@ maintaining @code{complex<>}, sanity checking and disbursement, configuration architecture, libio maintenance, and early math work. @item +Fran@,{c}ois Dumont for his work on libstdc++-v3, especially maintaining and +improving @code{debug-mode} and associative and unordered containers. + +@item Zdenek Dvorak for a new loop unroller and various fixes. @item @@ -838,6 +842,9 @@ Lars Segerlund for work on GNU Fortran. Dodji Seketeli for numerous C++ bug fixes and debug info improvements. @item +Tim Shen for major work on @code{<regex>}. + +@item Joel Sherrill for his direction via the steering committee, RTEMS contributions and RTEMS testing. @@ -873,6 +880,10 @@ Danny Smith for his major efforts on the Mingw (and Cygwin) ports. Randy Smith finished the Sun FPA support. @item +Ed Smith-Rowland for his continuous work on libstdc++-v3, special functions, +@code{<random>}, and various improvements to C++11 features. + +@item Scott Snyder for queue, iterator, istream, and string fixes and libstdc++ testsuite entries. Also for providing the patch to G77 to add rudimentary support for @code{INTEGER*1}, @code{INTEGER*2}, and @@ -995,7 +1006,7 @@ Feng Wang for contributions to GNU Fortran. @item Stephen M. Webb for time and effort on making libstdc++ shadow files work with the tricky Solaris 8+ headers, and for pushing the build-time -header tree. +header tree. Also, for starting and driving the @code{<regex>} effort. @item John Wehle for various improvements for the x86 code generator, diff --git a/gcc/doc/cpp.texi b/gcc/doc/cpp.texi index 7ff04cde765..0ab9361bb42 100644 --- a/gcc/doc/cpp.texi +++ b/gcc/doc/cpp.texi @@ -2389,6 +2389,40 @@ These macros are defined with value 1 if the backend supports the the include file @file{math.h} can define the macros @code{FP_FAST_FMA}, @code{FP_FAST_FMAF}, and @code{FP_FAST_FMAL} for compatibility with the 1999 C standard. + +@item __GCC_IEC_559 +This macro is defined to indicate the intended level of support for +IEEE 754 (IEC 60559) floating-point arithmetic. It expands to a +nonnegative integer value. If 0, it indicates that the combination of +the compiler configuration and the command-line options is not +intended to support IEEE 754 arithmetic for @code{float} and +@code{double} as defined in C99 and C11 Annex F (for example, that the +standard rounding modes and exceptions are not supported, or that +optimizations are enabled that conflict with IEEE 754 semantics). If +1, it indicates that IEEE 754 arithmetic is intended to be supported; +this does not mean that all relevant language features are supported +by GCC. If 2 or more, it additionally indicates support for IEEE +754-2008 (in particular, that the binary encodings for quiet and +signaling NaNs are as specified in IEEE 754-2008). + +This macro does not indicate the default state of command-line options +that control optimizations that C99 and C11 permit to be controlled by +standard pragmas, where those standards do not require a particular +default state. It does not indicate whether optimizations respect +signaling NaN semantics (the macro for that is +@code{__SUPPORT_SNAN__}). It does not indicate support for decimal +floating point or the IEEE 754 binary16 and binary128 types. + +@item __GCC_IEC_559_COMPLEX +This macro is defined to indicate the intended level of support for +IEEE 754 (IEC 60559) floating-point arithmetic for complex numbers, as +defined in C99 and C11 Annex G. It expands to a nonnegative integer +value. If 0, it indicates that the combination of the compiler +configuration and the command-line options is not intended to support +Annex G requirements (for example, because @option{-fcx-limited-range} +was used). If 1 or more, it indicates that it is intended to support +those requirements; this does not mean that all relevant language +features are supported by GCC. @end table @node System-specific Predefined Macros diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 562b676a47b..799ede1ec95 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -82,6 +82,7 @@ extensions, accepted by GCC in C90 mode and in C++. * x86 specific memory model extensions for transactional memory:: x86 memory models. * Object Size Checking:: Built-in functions for limited buffer overflow checking. +* Pointer Bounds Checker builtins:: Built-in functions for Pointer Bounds Checker. * Cilk Plus Builtins:: Built-in functions for the Cilk Plus language extension. * Other Builtins:: Other built-in functions. * Target Builtins:: Built-in functions specific to particular targets. @@ -2137,7 +2138,7 @@ attributes are currently defined for functions on all targets: @code{returns_nonnull}, @code{gnu_inline}, @code{externally_visible}, @code{hot}, @code{cold}, @code{artificial}, @code{no_sanitize_address}, @code{no_address_safety_analysis}, -@code{no_sanitize_undefined}, +@code{no_sanitize_undefined}, @code{bnd_legacy}, @code{error} and @code{warning}. Several other attributes are defined for functions on particular target systems. Other attributes, including @code{section} are @@ -2504,6 +2505,12 @@ on data in the eight-bit data area. Note the eight-bit data area is limited to You must use GAS and GLD from GNU binutils version 2.7 or later for this attribute to work correctly. +@item exception +@cindex exception handler functions +Use this attribute on the NDS32 target to indicate that the specified function +is an exception handler. The compiler will generate corresponding sections +for use in an exception handler. + @item exception_handler @cindex exception handler functions on the Blackfin processor Use this attribute on the Blackfin to indicate that the specified function @@ -2964,6 +2971,32 @@ void __attribute__ ((interrupt, use_shadow_register_set, use_debug_exception_return)) v7 (); @end smallexample +On NDS32 target, this attribute is to indicate that the specified function +is an interrupt handler. The compiler will generate corresponding sections +for use in an interrupt handler. You can use the following attributes +to modify the behavior: +@table @code +@item nested +@cindex @code{nested} attribute +This interrupt service routine is interruptible. +@item not_nested +@cindex @code{not_nested} attribute +This interrupt service routine is not interruptible. +@item nested_ready +@cindex @code{nested_ready} attribute +This interrupt service routine is interruptible after @code{PSW.GIE} +(global interrupt enable) is set. This allows interrupt service routine to +finish some short critical code before enabling interrupts. +@item save_all +@cindex @code{save_all} attribute +The system will help save all registers into stack before entering +interrupt handler. +@item partial_save +@cindex @code{partial_save} attribute +The system will help save caller registers into stack before entering +interrupt handler. +@end table + On RL78, use @code{brk_interrupt} instead of @code{interrupt} for handlers intended to be used with the @code{BRK} opcode (i.e.@: those that must end with @code{RETB} instead of @code{RETI}). @@ -3200,9 +3233,10 @@ and newer. @item naked @cindex function without a prologue/epilogue code -Use this attribute on the ARM, AVR, MCORE, MSP430, RL78, RX and SPU ports to indicate that -the specified function does not need prologue/epilogue sequences generated by -the compiler. It is up to the programmer to provide these sequences. The +Use this attribute on the ARM, AVR, MCORE, MSP430, NDS32, RL78, RX and SPU +ports to indicate that the specified function does not need prologue/epilogue +sequences generated by the compiler. +It is up to the programmer to provide these sequences. The only statements that can be safely included in naked functions are @code{asm} statements that do not have operands. All other statements, including declarations of local variables, @code{if} statements, and so @@ -3548,6 +3582,12 @@ The @code{no_sanitize_undefined} attribute on functions is used to inform the compiler that it should not check for undefined behavior in the function when compiling with the @option{-fsanitize=undefined} option. +@item bnd_legacy +@cindex @code{bnd_legacy} function attribute +The @code{bnd_legacy} attribute on functions is used to inform +compiler that function should not be instrumented when compiled +with @option{-fcheck-pointers} option. + @item regparm (@var{number}) @cindex @code{regparm} attribute @cindex functions that are passed arguments in registers on the 386 @@ -3568,6 +3608,21 @@ safe since the loaders there save EAX, EDX and ECX. (Lazy binding can be disabled with the linker or the loader if desired, to avoid the problem.) +@item reset +@cindex reset handler functions +Use this attribute on the NDS32 target to indicate that the specified function +is a reset handler. The compiler will generate corresponding sections +for use in a reset handler. You can use the following attributes +to provide extra exception handling: +@table @code +@item nmi +@cindex @code{nmi} attribute +Provide a user-defined function to handle NMI exception. +@item warm +@cindex @code{warm} attribute +Provide a user-defined function to handle warm reset exception. +@end table + @item sseregparm @cindex @code{sseregparm} attribute On the Intel 386 with SSE support, the @code{sseregparm} attribute @@ -5320,12 +5375,12 @@ placed in either the @code{.bss_below100} section or the The keyword @code{__attribute__} allows you to specify special attributes of @code{struct} and @code{union} types when you define such types. This keyword is followed by an attribute specification -inside double parentheses. Seven attributes are currently defined for +inside double parentheses. Eight attributes are currently defined for types: @code{aligned}, @code{packed}, @code{transparent_union}, -@code{unused}, @code{deprecated}, @code{visibility}, and -@code{may_alias}. Other attributes are defined for functions -(@pxref{Function Attributes}) and for variables (@pxref{Variable -Attributes}). +@code{unused}, @code{deprecated}, @code{visibility}, @code{may_alias} +and @code{bnd_variable_size}. Other attributes are defined for +functions (@pxref{Function Attributes}) and for variables +(@pxref{Variable Attributes}). You may also specify any one of these attributes with @samp{__} preceding and following its keyword. This allows you to use these @@ -5617,6 +5672,35 @@ and caught in another, the class must have default visibility. Otherwise the two shared objects are unable to use the same typeinfo node and exception handling will break. +@item bnd_variable_size +When applied to a structure field, this attribute tells Pointer +Bounds Checker that the size of this field should not be computed +using static type information. It may be used to mark variable +sized static array fields placed at the end of a structure. + +@smallexample +struct S +@{ + int size; + char data[1]; +@} +S *p = (S *)malloc (sizeof(S) + 100); +p->data[10] = 0; //Bounds violation +@end smallexample + +By using an attribute for a field we may avoid bound violation +we most probably do not want to see: + +@smallexample +struct S +@{ + int size; + char data[1] __attribute__((bnd_variable_size)); +@} +S *p = (S *)malloc (sizeof(S) + 100); +p->data[10] = 0; //OK +@end smallexample + @end table To specify multiple attributes, separate them by commas within the @@ -7752,6 +7836,176 @@ format string @var{fmt}. If the compiler is able to optimize them to @code{fputc} etc.@: functions, it does, otherwise the checking function is called and the @var{flag} argument passed to it. +@node Pointer Bounds Checker builtins +@section Pointer Bounds Checker Built-in Functions +@findex __builtin___bnd_set_ptr_bounds +@findex __builtin___bnd_narrow_ptr_bounds +@findex __builtin___bnd_copy_ptr_bounds +@findex __builtin___bnd_init_ptr_bounds +@findex __builtin___bnd_null_ptr_bounds +@findex __builtin___bnd_store_ptr_bounds +@findex __builtin___bnd_chk_ptr_lbounds +@findex __builtin___bnd_chk_ptr_ubounds +@findex __builtin___bnd_chk_ptr_bounds +@findex __builtin___bnd_get_ptr_lbound +@findex __builtin___bnd_get_ptr_ubound + +GCC provides a set of built-in functions to control Pointer Bounds Checker +instrumentation. Note that all Pointer Bounds Checker builtins are allowed +to use even if you compile with Pointer Bounds Checker off. But functions +behavior may differ in such case. + +@deftypefn {Built-in Function} void * __builtin___bnd_set_ptr_bounds (const void * @var{q}, size_t @var{size}) + +This built-in function returns a new pointer with the value of @var{q}, and +associate it with the bounds [@var{q}, @var{q}+@var{size}-1]. With Pointer +Bounds Checker off built-in function just returns the first argument. + +@smallexample +extern void *__wrap_malloc (size_t n) +@{ + void *p = (void *)__real_malloc (n); + if (!p) return __builtin___bnd_null_ptr_bounds (p); + return __builtin___bnd_set_ptr_bounds (p, n); +@} +@end smallexample + +@end deftypefn + +@deftypefn {Built-in Function} void * __builtin___bnd_narrow_ptr_bounds (const void * @var{p}, const void * @var{q}, size_t @var{size}) + +This built-in function returns a new pointer with the value of @var{p} +and associate it with the narrowed bounds formed by the intersection +of bounds associated with @var{q} and the [@var{p}, @var{p} + @var{size} - 1]. +With Pointer Bounds Checker off built-in function just returns the first +argument. + +@smallexample +void init_objects (object *objs, size_t size) +@{ + size_t i; + /* Initialize objects one-by-one passing pointers with bounds of an object, + not the full array of objects. */ + for (i = 0; i < size; i++) + init_object (__builtin___bnd_narrow_ptr_bounds (objs + i, objs, sizeof(object))); +@} +@end smallexample + +@end deftypefn + +@deftypefn {Built-in Function} void * __builtin___bnd_copy_ptr_bounds (const void * @var{q}, const void * @var{r}) + +This built-in function returns a new pointer with the value of @var{q}, +and associate it with the bounds already associated with pointer @var{r}. +With Pointer Bounds Checker off built-in function just returns the first +argument. + +@smallexample +/* Here is a way to get pointer to object's field but + still with the full object's bounds. */ +int *field_ptr = __builtin___bnd_copy_ptr_bounds (&objptr->int_filed, objptr); +@end smallexample + +@end deftypefn + +@deftypefn {Built-in Function} void * __builtin___bnd_init_ptr_bounds (const void * @var{q}) + +This built-in function returns a new pointer with the value of @var{q}, and +associate it with INIT (allowing full memory access) bounds. With Pointer +Bounds Checker off built-in function just returns the first argument. + +@end deftypefn + +@deftypefn {Built-in Function} void * __builtin___bnd_null_ptr_bounds (const void * @var{q}) + +This built-in function returns a new pointer with the value of @var{q}, and +associate it with NULL (allowing no memory access) bounds. With Pointer +Bounds Checker off built-in function just returns the first argument. + +@end deftypefn + +@deftypefn {Built-in Function} void __builtin___bnd_store_ptr_bounds (const void ** @var{ptr_addr}, const void * @var{ptr_val}) + +This built-in function stores the bounds associated with pointer @var{ptr_val} +and location @var{ptr_addr} into Bounds Table. This can be useful to propagate +bounds from legacy code without touching the associated pointer's memory when +pointers were copied as integers. With Pointer Bounds Checker off built-in +function call is ignored. + +@end deftypefn + +@deftypefn {Built-in Function} void __builtin___bnd_chk_ptr_lbounds (const void * @var{q}) + +This built-in function checks if the pointer @var{q} is within the lower +bound of its associated bounds. With Pointer Bounds Checker off built-in +function call is ignored. + +@smallexample +extern void *__wrap_memset (void *dst, int c, size_t len) +@{ + if (len > 0) + @{ + __builtin___bnd_chk_ptr_lbounds (dst); + __builtin___bnd_chk_ptr_ubounds ((char *)dst + len - 1); + __real_memset (dst, c, len); + @} + return dst; +@} +@end smallexample + +@end deftypefn + +@deftypefn {Built-in Function} void __builtin___bnd_chk_ptr_ubounds (const void * @var{q}) + +This built-in function checks if the pointer @var{q} is within the upper +bound of its associated bounds. With Pointer Bounds Checker off built-in +function call is ignored. + +@end deftypefn + +@deftypefn {Built-in Function} void __builtin___bnd_chk_ptr_bounds (const void * @var{q}, size_t @var{size}) + +This built-in function checks if [@var{q}, @var{q} + @var{size} - 1] is within +the lower and upper bounds associated with @var{q}. With Pointer Bounds Checker +off built-in function call is ignored. + +@smallexample +extern void *__wrap_memcpy (void *dst, const void *src, size_t n) +@{ + if (n > 0) + @{ + __bnd_chk_ptr_bounds (dst, n); + __bnd_chk_ptr_bounds (src, n); + __real_memcpy (dst, src, n); + @} + return dst; +@} +@end smallexample + +@end deftypefn + +@deftypefn {Built-in Function} const void * __builtin___bnd_get_ptr_lbound (const void * @var{q}) + +This built-in function returns the lower bound (which is a pointer) associated +with the pointer @var{q}. This is at least useful for debugging using printf. +With Pointer Bounds Checker off built-in function returns 0. + +@smallexample +void *lb = __builtin___bnd_get_ptr_lbound (q); +void *ub = __builtin___bnd_get_ptr_ubound (q); +printf ("q = %p lb(q) = %p ub(q) = %p", q, lb, ub); +@end smallexample + +@end deftypefn + +@deftypefn {Built-in Function} const void * __builtin___bnd_get_ptr_ubound (const void * @var{q}) + +This built-in function returns the upper bound (which is a pointer) associated +with the pointer @var{q}. With Pointer Bounds Checker off built-in function +returns -1. + +@end deftypefn + @node Other Builtins @section Other Built-in Functions Provided by GCC @cindex built-in functions @@ -8925,6 +9179,7 @@ instructions, but allow the compiler to schedule those calls. * MIPS Loongson Built-in Functions:: * Other MIPS Built-in Functions:: * MSP430 Built-in Functions:: +* NDS32 Built-in Functions:: * picoChip Built-in Functions:: * PowerPC Built-in Functions:: * PowerPC AltiVec/VSX Built-in Functions:: @@ -12378,6 +12633,44 @@ handlers and the changes to the status register will only take affect once the handler returns. @end table +@node NDS32 Built-in Functions +@subsection NDS32 Built-in Functions + +These built-in functions are available for the NDS32 target: + +@deftypefn {Built-in Function} void __builtin_nds32_isync (int *@var{addr}) +Insert an ISYNC instruction into the instruction stream where +@var{addr} is an instruction address for serialization. +@end deftypefn + +@deftypefn {Built-in Function} void __builtin_nds32_isb (void) +Insert an ISB instruction into the instruction stream. +@end deftypefn + +@deftypefn {Built-in Function} int __builtin_nds32_mfsr (int @var{sr}) +Return the content of a system register which is mapped by @var{sr}. +@end deftypefn + +@deftypefn {Built-in Function} int __builtin_nds32_mfusr (int @var{usr}) +Return the content of a user space register which is mapped by @var{usr}. +@end deftypefn + +@deftypefn {Built-in Function} void __builtin_nds32_mtsr (int @var{value}, int @var{sr}) +Move the @var{value} to a system register which is mapped by @var{sr}. +@end deftypefn + +@deftypefn {Built-in Function} void __builtin_nds32_mtusr (int @var{value}, int @var{usr}) +Move the @var{value} to a user space register which is mapped by @var{usr}. +@end deftypefn + +@deftypefn {Built-in Function} void __builtin_nds32_setgie_en (void) +Enable global interrupt. +@end deftypefn + +@deftypefn {Built-in Function} void __builtin_nds32_setgie_dis (void) +Disable global interrupt. +@end deftypefn + @node picoChip Built-in Functions @subsection picoChip Built-in Functions @@ -15473,6 +15766,7 @@ for further explanation. * Visibility Pragmas:: * Push/Pop Macro Pragmas:: * Function Specific Option Pragmas:: +* Loop-Specific Pragmas:: @end menu @node ARM Pragmas @@ -15995,6 +16289,48 @@ The @samp{#pragma GCC reset_options} pragma is not implemented in GCC versions earlier than 4.4. @end table +@node Loop-Specific Pragmas +@subsection Loop-Specific Pragmas + +@table @code +@item #pragma GCC ivdep +@cindex pragma GCC ivdep +@end table + +With this pragma, the programmer asserts that there are no loop-carried +dependencies which would prevent that consecutive iterations of +the following loop can be executed concurrently with SIMD +(single instruction multiple data) instructions. + +For example, the compiler can only unconditionally vectorize the following +loop with the pragma: + +@smallexample +void foo (int n, int *a, int *b, int *c) +@{ + int i, j; +#pragma GCC ivdep + for (i = 0; i < n; ++i) + a[i] = b[i] + c[i]; +@} +@end smallexample + +@noindent +In this example, using the @code{restrict} qualifier had the same +effect. In the following example, that would not be possible. Assume +@math{k < -m} or @math{k >= m}. Only with the pragma, the compiler knows +that it can unconditionally vectorize the following loop: + +@smallexample +void ignore_vec_dep (int *a, int k, int c, int m) +@{ +#pragma GCC ivdep + for (int i = 0; i < m; i++) + a[i] = a[i + k] * c; +@} +@end smallexample + + @node Unnamed Fields @section Unnamed struct/union fields within structs/unions @cindex @code{struct} diff --git a/gcc/doc/generic.texi b/gcc/doc/generic.texi index a78c19d3781..238a9cead89 100644 --- a/gcc/doc/generic.texi +++ b/gcc/doc/generic.texi @@ -1265,6 +1265,7 @@ the byte offset of the field, but should not be used directly; call @tindex SAVE_EXPR @tindex TARGET_EXPR @tindex VA_ARG_EXPR +@tindex ANNOTATE_EXPR @table @code @item NEGATE_EXPR @@ -1678,8 +1679,13 @@ mechanism. It represents expressions like @code{va_arg (ap, type)}. Its @code{TREE_TYPE} yields the tree representation for @code{type} and its sole argument yields the representation for @code{ap}. +@item ANNOTATE_EXPR +This node is used to attach markers to an expression. The first operand +is the annotated expression, the second is an @code{INTEGER_CST} with +a value from @code{enum annot_expr_kind}. @end table + @node Vectors @subsection Vectors @tindex VEC_LSHIFT_EXPR @@ -3146,6 +3152,30 @@ several statements chained together. Used to represent a @code{break} statement. There are no additional fields. +@item CILK_SPAWN_STMT + +Used to represent a spawning function in the Cilk Plus language extension. +This tree has one field that holds the name of the spawning function. +@code{_Cilk_spawn} can be written in C in the following way: + +@smallexample +@code{_Cilk_spawn} <function_name> (<parameters>); +@end smallexample + +Detailed description for usage and functionality of @code{_Cilk_spawn} can be +found at http://www.cilkplus.org + +@item CILK_SYNC_STMT + +This statement is part of the Cilk Plus language extension. It indicates that +the current function cannot continue in parallel with its spawned children. +There are no additional fields. @code{_Cilk_sync} can be written in C in the +following way: + +@smallexample +@code{_Cilk_sync}; +@end smallexample + @item CLEANUP_STMT Used to represent an action that should take place upon exit from the diff --git a/gcc/doc/gty.texi b/gcc/doc/gty.texi index 82e8e4f728f..a64d110a980 100644 --- a/gcc/doc/gty.texi +++ b/gcc/doc/gty.texi @@ -87,6 +87,7 @@ data members. @menu * GTY Options:: What goes inside a @code{GTY(())}. +* Inheritance and GTY:: Adding GTY to a class hierarchy. * User GC:: Adding user-provided GC marking routines. * GGC Roots:: Making global variables GGC roots. * Files:: How the generated files work. @@ -234,6 +235,10 @@ In this example, the value of BINDING_HAS_LEVEL_P when applied to a mechanism will treat the field @code{level} as being present and if 0, will treat the field @code{scope} as being present. +The @code{desc} and @code{tag} options can also be used for inheritance +to denote which subclass an instance is. See @ref{Inheritance and GTY} +for more information. + @findex param_is @findex use_param @item param_is (@var{type}) @@ -470,6 +475,60 @@ fields is completely handled by user-provided routines. See section @ref{User GC} for details on what functions need to be provided. @end table +@node Inheritance and GTY +@section Support for inheritance +gengtype has some support for simple class hierarchies. You can use +this to have gengtype autogenerate marking routines, provided: + +@itemize @bullet +@item +There must be a concrete base class, with a discriminator expression +that can be used to identify which subclass an instance is. +@item +Only single inheritance is used. +@item +None of the classes within the hierarchy are templates. +@end itemize + +If your class hierarchy does not fit in this pattern, you must use +@ref{User GC} instead. + +The base class and its discriminator must be identified using the ``desc'' +option. Each concrete subclass must use the ``tag'' option to identify +which value of the discriminator it corresponds to. + +Every class in the hierarchy must have a @code{GTY(())} marker, as +gengtype will only attempt to parse classes that have such a marker +@footnote{Classes lacking such a marker will not be identified as being +part of the hierarchy, and so the marking routines will not handle them, +leading to a assertion failure within the marking routines due to an +unknown tag value (assuming that assertions are enabled).}. + +@smallexample +class GTY((desc("%h.kind"), tag("0"))) example_base +@{ +public: + int kind; + tree a; +@}; + +class GTY((tag("1")) some_subclass : public example_base +@{ +public: + tree b; +@}; + +class GTY((tag("2")) some_other_subclass : public example_base +@{ +public: + tree c; +@}; +@end smallexample + +The generated marking routines for the above will contain a ``switch'' +on ``kind'', visiting all appropriate fields. For example, if kind is +2, it will cast to ``some_other_subclass'' and visit fields a, b, and c. + @node User GC @section Support for user-provided GC marking routines @cindex user gc diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi index 5cb4d3c3076..fa5d6e5a611 100644 --- a/gcc/doc/install.texi +++ b/gcc/doc/install.texi @@ -1391,7 +1391,7 @@ addition, @samp{libstdc++}'s include files will be installed into @option{--with-gxx-include-dir=@var{dirname}}. Using this option is particularly useful if you intend to use several versions of GCC in parallel. This is currently supported by @samp{libgfortran}, -@samp{libjava}, @samp{libmudflap}, @samp{libstdc++}, and @samp{libobjc}. +@samp{libjava}, @samp{libstdc++}, and @samp{libobjc}. @item --enable-languages=@var{lang1},@var{lang2},@dots{} Specify that only a particular subset of compilers and @@ -1862,6 +1862,11 @@ This option is only supported for the AVR target. It is not supported for RTEMS configurations, which currently use newlib. The option is supported since version 4.7.2 and is the default in 4.8.0 and newer. +@item --with-nds32-lib=@var{library} +Specifies that @var{library} setting is used for building @file{libgcc.a}. +Currently, the valid @var{library} is @samp{newlib} or @samp{mculib}. +This option is only supported for the NDS32 target. + @item --with-build-time-tools=@var{dir} Specifies where to find the set of target tools (assembler, linker, etc.) that will be used while building GCC itself. This option can be useful diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index a8d6dfa5459..e84bca30ab2 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -190,7 +190,7 @@ in the following sections. -frepo -fno-rtti -fstats -ftemplate-backtrace-limit=@var{n} @gol -ftemplate-depth=@var{n} @gol -fno-threadsafe-statics -fuse-cxa-atexit -fno-weak -nostdinc++ @gol --fno-default-inline -fvisibility-inlines-hidden @gol +-fvisibility-inlines-hidden @gol -fvtable-verify=@var{std|preinit|none} @gol -fvtv-counts -fvtv-debug @gol -fvisibility-ms-compat @gol @@ -256,7 +256,6 @@ Objective-C and Objective-C++ Dialects}. -Wlogical-op -Wlong-long @gol -Wmain -Wmaybe-uninitialized -Wmissing-braces -Wmissing-field-initializers @gol -Wmissing-include-dirs @gol --Wno-mudflap @gol -Wno-multichar -Wnonnull -Wno-overflow @gol -Woverlength-strings -Wpacked -Wpacked-bitfield-compat -Wpadded @gol -Wparentheses -Wpedantic-ms-format -Wno-pedantic-ms-format @gol @@ -308,7 +307,7 @@ Objective-C and Objective-C++ Dialects}. -fdump-tree-ch @gol -fdump-tree-ssa@r{[}-@var{n}@r{]} -fdump-tree-pre@r{[}-@var{n}@r{]} @gol -fdump-tree-ccp@r{[}-@var{n}@r{]} -fdump-tree-dce@r{[}-@var{n}@r{]} @gol --fdump-tree-gimple@r{[}-raw@r{]} -fdump-tree-mudflap@r{[}-@var{n}@r{]} @gol +-fdump-tree-gimple@r{[}-raw@r{]} @gol -fdump-tree-dom@r{[}-@var{n}@r{]} @gol -fdump-tree-dse@r{[}-@var{n}@r{]} @gol -fdump-tree-phiprop@r{[}-@var{n}@r{]} @gol @@ -322,7 +321,6 @@ Objective-C and Objective-C++ Dialects}. -fdump-tree-fre@r{[}-@var{n}@r{]} @gol -fdump-tree-vtable-verify @gol -fdump-tree-vrp@r{[}-@var{n}@r{]} @gol --ftree-vectorizer-verbose=@var{n} @gol -fdump-tree-storeccp@r{[}-@var{n}@r{]} @gol -fdump-final-insns=@var{file} @gol -fcompare-debug@r{[}=@var{opts}@r{]} -fcompare-debug-second @gol @@ -384,19 +382,18 @@ Objective-C and Objective-C++ Dialects}. -floop-parallelize-all -flto -flto-compression-level @gol -flto-partition=@var{alg} -flto-report -flto-report-wpa -fmerge-all-constants @gol -fmerge-constants -fmodulo-sched -fmodulo-sched-allow-regmoves @gol --fmove-loop-invariants fmudflap -fmudflapir -fmudflapth -fno-branch-count-reg @gol --fno-default-inline @gol +-fmove-loop-invariants -fno-branch-count-reg @gol -fno-defer-pop -fno-function-cse -fno-guess-branch-probability @gol -fno-inline -fno-math-errno -fno-peephole -fno-peephole2 @gol -fno-sched-interblock -fno-sched-spec -fno-signed-zeros @gol -fno-toplevel-reorder -fno-trapping-math -fno-zero-initialized-in-bss @gol --fomit-frame-pointer -foptimize-register-move -foptimize-sibling-calls @gol +-fomit-frame-pointer -foptimize-sibling-calls @gol -fpartial-inlining -fpeel-loops -fpredictive-commoning @gol -fprefetch-loop-arrays -fprofile-report @gol -fprofile-correction -fprofile-dir=@var{path} -fprofile-generate @gol -fprofile-generate=@var{path} @gol -fprofile-use -fprofile-use=@var{path} -fprofile-values @gol --freciprocal-math -free -fregmove -frename-registers -freorder-blocks @gol +-freciprocal-math -free -frename-registers -freorder-blocks @gol -freorder-blocks-and-partition -freorder-functions @gol -frerun-cse-after-loop -freschedule-modulo-scheduled-loops @gol -frounding-math -fsched2-use-superblocks -fsched-pressure @gol @@ -669,7 +666,7 @@ Objective-C and Objective-C++ Dialects}. -mavx2 -mavx512f -mavx512pf -mavx512er -mavx512cd @gol -maes -mpclmul -mfsgsbase -mrdrnd -mf16c -mfma @gol -msse4a -m3dnow -mpopcnt -mabm -mbmi -mtbm -mfma4 -mxop -mlzcnt @gol --mbmi2 -mfxsr -mxsave -mxsaveopt -mrtm -mlwp -mthreads @gol +-mbmi2 -mfxsr -mxsave -mxsaveopt -mrtm -mlwp -mmpx -mthreads @gol -mno-align-stringops -minline-all-stringops @gol -minline-stringops-dynamically -mstringop-strategy=@var{alg} @gol -mmemcpy-strategy=@var{strategy} -mmemset-strategy=@var{strategy} @@ -825,6 +822,20 @@ Objective-C and Objective-C++ Dialects}. @emph{MSP430 Options} @gccoptlist{-msim -masm-hex -mmcu= -mlarge -msmall -mrelax} +@emph{NDS32 Options} +@gccoptlist{-mbig-endian -mlittle-endian @gol +-mreduced-regs -mfull-regs @gol +-mcmov -mno-cmov @gol +-mperf-ext -mno-perf-ext @gol +-mv3push -mno-v3push @gol +-m16bit -mno-16bit @gol +-mgp-direct -mno-gp-direct @gol +-misr-vector-size=@var{num} @gol +-mcache-block-size=@var{num} @gol +-march=@var{arch} @gol +-mforce-fp-as-gp -mforbid-fp-as-gp @gol +-mex9 -mctor-dtor -mrelax} + @emph{PDP-11 Options} @gccoptlist{-mfpu -msoft-float -mac0 -mno-ac0 -m40 -m45 -m10 @gol -mbcopy -mbcopy-builtin -mint32 -mno-int16 @gol @@ -1826,7 +1837,7 @@ freestanding and hosted environments. Enable handling of OpenMP directives @code{#pragma omp} in C/C++ and @code{!$omp} in Fortran. When @option{-fopenmp} is specified, the compiler generates parallel code according to the OpenMP Application -Program Interface v3.0 @w{@uref{http://www.openmp.org/}}. This option +Program Interface v4.0 @w{@uref{http://www.openmp.org/}}. This option implies @option{-pthread}, and thus is only supported on targets that have support for @option{-pthread}. @@ -2403,13 +2414,6 @@ In addition, these optimization, warning, and code generation options have meanings only for C++ programs: @table @gcctabopt -@item -fno-default-inline -@opindex fno-default-inline -Do not assume @samp{inline} for functions defined inside a class scope. -@xref{Optimize Options,,Options That Control Optimization}. Note that these -functions have linkage like inline functions; they just aren't -inlined by default. - @item -Wabi @r{(C, Objective-C, C++ and Objective-C++ only)} @opindex Wabi @opindex Wno-abi @@ -4999,11 +5003,6 @@ This option is only supported for C and Objective-C@. It is implied by This option is only active when @option{-fstack-protector} is active. It warns about functions that are not protected against stack smashing. -@item -Wno-mudflap -@opindex Wno-mudflap -Suppress warnings about constructs that cannot be instrumented by -@option{-fmudflap}. - @item -Woverlength-strings @opindex Woverlength-strings @opindex Wno-overlength-strings @@ -5087,6 +5086,12 @@ possible. @opindex gpubnames Generate dwarf .debug_pubnames and .debug_pubtypes sections. +@item -ggnu-pubnames +@opindex ggnu-pubnames +Generate .debug_pubnames and .debug_pubtypes sections in a format +suitable for conversion into a GDB@ index. This option is only useful +with a linker that can produce GDB@ index version 7. + @item -gstabs @opindex gstabs Produce debugging information in stabs format (if that is supported), @@ -5830,10 +5835,6 @@ Dump after post-reload optimizations. @opindex fdump-rtl-pro_and_epilogue Dump after generating the function prologues and epilogues. -@item -fdump-rtl-regmove -@opindex fdump-rtl-regmove -Dump after the register move pass. - @item -fdump-rtl-sched1 @itemx -fdump-rtl-sched2 @opindex fdump-rtl-sched1 @@ -6202,11 +6203,6 @@ by appending @file{.store_copyprop} to the source file name. Dump each function after dead code elimination. The file name is made by appending @file{.dce} to the source file name. -@item mudflap -@opindex fdump-tree-mudflap -Dump each function after adding mudflap instrumentation. The file name is -made by appending @file{.mudflap} to the source file name. - @item sra @opindex fdump-tree-sra Dump each function after performing scalar replacement of aggregates. The @@ -6378,24 +6374,6 @@ the first option takes effect and the subsequent options are ignored. Thus only the @file{vec.miss} is produced which cotaints dumps from the vectorizer about missed opportunities. -@item -ftree-vectorizer-verbose=@var{n} -@opindex ftree-vectorizer-verbose -This option is deprecated and is implemented in terms of -@option{-fopt-info}. Please use @option{-fopt-info-@var{kind}} form -instead, where @var{kind} is one of the valid opt-info options. It -prints additional optimization information. For @var{n}=0 no -diagnostic information is reported. If @var{n}=1 the vectorizer -reports each loop that got vectorized, and the total number of loops -that got vectorized. If @var{n}=2 the vectorizer reports locations -which could not be vectorized and the reasons for those. For any -higher verbosity levels all the analysis and transformation -information from the vectorizer is reported. - -Note that the information output by @option{-ftree-vectorizer-verbose} -option is sent to @file{stderr}. If the equivalent form -@option{-fopt-info-@var{options}=@var{filename}} is used then the -output is sent into @var{filename} instead. - @item -frandom-seed=@var{string} @opindex frandom-seed This option provides a seed that GCC uses in place of @@ -6751,7 +6729,6 @@ also turns on the following optimization flags: -foptimize-sibling-calls @gol -fpartial-inlining @gol -fpeephole2 @gol --fregmove @gol -freorder-blocks -freorder-functions @gol -frerun-cse-after-loop @gol -fsched-interblock -fsched-spec @gol @@ -6822,14 +6799,6 @@ can use the following flags in the rare cases when ``fine-tuning'' of optimizations to be performed is desired. @table @gcctabopt -@item -fno-default-inline -@opindex fno-default-inline -Do not make member functions inline by default merely because they are -defined inside the class scope (C++ only). Otherwise, when you specify -@w{@option{-O}}, member functions defined inside class scope are compiled -inline by default; i.e., you don't need to add @samp{inline} in front of -the member function name. - @item -fno-defer-pop @opindex fno-defer-pop Always pop the arguments to each function call as soon as that function @@ -7081,32 +7050,6 @@ assumptions based on that. The default is @option{-fzero-initialized-in-bss}. -@item -fmudflap -fmudflapth -fmudflapir -@opindex fmudflap -@opindex fmudflapth -@opindex fmudflapir -@cindex bounds checking -@cindex mudflap -For front-ends that support it (C and C++), instrument all risky -pointer/array dereferencing operations, some standard library -string/heap functions, and some other associated constructs with -range/validity tests. Modules so instrumented should be immune to -buffer overflows, invalid heap use, and some other classes of C/C++ -programming errors. The instrumentation relies on a separate runtime -library (@file{libmudflap}), which is linked into a program if -@option{-fmudflap} is given at link time. Run-time behavior of the -instrumented program is controlled by the @env{MUDFLAP_OPTIONS} -environment variable. See @code{env MUDFLAP_OPTIONS=-help a.out} -for its options. - -Use @option{-fmudflapth} instead of @option{-fmudflap} to compile and to -link if your program is multi-threaded. Use @option{-fmudflapir}, in -addition to @option{-fmudflap} or @option{-fmudflapth}, if -instrumentation should ignore pointer reads. This produces less -instrumentation (and therefore faster execution) and still provides -some protection against outright memory corrupting writes, but allows -erroneously read data to propagate within a program. - @item -fthread-jumps @opindex fthread-jumps Perform optimizations that check to see if a jump branches to a @@ -7309,20 +7252,6 @@ registers after writing to their lower 32-bit half. Enabled for x86 at levels @option{-O2}, @option{-O3}. -@item -foptimize-register-move -@itemx -fregmove -@opindex foptimize-register-move -@opindex fregmove -Attempt to reassign register numbers in move instructions and as -operands of other simple instructions in order to maximize the amount of -register tying. This is especially helpful on machines with two-operand -instructions. - -Note @option{-fregmove} and @option{-foptimize-register-move} are the same -optimization. - -Enabled at levels @option{-O2}, @option{-O3}, @option{-Os}. - @item -fira-algorithm=@var{algorithm} Use the specified coloring algorithm for the integrated register allocator. The @var{algorithm} argument can be @samp{priority}, which @@ -8364,7 +8293,7 @@ statements. Output them in the same order that they appear in the input file. When this option is used, unreferenced static variables are not removed. This option is intended to support existing code that relies on a particular ordering. For new code, it is better to -use attributes. +use attributes when possible. Enabled at level @option{-O0}. When disabled explicitly, it also implies @option{-fno-section-anchors}, which is otherwise enabled at @option{-O0} on some @@ -10367,7 +10296,7 @@ separator character at the end of the path. @option{-B} prefixes that effectively specify directory names also apply to libraries in the linker, because the compiler translates these options into @option{-L} options for the linker. They also apply to -includes files in the preprocessor, because the compiler translates these +include files in the preprocessor, because the compiler translates these options into @option{-isystem} options for the preprocessor. In this case, the compiler appends @samp{include} to the prefix. @@ -11076,6 +11005,7 @@ platform. * MN10300 Options:: * Moxie Options:: * MSP430 Options:: +* NDS32 Options:: * PDP-11 Options:: * picoChip Options:: * PowerPC Options:: @@ -15002,6 +14932,8 @@ preferred alignment to @option{-mpreferred-stack-boundary=2}. @itemx -mrtm @itemx -mtbm @itemx -mno-tbm +@itemx -mmpx +@itemx -mno-mpx @opindex mmmx @opindex mno-mmx @opindex msse @@ -15011,7 +14943,7 @@ preferred alignment to @option{-mpreferred-stack-boundary=2}. These switches enable or disable the use of instructions in the MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, AVX, AVX2, AVX512F, AVX512PF, AVX512ER, AVX512CD, AES, PCLMUL, FSGSBASE, RDRND, F16C, FMA, SSE4A, FMA4, XOP, LWP, ABM, BMI, BMI2, -FXSR, XSAVE, XSAVEOPT, LZCNT, RTM or 3DNow!@: +FXSR, XSAVE, XSAVEOPT, LZCNT, RTM, MPX or 3DNow!@: extended instruction sets. These extensions are also available as built-in functions: see @ref{X86 Built-in Functions}, for details of the functions enabled and @@ -17875,6 +17807,108 @@ the final link. @end table +@node NDS32 Options +@subsection NDS32 Options +@cindex NDS32 Options + +These options are defined for NDS32 implementations: + +@table @gcctabopt + +@item -mbig-endian +@opindex mbig-endian +Generate code in big-endian mode. + +@item -mlittle-endian +@opindex mlittle-endian +Generate code in little-endian mode. + +@item -mreduced-regs +@opindex mreduced-regs +Use reduced-set registers for register allocation. + +@item -mfull-regs +@opindex mfull-regs +Use full-set registers for register allocation. + +@item -mcmov +@opindex mcmov +Generate conditional move instructions. + +@item -mno-cmov +@opindex mno-cmov +Do not generate conditional move instructions. + +@item -mperf-ext +@opindex mperf-ext +Generate performance extension instructions. + +@item -mno-perf-ext +@opindex mno-perf-ext +Do not generate performance extension instructions. + +@item -mv3push +@opindex mv3push +Generate v3 push25/pop25 instructions. + +@item -mno-v3push +@opindex mno-v3push +Do not generate v3 push25/pop25 instructions. + +@item -m16-bit +@opindex m16-bit +Generate 16-bit instructions. + +@item -mno-16-bit +@opindex mno-16-bit +Do not generate 16-bit instructions. + +@item -mgp-direct +@opindex mgp-direct +Generate GP base instructions directly. + +@item -mno-gp-direct +@opindex mno-gp-direct +Do no generate GP base instructions directly. + +@item -misr-vector-size=@var{num} +@opindex misr-vector-size +Specify the size of each interrupt vector, which must be 4 or 16. + +@item -mcache-block-size=@var{num} +@opindex mcache-block-size +Specify the size of each cache block, +which must be a power of 2 between 4 and 512. + +@item -march=@var{arch} +@opindex march +Specify the name of the target architecture. + +@item -mforce-fp-as-gp +@opindex mforce-fp-as-gp +Prevent $fp being allocated during register allocation so that compiler +is able to force performing fp-as-gp optimization. + +@item -mforbid-fp-as-gp +@opindex mforbid-fp-as-gp +Forbid using $fp to access static and global variables. +This option strictly forbids fp-as-gp optimization +regardless of @option{-mforce-fp-as-gp}. + +@item -mex9 +@opindex mex9 +Use special directives to guide linker doing ex9 optimization. + +@item -mctor-dtor +@opindex mctor-dtor +Enable constructor/destructor feature. + +@item -mrelax +@opindex mrelax +Guide linker to relax instructions. + +@end table + @node PDP-11 Options @subsection PDP-11 Options @cindex PDP-11 Options diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index 2a5a2e12dda..ac10a0ad03c 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -3152,6 +3152,87 @@ Memory reference, stack only. @end table +@item NDS32---@file{config/nds32/constraints.md} +@table @code +@item w +LOW register class $r0 to $r7 constraint for V3/V3M ISA. +@item l +LOW register class $r0 to $r7. +@item d +MIDDLE register class $r0 to $r11, $r16 to $r19. +@item h +HIGH register class $r12 to $r14, $r20 to $r31. +@item t +Temporary assist register $ta (i.e.@: $r15). +@item k +Stack register $sp. +@item Iu03 +Unsigned immediate 3-bit value. +@item In03 +Negative immediate 3-bit value in the range of @minus{}7--0. +@item Iu04 +Unsigned immediate 4-bit value. +@item Is05 +Signed immediate 5-bit value. +@item Iu05 +Unsigned immediate 5-bit value. +@item In05 +Negative immediate 5-bit value in the range of @minus{}31--0. +@item Ip05 +Unsigned immediate 5-bit value for movpi45 instruction with range 16--47. +@item Iu06 +Unsigned immediate 6-bit value constraint for addri36.sp instruction. +@item Iu08 +Unsigned immediate 8-bit value. +@item Iu09 +Unsigned immediate 9-bit value. +@item Is10 +Signed immediate 10-bit value. +@item Is11 +Signed immediate 11-bit value. +@item Is15 +Signed immediate 15-bit value. +@item Iu15 +Unsigned immediate 15-bit value. +@item Ic15 +A constant which is not in the range of imm15u but ok for bclr instruction. +@item Ie15 +A constant which is not in the range of imm15u but ok for bset instruction. +@item It15 +A constant which is not in the range of imm15u but ok for btgl instruction. +@item Ii15 +A constant whose compliment value is in the range of imm15u +and ok for bitci instruction. +@item Is16 +Signed immediate 16-bit value. +@item Is17 +Signed immediate 17-bit value. +@item Is19 +Signed immediate 19-bit value. +@item Is20 +Signed immediate 20-bit value. +@item Ihig +The immediate value that can be simply set high 20-bit. +@item Izeb +The immediate value 0xff. +@item Izeh +The immediate value 0xffff. +@item Ixls +The immediate value 0x01. +@item Ix11 +The immediate value 0x7ff. +@item Ibms +The immediate value with power of 2. +@item Ifex +The immediate value with power of 2 minus 1. +@item U33 +Memory constraint for 333 format. +@item U45 +Memory constraint for 45 format. +@item U37 +Memory constraint for 37 format. +@end table + @item PDP-11---@file{config/pdp11/constraints.md} @table @code @item a diff --git a/gcc/doc/passes.texi b/gcc/doc/passes.texi index 045f964a939..3ed9a4fc204 100644 --- a/gcc/doc/passes.texi +++ b/gcc/doc/passes.texi @@ -124,13 +124,45 @@ true, then we expand them using either @code{expand_array_notation_exprs} or inside conditions, they are transformed using the function @code{fix_conditional_array_notations}. The C language-specific routines are located in @file{c/c-array-notation.c} and the equivalent C++ routines are in -file @file{cp/cp-array-notation.c}. Common routines such as functions to -initialize builtin functions are stored in @file{array-notation-common.c}. +the file @file{cp/cp-array-notation.c}. Common routines such as functions to +initialize built-in functions are stored in @file{array-notation-common.c}. + +@item Cilk keywords: +@itemize @bullet +@item @code{_Cilk_spawn}: +The @code{_Cilk_spawn} keyword is parsed and the function it contains is marked +as a spawning function. The spawning function is called the spawner. At +the end of the parsing phase, appropriate built-in functions are +added to the spawner that are defined in the Cilk runtime. The appropriate +locations of these functions, and the internal structures are detailed in +@code{cilk_init_builtins} in the file @file{cilk-common.c}. The pointers to +Cilk functions and fields of internal structures are described +in @file{cilk.h}. The built-in functions are described in +@file{cilk-builtins.def}. + +During gimplification, a new "spawn-helper" function is created. +The spawned function is replaced with a spawn helper function in the spawner. +The spawned function-call is moved into the spawn helper. The main function +that does these transformations is @code{gimplify_cilk_spawn} in +@file{c-family/cilk.c}. In the spawn-helper, the gimplification function +@code{gimplify_call_expr}, inserts a function call @code{__cilkrts_detach}. +This function is expanded by @code{builtin_expand_cilk_detach} located in +@file{c-family/cilk.c}. + +@item @code{_Cilk_sync}: +@code{_Cilk_sync} is parsed like a keyword. During gimplification, +the function @code{gimplify_cilk_sync} in @file{c-family/cilk.c}, will replace +this keyword with a set of functions that are stored in the Cilk runtime. +One of the internal functions inserted during gimplification, +@code{__cilkrts_pop_frame} must be expanded by the compiler and is +done by @code{builtin_expand_cilk_pop_frame} in @file{cilk-common.c}. + +@end itemize @end itemize -Detailed information about Cilk Plus and language specification is provided in -@w{@uref{http://www.cilkplus.org/}}. It is worth mentioning that the current -implementation follows ABI 0.9. +Documentation about Cilk Plus and language specification is provided under the +"Learn" section in @w{@uref{http://www.cilkplus.org/}}. It is worth mentioning +that the current implementation follows ABI 1.1. @node Gimplification pass @section Gimplification pass @@ -225,20 +257,6 @@ stuff quickly rather than wait until later when it's more work to get rid of it. This pass is located in @file{tree-cfg.c} and described by @code{pass_remove_useless_stmts}. -@item Mudflap declaration registration - -If mudflap (@pxref{Optimize Options,,-fmudflap -fmudflapth --fmudflapir,gcc,Using the GNU Compiler Collection (GCC)}) is -enabled, we generate code to register some variable declarations with -the mudflap runtime. Specifically, the runtime tracks the lifetimes of -those variable declarations that have their addresses taken, or whose -bounds are unknown at compile time (@code{extern}). This pass generates -new exception handling constructs (@code{try}/@code{finally}), and so -must run before those are lowered. In addition, the pass enqueues -declarations of static variables whose lifetimes extend to the entire -program. The pass is located in @file{tree-mudflap.c} and is described -by @code{pass_mudflap_1}. - @item OpenMP lowering If OpenMP generation (@option{-fopenmp}) is enabled, this pass lowers @@ -576,18 +594,6 @@ run last so that we have as much time as possible to prove that the statement is not reachable. It is located in @file{tree-cfg.c} and is described by @code{pass_warn_function_return}. -@item Mudflap statement annotation - -If mudflap is enabled, we rewrite some memory accesses with code to -validate that the memory access is correct. In particular, expressions -involving pointer dereferences (@code{INDIRECT_REF}, @code{ARRAY_REF}, -etc.) are replaced by code that checks the selected address range -against the mudflap runtime's database of valid regions. This check -includes an inline lookup into a direct-mapped cache, based on -shift/mask operations of the pointer value, with a fallback function -call into the runtime. The pass is located in @file{tree-mudflap.c} and -is described by @code{pass_mudflap_2}. - @item Leave static single assignment form This pass rewrites the function such that it is in normal form. At @@ -817,14 +823,6 @@ RTL expressions for the instructions by substitution, simplifies the result using algebra, and then attempts to match the result against the machine description. The code is located in @file{combine.c}. -@item Register movement - -This pass looks for cases where matching constraints would force an -instruction to need a reload, and this reload would be a -register-to-register move. It then attempts to change the registers -used by the instruction to avoid the move instruction. The code is -located in @file{regmove.c}. - @item Mode switching optimization This pass looks for instructions that require the processor to be in a @@ -863,11 +861,6 @@ them on the stack. This is done in several subpasses: @itemize @bullet @item -Register move optimizations. This pass makes some simple RTL code -transformations which improve the subsequent register allocation. The -source file is @file{regmove.c}. - -@item The integrated register allocator (@acronym{IRA}). It is called integrated because coalescing, register live range splitting, and hard register preferencing are done on-the-fly during coloring. It also @@ -968,10 +961,7 @@ This pass outputs the assembler code for the function. The source files are @file{final.c} plus @file{insn-output.c}; the latter is generated automatically from the machine description by the tool @file{genoutput}. The header file @file{conditions.h} is used for communication between -these files. If mudflap is enabled, the queue of deferred declarations -and any addressed constants (e.g., string literals) is processed by -@code{mudflap_finish_file} into a synthetic constructor function -containing calls into the mudflap runtime. +these files. @item Debugging information output diff --git a/gcc/doc/rtl.texi b/gcc/doc/rtl.texi index 03732f1a2d4..8dc531c35d2 100644 --- a/gcc/doc/rtl.texi +++ b/gcc/doc/rtl.texi @@ -1295,6 +1295,12 @@ These modes stand for a complex number represented as a pair of integer values. The integer values are in @code{QImode}, @code{HImode}, @code{SImode}, @code{DImode}, @code{TImode}, and @code{OImode}, respectively. + +@findex BND32mode +@findex BND64mode +@item BND32mode BND64mode +These modes stand for bounds for pointer of 32 and 64 bit size respectively. +Mode size is double pointer mode size. @end table The machine description defines @code{Pmode} as a C macro which expands @@ -1382,6 +1388,12 @@ any @code{CC_MODE} modes listed in the @file{@var{machine}-modes.def}. @xref{Jump Patterns}, also see @ref{Condition Code}. +@findex MODE_POINTER_BOUNDS +@item MODE_POINTER_BOUNDS +Pointer bounds modes. Used to represent values of pointer bounds type. +Operations in these modes may be executed as NOPs depending on hardware +features and environment setup. + @findex MODE_RANDOM @item MODE_RANDOM This is a catchall mode class for modes which don't fit into the above diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi index 90bd0bdf230..1a709168458 100644 --- a/gcc/doc/sourcebuild.texi +++ b/gcc/doc/sourcebuild.texi @@ -103,10 +103,6 @@ The runtime support library for transactional memory. @item libjava The Java runtime library. -@item libmudflap -The @code{libmudflap} library, used for instrumenting pointer and array -dereferencing operations. - @item libobjc The Objective-C and Objective-C++ runtime library. diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index ae99c12ecad..79111346a03 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -768,6 +768,10 @@ Define this macro to 1 if your target needs this facility. The default is 0. @end defmac +@deftypefn {Target Hook} bool TARGET_FLOAT_EXCEPTIONS_ROUNDING_SUPPORTED_P (void) +Returns true if the target supports IEEE 754 floating-point exceptions and rounding modes, false otherwise. This is intended to relate to the @code{float} and @code{double} types, but not necessarily @code{long double}. By default, returns true if the @code{adddf3} instruction pattern is available and false otherwise, on the assumption that hardware floating point supports exceptions and rounding modes but software floating point does not. +@end deftypefn + @node Per-Function Data @section Defining data structures for per-function information. @cindex per-function data @@ -4334,6 +4338,13 @@ This hook returns the va_list type of the calling convention specified by The default version of this hook returns @code{va_list_type_node}. @end deftypefn +@deftypefn {Target Hook} tree TARGET_FN_ABI_VA_LIST_BOUNDS_SIZE (tree @var{fndecl}) +This hook returns size for @code{va_list} object in function specified +by @var{fndecl}. This hook is used by Pointer Bounds Checker to build bounds +for @code{va_list} object. Return @code{integer_zero_node} if no bounds +should be used (e.g. @code{va_list} is a scalar pointer to the stack). +@end deftypefn + @deftypefn {Target Hook} tree TARGET_CANONICAL_VA_LIST_TYPE (tree @var{type}) This hook returns the va_list type of the calling convention specified by the type of @var{type}. If @var{type} is not a valid va_list type, it returns @@ -5151,6 +5162,26 @@ defined, then define this hook to return @code{true} if Otherwise, you should not define this hook. @end deftypefn +@deftypefn {Target Hook} rtx TARGET_LOAD_BOUNDS_FOR_ARG (rtx @var{slot}, rtx @var{arg}, rtx @var{slot_no}) +This hook is used by expand pass to emit insn to load bounds of +@var{arg} passed in @var{slot}. Expand pass uses this hook in case +bounds of @var{arg} are not passed in register. If @var{slot} is a +memory, then bounds are loaded as for regular pointer loaded from +memory. If @var{slot} is not a memory then @var{slot_no} is an integer +constant holding number of the target dependent special slot which +should be used to obtain bounds. Hook returns RTX holding loaded bounds. +@end deftypefn + +@deftypefn {Target Hook} void TARGET_STORE_BOUNDS_FOR_ARG (rtx @var{arg}, rtx @var{slot}, rtx @var{bounds}, rtx @var{slot_no}) +This hook is used by expand pass to emit insns to store @var{bounds} of +@var{arg} passed in @var{slot}. Expand pass uses this hook in case +@var{bounds} of @var{arg} are not passed in register. If @var{slot} is a +memory, then @var{bounds} are stored as for regular pointer stored in +memory. If @var{slot} is not a memory then @var{slot_no} is an integer +constant holding number of the target dependent special slot which +should be used to store @var{bounds}. +@end deftypefn + @node Trampolines @section Trampolines for Nested Functions @cindex trampolines for nested functions @@ -10901,6 +10932,96 @@ ignored. This function should return the result of the call to the built-in function. @end deftypefn +@deftypefn {Target Hook} tree TARGET_BUILTIN_CHKP_FUNCTION (unsigned @var{fcode}) +This hook allows target to redefine built-in functions used by +Pointer Bounds Checker for code instrumentation. Hook should return +fndecl of function implementing generic builtin whose code is +passed in @var{fcode}. Currently following built-in functions are +obtained using this hook: +@deftypefn {Built-in Function} bnd __chkp_bndmk (const void *@var{lb}, size_t @var{size}) +Function code - BUILT_IN_CHKP_BNDMK. This built-in function is used +by Pointer Bounds Checker to create bound values. @var{lb} holds low +bound of the resulting bounds. @var{size} holds size of created bounds. +@end deftypefn + +@deftypefn {Built-in Function} void __chkp_bndstx (const void **@var{loc}, const void *@var{ptr}, bnd @var{b}) +Function code - @code{BUILT_IN_CHKP_BNDSTX}. This built-in function is used +by Pointer Bounds Checker to store bounds @var{b} for pointer @var{ptr} +stored by address @var{loc}. +@end deftypefn + +@deftypefn {Built-in Function} bnd __chkp_bndldx (const void **@var{loc}, const void *@var{ptr}) +Function code - @code{BUILT_IN_CHKP_BNDLDX}. This built-in function is used +by Pointer Bounds Checker to get bounds of pointer @var{ptr} loaded by +address @var{loc}. +@end deftypefn + +@deftypefn {Built-in Function} void __chkp_bndcl (bnd @var{b}, const void *@var{ptr}) +Function code - @code{BUILT_IN_CHKP_BNDCL}. This built-in function is used +by Pointer Bounds Checker to perform check for pointer @var{ptr} against +lower bound of bounds @var{b}. +@end deftypefn + +@deftypefn {Built-in Function} void __chkp_bndcu (bnd @var{b}, const void *@var{ptr}) +Function code - @code{BUILT_IN_CHKP_BNDCU}. This built-in function is used +by Pointer Bounds Checker to perform check for pointer @var{ptr} against +upper bound of bounds @var{b}. +@end deftypefn + +@deftypefn {Built-in Function} bnd __chkp_bndret (void *@var{ptr}) +Function code - @code{BUILT_IN_CHKP_BNDRET}. This built-in function is used +by Pointer Bounds Checker to obtain bounds returned by call statement. +@var{ptr} passed to buil-in is @code{SSA_NAME} returned by call. +@end deftypefn + +@deftypefn {Built-in Function} bnd __chkp_arg_bnd (void *@var{arg}) +Function code - @code{BUILT_IN_CHKP_ARG_BND}. This built-in function is +used by Pointer Bounds Checker to obtain bounds passed for input argument. +@var{arg} is default @code{SSA_NAME} of the @code{PARM_DECL} whose +bounds we want to obtain. +@end deftypefn + +@deftypefn {Built-in Function} bnd __chkp_intersect (bnd @var{b1}, bnd @var{b2}) +Function code - @code{BUILT_IN_CHKP_INTERSECT}. This built-in function +returns intersection of bounds @var{b1} and @var{b2}. +@end deftypefn + +@deftypefn {Built-in Function} bnd __chkp_narrow (const void *@var{ptr}, bnd @var{b}, size_t @var{s}) +Function code - @code{BUILT_IN_CHKP_NARROW}. This built-in function +returns intersection of bounds @var{b} and +[@var{ptr}, @var{ptr} + @var{s} - @code{1}]. +@end deftypefn + +@deftypefn {Built-in Function} void *__chkp_set_bounds (const void *@var{ptr}, size_t @var{s}) +Function code - @code{BUILT_IN_CHKP_SET_PTR_BOUNDS}. This built-in function +returns @var{ptr} with bounds [@var{ptr}, @var{ptr} + @var{s} - @code{1}]. +@end deftypefn + +@deftypefn {Built-in Function} size_t __chkp_sizeof (const void *@var{ptr}) +Function code - @code{BUILT_IN_CHKP_SIZEOF}. This built-in function +returns size of object referenced by @var{ptr}. @var{ptr} is always +@code{ADDR_EXPR} of @code{VAR_DECL}. This built-in is used by +Pointer Boudns Checker when bounds of object cannot be computed statically +(e.g. object has incomplete type). +@end deftypefn + +@deftypefn {Built-in Function} const void *__chkp_extract_lower (bnd @var{b}) +Function code - @code{BUILT_IN_CHKP_EXTRACT_LOWER}. This built-in function +returns lower bound of bounds @var{b}. +@end deftypefn + +@deftypefn {Built-in Function} const void *__chkp_extract_upper (bnd @var{b}) +Function code - @code{BUILT_IN_CHKP_EXTRACT_UPPER}. This built-in function +returns upper bound of bounds @var{b}. +@end deftypefn +@end deftypefn +@deftypefn {Target Hook} tree TARGET_CHKP_BOUND_TYPE (void) +Return type to be used for bounds +@end deftypefn +@deftypefn {Target Hook} {enum machine_mode} TARGET_CHKP_BOUND_MODE (void) +Return mode to be used for bounds. +@end deftypefn + @deftypefn {Target Hook} tree TARGET_RESOLVE_OVERLOADED_BUILTIN (unsigned int @var{loc}, tree @var{fndecl}, void *@var{arglist}) Select a replacement for a machine specific built-in function that was set up by @samp{TARGET_INIT_BUILTINS}. This is done diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index 368afd6b1e7..78a4e39382c 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -744,6 +744,8 @@ Define this macro to 1 if your target needs this facility. The default is 0. @end defmac +@hook TARGET_FLOAT_EXCEPTIONS_ROUNDING_SUPPORTED_P + @node Per-Function Data @section Defining data structures for per-function information. @cindex per-function data @@ -3694,6 +3696,8 @@ stack. @hook TARGET_FN_ABI_VA_LIST +@hook TARGET_FN_ABI_VA_LIST_BOUNDS_SIZE + @hook TARGET_CANONICAL_VA_LIST_TYPE @hook TARGET_GIMPLIFY_VA_ARG_EXPR @@ -4064,6 +4068,10 @@ These machine description macros help implement varargs: @hook TARGET_PRETEND_OUTGOING_VARARGS_NAMED +@hook TARGET_LOAD_BOUNDS_FOR_ARG + +@hook TARGET_STORE_BOUNDS_FOR_ARG + @node Trampolines @section Trampolines for Nested Functions @cindex trampolines for nested functions @@ -8178,6 +8186,10 @@ to by @var{ce_info}. @hook TARGET_EXPAND_BUILTIN +@hook TARGET_BUILTIN_CHKP_FUNCTION +@hook TARGET_CHKP_BOUND_TYPE +@hook TARGET_CHKP_BOUND_MODE + @hook TARGET_RESOLVE_OVERLOADED_BUILTIN @hook TARGET_FOLD_BUILTIN diff --git a/gcc/doc/tree-ssa.texi b/gcc/doc/tree-ssa.texi index aaf741b33f1..93f596d07a4 100644 --- a/gcc/doc/tree-ssa.texi +++ b/gcc/doc/tree-ssa.texi @@ -526,31 +526,29 @@ the result of ``merging'' @code{a_1}, @code{a_2} and @code{a_3}. Hence, PHI nodes mean ``one of these operands. I don't know which''. -The following macros can be used to examine PHI nodes +The following functions can be used to examine PHI nodes -@defmac PHI_RESULT (@var{phi}) +@defun gimple_phi_result (@var{phi}) Returns the @code{SSA_NAME} created by PHI node @var{phi} (i.e., @var{phi}'s LHS)@. -@end defmac +@end defun -@defmac PHI_NUM_ARGS (@var{phi}) +@defun gimple_phi_num_args (@var{phi}) Returns the number of arguments in @var{phi}. This number is exactly the number of incoming edges to the basic block holding @var{phi}@. -@end defmac +@end defun -@defmac PHI_ARG_ELT (@var{phi}, @var{i}) -Returns a tuple representing the @var{i}th argument of @var{phi}@. -Each element of this tuple contains an @code{SSA_NAME} @var{var} and -the incoming edge through which @var{var} flows. -@end defmac +@defun gimple_phi_arg (@var{phi}, @var{i}) +Returns @var{i}th argument of @var{phi}@. +@end defun -@defmac PHI_ARG_EDGE (@var{phi}, @var{i}) +@defun gimple_phi_arg_edge (@var{phi}, @var{i}) Returns the incoming edge for the @var{i}th argument of @var{phi}. -@end defmac +@end defun -@defmac PHI_ARG_DEF (@var{phi}, @var{i}) +@defun gimple_phi_arg_def (@var{phi}, @var{i}) Returns the @code{SSA_NAME} for the @var{i}th argument of @var{phi}. -@end defmac +@end defun @subsection Preserving the SSA form diff --git a/gcc/dse.c b/gcc/dse.c index 1d04a252583..b602caa291f 100644 --- a/gcc/dse.c +++ b/gcc/dse.c @@ -46,7 +46,8 @@ along with GCC; see the file COPYING3. If not see #include "dbgcnt.h" #include "target.h" #include "params.h" -#include "tree-ssa.h" /* for may_be_aliased */ +#include "gimple.h" +#include "gimple-ssa.h" /* This file contains three techniques for performing Dead Store Elimination (dse). diff --git a/gcc/dwarf2cfi.c b/gcc/dwarf2cfi.c index 5a096adcd0f..e0f85edc61b 100644 --- a/gcc/dwarf2cfi.c +++ b/gcc/dwarf2cfi.c @@ -24,6 +24,7 @@ along with GCC; see the file COPYING3. If not see #include "version.h" #include "flags.h" #include "rtl.h" +#include "tree.h" #include "function.h" #include "basic-block.h" #include "dwarf2.h" diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 54fc6f7320d..07cb28e8d3c 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -93,6 +93,7 @@ along with GCC; see the file COPYING3. If not see #include "dumpfile.h" #include "opts.h" #include "tree-dfa.h" +#include "gdb/gdb-index.h" static void dwarf2out_source_line (unsigned int, const char *, int, bool); static rtx last_var_location_insn; @@ -3369,10 +3370,14 @@ new_addr_loc_descr (rtx addr, enum dtprel_bool dtprel) #define DEBUG_DWO_LOC_SECTION ".debug_loc.dwo" #endif #ifndef DEBUG_PUBNAMES_SECTION -#define DEBUG_PUBNAMES_SECTION ".debug_pubnames" +#define DEBUG_PUBNAMES_SECTION \ + ((debug_generate_pub_sections == 2) \ + ? ".debug_gnu_pubnames" : ".debug_pubnames") #endif #ifndef DEBUG_PUBTYPES_SECTION -#define DEBUG_PUBTYPES_SECTION ".debug_pubtypes" +#define DEBUG_PUBTYPES_SECTION \ + ((debug_generate_pub_sections == 2) \ + ? ".debug_gnu_pubtypes" : ".debug_pubtypes") #endif #define DEBUG_NORM_STR_OFFSETS_SECTION ".debug_str_offsets" #define DEBUG_DWO_STR_OFFSETS_SECTION ".debug_str_offsets.dwo" @@ -4630,6 +4635,16 @@ is_cxx (void) return lang == DW_LANG_C_plus_plus || lang == DW_LANG_ObjC_plus_plus; } +/* Return TRUE if the language is Java. */ + +static inline bool +is_java (void) +{ + unsigned int lang = get_AT_unsigned (comp_unit_die (), DW_AT_language); + + return lang == DW_LANG_Java; +} + /* Return TRUE if the language is Fortran. */ static inline bool @@ -8052,6 +8067,12 @@ unmark_all_dies (dw_die_ref die) static bool include_pubname_in_output (vec<pubname_entry, va_gc> *table, pubname_entry *p) { + /* By limiting gnu pubnames to definitions only, gold can generate a + gdb index without entries for declarations, which don't include + enough information to be useful. */ + if (debug_generate_pub_sections == 2 && is_declaration_die (p->die)) + return false; + if (table == pubname_table) { /* Enumerator names are part of the pubname table, but the @@ -8081,11 +8102,12 @@ size_of_pubnames (vec<pubname_entry, va_gc> *names) unsigned long size; unsigned i; pubname_ref p; + int space_for_flags = (debug_generate_pub_sections == 2) ? 1 : 0; size = DWARF_PUBNAMES_HEADER_SIZE; FOR_EACH_VEC_ELT (*names, i, p) if (include_pubname_in_output (names, p)) - size += strlen (p->name) + DWARF_OFFSET_SIZE + 1; + size += strlen (p->name) + DWARF_OFFSET_SIZE + 1 + space_for_flags; size += DWARF_OFFSET_SIZE; return size; @@ -9278,6 +9300,76 @@ add_pubtype (tree decl, dw_die_ref die) } } +/* Output a single entry in the pubnames table. */ + +static void +output_pubname (dw_offset die_offset, pubname_entry *entry) +{ + dw_die_ref die = entry->die; + int is_static = get_AT_flag (die, DW_AT_external) ? 0 : 1; + + dw2_asm_output_data (DWARF_OFFSET_SIZE, die_offset, "DIE offset"); + + if (debug_generate_pub_sections == 2) + { + /* This logic follows gdb's method for determining the value of the flag + byte. */ + uint32_t flags = GDB_INDEX_SYMBOL_KIND_NONE; + switch (die->die_tag) + { + case DW_TAG_typedef: + case DW_TAG_base_type: + case DW_TAG_subrange_type: + GDB_INDEX_SYMBOL_KIND_SET_VALUE(flags, GDB_INDEX_SYMBOL_KIND_TYPE); + GDB_INDEX_SYMBOL_STATIC_SET_VALUE(flags, 1); + break; + case DW_TAG_enumerator: + GDB_INDEX_SYMBOL_KIND_SET_VALUE(flags, + GDB_INDEX_SYMBOL_KIND_VARIABLE); + if (!is_cxx () && !is_java ()) + GDB_INDEX_SYMBOL_STATIC_SET_VALUE(flags, 1); + break; + case DW_TAG_subprogram: + GDB_INDEX_SYMBOL_KIND_SET_VALUE(flags, + GDB_INDEX_SYMBOL_KIND_FUNCTION); + if (!is_ada ()) + GDB_INDEX_SYMBOL_STATIC_SET_VALUE(flags, is_static); + break; + case DW_TAG_constant: + GDB_INDEX_SYMBOL_KIND_SET_VALUE(flags, + GDB_INDEX_SYMBOL_KIND_VARIABLE); + GDB_INDEX_SYMBOL_STATIC_SET_VALUE(flags, is_static); + break; + case DW_TAG_variable: + GDB_INDEX_SYMBOL_KIND_SET_VALUE(flags, + GDB_INDEX_SYMBOL_KIND_VARIABLE); + GDB_INDEX_SYMBOL_STATIC_SET_VALUE(flags, is_static); + break; + case DW_TAG_namespace: + case DW_TAG_imported_declaration: + GDB_INDEX_SYMBOL_KIND_SET_VALUE(flags, GDB_INDEX_SYMBOL_KIND_TYPE); + break; + case DW_TAG_class_type: + case DW_TAG_interface_type: + case DW_TAG_structure_type: + case DW_TAG_union_type: + case DW_TAG_enumeration_type: + GDB_INDEX_SYMBOL_KIND_SET_VALUE(flags, GDB_INDEX_SYMBOL_KIND_TYPE); + if (!is_cxx () && !is_java ()) + GDB_INDEX_SYMBOL_STATIC_SET_VALUE(flags, 1); + break; + default: + /* An unusual tag. Leave the flag-byte empty. */ + break; + } + dw2_asm_output_data (1, flags >> GDB_INDEX_CU_BITSIZE, + "GDB-index flags"); + } + + dw2_asm_output_nstring (entry->name, -1, "external name"); +} + + /* Output the public names table used to speed up access to externally visible names; or the public types table used to find type definitions. */ @@ -9288,23 +9380,14 @@ output_pubnames (vec<pubname_entry, va_gc> *names) unsigned long pubnames_length = size_of_pubnames (names); pubname_ref pub; - if (!want_pubnames () || !info_section_emitted) - return; - if (names == pubname_table) - switch_to_section (debug_pubnames_section); - else - switch_to_section (debug_pubtypes_section); if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4) dw2_asm_output_data (4, 0xffffffff, "Initial length escape value indicating 64-bit DWARF extension"); - if (names == pubname_table) - dw2_asm_output_data (DWARF_OFFSET_SIZE, pubnames_length, - "Length of Public Names Info"); - else - dw2_asm_output_data (DWARF_OFFSET_SIZE, pubnames_length, - "Length of Public Type Names Info"); - /* Version number for pubnames/pubtypes is still 2, even in DWARF3. */ + dw2_asm_output_data (DWARF_OFFSET_SIZE, pubnames_length, "Pub Info Length"); + + /* Version number for pubnames/pubtypes is independent of dwarf version. */ dw2_asm_output_data (2, 2, "DWARF Version"); + if (dwarf_split_debug_info) dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_skeleton_info_section_label, debug_skeleton_info_section, @@ -9340,15 +9423,31 @@ output_pubnames (vec<pubname_entry, va_gc> *names) : 0); } - dw2_asm_output_data (DWARF_OFFSET_SIZE, die_offset, "DIE offset"); - - dw2_asm_output_nstring (pub->name, -1, "external name"); + output_pubname (die_offset, pub); } } dw2_asm_output_data (DWARF_OFFSET_SIZE, 0, NULL); } +/* Output public names and types tables if necessary. */ + +static void +output_pubtables (void) +{ + if (!want_pubnames () || !info_section_emitted) + return; + + switch_to_section (debug_pubnames_section); + output_pubnames (pubname_table); + /* ??? Only defined by DWARF3, but emitted by Darwin for DWARF2. + It shouldn't hurt to emit it always, since pure DWARF2 consumers + simply won't look for the section. */ + switch_to_section (debug_pubtypes_section); + output_pubnames (pubtype_table); +} + + /* Output the information that goes into the .debug_aranges table. Namely, define the beginning and ending address range of the text section generated for this compilation unit. */ @@ -15211,7 +15310,7 @@ reference_to_unused (tree * tp, int * walk_subtrees, else if (TREE_CODE (*tp) == VAR_DECL) { struct varpool_node *node = varpool_get_node (*tp); - if (!node || !node->symbol.definition) + if (!node || !node->definition) return *tp; } else if (TREE_CODE (*tp) == FUNCTION_DECL @@ -17884,7 +17983,7 @@ premark_types_used_by_global_vars_helper (void **slot, /* Ask cgraph if the global variable really is to be emitted. If yes, then we'll keep the DIE of ENTRY->TYPE. */ struct varpool_node *node = varpool_get_node (entry->var_decl); - if (node && node->symbol.definition) + if (node && node->definition) { die->die_perennial_p = 1; /* Keep the parent DIEs as well. */ @@ -24264,12 +24363,7 @@ dwarf2out_finish (const char *filename) output_location_lists (comp_unit_die ()); } - /* Output public names and types tables if necessary. */ - output_pubnames (pubname_table); - /* ??? Only defined by DWARF3, but emitted by Darwin for DWARF2. - It shouldn't hurt to emit it always, since pure DWARF2 consumers - simply won't look for the section. */ - output_pubnames (pubtype_table); + output_pubtables (); /* Output the address range information if a CU (.debug_info section) was emitted. We output an empty table even if we had no functions diff --git a/gcc/except.c b/gcc/except.c index a3076056aea..937935f03b6 100644 --- a/gcc/except.c +++ b/gcc/except.c @@ -139,7 +139,7 @@ along with GCC; see the file COPYING3. If not see #include "diagnostic.h" #include "tree-pretty-print.h" #include "tree-pass.h" -#include "tree-ssa.h" +#include "gimple.h" #include "cfgloop.h" /* Provide defaults for stuff that may not be defined when using diff --git a/gcc/expmed.c b/gcc/expmed.c index 90aa45e09e1..f7303c9eab4 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -636,13 +636,28 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, || (bitsize % BITS_PER_WORD == 0 && bitnum % BITS_PER_WORD == 0))) { /* Use the subreg machinery either to narrow OP0 to the required - words or to cope with mode punning between equal-sized modes. */ - rtx sub = simplify_gen_subreg (fieldmode, op0, GET_MODE (op0), - bitnum / BITS_PER_UNIT); - if (sub) + words or to cope with mode punning between equal-sized modes. + In the latter case, use subreg on the rhs side, not lhs. */ + rtx sub; + + if (bitsize == GET_MODE_BITSIZE (GET_MODE (op0))) { - emit_move_insn (sub, value); - return true; + sub = simplify_gen_subreg (GET_MODE (op0), value, fieldmode, 0); + if (sub) + { + emit_move_insn (op0, sub); + return true; + } + } + else + { + sub = simplify_gen_subreg (fieldmode, op0, GET_MODE (op0), + bitnum / BITS_PER_UNIT); + if (sub) + { + emit_move_insn (sub, value); + return true; + } } } diff --git a/gcc/expr.c b/gcc/expr.c index 60d9de62582..c751004c68e 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -43,12 +43,16 @@ along with GCC; see the file COPYING3. If not see #include "intl.h" #include "tm_p.h" #include "tree-iterator.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "cgraph.h" +#include "tree-ssanames.h" #include "target.h" #include "common/common-target.h" #include "timevar.h" #include "df.h" #include "diagnostic.h" +#include "tree-ssa-live.h" #include "tree-outof-ssa.h" #include "target-globals.h" #include "params.h" @@ -6522,16 +6526,18 @@ get_inner_reference (tree exp, HOST_WIDE_INT *pbitsize, { tree field = TREE_OPERAND (exp, 1); size_tree = DECL_SIZE (field); - if (!DECL_BIT_FIELD (field)) - mode = DECL_MODE (field); - else if (DECL_MODE (field) == BLKmode) - blkmode_bitfield = true; - else if (TREE_THIS_VOLATILE (exp) - && flag_strict_volatile_bitfields > 0) + if (flag_strict_volatile_bitfields > 0 + && TREE_THIS_VOLATILE (exp) + && DECL_BIT_FIELD_TYPE (field) + && DECL_MODE (field) != BLKmode) /* Volatile bitfields should be accessed in the mode of the field's type, not the mode computed based on the bit size. */ mode = TYPE_MODE (DECL_BIT_FIELD_TYPE (field)); + else if (!DECL_BIT_FIELD (field)) + mode = DECL_MODE (field); + else if (DECL_MODE (field) == BLKmode) + blkmode_bitfield = true; *punsignedp = DECL_UNSIGNED (field); } @@ -7248,72 +7254,14 @@ safe_from_p (const_rtx x, tree exp, int top_p) unsigned HOST_WIDE_INT highest_pow2_factor (const_tree exp) { - unsigned HOST_WIDE_INT c0, c1; - - switch (TREE_CODE (exp)) - { - case INTEGER_CST: - /* We can find the lowest bit that's a one. If the low - HOST_BITS_PER_WIDE_INT bits are zero, return BIGGEST_ALIGNMENT. - We need to handle this case since we can find it in a COND_EXPR, - a MIN_EXPR, or a MAX_EXPR. If the constant overflows, we have an - erroneous program, so return BIGGEST_ALIGNMENT to avoid any - later ICE. */ - if (TREE_OVERFLOW (exp)) - return BIGGEST_ALIGNMENT; - else - { - c0 = tree_to_hwi (exp); - c0 &= -c0; - return c0 ? c0 : BIGGEST_ALIGNMENT; - } - break; - - case PLUS_EXPR: case MINUS_EXPR: case MIN_EXPR: case MAX_EXPR: - c0 = highest_pow2_factor (TREE_OPERAND (exp, 0)); - c1 = highest_pow2_factor (TREE_OPERAND (exp, 1)); - return MIN (c0, c1); - - case MULT_EXPR: - c0 = highest_pow2_factor (TREE_OPERAND (exp, 0)); - c1 = highest_pow2_factor (TREE_OPERAND (exp, 1)); - return c0 * c1; - - case ROUND_DIV_EXPR: case TRUNC_DIV_EXPR: case FLOOR_DIV_EXPR: - case CEIL_DIV_EXPR: - if (integer_pow2p (TREE_OPERAND (exp, 1)) - && tree_fits_uhwi_p (TREE_OPERAND (exp, 1))) - { - c0 = highest_pow2_factor (TREE_OPERAND (exp, 0)); - c1 = tree_to_uhwi (TREE_OPERAND (exp, 1)); - return MAX (1, c0 / c1); - } - break; - - case BIT_AND_EXPR: - /* The highest power of two of a bit-and expression is the maximum of - that of its operands. We typically get here for a complex LHS and - a constant negative power of two on the RHS to force an explicit - alignment, so don't bother looking at the LHS. */ - return highest_pow2_factor (TREE_OPERAND (exp, 1)); - - CASE_CONVERT: - case SAVE_EXPR: - return highest_pow2_factor (TREE_OPERAND (exp, 0)); - - case COMPOUND_EXPR: - return highest_pow2_factor (TREE_OPERAND (exp, 1)); - - case COND_EXPR: - c0 = highest_pow2_factor (TREE_OPERAND (exp, 1)); - c1 = highest_pow2_factor (TREE_OPERAND (exp, 2)); - return MIN (c0, c1); - - default: - break; - } - - return 1; + unsigned HOST_WIDE_INT ret; + int trailing_zeros = tree_ctz (exp); + if (trailing_zeros >= HOST_BITS_PER_WIDE_INT) + return BIGGEST_ALIGNMENT; + ret = (unsigned HOST_WIDE_INT) 1 << trailing_zeros; + if (ret > BIGGEST_ALIGNMENT) + return BIGGEST_ALIGNMENT; + return ret; } /* Similar, except that the alignment requirements of TARGET are @@ -9620,13 +9568,13 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, } align = get_object_alignment (exp); op0 = expand_expr (base, NULL_RTX, VOIDmode, EXPAND_SUM); - op0 = memory_address_addr_space (address_mode, op0, as); + op0 = memory_address_addr_space (mode, op0, as); if (!integer_zerop (TREE_OPERAND (exp, 1))) { rtx off = immed_wide_int_const (mem_ref_offset (exp), address_mode); op0 = simplify_gen_binary (PLUS, address_mode, op0, off); + op0 = memory_address_addr_space (mode, op0, as); } - op0 = memory_address_addr_space (mode, op0, as); temp = gen_rtx_MEM (mode, op0); set_mem_attributes (temp, exp, 0); set_mem_addr_space (temp, as); diff --git a/gcc/expr.h b/gcc/expr.h index f0bbb0ed5d6..ca93058e5e1 100644 --- a/gcc/expr.h +++ b/gcc/expr.h @@ -28,7 +28,7 @@ along with GCC; see the file COPYING3. If not see #include "flags.h" /* For tree_fits_uhwi_p, tree_to_uhwi, fold_convert, size_binop, ssize_int, TREE_CODE, TYPE_SIZE, int_size_in_bytes, */ -#include "tree.h" +#include "tree-core.h" /* For GET_MODE_BITSIZE, word_mode */ #include "machmode.h" diff --git a/gcc/final.c b/gcc/final.c index 8a9b48f631b..052103cd0ea 100644 --- a/gcc/final.c +++ b/gcc/final.c @@ -70,8 +70,8 @@ along with GCC; see the file COPYING3. If not see #include "debug.h" #include "expr.h" #include "tree-pass.h" -#include "tree-ssa.h" #include "cgraph.h" +#include "tree-ssa.h" #include "coverage.h" #include "df.h" #include "ggc.h" diff --git a/gcc/flag-types.h b/gcc/flag-types.h index a2be8bb1ad2..7d0ac3582e4 100644 --- a/gcc/flag-types.h +++ b/gcc/flag-types.h @@ -210,7 +210,9 @@ enum sanitize_code { SANITIZE_SHIFT = 1 << 2, SANITIZE_DIVIDE = 1 << 3, SANITIZE_UNREACHABLE = 1 << 4, + SANITIZE_VLA = 1 << 5, SANITIZE_UNDEFINED = SANITIZE_SHIFT | SANITIZE_DIVIDE | SANITIZE_UNREACHABLE + | SANITIZE_VLA }; /* flag_vtable_verify initialization levels. */ diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 296b7ec24b8..2a5665f1865 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -58,7 +58,7 @@ along with GCC; see the file COPYING3. If not see #include "langhooks.h" #include "md5.h" #include "gimple.h" -#include "tree-ssa.h" +#include "tree-dfa.h" /* Nonzero if we are folding constants inside an initializer; zero otherwise. */ @@ -2716,10 +2716,11 @@ operand_equal_p (const_tree arg0, const_tree arg1, unsigned int flags) case COMPONENT_REF: /* Handle operand 2 the same as for ARRAY_REF. Operand 0 may be NULL when we're called to compare MEM_EXPRs. */ - if (!OP_SAME_WITH_NULL (0)) + if (!OP_SAME_WITH_NULL (0) + || !OP_SAME (1)) return 0; flags &= ~OEP_CONSTANT_ADDRESS_OF; - return OP_SAME (1) && OP_SAME_WITH_NULL (2); + return OP_SAME_WITH_NULL (2); case BIT_FIELD_REF: if (!OP_SAME (0)) @@ -3473,11 +3474,6 @@ optimize_bit_field_compare (location_t loc, enum tree_code code, tree mask; tree offset; - /* In the strict volatile bitfields case, doing code changes here may prevent - other optimizations, in particular in a SLOW_BYTE_ACCESS setting. */ - if (flag_strict_volatile_bitfields > 0) - return 0; - /* Get all the information about the extractions being done. If the bit size if the same as the size of the underlying object, we aren't doing an extraction at all and so can do nothing. We also don't want to @@ -3486,7 +3482,7 @@ optimize_bit_field_compare (location_t loc, enum tree_code code, linner = get_inner_reference (lhs, &lbitsize, &lbitpos, &offset, &lmode, &lunsignedp, &lvolatilep, false); if (linner == lhs || lbitsize == GET_MODE_BITSIZE (lmode) || lbitsize < 0 - || offset != 0 || TREE_CODE (linner) == PLACEHOLDER_EXPR) + || offset != 0 || TREE_CODE (linner) == PLACEHOLDER_EXPR || lvolatilep) return 0; if (!const_p) @@ -3498,22 +3494,17 @@ optimize_bit_field_compare (location_t loc, enum tree_code code, if (rinner == rhs || lbitpos != rbitpos || lbitsize != rbitsize || lunsignedp != runsignedp || offset != 0 - || TREE_CODE (rinner) == PLACEHOLDER_EXPR) + || TREE_CODE (rinner) == PLACEHOLDER_EXPR || rvolatilep) return 0; } /* See if we can find a mode to refer to this field. We should be able to, but fail if we can't. */ - if (lvolatilep - && GET_MODE_BITSIZE (lmode) > 0 - && flag_strict_volatile_bitfields > 0) - nmode = lmode; - else - nmode = get_best_mode (lbitsize, lbitpos, 0, 0, - const_p ? TYPE_ALIGN (TREE_TYPE (linner)) - : MIN (TYPE_ALIGN (TREE_TYPE (linner)), - TYPE_ALIGN (TREE_TYPE (rinner))), - word_mode, lvolatilep || rvolatilep); + nmode = get_best_mode (lbitsize, lbitpos, 0, 0, + const_p ? TYPE_ALIGN (TREE_TYPE (linner)) + : MIN (TYPE_ALIGN (TREE_TYPE (linner)), + TYPE_ALIGN (TREE_TYPE (rinner))), + word_mode, false); if (nmode == VOIDmode) return 0; @@ -3602,11 +3593,6 @@ optimize_bit_field_compare (location_t loc, enum tree_code code, appropriate number of bits and mask it with the computed mask (in case this was a signed field). If we changed it, make a new one. */ lhs = make_bit_field_ref (loc, linner, unsigned_type, nbitsize, nbitpos, 1); - if (lvolatilep) - { - TREE_SIDE_EFFECTS (lhs) = 1; - TREE_THIS_VOLATILE (lhs) = 1; - } rhs = const_binop (BIT_AND_EXPR, const_binop (LSHIFT_EXPR, @@ -4954,12 +4940,16 @@ fold_range_test (location_t loc, enum tree_code code, tree type, int in0_p, in1_p, in_p; tree low0, low1, low, high0, high1, high; bool strict_overflow_p = false; - tree lhs = make_range (op0, &in0_p, &low0, &high0, &strict_overflow_p); - tree rhs = make_range (op1, &in1_p, &low1, &high1, &strict_overflow_p); - tree tem; + tree tem, lhs, rhs; const char * const warnmsg = G_("assuming signed overflow does not occur " "when simplifying range test"); + if (!INTEGRAL_TYPE_P (type)) + return 0; + + lhs = make_range (op0, &in0_p, &low0, &high0, &strict_overflow_p); + rhs = make_range (op1, &in1_p, &low1, &high1, &strict_overflow_p); + /* If this is an OR operation, invert both sides; we will invert again at the end. */ if (or_op) @@ -10949,6 +10939,13 @@ fold_binary_loc (location_t loc, fold_build2_loc (loc, MULT_EXPR, type, build_int_cst (type, 2) , arg1)); + /* ((T) (X /[ex] C)) * C cancels out if the conversion is + sign-changing only. */ + if (TREE_CODE (arg1) == INTEGER_CST + && TREE_CODE (arg0) == EXACT_DIV_EXPR + && operand_equal_p (arg1, TREE_OPERAND (arg0, 1), 0)) + return fold_convert_loc (loc, type, TREE_OPERAND (arg0, 0)); + strict_overflow_p = false; if (TREE_CODE (arg1) == INTEGER_CST && 0 != (tem = extract_muldiv (op0, arg1, code, NULL_TREE, diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 067d1fdca5b..059b7b3528c 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,46 @@ +2013-10-29 Tobias Burnus <burnus@net-b.de> + + PR fortran/44350 + * parse.c (parse_spec): Add C1116 constraint + check for BLOCK DATA. + +2013-10-29 Paul Thomas <pault@gcc.gnu.org> + + PR fortran/58793 + * trans-types.c (gfc_typenode_for_spec): Add typenode for + BT_HOLLERITH. Note that the length is incorrect but unusable. + + PR fortran/58858 + * target-memory.c (gfc_element_size): Add element sizes for + BT_VOID and BT_ASSUMED, using gfc_typenode_for_spec. + +2013-10-24 Tobias Burnus <burnus@net-b.de> + + PR fortran/44646 + * trans-stmt.c (struct forall_info): Add do_concurrent field. + (gfc_trans_forall_1): Set it for do concurrent. + (gfc_trans_forall_loop): Mark those as annot_expr_ivdep_kind. + +2013-10-23 Tobias Burnus <burnus@net-b.de> + + PR fortran/58793 + * interface.c (compare_parameter): Reject passing TYPE(*) + to CLASS(*). + +2013-10-22 Paul Thomas <pault@gcc.gnu.org> + + PR fortran 57893 + * class.c : Include target-memory.h. + (gfc_find_intrinsic_vtab) Build a minimal expression so that + gfc_element_size can be used to obtain the storage size, rather + that the kind value. + +2013-10-21 Tobias Burnus <burnus@net-b.de> + + PR fortran/58803 + * decl.c (match_ppc_decl): Prevent later + double free. + 2013-10-17 Andrew MacLeod <amacleod@redhat.com> * trans-openmp.c: Include omp-low.h. @@ -1424,7 +1467,7 @@ (TS 29113 Status): Add TYPE(*) and DIMENSION(..). (C Interop): Update the section about TS29113. -2013-02-06 Paul Thomas <pault@gcc.gnu.org> +2013-02-06 Paul Thomas <pault@gcc.gnu.org> PR fortran/55789 * trans-array.c (trans_array_constructor): Remove condition @@ -1521,7 +1564,7 @@ (variable_decl): Remove undeclared type error. (gfc_match_import): Use renamed instead of original name. -2013-01-27 Paul Thomas <pault@gcc.gnu.org> +2013-01-27 Paul Thomas <pault@gcc.gnu.org> PR fortran/55984 PR fortran/56047 diff --git a/gcc/fortran/class.c b/gcc/fortran/class.c index be4959a7dee..52b9760b271 100644 --- a/gcc/fortran/class.c +++ b/gcc/fortran/class.c @@ -53,6 +53,7 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "gfortran.h" #include "constructor.h" +#include "target-memory.h" /* Inserts a derived type component reference in a data reference chain. TS: base type of the ref chain so far, in which we will pick the component @@ -618,7 +619,7 @@ gfc_build_class_symbol (gfc_typespec *ts, symbol_attribute *attr, if (!ts->u.derived->attr.unlimited_polymorphic) fclass->attr.abstract = ts->u.derived->attr.abstract; fclass->f2k_derived = gfc_get_namespace (NULL, 0); - if (!gfc_add_flavor (&fclass->attr, FL_DERIVED, NULL, + if (!gfc_add_flavor (&fclass->attr, FL_DERIVED, NULL, &gfc_current_locus)) return false; @@ -2135,7 +2136,7 @@ gfc_find_derived_vtab (gfc_symbol *derived) { gfc_get_symbol (name, ns, &vtab); vtab->ts.type = BT_DERIVED; - if (!gfc_add_flavor (&vtab->attr, FL_VARIABLE, NULL, + if (!gfc_add_flavor (&vtab->attr, FL_VARIABLE, NULL, &gfc_current_locus)) goto cleanup; vtab->attr.target = 1; @@ -2152,7 +2153,7 @@ gfc_find_derived_vtab (gfc_symbol *derived) gfc_symbol *parent = NULL, *parent_vtab = NULL; gfc_get_symbol (name, ns, &vtype); - if (!gfc_add_flavor (&vtype->attr, FL_DERIVED, NULL, + if (!gfc_add_flavor (&vtype->attr, FL_DERIVED, NULL, &gfc_current_locus)) goto cleanup; vtype->attr.access = ACCESS_PUBLIC; @@ -2456,7 +2457,7 @@ gfc_find_intrinsic_vtab (gfc_typespec *ts) { gfc_get_symbol (name, ns, &vtab); vtab->ts.type = BT_DERIVED; - if (!gfc_add_flavor (&vtab->attr, FL_VARIABLE, NULL, + if (!gfc_add_flavor (&vtab->attr, FL_VARIABLE, NULL, &gfc_current_locus)) goto cleanup; vtab->attr.target = 1; @@ -2473,9 +2474,10 @@ gfc_find_intrinsic_vtab (gfc_typespec *ts) int hash; gfc_namespace *sub_ns; gfc_namespace *contained; + gfc_expr *e; gfc_get_symbol (name, ns, &vtype); - if (!gfc_add_flavor (&vtype->attr, FL_DERIVED, NULL, + if (!gfc_add_flavor (&vtype->attr, FL_DERIVED, NULL, &gfc_current_locus)) goto cleanup; vtype->attr.access = ACCESS_PUBLIC; @@ -2498,12 +2500,16 @@ gfc_find_intrinsic_vtab (gfc_typespec *ts) c->ts.type = BT_INTEGER; c->ts.kind = 4; c->attr.access = ACCESS_PRIVATE; - if (ts->type == BT_CHARACTER) - c->initializer = gfc_get_int_expr (gfc_default_integer_kind, - NULL, charlen*ts->kind); - else - c->initializer = gfc_get_int_expr (gfc_default_integer_kind, - NULL, ts->kind); + + /* Build a minimal expression to make use of + target-memory.c/gfc_element_size for 'size'. */ + e = gfc_get_expr (); + e->ts = *ts; + e->expr_type = EXPR_VARIABLE; + c->initializer = gfc_get_int_expr (gfc_default_integer_kind, + NULL, + (int)gfc_element_size (e)); + gfc_free_expr (e); /* Add component _extends. */ if (!gfc_add_component (vtype, "_extends", &c)) diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c index 3a8175f3ff2..9c9fd4ffbf0 100644 --- a/gcc/fortran/decl.c +++ b/gcc/fortran/decl.c @@ -5055,7 +5055,14 @@ match_ppc_decl (void) if (!gfc_add_proc (&c->attr, name, NULL)) return MATCH_ERROR; - c->tb = tb; + if (num == 1) + c->tb = tb; + else + { + c->tb = XCNEW (gfc_typebound_proc); + c->tb->where = gfc_current_locus; + *c->tb = *tb; + } /* Set interface. */ if (proc_if != NULL) diff --git a/gcc/fortran/interface.c b/gcc/fortran/interface.c index b3ddf5f08b3..0504c904b96 100644 --- a/gcc/fortran/interface.c +++ b/gcc/fortran/interface.c @@ -1972,6 +1972,15 @@ compare_parameter (gfc_symbol *formal, gfc_expr *actual, return 0; } + if (actual->ts.type == BT_ASSUMED && formal->ts.type != BT_ASSUMED) + { + if (where) + gfc_error ("Assumed-type actual argument at %L requires that dummy " + "argument '%s' is of assumed type", &actual->where, + formal->name); + return 0; + } + /* F2008, 12.5.2.5; IR F08/0073. */ if (formal->ts.type == BT_CLASS && formal->attr.class_ok && actual->expr_type != EXPR_NULL diff --git a/gcc/fortran/parse.c b/gcc/fortran/parse.c index 512babfd450..e8b988558a8 100644 --- a/gcc/fortran/parse.c +++ b/gcc/fortran/parse.c @@ -2628,6 +2628,33 @@ loop: default: break; } + else if (gfc_current_state () == COMP_BLOCK_DATA) + /* Fortran 2008, C1116. */ + switch (st) + { + case ST_DATA_DECL: + case ST_COMMON: + case ST_DATA: + case ST_TYPE: + case ST_END_BLOCK_DATA: + case ST_ATTR_DECL: + case ST_EQUIVALENCE: + case ST_PARAMETER: + case ST_IMPLICIT: + case ST_IMPLICIT_NONE: + case ST_DERIVED_DECL: + case ST_USE: + break; + + case ST_NONE: + break; + + default: + gfc_error ("%s statement is not allowed inside of BLOCK DATA at %C", + gfc_ascii_statement (st)); + reject_statement (); + break; + } /* If we find a statement that can not be followed by an IMPLICIT statement (and thus we can expect to see none any further), type the function result diff --git a/gcc/fortran/target-memory.c b/gcc/fortran/target-memory.c index 937fda529b8..da8c7bf1165 100644 --- a/gcc/fortran/target-memory.c +++ b/gcc/fortran/target-memory.c @@ -33,7 +33,7 @@ along with GCC; see the file COPYING3. If not see #include "target-memory.h" #include "wide-int.h" -/* --------------------------------------------------------------- */ +/* --------------------------------------------------------------- */ /* Calculate the size of an expression. */ @@ -110,6 +110,8 @@ gfc_element_size (gfc_expr *e) return e->representation.length; case BT_DERIVED: case BT_CLASS: + case BT_VOID: + case BT_ASSUMED: { /* Determine type size without clobbering the typespec for ISO C binding types. */ @@ -152,7 +154,7 @@ gfc_target_expr_size (gfc_expr *e) } -/* The encode_* functions export a value into a buffer, and +/* The encode_* functions export a value into a buffer, and return the number of bytes of the buffer that have been used. */ @@ -287,7 +289,7 @@ gfc_target_encode_expr (gfc_expr *source, unsigned char *buffer, || source->expr_type == EXPR_STRUCTURE || source->expr_type == EXPR_SUBSTRING); - /* If we already have a target-memory representation, we use that rather + /* If we already have a target-memory representation, we use that rather than recreating one. */ if (source->representation.string) { @@ -497,7 +499,7 @@ gfc_interpret_derived (unsigned char *buffer, size_t buffer_size, gfc_expr *resu /* Needed as gfc_typenode_for_spec as gfc_typenode_for_spec sets this to BT_INTEGER. */ result->ts.type = BT_DERIVED; - e = gfc_get_constant_expr (cmp->ts.type, cmp->ts.kind, &result->where); + e = gfc_get_constant_expr (cmp->ts.type, cmp->ts.kind, &result->where); c = gfc_constructor_append_expr (&result->value.constructor, e, NULL); c->n.component = cmp; gfc_target_interpret_expr (buffer, buffer_size, e, true); @@ -512,7 +514,7 @@ gfc_interpret_derived (unsigned char *buffer, size_t buffer_size, gfc_expr *resu { gfc_constructor *c; gfc_expr *e = gfc_get_constant_expr (cmp->ts.type, cmp->ts.kind, - &result->where); + &result->where); e->ts = cmp->ts; /* Copy shape, if needed. */ @@ -552,7 +554,7 @@ gfc_interpret_derived (unsigned char *buffer, size_t buffer_size, gfc_expr *resu gfc_target_interpret_expr (&buffer[ptr], buffer_size - ptr, e, true); } - + return int_size_in_bytes (type); } @@ -568,31 +570,31 @@ gfc_target_interpret_expr (unsigned char *buffer, size_t buffer_size, switch (result->ts.type) { case BT_INTEGER: - result->representation.length = + result->representation.length = gfc_interpret_integer (result->ts.kind, buffer, buffer_size, result->value.integer); break; case BT_REAL: - result->representation.length = + result->representation.length = gfc_interpret_float (result->ts.kind, buffer, buffer_size, result->value.real); break; case BT_COMPLEX: - result->representation.length = + result->representation.length = gfc_interpret_complex (result->ts.kind, buffer, buffer_size, result->value.complex); break; case BT_LOGICAL: - result->representation.length = + result->representation.length = gfc_interpret_logical (result->ts.kind, buffer, buffer_size, &result->value.logical); break; case BT_CHARACTER: - result->representation.length = + result->representation.length = gfc_interpret_character (buffer, buffer_size, result); break; @@ -600,7 +602,7 @@ gfc_target_interpret_expr (unsigned char *buffer, size_t buffer_size, result->ts = CLASS_DATA (result)->ts; /* Fall through. */ case BT_DERIVED: - result->representation.length = + result->representation.length = gfc_interpret_derived (buffer, buffer_size, result); gcc_assert (result->representation.length >= 0); break; @@ -627,7 +629,7 @@ gfc_target_interpret_expr (unsigned char *buffer, size_t buffer_size, } -/* --------------------------------------------------------------- */ +/* --------------------------------------------------------------- */ /* Two functions used by trans-common.c to write overlapping equivalence initializers to a buffer. This is added to the union and the original initializers freed. */ @@ -792,7 +794,7 @@ gfc_convert_boz (gfc_expr *expr, gfc_typespec *ts) gfc_interpret_complex (ts->kind, buffer, buffer_size, expr->value.complex); } - expr->is_boz = 0; + expr->is_boz = 0; expr->ts.type = ts->type; expr->ts.kind = ts->kind; diff --git a/gcc/fortran/trans-stmt.c b/gcc/fortran/trans-stmt.c index edd2dacf579..62e690d407c 100644 --- a/gcc/fortran/trans-stmt.c +++ b/gcc/fortran/trans-stmt.c @@ -53,6 +53,7 @@ typedef struct forall_info int nvar; tree size; struct forall_info *prev_nest; + bool do_concurrent; } forall_info; @@ -2759,6 +2760,11 @@ gfc_trans_forall_loop (forall_info *forall_tmp, tree body, /* The exit condition. */ cond = fold_build2_loc (input_location, LE_EXPR, boolean_type_node, count, build_int_cst (TREE_TYPE (count), 0)); + if (forall_tmp->do_concurrent) + cond = build2 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, + build_int_cst (integer_type_node, + annot_expr_ivdep_kind)); + tmp = build1_v (GOTO_EXPR, exit_label); tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, tmp, build_empty_stmt (input_location)); @@ -3842,6 +3848,7 @@ gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info) } tmp = gfc_finish_block (&body); + nested_forall_info->do_concurrent = true; tmp = gfc_trans_nested_forall_loop (nested_forall_info, tmp, 1); gfc_add_expr_to_block (&block, tmp); goto done; diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c index 48ab6545071..03ceea7417b 100644 --- a/gcc/fortran/trans-types.c +++ b/gcc/fortran/trans-types.c @@ -1094,6 +1094,12 @@ gfc_typenode_for_spec (gfc_typespec * spec) basetype = gfc_get_character_type (spec->kind, spec->u.cl); break; + case BT_HOLLERITH: + /* Since this cannot be used, return a length one character. */ + basetype = gfc_get_character_type_len (gfc_default_character_kind, + gfc_index_one_node); + break; + case BT_DERIVED: case BT_CLASS: basetype = gfc_get_derived_type (spec->u.derived); diff --git a/gcc/function.c b/gcc/function.c index ae56aedcdae..aace4361e9b 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -4128,12 +4128,11 @@ void reorder_blocks (void) { tree block = DECL_INITIAL (current_function_decl); - vec<tree> block_stack; if (block == NULL_TREE) return; - block_stack.create (10); + stack_vec<tree, 10> block_stack; /* Reset the TREE_ASM_WRITTEN bit for all blocks. */ clear_block_marks (block); @@ -4145,8 +4144,6 @@ reorder_blocks (void) /* Recreate the block tree from the note nesting. */ reorder_blocks_1 (get_insns (), block, &block_stack); BLOCK_SUBBLOCKS (block) = blocks_nreverse_all (BLOCK_SUBBLOCKS (block)); - - block_stack.release (); } /* Helper function for reorder_blocks. Reset TREE_ASM_WRITTEN. */ diff --git a/gcc/function.h b/gcc/function.h index d1f4ffc1fd4..9bb6ff04c50 100644 --- a/gcc/function.h +++ b/gcc/function.h @@ -552,6 +552,9 @@ struct GTY(()) function { /* Vector of function local variables, functions, types and constants. */ vec<tree, va_gc> *local_decls; + /* In a Cilk function, the VAR_DECL for the frame descriptor. */ + tree cilk_frame_decl; + /* For md files. */ /* tm.h can use this to store whatever it likes. */ @@ -607,6 +610,12 @@ struct GTY(()) function { either as a subroutine or builtin. */ unsigned int calls_alloca : 1; + /* This will indicate whether a function is a cilk function */ + unsigned int is_cilk_function : 1; + + /* Nonzero if this is a Cilk function that spawns. */ + unsigned int calls_cilk_spawn : 1; + /* Nonzero if function being compiled receives nonlocal gotos from nested functions. */ unsigned int has_nonlocal_label : 1; diff --git a/gcc/gcc.c b/gcc/gcc.c index 2bbc9426cf9..22982497a3b 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -523,28 +523,12 @@ proper position among the other output files. */ #define LIB_SPEC "%{!shared:%{g*:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}}" #endif -/* mudflap specs */ -#ifndef MFWRAP_SPEC -/* XXX: valid only for GNU ld */ -/* XXX: should exactly match hooks provided by libmudflap.a */ -#define MFWRAP_SPEC " %{static: %{fmudflap|fmudflapth: \ - --wrap=malloc --wrap=free --wrap=calloc --wrap=realloc\ - --wrap=mmap --wrap=mmap64 --wrap=munmap --wrap=alloca\ -} %{fmudflapth: --wrap=pthread_create\ -}} %{fmudflap|fmudflapth: --wrap=main}" -#endif -#ifndef MFLIB_SPEC -#define MFLIB_SPEC "%{fmudflap|fmudflapth: -export-dynamic}" -#endif - /* When using -fsplit-stack we need to wrap pthread_create, in order to initialize the stack guard. We always use wrapping, rather than shared library ordering, and we keep the wrapper function in libgcc. This is not yet a real spec, though it could become one; it is currently just stuffed into LINK_SPEC. FIXME: This wrapping - only works with GNU ld and gold. FIXME: This is incompatible with - -fmudflap when linking statically, which wants to do its own - wrapping. */ + only works with GNU ld and gold. */ #define STACK_SPLIT_SPEC " %{fsplit-stack: --wrap=pthread_create}" #ifndef LIBASAN_SPEC @@ -820,8 +804,6 @@ static const char *asm_spec = ASM_SPEC; static const char *asm_final_spec = ASM_FINAL_SPEC; static const char *link_spec = LINK_SPEC; static const char *lib_spec = LIB_SPEC; -static const char *mfwrap_spec = MFWRAP_SPEC; -static const char *mflib_spec = MFLIB_SPEC; static const char *link_gomp_spec = ""; static const char *libgcc_spec = LIBGCC_SPEC; static const char *endfile_spec = ENDFILE_SPEC; @@ -862,8 +844,6 @@ static const char *cpp_unique_options = %{remap} %{g3|ggdb3|gstabs3|gcoff3|gxcoff3|gvms3:-dD}\ %{!iplugindir*:%{fplugin*:%:find-plugindir()}}\ %{H} %C %{D*&U*&A*} %{i*} %Z %i\ - %{fmudflap:-D_MUDFLAP -include mf-runtime.h}\ - %{fmudflapth:-D_MUDFLAP -D_MUDFLAPTH -include mf-runtime.h}\ %{E|M|MM:%W{o*}}"; /* This contains cpp options which are common with cc1_options and are passed @@ -895,7 +875,6 @@ static const char *cc1_options = %{-help=*:--help=%*}\ %{!fsyntax-only:%{S:%W{o*}%{!o*:-o %b.s}}}\ %{fsyntax-only:-o %j} %{-param*}\ - %{fmudflap|fmudflapth:-fno-builtin -fno-merge-constants}\ %{coverage:-fprofile-arcs -ftest-coverage}"; static const char *asm_options = @@ -1309,8 +1288,6 @@ static struct spec_list static_specs[] = INIT_STATIC_SPEC ("endfile", &endfile_spec), INIT_STATIC_SPEC ("link", &link_spec), INIT_STATIC_SPEC ("lib", &lib_spec), - INIT_STATIC_SPEC ("mfwrap", &mfwrap_spec), - INIT_STATIC_SPEC ("mflib", &mflib_spec), INIT_STATIC_SPEC ("link_gomp", &link_gomp_spec), INIT_STATIC_SPEC ("libgcc", &libgcc_spec), INIT_STATIC_SPEC ("startfile", &startfile_spec), diff --git a/gcc/gcse.c b/gcc/gcse.c index 0d02d0a0312..a00bbfab881 100644 --- a/gcc/gcse.c +++ b/gcc/gcse.c @@ -2542,7 +2542,7 @@ gcse_emit_move_after (rtx dest, rtx src, rtx insn) /* Delete redundant computations. Deletion is done by changing the insn to copy the `reaching_reg' of the expression into the result of the SET. It is left to later passes - (cprop, cse2, flow, combine, regmove) to propagate the copy or eliminate it. + to propagate the copy or eliminate it. Return nonzero if a change is made. */ diff --git a/gcc/gdbhooks.py b/gcc/gdbhooks.py index 3d69b11bfe9..53abf329113 100644 --- a/gcc/gdbhooks.py +++ b/gcc/gdbhooks.py @@ -226,8 +226,7 @@ class CGraphNodePrinter: # symtab_node_name calls lang_hooks.decl_printable_name # default implementation (lhd_decl_printable_name) is: # return IDENTIFIER_POINTER (DECL_NAME (decl)); - symbol = self.gdbval['symbol'] - tree_decl = Tree(symbol['decl']) + tree_decl = Tree(self.gdbval['decl']) result += ' "%s"' % tree_decl.DECL_NAME().IDENTIFIER_POINTER() result += '>' return result diff --git a/gcc/genattrtab.c b/gcc/genattrtab.c index 973cade3fc2..f79380d6e46 100644 --- a/gcc/genattrtab.c +++ b/gcc/genattrtab.c @@ -5100,6 +5100,7 @@ write_header (FILE *outf) fprintf (outf, "#include \"system.h\"\n"); fprintf (outf, "#include \"coretypes.h\"\n"); fprintf (outf, "#include \"tm.h\"\n"); + fprintf (outf, "#include \"tree.h\"\n"); fprintf (outf, "#include \"rtl.h\"\n"); fprintf (outf, "#include \"insn-attr.h\"\n"); fprintf (outf, "#include \"tm_p.h\"\n"); diff --git a/gcc/genautomata.c b/gcc/genautomata.c index a0bf0767aa9..f6c4b91c42e 100644 --- a/gcc/genautomata.c +++ b/gcc/genautomata.c @@ -9665,6 +9665,7 @@ main (int argc, char **argv) "#include \"system.h\"\n" "#include \"coretypes.h\"\n" "#include \"tm.h\"\n" + "#include \"tree.h\"\n" "#include \"rtl.h\"\n" "#include \"tm_p.h\"\n" "#include \"insn-config.h\"\n" diff --git a/gcc/genemit.c b/gcc/genemit.c index 223999ac165..45d3936ddba 100644 --- a/gcc/genemit.c +++ b/gcc/genemit.c @@ -791,6 +791,7 @@ from the machine description file `md'. */\n\n"); printf ("#include \"system.h\"\n"); printf ("#include \"coretypes.h\"\n"); printf ("#include \"tm.h\"\n"); + printf ("#include \"tree.h\"\n"); printf ("#include \"rtl.h\"\n"); printf ("#include \"tm_p.h\"\n"); printf ("#include \"function.h\"\n"); diff --git a/gcc/gengtype-parse.c b/gcc/gengtype-parse.c index 244ddcc85a1..9fb554c628e 100644 --- a/gcc/gengtype-parse.c +++ b/gcc/gengtype-parse.c @@ -165,6 +165,21 @@ require (int t) return v; } +/* As per require, but do not advance. */ +static const char * +require_without_advance (int t) +{ + int u = token (); + const char *v = T.value; + if (u != t) + { + parse_error ("expected %s, have %s", + print_token (t, 0), print_token (u, v)); + return 0; + } + return v; +} + /* If the next token does not have one of the codes T1 or T2, report a parse error; otherwise return the token's value. */ static const char * @@ -822,7 +837,7 @@ struct_field_seq (void) /* Return true if OPTS contain the option named STR. */ -static bool +bool opts_have (options_p opts, const char *str) { for (options_p opt = opts; opt; opt = opt->next) @@ -873,6 +888,7 @@ type (options_p *optsp, bool nested) case STRUCT: case UNION: { + type_p base_class = NULL; options_p opts = 0; /* GTY annotations follow attribute syntax GTY_BEFORE_ID is for union/struct declarations @@ -912,16 +928,39 @@ type (options_p *optsp, bool nested) opts = gtymarker_opt (); } + bool is_user_gty = opts_have (opts, "user"); + if (token () == ':') { - /* Skip over C++ inheritance specification. */ - while (token () != '{') - advance (); + if (is_gty && !is_user_gty) + { + /* For GTY-marked types that are not "user", parse some C++ + inheritance specifications. + We require single-inheritance from a non-template type. */ + advance (); + const char *basename = require (ID); + /* This may be either an access specifier, or the base name. */ + if (0 == strcmp (basename, "public") + || 0 == strcmp (basename, "protected") + || 0 == strcmp (basename, "private")) + basename = require (ID); + base_class = find_structure (basename, TYPE_STRUCT); + if (!base_class) + parse_error ("unrecognized base class: %s", basename); + require_without_advance ('{'); + } + else + { + /* For types lacking GTY-markings, skip over C++ inheritance + specification (and thus avoid having to parse e.g. template + types). */ + while (token () != '{') + advance (); + } } if (is_gty) { - bool is_user_gty = opts_have (opts, "user"); if (token () == '{') { pair_p fields; @@ -944,7 +983,8 @@ type (options_p *optsp, bool nested) return create_user_defined_type (s, &lexer_line); } - return new_structure (s, kind, &lexer_line, fields, opts); + return new_structure (s, kind, &lexer_line, fields, opts, + base_class); } } else if (token () == '{') diff --git a/gcc/gengtype-state.c b/gcc/gengtype-state.c index 0b5cf8f0866..ed61375283a 100644 --- a/gcc/gengtype-state.c +++ b/gcc/gengtype-state.c @@ -956,6 +956,7 @@ state_writer::write_state_struct_type (type_p current) { write_state_struct_union_type (current, "struct"); write_state_type (current->u.s.lang_struct); + write_state_type (current->u.s.base_class); } /* Write a GTY user-defined struct type. */ @@ -1612,6 +1613,9 @@ read_state_struct_type (type_p type) read_state_options (&(type->u.s.opt)); read_state_lang_bitmap (&(type->u.s.bitmap)); read_state_type (&(type->u.s.lang_struct)); + read_state_type (&(type->u.s.base_class)); + if (type->u.s.base_class) + add_subclass (type->u.s.base_class, type); } else { diff --git a/gcc/gengtype.c b/gcc/gengtype.c index e2d9dd4f947..c82536df206 100644 --- a/gcc/gengtype.c +++ b/gcc/gengtype.c @@ -136,6 +136,16 @@ xasprintf (const char *format, ...) return result; } +/* Locate the ultimate base class of struct S. */ + +static const_type_p +get_ultimate_base_class (const_type_p s) +{ + while (s->u.s.base_class) + s = s->u.s.base_class; + return s; +} + /* Input file handling. */ /* Table of all input files. */ @@ -666,6 +676,16 @@ resolve_typedef (const char *s, struct fileloc *pos) return p; } +/* Add SUBCLASS to head of linked list of BASE's subclasses. */ + +void add_subclass (type_p base, type_p subclass) +{ + gcc_assert (union_or_struct_p (base)); + gcc_assert (union_or_struct_p (subclass)); + + subclass->u.s.next_sibling_class = base->u.s.first_subclass; + base->u.s.first_subclass = subclass; +} /* Create and return a new structure with tag NAME at POS with fields FIELDS and options O. The KIND of structure must be one of @@ -673,7 +693,7 @@ resolve_typedef (const char *s, struct fileloc *pos) type_p new_structure (const char *name, enum typekind kind, struct fileloc *pos, - pair_p fields, options_p o) + pair_p fields, options_p o, type_p base_class) { type_p si; type_p s = NULL; @@ -747,6 +767,9 @@ new_structure (const char *name, enum typekind kind, struct fileloc *pos, s->u.s.bitmap = bitmap; if (s->u.s.lang_struct) s->u.s.lang_struct->u.s.bitmap |= bitmap; + s->u.s.base_class = base_class; + if (base_class) + add_subclass (base_class, s); return s; } @@ -975,7 +998,7 @@ create_optional_field_ (pair_p next, type_p type, const char *name, create_string_option (union_fields->opt, "tag", "1"); union_type = new_structure (xasprintf ("%s_%d", "fake_union", id++), TYPE_UNION, - &lexer_line, union_fields, NULL); + &lexer_line, union_fields, NULL, NULL); /* Create the field and give it the new fake union type. Add a "desc" tag that specifies the condition under which the field is valid. */ @@ -1166,7 +1189,7 @@ adjust_field_rtx_def (type_p t, options_p ARG_UNUSED (opt)) create_string_option (nodot, "tag", note_insn_name[c]); } note_union_tp = new_structure ("rtx_def_note_subunion", TYPE_UNION, - &lexer_line, note_flds, NULL); + &lexer_line, note_flds, NULL, NULL); } /* Create a type to represent the various forms of SYMBOL_REF_DATA. */ { @@ -1176,7 +1199,7 @@ adjust_field_rtx_def (type_p t, options_p ARG_UNUSED (opt)) sym_flds = create_field (sym_flds, constant_tp, "rt_constant"); sym_flds->opt = create_string_option (nodot, "tag", "1"); symbol_union_tp = new_structure ("rtx_def_symbol_subunion", TYPE_UNION, - &lexer_line, sym_flds, NULL); + &lexer_line, sym_flds, NULL, NULL); } for (i = 0; i < NUM_RTX_CODE; i++) { @@ -1318,7 +1341,7 @@ adjust_field_rtx_def (type_p t, options_p ARG_UNUSED (opt)) sname = xasprintf ("rtx_def_%s", rtx_name[i]); substruct = new_structure (sname, TYPE_STRUCT, &lexer_line, subfields, - NULL); + NULL, NULL); ftag = xstrdup (rtx_name[i]); for (nmindex = 0; nmindex < strlen (ftag); nmindex++) @@ -1327,7 +1350,7 @@ adjust_field_rtx_def (type_p t, options_p ARG_UNUSED (opt)) flds->opt = create_string_option (nodot, "tag", ftag); } return new_structure ("rtx_def_subunion", TYPE_UNION, &lexer_line, flds, - nodot); + nodot, NULL); } /* Handle `special("tree_exp")'. This is a special case for @@ -1357,7 +1380,7 @@ adjust_field_tree_exp (type_p t, options_p opt ATTRIBUTE_UNUSED) flds->opt = create_string_option (flds->opt, "default", ""); return new_structure ("tree_exp_subunion", TYPE_UNION, &lexer_line, flds, - nodot); + nodot, NULL); } /* Perform any special processing on a type T, about to become the type @@ -1530,7 +1553,17 @@ set_gc_used_type (type_p t, enum gc_used_enum level, type_p param[NUM_PARAM], process_gc_options (t->u.s.opt, level, &dummy, &dummy, &dummy, &dummy, &dummy2); - for (f = t->u.s.fields; f; f = f->next) + if (t->u.s.base_class) + set_gc_used_type (t->u.s.base_class, level, param, + allow_undefined_types); + /* Anything pointing to a base class might actually be pointing + to a subclass. */ + for (type_p subclass = t->u.s.first_subclass; subclass; + subclass = subclass->u.s.next_sibling_class) + set_gc_used_type (subclass, level, param, + allow_undefined_types); + + FOR_ALL_INHERITED_FIELDS(t, f) { int maybe_undef = 0; int pass_param = 0; @@ -1735,8 +1768,12 @@ open_base_files (void) "tree.h", "rtl.h", "wide-int.h", "function.h", "insn-config.h", "expr.h", "hard-reg-set.h", "basic-block.h", "cselib.h", "insn-addr.h", "optabs.h", "libfuncs.h", "debug.h", "ggc.h", "cgraph.h", + "gimple.h", "gimple-ssa.h", "tree-cfg.h", "tree-phinodes.h", + "ssa-iterators.h", "tree-ssanames.h", "tree-ssa-loop.h", + "tree-ssa-loop-ivopts.h", "tree-ssa-loop-manip.h", + "tree-ssa-loop-niter.h", "tree-into-ssa.h", "tree-dfa.h", "tree-ssa.h", "reload.h", "cpp-id-data.h", "tree-chrec.h", - "except.h", "output.h", "gimple.h", "cfgloop.h", + "except.h", "output.h", "cfgloop.h", "target.h", "ipa-prop.h", "lto-streamer.h", "target-globals.h", "ipa-inline.h", "dwarf2out.h", NULL }; @@ -2338,6 +2375,8 @@ is_file_equal (outf_p of) break; } } + if (equal && EOF != fgetc (newfile)) + equal = false; fclose (newfile); return equal; } @@ -2539,6 +2578,10 @@ output_mangled_typename (outf_p of, const_type_p t) case TYPE_LANG_STRUCT: case TYPE_USER_STRUCT: { + /* For references to classes within an inheritance hierarchy, + only ever reference the ultimate base class, since only + it will have gt_ functions. */ + t = get_ultimate_base_class (t); const char *id_for_tag = filter_type_name (t->u.s.tag); oprintf (of, "%lu%s", (unsigned long) strlen (id_for_tag), id_for_tag); @@ -2601,6 +2644,42 @@ output_escaped_param (struct walk_type_data *d, const char *param, } } +const char * +get_string_option (options_p opt, const char *key) +{ + for (; opt; opt = opt->next) + if (strcmp (opt->name, key) == 0) + return opt->info.string; + return NULL; +} + +static void +walk_subclasses (type_p base, struct walk_type_data *d) +{ + for (type_p sub = base->u.s.first_subclass; sub != NULL; + sub = sub->u.s.next_sibling_class) + { + const char *type_tag = get_string_option (sub->u.s.opt, "tag"); + if (type_tag) + { + oprintf (d->of, "%*scase %s:\n", d->indent, "", type_tag); + d->indent += 2; + oprintf (d->of, "%*s{\n", d->indent, ""); + d->indent += 2; + oprintf (d->of, "%*s%s *sub = static_cast <%s *> (x);\n", + d->indent, "", sub->u.s.tag, sub->u.s.tag); + const char *old_val = d->val; + d->val = "(*sub)"; + walk_type (sub, d); + d->val = old_val; + d->indent -= 2; + oprintf (d->of, "%*s}\n", d->indent, ""); + oprintf (d->of, "%*sbreak;\n", d->indent, ""); + d->indent -= 2; + } + walk_subclasses (sub, d); + } +} /* Call D->PROCESS_FIELD for every field (or subfield) of D->VAL, which is of type T. Write code to D->OF to constrain execution (at @@ -2618,6 +2697,7 @@ walk_type (type_p t, struct walk_type_data *d) { const char *length = NULL; const char *desc = NULL; + const char *type_tag = NULL; int maybe_undef_p = 0; int use_param_num = -1; int use_params_p = 0; @@ -2646,7 +2726,7 @@ walk_type (type_p t, struct walk_type_data *d) else if (strcmp (oo->name, "dot") == 0) ; else if (strcmp (oo->name, "tag") == 0) - ; + type_tag = oo->info.string; else if (strcmp (oo->name, "special") == 0) ; else if (strcmp (oo->name, "skip") == 0) @@ -2965,8 +3045,32 @@ walk_type (type_p t, struct walk_type_data *d) d->indent += 2; oprintf (d->of, "%*s{\n", d->indent, ""); } + else if (desc) + { + /* We have a "desc" option on a struct, signifying the + base class within a GC-managed inheritance hierarchy. + The current code specialcases the base class, then walks + into subclasses, recursing into this routine to handle them. + This organization requires the base class to have a case in + the switch statement, and hence a tag value is mandatory + for the base class. This restriction could be removed, but + it would require some restructing of this code. */ + if (!type_tag) + { + error_at_line (d->line, + "missing `tag' option for type `%s'", + t->u.s.tag); + } + oprintf (d->of, "%*sswitch (", d->indent, ""); + output_escaped_param (d, desc, "desc"); + oprintf (d->of, ")\n"); + d->indent += 2; + oprintf (d->of, "%*s{\n", d->indent, ""); + oprintf (d->of, "%*scase %s:\n", d->indent, "", type_tag); + d->indent += 2; + } - for (f = t->u.s.fields; f; f = f->next) + FOR_ALL_INHERITED_FIELDS (t, f) { options_p oo; int skip_p = 0; @@ -3004,7 +3108,7 @@ walk_type (type_p t, struct walk_type_data *d) } endcounter = d->counter; - for (f = t->u.s.fields; f; f = f->next) + FOR_ALL_INHERITED_FIELDS (t, f) { options_p oo; const char *dot = "."; @@ -3106,11 +3210,36 @@ walk_type (type_p t, struct walk_type_data *d) oprintf (d->of, "%*sdefault:\n", d->indent, ""); oprintf (d->of, "%*s break;\n", d->indent, ""); } + + if (desc && !union_p) + { + oprintf (d->of, "%*sbreak;\n", d->indent, ""); + d->indent -= 2; + } if (union_p) { oprintf (d->of, "%*s}\n", d->indent, ""); d->indent -= 2; } + else if (desc) + { + /* Add cases to handle subclasses. */ + walk_subclasses (t, d); + + /* Ensure that if someone forgets a "tag" option that we don't + silent fail to traverse that subclass's fields. */ + if (!seen_default_p) + { + oprintf (d->of, "%*s/* Unrecognized tag value. */\n", + d->indent, ""); + oprintf (d->of, "%*sdefault: gcc_unreachable (); \n", + d->indent, ""); + } + + /* End of the switch statement */ + oprintf (d->of, "%*s}\n", d->indent, ""); + d->indent -= 2; + } if (any_length_seen) { d->indent -= 2; @@ -3456,6 +3585,24 @@ write_func_for_structure (type_p orig_s, type_p s, type_p *param, options_p opt; struct walk_type_data d; + if (s->u.s.base_class) + { + /* Verify that the base class has a "desc", since otherwise + the traversal hooks there won't attempt to visit fields of + subclasses such as this one. */ + const_type_p ubc = get_ultimate_base_class (s); + if ((!opts_have (ubc->u.s.opt, "user") + && !opts_have (ubc->u.s.opt, "desc"))) + error_at_line (&s->u.s.line, + ("'%s' is a subclass of non-GTY(user) GTY class '%s'" + ", but '%s' lacks a discriminator 'desc' option"), + s->u.s.tag, ubc->u.s.tag, ubc->u.s.tag); + + /* Don't write fns for subclasses, only for the ultimate base class + within an inheritance hierarchy. */ + return; + } + memset (&d, 0, sizeof (d)); d.of = get_output_file_for_structure (s, param); for (opt = s->u.s.opt; opt; opt = opt->next) @@ -3632,7 +3779,10 @@ write_types (outf_p output_header, type_p structures, type_p param_structs, emitted afterwards. This is needed in plugin mode. */ oprintf (output_header, "/* Macros and declarations. */\n"); for (s = structures; s; s = s->next) - if (s->gc_used == GC_POINTED_TO || s->gc_used == GC_MAYBE_POINTED_TO) + /* Do not emit handlers for derived classes; we only ever deal with + the ultimate base class within an inheritance hierarchy. */ + if ((s->gc_used == GC_POINTED_TO || s->gc_used == GC_MAYBE_POINTED_TO) + && !s->u.s.base_class) { options_p opt; @@ -3937,6 +4087,11 @@ write_local_func_for_structure (const_type_p orig_s, type_p s, type_p *param) { struct walk_type_data d; + /* Don't write fns for subclasses, only for the ultimate base class + within an inheritance hierarchy. */ + if (s->u.s.base_class) + return; + memset (&d, 0, sizeof (d)); d.of = get_output_file_for_structure (s, param); d.process_field = write_types_local_process_field; @@ -4081,7 +4236,9 @@ write_local (outf_p output_header, type_p structures, type_p param_structs) || ((s)->gc_used == GC_MAYBE_POINTED_TO \ && s->u.s.line.file != NULL) \ || ((s)->gc_used == GC_USED \ - && strncmp (s->u.s.tag, "anonymous", strlen ("anonymous")))))) + && strncmp (s->u.s.tag, "anonymous", strlen ("anonymous"))) \ + || (s->u.s.base_class && opts_have (s->u.s.opt, "tag"))))) + /* Might T contain any non-pointer elements? */ @@ -4356,7 +4513,7 @@ write_root (outf_p f, pair_p v, type_p type, const char *name, int has_length, case TYPE_POINTER: { - type_p tp; + const_type_p tp; if (!start_root_entry (f, v, name, line)) return; @@ -4365,6 +4522,7 @@ write_root (outf_p f, pair_p v, type_p type, const char *name, int has_length, if (!has_length && union_or_struct_p (tp)) { + tp = get_ultimate_base_class (tp); const char *id_for_tag = filter_type_name (tp->u.s.tag); oprintf (f, " >_ggc_mx_%s,\n", id_for_tag); if (emit_pch) diff --git a/gcc/gengtype.h b/gcc/gengtype.h index f71ad97049d..0c3ec964a2f 100644 --- a/gcc/gengtype.h +++ b/gcc/gengtype.h @@ -291,6 +291,17 @@ struct type { field the original TYPE_LANG_STRUCT type. This is a dirty trick, see the new_structure function for details. */ type_p lang_struct; + + type_p base_class; /* the parent class, if any. */ + + /* The following two fields are not serialized in state files, and + are instead reconstructed on load. */ + + /* The head of a singly-linked list of immediate descendents in + the inheritance hierarchy. */ + type_p first_subclass; + /* The next in that list. */ + type_p next_sibling_class; } s; /* when TYPE_SCALAR: */ @@ -422,9 +433,10 @@ extern char *xasprintf (const char *, ...) ATTRIBUTE_PRINTF_1; extern void do_typedef (const char *s, type_p t, struct fileloc *pos); extern void do_scalar_typedef (const char *s, struct fileloc *pos); extern type_p resolve_typedef (const char *s, struct fileloc *pos); +extern void add_subclass (type_p base, type_p subclass); extern type_p new_structure (const char *name, enum typekind kind, struct fileloc *pos, pair_p fields, - options_p o); + options_p o, type_p base); type_p create_user_defined_type (const char *, struct fileloc *); extern type_p find_structure (const char *s, enum typekind kind); extern type_p create_scalar_type (const char *name); @@ -504,4 +516,12 @@ void dbgprint_count_type_at (const char *, int, const char *, type_p); #define DBGPRINT_COUNT_TYPE(Msg,Ty) do{/*nodbgprint_count_type*/}while (0) #endif /*ENABLE_CHECKING */ +#define FOR_ALL_INHERITED_FIELDS(TYPE, FIELD_VAR) \ + for (type_p sub = (TYPE); sub; sub = sub->u.s.base_class) \ + for (FIELD_VAR = sub->u.s.fields; FIELD_VAR; FIELD_VAR = FIELD_VAR->next) + +extern bool +opts_have (options_p opts, const char *str); + + #endif diff --git a/gcc/genmodes.c b/gcc/genmodes.c index 8122a3ff924..6f0fba85ec4 100644 --- a/gcc/genmodes.c +++ b/gcc/genmodes.c @@ -333,6 +333,7 @@ complete_mode (struct mode_data *m) break; case MODE_INT: + case MODE_POINTER_BOUNDS: case MODE_FLOAT: case MODE_DECIMAL_FLOAT: case MODE_FRACT: @@ -534,6 +535,19 @@ make_special_mode (enum mode_class cl, const char *name, new_mode (cl, name, file, line); } +#define POINTER_BOUNDS_MODE(N, Y) \ + make_pointer_bounds_mode (#N, Y, __FILE__, __LINE__) + +static void ATTRIBUTE_UNUSED +make_pointer_bounds_mode (const char *name, + unsigned int bytesize, + const char *file, unsigned int line) +{ + struct mode_data *m = new_mode (MODE_POINTER_BOUNDS, name, file, line); + m->bytesize = bytesize; +} + + #define INT_MODE(N, Y) FRACTIONAL_INT_MODE (N, -1U, Y) #define FRACTIONAL_INT_MODE(N, B, Y) \ make_int_mode (#N, B, Y, __FILE__, __LINE__) @@ -630,10 +644,10 @@ reset_float_format (const char *name, const char *format, m->format = format; } -/* Partial integer modes are specified by relation to a full integer mode. - For now, we do not attempt to narrow down their bit sizes. */ -#define PARTIAL_INT_MODE(M) \ - make_partial_integer_mode (#M, "P" #M, -1U, __FILE__, __LINE__) +/* Partial integer modes are specified by relation to a full integer + mode. */ +#define PARTIAL_INT_MODE(M,PREC,NAME) \ + make_partial_integer_mode (#M, #NAME, PREC, __FILE__, __LINE__) static void ATTRIBUTE_UNUSED make_partial_integer_mode (const char *base, const char *name, unsigned int precision, @@ -670,7 +684,7 @@ make_vector_mode (enum mode_class bclass, struct mode_data *v; enum mode_class vclass = vector_class (bclass); struct mode_data *component = find_mode (base); - char namebuf[8]; + char namebuf[16]; if (vclass == MODE_RANDOM) return; @@ -918,7 +932,7 @@ enum machine_mode\n{"); end will try to use it for bitfields in structures and the like, which we do not want. Only the target md file should generate BImode widgets. */ - if (first && first->precision == 1) + if (first && first->precision == 1 && c == MODE_INT) first = first->next; if (first && last) @@ -1188,7 +1202,7 @@ emit_class_narrowest_mode (void) /* Bleah, all this to get the comment right for MIN_MODE_INT. */ tagged_printf ("MIN_%s", mode_class_names[c], modes[c] - ? (modes[c]->precision != 1 + ? ((c != MODE_INT || modes[c]->precision != 1) ? modes[c]->name : (modes[c]->next ? modes[c]->next->name diff --git a/gcc/genopinit.c b/gcc/genopinit.c index 9c7cf2c06a4..3efb71e249e 100644 --- a/gcc/genopinit.c +++ b/gcc/genopinit.c @@ -404,6 +404,7 @@ main (int argc, char **argv) "#include \"system.h\"\n" "#include \"coretypes.h\"\n" "#include \"tm.h\"\n" + "#include \"tree.h\"\n" "#include \"rtl.h\"\n" "#include \"tm_p.h\"\n" "#include \"flags.h\"\n" diff --git a/gcc/genoutput.c b/gcc/genoutput.c index c3a0936fc97..2a7ee2391db 100644 --- a/gcc/genoutput.c +++ b/gcc/genoutput.c @@ -238,6 +238,7 @@ output_prologue (void) printf ("#include \"tm.h\"\n"); printf ("#include \"flags.h\"\n"); printf ("#include \"ggc.h\"\n"); + printf ("#include \"tree.h\"\n"); printf ("#include \"rtl.h\"\n"); printf ("#include \"expr.h\"\n"); printf ("#include \"insn-codes.h\"\n"); diff --git a/gcc/genpeep.c b/gcc/genpeep.c index a14d061a50b..877fde3ec90 100644 --- a/gcc/genpeep.c +++ b/gcc/genpeep.c @@ -359,6 +359,7 @@ from the machine description file `md'. */\n\n"); printf ("#include \"coretypes.h\"\n"); printf ("#include \"tm.h\"\n"); printf ("#include \"insn-config.h\"\n"); + printf ("#include \"tree.h\"\n"); printf ("#include \"rtl.h\"\n"); printf ("#include \"tm_p.h\"\n"); printf ("#include \"regs.h\"\n"); diff --git a/gcc/ggc-page.c b/gcc/ggc-page.c index 249aa010507..f68129e4da6 100644 --- a/gcc/ggc-page.c +++ b/gcc/ggc-page.c @@ -30,7 +30,7 @@ along with GCC; see the file COPYING3. If not see #include "ggc-internal.h" #include "timevar.h" #include "params.h" -#include "tree-ssa.h" +#include "cgraph.h" #include "cfgloop.h" #include "plugin.h" diff --git a/gcc/gimple-builder.c b/gcc/gimple-builder.c index 665c8020b93..6b53221b6b3 100644 --- a/gcc/gimple-builder.c +++ b/gcc/gimple-builder.c @@ -22,7 +22,7 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tree.h" #include "gimple.h" -#include "tree-ssa.h" +#include "tree-ssanames.h" /* Return the expression type to use based on the CODE and type of diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index 36d993ca5a8..6ad5981cc1b 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -26,6 +26,12 @@ along with GCC; see the file COPYING3. If not see #include "flags.h" #include "function.h" #include "dumpfile.h" +#include "bitmap.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-ssanames.h" +#include "tree-into-ssa.h" +#include "tree-dfa.h" #include "tree-ssa.h" #include "tree-ssa-propagate.h" #include "target.h" @@ -60,7 +66,7 @@ can_refer_decl_in_current_unit_p (tree decl, tree from_decl) { struct varpool_node *vnode; struct cgraph_node *node; - symtab_node snode; + symtab_node *snode; if (DECL_ABSTRACT (decl)) return false; @@ -87,14 +93,14 @@ can_refer_decl_in_current_unit_p (tree decl, tree from_decl) || TREE_CODE (from_decl) != VAR_DECL || !DECL_EXTERNAL (from_decl) || (flag_ltrans - && symtab_get_node (from_decl)->symbol.in_other_partition)) + && symtab_get_node (from_decl)->in_other_partition)) return true; /* We are folding reference from external vtable. The vtable may reffer to a symbol keyed to other compilation unit. The other compilation unit may be in separate DSO and the symbol may be hidden. */ if (DECL_VISIBILITY_SPECIFIED (decl) && DECL_EXTERNAL (decl) - && (!(snode = symtab_get_node (decl)) || !snode->symbol.in_other_partition)) + && (!(snode = symtab_get_node (decl)) || !snode->in_other_partition)) return false; /* When function is public, we always can introduce new reference. Exception are the COMDAT functions where introducing a direct @@ -125,7 +131,7 @@ can_refer_decl_in_current_unit_p (tree decl, tree from_decl) The second is important when devirtualization happens during final compilation stage when making a new reference no longer makes callee to be compiled. */ - if (!node || !node->symbol.definition || node->global.inlined_to) + if (!node || !node->definition || node->global.inlined_to) { gcc_checking_assert (!TREE_ASM_WRITTEN (decl)); return false; @@ -134,7 +140,7 @@ can_refer_decl_in_current_unit_p (tree decl, tree from_decl) else if (TREE_CODE (decl) == VAR_DECL) { vnode = varpool_get_node (decl); - if (!vnode || !vnode->symbol.definition) + if (!vnode || !vnode->definition) { gcc_checking_assert (!TREE_ASM_WRITTEN (decl)); return false; diff --git a/gcc/gimple-iterator.c b/gcc/gimple-iterator.c index 574e31f298f..e430050fcf7 100644 --- a/gcc/gimple-iterator.c +++ b/gcc/gimple-iterator.c @@ -24,6 +24,11 @@ along with GCC; see the file COPYING3. If not see #include "tm.h" #include "tree.h" #include "gimple.h" +#include "gimple-ssa.h" +#include "cgraph.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" #include "tree-ssa.h" #include "value-prof.h" diff --git a/gcc/gimple-low.c b/gcc/gimple-low.c index cf61204c411..d527d86ab22 100644 --- a/gcc/gimple-low.c +++ b/gcc/gimple-low.c @@ -26,7 +26,6 @@ along with GCC; see the file COPYING3. If not see #include "gimple.h" #include "tree-iterator.h" #include "tree-inline.h" -#include "tree-ssa.h" #include "flags.h" #include "function.h" #include "diagnostic-core.h" diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c index a45dd535d95..c95b9c46357 100644 --- a/gcc/gimple-pretty-print.c +++ b/gcc/gimple-pretty-print.c @@ -27,9 +27,13 @@ along with GCC; see the file COPYING3. If not see #include "diagnostic.h" #include "gimple-pretty-print.h" #include "hashtab.h" -#include "tree-ssa.h" -#include "dumpfile.h" /* for dump_flags */ +#include "bitmap.h" #include "gimple.h" +#include "gimple-ssa.h" +#include "cgraph.h" +#include "tree-cfg.h" +#include "tree-ssanames.h" +#include "dumpfile.h" /* for dump_flags */ #include "value-prof.h" #include "trans-mem.h" @@ -535,11 +539,12 @@ dump_gimple_assign (pretty_printer *buffer, gimple gs, int spc, int flags) static void dump_gimple_return (pretty_printer *buffer, gimple gs, int spc, int flags) { - tree t; + tree t, t2; t = gimple_return_retval (gs); + t2 = gimple_return_retbnd (gs); if (flags & TDF_RAW) - dump_gimple_fmt (buffer, spc, flags, "%G <%T>", gs, t); + dump_gimple_fmt (buffer, spc, flags, "%G <%T %T>", gs, t, t2); else { pp_string (buffer, "return"); @@ -548,6 +553,11 @@ dump_gimple_return (pretty_printer *buffer, gimple gs, int spc, int flags) pp_space (buffer); dump_generic_node (buffer, t, spc, flags, false); } + if (t2) + { + pp_string (buffer, ", "); + dump_generic_node (buffer, t2, spc, flags, false); + } pp_semicolon (buffer); } } @@ -1714,7 +1724,7 @@ dump_ssaname_info (pretty_printer *buffer, tree node, int spc) { unsigned int align, misalign; struct ptr_info_def *pi = SSA_NAME_PTR_INFO (node); - pp_string (buffer, "PT = "); + pp_string (buffer, "# PT = "); pp_points_to_solution (buffer, &pi->pt); newline_and_indent (buffer, spc); if (get_ptr_info_alignment (pi, &align, &misalign)) @@ -1722,17 +1732,16 @@ dump_ssaname_info (pretty_printer *buffer, tree node, int spc) pp_printf (buffer, "# ALIGN = %u, MISALIGN = %u", align, misalign); newline_and_indent (buffer, spc); } - pp_string (buffer, "# "); } if (!POINTER_TYPE_P (TREE_TYPE (node)) && SSA_NAME_RANGE_INFO (node)) { - widest_int min, max; + widest_int min, max, nonzero_bits; value_range_type range_type = get_range_info (node, &min, &max); if (range_type == VR_VARYING) - pp_printf (buffer, "# RANGE VR_VARYING"); + pp_printf (buffer, "# RANGE VR_VARYING"); else if (range_type == VR_RANGE || range_type == VR_ANTI_RANGE) { pp_printf (buffer, "# RANGE "); @@ -1741,18 +1750,27 @@ dump_ssaname_info (pretty_printer *buffer, tree node, int spc) pp_printf (buffer, ", "); pp_wide_int (buffer, max, TYPE_SIGN (TREE_TYPE (node))); pp_printf (buffer, "]"); - newline_and_indent (buffer, spc); } + nonzero_bits = get_nonzero_bits (node); + if (nonzero_bits != -1 + && (nonzero_bits + != wi::mask <widest_int> (TYPE_PRECISION (TREE_TYPE (node)), false))) + { + pp_string (buffer, " NONZERO "); + pp_wide_int (buffer, nonzero_bits, UNSIGNED); + } + newline_and_indent (buffer, spc); } } /* Dump a PHI node PHI. BUFFER, SPC and FLAGS are as in pp_gimple_stmt_1. The caller is responsible for calling pp_flush on BUFFER to finalize - pretty printer. */ + pretty printer. If COMMENT is true, print this after #. */ static void -dump_gimple_phi (pretty_printer *buffer, gimple phi, int spc, int flags) +dump_gimple_phi (pretty_printer *buffer, gimple phi, int spc, bool comment, + int flags) { size_t i; tree lhs = gimple_phi_result (phi); @@ -1760,6 +1778,9 @@ dump_gimple_phi (pretty_printer *buffer, gimple phi, int spc, int flags) if (flags & TDF_ALIAS) dump_ssaname_info (buffer, lhs, spc); + if (comment) + pp_string (buffer, "# "); + if (flags & TDF_RAW) dump_gimple_fmt (buffer, spc, flags, "%G <%T, ", phi, gimple_phi_result (phi)); @@ -2095,7 +2116,7 @@ pp_gimple_stmt_1 (pretty_printer *buffer, gimple gs, int spc, int flags) break; case GIMPLE_PHI: - dump_gimple_phi (buffer, gs, spc, flags); + dump_gimple_phi (buffer, gs, spc, false, flags); break; case GIMPLE_OMP_PARALLEL: @@ -2271,8 +2292,7 @@ dump_phi_nodes (pretty_printer *buffer, basic_block bb, int indent, int flags) if (!virtual_operand_p (gimple_phi_result (phi)) || (flags & TDF_VOPS)) { INDENT (indent); - pp_string (buffer, "# "); - dump_gimple_phi (buffer, phi, indent, flags); + dump_gimple_phi (buffer, phi, indent, true, flags); pp_newline (buffer); } } diff --git a/gcc/gimple-ssa-strength-reduction.c b/gcc/gimple-ssa-strength-reduction.c index 4d9c1f8d68d..69680b28585 100644 --- a/gcc/gimple-ssa-strength-reduction.c +++ b/gcc/gimple-ssa-strength-reduction.c @@ -42,7 +42,11 @@ along with GCC; see the file COPYING3. If not see #include "tree-pass.h" #include "cfgloop.h" #include "gimple-pretty-print.h" -#include "tree-ssa.h" +#include "gimple-ssa.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" #include "domwalk.h" #include "pointer-set.h" #include "expmed.h" diff --git a/gcc/gimple-streamer-in.c b/gcc/gimple-streamer-in.c index 8161a087656..2a19aab44fe 100644 --- a/gcc/gimple-streamer-in.c +++ b/gcc/gimple-streamer-in.c @@ -24,7 +24,10 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "diagnostic.h" #include "tree.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-phinodes.h" +#include "tree-ssanames.h" #include "data-streamer.h" #include "tree-streamer.h" #include "gimple-streamer.h" diff --git a/gcc/gimple-streamer-out.c b/gcc/gimple-streamer-out.c index 33699bbbfa9..976f57ecef4 100644 --- a/gcc/gimple-streamer-out.c +++ b/gcc/gimple-streamer-out.c @@ -23,7 +23,8 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "tree.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "gimple-ssa.h" #include "data-streamer.h" #include "gimple-streamer.h" #include "lto-streamer.h" diff --git a/gcc/gimple.c b/gcc/gimple.c index f6ed803857b..da7be0c4f4e 100644 --- a/gcc/gimple.c +++ b/gcc/gimple.c @@ -174,7 +174,7 @@ gimple_build_with_ops_stat (enum gimple_code code, unsigned subcode, gimple gimple_build_return (tree retval) { - gimple s = gimple_build_with_ops (GIMPLE_RETURN, ERROR_MARK, 1); + gimple s = gimple_build_with_ops (GIMPLE_RETURN, ERROR_MARK, 2); if (retval) gimple_return_set_retval (s, retval); return s; @@ -366,6 +366,26 @@ gimple_build_call_from_tree (tree t) } +/* Return index of INDEX's non bound argument of the call. */ + +unsigned +gimple_call_get_nobnd_arg_index (const_gimple gs, unsigned index) +{ + unsigned num_args = gimple_call_num_args (gs); + for (unsigned n = 0; n < num_args; n++) + { + if (POINTER_BOUNDS_P (gimple_call_arg (gs, n))) + continue; + else if (index) + index--; + else + return n; + } + + gcc_unreachable (); +} + + /* Extract the operands and code for expression EXPR into *SUBCODE_P, *OP1_P, *OP2_P and *OP3_P respectively. */ diff --git a/gcc/gimple.h b/gcc/gimple.h index d8528acade5..b34424c18d3 100644 --- a/gcc/gimple.h +++ b/gcc/gimple.h @@ -27,7 +27,6 @@ along with GCC; see the file COPYING3. If not see #include "vec.h" #include "ggc.h" #include "basic-block.h" -#include "tree.h" #include "tree-ssa-alias.h" #include "internal-fn.h" #include "gimple-fold.h" @@ -919,6 +918,7 @@ extern tree get_initialized_tmp_var (tree, gimple_seq *, gimple_seq *); extern tree get_formal_tmp_var (tree, gimple_seq *); extern void declare_vars (tree, gimple, bool); extern void annotate_all_with_location (gimple_seq, location_t); +extern unsigned gimple_call_get_nobnd_arg_index (const_gimple, unsigned); /* Validation of GIMPLE expressions. Note that these predicates only check the basic form of the expression, they don't recurse to make sure that @@ -2414,6 +2414,32 @@ gimple_call_arg (const_gimple gs, unsigned index) } +/* Return the number of arguments used by call statement GS + ignoring bound ones. */ + +static inline unsigned +gimple_call_num_nobnd_args (const_gimple gs) +{ + unsigned num_args = gimple_call_num_args (gs); + unsigned res = num_args; + for (unsigned n = 0; n < num_args; n++) + if (POINTER_BOUNDS_P (gimple_call_arg (gs, n))) + res--; + return res; +} + + +/* Return INDEX's call argument ignoring bound ones. */ +static inline tree +gimple_call_nobnd_arg (const_gimple gs, unsigned index) +{ + /* No bound args may exist if pointers checker is off. */ + if (!flag_check_pointer_bounds) + return gimple_call_arg (gs, index); + return gimple_call_arg (gs, gimple_call_get_nobnd_arg_index (gs, index)); +} + + /* Return a pointer to the argument at position INDEX for call statement GS. */ @@ -5220,6 +5246,26 @@ gimple_return_set_retval (gimple gs, tree retval) } +/* Return the return bounds for GIMPLE_RETURN GS. */ + +static inline tree +gimple_return_retbnd (const_gimple gs) +{ + GIMPLE_CHECK (gs, GIMPLE_RETURN); + return gimple_op (gs, 1); +} + + +/* Set RETVAL to be the return bounds for GIMPLE_RETURN GS. */ + +static inline void +gimple_return_set_retbnd (gimple gs, tree retval) +{ + GIMPLE_CHECK (gs, GIMPLE_RETURN); + gimple_set_op (gs, 1, retval); +} + + /* Returns true when the gimple statement STMT is any of the OpenMP types. */ #define CASE_GIMPLE_OMP \ @@ -5534,6 +5580,20 @@ gsi_start_nondebug_bb (basic_block bb) return i; } +/* Return a new iterator pointing to the first non-debug non-label statement in + basic block BB. */ + +static inline gimple_stmt_iterator +gsi_start_nondebug_after_labels_bb (basic_block bb) +{ + gimple_stmt_iterator i = gsi_after_labels (bb); + + if (!gsi_end_p (i) && is_gimple_debug (gsi_stmt (i))) + gsi_next_nondebug (&i); + + return i; +} + /* Return a new iterator pointing to the last non-debug statement in basic block BB. */ diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 21861d244ea..21dc7cad156 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -30,8 +30,12 @@ along with GCC; see the file COPYING3. If not see #include "tree-inline.h" #include "tree-pretty-print.h" #include "langhooks.h" -#include "tree-ssa.h" +#include "bitmap.h" +#include "gimple-ssa.h" #include "cgraph.h" +#include "tree-cfg.h" +#include "tree-ssanames.h" +#include "tree-ssa.h" #include "timevar.h" #include "hashtab.h" #include "flags.h" @@ -44,10 +48,10 @@ along with GCC; see the file COPYING3. If not see #include "vec.h" #include "omp-low.h" #include "gimple-low.h" +#include "cilk.h" #include "langhooks-def.h" /* FIXME: for lhd_set_decl_assembler_name */ #include "tree-pass.h" /* FIXME: only for PROP_gimple_any */ -#include "tree-mudflap.h" #include "expr.h" #include "tm_p.h" @@ -974,7 +978,7 @@ unshare_body (tree fndecl) if (cgn) for (cgn = cgn->nested; cgn; cgn = cgn->next_nested) - unshare_body (cgn->symbol.decl); + unshare_body (cgn->decl); } /* Callback for walk_tree to unmark the visited trees rooted at *TP. @@ -1017,7 +1021,7 @@ unvisit_body (tree fndecl) if (cgn) for (cgn = cgn->nested; cgn; cgn = cgn->next_nested) - unvisit_body (cgn->symbol.decl); + unvisit_body (cgn->decl); } /* Unconditionally make an unshared copy of EXPR. This is used when using @@ -1232,8 +1236,7 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p) gimple stack_restore; /* Save stack on entry and restore it on exit. Add a try_finally - block to achieve this. Note that mudflap depends on the - format of the emitted code: see mx_register_decls(). */ + block to achieve this. */ build_stack_save_restore (&stack_save, &stack_restore); gimplify_seq_add_stmt (&cleanup, stack_restore); @@ -1307,6 +1310,15 @@ gimplify_return_expr (tree stmt, gimple_seq *pre_p) if (ret_expr == error_mark_node) return GS_ERROR; + /* Implicit _Cilk_sync must be inserted right before any return statement + if there is a _Cilk_spawn in the function. If the user has provided a + _Cilk_sync, the optimizer should remove this duplicate one. */ + if (fn_contains_cilk_spawn_p (cfun)) + { + tree impl_sync = build0 (CILK_SYNC_STMT, void_type_node); + gimplify_and_add (impl_sync, pre_p); + } + if (!ret_expr || TREE_CODE (ret_expr) == RESULT_DECL || ret_expr == error_mark_node) @@ -1391,8 +1403,7 @@ static void gimplify_vla_decl (tree decl, gimple_seq *seq_p) { /* This is a variable-sized decl. Simplify its size and mark it - for deferred expansion. Note that mudflap depends on the format - of the emitted code: see mx_register_decls(). */ + for deferred expansion. */ tree t, addr, ptr_type; gimplify_one_sizepos (&DECL_SIZE (decl), seq_p); @@ -2127,7 +2138,6 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, fallback_t fallback) { tree *p; - vec<tree> expr_stack; enum gimplify_status ret = GS_ALL_DONE, tret; int i; location_t loc = EXPR_LOCATION (*expr_p); @@ -2135,7 +2145,7 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, /* Create a stack of the subexpressions so later we can walk them in order from inner to outer. */ - expr_stack.create (10); + stack_vec<tree, 10> expr_stack; /* We can handle anything that get_inner_reference can deal with. */ for (p = expr_p; ; p = &TREE_OPERAND (*p, 0)) @@ -2493,6 +2503,12 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value) if (! EXPR_HAS_LOCATION (*expr_p)) SET_EXPR_LOCATION (*expr_p, input_location); + if (fn_contains_cilk_spawn_p (cfun) + && lang_hooks.cilkplus.cilk_detect_spawn_and_unwrap (expr_p) + && !seen_error ()) + return (enum gimplify_status) + lang_hooks.cilkplus.gimplify_cilk_spawn (expr_p, pre_p, NULL); + /* This may be a call to a builtin function. Builtin function calls may be transformed into different @@ -3068,6 +3084,17 @@ gimple_boolify (tree expr) TREE_TYPE (expr) = boolean_type_node; return expr; + case ANNOTATE_EXPR: + if ((enum annot_expr_kind) tree_to_uhwi (TREE_OPERAND (expr, 1)) + == annot_expr_ivdep_kind) + { + TREE_OPERAND (expr, 0) = gimple_boolify (TREE_OPERAND (expr, 0)); + if (TREE_CODE (type) != BOOLEAN_TYPE) + TREE_TYPE (expr) = boolean_type_node; + return expr; + } + /* FALLTHRU */ + default: if (COMPARISON_CLASS_P (expr)) { @@ -4048,10 +4075,19 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, individual element initialization. Also don't do this for small all-zero initializers (which aren't big enough to merit clearing), and don't try to make bitwise copies of - TREE_ADDRESSABLE types. */ + TREE_ADDRESSABLE types. + + We cannot apply such transformation when compiling chkp static + initializer because creation of initializer image in the memory + will require static initialization of bounds for it. It should + result in another gimplification of similar initializer and we + may fall into infinite loop. */ if (valid_const_initializer && !(cleared || num_nonzero_elements == 0) - && !TREE_ADDRESSABLE (type)) + && !TREE_ADDRESSABLE (type) + && (!current_function_decl + || !lookup_attribute ("chkp ctor", + DECL_ATTRIBUTES (current_function_decl)))) { HOST_WIDE_INT size = int_size_in_bytes (type); unsigned int align; @@ -4698,6 +4734,12 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, gcc_assert (TREE_CODE (*expr_p) == MODIFY_EXPR || TREE_CODE (*expr_p) == INIT_EXPR); + + if (fn_contains_cilk_spawn_p (cfun) + && lang_hooks.cilkplus.cilk_detect_spawn_and_unwrap (expr_p) + && !seen_error ()) + return (enum gimplify_status) + lang_hooks.cilkplus.gimplify_cilk_spawn (expr_p, pre_p, post_p); /* Trying to simplify a clobber using normal logic doesn't work, so handle it here. */ @@ -7644,6 +7686,19 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, } break; + case CILK_SPAWN_STMT: + gcc_assert + (fn_contains_cilk_spawn_p (cfun) + && lang_hooks.cilkplus.cilk_detect_spawn_and_unwrap (expr_p)); + if (!seen_error ()) + { + ret = (enum gimplify_status) + lang_hooks.cilkplus.gimplify_cilk_spawn (expr_p, pre_p, + post_p); + break; + } + /* If errors are seen, then just process it as a CALL_EXPR. */ + case CALL_EXPR: ret = gimplify_call_expr (expr_p, pre_p, fallback != fb_none); @@ -7723,6 +7778,21 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, ret = gimplify_addr_expr (expr_p, pre_p, post_p); break; + case ANNOTATE_EXPR: + { + tree cond = TREE_OPERAND (*expr_p, 0); + tree id = TREE_OPERAND (*expr_p, 1); + tree tmp = create_tmp_var_raw (TREE_TYPE(cond), NULL); + gimplify_arg (&cond, pre_p, EXPR_LOCATION (*expr_p)); + gimple call = gimple_build_call_internal (IFN_ANNOTATE, 2, + cond, id); + gimple_call_set_lhs (call, tmp); + gimplify_seq_add_stmt (pre_p, call); + *expr_p = tmp; + ret = GS_ALL_DONE; + break; + } + case VA_ARG_EXPR: ret = gimplify_va_arg_expr (expr_p, pre_p, post_p); break; @@ -8264,6 +8334,22 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, break; } + case CILK_SYNC_STMT: + { + if (!fn_contains_cilk_spawn_p (cfun)) + { + error_at (EXPR_LOCATION (*expr_p), + "expected %<_Cilk_spawn%> before %<_Cilk_sync%>"); + ret = GS_ERROR; + } + else + { + gimplify_cilk_sync (expr_p, pre_p); + ret = GS_ALL_DONE; + } + break; + } + default: switch (TREE_CODE_CLASS (TREE_CODE (*expr_p))) { @@ -9224,118 +9310,107 @@ force_gimple_operand_gsi (gimple_stmt_iterator *gsi, tree expr, var, before, m); } -#ifndef PAD_VARARGS_DOWN -#define PAD_VARARGS_DOWN BYTES_BIG_ENDIAN -#endif +/* Return a dummy expression of type TYPE in order to keep going after an + error. */ -/* Build an indirect-ref expression over the given TREE, which represents a - piece of a va_arg() expansion. */ -tree -build_va_arg_indirect_ref (tree addr) +static tree +dummy_object (tree type) { - addr = build_simple_mem_ref_loc (EXPR_LOCATION (addr), addr); - - if (flag_mudflap) /* Don't instrument va_arg INDIRECT_REF. */ - mf_mark (addr); - - return addr; + tree t = build_int_cst (build_pointer_type (type), 0); + return build2 (MEM_REF, type, t, t); } -/* The "standard" implementation of va_arg: read the value from the - current (padded) address and increment by the (padded) size. */ +/* Gimplify __builtin_va_arg, aka VA_ARG_EXPR, which is not really a + builtin function, but a very special sort of operator. */ -tree -std_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p, - gimple_seq *post_p) -{ - tree addr, t, type_size, rounded_size, valist_tmp; - unsigned HOST_WIDE_INT align, boundary; - bool indirect; - -#ifdef ARGS_GROW_DOWNWARD - /* All of the alignment and movement below is for args-grow-up machines. - As of 2004, there are only 3 ARGS_GROW_DOWNWARD targets, and they all - implement their own specialized gimplify_va_arg_expr routines. */ - gcc_unreachable (); -#endif - - indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false); - if (indirect) - type = build_pointer_type (type); +enum gimplify_status +gimplify_va_arg_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) +{ + tree promoted_type, have_va_type; + tree valist = TREE_OPERAND (*expr_p, 0); + tree type = TREE_TYPE (*expr_p); + tree t; + location_t loc = EXPR_LOCATION (*expr_p); - align = PARM_BOUNDARY / BITS_PER_UNIT; - boundary = targetm.calls.function_arg_boundary (TYPE_MODE (type), type); + /* Verify that valist is of the proper type. */ + have_va_type = TREE_TYPE (valist); + if (have_va_type == error_mark_node) + return GS_ERROR; + have_va_type = targetm.canonical_va_list_type (have_va_type); - /* When we align parameter on stack for caller, if the parameter - alignment is beyond MAX_SUPPORTED_STACK_ALIGNMENT, it will be - aligned at MAX_SUPPORTED_STACK_ALIGNMENT. We will match callee - here with caller. */ - if (boundary > MAX_SUPPORTED_STACK_ALIGNMENT) - boundary = MAX_SUPPORTED_STACK_ALIGNMENT; + if (have_va_type == NULL_TREE) + { + error_at (loc, "first argument to %<va_arg%> not of type %<va_list%>"); + return GS_ERROR; + } - boundary /= BITS_PER_UNIT; + /* Generate a diagnostic for requesting data of a type that cannot + be passed through `...' due to type promotion at the call site. */ + if ((promoted_type = lang_hooks.types.type_promotes_to (type)) + != type) + { + static bool gave_help; + bool warned; - /* Hoist the valist value into a temporary for the moment. */ - valist_tmp = get_initialized_tmp_var (valist, pre_p, NULL); + /* Unfortunately, this is merely undefined, rather than a constraint + violation, so we cannot make this an error. If this call is never + executed, the program is still strictly conforming. */ + warned = warning_at (loc, 0, + "%qT is promoted to %qT when passed through %<...%>", + type, promoted_type); + if (!gave_help && warned) + { + gave_help = true; + inform (loc, "(so you should pass %qT not %qT to %<va_arg%>)", + promoted_type, type); + } - /* va_list pointer is aligned to PARM_BOUNDARY. If argument actually - requires greater alignment, we must perform dynamic alignment. */ - if (boundary > align - && !integer_zerop (TYPE_SIZE (type))) - { - t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp, - fold_build_pointer_plus_hwi (valist_tmp, boundary - 1)); + /* We can, however, treat "undefined" any way we please. + Call abort to encourage the user to fix the program. */ + if (warned) + inform (loc, "if this code is reached, the program will abort"); + /* Before the abort, allow the evaluation of the va_list + expression to exit or longjmp. */ + gimplify_and_add (valist, pre_p); + t = build_call_expr_loc (loc, + builtin_decl_implicit (BUILT_IN_TRAP), 0); gimplify_and_add (t, pre_p); - t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp, - fold_build2 (BIT_AND_EXPR, TREE_TYPE (valist), - valist_tmp, - build_int_cst (TREE_TYPE (valist), -boundary))); - gimplify_and_add (t, pre_p); + /* This is dead code, but go ahead and finish so that the + mode of the result comes out right. */ + *expr_p = dummy_object (type); + return GS_ALL_DONE; } else - boundary = align; - - /* If the actual alignment is less than the alignment of the type, - adjust the type accordingly so that we don't assume strict alignment - when dereferencing the pointer. */ - boundary *= BITS_PER_UNIT; - if (boundary < TYPE_ALIGN (type)) { - type = build_variant_type_copy (type); - TYPE_ALIGN (type) = boundary; - } + /* Make it easier for the backends by protecting the valist argument + from multiple evaluations. */ + if (TREE_CODE (have_va_type) == ARRAY_TYPE) + { + /* For this case, the backends will be expecting a pointer to + TREE_TYPE (abi), but it's possible we've + actually been given an array (an actual TARGET_FN_ABI_VA_LIST). + So fix it. */ + if (TREE_CODE (TREE_TYPE (valist)) == ARRAY_TYPE) + { + tree p1 = build_pointer_type (TREE_TYPE (have_va_type)); + valist = fold_convert_loc (loc, p1, + build_fold_addr_expr_loc (loc, valist)); + } - /* Compute the rounded size of the type. */ - type_size = size_in_bytes (type); - rounded_size = round_up (type_size, align); + gimplify_expr (&valist, pre_p, post_p, is_gimple_val, fb_rvalue); + } + else + gimplify_expr (&valist, pre_p, post_p, is_gimple_min_lval, fb_lvalue); - /* Reduce rounded_size so it's sharable with the postqueue. */ - gimplify_expr (&rounded_size, pre_p, post_p, is_gimple_val, fb_rvalue); + if (!targetm.gimplify_va_arg_expr) + /* FIXME: Once most targets are converted we should merely + assert this is non-null. */ + return GS_ALL_DONE; - /* Get AP. */ - addr = valist_tmp; - if (PAD_VARARGS_DOWN && !integer_zerop (rounded_size)) - { - /* Small args are padded downward. */ - t = fold_build2_loc (input_location, GT_EXPR, sizetype, - rounded_size, size_int (align)); - t = fold_build3 (COND_EXPR, sizetype, t, size_zero_node, - size_binop (MINUS_EXPR, rounded_size, type_size)); - addr = fold_build_pointer_plus (addr, t); + *expr_p = targetm.gimplify_va_arg_expr (valist, type, pre_p, post_p); + return GS_OK; } - - /* Compute new value for AP. */ - t = fold_build_pointer_plus (valist_tmp, rounded_size); - t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t); - gimplify_and_add (t, pre_p); - - addr = fold_convert (build_pointer_type (type), addr); - - if (indirect) - addr = build_va_arg_indirect_ref (addr); - - return build_va_arg_indirect_ref (addr); } #include "gt-gimplify.h" diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index 45220b640b2..9dbbfbf8f1d 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -3351,14 +3351,10 @@ Type_conversion_expression::do_get_tree(Translate_context* context) return se->get_tree(context); } - static tree int_to_string_fndecl; - ret = Gogo::call_builtin(&int_to_string_fndecl, - this->location(), - "__go_int_to_string", - 1, - type_tree, - int_type_tree, - expr_tree); + Call_expression* i2s_expr = + Runtime::make_call(Runtime::INT_TO_STRING, this->location(), 1, + this->expr_); + ret = i2s_expr->get_tree(context); } else if (type->is_string_type() && expr_type->is_slice_type()) { @@ -3408,29 +3404,18 @@ Type_conversion_expression::do_get_tree(Translate_context* context) { Type* e = type->array_type()->element_type()->forwarded(); go_assert(e->integer_type() != NULL); + + Call_expression* s2a_expr; if (e->integer_type()->is_byte()) - { - tree string_to_byte_array_fndecl = NULL_TREE; - ret = Gogo::call_builtin(&string_to_byte_array_fndecl, - this->location(), - "__go_string_to_byte_array", - 1, - type_tree, - TREE_TYPE(expr_tree), - expr_tree); - } + s2a_expr = Runtime::make_call(Runtime::STRING_TO_BYTE_ARRAY, + this->location(), 1, this->expr_); else { go_assert(e->integer_type()->is_rune()); - tree string_to_int_array_fndecl = NULL_TREE; - ret = Gogo::call_builtin(&string_to_int_array_fndecl, - this->location(), - "__go_string_to_int_array", - 1, - type_tree, - TREE_TYPE(expr_tree), - expr_tree); + s2a_expr = Runtime::make_call(Runtime::STRING_TO_INT_ARRAY, + this->location(), 1, this->expr_); } + ret = s2a_expr->get_tree(context); } else if ((type->is_unsafe_pointer_type() && expr_type->points_to() != NULL) @@ -10250,7 +10235,9 @@ Index_expression::do_traverse(Traverse* traverse) if (Expression::traverse(&this->left_, traverse) == TRAVERSE_EXIT || Expression::traverse(&this->start_, traverse) == TRAVERSE_EXIT || (this->end_ != NULL - && Expression::traverse(&this->end_, traverse) == TRAVERSE_EXIT)) + && Expression::traverse(&this->end_, traverse) == TRAVERSE_EXIT) + || (this->cap_ != NULL + && Expression::traverse(&this->cap_, traverse) == TRAVERSE_EXIT)) return TRAVERSE_EXIT; return TRAVERSE_CONTINUE; } @@ -10265,6 +10252,7 @@ Index_expression::do_lower(Gogo*, Named_object*, Statement_inserter*, int) Expression* left = this->left_; Expression* start = this->start_; Expression* end = this->end_; + Expression* cap = this->cap_; Type* type = left->type(); if (type->is_error()) @@ -10275,20 +10263,27 @@ Index_expression::do_lower(Gogo*, Named_object*, Statement_inserter*, int) return Expression::make_error(location); } else if (type->array_type() != NULL) - return Expression::make_array_index(left, start, end, location); + return Expression::make_array_index(left, start, end, cap, location); else if (type->points_to() != NULL && type->points_to()->array_type() != NULL && !type->points_to()->is_slice_type()) { Expression* deref = Expression::make_unary(OPERATOR_MULT, left, location); - return Expression::make_array_index(deref, start, end, location); + return Expression::make_array_index(deref, start, end, cap, location); } else if (type->is_string_type()) - return Expression::make_string_index(left, start, end, location); + { + if (cap != NULL) + { + error_at(location, "invalid 3-index slice of string"); + return Expression::make_error(location); + } + return Expression::make_string_index(left, start, end, location); + } else if (type->map_type() != NULL) { - if (end != NULL) + if (end != NULL || cap != NULL) { error_at(location, "invalid slice of map"); return Expression::make_error(location); @@ -10307,14 +10302,15 @@ Index_expression::do_lower(Gogo*, Named_object*, Statement_inserter*, int) } } -// Write an indexed expression (expr[expr:expr] or expr[expr]) to a -// dump context +// Write an indexed expression +// (expr[expr:expr:expr], expr[expr:expr] or expr[expr]) to a dump context. void Index_expression::dump_index_expression(Ast_dump_context* ast_dump_context, const Expression* expr, const Expression* start, - const Expression* end) + const Expression* end, + const Expression* cap) { expr->dump_expression(ast_dump_context); ast_dump_context->ostream() << "["; @@ -10324,6 +10320,11 @@ Index_expression::dump_index_expression(Ast_dump_context* ast_dump_context, ast_dump_context->ostream() << ":"; end->dump_expression(ast_dump_context); } + if (cap != NULL) + { + ast_dump_context->ostream() << ":"; + cap->dump_expression(ast_dump_context); + } ast_dump_context->ostream() << "]"; } @@ -10334,16 +10335,16 @@ Index_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const { Index_expression::dump_index_expression(ast_dump_context, this->left_, - this->start_, this->end_); + this->start_, this->end_, this->cap_); } // Make an index expression. Expression* Expression::make_index(Expression* left, Expression* start, Expression* end, - Location location) + Expression* cap, Location location) { - return new Index_expression(left, start, end, location); + return new Index_expression(left, start, end, cap, location); } // An array index. This is used for both indexing and slicing. @@ -10352,9 +10353,9 @@ class Array_index_expression : public Expression { public: Array_index_expression(Expression* array, Expression* start, - Expression* end, Location location) + Expression* end, Expression* cap, Location location) : Expression(EXPRESSION_ARRAY_INDEX, location), - array_(array), start_(start), end_(end), type_(NULL) + array_(array), start_(start), end_(end), cap_(cap), type_(NULL) { } protected: @@ -10378,6 +10379,9 @@ class Array_index_expression : public Expression (this->end_ == NULL ? NULL : this->end_->copy()), + (this->cap_ == NULL + ? NULL + : this->cap_->copy()), this->location()); } @@ -10409,6 +10413,9 @@ class Array_index_expression : public Expression // The end index of a slice. This may be NULL for a simple array // index, or it may be a nil expression for the length of the array. Expression* end_; + // The capacity argument of a slice. This may be NULL for an array index or + // slice. + Expression* cap_; // The type of the expression. Type* type_; }; @@ -10427,6 +10434,11 @@ Array_index_expression::do_traverse(Traverse* traverse) if (Expression::traverse(&this->end_, traverse) == TRAVERSE_EXIT) return TRAVERSE_EXIT; } + if (this->cap_ != NULL) + { + if (Expression::traverse(&this->cap_, traverse) == TRAVERSE_EXIT) + return TRAVERSE_EXIT; + } return TRAVERSE_CONTINUE; } @@ -10466,6 +10478,8 @@ Array_index_expression::do_determine_type(const Type_context*) this->start_->determine_type_no_context(); if (this->end_ != NULL) this->end_->determine_type_no_context(); + if (this->cap_ != NULL) + this->cap_->determine_type_no_context(); } // Check types of an array index. @@ -10488,6 +10502,14 @@ Array_index_expression::do_check_types(Gogo*) && (!this->end_->numeric_constant_value(&nc) || nc.to_unsigned_long(&v) == Numeric_constant::NC_UL_NOTINT)) this->report_error(_("slice end must be integer")); + if (this->cap_ != NULL + && this->cap_->type()->integer_type() == NULL + && !this->cap_->type()->is_error() + && !this->cap_->is_nil_expression() + && !this->cap_->is_error_expression() + && (!this->cap_->numeric_constant_value(&nc) + || nc.to_unsigned_long(&v) == Numeric_constant::NC_UL_NOTINT)) + this->report_error(_("slice capacity must be integer")); Array_type* array_type = this->array_->type()->array_type(); if (array_type == NULL) @@ -10525,8 +10547,10 @@ Array_index_expression::do_check_types(Gogo*) { Numeric_constant enc; mpz_t eval; + bool eval_valid = false; if (this->end_->numeric_constant_value(&enc) && enc.to_int(&eval)) { + eval_valid = true; if (mpz_sgn(eval) < 0 || mpz_sizeinbase(eval, 2) >= int_bits || (lval_valid && mpz_cmp(eval, lval) > 0)) @@ -10536,8 +10560,37 @@ Array_index_expression::do_check_types(Gogo*) } else if (ival_valid && mpz_cmp(ival, eval) > 0) this->report_error(_("inverted slice range")); - mpz_clear(eval); } + + Numeric_constant cnc; + mpz_t cval; + if (this->cap_ != NULL + && this->cap_->numeric_constant_value(&cnc) && cnc.to_int(&cval)) + { + if (mpz_sgn(cval) < 0 + || mpz_sizeinbase(cval, 2) >= int_bits + || (lval_valid && mpz_cmp(cval, lval) > 0)) + { + error_at(this->cap_->location(), "array index out of bounds"); + this->set_is_error(); + } + else if (ival_valid && mpz_cmp(ival, cval) > 0) + { + error_at(this->cap_->location(), + "invalid slice index: capacity less than start"); + this->set_is_error(); + } + else if (eval_valid && mpz_cmp(eval, cval) > 0) + { + error_at(this->cap_->location(), + "invalid slice index: capacity less than length"); + this->set_is_error(); + } + mpz_clear(cval); + } + + if (eval_valid) + mpz_clear(eval); } if (ival_valid) mpz_clear(ival); @@ -10617,9 +10670,17 @@ Array_index_expression::do_get_tree(Translate_context* context) capacity_tree = save_expr(capacity_tree); } + tree cap_arg = capacity_tree; + if (this->cap_ != NULL) + { + cap_arg = this->cap_->get_tree(context); + if (cap_arg == error_mark_node) + return error_mark_node; + } + tree length_type = (length_tree != NULL_TREE ? TREE_TYPE(length_tree) - : TREE_TYPE(capacity_tree)); + : TREE_TYPE(cap_arg)); tree bad_index = boolean_false_node; @@ -10691,6 +10752,29 @@ Array_index_expression::do_get_tree(Translate_context* context) // Array slice. + if (this->cap_ != NULL) + { + if (!DECL_P(cap_arg)) + cap_arg = save_expr(cap_arg); + if (!INTEGRAL_TYPE_P(TREE_TYPE(cap_arg))) + cap_arg = convert_to_integer(length_type, cap_arg); + + bad_index = Expression::check_bounds(cap_arg, length_type, bad_index, + loc); + cap_arg = fold_convert_loc(loc.gcc_location(), length_type, cap_arg); + + tree bad_cap = fold_build2_loc(loc.gcc_location(), TRUTH_OR_EXPR, + boolean_type_node, + fold_build2_loc(loc.gcc_location(), + LT_EXPR, boolean_type_node, + cap_arg, start_tree), + fold_build2_loc(loc.gcc_location(), + GT_EXPR, boolean_type_node, + cap_arg, capacity_tree)); + bad_index = fold_build2_loc(loc.gcc_location(), TRUTH_OR_EXPR, + boolean_type_node, bad_index, bad_cap); + } + tree end_tree; if (this->end_->is_nil_expression()) end_tree = length_tree; @@ -10716,11 +10800,12 @@ Array_index_expression::do_get_tree(Translate_context* context) end_tree, start_tree), fold_build2_loc(loc.gcc_location(), GT_EXPR, boolean_type_node, - end_tree, capacity_tree)); + end_tree, cap_arg)); bad_index = fold_build2_loc(loc.gcc_location(), TRUTH_OR_EXPR, boolean_type_node, bad_index, bad_end); } + Type* element_type = array_type->element_type(); tree element_type_tree = type_to_tree(element_type->get_backend(gogo)); if (element_type_tree == error_mark_node) @@ -10744,8 +10829,7 @@ Array_index_expression::do_get_tree(Translate_context* context) length_type, end_tree, start_tree); tree result_capacity_tree = fold_build2_loc(loc.gcc_location(), MINUS_EXPR, - length_type, capacity_tree, - start_tree); + length_type, cap_arg, start_tree); tree struct_tree = type_to_tree(this->type()->get_backend(gogo)); go_assert(TREE_CODE(struct_tree) == RECORD_TYPE); @@ -10795,16 +10879,17 @@ Array_index_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const { Index_expression::dump_index_expression(ast_dump_context, this->array_, - this->start_, this->end_); + this->start_, this->end_, this->cap_); } -// Make an array index expression. END may be NULL. +// Make an array index expression. END and CAP may be NULL. Expression* Expression::make_array_index(Expression* array, Expression* start, - Expression* end, Location location) + Expression* end, Expression* cap, + Location location) { - return new Array_index_expression(array, start, end, location); + return new Array_index_expression(array, start, end, cap, location); } // A string index. This is used for both indexing and slicing. @@ -11082,8 +11167,8 @@ void String_index_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const { - Index_expression::dump_index_expression(ast_dump_context, this->string_, - this->start_, this->end_); + Index_expression::dump_index_expression(ast_dump_context, this->string_, + this->start_, this->end_, NULL); } // Make a string index expression. END may be NULL. @@ -11310,8 +11395,8 @@ void Map_index_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const { - Index_expression::dump_index_expression(ast_dump_context, - this->map_, this->index_, NULL); + Index_expression::dump_index_expression(ast_dump_context, this->map_, + this->index_, NULL, NULL); } // Make a map index expression. diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h index 35bfcfe8e4f..a94330dc4d7 100644 --- a/gcc/go/gofrontend/expressions.h +++ b/gcc/go/gofrontend/expressions.h @@ -232,19 +232,21 @@ class Expression Named_object* function, Location); // Make an index or slice expression. This is a parser expression - // which represents LEFT[START:END]. END may be NULL, meaning an - // index rather than a slice. At parse time we may not know the - // type of LEFT. After parsing this is lowered to an array index, a - // string index, or a map index. + // which represents LEFT[START:END:CAP]. END may be NULL, meaning an + // index rather than a slice. CAP may be NULL, meaning we use the default + // capacity of LEFT. At parse time we may not know the type of LEFT. + // After parsing this is lowered to an array index, a string index, + // or a map index. static Expression* make_index(Expression* left, Expression* start, Expression* end, - Location); + Expression* cap, Location); // Make an array index expression. END may be NULL, in which case - // this is an lvalue. + // this is an lvalue. CAP may be NULL, in which case it defaults + // to cap(ARRAY). static Expression* make_array_index(Expression* array, Expression* start, Expression* end, - Location); + Expression* cap, Location); // Make a string index expression. END may be NULL. This is never // an lvalue. @@ -1672,9 +1674,9 @@ class Index_expression : public Parser_expression { public: Index_expression(Expression* left, Expression* start, Expression* end, - Location location) + Expression* cap, Location location) : Parser_expression(EXPRESSION_INDEX, location), - left_(left), start_(start), end_(end), is_lvalue_(false) + left_(left), start_(start), end_(end), cap_(cap), is_lvalue_(false) { } // Record that this expression is an lvalue. @@ -1683,10 +1685,11 @@ class Index_expression : public Parser_expression { this->is_lvalue_ = true; } // Dump an index expression, i.e. an expression of the form - // expr[expr] or expr[expr:expr], to a dump context. + // expr[expr], expr[expr:expr], or expr[expr:expr:expr] to a dump context. static void dump_index_expression(Ast_dump_context*, const Expression* expr, - const Expression* start, const Expression* end); + const Expression* start, const Expression* end, + const Expression* cap); protected: int @@ -1702,6 +1705,9 @@ class Index_expression : public Parser_expression (this->end_ == NULL ? NULL : this->end_->copy()), + (this->cap_ == NULL + ? NULL + : this->cap_->copy()), this->location()); } @@ -1723,6 +1729,10 @@ class Index_expression : public Parser_expression // The second index. This is NULL for an index, non-NULL for a // slice. Expression* end_; + // The capacity argument. This is NULL for indices and slices that use the + // default capacity, non-NULL for indices and slices that specify the + // capacity. + Expression* cap_; // Whether this is being used as an l-value. We set this during the // parse because map index expressions need to know. bool is_lvalue_; diff --git a/gcc/go/gofrontend/parse.cc b/gcc/go/gofrontend/parse.cc index 9c7d8277efa..6e56f835699 100644 --- a/gcc/go/gofrontend/parse.cc +++ b/gcc/go/gofrontend/parse.cc @@ -3152,7 +3152,7 @@ Parse::selector(Expression* left, bool* is_type_switch) } // Index = "[" Expression "]" . -// Slice = "[" Expression ":" [ Expression ] "]" . +// Slice = "[" Expression ":" [ Expression ] [ ":" Expression ] "]" . Expression* Parse::index(Expression* expr) @@ -3178,14 +3178,31 @@ Parse::index(Expression* expr) // We use nil to indicate a missing high expression. if (this->advance_token()->is_op(OPERATOR_RSQUARE)) end = Expression::make_nil(this->location()); + else if (this->peek_token()->is_op(OPERATOR_COLON)) + { + error_at(this->location(), "middle index required in 3-index slice"); + end = Expression::make_error(this->location()); + } else end = this->expression(PRECEDENCE_NORMAL, false, true, NULL, NULL); } + + Expression* cap = NULL; + if (this->peek_token()->is_op(OPERATOR_COLON)) + { + if (this->advance_token()->is_op(OPERATOR_RSQUARE)) + { + error_at(this->location(), "final index required in 3-index slice"); + cap = Expression::make_error(this->location()); + } + else + cap = this->expression(PRECEDENCE_NORMAL, false, true, NULL, NULL); + } if (!this->peek_token()->is_op(OPERATOR_RSQUARE)) error_at(this->location(), "missing %<]%>"); else this->advance_token(); - return Expression::make_index(expr, start, end, location); + return Expression::make_index(expr, start, end, cap, location); } // Call = "(" [ ArgumentList [ "," ] ] ")" . diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc index a5102c0c450..3a0bc3b9739 100644 --- a/gcc/go/gofrontend/statements.cc +++ b/gcc/go/gofrontend/statements.cc @@ -5540,7 +5540,7 @@ For_range_statement::lower_range_array(Gogo* gogo, ref = this->make_range_ref(range_object, range_temp, loc); Expression* ref2 = Expression::make_temporary_reference(index_temp, loc); - Expression* index = Expression::make_index(ref, ref2, NULL, loc); + Expression* index = Expression::make_index(ref, ref2, NULL, NULL, loc); tref = Expression::make_temporary_reference(value_temp, loc); tref->set_is_lvalue(); @@ -5641,7 +5641,7 @@ For_range_statement::lower_range_slice(Gogo* gogo, ref = Expression::make_temporary_reference(for_temp, loc); Expression* ref2 = Expression::make_temporary_reference(index_temp, loc); - Expression* index = Expression::make_index(ref, ref2, NULL, loc); + Expression* index = Expression::make_index(ref, ref2, NULL, NULL, loc); tref = Expression::make_temporary_reference(value_temp, loc); tref->set_is_lvalue(); @@ -5849,7 +5849,7 @@ For_range_statement::lower_range_map(Gogo*, Expression* zexpr = Expression::make_integer(&zval, NULL, loc); mpz_clear(zval); - Expression* index = Expression::make_index(ref, zexpr, NULL, loc); + Expression* index = Expression::make_index(ref, zexpr, NULL, NULL, loc); Expression* ne = Expression::make_binary(OPERATOR_NOTEQ, index, Expression::make_nil(loc), diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc index f0d58e5ed35..ea68c43714b 100644 --- a/gcc/go/gofrontend/types.cc +++ b/gcc/go/gofrontend/types.cc @@ -5645,12 +5645,12 @@ Array_type::write_equal_function(Gogo* gogo, Named_type* name) Expression* e1 = Expression::make_temporary_reference(p1, bloc); e1 = Expression::make_unary(OPERATOR_MULT, e1, bloc); ref = Expression::make_temporary_reference(index, bloc); - e1 = Expression::make_array_index(e1, ref, NULL, bloc); + e1 = Expression::make_array_index(e1, ref, NULL, NULL, bloc); Expression* e2 = Expression::make_temporary_reference(p2, bloc); e2 = Expression::make_unary(OPERATOR_MULT, e2, bloc); ref = Expression::make_temporary_reference(index, bloc); - e2 = Expression::make_array_index(e2, ref, NULL, bloc); + e2 = Expression::make_array_index(e2, ref, NULL, NULL, bloc); Expression* cond = Expression::make_binary(OPERATOR_NOTEQ, e1, e2, bloc); diff --git a/gcc/graph.c b/gcc/graph.c index 0ec279d86a9..5c890e5956c 100644 --- a/gcc/graph.c +++ b/gcc/graph.c @@ -160,9 +160,9 @@ draw_cfg_nodes_no_loops (pretty_printer *pp, struct function *fun) visited = sbitmap_alloc (last_basic_block); bitmap_clear (visited); - /* FIXME: pre_and_rev_post_order_compute only works if fun == cfun. */ - n = pre_and_rev_post_order_compute (NULL, rpo, true); - for (i = 0; i < n; i++) + n = pre_and_rev_post_order_compute_fn (fun, NULL, rpo, true); + for (i = n_basic_blocks_for_function (fun) - n; + i < n_basic_blocks_for_function (fun); i++) { basic_block bb = BASIC_BLOCK (rpo[i]); draw_cfg_node (pp, fun->funcdef_no, bb); diff --git a/gcc/graphite-blocking.c b/gcc/graphite-blocking.c index 9226da00eae..1fff36c53bc 100644 --- a/gcc/graphite-blocking.c +++ b/gcc/graphite-blocking.c @@ -34,7 +34,9 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" -#include "tree-ssa.h" +#include "tree.h" +#include "gimple.h" +#include "tree-ssa-loop.h" #include "dumpfile.h" #include "cfgloop.h" #include "tree-chrec.h" diff --git a/gcc/graphite-clast-to-gimple.c b/gcc/graphite-clast-to-gimple.c index 883011c8532..ce3c5bd0792 100644 --- a/gcc/graphite-clast-to-gimple.c +++ b/gcc/graphite-clast-to-gimple.c @@ -35,7 +35,12 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "diagnostic-core.h" -#include "tree-ssa.h" +#include "tree.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-ssa-loop-manip.h" +#include "tree-ssa-loop.h" +#include "tree-into-ssa.h" #include "tree-pass.h" #include "cfgloop.h" #include "tree-chrec.h" @@ -1646,8 +1651,7 @@ debug_generated_program (scop_p scop) bool gloog (scop_p scop, bb_pbb_htab_type bb_pbb_mapping) { - vec<tree> newivs; - newivs.create (10); + stack_vec<tree, 10> newivs; loop_p context_loop; sese region = SCOP_REGION (scop); ifsese if_region = NULL; @@ -1705,7 +1709,6 @@ gloog (scop_p scop, bb_pbb_htab_type bb_pbb_mapping) newivs_index.dispose (); params_index.dispose (); - newivs.release (); cloog_clast_free (clast); timevar_pop (TV_GRAPHITE_CODE_GEN); diff --git a/gcc/graphite-dependences.c b/gcc/graphite-dependences.c index 5139e69b942..417ea2cd153 100644 --- a/gcc/graphite-dependences.c +++ b/gcc/graphite-dependences.c @@ -33,7 +33,9 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" -#include "tree-ssa.h" +#include "tree.h" +#include "gimple.h" +#include "tree-ssa-loop.h" #include "tree-pass.h" #include "cfgloop.h" #include "tree-chrec.h" @@ -583,13 +585,11 @@ loop_is_parallel_p (loop_p loop, bb_pbb_htab_type bb_pbb_mapping, int depth) { bool dependences; scop_p scop; - vec<poly_bb_p> body; - body.create (3); timevar_push (TV_GRAPHITE_DATA_DEPS); + stack_vec<poly_bb_p, 3> body; scop = get_loop_body_pbbs (loop, bb_pbb_mapping, &body); dependences = loop_level_carries_dependences (scop, body, depth); - body.release (); timevar_pop (TV_GRAPHITE_DATA_DEPS); return !dependences; diff --git a/gcc/graphite-interchange.c b/gcc/graphite-interchange.c index 289c1d9568f..36e1b55757d 100644 --- a/gcc/graphite-interchange.c +++ b/gcc/graphite-interchange.c @@ -35,7 +35,9 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" -#include "tree-ssa.h" +#include "tree.h" +#include "gimple.h" +#include "tree-ssa-loop.h" #include "dumpfile.h" #include "cfgloop.h" #include "tree-chrec.h" diff --git a/gcc/graphite-optimize-isl.c b/gcc/graphite-optimize-isl.c index b9b21566fb5..d039c1b74e1 100644 --- a/gcc/graphite-optimize-isl.c +++ b/gcc/graphite-optimize-isl.c @@ -32,7 +32,9 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" -#include "tree-ssa.h" +#include "tree.h" +#include "gimple.h" +#include "tree-ssa-loop.h" #include "dumpfile.h" #include "cfgloop.h" #include "tree-chrec.h" diff --git a/gcc/graphite-poly.c b/gcc/graphite-poly.c index 35fe3ba2342..2749555c371 100644 --- a/gcc/graphite-poly.c +++ b/gcc/graphite-poly.c @@ -35,7 +35,9 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "diagnostic-core.h" -#include "tree-ssa.h" +#include "tree.h" +#include "gimple.h" +#include "tree-ssa-loop.h" #include "dumpfile.h" #include "gimple-pretty-print.h" #include "cfgloop.h" diff --git a/gcc/graphite-scop-detection.c b/gcc/graphite-scop-detection.c index e56aa871773..f1dd455fb05 100644 --- a/gcc/graphite-scop-detection.c +++ b/gcc/graphite-scop-detection.c @@ -31,6 +31,15 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" +#include "tree.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssa-loop-manip.h" +#include "tree-ssa-loop-niter.h" +#include "tree-ssa-loop.h" +#include "tree-into-ssa.h" #include "tree-ssa.h" #include "cfgloop.h" #include "tree-chrec.h" @@ -466,8 +475,7 @@ scopdet_basic_block_info (basic_block bb, loop_p outermost_loop, case GBB_LOOP_SING_EXIT_HEADER: { - vec<sd_region> regions; - regions.create (3); + stack_vec<sd_region, 3> regions; struct scopdet_info sinfo; edge exit_e = single_exit (loop); @@ -532,8 +540,7 @@ scopdet_basic_block_info (basic_block bb, loop_p outermost_loop, { /* XXX: For now we just do not join loops with multiple exits. If the exits lead to the same bb it may be possible to join the loop. */ - vec<sd_region> regions; - regions.create (3); + stack_vec<sd_region, 3> regions; vec<edge> exits = get_loop_exit_edges (loop); edge e; int i; @@ -576,8 +583,7 @@ scopdet_basic_block_info (basic_block bb, loop_p outermost_loop, } case GBB_COND_HEADER: { - vec<sd_region> regions; - regions.create (3); + stack_vec<sd_region, 3> regions; struct scopdet_info sinfo; vec<basic_block> dominated; int i; @@ -1180,8 +1186,7 @@ print_graphite_statistics (FILE* file, vec<scop_p> scops) static void limit_scops (vec<scop_p> *scops) { - vec<sd_region> regions; - regions.create (3); + stack_vec<sd_region, 3> regions; int i; scop_p scop; @@ -1216,7 +1221,6 @@ limit_scops (vec<scop_p> *scops) create_sese_edges (regions); build_graphite_scops (regions, scops); - regions.release (); } /* Returns true when P1 and P2 are close phis with the same @@ -1395,8 +1399,7 @@ void build_scops (vec<scop_p> *scops) { struct loop *loop = current_loops->tree_root; - vec<sd_region> regions; - regions.create (3); + stack_vec<sd_region, 3> regions; canonicalize_loop_closed_ssa_form (); build_scops_1 (single_succ (ENTRY_BLOCK_PTR), ENTRY_BLOCK_PTR->loop_father, @@ -1586,7 +1589,7 @@ dot_all_scops (vec<scop_p> scops) DEBUG_FUNCTION void dot_scop (scop_p scop) { - vec<scop_p> scops = vNULL; + stack_vec<scop_p, 1> scops; if (scop) scops.safe_push (scop); @@ -1606,8 +1609,6 @@ dot_scop (scop_p scop) #else dot_all_scops_1 (stderr, scops); #endif - - scops.release (); } #endif diff --git a/gcc/graphite-sese-to-poly.c b/gcc/graphite-sese-to-poly.c index b929511c728..5a1f1bf8950 100644 --- a/gcc/graphite-sese-to-poly.c +++ b/gcc/graphite-sese-to-poly.c @@ -33,7 +33,17 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" -#include "tree-ssa.h" +#include "tree.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" +#include "tree-ssa-loop-manip.h" +#include "tree-ssa-loop-niter.h" +#include "tree-ssa-loop.h" +#include "tree-into-ssa.h" #include "tree-pass.h" #include "cfgloop.h" #include "tree-chrec.h" @@ -1220,27 +1230,18 @@ class sese_dom_walker : public dom_walker { public: sese_dom_walker (cdi_direction, sese); - ~sese_dom_walker (); virtual void before_dom_children (basic_block); virtual void after_dom_children (basic_block); private: - vec<gimple> m_conditions, m_cases; + stack_vec<gimple, 3> m_conditions, m_cases; sese m_region; }; sese_dom_walker::sese_dom_walker (cdi_direction direction, sese region) : dom_walker (direction), m_region (region) { - m_conditions.create (3); - m_cases.create (3); -} - -sese_dom_walker::~sese_dom_walker () -{ - m_conditions.release (); - m_cases.release (); } /* Call-back for dom_walk executed before visiting the dominated @@ -1879,8 +1880,7 @@ build_scop_drs (scop_p scop) int i, j; poly_bb_p pbb; data_reference_p dr; - vec<data_reference_p> drs; - drs.create (3); + stack_vec<data_reference_p, 3> drs; /* Remove all the PBBs that do not have data references: these basic blocks are not handled in the polyhedral representation. */ @@ -1978,8 +1978,7 @@ insert_stmts (scop_p scop, gimple stmt, gimple_seq stmts, gimple_stmt_iterator insert_gsi) { gimple_stmt_iterator gsi; - vec<gimple> x; - x.create (3); + stack_vec<gimple, 3> x; gimple_seq_add_stmt (&stmts, stmt); for (gsi = gsi_start (stmts); !gsi_end_p (gsi); gsi_next (&gsi)) @@ -1987,7 +1986,6 @@ insert_stmts (scop_p scop, gimple stmt, gimple_seq stmts, gsi_insert_seq_before (&insert_gsi, stmts, GSI_SAME_STMT); analyze_drs_in_stmts (scop, gsi_bb (insert_gsi), x); - x.release (); } /* Insert the assignment "RES := EXPR" just after AFTER_STMT. */ @@ -1999,8 +1997,7 @@ insert_out_of_ssa_copy (scop_p scop, tree res, tree expr, gimple after_stmt) gimple_stmt_iterator gsi; tree var = force_gimple_operand (expr, &stmts, true, NULL_TREE); gimple stmt = gimple_build_assign (unshare_expr (res), var); - vec<gimple> x; - x.create (3); + stack_vec<gimple, 3> x; gimple_seq_add_stmt (&stmts, stmt); for (gsi = gsi_start (stmts); !gsi_end_p (gsi); gsi_next (&gsi)) @@ -2018,7 +2015,6 @@ insert_out_of_ssa_copy (scop_p scop, tree res, tree expr, gimple after_stmt) } analyze_drs_in_stmts (scop, gimple_bb (after_stmt), x); - x.release (); } /* Creates a poly_bb_p for basic_block BB from the existing PBB. */ @@ -2056,8 +2052,7 @@ insert_out_of_ssa_copy_on_edge (scop_p scop, edge e, tree res, tree expr) tree var = force_gimple_operand (expr, &stmts, true, NULL_TREE); gimple stmt = gimple_build_assign (unshare_expr (res), var); basic_block bb; - vec<gimple> x; - x.create (3); + stack_vec<gimple, 3> x; gimple_seq_add_stmt (&stmts, stmt); for (gsi = gsi_start (stmts); !gsi_end_p (gsi); gsi_next (&gsi)) @@ -2074,7 +2069,6 @@ insert_out_of_ssa_copy_on_edge (scop_p scop, edge e, tree res, tree expr) new_pbb_from_pbb (scop, pbb_from_bb (e->src), bb); analyze_drs_in_stmts (scop, bb, x); - x.release (); } /* Creates a zero dimension array of the same type as VAR. */ @@ -2870,8 +2864,7 @@ remove_phi (gimple phi) tree def; use_operand_p use_p; gimple_stmt_iterator gsi; - vec<gimple> update; - update.create (3); + stack_vec<gimple, 3> update; unsigned int i; gimple stmt; @@ -2890,8 +2883,6 @@ remove_phi (gimple phi) FOR_EACH_VEC_ELT (update, i, stmt) update_stmt (stmt); - update.release (); - gsi = gsi_for_phi_node (phi); remove_phi_node (&gsi, false); } @@ -3031,18 +3022,14 @@ rewrite_commutative_reductions_out_of_ssa_close_phi (scop_p scop, gimple close_phi) { bool res; - vec<gimple> in; - in.create (10); - vec<gimple> out; - out.create (10); + stack_vec<gimple, 10> in; + stack_vec<gimple, 10> out; detect_commutative_reduction (scop, close_phi, &in, &out); res = in.length () > 1; if (res) translate_scalar_reduction_to_array (scop, in, out); - in.release (); - out.release (); return res; } diff --git a/gcc/graphite.c b/gcc/graphite.c index b26c520abcb..176c47c980e 100644 --- a/gcc/graphite.c +++ b/gcc/graphite.c @@ -47,7 +47,10 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "diagnostic-core.h" -#include "tree-ssa.h" +#include "tree.h" +#include "gimple.h" +#include "tree-cfg.h" +#include "tree-ssa-loop.h" #include "tree-dump.h" #include "cfgloop.h" #include "tree-chrec.h" diff --git a/gcc/hw-doloop.c b/gcc/hw-doloop.c index 9b59f5ddc6d..5d266387485 100644 --- a/gcc/hw-doloop.c +++ b/gcc/hw-doloop.c @@ -237,7 +237,6 @@ discover_loop (hwloop_info loop, basic_block tail_bb, rtx tail_insn, rtx reg) bool found_tail; unsigned dwork = 0; basic_block bb; - vec<basic_block> works; loop->tail = tail_bb; loop->loop_end = tail_insn; @@ -253,7 +252,7 @@ discover_loop (hwloop_info loop, basic_block tail_bb, rtx tail_insn, rtx reg) loop->head = BRANCH_EDGE (tail_bb)->dest; loop->successor = FALLTHRU_EDGE (tail_bb)->dest; - works.create (20); + stack_vec<basic_block, 20> works; works.safe_push (loop->head); found_tail = false; @@ -340,8 +339,6 @@ discover_loop (hwloop_info loop, basic_block tail_bb, rtx tail_insn, rtx reg) } } } - - works.release (); } /* Analyze the structure of the loops in the current function. Use diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c index 983efeb751b..a22f222012c 100644 --- a/gcc/internal-fn.c +++ b/gcc/internal-fn.c @@ -109,6 +109,12 @@ expand_STORE_LANES (gimple stmt) expand_insn (get_multi_vector_move (type, vec_store_lanes_optab), 2, ops); } +static void +expand_ANNOTATE (gimple stmt ATTRIBUTE_UNUSED) +{ + gcc_unreachable (); +} + /* This should get expanded in adjust_simduid_builtins. */ static void diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def index 5427664b8e3..0f5cc3cba42 100644 --- a/gcc/internal-fn.def +++ b/gcc/internal-fn.def @@ -43,3 +43,4 @@ DEF_INTERNAL_FN (STORE_LANES, ECF_CONST | ECF_LEAF) DEF_INTERNAL_FN (GOMP_SIMD_LANE, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW) DEF_INTERNAL_FN (GOMP_SIMD_VF, ECF_CONST | ECF_LEAF | ECF_NOTHROW) DEF_INTERNAL_FN (GOMP_SIMD_LAST_LANE, ECF_CONST | ECF_LEAF | ECF_NOTHROW) +DEF_INTERNAL_FN (ANNOTATE, ECF_CONST | ECF_LEAF | ECF_NOTHROW) diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c index f6f49dadc94..82d94057b77 100644 --- a/gcc/ipa-cp.c +++ b/gcc/ipa-cp.c @@ -104,11 +104,10 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "tree.h" -#include "target.h" #include "gimple.h" -#include "cgraph.h" +#include "target.h" #include "ipa-prop.h" -#include "tree-ssa.h" +#include "bitmap.h" #include "tree-pass.h" #include "flags.h" #include "diagnostic.h" @@ -353,7 +352,7 @@ print_lattice (FILE * f, struct ipcp_lattice *lat, fprintf (f, " [from:"); for (s = val->sources; s; s = s->next) - fprintf (f, " %i(%i)", s->cs->caller->symbol.order, + fprintf (f, " %i(%i)", s->cs->caller->order, s->cs->frequency); fprintf (f, "]"); } @@ -383,7 +382,7 @@ print_all_lattices (FILE * f, bool dump_sources, bool dump_benefits) info = IPA_NODE_REF (node); fprintf (f, " Node: %s/%i:\n", cgraph_node_name (node), - node->symbol.order); + node->order); count = ipa_get_param_count (info); for (i = 0; i < count; i++) { @@ -424,16 +423,16 @@ determine_versionability (struct cgraph_node *node) /* There are a number of generic reasons functions cannot be versioned. We also cannot remove parameters if there are type attributes such as fnspec present. */ - if (node->symbol.alias || node->thunk.thunk_p) + if (node->alias || node->thunk.thunk_p) reason = "alias or thunk"; else if (!node->local.versionable) reason = "not a tree_versionable_function"; else if (cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE) reason = "insufficient body availability"; - if (reason && dump_file && !node->symbol.alias && !node->thunk.thunk_p) + if (reason && dump_file && !node->alias && !node->thunk.thunk_p) fprintf (dump_file, "Function %s/%i is not versionable, reason: %s.\n", - cgraph_node_name (node), node->symbol.order, reason); + cgraph_node_name (node), node->order, reason); node->local.versionable = (reason == NULL); } @@ -509,7 +508,7 @@ ipcp_cloning_candidate_p (struct cgraph_node *node) return false; } - if (!optimize_function_for_speed_p (DECL_STRUCT_FUNCTION (node->symbol.decl))) + if (!optimize_function_for_speed_p (DECL_STRUCT_FUNCTION (node->decl))) { if (dump_file) fprintf (dump_file, "Not considering %s for cloning; " @@ -711,9 +710,9 @@ initialize_node_lattices (struct cgraph_node *node) set_all_contains_variable (plats); } if (dump_file && (dump_flags & TDF_DETAILS) - && !node->symbol.alias && !node->thunk.thunk_p) + && !node->alias && !node->thunk.thunk_p) fprintf (dump_file, "Marking all lattices of %s/%i as %s\n", - cgraph_node_name (node), node->symbol.order, + cgraph_node_name (node), node->order, disable ? "BOTTOM" : "VARIABLE"); } @@ -1406,7 +1405,7 @@ propagate_constants_accross_call (struct cgraph_edge *cs) int i, args_count, parms_count; callee = cgraph_function_node (cs->callee, &availability); - if (!callee->symbol.definition) + if (!callee->definition) return false; gcc_checking_assert (cgraph_function_with_gimple_body_p (callee)); callee_info = IPA_NODE_REF (callee); @@ -1419,7 +1418,7 @@ propagate_constants_accross_call (struct cgraph_edge *cs) parameter. However, we might need to uncover a thunk from below a series of aliases first. */ alias_or_thunk = cs->callee; - while (alias_or_thunk->symbol.alias) + while (alias_or_thunk->alias) alias_or_thunk = cgraph_alias_target (alias_or_thunk); if (alias_or_thunk->thunk.thunk_p) { @@ -1598,7 +1597,7 @@ devirtualization_time_bonus (struct cgraph_node *node, /* Only bare minimum benefit for clearly un-inlineable targets. */ res += 1; callee = cgraph_get_node (target); - if (!callee || !callee->symbol.definition) + if (!callee || !callee->definition) continue; isummary = inline_summary (callee); if (!isummary->inlinable) @@ -1611,7 +1610,7 @@ devirtualization_time_bonus (struct cgraph_node *node, else if (isummary->size <= MAX_INLINE_INSNS_AUTO / 2) res += 15; else if (isummary->size <= MAX_INLINE_INSNS_AUTO - || DECL_DECLARED_INLINE_P (callee->symbol.decl)) + || DECL_DECLARED_INLINE_P (callee->decl)) res += 7; } @@ -1641,7 +1640,7 @@ good_cloning_opportunity_p (struct cgraph_node *node, int time_benefit, { if (time_benefit == 0 || !flag_ipa_cp_clone - || !optimize_function_for_speed_p (DECL_STRUCT_FUNCTION (node->symbol.decl))) + || !optimize_function_for_speed_p (DECL_STRUCT_FUNCTION (node->decl))) return false; gcc_assert (size_cost > 0); @@ -1818,7 +1817,7 @@ estimate_local_effects (struct cgraph_node *node) if (dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, "\nEstimating effects for %s/%i, base_time: %i.\n", - cgraph_node_name (node), node->symbol.order, base_time); + cgraph_node_name (node), node->order, base_time); always_const = gather_context_independent_values (info, &known_csts, &known_binfos, &known_aggs, @@ -2220,7 +2219,7 @@ ipcp_propagate_stage (struct topo_info *topo) ipa_get_param_count (info)); initialize_node_lattices (node); } - if (node->symbol.definition && !node->symbol.alias) + if (node->definition && !node->alias) overall_size += inline_summary (node)->self_size; if (node->count > max_count) max_count = node->count; @@ -2288,8 +2287,8 @@ ipcp_discover_new_direct_edges (struct cgraph_node *node, fprintf (dump_file, " controlled uses count of param " "%i bumped down to %i\n", param_index, c); if (c == 0 - && (to_del = ipa_find_reference ((symtab_node) node, - (symtab_node) cs->callee, + && (to_del = ipa_find_reference (node, + cs->callee, NULL, 0))) { if (dump_file && (dump_flags & TDF_DETAILS)) @@ -2545,7 +2544,7 @@ update_profiling_info (struct cgraph_node *orig_node, fprintf (dump_file, " Problem: node %s/%i has too low count " HOST_WIDE_INT_PRINT_DEC " while the sum of incoming " "counts is " HOST_WIDE_INT_PRINT_DEC "\n", - cgraph_node_name (orig_node), orig_node->symbol.order, + cgraph_node_name (orig_node), orig_node->order, (HOST_WIDE_INT) orig_node_count, (HOST_WIDE_INT) (orig_sum + new_sum)); @@ -2678,13 +2677,13 @@ create_specialized_node (struct cgraph_node *node, args_to_skip, "constprop"); ipa_set_node_agg_value_chain (new_node, aggvals); for (av = aggvals; av; av = av->next) - ipa_maybe_record_reference ((symtab_node) new_node, av->value, + ipa_maybe_record_reference (new_node, av->value, IPA_REF_ADDR, NULL); if (dump_file && (dump_flags & TDF_DETAILS)) { fprintf (dump_file, " the new node is %s/%i.\n", - cgraph_node_name (new_node), new_node->symbol.order); + cgraph_node_name (new_node), new_node->order); if (aggvals) ipa_dump_agg_replacement_values (dump_file, aggvals); } @@ -3237,9 +3236,9 @@ perhaps_add_new_callers (struct cgraph_node *node, struct ipcp_value *val) fprintf (dump_file, " - adding an extra caller %s/%i" " of %s/%i\n", xstrdup (cgraph_node_name (cs->caller)), - cs->caller->symbol.order, + cs->caller->order, xstrdup (cgraph_node_name (val->spec_node)), - val->spec_node->symbol.order); + val->spec_node->order); cgraph_redirect_edge_callee (cs, val->spec_node); redirected_sum += cs->count; @@ -3343,7 +3342,7 @@ decide_about_value (struct cgraph_node *node, int index, HOST_WIDE_INT offset, if (dump_file) fprintf (dump_file, " Creating a specialized node of %s/%i.\n", - cgraph_node_name (node), node->symbol.order); + cgraph_node_name (node), node->order); callers = gather_edges_for_value (val, caller_count); kv = known_csts.copy (); @@ -3380,7 +3379,7 @@ decide_whether_version_node (struct cgraph_node *node) if (dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, "\nEvaluating opportunities for %s/%i.\n", - cgraph_node_name (node), node->symbol.order); + cgraph_node_name (node), node->order); gather_context_independent_values (info, &known_csts, &known_binfos, info->do_clone_for_all_contexts ? &known_aggs @@ -3424,7 +3423,7 @@ decide_whether_version_node (struct cgraph_node *node) if (dump_file) fprintf (dump_file, " - Creating a specialized node of %s/%i " "for all known contexts.\n", cgraph_node_name (node), - node->symbol.order); + node->order); callers = collect_callers_of_node (node); move_binfos_to_values (known_csts, known_binfos); @@ -3499,23 +3498,23 @@ static void identify_dead_nodes (struct cgraph_node *node) { struct cgraph_node *v; - for (v = node; v ; v = ((struct ipa_dfs_info *) v->symbol.aux)->next_cycle) + for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle) if (cgraph_will_be_removed_from_program_if_no_direct_calls (v) && !cgraph_for_node_and_aliases (v, has_undead_caller_from_outside_scc_p, NULL, true)) IPA_NODE_REF (v)->node_dead = 1; - for (v = node; v ; v = ((struct ipa_dfs_info *) v->symbol.aux)->next_cycle) + for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle) if (!IPA_NODE_REF (v)->node_dead) spread_undeadness (v); if (dump_file && (dump_flags & TDF_DETAILS)) { - for (v = node; v ; v = ((struct ipa_dfs_info *) v->symbol.aux)->next_cycle) + for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle) if (IPA_NODE_REF (v)->node_dead) fprintf (dump_file, " Marking node as dead: %s/%i.\n", - cgraph_node_name (v), v->symbol.order); + cgraph_node_name (v), v->order); } } @@ -3539,7 +3538,7 @@ ipcp_decision_stage (struct topo_info *topo) { struct cgraph_node *v; iterate = false; - for (v = node; v ; v = ((struct ipa_dfs_info *) v->symbol.aux)->next_cycle) + for (v = node; v ; v = ((struct ipa_dfs_info *) v->aux)->next_cycle) if (cgraph_function_with_gimple_body_p (v) && ipcp_versionable_function_p (v)) iterate |= decide_whether_version_node (v); @@ -3612,7 +3611,7 @@ ipcp_generate_summary (void) FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node) { node->local.versionable - = tree_versionable_function_p (node->symbol.decl); + = tree_versionable_function_p (node->decl); ipa_analyze_node (node); } } diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c index 5f071f10645..4877816f9d6 100644 --- a/gcc/ipa-devirt.c +++ b/gcc/ipa-devirt.c @@ -109,6 +109,7 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "tm.h" +#include "tree.h" #include "cgraph.h" #include "tree-pass.h" #include "ggc.h" @@ -543,9 +544,9 @@ build_type_inheritance_graph (void) /* We reconstruct the graph starting of types of all methods seen in the the unit. */ FOR_EACH_FUNCTION (n) - if (DECL_VIRTUAL_P (n->symbol.decl) - && symtab_real_symbol_p ((symtab_node)n)) - get_odr_type (method_class_type (TREE_TYPE (n->symbol.decl)), true); + if (DECL_VIRTUAL_P (n->decl) + && symtab_real_symbol_p (n)) + get_odr_type (method_class_type (TREE_TYPE (n->decl)), true); if (inheritance_dump_file) { dump_type_inheritance_graph (inheritance_dump_file); @@ -571,8 +572,8 @@ maybe_record_node (vec <cgraph_node *> &nodes, && !pointer_set_insert (inserted, target) && (target_node = cgraph_get_node (target)) != NULL && (TREE_PUBLIC (target) - || target_node->symbol.definition) - && symtab_real_symbol_p ((symtab_node)target_node)) + || target_node->definition) + && symtab_real_symbol_p (target_node)) { pointer_set_insert (cached_polymorphic_call_targets, target_node); @@ -626,7 +627,7 @@ record_binfo (vec <cgraph_node *> &nodes, if (TREE_CODE (vtable) == POINTER_PLUS_EXPR) vtable = TREE_OPERAND (TREE_OPERAND (vtable, 0), 0); vnode = varpool_get_node (vtable); - if (!vnode || !vnode->symbol.definition) + if (!vnode || !vnode->definition) return; } tree target = gimple_get_virt_method_for_binfo (otr_token, type_binfo); @@ -760,8 +761,8 @@ devirt_variable_node_removal_hook (struct varpool_node *n, void *d ATTRIBUTE_UNUSED) { if (cached_polymorphic_call_targets - && DECL_VIRTUAL_P (n->symbol.decl) - && type_in_anonymous_namespace_p (DECL_CONTEXT (n->symbol.decl))) + && DECL_VIRTUAL_P (n->decl) + && type_in_anonymous_namespace_p (DECL_CONTEXT (n->decl))) free_polymorphic_call_targets_hash (); } @@ -890,7 +891,7 @@ dump_possible_polymorphic_call_targets (FILE *f, final ? " (full list)" : " (partial list, may call to other unit)"); for (i = 0; i < targets.length (); i++) fprintf (f, " %s/%i", cgraph_node_name (targets[i]), - targets[i]->symbol.order); + targets[i]->order); fprintf (f, "\n"); } @@ -916,7 +917,7 @@ possible_polymorphic_call_target_p (tree otr_type, /* At a moment we allow middle end to dig out new external declarations as a targets of polymorphic calls. */ - if (!final && !n->symbol.definition) + if (!final && !n->definition) return true; return false; } @@ -937,10 +938,10 @@ update_type_inheritance_graph (void) /* We reconstruct the graph starting of types of all methods seen in the the unit. */ FOR_EACH_FUNCTION (n) - if (DECL_VIRTUAL_P (n->symbol.decl) - && !n->symbol.definition - && symtab_real_symbol_p ((symtab_node)n)) - get_odr_type (method_class_type (TREE_TYPE (n->symbol.decl)), true); + if (DECL_VIRTUAL_P (n->decl) + && !n->definition + && symtab_real_symbol_p (n)) + get_odr_type (method_class_type (TREE_TYPE (n->decl)), true); timevar_pop (TV_IPA_INHERITANCE); } @@ -954,13 +955,13 @@ likely_target_p (struct cgraph_node *n) { int flags; /* cxa_pure_virtual and similar things are not likely. */ - if (TREE_CODE (TREE_TYPE (n->symbol.decl)) != METHOD_TYPE) + if (TREE_CODE (TREE_TYPE (n->decl)) != METHOD_TYPE) return false; - flags = flags_from_decl_or_type (n->symbol.decl); + flags = flags_from_decl_or_type (n->decl); if (flags & ECF_NORETURN) return false; if (lookup_attribute ("cold", - DECL_ATTRIBUTES (n->symbol.decl))) + DECL_ATTRIBUTES (n->decl))) return false; if (n->frequency < NODE_FREQUENCY_NORMAL) return false; @@ -987,7 +988,7 @@ ipa_devirt (void) bool update = false; if (dump_file && n->indirect_calls) fprintf (dump_file, "\n\nProcesing function %s/%i\n", - cgraph_node_name (n), n->symbol.order); + cgraph_node_name (n), n->order); for (e = n->indirect_calls; e; e = e->next_callee) if (e->indirect_info->polymorphic) { @@ -1068,7 +1069,7 @@ ipa_devirt (void) } continue; } - if (!likely_target->symbol.definition) + if (!likely_target->definition) { if (dump_file) fprintf (dump_file, "Target is not an definition\n"); @@ -1079,7 +1080,7 @@ ipa_devirt (void) can handle these just well, it is common for programs to incorrectly with headers defining methods they are linked with. */ - if (DECL_EXTERNAL (likely_target->symbol.decl)) + if (DECL_EXTERNAL (likely_target->decl)) { if (dump_file) fprintf (dump_file, "Target is external\n"); @@ -1088,7 +1089,7 @@ ipa_devirt (void) } if (cgraph_function_body_availability (likely_target) <= AVAIL_OVERWRITABLE - && symtab_can_be_discarded ((symtab_node) likely_target)) + && symtab_can_be_discarded (likely_target)) { if (dump_file) fprintf (dump_file, "Target is overwritable\n"); @@ -1100,14 +1101,14 @@ ipa_devirt (void) if (dump_file) fprintf (dump_file, "Speculatively devirtualizing call in %s/%i to %s/%i\n", - cgraph_node_name (n), n->symbol.order, + cgraph_node_name (n), n->order, cgraph_node_name (likely_target), - likely_target->symbol.order); - if (!symtab_can_be_discarded ((symtab_node) likely_target)) + likely_target->order); + if (!symtab_can_be_discarded (likely_target)) { cgraph_node *alias; alias = cgraph (symtab_nonoverwritable_alias - ((symtab_node)likely_target)); + (likely_target)); if (alias) likely_target = alias; } diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c index 304f9f5d7cc..445872387d8 100644 --- a/gcc/ipa-inline-analysis.c +++ b/gcc/ipa-inline-analysis.c @@ -72,14 +72,20 @@ along with GCC; see the file COPYING3. If not see #include "tree-inline.h" #include "langhooks.h" #include "flags.h" -#include "cgraph.h" #include "diagnostic.h" #include "gimple-pretty-print.h" #include "params.h" #include "tree-pass.h" #include "coverage.h" #include "ggc.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" +#include "tree-ssa-loop-niter.h" +#include "tree-ssa-loop.h" #include "ipa-prop.h" #include "lto-streamer.h" #include "data-streamer.h" @@ -89,6 +95,7 @@ along with GCC; see the file COPYING3. If not see #include "cfgloop.h" #include "tree-scalar-evolution.h" #include "ipa-utils.h" +#include "cilk.h" /* Estimate runtime of function can easilly run into huge numbers with many nested loops. Be sure we can compute time * INLINE_SIZE_SCALE * 2 in an @@ -1292,7 +1299,7 @@ dump_inline_edge_summary (FILE *f, int indent, struct cgraph_node *node, fprintf (f, "%*s%s/%i %s\n%*s loop depth:%2i freq:%4i size:%2i" " time: %2i callee size:%2i stack:%2i", - indent, "", cgraph_node_name (callee), callee->symbol.order, + indent, "", cgraph_node_name (callee), callee->order, !edge->inline_failed ? "inlined" : cgraph_inline_failed_string (edge-> inline_failed), indent, "", es->loop_depth, edge->frequency, @@ -1352,14 +1359,14 @@ dump_inline_edge_summary (FILE *f, int indent, struct cgraph_node *node, void dump_inline_summary (FILE *f, struct cgraph_node *node) { - if (node->symbol.definition) + if (node->definition) { struct inline_summary *s = inline_summary (node); size_time_entry *e; int i; fprintf (f, "Inline summary for %s/%i", cgraph_node_name (node), - node->symbol.order); - if (DECL_DISREGARD_INLINE_LIMITS (node->symbol.decl)) + node->order); + if (DECL_DISREGARD_INLINE_LIMITS (node->decl)) fprintf (f, " always_inline"); if (s->inlinable) fprintf (f, " inlinable"); @@ -1428,12 +1435,15 @@ initialize_inline_failed (struct cgraph_edge *e) if (e->indirect_unknown_callee) e->inline_failed = CIF_INDIRECT_UNKNOWN_CALL; - else if (!callee->symbol.definition) + else if (!callee->definition) e->inline_failed = CIF_BODY_NOT_AVAILABLE; else if (callee->local.redefined_extern_inline) e->inline_failed = CIF_REDEFINED_EXTERN_INLINE; else if (e->call_stmt_cannot_inline_p) e->inline_failed = CIF_MISMATCHED_ARGUMENTS; + else if (cfun && fn_contains_cilk_spawn_p (cfun)) + /* We can't inline if the function is spawing a function. */ + e->inline_failed = CIF_FUNCTION_NOT_INLINABLE; else e->inline_failed = CIF_FUNCTION_NOT_CONSIDERED; } @@ -1815,7 +1825,7 @@ compute_bb_predicates (struct cgraph_node *node, struct ipa_node_params *parms_info, struct inline_summary *summary) { - struct function *my_function = DECL_STRUCT_FUNCTION (node->symbol.decl); + struct function *my_function = DECL_STRUCT_FUNCTION (node->decl); bool done = false; basic_block bb; @@ -2342,7 +2352,7 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early) <0,2>. */ basic_block bb; gimple_stmt_iterator bsi; - struct function *my_function = DECL_STRUCT_FUNCTION (node->symbol.decl); + struct function *my_function = DECL_STRUCT_FUNCTION (node->decl); int freq; struct inline_summary *info = inline_summary (node); struct predicate bb_predicate; @@ -2390,7 +2400,7 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early) for (n = 0; n < nblocks; n++) { bb = BASIC_BLOCK (order[n]); - freq = compute_call_stmt_bb_frequency (node->symbol.decl, bb); + freq = compute_call_stmt_bb_frequency (node->decl, bb); /* TODO: Obviously predicates can be propagated down across CFG. */ if (parms_info) @@ -2737,7 +2747,7 @@ compute_inline_parameters (struct cgraph_node *node, bool early) } /* Even is_gimple_min_invariant rely on current_function_decl. */ - push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl)); + push_cfun (DECL_STRUCT_FUNCTION (node->decl)); /* Estimate the stack size for the function if we're optimizing. */ self_stack_size = optimize ? estimated_stack_frame_size (node) : 0; @@ -2747,13 +2757,13 @@ compute_inline_parameters (struct cgraph_node *node, bool early) /* Can this function be inlined at all? */ if (!optimize && !lookup_attribute ("always_inline", - DECL_ATTRIBUTES (node->symbol.decl))) + DECL_ATTRIBUTES (node->decl))) info->inlinable = false; else - info->inlinable = tree_inlinable_function_p (node->symbol.decl); + info->inlinable = tree_inlinable_function_p (node->decl); /* Type attributes can use parameter indices to describe them. */ - if (TYPE_ATTRIBUTES (TREE_TYPE (node->symbol.decl))) + if (TYPE_ATTRIBUTES (TREE_TYPE (node->decl))) node->local.can_change_signature = false; else { @@ -2765,7 +2775,7 @@ compute_inline_parameters (struct cgraph_node *node, bool early) /* Functions calling builtin_apply can not change signature. */ for (e = node->callees; e; e = e->next_callee) { - tree cdecl = e->callee->symbol.decl; + tree cdecl = e->callee->decl; if (DECL_BUILT_IN (cdecl) && DECL_BUILT_IN_CLASS (cdecl) == BUILT_IN_NORMAL && (DECL_FUNCTION_CODE (cdecl) == BUILT_IN_APPLY_ARGS @@ -2873,7 +2883,7 @@ estimate_edge_devirt_benefit (struct cgraph_edge *ie, gcc_checking_assert (*size >= 0); callee = cgraph_get_node (target); - if (!callee || !callee->symbol.definition) + if (!callee || !callee->definition) return false; isummary = inline_summary (callee); return isummary->inlinable; @@ -2979,7 +2989,7 @@ estimate_node_size_and_time (struct cgraph_node *node, bool found = false; fprintf (dump_file, " Estimating body: %s/%i\n" " Known to be false: ", cgraph_node_name (node), - node->symbol.order); + node->order); for (i = predicate_not_inlined_condition; i < (predicate_first_dynamic_condition @@ -3030,7 +3040,7 @@ estimate_node_size_and_time (struct cgraph_node *node, hints |= INLINE_HINT_array_index; if (info->scc_no) hints |= INLINE_HINT_in_scc; - if (DECL_DECLARED_INLINE_P (node->symbol.decl)) + if (DECL_DECLARED_INLINE_P (node->decl)) hints |= INLINE_HINT_declared_inline; estimate_calls_size_and_time (node, &size, &time, &hints, possible_truths, @@ -3490,8 +3500,8 @@ simple_edge_hints (struct cgraph_edge *edge) && !cgraph_edge_recursive_p (edge)) hints |= INLINE_HINT_same_scc; - if (to->symbol.lto_file_data && edge->callee->symbol.lto_file_data - && to->symbol.lto_file_data != edge->callee->symbol.lto_file_data) + if (to->lto_file_data && edge->callee->lto_file_data + && to->lto_file_data != edge->callee->lto_file_data) hints |= INLINE_HINT_cross_module; return hints; @@ -3710,7 +3720,7 @@ do_estimate_growth (struct cgraph_node *node) return zero or negative growths. */ if (d.self_recursive) d.growth = d.growth < info->size ? info->size : d.growth; - else if (DECL_EXTERNAL (node->symbol.decl)) + else if (DECL_EXTERNAL (node->decl)) ; else { @@ -3719,7 +3729,7 @@ do_estimate_growth (struct cgraph_node *node) /* COMDAT functions are very often not shared across multiple units since they come from various template instantiations. Take this into account. */ - else if (DECL_COMDAT (node->symbol.decl) + else if (DECL_COMDAT (node->decl) && cgraph_can_remove_if_no_direct_calls_p (node)) d.growth -= (info->size * (100 - PARAM_VALUE (PARAM_COMDAT_SHARING_PROBABILITY)) @@ -3756,11 +3766,11 @@ inline_indirect_intraprocedural_analysis (struct cgraph_node *node) static void inline_analyze_function (struct cgraph_node *node) { - push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl)); + push_cfun (DECL_STRUCT_FUNCTION (node->decl)); if (dump_file) fprintf (dump_file, "\nAnalyzing function: %s/%u\n", - cgraph_node_name (node), node->symbol.order); + cgraph_node_name (node), node->order); if (optimize && !node->thunk.thunk_p) inline_indirect_intraprocedural_analysis (node); compute_inline_parameters (node, false); @@ -3813,7 +3823,7 @@ inline_generate_summary (void) inline_free_summary (); FOR_EACH_DEFINED_FUNCTION (node) - if (!node->symbol.alias) + if (!node->alias) inline_analyze_function (node); } @@ -4045,18 +4055,18 @@ inline_write_summary (void) for (i = 0; i < lto_symtab_encoder_size (encoder); i++) { - symtab_node snode = lto_symtab_encoder_deref (encoder, i); + symtab_node *snode = lto_symtab_encoder_deref (encoder, i); cgraph_node *cnode = dyn_cast <cgraph_node> (snode); - if (cnode && cnode->symbol.definition && !cnode->symbol.alias) + if (cnode && cnode->definition && !cnode->alias) count++; } streamer_write_uhwi (ob, count); for (i = 0; i < lto_symtab_encoder_size (encoder); i++) { - symtab_node snode = lto_symtab_encoder_deref (encoder, i); + symtab_node *snode = lto_symtab_encoder_deref (encoder, i); cgraph_node *cnode = dyn_cast <cgraph_node> (snode); - if (cnode && (node = cnode)->symbol.definition && !node->symbol.alias) + if (cnode && (node = cnode)->definition && !node->alias) { struct inline_summary *info = inline_summary (node); struct bitpack_d bp; @@ -4067,7 +4077,7 @@ inline_write_summary (void) streamer_write_uhwi (ob, lto_symtab_encoder_encode (encoder, - (symtab_node) + node)); streamer_write_hwi (ob, info->estimated_self_stack_size); streamer_write_hwi (ob, info->self_size); diff --git a/gcc/ipa-inline-transform.c b/gcc/ipa-inline-transform.c index d8a637cb850..32f068e460e 100644 --- a/gcc/ipa-inline-transform.c +++ b/gcc/ipa-inline-transform.c @@ -34,11 +34,10 @@ along with GCC; see the file COPYING3. If not see #include "tm.h" #include "tree.h" #include "langhooks.h" -#include "cgraph.h" #include "intl.h" #include "coverage.h" #include "ggc.h" -#include "tree-ssa.h" +#include "tree-cfg.h" #include "ipa-prop.h" #include "ipa-inline.h" #include "tree-inline.h" @@ -86,15 +85,15 @@ can_remove_node_now_p_1 (struct cgraph_node *node) /* FIXME: When address is taken of DECL_EXTERNAL function we still can remove its offline copy, but we would need to keep unanalyzed node in the callgraph so references can point to it. */ - return (!node->symbol.address_taken - && !ipa_ref_has_aliases_p (&node->symbol.ref_list) + return (!node->address_taken + && !ipa_ref_has_aliases_p (&node->ref_list) && !node->used_as_abstract_origin && cgraph_can_remove_if_no_direct_calls_p (node) /* Inlining might enable more devirtualizing, so we want to remove those only after all devirtualizable virtual calls are processed. Lacking may edges in callgraph we just preserve them post inlining. */ - && !DECL_VIRTUAL_P (node->symbol.decl) + && !DECL_VIRTUAL_P (node->decl) /* During early inlining some unanalyzed cgraph nodes might be in the callgraph and they might reffer the function in question. */ && !cgraph_new_nodes); @@ -113,10 +112,10 @@ can_remove_node_now_p (struct cgraph_node *node, struct cgraph_edge *e) /* When we see same comdat group, we need to be sure that all items can be removed. */ - if (!node->symbol.same_comdat_group) + if (!node->same_comdat_group) return true; - for (next = cgraph (node->symbol.same_comdat_group); - next != node; next = cgraph (next->symbol.same_comdat_group)) + for (next = cgraph (node->same_comdat_group); + next != node; next = cgraph (next->same_comdat_group)) if ((next->callers && next->callers != e) || !can_remove_node_now_p_1 (next)) return false; @@ -162,28 +161,28 @@ clone_inlined_nodes (struct cgraph_edge *e, bool duplicate, For now we keep the ohter functions in the group in program until cgraph_remove_unreachable_functions gets rid of them. */ gcc_assert (!e->callee->global.inlined_to); - symtab_dissolve_same_comdat_group_list ((symtab_node) e->callee); - if (e->callee->symbol.definition && !DECL_EXTERNAL (e->callee->symbol.decl)) + symtab_dissolve_same_comdat_group_list (e->callee); + if (e->callee->definition && !DECL_EXTERNAL (e->callee->decl)) { if (overall_size) *overall_size -= inline_summary (e->callee)->size; nfunctions_inlined++; } duplicate = false; - e->callee->symbol.externally_visible = false; + e->callee->externally_visible = false; update_noncloned_frequencies (e->callee, e->frequency); } else { struct cgraph_node *n; - n = cgraph_clone_node (e->callee, e->callee->symbol.decl, + n = cgraph_clone_node (e->callee, e->callee->decl, e->count, e->frequency, update_original, vNULL, true, inlining_into); cgraph_redirect_edge_callee (e, n); } } else - symtab_dissolve_same_comdat_group_list ((symtab_node) e->callee); + symtab_dissolve_same_comdat_group_list (e->callee); e->callee->global.inlined_to = inlining_into; @@ -235,7 +234,7 @@ inline_call (struct cgraph_edge *e, bool update_original, gcc_assert (!callee->global.inlined_to); e->inline_failed = CIF_OK; - DECL_POSSIBLY_INLINED (callee->symbol.decl) = true; + DECL_POSSIBLY_INLINED (callee->decl) = true; to = e->caller; if (to->global.inlined_to) @@ -287,7 +286,7 @@ inline_call (struct cgraph_edge *e, bool update_original, /* Account the change of overall unit size; external functions will be removed and are thus not accounted. */ if (overall_size - && !DECL_EXTERNAL (to->symbol.decl)) + && !DECL_EXTERNAL (to->decl)) *overall_size += new_size - old_size; ncalls_inlined++; @@ -313,13 +312,13 @@ save_inline_function_body (struct cgraph_node *node) fprintf (dump_file, "\nSaving body of %s for later reuse\n", cgraph_node_name (node)); - gcc_assert (node == cgraph_get_node (node->symbol.decl)); + gcc_assert (node == cgraph_get_node (node->decl)); /* first_clone will be turned into real function. */ first_clone = node->clones; - first_clone->symbol.decl = copy_node (node->symbol.decl); - symtab_insert_node_to_hashtable ((symtab_node) first_clone); - gcc_assert (first_clone == cgraph_get_node (first_clone->symbol.decl)); + first_clone->decl = copy_node (node->decl); + symtab_insert_node_to_hashtable (first_clone); + gcc_assert (first_clone == cgraph_get_node (first_clone->decl)); /* Now reshape the clone tree, so all other clones descends from first_clone. */ @@ -347,8 +346,8 @@ save_inline_function_body (struct cgraph_node *node) if (first_clone->clones) for (n = first_clone->clones; n != first_clone;) { - gcc_assert (n->symbol.decl == node->symbol.decl); - n->symbol.decl = first_clone->symbol.decl; + gcc_assert (n->decl == node->decl); + n->decl = first_clone->decl; if (n->clones) n = n->clones; else if (n->next_sibling_clone) @@ -363,16 +362,16 @@ save_inline_function_body (struct cgraph_node *node) } /* Copy the OLD_VERSION_NODE function tree to the new version. */ - tree_function_versioning (node->symbol.decl, first_clone->symbol.decl, + tree_function_versioning (node->decl, first_clone->decl, NULL, true, NULL, false, NULL, NULL); /* The function will be short lived and removed after we inline all the clones, but make it internal so we won't confuse ourself. */ - DECL_EXTERNAL (first_clone->symbol.decl) = 0; - DECL_COMDAT_GROUP (first_clone->symbol.decl) = NULL_TREE; - TREE_PUBLIC (first_clone->symbol.decl) = 0; - DECL_COMDAT (first_clone->symbol.decl) = 0; + DECL_EXTERNAL (first_clone->decl) = 0; + DECL_COMDAT_GROUP (first_clone->decl) = NULL_TREE; + TREE_PUBLIC (first_clone->decl) = 0; + DECL_COMDAT (first_clone->decl) = 0; first_clone->ipa_transforms_to_apply.release (); /* When doing recursive inlining, the clone may become unnecessary. @@ -398,7 +397,7 @@ static bool preserve_function_body_p (struct cgraph_node *node) { gcc_assert (cgraph_global_info_ready); - gcc_assert (!node->symbol.alias && !node->thunk.thunk_p); + gcc_assert (!node->alias && !node->thunk.thunk_p); /* Look if there is any clone around. */ if (node->clones) @@ -429,7 +428,7 @@ inline_transform (struct cgraph_node *node) next = e->next_callee; cgraph_redirect_edge_call_stmt_to_callee (e); } - ipa_remove_all_references (&node->symbol.ref_list); + ipa_remove_all_references (&node->ref_list); timevar_push (TV_INTEGRATION); if (node->callees && optimize) diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c index 4822c38ca58..f4cb72a9c2b 100644 --- a/gcc/ipa-inline.c +++ b/gcc/ipa-inline.c @@ -97,7 +97,6 @@ along with GCC; see the file COPYING3. If not see #include "tree-inline.h" #include "langhooks.h" #include "flags.h" -#include "cgraph.h" #include "diagnostic.h" #include "gimple-pretty-print.h" #include "params.h" @@ -107,13 +106,16 @@ along with GCC; see the file COPYING3. If not see #include "coverage.h" #include "ggc.h" #include "rtl.h" -#include "tree-ssa.h" +#include "bitmap.h" +#include "gimple.h" +#include "gimple-ssa.h" #include "ipa-prop.h" #include "except.h" #include "target.h" #include "ipa-inline.h" #include "ipa-utils.h" #include "sreal.h" +#include "cilk.h" /* Statistics we collect about inlining algorithm. */ static int overall_size; @@ -220,8 +222,8 @@ report_inline_failed_reason (struct cgraph_edge *e) if (dump_file) { fprintf (dump_file, " not inlinable: %s/%i -> %s/%i, %s\n", - xstrdup (cgraph_node_name (e->caller)), e->caller->symbol.order, - xstrdup (cgraph_node_name (e->callee)), e->callee->symbol.order, + xstrdup (cgraph_node_name (e->caller)), e->caller->order, + xstrdup (cgraph_node_name (e->callee)), e->callee->order, cgraph_inline_failed_string (e->inline_failed)); } } @@ -243,27 +245,28 @@ can_inline_edge_p (struct cgraph_edge *e, bool report, enum availability avail; struct cgraph_node *callee = cgraph_function_or_thunk_node (e->callee, &avail); - tree caller_tree = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (e->caller->symbol.decl); + tree caller_tree = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (e->caller->decl); tree callee_tree - = callee ? DECL_FUNCTION_SPECIFIC_OPTIMIZATION (callee->symbol.decl) : NULL; - struct function *caller_cfun = DECL_STRUCT_FUNCTION (e->caller->symbol.decl); + = callee ? DECL_FUNCTION_SPECIFIC_OPTIMIZATION (callee->decl) : NULL; + struct function *caller_cfun = DECL_STRUCT_FUNCTION (e->caller->decl); struct function *callee_cfun - = callee ? DECL_STRUCT_FUNCTION (callee->symbol.decl) : NULL; + = callee ? DECL_STRUCT_FUNCTION (callee->decl) : NULL; if (!caller_cfun && e->caller->clone_of) - caller_cfun = DECL_STRUCT_FUNCTION (e->caller->clone_of->symbol.decl); + caller_cfun = DECL_STRUCT_FUNCTION (e->caller->clone_of->decl); if (!callee_cfun && callee && callee->clone_of) - callee_cfun = DECL_STRUCT_FUNCTION (callee->clone_of->symbol.decl); + callee_cfun = DECL_STRUCT_FUNCTION (callee->clone_of->decl); gcc_assert (e->inline_failed); - if (!callee || !callee->symbol.definition) + if (!callee || !callee->definition) { e->inline_failed = CIF_BODY_NOT_AVAILABLE; inlinable = false; } - else if (!inline_summary (callee)->inlinable) + else if (!inline_summary (callee)->inlinable + || (caller_cfun && fn_contains_cilk_spawn_p (caller_cfun))) { e->inline_failed = CIF_FUNCTION_NOT_INLINABLE; inlinable = false; @@ -280,18 +283,18 @@ can_inline_edge_p (struct cgraph_edge *e, bool report, inlinable = false; } /* Don't inline if the functions have different EH personalities. */ - else if (DECL_FUNCTION_PERSONALITY (e->caller->symbol.decl) - && DECL_FUNCTION_PERSONALITY (callee->symbol.decl) - && (DECL_FUNCTION_PERSONALITY (e->caller->symbol.decl) - != DECL_FUNCTION_PERSONALITY (callee->symbol.decl))) + else if (DECL_FUNCTION_PERSONALITY (e->caller->decl) + && DECL_FUNCTION_PERSONALITY (callee->decl) + && (DECL_FUNCTION_PERSONALITY (e->caller->decl) + != DECL_FUNCTION_PERSONALITY (callee->decl))) { e->inline_failed = CIF_EH_PERSONALITY; inlinable = false; } /* TM pure functions should not be inlined into non-TM_pure functions. */ - else if (is_tm_pure (callee->symbol.decl) - && !is_tm_pure (e->caller->symbol.decl)) + else if (is_tm_pure (callee->decl) + && !is_tm_pure (e->caller->decl)) { e->inline_failed = CIF_UNSPECIFIED; inlinable = false; @@ -307,20 +310,20 @@ can_inline_edge_p (struct cgraph_edge *e, bool report, inlinable = false; } /* Check compatibility of target optimization options. */ - else if (!targetm.target_option.can_inline_p (e->caller->symbol.decl, - callee->symbol.decl)) + else if (!targetm.target_option.can_inline_p (e->caller->decl, + callee->decl)) { e->inline_failed = CIF_TARGET_OPTION_MISMATCH; inlinable = false; } /* Check if caller growth allows the inlining. */ - else if (!DECL_DISREGARD_INLINE_LIMITS (callee->symbol.decl) + else if (!DECL_DISREGARD_INLINE_LIMITS (callee->decl) && !disregard_limits && !lookup_attribute ("flatten", DECL_ATTRIBUTES (e->caller->global.inlined_to - ? e->caller->global.inlined_to->symbol.decl - : e->caller->symbol.decl)) + ? e->caller->global.inlined_to->decl + : e->caller->decl)) && !caller_growth_limits (e)) inlinable = false; /* Don't inline a function with a higher optimization level than the @@ -341,7 +344,7 @@ can_inline_edge_p (struct cgraph_edge *e, bool report, if (((caller_opt->x_optimize > callee_opt->x_optimize) || (caller_opt->x_optimize_size != callee_opt->x_optimize_size)) /* gcc.dg/pr43564.c. Look at forced inline even in -O0. */ - && !DECL_DISREGARD_INLINE_LIMITS (e->callee->symbol.decl)) + && !DECL_DISREGARD_INLINE_LIMITS (e->callee->decl)) { e->inline_failed = CIF_OPTIMIZATION_MISMATCH; inlinable = false; @@ -364,7 +367,7 @@ can_early_inline_edge_p (struct cgraph_edge *e) /* Early inliner might get called at WPA stage when IPA pass adds new function. In this case we can not really do any of early inlining because function bodies are missing. */ - if (!gimple_has_body_p (callee->symbol.decl)) + if (!gimple_has_body_p (callee->decl)) { e->inline_failed = CIF_BODY_NOT_AVAILABLE; return false; @@ -373,8 +376,8 @@ can_early_inline_edge_p (struct cgraph_edge *e) (i.e. the callgraph is cyclic and we did not process the callee by early inliner, yet). We don't have CIF code for this case; later we will re-do the decision in the real inliner. */ - if (!gimple_in_ssa_p (DECL_STRUCT_FUNCTION (e->caller->symbol.decl)) - || !gimple_in_ssa_p (DECL_STRUCT_FUNCTION (callee->symbol.decl))) + if (!gimple_in_ssa_p (DECL_STRUCT_FUNCTION (e->caller->decl)) + || !gimple_in_ssa_p (DECL_STRUCT_FUNCTION (callee->decl))) { if (dump_file) fprintf (dump_file, " edge not inlinable: not in SSA form\n"); @@ -395,7 +398,7 @@ num_calls (struct cgraph_node *n) int num = 0; for (e = n->callees; e; e = e->next_callee) - if (!is_inexpensive_builtin (e->callee->symbol.decl)) + if (!is_inexpensive_builtin (e->callee->decl)) num++; return num; } @@ -409,9 +412,9 @@ want_early_inline_function_p (struct cgraph_edge *e) bool want_inline = true; struct cgraph_node *callee = cgraph_function_or_thunk_node (e->callee, NULL); - if (DECL_DISREGARD_INLINE_LIMITS (callee->symbol.decl)) + if (DECL_DISREGARD_INLINE_LIMITS (callee->decl)) ; - else if (!DECL_DECLARED_INLINE_P (callee->symbol.decl) + else if (!DECL_DECLARED_INLINE_P (callee->decl) && !flag_inline_small_functions) { e->inline_failed = CIF_FUNCTION_NOT_INLINE_CANDIDATE; @@ -432,8 +435,8 @@ want_early_inline_function_p (struct cgraph_edge *e) fprintf (dump_file, " will not early inline: %s/%i->%s/%i, " "call is cold and code would grow by %i\n", xstrdup (cgraph_node_name (e->caller)), - e->caller->symbol.order, - xstrdup (cgraph_node_name (callee)), callee->symbol.order, + e->caller->order, + xstrdup (cgraph_node_name (callee)), callee->order, growth); want_inline = false; } @@ -443,8 +446,8 @@ want_early_inline_function_p (struct cgraph_edge *e) fprintf (dump_file, " will not early inline: %s/%i->%s/%i, " "growth %i exceeds --param early-inlining-insns\n", xstrdup (cgraph_node_name (e->caller)), - e->caller->symbol.order, - xstrdup (cgraph_node_name (callee)), callee->symbol.order, + e->caller->order, + xstrdup (cgraph_node_name (callee)), callee->order, growth); want_inline = false; } @@ -456,8 +459,8 @@ want_early_inline_function_p (struct cgraph_edge *e) "growth %i exceeds --param early-inlining-insns " "divided by number of calls\n", xstrdup (cgraph_node_name (e->caller)), - e->caller->symbol.order, - xstrdup (cgraph_node_name (callee)), callee->symbol.order, + e->caller->order, + xstrdup (cgraph_node_name (callee)), callee->order, growth); want_inline = false; } @@ -527,9 +530,9 @@ want_inline_small_function_p (struct cgraph_edge *e, bool report) bool want_inline = true; struct cgraph_node *callee = cgraph_function_or_thunk_node (e->callee, NULL); - if (DECL_DISREGARD_INLINE_LIMITS (callee->symbol.decl)) + if (DECL_DISREGARD_INLINE_LIMITS (callee->decl)) ; - else if (!DECL_DECLARED_INLINE_P (callee->symbol.decl) + else if (!DECL_DECLARED_INLINE_P (callee->decl) && !flag_inline_small_functions) { e->inline_failed = CIF_FUNCTION_NOT_INLINE_CANDIDATE; @@ -545,7 +548,7 @@ want_inline_small_function_p (struct cgraph_edge *e, bool report) ; /* Apply MAX_INLINE_INSNS_SINGLE limit. Do not do so when hints suggests that inlining given function is very profitable. */ - else if (DECL_DECLARED_INLINE_P (callee->symbol.decl) + else if (DECL_DECLARED_INLINE_P (callee->decl) && growth >= MAX_INLINE_INSNS_SINGLE && !big_speedup && !(hints & (INLINE_HINT_indirect_call @@ -588,11 +591,11 @@ want_inline_small_function_p (struct cgraph_edge *e, bool report) Consequently we ask cgraph_can_remove_if_no_direct_calls_p instead of cgraph_will_be_removed_from_program_if_no_direct_calls */ - && !DECL_EXTERNAL (callee->symbol.decl) + && !DECL_EXTERNAL (callee->decl) && cgraph_can_remove_if_no_direct_calls_p (callee) && estimate_growth (callee) <= 0) ; - else if (!DECL_DECLARED_INLINE_P (callee->symbol.decl) + else if (!DECL_DECLARED_INLINE_P (callee->decl) && !flag_inline_functions) { e->inline_failed = CIF_NOT_DECLARED_INLINED; @@ -601,7 +604,7 @@ want_inline_small_function_p (struct cgraph_edge *e, bool report) /* Apply MAX_INLINE_INSNS_AUTO limit for functions not declared inline Upgrade it to MAX_INLINE_INSNS_SINGLE when hints suggests that inlining given function is very profitable. */ - else if (!DECL_DECLARED_INLINE_P (callee->symbol.decl) + else if (!DECL_DECLARED_INLINE_P (callee->decl) && !big_speedup && growth >= ((hints & (INLINE_HINT_indirect_call | INLINE_HINT_loop_iterations @@ -648,7 +651,7 @@ want_inline_self_recursive_call_p (struct cgraph_edge *edge, int caller_freq = CGRAPH_FREQ_BASE; int max_depth = PARAM_VALUE (PARAM_MAX_INLINE_RECURSIVE_DEPTH_AUTO); - if (DECL_DECLARED_INLINE_P (edge->caller->symbol.decl)) + if (DECL_DECLARED_INLINE_P (edge->caller->decl)) max_depth = PARAM_VALUE (PARAM_MAX_INLINE_RECURSIVE_DEPTH); if (!cgraph_maybe_hot_edge_p (edge)) @@ -814,8 +817,8 @@ relative_time_benefit (struct inline_summary *callee_info, /* Inlining into extern inline function is not a win. */ if (DECL_EXTERNAL (edge->caller->global.inlined_to - ? edge->caller->global.inlined_to->symbol.decl - : edge->caller->symbol.decl)) + ? edge->caller->global.inlined_to->decl + : edge->caller->decl)) return 1; /* Watch overflows. */ @@ -854,7 +857,7 @@ edge_badness (struct cgraph_edge *edge, bool dump) struct inline_summary *callee_info = inline_summary (callee); inline_hints hints; - if (DECL_DISREGARD_INLINE_LIMITS (callee->symbol.decl)) + if (DECL_DISREGARD_INLINE_LIMITS (callee->decl)) return INT_MIN; growth = estimate_edge_growth (edge); @@ -868,9 +871,9 @@ edge_badness (struct cgraph_edge *edge, bool dump) { fprintf (dump_file, " Badness calculation for %s/%i -> %s/%i\n", xstrdup (cgraph_node_name (edge->caller)), - edge->caller->symbol.order, + edge->caller->order, xstrdup (cgraph_node_name (callee)), - edge->callee->symbol.order); + edge->callee->order); fprintf (dump_file, " size growth %i, time %i ", growth, edge_time); @@ -903,12 +906,16 @@ edge_badness (struct cgraph_edge *edge, bool dump) { sreal tmp, relbenefit_real, growth_real; int relbenefit = relative_time_benefit (callee_info, edge, edge_time); + /* Capping edge->count to max_count. edge->count can be larger than + max_count if an inline adds new edges which increase max_count + after max_count is computed. */ + int edge_count = edge->count > max_count ? max_count : edge->count; sreal_init (&relbenefit_real, relbenefit, 0); sreal_init (&growth_real, growth, 0); /* relative_edge_count. */ - sreal_init (&tmp, edge->count, 0); + sreal_init (&tmp, edge_count, 0); sreal_div (&tmp, &tmp, &max_count_real); /* relative_time_benefit. */ @@ -921,16 +928,14 @@ edge_badness (struct cgraph_edge *edge, bool dump) badness = -1 * sreal_to_int (&tmp); - /* Be sure that insanity of the profile won't lead to increasing counts - in the scalling and thus to overflow in the computation above. */ - gcc_assert (max_count >= edge->count); if (dump) { fprintf (dump_file, - " %i (relative %f): profile info. Relative count %f" + " %i (relative %f): profile info. Relative count %f%s" " * Relative benefit %f\n", (int) badness, (double) badness / INT_MIN, - (double) edge->count / max_count, + (double) edge_count / max_count, + edge->count > max_count ? " (capped to max_count)" : "", relbenefit * 100.0 / RELATIVE_TIME_BENEFIT_RANGE); } } @@ -1033,9 +1038,9 @@ update_edge_key (fibheap_t heap, struct cgraph_edge *edge) fprintf (dump_file, " decreasing badness %s/%i -> %s/%i, %i to %i\n", xstrdup (cgraph_node_name (edge->caller)), - edge->caller->symbol.order, + edge->caller->order, xstrdup (cgraph_node_name (edge->callee)), - edge->callee->symbol.order, + edge->callee->order, (int)n->key, badness); } @@ -1050,9 +1055,9 @@ update_edge_key (fibheap_t heap, struct cgraph_edge *edge) fprintf (dump_file, " enqueuing call %s/%i -> %s/%i, badness %i\n", xstrdup (cgraph_node_name (edge->caller)), - edge->caller->symbol.order, + edge->caller->order, xstrdup (cgraph_node_name (edge->callee)), - edge->callee->symbol.order, + edge->callee->order, badness); } edge->aux = fibheap_insert (heap, badness, edge); @@ -1083,7 +1088,7 @@ reset_edge_caches (struct cgraph_node *node) for (edge = where->callers; edge; edge = edge->next_caller) if (edge->inline_failed) reset_edge_growth_cache (edge); - for (i = 0; ipa_ref_list_referring_iterate (&where->symbol.ref_list, + for (i = 0; ipa_ref_list_referring_iterate (&where->ref_list, i, ref); i++) if (ref->use == IPA_REF_ALIAS) reset_edge_caches (ipa_ref_referring_node (ref)); @@ -1128,13 +1133,13 @@ update_caller_keys (fibheap_t heap, struct cgraph_node *node, int i; struct ipa_ref *ref; - if ((!node->symbol.alias && !inline_summary (node)->inlinable) + if ((!node->alias && !inline_summary (node)->inlinable) || node->global.inlined_to) return; if (!bitmap_set_bit (updated_nodes, node->uid)) return; - for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list, + for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list, i, ref); i++) if (ref->use == IPA_REF_ALIAS) { @@ -1266,7 +1271,7 @@ recursive_inlining (struct cgraph_edge *edge, if (node->global.inlined_to) node = node->global.inlined_to; - if (DECL_DECLARED_INLINE_P (node->symbol.decl)) + if (DECL_DECLARED_INLINE_P (node->decl)) limit = PARAM_VALUE (PARAM_MAX_INLINE_INSNS_RECURSIVE); /* Make sure that function is small enough to be considered for inlining. */ @@ -1315,8 +1320,8 @@ recursive_inlining (struct cgraph_edge *edge, depth = 1; for (cnode = curr->caller; cnode->global.inlined_to; cnode = cnode->callers->caller) - if (node->symbol.decl - == cgraph_function_or_thunk_node (curr->callee, NULL)->symbol.decl) + if (node->decl + == cgraph_function_or_thunk_node (curr->callee, NULL)->decl) depth++; if (!want_inline_self_recursive_call_p (curr, node, false, depth)) @@ -1340,7 +1345,7 @@ recursive_inlining (struct cgraph_edge *edge, if (!master_clone) { /* We need original clone to copy around. */ - master_clone = cgraph_clone_node (node, node->symbol.decl, + master_clone = cgraph_clone_node (node, node->decl, node->count, CGRAPH_FREQ_BASE, false, vNULL, true, NULL); for (e = master_clone->callees; e; e = e->next_callee) @@ -1452,7 +1457,7 @@ speculation_useful_p (struct cgraph_edge *e, bool anticipate_inlining) else we propagate is useless. */ if (avail >= AVAIL_AVAILABLE) { - int ecf_flags = flags_from_decl_or_type (target->symbol.decl); + int ecf_flags = flags_from_decl_or_type (target->decl); if (ecf_flags & ECF_CONST) { cgraph_speculative_call_info (e, direct, indirect, ref); @@ -1542,9 +1547,9 @@ inline_small_functions (void) || node->thunk.thunk_p) { struct inline_summary *info = inline_summary (node); - struct ipa_dfs_info *dfs = (struct ipa_dfs_info *) node->symbol.aux; + struct ipa_dfs_info *dfs = (struct ipa_dfs_info *) node->aux; - if (!DECL_EXTERNAL (node->symbol.decl)) + if (!DECL_EXTERNAL (node->decl)) initial_size += info->size; info->growth = estimate_growth (node); if (dfs && dfs->next_cycle) @@ -1552,7 +1557,7 @@ inline_small_functions (void) struct cgraph_node *n2; int id = dfs->scc_no + 1; for (n2 = node; n2; - n2 = ((struct ipa_dfs_info *) node->symbol.aux)->next_cycle) + n2 = ((struct ipa_dfs_info *) node->aux)->next_cycle) { struct inline_summary *info2 = inline_summary (n2); if (info2->scc_no) @@ -1590,7 +1595,7 @@ inline_small_functions (void) if (dump_file) fprintf (dump_file, "Enqueueing calls in %s/%i.\n", - cgraph_node_name (node), node->symbol.order); + cgraph_node_name (node), node->order); for (edge = node->callees; edge; edge = next) { @@ -1673,13 +1678,13 @@ inline_small_functions (void) { fprintf (dump_file, "\nConsidering %s/%i with %i size\n", - cgraph_node_name (callee), callee->symbol.order, + cgraph_node_name (callee), callee->order, inline_summary (callee)->size); fprintf (dump_file, " to be inlined into %s/%i in %s:%i\n" " Estimated growth after inlined into all is %+i insns.\n" " Estimated badness is %i, frequency %.2f.\n", - cgraph_node_name (edge->caller), edge->caller->symbol.order, + cgraph_node_name (edge->caller), edge->caller->order, flag_wpa ? "unknown" : gimple_filename ((const_gimple) edge->call_stmt), flag_wpa ? -1 @@ -1695,7 +1700,7 @@ inline_small_functions (void) } if (overall_size + growth > max_size - && !DECL_DISREGARD_INLINE_LIMITS (callee->symbol.decl)) + && !DECL_DISREGARD_INLINE_LIMITS (callee->decl)) { edge->inline_failed = CIF_INLINE_UNIT_GROWTH_LIMIT; report_inline_failed_reason (edge); @@ -1747,7 +1752,7 @@ inline_small_functions (void) where = edge->caller; while (where->global.inlined_to) { - if (where->symbol.decl == callee->symbol.decl) + if (where->decl == callee->decl) outer_node = where, depth++; where = where->callers->caller; } @@ -1756,7 +1761,7 @@ inline_small_functions (void) true, depth)) { edge->inline_failed - = (DECL_DISREGARD_INLINE_LIMITS (edge->callee->symbol.decl) + = (DECL_DISREGARD_INLINE_LIMITS (edge->callee->decl) ? CIF_RECURSIVE_INLINING : CIF_UNSPECIFIED); resolve_noninline_speculation (edge_heap, edge); continue; @@ -1828,9 +1833,9 @@ flatten_function (struct cgraph_node *node, bool early) struct cgraph_edge *e; /* We shouldn't be called recursively when we are being processed. */ - gcc_assert (node->symbol.aux == NULL); + gcc_assert (node->aux == NULL); - node->symbol.aux = (void *) node; + node->aux = (void *) node; for (e = node->callees; e; e = e->next_callee) { @@ -1838,7 +1843,7 @@ flatten_function (struct cgraph_node *node, bool early) struct cgraph_node *callee = cgraph_function_or_thunk_node (e->callee, NULL); /* We've hit cycle? It is time to give up. */ - if (callee->symbol.aux) + if (callee->aux) { if (dump_file) fprintf (dump_file, @@ -1872,8 +1877,8 @@ flatten_function (struct cgraph_node *node, bool early) continue; } - if (gimple_in_ssa_p (DECL_STRUCT_FUNCTION (node->symbol.decl)) - != gimple_in_ssa_p (DECL_STRUCT_FUNCTION (callee->symbol.decl))) + if (gimple_in_ssa_p (DECL_STRUCT_FUNCTION (node->decl)) + != gimple_in_ssa_p (DECL_STRUCT_FUNCTION (callee->decl))) { if (dump_file) fprintf (dump_file, "Not inlining: SSA form does not match.\n"); @@ -1889,13 +1894,13 @@ flatten_function (struct cgraph_node *node, bool early) orig_callee = callee; inline_call (e, true, NULL, NULL, false); if (e->callee != orig_callee) - orig_callee->symbol.aux = (void *) node; + orig_callee->aux = (void *) node; flatten_function (e->callee, early); if (e->callee != orig_callee) - orig_callee->symbol.aux = NULL; + orig_callee->aux = NULL; } - node->symbol.aux = NULL; + node->aux = NULL; if (!node->global.inlined_to) inline_update_overall_summary (node); } @@ -1981,7 +1986,7 @@ ipa_inline (void) nnodes = ipa_reverse_postorder (order); FOR_EACH_FUNCTION (node) - node->symbol.aux = 0; + node->aux = 0; if (dump_file) fprintf (dump_file, "\nFlattening functions:\n"); @@ -1998,7 +2003,7 @@ ipa_inline (void) try to flatten itself turning it into a self-recursive function. */ if (lookup_attribute ("flatten", - DECL_ATTRIBUTES (node->symbol.decl)) != NULL) + DECL_ATTRIBUTES (node->decl)) != NULL) { if (dump_file) fprintf (dump_file, @@ -2103,7 +2108,7 @@ inline_always_inline_functions (struct cgraph_node *node) for (e = node->callees; e; e = e->next_callee) { struct cgraph_node *callee = cgraph_function_or_thunk_node (e->callee, NULL); - if (!DECL_DISREGARD_INLINE_LIMITS (callee->symbol.decl)) + if (!DECL_DISREGARD_INLINE_LIMITS (callee->decl)) continue; if (cgraph_edge_recursive_p (e)) @@ -2121,7 +2126,7 @@ inline_always_inline_functions (struct cgraph_node *node) is not inlinable. This will allow flagging an error later in expand_call_inline in tree-inline.c. */ if (lookup_attribute ("always_inline", - DECL_ATTRIBUTES (callee->symbol.decl)) != NULL) + DECL_ATTRIBUTES (callee->decl)) != NULL) inlined = true; continue; } @@ -2156,7 +2161,7 @@ early_inline_small_functions (struct cgraph_node *node) continue; /* Do not consider functions not declared inline. */ - if (!DECL_DECLARED_INLINE_P (callee->symbol.decl) + if (!DECL_DECLARED_INLINE_P (callee->decl) && !flag_inline_small_functions && !flag_inline_functions) continue; @@ -2216,7 +2221,7 @@ early_inliner (void) #ifdef ENABLE_CHECKING verify_cgraph_node (node); #endif - ipa_remove_all_references (&node->symbol.ref_list); + ipa_remove_all_references (&node->ref_list); /* Even when not optimizing or not inlining inline always-inline functions. */ @@ -2233,10 +2238,10 @@ early_inliner (void) cycles of edges to be always inlined in the callgraph. We might want to be smarter and just avoid this type of inlining. */ - || DECL_DISREGARD_INLINE_LIMITS (node->symbol.decl)) + || DECL_DISREGARD_INLINE_LIMITS (node->decl)) ; else if (lookup_attribute ("flatten", - DECL_ATTRIBUTES (node->symbol.decl)) != NULL) + DECL_ATTRIBUTES (node->decl)) != NULL) { /* When the function is marked to be flattened, recursively inline all calls in it. */ @@ -2267,9 +2272,9 @@ early_inliner (void) = estimate_num_insns (edge->call_stmt, &eni_size_weights); es->call_stmt_time = estimate_num_insns (edge->call_stmt, &eni_time_weights); - if (edge->callee->symbol.decl + if (edge->callee->decl && !gimple_check_call_matching_types ( - edge->call_stmt, edge->callee->symbol.decl, false)) + edge->call_stmt, edge->callee->decl, false)) edge->call_stmt_cannot_inline_p = true; } timevar_pop (TV_INTEGRATION); diff --git a/gcc/ipa-profile.c b/gcc/ipa-profile.c index bae9aecd3b1..1260069207e 100644 --- a/gcc/ipa-profile.c +++ b/gcc/ipa-profile.c @@ -48,6 +48,7 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "tm.h" +#include "tree.h" #include "cgraph.h" #include "tree-pass.h" #include "gimple.h" @@ -184,7 +185,7 @@ ipa_profile_generate_summary (void) 10); FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node) - FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->symbol.decl)) + FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl)) { int time = 0; int size = 0; @@ -196,7 +197,7 @@ ipa_profile_generate_summary (void) { histogram_value h; h = gimple_histogram_value_of_type - (DECL_STRUCT_FUNCTION (node->symbol.decl), + (DECL_STRUCT_FUNCTION (node->decl), stmt, HIST_TYPE_INDIR_CALL); /* No need to do sanity check: gimple_ic_transform already takes away bad histograms. */ @@ -218,7 +219,7 @@ ipa_profile_generate_summary (void) e->indirect_info->common_target_probability = REG_BR_PROB_BASE; } } - gimple_remove_histogram_value (DECL_STRUCT_FUNCTION (node->symbol.decl), + gimple_remove_histogram_value (DECL_STRUCT_FUNCTION (node->decl), stmt, h); } } @@ -324,7 +325,7 @@ ipa_propagate_frequency_1 (struct cgraph_node *node, void *data) /* It makes sense to put main() together with the static constructors. It will be executed for sure, but rest of functions called from main are definitely not at startup only. */ - if (MAIN_NAME_P (DECL_NAME (edge->caller->symbol.decl))) + if (MAIN_NAME_P (DECL_NAME (edge->caller->decl))) d->only_called_at_startup = 0; d->only_called_at_exit &= edge->caller->only_called_at_exit; } @@ -400,10 +401,10 @@ ipa_propagate_frequency (struct cgraph_node *node) /* We can not propagate anything useful about externally visible functions nor about virtuals. */ if (!node->local.local - || node->symbol.alias - || (flag_devirtualize && DECL_VIRTUAL_P (node->symbol.decl))) + || node->alias + || (flag_devirtualize && DECL_VIRTUAL_P (node->decl))) return false; - gcc_assert (node->symbol.analyzed); + gcc_assert (node->analyzed); if (dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, "Processing frequency %s\n", cgraph_node_name (node)); @@ -588,8 +589,8 @@ ipa_profile (void) { fprintf (dump_file, "Indirect call -> direct call from" " other module %s/%i => %s/%i, prob %3.2f\n", - xstrdup (cgraph_node_name (n)), n->symbol.order, - xstrdup (cgraph_node_name (n2)), n2->symbol.order, + xstrdup (cgraph_node_name (n)), n->order, + xstrdup (cgraph_node_name (n2)), n2->order, e->indirect_info->common_target_probability / (float)REG_BR_PROB_BASE); } @@ -610,7 +611,7 @@ ipa_profile (void) } else if (cgraph_function_body_availability (n2) <= AVAIL_OVERWRITABLE - && symtab_can_be_discarded ((symtab_node) n2)) + && symtab_can_be_discarded (n2)) { nuseless++; if (dump_file) @@ -624,11 +625,11 @@ ipa_profile (void) control flow goes to this particular implementation of N2. Speculate on the local alias to allow inlining. */ - if (!symtab_can_be_discarded ((symtab_node) n2)) + if (!symtab_can_be_discarded (n2)) { cgraph_node *alias; alias = cgraph (symtab_nonoverwritable_alias - ((symtab_node)n2)); + (n2)); if (alias) n2 = alias; } @@ -676,13 +677,13 @@ ipa_profile (void) if (order[i]->local.local && ipa_propagate_frequency (order[i])) { for (e = order[i]->callees; e; e = e->next_callee) - if (e->callee->local.local && !e->callee->symbol.aux) + if (e->callee->local.local && !e->callee->aux) { something_changed = true; - e->callee->symbol.aux = (void *)1; + e->callee->aux = (void *)1; } } - order[i]->symbol.aux = NULL; + order[i]->aux = NULL; } while (something_changed) @@ -690,16 +691,16 @@ ipa_profile (void) something_changed = false; for (i = order_pos - 1; i >= 0; i--) { - if (order[i]->symbol.aux && ipa_propagate_frequency (order[i])) + if (order[i]->aux && ipa_propagate_frequency (order[i])) { for (e = order[i]->callees; e; e = e->next_callee) - if (e->callee->local.local && !e->callee->symbol.aux) + if (e->callee->local.local && !e->callee->aux) { something_changed = true; - e->callee->symbol.aux = (void *)1; + e->callee->aux = (void *)1; } } - order[i]->symbol.aux = NULL; + order[i]->aux = NULL; } } free (order); diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c index dae58d9bf15..9761d6e0a99 100644 --- a/gcc/ipa-prop.c +++ b/gcc/ipa-prop.c @@ -21,16 +21,21 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "tree.h" +#include "gimple.h" #include "langhooks.h" #include "ggc.h" #include "target.h" -#include "cgraph.h" #include "ipa-prop.h" -#include "tree-ssa.h" +#include "bitmap.h" +#include "gimple-ssa.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-into-ssa.h" +#include "tree-dfa.h" #include "tree-pass.h" #include "tree-inline.h" #include "ipa-inline.h" -#include "gimple.h" #include "flags.h" #include "diagnostic.h" #include "gimple-pretty-print.h" @@ -85,7 +90,7 @@ static alloc_pool ipa_refdesc_pool; static bool ipa_func_spec_opts_forbid_analysis_p (struct cgraph_node *node) { - tree fs_opts = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (node->symbol.decl); + tree fs_opts = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (node->decl); struct cl_optimization *os; if (!fs_opts) @@ -131,7 +136,7 @@ ipa_populate_param_decls (struct cgraph_node *node, tree parm; int param_num; - fndecl = node->symbol.decl; + fndecl = node->decl; gcc_assert (gimple_has_body_p (fndecl)); fnargs = DECL_ARGUMENTS (fndecl); param_num = 0; @@ -196,7 +201,7 @@ ipa_initialize_node_params (struct cgraph_node *node) if (!info->descriptors.exists ()) { - ipa_alloc_node_params (node, count_formal_params (node->symbol.decl)); + ipa_alloc_node_params (node, count_formal_params (node->decl)); ipa_populate_param_decls (node, info->descriptors); } } @@ -310,16 +315,16 @@ ipa_print_node_jump_functions (FILE *f, struct cgraph_node *node) struct cgraph_edge *cs; fprintf (f, " Jump functions of caller %s/%i:\n", cgraph_node_name (node), - node->symbol.order); + node->order); for (cs = node->callees; cs; cs = cs->next_callee) { if (!ipa_edge_args_info_available_for_edge_p (cs)) continue; fprintf (f, " callsite %s/%i -> %s/%i : \n", - xstrdup (cgraph_node_name (node)), node->symbol.order, + xstrdup (cgraph_node_name (node)), node->order, xstrdup (cgraph_node_name (cs->callee)), - cs->callee->symbol.order); + cs->callee->order); ipa_print_node_jump_functions_for_edge (f, cs); } @@ -1508,7 +1513,7 @@ ipa_get_callee_param_type (struct cgraph_edge *e, int i) { int n; tree type = (e->callee - ? TREE_TYPE (e->callee->symbol.decl) + ? TREE_TYPE (e->callee->decl) : gimple_call_fntype (e->call_stmt)); tree t = TYPE_ARG_TYPES (type); @@ -1522,7 +1527,7 @@ ipa_get_callee_param_type (struct cgraph_edge *e, int i) return TREE_VALUE (t); if (!e->callee) return NULL; - t = DECL_ARGUMENTS (e->callee->symbol.decl); + t = DECL_ARGUMENTS (e->callee->decl); for (n = 0; n < i; n++) { if (!t) @@ -1642,7 +1647,7 @@ ipa_compute_jump_functions (struct cgraph_node *node, NULL); /* We do not need to bother analyzing calls to unknown functions unless they may become known during lto/whopr. */ - if (!callee->symbol.definition && !flag_lto) + if (!callee->definition && !flag_lto) continue; ipa_compute_jump_functions_for_edge (parms_ainfo, cs); } @@ -2051,7 +2056,7 @@ static void ipa_analyze_params_uses (struct cgraph_node *node, struct param_analysis_info *parms_ainfo) { - tree decl = node->symbol.decl; + tree decl = node->decl; basic_block bb; struct function *func; gimple_stmt_iterator gsi; @@ -2081,7 +2086,7 @@ ipa_analyze_params_uses (struct cgraph_node *node, the flag during modification analysis. */ if (is_gimple_reg (parm)) { - tree ddef = ssa_default_def (DECL_STRUCT_FUNCTION (node->symbol.decl), + tree ddef = ssa_default_def (DECL_STRUCT_FUNCTION (node->decl), parm); if (ddef && !has_zero_uses (ddef)) { @@ -2160,7 +2165,7 @@ ipa_analyze_node (struct cgraph_node *node) ipa_check_create_node_params (); ipa_check_create_edge_args (); info = IPA_NODE_REF (node); - push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl)); + push_cfun (DECL_STRUCT_FUNCTION (node->decl)); ipa_initialize_node_params (node); param_count = ipa_get_param_count (info); @@ -2413,7 +2418,7 @@ ipa_make_edge_direct_to_target (struct cgraph_edge *ie, tree target) if (dump_file) fprintf (dump_file, "ipa-prop: Discovered direct call to non-function" " in %s/%i, making it unreachable.\n", - cgraph_node_name (ie->caller), ie->caller->symbol.order); + cgraph_node_name (ie->caller), ie->caller->order); target = builtin_decl_implicit (BUILT_IN_UNREACHABLE); callee = cgraph_get_create_node (target); unreachable = true; @@ -2440,9 +2445,9 @@ ipa_make_edge_direct_to_target (struct cgraph_edge *ie, tree target) fprintf (dump_file, "ipa-prop: Discovered call to a known target " "(%s/%i -> %s/%i) but can not refer to it. Giving up.\n", xstrdup (cgraph_node_name (ie->caller)), - ie->caller->symbol.order, + ie->caller->order, xstrdup (cgraph_node_name (ie->callee)), - ie->callee->symbol.order); + ie->callee->order); return NULL; } callee = cgraph_get_create_real_symbol_node (target); @@ -2459,9 +2464,9 @@ ipa_make_edge_direct_to_target (struct cgraph_edge *ie, tree target) "(%s/%i -> %s/%i), for stmt ", ie->indirect_info->polymorphic ? "a virtual" : "an indirect", xstrdup (cgraph_node_name (ie->caller)), - ie->caller->symbol.order, + ie->caller->order, xstrdup (cgraph_node_name (callee)), - callee->symbol.order); + callee->order); if (ie->call_stmt) print_gimple_stmt (dump_file, ie->call_stmt, 2, TDF_SLIM); else @@ -2507,7 +2512,7 @@ ipa_find_agg_cst_for_param (struct ipa_agg_jump_function *agg, successfully found and removed. */ static bool -remove_described_reference (symtab_node symbol, struct ipa_cst_ref_desc *rdesc) +remove_described_reference (symtab_node *symbol, struct ipa_cst_ref_desc *rdesc) { struct ipa_ref *to_del; struct cgraph_edge *origin; @@ -2515,7 +2520,7 @@ remove_described_reference (symtab_node symbol, struct ipa_cst_ref_desc *rdesc) origin = rdesc->cs; if (!origin) return false; - to_del = ipa_find_reference ((symtab_node) origin->caller, symbol, + to_del = ipa_find_reference (origin->caller, symbol, origin->call_stmt, origin->lto_stmt_uid); if (!to_del) return false; @@ -2524,7 +2529,7 @@ remove_described_reference (symtab_node symbol, struct ipa_cst_ref_desc *rdesc) if (dump_file) fprintf (dump_file, "ipa-prop: Removed a reference from %s/%i to %s.\n", xstrdup (cgraph_node_name (origin->caller)), - origin->caller->symbol.order, xstrdup (symtab_node_name (symbol))); + origin->caller->order, xstrdup (symtab_node_name (symbol))); return true; } @@ -2572,7 +2577,7 @@ try_decrement_rdesc_refcount (struct ipa_jump_func *jfunc) && (rdesc = jfunc_rdesc_usable (jfunc)) && --rdesc->refcount == 0) { - symtab_node symbol = (symtab_node) cgraph_node_for_jfunc (jfunc); + symtab_node *symbol = cgraph_node_for_jfunc (jfunc); if (!symbol) return false; @@ -2732,7 +2737,7 @@ update_indirect_edges_after_inlining (struct cgraph_edge *cs, new_direct_edge->call_stmt_cannot_inline_p = !gimple_check_call_matching_types ( new_direct_edge->call_stmt, - new_direct_edge->callee->symbol.decl, false); + new_direct_edge->callee->decl, false); if (new_edges) { new_edges->safe_push (new_direct_edge); @@ -2848,15 +2853,15 @@ propagate_controlled_uses (struct cgraph_edge *cs) if (t && TREE_CODE (t) == ADDR_EXPR && TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL && (n = cgraph_get_node (TREE_OPERAND (t, 0))) - && (ref = ipa_find_reference ((symtab_node) new_root, - (symtab_node) n, NULL, 0))) + && (ref = ipa_find_reference (new_root, + n, NULL, 0))) { if (dump_file) fprintf (dump_file, "ipa-prop: Removing cloning-created " "reference from %s/%i to %s/%i.\n", xstrdup (cgraph_node_name (new_root)), - new_root->symbol.order, - xstrdup (cgraph_node_name (n)), n->symbol.order); + new_root->order, + xstrdup (cgraph_node_name (n)), n->order); ipa_remove_reference (ref); } } @@ -2879,7 +2884,7 @@ propagate_controlled_uses (struct cgraph_edge *cs) { struct cgraph_node *clone; bool ok; - ok = remove_described_reference ((symtab_node) n, rdesc); + ok = remove_described_reference (n, rdesc); gcc_checking_assert (ok); clone = cs->caller; @@ -2888,8 +2893,8 @@ propagate_controlled_uses (struct cgraph_edge *cs) && IPA_NODE_REF (clone)->ipcp_orig_node) { struct ipa_ref *ref; - ref = ipa_find_reference ((symtab_node) clone, - (symtab_node) n, NULL, 0); + ref = ipa_find_reference (clone, + n, NULL, 0); if (ref) { if (dump_file) @@ -2897,9 +2902,9 @@ propagate_controlled_uses (struct cgraph_edge *cs) "cloning-created reference " "from %s/%i to %s/%i.\n", xstrdup (cgraph_node_name (clone)), - clone->symbol.order, + clone->order, xstrdup (cgraph_node_name (n)), - n->symbol.order); + n->order); ipa_remove_reference (ref); } clone = clone->callers->caller; @@ -3092,12 +3097,12 @@ ipa_edge_duplication_hook (struct cgraph_edge *src, struct cgraph_edge *dst, else if (src->caller == dst->caller) { struct ipa_ref *ref; - symtab_node n = (symtab_node) cgraph_node_for_jfunc (src_jf); + symtab_node *n = cgraph_node_for_jfunc (src_jf); gcc_checking_assert (n); - ref = ipa_find_reference ((symtab_node) src->caller, n, + ref = ipa_find_reference (src->caller, n, src->call_stmt, src->lto_stmt_uid); gcc_checking_assert (ref); - ipa_clone_ref (ref, (symtab_node) dst->caller, ref->stmt); + ipa_clone_ref (ref, dst->caller, ref->stmt); gcc_checking_assert (ipa_refdesc_pool); struct ipa_cst_ref_desc *dst_rdesc @@ -3278,11 +3283,11 @@ ipa_print_node_params (FILE *f, struct cgraph_node *node) int i, count; struct ipa_node_params *info; - if (!node->symbol.definition) + if (!node->definition) return; info = IPA_NODE_REF (node); fprintf (f, " function %s/%i parameter descriptors:\n", - cgraph_node_name (node), node->symbol.order); + cgraph_node_name (node), node->order); count = ipa_get_param_count (info); for (i = 0; i < count; i++) { @@ -3525,8 +3530,8 @@ ipa_modify_call_arguments (struct cgraph_edge *cs, gimple stmt, len = adjustments.length (); vargs.create (len); - callee_decl = !cs ? gimple_call_fndecl (stmt) : cs->callee->symbol.decl; - ipa_remove_stmt_references ((symtab_node) current_node, stmt); + callee_decl = !cs ? gimple_call_fndecl (stmt) : cs->callee->decl; + ipa_remove_stmt_references (current_node, stmt); gsi = gsi_for_stmt (stmt); prev_gsi = gsi; @@ -4117,7 +4122,7 @@ ipa_write_node_info (struct output_block *ob, struct cgraph_node *node) struct bitpack_d bp; encoder = ob->decl_state->symtab_node_encoder; - node_ref = lto_symtab_encoder_encode (encoder, (symtab_node) node); + node_ref = lto_symtab_encoder_encode (encoder, node); streamer_write_uhwi (ob, node_ref); streamer_write_uhwi (ob, ipa_get_param_count (info)); @@ -4281,7 +4286,7 @@ ipa_prop_read_section (struct lto_file_decl_data *file_data, const char *data, index = streamer_read_uhwi (&ib_main); encoder = file_data->symtab_node_encoder; node = cgraph (lto_symtab_encoder_deref (encoder, index)); - gcc_assert (node->symbol.definition); + gcc_assert (node->definition); ipa_read_node_info (&ib_main, node, data_in); } lto_free_section_data (file_data, LTO_section_jump_functions, NULL, data, @@ -4333,7 +4338,7 @@ write_agg_replacement_chain (struct output_block *ob, struct cgraph_node *node) aggvals = ipa_get_agg_replacements_for_node (node); encoder = ob->decl_state->symtab_node_encoder; - node_ref = lto_symtab_encoder_encode (encoder, (symtab_node) node); + node_ref = lto_symtab_encoder_encode (encoder, node); streamer_write_uhwi (ob, node_ref); for (av = aggvals; av; av = av->next) @@ -4457,7 +4462,7 @@ read_replacements_section (struct lto_file_decl_data *file_data, index = streamer_read_uhwi (&ib_main); encoder = file_data->symtab_node_encoder; node = cgraph (lto_symtab_encoder_deref (encoder, index)); - gcc_assert (node->symbol.definition); + gcc_assert (node->definition); read_agg_replacement_chain (&ib_main, node, data_in); } lto_free_section_data (file_data, LTO_section_jump_functions, NULL, data, @@ -4539,12 +4544,12 @@ ipcp_transform_function (struct cgraph_node *node) if (dump_file) fprintf (dump_file, "Modification phase of node %s/%i\n", - cgraph_node_name (node), node->symbol.order); + cgraph_node_name (node), node->order); aggval = ipa_get_agg_replacements_for_node (node); if (!aggval) return 0; - param_count = count_formal_params (node->symbol.decl); + param_count = count_formal_params (node->decl); if (param_count == 0) return 0; adjust_agg_replacement_values (node, aggval); diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h index 48634d2e172..4da22a1c05d 100644 --- a/gcc/ipa-prop.h +++ b/gcc/ipa-prop.h @@ -20,10 +20,8 @@ along with GCC; see the file COPYING3. If not see #ifndef IPA_PROP_H #define IPA_PROP_H -#include "tree.h" #include "vec.h" #include "cgraph.h" -#include "gimple.h" #include "alloc-pool.h" /* The following definitions and interfaces are used by diff --git a/gcc/ipa-pure-const.c b/gcc/ipa-pure-const.c index 85e5736d770..50bf500b172 100644 --- a/gcc/ipa-pure-const.c +++ b/gcc/ipa-pure-const.c @@ -36,15 +36,15 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tm.h" #include "tree.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "tree-cfg.h" +#include "tree-ssa-loop-niter.h" #include "tree-inline.h" #include "tree-pass.h" #include "langhooks.h" #include "pointer-set.h" #include "ggc.h" #include "ipa-utils.h" -#include "gimple.h" -#include "cgraph.h" #include "flags.h" #include "diagnostic.h" #include "gimple-pretty-print.h" @@ -190,15 +190,6 @@ warn_function_noreturn (tree decl) true, warned_about, "noreturn"); } -/* Init the function state. */ - -static void -finish_state (void) -{ - funct_state_vec.release (); -} - - /* Return true if we have a function state for NODE. */ static inline bool @@ -725,7 +716,7 @@ check_stmt (gimple_stmt_iterator *gsip, funct_state local, bool ipa) static funct_state analyze_function (struct cgraph_node *fn, bool ipa) { - tree decl = fn->symbol.decl; + tree decl = fn->decl; funct_state l; basic_block this_block; @@ -736,10 +727,10 @@ analyze_function (struct cgraph_node *fn, bool ipa) l->looping = false; l->can_throw = false; state_from_flags (&l->state_previously_known, &l->looping_previously_known, - flags_from_decl_or_type (fn->symbol.decl), + flags_from_decl_or_type (fn->decl), cgraph_node_cannot_return (fn)); - if (fn->thunk.thunk_p || fn->symbol.alias) + if (fn->thunk.thunk_p || fn->alias) { /* Thunk gets propagated through, so nothing interesting happens. */ gcc_assert (ipa); @@ -952,7 +943,7 @@ pure_const_write_summary (void) lsei_next_function_in_partition (&lsei)) { node = lsei_cgraph_node (lsei); - if (node->symbol.definition && has_function_state (node)) + if (node->definition && has_function_state (node)) count++; } @@ -963,7 +954,7 @@ pure_const_write_summary (void) lsei_next_function_in_partition (&lsei)) { node = lsei_cgraph_node (lsei); - if (node->symbol.definition && has_function_state (node)) + if (node->definition && has_function_state (node)) { struct bitpack_d bp; funct_state fs; @@ -973,7 +964,7 @@ pure_const_write_summary (void) fs = get_function_state (node); encoder = ob->decl_state->symtab_node_encoder; - node_ref = lto_symtab_encoder_encode (encoder, (symtab_node)node); + node_ref = lto_symtab_encoder_encode (encoder, node); streamer_write_uhwi_stream (ob->main_stream, node_ref); /* Note that flags will need to be read in the opposite @@ -1042,10 +1033,10 @@ pure_const_read_summary (void) fs->can_throw = bp_unpack_value (&bp, 1); if (dump_file) { - int flags = flags_from_decl_or_type (node->symbol.decl); + int flags = flags_from_decl_or_type (node->decl); fprintf (dump_file, "Read info for %s/%i ", cgraph_node_name (node), - node->symbol.order); + node->order); if (flags & ECF_CONST) fprintf (dump_file, " const"); if (flags & ECF_PURE) @@ -1126,7 +1117,7 @@ propagate_pure_const (void) int count = 0; node = order[i]; - if (node->symbol.alias) + if (node->alias) continue; if (dump_file && (dump_flags & TDF_DETAILS)) @@ -1145,7 +1136,7 @@ propagate_pure_const (void) if (dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, " Visiting %s/%i state:%s looping %i\n", cgraph_node_name (w), - w->symbol.order, + w->order, pure_const_names[w_l->pure_const_state], w_l->looping); @@ -1192,7 +1183,7 @@ propagate_pure_const (void) fprintf (dump_file, " Call to %s/%i", cgraph_node_name (e->callee), - e->callee->symbol.order); + e->callee->order); } if (avail > AVAIL_OVERWRITABLE) { @@ -1221,11 +1212,11 @@ propagate_pure_const (void) } } else if (special_builtin_state (&edge_state, &edge_looping, - y->symbol.decl)) + y->decl)) ; else state_from_flags (&edge_state, &edge_looping, - flags_from_decl_or_type (y->symbol.decl), + flags_from_decl_or_type (y->decl), cgraph_edge_cannot_lead_to_return (e)); /* Merge the results with what we already know. */ @@ -1264,7 +1255,7 @@ propagate_pure_const (void) break; /* And finally all loads and stores. */ - for (i = 0; ipa_ref_list_reference_iterate (&w->symbol.ref_list, i, ref); i++) + for (i = 0; ipa_ref_list_reference_iterate (&w->ref_list, i, ref); i++) { enum pure_const_state_e ref_state = IPA_CONST; bool ref_looping = false; @@ -1272,7 +1263,7 @@ propagate_pure_const (void) { case IPA_REF_LOAD: /* readonly reads are safe. */ - if (TREE_READONLY (ipa_ref_varpool_node (ref)->symbol.decl)) + if (TREE_READONLY (ipa_ref_varpool_node (ref)->decl)) break; if (dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, " nonreadonly global var read\n"); @@ -1296,7 +1287,7 @@ propagate_pure_const (void) if (pure_const_state == IPA_NEITHER) break; } - w_info = (struct ipa_dfs_info *) w->symbol.aux; + w_info = (struct ipa_dfs_info *) w->aux; w = w_info->next_cycle; } if (dump_file && (dump_flags & TDF_DETAILS)) @@ -1331,9 +1322,9 @@ propagate_pure_const (void) switch (this_state) { case IPA_CONST: - if (!TREE_READONLY (w->symbol.decl)) + if (!TREE_READONLY (w->decl)) { - warn_function_const (w->symbol.decl, !this_looping); + warn_function_const (w->decl, !this_looping); if (dump_file) fprintf (dump_file, "Function found to be %sconst: %s\n", this_looping ? "looping " : "", @@ -1343,9 +1334,9 @@ propagate_pure_const (void) break; case IPA_PURE: - if (!DECL_PURE_P (w->symbol.decl)) + if (!DECL_PURE_P (w->decl)) { - warn_function_pure (w->symbol.decl, !this_looping); + warn_function_pure (w->decl, !this_looping); if (dump_file) fprintf (dump_file, "Function found to be %spure: %s\n", this_looping ? "looping " : "", @@ -1357,7 +1348,7 @@ propagate_pure_const (void) default: break; } - w_info = (struct ipa_dfs_info *) w->symbol.aux; + w_info = (struct ipa_dfs_info *) w->aux; w = w_info->next_cycle; } } @@ -1396,7 +1387,7 @@ propagate_nothrow (void) bool can_throw = false; node = order[i]; - if (node->symbol.alias) + if (node->alias) continue; /* Find the worst state for any node in the cycle. */ @@ -1424,11 +1415,11 @@ propagate_nothrow (void) if (can_throw) break; - if (y_l->can_throw && !TREE_NOTHROW (w->symbol.decl) + if (y_l->can_throw && !TREE_NOTHROW (w->decl) && e->can_throw_external) can_throw = true; } - else if (e->can_throw_external && !TREE_NOTHROW (y->symbol.decl)) + else if (e->can_throw_external && !TREE_NOTHROW (y->decl)) can_throw = true; } for (ie = node->indirect_calls; ie; ie = ie->next_callee) @@ -1437,7 +1428,7 @@ propagate_nothrow (void) can_throw = true; break; } - w_info = (struct ipa_dfs_info *) w->symbol.aux; + w_info = (struct ipa_dfs_info *) w->aux; w = w_info->next_cycle; } @@ -1447,16 +1438,16 @@ propagate_nothrow (void) while (w) { funct_state w_l = get_function_state (w); - if (!can_throw && !TREE_NOTHROW (w->symbol.decl)) + if (!can_throw && !TREE_NOTHROW (w->decl)) { cgraph_set_nothrow_flag (w, true); if (dump_file) fprintf (dump_file, "Function found to be nothrow: %s\n", cgraph_node_name (w)); } - else if (can_throw && !TREE_NOTHROW (w->symbol.decl)) + else if (can_throw && !TREE_NOTHROW (w->decl)) w_l->can_throw = true; - w_info = (struct ipa_dfs_info *) w->symbol.aux; + w_info = (struct ipa_dfs_info *) w->aux; w = w_info->next_cycle; } } @@ -1488,7 +1479,6 @@ propagate (void) if (has_function_state (node)) free (get_function_state (node)); funct_state_vec.release (); - finish_state (); return 0; } diff --git a/gcc/ipa-ref-inline.h b/gcc/ipa-ref-inline.h index bb74f8723a4..4bb43c2af1d 100644 --- a/gcc/ipa-ref-inline.h +++ b/gcc/ipa-ref-inline.h @@ -54,7 +54,7 @@ ipa_ref_referring_varpool_node (struct ipa_ref *ref) static inline struct ipa_ref_list * ipa_ref_referring_ref_list (struct ipa_ref *ref) { - return &ref->referring->symbol.ref_list; + return &ref->referring->ref_list; } /* Return reference list REF is in. */ @@ -62,7 +62,7 @@ ipa_ref_referring_ref_list (struct ipa_ref *ref) static inline struct ipa_ref_list * ipa_ref_referred_ref_list (struct ipa_ref *ref) { - return &ref->referred->symbol.ref_list; + return &ref->referred->ref_list; } /* Return first reference in LIST or NULL if empty. */ diff --git a/gcc/ipa-ref.c b/gcc/ipa-ref.c index a7c3b40b0cf..04ce9090dfe 100644 --- a/gcc/ipa-ref.c +++ b/gcc/ipa-ref.c @@ -34,8 +34,8 @@ static const char *ipa_ref_use_name[] = {"read","write","addr","alias"}; of the use and STMT the statement (if it exists). */ struct ipa_ref * -ipa_record_reference (symtab_node referring_node, - symtab_node referred_node, +ipa_record_reference (symtab_node *referring_node, + symtab_node *referred_node, enum ipa_ref_use use_type, gimple stmt) { struct ipa_ref *ref, *ref2; @@ -45,12 +45,12 @@ ipa_record_reference (symtab_node referring_node, gcc_checking_assert (!stmt || is_a <cgraph_node> (referring_node)); gcc_checking_assert (use_type != IPA_REF_ALIAS || !stmt); - list = &referring_node->symbol.ref_list; + list = &referring_node->ref_list; old_references = vec_safe_address (list->references); vec_safe_grow (list->references, vec_safe_length (list->references) + 1); ref = &list->references->last (); - list2 = &referred_node->symbol.ref_list; + list2 = &referred_node->ref_list; list2->referring.safe_push (ref); ref->referred_index = list2->referring.length () - 1; ref->referring = referring_node; @@ -76,7 +76,7 @@ ipa_record_reference (symtab_node referring_node, reference or NULL if none was created. */ struct ipa_ref * -ipa_maybe_record_reference (symtab_node referring_node, tree val, +ipa_maybe_record_reference (symtab_node *referring_node, tree val, enum ipa_ref_use use_type, gimple stmt) { STRIP_NOPS (val); @@ -86,7 +86,7 @@ ipa_maybe_record_reference (symtab_node referring_node, tree val, if (val && (TREE_CODE (val) == FUNCTION_DECL || TREE_CODE (val) == VAR_DECL)) { - symtab_node referred = symtab_get_node (val); + symtab_node *referred = symtab_get_node (val); gcc_checking_assert (referred); return ipa_record_reference (referring_node, referred, use_type, stmt); @@ -155,7 +155,7 @@ ipa_dump_references (FILE * file, struct ipa_ref_list *list) { fprintf (file, "%s/%i (%s)", symtab_node_asm_name (ref->referred), - ref->referred->symbol.order, + ref->referred->order, ipa_ref_use_name [ref->use]); if (ref->speculative) fprintf (file, " (speculative)"); @@ -174,7 +174,7 @@ ipa_dump_referring (FILE * file, struct ipa_ref_list *list) { fprintf (file, "%s/%i (%s)", symtab_node_asm_name (ref->referring), - ref->referring->symbol.order, + ref->referring->order, ipa_ref_use_name [ref->use]); if (ref->speculative) fprintf (file, " (speculative)"); @@ -186,7 +186,7 @@ ipa_dump_referring (FILE * file, struct ipa_ref_list *list) struct ipa_ref * ipa_clone_ref (struct ipa_ref *ref, - symtab_node dest_node, + symtab_node *dest_node, gimple stmt) { bool speculative = ref->speculative; @@ -204,7 +204,7 @@ ipa_clone_ref (struct ipa_ref *ref, /* Clone all references from SRC to DEST_NODE or DEST_VARPOOL_NODE. */ void -ipa_clone_references (symtab_node dest_node, +ipa_clone_references (symtab_node *dest_node, struct ipa_ref_list *src) { struct ipa_ref *ref, *ref2; @@ -225,7 +225,7 @@ ipa_clone_references (symtab_node dest_node, /* Clone all referring from SRC to DEST_NODE or DEST_VARPOOL_NODE. */ void -ipa_clone_referring (symtab_node dest_node, +ipa_clone_referring (symtab_node *dest_node, struct ipa_ref_list *src) { struct ipa_ref *ref, *ref2; @@ -268,13 +268,13 @@ ipa_ref_has_aliases_p (struct ipa_ref_list *ref_list) and associated with statement STMT. */ struct ipa_ref * -ipa_find_reference (symtab_node referring_node, symtab_node referred_node, +ipa_find_reference (symtab_node *referring_node, symtab_node *referred_node, gimple stmt, unsigned int lto_stmt_uid) { struct ipa_ref *r = NULL; int i; - for (i = 0; ipa_ref_list_reference_iterate (&referring_node->symbol.ref_list, i, r); i++) + for (i = 0; ipa_ref_list_reference_iterate (&referring_node->ref_list, i, r); i++) if (r->referred == referred_node && !r->speculative && ((stmt && r->stmt == stmt) @@ -288,12 +288,12 @@ ipa_find_reference (symtab_node referring_node, symtab_node referred_node, STMT. */ void -ipa_remove_stmt_references (symtab_node referring_node, gimple stmt) +ipa_remove_stmt_references (symtab_node *referring_node, gimple stmt) { struct ipa_ref *r = NULL; int i; - for (i = 0; ipa_ref_list_reference_iterate (&referring_node->symbol.ref_list, i, r); i++) + for (i = 0; ipa_ref_list_reference_iterate (&referring_node->ref_list, i, r); i++) if (r->stmt == stmt) ipa_remove_reference (r); } @@ -304,12 +304,12 @@ ipa_remove_stmt_references (symtab_node referring_node, gimple stmt) with callgraph edges associated with them. */ void -ipa_clear_stmts_in_references (symtab_node referring_node) +ipa_clear_stmts_in_references (symtab_node *referring_node) { struct ipa_ref *r = NULL; int i; - for (i = 0; ipa_ref_list_reference_iterate (&referring_node->symbol.ref_list, i, r); i++) + for (i = 0; ipa_ref_list_reference_iterate (&referring_node->ref_list, i, r); i++) if (!r->speculative) { r->stmt = NULL; diff --git a/gcc/ipa-ref.h b/gcc/ipa-ref.h index e0553bb6609..9f392b41588 100644 --- a/gcc/ipa-ref.h +++ b/gcc/ipa-ref.h @@ -20,9 +20,7 @@ along with GCC; see the file COPYING3. If not see struct cgraph_node; struct varpool_node; -union symtab_node_def; -typedef union symtab_node_def *symtab_node; -typedef const union symtab_node_def *const_symtab_node; +class symtab_node; /* How the reference is done. */ @@ -37,8 +35,8 @@ enum GTY(()) ipa_ref_use /* Record of reference in callgraph or varpool. */ struct GTY(()) ipa_ref { - symtab_node referring; - symtab_node referred; + symtab_node *referring; + symtab_node *referred; gimple stmt; unsigned int lto_stmt_uid; unsigned int referred_index; @@ -60,10 +58,10 @@ struct GTY(()) ipa_ref_list vec<ipa_ref_ptr> GTY((skip)) referring; }; -struct ipa_ref * ipa_record_reference (symtab_node, - symtab_node, +struct ipa_ref * ipa_record_reference (symtab_node *, + symtab_node *, enum ipa_ref_use, gimple); -struct ipa_ref * ipa_maybe_record_reference (symtab_node, tree, +struct ipa_ref * ipa_maybe_record_reference (symtab_node *, tree, enum ipa_ref_use, gimple); void ipa_remove_reference (struct ipa_ref *); @@ -71,11 +69,11 @@ void ipa_remove_all_references (struct ipa_ref_list *); void ipa_remove_all_referring (struct ipa_ref_list *); void ipa_dump_references (FILE *, struct ipa_ref_list *); void ipa_dump_referring (FILE *, struct ipa_ref_list *); -void ipa_clone_references (symtab_node, struct ipa_ref_list *); -void ipa_clone_referring (symtab_node, struct ipa_ref_list *); -struct ipa_ref * ipa_clone_ref (struct ipa_ref *, symtab_node, gimple); +void ipa_clone_references (symtab_node *, struct ipa_ref_list *); +void ipa_clone_referring (symtab_node *, struct ipa_ref_list *); +struct ipa_ref * ipa_clone_ref (struct ipa_ref *, symtab_node *, gimple); bool ipa_ref_cannot_lead_to_return (struct ipa_ref *); bool ipa_ref_has_aliases_p (struct ipa_ref_list *); -struct ipa_ref * ipa_find_reference (symtab_node, symtab_node, gimple, unsigned int); -void ipa_remove_stmt_references (symtab_node, gimple); -void ipa_clear_stmts_in_references (symtab_node); +struct ipa_ref * ipa_find_reference (symtab_node *, symtab_node *, gimple, unsigned int); +void ipa_remove_stmt_references (symtab_node *, gimple); +void ipa_clear_stmts_in_references (symtab_node *); diff --git a/gcc/ipa-reference.c b/gcc/ipa-reference.c index d9463804ea2..ae8ba3c651f 100644 --- a/gcc/ipa-reference.c +++ b/gcc/ipa-reference.c @@ -41,7 +41,7 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tm.h" #include "tree.h" -#include "tree-ssa.h" +#include "gimple.h" #include "tree-inline.h" #include "tree-pass.h" #include "pointer-set.h" @@ -49,8 +49,6 @@ along with GCC; see the file COPYING3. If not see #include "ggc.h" #include "ipa-utils.h" #include "ipa-reference.h" -#include "gimple.h" -#include "cgraph.h" #include "flags.h" #include "diagnostic.h" #include "data-streamer.h" @@ -180,7 +178,7 @@ ipa_reference_get_not_read_global (struct cgraph_node *fn) get_reference_optimization_summary (cgraph_function_node (fn, NULL)); if (info) return info->statics_not_read; - else if (flags_from_decl_or_type (fn->symbol.decl) & ECF_LEAF) + else if (flags_from_decl_or_type (fn->decl) & ECF_LEAF) return all_module_statics; else return NULL; @@ -198,7 +196,7 @@ ipa_reference_get_not_written_global (struct cgraph_node *fn) get_reference_optimization_summary (fn); if (info) return info->statics_not_written; - else if (flags_from_decl_or_type (fn->symbol.decl) & ECF_LEAF) + else if (flags_from_decl_or_type (fn->decl) & ECF_LEAF) return all_module_statics; else return NULL; @@ -367,7 +365,7 @@ propagate_bits (ipa_reference_global_vars_info_t x_global, struct cgraph_node *x continue; /* Only look into nodes we can propagate something. */ - int flags = flags_from_decl_or_type (y->symbol.decl); + int flags = flags_from_decl_or_type (y->decl); if (avail > AVAIL_OVERWRITABLE || (avail == AVAIL_OVERWRITABLE && (flags & ECF_LEAF))) { @@ -462,11 +460,11 @@ analyze_function (struct cgraph_node *fn) tree var; local = init_function_info (fn); - for (i = 0; ipa_ref_list_reference_iterate (&fn->symbol.ref_list, i, ref); i++) + for (i = 0; ipa_ref_list_reference_iterate (&fn->ref_list, i, ref); i++) { if (!is_a <varpool_node> (ref->referred)) continue; - var = ipa_ref_varpool_node (ref)->symbol.decl; + var = ipa_ref_varpool_node (ref)->decl; if (!is_proper_for_analysis (var)) continue; switch (ref->use) @@ -564,7 +562,7 @@ generate_summary (void) l = &get_reference_vars_info (node)->local; fprintf (dump_file, "\nFunction name:%s/%i:", - cgraph_node_asm_name (node), node->symbol.order); + cgraph_node_asm_name (node), node->order); fprintf (dump_file, "\n locals read: "); if (l->statics_read) EXECUTE_IF_SET_IN_BITMAP (l->statics_read, @@ -589,7 +587,7 @@ static void read_write_all_from_decl (struct cgraph_node *node, bool &read_all, bool &write_all) { - tree decl = node->symbol.decl; + tree decl = node->decl; int flags = flags_from_decl_or_type (decl); if ((flags & ECF_LEAF) && cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE) @@ -602,7 +600,7 @@ read_write_all_from_decl (struct cgraph_node *node, read_all = true; if (dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, " %s/%i -> read all\n", - cgraph_node_asm_name (node), node->symbol.order); + cgraph_node_asm_name (node), node->order); } else { @@ -612,7 +610,7 @@ read_write_all_from_decl (struct cgraph_node *node, write_all = true; if (dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, " %s/%i -> read all, write all\n", - cgraph_node_asm_name (node), node->symbol.order); + cgraph_node_asm_name (node), node->order); } } @@ -679,12 +677,12 @@ propagate (void) /* Now we know what vars are really statics; prune out those that aren't. */ FOR_EACH_VARIABLE (vnode) - if (vnode->symbol.externally_visible - || TREE_ADDRESSABLE (vnode->symbol.decl) - || TREE_READONLY (vnode->symbol.decl) - || !is_proper_for_analysis (vnode->symbol.decl) - || !vnode->symbol.definition) - bitmap_clear_bit (all_module_statics, DECL_UID (vnode->symbol.decl)); + if (vnode->externally_visible + || TREE_ADDRESSABLE (vnode->decl) + || TREE_READONLY (vnode->decl) + || !is_proper_for_analysis (vnode->decl) + || !vnode->definition) + bitmap_clear_bit (all_module_statics, DECL_UID (vnode->decl)); /* Forget info we collected "just for fun" on variables that turned out to be non-local. */ @@ -715,7 +713,7 @@ propagate (void) bool write_all = false; node = order[i]; - if (node->symbol.alias) + if (node->alias) continue; node_info = get_reference_vars_info (node); @@ -725,7 +723,7 @@ propagate (void) if (dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, "Starting cycle with %s/%i\n", - cgraph_node_asm_name (node), node->symbol.order); + cgraph_node_asm_name (node), node->order); vec<cgraph_node_ptr> cycle_nodes = ipa_get_nodes_in_cycle (node); @@ -734,7 +732,7 @@ propagate (void) { if (dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, " Visiting %s/%i\n", - cgraph_node_asm_name (w), w->symbol.order); + cgraph_node_asm_name (w), w->order); get_read_write_all_from_node (w, read_all, write_all); if (read_all && write_all) break; @@ -761,7 +759,7 @@ propagate (void) { ipa_reference_vars_info_t w_ri = get_reference_vars_info (w); ipa_reference_local_vars_info_t w_l = &w_ri->local; - int flags = flags_from_decl_or_type (w->symbol.decl); + int flags = flags_from_decl_or_type (w->decl); if (!(flags & ECF_CONST)) read_all = union_static_var_sets (node_g->statics_read, @@ -793,12 +791,12 @@ propagate (void) struct cgraph_node *w; node = order[i]; - if (node->symbol.alias) + if (node->alias) continue; fprintf (dump_file, "\nFunction name:%s/%i:", - cgraph_node_asm_name (node), node->symbol.order); + cgraph_node_asm_name (node), node->order); ipa_reference_vars_info_t node_info = get_reference_vars_info (node); ipa_reference_global_vars_info_t node_g = &node_info->global; @@ -810,7 +808,7 @@ propagate (void) ipa_reference_local_vars_info_t w_l = &w_ri->local; if (w != node) fprintf (dump_file, "\n next cycle: %s/%i ", - cgraph_node_asm_name (w), w->symbol.order); + cgraph_node_asm_name (w), w->order); fprintf (dump_file, "\n locals read: "); dump_static_vars_set_to_file (dump_file, w_l->statics_read); fprintf (dump_file, "\n locals written: "); @@ -834,9 +832,9 @@ propagate (void) ipa_reference_optimization_summary_t opt; node_info = get_reference_vars_info (node); - if (!node->symbol.alias + if (!node->alias && (cgraph_function_body_availability (node) > AVAIL_OVERWRITABLE - || (flags_from_decl_or_type (node->symbol.decl) & ECF_LEAF))) + || (flags_from_decl_or_type (node->decl) & ECF_LEAF))) { node_g = &node_info->global; @@ -893,7 +891,7 @@ write_node_summary_p (struct cgraph_node *node, ipa_reference_optimization_summary_t info; /* See if we have (non-empty) info. */ - if (!node->symbol.definition || node->global.inlined_to) + if (!node->definition || node->global.inlined_to) return false; info = get_reference_optimization_summary (node); if (!info || (bitmap_empty_p (info->statics_not_read) @@ -907,7 +905,7 @@ write_node_summary_p (struct cgraph_node *node, In future we might also want to include summaries of functions references by initializers of constant variables references in current unit. */ if (!reachable_from_this_partition_p (node, encoder) - && !referenced_from_this_partition_p (&node->symbol.ref_list, encoder)) + && !referenced_from_this_partition_p (&node->ref_list, encoder)) return false; /* See if the info has non-empty intersections with vars we want to encode. */ @@ -970,13 +968,13 @@ ipa_reference_write_optimization_summary (void) /* See what variables we are interested in. */ for (i = 0; i < lto_symtab_encoder_size (encoder); i++) { - symtab_node snode = lto_symtab_encoder_deref (encoder, i); + symtab_node *snode = lto_symtab_encoder_deref (encoder, i); varpool_node *vnode = dyn_cast <varpool_node> (snode); if (vnode - && bitmap_bit_p (all_module_statics, DECL_UID (vnode->symbol.decl)) - && referenced_from_this_partition_p (&vnode->symbol.ref_list, encoder)) + && bitmap_bit_p (all_module_statics, DECL_UID (vnode->decl)) + && referenced_from_this_partition_p (&vnode->ref_list, encoder)) { - tree decl = vnode->symbol.decl; + tree decl = vnode->decl; bitmap_set_bit (ltrans_statics, DECL_UID (decl)); splay_tree_insert (reference_vars_to_consider, DECL_UID (decl), (splay_tree_value)decl); @@ -988,7 +986,7 @@ ipa_reference_write_optimization_summary (void) if (ltrans_statics_bitcount) for (i = 0; i < lto_symtab_encoder_size (encoder); i++) { - symtab_node snode = lto_symtab_encoder_deref (encoder, i); + symtab_node *snode = lto_symtab_encoder_deref (encoder, i); cgraph_node *cnode = dyn_cast <cgraph_node> (snode); if (cnode && write_node_summary_p (cnode, encoder, ltrans_statics)) count++; @@ -1003,7 +1001,7 @@ ipa_reference_write_optimization_summary (void) if (ltrans_statics_bitcount) for (i = 0; i < lto_symtab_encoder_size (encoder); i++) { - symtab_node snode = lto_symtab_encoder_deref (encoder, i); + symtab_node *snode = lto_symtab_encoder_deref (encoder, i); cgraph_node *cnode = dyn_cast <cgraph_node> (snode); if (cnode && write_node_summary_p (cnode, encoder, ltrans_statics)) { @@ -1088,7 +1086,7 @@ ipa_reference_read_optimization_summary (void) if (dump_file) fprintf (dump_file, "\nFunction name:%s/%i:\n static not read:", - cgraph_node_asm_name (node), node->symbol.order); + cgraph_node_asm_name (node), node->order); /* Set the statics not read. */ v_count = streamer_read_hwi (ib); diff --git a/gcc/ipa-reference.h b/gcc/ipa-reference.h index c1e910e481a..317ebb02de2 100644 --- a/gcc/ipa-reference.h +++ b/gcc/ipa-reference.h @@ -21,7 +21,7 @@ along with GCC; see the file COPYING3. If not see #ifndef GCC_IPA_REFERENCE_H #define GCC_IPA_REFERENCE_H #include "bitmap.h" -#include "tree.h" +#include "cgraph.h" /* In ipa-reference.c */ bitmap ipa_reference_get_not_read_global (struct cgraph_node *fn); diff --git a/gcc/ipa-split.c b/gcc/ipa-split.c index 874e7b83542..849868ca68c 100644 --- a/gcc/ipa-split.c +++ b/gcc/ipa-split.c @@ -78,10 +78,16 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "tree.h" +#include "gimple.h" #include "target.h" -#include "cgraph.h" #include "ipa-prop.h" -#include "tree-ssa.h" +#include "gimple-ssa.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" +#include "tree-into-ssa.h" +#include "tree-dfa.h" #include "tree-pass.h" #include "flags.h" #include "diagnostic.h" @@ -1217,20 +1223,20 @@ split_function (struct split_point *split_point) /* For usual cloning it is enough to clear builtin only when signature changes. For partial inlining we however can not expect the part of builtin implementation to have same semantic as the whole. */ - if (DECL_BUILT_IN (node->symbol.decl)) + if (DECL_BUILT_IN (node->decl)) { - DECL_BUILT_IN_CLASS (node->symbol.decl) = NOT_BUILT_IN; - DECL_FUNCTION_CODE (node->symbol.decl) = (enum built_in_function) 0; + DECL_BUILT_IN_CLASS (node->decl) = NOT_BUILT_IN; + DECL_FUNCTION_CODE (node->decl) = (enum built_in_function) 0; } /* If the original function is declared inline, there is no point in issuing a warning for the non-inlinable part. */ - DECL_NO_INLINE_WARNING_P (node->symbol.decl) = 1; + DECL_NO_INLINE_WARNING_P (node->decl) = 1; cgraph_node_remove_callees (cur_node); - ipa_remove_all_references (&cur_node->symbol.ref_list); + ipa_remove_all_references (&cur_node->ref_list); if (!split_part_return_p) - TREE_THIS_VOLATILE (node->symbol.decl) = 1; + TREE_THIS_VOLATILE (node->decl) = 1; if (dump_file) - dump_function_to_file (node->symbol.decl, dump_file, dump_flags); + dump_function_to_file (node->decl, dump_file, dump_flags); /* Create the basic block we place call into. It is the entry basic block split after last label. */ @@ -1255,7 +1261,7 @@ split_function (struct split_point *split_point) false, GSI_CONTINUE_LINKING); args_to_pass[i] = arg; } - call = gimple_build_call_vec (node->symbol.decl, args_to_pass); + call = gimple_build_call_vec (node->decl, args_to_pass); gimple_set_block (call, DECL_INITIAL (current_function_decl)); args_to_pass.release (); @@ -1282,7 +1288,7 @@ split_function (struct split_point *split_point) continue; if (debug_args == NULL) - debug_args = decl_debug_args_insert (node->symbol.decl); + debug_args = decl_debug_args_insert (node->decl); ddecl = make_node (DEBUG_EXPR_DECL); DECL_ARTIFICIAL (ddecl) = 1; TREE_TYPE (ddecl) = TREE_TYPE (parm); @@ -1308,8 +1314,8 @@ split_function (struct split_point *split_point) gimple_stmt_iterator cgsi; gimple def_temp; - push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl)); - var = BLOCK_VARS (DECL_INITIAL (node->symbol.decl)); + push_cfun (DECL_STRUCT_FUNCTION (node->decl)); + var = BLOCK_VARS (DECL_INITIAL (node->decl)); i = vec_safe_length (*debug_args); cgsi = gsi_after_labels (single_succ (ENTRY_BLOCK_PTR)); do @@ -1509,7 +1515,7 @@ execute_split_functions (void) fprintf (dump_file, "Not splitting: not inlinable.\n"); return 0; } - if (DECL_DISREGARD_INLINE_LIMITS (node->symbol.decl)) + if (DECL_DISREGARD_INLINE_LIMITS (node->decl)) { if (dump_file) fprintf (dump_file, "Not splitting: disregarding inline limits.\n"); @@ -1543,8 +1549,8 @@ execute_split_functions (void) if ((!node->callers /* Local functions called once will be completely inlined most of time. */ || (!node->callers->next_caller && node->local.local)) - && !node->symbol.address_taken - && (!flag_lto || !node->symbol.externally_visible)) + && !node->address_taken + && (!flag_lto || !node->externally_visible)) { if (dump_file) fprintf (dump_file, "Not splitting: not called directly " diff --git a/gcc/ipa-utils.c b/gcc/ipa-utils.c index 5802884afdf..84108166e66 100644 --- a/gcc/ipa-utils.c +++ b/gcc/ipa-utils.c @@ -23,7 +23,7 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tm.h" #include "tree.h" -#include "tree-ssa.h" +#include "gimple.h" #include "tree-inline.h" #include "dumpfile.h" #include "langhooks.h" @@ -32,8 +32,6 @@ along with GCC; see the file COPYING3. If not see #include "ggc.h" #include "ipa-utils.h" #include "ipa-reference.h" -#include "gimple.h" -#include "cgraph.h" #include "flags.h" #include "diagnostic.h" #include "langhooks.h" @@ -86,7 +84,7 @@ searchc (struct searchc_env* env, struct cgraph_node *v, bool (*ignore_edge) (struct cgraph_edge *)) { struct cgraph_edge *edge; - struct ipa_dfs_info *v_info = (struct ipa_dfs_info *) v->symbol.aux; + struct ipa_dfs_info *v_info = (struct ipa_dfs_info *) v->aux; /* mark node as old */ v_info->new_node = false; @@ -107,11 +105,11 @@ searchc (struct searchc_env* env, struct cgraph_node *v, if (!w || (ignore_edge && ignore_edge (edge))) continue; - if (w->symbol.aux + if (w->aux && (avail > AVAIL_OVERWRITABLE || (env->allow_overwritable && avail == AVAIL_OVERWRITABLE))) { - w_info = (struct ipa_dfs_info *) w->symbol.aux; + w_info = (struct ipa_dfs_info *) w->aux; if (w_info->new_node) { searchc (env, w, ignore_edge); @@ -136,7 +134,7 @@ searchc (struct searchc_env* env, struct cgraph_node *v, struct ipa_dfs_info *x_info; do { x = env->stack[--(env->stack_size)]; - x_info = (struct ipa_dfs_info *) x->symbol.aux; + x_info = (struct ipa_dfs_info *) x->aux; x_info->on_stack = false; x_info->scc_no = v_info->dfn_number; @@ -190,20 +188,20 @@ ipa_reduced_postorder (struct cgraph_node **order, && (avail == AVAIL_OVERWRITABLE))) { /* Reuse the info if it is already there. */ - struct ipa_dfs_info *info = (struct ipa_dfs_info *) node->symbol.aux; + struct ipa_dfs_info *info = (struct ipa_dfs_info *) node->aux; if (!info) info = XCNEW (struct ipa_dfs_info); info->new_node = true; info->on_stack = false; info->next_cycle = NULL; - node->symbol.aux = info; + node->aux = info; splay_tree_insert (env.nodes_marked_new, (splay_tree_key)node->uid, (splay_tree_value)node); } else - node->symbol.aux = NULL; + node->aux = NULL; } result = splay_tree_min (env.nodes_marked_new); while (result) @@ -228,10 +226,10 @@ ipa_free_postorder_info (void) FOR_EACH_DEFINED_FUNCTION (node) { /* Get rid of the aux information. */ - if (node->symbol.aux) + if (node->aux) { - free (node->symbol.aux); - node->symbol.aux = NULL; + free (node->aux); + node->aux = NULL; } } } @@ -247,7 +245,7 @@ ipa_get_nodes_in_cycle (struct cgraph_node *node) while (node) { v.safe_push (node); - node_dfs_info = (struct ipa_dfs_info *) node->symbol.aux; + node_dfs_info = (struct ipa_dfs_info *) node->aux; node = node_dfs_info->next_cycle; } return v; @@ -259,11 +257,11 @@ ipa_get_nodes_in_cycle (struct cgraph_node *node) bool ipa_edge_within_scc (struct cgraph_edge *cs) { - struct ipa_dfs_info *caller_dfs = (struct ipa_dfs_info *) cs->caller->symbol.aux; + struct ipa_dfs_info *caller_dfs = (struct ipa_dfs_info *) cs->caller->aux; struct ipa_dfs_info *callee_dfs; struct cgraph_node *callee = cgraph_function_node (cs->callee, NULL); - callee_dfs = (struct ipa_dfs_info *) callee->symbol.aux; + callee_dfs = (struct ipa_dfs_info *) callee->aux; return (caller_dfs && callee_dfs && caller_dfs->scc_no == callee_dfs->scc_no); @@ -298,21 +296,21 @@ ipa_reverse_postorder (struct cgraph_node **order) to be output and put them into order as well, so we get dependencies right through inline functions. */ FOR_EACH_FUNCTION (node) - node->symbol.aux = NULL; + node->aux = NULL; for (pass = 0; pass < 2; pass++) FOR_EACH_FUNCTION (node) - if (!node->symbol.aux + if (!node->aux && (pass - || (!node->symbol.address_taken + || (!node->address_taken && !node->global.inlined_to - && !node->symbol.alias && !node->thunk.thunk_p + && !node->alias && !node->thunk.thunk_p && !cgraph_only_called_directly_p (node)))) { stack_size = 0; stack[stack_size].node = node; stack[stack_size].edge = node->callers; stack[stack_size].ref = 0; - node->symbol.aux = (void *)(size_t)1; + node->aux = (void *)(size_t)1; while (stack_size >= 0) { while (true) @@ -326,12 +324,12 @@ ipa_reverse_postorder (struct cgraph_node **order) /* Break possible cycles involving always-inline functions by ignoring edges from always-inline functions to non-always-inline functions. */ - if (DECL_DISREGARD_INLINE_LIMITS (edge->caller->symbol.decl) + if (DECL_DISREGARD_INLINE_LIMITS (edge->caller->decl) && !DECL_DISREGARD_INLINE_LIMITS - (cgraph_function_node (edge->callee, NULL)->symbol.decl)) + (cgraph_function_node (edge->callee, NULL)->decl)) node2 = NULL; } - for (;ipa_ref_list_referring_iterate (&stack[stack_size].node->symbol.ref_list, + for (;ipa_ref_list_referring_iterate (&stack[stack_size].node->ref_list, stack[stack_size].ref, ref) && !node2; stack[stack_size].ref++) @@ -341,12 +339,12 @@ ipa_reverse_postorder (struct cgraph_node **order) } if (!node2) break; - if (!node2->symbol.aux) + if (!node2->aux) { stack[++stack_size].node = node2; stack[stack_size].edge = node2->callers; stack[stack_size].ref = 0; - node2->symbol.aux = (void *)(size_t)1; + node2->aux = (void *)(size_t)1; } } order[order_pos++] = stack[stack_size--].node; @@ -354,7 +352,7 @@ ipa_reverse_postorder (struct cgraph_node **order) } free (stack); FOR_EACH_FUNCTION (node) - node->symbol.aux = NULL; + node->aux = NULL; return order_pos; } @@ -483,7 +481,7 @@ dump_cgraph_node_set (FILE *f, cgraph_node_set set) for (iter = csi_start (set); !csi_end_p (iter); csi_next (&iter)) { struct cgraph_node *node = csi_node (iter); - fprintf (f, " %s/%i", cgraph_node_name (node), node->symbol.order); + fprintf (f, " %s/%i", cgraph_node_name (node), node->order); } fprintf (f, "\n"); } @@ -645,12 +643,12 @@ void ipa_merge_profiles (struct cgraph_node *dst, struct cgraph_node *src) { - tree oldsrcdecl = src->symbol.decl; + tree oldsrcdecl = src->decl; struct function *srccfun, *dstcfun; bool match = true; - if (!src->symbol.definition - || !dst->symbol.definition) + if (!src->definition + || !dst->definition) return; if (src->frequency < dst->frequency) src->frequency = dst->frequency; @@ -659,8 +657,8 @@ ipa_merge_profiles (struct cgraph_node *dst, if (cgraph_dump_file) { fprintf (cgraph_dump_file, "Merging profiles of %s/%i to %s/%i\n", - xstrdup (cgraph_node_name (src)), src->symbol.order, - xstrdup (cgraph_node_name (dst)), dst->symbol.order); + xstrdup (cgraph_node_name (src)), src->order, + xstrdup (cgraph_node_name (dst)), dst->order); } dst->count += src->count; @@ -668,7 +666,7 @@ ipa_merge_profiles (struct cgraph_node *dst, If declaration is merged, we need to duplicate it to be able to load body that is being replaced. This makes symbol table temporarily inconsistent. */ - if (src->symbol.decl == dst->symbol.decl) + if (src->decl == dst->decl) { void **slot; struct lto_in_decl_state temp; @@ -676,32 +674,32 @@ ipa_merge_profiles (struct cgraph_node *dst, /* We are going to move the decl, we want to remove its file decl data. and link these with the new decl. */ - temp.fn_decl = src->symbol.decl; - slot = htab_find_slot (src->symbol.lto_file_data->function_decl_states, + temp.fn_decl = src->decl; + slot = htab_find_slot (src->lto_file_data->function_decl_states, &temp, NO_INSERT); state = (lto_in_decl_state *)*slot; - htab_clear_slot (src->symbol.lto_file_data->function_decl_states, slot); + htab_clear_slot (src->lto_file_data->function_decl_states, slot); gcc_assert (state); /* Duplicate the decl and be sure it does not link into body of DST. */ - src->symbol.decl = copy_node (src->symbol.decl); - DECL_STRUCT_FUNCTION (src->symbol.decl) = NULL; - DECL_ARGUMENTS (src->symbol.decl) = NULL; - DECL_INITIAL (src->symbol.decl) = NULL; - DECL_RESULT (src->symbol.decl) = NULL; + src->decl = copy_node (src->decl); + DECL_STRUCT_FUNCTION (src->decl) = NULL; + DECL_ARGUMENTS (src->decl) = NULL; + DECL_INITIAL (src->decl) = NULL; + DECL_RESULT (src->decl) = NULL; /* Associate the decl state with new declaration, so LTO streamer can look it up. */ - state->fn_decl = src->symbol.decl; - slot = htab_find_slot (src->symbol.lto_file_data->function_decl_states, + state->fn_decl = src->decl; + slot = htab_find_slot (src->lto_file_data->function_decl_states, state, INSERT); gcc_assert (!*slot); *slot = state; } cgraph_get_body (src); cgraph_get_body (dst); - srccfun = DECL_STRUCT_FUNCTION (src->symbol.decl); - dstcfun = DECL_STRUCT_FUNCTION (dst->symbol.decl); + srccfun = DECL_STRUCT_FUNCTION (src->decl); + dstcfun = DECL_STRUCT_FUNCTION (dst->decl); if (n_basic_blocks_for_function (srccfun) != n_basic_blocks_for_function (dstcfun)) { @@ -789,7 +787,7 @@ ipa_merge_profiles (struct cgraph_node *dst, gcc_assert (!e->speculative); e->count = gimple_bb (e->call_stmt)->count; e->frequency = compute_call_stmt_bb_frequency - (dst->symbol.decl, + (dst->decl, gimple_bb (e->call_stmt)); } for (e = dst->indirect_calls; e; e = e->next_callee) @@ -797,14 +795,14 @@ ipa_merge_profiles (struct cgraph_node *dst, gcc_assert (!e->speculative); e->count = gimple_bb (e->call_stmt)->count; e->frequency = compute_call_stmt_bb_frequency - (dst->symbol.decl, + (dst->decl, gimple_bb (e->call_stmt)); } cgraph_release_function_body (src); inline_update_overall_summary (dst); } /* TODO: if there is no match, we can scale up. */ - src->symbol.decl = oldsrcdecl; + src->decl = oldsrcdecl; } /* Return true if call to DEST is known to be self-recusive call withing FUNC. */ @@ -815,6 +813,6 @@ recursive_call_p (tree func, tree dest) struct cgraph_node *dest_node = cgraph_get_create_node (dest); struct cgraph_node *cnode = cgraph_get_create_node (func); - return symtab_semantically_equivalent_p ((symtab_node)dest_node, - (symtab_node)cnode); + return symtab_semantically_equivalent_p (dest_node, + cnode); } diff --git a/gcc/ipa-utils.h b/gcc/ipa-utils.h index 15f312e6065..ca8b87290b5 100644 --- a/gcc/ipa-utils.h +++ b/gcc/ipa-utils.h @@ -20,7 +20,6 @@ along with GCC; see the file COPYING3. If not see #ifndef GCC_IPA_UTILS_H #define GCC_IPA_UTILS_H -#include "tree.h" #include "cgraph.h" struct ipa_dfs_info { diff --git a/gcc/ipa.c b/gcc/ipa.c index 92343fb22c9..aef437a46f5 100644 --- a/gcc/ipa.c +++ b/gcc/ipa.c @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "tm.h" +#include "tree.h" #include "cgraph.h" #include "tree-pass.h" #include "gimple.h" @@ -42,12 +43,12 @@ cgraph_non_local_node_p_1 (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED { /* FIXME: Aliases can be local, but i386 gets thunks wrong then. */ return !(cgraph_only_called_directly_or_aliased_p (node) - && !ipa_ref_has_aliases_p (&node->symbol.ref_list) - && node->symbol.definition - && !DECL_EXTERNAL (node->symbol.decl) - && !node->symbol.externally_visible - && !node->symbol.used_from_other_partition - && !node->symbol.in_other_partition); + && !ipa_ref_has_aliases_p (&node->ref_list) + && node->definition + && !DECL_EXTERNAL (node->decl) + && !node->externally_visible + && !node->used_from_other_partition + && !node->in_other_partition); } /* Return true when function can be marked local. */ @@ -75,7 +76,7 @@ has_addr_references_p (struct cgraph_node *node, int i; struct ipa_ref *ref; - for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list, + for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list, i, ref); i++) if (ref->use == IPA_REF_ADDR) return true; @@ -106,17 +107,17 @@ update_inlined_to_pointer (struct cgraph_node *node, struct cgraph_node *inlined reachable. */ static void -enqueue_node (symtab_node node, symtab_node *first, +enqueue_node (symtab_node *node, symtab_node **first, struct pointer_set_t *reachable) { /* Node is still in queue; do nothing. */ - if (node->symbol.aux && node->symbol.aux != (void *) 2) + if (node->aux && node->aux != (void *) 2) return; /* Node was already processed as unreachable, re-enqueue only if it became reachable now. */ - if (node->symbol.aux == (void *)2 && !pointer_set_contains (reachable, node)) + if (node->aux == (void *)2 && !pointer_set_contains (reachable, node)) return; - node->symbol.aux = *first; + node->aux = *first; *first = node; } @@ -124,7 +125,7 @@ enqueue_node (symtab_node node, symtab_node *first, static void process_references (struct ipa_ref_list *list, - symtab_node *first, + symtab_node **first, bool before_inlining_p, struct pointer_set_t *reachable) { @@ -132,20 +133,20 @@ process_references (struct ipa_ref_list *list, struct ipa_ref *ref; for (i = 0; ipa_ref_list_reference_iterate (list, i, ref); i++) { - symtab_node node = ref->referred; + symtab_node *node = ref->referred; - if (node->symbol.definition && !node->symbol.in_other_partition - && ((!DECL_EXTERNAL (node->symbol.decl) || node->symbol.alias) + if (node->definition && !node->in_other_partition + && ((!DECL_EXTERNAL (node->decl) || node->alias) || (before_inlining_p /* We use variable constructors during late complation for constant folding. Keep references alive so partitioning knows about potential references. */ - || (TREE_CODE (node->symbol.decl) == VAR_DECL + || (TREE_CODE (node->decl) == VAR_DECL && flag_wpa - && ctor_for_folding (node->symbol.decl) + && ctor_for_folding (node->decl) != error_mark_node)))) pointer_set_insert (reachable, node); - enqueue_node ((symtab_node) node, first, reachable); + enqueue_node (node, first, reachable); } } @@ -160,7 +161,7 @@ process_references (struct ipa_ref_list *list, static void walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets, struct cgraph_edge *edge, - symtab_node *first, + symtab_node **first, pointer_set_t *reachable, bool before_inlining_p) { unsigned int i; @@ -180,21 +181,21 @@ walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets, /* Do not bother to mark virtual methods in anonymous namespace; either we will find use of virtual table defining it, or it is unused. */ - if (TREE_CODE (TREE_TYPE (n->symbol.decl)) == METHOD_TYPE + if (TREE_CODE (TREE_TYPE (n->decl)) == METHOD_TYPE && type_in_anonymous_namespace_p - (method_class_type (TREE_TYPE (n->symbol.decl)))) + (method_class_type (TREE_TYPE (n->decl)))) continue; /* Prior inlining, keep alive bodies of possible targets for devirtualization. */ - if (n->symbol.definition + if (n->definition && before_inlining_p) pointer_set_insert (reachable, n); /* Even after inlining we want to keep the possible targets in the boundary, so late passes can still produce direct call even if the chance for inlining is lost. */ - enqueue_node ((symtab_node) n, first, reachable); + enqueue_node (n, first, reachable); } } @@ -217,8 +218,8 @@ walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets, fprintf (dump_file, "Devirtualizing call in %s/%i to %s/%i\n", cgraph_node_name (edge->caller), - edge->caller->symbol.order, - cgraph_node_name (target), target->symbol.order); + edge->caller->order, + cgraph_node_name (target), target->order); edge = cgraph_make_edge_direct (edge, target); if (!inline_summary_vec && edge->call_stmt) cgraph_redirect_edge_call_stmt_to_callee (edge); @@ -286,7 +287,7 @@ walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets, bool symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file) { - symtab_node first = (symtab_node) (void *) 1; + symtab_node *first = (symtab_node *) (void *) 1; struct cgraph_node *node, *next; struct varpool_node *vnode, *vnext; bool changed = false; @@ -304,9 +305,9 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file) fprintf (file, "\nReclaiming functions:"); #ifdef ENABLE_CHECKING FOR_EACH_FUNCTION (node) - gcc_assert (!node->symbol.aux); + gcc_assert (!node->aux); FOR_EACH_VARIABLE (vnode) - gcc_assert (!vnode->symbol.aux); + gcc_assert (!vnode->aux); #endif /* Mark functions whose bodies are obviously needed. This is mostly when they can be referenced externally. Inline clones @@ -315,62 +316,62 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file) FOR_EACH_FUNCTION (node) { node->used_as_abstract_origin = false; - if (node->symbol.definition + if (node->definition && !node->global.inlined_to - && !node->symbol.in_other_partition + && !node->in_other_partition && !cgraph_can_remove_if_no_direct_calls_and_refs_p (node)) { gcc_assert (!node->global.inlined_to); pointer_set_insert (reachable, node); - enqueue_node ((symtab_node)node, &first, reachable); + enqueue_node (node, &first, reachable); } else - gcc_assert (!node->symbol.aux); + gcc_assert (!node->aux); } /* Mark variables that are obviously needed. */ FOR_EACH_DEFINED_VARIABLE (vnode) if (!varpool_can_remove_if_no_refs (vnode) - && !vnode->symbol.in_other_partition) + && !vnode->in_other_partition) { pointer_set_insert (reachable, vnode); - enqueue_node ((symtab_node)vnode, &first, reachable); + enqueue_node (vnode, &first, reachable); } /* Perform reachability analysis. */ - while (first != (symtab_node) (void *) 1) + while (first != (symtab_node *) (void *) 1) { bool in_boundary_p = !pointer_set_contains (reachable, first); - symtab_node node = first; + symtab_node *node = first; - first = (symtab_node)first->symbol.aux; + first = (symtab_node *)first->aux; /* If we are processing symbol in boundary, mark its AUX pointer for possible later re-processing in enqueue_node. */ if (in_boundary_p) - node->symbol.aux = (void *)2; + node->aux = (void *)2; else { - if (DECL_ABSTRACT_ORIGIN (node->symbol.decl)) + if (DECL_ABSTRACT_ORIGIN (node->decl)) { struct cgraph_node *origin_node - = cgraph_get_create_real_symbol_node (DECL_ABSTRACT_ORIGIN (node->symbol.decl)); + = cgraph_get_create_real_symbol_node (DECL_ABSTRACT_ORIGIN (node->decl)); origin_node->used_as_abstract_origin = true; - enqueue_node ((symtab_node) origin_node, &first, reachable); + enqueue_node (origin_node, &first, reachable); } /* If any symbol in a comdat group is reachable, force all other in the same comdat group to be also reachable. */ - if (node->symbol.same_comdat_group) + if (node->same_comdat_group) { - symtab_node next; - for (next = node->symbol.same_comdat_group; + symtab_node *next; + for (next = node->same_comdat_group; next != node; - next = next->symbol.same_comdat_group) + next = next->same_comdat_group) if (!pointer_set_insert (reachable, next)) - enqueue_node ((symtab_node) next, &first, reachable); + enqueue_node (next, &first, reachable); } /* Mark references as reachable. */ - process_references (&node->symbol.ref_list, &first, + process_references (&node->ref_list, &first, before_inlining_p, reachable); } @@ -396,31 +397,31 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file) } for (e = cnode->callees; e; e = e->next_callee) { - if (e->callee->symbol.definition - && !e->callee->symbol.in_other_partition + if (e->callee->definition + && !e->callee->in_other_partition && (!e->inline_failed - || !DECL_EXTERNAL (e->callee->symbol.decl) - || e->callee->symbol.alias + || !DECL_EXTERNAL (e->callee->decl) + || e->callee->alias || before_inlining_p)) pointer_set_insert (reachable, e->callee); - enqueue_node ((symtab_node) e->callee, &first, reachable); + enqueue_node (e->callee, &first, reachable); } /* When inline clone exists, mark body to be preserved so when removing offline copy of the function we don't kill it. */ if (cnode->global.inlined_to) - pointer_set_insert (body_needed_for_clonning, cnode->symbol.decl); + pointer_set_insert (body_needed_for_clonning, cnode->decl); /* For non-inline clones, force their origins to the boundary and ensure that body is not removed. */ while (cnode->clone_of) { - bool noninline = cnode->clone_of->symbol.decl != cnode->symbol.decl; + bool noninline = cnode->clone_of->decl != cnode->decl; cnode = cnode->clone_of; if (noninline) { - pointer_set_insert (body_needed_for_clonning, cnode->symbol.decl); - enqueue_node ((symtab_node)cnode, &first, reachable); + pointer_set_insert (body_needed_for_clonning, cnode->decl); + enqueue_node (cnode, &first, reachable); } } } @@ -430,12 +431,12 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file) refers to. */ varpool_node *vnode = dyn_cast <varpool_node> (node); if (vnode - && DECL_EXTERNAL (node->symbol.decl) - && !vnode->symbol.alias + && DECL_EXTERNAL (node->decl) + && !vnode->alias && in_boundary_p) { struct ipa_ref *ref; - for (int i = 0; ipa_ref_list_reference_iterate (&node->symbol.ref_list, i, ref); i++) + for (int i = 0; ipa_ref_list_reference_iterate (&node->ref_list, i, ref); i++) enqueue_node (ref->referred, &first, reachable); } } @@ -446,7 +447,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file) next = cgraph_next_function (node); /* If node is not needed at all, remove it. */ - if (!node->symbol.aux) + if (!node->aux) { if (file) fprintf (file, " %s", cgraph_node_name (node)); @@ -456,29 +457,29 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file) /* If node is unreachable, remove its body. */ else if (!pointer_set_contains (reachable, node)) { - if (!pointer_set_contains (body_needed_for_clonning, node->symbol.decl)) + if (!pointer_set_contains (body_needed_for_clonning, node->decl)) cgraph_release_function_body (node); else if (!node->clone_of) - gcc_assert (in_lto_p || DECL_RESULT (node->symbol.decl)); - if (node->symbol.definition) + gcc_assert (in_lto_p || DECL_RESULT (node->decl)); + if (node->definition) { if (file) fprintf (file, " %s", cgraph_node_name (node)); - node->symbol.analyzed = false; - node->symbol.definition = false; - node->symbol.cpp_implicit_alias = false; - node->symbol.alias = false; - node->symbol.weakref = false; - if (!node->symbol.in_other_partition) + node->analyzed = false; + node->definition = false; + node->cpp_implicit_alias = false; + node->alias = false; + node->weakref = false; + if (!node->in_other_partition) node->local.local = false; cgraph_node_remove_callees (node); - ipa_remove_all_references (&node->symbol.ref_list); + ipa_remove_all_references (&node->ref_list); changed = true; } } else gcc_assert (node->clone_of || !cgraph_function_with_gimple_body_p (node) - || in_lto_p || DECL_RESULT (node->symbol.decl)); + || in_lto_p || DECL_RESULT (node->decl)); } /* Inline clones might be kept around so their materializing allows further @@ -493,7 +494,7 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file) node->global.inlined_to = NULL; update_inlined_to_pointer (node, node); } - node->symbol.aux = NULL; + node->aux = NULL; } /* Remove unreachable variables. */ @@ -502,11 +503,11 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file) for (vnode = varpool_first_variable (); vnode; vnode = vnext) { vnext = varpool_next_variable (vnode); - if (!vnode->symbol.aux + if (!vnode->aux /* For can_refer_decl_in_current_unit_p we want to track for all external variables if they are defined in other partition or not. */ - && (!flag_ltrans || !DECL_EXTERNAL (vnode->symbol.decl))) + && (!flag_ltrans || !DECL_EXTERNAL (vnode->decl))) { if (file) fprintf (file, " %s", varpool_node_name (vnode)); @@ -516,25 +517,25 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file) else if (!pointer_set_contains (reachable, vnode)) { tree init; - if (vnode->symbol.definition) + if (vnode->definition) { if (file) fprintf (file, " %s", varpool_node_name (vnode)); changed = true; } - vnode->symbol.definition = false; - vnode->symbol.analyzed = false; - vnode->symbol.aux = NULL; + vnode->definition = false; + vnode->analyzed = false; + vnode->aux = NULL; /* Keep body if it may be useful for constant folding. */ - if ((init = ctor_for_folding (vnode->symbol.decl)) == error_mark_node) + if ((init = ctor_for_folding (vnode->decl)) == error_mark_node) varpool_remove_initializer (vnode); else - DECL_INITIAL (vnode->symbol.decl) = init; - ipa_remove_all_references (&vnode->symbol.ref_list); + DECL_INITIAL (vnode->decl) = init; + ipa_remove_all_references (&vnode->ref_list); } else - vnode->symbol.aux = NULL; + vnode->aux = NULL; } pointer_set_destroy (reachable); @@ -545,14 +546,14 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file) if (file) fprintf (file, "\nClearing address taken flags:"); FOR_EACH_DEFINED_FUNCTION (node) - if (node->symbol.address_taken - && !node->symbol.used_from_other_partition) + if (node->address_taken + && !node->used_from_other_partition) { if (!cgraph_for_node_and_aliases (node, has_addr_references_p, NULL, true)) { if (file) fprintf (file, " %s", cgraph_node_name (node)); - node->symbol.address_taken = false; + node->address_taken = false; changed = true; if (cgraph_local_node_p (node)) { @@ -594,15 +595,15 @@ ipa_discover_readonly_nonaddressable_vars (void) if (dump_file) fprintf (dump_file, "Clearing variable flags:"); FOR_EACH_VARIABLE (vnode) - if (vnode->symbol.definition && varpool_all_refs_explicit_p (vnode) - && (TREE_ADDRESSABLE (vnode->symbol.decl) - || !TREE_READONLY (vnode->symbol.decl))) + if (vnode->definition && varpool_all_refs_explicit_p (vnode) + && (TREE_ADDRESSABLE (vnode->decl) + || !TREE_READONLY (vnode->decl))) { bool written = false; bool address_taken = false; int i; struct ipa_ref *ref; - for (i = 0; ipa_ref_list_referring_iterate (&vnode->symbol.ref_list, + for (i = 0; ipa_ref_list_referring_iterate (&vnode->ref_list, i, ref) && (!written || !address_taken); i++) switch (ref->use) @@ -616,21 +617,21 @@ ipa_discover_readonly_nonaddressable_vars (void) written = true; break; } - if (TREE_ADDRESSABLE (vnode->symbol.decl) && !address_taken) + if (TREE_ADDRESSABLE (vnode->decl) && !address_taken) { if (dump_file) fprintf (dump_file, " %s (addressable)", varpool_node_name (vnode)); - TREE_ADDRESSABLE (vnode->symbol.decl) = 0; + TREE_ADDRESSABLE (vnode->decl) = 0; } - if (!TREE_READONLY (vnode->symbol.decl) && !address_taken && !written + if (!TREE_READONLY (vnode->decl) && !address_taken && !written /* Making variable in explicit section readonly can cause section type conflict. See e.g. gcc.c-torture/compile/pr23237.c */ - && DECL_SECTION_NAME (vnode->symbol.decl) == NULL) + && DECL_SECTION_NAME (vnode->decl) == NULL) { if (dump_file) fprintf (dump_file, " %s (read-only)", varpool_node_name (vnode)); - TREE_READONLY (vnode->symbol.decl) = 1; + TREE_READONLY (vnode->decl) = 1; } } if (dump_file) @@ -639,11 +640,11 @@ ipa_discover_readonly_nonaddressable_vars (void) /* Return true when there is a reference to node and it is not vtable. */ static bool -address_taken_from_non_vtable_p (symtab_node node) +address_taken_from_non_vtable_p (symtab_node *node) { int i; struct ipa_ref *ref; - for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list, + for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list, i, ref); i++) if (ref->use == IPA_REF_ADDR) { @@ -651,7 +652,7 @@ address_taken_from_non_vtable_p (symtab_node node) if (is_a <cgraph_node> (ref->referring)) return true; node = ipa_ref_referring_varpool_node (ref); - if (!DECL_VIRTUAL_P (node->symbol.decl)) + if (!DECL_VIRTUAL_P (node->decl)) return true; } return false; @@ -660,35 +661,35 @@ address_taken_from_non_vtable_p (symtab_node node) /* A helper for comdat_can_be_unshared_p. */ static bool -comdat_can_be_unshared_p_1 (symtab_node node) +comdat_can_be_unshared_p_1 (symtab_node *node) { /* When address is taken, we don't know if equality comparison won't break eventually. Exception are virutal functions, C++ constructors/destructors and vtables, where this is not possible by language standard. */ - if (!DECL_VIRTUAL_P (node->symbol.decl) - && (TREE_CODE (node->symbol.decl) != FUNCTION_DECL - || (!DECL_CXX_CONSTRUCTOR_P (node->symbol.decl) - && !DECL_CXX_DESTRUCTOR_P (node->symbol.decl))) + if (!DECL_VIRTUAL_P (node->decl) + && (TREE_CODE (node->decl) != FUNCTION_DECL + || (!DECL_CXX_CONSTRUCTOR_P (node->decl) + && !DECL_CXX_DESTRUCTOR_P (node->decl))) && address_taken_from_non_vtable_p (node)) return false; /* If the symbol is used in some weird way, better to not touch it. */ - if (node->symbol.force_output) + if (node->force_output) return false; /* Explicit instantiations needs to be output when possibly used externally. */ - if (node->symbol.forced_by_abi - && TREE_PUBLIC (node->symbol.decl) - && (node->symbol.resolution != LDPR_PREVAILING_DEF_IRONLY + if (node->forced_by_abi + && TREE_PUBLIC (node->decl) + && (node->resolution != LDPR_PREVAILING_DEF_IRONLY && !flag_whole_program)) return false; /* Non-readonly and volatile variables can not be duplicated. */ if (is_a <varpool_node> (node) - && (!TREE_READONLY (node->symbol.decl) - || TREE_THIS_VOLATILE (node->symbol.decl))) + && (!TREE_READONLY (node->decl) + || TREE_THIS_VOLATILE (node->decl))) return false; return true; } @@ -703,19 +704,19 @@ comdat_can_be_unshared_p_1 (symtab_node node) but in C++ there is no way to compare their addresses for equality. */ static bool -comdat_can_be_unshared_p (symtab_node node) +comdat_can_be_unshared_p (symtab_node *node) { if (!comdat_can_be_unshared_p_1 (node)) return false; - if (node->symbol.same_comdat_group) + if (node->same_comdat_group) { - symtab_node next; + symtab_node *next; /* If more than one function is in the same COMDAT group, it must be shared even if just one function in the comdat group has address taken. */ - for (next = node->symbol.same_comdat_group; - next != node; next = next->symbol.same_comdat_group) + for (next = node->same_comdat_group; + next != node; next = next->same_comdat_group) if (!comdat_can_be_unshared_p_1 (next)) return false; } @@ -728,10 +729,10 @@ static bool cgraph_externally_visible_p (struct cgraph_node *node, bool whole_program) { - if (!node->symbol.definition) + if (!node->definition) return false; - if (!TREE_PUBLIC (node->symbol.decl) - || DECL_EXTERNAL (node->symbol.decl)) + if (!TREE_PUBLIC (node->decl) + || DECL_EXTERNAL (node->decl)) return false; /* Do not try to localize built-in functions yet. One of problems is that we @@ -739,44 +740,44 @@ cgraph_externally_visible_p (struct cgraph_node *node, using the implicit built-in declarations anymore. Similarly this enables us to remove them as unreachable before actual calls may appear during expansion or folding. */ - if (DECL_BUILT_IN (node->symbol.decl)) + if (DECL_BUILT_IN (node->decl)) return true; /* If linker counts on us, we must preserve the function. */ - if (symtab_used_from_object_file_p ((symtab_node) node)) + if (symtab_used_from_object_file_p (node)) return true; - if (DECL_PRESERVE_P (node->symbol.decl)) + if (DECL_PRESERVE_P (node->decl)) return true; if (lookup_attribute ("externally_visible", - DECL_ATTRIBUTES (node->symbol.decl))) + DECL_ATTRIBUTES (node->decl))) return true; if (TARGET_DLLIMPORT_DECL_ATTRIBUTES && lookup_attribute ("dllexport", - DECL_ATTRIBUTES (node->symbol.decl))) + DECL_ATTRIBUTES (node->decl))) return true; - if (node->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY) + if (node->resolution == LDPR_PREVAILING_DEF_IRONLY) return false; /* When doing LTO or whole program, we can bring COMDAT functoins static. This improves code quality and we know we will duplicate them at most twice (in the case that we are not using plugin and link with object file implementing same COMDAT) */ if ((in_lto_p || whole_program) - && DECL_COMDAT (node->symbol.decl) - && comdat_can_be_unshared_p ((symtab_node) node)) + && DECL_COMDAT (node->decl) + && comdat_can_be_unshared_p (node)) return false; /* When doing link time optimizations, hidden symbols become local. */ if (in_lto_p - && (DECL_VISIBILITY (node->symbol.decl) == VISIBILITY_HIDDEN - || DECL_VISIBILITY (node->symbol.decl) == VISIBILITY_INTERNAL) + && (DECL_VISIBILITY (node->decl) == VISIBILITY_HIDDEN + || DECL_VISIBILITY (node->decl) == VISIBILITY_INTERNAL) /* Be sure that node is defined in IR file, not in other object file. In that case we don't set used_from_other_object_file. */ - && node->symbol.definition) + && node->definition) ; else if (!whole_program) return true; - if (MAIN_NAME_P (DECL_NAME (node->symbol.decl))) + if (MAIN_NAME_P (DECL_NAME (node->decl))) return true; return false; @@ -787,26 +788,26 @@ cgraph_externally_visible_p (struct cgraph_node *node, bool varpool_externally_visible_p (struct varpool_node *vnode) { - if (DECL_EXTERNAL (vnode->symbol.decl)) + if (DECL_EXTERNAL (vnode->decl)) return true; - if (!TREE_PUBLIC (vnode->symbol.decl)) + if (!TREE_PUBLIC (vnode->decl)) return false; /* If linker counts on us, we must preserve the function. */ - if (symtab_used_from_object_file_p ((symtab_node) vnode)) + if (symtab_used_from_object_file_p (vnode)) return true; - if (DECL_HARD_REGISTER (vnode->symbol.decl)) + if (DECL_HARD_REGISTER (vnode->decl)) return true; - if (DECL_PRESERVE_P (vnode->symbol.decl)) + if (DECL_PRESERVE_P (vnode->decl)) return true; if (lookup_attribute ("externally_visible", - DECL_ATTRIBUTES (vnode->symbol.decl))) + DECL_ATTRIBUTES (vnode->decl))) return true; if (TARGET_DLLIMPORT_DECL_ATTRIBUTES && lookup_attribute ("dllexport", - DECL_ATTRIBUTES (vnode->symbol.decl))) + DECL_ATTRIBUTES (vnode->decl))) return true; /* See if we have linker information about symbol not being used or @@ -815,9 +816,9 @@ varpool_externally_visible_p (struct varpool_node *vnode) Even if the linker clams the symbol is unused, never bring internal symbols that are declared by user as used or externally visible. This is needed for i.e. references from asm statements. */ - if (symtab_used_from_object_file_p ((symtab_node) vnode)) + if (symtab_used_from_object_file_p (vnode)) return true; - if (vnode->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY) + if (vnode->resolution == LDPR_PREVAILING_DEF_IRONLY) return false; /* As a special case, the COMDAT virtual tables can be unshared. @@ -826,17 +827,17 @@ varpool_externally_visible_p (struct varpool_node *vnode) is faster for dynamic linking. Also this match logic hidding vtables from LTO symbol tables. */ if ((in_lto_p || flag_whole_program) - && DECL_COMDAT (vnode->symbol.decl) - && comdat_can_be_unshared_p ((symtab_node) vnode)) + && DECL_COMDAT (vnode->decl) + && comdat_can_be_unshared_p (vnode)) return false; /* When doing link time optimizations, hidden symbols become local. */ if (in_lto_p - && (DECL_VISIBILITY (vnode->symbol.decl) == VISIBILITY_HIDDEN - || DECL_VISIBILITY (vnode->symbol.decl) == VISIBILITY_INTERNAL) + && (DECL_VISIBILITY (vnode->decl) == VISIBILITY_HIDDEN + || DECL_VISIBILITY (vnode->decl) == VISIBILITY_INTERNAL) /* Be sure that node is defined in IR file, not in other object file. In that case we don't set used_from_other_object_file. */ - && vnode->symbol.definition) + && vnode->definition) ; else if (!flag_whole_program) return true; @@ -848,7 +849,7 @@ varpool_externally_visible_p (struct varpool_node *vnode) FIXME: We can do so for readonly vars with no address taken and possibly also for vtables since no direct pointer comparsion is done. It might be interesting to do so to reduce linking overhead. */ - if (DECL_COMDAT (vnode->symbol.decl) || DECL_WEAK (vnode->symbol.decl)) + if (DECL_COMDAT (vnode->decl) || DECL_WEAK (vnode->decl)) return true; return false; } @@ -858,7 +859,7 @@ varpool_externally_visible_p (struct varpool_node *vnode) */ bool -can_replace_by_local_alias (symtab_node node) +can_replace_by_local_alias (symtab_node *node) { return (symtab_node_availability (node) > AVAIL_OVERWRITABLE && !symtab_can_be_discarded (node)); @@ -886,85 +887,85 @@ function_and_variable_visibility (bool whole_program) FOR_EACH_FUNCTION (node) { - int flags = flags_from_decl_or_type (node->symbol.decl); + int flags = flags_from_decl_or_type (node->decl); /* Optimize away PURE and CONST constructors and destructors. */ if (optimize && (flags & (ECF_CONST | ECF_PURE)) && !(flags & ECF_LOOPING_CONST_OR_PURE)) { - DECL_STATIC_CONSTRUCTOR (node->symbol.decl) = 0; - DECL_STATIC_DESTRUCTOR (node->symbol.decl) = 0; + DECL_STATIC_CONSTRUCTOR (node->decl) = 0; + DECL_STATIC_DESTRUCTOR (node->decl) = 0; } /* Frontends and alias code marks nodes as needed before parsing is finished. We may end up marking as node external nodes where this flag is meaningless strip it. */ - if (DECL_EXTERNAL (node->symbol.decl) || !node->symbol.definition) + if (DECL_EXTERNAL (node->decl) || !node->definition) { - node->symbol.force_output = 0; - node->symbol.forced_by_abi = 0; + node->force_output = 0; + node->forced_by_abi = 0; } /* C++ FE on lack of COMDAT support create local COMDAT functions (that ought to be shared but can not due to object format limitations). It is necessary to keep the flag to make rest of C++ FE happy. Clear the flag here to avoid confusion in middle-end. */ - if (DECL_COMDAT (node->symbol.decl) && !TREE_PUBLIC (node->symbol.decl)) - DECL_COMDAT (node->symbol.decl) = 0; + if (DECL_COMDAT (node->decl) && !TREE_PUBLIC (node->decl)) + DECL_COMDAT (node->decl) = 0; /* For external decls stop tracking same_comdat_group. It doesn't matter what comdat group they are in when they won't be emitted in this TU. */ - if (node->symbol.same_comdat_group && DECL_EXTERNAL (node->symbol.decl)) + if (node->same_comdat_group && DECL_EXTERNAL (node->decl)) { #ifdef ENABLE_CHECKING - symtab_node n; + symtab_node *n; - for (n = node->symbol.same_comdat_group; - n != (symtab_node)node; - n = n->symbol.same_comdat_group) + for (n = node->same_comdat_group; + n != node; + n = n->same_comdat_group) /* If at least one of same comdat group functions is external, all of them have to be, otherwise it is a front-end bug. */ - gcc_assert (DECL_EXTERNAL (n->symbol.decl)); + gcc_assert (DECL_EXTERNAL (n->decl)); #endif - symtab_dissolve_same_comdat_group_list ((symtab_node) node); + symtab_dissolve_same_comdat_group_list (node); } - gcc_assert ((!DECL_WEAK (node->symbol.decl) - && !DECL_COMDAT (node->symbol.decl)) - || TREE_PUBLIC (node->symbol.decl) - || node->symbol.weakref - || DECL_EXTERNAL (node->symbol.decl)); + gcc_assert ((!DECL_WEAK (node->decl) + && !DECL_COMDAT (node->decl)) + || TREE_PUBLIC (node->decl) + || node->weakref + || DECL_EXTERNAL (node->decl)); if (cgraph_externally_visible_p (node, whole_program)) { gcc_assert (!node->global.inlined_to); - node->symbol.externally_visible = true; + node->externally_visible = true; } else { - node->symbol.externally_visible = false; - node->symbol.forced_by_abi = false; + node->externally_visible = false; + node->forced_by_abi = false; } - if (!node->symbol.externally_visible - && node->symbol.definition && !node->symbol.weakref - && !DECL_EXTERNAL (node->symbol.decl)) + if (!node->externally_visible + && node->definition && !node->weakref + && !DECL_EXTERNAL (node->decl)) { gcc_assert (whole_program || in_lto_p - || !TREE_PUBLIC (node->symbol.decl)); - node->symbol.unique_name = ((node->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY - || node->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY_EXP) - && TREE_PUBLIC (node->symbol.decl)); - symtab_make_decl_local (node->symbol.decl); - node->symbol.resolution = LDPR_PREVAILING_DEF_IRONLY; - if (node->symbol.same_comdat_group) + || !TREE_PUBLIC (node->decl)); + node->unique_name = ((node->resolution == LDPR_PREVAILING_DEF_IRONLY + || node->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP) + && TREE_PUBLIC (node->decl)); + symtab_make_decl_local (node->decl); + node->resolution = LDPR_PREVAILING_DEF_IRONLY; + if (node->same_comdat_group) /* cgraph_externally_visible_p has already checked all other nodes in the group and they will all be made local. We need to dissolve the group at once so that the predicate does not segfault though. */ - symtab_dissolve_same_comdat_group_list ((symtab_node) node); + symtab_dissolve_same_comdat_group_list (node); } if (node->thunk.thunk_p - && TREE_PUBLIC (node->symbol.decl)) + && TREE_PUBLIC (node->decl)) { struct cgraph_node *decl_node = node; @@ -972,16 +973,16 @@ function_and_variable_visibility (bool whole_program) /* Thunks have the same visibility as function they are attached to. Make sure the C++ front end set this up properly. */ - if (DECL_ONE_ONLY (decl_node->symbol.decl)) + if (DECL_ONE_ONLY (decl_node->decl)) { - gcc_checking_assert (DECL_COMDAT (node->symbol.decl) - == DECL_COMDAT (decl_node->symbol.decl)); - gcc_checking_assert (DECL_COMDAT_GROUP (node->symbol.decl) - == DECL_COMDAT_GROUP (decl_node->symbol.decl)); - gcc_checking_assert (node->symbol.same_comdat_group); + gcc_checking_assert (DECL_COMDAT (node->decl) + == DECL_COMDAT (decl_node->decl)); + gcc_checking_assert (DECL_COMDAT_GROUP (node->decl) + == DECL_COMDAT_GROUP (decl_node->decl)); + gcc_checking_assert (node->same_comdat_group); } - if (DECL_EXTERNAL (decl_node->symbol.decl)) - DECL_EXTERNAL (node->symbol.decl) = 1; + if (DECL_EXTERNAL (decl_node->decl)) + DECL_EXTERNAL (node->decl) = 1; } } FOR_EACH_DEFINED_FUNCTION (node) @@ -994,9 +995,9 @@ function_and_variable_visibility (bool whole_program) cheaper and enable more optimization. TODO: We can also update virtual tables. */ - if (node->callers && can_replace_by_local_alias ((symtab_node)node)) + if (node->callers && can_replace_by_local_alias (node)) { - struct cgraph_node *alias = cgraph (symtab_nonoverwritable_alias ((symtab_node) node)); + struct cgraph_node *alias = cgraph (symtab_nonoverwritable_alias (node)); if (alias && alias != node) { @@ -1005,9 +1006,9 @@ function_and_variable_visibility (bool whole_program) struct cgraph_edge *e = node->callers; cgraph_redirect_edge_callee (e, alias); - if (gimple_has_body_p (e->caller->symbol.decl)) + if (gimple_has_body_p (e->caller->decl)) { - push_cfun (DECL_STRUCT_FUNCTION (e->caller->symbol.decl)); + push_cfun (DECL_STRUCT_FUNCTION (e->caller->decl)); cgraph_redirect_edge_call_stmt_to_callee (e); pop_cfun (); } @@ -1018,10 +1019,10 @@ function_and_variable_visibility (bool whole_program) FOR_EACH_VARIABLE (vnode) { /* weak flag makes no sense on local variables. */ - gcc_assert (!DECL_WEAK (vnode->symbol.decl) - || vnode->symbol.weakref - || TREE_PUBLIC (vnode->symbol.decl) - || DECL_EXTERNAL (vnode->symbol.decl)); + gcc_assert (!DECL_WEAK (vnode->decl) + || vnode->weakref + || TREE_PUBLIC (vnode->decl) + || DECL_EXTERNAL (vnode->decl)); /* In several cases declarations can not be common: - when declaration has initializer @@ -1035,39 +1036,39 @@ function_and_variable_visibility (bool whole_program) static int a __attribute__ ((common)) Canonicalize things here and clear the redundant flag. */ - if (DECL_COMMON (vnode->symbol.decl) - && (!(TREE_PUBLIC (vnode->symbol.decl) - || DECL_EXTERNAL (vnode->symbol.decl)) - || (DECL_INITIAL (vnode->symbol.decl) - && DECL_INITIAL (vnode->symbol.decl) != error_mark_node) - || DECL_WEAK (vnode->symbol.decl) - || DECL_SECTION_NAME (vnode->symbol.decl) != NULL + if (DECL_COMMON (vnode->decl) + && (!(TREE_PUBLIC (vnode->decl) + || DECL_EXTERNAL (vnode->decl)) + || (DECL_INITIAL (vnode->decl) + && DECL_INITIAL (vnode->decl) != error_mark_node) + || DECL_WEAK (vnode->decl) + || DECL_SECTION_NAME (vnode->decl) != NULL || ! (ADDR_SPACE_GENERIC_P - (TYPE_ADDR_SPACE (TREE_TYPE (vnode->symbol.decl)))))) - DECL_COMMON (vnode->symbol.decl) = 0; + (TYPE_ADDR_SPACE (TREE_TYPE (vnode->decl)))))) + DECL_COMMON (vnode->decl) = 0; } FOR_EACH_DEFINED_VARIABLE (vnode) { - if (!vnode->symbol.definition) + if (!vnode->definition) continue; if (varpool_externally_visible_p (vnode)) - vnode->symbol.externally_visible = true; + vnode->externally_visible = true; else { - vnode->symbol.externally_visible = false; - vnode->symbol.forced_by_abi = false; + vnode->externally_visible = false; + vnode->forced_by_abi = false; } - if (!vnode->symbol.externally_visible - && !vnode->symbol.weakref) + if (!vnode->externally_visible + && !vnode->weakref) { - gcc_assert (in_lto_p || whole_program || !TREE_PUBLIC (vnode->symbol.decl)); - vnode->symbol.unique_name = ((vnode->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY - || vnode->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY_EXP) - && TREE_PUBLIC (vnode->symbol.decl)); - symtab_make_decl_local (vnode->symbol.decl); - if (vnode->symbol.same_comdat_group) - symtab_dissolve_same_comdat_group_list ((symtab_node) vnode); - vnode->symbol.resolution = LDPR_PREVAILING_DEF_IRONLY; + gcc_assert (in_lto_p || whole_program || !TREE_PUBLIC (vnode->decl)); + vnode->unique_name = ((vnode->resolution == LDPR_PREVAILING_DEF_IRONLY + || vnode->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP) + && TREE_PUBLIC (vnode->decl)); + symtab_make_decl_local (vnode->decl); + if (vnode->same_comdat_group) + symtab_dissolve_same_comdat_group_list (vnode); + vnode->resolution = LDPR_PREVAILING_DEF_IRONLY; } } @@ -1080,12 +1081,12 @@ function_and_variable_visibility (bool whole_program) fprintf (dump_file, "\n\n"); fprintf (dump_file, "\nMarking externally visible functions:"); FOR_EACH_DEFINED_FUNCTION (node) - if (node->symbol.externally_visible) + if (node->externally_visible) fprintf (dump_file, " %s", cgraph_node_name (node)); fprintf (dump_file, "\n\n"); fprintf (dump_file, "\nMarking externally visible variables:"); FOR_EACH_DEFINED_VARIABLE (vnode) - if (vnode->symbol.externally_visible) + if (vnode->externally_visible) fprintf (dump_file, " %s", varpool_node_name (vnode)); fprintf (dump_file, "\n\n"); } @@ -1259,9 +1260,11 @@ make_pass_ipa_whole_program_visibility (gcc::context *ctxt) } /* Generate and emit a static constructor or destructor. WHICH must - be one of 'I' (for a constructor) or 'D' (for a destructor). BODY - is a STATEMENT_LIST containing GENERIC statements. PRIORITY is the - initialization priority for this constructor or destructor. + be one of 'I' (for a constructor), 'D' (for a destructor), 'P' + (for chp static vars constructor) or 'B' (for chkp static bounds + constructor). BODY is a STATEMENT_LIST containing GENERIC + statements. PRIORITY is the initialization priority for this + constructor or destructor. FINAL specify whether the externally visible name for collect2 should be produced. */ @@ -1320,6 +1323,20 @@ cgraph_build_static_cdtor_1 (char which, tree body, int priority, bool final) DECL_STATIC_CONSTRUCTOR (decl) = 1; decl_init_priority_insert (decl, priority); break; + case 'P': + DECL_STATIC_CONSTRUCTOR (decl) = 1; + DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("chkp ctor"), + NULL, + NULL_TREE); + decl_init_priority_insert (decl, priority); + break; + case 'B': + DECL_STATIC_CONSTRUCTOR (decl) = 1; + DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("bnd_legacy"), + NULL, + NULL_TREE); + decl_init_priority_insert (decl, priority); + break; case 'D': DECL_STATIC_DESTRUCTOR (decl) = 1; decl_fini_priority_insert (decl, priority); @@ -1337,9 +1354,11 @@ cgraph_build_static_cdtor_1 (char which, tree body, int priority, bool final) } /* Generate and emit a static constructor or destructor. WHICH must - be one of 'I' (for a constructor) or 'D' (for a destructor). BODY - is a STATEMENT_LIST containing GENERIC statements. PRIORITY is the - initialization priority for this constructor or destructor. */ + be one of 'I' (for a constructor), 'D' (for a destructor), 'P' + (for chkp static vars constructor) or 'B' (for chkp static bounds + constructor). BODY is a STATEMENT_LIST containing GENERIC + statements. PRIORITY is the initialization priority for this + constructor or destructor. */ void cgraph_build_static_cdtor (char which, tree body, int priority) @@ -1362,12 +1381,12 @@ static vec<tree> static_dtors; static void record_cdtor_fn (struct cgraph_node *node) { - if (DECL_STATIC_CONSTRUCTOR (node->symbol.decl)) - static_ctors.safe_push (node->symbol.decl); - if (DECL_STATIC_DESTRUCTOR (node->symbol.decl)) - static_dtors.safe_push (node->symbol.decl); - node = cgraph_get_node (node->symbol.decl); - DECL_DISREGARD_INLINE_LIMITS (node->symbol.decl) = 1; + if (DECL_STATIC_CONSTRUCTOR (node->decl)) + static_ctors.safe_push (node->decl); + if (DECL_STATIC_DESTRUCTOR (node->decl)) + static_dtors.safe_push (node->decl); + node = cgraph_get_node (node->decl); + DECL_DISREGARD_INLINE_LIMITS (node->decl) = 1; } /* Define global constructors/destructor functions for the CDTORS, of @@ -1521,8 +1540,8 @@ ipa_cdtor_merge (void) { struct cgraph_node *node; FOR_EACH_DEFINED_FUNCTION (node) - if (DECL_STATIC_CONSTRUCTOR (node->symbol.decl) - || DECL_STATIC_DESTRUCTOR (node->symbol.decl)) + if (DECL_STATIC_CONSTRUCTOR (node->decl) + || DECL_STATIC_DESTRUCTOR (node->decl)) record_cdtor_fn (node); build_cdtor_fns (); static_ctors.release (); diff --git a/gcc/ira-build.c b/gcc/ira-build.c index 32aec6f1da4..ed513767f3c 100644 --- a/gcc/ira-build.c +++ b/gcc/ira-build.c @@ -79,6 +79,13 @@ int ira_objects_num; /* Map a conflict id to its conflict record. */ ira_object_t *ira_object_id_map; +/* Array of references to all allocno preferences. The order number + of the preference corresponds to the index in the array. */ +ira_pref_t *ira_prefs; + +/* Size of the previous array. */ +int ira_prefs_num; + /* Array of references to all copies. The order number of the copy corresponds to the index in the array. Removed copies have NULL element value. */ @@ -515,6 +522,7 @@ ira_create_allocno (int regno, bool cap_p, ALLOCNO_BAD_SPILL_P (a) = false; ALLOCNO_ASSIGNED_P (a) = false; ALLOCNO_MODE (a) = (regno < 0 ? VOIDmode : PSEUDO_REGNO_MODE (regno)); + ALLOCNO_PREFS (a) = NULL; ALLOCNO_COPIES (a) = NULL; ALLOCNO_HARD_REG_COSTS (a) = NULL; ALLOCNO_CONFLICT_HARD_REG_COSTS (a) = NULL; @@ -1163,6 +1171,195 @@ finish_allocnos (void) +/* Pools for allocno preferences. */ +static alloc_pool pref_pool; + +/* Vec containing references to all created preferences. It is a + container of array ira_prefs. */ +static vec<ira_pref_t> pref_vec; + +/* The function initializes data concerning allocno prefs. */ +static void +initiate_prefs (void) +{ + pref_pool + = create_alloc_pool ("prefs", sizeof (struct ira_allocno_pref), 100); + pref_vec.create (get_max_uid ()); + ira_prefs = NULL; + ira_prefs_num = 0; +} + +/* Return pref for A and HARD_REGNO if any. */ +static ira_pref_t +find_allocno_pref (ira_allocno_t a, int hard_regno) +{ + ira_pref_t pref; + + for (pref = ALLOCNO_PREFS (a); pref != NULL; pref = pref->next_pref) + if (pref->allocno == a && pref->hard_regno == hard_regno) + return pref; + return NULL; +} + +/* Create and return pref with given attributes A, HARD_REGNO, and FREQ. */ +ira_pref_t +ira_create_pref (ira_allocno_t a, int hard_regno, int freq) +{ + ira_pref_t pref; + + pref = (ira_pref_t) pool_alloc (pref_pool); + pref->num = ira_prefs_num; + pref->allocno = a; + pref->hard_regno = hard_regno; + pref->freq = freq; + pref_vec.safe_push (pref); + ira_prefs = pref_vec.address (); + ira_prefs_num = pref_vec.length (); + return pref; +} + +/* Attach a pref PREF to the cooresponding allocno. */ +static void +add_allocno_pref_to_list (ira_pref_t pref) +{ + ira_allocno_t a = pref->allocno; + + pref->next_pref = ALLOCNO_PREFS (a); + ALLOCNO_PREFS (a) = pref; +} + +/* Create (or update frequency if the pref already exists) the pref of + allocnos A preferring HARD_REGNO with frequency FREQ. */ +void +ira_add_allocno_pref (ira_allocno_t a, int hard_regno, int freq) +{ + ira_pref_t pref; + + if (freq <= 0) + return; + if ((pref = find_allocno_pref (a, hard_regno)) != NULL) + { + pref->freq += freq; + return; + } + pref = ira_create_pref (a, hard_regno, freq); + ira_assert (a != NULL); + add_allocno_pref_to_list (pref); +} + +/* Print info about PREF into file F. */ +static void +print_pref (FILE *f, ira_pref_t pref) +{ + fprintf (f, " pref%d:a%d(r%d)<-hr%d@%d\n", pref->num, + ALLOCNO_NUM (pref->allocno), ALLOCNO_REGNO (pref->allocno), + pref->hard_regno, pref->freq); +} + +/* Print info about PREF into stderr. */ +void +ira_debug_pref (ira_pref_t pref) +{ + print_pref (stderr, pref); +} + +/* Print info about all prefs into file F. */ +static void +print_prefs (FILE *f) +{ + ira_pref_t pref; + ira_pref_iterator pi; + + FOR_EACH_PREF (pref, pi) + print_pref (f, pref); +} + +/* Print info about all prefs into stderr. */ +void +ira_debug_prefs (void) +{ + print_prefs (stderr); +} + +/* Print info about prefs involving allocno A into file F. */ +static void +print_allocno_prefs (FILE *f, ira_allocno_t a) +{ + ira_pref_t pref; + + fprintf (f, " a%d(r%d):", ALLOCNO_NUM (a), ALLOCNO_REGNO (a)); + for (pref = ALLOCNO_PREFS (a); pref != NULL; pref = pref->next_pref) + fprintf (f, " pref%d:hr%d@%d", pref->num, pref->hard_regno, pref->freq); + fprintf (f, "\n"); +} + +/* Print info about prefs involving allocno A into stderr. */ +void +ira_debug_allocno_prefs (ira_allocno_t a) +{ + print_allocno_prefs (stderr, a); +} + +/* The function frees memory allocated for PREF. */ +static void +finish_pref (ira_pref_t pref) +{ + ira_prefs[pref->num] = NULL; + pool_free (pref_pool, pref); +} + +/* Remove PREF from the list of allocno prefs and free memory for + it. */ +void +ira_remove_pref (ira_pref_t pref) +{ + ira_pref_t cpref, prev; + + if (internal_flag_ira_verbose > 1 && ira_dump_file != NULL) + fprintf (ira_dump_file, " Removing pref%d:hr%d@%d\n", + pref->num, pref->hard_regno, pref->freq); + for (prev = NULL, cpref = ALLOCNO_PREFS (pref->allocno); + cpref != NULL; + prev = cpref, cpref = cpref->next_pref) + if (cpref == pref) + break; + ira_assert (cpref != NULL); + if (prev == NULL) + ALLOCNO_PREFS (pref->allocno) = pref->next_pref; + else + prev->next_pref = pref->next_pref; + finish_pref (pref); +} + +/* Remove all prefs of allocno A. */ +void +ira_remove_allocno_prefs (ira_allocno_t a) +{ + ira_pref_t pref, next_pref; + + for (pref = ALLOCNO_PREFS (a); pref != NULL; pref = next_pref) + { + next_pref = pref->next_pref; + finish_pref (pref); + } + ALLOCNO_PREFS (a) = NULL; +} + +/* Free memory allocated for all prefs. */ +static void +finish_prefs (void) +{ + ira_pref_t pref; + ira_pref_iterator pi; + + FOR_EACH_PREF (pref, pi) + finish_pref (pref); + pref_vec.release (); + free_alloc_pool (pref_pool); +} + + + /* Pools for copies. */ static alloc_pool copy_pool; @@ -1235,8 +1432,8 @@ ira_create_copy (ira_allocno_t first, ira_allocno_t second, int freq, } /* Attach a copy CP to allocnos involved into the copy. */ -void -ira_add_allocno_copy_to_list (ira_copy_t cp) +static void +add_allocno_copy_to_list (ira_copy_t cp) { ira_allocno_t first = cp->first, second = cp->second; @@ -1264,8 +1461,8 @@ ira_add_allocno_copy_to_list (ira_copy_t cp) /* Make a copy CP a canonical copy where number of the first allocno is less than the second one. */ -void -ira_swap_allocno_copy_ends_if_necessary (ira_copy_t cp) +static void +swap_allocno_copy_ends_if_necessary (ira_copy_t cp) { ira_allocno_t temp; ira_copy_t temp_cp; @@ -1305,8 +1502,8 @@ ira_add_allocno_copy (ira_allocno_t first, ira_allocno_t second, int freq, cp = ira_create_copy (first, second, freq, constraint_p, insn, loop_tree_node); ira_assert (first != NULL && second != NULL); - ira_add_allocno_copy_to_list (cp); - ira_swap_allocno_copy_ends_if_necessary (cp); + add_allocno_copy_to_list (cp); + swap_allocno_copy_ends_if_necessary (cp); return cp; } @@ -2305,6 +2502,7 @@ remove_unnecessary_allocnos (void) map to avoid info propagation of subsequent allocno into this already removed allocno. */ a_node->regno_allocno_map[regno] = NULL; + ira_remove_allocno_prefs (a); finish_allocno (a); } } @@ -2388,7 +2586,10 @@ remove_low_level_allocnos (void) #endif } else - finish_allocno (a); + { + ira_remove_allocno_prefs (a); + finish_allocno (a); + } } if (merged_p) ira_rebuild_start_finish_chains (); @@ -3105,6 +3306,7 @@ ira_flattening (int max_regno_before_emit, int ira_max_point_before_emit) if (internal_flag_ira_verbose > 4 && ira_dump_file != NULL) fprintf (ira_dump_file, " Remove a%dr%d\n", ALLOCNO_NUM (a), REGNO (allocno_emit_reg (a))); + ira_remove_allocno_prefs (a); finish_allocno (a); continue; } @@ -3131,8 +3333,8 @@ ira_flattening (int max_regno_before_emit, int ira_max_point_before_emit) ira_assert (ALLOCNO_LOOP_TREE_NODE (cp->first) == ira_loop_tree_root && ALLOCNO_LOOP_TREE_NODE (cp->second) == ira_loop_tree_root); - ira_add_allocno_copy_to_list (cp); - ira_swap_allocno_copy_ends_if_necessary (cp); + add_allocno_copy_to_list (cp); + swap_allocno_copy_ends_if_necessary (cp); } rebuild_regno_allocno_maps (); if (ira_max_point != ira_max_point_before_emit) @@ -3220,6 +3422,7 @@ ira_build (void) df_analyze (); initiate_cost_vectors (); initiate_allocnos (); + initiate_prefs (); initiate_copies (); create_loop_tree_nodes (); form_loop_tree (); @@ -3265,6 +3468,8 @@ ira_build (void) } if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL) print_copies (ira_dump_file); + if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL) + print_prefs (ira_dump_file); if (internal_flag_ira_verbose > 0 && ira_dump_file != NULL) { int n, nr, nr_big; @@ -3304,6 +3509,7 @@ void ira_destroy (void) { finish_loop_tree_nodes (); + finish_prefs (); finish_copies (); finish_allocnos (); finish_cost_vectors (); diff --git a/gcc/ira-color.c b/gcc/ira-color.c index 0ee31573e2e..295cd5327d7 100644 --- a/gcc/ira-color.c +++ b/gcc/ira-color.c @@ -88,6 +88,17 @@ struct allocno_hard_regs_node allocno_hard_regs_node_t parent, first, prev, next; }; +/* Info about changing hard reg costs of an allocno. */ +struct update_cost_record +{ + /* Hard regno for which we changed the cost. */ + int hard_regno; + /* Divisor used when we changed the cost of HARD_REGNO. */ + int divisor; + /* Next record for given allocno. */ + struct update_cost_record *next; +}; + /* To decrease footprint of ira_allocno structure we store all data needed only for coloring in the following structure. */ struct allocno_color_data @@ -126,6 +137,11 @@ struct allocno_color_data int hard_regs_subnodes_start; /* The length of the previous array. */ int hard_regs_subnodes_num; + /* Records about updating allocno hard reg costs from copies. If + the allocno did not get expected hard register, these records are + used to restore original hard reg costs of allocnos connected to + this allocno by copies. */ + struct update_cost_record *update_cost_records; }; /* See above. */ @@ -1113,6 +1129,53 @@ setup_profitable_hard_regs (void) /* This page contains functions used to choose hard registers for allocnos. */ +/* Pool for update cost records. */ +static alloc_pool update_cost_record_pool; + +/* Initiate update cost records. */ +static void +init_update_cost_records (void) +{ + update_cost_record_pool + = create_alloc_pool ("update cost records", + sizeof (struct update_cost_record), 100); +} + +/* Return new update cost record with given params. */ +static struct update_cost_record * +get_update_cost_record (int hard_regno, int divisor, + struct update_cost_record *next) +{ + struct update_cost_record *record; + + record = (struct update_cost_record *) pool_alloc (update_cost_record_pool); + record->hard_regno = hard_regno; + record->divisor = divisor; + record->next = next; + return record; +} + +/* Free memory for all records in LIST. */ +static void +free_update_cost_record_list (struct update_cost_record *list) +{ + struct update_cost_record *next; + + while (list != NULL) + { + next = list->next; + pool_free (update_cost_record_pool, list); + list = next; + } +} + +/* Free memory allocated for all update cost records. */ +static void +finish_update_cost_records (void) +{ + free_alloc_pool (update_cost_record_pool); +} + /* Array whose element value is TRUE if the corresponding hard register was already allocated for an allocno. */ static bool allocated_hardreg_p[FIRST_PSEUDO_REGISTER]; @@ -1129,6 +1192,11 @@ struct update_cost_queue_elem connecting this allocno to the one being allocated. */ int divisor; + /* Allocno from which we are chaning costs of connected allocnos. + It is used not go back in graph of allocnos connected by + copies. */ + ira_allocno_t from; + /* The next allocno in the queue, or null if this is the last element. */ ira_allocno_t next; }; @@ -1145,11 +1213,11 @@ static struct update_cost_queue_elem *update_cost_queue_tail; Elements are indexed by ALLOCNO_NUM. */ static struct update_cost_queue_elem *update_cost_queue_elems; -/* The current value of update_copy_cost call count. */ +/* The current value of update_costs_from_copies call count. */ static int update_cost_check; /* Allocate and initialize data necessary for function - update_copy_costs. */ + update_costs_from_copies. */ static void initiate_cost_update (void) { @@ -1160,13 +1228,15 @@ initiate_cost_update (void) = (struct update_cost_queue_elem *) ira_allocate (size); memset (update_cost_queue_elems, 0, size); update_cost_check = 0; + init_update_cost_records (); } -/* Deallocate data used by function update_copy_costs. */ +/* Deallocate data used by function update_costs_from_copies. */ static void finish_cost_update (void) { ira_free (update_cost_queue_elems); + finish_update_cost_records (); } /* When we traverse allocnos to update hard register costs, the cost @@ -1182,10 +1252,10 @@ start_update_cost (void) update_cost_queue = NULL; } -/* Add (ALLOCNO, DIVISOR) to the end of update_cost_queue, unless +/* Add (ALLOCNO, FROM, DIVISOR) to the end of update_cost_queue, unless ALLOCNO is already in the queue, or has NO_REGS class. */ static inline void -queue_update_cost (ira_allocno_t allocno, int divisor) +queue_update_cost (ira_allocno_t allocno, ira_allocno_t from, int divisor) { struct update_cost_queue_elem *elem; @@ -1194,6 +1264,7 @@ queue_update_cost (ira_allocno_t allocno, int divisor) && ALLOCNO_CLASS (allocno) != NO_REGS) { elem->check = update_cost_check; + elem->from = from; elem->divisor = divisor; elem->next = NULL; if (update_cost_queue == NULL) @@ -1204,11 +1275,11 @@ queue_update_cost (ira_allocno_t allocno, int divisor) } } -/* Try to remove the first element from update_cost_queue. Return false - if the queue was empty, otherwise make (*ALLOCNO, *DIVISOR) describe - the removed element. */ +/* Try to remove the first element from update_cost_queue. Return + false if the queue was empty, otherwise make (*ALLOCNO, *FROM, + *DIVISOR) describe the removed element. */ static inline bool -get_next_update_cost (ira_allocno_t *allocno, int *divisor) +get_next_update_cost (ira_allocno_t *allocno, ira_allocno_t *from, int *divisor) { struct update_cost_queue_elem *elem; @@ -1217,34 +1288,50 @@ get_next_update_cost (ira_allocno_t *allocno, int *divisor) *allocno = update_cost_queue; elem = &update_cost_queue_elems[ALLOCNO_NUM (*allocno)]; + *from = elem->from; *divisor = elem->divisor; update_cost_queue = elem->next; return true; } -/* Update the cost of allocnos to increase chances to remove some - copies as the result of subsequent assignment. */ +/* Increase costs of HARD_REGNO by UPDATE_COST for ALLOCNO. Return + true if we really modified the cost. */ +static bool +update_allocno_cost (ira_allocno_t allocno, int hard_regno, int update_cost) +{ + int i; + enum reg_class aclass = ALLOCNO_CLASS (allocno); + + i = ira_class_hard_reg_index[aclass][hard_regno]; + if (i < 0) + return false; + ira_allocate_and_set_or_copy_costs + (&ALLOCNO_UPDATED_HARD_REG_COSTS (allocno), aclass, + ALLOCNO_UPDATED_CLASS_COST (allocno), + ALLOCNO_HARD_REG_COSTS (allocno)); + ira_allocate_and_set_or_copy_costs + (&ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (allocno), + aclass, 0, ALLOCNO_CONFLICT_HARD_REG_COSTS (allocno)); + ALLOCNO_UPDATED_HARD_REG_COSTS (allocno)[i] += update_cost; + ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (allocno)[i] += update_cost; + return true; +} + +/* Update (decrease if DECR_P) HARD_REGNO cost of allocnos connected + by copies to ALLOCNO to increase chances to remove some copies as + the result of subsequent assignment. Record cost updates if + RECORD_P is true. */ static void -update_copy_costs (ira_allocno_t allocno, bool decr_p) +update_costs_from_allocno (ira_allocno_t allocno, int hard_regno, + int divisor, bool decr_p, bool record_p) { - int i, cost, update_cost, hard_regno, divisor; + int cost, update_cost; enum machine_mode mode; enum reg_class rclass, aclass; - ira_allocno_t another_allocno; + ira_allocno_t another_allocno, from = NULL; ira_copy_t cp, next_cp; - hard_regno = ALLOCNO_HARD_REGNO (allocno); - ira_assert (hard_regno >= 0); - - aclass = ALLOCNO_CLASS (allocno); - if (aclass == NO_REGS) - return; - i = ira_class_hard_reg_index[aclass][hard_regno]; - ira_assert (i >= 0); rclass = REGNO_REG_CLASS (hard_regno); - - start_update_cost (); - divisor = 1; do { mode = ALLOCNO_MODE (allocno); @@ -1264,6 +1351,9 @@ update_copy_costs (ira_allocno_t allocno, bool decr_p) else gcc_unreachable (); + if (another_allocno == from) + continue; + aclass = ALLOCNO_CLASS (another_allocno); if (! TEST_HARD_REG_BIT (reg_class_contents[aclass], hard_regno) @@ -1280,24 +1370,67 @@ update_copy_costs (ira_allocno_t allocno, bool decr_p) if (update_cost == 0) continue; - ira_allocate_and_set_or_copy_costs - (&ALLOCNO_UPDATED_HARD_REG_COSTS (another_allocno), aclass, - ALLOCNO_UPDATED_CLASS_COST (another_allocno), - ALLOCNO_HARD_REG_COSTS (another_allocno)); - ira_allocate_and_set_or_copy_costs - (&ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (another_allocno), - aclass, 0, ALLOCNO_CONFLICT_HARD_REG_COSTS (another_allocno)); - i = ira_class_hard_reg_index[aclass][hard_regno]; - if (i < 0) + if (! update_allocno_cost (another_allocno, hard_regno, update_cost)) continue; - ALLOCNO_UPDATED_HARD_REG_COSTS (another_allocno)[i] += update_cost; - ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (another_allocno)[i] - += update_cost; - - queue_update_cost (another_allocno, divisor * COST_HOP_DIVISOR); + queue_update_cost (another_allocno, allocno, divisor * COST_HOP_DIVISOR); + if (record_p && ALLOCNO_COLOR_DATA (another_allocno) != NULL) + ALLOCNO_COLOR_DATA (another_allocno)->update_cost_records + = get_update_cost_record (hard_regno, divisor, + ALLOCNO_COLOR_DATA (another_allocno) + ->update_cost_records); } } - while (get_next_update_cost (&allocno, &divisor)); + while (get_next_update_cost (&allocno, &from, &divisor)); +} + +/* Decrease preferred ALLOCNO hard register costs and costs of + allocnos connected to ALLOCNO through copy. */ +static void +update_costs_from_prefs (ira_allocno_t allocno) +{ + ira_pref_t pref; + + start_update_cost (); + for (pref = ALLOCNO_PREFS (allocno); pref != NULL; pref = pref->next_pref) + update_costs_from_allocno (allocno, pref->hard_regno, + COST_HOP_DIVISOR, true, true); +} + +/* Update (decrease if DECR_P) the cost of allocnos connected to + ALLOCNO through copies to increase chances to remove some copies as + the result of subsequent assignment. ALLOCNO was just assigned to + a hard register. Record cost updates if RECORD_P is true. */ +static void +update_costs_from_copies (ira_allocno_t allocno, bool decr_p, bool record_p) +{ + int hard_regno; + + hard_regno = ALLOCNO_HARD_REGNO (allocno); + ira_assert (hard_regno >= 0 && ALLOCNO_CLASS (allocno) != NO_REGS); + start_update_cost (); + update_costs_from_allocno (allocno, hard_regno, 1, decr_p, record_p); +} + +/* Restore costs of allocnos connected to ALLOCNO by copies as it was + before updating costs of these allocnos from given allocno. This + is a wise thing to do as if given allocno did not get an expected + hard reg, using smaller cost of the hard reg for allocnos connected + by copies to given allocno becomes actually misleading. Free all + update cost records for ALLOCNO as we don't need them anymore. */ +static void +restore_costs_from_copies (ira_allocno_t allocno) +{ + struct update_cost_record *records, *curr; + + if (ALLOCNO_COLOR_DATA (allocno) == NULL) + return; + records = ALLOCNO_COLOR_DATA (allocno)->update_cost_records; + start_update_cost (); + for (curr = records; curr != NULL; curr = curr->next) + update_costs_from_allocno (allocno, curr->hard_regno, + curr->divisor, true, false); + free_update_cost_record_list (records); + ALLOCNO_COLOR_DATA (allocno)->update_cost_records = NULL; } /* This function updates COSTS (decrease if DECR_P) for hard_registers @@ -1313,10 +1446,10 @@ update_conflict_hard_regno_costs (int *costs, enum reg_class aclass, int *conflict_costs; bool cont_p; enum reg_class another_aclass; - ira_allocno_t allocno, another_allocno; + ira_allocno_t allocno, another_allocno, from; ira_copy_t cp, next_cp; - while (get_next_update_cost (&allocno, &divisor)) + while (get_next_update_cost (&allocno, &from, &divisor)) for (cp = ALLOCNO_COPIES (allocno); cp != NULL; cp = next_cp) { if (cp->first == allocno) @@ -1331,6 +1464,10 @@ update_conflict_hard_regno_costs (int *costs, enum reg_class aclass, } else gcc_unreachable (); + + if (another_allocno == from) + continue; + another_aclass = ALLOCNO_CLASS (another_allocno); if (! ira_reg_classes_intersect_p[aclass][another_aclass] || ALLOCNO_ASSIGNED_P (another_allocno) @@ -1374,7 +1511,7 @@ update_conflict_hard_regno_costs (int *costs, enum reg_class aclass, * COST_HOP_DIVISOR * COST_HOP_DIVISOR * COST_HOP_DIVISOR)) - queue_update_cost (another_allocno, divisor * COST_HOP_DIVISOR); + queue_update_cost (another_allocno, allocno, divisor * COST_HOP_DIVISOR); } } @@ -1640,7 +1777,8 @@ assign_hard_reg (ira_allocno_t a, bool retry_p) continue; full_costs[j] -= conflict_costs[k]; } - queue_update_cost (conflict_a, COST_HOP_DIVISOR); + queue_update_cost (conflict_a, NULL, COST_HOP_DIVISOR); + } } } @@ -1654,7 +1792,7 @@ assign_hard_reg (ira_allocno_t a, bool retry_p) if (! retry_p) { start_update_cost (); - queue_update_cost (a, COST_HOP_DIVISOR); + queue_update_cost (a, NULL, COST_HOP_DIVISOR); update_conflict_hard_regno_costs (full_costs, aclass, false); } min_cost = min_full_cost = INT_MAX; @@ -1711,10 +1849,12 @@ assign_hard_reg (ira_allocno_t a, bool retry_p) for (i = hard_regno_nregs[best_hard_regno][mode] - 1; i >= 0; i--) allocated_hardreg_p[best_hard_regno + i] = true; } + if (! retry_p) + restore_costs_from_copies (a); ALLOCNO_HARD_REGNO (a) = best_hard_regno; ALLOCNO_ASSIGNED_P (a) = true; if (best_hard_regno >= 0) - update_copy_costs (a, true); + update_costs_from_copies (a, true, ! retry_p); ira_assert (ALLOCNO_CLASS (a) == aclass); /* We don't need updated costs anymore: */ ira_free_allocno_updated_costs (a); @@ -2164,7 +2304,9 @@ pop_allocnos_from_stack (void) else if (ALLOCNO_ASSIGNED_P (allocno)) { if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL) - fprintf (ira_dump_file, "spill\n"); + fprintf (ira_dump_file, "spill%s\n", + ALLOCNO_COLOR_DATA (allocno)->may_be_spilled_p + ? "" : "!"); } ALLOCNO_COLOR_DATA (allocno)->in_graph_p = true; } @@ -2546,6 +2688,32 @@ color_allocnos (void) ira_allocno_t a; setup_profitable_hard_regs (); + EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi) + { + int l, nr; + HARD_REG_SET conflict_hard_regs; + allocno_color_data_t data; + ira_pref_t pref, next_pref; + + a = ira_allocnos[i]; + nr = ALLOCNO_NUM_OBJECTS (a); + CLEAR_HARD_REG_SET (conflict_hard_regs); + for (l = 0; l < nr; l++) + { + ira_object_t obj = ALLOCNO_OBJECT (a, l); + IOR_HARD_REG_SET (conflict_hard_regs, + OBJECT_CONFLICT_HARD_REGS (obj)); + } + data = ALLOCNO_COLOR_DATA (a); + for (pref = ALLOCNO_PREFS (a); pref != NULL; pref = next_pref) + { + next_pref = pref->next_pref; + if (! ira_hard_reg_in_set_p (pref->hard_regno, + ALLOCNO_MODE (a), + data->profitable_hard_regs)) + ira_remove_pref (pref); + } + } if (flag_ira_algorithm == IRA_ALGORITHM_PRIORITY) { n = 0; @@ -2605,7 +2773,10 @@ color_allocnos (void) { a = ira_allocnos[i]; if (ALLOCNO_CLASS (a) != NO_REGS && ! empty_profitable_hard_regs (a)) - ALLOCNO_COLOR_DATA (a)->in_graph_p = true; + { + ALLOCNO_COLOR_DATA (a)->in_graph_p = true; + update_costs_from_prefs (a); + } else { ALLOCNO_HARD_REGNO (a) = -1; @@ -2772,7 +2943,7 @@ color_pass (ira_loop_tree_node_t loop_tree_node) ALLOCNO_HARD_REGNO (subloop_allocno) = hard_regno; ALLOCNO_ASSIGNED_P (subloop_allocno) = true; if (hard_regno >= 0) - update_copy_costs (subloop_allocno, true); + update_costs_from_copies (subloop_allocno, true, true); /* We don't need updated costs anymore: */ ira_free_allocno_updated_costs (subloop_allocno); } @@ -2816,7 +2987,7 @@ color_pass (ira_loop_tree_node_t loop_tree_node) ALLOCNO_HARD_REGNO (subloop_allocno) = hard_regno; ALLOCNO_ASSIGNED_P (subloop_allocno) = true; if (hard_regno >= 0) - update_copy_costs (subloop_allocno, true); + update_costs_from_copies (subloop_allocno, true, true); /* We don't need updated costs anymore: */ ira_free_allocno_updated_costs (subloop_allocno); } @@ -2832,7 +3003,7 @@ color_pass (ira_loop_tree_node_t loop_tree_node) ALLOCNO_HARD_REGNO (subloop_allocno) = hard_regno; ALLOCNO_ASSIGNED_P (subloop_allocno) = true; if (hard_regno >= 0) - update_copy_costs (subloop_allocno, true); + update_costs_from_copies (subloop_allocno, true, true); /* We don't need updated costs anymore: */ ira_free_allocno_updated_costs (subloop_allocno); } @@ -3813,7 +3984,7 @@ ira_mark_allocation_change (int regno) ? ALLOCNO_CLASS_COST (a) : ALLOCNO_HARD_REG_COSTS (a) [ira_class_hard_reg_index[aclass][old_hard_regno]]); - update_copy_costs (a, false); + update_costs_from_copies (a, false, false); } ira_overall_cost -= cost; ALLOCNO_HARD_REGNO (a) = hard_regno; @@ -3828,7 +3999,7 @@ ira_mark_allocation_change (int regno) ? ALLOCNO_CLASS_COST (a) : ALLOCNO_HARD_REG_COSTS (a) [ira_class_hard_reg_index[aclass][hard_regno]]); - update_copy_costs (a, true); + update_costs_from_copies (a, true, false); } else /* Reload changed class of the allocno. */ diff --git a/gcc/ira-conflicts.c b/gcc/ira-conflicts.c index 710986b073e..ba0e4e5fad3 100644 --- a/gcc/ira-conflicts.c +++ b/gcc/ira-conflicts.c @@ -208,149 +208,6 @@ allocnos_conflict_for_copy_p (ira_allocno_t a1, ira_allocno_t a2) return OBJECTS_CONFLICT_P (obj1, obj2); } -/* Return TRUE if the operand constraint STR is commutative. */ -static bool -commutative_constraint_p (const char *str) -{ - int curr_alt, c; - bool ignore_p; - - for (ignore_p = false, curr_alt = 0;;) - { - c = *str; - if (c == '\0') - break; - str += CONSTRAINT_LEN (c, str); - if (c == '#' || !recog_data.alternative_enabled_p[curr_alt]) - ignore_p = true; - else if (c == ',') - { - curr_alt++; - ignore_p = false; - } - else if (! ignore_p) - { - /* Usually `%' is the first constraint character but the - documentation does not require this. */ - if (c == '%') - return true; - } - } - return false; -} - -/* Return the number of the operand which should be the same in any - case as operand with number OP_NUM (or negative value if there is - no such operand). If USE_COMMUT_OP_P is TRUE, the function makes - temporarily commutative operand exchange before this. The function - takes only really possible alternatives into consideration. */ -static int -get_dup_num (int op_num, bool use_commut_op_p) -{ - int curr_alt, c, original, dup; - bool ignore_p, commut_op_used_p; - const char *str; - rtx op; - - if (op_num < 0 || recog_data.n_alternatives == 0) - return -1; - op = recog_data.operand[op_num]; - commut_op_used_p = true; - if (use_commut_op_p) - { - if (commutative_constraint_p (recog_data.constraints[op_num])) - op_num++; - else if (op_num > 0 && commutative_constraint_p (recog_data.constraints - [op_num - 1])) - op_num--; - else - commut_op_used_p = false; - } - str = recog_data.constraints[op_num]; - for (ignore_p = false, original = -1, curr_alt = 0;;) - { - c = *str; - if (c == '\0') - break; - if (c == '#' || !recog_data.alternative_enabled_p[curr_alt]) - ignore_p = true; - else if (c == ',') - { - curr_alt++; - ignore_p = false; - } - else if (! ignore_p) - switch (c) - { - case 'X': - return -1; - - case 'm': - case 'o': - /* Accept a register which might be placed in memory. */ - return -1; - break; - - case 'V': - case '<': - case '>': - break; - - case 'p': - if (address_operand (op, VOIDmode)) - return -1; - break; - - case 'g': - return -1; - - case 'r': - case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': - case 'h': case 'j': case 'k': case 'l': - case 'q': case 't': case 'u': - case 'v': case 'w': case 'x': case 'y': case 'z': - case 'A': case 'B': case 'C': case 'D': - case 'Q': case 'R': case 'S': case 'T': case 'U': - case 'W': case 'Y': case 'Z': - { - enum reg_class cl; - - cl = (c == 'r' - ? GENERAL_REGS : REG_CLASS_FROM_CONSTRAINT (c, str)); - if (cl != NO_REGS) - return -1; -#ifdef EXTRA_CONSTRAINT_STR - else if (EXTRA_CONSTRAINT_STR (op, c, str)) - return -1; -#endif - break; - } - - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - if (original != -1 && original != c) - return -1; - original = c; - break; - } - str += CONSTRAINT_LEN (c, str); - } - if (original == -1) - return -1; - dup = original - '0'; - if (use_commut_op_p) - { - if (commutative_constraint_p (recog_data.constraints[dup])) - dup++; - else if (dup > 0 - && commutative_constraint_p (recog_data.constraints[dup -1])) - dup--; - else if (! commut_op_used_p) - return -1; - } - return dup; -} - /* Check that X is REG or SUBREG of REG. */ #define REG_SUBREG_P(x) \ (REG_P (x) || (GET_CODE (x) == SUBREG && REG_P (SUBREG_REG (x)))) @@ -461,6 +318,7 @@ process_regs_for_copy (rtx reg1, rtx reg2, bool constraint_p, ALLOCNO_CONFLICT_HARD_REG_COSTS (a)[index] -= cost; if (ALLOCNO_HARD_REG_COSTS (a)[index] < ALLOCNO_CLASS_COST (a)) ALLOCNO_CLASS_COST (a) = ALLOCNO_HARD_REG_COSTS (a)[index]; + ira_add_allocno_pref (a, allocno_preferenced_hard_regno, freq); a = ira_parent_or_cap_allocno (a); } while (a != NULL); @@ -498,9 +356,9 @@ static void add_insn_allocno_copies (rtx insn) { rtx set, operand, dup; - const char *str; - bool commut_p, bound_p[MAX_RECOG_OPERANDS]; - int i, j, n, freq; + bool bound_p[MAX_RECOG_OPERANDS]; + int i, n, freq; + HARD_REG_SET alts; freq = REG_FREQ_FROM_BB (BLOCK_FOR_INSN (insn)); if (freq == 0) @@ -513,7 +371,7 @@ add_insn_allocno_copies (rtx insn) ? SET_SRC (set) : SUBREG_REG (SET_SRC (set))) != NULL_RTX) { - process_regs_for_copy (SET_DEST (set), SET_SRC (set), + process_regs_for_copy (SET_SRC (set), SET_DEST (set), false, insn, freq); return; } @@ -521,7 +379,7 @@ add_insn_allocno_copies (rtx insn) there are no dead registers, there will be no such copies. */ if (! find_reg_note (insn, REG_DEAD, NULL_RTX)) return; - extract_insn (insn); + ira_setup_alts (insn, alts); for (i = 0; i < recog_data.n_operands; i++) bound_p[i] = false; for (i = 0; i < recog_data.n_operands; i++) @@ -529,21 +387,18 @@ add_insn_allocno_copies (rtx insn) operand = recog_data.operand[i]; if (! REG_SUBREG_P (operand)) continue; - str = recog_data.constraints[i]; - while (*str == ' ' || *str == '\t') - str++; - for (j = 0, commut_p = false; j < 2; j++, commut_p = true) - if ((n = get_dup_num (i, commut_p)) >= 0) - { - bound_p[n] = true; - dup = recog_data.operand[n]; - if (REG_SUBREG_P (dup) - && find_reg_note (insn, REG_DEAD, - REG_P (operand) - ? operand - : SUBREG_REG (operand)) != NULL_RTX) - process_regs_for_copy (operand, dup, true, NULL_RTX, freq); - } + if ((n = ira_get_dup_out_num (i, alts)) >= 0) + { + bound_p[n] = true; + dup = recog_data.operand[n]; + if (REG_SUBREG_P (dup) + && find_reg_note (insn, REG_DEAD, + REG_P (operand) + ? operand + : SUBREG_REG (operand)) != NULL_RTX) + process_regs_for_copy (operand, dup, true, NULL_RTX, + freq); + } } for (i = 0; i < recog_data.n_operands; i++) { diff --git a/gcc/ira-costs.c b/gcc/ira-costs.c index 5f998f7aefb..424b99c2c53 100644 --- a/gcc/ira-costs.c +++ b/gcc/ira-costs.c @@ -405,7 +405,6 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops, { int alt; int i, j, k; - rtx set; int insn_allows_mem[MAX_RECOG_OPERANDS]; for (i = 0; i < n_ops; i++) @@ -914,60 +913,6 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops, ALLOCNO_BAD_SPILL_P (a) = true; } - /* If this insn is a single set copying operand 1 to operand 0 and - one operand is an allocno with the other a hard reg or an allocno - that prefers a hard register that is in its own register class - then we may want to adjust the cost of that register class to -1. - - Avoid the adjustment if the source does not die to avoid - stressing of register allocator by preferrencing two colliding - registers into single class. - - Also avoid the adjustment if a copy between hard registers of the - class is expensive (ten times the cost of a default copy is - considered arbitrarily expensive). This avoids losing when the - preferred class is very expensive as the source of a copy - instruction. */ - if ((set = single_set (insn)) != 0 - && ops[0] == SET_DEST (set) && ops[1] == SET_SRC (set) - && REG_P (ops[0]) && REG_P (ops[1]) - && find_regno_note (insn, REG_DEAD, REGNO (ops[1]))) - for (i = 0; i <= 1; i++) - if (REGNO (ops[i]) >= FIRST_PSEUDO_REGISTER - && REGNO (ops[!i]) < FIRST_PSEUDO_REGISTER) - { - unsigned int regno = REGNO (ops[i]); - unsigned int other_regno = REGNO (ops[!i]); - enum machine_mode mode = GET_MODE (ops[!i]); - cost_classes_t cost_classes_ptr = regno_cost_classes[regno]; - enum reg_class *cost_classes = cost_classes_ptr->classes; - reg_class_t rclass; - int nr; - - for (k = cost_classes_ptr->num - 1; k >= 0; k--) - { - rclass = cost_classes[k]; - if (TEST_HARD_REG_BIT (reg_class_contents[rclass], other_regno) - && (reg_class_size[(int) rclass] - == ira_reg_class_max_nregs [(int) rclass][(int) mode])) - { - if (reg_class_size[rclass] == 1) - op_costs[i]->cost[k] = -frequency; - else - { - for (nr = 0; - nr < hard_regno_nregs[other_regno][mode]; - nr++) - if (! TEST_HARD_REG_BIT (reg_class_contents[rclass], - other_regno + nr)) - break; - - if (nr == hard_regno_nregs[other_regno][mode]) - op_costs[i]->cost[k] = -frequency; - } - } - } - } } @@ -1204,6 +1149,8 @@ record_operand_costs (rtx insn, enum reg_class *pref) { const char *constraints[MAX_RECOG_OPERANDS]; enum machine_mode modes[MAX_RECOG_OPERANDS]; + rtx ops[MAX_RECOG_OPERANDS]; + rtx set; int i; for (i = 0; i < recog_data.n_operands; i++) @@ -1221,6 +1168,7 @@ record_operand_costs (rtx insn, enum reg_class *pref) { memcpy (op_costs[i], init_cost, struct_costs_size); + ops[i] = recog_data.operand[i]; if (GET_CODE (recog_data.operand[i]) == SUBREG) recog_data.operand[i] = SUBREG_REG (recog_data.operand[i]); @@ -1260,6 +1208,77 @@ record_operand_costs (rtx insn, enum reg_class *pref) record_reg_classes (recog_data.n_alternatives, recog_data.n_operands, recog_data.operand, modes, constraints, insn, pref); + + /* If this insn is a single set copying operand 1 to operand 0 and + one operand is an allocno with the other a hard reg or an allocno + that prefers a hard register that is in its own register class + then we may want to adjust the cost of that register class to -1. + + Avoid the adjustment if the source does not die to avoid + stressing of register allocator by preferrencing two colliding + registers into single class. + + Also avoid the adjustment if a copy between hard registers of the + class is expensive (ten times the cost of a default copy is + considered arbitrarily expensive). This avoids losing when the + preferred class is very expensive as the source of a copy + instruction. */ + if ((set = single_set (insn)) != NULL_RTX + && ops[0] == SET_DEST (set) && ops[1] == SET_SRC (set)) + { + int regno, other_regno; + rtx dest = SET_DEST (set); + rtx src = SET_SRC (set); + + dest = SET_DEST (set); + src = SET_SRC (set); + if (GET_CODE (dest) == SUBREG + && (GET_MODE_SIZE (GET_MODE (dest)) + == GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest))))) + dest = SUBREG_REG (dest); + if (GET_CODE (src) == SUBREG + && (GET_MODE_SIZE (GET_MODE (src)) + == GET_MODE_SIZE (GET_MODE (SUBREG_REG (src))))) + src = SUBREG_REG (src); + if (REG_P (src) && REG_P (dest) + && find_regno_note (insn, REG_DEAD, REGNO (src)) + && (((regno = REGNO (src)) >= FIRST_PSEUDO_REGISTER + && (other_regno = REGNO (dest)) < FIRST_PSEUDO_REGISTER) + || ((regno = REGNO (dest)) >= FIRST_PSEUDO_REGISTER + && (other_regno = REGNO (src)) < FIRST_PSEUDO_REGISTER))) + { + enum machine_mode mode = GET_MODE (src); + cost_classes_t cost_classes_ptr = regno_cost_classes[regno]; + enum reg_class *cost_classes = cost_classes_ptr->classes; + reg_class_t rclass; + int k, nr; + + i = regno == (int) REGNO (src) ? 1 : 0; + for (k = cost_classes_ptr->num - 1; k >= 0; k--) + { + rclass = cost_classes[k]; + if (TEST_HARD_REG_BIT (reg_class_contents[rclass], other_regno) + && (reg_class_size[(int) rclass] + == ira_reg_class_max_nregs [(int) rclass][(int) mode])) + { + if (reg_class_size[rclass] == 1) + op_costs[i]->cost[k] = -frequency; + else + { + for (nr = 0; + nr < hard_regno_nregs[other_regno][mode]; + nr++) + if (! TEST_HARD_REG_BIT (reg_class_contents[rclass], + other_regno + nr)) + break; + + if (nr == hard_regno_nregs[other_regno][mode]) + op_costs[i]->cost[k] = -frequency; + } + } + } + } + } } @@ -1741,14 +1760,15 @@ find_costs_and_classes (FILE *dump_file) a != NULL; a = ALLOCNO_NEXT_REGNO_ALLOCNO (a)) { - a_num = ALLOCNO_NUM (a); - if (regno_aclass[i] == NO_REGS) + enum reg_class aclass = regno_aclass[i]; + int a_num = ALLOCNO_NUM (a); + int *total_a_costs = COSTS (total_allocno_costs, a_num)->cost; + int *a_costs = COSTS (costs, a_num)->cost; + + if (aclass == NO_REGS) best = NO_REGS; else { - int *total_a_costs = COSTS (total_allocno_costs, a_num)->cost; - int *a_costs = COSTS (costs, a_num)->cost; - /* Finding best class which is subset of the common class. */ best_cost = (1 << (HOST_BITS_PER_INT - 2)) - 1; @@ -1757,7 +1777,7 @@ find_costs_and_classes (FILE *dump_file) for (k = 0; k < cost_classes_ptr->num; k++) { rclass = cost_classes[k]; - if (! ira_class_subset_p[rclass][regno_aclass[i]]) + if (! ira_class_subset_p[rclass][aclass]) continue; /* Ignore classes that are too small or invalid for this operand. */ @@ -1792,9 +1812,25 @@ find_costs_and_classes (FILE *dump_file) ALLOCNO_LOOP_TREE_NODE (a)->loop_num); fprintf (dump_file, ") best %s, allocno %s\n", reg_class_names[best], - reg_class_names[regno_aclass[i]]); + reg_class_names[aclass]); } pref[a_num] = best; + if (pass == flag_expensive_optimizations && best != aclass + && ira_class_hard_regs_num[best] > 0 + && (ira_reg_class_max_nregs[best][ALLOCNO_MODE (a)] + >= ira_class_hard_regs_num[best])) + { + int ind = cost_classes_ptr->index[aclass]; + + ira_assert (ind >= 0); + ira_add_allocno_pref (a, ira_class_hard_regs[best][0], + (a_costs[ind] - ALLOCNO_CLASS_COST (a)) + / (ira_register_move_cost + [ALLOCNO_MODE (a)][best][aclass])); + for (k = 0; k < cost_classes_ptr->num; k++) + if (ira_class_subset_p[cost_classes[k]][best]) + a_costs[k] = a_costs[ind]; + } } } @@ -1820,11 +1856,11 @@ find_costs_and_classes (FILE *dump_file) static void process_bb_node_for_hard_reg_moves (ira_loop_tree_node_t loop_tree_node) { - int i, freq, cost, src_regno, dst_regno, hard_regno; + int i, freq, src_regno, dst_regno, hard_regno, a_regno; bool to_p; - ira_allocno_t a; - enum reg_class rclass, hard_reg_class; - enum machine_mode mode; + ira_allocno_t a, curr_a; + ira_loop_tree_node_t curr_loop_tree_node; + enum reg_class rclass; basic_block bb; rtx insn, set, src, dst; @@ -1851,15 +1887,15 @@ process_bb_node_for_hard_reg_moves (ira_loop_tree_node_t loop_tree_node) && src_regno < FIRST_PSEUDO_REGISTER) { hard_regno = src_regno; - to_p = true; a = ira_curr_regno_allocno_map[dst_regno]; + to_p = true; } else if (src_regno >= FIRST_PSEUDO_REGISTER && dst_regno < FIRST_PSEUDO_REGISTER) { hard_regno = dst_regno; - to_p = false; a = ira_curr_regno_allocno_map[src_regno]; + to_p = false; } else continue; @@ -1869,20 +1905,31 @@ process_bb_node_for_hard_reg_moves (ira_loop_tree_node_t loop_tree_node) i = ira_class_hard_reg_index[rclass][hard_regno]; if (i < 0) continue; - mode = ALLOCNO_MODE (a); - hard_reg_class = REGNO_REG_CLASS (hard_regno); - ira_init_register_move_cost_if_necessary (mode); - cost - = (to_p ? ira_register_move_cost[mode][hard_reg_class][rclass] - : ira_register_move_cost[mode][rclass][hard_reg_class]) * freq; - ira_allocate_and_set_costs (&ALLOCNO_HARD_REG_COSTS (a), rclass, - ALLOCNO_CLASS_COST (a)); - ira_allocate_and_set_costs (&ALLOCNO_CONFLICT_HARD_REG_COSTS (a), - rclass, 0); - ALLOCNO_HARD_REG_COSTS (a)[i] -= cost; - ALLOCNO_CONFLICT_HARD_REG_COSTS (a)[i] -= cost; - ALLOCNO_CLASS_COST (a) = MIN (ALLOCNO_CLASS_COST (a), - ALLOCNO_HARD_REG_COSTS (a)[i]); + a_regno = ALLOCNO_REGNO (a); + for (curr_loop_tree_node = ALLOCNO_LOOP_TREE_NODE (a); + curr_loop_tree_node != NULL; + curr_loop_tree_node = curr_loop_tree_node->parent) + if ((curr_a = curr_loop_tree_node->regno_allocno_map[a_regno]) != NULL) + ira_add_allocno_pref (curr_a, hard_regno, freq); + { + int cost; + enum reg_class hard_reg_class; + enum machine_mode mode; + + mode = ALLOCNO_MODE (a); + hard_reg_class = REGNO_REG_CLASS (hard_regno); + ira_init_register_move_cost_if_necessary (mode); + cost = (to_p ? ira_register_move_cost[mode][hard_reg_class][rclass] + : ira_register_move_cost[mode][rclass][hard_reg_class]) * freq; + ira_allocate_and_set_costs (&ALLOCNO_HARD_REG_COSTS (a), rclass, + ALLOCNO_CLASS_COST (a)); + ira_allocate_and_set_costs (&ALLOCNO_CONFLICT_HARD_REG_COSTS (a), + rclass, 0); + ALLOCNO_HARD_REG_COSTS (a)[i] -= cost; + ALLOCNO_CONFLICT_HARD_REG_COSTS (a)[i] -= cost; + ALLOCNO_CLASS_COST (a) = MIN (ALLOCNO_CLASS_COST (a), + ALLOCNO_HARD_REG_COSTS (a)[i]); + } } } diff --git a/gcc/ira-int.h b/gcc/ira-int.h index 519f656f652..b9b21ba27af 100644 --- a/gcc/ira-int.h +++ b/gcc/ira-int.h @@ -57,6 +57,7 @@ extern FILE *ira_dump_file; allocnos. */ typedef struct live_range *live_range_t; typedef struct ira_allocno *ira_allocno_t; +typedef struct ira_allocno_pref *ira_pref_t; typedef struct ira_allocno_copy *ira_copy_t; typedef struct ira_object *ira_object_t; @@ -346,6 +347,8 @@ struct ira_allocno register class living at the point than number of hard-registers of the class available for the allocation. */ int excess_pressure_points_num; + /* Allocno hard reg preferences. */ + ira_pref_t allocno_prefs; /* Copies to other non-conflicting allocnos. The copies can represent move insn or potential move insn usually because of two operand insn constraints. */ @@ -426,6 +429,7 @@ struct ira_allocno #define ALLOCNO_BAD_SPILL_P(A) ((A)->bad_spill_p) #define ALLOCNO_ASSIGNED_P(A) ((A)->assigned_p) #define ALLOCNO_MODE(A) ((A)->mode) +#define ALLOCNO_PREFS(A) ((A)->allocno_prefs) #define ALLOCNO_COPIES(A) ((A)->allocno_copies) #define ALLOCNO_HARD_REG_COSTS(A) ((A)->hard_reg_costs) #define ALLOCNO_UPDATED_HARD_REG_COSTS(A) ((A)->updated_hard_reg_costs) @@ -516,6 +520,33 @@ extern ira_object_t *ira_object_id_map; /* The size of the previous array. */ extern int ira_objects_num; +/* The following structure represents a hard register prefererence of + allocno. The preference represent move insns or potential move + insns usually because of two operand insn constraints. One move + operand is a hard register. */ +struct ira_allocno_pref +{ + /* The unique order number of the preference node starting with 0. */ + int num; + /* Preferred hard register. */ + int hard_regno; + /* Accumulated execution frequency of insns from which the + preference created. */ + int freq; + /* Given allocno. */ + ira_allocno_t allocno; + /* All prefernces with the same allocno are linked by the following + member. */ + ira_pref_t next_pref; +}; + +/* Array of references to all allocno preferences. The order number + of the preference corresponds to the index in the array. */ +extern ira_pref_t *ira_prefs; + +/* Size of the previous array. */ +extern int ira_prefs_num; + /* The following structure represents a copy of two allocnos. The copies represent move insns or potential move insns usually because of two operand insn constraints. To remove register shuffle, we @@ -925,6 +956,8 @@ extern void ira_print_disposition (FILE *); extern void ira_debug_disposition (void); extern void ira_debug_allocno_classes (void); extern void ira_init_register_move_cost (enum machine_mode); +extern void ira_setup_alts (rtx insn, HARD_REG_SET &alts); +extern int ira_get_dup_out_num (int op_num, HARD_REG_SET &alts); /* ira-build.c */ @@ -932,6 +965,10 @@ extern void ira_init_register_move_cost (enum machine_mode); extern ira_loop_tree_node_t ira_curr_loop_tree_node; extern ira_allocno_t *ira_curr_regno_allocno_map; +extern void ira_debug_pref (ira_pref_t); +extern void ira_debug_prefs (void); +extern void ira_debug_allocno_prefs (ira_allocno_t); + extern void ira_debug_copy (ira_copy_t); extern void debug (ira_allocno_copy &ref); extern void debug (ira_allocno_copy *ptr); @@ -963,10 +1000,12 @@ extern bool ira_live_ranges_intersect_p (live_range_t, live_range_t); extern void ira_finish_live_range (live_range_t); extern void ira_finish_live_range_list (live_range_t); extern void ira_free_allocno_updated_costs (ira_allocno_t); +extern ira_pref_t ira_create_pref (ira_allocno_t, int, int); +extern void ira_add_allocno_pref (ira_allocno_t, int, int); +extern void ira_remove_pref (ira_pref_t); +extern void ira_remove_allocno_prefs (ira_allocno_t); extern ira_copy_t ira_create_copy (ira_allocno_t, ira_allocno_t, int, bool, rtx, ira_loop_tree_node_t); -extern void ira_add_allocno_copy_to_list (ira_copy_t); -extern void ira_swap_allocno_copy_ends_if_necessary (ira_copy_t); extern ira_copy_t ira_add_allocno_copy (ira_allocno_t, ira_allocno_t, int, bool, rtx, ira_loop_tree_node_t); @@ -1151,6 +1190,44 @@ ira_allocno_object_iter_cond (ira_allocno_object_iterator *i, ira_allocno_t a, ira_allocno_object_iter_cond (&(ITER), (A), &(O));) +/* The iterator for prefs. */ +typedef struct { + /* The number of the current element in IRA_PREFS. */ + int n; +} ira_pref_iterator; + +/* Initialize the iterator I. */ +static inline void +ira_pref_iter_init (ira_pref_iterator *i) +{ + i->n = 0; +} + +/* Return TRUE if we have more prefs to visit, in which case *PREF is + set to the pref to be visited. Otherwise, return FALSE. */ +static inline bool +ira_pref_iter_cond (ira_pref_iterator *i, ira_pref_t *pref) +{ + int n; + + for (n = i->n; n < ira_prefs_num; n++) + if (ira_prefs[n] != NULL) + { + *pref = ira_prefs[n]; + i->n = n + 1; + return true; + } + return false; +} + +/* Loop over all prefs. In each iteration, P is set to the next + pref. ITER is an instance of ira_pref_iterator used to iterate + the prefs. */ +#define FOR_EACH_PREF(P, ITER) \ + for (ira_pref_iter_init (&(ITER)); \ + ira_pref_iter_cond (&(ITER), &(P));) + + /* The iterator for copies. */ typedef struct { /* The number of the current element in IRA_COPIES. */ diff --git a/gcc/ira.c b/gcc/ira.c index 203fbff6a26..9e94704706c 100644 --- a/gcc/ira.c +++ b/gcc/ira.c @@ -361,6 +361,7 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tm.h" #include "regs.h" +#include "tree.h" #include "rtl.h" #include "tm_p.h" #include "target.h" @@ -1760,6 +1761,527 @@ setup_prohibited_mode_move_regs (void) +/* Return TRUE if the operand constraint STR is commutative. */ +static bool +commutative_constraint_p (const char *str) +{ + int curr_alt, c; + bool ignore_p; + + for (ignore_p = false, curr_alt = 0;;) + { + c = *str; + if (c == '\0') + break; + str += CONSTRAINT_LEN (c, str); + if (c == '#' || !recog_data.alternative_enabled_p[curr_alt]) + ignore_p = true; + else if (c == ',') + { + curr_alt++; + ignore_p = false; + } + else if (! ignore_p) + { + /* Usually `%' is the first constraint character but the + documentation does not require this. */ + if (c == '%') + return true; + } + } + return false; +} + +/* Setup possible alternatives in ALTS for INSN. */ +void +ira_setup_alts (rtx insn, HARD_REG_SET &alts) +{ + /* MAP nalt * nop -> start of constraints for given operand and + alternative */ + static vec<const char *> insn_constraints; + int nop, nalt; + bool curr_swapped; + const char *p; + rtx op; + int commutative = -1; + + extract_insn (insn); + CLEAR_HARD_REG_SET (alts); + insn_constraints.release (); + insn_constraints.safe_grow_cleared (recog_data.n_operands + * recog_data.n_alternatives + 1); + /* Check that the hard reg set is enough for holding all + alternatives. It is hard to imagine the situation when the + assertion is wrong. */ + ira_assert (recog_data.n_alternatives + <= (int) MAX (sizeof (HARD_REG_ELT_TYPE) * CHAR_BIT, + FIRST_PSEUDO_REGISTER)); + for (curr_swapped = false;; curr_swapped = true) + { + /* Calculate some data common for all alternatives to speed up the + function. */ + for (nop = 0; nop < recog_data.n_operands; nop++) + { + for (nalt = 0, p = recog_data.constraints[nop]; + nalt < recog_data.n_alternatives; + nalt++) + { + insn_constraints[nop * recog_data.n_alternatives + nalt] = p; + while (*p && *p != ',') + p++; + if (*p) + p++; + } + } + for (nalt = 0; nalt < recog_data.n_alternatives; nalt++) + { + if (! recog_data.alternative_enabled_p[nalt] || TEST_HARD_REG_BIT (alts, nalt)) + continue; + + for (nop = 0; nop < recog_data.n_operands; nop++) + { + int c, len; + + op = recog_data.operand[nop]; + p = insn_constraints[nop * recog_data.n_alternatives + nalt]; + if (*p == 0 || *p == ',') + continue; + + do + switch (c = *p, len = CONSTRAINT_LEN (c, p), c) + { + case '#': + case ',': + c = '\0'; + case '\0': + len = 0; + break; + + case '?': case '!': case '*': case '=': case '+': + break; + + case '%': + /* We only support one commutative marker, the + first one. We already set commutative + above. */ + if (commutative < 0) + commutative = nop; + break; + + case '&': + break; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + goto op_success; + break; + + case 'p': + case 'g': + case 'X': + case TARGET_MEM_CONSTRAINT: + goto op_success; + break; + + case '<': + if (MEM_P (op) + && (GET_CODE (XEXP (op, 0)) == PRE_DEC + || GET_CODE (XEXP (op, 0)) == POST_DEC)) + goto op_success; + break; + + case '>': + if (MEM_P (op) + && (GET_CODE (XEXP (op, 0)) == PRE_INC + || GET_CODE (XEXP (op, 0)) == POST_INC)) + goto op_success; + break; + + case 'E': + case 'F': + if (CONST_DOUBLE_AS_FLOAT_P (op) + || (GET_CODE (op) == CONST_VECTOR + && GET_MODE_CLASS (GET_MODE (op)) == MODE_VECTOR_FLOAT)) + goto op_success; + break; + + case 'G': + case 'H': + if (CONST_DOUBLE_AS_FLOAT_P (op) + && CONST_DOUBLE_OK_FOR_CONSTRAINT_P (op, c, p)) + goto op_success; + break; + + case 's': + if (CONST_SCALAR_INT_P (op)) + break; + case 'i': + if (CONSTANT_P (op)) + goto op_success; + break; + + case 'n': + if (CONST_SCALAR_INT_P (op)) + goto op_success; + break; + + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'O': + case 'P': + if (CONST_INT_P (op) + && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), c, p)) + goto op_success; + break; + + case 'V': + if (MEM_P (op) && ! offsettable_memref_p (op)) + goto op_success; + break; + + case 'o': + goto op_success; + break; + + default: + { + enum reg_class cl; + + cl = (c == 'r' ? GENERAL_REGS : REG_CLASS_FROM_CONSTRAINT (c, p)); + if (cl != NO_REGS) + goto op_success; +#ifdef EXTRA_CONSTRAINT_STR + else if (EXTRA_CONSTRAINT_STR (op, c, p)) + goto op_success; + else if (EXTRA_MEMORY_CONSTRAINT (c, p)) + goto op_success; + else if (EXTRA_ADDRESS_CONSTRAINT (c, p)) + goto op_success; +#endif + break; + } + } + while (p += len, c); + break; + op_success: + ; + } + if (nop >= recog_data.n_operands) + SET_HARD_REG_BIT (alts, nalt); + } + if (commutative < 0) + break; + if (curr_swapped) + break; + op = recog_data.operand[commutative]; + recog_data.operand[commutative] = recog_data.operand[commutative + 1]; + recog_data.operand[commutative + 1] = op; + + } +} + +/* Return the number of the output non-early clobber operand which + should be the same in any case as operand with number OP_NUM (or + negative value if there is no such operand). The function takes + only really possible alternatives into consideration. */ +int +ira_get_dup_out_num (int op_num, HARD_REG_SET &alts) +{ + int curr_alt, c, original, dup; + bool ignore_p, use_commut_op_p; + const char *str; +#ifdef EXTRA_CONSTRAINT_STR + rtx op; +#endif + + if (op_num < 0 || recog_data.n_alternatives == 0) + return -1; + use_commut_op_p = false; + str = recog_data.constraints[op_num]; + for (;;) + { +#ifdef EXTRA_CONSTRAINT_STR + op = recog_data.operand[op_num]; +#endif + + for (ignore_p = false, original = -1, curr_alt = 0;;) + { + c = *str; + if (c == '\0') + break; + if (c == '#' || !TEST_HARD_REG_BIT (alts, curr_alt)) + ignore_p = true; + else if (c == ',') + { + curr_alt++; + ignore_p = false; + } + else if (! ignore_p) + switch (c) + { + /* We should find duplications only for input operands. */ + case '=': + case '+': + goto fail; + case 'X': + case 'p': + case 'g': + goto fail; + case 'r': + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + case 'h': case 'j': case 'k': case 'l': + case 'q': case 't': case 'u': + case 'v': case 'w': case 'x': case 'y': case 'z': + case 'A': case 'B': case 'C': case 'D': + case 'Q': case 'R': case 'S': case 'T': case 'U': + case 'W': case 'Y': case 'Z': + { + enum reg_class cl; + + cl = (c == 'r' + ? GENERAL_REGS : REG_CLASS_FROM_CONSTRAINT (c, str)); + if (cl != NO_REGS) + { + if (! targetm.class_likely_spilled_p (cl)) + goto fail; + } +#ifdef EXTRA_CONSTRAINT_STR + else if (EXTRA_CONSTRAINT_STR (op, c, str)) + goto fail; +#endif + break; + } + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + if (original != -1 && original != c) + goto fail; + original = c; + break; + } + str += CONSTRAINT_LEN (c, str); + } + if (original == -1) + goto fail; + dup = -1; + for (ignore_p = false, str = recog_data.constraints[original - '0']; + *str != 0; + str++) + if (ignore_p) + { + if (*str == ',') + ignore_p = false; + } + else if (*str == '#') + ignore_p = true; + else if (! ignore_p) + { + if (*str == '=') + dup = original - '0'; + /* It is better ignore an alternative with early clobber. */ + else if (*str == '&') + goto fail; + } + if (dup >= 0) + return dup; + fail: + if (use_commut_op_p) + break; + use_commut_op_p = true; + if (commutative_constraint_p (recog_data.constraints[op_num])) + str = recog_data.constraints[op_num + 1]; + else if (op_num > 0 && commutative_constraint_p (recog_data.constraints + [op_num - 1])) + str = recog_data.constraints[op_num - 1]; + else + break; + } + return -1; +} + + + +/* Search forward to see if the source register of a copy insn dies + before either it or the destination register is modified, but don't + scan past the end of the basic block. If so, we can replace the + source with the destination and let the source die in the copy + insn. + + This will reduce the number of registers live in that range and may + enable the destination and the source coalescing, thus often saving + one register in addition to a register-register copy. */ + +static void +decrease_live_ranges_number (void) +{ + basic_block bb; + rtx insn, set, src, dest, dest_death, p, q, note; + int sregno, dregno; + + if (! flag_expensive_optimizations) + return; + + if (ira_dump_file) + fprintf (ira_dump_file, "Starting decreasing number of live ranges...\n"); + + FOR_EACH_BB (bb) + FOR_BB_INSNS (bb, insn) + { + set = single_set (insn); + if (! set) + continue; + src = SET_SRC (set); + dest = SET_DEST (set); + if (! REG_P (src) || ! REG_P (dest) + || find_reg_note (insn, REG_DEAD, src)) + continue; + sregno = REGNO (src); + dregno = REGNO (dest); + + /* We don't want to mess with hard regs if register classes + are small. */ + if (sregno == dregno + || (targetm.small_register_classes_for_mode_p (GET_MODE (src)) + && (sregno < FIRST_PSEUDO_REGISTER + || dregno < FIRST_PSEUDO_REGISTER)) + /* We don't see all updates to SP if they are in an + auto-inc memory reference, so we must disallow this + optimization on them. */ + || sregno == STACK_POINTER_REGNUM + || dregno == STACK_POINTER_REGNUM) + continue; + + dest_death = NULL_RTX; + + for (p = NEXT_INSN (insn); p; p = NEXT_INSN (p)) + { + if (! INSN_P (p)) + continue; + if (BLOCK_FOR_INSN (p) != bb) + break; + + if (reg_set_p (src, p) || reg_set_p (dest, p) + /* If SRC is an asm-declared register, it must not be + replaced in any asm. Unfortunately, the REG_EXPR + tree for the asm variable may be absent in the SRC + rtx, so we can't check the actual register + declaration easily (the asm operand will have it, + though). To avoid complicating the test for a rare + case, we just don't perform register replacement + for a hard reg mentioned in an asm. */ + || (sregno < FIRST_PSEUDO_REGISTER + && asm_noperands (PATTERN (p)) >= 0 + && reg_overlap_mentioned_p (src, PATTERN (p))) + /* Don't change hard registers used by a call. */ + || (CALL_P (p) && sregno < FIRST_PSEUDO_REGISTER + && find_reg_fusage (p, USE, src)) + /* Don't change a USE of a register. */ + || (GET_CODE (PATTERN (p)) == USE + && reg_overlap_mentioned_p (src, XEXP (PATTERN (p), 0)))) + break; + + /* See if all of SRC dies in P. This test is slightly + more conservative than it needs to be. */ + if ((note = find_regno_note (p, REG_DEAD, sregno)) + && GET_MODE (XEXP (note, 0)) == GET_MODE (src)) + { + int failed = 0; + + /* We can do the optimization. Scan forward from INSN + again, replacing regs as we go. Set FAILED if a + replacement can't be done. In that case, we can't + move the death note for SRC. This should be + rare. */ + + /* Set to stop at next insn. */ + for (q = next_real_insn (insn); + q != next_real_insn (p); + q = next_real_insn (q)) + { + if (reg_overlap_mentioned_p (src, PATTERN (q))) + { + /* If SRC is a hard register, we might miss + some overlapping registers with + validate_replace_rtx, so we would have to + undo it. We can't if DEST is present in + the insn, so fail in that combination of + cases. */ + if (sregno < FIRST_PSEUDO_REGISTER + && reg_mentioned_p (dest, PATTERN (q))) + failed = 1; + + /* Attempt to replace all uses. */ + else if (!validate_replace_rtx (src, dest, q)) + failed = 1; + + /* If this succeeded, but some part of the + register is still present, undo the + replacement. */ + else if (sregno < FIRST_PSEUDO_REGISTER + && reg_overlap_mentioned_p (src, PATTERN (q))) + { + validate_replace_rtx (dest, src, q); + failed = 1; + } + } + + /* If DEST dies here, remove the death note and + save it for later. Make sure ALL of DEST dies + here; again, this is overly conservative. */ + if (! dest_death + && (dest_death = find_regno_note (q, REG_DEAD, dregno))) + { + if (GET_MODE (XEXP (dest_death, 0)) == GET_MODE (dest)) + remove_note (q, dest_death); + else + { + failed = 1; + dest_death = 0; + } + } + } + + if (! failed) + { + /* Move death note of SRC from P to INSN. */ + remove_note (p, note); + XEXP (note, 1) = REG_NOTES (insn); + REG_NOTES (insn) = note; + } + + /* DEST is also dead if INSN has a REG_UNUSED note for + DEST. */ + if (! dest_death + && (dest_death + = find_regno_note (insn, REG_UNUSED, dregno))) + { + PUT_REG_NOTE_KIND (dest_death, REG_DEAD); + remove_note (insn, dest_death); + } + + /* Put death note of DEST on P if we saw it die. */ + if (dest_death) + { + XEXP (dest_death, 1) = REG_NOTES (p); + REG_NOTES (p) = dest_death; + } + break; + } + + /* If SRC is a hard register which is set or killed in + some other way, we can't do this optimization. */ + else if (sregno < FIRST_PSEUDO_REGISTER && dead_or_set_p (p, src)) + break; + } + } +} + + + /* Return nonzero if REGNO is a particularly bad choice for reloading X. */ static bool ira_bad_reload_regno_1 (int regno, rtx x) @@ -1873,6 +2395,9 @@ ira_setup_eliminable_regset (bool from_ira_p) || (flag_stack_check && STACK_CHECK_MOVING_SP) || crtl->accesses_prior_frames || crtl->stack_realign_needed + /* We need a frame pointer for all Cilk Plus functions that use + Cilk keywords. */ + || (flag_enable_cilkplus && cfun->is_cilk_function) || targetm.frame_pointer_required ()); if (from_ira_p && ira_use_lra_p) @@ -4465,7 +4990,7 @@ ira (FILE *f) } setup_prohibited_mode_move_regs (); - + decrease_live_ranges_number (); df_note_add_problem (); /* DF_LIVE can't be used in the register allocator, too many other @@ -4481,6 +5006,7 @@ ira (FILE *f) df->changeable_flags |= DF_VERIFY_SCHEDULED; #endif df_analyze (); + df_clear_flags (DF_NO_INSN_RESCAN); regstat_init_n_sets_and_refs (); regstat_compute_ri (); diff --git a/gcc/is-a.h b/gcc/is-a.h index b5ee8543abe..c47d10f20f4 100644 --- a/gcc/is-a.h +++ b/gcc/is-a.h @@ -31,7 +31,7 @@ bool is_a <TYPE> (pointer) Tests whether the pointer actually points to a more derived TYPE. - Suppose you have a symtab_node_def *ptr, AKA symtab_node ptr. You can test + Suppose you have a symtab_node *ptr, AKA symtab_node *ptr. You can test whether it points to a 'derived' cgraph_node as follows. if (is_a <cgraph_node> (ptr)) @@ -110,9 +110,9 @@ example, template <> template <> inline bool - is_a_helper <cgraph_node>::test (symtab_node_def *p) + is_a_helper <cgraph_node>::test (symtab_node *p) { - return p->symbol.type == SYMTAB_FUNCTION; + return p->type == SYMTAB_FUNCTION; } If a simple reinterpret_cast between the pointer types is incorrect, then you @@ -122,7 +122,7 @@ when needed may result in a crash. For example, template <> template <> inline bool - is_a_helper <cgraph_node>::cast (symtab_node_def *p) + is_a_helper <cgraph_node>::cast (symtab_node *p) { return &p->x_function; } diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog index 3c6563eaa8e..d6a75fe1981 100644 --- a/gcc/java/ChangeLog +++ b/gcc/java/ChangeLog @@ -1,3 +1,12 @@ +2013-10-29 David Malcolm <dmalcolm@redhat.com> + + Patch autogenerated by refactor_symtab.py from + https://github.com/davidmalcolm/gcc-refactoring-scripts + revision 58bb219cc090b2f4516a9297d868c245495ee622 + + * decl.c (java_mark_decl_local): Update for conversion of symtab types + to a true class hierarchy. + 2013-10-14 David Malcolm <dmalcolm@redhat.com> * lang.c (java_handle_option): Update for introduction of diff --git a/gcc/java/decl.c b/gcc/java/decl.c index c5a654d1c61..0a2cecc3fef 100644 --- a/gcc/java/decl.c +++ b/gcc/java/decl.c @@ -1904,7 +1904,7 @@ java_mark_decl_local (tree decl) if (TREE_CODE (decl) == FUNCTION_DECL) { struct cgraph_node *node = cgraph_get_node (decl); - gcc_assert (!node || !node->symbol.definition); + gcc_assert (!node || !node->definition); } #endif gcc_assert (!DECL_RTL_SET_P (decl)); diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h index b7be47200a8..67eb2faa778 100644 --- a/gcc/langhooks-def.h +++ b/gcc/langhooks-def.h @@ -118,6 +118,7 @@ extern bool lhd_omp_mappable_type (tree); #define LANG_HOOKS_BLOCK_MAY_FALLTHRU hook_bool_const_tree_true #define LANG_HOOKS_EH_USE_CXA_END_CLEANUP false #define LANG_HOOKS_DEEP_UNSHARING false +#define LANG_HOOKS_CHKP_SUPPORTED false /* Attribute hooks. */ #define LANG_HOOKS_ATTRIBUTE_TABLE NULL @@ -214,6 +215,18 @@ extern tree lhd_make_node (enum tree_code); #define LANG_HOOKS_OMP_CLAUSE_DTOR hook_tree_tree_tree_null #define LANG_HOOKS_OMP_FINISH_CLAUSE hook_void_tree +extern void lhd_install_body_with_frame_cleanup (tree, tree); +extern bool lhd_cilk_detect_spawn (tree *); +#define LANG_HOOKS_CILKPLUS_DETECT_SPAWN_AND_UNWRAP lhd_cilk_detect_spawn +#define LANG_HOOKS_CILKPLUS_FRAME_CLEANUP lhd_install_body_with_frame_cleanup +#define LANG_HOOKS_CILKPLUS_GIMPLIFY_SPAWN lhd_gimplify_expr + +#define LANG_HOOKS_CILKPLUS { \ + LANG_HOOKS_CILKPLUS_DETECT_SPAWN_AND_UNWRAP, \ + LANG_HOOKS_CILKPLUS_FRAME_CLEANUP, \ + LANG_HOOKS_CILKPLUS_GIMPLIFY_SPAWN \ +} + #define LANG_HOOKS_DECLS { \ LANG_HOOKS_GLOBAL_BINDINGS_P, \ LANG_HOOKS_PUSHDECL, \ @@ -291,6 +304,7 @@ extern void lhd_end_section (void); LANG_HOOKS_TREE_DUMP_INITIALIZER, \ LANG_HOOKS_DECLS, \ LANG_HOOKS_FOR_TYPES_INITIALIZER, \ + LANG_HOOKS_CILKPLUS, \ LANG_HOOKS_LTO, \ LANG_HOOKS_GET_INNERMOST_GENERIC_PARMS, \ LANG_HOOKS_GET_INNERMOST_GENERIC_ARGS, \ @@ -305,7 +319,8 @@ extern void lhd_end_section (void); LANG_HOOKS_EH_PROTECT_CLEANUP_ACTIONS, \ LANG_HOOKS_BLOCK_MAY_FALLTHRU, \ LANG_HOOKS_EH_USE_CXA_END_CLEANUP, \ - LANG_HOOKS_DEEP_UNSHARING \ + LANG_HOOKS_DEEP_UNSHARING, \ + LANG_HOOKS_CHKP_SUPPORTED \ } #endif /* GCC_LANG_HOOKS_DEF_H */ diff --git a/gcc/langhooks.c b/gcc/langhooks.c index 559d5c1beac..5d1457b1b22 100644 --- a/gcc/langhooks.c +++ b/gcc/langhooks.c @@ -675,3 +675,18 @@ lhd_end_section (void) saved_section = NULL; } } + +/* Empty function that is replaced with appropriate language dependent + frame cleanup function for _Cilk_spawn. */ + +void +lhd_install_body_with_frame_cleanup (tree, tree) +{ +} + +/* Empty function to handle cilk_valid_spawn. */ +bool +lhd_cilk_detect_spawn (tree *) +{ + return false; +} diff --git a/gcc/langhooks.h b/gcc/langhooks.h index a83bf7b71ed..48f18ac8269 100644 --- a/gcc/langhooks.h +++ b/gcc/langhooks.h @@ -139,6 +139,23 @@ struct lang_hooks_for_types tree (*reconstruct_complex_type) (tree, tree); }; +/* Language hooks related to Cilk Plus. */ + +struct lang_hooks_for_cilkplus +{ + /* Returns true if the expression passed in has a spawned function call. */ + bool (*cilk_detect_spawn_and_unwrap) (tree *); + + /* Function to add the clean up functions after spawn. The reason why it is + language dependent is because in C++, it must handle exceptions. */ + void (*install_body_with_frame_cleanup) (tree, tree); + + /* Function to gimplify a spawned function call. Returns enum gimplify + status, but as mentioned in a previous comment, we can't see that type + here, so just return an int. */ + int (*gimplify_cilk_spawn) (tree *, gimple_seq *, gimple_seq *); +}; + /* Language hooks related to decls and the symbol table. */ struct lang_hooks_for_decls @@ -408,6 +425,8 @@ struct lang_hooks struct lang_hooks_for_types types; + struct lang_hooks_for_cilkplus cilkplus; + struct lang_hooks_for_lto lto; /* Returns a TREE_VEC of the generic parameters of an instantiation of @@ -472,6 +491,9 @@ struct lang_hooks gimplification. */ bool deep_unsharing; + /* True if this language allows pointers checker instrumentation. */ + bool chkp_supported; + /* Whenever you add entries here, make sure you adjust langhooks-def.h and langhooks.c accordingly. */ }; diff --git a/gcc/loop-init.c b/gcc/loop-init.c index c7aee1da6b9..0318ba9e5f6 100644 --- a/gcc/loop-init.c +++ b/gcc/loop-init.c @@ -22,6 +22,7 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tm.h" #include "rtl.h" +#include "tree.h" #include "regs.h" #include "obstack.h" #include "basic-block.h" @@ -30,7 +31,8 @@ along with GCC; see the file COPYING3. If not see #include "flags.h" #include "df.h" #include "ggc.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "tree-ssa-loop-niter.h" /* Apply FLAGS to the loop state. */ diff --git a/gcc/loop-unroll.c b/gcc/loop-unroll.c index f0864111842..ac43f582d36 100644 --- a/gcc/loop-unroll.c +++ b/gcc/loop-unroll.c @@ -22,6 +22,7 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tm.h" #include "rtl.h" +#include "tree.h" #include "hard-reg-set.h" #include "obstack.h" #include "basic-block.h" diff --git a/gcc/lower-subreg.c b/gcc/lower-subreg.c index 57b4b3c2467..e67bc35648b 100644 --- a/gcc/lower-subreg.c +++ b/gcc/lower-subreg.c @@ -24,6 +24,7 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "machmode.h" #include "tm.h" +#include "tree.h" #include "rtl.h" #include "tm_p.h" #include "flags.h" @@ -966,7 +967,20 @@ resolve_simple_move (rtx set, rtx insn) rtx reg; reg = gen_reg_rtx (orig_mode); + +#ifdef AUTO_INC_DEC + { + rtx move = emit_move_insn (reg, src); + if (MEM_P (src)) + { + rtx note = find_reg_note (insn, REG_INC, NULL_RTX); + if (note) + add_reg_note (move, REG_INC, XEXP (note, 0)); + } + } +#else emit_move_insn (reg, src); +#endif src = reg; } @@ -1056,6 +1070,16 @@ resolve_simple_move (rtx set, rtx insn) mdest = simplify_gen_subreg (orig_mode, dest, GET_MODE (dest), 0); minsn = emit_move_insn (real_dest, mdest); +#ifdef AUTO_INC_DEC + if (MEM_P (real_dest) + && !(resolve_reg_p (real_dest) || resolve_subreg_p (real_dest))) + { + rtx note = find_reg_note (insn, REG_INC, NULL_RTX); + if (note) + add_reg_note (minsn, REG_INC, XEXP (note, 0)); + } +#endif + smove = single_set (minsn); gcc_assert (smove != NULL_RTX); @@ -1069,7 +1093,7 @@ resolve_simple_move (rtx set, rtx insn) emit_insn_before (insns, insn); - /* If we get here via self-recutsion, then INSN is not yet in the insns + /* If we get here via self-recursion, then INSN is not yet in the insns chain and delete_insn will fail. We only want to remove INSN from the current sequence. See PR56738. */ if (in_sequence_p ()) diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c index e741dd60a73..ee82c6f496c 100644 --- a/gcc/lra-constraints.c +++ b/gcc/lra-constraints.c @@ -1466,23 +1466,32 @@ process_alt_operands (int only_alternative) function. */ for (nop = 0; nop < n_operands; nop++) { + rtx reg; + op = no_subreg_reg_operand[nop] = *curr_id->operand_loc[nop]; /* The real hard regno of the operand after the allocation. */ hard_regno[nop] = get_hard_regno (op); - operand_reg[nop] = op; - biggest_mode[nop] = GET_MODE (operand_reg[nop]); - if (GET_CODE (operand_reg[nop]) == SUBREG) + operand_reg[nop] = reg = op; + biggest_mode[nop] = GET_MODE (op); + if (GET_CODE (op) == SUBREG) { - operand_reg[nop] = SUBREG_REG (operand_reg[nop]); + operand_reg[nop] = reg = SUBREG_REG (op); if (GET_MODE_SIZE (biggest_mode[nop]) - < GET_MODE_SIZE (GET_MODE (operand_reg[nop]))) - biggest_mode[nop] = GET_MODE (operand_reg[nop]); + < GET_MODE_SIZE (GET_MODE (reg))) + biggest_mode[nop] = GET_MODE (reg); } - if (REG_P (operand_reg[nop])) - no_subreg_reg_operand[nop] = operand_reg[nop]; - else + if (! REG_P (reg)) operand_reg[nop] = NULL_RTX; + else if (REGNO (reg) >= FIRST_PSEUDO_REGISTER + || ((int) REGNO (reg) + == lra_get_elimination_hard_regno (REGNO (reg)))) + no_subreg_reg_operand[nop] = reg; + else + operand_reg[nop] = no_subreg_reg_operand[nop] + /* Just use natural mode for elimination result. It should + be enough for extra constraints hooks. */ + = regno_reg_rtx[hard_regno[nop]]; } /* The constraints are made of several alternatives. Each operand's @@ -3975,18 +3984,6 @@ lra_constraints (bool first_p) dest_reg = SUBREG_REG (dest_reg); if ((REG_P (dest_reg) && (x = get_equiv_substitution (dest_reg)) != dest_reg - /* Check that this is actually an insn setting up - the equivalence. */ - && (in_list_p (curr_insn, - ira_reg_equiv - [REGNO (dest_reg)].init_insns) - /* Init insns may contain not all insns setting - up equivalence as we have live range - splitting. So here we use another condition - to check insn setting up the equivalence - which should be removed, e.g. in case when - the equivalence is a constant. */ - || ! MEM_P (x)) /* Remove insns which set up a pseudo whose value can not be changed. Such insns might be not in init_insns because we don't update equiv data @@ -3999,8 +3996,10 @@ lra_constraints (bool first_p) secondary memory movement. Then the pseudo is spilled and we use the equiv constant. In this case we should remove the additional insn and - this insn is not init_insns list. */ + this insn is not init_insns list. */ && (! MEM_P (x) || MEM_READONLY_P (x) + /* Check that this is actually an insn setting + up the equivalence. */ || in_list_p (curr_insn, ira_reg_equiv [REGNO (dest_reg)].init_insns))) diff --git a/gcc/lra-spills.c b/gcc/lra-spills.c index 7c0c630273d..4ab10c25b98 100644 --- a/gcc/lra-spills.c +++ b/gcc/lra-spills.c @@ -334,8 +334,8 @@ assign_spill_hard_regs (int *pseudo_regnos, int n) for (nr = 0; nr < hard_regno_nregs[hard_regno][lra_reg_info[regno].biggest_mode]; nr++) - /* Just loop. */; - df_set_regs_ever_live (hard_regno + nr, true); + /* Just loop. */ + df_set_regs_ever_live (hard_regno + nr, true); } bitmap_clear (&ok_insn_bitmap); free (reserved_hard_regs); @@ -618,6 +618,33 @@ alter_subregs (rtx *loc, bool final_p) return res; } +/* Return true if REGNO is used for return in the current + function. */ +static bool +return_regno_p (unsigned int regno) +{ + rtx outgoing = crtl->return_rtx; + + if (! outgoing) + return false; + + if (REG_P (outgoing)) + return REGNO (outgoing) == regno; + else if (GET_CODE (outgoing) == PARALLEL) + { + int i; + + for (i = 0; i < XVECLEN (outgoing, 0); i++) + { + rtx x = XEXP (XVECEXP (outgoing, 0, i), 0); + + if (REG_P (x) && REGNO (x) == regno) + return true; + } + } + return false; +} + /* Final change of pseudos got hard registers into the corresponding hard registers and removing temporary clobbers. */ void @@ -648,6 +675,24 @@ lra_final_code_change (void) continue; } + /* IRA can generate move insns involving pseudos. It is + better remove them earlier to speed up compiler a bit. + It is also better to do it here as they might not pass + final RTL check in LRA, (e.g. insn moving a control + register into itself). So remove an useless move insn + unless next insn is USE marking the return reg (we should + save this as some subsequent optimizations assume that + such original insns are saved). */ + if (NONJUMP_INSN_P (insn) && GET_CODE (pat) == SET + && REG_P (SET_SRC (pat)) && REG_P (SET_DEST (pat)) + && REGNO (SET_SRC (pat)) == REGNO (SET_DEST (pat)) + && ! return_regno_p (REGNO (SET_SRC (pat)))) + { + lra_invalidate_insn_data (insn); + delete_insn (insn); + continue; + } + lra_insn_recog_data_t id = lra_get_insn_recog_data (insn); struct lra_static_insn_data *static_id = id->insn_static_data; bool insn_change_p = false; diff --git a/gcc/lra.c b/gcc/lra.c index 532d3de3e09..1aea599a2e5 100644 --- a/gcc/lra.c +++ b/gcc/lra.c @@ -2017,10 +2017,8 @@ restore_scratches (void) static void check_rtl (bool final_p) { - int i; basic_block bb; rtx insn; - lra_insn_recog_data_t id; lra_assert (! final_p || reload_completed); FOR_EACH_BB (bb) @@ -2036,31 +2034,13 @@ check_rtl (bool final_p) lra_assert (constrain_operands (1)); continue; } + /* LRA code is based on assumption that all addresses can be + correctly decomposed. LRA can generate reloads for + decomposable addresses. The decomposition code checks the + correctness of the addresses. So we don't need to check + the addresses here. */ if (insn_invalid_p (insn, false)) fatal_insn_not_found (insn); - if (asm_noperands (PATTERN (insn)) >= 0) - continue; - id = lra_get_insn_recog_data (insn); - /* The code is based on assumption that all addresses in - regular instruction are legitimate before LRA. The code in - lra-constraints.c is based on assumption that there is no - subreg of memory as an insn operand. */ - for (i = 0; i < id->insn_static_data->n_operands; i++) - { - rtx op = *id->operand_loc[i]; - - if (MEM_P (op) - && (GET_MODE (op) != BLKmode - || GET_CODE (XEXP (op, 0)) != SCRATCH) - && ! memory_address_p (GET_MODE (op), XEXP (op, 0)) - /* Some ports don't recognize the following addresses - as legitimate. Although they are legitimate if - they satisfies the constraints and will be checked - by insn constraints which we ignore here. */ - && GET_CODE (XEXP (op, 0)) != UNSPEC - && GET_RTX_CLASS (GET_CODE (XEXP (op, 0))) != RTX_AUTOINC) - fatal_insn_not_found (insn); - } } } #endif /* #ifdef ENABLE_CHECKING */ diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c index 211eda97269..6a52da8a662 100644 --- a/gcc/lto-cgraph.c +++ b/gcc/lto-cgraph.c @@ -25,6 +25,7 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tm.h" #include "tree.h" +#include "gimple.h" #include "expr.h" #include "flags.h" #include "params.h" @@ -32,8 +33,7 @@ along with GCC; see the file COPYING3. If not see #include "hashtab.h" #include "langhooks.h" #include "basic-block.h" -#include "tree-ssa.h" -#include "cgraph.h" +#include "bitmap.h" #include "function.h" #include "ggc.h" #include "diagnostic-core.h" @@ -52,7 +52,7 @@ along with GCC; see the file COPYING3. If not see #include "ipa-utils.h" static void output_cgraph_opt_summary (void); -static void input_cgraph_opt_summary (vec<symtab_node> nodes); +static void input_cgraph_opt_summary (vec<symtab_node *> nodes); /* Number of LDPR values known to GCC. */ #define LDPR_NUM_KNOWN (LDPR_PREVAILING_DEF_IRONLY_EXP + 1) @@ -111,7 +111,7 @@ lto_symtab_encoder_delete (lto_symtab_encoder_t encoder) int lto_symtab_encoder_encode (lto_symtab_encoder_t encoder, - symtab_node node) + symtab_node *node) { int ref; void **slot; @@ -145,7 +145,7 @@ lto_symtab_encoder_encode (lto_symtab_encoder_t encoder, bool lto_symtab_encoder_delete_node (lto_symtab_encoder_t encoder, - symtab_node node) + symtab_node *node) { void **slot, **last_slot; int index; @@ -183,7 +183,7 @@ bool lto_symtab_encoder_encode_body_p (lto_symtab_encoder_t encoder, struct cgraph_node *node) { - int index = lto_symtab_encoder_lookup (encoder, (symtab_node)node); + int index = lto_symtab_encoder_lookup (encoder, node); return encoder->nodes[index].body; } @@ -193,8 +193,8 @@ static void lto_set_symtab_encoder_encode_body (lto_symtab_encoder_t encoder, struct cgraph_node *node) { - int index = lto_symtab_encoder_encode (encoder, (symtab_node)node); - gcc_checking_assert (encoder->nodes[index].node == (symtab_node)node); + int index = lto_symtab_encoder_encode (encoder, node); + gcc_checking_assert (encoder->nodes[index].node == node); encoder->nodes[index].body = true; } @@ -204,7 +204,7 @@ bool lto_symtab_encoder_encode_initializer_p (lto_symtab_encoder_t encoder, struct varpool_node *node) { - int index = lto_symtab_encoder_lookup (encoder, (symtab_node)node); + int index = lto_symtab_encoder_lookup (encoder, node); if (index == LCC_NOT_FOUND) return false; return encoder->nodes[index].initializer; @@ -216,7 +216,7 @@ static void lto_set_symtab_encoder_encode_initializer (lto_symtab_encoder_t encoder, struct varpool_node *node) { - int index = lto_symtab_encoder_lookup (encoder, (symtab_node)node); + int index = lto_symtab_encoder_lookup (encoder, node); encoder->nodes[index].initializer = true; } @@ -224,9 +224,9 @@ lto_set_symtab_encoder_encode_initializer (lto_symtab_encoder_t encoder, bool lto_symtab_encoder_in_partition_p (lto_symtab_encoder_t encoder, - symtab_node node) + symtab_node *node) { - int index = lto_symtab_encoder_lookup (encoder, (symtab_node)node); + int index = lto_symtab_encoder_lookup (encoder, node); if (index == LCC_NOT_FOUND) return false; return encoder->nodes[index].in_partition; @@ -236,9 +236,9 @@ lto_symtab_encoder_in_partition_p (lto_symtab_encoder_t encoder, void lto_set_symtab_encoder_in_partition (lto_symtab_encoder_t encoder, - symtab_node node) + symtab_node *node) { - int index = lto_symtab_encoder_encode (encoder, (symtab_node)node); + int index = lto_symtab_encoder_encode (encoder, node); encoder->nodes[index].in_partition = true; } @@ -259,13 +259,13 @@ lto_output_edge (struct lto_simple_output_block *ob, struct cgraph_edge *edge, streamer_write_enum (ob->main_stream, LTO_symtab_tags, LTO_symtab_last_tag, LTO_symtab_edge); - ref = lto_symtab_encoder_lookup (encoder, (symtab_node)edge->caller); + ref = lto_symtab_encoder_lookup (encoder, edge->caller); gcc_assert (ref != LCC_NOT_FOUND); streamer_write_hwi_stream (ob->main_stream, ref); if (!edge->indirect_unknown_callee) { - ref = lto_symtab_encoder_lookup (encoder, (symtab_node)edge->callee); + ref = lto_symtab_encoder_lookup (encoder, edge->callee); gcc_assert (ref != LCC_NOT_FOUND); streamer_write_hwi_stream (ob->main_stream, ref); } @@ -273,7 +273,7 @@ lto_output_edge (struct lto_simple_output_block *ob, struct cgraph_edge *edge, streamer_write_gcov_count_stream (ob->main_stream, edge->count); bp = bitpack_create (ob->main_stream); - uid = (!gimple_has_body_p (edge->caller->symbol.decl) + uid = (!gimple_has_body_p (edge->caller->decl) ? edge->lto_stmt_uid : gimple_uid (edge->call_stmt) + 1); bp_pack_enum (&bp, cgraph_inline_failed_enum, CIF_N_REASONS, edge->inline_failed); @@ -319,7 +319,7 @@ referenced_from_other_partition_p (struct ipa_ref_list *list, lto_symtab_encoder struct ipa_ref *ref; for (i = 0; ipa_ref_list_referring_iterate (list, i, ref); i++) { - if (ref->referring->symbol.in_other_partition + if (ref->referring->in_other_partition || !lto_symtab_encoder_in_partition_p (encoder, ref->referring)) return true; } @@ -332,13 +332,13 @@ bool reachable_from_other_partition_p (struct cgraph_node *node, lto_symtab_encoder_t encoder) { struct cgraph_edge *e; - if (!node->symbol.definition) + if (!node->definition) return false; if (node->global.inlined_to) return false; for (e = node->callers; e; e = e->next_caller) - if (e->caller->symbol.in_other_partition - || !lto_symtab_encoder_in_partition_p (encoder, (symtab_node)e->caller)) + if (e->caller->in_other_partition + || !lto_symtab_encoder_in_partition_p (encoder, e->caller)) return true; return false; } @@ -364,7 +364,7 @@ reachable_from_this_partition_p (struct cgraph_node *node, lto_symtab_encoder_t { struct cgraph_edge *e; for (e = node->callers; e; e = e->next_caller) - if (lto_symtab_encoder_in_partition_p (encoder, (symtab_node)e->caller)) + if (lto_symtab_encoder_in_partition_p (encoder, e->caller)) return true; return false; } @@ -391,16 +391,16 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node, int i; bool alias_p; - boundary_p = !lto_symtab_encoder_in_partition_p (encoder, (symtab_node)node); + boundary_p = !lto_symtab_encoder_in_partition_p (encoder, node); - if (node->symbol.analyzed && !boundary_p) + if (node->analyzed && !boundary_p) tag = LTO_symtab_analyzed_node; else tag = LTO_symtab_unavail_node; streamer_write_enum (ob->main_stream, LTO_symtab_tags, LTO_symtab_last_tag, tag); - streamer_write_hwi_stream (ob->main_stream, node->symbol.order); + streamer_write_hwi_stream (ob->main_stream, node->order); /* In WPA mode, we only output part of the call-graph. Also, we fake cgraph node attributes. There are two cases that we care. @@ -412,7 +412,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node, Cherry-picked nodes: These are nodes we pulled from other translation units into SET during IPA-inlining. We make them as local static nodes to prevent clashes with other local statics. */ - if (boundary_p && node->symbol.analyzed && !DECL_EXTERNAL (node->symbol.decl)) + if (boundary_p && node->analyzed && !DECL_EXTERNAL (node->decl)) { /* Inline clones can not be part of boundary. gcc_assert (!node->global.inlined_to); @@ -427,7 +427,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node, clone_of = node->clone_of; while (clone_of - && (ref = lto_symtab_encoder_lookup (encoder, (symtab_node)clone_of)) == LCC_NOT_FOUND) + && (ref = lto_symtab_encoder_lookup (encoder, clone_of)) == LCC_NOT_FOUND) if (clone_of->prev_sibling_clone) clone_of = clone_of->prev_sibling_clone; else @@ -450,7 +450,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node, streamer_write_hwi_stream (ob->main_stream, ref); - lto_output_fn_decl_index (ob->decl_state, ob->main_stream, node->symbol.decl); + lto_output_fn_decl_index (ob->decl_state, ob->main_stream, node->decl); streamer_write_gcov_count_stream (ob->main_stream, node->count); streamer_write_hwi_stream (ob->main_stream, node->count_materialization_scale); @@ -463,7 +463,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node, { if (node->global.inlined_to) { - ref = lto_symtab_encoder_lookup (encoder, (symtab_node)node->global.inlined_to); + ref = lto_symtab_encoder_lookup (encoder, node->global.inlined_to); gcc_assert (ref != LCC_NOT_FOUND); } else @@ -472,10 +472,10 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node, streamer_write_hwi_stream (ob->main_stream, ref); } - if (node->symbol.same_comdat_group && !boundary_p) + if (node->same_comdat_group && !boundary_p) { ref = lto_symtab_encoder_lookup (encoder, - node->symbol.same_comdat_group); + node->same_comdat_group); gcc_assert (ref != LCC_NOT_FOUND); } else @@ -484,20 +484,20 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node, bp = bitpack_create (ob->main_stream); bp_pack_value (&bp, node->local.local, 1); - bp_pack_value (&bp, node->symbol.externally_visible, 1); - bp_pack_value (&bp, node->symbol.definition, 1); + bp_pack_value (&bp, node->externally_visible, 1); + bp_pack_value (&bp, node->definition, 1); bp_pack_value (&bp, node->local.versionable, 1); bp_pack_value (&bp, node->local.can_change_signature, 1); bp_pack_value (&bp, node->local.redefined_extern_inline, 1); - bp_pack_value (&bp, node->symbol.force_output, 1); - bp_pack_value (&bp, node->symbol.forced_by_abi, 1); - bp_pack_value (&bp, node->symbol.unique_name, 1); - bp_pack_value (&bp, node->symbol.address_taken, 1); + bp_pack_value (&bp, node->force_output, 1); + bp_pack_value (&bp, node->forced_by_abi, 1); + bp_pack_value (&bp, node->unique_name, 1); + bp_pack_value (&bp, node->address_taken, 1); bp_pack_value (&bp, tag == LTO_symtab_analyzed_node - && !DECL_EXTERNAL (node->symbol.decl) - && !DECL_COMDAT (node->symbol.decl) + && !DECL_EXTERNAL (node->decl) + && !DECL_COMDAT (node->decl) && (reachable_from_other_partition_p (node, encoder) - || referenced_from_other_partition_p (&node->symbol.ref_list, + || referenced_from_other_partition_p (&node->ref_list, encoder)), 1); bp_pack_value (&bp, node->lowered, 1); bp_pack_value (&bp, in_other_partition, 1); @@ -507,16 +507,16 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node, defined in other unit, we may use the info on aliases to resolve symbol1 != symbol2 type tests that we can do only for locally defined objects otherwise. */ - alias_p = node->symbol.alias && (!boundary_p || node->symbol.weakref); + alias_p = node->alias && (!boundary_p || node->weakref); bp_pack_value (&bp, alias_p, 1); - bp_pack_value (&bp, node->symbol.weakref, 1); + bp_pack_value (&bp, node->weakref, 1); bp_pack_value (&bp, node->frequency, 2); bp_pack_value (&bp, node->only_called_at_startup, 1); bp_pack_value (&bp, node->only_called_at_exit, 1); bp_pack_value (&bp, node->tm_clone, 1); bp_pack_value (&bp, node->thunk.thunk_p && !boundary_p, 1); bp_pack_enum (&bp, ld_plugin_symbol_resolution, - LDPR_NUM_KNOWN, node->symbol.resolution); + LDPR_NUM_KNOWN, node->resolution); streamer_write_bitpack (&bp); if (node->thunk.thunk_p && !boundary_p) @@ -538,57 +538,57 @@ static void lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node *node, lto_symtab_encoder_t encoder) { - bool boundary_p = !lto_symtab_encoder_in_partition_p (encoder, (symtab_node)node); + bool boundary_p = !lto_symtab_encoder_in_partition_p (encoder, node); struct bitpack_d bp; int ref; bool alias_p; streamer_write_enum (ob->main_stream, LTO_symtab_tags, LTO_symtab_last_tag, LTO_symtab_variable); - streamer_write_hwi_stream (ob->main_stream, node->symbol.order); - lto_output_var_decl_index (ob->decl_state, ob->main_stream, node->symbol.decl); + streamer_write_hwi_stream (ob->main_stream, node->order); + lto_output_var_decl_index (ob->decl_state, ob->main_stream, node->decl); bp = bitpack_create (ob->main_stream); - bp_pack_value (&bp, node->symbol.externally_visible, 1); - bp_pack_value (&bp, node->symbol.force_output, 1); - bp_pack_value (&bp, node->symbol.forced_by_abi, 1); - bp_pack_value (&bp, node->symbol.unique_name, 1); - bp_pack_value (&bp, node->symbol.definition, 1); - alias_p = node->symbol.alias && (!boundary_p || node->symbol.weakref); + bp_pack_value (&bp, node->externally_visible, 1); + bp_pack_value (&bp, node->force_output, 1); + bp_pack_value (&bp, node->forced_by_abi, 1); + bp_pack_value (&bp, node->unique_name, 1); + bp_pack_value (&bp, node->definition, 1); + alias_p = node->alias && (!boundary_p || node->weakref); bp_pack_value (&bp, alias_p, 1); - bp_pack_value (&bp, node->symbol.weakref, 1); - bp_pack_value (&bp, node->symbol.analyzed && !boundary_p, 1); - gcc_assert (node->symbol.definition || !node->symbol.analyzed); + bp_pack_value (&bp, node->weakref, 1); + bp_pack_value (&bp, node->analyzed && !boundary_p, 1); + gcc_assert (node->definition || !node->analyzed); /* Constant pool initializers can be de-unified into individual ltrans units. FIXME: Alternatively at -Os we may want to avoid generating for them the local labels and share them across LTRANS partitions. */ - if (DECL_IN_CONSTANT_POOL (node->symbol.decl) - && !DECL_EXTERNAL (node->symbol.decl) - && !DECL_COMDAT (node->symbol.decl)) + if (DECL_IN_CONSTANT_POOL (node->decl) + && !DECL_EXTERNAL (node->decl) + && !DECL_COMDAT (node->decl)) { bp_pack_value (&bp, 0, 1); /* used_from_other_parition. */ bp_pack_value (&bp, 0, 1); /* in_other_partition. */ } else { - bp_pack_value (&bp, node->symbol.definition - && referenced_from_other_partition_p (&node->symbol.ref_list, + bp_pack_value (&bp, node->definition + && referenced_from_other_partition_p (&node->ref_list, encoder), 1); - bp_pack_value (&bp, node->symbol.analyzed - && boundary_p && !DECL_EXTERNAL (node->symbol.decl), 1); + bp_pack_value (&bp, node->analyzed + && boundary_p && !DECL_EXTERNAL (node->decl), 1); /* in_other_partition. */ } streamer_write_bitpack (&bp); - if (node->symbol.same_comdat_group && !boundary_p) + if (node->same_comdat_group && !boundary_p) { ref = lto_symtab_encoder_lookup (encoder, - node->symbol.same_comdat_group); + node->same_comdat_group); gcc_assert (ref != LCC_NOT_FOUND); } else ref = LCC_NOT_FOUND; streamer_write_hwi_stream (ob->main_stream, ref); streamer_write_enum (ob->main_stream, ld_plugin_symbol_resolution, - LDPR_NUM_KNOWN, node->symbol.resolution); + LDPR_NUM_KNOWN, node->resolution); } /* Output the varpool NODE to OB. @@ -703,15 +703,15 @@ output_refs (lto_symtab_encoder_t encoder) for (lsei = lsei_start_in_partition (encoder); !lsei_end_p (lsei); lsei_next_in_partition (&lsei)) { - symtab_node node = lsei_node (lsei); + symtab_node *node = lsei_node (lsei); - count = ipa_ref_list_nreferences (&node->symbol.ref_list); + count = ipa_ref_list_nreferences (&node->ref_list); if (count) { streamer_write_gcov_count_stream (ob->main_stream, count); streamer_write_uhwi_stream (ob->main_stream, lto_symtab_encoder_lookup (encoder, node)); - for (i = 0; ipa_ref_list_reference_iterate (&node->symbol.ref_list, + for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list, i, ref); i++) lto_output_ref (ob, ref, encoder); } @@ -733,7 +733,7 @@ add_node_to (lto_symtab_encoder_t encoder, struct cgraph_node *node, add_node_to (encoder, node->clone_of, include_body); else if (include_body) lto_set_symtab_encoder_encode_body (encoder, node); - lto_symtab_encoder_encode (encoder, (symtab_node)node); + lto_symtab_encoder_encode (encoder, node); } /* Add all references in LIST to encoders. */ @@ -779,13 +779,13 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder) { node = lsei_cgraph_node (lsei); add_node_to (encoder, node, true); - lto_set_symtab_encoder_in_partition (encoder, (symtab_node)node); - add_references (encoder, &node->symbol.ref_list); + lto_set_symtab_encoder_in_partition (encoder, node); + add_references (encoder, &node->ref_list); /* For proper debug info, we need to ship the origins, too. */ - if (DECL_ABSTRACT_ORIGIN (node->symbol.decl)) + if (DECL_ABSTRACT_ORIGIN (node->decl)) { struct cgraph_node *origin_node - = cgraph_get_node (DECL_ABSTRACT_ORIGIN (node->symbol.decl)); + = cgraph_get_node (DECL_ABSTRACT_ORIGIN (node->decl)); add_node_to (encoder, origin_node, true); } } @@ -794,15 +794,15 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder) { struct varpool_node *vnode = lsei_varpool_node (lsei); - lto_set_symtab_encoder_in_partition (encoder, (symtab_node)vnode); + lto_set_symtab_encoder_in_partition (encoder, vnode); lto_set_symtab_encoder_encode_initializer (encoder, vnode); - add_references (encoder, &vnode->symbol.ref_list); + add_references (encoder, &vnode->ref_list); /* For proper debug info, we need to ship the origins, too. */ - if (DECL_ABSTRACT_ORIGIN (vnode->symbol.decl)) + if (DECL_ABSTRACT_ORIGIN (vnode->decl)) { struct varpool_node *origin_node - = varpool_get_node (DECL_ABSTRACT_ORIGIN (node->symbol.decl)); - lto_set_symtab_encoder_in_partition (encoder, (symtab_node)origin_node); + = varpool_get_node (DECL_ABSTRACT_ORIGIN (node->decl)); + lto_set_symtab_encoder_in_partition (encoder, origin_node); } } /* Pickle in also the initializer of all referenced readonly variables @@ -810,15 +810,15 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder) pickle those too. */ for (i = 0; i < lto_symtab_encoder_size (encoder); i++) { - symtab_node node = lto_symtab_encoder_deref (encoder, i); + symtab_node *node = lto_symtab_encoder_deref (encoder, i); if (varpool_node *vnode = dyn_cast <varpool_node> (node)) { if (!lto_symtab_encoder_encode_initializer_p (encoder, vnode) - && ctor_for_folding (vnode->symbol.decl) != error_mark_node) + && ctor_for_folding (vnode->decl) != error_mark_node) { lto_set_symtab_encoder_encode_initializer (encoder, vnode); - add_references (encoder, &vnode->symbol.ref_list); + add_references (encoder, &vnode->ref_list); } } } @@ -832,7 +832,7 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder) for (edge = node->callees; edge; edge = edge->next_callee) { struct cgraph_node *callee = edge->callee; - if (!lto_symtab_encoder_in_partition_p (encoder, (symtab_node)callee)) + if (!lto_symtab_encoder_in_partition_p (encoder, callee)) { /* We should have moved all the inlines. */ gcc_assert (!callee->global.inlined_to); @@ -859,9 +859,9 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder) /* Adding an external declarations into the unit serves no purpose and just increases its boundary. */ - if (callee->symbol.definition + if (callee->definition && !lto_symtab_encoder_in_partition_p - (encoder, (symtab_node)callee)) + (encoder, callee)) { gcc_assert (!callee->global.inlined_to); add_node_to (encoder, callee, false); @@ -905,7 +905,7 @@ output_symtab (void) n_nodes = lto_symtab_encoder_size (encoder); for (i = 0; i < n_nodes; i++) { - symtab_node node = lto_symtab_encoder_deref (encoder, i); + symtab_node *node = lto_symtab_encoder_deref (encoder, i); if (cgraph_node *cnode = dyn_cast <cgraph_node> (node)) lto_output_node (ob, cnode, encoder); else @@ -952,24 +952,24 @@ input_overwrite_node (struct lto_file_decl_data *file_data, enum LTO_symtab_tags tag, struct bitpack_d *bp) { - node->symbol.aux = (void *) tag; - node->symbol.lto_file_data = file_data; + node->aux = (void *) tag; + node->lto_file_data = file_data; node->local.local = bp_unpack_value (bp, 1); - node->symbol.externally_visible = bp_unpack_value (bp, 1); - node->symbol.definition = bp_unpack_value (bp, 1); + node->externally_visible = bp_unpack_value (bp, 1); + node->definition = bp_unpack_value (bp, 1); node->local.versionable = bp_unpack_value (bp, 1); node->local.can_change_signature = bp_unpack_value (bp, 1); node->local.redefined_extern_inline = bp_unpack_value (bp, 1); - node->symbol.force_output = bp_unpack_value (bp, 1); - node->symbol.forced_by_abi = bp_unpack_value (bp, 1); - node->symbol.unique_name = bp_unpack_value (bp, 1); - node->symbol.address_taken = bp_unpack_value (bp, 1); - node->symbol.used_from_other_partition = bp_unpack_value (bp, 1); + node->force_output = bp_unpack_value (bp, 1); + node->forced_by_abi = bp_unpack_value (bp, 1); + node->unique_name = bp_unpack_value (bp, 1); + node->address_taken = bp_unpack_value (bp, 1); + node->used_from_other_partition = bp_unpack_value (bp, 1); node->lowered = bp_unpack_value (bp, 1); - node->symbol.analyzed = tag == LTO_symtab_analyzed_node; - node->symbol.in_other_partition = bp_unpack_value (bp, 1); - if (node->symbol.in_other_partition + node->analyzed = tag == LTO_symtab_analyzed_node; + node->in_other_partition = bp_unpack_value (bp, 1); + if (node->in_other_partition /* Avoid updating decl when we are seeing just inline clone. When inlining function that has functions already inlined into it, we produce clones of inline clones. @@ -978,19 +978,19 @@ input_overwrite_node (struct lto_file_decl_data *file_data, we might end up streaming inline clone from other partition to support clone we are interested in. */ && (!node->clone_of - || node->clone_of->symbol.decl != node->symbol.decl)) + || node->clone_of->decl != node->decl)) { - DECL_EXTERNAL (node->symbol.decl) = 1; - TREE_STATIC (node->symbol.decl) = 0; + DECL_EXTERNAL (node->decl) = 1; + TREE_STATIC (node->decl) = 0; } - node->symbol.alias = bp_unpack_value (bp, 1); - node->symbol.weakref = bp_unpack_value (bp, 1); + node->alias = bp_unpack_value (bp, 1); + node->weakref = bp_unpack_value (bp, 1); node->frequency = (enum node_frequency)bp_unpack_value (bp, 2); node->only_called_at_startup = bp_unpack_value (bp, 1); node->only_called_at_exit = bp_unpack_value (bp, 1); node->tm_clone = bp_unpack_value (bp, 1); node->thunk.thunk_p = bp_unpack_value (bp, 1); - node->symbol.resolution = bp_unpack_enum (bp, ld_plugin_symbol_resolution, + node->resolution = bp_unpack_enum (bp, ld_plugin_symbol_resolution, LDPR_NUM_KNOWN); } @@ -1011,7 +1011,7 @@ static struct cgraph_node * input_node (struct lto_file_decl_data *file_data, struct lto_input_block *ib, enum LTO_symtab_tags tag, - vec<symtab_node> nodes) + vec<symtab_node *> nodes) { gcc::pass_manager *passes = g->get_passes (); tree fn_decl; @@ -1041,11 +1041,11 @@ input_node (struct lto_file_decl_data *file_data, from other input file. We keep cgraph unmerged until after streaming of ipa passes is done. Alays forcingly create a fresh node. */ node = cgraph_create_empty_node (); - node->symbol.decl = fn_decl; - symtab_register_node ((symtab_node)node); + node->decl = fn_decl; + symtab_register_node (node); } - node->symbol.order = order; + node->order = order; if (order >= symtab_order) symtab_order = order + 1; @@ -1073,7 +1073,7 @@ input_node (struct lto_file_decl_data *file_data, have already been read will have their tag stored in the 'aux' field. Since built-in functions can be referenced in multiple functions, they are expected to be read more than once. */ - if (node->symbol.aux && !DECL_BUILT_IN (node->symbol.decl)) + if (node->aux && !DECL_BUILT_IN (node->decl)) internal_error ("bytecode stream: found multiple instances of cgraph " "node with uid %d", node->uid); @@ -1084,7 +1084,7 @@ input_node (struct lto_file_decl_data *file_data, node->global.inlined_to = (cgraph_node_ptr) (intptr_t) ref; /* Store a reference for now, and fix up later to be a pointer. */ - node->symbol.same_comdat_group = (symtab_node) (intptr_t) ref2; + node->same_comdat_group = (symtab_node *) (intptr_t) ref2; if (node->thunk.thunk_p) { @@ -1097,8 +1097,8 @@ input_node (struct lto_file_decl_data *file_data, node->thunk.virtual_value = virtual_value; node->thunk.virtual_offset_p = (type & 4); } - if (node->symbol.alias && !node->symbol.analyzed && node->symbol.weakref) - node->symbol.alias_target = get_alias_symbol (node->symbol.decl); + if (node->alias && !node->analyzed && node->weakref) + node->alias_target = get_alias_symbol (node->decl); node->profile_id = streamer_read_hwi (ib); return node; } @@ -1125,36 +1125,36 @@ input_varpool_node (struct lto_file_decl_data *file_data, from other input file. We keep cgraph unmerged until after streaming of ipa passes is done. Alays forcingly create a fresh node. */ node = varpool_create_empty_node (); - node->symbol.decl = var_decl; - symtab_register_node ((symtab_node)node); + node->decl = var_decl; + symtab_register_node (node); - node->symbol.order = order; + node->order = order; if (order >= symtab_order) symtab_order = order + 1; - node->symbol.lto_file_data = file_data; + node->lto_file_data = file_data; bp = streamer_read_bitpack (ib); - node->symbol.externally_visible = bp_unpack_value (&bp, 1); - node->symbol.force_output = bp_unpack_value (&bp, 1); - node->symbol.forced_by_abi = bp_unpack_value (&bp, 1); - node->symbol.unique_name = bp_unpack_value (&bp, 1); - node->symbol.definition = bp_unpack_value (&bp, 1); - node->symbol.alias = bp_unpack_value (&bp, 1); - node->symbol.weakref = bp_unpack_value (&bp, 1); - node->symbol.analyzed = bp_unpack_value (&bp, 1); - node->symbol.used_from_other_partition = bp_unpack_value (&bp, 1); - node->symbol.in_other_partition = bp_unpack_value (&bp, 1); - if (node->symbol.in_other_partition) + node->externally_visible = bp_unpack_value (&bp, 1); + node->force_output = bp_unpack_value (&bp, 1); + node->forced_by_abi = bp_unpack_value (&bp, 1); + node->unique_name = bp_unpack_value (&bp, 1); + node->definition = bp_unpack_value (&bp, 1); + node->alias = bp_unpack_value (&bp, 1); + node->weakref = bp_unpack_value (&bp, 1); + node->analyzed = bp_unpack_value (&bp, 1); + node->used_from_other_partition = bp_unpack_value (&bp, 1); + node->in_other_partition = bp_unpack_value (&bp, 1); + if (node->in_other_partition) { - DECL_EXTERNAL (node->symbol.decl) = 1; - TREE_STATIC (node->symbol.decl) = 0; + DECL_EXTERNAL (node->decl) = 1; + TREE_STATIC (node->decl) = 0; } - if (node->symbol.alias && !node->symbol.analyzed && node->symbol.weakref) - node->symbol.alias_target = get_alias_symbol (node->symbol.decl); + if (node->alias && !node->analyzed && node->weakref) + node->alias_target = get_alias_symbol (node->decl); ref = streamer_read_hwi (ib); /* Store a reference for now, and fix up later to be a pointer. */ - node->symbol.same_comdat_group = (symtab_node) (intptr_t) ref; - node->symbol.resolution = streamer_read_enum (ib, ld_plugin_symbol_resolution, + node->same_comdat_group = (symtab_node *) (intptr_t) ref; + node->resolution = streamer_read_enum (ib, ld_plugin_symbol_resolution, LDPR_NUM_KNOWN); return node; @@ -1165,10 +1165,10 @@ input_varpool_node (struct lto_file_decl_data *file_data, static void input_ref (struct lto_input_block *ib, - symtab_node referring_node, - vec<symtab_node> nodes) + symtab_node *referring_node, + vec<symtab_node *> nodes) { - symtab_node node = NULL; + symtab_node *node = NULL; struct bitpack_d bp; enum ipa_ref_use use; bool speculative; @@ -1190,7 +1190,7 @@ input_ref (struct lto_input_block *ib, indirect_unknown_callee set). */ static void -input_edge (struct lto_input_block *ib, vec<symtab_node> nodes, +input_edge (struct lto_input_block *ib, vec<symtab_node *> nodes, bool indirect) { struct cgraph_node *caller, *callee; @@ -1203,13 +1203,13 @@ input_edge (struct lto_input_block *ib, vec<symtab_node> nodes, int ecf_flags = 0; caller = cgraph (nodes[streamer_read_hwi (ib)]); - if (caller == NULL || caller->symbol.decl == NULL_TREE) + if (caller == NULL || caller->decl == NULL_TREE) internal_error ("bytecode stream: no caller found while reading edge"); if (!indirect) { callee = cgraph (nodes[streamer_read_hwi (ib)]); - if (callee == NULL || callee->symbol.decl == NULL_TREE) + if (callee == NULL || callee->decl == NULL_TREE) internal_error ("bytecode stream: no callee found while reading edge"); } else @@ -1257,13 +1257,13 @@ input_edge (struct lto_input_block *ib, vec<symtab_node> nodes, /* Read a cgraph from IB using the info in FILE_DATA. */ -static vec<symtab_node> +static vec<symtab_node *> input_cgraph_1 (struct lto_file_decl_data *file_data, struct lto_input_block *ib) { enum LTO_symtab_tags tag; - vec<symtab_node> nodes = vNULL; - symtab_node node; + vec<symtab_node *> nodes = vNULL; + symtab_node *node; unsigned i; tag = streamer_read_enum (ib, LTO_symtab_tags, LTO_symtab_last_tag); @@ -1276,14 +1276,14 @@ input_cgraph_1 (struct lto_file_decl_data *file_data, input_edge (ib, nodes, true); else if (tag == LTO_symtab_variable) { - node = (symtab_node)input_varpool_node (file_data, ib); + node = input_varpool_node (file_data, ib); nodes.safe_push (node); lto_symtab_encoder_encode (file_data->symtab_node_encoder, node); } else { - node = (symtab_node)input_node (file_data, ib, tag, nodes); - if (node == NULL || node->symbol.decl == NULL_TREE) + node = input_node (file_data, ib, tag, nodes); + if (node == NULL || node->decl == NULL_TREE) internal_error ("bytecode stream: found empty cgraph node"); nodes.safe_push (node); lto_symtab_encoder_encode (file_data->symtab_node_encoder, node); @@ -1297,7 +1297,7 @@ input_cgraph_1 (struct lto_file_decl_data *file_data, /* AUX pointers should be all non-zero for function nodes read from the stream. */ #ifdef ENABLE_CHECKING FOR_EACH_VEC_ELT (nodes, i, node) - gcc_assert (node->symbol.aux || !is_a <cgraph_node> (node)); + gcc_assert (node->aux || !is_a <cgraph_node> (node)); #endif FOR_EACH_VEC_ELT (nodes, i, node) { @@ -1307,9 +1307,9 @@ input_cgraph_1 (struct lto_file_decl_data *file_data, ref = (int) (intptr_t) cnode->global.inlined_to; /* We share declaration of builtins, so we may read same node twice. */ - if (!node->symbol.aux) + if (!node->aux) continue; - node->symbol.aux = NULL; + node->aux = NULL; /* Fixup inlined_to from reference to pointer. */ if (ref != LCC_NOT_FOUND) @@ -1318,16 +1318,16 @@ input_cgraph_1 (struct lto_file_decl_data *file_data, cnode->global.inlined_to = NULL; } - ref = (int) (intptr_t) node->symbol.same_comdat_group; + ref = (int) (intptr_t) node->same_comdat_group; /* Fixup same_comdat_group from reference to pointer. */ if (ref != LCC_NOT_FOUND) - node->symbol.same_comdat_group = nodes[ref]; + node->same_comdat_group = nodes[ref]; else - node->symbol.same_comdat_group = NULL; + node->same_comdat_group = NULL; } FOR_EACH_VEC_ELT (nodes, i, node) - node->symbol.aux = is_a <cgraph_node> (node) ? (void *)1 : NULL; + node->aux = is_a <cgraph_node> (node) ? (void *)1 : NULL; return nodes; } @@ -1335,13 +1335,13 @@ input_cgraph_1 (struct lto_file_decl_data *file_data, static void input_refs (struct lto_input_block *ib, - vec<symtab_node> nodes) + vec<symtab_node *> nodes) { int count; int idx; while (true) { - symtab_node node; + symtab_node *node; count = streamer_read_uhwi (ib); if (!count) break; @@ -1509,13 +1509,13 @@ merge_profile_summaries (struct lto_file_decl_data **file_data_vec) During LTRANS we already have values of count_materialization_scale computed, so just update them. */ FOR_EACH_FUNCTION (node) - if (node->symbol.lto_file_data - && node->symbol.lto_file_data->profile_info.runs) + if (node->lto_file_data + && node->lto_file_data->profile_info.runs) { int scale; scale = RDIV (node->count_materialization_scale * max_runs, - node->symbol.lto_file_data->profile_info.runs); + node->lto_file_data->profile_info.runs); node->count_materialization_scale = scale; if (scale < 0) fatal_error ("Profile information in %s corrupted", @@ -1545,7 +1545,7 @@ input_symtab (void) const char *data; size_t len; struct lto_input_block *ib; - vec<symtab_node> nodes; + vec<symtab_node *> nodes; ib = lto_create_simple_input_block (file_data, LTO_section_symtab_nodes, &data, &len); @@ -1583,8 +1583,8 @@ input_symtab (void) node for the parent function was never emitted to the gimple file, cgraph_node will create a node for it when setting the context of the nested function. */ - if (node->symbol.lto_file_data) - node->symbol.aux = NULL; + if (node->lto_file_data) + node->aux = NULL; } } @@ -1651,7 +1651,7 @@ output_node_opt_summary (struct output_block *ob, streamer_write_bitpack (&bp); } - if (lto_symtab_encoder_in_partition_p (encoder, (symtab_node) node)) + if (lto_symtab_encoder_in_partition_p (encoder, node)) { for (e = node->callees; e; e = e->next_callee) output_edge_opt_summary (ob, e); @@ -1676,7 +1676,7 @@ output_cgraph_opt_summary (void) n_nodes = lto_symtab_encoder_size (encoder); for (i = 0; i < n_nodes; i++) { - symtab_node node = lto_symtab_encoder_deref (encoder, i); + symtab_node *node = lto_symtab_encoder_deref (encoder, i); cgraph_node *cnode = dyn_cast <cgraph_node> (node); if (cnode && output_cgraph_opt_summary_p (cnode)) count++; @@ -1684,7 +1684,7 @@ output_cgraph_opt_summary (void) streamer_write_uhwi (ob, count); for (i = 0; i < n_nodes; i++) { - symtab_node node = lto_symtab_encoder_deref (encoder, i); + symtab_node *node = lto_symtab_encoder_deref (encoder, i); cgraph_node *cnode = dyn_cast <cgraph_node> (node); if (cnode && output_cgraph_opt_summary_p (cnode)) { @@ -1757,7 +1757,7 @@ input_node_opt_summary (struct cgraph_node *node, static void input_cgraph_opt_section (struct lto_file_decl_data *file_data, const char *data, size_t len, - vec<symtab_node> nodes) + vec<symtab_node *> nodes) { const struct lto_function_header *header = (const struct lto_function_header *) data; @@ -1791,7 +1791,7 @@ input_cgraph_opt_section (struct lto_file_decl_data *file_data, /* Input optimization summary of cgraph. */ static void -input_cgraph_opt_summary (vec<symtab_node> nodes) +input_cgraph_opt_summary (vec<symtab_node *> nodes) { struct lto_file_decl_data **file_data_vec = lto_get_file_decl_data (); struct lto_file_decl_data *file_data; diff --git a/gcc/lto-compress.c b/gcc/lto-compress.c index 238bb64574e..3a67616cf8b 100644 --- a/gcc/lto-compress.c +++ b/gcc/lto-compress.c @@ -28,6 +28,7 @@ along with GCC; see the file COPYING3. If not see #include <zlib.h> #include "coretypes.h" #include "tree.h" +#include "gimple.h" #include "diagnostic-core.h" #include "langhooks.h" #include "lto-streamer.h" diff --git a/gcc/lto-opts.c b/gcc/lto-opts.c index 4d9cdfd07eb..0a63f89c882 100644 --- a/gcc/lto-opts.c +++ b/gcc/lto-opts.c @@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "tree.h" +#include "gimple.h" #include "hashtab.h" #include "ggc.h" #include "vec.h" diff --git a/gcc/lto-section-in.c b/gcc/lto-section-in.c index d96cdb47548..e4f0aedfa0f 100644 --- a/gcc/lto-section-in.c +++ b/gcc/lto-section-in.c @@ -24,14 +24,13 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tm.h" #include "tree.h" +#include "gimple.h" #include "expr.h" #include "flags.h" #include "params.h" #include "input.h" #include "hashtab.h" #include "basic-block.h" -#include "tree-ssa.h" -#include "cgraph.h" #include "function.h" #include "ggc.h" #include "diagnostic-core.h" @@ -429,24 +428,24 @@ lto_free_function_in_decl_state (struct lto_in_decl_state *state) release trees needed by the NODE's body. */ void -lto_free_function_in_decl_state_for_node (symtab_node node) +lto_free_function_in_decl_state_for_node (symtab_node *node) { struct lto_in_decl_state temp; void **slot; - if (!node->symbol.lto_file_data) + if (!node->lto_file_data) return; - temp.fn_decl = node->symbol.decl; - slot = htab_find_slot (node->symbol.lto_file_data->function_decl_states, + temp.fn_decl = node->decl; + slot = htab_find_slot (node->lto_file_data->function_decl_states, &temp, NO_INSERT); if (slot && *slot) { lto_free_function_in_decl_state ((struct lto_in_decl_state*) *slot); - htab_clear_slot (node->symbol.lto_file_data->function_decl_states, + htab_clear_slot (node->lto_file_data->function_decl_states, slot); } - node->symbol.lto_file_data = NULL; + node->lto_file_data = NULL; } diff --git a/gcc/lto-section-out.c b/gcc/lto-section-out.c index 59eed716630..4a2867376d5 100644 --- a/gcc/lto-section-out.c +++ b/gcc/lto-section-out.c @@ -24,19 +24,17 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tm.h" #include "tree.h" +#include "gimple.h" #include "expr.h" #include "params.h" #include "input.h" #include "hashtab.h" #include "basic-block.h" -#include "tree-ssa.h" -#include "cgraph.h" #include "function.h" #include "ggc.h" #include "except.h" #include "vec.h" #include "pointer-set.h" -#include "bitmap.h" #include "langhooks.h" #include "data-streamer.h" #include "lto-streamer.h" diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c index 8975cd6dd70..bf823d0dcba 100644 --- a/gcc/lto-streamer-in.c +++ b/gcc/lto-streamer-in.c @@ -32,9 +32,14 @@ along with GCC; see the file COPYING3. If not see #include "input.h" #include "hashtab.h" #include "basic-block.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-cfg.h" +#include "tree-ssanames.h" +#include "tree-into-ssa.h" +#include "tree-dfa.h" #include "tree-ssa.h" #include "tree-pass.h" -#include "cgraph.h" #include "function.h" #include "ggc.h" #include "diagnostic.h" @@ -791,7 +796,7 @@ fixup_call_stmt_edges_1 (struct cgraph_node *node, gimple *stmts, fatal_error ("Cgraph edge statement index not found"); } for (i = 0; - ipa_ref_list_reference_iterate (&node->symbol.ref_list, i, ref); + ipa_ref_list_reference_iterate (&node->ref_list, i, ref); i++) if (ref->lto_stmt_uid) { @@ -814,7 +819,7 @@ fixup_call_stmt_edges (struct cgraph_node *orig, gimple *stmts) while (orig->clone_of) orig = orig->clone_of; - fn = DECL_STRUCT_FUNCTION (orig->symbol.decl); + fn = DECL_STRUCT_FUNCTION (orig->decl); fixup_call_stmt_edges_1 (orig, stmts, fn); if (orig->clones) @@ -1031,7 +1036,7 @@ lto_read_body (struct lto_file_decl_data *file_data, struct cgraph_node *node, int string_offset; struct lto_input_block ib_cfg; struct lto_input_block ib_main; - tree fn_decl = node->symbol.decl; + tree fn_decl = node->decl; header = (const struct lto_function_header *) data; cfg_offset = sizeof (struct lto_function_header); diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c index f6af7087194..ff6d345fe32 100644 --- a/gcc/lto-streamer-out.c +++ b/gcc/lto-streamer-out.c @@ -31,9 +31,10 @@ along with GCC; see the file COPYING3. If not see #include "input.h" #include "hashtab.h" #include "basic-block.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-ssanames.h" #include "tree-pass.h" -#include "cgraph.h" #include "function.h" #include "ggc.h" #include "diagnostic-core.h" @@ -1763,7 +1764,7 @@ output_function (struct cgraph_node *node) basic_block bb; struct output_block *ob; - function = node->symbol.decl; + function = node->decl; fn = DECL_STRUCT_FUNCTION (function); ob = create_output_block (LTO_section_function_body); @@ -1922,8 +1923,8 @@ lto_output_toplevel_asms (void) static void copy_function (struct cgraph_node *node) { - tree function = node->symbol.decl; - struct lto_file_decl_data *file_data = node->symbol.lto_file_data; + tree function = node->decl; + struct lto_file_decl_data *file_data = node->lto_file_data; struct lto_output_stream *output_stream = XCNEW (struct lto_output_stream); const char *data; size_t len; @@ -1950,7 +1951,7 @@ copy_function (struct cgraph_node *node) /* Copy decls. */ in_state = - lto_get_function_in_decl_state (node->symbol.lto_file_data, function); + lto_get_function_in_decl_state (node->lto_file_data, function); gcc_assert (in_state); for (i = 0; i < LTO_N_DECL_STREAMS; i++) @@ -1994,25 +1995,25 @@ lto_output (void) /* Process only the functions with bodies. */ for (i = 0; i < n_nodes; i++) { - symtab_node snode = lto_symtab_encoder_deref (encoder, i); + symtab_node *snode = lto_symtab_encoder_deref (encoder, i); cgraph_node *node = dyn_cast <cgraph_node> (snode); if (node && lto_symtab_encoder_encode_body_p (encoder, node) - && !node->symbol.alias) + && !node->alias) { #ifdef ENABLE_CHECKING - gcc_assert (!bitmap_bit_p (output, DECL_UID (node->symbol.decl))); - bitmap_set_bit (output, DECL_UID (node->symbol.decl)); + gcc_assert (!bitmap_bit_p (output, DECL_UID (node->decl))); + bitmap_set_bit (output, DECL_UID (node->decl)); #endif decl_state = lto_new_out_decl_state (); lto_push_out_decl_state (decl_state); - if (gimple_has_body_p (node->symbol.decl) || !flag_wpa) + if (gimple_has_body_p (node->decl) || !flag_wpa) output_function (node); else copy_function (node); gcc_assert (lto_get_out_decl_state () == decl_state); lto_pop_out_decl_state (); - lto_record_function_out_decl_state (node->symbol.decl, decl_state); + lto_record_function_out_decl_state (node->decl, decl_state); } } @@ -2244,10 +2245,10 @@ write_symbol (struct streamer_tree_cache_d *cache, /* When something is defined, it should have node attached. */ gcc_assert (alias || TREE_CODE (t) != VAR_DECL - || varpool_get_node (t)->symbol.definition); + || varpool_get_node (t)->definition); gcc_assert (alias || TREE_CODE (t) != FUNCTION_DECL || (cgraph_get_node (t) - && cgraph_get_node (t)->symbol.definition)); + && cgraph_get_node (t)->definition)); } /* Imitate what default_elf_asm_output_external do. @@ -2302,7 +2303,7 @@ write_symbol (struct streamer_tree_cache_d *cache, /* Return true if NODE should appear in the plugin symbol table. */ bool -output_symbol_p (symtab_node node) +output_symbol_p (symtab_node *node) { struct cgraph_node *cnode; if (!symtab_real_symbol_p (node)) @@ -2311,7 +2312,7 @@ output_symbol_p (symtab_node node) and devirtualization. We do not want to see them in symbol table as references unless they are really used. */ cnode = dyn_cast <cgraph_node> (node); - if (cnode && (!node->symbol.definition || DECL_EXTERNAL (cnode->symbol.decl)) + if (cnode && (!node->definition || DECL_EXTERNAL (cnode->decl)) && cnode->callers) return true; @@ -2319,18 +2320,18 @@ output_symbol_p (symtab_node node) part of the compilation unit until they are used by folding. Some symbols, like references to external construction vtables can not be referred to at all. We decide this at can_refer_decl_in_current_unit_p. */ - if (!node->symbol.definition || DECL_EXTERNAL (node->symbol.decl)) + if (!node->definition || DECL_EXTERNAL (node->decl)) { int i; struct ipa_ref *ref; - for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list, + for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list, i, ref); i++) { if (ref->use == IPA_REF_ALIAS) continue; if (is_a <cgraph_node> (ref->referring)) return true; - if (!DECL_EXTERNAL (ref->referring->symbol.decl)) + if (!DECL_EXTERNAL (ref->referring->decl)) return true; } return false; @@ -2364,20 +2365,20 @@ produce_symtab (struct output_block *ob) for (lsei = lsei_start (encoder); !lsei_end_p (lsei); lsei_next (&lsei)) { - symtab_node node = lsei_node (lsei); + symtab_node *node = lsei_node (lsei); - if (!output_symbol_p (node) || DECL_EXTERNAL (node->symbol.decl)) + if (!output_symbol_p (node) || DECL_EXTERNAL (node->decl)) continue; - write_symbol (cache, &stream, node->symbol.decl, seen, false); + write_symbol (cache, &stream, node->decl, seen, false); } for (lsei = lsei_start (encoder); !lsei_end_p (lsei); lsei_next (&lsei)) { - symtab_node node = lsei_node (lsei); + symtab_node *node = lsei_node (lsei); - if (!output_symbol_p (node) || !DECL_EXTERNAL (node->symbol.decl)) + if (!output_symbol_p (node) || !DECL_EXTERNAL (node->decl)) continue; - write_symbol (cache, &stream, node->symbol.decl, seen, false); + write_symbol (cache, &stream, node->decl, seen, false); } lto_write_stream (&stream); diff --git a/gcc/lto-streamer.c b/gcc/lto-streamer.c index f1d3b69127d..1540e4c4be8 100644 --- a/gcc/lto-streamer.c +++ b/gcc/lto-streamer.c @@ -28,9 +28,8 @@ along with GCC; see the file COPYING3. If not see #include "flags.h" #include "tree.h" #include "gimple.h" -#include "tree-ssa.h" -#include "diagnostic-core.h" #include "bitmap.h" +#include "diagnostic-core.h" #include "vec.h" #include "tree-streamer.h" #include "lto-streamer.h" diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h index 13a9593a866..797e92e335b 100644 --- a/gcc/lto-streamer.h +++ b/gcc/lto-streamer.h @@ -25,8 +25,6 @@ along with GCC; see the file COPYING3. If not see #include "plugin-api.h" #include "hash-table.h" -#include "tree.h" -#include "gimple.h" #include "target.h" #include "cgraph.h" #include "vec.h" @@ -432,7 +430,7 @@ struct lto_stats_d /* Entry of LTO symtab encoder. */ typedef struct { - symtab_node node; + symtab_node *node; /* Is the node in this partition (i.e. ltrans of this partition will be responsible for outputting it)? */ unsigned int in_partition:1; @@ -775,7 +773,7 @@ extern int lto_eq_in_decl_state (const void *, const void *); extern struct lto_in_decl_state *lto_get_function_in_decl_state ( struct lto_file_decl_data *, tree); extern void lto_free_function_in_decl_state (struct lto_in_decl_state *); -extern void lto_free_function_in_decl_state_for_node (symtab_node); +extern void lto_free_function_in_decl_state_for_node (symtab_node *); extern void lto_section_overrun (struct lto_input_block *) ATTRIBUTE_NORETURN; extern void lto_value_range_error (const char *, HOST_WIDE_INT, HOST_WIDE_INT, @@ -874,15 +872,15 @@ void lto_output_location (struct output_block *, struct bitpack_d *, location_t) /* In lto-cgraph.c */ lto_symtab_encoder_t lto_symtab_encoder_new (bool); -int lto_symtab_encoder_encode (lto_symtab_encoder_t, symtab_node); +int lto_symtab_encoder_encode (lto_symtab_encoder_t, symtab_node *); void lto_symtab_encoder_delete (lto_symtab_encoder_t); -bool lto_symtab_encoder_delete_node (lto_symtab_encoder_t, symtab_node); +bool lto_symtab_encoder_delete_node (lto_symtab_encoder_t, symtab_node *); bool lto_symtab_encoder_encode_body_p (lto_symtab_encoder_t, struct cgraph_node *); bool lto_symtab_encoder_in_partition_p (lto_symtab_encoder_t, - symtab_node); + symtab_node *); void lto_set_symtab_encoder_in_partition (lto_symtab_encoder_t, - symtab_node); + symtab_node *); bool lto_symtab_encoder_encode_initializer_p (lto_symtab_encoder_t, struct varpool_node *); @@ -1045,7 +1043,7 @@ lto_symtab_encoder_size (lto_symtab_encoder_t encoder) static inline int lto_symtab_encoder_lookup (lto_symtab_encoder_t encoder, - symtab_node node) + symtab_node *node) { void **slot = pointer_map_contains (encoder->map, node); return (slot && *slot ? (size_t) *(slot) - 1 : LCC_NOT_FOUND); @@ -1066,7 +1064,7 @@ lsei_next (lto_symtab_encoder_iterator *lsei) } /* Return the node pointed to by LSI. */ -static inline symtab_node +static inline symtab_node * lsei_node (lto_symtab_encoder_iterator lsei) { return lsei.encoder->nodes[lsei.index].node; @@ -1088,7 +1086,7 @@ lsei_varpool_node (lto_symtab_encoder_iterator lsei) /* Return the cgraph node corresponding to REF using ENCODER. */ -static inline symtab_node +static inline symtab_node * lto_symtab_encoder_deref (lto_symtab_encoder_t encoder, int ref) { if (ref == LCC_NOT_FOUND) diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog index 0bc08627d89..b3bed0b3921 100644 --- a/gcc/lto/ChangeLog +++ b/gcc/lto/ChangeLog @@ -1,3 +1,105 @@ +2013-10-31 David Malcolm <dmalcolm@redhat.com> + + Automated part of renaming of symtab_node_base to symtab_node. + + Patch autogenerated by rename_symtab.py from + https://github.com/davidmalcolm/gcc-refactoring-scripts + revision 58bb219cc090b2f4516a9297d868c245495ee622 + + * lto-partition.c (add_symbol_to_partition): Rename + symtab_node_base to symtab_node. + (get_symbol_class): Likewise. + (symbol_partitioned_p): Likewise. + (add_references_to_partition): Likewise. + (add_symbol_to_partition_1): Likewise. + (contained_in_symbol): Likewise. + (add_symbol_to_partition): Likewise. + (lto_1_to_1_map): Likewise. + (lto_max_map): Likewise. + (lto_balanced_map): Likewise. + (privatize_symbol_name): Likewise. + (promote_symbol): Likewise. + (may_need_named_section_p): Likewise. + (rename_statics): Likewise. + (lto_promote_statics_nonwpa): Likewise. + * lto-symtab.c (lto_symtab_merge): Likewise. + (lto_symtab_resolve_replaceable_p): Likewise. + (lto_symtab_symbol_p): Likewise. + (lto_symtab_resolve_can_prevail_p): Likewise. + (lto_symtab_resolve_symbols): Likewise. + (lto_symtab_merge_decls_2): Likewise. + (lto_symtab_merge_decls_1): Likewise. + (lto_symtab_merge_decls): Likewise. + (lto_symtab_merge_symbols_1): Likewise. + (lto_symtab_merge_symbols): Likewise. + (lto_symtab_prevailing_decl): Likewise. + * lto.c (lto_wpa_write_files): Likewise. + (read_cgraph_and_symbols): Likewise. + (do_whole_program_analysis): Likewise. + +2013-10-30 David Malcolm <dmalcolm@redhat.com> + + * lto-symtab.c (lto_symtab_merge_decls_2): Split symtab_node + declarations onto multiple lines to make things easier for + rename_symtab.py. + (lto_symtab_merge_decls_1): Likewise. + (lto_symtab_merge_symbols_1): Likewise. + +2013-10-29 Balaji V. Iyer <balaji.v.iyer@intel.com> + + * Make-lang.in (lto/lto-lang.o): Added cilk.h in dependency list. + * lto-lang.c (lto_init): Added a call to cilk_init_builtins if Cilk + Plus is enabled. + +2013-10-29 David Malcolm <dmalcolm@redhat.com> + + Patch autogenerated by refactor_symtab.py from + https://github.com/davidmalcolm/gcc-refactoring-scripts + revision 58bb219cc090b2f4516a9297d868c245495ee622 + + * lto-partition.c (lto_promote_cross_file_statics): Update for + conversion of symtab types to a true class hierarchy. + (rename_statics): Likewise. + (promote_symbol): Likewise. + (privatize_symbol_name): Likewise. + (lto_balanced_map): Likewise. + (varpool_node_cmp): Likewise. + (node_cmp): Likewise. + (lto_1_to_1_map): Likewise. + (undo_partition): Likewise. + (add_symbol_to_partition): Likewise. + (contained_in_symbol): Likewise. + (add_symbol_to_partition_1): Likewise. + (add_references_to_partition): Likewise. + (symbol_partitioned_p): Likewise. + (get_symbol_class): Likewise. + (lto_max_map): Likewise. + * lto-symtab.c (lto_symtab_prevailing_decl): Likewise. + (lto_symtab_merge_symbols): Likewise. + (lto_symtab_merge_symbols_1): Likewise. + (lto_symtab_merge_decls): Likewise. + (lto_symtab_merge_decls_1): Likewise. + (lto_symtab_merge_decls_2): Likewise. + (lto_symtab_resolve_symbols): Likewise. + (lto_symtab_resolve_can_prevail_p): Likewise. + (lto_symtab_symbol_p): Likewise. + (lto_symtab_resolve_replaceable_p): Likewise. + (lto_symtab_merge): Likewise. + (lto_varpool_replace_node): Likewise. + (lto_cgraph_replace_node): Likewise. + * lto.c (lto_main): Likewise. + (do_whole_program_analysis): Likewise. + (materialize_cgraph): Likewise. + (read_cgraph_and_symbols): Likewise. + (cmp_partitions_order): Likewise. + (lto_materialize_function): Likewise. + (has_analyzed_clone_p): Likewise. + +2013-10-29 Andrew MacLeod <amacleod@redhat.com> + + * lto/lto-object.c: Add gimple.h to include list. + * lto/lto-partition.c: Likewise. + 2013-10-18 Andrew MacLeod <amacleod@redhat.com> * lto.c: Remove tree-flow.h from include list. @@ -241,7 +343,7 @@ lto_register_function_decl_in_symtab): Update. (read_cgraph_and_symbols): Update resolution_map handling. -2013-06-11 Jan Hubicka <jh@suse.cz> +2013-06-11 Jan Hubicka <jh@suse.cz> * lto-partition.c (get_symbol_class): Simplify weakref handling. (add_symbol_to_partition_1): Likewise. @@ -704,7 +806,7 @@ builtins on the fly in the future. Change all uses, and poison the old names. Make sure 0 is not a legitimate builtin index. -2011-10-02 Andi Kleen <ak@linux.intel.com> +2011-10-02 Andi Kleen <ak@linux.intel.com> * lto-object.c (lto_obj_add_section_data): Add list. (lto_obj_add_section): Fill in list. @@ -743,7 +845,7 @@ lto_splay_tree_insert. (lto_file_read): Use lto_splay_tree_new. -2011-09-26 Andi Kleen <ak@linux.intel.com> +2011-09-26 Andi Kleen <ak@linux.intel.com> * lto.c (lto_resolution_read): Remove id dumping. (lto_section_with_id): Turn id HOST_WIDE_ID. @@ -1118,7 +1220,7 @@ * lto.c (lto_balanced_map): Do not produce empty partitions. -2010-10-06 Andi Kleen <ak@linux.intel.com> +2010-10-06 Andi Kleen <ak@linux.intel.com> * lto.c (lto_process_name): Add. (lto_main): Call lto_process_name. @@ -1144,11 +1246,11 @@ (do_whole_program_analysis): Chose proper partitioning alg. * Make-lang.in (lto.o): Add dependency on params.h -2010-10-04 Andi Kleen <ak@linux.intel.com> +2010-10-04 Andi Kleen <ak@linux.intel.com> * Make-lang.in (lto1): Add + to build rule. -2010-10-03 Andi Kleen <ak@linux.intel.com> +2010-10-03 Andi Kleen <ak@linux.intel.com> * lto.c (lto_file_finalize): Replace gcc_assert for missing section with fatal_error. @@ -1234,7 +1336,7 @@ * lto.c: Use FOR_EACH_VEC_ELT. -2010-07-27 Andi Kleen <ak@linux.intel.com> +2010-07-27 Andi Kleen <ak@linux.intel.com> * Make-lang.in (lto.o): Add dependency to splay-tree.h @@ -1251,7 +1353,7 @@ (LANG_HOOKS_OPTION_LANG_MASK, LANG_HOOKS_COMPLAIN_WRONG_LANG_P): Define. -2010-07-10 Andi Kleen <ak@linux.intel.com> +2010-07-10 Andi Kleen <ak@linux.intel.com> PR lto/44992 * lto.c: Include splay-tree.h @@ -1267,7 +1369,7 @@ (lto_flatten_file): Add. (read_cgraph_and_symbols): Handle linked lists of file_datas. -2010-07-10 Andi Kleen <ak@linux.intel.com> +2010-07-10 Andi Kleen <ak@linux.intel.com> * lto-coff.c (hash_name, eq_name): Move. (lto_obj_build_section_table): Call lto_obj_create_section_hash_table. diff --git a/gcc/lto/lto-lang.c b/gcc/lto/lto-lang.c index de9bda9ba67..55bf1787a3f 100644 --- a/gcc/lto/lto-lang.c +++ b/gcc/lto/lto-lang.c @@ -35,6 +35,7 @@ along with GCC; see the file COPYING3. If not see #include "diagnostic-core.h" #include "toplev.h" #include "lto-streamer.h" +#include "cilk.h" static tree lto_type_for_size (unsigned, int); @@ -1173,6 +1174,9 @@ lto_init (void) lto_define_builtins (va_list_type_node, build_reference_type (va_list_type_node)); } + + if (flag_enable_cilkplus) + cilk_init_builtins (); targetm.init_builtins (); build_common_builtin_nodes (); diff --git a/gcc/lto/lto-object.c b/gcc/lto/lto-object.c index 77be1fbe230..19f10ccb978 100644 --- a/gcc/lto/lto-object.c +++ b/gcc/lto/lto-object.c @@ -21,6 +21,8 @@ along with GCC; see the file COPYING3. If not see #include "config.h" #include "system.h" #include "coretypes.h" +#include "tree.h" +#include "gimple.h" #include "diagnostic-core.h" #include "lto.h" #include "tm.h" diff --git a/gcc/lto/lto-partition.c b/gcc/lto/lto-partition.c index e05f805fea4..6a3d881acca 100644 --- a/gcc/lto/lto-partition.c +++ b/gcc/lto/lto-partition.c @@ -22,6 +22,7 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "toplev.h" #include "tree.h" +#include "gimple.h" #include "tm.h" #include "cgraph.h" #include "lto-streamer.h" @@ -46,29 +47,29 @@ enum symbol_class vec<ltrans_partition> ltrans_partitions; -static void add_symbol_to_partition (ltrans_partition part, symtab_node node); +static void add_symbol_to_partition (ltrans_partition part, symtab_node *node); /* Classify symbol NODE. */ enum symbol_class -get_symbol_class (symtab_node node) +get_symbol_class (symtab_node *node) { /* Inline clones are always duplicated. This include external delcarations. */ cgraph_node *cnode = dyn_cast <cgraph_node> (node); - if (DECL_ABSTRACT (node->symbol.decl)) + if (DECL_ABSTRACT (node->decl)) return SYMBOL_EXTERNAL; if (cnode && cnode->global.inlined_to) return SYMBOL_DUPLICATE; /* Weakref aliases are always duplicated. */ - if (node->symbol.weakref) + if (node->weakref) return SYMBOL_DUPLICATE; /* External declarations are external. */ - if (DECL_EXTERNAL (node->symbol.decl)) + if (DECL_EXTERNAL (node->decl)) return SYMBOL_EXTERNAL; if (varpool_node *vnode = dyn_cast <varpool_node> (node)) @@ -76,22 +77,22 @@ get_symbol_class (symtab_node node) /* Constant pool references use local symbol names that can not be promoted global. We should never put into a constant pool objects that can not be duplicated across partitions. */ - if (DECL_IN_CONSTANT_POOL (node->symbol.decl)) + if (DECL_IN_CONSTANT_POOL (node->decl)) return SYMBOL_DUPLICATE; - gcc_checking_assert (vnode->symbol.definition); + gcc_checking_assert (vnode->definition); } /* Functions that are cloned may stay in callgraph even if they are unused. Handle them as external; compute_ltrans_boundary take care to make proper things to happen (i.e. to make them appear in the boundary but with body streamed, so clone can me materialized). */ - else if (!cgraph (node)->symbol.definition) + else if (!cgraph (node)->definition) return SYMBOL_EXTERNAL; /* Comdats are duplicated to every use unless they are keyed. Those do not need duplication. */ - if (DECL_COMDAT (node->symbol.decl) - && !node->symbol.force_output - && !symtab_used_from_object_file_p ((symtab_node) node)) + if (DECL_COMDAT (node->decl) + && !node->force_output + && !symtab_used_from_object_file_p (node)) return SYMBOL_DUPLICATE; return SYMBOL_PARTITION; @@ -130,27 +131,27 @@ free_ltrans_partitions (void) /* Return true if symbol is already in some partition. */ static inline bool -symbol_partitioned_p (symtab_node node) +symbol_partitioned_p (symtab_node *node) { - return node->symbol.aux; + return node->aux; } /* Add references into the partition. */ static void -add_references_to_partition (ltrans_partition part, symtab_node node) +add_references_to_partition (ltrans_partition part, symtab_node *node) { int i; struct ipa_ref *ref; /* Add all duplicated references to the partition. */ - for (i = 0; ipa_ref_list_reference_iterate (&node->symbol.ref_list, i, ref); i++) + for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list, i, ref); i++) if (get_symbol_class (ref->referred) == SYMBOL_DUPLICATE) add_symbol_to_partition (part, ref->referred); /* References to a readonly variable may be constant foled into its value. Recursively look into the initializers of the constant variable and add references, too. */ else if (is_a <varpool_node> (ref->referred) - && ctor_for_folding (ref->referred->symbol.decl) != error_mark_node + && ctor_for_folding (ref->referred->decl) != error_mark_node && !lto_symtab_encoder_in_partition_p (part->encoder, ref->referred)) { if (!part->initializers_visited) @@ -164,15 +165,15 @@ add_references_to_partition (ltrans_partition part, symtab_node node) of adding NODE to PART. */ static bool -add_symbol_to_partition_1 (ltrans_partition part, symtab_node node) +add_symbol_to_partition_1 (ltrans_partition part, symtab_node *node) { enum symbol_class c = get_symbol_class (node); int i; struct ipa_ref *ref; - symtab_node node1; + symtab_node *node1; /* If NODE is already there, we have nothing to do. */ - if (lto_symtab_encoder_in_partition_p (part->encoder, (symtab_node) node)) + if (lto_symtab_encoder_in_partition_p (part->encoder, node)) return true; /* non-duplicated aliases or tunks of a duplicated symbol needs to be output @@ -180,7 +181,7 @@ add_symbol_to_partition_1 (ltrans_partition part, symtab_node node) Be lax about comdats; they may or may not be duplicated and we may end up in need to duplicate keyed comdat because it has unkeyed alias. */ - if (c == SYMBOL_PARTITION && !DECL_COMDAT (node->symbol.decl) + if (c == SYMBOL_PARTITION && !DECL_COMDAT (node->decl) && symbol_partitioned_p (node)) return false; @@ -189,16 +190,16 @@ add_symbol_to_partition_1 (ltrans_partition part, symtab_node node) gcc_assert (c != SYMBOL_EXTERNAL && (c == SYMBOL_DUPLICATE || !symbol_partitioned_p (node))); - lto_set_symtab_encoder_in_partition (part->encoder, (symtab_node) node); + lto_set_symtab_encoder_in_partition (part->encoder, node); if (symbol_partitioned_p (node)) { - node->symbol.in_other_partition = 1; + node->in_other_partition = 1; if (cgraph_dump_file) fprintf (cgraph_dump_file, "Symbol node %s now used in multiple partitions\n", symtab_node_name (node)); } - node->symbol.aux = (void *)((size_t)node->symbol.aux + 1); + node->aux = (void *)((size_t)node->aux + 1); if (cgraph_node *cnode = dyn_cast <cgraph_node> (node)) { @@ -208,27 +209,27 @@ add_symbol_to_partition_1 (ltrans_partition part, symtab_node node) /* Add all inline clones and callees that are duplicated. */ for (e = cnode->callees; e; e = e->next_callee) if (!e->inline_failed) - add_symbol_to_partition_1 (part, (symtab_node) e->callee); - else if (get_symbol_class ((symtab_node) e->callee) == SYMBOL_DUPLICATE) - add_symbol_to_partition (part, (symtab_node) e->callee); + add_symbol_to_partition_1 (part, e->callee); + else if (get_symbol_class (e->callee) == SYMBOL_DUPLICATE) + add_symbol_to_partition (part, e->callee); /* Add all thunks associated with the function. */ for (e = cnode->callers; e; e = e->next_caller) if (e->caller->thunk.thunk_p) - add_symbol_to_partition_1 (part, (symtab_node) e->caller); + add_symbol_to_partition_1 (part, e->caller); } add_references_to_partition (part, node); /* Add all aliases associated with the symbol. */ - for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list, i, ref); i++) - if (ref->use == IPA_REF_ALIAS && !node->symbol.weakref) + for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list, i, ref); i++) + if (ref->use == IPA_REF_ALIAS && !node->weakref) add_symbol_to_partition_1 (part, ref->referring); /* Ensure that SAME_COMDAT_GROUP lists all allways added in a group. */ - if (node->symbol.same_comdat_group) - for (node1 = node->symbol.same_comdat_group; - node1 != node; node1 = node1->symbol.same_comdat_group) + if (node->same_comdat_group) + for (node1 = node->same_comdat_group; + node1 != node; node1 = node1->same_comdat_group) { bool added = add_symbol_to_partition_1 (part, node1); gcc_assert (added); @@ -240,21 +241,21 @@ add_symbol_to_partition_1 (ltrans_partition part, symtab_node node) internal label, thunk, alias or so), return the outer symbol. When add_symbol_to_partition_1 is called on the outer symbol it must eventually add NODE, too. */ -static symtab_node -contained_in_symbol (symtab_node node) +static symtab_node * +contained_in_symbol (symtab_node *node) { /* Weakrefs are never contained in anything. */ - if (node->symbol.weakref) + if (node->weakref) return node; if (cgraph_node *cnode = dyn_cast <cgraph_node> (node)) { cnode = cgraph_function_node (cnode, NULL); if (cnode->global.inlined_to) cnode = cnode->global.inlined_to; - return (symtab_node) cnode; + return cnode; } else if (varpool_node *vnode = dyn_cast <varpool_node> (node)) - return (symtab_node) varpool_variable_node (vnode, NULL); + return varpool_variable_node (vnode, NULL); return node; } @@ -262,9 +263,9 @@ contained_in_symbol (symtab_node node) of other symbol definition, add the other symbol, too. */ static void -add_symbol_to_partition (ltrans_partition part, symtab_node node) +add_symbol_to_partition (ltrans_partition part, symtab_node *node) { - symtab_node node1; + symtab_node *node1; /* Verify that we do not try to duplicate something that can not be. */ gcc_checking_assert (get_symbol_class (node) == SYMBOL_DUPLICATE @@ -280,7 +281,7 @@ add_symbol_to_partition (ltrans_partition part, symtab_node node) Be lax about comdats; they may or may not be duplicated and we may end up in need to duplicate keyed comdat because it has unkeyed alias. */ gcc_assert (get_symbol_class (node) == SYMBOL_DUPLICATE - || DECL_COMDAT (node->symbol.decl) + || DECL_COMDAT (node->decl) || !symbol_partitioned_p (node)); add_symbol_to_partition_1 (part, node); } @@ -293,7 +294,7 @@ undo_partition (ltrans_partition partition, unsigned int n_nodes) { while (lto_symtab_encoder_size (partition->encoder) > (int)n_nodes) { - symtab_node node = lto_symtab_encoder_deref (partition->encoder, + symtab_node *node = lto_symtab_encoder_deref (partition->encoder, n_nodes); /* After UNDO we no longer know what was visited. */ @@ -304,7 +305,7 @@ undo_partition (ltrans_partition partition, unsigned int n_nodes) if (cgraph_node *cnode = dyn_cast <cgraph_node> (node)) partition->insns -= inline_summary (cnode)->self_size; lto_symtab_encoder_delete_node (partition->encoder, node); - node->symbol.aux = (void *)((size_t)node->symbol.aux - 1); + node->aux = (void *)((size_t)node->aux - 1); } } @@ -314,7 +315,7 @@ undo_partition (ltrans_partition partition, unsigned int n_nodes) void lto_1_to_1_map (void) { - symtab_node node; + symtab_node *node; struct lto_file_decl_data *file_data; struct pointer_map_t *pmap; ltrans_partition partition; @@ -329,7 +330,7 @@ lto_1_to_1_map (void) || symbol_partitioned_p (node)) continue; - file_data = node->symbol.lto_file_data; + file_data = node->lto_file_data; if (file_data) { @@ -354,7 +355,7 @@ lto_1_to_1_map (void) npartitions++; } - add_symbol_to_partition (partition, (symtab_node) node); + add_symbol_to_partition (partition, node); } /* If the cgraph is empty, create one cgraph node set so that there is still @@ -371,7 +372,7 @@ lto_1_to_1_map (void) void lto_max_map (void) { - symtab_node node; + symtab_node *node; ltrans_partition partition; int npartitions = 0; @@ -381,7 +382,7 @@ lto_max_map (void) || symbol_partitioned_p (node)) continue; partition = new_partition (symtab_node_asm_name (node)); - add_symbol_to_partition (partition, (symtab_node) node); + add_symbol_to_partition (partition, node); npartitions++; } if (!npartitions) @@ -394,7 +395,7 @@ node_cmp (const void *pa, const void *pb) { const struct cgraph_node *a = *(const struct cgraph_node * const *) pa; const struct cgraph_node *b = *(const struct cgraph_node * const *) pb; - return b->symbol.order - a->symbol.order; + return b->order - a->order; } /* Helper function for qsort; sort nodes by order. */ @@ -403,7 +404,7 @@ varpool_node_cmp (const void *pa, const void *pb) { const struct varpool_node *a = *(const struct varpool_node * const *) pa; const struct varpool_node *b = *(const struct varpool_node * const *) pb; - return b->symbol.order - a->symbol.order; + return b->order - a->order; } /* Group cgraph nodes into equally-sized partitions. @@ -465,10 +466,10 @@ lto_balanced_map (void) int current_order = -1; FOR_EACH_VARIABLE (vnode) - gcc_assert (!vnode->symbol.aux); + gcc_assert (!vnode->aux); FOR_EACH_DEFINED_FUNCTION (node) - if (get_symbol_class ((symtab_node) node) == SYMBOL_PARTITION) + if (get_symbol_class (node) == SYMBOL_PARTITION) { order[n_nodes++] = node; total_size += inline_summary (node)->size; @@ -485,13 +486,13 @@ lto_balanced_map (void) qsort (order, n_nodes, sizeof (struct cgraph_node *), node_cmp); FOR_EACH_VARIABLE (vnode) - if (get_symbol_class ((symtab_node) vnode) == SYMBOL_PARTITION) + if (get_symbol_class (vnode) == SYMBOL_PARTITION) n_varpool_nodes++; varpool_order = XNEWVEC (struct varpool_node *, n_varpool_nodes); n_varpool_nodes = 0; FOR_EACH_VARIABLE (vnode) - if (get_symbol_class ((symtab_node) vnode) == SYMBOL_PARTITION) + if (get_symbol_class (vnode) == SYMBOL_PARTITION) varpool_order[n_varpool_nodes++] = vnode; qsort (varpool_order, n_varpool_nodes, sizeof (struct varpool_node *), varpool_node_cmp); @@ -509,21 +510,21 @@ lto_balanced_map (void) for (i = 0; i < n_nodes; i++) { - if (symbol_partitioned_p ((symtab_node) order[i])) + if (symbol_partitioned_p (order[i])) continue; - current_order = order[i]->symbol.order; + current_order = order[i]->order; if (!flag_toplevel_reorder) while (varpool_pos < n_varpool_nodes - && varpool_order[varpool_pos]->symbol.order < current_order) + && varpool_order[varpool_pos]->order < current_order) { - if (!symbol_partitioned_p ((symtab_node) varpool_order[varpool_pos])) - add_symbol_to_partition (partition, (symtab_node) varpool_order[varpool_pos]); + if (!symbol_partitioned_p (varpool_order[varpool_pos])) + add_symbol_to_partition (partition, varpool_order[varpool_pos]); varpool_pos++; } - add_symbol_to_partition (partition, (symtab_node) order[i]); + add_symbol_to_partition (partition, order[i]); total_size -= inline_summary (order[i])->size; @@ -544,22 +545,22 @@ lto_balanced_map (void) struct ipa_ref_list *refs; int j; struct ipa_ref *ref; - symtab_node snode = lto_symtab_encoder_deref (partition->encoder, + symtab_node *snode = lto_symtab_encoder_deref (partition->encoder, last_visited_node); if (cgraph_node *node = dyn_cast <cgraph_node> (snode)) { struct cgraph_edge *edge; - refs = &node->symbol.ref_list; + refs = &node->ref_list; last_visited_node++; - gcc_assert (node->symbol.definition || node->symbol.weakref); + gcc_assert (node->definition || node->weakref); /* Compute boundary cost of callgraph edges. */ for (edge = node->callees; edge; edge = edge->next_callee) - if (edge->callee->symbol.definition) + if (edge->callee->definition) { int edge_cost = edge->frequency; int index; @@ -568,7 +569,7 @@ lto_balanced_map (void) edge_cost = 1; gcc_assert (edge_cost > 0); index = lto_symtab_encoder_lookup (partition->encoder, - (symtab_node)edge->callee); + edge->callee); if (index != LCC_NOT_FOUND && index < last_visited_node - 1) cost -= edge_cost, internal += edge_cost; @@ -580,12 +581,12 @@ lto_balanced_map (void) int edge_cost = edge->frequency; int index; - gcc_assert (edge->caller->symbol.definition); + gcc_assert (edge->caller->definition); if (!edge_cost) edge_cost = 1; gcc_assert (edge_cost > 0); index = lto_symtab_encoder_lookup (partition->encoder, - (symtab_node)edge->caller); + edge->caller); if (index != LCC_NOT_FOUND && index < last_visited_node - 1) cost -= edge_cost; @@ -595,7 +596,7 @@ lto_balanced_map (void) } else { - refs = &snode->symbol.ref_list; + refs = &snode->ref_list; last_visited_node++; } @@ -607,13 +608,13 @@ lto_balanced_map (void) int index; vnode = ipa_ref_varpool_node (ref); - if (!vnode->symbol.definition) + if (!vnode->definition) continue; - if (!symbol_partitioned_p ((symtab_node) vnode) && flag_toplevel_reorder - && get_symbol_class ((symtab_node) vnode) == SYMBOL_PARTITION) - add_symbol_to_partition (partition, (symtab_node) vnode); + if (!symbol_partitioned_p (vnode) && flag_toplevel_reorder + && get_symbol_class (vnode) == SYMBOL_PARTITION) + add_symbol_to_partition (partition, vnode); index = lto_symtab_encoder_lookup (partition->encoder, - (symtab_node)vnode); + vnode); if (index != LCC_NOT_FOUND && index < last_visited_node - 1) cost--, internal++; @@ -625,10 +626,10 @@ lto_balanced_map (void) int index; node = ipa_ref_node (ref); - if (!node->symbol.definition) + if (!node->definition) continue; index = lto_symtab_encoder_lookup (partition->encoder, - (symtab_node)node); + node); if (index != LCC_NOT_FOUND && index < last_visited_node - 1) cost--, internal++; @@ -641,12 +642,12 @@ lto_balanced_map (void) int index; vnode = ipa_ref_referring_varpool_node (ref); - gcc_assert (vnode->symbol.definition); - if (!symbol_partitioned_p ((symtab_node) vnode) && flag_toplevel_reorder - && get_symbol_class ((symtab_node) vnode) == SYMBOL_PARTITION) - add_symbol_to_partition (partition, (symtab_node) vnode); + gcc_assert (vnode->definition); + if (!symbol_partitioned_p (vnode) && flag_toplevel_reorder + && get_symbol_class (vnode) == SYMBOL_PARTITION) + add_symbol_to_partition (partition, vnode); index = lto_symtab_encoder_lookup (partition->encoder, - (symtab_node)vnode); + vnode); if (index != LCC_NOT_FOUND && index < last_visited_node - 1) cost--; @@ -658,9 +659,9 @@ lto_balanced_map (void) int index; node = ipa_ref_referring_node (ref); - gcc_assert (node->symbol.definition); + gcc_assert (node->definition); index = lto_symtab_encoder_lookup (partition->encoder, - (symtab_node)node); + node); if (index != LCC_NOT_FOUND && index < last_visited_node - 1) cost--; @@ -687,7 +688,7 @@ lto_balanced_map (void) if (cgraph_dump_file) fprintf (cgraph_dump_file, "Step %i: added %s/%i, size %i, cost %i/%i " "best %i/%i, step %i\n", i, - cgraph_node_name (order[i]), order[i]->symbol.order, + cgraph_node_name (order[i]), order[i]->order, partition->insns, cost, internal, best_cost, best_internal, best_i); /* Partition is too large, unwind into step when best cost was reached and @@ -704,7 +705,7 @@ lto_balanced_map (void) } i = best_i; /* When we are finished, avoid creating empty partition. */ - while (i < n_nodes - 1 && symbol_partitioned_p ((symtab_node) order[i + 1])) + while (i < n_nodes - 1 && symbol_partitioned_p (order[i + 1])) i++; if (i == n_nodes - 1) break; @@ -736,16 +737,16 @@ lto_balanced_map (void) if (flag_toplevel_reorder) { FOR_EACH_VARIABLE (vnode) - if (get_symbol_class ((symtab_node) vnode) == SYMBOL_PARTITION - && !symbol_partitioned_p ((symtab_node) vnode)) - add_symbol_to_partition (partition, (symtab_node) vnode); + if (get_symbol_class (vnode) == SYMBOL_PARTITION + && !symbol_partitioned_p (vnode)) + add_symbol_to_partition (partition, vnode); } else { while (varpool_pos < n_varpool_nodes) { - if (!symbol_partitioned_p ((symtab_node) varpool_order[varpool_pos])) - add_symbol_to_partition (partition, (symtab_node) varpool_order[varpool_pos]); + if (!symbol_partitioned_p (varpool_order[varpool_pos])) + add_symbol_to_partition (partition, varpool_order[varpool_pos]); varpool_pos++; } free (varpool_order); @@ -762,15 +763,15 @@ lto_balanced_map (void) */ static bool -privatize_symbol_name (symtab_node node) +privatize_symbol_name (symtab_node *node) { - tree decl = node->symbol.decl; + tree decl = node->decl; const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); /* Our renaming machinery do not handle more than one change of assembler name. We should not need more than one anyway. */ - if (node->symbol.lto_file_data - && lto_get_decl_name_mapping (node->symbol.lto_file_data, name) != name) + if (node->lto_file_data + && lto_get_decl_name_mapping (node->lto_file_data, name) != name) { if (cgraph_dump_file) fprintf (cgraph_dump_file, @@ -782,7 +783,7 @@ privatize_symbol_name (symtab_node node) ??? should have a flag whether a symbol has a 'private' name already, since we produce some symbols like that i.e. for global constructors that are not really clones. */ - if (node->symbol.unique_name) + if (node->unique_name) { if (cgraph_dump_file) fprintf (cgraph_dump_file, @@ -791,8 +792,8 @@ privatize_symbol_name (symtab_node node) return false; } change_decl_assembler_name (decl, clone_function_name (decl, "lto_priv")); - if (node->symbol.lto_file_data) - lto_record_renamed_decl (node->symbol.lto_file_data, name, + if (node->lto_file_data) + lto_record_renamed_decl (node->lto_file_data, name, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))); if (cgraph_dump_file) @@ -805,22 +806,22 @@ privatize_symbol_name (symtab_node node) /* Promote variable VNODE to be static. */ static void -promote_symbol (symtab_node node) +promote_symbol (symtab_node *node) { /* We already promoted ... */ - if (DECL_VISIBILITY (node->symbol.decl) == VISIBILITY_HIDDEN - && DECL_VISIBILITY_SPECIFIED (node->symbol.decl) - && TREE_PUBLIC (node->symbol.decl)) + if (DECL_VISIBILITY (node->decl) == VISIBILITY_HIDDEN + && DECL_VISIBILITY_SPECIFIED (node->decl) + && TREE_PUBLIC (node->decl)) return; - gcc_checking_assert (!TREE_PUBLIC (node->symbol.decl) - && !DECL_EXTERNAL (node->symbol.decl)); + gcc_checking_assert (!TREE_PUBLIC (node->decl) + && !DECL_EXTERNAL (node->decl)); /* Be sure that newly public symbol does not conflict with anything already defined by the non-LTO part. */ privatize_symbol_name (node); - TREE_PUBLIC (node->symbol.decl) = 1; - DECL_VISIBILITY (node->symbol.decl) = VISIBILITY_HIDDEN; - DECL_VISIBILITY_SPECIFIED (node->symbol.decl) = true; + TREE_PUBLIC (node->decl) = 1; + DECL_VISIBILITY (node->decl) = VISIBILITY_HIDDEN; + DECL_VISIBILITY_SPECIFIED (node->decl) = true; if (cgraph_dump_file) fprintf (cgraph_dump_file, "Promoting as hidden: %s\n", symtab_node_name (node)); @@ -831,7 +832,7 @@ promote_symbol (symtab_node node) FIXME: we should really not use named sections for inline clones and master clones. */ static bool -may_need_named_section_p (lto_symtab_encoder_t encoder, symtab_node node) +may_need_named_section_p (lto_symtab_encoder_t encoder, symtab_node *node) { struct cgraph_node *cnode = dyn_cast <cgraph_node> (node); if (!cnode) @@ -851,18 +852,18 @@ may_need_named_section_p (lto_symtab_encoder_t encoder, symtab_node node) asm statemnets referring to them by symbol name. */ static void -rename_statics (lto_symtab_encoder_t encoder, symtab_node node) +rename_statics (lto_symtab_encoder_t encoder, symtab_node *node) { - tree decl = node->symbol.decl; - symtab_node s; + tree decl = node->decl; + symtab_node *s; tree name = DECL_ASSEMBLER_NAME (decl); /* See if this is static symbol. */ - if ((node->symbol.externally_visible + if ((node->externally_visible /* FIXME: externally_visible is somewhat illogically not set for external symbols (i.e. those not defined). Remove this test once this is fixed. */ - || DECL_EXTERNAL (node->symbol.decl) + || DECL_EXTERNAL (node->decl) || !symtab_real_symbol_p (node)) && !may_need_named_section_p (encoder, node)) return; @@ -871,9 +872,9 @@ rename_statics (lto_symtab_encoder_t encoder, symtab_node node) (all types of symbols counts here, since we can not have static of the same name as external or public symbol.) */ for (s = symtab_node_for_asm (name); - s; s = s->symbol.next_sharing_asm_name) + s; s = s->next_sharing_asm_name) if ((symtab_real_symbol_p (s) || may_need_named_section_p (encoder, s)) - && s->symbol.decl != node->symbol.decl + && s->decl != node->decl && (!encoder || lto_symtab_encoder_lookup (encoder, s) != LCC_NOT_FOUND)) break; @@ -889,10 +890,10 @@ rename_statics (lto_symtab_encoder_t encoder, symtab_node node) /* Assign every symbol in the set that shares the same ASM name an unique mangled name. */ for (s = symtab_node_for_asm (name); s;) - if (!s->symbol.externally_visible + if (!s->externally_visible && ((symtab_real_symbol_p (s) - && !DECL_EXTERNAL (node->symbol.decl) - && !TREE_PUBLIC (node->symbol.decl)) + && !DECL_EXTERNAL (node->decl) + && !TREE_PUBLIC (node->decl)) || may_need_named_section_p (encoder, s)) && (!encoder || lto_symtab_encoder_lookup (encoder, s) != LCC_NOT_FOUND)) @@ -900,9 +901,9 @@ rename_statics (lto_symtab_encoder_t encoder, symtab_node node) if (privatize_symbol_name (s)) /* Re-start from beginning since we do not know how many symbols changed a name. */ s = symtab_node_for_asm (name); - else s = s->symbol.next_sharing_asm_name; + else s = s->next_sharing_asm_name; } - else s = s->symbol.next_sharing_asm_name; + else s = s->next_sharing_asm_name; } /* Find out all static decls that need to be promoted to global because @@ -934,19 +935,19 @@ lto_promote_cross_file_statics (void) for (lsei = lsei_start (encoder); !lsei_end_p (lsei); lsei_next (&lsei)) { - symtab_node node = lsei_node (lsei); + symtab_node *node = lsei_node (lsei); /* If symbol is static, rename it if its assembler name clash with anything else in this unit. */ rename_statics (encoder, node); /* No need to promote if symbol already is externally visible ... */ - if (node->symbol.externally_visible + if (node->externally_visible /* ... or if it is part of current partition ... */ || lto_symtab_encoder_in_partition_p (encoder, node) /* ... or if we do not partition it. This mean that it will appear in every partition refernecing it. */ - || get_symbol_class ((symtab_node) node) != SYMBOL_PARTITION) + || get_symbol_class (node) != SYMBOL_PARTITION) continue; promote_symbol (node); @@ -960,7 +961,7 @@ lto_promote_cross_file_statics (void) void lto_promote_statics_nonwpa (void) { - symtab_node node; + symtab_node *node; FOR_EACH_SYMBOL (node) rename_statics (NULL, node); } diff --git a/gcc/lto/lto-symtab.c b/gcc/lto/lto-symtab.c index b1b7731c830..ced6cf97908 100644 --- a/gcc/lto/lto-symtab.c +++ b/gcc/lto/lto-symtab.c @@ -44,17 +44,17 @@ lto_cgraph_replace_node (struct cgraph_node *node, { fprintf (cgraph_dump_file, "Replacing cgraph node %s/%i by %s/%i" " for symbol %s\n", - cgraph_node_name (node), node->symbol.order, + cgraph_node_name (node), node->order, cgraph_node_name (prevailing_node), - prevailing_node->symbol.order, + prevailing_node->order, IDENTIFIER_POINTER ((*targetm.asm_out.mangle_assembler_name) - (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->symbol.decl))))); + (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl))))); } /* Merge node flags. */ - if (node->symbol.force_output) + if (node->force_output) cgraph_mark_force_output_node (prevailing_node); - if (node->symbol.address_taken) + if (node->address_taken) { gcc_assert (!prevailing_node->global.inlined_to); cgraph_mark_address_taken_node (prevailing_node); @@ -62,8 +62,8 @@ lto_cgraph_replace_node (struct cgraph_node *node, /* Redirect all incoming edges. */ compatible_p - = types_compatible_p (TREE_TYPE (TREE_TYPE (prevailing_node->symbol.decl)), - TREE_TYPE (TREE_TYPE (node->symbol.decl))); + = types_compatible_p (TREE_TYPE (TREE_TYPE (prevailing_node->decl)), + TREE_TYPE (TREE_TYPE (node->decl))); for (e = node->callers; e; e = next) { next = e->next_caller; @@ -76,12 +76,12 @@ lto_cgraph_replace_node (struct cgraph_node *node, e->call_stmt_cannot_inline_p = 1; } /* Redirect incomming references. */ - ipa_clone_referring ((symtab_node)prevailing_node, &node->symbol.ref_list); + ipa_clone_referring (prevailing_node, &node->ref_list); ipa_merge_profiles (prevailing_node, node); - lto_free_function_in_decl_state_for_node ((symtab_node)node); + lto_free_function_in_decl_state_for_node (node); - if (node->symbol.decl != prevailing_node->symbol.decl) + if (node->decl != prevailing_node->decl) cgraph_release_function_body (node); /* Finally remove the replaced node. */ @@ -95,15 +95,15 @@ static void lto_varpool_replace_node (struct varpool_node *vnode, struct varpool_node *prevailing_node) { - gcc_assert (!vnode->symbol.definition || prevailing_node->symbol.definition); - gcc_assert (!vnode->symbol.analyzed || prevailing_node->symbol.analyzed); + gcc_assert (!vnode->definition || prevailing_node->definition); + gcc_assert (!vnode->analyzed || prevailing_node->analyzed); - ipa_clone_referring ((symtab_node)prevailing_node, &vnode->symbol.ref_list); + ipa_clone_referring (prevailing_node, &vnode->ref_list); /* Be sure we can garbage collect the initializer. */ - if (DECL_INITIAL (vnode->symbol.decl) - && vnode->symbol.decl != prevailing_node->symbol.decl) - DECL_INITIAL (vnode->symbol.decl) = error_mark_node; + if (DECL_INITIAL (vnode->decl) + && vnode->decl != prevailing_node->decl) + DECL_INITIAL (vnode->decl) = error_mark_node; /* Finally remove the replaced node. */ varpool_remove_node (vnode); } @@ -113,10 +113,10 @@ lto_varpool_replace_node (struct varpool_node *vnode, should be emitted. */ static bool -lto_symtab_merge (symtab_node prevailing, symtab_node entry) +lto_symtab_merge (symtab_node *prevailing, symtab_node *entry) { - tree prevailing_decl = prevailing->symbol.decl; - tree decl = entry->symbol.decl; + tree prevailing_decl = prevailing->decl; + tree decl = entry->decl; tree prevailing_type, type; if (prevailing_decl == decl) @@ -216,17 +216,17 @@ lto_symtab_merge (symtab_node prevailing, symtab_node entry) entry. */ static bool -lto_symtab_resolve_replaceable_p (symtab_node e) +lto_symtab_resolve_replaceable_p (symtab_node *e) { - if (DECL_EXTERNAL (e->symbol.decl) - || DECL_COMDAT (e->symbol.decl) - || DECL_ONE_ONLY (e->symbol.decl) - || DECL_WEAK (e->symbol.decl)) + if (DECL_EXTERNAL (e->decl) + || DECL_COMDAT (e->decl) + || DECL_ONE_ONLY (e->decl) + || DECL_WEAK (e->decl)) return true; - if (TREE_CODE (e->symbol.decl) == VAR_DECL) - return (DECL_COMMON (e->symbol.decl) - || (!flag_no_common && !DECL_INITIAL (e->symbol.decl))); + if (TREE_CODE (e->decl) == VAR_DECL) + return (DECL_COMMON (e->decl) + || (!flag_no_common && !DECL_INITIAL (e->decl))); return false; } @@ -236,9 +236,9 @@ lto_symtab_resolve_replaceable_p (symtab_node e) handle renaming of static later in partitioning). */ static bool -lto_symtab_symbol_p (symtab_node e) +lto_symtab_symbol_p (symtab_node *e) { - if (!TREE_PUBLIC (e->symbol.decl) && !DECL_EXTERNAL (e->symbol.decl)) + if (!TREE_PUBLIC (e->decl) && !DECL_EXTERNAL (e->decl)) return false; return symtab_real_symbol_p (e); } @@ -246,7 +246,7 @@ lto_symtab_symbol_p (symtab_node e) /* Return true if the symtab entry E can be the prevailing one. */ static bool -lto_symtab_resolve_can_prevail_p (symtab_node e) +lto_symtab_resolve_can_prevail_p (symtab_node *e) { if (!lto_symtab_symbol_p (e)) return false; @@ -254,27 +254,27 @@ lto_symtab_resolve_can_prevail_p (symtab_node e) /* The C++ frontend ends up neither setting TREE_STATIC nor DECL_EXTERNAL on virtual methods but only TREE_PUBLIC. So do not reject !TREE_STATIC here but only DECL_EXTERNAL. */ - if (DECL_EXTERNAL (e->symbol.decl)) + if (DECL_EXTERNAL (e->decl)) return false; - return e->symbol.definition; + return e->definition; } /* Resolve the symbol with the candidates in the chain *SLOT and store their resolutions. */ -static symtab_node -lto_symtab_resolve_symbols (symtab_node first) +static symtab_node * +lto_symtab_resolve_symbols (symtab_node *first) { - symtab_node e; - symtab_node prevailing = NULL; + symtab_node *e; + symtab_node *prevailing = NULL; /* Always set e->node so that edges are updated to reflect decl merging. */ - for (e = first; e; e = e->symbol.next_sharing_asm_name) + for (e = first; e; e = e->next_sharing_asm_name) if (lto_symtab_symbol_p (e) - && (e->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY - || e->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY_EXP - || e->symbol.resolution == LDPR_PREVAILING_DEF)) + && (e->resolution == LDPR_PREVAILING_DEF_IRONLY + || e->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP + || e->resolution == LDPR_PREVAILING_DEF)) { prevailing = e; break; @@ -284,19 +284,19 @@ lto_symtab_resolve_symbols (symtab_node first) if (prevailing) { /* Assert it's the only one. */ - for (e = prevailing->symbol.next_sharing_asm_name; e; e = e->symbol.next_sharing_asm_name) + for (e = prevailing->next_sharing_asm_name; e; e = e->next_sharing_asm_name) if (lto_symtab_symbol_p (e) - && (e->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY - || e->symbol.resolution == LDPR_PREVAILING_DEF_IRONLY_EXP - || e->symbol.resolution == LDPR_PREVAILING_DEF)) + && (e->resolution == LDPR_PREVAILING_DEF_IRONLY + || e->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP + || e->resolution == LDPR_PREVAILING_DEF)) fatal_error ("multiple prevailing defs for %qE", - DECL_NAME (prevailing->symbol.decl)); + DECL_NAME (prevailing->decl)); return prevailing; } /* Find the single non-replaceable prevailing symbol and diagnose ODR violations. */ - for (e = first; e; e = e->symbol.next_sharing_asm_name) + for (e = first; e; e = e->next_sharing_asm_name) { if (!lto_symtab_resolve_can_prevail_p (e)) continue; @@ -306,9 +306,9 @@ lto_symtab_resolve_symbols (symtab_node first) { if (prevailing) { - error_at (DECL_SOURCE_LOCATION (e->symbol.decl), - "%qD has already been defined", e->symbol.decl); - inform (DECL_SOURCE_LOCATION (prevailing->symbol.decl), + error_at (DECL_SOURCE_LOCATION (e->decl), + "%qD has already been defined", e->decl); + inform (DECL_SOURCE_LOCATION (prevailing->decl), "previously defined here"); } prevailing = e; @@ -318,13 +318,13 @@ lto_symtab_resolve_symbols (symtab_node first) return prevailing; /* Do a second round choosing one from the replaceable prevailing decls. */ - for (e = first; e; e = e->symbol.next_sharing_asm_name) + for (e = first; e; e = e->next_sharing_asm_name) { if (!lto_symtab_resolve_can_prevail_p (e)) continue; /* Choose the first function that can prevail as prevailing. */ - if (TREE_CODE (e->symbol.decl) == FUNCTION_DECL) + if (TREE_CODE (e->decl) == FUNCTION_DECL) { prevailing = e; break; @@ -332,8 +332,8 @@ lto_symtab_resolve_symbols (symtab_node first) /* From variables that can prevail choose the largest one. */ if (!prevailing - || tree_int_cst_lt (DECL_SIZE (prevailing->symbol.decl), - DECL_SIZE (e->symbol.decl)) + || tree_int_cst_lt (DECL_SIZE (prevailing->decl), + DECL_SIZE (e->decl)) /* When variables are equivalent try to chose one that has useful DECL_INITIAL. This makes sense for keyed vtables that are DECL_EXTERNAL but initialized. In units that do not need them @@ -343,11 +343,11 @@ lto_symtab_resolve_symbols (symtab_node first) We know that the vtable is keyed outside the LTO unit - otherwise the keyed instance would prevail. We still can preserve useful info in the initializer. */ - || (DECL_SIZE (prevailing->symbol.decl) == DECL_SIZE (e->symbol.decl) - && (DECL_INITIAL (e->symbol.decl) - && DECL_INITIAL (e->symbol.decl) != error_mark_node) - && (!DECL_INITIAL (prevailing->symbol.decl) - || DECL_INITIAL (prevailing->symbol.decl) == error_mark_node))) + || (DECL_SIZE (prevailing->decl) == DECL_SIZE (e->decl) + && (DECL_INITIAL (e->decl) + && DECL_INITIAL (e->decl) != error_mark_node) + && (!DECL_INITIAL (prevailing->decl) + || DECL_INITIAL (prevailing->decl) == error_mark_node))) prevailing = e; } @@ -359,26 +359,27 @@ lto_symtab_resolve_symbols (symtab_node first) do not issue further diagnostics.*/ static void -lto_symtab_merge_decls_2 (symtab_node first, bool diagnosed_p) +lto_symtab_merge_decls_2 (symtab_node *first, bool diagnosed_p) { - symtab_node prevailing, e; + symtab_node *prevailing; + symtab_node *e; vec<tree> mismatches = vNULL; unsigned i; tree decl; /* Nothing to do for a single entry. */ prevailing = first; - if (!prevailing->symbol.next_sharing_asm_name) + if (!prevailing->next_sharing_asm_name) return; /* Try to merge each entry with the prevailing one. */ - for (e = prevailing->symbol.next_sharing_asm_name; - e; e = e->symbol.next_sharing_asm_name) - if (TREE_PUBLIC (e->symbol.decl)) + for (e = prevailing->next_sharing_asm_name; + e; e = e->next_sharing_asm_name) + if (TREE_PUBLIC (e->decl)) { if (!lto_symtab_merge (prevailing, e) && !diagnosed_p) - mismatches.safe_push (e->symbol.decl); + mismatches.safe_push (e->decl); } if (mismatches.is_empty ()) return; @@ -386,15 +387,15 @@ lto_symtab_merge_decls_2 (symtab_node first, bool diagnosed_p) /* Diagnose all mismatched re-declarations. */ FOR_EACH_VEC_ELT (mismatches, i, decl) { - if (!types_compatible_p (TREE_TYPE (prevailing->symbol.decl), + if (!types_compatible_p (TREE_TYPE (prevailing->decl), TREE_TYPE (decl))) diagnosed_p |= warning_at (DECL_SOURCE_LOCATION (decl), 0, "type of %qD does not match original " "declaration", decl); - else if ((DECL_USER_ALIGN (prevailing->symbol.decl) + else if ((DECL_USER_ALIGN (prevailing->decl) && DECL_USER_ALIGN (decl)) - && DECL_ALIGN (prevailing->symbol.decl) < DECL_ALIGN (decl)) + && DECL_ALIGN (prevailing->decl) < DECL_ALIGN (decl)) { diagnosed_p |= warning_at (DECL_SOURCE_LOCATION (decl), 0, "alignment of %qD is bigger than " @@ -402,7 +403,7 @@ lto_symtab_merge_decls_2 (symtab_node first, bool diagnosed_p) } } if (diagnosed_p) - inform (DECL_SOURCE_LOCATION (prevailing->symbol.decl), + inform (DECL_SOURCE_LOCATION (prevailing->decl), "previously declared here"); mismatches.release (); @@ -411,17 +412,18 @@ lto_symtab_merge_decls_2 (symtab_node first, bool diagnosed_p) /* Helper to process the decl chain for the symbol table entry *SLOT. */ static void -lto_symtab_merge_decls_1 (symtab_node first) +lto_symtab_merge_decls_1 (symtab_node *first) { - symtab_node e, prevailing; + symtab_node *e; + symtab_node *prevailing; bool diagnosed_p = false; if (cgraph_dump_file) { fprintf (cgraph_dump_file, "Merging nodes for %s. Candidates:\n", symtab_node_asm_name (first)); - for (e = first; e; e = e->symbol.next_sharing_asm_name) - if (TREE_PUBLIC (e->symbol.decl)) + for (e = first; e; e = e->next_sharing_asm_name) + if (TREE_PUBLIC (e->decl)) dump_symtab_node (cgraph_dump_file, e); } @@ -442,21 +444,21 @@ lto_symtab_merge_decls_1 (symtab_node first) This is needed for C++ typeinfos, for example in lto/20081204-1 there are typeifos in both units, just one of them do have size. */ - if (TREE_CODE (prevailing->symbol.decl) == VAR_DECL) + if (TREE_CODE (prevailing->decl) == VAR_DECL) { - for (e = prevailing->symbol.next_sharing_asm_name; - e; e = e->symbol.next_sharing_asm_name) - if (!COMPLETE_TYPE_P (TREE_TYPE (prevailing->symbol.decl)) - && COMPLETE_TYPE_P (TREE_TYPE (e->symbol.decl)) + for (e = prevailing->next_sharing_asm_name; + e; e = e->next_sharing_asm_name) + if (!COMPLETE_TYPE_P (TREE_TYPE (prevailing->decl)) + && COMPLETE_TYPE_P (TREE_TYPE (e->decl)) && lto_symtab_symbol_p (e)) prevailing = e; } /* For variables prefer the non-builtin if one is available. */ - else if (TREE_CODE (prevailing->symbol.decl) == FUNCTION_DECL) + else if (TREE_CODE (prevailing->decl) == FUNCTION_DECL) { - for (e = first; e; e = e->symbol.next_sharing_asm_name) - if (TREE_CODE (e->symbol.decl) == FUNCTION_DECL - && !DECL_BUILT_IN (e->symbol.decl) + for (e = first; e; e = e->next_sharing_asm_name) + if (TREE_CODE (e->decl) == FUNCTION_DECL + && !DECL_BUILT_IN (e->decl) && lto_symtab_symbol_p (e)) { prevailing = e; @@ -468,29 +470,29 @@ lto_symtab_merge_decls_1 (symtab_node first) symtab_prevail_in_asm_name_hash (prevailing); /* Diagnose mismatched objects. */ - for (e = prevailing->symbol.next_sharing_asm_name; - e; e = e->symbol.next_sharing_asm_name) + for (e = prevailing->next_sharing_asm_name; + e; e = e->next_sharing_asm_name) { - if (TREE_CODE (prevailing->symbol.decl) - == TREE_CODE (e->symbol.decl)) + if (TREE_CODE (prevailing->decl) + == TREE_CODE (e->decl)) continue; if (!lto_symtab_symbol_p (e)) continue; - switch (TREE_CODE (prevailing->symbol.decl)) + switch (TREE_CODE (prevailing->decl)) { case VAR_DECL: - gcc_assert (TREE_CODE (e->symbol.decl) == FUNCTION_DECL); - error_at (DECL_SOURCE_LOCATION (e->symbol.decl), + gcc_assert (TREE_CODE (e->decl) == FUNCTION_DECL); + error_at (DECL_SOURCE_LOCATION (e->decl), "variable %qD redeclared as function", - prevailing->symbol.decl); + prevailing->decl); break; case FUNCTION_DECL: - gcc_assert (TREE_CODE (e->symbol.decl) == VAR_DECL); - error_at (DECL_SOURCE_LOCATION (e->symbol.decl), + gcc_assert (TREE_CODE (e->decl) == VAR_DECL); + error_at (DECL_SOURCE_LOCATION (e->decl), "function %qD redeclared as variable", - prevailing->symbol.decl); + prevailing->decl); break; default: @@ -500,7 +502,7 @@ lto_symtab_merge_decls_1 (symtab_node first) diagnosed_p = true; } if (diagnosed_p) - inform (DECL_SOURCE_LOCATION (prevailing->symbol.decl), + inform (DECL_SOURCE_LOCATION (prevailing->decl), "previously declared here"); /* Merge the chain to the single prevailing decl and diagnose @@ -510,7 +512,7 @@ lto_symtab_merge_decls_1 (symtab_node first) if (cgraph_dump_file) { fprintf (cgraph_dump_file, "After resolution:\n"); - for (e = prevailing; e; e = e->symbol.next_sharing_asm_name) + for (e = prevailing; e; e = e->next_sharing_asm_name) dump_symtab_node (cgraph_dump_file, e); } } @@ -520,34 +522,35 @@ lto_symtab_merge_decls_1 (symtab_node first) void lto_symtab_merge_decls (void) { - symtab_node node; + symtab_node *node; /* Populate assembler name hash. */ symtab_initialize_asm_name_hash (); FOR_EACH_SYMBOL (node) - if (!node->symbol.previous_sharing_asm_name - && node->symbol.next_sharing_asm_name) + if (!node->previous_sharing_asm_name + && node->next_sharing_asm_name) lto_symtab_merge_decls_1 (node); } /* Helper to process the decl chain for the symbol table entry *SLOT. */ static void -lto_symtab_merge_symbols_1 (symtab_node prevailing) +lto_symtab_merge_symbols_1 (symtab_node *prevailing) { - symtab_node e, next; + symtab_node *e; + symtab_node *next; /* Replace the cgraph node of each entry with the prevailing one. */ - for (e = prevailing->symbol.next_sharing_asm_name; e; + for (e = prevailing->next_sharing_asm_name; e; e = next) { - next = e->symbol.next_sharing_asm_name; + next = e->next_sharing_asm_name; if (!lto_symtab_symbol_p (e)) continue; cgraph_node *ce = dyn_cast <cgraph_node> (e); - if (ce && !DECL_BUILT_IN (e->symbol.decl)) + if (ce && !DECL_BUILT_IN (e->decl)) lto_cgraph_replace_node (ce, cgraph (prevailing)); if (varpool_node *ve = dyn_cast <varpool_node> (e)) lto_varpool_replace_node (ve, varpool (prevailing)); @@ -562,7 +565,7 @@ lto_symtab_merge_symbols_1 (symtab_node prevailing) void lto_symtab_merge_symbols (void) { - symtab_node node; + symtab_node *node; if (!flag_ltrans) { @@ -574,8 +577,8 @@ lto_symtab_merge_symbols (void) updated to the ohter dupliate. */ FOR_EACH_SYMBOL (node) if (lto_symtab_symbol_p (node) - && node->symbol.next_sharing_asm_name - && !node->symbol.previous_sharing_asm_name) + && node->next_sharing_asm_name + && !node->previous_sharing_asm_name) lto_symtab_merge_symbols_1 (node); /* Resolve weakref aliases whose target are now in the compilation unit. @@ -584,26 +587,26 @@ lto_symtab_merge_symbols (void) { cgraph_node *cnode, *cnode2; varpool_node *vnode; - symtab_node node2; + symtab_node *node2; - if (!node->symbol.analyzed && node->symbol.alias_target) + if (!node->analyzed && node->alias_target) { - symtab_node tgt = symtab_node_for_asm (node->symbol.alias_target); - gcc_assert (node->symbol.weakref); + symtab_node *tgt = symtab_node_for_asm (node->alias_target); + gcc_assert (node->weakref); if (tgt) symtab_resolve_alias (node, tgt); } - node->symbol.aux = NULL; + node->aux = NULL; if (!(cnode = dyn_cast <cgraph_node> (node)) || !cnode->clone_of - || cnode->clone_of->symbol.decl != cnode->symbol.decl) + || cnode->clone_of->decl != cnode->decl) { /* Builtins are not merged via decl merging. It is however possible that tree merging unified the declaration. We do not want duplicate entries in symbol table. */ - if (cnode && DECL_BUILT_IN (node->symbol.decl) - && (cnode2 = cgraph_get_node (node->symbol.decl)) + if (cnode && DECL_BUILT_IN (node->decl) + && (cnode2 = cgraph_get_node (node->decl)) && cnode2 != cnode) lto_cgraph_replace_node (cnode2, cnode); @@ -611,8 +614,8 @@ lto_symtab_merge_symbols (void) symbol name (since it is irrelevant), but we need to unify symbol nodes if tree merging occured. */ if ((vnode = dyn_cast <varpool_node> (node)) - && DECL_HARD_REGISTER (vnode->symbol.decl) - && (node2 = symtab_get_node (vnode->symbol.decl)) + && DECL_HARD_REGISTER (vnode->decl) + && (node2 = symtab_get_node (vnode->decl)) && node2 != node) lto_varpool_replace_node (dyn_cast <varpool_node> (node2), vnode); @@ -620,12 +623,12 @@ lto_symtab_merge_symbols (void) /* Abstract functions may have duplicated cgraph nodes attached; remove them. */ - else if (cnode && DECL_ABSTRACT (cnode->symbol.decl) - && (cnode2 = cgraph_get_node (node->symbol.decl)) + else if (cnode && DECL_ABSTRACT (cnode->decl) + && (cnode2 = cgraph_get_node (node->decl)) && cnode2 != cnode) cgraph_remove_node (cnode2); - symtab_insert_node_to_hashtable ((symtab_node)node); + symtab_insert_node_to_hashtable (node); } } } @@ -636,7 +639,7 @@ lto_symtab_merge_symbols (void) tree lto_symtab_prevailing_decl (tree decl) { - symtab_node ret; + symtab_node *ret; /* Builtins and local symbols are their own prevailing decl. */ if ((!TREE_PUBLIC (decl) && !DECL_EXTERNAL (decl)) || is_builtin_fn (decl)) @@ -659,5 +662,5 @@ lto_symtab_prevailing_decl (tree decl) if (!ret) return decl; - return ret->symbol.decl; + return ret->decl; } diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c index 1168d7b4268..0473565549b 100644 --- a/gcc/lto/lto.c +++ b/gcc/lto/lto.c @@ -171,7 +171,7 @@ has_analyzed_clone_p (struct cgraph_node *node) if (node) while (node != orig) { - if (node->symbol.analyzed) + if (node->analyzed) return true; if (node->clones) node = node->clones; @@ -195,10 +195,10 @@ lto_materialize_function (struct cgraph_node *node) { tree decl; - decl = node->symbol.decl; + decl = node->decl; /* Read in functions with body (analyzed nodes) and also functions that are needed to produce virtual clones. */ - if ((cgraph_function_with_gimple_body_p (node) && node->symbol.analyzed) + if ((cgraph_function_with_gimple_body_p (node) && node->analyzed) || node->used_as_abstract_origin || has_analyzed_clone_p (node)) { @@ -2398,9 +2398,9 @@ cmp_partitions_order (const void *a, const void *b) int ordera = -1, orderb = -1; if (lto_symtab_encoder_size (pa->encoder)) - ordera = lto_symtab_encoder_deref (pa->encoder, 0)->symbol.order; + ordera = lto_symtab_encoder_deref (pa->encoder, 0)->order; if (lto_symtab_encoder_size (pb->encoder)) - orderb = lto_symtab_encoder_deref (pb->encoder, 0)->symbol.order; + orderb = lto_symtab_encoder_deref (pb->encoder, 0)->order; return orderb - ordera; } @@ -2479,14 +2479,14 @@ lto_wpa_write_files (void) for (lsei = lsei_start_in_partition (part->encoder); !lsei_end_p (lsei); lsei_next_in_partition (&lsei)) { - symtab_node node = lsei_node (lsei); + symtab_node *node = lsei_node (lsei); fprintf (cgraph_dump_file, "%s ", symtab_node_asm_name (node)); } fprintf (cgraph_dump_file, "\n Symbols in boundary: "); for (lsei = lsei_start (part->encoder); !lsei_end_p (lsei); lsei_next (&lsei)) { - symtab_node node = lsei_node (lsei); + symtab_node *node = lsei_node (lsei); if (!lto_symtab_encoder_in_partition_p (part->encoder, node)) { fprintf (cgraph_dump_file, "%s ", symtab_node_asm_name (node)); @@ -2750,7 +2750,7 @@ read_cgraph_and_symbols (unsigned nfiles, const char **fnames) int count = 0; struct lto_file_decl_data **decl_data; void **res; - symtab_node snode; + symtab_node *snode; init_cgraph (); @@ -2873,11 +2873,11 @@ read_cgraph_and_symbols (unsigned nfiles, const char **fnames) FOR_EACH_SYMBOL (snode) if (symtab_real_symbol_p (snode) - && snode->symbol.lto_file_data - && snode->symbol.lto_file_data->resolution_map - && (res = pointer_map_contains (snode->symbol.lto_file_data->resolution_map, - snode->symbol.decl))) - snode->symbol.resolution + && snode->lto_file_data + && snode->lto_file_data->resolution_map + && (res = pointer_map_contains (snode->lto_file_data->resolution_map, + snode->decl))) + snode->resolution = (enum ld_plugin_symbol_resolution)(size_t)*res; for (i = 0; all_file_decl_data[i]; i++) if (all_file_decl_data[i]->resolution_map) @@ -2979,7 +2979,7 @@ materialize_cgraph (void) FOR_EACH_FUNCTION (node) { - if (node->symbol.lto_file_data) + if (node->lto_file_data) { lto_materialize_function (node); lto_stats.num_input_cgraph_nodes++; @@ -3074,7 +3074,7 @@ print_lto_report_1 (void) static void do_whole_program_analysis (void) { - symtab_node node; + symtab_node *node; timevar_start (TV_PHASE_OPT_GEN); @@ -3126,7 +3126,7 @@ do_whole_program_analysis (void) /* AUX pointers are used by partitioning code to bookkeep number of partitions symbol is in. This is no longer needed. */ FOR_EACH_SYMBOL (node) - node->symbol.aux = NULL; + node->aux = NULL; lto_stats.num_cgraph_partitions += ltrans_partitions.length (); timevar_pop (TV_WHOPR_PARTITIONING); @@ -3288,7 +3288,7 @@ lto_main (void) /* Record the global variables. */ FOR_EACH_DEFINED_VARIABLE (vnode) - vec_safe_push (lto_global_var_decls, vnode->symbol.decl); + vec_safe_push (lto_global_var_decls, vnode->decl); } } diff --git a/gcc/machmode.def b/gcc/machmode.def index 9ca8b799e97..c425e6ae70f 100644 --- a/gcc/machmode.def +++ b/gcc/machmode.def @@ -121,11 +121,11 @@ along with GCC; see the file COPYING3. If not see to FORMAT. Use in an ARCH-modes.def to reset the format of one of the float modes defined in this file. - PARTIAL_INT_MODE (MODE); + PARTIAL_INT_MODE (MODE, PRECISION, NAME); declares a mode of class PARTIAL_INT with the same size as - MODE (which must be an INT mode). The name of the new mode - is made by prefixing a P to the name MODE. This statement - may grow a PRECISION argument in the future. + MODE (which must be an INT mode) and precision PREC. + Optionally, NAME is the new name of the mode. NAME is the + name of the mode. VECTOR_MODE (CLASS, MODE, COUNT); Declare a vector mode whose component mode is MODE (of class diff --git a/gcc/machmode.h b/gcc/machmode.h index da0923a81a2..71c72525b4a 100644 --- a/gcc/machmode.h +++ b/gcc/machmode.h @@ -174,6 +174,9 @@ extern const unsigned char mode_class[NUM_MACHINE_MODES]; || CLASS == MODE_ACCUM \ || CLASS == MODE_UACCUM) +#define POINTER_BOUNDS_MODE_P(MODE) \ + (GET_MODE_CLASS (MODE) == MODE_POINTER_BOUNDS) + /* Get the size in bytes and bits of an object of mode MODE. */ extern CONST_MODE_SIZE unsigned char mode_size[NUM_MACHINE_MODES]; diff --git a/gcc/mode-classes.def b/gcc/mode-classes.def index 7207ef7712b..a94fd614603 100644 --- a/gcc/mode-classes.def +++ b/gcc/mode-classes.def @@ -22,6 +22,7 @@ along with GCC; see the file COPYING3. If not see DEF_MODE_CLASS (MODE_CC), /* condition code in a register */ \ DEF_MODE_CLASS (MODE_INT), /* integer */ \ DEF_MODE_CLASS (MODE_PARTIAL_INT), /* integer with padding bits */ \ + DEF_MODE_CLASS (MODE_POINTER_BOUNDS), /* bounds */ \ DEF_MODE_CLASS (MODE_FRACT), /* signed fractional number */ \ DEF_MODE_CLASS (MODE_UFRACT), /* unsigned fractional number */ \ DEF_MODE_CLASS (MODE_ACCUM), /* signed accumulator */ \ diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 6c24d3eeaab..ad0c609622b 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -32,6 +32,14 @@ along with GCC; see the file COPYING3. If not see #include "tree-inline.h" #include "langhooks.h" #include "diagnostic-core.h" +#include "gimple-ssa.h" +#include "cgraph.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" +#include "tree-into-ssa.h" +#include "tree-dfa.h" #include "tree-ssa.h" #include "flags.h" #include "function.h" diff --git a/gcc/optabs.c b/gcc/optabs.c index 2bd82b09f2f..d6e49c9272c 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -6620,8 +6620,8 @@ expand_vec_perm (enum machine_mode mode, rtx v0, rtx v1, rtx sel, rtx target) icode = direct_optab_handler (vec_perm_const_optab, qimode); if (icode != CODE_FOR_nothing) { - tmp = expand_vec_perm_1 (icode, gen_lowpart (qimode, target), - gen_lowpart (qimode, v0), + tmp = mode != qimode ? gen_reg_rtx (qimode) : target; + tmp = expand_vec_perm_1 (icode, tmp, gen_lowpart (qimode, v0), gen_lowpart (qimode, v1), sel_qi); if (tmp) return gen_lowpart (mode, tmp); @@ -6670,7 +6670,7 @@ expand_vec_perm (enum machine_mode mode, rtx v0, rtx v1, rtx sel, rtx target) } tmp = gen_rtx_CONST_VECTOR (qimode, vec); sel = gen_lowpart (qimode, sel); - sel = expand_vec_perm (qimode, sel, sel, tmp, NULL); + sel = expand_vec_perm (qimode, gen_reg_rtx (qimode), sel, tmp, NULL); gcc_assert (sel != NULL); /* Add the byte offset to each byte element. */ @@ -6685,8 +6685,8 @@ expand_vec_perm (enum machine_mode mode, rtx v0, rtx v1, rtx sel, rtx target) gcc_assert (sel_qi != NULL); } - tmp = expand_vec_perm_1 (icode, gen_lowpart (qimode, target), - gen_lowpart (qimode, v0), + tmp = mode != qimode ? gen_reg_rtx (qimode) : target; + tmp = expand_vec_perm_1 (icode, tmp, gen_lowpart (qimode, v0), gen_lowpart (qimode, v1), sel_qi); if (tmp) tmp = gen_lowpart (mode, tmp); @@ -7036,8 +7036,7 @@ maybe_emit_atomic_exchange (rtx target, rtx mem, rtx val, enum memmodel model) create_output_operand (&ops[0], target, mode); create_fixed_operand (&ops[1], mem); - /* VAL may have been promoted to a wider mode. Shrink it if so. */ - create_convert_operand_to (&ops[2], val, mode, true); + create_input_operand (&ops[2], val, mode); create_integer_operand (&ops[3], model); if (maybe_expand_insn (icode, 4, ops)) return ops[0].value; @@ -7076,8 +7075,7 @@ maybe_emit_sync_lock_test_and_set (rtx target, rtx mem, rtx val, struct expand_operand ops[3]; create_output_operand (&ops[0], target, mode); create_fixed_operand (&ops[1], mem); - /* VAL may have been promoted to a wider mode. Shrink it if so. */ - create_convert_operand_to (&ops[2], val, mode, true); + create_input_operand (&ops[2], val, mode); if (maybe_expand_insn (icode, 3, ops)) return ops[0].value; } @@ -7119,8 +7117,6 @@ maybe_emit_compare_and_swap_exchange_loop (rtx target, rtx mem, rtx val) { if (!target || !register_operand (target, mode)) target = gen_reg_rtx (mode); - if (GET_MODE (val) != VOIDmode && GET_MODE (val) != mode) - val = convert_modes (mode, GET_MODE (val), val, 1); if (expand_compare_and_swap_loop (mem, target, val, NULL_RTX)) return target; } @@ -7332,8 +7328,8 @@ expand_atomic_compare_and_swap (rtx *ptarget_bool, rtx *ptarget_oval, create_output_operand (&ops[0], target_bool, bool_mode); create_output_operand (&ops[1], target_oval, mode); create_fixed_operand (&ops[2], mem); - create_convert_operand_to (&ops[3], expected, mode, true); - create_convert_operand_to (&ops[4], desired, mode, true); + create_input_operand (&ops[3], expected, mode); + create_input_operand (&ops[4], desired, mode); create_integer_operand (&ops[5], is_weak); create_integer_operand (&ops[6], succ_model); create_integer_operand (&ops[7], fail_model); @@ -7354,8 +7350,8 @@ expand_atomic_compare_and_swap (rtx *ptarget_bool, rtx *ptarget_oval, create_output_operand (&ops[0], target_oval, mode); create_fixed_operand (&ops[1], mem); - create_convert_operand_to (&ops[2], expected, mode, true); - create_convert_operand_to (&ops[3], desired, mode, true); + create_input_operand (&ops[2], expected, mode); + create_input_operand (&ops[3], desired, mode); if (!maybe_expand_insn (icode, 4, ops)) return false; diff --git a/gcc/opts-global.c b/gcc/opts-global.c index 8ce705ea636..af603b956e3 100644 --- a/gcc/opts-global.c +++ b/gcc/opts-global.c @@ -26,6 +26,7 @@ along with GCC; see the file COPYING3. If not see #include "flags.h" #include "ggc.h" #include "tree.h" /* Required by langhooks.h. */ +#include "gimple.h" #include "langhooks.h" #include "tm.h" /* Required by rtl.h. */ #include "rtl.h" @@ -231,40 +232,6 @@ read_cmdline_options (struct gcc_options *opts, struct gcc_options *opts_set, } } -/* Handle -ftree-vectorizer-verbose=ARG by remapping it to -fopt-info. - It remaps the old verbosity values as following: - - REPORT_NONE ==> No dump is output - REPORT_VECTORIZED_LOCATIONS ==> "-optimized" - REPORT_UNVECTORIZED_LOCATIONS ==> "-missed" - - Any higher verbosity levels get mapped to "-all" flags. */ - -static void -dump_remap_tree_vectorizer_verbose (const char *arg) -{ - int value = atoi (arg); - const char *remapped_opt_info = NULL; - - switch (value) - { - case 0: - break; - case 1: - remapped_opt_info = "optimized"; - break; - case 2: - remapped_opt_info = "missed"; - break; - default: - remapped_opt_info = "all"; - break; - } - - if (remapped_opt_info) - opt_info_switch_p (remapped_opt_info); -} - /* Language mask determined at initialization. */ static unsigned int initial_lang_mask; @@ -455,10 +422,6 @@ handle_common_deferred_options (void) stack_limit_rtx = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (opt->arg)); break; - case OPT_ftree_vectorizer_verbose_: - dump_remap_tree_vectorizer_verbose (opt->arg); - break; - default: gcc_unreachable (); } diff --git a/gcc/opts.c b/gcc/opts.c index 728d36d9fff..4db20f038d9 100644 --- a/gcc/opts.c +++ b/gcc/opts.c @@ -473,7 +473,6 @@ static const struct default_options default_options_table[] = { OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_fschedule_insns, NULL, 1 }, { OPT_LEVELS_2_PLUS, OPT_fschedule_insns2, NULL, 1 }, #endif - { OPT_LEVELS_2_PLUS, OPT_fregmove, NULL, 1 }, { OPT_LEVELS_2_PLUS, OPT_fstrict_aliasing, NULL, 1 }, { OPT_LEVELS_2_PLUS, OPT_fstrict_overflow, NULL, 1 }, { OPT_LEVELS_2_PLUS, OPT_freorder_blocks, NULL, 1 }, @@ -1445,6 +1444,7 @@ common_handle_option (struct gcc_options *opts, { "undefined", SANITIZE_UNDEFINED, sizeof "undefined" - 1 }, { "unreachable", SANITIZE_UNREACHABLE, sizeof "unreachable" - 1 }, + { "vla-bound", SANITIZE_VLA, sizeof "vla-bound" - 1 }, { NULL, 0, 0 } }; const char *comma; @@ -1789,12 +1789,6 @@ common_handle_option (struct gcc_options *opts, opts->x_flag_stack_usage_info = value != 0; break; - case OPT_ftree_vectorizer_verbose_: - /* -ftree-vectorizer-verbose is deprecated. It is defined in - -terms of fopt-info=N. */ - /* Deferred. */ - break; - case OPT_g: set_debug_level (NO_DEBUG, DEFAULT_GDB_EXTENSIONS, arg, opts, opts_set, loc); diff --git a/gcc/passes.c b/gcc/passes.c index 95fc6669440..19e5869c14b 100644 --- a/gcc/passes.c +++ b/gcc/passes.c @@ -56,11 +56,17 @@ along with GCC; see the file COPYING3. If not see #include "langhooks.h" #include "cfgloop.h" #include "hosthooks.h" -#include "cgraph.h" #include "opts.h" #include "coverage.h" #include "value-prof.h" #include "tree-inline.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-cfg.h" +#include "tree-ssanames.h" +#include "tree-ssa-loop-manip.h" +#include "tree-into-ssa.h" +#include "tree-dfa.h" #include "tree-ssa.h" #include "tree-pass.h" #include "tree-dump.h" @@ -887,7 +893,7 @@ pass_manager::dump_passes () const create_pass_tab (); FOR_EACH_FUNCTION (n) - if (DECL_STRUCT_FUNCTION (n->symbol.decl)) + if (DECL_STRUCT_FUNCTION (n->decl)) { node = n; break; @@ -896,7 +902,7 @@ pass_manager::dump_passes () const if (!node) return; - push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl)); + push_cfun (DECL_STRUCT_FUNCTION (node->decl)); dump_pass_list (all_lowering_passes, 1); dump_pass_list (all_small_ipa_passes, 1); @@ -1571,10 +1577,10 @@ do_per_function (void (*callback) (void *data), void *data) { struct cgraph_node *node; FOR_EACH_DEFINED_FUNCTION (node) - if (node->symbol.analyzed && gimple_has_body_p (node->symbol.decl) - && (!node->clone_of || node->symbol.decl != node->clone_of->symbol.decl)) + if (node->analyzed && gimple_has_body_p (node->decl) + && (!node->clone_of || node->decl != node->clone_of->decl)) { - push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl)); + push_cfun (DECL_STRUCT_FUNCTION (node->decl)); callback (data); if (!flag_wpa) { @@ -1621,7 +1627,7 @@ do_per_function_toporder (void (*callback) (void *data), void *data) if (cgraph_function_with_gimple_body_p (node)) { cgraph_get_body (node); - push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl)); + push_cfun (DECL_STRUCT_FUNCTION (node->decl)); callback (data); free_dominance_info (CDI_DOMINATORS); free_dominance_info (CDI_POST_DOMINATORS); @@ -2362,19 +2368,19 @@ ipa_write_summaries (void) ordering then matches the one IPA-passes get in their stmt_fixup hooks. */ - push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl)); + push_cfun (DECL_STRUCT_FUNCTION (node->decl)); renumber_gimple_stmt_uids (); pop_cfun (); } - if (node->symbol.definition) - lto_set_symtab_encoder_in_partition (encoder, (symtab_node)node); + if (node->definition) + lto_set_symtab_encoder_in_partition (encoder, node); } FOR_EACH_DEFINED_FUNCTION (node) - if (node->symbol.alias) - lto_set_symtab_encoder_in_partition (encoder, (symtab_node)node); + if (node->alias) + lto_set_symtab_encoder_in_partition (encoder, node); FOR_EACH_DEFINED_VARIABLE (vnode) - lto_set_symtab_encoder_in_partition (encoder, (symtab_node)vnode); + lto_set_symtab_encoder_in_partition (encoder, vnode); ipa_write_summaries_1 (compute_ltrans_boundary (encoder)); @@ -2440,10 +2446,10 @@ ipa_write_optimization_summaries (lto_symtab_encoder_t encoder) For functions newly born at WPA stage we need to initialize the uids here. */ - if (node->symbol.definition - && gimple_has_body_p (node->symbol.decl)) + if (node->definition + && gimple_has_body_p (node->decl)) { - push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl)); + push_cfun (DECL_STRUCT_FUNCTION (node->decl)); renumber_gimple_stmt_uids (); pop_cfun (); } @@ -2685,11 +2691,11 @@ function_called_by_processed_nodes_p (void) e; e = e->next_caller) { - if (e->caller->symbol.decl == current_function_decl) + if (e->caller->decl == current_function_decl) continue; if (!cgraph_function_with_gimple_body_p (e->caller)) continue; - if (TREE_ASM_WRITTEN (e->caller->symbol.decl)) + if (TREE_ASM_WRITTEN (e->caller->decl)) continue; if (!e->caller->process && !e->caller->global.inlined_to) break; diff --git a/gcc/passes.def b/gcc/passes.def index 84eb3f37e57..31ce11381d8 100644 --- a/gcc/passes.def +++ b/gcc/passes.def @@ -34,7 +34,6 @@ along with GCC; see the file COPYING3. If not see NEXT_PASS (pass_warn_unused_result); NEXT_PASS (pass_diagnose_omp_blocks); NEXT_PASS (pass_diagnose_tm_blocks); - NEXT_PASS (pass_mudflap_1); NEXT_PASS (pass_lower_omp); NEXT_PASS (pass_lower_cf); NEXT_PASS (pass_lower_tm); @@ -305,7 +304,6 @@ along with GCC; see the file COPYING3. If not see NEXT_PASS (pass_cleanup_eh); NEXT_PASS (pass_lower_resx); NEXT_PASS (pass_nrv); - NEXT_PASS (pass_mudflap_2); NEXT_PASS (pass_cleanup_cfg_post_optimizing); NEXT_PASS (pass_warn_function_noreturn); @@ -352,7 +350,6 @@ along with GCC; see the file COPYING3. If not see NEXT_PASS (pass_combine); NEXT_PASS (pass_if_after_combine); NEXT_PASS (pass_partition_blocks); - NEXT_PASS (pass_regmove); NEXT_PASS (pass_outof_cfg_layout_mode); NEXT_PASS (pass_split_all_insns); NEXT_PASS (pass_lower_subreg2); diff --git a/gcc/predict.c b/gcc/predict.c index d17b9f21a40..d164500d0c6 100644 --- a/gcc/predict.c +++ b/gcc/predict.c @@ -50,7 +50,14 @@ along with GCC; see the file COPYING3. If not see #include "params.h" #include "target.h" #include "cfgloop.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "cgraph.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssa-loop-niter.h" +#include "tree-ssa-loop.h" #include "ggc.h" #include "tree-pass.h" #include "tree-scalar-evolution.h" diff --git a/gcc/predict.def b/gcc/predict.def index f8dba66e871..2ce135c0ce0 100644 --- a/gcc/predict.def +++ b/gcc/predict.def @@ -117,9 +117,6 @@ DEF_PREDICTOR (PRED_NEGATIVE_RETURN, "negative return", HITRATE (96), 0) /* Branch ending with return; is probably not taken */ DEF_PREDICTOR (PRED_NULL_RETURN, "null return", HITRATE (90), 0) -/* Branches to a mudflap bounds check are extremely unlikely. */ -DEF_PREDICTOR (PRED_MUDFLAP, "mudflap check", PROB_VERY_LIKELY, 0) - /* Branches to compare induction variable to a loop bound is extremely likely. */ DEF_PREDICTOR (PRED_LOOP_IV_COMPARE_GUESS, "guess loop iv compare", diff --git a/gcc/print-tree.c b/gcc/print-tree.c index e38f59abcb5..d6cf945d385 100644 --- a/gcc/print-tree.c +++ b/gcc/print-tree.c @@ -28,7 +28,8 @@ along with GCC; see the file COPYING3. If not see #include "tree-iterator.h" #include "diagnostic.h" #include "gimple-pretty-print.h" /* FIXME */ -#include "tree-ssa.h" +#include "cgraph.h" +#include "tree-cfg.h" #include "tree-dump.h" #include "dumpfile.h" #include "wide-int-print.h" diff --git a/gcc/profile.c b/gcc/profile.c index edc202cf767..7118ac8ac29 100644 --- a/gcc/profile.c +++ b/gcc/profile.c @@ -61,7 +61,8 @@ along with GCC; see the file COPYING3. If not see #include "coverage.h" #include "value-prof.h" #include "tree.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "tree-cfg.h" #include "cfgloop.h" #include "dumpfile.h" diff --git a/gcc/recog.c b/gcc/recog.c index e4f4fadfd86..821ce267ede 100644 --- a/gcc/recog.c +++ b/gcc/recog.c @@ -22,6 +22,7 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "tm.h" +#include "tree.h" #include "rtl-error.h" #include "tm_p.h" #include "insn-config.h" @@ -725,7 +726,7 @@ validate_replace_rtx_1 (rtx *loc, rtx from, rtx to, rtx object, /* Call ourself recursively to perform the replacements. We must not replace inside already replaced expression, otherwise we get infinite recursion for replacements like (reg X)->(subreg (reg X)) - done by regmove, so we must special case shared ASM_OPERANDS. */ + so we must special case shared ASM_OPERANDS. */ if (GET_CODE (x) == PARALLEL) { @@ -761,6 +762,7 @@ validate_replace_rtx_1 (rtx *loc, rtx from, rtx to, rtx object, if (num_changes == prev_changes) return; + /* ??? The regmove is no more, so is this aberration still necessary? */ /* Allow substituted expression to have different mode. This is used by regmove to change mode of pseudo register. */ if (fmt[0] == 'e' && GET_MODE (XEXP (x, 0)) != VOIDmode) @@ -3126,6 +3128,9 @@ peep2_reg_dead_p (int ofs, rtx reg) return 1; } +/* Regno offset to be used in the register search. */ +static int search_ofs; + /* Try to find a hard register of mode MODE, matching the register class in CLASS_STR, which is available at the beginning of insn CURRENT_INSN and remains available until the end of LAST_INSN. LAST_INSN may be NULL_RTX, @@ -3141,7 +3146,6 @@ rtx peep2_find_free_register (int from, int to, const char *class_str, enum machine_mode mode, HARD_REG_SET *reg_set) { - static int search_ofs; enum reg_class cl; HARD_REG_SET live; df_ref *def_rec; @@ -3606,6 +3610,7 @@ peephole2_optimize (void) /* Initialize the regsets we're going to use. */ for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i) peep2_insn_data[i].live_before = BITMAP_ALLOC (®_obstack); + search_ofs = 0; live = BITMAP_ALLOC (®_obstack); FOR_EACH_BB_REVERSE (bb) diff --git a/gcc/reginfo.c b/gcc/reginfo.c index 26318dc503a..db66a095765 100644 --- a/gcc/reginfo.c +++ b/gcc/reginfo.c @@ -30,6 +30,7 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tm.h" #include "hard-reg-set.h" +#include "tree.h" #include "rtl.h" #include "expr.h" #include "tm_p.h" diff --git a/gcc/regmove.c b/gcc/regmove.c deleted file mode 100644 index 85c7ff490c8..00000000000 --- a/gcc/regmove.c +++ /dev/null @@ -1,1401 +0,0 @@ -/* Move registers around to reduce number of move instructions needed. - Copyright (C) 1987-2013 Free Software Foundation, Inc. - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 3, or (at your option) any later -version. - -GCC is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING3. If not see -<http://www.gnu.org/licenses/>. */ - - -/* This module makes some simple RTL code transformations which - improve the subsequent register allocation. */ - -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "tm.h" -#include "rtl.h" -#include "tm_p.h" -#include "insn-config.h" -#include "recog.h" -#include "target.h" -#include "regs.h" -#include "hard-reg-set.h" -#include "flags.h" -#include "function.h" -#include "expr.h" -#include "basic-block.h" -#include "except.h" -#include "diagnostic-core.h" -#include "reload.h" -#include "tree-pass.h" -#include "df.h" -#include "ira.h" - -static int optimize_reg_copy_1 (rtx, rtx, rtx); -static void optimize_reg_copy_2 (rtx, rtx, rtx); -static void optimize_reg_copy_3 (rtx, rtx, rtx); -static void copy_src_to_dest (rtx, rtx, rtx); - -enum match_use -{ - READ, - WRITE, - READWRITE -}; - -struct match { - int with[MAX_RECOG_OPERANDS]; - enum match_use use[MAX_RECOG_OPERANDS]; - int commutative[MAX_RECOG_OPERANDS]; - int early_clobber[MAX_RECOG_OPERANDS]; -}; - -static int find_matches (rtx, struct match *); -static int fixup_match_2 (rtx, rtx, rtx, rtx); - -/* Return nonzero if registers with CLASS1 and CLASS2 can be merged without - causing too much register allocation problems. */ -static int -regclass_compatible_p (reg_class_t class0, reg_class_t class1) -{ - return (class0 == class1 - || (reg_class_subset_p (class0, class1) - && ! targetm.class_likely_spilled_p (class0)) - || (reg_class_subset_p (class1, class0) - && ! targetm.class_likely_spilled_p (class1))); -} - - -#ifdef AUTO_INC_DEC - -/* Find the place in the rtx X where REG is used as a memory address. - Return the MEM rtx that so uses it. - If PLUSCONST is nonzero, search instead for a memory address equivalent to - (plus REG (const_int PLUSCONST)). - - If such an address does not appear, return 0. - If REG appears more than once, or is used other than in such an address, - return (rtx) 1. */ - -static rtx -find_use_as_address (rtx x, rtx reg, HOST_WIDE_INT plusconst) -{ - enum rtx_code code = GET_CODE (x); - const char * const fmt = GET_RTX_FORMAT (code); - int i; - rtx value = 0; - rtx tem; - - if (code == MEM && XEXP (x, 0) == reg && plusconst == 0) - return x; - - if (code == MEM && GET_CODE (XEXP (x, 0)) == PLUS - && XEXP (XEXP (x, 0), 0) == reg - && CONST_INT_P (XEXP (XEXP (x, 0), 1)) - && INTVAL (XEXP (XEXP (x, 0), 1)) == plusconst) - return x; - - if (code == SIGN_EXTRACT || code == ZERO_EXTRACT) - { - /* If REG occurs inside a MEM used in a bit-field reference, - that is unacceptable. */ - if (find_use_as_address (XEXP (x, 0), reg, 0) != 0) - return (rtx) (size_t) 1; - } - - if (x == reg) - return (rtx) (size_t) 1; - - for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) - { - if (fmt[i] == 'e') - { - tem = find_use_as_address (XEXP (x, i), reg, plusconst); - if (value == 0) - value = tem; - else if (tem != 0) - return (rtx) (size_t) 1; - } - else if (fmt[i] == 'E') - { - int j; - for (j = XVECLEN (x, i) - 1; j >= 0; j--) - { - tem = find_use_as_address (XVECEXP (x, i, j), reg, plusconst); - if (value == 0) - value = tem; - else if (tem != 0) - return (rtx) (size_t) 1; - } - } - } - - return value; -} - - -/* INC_INSN is an instruction that adds INCREMENT to REG. - Try to fold INC_INSN as a post/pre in/decrement into INSN. - Iff INC_INSN_SET is nonzero, inc_insn has a destination different from src. - Return nonzero for success. */ -static int -try_auto_increment (rtx insn, rtx inc_insn, rtx inc_insn_set, rtx reg, - HOST_WIDE_INT increment, int pre) -{ - enum rtx_code inc_code; - - rtx pset = single_set (insn); - if (pset) - { - /* Can't use the size of SET_SRC, we might have something like - (sign_extend:SI (mem:QI ... */ - rtx use = find_use_as_address (pset, reg, 0); - if (use != 0 && use != (rtx) (size_t) 1) - { - int size = GET_MODE_SIZE (GET_MODE (use)); - if (0 - || (HAVE_POST_INCREMENT - && pre == 0 && (inc_code = POST_INC, increment == size)) - || (HAVE_PRE_INCREMENT - && pre == 1 && (inc_code = PRE_INC, increment == size)) - || (HAVE_POST_DECREMENT - && pre == 0 && (inc_code = POST_DEC, increment == -size)) - || (HAVE_PRE_DECREMENT - && pre == 1 && (inc_code = PRE_DEC, increment == -size)) - ) - { - if (inc_insn_set) - validate_change - (inc_insn, - &SET_SRC (inc_insn_set), - XEXP (SET_SRC (inc_insn_set), 0), 1); - validate_change (insn, &XEXP (use, 0), - gen_rtx_fmt_e (inc_code, - GET_MODE (XEXP (use, 0)), reg), - 1); - if (apply_change_group ()) - { - /* If there is a REG_DEAD note on this insn, we must - change this not to REG_UNUSED meaning that the register - is set, but the value is dead. Failure to do so will - result in sched1 dying -- when it recomputes lifetime - information, the number of REG_DEAD notes will have - changed. */ - rtx note = find_reg_note (insn, REG_DEAD, reg); - if (note) - PUT_REG_NOTE_KIND (note, REG_UNUSED); - - add_reg_note (insn, REG_INC, reg); - - if (! inc_insn_set) - delete_insn (inc_insn); - return 1; - } - } - } - } - return 0; -} -#endif - - -static int *regno_src_regno; - -/* INSN is a copy from SRC to DEST, both registers, and SRC does not die - in INSN. - - Search forward to see if SRC dies before either it or DEST is modified, - but don't scan past the end of a basic block. If so, we can replace SRC - with DEST and let SRC die in INSN. - - This will reduce the number of registers live in that range and may enable - DEST to be tied to SRC, thus often saving one register in addition to a - register-register copy. */ - -static int -optimize_reg_copy_1 (rtx insn, rtx dest, rtx src) -{ - rtx p, q; - rtx note; - rtx dest_death = 0; - int sregno = REGNO (src); - int dregno = REGNO (dest); - basic_block bb = BLOCK_FOR_INSN (insn); - - /* We don't want to mess with hard regs if register classes are small. */ - if (sregno == dregno - || (targetm.small_register_classes_for_mode_p (GET_MODE (src)) - && (sregno < FIRST_PSEUDO_REGISTER - || dregno < FIRST_PSEUDO_REGISTER)) - /* We don't see all updates to SP if they are in an auto-inc memory - reference, so we must disallow this optimization on them. */ - || sregno == STACK_POINTER_REGNUM || dregno == STACK_POINTER_REGNUM) - return 0; - - for (p = NEXT_INSN (insn); p; p = NEXT_INSN (p)) - { - if (! INSN_P (p)) - continue; - if (BLOCK_FOR_INSN (p) != bb) - break; - - if (reg_set_p (src, p) || reg_set_p (dest, p) - /* If SRC is an asm-declared register, it must not be replaced - in any asm. Unfortunately, the REG_EXPR tree for the asm - variable may be absent in the SRC rtx, so we can't check the - actual register declaration easily (the asm operand will have - it, though). To avoid complicating the test for a rare case, - we just don't perform register replacement for a hard reg - mentioned in an asm. */ - || (sregno < FIRST_PSEUDO_REGISTER - && asm_noperands (PATTERN (p)) >= 0 - && reg_overlap_mentioned_p (src, PATTERN (p))) - /* Don't change hard registers used by a call. */ - || (CALL_P (p) && sregno < FIRST_PSEUDO_REGISTER - && find_reg_fusage (p, USE, src)) - /* Don't change a USE of a register. */ - || (GET_CODE (PATTERN (p)) == USE - && reg_overlap_mentioned_p (src, XEXP (PATTERN (p), 0)))) - break; - - /* See if all of SRC dies in P. This test is slightly more - conservative than it needs to be. */ - if ((note = find_regno_note (p, REG_DEAD, sregno)) != 0 - && GET_MODE (XEXP (note, 0)) == GET_MODE (src)) - { - int failed = 0; - int d_length = 0; - int s_length = 0; - int d_n_calls = 0; - int s_n_calls = 0; - int s_freq_calls = 0; - int d_freq_calls = 0; - - /* We can do the optimization. Scan forward from INSN again, - replacing regs as we go. Set FAILED if a replacement can't - be done. In that case, we can't move the death note for SRC. - This should be rare. */ - - /* Set to stop at next insn. */ - for (q = next_real_insn (insn); - q != next_real_insn (p); - q = next_real_insn (q)) - { - if (reg_overlap_mentioned_p (src, PATTERN (q))) - { - /* If SRC is a hard register, we might miss some - overlapping registers with validate_replace_rtx, - so we would have to undo it. We can't if DEST is - present in the insn, so fail in that combination - of cases. */ - if (sregno < FIRST_PSEUDO_REGISTER - && reg_mentioned_p (dest, PATTERN (q))) - failed = 1; - - /* Attempt to replace all uses. */ - else if (!validate_replace_rtx (src, dest, q)) - failed = 1; - - /* If this succeeded, but some part of the register - is still present, undo the replacement. */ - else if (sregno < FIRST_PSEUDO_REGISTER - && reg_overlap_mentioned_p (src, PATTERN (q))) - { - validate_replace_rtx (dest, src, q); - failed = 1; - } - } - - /* For SREGNO, count the total number of insns scanned. - For DREGNO, count the total number of insns scanned after - passing the death note for DREGNO. */ - if (!DEBUG_INSN_P (p)) - { - s_length++; - if (dest_death) - d_length++; - } - - /* If the insn in which SRC dies is a CALL_INSN, don't count it - as a call that has been crossed. Otherwise, count it. */ - if (q != p && CALL_P (q)) - { - /* Similarly, total calls for SREGNO, total calls beyond - the death note for DREGNO. */ - s_n_calls++; - s_freq_calls += REG_FREQ_FROM_BB (BLOCK_FOR_INSN (q)); - if (dest_death) - { - d_n_calls++; - d_freq_calls += REG_FREQ_FROM_BB (BLOCK_FOR_INSN (q)); - } - } - - /* If DEST dies here, remove the death note and save it for - later. Make sure ALL of DEST dies here; again, this is - overly conservative. */ - if (dest_death == 0 - && (dest_death = find_regno_note (q, REG_DEAD, dregno)) != 0) - { - if (GET_MODE (XEXP (dest_death, 0)) != GET_MODE (dest)) - failed = 1, dest_death = 0; - else - remove_note (q, dest_death); - } - } - - if (! failed) - { - /* These counters need to be updated if and only if we are - going to move the REG_DEAD note. */ - if (sregno >= FIRST_PSEUDO_REGISTER) - { - if (REG_LIVE_LENGTH (sregno) >= 0) - { - REG_LIVE_LENGTH (sregno) -= s_length; - /* REG_LIVE_LENGTH is only an approximation after - combine if sched is not run, so make sure that we - still have a reasonable value. */ - if (REG_LIVE_LENGTH (sregno) < 2) - REG_LIVE_LENGTH (sregno) = 2; - } - - REG_N_CALLS_CROSSED (sregno) -= s_n_calls; - REG_FREQ_CALLS_CROSSED (sregno) -= s_freq_calls; - } - - /* Move death note of SRC from P to INSN. */ - remove_note (p, note); - XEXP (note, 1) = REG_NOTES (insn); - REG_NOTES (insn) = note; - } - - /* DEST is also dead if INSN has a REG_UNUSED note for DEST. */ - if (! dest_death - && (dest_death = find_regno_note (insn, REG_UNUSED, dregno))) - { - PUT_REG_NOTE_KIND (dest_death, REG_DEAD); - remove_note (insn, dest_death); - } - - /* Put death note of DEST on P if we saw it die. */ - if (dest_death) - { - XEXP (dest_death, 1) = REG_NOTES (p); - REG_NOTES (p) = dest_death; - - if (dregno >= FIRST_PSEUDO_REGISTER) - { - /* If and only if we are moving the death note for DREGNO, - then we need to update its counters. */ - if (REG_LIVE_LENGTH (dregno) >= 0) - REG_LIVE_LENGTH (dregno) += d_length; - REG_N_CALLS_CROSSED (dregno) += d_n_calls; - REG_FREQ_CALLS_CROSSED (dregno) += d_freq_calls; - } - } - - return ! failed; - } - - /* If SRC is a hard register which is set or killed in some other - way, we can't do this optimization. */ - else if (sregno < FIRST_PSEUDO_REGISTER - && dead_or_set_p (p, src)) - break; - } - return 0; -} - -/* INSN is a copy of SRC to DEST, in which SRC dies. See if we now have - a sequence of insns that modify DEST followed by an insn that sets - SRC to DEST in which DEST dies, with no prior modification of DEST. - (There is no need to check if the insns in between actually modify - DEST. We should not have cases where DEST is not modified, but - the optimization is safe if no such modification is detected.) - In that case, we can replace all uses of DEST, starting with INSN and - ending with the set of SRC to DEST, with SRC. We do not do this - optimization if a CALL_INSN is crossed unless SRC already crosses a - call or if DEST dies before the copy back to SRC. - - It is assumed that DEST and SRC are pseudos; it is too complicated to do - this for hard registers since the substitutions we may make might fail. */ - -static void -optimize_reg_copy_2 (rtx insn, rtx dest, rtx src) -{ - rtx p, q; - rtx set; - int sregno = REGNO (src); - int dregno = REGNO (dest); - basic_block bb = BLOCK_FOR_INSN (insn); - - for (p = NEXT_INSN (insn); p; p = NEXT_INSN (p)) - { - if (! INSN_P (p)) - continue; - if (BLOCK_FOR_INSN (p) != bb) - break; - - set = single_set (p); - if (set && SET_SRC (set) == dest && SET_DEST (set) == src - && find_reg_note (p, REG_DEAD, dest)) - { - /* We can do the optimization. Scan forward from INSN again, - replacing regs as we go. */ - - /* Set to stop at next insn. */ - for (q = insn; q != NEXT_INSN (p); q = NEXT_INSN (q)) - if (INSN_P (q)) - { - if (reg_mentioned_p (dest, PATTERN (q))) - { - rtx note; - - PATTERN (q) = replace_rtx (PATTERN (q), dest, src); - note = FIND_REG_INC_NOTE (q, dest); - if (note) - { - remove_note (q, note); - add_reg_note (q, REG_INC, src); - } - df_insn_rescan (q); - } - - if (CALL_P (q)) - { - int freq = REG_FREQ_FROM_BB (BLOCK_FOR_INSN (q)); - REG_N_CALLS_CROSSED (dregno)--; - REG_N_CALLS_CROSSED (sregno)++; - REG_FREQ_CALLS_CROSSED (dregno) -= freq; - REG_FREQ_CALLS_CROSSED (sregno) += freq; - } - } - - remove_note (p, find_reg_note (p, REG_DEAD, dest)); - REG_N_DEATHS (dregno)--; - remove_note (insn, find_reg_note (insn, REG_DEAD, src)); - REG_N_DEATHS (sregno)--; - return; - } - - if (reg_set_p (src, p) - || find_reg_note (p, REG_DEAD, dest) - || (CALL_P (p) && REG_N_CALLS_CROSSED (sregno) == 0)) - break; - } -} - -/* INSN is a ZERO_EXTEND or SIGN_EXTEND of SRC to DEST. - Look if SRC dies there, and if it is only set once, by loading - it from memory. If so, try to incorporate the zero/sign extension - into the memory read, change SRC to the mode of DEST, and alter - the remaining accesses to use the appropriate SUBREG. This allows - SRC and DEST to be tied later. */ -static void -optimize_reg_copy_3 (rtx insn, rtx dest, rtx src) -{ - rtx src_reg = XEXP (src, 0); - int src_no = REGNO (src_reg); - int dst_no = REGNO (dest); - rtx p, set, set_insn; - enum machine_mode old_mode; - basic_block bb = BLOCK_FOR_INSN (insn); - - if (src_no < FIRST_PSEUDO_REGISTER - || dst_no < FIRST_PSEUDO_REGISTER - || ! find_reg_note (insn, REG_DEAD, src_reg) - || REG_N_DEATHS (src_no) != 1 - || REG_N_SETS (src_no) != 1) - return; - - for (p = PREV_INSN (insn); p && ! reg_set_p (src_reg, p); p = PREV_INSN (p)) - if (INSN_P (p) && BLOCK_FOR_INSN (p) != bb) - break; - - if (! p || BLOCK_FOR_INSN (p) != bb) - return; - - if (! (set = single_set (p)) - || !MEM_P (SET_SRC (set)) - /* If there's a REG_EQUIV note, this must be an insn that loads an - argument. Prefer keeping the note over doing this optimization. */ - || find_reg_note (p, REG_EQUIV, NULL_RTX) - || SET_DEST (set) != src_reg) - return; - - /* Be conservative: although this optimization is also valid for - volatile memory references, that could cause trouble in later passes. */ - if (MEM_VOLATILE_P (SET_SRC (set))) - return; - - /* Do not use a SUBREG to truncate from one mode to another if truncation - is not a nop. */ - if (GET_MODE_BITSIZE (GET_MODE (src_reg)) <= GET_MODE_BITSIZE (GET_MODE (src)) - && !TRULY_NOOP_TRUNCATION_MODES_P (GET_MODE (src), GET_MODE (src_reg))) - return; - - set_insn = p; - old_mode = GET_MODE (src_reg); - PUT_MODE (src_reg, GET_MODE (src)); - XEXP (src, 0) = SET_SRC (set); - - /* Include this change in the group so that it's easily undone if - one of the changes in the group is invalid. */ - validate_change (p, &SET_SRC (set), src, 1); - - /* Now walk forward making additional replacements. We want to be able - to undo all the changes if a later substitution fails. */ - while (p = NEXT_INSN (p), p != insn) - { - if (! INSN_P (p)) - continue; - - /* Make a tentative change. */ - validate_replace_rtx_group (src_reg, - gen_lowpart_SUBREG (old_mode, src_reg), - p); - } - - validate_replace_rtx_group (src, src_reg, insn); - - /* Now see if all the changes are valid. */ - if (! apply_change_group ()) - { - /* One or more changes were no good. Back out everything. */ - PUT_MODE (src_reg, old_mode); - XEXP (src, 0) = src_reg; - } - else - { - rtx note = find_reg_note (set_insn, REG_EQUAL, NULL_RTX); - if (note) - { - if (rtx_equal_p (XEXP (note, 0), XEXP (src, 0))) - { - XEXP (note, 0) - = gen_rtx_fmt_e (GET_CODE (src), GET_MODE (src), - XEXP (note, 0)); - df_notes_rescan (set_insn); - } - else - remove_note (set_insn, note); - } - } -} - - -/* If we were not able to update the users of src to use dest directly, try - instead moving the value to dest directly before the operation. */ - -static void -copy_src_to_dest (rtx insn, rtx src, rtx dest) -{ - rtx seq; - rtx link; - rtx next; - rtx set; - rtx move_insn; - rtx *p_insn_notes; - rtx *p_move_notes; - int src_regno; - int dest_regno; - - /* A REG_LIVE_LENGTH of -1 indicates the register must not go into - a hard register, e.g. because it crosses as setjmp. See the - comment in regstat.c:regstat_bb_compute_ri. Don't try to apply - any transformations to such regs. */ - - if (REG_P (src) - && REG_LIVE_LENGTH (REGNO (src)) > 0 - && REG_P (dest) - && REG_LIVE_LENGTH (REGNO (dest)) > 0 - && (set = single_set (insn)) != NULL_RTX - && !reg_mentioned_p (dest, SET_SRC (set)) - && GET_MODE (src) == GET_MODE (dest)) - { - int old_num_regs = reg_rtx_no; - - /* Generate the src->dest move. */ - start_sequence (); - emit_move_insn (dest, src); - seq = get_insns (); - end_sequence (); - /* If this sequence uses new registers, we may not use it. */ - if (old_num_regs != reg_rtx_no - || ! validate_replace_rtx (src, dest, insn)) - { - /* We have to restore reg_rtx_no to its old value, lest - recompute_reg_usage will try to compute the usage of the - new regs, yet reg_n_info is not valid for them. */ - reg_rtx_no = old_num_regs; - return; - } - emit_insn_before (seq, insn); - move_insn = PREV_INSN (insn); - p_move_notes = ®_NOTES (move_insn); - p_insn_notes = ®_NOTES (insn); - - /* Move any notes mentioning src to the move instruction. */ - for (link = REG_NOTES (insn); link != NULL_RTX; link = next) - { - next = XEXP (link, 1); - if (GET_CODE (link) == EXPR_LIST && XEXP (link, 0) == src) - { - *p_move_notes = link; - p_move_notes = &XEXP (link, 1); - } - else - { - *p_insn_notes = link; - p_insn_notes = &XEXP (link, 1); - } - } - - *p_move_notes = NULL_RTX; - *p_insn_notes = NULL_RTX; - - /* Update the various register tables. */ - dest_regno = REGNO (dest); - INC_REG_N_SETS (dest_regno, 1); - REG_LIVE_LENGTH (dest_regno)++; - src_regno = REGNO (src); - if (! find_reg_note (move_insn, REG_DEAD, src)) - REG_LIVE_LENGTH (src_regno)++; - } -} - -/* reg_set_in_bb[REGNO] points to basic block iff the register is set - only once in the given block and has REG_EQUAL note. */ - -static basic_block *reg_set_in_bb; - -/* Size of reg_set_in_bb array. */ -static unsigned int max_reg_computed; - - -/* Return whether REG is set in only one location, and is set to a - constant, but is set in a different basic block from INSN (an - instructions which uses REG). In this case REG is equivalent to a - constant, and we don't want to break that equivalence, because that - may increase register pressure and make reload harder. If REG is - set in the same basic block as INSN, we don't worry about it, - because we'll probably need a register anyhow (??? but what if REG - is used in a different basic block as well as this one?). */ - -static bool -reg_is_remote_constant_p (rtx reg, rtx insn) -{ - basic_block bb; - rtx p; - int max; - - if (!reg_set_in_bb) - { - max_reg_computed = max = max_reg_num (); - reg_set_in_bb = XCNEWVEC (basic_block, max); - - FOR_EACH_BB (bb) - FOR_BB_INSNS (bb, p) - { - rtx s; - - if (!INSN_P (p)) - continue; - s = single_set (p); - /* This is the instruction which sets REG. If there is a - REG_EQUAL note, then REG is equivalent to a constant. */ - if (s != 0 - && REG_P (SET_DEST (s)) - && REG_N_SETS (REGNO (SET_DEST (s))) == 1 - && find_reg_note (p, REG_EQUAL, NULL_RTX)) - reg_set_in_bb[REGNO (SET_DEST (s))] = bb; - } - } - - gcc_assert (REGNO (reg) < max_reg_computed); - if (reg_set_in_bb[REGNO (reg)] == NULL) - return false; - return (reg_set_in_bb[REGNO (reg)] != BLOCK_FOR_INSN (insn)); -} - -/* INSN is adding a CONST_INT to a REG. We search backwards looking for - another add immediate instruction with the same source and dest registers, - and if we find one, we change INSN to an increment, and return 1. If - no changes are made, we return 0. - - This changes - (set (reg100) (plus reg1 offset1)) - ... - (set (reg100) (plus reg1 offset2)) - to - (set (reg100) (plus reg1 offset1)) - ... - (set (reg100) (plus reg100 offset2-offset1)) */ - -/* ??? What does this comment mean? */ -/* cse disrupts preincrement / postdecrement sequences when it finds a - hard register as ultimate source, like the frame pointer. */ - -static int -fixup_match_2 (rtx insn, rtx dst, rtx src, rtx offset) -{ - rtx p, dst_death = 0; - int length, num_calls = 0, freq_calls = 0; - basic_block bb = BLOCK_FOR_INSN (insn); - - /* If SRC dies in INSN, we'd have to move the death note. This is - considered to be very unlikely, so we just skip the optimization - in this case. */ - if (find_regno_note (insn, REG_DEAD, REGNO (src))) - return 0; - - /* Scan backward to find the first instruction that sets DST. */ - - for (length = 0, p = PREV_INSN (insn); p; p = PREV_INSN (p)) - { - rtx pset; - - if (! INSN_P (p)) - continue; - if (BLOCK_FOR_INSN (p) != bb) - break; - - if (find_regno_note (p, REG_DEAD, REGNO (dst))) - dst_death = p; - if (! dst_death && !DEBUG_INSN_P (p)) - length++; - - pset = single_set (p); - if (pset && SET_DEST (pset) == dst - && GET_CODE (SET_SRC (pset)) == PLUS - && XEXP (SET_SRC (pset), 0) == src - && CONST_INT_P (XEXP (SET_SRC (pset), 1))) - { - HOST_WIDE_INT newconst - = INTVAL (offset) - INTVAL (XEXP (SET_SRC (pset), 1)); - rtx add = gen_add3_insn (dst, dst, - gen_int_mode (newconst, GET_MODE (dst))); - - if (add && validate_change (insn, &PATTERN (insn), add, 0)) - { - /* Remove the death note for DST from DST_DEATH. */ - if (dst_death) - { - remove_death (REGNO (dst), dst_death); - REG_LIVE_LENGTH (REGNO (dst)) += length; - REG_N_CALLS_CROSSED (REGNO (dst)) += num_calls; - REG_FREQ_CALLS_CROSSED (REGNO (dst)) += freq_calls; - } - - if (dump_file) - fprintf (dump_file, - "Fixed operand of insn %d.\n", - INSN_UID (insn)); - -#ifdef AUTO_INC_DEC - for (p = PREV_INSN (insn); p; p = PREV_INSN (p)) - { - if (! INSN_P (p)) - continue; - if (BLOCK_FOR_INSN (p) != bb) - break; - if (reg_overlap_mentioned_p (dst, PATTERN (p))) - { - if (try_auto_increment (p, insn, 0, dst, newconst, 0)) - return 1; - break; - } - } - for (p = NEXT_INSN (insn); p; p = NEXT_INSN (p)) - { - if (! INSN_P (p)) - continue; - if (BLOCK_FOR_INSN (p) != bb) - break; - if (reg_overlap_mentioned_p (dst, PATTERN (p))) - { - try_auto_increment (p, insn, 0, dst, newconst, 1); - break; - } - } -#endif - return 1; - } - } - - if (reg_set_p (dst, PATTERN (p))) - break; - - /* If we have passed a call instruction, and the - pseudo-reg SRC is not already live across a call, - then don't perform the optimization. */ - /* reg_set_p is overly conservative for CALL_INSNS, thinks that all - hard regs are clobbered. Thus, we only use it for src for - non-call insns. */ - if (CALL_P (p)) - { - if (! dst_death) - { - num_calls++; - freq_calls += REG_FREQ_FROM_BB (BLOCK_FOR_INSN (p)); - } - - if (REG_N_CALLS_CROSSED (REGNO (src)) == 0) - break; - - if ((HARD_REGISTER_P (dst) && call_used_regs [REGNO (dst)]) - || find_reg_fusage (p, CLOBBER, dst)) - break; - } - else if (reg_set_p (src, PATTERN (p))) - break; - } - - return 0; -} - -/* A forward pass. Replace output operands with input operands. */ - -static void -regmove_forward_pass (void) -{ - basic_block bb; - rtx insn; - - if (! flag_expensive_optimizations) - return; - - if (dump_file) - fprintf (dump_file, "Starting forward pass...\n"); - - FOR_EACH_BB (bb) - { - FOR_BB_INSNS (bb, insn) - { - rtx set = single_set (insn); - if (! set) - continue; - - if ((GET_CODE (SET_SRC (set)) == SIGN_EXTEND - || GET_CODE (SET_SRC (set)) == ZERO_EXTEND) - && REG_P (XEXP (SET_SRC (set), 0)) - && REG_P (SET_DEST (set))) - optimize_reg_copy_3 (insn, SET_DEST (set), SET_SRC (set)); - - if (REG_P (SET_SRC (set)) - && REG_P (SET_DEST (set))) - { - /* If this is a register-register copy where SRC is not dead, - see if we can optimize it. If this optimization succeeds, - it will become a copy where SRC is dead. */ - if ((find_reg_note (insn, REG_DEAD, SET_SRC (set)) - || optimize_reg_copy_1 (insn, SET_DEST (set), SET_SRC (set))) - && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER) - { - /* Similarly for a pseudo-pseudo copy when SRC is dead. */ - if (REGNO (SET_SRC (set)) >= FIRST_PSEUDO_REGISTER) - optimize_reg_copy_2 (insn, SET_DEST (set), SET_SRC (set)); - if (regno_src_regno[REGNO (SET_DEST (set))] < 0 - && SET_SRC (set) != SET_DEST (set)) - { - int srcregno = REGNO (SET_SRC (set)); - if (regno_src_regno[srcregno] >= 0) - srcregno = regno_src_regno[srcregno]; - regno_src_regno[REGNO (SET_DEST (set))] = srcregno; - } - } - } - } - } -} - -/* A backward pass. Replace input operands with output operands. */ - -static void -regmove_backward_pass (void) -{ - basic_block bb; - rtx insn, prev; - - if (dump_file) - fprintf (dump_file, "Starting backward pass...\n"); - - FOR_EACH_BB_REVERSE (bb) - { - /* ??? Use the safe iterator because fixup_match_2 can remove - insns via try_auto_increment. */ - FOR_BB_INSNS_REVERSE_SAFE (bb, insn, prev) - { - struct match match; - rtx copy_src, copy_dst; - int op_no, match_no; - int success = 0; - - if (! INSN_P (insn)) - continue; - - if (! find_matches (insn, &match)) - continue; - - /* Now scan through the operands looking for a destination operand - which is supposed to match a source operand. - Then scan backward for an instruction which sets the source - operand. If safe, then replace the source operand with the - dest operand in both instructions. */ - - copy_src = NULL_RTX; - copy_dst = NULL_RTX; - for (op_no = 0; op_no < recog_data.n_operands; op_no++) - { - rtx set, p, src, dst; - rtx src_note, dst_note; - int num_calls = 0, freq_calls = 0; - enum reg_class src_class, dst_class; - int length; - - match_no = match.with[op_no]; - - /* Nothing to do if the two operands aren't supposed to match. */ - if (match_no < 0) - continue; - - dst = recog_data.operand[match_no]; - src = recog_data.operand[op_no]; - - if (!REG_P (src)) - continue; - - if (!REG_P (dst) - || REGNO (dst) < FIRST_PSEUDO_REGISTER - || REG_LIVE_LENGTH (REGNO (dst)) < 0 - || GET_MODE (src) != GET_MODE (dst)) - continue; - - /* If the operands already match, then there is nothing to do. */ - if (operands_match_p (src, dst)) - continue; - - if (match.commutative[op_no] >= 0) - { - rtx comm = recog_data.operand[match.commutative[op_no]]; - if (operands_match_p (comm, dst)) - continue; - } - - set = single_set (insn); - if (! set) - continue; - - /* Note that single_set ignores parts of a parallel set for - which one of the destinations is REG_UNUSED. We can't - handle that here, since we can wind up rewriting things - such that a single register is set twice within a single - parallel. */ - if (reg_set_p (src, insn)) - continue; - - /* match_no/dst must be a write-only operand, and - operand_operand/src must be a read-only operand. */ - if (match.use[op_no] != READ - || match.use[match_no] != WRITE) - continue; - - if (match.early_clobber[match_no] - && count_occurrences (PATTERN (insn), src, 0) > 1) - continue; - - /* Make sure match_no is the destination. */ - if (recog_data.operand[match_no] != SET_DEST (set)) - continue; - - if (REGNO (src) < FIRST_PSEUDO_REGISTER) - { - if (GET_CODE (SET_SRC (set)) == PLUS - && CONST_INT_P (XEXP (SET_SRC (set), 1)) - && XEXP (SET_SRC (set), 0) == src - && fixup_match_2 (insn, dst, src, - XEXP (SET_SRC (set), 1))) - break; - continue; - } - src_class = reg_preferred_class (REGNO (src)); - dst_class = reg_preferred_class (REGNO (dst)); - - if (! (src_note = find_reg_note (insn, REG_DEAD, src))) - { - /* We used to force the copy here like in other cases, but - it produces worse code, as it eliminates no copy - instructions and the copy emitted will be produced by - reload anyway. On patterns with multiple alternatives, - there may be better solution available. - - In particular this change produced slower code for numeric - i387 programs. */ - - continue; - } - - if (! regclass_compatible_p (src_class, dst_class)) - { - if (!copy_src) - { - copy_src = src; - copy_dst = dst; - } - continue; - } - - /* Can not modify an earlier insn to set dst if this insn - uses an old value in the source. */ - if (reg_overlap_mentioned_p (dst, SET_SRC (set))) - { - if (!copy_src) - { - copy_src = src; - copy_dst = dst; - } - continue; - } - - /* If src is set once in a different basic block, - and is set equal to a constant, then do not use - it for this optimization, as this would make it - no longer equivalent to a constant. */ - - if (reg_is_remote_constant_p (src, insn)) - { - if (!copy_src) - { - copy_src = src; - copy_dst = dst; - } - continue; - } - - - if (dump_file) - fprintf (dump_file, - "Could fix operand %d of insn %d matching operand %d.\n", - op_no, INSN_UID (insn), match_no); - - /* Scan backward to find the first instruction that uses - the input operand. If the operand is set here, then - replace it in both instructions with match_no. */ - - for (length = 0, p = PREV_INSN (insn); p; p = PREV_INSN (p)) - { - rtx pset; - - if (! INSN_P (p)) - continue; - if (BLOCK_FOR_INSN (p) != bb) - break; - - if (!DEBUG_INSN_P (p)) - length++; - - /* ??? See if all of SRC is set in P. This test is much - more conservative than it needs to be. */ - pset = single_set (p); - if (pset && SET_DEST (pset) == src) - { - /* We use validate_replace_rtx, in case there - are multiple identical source operands. All - of them have to be changed at the same time: - when validate_replace_rtx() calls - apply_change_group(). */ - validate_change (p, &SET_DEST (pset), dst, 1); - if (validate_replace_rtx (src, dst, insn)) - success = 1; - break; - } - - /* We can't make this change if DST is mentioned at - all in P, since we are going to change its value. - We can't make this change if SRC is read or - partially written in P, since we are going to - eliminate SRC. However, if it's a debug insn, we - can't refrain from making the change, for this - would cause codegen differences, so instead we - invalidate debug expressions that reference DST, - and adjust references to SRC in them so that they - become references to DST. */ - if (reg_mentioned_p (dst, PATTERN (p))) - { - if (DEBUG_INSN_P (p)) - validate_change (p, &INSN_VAR_LOCATION_LOC (p), - gen_rtx_UNKNOWN_VAR_LOC (), 1); - else - break; - } - if (reg_overlap_mentioned_p (src, PATTERN (p))) - { - if (DEBUG_INSN_P (p)) - validate_replace_rtx_group (src, dst, p); - else - break; - } - - /* If we have passed a call instruction, and the - pseudo-reg DST is not already live across a call, - then don't perform the optimization. */ - if (CALL_P (p)) - { - num_calls++; - freq_calls += REG_FREQ_FROM_BB (BLOCK_FOR_INSN (p)); - - if (REG_N_CALLS_CROSSED (REGNO (dst)) == 0) - break; - } - } - - if (success) - { - int dstno, srcno; - - /* Remove the death note for SRC from INSN. */ - remove_note (insn, src_note); - /* Move the death note for SRC to P if it is used - there. */ - if (reg_overlap_mentioned_p (src, PATTERN (p))) - { - XEXP (src_note, 1) = REG_NOTES (p); - REG_NOTES (p) = src_note; - } - /* If there is a REG_DEAD note for DST on P, then remove - it, because DST is now set there. */ - if ((dst_note = find_reg_note (p, REG_DEAD, dst))) - remove_note (p, dst_note); - - dstno = REGNO (dst); - srcno = REGNO (src); - - INC_REG_N_SETS (dstno, 1); - INC_REG_N_SETS (srcno, -1); - - REG_N_CALLS_CROSSED (dstno) += num_calls; - REG_N_CALLS_CROSSED (srcno) -= num_calls; - REG_FREQ_CALLS_CROSSED (dstno) += freq_calls; - REG_FREQ_CALLS_CROSSED (srcno) -= freq_calls; - - REG_LIVE_LENGTH (dstno) += length; - if (REG_LIVE_LENGTH (srcno) >= 0) - { - REG_LIVE_LENGTH (srcno) -= length; - /* REG_LIVE_LENGTH is only an approximation after - combine if sched is not run, so make sure that we - still have a reasonable value. */ - if (REG_LIVE_LENGTH (srcno) < 2) - REG_LIVE_LENGTH (srcno) = 2; - } - - if (dump_file) - fprintf (dump_file, - "Fixed operand %d of insn %d matching operand %d.\n", - op_no, INSN_UID (insn), match_no); - - break; - } - else if (num_changes_pending () > 0) - cancel_changes (0); - } - - /* If we weren't able to replace any of the alternatives, try an - alternative approach of copying the source to the destination. */ - if (!success && copy_src != NULL_RTX) - copy_src_to_dest (insn, copy_src, copy_dst); - } - } -} - -/* Main entry for the register move optimization. */ - -static unsigned int -regmove_optimize (void) -{ - int i; - int nregs = max_reg_num (); - - df_note_add_problem (); - df_analyze (); - - regstat_init_n_sets_and_refs (); - regstat_compute_ri (); - - if (flag_ira_loop_pressure) - ira_set_pseudo_classes (true, dump_file); - - regno_src_regno = XNEWVEC (int, nregs); - for (i = nregs; --i >= 0; ) - regno_src_regno[i] = -1; - - /* A forward pass. Replace output operands with input operands. */ - regmove_forward_pass (); - - /* A backward pass. Replace input operands with output operands. */ - regmove_backward_pass (); - - /* Clean up. */ - free (regno_src_regno); - if (reg_set_in_bb) - { - free (reg_set_in_bb); - reg_set_in_bb = NULL; - } - regstat_free_n_sets_and_refs (); - regstat_free_ri (); - if (flag_ira_loop_pressure) - free_reg_info (); - return 0; -} - -/* Returns nonzero if INSN's pattern has matching constraints for any operand. - Returns 0 if INSN can't be recognized, or if the alternative can't be - determined. - - Initialize the info in MATCHP based on the constraints. */ - -static int -find_matches (rtx insn, struct match *matchp) -{ - int likely_spilled[MAX_RECOG_OPERANDS]; - int op_no; - int any_matches = 0; - - extract_insn (insn); - if (! constrain_operands (0)) - return 0; - - /* Must initialize this before main loop, because the code for - the commutative case may set matches for operands other than - the current one. */ - for (op_no = recog_data.n_operands; --op_no >= 0; ) - matchp->with[op_no] = matchp->commutative[op_no] = -1; - - for (op_no = 0; op_no < recog_data.n_operands; op_no++) - { - const char *p; - char c; - int i = 0; - - p = recog_data.constraints[op_no]; - - likely_spilled[op_no] = 0; - matchp->use[op_no] = READ; - matchp->early_clobber[op_no] = 0; - if (*p == '=') - matchp->use[op_no] = WRITE; - else if (*p == '+') - matchp->use[op_no] = READWRITE; - - for (;*p && i < which_alternative; p++) - if (*p == ',') - i++; - - while ((c = *p) != '\0' && c != ',') - { - switch (c) - { - case '=': - break; - case '+': - break; - case '&': - matchp->early_clobber[op_no] = 1; - break; - case '%': - matchp->commutative[op_no] = op_no + 1; - matchp->commutative[op_no + 1] = op_no; - break; - - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - { - char *end; - unsigned long match_ul = strtoul (p, &end, 10); - int match = match_ul; - - p = end; - - if (match < op_no && likely_spilled[match]) - continue; - matchp->with[op_no] = match; - any_matches = 1; - if (matchp->commutative[op_no] >= 0) - matchp->with[matchp->commutative[op_no]] = match; - } - continue; - - case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'h': - case 'j': case 'k': case 'l': case 'p': case 'q': case 't': case 'u': - case 'v': case 'w': case 'x': case 'y': case 'z': case 'A': case 'B': - case 'C': case 'D': case 'W': case 'Y': case 'Z': - if (targetm.class_likely_spilled_p (REG_CLASS_FROM_CONSTRAINT ((unsigned char) c, p))) - likely_spilled[op_no] = 1; - break; - } - p += CONSTRAINT_LEN (c, p); - } - } - return any_matches; -} - - - -static bool -gate_handle_regmove (void) -{ - return (optimize > 0 && flag_regmove); -} - - -namespace { - -const pass_data pass_data_regmove = -{ - RTL_PASS, /* type */ - "regmove", /* name */ - OPTGROUP_NONE, /* optinfo_flags */ - true, /* has_gate */ - true, /* has_execute */ - TV_REGMOVE, /* tv_id */ - 0, /* properties_required */ - 0, /* properties_provided */ - 0, /* properties_destroyed */ - 0, /* todo_flags_start */ - ( TODO_df_finish | TODO_verify_rtl_sharing ), /* todo_flags_finish */ -}; - -class pass_regmove : public rtl_opt_pass -{ -public: - pass_regmove (gcc::context *ctxt) - : rtl_opt_pass (pass_data_regmove, ctxt) - {} - - /* opt_pass methods: */ - bool gate () { return gate_handle_regmove (); } - unsigned int execute () { return regmove_optimize (); } - -}; // class pass_regmove - -} // anon namespace - -rtl_opt_pass * -make_pass_regmove (gcc::context *ctxt) -{ - return new pass_regmove (ctxt); -} diff --git a/gcc/reload1.c b/gcc/reload1.c index d56c554b10d..204685da316 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -373,6 +373,7 @@ static void init_eliminable_invariants (rtx, bool); static void init_elim_table (void); static void free_reg_equiv (void); static void update_eliminables (HARD_REG_SET *); +static bool update_eliminables_and_spill (void); static void elimination_costs_in_insn (rtx); static void spill_hard_reg (unsigned int, int); static int finish_spills (int); @@ -913,9 +914,6 @@ reload (rtx first, int global) if (caller_save_needed) setup_save_areas (); - /* If we allocated another stack slot, redo elimination bookkeeping. */ - if (something_was_spilled || starting_frame_size != get_frame_size ()) - continue; if (starting_frame_size && crtl->stack_alignment_needed) { /* If we have a stack frame, we must align it now. The @@ -927,8 +925,12 @@ reload (rtx first, int global) STARTING_FRAME_OFFSET not be already aligned to STACK_BOUNDARY. */ assign_stack_local (BLKmode, 0, crtl->stack_alignment_needed); - if (starting_frame_size != get_frame_size ()) - continue; + } + /* If we allocated another stack slot, redo elimination bookkeeping. */ + if (something_was_spilled || starting_frame_size != get_frame_size ()) + { + update_eliminables_and_spill (); + continue; } if (caller_save_needed) @@ -962,30 +964,11 @@ reload (rtx first, int global) else if (!verify_initial_elim_offsets ()) something_changed = 1; - { - HARD_REG_SET to_spill; - CLEAR_HARD_REG_SET (to_spill); - update_eliminables (&to_spill); - AND_COMPL_HARD_REG_SET (used_spill_regs, to_spill); - - for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) - if (TEST_HARD_REG_BIT (to_spill, i)) - { - spill_hard_reg (i, 1); - did_spill = 1; - - /* Regardless of the state of spills, if we previously had - a register that we thought we could eliminate, but now can - not eliminate, we must run another pass. - - Consider pseudos which have an entry in reg_equiv_* which - reference an eliminable register. We must make another pass - to update reg_equiv_* so that we do not substitute in the - old value from when we thought the elimination could be - performed. */ - something_changed = 1; - } - } + if (update_eliminables_and_spill ()) + { + did_spill = 1; + something_changed = 1; + } select_reload_regs (); if (failure) @@ -4031,6 +4014,38 @@ update_eliminables (HARD_REG_SET *pset) SET_HARD_REG_BIT (*pset, HARD_FRAME_POINTER_REGNUM); } +/* Call update_eliminables an spill any registers we can't eliminate anymore. + Return true iff a register was spilled. */ + +static bool +update_eliminables_and_spill (void) +{ + int i; + bool did_spill = false; + HARD_REG_SET to_spill; + CLEAR_HARD_REG_SET (to_spill); + update_eliminables (&to_spill); + AND_COMPL_HARD_REG_SET (used_spill_regs, to_spill); + + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + if (TEST_HARD_REG_BIT (to_spill, i)) + { + spill_hard_reg (i, 1); + did_spill = true; + + /* Regardless of the state of spills, if we previously had + a register that we thought we could eliminate, but now can + not eliminate, we must run another pass. + + Consider pseudos which have an entry in reg_equiv_* which + reference an eliminable register. We must make another pass + to update reg_equiv_* so that we do not substitute in the + old value from when we thought the elimination could be + performed. */ + } + return did_spill; +} + /* Return true if X is used as the target register of an elimination. */ bool @@ -6371,6 +6386,37 @@ replaced_subreg (rtx x) } #endif +/* Compute the offset to pass to subreg_regno_offset, for a pseudo of + mode OUTERMODE that is available in a hard reg of mode INNERMODE. + SUBREG is non-NULL if the pseudo is a subreg whose reg is a pseudo, + otherwise it is NULL. */ + +static int +compute_reload_subreg_offset (enum machine_mode outermode, + rtx subreg, + enum machine_mode innermode) +{ + int outer_offset; + enum machine_mode middlemode; + + if (!subreg) + return subreg_lowpart_offset (outermode, innermode); + + outer_offset = SUBREG_BYTE (subreg); + middlemode = GET_MODE (SUBREG_REG (subreg)); + + /* If SUBREG is paradoxical then return the normal lowpart offset + for OUTERMODE and INNERMODE. Our caller has already checked + that OUTERMODE fits in INNERMODE. */ + if (outer_offset == 0 + && GET_MODE_SIZE (outermode) > GET_MODE_SIZE (middlemode)) + return subreg_lowpart_offset (outermode, innermode); + + /* SUBREG is normal, but may not be lowpart; return OUTER_OFFSET + plus the normal lowpart offset for MIDDLEMODE and INNERMODE. */ + return outer_offset + subreg_lowpart_offset (middlemode, innermode); +} + /* Assign hard reg targets for the pseudo-registers we must reload into hard regs for this insn. Also output the instructions to copy them in and out of the hard regs. @@ -6508,6 +6554,7 @@ choose_reload_regs (struct insn_chain *chain) int byte = 0; int regno = -1; enum machine_mode mode = VOIDmode; + rtx subreg = NULL_RTX; if (rld[r].in == 0) ; @@ -6528,7 +6575,10 @@ choose_reload_regs (struct insn_chain *chain) if (regno < FIRST_PSEUDO_REGISTER) regno = subreg_regno (rld[r].in_reg); else - byte = SUBREG_BYTE (rld[r].in_reg); + { + subreg = rld[r].in_reg; + byte = SUBREG_BYTE (subreg); + } mode = GET_MODE (rld[r].in_reg); } #ifdef AUTO_INC_DEC @@ -6566,6 +6616,9 @@ choose_reload_regs (struct insn_chain *chain) rtx last_reg = reg_last_reload_reg[regno]; i = REGNO (last_reg); + byte = compute_reload_subreg_offset (mode, + subreg, + GET_MODE (last_reg)); i += subreg_regno_offset (i, GET_MODE (last_reg), byte, mode); last_class = REGNO_REG_CLASS (i); diff --git a/gcc/sanitizer.def b/gcc/sanitizer.def index 4c8a0377d8b..c7c780929b8 100644 --- a/gcc/sanitizer.def +++ b/gcc/sanitizer.def @@ -297,3 +297,7 @@ DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE, "__ubsan_handle_builtin_unreachable", BT_FN_VOID_PTR, ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST) +DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_VLA_BOUND_NOT_POSITIVE, + "__ubsan_handle_vla_bound_not_positive", + BT_FN_VOID_PTR_PTR, + ATTR_COLD_NOTHROW_LEAF_LIST) diff --git a/gcc/sese.c b/gcc/sese.c index a78a7967772..1daf4576258 100644 --- a/gcc/sese.c +++ b/gcc/sese.c @@ -25,7 +25,14 @@ along with GCC; see the file COPYING3. If not see #include "hash-table.h" #include "tree.h" #include "tree-pretty-print.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" +#include "tree-ssa-loop.h" +#include "tree-into-ssa.h" #include "cfgloop.h" #include "tree-chrec.h" #include "tree-data-ref.h" diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c index eed3b22e8df..ef5d74087cc 100644 --- a/gcc/stor-layout.c +++ b/gcc/stor-layout.c @@ -383,6 +383,7 @@ int_mode_for_mode (enum machine_mode mode) case MODE_VECTOR_ACCUM: case MODE_VECTOR_UFRACT: case MODE_VECTOR_UACCUM: + case MODE_POINTER_BOUNDS: mode = mode_for_size (GET_MODE_BITSIZE (mode), MODE_INT, 0); break; @@ -606,14 +607,10 @@ layout_decl (tree decl, unsigned int known_align) /* See if we can use an ordinary integer mode for a bit-field. Conditions are: a fixed size that is correct for another mode, - occupying a complete byte or bytes on proper boundary, - and not -fstrict-volatile-bitfields. If the latter is set, - we unfortunately can't check TREE_THIS_VOLATILE, as a cast - may make a volatile object later. */ + occupying a complete byte or bytes on proper boundary. */ if (TYPE_SIZE (type) != 0 && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST - && GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT - && flag_strict_volatile_bitfields <= 0) + && GET_MODE_CLASS (TYPE_MODE (type)) == MODE_INT) { enum machine_mode xmode = mode_for_size_tree (DECL_SIZE (decl), MODE_INT, 1); @@ -2129,6 +2126,14 @@ layout_type (tree type) SET_TYPE_MODE (type, VOIDmode); break; + case POINTER_BOUNDS_TYPE: + SET_TYPE_MODE (type, + mode_for_size (TYPE_PRECISION (type), + MODE_POINTER_BOUNDS, 0)); + TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (TYPE_MODE (type))); + TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (TYPE_MODE (type))); + break; + case OFFSET_TYPE: TYPE_SIZE (type) = bitsize_int (POINTER_SIZE); TYPE_SIZE_UNIT (type) = size_int (POINTER_SIZE / BITS_PER_UNIT); diff --git a/gcc/streamer-hooks.c b/gcc/streamer-hooks.c index 86fc10b75b3..c4f8475ddd8 100644 --- a/gcc/streamer-hooks.c +++ b/gcc/streamer-hooks.c @@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see #include "config.h" #include "system.h" #include "coretypes.h" +#include "input.h" #include "streamer-hooks.h" /* Streamer hooks. */ diff --git a/gcc/streamer-hooks.h b/gcc/streamer-hooks.h index d989cc90452..afbe0132639 100644 --- a/gcc/streamer-hooks.h +++ b/gcc/streamer-hooks.h @@ -23,8 +23,6 @@ along with GCC; see the file COPYING3. If not see #ifndef GCC_STREAMER_HOOKS_H #define GCC_STREAMER_HOOKS_H -#include "tree.h" - /* Forward declarations to avoid including unnecessary headers. */ struct output_block; struct lto_input_block; diff --git a/gcc/symtab.c b/gcc/symtab.c index 62fe166bd61..90924c31803 100644 --- a/gcc/symtab.c +++ b/gcc/symtab.c @@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tm.h" #include "tree.h" +#include "gimple.h" #include "tree-inline.h" #include "langhooks.h" #include "hashtab.h" @@ -48,12 +49,12 @@ const char * const ld_plugin_symbol_resolution_names[]= }; /* Hash table used to convert declarations into nodes. */ -static GTY((param_is (union symtab_node_def))) htab_t symtab_hash; +static GTY((param_is (symtab_node))) htab_t symtab_hash; /* Hash table used to convert assembler names into nodes. */ -static GTY((param_is (union symtab_node_def))) htab_t assembler_name_hash; +static GTY((param_is (symtab_node))) htab_t assembler_name_hash; /* Linked list of symbol table nodes. */ -symtab_node symtab_nodes; +symtab_node *symtab_nodes; /* The order index of the next symtab node to be created. This is used so that we can sort the cgraph nodes in order by when we saw @@ -65,8 +66,8 @@ int symtab_order; static hashval_t hash_node (const void *p) { - const_symtab_node n = (const_symtab_node ) p; - return (hashval_t) DECL_UID (n->symbol.decl); + const symtab_node *n = (const symtab_node *) p; + return (hashval_t) DECL_UID (n->decl); } @@ -75,9 +76,9 @@ hash_node (const void *p) static int eq_node (const void *p1, const void *p2) { - const_symtab_node n1 = (const_symtab_node) p1; - const_symtab_node n2 = (const_symtab_node) p2; - return DECL_UID (n1->symbol.decl) == DECL_UID (n2->symbol.decl); + const symtab_node *n1 = (const symtab_node *) p1; + const symtab_node *n2 = (const symtab_node *) p2; + return DECL_UID (n1->decl) == DECL_UID (n2->decl); } /* Returns a hash code for P. */ @@ -85,8 +86,8 @@ eq_node (const void *p1, const void *p2) static hashval_t hash_node_by_assembler_name (const void *p) { - const_symtab_node n = (const_symtab_node) p; - return (hashval_t) decl_assembler_name_hash (DECL_ASSEMBLER_NAME (n->symbol.decl)); + const symtab_node *n = (const symtab_node *) p; + return (hashval_t) decl_assembler_name_hash (DECL_ASSEMBLER_NAME (n->decl)); } /* Returns nonzero if P1 and P2 are equal. */ @@ -94,43 +95,43 @@ hash_node_by_assembler_name (const void *p) static int eq_assembler_name (const void *p1, const void *p2) { - const_symtab_node n1 = (const_symtab_node) p1; + const symtab_node *n1 = (const symtab_node *) p1; const_tree name = (const_tree)p2; - return (decl_assembler_name_equal (n1->symbol.decl, name)); + return (decl_assembler_name_equal (n1->decl, name)); } /* Insert NODE to assembler name hash. */ static void -insert_to_assembler_name_hash (symtab_node node, bool with_clones) +insert_to_assembler_name_hash (symtab_node *node, bool with_clones) { - if (is_a <varpool_node> (node) && DECL_HARD_REGISTER (node->symbol.decl)) + if (is_a <varpool_node> (node) && DECL_HARD_REGISTER (node->decl)) return; - gcc_checking_assert (!node->symbol.previous_sharing_asm_name - && !node->symbol.next_sharing_asm_name); + gcc_checking_assert (!node->previous_sharing_asm_name + && !node->next_sharing_asm_name); if (assembler_name_hash) { void **aslot; struct cgraph_node *cnode; - tree decl = node->symbol.decl; + tree decl = node->decl; - tree name = DECL_ASSEMBLER_NAME (node->symbol.decl); + tree name = DECL_ASSEMBLER_NAME (node->decl); aslot = htab_find_slot_with_hash (assembler_name_hash, name, decl_assembler_name_hash (name), INSERT); gcc_assert (*aslot != node); - node->symbol.next_sharing_asm_name = (symtab_node)*aslot; + node->next_sharing_asm_name = (symtab_node *)*aslot; if (*aslot != NULL) - ((symtab_node)*aslot)->symbol.previous_sharing_asm_name = node; + ((symtab_node *)*aslot)->previous_sharing_asm_name = node; *aslot = node; /* Update also possible inline clones sharing a decl. */ cnode = dyn_cast <cgraph_node> (node); if (cnode && cnode->clones && with_clones) for (cnode = cnode->clones; cnode; cnode = cnode->next_sibling_clone) - if (cnode->symbol.decl == decl) - insert_to_assembler_name_hash ((symtab_node) cnode, true); + if (cnode->decl == decl) + insert_to_assembler_name_hash (cnode, true); } } @@ -138,50 +139,50 @@ insert_to_assembler_name_hash (symtab_node node, bool with_clones) /* Remove NODE from assembler name hash. */ static void -unlink_from_assembler_name_hash (symtab_node node, bool with_clones) +unlink_from_assembler_name_hash (symtab_node *node, bool with_clones) { if (assembler_name_hash) { struct cgraph_node *cnode; - tree decl = node->symbol.decl; + tree decl = node->decl; - if (node->symbol.next_sharing_asm_name) - node->symbol.next_sharing_asm_name->symbol.previous_sharing_asm_name - = node->symbol.previous_sharing_asm_name; - if (node->symbol.previous_sharing_asm_name) + if (node->next_sharing_asm_name) + node->next_sharing_asm_name->previous_sharing_asm_name + = node->previous_sharing_asm_name; + if (node->previous_sharing_asm_name) { - node->symbol.previous_sharing_asm_name->symbol.next_sharing_asm_name - = node->symbol.next_sharing_asm_name; + node->previous_sharing_asm_name->next_sharing_asm_name + = node->next_sharing_asm_name; } else { - tree name = DECL_ASSEMBLER_NAME (node->symbol.decl); + tree name = DECL_ASSEMBLER_NAME (node->decl); void **slot; slot = htab_find_slot_with_hash (assembler_name_hash, name, decl_assembler_name_hash (name), NO_INSERT); gcc_assert (*slot == node); - if (!node->symbol.next_sharing_asm_name) + if (!node->next_sharing_asm_name) htab_clear_slot (assembler_name_hash, slot); else - *slot = node->symbol.next_sharing_asm_name; + *slot = node->next_sharing_asm_name; } - node->symbol.next_sharing_asm_name = NULL; - node->symbol.previous_sharing_asm_name = NULL; + node->next_sharing_asm_name = NULL; + node->previous_sharing_asm_name = NULL; /* Update also possible inline clones sharing a decl. */ cnode = dyn_cast <cgraph_node> (node); if (cnode && cnode->clones && with_clones) for (cnode = cnode->clones; cnode; cnode = cnode->next_sibling_clone) - if (cnode->symbol.decl == decl) - unlink_from_assembler_name_hash ((symtab_node) cnode, true); + if (cnode->decl == decl) + unlink_from_assembler_name_hash (cnode, true); } } /* Arrange node to be first in its entry of assembler_name_hash. */ void -symtab_prevail_in_asm_name_hash (symtab_node node) +symtab_prevail_in_asm_name_hash (symtab_node *node) { unlink_from_assembler_name_hash (node, false); insert_to_assembler_name_hash (node, false); @@ -192,27 +193,27 @@ symtab_prevail_in_asm_name_hash (symtab_node node) cgraph/varpool node creation routines. */ void -symtab_register_node (symtab_node node) +symtab_register_node (symtab_node *node) { - struct symtab_node_base key; - symtab_node *slot; + struct symtab_node key; + symtab_node **slot; - node->symbol.next = symtab_nodes; - node->symbol.previous = NULL; + node->next = symtab_nodes; + node->previous = NULL; if (symtab_nodes) - symtab_nodes->symbol.previous = node; + symtab_nodes->previous = node; symtab_nodes = node; if (!symtab_hash) symtab_hash = htab_create_ggc (10, hash_node, eq_node, NULL); - key.decl = node->symbol.decl; - slot = (symtab_node *) htab_find_slot (symtab_hash, &key, INSERT); + key.decl = node->decl; + slot = (symtab_node **) htab_find_slot (symtab_hash, &key, INSERT); if (*slot == NULL) *slot = node; - ipa_empty_ref_list (&node->symbol.ref_list); + ipa_empty_ref_list (&node->ref_list); - node->symbol.order = symtab_order++; + node->order = symtab_order++; /* Be sure to do this last; C++ FE might create new nodes via DECL_ASSEMBLER_NAME langhook! */ @@ -223,15 +224,15 @@ symtab_register_node (symtab_node node) of inline clones. */ void -symtab_insert_node_to_hashtable (symtab_node node) +symtab_insert_node_to_hashtable (symtab_node *node) { - struct symtab_node_base key; - symtab_node *slot; + struct symtab_node key; + symtab_node **slot; if (!symtab_hash) symtab_hash = htab_create_ggc (10, hash_node, eq_node, NULL); - key.decl = node->symbol.decl; - slot = (symtab_node *) htab_find_slot (symtab_hash, &key, INSERT); + key.decl = node->decl; + slot = (symtab_node **) htab_find_slot (symtab_hash, &key, INSERT); *slot = node; } @@ -239,34 +240,34 @@ symtab_insert_node_to_hashtable (symtab_node node) cgraph/varpool node removal routines. */ void -symtab_unregister_node (symtab_node node) +symtab_unregister_node (symtab_node *node) { void **slot; - ipa_remove_all_references (&node->symbol.ref_list); - ipa_remove_all_referring (&node->symbol.ref_list); + ipa_remove_all_references (&node->ref_list); + ipa_remove_all_referring (&node->ref_list); - if (node->symbol.same_comdat_group) + if (node->same_comdat_group) { - symtab_node prev; - for (prev = node->symbol.same_comdat_group; - prev->symbol.same_comdat_group != node; - prev = prev->symbol.same_comdat_group) + symtab_node *prev; + for (prev = node->same_comdat_group; + prev->same_comdat_group != node; + prev = prev->same_comdat_group) ; - if (node->symbol.same_comdat_group == prev) - prev->symbol.same_comdat_group = NULL; + if (node->same_comdat_group == prev) + prev->same_comdat_group = NULL; else - prev->symbol.same_comdat_group = node->symbol.same_comdat_group; - node->symbol.same_comdat_group = NULL; + prev->same_comdat_group = node->same_comdat_group; + node->same_comdat_group = NULL; } - if (node->symbol.previous) - node->symbol.previous->symbol.next = node->symbol.next; + if (node->previous) + node->previous->next = node->next; else - symtab_nodes = node->symbol.next; - if (node->symbol.next) - node->symbol.next->symbol.previous = node->symbol.previous; - node->symbol.next = NULL; - node->symbol.previous = NULL; + symtab_nodes = node->next; + if (node->next) + node->next->previous = node->previous; + node->next = NULL; + node->previous = NULL; slot = htab_find_slot (symtab_hash, node, NO_INSERT); @@ -275,26 +276,26 @@ symtab_unregister_node (symtab_node node) gcc_assert ((slot && *slot) || in_lto_p); if (slot && *slot && *slot == node) { - symtab_node replacement_node = NULL; + symtab_node *replacement_node = NULL; if (cgraph_node *cnode = dyn_cast <cgraph_node> (node)) - replacement_node = (symtab_node)cgraph_find_replacement_node (cnode); + replacement_node = cgraph_find_replacement_node (cnode); if (!replacement_node) htab_clear_slot (symtab_hash, slot); else *slot = replacement_node; } - if (!is_a <varpool_node> (node) || !DECL_HARD_REGISTER (node->symbol.decl)) + if (!is_a <varpool_node> (node) || !DECL_HARD_REGISTER (node->decl)) unlink_from_assembler_name_hash (node, false); } /* Return symbol table node associated with DECL, if any, and NULL otherwise. */ -symtab_node +symtab_node * symtab_get_node (const_tree decl) { - symtab_node *slot; - struct symtab_node_base key; + symtab_node **slot; + struct symtab_node key; #ifdef ENABLE_CHECKING /* Check that we are called for sane type of object - functions @@ -310,7 +311,7 @@ symtab_get_node (const_tree decl) key.decl = CONST_CAST2 (tree, const_tree, decl); - slot = (symtab_node *) htab_find_slot (symtab_hash, &key, + slot = (symtab_node **) htab_find_slot (symtab_hash, &key, NO_INSERT); if (slot) @@ -321,7 +322,7 @@ symtab_get_node (const_tree decl) /* Remove symtab NODE from the symbol table. */ void -symtab_remove_node (symtab_node node) +symtab_remove_node (symtab_node *node) { if (cgraph_node *cnode = dyn_cast <cgraph_node> (node)) cgraph_remove_node (cnode); @@ -334,7 +335,7 @@ symtab_remove_node (symtab_node node) void symtab_initialize_asm_name_hash (void) { - symtab_node node; + symtab_node *node; if (!assembler_name_hash) { assembler_name_hash = @@ -348,10 +349,10 @@ symtab_initialize_asm_name_hash (void) /* Return the cgraph node that has ASMNAME for its DECL_ASSEMBLER_NAME. Return NULL if there's no such node. */ -symtab_node +symtab_node * symtab_node_for_asm (const_tree asmname) { - symtab_node node; + symtab_node *node; void **slot; symtab_initialize_asm_name_hash (); @@ -361,7 +362,7 @@ symtab_node_for_asm (const_tree asmname) if (slot) { - node = (symtab_node) *slot; + node = (symtab_node *) *slot; return node; } return NULL; @@ -372,7 +373,7 @@ symtab_node_for_asm (const_tree asmname) void change_decl_assembler_name (tree decl, tree name) { - symtab_node node = NULL; + symtab_node *node = NULL; /* We can have user ASM names on things, like global register variables, that are not in the symbol table. */ @@ -414,41 +415,42 @@ change_decl_assembler_name (tree decl, tree name) /* Add NEW_ to the same comdat group that OLD is in. */ void -symtab_add_to_same_comdat_group (symtab_node new_node, - symtab_node old_node) +symtab_add_to_same_comdat_group (symtab_node *new_node, + symtab_node *old_node) { - gcc_assert (DECL_ONE_ONLY (old_node->symbol.decl)); - gcc_assert (!new_node->symbol.same_comdat_group); + gcc_assert (DECL_ONE_ONLY (old_node->decl)); + gcc_assert (!new_node->same_comdat_group); gcc_assert (new_node != old_node); - DECL_COMDAT_GROUP (new_node->symbol.decl) = DECL_COMDAT_GROUP (old_node->symbol.decl); - new_node->symbol.same_comdat_group = old_node; - if (!old_node->symbol.same_comdat_group) - old_node->symbol.same_comdat_group = new_node; + DECL_COMDAT_GROUP (new_node->decl) = DECL_COMDAT_GROUP (old_node->decl); + new_node->same_comdat_group = old_node; + if (!old_node->same_comdat_group) + old_node->same_comdat_group = new_node; else { - symtab_node n; - for (n = old_node->symbol.same_comdat_group; - n->symbol.same_comdat_group != old_node; - n = n->symbol.same_comdat_group) + symtab_node *n; + for (n = old_node->same_comdat_group; + n->same_comdat_group != old_node; + n = n->same_comdat_group) ; - n->symbol.same_comdat_group = new_node; + n->same_comdat_group = new_node; } } /* Dissolve the same_comdat_group list in which NODE resides. */ void -symtab_dissolve_same_comdat_group_list (symtab_node node) +symtab_dissolve_same_comdat_group_list (symtab_node *node) { - symtab_node n = node, next; + symtab_node *n = node; + symtab_node *next; - if (!node->symbol.same_comdat_group) + if (!node->same_comdat_group) return; do { - next = n->symbol.same_comdat_group; - n->symbol.same_comdat_group = NULL; + next = n->same_comdat_group; + n->same_comdat_group = NULL; n = next; } while (n != node); @@ -459,19 +461,19 @@ symtab_dissolve_same_comdat_group_list (symtab_node node) is unknown go with identifier name. */ const char * -symtab_node_asm_name (symtab_node node) +symtab_node_asm_name (symtab_node *node) { - if (!DECL_ASSEMBLER_NAME_SET_P (node->symbol.decl)) - return lang_hooks.decl_printable_name (node->symbol.decl, 2); - return IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->symbol.decl)); + if (!DECL_ASSEMBLER_NAME_SET_P (node->decl)) + return lang_hooks.decl_printable_name (node->decl, 2); + return IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl)); } /* Return printable identifier name. */ const char * -symtab_node_name (symtab_node node) +symtab_node_name (symtab_node *node) { - return lang_hooks.decl_printable_name (node->symbol.decl, 2); + return lang_hooks.decl_printable_name (node->decl, 2); } static const char * const symtab_type_names[] = {"symbol", "function", "variable"}; @@ -479,7 +481,7 @@ static const char * const symtab_type_names[] = {"symbol", "function", "variable /* Dump base fields of symtab nodes. Not to be used directly. */ void -dump_symtab_base (FILE *f, symtab_node node) +dump_symtab_base (FILE *f, symtab_node *node) { static const char * const visibility_types[] = { "default", "protected", "hidden", "internal" @@ -487,113 +489,113 @@ dump_symtab_base (FILE *f, symtab_node node) fprintf (f, "%s/%i (%s)", symtab_node_asm_name (node), - node->symbol.order, + node->order, symtab_node_name (node)); dump_addr (f, " @", (void *)node); - fprintf (f, "\n Type: %s", symtab_type_names[node->symbol.type]); + fprintf (f, "\n Type: %s", symtab_type_names[node->type]); - if (node->symbol.definition) + if (node->definition) fprintf (f, " definition"); - if (node->symbol.analyzed) + if (node->analyzed) fprintf (f, " analyzed"); - if (node->symbol.alias) + if (node->alias) fprintf (f, " alias"); - if (node->symbol.weakref) + if (node->weakref) fprintf (f, " weakref"); - if (node->symbol.cpp_implicit_alias) + if (node->cpp_implicit_alias) fprintf (f, " cpp_implicit_alias"); - if (node->symbol.alias_target) + if (node->alias_target) fprintf (f, " target:%s", - DECL_P (node->symbol.alias_target) + DECL_P (node->alias_target) ? IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME - (node->symbol.alias_target)) - : IDENTIFIER_POINTER (node->symbol.alias_target)); + (node->alias_target)) + : IDENTIFIER_POINTER (node->alias_target)); fprintf (f, "\n Visibility:"); - if (node->symbol.in_other_partition) + if (node->in_other_partition) fprintf (f, " in_other_partition"); - if (node->symbol.used_from_other_partition) + if (node->used_from_other_partition) fprintf (f, " used_from_other_partition"); - if (node->symbol.force_output) + if (node->force_output) fprintf (f, " force_output"); - if (node->symbol.forced_by_abi) + if (node->forced_by_abi) fprintf (f, " forced_by_abi"); - if (node->symbol.externally_visible) + if (node->externally_visible) fprintf (f, " externally_visible"); - if (node->symbol.resolution != LDPR_UNKNOWN) + if (node->resolution != LDPR_UNKNOWN) fprintf (f, " %s", - ld_plugin_symbol_resolution_names[(int)node->symbol.resolution]); - if (TREE_ASM_WRITTEN (node->symbol.decl)) + ld_plugin_symbol_resolution_names[(int)node->resolution]); + if (TREE_ASM_WRITTEN (node->decl)) fprintf (f, " asm_written"); - if (DECL_EXTERNAL (node->symbol.decl)) + if (DECL_EXTERNAL (node->decl)) fprintf (f, " external"); - if (TREE_PUBLIC (node->symbol.decl)) + if (TREE_PUBLIC (node->decl)) fprintf (f, " public"); - if (DECL_COMMON (node->symbol.decl)) + if (DECL_COMMON (node->decl)) fprintf (f, " common"); - if (DECL_WEAK (node->symbol.decl)) + if (DECL_WEAK (node->decl)) fprintf (f, " weak"); - if (DECL_DLLIMPORT_P (node->symbol.decl)) + if (DECL_DLLIMPORT_P (node->decl)) fprintf (f, " dll_import"); - if (DECL_COMDAT (node->symbol.decl)) + if (DECL_COMDAT (node->decl)) fprintf (f, " comdat"); - if (DECL_COMDAT_GROUP (node->symbol.decl)) + if (DECL_COMDAT_GROUP (node->decl)) fprintf (f, " comdat_group:%s", - IDENTIFIER_POINTER (DECL_COMDAT_GROUP (node->symbol.decl))); - if (DECL_ONE_ONLY (node->symbol.decl)) + IDENTIFIER_POINTER (DECL_COMDAT_GROUP (node->decl))); + if (DECL_ONE_ONLY (node->decl)) fprintf (f, " one_only"); - if (DECL_SECTION_NAME (node->symbol.decl)) + if (DECL_SECTION_NAME (node->decl)) fprintf (f, " section_name:%s", - TREE_STRING_POINTER (DECL_SECTION_NAME (node->symbol.decl))); - if (DECL_VISIBILITY_SPECIFIED (node->symbol.decl)) + TREE_STRING_POINTER (DECL_SECTION_NAME (node->decl))); + if (DECL_VISIBILITY_SPECIFIED (node->decl)) fprintf (f, " visibility_specified"); - if (DECL_VISIBILITY (node->symbol.decl)) + if (DECL_VISIBILITY (node->decl)) fprintf (f, " visibility:%s", - visibility_types [DECL_VISIBILITY (node->symbol.decl)]); - if (DECL_VIRTUAL_P (node->symbol.decl)) + visibility_types [DECL_VISIBILITY (node->decl)]); + if (DECL_VIRTUAL_P (node->decl)) fprintf (f, " virtual"); - if (DECL_ARTIFICIAL (node->symbol.decl)) + if (DECL_ARTIFICIAL (node->decl)) fprintf (f, " artificial"); - if (TREE_CODE (node->symbol.decl) == FUNCTION_DECL) + if (TREE_CODE (node->decl) == FUNCTION_DECL) { - if (DECL_STATIC_CONSTRUCTOR (node->symbol.decl)) + if (DECL_STATIC_CONSTRUCTOR (node->decl)) fprintf (f, " constructor"); - if (DECL_STATIC_DESTRUCTOR (node->symbol.decl)) + if (DECL_STATIC_DESTRUCTOR (node->decl)) fprintf (f, " destructor"); } fprintf (f, "\n"); - if (node->symbol.same_comdat_group) + if (node->same_comdat_group) fprintf (f, " Same comdat group as: %s/%i\n", - symtab_node_asm_name (node->symbol.same_comdat_group), - node->symbol.same_comdat_group->symbol.order); - if (node->symbol.next_sharing_asm_name) + symtab_node_asm_name (node->same_comdat_group), + node->same_comdat_group->order); + if (node->next_sharing_asm_name) fprintf (f, " next sharing asm name: %i\n", - node->symbol.next_sharing_asm_name->symbol.order); - if (node->symbol.previous_sharing_asm_name) + node->next_sharing_asm_name->order); + if (node->previous_sharing_asm_name) fprintf (f, " previous sharing asm name: %i\n", - node->symbol.previous_sharing_asm_name->symbol.order); + node->previous_sharing_asm_name->order); - if (node->symbol.address_taken) + if (node->address_taken) fprintf (f, " Address is taken.\n"); - if (node->symbol.aux) + if (node->aux) { fprintf (f, " Aux:"); - dump_addr (f, " @", (void *)node->symbol.aux); + dump_addr (f, " @", (void *)node->aux); } fprintf (f, " References: "); - ipa_dump_references (f, &node->symbol.ref_list); + ipa_dump_references (f, &node->ref_list); fprintf (f, " Referring: "); - ipa_dump_referring (f, &node->symbol.ref_list); - if (node->symbol.lto_file_data) + ipa_dump_referring (f, &node->ref_list); + if (node->lto_file_data) fprintf (f, " Read from file: %s\n", - node->symbol.lto_file_data->file_name); + node->lto_file_data->file_name); } /* Dump symtab node. */ void -dump_symtab_node (FILE *f, symtab_node node) +dump_symtab_node (FILE *f, symtab_node *node) { if (cgraph_node *cnode = dyn_cast <cgraph_node> (node)) dump_cgraph_node (f, cnode); @@ -606,7 +608,7 @@ dump_symtab_node (FILE *f, symtab_node node) void dump_symtab (FILE *f) { - symtab_node node; + symtab_node *node; fprintf (f, "Symbol table:\n\n"); FOR_EACH_SYMBOL (node) dump_symtab_node (f, node); @@ -615,7 +617,7 @@ dump_symtab (FILE *f) /* Dump symtab node NODE to stderr. */ DEBUG_FUNCTION void -debug_symtab_node (symtab_node node) +debug_symtab_node (symtab_node *node) { dump_symtab_node (stderr, node); } @@ -631,14 +633,14 @@ debug_symtab (void) /* Verify common part of symtab nodes. */ DEBUG_FUNCTION bool -verify_symtab_base (symtab_node node) +verify_symtab_base (symtab_node *node) { bool error_found = false; - symtab_node hashed_node; + symtab_node *hashed_node; if (is_a <cgraph_node> (node)) { - if (TREE_CODE (node->symbol.decl) != FUNCTION_DECL) + if (TREE_CODE (node->decl) != FUNCTION_DECL) { error ("function symbol is not function"); error_found = true; @@ -646,7 +648,7 @@ verify_symtab_base (symtab_node node) } else if (is_a <varpool_node> (node)) { - if (TREE_CODE (node->symbol.decl) != VAR_DECL) + if (TREE_CODE (node->decl) != VAR_DECL) { error ("variable symbol is not variable"); error_found = true; @@ -660,7 +662,7 @@ verify_symtab_base (symtab_node node) if (cgraph_state != CGRAPH_LTO_STREAMING) { - hashed_node = symtab_get_node (node->symbol.decl); + hashed_node = symtab_get_node (node->decl); if (!hashed_node) { error ("node not found in symtab decl hashtable"); @@ -669,8 +671,8 @@ verify_symtab_base (symtab_node node) if (hashed_node != node && (!is_a <cgraph_node> (node) || !dyn_cast <cgraph_node> (node)->clone_of - || dyn_cast <cgraph_node> (node)->clone_of->symbol.decl - != node->symbol.decl)) + || dyn_cast <cgraph_node> (node)->clone_of->decl + != node->decl)) { error ("node differs from symtab decl hashtable"); error_found = true; @@ -678,8 +680,8 @@ verify_symtab_base (symtab_node node) } if (assembler_name_hash) { - hashed_node = symtab_node_for_asm (DECL_ASSEMBLER_NAME (node->symbol.decl)); - if (hashed_node && hashed_node->symbol.previous_sharing_asm_name) + hashed_node = symtab_node_for_asm (DECL_ASSEMBLER_NAME (node->decl)); + if (hashed_node && hashed_node->previous_sharing_asm_name) { error ("assembler name hash list corrupted"); error_found = true; @@ -688,53 +690,53 @@ verify_symtab_base (symtab_node node) { if (hashed_node == node) break; - hashed_node = hashed_node->symbol.next_sharing_asm_name; + hashed_node = hashed_node->next_sharing_asm_name; } if (!hashed_node && !(is_a <varpool_node> (node) - || DECL_HARD_REGISTER (node->symbol.decl))) + || DECL_HARD_REGISTER (node->decl))) { error ("node not found in symtab assembler name hash"); error_found = true; } } - if (node->symbol.previous_sharing_asm_name - && node->symbol.previous_sharing_asm_name->symbol.next_sharing_asm_name != node) + if (node->previous_sharing_asm_name + && node->previous_sharing_asm_name->next_sharing_asm_name != node) { error ("double linked list of assembler names corrupted"); error_found = true; } - if (node->symbol.analyzed && !node->symbol.definition) + if (node->analyzed && !node->definition) { error ("node is analyzed byt it is not a definition"); error_found = true; } - if (node->symbol.cpp_implicit_alias && !node->symbol.alias) + if (node->cpp_implicit_alias && !node->alias) { error ("node is alias but not implicit alias"); error_found = true; } - if (node->symbol.alias && !node->symbol.definition - && !node->symbol.weakref) + if (node->alias && !node->definition + && !node->weakref) { error ("node is alias but not definition"); error_found = true; } - if (node->symbol.weakref && !node->symbol.alias) + if (node->weakref && !node->alias) { error ("node is weakref but not an alias"); error_found = true; } - if (node->symbol.same_comdat_group) + if (node->same_comdat_group) { - symtab_node n = node->symbol.same_comdat_group; + symtab_node *n = node->same_comdat_group; - if (!DECL_ONE_ONLY (n->symbol.decl)) + if (!DECL_ONE_ONLY (n->decl)) { error ("non-DECL_ONE_ONLY node in a same_comdat_group list"); error_found = true; } - if (n->symbol.type != node->symbol.type) + if (n->type != node->type) { error ("mixing different types of symbol in same comdat groups is not supported"); error_found = true; @@ -746,13 +748,13 @@ verify_symtab_base (symtab_node node) } do { - if (!n->symbol.same_comdat_group) + if (!n->same_comdat_group) { error ("same_comdat_group is not a circular list"); error_found = true; break; } - n = n->symbol.same_comdat_group; + n = n->same_comdat_group; } while (n != node); } @@ -762,7 +764,7 @@ verify_symtab_base (symtab_node node) /* Verify consistency of NODE. */ DEBUG_FUNCTION void -verify_symtab_node (symtab_node node) +verify_symtab_node (symtab_node *node) { if (seen_error ()) return; @@ -784,7 +786,7 @@ verify_symtab_node (symtab_node node) DEBUG_FUNCTION void verify_symtab (void) { - symtab_node node; + symtab_node *node; FOR_EACH_SYMBOL (node) verify_symtab_node (node); } @@ -805,11 +807,11 @@ resolution_used_from_other_file_p (enum ld_plugin_symbol_resolution resolution) Known only when doing LTO via linker plugin. */ bool -symtab_used_from_object_file_p (symtab_node node) +symtab_used_from_object_file_p (symtab_node *node) { - if (!TREE_PUBLIC (node->symbol.decl) || DECL_EXTERNAL (node->symbol.decl)) + if (!TREE_PUBLIC (node->decl) || DECL_EXTERNAL (node->decl)) return false; - if (resolution_used_from_other_file_p (node->symbol.resolution)) + if (resolution_used_from_other_file_p (node->resolution)) return true; return false; } @@ -857,7 +859,7 @@ symtab_make_decl_local (tree decl) /* Return availability of NODE. */ enum availability -symtab_node_availability (symtab_node node) +symtab_node_availability (symtab_node *node) { if (is_a <cgraph_node> (node)) return cgraph_function_body_availability (cgraph (node)); @@ -869,12 +871,12 @@ symtab_node_availability (symtab_node node) If NODE is not an alias, return NODE. When AVAILABILITY is non-NULL, get minimal availability in the chain. */ -symtab_node -symtab_alias_ultimate_target (symtab_node node, enum availability *availability) +symtab_node * +symtab_alias_ultimate_target (symtab_node *node, enum availability *availability) { bool weakref_p = false; - if (!node->symbol.alias) + if (!node->alias) { if (availability) *availability = symtab_node_availability (node); @@ -897,7 +899,7 @@ symtab_alias_ultimate_target (symtab_node node, enum availability *availability) if (availability) { - weakref_p = node->symbol.weakref; + weakref_p = node->weakref; if (!weakref_p) *availability = symtab_node_availability (node); else @@ -905,13 +907,13 @@ symtab_alias_ultimate_target (symtab_node node, enum availability *availability) } while (node) { - if (node->symbol.alias && node->symbol.analyzed) + if (node->alias && node->analyzed) node = symtab_alias_target (node); else { if (!availability) ; - else if (node->symbol.analyzed) + else if (node->analyzed) { if (weakref_p) { @@ -929,7 +931,7 @@ symtab_alias_ultimate_target (symtab_node node, enum availability *availability) enum availability a = symtab_node_availability (node); if (a < *availability) *availability = a; - weakref_p = node->symbol.weakref; + weakref_p = node->weakref; } } if (availability) @@ -945,35 +947,35 @@ symtab_alias_ultimate_target (symtab_node node, enum availability *availability) copy the visibility from the target to get things right. */ void -fixup_same_cpp_alias_visibility (symtab_node node, symtab_node target) +fixup_same_cpp_alias_visibility (symtab_node *node, symtab_node *target) { if (is_a <cgraph_node> (node)) { - DECL_DECLARED_INLINE_P (node->symbol.decl) - = DECL_DECLARED_INLINE_P (target->symbol.decl); - DECL_DISREGARD_INLINE_LIMITS (node->symbol.decl) - = DECL_DISREGARD_INLINE_LIMITS (target->symbol.decl); + DECL_DECLARED_INLINE_P (node->decl) + = DECL_DECLARED_INLINE_P (target->decl); + DECL_DISREGARD_INLINE_LIMITS (node->decl) + = DECL_DISREGARD_INLINE_LIMITS (target->decl); } /* FIXME: It is not really clear why those flags should not be copied for functions, too. */ else { - DECL_WEAK (node->symbol.decl) = DECL_WEAK (target->symbol.decl); - DECL_EXTERNAL (node->symbol.decl) = DECL_EXTERNAL (target->symbol.decl); - DECL_VISIBILITY (node->symbol.decl) = DECL_VISIBILITY (target->symbol.decl); + DECL_WEAK (node->decl) = DECL_WEAK (target->decl); + DECL_EXTERNAL (node->decl) = DECL_EXTERNAL (target->decl); + DECL_VISIBILITY (node->decl) = DECL_VISIBILITY (target->decl); } - DECL_VIRTUAL_P (node->symbol.decl) = DECL_VIRTUAL_P (target->symbol.decl); - if (TREE_PUBLIC (node->symbol.decl)) + DECL_VIRTUAL_P (node->decl) = DECL_VIRTUAL_P (target->decl); + if (TREE_PUBLIC (node->decl)) { - DECL_EXTERNAL (node->symbol.decl) = DECL_EXTERNAL (target->symbol.decl); - DECL_COMDAT (node->symbol.decl) = DECL_COMDAT (target->symbol.decl); - DECL_COMDAT_GROUP (node->symbol.decl) - = DECL_COMDAT_GROUP (target->symbol.decl); - if (DECL_ONE_ONLY (target->symbol.decl) - && !node->symbol.same_comdat_group) - symtab_add_to_same_comdat_group ((symtab_node)node, (symtab_node)target); + DECL_EXTERNAL (node->decl) = DECL_EXTERNAL (target->decl); + DECL_COMDAT (node->decl) = DECL_COMDAT (target->decl); + DECL_COMDAT_GROUP (node->decl) + = DECL_COMDAT_GROUP (target->decl); + if (DECL_ONE_ONLY (target->decl) + && !node->same_comdat_group) + symtab_add_to_same_comdat_group (node, target); } - node->symbol.externally_visible = target->symbol.externally_visible; + node->externally_visible = target->externally_visible; } /* Add reference recording that NODE is alias of TARGET. @@ -981,46 +983,46 @@ fixup_same_cpp_alias_visibility (symtab_node node, symtab_node target) it returns false. */ bool -symtab_resolve_alias (symtab_node node, symtab_node target) +symtab_resolve_alias (symtab_node *node, symtab_node *target) { - symtab_node n; + symtab_node *n; - gcc_assert (!node->symbol.analyzed - && !vec_safe_length (node->symbol.ref_list.references)); + gcc_assert (!node->analyzed + && !vec_safe_length (node->ref_list.references)); /* Never let cycles to creep into the symbol table alias references; those will make alias walkers to be infinite. */ - for (n = target; n && n->symbol.alias; - n = n->symbol.analyzed ? symtab_alias_target (n) : NULL) + for (n = target; n && n->alias; + n = n->analyzed ? symtab_alias_target (n) : NULL) if (n == node) { if (is_a <cgraph_node> (node)) - error ("function %q+D part of alias cycle", node->symbol.decl); + error ("function %q+D part of alias cycle", node->decl); else if (is_a <varpool_node> (node)) - error ("variable %q+D part of alias cycle", node->symbol.decl); + error ("variable %q+D part of alias cycle", node->decl); else gcc_unreachable (); - node->symbol.alias = false; + node->alias = false; return false; } /* "analyze" the node - i.e. mark the reference. */ - node->symbol.definition = true; - node->symbol.alias = true; - node->symbol.analyzed = true; + node->definition = true; + node->alias = true; + node->analyzed = true; ipa_record_reference (node, target, IPA_REF_ALIAS, NULL); /* Alias targets become reudndant after alias is resolved into an reference. We do not want to keep it around or we would have to mind updating them when renaming symbols. */ - node->symbol.alias_target = NULL; + node->alias_target = NULL; - if (node->symbol.cpp_implicit_alias && cgraph_state >= CGRAPH_STATE_CONSTRUCTION) + if (node->cpp_implicit_alias && cgraph_state >= CGRAPH_STATE_CONSTRUCTION) fixup_same_cpp_alias_visibility (node, target); /* If alias has address taken, so does the target. */ - if (node->symbol.address_taken) - symtab_alias_ultimate_target (target, NULL)->symbol.address_taken = true; + if (node->address_taken) + symtab_alias_ultimate_target (target, NULL)->address_taken = true; return true; } @@ -1029,8 +1031,8 @@ symtab_resolve_alias (symtab_node node, symtab_node target) skipped. */ bool -symtab_for_node_and_aliases (symtab_node node, - bool (*callback) (symtab_node, void *), +symtab_for_node_and_aliases (symtab_node *node, + bool (*callback) (symtab_node *, void *), void *data, bool include_overwritable) { @@ -1039,10 +1041,10 @@ symtab_for_node_and_aliases (symtab_node node, if (callback (node, data)) return true; - for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list, i, ref); i++) + for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list, i, ref); i++) if (ref->use == IPA_REF_ALIAS) { - symtab_node alias = ref->referring; + symtab_node *alias = ref->referring; if (include_overwritable || symtab_node_availability (alias) > AVAIL_OVERWRITABLE) if (symtab_for_node_and_aliases (alias, callback, data, @@ -1055,11 +1057,11 @@ symtab_for_node_and_aliases (symtab_node node, /* Worker searching nonoverwritable alias. */ static bool -symtab_nonoverwritable_alias_1 (symtab_node node, void *data) +symtab_nonoverwritable_alias_1 (symtab_node *node, void *data) { - if (decl_binds_to_current_def_p (node->symbol.decl)) + if (decl_binds_to_current_def_p (node->decl)) { - *(symtab_node *)data = node; + *(symtab_node **)data = node; return true; } return false; @@ -1069,16 +1071,16 @@ symtab_nonoverwritable_alias_1 (symtab_node node, void *data) definition, return NODE. Otherwise look for alias with such property and if none exists, introduce new one. */ -symtab_node -symtab_nonoverwritable_alias (symtab_node node) +symtab_node * +symtab_nonoverwritable_alias (symtab_node *node) { tree new_decl; - symtab_node new_node = NULL; + symtab_node *new_node = NULL; /* First try to look up existing alias or base object (if that is already non-overwritable). */ node = symtab_alias_ultimate_target (node, NULL); - gcc_assert (!node->symbol.alias && !node->symbol.weakref); + gcc_assert (!node->alias && !node->weakref); symtab_for_node_and_aliases (node, symtab_nonoverwritable_alias_1, (void *)&new_node, true); if (new_node) @@ -1089,8 +1091,8 @@ symtab_nonoverwritable_alias (symtab_node node) #endif /* Otherwise create a new one. */ - new_decl = copy_node (node->symbol.decl); - DECL_NAME (new_decl) = clone_function_name (node->symbol.decl, "localalias"); + new_decl = copy_node (node->decl); + DECL_NAME (new_decl) = clone_function_name (node->decl, "localalias"); if (TREE_CODE (new_decl) == FUNCTION_DECL) DECL_STRUCT_FUNCTION (new_decl) = NULL; DECL_INITIAL (new_decl) = NULL; @@ -1099,7 +1101,7 @@ symtab_nonoverwritable_alias (symtab_node node) /* Update the properties. */ DECL_EXTERNAL (new_decl) = 0; - if (DECL_ONE_ONLY (node->symbol.decl)) + if (DECL_ONE_ONLY (node->decl)) DECL_SECTION_NAME (new_decl) = NULL; DECL_COMDAT_GROUP (new_decl) = 0; TREE_PUBLIC (new_decl) = 0; @@ -1110,12 +1112,12 @@ symtab_nonoverwritable_alias (symtab_node node) { DECL_STATIC_CONSTRUCTOR (new_decl) = 0; DECL_STATIC_DESTRUCTOR (new_decl) = 0; - new_node = (symtab_node) cgraph_create_function_alias - (new_decl, node->symbol.decl); + new_node = cgraph_create_function_alias + (new_decl, node->decl); } else - new_node = (symtab_node) varpool_create_variable_alias (new_decl, - node->symbol.decl); + new_node = varpool_create_variable_alias (new_decl, + node->decl); symtab_resolve_alias (new_node, node); gcc_assert (decl_binds_to_current_def_p (new_decl)); return new_node; @@ -1124,14 +1126,15 @@ symtab_nonoverwritable_alias (symtab_node node) /* Return true if A and B represents semantically equivalent symbols. */ bool -symtab_semantically_equivalent_p (symtab_node a, - symtab_node b) +symtab_semantically_equivalent_p (symtab_node *a, + symtab_node *b) { enum availability avail; - symtab_node ba, bb; + symtab_node *ba; + symtab_node *bb; /* Equivalent functions are equivalent. */ - if (a->symbol.decl == b->symbol.decl) + if (a->decl == b->decl) return true; /* If symbol is not overwritable by different implementation, diff --git a/gcc/target-globals.c b/gcc/target-globals.c index 65ccb8af5e6..9d223fcbed0 100644 --- a/gcc/target-globals.c +++ b/gcc/target-globals.c @@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see #include "tm.h" #include "insn-config.h" #include "machmode.h" +#include "tree.h" #include "ggc.h" #include "toplev.h" #include "target-globals.h" diff --git a/gcc/target.def b/gcc/target.def index 912632f04f6..3bbbbd30260 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -1935,6 +1935,18 @@ DEFHOOK_UNDOC bool, (void), targhook_float_words_big_endian) +DEFHOOK +(float_exceptions_rounding_supported_p, + "Returns true if the target supports IEEE 754 floating-point exceptions\ + and rounding modes, false otherwise. This is intended to relate to the\ + @code{float} and @code{double} types, but not necessarily @code{long double}.\ + By default, returns true if the @code{adddf3} instruction pattern is\ + available and false otherwise, on the assumption that hardware floating\ + point supports exceptions and rounding modes but software floating point\ + does not.", + bool, (void), + default_float_exceptions_rounding_supported_p) + /* True if the target supports decimal floating point. */ DEFHOOK (decimal_float_supported_p, @@ -2023,6 +2035,104 @@ built-in function.", (tree exp, rtx target, rtx subtarget, enum machine_mode mode, int ignore), default_expand_builtin) +DEFHOOK +(builtin_chkp_function, + "This hook allows target to redefine built-in functions used by\n\ +Pointer Bounds Checker for code instrumentation. Hook should return\n\ +fndecl of function implementing generic builtin whose code is\n\ +passed in @var{fcode}. Currently following built-in functions are\n\ +obtained using this hook:\n\ +@deftypefn {Built-in Function} bnd __chkp_bndmk (const void *@var{lb}, size_t @var{size})\n\ +Function code - BUILT_IN_CHKP_BNDMK. This built-in function is used\n\ +by Pointer Bounds Checker to create bound values. @var{lb} holds low\n\ +bound of the resulting bounds. @var{size} holds size of created bounds.\n\ +@end deftypefn\n\ +\n\ +@deftypefn {Built-in Function} void __chkp_bndstx (const void **@var{loc}, const void *@var{ptr}, bnd @var{b})\n\ +Function code - @code{BUILT_IN_CHKP_BNDSTX}. This built-in function is used\n\ +by Pointer Bounds Checker to store bounds @var{b} for pointer @var{ptr}\n\ +stored by address @var{loc}.\n\ +@end deftypefn\n\ +\n\ +@deftypefn {Built-in Function} bnd __chkp_bndldx (const void **@var{loc}, const void *@var{ptr})\n\ +Function code - @code{BUILT_IN_CHKP_BNDLDX}. This built-in function is used\n\ +by Pointer Bounds Checker to get bounds of pointer @var{ptr} loaded by\n\ +address @var{loc}.\n\ +@end deftypefn\n\ +\n\ +@deftypefn {Built-in Function} void __chkp_bndcl (bnd @var{b}, const void *@var{ptr})\n\ +Function code - @code{BUILT_IN_CHKP_BNDCL}. This built-in function is used\n\ +by Pointer Bounds Checker to perform check for pointer @var{ptr} against\n\ +lower bound of bounds @var{b}.\n\ +@end deftypefn\n\ +\n\ +@deftypefn {Built-in Function} void __chkp_bndcu (bnd @var{b}, const void *@var{ptr})\n\ +Function code - @code{BUILT_IN_CHKP_BNDCU}. This built-in function is used\n\ +by Pointer Bounds Checker to perform check for pointer @var{ptr} against\n\ +upper bound of bounds @var{b}.\n\ +@end deftypefn\n\ +\n\ +@deftypefn {Built-in Function} bnd __chkp_bndret (void *@var{ptr})\n\ +Function code - @code{BUILT_IN_CHKP_BNDRET}. This built-in function is used\n\ +by Pointer Bounds Checker to obtain bounds returned by call statement.\n\ +@var{ptr} passed to buil-in is @code{SSA_NAME} returned by call.\n\ +@end deftypefn\n\ +\n\ +@deftypefn {Built-in Function} bnd __chkp_arg_bnd (void *@var{arg})\n\ +Function code - @code{BUILT_IN_CHKP_ARG_BND}. This built-in function is\n\ +used by Pointer Bounds Checker to obtain bounds passed for input argument.\n\ +@var{arg} is default @code{SSA_NAME} of the @code{PARM_DECL} whose\n\ +bounds we want to obtain.\n\ +@end deftypefn\n\ +\n\ +@deftypefn {Built-in Function} bnd __chkp_intersect (bnd @var{b1}, bnd @var{b2})\n\ +Function code - @code{BUILT_IN_CHKP_INTERSECT}. This built-in function\n\ +returns intersection of bounds @var{b1} and @var{b2}.\n\ +@end deftypefn\n\ +\n\ +@deftypefn {Built-in Function} bnd __chkp_narrow (const void *@var{ptr}, bnd @var{b}, size_t @var{s})\n\ +Function code - @code{BUILT_IN_CHKP_NARROW}. This built-in function\n\ +returns intersection of bounds @var{b} and\n\ +[@var{ptr}, @var{ptr} + @var{s} - @code{1}].\n\ +@end deftypefn\n\ +\n\ +@deftypefn {Built-in Function} void *__chkp_set_bounds (const void *@var{ptr}, size_t @var{s})\n\ +Function code - @code{BUILT_IN_CHKP_SET_PTR_BOUNDS}. This built-in function\n\ +returns @var{ptr} with bounds [@var{ptr}, @var{ptr} + @var{s} - @code{1}].\n\ +@end deftypefn\n\ +\n\ +@deftypefn {Built-in Function} size_t __chkp_sizeof (const void *@var{ptr})\n\ +Function code - @code{BUILT_IN_CHKP_SIZEOF}. This built-in function\n\ +returns size of object referenced by @var{ptr}. @var{ptr} is always\n\ +@code{ADDR_EXPR} of @code{VAR_DECL}. This built-in is used by\n\ +Pointer Boudns Checker when bounds of object cannot be computed statically\n\ +(e.g. object has incomplete type).\n\ +@end deftypefn\n\ +\n\ +@deftypefn {Built-in Function} const void *__chkp_extract_lower (bnd @var{b})\n\ +Function code - @code{BUILT_IN_CHKP_EXTRACT_LOWER}. This built-in function\n\ +returns lower bound of bounds @var{b}.\n\ +@end deftypefn\n\ +\n\ +@deftypefn {Built-in Function} const void *__chkp_extract_upper (bnd @var{b})\n\ +Function code - @code{BUILT_IN_CHKP_EXTRACT_UPPER}. This built-in function\n\ +returns upper bound of bounds @var{b}.\n\ +@end deftypefn", + tree, (unsigned fcode), + default_builtin_chkp_function) + +DEFHOOK +(chkp_bound_type, + "Return type to be used for bounds", + tree, (void), + default_chkp_bound_type) + +DEFHOOK +(chkp_bound_mode, + "Return mode to be used for bounds.", + enum machine_mode, (void), + default_chkp_bound_mode) + /* Select a replacement for a target-specific builtin. This is done *before* regular type checking, and so allows the target to implement a crude form of function overloading. The result is a @@ -3273,6 +3383,15 @@ The default version of this hook returns @code{va_list_type_node}.", tree, (tree fndecl), std_fn_abi_va_list) +DEFHOOK +(fn_abi_va_list_bounds_size, + "This hook returns size for @code{va_list} object in function specified\n\ +by @var{fndecl}. This hook is used by Pointer Bounds Checker to build bounds\n\ +for @code{va_list} object. Return @code{integer_zero_node} if no bounds\n\ +should be used (e.g. @code{va_list} is a scalar pointer to the stack).", + tree, (tree fndecl), + default_fn_abi_va_list_bounds_size) + /* Get the __builtin_va_list type dependent on input type. */ DEFHOOK (canonical_va_list_type, @@ -3704,6 +3823,30 @@ not generate any instructions in this case.", default_setup_incoming_varargs) DEFHOOK +(load_bounds_for_arg, + "This hook is used by expand pass to emit insn to load bounds of\n\ +@var{arg} passed in @var{slot}. Expand pass uses this hook in case\n\ +bounds of @var{arg} are not passed in register. If @var{slot} is a\n\ +memory, then bounds are loaded as for regular pointer loaded from\n\ +memory. If @var{slot} is not a memory then @var{slot_no} is an integer\n\ +constant holding number of the target dependent special slot which\n\ +should be used to obtain bounds. Hook returns RTX holding loaded bounds.", + rtx, (rtx slot, rtx arg, rtx slot_no), + default_load_bounds_for_arg) + +DEFHOOK +(store_bounds_for_arg, + "This hook is used by expand pass to emit insns to store @var{bounds} of\n\ +@var{arg} passed in @var{slot}. Expand pass uses this hook in case\n\ +@var{bounds} of @var{arg} are not passed in register. If @var{slot} is a\n\ +memory, then @var{bounds} are stored as for regular pointer stored in\n\ +memory. If @var{slot} is not a memory then @var{slot_no} is an integer\n\ +constant holding number of the target dependent special slot which\n\ +should be used to store @var{bounds}.", + void, (rtx arg, rtx slot, rtx bounds, rtx slot_no), + default_store_bounds_for_arg) + +DEFHOOK (strict_argument_naming, "Define this hook to return @code{true} if the location where a function\n\ argument is passed depends on whether or not it is a named argument.\n\ diff --git a/gcc/targhooks.c b/gcc/targhooks.c index eb2e02f7c62..fe3c7d0cac6 100644 --- a/gcc/targhooks.c +++ b/gcc/targhooks.c @@ -68,7 +68,8 @@ along with GCC; see the file COPYING3. If not see #include "recog.h" #include "intl.h" #include "opts.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "tree-ssanames.h" #include "tree-ssa-alias.h" #include "insn-codes.h" @@ -435,6 +436,19 @@ targhook_float_words_big_endian (void) return !!FLOAT_WORDS_BIG_ENDIAN; } +/* True if the target supports floating-point exceptions and rounding + modes. */ + +bool +default_float_exceptions_rounding_supported_p (void) +{ +#ifdef HAVE_adddf3 + return HAVE_adddf3; +#else + return false; +#endif +} + /* True if the target supports decimal floating point. */ bool @@ -1556,6 +1570,28 @@ default_member_type_forces_blk (const_tree, enum machine_mode) { return false; } +rtx +default_load_bounds_for_arg (rtx addr ATTRIBUTE_UNUSED, + rtx ptr ATTRIBUTE_UNUSED, + rtx bnd ATTRIBUTE_UNUSED) +{ + gcc_unreachable (); +} + +void +default_store_bounds_for_arg (rtx val ATTRIBUTE_UNUSED, + rtx addr ATTRIBUTE_UNUSED, + rtx bounds ATTRIBUTE_UNUSED, + rtx to ATTRIBUTE_UNUSED) +{ + gcc_unreachable (); +} + +tree +default_fn_abi_va_list_bounds_size (tree fndecl ATTRIBUTE_UNUSED) +{ + return integer_zero_node; +} /* Default version of canonicalize_comparison. */ @@ -1564,4 +1600,136 @@ default_canonicalize_comparison (int *, rtx *, rtx *, bool) { } +#ifndef PAD_VARARGS_DOWN +#define PAD_VARARGS_DOWN BYTES_BIG_ENDIAN +#endif + +/* Build an indirect-ref expression over the given TREE, which represents a + piece of a va_arg() expansion. */ +tree +build_va_arg_indirect_ref (tree addr) +{ + addr = build_simple_mem_ref_loc (EXPR_LOCATION (addr), addr); + return addr; +} + +/* The "standard" implementation of va_arg: read the value from the + current (padded) address and increment by the (padded) size. */ + +tree +std_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p, + gimple_seq *post_p) +{ + tree addr, t, type_size, rounded_size, valist_tmp; + unsigned HOST_WIDE_INT align, boundary; + bool indirect; + +#ifdef ARGS_GROW_DOWNWARD + /* All of the alignment and movement below is for args-grow-up machines. + As of 2004, there are only 3 ARGS_GROW_DOWNWARD targets, and they all + implement their own specialized gimplify_va_arg_expr routines. */ + gcc_unreachable (); +#endif + + indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false); + if (indirect) + type = build_pointer_type (type); + + align = PARM_BOUNDARY / BITS_PER_UNIT; + boundary = targetm.calls.function_arg_boundary (TYPE_MODE (type), type); + + /* When we align parameter on stack for caller, if the parameter + alignment is beyond MAX_SUPPORTED_STACK_ALIGNMENT, it will be + aligned at MAX_SUPPORTED_STACK_ALIGNMENT. We will match callee + here with caller. */ + if (boundary > MAX_SUPPORTED_STACK_ALIGNMENT) + boundary = MAX_SUPPORTED_STACK_ALIGNMENT; + + boundary /= BITS_PER_UNIT; + + /* Hoist the valist value into a temporary for the moment. */ + valist_tmp = get_initialized_tmp_var (valist, pre_p, NULL); + + /* va_list pointer is aligned to PARM_BOUNDARY. If argument actually + requires greater alignment, we must perform dynamic alignment. */ + if (boundary > align + && !integer_zerop (TYPE_SIZE (type))) + { + t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp, + fold_build_pointer_plus_hwi (valist_tmp, boundary - 1)); + gimplify_and_add (t, pre_p); + + t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist_tmp, + fold_build2 (BIT_AND_EXPR, TREE_TYPE (valist), + valist_tmp, + build_int_cst (TREE_TYPE (valist), -boundary))); + gimplify_and_add (t, pre_p); + } + else + boundary = align; + + /* If the actual alignment is less than the alignment of the type, + adjust the type accordingly so that we don't assume strict alignment + when dereferencing the pointer. */ + boundary *= BITS_PER_UNIT; + if (boundary < TYPE_ALIGN (type)) + { + type = build_variant_type_copy (type); + TYPE_ALIGN (type) = boundary; + } + + /* Compute the rounded size of the type. */ + type_size = size_in_bytes (type); + rounded_size = round_up (type_size, align); + + /* Reduce rounded_size so it's sharable with the postqueue. */ + gimplify_expr (&rounded_size, pre_p, post_p, is_gimple_val, fb_rvalue); + + /* Get AP. */ + addr = valist_tmp; + if (PAD_VARARGS_DOWN && !integer_zerop (rounded_size)) + { + /* Small args are padded downward. */ + t = fold_build2_loc (input_location, GT_EXPR, sizetype, + rounded_size, size_int (align)); + t = fold_build3 (COND_EXPR, sizetype, t, size_zero_node, + size_binop (MINUS_EXPR, rounded_size, type_size)); + addr = fold_build_pointer_plus (addr, t); + } + + /* Compute new value for AP. */ + t = fold_build_pointer_plus (valist_tmp, rounded_size); + t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t); + gimplify_and_add (t, pre_p); + + addr = fold_convert (build_pointer_type (type), addr); + + if (indirect) + addr = build_va_arg_indirect_ref (addr); + + return build_va_arg_indirect_ref (addr); +} + +tree +default_chkp_bound_type (void) +{ + tree res = make_node (POINTER_BOUNDS_TYPE); + TYPE_PRECISION (res) = TYPE_PRECISION (size_type_node) * 2; + layout_type (res); + return res; +} + +enum machine_mode +default_chkp_bound_mode (void) +{ + return VOIDmode; +} + +tree +default_builtin_chkp_function (unsigned int fcode ATTRIBUTE_UNUSED) +{ + return NULL_TREE; +} + + #include "gt-targhooks.h" diff --git a/gcc/targhooks.h b/gcc/targhooks.h index b3bd15503cd..e3e613ac3f3 100644 --- a/gcc/targhooks.h +++ b/gcc/targhooks.h @@ -69,6 +69,7 @@ extern tree default_mangle_assembler_name (const char *); extern bool default_scalar_mode_supported_p (enum machine_mode); extern bool targhook_words_big_endian (void); extern bool targhook_float_words_big_endian (void); +extern bool default_float_exceptions_rounding_supported_p (void); extern bool default_decimal_float_supported_p (void); extern bool default_fixed_point_supported_p (void); @@ -202,3 +203,12 @@ extern void default_asm_output_ident_directive (const char*); extern enum machine_mode default_cstore_mode (enum insn_code); extern bool default_member_type_forces_blk (const_tree, enum machine_mode); +extern tree build_va_arg_indirect_ref (tree); +extern tree std_gimplify_va_arg_expr (tree, tree, gimple_seq *, gimple_seq *); + +extern rtx default_load_bounds_for_arg (rtx, rtx, rtx); +extern void default_store_bounds_for_arg (rtx, rtx, rtx, rtx); +extern tree default_fn_abi_va_list_bounds_size (tree); +extern tree default_chkp_bound_type (void); +extern enum machine_mode default_chkp_bound_mode (void); +extern tree default_builtin_chkp_function (unsigned int); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 64d56a03446..1f487d7f822 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,563 @@ +2013-11-04 Vladimir Makarov <vmakarov@redhat.com> + + PR rtl-optimization/58968 + * gfortran.dg/pr58968.f: New + +2013-11-04 Marek Polacek <polacek@redhat.com> + + PR c++/58979 + * g++.dg/diagnostic/pr58979.C: New test. + +2013-11-04 Joseph Myers <joseph@codesourcery.com> + + * gcc.dg/iec-559-macros-1.c, gcc.dg/iec-559-macros-2.c, + gcc.dg/iec-559-macros-3.c, gcc.dg/iec-559-macros-4.c, + gcc.dg/iec-559-macros-5.c, gcc.dg/iec-559-macros-6.c, + gcc.dg/iec-559-macros-7.c, gcc.dg/iec-559-macros-8.c, + gcc.dg/iec-559-macros-9.c: New tests. + +2013-11-04 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/58946 + * gcc.c-torture/compile/pr58946.c: New test. + +2013-11-03 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/52071 + * g++.dg/parse/pr52071.C: New. + +2013-11-03 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/38313 + * g++.dg/lookup/name-clash10.C: New. + +2013-11-03 Kugan Vivekanandarajah <kuganv@linaro.org> + + * gcc.target/arm/neon-vcond-gt.c: Scan for vbsl or vbit or vbif. + * gcc.target/arm/neon-vcond-ltgt.c: Scan for vbsl or vbit or vbif. + * gcc.target/arm/neon-vcond-unordered.c: Scan for vbsl or vbit or + vbif. + +2013-11-03 Marek Polacek <polacek@redhat.com> + + * g++.dg/ubsan/cxx1y-vla.C: New test. + * c-c++-common/ubsan/vla-3.c: New test. + * c-c++-common/ubsan/vla-2.c: New test. + * c-c++-common/ubsan/vla-4.c: New test. + * c-c++-common/ubsan/vla-1.c: New test. + +2013-11-02 Bill Schmidt <wschmidt@vnet.linux.ibm.com> + + * gcc.dg/vmx/vec-set.c: New. + +2013-11-02 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/29234 + PR c++/56037 + * g++.dg/parse/pr29234.C: New. + * g++.dg/parse/pr56037.C: Likewise. + +2013-11-01 Balaji V. Iyer <balaji.v.iyer@intel.com> + + * gcc.dg/cilk-plus/cilk-plus.exp: Loaded libcilkrts library path and + passed it in as one of the options to all Cilk keywords test. + +2013-11-01 Edward Smith-Rowland <3dw4rd@verizon.net> + + PR c++/58708 + * g++.dg/cpp1y/pr58708.C: New. + +2013-11-01 Marc Glisse <marc.glisse@inria.fr> + + PR c++/58834 + * g++.dg/ext/pr58834.C: New file. + +2013-11-01 Jakub Jelinek <jakub@redhat.com> + + * gcc.dg/gomp/declare-simd-2.c (f12, f13, f14, f15, f16, f17): New + tests. + * g++.dg/gomp/declare-simd-2.C (f15, f16, f17, f18, f19, f20): New + tests. + +2013-11-01 Paul Thomas <pault@gcc.gnu.org> + + PR fortran/57893 + * gfortran.dg/unlimited_polymorphic_13.f90 : Break up select + type block. + +2013-10-31 Jakub Jelinek <jakub@redhat.com> + + * g++.dg/gomp/simd-1.C: New test. + * g++.dg/gomp/declare-simd-1.C (f32): Fix up aligned clause argument. + * g++.dg/gomp/declare-simd-2.C (fn13, fn14): Add new tests. + * gcc.dg/gomp/declare-simd-2.c (fn7, fn8, fn9, fn10, fn11): Likewise. + * c-c++-common/gomp/simd6.c: New test. + +2013-10-31 Edward Smith-Rowland <3dw4rd@verizon.net> + + Implement C++14 digit separators. + * g++.dg/cpp1y/digit-sep.C: New. + * g++.dg/cpp1y/digit-sep-neg.C: New. + * g++.dg/cpp1y/digit-sep-cxx11-neg.C: New. + +2013-10-31 Jakub Jelinek <jakub@redhat.com> + + * gcc.dg/vect/vect-align-3.c: New test. + + * g++.dg/warn/pr33738.C (main): Initialize a2 again to make sure + we warn about it already during VRP1 pass. + +2013-10-31 Martin Jambor <mjambor@suse.cz> + + PR rtl-optimization/58934 + Revert: + 2013-10-30 Martin Jambor <mjambor@suse.cz> + PR rtl-optimization/10474 + * gcc.dg/pr10474.c: New testcase. + * gcc.dg/ira-shrinkwrap-prep-1.c: Likewise. + * gcc.dg/ira-shrinkwrap-prep-2.c: Likewise. + +2013-10-31 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/58932 + Revert: + 2013-10-18 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/58466 + * g++.dg/cpp0x/variadic145.C: New. + + * g++.dg/cpp0x/sfinae49.C: New. + +2013-10-30 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/58581 + * g++.dg/cpp0x/deleted1.C: New. + +2013-10-31 Zhenqiang Chen <zhenqiang.chen@linaro.org> + + * gcc.target/arm/lp1243022.c: New test. + +2013-10-30 Joern Rennecke <joern.rennecke@embecosm.com> + + PR other/58545 + * gcc.target/avr/pr58545.c: New test. + +2013-10-30 Tobias Burnus <burnus@net-b.de> + + Revert: + 2013-10-30 Tobias Burnus <burnus@net-b.de> + * gcc.dg/cilk-plus/cilk-plus.exp: Add the libcilkrts library + path to the compile flags. + +2013-10-30 Cong Hou <congh@google.com> + + * gcc.target/i386/vect-abs-s8.c: New test. + * gcc.target/i386/vect-abs-s16.c: New test. + * gcc.target/i386/vect-abs-s32.c: New test. + +2013-10-30 Tobias Burnus <burnus@net-b.de> + + * gcc.dg/cilk-plus/cilk-plus.exp: Add the libcilkrts library + path to the compile flags. + +2013-10-30 Mikael Pettersson <mikpe@it.uu.se> + + PR rtl-optimization/58369 + * g++.dg/torture/pr58369.C: New test. + +2013-10-30 Tobias Burnus <burnus@net-b.de> + + PR other/33426 + * g++.dg/vect/pr33426-ivdep-2.cc: New. + * g++.dg/vect/pr33426-ivdep-3.cc: New. + * g++.dg/vect/pr33426-ivdep-4.cc: New. + +2013-10-30 Vladimir Makarov <vmakarov@redhat.com> + + PR target/58784 + * gcc.target/arm/pr58784.c: New. + +2013-10-30 Marc Glisse <marc.glisse@inria.fr> + + * gcc.dg/tree-ssa/alias-24.c: New file. + +2013-10-30 Vladimir Makarov <vmakarov@redhat.com> + + * gcc.target/i386/fma_double_3.c: Use pattern for + scan-assembler-times instead of just one insn name. + * gcc.target/i386/fma_double_5.c: Ditto. + * gcc.target/i386/fma_float_3.c: Ditto. + * gcc.target/i386/fma_float_5.c: Ditto. + * gcc.target/i386/l_fma_double_1.c: Ditto. + * gcc.target/i386/l_fma_double_2.c: Ditto. + * gcc.target/i386/l_fma_double_3.c: Ditto. + * gcc.target/i386/l_fma_double_4.c: Ditto. + * gcc.target/i386/l_fma_double_5.c: Ditto. + * gcc.target/i386/l_fma_double_6.c: Ditto. + * gcc.target/i386/l_fma_float_1.c: Ditto. + * gcc.target/i386/l_fma_float_2.c: Ditto. + * gcc.target/i386/l_fma_float_3.c: Ditto. + * gcc.target/i386/l_fma_float_4.c: Ditto. + * gcc.target/i386/l_fma_float_5.c: Ditto. + * gcc.target/i386/l_fma_float_6.c: Ditto. + +2013-10-30 Christian Bruel <christian.bruel@st.com> + + * gcc.c-torture/execute/builtins/strncmp-2.c: Enable for SH. + * gcc.target/sh/cmpstr.c: New test. + * gcc.target/sh/cmpstrn.c: New test. + +2013-10-30 Martin Jambor <mjambor@suse.cz> + + PR rtl-optimization/10474 + * gcc.dg/pr10474.c: New testcase. + * gcc.dg/ira-shrinkwrap-prep-1.c: Likewise. + * gcc.dg/ira-shrinkwrap-prep-2.c: Likewise. + +2013-10-29 Andrew Pinski <apinski@cavium.com> + Zhenqiang Chen <zhenqiang.chen@linaro.org> + + * gcc.dg/tree-ssa/ssa-ifcombine-ccmp-1.c: New test case. + * gcc.dg/tree-ssa/ssa-ifcombine-ccmp-2.c: New test case. + * gcc.dg/tree-ssa/ssa-ifcombine-ccmp-3.c: New test case. + * gcc.dg/tree-ssa/ssa-ifcombine-ccmp-4.c: New test case. + * gcc.dg/tree-ssa/ssa-ifcombine-ccmp-5.c: New test case. + * gcc.dg/tree-ssa/ssa-ifcombine-ccmp-6.c: New test case. + * gcc.dg/tree-ssa/phi-opt-9.c: Use a function call to prevent + conditional move to be used. + * gcc.dg/tree-ssa/ssa-dom-thread-3.c: Remove. + +2013-10-29 Tobias Burnus <burnus@net-b.de> + + PR fortran/44350 + * gfortran.dg/blockdata_8.f90: New. + +2013-10-29 Oleg Endo <olegendo@gcc.gnu.org> + + PR target/54236 + * gcc.target/sh/pr54236-2: New. + * gcc.target/sh/pr54089-6: Add another rotl special case. + +2013-10-29 Paul Thomas <pault@gcc.gnu.org> + + PR fortran/58793 + * gfortran.dg/unlimited_polymorphic_13.f90: Use real variables + to determine sizes of real kinds. + + PR fortran/58858 + * gfortran.dg/unlimited_polymorphic_14.f90: New test. + +2013-10-29 Balaji V. Iyer <balaji.v.iyer@intel.com> + + * c-c++-common/cilk-plus/CK/compound_cilk_spawn.c: New test. + * c-c++-common/cilk-plus/CK/concec_cilk_spawn.c: Likewise. + * c-c++-common/cilk-plus/CK/fib.c: Likewise. + * c-c++-common/cilk-plus/CK/no_args_error.c: Likewise. + * c-c++-common/cilk-plus/CK/spawnee_inline.c: Likewise. + * c-c++-common/cilk-plus/CK/spawner_inline.c: Likewise. + * c-c++-common/cilk-plus/CK/spawning_arg.c: Likewise. + * c-c++-common/cilk-plus/CK/steal_check.c: Likewise. + * c-c++-common/cilk-plus/CK/test__cilk.c: Likewise. + * c-c++-common/cilk-plus/CK/varargs_test.c: Likewise. + * c-c++-common/cilk-plus/CK/sync_wo_spawn.c: Likewise. + * c-c++-common/cilk-plus/CK/invalid_spawn.c: Likewise. + * c-c++-common/cilk-plus/CK/spawn_in_return.c: Likewise. + * c-c++-common/cilk-plus/CK/fib_init_expr_xy.c: Likewise. + * c-c++-common/cilk-plus/CK/fib_no_sync.c: Likewise. + * c-c++-common/cilk-plus/CK/fib_no_return.c: Likewise. + * gcc.dg/cilk-plus/cilk-plus.exp: Added support to run Cilk Keywords + test stored in c-c++-common. Also, added the Cilk runtime's library + to the ld_library_path. + +2013-10-29 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/58888 + * g++.dg/cpp0x/auto40.C: New. + * g++.dg/other/warning1.C: Adjust. + +2013-10-29 Richard Biener <rguenther@suse.de> + + * gcc.dg/torture/restrict-2.c: New testcase. + * gcc.dg/torture/restrict-3.c: Likewise. + * gcc.dg/torture/restrict-4.c: Likewise. + * gcc.dg/torture/restrict-5.c: Likewise. + +2013-10-29 Marc Glisse <marc.glisse@inria.fr> + + PR tree-optimization/19831 + * gcc.dg/tree-ssa/alias-25.c: New file. + +2013-10-29 Richard Biener <rguenther@suse.de> + + * g++.dg/vect/slp-pr56812.cc: Adjust with respect to -fvect-cost-model + changes. + * gcc.dg/vect/bb-slp-32.c: Likewise. + * gcc.dg/vect/costmodel/i386/i386-costmodel-vect.exp: Likewise. + * gcc.dg/vect/costmodel/ppc/ppc-costmodel-vect.exp: Likewise. + * gcc.dg/vect/costmodel/spu/spu-costmodel-vect.exp: Likewise. + * gcc.dg/vect/costmodel/x86_64/x86_64-costmodel-vect.exp: Likewise. + * gcc.target/powerpc/crypto-builtin-1.c: Likewise. + * gcc.target/powerpc/p8vector-builtin-1.c: Likewise. + * gcc.target/powerpc/p8vector-builtin-2.c: Likewise. + * gcc.target/powerpc/p8vector-builtin-3.c: Likewise. + * gcc.target/powerpc/p8vector-builtin-4.c: Likewise. + * gcc.target/powerpc/p8vector-builtin-5.c: Likewise. + * gcc.target/powerpc/p8vector-vectorize-1.c: Likewise. + * gcc.target/powerpc/p8vector-vectorize-2.c: Likewise. + * gcc.target/powerpc/p8vector-vectorize-3.c: Likewise. + * gcc.target/powerpc/p8vector-vectorize-4.c: Likewise. + * gcc.target/powerpc/p8vector-vectorize-5.c: Likewise. + * gfortran.dg/vect/vect.exp: Likewise. + +2013-10-28 Bill Schmidt <wschmidt@linux.vnet.ibm.com> + + * gcc.dg/vmx/gcc-bug-i.c: Add little endian variant. + * gcc.dg/vmx/eg-5.c: Likewise. + +2013-10-28 Claudiu Zissulescu <claziss@synopsys.com> + Joern Rennecke <joern.rennecke@embecosm.com> + + * gcc.target/arc/jump-around-jump.c: New test. + +2013-10-27 Tom de Vries <tom@codesourcery.com> + + * gcc.target/arm/require-pic-register-loc.c: New test. + +2013-10-27 Uros Bizjak <ubizjak@gmail.com> + + PR target/58679 + * gcc.target/i386/pr58679-1.c: New test. + * gcc.target/i386/pr58679-2.c: Ditto. + +2013-10-27 Tobias Burnus <burnus@net-b.de> + + PR other/33426 + * gcc.dg/vect/vect-ivdep-2.c: New. + +2013-10-26 Oleg Endo <olegendo@gcc.gnu.org> + + PR target/52483 + * gcc.target/sh/pr52483-1.c: Add tests for memory stores. + * gcc.target/sh/pr52483-2.c: Likewise. + * gcc.target/sh/pr52483-3.c: Likewise. + * gcc.target/sh/pr52483-4.c: Likewise. + +2013-10-26 Jeff Law <law@redhat.com> + + * g++.dg/torture/pr49309.C: Removed. + * gcc.dg/dfp/pr35739.c: Removed. + +2013-10-25 Vladimir Makarov <vmakarov@redhat.com> + + PR rtl-optimization/58759 + * gcc.target/i386/pr58759.c: New. + +2013-10-25 Tobias Burnus <burnus@net-b.de> + + * g++.dg/vect/pr33426-ivdep.cc: Use dg-options. + * gfortran.dg/vect/vect-do-concurrent-1.f90: Ditto. + * testsuite/gcc.dg/vect/vect-ivdep-1.c: Ditto. + +2013-10-25 Yufeng Zhang <yufeng.zhang@arm.com> + + * gcc.dg/wmul-1.c: New test. + +2013-10-25 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/58878 + * g++.dg/template/pr58878.C: New. + +2013-10-25 Marc Glisse <marc.glisse@inria.fr> + + * gcc.dg/tree-ssa/alias-23.c: New file. + +2013-10-25 Richard Biener <rguenther@suse.de> + + PR tree-optimization/58626 + * gcc.dg/torture/pr58626.c: New testcase. + +2013-10-25 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/54812 + * g++.dg/cpp0x/defaulted47.C: New. + +2013-10-25 Eric Botcazou <ebotcazou@adacore.com> + + * gcc.c-torture/execute/pr58831.c: New test. + +2013-10-25 Nick Clifton <nickc@redhat.com> + + * c-c++-common/pr57793.c: Add expected error messages for + targets with small integers. + * gcc.dg/c99-stdint-1.c: Only run on 32-bit plus targets. + * gcc.dg/c99-stdint-2.c: Likewise. + * gcc.dg/cdce1.c: Likewise. + * gcc.dg/fold-overflow-1.c: Likewise. + * gcc.dg/utf-cvt.c: Likewise. + * gcc.dg/ftrapv-1.c: Only run on targets that support trapping + arithmetic. + * gcc.dg/ftrapv-2.c: Likewise. + * gcc.dg/pr30286.c: Likewise. + * gcc.dg/pr19340.c: Only run on targets that support scheduling. + * lib/target-supports.exp (check_effective_target_trapping): New + proc. Returns true if the target supports trapping arithmetic. + +2013-10-25 Tobias Burnus <burnus@net-b.de> + + * g++.dg/parse/ivdep.C: New. + * g++.dg/vect/pr33426-ivdep.cc: New. + +2013-10-24 Richard Henderson <rth@redhat.com> + + PR rtl/58542 + * gcc.dg/atomic-store-6.c: New. + +2013-10-24 Ian Lance Taylor <iant@google.com> + + * go.test/go-test.exp (errchk): Combine quoted strings in comments. + +2013-10-24 Cong Hou <congh@google.com> + + * gcc.c-torture/execute/20030125-1.c: Update. + +2013-10-24 Tobias Burnus <burnus@net-b.de> + + PR fortran/44646 + * gfortran.dg/vect/vect-do-concurrent-1.f90: New. + +2013-10-24 Dehao Chen <dehao@google.com> + + * g++.dg/opt/devirt3.C: New test. + +2013-08-24 Tobias Burnus <burnus@net-b.de> + + PR other/33426 + * testsuite/gcc.dg/ivdep.c: New. + * testsuite/gcc.dg/vect/vect-ivdep-1.c: New. + +2013-10-24 Kyrylo Tkachov <kyrylo.tkachov@arm.com> + + * gcc.target/aarch64/c-output-mod-2.c: Fix for -fPIC. + * gcc.target/aarch64/c-output-mod-3.c: Likewise. + +2013-10-24 Nick Clifton <nickc@redhat.com> + + * gcc.dg/20020312-2.c: No PIC register for RL78 or MSP430. + +2013-10-24 Marek Polacek <polacek@redhat.com> + + PR c++/58705 + * g++.dg/parse/pr58705.C: New test. + +2013-10-24 Marek Polacek <polacek@redhat.com> + + * gcc.dg/c11-align-5.c: Add more testing. + +2013-10-23 Pat Haugen <pthaugen@us.ibm.com> + + * gcc.target/powerpc/direct-move.h: Fix header for executable tests. + +2013-10-23 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/58775 + PR tree-optimization/58791 + * gcc.dg/guality/pr58791-1.c: New test. + * gcc.dg/guality/pr58791-2.c: New test. + * gcc.dg/guality/pr58791-3.c: New test. + * gcc.dg/guality/pr58791-4.c: New test. + * gcc.dg/guality/pr58791-5.c: New test. + * gcc.c-torture/compile/pr58775.c: New test. + * gcc.dg/tree-ssa/reassoc-28.c: Don't scan reassoc1 dump. + +2013-10-23 Tom de Vries <tom@codesourcery.com> + + PR tree-optimization/58805 + * gcc.dg/pr58805.c: New test. + +2013-10-23 Jakub Jelinek <jakub@redhat.com> + + * gcc.target/i386/vect-div-1.c: New test. + + * gcc.dg/vect/pr58508.c: Remove dg-options. + +2013-10-23 Richard Biener <rguenther@suse.de> + + * gcc.dg/torture/pr58830.c: New testcase. + +2013-10-23 Edward Smith-Rowland <3dw4rd@verizon.net> + + Implement C++14 [[deprecated]] modulo [[gnu::deprecated]] bugs. + * g++.dg/cpp1y/attr-deprecated.C: New. + * g++.dg/cpp1y/attr-deprecated-neg.C: New. + +2013-10-23 Tobias Burnus <burnus@net-b.de> + + PR fortran/58793 + * gfortran.dg/assumed_type_8.f90: New. + +2013-10-22 Uros Bizjak <ubizjak@gmail.com> + + PR target/58779 + * gcc.target/i386/pr30315.c: Remove MINUSCC, DECCC, MINUSCCONLY + and MINUSCCZEXT defines. Update scan-assembler dg directive. + * gcc.dg/torture/pr58779.c: New test. + +2013-10-22 Steve Ellcey <sellcey@mips.com> + + * gcc.target/mips/nor.c: New. + +2013-10-22 Bill Schmidt <wschmidt@vnet.ibm.com> + + * gcc.target/powerpc/altivec-perm-1.c: Move the two vector pack + tests into... + * gcc.target/powerpc/altivec-perm-3.c: ...this new test, which is + restricted to big-endian targets. + +2013-10-22 Paul Thomas <pault@gcc.gnu.org> + + PR fortran 57893 + * gfortran.dg/unlimited_polymorphic_13.f90 : New test. + +2013-10-21 Tobias Burnus <burnus@net-b.de> + + PR fortran/58803 + * gfortran.dg/proc_ptr_comp_38.f90: New. + +2013-10-21 Marek Polacek <polacek@redhat.com> + + PR middle-end/58809 + * gcc.dg/gomp/pr58809.c: New test. + +2013-10-21 Vidya Praveen <vidyapraveen@arm.com> + + * gcc.dg/20050922-1.c: Remove stdlib.h and declare abort(). + * gcc.dg/20050922-1.c: Remove stdlib.h and declare abort() and exit(). + +2013-10-21 Richard Biener <rguenther@suse.de> + + PR tree-optimization/58794 + * c-c++-common/torture/pr58794-1.c: New testcase. + * c-c++-common/torture/pr58794-2.c: Likewise. + +2013-10-21 Richard Biener <rguenther@suse.de> + + PR middle-end/58742 + * c-c++-common/fold-divmul-1.c: New testcase. + +2013-10-21 Michael Zolotukhin <michael.v.zolotukhin@gmail.com> + + * gcc.target/i386/memset-vector_loop-1.c: New test. + * gcc.target/i386/memset-vector_loop-2.c: New test. + +2013-10-21 Diego Novillo <dnovillo@google.com> + + * g++.dg/plugin/selfassign.c: Include tree.h. + * gcc.dg/plugin/finish_unit_plugin.c: Likewise. + * gcc.dg/plugin/ggcplug.c: Likewise. + * gcc.dg/plugin/one_time_plugin.c: Likewise. + * gcc.dg/plugin/selfassign.c: Likewise. + * gcc.dg/plugin/start_unit_plugin.c: Likewise. + 2013-10-20 Richard Sandiford <rdsandiford@googlemail.com> * gcc.target/mips/mips-ps-5.c: Add alignment attributes. @@ -171,8 +731,8 @@ 2013-10-14 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> - * gcc.dg/torture/pr58670.c (ASM_STR) [__i386__ || __x86_64__]: Use - btsl. + * gcc.dg/torture/pr58670.c (ASM_STR) [__i386__ || __x86_64__]: + Use btsl. 2013-10-14 Eric Botcazou <ebotcazou@adacore.com> @@ -1951,6 +2511,7 @@ 2013-08-08 Richard Sandiford <rdsandiford@googlemail.com> + PR rtl-optimization/58079 * gcc.dg/torture/pr58079.c: New test. 2013-08-07 Eric Botcazou <ebotcazou@adacore.com> @@ -5981,7 +6542,7 @@ * gcc.target/arm/vselvsdf.c: Likewise. * gcc.target/arm/vselvssf.c: Likewise. -2013-03-25 Kyrylo Tkachov <kyrylo.tkachov at arm.com> +2013-03-25 Kyrylo Tkachov <kyrylo.tkachov@arm.com> * gcc.target/aarch64/atomic-comp-swap-release-acquire.c: Move test body from here... @@ -6869,7 +7430,7 @@ PR rtl-optimization/56151 * gcc.target/i386/pr56151.c: New test. -2013-02-11 Sriraman Tallam <tmsriramgoogle.com> +2013-02-11 Sriraman Tallam <tmsriram@google.com> * g++.dg/ext/mv12.C: New test. * g++.dg/ext/mv12.h: New file. @@ -7050,7 +7611,7 @@ PR target/54131 * gfortran.dg/pr54131.f: New test. -2013-02-06 Paul Thomas <pault@gcc.gnu.org> +2013-02-06 Paul Thomas <pault@gcc.gnu.org> PR fortran/55789 * gfortran.dg/array_constructor_41.f90: New test. diff --git a/gcc/testsuite/ChangeLog-2009 b/gcc/testsuite/ChangeLog-2009 index a4614a03ec7..4c14e744fab 100644 --- a/gcc/testsuite/ChangeLog-2009 +++ b/gcc/testsuite/ChangeLog-2009 @@ -4683,7 +4683,7 @@ * gcc.c-torture/compile/limits-fndefn.c: Add dg-timeout-factor. -2009-08-25 Ville Voutilainen <ville.voutilainen@gmail.com> +2009-08-25 Ville Voutilainen <ville.voutilainen@gmail.com> * g++.dg/cpp0x/alignof.C: New. Tests that the alignof keyword works in the same manner as __alignof. diff --git a/gcc/testsuite/ChangeLog-2012 b/gcc/testsuite/ChangeLog-2012 index 90e08399a79..83c15e1f4a6 100644 --- a/gcc/testsuite/ChangeLog-2012 +++ b/gcc/testsuite/ChangeLog-2012 @@ -5983,7 +5983,7 @@ PR c++/52637 * g++.dg/debug/localclass1.C: New. -2012-06-16 Ville Voutilainen <ville.voutilainen@gmail.com> +2012-06-16 Ville Voutilainen <ville.voutilainen@gmail.com> * g++.dg/cpp0x/override4.C: New. diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/compound_cilk_spawn.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/compound_cilk_spawn.c new file mode 100644 index 00000000000..5e687bd0a0c --- /dev/null +++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/compound_cilk_spawn.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-fcilkplus" } */ + +/* <feature> + A program is considered ill formed if the _Cilk_spawn form of this + expression appears other than in one of the following contexts: + as the entire body of an expression statement, + as the entire right hand side of an assignment expression that is the entire + body of an expression statement, or as the entire initializer-clause in a + simple declaration. + </feature> +*/ + +int spawn_func (int arg) +{ + return arg + 1; +} + +int check() +{ + int z; + z = 23, _Cilk_spawn spawn_func (3), 3424; /* { dg-error "spawned function call cannot be part of a comma expression" } */ + 23, spawn_func (5), _Cilk_spawn spawn_func (3); /* { dg-error "spawned function call cannot be part of a comma expression" } */ + _Cilk_spawn spawn_func (0), _Cilk_spawn spawn_func (3), 3, spawn_func (0); /* { dg-error "spawned function call cannot be part of a comma expression" } */ + return 23; +} diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/concec_cilk_spawn.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/concec_cilk_spawn.c new file mode 100644 index 00000000000..b93c9626d18 --- /dev/null +++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/concec_cilk_spawn.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-fcilkplus" } */ + +/* <feature> Consecutive _Cilk_spawn tokens are not permitted + </feature> +*/ + +int spawn_func (int arg) +{ + return arg + 1; +} + +void func () +{ + int a; + a = _Cilk_spawn _Cilk_spawn spawn_func (4); /* { dg-error "consecutive" } */ + a = _Cilk_spawn _Cilk_spawn _Cilk_spawn spawn_func (4); /* { dg-error "consecutive" } */ + a = _Cilk_spawn _Cilk_spawn _Cilk_spawn _Cilk_spawn spawn_func (4); /* { dg-error "consecutive" } */ + return; +} diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/fib.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/fib.c new file mode 100644 index 00000000000..6612936a05c --- /dev/null +++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/fib.c @@ -0,0 +1,61 @@ +/* { dg-options "-fcilkplus" } */ +/* { dg-do run { target i?86-*-* x86_64-*-* } } */ +/* { dg-options "-fcilkplus -lcilkrts" { target { i?86-*-* x86_64-*-* } } } */ + +#if HAVE_IO +#include <stdio.h> +#endif + +int fib (int); +int fib_serial (int); + +int main(void) +{ + int ii = 0, error = 0; + int fib_result[41], fib_serial_result[41]; +#if HAVE_IO + + for (ii = 0; ii <= 40; ii++) + printf("fib (%2d) = %10d\n", ii, fib (ii)); +#else + for (ii = 0; ii <= 40; ii++) + { + fib_result[ii] = fib (ii); + fib_serial_result[ii] = fib_serial (ii); + } + + for (ii = 0; ii <= 40; ii++) + { + if (fib_result[ii] != fib_serial_result[ii]) + error = 1; + } +#endif + return error; +} + +int fib_serial (int n) +{ + int x = 0, y = 0; + if (n < 2) + return n; + else + { + x = fib (n-1); + y = fib (n-2); + return (x+y); + } +} + +int fib(int n) +{ + int x = 0, y = 0; + if (n < 2) + return n; + else + { + x = _Cilk_spawn fib(n-1); + y = fib(n-2); + _Cilk_sync; + return (x+y); + } +} diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/fib_init_expr_xy.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/fib_init_expr_xy.c new file mode 100644 index 00000000000..6b09918a420 --- /dev/null +++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/fib_init_expr_xy.c @@ -0,0 +1,60 @@ +/* { dg-options "-fcilkplus" } */ +/* { dg-do run { target i?86-*-* x86_64-*-* } } */ +/* { dg-options "-fcilkplus -lcilkrts" { target { i?86-*-* x86_64-*-* } } } */ + +#if HAVE_IO +#include <stdio.h> +#endif + +int fib (int); +int fib_serial (int); + +int main(void) +{ + int ii = 0, error = 0; + int fib_result[41], fib_serial_result[41]; +#if HAVE_IO + + for (ii = 0; ii <= 40; ii++) + printf("fib (%2d) = %10d\n", ii, fib (ii)); +#else + for (ii = 0; ii <= 40; ii++) + { + fib_result[ii] = fib (ii); + fib_serial_result[ii] = fib_serial (ii); + } + + for (ii = 0; ii <= 40; ii++) + { + if (fib_result[ii] != fib_serial_result[ii]) + error = 1; + } +#endif + return error; +} + +int fib_serial (int n) +{ + int x = 0, y = 0; + if (n < 2) + return n; + else + { + x = fib (n-1); + y = fib (n-2); + return (x+y); + } +} + +int fib(int n) +{ + if (n < 2) + return n; + else + { + int x = _Cilk_spawn fib(n-1); + int y = fib(n-2); + _Cilk_sync; + return (x+y); + } +} diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/fib_no_return.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/fib_no_return.c new file mode 100644 index 00000000000..2adf3a2f6e1 --- /dev/null +++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/fib_no_return.c @@ -0,0 +1,65 @@ +/* { dg-options "-fcilkplus" } */ +/* { dg-do run { target i?86-*-* x86_64-*-* } } */ +/* { dg-options "-fcilkplus -lcilkrts" { target { i?86-*-* x86_64-*-* } } } */ + +#if HAVE_IO +#include <stdio.h> +#endif + +void fib (int *, int); +int fib_serial (int); + +int main(void) +{ + int ii = 0, error = 0; + int fib_result[41], fib_serial_result[41]; + +#if HAVE_IO + for (ii = 0; ii <= 40; ii++) + { + int result = 0; + fib (&result, ii); + printf("fib (%2d) = %10d\n", ii, result); + } +#else + for (ii = 0; ii <= 40; ii++) + { + fib (&fib_result[ii], ii); + fib_serial_result[ii] = fib_serial (ii); + } + + for (ii = 0; ii <= 40; ii++) + { + if (fib_result[ii] != fib_serial_result[ii]) + error = 1; + } +#endif + return error; +} + +int fib_serial (int n) +{ + int x = 0, y = 0; + if (n < 2) + return n; + else + { + fib (&x, n-1); + fib (&y, n-2); + return (x+y); + } +} + +void fib(int *result, int n) +{ + int x = 0, y = 0; + if (n < 2) + x = n; + else + { + _Cilk_spawn fib(&x, n-1); + fib(&y, n-2); + _Cilk_sync; + } + *result = (x+y); +} diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/fib_no_sync.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/fib_no_sync.c new file mode 100644 index 00000000000..9de70be7584 --- /dev/null +++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/fib_no_sync.c @@ -0,0 +1,59 @@ +/* { dg-options "-fcilkplus" } */ +/* { dg-do run { target i?86-*-* x86_64-*-* } } */ +/* { dg-options "-fcilkplus -lcilkrts" { target { i?86-*-* x86_64-*-* } } } */ + +#if HAVE_IO +#include <stdio.h> +#endif + +int fib (int); +int fib_serial (int); + +int main(void) +{ + int ii = 0, error = 0; + int fib_result[41], fib_serial_result[41]; +#if HAVE_IO + + for (ii = 0; ii <= 40; ii++) + printf("fib (%2d) = %10d\n", ii, fib (ii)); +#else + for (ii = 0; ii <= 40; ii++) + { + fib_result[ii] = fib (ii); + fib_serial_result[ii] = fib_serial (ii); + } + + for (ii = 0; ii <= 40; ii++) + { + if (fib_result[ii] != fib_serial_result[ii]) + error = 1; + } +#endif + return error; +} + +int fib_serial (int n) +{ + int x = 0, y = 0; + if (n < 2) + return n; + else + { + x = fib (n-1); + y = fib (n-2); + return (x+y); + } +} + +int fib(int n) +{ + if (n < 2) + return n; + else + { + int x = _Cilk_spawn fib(n-1); + int y = fib(n-2); + return (x+y); + } +} diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/invalid_spawns.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/invalid_spawns.c new file mode 100644 index 00000000000..90dd5c130b4 --- /dev/null +++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/invalid_spawns.c @@ -0,0 +1,11 @@ +extern int foo (); +int bar = _Cilk_spawn foo (); /* { dg-error "may only be used inside a function" } */ + + +int main (void) +{ + int x; + + _Cilk_spawn x; /* { dg-error "only function calls can be spawned" } */ + return x; +} diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/no_args_error.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/no_args_error.c new file mode 100644 index 00000000000..593732ef5ab --- /dev/null +++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/no_args_error.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-fcilkplus" } */ + +int spawn_1 (); +typedef int(*func) (int); + +void check () { + func var = spawn_1; /* { dg-error "invalid conversion from" "" { target c++ } 8 } */ + _Cilk_spawn var (); /* { dg-error "too few arguments to function" } */ +} + diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/spawn_in_return.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/spawn_in_return.c new file mode 100644 index 00000000000..14b7eef1276 --- /dev/null +++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/spawn_in_return.c @@ -0,0 +1,8 @@ +/* { dg-do compile } */ +/* { dg-options "-fcilkplus" } */ + +int main (void) +{ + extern int foo (); + return _Cilk_spawn foo (); /* { dg-error "return statement is not allowed" } */ +} diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/spawnee_inline.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/spawnee_inline.c new file mode 100644 index 00000000000..8060c6ceb15 --- /dev/null +++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/spawnee_inline.c @@ -0,0 +1,80 @@ +/* { dg-do run { target { i?86-*-* x86_64-*-* } } } */ +/* { dg-options "-fcilkplus -w" } */ +/* { dg-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */ + +#include <stdio.h> +#include <stdlib.h> +#define DEFAULT_VALUE "30" + +int fib (char *n_char) +{ + int n; + char n_char_minus_one[20], n_char_minus_two[20]; + if (n_char) + n = atoi (n_char); + else + n = atoi(DEFAULT_VALUE); + + if (n < 2) + return n; + else + { + int x, y; + sprintf (n_char_minus_one,"%d", n-1); + sprintf (n_char_minus_two,"%d", n-2); + x = _Cilk_spawn fib (n_char_minus_one); + y = _Cilk_spawn fib (n_char_minus_two); + _Cilk_sync; + return (x+y); + } +} + +int fib_serial (int n) +{ + int x, y; + if (n < 2) + return n; + else + { + x = fib_serial (n-1); + y = fib_serial (n-2); + return (x+y); + } + return 0; +} + +int main2_parallel (int argc, char *argv[]) +{ + int n, result_parallel = 0; + + if (argc == 2) + { + result_parallel = _Cilk_spawn fib (argv[1]); + _Cilk_sync; + } + else + { + result_parallel = _Cilk_spawn fib((char *)"30"); + _Cilk_sync; + } + return result_parallel; +} + +int main2_serial (int argc, char *argv[]) +{ + int n, result_serial = 0; + if (argc == 2) + result_serial = fib_serial (atoi (argv[1])); + else + result_serial = fib_serial (atoi (DEFAULT_VALUE)); + + return result_serial; +} + +int main (void) +{ + if (main2_serial (1, 0) != main2_parallel (1,0)) + return 1; + return 0; +} + diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/spawner_inline.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/spawner_inline.c new file mode 100644 index 00000000000..eab9e4206a0 --- /dev/null +++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/spawner_inline.c @@ -0,0 +1,67 @@ +/* { dg-do run { target { i?86-*-* x86_64-*-* } } } */ +/* { dg-options "-fcilkplus" } */ +/* { dg-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */ + +#include <stdlib.h> +#define DEFAULT_VALUE 30 +int fib (int n) +{ + if (n<2) + return n; + else + { + int x, y; + x = _Cilk_spawn fib (n-1); + y = _Cilk_spawn fib (n-2); + _Cilk_sync; + return (x+y); + return 5; + } +} + +int main_parallel (int argc, char *argv[]) +{ + int n, result; + if (argc == 2) + n = atoi(argv[1]); + else + n = DEFAULT_VALUE; + result = _Cilk_spawn fib(n); + _Cilk_sync; + return result; +} + +int fib_serial (int n) +{ + int x, y; + if (n < 2) + return n; + else + { + x = fib (n-1); + y = fib (n-2); + return (x+y); + } +} + +int main_serial (int argc, char *argv[]) +{ + int n, result; + + if (argc == 2) + n = atoi (argv[1]); + else + n = DEFAULT_VALUE; + result = fib_serial (n); + + return result; +} + +int main (void) +{ + if (main_serial (1, 0) != main_parallel (1,0)) + return 1; + else + return 0; +} + diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/spawning_arg.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/spawning_arg.c new file mode 100644 index 00000000000..ac379528379 --- /dev/null +++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/spawning_arg.c @@ -0,0 +1,37 @@ +/* { dg-do run { target { i?86-*-* x86_64-*-* } } } */ +/* { dg-options "-fcilkplus" } */ +/* { dg-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */ + +void f0(volatile int *steal_flag) +{ + int i = 0; + /* Wait for steal_flag to be set */ + while (!*steal_flag) + ; +} + +int f1() +{ + + volatile int steal_flag = 0; + _Cilk_spawn f0(&steal_flag); + steal_flag = 1; // Indicate stolen + _Cilk_sync; + return 0; +} + +void f2(int q) +{ + q = 5; +} + +void f3() +{ + _Cilk_spawn f2(f1()); +} + +int main() +{ + f3(); + return 0; +} diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/steal_check.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/steal_check.c new file mode 100644 index 00000000000..21d6797857d --- /dev/null +++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/steal_check.c @@ -0,0 +1,43 @@ +/* { dg-do run { target { i?86-*-* x86_64-*-* } } } */ +/* { dg-options "-fcilkplus" } */ +/* { dg-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */ + +// #include <cilk/cilk_api.h> +extern void __cilkrts_set_param (char *, char *); + +void foo(volatile int *); + +void main2(void); + +int main(void) +{ + // __cilkrts_set_param ((char *)"nworkers", (char *)"2"); + main2(); + return 0; +} + + +void main2(void) +{ + int some_var = 0; + + _Cilk_spawn foo(&some_var); + + some_var=1; + some_var=5; + some_var=3; + some_var=4; + + _Cilk_sync; + return; +} + +void foo(volatile int *some_other_var) +{ + while (*some_other_var == 0) + { + ; + } +} + + diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/sync_wo_spawn.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/sync_wo_spawn.c new file mode 100644 index 00000000000..51be796e562 --- /dev/null +++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/sync_wo_spawn.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-fcilkplus" } */ + +int main (void) +{ + _Cilk_sync; /* { dg-error "expected '_Cilk_spawn' before '_Cilk_sync'" } */ + return 0; +} + diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/test__cilk.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/test__cilk.c new file mode 100644 index 00000000000..2b37cd664c1 --- /dev/null +++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/test__cilk.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-do run { target { i?86-*-* x86_64-*-* } } } */ +/* { dg-options "-fcilkplus" } */ + +int main (void) +{ + if (__cilk == 200) + return 0; + return 1; +} diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/varargs_test.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/varargs_test.c new file mode 100644 index 00000000000..ab5d63a3f4c --- /dev/null +++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/varargs_test.c @@ -0,0 +1,47 @@ +/* { dg-do run { target { i?86-*-* x86_64-*-* } } } */ +/* { dg-options "-fcilkplus" } */ +/* { dg-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */ + +#include <stdarg.h> +#include <stdlib.h> + + +double compute_total (int no_elements, ...); + +int main(void) +{ + double array[5] = {5.0, 4.0, 9.0, 3.0, 4.0}; + double array2[5] = {5.0, 6.0, 8.0, 6.0}; + double yy=0, xx=0, xx_serial, yy_serial; + + yy = _Cilk_spawn compute_total(5,array[0],array[1],array[2], + array[3], array[4]); + xx= compute_total(4,array2[0],array2[1],array2[2], array2[3]); + + _Cilk_sync; + + yy_serial = compute_total(5,array[0],array[1],array[2], array[3], array[4]); + xx_serial = compute_total(4,array2[0],array2[1],array2[2], array2[3]); + + if ((xx + yy) != (xx_serial + yy_serial)) + return 1; + return 0; + +} + + +double compute_total (int no_elements, ...) +{ + double total = 0; + va_list args; + va_start(args, no_elements); + int ii = 0; + for (ii = 0; ii < no_elements; ii++) + { + total += va_arg(args,double); + } + va_end(args); + + return total; +} + diff --git a/gcc/testsuite/c-c++-common/fold-divmul-1.c b/gcc/testsuite/c-c++-common/fold-divmul-1.c new file mode 100644 index 00000000000..5c867923d2e --- /dev/null +++ b/gcc/testsuite/c-c++-common/fold-divmul-1.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-fdump-tree-original" } */ + +int * +fx (int *b, int *e) +{ + return b + (e - b); +} + +/* { dg-final { scan-tree-dump-not "/\\\[ex\\\]" "original" } } */ +/* { dg-final { cleanup-tree-dump "original" } } */ diff --git a/gcc/testsuite/c-c++-common/gomp/simd6.c b/gcc/testsuite/c-c++-common/gomp/simd6.c new file mode 100644 index 00000000000..3a90c225e9e --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/simd6.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-fopenmp" } */ + +extern int a[1024]; + +struct S { int i; } s; + +void +f1 (int x, float f, int *p) +{ + int i; + #pragma omp simd aligned(x : 32) /* { dg-error "neither a pointer nor an array" } */ + for (i = 0; i < 1024; i++) + a[i]++; + #pragma omp simd aligned(f) /* { dg-error "neither a pointer nor an array" } */ + for (i = 0; i < 1024; i++) + a[i]++; + #pragma omp simd aligned(s : 16) /* { dg-error "neither a pointer nor an array" } */ + for (i = 0; i < 1024; i++) + a[i]++; + #pragma omp simd aligned(a : 8) + for (i = 0; i < 1024; i++) + a[i]++; + #pragma omp simd aligned(p : 8) + for (i = 0; i < 1024; i++) + a[i]++; +} diff --git a/gcc/testsuite/c-c++-common/pr57793.c b/gcc/testsuite/c-c++-common/pr57793.c index d66fadaa1f7..f2719529ebb 100644 --- a/gcc/testsuite/c-c++-common/pr57793.c +++ b/gcc/testsuite/c-c++-common/pr57793.c @@ -3,8 +3,8 @@ struct A { unsigned a : 1; unsigned b : 1; }; struct B /* { dg-error "type .B. is too large" "" { target { c++ && ilp32 } } } */ { - unsigned char c[0x40000000]; - unsigned char d[0x40000ff0]; + unsigned char c[0x40000000]; /* { dg-error "size of array .c. is too large" "" { target { ! int32plus } } } */ + unsigned char d[0x40000ff0];/* { dg-error "size of array .d. is too large" "" { target { ! int32plus } } } */ struct A e; }; /* { dg-error "type .struct B. is too large" "" { target { c && ilp32 } } } */ diff --git a/gcc/testsuite/c-c++-common/torture/pr58794-1.c b/gcc/testsuite/c-c++-common/torture/pr58794-1.c new file mode 100644 index 00000000000..175629fec90 --- /dev/null +++ b/gcc/testsuite/c-c++-common/torture/pr58794-1.c @@ -0,0 +1,29 @@ +/* { dg-do compile } */ + +struct S0 +{ + int f; +}; + +struct S1 +{ + struct S0 f1; + volatile int f2; +}; + +struct S2 +{ + struct S1 g; +} a, b; + +static int *c[1][2] = {{0, (int *)&a.g.f2}}; +static int d; + +int +main () +{ + for (d = 0; d < 1; d++) + for (b.g.f1.f = 0; b.g.f1.f < 1; b.g.f1.f++) + *c[b.g.f1.f][d + 1] = 0; + return 0; +} diff --git a/gcc/testsuite/c-c++-common/torture/pr58794-2.c b/gcc/testsuite/c-c++-common/torture/pr58794-2.c new file mode 100644 index 00000000000..767798806db --- /dev/null +++ b/gcc/testsuite/c-c++-common/torture/pr58794-2.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ + +struct S +{ + volatile int f; +} a; + +unsigned int b; + +static int *c[1][2] = {{0, (int *)&a.f}}; +static unsigned int d; + +int +main () +{ + for (; d < 1; d++) + for (; b < 1; b++) + *c[b][d + 1] = 0; + + return 0; +} diff --git a/gcc/testsuite/c-c++-common/ubsan/vla-1.c b/gcc/testsuite/c-c++-common/ubsan/vla-1.c new file mode 100644 index 00000000000..6c1d81e9d22 --- /dev/null +++ b/gcc/testsuite/c-c++-common/ubsan/vla-1.c @@ -0,0 +1,48 @@ +/* { dg-do run } */ +/* { dg-options "-fsanitize=vla-bound -w" } */ + +static int +bar (void) +{ + return -42; +} + +typedef long int V; +int +main (void) +{ + int x = -1; + double di = -3.2; + V v = -666; + + int a[x]; + int aa[x][x]; + int aaa[x][x][x]; + int b[x - 4]; + int c[(int) di]; + int d[1 + x]; + int e[1 ? x : -1]; + int f[++x]; + int g[(signed char) --x]; + int h[(++x, --x, x)]; + int i[v]; + int j[bar ()]; + + return 0; +} + +/* { dg-output "variable length array bound evaluates to non-positive value -1(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value -1(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value -1(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value -1(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value -1(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value -1(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value -5(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value -3(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value 0(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value -1(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value 0(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value -1(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value -1(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value -666(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value -42(\n|\r\n|\r)" } */ diff --git a/gcc/testsuite/c-c++-common/ubsan/vla-2.c b/gcc/testsuite/c-c++-common/ubsan/vla-2.c new file mode 100644 index 00000000000..2fbeb7113b8 --- /dev/null +++ b/gcc/testsuite/c-c++-common/ubsan/vla-2.c @@ -0,0 +1,15 @@ +/* { dg-do run } */ +/* { dg-options "-fsanitize=vla-bound -w" } */ + +int +main (void) +{ + const int t = 0; + struct s { + int x; + /* Don't instrument this one. */ + int g[t]; + }; + + return 0; +} diff --git a/gcc/testsuite/c-c++-common/ubsan/vla-3.c b/gcc/testsuite/c-c++-common/ubsan/vla-3.c new file mode 100644 index 00000000000..20dd38b79a7 --- /dev/null +++ b/gcc/testsuite/c-c++-common/ubsan/vla-3.c @@ -0,0 +1,16 @@ +/* { dg-do run } */ +/* { dg-options "-fsanitize=vla-bound -w" } */ + +/* Don't instrument the arrays here. */ +int +foo (int n, int a[]) +{ + return a[n - 1]; +} + +int +main (void) +{ + int a[6] = { }; + return foo (3, a); +} diff --git a/gcc/testsuite/c-c++-common/ubsan/vla-4.c b/gcc/testsuite/c-c++-common/ubsan/vla-4.c new file mode 100644 index 00000000000..3f7dd1de50c --- /dev/null +++ b/gcc/testsuite/c-c++-common/ubsan/vla-4.c @@ -0,0 +1,13 @@ +/* { dg-do run } */ +/* { dg-options "-fsanitize=vla-bound" } */ + +int +main (void) +{ + int x = 1; + /* Check that the size of an array is evaluated only once. */ + int a[++x]; + if (x != 2) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/g++.dg/cpp0x/Wliteral-suffix.C b/gcc/testsuite/g++.dg/cpp0x/Wliteral-suffix.C index 39a8353561c..520d77ef5c5 100644 --- a/gcc/testsuite/g++.dg/cpp0x/Wliteral-suffix.C +++ b/gcc/testsuite/g++.dg/cpp0x/Wliteral-suffix.C @@ -1,5 +1,5 @@ // { dg-do run } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // Make sure -Wliteral-suffix is enabled by default and // triggers as expected. diff --git a/gcc/testsuite/g++.dg/cpp0x/Wzero-as-null-pointer-constant-1.C b/gcc/testsuite/g++.dg/cpp0x/Wzero-as-null-pointer-constant-1.C index aad273792ac..9acfafe2be9 100644 --- a/gcc/testsuite/g++.dg/cpp0x/Wzero-as-null-pointer-constant-1.C +++ b/gcc/testsuite/g++.dg/cpp0x/Wzero-as-null-pointer-constant-1.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x -Wzero-as-null-pointer-constant" } +// { dg-options "-std=c++11 -Wzero-as-null-pointer-constant" } struct A; diff --git a/gcc/testsuite/g++.dg/cpp0x/__func__.C b/gcc/testsuite/g++.dg/cpp0x/__func__.C index 1ac90651533..a7d5633614a 100644 --- a/gcc/testsuite/g++.dg/cpp0x/__func__.C +++ b/gcc/testsuite/g++.dg/cpp0x/__func__.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x -pedantic" } +// { dg-options "-std=c++11 -pedantic" } const char* foo() { diff --git a/gcc/testsuite/g++.dg/cpp0x/access01.C b/gcc/testsuite/g++.dg/cpp0x/access01.C index 43e5e863720..a6c86016146 100644 --- a/gcc/testsuite/g++.dg/cpp0x/access01.C +++ b/gcc/testsuite/g++.dg/cpp0x/access01.C @@ -1,5 +1,5 @@ // PR c++/49042 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template <class T> class A diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-0.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-0.C index f38f9932b44..7f5d361a627 100644 --- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-0.C +++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-0.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<template<class> class TT> struct X { }; template<class> struct Y { }; diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-1.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-1.C index cbba90fa133..e3704d39f4a 100644 --- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-1.C +++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-1.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // These also represent tests for printing alias declarations and // their instantiations. diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-10.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-10.C index 733e791c2bc..b4e80f411c0 100644 --- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-10.C +++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-10.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template <class T> using Ptr = T*; Ptr<unsigned>; // { dg-error "does not declare anything" } diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-11.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-11.C index 43ef7ba45e6..80795a8304d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-11.C +++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-11.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } namespace N { diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-12.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-12.C index 11c26865d9e..758d180e1f9 100644 --- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-12.C +++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-12.C @@ -1,4 +1,4 @@ // Origin: PR c++/51027 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } using INT = int // { dg-error "expected|;|at end of input" } diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-13.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-13.C index 8555154c634..a7a55ddc168 100644 --- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-13.C +++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-13.C @@ -1,5 +1,5 @@ // Origin PR c++/51191 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template< class T > class ClassTemplate {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-14.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-14.C index 1a998022adc..9e6b19cde93 100644 --- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-14.C +++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-14.C @@ -1,5 +1,5 @@ // Origin: PR c++/51145 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } struct A {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-15.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-15.C index b23e4029f79..6ef8bf7eb4a 100644 --- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-15.C +++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-15.C @@ -1,5 +1,5 @@ // Origin PR c++/51194 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<class U, class V> //#1 struct foo {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-2.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-2.C index 6b5b42f7fde..d8a71a48107 100644 --- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-2.C +++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-2.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<class T> struct S0 {}; template<class T> using AS0 = S0<T>; diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-3.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-3.C index 5484efce19e..072cfb1f03a 100644 --- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-3.C +++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-3.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // Exercise some member alias templates ... diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-4.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-4.C index 876944e23c3..c7da542189f 100644 --- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-4.C +++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-4.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // [temp.alias]/3: // The type-id in an alias template declaration shall not refer diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-5.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-5.C index 1a4cbd5e5bc..f57a67a0459 100644 --- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-5.C +++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-5.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // alias template of a partial specialization diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-6.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-6.C index f60b2ea7fc0..11440385c33 100644 --- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-6.C +++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-6.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // Alias template of non-class types. diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-7.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-7.C index 96c349a0da6..a1a6a362ec3 100644 --- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-7.C +++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-7.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // Add arguments to unbound template template parameter. diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-8.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-8.C index c926df7539b..80c2fdd6743 100644 --- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-8.C +++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-8.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } struct A { template <class U> using C = U; diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-9.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-9.C index dcf642d7683..b4a23d0b853 100644 --- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-9.C +++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-9.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template <class T> struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-debug-0.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-debug-0.C index a9aae374947..04e9b7065bf 100644 --- a/gcc/testsuite/g++.dg/cpp0x/alias-decl-debug-0.C +++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-debug-0.C @@ -1,6 +1,6 @@ // Origin: PR c++/51032 // { dg-skip-if "No stabs" { aarch64*-*-* mmix-*-* *-*-aix* alpha*-*-* hppa*64*-*-* ia64-*-* *-*-vxworks* } { "*" } { "" } } -// { dg-options "-std=c++0x -gstabs+" } +// { dg-options "-std=c++11 -gstabs+" } template <class C> struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/alignof.C b/gcc/testsuite/g++.dg/cpp0x/alignof.C index 8e8f715cdf3..a0a556131ca 100644 --- a/gcc/testsuite/g++.dg/cpp0x/alignof.C +++ b/gcc/testsuite/g++.dg/cpp0x/alignof.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } int main(void) { static_assert(alignof(int) == __alignof(int), "alignof(int) does not equal __alignof(int)"); diff --git a/gcc/testsuite/g++.dg/cpp0x/alignof2.C b/gcc/testsuite/g++.dg/cpp0x/alignof2.C index 7c5aad3de29..9683a1eb613 100644 --- a/gcc/testsuite/g++.dg/cpp0x/alignof2.C +++ b/gcc/testsuite/g++.dg/cpp0x/alignof2.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=c++0x -pedantic" } +// { dg-options "-std=c++11 -pedantic" } int main(void) { alignof(int); //ok with a type but not with an expression diff --git a/gcc/testsuite/g++.dg/cpp0x/alignof3.C b/gcc/testsuite/g++.dg/cpp0x/alignof3.C index 50c6ac915e1..75eff1f8ae0 100644 --- a/gcc/testsuite/g++.dg/cpp0x/alignof3.C +++ b/gcc/testsuite/g++.dg/cpp0x/alignof3.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=c++0x -pedantic" } +// { dg-options "-std=c++11 -pedantic" } int main(void) { alignof(void (void)); // { dg-warning "function type" } diff --git a/gcc/testsuite/g++.dg/cpp0x/alignof4.C b/gcc/testsuite/g++.dg/cpp0x/alignof4.C index 92d636faf09..a05baa89295 100644 --- a/gcc/testsuite/g++.dg/cpp0x/alignof4.C +++ b/gcc/testsuite/g++.dg/cpp0x/alignof4.C @@ -1,5 +1,5 @@ // PR c++/51316 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } int main() { diff --git a/gcc/testsuite/g++.dg/cpp0x/auto10.C b/gcc/testsuite/g++.dg/cpp0x/auto10.C index 9b89291d640..82e98ff8adc 100644 --- a/gcc/testsuite/g++.dg/cpp0x/auto10.C +++ b/gcc/testsuite/g++.dg/cpp0x/auto10.C @@ -1,6 +1,6 @@ // Positive test for auto // { dg-do run } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } #include <typeinfo> extern "C" void abort(); diff --git a/gcc/testsuite/g++.dg/cpp0x/auto11.C b/gcc/testsuite/g++.dg/cpp0x/auto11.C index bd21daef0c6..05f5f5c20ef 100644 --- a/gcc/testsuite/g++.dg/cpp0x/auto11.C +++ b/gcc/testsuite/g++.dg/cpp0x/auto11.C @@ -1,5 +1,5 @@ // PR c++/38256 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<int> struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/auto14.C b/gcc/testsuite/g++.dg/cpp0x/auto14.C index cb2c4e0351a..726fa05651d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/auto14.C +++ b/gcc/testsuite/g++.dg/cpp0x/auto14.C @@ -1,5 +1,5 @@ // PR c++/40306, c++/40307 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // { dg-do run } template< typename T > diff --git a/gcc/testsuite/g++.dg/cpp0x/auto15.C b/gcc/testsuite/g++.dg/cpp0x/auto15.C index b23e1e2fd6f..1dca688a6ed 100644 --- a/gcc/testsuite/g++.dg/cpp0x/auto15.C +++ b/gcc/testsuite/g++.dg/cpp0x/auto15.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template< typename Fn > struct function; diff --git a/gcc/testsuite/g++.dg/cpp0x/auto16.C b/gcc/testsuite/g++.dg/cpp0x/auto16.C index 1b4ae8f82b2..3610662b951 100644 --- a/gcc/testsuite/g++.dg/cpp0x/auto16.C +++ b/gcc/testsuite/g++.dg/cpp0x/auto16.C @@ -1,5 +1,5 @@ // PR c++/40619 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<typename U> struct X {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/auto17.C b/gcc/testsuite/g++.dg/cpp0x/auto17.C index 03608d33ac6..f04b89f30ce 100644 --- a/gcc/testsuite/g++.dg/cpp0x/auto17.C +++ b/gcc/testsuite/g++.dg/cpp0x/auto17.C @@ -1,5 +1,5 @@ // PR c++/42567 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<typename B> struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/auto18.C b/gcc/testsuite/g++.dg/cpp0x/auto18.C index 0a59242ab29..a5c521c685b 100644 --- a/gcc/testsuite/g++.dg/cpp0x/auto18.C +++ b/gcc/testsuite/g++.dg/cpp0x/auto18.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } void f() { diff --git a/gcc/testsuite/g++.dg/cpp0x/auto19.C b/gcc/testsuite/g++.dg/cpp0x/auto19.C index f7099028710..66c0cfe0528 100644 --- a/gcc/testsuite/g++.dg/cpp0x/auto19.C +++ b/gcc/testsuite/g++.dg/cpp0x/auto19.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct Explicit { Explicit() = default; // Line 2 diff --git a/gcc/testsuite/g++.dg/cpp0x/auto2.C b/gcc/testsuite/g++.dg/cpp0x/auto2.C index 626e9e245d4..cf6bcffbedf 100644 --- a/gcc/testsuite/g++.dg/cpp0x/auto2.C +++ b/gcc/testsuite/g++.dg/cpp0x/auto2.C @@ -1,6 +1,6 @@ // Positive test for auto // { dg-do run } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } #include <typeinfo> extern "C" void abort(); diff --git a/gcc/testsuite/g++.dg/cpp0x/auto20.C b/gcc/testsuite/g++.dg/cpp0x/auto20.C index 90f875114a0..8561b3d4a8a 100644 --- a/gcc/testsuite/g++.dg/cpp0x/auto20.C +++ b/gcc/testsuite/g++.dg/cpp0x/auto20.C @@ -1,6 +1,6 @@ // Test for proper non-deduced context handling of the initializer // for an auto declaration/new. -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct with_apply { diff --git a/gcc/testsuite/g++.dg/cpp0x/auto21.C b/gcc/testsuite/g++.dg/cpp0x/auto21.C index 1cbcac58d6a..1d022b390e8 100644 --- a/gcc/testsuite/g++.dg/cpp0x/auto21.C +++ b/gcc/testsuite/g++.dg/cpp0x/auto21.C @@ -1,5 +1,5 @@ // Origin PR c++/47208 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } constexpr auto list = { }; // { dg-error "deducing from brace-enclosed initializer list requires #include <initializer_list>" } static const int l = list.size(); diff --git a/gcc/testsuite/g++.dg/cpp0x/auto22.C b/gcc/testsuite/g++.dg/cpp0x/auto22.C index 66630e5367f..30111783624 100644 --- a/gcc/testsuite/g++.dg/cpp0x/auto22.C +++ b/gcc/testsuite/g++.dg/cpp0x/auto22.C @@ -1,5 +1,5 @@ // PR c++/47999 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } int& identity(int& i) { diff --git a/gcc/testsuite/g++.dg/cpp0x/auto23.C b/gcc/testsuite/g++.dg/cpp0x/auto23.C index 49b5a0eb9e8..799445c8c3f 100644 --- a/gcc/testsuite/g++.dg/cpp0x/auto23.C +++ b/gcc/testsuite/g++.dg/cpp0x/auto23.C @@ -1,4 +1,4 @@ // PR c++/46245 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<auto f()->int> struct A { }; diff --git a/gcc/testsuite/g++.dg/cpp0x/auto24.C b/gcc/testsuite/g++.dg/cpp0x/auto24.C index b024ad5b2ab..3911c5887d4 100644 --- a/gcc/testsuite/g++.dg/cpp0x/auto24.C +++ b/gcc/testsuite/g++.dg/cpp0x/auto24.C @@ -1,5 +1,5 @@ // PR c++/48599 -// { dg-options "-std=c++0x -pedantic-errors" } +// { dg-options "-std=c++11 -pedantic-errors" } int v[1]; auto (*p)[1] = &v; // { dg-error "array of .auto" } diff --git a/gcc/testsuite/g++.dg/cpp0x/auto25.C b/gcc/testsuite/g++.dg/cpp0x/auto25.C index 2917c0e1978..0153d9c96fb 100644 --- a/gcc/testsuite/g++.dg/cpp0x/auto25.C +++ b/gcc/testsuite/g++.dg/cpp0x/auto25.C @@ -1,5 +1,5 @@ // PR c++/42056 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<int> struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/auto26.C b/gcc/testsuite/g++.dg/cpp0x/auto26.C index 6e55aa451ac..9d0c89426d3 100644 --- a/gcc/testsuite/g++.dg/cpp0x/auto26.C +++ b/gcc/testsuite/g++.dg/cpp0x/auto26.C @@ -1,5 +1,5 @@ // PR c++/43321 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template <class T> void f(T t) diff --git a/gcc/testsuite/g++.dg/cpp0x/auto28.C b/gcc/testsuite/g++.dg/cpp0x/auto28.C index 8d250166a8c..1d6f0d0293d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/auto28.C +++ b/gcc/testsuite/g++.dg/cpp0x/auto28.C @@ -1,4 +1,4 @@ // PR c++/51404 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } int i = auto().x; // { dg-error "invalid use of" } diff --git a/gcc/testsuite/g++.dg/cpp0x/auto4.C b/gcc/testsuite/g++.dg/cpp0x/auto4.C index d47bca4369d..71b0dede29a 100644 --- a/gcc/testsuite/g++.dg/cpp0x/auto4.C +++ b/gcc/testsuite/g++.dg/cpp0x/auto4.C @@ -1,6 +1,6 @@ // Testcase for deduction of std::initializer_list for auto. // { dg-do run } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } #include <typeinfo> #include <initializer_list> diff --git a/gcc/testsuite/g++.dg/cpp0x/auto40.C b/gcc/testsuite/g++.dg/cpp0x/auto40.C new file mode 100644 index 00000000000..287191e5910 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/auto40.C @@ -0,0 +1,11 @@ +// PR c++/58888 +// { dg-do compile { target c++11 } } + +#include <initializer_list> + +struct A +{ + static constexpr auto b{1.0}; +}; + +constexpr decltype(A::b) A::b; diff --git a/gcc/testsuite/g++.dg/cpp0x/auto5.C b/gcc/testsuite/g++.dg/cpp0x/auto5.C index ebe2df22e6f..b5dd0d8a02c 100644 --- a/gcc/testsuite/g++.dg/cpp0x/auto5.C +++ b/gcc/testsuite/g++.dg/cpp0x/auto5.C @@ -1,5 +1,5 @@ // Testcase for non-dependent auto in templates -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/auto7.C b/gcc/testsuite/g++.dg/cpp0x/auto7.C index 3b3b8290168..d795c23baa5 100644 --- a/gcc/testsuite/g++.dg/cpp0x/auto7.C +++ b/gcc/testsuite/g++.dg/cpp0x/auto7.C @@ -1,6 +1,6 @@ // PR c++/37965 // Negative test for auto -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } auto i = 6; auto j; // { dg-error "has no initializer" } diff --git a/gcc/testsuite/g++.dg/cpp0x/auto9.C b/gcc/testsuite/g++.dg/cpp0x/auto9.C index f357f2b9663..ee6497921cd 100644 --- a/gcc/testsuite/g++.dg/cpp0x/auto9.C +++ b/gcc/testsuite/g++.dg/cpp0x/auto9.C @@ -1,7 +1,7 @@ // PR c++/37962 // Negative test for auto // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } #include <typeinfo> #include <stdarg.h> diff --git a/gcc/testsuite/g++.dg/cpp0x/bind.C b/gcc/testsuite/g++.dg/cpp0x/bind.C index 42a2ac203db..a0ce6b8ff62 100644 --- a/gcc/testsuite/g++.dg/cpp0x/bind.C +++ b/gcc/testsuite/g++.dg/cpp0x/bind.C @@ -1,4 +1,4 @@ -// { dg-options "--std=c++0x" } +// { dg-options "--std=c++11" } struct S{}; void f(S&&); diff --git a/gcc/testsuite/g++.dg/cpp0x/bracket1.C b/gcc/testsuite/g++.dg/cpp0x/bracket1.C index dfb5bf4ea40..abda4034374 100644 --- a/gcc/testsuite/g++.dg/cpp0x/bracket1.C +++ b/gcc/testsuite/g++.dg/cpp0x/bracket1.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename T> struct list {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/bracket2.C b/gcc/testsuite/g++.dg/cpp0x/bracket2.C index 300015d01e6..65cf2699c92 100644 --- a/gcc/testsuite/g++.dg/cpp0x/bracket2.C +++ b/gcc/testsuite/g++.dg/cpp0x/bracket2.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<int i> class X { /* ... */ }; X< 1>2 > x1; // // { dg-error "numeric constant" } diff --git a/gcc/testsuite/g++.dg/cpp0x/bracket4.C b/gcc/testsuite/g++.dg/cpp0x/bracket4.C index 0e1985ceff9..e6381c74c84 100644 --- a/gcc/testsuite/g++.dg/cpp0x/bracket4.C +++ b/gcc/testsuite/g++.dg/cpp0x/bracket4.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<typename T> struct vector { }; diff --git a/gcc/testsuite/g++.dg/cpp0x/cast-bug.C b/gcc/testsuite/g++.dg/cpp0x/cast-bug.C index 211f88b2b19..5485611dc65 100644 --- a/gcc/testsuite/g++.dg/cpp0x/cast-bug.C +++ b/gcc/testsuite/g++.dg/cpp0x/cast-bug.C @@ -1,4 +1,4 @@ -// { dg-options "--std=c++0x" } +// { dg-options "--std=c++11" } struct S { S(); diff --git a/gcc/testsuite/g++.dg/cpp0x/cast.C b/gcc/testsuite/g++.dg/cpp0x/cast.C index 9cf97e688b0..2f109762c26 100644 --- a/gcc/testsuite/g++.dg/cpp0x/cast.C +++ b/gcc/testsuite/g++.dg/cpp0x/cast.C @@ -3,7 +3,7 @@ // Test cast from lvalue to rvalue // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // { dg-skip-if "packed attribute missing for struct one" { "epiphany-*-*" } { "*" } { "" } } template <bool> struct sa; diff --git a/gcc/testsuite/g++.dg/cpp0x/collapse-bug.C b/gcc/testsuite/g++.dg/cpp0x/collapse-bug.C index 02a59cd1d21..93f2c9fc9b6 100644 --- a/gcc/testsuite/g++.dg/cpp0x/collapse-bug.C +++ b/gcc/testsuite/g++.dg/cpp0x/collapse-bug.C @@ -1,4 +1,4 @@ -// { dg-options "--std=c++0x" } +// { dg-options "--std=c++11" } template<typename T, typename U> struct same_type; template<typename T> struct same_type<T, T> {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/collapse.C b/gcc/testsuite/g++.dg/cpp0x/collapse.C index 96c32732461..98435f159d7 100644 --- a/gcc/testsuite/g++.dg/cpp0x/collapse.C +++ b/gcc/testsuite/g++.dg/cpp0x/collapse.C @@ -1,4 +1,4 @@ -// { dg-options "--std=c++0x" } +// { dg-options "--std=c++11" } template<typename T, typename U> struct same_type; template<typename T> struct same_type<T, T> {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-46336.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-46336.C index 3c51c2cbf54..4268a6ba43a 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-46336.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-46336.C @@ -1,5 +1,5 @@ // PR c++/46336 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } extern "C" { enum A { }; diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-46420.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-46420.C index 757a6e315b0..c59949aa68e 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-46420.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-46420.C @@ -1,5 +1,5 @@ // PR c++/46420 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<typename> class vector { }; struct A{}; diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-47570.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-47570.C index c60ba865862..53c20a62382 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-47570.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-47570.C @@ -1,5 +1,5 @@ // PR c++/47570 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } unsigned int constexpr one() { return 1; } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-47969.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-47969.C index c950a3642fe..140965150a1 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-47969.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-47969.C @@ -1,5 +1,5 @@ // PR c++/47969 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-48089.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-48089.C index a6cf4080756..039411ef58d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-48089.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-48089.C @@ -1,5 +1,5 @@ // PR c++/48089 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } // bang is ill-formed (diagnostic required) because its initializer is // non-constant, because it uses the value of an uninitialized object. diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-49776.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-49776.C index 3fe3dcb86c1..8f407191192 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-49776.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-49776.C @@ -1,5 +1,5 @@ // PR c++/49776 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct s { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-abi1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-abi1.C index e83f142300a..c596a4386a9 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-abi1.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-abi1.C @@ -1,5 +1,5 @@ // PR c++/47301 -// { dg-options "-std=c++0x -fabi-version=1" } +// { dg-options "-std=c++11 -fabi-version=1" } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-access.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-access.C index ee5fc9854fc..3cde1efa914 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-access.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-access.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } class base { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr.C index 36939e1afe1..db95e569492 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<class T> constexpr T do_get(T* x, int n) { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr2.C index 7cf733445d9..23c6ebdaf6a 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr2.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr2.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<class T> struct IsNegative { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr3.C index f84cb525774..a282b85490b 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr3.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr3.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } constexpr bool is_negative(int x) { return x < 0; diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr4.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr4.C index 697d2d9f708..f530265863d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr4.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr4.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } constexpr const int do_last(const int* x, int n) { return x[n - 1]; diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr5.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr5.C index d58f254f6c8..20b6344e490 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr5.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr5.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<class T> constexpr T do_last(T* x, int n) { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr6.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr6.C index 17dd6e50be9..c307edba6e1 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr6.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr6.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } typedef decltype(sizeof(char)) size_type; diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr7.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr7.C index 44775c0703c..7c83178a9b5 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr7.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-ptr7.C @@ -1,5 +1,5 @@ // PR c++/49290 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } typedef unsigned T; struct S diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-tparm.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-tparm.C index c17090cc3b4..4b6a3df1892 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-array-tparm.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array-tparm.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template <const int I[2]> struct A { int ir[I[0]]; }; extern constexpr int ar[2] = { 1, 2 }; diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array.C index e37400a8bda..f2c8ddcc966 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-array.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } // { dg-final { scan-assembler-not "static_initialization" } } struct A diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array2.C index 9577f75d9fd..4f556ae6661 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-array2.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array2.C @@ -1,5 +1,5 @@ // PR c++/46348 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<__SIZE_TYPE__ _Nw> struct _Base diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array3.C index 145a4307e36..38314ec0f5f 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-array3.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array3.C @@ -1,5 +1,5 @@ // PR c++/48132 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct C { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array4.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array4.C index 9aeb75d6b06..0658be9011f 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-array4.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array4.C @@ -1,5 +1,5 @@ // PR c++/49924 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { constexpr A() { } }; diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-attribute.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-attribute.C index ac85c076d3e..fef7007cf0c 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-attribute.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-attribute.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } //A few constexpr's constexpr int foo() { return __alignof__(int); } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-auto.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-auto.C index ddf0da0b9b4..60bd5589745 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-auto.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-auto.C @@ -1,2 +1,2 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } constexpr auto value = 0; diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-base.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-base.C index 774df318ab6..b159bb8dba4 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-base.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-base.C @@ -1,5 +1,5 @@ // Test base/member class and static_assert with constexpr -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { int i; diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-base2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-base2.C index 3ea75432a22..9849f206c54 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-base2.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-base2.C @@ -1,5 +1,5 @@ // PR c++/46293 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-base3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-base3.C index cffe9ea240c..ec6646bc560 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-base3.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-base3.C @@ -1,6 +1,6 @@ // PR c++/46526 // { dg-do run } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } struct Base { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-base4.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-base4.C index ce23cb9dd10..8a061bfd27e 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-base4.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-base4.C @@ -1,6 +1,6 @@ // PR c++/46626 // { dg-do run } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-bitfield.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-bitfield.C index 7eba49833f2..5025f4782d1 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-bitfield.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-bitfield.C @@ -1,5 +1,5 @@ // PR c++/46369 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-bitfield2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-bitfield2.C index 531bf31fc01..6ad5aeab586 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-bitfield2.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-bitfield2.C @@ -1,6 +1,6 @@ // PR c++/49136 // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } struct day { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-bitfield3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-bitfield3.C index b0ecbfb9abb..6b20e707f7b 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-bitfield3.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-bitfield3.C @@ -1,6 +1,6 @@ // PR c++/49136 // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } struct S { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-builtin1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-builtin1.C index b3f5576360b..ef2762e7cdb 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-builtin1.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-builtin1.C @@ -1,5 +1,5 @@ // PR c++/49813 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } inline constexpr bool isinf(long double __x) diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-cache1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-cache1.C index b6d7b647139..7c128df7b1b 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-cache1.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-cache1.C @@ -1,5 +1,5 @@ // PR c++/51433 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } constexpr int f(); constexpr int g() { return f(); } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-cleanup.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-cleanup.C index de17f3ddb25..ff86b1bdbce 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-cleanup.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-cleanup.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-complex.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-complex.C index eee773ef308..0d4ea010cb3 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-complex.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-complex.C @@ -1,5 +1,5 @@ // Make sure C99 complex works with constexpr -// { dg-options -std=gnu++0x } +// { dg-options -std=gnu++11 } struct complex { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-compound.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-compound.C index 81fcc54b3e6..006a8c77613 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-compound.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-compound.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x -pedantic-errors" } +// { dg-options "-std=c++11 -pedantic-errors" } constexpr int f() { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-condition.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-condition.C index e2328fcc578..dd47a79433d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-condition.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-condition.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } // Core DR 948 constexpr int something() { return 3; } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-condition2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-condition2.C index 243409669bf..855c8dcea2a 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-condition2.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-condition2.C @@ -1,5 +1,5 @@ // PR c++/48909 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } #define SA(X) static_assert((X),#X) diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor.C index 91c489db230..23076b3ac34 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor2.C index 5280b131b7b..02333734bb2 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor2.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor2.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor3.C index d5bfbad3d67..23159839c01 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor3.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor3.C @@ -1,5 +1,5 @@ // PR c++/46348 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor4.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor4.C index 397b4b054ef..96b99e320ad 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor4.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor4.C @@ -1,5 +1,5 @@ // PR c++/46873 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct S { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor5.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor5.C index 36b01785fee..63d4b151d71 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor5.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor5.C @@ -1,5 +1,5 @@ // PR c++/46877 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct new_allocator { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor6.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor6.C index 4f86f73a458..40512975003 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor6.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor6.C @@ -1,5 +1,5 @@ // PR c++/47041 -// { dg-options "-std=c++0x -fno-elide-constructors" } +// { dg-options "-std=c++11 -fno-elide-constructors" } struct S { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor7.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor7.C index 8338bf1f7ec..8a65ad2f34e 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor7.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor7.C @@ -1,5 +1,5 @@ // PR c++/47199 -// { dg-options "-std=c++0x -fno-elide-constructors" } +// { dg-options "-std=c++11 -fno-elide-constructors" } template < int > struct S { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor8.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor8.C index 81fc83737bc..4d204a17336 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor8.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor8.C @@ -1,5 +1,5 @@ // PR c++/46466 -// { dg-options "-std=c++0x -fno-elide-constructors" } +// { dg-options "-std=c++11 -fno-elide-constructors" } struct S { bool b; }; constexpr S f() { return S{true}; } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor9.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor9.C index b7693f1e637..9d7e88de0de 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor9.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ctor9.C @@ -1,5 +1,5 @@ // PR c++/47774 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-data1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-data1.C index 0943fa4225d..f2a4d443514 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-data1.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-data1.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } // From N2235 diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-data2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-data2.C index 2d614ec32ed..47967ab416e 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-data2.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-data2.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename _Tp, _Tp v> struct A3 diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-decl.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-decl.C index 8c46fab3334..1af0662ff53 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-decl.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-decl.C @@ -1,5 +1,5 @@ // PR c++/46930 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct S { static constexpr int size; // { dg-error "must have an initializer" "must have" } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-defarg.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-defarg.C index 1413b24bd84..22ccedd1359 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-defarg.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-defarg.C @@ -1,5 +1,5 @@ // PR c++/46335 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct T { }; struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-defarg2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-defarg2.C index faa8a3603ff..4a02336647c 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-defarg2.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-defarg2.C @@ -1,5 +1,5 @@ // PR c++/46368 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } class A; diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-default-ctor.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-default-ctor.C index d3868b599ac..02f695853db 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-default-ctor.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-default-ctor.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { int i; diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-delegating.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-delegating.C index a0208887671..571e58f3de6 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-delegating.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-delegating.C @@ -1,5 +1,5 @@ // PR c++/51526 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } const int j = 42; diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-delegating2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-delegating2.C index c85ed2e8191..8115baa1aa1 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-delegating2.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-delegating2.C @@ -1,5 +1,5 @@ // PR c++/51723 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template <int... V> struct A diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-delete.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-delete.C index 67c9503025b..5eb478d851c 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-delete.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-delete.C @@ -1,3 +1,3 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } constexpr bool never() = delete; // useless, but OK diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-deref.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-deref.C index 7363e98ecb8..29adab9f23e 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-deref.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-deref.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-diag1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-diag1.C index cbd4983e84b..21213eb5eb4 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-diag1.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-diag1.C @@ -1,5 +1,5 @@ // Test that we explain why a template instantiation isn't constexpr -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template <class T> struct A diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-diag2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-diag2.C index c78416ec1a3..161b5a7bdfb 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-diag2.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-diag2.C @@ -1,5 +1,5 @@ // PR c++/47207 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } constexpr int X (X); // { dg-error "not usable" } // { dg-message "own initializer" "" { target *-*-* } 4 } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C index 100c17edb45..0a0887fd6c1 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C @@ -1,5 +1,5 @@ // PR c++/45923 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } int f(int); diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-eh-spec.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-eh-spec.C index 6d231fafadb..45fee3bc032 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-eh-spec.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-eh-spec.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<class T> class my_limits { public: static constexpr T min() throw() { return T(); } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ellipsis.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ellipsis.C index 5d090b541d4..55f8fa5322f 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ellipsis.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ellipsis.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } constexpr int ellipsis(...) { return 1; } constexpr int ellipsis_c = ellipsis(); // OK diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ellipsis2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ellipsis2.C index 0bb6904061f..d6b44828e15 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ellipsis2.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ellipsis2.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-empty.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-empty.C index a9fc4388a34..6a5565fc3f4 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-empty.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-empty.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct Empty {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-empty2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-empty2.C index ef212119447..5e6694d9953 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-empty2.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-empty2.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct IsLiteral {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-empty3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-empty3.C index e0026fcc760..133ad42e36d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-empty3.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-empty3.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct IsLiteral {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-empty4.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-empty4.C index b07f924649d..3b7380d1284 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-empty4.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-empty4.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } typedef decltype(sizeof(char)) size_type; diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-empty5.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-empty5.C index 9bd9aa583dc..f693cc196f6 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-empty5.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-empty5.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { }; struct B: A { }; diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ex1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ex1.C index 3df7956fd28..acf8bccc176 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ex1.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ex1.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } // From N2235 diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ex2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ex2.C index 29e835c4bbb..a760a729022 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ex2.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ex2.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } // From N2235 diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ex3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ex3.C index 5c0b1e21cb7..1cda29b3b8d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ex3.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ex3.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x -ftrack-macro-expansion=0" } +// { dg-options "-std=c++11 -ftrack-macro-expansion=0" } #define SA(X) static_assert (X, #X) diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ex4.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ex4.C index 4214f5c52de..13089043c3b 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ex4.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ex4.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-expinst.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-expinst.C index 20898736983..d8ba4193e7c 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-expinst.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-expinst.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } // Error: Explicit instantiation of a function template shall not use the // inline or constexpr specifiers template<class T> constexpr inline T bar(T x) { return x; } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-explicit-inst.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-explicit-inst.C index 8f0da0af0c5..65210417226 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-explicit-inst.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-explicit-inst.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<class T> constexpr inline T bar(T x) { return x; } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-fnptr.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-fnptr.C index 4c84d827f07..a81ce5a1378 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-fnptr.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-fnptr.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } constexpr bool is_negative(int x) { return x < 0; } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-friend.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-friend.C index 57782cf349a..ee35f1ff98a 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-friend.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-friend.C @@ -1,5 +1,5 @@ // PR c++/48948 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { A(); }; diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-function1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-function1.C index c708b040f80..e4cddf7ea96 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-function1.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-function1.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } // From N2235 diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-function2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-function2.C index 6403ea16e87..5dda09305db 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-function2.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-function2.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } // From N2235 diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-function3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-function3.C index e8ca7bc68c9..bd35e97d1b8 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-function3.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-function3.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } // From N2235 diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-generated1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-generated1.C index 73ddc8f5c2e..e66d33286f1 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-generated1.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-generated1.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template <class T> struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ice.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ice.C index 3b72484a005..aca701531a1 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ice.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ice.C @@ -1,5 +1,5 @@ // We used to crash on this instead of giving a decent error. -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { int i; }; diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ice2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ice2.C index 856246fcc95..952c6fdcc4c 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ice2.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ice2.C @@ -1,3 +1,3 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } int x; constexpr int& rx = x; diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ice3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ice3.C index 23903bca78d..1a66840080e 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ice3.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ice3.C @@ -1,5 +1,5 @@ // PR c++/46289 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ice4.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ice4.C index e1ee36dfc90..35109e8d04f 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ice4.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ice4.C @@ -1,5 +1,5 @@ // PR c++/51612 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ice5.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ice5.C index b88ec66c9f6..56936b0ba65 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ice5.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ice5.C @@ -1,5 +1,5 @@ // PR c++/51621 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ice6.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ice6.C index 1a494bb3236..3512261cd31 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ice6.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ice6.C @@ -1,5 +1,5 @@ // PR c++/51327 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-incomplete1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-incomplete1.C index 3f40e29aec0..179566ba503 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-incomplete1.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-incomplete1.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-incomplete2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-incomplete2.C index f61535f06be..96de0c37243 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-incomplete2.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-incomplete2.C @@ -1,6 +1,6 @@ // A constructor that might or might not be constexpr still makes // its class literal. -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template <class T> struct B diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-incomplete3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-incomplete3.C index 81822b07e2f..26ffd3e1fbd 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-incomplete3.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-incomplete3.C @@ -1,5 +1,5 @@ // PR c++/49015 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } class A; diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist.C index 6854e7341b7..982332b82c7 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } // { dg-do run } namespace xstd { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist2.C index f34b9801607..7a75e5ff271 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist2.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist2.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } #include <initializer_list> diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist3.C index 7620e6b2c96..4909a082976 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist3.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist3.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } #include <initializer_list> #define SA(X) static_assert(X,#X) diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist4.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist4.C index 81518575692..a45e8cdcf3c 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist4.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist4.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { int i; }; struct B: A { constexpr B(): A{} {} }; diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist5.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist5.C index 97f03999802..9ddc9f8ab36 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist5.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist5.C @@ -1,5 +1,5 @@ // PR c++/50024 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template< class T > struct Container diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-is_literal.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-is_literal.C index 82514ed865a..6423588fd7f 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-is_literal.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-is_literal.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } #include <type_traits> diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-memfn1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-memfn1.C index ef7ac6b4842..10a0aaa2f08 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-memfn1.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-memfn1.C @@ -1,5 +1,5 @@ // PR c++/48296 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct X { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-missing.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-missing.C index 547f552e377..6f1d1a23653 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-missing.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-missing.C @@ -1,6 +1,6 @@ // PR c++/48911 // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } #define SA(X) static_assert((X),#X) diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-mutable1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-mutable1.C index a14d611cee8..3d595d5d925 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-mutable1.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-mutable1.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-neg1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-neg1.C index c27615f05ad..8e1bcd0f2f9 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-neg1.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-neg1.C @@ -1,5 +1,5 @@ // Negative examples from N3092 (FCD) -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } // OK: declaration constexpr int square(int x); // { dg-message "never defined" } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept.C index 0476f909654..9e337793092 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<class T> struct is_funny { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept2.C index 95a1443fa28..e4e998b50d4 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept2.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept2.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<class T> constexpr T value(T t) { return t; } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept3.C index 6e76ea8fa0b..1cda3521897 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept3.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept3.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } constexpr int f(int i) { return i; } #define SA(X) static_assert (X, #X) diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept4.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept4.C index 119d4e16730..b19c1575acf 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept4.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept4.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } // A call is noexcept if it is a valid subexpression of a constant // expression, even if it is not itself a constant expression. diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept5.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept5.C index 7bf961b3c45..52f2040b90b 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept5.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept5.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct booleable { bool data; diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept6.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept6.C index 91e93fd91bc..56dc68308ca 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept6.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-noexcept6.C @@ -1,5 +1,5 @@ // PR c++/51305 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } constexpr bool ok() noexcept { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-non-const-arg.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-non-const-arg.C index 7637c0a05bc..c8bdb28384b 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-non-const-arg.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-non-const-arg.C @@ -1,6 +1,6 @@ // Example from issue 1125 drafting; D() and v were well-formed with the // wording approved in Rapperswil, now seems they should be ill-formed. -// { dg-options "-std=c++0x -pedantic-errors" } +// { dg-options "-std=c++11 -pedantic-errors" } struct B { constexpr B(int x) : i(0) { } // "x" is unused diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-non-const-arg2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-non-const-arg2.C index 20e05c3c068..02ec95f7e9e 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-non-const-arg2.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-non-const-arg2.C @@ -1,5 +1,5 @@ // PR c++/47200 -// { dg-options "-std=c++0x -w" } +// { dg-options "-std=c++11 -w" } template < int > struct duration { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-non-const-arg3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-non-const-arg3.C index 581be6d15ce..3a9c92c4011 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-non-const-arg3.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-non-const-arg3.C @@ -1,5 +1,5 @@ // PR c++/49988 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } // { dg-do run } template<int ... I> struct X { }; diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-nonlit.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-nonlit.C index 9104c8afac6..21036d8e7d0 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-nonlit.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-nonlit.C @@ -1,5 +1,5 @@ // FIXME this is currently invalid, but seems like it should be OK -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { A() { } }; diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-nonlit2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-nonlit2.C index 21e8bd50961..77ceefe0569 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-nonlit2.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-nonlit2.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-nonstatic.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-nonstatic.C index 3951fbdb15c..110edd4db10 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-nonstatic.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-nonstatic.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-nullptr.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-nullptr.C index 6381323cc0c..77b56af049d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-nullptr.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-nullptr.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } constexpr int zero() { return 0; } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-object1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-object1.C index 6c9d4664418..f5c319ad9d6 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-object1.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-object1.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } // From N2235 diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-object2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-object2.C index a038970f6a4..9234ad218e2 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-object2.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-object2.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } constexpr int verysquare(int x) { return x * x; } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-overflow.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-overflow.C index 3eb27aa0a88..b9f82470727 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-overflow.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-overflow.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x -w -ftrack-macro-expansion=0" } +// { dg-options "-std=c++11 -w -ftrack-macro-expansion=0" } #include <limits.h> extern constexpr int max_s = INT_MAX + 1; // { dg-error "" } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-overflow2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-overflow2.C index 5d5749ce2c3..8534f5f9376 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-overflow2.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-overflow2.C @@ -1,5 +1,5 @@ // PR c++/47504 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } char constexpr sub(char arg) { return char(arg - char(1)); } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-pedantic.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-pedantic.C index dc393d75915..84ff462abc7 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-pedantic.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-pedantic.C @@ -1,6 +1,6 @@ // The FCD doesn't allow typedefs and static_assert in constexpr functions, // but it should. -// { dg-options "-std=c++0x -pedantic" } +// { dg-options "-std=c++11 -pedantic" } template <class T> constexpr T f(T t) diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-pos1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-pos1.C index 775080acce6..c234f4a8c34 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-pos1.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-pos1.C @@ -1,5 +1,5 @@ // Positive examples from N3092 (FCD) -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } #define SA(X) static_assert(X, #X) diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-potential1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-potential1.C index e933506b8a1..85a26f0886a 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-potential1.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-potential1.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } // We decided in Rapperswil that it's OK if any value of decide can produce // a constant expression. diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ptrmem.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ptrmem.C index f6ed2f40afb..8a1c5517bd4 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ptrmem.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ptrmem.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct C { // literal type int m; diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ptrsub.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ptrsub.C index bccec73bb0b..a7c79d7456d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ptrsub.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ptrsub.C @@ -1,6 +1,6 @@ // PR c++/51489 // DR 1313 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } struct array { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-pure.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-pure.C index e17e02a4220..556b4e7cb3f 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-pure.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-pure.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-recursion.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-recursion.C index 2f9b4887df6..327efa44648 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-recursion.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-recursion.C @@ -1,5 +1,5 @@ // Test that we catch excessive recursion. -// { dg-options "-std=c++0x -fconstexpr-depth=5" } +// { dg-options "-std=c++11 -fconstexpr-depth=5" } // { dg-prune-output "in constexpr expansion" } constexpr int f (int i) { return f (i-1); } constexpr int i = f(42); // { dg-error "constexpr evaluation depth" } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ref1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ref1.C index 482e1ba3691..0c10b4b5578 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ref1.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ref1.C @@ -1,5 +1,5 @@ // PR c++/49172 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } #define SA(X) static_assert((X),#X) diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ref2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ref2.C index 2a86eb765cb..5091593056f 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ref2.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ref2.C @@ -1,5 +1,5 @@ // Negative reference variable tests. -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } extern int *p; constexpr int& ri = *p; // { dg-error "p" } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ref3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ref3.C index 24cc9c82449..37222525e60 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ref3.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ref3.C @@ -1,5 +1,5 @@ // PR c++/50298 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } int global_variable; diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ref4.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ref4.C index 6ae355a273f..c256814a3ad 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-ref4.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ref4.C @@ -1,5 +1,5 @@ // PR c++/54777 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct S { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-rom.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-rom.C index a6aa34eb2f5..0f5384a9062 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-rom.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-rom.C @@ -1,5 +1,5 @@ // PR c++/49673: check that test_data goes into .rodata -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } // { dg-additional-options -G0 { target { { alpha*-*-* frv*-*-* ia64-*-* lm32*-*-* m32r*-*-* microblaze*-*-* mips*-*-* powerpc*-*-* rs6000*-*-* score*-*-* } && { ! { *-*-darwin* *-*-aix* alpha*-*-*vms* } } } } } // { dg-final { scan-assembler "\\.rdata" { target mips*-*-* } } } // { dg-final { scan-assembler "rodata" { target { { *-*-linux-gnu *-*-gnu* *-*-elf } && { ! mips*-*-* } } } } } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-sassert.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-sassert.C index 3e08fb0efa3..b9b5003a06f 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-sassert.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-sassert.C @@ -1,5 +1,5 @@ // Allow static_assert in constexpr constructors, too. -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<typename T> struct A diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-static.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-static.C index 8ed2b5e82ed..aa96499b284 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-static.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-static.C @@ -1,5 +1,5 @@ // Test for constant initialization of non-literal class (e.g. mutex) -// { dg-options "-std=c++0x -save-temps" } +// { dg-options "-std=c++11 -save-temps" } // { dg-do run } struct A diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-static2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-static2.C index 67c35308024..2ed8147ff1d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-static2.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-static2.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct IsLiteral {}; struct ShouldBeLiteral { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-static3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-static3.C index dccdc854b39..1951edbf43b 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-static3.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-static3.C @@ -1,5 +1,5 @@ // Test for constant initialization of class with vtable -// { dg-options "-std=c++0x -save-temps" } +// { dg-options "-std=c++11 -save-temps" } // { dg-final { scan-assembler-not "static_initialization" } } // { dg-final cleanup-saved-temps } // { dg-do run } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-static4.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-static4.C index 8189fc5de47..aa060b8d43d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-static4.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-static4.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } // { dg-do run } extern "C" void abort (); diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-static5.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-static5.C index a401cc0b890..886e693d52c 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-static5.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-static5.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template <class T> struct A diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-static6.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-static6.C index a34704d839c..cf64979a9a9 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-static6.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-static6.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct B { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-static7.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-static7.C index e46ddafd702..bb333b7d897 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-static7.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-static7.C @@ -1,5 +1,5 @@ // PR c++/48945 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { static constexpr bool is(); diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-static8.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-static8.C index 7c84cf8b07b..c6fd94e9c74 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-static8.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-static8.C @@ -1,5 +1,5 @@ // PR c++/50258 -// { dg-options "-std=c++0x -fpermissive" } +// { dg-options "-std=c++11 -fpermissive" } struct Foo { static const double d = 3.14; // { dg-warning "constexpr" } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-stmtexpr.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-stmtexpr.C index 40e0c2d65d0..562cf760872 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-stmtexpr.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-stmtexpr.C @@ -1,5 +1,5 @@ // PR c++/46977 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template < typename > void foo () diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-string.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-string.C index e76d00d7e63..a7132e1c812 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-string.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-string.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } constexpr char c1 = "hi"[1]; constexpr char c2 = "hi"[2]; diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-switch.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-switch.C index d229304e419..705d3553c45 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-switch.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-switch.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<class T> constexpr T value(T t = T()) { return t; } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-switch2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-switch2.C index 55cf2ad7ce8..a59e7671979 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-switch2.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-switch2.C @@ -1,5 +1,5 @@ // Test for constexpr conversion in case context -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } enum class E { e1, e2 }; diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-synth1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-synth1.C index 9830939806b..1e7a92a82c8 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-synth1.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-synth1.C @@ -1,5 +1,5 @@ // PR c++/46472 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<class T> struct A { T t; diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-targ.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-targ.C index 0c8c73d2e1d..ba97ab7f4c2 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-targ.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-targ.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-template1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-template1.C index 88077231b0d..d109229f002 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-template1.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-template1.C @@ -1,5 +1,5 @@ // PR c++/50248, DR 1358 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<class Elt, unsigned max> struct earray diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-template2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-template2.C index 6786d1651e5..368edb50705 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-template2.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-template2.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template <class T> struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-template3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-template3.C index 75b2fc4634e..66fcb2a7726 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-template3.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-template3.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { constexpr operator int() { return 42; } }; diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-throw.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-throw.C index f1ef9dc7d0d..7f06080c476 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-throw.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-throw.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } constexpr int may_throw(bool decide) { return decide ? 42 : throw -1; // { dg-error "throw" } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-typedef1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-typedef1.C index 2719e3aea12..98f25ecf5ba 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-typedef1.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-typedef1.C @@ -1,5 +1,5 @@ // PR c++/50508 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template <class T> struct integral_constant { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-typeid.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-typeid.C index b523bb38cc1..d72dc5a3f7a 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-typeid.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-typeid.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } #include <typeinfo> diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-union.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-union.C index 3c7a7f38ec8..53cecfaeb46 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-union.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-union.C @@ -1,6 +1,6 @@ // Test that we don't have to deal with type punning // DR 1188 says this is ill-formed -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } union U { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-union2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-union2.C index 0bf2aa7e2bc..2ae7e40dacf 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-union2.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-union2.C @@ -1,5 +1,5 @@ // PR c++/51675 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } union foo { diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-using.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-using.C index fc794e9abdf..a28d15eb781 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-using.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-using.C @@ -1,5 +1,5 @@ // Core issue 898 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } namespace N { const int i = 42; } namespace M { const int j = 42; } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-using2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-using2.C index 6b282813e55..18272a6faf6 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-using2.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-using2.C @@ -1,5 +1,5 @@ // PR c++/49520 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } namespace x { void foo(); } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-value.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-value.C index 85799d90b68..2004a779d73 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-value.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-value.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct HopefullyLiteral { HopefullyLiteral() = default; // Should be a constexpr c'tor as of 12.1/6 and 8.4.2/4 diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-value2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-value2.C index 1b0e28f162d..1be6a08dda3 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-value2.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-value2.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<class T> constexpr T value_init() { return T(); } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-value3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-value3.C index 38d89936ec4..57fe868cd47 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-value3.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-value3.C @@ -1,5 +1,5 @@ // PR c++/50234 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } #define SA(X) static_assert((X),#X) diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-variadic.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-variadic.C index 5d0ad05941e..c2be3272734 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-variadic.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-variadic.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<class... T> constexpr bool variadics(T&&...) { return true; } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-virtual.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-virtual.C index 448ecb1dc70..22ad73d50c9 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-virtual.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-virtual.C @@ -1,5 +1,5 @@ // PR c++/47067 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct X { virtual void x(); diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-wstring1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-wstring1.C index 059977bfff9..0195a863fde 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-wstring1.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-wstring1.C @@ -1,6 +1,6 @@ // PR c++/48570 // { dg-do run } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } extern "C" void abort (); constexpr wchar_t foo (int i) { return L"0123"[i]; } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-wstring2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-wstring2.C index 4fc8980ef96..586e0baa5e8 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-wstring2.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-wstring2.C @@ -1,6 +1,6 @@ // PR c++/48570 // { dg-do compile } -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } constexpr wchar_t c1 = L"hi"[3]; // { dg-error "out of bound" } constexpr char16_t c2 = u"hi"[3]; // { dg-error "out of bound" } diff --git a/gcc/testsuite/g++.dg/cpp0x/dc1.C b/gcc/testsuite/g++.dg/cpp0x/dc1.C index ba2e4f4fd05..c1a5f39dce3 100644 --- a/gcc/testsuite/g++.dg/cpp0x/dc1.C +++ b/gcc/testsuite/g++.dg/cpp0x/dc1.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options --std=c++0x } +// { dg-options --std=c++11 } struct B { int i; diff --git a/gcc/testsuite/g++.dg/cpp0x/dc2.C b/gcc/testsuite/g++.dg/cpp0x/dc2.C index dda0b9fc697..227bab13705 100644 --- a/gcc/testsuite/g++.dg/cpp0x/dc2.C +++ b/gcc/testsuite/g++.dg/cpp0x/dc2.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options --std=c++0x } +// { dg-options --std=c++11 } struct A { int i, j; diff --git a/gcc/testsuite/g++.dg/cpp0x/dc3.C b/gcc/testsuite/g++.dg/cpp0x/dc3.C index b411c997d8f..c68d622d202 100644 --- a/gcc/testsuite/g++.dg/cpp0x/dc3.C +++ b/gcc/testsuite/g++.dg/cpp0x/dc3.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options --std=c++0x } +// { dg-options --std=c++11 } struct X {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/dc5.C b/gcc/testsuite/g++.dg/cpp0x/dc5.C index 0052b321113..59cf2ea1785 100644 --- a/gcc/testsuite/g++.dg/cpp0x/dc5.C +++ b/gcc/testsuite/g++.dg/cpp0x/dc5.C @@ -1,5 +1,5 @@ // { dg-do run } -// { dg-options "--std=c++0x" } +// { dg-options "--std=c++11" } #include <cassert> diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype-1212.C b/gcc/testsuite/g++.dg/cpp0x/decltype-1212.C index 38393d3b874..24bf339a516 100644 --- a/gcc/testsuite/g++.dg/cpp0x/decltype-1212.C +++ b/gcc/testsuite/g++.dg/cpp0x/decltype-1212.C @@ -1,5 +1,5 @@ // Core 1212 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template <class T, class U> struct assert_same_type; template <class T> struct assert_same_type<T,T> {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype-33837.C b/gcc/testsuite/g++.dg/cpp0x/decltype-33837.C index 2c263dd0a97..7f85bc32c92 100644 --- a/gcc/testsuite/g++.dg/cpp0x/decltype-33837.C +++ b/gcc/testsuite/g++.dg/cpp0x/decltype-33837.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } // PR c++/33837 void foo() { diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype-33838.C b/gcc/testsuite/g++.dg/cpp0x/decltype-33838.C index 260a0d1cf09..8f4a86c12ad 100644 --- a/gcc/testsuite/g++.dg/cpp0x/decltype-33838.C +++ b/gcc/testsuite/g++.dg/cpp0x/decltype-33838.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } // PR c++/33838 template<typename T> struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype-refbug.C b/gcc/testsuite/g++.dg/cpp0x/decltype-refbug.C index 8e3c8240724..d58011b2a31 100644 --- a/gcc/testsuite/g++.dg/cpp0x/decltype-refbug.C +++ b/gcc/testsuite/g++.dg/cpp0x/decltype-refbug.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // PR c++/33045 int && f (); diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype1.C b/gcc/testsuite/g++.dg/cpp0x/decltype1.C index d1288e07d93..7b268fdbca0 100644 --- a/gcc/testsuite/g++.dg/cpp0x/decltype1.C +++ b/gcc/testsuite/g++.dg/cpp0x/decltype1.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename T, typename U> struct is_same diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype10.C b/gcc/testsuite/g++.dg/cpp0x/decltype10.C index 6c488998c59..381f6363b3a 100644 --- a/gcc/testsuite/g++.dg/cpp0x/decltype10.C +++ b/gcc/testsuite/g++.dg/cpp0x/decltype10.C @@ -1,6 +1,6 @@ // PR c++/34271 // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<int> struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype11.C b/gcc/testsuite/g++.dg/cpp0x/decltype11.C index ac32d349a6c..01a65568d9e 100644 --- a/gcc/testsuite/g++.dg/cpp0x/decltype11.C +++ b/gcc/testsuite/g++.dg/cpp0x/decltype11.C @@ -1,5 +1,5 @@ // PR c++/35316 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<int> struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype12.C b/gcc/testsuite/g++.dg/cpp0x/decltype12.C index 77c794bcf09..c39f6f103cd 100644 --- a/gcc/testsuite/g++.dg/cpp0x/decltype12.C +++ b/gcc/testsuite/g++.dg/cpp0x/decltype12.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<typename T, typename U> struct is_same { diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype15.C b/gcc/testsuite/g++.dg/cpp0x/decltype15.C index 5c2d445debf..e0348ea9a38 100644 --- a/gcc/testsuite/g++.dg/cpp0x/decltype15.C +++ b/gcc/testsuite/g++.dg/cpp0x/decltype15.C @@ -1,6 +1,6 @@ // PR c++/38640 // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<int N> void foo (decltype (N)); template<long int N> void foo (decltype (N)); diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype16.C b/gcc/testsuite/g++.dg/cpp0x/decltype16.C index 2002458b851..9f2398ece1f 100644 --- a/gcc/testsuite/g++.dg/cpp0x/decltype16.C +++ b/gcc/testsuite/g++.dg/cpp0x/decltype16.C @@ -1,5 +1,5 @@ // PR c++/39070 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<typename X> struct junk { template<typename Z> static Z y(); diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype17.C b/gcc/testsuite/g++.dg/cpp0x/decltype17.C index 7f36ff01e50..c3a44535974 100644 --- a/gcc/testsuite/g++.dg/cpp0x/decltype17.C +++ b/gcc/testsuite/g++.dg/cpp0x/decltype17.C @@ -1,5 +1,5 @@ // PR c++/36628 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // { dg-do run } #include <typeinfo> diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype18.C b/gcc/testsuite/g++.dg/cpp0x/decltype18.C index 0d44586e9d2..0f639a0cdfb 100644 --- a/gcc/testsuite/g++.dg/cpp0x/decltype18.C +++ b/gcc/testsuite/g++.dg/cpp0x/decltype18.C @@ -1,5 +1,5 @@ // PR c++/37875 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template <typename> struct X {}; X<decltype(1 > 2)> x; diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype2.C b/gcc/testsuite/g++.dg/cpp0x/decltype2.C index e0c59003047..81cb56b7ed9 100644 --- a/gcc/testsuite/g++.dg/cpp0x/decltype2.C +++ b/gcc/testsuite/g++.dg/cpp0x/decltype2.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename T, typename U> struct is_same diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype20.C b/gcc/testsuite/g++.dg/cpp0x/decltype20.C index 3155cdcf86a..bba848ccc41 100644 --- a/gcc/testsuite/g++.dg/cpp0x/decltype20.C +++ b/gcc/testsuite/g++.dg/cpp0x/decltype20.C @@ -1,5 +1,5 @@ // PR c++/42277 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct S { int s; }; template <int N> diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype21.C b/gcc/testsuite/g++.dg/cpp0x/decltype21.C index 733725626c3..a6e973ff88f 100644 --- a/gcc/testsuite/g++.dg/cpp0x/decltype21.C +++ b/gcc/testsuite/g++.dg/cpp0x/decltype21.C @@ -1,6 +1,6 @@ // PR c++/6709 (DR 743) // PR c++/42603 (DR 950) -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template <class T> T make(); diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype22.C b/gcc/testsuite/g++.dg/cpp0x/decltype22.C index 74811cfe701..623163f4b14 100644 --- a/gcc/testsuite/g++.dg/cpp0x/decltype22.C +++ b/gcc/testsuite/g++.dg/cpp0x/decltype22.C @@ -1,5 +1,5 @@ // PR c++/42761 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<typename _Tp> _Tp* fn(); diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype23.C b/gcc/testsuite/g++.dg/cpp0x/decltype23.C index 78eb89d8ee2..a2543243a52 100644 --- a/gcc/testsuite/g++.dg/cpp0x/decltype23.C +++ b/gcc/testsuite/g++.dg/cpp0x/decltype23.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } int x, &&y = static_cast<int &&>(x); typedef decltype((y)) myInt; // `y' is a parenthesized id-expression of type int that is an lvalue diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype24.C b/gcc/testsuite/g++.dg/cpp0x/decltype24.C index 16d0736d66f..3b3a7d59718 100644 --- a/gcc/testsuite/g++.dg/cpp0x/decltype24.C +++ b/gcc/testsuite/g++.dg/cpp0x/decltype24.C @@ -1,5 +1,5 @@ // PR c++/47068 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template <class T> struct broken { int member; diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype25.C b/gcc/testsuite/g++.dg/cpp0x/decltype25.C index c9559f1511a..04465b90220 100644 --- a/gcc/testsuite/g++.dg/cpp0x/decltype25.C +++ b/gcc/testsuite/g++.dg/cpp0x/decltype25.C @@ -1,5 +1,5 @@ // PR c++/47851 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct Type { void display_type(); diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype26.C b/gcc/testsuite/g++.dg/cpp0x/decltype26.C index a81d411558c..705fd64e51e 100644 --- a/gcc/testsuite/g++.dg/cpp0x/decltype26.C +++ b/gcc/testsuite/g++.dg/cpp0x/decltype26.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { }; diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype27.C b/gcc/testsuite/g++.dg/cpp0x/decltype27.C index cb962ada525..0f0cd42168b 100644 --- a/gcc/testsuite/g++.dg/cpp0x/decltype27.C +++ b/gcc/testsuite/g++.dg/cpp0x/decltype27.C @@ -1,5 +1,5 @@ // PR c++/48617 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<class T, decltype(T())> // # struct A {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype28.C b/gcc/testsuite/g++.dg/cpp0x/decltype28.C index 00457357b2b..591bb03b573 100644 --- a/gcc/testsuite/g++.dg/cpp0x/decltype28.C +++ b/gcc/testsuite/g++.dg/cpp0x/decltype28.C @@ -1,5 +1,5 @@ // PR c++/44175 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template <bool, class T> struct enable_if { }; template <class T> struct enable_if <true, T> { typedef T type; }; diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype29.C b/gcc/testsuite/g++.dg/cpp0x/decltype29.C index a64bb65a476..ae1cb2ab2fc 100644 --- a/gcc/testsuite/g++.dg/cpp0x/decltype29.C +++ b/gcc/testsuite/g++.dg/cpp0x/decltype29.C @@ -1,5 +1,5 @@ // PR c++/44175 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template <bool, class T> struct enable_if { }; template <class T> struct enable_if <true, T> { typedef T type; }; diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype3.C b/gcc/testsuite/g++.dg/cpp0x/decltype3.C index b44dd17c8ea..57300566e3b 100644 --- a/gcc/testsuite/g++.dg/cpp0x/decltype3.C +++ b/gcc/testsuite/g++.dg/cpp0x/decltype3.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename T, typename U> struct is_same diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype30.C b/gcc/testsuite/g++.dg/cpp0x/decltype30.C index b23c9a94d8f..2e7283e55d7 100644 --- a/gcc/testsuite/g++.dg/cpp0x/decltype30.C +++ b/gcc/testsuite/g++.dg/cpp0x/decltype30.C @@ -1,5 +1,5 @@ // PR c++/49369 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template <class,class> struct assert_same; template <class T> struct assert_same<T,T> {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype31.C b/gcc/testsuite/g++.dg/cpp0x/decltype31.C index b9817eb9e13..ce03ec11cc8 100644 --- a/gcc/testsuite/g++.dg/cpp0x/decltype31.C +++ b/gcc/testsuite/g++.dg/cpp0x/decltype31.C @@ -1,5 +1,5 @@ // PR c++/49921 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct Local { diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype32.C b/gcc/testsuite/g++.dg/cpp0x/decltype32.C index c5f3a55c6d2..a53f9d05469 100644 --- a/gcc/testsuite/g++.dg/cpp0x/decltype32.C +++ b/gcc/testsuite/g++.dg/cpp0x/decltype32.C @@ -1,5 +1,5 @@ // PR c++/50075 -// { dg-options "-std=c++0x -ftemplate-depth=10" } +// { dg-options "-std=c++11 -ftemplate-depth=10" } template <typename T> auto make_array(const T& il) -> diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype33.C b/gcc/testsuite/g++.dg/cpp0x/decltype33.C index d022d166482..935423ab555 100644 --- a/gcc/testsuite/g++.dg/cpp0x/decltype33.C +++ b/gcc/testsuite/g++.dg/cpp0x/decltype33.C @@ -1,5 +1,5 @@ // PR c++/50084 -// { dg-options "-std=c++0x -fno-inline" } +// { dg-options "-std=c++11 -fno-inline" } template<typename> struct remove_reference; template<typename T> struct remove_reference<T&> { typedef T type; }; diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype34.C b/gcc/testsuite/g++.dg/cpp0x/decltype34.C index fbd15c2797d..9d7c3182825 100644 --- a/gcc/testsuite/g++.dg/cpp0x/decltype34.C +++ b/gcc/testsuite/g++.dg/cpp0x/decltype34.C @@ -1,5 +1,5 @@ // PR c++/50870 -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } struct impl { diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype35.C b/gcc/testsuite/g++.dg/cpp0x/decltype35.C index d1fd47638a9..ee9537d97eb 100644 --- a/gcc/testsuite/g++.dg/cpp0x/decltype35.C +++ b/gcc/testsuite/g++.dg/cpp0x/decltype35.C @@ -1,5 +1,5 @@ // PR c++/50870 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template <class V> struct impl diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype36.C b/gcc/testsuite/g++.dg/cpp0x/decltype36.C index f3dfed992cf..2cf34c0ecf2 100644 --- a/gcc/testsuite/g++.dg/cpp0x/decltype36.C +++ b/gcc/testsuite/g++.dg/cpp0x/decltype36.C @@ -1,5 +1,5 @@ // PR c++/51265 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct Funny { diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype4.C b/gcc/testsuite/g++.dg/cpp0x/decltype4.C index cd715cb2892..5db826fc522 100644 --- a/gcc/testsuite/g++.dg/cpp0x/decltype4.C +++ b/gcc/testsuite/g++.dg/cpp0x/decltype4.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename T, typename U> struct is_same diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype5.C b/gcc/testsuite/g++.dg/cpp0x/decltype5.C index 1391539873f..4c31a2b4a6a 100644 --- a/gcc/testsuite/g++.dg/cpp0x/decltype5.C +++ b/gcc/testsuite/g++.dg/cpp0x/decltype5.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename T, typename U> struct is_same diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype6.C b/gcc/testsuite/g++.dg/cpp0x/decltype6.C index 7aa8e1505ef..2f742ce08cc 100644 --- a/gcc/testsuite/g++.dg/cpp0x/decltype6.C +++ b/gcc/testsuite/g++.dg/cpp0x/decltype6.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename T, typename U> struct is_same diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype9.C b/gcc/testsuite/g++.dg/cpp0x/decltype9.C index 4cd150ea6cf..c13ff8db5d6 100644 --- a/gcc/testsuite/g++.dg/cpp0x/decltype9.C +++ b/gcc/testsuite/g++.dg/cpp0x/decltype9.C @@ -1,6 +1,6 @@ // PR c++/34271 // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<int> struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/deduce.C b/gcc/testsuite/g++.dg/cpp0x/deduce.C index 635228cca08..5185f9a3953 100644 --- a/gcc/testsuite/g++.dg/cpp0x/deduce.C +++ b/gcc/testsuite/g++.dg/cpp0x/deduce.C @@ -1,4 +1,4 @@ -// { dg-options "--std=c++0x" } +// { dg-options "--std=c++11" } template<typename T, typename U> struct same_type; template<typename T> struct same_type<T, T> {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted1.C b/gcc/testsuite/g++.dg/cpp0x/defaulted1.C index e8fe37eb39a..1f36b185452 100644 --- a/gcc/testsuite/g++.dg/cpp0x/defaulted1.C +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted1.C @@ -1,6 +1,6 @@ // Positive test for defaulted/deleted fns // { dg-do run } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted10.C b/gcc/testsuite/g++.dg/cpp0x/defaulted10.C index 64fa5f01930..fe3eae5b417 100644 --- a/gcc/testsuite/g++.dg/cpp0x/defaulted10.C +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted10.C @@ -1,5 +1,5 @@ // PR c++/40381 -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted11.C b/gcc/testsuite/g++.dg/cpp0x/defaulted11.C index b9bed7e0037..65cd0e27f47 100644 --- a/gcc/testsuite/g++.dg/cpp0x/defaulted11.C +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted11.C @@ -1,5 +1,5 @@ // Core issue 901 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted13.C b/gcc/testsuite/g++.dg/cpp0x/defaulted13.C index 5ddbcb38c1c..ad15a0e853c 100644 --- a/gcc/testsuite/g++.dg/cpp0x/defaulted13.C +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted13.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<typename T> struct NonCopyable { diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted14.C b/gcc/testsuite/g++.dg/cpp0x/defaulted14.C index e476d576cfa..73072e2057d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/defaulted14.C +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted14.C @@ -1,5 +1,5 @@ // PR c++/39866 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } struct A { A& operator=(const A&) = delete; // { dg-bogus "" } diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted15.C b/gcc/testsuite/g++.dg/cpp0x/defaulted15.C index 6d182df2158..99400ac4f9c 100644 --- a/gcc/testsuite/g++.dg/cpp0x/defaulted15.C +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted15.C @@ -1,5 +1,5 @@ // PR c++/38796 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } #define SA(X) static_assert ((X), #X) diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted16.C b/gcc/testsuite/g++.dg/cpp0x/defaulted16.C index 741b43de27d..25b2d5ad673 100644 --- a/gcc/testsuite/g++.dg/cpp0x/defaulted16.C +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted16.C @@ -1,7 +1,7 @@ // Test that non-inline default causes the function to be defined even if // it isn't used. -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } // { dg-final { scan-assembler "_ZN1AC1Ev" } } struct A diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted17.C b/gcc/testsuite/g++.dg/cpp0x/defaulted17.C index 79e91a0eb61..48529f5a3a7 100644 --- a/gcc/testsuite/g++.dg/cpp0x/defaulted17.C +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted17.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A // { dg-error "const|operator=" } { diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted18.C b/gcc/testsuite/g++.dg/cpp0x/defaulted18.C index 559dfde4833..7dd17345d11 100644 --- a/gcc/testsuite/g++.dg/cpp0x/defaulted18.C +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted18.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } void f(char i, int j) = delete; // { dg-message "<deleted>" } void f(int i, ...); // { dg-message "void f" } diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted19.C b/gcc/testsuite/g++.dg/cpp0x/defaulted19.C index ea33df39838..f7de0730625 100644 --- a/gcc/testsuite/g++.dg/cpp0x/defaulted19.C +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted19.C @@ -1,5 +1,6 @@ -// We allocate a cookie to help us run the destructor even if it's deleted. -// { dg-options -std=c++0x } +// We don't allocate a cookie to help us run the destructor if it's trivial, +// even if it's deleted. +// { dg-options "-std=c++11" } // { dg-do run } struct A @@ -17,5 +18,5 @@ void *operator new[](__SIZE_TYPE__ t) int main() { A* ap = new A[5]; - return ap == p; + return ap != p; } diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted19a.C b/gcc/testsuite/g++.dg/cpp0x/defaulted19a.C new file mode 100644 index 00000000000..6d2a26a818c --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted19a.C @@ -0,0 +1,24 @@ +// We allocate a cookie to help us run the destructor if it's non-trivial, +// even if it's deleted. +// { dg-options "-std=c++0x" } +// { dg-do run } + +struct B { ~B() {} }; +struct A +{ + B b; + ~A() = delete; +}; + +void *p = 0; +void *operator new[](__SIZE_TYPE__ t) +{ + p = ::operator new (t); + return p; +} + +int main() +{ + A* ap = new A[5]; + return ap == p; +} diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted2.C b/gcc/testsuite/g++.dg/cpp0x/defaulted2.C index 57f74e8e714..3cef60050ac 100644 --- a/gcc/testsuite/g++.dg/cpp0x/defaulted2.C +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted2.C @@ -1,5 +1,5 @@ // Negative test for defaulted/deleted fns. -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } void f(); // { dg-error "previous" } void f() = delete; // { dg-error "deleted" } @@ -62,7 +62,7 @@ int main() { F f; F f2(f); // { dg-error "use" } - B* b = new const B; // { dg-error "uninitialized const" } + const B* b = new const B; // { dg-error "uninitialized const" } U u; // { dg-error "deleted" } } diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted20.C b/gcc/testsuite/g++.dg/cpp0x/defaulted20.C index 9b8c697abad..49919ef7813 100644 --- a/gcc/testsuite/g++.dg/cpp0x/defaulted20.C +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted20.C @@ -1,5 +1,5 @@ // PR c++/46497 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { A(A&&) = default; diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted21.C b/gcc/testsuite/g++.dg/cpp0x/defaulted21.C index 51505dc460e..09a211ff7d3 100644 --- a/gcc/testsuite/g++.dg/cpp0x/defaulted21.C +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted21.C @@ -1,5 +1,5 @@ // PR c++/46736 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct U { U(); diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted22.C b/gcc/testsuite/g++.dg/cpp0x/defaulted22.C index 61e9d320521..86dbed90bf8 100644 --- a/gcc/testsuite/g++.dg/cpp0x/defaulted22.C +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted22.C @@ -1,6 +1,6 @@ // Test that a virtual defaulted constructor is still virtual. // { dg-do run } -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } int r = 1; diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted23.C b/gcc/testsuite/g++.dg/cpp0x/defaulted23.C index 5b4438ddd02..be2fd2fbf90 100644 --- a/gcc/testsuite/g++.dg/cpp0x/defaulted23.C +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted23.C @@ -1,27 +1,37 @@ // Test for checking of exception specifications on defaulted fns -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { A() noexcept = default; }; +A a; + struct B { - B() throw (int) = default; // { dg-error "exception-specification that differs from the implicit declaration" } + B() throw (int) = default; // { dg-message "exception-specification" } }; +B b; // { dg-error "deleted" } + struct C { C() throw (int) { } }; +C c; + struct D: C { D() throw (int) = default; }; +D d; + struct E { E() = default; }; + +E e; diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted24.C b/gcc/testsuite/g++.dg/cpp0x/defaulted24.C index 307bf94ab85..7f9aed69f0e 100644 --- a/gcc/testsuite/g++.dg/cpp0x/defaulted24.C +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted24.C @@ -1,5 +1,5 @@ // PR c++/48280 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct S { template < typename > S (const S &) = default; // { dg-error "" } diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted25.C b/gcc/testsuite/g++.dg/cpp0x/defaulted25.C index 2a38fedb248..26b0c9184ea 100644 --- a/gcc/testsuite/g++.dg/cpp0x/defaulted25.C +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted25.C @@ -1,5 +1,5 @@ // PR c++/48930 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } // { dg-prune-output "note" } struct A diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted26.C b/gcc/testsuite/g++.dg/cpp0x/defaulted26.C index 746fa908180..b9be726b3a7 100644 --- a/gcc/testsuite/g++.dg/cpp0x/defaulted26.C +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted26.C @@ -1,5 +1,5 @@ // PR c++/49066 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } void foo() = delete; // { dg-message "declared here" } void foo(); diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted27.C b/gcc/testsuite/g++.dg/cpp0x/defaulted27.C index 7d9139d2373..8f71e9eb254 100644 --- a/gcc/testsuite/g++.dg/cpp0x/defaulted27.C +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted27.C @@ -1,5 +1,5 @@ // PR c++/47544 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } // { dg-final { scan-assembler "_ZN1sIiEC2Ev" } } // { dg-final { scan-assembler-not "_ZN1sIiED2Ev" } } diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted28.C b/gcc/testsuite/g++.dg/cpp0x/defaulted28.C index bcbf763f6da..e8b44daeae3 100644 --- a/gcc/testsuite/g++.dg/cpp0x/defaulted28.C +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted28.C @@ -1,6 +1,6 @@ // PR c++/49102 // PR c++/50034 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { A() = default; diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted29.C b/gcc/testsuite/g++.dg/cpp0x/defaulted29.C index 5fcf5b0c543..9e6382e3793 100644 --- a/gcc/testsuite/g++.dg/cpp0x/defaulted29.C +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted29.C @@ -1,5 +1,5 @@ // PR c++/46696 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted3.C b/gcc/testsuite/g++.dg/cpp0x/defaulted3.C index bc5b14d2d59..21b13783426 100644 --- a/gcc/testsuite/g++.dg/cpp0x/defaulted3.C +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted3.C @@ -1,5 +1,5 @@ // PR c++/37006 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<class T> struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted30.C b/gcc/testsuite/g++.dg/cpp0x/defaulted30.C index 0bf4425b875..2440b94034f 100644 --- a/gcc/testsuite/g++.dg/cpp0x/defaulted30.C +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted30.C @@ -1,5 +1,5 @@ // PR c++/49507 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<typename T> struct ConcretePoolKey diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted31.C b/gcc/testsuite/g++.dg/cpp0x/defaulted31.C index c76a0f2bd69..d866872157d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/defaulted31.C +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted31.C @@ -1,5 +1,5 @@ // PR c++/39164 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted32.C b/gcc/testsuite/g++.dg/cpp0x/defaulted32.C index 351cdae1102..a3654833617 100644 --- a/gcc/testsuite/g++.dg/cpp0x/defaulted32.C +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted32.C @@ -1,5 +1,5 @@ // PR c++/50531 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template <typename T> class DataFilter diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted34.C b/gcc/testsuite/g++.dg/cpp0x/defaulted34.C index 08219926739..463cc34e7fb 100644 --- a/gcc/testsuite/g++.dg/cpp0x/defaulted34.C +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted34.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } // { dg-final { scan-assembler "__cxa_deleted_virtual" } } struct A diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted35.C b/gcc/testsuite/g++.dg/cpp0x/defaulted35.C index ca700fb784c..8312ba16aa9 100644 --- a/gcc/testsuite/g++.dg/cpp0x/defaulted35.C +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted35.C @@ -1,5 +1,5 @@ // PR c++/53096 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct foo { diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted4.C b/gcc/testsuite/g++.dg/cpp0x/defaulted4.C index 56053840bdf..3e5e92604ed 100644 --- a/gcc/testsuite/g++.dg/cpp0x/defaulted4.C +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted4.C @@ -1,6 +1,6 @@ // PR c++/37208: SFINAE and deleted functions. -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // { dg-do compile } template<int> struct A { }; diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted43.C b/gcc/testsuite/g++.dg/cpp0x/defaulted43.C index e1c2b72ba27..f2846fe390c 100644 --- a/gcc/testsuite/g++.dg/cpp0x/defaulted43.C +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted43.C @@ -7,6 +7,8 @@ struct T ~T() noexcept(false) { } }; +T t; + struct A { A() noexcept; @@ -24,6 +26,8 @@ struct U ~U() noexcept(false) { } }; +U u; + struct B { B() noexcept(false); @@ -35,16 +39,22 @@ struct B B::B() noexcept(false) = default; B::~B() noexcept(false) = default; +B b; + struct V { V() noexcept(false) { } ~V() noexcept(false) { } }; +V v; + struct C { - C() noexcept = default; // { dg-error "defaulted" } - ~C() noexcept = default; // { dg-error "defaulted" } + C() noexcept = default; // { dg-message "exception-specification" } + ~C() noexcept = default; // { dg-message "exception-specification" } V v; }; + +C c; // { dg-error "deleted" } diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted46.C b/gcc/testsuite/g++.dg/cpp0x/defaulted46.C new file mode 100644 index 00000000000..d4562c95903 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted46.C @@ -0,0 +1,17 @@ +// { dg-require-effective-target c++11 } + +struct A +{ +protected: + A() = default; + int i; +}; + +struct B: A { + B() = default; +}; + +int main() +{ + B(); +} diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted47.C b/gcc/testsuite/g++.dg/cpp0x/defaulted47.C new file mode 100644 index 00000000000..f4b62a3c659 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted47.C @@ -0,0 +1,16 @@ +// PR c++/54812 +// { dg-do compile { target c++11 } } + +class A +{ + A() = default; // { dg-error "private" } +}; + +A a; // { dg-error "context" } + +class B +{ + ~B() = default; // { dg-error "private" } +}; + +B b; // { dg-error "context" } diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted5.C b/gcc/testsuite/g++.dg/cpp0x/defaulted5.C index b7bd16b4063..a8d7e9828cf 100644 --- a/gcc/testsuite/g++.dg/cpp0x/defaulted5.C +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted5.C @@ -1,6 +1,6 @@ // PR c++/37234 // { dg-do link } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template <typename T> class foo { diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted6.C b/gcc/testsuite/g++.dg/cpp0x/defaulted6.C index c33d5729223..05f06c94680 100644 --- a/gcc/testsuite/g++.dg/cpp0x/defaulted6.C +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted6.C @@ -1,5 +1,5 @@ // PR c++/37906 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } struct b { diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted7.C b/gcc/testsuite/g++.dg/cpp0x/defaulted7.C index 97c29258e98..00a24f03999 100644 --- a/gcc/testsuite/g++.dg/cpp0x/defaulted7.C +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted7.C @@ -1,5 +1,5 @@ // PR c++/38701, 38702 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } void foo() = default; // { dg-error "cannot be defaulted" } namespace diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted8.C b/gcc/testsuite/g++.dg/cpp0x/defaulted8.C index f446f815691..6ec936322d2 100644 --- a/gcc/testsuite/g++.dg/cpp0x/defaulted8.C +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted8.C @@ -1,5 +1,5 @@ // PR c++/38649 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted9.C b/gcc/testsuite/g++.dg/cpp0x/defaulted9.C index 1e5e2cbf9fb..2907b03a123 100644 --- a/gcc/testsuite/g++.dg/cpp0x/defaulted9.C +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted9.C @@ -1,5 +1,5 @@ // PR c++/39153 -// { dg-options "-std=c++0x -fno-inline" } +// { dg-options "-std=c++11 -fno-inline" } struct _Impl_base { diff --git a/gcc/testsuite/g++.dg/cpp0x/deleted1.C b/gcc/testsuite/g++.dg/cpp0x/deleted1.C new file mode 100644 index 00000000000..0a632bfb30b --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/deleted1.C @@ -0,0 +1,6 @@ +// PR c++/58581 +// { dg-do compile { target c++11 } } + +template<typename T> int foo(T) noexcept(T()) = delete; + +int i = foo(0); // { dg-error "deleted" } diff --git a/gcc/testsuite/g++.dg/cpp0x/dependent1.C b/gcc/testsuite/g++.dg/cpp0x/dependent1.C index 1ceeeafd78d..de8a1a9380b 100644 --- a/gcc/testsuite/g++.dg/cpp0x/dependent1.C +++ b/gcc/testsuite/g++.dg/cpp0x/dependent1.C @@ -1,5 +1,5 @@ // PR c++/48319 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } // We were failing to recognize declval<_Args1> as dependent. template<typename Tp> Tp declval() noexcept; diff --git a/gcc/testsuite/g++.dg/cpp0x/diag1.C b/gcc/testsuite/g++.dg/cpp0x/diag1.C index b3f30bcd0b4..0e53dcb69a3 100644 --- a/gcc/testsuite/g++.dg/cpp0x/diag1.C +++ b/gcc/testsuite/g++.dg/cpp0x/diag1.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template <int U> struct TypeA diff --git a/gcc/testsuite/g++.dg/cpp0x/elision.C b/gcc/testsuite/g++.dg/cpp0x/elision.C index 35d5e4b02fb..70162a151bb 100644 --- a/gcc/testsuite/g++.dg/cpp0x/elision.C +++ b/gcc/testsuite/g++.dg/cpp0x/elision.C @@ -3,7 +3,7 @@ // Test: Implicit cast to rvalue when eliding copy // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template <bool> struct sa; template <> struct sa<true> {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/elision2.C b/gcc/testsuite/g++.dg/cpp0x/elision2.C index 216b1b59d16..811c5394d7f 100644 --- a/gcc/testsuite/g++.dg/cpp0x/elision2.C +++ b/gcc/testsuite/g++.dg/cpp0x/elision2.C @@ -1,5 +1,5 @@ // Core 1148: should be able to move from value parameter on return -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/elision_neg.C b/gcc/testsuite/g++.dg/cpp0x/elision_neg.C index 78feac72a5b..f302605f73f 100644 --- a/gcc/testsuite/g++.dg/cpp0x/elision_neg.C +++ b/gcc/testsuite/g++.dg/cpp0x/elision_neg.C @@ -3,7 +3,7 @@ // Test: Implicit cast to rvalue when eliding copy // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template <bool> struct sa; template <> struct sa<true> {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/enum1.C b/gcc/testsuite/g++.dg/cpp0x/enum1.C index fb03692fab4..41dd62240d4 100644 --- a/gcc/testsuite/g++.dg/cpp0x/enum1.C +++ b/gcc/testsuite/g++.dg/cpp0x/enum1.C @@ -1,6 +1,6 @@ // PR c++/38021 // { dg-do compile } -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } enum : { }; // { dg-error "expected" } enum : 3 { }; // { dg-error "expected" } diff --git a/gcc/testsuite/g++.dg/cpp0x/enum10.C b/gcc/testsuite/g++.dg/cpp0x/enum10.C index 55a1ab46be1..825cc647d52 100644 --- a/gcc/testsuite/g++.dg/cpp0x/enum10.C +++ b/gcc/testsuite/g++.dg/cpp0x/enum10.C @@ -1,5 +1,5 @@ // PR c++/48534 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } enum class OpSE : bool; diff --git a/gcc/testsuite/g++.dg/cpp0x/enum11.C b/gcc/testsuite/g++.dg/cpp0x/enum11.C index 156c765beaf..a2bd3535213 100644 --- a/gcc/testsuite/g++.dg/cpp0x/enum11.C +++ b/gcc/testsuite/g++.dg/cpp0x/enum11.C @@ -1,5 +1,5 @@ // PR c++/48969 -// { dg-options "-std=c++0x -ftemplate-depth=10" } +// { dg-options "-std=c++11 -ftemplate-depth=10" } template<unsigned int N> struct Pair { }; struct Foo { enum { Mask = 1 }; } foo; diff --git a/gcc/testsuite/g++.dg/cpp0x/enum12.C b/gcc/testsuite/g++.dg/cpp0x/enum12.C index b2ec91990e2..46d2686a6b3 100644 --- a/gcc/testsuite/g++.dg/cpp0x/enum12.C +++ b/gcc/testsuite/g++.dg/cpp0x/enum12.C @@ -1,5 +1,5 @@ // PR c++/48780 -// { dg-options "-std=c++0x -fabi-version=0" } +// { dg-options "-std=c++11 -fabi-version=0" } typedef __builtin_va_list __gnuc_va_list; typedef __gnuc_va_list va_list; diff --git a/gcc/testsuite/g++.dg/cpp0x/enum13.C b/gcc/testsuite/g++.dg/cpp0x/enum13.C index ec02d3bf607..3f637241fdc 100644 --- a/gcc/testsuite/g++.dg/cpp0x/enum13.C +++ b/gcc/testsuite/g++.dg/cpp0x/enum13.C @@ -1,5 +1,5 @@ // PR c++/48780 -// { dg-options "-std=c++0x -fabi-version=5 -Wabi" } +// { dg-options "-std=c++11 -fabi-version=5 -Wabi" } typedef __builtin_va_list __gnuc_va_list; typedef __gnuc_va_list va_list; diff --git a/gcc/testsuite/g++.dg/cpp0x/enum14.C b/gcc/testsuite/g++.dg/cpp0x/enum14.C index 709b201d1f7..fe791f1a26b 100644 --- a/gcc/testsuite/g++.dg/cpp0x/enum14.C +++ b/gcc/testsuite/g++.dg/cpp0x/enum14.C @@ -1,5 +1,5 @@ // PR c++/48106 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } enum class E : char { diff --git a/gcc/testsuite/g++.dg/cpp0x/enum15.C b/gcc/testsuite/g++.dg/cpp0x/enum15.C index 1d33f90290f..61737742adb 100644 --- a/gcc/testsuite/g++.dg/cpp0x/enum15.C +++ b/gcc/testsuite/g++.dg/cpp0x/enum15.C @@ -1,5 +1,5 @@ // PR c++/44311 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } enum class A { Val0, Val1 }; diff --git a/gcc/testsuite/g++.dg/cpp0x/enum16.C b/gcc/testsuite/g++.dg/cpp0x/enum16.C index ebb48688b18..941d85b5c58 100644 --- a/gcc/testsuite/g++.dg/cpp0x/enum16.C +++ b/gcc/testsuite/g++.dg/cpp0x/enum16.C @@ -1,5 +1,5 @@ // PR c++/48935 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } enum class ENUM { a }; diff --git a/gcc/testsuite/g++.dg/cpp0x/enum17.C b/gcc/testsuite/g++.dg/cpp0x/enum17.C index 8ba827e50f4..e67928ba4ca 100644 --- a/gcc/testsuite/g++.dg/cpp0x/enum17.C +++ b/gcc/testsuite/g++.dg/cpp0x/enum17.C @@ -1,5 +1,5 @@ // PR c++/48536 -// { dg-options "-std=c++0x -pedantic-errors" } +// { dg-options "-std=c++11 -pedantic-errors" } #include <climits> diff --git a/gcc/testsuite/g++.dg/cpp0x/enum18.C b/gcc/testsuite/g++.dg/cpp0x/enum18.C index 306ed8259f9..c37eebe9de2 100644 --- a/gcc/testsuite/g++.dg/cpp0x/enum18.C +++ b/gcc/testsuite/g++.dg/cpp0x/enum18.C @@ -1,5 +1,5 @@ // PR c++/47277 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } int main(void) { enum e {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/enum19.C b/gcc/testsuite/g++.dg/cpp0x/enum19.C index acdd86c0ba4..de423aa8cca 100644 --- a/gcc/testsuite/g++.dg/cpp0x/enum19.C +++ b/gcc/testsuite/g++.dg/cpp0x/enum19.C @@ -1,5 +1,5 @@ // We shouldn't give an ABI warning about promotion in switch. -// { dg-options "-std=c++0x -fabi-version=5 -Wabi" } +// { dg-options "-std=c++11 -fabi-version=5 -Wabi" } enum class Foo { X }; void test(Foo val) diff --git a/gcc/testsuite/g++.dg/cpp0x/enum2.C b/gcc/testsuite/g++.dg/cpp0x/enum2.C index 21c265a923c..57eccafe14c 100644 --- a/gcc/testsuite/g++.dg/cpp0x/enum2.C +++ b/gcc/testsuite/g++.dg/cpp0x/enum2.C @@ -1,5 +1,5 @@ // PR c++/38637 // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<int> enum E : int { e }; // { dg-error "declaration|expected" } diff --git a/gcc/testsuite/g++.dg/cpp0x/enum20.C b/gcc/testsuite/g++.dg/cpp0x/enum20.C index e5dc186e4af..0fcd9c907de 100644 --- a/gcc/testsuite/g++.dg/cpp0x/enum20.C +++ b/gcc/testsuite/g++.dg/cpp0x/enum20.C @@ -1,5 +1,5 @@ // PR c++/47635 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } enum A { }; void A::f() { } // { dg-error "not a class" } diff --git a/gcc/testsuite/g++.dg/cpp0x/enum21b.C b/gcc/testsuite/g++.dg/cpp0x/enum21b.C index 48989128d89..aab0f5e215e 100644 --- a/gcc/testsuite/g++.dg/cpp0x/enum21b.C +++ b/gcc/testsuite/g++.dg/cpp0x/enum21b.C @@ -1,4 +1,4 @@ // { dg-do compile } -// { dg-options "-pedantic -std=c++0x" } +// { dg-options "-pedantic -std=c++11" } enum x { y, }; diff --git a/gcc/testsuite/g++.dg/cpp0x/enum3.C b/gcc/testsuite/g++.dg/cpp0x/enum3.C index 5ae5e1a9d66..3e630d6e1e8 100644 --- a/gcc/testsuite/g++.dg/cpp0x/enum3.C +++ b/gcc/testsuite/g++.dg/cpp0x/enum3.C @@ -1,5 +1,5 @@ // PR c++/38064 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // { dg-do run } enum class E { elem }; diff --git a/gcc/testsuite/g++.dg/cpp0x/enum4.C b/gcc/testsuite/g++.dg/cpp0x/enum4.C index 002edf0923e..adf24b9cecf 100644 --- a/gcc/testsuite/g++.dg/cpp0x/enum4.C +++ b/gcc/testsuite/g++.dg/cpp0x/enum4.C @@ -1,5 +1,5 @@ // PR c++/40633 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template< typename T > struct wrap { diff --git a/gcc/testsuite/g++.dg/cpp0x/enum5.C b/gcc/testsuite/g++.dg/cpp0x/enum5.C index c4ceebed71e..fd413228e69 100644 --- a/gcc/testsuite/g++.dg/cpp0x/enum5.C +++ b/gcc/testsuite/g++.dg/cpp0x/enum5.C @@ -1,5 +1,5 @@ // PR c++/40639 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template< typename T > struct wrap { diff --git a/gcc/testsuite/g++.dg/cpp0x/enum6.C b/gcc/testsuite/g++.dg/cpp0x/enum6.C index e0639847125..74bd228a0bf 100644 --- a/gcc/testsuite/g++.dg/cpp0x/enum6.C +++ b/gcc/testsuite/g++.dg/cpp0x/enum6.C @@ -1,5 +1,5 @@ // PR c++/37946 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } enum class E : char { diff --git a/gcc/testsuite/g++.dg/cpp0x/enum7.C b/gcc/testsuite/g++.dg/cpp0x/enum7.C index 407672a4799..ed6635d53bd 100644 --- a/gcc/testsuite/g++.dg/cpp0x/enum7.C +++ b/gcc/testsuite/g++.dg/cpp0x/enum7.C @@ -1,5 +1,5 @@ // PR c++/37816 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } class A { diff --git a/gcc/testsuite/g++.dg/cpp0x/enum8.C b/gcc/testsuite/g++.dg/cpp0x/enum8.C index 0075e2daa8b..b0205a92497 100644 --- a/gcc/testsuite/g++.dg/cpp0x/enum8.C +++ b/gcc/testsuite/g++.dg/cpp0x/enum8.C @@ -1,6 +1,6 @@ // PR c++/47704 // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } void foo () diff --git a/gcc/testsuite/g++.dg/cpp0x/enum9.C b/gcc/testsuite/g++.dg/cpp0x/enum9.C index 10e510bcd25..70a2103916e 100644 --- a/gcc/testsuite/g++.dg/cpp0x/enum9.C +++ b/gcc/testsuite/g++.dg/cpp0x/enum9.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } enum class E { }; E f(); diff --git a/gcc/testsuite/g++.dg/cpp0x/enum_base.C b/gcc/testsuite/g++.dg/cpp0x/enum_base.C index 7da232cc2aa..e63f4184237 100644 --- a/gcc/testsuite/g++.dg/cpp0x/enum_base.C +++ b/gcc/testsuite/g++.dg/cpp0x/enum_base.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } typedef unsigned volatile long long uvlonglong; diff --git a/gcc/testsuite/g++.dg/cpp0x/enum_base_warn.C b/gcc/testsuite/g++.dg/cpp0x/enum_base_warn.C index 4b14cf65e09..5257a9e4d11 100644 --- a/gcc/testsuite/g++.dg/cpp0x/enum_base_warn.C +++ b/gcc/testsuite/g++.dg/cpp0x/enum_base_warn.C @@ -1,5 +1,5 @@ // { dg-do run } -// { dg-options "-O2 -Wtype-limits -std=c++0x" } +// { dg-options "-O2 -Wtype-limits -std=c++11" } extern void link_error (void); enum Alpha : unsigned char { diff --git a/gcc/testsuite/g++.dg/cpp0x/error1.C b/gcc/testsuite/g++.dg/cpp0x/error1.C index 15cd38f8807..59abd169503 100644 --- a/gcc/testsuite/g++.dg/cpp0x/error1.C +++ b/gcc/testsuite/g++.dg/cpp0x/error1.C @@ -1,6 +1,6 @@ // PR c++/34395 // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<int... N> void foo (int... x[N]) // { dg-message "int \\\[N\\\]\\.\\.\\. x" } { diff --git a/gcc/testsuite/g++.dg/cpp0x/error2.C b/gcc/testsuite/g++.dg/cpp0x/error2.C index ca681eb2f79..d39e7f023f6 100644 --- a/gcc/testsuite/g++.dg/cpp0x/error2.C +++ b/gcc/testsuite/g++.dg/cpp0x/error2.C @@ -1,5 +1,5 @@ // PR c++/38656 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<int> int foo(); diff --git a/gcc/testsuite/g++.dg/cpp0x/error3.C b/gcc/testsuite/g++.dg/cpp0x/error3.C index e7da961950e..deee9a24253 100644 --- a/gcc/testsuite/g++.dg/cpp0x/error3.C +++ b/gcc/testsuite/g++.dg/cpp0x/error3.C @@ -1,5 +1,5 @@ // PR c++/47336 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template <typename T> void g(T t) diff --git a/gcc/testsuite/g++.dg/cpp0x/error4.C b/gcc/testsuite/g++.dg/cpp0x/error4.C index 064c2f2f620..fa638a44d25 100644 --- a/gcc/testsuite/g++.dg/cpp0x/error4.C +++ b/gcc/testsuite/g++.dg/cpp0x/error4.C @@ -1,5 +1,5 @@ // PR c++/49156 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<typename T> T declval(); diff --git a/gcc/testsuite/g++.dg/cpp0x/error5.C b/gcc/testsuite/g++.dg/cpp0x/error5.C index 19319264224..0baa5000694 100644 --- a/gcc/testsuite/g++.dg/cpp0x/error5.C +++ b/gcc/testsuite/g++.dg/cpp0x/error5.C @@ -1,5 +1,5 @@ // PR c++/49181 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } namespace std { diff --git a/gcc/testsuite/g++.dg/cpp0x/error6.C b/gcc/testsuite/g++.dg/cpp0x/error6.C index 3b457952d38..e059e2261d2 100644 --- a/gcc/testsuite/g++.dg/cpp0x/error6.C +++ b/gcc/testsuite/g++.dg/cpp0x/error6.C @@ -1,5 +1,5 @@ // PR c++/48284 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<typename C> auto g(C& c) -> decltype (c.f()) { return c.f(); } // { dg-message "decltype .c\\.f" } diff --git a/gcc/testsuite/g++.dg/cpp0x/error7.C b/gcc/testsuite/g++.dg/cpp0x/error7.C index 0dfbf9f0406..9c9f1c9b1c1 100644 --- a/gcc/testsuite/g++.dg/cpp0x/error7.C +++ b/gcc/testsuite/g++.dg/cpp0x/error7.C @@ -1,5 +1,5 @@ // Test for printing the type of T{} in error messages. -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template <class T, T t> struct A { }; template <class T> A<T,T{}> f(T t); // { dg-message "T{}" } diff --git a/gcc/testsuite/g++.dg/cpp0x/explicit1.C b/gcc/testsuite/g++.dg/cpp0x/explicit1.C index fe164fc8cb1..e3004c7314d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/explicit1.C +++ b/gcc/testsuite/g++.dg/cpp0x/explicit1.C @@ -1,5 +1,5 @@ // Test for explicit conversion ops from N2437. -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } class U; class V; class T diff --git a/gcc/testsuite/g++.dg/cpp0x/explicit2.C b/gcc/testsuite/g++.dg/cpp0x/explicit2.C index c2327c140d8..9938f549712 100644 --- a/gcc/testsuite/g++.dg/cpp0x/explicit2.C +++ b/gcc/testsuite/g++.dg/cpp0x/explicit2.C @@ -1,5 +1,5 @@ // Test for explicit conversion ops in various conversion situations. -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } typedef void (*pfn)(); diff --git a/gcc/testsuite/g++.dg/cpp0x/explicit3.C b/gcc/testsuite/g++.dg/cpp0x/explicit3.C index 78d6f590cab..6933c8cfa01 100644 --- a/gcc/testsuite/g++.dg/cpp0x/explicit3.C +++ b/gcc/testsuite/g++.dg/cpp0x/explicit3.C @@ -1,5 +1,5 @@ // Test for "contextually converted to bool" -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/explicit4.C b/gcc/testsuite/g++.dg/cpp0x/explicit4.C index 0f3bc623a53..bbefb68cbe5 100644 --- a/gcc/testsuite/g++.dg/cpp0x/explicit4.C +++ b/gcc/testsuite/g++.dg/cpp0x/explicit4.C @@ -1,5 +1,5 @@ // Negative explicit conv test. -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } struct A { A(const A&, int = 0); // { dg-message "note" } diff --git a/gcc/testsuite/g++.dg/cpp0x/explicit5.C b/gcc/testsuite/g++.dg/cpp0x/explicit5.C index 88a47071db1..4573fc6296c 100644 --- a/gcc/testsuite/g++.dg/cpp0x/explicit5.C +++ b/gcc/testsuite/g++.dg/cpp0x/explicit5.C @@ -1,5 +1,5 @@ // test for extension of DR 899 to handle template ctors -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // { dg-do run } int r = 1; diff --git a/gcc/testsuite/g++.dg/cpp0x/explicit6.C b/gcc/testsuite/g++.dg/cpp0x/explicit6.C index 0d620be0803..741b9a29fc2 100644 --- a/gcc/testsuite/g++.dg/cpp0x/explicit6.C +++ b/gcc/testsuite/g++.dg/cpp0x/explicit6.C @@ -1,5 +1,5 @@ // PR c++/47080 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { explicit operator int(); // { dg-message "qualification conversion" } diff --git a/gcc/testsuite/g++.dg/cpp0x/explicit7.C b/gcc/testsuite/g++.dg/cpp0x/explicit7.C index 7a0b73e9ba0..ed3b494fce5 100644 --- a/gcc/testsuite/g++.dg/cpp0x/explicit7.C +++ b/gcc/testsuite/g++.dg/cpp0x/explicit7.C @@ -3,7 +3,7 @@ // can be converted to type T with a qualification conversion (4.4) are // also candidate functions. -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { }; struct B: A { }; diff --git a/gcc/testsuite/g++.dg/cpp0x/extern_template-1.C b/gcc/testsuite/g++.dg/cpp0x/extern_template-1.C index ec2cb784e19..9cec57c1c66 100644 --- a/gcc/testsuite/g++.dg/cpp0x/extern_template-1.C +++ b/gcc/testsuite/g++.dg/cpp0x/extern_template-1.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x -pedantic" } +// { dg-options "-std=c++11 -pedantic" } template <typename> void f() {} extern template void f<int>(); diff --git a/gcc/testsuite/g++.dg/cpp0x/extern_template-2.C b/gcc/testsuite/g++.dg/cpp0x/extern_template-2.C index 89a9ceb5a77..7ec1864ec8f 100644 --- a/gcc/testsuite/g++.dg/cpp0x/extern_template-2.C +++ b/gcc/testsuite/g++.dg/cpp0x/extern_template-2.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x -pedantic" } +// { dg-options "-std=c++11 -pedantic" } template <typename> class S {}; extern template class S<int>; diff --git a/gcc/testsuite/g++.dg/cpp0x/fntmpdefarg1.C b/gcc/testsuite/g++.dg/cpp0x/fntmpdefarg1.C index 25192ad8672..27cb0579d85 100644 --- a/gcc/testsuite/g++.dg/cpp0x/fntmpdefarg1.C +++ b/gcc/testsuite/g++.dg/cpp0x/fntmpdefarg1.C @@ -1,5 +1,5 @@ // PR c++/37766 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } int a = 1; template<int& b = a> void f() { diff --git a/gcc/testsuite/g++.dg/cpp0x/fntmpdefarg2.C b/gcc/testsuite/g++.dg/cpp0x/fntmpdefarg2.C index d94843c1fe5..c119e86afed 100644 --- a/gcc/testsuite/g++.dg/cpp0x/fntmpdefarg2.C +++ b/gcc/testsuite/g++.dg/cpp0x/fntmpdefarg2.C @@ -1,5 +1,5 @@ // PR c++/46831 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct B { }; struct D : B { }; diff --git a/gcc/testsuite/g++.dg/cpp0x/forw_enum1.C b/gcc/testsuite/g++.dg/cpp0x/forw_enum1.C index 2817ae59573..a147538ded9 100644 --- a/gcc/testsuite/g++.dg/cpp0x/forw_enum1.C +++ b/gcc/testsuite/g++.dg/cpp0x/forw_enum1.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // opaque enum declarations enum class E1; diff --git a/gcc/testsuite/g++.dg/cpp0x/forw_enum10.C b/gcc/testsuite/g++.dg/cpp0x/forw_enum10.C index a57c0a9f415..59c8045cdad 100644 --- a/gcc/testsuite/g++.dg/cpp0x/forw_enum10.C +++ b/gcc/testsuite/g++.dg/cpp0x/forw_enum10.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } //This error is diagnosed at instantiation time template<typename T> struct S1 diff --git a/gcc/testsuite/g++.dg/cpp0x/forw_enum2.C b/gcc/testsuite/g++.dg/cpp0x/forw_enum2.C index b6ad8714867..d11dc7465ff 100644 --- a/gcc/testsuite/g++.dg/cpp0x/forw_enum2.C +++ b/gcc/testsuite/g++.dg/cpp0x/forw_enum2.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } struct S1 { diff --git a/gcc/testsuite/g++.dg/cpp0x/forw_enum3.C b/gcc/testsuite/g++.dg/cpp0x/forw_enum3.C index 4a7e9f98d47..682fd93c772 100644 --- a/gcc/testsuite/g++.dg/cpp0x/forw_enum3.C +++ b/gcc/testsuite/g++.dg/cpp0x/forw_enum3.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } namespace S1 { diff --git a/gcc/testsuite/g++.dg/cpp0x/forw_enum4.C b/gcc/testsuite/g++.dg/cpp0x/forw_enum4.C index 0fcc3bde0f5..162b4bf332e 100644 --- a/gcc/testsuite/g++.dg/cpp0x/forw_enum4.C +++ b/gcc/testsuite/g++.dg/cpp0x/forw_enum4.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<typename T> struct S1 { diff --git a/gcc/testsuite/g++.dg/cpp0x/forw_enum5.C b/gcc/testsuite/g++.dg/cpp0x/forw_enum5.C index a2edfa7635c..a0e74863306 100644 --- a/gcc/testsuite/g++.dg/cpp0x/forw_enum5.C +++ b/gcc/testsuite/g++.dg/cpp0x/forw_enum5.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } namespace one { diff --git a/gcc/testsuite/g++.dg/cpp0x/forw_enum6.C b/gcc/testsuite/g++.dg/cpp0x/forw_enum6.C index 51ef6e43ec7..a42d93c47b0 100644 --- a/gcc/testsuite/g++.dg/cpp0x/forw_enum6.C +++ b/gcc/testsuite/g++.dg/cpp0x/forw_enum6.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } enum class E1 : int; // { dg-error "previous definition" } enum E1 : int; // { dg-error "scoped/unscoped mismatch" } diff --git a/gcc/testsuite/g++.dg/cpp0x/forw_enum7.C b/gcc/testsuite/g++.dg/cpp0x/forw_enum7.C index 62e445c707b..34e9af077d2 100644 --- a/gcc/testsuite/g++.dg/cpp0x/forw_enum7.C +++ b/gcc/testsuite/g++.dg/cpp0x/forw_enum7.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<typename T> struct S1 { diff --git a/gcc/testsuite/g++.dg/cpp0x/forw_enum8.C b/gcc/testsuite/g++.dg/cpp0x/forw_enum8.C index 69e73119e0c..1d85162aa2d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/forw_enum8.C +++ b/gcc/testsuite/g++.dg/cpp0x/forw_enum8.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } //This instatiation is ok template<typename T> struct S1 diff --git a/gcc/testsuite/g++.dg/cpp0x/forw_enum9.C b/gcc/testsuite/g++.dg/cpp0x/forw_enum9.C index da8cde27b40..ba7d3c76717 100644 --- a/gcc/testsuite/g++.dg/cpp0x/forw_enum9.C +++ b/gcc/testsuite/g++.dg/cpp0x/forw_enum9.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<typename T> struct S1 { diff --git a/gcc/testsuite/g++.dg/cpp0x/friend1.C b/gcc/testsuite/g++.dg/cpp0x/friend1.C index 2cf4c3c715a..838d250b23b 100644 --- a/gcc/testsuite/g++.dg/cpp0x/friend1.C +++ b/gcc/testsuite/g++.dg/cpp0x/friend1.C @@ -1,5 +1,5 @@ // From N1791 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } class C; typedef C Ct; diff --git a/gcc/testsuite/g++.dg/cpp0x/friend2.C b/gcc/testsuite/g++.dg/cpp0x/friend2.C index 39276a05ac3..7dbc8946b23 100644 --- a/gcc/testsuite/g++.dg/cpp0x/friend2.C +++ b/gcc/testsuite/g++.dg/cpp0x/friend2.C @@ -1,5 +1,5 @@ // PR c++/47721 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } // template type parameter friend: diff --git a/gcc/testsuite/g++.dg/cpp0x/implicit-copy.C b/gcc/testsuite/g++.dg/cpp0x/implicit-copy.C index c3f6b85e247..70454dbf9c3 100644 --- a/gcc/testsuite/g++.dg/cpp0x/implicit-copy.C +++ b/gcc/testsuite/g++.dg/cpp0x/implicit-copy.C @@ -1,4 +1,4 @@ -// { dg-options "--std=c++0x" } +// { dg-options "--std=c++11" } struct S { S(); diff --git a/gcc/testsuite/g++.dg/cpp0x/implicit-trivial1.C b/gcc/testsuite/g++.dg/cpp0x/implicit-trivial1.C index 64084c14855..7ab73bd22cf 100644 --- a/gcc/testsuite/g++.dg/cpp0x/implicit-trivial1.C +++ b/gcc/testsuite/g++.dg/cpp0x/implicit-trivial1.C @@ -1,8 +1,8 @@ // PR c++/46807 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } // In C++98/03, B::B(const B&) is trivial because A::A(const A&) is trivial, // even though doing overload resolution would mean calling the template -// constructor. In C++0x, we do overload resolution to determine triviality. +// constructor. In C++11, we do overload resolution to determine triviality. struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/implicit1.C b/gcc/testsuite/g++.dg/cpp0x/implicit1.C index e4e16e1ad35..777ed549249 100644 --- a/gcc/testsuite/g++.dg/cpp0x/implicit1.C +++ b/gcc/testsuite/g++.dg/cpp0x/implicit1.C @@ -1,5 +1,5 @@ // Test for implicitly deleted destructors. -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // { dg-prune-output "default definition would be ill-formed" } // { dg-prune-output "within this context" } diff --git a/gcc/testsuite/g++.dg/cpp0x/implicit10.C b/gcc/testsuite/g++.dg/cpp0x/implicit10.C index 721a93dd57e..fcc47616f76 100644 --- a/gcc/testsuite/g++.dg/cpp0x/implicit10.C +++ b/gcc/testsuite/g++.dg/cpp0x/implicit10.C @@ -1,5 +1,5 @@ // PR c++/46103 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct MoveOnly { MoveOnly(const MoveOnly&) = delete; diff --git a/gcc/testsuite/g++.dg/cpp0x/implicit11.C b/gcc/testsuite/g++.dg/cpp0x/implicit11.C index c974e2b7761..9f5841d17cf 100644 --- a/gcc/testsuite/g++.dg/cpp0x/implicit11.C +++ b/gcc/testsuite/g++.dg/cpp0x/implicit11.C @@ -1,6 +1,6 @@ // Test that we consider base dtors in determining whether // a derived ctor is deleted even if the ctor is trivial. -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { @@ -12,6 +12,6 @@ struct B: A { }; // { dg-error "deleted" } extern B eb; int main() { - B* b1 = new B; // { dg-error "use of deleted function" "" { xfail *-*-* } } + B* b1 = new B; // { dg-error "use of deleted function" } B* b2 = new B(eb); // { dg-error "use of deleted function" } } diff --git a/gcc/testsuite/g++.dg/cpp0x/implicit12.C b/gcc/testsuite/g++.dg/cpp0x/implicit12.C index da806e006a6..ab51a87005f 100644 --- a/gcc/testsuite/g++.dg/cpp0x/implicit12.C +++ b/gcc/testsuite/g++.dg/cpp0x/implicit12.C @@ -1,5 +1,5 @@ // PR c++/50500 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // If a class declares move operations, the implicitly declared copy // operations are deleted. diff --git a/gcc/testsuite/g++.dg/cpp0x/implicit2.C b/gcc/testsuite/g++.dg/cpp0x/implicit2.C index f24a78838fa..ae516b7fe82 100644 --- a/gcc/testsuite/g++.dg/cpp0x/implicit2.C +++ b/gcc/testsuite/g++.dg/cpp0x/implicit2.C @@ -1,6 +1,6 @@ // Test that the synthesized C copy constructor calls the A template // constructor and has the appropriate exception specification. -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } // { dg-do run } int r = 1; diff --git a/gcc/testsuite/g++.dg/cpp0x/implicit3.C b/gcc/testsuite/g++.dg/cpp0x/implicit3.C index a43eca708c0..abef33a8e63 100644 --- a/gcc/testsuite/g++.dg/cpp0x/implicit3.C +++ b/gcc/testsuite/g++.dg/cpp0x/implicit3.C @@ -1,6 +1,6 @@ // Basic runtime test for implicit move constructor // { dg-do run } -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } int m; diff --git a/gcc/testsuite/g++.dg/cpp0x/implicit4.C b/gcc/testsuite/g++.dg/cpp0x/implicit4.C index 47fd56a5252..16cd4b4a0f0 100644 --- a/gcc/testsuite/g++.dg/cpp0x/implicit4.C +++ b/gcc/testsuite/g++.dg/cpp0x/implicit4.C @@ -1,6 +1,6 @@ // Test that a base with only a move constructor causes the implicit copy // constructor to be deleted. -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } struct A // { dg-message "declares a move" } { diff --git a/gcc/testsuite/g++.dg/cpp0x/implicit5.C b/gcc/testsuite/g++.dg/cpp0x/implicit5.C index d25294831e3..89ab44a2c30 100644 --- a/gcc/testsuite/g++.dg/cpp0x/implicit5.C +++ b/gcc/testsuite/g++.dg/cpp0x/implicit5.C @@ -1,6 +1,6 @@ // Test that the default B copy constructor calls the deleted A // copy constructor. -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A // { dg-message "declares a move" } { diff --git a/gcc/testsuite/g++.dg/cpp0x/implicit6.C b/gcc/testsuite/g++.dg/cpp0x/implicit6.C index c7902969dce..41781fb83d1 100644 --- a/gcc/testsuite/g++.dg/cpp0x/implicit6.C +++ b/gcc/testsuite/g++.dg/cpp0x/implicit6.C @@ -1,5 +1,5 @@ // Circular implicit declarations were causing errors -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct Ray; diff --git a/gcc/testsuite/g++.dg/cpp0x/implicit7.C b/gcc/testsuite/g++.dg/cpp0x/implicit7.C index f29e5009fbd..4d9d6a6076c 100644 --- a/gcc/testsuite/g++.dg/cpp0x/implicit7.C +++ b/gcc/testsuite/g++.dg/cpp0x/implicit7.C @@ -1,5 +1,5 @@ // PR c++/44909 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } // Declaring A<D<E>>'s copy ctor means choosing a ctor to initialize D<E>, // which means choosing a ctor for C<B<E>>, which meant considering // C(const B<E>&) which means choosing a ctor for B<E>, which means choosing diff --git a/gcc/testsuite/g++.dg/cpp0x/implicit8.C b/gcc/testsuite/g++.dg/cpp0x/implicit8.C index c949af21050..ba7f1b62a8e 100644 --- a/gcc/testsuite/g++.dg/cpp0x/implicit8.C +++ b/gcc/testsuite/g++.dg/cpp0x/implicit8.C @@ -1,6 +1,6 @@ // The hack for PR c++/44909 breaks this testcase. We need feedback // from the C++ committee to know how to proceed. -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/implicit9.C b/gcc/testsuite/g++.dg/cpp0x/implicit9.C index 3a6dbc558d9..dd5dd76e0f2 100644 --- a/gcc/testsuite/g++.dg/cpp0x/implicit9.C +++ b/gcc/testsuite/g++.dg/cpp0x/implicit9.C @@ -1,5 +1,5 @@ // Test that private base dtor makes derived ctor deleted -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-array2.C b/gcc/testsuite/g++.dg/cpp0x/initlist-array2.C index 19eec33acf7..6eb5bf25e3d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist-array2.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist-array2.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } typedef int IA[2]; typedef double DA[2]; diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-arrray1.C b/gcc/testsuite/g++.dg/cpp0x/initlist-arrray1.C index 25113d770b0..e3008cc559c 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist-arrray1.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist-arrray1.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } typedef int IRT[2]; diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-deduce.C b/gcc/testsuite/g++.dg/cpp0x/initlist-deduce.C index 0ffcb3bcbae..13ac0b3fec4 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist-deduce.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist-deduce.C @@ -2,7 +2,7 @@ // supported by the working draft, but is necessary for perfect forwarding // of initializer-lists to things that can take a std::initializer_list. -// { dg-options "-std=c++0x -fdeduce-init-list" } +// { dg-options "-std=c++11 -fdeduce-init-list" } // { dg-do run } #include <initializer_list> diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-lifetime1.C b/gcc/testsuite/g++.dg/cpp0x/initlist-lifetime1.C index e43ce5d62cd..673a05fcb59 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist-lifetime1.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist-lifetime1.C @@ -1,6 +1,6 @@ // Test that we properly extend the lifetime of the initializer_list // array even if the initializer_list is a subobject. -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } // { dg-do run } #include <initializer_list> diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-lifetime2.C b/gcc/testsuite/g++.dg/cpp0x/initlist-lifetime2.C index 16ae1ac6e07..914b2c82d47 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist-lifetime2.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist-lifetime2.C @@ -1,6 +1,6 @@ // Test that we properly extend the lifetime of the initializer_list // array even if the initializer_list is a subobject. -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } // { dg-do run } #include <initializer_list> diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-opt.C b/gcc/testsuite/g++.dg/cpp0x/initlist-opt.C index d17cda3f63a..9999f2ebe86 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist-opt.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist-opt.C @@ -1,5 +1,5 @@ // PR c++/41997 -// { dg-options "-std=c++0x -O2 -fdump-tree-optimized" } +// { dg-options "-std=c++11 -O2 -fdump-tree-optimized" } // { dg-final { scan-tree-dump-not "_0" "optimized" } } // { dg-final { cleanup-tree-dump "optimized" } } diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-postfix-open-square.C b/gcc/testsuite/g++.dg/cpp0x/initlist-postfix-open-square.C index 38b17820db3..87c926ef6e2 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist-postfix-open-square.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist-postfix-open-square.C @@ -1,5 +1,5 @@ // PR c++/51738 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct Index { diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-value.C b/gcc/testsuite/g++.dg/cpp0x/initlist-value.C index 215bb90d4df..bb40b786d30 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist-value.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist-value.C @@ -1,5 +1,5 @@ // Test for value-initialization via {} -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } // { dg-do run } void * operator new (__SIZE_TYPE__, void *p) { return p; } diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-value2.C b/gcc/testsuite/g++.dg/cpp0x/initlist-value2.C index 2b78241e956..594d814e405 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist-value2.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist-value2.C @@ -2,7 +2,7 @@ // constructor but defaulted default constructor. The FDIS got this // wrong; see c++std-core-19883. -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } // { dg-do run } struct A diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist1.C b/gcc/testsuite/g++.dg/cpp0x/initlist1.C index ff45f7176f6..fab577130d7 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist1.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist1.C @@ -1,6 +1,6 @@ // Basic uses of initializer lists // { dg-do run } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } #include <initializer_list> diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist10.C b/gcc/testsuite/g++.dg/cpp0x/initlist10.C index bf955f513e3..0f78b2c5f66 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist10.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist10.C @@ -1,5 +1,5 @@ // PR c++/38380 -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } namespace std { diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist11.C b/gcc/testsuite/g++.dg/cpp0x/initlist11.C index 546a5335f1a..1948d3ec534 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist11.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist11.C @@ -1,5 +1,5 @@ // PR c++/38684 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } #include <initializer_list> diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist12.C b/gcc/testsuite/g++.dg/cpp0x/initlist12.C index f344c780cc2..f18f48f3290 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist12.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist12.C @@ -1,5 +1,5 @@ // PR c++/38698 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // { dg-prune-output "note" } struct A diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist13.C b/gcc/testsuite/g++.dg/cpp0x/initlist13.C index bc5ee2c3aec..53c90590a29 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist13.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist13.C @@ -1,6 +1,6 @@ // PR c++/39056 // { dg-do compile } -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } #include <complex> diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist14.C b/gcc/testsuite/g++.dg/cpp0x/initlist14.C index bb67f3e54da..1760c612a8d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist14.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist14.C @@ -1,6 +1,6 @@ // Bug: We weren't doing the normal replacement of array with pointer // for deduction in the context of a call because of the initializer list. -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } #include <initializer_list> diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist15.C b/gcc/testsuite/g++.dg/cpp0x/initlist15.C index b75cc81729f..55fc4a47936 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist15.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist15.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // Just discard errors pointing at header files // { dg-prune-output "include" } diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist16.C b/gcc/testsuite/g++.dg/cpp0x/initlist16.C index 86a00396051..b6d1b1a09a8 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist16.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist16.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // { dg-do run } extern "C" void abort(); diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist17.C b/gcc/testsuite/g++.dg/cpp0x/initlist17.C index 6ea08d15003..4e78bad91d8 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist17.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist17.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x -pedantic-errors" } +// { dg-options "-std=c++11 -pedantic-errors" } void f(int i); diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist18.C b/gcc/testsuite/g++.dg/cpp0x/initlist18.C index c9a9bcd9415..755c267d6cd 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist18.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist18.C @@ -1,6 +1,6 @@ // PR c++/40308, 40311 // { dg-do run } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template< typename T > struct test { diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist19.C b/gcc/testsuite/g++.dg/cpp0x/initlist19.C index 9cb197c9be2..6edd069c94c 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist19.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist19.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // Allow other errors, too // { dg-prune-output "error" } diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist2.C b/gcc/testsuite/g++.dg/cpp0x/initlist2.C index 2fe4770560d..c0133dd2523 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist2.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist2.C @@ -2,7 +2,7 @@ // user-defined conversions. // { dg-do link } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } #include <initializer_list> diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist20.C b/gcc/testsuite/g++.dg/cpp0x/initlist20.C index fcdb73f190c..ce2982b7f51 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist20.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist20.C @@ -1,5 +1,5 @@ // PR c++/40689 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } class X { diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist21.C b/gcc/testsuite/g++.dg/cpp0x/initlist21.C index 16923f87d7d..bad9e003d8f 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist21.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist21.C @@ -1,5 +1,5 @@ // PR c++/40689 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } class X { diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist22.C b/gcc/testsuite/g++.dg/cpp0x/initlist22.C index 0855b59d5d5..f913aebb906 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist22.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist22.C @@ -1,5 +1,5 @@ // Core issue 934 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } int i; diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist23.C b/gcc/testsuite/g++.dg/cpp0x/initlist23.C index 48a997fca20..bc37fe601a5 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist23.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist23.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } #include <initializer_list> diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist24.C b/gcc/testsuite/g++.dg/cpp0x/initlist24.C index 33e97c7dfb4..e4c99c4fc8f 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist24.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist24.C @@ -1,5 +1,5 @@ // PR c++/39923 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } #include <initializer_list> diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist25.C b/gcc/testsuite/g++.dg/cpp0x/initlist25.C index 8e5e0065cfc..cf0bfdaeb13 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist25.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist25.C @@ -1,5 +1,5 @@ // PR c++/41754 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } // { dg-do run } #include <map> diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist26.C b/gcc/testsuite/g++.dg/cpp0x/initlist26.C index bb28bdbd9b3..1b9dfcad6fd 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist26.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist26.C @@ -1,6 +1,6 @@ // PR c++/42059 // { dg-do compile } -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } void foo (int i) diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist27.C b/gcc/testsuite/g++.dg/cpp0x/initlist27.C index f8536d3e7e7..95f93ac43aa 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist27.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist27.C @@ -1,5 +1,5 @@ // PR c++/42061 // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } int& i = { j }; // { dg-error "invalid initialization|was not declared" } diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist28.C b/gcc/testsuite/g++.dg/cpp0x/initlist28.C index d1df7cb0044..b4125a5b43d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist28.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist28.C @@ -1,5 +1,5 @@ // PR c++/42060 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } void foo() { diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist29.C b/gcc/testsuite/g++.dg/cpp0x/initlist29.C index 1568678e0d0..dbedeb9d29e 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist29.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist29.C @@ -1,5 +1,5 @@ // PR c++/42331 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } class Mesh { diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist3.C b/gcc/testsuite/g++.dg/cpp0x/initlist3.C index 412deb51129..063a08f5633 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist3.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist3.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } #include <initializer_list> diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist30.C b/gcc/testsuite/g++.dg/cpp0x/initlist30.C index a5bdb2eda91..e2c21ab17a3 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist30.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist30.C @@ -1,5 +1,5 @@ // Testcase for variadic init list deduction. -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } #include <initializer_list> diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist31.C b/gcc/testsuite/g++.dg/cpp0x/initlist31.C index ffc985567ed..85594a6fcf1 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist31.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist31.C @@ -1,5 +1,5 @@ // PR c++/43028 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } #include <initializer_list> diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist32.C b/gcc/testsuite/g++.dg/cpp0x/initlist32.C index 78bbb5ef996..7db5e78fd6f 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist32.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist32.C @@ -1,5 +1,5 @@ // Test that we try normal init if no list ctor is viable. -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } #include <initializer_list> diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist33.C b/gcc/testsuite/g++.dg/cpp0x/initlist33.C index b1c0ba09b5e..6376473922b 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist33.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist33.C @@ -1,5 +1,5 @@ // PR c++/44045 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } struct base { diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist34.C b/gcc/testsuite/g++.dg/cpp0x/initlist34.C index 92f5a3a4605..20df3432b05 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist34.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist34.C @@ -1,5 +1,5 @@ // PR c++/44157 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } #include <initializer_list> diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist35.C b/gcc/testsuite/g++.dg/cpp0x/initlist35.C index e5b7cb4bd52..4b8547504c1 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist35.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist35.C @@ -1,5 +1,5 @@ // PR c++/41510 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } struct B { diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist36.C b/gcc/testsuite/g++.dg/cpp0x/initlist36.C index a703b45907e..2d412466aef 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist36.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist36.C @@ -1,5 +1,5 @@ // PR c++/44358 -// { dg-options "-std=c++0x -pedantic-errors" } +// { dg-options "-std=c++11 -pedantic-errors" } #include <initializer_list> diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist37.C b/gcc/testsuite/g++.dg/cpp0x/initlist37.C index 20c6ab6311f..8fed990eb05 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist37.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist37.C @@ -1,5 +1,5 @@ // DR 990 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } #include <initializer_list> diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist38.C b/gcc/testsuite/g++.dg/cpp0x/initlist38.C index 32e20d591c7..1a4b8e50549 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist38.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist38.C @@ -1,5 +1,5 @@ // DR 990 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } #include <initializer_list> diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist39.C b/gcc/testsuite/g++.dg/cpp0x/initlist39.C index a6dd1ec43d1..afd8315496a 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist39.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist39.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { int i; }; diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist4.C b/gcc/testsuite/g++.dg/cpp0x/initlist4.C index d1ffab8546c..8e5edb9abc4 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist4.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist4.C @@ -1,5 +1,5 @@ // Test for initializer-list 'explicit' rule -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist40.C b/gcc/testsuite/g++.dg/cpp0x/initlist40.C index 8cf36be1ca1..0592fa23f96 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist40.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist40.C @@ -1,5 +1,5 @@ // PR c++/54835, DR 1518 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist41.C b/gcc/testsuite/g++.dg/cpp0x/initlist41.C index b5385480c89..f07cf1dd832 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist41.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist41.C @@ -1,5 +1,5 @@ // PR c++/44703 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } #include <initializer_list> diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist42.C b/gcc/testsuite/g++.dg/cpp0x/initlist42.C index e63959deb21..c1ab63dc2e0 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist42.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist42.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } enum Unscoped { }; enum class Scoped { }; diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist43.C b/gcc/testsuite/g++.dg/cpp0x/initlist43.C index 72a09bdea49..6e524f4bf63 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist43.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist43.C @@ -1,5 +1,5 @@ // Test that using T{} at file scope doesn't create a static temporary. -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } // { dg-final { scan-assembler-not "local" } } struct A { }; diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist44.C b/gcc/testsuite/g++.dg/cpp0x/initlist44.C index fbe0ea3fefe..1c6403336a9 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist44.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist44.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } #include <initializer_list> diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist45.C b/gcc/testsuite/g++.dg/cpp0x/initlist45.C index 0e34bc18977..c4c1867bf67 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist45.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist45.C @@ -1,5 +1,5 @@ // PR c++/46289 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist46.C b/gcc/testsuite/g++.dg/cpp0x/initlist46.C index 2b9f07dbdc9..64bc314ffbd 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist46.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist46.C @@ -1,5 +1,5 @@ // PR c++/48281 -// { dg-options "-std=c++0x -O2" } +// { dg-options "-std=c++11 -O2" } // { dg-do run } #include <initializer_list> diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist47.C b/gcc/testsuite/g++.dg/cpp0x/initlist47.C index 06d683e038a..91f7d5edd84 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist47.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist47.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { ~A() = delete; }; // { dg-message "declared" } diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist48.C b/gcc/testsuite/g++.dg/cpp0x/initlist48.C index 9eb451a8277..b8a5cf2d960 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist48.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist48.C @@ -1,5 +1,5 @@ // PR c++/48726 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } #include <memory> diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist49.C b/gcc/testsuite/g++.dg/cpp0x/initlist49.C index 752c4331afb..cfed1547423 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist49.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist49.C @@ -1,5 +1,5 @@ // Test for non-trivial list-initialization with array new. -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } // { dg-do run } struct A diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist5.C b/gcc/testsuite/g++.dg/cpp0x/initlist5.C index 51345c73fc1..ed8f00a7a73 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist5.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist5.C @@ -1,5 +1,5 @@ // Test for narrowing diagnostics -// { dg-options "-std=c++0x -pedantic-errors" } +// { dg-options "-std=c++11 -pedantic-errors" } #include <initializer_list> diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist50.C b/gcc/testsuite/g++.dg/cpp0x/initlist50.C index 5cb23e2db3e..50b5d18efb3 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist50.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist50.C @@ -1,5 +1,5 @@ // PR c++/45418 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A1 { }; struct A2 { diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist51.C b/gcc/testsuite/g++.dg/cpp0x/initlist51.C index 9163dd3a867..1a63570f6a9 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist51.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist51.C @@ -1,5 +1,5 @@ // PR c++/47184 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct S { diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist52.C b/gcc/testsuite/g++.dg/cpp0x/initlist52.C index 17c0cfe3f14..8a70513bca9 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist52.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist52.C @@ -1,5 +1,5 @@ // PR c++/45378 -// { dg-options "-std=c++0x -pedantic-errors" } +// { dg-options "-std=c++11 -pedantic-errors" } int main() { diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist53.C b/gcc/testsuite/g++.dg/cpp0x/initlist53.C index 22633f90955..8e5332704be 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist53.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist53.C @@ -1,5 +1,5 @@ // PR c++/49216 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } // { dg-do run } #include <initializer_list> diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist54.C b/gcc/testsuite/g++.dg/cpp0x/initlist54.C index cdb296133f8..d50c230dba6 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist54.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist54.C @@ -1,5 +1,5 @@ // PR c++/49355 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } #include <string> diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist55.C b/gcc/testsuite/g++.dg/cpp0x/initlist55.C index cb42e81ed6a..917bc935470 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist55.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist55.C @@ -1,5 +1,5 @@ // Test for -Wno-narrowing -// { dg-options "-std=c++0x -pedantic-errors -Wno-narrowing" } +// { dg-options "-std=c++11 -pedantic-errors -Wno-narrowing" } int i; float d = { i }; diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist56.C b/gcc/testsuite/g++.dg/cpp0x/initlist56.C index 862b41bb3c8..72ad364ef27 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist56.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist56.C @@ -1,5 +1,5 @@ // PR c++/47453 -// { dg-options "-std=c++0x -pedantic-errors" } +// { dg-options "-std=c++11 -pedantic-errors" } // invalid int a({0}); // { dg-error "" } diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist57.C b/gcc/testsuite/g++.dg/cpp0x/initlist57.C index d945a468988..1a44b8124d0 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist57.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist57.C @@ -1,5 +1,5 @@ // PR c++/50054 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } void g( const int& (a)[1] ) {} // { dg-error "array of references" } diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist58.C b/gcc/testsuite/g++.dg/cpp0x/initlist58.C index dfb9f0cd508..a04e191b57d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist58.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist58.C @@ -1,5 +1,5 @@ // PR c++/50209 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct S { int i,j; }; diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist59.C b/gcc/testsuite/g++.dg/cpp0x/initlist59.C index 2cc015d1fee..3974042d26e 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist59.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist59.C @@ -1,5 +1,5 @@ // PR c++/49996 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist6.C b/gcc/testsuite/g++.dg/cpp0x/initlist6.C index 523570315eb..631bbd0407a 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist6.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist6.C @@ -1,5 +1,5 @@ // Test for initlist lifetime -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // { dg-do run } #include <initializer_list> diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist62.C b/gcc/testsuite/g++.dg/cpp0x/initlist62.C index cabbcd1db4e..3a25e13f1ef 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist62.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist62.C @@ -1,5 +1,5 @@ // PR c++/51399 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } #include <initializer_list> diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist64.C b/gcc/testsuite/g++.dg/cpp0x/initlist64.C index bcf1658074d..1550d477fb3 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist64.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist64.C @@ -1,5 +1,5 @@ // PR c++/51553 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct X { diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist7.C b/gcc/testsuite/g++.dg/cpp0x/initlist7.C index 55a0371860f..73c924250bf 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist7.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist7.C @@ -1,5 +1,5 @@ // PR c++/37932 -// { dg-options "-std=c++0x -pedantic-errors" } +// { dg-options "-std=c++11 -pedantic-errors" } typedef enum { AA=1, BB=2 } my_enum; diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist8.C b/gcc/testsuite/g++.dg/cpp0x/initlist8.C index db63eee78b6..e2c85d70d20 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist8.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist8.C @@ -1,5 +1,5 @@ // PR c++/37740 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist9.C b/gcc/testsuite/g++.dg/cpp0x/initlist9.C index 197fdd4ad04..0ad39463bc0 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist9.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist9.C @@ -1,5 +1,5 @@ // PR c++/37860 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } struct b { diff --git a/gcc/testsuite/g++.dg/cpp0x/inline-ns1.C b/gcc/testsuite/g++.dg/cpp0x/inline-ns1.C index e422d8970f1..287b7e072aa 100644 --- a/gcc/testsuite/g++.dg/cpp0x/inline-ns1.C +++ b/gcc/testsuite/g++.dg/cpp0x/inline-ns1.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } // { dg-final { scan-assembler "_ZN1Q2V11fEv" } } // { dg-final { scan-assembler "_ZN1Q2V11iE" } } diff --git a/gcc/testsuite/g++.dg/cpp0x/inline-ns2.C b/gcc/testsuite/g++.dg/cpp0x/inline-ns2.C index 17a8bf60192..19fb9adfe90 100644 --- a/gcc/testsuite/g++.dg/cpp0x/inline-ns2.C +++ b/gcc/testsuite/g++.dg/cpp0x/inline-ns2.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } namespace Q { inline namespace V1 { diff --git a/gcc/testsuite/g++.dg/cpp0x/inline-ns3.C b/gcc/testsuite/g++.dg/cpp0x/inline-ns3.C index 7c9d6b9b546..4e8449e30ec 100644 --- a/gcc/testsuite/g++.dg/cpp0x/inline-ns3.C +++ b/gcc/testsuite/g++.dg/cpp0x/inline-ns3.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } namespace C { diff --git a/gcc/testsuite/g++.dg/cpp0x/iop.C b/gcc/testsuite/g++.dg/cpp0x/iop.C index 2eb3a3ce337..34a5a5a1c2d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/iop.C +++ b/gcc/testsuite/g++.dg/cpp0x/iop.C @@ -7,7 +7,7 @@ // section "Revision 1 Summary and Rationale" for more details. // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // { dg-skip-if "packed attribute missing for struct one" { "epiphany-*-*" } { "*" } { "" } } template <bool> struct sa; diff --git a/gcc/testsuite/g++.dg/cpp0x/linkage2.C b/gcc/testsuite/g++.dg/cpp0x/linkage2.C index f41c21a7741..d9932948a20 100644 --- a/gcc/testsuite/g++.dg/cpp0x/linkage2.C +++ b/gcc/testsuite/g++.dg/cpp0x/linkage2.C @@ -4,7 +4,7 @@ // o the variable or function is not used (3.2 [basic.def.odr]) or is // defined in the same translation unit. -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template <typename T> struct B { void g(T){} diff --git a/gcc/testsuite/g++.dg/cpp0x/long_long.C b/gcc/testsuite/g++.dg/cpp0x/long_long.C index 3ef710df483..eb6a326bba3 100644 --- a/gcc/testsuite/g++.dg/cpp0x/long_long.C +++ b/gcc/testsuite/g++.dg/cpp0x/long_long.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x -pedantic" } +// { dg-options "-std=c++11 -pedantic" } void foo() { diff --git a/gcc/testsuite/g++.dg/cpp0x/move1.C b/gcc/testsuite/g++.dg/cpp0x/move1.C index 12e363a8cab..f86618a7036 100644 --- a/gcc/testsuite/g++.dg/cpp0x/move1.C +++ b/gcc/testsuite/g++.dg/cpp0x/move1.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x -pedantic-errors" } +// { dg-options "-std=c++11 -pedantic-errors" } #include <utility> diff --git a/gcc/testsuite/g++.dg/cpp0x/named.C b/gcc/testsuite/g++.dg/cpp0x/named.C index 2dff24ca475..e97f4f6fd6a 100644 --- a/gcc/testsuite/g++.dg/cpp0x/named.C +++ b/gcc/testsuite/g++.dg/cpp0x/named.C @@ -1,4 +1,4 @@ -// { dg-options "--std=c++0x" } +// { dg-options "--std=c++11" } // { dg-do link } template<typename _Tp> diff --git a/gcc/testsuite/g++.dg/cpp0x/named_refs.C b/gcc/testsuite/g++.dg/cpp0x/named_refs.C index 0ccd42f4a0f..f710f1e1f73 100644 --- a/gcc/testsuite/g++.dg/cpp0x/named_refs.C +++ b/gcc/testsuite/g++.dg/cpp0x/named_refs.C @@ -3,7 +3,7 @@ // Test: Named rvalue references are treated as lvalues. // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // { dg-skip-if "packed attribute missing for struct one" { "epiphany-*-*" } { "*" } { "" } } template <bool> struct sa; diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept01.C b/gcc/testsuite/g++.dg/cpp0x/noexcept01.C index b6be1ef7a3f..4526cd30158 100644 --- a/gcc/testsuite/g++.dg/cpp0x/noexcept01.C +++ b/gcc/testsuite/g++.dg/cpp0x/noexcept01.C @@ -1,5 +1,5 @@ // Test for noexcept-expression -// { dg-options "-std=c++0x -O2" } +// { dg-options "-std=c++11 -O2" } #include <typeinfo> diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept02.C b/gcc/testsuite/g++.dg/cpp0x/noexcept02.C index ffbb0919241..78831762491 100644 --- a/gcc/testsuite/g++.dg/cpp0x/noexcept02.C +++ b/gcc/testsuite/g++.dg/cpp0x/noexcept02.C @@ -1,5 +1,5 @@ // Test for noexcept-specification -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } #define SA(X) static_assert(X, #X) diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept03.C b/gcc/testsuite/g++.dg/cpp0x/noexcept03.C index 41c442e90be..b45cf365ce2 100644 --- a/gcc/testsuite/g++.dg/cpp0x/noexcept03.C +++ b/gcc/testsuite/g++.dg/cpp0x/noexcept03.C @@ -1,5 +1,5 @@ // Runtime test for noexcept-specification. -// { dg-options "-std=c++0x -Wnoexcept" } +// { dg-options "-std=c++11 -Wnoexcept" } // { dg-do run { target nonpic } } #include <exception> diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept04.C b/gcc/testsuite/g++.dg/cpp0x/noexcept04.C index 8df818610f5..6d31e5b4ca7 100644 --- a/gcc/testsuite/g++.dg/cpp0x/noexcept04.C +++ b/gcc/testsuite/g++.dg/cpp0x/noexcept04.C @@ -3,7 +3,7 @@ // the compiler doesn't get clever about optimizing the calls based on // knowledge about the called functions. -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // { dg-do run } #include <exception> diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept05.C b/gcc/testsuite/g++.dg/cpp0x/noexcept05.C index 6acea432736..8c74712b647 100644 --- a/gcc/testsuite/g++.dg/cpp0x/noexcept05.C +++ b/gcc/testsuite/g++.dg/cpp0x/noexcept05.C @@ -8,7 +8,7 @@ // { dg-final { scan-assembler-not "EHB" } } // { dg-final { scan-assembler "LSDA" } } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } struct A { ~A(); }; void g(); diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept06.C b/gcc/testsuite/g++.dg/cpp0x/noexcept06.C index 3babdffdad5..5168dc640fc 100644 --- a/gcc/testsuite/g++.dg/cpp0x/noexcept06.C +++ b/gcc/testsuite/g++.dg/cpp0x/noexcept06.C @@ -1,6 +1,6 @@ // Test that checking of a nothrow specification uses the one on the // definition. -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // { dg-do run } #include <exception> diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept07.C b/gcc/testsuite/g++.dg/cpp0x/noexcept07.C index 0a5773fc86b..f6df39f950e 100644 --- a/gcc/testsuite/g++.dg/cpp0x/noexcept07.C +++ b/gcc/testsuite/g++.dg/cpp0x/noexcept07.C @@ -1,6 +1,6 @@ // Test that checking of a nothrow specification uses the one on the // definition. -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // { dg-do run } #include <exception> diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept08.C b/gcc/testsuite/g++.dg/cpp0x/noexcept08.C index 1df85efff9c..bceebb7ca19 100644 --- a/gcc/testsuite/g++.dg/cpp0x/noexcept08.C +++ b/gcc/testsuite/g++.dg/cpp0x/noexcept08.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // { dg-prune-output "overriding" } struct A diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept09.C b/gcc/testsuite/g++.dg/cpp0x/noexcept09.C index 2a4525cbd6c..b50ef9975db 100644 --- a/gcc/testsuite/g++.dg/cpp0x/noexcept09.C +++ b/gcc/testsuite/g++.dg/cpp0x/noexcept09.C @@ -1,5 +1,5 @@ // Test that -Wnoexcept works with templates -// { dg-options "-std=c++0x -Wnoexcept" } +// { dg-options "-std=c++11 -Wnoexcept" } template <class T> T f (T t) { return t; } // { dg-warning "does not throw" } diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept10.C b/gcc/testsuite/g++.dg/cpp0x/noexcept10.C index 058a387d778..1e86ac205ba 100644 --- a/gcc/testsuite/g++.dg/cpp0x/noexcept10.C +++ b/gcc/testsuite/g++.dg/cpp0x/noexcept10.C @@ -1,5 +1,5 @@ // PR c++/49082 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } namespace std { template <class T> T&& declval() noexcept; } diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept11.C b/gcc/testsuite/g++.dg/cpp0x/noexcept11.C index b7c64a6ef06..879a63ee5e2 100644 --- a/gcc/testsuite/g++.dg/cpp0x/noexcept11.C +++ b/gcc/testsuite/g++.dg/cpp0x/noexcept11.C @@ -1,5 +1,5 @@ // PR c++/49107 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<typename _Tp> _Tp declval() noexcept; diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept12.C b/gcc/testsuite/g++.dg/cpp0x/noexcept12.C index 1fd1b032f4c..592504bd5e9 100644 --- a/gcc/testsuite/g++.dg/cpp0x/noexcept12.C +++ b/gcc/testsuite/g++.dg/cpp0x/noexcept12.C @@ -1,5 +1,5 @@ // Test that we handle merging with deferred noexcept. -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template <class U> struct O diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept13.C b/gcc/testsuite/g++.dg/cpp0x/noexcept13.C index 7d51c82b549..7e76200befe 100644 --- a/gcc/testsuite/g++.dg/cpp0x/noexcept13.C +++ b/gcc/testsuite/g++.dg/cpp0x/noexcept13.C @@ -1,5 +1,5 @@ // PR c++/49107 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } namespace std { diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept14.C b/gcc/testsuite/g++.dg/cpp0x/noexcept14.C index eba2c408089..e6afca2b43a 100644 --- a/gcc/testsuite/g++.dg/cpp0x/noexcept14.C +++ b/gcc/testsuite/g++.dg/cpp0x/noexcept14.C @@ -1,4 +1,4 @@ // PR c++/50309 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } void foo () noexcept () { } // { dg-error "expected" } diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept15.C b/gcc/testsuite/g++.dg/cpp0x/noexcept15.C index db5b5c7f3d7..efbd2ba90b6 100644 --- a/gcc/testsuite/g++.dg/cpp0x/noexcept15.C +++ b/gcc/testsuite/g++.dg/cpp0x/noexcept15.C @@ -1,5 +1,5 @@ // PR c++/50391 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } #include <type_traits> diff --git a/gcc/testsuite/g++.dg/cpp0x/nolinkage1.C b/gcc/testsuite/g++.dg/cpp0x/nolinkage1.C index b69b6ddc4cf..a7e6cd82c0d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nolinkage1.C +++ b/gcc/testsuite/g++.dg/cpp0x/nolinkage1.C @@ -3,7 +3,7 @@ // { dg-additional-sources "nolinkage1a.cc" } // { dg-do link } -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } #include "nolinkage1.h" diff --git a/gcc/testsuite/g++.dg/cpp0x/not_special.C b/gcc/testsuite/g++.dg/cpp0x/not_special.C index 2b510bb9a1b..7b3c4ad1e3d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/not_special.C +++ b/gcc/testsuite/g++.dg/cpp0x/not_special.C @@ -4,7 +4,7 @@ // That is, their presence should cause compiler declared // copy ctor or assignment to be deleted. -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } #include <assert.h> diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-const1.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-const1.C index ddf9f04c580..1051288a4d8 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nsdmi-const1.C +++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-const1.C @@ -1,5 +1,5 @@ // PR c++/50707 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } int g; diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer1.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer1.C index b3d9b935750..4398739c8cd 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer1.C +++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer1.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } #define SA(X) static_assert(X,#X) diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer2.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer2.C index 1951262f9da..e4b963c9436 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer2.C +++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer2.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer3.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer3.C index 2777fb5d8e6..3aae12c2a4c 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer3.C +++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer3.C @@ -1,5 +1,5 @@ // Do NSDMI get deferred instantiation? -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template <class T> struct A diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer4.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer4.C index 65b2e738077..9d39f29df6e 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer4.C +++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer4.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } // { dg-do run } struct A diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer5.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer5.C index 85abfbf8618..ada5104615d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer5.C +++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-defer5.C @@ -1,5 +1,5 @@ // PR c++/51666 (DR 325) -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<typename T, typename U> struct tuple diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-eh1.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-eh1.C index 09c92d2f158..301eb61053e 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nsdmi-eh1.C +++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-eh1.C @@ -1,6 +1,6 @@ // Core issue 1351 // { dg-do run { xfail *-*-* } } -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } bool fail; struct A diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-list1.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-list1.C index 526f29ae285..68af7353755 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nsdmi-list1.C +++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-list1.C @@ -1,5 +1,5 @@ // PR c++/50563 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct S1 { int a{10}, b{20}; // OK diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-list2.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-list2.C index a6321ffb605..0d71417389f 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nsdmi-list2.C +++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-list2.C @@ -1,5 +1,5 @@ // PR c++/50930 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct nmc { nmc() = default; diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-template1.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template1.C index 04f1e0391d9..aa77680f2e9 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nsdmi-template1.C +++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template1.C @@ -1,5 +1,5 @@ // { dg-do run } -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct base { diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-template2.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template2.C index 27b0aa5f9da..952949c8950 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nsdmi-template2.C +++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-template2.C @@ -1,5 +1,5 @@ // PR c++/50614 -// { dg-options "-std=c++0x -fcompare-debug" } +// { dg-options "-std=c++11 -fcompare-debug" } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-virtual1.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-virtual1.C index 4aa8d482da8..edf54bb1d2d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nsdmi-virtual1.C +++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-virtual1.C @@ -1,5 +1,5 @@ // PR c++/51611 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } // { dg-do run } struct A diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi1.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi1.C index 159c16de851..a840700e88c 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nsdmi1.C +++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi1.C @@ -1,5 +1,5 @@ // { dg-do run } -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi2.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi2.C index 9636bed8820..5be3366f1dd 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nsdmi2.C +++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi2.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi3.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi3.C index 73b2bc2e1ac..3024e731587 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nsdmi3.C +++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi3.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi4.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi4.C index db365cb55e5..08579eef194 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nsdmi4.C +++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi4.C @@ -1,5 +1,5 @@ // { dg-do run } -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } int c; diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi5.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi5.C index 62803b0819e..9b33346422c 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nsdmi5.C +++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi5.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct X { diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi9.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi9.C new file mode 100644 index 00000000000..febe0ecac46 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi9.C @@ -0,0 +1,13 @@ +// PR c++/58162 +// { dg-require-effective-target c++11 } + +struct A { + A(); + A(A&&); +}; + +struct B { + A const a = A(); +}; + +B b; diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr01.C b/gcc/testsuite/g++.dg/cpp0x/nullptr01.C index de3860c9ea4..27643e6b732 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nullptr01.C +++ b/gcc/testsuite/g++.dg/cpp0x/nullptr01.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // Test assignment to pointer diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr02.C b/gcc/testsuite/g++.dg/cpp0x/nullptr02.C index 80977cb2f00..7c330743b8c 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nullptr02.C +++ b/gcc/testsuite/g++.dg/cpp0x/nullptr02.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // Test assignment to nullptr_t diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr03.C b/gcc/testsuite/g++.dg/cpp0x/nullptr03.C index b6df8963740..aaf199ce0db 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nullptr03.C +++ b/gcc/testsuite/g++.dg/cpp0x/nullptr03.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // Test assignment to int diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr04.C b/gcc/testsuite/g++.dg/cpp0x/nullptr04.C index be581bcb6e3..999f05467c3 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nullptr04.C +++ b/gcc/testsuite/g++.dg/cpp0x/nullptr04.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // Test cast to int diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr05.C b/gcc/testsuite/g++.dg/cpp0x/nullptr05.C index 22a8b51c1c7..e6e6a1bb9d3 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nullptr05.C +++ b/gcc/testsuite/g++.dg/cpp0x/nullptr05.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // Test assignment to method pointer diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr06.C b/gcc/testsuite/g++.dg/cpp0x/nullptr06.C index c50bb9bc113..9b7b4dccfce 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nullptr06.C +++ b/gcc/testsuite/g++.dg/cpp0x/nullptr06.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // Test compare to pointer diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr07.C b/gcc/testsuite/g++.dg/cpp0x/nullptr07.C index 64d442be331..b2c27e81114 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nullptr07.C +++ b/gcc/testsuite/g++.dg/cpp0x/nullptr07.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // Test compare to int diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr08.C b/gcc/testsuite/g++.dg/cpp0x/nullptr08.C index 1e5db278ddf..d09e070eaa8 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nullptr08.C +++ b/gcc/testsuite/g++.dg/cpp0x/nullptr08.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // Test conversion to bool diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr09.C b/gcc/testsuite/g++.dg/cpp0x/nullptr09.C index b35a3c3207d..df6f5014a01 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nullptr09.C +++ b/gcc/testsuite/g++.dg/cpp0x/nullptr09.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // Test compare to literal 0 diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr10.C b/gcc/testsuite/g++.dg/cpp0x/nullptr10.C index fa32267ec02..4924dba9ce1 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nullptr10.C +++ b/gcc/testsuite/g++.dg/cpp0x/nullptr10.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // Test arithmetic operations diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr11.C b/gcc/testsuite/g++.dg/cpp0x/nullptr11.C index 5907816a847..91e8e71a3a8 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nullptr11.C +++ b/gcc/testsuite/g++.dg/cpp0x/nullptr11.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // Test relational operators diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr12.C b/gcc/testsuite/g++.dg/cpp0x/nullptr12.C index 1713259f103..0c131518297 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nullptr12.C +++ b/gcc/testsuite/g++.dg/cpp0x/nullptr12.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // Test sizeof diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr13.C b/gcc/testsuite/g++.dg/cpp0x/nullptr13.C index a9377584c56..c51c81ef962 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nullptr13.C +++ b/gcc/testsuite/g++.dg/cpp0x/nullptr13.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // Test typeid diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr14.C b/gcc/testsuite/g++.dg/cpp0x/nullptr14.C index 4c4627b541b..1e9e5173786 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nullptr14.C +++ b/gcc/testsuite/g++.dg/cpp0x/nullptr14.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // Test overload preference char*/int diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr15.C b/gcc/testsuite/g++.dg/cpp0x/nullptr15.C index af661ecc3af..1f91bae4fe5 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nullptr15.C +++ b/gcc/testsuite/g++.dg/cpp0x/nullptr15.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // Test template deduction diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr16.C b/gcc/testsuite/g++.dg/cpp0x/nullptr16.C index 0ec0b6a12b6..9456523037b 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nullptr16.C +++ b/gcc/testsuite/g++.dg/cpp0x/nullptr16.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // Test template deduction diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr17.C b/gcc/testsuite/g++.dg/cpp0x/nullptr17.C index 2e580557bc3..72884149525 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nullptr17.C +++ b/gcc/testsuite/g++.dg/cpp0x/nullptr17.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // Test that bool is a better overload match than int diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr18.C b/gcc/testsuite/g++.dg/cpp0x/nullptr18.C index b8fa38c718d..656628828f4 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nullptr18.C +++ b/gcc/testsuite/g++.dg/cpp0x/nullptr18.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // Test overload of pointer versus bool when applied on a nullptr_t diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr19.C b/gcc/testsuite/g++.dg/cpp0x/nullptr19.C index ecc36139a40..92e7f9a88d2 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nullptr19.C +++ b/gcc/testsuite/g++.dg/cpp0x/nullptr19.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // Test overload of pointer versus nullptr_t when applied on a literal 0/__null diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr20.C b/gcc/testsuite/g++.dg/cpp0x/nullptr20.C index 3e58406770d..6c07eced7d1 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nullptr20.C +++ b/gcc/testsuite/g++.dg/cpp0x/nullptr20.C @@ -1,5 +1,5 @@ // { dg-do run } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // Test passing to ellipisis diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr21.C b/gcc/testsuite/g++.dg/cpp0x/nullptr21.C index 8362bd2965b..0355b826062 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nullptr21.C +++ b/gcc/testsuite/g++.dg/cpp0x/nullptr21.C @@ -1,5 +1,5 @@ // { dg-do run } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // Test throw and catch diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr22.C b/gcc/testsuite/g++.dg/cpp0x/nullptr22.C index d800f9869d2..08c3b0ae037 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nullptr22.C +++ b/gcc/testsuite/g++.dg/cpp0x/nullptr22.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=c++0x -Wall -Wformat=2 -Wstrict-null-sentinel" } +// { dg-options "-std=c++11 -Wall -Wformat=2 -Wstrict-null-sentinel" } // Test various warnings diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr23.C b/gcc/testsuite/g++.dg/cpp0x/nullptr23.C index a078269de20..077cd36806e 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nullptr23.C +++ b/gcc/testsuite/g++.dg/cpp0x/nullptr23.C @@ -1,5 +1,5 @@ // PR c++/50361 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } #include <initializer_list> diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr24.C b/gcc/testsuite/g++.dg/cpp0x/nullptr24.C index f3917796627..e7833d11ef4 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nullptr24.C +++ b/gcc/testsuite/g++.dg/cpp0x/nullptr24.C @@ -1,5 +1,5 @@ // PR c++/50371 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<decltype(nullptr)> struct nt; diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr25.C b/gcc/testsuite/g++.dg/cpp0x/nullptr25.C index b8a7f45c674..bdc2ed3ad5c 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nullptr25.C +++ b/gcc/testsuite/g++.dg/cpp0x/nullptr25.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<decltype(nullptr)> struct nt{}; diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr26.C b/gcc/testsuite/g++.dg/cpp0x/nullptr26.C index b7421b8d048..457e3ae2d34 100644 --- a/gcc/testsuite/g++.dg/cpp0x/nullptr26.C +++ b/gcc/testsuite/g++.dg/cpp0x/nullptr26.C @@ -1,5 +1,5 @@ // PR c++/51530 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template <class T, class U> void f(T, U); diff --git a/gcc/testsuite/g++.dg/cpp0x/overload-conv-1.C b/gcc/testsuite/g++.dg/cpp0x/overload-conv-1.C index 778111283ff..2661060b6e7 100644 --- a/gcc/testsuite/g++.dg/cpp0x/overload-conv-1.C +++ b/gcc/testsuite/g++.dg/cpp0x/overload-conv-1.C @@ -1,4 +1,4 @@ -// { dg-options "--std=c++0x" } +// { dg-options "--std=c++11" } // { dg-do link } struct S {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/overload-conv-2.C b/gcc/testsuite/g++.dg/cpp0x/overload-conv-2.C index 0e622bcacb2..a3fdd3a8fa4 100644 --- a/gcc/testsuite/g++.dg/cpp0x/overload-conv-2.C +++ b/gcc/testsuite/g++.dg/cpp0x/overload-conv-2.C @@ -1,4 +1,4 @@ -// { dg-options "--std=c++0x" } +// { dg-options "--std=c++11" } // { dg-do link } struct T {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/overload.C b/gcc/testsuite/g++.dg/cpp0x/overload.C index 3782d4a208e..b10bb43fe11 100644 --- a/gcc/testsuite/g++.dg/cpp0x/overload.C +++ b/gcc/testsuite/g++.dg/cpp0x/overload.C @@ -1,4 +1,4 @@ -// { dg-options "--std=c++0x" } +// { dg-options "--std=c++11" } // { dg-do link } // Generated by overload.py diff --git a/gcc/testsuite/g++.dg/cpp0x/overload2.C b/gcc/testsuite/g++.dg/cpp0x/overload2.C index b335ea2be99..e532fa25d54 100644 --- a/gcc/testsuite/g++.dg/cpp0x/overload2.C +++ b/gcc/testsuite/g++.dg/cpp0x/overload2.C @@ -1,5 +1,5 @@ // Core 1321 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } // Two dependent names are equivalent even if the overload sets found by // phase 1 lookup are different. Merging them keeps the earlier set. diff --git a/gcc/testsuite/g++.dg/cpp0x/overloadn.C b/gcc/testsuite/g++.dg/cpp0x/overloadn.C index a42707fe4f1..00f9fde4900 100644 --- a/gcc/testsuite/g++.dg/cpp0x/overloadn.C +++ b/gcc/testsuite/g++.dg/cpp0x/overloadn.C @@ -1,4 +1,4 @@ -// { dg-options "--std=c++0x" } +// { dg-options "--std=c++11" } // { dg-do link } // Generated by overload.py diff --git a/gcc/testsuite/g++.dg/cpp0x/override1.C b/gcc/testsuite/g++.dg/cpp0x/override1.C index ba580b5c09f..5b487106bfa 100644 --- a/gcc/testsuite/g++.dg/cpp0x/override1.C +++ b/gcc/testsuite/g++.dg/cpp0x/override1.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "--std=c++0x" } +// { dg-options "--std=c++11" } struct B { virtual void f() final {} diff --git a/gcc/testsuite/g++.dg/cpp0x/override2.C b/gcc/testsuite/g++.dg/cpp0x/override2.C index 1a7a36e1ae0..e5a9aa6ac50 100644 --- a/gcc/testsuite/g++.dg/cpp0x/override2.C +++ b/gcc/testsuite/g++.dg/cpp0x/override2.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "--std=c++0x" } +// { dg-options "--std=c++11" } struct B1 {}; struct B2 final {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/parse1.C b/gcc/testsuite/g++.dg/cpp0x/parse1.C index 4fa7461cb22..0a86caf4ac4 100644 --- a/gcc/testsuite/g++.dg/cpp0x/parse1.C +++ b/gcc/testsuite/g++.dg/cpp0x/parse1.C @@ -1,5 +1,5 @@ // PR c++/43509 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } typedef int B; // { dg-message "" } B::B() {} // { dg-error "" } diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31431-2.C b/gcc/testsuite/g++.dg/cpp0x/pr31431-2.C index 076493938a8..95901e56aa1 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr31431-2.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr31431-2.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename, typename..., typename> void foo(); // { dg-message "note" } void bar() diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31431.C b/gcc/testsuite/g++.dg/cpp0x/pr31431.C index afd32371574..1e7507cd8b8 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr31431.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr31431.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename..., typename> void foo(); // { dg-message "note" } void bar() diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31432.C b/gcc/testsuite/g++.dg/cpp0x/pr31432.C index 8016ee69d75..f4de1973bd9 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr31432.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr31432.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename..., typename> struct A // { dg-error "parameter pack" } { static int i; diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31434.C b/gcc/testsuite/g++.dg/cpp0x/pr31434.C index 54786167c35..3bce5785eca 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr31434.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr31434.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename... T> int foo(const T&) // { dg-error "not expanded with|T" } { union { T t; }; // { dg-error "not expanded with|T" } diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31437.C b/gcc/testsuite/g++.dg/cpp0x/pr31437.C index 956a08b058d..b7a7bbf28bf 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr31437.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr31437.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template <typename... T> struct A // { dg-message "candidates|A" } { A(T* p) { // { dg-error "parameter packs|T" } diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31438.C b/gcc/testsuite/g++.dg/cpp0x/pr31438.C index 74738830ad1..26c34b05ae3 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr31438.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr31438.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename> struct A; template<typename T, typename... U> struct A<T(U)> // { dg-error "parameter packs|U" } diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31439.C b/gcc/testsuite/g++.dg/cpp0x/pr31439.C index c64bc3145b6..13221959bd9 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr31439.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr31439.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<typename...> struct A; template<char> struct A<> {}; // { dg-error "not used in partial specialization|anonymous|declaration" } diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31442.C b/gcc/testsuite/g++.dg/cpp0x/pr31442.C index f4e411c4505..bed4b57be97 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr31442.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr31442.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename... T, T = 0> struct A {}; // { dg-error "parameter packs|T|the end|parameter packs|anonymous" } struct B diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31443.C b/gcc/testsuite/g++.dg/cpp0x/pr31443.C index 1eb9d318de0..0decd759367 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr31443.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr31443.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<int, typename... T> struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31444.C b/gcc/testsuite/g++.dg/cpp0x/pr31444.C index b1f86fe7a7e..316ddb62187 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr31444.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr31444.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename... T> struct A { template<int> void foo(A<T>); // { dg-error "not expanded|T" } diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31445.C b/gcc/testsuite/g++.dg/cpp0x/pr31445.C index b3f2b5b09da..283eafb5990 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr31445.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr31445.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template <typename... T> struct A { void foo(T...); diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31993.C b/gcc/testsuite/g++.dg/cpp0x/pr31993.C index 94fb9ccdab9..39a73498fc8 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr31993.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr31993.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<typename...> struct A; diff --git a/gcc/testsuite/g++.dg/cpp0x/pr32114.C b/gcc/testsuite/g++.dg/cpp0x/pr32114.C index e78dfdf1df9..923187163b4 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr32114.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr32114.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<typename ...T> struct A { typedef typename T::X Y; // { dg-error "not expanded|T" } diff --git a/gcc/testsuite/g++.dg/cpp0x/pr32115.C b/gcc/testsuite/g++.dg/cpp0x/pr32115.C index a721eed4eb7..4e5700cdf73 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr32115.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr32115.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<typename ...T, int = 0> struct A {}; // { dg-error "end of" } A<int> a; // { dg-error "mismatch|expected|invalid" } diff --git a/gcc/testsuite/g++.dg/cpp0x/pr32125.C b/gcc/testsuite/g++.dg/cpp0x/pr32125.C index 210a29c0829..7b913605b8b 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr32125.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr32125.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<typename...> struct A; template<typename...T> struct A<T*> // { dg-error "not expanded|T" } diff --git a/gcc/testsuite/g++.dg/cpp0x/pr32126.C b/gcc/testsuite/g++.dg/cpp0x/pr32126.C index c525cca684b..c1cca94b869 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr32126.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr32126.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<typename...> struct A; template<typename...T> struct A<T> // { dg-error "not expanded|T|" } diff --git a/gcc/testsuite/g++.dg/cpp0x/pr32127.C b/gcc/testsuite/g++.dg/cpp0x/pr32127.C index 8e4bc0050b2..ca197ec4b3f 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr32127.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr32127.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<typename...T> struct A { static T i; // { dg-error "parameter packs|T" } diff --git a/gcc/testsuite/g++.dg/cpp0x/pr32128.C b/gcc/testsuite/g++.dg/cpp0x/pr32128.C index 5876dbec485..595e20e0876 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr32128.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr32128.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<typename...> struct A; template<typename...T, typename...U> diff --git a/gcc/testsuite/g++.dg/cpp0x/pr32252.C b/gcc/testsuite/g++.dg/cpp0x/pr32252.C index 543dc887390..f0f4b3ca610 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr32252.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr32252.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } int x[5]; template<int M, int N, int (&... p)[N]> struct A; diff --git a/gcc/testsuite/g++.dg/cpp0x/pr32253.C b/gcc/testsuite/g++.dg/cpp0x/pr32253.C index d8f7b03b92f..df30b6a7842 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr32253.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr32253.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<void (*... fp)()> struct A { A() { fp(); } // { dg-error "not expanded|fp" } diff --git a/gcc/testsuite/g++.dg/cpp0x/pr32566.C b/gcc/testsuite/g++.dg/cpp0x/pr32566.C index f6e7a5b548d..5802078f7c9 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr32566.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr32566.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<int...> struct A; template<template<int> class... T> struct A<T...> {}; // { dg-error "mismatch|expected" } diff --git a/gcc/testsuite/g++.dg/cpp0x/pr33839.C b/gcc/testsuite/g++.dg/cpp0x/pr33839.C index 0a6610ac995..b4d3a620339 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr33839.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr33839.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<int> struct A; void foo() diff --git a/gcc/testsuite/g++.dg/cpp0x/pr33930.C b/gcc/testsuite/g++.dg/cpp0x/pr33930.C index d1e6fa56b1d..814fb6537b9 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr33930.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr33930.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } typedef const int* type; float& foo( const type& ggg ); diff --git a/gcc/testsuite/g++.dg/cpp0x/pr33955.C b/gcc/testsuite/g++.dg/cpp0x/pr33955.C index cde92dedf97..191fe5c356d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr33955.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr33955.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<typename T> struct uncvref { diff --git a/gcc/testsuite/g++.dg/cpp0x/pr33996.C b/gcc/testsuite/g++.dg/cpp0x/pr33996.C index 07590f06f95..47829c04bc1 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr33996.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr33996.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } #define BUG struct type diff --git a/gcc/testsuite/g++.dg/cpp0x/pr34054.C b/gcc/testsuite/g++.dg/cpp0x/pr34054.C index cfc6c4bdc76..19fcece6ca5 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr34054.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr34054.C @@ -1,5 +1,5 @@ // PR c++/34054 // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<typename... T> T foo() {} // { dg-error "not expanded|T" } diff --git a/gcc/testsuite/g++.dg/cpp0x/pr34056.C b/gcc/testsuite/g++.dg/cpp0x/pr34056.C index 0e5246b6ab6..f227ce1a405 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr34056.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr34056.C @@ -1,6 +1,6 @@ // PR c++/34056 // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<typename... T> struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/pr34057.C b/gcc/testsuite/g++.dg/cpp0x/pr34057.C index 38da5ff5015..1c28c546b31 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr34057.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr34057.C @@ -1,6 +1,6 @@ // PR c++/34057 // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template <typename... T> struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/pr34058.C b/gcc/testsuite/g++.dg/cpp0x/pr34058.C index 0cf1faec73f..74dabc5151f 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr34058.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr34058.C @@ -1,6 +1,6 @@ // PR c++/34058 // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template <typename...T> struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/pr34060.C b/gcc/testsuite/g++.dg/cpp0x/pr34060.C index 8e0d321b2ac..6653eb68fc8 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr34060.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr34060.C @@ -1,6 +1,6 @@ // PR c++/34060 // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template <int> struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/pr34061.C b/gcc/testsuite/g++.dg/cpp0x/pr34061.C index 7d6e71d0e74..bb750f1d6cd 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr34061.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr34061.C @@ -1,5 +1,5 @@ // PR c++/34061 // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<template<int> class ...T> struct A : T<0> {}; // { dg-error "not expanded|T" } diff --git a/gcc/testsuite/g++.dg/cpp0x/pr38646.C b/gcc/testsuite/g++.dg/cpp0x/pr38646.C index f15fc8c29bb..2177aab8f02 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr38646.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr38646.C @@ -1,6 +1,6 @@ /* PR c++/38646 */ /* { dg-do compile } */ -/* { dg-options "-std=c++0x" } */ +/* { dg-options "-std=c++11" } */ template<int...> struct A; diff --git a/gcc/testsuite/g++.dg/cpp0x/pr38795.C b/gcc/testsuite/g++.dg/cpp0x/pr38795.C index 54fb361d3d4..bf44357fdf7 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr38795.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr38795.C @@ -1,6 +1,6 @@ // PR c++/38795 // { dg-do compile } -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename... T> int foo(int i) { diff --git a/gcc/testsuite/g++.dg/cpp0x/pr39639.C b/gcc/testsuite/g++.dg/cpp0x/pr39639.C index 0838a0ba25f..873c51e35f0 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr39639.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr39639.C @@ -1,7 +1,7 @@ // Contributed by Dodji Seketeli <dodji@redhat.com> // Origin: PR c++/39639 // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // { dg-prune-output "template argument 1 is invalid" } template <class... Types> diff --git a/gcc/testsuite/g++.dg/cpp0x/pr42844-2.C b/gcc/testsuite/g++.dg/cpp0x/pr42844-2.C index 4425aacf627..c7a02c2c738 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr42844-2.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr42844-2.C @@ -1,6 +1,6 @@ // PR c++/42844 // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } struct A // { dg-message "user-provided default constructor" } { diff --git a/gcc/testsuite/g++.dg/cpp0x/pr45908.C b/gcc/testsuite/g++.dg/cpp0x/pr45908.C index 45399b5395f..b50b7b03ca0 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr45908.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr45908.C @@ -2,7 +2,7 @@ // Testcase by Jonathan Wakely <redi@gcc.gnu.org> // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } struct vector { struct iterator { }; diff --git a/gcc/testsuite/g++.dg/cpp0x/pr47416.C b/gcc/testsuite/g++.dg/cpp0x/pr47416.C index 55426c1f81d..d7c5b13080a 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr47416.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr47416.C @@ -1,6 +1,6 @@ // PR c++/47416 // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } namespace std { diff --git a/gcc/testsuite/g++.dg/cpp0x/pr47476.C b/gcc/testsuite/g++.dg/cpp0x/pr47476.C index 1f6f09cccc6..dd386d17e8a 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr47476.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr47476.C @@ -1,6 +1,6 @@ // PR c++/47476 // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } int foo (int a, int b) diff --git a/gcc/testsuite/g++.dg/cpp0x/pr48522.C b/gcc/testsuite/g++.dg/cpp0x/pr48522.C index 1543d8a281d..4f1117b9e31 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr48522.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr48522.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template <typename T> struct Handle diff --git a/gcc/testsuite/g++.dg/cpp0x/pr50491.C b/gcc/testsuite/g++.dg/cpp0x/pr50491.C index 48e7a1f743b..c6177169a73 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr50491.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr50491.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } struct GrandParent { void *get(); diff --git a/gcc/testsuite/g++.dg/cpp0x/pr50901.C b/gcc/testsuite/g++.dg/cpp0x/pr50901.C index 439c15cc1cd..091952f3e68 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr50901.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr50901.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<class T> int foo(int a) { diff --git a/gcc/testsuite/g++.dg/cpp0x/pr51150.C b/gcc/testsuite/g++.dg/cpp0x/pr51150.C index 37eb166b43e..8fe2b6f0f2b 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr51150.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr51150.C @@ -1,5 +1,5 @@ // PR c++/51150 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } struct Clock { double Now(); diff --git a/gcc/testsuite/g++.dg/cpp0x/pr51216.C b/gcc/testsuite/g++.dg/cpp0x/pr51216.C index 4bdd071475e..0433c848f09 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr51216.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr51216.C @@ -1,5 +1,5 @@ // PR c++/51216 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } void foo() { diff --git a/gcc/testsuite/g++.dg/cpp0x/pr51225.C b/gcc/testsuite/g++.dg/cpp0x/pr51225.C index 6fcf8611f9c..a9f1cf0dc67 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr51225.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr51225.C @@ -1,5 +1,5 @@ // PR c++/51225 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<int> struct A {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/pr51313.C b/gcc/testsuite/g++.dg/cpp0x/pr51313.C index ff078e02d67..20332963564 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr51313.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr51313.C @@ -1,5 +1,5 @@ // PR c++/51313 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } class ostream; diff --git a/gcc/testsuite/g++.dg/cpp0x/pr51547.C b/gcc/testsuite/g++.dg/cpp0x/pr51547.C index 80215f6a341..5fae55a5f9c 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr51547.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr51547.C @@ -1,5 +1,5 @@ // PR c++/51547 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template <class T> struct vector diff --git a/gcc/testsuite/g++.dg/cpp0x/pr51619.C b/gcc/testsuite/g++.dg/cpp0x/pr51619.C index dd51679158d..75a922091aa 100644 --- a/gcc/testsuite/g++.dg/cpp0x/pr51619.C +++ b/gcc/testsuite/g++.dg/cpp0x/pr51619.C @@ -1,6 +1,6 @@ // PR c++/51619 // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } struct A { virtual ~A(); }; struct B { A a[1][1]; } b; diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for1.C b/gcc/testsuite/g++.dg/cpp0x/range-for1.C index 49e2ecd0bde..b0e71158174 100644 --- a/gcc/testsuite/g++.dg/cpp0x/range-for1.C +++ b/gcc/testsuite/g++.dg/cpp0x/range-for1.C @@ -2,7 +2,7 @@ // Test the loop with an array // { dg-do run } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } extern "C" void abort(); diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for10.C b/gcc/testsuite/g++.dg/cpp0x/range-for10.C index 662074890d9..e93f76eb4e9 100644 --- a/gcc/testsuite/g++.dg/cpp0x/range-for10.C +++ b/gcc/testsuite/g++.dg/cpp0x/range-for10.C @@ -1,6 +1,6 @@ // PR c++/47388 // { dg-do compile } -// { dg-options "-fno-for-scope -std=c++0x" } +// { dg-options "-fno-for-scope -std=c++11" } template <int> void diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for11.C b/gcc/testsuite/g++.dg/cpp0x/range-for11.C index d02519a2519..84f855890ae 100644 --- a/gcc/testsuite/g++.dg/cpp0x/range-for11.C +++ b/gcc/testsuite/g++.dg/cpp0x/range-for11.C @@ -3,7 +3,7 @@ // with begin/end as member functions // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } struct iterator { diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for12.C b/gcc/testsuite/g++.dg/cpp0x/range-for12.C index 9b405dc620a..4b85366e6a7 100644 --- a/gcc/testsuite/g++.dg/cpp0x/range-for12.C +++ b/gcc/testsuite/g++.dg/cpp0x/range-for12.C @@ -2,7 +2,7 @@ // and begin/end as member functions // { dg-do run } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } /* Preliminary declarations */ namespace pre diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for13.C b/gcc/testsuite/g++.dg/cpp0x/range-for13.C index 7ebf0c563e8..2b8d7f7105b 100644 --- a/gcc/testsuite/g++.dg/cpp0x/range-for13.C +++ b/gcc/testsuite/g++.dg/cpp0x/range-for13.C @@ -2,7 +2,7 @@ // with member begin/end // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } //These should not be used template<typename T> int *begin(T &t) diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for14.C b/gcc/testsuite/g++.dg/cpp0x/range-for14.C index 438555e1344..651ce37f1d8 100644 --- a/gcc/testsuite/g++.dg/cpp0x/range-for14.C +++ b/gcc/testsuite/g++.dg/cpp0x/range-for14.C @@ -2,7 +2,7 @@ // begin/end member functions // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } //These should not be used template<typename T> int *begin(T &t) diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for15.C b/gcc/testsuite/g++.dg/cpp0x/range-for15.C index 38f330771ea..bbdc1999b04 100644 --- a/gcc/testsuite/g++.dg/cpp0x/range-for15.C +++ b/gcc/testsuite/g++.dg/cpp0x/range-for15.C @@ -2,7 +2,7 @@ // and begin/end as member (non-)virtual functions // { dg-do run } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } unsigned int g; diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for16.C b/gcc/testsuite/g++.dg/cpp0x/range-for16.C index 86cc2a828bf..76c1b91649a 100644 --- a/gcc/testsuite/g++.dg/cpp0x/range-for16.C +++ b/gcc/testsuite/g++.dg/cpp0x/range-for16.C @@ -2,7 +2,7 @@ // incomplete type or unknown size // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } extern int a[10]; extern int b[]; diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for17.C b/gcc/testsuite/g++.dg/cpp0x/range-for17.C index eb888d9ab62..72516f15e05 100644 --- a/gcc/testsuite/g++.dg/cpp0x/range-for17.C +++ b/gcc/testsuite/g++.dg/cpp0x/range-for17.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } extern "C" int printf (const char *, ...); diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for18.C b/gcc/testsuite/g++.dg/cpp0x/range-for18.C index 386d73d1817..f06311c7668 100644 --- a/gcc/testsuite/g++.dg/cpp0x/range-for18.C +++ b/gcc/testsuite/g++.dg/cpp0x/range-for18.C @@ -1,7 +1,7 @@ // PR c++/48994 // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template <typename T> struct myvec diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for19.C b/gcc/testsuite/g++.dg/cpp0x/range-for19.C index 4306fbda6ce..ee208d77e1b 100644 --- a/gcc/testsuite/g++.dg/cpp0x/range-for19.C +++ b/gcc/testsuite/g++.dg/cpp0x/range-for19.C @@ -1,7 +1,7 @@ // PR c++/49838 // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } int main() { diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for2.C b/gcc/testsuite/g++.dg/cpp0x/range-for2.C index 17eb41dba7b..325525ce4e3 100644 --- a/gcc/testsuite/g++.dg/cpp0x/range-for2.C +++ b/gcc/testsuite/g++.dg/cpp0x/range-for2.C @@ -3,7 +3,7 @@ // with begin/end in an associated namespace // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } struct iterator { diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for20.C b/gcc/testsuite/g++.dg/cpp0x/range-for20.C index 890eb0aeaf9..3d979d26fd1 100644 --- a/gcc/testsuite/g++.dg/cpp0x/range-for20.C +++ b/gcc/testsuite/g++.dg/cpp0x/range-for20.C @@ -1,6 +1,6 @@ // PR c++/49834 // PR c++/50020 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for21.C b/gcc/testsuite/g++.dg/cpp0x/range-for21.C index 07bb95fbf2b..bf0b02bf398 100644 --- a/gcc/testsuite/g++.dg/cpp0x/range-for21.C +++ b/gcc/testsuite/g++.dg/cpp0x/range-for21.C @@ -1,5 +1,5 @@ // PR c++/49983 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template <class T> void f(T t) diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for22.C b/gcc/testsuite/g++.dg/cpp0x/range-for22.C index 5fef5e6accb..9db46eeb8fd 100644 --- a/gcc/testsuite/g++.dg/cpp0x/range-for22.C +++ b/gcc/testsuite/g++.dg/cpp0x/range-for22.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<int I> void f() { for (auto i: {I} ); diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for3.C b/gcc/testsuite/g++.dg/cpp0x/range-for3.C index 85115a38f5e..c2204f91758 100644 --- a/gcc/testsuite/g++.dg/cpp0x/range-for3.C +++ b/gcc/testsuite/g++.dg/cpp0x/range-for3.C @@ -3,7 +3,7 @@ // with begin/end in std // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } struct iterator { diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for4.C b/gcc/testsuite/g++.dg/cpp0x/range-for4.C index afbcf14b26e..b27ec6ff4bf 100644 --- a/gcc/testsuite/g++.dg/cpp0x/range-for4.C +++ b/gcc/testsuite/g++.dg/cpp0x/range-for4.C @@ -1,7 +1,7 @@ // Test for range-based for loop with templates // { dg-do run } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } /* Preliminary declarations */ namespace pre diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for5.C b/gcc/testsuite/g++.dg/cpp0x/range-for5.C index 04754b780e6..e74e33a2373 100644 --- a/gcc/testsuite/g++.dg/cpp0x/range-for5.C +++ b/gcc/testsuite/g++.dg/cpp0x/range-for5.C @@ -1,7 +1,7 @@ // Test for errors in range-based for loops // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } struct container { diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for6.C b/gcc/testsuite/g++.dg/cpp0x/range-for6.C index 775507f8de8..5fe405fac88 100644 --- a/gcc/testsuite/g++.dg/cpp0x/range-for6.C +++ b/gcc/testsuite/g++.dg/cpp0x/range-for6.C @@ -2,7 +2,7 @@ // Test the loop with an initializer_list // { dg-do run } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } #include <initializer_list> diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for7.C b/gcc/testsuite/g++.dg/cpp0x/range-for7.C index ad89dc201b6..253d6b0c433 100644 --- a/gcc/testsuite/g++.dg/cpp0x/range-for7.C +++ b/gcc/testsuite/g++.dg/cpp0x/range-for7.C @@ -1,7 +1,7 @@ // PR c++/46056 // Check that range-based for loop calls destructors // when required -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // { dg-do run } extern "C" void abort(); diff --git a/gcc/testsuite/g++.dg/cpp0x/range-for8.C b/gcc/testsuite/g++.dg/cpp0x/range-for8.C index 641dfe052c2..7ef214edfaf 100644 --- a/gcc/testsuite/g++.dg/cpp0x/range-for8.C +++ b/gcc/testsuite/g++.dg/cpp0x/range-for8.C @@ -2,7 +2,7 @@ // a new type // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } #include <initializer_list> diff --git a/gcc/testsuite/g++.dg/cpp0x/reference_collapsing.C b/gcc/testsuite/g++.dg/cpp0x/reference_collapsing.C index 5b682e30459..669689dbba5 100644 --- a/gcc/testsuite/g++.dg/cpp0x/reference_collapsing.C +++ b/gcc/testsuite/g++.dg/cpp0x/reference_collapsing.C @@ -4,7 +4,7 @@ // for how cv-qualifications are applied to reference types. 7.1.3, 14.3.1 // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template <bool> struct sa; template <> struct sa<true> {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-bitfield.C b/gcc/testsuite/g++.dg/cpp0x/rv-bitfield.C index ed866f9e1f3..e4db7a27736 100644 --- a/gcc/testsuite/g++.dg/cpp0x/rv-bitfield.C +++ b/gcc/testsuite/g++.dg/cpp0x/rv-bitfield.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-bitfield2.C b/gcc/testsuite/g++.dg/cpp0x/rv-bitfield2.C index e054151b056..1f0d12e48a6 100644 --- a/gcc/testsuite/g++.dg/cpp0x/rv-bitfield2.C +++ b/gcc/testsuite/g++.dg/cpp0x/rv-bitfield2.C @@ -1,5 +1,5 @@ // PR c++/51868 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { A() {} diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-cast.C b/gcc/testsuite/g++.dg/cpp0x/rv-cast.C index 48b7c13ba59..d7bafc483cf 100644 --- a/gcc/testsuite/g++.dg/cpp0x/rv-cast.C +++ b/gcc/testsuite/g++.dg/cpp0x/rv-cast.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } void f(int i) { diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-cast2.C b/gcc/testsuite/g++.dg/cpp0x/rv-cast2.C index 94ee4ca849e..4d2ed52128d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/rv-cast2.C +++ b/gcc/testsuite/g++.dg/cpp0x/rv-cast2.C @@ -1,5 +1,5 @@ // Test for const_cast to reference (5.2.11/4). -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template <class T> T&& xval(); template <class T> T& lval(); diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-conv1.C b/gcc/testsuite/g++.dg/cpp0x/rv-conv1.C index 38529913f85..ba2b6bb4d6d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/rv-conv1.C +++ b/gcc/testsuite/g++.dg/cpp0x/rv-conv1.C @@ -1,5 +1,5 @@ // PR c++/49267 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct X { operator int&(); diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-deduce.C b/gcc/testsuite/g++.dg/cpp0x/rv-deduce.C index 043543631ad..7763c42b290 100644 --- a/gcc/testsuite/g++.dg/cpp0x/rv-deduce.C +++ b/gcc/testsuite/g++.dg/cpp0x/rv-deduce.C @@ -1,5 +1,5 @@ // PR c++/36816, core issue 873 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template <class T> void h (T&&) { } diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-deduce2.C b/gcc/testsuite/g++.dg/cpp0x/rv-deduce2.C index 160296f640f..26a8d551fb6 100644 --- a/gcc/testsuite/g++.dg/cpp0x/rv-deduce2.C +++ b/gcc/testsuite/g++.dg/cpp0x/rv-deduce2.C @@ -1,5 +1,5 @@ // PR c++/48313 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<typename F> void f(F&&) { } diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-dotstar.C b/gcc/testsuite/g++.dg/cpp0x/rv-dotstar.C index 65aac8da2a1..104ecbdacca 100644 --- a/gcc/testsuite/g++.dg/cpp0x/rv-dotstar.C +++ b/gcc/testsuite/g++.dg/cpp0x/rv-dotstar.C @@ -1,5 +1,5 @@ // PR c++/49389 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<class T> T&& val(); diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-func.C b/gcc/testsuite/g++.dg/cpp0x/rv-func.C index db142961128..3ac7118b49f 100644 --- a/gcc/testsuite/g++.dg/cpp0x/rv-func.C +++ b/gcc/testsuite/g++.dg/cpp0x/rv-func.C @@ -1,5 +1,5 @@ // PR c++/48457, Core 1238 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<class T> T&& create(); diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-func2.C b/gcc/testsuite/g++.dg/cpp0x/rv-func2.C index b792342dada..51516bf53de 100644 --- a/gcc/testsuite/g++.dg/cpp0x/rv-func2.C +++ b/gcc/testsuite/g++.dg/cpp0x/rv-func2.C @@ -1,5 +1,5 @@ // PR c++/49458 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } typedef void ftype(); diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-func3.C b/gcc/testsuite/g++.dg/cpp0x/rv-func3.C index 8504682d791..f33140174a4 100644 --- a/gcc/testsuite/g++.dg/cpp0x/rv-func3.C +++ b/gcc/testsuite/g++.dg/cpp0x/rv-func3.C @@ -1,5 +1,5 @@ // DR 1328 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template <class T> struct A { operator T&(); // #1 diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-lvalue-req.C b/gcc/testsuite/g++.dg/cpp0x/rv-lvalue-req.C index a8f424df003..fd5aa65b3a6 100644 --- a/gcc/testsuite/g++.dg/cpp0x/rv-lvalue-req.C +++ b/gcc/testsuite/g++.dg/cpp0x/rv-lvalue-req.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template <class T> T&& declval(); diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-reinterpret.C b/gcc/testsuite/g++.dg/cpp0x/rv-reinterpret.C index 5b6e4c3d126..02061fc3f28 100644 --- a/gcc/testsuite/g++.dg/cpp0x/rv-reinterpret.C +++ b/gcc/testsuite/g++.dg/cpp0x/rv-reinterpret.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } // { dg-do run } void f(int &); diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-restrict.C b/gcc/testsuite/g++.dg/cpp0x/rv-restrict.C index 569ee5bb6c9..23c7bbe2212 100644 --- a/gcc/testsuite/g++.dg/cpp0x/rv-restrict.C +++ b/gcc/testsuite/g++.dg/cpp0x/rv-restrict.C @@ -1,5 +1,5 @@ // PR c++/45401 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } typedef int &__restrict restrictLvref; typedef restrictLvref &&rvrefToRestrictLvref; diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-return.C b/gcc/testsuite/g++.dg/cpp0x/rv-return.C index 3ab659833ea..088f376cf1f 100644 --- a/gcc/testsuite/g++.dg/cpp0x/rv-return.C +++ b/gcc/testsuite/g++.dg/cpp0x/rv-return.C @@ -1,5 +1,5 @@ // PR c++/41815 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<typename T, typename U> struct same_type; template<typename T> struct same_type<T, T> {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-template1.C b/gcc/testsuite/g++.dg/cpp0x/rv-template1.C index 11f53bd1c0a..d73108c23b9 100644 --- a/gcc/testsuite/g++.dg/cpp0x/rv-template1.C +++ b/gcc/testsuite/g++.dg/cpp0x/rv-template1.C @@ -1,5 +1,5 @@ // PR c++/44870 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } void foo(int&& data); diff --git a/gcc/testsuite/g++.dg/cpp0x/rv-trivial-bug.C b/gcc/testsuite/g++.dg/cpp0x/rv-trivial-bug.C index cbce7c4ddd7..217116a3902 100644 --- a/gcc/testsuite/g++.dg/cpp0x/rv-trivial-bug.C +++ b/gcc/testsuite/g++.dg/cpp0x/rv-trivial-bug.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // PR c++/33235 #include <cassert> diff --git a/gcc/testsuite/g++.dg/cpp0x/rv10.C b/gcc/testsuite/g++.dg/cpp0x/rv10.C index 5e78b1dbb69..3c6566bcd91 100644 --- a/gcc/testsuite/g++.dg/cpp0x/rv10.C +++ b/gcc/testsuite/g++.dg/cpp0x/rv10.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/rv1n.C b/gcc/testsuite/g++.dg/cpp0x/rv1n.C index b15bdfb4c93..9ee46dc12f5 100644 --- a/gcc/testsuite/g++.dg/cpp0x/rv1n.C +++ b/gcc/testsuite/g++.dg/cpp0x/rv1n.C @@ -3,7 +3,7 @@ // Test overload resolution among reference types // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template <bool> struct sa; template <> struct sa<true> {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/rv1p.C b/gcc/testsuite/g++.dg/cpp0x/rv1p.C index 99e39e6a4bc..f2f4c0b0391 100644 --- a/gcc/testsuite/g++.dg/cpp0x/rv1p.C +++ b/gcc/testsuite/g++.dg/cpp0x/rv1p.C @@ -3,7 +3,7 @@ // Test overload resolution among reference types // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // { dg-skip-if "packed attribute missing for struct one/three/five/seven" { "epiphany-*-*" } { "*" } { "" } } template <bool> struct sa; diff --git a/gcc/testsuite/g++.dg/cpp0x/rv2n.C b/gcc/testsuite/g++.dg/cpp0x/rv2n.C index f22e863230e..c39d5c06e50 100644 --- a/gcc/testsuite/g++.dg/cpp0x/rv2n.C +++ b/gcc/testsuite/g++.dg/cpp0x/rv2n.C @@ -3,7 +3,7 @@ // Test overload resolution among reference types // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template <bool> struct sa; template <> struct sa<true> {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/rv2p.C b/gcc/testsuite/g++.dg/cpp0x/rv2p.C index fca45c7352a..209f89392ad 100644 --- a/gcc/testsuite/g++.dg/cpp0x/rv2p.C +++ b/gcc/testsuite/g++.dg/cpp0x/rv2p.C @@ -3,7 +3,7 @@ // Test overload resolution among reference types // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // { dg-skip-if "packed attribute missing for struct one/three/five/seven" { "epiphany-*-*" } { "*" } { "" } } template <bool> struct sa; diff --git a/gcc/testsuite/g++.dg/cpp0x/rv3n.C b/gcc/testsuite/g++.dg/cpp0x/rv3n.C index 14b810ae68d..67cbde24d5e 100644 --- a/gcc/testsuite/g++.dg/cpp0x/rv3n.C +++ b/gcc/testsuite/g++.dg/cpp0x/rv3n.C @@ -3,7 +3,7 @@ // Test overload resolution among reference types // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template <bool> struct sa; template <> struct sa<true> {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/rv3p.C b/gcc/testsuite/g++.dg/cpp0x/rv3p.C index 804b2ffbdbe..12db70ca2e7 100644 --- a/gcc/testsuite/g++.dg/cpp0x/rv3p.C +++ b/gcc/testsuite/g++.dg/cpp0x/rv3p.C @@ -3,7 +3,7 @@ // Test overload resolution among reference types // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // { dg-skip-if "packed attribute missing for struct one/three/five/seven" { "epiphany-*-*" } { "*" } { "" } } template <bool> struct sa; diff --git a/gcc/testsuite/g++.dg/cpp0x/rv4n.C b/gcc/testsuite/g++.dg/cpp0x/rv4n.C index 076e9a0488e..9ed324e4655 100644 --- a/gcc/testsuite/g++.dg/cpp0x/rv4n.C +++ b/gcc/testsuite/g++.dg/cpp0x/rv4n.C @@ -3,7 +3,7 @@ // Test overload resolution among reference types // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template <bool> struct sa; template <> struct sa<true> {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/rv4p.C b/gcc/testsuite/g++.dg/cpp0x/rv4p.C index b2744e3cd9e..8ec25717919 100644 --- a/gcc/testsuite/g++.dg/cpp0x/rv4p.C +++ b/gcc/testsuite/g++.dg/cpp0x/rv4p.C @@ -3,7 +3,7 @@ // Test overload resolution among reference types // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // { dg-skip-if "packed attribute missing for struct one/three/five/seven" { "epiphany-*-*" } { "*" } { "" } } template <bool> struct sa; diff --git a/gcc/testsuite/g++.dg/cpp0x/rv5n.C b/gcc/testsuite/g++.dg/cpp0x/rv5n.C index d9b8cd23988..667012f55b5 100644 --- a/gcc/testsuite/g++.dg/cpp0x/rv5n.C +++ b/gcc/testsuite/g++.dg/cpp0x/rv5n.C @@ -3,7 +3,7 @@ // Test overload resolution among reference types // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template <bool> struct sa; template <> struct sa<true> {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/rv5p.C b/gcc/testsuite/g++.dg/cpp0x/rv5p.C index 9bb5e2bbb89..171b6dcf706 100644 --- a/gcc/testsuite/g++.dg/cpp0x/rv5p.C +++ b/gcc/testsuite/g++.dg/cpp0x/rv5p.C @@ -3,7 +3,7 @@ // Test overload resolution among reference types // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // { dg-skip-if "packed attribute missing for struct one/three/five/seven" { "epiphany-*-*" } { "*" } { "" } } template <bool> struct sa; diff --git a/gcc/testsuite/g++.dg/cpp0x/rv6n.C b/gcc/testsuite/g++.dg/cpp0x/rv6n.C index fbc932de1ef..89ed1c0ac50 100644 --- a/gcc/testsuite/g++.dg/cpp0x/rv6n.C +++ b/gcc/testsuite/g++.dg/cpp0x/rv6n.C @@ -3,7 +3,7 @@ // Test overload resolution among reference types // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template <bool> struct sa; template <> struct sa<true> {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/rv6p.C b/gcc/testsuite/g++.dg/cpp0x/rv6p.C index b2a3bdedd1b..92a4f94336f 100644 --- a/gcc/testsuite/g++.dg/cpp0x/rv6p.C +++ b/gcc/testsuite/g++.dg/cpp0x/rv6p.C @@ -3,7 +3,7 @@ // Test overload resolution among reference types // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // { dg-skip-if "packed attribute missing for struct one/three/five/seven" { "epiphany-*-*" } { "*" } { "" } } template <bool> struct sa; diff --git a/gcc/testsuite/g++.dg/cpp0x/rv7n.C b/gcc/testsuite/g++.dg/cpp0x/rv7n.C index 206cc79bb14..4d81e2a71c1 100644 --- a/gcc/testsuite/g++.dg/cpp0x/rv7n.C +++ b/gcc/testsuite/g++.dg/cpp0x/rv7n.C @@ -3,7 +3,7 @@ // Test overload resolution among reference types // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template <bool> struct sa; template <> struct sa<true> {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/rv7p.C b/gcc/testsuite/g++.dg/cpp0x/rv7p.C index 918dc14b98c..551b9d9c783 100644 --- a/gcc/testsuite/g++.dg/cpp0x/rv7p.C +++ b/gcc/testsuite/g++.dg/cpp0x/rv7p.C @@ -3,7 +3,7 @@ // Test overload resolution among reference types // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // { dg-skip-if "packed attribute missing for struct one/three/five/seven" { "epiphany-*-*" } { "*" } { "" } } template <bool> struct sa; diff --git a/gcc/testsuite/g++.dg/cpp0x/rv8p.C b/gcc/testsuite/g++.dg/cpp0x/rv8p.C index f6784dffc22..650fd76ba82 100644 --- a/gcc/testsuite/g++.dg/cpp0x/rv8p.C +++ b/gcc/testsuite/g++.dg/cpp0x/rv8p.C @@ -3,7 +3,7 @@ // Test overload resolution among reference types // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // { dg-skip-if "packed attribute missing for struct one/three/five/seven" { "epiphany-*-*" } { "*" } { "" } } template <bool> struct sa; diff --git a/gcc/testsuite/g++.dg/cpp0x/rv9p.C b/gcc/testsuite/g++.dg/cpp0x/rv9p.C index ec08a824865..4714d7c936e 100644 --- a/gcc/testsuite/g++.dg/cpp0x/rv9p.C +++ b/gcc/testsuite/g++.dg/cpp0x/rv9p.C @@ -1,5 +1,5 @@ // PR c++/36744 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // { dg-do run } struct S diff --git a/gcc/testsuite/g++.dg/cpp0x/rvo.C b/gcc/testsuite/g++.dg/cpp0x/rvo.C index d4459af64d3..0ba8b100293 100644 --- a/gcc/testsuite/g++.dg/cpp0x/rvo.C +++ b/gcc/testsuite/g++.dg/cpp0x/rvo.C @@ -1,5 +1,5 @@ // { dg-do run } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // Contributed by Sylvain Pion static int rvalue_constructions = 0; diff --git a/gcc/testsuite/g++.dg/cpp0x/scoped_enum.C b/gcc/testsuite/g++.dg/cpp0x/scoped_enum.C index 20391eb407b..a1f99482940 100644 --- a/gcc/testsuite/g++.dg/cpp0x/scoped_enum.C +++ b/gcc/testsuite/g++.dg/cpp0x/scoped_enum.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } enum class Color1 { Red, Green, diff --git a/gcc/testsuite/g++.dg/cpp0x/scoped_enum2.C b/gcc/testsuite/g++.dg/cpp0x/scoped_enum2.C index e87b36a2732..bf9e6574dc7 100644 --- a/gcc/testsuite/g++.dg/cpp0x/scoped_enum2.C +++ b/gcc/testsuite/g++.dg/cpp0x/scoped_enum2.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } enum class E { e = 10 }; enum E2 { e2 = 10 }; diff --git a/gcc/testsuite/g++.dg/cpp0x/scoped_enum_examples.C b/gcc/testsuite/g++.dg/cpp0x/scoped_enum_examples.C index 67c3fcbebb1..aea744d9a4d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/scoped_enum_examples.C +++ b/gcc/testsuite/g++.dg/cpp0x/scoped_enum_examples.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } enum class Col { red, yellow, green }; int x = Col::red; // { dg-error "cannot convert" } diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae1.C b/gcc/testsuite/g++.dg/cpp0x/sfinae1.C index 292d8ae04b0..855d96795cd 100644 --- a/gcc/testsuite/g++.dg/cpp0x/sfinae1.C +++ b/gcc/testsuite/g++.dg/cpp0x/sfinae1.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template< typename T_VECTOR > void f(const T_VECTOR &a, decltype(a[0]) t = 0); diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae10.C b/gcc/testsuite/g++.dg/cpp0x/sfinae10.C index ede8b704245..c62aba77373 100644 --- a/gcc/testsuite/g++.dg/cpp0x/sfinae10.C +++ b/gcc/testsuite/g++.dg/cpp0x/sfinae10.C @@ -1,5 +1,5 @@ // PR c++/48452 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } namespace std { template <class T> T&& declval(); } diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae11.C b/gcc/testsuite/g++.dg/cpp0x/sfinae11.C index 2e8408d8f4d..e5d5255c11c 100644 --- a/gcc/testsuite/g++.dg/cpp0x/sfinae11.C +++ b/gcc/testsuite/g++.dg/cpp0x/sfinae11.C @@ -1,5 +1,5 @@ // PR c++/48468 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } // { dg-prune-output "note" } template<class T> diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae12.C b/gcc/testsuite/g++.dg/cpp0x/sfinae12.C index 114f1b42da8..927ac7a6d82 100644 --- a/gcc/testsuite/g++.dg/cpp0x/sfinae12.C +++ b/gcc/testsuite/g++.dg/cpp0x/sfinae12.C @@ -1,5 +1,5 @@ // PR c++/48535 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<class T, class = decltype(T{}) diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae13.C b/gcc/testsuite/g++.dg/cpp0x/sfinae13.C index 465df2d8b8c..511944b8e46 100644 --- a/gcc/testsuite/g++.dg/cpp0x/sfinae13.C +++ b/gcc/testsuite/g++.dg/cpp0x/sfinae13.C @@ -1,5 +1,5 @@ // PR c++/48581 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<class T> T&& create(); diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae14.C b/gcc/testsuite/g++.dg/cpp0x/sfinae14.C index 305f96eddca..23ef8443fdb 100644 --- a/gcc/testsuite/g++.dg/cpp0x/sfinae14.C +++ b/gcc/testsuite/g++.dg/cpp0x/sfinae14.C @@ -1,5 +1,5 @@ // PR c++/48557 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<class T> struct add_rval_ref diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae15.C b/gcc/testsuite/g++.dg/cpp0x/sfinae15.C index 595ca40b555..e2830968bb0 100644 --- a/gcc/testsuite/g++.dg/cpp0x/sfinae15.C +++ b/gcc/testsuite/g++.dg/cpp0x/sfinae15.C @@ -1,5 +1,5 @@ // PR c++/48531 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<class T, class = decltype(T()) diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae16.C b/gcc/testsuite/g++.dg/cpp0x/sfinae16.C index 6470567b7a2..7bd1aabd8a3 100644 --- a/gcc/testsuite/g++.dg/cpp0x/sfinae16.C +++ b/gcc/testsuite/g++.dg/cpp0x/sfinae16.C @@ -1,5 +1,5 @@ // PR c++/48531 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<class T, class = decltype(T()) diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae17.C b/gcc/testsuite/g++.dg/cpp0x/sfinae17.C index dbbd9efe410..3b91621b11a 100644 --- a/gcc/testsuite/g++.dg/cpp0x/sfinae17.C +++ b/gcc/testsuite/g++.dg/cpp0x/sfinae17.C @@ -1,5 +1,5 @@ // PR c++/48530 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<class T, class = decltype(T{}) diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae18.C b/gcc/testsuite/g++.dg/cpp0x/sfinae18.C index bb54335e6cc..bf98f402451 100644 --- a/gcc/testsuite/g++.dg/cpp0x/sfinae18.C +++ b/gcc/testsuite/g++.dg/cpp0x/sfinae18.C @@ -1,5 +1,5 @@ // PR c++/48530 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<class T, class = decltype(T()) diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae19.C b/gcc/testsuite/g++.dg/cpp0x/sfinae19.C index be96983bf39..59c6a71b2d1 100644 --- a/gcc/testsuite/g++.dg/cpp0x/sfinae19.C +++ b/gcc/testsuite/g++.dg/cpp0x/sfinae19.C @@ -1,5 +1,5 @@ // PR c++/48737 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<class T> T&& create(); diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae2.C b/gcc/testsuite/g++.dg/cpp0x/sfinae2.C index b9ef70d99cf..1eec1a10525 100644 --- a/gcc/testsuite/g++.dg/cpp0x/sfinae2.C +++ b/gcc/testsuite/g++.dg/cpp0x/sfinae2.C @@ -1,5 +1,5 @@ // PR c++/44967 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template <typename T> T&& declval(); diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae20.C b/gcc/testsuite/g++.dg/cpp0x/sfinae20.C index 486064c3af7..c0ba70ced97 100644 --- a/gcc/testsuite/g++.dg/cpp0x/sfinae20.C +++ b/gcc/testsuite/g++.dg/cpp0x/sfinae20.C @@ -1,5 +1,5 @@ // PR c++/48744 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<class T> struct add_rval_ref { diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae21.C b/gcc/testsuite/g++.dg/cpp0x/sfinae21.C index 4fba6eb82a1..62c003a458c 100644 --- a/gcc/testsuite/g++.dg/cpp0x/sfinae21.C +++ b/gcc/testsuite/g++.dg/cpp0x/sfinae21.C @@ -1,5 +1,5 @@ // PR c++/48735 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<class T, class = decltype(T{}) @@ -9,6 +9,10 @@ char f(int); template<class> char (&f(...))[2]; -struct ND { ND() = delete; }; +struct ND { + // Make ND() non-aggregate. + virtual void f(); + ND() = delete; +}; static_assert(sizeof(f<ND[1]>(0)) != 1, "Error"); diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae22.C b/gcc/testsuite/g++.dg/cpp0x/sfinae22.C index 1c3efd2e079..8379d04ca3e 100644 --- a/gcc/testsuite/g++.dg/cpp0x/sfinae22.C +++ b/gcc/testsuite/g++.dg/cpp0x/sfinae22.C @@ -1,5 +1,5 @@ // PR c++/48745 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<class T> struct add_rval_ref { diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae23.C b/gcc/testsuite/g++.dg/cpp0x/sfinae23.C index 4e2ea88b171..794b336aead 100644 --- a/gcc/testsuite/g++.dg/cpp0x/sfinae23.C +++ b/gcc/testsuite/g++.dg/cpp0x/sfinae23.C @@ -1,5 +1,5 @@ // PR c++/48647 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template< class T > T&& declval(); diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae24.C b/gcc/testsuite/g++.dg/cpp0x/sfinae24.C index f974d82b144..d6746e01e21 100644 --- a/gcc/testsuite/g++.dg/cpp0x/sfinae24.C +++ b/gcc/testsuite/g++.dg/cpp0x/sfinae24.C @@ -1,7 +1,7 @@ // PR c++/49058 // This error is not subject to SFINAE because it doesn't happen in the // deduction context. -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } // { dg-prune-output "note" } template<typename T> T val(); diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae25.C b/gcc/testsuite/g++.dg/cpp0x/sfinae25.C index 7bdc8f88e51..d8c46d0597a 100644 --- a/gcc/testsuite/g++.dg/cpp0x/sfinae25.C +++ b/gcc/testsuite/g++.dg/cpp0x/sfinae25.C @@ -1,5 +1,5 @@ // PR c++/49105 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<class T, class = decltype(T{})> char f(int); diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae26.C b/gcc/testsuite/g++.dg/cpp0x/sfinae26.C index 374f9976b2c..3fc5b280da7 100644 --- a/gcc/testsuite/g++.dg/cpp0x/sfinae26.C +++ b/gcc/testsuite/g++.dg/cpp0x/sfinae26.C @@ -1,5 +1,5 @@ // PR c++/49229 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } extern void* enabler; diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae27.C b/gcc/testsuite/g++.dg/cpp0x/sfinae27.C index 93327ba9cc5..2fa2232ab39 100644 --- a/gcc/testsuite/g++.dg/cpp0x/sfinae27.C +++ b/gcc/testsuite/g++.dg/cpp0x/sfinae27.C @@ -1,5 +1,5 @@ // PR c++/50157 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<class T> T val(); diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae28.C b/gcc/testsuite/g++.dg/cpp0x/sfinae28.C index da64f413c71..a06fc9f7407 100644 --- a/gcc/testsuite/g++.dg/cpp0x/sfinae28.C +++ b/gcc/testsuite/g++.dg/cpp0x/sfinae28.C @@ -1,5 +1,5 @@ // PR c++/50324 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct complete { }; struct incomplete; diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae29.C b/gcc/testsuite/g++.dg/cpp0x/sfinae29.C index a2e10b41d3e..49ab9699376 100644 --- a/gcc/testsuite/g++.dg/cpp0x/sfinae29.C +++ b/gcc/testsuite/g++.dg/cpp0x/sfinae29.C @@ -1,5 +1,5 @@ // PR c++/51047 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<typename T> T &&declval(); template<class T> decltype(declval<T>().x) f(T *); diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae3.C b/gcc/testsuite/g++.dg/cpp0x/sfinae3.C index 8582ba777c4..b25b3886137 100644 --- a/gcc/testsuite/g++.dg/cpp0x/sfinae3.C +++ b/gcc/testsuite/g++.dg/cpp0x/sfinae3.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } namespace std { template <class T> T&& declval(); } diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae31.C b/gcc/testsuite/g++.dg/cpp0x/sfinae31.C index ea151fe6490..066b1de022a 100644 --- a/gcc/testsuite/g++.dg/cpp0x/sfinae31.C +++ b/gcc/testsuite/g++.dg/cpp0x/sfinae31.C @@ -1,5 +1,5 @@ // PR c++/51973 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template <class T> void f(T t) { }; diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae32.C b/gcc/testsuite/g++.dg/cpp0x/sfinae32.C index db3bf5a21fc..67237ffb490 100644 --- a/gcc/testsuite/g++.dg/cpp0x/sfinae32.C +++ b/gcc/testsuite/g++.dg/cpp0x/sfinae32.C @@ -1,5 +1,5 @@ // PR c++/51989 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template <typename T> struct is_container diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae4.C b/gcc/testsuite/g++.dg/cpp0x/sfinae4.C index b6648312498..a409bf8b8b7 100644 --- a/gcc/testsuite/g++.dg/cpp0x/sfinae4.C +++ b/gcc/testsuite/g++.dg/cpp0x/sfinae4.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } namespace std { template <class T> T&& declval(); } diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae49.C b/gcc/testsuite/g++.dg/cpp0x/sfinae49.C new file mode 100644 index 00000000000..59381f341b4 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/sfinae49.C @@ -0,0 +1,29 @@ +// PR c++/58932 +// { dg-do compile { target c++11 } } + +using nullptr_t = decltype(nullptr); + +template<typename T, typename Sfinae = nullptr_t> +struct B { + static float& int_if_addable(); +}; + +template<typename T> +struct B<T, decltype( (T() + T()), nullptr )> { + static int& int_if_addable(); +}; + +struct X { }; + +struct Y { }; +Y operator+(Y, Y); + +struct Z { }; +Z operator+(Z, Z) = delete; + +int main() +{ + float& a = B<X>::int_if_addable(); + int& b = B<Y>::int_if_addable(); + float& c = B<Z>::int_if_addable(); +} diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae5.C b/gcc/testsuite/g++.dg/cpp0x/sfinae5.C index 8474fb31431..e3592d06b49 100644 --- a/gcc/testsuite/g++.dg/cpp0x/sfinae5.C +++ b/gcc/testsuite/g++.dg/cpp0x/sfinae5.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<class T> T&& create(); diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae6.C b/gcc/testsuite/g++.dg/cpp0x/sfinae6.C index 401d5362d84..1b884330165 100644 --- a/gcc/testsuite/g++.dg/cpp0x/sfinae6.C +++ b/gcc/testsuite/g++.dg/cpp0x/sfinae6.C @@ -1,5 +1,5 @@ // PR c++/48113 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<typename T> T declval(); diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae7.C b/gcc/testsuite/g++.dg/cpp0x/sfinae7.C index 0a95a9644c7..19ec2ad1961 100644 --- a/gcc/testsuite/g++.dg/cpp0x/sfinae7.C +++ b/gcc/testsuite/g++.dg/cpp0x/sfinae7.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae8.C b/gcc/testsuite/g++.dg/cpp0x/sfinae8.C index 7f3012f94df..a5464dee03b 100644 --- a/gcc/testsuite/g++.dg/cpp0x/sfinae8.C +++ b/gcc/testsuite/g++.dg/cpp0x/sfinae8.C @@ -1,5 +1,5 @@ // PR c++/48449 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<class T, class = decltype(T())> char f(int); diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae9.C b/gcc/testsuite/g++.dg/cpp0x/sfinae9.C index 6f1de21d51d..98ac52c12a2 100644 --- a/gcc/testsuite/g++.dg/cpp0x/sfinae9.C +++ b/gcc/testsuite/g++.dg/cpp0x/sfinae9.C @@ -1,5 +1,5 @@ // PR c++/48450 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } namespace std { template <class T> T&& declval(); diff --git a/gcc/testsuite/g++.dg/cpp0x/static_assert1.C b/gcc/testsuite/g++.dg/cpp0x/static_assert1.C index a54617598fb..81a86615a55 100644 --- a/gcc/testsuite/g++.dg/cpp0x/static_assert1.C +++ b/gcc/testsuite/g++.dg/cpp0x/static_assert1.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } void foo() { static_assert(1, "okay"); diff --git a/gcc/testsuite/g++.dg/cpp0x/static_assert2.C b/gcc/testsuite/g++.dg/cpp0x/static_assert2.C index 3e74bb1b480..ac7dfdc9260 100644 --- a/gcc/testsuite/g++.dg/cpp0x/static_assert2.C +++ b/gcc/testsuite/g++.dg/cpp0x/static_assert2.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<int I> struct accept_evens { static_assert( I % 2 == 0, "I must be an even number"); // { dg-error "even number" } diff --git a/gcc/testsuite/g++.dg/cpp0x/static_assert3.C b/gcc/testsuite/g++.dg/cpp0x/static_assert3.C index 0a4cbc98aff..84d2e2a0b16 100644 --- a/gcc/testsuite/g++.dg/cpp0x/static_assert3.C +++ b/gcc/testsuite/g++.dg/cpp0x/static_assert3.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } static_assert(7 / 0, "X"); // { dg-error "non-constant condition" "non-constant" } // { dg-warning "division by zero" "zero" { target *-*-* } 2 } // { dg-error "7 / 0.. is not a constant expression" "not a constant" { target *-*-* } 2 } diff --git a/gcc/testsuite/g++.dg/cpp0x/static_assert4.C b/gcc/testsuite/g++.dg/cpp0x/static_assert4.C index b0818873f10..97c0bd65950 100644 --- a/gcc/testsuite/g++.dg/cpp0x/static_assert4.C +++ b/gcc/testsuite/g++.dg/cpp0x/static_assert4.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x --param ggc-min-heapsize=0 --param ggc-min-expand=0 " } +// { dg-options "-std=c++11 --param ggc-min-heapsize=0 --param ggc-min-expand=0 " } // PR C++/30033 // Make sure that the static assert does not crash the GC. diff --git a/gcc/testsuite/g++.dg/cpp0x/static_assert5.C b/gcc/testsuite/g++.dg/cpp0x/static_assert5.C index b918796220c..fdf26d12f07 100644 --- a/gcc/testsuite/g++.dg/cpp0x/static_assert5.C +++ b/gcc/testsuite/g++.dg/cpp0x/static_assert5.C @@ -1,5 +1,5 @@ // PR c++/50837 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<class T> struct z diff --git a/gcc/testsuite/g++.dg/cpp0x/static_assert6.C b/gcc/testsuite/g++.dg/cpp0x/static_assert6.C index d1ab0dded9d..6fd9c27b85a 100644 --- a/gcc/testsuite/g++.dg/cpp0x/static_assert6.C +++ b/gcc/testsuite/g++.dg/cpp0x/static_assert6.C @@ -1,4 +1,4 @@ // PR c++/51397 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } static_assert('X' != '\130', "'X' has the wrong value"); // { dg-error "'X' has the wrong value" } diff --git a/gcc/testsuite/g++.dg/cpp0x/std-layout1.C b/gcc/testsuite/g++.dg/cpp0x/std-layout1.C index bdad8211145..bff657c7396 100644 --- a/gcc/testsuite/g++.dg/cpp0x/std-layout1.C +++ b/gcc/testsuite/g++.dg/cpp0x/std-layout1.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // [basic.types]/10: // Scalar types, standard-layout class types (Clause 9), arrays of such diff --git a/gcc/testsuite/g++.dg/cpp0x/syntax-err1.C b/gcc/testsuite/g++.dg/cpp0x/syntax-err1.C index ce1c9eea534..818eaac0a14 100644 --- a/gcc/testsuite/g++.dg/cpp0x/syntax-err1.C +++ b/gcc/testsuite/g++.dg/cpp0x/syntax-err1.C @@ -1,5 +1,5 @@ // PR c++/47198 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct S { diff --git a/gcc/testsuite/g++.dg/cpp0x/temp-constructor-bug.C b/gcc/testsuite/g++.dg/cpp0x/temp-constructor-bug.C index a0672070205..b7bb9b85a25 100644 --- a/gcc/testsuite/g++.dg/cpp0x/temp-constructor-bug.C +++ b/gcc/testsuite/g++.dg/cpp0x/temp-constructor-bug.C @@ -1,4 +1,4 @@ -// { dg-options "--std=c++0x" } +// { dg-options "--std=c++11" } struct S { }; diff --git a/gcc/testsuite/g++.dg/cpp0x/temp-va-arg-bug.C b/gcc/testsuite/g++.dg/cpp0x/temp-va-arg-bug.C index 085915f907e..97b33ac67d4 100644 --- a/gcc/testsuite/g++.dg/cpp0x/temp-va-arg-bug.C +++ b/gcc/testsuite/g++.dg/cpp0x/temp-va-arg-bug.C @@ -1,5 +1,5 @@ -// { dg-options "--std=c++0x" } -// { dg-options "-Wno-abi --std=c++0x" { target arm_eabi } } +// { dg-options "--std=c++11" } +// { dg-options "-Wno-abi --std=c++11" { target arm_eabi } } #include <stdarg.h> struct S { }; diff --git a/gcc/testsuite/g++.dg/cpp0x/temp_default1.C b/gcc/testsuite/g++.dg/cpp0x/temp_default1.C index dfa2cfb7bc7..bf2629214ed 100644 --- a/gcc/testsuite/g++.dg/cpp0x/temp_default1.C +++ b/gcc/testsuite/g++.dg/cpp0x/temp_default1.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<typename T, typename U> struct is_same diff --git a/gcc/testsuite/g++.dg/cpp0x/temp_default2.C b/gcc/testsuite/g++.dg/cpp0x/temp_default2.C index dab1650e448..0d1598ce959 100644 --- a/gcc/testsuite/g++.dg/cpp0x/temp_default2.C +++ b/gcc/testsuite/g++.dg/cpp0x/temp_default2.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template <class T, class U = double> void f(T t = 0, U u = 0); // { dg-message "note" } diff --git a/gcc/testsuite/g++.dg/cpp0x/temp_default3.C b/gcc/testsuite/g++.dg/cpp0x/temp_default3.C index f71fe0f435a..e72e75797fb 100644 --- a/gcc/testsuite/g++.dg/cpp0x/temp_default3.C +++ b/gcc/testsuite/g++.dg/cpp0x/temp_default3.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<typename T, typename U = typename T::value_type> void f(T); diff --git a/gcc/testsuite/g++.dg/cpp0x/temp_default4.C b/gcc/testsuite/g++.dg/cpp0x/temp_default4.C index aa2ad58e01e..6b2f5b18928 100644 --- a/gcc/testsuite/g++.dg/cpp0x/temp_default4.C +++ b/gcc/testsuite/g++.dg/cpp0x/temp_default4.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } class X { template<typename T = int> friend void f(X) { } diff --git a/gcc/testsuite/g++.dg/cpp0x/template_deduction.C b/gcc/testsuite/g++.dg/cpp0x/template_deduction.C index 4b8bd12b489..73aa3eec9dc 100644 --- a/gcc/testsuite/g++.dg/cpp0x/template_deduction.C +++ b/gcc/testsuite/g++.dg/cpp0x/template_deduction.C @@ -3,7 +3,7 @@ // Test the "Augmented" template argument deduction when binding an lvalue to an rvalue reference. // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template <bool> struct sa; template <> struct sa<true> {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/trailing1.C b/gcc/testsuite/g++.dg/cpp0x/trailing1.C index f637857b427..8b568a286ca 100644 --- a/gcc/testsuite/g++.dg/cpp0x/trailing1.C +++ b/gcc/testsuite/g++.dg/cpp0x/trailing1.C @@ -1,5 +1,5 @@ // Tests for late-specified return type. -// { dg-options "-std=c++0x -fabi-version=5" } +// { dg-options "-std=c++11 -fabi-version=5" } auto f() -> int { diff --git a/gcc/testsuite/g++.dg/cpp0x/trailing3.C b/gcc/testsuite/g++.dg/cpp0x/trailing3.C index 1c64f45731a..d95f298a157 100644 --- a/gcc/testsuite/g++.dg/cpp0x/trailing3.C +++ b/gcc/testsuite/g++.dg/cpp0x/trailing3.C @@ -1,5 +1,5 @@ // More auto/decltype mangling tests. -// { dg-options "-std=c++0x -fabi-version=0" } +// { dg-options "-std=c++11 -fabi-version=0" } template <class T> struct B diff --git a/gcc/testsuite/g++.dg/cpp0x/trailing4.C b/gcc/testsuite/g++.dg/cpp0x/trailing4.C index 8d4baa97e5d..f508bc4e890 100644 --- a/gcc/testsuite/g++.dg/cpp0x/trailing4.C +++ b/gcc/testsuite/g++.dg/cpp0x/trailing4.C @@ -1,5 +1,5 @@ // PR c++/38597 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<class T, class U> auto f(T,U) -> decltype(T() + U()) diff --git a/gcc/testsuite/g++.dg/cpp0x/trailing5.C b/gcc/testsuite/g++.dg/cpp0x/trailing5.C index b97d362be2f..b4f2bf75ffb 100644 --- a/gcc/testsuite/g++.dg/cpp0x/trailing5.C +++ b/gcc/testsuite/g++.dg/cpp0x/trailing5.C @@ -1,5 +1,5 @@ // PR c++/38798, DR 770 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A {}; auto foo() -> struct A {} diff --git a/gcc/testsuite/g++.dg/cpp0x/trailing6.C b/gcc/testsuite/g++.dg/cpp0x/trailing6.C index 3476e90e580..86b8e4435c0 100644 --- a/gcc/testsuite/g++.dg/cpp0x/trailing6.C +++ b/gcc/testsuite/g++.dg/cpp0x/trailing6.C @@ -1,5 +1,5 @@ // PR c++/49003 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { auto a() const -> decltype(this) { return this; } diff --git a/gcc/testsuite/g++.dg/cpp0x/trailing7.C b/gcc/testsuite/g++.dg/cpp0x/trailing7.C index c4db10ec80d..e322a3c5ad9 100644 --- a/gcc/testsuite/g++.dg/cpp0x/trailing7.C +++ b/gcc/testsuite/g++.dg/cpp0x/trailing7.C @@ -1,5 +1,5 @@ // PR c++/50365 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { int i; }; diff --git a/gcc/testsuite/g++.dg/cpp0x/trivial1.C b/gcc/testsuite/g++.dg/cpp0x/trivial1.C index 109c8ccdbd4..06ed25733f3 100644 --- a/gcc/testsuite/g++.dg/cpp0x/trivial1.C +++ b/gcc/testsuite/g++.dg/cpp0x/trivial1.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // [basic.types]/10: // Scalar types, trivial class types (Clause 9), arrays of such types and diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-addr.C b/gcc/testsuite/g++.dg/cpp0x/udlit-addr.C index 7d3286e007b..92f192450a5 100644 --- a/gcc/testsuite/g++.dg/cpp0x/udlit-addr.C +++ b/gcc/testsuite/g++.dg/cpp0x/udlit-addr.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } #include <cstddef> diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-args-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-args-neg.C index df7b7281c3d..602d8293e35 100644 --- a/gcc/testsuite/g++.dg/cpp0x/udlit-args-neg.C +++ b/gcc/testsuite/g++.dg/cpp0x/udlit-args-neg.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } #include <cstddef> diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-args.C b/gcc/testsuite/g++.dg/cpp0x/udlit-args.C index ca2039c59d3..15aa6a3ad2c 100644 --- a/gcc/testsuite/g++.dg/cpp0x/udlit-args.C +++ b/gcc/testsuite/g++.dg/cpp0x/udlit-args.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } #include <cstddef> diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-clink-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-clink-neg.C index a80e7244afd..675ef31d241 100644 --- a/gcc/testsuite/g++.dg/cpp0x/udlit-clink-neg.C +++ b/gcc/testsuite/g++.dg/cpp0x/udlit-clink-neg.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } extern "C" { diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-concat-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-concat-neg.C index 61dc2ab02c6..10ff69b7a2b 100644 --- a/gcc/testsuite/g++.dg/cpp0x/udlit-concat-neg.C +++ b/gcc/testsuite/g++.dg/cpp0x/udlit-concat-neg.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } #include <string> diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-concat.C b/gcc/testsuite/g++.dg/cpp0x/udlit-concat.C index 612bc1d1116..870ddc3f5e2 100644 --- a/gcc/testsuite/g++.dg/cpp0x/udlit-concat.C +++ b/gcc/testsuite/g++.dg/cpp0x/udlit-concat.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } #include <string> diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-constexpr.C b/gcc/testsuite/g++.dg/cpp0x/udlit-constexpr.C index 40b0dfac531..e62c34af0c1 100644 --- a/gcc/testsuite/g++.dg/cpp0x/udlit-constexpr.C +++ b/gcc/testsuite/g++.dg/cpp0x/udlit-constexpr.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } constexpr unsigned long long operator"" _grow(unsigned long long n) diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-declare-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-declare-neg.C index 9060abba494..a7eeb4629ab 100644 --- a/gcc/testsuite/g++.dg/cpp0x/udlit-declare-neg.C +++ b/gcc/testsuite/g++.dg/cpp0x/udlit-declare-neg.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // Check that undeclared literal operator calls and literals give appropriate errors. diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-embed-quote.C b/gcc/testsuite/g++.dg/cpp0x/udlit-embed-quote.C index 48a2a1b171d..2832312f3a4 100644 --- a/gcc/testsuite/g++.dg/cpp0x/udlit-embed-quote.C +++ b/gcc/testsuite/g++.dg/cpp0x/udlit-embed-quote.C @@ -1,5 +1,5 @@ // { dg-do run } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // Make sure embedded quotes are not a problem for string and char literals. diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-friend.C b/gcc/testsuite/g++.dg/cpp0x/udlit-friend.C index b3f3ef8a604..0319701edb5 100644 --- a/gcc/testsuite/g++.dg/cpp0x/udlit-friend.C +++ b/gcc/testsuite/g++.dg/cpp0x/udlit-friend.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } long double operator"" _Hertz(long double); diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-general.C b/gcc/testsuite/g++.dg/cpp0x/udlit-general.C index 9e448ac8050..b876a07cde4 100644 --- a/gcc/testsuite/g++.dg/cpp0x/udlit-general.C +++ b/gcc/testsuite/g++.dg/cpp0x/udlit-general.C @@ -1,5 +1,5 @@ // { dg-do run } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // Test user-defined literals. // Test simple operator declaration and definition. diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-implicit-conv-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-implicit-conv-neg.C index 998ad155bf7..851cd9b9c18 100644 --- a/gcc/testsuite/g++.dg/cpp0x/udlit-implicit-conv-neg.C +++ b/gcc/testsuite/g++.dg/cpp0x/udlit-implicit-conv-neg.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } #include <cstdint> diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-inline.C b/gcc/testsuite/g++.dg/cpp0x/udlit-inline.C index 75032c57679..063fd8345de 100644 --- a/gcc/testsuite/g++.dg/cpp0x/udlit-inline.C +++ b/gcc/testsuite/g++.dg/cpp0x/udlit-inline.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // Literal operators can be inline. diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-linkage-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-linkage-neg.C index c2ecede8d48..f969bb5ebab 100644 --- a/gcc/testsuite/g++.dg/cpp0x/udlit-linkage-neg.C +++ b/gcc/testsuite/g++.dg/cpp0x/udlit-linkage-neg.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } extern "C"_badlinkage { // { dg-error "expected unqualified-id before" } diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-mangle.C b/gcc/testsuite/g++.dg/cpp0x/udlit-mangle.C index 6de31b65ea7..c226c269a54 100644 --- a/gcc/testsuite/g++.dg/cpp0x/udlit-mangle.C +++ b/gcc/testsuite/g++.dg/cpp0x/udlit-mangle.C @@ -1,5 +1,5 @@ // PR c++/52521 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } // { dg-final { scan-assembler "_Zli2_wPKc" } } int operator "" _w(const char*); diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-member-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-member-neg.C index a6220c4c0fc..e6ea5776213 100644 --- a/gcc/testsuite/g++.dg/cpp0x/udlit-member-neg.C +++ b/gcc/testsuite/g++.dg/cpp0x/udlit-member-neg.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } class Foo { diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-namespace.C b/gcc/testsuite/g++.dg/cpp0x/udlit-namespace.C index e5d54e51900..a84ed0e3a4f 100644 --- a/gcc/testsuite/g++.dg/cpp0x/udlit-namespace.C +++ b/gcc/testsuite/g++.dg/cpp0x/udlit-namespace.C @@ -1,5 +1,5 @@ // { dg-do run } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // Test user-defined literals. // Test simple operator declaration and definition in namespaces. diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-nofunc-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-nofunc-neg.C index 6ad79b85b1d..2de8f778983 100644 --- a/gcc/testsuite/g++.dg/cpp0x/udlit-nofunc-neg.C +++ b/gcc/testsuite/g++.dg/cpp0x/udlit-nofunc-neg.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // Test user-defined literals. // Test error on non-function declaration. diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-nonempty-str-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-nonempty-str-neg.C index 981865f1526..e8ad1232ef0 100644 --- a/gcc/testsuite/g++.dg/cpp0x/udlit-nonempty-str-neg.C +++ b/gcc/testsuite/g++.dg/cpp0x/udlit-nonempty-str-neg.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // Test user-defined literals. // Test error on non-empty string after 'operator' keyword. diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-nospace-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-nospace-neg.C index f06bd8bdf02..429a876efc1 100644 --- a/gcc/testsuite/g++.dg/cpp0x/udlit-nospace-neg.C +++ b/gcc/testsuite/g++.dg/cpp0x/udlit-nospace-neg.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } float operator ""_abc(const char*); diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-nosuffix-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-nosuffix-neg.C index b90635cd0fc..3c56f216a15 100644 --- a/gcc/testsuite/g++.dg/cpp0x/udlit-nosuffix-neg.C +++ b/gcc/testsuite/g++.dg/cpp0x/udlit-nosuffix-neg.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } char32_t operator"" (char32_t C) // { dg-error "expected suffix identifier" } diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-nounder-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-nounder-neg.C index 2067bbe561f..b238f132878 100644 --- a/gcc/testsuite/g++.dg/cpp0x/udlit-nounder-neg.C +++ b/gcc/testsuite/g++.dg/cpp0x/udlit-nounder-neg.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // Test user-defined literals. // Test warning on declaration without leading underscore. diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-operator-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-operator-neg.C index 27fdedec766..caaaa4951e2 100644 --- a/gcc/testsuite/g++.dg/cpp0x/udlit-operator-neg.C +++ b/gcc/testsuite/g++.dg/cpp0x/udlit-operator-neg.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // Can't have *both* literal operator template and raw literal operator. diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-overflow-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-overflow-neg.C index ed2de22e49d..c90467b6dda 100644 --- a/gcc/testsuite/g++.dg/cpp0x/udlit-overflow-neg.C +++ b/gcc/testsuite/g++.dg/cpp0x/udlit-overflow-neg.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x -Woverflow" } +// { dg-options "-std=c++11 -Woverflow" } // PR c++/52654 int diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-overflow.C b/gcc/testsuite/g++.dg/cpp0x/udlit-overflow.C index 85c15721887..569c10f279c 100644 --- a/gcc/testsuite/g++.dg/cpp0x/udlit-overflow.C +++ b/gcc/testsuite/g++.dg/cpp0x/udlit-overflow.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x }
+// { dg-options -std=c++11 }
// PR c++/52654
int
diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-preproc-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-preproc-neg.C index 23633390cf0..0638ceeb4fe 100644 --- a/gcc/testsuite/g++.dg/cpp0x/udlit-preproc-neg.C +++ b/gcc/testsuite/g++.dg/cpp0x/udlit-preproc-neg.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } int operator"" _badpreproc(const char *str) diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-raw-length.C b/gcc/testsuite/g++.dg/cpp0x/udlit-raw-length.C index 2d910624a7c..d30e9eeeec1 100644 --- a/gcc/testsuite/g++.dg/cpp0x/udlit-raw-length.C +++ b/gcc/testsuite/g++.dg/cpp0x/udlit-raw-length.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // PR c++/50958 typedef decltype(sizeof(0)) size_type; diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-raw-op-string-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-raw-op-string-neg.C index 58ad0e609d0..36d364c908b 100644 --- a/gcc/testsuite/g++.dg/cpp0x/udlit-raw-op-string-neg.C +++ b/gcc/testsuite/g++.dg/cpp0x/udlit-raw-op-string-neg.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // Make sure handing a string to a raw literal generates a sensible error message. diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-raw-op.C b/gcc/testsuite/g++.dg/cpp0x/udlit-raw-op.C index a31ef9328d2..dea0734b5d3 100644 --- a/gcc/testsuite/g++.dg/cpp0x/udlit-raw-op.C +++ b/gcc/testsuite/g++.dg/cpp0x/udlit-raw-op.C @@ -1,5 +1,5 @@ // { dg-do run } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } #include <cassert> #include <cstring> diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-raw-str.C b/gcc/testsuite/g++.dg/cpp0x/udlit-raw-str.C index e94410fd061..e0778897598 100644 --- a/gcc/testsuite/g++.dg/cpp0x/udlit-raw-str.C +++ b/gcc/testsuite/g++.dg/cpp0x/udlit-raw-str.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } #include <string> diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-resolve.C b/gcc/testsuite/g++.dg/cpp0x/udlit-resolve.C index a25516220c2..b4544ee0727 100644 --- a/gcc/testsuite/g++.dg/cpp0x/udlit-resolve.C +++ b/gcc/testsuite/g++.dg/cpp0x/udlit-resolve.C @@ -1,5 +1,5 @@ // { dg-do run } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } #include <cstdint> #include <cassert> diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-shadow-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-shadow-neg.C index 994d58c1a0b..65284073b1a 100644 --- a/gcc/testsuite/g++.dg/cpp0x/udlit-shadow-neg.C +++ b/gcc/testsuite/g++.dg/cpp0x/udlit-shadow-neg.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } // Test that the standard suffixes shadow any user-defined suffixes of the same name. long double diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-string-length.C b/gcc/testsuite/g++.dg/cpp0x/udlit-string-length.C index 86903e8355a..d8be7b78cb0 100644 --- a/gcc/testsuite/g++.dg/cpp0x/udlit-string-length.C +++ b/gcc/testsuite/g++.dg/cpp0x/udlit-string-length.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // PR c++/50941 typedef decltype(sizeof(0)) size_type; diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-suffix-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-suffix-neg.C index 56eab01d736..e3b7e96936b 100644 --- a/gcc/testsuite/g++.dg/cpp0x/udlit-suffix-neg.C +++ b/gcc/testsuite/g++.dg/cpp0x/udlit-suffix-neg.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } #include <string> diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-systemheader.C b/gcc/testsuite/g++.dg/cpp0x/udlit-systemheader.C index 599c8652a14..33dfb9e5d06 100644 --- a/gcc/testsuite/g++.dg/cpp0x/udlit-systemheader.C +++ b/gcc/testsuite/g++.dg/cpp0x/udlit-systemheader.C @@ -1,3 +1,3 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } #include "udlit_system_header" diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-template.C b/gcc/testsuite/g++.dg/cpp0x/udlit-template.C index 6a28f74a22b..55dca2ff815 100644 --- a/gcc/testsuite/g++.dg/cpp0x/udlit-template.C +++ b/gcc/testsuite/g++.dg/cpp0x/udlit-template.C @@ -1,5 +1,5 @@ // { dg-do run } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // Test user-defined literals. // Test template operator declaration and definition. diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-arg-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-arg-neg.C index e8ccb6f545d..f2efdd7a658 100644 --- a/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-arg-neg.C +++ b/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-arg-neg.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<char...> int operator"" _xyz(unsigned long long); // { dg-error "has invalid argument list" } diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-arg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-arg.C index 6324823fabb..fb21f281e10 100644 --- a/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-arg.C +++ b/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-arg.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<char...> int operator"" _abc(); diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-parms-neg.C b/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-parms-neg.C index 4dab4d2f6f0..729325473a1 100644 --- a/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-parms-neg.C +++ b/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-parms-neg.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } class Foo { }; diff --git a/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-parms.C b/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-parms.C index 77456737c70..d83fee8723a 100644 --- a/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-parms.C +++ b/gcc/testsuite/g++.dg/cpp0x/udlit-tmpl-parms.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } class Foo { }; diff --git a/gcc/testsuite/g++.dg/cpp0x/union1.C b/gcc/testsuite/g++.dg/cpp0x/union1.C index cb0f01719c9..f83c89bdeec 100644 --- a/gcc/testsuite/g++.dg/cpp0x/union1.C +++ b/gcc/testsuite/g++.dg/cpp0x/union1.C @@ -1,5 +1,5 @@ -// Negative test for C++0x unrestricted unions -// { dg-options -std=c++0x } +// Negative test for C++11 unrestricted unions +// { dg-options -std=c++11 } // { dg-prune-output "implicitly deleted because" } struct A diff --git a/gcc/testsuite/g++.dg/cpp0x/union2.C b/gcc/testsuite/g++.dg/cpp0x/union2.C index 4f193e281c8..78d88b2b6d9 100644 --- a/gcc/testsuite/g++.dg/cpp0x/union2.C +++ b/gcc/testsuite/g++.dg/cpp0x/union2.C @@ -1,5 +1,5 @@ -// Positive test for C++0x unrestricted unions -// { dg-options -std=c++0x } +// Positive test for C++11 unrestricted unions +// { dg-options -std=c++11 } struct A { diff --git a/gcc/testsuite/g++.dg/cpp0x/union3.C b/gcc/testsuite/g++.dg/cpp0x/union3.C index f1e8ddb6109..a1212e1a93c 100644 --- a/gcc/testsuite/g++.dg/cpp0x/union3.C +++ b/gcc/testsuite/g++.dg/cpp0x/union3.C @@ -1,5 +1,5 @@ -// Runtime test for C++0x unrestricted unions -// { dg-options -std=c++0x } +// Runtime test for C++11 unrestricted unions +// { dg-options -std=c++11 } // { dg-do run } int c, d; diff --git a/gcc/testsuite/g++.dg/cpp0x/union4.C b/gcc/testsuite/g++.dg/cpp0x/union4.C index c82a81cdba8..fa3e97f9226 100644 --- a/gcc/testsuite/g++.dg/cpp0x/union4.C +++ b/gcc/testsuite/g++.dg/cpp0x/union4.C @@ -1,5 +1,5 @@ // PR c++/48537 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct SFoo { diff --git a/gcc/testsuite/g++.dg/cpp0x/union5.C b/gcc/testsuite/g++.dg/cpp0x/union5.C index 423b3482323..51780619af0 100644 --- a/gcc/testsuite/g++.dg/cpp0x/union5.C +++ b/gcc/testsuite/g++.dg/cpp0x/union5.C @@ -1,5 +1,5 @@ // PR c++/49803 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct X { diff --git a/gcc/testsuite/g++.dg/cpp0x/unnamed_refs.C b/gcc/testsuite/g++.dg/cpp0x/unnamed_refs.C index c5966764586..8afe7a7ff27 100644 --- a/gcc/testsuite/g++.dg/cpp0x/unnamed_refs.C +++ b/gcc/testsuite/g++.dg/cpp0x/unnamed_refs.C @@ -3,7 +3,7 @@ // Test: Unamed rvalue references are treated as lvalues. // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template <bool> struct sa; template <> struct sa<true> {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-104.C b/gcc/testsuite/g++.dg/cpp0x/variadic-104.C index c693b33f9a5..e7a032c1993 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic-104.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-104.C @@ -1,5 +1,5 @@ // PR c++/45236 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template <class T, class S> class foo; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-bind.C b/gcc/testsuite/g++.dg/cpp0x/variadic-bind.C index abe445d4341..21ebb2ff9f9 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic-bind.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-bind.C @@ -1,5 +1,5 @@ // { dg-do run } -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } // A basic implementation of TR1's bind using variadic teplates // Contributed by Douglas Gregor <doug.gregor@gmail.com> #include <cassert> diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-crash1.C b/gcc/testsuite/g++.dg/cpp0x/variadic-crash1.C index f26aee2a91f..768f2ee3977 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic-crash1.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-crash1.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } #define ONE #define TWO diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-crash2.C b/gcc/testsuite/g++.dg/cpp0x/variadic-crash2.C index f46b8e534e4..f6b31966482 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic-crash2.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-crash2.C @@ -1,7 +1,7 @@ // Contributed by Dodji Seketeli <dodji@redhat.com> // Origin: PR c++/39637 // { dg-do compile } -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<class... Types> void diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-default.C b/gcc/testsuite/g++.dg/cpp0x/variadic-default.C index 2625e259f78..0653d2a2cf0 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic-default.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-default.C @@ -1,5 +1,5 @@ // PR c++/49205 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } #include <initializer_list> diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex1.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex1.C index 485fffa476c..0fd2ab969fb 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic-ex1.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-ex1.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename ... Elements> class Tuple; Tuple<>* t; // OK: Elements is empty Tuple* u; // { dg-error "template-name" } diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex10.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex10.C index e8b6b722148..4515453294b 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic-ex10.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-ex10.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename... Types> struct Tuple { }; Tuple<> t0; // Types contains no arguments diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex11.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex11.C index 57ef2a3d30e..4d45d5e5a8e 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic-ex11.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-ex11.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename... Types> void f(Types... args); diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex12.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex12.C index b97df310203..35a71a9c9ca 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic-ex12.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-ex12.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename... Types> void f(Types... rest); diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex13.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex13.C index b742cb1d369..f024f8474c6 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic-ex13.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-ex13.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename T, typename U> struct is_same { static const bool value = false; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex14.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex14.C index 105096a78bf..108d1111a69 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic-ex14.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-ex14.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<class T> class A { /* ... */ }; template<class T, class U = T> class B { /* ... */ }; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex2.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex2.C index ca5fa271637..0eb029bcb3f 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic-ex2.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-ex2.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<class... Types> struct B { // { dg-error "declaration of" } void f3(); void f4(); diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex3.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex3.C index 018eaa3ed8b..25d80181d6d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic-ex3.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-ex3.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<class X, class Y, class... Z> X f(Y); // { dg-message "note" } void g() { diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex4.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex4.C index 0a777c4853b..b05ca57f3cf 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic-ex4.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-ex4.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<class X, class Y, class Z> X f(Y,Z); // { dg-message "note" } template<class... Args> void f2(); void g() diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex5.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex5.C index 2439a51c5a4..81b57971050 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic-ex5.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-ex5.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename... Types> void f(Types... values); void g() diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex6.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex6.C index 87b1bf20576..5bb01d5141d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic-ex6.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-ex6.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<class...> struct Tuple { }; template<class... Types> void f(Types&...); diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex7.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex7.C index 7ca31f9c67b..69f94672b6b 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic-ex7.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-ex7.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename...> struct Tuple { }; template<typename... Types> char& g(Tuple<Types...>); // #1 template<typename T1, typename... Types> short& g(Tuple<T1, Types...>); // #2 diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex8.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex8.C index 03d28b82535..f7fb32ffe26 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic-ex8.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-ex8.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<class> struct X { static const bool primary = true; }; template<class R, class... ArgTypes> struct X<R(int, ArgTypes...)> { static const bool primary = false; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ex9.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ex9.C index 74215c99727..8b68711b877 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic-ex9.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-ex9.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename... Args> char& f(Args... args); // #1 template<typename T1, typename... Args> short& f(T1 a1, Args... args); // #2 template<typename T1, typename T2> int& f(T1 a2, T2 a3); // #3 diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-explicit1.C b/gcc/testsuite/g++.dg/cpp0x/variadic-explicit1.C index a097f43d218..8a1e285ecdd 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic-explicit1.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-explicit1.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<class T, class U> struct A { }; template<class... T, class ... U> void f( A<T,U>... p); diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-function.C b/gcc/testsuite/g++.dg/cpp0x/variadic-function.C index eeb137705f2..4240b4f3284 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic-function.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-function.C @@ -1,5 +1,5 @@ // { dg-do run } -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } // A basic implementation of TR1's function using variadic teplates // Contributed by Douglas Gregor <doug.gregor@gmail.com> #include <cassert> diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-init.C b/gcc/testsuite/g++.dg/cpp0x/variadic-init.C index 34ade85e0f9..9972928d2cc 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic-init.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-init.C @@ -1,5 +1,5 @@ // { dg-do run } -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } // PR c++/33510 #define SIZE_FROM_CTOR diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-lambda.C b/gcc/testsuite/g++.dg/cpp0x/variadic-lambda.C index 705d441493e..51263fd57e6 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic-lambda.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-lambda.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } struct int_placeholder; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-mem_fn.C b/gcc/testsuite/g++.dg/cpp0x/variadic-mem_fn.C index 51c5c79ef9f..4e090d1e83f 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic-mem_fn.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-mem_fn.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } // { dg-do run } // A basic implementation of TR1's mem_fn using variadic teplates // Contributed by Douglas Gregor <doug.gregor@gmail.com> diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-new.C b/gcc/testsuite/g++.dg/cpp0x/variadic-new.C index 5bbb9c81b0e..45d11bae286 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic-new.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-new.C @@ -1,5 +1,5 @@ // { dg-do run } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // Contributed by Peter Dimov // PR c++/32597 #include <assert.h> diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-new2.C b/gcc/testsuite/g++.dg/cpp0x/variadic-new2.C index 81d333398bd..c47fbf43868 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic-new2.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-new2.C @@ -1,5 +1,5 @@ // { dg-do run } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // PR c++/32597 #include <assert.h> #include <new> diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-nondeduce1.C b/gcc/testsuite/g++.dg/cpp0x/variadic-nondeduce1.C index a64d7971c6e..c6e44bb77aa 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic-nondeduce1.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-nondeduce1.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template <class... T> void f(T..., int, T...) { } diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-rref.C b/gcc/testsuite/g++.dg/cpp0x/variadic-rref.C index 08221b460fe..609868475fa 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic-rref.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-rref.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // PR c++/33939 template<typename T> struct refs_only; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-throw.C b/gcc/testsuite/g++.dg/cpp0x/variadic-throw.C index 8363c2a73f9..4c3bd95bf33 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic-throw.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-throw.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } // { dg-prune-output "note" } // PR c++/33509 template<int M, int N> struct pair diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-ttp.C b/gcc/testsuite/g++.dg/cpp0x/variadic-ttp.C index 41f1c1db43d..d8f14cb16aa 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic-ttp.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-ttp.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } // PR c++/34101 template<typename> struct A {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-tuple.C b/gcc/testsuite/g++.dg/cpp0x/variadic-tuple.C index 11ce14af28c..4ad2cc39a7b 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic-tuple.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-tuple.C @@ -1,5 +1,5 @@ // { dg-do run } -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } // An implementation of TR1's <tuple> using variadic teplates // Contributed by Douglas Gregor <doug.gregor@gmail.com> diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-unify-2.C b/gcc/testsuite/g++.dg/cpp0x/variadic-unify-2.C index 80c9f5d2c3a..33920a9a1a7 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic-unify-2.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-unify-2.C @@ -1,6 +1,6 @@ // Contributed by Dodji Seketeli <dodji@redhat.com> // Origin: PR c++/40155 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // { dg-do compile } template <typename T> struct identity diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-unify.C b/gcc/testsuite/g++.dg/cpp0x/variadic-unify.C index 54234391e64..5213dbbabf3 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic-unify.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-unify.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<typename...> struct tuple { }; template<typename... Args1, typename... Args2> diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-unresolved.C b/gcc/testsuite/g++.dg/cpp0x/variadic-unresolved.C index a8463de1980..2fc3471dded 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic-unresolved.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic-unresolved.C @@ -1,5 +1,5 @@ // PR c++/50086 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<typename T> void tfun(); template<typename T> void fun1(T); diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic1.C b/gcc/testsuite/g++.dg/cpp0x/variadic1.C index f87d53ca386..884ef886239 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic1.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic1.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename...> class tuple; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic10.C b/gcc/testsuite/g++.dg/cpp0x/variadic10.C index 5f73eba8d68..6a03df053a7 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic10.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic10.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename T1, typename T2> struct pair {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic100.C b/gcc/testsuite/g++.dg/cpp0x/variadic100.C index a364bbc9116..654c4e9013b 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic100.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic100.C @@ -1,5 +1,5 @@ // PR c++/43143 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<typename T> T&& declval(); diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic101.C b/gcc/testsuite/g++.dg/cpp0x/variadic101.C index 445a770afa1..d028a570eaa 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic101.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic101.C @@ -1,5 +1,5 @@ // PR c++/43382 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<class T> struct Container diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic102.C b/gcc/testsuite/g++.dg/cpp0x/variadic102.C index dc9c4aea8cb..e656886fc3e 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic102.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic102.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } struct nAny { template<class... T> diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic103.C b/gcc/testsuite/g++.dg/cpp0x/variadic103.C index 9d6b5ea20b8..cab73d7647d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic103.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic103.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<class T> T&& create(); diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic105.C b/gcc/testsuite/g++.dg/cpp0x/variadic105.C index 66d24a7efe3..ecd2410f4bb 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic105.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic105.C @@ -1,5 +1,5 @@ // PR c++/47289 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } // { dg-prune-output "note" } template <template <typename... __ARGS> class _F, typename... _ARGS> diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic106.C b/gcc/testsuite/g++.dg/cpp0x/variadic106.C index 80ec0844fbf..d68b9ff011a 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic106.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic106.C @@ -1,5 +1,5 @@ // Origin: PR c++/47326 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // { dg-do compile } template <int _N> diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic107.C b/gcc/testsuite/g++.dg/cpp0x/variadic107.C index 5c3f468515d..0d6923f4fd1 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic107.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic107.C @@ -1,5 +1,5 @@ // PR c++/48451 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } namespace std { template <class T> T&& declval(); diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic108.C b/gcc/testsuite/g++.dg/cpp0x/variadic108.C index 3ad5af45717..0986516415c 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic108.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic108.C @@ -1,5 +1,5 @@ // PR c++/48736 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<class T> T&& create(); diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic109.C b/gcc/testsuite/g++.dg/cpp0x/variadic109.C index 0ec69af812e..8acdfb8c819 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic109.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic109.C @@ -1,5 +1,5 @@ // PR c++/48292 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template <typename... Args> int g(Args...); diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic11.C b/gcc/testsuite/g++.dg/cpp0x/variadic11.C index 3c27de0fb19..58eb1636f04 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic11.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic11.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename...> struct count; template<> diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic110.C b/gcc/testsuite/g++.dg/cpp0x/variadic110.C index 86f1bb1543c..556594c3b74 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic110.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic110.C @@ -1,5 +1,5 @@ // PR c++/45698 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template <class... Ts> struct tuple { }; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic111.C b/gcc/testsuite/g++.dg/cpp0x/variadic111.C index cb94ce69755..01a6653612f 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic111.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic111.C @@ -1,5 +1,5 @@ // PR c++/48424 -// { dg-options "-std=c++0x -fabi-version=0" } +// { dg-options "-std=c++11 -fabi-version=0" } template<typename... Args1> struct S diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic112.C b/gcc/testsuite/g++.dg/cpp0x/variadic112.C index 1640657d950..be435542643 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic112.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic112.C @@ -1,5 +1,5 @@ // PR c++/49420 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct A { }; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic113.C b/gcc/testsuite/g++.dg/cpp0x/variadic113.C index 3f1bb2ad04a..bee367e947d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic113.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic113.C @@ -1,5 +1,5 @@ // PR c++/49251 -// { dg-options "-std=c++0x -Wunused-parameter" } +// { dg-options "-std=c++11 -Wunused-parameter" } struct A {}; template <int> int f(A); diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic114.C b/gcc/testsuite/g++.dg/cpp0x/variadic114.C index 3ffede5c507..80f546a82b4 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic114.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic114.C @@ -1,5 +1,5 @@ // PR c++/49785 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template <typename, typename ...> struct B { }; template <typename> class A; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic115.C b/gcc/testsuite/g++.dg/cpp0x/variadic115.C index fa032e3b022..8c59a79497d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic115.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic115.C @@ -1,5 +1,5 @@ // PR c++/49593 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<typename... T> void f(T...) { } diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic116.C b/gcc/testsuite/g++.dg/cpp0x/variadic116.C index 079d751cb46..ab4ed45f9b7 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic116.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic116.C @@ -1,5 +1,5 @@ // Origin: PR c++/48320 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<class... T> struct tuple diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic117.C b/gcc/testsuite/g++.dg/cpp0x/variadic117.C index 22f2fc5ae2d..477a9f1e275 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic117.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic117.C @@ -1,4 +1,4 @@ -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template <class T> struct A { typedef T type; }; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic118.C b/gcc/testsuite/g++.dg/cpp0x/variadic118.C index 43bf9bab213..75ee1cdcabe 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic118.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic118.C @@ -1,5 +1,5 @@ // This should fail deduction, before it produces a candidate. -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template <class... T> void f(T... ts); // { dg-message "deduction" } diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic12.C b/gcc/testsuite/g++.dg/cpp0x/variadic12.C index 30108c99932..4b56b0117e8 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic12.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic12.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } // A tuple type template<typename... Args> struct tuple { }; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic121.C b/gcc/testsuite/g++.dg/cpp0x/variadic121.C index 805c0065fe9..1d086fc8ccd 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic121.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic121.C @@ -1,5 +1,5 @@ // PR c++/51507 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<typename ...> struct foo { typedef void type; }; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic13.C b/gcc/testsuite/g++.dg/cpp0x/variadic13.C index 7794e8a3dc9..24601e03ab2 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic13.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic13.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename... Args> struct tuple1 { }; template<typename... Args> struct tuple2 { }; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic135.C b/gcc/testsuite/g++.dg/cpp0x/variadic135.C index fbf5dec4797..841f7ceebbe 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic135.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic135.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template <typename ...> struct S; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic14.C b/gcc/testsuite/g++.dg/cpp0x/variadic14.C index 3c1bb0d6d23..339d5f921d4 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic14.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic14.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename R, typename... ArgTypes> struct make_function_type { diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic143.C b/gcc/testsuite/g++.dg/cpp0x/variadic143.C index 7737b4cacf4..da3e7c4789e 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic143.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic143.C @@ -1,5 +1,5 @@ // PR c++/56782 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<class T> T&& declval(); diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic145.C b/gcc/testsuite/g++.dg/cpp0x/variadic145.C deleted file mode 100644 index 65e4607f9a7..00000000000 --- a/gcc/testsuite/g++.dg/cpp0x/variadic145.C +++ /dev/null @@ -1,10 +0,0 @@ -// PR c++/58466 -// { dg-do compile { target c++11 } } - -template<char, char...> struct A; - -template<typename> struct B; - -template<char... C> struct B<A<C...>> {}; - -B<A<'X'>> b; // { dg-error "incomplete type" } diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic15.C b/gcc/testsuite/g++.dg/cpp0x/variadic15.C index 68786cb8229..c7dadc6276d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic15.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic15.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename R, typename... ArgTypes> struct make_function_type { diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic16.C b/gcc/testsuite/g++.dg/cpp0x/variadic16.C index 001919d469f..23a5710760b 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic16.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic16.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename R, typename... ArgTypes> struct make_function_type { diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic17.C b/gcc/testsuite/g++.dg/cpp0x/variadic17.C index 986721bbec3..cc1a5f02125 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic17.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic17.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename R, typename... ArgTypes> struct make_function_type { diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic18.C b/gcc/testsuite/g++.dg/cpp0x/variadic18.C index 147ed8e4bfc..cfacd7a7910 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic18.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic18.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename...> class tuple { }; template<typename T, template<typename T> class... Metafunctions> diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic19.C b/gcc/testsuite/g++.dg/cpp0x/variadic19.C index 92e7a953aba..7a0864504c7 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic19.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic19.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename... Args> struct tuple { static const int value = 0; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic2.C b/gcc/testsuite/g++.dg/cpp0x/variadic2.C index 207a80648f3..023cb08316d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic2.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic2.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename... Args = int> // { dg-error "default argument" } class tuple2; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic20.C b/gcc/testsuite/g++.dg/cpp0x/variadic20.C index bfb42bea09c..e8bdf121bf4 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic20.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic20.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename T> struct add_pointer; template<typename T> struct add_reference; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic21.C b/gcc/testsuite/g++.dg/cpp0x/variadic21.C index b65e995b9a1..e2115f1362c 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic21.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic21.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename T, int... Dims> struct array { }; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic22.C b/gcc/testsuite/g++.dg/cpp0x/variadic22.C index 1d26e40d981..c37f056c2bb 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic22.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic22.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename R, typename... ArgTypes> struct make_function_type { diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic23.C b/gcc/testsuite/g++.dg/cpp0x/variadic23.C index 43309a1e1f8..ea0d31c5007 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic23.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic23.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename T, int... Dims> struct array { static const int value = 0; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic24.C b/gcc/testsuite/g++.dg/cpp0x/variadic24.C index 6ef8e8a77d0..fe953bc150e 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic24.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic24.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename T, T... Values> struct vector_c { }; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic25.C b/gcc/testsuite/g++.dg/cpp0x/variadic25.C index 6589e7f60af..a5f1eee7054 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic25.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic25.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<int... Values> struct sum; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic26.C b/gcc/testsuite/g++.dg/cpp0x/variadic26.C index 7f9f6bc8052..9150e429958 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic26.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic26.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<template<int, int> class Meta, int Initial, int... Values> struct accumulate { static const int value = Initial; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic27.C b/gcc/testsuite/g++.dg/cpp0x/variadic27.C index 45a897ce2c9..f4b4470a39c 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic27.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic27.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename Signature> struct function_traits; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic28.C b/gcc/testsuite/g++.dg/cpp0x/variadic28.C index 167088b4945..4e60d9f2815 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic28.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic28.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename Signature> struct function_traits; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic29.C b/gcc/testsuite/g++.dg/cpp0x/variadic29.C index aaed595831d..a7bc877c73c 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic29.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic29.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename Signature> struct function_traits; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic3.C b/gcc/testsuite/g++.dg/cpp0x/variadic3.C index 42ba8ab47ea..f08ff62b8fb 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic3.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic3.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename... Args> class tuple {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic30.C b/gcc/testsuite/g++.dg/cpp0x/variadic30.C index 66cbe9f6272..36d93c12f3e 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic30.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic30.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename... T> void eat(T...); diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic31.C b/gcc/testsuite/g++.dg/cpp0x/variadic31.C index db8daa89858..48ae5604c92 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic31.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic31.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x -g" } +// { dg-options "-std=gnu++11 -g" } template<typename... T> void eat(T...) { } diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic32.C b/gcc/testsuite/g++.dg/cpp0x/variadic32.C index c5bee55ccb7..0f620ecbd13 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic32.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic32.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename... T> void eat(const T&...) { } diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic33.C b/gcc/testsuite/g++.dg/cpp0x/variadic33.C index 5784be887ac..d962f5a1da9 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic33.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic33.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } void print_all() {} template<typename T, typename... Rest> diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic34.C b/gcc/testsuite/g++.dg/cpp0x/variadic34.C index 5eee3f13c62..e266b603e82 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic34.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic34.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<int I, typename... Args> void get_ith(const Args&... args); diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic35.C b/gcc/testsuite/g++.dg/cpp0x/variadic35.C index 666a1f5d039..518edec4145 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic35.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic35.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<int I, typename... Args> void get_ith(const Args&... args); // { dg-message "note" } diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic36.C b/gcc/testsuite/g++.dg/cpp0x/variadic36.C index 90636020401..bbd2159b65f 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic36.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic36.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename T, typename... Args> void f(const T&, const Args&... args) { diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic37.C b/gcc/testsuite/g++.dg/cpp0x/variadic37.C index a6e5f613fcd..2f6042ec27c 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic37.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic37.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename... Values> struct tuple { diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic38.C b/gcc/testsuite/g++.dg/cpp0x/variadic38.C index e4ae4a6305d..b320a8a3c5c 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic38.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic38.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<int... Values> struct int_vec {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic39.C b/gcc/testsuite/g++.dg/cpp0x/variadic39.C index bd656ba8504..4ee19552711 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic39.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic39.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename... Args> struct tuple {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic4.C b/gcc/testsuite/g++.dg/cpp0x/variadic4.C index 1bdad3256fb..5371a860bfa 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic4.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic4.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x -fabi-version=0" } +// { dg-options "-std=gnu++11 -fabi-version=0" } // { dg-do compile } template<typename... Args> class tuple {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic40.C b/gcc/testsuite/g++.dg/cpp0x/variadic40.C index 6cc9273a897..c6512e90192 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic40.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic40.C @@ -1,3 +1,3 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename... Values, typename T> struct backward_tuple {}; // { dg-error "end" } diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic41.C b/gcc/testsuite/g++.dg/cpp0x/variadic41.C index 9cfd847f318..3eee1f572c3 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic41.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic41.C @@ -1,5 +1,5 @@ // A function parameter pack is only deduced if it's at the end -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename... Args> void f(const Args&... args, int oops); diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic42.C b/gcc/testsuite/g++.dg/cpp0x/variadic42.C index 3ec68e8b1ff..b5d917f186a 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic42.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic42.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x -fabi-version=5" } +// { dg-options "-std=gnu++11 -fabi-version=5" } // { dg-do compile } template<typename... Args> void f(Args...) { } diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic43.C b/gcc/testsuite/g++.dg/cpp0x/variadic43.C index fce81ae0dd1..7310660752c 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic43.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic43.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename... Args> int f(const Args&...); diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic44.C b/gcc/testsuite/g++.dg/cpp0x/variadic44.C index 8452a96cc21..1e314be8b19 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic44.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic44.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } // { dg-do compile } template<typename... Args> int f(const Args&...); diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic45.C b/gcc/testsuite/g++.dg/cpp0x/variadic45.C index c5a66ab2062..a36a56b7491 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic45.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic45.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename... Args> int& f(Args...); diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic46.C b/gcc/testsuite/g++.dg/cpp0x/variadic46.C index 8b81a363bf1..1fe0e60e0ea 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic46.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic46.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename... Args> int& f(Args&...); diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic47.C b/gcc/testsuite/g++.dg/cpp0x/variadic47.C index d80371c0eee..252a4e7b1a5 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic47.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic47.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename T> struct wrap { }; template<typename... Args> diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic48.C b/gcc/testsuite/g++.dg/cpp0x/variadic48.C index ab3f777f795..ca562c22e6f 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic48.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic48.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename T, typename... Args> int& f(const T&, Args...); diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic49.C b/gcc/testsuite/g++.dg/cpp0x/variadic49.C index 7e2215f2c23..4ccedb1cd12 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic49.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic49.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } int& f(...); template<typename... Args> diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic5.C b/gcc/testsuite/g++.dg/cpp0x/variadic5.C index d1f333566d8..b2a35106195 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic5.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic5.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename... Args> struct tuple { static const int value = 0; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic50.C b/gcc/testsuite/g++.dg/cpp0x/variadic50.C index a2c3b7c908f..32fbb65f42d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic50.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic50.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } int& f(int, double, ...); template<typename... Args> diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic51.C b/gcc/testsuite/g++.dg/cpp0x/variadic51.C index e2e2d630a7b..9b2fa218dd6 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic51.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic51.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename T1, typename T2> float& f(T1, T2); diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic52.C b/gcc/testsuite/g++.dg/cpp0x/variadic52.C index 12b121fe4ec..9293d86878a 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic52.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic52.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename T, T... Values> struct vector_c { }; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic53.C b/gcc/testsuite/g++.dg/cpp0x/variadic53.C index 09a3879b420..b595df5db56 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic53.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic53.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename F, typename... BoundArgs> class bound_functor { diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic54.C b/gcc/testsuite/g++.dg/cpp0x/variadic54.C index db750d76511..dd3ab109da8 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic54.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic54.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename F, typename... BoundArgs> class bound_functor { diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic55.C b/gcc/testsuite/g++.dg/cpp0x/variadic55.C index b9c8cffb027..e22a16bb8a1 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic55.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic55.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename F, typename... BoundArgs> class bound_functor { diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic56.C b/gcc/testsuite/g++.dg/cpp0x/variadic56.C index 77846e51321..f0c1beb7894 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic56.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic56.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename... Elements> struct tuple { }; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic57.C b/gcc/testsuite/g++.dg/cpp0x/variadic57.C index 9833b1bb359..ca12a2d1a3e 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic57.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic57.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename T, int... Dims> struct array { int foo(); diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic58.C b/gcc/testsuite/g++.dg/cpp0x/variadic58.C index 5da0730b5aa..3099ef6808f 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic58.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic58.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } #include <typeinfo> template<typename... Args> diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic59.C b/gcc/testsuite/g++.dg/cpp0x/variadic59.C index 6d6e52f9319..e7abf8b78a8 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic59.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic59.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<class T, typename... VarArgs> void print(T t, VarArgs args); // { dg-error "packs not expanded" } // { dg-message "VarArgs" "note" { target *-*-* } 3 } diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic6.C b/gcc/testsuite/g++.dg/cpp0x/variadic6.C index 105550bb903..bf6350e1dd5 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic6.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic6.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename ... Args> struct tuple_base {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic63.C b/gcc/testsuite/g++.dg/cpp0x/variadic63.C index 359def1cd10..83db8fc43b4 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic63.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic63.C @@ -1,2 +1,2 @@ -// { dg-options "-std=gnu++0x -pedantic" } +// { dg-options "-std=gnu++11 -pedantic" } template<typename... Args> class tuple; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic64.C b/gcc/testsuite/g++.dg/cpp0x/variadic64.C index c9212e2e959..fdc53540613 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic64.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic64.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<int... Indexes> struct _Index_tuple { }; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic65.C b/gcc/testsuite/g++.dg/cpp0x/variadic65.C index 77be10676ae..4544f9289ca 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic65.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic65.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } struct unused; template<typename T1 = unused, typename T2 = unused, typename T3 = unused, typename T4 = unused, typename T5 = unused, typename T6 = unused> diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic66.C b/gcc/testsuite/g++.dg/cpp0x/variadic66.C index 5c31ae06fd4..943bd70d0aa 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic66.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic66.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename Result, typename Functor, typename... ArgTypes> Result bind(Functor, ArgTypes...) { } diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic67.C b/gcc/testsuite/g++.dg/cpp0x/variadic67.C index e496bfc176c..5538bc911e2 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic67.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic67.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename... Elements> struct tuple {}; template<typename... Args> diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic68.C b/gcc/testsuite/g++.dg/cpp0x/variadic68.C index 07cf8e3896a..22b3444a0ec 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic68.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic68.C @@ -1,5 +1,5 @@ // { dg-do run } -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } extern "C" void abort(); template<typename T, T... Values> diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic69.C b/gcc/testsuite/g++.dg/cpp0x/variadic69.C index 5fe9a1950ff..eb8626524be 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic69.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic69.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename T> struct stored_value { diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic7.C b/gcc/testsuite/g++.dg/cpp0x/variadic7.C index 3ba37bfb66e..68358f06717 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic7.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic7.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename... Args> struct tuple_base { static const int value = 0; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic70.C b/gcc/testsuite/g++.dg/cpp0x/variadic70.C index 15bed461dc7..cc269915f42 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic70.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic70.C @@ -1,5 +1,5 @@ // { dg-do run } -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template <typename T, T... Args> struct bomb; template <typename T> diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic71.C b/gcc/testsuite/g++.dg/cpp0x/variadic71.C index bea3cc34631..879321593bc 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic71.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic71.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename...> struct list {}; template<typename Sequence, typename Head> diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic72.C b/gcc/testsuite/g++.dg/cpp0x/variadic72.C index b1a620d5386..77520b301c2 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic72.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic72.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } struct A {}; struct B {}; struct C {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic73.C b/gcc/testsuite/g++.dg/cpp0x/variadic73.C index 05925e7aa57..00e8fb46330 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic73.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic73.C @@ -1,5 +1,5 @@ // { dg-do run } -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } struct A {}; struct B {}; struct C {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic75.C b/gcc/testsuite/g++.dg/cpp0x/variadic75.C index f57f8b3ef47..32df43fd116 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic75.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic75.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename...> struct tuple { }; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic76.C b/gcc/testsuite/g++.dg/cpp0x/variadic76.C index ff0211ded15..df147fdcb7a 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic76.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic76.C @@ -1,6 +1,6 @@ // PR c++/33496 // { dg-do compile } -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<int... N> int foo () { diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic77.C b/gcc/testsuite/g++.dg/cpp0x/variadic77.C index 8c6119ff160..49b5684b3e3 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic77.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic77.C @@ -1,6 +1,6 @@ // PR c++/33496 // { dg-do compile } -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<int M, int N> struct pair { diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic78.C b/gcc/testsuite/g++.dg/cpp0x/variadic78.C index 9e2b84ad0a6..4d3d5428c0a 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic78.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic78.C @@ -1,6 +1,6 @@ // PR c++/33496 // { dg-do compile } -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<int M, int N> struct pair { diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic79.C b/gcc/testsuite/g++.dg/cpp0x/variadic79.C index c6479e04fe5..e7a2a15c049 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic79.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic79.C @@ -1,6 +1,6 @@ // PR c++/33213 // { dg-do compile } -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<template<typename> class...> struct A; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic8.C b/gcc/testsuite/g++.dg/cpp0x/variadic8.C index c3a1340cf26..96fbfad7e79 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic8.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic8.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename... Args> struct tuple_base { static const int value = 0; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic80.C b/gcc/testsuite/g++.dg/cpp0x/variadic80.C index a56cdb404c0..a8bb9023a68 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic80.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic80.C @@ -1,6 +1,6 @@ // PR c++/31434 // { dg-do run } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } extern "C" void abort (); diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic81.C b/gcc/testsuite/g++.dg/cpp0x/variadic81.C index cce61b31649..e282394145c 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic81.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic81.C @@ -1,5 +1,5 @@ // PR c++/33461 -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename> struct A; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic82.C b/gcc/testsuite/g++.dg/cpp0x/variadic82.C index 03aec80211d..50be75db557 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic82.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic82.C @@ -1,5 +1,5 @@ // PR c++/33461 -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename> struct A; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic83.C b/gcc/testsuite/g++.dg/cpp0x/variadic83.C index c446e697420..3293d813a89 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic83.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic83.C @@ -1,5 +1,5 @@ // PR c++/31441 -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename> struct A; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic84.C b/gcc/testsuite/g++.dg/cpp0x/variadic84.C index ce31267954f..8e0dc4475fe 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic84.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic84.C @@ -1,6 +1,6 @@ // PR c++/32565 // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<typename...> struct A1; template<template<int...> class T> struct A1<T<0> > {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic85.C b/gcc/testsuite/g++.dg/cpp0x/variadic85.C index facb263910f..6f6cb8a17bf 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic85.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic85.C @@ -1,6 +1,6 @@ // PR c++/32565 // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<typename...> struct A1; template<template<int, int...> class T> struct A1<T<0, 1> > {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic86.C b/gcc/testsuite/g++.dg/cpp0x/variadic86.C index d8fcd620e95..73400548a96 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic86.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic86.C @@ -1,6 +1,6 @@ // PR c++/33943 // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<typename... A> struct foo {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic87.C b/gcc/testsuite/g++.dg/cpp0x/variadic87.C index 1defa23da29..7e82f37a663 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic87.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic87.C @@ -1,5 +1,5 @@ // PR c++/33965 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<typename T> struct foo { diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic88.C b/gcc/testsuite/g++.dg/cpp0x/variadic88.C index b14cabe3218..a917b530212 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic88.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic88.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<template<typename...> class TT> TT<int, float, double> foo(TT<int, float>) diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic89.C b/gcc/testsuite/g++.dg/cpp0x/variadic89.C index b943771a6de..b5bedeba7e6 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic89.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic89.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // Contributed by Eric Niebler template<typename T, typename U> struct pair diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic9.C b/gcc/testsuite/g++.dg/cpp0x/variadic9.C index c5db6af6a89..2d12de5fdf1 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic9.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic9.C @@ -1,4 +1,4 @@ -// { dg-options "-std=gnu++0x" } +// { dg-options "-std=gnu++11" } template<typename T1, typename T2> struct pair {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic90.C b/gcc/testsuite/g++.dg/cpp0x/variadic90.C index 632e166c346..0529057e623 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic90.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic90.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<template<typename...> class TT> struct X { }; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic91.C b/gcc/testsuite/g++.dg/cpp0x/variadic91.C index d78b791fbf4..a5ebdfe7aa2 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic91.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic91.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<int N> struct Int2Type { }; template<typename... T> diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic92.C b/gcc/testsuite/g++.dg/cpp0x/variadic92.C index d382912c91f..b7fa0006b34 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic92.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic92.C @@ -1,5 +1,5 @@ // Various tests for variadic templates and partial specialization. -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // PR c++/36846 template<typename A, typename B> diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic93.C b/gcc/testsuite/g++.dg/cpp0x/variadic93.C index 7d8c3298e61..c17988490fa 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic93.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic93.C @@ -1,5 +1,5 @@ // PR c++/35297 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template <class T=int, class... ARGS> struct test2 {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic94.C b/gcc/testsuite/g++.dg/cpp0x/variadic94.C index 8420f73a6a6..213e53cab58 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic94.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic94.C @@ -1,5 +1,5 @@ // PR c++/40595 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<int N> struct S diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic95.C b/gcc/testsuite/g++.dg/cpp0x/variadic95.C index ebb04ebc10b..b84489aa593 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic95.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic95.C @@ -1,5 +1,5 @@ // PR c++/39863 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template <typename... T> struct A {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic96.C b/gcc/testsuite/g++.dg/cpp0x/variadic96.C index d4709d074b6..e5e7df14729 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic96.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic96.C @@ -1,6 +1,6 @@ // Contributed by Dodji Seketeli <dodji@redhat.com> // Origin: PR c++/41785 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } struct a {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic97.C b/gcc/testsuite/g++.dg/cpp0x/variadic97.C index a2070319ebd..8c3783251df 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic97.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic97.C @@ -1,5 +1,5 @@ // PR c++/42266 -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } template<typename... _Elements> class tuple; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic98.C b/gcc/testsuite/g++.dg/cpp0x/variadic98.C index 6af599fcaa0..a29ee8e4211 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic98.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic98.C @@ -1,6 +1,6 @@ // PR c++/42358 // { dg-do assemble } -// { dg-options -std=c++0x } +// { dg-options -std=c++11 } typedef __PTRDIFF_TYPE__ ptrdiff_t; typedef __SIZE_TYPE__ size_t; diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic99.C b/gcc/testsuite/g++.dg/cpp0x/variadic99.C index 457212712bd..f6544310bc5 100644 --- a/gcc/testsuite/g++.dg/cpp0x/variadic99.C +++ b/gcc/testsuite/g++.dg/cpp0x/variadic99.C @@ -1,5 +1,5 @@ // PR c++/43054 -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<typename R> struct future { }; diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-33964.C b/gcc/testsuite/g++.dg/cpp0x/vt-33964.C index 0b84b6cec89..9ba9367e8da 100644 --- a/gcc/testsuite/g++.dg/cpp0x/vt-33964.C +++ b/gcc/testsuite/g++.dg/cpp0x/vt-33964.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<typename ... Args> struct foo { diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-34050.C b/gcc/testsuite/g++.dg/cpp0x/vt-34050.C index cb19b3914c0..fba340abfd5 100644 --- a/gcc/testsuite/g++.dg/cpp0x/vt-34050.C +++ b/gcc/testsuite/g++.dg/cpp0x/vt-34050.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } struct A {}; template<typename... T> struct B : T... diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-34051-2.C b/gcc/testsuite/g++.dg/cpp0x/vt-34051-2.C index 2c7bb50f081..02373f89027 100644 --- a/gcc/testsuite/g++.dg/cpp0x/vt-34051-2.C +++ b/gcc/testsuite/g++.dg/cpp0x/vt-34051-2.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<typename... T> struct A { int i __attribute__((aligned(__alignof(T)))); // { dg-error "parameter packs|T" } diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-34051.C b/gcc/testsuite/g++.dg/cpp0x/vt-34051.C index 88ae5670323..7d37bf27181 100644 --- a/gcc/testsuite/g++.dg/cpp0x/vt-34051.C +++ b/gcc/testsuite/g++.dg/cpp0x/vt-34051.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } struct A { operator int(); diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-34052.C b/gcc/testsuite/g++.dg/cpp0x/vt-34052.C index 15310cfe74d..a2e44b6cde7 100644 --- a/gcc/testsuite/g++.dg/cpp0x/vt-34052.C +++ b/gcc/testsuite/g++.dg/cpp0x/vt-34052.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<typename... T, typename = T> struct A {}; // { dg-error "must be at the end" } diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-34055.C b/gcc/testsuite/g++.dg/cpp0x/vt-34055.C index c50778430e0..3caee091862 100644 --- a/gcc/testsuite/g++.dg/cpp0x/vt-34055.C +++ b/gcc/testsuite/g++.dg/cpp0x/vt-34055.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // PR c++/34055 template<typename...> struct A; diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-34102.C b/gcc/testsuite/g++.dg/cpp0x/vt-34102.C index 00f0b4f4aac..90ef7728058 100644 --- a/gcc/testsuite/g++.dg/cpp0x/vt-34102.C +++ b/gcc/testsuite/g++.dg/cpp0x/vt-34102.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // PR c++/34102 struct A {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-34103.C b/gcc/testsuite/g++.dg/cpp0x/vt-34103.C index 3bbbb46a012..e1a8574d27e 100644 --- a/gcc/testsuite/g++.dg/cpp0x/vt-34103.C +++ b/gcc/testsuite/g++.dg/cpp0x/vt-34103.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // PR c++/34103 template<typename> struct A {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-34219-2.C b/gcc/testsuite/g++.dg/cpp0x/vt-34219-2.C index 193bc0c6cf9..4f145ca2721 100644 --- a/gcc/testsuite/g++.dg/cpp0x/vt-34219-2.C +++ b/gcc/testsuite/g++.dg/cpp0x/vt-34219-2.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<template<typename... T> class Comp, typename... T> void f( T... Value) { static_assert( Comp<T>::value > 0, "" ); // { dg-error "parameter packs|T" } diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-34219.C b/gcc/testsuite/g++.dg/cpp0x/vt-34219.C index fb3584ea88d..0cf603e8872 100644 --- a/gcc/testsuite/g++.dg/cpp0x/vt-34219.C +++ b/gcc/testsuite/g++.dg/cpp0x/vt-34219.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<typename T, T a, T... Params> struct max { diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-34314.C b/gcc/testsuite/g++.dg/cpp0x/vt-34314.C index 4a935b367d6..6f3d0159392 100644 --- a/gcc/testsuite/g++.dg/cpp0x/vt-34314.C +++ b/gcc/testsuite/g++.dg/cpp0x/vt-34314.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<typename Fun, typename... Args> // { dg-error "template parameter" } struct call; diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-34399.C b/gcc/testsuite/g++.dg/cpp0x/vt-34399.C index 542fae586ca..11e7391372d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/vt-34399.C +++ b/gcc/testsuite/g++.dg/cpp0x/vt-34399.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<int...> struct A { void foo(); diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-34606.C b/gcc/testsuite/g++.dg/cpp0x/vt-34606.C index 46794335442..679bb9a7a24 100644 --- a/gcc/testsuite/g++.dg/cpp0x/vt-34606.C +++ b/gcc/testsuite/g++.dg/cpp0x/vt-34606.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<typename...> struct A; template<typename T, typename... U> struct A<T, U> // { dg-error "parameter packs|U" } diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-34751.C b/gcc/testsuite/g++.dg/cpp0x/vt-34751.C index e3ca39e798d..f500396fc94 100644 --- a/gcc/testsuite/g++.dg/cpp0x/vt-34751.C +++ b/gcc/testsuite/g++.dg/cpp0x/vt-34751.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // PR c++/34751 struct A {}; diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-34753.C b/gcc/testsuite/g++.dg/cpp0x/vt-34753.C index 15eaebebc88..d435138d1c3 100644 --- a/gcc/testsuite/g++.dg/cpp0x/vt-34753.C +++ b/gcc/testsuite/g++.dg/cpp0x/vt-34753.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<typename... T> struct A { template<T> struct B {}; // { dg-error "not expanded|T" } diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-34754.C b/gcc/testsuite/g++.dg/cpp0x/vt-34754.C index 97c0065328f..ae0c4ec71da 100644 --- a/gcc/testsuite/g++.dg/cpp0x/vt-34754.C +++ b/gcc/testsuite/g++.dg/cpp0x/vt-34754.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<template<int> class... T> struct A { void foo(T<0>); // { dg-error "not expanded|T" } diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-34755.C b/gcc/testsuite/g++.dg/cpp0x/vt-34755.C index 9d5a3d1ca4d..c642b776cb7 100644 --- a/gcc/testsuite/g++.dg/cpp0x/vt-34755.C +++ b/gcc/testsuite/g++.dg/cpp0x/vt-34755.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<typename> struct A {}; template<template<typename> class... T> void foo(T<int>) {} // { dg-error "not expanded|T" } diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-34919.C b/gcc/testsuite/g++.dg/cpp0x/vt-34919.C index 829579918e1..94de312bf9c 100644 --- a/gcc/testsuite/g++.dg/cpp0x/vt-34919.C +++ b/gcc/testsuite/g++.dg/cpp0x/vt-34919.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<int... N> struct A { static void foo() diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-34961.C b/gcc/testsuite/g++.dg/cpp0x/vt-34961.C index 3a872146e25..368a4530951 100644 --- a/gcc/testsuite/g++.dg/cpp0x/vt-34961.C +++ b/gcc/testsuite/g++.dg/cpp0x/vt-34961.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<typename... T> struct A { static const int i __attribute__((aligned(__alignof(T)))) = 0; // { dg-error "not expanded|T" } diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-35023.C b/gcc/testsuite/g++.dg/cpp0x/vt-35023.C index 9db20503e7e..4646b7a74b5 100644 --- a/gcc/testsuite/g++.dg/cpp0x/vt-35023.C +++ b/gcc/testsuite/g++.dg/cpp0x/vt-35023.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<typename... T> int foo() { T t; // { dg-error "parameter packs|T" } diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-35024.C b/gcc/testsuite/g++.dg/cpp0x/vt-35024.C index 77f0b66bdc0..3e2654f1e36 100644 --- a/gcc/testsuite/g++.dg/cpp0x/vt-35024.C +++ b/gcc/testsuite/g++.dg/cpp0x/vt-35024.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<typename... T> int foo() { typename T::X x; // { dg-error "parameter packs|T" } diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-35026.C b/gcc/testsuite/g++.dg/cpp0x/vt-35026.C index 643a416c578..491537df977 100644 --- a/gcc/testsuite/g++.dg/cpp0x/vt-35026.C +++ b/gcc/testsuite/g++.dg/cpp0x/vt-35026.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<typename... T> struct A { T* x[1]; // { dg-error "parameter packs|T" } diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-35147.C b/gcc/testsuite/g++.dg/cpp0x/vt-35147.C index fecb36ec8c9..3b2250baeef 100644 --- a/gcc/testsuite/g++.dg/cpp0x/vt-35147.C +++ b/gcc/testsuite/g++.dg/cpp0x/vt-35147.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<typename _Tp> _Tp&& forward(_Tp&& __t) { return __t; } // { dg-message "note" } diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-35242.C b/gcc/testsuite/g++.dg/cpp0x/vt-35242.C index 9cc859b875e..2df4bae4922 100644 --- a/gcc/testsuite/g++.dg/cpp0x/vt-35242.C +++ b/gcc/testsuite/g++.dg/cpp0x/vt-35242.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } struct A { template<typename... T> struct B; diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-35243.C b/gcc/testsuite/g++.dg/cpp0x/vt-35243.C index 4b555744269..a425528b233 100644 --- a/gcc/testsuite/g++.dg/cpp0x/vt-35243.C +++ b/gcc/testsuite/g++.dg/cpp0x/vt-35243.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } struct A {}; template<typename... T> struct B : T... diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-35331.C b/gcc/testsuite/g++.dg/cpp0x/vt-35331.C index 0add9819bd0..06fda619102 100644 --- a/gcc/testsuite/g++.dg/cpp0x/vt-35331.C +++ b/gcc/testsuite/g++.dg/cpp0x/vt-35331.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<typename...> struct A; template<typename...T> struct A<T*> // { dg-error "not expanded|T" } diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-37737-1.C b/gcc/testsuite/g++.dg/cpp0x/vt-37737-1.C index de11b1651b4..8745dde372e 100644 --- a/gcc/testsuite/g++.dg/cpp0x/vt-37737-1.C +++ b/gcc/testsuite/g++.dg/cpp0x/vt-37737-1.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } // { dg-prune-output "note" } void f() { } diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-37737-2.C b/gcc/testsuite/g++.dg/cpp0x/vt-37737-2.C index 5514259ec3f..178db4f7c19 100644 --- a/gcc/testsuite/g++.dg/cpp0x/vt-37737-2.C +++ b/gcc/testsuite/g++.dg/cpp0x/vt-37737-2.C @@ -1,4 +1,4 @@ -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template<class U, class... T> void f() // { dg-message "note" } diff --git a/gcc/testsuite/g++.dg/cpp0x/vt-40092.C b/gcc/testsuite/g++.dg/cpp0x/vt-40092.C index ecb69806130..f3b53d00229 100644 --- a/gcc/testsuite/g++.dg/cpp0x/vt-40092.C +++ b/gcc/testsuite/g++.dg/cpp0x/vt-40092.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-std=c++0x" } +// { dg-options "-std=c++11" } template <typename... Types> struct package {}; diff --git a/gcc/testsuite/g++.dg/cpp1y/attr-deprecated-neg.C b/gcc/testsuite/g++.dg/cpp1y/attr-deprecated-neg.C new file mode 100644 index 00000000000..b2f0e1238d7 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/attr-deprecated-neg.C @@ -0,0 +1,59 @@ +// { dg-do compile } +// { dg-options -std=c++11 } + +class [[deprecated]] A // { dg-warning "attribute directive ignored" } +{ +}; + +[[deprecated]] +int +foo(int n) // { dg-warning "attribute directive ignored" } +{ + return 42 + n; +} + +class [[deprecated("B has been superceded by C")]] B // { dg-warning "attribute directive ignored" } +{ +}; + +[[deprecated("bar is unsafe; use foobar instead")]] +int +bar(int n) // { dg-warning "attribute directive ignored" } +{ + return 42 + n - 1; +} + +#if __cplusplus > 201103L + +// Deprecate C for C++14 onwards. +class [[deprecated]] C; + +// Deprecate foobar for C++14 onwards. +[[deprecated]] +int +foobar(int n); + +#endif + +class C +{ +}; + +int +foobar(int n) +{ + return 43 + n - 1; +} + +int +main() +{ + A aaa; + int n = foo(12); + + B bbb; + int m = bar(666); + + C ccc; + int l = foobar(8); +} diff --git a/gcc/testsuite/g++.dg/cpp1y/attr-deprecated.C b/gcc/testsuite/g++.dg/cpp1y/attr-deprecated.C new file mode 100644 index 00000000000..8cd09c7bb7c --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/attr-deprecated.C @@ -0,0 +1,59 @@ +// { dg-do compile } +// { dg-options -std=c++1y } + +class [[deprecated]] A +{ +}; + +[[deprecated]] +int +foo(int n) +{ + return 42 + n; +} + +class [[deprecated("B has been superceded by C")]] B +{ +}; + +[[deprecated("bar is unsafe; use foobar instead")]] +int +bar(int n) +{ + return 42 + n - 1; +} + +#if __cplusplus > 201103L + +// Deprecate C for C++14 onwards. +class [[deprecated]] C; + +// Deprecate foobar for C++14 onwards. +[[deprecated]] +int +foobar(int n); + +#endif + +class C +{ +}; + +int +foobar(int n) +{ + return 43 + n - 1; +} + +int +main() +{ + A aaa; // { dg-warning "is deprecated" } + int n = foo(12); // { dg-warning "is deprecated" } + + B bbb; // { dg-warning "is deprecated" "B has been superceded by C" } + int m = bar(666); // { dg-warning "is deprecated" "bar is unsafe; use foobar instead" } + + C ccc; // { dg-warning "is deprecated" } + int l = foobar(8); // { dg-warning "is deprecated" } +} diff --git a/gcc/testsuite/g++.dg/cpp1y/digit-sep-cxx11-neg.C b/gcc/testsuite/g++.dg/cpp1y/digit-sep-cxx11-neg.C new file mode 100644 index 00000000000..a078fa2a33f --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/digit-sep-cxx11-neg.C @@ -0,0 +1,12 @@ +// { dg-options -std=c++11 } + +#define assert(E) if(!(E))__builtin_abort(); + +#define m(x) 0 + +int +main() +{ + int i = m(1'2)+(3'4); + assert(i == 0); +} diff --git a/gcc/testsuite/g++.dg/cpp1y/digit-sep-neg.C b/gcc/testsuite/g++.dg/cpp1y/digit-sep-neg.C new file mode 100644 index 00000000000..371e675577c --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/digit-sep-neg.C @@ -0,0 +1,26 @@ +// { dg-options -std=c++1y } + +int +main() +{ + int i = 0; + i = 1048''576; // { dg-error "adjacent digit separators" } + i = 0X'100000; // { dg-error "digit separator after base indicator" } + i = 0x'100000; // { dg-error "digit separator after base indicator" } + 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 "digit separator outside digit sequence" } + unsigned u = 0b0001'0000'0000'0000'0000'0000'U; // { dg-error "digit separator outside digit sequence" } + + double d = 0.0; + d = 1'.602'176'565e-19; // { dg-error "digit separator adjacent to decimal point" } + 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 "digit separator adjacent to exponent" } + 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 "digit separator outside digit sequence" } + float f = 1.602'176'565e-19'F; // { dg-error "digit separator outside digit sequence" } +} diff --git a/gcc/testsuite/g++.dg/cpp1y/digit-sep.C b/gcc/testsuite/g++.dg/cpp1y/digit-sep.C new file mode 100644 index 00000000000..69b1c691014 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/digit-sep.C @@ -0,0 +1,22 @@ +// { dg-options -std=c++1y } + +#define assert(E) if(!(E))__builtin_abort(); + +#define m(x) 0 + +int +main() +{ + assert(1048576 == 1'048'576); + assert(1048576 == 0X100000); + assert(1048576 == 0x10'0000); + assert(1048576 == 0'004'000'000); + assert(1048576 == 0B100000000000000000000); + assert(1048576 == 0b0001'0000'0000'0000'0000'0000); + + assert(1.602'176'565e-19 == 1.602176565e-19); + assert(1.602'176'565e-1'9 == 1.602176565e-19); + + int i = m(1'2)+(3'4); + assert(i == 34); +} diff --git a/gcc/testsuite/g++.dg/cpp1y/pr58708.C b/gcc/testsuite/g++.dg/cpp1y/pr58708.C new file mode 100644 index 00000000000..a9c19ebb6c3 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/pr58708.C @@ -0,0 +1,60 @@ +// { dg-options -std=c++1y } +// { dg-do run } + +template<typename, typename> + struct is_same + { + static constexpr bool value = false; + }; + +template<typename _Tp> + struct is_same<_Tp, _Tp> + { + static constexpr bool value = true; + }; + +template<typename CharT, CharT... Str> + struct Foo + { + using char_type = CharT; + char_type chars[sizeof...(Str)]{Str...}; + }; + +template<typename CharT, CharT... Str> + Foo<CharT, Str...> + operator""_foo() + { + return Foo<CharT, Str...>(); + } + +int +main() +{ + auto fooU = U"\x10000\x10001\x10002"_foo; + if (is_same<decltype(fooU)::char_type, char32_t>::value != true) __builtin_abort(); + if (sizeof(fooU.chars)/sizeof(char32_t) != 3) __builtin_abort(); + if (fooU.chars[0] != 65536) __builtin_abort(); + if (fooU.chars[1] != 65537) __builtin_abort(); + if (fooU.chars[2] != 65538) __builtin_abort(); + + auto foo = "\x61\x62\x63"_foo; + if (is_same<decltype(foo)::char_type, char>::value != true) __builtin_abort(); + if (sizeof(foo.chars)/sizeof(char) != 3) __builtin_abort(); + if (foo.chars[0] != 97) __builtin_abort(); + if (foo.chars[1] != 98) __builtin_abort(); + if (foo.chars[2] != 99) __builtin_abort(); + + auto wfoo = L"\x01020304\x05060708"_foo; + if (is_same<decltype(wfoo)::char_type, wchar_t>::value != true) __builtin_abort(); + if (sizeof(wfoo.chars)/sizeof(wchar_t) != 2) __builtin_abort(); + if (wfoo.chars[0] != 16909060) __builtin_abort(); + if (wfoo.chars[1] != 84281096) __builtin_abort(); + + auto foou = u"\x0102\x0304\x0506\x0708"_foo; + if (is_same<decltype(foou)::char_type, char16_t>::value != true) __builtin_abort(); + if (sizeof(foou.chars)/sizeof(char16_t) != 4) __builtin_abort(); + if (foou.chars[0] != 258) __builtin_abort(); + if (foou.chars[1] != 772) __builtin_abort(); + if (foou.chars[2] != 1286) __builtin_abort(); + if (foou.chars[3] != 1800) __builtin_abort(); +} diff --git a/gcc/testsuite/g++.dg/diagnostic/pr58979.C b/gcc/testsuite/g++.dg/diagnostic/pr58979.C new file mode 100644 index 00000000000..6be3f143693 --- /dev/null +++ b/gcc/testsuite/g++.dg/diagnostic/pr58979.C @@ -0,0 +1,4 @@ +// PR c++/58979 +// { dg-do compile } + +int i = 0->*0; // { dg-error "invalid type argument of" } diff --git a/gcc/testsuite/g++.dg/ext/anon-struct4.C b/gcc/testsuite/g++.dg/ext/anon-struct4.C index 5d0bf71ae63..9c8e887dacc 100644 --- a/gcc/testsuite/g++.dg/ext/anon-struct4.C +++ b/gcc/testsuite/g++.dg/ext/anon-struct4.C @@ -1,5 +1,5 @@ // PR c++/14401 -struct { struct { int& i ; } bar ; } foo ; // { dg-error "uninitialized" "uninit" } +struct { struct { int& i ; } bar ; } foo ; // { dg-error "deleted|uninitialized" "uninit" } // { dg-warning "anonymous" "anon" { target c++98 } 3 } -// { dg-message "should be initialized" "ref-uninit" { target *-*-* } 3 } +// { dg-message "should be initialized" "ref-uninit" { target c++98 } 3 } diff --git a/gcc/testsuite/g++.dg/ext/pr58834.C b/gcc/testsuite/g++.dg/ext/pr58834.C new file mode 100644 index 00000000000..02930333170 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/pr58834.C @@ -0,0 +1,5 @@ +template<typename> void foo() +{ + int i __attribute__((vector_size(2*sizeof(int)))); + (void) __builtin_shuffle(i, i); +} diff --git a/gcc/testsuite/g++.dg/gomp/declare-simd-1.C b/gcc/testsuite/g++.dg/gomp/declare-simd-1.C index 1fd88b7efab..e9be161948e 100644 --- a/gcc/testsuite/g++.dg/gomp/declare-simd-1.C +++ b/gcc/testsuite/g++.dg/gomp/declare-simd-1.C @@ -205,7 +205,7 @@ f30 (int x) template <int N> struct C { - #pragma omp declare simd simdlen (N) aligned (a : N * sizeof (int)) linear (c : N) notinbranch + #pragma omp declare simd simdlen (N) aligned (b : N * sizeof (int)) linear (c : N) notinbranch int f32 (int a, int *b, int c); }; diff --git a/gcc/testsuite/g++.dg/gomp/declare-simd-2.C b/gcc/testsuite/g++.dg/gomp/declare-simd-2.C index f64004fb012..a6151015bae 100644 --- a/gcc/testsuite/g++.dg/gomp/declare-simd-2.C +++ b/gcc/testsuite/g++.dg/gomp/declare-simd-2.C @@ -64,4 +64,35 @@ struct D int e; }; +#pragma omp declare simd aligned (a, b, c, d) +int fn13 (int *a, int b[64], int *&c, int (&d)[64]); + +#pragma omp declare simd aligned (a) // { dg-error "neither a pointer nor an array" } +int fn14 (int a); + +#pragma omp declare simd aligned (b) // { dg-error "neither a pointer nor an array" } +int fn14 (int &b); + +#pragma omp declare simd aligned (c) // { dg-error "neither a pointer nor an array" } +int fn14 (float c); + +#pragma omp declare simd aligned (d) // { dg-error "neither a pointer nor an array" } +int fn14 (double &d); + +#pragma omp declare simd aligned (e) // { dg-error "neither a pointer nor an array" } +int fn14 (D e); + +#pragma omp declare simd linear(a:7) uniform(a) // { dg-error "appears more than once" } +int f15 (int a); +#pragma omp declare simd linear(a) linear(a) // { dg-error "appears more than once" } +int f16 (int a); +#pragma omp declare simd linear(a) linear(a:7) // { dg-error "appears more than once" } +int f17 (int a); +#pragma omp declare simd linear(a:6) linear(a:6)// { dg-error "appears more than once" } +int f18 (int a); +#pragma omp declare simd uniform(a) uniform(a) // { dg-error "appears more than once" } +int f19 (int a); +#pragma omp declare simd uniform(a) aligned (a: 32) +int f20 (int *a); + // { dg-error "has no member" "" { target *-*-* } 61 } diff --git a/gcc/testsuite/g++.dg/gomp/simd-1.C b/gcc/testsuite/g++.dg/gomp/simd-1.C new file mode 100644 index 00000000000..c9c2e73bb40 --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/simd-1.C @@ -0,0 +1,31 @@ +// { dg-do compile } +// { dg-options "-fopenmp" } + +extern int a[1024]; +int (&b)[1024] = a; + +struct S { int s; } s, &t = s; + +void +f1 (int &x, float &f, int *&p) +{ + int i; + #pragma omp simd aligned(x : 32) // { dg-error "neither a pointer nor an array" } + for (i = 0; i < 1024; i++) + a[i]++; + #pragma omp simd aligned(f) // { dg-error "neither a pointer nor an array" } + for (i = 0; i < 1024; i++) + a[i]++; + #pragma omp simd aligned(t : 16) // { dg-error "neither a pointer nor an array" } + for (i = 0; i < 1024; i++) + a[i]++; + #pragma omp simd aligned(a : 8) + for (i = 0; i < 1024; i++) + a[i]++; + #pragma omp simd aligned(b : 8) + for (i = 0; i < 1024; i++) + b[i]++; + #pragma omp simd aligned(p : 8) + for (i = 0; i < 1024; i++) + a[i]++; +} diff --git a/gcc/testsuite/g++.dg/init/ctor8.C b/gcc/testsuite/g++.dg/init/ctor8.C index 3491f6a1d2c..7eb72eb833f 100644 --- a/gcc/testsuite/g++.dg/init/ctor8.C +++ b/gcc/testsuite/g++.dg/init/ctor8.C @@ -1,9 +1,10 @@ // PR c++/29039 -typedef struct S { +typedef struct S { // { dg-error "reference" "" { target c++11 } } int &r; }; // { dg-warning "'typedef' was ignored" } + S f () { - return S (); // { dg-error "reference" } + return S (); // { dg-error "reference|deleted" } } diff --git a/gcc/testsuite/g++.dg/init/pr25811.C b/gcc/testsuite/g++.dg/init/pr25811.C index c906a9bbd35..e8945dafe93 100644 --- a/gcc/testsuite/g++.dg/init/pr25811.C +++ b/gcc/testsuite/g++.dg/init/pr25811.C @@ -1,51 +1,51 @@ // PR c++/25811 // { dg-do compile } -struct A1 +struct A1 // { dg-error "uninitialized" "" { target c++11 } } { - int const j; // { dg-message "should be initialized" } + int const j; // { dg-message "should be initialized" "" { target c++98 } } }; -struct A2 +struct A2 // { dg-error "uninitialized" "" { target c++11 } } { - int const volatile i; // { dg-message "should be initialized" } + int const volatile i; // { dg-message "should be initialized" "" { target c++98 } } }; -struct A3 +struct A3 // { dg-error "uninitialized" "" { target c++11 } } { - int& ref; // { dg-message "should be initialized" } + int& ref; // { dg-message "should be initialized" "" { target c++98 } } }; -struct A4 +struct A4 // { dg-error "uninitialized" "" { target c++11 } } { - int const& ref; // { dg-message "should be initialized" } + int const& ref; // { dg-message "should be initialized" "" { target c++98 } } }; -struct A5 +struct A5 // { dg-error "uninitialized" "" { target c++11 } } { - int& ref; // { dg-message "should be initialized" } - int const i; // { dg-message "should be initialized" } + int& ref; // { dg-message "should be initialized" "" { target c++98 } } + int const i; // { dg-message "should be initialized" "" { target c++98 } } }; -template <class T> struct S1 +template <class T> struct S1 // { dg-error "uninitialized" "" { target c++11 } } { - T const i; // { dg-message "should be initialized" } + T const i; // { dg-message "should be initialized" "" { target c++98 } } }; -template <class T> struct S2 +template <class T> struct S2 // { dg-error "uninitialized" "" { target c++11 } } { - T const volatile i; // { dg-message "should be initialized" } + T const volatile i; // { dg-message "should be initialized" "" { target c++98 } } }; -template <class T> struct S3 +template <class T> struct S3 // { dg-error "uninitialized" "" { target c++11 } } { - T& ref; // { dg-message "should be initialized" } + T& ref; // { dg-message "should be initialized" "" { target c++98 } } }; -template <class T> struct S4 +template <class T> struct S4 // { dg-error "uninitialized" "" { target c++11 } } { - T const i; // { dg-message "should be initialized" } - T& ref; // { dg-message "should be initialized" } + T const i; // { dg-message "should be initialized" "" { target c++98 } } + T& ref; // { dg-message "should be initialized" "" { target c++98 } } }; struct X @@ -55,44 +55,44 @@ struct X int const& r; }; -struct Y11 +struct Y11 // { dg-error "uninitialized" "" { target c++11 } } { - int const i; // { dg-message "should be initialized" } + int const i; // { dg-message "should be initialized" "" { target c++98 } } }; -struct Y1 +struct Y1 // { dg-error "deleted" "" { target c++11 } } { Y11 a[1]; }; -struct Y22 +struct Y22 // { dg-error "uninitialized" "" { target c++11 } } { - int& ref; // { dg-message "should be initialized" } + int& ref; // { dg-message "should be initialized" "" { target c++98 } } }; -struct Y2 +struct Y2 // { dg-error "deleted" "" { target c++11 } } { Y22 a[1]; }; -struct Z1 +struct Z1 // { dg-error "uninitialized" "" { target c++11 } } { - int const i; // { dg-message "should be initialized" } + int const i; // { dg-message "should be initialized" "" { target c++98 } } }; -struct Z2 +struct Z2 // { dg-error "uninitialized" "" { target c++11 } } { - int& ref; // { dg-message "should be initialized" } + int& ref; // { dg-message "should be initialized" "" { target c++98 } } }; -struct Z3 +struct Z3 // { dg-error "uninitialized" "" { target c++11 } } { - int const i; // { dg-message "should be initialized" } + int const i; // { dg-message "should be initialized" "" { target c++98 } } }; -struct Z4 +struct Z4 // { dg-error "uninitialized" "" { target c++11 } } { - int& ref; // { dg-message "should be initialized" } + int& ref; // { dg-message "should be initialized" "" { target c++98 } } }; struct Z5 @@ -100,7 +100,7 @@ struct Z5 int i; }; -struct Z +struct Z // { dg-error "deleted" "" { target c++11 } } { Z1 z1; Z2 z2; @@ -109,54 +109,54 @@ struct Z Z5 z5; }; -union U +union U // { dg-error "uninitialized" "" { target c++11 } } { - int const i; // { dg-message "should be initialized" } + int const i; // { dg-message "should be initialized" "" { target c++98 } } }; void f1 () { - new A1; // { dg-error "uninitialized const member" } + new A1; // { dg-error "deleted|uninitialized const member" } } void f2 () { - new A2; // { dg-error "uninitialized const member" } + new A2; // { dg-error "deleted|uninitialized const member" } } void f3 () { - new A3; // { dg-error "uninitialized reference member" } + new A3; // { dg-error "deleted|uninitialized reference member" } } void f4 () { - new A4; // { dg-error "uninitialized reference member" } + new A4; // { dg-error "deleted|uninitialized reference member" } } void f5 () { - new A5; // { dg-error "uninitialized reference member|uninitialized const member" } + new A5; // { dg-error "deleted|uninitialized reference member|uninitialized const member" } } void f6 () { - new S1<int>; // { dg-error "uninitialized const member" } + new S1<int>; // { dg-error "deleted|uninitialized const member" } } void f7 () { - new S2<int>; // { dg-error "uninitialized const member" } + new S2<int>; // { dg-error "deleted|uninitialized const member" } } void f8 () { - new S3<int>; // { dg-error "uninitialized reference member" } + new S3<int>; // { dg-error "deleted|uninitialized reference member" } } void f9 () { - new S4<int>; // { dg-error "uninitialized reference member|uninitialized const member" } + new S4<int>; // { dg-error "deleted|uninitialized reference member|uninitialized const member" } } void f10 () @@ -166,30 +166,30 @@ void f10 () void f11 () { - new A1[1]; // { dg-error "uninitialized const member" } + new A1[1]; // { dg-error "deleted|uninitialized const member" } } void f12 () { - new A3[1]; // { dg-error "uninitialized reference member" } + new A3[1]; // { dg-error "deleted|uninitialized reference member" } } void f13 () { - new Y1; // { dg-error "uninitialized const member" } + new Y1; // { dg-error "deleted|uninitialized const member" } } void f14 () { - new Y2; // { dg-error "uninitialized reference member" } + new Y2; // { dg-error "deleted|uninitialized reference member" } } void f15 () { - new Z; // { dg-error "uninitialized reference member|uninitialized const member" } + new Z; // { dg-error "deleted|uninitialized reference member|uninitialized const member" } } void f16 () { - new U; // { dg-error "uninitialized const member" } + new U; // { dg-error "deleted|uninitialized const member" } } diff --git a/gcc/testsuite/g++.dg/init/pr29043.C b/gcc/testsuite/g++.dg/init/pr29043.C index 6ed31b5d6b5..f868dfb91a4 100644 --- a/gcc/testsuite/g++.dg/init/pr29043.C +++ b/gcc/testsuite/g++.dg/init/pr29043.C @@ -1,27 +1,27 @@ // PR c++/29043 // { dg-do compile } -struct S +struct S // { dg-error "uninitialized" "" { target c++11 } } { - int const i; // { dg-message "should be initialized" } + int const i; // { dg-message "should be initialized" "" { target c++98 } } }; class C { public: - C() {} // { dg-error "uninitialized const member" } + C() {} // { dg-error "uninitialized const member|deleted" } S s; }; -struct S2 +struct S2 // { dg-error "uninitialized" "" { target c++11 } } { - int& ref; // { dg-message "should be initialized" } + int& ref; // { dg-message "should be initialized" "" { target c++98 } } }; class C2 { public: - C2() {} // { dg-error "uninitialized reference member" } + C2() {} // { dg-error "uninitialized reference member|deleted" } S2 s; }; @@ -33,14 +33,14 @@ class C3 }; }; -struct S4 +struct S4 // { dg-error "uninitialized" "" { target c++11 } } { - int const i; // { dg-message "should be initialized" } + int const i; // { dg-message "should be initialized" "" { target c++98 } } }; struct C4 { - C4() {} // { dg-error "uninitialized const member" } + C4() {} // { dg-error "uninitialized const member|deleted" } S4 s4[ 1 ]; }; diff --git a/gcc/testsuite/g++.dg/init/pr43719.C b/gcc/testsuite/g++.dg/init/pr43719.C index d3487c94a09..13a82210bc6 100644 --- a/gcc/testsuite/g++.dg/init/pr43719.C +++ b/gcc/testsuite/g++.dg/init/pr43719.C @@ -1,51 +1,51 @@ // PR c++/43719 // { dg-do compile } -struct A1 +struct A1 // { dg-error "uninitialized" "" { target c++11 } } { - int const j; // { dg-message "should be initialized" } + int const j; // { dg-message "should be initialized" "" { target c++98 } } }; -struct A2 +struct A2 // { dg-error "uninitialized" "" { target c++11 } } { - int const volatile i; // { dg-message "should be initialized" } + int const volatile i; // { dg-message "should be initialized" "" { target c++98 } } }; -struct A3 +struct A3 // { dg-error "uninitialized" "" { target c++11 } } { - int& ref; // { dg-message "should be initialized" } + int& ref; // { dg-message "should be initialized" "" { target c++98 } } }; -struct A4 +struct A4 // { dg-error "uninitialized" "" { target c++11 } } { - int const& ref; // { dg-message "should be initialized" } + int const& ref; // { dg-message "should be initialized" "" { target c++98 } } }; -struct A5 +struct A5 // { dg-error "uninitialized" "" { target c++11 } } { - int& ref; // { dg-message "should be initialized" } - int const i; // { dg-message "should be initialized" } + int& ref; // { dg-message "should be initialized" "" { target c++98 } } + int const i; // { dg-message "should be initialized" "" { target c++98 } } }; -template <class T> struct S1 +template <class T> struct S1 // { dg-error "uninitialized" "" { target c++11 } } { - T const i; // { dg-message "should be initialized" } + T const i; // { dg-message "should be initialized" "" { target c++98 } } }; -template <class T> struct S2 +template <class T> struct S2 // { dg-error "uninitialized" "" { target c++11 } } { - T const volatile i; // { dg-message "should be initialized" } + T const volatile i; // { dg-message "should be initialized" "" { target c++98 } } }; -template <class T> struct S3 +template <class T> struct S3 // { dg-error "uninitialized" "" { target c++11 } } { - T& ref; // { dg-message "should be initialized" } + T& ref; // { dg-message "should be initialized" "" { target c++98 } } }; -template <class T> struct S4 +template <class T> struct S4 // { dg-error "uninitialized" "" { target c++11 } } { - T const i; // { dg-message "should be initialized" } - T& ref; // { dg-message "should be initialized" } + T const i; // { dg-message "should be initialized" "" { target c++98 } } + T& ref; // { dg-message "should be initialized" "" { target c++98 } } }; struct X @@ -55,44 +55,44 @@ struct X int const& r; }; -struct Y11 +struct Y11 // { dg-error "uninitialized" "" { target c++11 } } { - int const i; // { dg-message "should be initialized" } + int const i; // { dg-message "should be initialized" "" { target c++98 } } }; -struct Y1 +struct Y1 // { dg-error "deleted" "" { target c++11 } } { Y11 a[1]; }; -struct Y22 +struct Y22 // { dg-error "uninitialized" "" { target c++11 } } { - int& ref; // { dg-message "should be initialized" } + int& ref; // { dg-message "should be initialized" "" { target c++98 } } }; -struct Y2 +struct Y2 // { dg-error "deleted" "" { target c++11 } } { Y22 a[1]; }; -struct Z1 +struct Z1 // { dg-error "uninitialized" "" { target c++11 } } { - int const i; // { dg-message "should be initialized" } + int const i; // { dg-message "should be initialized" "" { target c++98 } } }; -struct Z2 +struct Z2 // { dg-error "uninitialized" "" { target c++11 } } { - int& ref; // { dg-message "should be initialized" } + int& ref; // { dg-message "should be initialized" "" { target c++98 } } }; -struct Z3 +struct Z3 // { dg-error "uninitialized" "" { target c++11 } } { - int const i; // { dg-message "should be initialized" } + int const i; // { dg-message "should be initialized" "" { target c++98 } } }; -struct Z4 +struct Z4 // { dg-error "uninitialized" "" { target c++11 } } { - int& ref; // { dg-message "should be initialized" } + int& ref; // { dg-message "should be initialized" "" { target c++98 } } }; struct Z5 @@ -100,7 +100,7 @@ struct Z5 int i; }; -struct Z +struct Z // { dg-error "deleted" "" { target c++11 } } { Z1 z1; Z2 z2; @@ -109,55 +109,55 @@ struct Z Z5 z5; }; -union U +union U // { dg-error "uninitialized" "" { target c++11 } } { - int const i; // { dg-message "should be initialized" } + int const i; // { dg-message "should be initialized" "" { target c++98 } } }; void f1 () { - A1 a1; // { dg-error "uninitialized const member" } + A1 a1; // { dg-error "uninitialized const member|deleted" } } void f2 () { - A2 a2; // { dg-error "uninitialized const member" } + A2 a2; // { dg-error "uninitialized const member|deleted" } } void f3 () { - A3 a3; // { dg-error "uninitialized reference member" } + A3 a3; // { dg-error "uninitialized reference member|deleted" } } void f4 () { - A4 a4; // { dg-error "uninitialized reference member" } + A4 a4; // { dg-error "uninitialized reference member|deleted" } } void f5 () { - A5 a5; // { dg-error "uninitialized reference member|uninitialized const member" } + A5 a5; // { dg-error "uninitialized reference member|uninitialized const member|deleted" } } void f6 () { - S1<int> s; // { dg-error "uninitialized const member" } + S1<int> s; // { dg-error "uninitialized const member|deleted" } } void f7 () { - S2<int> s; // { dg-error "uninitialized const member" } + S2<int> s; // { dg-error "uninitialized const member|deleted" } } void f8 () { - S3<int> s; // { dg-error "uninitialized reference member" } + S3<int> s; // { dg-error "uninitialized reference member|deleted" } } void f9 () { - S4<int> s; // { dg-error "uninitialized reference member|uninitialized const member" } + S4<int> s; // { dg-error "uninitialized reference member|uninitialized const member|deleted" } } void f10 () @@ -167,31 +167,31 @@ void f10 () void f11 () { - A1 a[ 1 ]; // { dg-error "uninitialized const member" } + A1 a[ 1 ]; // { dg-error "uninitialized const member|deleted" } } void f12 () { - A3 a[ 1 ]; // { dg-error "uninitialized reference member" } + A3 a[ 1 ]; // { dg-error "uninitialized reference member|deleted" } } void f13 () { - Y1 y1; // { dg-error "uninitialized const member" } + Y1 y1; // { dg-error "uninitialized const member|deleted" } } void f14 () { - Y2 y2; // { dg-error "uninitialized reference member" } + Y2 y2; // { dg-error "uninitialized reference member|deleted" } } void f15 () { - Z z; // { dg-error "uninitialized reference member|uninitialized const member" } + Z z; // { dg-error "uninitialized reference member|uninitialized const member|deleted" } } void f16 () { - U u; // { dg-error "uninitialized const member" } + U u; // { dg-error "uninitialized const member|deleted" } } diff --git a/gcc/testsuite/g++.dg/init/pr44086.C b/gcc/testsuite/g++.dg/init/pr44086.C index e3304f4a27b..b4b0833dd69 100644 --- a/gcc/testsuite/g++.dg/init/pr44086.C +++ b/gcc/testsuite/g++.dg/init/pr44086.C @@ -1,15 +1,15 @@ // PR c++/44086 // { dg-do compile } -struct A +struct A // { dg-error "uninitialized" "" { target c++11 } } { - int const i : 2; // { dg-message "should be initialized" } + int const i : 2; // { dg-message "should be initialized" "" { target c++98 } } }; void f() { - A a; // { dg-error "uninitialized const" } - new A; // { dg-error "uninitialized const" } - A(); - new A(); + A a; // { dg-error "deleted|uninitialized const" } + new A; // { dg-error "deleted|uninitialized const" } + A(); // { dg-error "deleted" "" { target c++11 } } + new A(); // { dg-error "deleted" "" { target c++11 } } } diff --git a/gcc/testsuite/g++.dg/init/ref14.C b/gcc/testsuite/g++.dg/init/ref14.C index 212e6e95d7e..6ac42415b43 100644 --- a/gcc/testsuite/g++.dg/init/ref14.C +++ b/gcc/testsuite/g++.dg/init/ref14.C @@ -1,4 +1,6 @@ // PR c++/33459 +// { dg-prune-output "uninitialized" } +// { dg-prune-output "deleted" } union A { diff --git a/gcc/testsuite/g++.dg/init/uninitialized1.C b/gcc/testsuite/g++.dg/init/uninitialized1.C index 200c424305d..1e4f7ae84e2 100644 --- a/gcc/testsuite/g++.dg/init/uninitialized1.C +++ b/gcc/testsuite/g++.dg/init/uninitialized1.C @@ -1,12 +1,12 @@ // PR c++/58126 -struct A { +struct A { // { dg-error "uninitialized" "" { target c++11 } } const int value1; int& value2; }; -struct B : A { }; +struct B : A { }; // { dg-error "deleted" "" { target c++11 } } -A a; // { dg-error "uninitialized const member in 'struct A'|uninitialized reference member in 'struct A'" } +A a; // { dg-error "deleted|uninitialized const member in 'struct A'|uninitialized reference member in 'struct A'" } -B b; // { dg-error "uninitialized const member in base 'struct A' of 'struct B'|uninitialized reference member in base 'struct A' of 'struct B'" } +B b; // { dg-error "deleted|uninitialized const member in base 'struct A' of 'struct B'|uninitialized reference member in base 'struct A' of 'struct B'" } diff --git a/gcc/testsuite/g++.dg/lookup/name-clash10.C b/gcc/testsuite/g++.dg/lookup/name-clash10.C new file mode 100644 index 00000000000..0a089be257a --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/name-clash10.C @@ -0,0 +1,8 @@ +// PR c++/38313 + +struct foo { }; +struct bar { }; + +struct baz { + static foo (bar)(); +}; diff --git a/gcc/testsuite/g++.dg/opt/devirt3.C b/gcc/testsuite/g++.dg/opt/devirt3.C new file mode 100644 index 00000000000..673867361c1 --- /dev/null +++ b/gcc/testsuite/g++.dg/opt/devirt3.C @@ -0,0 +1,24 @@ +// { dg-do compile } +// { dg-options "-O2" } + +class ert_RefCounter { + protected: + int refCounterE; + virtual ~ert_RefCounter() {} +}; + +class ebs_Object : virtual public ert_RefCounter { +}; + +class dpr_App : public ebs_Object { + public: + virtual void run(); +}; + +class dpr_Job : public ebs_Object {}; + +void dpr_run(ebs_Object& objectA) { + ((dpr_App&)objectA).run(); + dpr_Job jobL; + dpr_run(jobL); +} diff --git a/gcc/testsuite/g++.dg/other/warning1.C b/gcc/testsuite/g++.dg/other/warning1.C index c65ae0ff6ef..a23d0ca6cba 100644 --- a/gcc/testsuite/g++.dg/other/warning1.C +++ b/gcc/testsuite/g++.dg/other/warning1.C @@ -7,8 +7,8 @@ extern "C" int printf(const char *, ...); struct S { - static const float inf = 1.0f / 0.0f; // { dg-warning "1.0|float|initializ" } - static const float nan = 0.0f / 0.0f; // { dg-warning "0.0|float|initializ" } + static const float inf = 1.0f / 0.0f; // { dg-error "1.0|float|initializ" } + static const float nan = 0.0f / 0.0f; // { dg-error "0.0|float|initializ" } }; int main() diff --git a/gcc/testsuite/g++.dg/parse/ivdep.C b/gcc/testsuite/g++.dg/parse/ivdep.C new file mode 100644 index 00000000000..23d51de9fe3 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/ivdep.C @@ -0,0 +1,11 @@ +/* { dg-do compile } */ + +/* PR other/33426 */ + +void foo(int n, int *a, int *b, int *c, int *d, int *e) { + int i, j; +#pragma GCC ivdep + for (i = 0; ; ++i) { /* { dg-error "missing loop condition in loop with 'GCC ivdep' pragma before ';' token" } */ + a[i] = b[i] + c[i]; + } +} diff --git a/gcc/testsuite/g++.dg/parse/pr29234.C b/gcc/testsuite/g++.dg/parse/pr29234.C new file mode 100644 index 00000000000..d2dc735f226 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/pr29234.C @@ -0,0 +1,16 @@ +// PR c++/29234 + +struct S { void operator()(); }; + +void foo () +{ + ( S()() ); +} + +struct C { void operator[](C); }; + +void bar () +{ + C x; + ( C()[x] ); +} diff --git a/gcc/testsuite/g++.dg/parse/pr52071.C b/gcc/testsuite/g++.dg/parse/pr52071.C new file mode 100644 index 00000000000..99456c0041a --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/pr52071.C @@ -0,0 +1,23 @@ +// PR c++/52071 + +struct C1 { + C1(int); +}; + +struct C2 { + C2(); + C2(C1); +}; + +void f() +{ + int x; + int y = 1; + C2 vc; + + vc = C2(C1(x = y)); + + vc = (C2(C1(x = y))); + + vc = (C2(C1((0, x = y)))); +} diff --git a/gcc/testsuite/g++.dg/parse/pr56037.C b/gcc/testsuite/g++.dg/parse/pr56037.C new file mode 100644 index 00000000000..10f145ae5ee --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/pr56037.C @@ -0,0 +1,12 @@ +// PR c++/56037 + +struct T +{ + T(int, int); +}; + +int main() +{ + static const int zero = 0; + (T(int(zero), int(zero))); +} diff --git a/gcc/testsuite/g++.dg/parse/pr58705.C b/gcc/testsuite/g++.dg/parse/pr58705.C new file mode 100644 index 00000000000..de2b396a5e4 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/pr58705.C @@ -0,0 +1,5 @@ +// PR c++/58705 +// { dg-do compile } +// { dg-options "-Wnarrowing" } + +_Complex float f = {{}}; diff --git a/gcc/testsuite/g++.dg/plugin/selfassign.c b/gcc/testsuite/g++.dg/plugin/selfassign.c index 7235089c7d3..5331f792cb2 100644 --- a/gcc/testsuite/g++.dg/plugin/selfassign.c +++ b/gcc/testsuite/g++.dg/plugin/selfassign.c @@ -7,6 +7,7 @@ #include "system.h" #include "coretypes.h" #include "tm.h" +#include "tree.h" #include "toplev.h" #include "basic-block.h" #include "gimple.h" diff --git a/gcc/testsuite/g++.dg/template/pr58878.C b/gcc/testsuite/g++.dg/template/pr58878.C new file mode 100644 index 00000000000..adad9fe5b07 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/pr58878.C @@ -0,0 +1,61 @@ +// PR c++/58878 + +// Template-members of non-template class +struct A +{ + template <typename t> // { dg-error "shadows" } + void f() + { + int t = 1; // { dg-error "declaration" } + } + + template <typename t> + void g(); +}; + +template <typename t> // { dg-error "shadows" } +void A::g() +{ + int t = 2; // { dg-error "declaration" } +} + +// (Non-template) Members of template class +template <typename t> // { dg-error "shadows" } +struct B +{ + void f() + { + int t = 3; // { dg-error "declaration" } + } + + void g(); +}; + +template <typename t> // { dg-error "shadows" } +void B<t>::g() +{ + int t = 4; // { dg-error "declaration" } +} + +// Template members of template class +template <typename t> // { dg-error "shadows" } +struct C +{ + template <typename s> // { dg-error "shadows" } + void f() + { + int t = 5; // { dg-error "declaration" } + int s = 6; // { dg-error "declaration" } + } + + template <typename s> + void g(); +}; + +template <typename t> // { dg-error "shadows" } +template <typename s> // { dg-error "shadows" } +void C<t>::g() +{ + int t = 7; // { dg-error "declaration" } + int s = 8; // { dg-error "declaration" } +} diff --git a/gcc/testsuite/g++.dg/torture/pr49309.C b/gcc/testsuite/g++.dg/torture/pr49309.C deleted file mode 100644 index f96967ddd34..00000000000 --- a/gcc/testsuite/g++.dg/torture/pr49309.C +++ /dev/null @@ -1,16 +0,0 @@ -// PR tree-optimization/49309 -// { dg-do compile } -// { dg-skip-if "" { *-*-* } { "-flto" } { "" } } -// { dg-options "-fpreprocessed -fmudflap" } - -struct A -{ - int i; - - A(); - A(const A&); -}; - -inline void foo(A a) { a = A(); } - -void bar() { foo(A()); } diff --git a/gcc/testsuite/g++.dg/torture/pr58369.C b/gcc/testsuite/g++.dg/torture/pr58369.C new file mode 100644 index 00000000000..9284e2ca768 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr58369.C @@ -0,0 +1,109 @@ +// { dg-do compile } +// Reduced from boost-1.54 + +int pow(int, int); +int sqrt(int); + +class PolicyA { }; + +template <class> +int max_value() { return 0x7fffffff; } + +template <class> +int min_value() { return 1; } + +void raise_denorm_error(); + +template <class T> +void raise_domain_error(int, int, const T &, const PolicyA &); + +template <class> +int check_overflow(long double p1) { + long double __trans_tmp_2 = __builtin_fabsl(p1); + if (__trans_tmp_2 > max_value<int>()) + return 1; + return 0; +} + +template <class> +int check_underflow(long double p1) { + if (p1 && (double)p1) + return 1; + return 0; +} + +template <class> +int check_denorm(long double p1) { + long double __trans_tmp_3 = __builtin_fabsl(p1); + if (__trans_tmp_3 < min_value<int>() && (double)p1) { + raise_denorm_error(); + return 1; + } + return 0; +} + +template <class, class> +double checked_narrowing_cast(long double p1) { + if (check_overflow<int>(p1)) + return 0; + if (check_underflow<int>(p1)) + return 0; + if (check_denorm<int>(p1)) + return 0; + return (double)p1; +} + +long double ellint_rf_imp(long double, long double, long double); + +template <typename T, typename Policy> +T ellint_rj_imp(T p1, T p2, T p3, T p4, Policy &p5) { + T value, tolerance, P, S3; + if (p4) + return 0; + if (p3 || p1) + raise_domain_error(0, 0, 0, p5); + tolerance = pow(0, 0); + if (p4) { + T q = -p4; + { + long double q6 = ellint_rj_imp((long double)p1, (long double)(double)p2, (long double)(double)p3, (long double)(int)0, p5); + value = checked_narrowing_cast<T, int>(q6); + } + { + long double q7 = ellint_rf_imp((long double)p1, (long double)(double)p2, (long double)(double)p3); + value -= checked_narrowing_cast<T, const int>(q7); + } + value += p1 * p3 + p4 * q; + return value; + } + do { + P = p4 / p1; + if (0 < tolerance) + break; + sqrt(p3); + } while (1); + S3 = P * p2 * 0; + value = S3 / p1; + return value; +} + +template <typename Policy> +void ellint_pi_imp4(double, double p3, Policy &p4) { + double x, y, z; + ellint_rj_imp(x, y, z, p3, p4); +} + +template <typename Policy> +double ellint_pi_imp5(double, double p3, double p4, Policy &p5) { + double x, y, z, p; + if (p3 > 0) + return 0; + ellint_rj_imp(x, y, z, p, p5); + ellint_pi_imp4((double)0, p4, p5); +} + +void boost_ellint_3f() { + PolicyA p4; + ellint_pi_imp5((double)0, (double)0, (double)0, p4); +} + diff --git a/gcc/testsuite/g++.dg/ubsan/cxx1y-vla.C b/gcc/testsuite/g++.dg/ubsan/cxx1y-vla.C new file mode 100644 index 00000000000..350db3f3473 --- /dev/null +++ b/gcc/testsuite/g++.dg/ubsan/cxx1y-vla.C @@ -0,0 +1,13 @@ +/* { dg-do run } */ +/* { dg-options "-fsanitize=vla-bound -w -std=c++1y" } */ +/* { dg-shouldfail "ubsan" } */ + +int +main (void) +{ + int y = -18; + int a[y]; + return 0; +} + +/* { dg-output "terminate called after throwing an instance" } */ diff --git a/gcc/testsuite/g++.dg/vect/pr33426-ivdep-2.cc b/gcc/testsuite/g++.dg/vect/pr33426-ivdep-2.cc new file mode 100644 index 00000000000..3d042301f96 --- /dev/null +++ b/gcc/testsuite/g++.dg/vect/pr33426-ivdep-2.cc @@ -0,0 +1,39 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target vect_float } */ +/* { dg-additional-options "-O3 -fopt-info-vec-optimized -fdump-tree-original -fdump-tree-gimple" } */ + +/* PR other/33426 */ +/* Testing whether #pragma ivdep is working. */ + +void foo(int n, int *a, int *b, int *c) { + int i; + i = 0; +#pragma GCC ivdep + while(i < n) + { + a[i] = b[i] + c[i]; + ++i; + } +} + +void bar(int n, int *a, int *b, int *c) { + int i; + i = 0; +#pragma GCC ivdep + do + { + a[i] = b[i] + c[i]; + ++i; + } + while(i < n); +} + +/* { dg-message "loop vectorized" "" { target *-*-* } 0 } */ +/* { dg-bogus " version" "" { target *-*-* } 0 } */ +/* { dg-bogus " alias" "" { target *-*-* } 0 } */ +/* { dg-final { cleanup-tree-dump "vect" } } */ + +/* { dg-final { scan-tree-dump-times "ANNOTATE_EXPR " 2 "original" } } */ +/* { dg-final { cleanup-tree-dump "original" } } */ +/* { dg-final { scan-tree-dump-times "ANNOTATE " 2 "gimple" } } */ +/* { dg-final { cleanup-tree-dump "gimple" } } */ diff --git a/gcc/testsuite/g++.dg/vect/pr33426-ivdep-3.cc b/gcc/testsuite/g++.dg/vect/pr33426-ivdep-3.cc new file mode 100644 index 00000000000..35de3b285e7 --- /dev/null +++ b/gcc/testsuite/g++.dg/vect/pr33426-ivdep-3.cc @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target vect_float } */ +/* { dg-additional-options "-std=c++11 -O3 -fopt-info-vec-optimized -fdump-tree-original -fdump-tree-gimple" } */ + +/* PR other/33426 */ +/* Testing whether #pragma ivdep is working. */ + +int ar[100]; + +void foo(int *a) { +#pragma GCC ivdep + for (auto &i : ar) { + i *= *a; + } +} + +/* { dg-message "loop vectorized" "" { target *-*-* } 0 } */ +/* { dg-bogus " version" "" { target *-*-* } 0 } */ +/* { dg-bogus " alias" "" { target *-*-* } 0 } */ +/* { dg-final { cleanup-tree-dump "vect" } } */ + +/* { dg-final { scan-tree-dump-times "ANNOTATE_EXPR " 1 "original" } } */ +/* { dg-final { cleanup-tree-dump "original" } } */ +/* { dg-final { scan-tree-dump-times "ANNOTATE " 1 "gimple" } } */ +/* { dg-final { cleanup-tree-dump "gimple" } } */ diff --git a/gcc/testsuite/g++.dg/vect/pr33426-ivdep-4.cc b/gcc/testsuite/g++.dg/vect/pr33426-ivdep-4.cc new file mode 100644 index 00000000000..8850505ac1f --- /dev/null +++ b/gcc/testsuite/g++.dg/vect/pr33426-ivdep-4.cc @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target vect_float } */ +/* { dg-additional-options "-std=c++11 -O3 -fopt-info-vec-optimized -fdump-tree-original -fdump-tree-gimple" } */ + +/* PR other/33426 */ +/* Testing whether #pragma ivdep is working. */ + +#include <vector> + +template<class T, class T2> +void Loop(T *b, T2 c) { +#pragma GCC ivdep + for (auto &i : *b) { + i *= *c; + } +} + +void foo(std::vector<int> *ar, int *b) { + Loop<std::vector<int>, int*>(ar, b); +} + +/* { dg-message "loop vectorized" "" { target *-*-* } 0 } */ +/* FIXME: dg-bogus " version" "" { target *-*-* } 0 */ +/* FIXME: dg-bogus " alias" "" { target *-*-* } 0 */ +/* { dg-final { cleanup-tree-dump "vect" } } */ + +/* { dg-final { scan-tree-dump-times "ANNOTATE_EXPR " 1 "original" } } */ +/* { dg-final { cleanup-tree-dump "original" } } */ +/* { dg-final { scan-tree-dump-times "ANNOTATE " 1 "gimple" } } */ +/* { dg-final { cleanup-tree-dump "gimple" } } */ diff --git a/gcc/testsuite/g++.dg/vect/pr33426-ivdep.cc b/gcc/testsuite/g++.dg/vect/pr33426-ivdep.cc new file mode 100644 index 00000000000..9715e9423f4 --- /dev/null +++ b/gcc/testsuite/g++.dg/vect/pr33426-ivdep.cc @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target vect_float } */ +/* { dg-additional-options "-O3 -fopt-info-vec-optimized" } */ + +/* PR other/33426 */ +/* Testing whether #pragma ivdep is working. */ + +void foo(int n, int *a, int *b, int *c, int *d, int *e) { + int i; +#pragma GCC ivdep + for (i = 0; i < n; ++i) { + a[i] = b[i] + c[i]; + } +} + +/* { dg-message "loop vectorized" "" { target *-*-* } 0 } */ +/* { dg-bogus " version" "" { target *-*-* } 0 } */ +/* { dg-bogus " alias" "" { target *-*-* } 0 } */ +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/g++.dg/vect/slp-pr56812.cc b/gcc/testsuite/g++.dg/vect/slp-pr56812.cc index e98abc89df0..9c0b2b8b78b 100644 --- a/gcc/testsuite/g++.dg/vect/slp-pr56812.cc +++ b/gcc/testsuite/g++.dg/vect/slp-pr56812.cc @@ -1,7 +1,7 @@ /* { dg-do compile } */
/* { dg-require-effective-target vect_float } */
/* { dg-require-effective-target vect_hw_misalign } */
-/* { dg-additional-options "-O3 -funroll-loops -fvect-cost-model" } */
+/* { dg-additional-options "-O3 -funroll-loops -fvect-cost-model=dynamic" } */
class mydata {
public:
diff --git a/gcc/testsuite/g++.dg/warn/pr33738.C b/gcc/testsuite/g++.dg/warn/pr33738.C index e84fece13f6..60ee0b48412 100644 --- a/gcc/testsuite/g++.dg/warn/pr33738.C +++ b/gcc/testsuite/g++.dg/warn/pr33738.C @@ -18,6 +18,7 @@ int main() { if (a2 == -1) { // { dg-warning "always false due" } link_error (); } + a2 = static_cast<Alpha>(GetM1()); if (-1 == a2) { // { dg-warning "always false due" } link_error (); } diff --git a/gcc/testsuite/gcc.c-torture/compile/pr58775.c b/gcc/testsuite/gcc.c-torture/compile/pr58775.c new file mode 100644 index 00000000000..8de06ddc05c --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr58775.c @@ -0,0 +1,26 @@ +/* PR tree-optimization/58775 */ + +void bar (void); + +void +foo (char *x) +{ + char a; + _Bool b, c, d, e, f, g, h, i, j, k, l, m; + + a = *x; + b = a == 100; + c = a == 105; + d = b | c; + e = a != 111; + f = !d; + g = e & f; + h = a != 117; + i = g & h; + j = a != 120; + k = i & j; + l = a != 88; + m = k & l; + if (m == 0) + bar (); +} diff --git a/gcc/testsuite/gcc.c-torture/compile/pr58946.c b/gcc/testsuite/gcc.c-torture/compile/pr58946.c new file mode 100644 index 00000000000..0ec5eba16f0 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr58946.c @@ -0,0 +1,20 @@ +/* PR tree-optimization/58946 */ + +int +foo (unsigned int c) +{ + unsigned int d, e, f; + if ((int) c < 0) + d = 0; + else + d = c; + if (d == 0) + e = __INT_MAX__ + 1U; + else + e = d; + if ((int) e < 0) + f = 0; + else + f = e; + return f; +} diff --git a/gcc/testsuite/gcc.c-torture/execute/20030125-1.c b/gcc/testsuite/gcc.c-torture/execute/20030125-1.c index 8eb9a4211a8..28cfbd10b4c 100644 --- a/gcc/testsuite/gcc.c-torture/execute/20030125-1.c +++ b/gcc/testsuite/gcc.c-torture/execute/20030125-1.c @@ -44,11 +44,11 @@ __attribute__ ((noinline)) double sin(double a) { - abort (); + return a; } __attribute__ ((noinline)) float sinf(float a) { - return a; + abort (); } diff --git a/gcc/testsuite/gcc.c-torture/execute/builtins/strncmp-2.c b/gcc/testsuite/gcc.c-torture/execute/builtins/strncmp-2.c index fe3462724ea..508b2d3309a 100644 --- a/gcc/testsuite/gcc.c-torture/execute/builtins/strncmp-2.c +++ b/gcc/testsuite/gcc.c-torture/execute/builtins/strncmp-2.c @@ -12,7 +12,7 @@ extern int strncmp (const char *, const char *, size_t); void main_test (void) { -#if !defined(__OPTIMIZE__) || ((defined(__i386__) || defined (__x86_64__)) && !defined(__OPTIMIZE_SIZE__)) +#if !defined(__OPTIMIZE__) || ((defined(__sh__) || defined(__i386__) || defined (__x86_64__)) && !defined(__OPTIMIZE_SIZE__)) /* These tests work on platforms which support cmpstrsi. We test it at -O0 on all platforms to ensure the strncmp logic is correct. */ const char *const s1 = "hello world"; diff --git a/gcc/testsuite/gcc.c-torture/execute/pr58831.c b/gcc/testsuite/gcc.c-torture/execute/pr58831.c new file mode 100644 index 00000000000..a40cd54d222 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr58831.c @@ -0,0 +1,40 @@ +#include <assert.h> + +int a, *b, c, d, f, **i, p, q, *r; +short o, j; + +static int __attribute__((noinline, noclone)) +fn1 (int *p1, int **p2) +{ + int **e = &b; + for (; p; p++) + *p1 = 1; + *e = *p2 = &d; + + assert (r); + + return c; +} + +static int ** __attribute__((noinline, noclone)) +fn2 (void) +{ + for (f = 0; f != 42; f++) + { + int *g[3] = {0, 0, 0}; + for (o = 0; o; o--) + for (; a > 1;) + { + int **h[1] = { &g[2] }; + } + } + return &r; +} + +int +main (void) +{ + i = fn2 (); + fn1 (b, i); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/20020312-2.c b/gcc/testsuite/gcc.dg/20020312-2.c index 633da5be189..299910047f5 100644 --- a/gcc/testsuite/gcc.dg/20020312-2.c +++ b/gcc/testsuite/gcc.dg/20020312-2.c @@ -96,6 +96,10 @@ extern void abort (void); #endif #elif defined (__aarch64__) /* No pic register -- yet. */ +#elif defined(__RL78__) +/* No pic register. */ +#elif defined(__MSP430__) +/* No pic register. */ #else # error "Modify the test for your target." #endif diff --git a/gcc/testsuite/gcc.dg/20050922-1.c b/gcc/testsuite/gcc.dg/20050922-1.c index ed5a3c63e9d..982f82011ba 100644 --- a/gcc/testsuite/gcc.dg/20050922-1.c +++ b/gcc/testsuite/gcc.dg/20050922-1.c @@ -4,7 +4,7 @@ /* { dg-do run } */ /* { dg-options "-O1 -std=c99" } */ -#include <stdlib.h> +extern void abort (void); #if __INT_MAX__ == 2147483647 typedef unsigned int uint32_t; diff --git a/gcc/testsuite/gcc.dg/20050922-2.c b/gcc/testsuite/gcc.dg/20050922-2.c index c2974d03d9c..2e8db829e29 100644 --- a/gcc/testsuite/gcc.dg/20050922-2.c +++ b/gcc/testsuite/gcc.dg/20050922-2.c @@ -4,7 +4,8 @@ /* { dg-do run } */ /* { dg-options "-O1 -std=c99" } */ -#include <stdlib.h> +extern void abort (void); +extern void exit (int); #if __INT_MAX__ == 2147483647 typedef unsigned int uint32_t; diff --git a/gcc/testsuite/gcc.dg/atomic-store-6.c b/gcc/testsuite/gcc.dg/atomic-store-6.c new file mode 100644 index 00000000000..81499cd716b --- /dev/null +++ b/gcc/testsuite/gcc.dg/atomic-store-6.c @@ -0,0 +1,13 @@ +/* { dg-do run } */ +/* { dg-require-effective-target sync_int_128_runtime } */ +/* { dg-options "-mcx16" { target { i?86-*-* x86_64-*-* } } } */ + +__int128_t i; + +int main() +{ + __atomic_store_16(&i, -1, 0); + if (i != -1) + __builtin_abort(); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/builtin-complex-err-1.c b/gcc/testsuite/gcc.dg/builtin-complex-err-1.c index 3ef50da9278..ddc72b583cb 100644 --- a/gcc/testsuite/gcc.dg/builtin-complex-err-1.c +++ b/gcc/testsuite/gcc.dg/builtin-complex-err-1.c @@ -1,6 +1,6 @@ /* Test __builtin_complex errors. */ /* { dg-do compile } */ -/* { dg-options "-std=c1x -pedantic-errors" } */ +/* { dg-options "-std=c11 -pedantic-errors" } */ typedef double D; diff --git a/gcc/testsuite/gcc.dg/c1x-align-1.c b/gcc/testsuite/gcc.dg/c11-align-1.c index 9fe5757bed0..e0058c38007 100644 --- a/gcc/testsuite/gcc.dg/c1x-align-1.c +++ b/gcc/testsuite/gcc.dg/c11-align-1.c @@ -1,6 +1,6 @@ -/* Test C1X alignment support. Test valid code. */ +/* Test C11 alignment support. Test valid code. */ /* { dg-do compile } */ -/* { dg-options "-std=c1x -pedantic-errors" } */ +/* { dg-options "-std=c11 -pedantic-errors" } */ #include <stddef.h> diff --git a/gcc/testsuite/gcc.dg/c1x-align-2.c b/gcc/testsuite/gcc.dg/c11-align-2.c index 19f7dd67214..a1750ac547a 100644 --- a/gcc/testsuite/gcc.dg/c1x-align-2.c +++ b/gcc/testsuite/gcc.dg/c11-align-2.c @@ -1,6 +1,6 @@ -/* Test C1X alignment support. Test valid code using stdalign.h. */ +/* Test C11 alignment support. Test valid code using stdalign.h. */ /* { dg-do run } */ -/* { dg-options "-std=c1x -pedantic-errors" } */ +/* { dg-options "-std=c11 -pedantic-errors" } */ #include <stdalign.h> #include <stddef.h> diff --git a/gcc/testsuite/gcc.dg/c1x-align-3.c b/gcc/testsuite/gcc.dg/c11-align-3.c index b97351cdeaf..39b81ef6f57 100644 --- a/gcc/testsuite/gcc.dg/c1x-align-3.c +++ b/gcc/testsuite/gcc.dg/c11-align-3.c @@ -1,6 +1,6 @@ -/* Test C1X alignment support. Test invalid code. */ +/* Test C11 alignment support. Test invalid code. */ /* { dg-do compile } */ -/* { dg-options "-std=c1x -pedantic-errors" } */ +/* { dg-options "-std=c11 -pedantic-errors" } */ int a = _Alignof (void (void)); /* { dg-error "function" } */ struct s; diff --git a/gcc/testsuite/gcc.dg/c1x-align-4.c b/gcc/testsuite/gcc.dg/c11-align-4.c index cc13f93d9c0..6377db6edf3 100644 --- a/gcc/testsuite/gcc.dg/c1x-align-4.c +++ b/gcc/testsuite/gcc.dg/c11-align-4.c @@ -1,7 +1,7 @@ -/* Test C1X alignment support. Test reducing alignment (assumes there +/* Test C11 alignment support. Test reducing alignment (assumes there are at least some alignment constraints). */ /* { dg-do compile } */ -/* { dg-options "-std=c1x -pedantic-errors" } */ +/* { dg-options "-std=c11 -pedantic-errors" } */ /* { dg-skip-if "no alignment constraints" { "avr-*-*" } { "*" } { "" } } */ #include <stddef.h> diff --git a/gcc/testsuite/gcc.dg/c1x-align-5.c b/gcc/testsuite/gcc.dg/c11-align-5.c index 614edcf6f9b..f3a14779ff8 100644 --- a/gcc/testsuite/gcc.dg/c1x-align-5.c +++ b/gcc/testsuite/gcc.dg/c11-align-5.c @@ -1,6 +1,6 @@ -/* Test C1X alignment support. Test invalid code. */ +/* Test C11 alignment support. Test invalid code. */ /* { dg-do compile } */ -/* { dg-options "-std=c1x -pedantic-errors" } */ +/* { dg-options "-std=c11 -pedantic-errors" } */ void foo (int []); void bar1 (int [_Alignas (double) 10]); /* { dg-error "expected expression before" } */ @@ -14,6 +14,14 @@ void foo (int a[_Alignas (0) 10]) { } /* { dg-error "expected expression before" void test (void) { + int *_Alignas (long) p; /* { dg-error "expected" } */ + int *const _Alignas (long) *q; /* { dg-error "expected" } */ + struct s { int n; }; + __builtin_offsetof (struct s _Alignas (int), n); /* { dg-error "expected" } */ + __typeof (long double _Alignas (0)) e; /* { dg-error "expected" } */ + sizeof (int _Alignas (int)); /* { dg-error "expected" } */ + _Alignas (int _Alignas (float)) int t; /* { dg-error "expected" } */ + __builtin_types_compatible_p (signed _Alignas (0), unsigned); /* { dg-error "expected" } */ int a[_Alignas (int) 10]; /* { dg-error "expected expression before" } */ int b[10]; foo (b); diff --git a/gcc/testsuite/gcc.dg/c1x-anon-struct-1.c b/gcc/testsuite/gcc.dg/c11-anon-struct-1.c index 6d4b433d733..779ae66b7e1 100644 --- a/gcc/testsuite/gcc.dg/c1x-anon-struct-1.c +++ b/gcc/testsuite/gcc.dg/c11-anon-struct-1.c @@ -1,6 +1,6 @@ -/* Test for anonymous structures and unions in C1X. */ +/* Test for anonymous structures and unions in C11. */ /* { dg-do compile } */ -/* { dg-options "-std=c1x -pedantic-errors" } */ +/* { dg-options "-std=c11 -pedantic-errors" } */ #include <stddef.h> diff --git a/gcc/testsuite/gcc.dg/c1x-anon-struct-2.c b/gcc/testsuite/gcc.dg/c11-anon-struct-2.c index cb8043117d5..d954b4b1270 100644 --- a/gcc/testsuite/gcc.dg/c1x-anon-struct-2.c +++ b/gcc/testsuite/gcc.dg/c11-anon-struct-2.c @@ -1,7 +1,7 @@ -/* Test for anonymous structures and unions in C1X. Test for invalid +/* Test for anonymous structures and unions in C11. Test for invalid cases. */ /* { dg-do compile } */ -/* { dg-options "-std=c1x -pedantic-errors" } */ +/* { dg-options "-std=c11 -pedantic-errors" } */ typedef struct s0 { diff --git a/gcc/testsuite/gcc.dg/c1x-anon-struct-3.c b/gcc/testsuite/gcc.dg/c11-anon-struct-3.c index 1841eddd0a1..05cc3660cb8 100644 --- a/gcc/testsuite/gcc.dg/c1x-anon-struct-3.c +++ b/gcc/testsuite/gcc.dg/c11-anon-struct-3.c @@ -1,7 +1,7 @@ -/* Test for anonymous structures and unions in C1X. Test for invalid +/* Test for anonymous structures and unions in C11. Test for invalid cases: typedefs disallowed by N1549. */ /* { dg-do compile } */ -/* { dg-options "-std=c1x -pedantic-errors" } */ +/* { dg-options "-std=c11 -pedantic-errors" } */ typedef struct { diff --git a/gcc/testsuite/gcc.dg/c1x-float-1.c b/gcc/testsuite/gcc.dg/c11-float-1.c index 75233ac8227..376c44d3e78 100644 --- a/gcc/testsuite/gcc.dg/c1x-float-1.c +++ b/gcc/testsuite/gcc.dg/c11-float-1.c @@ -1,9 +1,9 @@ -/* Test for <float.h> C1X macros. */ +/* Test for <float.h> C11 macros. */ /* Origin: Joseph Myers <joseph@codesourcery.com> */ /* { dg-do preprocess } */ -/* { dg-options "-std=c1x -pedantic-errors" } */ +/* { dg-options "-std=c11 -pedantic-errors" } */ -/* This test checks that the C1X macros are defined; +/* This test checks that the C11 macros are defined; it does not check the correctness of their values. */ #include <float.h> diff --git a/gcc/testsuite/gcc.dg/c1x-noreturn-1.c b/gcc/testsuite/gcc.dg/c11-noreturn-1.c index d9c141d5326..e92c5ae0456 100644 --- a/gcc/testsuite/gcc.dg/c1x-noreturn-1.c +++ b/gcc/testsuite/gcc.dg/c11-noreturn-1.c @@ -1,6 +1,6 @@ -/* Test C1X _Noreturn. Test valid code. */ +/* Test C11 _Noreturn. Test valid code. */ /* { dg-do compile } */ -/* { dg-options "-std=c1x -pedantic-errors" } */ +/* { dg-options "-std=c11 -pedantic-errors" } */ _Noreturn void exit (int); diff --git a/gcc/testsuite/gcc.dg/c1x-noreturn-2.c b/gcc/testsuite/gcc.dg/c11-noreturn-2.c index 81972f1e8be..951d028f7ae 100644 --- a/gcc/testsuite/gcc.dg/c1x-noreturn-2.c +++ b/gcc/testsuite/gcc.dg/c11-noreturn-2.c @@ -1,6 +1,6 @@ -/* Test C1X _Noreturn. Test valid code using stdnoreturn.h. */ +/* Test C11 _Noreturn. Test valid code using stdnoreturn.h. */ /* { dg-do run } */ -/* { dg-options "-std=c1x -pedantic-errors" } */ +/* { dg-options "-std=c11 -pedantic-errors" } */ #include <stdnoreturn.h> diff --git a/gcc/testsuite/gcc.dg/c1x-noreturn-3.c b/gcc/testsuite/gcc.dg/c11-noreturn-3.c index b12c23efafc..168d012a3f0 100644 --- a/gcc/testsuite/gcc.dg/c1x-noreturn-3.c +++ b/gcc/testsuite/gcc.dg/c11-noreturn-3.c @@ -1,6 +1,6 @@ -/* Test C1X _Noreturn. Test _Noreturn on main, hosted. */ +/* Test C11 _Noreturn. Test _Noreturn on main, hosted. */ /* { dg-do compile } */ -/* { dg-options "-std=c1x -pedantic-errors -fhosted" } */ +/* { dg-options "-std=c11 -pedantic-errors -fhosted" } */ _Noreturn void exit (int); diff --git a/gcc/testsuite/gcc.dg/c11-noreturn-4.c b/gcc/testsuite/gcc.dg/c11-noreturn-4.c new file mode 100644 index 00000000000..a92a1140f67 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c11-noreturn-4.c @@ -0,0 +1,11 @@ +/* Test C11 _Noreturn. Test _Noreturn on main, freestanding. */ +/* { dg-do compile } */ +/* { dg-options "-std=c11 -pedantic-errors -ffreestanding" } */ + +_Noreturn void exit (int); + +_Noreturn int +main (void) +{ + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/c1x-noreturn-5.c b/gcc/testsuite/gcc.dg/c11-noreturn-5.c index 73f22165cb0..d1c0949f32b 100644 --- a/gcc/testsuite/gcc.dg/c1x-noreturn-5.c +++ b/gcc/testsuite/gcc.dg/c11-noreturn-5.c @@ -1,6 +1,6 @@ -/* Test C1X _Noreturn. Test invalid uses. */ +/* Test C11 _Noreturn. Test invalid uses. */ /* { dg-do compile } */ -/* { dg-options "-std=c1x -pedantic-errors" } */ +/* { dg-options "-std=c11 -pedantic-errors" } */ _Noreturn struct s; /* { dg-error "empty declaration" } */ diff --git a/gcc/testsuite/gcc.dg/c1x-pointer-float-1.c b/gcc/testsuite/gcc.dg/c11-pointer-float-1.c index 57c5be88736..8c241658777 100644 --- a/gcc/testsuite/gcc.dg/c1x-pointer-float-1.c +++ b/gcc/testsuite/gcc.dg/c11-pointer-float-1.c @@ -1,6 +1,6 @@ -/* Test C1X constraint against pointer / floating-point casts. */ +/* Test C11 constraint against pointer / floating-point casts. */ /* { dg-do compile } */ -/* { dg-options "-std=c1x -pedantic-errors" } */ +/* { dg-options "-std=c11 -pedantic-errors" } */ void *p; float f; diff --git a/gcc/testsuite/gcc.dg/c1x-static-assert-1.c b/gcc/testsuite/gcc.dg/c11-static-assert-1.c index bf7aa594511..9209a7a4076 100644 --- a/gcc/testsuite/gcc.dg/c1x-static-assert-1.c +++ b/gcc/testsuite/gcc.dg/c11-static-assert-1.c @@ -1,6 +1,6 @@ -/* Test C1X static assertions. Valid assertions. */ +/* Test C11 static assertions. Valid assertions. */ /* { dg-do compile } */ -/* { dg-options "-std=c1x -pedantic-errors" } */ +/* { dg-options "-std=c11 -pedantic-errors" } */ _Static_assert (1, "foo"); diff --git a/gcc/testsuite/gcc.dg/c1x-static-assert-2.c b/gcc/testsuite/gcc.dg/c11-static-assert-2.c index 9a48ca7e861..de2f573cb8c 100644 --- a/gcc/testsuite/gcc.dg/c1x-static-assert-2.c +++ b/gcc/testsuite/gcc.dg/c11-static-assert-2.c @@ -1,6 +1,6 @@ -/* Test C1X static assertions. Failed assertions. */ +/* Test C11 static assertions. Failed assertions. */ /* { dg-do compile } */ -/* { dg-options "-std=c1x -pedantic-errors" } */ +/* { dg-options "-std=c11 -pedantic-errors" } */ _Static_assert (0, "assert1"); /* { dg-error "static assertion failed: \"assert1\"" } */ diff --git a/gcc/testsuite/gcc.dg/c1x-static-assert-3.c b/gcc/testsuite/gcc.dg/c11-static-assert-3.c index 81b504e2ab1..79448a533e5 100644 --- a/gcc/testsuite/gcc.dg/c1x-static-assert-3.c +++ b/gcc/testsuite/gcc.dg/c11-static-assert-3.c @@ -1,6 +1,6 @@ -/* Test C1X static assertions. Invalid assertions. */ +/* Test C11 static assertions. Invalid assertions. */ /* { dg-do compile } */ -/* { dg-options "-std=c1x -pedantic-errors" } */ +/* { dg-options "-std=c11 -pedantic-errors" } */ _Static_assert (__INT_MAX__ * 2, "overflow"); /* { dg-warning "integer overflow in expression" } */ /* { dg-error "overflow in constant expression" "error" { target *-*-* } 5 } */ diff --git a/gcc/testsuite/gcc.dg/c1x-static-assert-4.c b/gcc/testsuite/gcc.dg/c11-static-assert-4.c index ebc95f5f906..ddab440ff48 100644 --- a/gcc/testsuite/gcc.dg/c1x-static-assert-4.c +++ b/gcc/testsuite/gcc.dg/c11-static-assert-4.c @@ -1,6 +1,6 @@ -/* Test C1X static assertions. More invalid assertions. */ +/* Test C11 static assertions. More invalid assertions. */ /* { dg-do compile } */ -/* { dg-options "-std=c1x -pedantic-errors" } */ +/* { dg-options "-std=c11 -pedantic-errors" } */ /* Static assertions not valid in old-style parameter declarations because declarations there must have declarators. */ diff --git a/gcc/testsuite/gcc.dg/c1x-static-assert-5.c b/gcc/testsuite/gcc.dg/c11-static-assert-5.c index d4d0821f0e3..e88b8167a19 100644 --- a/gcc/testsuite/gcc.dg/c1x-static-assert-5.c +++ b/gcc/testsuite/gcc.dg/c11-static-assert-5.c @@ -1,5 +1,5 @@ -/* Test C1X static assertions. Non-constant-expression without -pedantic. */ +/* Test C11 static assertions. Non-constant-expression without -pedantic. */ /* { dg-do compile } */ -/* { dg-options "-std=c1x" } */ +/* { dg-options "-std=c11" } */ _Static_assert ((int)(1.0 + 1.0), "non-constant-expression"); diff --git a/gcc/testsuite/gcc.dg/c1x-static-assert-6.c b/gcc/testsuite/gcc.dg/c11-static-assert-6.c index c544cadc268..ac7e14114db 100644 --- a/gcc/testsuite/gcc.dg/c1x-static-assert-6.c +++ b/gcc/testsuite/gcc.dg/c11-static-assert-6.c @@ -1,5 +1,5 @@ -/* Test C1X static assertions. Non-constant-expression with -pedantic. */ +/* Test C11 static assertions. Non-constant-expression with -pedantic. */ /* { dg-do compile } */ -/* { dg-options "-std=c1x -pedantic" } */ +/* { dg-options "-std=c11 -pedantic" } */ _Static_assert ((int)(1.0 + 1.0), "non-constant-expression"); /* { dg-warning "not an integer constant expression" } */ diff --git a/gcc/testsuite/gcc.dg/c1x-typedef-1.c b/gcc/testsuite/gcc.dg/c11-typedef-1.c index a68b23ff5e6..3224ba5a418 100644 --- a/gcc/testsuite/gcc.dg/c1x-typedef-1.c +++ b/gcc/testsuite/gcc.dg/c11-typedef-1.c @@ -1,8 +1,8 @@ -/* Test typedef redeclaration in C1X. */ +/* Test typedef redeclaration in C11. */ /* { dg-do compile } */ -/* { dg-options "-std=c1x -pedantic-errors" } */ +/* { dg-options "-std=c11 -pedantic-errors" } */ -/* C1X permits typedefs to be redeclared to the same type, but not to +/* C11 permits typedefs to be redeclared to the same type, but not to different-but-compatible types, and not when the type is variably modified. */ diff --git a/gcc/testsuite/gcc.dg/c1x-uni-string-1.c b/gcc/testsuite/gcc.dg/c11-uni-string-1.c index 30a98c1d669..9f86bea826b 100644 --- a/gcc/testsuite/gcc.dg/c1x-uni-string-1.c +++ b/gcc/testsuite/gcc.dg/c11-uni-string-1.c @@ -1,10 +1,10 @@ -/* Test Unicode strings in C1X. Test valid code. */ +/* Test Unicode strings in C11. Test valid code. */ /* { dg-do run } */ -/* { dg-options "-std=c1x -pedantic-errors" } */ +/* { dg-options "-std=c11 -pedantic-errors" } */ /* More thorough tests are in c-c++-common/raw-string-*.c; this test verifies the particular subset (Unicode but not raw strings) that - is in C1X. */ + is in C11. */ typedef __CHAR16_TYPE__ char16_t; typedef __CHAR32_TYPE__ char32_t; diff --git a/gcc/testsuite/gcc.dg/c1x-uni-string-2.c b/gcc/testsuite/gcc.dg/c11-uni-string-2.c index 698b0c1df39..583c38a87e2 100644 --- a/gcc/testsuite/gcc.dg/c1x-uni-string-2.c +++ b/gcc/testsuite/gcc.dg/c11-uni-string-2.c @@ -1,6 +1,6 @@ -/* Test Unicode strings in C1X. Test constraint. */ +/* Test Unicode strings in C11. Test constraint. */ /* { dg-do compile } */ -/* { dg-options "-std=c1x -pedantic-errors" } */ +/* { dg-options "-std=c11 -pedantic-errors" } */ const void *p1 = L"a" u8"b"; /* { dg-error "concatenation" } */ const void *p2 = L"a" "b" u8"c"; /* { dg-error "concatenation" } */ diff --git a/gcc/testsuite/gcc.dg/c1x-noreturn-4.c b/gcc/testsuite/gcc.dg/c1x-noreturn-4.c deleted file mode 100644 index 72dceafba19..00000000000 --- a/gcc/testsuite/gcc.dg/c1x-noreturn-4.c +++ /dev/null @@ -1,11 +0,0 @@ -/* Test C1X _Noreturn. Test _Noreturn on main, freestanding. */ -/* { dg-do compile } */ -/* { dg-options "-std=c1x -pedantic-errors -ffreestanding" } */ - -_Noreturn void exit (int); - -_Noreturn int -main (void) -{ - exit (0); -} diff --git a/gcc/testsuite/gcc.dg/c90-float-1.c b/gcc/testsuite/gcc.dg/c90-float-1.c index 5a2cab657a3..649cddfa071 100644 --- a/gcc/testsuite/gcc.dg/c90-float-1.c +++ b/gcc/testsuite/gcc.dg/c90-float-1.c @@ -3,7 +3,7 @@ /* { dg-do preprocess } */ /* { dg-options "-std=iso9899:1990 -pedantic-errors" } */ -/* This test checks that the C90 macros (but not the C99 or C1X ones) +/* This test checks that the C90 macros (but not the C99 or C11 ones) are defined; it does not check the correctness of their values. */ #include <float.h> diff --git a/gcc/testsuite/gcc.dg/c99-float-1.c b/gcc/testsuite/gcc.dg/c99-float-1.c index f0dc39136e9..7ee87a564a4 100644 --- a/gcc/testsuite/gcc.dg/c99-float-1.c +++ b/gcc/testsuite/gcc.dg/c99-float-1.c @@ -3,7 +3,7 @@ /* { dg-do preprocess } */ /* { dg-options "-std=iso9899:1999 -pedantic-errors" } */ -/* This test checks that the C99 macros (but not the C1X ones) are defined; +/* This test checks that the C99 macros (but not the C11 ones) are defined; it does not check the correctness of their values. */ #include <float.h> diff --git a/gcc/testsuite/gcc.dg/c99-stdint-1.c b/gcc/testsuite/gcc.dg/c99-stdint-1.c index 89bdec809f8..530d13025e7 100644 --- a/gcc/testsuite/gcc.dg/c99-stdint-1.c +++ b/gcc/testsuite/gcc.dg/c99-stdint-1.c @@ -9,6 +9,7 @@ version). */ /* { dg-do compile } */ /* { dg-options "-std=iso9899:1999 -pedantic-errors -fhosted" } */ +/* { dg-require-effective-target ptr32plus } */ #include <limits.h> #include <stdint.h> @@ -214,7 +215,6 @@ test_max (void) void test_misc_limits (void) { -/* { dg-bogus "size" "ptrdiff is 16bits" { xfail avr-*-* } 56 } */ CHECK_SIGNED_LIMITS_2(__PTRDIFF_TYPE__, PTRDIFF_MIN, PTRDIFF_MAX, -65535L, 65535L); #ifndef SIGNAL_SUPPRESS CHECK_LIMITS_2(sig_atomic_t, SIG_ATOMIC_MIN, SIG_ATOMIC_MAX, -127, 127, 255); diff --git a/gcc/testsuite/gcc.dg/c99-stdint-2.c b/gcc/testsuite/gcc.dg/c99-stdint-2.c index d1be0fb6332..1784b0c413e 100644 --- a/gcc/testsuite/gcc.dg/c99-stdint-2.c +++ b/gcc/testsuite/gcc.dg/c99-stdint-2.c @@ -2,7 +2,7 @@ Freestanding version. */ /* { dg-do compile } */ /* { dg-options "-std=iso9899:1999 -pedantic-errors -ffreestanding" } */ -/* { dg-xfail-if "ptrdiff size is 16bits" { avr-*-* } } */ +/* { dg-require-effective-target ptr32plus } */ /* The test is that there are no diagnostics, so just include the hosted version. */ #include "c99-stdint-1.c" diff --git a/gcc/testsuite/gcc.dg/cdce1.c b/gcc/testsuite/gcc.dg/cdce1.c index 3bd35ecb786..2123f7fd8e9 100644 --- a/gcc/testsuite/gcc.dg/cdce1.c +++ b/gcc/testsuite/gcc.dg/cdce1.c @@ -1,6 +1,7 @@ /* { dg-do run } */ /* { dg-options "-O2 -fmath-errno -fdump-tree-cdce-details -lm" } */ -/* { dg-final { scan-tree-dump "cdce1.c:16: note: function call is shrink-wrapped into error conditions\." "cdce" } } */ +/* { dg-require-effective-target int32plus } */ +/* { dg-final { scan-tree-dump "cdce1.c:17: note: function call is shrink-wrapped into error conditions\." "cdce" } } */ /* { dg-final { cleanup-tree-dump "cdce" } } */ /* { dg-require-effective-target large_double } */ diff --git a/gcc/testsuite/gcc.dg/cilk-plus/cilk-plus.exp b/gcc/testsuite/gcc.dg/cilk-plus/cilk-plus.exp index 2533febc8ab..0267fe120ad 100644 --- a/gcc/testsuite/gcc.dg/cilk-plus/cilk-plus.exp +++ b/gcc/testsuite/gcc.dg/cilk-plus/cilk-plus.exp @@ -23,6 +23,14 @@ if { ![check_effective_target_cilkplus] } { return; } +verbose "$tool $libdir" 1 +set library_var [get_multilibs] +# Pointing the ld_library_path to the Cilk Runtime library binaries. +set ld_library_path "${library_var}/libcilkrts/.libs" + +set ALWAYS_CFLAGS "" +lappend ALWAYS_CFLAGS "-L${library_var}/libcilkrts/.libs" + dg-init dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -fcilkplus" " " dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -O0 -fcilkplus" " " @@ -46,4 +54,31 @@ dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -f dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -fcilkplus -g -O2 -ftree-vectorize -std=c99" " " dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -fcilkplus -g -O3 -std=c99" " " dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -O3 -ftree-vectorize -std=c99 -g -fcilkplus" " " + + +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -fcilkplus $ALWAYS_CFLAGS " " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O0 -fcilkplus $ALWAYS_CFLAGS" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O1 -fcilkplus $ALWAYS_CFLAGS" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O2 -ftree-vectorize -fcilkplus $ALWAYS_CFLAGS" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O3 -fcilkplus $ALWAYS_CFLAGS" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -g -fcilkplus $ALWAYS_CFLAGS" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -g -O0 -fcilkplus $ALWAYS_CFLAGS" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -g -O1 -fcilkplus $ALWAYS_CFLAGS" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -g -O2 -ftree-vectorize -fcilkplus $ALWAYS_CFLAGS" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -g -O3 -fcilkplus $ALWAYS_CFLAGS" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O3 -ftree-vectorize -fcilkplus -g $ALWAYS_CFLAGS" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -fcilkplus -std=c99 $ALWAYS_CFLAGS" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -fcilkplus -O0 -std=c99 $ALWAYS_CFLAGS" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -fcilkplus -O1 -std=c99 $ALWAYS_CFLAGS" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -fcilkplus -O2 -ftree-vectorize -std=c99 $ALWAYS_CFLAGS" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -fcilkplus -O3 -std=c99 $ALWAYS_CFLAGS" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -fcilkplus -g -std=c99 $ALWAYS_CFLAGS" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -fcilkplus -g -O0 -std=c99 $ALWAYS_CFLAGS" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -fcilkplus -g -O1 -std=c99 $ALWAYS_CFLAGS" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -fcilkplus -g -O2 -ftree-vectorize -std=c99 $ALWAYS_CFLAGS" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -fcilkplus -g -O3 -std=c99 $ALWAYS_CFLAGS" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O3 -ftree-vectorize -std=c99 -g -fcilkplus $ALWAYS_CFLAGS" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O0 -flto -g -fcilkplus $ALWAYS_CFLAGS" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O2 -flto -g -fcilkplus $ALWAYS_CFLAGS" " " +dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O3 -flto -g -fcilkplus $ALWAYS_CFLAGS" " " dg-finish diff --git a/gcc/testsuite/gcc.dg/dfp/pr35739.c b/gcc/testsuite/gcc.dg/dfp/pr35739.c deleted file mode 100644 index 0fc9d478f5f..00000000000 --- a/gcc/testsuite/gcc.dg/dfp/pr35739.c +++ /dev/null @@ -1,16 +0,0 @@ -/* PR c/35739 */ -/* { dg-do compile { target *-*-linux* *-*-gnu* } } */ -/* { dg-options "-O -fpreprocessed -fmudflap" } */ - -_Decimal128 -foo (int n, ...) -{ - int i; - _Decimal128 j = 0; - __builtin_va_list ap; - __builtin_va_start (ap, n); - for (i = 0; i < n; i++) - j += __builtin_va_arg (ap, _Decimal128); - __builtin_va_end (ap); - return j; -} diff --git a/gcc/testsuite/gcc.dg/fold-overflow-1.c b/gcc/testsuite/gcc.dg/fold-overflow-1.c index 8fddc9fc0ee..4f45b35ee45 100644 --- a/gcc/testsuite/gcc.dg/fold-overflow-1.c +++ b/gcc/testsuite/gcc.dg/fold-overflow-1.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-skip-if "consts are shorts, not longs" { "m32c-*-*" "avr-*-*" } { "*" } { "" } } */ +/* { dg-require-effective-target int32plus } */ /* { dg-skip-if "No Inf support" { spu-*-* } } */ /* { dg-options "-O -ftrapping-math" } */ diff --git a/gcc/testsuite/gcc.dg/ftrapv-1.c b/gcc/testsuite/gcc.dg/ftrapv-1.c index 44eb176b50d..86bd802cf13 100644 --- a/gcc/testsuite/gcc.dg/ftrapv-1.c +++ b/gcc/testsuite/gcc.dg/ftrapv-1.c @@ -7,6 +7,7 @@ /* { dg-do run } */ /* { dg-options "-ftrapv" } */ +/* { dg-require-effective-target trapping } */ __attribute__((noinline)) int mulv(int a, int b) diff --git a/gcc/testsuite/gcc.dg/ftrapv-2.c b/gcc/testsuite/gcc.dg/ftrapv-2.c index d79b86dde9c..7d765747c9c 100644 --- a/gcc/testsuite/gcc.dg/ftrapv-2.c +++ b/gcc/testsuite/gcc.dg/ftrapv-2.c @@ -8,6 +8,7 @@ /* { dg-do run } */ /* { dg-options "-ftrapv" } */ +/* { dg-require-effective-target trapping } */ extern void abort(void); extern long labs(long); diff --git a/gcc/testsuite/gcc.dg/gomp/declare-simd-2.c b/gcc/testsuite/gcc.dg/gomp/declare-simd-2.c index 118549be908..c0a42a2ef46 100644 --- a/gcc/testsuite/gcc.dg/gomp/declare-simd-2.c +++ b/gcc/testsuite/gcc.dg/gomp/declare-simd-2.c @@ -22,3 +22,33 @@ int fn5 (int a); #pragma omp declare simd inbranch notinbranch /* { dg-error "clause is incompatible with" } */ int fn6 (int); + +#pragma omp declare simd aligned (a, b) +int fn7 (int *a, int b[64]); + +#pragma omp declare simd aligned (a) /* { dg-error "neither a pointer nor an array" } */ +int fn8 (int a); + +#pragma omp declare simd aligned (c) /* { dg-error "neither a pointer nor an array" } */ +int fn9 (float c); + +#pragma omp declare simd aligned (d) /* { dg-error "neither a pointer nor an array" } */ +int fn10 (double d); + +struct D { int d; }; + +#pragma omp declare simd aligned (e) /* { dg-error "neither a pointer nor an array" } */ +int fn11 (struct D e); + +#pragma omp declare simd linear(a:7) uniform(a) /* { dg-error "appears more than once" } */ +int f12 (int a); +#pragma omp declare simd linear(a) linear(a) /* { dg-error "appears more than once" } */ +int f13 (int a); +#pragma omp declare simd linear(a) linear(a:7) /* { dg-error "appears more than once" } */ +int f14 (int a); +#pragma omp declare simd linear(a:6) linear(a:6)/* { dg-error "appears more than once" } */ +int f15 (int a); +#pragma omp declare simd uniform(a) uniform(a) /* { dg-error "appears more than once" } */ +int f16 (int a); +#pragma omp declare simd uniform(a) aligned (a: 32) +int f17 (int *a); diff --git a/gcc/testsuite/gcc.dg/gomp/pr58809.c b/gcc/testsuite/gcc.dg/gomp/pr58809.c new file mode 100644 index 00000000000..5dc02f65aa8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/gomp/pr58809.c @@ -0,0 +1,13 @@ +/* PR middle-end/58809 */ +/* { dg-do compile } */ +/* { dg-options "-fopenmp -O" } */ + +int i; +#pragma omp threadprivate (i) + +void foo() +{ + _Complex int j; +#pragma omp parallel copyin (i) reduction (&&:j) + ; +} diff --git a/gcc/testsuite/gcc.dg/guality/pr58791-1.c b/gcc/testsuite/gcc.dg/guality/pr58791-1.c new file mode 100644 index 00000000000..62ce881bfc2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/guality/pr58791-1.c @@ -0,0 +1,34 @@ +/* PR tree-optimization/58791 */ +/* { dg-do run } */ +/* { dg-options "-g" } */ + +#include "../nop.h" + +__attribute__((noinline, noclone)) int +foo (int x, int y) +{ + _Bool a = x != 0; + _Bool b = y != 2; + _Bool c = a & b; + _Bool d = !c; + int ret; + if (c) + { + if (y < 3 || y > 4) + ret = 1; + else + ret = 0; + } + else + ret = 0; + asm volatile (NOP : : : "memory"); /* { dg-final { gdb-test pr58791-1.c:25 "c & 1" "1" } } */ + asm volatile (NOP : : : "memory"); /* { dg-final { gdb-test pr58791-1.c:25 "d & 1" "0" } } */ + return ret; +} + +int +main () +{ + foo (1, 3); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/guality/pr58791-2.c b/gcc/testsuite/gcc.dg/guality/pr58791-2.c new file mode 100644 index 00000000000..d7da69b48c4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/guality/pr58791-2.c @@ -0,0 +1,36 @@ +/* PR tree-optimization/58791 */ +/* { dg-do run } */ +/* { dg-options "-g" } */ + +#include "../nop.h" + +__attribute__((noinline, noclone)) int +foo (unsigned char c) +{ + int ret; + _Bool a, b, d, e, f; + + a = c == 34; + b = c == 32; + d = a | b; + f = !d; + if (d) + ret = 1; + else + { + e = c <= 31; + ret = e; + } + + asm volatile (NOP : : : "memory"); /* { dg-final { gdb-test pr58791-2.c:27 "d & 1" "1" } } */ + asm volatile (NOP : : : "memory"); /* { dg-final { gdb-test pr58791-2.c:27 "f & 1" "0" } } */ + return ret; +} + + +int +main () +{ + foo (32); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/guality/pr58791-3.c b/gcc/testsuite/gcc.dg/guality/pr58791-3.c new file mode 100644 index 00000000000..6316ace5667 --- /dev/null +++ b/gcc/testsuite/gcc.dg/guality/pr58791-3.c @@ -0,0 +1,28 @@ +/* PR tree-optimization/58791 */ +/* { dg-do run } */ +/* { dg-options "-g" } */ + +#include "../nop.h" + +__attribute__((noinline, noclone)) unsigned +foo (unsigned a, unsigned b, unsigned c, unsigned d, unsigned e) +{ + unsigned f = b + c; /* { dg-final { gdb-test pr58791-3.c:19 "f" "5" } } */ + unsigned g = a - f; /* { dg-final { gdb-test pr58791-3.c:19 "g" "24" } } */ + unsigned h = d + e; /* { dg-final { gdb-test pr58791-3.c:19 "h" "9" } } */ + unsigned i = g - h; /* { dg-final { gdb-test pr58791-3.c:19 "i" "15" } } */ + unsigned j = f + 1; /* { dg-final { gdb-test pr58791-3.c:19 "j" "6" } } */ + unsigned k = g + 1; /* { dg-final { gdb-test pr58791-3.c:19 "k" "25" } } */ + unsigned l = h + 1; /* { dg-final { gdb-test pr58791-3.c:19 "l" "10" } } */ + unsigned m = i + 1; /* { dg-final { gdb-test pr58791-3.c:19 "m" "16" } } */ + asm volatile (NOP : : : "memory"); + asm volatile (NOP : : : "memory"); + return i; +} + +int +main () +{ + foo (29, 2, 3, 4, 5); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/guality/pr58791-4.c b/gcc/testsuite/gcc.dg/guality/pr58791-4.c new file mode 100644 index 00000000000..d988a9cfbbe --- /dev/null +++ b/gcc/testsuite/gcc.dg/guality/pr58791-4.c @@ -0,0 +1,41 @@ +/* PR tree-optimization/58791 */ +/* { dg-do run } */ +/* { dg-options "-g -ffast-math" } */ + +#include "../nop.h" + +__attribute__((noinline, noclone)) double +foo (float a, float b, float c, float d, float l, double u) +{ + float e = a * d; + float f = d * e; + double g = (double) f; + double h = (double) b; + double i = g * h; /* { dg-final { gdb-test pr58791-4.c:32 "i" "486" { target { x86_64-*-* && lp64 } } } } */ + double i2 = i + 1.0; /* { dg-final { gdb-test pr58791-4.c:32 "i2" "487" { target { x86_64-*-* && lp64 } } } } */ + double j = i * 3.25; + double k = h + j; + float m = l * 8.75; + double n = (double) m; + double o = (double) a; + double p = n * o; + double q = h * p; + double r = q * 2.5; + double s = k - r; + double t = (double) c; + double v = o * u; + double w = o * v; + double x = h * w; + double y = h * x; + double z = y * 8.5; + asm volatile (NOP : : : "memory"); + asm volatile (NOP : : : "memory"); + return s - z; +} + +int +main () +{ + foo (3.0f, 2.0f, -1.0f, 9.0f, 1.0f, 2.0); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/guality/pr58791-5.c b/gcc/testsuite/gcc.dg/guality/pr58791-5.c new file mode 100644 index 00000000000..c2377691940 --- /dev/null +++ b/gcc/testsuite/gcc.dg/guality/pr58791-5.c @@ -0,0 +1,29 @@ +/* PR tree-optimization/58791 */ +/* { dg-do run } */ +/* { dg-options "-g" } */ + +#include "../nop.h" + +__attribute__((noinline, noclone)) unsigned int +foo (unsigned int a0, unsigned int a1, unsigned int a2, + unsigned int a3, unsigned int a4) +{ + unsigned int b0, b1, b2, b3, b4, e; + /* this can be optimized to four additions... */ + b4 = a4 + a3 + a2 + a1 + a0; /* { dg-final { gdb-test pr58791-5.c:20 "b4" "4681" } } */ + b3 = a3 + a2 + a1 + a0; /* { dg-final { gdb-test pr58791-5.c:20 "b3" "585" } } */ + b2 = a2 + a1 + a0; /* { dg-final { gdb-test pr58791-5.c:20 "b2" "73" } } */ + b1 = a1 + a0; /* { dg-final { gdb-test pr58791-5.c:20 "b1" "9" } } */ + /* This is actually 0 */ + e = b4 - b3 + b2 - b1 - a4 - a2; /* { dg-final { gdb-test pr58791-5.c:20 "e" "0" } } */ + asm volatile (NOP : : : "memory"); + asm volatile (NOP : : : "memory"); + return e; +} + +int +main () +{ + foo (1, 8, 64, 512, 4096); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/iec-559-macros-1.c b/gcc/testsuite/gcc.dg/iec-559-macros-1.c new file mode 100644 index 00000000000..bd5d037afc4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/iec-559-macros-1.c @@ -0,0 +1,16 @@ +/* Test __GCC_IEC_559 and __GCC_IEC_559_COMPLEX macros values. */ +/* { dg-do preprocess } */ +/* { dg-options "" } */ + +#ifndef __GCC_IEC_559 +# error "__GCC_IEC_559 not defined" +#endif +#ifndef __GCC_IEC_559_COMPLEX +# error "__GCC_IEC_559_COMPLEX not defined" +#endif +#if __GCC_IEC_559_COMPLEX > __GCC_IEC_559 +# error "__GCC_IEC_559_COMPLEX > __GCC_IEC_559" +#endif +#if __GCC_IEC_559_COMPLEX < 0 +# error "__GCC_IEC_559_COMPLEX < 0" +#endif diff --git a/gcc/testsuite/gcc.dg/iec-559-macros-2.c b/gcc/testsuite/gcc.dg/iec-559-macros-2.c new file mode 100644 index 00000000000..5a28574ac99 --- /dev/null +++ b/gcc/testsuite/gcc.dg/iec-559-macros-2.c @@ -0,0 +1,23 @@ +/* Test __GCC_IEC_559 and __GCC_IEC_559_COMPLEX macros values. */ +/* { dg-do preprocess } */ +/* { dg-options "-funsafe-math-optimizations" } */ + +#ifndef __GCC_IEC_559 +# error "__GCC_IEC_559 not defined" +#endif +#ifndef __GCC_IEC_559_COMPLEX +# error "__GCC_IEC_559_COMPLEX not defined" +#endif +#if __GCC_IEC_559_COMPLEX > __GCC_IEC_559 +# error "__GCC_IEC_559_COMPLEX > __GCC_IEC_559" +#endif +#if __GCC_IEC_559_COMPLEX < 0 +# error "__GCC_IEC_559_COMPLEX < 0" +#endif + +#if __GCC_IEC_559 != 0 +# error "__GCC_IEC_559 != 0 with -funsafe-math-optimizations" +#endif +#if __GCC_IEC_559_COMPLEX != 0 +# error "__GCC_IEC_559_COMPLEX != 0 with -funsafe-math-optimizations" +#endif diff --git a/gcc/testsuite/gcc.dg/iec-559-macros-3.c b/gcc/testsuite/gcc.dg/iec-559-macros-3.c new file mode 100644 index 00000000000..5eeb34503fe --- /dev/null +++ b/gcc/testsuite/gcc.dg/iec-559-macros-3.c @@ -0,0 +1,23 @@ +/* Test __GCC_IEC_559 and __GCC_IEC_559_COMPLEX macros values. */ +/* { dg-do preprocess } */ +/* { dg-options "-freciprocal-math" } */ + +#ifndef __GCC_IEC_559 +# error "__GCC_IEC_559 not defined" +#endif +#ifndef __GCC_IEC_559_COMPLEX +# error "__GCC_IEC_559_COMPLEX not defined" +#endif +#if __GCC_IEC_559_COMPLEX > __GCC_IEC_559 +# error "__GCC_IEC_559_COMPLEX > __GCC_IEC_559" +#endif +#if __GCC_IEC_559_COMPLEX < 0 +# error "__GCC_IEC_559_COMPLEX < 0" +#endif + +#if __GCC_IEC_559 != 0 +# error "__GCC_IEC_559 != 0 with -freciprocal-math" +#endif +#if __GCC_IEC_559_COMPLEX != 0 +# error "__GCC_IEC_559_COMPLEX != 0 with -freciprocal-math" +#endif diff --git a/gcc/testsuite/gcc.dg/iec-559-macros-4.c b/gcc/testsuite/gcc.dg/iec-559-macros-4.c new file mode 100644 index 00000000000..7bf6b9c30bc --- /dev/null +++ b/gcc/testsuite/gcc.dg/iec-559-macros-4.c @@ -0,0 +1,23 @@ +/* Test __GCC_IEC_559 and __GCC_IEC_559_COMPLEX macros values. */ +/* { dg-do preprocess } */ +/* { dg-options "-ffinite-math-only" } */ + +#ifndef __GCC_IEC_559 +# error "__GCC_IEC_559 not defined" +#endif +#ifndef __GCC_IEC_559_COMPLEX +# error "__GCC_IEC_559_COMPLEX not defined" +#endif +#if __GCC_IEC_559_COMPLEX > __GCC_IEC_559 +# error "__GCC_IEC_559_COMPLEX > __GCC_IEC_559" +#endif +#if __GCC_IEC_559_COMPLEX < 0 +# error "__GCC_IEC_559_COMPLEX < 0" +#endif + +#if __GCC_IEC_559 != 0 +# error "__GCC_IEC_559 != 0 with -ffinite-math-only" +#endif +#if __GCC_IEC_559_COMPLEX != 0 +# error "__GCC_IEC_559_COMPLEX != 0 with -ffinite-math-only" +#endif diff --git a/gcc/testsuite/gcc.dg/iec-559-macros-5.c b/gcc/testsuite/gcc.dg/iec-559-macros-5.c new file mode 100644 index 00000000000..ea37474fd1e --- /dev/null +++ b/gcc/testsuite/gcc.dg/iec-559-macros-5.c @@ -0,0 +1,23 @@ +/* Test __GCC_IEC_559 and __GCC_IEC_559_COMPLEX macros values. */ +/* { dg-do preprocess } */ +/* { dg-options "-fno-signed-zeros" } */ + +#ifndef __GCC_IEC_559 +# error "__GCC_IEC_559 not defined" +#endif +#ifndef __GCC_IEC_559_COMPLEX +# error "__GCC_IEC_559_COMPLEX not defined" +#endif +#if __GCC_IEC_559_COMPLEX > __GCC_IEC_559 +# error "__GCC_IEC_559_COMPLEX > __GCC_IEC_559" +#endif +#if __GCC_IEC_559_COMPLEX < 0 +# error "__GCC_IEC_559_COMPLEX < 0" +#endif + +#if __GCC_IEC_559 != 0 +# error "__GCC_IEC_559 != 0 with -fno-signed-zeros" +#endif +#if __GCC_IEC_559_COMPLEX != 0 +# error "__GCC_IEC_559_COMPLEX != 0 with -fno-signed-zeros" +#endif diff --git a/gcc/testsuite/gcc.dg/iec-559-macros-6.c b/gcc/testsuite/gcc.dg/iec-559-macros-6.c new file mode 100644 index 00000000000..e2be757f86c --- /dev/null +++ b/gcc/testsuite/gcc.dg/iec-559-macros-6.c @@ -0,0 +1,23 @@ +/* Test __GCC_IEC_559 and __GCC_IEC_559_COMPLEX macros values. */ +/* { dg-do preprocess } */ +/* { dg-options "-fsingle-precision-constant" } */ + +#ifndef __GCC_IEC_559 +# error "__GCC_IEC_559 not defined" +#endif +#ifndef __GCC_IEC_559_COMPLEX +# error "__GCC_IEC_559_COMPLEX not defined" +#endif +#if __GCC_IEC_559_COMPLEX > __GCC_IEC_559 +# error "__GCC_IEC_559_COMPLEX > __GCC_IEC_559" +#endif +#if __GCC_IEC_559_COMPLEX < 0 +# error "__GCC_IEC_559_COMPLEX < 0" +#endif + +#if __GCC_IEC_559 != 0 +# error "__GCC_IEC_559 != 0 with -fsingle-precision-constant" +#endif +#if __GCC_IEC_559_COMPLEX != 0 +# error "__GCC_IEC_559_COMPLEX != 0 with -fsingle-precision-constant" +#endif diff --git a/gcc/testsuite/gcc.dg/iec-559-macros-7.c b/gcc/testsuite/gcc.dg/iec-559-macros-7.c new file mode 100644 index 00000000000..3b1f79172d7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/iec-559-macros-7.c @@ -0,0 +1,20 @@ +/* Test __GCC_IEC_559 and __GCC_IEC_559_COMPLEX macros values. */ +/* { dg-do preprocess } */ +/* { dg-options "-fcx-limited-range" } */ + +#ifndef __GCC_IEC_559 +# error "__GCC_IEC_559 not defined" +#endif +#ifndef __GCC_IEC_559_COMPLEX +# error "__GCC_IEC_559_COMPLEX not defined" +#endif +#if __GCC_IEC_559_COMPLEX > __GCC_IEC_559 +# error "__GCC_IEC_559_COMPLEX > __GCC_IEC_559" +#endif +#if __GCC_IEC_559_COMPLEX < 0 +# error "__GCC_IEC_559_COMPLEX < 0" +#endif + +#if __GCC_IEC_559_COMPLEX != 0 +# error "__GCC_IEC_559_COMPLEX != 0 with -fcx-limited-range" +#endif diff --git a/gcc/testsuite/gcc.dg/iec-559-macros-8.c b/gcc/testsuite/gcc.dg/iec-559-macros-8.c new file mode 100644 index 00000000000..1990b944dc5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/iec-559-macros-8.c @@ -0,0 +1,20 @@ +/* Test __GCC_IEC_559 and __GCC_IEC_559_COMPLEX macros values. */ +/* { dg-do preprocess } */ +/* { dg-options "-fcx-fortran-rules" } */ + +#ifndef __GCC_IEC_559 +# error "__GCC_IEC_559 not defined" +#endif +#ifndef __GCC_IEC_559_COMPLEX +# error "__GCC_IEC_559_COMPLEX not defined" +#endif +#if __GCC_IEC_559_COMPLEX > __GCC_IEC_559 +# error "__GCC_IEC_559_COMPLEX > __GCC_IEC_559" +#endif +#if __GCC_IEC_559_COMPLEX < 0 +# error "__GCC_IEC_559_COMPLEX < 0" +#endif + +#if __GCC_IEC_559_COMPLEX != 0 +# error "__GCC_IEC_559_COMPLEX != 0 with -fcx-fortran-rules" +#endif diff --git a/gcc/testsuite/gcc.dg/iec-559-macros-9.c b/gcc/testsuite/gcc.dg/iec-559-macros-9.c new file mode 100644 index 00000000000..6179a3bfe45 --- /dev/null +++ b/gcc/testsuite/gcc.dg/iec-559-macros-9.c @@ -0,0 +1,23 @@ +/* Test __GCC_IEC_559 and __GCC_IEC_559_COMPLEX macros values. */ +/* { dg-do preprocess { target i?86-*-linux* x86_64-*-linux* powerpc*-*-linux* } } */ +/* { dg-options "-std=c11" } */ + +#ifndef __GCC_IEC_559 +# error "__GCC_IEC_559 not defined" +#endif +#ifndef __GCC_IEC_559_COMPLEX +# error "__GCC_IEC_559_COMPLEX not defined" +#endif +#if __GCC_IEC_559_COMPLEX > __GCC_IEC_559 +# error "__GCC_IEC_559_COMPLEX > __GCC_IEC_559" +#endif +#if __GCC_IEC_559_COMPLEX < 0 +# error "__GCC_IEC_559_COMPLEX < 0" +#endif + +#if __GCC_IEC_559 < 2 +# error "__GCC_IEC_559 < 2" +#endif +#if __GCC_IEC_559_COMPLEX < 2 +# error "__GCC_IEC_559_COMPLEX < 2" +#endif diff --git a/gcc/testsuite/gcc.dg/ivdep.c b/gcc/testsuite/gcc.dg/ivdep.c new file mode 100644 index 00000000000..23d51de9fe3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/ivdep.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ + +/* PR other/33426 */ + +void foo(int n, int *a, int *b, int *c, int *d, int *e) { + int i, j; +#pragma GCC ivdep + for (i = 0; ; ++i) { /* { dg-error "missing loop condition in loop with 'GCC ivdep' pragma before ';' token" } */ + a[i] = b[i] + c[i]; + } +} diff --git a/gcc/testsuite/gcc.dg/plugin/finish_unit_plugin.c b/gcc/testsuite/gcc.dg/plugin/finish_unit_plugin.c index 26496a2e695..72d724063e4 100644 --- a/gcc/testsuite/gcc.dg/plugin/finish_unit_plugin.c +++ b/gcc/testsuite/gcc.dg/plugin/finish_unit_plugin.c @@ -6,6 +6,7 @@ #include "system.h" #include "coretypes.h" #include "tm.h" +#include "tree.h" #include "toplev.h" #include "basic-block.h" #include "gimple.h" diff --git a/gcc/testsuite/gcc.dg/plugin/ggcplug.c b/gcc/testsuite/gcc.dg/plugin/ggcplug.c index 3094b2ebb63..eb61ece4522 100644 --- a/gcc/testsuite/gcc.dg/plugin/ggcplug.c +++ b/gcc/testsuite/gcc.dg/plugin/ggcplug.c @@ -5,6 +5,7 @@ #include "system.h" #include "coretypes.h" #include "tm.h" +#include "tree.h" #include "toplev.h" #include "basic-block.h" #include "gimple.h" diff --git a/gcc/testsuite/gcc.dg/plugin/one_time_plugin.c b/gcc/testsuite/gcc.dg/plugin/one_time_plugin.c index c4dace5ab27..1e601a63c90 100644 --- a/gcc/testsuite/gcc.dg/plugin/one_time_plugin.c +++ b/gcc/testsuite/gcc.dg/plugin/one_time_plugin.c @@ -3,6 +3,7 @@ #include "gcc-plugin.h" #include "system.h" #include "coretypes.h" +#include "tree.h" #include "tm.h" #include "toplev.h" #include "gimple.h" diff --git a/gcc/testsuite/gcc.dg/plugin/selfassign.c b/gcc/testsuite/gcc.dg/plugin/selfassign.c index 7235089c7d3..5331f792cb2 100644 --- a/gcc/testsuite/gcc.dg/plugin/selfassign.c +++ b/gcc/testsuite/gcc.dg/plugin/selfassign.c @@ -7,6 +7,7 @@ #include "system.h" #include "coretypes.h" #include "tm.h" +#include "tree.h" #include "toplev.h" #include "basic-block.h" #include "gimple.h" diff --git a/gcc/testsuite/gcc.dg/plugin/start_unit_plugin.c b/gcc/testsuite/gcc.dg/plugin/start_unit_plugin.c index 852ab88bfc7..257aad85a8a 100644 --- a/gcc/testsuite/gcc.dg/plugin/start_unit_plugin.c +++ b/gcc/testsuite/gcc.dg/plugin/start_unit_plugin.c @@ -10,6 +10,7 @@ #include "system.h" #include "coretypes.h" #include "tm.h" +#include "tree.h" #include "toplev.h" #include "basic-block.h" #include "gimple.h" diff --git a/gcc/testsuite/gcc.dg/pr19340.c b/gcc/testsuite/gcc.dg/pr19340.c index 4a665910a91..c75d35d1d01 100644 --- a/gcc/testsuite/gcc.dg/pr19340.c +++ b/gcc/testsuite/gcc.dg/pr19340.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O1 -fschedule-insns2 -fsched2-use-superblocks" } */ -/* { dg-skip-if "No scheduling" { mmix-*-* cris-*-* crisv32-*-* fido-*-* m68k-*-* m32c-*-* avr-*-* moxie-*-* } { "*" } { "" } } */ +/* { dg-require-effective-target scheduling } */ extern double f (double x); diff --git a/gcc/testsuite/gcc.dg/pr30286.c b/gcc/testsuite/gcc.dg/pr30286.c index 9ec49b4231a..d35eacd807a 100644 --- a/gcc/testsuite/gcc.dg/pr30286.c +++ b/gcc/testsuite/gcc.dg/pr30286.c @@ -1,6 +1,7 @@ /* PR middle-end/30286 */ /* { dg-do run } */ /* { dg-options "-O2 -ftrapv" } */ +/* { dg-require-effective-target trapping } */ extern void abort (void); struct S { struct S *s; }; diff --git a/gcc/testsuite/gcc.dg/pr38364.c b/gcc/testsuite/gcc.dg/pr38364.c index 23f72de74ee..6b22e9d78e9 100644 --- a/gcc/testsuite/gcc.dg/pr38364.c +++ b/gcc/testsuite/gcc.dg/pr38364.c @@ -1,6 +1,7 @@ /* PR middle-end/38364 */ /* { dg-do run } */ /* { dg-options "-O2 -ftrapv" } */ +/* { dg-require-effective-target trapping } */ extern void abort (void); diff --git a/gcc/testsuite/gcc.dg/pr58805.c b/gcc/testsuite/gcc.dg/pr58805.c new file mode 100644 index 00000000000..dda0e4bdf4b --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr58805.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-tail-merge -fdump-tree-pre" } */ + +/* Type that matches the 'p' constraint. */ +#define TYPE void * + +static inline +void bar (TYPE *r) +{ + TYPE t; + __asm__ ("" : "=&p" (t), "=p" (*r)); +} + +void +foo (int n, TYPE *x, TYPE *y) +{ + if (n == 0) + bar (x); + else + bar (y); +} + +/* { dg-final { scan-tree-dump-times "__asm__" 2 "pre"} } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/torture/builtin-complex-1.c b/gcc/testsuite/gcc.dg/torture/builtin-complex-1.c index 20dc4c48a28..0d26c9cc707 100644 --- a/gcc/testsuite/gcc.dg/torture/builtin-complex-1.c +++ b/gcc/testsuite/gcc.dg/torture/builtin-complex-1.c @@ -1,6 +1,6 @@ /* Test __builtin_complex semantics. */ /* { dg-do run } */ -/* { dg-options "-std=c1x -pedantic-errors" } */ +/* { dg-options "-std=c11 -pedantic-errors" } */ /* { dg-add-options ieee } */ extern void exit (int); diff --git a/gcc/testsuite/gcc.dg/torture/pr58626.c b/gcc/testsuite/gcc.dg/torture/pr58626.c new file mode 100644 index 00000000000..1416384b7a6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr58626.c @@ -0,0 +1,20 @@ +/* { dg-do run } */ + +extern void abort (void); + +int a[8][6] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; +int b; + +int main(void) +{ + for (b = 0; b <= 1; b++) { + a[1][3] = 0; + int c; + for (c = 0; c <= 1; c++) { + a[c + 1][b] = a[c + 2][b]; + } + } + if (a[1][1] != 1) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr58779.c b/gcc/testsuite/gcc.dg/torture/pr58779.c new file mode 100644 index 00000000000..b0c0c869513 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr58779.c @@ -0,0 +1,12 @@ +/* { dg-do run } */ + +int a, c; + +int main () +{ + int e = -1; + short d = (c <= 0) ^ e; + if ((unsigned int) a - (a || d) <= (unsigned int) a) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr58830.c b/gcc/testsuite/gcc.dg/torture/pr58830.c new file mode 100644 index 00000000000..8081f8b2c27 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr58830.c @@ -0,0 +1,42 @@ +/* { dg-do run } */ +/* { dg-additional-options "-ftree-pre -ftree-partial-pre" } */ + +extern void abort (void); + +int b, c, d, f, g, h, i, j[6], *l = &b, *m, n, *o, r; +char k; + +static int +foo () +{ + char *p = &k; + + for (; d; d++) + if (i) + h = 0; + else + h = c || (r = 0); + + for (f = 0; f < 2; f++) + { + unsigned int q; + *l = 0; + if (n) + *m = g; + if (g) + o = 0; + for (q = -8; q >= 5; q++) + (*p)--; + } + + return 0; +} + +int +main () +{ + foo (); + if (j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[j[0]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] ^ (k & 15)] != 0) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/restrict-2.c b/gcc/testsuite/gcc.dg/torture/restrict-2.c new file mode 100644 index 00000000000..ec51ade6163 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/restrict-2.c @@ -0,0 +1,27 @@ +/* { dg-do run } */ + +extern void abort (void); + +static inline void +foo (int * p) +{ + int * __restrict pr = p; + *pr = 1; +} + +int __attribute__((noinline,noclone)) +bar (int *q) +{ + int * __restrict qr = q; + *qr = 0; + foo (qr); + return *qr; +} + +int main() +{ + int i; + if (bar (&i) != 1) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/restrict-3.c b/gcc/testsuite/gcc.dg/torture/restrict-3.c new file mode 100644 index 00000000000..d815b8076e6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/restrict-3.c @@ -0,0 +1,26 @@ +/* { dg-do run } */ + +extern void abort (void); + +static inline void +foo (int * __restrict pr) +{ + *pr = 1; +} + +int __attribute__((noinline,noclone)) +bar (int *q) +{ + int * __restrict qr = q; + *qr = 0; + foo (qr); + return *qr; +} + +int main() +{ + int i; + if (bar (&i) != 1) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/restrict-4.c b/gcc/testsuite/gcc.dg/torture/restrict-4.c new file mode 100644 index 00000000000..52994d48b2e --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/restrict-4.c @@ -0,0 +1,26 @@ +/* { dg-do run } */ + +extern void abort (void); + +static inline void +foo (int * p) +{ + int * __restrict pr = p; + *pr = 1; +} + +int __attribute__((noinline,noclone)) +bar (int * __restrict qr) +{ + *qr = 0; + foo (qr); + return *qr; +} + +int main() +{ + int i; + if (bar (&i) != 1) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/restrict-5.c b/gcc/testsuite/gcc.dg/torture/restrict-5.c new file mode 100644 index 00000000000..233a9075f96 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/restrict-5.c @@ -0,0 +1,25 @@ +/* { dg-do run } */ + +extern void abort (void); + +static inline void +foo (int * __restrict pr) +{ + *pr = 1; +} + +int __attribute__((noinline,noclone)) +bar (int * __restrict qr) +{ + *qr = 0; + foo (qr); + return *qr; +} + +int main() +{ + int i; + if (bar (&i) != 1) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-23.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-23.c new file mode 100644 index 00000000000..9d0dd32061f --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-23.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +typedef struct A { int i; double d; } A; + +void f1 (const char *c) +{ + A *s = (A*) __builtin_malloc (sizeof (A)); + double *p = &s->d; + s->i = 42; + __builtin_memcpy (p, c, sizeof (double)); + int j = s->i; + if (j != 42) __builtin_abort(); +} + +/* { dg-final { scan-tree-dump-not "abort" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-24.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-24.c new file mode 100644 index 00000000000..0edd51f85cd --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-24.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +void f (const char *c, int *i) +{ + *i = 42; + __builtin_memcpy (i + 1, c, sizeof (int)); + if (*i != 42) __builtin_abort(); +} + +extern void keepit (); +void g (const char *c, int *i) +{ + *i = 33; + __builtin_memcpy (i - 1, c, 3 * sizeof (int)); + if (*i != 33) keepit(); +} + +/* { dg-final { scan-tree-dump-not "abort" "optimized" } } */ +/* { dg-final { scan-tree-dump "keepit" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-25.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-25.c new file mode 100644 index 00000000000..f5705d03cd9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-25.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +void f (long *p) { + *p = 42; + p[4] = 42; + __builtin_free (p); +} + +/* { dg-final { scan-tree-dump-not "= 42" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-9.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-9.c index dccea7b0506..a224788f5d8 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-9.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-9.c @@ -2,13 +2,14 @@ /* { dg-options "-O -fdump-tree-optimized" } */ int g(int,int); +int h(int); int f(int t, int c) { int d = 0; int e = 0; if (t) { - d = c+1; + d = h(c); e = t; } else d = 0, e = 0; diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-28.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-28.c index 3d10b49ccaf..2e999860148 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-28.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-28.c @@ -1,5 +1,5 @@ /* { dg-do run} */ -/* { dg-options "-O2 -fdump-tree-reassoc1-details" } */ +/* { dg-options "-O2" } */ #define LENGTH 4 void abort (void); @@ -30,8 +30,3 @@ int main() { abort (); return 0; } - -/* Verify one stmt has been moved to another BB to ensure correct dependences. */ -/* { dg-final { scan-tree-dump-times "to a different BB" 1 "reassoc1"} }*/ -/* { dg-final { scan-tree-dump-times "within same BB" 2 "reassoc1"} }*/ -/* { dg-final { cleanup-tree-dump "reassoc1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-3.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-3.c deleted file mode 100644 index 0d53f501d84..00000000000 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-3.c +++ /dev/null @@ -1,48 +0,0 @@ -/* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-dom1-details -fno-short-enums" } */ - -extern void abort (void) __attribute__ ((__noreturn__)); -union tree_node; -typedef union tree_node *tree; -enum tree_code -{ - VAR_DECL, - SSA_NAME, - MAX_TREE_CODES -}; -extern unsigned char tree_contains_struct[MAX_TREE_CODES][64]; -struct tree_base -{ - enum tree_code code:16; -}; -enum tree_node_structure_enum -{ - TS_DECL_COMMON -}; -struct tree_ssa_name -{ - tree var; -}; -union tree_node -{ - struct tree_base base; - struct tree_ssa_name ssa_name; -}; -long -expand_one_var (tree var, unsigned char toplevel, unsigned char really_expand) -{ - tree origvar = var; - var = var->ssa_name.var; - if (((enum tree_code) (origvar)->base.code) == SSA_NAME - && !((var->base.code != VAR_DECL))) - abort (); - if ((var->base.code) != VAR_DECL && ((origvar)->base.code) != SSA_NAME) - ; - else if (tree_contains_struct[(var->base.code)][(TS_DECL_COMMON)] != 1) - abort (); -} -/* We should thread the jump, through an intermediate block. */ -/* { dg-final { scan-tree-dump-times "Threaded" 2 "dom1"} } */ -/* { dg-final { scan-tree-dump-times "Registering jump thread: \\(.*\\) incoming edge; \\(.*\\) joiner; \\(.*\\) nocopy;" 1 "dom1"} } */ -/* { dg-final { cleanup-tree-dump "dom1" } } */ - diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-1.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-1.c new file mode 100644 index 00000000000..56c936daccd --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-1.c @@ -0,0 +1,14 @@ +/* { dg-do compile { target { ! "m68k*-*-* mmix*-*-* mep*-*-* bfin*-*-* v850*-*-* picochip*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-*"} } } */ + +/* { dg-options "-O2 -g -fdump-tree-optimized" } */ +/* { dg-additional-options "-mbranch-cost=2" { target avr-*-* } } */ + +int t (int a, int b) +{ + if (a > 0) + if (b > 0) + return 0; + return 1; +} +/* { dg-final { scan-tree-dump "\&" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-2.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-2.c new file mode 100644 index 00000000000..3273bcc5f38 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-2.c @@ -0,0 +1,17 @@ +/* { dg-do compile { target { ! "m68k*-*-* mmix*-*-* mep*-*-* bfin*-*-* v850*-*-* picochip*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-*"} } } */ + +/* { dg-options "-O2 -g -fdump-tree-optimized" } */ +/* { dg-additional-options "-mbranch-cost=2" { target avr-*-* } } */ + +int t (int a, int b) +{ + if (a > 0) + goto L1; + if (b > 0) + goto L1; + return 0; +L1: + return 1; +} +/* { dg-final { scan-tree-dump "\|" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-3.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-3.c new file mode 100644 index 00000000000..500cb011708 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-3.c @@ -0,0 +1,20 @@ +/* { dg-do compile { target { ! "m68k*-*-* mmix*-*-* mep*-*-* bfin*-*-* v850*-*-* picochip*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-*"} } } */ + +/* { dg-options "-O2 -g -fdump-tree-optimized" } */ +/* { dg-additional-options "-mbranch-cost=2" { target avr-*-* } } */ + +int t (int a, int b) +{ + if (a > 0) + goto L1; + else + goto L2; +L1: + if (b > 0) + goto L2; + return 5; +L2: + return 6; +} +/* { dg-final { scan-tree-dump "\|" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-4.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-4.c new file mode 100644 index 00000000000..8b8710115c0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-4.c @@ -0,0 +1,18 @@ +/* { dg-do compile { target { ! "m68k*-*-* mmix*-*-* mep*-*-* bfin*-*-* v850*-*-* picochip*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-*"} } } */ + +/* { dg-options "-O2 -g -fdump-tree-optimized" } */ +/* { dg-additional-options "-mbranch-cost=2" { target avr-*-* } } */ + +int t (int a, int b) +{ + if (a > 0) + goto L1; + if (b > 0) + goto L2; +L1: + return 0; +L2: + return 1; +} +/* { dg-final { scan-tree-dump "\&" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-5.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-5.c new file mode 100644 index 00000000000..2aa225bd433 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-5.c @@ -0,0 +1,13 @@ +/* { dg-do compile { target { ! "m68k*-*-* mmix*-*-* mep*-*-* bfin*-*-* v850*-*-* picochip*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-*"} } } */ + +/* { dg-options "-O2 -g -fdump-tree-optimized" } */ +/* { dg-additional-options "-mbranch-cost=2" { target avr-*-* } } */ + +int t (int a, int b, int c) +{ + if (a > 0 && b > 0 && c > 0) + return 0; + return 1; +} +/* { dg-final { scan-tree-dump-times "\&" 2 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-6.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-6.c new file mode 100644 index 00000000000..659e8164beb --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-6.c @@ -0,0 +1,13 @@ +/* { dg-do compile { target { ! "m68k*-*-* mmix*-*-* mep*-*-* bfin*-*-* v850*-*-* picochip*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-*"} } } */ + +/* { dg-options "-O2 -g -fdump-tree-optimized" } */ +/* { dg-additional-options "-mbranch-cost=2" { target avr-*-* } } */ + +int t (int a, int b, int c) +{ + if (a > 0 || b > 0 || c > 0) + return 0; + return 1; +} +/* { dg-final { scan-tree-dump-times "\\|" 2 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/utf-cvt.c b/gcc/testsuite/gcc.dg/utf-cvt.c index 7f51179eeb4..d6f18eeade7 100644 --- a/gcc/testsuite/gcc.dg/utf-cvt.c +++ b/gcc/testsuite/gcc.dg/utf-cvt.c @@ -1,7 +1,7 @@ /* Contributed by Kris Van Hees <kris.van.hees@oracle.com> */ /* Test the char16_t and char32_t promotion rules. */ /* { dg-do compile } */ -/* { dg-excess-errors "short and int are 16bit" { target { "avr-*-*" } } } */ +/* { dg-require-effective-target int32plus } */ /* { dg-options "-std=gnu99 -Wall -Wconversion -Wsign-conversion" } */ typedef __CHAR16_TYPE__ char16_t; diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-32.c b/gcc/testsuite/gcc.dg/vect/bb-slp-32.c index 765f842ec8c..6d69d15c965 100644 --- a/gcc/testsuite/gcc.dg/vect/bb-slp-32.c +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-32.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target vect_int } */ -/* { dg-additional-options "-fvect-cost-model" } */ +/* { dg-additional-options "-fvect-cost-model=dynamic" } */ void bar (int *); int foo (int *p) diff --git a/gcc/testsuite/gcc.dg/vect/costmodel/i386/i386-costmodel-vect.exp b/gcc/testsuite/gcc.dg/vect/costmodel/i386/i386-costmodel-vect.exp index da80bba9d6c..93ad2759468 100644 --- a/gcc/testsuite/gcc.dg/vect/costmodel/i386/i386-costmodel-vect.exp +++ b/gcc/testsuite/gcc.dg/vect/costmodel/i386/i386-costmodel-vect.exp @@ -28,7 +28,7 @@ if { ![istarget i?86*-*-*] && ![istarget x86_64-*-*] } then { set DEFAULT_VECTCFLAGS "" # These flags are used for all targets. -lappend DEFAULT_VECTCFLAGS "-O2" "-ftree-vectorize" "-fvect-cost-model" +lappend DEFAULT_VECTCFLAGS "-O2" "-ftree-vectorize" "-fvect-cost-model=dynamic" # If the target system supports vector instructions, the default action # for a test is 'run', otherwise it's 'compile'. Save current default. diff --git a/gcc/testsuite/gcc.dg/vect/costmodel/ppc/ppc-costmodel-vect.exp b/gcc/testsuite/gcc.dg/vect/costmodel/ppc/ppc-costmodel-vect.exp index 010d7459a1e..f77caec669f 100644 --- a/gcc/testsuite/gcc.dg/vect/costmodel/ppc/ppc-costmodel-vect.exp +++ b/gcc/testsuite/gcc.dg/vect/costmodel/ppc/ppc-costmodel-vect.exp @@ -33,7 +33,7 @@ if ![is-effective-target powerpc_altivec_ok] { set DEFAULT_VECTCFLAGS "" # These flags are used for all targets. -lappend DEFAULT_VECTCFLAGS "-O2" "-ftree-vectorize" "-fvect-cost-model" "-fno-common" +lappend DEFAULT_VECTCFLAGS "-O2" "-ftree-vectorize" "-fvect-cost-model=dynamic" "-fno-common" # If the target system supports vector instructions, the default action # for a test is 'run', otherwise it's 'compile'. Save current default. diff --git a/gcc/testsuite/gcc.dg/vect/costmodel/spu/spu-costmodel-vect.exp b/gcc/testsuite/gcc.dg/vect/costmodel/spu/spu-costmodel-vect.exp index cb18c15fa59..b56e7c8a064 100644 --- a/gcc/testsuite/gcc.dg/vect/costmodel/spu/spu-costmodel-vect.exp +++ b/gcc/testsuite/gcc.dg/vect/costmodel/spu/spu-costmodel-vect.exp @@ -29,7 +29,7 @@ if { ![istarget spu*-*-*] } then { set DEFAULT_VECTCFLAGS "" # These flags are used for all targets. -lappend DEFAULT_VECTCFLAGS "-O2" "-ftree-vectorize" "-fvect-cost-model" +lappend DEFAULT_VECTCFLAGS "-O2" "-ftree-vectorize" "-fvect-cost-model=dynamic" # If the target system supports vector instructions, the default action # for a test is 'run', otherwise it's 'compile'. Save current default. diff --git a/gcc/testsuite/gcc.dg/vect/costmodel/x86_64/x86_64-costmodel-vect.exp b/gcc/testsuite/gcc.dg/vect/costmodel/x86_64/x86_64-costmodel-vect.exp index e32e33bb4fe..7afbf6a5238 100644 --- a/gcc/testsuite/gcc.dg/vect/costmodel/x86_64/x86_64-costmodel-vect.exp +++ b/gcc/testsuite/gcc.dg/vect/costmodel/x86_64/x86_64-costmodel-vect.exp @@ -29,7 +29,7 @@ if { (![istarget x86_64-*-*] && ![istarget i?86-*-*]) set DEFAULT_VECTCFLAGS "" # These flags are used for all targets. -lappend DEFAULT_VECTCFLAGS "-O2" "-ftree-vectorize" "-fvect-cost-model" +lappend DEFAULT_VECTCFLAGS "-O2" "-ftree-vectorize" "-fvect-cost-model=dynamic" # If the target system supports vector instructions, the default action # for a test is 'run', otherwise it's 'compile'. Save current default. diff --git a/gcc/testsuite/gcc.dg/vect/pr58508.c b/gcc/testsuite/gcc.dg/vect/pr58508.c index 6484a65c8d9..2db761e2627 100644 --- a/gcc/testsuite/gcc.dg/vect/pr58508.c +++ b/gcc/testsuite/gcc.dg/vect/pr58508.c @@ -1,5 +1,4 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -ftree-vectorize -fdump-tree-vect-details" } */ /* The GCC vectorizer generates loop versioning for the following loop diff --git a/gcc/testsuite/gcc.dg/vect/vect-align-3.c b/gcc/testsuite/gcc.dg/vect/vect-align-3.c new file mode 100644 index 00000000000..a8d3e485e6c --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-align-3.c @@ -0,0 +1,54 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target vect_int } */ + +int a[2048]; + +void +f1 (int x, int y) +{ + int i; + x &= -256; + y &= -256; + for (i = x + 256; i < y; i++) + a[i]++; +} + +void +f2 (int x, int y) +{ + int i; + if (x & 31) + __builtin_unreachable (); + if (y & 31) + __builtin_unreachable (); + for (i = x + 256; i < x + y; i++) + a[i]++; +} + +void +f3 (int x, int y) +{ + int i; + if (x % 256) + __builtin_unreachable (); + if (y % 256) + __builtin_unreachable (); + for (i = x + 256; i < x + y; i++) + a[i]++; +} + +void +f4 (int x, int y) +{ + int i; + if ((x % 256) != 0) + __builtin_unreachable (); + if ((y % 256) != 0) + __builtin_unreachable (); + for (i = x + 256; i < x + y; i++) + a[i]++; +} + +/* { dg-final { scan-tree-dump-not "vect_do_peeling_for_loop_bound" "vect" } } */ +/* { dg-final { scan-tree-dump-not "loop peeled for vectorization" "vect" } } */ +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-ivdep-1.c b/gcc/testsuite/gcc.dg/vect/vect-ivdep-1.c new file mode 100644 index 00000000000..f51b044dfc9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-ivdep-1.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target vect_float } */ +/* { dg-additional-options "-O3 -fopt-info-vec-optimized" } */ + +/* PR other/33426 */ +/* Testing whether #pragma ivdep is working. */ + +void foo(int n, int *a, int *b, int *c, int *d, int *e) { + int i, j; +#pragma GCC ivdep + for (i = 0; i < n; ++i) { + a[i] = b[i] + c[i]; + } +} + +/* { dg-message "loop vectorized" "" { target *-*-* } 0 } */ +/* { dg-bogus " version" "" { target *-*-* } 0 } */ +/* { dg-bogus " alias" "" { target *-*-* } 0 } */ +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-ivdep-2.c b/gcc/testsuite/gcc.dg/vect/vect-ivdep-2.c new file mode 100644 index 00000000000..ff9cb20ccb1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-ivdep-2.c @@ -0,0 +1,35 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target vect_float } */ +/* { dg-additional-options "-O3 -fopt-info-vec-optimized" } */ + +/* PR other/33426 */ +/* Testing whether #pragma ivdep is working. */ + +void foo(int n, int *a, int *b, int *c) { + int i; + i = 0; +#pragma GCC ivdep + while(i < n) + { + a[i] = b[i] + c[i]; + ++i; + } +} + +void bar(int n, int *a, int *b, int *c) { + int i; + i = 0; +#pragma GCC ivdep + do + { + a[i] = b[i] + c[i]; + ++i; + } + while(i < n); +} + + +/* { dg-message "loop vectorized" "" { target *-*-* } 0 } */ +/* { dg-bogus " version" "" { target *-*-* } 0 } */ +/* { dg-bogus " alias" "" { target *-*-* } 0 } */ +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vmx/eg-5.c b/gcc/testsuite/gcc.dg/vmx/eg-5.c index 0b37e69d194..eb43e846b79 100644 --- a/gcc/testsuite/gcc.dg/vmx/eg-5.c +++ b/gcc/testsuite/gcc.dg/vmx/eg-5.c @@ -7,10 +7,17 @@ matvecmul4 (vector float c0, vector float c1, vector float c2, /* Set result to a vector of f32 0's */ vector float result = ((vector float){0.,0.,0.,0.}); +#ifdef __LITTLE_ENDIAN__ + result = vec_madd (c0, vec_splat (v, 3), result); + result = vec_madd (c1, vec_splat (v, 2), result); + result = vec_madd (c2, vec_splat (v, 1), result); + result = vec_madd (c3, vec_splat (v, 0), result); +#else result = vec_madd (c0, vec_splat (v, 0), result); result = vec_madd (c1, vec_splat (v, 1), result); result = vec_madd (c2, vec_splat (v, 2), result); result = vec_madd (c3, vec_splat (v, 3), result); +#endif return result; } diff --git a/gcc/testsuite/gcc.dg/vmx/gcc-bug-i.c b/gcc/testsuite/gcc.dg/vmx/gcc-bug-i.c index 97ef1448819..3e0e6a0793e 100644 --- a/gcc/testsuite/gcc.dg/vmx/gcc-bug-i.c +++ b/gcc/testsuite/gcc.dg/vmx/gcc-bug-i.c @@ -13,12 +13,27 @@ #define DO_INLINE __attribute__ ((always_inline)) #define DONT_INLINE __attribute__ ((noinline)) +#ifdef __LITTLE_ENDIAN__ +static inline DO_INLINE int inline_me(vector signed short data) +{ + union {vector signed short v; signed short s[8];} u; + signed short x; + unsigned char x1, x2; + + u.v = data; + x = u.s[7]; + x1 = (x >> 8) & 0xff; + x2 = x & 0xff; + return ((x2 << 8) | x1); +} +#else static inline DO_INLINE int inline_me(vector signed short data) { union {vector signed short v; signed short s[8];} u; u.v = data; return u.s[7]; } +#endif static DONT_INLINE int foo(vector signed short data) { diff --git a/gcc/testsuite/gcc.dg/vmx/vec-set.c b/gcc/testsuite/gcc.dg/vmx/vec-set.c new file mode 100644 index 00000000000..fa11c47a122 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vmx/vec-set.c @@ -0,0 +1,14 @@ +#include "harness.h" + +vector short +vec_set (short m) +{ + return (vector short){m, 0, 0, 0, 0, 0, 0, 0}; +} + +static void test() +{ + check (vec_all_eq (vec_set (7), + ((vector short){7, 0, 0, 0, 0, 0, 0, 0})), + "vec_set"); +} diff --git a/gcc/testsuite/gcc.dg/wmul-1.c b/gcc/testsuite/gcc.dg/wmul-1.c new file mode 100644 index 00000000000..3e762f4c18c --- /dev/null +++ b/gcc/testsuite/gcc.dg/wmul-1.c @@ -0,0 +1,19 @@ +/* Not to fuse widening multiply with accumulate if the multiply has more than + one uses. + Note that for targets where pointer and int are of the same size or + widening multiply-and-accumulate is not available, this test just passes. */ + +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-widening_mul" } */ + +typedef int ArrT [10][10]; + +void +foo (ArrT Arr, int Idx) +{ + Arr[Idx][Idx] = 1; + Arr[Idx + 10][Idx] = 2; +} + +/* { dg-final { scan-tree-dump-not "WIDEN_MULT_PLUS_EXPR" "widening_mul" } } */ +/* { dg-final { cleanup-tree-dump "widening_mul" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/c-output-template-2.c b/gcc/testsuite/gcc.target/aarch64/c-output-template-2.c index 16ff58d9e28..ced96d04542 100644 --- a/gcc/testsuite/gcc.target/aarch64/c-output-template-2.c +++ b/gcc/testsuite/gcc.target/aarch64/c-output-template-2.c @@ -1,15 +1,9 @@ /* { dg-do compile } */ -struct tracepoint { - int dummy; - int state; -}; -static struct tracepoint tp; - void test (void) { - __asm__ ("@ %c0" : : "i" (&tp)); + __asm__ ("@ %c0" : : "S" (test)); } -/* { dg-final { scan-assembler "@ tp" } } */ +/* { dg-final { scan-assembler "@ test" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/c-output-template-3.c b/gcc/testsuite/gcc.target/aarch64/c-output-template-3.c index e332fe18fb9..c28837cd501 100644 --- a/gcc/testsuite/gcc.target/aarch64/c-output-template-3.c +++ b/gcc/testsuite/gcc.target/aarch64/c-output-template-3.c @@ -1,15 +1,10 @@ /* { dg-do compile } */ - -struct tracepoint { - int dummy; - int state; -}; -static struct tracepoint tp; +/* { dg-options "-Wno-pointer-arith" } */ void test (void) { - __asm__ ("@ %c0" : : "i" (&tp.state)); + __asm__ ("@ %c0" : : "S" (&test + 4)); } -/* { dg-final { scan-assembler "@ tp\\+4" } } */ +/* { dg-final { scan-assembler "@ test\\+4" } } */ diff --git a/gcc/testsuite/gcc.target/arc/jump-around-jump.c b/gcc/testsuite/gcc.target/arc/jump-around-jump.c new file mode 100644 index 00000000000..1b453283656 --- /dev/null +++ b/gcc/testsuite/gcc.target/arc/jump-around-jump.c @@ -0,0 +1,123 @@ +/* { dg-do compile } */ +/* { dg-options "-Os -mlock -mswape -mrtsc -fno-reorder-blocks" } */ + +/* This caused an ICE in arc_ifcvt when the 1->3 state change was not + implemented for TYPE_UNCOND_BRANCH in arc_ccfsm_post_advance. */ + +typedef long __kernel_long_t; +typedef __kernel_long_t __kernel_time_t; + +struct timespec { + __kernel_time_t tv_sec; + long tv_nsec; +}; + + +struct module; +struct device { + struct device *parent; +}; + +struct rtc_time { + int tm_sec; + int tm_min; + int tm_hour; + int tm_mday; + int tm_mon; + int tm_year; + int tm_wday; + int tm_yday; + int tm_isdst; +}; +struct rtc_wkalrm { + unsigned char enabled; + unsigned char pending; + struct rtc_time time; +}; + +struct rtc_class_ops { + int (*open)(struct device *); + void (*release)(struct device *); + int (*ioctl)(struct device *, unsigned int, unsigned long); + int (*read_time)(struct device *, struct rtc_time *); + int (*set_time)(struct device *, struct rtc_time *); + int (*read_alarm)(struct device *, struct rtc_wkalrm *); + int (*set_alarm)(struct device *, struct rtc_wkalrm *); + //int (*proc)(struct device *, struct seq_file *); + int (*set_mmss)(struct device *, unsigned long secs); + int (*read_callback)(struct device *, int data); + int (*alarm_irq_enable)(struct device *, unsigned int enabled); +}; + +struct rtc_device +{ + struct device dev; + struct module *owner; + + int id; + char name[20]; + + const struct rtc_class_ops *ops; + // struct mutex ops_lock; + + // struct cdev char_dev; + unsigned long flags; + + unsigned long irq_data; + //spinlock_t irq_lock; + //wait_queue_head_t irq_queue; + //struct fasync_struct *async_queue; + + //struct rtc_task *irq_task; + //spinlock_t irq_task_lock; + int irq_freq; + int max_user_freq; + + //struct timerqueue_head timerqueue; + //struct rtc_timer aie_timer; + //struct rtc_timer uie_rtctimer; + //struct hrtimer pie_timer; + int pie_enabled; + //struct work_struct irqwork; + + int uie_unsupported; + + + //struct work_struct uie_task; + //struct timer_list uie_timer; + + unsigned int oldsecs; + unsigned int uie_irq_active:1; + unsigned int stop_uie_polling:1; + unsigned int uie_task_active:1; + unsigned int uie_timer_active:1; + +}; + +extern void rtc_time_to_tm(unsigned long time, struct rtc_time *tm); +extern struct rtc_device *rtc_class_open(const char *name); +extern void rtc_class_close(struct rtc_device *rtc); + + +int rtc_set_ntp_time(struct timespec now) +{ + struct rtc_device *rtc; + struct rtc_time tm; + int err = -19; + + if (now.tv_nsec < (1000000000L >> 1)) + rtc_time_to_tm(now.tv_sec, &tm); + else + rtc_time_to_tm(now.tv_sec + 1, &tm); + + rtc = rtc_class_open("rtc0"); + if (rtc) { + + + if (rtc->ops && (rtc->ops->set_time || rtc->ops->set_mmss)) + err = rtc_set_time(rtc, &tm); + rtc_class_close(rtc); + } + + return err; +} diff --git a/gcc/testsuite/gcc.target/arm/lp1243022.c b/gcc/testsuite/gcc.target/arm/lp1243022.c new file mode 100644 index 00000000000..91a544d1b7d --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/lp1243022.c @@ -0,0 +1,201 @@ +/* { dg-do compile { target arm_thumb2 } } */ +/* { dg-options "-O2 -fdump-rtl-subreg2" } */ + +/* { dg-final { scan-rtl-dump "REG_INC" "subreg2" } } */ +/* { dg-final { cleanup-rtl-dump "subreg2" } } */ +struct device; +typedef unsigned int __u32; +typedef unsigned long long u64; +typedef __u32 __le32; +typedef u64 dma_addr_t; +typedef unsigned gfp_t; +int dev_warn (const struct device *dev, const char *fmt, ...); +struct usb_bus +{ + struct device *controller; +}; +struct usb_hcd +{ + struct usb_bus self; +}; +struct xhci_generic_trb +{ + __le32 field[4]; +}; +union xhci_trb +{ + struct xhci_generic_trb generic; +}; +struct xhci_segment +{ + union xhci_trb *trbs; + dma_addr_t dma; +}; +struct xhci_ring +{ + struct xhci_segment *first_seg; +}; +struct xhci_hcd +{ + struct xhci_ring *cmd_ring; + struct xhci_ring *event_ring; +}; +struct usb_hcd *xhci_to_hcd (struct xhci_hcd *xhci) +{ +} +dma_addr_t xhci_trb_virt_to_dma (struct xhci_segment * seg, + union xhci_trb * trb); +struct xhci_segment *trb_in_td (struct xhci_segment *start_seg, + dma_addr_t suspect_dma); +xhci_test_trb_in_td (struct xhci_hcd *xhci, struct xhci_segment *input_seg, + union xhci_trb *start_trb, union xhci_trb *end_trb, + dma_addr_t input_dma, struct xhci_segment *result_seg, + char *test_name, int test_number) +{ + unsigned long long start_dma; + unsigned long long end_dma; + struct xhci_segment *seg; + start_dma = xhci_trb_virt_to_dma (input_seg, start_trb); + end_dma = xhci_trb_virt_to_dma (input_seg, end_trb); + { + dev_warn (xhci_to_hcd (xhci)->self.controller, + "%d\n", test_number); + dev_warn (xhci_to_hcd (xhci)->self.controller, + "Expected seg %p, got seg %p\n", result_seg, seg); + } +} +xhci_check_trb_in_td_math (struct xhci_hcd *xhci, gfp_t mem_flags) +{ + struct + { + dma_addr_t input_dma; + struct xhci_segment *result_seg; + } + simple_test_vector[] = + { + { + 0, ((void *) 0) + } + , + { + xhci->event_ring->first_seg->dma - 16, ((void *) 0)} + , + { + xhci->event_ring->first_seg->dma - 1, ((void *) 0)} + , + { + xhci->event_ring->first_seg->dma, xhci->event_ring->first_seg} + , + { + xhci->event_ring->first_seg->dma + (64 - 1) * 16, + xhci->event_ring->first_seg + } + , + { + xhci->event_ring->first_seg->dma + (64 - 1) * 16 + 1, ((void *) 0)} + , + { + xhci->event_ring->first_seg->dma + (64) * 16, ((void *) 0)} + , + { + (dma_addr_t) (~0), ((void *) 0) + } + }; + struct + { + struct xhci_segment *input_seg; + union xhci_trb *start_trb; + union xhci_trb *end_trb; + dma_addr_t input_dma; + struct xhci_segment *result_seg; + } + complex_test_vector[] = + { + { + .input_seg = xhci->event_ring->first_seg,.start_trb = + xhci->event_ring->first_seg->trbs,.end_trb = + &xhci->event_ring->first_seg->trbs[64 - 1],.input_dma = + xhci->cmd_ring->first_seg->dma,.result_seg = ((void *) 0), + } + , + { + .input_seg = xhci->event_ring->first_seg,.start_trb = + xhci->event_ring->first_seg->trbs,.end_trb = + &xhci->cmd_ring->first_seg->trbs[64 - 1],.input_dma = + xhci->cmd_ring->first_seg->dma,.result_seg = ((void *) 0), + } + , + { + .input_seg = xhci->event_ring->first_seg,.start_trb = + xhci->cmd_ring->first_seg->trbs,.end_trb = + &xhci->cmd_ring->first_seg->trbs[64 - 1],.input_dma = + xhci->cmd_ring->first_seg->dma,.result_seg = ((void *) 0), + } + , + { + .input_seg = xhci->event_ring->first_seg,.start_trb = + &xhci->event_ring->first_seg->trbs[0],.end_trb = + &xhci->event_ring->first_seg->trbs[3],.input_dma = + xhci->event_ring->first_seg->dma + 4 * 16,.result_seg = ((void *) 0), + } + , + { + .input_seg = xhci->event_ring->first_seg,.start_trb = + &xhci->event_ring->first_seg->trbs[3],.end_trb = + &xhci->event_ring->first_seg->trbs[6],.input_dma = + xhci->event_ring->first_seg->dma + 2 * 16,.result_seg = ((void *) 0), + } + , + { + .input_seg = xhci->event_ring->first_seg,.start_trb = + &xhci->event_ring->first_seg->trbs[64 - 3],.end_trb = + &xhci->event_ring->first_seg->trbs[1],.input_dma = + xhci->event_ring->first_seg->dma + 2 * 16,.result_seg = ((void *) 0), + } + , + { + .input_seg = xhci->event_ring->first_seg,.start_trb = + &xhci->event_ring->first_seg->trbs[64 - 3],.end_trb = + &xhci->event_ring->first_seg->trbs[1],.input_dma = + xhci->event_ring->first_seg->dma + (64 - 4) * 16,.result_seg = + ((void *) 0), + } + , + { + .input_seg = xhci->event_ring->first_seg,.start_trb = + &xhci->event_ring->first_seg->trbs[64 - 3],.end_trb = + &xhci->event_ring->first_seg->trbs[1],.input_dma = + xhci->cmd_ring->first_seg->dma + 2 * 16,.result_seg = ((void *) 0), + } + }; + unsigned int num_tests; + int i, ret; + num_tests = + (sizeof (simple_test_vector) / sizeof ((simple_test_vector)[0]) + + (sizeof (struct + { + } + ))); + for (i = 0; i < num_tests; i++) + { + ret = + xhci_test_trb_in_td (xhci, xhci->event_ring->first_seg, + xhci->event_ring->first_seg->trbs, + &xhci->event_ring->first_seg->trbs[64 - 1], + simple_test_vector[i].input_dma, + simple_test_vector[i].result_seg, "Simple", i); + if (ret < 0) + return ret; + } + for (i = 0; i < num_tests; i++) + { + ret = + xhci_test_trb_in_td (xhci, complex_test_vector[i].input_seg, + complex_test_vector[i].start_trb, + complex_test_vector[i].end_trb, + complex_test_vector[i].input_dma, + complex_test_vector[i].result_seg, "Complex", i); + if (ret < 0) + return ret; + } +} diff --git a/gcc/testsuite/gcc.target/arm/neon-vcond-gt.c b/gcc/testsuite/gcc.target/arm/neon-vcond-gt.c index 86ccf95ada6..8e9f3785169 100644 --- a/gcc/testsuite/gcc.target/arm/neon-vcond-gt.c +++ b/gcc/testsuite/gcc.target/arm/neon-vcond-gt.c @@ -14,4 +14,4 @@ void foo (int ilast,float* w, float* w2) } /* { dg-final { scan-assembler "vcgt\\.f32\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+" } } */ -/* { dg-final { scan-assembler "vbit\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+" } } */ +/* { dg-final { scan-assembler "vbsl|vbit|vbif\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+" } } */ diff --git a/gcc/testsuite/gcc.target/arm/neon-vcond-ltgt.c b/gcc/testsuite/gcc.target/arm/neon-vcond-ltgt.c index acb23a947ff..c8306e364a3 100644 --- a/gcc/testsuite/gcc.target/arm/neon-vcond-ltgt.c +++ b/gcc/testsuite/gcc.target/arm/neon-vcond-ltgt.c @@ -15,4 +15,4 @@ void foo (int ilast,float* w, float* w2) /* { dg-final { scan-assembler-times "vcgt\\.f32\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+" 2 } } */ /* { dg-final { scan-assembler "vorr\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+" } } */ -/* { dg-final { scan-assembler "vbsl\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+" } } */ +/* { dg-final { scan-assembler "vbsl|vbit|vbif\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+" } } */ diff --git a/gcc/testsuite/gcc.target/arm/neon-vcond-unordered.c b/gcc/testsuite/gcc.target/arm/neon-vcond-unordered.c index c3e448d621b..3bb67d3afe3 100644 --- a/gcc/testsuite/gcc.target/arm/neon-vcond-unordered.c +++ b/gcc/testsuite/gcc.target/arm/neon-vcond-unordered.c @@ -16,4 +16,4 @@ void foo (int ilast,float* w, float* w2) /* { dg-final { scan-assembler "vcgt\\.f32\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+" } } */ /* { dg-final { scan-assembler "vcge\\.f32\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+" } } */ /* { dg-final { scan-assembler "vorr\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+" } } */ -/* { dg-final { scan-assembler "vbsl\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+" } } */ +/* { dg-final { scan-assembler "vbsl|vbit|vbif\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+,\[\\t \]*q\[0-9\]+" } } */ diff --git a/gcc/testsuite/gcc.target/arm/pr58784.c b/gcc/testsuite/gcc.target/arm/pr58784.c new file mode 100644 index 00000000000..e3ef950b499 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/pr58784.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-march=armv7-a -mfloat-abi=hard -mfpu=neon -marm -O2" } */ + +typedef struct __attribute__ ((__packed__)) +{ + char valueField[2]; +} ptp_tlv_t; +typedef struct __attribute__ ((__packed__)) +{ + char stepsRemoved; + ptp_tlv_t tlv[1]; +} ptp_message_announce_t; +int ptplib_send_announce(int sequenceId, int i) +{ + ptp_message_announce_t tx_packet; + ((long long *)tx_packet.tlv[0].valueField)[sequenceId] = i; + f(&tx_packet); +} diff --git a/gcc/testsuite/gcc.target/arm/require-pic-register-loc.c b/gcc/testsuite/gcc.target/arm/require-pic-register-loc.c new file mode 100644 index 00000000000..bd85e8640c2 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/require-pic-register-loc.c @@ -0,0 +1,29 @@ +/* { dg-do compile } */ +/* { dg-options "-g -fPIC" } */ + +void *v; +void a (void *x) { } +void b (void) { } + /* line 7. */ +int /* line 8. */ +main (int argc) /* line 9. */ +{ /* line 10. */ + if (argc == 12345) /* line 11. */ + { + a (v); + return 1; + } + b (); + + return 0; +} + +/* { dg-final { scan-assembler-not "\.loc 1 7 0" } } */ +/* { dg-final { scan-assembler-not "\.loc 1 8 0" } } */ +/* { dg-final { scan-assembler-not "\.loc 1 9 0" } } */ + +/* The loc at the start of the prologue. */ +/* { dg-final { scan-assembler-times "\.loc 1 10 0" 1 } } */ + +/* The loc at the end of the prologue, with the first user line. */ +/* { dg-final { scan-assembler-times "\.loc 1 11 0" 1 } } */ diff --git a/gcc/testsuite/gcc.target/avr/pr58545.c b/gcc/testsuite/gcc.target/avr/pr58545.c new file mode 100644 index 00000000000..d1b8461f7cf --- /dev/null +++ b/gcc/testsuite/gcc.target/avr/pr58545.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-Os -mmcu=atmega8" } */ + +typedef unsigned char uint8_t; +typedef unsigned int uint16_t; + +extern uint8_t f1 (const uint8_t*); +extern void f2 (uint8_t*, uint8_t); + +void func (uint16_t parameter, uint8_t *addr, uint8_t data) +{ + uint8_t status; + + status = f1 (addr + 8); + + addr++; + + if (*addr == parameter + 8) + *addr = parameter; + + f2 (addr, data); + f2 (addr + 8, status + 1); +} diff --git a/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-1.c b/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-1.c index e7eef6d7a90..1fe52bbb598 100644 --- a/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-1.c +++ b/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-1.c @@ -14,6 +14,6 @@ avx_test (void) c[i] = a[i] * b[i+3]; } -/* { dg-final { scan-assembler-not "avx_loadups256" } } */ -/* { dg-final { scan-assembler "sse_loadups" } } */ +/* { dg-final { scan-assembler-not "(avx_loadups256|vmovups\[^\n\r]*movv8sf_internal)" } } */ +/* { dg-final { scan-assembler "(sse_loadups|movv4sf_internal)" } } */ /* { dg-final { scan-assembler "vinsertf128" } } */ diff --git a/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-2.c b/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-2.c index e3ec8542e01..933f265eed5 100644 --- a/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-2.c +++ b/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-2.c @@ -10,6 +10,6 @@ avx_test (char **cp, char **ep) *ap++ = *cp++; } -/* { dg-final { scan-assembler-not "avx_loaddqu256" } } */ -/* { dg-final { scan-assembler "sse2_loaddqu" } } */ +/* { dg-final { scan-assembler-not "(avx_loaddqu256|vmovdqu\[^\n\r]*movv32qi_internal)" } } */ +/* { dg-final { scan-assembler "(sse2_loaddqu|vmovdqu\[^\n\r]*movv16qi_internal)" } } */ /* { dg-final { scan-assembler "vinsert.128" } } */ diff --git a/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-3.c b/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-3.c index b0e0e79bdd8..fe66e0b1713 100644 --- a/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-3.c +++ b/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-3.c @@ -14,6 +14,6 @@ avx_test (void) c[i] = a[i] * b[i+3]; } -/* { dg-final { scan-assembler-not "avx_loadupd256" } } */ -/* { dg-final { scan-assembler "sse2_loadupd" } } */ +/* { dg-final { scan-assembler-not "(avx_loadupd256|vmovupd\[^\n\r]*movv4df_internal)" } } */ +/* { dg-final { scan-assembler "(sse2_loadupd|vmovupd\[^\n\r]*movv2df_internal)" } } */ /* { dg-final { scan-assembler "vinsertf128" } } */ diff --git a/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-4.c b/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-4.c index c5afa061963..1d35ef57b48 100644 --- a/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-4.c +++ b/gcc/testsuite/gcc.target/i386/avx256-unaligned-load-4.c @@ -14,6 +14,6 @@ avx_test (void) b[i] = a[i+3] * 2; } -/* { dg-final { scan-assembler "avx_loadups256" } } */ -/* { dg-final { scan-assembler-not "sse_loadups" } } */ +/* { dg-final { scan-assembler "(avx_loadups256|vmovups\[^\n\r]*movv8sf_internal)" } } */ +/* { dg-final { scan-assembler-not "(sse_loadups|vmovups\[^\n\r]*movv4sf_internal)" } } */ /* { dg-final { scan-assembler-not "vinsertf128" } } */ diff --git a/gcc/testsuite/gcc.target/i386/fma_double_3.c b/gcc/testsuite/gcc.target/i386/fma_double_3.c index ac69684fee0..3a04777c6bf 100644 --- a/gcc/testsuite/gcc.target/i386/fma_double_3.c +++ b/gcc/testsuite/gcc.target/i386/fma_double_3.c @@ -8,11 +8,7 @@ #include "fma_3.h" -/* { dg-final { scan-assembler-times "vfmadd132sd" 4 } } */ -/* { dg-final { scan-assembler-times "vfmadd231sd" 4 } } */ -/* { dg-final { scan-assembler-times "vfmsub132sd" 4 } } */ -/* { dg-final { scan-assembler-times "vfmsub231sd" 4 } } */ -/* { dg-final { scan-assembler-times "vfnmadd132sd" 4 } } */ -/* { dg-final { scan-assembler-times "vfnmadd231sd" 4 } } */ -/* { dg-final { scan-assembler-times "vfnmsub132sd" 4 } } */ -/* { dg-final { scan-assembler-times "vfnmsub231sd" 4 } } */ +/* { dg-final { scan-assembler-times "vfmadd\[123\]+sd" 8 } } */ +/* { dg-final { scan-assembler-times "vfmsub\[132\]+sd" 8 } } */ +/* { dg-final { scan-assembler-times "vfnmadd\[132\]+sd" 8 } } */ +/* { dg-final { scan-assembler-times "vfnmsub\[132\]+sd" 8 } } */ diff --git a/gcc/testsuite/gcc.target/i386/fma_double_5.c b/gcc/testsuite/gcc.target/i386/fma_double_5.c index 3eca38c1494..640b552b0f0 100644 --- a/gcc/testsuite/gcc.target/i386/fma_double_5.c +++ b/gcc/testsuite/gcc.target/i386/fma_double_5.c @@ -8,7 +8,7 @@ #include "fma_5.h" -/* { dg-final { scan-assembler-times "vfmadd132sd" 8 } } */ -/* { dg-final { scan-assembler-times "vfmsub132sd" 8 } } */ -/* { dg-final { scan-assembler-times "vfnmadd132sd" 8 } } */ -/* { dg-final { scan-assembler-times "vfnmsub132sd" 8 } } */ +/* { dg-final { scan-assembler-times "vfmadd\[132\]+sd" 8 } } */ +/* { dg-final { scan-assembler-times "vfmsub\[132\]+sd" 8 } } */ +/* { dg-final { scan-assembler-times "vfnmadd\[132\]+sd" 8 } } */ +/* { dg-final { scan-assembler-times "vfnmsub\[132\]+sd" 8 } } */ diff --git a/gcc/testsuite/gcc.target/i386/fma_float_3.c b/gcc/testsuite/gcc.target/i386/fma_float_3.c index afb88b60745..7986ce4ee76 100644 --- a/gcc/testsuite/gcc.target/i386/fma_float_3.c +++ b/gcc/testsuite/gcc.target/i386/fma_float_3.c @@ -8,11 +8,7 @@ #include "fma_3.h" -/* { dg-final { scan-assembler-times "vfmadd132ss" 4 } } */ -/* { dg-final { scan-assembler-times "vfmadd231ss" 4 } } */ -/* { dg-final { scan-assembler-times "vfmsub132ss" 4 } } */ -/* { dg-final { scan-assembler-times "vfmsub231ss" 4 } } */ -/* { dg-final { scan-assembler-times "vfnmadd132ss" 4 } } */ -/* { dg-final { scan-assembler-times "vfnmadd231ss" 4 } } */ -/* { dg-final { scan-assembler-times "vfnmsub132ss" 4 } } */ -/* { dg-final { scan-assembler-times "vfnmsub231ss" 4 } } */ +/* { dg-final { scan-assembler-times "vfmadd\[132\]+ss" 8 } } */ +/* { dg-final { scan-assembler-times "vfmsub\[132\]+ss" 8 } } */ +/* { dg-final { scan-assembler-times "vfnmadd\[132\]+ss" 8 } } */ +/* { dg-final { scan-assembler-times "vfnmsub\[132\]+ss" 8 } } */ diff --git a/gcc/testsuite/gcc.target/i386/fma_float_5.c b/gcc/testsuite/gcc.target/i386/fma_float_5.c index cb067ca4a91..2105ae627f0 100644 --- a/gcc/testsuite/gcc.target/i386/fma_float_5.c +++ b/gcc/testsuite/gcc.target/i386/fma_float_5.c @@ -8,7 +8,7 @@ #include "fma_5.h" -/* { dg-final { scan-assembler-times "vfmadd132ss" 8 } } */ -/* { dg-final { scan-assembler-times "vfmsub132ss" 8 } } */ -/* { dg-final { scan-assembler-times "vfnmadd132ss" 8 } } */ -/* { dg-final { scan-assembler-times "vfnmsub132ss" 8 } } */ +/* { dg-final { scan-assembler-times "vfmadd\[132\]+ss" 8 } } */ +/* { dg-final { scan-assembler-times "vfmsub\[132\]+ss" 8 } } */ +/* { dg-final { scan-assembler-times "vfnmadd\[132\]+ss" 8 } } */ +/* { dg-final { scan-assembler-times "vfnmsub\[132\]+ss" 8 } } */ diff --git a/gcc/testsuite/gcc.target/i386/l_fma_double_1.c b/gcc/testsuite/gcc.target/i386/l_fma_double_1.c index 3ceababec10..1d99b4caa5b 100644 --- a/gcc/testsuite/gcc.target/i386/l_fma_double_1.c +++ b/gcc/testsuite/gcc.target/i386/l_fma_double_1.c @@ -9,19 +9,11 @@ typedef double adouble __attribute__((aligned(sizeof (double)))); #include "l_fma_1.h" -/* { dg-final { scan-assembler-times "vfmadd132pd" 4 } } */ -/* { dg-final { scan-assembler-times "vfmadd231pd" 4 } } */ -/* { dg-final { scan-assembler-times "vfmsub132pd" 4 } } */ -/* { dg-final { scan-assembler-times "vfmsub231pd" 4 } } */ -/* { dg-final { scan-assembler-times "vfnmadd132pd" 4 } } */ -/* { dg-final { scan-assembler-times "vfnmadd231pd" 4 } } */ -/* { dg-final { scan-assembler-times "vfnmsub132pd" 4 } } */ -/* { dg-final { scan-assembler-times "vfnmsub231pd" 4 } } */ -/* { dg-final { scan-assembler-times "vfmadd132sd" 28 } } */ -/* { dg-final { scan-assembler-times "vfmadd213sd" 28 } } */ -/* { dg-final { scan-assembler-times "vfmsub132sd" 28 } } */ -/* { dg-final { scan-assembler-times "vfmsub213sd" 28 } } */ -/* { dg-final { scan-assembler-times "vfnmadd132sd" 28 } } */ -/* { dg-final { scan-assembler-times "vfnmadd213sd" 28 } } */ -/* { dg-final { scan-assembler-times "vfnmsub132sd" 28 } } */ -/* { dg-final { scan-assembler-times "vfnmsub213sd" 28 } } */ +/* { dg-final { scan-assembler-times "vfmadd\[123\]+pd" 8 } } */ +/* { dg-final { scan-assembler-times "vfmsub\[123\]+pd" 8 } } */ +/* { dg-final { scan-assembler-times "vfnmadd\[123\]+pd" 8 } } */ +/* { dg-final { scan-assembler-times "vfnmsub\[123\]+pd" 8 } } */ +/* { dg-final { scan-assembler-times "vfmadd\[123\]+sd" 56 } } */ +/* { dg-final { scan-assembler-times "vfmsub\[123\]+sd" 56 } } */ +/* { dg-final { scan-assembler-times "vfnmadd\[123\]+sd" 56 } } */ +/* { dg-final { scan-assembler-times "vfnmsub\[123\]+sd" 56 } } */ diff --git a/gcc/testsuite/gcc.target/i386/l_fma_double_2.c b/gcc/testsuite/gcc.target/i386/l_fma_double_2.c index 713b24b7c27..e10110006f3 100644 --- a/gcc/testsuite/gcc.target/i386/l_fma_double_2.c +++ b/gcc/testsuite/gcc.target/i386/l_fma_double_2.c @@ -9,11 +9,11 @@ typedef double adouble __attribute__((aligned(sizeof (double)))); #include "l_fma_2.h" -/* { dg-final { scan-assembler-times "vfmadd132pd" 8 } } */ -/* { dg-final { scan-assembler-times "vfmsub132pd" 8 } } */ -/* { dg-final { scan-assembler-times "vfnmadd132pd" 8 } } */ -/* { dg-final { scan-assembler-times "vfnmsub132pd" 8 } } */ -/* { dg-final { scan-assembler-times "vfmadd132sd" 56 } } */ -/* { dg-final { scan-assembler-times "vfmsub132sd" 56 } } */ -/* { dg-final { scan-assembler-times "vfnmadd132sd" 56 } } */ -/* { dg-final { scan-assembler-times "vfnmsub132sd" 56 } } */ +/* { dg-final { scan-assembler-times "vfmadd\[123\]+pd" 8 } } */ +/* { dg-final { scan-assembler-times "vfmsub\[123\]+pd" 8 } } */ +/* { dg-final { scan-assembler-times "vfnmadd\[123\]+pd" 8 } } */ +/* { dg-final { scan-assembler-times "vfnmsub\[123\]+pd" 8 } } */ +/* { dg-final { scan-assembler-times "vfmadd\[123\]+sd" 56 } } */ +/* { dg-final { scan-assembler-times "vfmsub\[123\]+sd" 56 } } */ +/* { dg-final { scan-assembler-times "vfnmadd\[123\]+sd" 56 } } */ +/* { dg-final { scan-assembler-times "vfnmsub\[123\]+sd" 56 } } */ diff --git a/gcc/testsuite/gcc.target/i386/l_fma_double_3.c b/gcc/testsuite/gcc.target/i386/l_fma_double_3.c index 74e3e1c55df..f099e25f8ed 100644 --- a/gcc/testsuite/gcc.target/i386/l_fma_double_3.c +++ b/gcc/testsuite/gcc.target/i386/l_fma_double_3.c @@ -9,19 +9,11 @@ typedef double adouble __attribute__((aligned(sizeof (double)))); #include "l_fma_3.h" -/* { dg-final { scan-assembler-times "vfmadd132pd" 4 } } */ -/* { dg-final { scan-assembler-times "vfmadd231pd" 4 } } */ -/* { dg-final { scan-assembler-times "vfmsub132pd" 4 } } */ -/* { dg-final { scan-assembler-times "vfmsub231pd" 4 } } */ -/* { dg-final { scan-assembler-times "vfnmadd132pd" 4 } } */ -/* { dg-final { scan-assembler-times "vfnmadd231pd" 4 } } */ -/* { dg-final { scan-assembler-times "vfnmsub132pd" 4 } } */ -/* { dg-final { scan-assembler-times "vfnmsub231pd" 4 } } */ -/* { dg-final { scan-assembler-times "vfmadd132sd" 28 } } */ -/* { dg-final { scan-assembler-times "vfmadd213sd" 28 } } */ -/* { dg-final { scan-assembler-times "vfmsub132sd" 28 } } */ -/* { dg-final { scan-assembler-times "vfmsub213sd" 28 } } */ -/* { dg-final { scan-assembler-times "vfnmadd132sd" 28 } } */ -/* { dg-final { scan-assembler-times "vfnmadd213sd" 28 } } */ -/* { dg-final { scan-assembler-times "vfnmsub132sd" 28 } } */ -/* { dg-final { scan-assembler-times "vfnmsub213sd" 28 } } */ +/* { dg-final { scan-assembler-times "vfmadd\[123\]+pd" 8 } } */ +/* { dg-final { scan-assembler-times "vfmsub\[123\]+pd" 8 } } */ +/* { dg-final { scan-assembler-times "vfnmadd\[123\]+pd" 8 } } */ +/* { dg-final { scan-assembler-times "vfnmsub\[123\]+pd" 8 } } */ +/* { dg-final { scan-assembler-times "vfmadd\[123\]+sd" 56 } } */ +/* { dg-final { scan-assembler-times "vfmsub\[123\]+sd" 56 } } */ +/* { dg-final { scan-assembler-times "vfnmadd\[123\]+sd" 56 } } */ +/* { dg-final { scan-assembler-times "vfnmsub\[123\]+sd" 56 } } */ diff --git a/gcc/testsuite/gcc.target/i386/l_fma_double_4.c b/gcc/testsuite/gcc.target/i386/l_fma_double_4.c index d571aca1b01..969f31c7f35 100644 --- a/gcc/testsuite/gcc.target/i386/l_fma_double_4.c +++ b/gcc/testsuite/gcc.target/i386/l_fma_double_4.c @@ -9,11 +9,11 @@ typedef double adouble __attribute__((aligned(sizeof (double)))); #include "l_fma_4.h" -/* { dg-final { scan-assembler-times "vfmadd132pd" 8 } } */ -/* { dg-final { scan-assembler-times "vfmsub132pd" 8 } } */ -/* { dg-final { scan-assembler-times "vfnmadd132pd" 8 } } */ -/* { dg-final { scan-assembler-times "vfnmsub132pd" 8 } } */ -/* { dg-final { scan-assembler-times "vfmadd132sd" 56 } } */ -/* { dg-final { scan-assembler-times "vfmsub132sd" 56 } } */ -/* { dg-final { scan-assembler-times "vfnmadd132sd" 56 } } */ -/* { dg-final { scan-assembler-times "vfnmsub132sd" 56 } } */ +/* { dg-final { scan-assembler-times "vfmadd\[123\]+pd" 8 } } */ +/* { dg-final { scan-assembler-times "vfmsub\[123\]+pd" 8 } } */ +/* { dg-final { scan-assembler-times "vfnmadd\[123\]+pd" 8 } } */ +/* { dg-final { scan-assembler-times "vfnmsub\[123\]+pd" 8 } } */ +/* { dg-final { scan-assembler-times "vfmadd\[123\]+sd" 56 } } */ +/* { dg-final { scan-assembler-times "vfmsub\[123\]+sd" 56 } } */ +/* { dg-final { scan-assembler-times "vfnmadd\[123\]+sd" 56 } } */ +/* { dg-final { scan-assembler-times "vfnmsub\[123\]+sd" 56 } } */ diff --git a/gcc/testsuite/gcc.target/i386/l_fma_double_5.c b/gcc/testsuite/gcc.target/i386/l_fma_double_5.c index 56d86369bc3..85ccdd0da44 100644 --- a/gcc/testsuite/gcc.target/i386/l_fma_double_5.c +++ b/gcc/testsuite/gcc.target/i386/l_fma_double_5.c @@ -9,11 +9,11 @@ typedef double adouble __attribute__((aligned(sizeof (double)))); #include "l_fma_5.h" -/* { dg-final { scan-assembler-times "vfmadd132pd" 8 } } */ -/* { dg-final { scan-assembler-times "vfmsub132pd" 8 } } */ -/* { dg-final { scan-assembler-times "vfnmadd132pd" 8 } } */ -/* { dg-final { scan-assembler-times "vfnmsub132pd" 8 } } */ -/* { dg-final { scan-assembler-times "vfmadd132sd" 56 } } */ -/* { dg-final { scan-assembler-times "vfmsub132sd" 56 } } */ -/* { dg-final { scan-assembler-times "vfnmadd132sd" 56 } } */ -/* { dg-final { scan-assembler-times "vfnmsub132sd" 56 } } */ +/* { dg-final { scan-assembler-times "vfmadd\[123\]+pd" 8 } } */ +/* { dg-final { scan-assembler-times "vfmsub\[123\]+pd" 8 } } */ +/* { dg-final { scan-assembler-times "vfnmadd\[123\]+pd" 8 } } */ +/* { dg-final { scan-assembler-times "vfnmsub\[123\]+pd" 8 } } */ +/* { dg-final { scan-assembler-times "vfmadd\[123\]+sd" 56 } } */ +/* { dg-final { scan-assembler-times "vfmsub\[123\]+sd" 56 } } */ +/* { dg-final { scan-assembler-times "vfnmadd\[123\]+sd" 56 } } */ +/* { dg-final { scan-assembler-times "vfnmsub\[123\]+sd" 56 } } */ diff --git a/gcc/testsuite/gcc.target/i386/l_fma_double_6.c b/gcc/testsuite/gcc.target/i386/l_fma_double_6.c index f22763d6f99..019ed9ad028 100644 --- a/gcc/testsuite/gcc.target/i386/l_fma_double_6.c +++ b/gcc/testsuite/gcc.target/i386/l_fma_double_6.c @@ -9,11 +9,11 @@ typedef double adouble __attribute__((aligned(sizeof (double)))); #include "l_fma_6.h" -/* { dg-final { scan-assembler-times "vfmadd132pd" 8 } } */ -/* { dg-final { scan-assembler-times "vfmsub132pd" 8 } } */ -/* { dg-final { scan-assembler-times "vfnmadd132pd" 8 } } */ -/* { dg-final { scan-assembler-times "vfnmsub132pd" 8 } } */ -/* { dg-final { scan-assembler-times "vfmadd132sd" 56 } } */ -/* { dg-final { scan-assembler-times "vfmsub132sd" 56 } } */ -/* { dg-final { scan-assembler-times "vfnmadd132sd" 56 } } */ -/* { dg-final { scan-assembler-times "vfnmsub132sd" 56 } } */ +/* { dg-final { scan-assembler-times "vfmadd\[123\]+pd" 8 } } */ +/* { dg-final { scan-assembler-times "vfmsub\[123\]+pd" 8 } } */ +/* { dg-final { scan-assembler-times "vfnmadd\[123\]+pd" 8 } } */ +/* { dg-final { scan-assembler-times "vfnmsub\[123\]+pd" 8 } } */ +/* { dg-final { scan-assembler-times "vfmadd\[123\]+sd" 56 } } */ +/* { dg-final { scan-assembler-times "vfmsub\[123\]+sd" 56 } } */ +/* { dg-final { scan-assembler-times "vfnmadd\[123\]+sd" 56 } } */ +/* { dg-final { scan-assembler-times "vfnmsub\[123\]+sd" 56 } } */ diff --git a/gcc/testsuite/gcc.target/i386/l_fma_float_1.c b/gcc/testsuite/gcc.target/i386/l_fma_float_1.c index 4a7ca95930e..d1913d7683f 100644 --- a/gcc/testsuite/gcc.target/i386/l_fma_float_1.c +++ b/gcc/testsuite/gcc.target/i386/l_fma_float_1.c @@ -8,19 +8,11 @@ #include "l_fma_1.h" -/* { dg-final { scan-assembler-times "vfmadd132ps" 4 } } */ -/* { dg-final { scan-assembler-times "vfmadd231ps" 4 } } */ -/* { dg-final { scan-assembler-times "vfmsub132ps" 4 } } */ -/* { dg-final { scan-assembler-times "vfmsub231ps" 4 } } */ -/* { dg-final { scan-assembler-times "vfnmadd132ps" 4 } } */ -/* { dg-final { scan-assembler-times "vfnmadd231ps" 4 } } */ -/* { dg-final { scan-assembler-times "vfnmsub132ps" 4 } } */ -/* { dg-final { scan-assembler-times "vfnmsub231ps" 4 } } */ -/* { dg-final { scan-assembler-times "vfmadd132ss" 60 } } */ -/* { dg-final { scan-assembler-times "vfmadd213ss" 60 } } */ -/* { dg-final { scan-assembler-times "vfmsub132ss" 60 } } */ -/* { dg-final { scan-assembler-times "vfmsub213ss" 60 } } */ -/* { dg-final { scan-assembler-times "vfnmadd132ss" 60 } } */ -/* { dg-final { scan-assembler-times "vfnmadd213ss" 60 } } */ -/* { dg-final { scan-assembler-times "vfnmsub132ss" 60 } } */ -/* { dg-final { scan-assembler-times "vfnmsub213ss" 60 } } */ +/* { dg-final { scan-assembler-times "vfmadd\[123\]+ps" 8 } } */ +/* { dg-final { scan-assembler-times "vfmsub\[123\]+ps" 8 } } */ +/* { dg-final { scan-assembler-times "vfnmadd\[123\]+ps" 8 } } */ +/* { dg-final { scan-assembler-times "vfnmsub\[123\]+ps" 8 } } */ +/* { dg-final { scan-assembler-times "vfmadd\[123\]+ss" 120 } } */ +/* { dg-final { scan-assembler-times "vfmsub\[123\]+ss" 120 } } */ +/* { dg-final { scan-assembler-times "vfnmadd\[123\]+ss" 120 } } */ +/* { dg-final { scan-assembler-times "vfnmsub\[123\]+ss" 120 } } */ diff --git a/gcc/testsuite/gcc.target/i386/l_fma_float_2.c b/gcc/testsuite/gcc.target/i386/l_fma_float_2.c index 6377585bffe..5e0142545c8 100644 --- a/gcc/testsuite/gcc.target/i386/l_fma_float_2.c +++ b/gcc/testsuite/gcc.target/i386/l_fma_float_2.c @@ -8,11 +8,11 @@ #include "l_fma_2.h" -/* { dg-final { scan-assembler-times "vfmadd132ps" 8 } } */ -/* { dg-final { scan-assembler-times "vfmsub132ps" 8 } } */ -/* { dg-final { scan-assembler-times "vfnmadd132ps" 8 } } */ -/* { dg-final { scan-assembler-times "vfnmsub132ps" 8 } } */ -/* { dg-final { scan-assembler-times "vfmadd132ss" 120 } } */ -/* { dg-final { scan-assembler-times "vfmsub132ss" 120 } } */ -/* { dg-final { scan-assembler-times "vfnmadd132ss" 120 } } */ -/* { dg-final { scan-assembler-times "vfnmsub132ss" 120 } } */ +/* { dg-final { scan-assembler-times "vfmadd\[123\]+ps" 8 } } */ +/* { dg-final { scan-assembler-times "vfmsub\[123\]+ps" 8 } } */ +/* { dg-final { scan-assembler-times "vfnmadd\[123\]+ps" 8 } } */ +/* { dg-final { scan-assembler-times "vfnmsub\[123\]+ps" 8 } } */ +/* { dg-final { scan-assembler-times "vfmadd\[123\]+ss" 120 } } */ +/* { dg-final { scan-assembler-times "vfmsub\[123\]+ss" 120 } } */ +/* { dg-final { scan-assembler-times "vfnmadd\[123\]+ss" 120 } } */ +/* { dg-final { scan-assembler-times "vfnmsub\[123\]+ss" 120 } } */ diff --git a/gcc/testsuite/gcc.target/i386/l_fma_float_3.c b/gcc/testsuite/gcc.target/i386/l_fma_float_3.c index f3fa74f98bd..7b9e3f54528 100644 --- a/gcc/testsuite/gcc.target/i386/l_fma_float_3.c +++ b/gcc/testsuite/gcc.target/i386/l_fma_float_3.c @@ -8,19 +8,11 @@ #include "l_fma_3.h" -/* { dg-final { scan-assembler-times "vfmadd132ps" 4 } } */ -/* { dg-final { scan-assembler-times "vfmadd231ps" 4 } } */ -/* { dg-final { scan-assembler-times "vfmsub132ps" 4 } } */ -/* { dg-final { scan-assembler-times "vfmsub231ps" 4 } } */ -/* { dg-final { scan-assembler-times "vfnmadd132ps" 4 } } */ -/* { dg-final { scan-assembler-times "vfnmadd231ps" 4 } } */ -/* { dg-final { scan-assembler-times "vfnmsub132ps" 4 } } */ -/* { dg-final { scan-assembler-times "vfnmsub231ps" 4 } } */ -/* { dg-final { scan-assembler-times "vfmadd132ss" 60 } } */ -/* { dg-final { scan-assembler-times "vfmadd213ss" 60 } } */ -/* { dg-final { scan-assembler-times "vfmsub132ss" 60 } } */ -/* { dg-final { scan-assembler-times "vfmsub213ss" 60 } } */ -/* { dg-final { scan-assembler-times "vfnmadd132ss" 60 } } */ -/* { dg-final { scan-assembler-times "vfnmadd213ss" 60 } } */ -/* { dg-final { scan-assembler-times "vfnmsub132ss" 60 } } */ -/* { dg-final { scan-assembler-times "vfnmsub213ss" 60 } } */ +/* { dg-final { scan-assembler-times "vfmadd\[123\]+ps" 8 } } */ +/* { dg-final { scan-assembler-times "vfmsub\[123\]+ps" 8 } } */ +/* { dg-final { scan-assembler-times "vfnmadd\[123\]+ps" 8 } } */ +/* { dg-final { scan-assembler-times "vfnmsub\[123\]+ps" 8 } } */ +/* { dg-final { scan-assembler-times "vfmadd\[123\]+ss" 120 } } */ +/* { dg-final { scan-assembler-times "vfmsub\[123\]+ss" 120 } } */ +/* { dg-final { scan-assembler-times "vfnmadd\[123\]+ss" 120 } } */ +/* { dg-final { scan-assembler-times "vfnmsub\[123\]+ss" 120 } } */ diff --git a/gcc/testsuite/gcc.target/i386/l_fma_float_4.c b/gcc/testsuite/gcc.target/i386/l_fma_float_4.c index bacb01e7f3f..cc675c14aae 100644 --- a/gcc/testsuite/gcc.target/i386/l_fma_float_4.c +++ b/gcc/testsuite/gcc.target/i386/l_fma_float_4.c @@ -8,11 +8,11 @@ #include "l_fma_4.h" -/* { dg-final { scan-assembler-times "vfmadd132ps" 8 } } */ -/* { dg-final { scan-assembler-times "vfmsub132ps" 8 } } */ -/* { dg-final { scan-assembler-times "vfnmadd132ps" 8 } } */ -/* { dg-final { scan-assembler-times "vfnmsub132ps" 8 } } */ -/* { dg-final { scan-assembler-times "vfmadd132ss" 120 } } */ -/* { dg-final { scan-assembler-times "vfmsub132ss" 120 } } */ -/* { dg-final { scan-assembler-times "vfnmadd132ss" 120 } } */ -/* { dg-final { scan-assembler-times "vfnmsub132ss" 120 } } */ +/* { dg-final { scan-assembler-times "vfmadd\[123\]+ps" 8 } } */ +/* { dg-final { scan-assembler-times "vfmsub\[123\]+ps" 8 } } */ +/* { dg-final { scan-assembler-times "vfnmadd\[123\]+ps" 8 } } */ +/* { dg-final { scan-assembler-times "vfnmsub\[123\]+ps" 8 } } */ +/* { dg-final { scan-assembler-times "vfmadd\[123\]+ss" 120 } } */ +/* { dg-final { scan-assembler-times "vfmsub\[123\]+ss" 120 } } */ +/* { dg-final { scan-assembler-times "vfnmadd\[123\]+ss" 120 } } */ +/* { dg-final { scan-assembler-times "vfnmsub\[123\]+ss" 120 } } */ diff --git a/gcc/testsuite/gcc.target/i386/l_fma_float_5.c b/gcc/testsuite/gcc.target/i386/l_fma_float_5.c index a32fc41d9f9..ac0b361475a 100644 --- a/gcc/testsuite/gcc.target/i386/l_fma_float_5.c +++ b/gcc/testsuite/gcc.target/i386/l_fma_float_5.c @@ -8,11 +8,11 @@ #include "l_fma_5.h" -/* { dg-final { scan-assembler-times "vfmadd132ps" 8 } } */ -/* { dg-final { scan-assembler-times "vfmsub132ps" 8 } } */ -/* { dg-final { scan-assembler-times "vfnmadd132ps" 8 } } */ -/* { dg-final { scan-assembler-times "vfnmsub132ps" 8 } } */ -/* { dg-final { scan-assembler-times "vfmadd132ss" 120 } } */ -/* { dg-final { scan-assembler-times "vfmsub132ss" 120 } } */ -/* { dg-final { scan-assembler-times "vfnmadd132ss" 120 } } */ -/* { dg-final { scan-assembler-times "vfnmsub132ss" 120 } } */ +/* { dg-final { scan-assembler-times "vfmadd\[123\]+ps" 8 } } */ +/* { dg-final { scan-assembler-times "vfmsub\[123\]+ps" 8 } } */ +/* { dg-final { scan-assembler-times "vfnmadd\[123\]+ps" 8 } } */ +/* { dg-final { scan-assembler-times "vfnmsub\[123\]+ps" 8 } } */ +/* { dg-final { scan-assembler-times "vfmadd\[123\]+ss" 120 } } */ +/* { dg-final { scan-assembler-times "vfmsub\[123\]+ss" 120 } } */ +/* { dg-final { scan-assembler-times "vfnmadd\[123\]+ss" 120 } } */ +/* { dg-final { scan-assembler-times "vfnmsub\[123\]+ss" 120 } } */ diff --git a/gcc/testsuite/gcc.target/i386/l_fma_float_6.c b/gcc/testsuite/gcc.target/i386/l_fma_float_6.c index a7a74fb4222..c84ac1196b4 100644 --- a/gcc/testsuite/gcc.target/i386/l_fma_float_6.c +++ b/gcc/testsuite/gcc.target/i386/l_fma_float_6.c @@ -8,11 +8,11 @@ #include "l_fma_6.h" -/* { dg-final { scan-assembler-times "vfmadd132ps" 8 } } */ -/* { dg-final { scan-assembler-times "vfmsub132ps" 8 } } */ -/* { dg-final { scan-assembler-times "vfnmadd132ps" 8 } } */ -/* { dg-final { scan-assembler-times "vfnmsub132ps" 8 } } */ -/* { dg-final { scan-assembler-times "vfmadd132ss" 120 } } */ -/* { dg-final { scan-assembler-times "vfmsub132ss" 120 } } */ -/* { dg-final { scan-assembler-times "vfnmadd132ss" 120 } } */ -/* { dg-final { scan-assembler-times "vfnmsub132ss" 120 } } */ +/* { dg-final { scan-assembler-times "vfmadd\[123\]+ps" 8 } } */ +/* { dg-final { scan-assembler-times "vfmsub\[123\]+ps" 8 } } */ +/* { dg-final { scan-assembler-times "vfnmadd\[123\]+ps" 8 } } */ +/* { dg-final { scan-assembler-times "vfnmsub\[123\]+ps" 8 } } */ +/* { dg-final { scan-assembler-times "vfmadd\[123\]+ss" 120 } } */ +/* { dg-final { scan-assembler-times "vfmsub\[123\]+ss" 120 } } */ +/* { dg-final { scan-assembler-times "vfnmadd\[123\]+ss" 120 } } */ +/* { dg-final { scan-assembler-times "vfnmsub\[123\]+ss" 120 } } */ diff --git a/gcc/testsuite/gcc.target/i386/memset-vector_loop-1.c b/gcc/testsuite/gcc.target/i386/memset-vector_loop-1.c new file mode 100644 index 00000000000..ad0d130371b --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/memset-vector_loop-1.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=atom -minline-all-stringops -mstringop-strategy=vector_loop" } */ +/* { dg-final { scan-assembler-times "movdqa" 4 } } */ + +char a[2048]; +void t (void) +{ + __builtin_memset (a, 0, 2048); +} + + diff --git a/gcc/testsuite/gcc.target/i386/memset-vector_loop-2.c b/gcc/testsuite/gcc.target/i386/memset-vector_loop-2.c new file mode 100644 index 00000000000..f2ceb442c7b --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/memset-vector_loop-2.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=atom -minline-all-stringops -mstringop-strategy=vector_loop" } */ +/* { dg-final { scan-assembler-times "movdqa" 4} } */ + +char *a; +void t (void) +{ + __builtin_memset (a, 0, 2048); +} + diff --git a/gcc/testsuite/gcc.target/i386/pr30315.c b/gcc/testsuite/gcc.target/i386/pr30315.c index 998d5071e5c..557b4f75174 100644 --- a/gcc/testsuite/gcc.target/i386/pr30315.c +++ b/gcc/testsuite/gcc.target/i386/pr30315.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O2" } */ -/* { dg-final { scan-assembler-times "cmp" 4 } } */ +/* { dg-final { scan-assembler-not "cmp" } } */ extern void abort (void); int c; @@ -34,39 +34,10 @@ void pluscconly##t##C (T a, T b) \ } #define PLUSCCONLY(T, t) PLUSCCONLY1(T, t, a) PLUSCCONLY1(T, t, b) -#define MINUSCC(T, t) \ -T minuscc##t (T a, T b) \ -{ \ - T difference = a - b; \ - if (difference > a) \ - abort (); \ - return difference; \ -} - -#define DECCC(T, t) \ -T deccc##t (T a, T b) \ -{ \ - T difference = a - b; \ - if (difference > a) \ - c --; \ - return difference; \ -} - -#define MINUSCCONLY(T, t) \ -void minuscconly##t (T a, T b) \ -{ \ - T difference = a - b; \ - if (difference > a) \ - abort (); \ -} - #define TEST(T, t) \ PLUSCC(T, t) \ PLUSCCONLY(T, t) \ - INCCC(T, t) \ - MINUSCC(T, t) \ - MINUSCCONLY(T, t) \ - DECCC(T, t) + INCCC(T, t) TEST (unsigned long, l) TEST (unsigned int, i) @@ -84,14 +55,3 @@ unsigned long pluscczext##C (unsigned int a, unsigned int b) \ PLUSCCZEXT(a) PLUSCCZEXT(b) - -#define MINUSCCZEXT \ -unsigned long minuscczext (unsigned int a, unsigned int b) \ -{ \ - unsigned int difference = a - b; \ - if (difference > a) \ - abort (); \ - return difference; \ -} - -MINUSCCZEXT diff --git a/gcc/testsuite/gcc.target/i386/pr58679-1.c b/gcc/testsuite/gcc.target/i386/pr58679-1.c new file mode 100644 index 00000000000..91db8e63e7f --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr58679-1.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mavx" } */ + +typedef struct { char a; long long b; } S; + +S foo (S x, S y) +{ + S z; + + z.a = 0; + z.b = x.b / y.b; + return z; +} diff --git a/gcc/testsuite/gcc.target/i386/pr58679-2.c b/gcc/testsuite/gcc.target/i386/pr58679-2.c new file mode 100644 index 00000000000..b63545bc076 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr58679-2.c @@ -0,0 +1,7 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mavx" } */ + +int f (long long a, long long b) +{ + return (a * b) >> 16; +} diff --git a/gcc/testsuite/gcc.target/i386/pr58759.c b/gcc/testsuite/gcc.target/i386/pr58759.c new file mode 100644 index 00000000000..8257dde533d --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr58759.c @@ -0,0 +1,38 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + + +int a, b, c, d, e, f, h, l, m, n, k, o; +long long g; + +struct S +{ + int f1; + int f2; + int f3; + int f4; +}; + +static struct S i = {0,0,0,0}, j; + +void +foo () +{ + m = 1 & d; + n = b + c; + o = k >> 1; + f = 0 == e; +} + +int +main () +{ + for (; h < 1; h++) + { + g = 1 | (0 > 1 - a ? 0 : a); + foo (); + for (l = 0; l < 3; l++) + j = i; + } + return 0; +} diff --git a/gcc/testsuite/gcc.target/i386/vect-abs-s16.c b/gcc/testsuite/gcc.target/i386/vect-abs-s16.c new file mode 100644 index 00000000000..191ae3434e4 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/vect-abs-s16.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -msse2 -mno-sse3 -fdump-tree-vect-details" } */ + + +void test (short* a, short* b) +{ + int i; + for (i = 0; i < 10000; ++i) + a[i] = abs (b[i]); +} + + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */ +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.target/i386/vect-abs-s32.c b/gcc/testsuite/gcc.target/i386/vect-abs-s32.c new file mode 100644 index 00000000000..575e8efe0a8 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/vect-abs-s32.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -msse2 -mno-sse3 -fdump-tree-vect-details" } */ + + +void test (int* a, int* b) +{ + int i; + for (i = 0; i < 10000; ++i) + a[i] = abs (b[i]); +} + + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */ +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.target/i386/vect-abs-s8.c b/gcc/testsuite/gcc.target/i386/vect-abs-s8.c new file mode 100644 index 00000000000..3f3f3facb79 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/vect-abs-s8.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -msse2 -mno-sse3 -fdump-tree-vect-details" } */ + + +void test (char* a, char* b) +{ + int i; + for (i = 0; i < 10000; ++i) + a[i] = abs (b[i]); +} + + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */ +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.target/i386/vect-div-1.c b/gcc/testsuite/gcc.target/i386/vect-div-1.c new file mode 100644 index 00000000000..b3eed19c7d7 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/vect-div-1.c @@ -0,0 +1,43 @@ +/* { dg-do compile { target sse2 } } */ +/* { dg-options "-O2 -ftree-vectorize -fno-common -msse2" } */ + +unsigned short b[1024] = { 0 }; +int a[1024] = { 0 }; + +int +f1 (int x) +{ + int i; + for (i = 0; i < 1024; i++) + a[i] = (b[i] + 7) / 15; +} + +int +f2 (int x) +{ + int i; + for (i = 0; i < 1024; i++) + a[i] = (b[i] + 7) % 15; +} + +int +f3 (int x) +{ + int i; + for (i = 0; i < 1024; i++) + a[i] = (b[i] - 66000) / 15; +} + +int +f4 (int x) +{ + int i; + for (i = 0; i < 1024; i++) + a[i] = (b[i] - 66000) % 15; +} + +/* In f1 and f2, VRP can prove the first operand of division or modulo + is always non-negative, so there is no need to do >> 31 shift + etc. to check if it is. And in f3 and f4, VRP can prove it is always + negative. */ +/* { dg-final { scan-assembler-not "psrad\[^\n\r\]*\\\$31" } } */ diff --git a/gcc/testsuite/gcc.target/mips/nor.c b/gcc/testsuite/gcc.target/mips/nor.c new file mode 100644 index 00000000000..e71791ba31f --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/nor.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */ +/* { dg-final { scan-assembler-times "\tnor\t" 1 } } */ +/* { dg-final { scan-assembler-not "\tor" } } */ + +/* Test that we generate a 'nor' instruction and no 'or' instructions. */ + +NOMIPS16 int f (int a, int b) +{ + return ~(a|b); +} diff --git a/gcc/testsuite/gcc.target/powerpc/altivec-perm-1.c b/gcc/testsuite/gcc.target/powerpc/altivec-perm-1.c index ee5c5eee900..c3cf67e44f4 100644 --- a/gcc/testsuite/gcc.target/powerpc/altivec-perm-1.c +++ b/gcc/testsuite/gcc.target/powerpc/altivec-perm-1.c @@ -19,19 +19,6 @@ V b4(V x) return __builtin_shuffle(x, (V){ 4,5,6,7, 4,5,6,7, 4,5,6,7, 4,5,6,7, }); } -V p2(V x, V y) -{ - return __builtin_shuffle(x, y, - (V){ 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31 }); - -} - -V p4(V x, V y) -{ - return __builtin_shuffle(x, y, - (V){ 2, 3, 6, 7, 10, 11, 14, 15, 18, 19, 22, 23, 26, 27, 30, 31 }); -} - V h1(V x, V y) { return __builtin_shuffle(x, y, @@ -72,5 +59,3 @@ V l4(V x, V y) /* { dg-final { scan-assembler "vspltb" } } */ /* { dg-final { scan-assembler "vsplth" } } */ /* { dg-final { scan-assembler "vspltw" } } */ -/* { dg-final { scan-assembler "vpkuhum" } } */ -/* { dg-final { scan-assembler "vpkuwum" } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/altivec-perm-3.c b/gcc/testsuite/gcc.target/powerpc/altivec-perm-3.c new file mode 100644 index 00000000000..d0b671eac77 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/altivec-perm-3.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target powerpc_altivec_ok } */ +/* { dg-skip-if "" { powerpc*le-*-* } { "*" } { "" } } */ +/* { dg-options "-O -maltivec -mno-vsx" } */ + +typedef unsigned char V __attribute__((vector_size(16))); + +V p2(V x, V y) +{ + return __builtin_shuffle(x, y, + (V){ 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31 }); + +} + +V p4(V x, V y) +{ + return __builtin_shuffle(x, y, + (V){ 2, 3, 6, 7, 10, 11, 14, 15, 18, 19, 22, 23, 26, 27, 30, 31 }); +} + +/* { dg-final { scan-assembler-not "vperm" } } */ +/* { dg-final { scan-assembler "vpkuhum" } } */ +/* { dg-final { scan-assembler "vpkuwum" } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/crypto-builtin-1.c b/gcc/testsuite/gcc.target/powerpc/crypto-builtin-1.c index 87291954ee3..ce5da6a03d1 100644 --- a/gcc/testsuite/gcc.target/powerpc/crypto-builtin-1.c +++ b/gcc/testsuite/gcc.target/powerpc/crypto-builtin-1.c @@ -1,7 +1,7 @@ /* { dg-do compile { target { powerpc*-*-* } } } */ /* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ /* { dg-require-effective-target powerpc_p8vector_ok } */ -/* { dg-options "-mcpu=power8 -O2 -ftree-vectorize -fvect-cost-model -fno-unroll-loops -fno-unroll-all-loops" } */ +/* { dg-options "-mcpu=power8 -O2 -ftree-vectorize -fvect-cost-model=dynamic -fno-unroll-loops -fno-unroll-all-loops" } */ typedef vector unsigned long long crypto_t; typedef vector unsigned long long v2di_t; diff --git a/gcc/testsuite/gcc.target/powerpc/direct-move.h b/gcc/testsuite/gcc.target/powerpc/direct-move.h index 4e84fd678bb..c1709e6c7ef 100644 --- a/gcc/testsuite/gcc.target/powerpc/direct-move.h +++ b/gcc/testsuite/gcc.target/powerpc/direct-move.h @@ -1,5 +1,7 @@ /* Test functions for direct move support. */ +#include <math.h> +extern void abort (void); void __attribute__((__noinline__)) copy (TYPE *a, TYPE *b) @@ -107,7 +109,7 @@ const struct test_struct test_functions[] = { void __attribute__((__noinline__)) test_value (TYPE a) { - size_t i; + long i; for (i = 0; i < sizeof (test_functions) / sizeof (test_functions[0]); i++) { @@ -123,8 +125,7 @@ test_value (TYPE a) int main (void) { - size_t i; - long j; + long i,j; union { TYPE value; unsigned char bytes[sizeof (TYPE)]; diff --git a/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-1.c b/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-1.c index 6fd3acc2a9d..f0a68ec8845 100644 --- a/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-1.c +++ b/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-1.c @@ -1,7 +1,7 @@ /* { dg-do compile { target { powerpc*-*-* } } } */ /* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ /* { dg-require-effective-target powerpc_p8vector_ok } */ -/* { dg-options "-mcpu=power8 -O2 -ftree-vectorize -fvect-cost-model -fno-unroll-loops -fno-unroll-all-loops" } */ +/* { dg-options "-mcpu=power8 -O2 -ftree-vectorize -fvect-cost-model=dynamic -fno-unroll-loops -fno-unroll-all-loops" } */ #ifndef TYPE #define TYPE long long diff --git a/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-2.c b/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-2.c index 412040bfa05..394f416403f 100644 --- a/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-2.c +++ b/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-2.c @@ -1,7 +1,7 @@ /* { dg-do compile { target { powerpc*-*-* } } } */ /* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ /* { dg-require-effective-target powerpc_p8vector_ok } */ -/* { dg-options "-mcpu=power8 -O2 -ftree-vectorize -fvect-cost-model -fno-unroll-loops -fno-unroll-all-loops" } */ +/* { dg-options "-mcpu=power8 -O2 -ftree-vectorize -fvect-cost-model=dynamic -fno-unroll-loops -fno-unroll-all-loops" } */ #include <altivec.h> diff --git a/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-3.c b/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-3.c index b3f725f2d96..cb8a5b8afeb 100644 --- a/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-3.c +++ b/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-3.c @@ -1,7 +1,7 @@ /* { dg-do compile { target { powerpc*-*-* } } } */ /* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ /* { dg-require-effective-target powerpc_p8vector_ok } */ -/* { dg-options "-mcpu=power8 -O3 -ftree-vectorize -fvect-cost-model" } */ +/* { dg-options "-mcpu=power8 -O3 -ftree-vectorize -fvect-cost-model=dynamic" } */ #include <altivec.h> diff --git a/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-4.c b/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-4.c index 518a6aa5e64..8aaa6eacaab 100644 --- a/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-4.c +++ b/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-4.c @@ -1,7 +1,7 @@ /* { dg-do compile { target { powerpc*-*-* } } } */ /* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ /* { dg-require-effective-target powerpc_p8vector_ok } */ -/* { dg-options "-mcpu=power8 -O3 -ftree-vectorize -fvect-cost-model" } */ +/* { dg-options "-mcpu=power8 -O3 -ftree-vectorize -fvect-cost-model=dynamic" } */ #include <altivec.h> diff --git a/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-5.c b/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-5.c index 2e64551ff68..36de9eb9bf0 100644 --- a/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-5.c +++ b/gcc/testsuite/gcc.target/powerpc/p8vector-builtin-5.c @@ -1,7 +1,7 @@ /* { dg-do compile { target { powerpc*-*-* } } } */ /* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ /* { dg-require-effective-target powerpc_p8vector_ok } */ -/* { dg-options "-mcpu=power8 -O2 -ftree-vectorize -fvect-cost-model -fno-unroll-loops -fno-unroll-all-loops" } */ +/* { dg-options "-mcpu=power8 -O2 -ftree-vectorize -fvect-cost-model=dynamic -fno-unroll-loops -fno-unroll-all-loops" } */ #include <altivec.h> diff --git a/gcc/testsuite/gcc.target/powerpc/p8vector-vectorize-1.c b/gcc/testsuite/gcc.target/powerpc/p8vector-vectorize-1.c index 9a975bd6fe2..99b7ddfb2d9 100644 --- a/gcc/testsuite/gcc.target/powerpc/p8vector-vectorize-1.c +++ b/gcc/testsuite/gcc.target/powerpc/p8vector-vectorize-1.c @@ -1,7 +1,7 @@ /* { dg-do compile { target { powerpc*-*-* } } } */ /* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ /* { dg-require-effective-target powerpc_p8vector_ok } */ -/* { dg-options "-mcpu=power8 -O2 -ftree-vectorize -fvect-cost-model -fno-unroll-loops -fno-unroll-all-loops" } */ +/* { dg-options "-mcpu=power8 -O2 -ftree-vectorize -fvect-cost-model=dynamic -fno-unroll-loops -fno-unroll-all-loops" } */ #ifndef SIZE #define SIZE 1024 diff --git a/gcc/testsuite/gcc.target/powerpc/p8vector-vectorize-2.c b/gcc/testsuite/gcc.target/powerpc/p8vector-vectorize-2.c index 8feba0a1347..a29240754f6 100644 --- a/gcc/testsuite/gcc.target/powerpc/p8vector-vectorize-2.c +++ b/gcc/testsuite/gcc.target/powerpc/p8vector-vectorize-2.c @@ -1,7 +1,7 @@ /* { dg-do compile { target { powerpc*-*-* } } } */ /* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ /* { dg-require-effective-target powerpc_p8vector_ok } */ -/* { dg-options "-mcpu=power8 -O2 -ftree-vectorize -fvect-cost-model" } */ +/* { dg-options "-mcpu=power8 -O2 -ftree-vectorize -fvect-cost-model=dynamic" } */ #include <stddef.h> diff --git a/gcc/testsuite/gcc.target/powerpc/p8vector-vectorize-3.c b/gcc/testsuite/gcc.target/powerpc/p8vector-vectorize-3.c index 570f2e5991c..b86f7de816b 100644 --- a/gcc/testsuite/gcc.target/powerpc/p8vector-vectorize-3.c +++ b/gcc/testsuite/gcc.target/powerpc/p8vector-vectorize-3.c @@ -1,7 +1,7 @@ /* { dg-do compile { target { powerpc*-*-* } } } */ /* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ /* { dg-require-effective-target powerpc_p8vector_ok } */ -/* { dg-options "-mcpu=power8 -O2 -ftree-vectorize -fvect-cost-model" } */ +/* { dg-options "-mcpu=power8 -O2 -ftree-vectorize -fvect-cost-model=dynamic" } */ #include <stddef.h> diff --git a/gcc/testsuite/gcc.target/powerpc/p8vector-vectorize-4.c b/gcc/testsuite/gcc.target/powerpc/p8vector-vectorize-4.c index 90df8868051..1e886387ee7 100644 --- a/gcc/testsuite/gcc.target/powerpc/p8vector-vectorize-4.c +++ b/gcc/testsuite/gcc.target/powerpc/p8vector-vectorize-4.c @@ -1,7 +1,7 @@ /* { dg-do compile { target { powerpc*-*-* } } } */ /* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ /* { dg-require-effective-target powerpc_p8vector_ok } */ -/* { dg-options "-mcpu=power8 -O2 -ftree-vectorize -fvect-cost-model -fno-unroll-loops -fno-unroll-all-loops" } */ +/* { dg-options "-mcpu=power8 -O2 -ftree-vectorize -fvect-cost-model=dynamic -fno-unroll-loops -fno-unroll-all-loops" } */ #ifndef SIZE #define SIZE 1024 diff --git a/gcc/testsuite/gcc.target/powerpc/p8vector-vectorize-5.c b/gcc/testsuite/gcc.target/powerpc/p8vector-vectorize-5.c index 17563bf477a..0102510dadb 100644 --- a/gcc/testsuite/gcc.target/powerpc/p8vector-vectorize-5.c +++ b/gcc/testsuite/gcc.target/powerpc/p8vector-vectorize-5.c @@ -1,7 +1,7 @@ /* { dg-do compile { target { powerpc*-*-* } } } */ /* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ /* { dg-require-effective-target powerpc_p8vector_ok } */ -/* { dg-options "-mcpu=power8 -O2 -ftree-vectorize -fvect-cost-model -fno-unroll-loops -fno-unroll-all-loops" } */ +/* { dg-options "-mcpu=power8 -O2 -ftree-vectorize -fvect-cost-model=dynamic -fno-unroll-loops -fno-unroll-all-loops" } */ #ifndef SIZE #define SIZE 1024 diff --git a/gcc/testsuite/gcc.target/sh/cmpstr.c b/gcc/testsuite/gcc.target/sh/cmpstr.c new file mode 100644 index 00000000000..3e75e4a6434 --- /dev/null +++ b/gcc/testsuite/gcc.target/sh/cmpstr.c @@ -0,0 +1,27 @@ +/* Check that the __builtin_strcmp function is inlined with cmp/str + when optimizing for speed. */ +/* { dg-do compile { target "sh*-*-*" } } */ +/* { dg-options "-O2" } */ +/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" } { "" } } */ +/* { dg-final { scan-assembler-not "jmp" } } */ +/* { dg-final { scan-assembler-times "cmp/str" 3 } } */ +/* { dg-final { scan-assembler-times "tst\t#3" 2 } } */ + +test00 (const char *s1, const char *s2) +{ + return __builtin_strcmp (s1, s2); +} + +/* NB: This might change as further optimisation might detect the + max length and fallback to cmpstrn. */ +test01(const char *s2) +{ + return __builtin_strcmp ("abc", s2); +} + +/* Check that no test for alignment is needed. */ +test03(const char *s1, const char *s2) +{ + return __builtin_strcmp (__builtin_assume_aligned (s1, 4), + __builtin_assume_aligned (s2, 4)); +} diff --git a/gcc/testsuite/gcc.target/sh/cmpstrn.c b/gcc/testsuite/gcc.target/sh/cmpstrn.c new file mode 100644 index 00000000000..b2260f92110 --- /dev/null +++ b/gcc/testsuite/gcc.target/sh/cmpstrn.c @@ -0,0 +1,21 @@ +/* Check that the __builtin_strncmp function is inlined + when optimizing for speed. */ +/* { dg-do compile { target "sh*-*-*" } } */ +/* { dg-options "-O2" } */ +/* { dg-skip-if "" { "sh*-*-*" } { "-m5*" } { "" } } */ +/* { dg-final { scan-assembler-not "jmp" } } */ +/* { dg-final { scan-assembler-times "cmp/str" 1 } } */ + +/* Test that the cmp/str loop is optimized out. */ +test01(const char *s1, const char *s2, int n) +{ + return __builtin_strncmp (s1, "abcde", 3); +} + +/* Test that the cmp/str loop is used. */ +test02(const char *s1, const char *s2, int n) +{ + return __builtin_strncmp (s1, "abcdefghi", 8); +} + + diff --git a/gcc/testsuite/gcc.target/sh/pr52483-1.c b/gcc/testsuite/gcc.target/sh/pr52483-1.c index 6538a0570b2..e63d18279f8 100644 --- a/gcc/testsuite/gcc.target/sh/pr52483-1.c +++ b/gcc/testsuite/gcc.target/sh/pr52483-1.c @@ -1,9 +1,9 @@ -/* Check that loads from volatile mems don't result in redundant sign - extensions. */ +/* Check that loads/stores from/to volatile mems don't result in redundant + sign/zero extensions. */ /* { dg-do compile { target "sh*-*-*" } } */ -/* { dg-options "-O1" } */ +/* { dg-options "-O2" } */ /* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */ -/* { dg-final { scan-assembler-not "exts" } } */ +/* { dg-final { scan-assembler-not "exts|extu" } } */ int test_00 (volatile char* x) @@ -11,20 +11,44 @@ test_00 (volatile char* x) return *x; } +void +test_100 (volatile char* x, char y) +{ + *x = y; +} + int test_01 (volatile short* x) { return *x; } +void +test_101 (volatile unsigned char* x, unsigned char y) +{ + *x = y; +} + int test_02 (volatile unsigned char* x) { return *x == 0x80; } +void +test_102 (volatile short* x, short y) +{ + *x = y; +} + int test_03 (volatile unsigned short* x) { return *x == 0xFF80; } + +void +test_103 (volatile unsigned short* x, unsigned short y) +{ + *x = y; +} diff --git a/gcc/testsuite/gcc.target/sh/pr52483-2.c b/gcc/testsuite/gcc.target/sh/pr52483-2.c index 5681039db4d..e3626c2149e 100644 --- a/gcc/testsuite/gcc.target/sh/pr52483-2.c +++ b/gcc/testsuite/gcc.target/sh/pr52483-2.c @@ -1,14 +1,15 @@ -/* Check that loads from volatile mems utilize displacement addressing - modes and do not result in redundant sign extensions. */ +/* Check that loads/stores from/to volatile mems utilize displacement + addressing modes and do not result in redundant sign/zero extensions. */ /* { dg-do compile { target "sh*-*-*" } } */ /* { dg-options "-O1" } */ /* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */ -/* { dg-final { scan-assembler-times "@\\(5," 2 } } */ -/* { dg-final { scan-assembler-times "@\\(10," 2 } } */ -/* { dg-final { scan-assembler-times "@\\(20," 2 } } */ -/* { dg-final { scan-assembler-times "@\\(40," 2 } } */ -/* { dg-final { scan-assembler-times "@\\(44," 2 } } */ +/* { dg-final { scan-assembler-times "@\\(5," 4 } } */ +/* { dg-final { scan-assembler-times "@\\(10," 4 } } */ +/* { dg-final { scan-assembler-times "@\\(20," 4 } } */ +/* { dg-final { scan-assembler-times "@\\(40," 4 } } */ +/* { dg-final { scan-assembler-times "@\\(44," 4 } } */ /* { dg-final { scan-assembler-not "exts" } } */ +/* { dg-final { scan-assembler-times "extu|movu" 2 } } */ int test_00 (volatile char* x) @@ -16,35 +17,73 @@ test_00 (volatile char* x) return x[5]; } +void +test_100 (volatile char* x, char y) +{ + x[5] = y; +} + int test_01 (volatile short* x) { return x[5]; } +void +test_101 (volatile short* x, short y) +{ + x[5] = y; +} + int test_02 (volatile int* x) { return x[5]; } +void +test_102 (volatile int* x, int y) +{ + x[5] = y; +} + long long test_03 (volatile long long* x) { return x[5]; } +void +test_103 (volatile long long* x, long long y) +{ + x[5] = y; +} + unsigned int test_04 (volatile unsigned char* x) { + // expected 1x extu.b or movu.b return x[5]; } +void +test_104 (volatile unsigned char* x, unsigned char y) +{ + x[5] = y; +} + unsigned int test_05 (volatile unsigned short* x) { + // expected 1x extu.w or movu.w return x[5]; } + +void +test_105 (volatile unsigned short* x, unsigned short y) +{ + x[5] = y; +} unsigned int test_06 (volatile unsigned int* x) @@ -52,8 +91,20 @@ test_06 (volatile unsigned int* x) return x[5]; } +void +test_106 (volatile unsigned int* x, unsigned int y) +{ + x[5] = y; +} + unsigned long long test_07 (volatile unsigned long long* x) { return x[5]; } + +void +test_107 (volatile unsigned long long* x, unsigned long long y) +{ + x[5] = y; +} diff --git a/gcc/testsuite/gcc.target/sh/pr52483-3.c b/gcc/testsuite/gcc.target/sh/pr52483-3.c index 4d04193eb45..81b03c89b72 100644 --- a/gcc/testsuite/gcc.target/sh/pr52483-3.c +++ b/gcc/testsuite/gcc.target/sh/pr52483-3.c @@ -1,10 +1,10 @@ -/* Check that loads from volatile mems utilize indexed addressing - modes and do not result in redundant sign extensions. */ +/* Check that loads/stores from/to volatile mems utilize indexed addressing + modes and do not result in redundant sign/zero extensions. */ /* { dg-do compile { target "sh*-*-*" } } */ /* { dg-options "-O1" } */ /* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */ -/* { dg-final { scan-assembler-times "@\\(r0," 3 } } */ -/* { dg-final { scan-assembler-not "exts" } } */ +/* { dg-final { scan-assembler-times "@\\(r0," 6 } } */ +/* { dg-final { scan-assembler-not "exts|extu" } } */ int test_00 (volatile char* x, unsigned int y) @@ -12,14 +12,32 @@ test_00 (volatile char* x, unsigned int y) return x[y]; } +void +test_100 (volatile char* x, unsigned int y, char z) +{ + x[y] = z; +} + int test_01 (volatile short* x, unsigned int y) { return x[y]; } +void +test_101 (volatile short* x, unsigned int y, short z) +{ + x[y] = z; +} + int test_02 (volatile int* x, unsigned int y) { return x[y]; } + +int +test_102 (volatile int* x, unsigned int y, int z) +{ + x[y] = z; +} diff --git a/gcc/testsuite/gcc.target/sh/pr52483-4.c b/gcc/testsuite/gcc.target/sh/pr52483-4.c index 8bf8626f148..2f850c1bbfe 100644 --- a/gcc/testsuite/gcc.target/sh/pr52483-4.c +++ b/gcc/testsuite/gcc.target/sh/pr52483-4.c @@ -1,12 +1,18 @@ -/* Check that loads from volatile floating point mems utilize indexed - addressing modes. */ +/* Check that loads/stores from/to volatile floating point mems utilize + indexed addressing modes. */ /* { dg-do compile { target "sh*-*-*" } } */ /* { dg-options "-O1" } */ /* { dg-skip-if "" { "sh*-*-*" } { "-m1" "-m2" "-m3" "-m4al" "*nofpu" "-m4-340*" "-m4-400*" "-m4-500*" "-m5*" } { "" } } */ -/* { dg-final { scan-assembler-times "@\\(r0," 1 } } */ +/* { dg-final { scan-assembler-times "@\\(r0," 2 } } */ float test_00 (volatile float* x, unsigned int y) { return x[y]; } + +void +test_100 (volatile float* x, unsigned int y, float z) +{ + x[y] = z; +} diff --git a/gcc/testsuite/gcc.target/sh/pr54089-6.c b/gcc/testsuite/gcc.target/sh/pr54089-6.c index a12a0e93044..629a7644186 100644 --- a/gcc/testsuite/gcc.target/sh/pr54089-6.c +++ b/gcc/testsuite/gcc.target/sh/pr54089-6.c @@ -3,7 +3,7 @@ /* { dg-options "-O1" } */ /* { dg-skip-if "" { "sh*-*-*" } { "-m5*" } { "" } } */ /* { dg-final { scan-assembler-times "rotr" 2 } } */ -/* { dg-final { scan-assembler-times "rotl" 2 } } */ +/* { dg-final { scan-assembler-times "rotl" 3 } } */ int test_00 (int a) @@ -28,3 +28,9 @@ test_03 (int a) { return ((a >> 1) & 0x7FFFFFFF) | (a << 31); } + +int +test_04 (int a) +{ + return a + a + ((a >> 31) & 1); +} diff --git a/gcc/testsuite/gcc.target/sh/pr54236-2.c b/gcc/testsuite/gcc.target/sh/pr54236-2.c new file mode 100644 index 00000000000..afcd33817c6 --- /dev/null +++ b/gcc/testsuite/gcc.target/sh/pr54236-2.c @@ -0,0 +1,270 @@ +/* Tests to check the utilization of the addc instruction in special cases. + If everything works as expected we won't see any movt instructions in + these cases. */ +/* { dg-do compile { target "sh*-*-*" } } */ +/* { dg-options "-O1" } */ +/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */ +/* { dg-final { scan-assembler-times "addc" 37 } } */ +/* { dg-final { scan-assembler-times "shlr" 23 } } */ +/* { dg-final { scan-assembler-times "shll" 14 } } */ +/* { dg-final { scan-assembler-times "add\t" 12 } } */ +/* { dg-final { scan-assembler-not "movt" } } */ + +int +test_000 (int a, int c, int b, int d) +{ + // 1x shlr, 1x addc + return a + (b & 1); +} + +int +test_001 (int a, int c, int b, int d) +{ + // 1x shlr, 1x addc + return a + b + (c & 1); +} + +int +test_002 (int a, int c, int b, int d) +{ + // 1x shlr, 1x add, 1x addc + return a + b + c + (d & 1); +} + +int +test_003 (int a, int c, int b, int d) +{ + // 1x shlr, 1x addc + return (b & 1) + a; +} + +int +test_004 (int a, int c, int b, int d) +{ + // 1x shlr, 1x addc + return a + (c & 1) + b; +} + +int +test_005 (int a, int c, int b, int d) +{ + // 1x shlr, 1x add, 1x addc + return a + b + (d & 1) + c; +} + +int +test_006 (int a, int c, int b, int d) +{ + // 1x shlr, 1x addc + return (c & 1) + a + b; +} + +int +test_007 (int a, int c, int b, int d) +{ + // 1x shlr, 1x add, 1x addc + return a + (d & 1) + b + c; +} + +int +test_008 (int a, int c, int b, int d) +{ + // 1x shlr, 1x add, 1x addc + return (d & 1) + a + b + c; +} + +int +test_009 (int a, int c, int b, int d) +{ + // 1x shlr, 1x addc + return a + b + (b & 1); +} + +int +test_010 (int a, int c, int b, int d) +{ + // 1x shlr, 1x addc + return a + (b & 1) + b; +} + +int +test_011 (int a, int c, int b, int d) +{ + // 1x shlr, 1x addc + return (b & 1) + a + b; +} + +int +test_012 (int a, int c, int b, int d) +{ + // 1x shlr, 1x add, 1x addc + return a + b + d + (b & 1); +} + +int +test_013 (int a, int c, int b, int d) +{ + // 1x shlr, 1x add, 1x addc + return a + d + (b & 1) + b; +} + +int +test_014 (int a, int c, int b, int d) +{ + // 1x shlr, 1x add, 1x addc + return a + (b & 1) + d + b; +} + +int +test_015 (int a, int c, int b, int d) +{ + // 1x shlr, 1x add, 1x addc + return (b & 1) + a + d + b; +} + +int +test_016 (int a, int b, int c, int d) +{ + // 1x shlr, 1x addc + return a + (a & 1); +} + +int +test_017 (int a, int b, int c, int d) +{ + // 1x shlr, 1x addc + return a + a + (a & 1); +} + +int +test_018 (int a, int b, int c, int d) +{ + // 1x shlr, 1x addc + return a + (a & 1) + a; +} + +int +test_019 (int a, int b, int c, int d) +{ + // 1x shlr, 1x addc + return (a & 1) + a + a; +} + +int +test_020 (int a, int b, int c, int d) +{ + // 1x shlr, 1x addc + return b + b + (a & 1); +} + +int +test_021 (int a, int b, int c, int d) +{ + // 1x shlr, 1x addc + return b + (a & 1) + b; +} + +int +test_022 (int a, int b, int c, int d) +{ + // 1x shlr, 1x addc + return (a & 1) + b + b; +} + +int +test_023 (int a, int b, int c, int d) +{ + // 1x shll, 1x addc + return a + ((b >> 31) & 1); +} + +int +test_024 (int a, int b, int c, int d) +{ + // 1x shll, 1x addc + return ((b >> 31) & 1) + a; +} + +int +test_025 (int a, int b, int c, int d) +{ + // 1x shll, 1x addc + return ((a >> 31) & 1) + a; +} + +int +test_026 (int a, int b, int c, int d) +{ + // 1x shll, 1x addc + return a + ((a >> 31) & 1); +} + +int +test_027 (int a, int b, int c, int d) +{ + // 1x shll, 1x addc + return a + b + ((c >> 31) & 1); +} + +int +test_028 (int a, int b, int c, int d) +{ + // 1x shll, 1x addc + return a + ((c >> 31) & 1) + b; +} + +int +test_029 (int a, int b, int c, int d) +{ + // 1x shll, 1x addc + return ((c >> 31) & 1) + a + b; +} + +int +test_030 (int a, int b, int c, int d) +{ + // 1x shll, 1x addc, 1x add + return a + b + c + ((d >> 31) & 1); +} + +int +test_031 (int a, int b, int c, int d) +{ + // 1x shll, 1x addc, 1x add + return a + b + ((d >> 31) & 1) + c; +} + +int +test_032 (int a, int b, int c, int d) +{ + // 1x shll, 1x addc, 1x add + return a + ((d >> 31) & 1) + b + c; +} + +int +test_033 (int a, int b, int c, int d) +{ + // 1x shll, 1x addc, 1x add + return ((d >> 31) & 1) + a + b + c; +} + +int +test_034 (int a, int b, int c, int d) +{ + // 1x shll, 1x addc + return a + a + ((d >> 31) & 1); +} + +int +test_035 (int a, int b, int c, int d) +{ + // 1x shll, 1x addc + return a + ((d >> 31) & 1) + a; +} + +int +test_036 (int a, int b, int c, int d) +{ + // 1x shll, 1x addc + return ((d >> 31) & 1) + a + a; +} diff --git a/gcc/testsuite/gfortran.dg/assumed_type_8.f90 b/gcc/testsuite/gfortran.dg/assumed_type_8.f90 new file mode 100644 index 00000000000..543e693bb4b --- /dev/null +++ b/gcc/testsuite/gfortran.dg/assumed_type_8.f90 @@ -0,0 +1,19 @@ +! { dg-do compile } +! +! Issue came up during the review of PR fortran/58793 +! +! Test for TS29113:2012's C407b. +! +program test + use iso_c_binding + integer,target ::aa + call up(c_loc(aa)) +contains + subroutine up(x) + class(*) :: x + end subroutine + subroutine bar(x) + type(*) :: x + call up(x) ! { dg-error "Assumed-type actual argument at .1. requires that dummy argument 'x' is of assumed type" } + end subroutine bar +end program test diff --git a/gcc/testsuite/gfortran.dg/blockdata_8.f90 b/gcc/testsuite/gfortran.dg/blockdata_8.f90 new file mode 100644 index 00000000000..d3f992564ad --- /dev/null +++ b/gcc/testsuite/gfortran.dg/blockdata_8.f90 @@ -0,0 +1,48 @@ +! { dg-do compile } +! +! PR fortran/44350 +! +! Fortran 2008, C1116 only permits a small subset of statements in BLOCK DATA +! +! Part of the test case was contributed by Vittorio Zecca +! +module m +end module m + +BLOCK DATA valid2 + use m + implicit integer(a-z) + intrinsic :: sin + common /one/ a, c + bind(C) :: /one/ + dimension c(5) + parameter (g = 7) +END BLOCK DATA valid2 + +BLOCK DATA valid + use m + implicit none + type t + sequence + end type t + type(t), save :: x + integer :: y + real :: q + save :: y + dimension :: q(5) +! class(*) :: zz ! See PR fortran/58857 +! pointer :: zz + target :: q + volatile y + asynchronous q +END BLOCK DATA valid + +block data invalid + common x + f(x)=x ! { dg-error "STATEMENT FUNCTION statement is not allowed inside of BLOCK DATA" } + interface ! { dg-error "INTERFACE statement is not allowed inside of BLOCK DATA" } + end interface +1 format() ! { dg-error "FORMAT statement is not allowed inside of BLOCK DATA" } +end block invalid ! { dg-error "Expecting END BLOCK DATA statement" } + +! { dg-error "Unexpected end of file" "" { target "*-*-*" } 0 } diff --git a/gcc/testsuite/gfortran.dg/pr58968.f b/gcc/testsuite/gfortran.dg/pr58968.f new file mode 100644 index 00000000000..db06d50fa27 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr58968.f @@ -0,0 +1,96 @@ +C PR rtl-optimization/58968.f +C { dg-do compile { target powerpc*-*-*} } +C { dg-options "-mcpu=power7 -O3 -w -ffast-math -funroll-loops" } + SUBROUTINE MAKTABS(IW,SOME,LBOX1,LBOX2,LBOX3,NSPACE,NA,NB, + * LBST,X, + * NX,IAMA,IAMI,IBMA,IBMI,MNUM,IDIM,MSTA,IBO, + * IDSYM,ISYM1,NSYM, + * NACT,LWRK,KTAB,LGMUL, + * LCON,LCOA,LCOB, + * LANDET,LBNDET,NAST,NBST,LSYMA,LSYMB,LGCOM, + * MINI,MAXI,LSPA,LSPB,LDISB, + * LSAS,LSBS,LSAC,LSBC, + * ITGA,ITGB,IAST,IBST,NCI,NA1EX,NB1EX,FDIRCT) + IMPLICIT DOUBLE PRECISION(A-H,O-Z) + LOGICAL SOME + DIMENSION LBOX1(NSPACE),LBOX2(NSPACE),LBOX3(NSPACE),LBST(NSPACE) + DIMENSION X(NX) + DIMENSION IAMA(NSPACE),IAMI(NSPACE),IBMA(NSPACE),IBMI(NSPACE) + DIMENSION MNUM(NSPACE),IDIM(NSPACE),MSTA(NSPACE+1),IBO(NACT) + DIMENSION LWRK(43),KTAB(NSYM),LGMUL(NSYM,NSYM) + DIMENSION LCON(NA) + DIMENSION LCOA(NSYM,ITGA),LCOB(NSYM,ITGB) + DIMENSION LANDET(NSPACE,ITGA),LBNDET(NSPACE,ITGB) + DIMENSION NAST(ITGA+1),NBST(ITGB+1) + DIMENSION LSYMA(IAST),LSYMB(IBST) + DIMENSION LGCOM(ITGB,ITGA) + DIMENSION MINI(NSPACE),MAXI(NSPACE) + DIMENSION LSPA(IAST),LSPB(IBST) + DIMENSION LDISB(NSYM,ITGB,ITGA) + DIMENSION LSAS(NSYM+1,ITGA),LSBS(NSYM+1,ITGB) + DIMENSION LSAC(IAST),LSBC(IBST) + LOGICAL FDIRCT + LCOA = 0 + LCOB = 0 + ISTA1 = LBST(1) + CALL RESETCO(LBOX1,NSPACE,NB,IBMA,IBMI,LBOX2) + NAST(1) = 0 + NBST(1) = 0 + DO II=1,ITGA + ITOT = 1 + DO JJ=1,NSPACE + ITOT = ITOT * LANDET(JJ,II) + ENDDO + NAST(II+1) = NAST(II) + ITOT + ENDDO + DO II=1,ITGB + ITOT = 1 + DO JJ=1,NSPACE + ITOT = ITOT * LBNDET(JJ,II) + ENDDO + NBST(II+1) = NBST(II) + ITOT + ENDDO + ICOMP = 0 + CALL RESETCO(LBOX1,NSPACE,NA,IAMA,IAMI,LBOX3) + NA1EX = 0 + NB1EX = 0 + CALL RESETCO(LBOX1,NSPACE,NB,IBMA,IBMI,LBOX3) + DO IIB = 1,ITGB + CALL RESETDE(LBOX1,NSPACE,NB,MSTA,LCON) + DO KKB=NBST(IIB)+1,NBST(IIB+1) + DO II=1,NSPACE + LBOX2(II) = LBOX1(II) + ENDDO + IEBS = NB+1 + DO ISPB1=NSPACE,1,-1 + IOC1 = LBOX1(ISPB1) + IEBE = IEBS - 1 + IEBS = IEBS - IOC1 + LBOX2(ISPB1) = LBOX2(ISPB1)-1 + DO IB1=IEBE,IEBS,-1 + IO1 = LCON(IB1) + IGBE = IEBE - LBOX1(ISPB1) + DO ISPB2=ISPB1,NSPACE + IGBS = IGBE + 1 + IGBE = IGBE + LBOX1(ISPB2) + LBOX2(ISPB2) = LBOX2(ISPB2) + 1 + IGBA = MAX(IB1+1,IGBS) + DO IGAP=IGBA,IGBE+1 + DO JJ=ISTA,IEND + NB1EX = NB1EX + 1 + ENDDO + ISTA = LCON(IGAP)+1 + IEND = LCON(IGAP+1)-1 + IF (IGAP.EQ.IGBE) IEND=MSTA(ISPB2+1)-1 + ENDDO + LBOX2(ISPB2) = LBOX2(ISPB2) - 1 + ENDDO + ENDDO + LBOX2(ISPB1) = LBOX2(ISPB1) + 1 + ENDDO + CALL MOVEUP2(LBOX1,NSPACE,NB,MSTA,LCON) + ENDDO + CALL PUSHCO(LBOX1,NSPACE,NB,IBMA,IBMI,LBOX3,IEND) + ENDDO + RETURN + END diff --git a/gcc/testsuite/gfortran.dg/proc_ptr_comp_38.f90 b/gcc/testsuite/gfortran.dg/proc_ptr_comp_38.f90 new file mode 100644 index 00000000000..2a71ca052cd --- /dev/null +++ b/gcc/testsuite/gfortran.dg/proc_ptr_comp_38.f90 @@ -0,0 +1,12 @@ +! { dg-do compile } +! +! PR fortran/58803 +! +! Contributed by Vittorio Zecca +! +! Was before ICEing due to a double free +! + type t + procedure(real), pointer, nopass :: f1, f2 + end type + end diff --git a/gcc/testsuite/gfortran.dg/unlimited_polymorphic_13.f90 b/gcc/testsuite/gfortran.dg/unlimited_polymorphic_13.f90 new file mode 100644 index 00000000000..0e27b172fb8 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/unlimited_polymorphic_13.f90 @@ -0,0 +1,67 @@ +! { dg-do run } +! +! PR fortran/58793 +! +! Contributed by Vladimir Fuka +! +! Had the wrong value for the storage_size for complex +! +module m + use iso_fortran_env + implicit none + integer, parameter :: c1 = real_kinds(1) + integer, parameter :: c2 = real_kinds(2) + integer, parameter :: c3 = real_kinds(size(real_kinds)-1) + integer, parameter :: c4 = real_kinds(size(real_kinds)) + real(c1) :: r1 + real(c2) :: r2 + real(c3) :: r3 + real(c4) :: r4 +contains + subroutine s(o, k) + class(*) :: o + integer :: k + integer :: sz + + select case (k) + case (4) + sz = storage_size(r1)*2 + case (8) + sz = storage_size(r2)*2 + case (10) + sz = storage_size(r3)*2 + case (16) + sz = storage_size(r4)*2 + case default + call abort() + end select + + if (storage_size(o) /= sz) call abort() + +! Break up the SELECT TYPE to pre-empt collisions in the value of 'cn' + select type (o) + type is (complex(c1)) + if (storage_size(o) /= sz) call abort() + end select + select type (o) + type is (complex(c2)) + if (storage_size(o) /= sz) call abort() + end select + select type (o) + type is (complex(c3)) + if (storage_size(o) /= sz) call abort() + end select + select type (o) + type is (complex(c4)) + if (storage_size(o) /= sz) call abort() + end select + end subroutine s +end module m + +program p + use m + call s((1._c1, 2._c1), c1) + call s((1._c2, 2._c2), c2) + call s((1._c3, 2._c3), c3) + call s((1._c4, 2._c4), c4) +end program p diff --git a/gcc/testsuite/gfortran.dg/unlimited_polymorphic_14.f90 b/gcc/testsuite/gfortran.dg/unlimited_polymorphic_14.f90 new file mode 100644 index 00000000000..215b03f64ee --- /dev/null +++ b/gcc/testsuite/gfortran.dg/unlimited_polymorphic_14.f90 @@ -0,0 +1,26 @@ +! { dg-do run } +! +! Uncovered in fixing PR fortran/58793 +! +! Contributed by Tobias Burnus <burnus@gcc.gnu.org> +! +! Barfed on the hollerith argument +! +program test + logical l + call up("abc", l) + if (l) call abort + call up(3habc, l) ! { dg-warning "Legacy Extension" } + if (.not. l) call abort +contains + subroutine up(x, l) + class(*) :: x + logical l + select type(x) + type is (character(*)) + l = .false. + class default + l = .true. + end select + end subroutine +end program test diff --git a/gcc/testsuite/gfortran.dg/vect/vect-do-concurrent-1.f90 b/gcc/testsuite/gfortran.dg/vect/vect-do-concurrent-1.f90 new file mode 100644 index 00000000000..287dfe1d177 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/vect/vect-do-concurrent-1.f90 @@ -0,0 +1,17 @@ +! { dg-do compile } +! { dg-require-effective-target vect_float } +! { dg-additional-options "-O3 -fopt-info-vec-optimized" } + +subroutine test(n, a, b, c) + integer, value :: n + real, contiguous, pointer :: a(:), b(:), c(:) + integer :: i + do concurrent (i = 1:n) + a(i) = b(i) + c(i) + end do +end subroutine test + +! { dg-message "loop vectorized" "" { target *-*-* } 0 } +! { dg-bogus " version" "" { target *-*-* } 0 } +! { dg-bogus " alias" "" { target *-*-* } 0 } +! { dg-final { cleanup-tree-dump "vect" } } diff --git a/gcc/testsuite/gfortran.dg/vect/vect.exp b/gcc/testsuite/gfortran.dg/vect/vect.exp index daa81c87801..2d593cee35c 100644 --- a/gcc/testsuite/gfortran.dg/vect/vect.exp +++ b/gcc/testsuite/gfortran.dg/vect/vect.exp @@ -25,7 +25,7 @@ global DEFAULT_VECTCFLAGS set DEFAULT_VECTCFLAGS "" # These flags are used for all targets. -lappend DEFAULT_VECTCFLAGS "-O2" "-ftree-vectorize" "-fno-vect-cost-model" \ +lappend DEFAULT_VECTCFLAGS "-O2" "-ftree-vectorize" "-fvect-cost-model=unlimited" \ "-fdump-tree-vect-details" # If the target system supports vector instructions, the default action @@ -68,7 +68,7 @@ dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/fast-math-real8*.\[fF\]{,90, # -fvect-cost-model tests set DEFAULT_VECTCFLAGS $SAVED_DEFAULT_VECTCFLAGS -lappend DEFAULT_VECTCFLAGS "-fvect-cost-model" +lappend DEFAULT_VECTCFLAGS "-fvect-cost-model=dynamic" dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/cost-model-*.\[fF\]{,90,95,03,08} ]] \ "" $DEFAULT_VECTCFLAGS diff --git a/gcc/testsuite/go.test/go-test.exp b/gcc/testsuite/go.test/go-test.exp index 284bc99e2c0..1a636573d73 100644 --- a/gcc/testsuite/go.test/go-test.exp +++ b/gcc/testsuite/go.test/go-test.exp @@ -90,6 +90,21 @@ proc errchk { test opts } { puts $fdout $copy_line continue } + + # Combine quoted strings in comments, so that + # // ERROR "first error" "second error" + # turns into + # // ERROR "first error|second error" + # This format is used by the master testsuite to recognize + # multiple errors on a single line. We don't require that all + # the errors be present, but we do want to accept any of them. + set changed "" + while { $changed != $copy_line } { + set changed $copy_line + regsub "\(// \[^\"\]*\"\[^\"\]*\)\" \"" $copy_line "\\1|" out_line + set copy_line $out_line + } + regsub "// \(GCCGO_\)?ERROR \"\(\[^\"\]*\)\".*$" $copy_line "// \{ dg-error \"\\2\" \}" out_line if [string match "*dg-error*\\\[*" $out_line] { set index [string first "dg-error" $out_line] diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index 8701cf6c21d..5ca0b76d5fc 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -701,6 +701,14 @@ proc check_effective_target_scheduling {} { } "-fschedule-insns"] } +# Return 1 if trapping arithmetic is available, 0 otherwise. + +proc check_effective_target_trapping {} { + return [check_no_compiler_messages scheduling object { + add (int a, int b) { return a + b; } + } "-ftrapv"] +} + # Return 1 if compilation with -fgraphite is error-free for trivial # code, 0 otherwise. diff --git a/gcc/timevar.def b/gcc/timevar.def index 5a880a8a364..66d61aecc4d 100644 --- a/gcc/timevar.def +++ b/gcc/timevar.def @@ -221,7 +221,6 @@ DEFTIMEVAR (TV_CSE2 , "CSE 2") DEFTIMEVAR (TV_BRANCH_PROB , "branch prediction") DEFTIMEVAR (TV_COMBINE , "combiner") DEFTIMEVAR (TV_IFCVT , "if-conversion") -DEFTIMEVAR (TV_REGMOVE , "regmove") DEFTIMEVAR (TV_MODE_SWITCH , "mode switching") DEFTIMEVAR (TV_SMS , "sms modulo scheduling") DEFTIMEVAR (TV_SCHED , "scheduling") diff --git a/gcc/toplev.c b/gcc/toplev.c index cc8e905cd1f..f78912e09db 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -68,7 +68,6 @@ along with GCC; see the file COPYING3. If not see #include "coverage.h" #include "value-prof.h" #include "alloc-pool.h" -#include "tree-mudflap.h" #include "asan.h" #include "tsan.h" #include "gimple.h" @@ -395,15 +394,15 @@ wrapup_global_declaration_2 (tree decl) if (!node && flag_ltrans) needed = false; - else if (node && node->symbol.definition) + else if (node && node->definition) needed = false; - else if (node && node->symbol.alias) + else if (node && node->alias) needed = false; else if (!cgraph_global_info_ready && (TREE_USED (decl) || TREE_USED (DECL_ASSEMBLER_NAME (decl)))) /* needed */; - else if (node && node->symbol.analyzed) + else if (node && node->analyzed) /* needed */; else if (DECL_COMDAT (decl)) needed = false; @@ -568,10 +567,6 @@ compile_file (void) basically finished. */ if (in_lto_p || !flag_lto || flag_fat_lto_objects) { - /* Likewise for mudflap static object registrations. */ - if (flag_mudflap) - mudflap_finish_file (); - /* File-scope initialization for AddressSanitizer. */ if (flag_sanitize & SANITIZE_ADDRESS) asan_finish_file (); @@ -1287,8 +1282,14 @@ process_options (void) "and -ftree-loop-linear)"); #endif - if (flag_mudflap && flag_lto) - sorry ("mudflap cannot be used together with link-time optimization"); + if (flag_check_pointer_bounds) + { + if (targetm.chkp_bound_mode () == VOIDmode) + error ("-fcheck-pointers is not supported for this target"); + + if (!lang_hooks.chkp_supported) + flag_check_pointer_bounds = 0; + } /* One region RA really helps to decrease the code size. */ if (flag_ira_region == IRA_REGION_AUTODETECT) diff --git a/gcc/tracer.c b/gcc/tracer.c index 57055662ea5..86557febab7 100644 --- a/gcc/tracer.c +++ b/gcc/tracer.c @@ -46,6 +46,8 @@ #include "params.h" #include "coverage.h" #include "tree-pass.h" +#include "gimple.h" +#include "tree-cfg.h" #include "tree-ssa.h" #include "tree-inline.h" #include "cfgloop.h" diff --git a/gcc/trans-mem.c b/gcc/trans-mem.c index 3371c7ea26e..9ba2a38814e 100644 --- a/gcc/trans-mem.c +++ b/gcc/trans-mem.c @@ -23,7 +23,11 @@ #include "hash-table.h" #include "tree.h" #include "gimple.h" -#include "tree-ssa.h" +#include "gimple-ssa.h" +#include "cgraph.h" +#include "tree-cfg.h" +#include "tree-ssanames.h" +#include "tree-into-ssa.h" #include "tree-pass.h" #include "tree-inline.h" #include "diagnostic-core.h" @@ -4036,16 +4040,16 @@ get_cg_data (struct cgraph_node **node, bool traverse_aliases) { struct tm_ipa_cg_data *d; - if (traverse_aliases && (*node)->symbol.alias) + if (traverse_aliases && (*node)->alias) *node = cgraph_alias_target (*node); - d = (struct tm_ipa_cg_data *) (*node)->symbol.aux; + d = (struct tm_ipa_cg_data *) (*node)->aux; if (d == NULL) { d = (struct tm_ipa_cg_data *) obstack_alloc (&tm_obstack.obstack, sizeof (*d)); - (*node)->symbol.aux = (void *) d; + (*node)->aux = (void *) d; memset (d, 0, sizeof (*d)); } @@ -4188,7 +4192,7 @@ static void ipa_tm_scan_calls_clone (struct cgraph_node *node, cgraph_node_queue *callees_p) { - struct function *fn = DECL_STRUCT_FUNCTION (node->symbol.decl); + struct function *fn = DECL_STRUCT_FUNCTION (node->decl); basic_block bb; FOR_EACH_BB_FN (bb, fn) @@ -4217,7 +4221,7 @@ ipa_tm_note_irrevocable (struct cgraph_node *node, continue; /* Even if we think we can go irrevocable, believe the user above all. */ - if (is_tm_safe_or_pure (e->caller->symbol.decl)) + if (is_tm_safe_or_pure (e->caller->decl)) continue; caller = e->caller; @@ -4489,11 +4493,11 @@ ipa_tm_scan_irr_function (struct cgraph_node *node, bool for_clone) bool ret = false; /* Builtin operators (operator new, and such). */ - if (DECL_STRUCT_FUNCTION (node->symbol.decl) == NULL - || DECL_STRUCT_FUNCTION (node->symbol.decl)->cfg == NULL) + if (DECL_STRUCT_FUNCTION (node->decl) == NULL + || DECL_STRUCT_FUNCTION (node->decl)->cfg == NULL) return false; - push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl)); + push_cfun (DECL_STRUCT_FUNCTION (node->decl)); calculate_dominance_info (CDI_DOMINATORS); d = get_cg_data (&node, true); @@ -4579,7 +4583,7 @@ ipa_tm_mayenterirr_function (struct cgraph_node *node) unsigned flags; d = get_cg_data (&node, true); - decl = node->symbol.decl; + decl = node->decl; flags = flags_from_decl_or_type (decl); /* Handle some TM builtins. Ordinarily these aren't actually generated @@ -4622,7 +4626,7 @@ ipa_tm_mayenterirr_function (struct cgraph_node *node) /* Recurse on the main body for aliases. In general, this will result in one of the bits above being set so that we will not have to recurse next time. */ - if (node->symbol.alias) + if (node->alias) return ipa_tm_mayenterirr_function (cgraph_get_node (node->thunk.alias)); /* What remains is unmarked local functions without items that force @@ -4639,11 +4643,11 @@ ipa_tm_diagnose_tm_safe (struct cgraph_node *node) struct cgraph_edge *e; for (e = node->callees; e ; e = e->next_callee) - if (!is_tm_callable (e->callee->symbol.decl) + if (!is_tm_callable (e->callee->decl) && e->callee->local.tm_may_enter_irr) error_at (gimple_location (e->call_stmt), "unsafe function call %qD within " - "%<transaction_safe%> function", e->callee->symbol.decl); + "%<transaction_safe%> function", e->callee->decl); } /* Diagnose call from atomic transactions to unmarked functions @@ -4782,14 +4786,14 @@ static inline void ipa_tm_mark_force_output_node (struct cgraph_node *node) { cgraph_mark_force_output_node (node); - node->symbol.analyzed = true; + node->analyzed = true; } static inline void ipa_tm_mark_forced_by_abi_node (struct cgraph_node *node) { - node->symbol.forced_by_abi = true; - node->symbol.analyzed = true; + node->forced_by_abi = true; + node->analyzed = true; } /* Callback data for ipa_tm_create_version_alias. */ @@ -4810,10 +4814,10 @@ ipa_tm_create_version_alias (struct cgraph_node *node, void *data) tree old_decl, new_decl, tm_name; struct cgraph_node *new_node; - if (!node->symbol.cpp_implicit_alias) + if (!node->cpp_implicit_alias) return false; - old_decl = node->symbol.decl; + old_decl = node->decl; tm_name = tm_mangle (DECL_ASSEMBLER_NAME (old_decl)); new_decl = build_decl (DECL_SOURCE_LOCATION (old_decl), TREE_CODE (old_decl), tm_name, @@ -4839,16 +4843,16 @@ ipa_tm_create_version_alias (struct cgraph_node *node, void *data) new_node = cgraph_same_body_alias (NULL, new_decl, info->new_decl); new_node->tm_clone = true; - new_node->symbol.externally_visible = info->old_node->symbol.externally_visible; + new_node->externally_visible = info->old_node->externally_visible; /* ?? Do not traverse aliases here. */ get_cg_data (&node, false)->clone = new_node; record_tm_clone_pair (old_decl, new_decl); - if (info->old_node->symbol.force_output - || ipa_ref_list_first_referring (&info->old_node->symbol.ref_list)) + if (info->old_node->force_output + || ipa_ref_list_first_referring (&info->old_node->ref_list)) ipa_tm_mark_force_output_node (new_node); - if (info->old_node->symbol.forced_by_abi) + if (info->old_node->forced_by_abi) ipa_tm_mark_forced_by_abi_node (new_node); return false; } @@ -4862,7 +4866,7 @@ ipa_tm_create_version (struct cgraph_node *old_node) tree new_decl, old_decl, tm_name; struct cgraph_node *new_node; - old_decl = old_node->symbol.decl; + old_decl = old_node->decl; new_decl = copy_node (old_decl); /* DECL_ASSEMBLER_NAME needs to be set before we call @@ -4879,7 +4883,7 @@ ipa_tm_create_version (struct cgraph_node *old_node) new_node = cgraph_copy_node_for_versioning (old_node, new_decl, vNULL, NULL); new_node->local.local = false; - new_node->symbol.externally_visible = old_node->symbol.externally_visible; + new_node->externally_visible = old_node->externally_visible; new_node->lowered = true; new_node->tm_clone = 1; get_cg_data (&old_node, true)->clone = new_node; @@ -4903,10 +4907,10 @@ ipa_tm_create_version (struct cgraph_node *old_node) record_tm_clone_pair (old_decl, new_decl); cgraph_call_function_insertion_hooks (new_node); - if (old_node->symbol.force_output - || ipa_ref_list_first_referring (&old_node->symbol.ref_list)) + if (old_node->force_output + || ipa_ref_list_first_referring (&old_node->ref_list)) ipa_tm_mark_force_output_node (new_node); - if (old_node->symbol.forced_by_abi) + if (old_node->forced_by_abi) ipa_tm_mark_forced_by_abi_node (new_node); /* Do the same thing, but for any aliases of the original node. */ @@ -4941,7 +4945,7 @@ ipa_tm_insert_irr_call (struct cgraph_node *node, struct tm_region *region, cgraph_get_create_node (builtin_decl_explicit (BUILT_IN_TM_IRREVOCABLE)), g, 0, - compute_call_stmt_bb_frequency (node->symbol.decl, + compute_call_stmt_bb_frequency (node->decl, gimple_bb (g))); } @@ -4991,7 +4995,7 @@ ipa_tm_insert_gettmclone_call (struct cgraph_node *node, gsi_insert_before (gsi, g, GSI_SAME_STMT); cgraph_create_edge (node, cgraph_get_create_node (gettm_fn), g, 0, - compute_call_stmt_bb_frequency (node->symbol.decl, + compute_call_stmt_bb_frequency (node->decl, gimple_bb (g))); /* Cast return value from tm_gettmclone* into appropriate function @@ -5118,7 +5122,7 @@ ipa_tm_transform_calls_redirect (struct cgraph_node *node, return; } - fndecl = new_node->symbol.decl; + fndecl = new_node->decl; } cgraph_redirect_edge_callee (e, new_node); @@ -5212,7 +5216,7 @@ ipa_tm_transform_transaction (struct cgraph_node *node) d = get_cg_data (&node, true); - push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl)); + push_cfun (DECL_STRUCT_FUNCTION (node->decl)); calculate_dominance_info (CDI_DOMINATORS); for (region = d->all_tm_regions; region; region = region->next) @@ -5255,7 +5259,7 @@ ipa_tm_transform_clone (struct cgraph_node *node) if (!node->callees && !node->indirect_calls && !d->irrevocable_blocks_clone) return; - push_cfun (DECL_STRUCT_FUNCTION (d->clone->symbol.decl)); + push_cfun (DECL_STRUCT_FUNCTION (d->clone->decl)); calculate_dominance_info (CDI_DOMINATORS); need_ssa_rename = @@ -5291,7 +5295,7 @@ ipa_tm_execute (void) /* For all local functions marked tm_callable, queue them. */ FOR_EACH_DEFINED_FUNCTION (node) - if (is_tm_callable (node->symbol.decl) + if (is_tm_callable (node->decl) && cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE) { d = get_cg_data (&node, true); @@ -5306,14 +5310,14 @@ ipa_tm_execute (void) /* ... marked tm_pure, record that fact for the runtime by indicating that the pure function is its own tm_callable. No need to do this if the function's address can't be taken. */ - if (is_tm_pure (node->symbol.decl)) + if (is_tm_pure (node->decl)) { if (!node->local.local) - record_tm_clone_pair (node->symbol.decl, node->symbol.decl); + record_tm_clone_pair (node->decl, node->decl); continue; } - push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl)); + push_cfun (DECL_STRUCT_FUNCTION (node->decl)); calculate_dominance_info (CDI_DOMINATORS); tm_region_init (NULL); @@ -5351,20 +5355,20 @@ ipa_tm_execute (void) /* Some callees cannot be arbitrarily cloned. These will always be irrevocable. Mark these now, so that we need not scan them. */ - if (is_tm_irrevocable (node->symbol.decl)) + if (is_tm_irrevocable (node->decl)) ipa_tm_note_irrevocable (node, &irr_worklist); else if (a <= AVAIL_NOT_AVAILABLE - && !is_tm_safe_or_pure (node->symbol.decl)) + && !is_tm_safe_or_pure (node->decl)) ipa_tm_note_irrevocable (node, &irr_worklist); else if (a >= AVAIL_OVERWRITABLE) { - if (!tree_versionable_function_p (node->symbol.decl)) + if (!tree_versionable_function_p (node->decl)) ipa_tm_note_irrevocable (node, &irr_worklist); else if (!d->is_irrevocable) { /* If this is an alias, make sure its base is queued as well. we need not scan the callees now, as the base will do. */ - if (node->symbol.alias) + if (node->alias) { node = cgraph_get_node (node->thunk.alias); d = get_cg_data (&node, true); @@ -5442,7 +5446,7 @@ ipa_tm_execute (void) for (e = node->callers; e ; e = e->next_caller) { caller = e->caller; - if (!is_tm_safe_or_pure (caller->symbol.decl) + if (!is_tm_safe_or_pure (caller->decl) && !caller->local.tm_may_enter_irr) { d = get_cg_data (&caller, true); @@ -5451,7 +5455,7 @@ ipa_tm_execute (void) } /* Propagate back to referring aliases as well. */ - for (j = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list, j, ref); j++) + for (j = 0; ipa_ref_list_referring_iterate (&node->ref_list, j, ref); j++) { caller = cgraph (ref->referring); if (ref->use == IPA_REF_ALIAS @@ -5471,7 +5475,7 @@ ipa_tm_execute (void) && cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE) { d = get_cg_data (&node, true); - if (is_tm_safe (node->symbol.decl)) + if (is_tm_safe (node->decl)) ipa_tm_diagnose_tm_safe (node); else if (d->all_tm_regions) ipa_tm_diagnose_transaction (node, d->all_tm_regions); @@ -5485,15 +5489,15 @@ ipa_tm_execute (void) bool doit = false; node = tm_callees[i]; - if (node->symbol.cpp_implicit_alias) + if (node->cpp_implicit_alias) continue; a = cgraph_function_body_availability (node); d = get_cg_data (&node, true); if (a <= AVAIL_NOT_AVAILABLE) - doit = is_tm_callable (node->symbol.decl); - else if (a <= AVAIL_AVAILABLE && is_tm_callable (node->symbol.decl)) + doit = is_tm_callable (node->decl); + else if (a <= AVAIL_AVAILABLE && is_tm_callable (node->decl)) doit = true; else if (!d->is_irrevocable && d->tm_callers_normal + d->tm_callers_clone > 0) @@ -5507,7 +5511,7 @@ ipa_tm_execute (void) for (i = 0; i < tm_callees.length (); ++i) { node = tm_callees[i]; - if (node->symbol.analyzed) + if (node->analyzed) { d = get_cg_data (&node, true); if (d->clone) @@ -5530,7 +5534,7 @@ ipa_tm_execute (void) free_original_copy_tables (); FOR_EACH_FUNCTION (node) - node->symbol.aux = NULL; + node->aux = NULL; #ifdef ENABLE_CHECKING verify_cgraph (); diff --git a/gcc/tree-call-cdce.c b/gcc/tree-call-cdce.c index fa41e297e1b..58065ad8377 100644 --- a/gcc/tree-call-cdce.c +++ b/gcc/tree-call-cdce.c @@ -25,8 +25,11 @@ along with GCC; see the file COPYING3. If not see #include "basic-block.h" #include "tree.h" #include "gimple-pretty-print.h" -#include "tree-ssa.h" #include "gimple.h" +#include "gimple-ssa.h" +#include "tree-cfg.h" +#include "tree-ssanames.h" +#include "tree-into-ssa.h" #include "tree-pass.h" #include "flags.h" @@ -710,7 +713,6 @@ shrink_wrap_one_built_in_call (gimple bi_call) basic_block bi_call_bb, join_tgt_bb, guard_bb, guard_bb0; edge join_tgt_in_edge_from_call, join_tgt_in_edge_fall_thru; edge bi_call_in_edge0, guard_bb_in_edge; - vec<gimple> conds; unsigned tn_cond_stmts, nconds; unsigned ci; gimple cond_expr = NULL; @@ -718,7 +720,7 @@ shrink_wrap_one_built_in_call (gimple bi_call) tree bi_call_label_decl; gimple bi_call_label; - conds.create (12); + stack_vec<gimple, 12> conds; gen_shrink_wrap_conditions (bi_call, conds, &nconds); /* This can happen if the condition generator decides @@ -726,10 +728,7 @@ shrink_wrap_one_built_in_call (gimple bi_call) return false and do not do any transformation for the call. */ if (nconds == 0) - { - conds.release (); - return false; - } + return false; bi_call_bb = gimple_bb (bi_call); @@ -740,10 +739,7 @@ shrink_wrap_one_built_in_call (gimple bi_call) it could e.g. have EH edges. */ join_tgt_in_edge_from_call = find_fallthru_edge (bi_call_bb->succs); if (join_tgt_in_edge_from_call == NULL) - { - conds.release (); - return false; - } + return false; } else join_tgt_in_edge_from_call = split_block (bi_call_bb, bi_call); @@ -829,7 +825,6 @@ shrink_wrap_one_built_in_call (gimple bi_call) guard_bb_in_edge->count = guard_bb->count - bi_call_in_edge->count; } - conds.release (); if (dump_file && (dump_flags & TDF_DETAILS)) { location_t loc; diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index 94be3610c91..6c551f4fe96 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -30,6 +30,17 @@ along with GCC; see the file COPYING3. If not see #include "function.h" #include "ggc.h" #include "gimple-pretty-print.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "cgraph.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" +#include "tree-ssa-loop-manip.h" +#include "tree-ssa-loop-niter.h" +#include "tree-into-ssa.h" +#include "tree-dfa.h" #include "tree-ssa.h" #include "tree-dump.h" #include "tree-pass.h" @@ -241,6 +252,72 @@ build_gimple_cfg (gimple_seq seq) discriminator_per_locus.dispose (); } + +/* Search for ANNOTATE call with annot_expr_ivdep_kind; if found, remove + it and set loop->safelen to INT_MAX. We assume that the annotation + comes immediately before the condition. */ + +static void +replace_loop_annotate () +{ + struct loop *loop; + loop_iterator li; + basic_block bb; + gimple_stmt_iterator gsi; + gimple stmt; + + FOR_EACH_LOOP (li, loop, 0) + { + gsi = gsi_last_bb (loop->header); + stmt = gsi_stmt (gsi); + if (stmt && gimple_code (stmt) == GIMPLE_COND) + { + gsi_prev_nondebug (&gsi); + if (gsi_end_p (gsi)) + continue; + stmt = gsi_stmt (gsi); + if (gimple_code (stmt) != GIMPLE_CALL) + continue; + if (!gimple_call_internal_p (stmt) + || gimple_call_internal_fn (stmt) != IFN_ANNOTATE) + continue; + if ((annot_expr_kind) tree_to_shwi (gimple_call_arg (stmt, 1)) + != annot_expr_ivdep_kind) + continue; + stmt = gimple_build_assign (gimple_call_lhs (stmt), + gimple_call_arg (stmt, 0)); + gsi_replace (&gsi, stmt, true); + loop->safelen = INT_MAX; + } + } + + /* Remove IFN_ANNOTATE. Safeguard for the case loop->latch == NULL. */ + FOR_EACH_BB (bb) + { + gsi = gsi_last_bb (bb); + stmt = gsi_stmt (gsi); + if (stmt && gimple_code (stmt) == GIMPLE_COND) + gsi_prev_nondebug (&gsi); + if (gsi_end_p (gsi)) + continue; + stmt = gsi_stmt (gsi); + if (gimple_code (stmt) != GIMPLE_CALL) + continue; + if (!gimple_call_internal_p (stmt) + || gimple_call_internal_fn (stmt) != IFN_ANNOTATE) + continue; + if ((annot_expr_kind) tree_to_shwi (gimple_call_arg (stmt, 1)) + != annot_expr_ivdep_kind) + continue; + warning_at (gimple_location (stmt), 0, "ignoring %<GCC ivdep%> " + "annotation"); + stmt = gimple_build_assign (gimple_call_lhs (stmt), + gimple_call_arg (stmt, 0)); + gsi_replace (&gsi, stmt, true); + } +} + + static unsigned int execute_build_cfg (void) { @@ -255,6 +332,7 @@ execute_build_cfg (void) } cleanup_tree_cfg (); loop_optimizer_init (AVOID_CFG_MODIFICATIONS); + replace_loop_annotate (); return 0; } @@ -305,6 +383,50 @@ computed_goto_p (gimple t) && TREE_CODE (gimple_goto_dest (t)) != LABEL_DECL); } +/* Returns true for edge E where e->src ends with a GIMPLE_COND and + the other edge points to a bb with just __builtin_unreachable (). + I.e. return true for C->M edge in: + <bb C>: + ... + if (something) + goto <bb N>; + else + goto <bb M>; + <bb N>: + __builtin_unreachable (); + <bb M>: */ + +bool +assert_unreachable_fallthru_edge_p (edge e) +{ + basic_block pred_bb = e->src; + gimple last = last_stmt (pred_bb); + if (last && gimple_code (last) == GIMPLE_COND) + { + basic_block other_bb = EDGE_SUCC (pred_bb, 0)->dest; + if (other_bb == e->dest) + other_bb = EDGE_SUCC (pred_bb, 1)->dest; + if (EDGE_COUNT (other_bb->succs) == 0) + { + gimple_stmt_iterator gsi = gsi_after_labels (other_bb); + gimple stmt; + + if (gsi_end_p (gsi)) + return false; + stmt = gsi_stmt (gsi); + if (is_gimple_debug (stmt)) + { + gsi_next_nondebug (&gsi); + if (gsi_end_p (gsi)) + return false; + stmt = gsi_stmt (gsi); + } + return gimple_call_builtin_p (stmt, BUILT_IN_UNREACHABLE); + } + } + return false; +} + /* Search the CFG for any computed gotos. If found, factor them to a common computed goto site. Also record the location of that site so diff --git a/gcc/tree-cfg.h b/gcc/tree-cfg.h index d6a5d8fce0d..c5c105dbdaa 100644 --- a/gcc/tree-cfg.h +++ b/gcc/tree-cfg.h @@ -51,6 +51,7 @@ extern bool is_ctrl_stmt (gimple); extern bool is_ctrl_altering_stmt (gimple); extern bool simple_goto_p (gimple); extern bool stmt_ends_bb_p (gimple); +extern bool assert_unreachable_fallthru_edge_p (edge); extern void delete_tree_cfg_annotations (void); extern gimple first_stmt (basic_block); extern gimple last_stmt (basic_block); diff --git a/gcc/tree-cfgcleanup.c b/gcc/tree-cfgcleanup.c index 830cdf36b6b..c627d2cac57 100644 --- a/gcc/tree-cfgcleanup.c +++ b/gcc/tree-cfgcleanup.c @@ -29,6 +29,14 @@ along with GCC; see the file COPYING3. If not see #include "function.h" #include "ggc.h" #include "langhooks.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" +#include "tree-ssa-loop-manip.h" +#include "tree-dfa.h" #include "tree-ssa.h" #include "tree-pass.h" #include "except.h" diff --git a/gcc/tree-chrec.c b/gcc/tree-chrec.c index 1d02da669fd..91a14e41f53 100644 --- a/gcc/tree-chrec.c +++ b/gcc/tree-chrec.c @@ -29,7 +29,9 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "tree-pretty-print.h" #include "cfgloop.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "tree-ssa-loop-ivopts.h" +#include "tree-ssa-loop-niter.h" #include "tree-chrec.h" #include "dumpfile.h" #include "params.h" diff --git a/gcc/tree-complex.c b/gcc/tree-complex.c index 7d9b696d9a8..6439402ba75 100644 --- a/gcc/tree-complex.c +++ b/gcc/tree-complex.c @@ -23,8 +23,14 @@ along with GCC; see the file COPYING3. If not see #include "tm.h" #include "tree.h" #include "flags.h" -#include "tree-ssa.h" #include "gimple.h" +#include "gimple-ssa.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" +#include "tree-dfa.h" +#include "tree-ssa.h" #include "tree-iterator.h" #include "tree-pass.h" #include "tree-ssa-propagate.h" diff --git a/gcc/tree-core.h b/gcc/tree-core.h index 4aff4c9d1d5..a52893c7fb9 100644 --- a/gcc/tree-core.h +++ b/gcc/tree-core.h @@ -448,6 +448,8 @@ enum tree_index { TI_FILEPTR_TYPE, TI_POINTER_SIZED_TYPE, + TI_POINTER_BOUNDS_TYPE, + TI_DFLOAT32_TYPE, TI_DFLOAT64_TYPE, TI_DFLOAT128_TYPE, @@ -647,6 +649,10 @@ enum tree_node_kind { all_kinds }; +enum annot_expr_kind { + annot_expr_ivdep_kind +}; + /*--------------------------------------------------------------------------- Type definitions diff --git a/gcc/tree-data-ref.c b/gcc/tree-data-ref.c index 6fa9f3b5abc..67528a8d7c5 100644 --- a/gcc/tree-data-ref.c +++ b/gcc/tree-data-ref.c @@ -78,6 +78,9 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tree.h" #include "gimple-pretty-print.h" +#include "gimple.h" +#include "tree-ssa-loop-niter.h" +#include "tree-ssa-loop.h" #include "tree-ssa.h" #include "cfgloop.h" #include "tree-data-ref.h" @@ -4322,7 +4325,7 @@ typedef struct data_ref_loc_d true if STMT clobbers memory, false otherwise. */ static bool -get_references_in_stmt (gimple stmt, vec<data_ref_loc, va_stack> *references) +get_references_in_stmt (gimple stmt, vec<data_ref_loc, va_heap> *references) { bool clobbers_memory = false; data_ref_loc ref; @@ -4414,17 +4417,13 @@ find_data_references_in_stmt (struct loop *nest, gimple stmt, vec<data_reference_p> *datarefs) { unsigned i; - vec<data_ref_loc, va_stack> references; + stack_vec<data_ref_loc, 2> references; data_ref_loc *ref; bool ret = true; data_reference_p dr; - vec_stack_alloc (data_ref_loc, references, 2); if (get_references_in_stmt (stmt, &references)) - { - references.release (); - return false; - } + return false; FOR_EACH_VEC_ELT (references, i, ref) { @@ -4448,17 +4447,13 @@ graphite_find_data_references_in_stmt (loop_p nest, loop_p loop, gimple stmt, vec<data_reference_p> *datarefs) { unsigned i; - vec<data_ref_loc, va_stack> references; + stack_vec<data_ref_loc, 2> references; data_ref_loc *ref; bool ret = true; data_reference_p dr; - vec_stack_alloc (data_ref_loc, references, 2); if (get_references_in_stmt (stmt, &references)) - { - references.release (); - return false; - } + return false; FOR_EACH_VEC_ELT (references, i, ref) { diff --git a/gcc/tree-dfa.c b/gcc/tree-dfa.c index 688bf7e2041..13b27599aea 100644 --- a/gcc/tree-dfa.c +++ b/gcc/tree-dfa.c @@ -33,12 +33,15 @@ along with GCC; see the file COPYING3. If not see #include "function.h" #include "tree-pretty-print.h" #include "gimple.h" -#include "tree-ssa.h" +#include "gimple-ssa.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" +#include "tree-dfa.h" #include "tree-inline.h" #include "tree-pass.h" #include "convert.h" #include "params.h" -#include "cgraph.h" /* Build and maintain data flow information for trees. */ @@ -741,8 +744,7 @@ dump_enumerated_decls (FILE *file, int flags) { basic_block bb; struct walk_stmt_info wi; - vec<numbered_tree> decl_list; - decl_list.create (40); + stack_vec<numbered_tree, 40> decl_list; memset (&wi, '\0', sizeof (wi)); wi.info = (void *) &decl_list; @@ -773,5 +775,4 @@ dump_enumerated_decls (FILE *file, int flags) last = ntp->t; } } - decl_list.release (); } diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c index 9c7817d42e2..a91542d56aa 100644 --- a/gcc/tree-eh.c +++ b/gcc/tree-eh.c @@ -27,13 +27,20 @@ along with GCC; see the file COPYING3. If not see #include "function.h" #include "except.h" #include "pointer-set.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "cgraph.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" +#include "tree-into-ssa.h" #include "tree-ssa.h" #include "tree-inline.h" #include "tree-pass.h" #include "langhooks.h" #include "ggc.h" #include "diagnostic-core.h" -#include "gimple.h" #include "target.h" #include "cfgloop.h" #include "gimple-low.h" @@ -2595,7 +2602,7 @@ tree_could_trap_p (tree expr) if (!DECL_EXTERNAL (expr)) return false; node = cgraph_function_node (cgraph_get_node (expr), NULL); - if (node && node->symbol.in_other_partition) + if (node && node->in_other_partition) return false; return true; } @@ -2611,7 +2618,7 @@ tree_could_trap_p (tree expr) if (!DECL_EXTERNAL (expr)) return false; node = varpool_variable_node (varpool_get_node (expr), NULL); - if (node && node->symbol.in_other_partition) + if (node && node->in_other_partition) return false; return true; } diff --git a/gcc/tree-emutls.c b/gcc/tree-emutls.c index 73592953912..b5ca407d62e 100644 --- a/gcc/tree-emutls.c +++ b/gcc/tree-emutls.c @@ -23,8 +23,11 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "gimple.h" #include "tree-pass.h" -#include "tree-ssa.h" +#include "gimple-ssa.h" #include "cgraph.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" #include "langhooks.h" #include "target.h" #include "targhooks.h" @@ -337,7 +340,7 @@ new_emutls_decl (tree decl, tree alias_of) else varpool_create_variable_alias (to, varpool_node_for_asm - (DECL_ASSEMBLER_NAME (DECL_VALUE_EXPR (alias_of)))->symbol.decl); + (DECL_ASSEMBLER_NAME (DECL_VALUE_EXPR (alias_of)))->decl); return to; } @@ -365,7 +368,7 @@ emutls_decl (tree decl) i = emutls_index (decl); var = control_vars[i]; - return var->symbol.decl; + return var->decl; } /* Generate a call statement to initialize CONTROL_DECL for TLS_DECL. @@ -427,7 +430,7 @@ gen_emutls_addr (tree decl, struct lower_emutls_data *d) gimple x; cvar = control_vars[index]; - cdecl = cvar->symbol.decl; + cdecl = cvar->decl; TREE_ADDRESSABLE (cdecl) = 1; addr = create_tmp_var (build_pointer_type (TREE_TYPE (decl)), NULL); @@ -444,7 +447,7 @@ gen_emutls_addr (tree decl, struct lower_emutls_data *d) /* We may be adding a new reference to a new variable to the function. This means we have to play with the ipa-reference web. */ - ipa_record_reference ((symtab_node)d->cfun_node, (symtab_node)cvar, IPA_REF_ADDR, x); + ipa_record_reference (d->cfun_node, cvar, IPA_REF_ADDR, x); /* Record this ssa_name for possible use later in the basic block. */ access_vars[index] = addr; @@ -617,7 +620,7 @@ lower_emutls_function_body (struct cgraph_node *node) struct lower_emutls_data d; bool any_edge_inserts = false; - push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl)); + push_cfun (DECL_STRUCT_FUNCTION (node->decl)); d.cfun_node = node; d.builtin_decl = builtin_decl_explicit (BUILT_IN_EMUTLS_GET_ADDRESS); @@ -699,29 +702,29 @@ create_emultls_var (struct varpool_node *var, void *data) tree cdecl; struct varpool_node *cvar; - cdecl = new_emutls_decl (var->symbol.decl, - var->symbol.alias && var->symbol.analyzed - ? varpool_alias_target (var)->symbol.decl : NULL); + cdecl = new_emutls_decl (var->decl, + var->alias && var->analyzed + ? varpool_alias_target (var)->decl : NULL); cvar = varpool_get_node (cdecl); control_vars.quick_push (cvar); - if (!var->symbol.alias) + if (!var->alias) { /* Make sure the COMMON block control variable gets initialized. Note that there's no point in doing this for aliases; we only need to do this once for the main variable. */ - emutls_common_1 (var->symbol.decl, cdecl, (tree *)data); + emutls_common_1 (var->decl, cdecl, (tree *)data); } - if (var->symbol.alias && !var->symbol.analyzed) - cvar->symbol.alias = true; + if (var->alias && !var->analyzed) + cvar->alias = true; /* Indicate that the value of the TLS variable may be found elsewhere, preventing the variable from re-appearing in the GIMPLE. We cheat and use the control variable here (rather than a full call_expr), which is special-cased inside the DWARF2 output routines. */ - SET_DECL_VALUE_EXPR (var->symbol.decl, cdecl); - DECL_HAS_VALUE_EXPR_P (var->symbol.decl) = 1; + SET_DECL_VALUE_EXPR (var->decl, cdecl); + DECL_HAS_VALUE_EXPR_P (var->decl) = 1; return false; } @@ -740,12 +743,12 @@ ipa_lower_emutls (void) /* Examine all global variables for TLS variables. */ FOR_EACH_VARIABLE (var) - if (DECL_THREAD_LOCAL_P (var->symbol.decl)) + if (DECL_THREAD_LOCAL_P (var->decl)) { - gcc_checking_assert (TREE_STATIC (var->symbol.decl) - || DECL_EXTERNAL (var->symbol.decl)); + gcc_checking_assert (TREE_STATIC (var->decl) + || DECL_EXTERNAL (var->decl)); varpool_node_set_add (tls_vars, var); - if (var->symbol.alias && var->symbol.definition) + if (var->alias && var->definition) varpool_node_set_add (tls_vars, varpool_variable_node (var, NULL)); } @@ -769,9 +772,9 @@ ipa_lower_emutls (void) { var = tls_vars->nodes[i]; - if (var->symbol.alias && !var->symbol.analyzed) + if (var->alias && !var->analyzed) any_aliases = true; - else if (!var->symbol.alias) + else if (!var->alias) varpool_for_node_and_aliases (var, create_emultls_var, &ctor_body, true); } diff --git a/gcc/tree-if-conv.c b/gcc/tree-if-conv.c index b487381e4be..31994b718e5 100644 --- a/gcc/tree-if-conv.c +++ b/gcc/tree-if-conv.c @@ -88,6 +88,13 @@ along with GCC; see the file COPYING3. If not see #include "flags.h" #include "basic-block.h" #include "gimple-pretty-print.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" +#include "tree-into-ssa.h" #include "tree-ssa.h" #include "cfgloop.h" #include "tree-chrec.h" @@ -1158,7 +1165,6 @@ if_convertible_loop_p (struct loop *loop) bool res = false; vec<data_reference_p> refs; vec<ddr_p> ddrs; - vec<loop_p> loop_nest; /* Handle only innermost loop. */ if (!loop || loop->inner) @@ -1192,7 +1198,7 @@ if_convertible_loop_p (struct loop *loop) refs.create (5); ddrs.create (25); - loop_nest.create (3); + stack_vec<loop_p, 3> loop_nest; res = if_convertible_loop_p_1 (loop, &loop_nest, &refs, &ddrs); if (flag_tree_loop_if_convert_stores) diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index 4543b270e5d..2796ff22362 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -33,12 +33,17 @@ along with GCC; see the file COPYING3. If not see #include "langhooks.h" #include "basic-block.h" #include "tree-iterator.h" -#include "cgraph.h" #include "intl.h" -#include "tree-mudflap.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" +#include "tree-into-ssa.h" +#include "tree-dfa.h" #include "tree-ssa.h" #include "function.h" -#include "tree-ssa.h" #include "tree-pretty-print.h" #include "except.h" #include "debug.h" @@ -53,7 +58,6 @@ along with GCC; see the file COPYING3. If not see /* I'm not real happy about this, but we need to handle gimple and non-gimple trees. */ -#include "gimple.h" /* Inlining, Cloning, Versioning, Parallelization @@ -1740,7 +1744,7 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale, /* We could also just rescale the frequency, but doing so would introduce roundoff errors and make verifier unhappy. */ - new_freq = compute_call_stmt_bb_frequency (id->dst_node->symbol.decl, + new_freq = compute_call_stmt_bb_frequency (id->dst_node->decl, copy_basic_block); /* Speculative calls consist of two edges - direct and indirect. @@ -1765,7 +1769,7 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale, (old_edge->frequency + indirect->frequency)), CGRAPH_FREQ_MAX); } - ipa_clone_ref (ref, (symtab_node)id->dst_node, stmt); + ipa_clone_ref (ref, id->dst_node, stmt); } else { @@ -1810,7 +1814,7 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale, if ((!edge || (edge->indirect_inlining_edge && id->transform_call_graph_edges == CB_CGE_MOVE_CLONES)) - && id->dst_node->symbol.definition + && id->dst_node->definition && (fn = gimple_call_fndecl (stmt)) != NULL) { struct cgraph_node *dest = cgraph_get_node (fn); @@ -1821,21 +1825,21 @@ copy_bb (copy_body_data *id, basic_block bb, int frequency_scale, producing dead clone (for further cloning). In all other cases we hit a bug (incorrect node sharing is the most common reason for missing edges). */ - gcc_assert (!dest->symbol.definition - || dest->symbol.address_taken - || !id->src_node->symbol.definition - || !id->dst_node->symbol.definition); + gcc_assert (!dest->definition + || dest->address_taken + || !id->src_node->definition + || !id->dst_node->definition); if (id->transform_call_graph_edges == CB_CGE_MOVE_CLONES) cgraph_create_edge_including_clones (id->dst_node, dest, orig_stmt, stmt, bb->count, - compute_call_stmt_bb_frequency (id->dst_node->symbol.decl, + compute_call_stmt_bb_frequency (id->dst_node->decl, copy_basic_block), CIF_ORIGINALLY_INDIRECT_CALL); else cgraph_create_edge (id->dst_node, dest, stmt, bb->count, compute_call_stmt_bb_frequency - (id->dst_node->symbol.decl, + (id->dst_node->decl, copy_basic_block))->inline_failed = CIF_ORIGINALLY_INDIRECT_CALL; if (dump_file) @@ -3739,7 +3743,7 @@ estimate_num_insns (gimple stmt, eni_weights *weights) /* Do not special case builtins where we see the body. This just confuse inliner. */ - if (!decl || !(node = cgraph_get_node (decl)) || node->symbol.definition) + if (!decl || !(node = cgraph_get_node (decl)) || node->definition) ; /* For buitins that are likely expanded to nothing or inlined do not account operand costs. */ @@ -4011,7 +4015,7 @@ expand_call_inline (basic_block bb, gimple stmt, copy_body_data *id) If we cannot, then there is no hope of inlining the function. */ if (cg_edge->indirect_unknown_callee) goto egress; - fn = cg_edge->callee->symbol.decl; + fn = cg_edge->callee->decl; gcc_checking_assert (fn); /* If FN is a declaration of a function in a nested scope that was @@ -4071,11 +4075,11 @@ expand_call_inline (basic_block bb, gimple stmt, copy_body_data *id) } goto egress; } - fn = cg_edge->callee->symbol.decl; + fn = cg_edge->callee->decl; cgraph_get_body (cg_edge->callee); #ifdef ENABLE_CHECKING - if (cg_edge->callee->symbol.decl != id->dst_node->symbol.decl) + if (cg_edge->callee->decl != id->dst_node->decl) verify_cgraph_node (cg_edge->callee); #endif @@ -4083,9 +4087,9 @@ expand_call_inline (basic_block bb, gimple stmt, copy_body_data *id) id->eh_lp_nr = lookup_stmt_eh_lp (stmt); /* Update the callers EH personality. */ - if (DECL_FUNCTION_PERSONALITY (cg_edge->callee->symbol.decl)) - DECL_FUNCTION_PERSONALITY (cg_edge->caller->symbol.decl) - = DECL_FUNCTION_PERSONALITY (cg_edge->callee->symbol.decl); + if (DECL_FUNCTION_PERSONALITY (cg_edge->callee->decl)) + DECL_FUNCTION_PERSONALITY (cg_edge->caller->decl) + = DECL_FUNCTION_PERSONALITY (cg_edge->callee->decl); /* Split the block holding the GIMPLE_CALL. */ e = split_block (bb, stmt); @@ -4333,7 +4337,7 @@ expand_call_inline (basic_block bb, gimple stmt, copy_body_data *id) variables in the function when the blocks get blown away as soon as we remove the cgraph node. */ if (gimple_block (stmt)) - (*debug_hooks->outlining_inline_function) (cg_edge->callee->symbol.decl); + (*debug_hooks->outlining_inline_function) (cg_edge->callee->decl); /* Update callgraph if needed. */ cgraph_remove_node (cg_edge->callee); @@ -4485,7 +4489,7 @@ optimize_inline_calls (tree fn) memset (&id, 0, sizeof (id)); id.src_node = id.dst_node = cgraph_get_node (fn); - gcc_assert (id.dst_node->symbol.definition); + gcc_assert (id.dst_node->definition); id.dst_fn = fn; /* Or any functions that aren't finished yet. */ if (current_function_decl) @@ -4585,10 +4589,6 @@ copy_tree_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED) /* Copy the node. */ new_tree = copy_node (*tp); - /* Propagate mudflap marked-ness. */ - if (flag_mudflap && mf_marked_p (*tp)) - mf_mark (new_tree); - *tp = new_tree; /* Now, restore the chain, if appropriate. That will cause @@ -4610,11 +4610,6 @@ copy_tree_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED) tree new_tree; new_tree = copy_node (*tp); - - /* Propagate mudflap marked-ness. */ - if (flag_mudflap && mf_marked_p (*tp)) - mf_mark (new_tree); - CONSTRUCTOR_ELTS (new_tree) = vec_safe_copy (CONSTRUCTOR_ELTS (*tp)); *tp = new_tree; } @@ -5080,7 +5075,7 @@ delete_unreachable_blocks_update_callgraph (copy_body_data *id) struct cgraph_edge *e; struct cgraph_node *node; - ipa_remove_stmt_references ((symtab_node)id->dst_node, gsi_stmt (bsi)); + ipa_remove_stmt_references (id->dst_node, gsi_stmt (bsi)); if (gimple_code (gsi_stmt (bsi)) == GIMPLE_CALL &&(e = cgraph_edge (id->dst_node, gsi_stmt (bsi))) != NULL) @@ -5094,7 +5089,7 @@ delete_unreachable_blocks_update_callgraph (copy_body_data *id) && id->dst_node->clones) for (node = id->dst_node->clones; node != id->dst_node;) { - ipa_remove_stmt_references ((symtab_node)node, gsi_stmt (bsi)); + ipa_remove_stmt_references (node, gsi_stmt (bsi)); if (gimple_code (gsi_stmt (bsi)) == GIMPLE_CALL && (e = cgraph_edge (node, gsi_stmt (bsi))) != NULL) { @@ -5190,8 +5185,7 @@ tree_function_versioning (tree old_decl, tree new_decl, unsigned i; struct ipa_replace_map *replace_info; basic_block old_entry_block, bb; - vec<gimple> init_stmts; - init_stmts.create (10); + stack_vec<gimple, 10> init_stmts; tree vars = NULL_TREE; gcc_assert (TREE_CODE (old_decl) == FUNCTION_DECL @@ -5417,7 +5411,7 @@ tree_function_versioning (tree old_decl, tree new_decl, pointer_set_destroy (id.statements_to_fold); fold_cond_expr_cond (); delete_unreachable_blocks_update_callgraph (&id); - if (id.dst_node->symbol.definition) + if (id.dst_node->definition) cgraph_rebuild_references (); update_ssa (TODO_update_ssa); @@ -5449,7 +5443,6 @@ tree_function_versioning (tree old_decl, tree new_decl, free_dominance_info (CDI_POST_DOMINATORS); gcc_assert (!id.debug_stmts.exists ()); - init_stmts.release (); pop_cfun (); return; } diff --git a/gcc/tree-inline.h b/gcc/tree-inline.h index a78e4b69f0e..cd327154560 100644 --- a/gcc/tree-inline.h +++ b/gcc/tree-inline.h @@ -131,6 +131,10 @@ typedef struct copy_body_data the originals have been mapped to a value rather than to a variable. */ struct pointer_map_t *debug_map; + + /* Cilk keywords currently need to replace some variables that + ordinary nested functions do not. */ + bool remap_var_for_cilk; } copy_body_data; /* Weights of constructions for estimate_num_insns. */ diff --git a/gcc/tree-into-ssa.c b/gcc/tree-into-ssa.c index 5a04ee7924f..981e9f4bfb4 100644 --- a/gcc/tree-into-ssa.c +++ b/gcc/tree-into-ssa.c @@ -29,9 +29,15 @@ along with GCC; see the file COPYING3. If not see #include "basic-block.h" #include "function.h" #include "gimple-pretty-print.h" -#include "bitmap.h" -#include "tree-ssa.h" #include "gimple.h" +#include "gimple-ssa.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" +#include "tree-into-ssa.h" +#include "tree-dfa.h" +#include "tree-ssa.h" #include "tree-inline.h" #include "hash-table.h" #include "tree-pass.h" diff --git a/gcc/tree-loop-distribution.c b/gcc/tree-loop-distribution.c index 015b50d46c9..79884bf4272 100644 --- a/gcc/tree-loop-distribution.c +++ b/gcc/tree-loop-distribution.c @@ -44,6 +44,16 @@ along with GCC; see the file COPYING3. If not see #include "config.h" #include "system.h" #include "coretypes.h" +#include "tree.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" +#include "tree-ssa-loop-manip.h" +#include "tree-ssa-loop.h" +#include "tree-into-ssa.h" #include "tree-ssa.h" #include "cfgloop.h" #include "tree-chrec.h" @@ -86,15 +96,6 @@ enum rdg_dep_type /* Read After Write (RAW). */ flow_dd = 'f', - /* Write After Read (WAR). */ - anti_dd = 'a', - - /* Write After Write (WAW). */ - output_dd = 'o', - - /* Read After Read (RAR). */ - input_dd = 'i', - /* Control dependence (execute conditional on). */ control_dd = 'c' }; @@ -105,19 +106,9 @@ typedef struct rdg_edge { /* Type of the dependence. */ enum rdg_dep_type type; - - /* Levels of the dependence: the depth of the loops that carry the - dependence. */ - unsigned level; - - /* Dependence relation between data dependences, NULL when one of - the vertices is a scalar. */ - ddr_p relation; } *rdg_edge_p; #define RDGE_TYPE(E) ((struct rdg_edge *) ((E)->data))->type -#define RDGE_LEVEL(E) ((struct rdg_edge *) ((E)->data))->level -#define RDGE_RELATION(E) ((struct rdg_edge *) ((E)->data))->relation /* Dump vertex I in RDG to FILE. */ @@ -205,23 +196,11 @@ dot_rdg_1 (FILE *file, struct graph *rdg) for (e = v->succ; e; e = e->succ_next) switch (RDGE_TYPE (e)) { - case input_dd: - fprintf (file, "%d -> %d [label=input] \n", i, e->dest); - break; - - case output_dd: - fprintf (file, "%d -> %d [label=output] \n", i, e->dest); - break; - case flow_dd: /* These are the most common dependences: don't print these. */ fprintf (file, "%d -> %d \n", i, e->dest); break; - case anti_dd: - fprintf (file, "%d -> %d [label=anti] \n", i, e->dest); - break; - case control_dd: fprintf (file, "%d -> %d [label=control] \n", i, e->dest); break; @@ -263,52 +242,6 @@ rdg_vertex_for_stmt (struct graph *rdg ATTRIBUTE_UNUSED, gimple stmt) return index; } -/* Creates an edge in RDG for each distance vector from DDR. The - order that we keep track of in the RDG is the order in which - statements have to be executed. */ - -static void -create_rdg_edge_for_ddr (struct graph *rdg, ddr_p ddr) -{ - struct graph_edge *e; - int va, vb; - data_reference_p dra = DDR_A (ddr); - data_reference_p drb = DDR_B (ddr); - unsigned level = ddr_dependence_level (ddr); - - /* For non scalar dependences, when the dependence is REVERSED, - statement B has to be executed before statement A. */ - if (level > 0 - && !DDR_REVERSED_P (ddr)) - { - data_reference_p tmp = dra; - dra = drb; - drb = tmp; - } - - va = rdg_vertex_for_stmt (rdg, DR_STMT (dra)); - vb = rdg_vertex_for_stmt (rdg, DR_STMT (drb)); - - if (va < 0 || vb < 0) - return; - - e = add_edge (rdg, va, vb); - e->data = XNEW (struct rdg_edge); - - RDGE_LEVEL (e) = level; - RDGE_RELATION (e) = ddr; - - /* Determines the type of the data dependence. */ - if (DR_IS_READ (dra) && DR_IS_READ (drb)) - RDGE_TYPE (e) = input_dd; - else if (DR_IS_WRITE (dra) && DR_IS_WRITE (drb)) - RDGE_TYPE (e) = output_dd; - else if (DR_IS_WRITE (dra) && DR_IS_READ (drb)) - RDGE_TYPE (e) = flow_dd; - else if (DR_IS_READ (dra) && DR_IS_WRITE (drb)) - RDGE_TYPE (e) = anti_dd; -} - /* Creates dependence edges in RDG for all the uses of DEF. IDEF is the index of DEF in RDG. */ @@ -329,7 +262,6 @@ create_rdg_edges_for_scalar (struct graph *rdg, tree def, int idef) e = add_edge (rdg, idef, use); e->data = XNEW (struct rdg_edge); RDGE_TYPE (e) = flow_dd; - RDGE_RELATION (e) = NULL; } } @@ -356,7 +288,6 @@ create_edge_for_control_dependence (struct graph *rdg, basic_block bb, e = add_edge (rdg, c, v); e->data = XNEW (struct rdg_edge); RDGE_TYPE (e) = control_dd; - RDGE_RELATION (e) = NULL; } } } @@ -364,38 +295,38 @@ create_edge_for_control_dependence (struct graph *rdg, basic_block bb, /* Creates the edges of the reduced dependence graph RDG. */ static void -create_rdg_edges (struct graph *rdg, vec<ddr_p> ddrs, control_dependences *cd) +create_rdg_flow_edges (struct graph *rdg) { int i; - struct data_dependence_relation *ddr; def_operand_p def_p; ssa_op_iter iter; - FOR_EACH_VEC_ELT (ddrs, i, ddr) - if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE) - create_rdg_edge_for_ddr (rdg, ddr); - else - free_dependence_relation (ddr); - for (i = 0; i < rdg->n_vertices; i++) FOR_EACH_PHI_OR_STMT_DEF (def_p, RDG_STMT (rdg, i), iter, SSA_OP_DEF) create_rdg_edges_for_scalar (rdg, DEF_FROM_PTR (def_p), i); +} - if (cd) - for (i = 0; i < rdg->n_vertices; i++) - { - gimple stmt = RDG_STMT (rdg, i); - if (gimple_code (stmt) == GIMPLE_PHI) - { - edge_iterator ei; - edge e; - FOR_EACH_EDGE (e, ei, gimple_bb (stmt)->preds) +/* Creates the edges of the reduced dependence graph RDG. */ + +static void +create_rdg_cd_edges (struct graph *rdg, control_dependences *cd) +{ + int i; + + for (i = 0; i < rdg->n_vertices; i++) + { + gimple stmt = RDG_STMT (rdg, i); + if (gimple_code (stmt) == GIMPLE_PHI) + { + edge_iterator ei; + edge e; + FOR_EACH_EDGE (e, ei, gimple_bb (stmt)->preds) create_edge_for_control_dependence (rdg, e->src, i, cd); - } - else - create_edge_for_control_dependence (rdg, gimple_bb (stmt), i, cd); - } + } + else + create_edge_for_control_dependence (rdg, gimple_bb (stmt), i, cd); + } } /* Build the vertices of the reduced dependence graph RDG. Return false @@ -484,10 +415,7 @@ free_rdg (struct graph *rdg) struct graph_edge *e; for (e = v->succ; e; e = e->succ_next) - { - free_dependence_relation (RDGE_RELATION (e)); - free (e->data); - } + free (e->data); if (v->data) { @@ -508,37 +436,25 @@ static struct graph * build_rdg (vec<loop_p> loop_nest, control_dependences *cd) { struct graph *rdg; - vec<gimple> stmts; vec<data_reference_p> datarefs; - vec<ddr_p> dependence_relations; /* Create the RDG vertices from the stmts of the loop nest. */ - stmts.create (10); + stack_vec<gimple, 10> stmts; stmts_from_loop (loop_nest[0], &stmts); rdg = new_graph (stmts.length ()); datarefs.create (10); if (!create_rdg_vertices (rdg, stmts, loop_nest[0], &datarefs)) { - stmts.release (); datarefs.release (); free_rdg (rdg); return NULL; } stmts.release (); - /* Create the RDG edges from the data dependences in the loop nest. */ - dependence_relations.create (100); - if (!compute_all_dependences (datarefs, &dependence_relations, loop_nest, - false) - || !known_dependences_p (dependence_relations)) - { - free_dependence_relations (dependence_relations); - datarefs.release (); - free_rdg (rdg); - return NULL; - } - create_rdg_edges (rdg, dependence_relations, cd); - dependence_relations.release (); + create_rdg_flow_edges (rdg); + if (cd) + create_rdg_cd_edges (rdg, cd); + datarefs.release (); return rdg; @@ -1033,11 +949,10 @@ static partition_t build_rdg_partition_for_vertex (struct graph *rdg, int v) { partition_t partition = partition_alloc (NULL, NULL); - vec<int> nodes; + stack_vec<int, 3> nodes; unsigned i; int x; - nodes.create (3); graphds_dfs (rdg, &v, 1, &nodes, false, NULL); FOR_EACH_VEC_ELT (nodes, i, x) @@ -1047,7 +962,6 @@ build_rdg_partition_for_vertex (struct graph *rdg, int v) loop_containing_stmt (RDG_STMT (rdg, x))->num); } - nodes.release (); return partition; } @@ -1395,6 +1309,70 @@ partition_contains_all_rw (struct graph *rdg, return false; } +/* Compute partition dependence created by the data references in DRS1 + and DRS2 and modify and return DIR according to that. */ + +static int +pg_add_dependence_edges (struct graph *rdg, vec<loop_p> loops, int dir, + vec<data_reference_p> drs1, + vec<data_reference_p> drs2) +{ + data_reference_p dr1, dr2; + + /* dependence direction - 0 is no dependence, -1 is back, + 1 is forth, 2 is both (we can stop then, merging will occur). */ + for (int ii = 0; drs1.iterate (ii, &dr1); ++ii) + for (int jj = 0; drs2.iterate (jj, &dr2); ++jj) + { + int this_dir = 1; + ddr_p ddr; + /* Re-shuffle data-refs to be in dominator order. */ + if (rdg_vertex_for_stmt (rdg, DR_STMT (dr1)) + > rdg_vertex_for_stmt (rdg, DR_STMT (dr2))) + { + data_reference_p tem = dr1; + dr1 = dr2; + dr2 = tem; + this_dir = -this_dir; + } + ddr = initialize_data_dependence_relation (dr1, dr2, loops); + compute_affine_dependence (ddr, loops[0]); + if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know) + this_dir = 2; + else if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE) + { + if (DDR_REVERSED_P (ddr)) + { + data_reference_p tem = dr1; + dr1 = dr2; + dr2 = tem; + this_dir = -this_dir; + } + /* Known dependences can still be unordered througout the + iteration space, see gcc.dg/tree-ssa/ldist-16.c. */ + if (DDR_NUM_DIST_VECTS (ddr) == 0) + this_dir = 2; + } + else + this_dir = 0; + free_dependence_relation (ddr); + if (dir == 0) + dir = this_dir; + else if (dir != this_dir) + return 2; + } + return dir; +} + +/* Compare postorder number of the partition graph vertices V1 and V2. */ + +static int +pgcmp (const void *v1_, const void *v2_) +{ + const vertex *v1 = (const vertex *)v1_; + const vertex *v2 = (const vertex *)v2_; + return v2->post - v1->post; +} /* Distributes the code from LOOP in such a way that producer statements are placed before consumer statements. Tries to separate @@ -1406,19 +1384,17 @@ distribute_loop (struct loop *loop, vec<gimple> stmts, control_dependences *cd, int *nb_calls) { struct graph *rdg; - vec<loop_p> loop_nest; vec<partition_t> partitions; partition_t partition; bool any_builtin; int i, nbp; + graph *pg = NULL; + int num_sccs = 1; *nb_calls = 0; - loop_nest.create (3); + stack_vec<loop_p, 3> loop_nest; if (!find_loop_nest (loop, &loop_nest)) - { - loop_nest.release (); - return 0; - } + return 0; rdg = build_rdg (loop_nest, cd); if (!rdg) @@ -1428,7 +1404,6 @@ distribute_loop (struct loop *loop, vec<gimple> stmts, "Loop %d not distributed: failed to build the RDG.\n", loop->num); - loop_nest.release (); return 0; } @@ -1445,8 +1420,8 @@ distribute_loop (struct loop *loop, vec<gimple> stmts, any_builtin |= partition_builtin_p (partition); } - /* If we did not detect any builtin but are not asked to apply - regular loop distribution simply bail out. */ + /* If we are only distributing patterns but did not detect any, + simply bail out. */ if (!flag_tree_loop_distribution && !any_builtin) { @@ -1454,9 +1429,56 @@ distribute_loop (struct loop *loop, vec<gimple> stmts, goto ldist_done; } + /* If we are only distributing patterns fuse all partitions that + were not classified as builtins. This also avoids chopping + a loop into pieces, separated by builtin calls. That is, we + only want no or a single loop body remaining. */ + partition_t into; + if (!flag_tree_loop_distribution) + { + for (i = 0; partitions.iterate (i, &into); ++i) + if (!partition_builtin_p (into)) + break; + for (++i; partitions.iterate (i, &partition); ++i) + if (!partition_builtin_p (partition)) + { + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, "fusing non-builtin partitions\n"); + dump_bitmap (dump_file, into->stmts); + dump_bitmap (dump_file, partition->stmts); + } + partition_merge_into (into, partition); + partitions.unordered_remove (i); + partition_free (partition); + i--; + } + } + + /* Due to limitations in the transform phase we have to fuse all + reduction partitions into the last partition so the existing + loop will contain all loop-closed PHI nodes. */ + for (i = 0; partitions.iterate (i, &into); ++i) + if (partition_reduction_p (into)) + break; + for (i = i + 1; partitions.iterate (i, &partition); ++i) + if (partition_reduction_p (partition)) + { + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, "fusing partitions\n"); + dump_bitmap (dump_file, into->stmts); + dump_bitmap (dump_file, partition->stmts); + fprintf (dump_file, "because they have reductions\n"); + } + partition_merge_into (into, partition); + partitions.unordered_remove (i); + partition_free (partition); + i--; + } + /* Apply our simple cost model - fuse partitions with similar memory accesses. */ - partition_t into; for (i = 0; partitions.iterate (i, &into); ++i) { if (partition_builtin_p (into)) @@ -1476,61 +1498,119 @@ distribute_loop (struct loop *loop, vec<gimple> stmts, "memory accesses\n"); } partition_merge_into (into, partition); - partitions.ordered_remove (j); + partitions.unordered_remove (j); partition_free (partition); j--; } } } - /* If we are only distributing patterns fuse all partitions that - were not properly classified as builtins. */ - if (!flag_tree_loop_distribution) + /* Build the partition dependency graph. */ + if (partitions.length () > 1) { - partition_t into; - /* Only fuse adjacent non-builtin partitions, see PR53616. - ??? Use dependence information to improve partition ordering. */ - i = 0; - do + pg = new_graph (partitions.length ()); + struct pgdata { + partition_t partition; + vec<data_reference_p> writes; + vec<data_reference_p> reads; + }; +#define PGDATA(i) ((pgdata *)(pg->vertices[i].data)) + for (i = 0; partitions.iterate (i, &partition); ++i) + { + vertex *v = &pg->vertices[i]; + pgdata *data = new pgdata; + data_reference_p dr; + /* FIXME - leaks. */ + v->data = data; + bitmap_iterator bi; + unsigned j; + data->partition = partition; + data->reads = vNULL; + data->writes = vNULL; + EXECUTE_IF_SET_IN_BITMAP (partition->stmts, 0, j, bi) + for (int k = 0; RDG_DATAREFS (rdg, j).iterate (k, &dr); ++k) + if (DR_IS_READ (dr)) + data->reads.safe_push (dr); + else + data->writes.safe_push (dr); + } + partition_t partition1, partition2; + for (i = 0; partitions.iterate (i, &partition1); ++i) + for (int j = i + 1; partitions.iterate (j, &partition2); ++j) + { + /* dependence direction - 0 is no dependence, -1 is back, + 1 is forth, 2 is both (we can stop then, merging will occur). */ + int dir = 0; + dir = pg_add_dependence_edges (rdg, loop_nest, dir, + PGDATA(i)->writes, + PGDATA(j)->reads); + if (dir != 2) + dir = pg_add_dependence_edges (rdg, loop_nest, dir, + PGDATA(i)->reads, + PGDATA(j)->writes); + if (dir != 2) + dir = pg_add_dependence_edges (rdg, loop_nest, dir, + PGDATA(i)->writes, + PGDATA(j)->writes); + if (dir == 1 || dir == 2) + add_edge (pg, i, j); + if (dir == -1 || dir == 2) + add_edge (pg, j, i); + } + + /* Add edges to the reduction partition (if any) to force it last. */ + unsigned j; + for (j = 0; partitions.iterate (j, &partition); ++j) + if (partition_reduction_p (partition)) + break; + if (j < partitions.length ()) + { + for (unsigned i = 0; partitions.iterate (i, &partition); ++i) + if (i != j) + add_edge (pg, i, j); + } + + /* Compute partitions we cannot separate and fuse them. */ + num_sccs = graphds_scc (pg, NULL); + for (i = 0; i < num_sccs; ++i) { - for (; partitions.iterate (i, &into); ++i) - if (!partition_builtin_p (into)) + partition_t first; + int j; + for (j = 0; partitions.iterate (j, &first); ++j) + if (pg->vertices[j].component == i) break; - for (++i; partitions.iterate (i, &partition); ++i) - if (!partition_builtin_p (partition)) + for (j = j + 1; partitions.iterate (j, &partition); ++j) + if (pg->vertices[j].component == i) { - partition_merge_into (into, partition); - partitions.ordered_remove (i); + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, "fusing partitions\n"); + dump_bitmap (dump_file, first->stmts); + dump_bitmap (dump_file, partition->stmts); + fprintf (dump_file, "because they are in the same " + "dependence SCC\n"); + } + partition_merge_into (first, partition); + partitions[j] = NULL; partition_free (partition); - i--; + PGDATA (j)->partition = NULL; } - else - break; } - while ((unsigned) i < partitions.length ()); - } - /* Fuse all reduction partitions into the last. */ - if (partitions.length () > 1) - { - partition_t into = partitions.last (); - for (i = partitions.length () - 2; i >= 0; --i) + /* Now order the remaining nodes in postorder. */ + qsort (pg->vertices, pg->n_vertices, sizeof (vertex), pgcmp); + partitions.truncate (0); + for (i = 0; i < pg->n_vertices; ++i) { - partition_t what = partitions[i]; - if (partition_reduction_p (what)) - { - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, "fusing partitions\n"); - dump_bitmap (dump_file, into->stmts); - dump_bitmap (dump_file, what->stmts); - fprintf (dump_file, "because the latter has reductions\n"); - } - partition_merge_into (into, what); - partitions.ordered_remove (i); - partition_free (what); - } + pgdata *data = PGDATA (i); + if (data->partition) + partitions.safe_push (data->partition); + data->reads.release (); + data->writes.release (); + delete data; } + gcc_assert (partitions.length () == (unsigned)num_sccs); + free_graph (pg); } nbp = partitions.length (); @@ -1559,7 +1639,6 @@ distribute_loop (struct loop *loop, vec<gimple> stmts, partitions.release (); free_rdg (rdg); - loop_nest.release (); return nbp - *nb_calls; } diff --git a/gcc/tree-mudflap.h b/gcc/tree-mudflap.h deleted file mode 100644 index 96f38c40c16..00000000000 --- a/gcc/tree-mudflap.h +++ /dev/null @@ -1,34 +0,0 @@ -/* Mudflap: narrow-pointer bounds-checking by tree rewriting. - Copyright (C) 2001-2013 Free Software Foundation, Inc. - Contributed by Frank Ch. Eigler <fche@redhat.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/>. */ - -#ifndef TREE_MUDFLAP_H -#define TREE_MUDFLAP_H - -/* Instrumentation. */ -extern void mudflap_init (void); -extern void mudflap_enqueue_decl (tree); -extern void mudflap_enqueue_constant (tree); -extern void mudflap_finish_file (void); - -/* Tree node marking. */ -extern int mf_marked_p (tree); -extern tree mf_mark (tree); - -#endif /* TREE_MUDFLAP_H */ diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c index b0922f6aabd..dc63ef6902e 100644 --- a/gcc/tree-nested.c +++ b/gcc/tree-nested.c @@ -28,8 +28,9 @@ #include "tree-inline.h" #include "gimple.h" #include "tree-iterator.h" -#include "tree-ssa.h" +#include "bitmap.h" #include "cgraph.h" +#include "tree-cfg.h" #include "expr.h" /* FIXME: For STACK_SAVEAREA_MODE and SAVE_NONLOCAL. */ #include "langhooks.h" #include "pointer-set.h" @@ -700,11 +701,11 @@ check_for_nested_with_variably_modified (tree fndecl, tree orig_fndecl) for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested) { - for (arg = DECL_ARGUMENTS (cgn->symbol.decl); arg; arg = DECL_CHAIN (arg)) + for (arg = DECL_ARGUMENTS (cgn->decl); arg; arg = DECL_CHAIN (arg)) if (variably_modified_type_p (TREE_TYPE (arg), orig_fndecl)) return true; - if (check_for_nested_with_variably_modified (cgn->symbol.decl, + if (check_for_nested_with_variably_modified (cgn->decl, orig_fndecl)) return true; } @@ -723,7 +724,7 @@ create_nesting_tree (struct cgraph_node *cgn) info->var_map = pointer_map_create (); info->mem_refs = pointer_set_create (); info->suppress_expansion = BITMAP_ALLOC (&nesting_info_bitmap_obstack); - info->context = cgn->symbol.decl; + info->context = cgn->decl; for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested) { @@ -2629,8 +2630,8 @@ static void gimplify_all_functions (struct cgraph_node *root) { struct cgraph_node *iter; - if (!gimple_body (root->symbol.decl)) - gimplify_function_tree (root->symbol.decl); + if (!gimple_body (root->decl)) + gimplify_function_tree (root->decl); for (iter = root->nested; iter; iter = iter->next_nested) gimplify_all_functions (iter); } diff --git a/gcc/tree-nomudflap.c b/gcc/tree-nomudflap.c deleted file mode 100644 index fe9ea6058bd..00000000000 --- a/gcc/tree-nomudflap.c +++ /dev/null @@ -1,169 +0,0 @@ -/* Mudflap: narrow-pointer bounds-checking by tree rewriting. - Copyright (C) 2001-2013 Free Software Foundation, Inc. - Contributed by Frank Ch. Eigler <fche@redhat.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" -#include "system.h" -#include "coretypes.h" -#include "tm.h" -#include "tree.h" -#include "tree-inline.h" -#include "gimple.h" -#include "hashtab.h" -#include "langhooks.h" -#include "tree-mudflap.h" -#include "tree-pass.h" -#include "ggc.h" -#include "diagnostic-core.h" - - - -/* This file contains placeholder functions, to be used only for - language processors that cannot handle tree-mudflap.c directly. - (e.g. Fortran). */ - -static void -nogo (void) -{ - sorry ("mudflap: this language is not supported"); -} - -void -mudflap_enqueue_decl (tree obj ATTRIBUTE_UNUSED) -{ - nogo (); -} - -void -mudflap_enqueue_constant (tree obj ATTRIBUTE_UNUSED) -{ - nogo (); -} - -void -mudflap_finish_file (void) -{ - nogo (); -} - -int -mf_marked_p (tree t ATTRIBUTE_UNUSED) -{ - nogo (); - return 0; -} - -tree -mf_mark (tree t ATTRIBUTE_UNUSED) -{ - nogo (); - return NULL; -} - -/* The pass structures must exist, but need not do anything. */ - -static bool -gate_mudflap (void) -{ - return flag_mudflap != 0; -} - -namespace { - -const pass_data pass_data_mudflap_1 = -{ - GIMPLE_PASS, /* type */ - "mudflap1", /* name */ - OPTGROUP_NONE, /* optinfo_flags */ - true, /* has_gate */ - false, /* has_execute */ - TV_NONE, /* tv_id */ - 0, /* properties_required */ - 0, /* properties_provided */ - 0, /* properties_destroyed */ - 0, /* todo_flags_start */ - 0, /* todo_flags_finish */ -}; - -class pass_mudflap_1 : public gimple_opt_pass -{ -public: - pass_mudflap_1 (gcc::context *ctxt) - : gimple_opt_pass (pass_data_mudflap_1, ctxt) - {} - - /* opt_pass methods: */ - bool gate () { return gate_mudflap (); } - -}; // class pass_mudflap_1 - -} // anon namespace - -gimple_opt_pass * -make_pass_mudflap_1 (gcc::context *ctxt) -{ - return new pass_mudflap_1 (ctxt); -} - -namespace { - -const pass_data pass_data_mudflap_2 = -{ - GIMPLE_PASS, /* type */ - "mudflap2", /* name */ - OPTGROUP_NONE, /* optinfo_flags */ - true, /* has_gate */ - false, /* has_execute */ - TV_NONE, /* tv_id */ - 0, /* properties_required */ - 0, /* properties_provided */ - 0, /* properties_destroyed */ - 0, /* todo_flags_start */ - 0, /* todo_flags_finish */ -}; - -class pass_mudflap_2 : public gimple_opt_pass -{ -public: - pass_mudflap_2 (gcc::context *ctxt) - : gimple_opt_pass (pass_data_mudflap_2, ctxt) - {} - - /* opt_pass methods: */ - bool gate () { return gate_mudflap (); } - -}; // class pass_mudflap_2 - -} // anon namespace - -gimple_opt_pass * -make_pass_mudflap_2 (gcc::context *ctxt) -{ - return new pass_mudflap_2 (ctxt); -} - -/* Instead of: -#include "gt-tree-mudflap.h" -We prepare a little dummy struct here. -*/ - -EXPORTED_CONST struct ggc_root_tab gt_ggc_r_gt_tree_mudflap_h[] = { - LAST_GGC_ROOT_TAB -}; diff --git a/gcc/tree-nrv.c b/gcc/tree-nrv.c index 1fec697589c..1425d195252 100644 --- a/gcc/tree-nrv.c +++ b/gcc/tree-nrv.c @@ -25,7 +25,9 @@ along with GCC; see the file COPYING3. If not see #include "function.h" #include "basic-block.h" #include "tree-pretty-print.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-ssanames.h" #include "tree-pass.h" #include "langhooks.h" #include "flags.h" /* For "optimize" in gate_pass_return_slot. diff --git a/gcc/tree-object-size.c b/gcc/tree-object-size.c index ca21e92256e..0b53f09f708 100644 --- a/gcc/tree-object-size.c +++ b/gcc/tree-object-size.c @@ -25,7 +25,10 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "diagnostic-core.h" #include "gimple-pretty-print.h" -#include "tree-ssa.h" +#include "bitmap.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-ssanames.h" #include "tree-pass.h" #include "tree-ssa-propagate.h" diff --git a/gcc/tree-outof-ssa.c b/gcc/tree-outof-ssa.c index f732e09d6fe..1e982857e14 100644 --- a/gcc/tree-outof-ssa.c +++ b/gcc/tree-outof-ssa.c @@ -28,9 +28,17 @@ along with GCC; see the file COPYING3. If not see #include "gimple-pretty-print.h" #include "bitmap.h" #include "sbitmap.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" #include "dumpfile.h" #include "diagnostic-core.h" +#include "tree-ssa-live.h" +#include "tree-ssa-ter.h" +#include "tree-ssa-coalesce.h" #include "tree-outof-ssa.h" /* FIXME: A lot of code here deals with expanding to RTL. All that code diff --git a/gcc/tree-outof-ssa.h b/gcc/tree-outof-ssa.h index 8c37f55ce50..69a329f8b2f 100644 --- a/gcc/tree-outof-ssa.h +++ b/gcc/tree-outof-ssa.h @@ -21,9 +21,6 @@ along with GCC; see the file COPYING3. If not see #ifndef GCC_TREE_OUTOF_SSA_H #define GCC_TREE_OUTOF_SSA_H -#include "tree-ssa-live.h" -#include "tree-ssa-ter.h" -#include "tree-ssa-coalesce.h" /* This structure (of which only a singleton SA exists) is used to pass around information between the outof-SSA functions, cfgexpand diff --git a/gcc/tree-parloops.c b/gcc/tree-parloops.c index cdef5c62fbe..25a0f0ac52b 100644 --- a/gcc/tree-parloops.c +++ b/gcc/tree-parloops.c @@ -22,7 +22,18 @@ along with GCC; see the file COPYING3. If not see #include "config.h" #include "system.h" #include "coretypes.h" -#include "tree-ssa.h" +#include "tree.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" +#include "tree-ssa-loop-ivopts.h" +#include "tree-ssa-loop-manip.h" +#include "tree-ssa-loop-niter.h" +#include "tree-ssa-loop.h" +#include "tree-into-ssa.h" #include "cfgloop.h" #include "tree-data-ref.h" #include "tree-scalar-evolution.h" @@ -384,7 +395,6 @@ lambda_transform_legal_p (lambda_trans_matrix trans, static bool loop_parallel_p (struct loop *loop, struct obstack * parloop_obstack) { - vec<loop_p> loop_nest; vec<ddr_p> dependence_relations; vec<data_reference_p> datarefs; lambda_trans_matrix trans; @@ -401,9 +411,9 @@ loop_parallel_p (struct loop *loop, struct obstack * parloop_obstack) /* Check for problems with dependences. If the loop can be reversed, the iterations are independent. */ + stack_vec<loop_p, 3> loop_nest; datarefs.create (10); - dependence_relations.create (10 * 10); - loop_nest.create (3); + dependence_relations.create (100); if (! compute_data_dependences_for_loop (loop, true, &loop_nest, &datarefs, &dependence_relations)) { @@ -429,7 +439,6 @@ loop_parallel_p (struct loop *loop, struct obstack * parloop_obstack) " FAILED: data dependencies exist across iterations\n"); end: - loop_nest.release (); free_dependence_relations (dependence_relations); free_data_refs (datarefs); @@ -730,8 +739,7 @@ static void eliminate_local_variables (edge entry, edge exit) { basic_block bb; - vec<basic_block> body; - body.create (3); + stack_vec<basic_block, 3> body; unsigned i; gimple_stmt_iterator gsi; bool has_debug_stmt = false; @@ -761,7 +769,6 @@ eliminate_local_variables (edge entry, edge exit) eliminate_local_variables_stmt (entry, &gsi, decl_address); decl_address.dispose (); - body.release (); } /* Returns true if expression EXPR is not defined between ENTRY and @@ -1286,8 +1293,7 @@ separate_decls_in_region (edge entry, edge exit, tree type, type_name, nvar; gimple_stmt_iterator gsi; struct clsn_data clsn_data; - vec<basic_block> body; - body.create (3); + stack_vec<basic_block, 3> body; basic_block bb; basic_block entry_bb = bb1; basic_block exit_bb = exit->dest; @@ -1345,8 +1351,6 @@ separate_decls_in_region (edge entry, edge exit, } } - body.release (); - if (name_copies.elements () == 0 && reduction_list.elements () == 0) { /* It may happen that there is nothing to copy (if there are only diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h index e72fe9aeee4..c4d09fe0821 100644 --- a/gcc/tree-pass.h +++ b/gcc/tree-pass.h @@ -338,8 +338,6 @@ extern void register_pass (register_pass_info *); extern void register_pass (opt_pass* pass, pass_positioning_ops pos, const char* ref_pass_name, int ref_pass_inst_number); -extern gimple_opt_pass *make_pass_mudflap_1 (gcc::context *ctxt); -extern gimple_opt_pass *make_pass_mudflap_2 (gcc::context *ctxt); extern gimple_opt_pass *make_pass_asan (gcc::context *ctxt); extern gimple_opt_pass *make_pass_asan_O0 (gcc::context *ctxt); extern gimple_opt_pass *make_pass_tsan (gcc::context *ctxt); @@ -526,7 +524,6 @@ extern rtl_opt_pass *make_pass_if_after_combine (gcc::context *ctxt); extern rtl_opt_pass *make_pass_ree (gcc::context *ctxt); extern rtl_opt_pass *make_pass_partition_blocks (gcc::context *ctxt); extern rtl_opt_pass *make_pass_match_asm_constraints (gcc::context *ctxt); -extern rtl_opt_pass *make_pass_regmove (gcc::context *ctxt); extern rtl_opt_pass *make_pass_split_all_insns (gcc::context *ctxt); extern rtl_opt_pass *make_pass_fast_rtl_byte_dce (gcc::context *ctxt); extern rtl_opt_pass *make_pass_lower_subreg2 (gcc::context *ctxt); diff --git a/gcc/tree-phinodes.c b/gcc/tree-phinodes.c index f96dafa476c..2cef1c4ab23 100644 --- a/gcc/tree-phinodes.c +++ b/gcc/tree-phinodes.c @@ -24,9 +24,13 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "ggc.h" #include "basic-block.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" #include "tree-ssa.h" #include "diagnostic-core.h" -#include "gimple.h" /* Rewriting a function into SSA form can create a huge number of PHIs many of which may be thrown away shortly after their creation if jumps diff --git a/gcc/tree-predcom.c b/gcc/tree-predcom.c index ace59d3b298..9a4898b8143 100644 --- a/gcc/tree-predcom.c +++ b/gcc/tree-predcom.c @@ -191,6 +191,17 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "tm_p.h" #include "cfgloop.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" +#include "tree-ssa-loop-ivopts.h" +#include "tree-ssa-loop-manip.h" +#include "tree-ssa-loop-niter.h" +#include "tree-ssa-loop.h" +#include "tree-into-ssa.h" +#include "tree-dfa.h" #include "tree-ssa.h" #include "ggc.h" #include "tree-data-ref.h" @@ -2410,7 +2421,6 @@ prepare_initializers (struct loop *loop, vec<chain_p> chains) static bool tree_predictive_commoning_loop (struct loop *loop) { - vec<loop_p> loop_nest; vec<data_reference_p> datarefs; vec<ddr_p> dependences; struct component *components; @@ -2426,15 +2436,14 @@ tree_predictive_commoning_loop (struct loop *loop) /* Find the data references and split them into components according to their dependence relations. */ - datarefs.create (10); + stack_vec<loop_p, 3> loop_nest; dependences.create (10); - loop_nest.create (3); + datarefs.create (10); if (! compute_data_dependences_for_loop (loop, true, &loop_nest, &datarefs, &dependences)) { if (dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, "Cannot analyze data dependencies\n"); - loop_nest.release (); free_data_refs (datarefs); free_dependence_relations (dependences); return false; diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c index c88d0731acf..1d831ee24ab 100644 --- a/gcc/tree-pretty-print.c +++ b/gcc/tree-pretty-print.c @@ -25,7 +25,8 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "tree-pretty-print.h" #include "hashtab.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "cgraph.h" #include "langhooks.h" #include "tree-iterator.h" #include "tree-chrec.h" @@ -866,6 +867,7 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags, break; case VOID_TYPE: + case POINTER_BOUNDS_TYPE: case INTEGER_TYPE: case REAL_TYPE: case FIXED_POINT_TYPE: @@ -2108,6 +2110,18 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags, pp_string (buffer, " predictor."); break; + case ANNOTATE_EXPR: + pp_string (buffer, "ANNOTATE_EXPR <"); + switch ((enum annot_expr_kind) tree_to_shwi (TREE_OPERAND (node, 1))) + { + case annot_expr_ivdep_kind: + pp_string (buffer, "ivdep, "); + break; + } + dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false); + pp_greater (buffer); + break; + case RETURN_EXPR: pp_string (buffer, "return"); op0 = TREE_OPERAND (node, 0); @@ -2644,6 +2658,15 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags, dump_block_node (buffer, node, spc, flags); break; + case CILK_SPAWN_STMT: + pp_string (buffer, "_Cilk_spawn "); + dump_generic_node (buffer, TREE_OPERAND (node, 0), spc, flags, false); + break; + + case CILK_SYNC_STMT: + pp_string (buffer, "_Cilk_sync"); + break; + default: NIY; } @@ -3390,7 +3413,7 @@ dump_function_header (FILE *dump_file, tree fdecl, int flags) fprintf (dump_file, ", decl_uid=%d", DECL_UID (fdecl)); if (node) { - fprintf (dump_file, ", symbol_order=%d)%s\n\n", node->symbol.order, + fprintf (dump_file, ", symbol_order=%d)%s\n\n", node->order, node->frequency == NODE_FREQUENCY_HOT ? " (hot)" : node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED diff --git a/gcc/tree-profile.c b/gcc/tree-profile.c index d5713ac6521..e98ea686fbc 100644 --- a/gcc/tree-profile.c +++ b/gcc/tree-profile.c @@ -34,10 +34,14 @@ along with GCC; see the file COPYING3. If not see #include "diagnostic-core.h" #include "coverage.h" #include "tree.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "cgraph.h" +#include "tree-cfg.h" +#include "tree-ssanames.h" +#include "tree-into-ssa.h" #include "tree-pass.h" #include "value-prof.h" -#include "cgraph.h" #include "profile.h" #include "target.h" #include "tree-cfgcleanup.h" @@ -524,14 +528,14 @@ tree_profiling (void) FOR_EACH_DEFINED_FUNCTION (node) { - if (!gimple_has_body_p (node->symbol.decl)) + if (!gimple_has_body_p (node->decl)) continue; /* Don't profile functions produced for builtin stuff. */ - if (DECL_SOURCE_LOCATION (node->symbol.decl) == BUILTINS_LOCATION) + if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION) continue; - push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl)); + push_cfun (DECL_STRUCT_FUNCTION (node->decl)); /* Local pure-const may imply need to fixup the cfg. */ if (execute_fixup_cfg () & TODO_cleanup_cfg) @@ -559,13 +563,13 @@ tree_profiling (void) /* Drop pure/const flags from instrumented functions. */ FOR_EACH_DEFINED_FUNCTION (node) { - if (!gimple_has_body_p (node->symbol.decl) + if (!gimple_has_body_p (node->decl) || !(!node->clone_of - || node->symbol.decl != node->clone_of->symbol.decl)) + || node->decl != node->clone_of->decl)) continue; /* Don't profile functions produced for builtin stuff. */ - if (DECL_SOURCE_LOCATION (node->symbol.decl) == BUILTINS_LOCATION) + if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION) continue; cgraph_set_const_flag (node, false, false); @@ -577,16 +581,16 @@ tree_profiling (void) { basic_block bb; - if (!gimple_has_body_p (node->symbol.decl) + if (!gimple_has_body_p (node->decl) || !(!node->clone_of - || node->symbol.decl != node->clone_of->symbol.decl)) + || node->decl != node->clone_of->decl)) continue; /* Don't profile functions produced for builtin stuff. */ - if (DECL_SOURCE_LOCATION (node->symbol.decl) == BUILTINS_LOCATION) + if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION) continue; - push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl)); + push_cfun (DECL_STRUCT_FUNCTION (node->decl)); FOR_EACH_BB (bb) { diff --git a/gcc/tree-scalar-evolution.c b/gcc/tree-scalar-evolution.c index 16d9d7d4b23..cafc70cb54b 100644 --- a/gcc/tree-scalar-evolution.c +++ b/gcc/tree-scalar-evolution.c @@ -259,6 +259,15 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "hash-table.h" #include "gimple-pretty-print.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "tree-ssanames.h" +#include "tree-ssa-loop-ivopts.h" +#include "tree-ssa-loop-manip.h" +#include "tree-ssa-loop-niter.h" +#include "tree-ssa-loop.h" #include "tree-ssa.h" #include "cfgloop.h" #include "tree-chrec.h" diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c index a4e6f629392..4f4d0a00648 100644 --- a/gcc/tree-sra.c +++ b/gcc/tree-sra.c @@ -79,7 +79,13 @@ along with GCC; see the file COPYING3. If not see #include "tm.h" #include "tree.h" #include "gimple.h" -#include "cgraph.h" +#include "bitmap.h" +#include "gimple-ssa.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" +#include "tree-dfa.h" #include "tree-ssa.h" #include "tree-pass.h" #include "ipa-prop.h" @@ -4832,14 +4838,14 @@ convert_callers_for_node (struct cgraph_node *node, for (cs = node->callers; cs; cs = cs->next_caller) { - push_cfun (DECL_STRUCT_FUNCTION (cs->caller->symbol.decl)); + push_cfun (DECL_STRUCT_FUNCTION (cs->caller->decl)); if (dump_file) fprintf (dump_file, "Adjusting call %s/%i -> %s/%i\n", xstrdup (cgraph_node_name (cs->caller)), - cs->caller->symbol.order, + cs->caller->order, xstrdup (cgraph_node_name (cs->callee)), - cs->callee->symbol.order); + cs->callee->order); ipa_modify_call_arguments (cs, cs->call_stmt, *adjustments); @@ -4848,7 +4854,7 @@ convert_callers_for_node (struct cgraph_node *node, for (cs = node->callers; cs; cs = cs->next_caller) if (bitmap_set_bit (recomputed_callers, cs->caller->uid) - && gimple_in_ssa_p (DECL_STRUCT_FUNCTION (cs->caller->symbol.decl))) + && gimple_in_ssa_p (DECL_STRUCT_FUNCTION (cs->caller->decl))) compute_inline_parameters (cs->caller, true); BITMAP_FREE (recomputed_callers); @@ -4884,7 +4890,7 @@ convert_callers (struct cgraph_node *node, tree old_decl, { if (dump_file) fprintf (dump_file, "Adjusting recursive call"); - gimple_call_set_fndecl (stmt, node->symbol.decl); + gimple_call_set_fndecl (stmt, node->decl); ipa_modify_call_arguments (NULL, stmt, adjustments); } } @@ -4912,11 +4918,11 @@ modify_function (struct cgraph_node *node, ipa_parm_adjustment_vec adjustments) NULL, false, NULL, NULL, "isra"); redirect_callers.release (); - push_cfun (DECL_STRUCT_FUNCTION (new_node->symbol.decl)); + push_cfun (DECL_STRUCT_FUNCTION (new_node->decl)); ipa_modify_formal_parameters (current_function_decl, adjustments, "ISRA"); cfg_changed = ipa_sra_modify_function_body (adjustments); sra_ipa_reset_debug_stmts (adjustments); - convert_callers (new_node, node->symbol.decl, adjustments); + convert_callers (new_node, node->decl, adjustments); cgraph_make_node_local (new_node); return cfg_changed; } @@ -4952,7 +4958,7 @@ ipa_sra_preliminary_function_checks (struct cgraph_node *node) return false; } - if (!tree_versionable_function_p (node->symbol.decl)) + if (!tree_versionable_function_p (node->decl)) { if (dump_file) fprintf (dump_file, "Function is not versionable.\n"); @@ -4966,7 +4972,7 @@ ipa_sra_preliminary_function_checks (struct cgraph_node *node) return false; } - if ((DECL_COMDAT (node->symbol.decl) || DECL_EXTERNAL (node->symbol.decl)) + if ((DECL_COMDAT (node->decl) || DECL_EXTERNAL (node->decl)) && inline_summary (node)->size >= MAX_INLINE_INSNS_AUTO) { if (dump_file) @@ -4989,7 +4995,7 @@ ipa_sra_preliminary_function_checks (struct cgraph_node *node) return false; } - if (TYPE_ATTRIBUTES (TREE_TYPE (node->symbol.decl))) + if (TYPE_ATTRIBUTES (TREE_TYPE (node->decl))) return false; return true; diff --git a/gcc/tree-ssa-address.c b/gcc/tree-ssa-address.c index 0d587896896..d97f7bbdf7a 100644 --- a/gcc/tree-ssa-address.c +++ b/gcc/tree-ssa-address.c @@ -28,7 +28,10 @@ along with GCC; see the file COPYING3. If not see #include "tm_p.h" #include "basic-block.h" #include "tree-pretty-print.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "tree-ssanames.h" +#include "tree-ssa-loop-ivopts.h" +#include "tree-dfa.h" #include "dumpfile.h" #include "flags.h" #include "tree-inline.h" diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c index 5e80e66479c..1a58ce722ed 100644 --- a/gcc/tree-ssa-alias.c +++ b/gcc/tree-ssa-alias.c @@ -34,11 +34,12 @@ along with GCC; see the file COPYING3. If not see #include "tree-pretty-print.h" #include "dumpfile.h" #include "gimple.h" -#include "tree-ssa.h" +#include "gimple-ssa.h" +#include "tree-ssanames.h" +#include "tree-dfa.h" #include "tree-inline.h" #include "params.h" #include "vec.h" -#include "bitmap.h" #include "pointer-set.h" #include "alloc-pool.h" #include "tree-ssa-alias.h" @@ -565,8 +566,24 @@ ao_ref_alias_set (ao_ref *ref) void ao_ref_init_from_ptr_and_size (ao_ref *ref, tree ptr, tree size) { - HOST_WIDE_INT t1, t2; + HOST_WIDE_INT t1, t2, extra_offset = 0; ref->ref = NULL_TREE; + if (TREE_CODE (ptr) == SSA_NAME) + { + gimple stmt = SSA_NAME_DEF_STMT (ptr); + if (gimple_assign_single_p (stmt) + && gimple_assign_rhs_code (stmt) == ADDR_EXPR) + ptr = gimple_assign_rhs1 (stmt); + else if (is_gimple_assign (stmt) + && gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR + && tree_fits_shwi_p (gimple_assign_rhs2 (stmt)) + && (t1 = int_cst_value (gimple_assign_rhs2 (stmt))) >= 0) + { + ptr = gimple_assign_rhs1 (stmt); + extra_offset = BITS_PER_UNIT * t1; + } + } + if (TREE_CODE (ptr) == ADDR_EXPR) ref->base = get_ref_base_and_extent (TREE_OPERAND (ptr, 0), &ref->offset, &t1, &t2); @@ -576,10 +593,11 @@ ao_ref_init_from_ptr_and_size (ao_ref *ref, tree ptr, tree size) ptr, null_pointer_node); ref->offset = 0; } + ref->offset += extra_offset; if (size && tree_fits_shwi_p (size) - && tree_to_shwi (size) * 8 / 8 == tree_to_shwi (size)) - ref->max_size = ref->size = tree_to_shwi (size) * 8; + && tree_to_shwi (size) * BITS_PER_UNIT / BITS_PER_UNIT == tree_to_shwi (size)) + ref->max_size = ref->size = tree_to_shwi (size) * BITS_PER_UNIT; else ref->max_size = ref->size = -1; ref->ref_alias_set = 0; @@ -727,11 +745,8 @@ aliasing_component_refs_p (tree ref1, static bool nonoverlapping_component_refs_of_decl_p (tree ref1, tree ref2) { - vec<tree, va_stack> component_refs1; - vec<tree, va_stack> component_refs2; - - vec_stack_alloc (tree, component_refs1, 16); - vec_stack_alloc (tree, component_refs2, 16); + stack_vec<tree, 16> component_refs1; + stack_vec<tree, 16> component_refs2; /* Create the stack of handled components for REF1. */ while (handled_component_p (ref1)) @@ -2054,6 +2069,16 @@ stmt_kills_ref_p_1 (gimple stmt, ao_ref *ref) && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL) switch (DECL_FUNCTION_CODE (callee)) { + case BUILT_IN_FREE: + { + tree ptr = gimple_call_arg (stmt, 0); + tree base = ao_ref_base (ref); + if (base && TREE_CODE (base) == MEM_REF + && TREE_OPERAND (base, 0) == ptr) + return true; + break; + } + case BUILT_IN_MEMCPY: case BUILT_IN_MEMPCPY: case BUILT_IN_MEMMOVE: diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c index 202703b2052..1c86bf93e9a 100644 --- a/gcc/tree-ssa-ccp.c +++ b/gcc/tree-ssa-ccp.c @@ -128,7 +128,12 @@ along with GCC; see the file COPYING3. If not see #include "basic-block.h" #include "function.h" #include "gimple-pretty-print.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" #include "tree-pass.h" #include "tree-ssa-propagate.h" #include "value-prof.h" @@ -267,6 +272,19 @@ get_default_value (tree var) { val.lattice_val = VARYING; val.mask = -1; + if (flag_tree_bit_ccp) + { + widest_int nonzero_bits = get_nonzero_bits (var); + widest_int mask + = wi::mask <widest_int> (TYPE_PRECISION (TREE_TYPE (var)), false); + if (nonzero_bits != -1 && nonzero_bits != mask) + { + val.lattice_val = CONSTANT; + val.value = build_zero_cst (TREE_TYPE (var)); + /* CCP wants the bits above precision set. */ + val.mask = nonzero_bits | ~mask; + } + } } } else if (is_gimple_assign (stmt)) @@ -832,7 +850,8 @@ ccp_finalize (void) do_dbg_cnt (); /* Derive alignment and misalignment information from partially - constant pointers in the lattice. */ + constant pointers in the lattice or nonzero bits from partially + constant integers. */ for (i = 1; i < num_ssa_names; ++i) { tree name = ssa_name (i); @@ -840,7 +859,11 @@ ccp_finalize (void) unsigned int tem, align; if (!name - || !POINTER_TYPE_P (TREE_TYPE (name))) + || (!POINTER_TYPE_P (TREE_TYPE (name)) + && (!INTEGRAL_TYPE_P (TREE_TYPE (name)) + /* Don't record nonzero bits before IPA to avoid + using too much memory. */ + || first_pass_instance))) continue; val = get_value (name); @@ -848,13 +871,24 @@ ccp_finalize (void) || TREE_CODE (val->value) != INTEGER_CST) continue; - /* Trailing constant bits specify the alignment, trailing value - bits the misalignment. */ - tem = val->mask.to_uhwi (); - align = (tem & -tem); - if (align > 1) - set_ptr_info_alignment (get_ptr_info (name), align, - tree_to_hwi (val->value) & (align - 1)); + if (POINTER_TYPE_P (TREE_TYPE (name))) + { + /* Trailing mask bits specify the alignment, trailing value + bits the misalignment. */ + tem = val->mask.to_uhwi (); + align = (tem & -tem); + if (align > 1) + set_ptr_info_alignment (get_ptr_info (name), align, + (tree_to_hwi (val->value) + & (align - 1))); + } + else + { + widest_int nonzero_bits = val->mask; + nonzero_bits = nonzero_bits | wi::to_widest (val->value); + nonzero_bits &= get_nonzero_bits (name); + set_nonzero_bits (name, nonzero_bits); + } } /* Perform substitutions based on the known constant values. */ @@ -1712,6 +1746,39 @@ evaluate_stmt (gimple stmt) is_constant = (val.lattice_val == CONSTANT); } + if (flag_tree_bit_ccp + && ((is_constant && TREE_CODE (val.value) == INTEGER_CST) + || (!is_constant && likelyvalue != UNDEFINED)) + && gimple_get_lhs (stmt) + && TREE_CODE (gimple_get_lhs (stmt)) == SSA_NAME) + { + tree lhs = gimple_get_lhs (stmt); + widest_int nonzero_bits = get_nonzero_bits (lhs); + widest_int mask = wi::mask <widest_int> (TYPE_PRECISION (TREE_TYPE (lhs)), false); + if (nonzero_bits != -1 && nonzero_bits != mask) + { + if (!is_constant) + { + val.lattice_val = CONSTANT; + val.value = build_zero_cst (TREE_TYPE (lhs)); + /* CCP wants the bits above precision set. */ + val.mask = nonzero_bits | ~mask; + is_constant = true; + } + else + { + widest_int valv = wi::to_widest (val.value); + if ((valv & ~nonzero_bits & mask) != 0) + val.value = wide_int_to_tree (TREE_TYPE (lhs), + valv & nonzero_bits); + if (nonzero_bits == 0) + val.mask = 0; + else + val.mask = val.mask & (nonzero_bits | ~mask); + } + } + } + if (!is_constant) { /* The statement produced a nonconstant value. If the statement diff --git a/gcc/tree-ssa-coalesce.c b/gcc/tree-ssa-coalesce.c index 2f5507ca8fc..c445c78626e 100644 --- a/gcc/tree-ssa-coalesce.c +++ b/gcc/tree-ssa-coalesce.c @@ -27,9 +27,14 @@ along with GCC; see the file COPYING3. If not see #include "tree-pretty-print.h" #include "bitmap.h" #include "dumpfile.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" #include "hash-table.h" -#include "tree-outof-ssa.h" +#include "tree-ssa-live.h" +#include "tree-ssa-coalesce.h" #include "diagnostic-core.h" diff --git a/gcc/tree-ssa-copy.c b/gcc/tree-ssa-copy.c index 4ec941bcbf0..15c6896e945 100644 --- a/gcc/tree-ssa-copy.c +++ b/gcc/tree-ssa-copy.c @@ -27,7 +27,12 @@ along with GCC; see the file COPYING3. If not see #include "basic-block.h" #include "function.h" #include "gimple-pretty-print.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" #include "tree-pass.h" #include "tree-ssa-propagate.h" #include "langhooks.h" diff --git a/gcc/tree-ssa-copyrename.c b/gcc/tree-ssa-copyrename.c index d8660c56e62..30b339def7d 100644 --- a/gcc/tree-ssa-copyrename.c +++ b/gcc/tree-ssa-copyrename.c @@ -29,8 +29,9 @@ along with GCC; see the file COPYING3. If not see #include "function.h" #include "tree-pretty-print.h" #include "bitmap.h" -#include "tree-ssa.h" -#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-ssanames.h" +#include "tree-dfa.h" #include "tree-inline.h" #include "hashtab.h" #include "tree-ssa-live.h" diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c index 7b0cd2819bc..72e2fb8fa65 100644 --- a/gcc/tree-ssa-dce.c +++ b/gcc/tree-ssa-dce.c @@ -50,8 +50,15 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "gimple-pretty-print.h" #include "basic-block.h" -#include "tree-ssa.h" #include "gimple.h" +#include "gimple-ssa.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" +#include "tree-ssa-loop-niter.h" +#include "tree-into-ssa.h" +#include "tree-dfa.h" #include "tree-pass.h" #include "flags.h" #include "cfgloop.h" diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c index 4ce29aed54e..211bfcf5cc4 100644 --- a/gcc/tree-ssa-dom.c +++ b/gcc/tree-ssa-dom.c @@ -30,7 +30,13 @@ along with GCC; see the file COPYING3. If not see #include "cfgloop.h" #include "function.h" #include "gimple-pretty-print.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" +#include "tree-into-ssa.h" #include "domwalk.h" #include "tree-pass.h" #include "tree-ssa-propagate.h" diff --git a/gcc/tree-ssa-dse.c b/gcc/tree-ssa-dse.c index f73fb3c522b..202eb3e673b 100644 --- a/gcc/tree-ssa-dse.c +++ b/gcc/tree-ssa-dse.c @@ -26,7 +26,14 @@ along with GCC; see the file COPYING3. If not see #include "tm_p.h" #include "basic-block.h" #include "gimple-pretty-print.h" -#include "tree-ssa.h" +#include "bitmap.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" +#include "tree-dfa.h" #include "tree-pass.h" #include "domwalk.h" #include "flags.h" diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c index 1b5ea19f956..5721861331a 100644 --- a/gcc/tree-ssa-forwprop.c +++ b/gcc/tree-ssa-forwprop.c @@ -25,11 +25,16 @@ along with GCC; see the file COPYING3. If not see #include "tm_p.h" #include "basic-block.h" #include "gimple-pretty-print.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" +#include "tree-dfa.h" #include "tree-pass.h" #include "langhooks.h" #include "flags.h" -#include "gimple.h" #include "expr.h" #include "cfgloop.h" #include "optabs.h" diff --git a/gcc/tree-ssa-ifcombine.c b/gcc/tree-ssa-ifcombine.c index 268275e3968..73ebfe8b24e 100644 --- a/gcc/tree-ssa-ifcombine.c +++ b/gcc/tree-ssa-ifcombine.c @@ -22,12 +22,26 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "tm.h" +/* rtl is needed only because arm back-end requires it for + BRANCH_COST. */ +#include "rtl.h" +#include "tm_p.h" #include "tree.h" #include "basic-block.h" #include "tree-pretty-print.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" #include "tree-pass.h" +#ifndef LOGICAL_OP_NON_SHORT_CIRCUIT +#define LOGICAL_OP_NON_SHORT_CIRCUIT \ + (BRANCH_COST (optimize_function_for_speed_p (cfun), \ + false) >= 2) +#endif + /* This pass combines COND_EXPRs to simplify control flow. It currently recognizes bit tests and comparisons in chains that represent logical and or logical or of two COND_EXPRs. @@ -484,7 +498,35 @@ ifcombine_ifandif (basic_block inner_cond_bb, bool inner_inv, outer_cond_code, gimple_cond_lhs (outer_cond), gimple_cond_rhs (outer_cond)))) - return false; + { + tree t1, t2; + gimple_stmt_iterator gsi; + if (!LOGICAL_OP_NON_SHORT_CIRCUIT) + return false; + /* Only do this optimization if the inner bb contains only the conditional. */ + if (!gsi_one_before_end_p (gsi_start_nondebug_after_labels_bb (inner_cond_bb))) + return false; + t1 = fold_build2_loc (gimple_location (inner_cond), + inner_cond_code, + boolean_type_node, + gimple_cond_lhs (inner_cond), + gimple_cond_rhs (inner_cond)); + t2 = fold_build2_loc (gimple_location (outer_cond), + outer_cond_code, + boolean_type_node, + gimple_cond_lhs (outer_cond), + gimple_cond_rhs (outer_cond)); + t = fold_build2_loc (gimple_location (inner_cond), + TRUTH_AND_EXPR, boolean_type_node, t1, t2); + if (result_inv) + { + t = fold_build1 (TRUTH_NOT_EXPR, TREE_TYPE (t), t); + result_inv = false; + } + gsi = gsi_for_stmt (inner_cond); + t = force_gimple_operand_gsi_1 (&gsi, t, is_gimple_condexpr, NULL, true, + GSI_SAME_STMT); + } if (result_inv) t = fold_build1 (TRUTH_NOT_EXPR, TREE_TYPE (t), t); t = canonicalize_cond_expr_cond (t); @@ -627,7 +669,15 @@ tree_ssa_ifcombine (void) bbs = single_pred_before_succ_order (); calculate_dominance_info (CDI_DOMINATORS); - for (i = 0; i < n_basic_blocks - NUM_FIXED_BLOCKS; ++i) + /* Search every basic block for COND_EXPR we may be able to optimize. + + We walk the blocks in order that guarantees that a block with + a single predecessor is processed after the predecessor. + This ensures that we collapse outter ifs before visiting the + inner ones, and also that we do not try to visit a removed + block. This is opposite of PHI-OPT, because we cascade the + combining rather than cascading PHIs. */ + for (i = n_basic_blocks - NUM_FIXED_BLOCKS - 1; i >= 0; i--) { basic_block bb = bbs[i]; gimple stmt = last_stmt (bb); diff --git a/gcc/tree-ssa-live.c b/gcc/tree-ssa-live.c index 94a9beead58..17849a21159 100644 --- a/gcc/tree-ssa-live.c +++ b/gcc/tree-ssa-live.c @@ -27,14 +27,18 @@ along with GCC; see the file COPYING3. If not see #include "gimple-pretty-print.h" #include "bitmap.h" #include "sbitmap.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" +#include "tree-dfa.h" #include "timevar.h" #include "dumpfile.h" #include "tree-ssa-live.h" #include "diagnostic-core.h" #include "debug.h" #include "flags.h" -#include "gimple.h" #ifdef ENABLE_CHECKING static void verify_live_on_entry (tree_live_info_p); diff --git a/gcc/tree-ssa-loop-ch.c b/gcc/tree-ssa-loop-ch.c index 15b34bb9d0c..b74c56de330 100644 --- a/gcc/tree-ssa-loop-ch.c +++ b/gcc/tree-ssa-loop-ch.c @@ -24,7 +24,10 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "tm_p.h" #include "basic-block.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-cfg.h" +#include "tree-into-ssa.h" #include "tree-pass.h" #include "cfgloop.h" #include "tree-inline.h" diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c index bfd2ca7148b..10a86814abd 100644 --- a/gcc/tree-ssa-loop-im.c +++ b/gcc/tree-ssa-loop-im.c @@ -25,7 +25,15 @@ along with GCC; see the file COPYING3. If not see #include "tm_p.h" #include "basic-block.h" #include "gimple-pretty-print.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" +#include "tree-ssa-loop-manip.h" +#include "tree-ssa-loop.h" +#include "tree-into-ssa.h" #include "cfgloop.h" #include "domwalk.h" #include "params.h" diff --git a/gcc/tree-ssa-loop-ivcanon.c b/gcc/tree-ssa-loop-ivcanon.c index 50ce3a8d2a6..99abd9e480a 100644 --- a/gcc/tree-ssa-loop-ivcanon.c +++ b/gcc/tree-ssa-loop-ivcanon.c @@ -40,7 +40,17 @@ along with GCC; see the file COPYING3. If not see #include "tm_p.h" #include "basic-block.h" #include "gimple-pretty-print.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "cgraph.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" +#include "tree-ssa-loop-manip.h" +#include "tree-ssa-loop-niter.h" +#include "tree-ssa-loop.h" +#include "tree-into-ssa.h" #include "cfgloop.h" #include "tree-pass.h" #include "tree-chrec.h" @@ -1090,7 +1100,7 @@ propagate_constants_for_unrolling (basic_block bb) static bool tree_unroll_loops_completely_1 (bool may_increase_size, bool unroll_outer, - vec<loop_p, va_stack>& father_stack, + vec<loop_p, va_heap>& father_stack, struct loop *loop) { struct loop *loop_father; @@ -1154,12 +1164,11 @@ tree_unroll_loops_completely_1 (bool may_increase_size, bool unroll_outer, unsigned int tree_unroll_loops_completely (bool may_increase_size, bool unroll_outer) { - vec<loop_p, va_stack> father_stack; + stack_vec<loop_p, 16> father_stack; bool changed; int iteration = 0; bool irred_invalidated = false; - vec_stack_alloc (loop_p, father_stack, 16); do { changed = false; diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c index 6846fcf6115..9e6a9920bad 100644 --- a/gcc/tree-ssa-loop-ivopts.c +++ b/gcc/tree-ssa-loop-ivopts.c @@ -69,6 +69,18 @@ along with GCC; see the file COPYING3. If not see #include "tm_p.h" #include "basic-block.h" #include "gimple-pretty-print.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "cgraph.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" +#include "tree-ssa-loop-ivopts.h" +#include "tree-ssa-loop-manip.h" +#include "tree-ssa-loop-niter.h" +#include "tree-ssa-loop.h" +#include "tree-dfa.h" #include "tree-ssa.h" #include "cfgloop.h" #include "tree-pass.h" @@ -2011,12 +2023,12 @@ find_interesting_uses (struct ivopts_data *data) static tree strip_offset_1 (tree expr, bool inside_addr, bool top_compref, - unsigned HOST_WIDE_INT *offset) + HOST_WIDE_INT *offset) { tree op0 = NULL_TREE, op1 = NULL_TREE, tmp, step; enum tree_code code; tree type, orig_type = TREE_TYPE (expr); - unsigned HOST_WIDE_INT off0, off1, st; + HOST_WIDE_INT off0, off1, st; tree orig_expr = expr; STRIP_NOPS (expr); @@ -2107,19 +2119,32 @@ strip_offset_1 (tree expr, bool inside_addr, bool top_compref, break; case COMPONENT_REF: - if (!inside_addr) - return orig_expr; + { + tree field; - tmp = component_ref_field_offset (expr); - if (top_compref - && cst_fits_shwi_p (tmp)) - { - /* Strip the component reference completely. */ - op0 = TREE_OPERAND (expr, 0); - op0 = strip_offset_1 (op0, inside_addr, top_compref, &off0); - *offset = off0 + int_cst_value (tmp); - return op0; - } + if (!inside_addr) + return orig_expr; + + tmp = component_ref_field_offset (expr); + field = TREE_OPERAND (expr, 1); + if (top_compref + && cst_fits_shwi_p (tmp) + && cst_fits_shwi_p (DECL_FIELD_BIT_OFFSET (field))) + { + HOST_WIDE_INT boffset, abs_off; + + /* Strip the component reference completely. */ + op0 = TREE_OPERAND (expr, 0); + op0 = strip_offset_1 (op0, inside_addr, top_compref, &off0); + boffset = int_cst_value (DECL_FIELD_BIT_OFFSET (field)); + abs_off = abs_hwi (boffset) / BITS_PER_UNIT; + if (boffset < 0) + abs_off = -abs_off; + + *offset = off0 + int_cst_value (tmp) + abs_off; + return op0; + } + } break; case ADDR_EXPR: @@ -2170,7 +2195,10 @@ strip_offset_1 (tree expr, bool inside_addr, bool top_compref, static tree strip_offset (tree expr, unsigned HOST_WIDE_INT *offset) { - return strip_offset_1 (expr, false, false, offset); + HOST_WIDE_INT off; + tree core = strip_offset_1 (expr, false, false, &off); + *offset = off; + return core; } /* Returns variant of TYPE that can be used as base for different uses. @@ -3111,16 +3139,19 @@ multiplier_allowed_in_address_p (HOST_WIDE_INT ratio, enum machine_mode mode, { enum machine_mode address_mode = targetm.addr_space.address_mode (as); rtx reg1 = gen_raw_REG (address_mode, LAST_VIRTUAL_REGISTER + 1); - rtx addr; + rtx reg2 = gen_raw_REG (address_mode, LAST_VIRTUAL_REGISTER + 2); + rtx addr, scaled; HOST_WIDE_INT i; valid_mult = sbitmap_alloc (2 * MAX_RATIO + 1); bitmap_clear (valid_mult); - addr = gen_rtx_fmt_ee (MULT, address_mode, reg1, NULL_RTX); + scaled = gen_rtx_fmt_ee (MULT, address_mode, reg1, NULL_RTX); + addr = gen_rtx_fmt_ee (PLUS, address_mode, scaled, reg2); for (i = -MAX_RATIO; i <= MAX_RATIO; i++) { - XEXP (addr, 1) = gen_int_mode (i, address_mode); - if (memory_address_addr_space_p (mode, addr, as)) + XEXP (scaled, 1) = gen_int_mode (i, address_mode); + if (memory_address_addr_space_p (mode, addr, as) + || memory_address_addr_space_p (mode, scaled, as)) bitmap_set_bit (valid_mult, i + MAX_RATIO); } diff --git a/gcc/tree-ssa-loop-manip.c b/gcc/tree-ssa-loop-manip.c index e44458e4a0f..da9761be655 100644 --- a/gcc/tree-ssa-loop-manip.c +++ b/gcc/tree-ssa-loop-manip.c @@ -24,6 +24,17 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "tm_p.h" #include "basic-block.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" +#include "tree-ssa-loop-ivopts.h" +#include "tree-ssa-loop-manip.h" +#include "tree-ssa-loop-niter.h" +#include "tree-ssa-loop.h" +#include "tree-into-ssa.h" #include "tree-ssa.h" #include "dumpfile.h" #include "gimple-pretty-print.h" diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c index 0b37c91f68d..9a07db20e61 100644 --- a/gcc/tree-ssa-loop-niter.c +++ b/gcc/tree-ssa-loop-niter.c @@ -26,7 +26,14 @@ along with GCC; see the file COPYING3. If not see #include "basic-block.h" #include "gimple-pretty-print.h" #include "intl.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssa-loop-ivopts.h" +#include "tree-ssa-loop-niter.h" +#include "tree-ssa-loop.h" #include "dumpfile.h" #include "cfgloop.h" #include "ggc.h" diff --git a/gcc/tree-ssa-loop-prefetch.c b/gcc/tree-ssa-loop-prefetch.c index b05a99c68df..6a84bdc0496 100644 --- a/gcc/tree-ssa-loop-prefetch.c +++ b/gcc/tree-ssa-loop-prefetch.c @@ -25,7 +25,13 @@ along with GCC; see the file COPYING3. If not see #include "tm_p.h" #include "basic-block.h" #include "tree-pretty-print.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-ssa-loop-ivopts.h" +#include "tree-ssa-loop-manip.h" +#include "tree-ssa-loop-niter.h" +#include "tree-ssa-loop.h" +#include "tree-into-ssa.h" #include "cfgloop.h" #include "tree-pass.h" #include "insn-config.h" diff --git a/gcc/tree-ssa-loop-unswitch.c b/gcc/tree-ssa-loop-unswitch.c index 74af9758b1a..e2b1c0735ad 100644 --- a/gcc/tree-ssa-loop-unswitch.c +++ b/gcc/tree-ssa-loop-unswitch.c @@ -24,7 +24,14 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "tm_p.h" #include "basic-block.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssa-loop-niter.h" +#include "tree-ssa-loop.h" +#include "tree-into-ssa.h" #include "cfgloop.h" #include "params.h" #include "tree-pass.h" diff --git a/gcc/tree-ssa-loop.c b/gcc/tree-ssa-loop.c index cbb14e6066d..9bb002868be 100644 --- a/gcc/tree-ssa-loop.c +++ b/gcc/tree-ssa-loop.c @@ -24,7 +24,11 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "tm_p.h" #include "basic-block.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "tree-ssa-loop-ivopts.h" +#include "tree-ssa-loop-manip.h" +#include "tree-ssa-loop-niter.h" +#include "tree-ssa-loop.h" #include "tree-pass.h" #include "cfgloop.h" #include "flags.h" diff --git a/gcc/tree-ssa-loop.h b/gcc/tree-ssa-loop.h index 3f6a6bcc5fa..0eb8b742f92 100644 --- a/gcc/tree-ssa-loop.h +++ b/gcc/tree-ssa-loop.h @@ -20,9 +20,6 @@ along with GCC; see the file COPYING3. If not see #ifndef GCC_TREE_SSA_LOOP_H #define GCC_TREE_SSA_LOOP_H -#include "tree-ssa-loop-ivopts.h" -#include "tree-ssa-loop-manip.h" -#include "tree-ssa-loop-niter.h" #include "wide-int.h" /* Affine iv. */ diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c index e7a489d6e77..b338f63eb5f 100644 --- a/gcc/tree-ssa-math-opts.c +++ b/gcc/tree-ssa-math-opts.c @@ -90,6 +90,13 @@ along with GCC; see the file COPYING3. If not see #include "tm.h" #include "flags.h" #include "tree.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" +#include "tree-dfa.h" #include "tree-ssa.h" #include "tree-pass.h" #include "alloc-pool.h" @@ -2425,20 +2432,25 @@ convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt, It might also appear that it would be sufficient to use the existing operands of the widening multiply, but that would limit the choice of - multiply-and-accumulate instructions. */ + multiply-and-accumulate instructions. + + If the widened-multiplication result has more than one uses, it is + probably wiser not to do the conversion. */ if (code == PLUS_EXPR && (rhs1_code == MULT_EXPR || rhs1_code == WIDEN_MULT_EXPR)) { - if (!is_widening_mult_p (rhs1_stmt, &type1, &mult_rhs1, - &type2, &mult_rhs2)) + if (!has_single_use (rhs1) + || !is_widening_mult_p (rhs1_stmt, &type1, &mult_rhs1, + &type2, &mult_rhs2)) return false; add_rhs = rhs2; conv_stmt = conv1_stmt; } else if (rhs2_code == MULT_EXPR || rhs2_code == WIDEN_MULT_EXPR) { - if (!is_widening_mult_p (rhs2_stmt, &type1, &mult_rhs1, - &type2, &mult_rhs2)) + if (!has_single_use (rhs2) + || !is_widening_mult_p (rhs2_stmt, &type1, &mult_rhs1, + &type2, &mult_rhs2)) return false; add_rhs = rhs1; conv_stmt = conv2_stmt; diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c index f397bb94f0a..4e05d2df046 100644 --- a/gcc/tree-ssa-operands.c +++ b/gcc/tree-ssa-operands.c @@ -25,7 +25,12 @@ along with GCC; see the file COPYING3. If not see #include "flags.h" #include "function.h" #include "gimple-pretty-print.h" -#include "tree-ssa.h" +#include "bitmap.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" #include "tree-inline.h" #include "timevar.h" #include "dumpfile.h" diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c index 9435cc1b10c..5e8a7ce57a5 100644 --- a/gcc/tree-ssa-phiopt.c +++ b/gcc/tree-ssa-phiopt.c @@ -27,7 +27,13 @@ along with GCC; see the file COPYING3. If not see #include "flags.h" #include "tm_p.h" #include "basic-block.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" +#include "tree-dfa.h" #include "tree-pass.h" #include "langhooks.h" #include "pointer-set.h" @@ -1674,7 +1680,6 @@ cond_if_else_store_replacement (basic_block then_bb, basic_block else_bb, data_reference_p then_dr, else_dr; int i, j; tree then_lhs, else_lhs; - vec<gimple> then_stores, else_stores; basic_block blocks[3]; if (MAX_STORES_TO_SINK == 0) @@ -1701,8 +1706,7 @@ cond_if_else_store_replacement (basic_block then_bb, basic_block else_bb, } /* Find pairs of stores with equal LHS. */ - then_stores.create (1); - else_stores.create (1); + stack_vec<gimple, 1> then_stores, else_stores; FOR_EACH_VEC_ELT (then_datarefs, i, then_dr) { if (DR_IS_READ (then_dr)) @@ -1740,8 +1744,6 @@ cond_if_else_store_replacement (basic_block then_bb, basic_block else_bb, { free_data_refs (then_datarefs); free_data_refs (else_datarefs); - then_stores.release (); - else_stores.release (); return false; } @@ -1757,8 +1759,6 @@ cond_if_else_store_replacement (basic_block then_bb, basic_block else_bb, free_dependence_relations (else_ddrs); free_data_refs (then_datarefs); free_data_refs (else_datarefs); - then_stores.release (); - else_stores.release (); return false; } blocks[0] = then_bb; @@ -1784,8 +1784,6 @@ cond_if_else_store_replacement (basic_block then_bb, basic_block else_bb, free_dependence_relations (else_ddrs); free_data_refs (then_datarefs); free_data_refs (else_datarefs); - then_stores.release (); - else_stores.release (); return false; } } @@ -1808,8 +1806,6 @@ cond_if_else_store_replacement (basic_block then_bb, basic_block else_bb, free_dependence_relations (else_ddrs); free_data_refs (then_datarefs); free_data_refs (else_datarefs); - then_stores.release (); - else_stores.release (); return false; } } @@ -1827,8 +1823,6 @@ cond_if_else_store_replacement (basic_block then_bb, basic_block else_bb, free_dependence_relations (else_ddrs); free_data_refs (then_datarefs); free_data_refs (else_datarefs); - then_stores.release (); - else_stores.release (); return ok; } diff --git a/gcc/tree-ssa-phiprop.c b/gcc/tree-ssa-phiprop.c index f3ea552795d..e0e682e5dc2 100644 --- a/gcc/tree-ssa-phiprop.c +++ b/gcc/tree-ssa-phiprop.c @@ -26,7 +26,11 @@ along with GCC; see the file COPYING3. If not see #include "tm_p.h" #include "basic-block.h" #include "gimple-pretty-print.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" #include "tree-pass.h" #include "langhooks.h" #include "flags.h" diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c index ac8d528ef8d..a5d54877ff2 100644 --- a/gcc/tree-ssa-pre.c +++ b/gcc/tree-ssa-pre.c @@ -27,15 +27,22 @@ along with GCC; see the file COPYING3. If not see #include "basic-block.h" #include "gimple-pretty-print.h" #include "tree-inline.h" -#include "tree-ssa.h" #include "gimple.h" +#include "gimple-ssa.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" +#include "tree-ssa-loop.h" +#include "tree-into-ssa.h" +#include "tree-dfa.h" +#include "tree-ssa.h" #include "hash-table.h" #include "tree-iterator.h" #include "alloc-pool.h" #include "obstack.h" #include "tree-pass.h" #include "flags.h" -#include "bitmap.h" #include "langhooks.h" #include "cfgloop.h" #include "tree-ssa-sccvn.h" diff --git a/gcc/tree-ssa-propagate.c b/gcc/tree-ssa-propagate.c index 180ae85e091..d5bcc9c8cf7 100644 --- a/gcc/tree-ssa-propagate.c +++ b/gcc/tree-ssa-propagate.c @@ -30,12 +30,17 @@ #include "gimple-pretty-print.h" #include "dumpfile.h" #include "sbitmap.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" #include "tree-ssa.h" #include "tree-ssa-propagate.h" #include "langhooks.h" #include "vec.h" #include "value-prof.h" -#include "gimple.h" /* This file implements a generic value propagation engine based on the same propagation used by the SSA-CCP algorithm [1]. diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c index 2533aedfae2..df34bc29ffc 100644 --- a/gcc/tree-ssa-reassoc.c +++ b/gcc/tree-ssa-reassoc.c @@ -29,8 +29,16 @@ along with GCC; see the file COPYING3. If not see #include "basic-block.h" #include "gimple-pretty-print.h" #include "tree-inline.h" -#include "tree-ssa.h" #include "gimple.h" +#include "gimple-ssa.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" +#include "tree-ssa-loop-niter.h" +#include "tree-ssa-loop.h" +#include "tree-dfa.h" +#include "tree-ssa.h" #include "tree-iterator.h" #include "tree-pass.h" #include "alloc-pool.h" @@ -1143,12 +1151,94 @@ zero_one_operation (tree *def, enum tree_code opcode, tree op) while (1); } -/* Returns the UID of STMT if it is non-NULL. Otherwise return 1. */ +/* Returns true if statement S1 dominates statement S2. Like + stmt_dominates_stmt_p, but uses stmt UIDs to optimize. */ -static inline unsigned -get_stmt_uid_with_default (gimple stmt) +static bool +reassoc_stmt_dominates_stmt_p (gimple s1, gimple s2) { - return stmt ? gimple_uid (stmt) : 1; + basic_block bb1 = gimple_bb (s1), bb2 = gimple_bb (s2); + + /* If bb1 is NULL, it should be a GIMPLE_NOP def stmt of an (D) + SSA_NAME. Assume it lives at the beginning of function and + thus dominates everything. */ + if (!bb1 || s1 == s2) + return true; + + /* If bb2 is NULL, it doesn't dominate any stmt with a bb. */ + if (!bb2) + return false; + + if (bb1 == bb2) + { + /* PHIs in the same basic block are assumed to be + executed all in parallel, if only one stmt is a PHI, + it dominates the other stmt in the same basic block. */ + if (gimple_code (s1) == GIMPLE_PHI) + return true; + + if (gimple_code (s2) == GIMPLE_PHI) + return false; + + gcc_assert (gimple_uid (s1) && gimple_uid (s2)); + + if (gimple_uid (s1) < gimple_uid (s2)) + return true; + + if (gimple_uid (s1) > gimple_uid (s2)) + return false; + + gimple_stmt_iterator gsi = gsi_for_stmt (s1); + unsigned int uid = gimple_uid (s1); + for (gsi_next (&gsi); !gsi_end_p (gsi); gsi_next (&gsi)) + { + gimple s = gsi_stmt (gsi); + if (gimple_uid (s) != uid) + break; + if (s == s2) + return true; + } + + return false; + } + + return dominated_by_p (CDI_DOMINATORS, bb2, bb1); +} + +/* Insert STMT after INSERT_POINT. */ + +static void +insert_stmt_after (gimple stmt, gimple insert_point) +{ + gimple_stmt_iterator gsi; + basic_block bb; + + if (gimple_code (insert_point) == GIMPLE_PHI) + bb = gimple_bb (insert_point); + else if (!stmt_ends_bb_p (insert_point)) + { + gsi = gsi_for_stmt (insert_point); + gimple_set_uid (stmt, gimple_uid (insert_point)); + gsi_insert_after (&gsi, stmt, GSI_NEW_STMT); + return; + } + else + /* We assume INSERT_POINT is a SSA_NAME_DEF_STMT of some SSA_NAME, + thus if it must end a basic block, it should be a call that can + throw, or some assignment that can throw. If it throws, the LHS + of it will not be initialized though, so only valid places using + the SSA_NAME should be dominated by the fallthru edge. */ + bb = find_fallthru_edge (gimple_bb (insert_point)->succs)->dest; + gsi = gsi_after_labels (bb); + if (gsi_end_p (gsi)) + { + gimple_stmt_iterator gsi2 = gsi_last_bb (bb); + gimple_set_uid (stmt, + gsi_end_p (gsi2) ? 1 : gimple_uid (gsi_stmt (gsi2))); + } + else + gimple_set_uid (stmt, gimple_uid (gsi_stmt (gsi))); + gsi_insert_before (&gsi, stmt, GSI_SAME_STMT); } /* Builds one statement performing OP1 OPCODE OP2 using TMPVAR for @@ -1176,64 +1266,27 @@ build_and_add_sum (tree type, tree op1, tree op2, enum tree_code opcode) && (!op2def || gimple_nop_p (op2def))) { gsi = gsi_after_labels (single_succ (ENTRY_BLOCK_PTR)); - gimple_set_uid (sum, get_stmt_uid_with_default (gsi_stmt (gsi))); - gsi_insert_before (&gsi, sum, GSI_NEW_STMT); - } - else if ((!op1def || gimple_nop_p (op1def)) - || (op2def && !gimple_nop_p (op2def) - && stmt_dominates_stmt_p (op1def, op2def))) - { - if (gimple_code (op2def) == GIMPLE_PHI) + if (gsi_end_p (gsi)) { - gsi = gsi_after_labels (gimple_bb (op2def)); - gimple_set_uid (sum, get_stmt_uid_with_default (gsi_stmt (gsi))); - gsi_insert_before (&gsi, sum, GSI_NEW_STMT); + gimple_stmt_iterator gsi2 + = gsi_last_bb (single_succ (ENTRY_BLOCK_PTR)); + gimple_set_uid (sum, + gsi_end_p (gsi2) ? 1 : gimple_uid (gsi_stmt (gsi2))); } else - { - if (!stmt_ends_bb_p (op2def)) - { - gsi = gsi_for_stmt (op2def); - gimple_set_uid (sum, gimple_uid (op2def)); - gsi_insert_after (&gsi, sum, GSI_NEW_STMT); - } - else - { - edge e; - edge_iterator ei; - - FOR_EACH_EDGE (e, ei, gimple_bb (op2def)->succs) - if (e->flags & EDGE_FALLTHRU) - gsi_insert_on_edge_immediate (e, sum); - } - } + gimple_set_uid (sum, gimple_uid (gsi_stmt (gsi))); + gsi_insert_before (&gsi, sum, GSI_NEW_STMT); } else { - if (gimple_code (op1def) == GIMPLE_PHI) - { - gsi = gsi_after_labels (gimple_bb (op1def)); - gimple_set_uid (sum, get_stmt_uid_with_default (gsi_stmt (gsi))); - gsi_insert_before (&gsi, sum, GSI_NEW_STMT); - } + gimple insert_point; + if ((!op1def || gimple_nop_p (op1def)) + || (op2def && !gimple_nop_p (op2def) + && reassoc_stmt_dominates_stmt_p (op1def, op2def))) + insert_point = op2def; else - { - if (!stmt_ends_bb_p (op1def)) - { - gsi = gsi_for_stmt (op1def); - gimple_set_uid (sum, gimple_uid (op1def)); - gsi_insert_after (&gsi, sum, GSI_NEW_STMT); - } - else - { - edge e; - edge_iterator ei; - - FOR_EACH_EDGE (e, ei, gimple_bb (op1def)->succs) - if (e->flags & EDGE_FALLTHRU) - gsi_insert_on_edge_immediate (e, sum); - } - } + insert_point = op1def; + insert_stmt_after (sum, insert_point); } update_stmt (sum); @@ -1954,8 +2007,8 @@ range_entry_cmp (const void *a, const void *b) true if the range merge has been successful. If OPCODE is ERROR_MARK, this is called from within maybe_optimize_range_tests and is performing inter-bb range optimization. - Changes should be then performed right away, and whether an op is - BIT_AND_EXPR or BIT_IOR_EXPR is found in oe->rank. */ + In that case, whether an op is BIT_AND_EXPR or BIT_IOR_EXPR is found in + oe->rank. */ static bool update_range_test (struct range_entry *range, struct range_entry *otherrange, @@ -2011,36 +2064,12 @@ update_range_test (struct range_entry *range, struct range_entry *otherrange, gsi = gsi_for_stmt (stmt); tem = force_gimple_operand_gsi (&gsi, tem, true, NULL_TREE, true, GSI_SAME_STMT); + for (gsi_prev (&gsi); !gsi_end_p (gsi); gsi_prev (&gsi)) + if (gimple_uid (gsi_stmt (gsi))) + break; + else + gimple_set_uid (gsi_stmt (gsi), gimple_uid (stmt)); - /* If doing inter-bb range test optimization, update the - stmts immediately. Start with changing the first range test - immediate use to the new value (TEM), or, if the first range - test is a GIMPLE_COND stmt, change that condition. */ - if (opcode == ERROR_MARK) - { - if (op) - { - imm_use_iterator iter; - use_operand_p use_p; - gimple use_stmt; - - FOR_EACH_IMM_USE_STMT (use_stmt, iter, op) - { - if (is_gimple_debug (use_stmt)) - continue; - FOR_EACH_IMM_USE_ON_STMT (use_p, iter) - SET_USE (use_p, tem); - update_stmt (use_stmt); - } - } - else - { - gimple_cond_set_code (stmt, NE_EXPR); - gimple_cond_set_lhs (stmt, tem); - gimple_cond_set_rhs (stmt, boolean_false_node); - update_stmt (stmt); - } - } oe->op = tem; range->exp = exp; range->low = low; @@ -2056,78 +2085,14 @@ update_range_test (struct range_entry *range, struct range_entry *otherrange, if (opcode == ERROR_MARK) { if (oe->op) - { - imm_use_iterator iter; - use_operand_p use_p; - gimple use_stmt; - - FOR_EACH_IMM_USE_STMT (use_stmt, iter, oe->op) - { - if (is_gimple_debug (use_stmt)) - continue; - /* If imm use of _8 is a statement like _7 = _8 | _9;, - adjust it into _7 = _9;. */ - if (is_gimple_assign (use_stmt) - && gimple_assign_rhs_code (use_stmt) == oe->rank) - { - tree expr = NULL_TREE; - if (oe->op == gimple_assign_rhs1 (use_stmt)) - expr = gimple_assign_rhs2 (use_stmt); - else if (oe->op == gimple_assign_rhs2 (use_stmt)) - expr = gimple_assign_rhs1 (use_stmt); - if (expr - && expr != oe->op - && TREE_CODE (expr) == SSA_NAME) - { - gimple_stmt_iterator gsi2 = gsi_for_stmt (use_stmt); - gimple_assign_set_rhs_with_ops (&gsi2, SSA_NAME, - expr, NULL_TREE); - update_stmt (use_stmt); - continue; - } - } - /* If imm use of _8 is a statement like _7 = (int) _8;, - adjust it into _7 = 0; or _7 = 1;. */ - if (gimple_assign_cast_p (use_stmt) - && oe->op == gimple_assign_rhs1 (use_stmt)) - { - tree lhs = gimple_assign_lhs (use_stmt); - if (INTEGRAL_TYPE_P (TREE_TYPE (lhs))) - { - gimple_stmt_iterator gsi2 - = gsi_for_stmt (use_stmt); - tree expr = build_int_cst (TREE_TYPE (lhs), - oe->rank == BIT_IOR_EXPR - ? 0 : 1); - gimple_assign_set_rhs_with_ops (&gsi2, - INTEGER_CST, - expr, NULL_TREE); - update_stmt (use_stmt); - continue; - } - } - /* Otherwise replace the use with 0 or 1. */ - FOR_EACH_IMM_USE_ON_STMT (use_p, iter) - SET_USE (use_p, - build_int_cst (TREE_TYPE (oe->op), - oe->rank == BIT_IOR_EXPR - ? 0 : 1)); - update_stmt (use_stmt); - } - } + oe->op = build_int_cst (TREE_TYPE (oe->op), + oe->rank == BIT_IOR_EXPR ? 0 : 1); else - { - /* If range test was a GIMPLE_COND, simply change it - into an always false or always true condition. */ - stmt = last_stmt (BASIC_BLOCK (oe->id)); - if (oe->rank == BIT_IOR_EXPR) - gimple_cond_make_false (stmt); - else - gimple_cond_make_true (stmt); - update_stmt (stmt); - } + oe->op = (oe->rank == BIT_IOR_EXPR + ? boolean_false_node : boolean_true_node); } - oe->op = error_mark_node; + else + oe->op = error_mark_node; range->exp = NULL_TREE; } return true; @@ -2288,7 +2253,7 @@ optimize_range_tests_1 (enum tree_code opcode, int first, int length, GIMPLE_COND is && or ||ed into the test, and oe->rank says the actual opcode. */ -static void +static bool optimize_range_tests (enum tree_code opcode, vec<operand_entry_t> *ops) { @@ -2298,7 +2263,7 @@ optimize_range_tests (enum tree_code opcode, bool any_changes = false; if (length == 1) - return; + return false; ranges = XNEWVEC (struct range_entry, length); for (i = 0; i < length; i++) @@ -2378,6 +2343,7 @@ optimize_range_tests (enum tree_code opcode, } XDELETEVEC (ranges); + return any_changes; } /* Return true if STMT is a cast like: @@ -2624,6 +2590,60 @@ get_ops (tree var, enum tree_code code, vec<operand_entry_t> *ops, return true; } +/* Find the ops that were added by get_ops starting from VAR, see if + they were changed during update_range_test and if yes, create new + stmts. */ + +static tree +update_ops (tree var, enum tree_code code, vec<operand_entry_t> ops, + unsigned int *pidx, struct loop *loop) +{ + gimple stmt = SSA_NAME_DEF_STMT (var); + tree rhs[4]; + int i; + + if (!is_reassociable_op (stmt, code, loop)) + return NULL; + + rhs[0] = gimple_assign_rhs1 (stmt); + rhs[1] = gimple_assign_rhs2 (stmt); + rhs[2] = rhs[0]; + rhs[3] = rhs[1]; + for (i = 0; i < 2; i++) + if (TREE_CODE (rhs[i]) == SSA_NAME) + { + rhs[2 + i] = update_ops (rhs[i], code, ops, pidx, loop); + if (rhs[2 + i] == NULL_TREE) + { + if (has_single_use (rhs[i])) + rhs[2 + i] = ops[(*pidx)++]->op; + else + rhs[2 + i] = rhs[i]; + } + } + if ((rhs[2] != rhs[0] || rhs[3] != rhs[1]) + && (rhs[2] != rhs[1] || rhs[3] != rhs[0])) + { + gimple_stmt_iterator gsi = gsi_for_stmt (stmt); + var = make_ssa_name (TREE_TYPE (var), NULL); + gimple g = gimple_build_assign_with_ops (gimple_assign_rhs_code (stmt), + var, rhs[2], rhs[3]); + gimple_set_uid (g, gimple_uid (stmt)); + gimple_set_visited (g, true); + gsi_insert_before (&gsi, g, GSI_SAME_STMT); + } + return var; +} + +/* Structure to track the initial value passed to get_ops and + the range in the ops vector for each basic block. */ + +struct inter_bb_range_test_entry +{ + tree op; + unsigned int first_idx, last_idx; +}; + /* Inter-bb range test optimization. */ static void @@ -2636,6 +2656,8 @@ maybe_optimize_range_tests (gimple stmt) edge_iterator ei; edge e; vec<operand_entry_t> ops = vNULL; + vec<inter_bb_range_test_entry> bbinfo = vNULL; + bool any_changes = false; /* Consider only basic blocks that end with GIMPLE_COND or a cast statement satisfying final_range_test_p. All @@ -2737,7 +2759,11 @@ maybe_optimize_range_tests (gimple stmt) { enum tree_code code; tree lhs, rhs; + inter_bb_range_test_entry bb_ent; + bb_ent.op = NULL_TREE; + bb_ent.first_idx = ops.length (); + bb_ent.last_idx = bb_ent.first_idx; e = find_edge (bb, other_bb); stmt = last_stmt (bb); gimple_set_visited (stmt, true); @@ -2794,7 +2820,12 @@ maybe_optimize_range_tests (gimple stmt) oe->id = 0; oe->count = 1; ops.safe_push (oe); + bb_ent.last_idx++; } + else + bb_ent.last_idx = ops.length (); + bb_ent.op = rhs; + bbinfo.safe_push (bb_ent); continue; } /* Otherwise stmt is GIMPLE_COND. */ @@ -2827,12 +2858,119 @@ maybe_optimize_range_tests (gimple stmt) oe->id = bb->index; oe->count = 1; ops.safe_push (oe); + bb_ent.op = NULL; + bb_ent.last_idx++; } + else if (ops.length () > bb_ent.first_idx) + { + bb_ent.op = lhs; + bb_ent.last_idx = ops.length (); + } + bbinfo.safe_push (bb_ent); if (bb == first_bb) break; } if (ops.length () > 1) - optimize_range_tests (ERROR_MARK, &ops); + any_changes = optimize_range_tests (ERROR_MARK, &ops); + if (any_changes) + { + unsigned int idx; + /* update_ops relies on has_single_use predicates returning the + same values as it did during get_ops earlier. Additionally it + never removes statements, only adds new ones and it should walk + from the single imm use and check the predicate already before + making those changes. + On the other side, the handling of GIMPLE_COND directly can turn + previously multiply used SSA_NAMEs into single use SSA_NAMEs, so + it needs to be done in a separate loop afterwards. */ + for (bb = last_bb, idx = 0; ; bb = single_pred (bb), idx++) + { + if (bbinfo[idx].first_idx < bbinfo[idx].last_idx + && bbinfo[idx].op != NULL_TREE) + { + tree new_op; + + stmt = last_stmt (bb); + new_op = update_ops (bbinfo[idx].op, + (enum tree_code) + ops[bbinfo[idx].first_idx]->rank, + ops, &bbinfo[idx].first_idx, + loop_containing_stmt (stmt)); + if (new_op == NULL_TREE) + { + gcc_assert (bb == last_bb); + new_op = ops[bbinfo[idx].first_idx++]->op; + } + if (bbinfo[idx].op != new_op) + { + imm_use_iterator iter; + use_operand_p use_p; + gimple use_stmt, cast_stmt = NULL; + + FOR_EACH_IMM_USE_STMT (use_stmt, iter, bbinfo[idx].op) + if (is_gimple_debug (use_stmt)) + continue; + else if (gimple_code (use_stmt) == GIMPLE_COND + || gimple_code (use_stmt) == GIMPLE_PHI) + FOR_EACH_IMM_USE_ON_STMT (use_p, iter) + SET_USE (use_p, new_op); + else if (gimple_assign_cast_p (use_stmt)) + cast_stmt = use_stmt; + else + gcc_unreachable (); + if (cast_stmt) + { + gcc_assert (bb == last_bb); + tree lhs = gimple_assign_lhs (cast_stmt); + tree new_lhs = make_ssa_name (TREE_TYPE (lhs), NULL); + enum tree_code rhs_code + = gimple_assign_rhs_code (cast_stmt); + gimple g + = gimple_build_assign_with_ops (rhs_code, new_lhs, + new_op, NULL_TREE); + gimple_stmt_iterator gsi = gsi_for_stmt (cast_stmt); + gimple_set_uid (g, gimple_uid (cast_stmt)); + gimple_set_visited (g, true); + gsi_insert_before (&gsi, g, GSI_SAME_STMT); + FOR_EACH_IMM_USE_STMT (use_stmt, iter, lhs) + if (is_gimple_debug (use_stmt)) + continue; + else if (gimple_code (use_stmt) == GIMPLE_COND + || gimple_code (use_stmt) == GIMPLE_PHI) + FOR_EACH_IMM_USE_ON_STMT (use_p, iter) + SET_USE (use_p, new_lhs); + else + gcc_unreachable (); + } + } + } + if (bb == first_bb) + break; + } + for (bb = last_bb, idx = 0; ; bb = single_pred (bb), idx++) + { + if (bbinfo[idx].first_idx < bbinfo[idx].last_idx + && bbinfo[idx].op == NULL_TREE + && ops[bbinfo[idx].first_idx]->op != NULL_TREE) + { + stmt = last_stmt (bb); + if (integer_zerop (ops[bbinfo[idx].first_idx]->op)) + gimple_cond_make_false (stmt); + else if (integer_onep (ops[bbinfo[idx].first_idx]->op)) + gimple_cond_make_true (stmt); + else + { + gimple_cond_set_code (stmt, NE_EXPR); + gimple_cond_set_lhs (stmt, ops[bbinfo[idx].first_idx]->op); + gimple_cond_set_rhs (stmt, boolean_false_node); + } + update_stmt (stmt); + } + if (bb == first_bb) + break; + } + } + bbinfo.release (); ops.release (); } @@ -2941,175 +3079,36 @@ swap_ops_for_binary_stmt (vec<operand_entry_t> ops, oe2->op = oe1->op; oe2->rank = oe1->rank; oe1->op = temp.op; - oe1->rank= temp.rank; - } -} - -/* Determine if stmt A is not dominated by stmt B. If A and B are in - same basic block, then A's UID has to be less than B. If they are - in different BB's, then A's BB must not be dominated by B's BB. */ - -static inline bool -not_dominated_by (gimple a, gimple b) -{ - basic_block bb_a, bb_b; - bb_a = gimple_bb (a); - bb_b = gimple_bb (b); - return ((bb_a == bb_b && gimple_uid (a) < gimple_uid (b)) - || (bb_a != bb_b - && !dominated_by_p (CDI_DOMINATORS, bb_a, bb_b))); - -} - -/* Among STMT1 and STMT2, return the statement that appears later. Both - statements are in same BB and have the same UID. */ - -static gimple -appears_later_in_bb (gimple stmt1, gimple stmt2) -{ - unsigned uid = gimple_uid (stmt1); - gimple_stmt_iterator gsi = gsi_for_stmt (stmt1); - for (gsi_next (&gsi); !gsi_end_p (gsi); gsi_next (&gsi)) - { - gimple stmt = gsi_stmt (gsi); - - /* If STMT has a different UID than STMT1 and we haven't seen - STMT2 during traversal, we know STMT1 appears later. */ - if (gimple_uid (stmt) != uid) - return stmt1; - else if (stmt == stmt2) - return stmt2; + oe1->rank = temp.rank; } - return stmt1; } -/* Find the statement after which STMT must be moved so that the - dependency from DEP_STMT to STMT is maintained. */ - -static gimple -find_insert_point (gimple stmt, gimple dep_stmt) -{ - gimple insert_stmt = stmt; - if (dep_stmt == NULL) - return stmt; - if (gimple_uid (insert_stmt) == gimple_uid (dep_stmt) - && gimple_bb (insert_stmt) == gimple_bb (dep_stmt) - && insert_stmt != dep_stmt) - insert_stmt = appears_later_in_bb (insert_stmt, dep_stmt); - else if (not_dominated_by (insert_stmt, dep_stmt)) - insert_stmt = dep_stmt; - return insert_stmt; -} - -/* Insert STMT after INSERT_POINT. */ - -static void -insert_stmt_after (gimple stmt, gimple insert_point) -{ - imm_use_iterator iter; - tree lhs; - gimple use_stmt; - gimple_stmt_iterator gsistmt = gsi_for_stmt (stmt), gsi_insert; - basic_block insert_bb = gimple_bb (insert_point); - bool insert_bb_different = (insert_bb != gimple_bb (stmt)); - lhs = gimple_assign_lhs (stmt); - /* If there are any debug uses of LHS, reset them. */ - FOR_EACH_IMM_USE_STMT (use_stmt, iter, lhs) - { - if (is_gimple_debug (use_stmt) - && not_dominated_by (use_stmt, insert_point)) - { - gimple_debug_bind_reset_value (use_stmt); - update_stmt (use_stmt); - } - } - /* If INSERT_STMT is a phi node, then do not insert just after that statement. - Instead, find the first non-label gimple statement in BB and insert before - that. */ - if (gimple_code (insert_point) == GIMPLE_PHI) - { - gsi_insert = gsi_after_labels (insert_bb); - gsi_move_before (&gsistmt, &gsi_insert); - } - /* Statements marked for throw can not be in the middle of a basic block. So - we can not insert a statement (not marked for throw) immediately after. */ - else if (stmt_ends_bb_p (insert_point)) - { - edge succ_edge = find_fallthru_edge (insert_bb->succs); - insert_bb = succ_edge->dest; - insert_bb_different = (insert_bb != gimple_bb (stmt)); - /* Insert STMT at the beginning of the successor basic block. */ - gsi_insert = gsi_after_labels (insert_bb); - gsi_move_before (&gsistmt, &gsi_insert); - } - else - { - gsi_insert = gsi_for_stmt (insert_point); - gsi_move_after (&gsistmt, &gsi_insert); - } - /* Set the UID of STMT to that of INSERT_POINT so that subsequent comparisons - of UIDs to determine dominance within a basic block works. */ - gimple_set_uid (stmt, gimple_uid (insert_point)); - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, "Moved stmt "); - print_gimple_stmt (dump_file, stmt, 0, 0); - fprintf (dump_file, " %s to satisfy dependences\n", - insert_bb_different ? "to a different BB" : "within same BB"); - } - -} - -/* If OP is a SSA variable and is not the default definition, return the - gimple statement that defines OP. Else return NULL. */ +/* If definition of RHS1 or RHS2 dominates STMT, return the later of those + two definitions, otherwise return STMT. */ static inline gimple -get_def_stmt (tree op) +find_insert_point (gimple stmt, tree rhs1, tree rhs2) { - if (TREE_CODE (op) == SSA_NAME - && !SSA_NAME_IS_DEFAULT_DEF (op)) - return SSA_NAME_DEF_STMT (op); - else - return NULL; -} - -/* Ensure that operands in the OPS vector are available for STMT and all - gimple statements on which STMT depends. */ - -static void -ensure_ops_are_available (gimple stmt, vec<operand_entry_t> ops, int opindex) -{ - unsigned int len = ops.length (); - gimple insert_stmt = stmt; - gimple dep_stmts[2]; - dep_stmts[0] = get_def_stmt (ops[opindex]->op); - if (len - opindex == 2) - { - dep_stmts[1] = get_def_stmt (ops[opindex + 1]->op); - } - else - { - gimple stmt1 = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt)); - ensure_ops_are_available (stmt1, ops, opindex + 1); - dep_stmts[1] = stmt1; - } - for (int i = 0; i < 2; i++) - insert_stmt = find_insert_point (insert_stmt, dep_stmts[i]); - - if (insert_stmt != stmt) - insert_stmt_after (stmt, insert_stmt); + if (TREE_CODE (rhs1) == SSA_NAME + && reassoc_stmt_dominates_stmt_p (stmt, SSA_NAME_DEF_STMT (rhs1))) + stmt = SSA_NAME_DEF_STMT (rhs1); + if (TREE_CODE (rhs2) == SSA_NAME + && reassoc_stmt_dominates_stmt_p (stmt, SSA_NAME_DEF_STMT (rhs2))) + stmt = SSA_NAME_DEF_STMT (rhs2); + return stmt; } /* Recursively rewrite our linearized statements so that the operators match those in OPS[OPINDEX], putting the computation in rank - order. */ + order. Return new lhs. */ -static void +static tree rewrite_expr_tree (gimple stmt, unsigned int opindex, - vec<operand_entry_t> ops, bool moved) + vec<operand_entry_t> ops, bool changed) { tree rhs1 = gimple_assign_rhs1 (stmt); tree rhs2 = gimple_assign_rhs2 (stmt); + tree lhs = gimple_assign_lhs (stmt); operand_entry_t oe; /* The final recursion case for this function is that you have @@ -3126,15 +3125,38 @@ rewrite_expr_tree (gimple stmt, unsigned int opindex, if (rhs1 != oe1->op || rhs2 != oe2->op) { + gimple_stmt_iterator gsi = gsi_for_stmt (stmt); + unsigned int uid = gimple_uid (stmt); + if (dump_file && (dump_flags & TDF_DETAILS)) { fprintf (dump_file, "Transforming "); print_gimple_stmt (dump_file, stmt, 0, 0); } - gimple_assign_set_rhs1 (stmt, oe1->op); - gimple_assign_set_rhs2 (stmt, oe2->op); - update_stmt (stmt); + if (changed) + { + gimple insert_point = find_insert_point (stmt, oe1->op, oe2->op); + lhs = make_ssa_name (TREE_TYPE (lhs), NULL); + stmt + = gimple_build_assign_with_ops (gimple_assign_rhs_code (stmt), + lhs, oe1->op, oe2->op); + gimple_set_uid (stmt, uid); + gimple_set_visited (stmt, true); + if (insert_point == gsi_stmt (gsi)) + gsi_insert_before (&gsi, stmt, GSI_SAME_STMT); + else + insert_stmt_after (stmt, insert_point); + } + else + { + gcc_checking_assert (find_insert_point (stmt, oe1->op, oe2->op) + == stmt); + gimple_assign_set_rhs1 (stmt, oe1->op); + gimple_assign_set_rhs2 (stmt, oe2->op); + update_stmt (stmt); + } + if (rhs1 != oe1->op && rhs1 != oe2->op) remove_visited_stmt_chain (rhs1); @@ -3144,7 +3166,7 @@ rewrite_expr_tree (gimple stmt, unsigned int opindex, print_gimple_stmt (dump_file, stmt, 0, 0); } } - return; + return lhs; } /* If we hit here, we should have 3 or more ops left. */ @@ -3153,22 +3175,51 @@ rewrite_expr_tree (gimple stmt, unsigned int opindex, /* Rewrite the next operator. */ oe = ops[opindex]; - if (oe->op != rhs2) - { - if (!moved) - { - ensure_ops_are_available (stmt, ops, opindex); - moved = true; - } + /* Recurse on the LHS of the binary operator, which is guaranteed to + be the non-leaf side. */ + tree new_rhs1 + = rewrite_expr_tree (SSA_NAME_DEF_STMT (rhs1), opindex + 1, ops, + changed || oe->op != rhs2); + if (oe->op != rhs2 || new_rhs1 != rhs1) + { if (dump_file && (dump_flags & TDF_DETAILS)) { fprintf (dump_file, "Transforming "); print_gimple_stmt (dump_file, stmt, 0, 0); } - gimple_assign_set_rhs2 (stmt, oe->op); - update_stmt (stmt); + /* If changed is false, this is either opindex == 0 + or all outer rhs2's were equal to corresponding oe->op, + and powi_result is NULL. + That means lhs is equivalent before and after reassociation. + Otherwise ensure the old lhs SSA_NAME is not reused and + create a new stmt as well, so that any debug stmts will be + properly adjusted. */ + if (changed) + { + gimple_stmt_iterator gsi = gsi_for_stmt (stmt); + unsigned int uid = gimple_uid (stmt); + gimple insert_point = find_insert_point (stmt, new_rhs1, oe->op); + + lhs = make_ssa_name (TREE_TYPE (lhs), NULL); + stmt = gimple_build_assign_with_ops (gimple_assign_rhs_code (stmt), + lhs, new_rhs1, oe->op); + gimple_set_uid (stmt, uid); + gimple_set_visited (stmt, true); + if (insert_point == gsi_stmt (gsi)) + gsi_insert_before (&gsi, stmt, GSI_SAME_STMT); + else + insert_stmt_after (stmt, insert_point); + } + else + { + gcc_checking_assert (find_insert_point (stmt, new_rhs1, oe->op) + == stmt); + gimple_assign_set_rhs1 (stmt, new_rhs1); + gimple_assign_set_rhs2 (stmt, oe->op); + update_stmt (stmt); + } if (dump_file && (dump_flags & TDF_DETAILS)) { @@ -3176,9 +3227,7 @@ rewrite_expr_tree (gimple stmt, unsigned int opindex, print_gimple_stmt (dump_file, stmt, 0, 0); } } - /* Recurse on the LHS of the binary operator, which is guaranteed to - be the non-leaf side. */ - rewrite_expr_tree (SSA_NAME_DEF_STMT (rhs1), opindex + 1, ops, moved); + return lhs; } /* Find out how many cycles we need to compute statements chain. @@ -3260,7 +3309,7 @@ get_reassociation_width (int ops_num, enum tree_code opc, static void rewrite_expr_tree_parallel (gimple stmt, int width, - vec<operand_entry_t> ops) + vec<operand_entry_t> ops) { enum tree_code opcode = gimple_assign_rhs_code (stmt); int op_num = ops.length (); @@ -3356,24 +3405,28 @@ rewrite_expr_tree_parallel (gimple stmt, int width, static void linearize_expr (gimple stmt) { - gimple_stmt_iterator gsinow, gsirhs; + gimple_stmt_iterator gsi; gimple binlhs = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt)); gimple binrhs = SSA_NAME_DEF_STMT (gimple_assign_rhs2 (stmt)); + gimple oldbinrhs = binrhs; enum tree_code rhscode = gimple_assign_rhs_code (stmt); gimple newbinrhs = NULL; struct loop *loop = loop_containing_stmt (stmt); + tree lhs = gimple_assign_lhs (stmt); gcc_assert (is_reassociable_op (binlhs, rhscode, loop) && is_reassociable_op (binrhs, rhscode, loop)); - gsinow = gsi_for_stmt (stmt); - gsirhs = gsi_for_stmt (binrhs); - gsi_move_before (&gsirhs, &gsinow); - gimple_set_uid (binrhs, gimple_uid (stmt)); + gsi = gsi_for_stmt (stmt); gimple_assign_set_rhs2 (stmt, gimple_assign_rhs1 (binrhs)); - gimple_assign_set_rhs1 (binrhs, gimple_assign_lhs (binlhs)); + binrhs = gimple_build_assign_with_ops (gimple_assign_rhs_code (binrhs), + make_ssa_name (TREE_TYPE (lhs), NULL), + gimple_assign_lhs (binlhs), + gimple_assign_rhs2 (binrhs)); gimple_assign_set_rhs1 (stmt, gimple_assign_lhs (binrhs)); + gsi_insert_before (&gsi, binrhs, GSI_SAME_STMT); + gimple_set_uid (binrhs, gimple_uid (stmt)); if (TREE_CODE (gimple_assign_rhs2 (stmt)) == SSA_NAME) newbinrhs = SSA_NAME_DEF_STMT (gimple_assign_rhs2 (stmt)); @@ -3385,10 +3438,12 @@ linearize_expr (gimple stmt) } reassociate_stats.linearized++; - update_stmt (binrhs); - update_stmt (binlhs); update_stmt (stmt); + gsi = gsi_for_stmt (oldbinrhs); + gsi_remove (&gsi, true); + release_defs (oldbinrhs); + gimple_set_visited (stmt, true); gimple_set_visited (binlhs, true); gimple_set_visited (binrhs, true); @@ -3425,10 +3480,12 @@ get_single_immediate_use (tree lhs) transform b_3 + b_4 into a_5 = -b_3 + -b_4. */ static tree -negate_value (tree tonegate, gimple_stmt_iterator *gsi) +negate_value (tree tonegate, gimple_stmt_iterator *gsip) { - gimple negatedefstmt= NULL; + gimple negatedefstmt = NULL; tree resultofnegate; + gimple_stmt_iterator gsi; + unsigned int uid; /* If we are trying to negate a name, defined by an add, negate the add operands instead. */ @@ -3440,25 +3497,38 @@ negate_value (tree tonegate, gimple_stmt_iterator *gsi) && has_single_use (gimple_assign_lhs (negatedefstmt)) && gimple_assign_rhs_code (negatedefstmt) == PLUS_EXPR) { - gimple_stmt_iterator gsi; tree rhs1 = gimple_assign_rhs1 (negatedefstmt); tree rhs2 = gimple_assign_rhs2 (negatedefstmt); + tree lhs = gimple_assign_lhs (negatedefstmt); + gimple g; gsi = gsi_for_stmt (negatedefstmt); rhs1 = negate_value (rhs1, &gsi); - gimple_assign_set_rhs1 (negatedefstmt, rhs1); gsi = gsi_for_stmt (negatedefstmt); rhs2 = negate_value (rhs2, &gsi); - gimple_assign_set_rhs2 (negatedefstmt, rhs2); - update_stmt (negatedefstmt); - return gimple_assign_lhs (negatedefstmt); + gsi = gsi_for_stmt (negatedefstmt); + lhs = make_ssa_name (TREE_TYPE (lhs), NULL); + gimple_set_visited (negatedefstmt, true); + g = gimple_build_assign_with_ops (PLUS_EXPR, lhs, rhs1, rhs2); + gimple_set_uid (g, gimple_uid (negatedefstmt)); + gsi_insert_before (&gsi, g, GSI_SAME_STMT); + return lhs; } tonegate = fold_build1 (NEGATE_EXPR, TREE_TYPE (tonegate), tonegate); - resultofnegate = force_gimple_operand_gsi (gsi, tonegate, true, + resultofnegate = force_gimple_operand_gsi (gsip, tonegate, true, NULL_TREE, true, GSI_SAME_STMT); + gsi = *gsip; + uid = gimple_uid (gsi_stmt (gsi)); + for (gsi_prev (&gsi); !gsi_end_p (gsi); gsi_prev (&gsi)) + { + gimple stmt = gsi_stmt (gsi); + if (gimple_uid (stmt) != 0) + break; + gimple_set_uid (stmt, uid); + } return resultofnegate; } @@ -3763,16 +3833,18 @@ repropagate_negates (void) plus_negates vector. */ gimple feed = SSA_NAME_DEF_STMT (negate); tree a = gimple_assign_rhs1 (feed); - tree rhs2 = gimple_assign_rhs2 (user); - gimple_stmt_iterator gsi = gsi_for_stmt (feed), gsi2; - gimple_replace_ssa_lhs (feed, negate); - gimple_assign_set_rhs_with_ops (&gsi, PLUS_EXPR, a, rhs2); - update_stmt (gsi_stmt (gsi)); - gsi2 = gsi_for_stmt (user); - gimple_assign_set_rhs_with_ops (&gsi2, NEGATE_EXPR, negate, NULL); - update_stmt (gsi_stmt (gsi2)); - gsi_move_before (&gsi, &gsi2); - plus_negates.safe_push (gimple_assign_lhs (gsi_stmt (gsi2))); + tree b = gimple_assign_rhs2 (user); + gimple_stmt_iterator gsi = gsi_for_stmt (feed); + gimple_stmt_iterator gsi2 = gsi_for_stmt (user); + tree x = make_ssa_name (TREE_TYPE (gimple_assign_lhs (feed)), NULL); + gimple g = gimple_build_assign_with_ops (PLUS_EXPR, x, a, b); + gsi_insert_before (&gsi2, g, GSI_SAME_STMT); + gimple_assign_set_rhs_with_ops (&gsi2, NEGATE_EXPR, x, NULL); + user = gsi_stmt (gsi2); + update_stmt (user); + gsi_remove (&gsi, true); + release_defs (feed); + plus_negates.safe_push (gimple_assign_lhs (user)); } else { @@ -3819,18 +3891,21 @@ can_reassociate_p (tree op) we want to break up k = t - q, but we won't until we've transformed q = b - r, which won't be broken up until we transform b = c - d. - En passant, clear the GIMPLE visited flag on every statement. */ + En passant, clear the GIMPLE visited flag on every statement + and set UIDs within each basic block. */ static void break_up_subtract_bb (basic_block bb) { gimple_stmt_iterator gsi; basic_block son; + unsigned int uid = 1; for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) { gimple stmt = gsi_stmt (gsi); gimple_set_visited (stmt, false); + gimple_set_uid (stmt, uid++); if (!is_gimple_assign (stmt) || !can_reassociate_p (gimple_assign_lhs (stmt))) @@ -4366,6 +4441,7 @@ reassociate_bb (basic_block bb) enum machine_mode mode = TYPE_MODE (TREE_TYPE (lhs)); int ops_num = ops.length (); int width = get_reassociation_width (ops_num, rhs_code, mode); + tree new_lhs = lhs; if (dump_file && (dump_flags & TDF_DETAILS)) fprintf (dump_file, @@ -4383,7 +4459,8 @@ reassociate_bb (basic_block bb) if (len >= 3) swap_ops_for_binary_stmt (ops, len - 3, stmt); - rewrite_expr_tree (stmt, 0, ops, false); + new_lhs = rewrite_expr_tree (stmt, 0, ops, + powi_result != NULL); } /* If we combined some repeated factors into a @@ -4391,12 +4468,14 @@ reassociate_bb (basic_block bb) reassociated operands. */ if (powi_result) { - gimple mul_stmt; - tree type = TREE_TYPE (gimple_get_lhs (stmt)); + gimple mul_stmt, lhs_stmt = SSA_NAME_DEF_STMT (lhs); + tree type = TREE_TYPE (lhs); tree target_ssa = make_temp_ssa_name (type, NULL, "reassocpow"); - gimple_set_lhs (stmt, target_ssa); - update_stmt (stmt); + gimple_set_lhs (lhs_stmt, target_ssa); + update_stmt (lhs_stmt); + if (lhs != new_lhs) + target_ssa = new_lhs; mul_stmt = gimple_build_assign_with_ops (MULT_EXPR, lhs, powi_result, target_ssa); @@ -4445,7 +4524,6 @@ static void do_reassoc (void) { break_up_subtract_bb (ENTRY_BLOCK_PTR); - renumber_gimple_stmt_uids (); reassociate_bb (EXIT_BLOCK_PTR); } diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c index a56c55b622f..5d7bcfc9ab6 100644 --- a/gcc/tree-ssa-sccvn.c +++ b/gcc/tree-ssa-sccvn.c @@ -26,13 +26,17 @@ along with GCC; see the file COPYING3. If not see #include "basic-block.h" #include "gimple-pretty-print.h" #include "tree-inline.h" -#include "tree-ssa.h" #include "gimple.h" +#include "gimple-ssa.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" +#include "tree-dfa.h" +#include "tree-ssa.h" #include "dumpfile.h" #include "hash-table.h" #include "alloc-pool.h" #include "flags.h" -#include "bitmap.h" #include "cfgloop.h" #include "params.h" #include "tree-ssa-propagate.h" diff --git a/gcc/tree-ssa-sink.c b/gcc/tree-ssa-sink.c index e3d62fb9b4e..a8b149287c9 100644 --- a/gcc/tree-ssa-sink.c +++ b/gcc/tree-ssa-sink.c @@ -26,14 +26,16 @@ along with GCC; see the file COPYING3. If not see #include "basic-block.h" #include "gimple-pretty-print.h" #include "tree-inline.h" -#include "tree-ssa.h" #include "gimple.h" +#include "gimple-ssa.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" #include "hashtab.h" #include "tree-iterator.h" #include "alloc-pool.h" #include "tree-pass.h" #include "flags.h" -#include "bitmap.h" #include "cfgloop.h" #include "params.h" diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c index d2899539ca5..4d3acf303da 100644 --- a/gcc/tree-ssa-strlen.c +++ b/gcc/tree-ssa-strlen.c @@ -21,8 +21,15 @@ along with GCC; see the file COPYING3. If not see #include "config.h" #include "system.h" #include "coretypes.h" +#include "tree.h" #include "hash-table.h" -#include "tree-ssa.h" +#include "bitmap.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" +#include "tree-dfa.h" #include "tree-pass.h" #include "domwalk.h" #include "alloc-pool.h" diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c index affc0b69dcc..78d1a7c2e53 100644 --- a/gcc/tree-ssa-structalias.c +++ b/gcc/tree-ssa-structalias.c @@ -29,18 +29,20 @@ #include "flags.h" #include "basic-block.h" #include "tree.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "cgraph.h" +#include "tree-ssanames.h" +#include "tree-into-ssa.h" +#include "tree-dfa.h" #include "tree-inline.h" #include "diagnostic-core.h" -#include "gimple.h" #include "hash-table.h" #include "function.h" -#include "cgraph.h" #include "tree-pass.h" #include "alloc-pool.h" #include "splay-tree.h" #include "params.h" -#include "cgraph.h" #include "alias.h" #include "pointer-set.h" @@ -2875,10 +2877,10 @@ get_constraint_for_ssa_var (tree t, vec<ce_s> *results, bool address_p) && (TREE_STATIC (t) || DECL_EXTERNAL (t))) { struct varpool_node *node = varpool_get_node (t); - if (node && node->symbol.alias && node->symbol.analyzed) + if (node && node->alias && node->analyzed) { node = varpool_variable_node (node, NULL); - t = node->symbol.decl; + t = node->decl; } } @@ -5751,7 +5753,7 @@ create_variable_info_for (tree decl, const char *name) /* If this is a global variable with an initializer and we are in IPA mode generate constraints for it. */ if (DECL_INITIAL (decl) - && vnode->symbol.definition) + && vnode->definition) { vec<ce_s> rhsc = vNULL; struct constraint_expr lhs, *rhsp; @@ -7057,9 +7059,9 @@ struct pt_solution ipa_escaped_pt static bool associate_varinfo_to_alias (struct cgraph_node *node, void *data) { - if ((node->symbol.alias || node->thunk.thunk_p) - && node->symbol.analyzed) - insert_vi_for_tree (node->symbol.decl, (varinfo_t)data); + if ((node->alias || node->thunk.thunk_p) + && node->analyzed) + insert_vi_for_tree (node->decl, (varinfo_t)data); return false; } @@ -7094,18 +7096,18 @@ ipa_pta_execute (void) gcc_assert (!node->clone_of); - vi = create_function_info_for (node->symbol.decl, - alias_get_name (node->symbol.decl)); + vi = create_function_info_for (node->decl, + alias_get_name (node->decl)); cgraph_for_node_and_aliases (node, associate_varinfo_to_alias, vi, true); } /* Create constraints for global variables and their initializers. */ FOR_EACH_VARIABLE (var) { - if (var->symbol.alias && var->symbol.analyzed) + if (var->alias && var->analyzed) continue; - get_vi_for_tree (var->symbol.decl); + get_vi_for_tree (var->decl); } if (dump_file) @@ -7130,32 +7132,32 @@ ipa_pta_execute (void) { fprintf (dump_file, "Generating constraints for %s", cgraph_node_name (node)); - if (DECL_ASSEMBLER_NAME_SET_P (node->symbol.decl)) + if (DECL_ASSEMBLER_NAME_SET_P (node->decl)) fprintf (dump_file, " (%s)", IDENTIFIER_POINTER - (DECL_ASSEMBLER_NAME (node->symbol.decl))); + (DECL_ASSEMBLER_NAME (node->decl))); fprintf (dump_file, "\n"); } - func = DECL_STRUCT_FUNCTION (node->symbol.decl); + func = DECL_STRUCT_FUNCTION (node->decl); push_cfun (func); /* For externally visible or attribute used annotated functions use local constraints for their arguments. For local functions we see all callers and thus do not need initial constraints for parameters. */ - if (node->symbol.used_from_other_partition - || node->symbol.externally_visible - || node->symbol.force_output) + if (node->used_from_other_partition + || node->externally_visible + || node->force_output) { intra_create_variable_infos (); /* We also need to make function return values escape. Nothing escapes by returning from main though. */ - if (!MAIN_NAME_P (DECL_NAME (node->symbol.decl))) + if (!MAIN_NAME_P (DECL_NAME (node->decl))) { varinfo_t fi, rvi; - fi = lookup_vi_for_tree (node->symbol.decl); + fi = lookup_vi_for_tree (node->decl); rvi = first_vi_for_offset (fi, fi_result); if (rvi && rvi->offset == fi_result) { @@ -7235,7 +7237,7 @@ ipa_pta_execute (void) if (!cgraph_function_with_gimple_body_p (node) || node->clone_of) continue; - fn = DECL_STRUCT_FUNCTION (node->symbol.decl); + fn = DECL_STRUCT_FUNCTION (node->decl); /* Compute the points-to sets for pointer SSA_NAMEs. */ FOR_EACH_VEC_ELT (*fn->gimple_df->ssa_names, i, ptr) @@ -7246,7 +7248,7 @@ ipa_pta_execute (void) } /* Compute the call-use and call-clobber sets for all direct calls. */ - fi = lookup_vi_for_tree (node->symbol.decl); + fi = lookup_vi_for_tree (node->decl); gcc_assert (fi->is_fn_info); clobbers = find_what_var_points_to (first_vi_for_offset (fi, fi_clobbers)); diff --git a/gcc/tree-ssa-tail-merge.c b/gcc/tree-ssa-tail-merge.c index 9094935391c..db95ce1059c 100644 --- a/gcc/tree-ssa-tail-merge.c +++ b/gcc/tree-ssa-tail-merge.c @@ -194,8 +194,12 @@ along with GCC; see the file COPYING3. If not see #include "basic-block.h" #include "flags.h" #include "function.h" -#include "tree-ssa.h" -#include "bitmap.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-into-ssa.h" #include "tree-ssa-alias.h" #include "params.h" #include "hash-table.h" @@ -300,7 +304,8 @@ stmt_local_def (gimple stmt) tree val; def_operand_p def_p; - if (gimple_has_side_effects (stmt)) + if (gimple_has_side_effects (stmt) + || gimple_vdef (stmt) != NULL_TREE) return false; def_p = SINGLE_SSA_DEF_OPERAND (stmt, SSA_OP_DEF); @@ -1462,7 +1467,7 @@ static void replace_block_by (basic_block bb1, basic_block bb2) { edge pred_edge; - edge e1; + edge e1, e2; edge_iterator ei; unsigned int i; gimple bb2_phi; @@ -1497,15 +1502,21 @@ replace_block_by (basic_block bb1, basic_block bb2) bb2->count += bb1->count; /* Merge the outgoing edge counts from bb1 onto bb2. */ + gcov_type out_sum = 0; FOR_EACH_EDGE (e1, ei, bb1->succs) { - edge e2; e2 = find_edge (bb2, e1->dest); gcc_assert (e2); e2->count += e1->count; - /* Recompute the probability from the new merged edge count (bb2->count - was updated above). */ - e2->probability = GCOV_COMPUTE_SCALE (e2->count, bb2->count); + out_sum += e2->count; + } + /* Recompute the edge probabilities from the new merged edge count. + Use the sum of the new merged edge counts computed above instead + of bb2's merged count, in case there are profile count insanities + making the bb count inconsistent with the edge weights. */ + FOR_EACH_EDGE (e2, ei, bb2->succs) + { + e2->probability = GCOV_COMPUTE_SCALE (e2->count, out_sum); } /* Do updates that use bb1, before deleting bb1. */ diff --git a/gcc/tree-ssa-ter.c b/gcc/tree-ssa-ter.c index 3659cf0c428..6090c5ff5f5 100644 --- a/gcc/tree-ssa-ter.c +++ b/gcc/tree-ssa-ter.c @@ -26,8 +26,14 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "gimple-pretty-print.h" #include "bitmap.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" #include "dumpfile.h" +#include "tree-ssa-live.h" +#include "tree-ssa-ter.h" #include "tree-outof-ssa.h" #include "flags.h" diff --git a/gcc/tree-ssa-ter.h b/gcc/tree-ssa-ter.h index 4565db16b86..e71f78b492f 100644 --- a/gcc/tree-ssa-ter.h +++ b/gcc/tree-ssa-ter.h @@ -24,29 +24,3 @@ extern bitmap find_replaceable_exprs (var_map); extern void dump_replaceable_exprs (FILE *, bitmap); #endif /* GCC_TREE_SSA_TER_H */ -/* Header file for tree-ssa-ter.c exports. - Copyright (C) 2013 Free Software Foundation, Inc. - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 3, or (at your option) any later -version. - -GCC is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING3. If not see -<http://www.gnu.org/licenses/>. */ - -#ifndef GCC_TREE_SSA_TER_H -#define GCC_TREE_SSA_TER_H - -extern bitmap find_replaceable_exprs (var_map); -extern void dump_replaceable_exprs (FILE *, bitmap); - -#endif /* GCC_TREE_SSA_TER_H */ diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c index f5675572ff0..c3e7bd0d138 100644 --- a/gcc/tree-ssa-threadedge.c +++ b/gcc/tree-ssa-threadedge.c @@ -30,7 +30,12 @@ along with GCC; see the file COPYING3. If not see #include "function.h" #include "timevar.h" #include "dumpfile.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" #include "tree-ssa-propagate.h" #include "tree-ssa-threadupdate.h" #include "langhooks.h" @@ -639,7 +644,7 @@ propagate_threaded_block_debug_into (basic_block dest, basic_block src) i++; } - vec<tree, va_stack> fewvars = vNULL; + stack_vec<tree, alloc_count> fewvars; pointer_set_t *vars = NULL; /* If we're already starting with 3/4 of alloc_count, go for a @@ -647,8 +652,6 @@ propagate_threaded_block_debug_into (basic_block dest, basic_block src) VEC. */ if (i * 4 > alloc_count * 3) vars = pointer_set_create (); - else if (alloc_count) - vec_stack_alloc (tree, fewvars, alloc_count); /* Now go through the initial debug stmts in DEST again, this time actually inserting in VARS or FEWVARS. Don't bother checking for @@ -883,7 +886,8 @@ thread_through_normal_block (edge e, bool handle_dominating_asserts, vec<tree> *stack, tree (*simplify) (gimple, gimple), - vec<jump_thread_edge *> *path) + vec<jump_thread_edge *> *path, + bitmap visited) { /* If E is a backedge, then we want to verify that the COND_EXPR, SWITCH_EXPR or GOTO_EXPR at the end of e->dest is not affected @@ -922,11 +926,10 @@ thread_through_normal_block (edge e, { edge taken_edge = find_taken_edge (e->dest, cond); basic_block dest = (taken_edge ? taken_edge->dest : NULL); - bitmap visited; /* DEST could be NULL for a computed jump to an absolute address. */ - if (dest == NULL || dest == e->dest) + if (dest == NULL || dest == e->dest || bitmap_bit_p (visited, dest->index)) return false; jump_thread_edge *x @@ -944,7 +947,6 @@ thread_through_normal_block (edge e, { /* We don't want to thread back to a block we have already visited. This may be overly conservative. */ - visited = BITMAP_ALLOC (NULL); bitmap_set_bit (visited, dest->index); bitmap_set_bit (visited, e->dest->index); thread_around_empty_blocks (taken_edge, @@ -953,7 +955,6 @@ thread_through_normal_block (edge e, simplify, visited, path); - BITMAP_FREE (visited); } return true; } @@ -995,15 +996,21 @@ thread_across_edge (gimple dummy_cond, vec<tree> *stack, tree (*simplify) (gimple, gimple)) { + bitmap visited = BITMAP_ALLOC (NULL); + stmt_count = 0; vec<jump_thread_edge *> *path = new vec<jump_thread_edge *> (); + bitmap_clear (visited); + bitmap_set_bit (visited, e->src->index); + bitmap_set_bit (visited, e->dest->index); if (thread_through_normal_block (e, dummy_cond, handle_dominating_asserts, - stack, simplify, path)) + stack, simplify, path, visited)) { propagate_threaded_block_debug_into (path->last ()->e->dest, e->dest); remove_temporary_equivalences (stack); + BITMAP_FREE (visited); register_jump_thread (path); return; } @@ -1030,7 +1037,16 @@ thread_across_edge (gimple dummy_cond, edge taken_edge; edge_iterator ei; bool found; - bitmap visited = BITMAP_ALLOC (NULL); + + /* If E->dest has abnormal outgoing edges, then there's no guarantee + we can safely redirect any of the edges. Just punt those cases. */ + FOR_EACH_EDGE (taken_edge, ei, e->dest->succs) + if (taken_edge->flags & EDGE_ABNORMAL) + { + remove_temporary_equivalences (stack); + BITMAP_FREE (visited); + return; + } /* Look at each successor of E->dest to see if we can thread through it. */ FOR_EACH_EDGE (taken_edge, ei, e->dest->succs) diff --git a/gcc/tree-ssa-threadupdate.c b/gcc/tree-ssa-threadupdate.c index e791269ebac..10271919786 100644 --- a/gcc/tree-ssa-threadupdate.c +++ b/gcc/tree-ssa-threadupdate.c @@ -24,6 +24,9 @@ along with GCC; see the file COPYING3. If not see #include "flags.h" #include "basic-block.h" #include "function.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-phinodes.h" #include "tree-ssa.h" #include "tree-ssa-threadupdate.h" #include "dumpfile.h" @@ -613,10 +616,12 @@ redirection_block_p (basic_block bb) the appropriate duplicate of BB. If NOLOOP_ONLY is true, we only perform the threading as long as it - does not affect the structure of the loops in a nontrivial way. */ + does not affect the structure of the loops in a nontrivial way. + + If JOINERS is true, then thread through joiner blocks as well. */ static bool -thread_block (basic_block bb, bool noloop_only) +thread_block_1 (basic_block bb, bool noloop_only, bool joiners) { /* E is an incoming edge into BB that we may or may not want to redirect to a duplicate of BB. */ @@ -639,7 +644,9 @@ thread_block (basic_block bb, bool noloop_only) e = loop_latch_edge (loop); vec<jump_thread_edge *> *path = THREAD_PATH (e); - if (path) + if (path + && (((*path)[1]->type == EDGE_COPY_SRC_JOINER_BLOCK && joiners) + || ((*path)[1]->type == EDGE_COPY_SRC_BLOCK && !joiners))) { for (unsigned int i = 1; i < path->length (); i++) { @@ -663,6 +670,11 @@ thread_block (basic_block bb, bool noloop_only) continue; vec<jump_thread_edge *> *path = THREAD_PATH (e); + + if (((*path)[1]->type == EDGE_COPY_SRC_JOINER_BLOCK && !joiners) + || ((*path)[1]->type == EDGE_COPY_SRC_BLOCK && joiners)) + continue; + e2 = path->last ()->e; if (!e2 || noloop_only) { @@ -759,6 +771,24 @@ thread_block (basic_block bb, bool noloop_only) return local_info.jumps_threaded; } +/* Wrapper for thread_block_1 so that we can first handle jump + thread paths which do not involve copying joiner blocks, then + handle jump thread paths which have joiner blocks. + + By doing things this way we can be as aggressive as possible and + not worry that copying a joiner block will create a jump threading + opportunity. */ + +static bool +thread_block (basic_block bb, bool noloop_only) +{ + bool retval; + retval = thread_block_1 (bb, noloop_only, false); + retval |= thread_block_1 (bb, noloop_only, true); + return retval; +} + + /* Threads edge E through E->dest to the edge THREAD_TARGET (E). Returns the copy of E->dest created during threading, or E->dest if it was not necessary to copy it (E is its single predecessor). */ @@ -1237,47 +1267,14 @@ mark_threaded_blocks (bitmap threaded_blocks) edge e; edge_iterator ei; - /* It is possible to have jump threads in which one is a subpath - of the other. ie, (A, B), (B, C), (C, D) where B is a joiner - block and (B, C), (C, D) where no joiner block exists. - - When this occurs ignore the jump thread request with the joiner - block. It's totally subsumed by the simpler jump thread request. - - This results in less block copying, simpler CFGs. More improtantly, - when we duplicate the joiner block, B, in this case we will create - a new threading opportunity that we wouldn't be able to optimize - until the next jump threading iteration. - - So first convert the jump thread requests which do not require a - joiner block. */ - for (i = 0; i < paths.length (); i++) - { - vec<jump_thread_edge *> *path = paths[i]; - - if ((*path)[1]->type != EDGE_COPY_SRC_JOINER_BLOCK) - { - edge e = (*path)[0]->e; - e->aux = (void *)path; - bitmap_set_bit (tmp, e->dest->index); - } - } - - - /* Now iterate again, converting cases where we threaded through - a joiner block, but ignoring those where we have already - threaded through the joiner block. */ + /* Move the jump threading requests from PATHS to each edge + which starts a jump thread path. */ for (i = 0; i < paths.length (); i++) { vec<jump_thread_edge *> *path = paths[i]; - - if ((*path)[1]->type == EDGE_COPY_SRC_JOINER_BLOCK - && (*path)[0]->e->aux == NULL) - { - edge e = (*path)[0]->e; - e->aux = path; - bitmap_set_bit (tmp, e->dest->index); - } + edge e = (*path)[0]->e; + e->aux = (void *)path; + bitmap_set_bit (tmp, e->dest->index); } /* If we have a joiner block (J) which has two successors S1 and S2 and @@ -1475,6 +1472,39 @@ thread_through_all_blocks (bool may_peel_loop_headers) retval |= thread_through_loop_header (loop, may_peel_loop_headers); } + /* Assume we had a jump thread path which went from the latch to the exit + and a path which goes from outside to inside the same loop. + + If the latch to exit was handled first, we will thread it and clear + loop->header. + + The second path will be ignored by thread_block because we're going + through a loop header. It will also be ignored by the loop above + because loop->header is NULL. + + This results in the second path never being threaded. The failure + mode is a dangling AUX field. + + This is inherently a bit of a pain to fix, so we just walk all the + blocks and all the incoming edges to those blocks and clear their + AUX fields. */ + basic_block bb; + edge_iterator ei; + edge e; + FOR_EACH_BB (bb) + { + FOR_EACH_EDGE (e, ei, bb->preds) + if (e->aux) + { + vec<jump_thread_edge *> *path = THREAD_PATH (e); + + for (unsigned int i = 0; i < path->length (); i++) + delete (*path)[i]; + path->release (); + e->aux = NULL; + } + } + statistics_counter_event (cfun, "Jumps threaded", thread_stats.num_threaded_edges); diff --git a/gcc/tree-ssa-uncprop.c b/gcc/tree-ssa-uncprop.c index 28ff546c627..5255d7fb738 100644 --- a/gcc/tree-ssa-uncprop.c +++ b/gcc/tree-ssa-uncprop.c @@ -26,7 +26,11 @@ along with GCC; see the file COPYING3. If not see #include "tm_p.h" #include "basic-block.h" #include "function.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" #include "domwalk.h" #include "tree-pass.h" #include "tree-ssa-propagate.h" @@ -357,15 +361,7 @@ record_equiv (tree value, tree equivalence) class uncprop_dom_walker : public dom_walker { public: - uncprop_dom_walker (cdi_direction direction) - : dom_walker (direction) - { - m_equiv_stack.create (2); - } - ~uncprop_dom_walker () - { - m_equiv_stack.release (); - } + uncprop_dom_walker (cdi_direction direction) : dom_walker (direction) {} virtual void before_dom_children (basic_block); virtual void after_dom_children (basic_block); @@ -376,7 +372,7 @@ private: leading to this block. If no such edge equivalency exists, then we record NULL. These equivalences are live until we leave the dominator subtree rooted at the block where we record the equivalency. */ - vec<tree> m_equiv_stack; + stack_vec<tree, 2> m_equiv_stack; }; /* Main driver for un-cprop. */ diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c index 43ca5268c58..108da393234 100644 --- a/gcc/tree-ssa-uninit.c +++ b/gcc/tree-ssa-uninit.c @@ -30,8 +30,11 @@ along with GCC; see the file COPYING3. If not see #include "gimple-pretty-print.h" #include "bitmap.h" #include "pointer-set.h" -#include "tree-ssa.h" #include "gimple.h" +#include "gimple-ssa.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssa.h" #include "tree-inline.h" #include "hashtab.h" #include "tree-pass.h" diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c index 8706f95f5d0..9072ce11673 100644 --- a/gcc/tree-ssa.c +++ b/gcc/tree-ssa.c @@ -30,10 +30,15 @@ along with GCC; see the file COPYING3. If not see #include "basic-block.h" #include "function.h" #include "gimple-pretty-print.h" -#include "bitmap.h" #include "pointer-set.h" -#include "tree-ssa.h" #include "gimple.h" +#include "gimple-ssa.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" +#include "tree-ssa-loop-manip.h" +#include "tree-into-ssa.h" +#include "tree-ssa.h" #include "tree-inline.h" #include "hashtab.h" #include "tree-pass.h" diff --git a/gcc/tree-ssa.h b/gcc/tree-ssa.h index c68a044221c..ab1c920ff83 100644 --- a/gcc/tree-ssa.h +++ b/gcc/tree-ssa.h @@ -20,18 +20,6 @@ along with GCC; see the file COPYING3. If not see #ifndef GCC_TREE_SSA_H #define GCC_TREE_SSA_H -#include "bitmap.h" -#include "gimple.h" -#include "gimple-ssa.h" -#include "cgraph.h" -#include "tree-cfg.h" -#include "tree-phinodes.h" -#include "ssa-iterators.h" -#include "tree-ssanames.h" -#include "tree-ssa-loop.h" -#include "tree-into-ssa.h" -#include "tree-dfa.h" - /* Mapping for redirected edges. */ struct _edge_var_map { tree result; /* PHI result. */ diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c index b1ef37d6879..2c177eeaec8 100644 --- a/gcc/tree-ssanames.c +++ b/gcc/tree-ssanames.c @@ -22,6 +22,12 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tm.h" #include "tree.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" +#include "tree-into-ssa.h" #include "tree-ssa.h" #include "tree-pass.h" @@ -183,11 +189,29 @@ set_range_info (tree name, widest_int min, widest_int max) { ri = ggc_alloc_cleared_range_info_def (); SSA_NAME_RANGE_INFO (name) = ri; + ri->nonzero_bits = wi::mask <widest_int> (TYPE_PRECISION (TREE_TYPE (name)), + false); } /* Set the values. */ ri->min = min; ri->max = max; + + /* If it is a range, try to improve nonzero_bits from the min/max. */ + if (wi::cmp (min, max, TYPE_SIGN (TREE_TYPE (name))) != 1) + { + int prec = TYPE_PRECISION (TREE_TYPE (name)); + widest_int xorv; + + min = wi::zext (min, prec); + max = wi::zext (max, prec); + xorv = min ^ max; + if (xorv != 0) + xorv = wi::mask <widest_int> (MAX_BITSIZE_MODE_ANY_INT + - wi::clz (xorv), + false); + ri->nonzero_bits = ri->nonzero_bits & (min | xorv); + } } @@ -196,7 +220,7 @@ set_range_info (tree name, widest_int min, widest_int max) is used to determine if MIN and MAX are valid values. */ enum value_range_type -get_range_info (tree name, widest_int *min, widest_int *max) +get_range_info (const_tree name, widest_int *min, widest_int *max) { enum value_range_type range_type; gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name))); @@ -227,6 +251,49 @@ get_range_info (tree name, widest_int *min, widest_int *max) return range_type; } +/* Change non-zero bits bitmask of NAME. */ + +void +set_nonzero_bits (tree name, widest_int mask) +{ + gcc_assert (!POINTER_TYPE_P (TREE_TYPE (name))); + if (SSA_NAME_RANGE_INFO (name) == NULL) + set_range_info (name, + wi::to_widest (TYPE_MIN_VALUE (TREE_TYPE (name))), + wi::to_widest (TYPE_MAX_VALUE (TREE_TYPE (name)))); + range_info_def *ri = SSA_NAME_RANGE_INFO (name); + ri->nonzero_bits + = mask & wi::mask <widest_int> (TYPE_PRECISION (TREE_TYPE (name)), + false); +} + +/* Return a widest_int with potentially non-zero bits in SSA_NAME + NAME, or -1 if unknown. */ + +widest_int +get_nonzero_bits (const_tree name) +{ + if (POINTER_TYPE_P (TREE_TYPE (name))) + { + struct ptr_info_def *pi = SSA_NAME_PTR_INFO (name); + if (pi && pi->align) + { + widest_int al = pi->align - 1; + return ((wi::mask <widest_int> (TYPE_PRECISION (TREE_TYPE (name)), + false) & ~al) + | pi->misalign); + } + return -1; + } + + range_info_def *ri = SSA_NAME_RANGE_INFO (name); + if (!ri || (GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (name))) + > 2 * HOST_BITS_PER_WIDE_INT)) + return -1; + + return ri->nonzero_bits; +} + /* We no longer need the SSA_NAME expression VAR, release it so that it may be reused. diff --git a/gcc/tree-ssanames.h b/gcc/tree-ssanames.h index 2c92d5772d7..cafcd7c482a 100644 --- a/gcc/tree-ssanames.h +++ b/gcc/tree-ssanames.h @@ -52,6 +52,8 @@ struct GTY (()) range_info_def { widest_int min; /* Maximum for value range. */ widest_int max; + /* Non-zero bits - bits not set are guaranteed to be always zero. */ + widest_int nonzero_bits; }; @@ -68,10 +70,12 @@ struct GTY (()) range_info_def { enum value_range_type { VR_UNDEFINED, VR_RANGE, VR_ANTI_RANGE, VR_VARYING }; /* Sets the value range to SSA. */ -extern void set_range_info (tree ssa, widest_int min, widest_int max); +extern void set_range_info (tree, widest_int, widest_int); /* Gets the value range from SSA. */ -extern enum value_range_type get_range_info (tree name, widest_int *min, - widest_int *max); +extern enum value_range_type get_range_info (const_tree, widest_int *, + widest_int *); +extern void set_nonzero_bits (tree, widest_int); +extern widest_int get_nonzero_bits (const_tree); extern void init_ssanames (struct function *, int); extern void fini_ssanames (void); extern void ssanames_print_statistics (void); diff --git a/gcc/tree-stdarg.c b/gcc/tree-stdarg.c index 58c2e871ebd..622d8efe13d 100644 --- a/gcc/tree-stdarg.c +++ b/gcc/tree-stdarg.c @@ -27,7 +27,12 @@ along with GCC; see the file COPYING3. If not see #include "langhooks.h" #include "gimple-pretty-print.h" #include "target.h" -#include "tree-ssa.h" +#include "bitmap.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" #include "sbitmap.h" #include "tree-pass.h" #include "tree-stdarg.h" diff --git a/gcc/tree-streamer-in.c b/gcc/tree-streamer-in.c index ffc468a56cc..c0989c8ff72 100644 --- a/gcc/tree-streamer-in.c +++ b/gcc/tree-streamer-in.c @@ -24,7 +24,7 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "diagnostic.h" #include "tree.h" -#include "tree-ssa.h" +#include "gimple.h" #include "tree-streamer.h" #include "data-streamer.h" #include "streamer-hooks.h" diff --git a/gcc/tree-streamer-out.c b/gcc/tree-streamer-out.c index 3439bffed5c..7161dba1a54 100644 --- a/gcc/tree-streamer-out.c +++ b/gcc/tree-streamer-out.c @@ -25,6 +25,7 @@ along with GCC; see the file COPYING3. If not see #include "tm.h" #include "diagnostic.h" #include "tree.h" +#include "gimple.h" #include "tree-streamer.h" #include "data-streamer.h" #include "streamer-hooks.h" diff --git a/gcc/tree-streamer.c b/gcc/tree-streamer.c index 8d532d9c250..8534f4a9b8b 100644 --- a/gcc/tree-streamer.c +++ b/gcc/tree-streamer.c @@ -23,6 +23,8 @@ along with GCC; see the file COPYING3. If not see #include "config.h" #include "system.h" #include "coretypes.h" +#include "tree.h" +#include "gimple.h" #include "streamer-hooks.h" #include "tree-streamer.h" diff --git a/gcc/tree-streamer.h b/gcc/tree-streamer.h index 02f8f51a195..1ed215c9792 100644 --- a/gcc/tree-streamer.h +++ b/gcc/tree-streamer.h @@ -22,7 +22,6 @@ along with GCC; see the file COPYING3. If not see #ifndef GCC_TREE_STREAMER_H #define GCC_TREE_STREAMER_H -#include "tree.h" #include "streamer-hooks.h" #include "lto-streamer.h" diff --git a/gcc/tree-switch-conversion.c b/gcc/tree-switch-conversion.c index 776b8c13306..9486132a0b9 100644 --- a/gcc/tree-switch-conversion.c +++ b/gcc/tree-switch-conversion.c @@ -31,7 +31,12 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "flags.h" #include "tree.h" #include "basic-block.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "cgraph.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "tree-ssanames.h" #include "tree-pass.h" #include "gimple-pretty-print.h" #include "cfgloop.h" diff --git a/gcc/tree-tailcall.c b/gcc/tree-tailcall.c index 415d19acbbb..70d167a58e9 100644 --- a/gcc/tree-tailcall.c +++ b/gcc/tree-tailcall.c @@ -25,7 +25,13 @@ along with GCC; see the file COPYING3. If not see #include "tm_p.h" #include "basic-block.h" #include "function.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "tree-ssanames.h" +#include "tree-into-ssa.h" +#include "tree-dfa.h" #include "gimple-pretty-print.h" #include "except.h" #include "tree-pass.h" diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c index 3764cfb98f8..919db21fb96 100644 --- a/gcc/tree-vect-data-refs.c +++ b/gcc/tree-vect-data-refs.c @@ -30,7 +30,14 @@ along with GCC; see the file COPYING3. If not see #include "target.h" #include "basic-block.h" #include "gimple-pretty-print.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" +#include "tree-ssa-loop-ivopts.h" +#include "tree-ssa-loop-manip.h" +#include "tree-ssa-loop.h" #include "dumpfile.h" #include "cfgloop.h" #include "tree-chrec.h" diff --git a/gcc/tree-vect-generic.c b/gcc/tree-vect-generic.c index d242959b131..d58ddffb50b 100644 --- a/gcc/tree-vect-generic.c +++ b/gcc/tree-vect-generic.c @@ -23,8 +23,10 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "tm.h" #include "langhooks.h" -#include "tree-ssa.h" #include "gimple.h" +#include "gimple-ssa.h" +#include "tree-cfg.h" +#include "tree-ssanames.h" #include "tree-iterator.h" #include "tree-pass.h" #include "flags.h" diff --git a/gcc/tree-vect-loop-manip.c b/gcc/tree-vect-loop-manip.c index 1fe20d91cb4..9b879a4125c 100644 --- a/gcc/tree-vect-loop-manip.c +++ b/gcc/tree-vect-loop-manip.c @@ -28,6 +28,14 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "basic-block.h" #include "gimple-pretty-print.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" +#include "tree-ssa-loop-manip.h" +#include "tree-into-ssa.h" #include "tree-ssa.h" #include "tree-pass.h" #include "cfgloop.h" @@ -107,7 +115,7 @@ typedef struct with a PHI DEF that would soon become non-dominant, and when we got to the suitable one, it wouldn't have anything to substitute any more. */ -static vec<adjust_info, va_stack> adjust_vec; +static vec<adjust_info, va_heap> adjust_vec; /* Adjust any debug stmts that referenced AI->from values to use the loop-closed AI->to, if the references are dominated by AI->bb and @@ -1125,7 +1133,7 @@ slpeel_tree_peel_loop_to_edge (struct loop *loop, if (MAY_HAVE_DEBUG_STMTS) { gcc_assert (!adjust_vec.exists ()); - vec_stack_alloc (adjust_info, adjust_vec, 32); + adjust_vec.create (32); } if (e == exit_e) @@ -1429,7 +1437,7 @@ vect_build_loop_niters (loop_vec_info loop_vinfo, gimple_seq seq) and places them at the loop preheader edge or in COND_EXPR_STMT_LIST if that is non-NULL. */ -static void +void vect_generate_tmps_on_preheader (loop_vec_info loop_vinfo, tree *ni_name_ptr, tree *ratio_mult_vf_name_ptr, diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c index bb700d0e60c..1652b11bcaa 100644 --- a/gcc/tree-vect-loop.c +++ b/gcc/tree-vect-loop.c @@ -28,7 +28,14 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "basic-block.h" #include "gimple-pretty-print.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" +#include "tree-ssa-loop-ivopts.h" +#include "tree-ssa-loop-manip.h" +#include "tree-ssa-loop-niter.h" #include "tree-pass.h" #include "cfgloop.h" #include "expr.h" @@ -584,8 +591,7 @@ vect_analyze_scalar_cycles_1 (loop_vec_info loop_vinfo, struct loop *loop) { basic_block bb = loop->header; tree init, step; - vec<gimple> worklist; - worklist.create (64); + stack_vec<gimple, 64> worklist; gimple_stmt_iterator gsi; bool double_reduc; @@ -716,8 +722,6 @@ vect_analyze_scalar_cycles_1 (loop_vec_info loop_vinfo, struct loop *loop) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, "Unknown def-use cycle pattern.\n"); } - - worklist.release (); } @@ -1579,9 +1583,9 @@ vect_analyze_loop_operations (loop_vec_info loop_vinfo, bool slp) return false; } - if (!LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo) - || LOOP_VINFO_INT_NITERS (loop_vinfo) % vectorization_factor != 0 - || LOOP_PEELING_FOR_ALIGNMENT (loop_vinfo)) + if (LOOP_PEELING_FOR_ALIGNMENT (loop_vinfo) + || ((int) tree_ctz (LOOP_VINFO_NITERS (loop_vinfo)) + < exact_log2 (vectorization_factor))) { if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, "epilog loop required.\n"); @@ -5649,15 +5653,20 @@ vect_transform_loop (loop_vec_info loop_vinfo) will remain scalar and will compute the remaining (n%VF) iterations. (VF is the vectorization factor). */ - if (!LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo) - || (LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo) - && LOOP_VINFO_INT_NITERS (loop_vinfo) % vectorization_factor != 0) - || LOOP_VINFO_PEELING_FOR_GAPS (loop_vinfo)) + if ((int) tree_ctz (LOOP_VINFO_NITERS (loop_vinfo)) + < exact_log2 (vectorization_factor) + || LOOP_VINFO_PEELING_FOR_GAPS (loop_vinfo)) vect_do_peeling_for_loop_bound (loop_vinfo, &ratio, th, check_profitability); - else + else if (LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)) ratio = build_int_cst (TREE_TYPE (LOOP_VINFO_NITERS (loop_vinfo)), LOOP_VINFO_INT_NITERS (loop_vinfo) / vectorization_factor); + else + { + tree ni_name, ratio_mult_vf; + vect_generate_tmps_on_preheader (loop_vinfo, &ni_name, &ratio_mult_vf, + &ratio, NULL); + } /* 1) Make sure the loop header has exactly two entries 2) Make sure we have a preheader basic block. */ diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c index e9222232479..5075246a19b 100644 --- a/gcc/tree-vect-patterns.c +++ b/gcc/tree-vect-patterns.c @@ -27,7 +27,11 @@ along with GCC; see the file COPYING3. If not see #include "target.h" #include "basic-block.h" #include "gimple-pretty-print.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" #include "cfgloop.h" #include "expr.h" #include "optabs.h" @@ -2226,20 +2230,19 @@ vect_recog_divmod_pattern (vec<gimple> *stmts, if (post_shift >= prec) return NULL; - /* t1 = oprnd1 h* ml; */ + /* t1 = oprnd0 h* ml; */ t1 = vect_recog_temp_ssa_var (itype, NULL); def_stmt = gimple_build_assign_with_ops (MULT_HIGHPART_EXPR, t1, oprnd0, build_int_cst (itype, ml)); - append_pattern_def_seq (stmt_vinfo, def_stmt); if (add) { /* t2 = t1 + oprnd0; */ + append_pattern_def_seq (stmt_vinfo, def_stmt); t2 = vect_recog_temp_ssa_var (itype, NULL); def_stmt = gimple_build_assign_with_ops (PLUS_EXPR, t2, t1, oprnd0); - append_pattern_def_seq (stmt_vinfo, def_stmt); } else t2 = t1; @@ -2247,27 +2250,57 @@ vect_recog_divmod_pattern (vec<gimple> *stmts, if (post_shift) { /* t3 = t2 >> post_shift; */ + append_pattern_def_seq (stmt_vinfo, def_stmt); t3 = vect_recog_temp_ssa_var (itype, NULL); def_stmt = gimple_build_assign_with_ops (RSHIFT_EXPR, t3, t2, build_int_cst (itype, post_shift)); - append_pattern_def_seq (stmt_vinfo, def_stmt); } else t3 = t2; - /* t4 = oprnd0 >> (prec - 1); */ - t4 = vect_recog_temp_ssa_var (itype, NULL); - def_stmt - = gimple_build_assign_with_ops (RSHIFT_EXPR, t4, oprnd0, - build_int_cst (itype, prec - 1)); - append_pattern_def_seq (stmt_vinfo, def_stmt); + widest_int oprnd0_min, oprnd0_max; + int msb = 1; + if (get_range_info (oprnd0, &oprnd0_min, &oprnd0_max) == VR_RANGE) + { + if (!wi::neg_p (oprnd0_min)) + msb = 0; + else if (wi::neg_p (oprnd0_max)) + msb = -1; + } - /* q = t3 - t4; or q = t4 - t3; */ - q = vect_recog_temp_ssa_var (itype, NULL); - pattern_stmt - = gimple_build_assign_with_ops (MINUS_EXPR, q, d < 0 ? t4 : t3, - d < 0 ? t3 : t4); + if (msb == 0 && d >= 0) + { + /* q = t3; */ + q = t3; + pattern_stmt = def_stmt; + } + else + { + /* t4 = oprnd0 >> (prec - 1); + or if we know from VRP that oprnd0 >= 0 + t4 = 0; + or if we know from VRP that oprnd0 < 0 + t4 = -1; */ + append_pattern_def_seq (stmt_vinfo, def_stmt); + t4 = vect_recog_temp_ssa_var (itype, NULL); + if (msb != 1) + def_stmt + = gimple_build_assign_with_ops (INTEGER_CST, + t4, build_int_cst (itype, msb), + NULL_TREE); + else + def_stmt + = gimple_build_assign_with_ops (RSHIFT_EXPR, t4, oprnd0, + build_int_cst (itype, prec - 1)); + append_pattern_def_seq (stmt_vinfo, def_stmt); + + /* q = t3 - t4; or q = t4 - t3; */ + q = vect_recog_temp_ssa_var (itype, NULL); + pattern_stmt + = gimple_build_assign_with_ops (MINUS_EXPR, q, d < 0 ? t4 : t3, + d < 0 ? t3 : t4); + } } if (rhs_code == TRUNC_MOD_EXPR) @@ -3174,8 +3207,7 @@ vect_pattern_recog (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo) gimple_stmt_iterator si; unsigned int i, j; vect_recog_func_ptr vect_recog_func; - vec<gimple> stmts_to_replace; - stmts_to_replace.create (1); + stack_vec<gimple, 1> stmts_to_replace; gimple stmt; if (dump_enabled_p ()) @@ -3215,6 +3247,4 @@ vect_pattern_recog (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo) } } } - - stmts_to_replace.release (); } diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c index b3b3abec110..825f73a429a 100644 --- a/gcc/tree-vect-slp.c +++ b/gcc/tree-vect-slp.c @@ -29,7 +29,11 @@ along with GCC; see the file COPYING3. If not see #include "target.h" #include "basic-block.h" #include "gimple-pretty-print.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" #include "tree-pass.h" #include "cfgloop.h" #include "expr.h" @@ -1930,7 +1934,7 @@ vect_slp_analyze_operations (bb_vec_info bb_vinfo) static unsigned vect_bb_slp_scalar_cost (basic_block bb, - slp_tree node, vec<bool, va_stack> life) + slp_tree node, vec<bool, va_heap> *life) { unsigned scalar_cost = 0; unsigned i; @@ -1944,7 +1948,7 @@ vect_bb_slp_scalar_cost (basic_block bb, def_operand_p def_p; stmt_vec_info stmt_info; - if (life[i]) + if ((*life)[i]) continue; /* If there is a non-vectorized use of the defs then the scalar @@ -1961,11 +1965,11 @@ vect_bb_slp_scalar_cost (basic_block bb, || gimple_bb (use_stmt) != bb || !STMT_VINFO_VECTORIZABLE (vinfo_for_stmt (use_stmt))) { - life[i] = true; + (*life)[i] = true; BREAK_FROM_IMM_USE_STMT (use_iter); } } - if (life[i]) + if ((*life)[i]) continue; stmt_info = vinfo_for_stmt (stmt); @@ -2019,13 +2023,11 @@ vect_bb_vectorization_profitable_p (bb_vec_info bb_vinfo) /* Calculate scalar cost. */ FOR_EACH_VEC_ELT (slp_instances, i, instance) { - vec<bool, va_stack> life; - vec_stack_alloc (bool, life, SLP_INSTANCE_GROUP_SIZE (instance)); - life.quick_grow_cleared (SLP_INSTANCE_GROUP_SIZE (instance)); + stack_vec<bool, 20> life; + life.safe_grow_cleared (SLP_INSTANCE_GROUP_SIZE (instance)); scalar_cost += vect_bb_slp_scalar_cost (BB_VINFO_BB (bb_vinfo), SLP_INSTANCE_TREE (instance), - life); - life.release (); + &life); } /* Complete the target-specific cost calculation. */ diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c index ae2abba530d..3a9d6298e66 100644 --- a/gcc/tree-vect-stmts.c +++ b/gcc/tree-vect-stmts.c @@ -29,7 +29,13 @@ along with GCC; see the file COPYING3. If not see #include "target.h" #include "basic-block.h" #include "gimple-pretty-print.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" +#include "tree-ssa-loop-manip.h" #include "cfgloop.h" #include "expr.h" #include "recog.h" /* FIXME: for insn_data */ @@ -574,7 +580,6 @@ process_use (gimple stmt, tree use, loop_vec_info loop_vinfo, bool live_p, bool vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo) { - vec<gimple> worklist; struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo); unsigned int nbbs = loop->num_nodes; @@ -592,7 +597,7 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo) dump_printf_loc (MSG_NOTE, vect_location, "=== vect_mark_stmts_to_be_vectorized ===\n"); - worklist.create (64); + stack_vec<gimple, 64> worklist; /* 1. Init worklist. */ for (i = 0; i < nbbs; i++) @@ -682,7 +687,6 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo) if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, "unsupported use of reduction.\n"); - worklist.release (); return false; } @@ -698,7 +702,6 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, "unsupported use of nested cycle.\n"); - worklist.release (); return false; } @@ -713,7 +716,6 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, "unsupported use of double reduction.\n"); - worklist.release (); return false; } @@ -741,10 +743,7 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo) live_p, relevant, &worklist, false) || !process_use (stmt, TREE_OPERAND (op, 1), loop_vinfo, live_p, relevant, &worklist, false)) - { - worklist.release (); - return false; - } + return false; i = 2; } for (; i < gimple_num_ops (stmt); i++) @@ -752,10 +751,7 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo) op = gimple_op (stmt, i); if (!process_use (stmt, op, loop_vinfo, live_p, relevant, &worklist, false)) - { - worklist.release (); - return false; - } + return false; } } else if (is_gimple_call (stmt)) @@ -765,10 +761,7 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo) tree arg = gimple_call_arg (stmt, i); if (!process_use (stmt, arg, loop_vinfo, live_p, relevant, &worklist, false)) - { - worklist.release (); - return false; - } + return false; } } } @@ -778,10 +771,7 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo) tree op = USE_FROM_PTR (use_p); if (!process_use (stmt, op, loop_vinfo, live_p, relevant, &worklist, false)) - { - worklist.release (); - return false; - } + return false; } if (STMT_VINFO_GATHER_P (stmt_vinfo)) @@ -791,14 +781,10 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo) gcc_assert (decl); if (!process_use (stmt, off, loop_vinfo, live_p, relevant, &worklist, true)) - { - worklist.release (); - return false; - } + return false; } } /* while worklist */ - worklist.release (); return true; } @@ -5546,11 +5532,9 @@ vectorizable_condition (gimple stmt, gimple_stmt_iterator *gsi, { if (slp_node) { - vec<tree> ops; - ops.create (4); - vec<vec<tree> > vec_defs; + stack_vec<tree, 4> ops; + stack_vec<vec<tree>, 4> vec_defs; - vec_defs.create (4); ops.safe_push (TREE_OPERAND (cond_expr, 0)); ops.safe_push (TREE_OPERAND (cond_expr, 1)); ops.safe_push (then_clause); diff --git a/gcc/tree-vectorizer.c b/gcc/tree-vectorizer.c index 511972ae313..8e3190fa2c1 100644 --- a/gcc/tree-vectorizer.c +++ b/gcc/tree-vectorizer.c @@ -62,7 +62,12 @@ along with GCC; see the file COPYING3. If not see #include "ggc.h" #include "tree.h" #include "tree-pretty-print.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "cgraph.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssa-loop-manip.h" #include "cfgloop.h" #include "tree-vectorizer.h" #include "tree-pass.h" @@ -547,7 +552,7 @@ increase_alignment (void) /* Increase the alignment of all global arrays for vectorization. */ FOR_EACH_DEFINED_VARIABLE (vnode) { - tree vectype, decl = vnode->symbol.decl; + tree vectype, decl = vnode->decl; tree t; unsigned int alignment; diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h index 2dc0c702fa8..97dbfb56507 100644 --- a/gcc/tree-vectorizer.h +++ b/gcc/tree-vectorizer.h @@ -901,6 +901,8 @@ extern void slpeel_make_loop_iterate_ntimes (struct loop *, tree); extern bool slpeel_can_duplicate_loop_p (const struct loop *, const_edge); struct loop *slpeel_tree_duplicate_loop_to_edge_cfg (struct loop *, edge); extern void vect_loop_versioning (loop_vec_info, unsigned int, bool); +extern void vect_generate_tmps_on_preheader (loop_vec_info, tree *, tree *, + tree *, gimple_seq); extern void vect_do_peeling_for_loop_bound (loop_vec_info, tree *, unsigned int, bool); extern void vect_do_peeling_for_alignment (loop_vec_info, unsigned int, bool); diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index fa30d1da997..03fb075193d 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -26,6 +26,16 @@ along with GCC; see the file COPYING3. If not see #include "flags.h" #include "tree.h" #include "basic-block.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" +#include "tree-ssa-loop-manip.h" +#include "tree-ssa-loop-niter.h" +#include "tree-ssa-loop.h" +#include "tree-into-ssa.h" #include "tree-ssa.h" #include "tree-pass.h" #include "tree-dump.h" @@ -6376,6 +6386,87 @@ check_all_array_refs (void) } } +/* Return true if all imm uses of VAR are either in STMT, or + feed (optionally through a chain of single imm uses) GIMPLE_COND + in basic block COND_BB. */ + +static bool +all_imm_uses_in_stmt_or_feed_cond (tree var, gimple stmt, basic_block cond_bb) +{ + use_operand_p use_p, use2_p; + imm_use_iterator iter; + + FOR_EACH_IMM_USE_FAST (use_p, iter, var) + if (USE_STMT (use_p) != stmt) + { + gimple use_stmt = USE_STMT (use_p); + if (is_gimple_debug (use_stmt)) + continue; + while (is_gimple_assign (use_stmt) + && single_imm_use (gimple_assign_lhs (use_stmt), + &use2_p, &use_stmt)) + ; + if (gimple_code (use_stmt) != GIMPLE_COND + || gimple_bb (use_stmt) != cond_bb) + return false; + } + return true; +} + +/* Handle + _4 = x_3 & 31; + if (_4 != 0) + goto <bb 6>; + else + goto <bb 7>; + <bb 6>: + __builtin_unreachable (); + <bb 7>: + x_5 = ASSERT_EXPR <x_3, ...>; + If x_3 has no other immediate uses (checked by caller), + var is the x_3 var from ASSERT_EXPR, we can clear low 5 bits + from the non-zero bitmask. */ + +static void +maybe_set_nonzero_bits (basic_block bb, tree var) +{ + edge e = single_pred_edge (bb); + basic_block cond_bb = e->src; + gimple stmt = last_stmt (cond_bb); + tree cst; + + if (stmt == NULL + || gimple_code (stmt) != GIMPLE_COND + || gimple_cond_code (stmt) != ((e->flags & EDGE_TRUE_VALUE) + ? EQ_EXPR : NE_EXPR) + || TREE_CODE (gimple_cond_lhs (stmt)) != SSA_NAME + || !integer_zerop (gimple_cond_rhs (stmt))) + return; + + stmt = SSA_NAME_DEF_STMT (gimple_cond_lhs (stmt)); + if (!is_gimple_assign (stmt) + || gimple_assign_rhs_code (stmt) != BIT_AND_EXPR + || TREE_CODE (gimple_assign_rhs2 (stmt)) != INTEGER_CST) + return; + if (gimple_assign_rhs1 (stmt) != var) + { + gimple stmt2; + + if (TREE_CODE (gimple_assign_rhs1 (stmt)) != SSA_NAME) + return; + stmt2 = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (stmt)); + if (!gimple_assign_cast_p (stmt2) + || gimple_assign_rhs1 (stmt2) != var + || !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (stmt2)) + || (TYPE_PRECISION (TREE_TYPE (gimple_assign_rhs1 (stmt))) + != TYPE_PRECISION (TREE_TYPE (var)))) + return; + } + cst = gimple_assign_rhs2 (stmt); + set_nonzero_bits (var, (get_nonzero_bits (var) + & ~wi::to_widest (cst))); +} + /* Convert range assertion expressions into the implied copies and copy propagate away the copies. Doing the trivial copy propagation here avoids the need to run the full copy propagation pass after @@ -6405,12 +6496,16 @@ remove_range_assertions (void) { basic_block bb; gimple_stmt_iterator si; + /* 1 if looking at ASSERT_EXPRs immediately at the beginning of + a basic block preceeded by GIMPLE_COND branching to it and + __builtin_trap, -1 if not yet checked, 0 otherwise. */ + int is_unreachable; /* Note that the BSI iterator bump happens at the bottom of the loop and no bump is necessary if we're removing the statement referenced by the current BSI. */ FOR_EACH_BB (bb) - for (si = gsi_start_bb (bb); !gsi_end_p (si);) + for (si = gsi_after_labels (bb), is_unreachable = -1; !gsi_end_p (si);) { gimple stmt = gsi_stmt (si); gimple use_stmt; @@ -6418,6 +6513,7 @@ remove_range_assertions (void) if (is_gimple_assign (stmt) && gimple_assign_rhs_code (stmt) == ASSERT_EXPR) { + tree lhs = gimple_assign_lhs (stmt); tree rhs = gimple_assign_rhs1 (stmt); tree var; tree cond = fold (ASSERT_EXPR_COND (rhs)); @@ -6426,22 +6522,52 @@ remove_range_assertions (void) gcc_assert (cond != boolean_false_node); - /* Propagate the RHS into every use of the LHS. */ var = ASSERT_EXPR_VAR (rhs); - FOR_EACH_IMM_USE_STMT (use_stmt, iter, - gimple_assign_lhs (stmt)) + gcc_assert (TREE_CODE (var) == SSA_NAME); + + if (!POINTER_TYPE_P (TREE_TYPE (lhs)) + && SSA_NAME_RANGE_INFO (lhs)) + { + if (is_unreachable == -1) + { + is_unreachable = 0; + if (single_pred_p (bb) + && assert_unreachable_fallthru_edge_p + (single_pred_edge (bb))) + is_unreachable = 1; + } + /* Handle + if (x_7 >= 10 && x_7 < 20) + __builtin_unreachable (); + x_8 = ASSERT_EXPR <x_7, ...>; + if the only uses of x_7 are in the ASSERT_EXPR and + in the condition. In that case, we can copy the + range info from x_8 computed in this pass also + for x_7. */ + if (is_unreachable + && all_imm_uses_in_stmt_or_feed_cond (var, stmt, + single_pred (bb))) + { + set_range_info (var, SSA_NAME_RANGE_INFO (lhs)->min, + SSA_NAME_RANGE_INFO (lhs)->max); + maybe_set_nonzero_bits (bb, var); + } + } + + /* Propagate the RHS into every use of the LHS. */ + FOR_EACH_IMM_USE_STMT (use_stmt, iter, lhs) FOR_EACH_IMM_USE_ON_STMT (use_p, iter) - { - SET_USE (use_p, var); - gcc_assert (TREE_CODE (var) == SSA_NAME); - } + SET_USE (use_p, var); /* And finally, remove the copy, it is not needed. */ gsi_remove (&si, true); release_defs (stmt); } else - gsi_next (&si); + { + gsi_next (&si); + is_unreachable = 0; + } } } diff --git a/gcc/tree.c b/gcc/tree.c index 9344f7f0429..133dbb16da9 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -47,7 +47,13 @@ along with GCC; see the file COPYING3. If not see #include "tree-inline.h" #include "tree-iterator.h" #include "basic-block.h" -#include "tree-ssa.h" +#include "bitmap.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "cgraph.h" +#include "tree-phinodes.h" +#include "tree-ssanames.h" +#include "tree-dfa.h" #include "params.h" #include "pointer-set.h" #include "tree-pass.h" @@ -55,7 +61,6 @@ along with GCC; see the file COPYING3. If not see #include "diagnostic.h" #include "tree-diagnostic.h" #include "tree-pretty-print.h" -#include "cgraph.h" #include "except.h" #include "debug.h" #include "intl.h" @@ -1284,7 +1289,8 @@ wide_int_to_tree (tree type, const wide_int_ref &pcst) case POINTER_TYPE: case REFERENCE_TYPE: - /* Cache NULL pointer. */ + case POINTER_BOUNDS_TYPE: + /* Cache NULL pointer and zero bounds. */ if (cst == 0) { limit = 1; @@ -2222,6 +2228,119 @@ tree_floor_log2 (const_tree expr) return wi::floor_log2 (expr); } +/* Return number of known trailing zero bits in EXPR, or, if the value of + EXPR is known to be zero, the precision of it's type. */ + +unsigned int +tree_ctz (const_tree expr) +{ + if (!INTEGRAL_TYPE_P (TREE_TYPE (expr)) + && !POINTER_TYPE_P (TREE_TYPE (expr))) + return 0; + + unsigned int ret1, ret2, prec = TYPE_PRECISION (TREE_TYPE (expr)); + switch (TREE_CODE (expr)) + { + case INTEGER_CST: + ret1 = wi::ctz (expr); + return MIN (ret1, prec); + case SSA_NAME: + ret1 = wi::ctz (get_nonzero_bits (expr)); + return MIN (ret1, prec); + case PLUS_EXPR: + case MINUS_EXPR: + case BIT_IOR_EXPR: + case BIT_XOR_EXPR: + case MIN_EXPR: + case MAX_EXPR: + ret1 = tree_ctz (TREE_OPERAND (expr, 0)); + if (ret1 == 0) + return ret1; + ret2 = tree_ctz (TREE_OPERAND (expr, 1)); + return MIN (ret1, ret2); + case POINTER_PLUS_EXPR: + ret1 = tree_ctz (TREE_OPERAND (expr, 0)); + ret2 = tree_ctz (TREE_OPERAND (expr, 1)); + /* Second operand is sizetype, which could be in theory + wider than pointer's precision. Make sure we never + return more than prec. */ + ret2 = MIN (ret2, prec); + return MIN (ret1, ret2); + case BIT_AND_EXPR: + ret1 = tree_ctz (TREE_OPERAND (expr, 0)); + ret2 = tree_ctz (TREE_OPERAND (expr, 1)); + return MAX (ret1, ret2); + case MULT_EXPR: + ret1 = tree_ctz (TREE_OPERAND (expr, 0)); + ret2 = tree_ctz (TREE_OPERAND (expr, 1)); + return MIN (ret1 + ret2, prec); + case LSHIFT_EXPR: + ret1 = tree_ctz (TREE_OPERAND (expr, 0)); + if (tree_fits_uhwi_p (TREE_OPERAND (expr, 1)) + && ((unsigned HOST_WIDE_INT) tree_to_uhwi (TREE_OPERAND (expr, 1)) + < (unsigned HOST_WIDE_INT) prec)) + { + ret2 = tree_to_uhwi (TREE_OPERAND (expr, 1)); + return MIN (ret1 + ret2, prec); + } + return ret1; + case RSHIFT_EXPR: + if (tree_fits_uhwi_p (TREE_OPERAND (expr, 1)) + && ((unsigned HOST_WIDE_INT) tree_to_uhwi (TREE_OPERAND (expr, 1)) + < (unsigned HOST_WIDE_INT) prec)) + { + ret1 = tree_ctz (TREE_OPERAND (expr, 0)); + ret2 = tree_to_uhwi (TREE_OPERAND (expr, 1)); + if (ret1 > ret2) + return ret1 - ret2; + } + return 0; + case TRUNC_DIV_EXPR: + case CEIL_DIV_EXPR: + case FLOOR_DIV_EXPR: + case ROUND_DIV_EXPR: + case EXACT_DIV_EXPR: + if (TREE_CODE (TREE_OPERAND (expr, 1)) == INTEGER_CST + && tree_int_cst_sgn (TREE_OPERAND (expr, 1)) == 1) + { + int l = tree_log2 (TREE_OPERAND (expr, 1)); + if (l >= 0) + { + ret1 = tree_ctz (TREE_OPERAND (expr, 0)); + ret2 = l; + if (ret1 > ret2) + return ret1 - ret2; + } + } + return 0; + CASE_CONVERT: + ret1 = tree_ctz (TREE_OPERAND (expr, 0)); + if (ret1 && ret1 == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (expr, 0)))) + ret1 = prec; + return MIN (ret1, prec); + case SAVE_EXPR: + return tree_ctz (TREE_OPERAND (expr, 0)); + case COND_EXPR: + ret1 = tree_ctz (TREE_OPERAND (expr, 1)); + if (ret1 == 0) + return 0; + ret2 = tree_ctz (TREE_OPERAND (expr, 2)); + return MIN (ret1, ret2); + case COMPOUND_EXPR: + return tree_ctz (TREE_OPERAND (expr, 1)); + case ADDR_EXPR: + ret1 = get_pointer_alignment (CONST_CAST_TREE (expr)); + if (ret1 > BITS_PER_UNIT) + { + ret1 = ctz_hwi (ret1 / BITS_PER_UNIT); + return MIN (ret1, prec); + } + return 0; + default: + return 0; + } +} + /* Return 1 if EXPR is the real constant zero. Trailing zeroes matter for decimal float constants, so don't return 1 for them. */ @@ -3279,6 +3398,7 @@ type_contains_placeholder_1 (const_tree type) switch (TREE_CODE (type)) { case VOID_TYPE: + case POINTER_BOUNDS_TYPE: case COMPLEX_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE: @@ -5013,7 +5133,7 @@ free_lang_data_in_decl (tree decl) { struct cgraph_node *node; if (!(node = cgraph_get_node (decl)) - || (!node->symbol.definition && !node->clones)) + || (!node->definition && !node->clones)) { if (node) cgraph_release_function_body (node); @@ -5427,14 +5547,14 @@ find_decls_types_in_node (struct cgraph_node *n, struct free_lang_data_d *fld) unsigned ix; tree t; - find_decls_types (n->symbol.decl, fld); + find_decls_types (n->decl, fld); - if (!gimple_has_body_p (n->symbol.decl)) + if (!gimple_has_body_p (n->decl)) return; gcc_assert (current_function_decl == NULL_TREE && cfun == NULL); - fn = DECL_STRUCT_FUNCTION (n->symbol.decl); + fn = DECL_STRUCT_FUNCTION (n->decl); /* Traverse locals. */ FOR_EACH_LOCAL_DECL (fn, ix, t) @@ -5490,7 +5610,7 @@ find_decls_types_in_node (struct cgraph_node *n, struct free_lang_data_d *fld) static void find_decls_types_in_var (struct varpool_node *v, struct free_lang_data_d *fld) { - find_decls_types (v->symbol.decl, fld); + find_decls_types (v->decl, fld); } /* If T needs an assembler name, have one created for it. */ @@ -9676,6 +9796,8 @@ build_common_tree_nodes (bool signed_char, bool short_double) void_type_node = make_node (VOID_TYPE); layout_type (void_type_node); + pointer_bounds_type_node = targetm.chkp_bound_type (); + /* We are not going to have real types in C with less than byte alignment, so we might as well not have any types that claim to have it. */ TYPE_ALIGN (void_type_node) = BITS_PER_UNIT; diff --git a/gcc/tree.def b/gcc/tree.def index 0f9646af071..47acd7b941d 100644 --- a/gcc/tree.def +++ b/gcc/tree.def @@ -232,6 +232,11 @@ DEFTREECODE (QUAL_UNION_TYPE, "qual_union_type", tcc_type, 0) /* The void type in C */ DEFTREECODE (VOID_TYPE, "void_type", tcc_type, 0) +/* Type to hold bounds for a pointer. + Has TYPE_PRECISION component to specify number of bits used + by this type. */ +DEFTREECODE (POINTER_BOUNDS_TYPE, "pointer_bounds_type", tcc_type, 0) + /* Type of functions. Special fields: TREE_TYPE type of value returned. TYPE_ARG_TYPES list of types of arguments expected. @@ -1272,6 +1277,18 @@ DEFTREECODE (OPTIMIZATION_NODE, "optimization_node", tcc_exceptional, 0) /* TARGET_OPTION_NODE. Node to store the target specific options. */ DEFTREECODE (TARGET_OPTION_NODE, "target_option_node", tcc_exceptional, 0) +/* ANNOTATE_EXPR. + Operand 0 is the expression to be annotated. + Operand 1 is the annotation id. */ +DEFTREECODE (ANNOTATE_EXPR, "annotate_expr", tcc_expression, 2) + +/* Cilk spawn statement + Operand 0 is the CALL_EXPR. */ +DEFTREECODE (CILK_SPAWN_STMT, "cilk_spawn_stmt", tcc_statement, 1) + +/* Cilk Sync statement: Does not have any operands. */ +DEFTREECODE (CILK_SYNC_STMT, "cilk_sync_stmt", tcc_statement, 0) + /* Local variables: mode:c diff --git a/gcc/tree.h b/gcc/tree.h index 43f383fff80..ec92f843a41 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -91,25 +91,25 @@ along with GCC; see the file COPYING3. If not see #define TREE_CODE_CLASS(CODE) tree_code_type[(int) (CODE)] -/* Nonzero if CODE represents an exceptional code. */ +/* Nonzero if NODE represents an exceptional code. */ -#define EXCEPTIONAL_CLASS_P(CODE)\ - (TREE_CODE_CLASS (TREE_CODE (CODE)) == tcc_exceptional) +#define EXCEPTIONAL_CLASS_P(NODE)\ + (TREE_CODE_CLASS (TREE_CODE (NODE)) == tcc_exceptional) -/* Nonzero if CODE represents a constant. */ +/* Nonzero if NODE represents a constant. */ -#define CONSTANT_CLASS_P(CODE)\ - (TREE_CODE_CLASS (TREE_CODE (CODE)) == tcc_constant) +#define CONSTANT_CLASS_P(NODE)\ + (TREE_CODE_CLASS (TREE_CODE (NODE)) == tcc_constant) -/* Nonzero if CODE represents a type. */ +/* Nonzero if NODE represents a type. */ -#define TYPE_P(CODE)\ - (TREE_CODE_CLASS (TREE_CODE (CODE)) == tcc_type) +#define TYPE_P(NODE)\ + (TREE_CODE_CLASS (TREE_CODE (NODE)) == tcc_type) -/* Nonzero if CODE represents a declaration. */ +/* Nonzero if NODE represents a declaration. */ -#define DECL_P(CODE)\ - (TREE_CODE_CLASS (TREE_CODE (CODE)) == tcc_declaration) +#define DECL_P(NODE)\ + (TREE_CODE_CLASS (TREE_CODE (NODE)) == tcc_declaration) /* True if NODE designates a variable declaration. */ #define VAR_P(NODE) \ @@ -120,52 +120,52 @@ along with GCC; see the file COPYING3. If not see #define VAR_OR_FUNCTION_DECL_P(DECL)\ (TREE_CODE (DECL) == VAR_DECL || TREE_CODE (DECL) == FUNCTION_DECL) -/* Nonzero if CODE represents a INDIRECT_REF. Keep these checks in +/* Nonzero if NODE represents a INDIRECT_REF. Keep these checks in ascending code order. */ -#define INDIRECT_REF_P(CODE)\ - (TREE_CODE (CODE) == INDIRECT_REF) +#define INDIRECT_REF_P(NODE)\ + (TREE_CODE (NODE) == INDIRECT_REF) -/* Nonzero if CODE represents a reference. */ +/* Nonzero if NODE represents a reference. */ -#define REFERENCE_CLASS_P(CODE)\ - (TREE_CODE_CLASS (TREE_CODE (CODE)) == tcc_reference) +#define REFERENCE_CLASS_P(NODE)\ + (TREE_CODE_CLASS (TREE_CODE (NODE)) == tcc_reference) -/* Nonzero if CODE represents a comparison. */ +/* Nonzero if NODE represents a comparison. */ -#define COMPARISON_CLASS_P(CODE)\ - (TREE_CODE_CLASS (TREE_CODE (CODE)) == tcc_comparison) +#define COMPARISON_CLASS_P(NODE)\ + (TREE_CODE_CLASS (TREE_CODE (NODE)) == tcc_comparison) -/* Nonzero if CODE represents a unary arithmetic expression. */ +/* Nonzero if NODE represents a unary arithmetic expression. */ -#define UNARY_CLASS_P(CODE)\ - (TREE_CODE_CLASS (TREE_CODE (CODE)) == tcc_unary) +#define UNARY_CLASS_P(NODE)\ + (TREE_CODE_CLASS (TREE_CODE (NODE)) == tcc_unary) -/* Nonzero if CODE represents a binary arithmetic expression. */ +/* Nonzero if NODE represents a binary arithmetic expression. */ -#define BINARY_CLASS_P(CODE)\ - (TREE_CODE_CLASS (TREE_CODE (CODE)) == tcc_binary) +#define BINARY_CLASS_P(NODE)\ + (TREE_CODE_CLASS (TREE_CODE (NODE)) == tcc_binary) -/* Nonzero if CODE represents a statement expression. */ +/* Nonzero if NODE represents a statement expression. */ -#define STATEMENT_CLASS_P(CODE)\ - (TREE_CODE_CLASS (TREE_CODE (CODE)) == tcc_statement) +#define STATEMENT_CLASS_P(NODE)\ + (TREE_CODE_CLASS (TREE_CODE (NODE)) == tcc_statement) -/* Nonzero if CODE represents a function call-like expression with a +/* Nonzero if NODE represents a function call-like expression with a variable-length operand vector. */ -#define VL_EXP_CLASS_P(CODE)\ - (TREE_CODE_CLASS (TREE_CODE (CODE)) == tcc_vl_exp) +#define VL_EXP_CLASS_P(NODE)\ + (TREE_CODE_CLASS (TREE_CODE (NODE)) == tcc_vl_exp) -/* Nonzero if CODE represents any other expression. */ +/* Nonzero if NODE represents any other expression. */ -#define EXPRESSION_CLASS_P(CODE)\ - (TREE_CODE_CLASS (TREE_CODE (CODE)) == tcc_expression) +#define EXPRESSION_CLASS_P(NODE)\ + (TREE_CODE_CLASS (TREE_CODE (NODE)) == tcc_expression) -/* Returns nonzero iff CODE represents a type or declaration. */ +/* Returns nonzero iff NODE represents a type or declaration. */ -#define IS_TYPE_OR_DECL_P(CODE)\ - (TYPE_P (CODE) || DECL_P (CODE)) +#define IS_TYPE_OR_DECL_P(NODE)\ + (TYPE_P (NODE) || DECL_P (NODE)) /* Returns nonzero iff CLASS is the tree-code class of an expression. */ @@ -552,6 +552,21 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int, /* Nonzero if this type is a complete type. */ #define COMPLETE_TYPE_P(NODE) (TYPE_SIZE (NODE) != NULL_TREE) +/* Nonzero if this type is a pointer bounds type. */ +#define POINTER_BOUNDS_TYPE_P(NODE) \ + (TREE_CODE (NODE) == POINTER_BOUNDS_TYPE) + +/* Nonzero if this node has a pointer bounds type. */ +#define POINTER_BOUNDS_P(NODE) \ + (POINTER_BOUNDS_TYPE_P (TREE_TYPE (NODE))) + +/* Nonzero if this type supposes bounds existence. */ +#define BOUNDED_TYPE_P(type) (POINTER_TYPE_P (type)) + +/* Nonzero for objects with bounded type. */ +#define BOUNDED_P(node) \ + BOUNDED_TYPE_P (TREE_TYPE (node)) + /* Nonzero if this type is the (possibly qualified) void type. */ #define VOID_TYPE_P(NODE) (TREE_CODE (NODE) == VOID_TYPE) @@ -799,6 +814,9 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int, #define CALL_EXPR_RETURN_SLOT_OPT(NODE) \ (CALL_EXPR_CHECK (NODE)->base.private_flag) +/* Cilk keywords accessors. */ +#define CILK_SPAWN_FN(NODE) TREE_OPERAND (CILK_SPAWN_STMT_CHECK (NODE), 0) + /* In a RESULT_DECL, PARM_DECL and VAR_DECL, means that it is passed by invisible reference (and the TREE_TYPE is a pointer to the true type). */ @@ -3387,6 +3405,8 @@ tree_operand_check_code (const_tree __t, enum tree_code __code, int __i, #define complex_double_type_node global_trees[TI_COMPLEX_DOUBLE_TYPE] #define complex_long_double_type_node global_trees[TI_COMPLEX_LONG_DOUBLE_TYPE] +#define pointer_bounds_type_node global_trees[TI_POINTER_BOUNDS_TYPE] + #define void_type_node global_trees[TI_VOID_TYPE] /* The C type `void *'. */ #define ptr_type_node global_trees[TI_PTR_TYPE] @@ -4681,8 +4701,6 @@ extern tree build_call_expr_loc (location_t, tree, int, ...); extern tree build_call_expr (tree, int, ...); extern tree mathfn_built_in (tree, enum built_in_function fn); extern tree c_strlen (tree, int); -extern tree std_gimplify_va_arg_expr (tree, tree, gimple_seq *, gimple_seq *); -extern tree build_va_arg_indirect_ref (tree); extern tree build_string_literal (int, const char *); extern bool validate_arglist (const_tree, ...); extern rtx builtin_memset_read_str (void *, HOST_WIDE_INT, enum machine_mode); @@ -4719,6 +4737,7 @@ extern void get_type_static_bounds (const_tree, mpz_t, mpz_t); extern bool variably_modified_type_p (tree, tree); extern int tree_log2 (const_tree); extern int tree_floor_log2 (const_tree); +extern unsigned int tree_ctz (const_tree); extern int simple_cst_equal (const_tree, const_tree); extern hashval_t iterative_hash_expr (const_tree, hashval_t); extern hashval_t iterative_hash_exprs_commutative (const_tree, diff --git a/gcc/tsan.c b/gcc/tsan.c index 6ddacfe3c94..d273f168cef 100644 --- a/gcc/tsan.c +++ b/gcc/tsan.c @@ -28,14 +28,16 @@ along with GCC; see the file COPYING3. If not see #include "basic-block.h" #include "gimple.h" #include "function.h" -#include "tree-ssa.h" +#include "gimple-ssa.h" +#include "cgraph.h" +#include "tree-cfg.h" +#include "tree-ssanames.h" #include "tree-pass.h" #include "tree-iterator.h" #include "langhooks.h" #include "output.h" #include "options.h" #include "target.h" -#include "cgraph.h" #include "diagnostic.h" #include "tree-ssa-propagate.h" #include "tsan.h" diff --git a/gcc/value-prof.c b/gcc/value-prof.c index 29f51e7457a..71766093367 100644 --- a/gcc/value-prof.c +++ b/gcc/value-prof.c @@ -21,6 +21,7 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "tm.h" +#include "tree.h" #include "rtl.h" #include "expr.h" #include "hard-reg-set.h" @@ -32,13 +33,17 @@ along with GCC; see the file COPYING3. If not see #include "optabs.h" #include "regs.h" #include "ggc.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-cfg.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" #include "diagnostic.h" #include "gimple-pretty-print.h" #include "coverage.h" #include "tree.h" #include "gcov-io.h" -#include "cgraph.h" #include "timevar.h" #include "dumpfile.h" #include "pointer-set.h" @@ -1211,9 +1216,9 @@ init_node_map (bool local) " with nodes %s/%i %s/%i\n", n->profile_id, cgraph_node_name (n), - n->symbol.order, - symtab_node_name (*(symtab_node*)val), - (*(symtab_node *)val)->symbol.order); + n->order, + symtab_node_name (*(symtab_node **)val), + (*(symtab_node **)val)->order); n->profile_id = (n->profile_id + 1) & 0x7fffffff; } } @@ -1224,7 +1229,7 @@ init_node_map (bool local) "Node %s/%i has no profile-id" " (profile feedback missing?)\n", cgraph_node_name (n), - n->symbol.order); + n->order); continue; } else if ((val = pointer_map_contains (cgraph_node_map, @@ -1235,7 +1240,7 @@ init_node_map (bool local) "Node %s/%i has IP profile-id %i conflict. " "Giving up.\n", cgraph_node_name (n), - n->symbol.order, + n->order, n->profile_id); *val = NULL; continue; @@ -1276,7 +1281,7 @@ static bool check_ic_target (gimple call_stmt, struct cgraph_node *target) { location_t locus; - if (gimple_check_call_matching_types (call_stmt, target->symbol.decl, true)) + if (gimple_check_call_matching_types (call_stmt, target->decl, true)) return true; locus = gimple_location (call_stmt); @@ -1319,7 +1324,7 @@ gimple_ic (gimple icall_stmt, struct cgraph_node *direct_call, load_stmt = gimple_build_assign (tmp0, tmp); gsi_insert_before (&gsi, load_stmt, GSI_SAME_STMT); - tmp = fold_convert (optype, build_addr (direct_call->symbol.decl, + tmp = fold_convert (optype, build_addr (direct_call->decl, current_function_decl)); load_stmt = gimple_build_assign (tmp1, tmp); gsi_insert_before (&gsi, load_stmt, GSI_SAME_STMT); @@ -1331,8 +1336,8 @@ gimple_ic (gimple icall_stmt, struct cgraph_node *direct_call, gimple_set_vuse (icall_stmt, NULL_TREE); update_stmt (icall_stmt); dcall_stmt = gimple_copy (icall_stmt); - gimple_call_set_fndecl (dcall_stmt, direct_call->symbol.decl); - dflags = flags_from_decl_or_type (direct_call->symbol.decl); + gimple_call_set_fndecl (dcall_stmt, direct_call->decl); + dflags = flags_from_decl_or_type (direct_call->decl); if ((dflags & ECF_NORETURN) != 0) gimple_call_set_lhs (dcall_stmt, NULL_TREE); gsi_insert_before (&gsi, dcall_stmt, GSI_SAME_STMT); @@ -1497,7 +1502,7 @@ gimple_ic_transform (gimple_stmt_iterator *gsi) fprintf (dump_file, "Indirect call -> direct call "); print_generic_expr (dump_file, gimple_call_fn (stmt), TDF_SLIM); fprintf (dump_file, "=> "); - print_generic_expr (dump_file, direct_call->symbol.decl, TDF_SLIM); + print_generic_expr (dump_file, direct_call->decl, TDF_SLIM); fprintf (dump_file, " transformation skipped because of type mismatch"); print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM); } @@ -1510,7 +1515,7 @@ gimple_ic_transform (gimple_stmt_iterator *gsi) fprintf (dump_file, "Indirect call -> direct call "); print_generic_expr (dump_file, gimple_call_fn (stmt), TDF_SLIM); fprintf (dump_file, "=> "); - print_generic_expr (dump_file, direct_call->symbol.decl, TDF_SLIM); + print_generic_expr (dump_file, direct_call->decl, TDF_SLIM); fprintf (dump_file, " transformation on insn postponned to ipa-profile"); print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM); fprintf (dump_file, "hist->count "HOST_WIDEST_INT_PRINT_DEC diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c index 89c53efc95a..eb3f7ce3a7d 100644 --- a/gcc/var-tracking.c +++ b/gcc/var-tracking.c @@ -104,6 +104,8 @@ #include "regs.h" #include "expr.h" #include "tree-pass.h" +#include "bitmap.h" +#include "tree-dfa.h" #include "tree-ssa.h" #include "cselib.h" #include "target.h" @@ -7922,7 +7924,7 @@ struct expand_loc_callback_data /* Stack of values and debug_exprs under expansion, and their children. */ - vec<rtx, va_stack> expanding; + stack_vec<rtx, 4> expanding; /* Stack of values and debug_exprs whose expansion hit recursion cycles. They will have VALUE_RECURSED_INTO marked when added to @@ -7930,7 +7932,7 @@ struct expand_loc_callback_data resolves to a valid location. So, if the flag remains set at the end of the search, we know no valid location for this one can possibly exist. */ - vec<rtx, va_stack> pending; + stack_vec<rtx, 4> pending; /* The maximum depth among the sub-expressions under expansion. Zero indicates no expansion so far. */ @@ -8432,11 +8434,11 @@ vt_expand_loc_callback (rtx x, bitmap regs, This function performs this finalization of NULL locations. */ static void -resolve_expansions_pending_recursion (vec<rtx, va_stack> pending) +resolve_expansions_pending_recursion (vec<rtx, va_heap> *pending) { - while (!pending.is_empty ()) + while (!pending->is_empty ()) { - rtx x = pending.pop (); + rtx x = pending->pop (); decl_or_value dv; if (!VALUE_RECURSED_INTO (x)) @@ -8456,8 +8458,6 @@ resolve_expansions_pending_recursion (vec<rtx, va_stack> pending) do \ { \ (d).vars = (v); \ - vec_stack_alloc (rtx, (d).expanding, 4); \ - vec_stack_alloc (rtx, (d).pending, 4); \ (d).depth.complexity = (d).depth.entryvals = 0; \ } \ while (0) @@ -8465,7 +8465,7 @@ resolve_expansions_pending_recursion (vec<rtx, va_stack> pending) #define FINI_ELCD(d, l) \ do \ { \ - resolve_expansions_pending_recursion ((d).pending); \ + resolve_expansions_pending_recursion (&(d).pending); \ (d).pending.release (); \ (d).expanding.release (); \ \ @@ -8759,7 +8759,7 @@ emit_note_insn_var_location (variable_def **varp, emit_note_data *data) int var_track_values_to_stack (variable_def **slot, - vec<rtx, va_stack> *changed_values_stack) + vec<rtx, va_heap> *changed_values_stack) { variable var = *slot; @@ -8794,7 +8794,7 @@ remove_value_from_changed_variables (rtx val) static void notify_dependents_of_changed_value (rtx val, variable_table_type htab, - vec<rtx, va_stack> *changed_values_stack) + vec<rtx, va_heap> *changed_values_stack) { variable_def **slot; variable var; @@ -8879,13 +8879,11 @@ process_changed_values (variable_table_type htab) { int i, n; rtx val; - vec<rtx, va_stack> changed_values_stack; - - vec_stack_alloc (rtx, changed_values_stack, 20); + stack_vec<rtx, 20> changed_values_stack; /* Move values from changed_variables to changed_values_stack. */ changed_variables - .traverse <vec<rtx, va_stack>*, var_track_values_to_stack> + .traverse <vec<rtx, va_heap>*, var_track_values_to_stack> (&changed_values_stack); /* Back-propagate change notifications in values while popping @@ -8906,8 +8904,6 @@ process_changed_values (variable_table_type htab) n--; } } - - changed_values_stack.release (); } /* Emit NOTE_INSN_VAR_LOCATION note for each variable from a chain diff --git a/gcc/varasm.c b/gcc/varasm.c index 2ad6b4488ab..1f772c7a398 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -46,7 +46,6 @@ along with GCC; see the file COPYING3. If not see #include "target.h" #include "common/common-target.h" #include "targhooks.h" -#include "tree-mudflap.h" #include "cgraph.h" #include "pointer-set.h" #include "asan.h" @@ -1247,10 +1246,6 @@ make_decl_rtl (tree decl) && SYMBOL_REF_HAS_BLOCK_INFO_P (XEXP (x, 0))) change_symbol_block (XEXP (x, 0), get_block_for_decl (decl)); - /* Make this function static known to the mudflap runtime. */ - if (flag_mudflap && TREE_CODE (decl) == VAR_DECL) - mudflap_enqueue_decl (decl); - return; } @@ -1387,10 +1382,6 @@ make_decl_rtl (tree decl) If the name is changed, the macro ASM_OUTPUT_LABELREF will have to know how to strip this information. */ targetm.encode_section_info (decl, DECL_RTL (decl), true); - - /* Make this function static known to the mudflap runtime. */ - if (flag_mudflap && TREE_CODE (decl) == VAR_DECL) - mudflap_enqueue_decl (decl); } /* Like make_decl_rtl, but inhibit creation of new alias sets when @@ -1400,7 +1391,7 @@ make_decl_rtl (tree decl) rtx make_decl_rtl_for_debug (tree decl) { - unsigned int save_aliasing_flag, save_mudflap_flag; + unsigned int save_aliasing_flag; rtx rtl; if (DECL_RTL_SET_P (decl)) @@ -1411,12 +1402,9 @@ make_decl_rtl_for_debug (tree decl) we do not want to create alias sets that will throw the alias numbers off in the comparison dumps. So... clearing flag_strict_aliasing will keep new_alias_set() from creating a - new set. It is undesirable to register decl with mudflap - in this case as well. */ + new set. */ save_aliasing_flag = flag_strict_aliasing; flag_strict_aliasing = 0; - save_mudflap_flag = flag_mudflap; - flag_mudflap = 0; rtl = DECL_RTL (decl); /* Reset DECL_RTL back, as various parts of the compiler expects @@ -1424,8 +1412,6 @@ make_decl_rtl_for_debug (tree decl) SET_DECL_RTL (decl, NULL); flag_strict_aliasing = save_aliasing_flag; - flag_mudflap = save_mudflap_flag; - return rtl; } @@ -2371,7 +2357,7 @@ mark_decl_referenced (tree decl) definition. */ struct cgraph_node *node = cgraph_get_create_node (decl); if (!DECL_EXTERNAL (decl) - && !node->symbol.definition) + && !node->definition) cgraph_mark_force_output_node (node); } else if (TREE_CODE (decl) == VAR_DECL) @@ -2379,7 +2365,7 @@ mark_decl_referenced (tree decl) struct varpool_node *node = varpool_node_for_decl (decl); /* C++ frontend use mark_decl_references to force COMDAT variables to be output that might appear dead otherwise. */ - node->symbol.force_output = true; + node->force_output = true; } /* else do nothing - we can get various sorts of CST nodes here, which do not need to be marked. */ @@ -3206,10 +3192,6 @@ build_constant_desc (tree exp) desc = ggc_alloc_constant_descriptor_tree (); desc->value = copy_constant (exp); - /* Propagate marked-ness to copied constant. */ - if (flag_mudflap && mf_marked_p (exp)) - mf_mark (desc->value); - /* Create a string containing the label name, in LABEL. */ labelno = const_labelno++; ASM_GENERATE_INTERNAL_LABEL (label, "LC", labelno); @@ -3405,8 +3387,6 @@ output_constant_def_contents (rtx symbol) assemble_zeros (asan_red_zone_size (size)); } } - if (flag_mudflap) - mudflap_enqueue_constant (exp); } /* Look up EXP in the table of constant descriptors. Return the rtl @@ -4712,6 +4692,7 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align) case REFERENCE_TYPE: case OFFSET_TYPE: case FIXED_POINT_TYPE: + case POINTER_BOUNDS_TYPE: if (! assemble_integer (expand_expr (exp, NULL_RTX, VOIDmode, EXPAND_INITIALIZER), MIN (size, thissize), align, 0)) @@ -5392,9 +5373,9 @@ weak_finish_1 (tree decl) static tree find_decl (tree target) { - symtab_node node = symtab_node_for_asm (target); + symtab_node *node = symtab_node_for_asm (target); if (node) - return node->symbol.decl; + return node->decl; return NULL_TREE; } @@ -5679,9 +5660,9 @@ assemble_alias (tree decl, tree target) /* Allow aliases to aliases. */ if (TREE_CODE (decl) == FUNCTION_DECL) - cgraph_get_create_node (decl)->symbol.alias = true; + cgraph_get_create_node (decl)->alias = true; else - varpool_node_for_decl (decl)->symbol.alias = true; + varpool_node_for_decl (decl)->alias = true; /* If the target has already been emitted, we don't have to queue the alias. This saves a tad of memory. */ @@ -5784,12 +5765,12 @@ dump_tm_clone_pairs (vec<tm_alias_pair> tm_alias_pairs) TM_GETTMCLONE. If neither of these are true, we didn't generate a clone, and we didn't call it indirectly... no sense keeping it in the clone table. */ - if (!dst_n || !dst_n->symbol.definition) + if (!dst_n || !dst_n->definition) continue; /* This covers the case where we have optimized the original function away, and only access the transactional clone. */ - if (!src_n || !src_n->symbol.definition) + if (!src_n || !src_n->definition) continue; if (!switched) @@ -6284,9 +6265,8 @@ categorize_decl_for_section (const_tree decl, int reloc) return SECCAT_TEXT; else if (TREE_CODE (decl) == STRING_CST) { - if (flag_mudflap - || ((flag_sanitize & SANITIZE_ADDRESS) - && asan_protect_global (CONST_CAST_TREE (decl)))) + if ((flag_sanitize & SANITIZE_ADDRESS) + && asan_protect_global (CONST_CAST_TREE (decl))) /* or !flag_merge_constants */ return SECCAT_RODATA; else @@ -6311,7 +6291,7 @@ categorize_decl_for_section (const_tree decl, int reloc) } else if (reloc & targetm.asm_out.reloc_rw_mask ()) ret = reloc == 1 ? SECCAT_DATA_REL_RO_LOCAL : SECCAT_DATA_REL_RO; - else if (reloc || flag_merge_constants < 2 || flag_mudflap + else if (reloc || flag_merge_constants < 2 || ((flag_sanitize & SANITIZE_ADDRESS) && asan_protect_global (CONST_CAST_TREE (decl)))) /* C and C++ don't allow different variables to share the same @@ -6735,20 +6715,20 @@ default_binds_local_p_1 (const_tree exp, int shlib) && (TREE_STATIC (exp) || DECL_EXTERNAL (exp))) { struct varpool_node *vnode = varpool_get_node (exp); - if (vnode && resolution_local_p (vnode->symbol.resolution)) + if (vnode && resolution_local_p (vnode->resolution)) resolved_locally = true; if (vnode - && resolution_to_local_definition_p (vnode->symbol.resolution)) + && resolution_to_local_definition_p (vnode->resolution)) resolved_to_local_def = true; } else if (TREE_CODE (exp) == FUNCTION_DECL && TREE_PUBLIC (exp)) { struct cgraph_node *node = cgraph_get_node (exp); if (node - && resolution_local_p (node->symbol.resolution)) + && resolution_local_p (node->resolution)) resolved_locally = true; if (node - && resolution_to_local_definition_p (node->symbol.resolution)) + && resolution_to_local_definition_p (node->resolution)) resolved_to_local_def = true; } @@ -6829,15 +6809,15 @@ decl_binds_to_current_def_p (tree decl) { struct varpool_node *vnode = varpool_get_node (decl); if (vnode - && vnode->symbol.resolution != LDPR_UNKNOWN) - return resolution_to_local_definition_p (vnode->symbol.resolution); + && vnode->resolution != LDPR_UNKNOWN) + return resolution_to_local_definition_p (vnode->resolution); } else if (TREE_CODE (decl) == FUNCTION_DECL) { struct cgraph_node *node = cgraph_get_node (decl); if (node - && node->symbol.resolution != LDPR_UNKNOWN) - return resolution_to_local_definition_p (node->symbol.resolution); + && node->resolution != LDPR_UNKNOWN) + return resolution_to_local_definition_p (node->resolution); } /* Otherwise we have to assume the worst for DECL_WEAK (hidden weaks binds locally but still can be overwritten), DECL_COMMON (can be merged diff --git a/gcc/varpool.c b/gcc/varpool.c index d5324adb52b..4f1658ea635 100644 --- a/gcc/varpool.c +++ b/gcc/varpool.c @@ -33,7 +33,6 @@ along with GCC; see the file COPYING3. If not see #include "target.h" #include "output.h" #include "gimple.h" -#include "tree-ssa.h" #include "flags.h" /* List of hooks triggered on varpool_node events. */ @@ -136,7 +135,7 @@ struct varpool_node * varpool_create_empty_node (void) { struct varpool_node *node = ggc_alloc_cleared_varpool_node (); - node->symbol.type = SYMTAB_VARIABLE; + node->type = SYMTAB_VARIABLE; return node; } @@ -150,8 +149,8 @@ varpool_node_for_decl (tree decl) return node; node = varpool_create_empty_node (); - node->symbol.decl = decl; - symtab_register_node ((symtab_node)node); + node->decl = decl; + symtab_register_node (node); return node; } @@ -161,15 +160,15 @@ varpool_remove_node (struct varpool_node *node) { tree init; varpool_call_node_removal_hooks (node); - symtab_unregister_node ((symtab_node)node); + symtab_unregister_node (node); /* Because we remove references from external functions before final compilation, we may end up removing useful constructors. FIXME: We probably want to trace boundaries better. */ - if ((init = ctor_for_folding (node->symbol.decl)) == error_mark_node) + if ((init = ctor_for_folding (node->decl)) == error_mark_node) varpool_remove_initializer (node); else - DECL_INITIAL (node->symbol.decl) = init; + DECL_INITIAL (node->decl) = init; ggc_free (node); } @@ -177,10 +176,10 @@ varpool_remove_node (struct varpool_node *node) void varpool_remove_initializer (struct varpool_node *node) { - if (DECL_INITIAL (node->symbol.decl) - && !DECL_IN_CONSTANT_POOL (node->symbol.decl) + if (DECL_INITIAL (node->decl) + && !DECL_IN_CONSTANT_POOL (node->decl) /* Keep vtables for BINFO folding. */ - && !DECL_VIRTUAL_P (node->symbol.decl) + && !DECL_VIRTUAL_P (node->decl) /* FIXME: http://gcc.gnu.org/PR55395 */ && debug_info_level == DINFO_LEVEL_NONE /* When doing declaration merging we have duplicate @@ -188,26 +187,26 @@ varpool_remove_initializer (struct varpool_node *node) the boides, or we will end up remiving wrong one. */ && cgraph_state != CGRAPH_LTO_STREAMING) - DECL_INITIAL (node->symbol.decl) = error_mark_node; + DECL_INITIAL (node->decl) = error_mark_node; } /* Dump given cgraph node. */ void dump_varpool_node (FILE *f, struct varpool_node *node) { - dump_symtab_base (f, (symtab_node)node); + dump_symtab_base (f, node); fprintf (f, " Availability: %s\n", cgraph_function_flags_ready ? cgraph_availability_names[cgraph_variable_initializer_availability (node)] : "not-ready"); fprintf (f, " Varpool flags:"); - if (DECL_INITIAL (node->symbol.decl)) + if (DECL_INITIAL (node->decl)) fprintf (f, " initialized"); if (node->output) fprintf (f, " output"); - if (TREE_READONLY (node->symbol.decl)) + if (TREE_READONLY (node->decl)) fprintf (f, " read-only"); - if (ctor_for_folding (node->symbol.decl) != error_mark_node) + if (ctor_for_folding (node->decl) != error_mark_node) fprintf (f, " const-value-known"); fprintf (f, "\n"); } @@ -235,7 +234,7 @@ debug_varpool (void) struct varpool_node * varpool_node_for_asm (tree asmname) { - if (symtab_node node = symtab_node_for_asm (asmname)) + if (symtab_node *node = symtab_node_for_asm (asmname)) return dyn_cast <varpool_node> (node); else return NULL; @@ -276,7 +275,7 @@ ctor_for_folding (tree decl) if (node) { real_node = varpool_variable_node (node); - real_decl = real_node->symbol.decl; + real_decl = real_node->decl; } else real_decl = decl; @@ -293,7 +292,7 @@ ctor_for_folding (tree decl) if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))) { node = varpool_alias_target (node); - decl = node->symbol.decl; + decl = node->decl; } } @@ -343,7 +342,7 @@ varpool_add_new_variable (tree decl) node = varpool_node_for_decl (decl); varpool_call_variable_insertion_hooks (node); if (varpool_externally_visible_p (node)) - node->symbol.externally_visible = true; + node->externally_visible = true; } /* Return variable availability. See cgraph.h for description of individual @@ -352,14 +351,14 @@ enum availability cgraph_variable_initializer_availability (struct varpool_node *node) { gcc_assert (cgraph_function_flags_ready); - if (!node->symbol.definition) + if (!node->definition) return AVAIL_NOT_AVAILABLE; - if (!TREE_PUBLIC (node->symbol.decl)) + if (!TREE_PUBLIC (node->decl)) return AVAIL_AVAILABLE; - if (DECL_IN_CONSTANT_POOL (node->symbol.decl) - || DECL_VIRTUAL_P (node->symbol.decl)) + if (DECL_IN_CONSTANT_POOL (node->decl) + || DECL_VIRTUAL_P (node->decl)) return AVAIL_AVAILABLE; - if (node->symbol.alias && node->symbol.weakref) + if (node->alias && node->weakref) { enum availability avail; @@ -370,8 +369,8 @@ cgraph_variable_initializer_availability (struct varpool_node *node) /* If the variable can be overwritten, return OVERWRITABLE. Takes care of at least one notable extension - the COMDAT variables used to share template instantiations in C++. */ - if (decl_replaceable_p (node->symbol.decl) - || DECL_EXTERNAL (node->symbol.decl)) + if (decl_replaceable_p (node->decl) + || DECL_EXTERNAL (node->decl)) return AVAIL_OVERWRITABLE; return AVAIL_AVAILABLE; } @@ -379,24 +378,24 @@ cgraph_variable_initializer_availability (struct varpool_node *node) void varpool_analyze_node (struct varpool_node *node) { - tree decl = node->symbol.decl; + tree decl = node->decl; /* When reading back varpool at LTO time, we re-construct the queue in order to have "needed" list right by inserting all needed nodes into varpool. We however don't want to re-analyze already analyzed nodes. */ - if (!node->symbol.analyzed) + if (!node->analyzed) { gcc_assert (!in_lto_p || cgraph_function_flags_ready); /* Compute the alignment early so function body expanders are already informed about increased alignment. */ align_variable (decl, 0); } - if (node->symbol.alias) + if (node->alias) symtab_resolve_alias - ((symtab_node) node, (symtab_node) varpool_get_node (node->symbol.alias_target)); + (node, varpool_get_node (node->alias_target)); else if (DECL_INITIAL (decl)) - record_references_in_initializer (decl, node->symbol.analyzed); - node->symbol.analyzed = true; + record_references_in_initializer (decl, node->analyzed); + node->analyzed = true; } /* Assemble thunks and aliases associated to NODE. */ @@ -406,12 +405,12 @@ assemble_aliases (struct varpool_node *node) { int i; struct ipa_ref *ref; - for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list, i, ref); i++) + for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list, i, ref); i++) if (ref->use == IPA_REF_ALIAS) { struct varpool_node *alias = ipa_ref_referring_varpool_node (ref); - do_assemble_alias (alias->symbol.decl, - DECL_ASSEMBLER_NAME (node->symbol.decl)); + do_assemble_alias (alias->decl, + DECL_ASSEMBLER_NAME (node->decl)); assemble_aliases (alias); } } @@ -421,11 +420,11 @@ assemble_aliases (struct varpool_node *node) bool varpool_assemble_decl (struct varpool_node *node) { - tree decl = node->symbol.decl; + tree decl = node->decl; /* Aliases are outout when their target is produced or by output_weakrefs. */ - if (node->symbol.alias) + if (node->alias) return false; /* Constant pool is output from RTL land when the reference @@ -449,12 +448,12 @@ varpool_assemble_decl (struct varpool_node *node) && TREE_CODE (decl) == VAR_DECL && !DECL_HAS_VALUE_EXPR_P (decl)); - if (!node->symbol.in_other_partition + if (!node->in_other_partition && !DECL_EXTERNAL (decl)) { assemble_variable (decl, 0, 1, 0); gcc_assert (TREE_ASM_WRITTEN (decl)); - node->symbol.definition = true; + node->definition = true; assemble_aliases (node); return true; } @@ -468,10 +467,10 @@ varpool_assemble_decl (struct varpool_node *node) static void enqueue_node (struct varpool_node *node, struct varpool_node **first) { - if (node->symbol.aux) + if (node->aux) return; gcc_checking_assert (*first); - node->symbol.aux = *first; + node->aux = *first; *first = node; } @@ -495,11 +494,11 @@ varpool_remove_unreferenced_decls (void) fprintf (cgraph_dump_file, "Trivially needed variables:"); FOR_EACH_DEFINED_VARIABLE (node) { - if (node->symbol.analyzed + if (node->analyzed && (!varpool_can_remove_if_no_refs (node) /* We just expanded all function bodies. See if any of them needed the variable. */ - || DECL_RTL_SET_P (node->symbol.decl))) + || DECL_RTL_SET_P (node->decl))) { enqueue_node (node, &first); if (cgraph_dump_file) @@ -509,27 +508,27 @@ varpool_remove_unreferenced_decls (void) while (first != (struct varpool_node *)(void *)1) { node = first; - first = (struct varpool_node *)first->symbol.aux; + first = (struct varpool_node *)first->aux; - if (node->symbol.same_comdat_group) + if (node->same_comdat_group) { - symtab_node next; - for (next = node->symbol.same_comdat_group; - next != (symtab_node)node; - next = next->symbol.same_comdat_group) + symtab_node *next; + for (next = node->same_comdat_group; + next != node; + next = next->same_comdat_group) { varpool_node *vnext = dyn_cast <varpool_node> (next); - if (vnext && vnext->symbol.analyzed) + if (vnext && vnext->analyzed) enqueue_node (vnext, &first); } } - for (i = 0; ipa_ref_list_reference_iterate (&node->symbol.ref_list, i, ref); i++) + for (i = 0; ipa_ref_list_reference_iterate (&node->ref_list, i, ref); i++) { varpool_node *vnode = dyn_cast <varpool_node> (ref->referred); if (vnode - && (!DECL_EXTERNAL (ref->referred->symbol.decl) - || vnode->symbol.alias) - && vnode->symbol.analyzed) + && (!DECL_EXTERNAL (ref->referred->decl) + || vnode->alias) + && vnode->analyzed) enqueue_node (vnode, &first); } } @@ -538,7 +537,7 @@ varpool_remove_unreferenced_decls (void) for (node = varpool_first_defined_variable (); node; node = next) { next = varpool_next_defined_variable (node); - if (!node->symbol.aux) + if (!node->aux) { if (cgraph_dump_file) fprintf (cgraph_dump_file, " %s", varpool_node_asm_name (node)); @@ -556,14 +555,14 @@ varpool_remove_unreferenced_decls (void) void varpool_finalize_named_section_flags (struct varpool_node *node) { - if (!TREE_ASM_WRITTEN (node->symbol.decl) - && !node->symbol.alias - && !node->symbol.in_other_partition - && !DECL_EXTERNAL (node->symbol.decl) - && TREE_CODE (node->symbol.decl) == VAR_DECL - && !DECL_HAS_VALUE_EXPR_P (node->symbol.decl) - && DECL_SECTION_NAME (node->symbol.decl)) - get_variable_section (node->symbol.decl, false); + if (!TREE_ASM_WRITTEN (node->decl) + && !node->alias + && !node->in_other_partition + && !DECL_EXTERNAL (node->decl) + && TREE_CODE (node->decl) == VAR_DECL + && !DECL_HAS_VALUE_EXPR_P (node->decl) + && DECL_SECTION_NAME (node->decl)) + get_variable_section (node->decl, false); } /* Output all variables enqueued to be assembled. */ @@ -608,7 +607,7 @@ add_new_static_var (tree type) new_node = varpool_node_for_decl (new_decl); varpool_finalize_decl (new_decl); - return new_node->symbol.decl; + return new_node->decl; } /* Attempt to mark ALIAS as an alias to DECL. Return TRUE if successful. @@ -622,11 +621,11 @@ varpool_create_variable_alias (tree alias, tree decl) gcc_assert (TREE_CODE (decl) == VAR_DECL); gcc_assert (TREE_CODE (alias) == VAR_DECL); alias_node = varpool_node_for_decl (alias); - alias_node->symbol.alias = true; - alias_node->symbol.definition = true; - alias_node->symbol.alias_target = decl; + alias_node->alias = true; + alias_node->definition = true; + alias_node->alias_target = decl; if (lookup_attribute ("weakref", DECL_ATTRIBUTES (alias)) != NULL) - alias_node->symbol.weakref = true; + alias_node->weakref = true; return alias_node; } @@ -643,15 +642,15 @@ varpool_extra_name_alias (tree alias, tree decl) return NULL; #endif alias_node = varpool_create_variable_alias (alias, decl); - alias_node->symbol.cpp_implicit_alias = true; + alias_node->cpp_implicit_alias = true; /* Extra name alias mechanizm creates aliases really late via DECL_ASSEMBLER_NAME mechanizm. This is unfortunate because they are not going through the standard channels. Ensure they get output. */ if (cpp_implicit_aliases_done) - symtab_resolve_alias ((symtab_node)alias_node, - (symtab_node)varpool_node_for_decl (decl)); + symtab_resolve_alias (alias_node, + varpool_node_for_decl (decl)); return alias_node; } @@ -670,7 +669,7 @@ varpool_for_node_and_aliases (struct varpool_node *node, if (callback (node, data)) return true; - for (i = 0; ipa_ref_list_referring_iterate (&node->symbol.ref_list, i, ref); i++) + for (i = 0; ipa_ref_list_referring_iterate (&node->ref_list, i, ref); i++) if (ref->use == IPA_REF_ALIAS) { struct varpool_node *alias = ipa_ref_referring_varpool_node (ref); diff --git a/gcc/vec.c b/gcc/vec.c index 1303d531c0f..f3c331507d5 100644 --- a/gcc/vec.c +++ b/gcc/vec.c @@ -217,49 +217,6 @@ vec_prefix::calculate_allocation (vec_prefix *pfx, unsigned reserve, } -/* Stack vectors are a little different. VEC_alloc turns into a call - to vec<T, A>::stack_reserve and passes in space allocated via a - call to alloca. We record that pointer so that we know that we - shouldn't free it. If the vector is resized, we resize it on the - heap. We record the pointers in a vector and search it in LIFO - order--i.e., we look for the newest stack vectors first. We don't - expect too many stack vectors at any one level, and searching from - the end should normally be efficient even if they are used in a - recursive function. */ - -static vec<void *> stack_vecs; - -/* Add a stack vector to STACK_VECS. */ - -void -register_stack_vec (void *vec) -{ - stack_vecs.safe_push (vec); -} - - -/* If VEC is registered in STACK_VECS, return its index. - Otherwise, return -1. */ - -int -stack_vec_register_index (void *vec) -{ - for (unsigned ix = stack_vecs.length (); ix > 0; --ix) - if (stack_vecs[ix - 1] == vec) - return static_cast<int> (ix - 1); - return -1; -} - - -/* Remove vector at slot IX from the list of registered stack vectors. */ - -void -unregister_stack_vec (unsigned ix) -{ - stack_vecs.unordered_remove (ix); -} - - /* Helper for qsort; sort descriptors by amount of memory consumed. */ static int diff --git a/gcc/vec.h b/gcc/vec.h index 60b77ec0ffc..f97e022f24a 100644 --- a/gcc/vec.h +++ b/gcc/vec.h @@ -101,8 +101,6 @@ along with GCC; see the file COPYING3. If not see - Heap: allocation is done using malloc/free. This is the default allocation strategy. - - Stack: allocation is done using alloca. - - GC: allocation is done using ggc_alloc/ggc_free. - GC atomic: same as GC with the exception that the elements @@ -233,9 +231,9 @@ struct vec_prefix friend struct va_gc; friend struct va_gc_atomic; friend struct va_heap; - friend struct va_stack; - unsigned m_alloc; + unsigned m_alloc : 31; + unsigned m_has_auto_buf : 1; unsigned m_num; }; @@ -255,8 +253,7 @@ struct vl_ptr { }; va_heap - Allocation uses malloc/free. va_gc - Allocation uses ggc_alloc. va_gc_atomic - Same as GC, but individual elements of the array - do not need to be marked during collection. - va_stack - Allocation uses alloca. */ + do not need to be marked during collection. */ /* Allocator type for heap vectors. */ struct va_heap @@ -401,107 +398,6 @@ struct va_gc_atomic : va_gc }; -/* Allocator type for stack vectors. */ -struct va_stack -{ - /* Use vl_ptr as the default layout for stack vectors. */ - typedef vl_ptr default_layout; - - template<typename T> - static void alloc (vec<T, va_stack, vl_ptr>&, unsigned, - vec<T, va_stack, vl_embed> *); - - template <typename T> - static void reserve (vec<T, va_stack, vl_embed> *&, unsigned, bool - CXX_MEM_STAT_INFO); - - template <typename T> - static void release (vec<T, va_stack, vl_embed> *&); -}; - -/* Helper functions to keep track of vectors allocated on the stack. */ -void register_stack_vec (void *); -int stack_vec_register_index (void *); -void unregister_stack_vec (unsigned); - -/* Allocate a vector V which uses alloca for the initial allocation. - SPACE is space allocated using alloca. NELEMS is the number of - entries allocated. */ - -template<typename T> -void -va_stack::alloc (vec<T, va_stack, vl_ptr> &v, unsigned nelems, - vec<T, va_stack, vl_embed> *space) -{ - v.m_vec = space; - register_stack_vec (static_cast<void *> (v.m_vec)); - v.m_vec->embedded_init (nelems, 0); -} - - -/* Reserve NELEMS slots for a vector initially allocated on the stack. - When this happens, we switch back to heap allocation. We remove - the vector from stack_vecs, if it is there, since we no longer need - to avoid freeing it. If EXACT is true, grow exactly, otherwise - grow exponentially. */ - -template<typename T> -void -va_stack::reserve (vec<T, va_stack, vl_embed> *&v, unsigned nelems, bool exact - MEM_STAT_DECL) -{ - int ix = stack_vec_register_index (static_cast<void *> (v)); - if (ix >= 0) - unregister_stack_vec (ix); - else - { - /* V is already on the heap. */ - va_heap::reserve (reinterpret_cast<vec<T, va_heap, vl_embed> *&> (v), - nelems, exact PASS_MEM_STAT); - return; - } - - /* Move VEC_ to the heap. */ - nelems += v->m_vecpfx.m_num; - vec<T, va_stack, vl_embed> *oldvec = v; - v = NULL; - va_heap::reserve (reinterpret_cast<vec<T, va_heap, vl_embed> *&>(v), nelems, - exact PASS_MEM_STAT); - if (v && oldvec) - { - v->m_vecpfx.m_num = oldvec->length (); - memcpy (v->m_vecdata, - oldvec->m_vecdata, - oldvec->length () * sizeof (T)); - } -} - - -/* Free a vector allocated on the stack. Don't actually free it if we - find it in the hash table. */ - -template<typename T> -void -va_stack::release (vec<T, va_stack, vl_embed> *&v) -{ - if (v == NULL) - return; - - int ix = stack_vec_register_index (static_cast<void *> (v)); - if (ix >= 0) - { - unregister_stack_vec (ix); - v = NULL; - } - else - { - /* The vector was not on the list of vectors allocated on the stack, so it - must be allocated on the heap. */ - va_heap::release (reinterpret_cast<vec<T, va_heap, vl_embed> *&> (v)); - } -} - - /* Generic vector template. Default values for A and L indicate the most commonly used strategies. @@ -597,7 +493,6 @@ public: friend struct va_gc; friend struct va_gc_atomic; friend struct va_heap; - friend struct va_stack; /* FIXME - These fields should be private, but we need to cater to compilers that have stricter notions of PODness for types. */ @@ -1112,6 +1007,7 @@ inline void vec<T, A, vl_embed>::embedded_init (unsigned alloc, unsigned num) { m_vecpfx.m_alloc = alloc; + m_vecpfx.m_has_auto_buf = 0; m_vecpfx.m_num = num; } @@ -1218,8 +1114,8 @@ gt_pch_nx (vec<T, A, vl_embed> *v, gt_pointer_operator op, void *cookie) As long as we use C++03, we cannot have constructors nor destructors in classes that are stored in unions. */ -template<typename T, typename A> -struct vec<T, A, vl_ptr> +template<typename T> +struct vec<T, va_heap, vl_ptr> { public: /* Memory allocation and deallocation for the embedded vector. @@ -1284,23 +1180,39 @@ public: void qsort (int (*) (const void *, const void *)); unsigned lower_bound (T, bool (*)(const T &, const T &)) const; - template<typename T1> - friend void va_stack::alloc (vec<T1, va_stack, vl_ptr>&, unsigned, - vec<T1, va_stack, vl_embed> *); + bool using_auto_storage () const; /* FIXME - This field should be private, but we need to cater to compilers that have stricter notions of PODness for types. */ - vec<T, A, vl_embed> *m_vec; + vec<T, va_heap, vl_embed> *m_vec; }; -/* Empty specialization for GC allocation. This will prevent GC - vectors from using the vl_ptr layout. FIXME: This is needed to - circumvent limitations in the GTY machinery. */ - -template<typename T> -struct vec<T, va_gc, vl_ptr> +/* stack_vec is a subclass of vec containing N elements of internal storage. + You probably only want to allocate this on the stack because if the array + ends up being larger or much smaller than N it will be wasting space. */ +template<typename T, size_t N> +class stack_vec : public vec<T, va_heap> { +public: + stack_vec () + { + m_header.m_alloc = N; + m_header.m_has_auto_buf = 1; + m_header.m_num = 0; + this->m_vec = reinterpret_cast<vec<T, va_heap, vl_embed> *> (&m_header); + } + + ~stack_vec () + { + this->release (); + } + +private: + friend class vec<T, va_heap, vl_ptr>; + + vec_prefix m_header; + T m_data[N]; }; @@ -1343,45 +1255,6 @@ vec_free (vec<T> *&v) } -/* Allocate a new stack vector with space for exactly NELEMS objects. - If NELEMS is zero, NO vector is created. - - For the stack allocator, no memory is really allocated. The vector - is initialized to be at address SPACE and contain NELEMS slots. - Memory allocation actually occurs in the expansion of VEC_alloc. - - Usage notes: - - * This does not allocate an instance of vec<T, A>. It allocates the - actual vector of elements (i.e., vec<T, A, vl_embed>) inside a - vec<T, A> instance. - - * This allocator must always be a macro: - - We support a vector which starts out with space on the stack and - switches to heap space when forced to reallocate. This works a - little differently. In the case of stack vectors, vec_alloc will - expand to a call to vec_alloc_1 that calls XALLOCAVAR to request - the initial allocation. This uses alloca to get the initial - space. Since alloca can not be usefully called in an inline - function, vec_alloc must always be a macro. - - Important limitations of stack vectors: - - - Only the initial allocation will be made using alloca, so pass - a reasonable estimate that doesn't use too much stack space; - don't pass zero. - - - Don't return a stack-allocated vector from the function which - allocated it. */ - -#define vec_stack_alloc(T,V,N) \ - do { \ - typedef vec<T, va_stack, vl_embed> stackv; \ - va_stack::alloc (V, N, XALLOCAVAR (stackv, stackv::embedded_size (N)));\ - } while (0) - - /* Return iteration condition and update PTR to point to the IX'th element of this vector. Use this to iterate over the elements of a vector as follows, @@ -1389,9 +1262,9 @@ vec_free (vec<T> *&v) for (ix = 0; v.iterate (ix, &ptr); ix++) continue; */ -template<typename T, typename A> +template<typename T> inline bool -vec<T, A, vl_ptr>::iterate (unsigned ix, T *ptr) const +vec<T, va_heap, vl_ptr>::iterate (unsigned ix, T *ptr) const { if (m_vec) return m_vec->iterate (ix, ptr); @@ -1412,9 +1285,9 @@ vec<T, A, vl_ptr>::iterate (unsigned ix, T *ptr) const This variant is for vectors of objects. */ -template<typename T, typename A> +template<typename T> inline bool -vec<T, A, vl_ptr>::iterate (unsigned ix, T **ptr) const +vec<T, va_heap, vl_ptr>::iterate (unsigned ix, T **ptr) const { if (m_vec) return m_vec->iterate (ix, ptr); @@ -1451,11 +1324,11 @@ vec<T, A, vl_ptr>::iterate (unsigned ix, T **ptr) const /* Return a copy of this vector. */ -template<typename T, typename A> -inline vec<T, A, vl_ptr> -vec<T, A, vl_ptr>::copy (ALONE_MEM_STAT_DECL) const +template<typename T> +inline vec<T, va_heap, vl_ptr> +vec<T, va_heap, vl_ptr>::copy (ALONE_MEM_STAT_DECL) const { - vec<T, A, vl_ptr> new_vec = vNULL; + vec<T, va_heap, vl_ptr> new_vec = vNULL; if (length ()) new_vec.m_vec = m_vec->copy (); return new_vec; @@ -1471,14 +1344,34 @@ vec<T, A, vl_ptr>::copy (ALONE_MEM_STAT_DECL) const Note that this can cause the embedded vector to be reallocated. Returns true iff reallocation actually occurred. */ -template<typename T, typename A> +template<typename T> inline bool -vec<T, A, vl_ptr>::reserve (unsigned nelems, bool exact MEM_STAT_DECL) -{ - bool extend = nelems ? !space (nelems) : false; - if (extend) - A::reserve (m_vec, nelems, exact PASS_MEM_STAT); - return extend; +vec<T, va_heap, vl_ptr>::reserve (unsigned nelems, bool exact MEM_STAT_DECL) +{ + if (!nelems || space (nelems)) + return false; + + /* For now play a game with va_heap::reserve to hide our auto storage if any, + this is necessary because it doesn't have enough information to know the + embedded vector is in auto storage, and so should not be freed. */ + vec<T, va_heap, vl_embed> *oldvec = m_vec; + unsigned int oldsize = 0; + bool handle_auto_vec = m_vec && using_auto_storage (); + if (handle_auto_vec) + { + m_vec = NULL; + oldsize = oldvec->length (); + nelems += oldsize; + } + + va_heap::reserve (m_vec, nelems, exact PASS_MEM_STAT); + if (handle_auto_vec) + { + memcpy (m_vec->address (), oldvec->address (), sizeof (T) * oldsize); + m_vec->m_vecpfx.m_num = oldsize; + } + + return true; } @@ -1487,9 +1380,9 @@ vec<T, A, vl_ptr>::reserve (unsigned nelems, bool exact MEM_STAT_DECL) embedded vector to be reallocated. Returns true iff reallocation actually occurred. */ -template<typename T, typename A> +template<typename T> inline bool -vec<T, A, vl_ptr>::reserve_exact (unsigned nelems MEM_STAT_DECL) +vec<T, va_heap, vl_ptr>::reserve_exact (unsigned nelems MEM_STAT_DECL) { return reserve (nelems, true PASS_MEM_STAT); } @@ -1500,9 +1393,9 @@ vec<T, A, vl_ptr>::reserve_exact (unsigned nelems MEM_STAT_DECL) unconditionally allocated from scratch. The old one, if it existed, is lost. */ -template<typename T, typename A> +template<typename T> inline void -vec<T, A, vl_ptr>::create (unsigned nelems MEM_STAT_DECL) +vec<T, va_heap, vl_ptr>::create (unsigned nelems MEM_STAT_DECL) { m_vec = NULL; if (nelems > 0) @@ -1512,23 +1405,30 @@ vec<T, A, vl_ptr>::create (unsigned nelems MEM_STAT_DECL) /* Free the memory occupied by the embedded vector. */ -template<typename T, typename A> +template<typename T> inline void -vec<T, A, vl_ptr>::release (void) +vec<T, va_heap, vl_ptr>::release (void) { - if (m_vec) - A::release (m_vec); -} + if (!m_vec) + return; + if (using_auto_storage ()) + { + static_cast<stack_vec<T, 1> *> (this)->m_header.m_num = 0; + return; + } + + va_heap::release (m_vec); +} /* Copy the elements from SRC to the end of this vector as if by memcpy. SRC and this vector must be allocated with the same memory allocation mechanism. This vector is assumed to have sufficient headroom available. */ -template<typename T, typename A> +template<typename T> inline void -vec<T, A, vl_ptr>::splice (vec<T, A, vl_ptr> &src) +vec<T, va_heap, vl_ptr>::splice (vec<T, va_heap, vl_ptr> &src) { if (src.m_vec) m_vec->splice (*(src.m_vec)); @@ -1540,9 +1440,10 @@ vec<T, A, vl_ptr>::splice (vec<T, A, vl_ptr> &src) If there is not enough headroom in this vector, it will be reallocated as needed. */ -template<typename T, typename A> +template<typename T> inline void -vec<T, A, vl_ptr>::safe_splice (vec<T, A, vl_ptr> &src MEM_STAT_DECL) +vec<T, va_heap, vl_ptr>::safe_splice (vec<T, va_heap, vl_ptr> &src + MEM_STAT_DECL) { if (src.length ()) { @@ -1556,9 +1457,9 @@ vec<T, A, vl_ptr>::safe_splice (vec<T, A, vl_ptr> &src MEM_STAT_DECL) sufficient space in the vector. Return a pointer to the slot where OBJ was inserted. */ -template<typename T, typename A> +template<typename T> inline T * -vec<T, A, vl_ptr>::quick_push (const T &obj) +vec<T, va_heap, vl_ptr>::quick_push (const T &obj) { return m_vec->quick_push (obj); } @@ -1568,9 +1469,9 @@ vec<T, A, vl_ptr>::quick_push (const T &obj) the embedded vector, if needed. Return a pointer to the slot where OBJ was inserted. */ -template<typename T, typename A> +template<typename T> inline T * -vec<T, A, vl_ptr>::safe_push (const T &obj MEM_STAT_DECL) +vec<T, va_heap, vl_ptr>::safe_push (const T &obj MEM_STAT_DECL) { reserve (1, false PASS_MEM_STAT); return quick_push (obj); @@ -1579,9 +1480,9 @@ vec<T, A, vl_ptr>::safe_push (const T &obj MEM_STAT_DECL) /* Pop and return the last element off the end of the vector. */ -template<typename T, typename A> +template<typename T> inline T & -vec<T, A, vl_ptr>::pop (void) +vec<T, va_heap, vl_ptr>::pop (void) { return m_vec->pop (); } @@ -1590,9 +1491,9 @@ vec<T, A, vl_ptr>::pop (void) /* Set the length of the vector to LEN. The new length must be less than or equal to the current length. This is an O(1) operation. */ -template<typename T, typename A> +template<typename T> inline void -vec<T, A, vl_ptr>::truncate (unsigned size) +vec<T, va_heap, vl_ptr>::truncate (unsigned size) { if (m_vec) m_vec->truncate (size); @@ -1605,9 +1506,9 @@ vec<T, A, vl_ptr>::truncate (unsigned size) longer than the current length. The new elements are uninitialized. Reallocate the internal vector, if needed. */ -template<typename T, typename A> +template<typename T> inline void -vec<T, A, vl_ptr>::safe_grow (unsigned len MEM_STAT_DECL) +vec<T, va_heap, vl_ptr>::safe_grow (unsigned len MEM_STAT_DECL) { unsigned oldlen = length (); gcc_checking_assert (oldlen <= len); @@ -1620,9 +1521,9 @@ vec<T, A, vl_ptr>::safe_grow (unsigned len MEM_STAT_DECL) long or longer than the current length. The new elements are initialized to zero. Reallocate the internal vector, if needed. */ -template<typename T, typename A> +template<typename T> inline void -vec<T, A, vl_ptr>::safe_grow_cleared (unsigned len MEM_STAT_DECL) +vec<T, va_heap, vl_ptr>::safe_grow_cleared (unsigned len MEM_STAT_DECL) { unsigned oldlen = length (); safe_grow (len PASS_MEM_STAT); @@ -1633,9 +1534,9 @@ vec<T, A, vl_ptr>::safe_grow_cleared (unsigned len MEM_STAT_DECL) /* Same as vec::safe_grow but without reallocation of the internal vector. If the vector cannot be extended, a runtime assertion will be triggered. */ -template<typename T, typename A> +template<typename T> inline void -vec<T, A, vl_ptr>::quick_grow (unsigned len) +vec<T, va_heap, vl_ptr>::quick_grow (unsigned len) { gcc_checking_assert (m_vec); m_vec->quick_grow (len); @@ -1646,9 +1547,9 @@ vec<T, A, vl_ptr>::quick_grow (unsigned len) internal vector. If the vector cannot be extended, a runtime assertion will be triggered. */ -template<typename T, typename A> +template<typename T> inline void -vec<T, A, vl_ptr>::quick_grow_cleared (unsigned len) +vec<T, va_heap, vl_ptr>::quick_grow_cleared (unsigned len) { gcc_checking_assert (m_vec); m_vec->quick_grow_cleared (len); @@ -1658,9 +1559,9 @@ vec<T, A, vl_ptr>::quick_grow_cleared (unsigned len) /* Insert an element, OBJ, at the IXth position of this vector. There must be sufficient space. */ -template<typename T, typename A> +template<typename T> inline void -vec<T, A, vl_ptr>::quick_insert (unsigned ix, const T &obj) +vec<T, va_heap, vl_ptr>::quick_insert (unsigned ix, const T &obj) { m_vec->quick_insert (ix, obj); } @@ -1669,9 +1570,9 @@ vec<T, A, vl_ptr>::quick_insert (unsigned ix, const T &obj) /* Insert an element, OBJ, at the IXth position of the vector. Reallocate the embedded vector, if necessary. */ -template<typename T, typename A> +template<typename T> inline void -vec<T, A, vl_ptr>::safe_insert (unsigned ix, const T &obj MEM_STAT_DECL) +vec<T, va_heap, vl_ptr>::safe_insert (unsigned ix, const T &obj MEM_STAT_DECL) { reserve (1, false PASS_MEM_STAT); quick_insert (ix, obj); @@ -1682,9 +1583,9 @@ vec<T, A, vl_ptr>::safe_insert (unsigned ix, const T &obj MEM_STAT_DECL) remaining elements is preserved. This is an O(N) operation due to a memmove. */ -template<typename T, typename A> +template<typename T> inline void -vec<T, A, vl_ptr>::ordered_remove (unsigned ix) +vec<T, va_heap, vl_ptr>::ordered_remove (unsigned ix) { m_vec->ordered_remove (ix); } @@ -1693,9 +1594,9 @@ vec<T, A, vl_ptr>::ordered_remove (unsigned ix) /* Remove an element from the IXth position of this vector. Ordering of remaining elements is destroyed. This is an O(1) operation. */ -template<typename T, typename A> +template<typename T> inline void -vec<T, A, vl_ptr>::unordered_remove (unsigned ix) +vec<T, va_heap, vl_ptr>::unordered_remove (unsigned ix) { m_vec->unordered_remove (ix); } @@ -1704,9 +1605,9 @@ vec<T, A, vl_ptr>::unordered_remove (unsigned ix) /* Remove LEN elements starting at the IXth. Ordering is retained. This is an O(N) operation due to memmove. */ -template<typename T, typename A> +template<typename T> inline void -vec<T, A, vl_ptr>::block_remove (unsigned ix, unsigned len) +vec<T, va_heap, vl_ptr>::block_remove (unsigned ix, unsigned len) { m_vec->block_remove (ix, len); } @@ -1715,9 +1616,9 @@ vec<T, A, vl_ptr>::block_remove (unsigned ix, unsigned len) /* Sort the contents of this vector with qsort. CMP is the comparison function to pass to qsort. */ -template<typename T, typename A> +template<typename T> inline void -vec<T, A, vl_ptr>::qsort (int (*cmp) (const void *, const void *)) +vec<T, va_heap, vl_ptr>::qsort (int (*cmp) (const void *, const void *)) { if (m_vec) m_vec->qsort (cmp); @@ -1729,14 +1630,27 @@ vec<T, A, vl_ptr>::qsort (int (*cmp) (const void *, const void *)) function that returns true if the first argument is strictly less than the second. */ -template<typename T, typename A> +template<typename T> inline unsigned -vec<T, A, vl_ptr>::lower_bound (T obj, bool (*lessthan)(const T &, const T &)) +vec<T, va_heap, vl_ptr>::lower_bound (T obj, + bool (*lessthan)(const T &, const T &)) const { return m_vec ? m_vec->lower_bound (obj, lessthan) : 0; } +template<typename T> +inline bool +vec<T, va_heap, vl_ptr>::using_auto_storage () const +{ + if (!m_vec->m_vecpfx.m_has_auto_buf) + return false; + + const vec_prefix *auto_header + = &static_cast<const stack_vec<T, 1> *> (this)->m_header; + return reinterpret_cast<vec_prefix *> (m_vec) == auto_header; +} + #if (GCC_VERSION >= 3000) # pragma GCC poison m_vec m_vecpfx m_vecdata #endif diff --git a/gcc/vtable-verify.c b/gcc/vtable-verify.c index d954d1f91e0..fb26978d273 100644 --- a/gcc/vtable-verify.c +++ b/gcc/vtable-verify.c @@ -138,7 +138,11 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tree.h" #include "basic-block.h" -#include "tree-ssa.h" +#include "gimple.h" +#include "gimple-ssa.h" +#include "tree-phinodes.h" +#include "ssa-iterators.h" +#include "tree-ssanames.h" #include "tree-pass.h" #include "cfgloop.h" |