diff options
author | mrs <mrs@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-01-13 19:14:33 +0000 |
---|---|---|
committer | mrs <mrs@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-01-13 19:14:33 +0000 |
commit | 0dd8cf9cc8350069e94a624959d1ad4487c46a8c (patch) | |
tree | 63472a8da3b4d5a6c33190c256b60a5710d30a18 /gcc | |
parent | fe644b69d013e77c7fc2db2a9863969d4f564561 (diff) | |
parent | 69888cc76b4873822f5e48b66f69e9d20d19fc50 (diff) |
Merge in trunk.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/wide-int@206584 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
257 files changed, 5052 insertions, 1278 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index cf4cfabeb820..01b10357fb95 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,7 +1,523 @@ -2014-01-03 Bingfeng Mei <bmei@broadcom.com> +2014-01-13 Kyrylo Tkachov <kyrylo.tkachov@arm.com> + + * config/arm/arm.h (MAX_CONDITIONAL_EXECUTE): Fix typo in description. + +2014-01-13 Eric Botcazou <ebotcazou@adacore.com> + + * builtins.c (get_object_alignment_2): Minor tweak. + * tree-ssa-loop-ivopts.c (may_be_unaligned_p): Rewrite. + +2014-01-13 Christian Bruel <christian.bruel@st.com> + + * config/sh/sh-mem.cc (sh_expand_cmpnstr): Unroll small sizes and + optimized non constant lengths. + +2014-01-13 Jakub Jelinek <jakub@redhat.com> + + PR libgomp/59194 + * omp-low.c (expand_omp_atomic_pipeline): Expand the initial + load as __atomic_load_N if possible. + +2014-01-11 David Edelsohn <dje.gcc@gmail.com> + + * config/rs6000/rs6000.c (rs6000_expand_mtfsf_builtin): Remove + target parameter. + (rs6000_expand_builtin): Adjust call. + +2014-01-11 David Edelsohn <dje.gcc@gmail.com> + + PR target/58115 + * config/rs6000/rs6000.h (SWITCHABLE_TARGET): Define. + * config/rs6000/rs6000.c: Include target-globals.h. + (rs6000_set_current_function): Instead of doing target_reinit + unconditionally, use save_target_globals_default_opts and + restore_target_globals. + + * config/rs6000/rs6000-builtin.def (mffs, mtfsf): Add builtins for + FPSCR. + * config/rs6000/rs6000.c (rs6000_expand_mtfsf_builtin): New. + (rs6000_expand_builtin): Handle mffs and mtfsf. + (rs6000_init_builtins): Define mffs and mtfsf. + * config/rs6000/rs6000.md (UNSPECV_MFFS, UNSPECV_MTFSF): New constants. + (rs6000_mffs): New pattern. + (rs6000_mtfsf): New pattern. + +2014-01-11 Bin Cheng <bin.cheng@arm.com> + + * tree-ssa-loop-ivopts.c (iv_ca_narrow): New parameter. + Start narrowing with START. Apply candidate-use pair + and check overall cost in narrowing. + (iv_ca_prune): Pass new argument. + +2014-01-10 Jeff Law <law@redhat.com> + + PR middle-end/59743 + * ree.c (combine_reaching_defs): Ensure the defining statement + occurs before the extension when optimizing extensions with + different source and destination hard registers. + +2014-01-10 Jan Hubicka <jh@suse.cz> + + PR ipa/58585 + * ipa-devirt.c (build_type_inheritance_graph): Also add types of vtables + into the type inheritance graph. + +2014-01-10 Jakub Jelinek <jakub@redhat.com> + + PR rtl-optimization/59754 + * ree.c (combine_reaching_defs): Disallow !SCALAR_INT_MODE_P + modes in the REGNO != REGNO case. + +2014-01-10 Bill Schmidt <wschmidt@linux.vnet.ibm.com> + + * config/rs6000/rs6000-builtin.def: Fix pasto for VPKSDUS. + +2014-01-10 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/59745 + * tree-predcom.c (tree_predictive_commoning_loop): Call + free_affine_expand_cache if giving up because components is NULL. + + * target-globals.c (save_target_globals): Allocate < 4KB structs using + GC in payload of target_globals struct instead of allocating them on + the heap and the larger structs separately using GC. + * target-globals.h (struct target_globals): Make regs, hard_regs, + reload, expmed, ira, ira_int and lra_fields GTY((atomic)) instead + of GTY((skip)) and change type to void *. + (reset_target_globals): Cast loads from those fields to corresponding + types. + +2014-01-10 Steve Ellcey <sellcey@mips.com> + + PR plugins/59335 + * Makefile.in (PLUGIN_HEADERS): Add gimplify.h, gimple-iterator.h, + gimple-ssa.h, fold-const.h, tree-cfg.h, tree-into-ssa.h, + tree-ssanames.h, print-tree.h, varasm.h, and context.h. + +2014-01-10 Richard Earnshaw <rearnsha@arm.com> + + PR target/59744 + * aarch64-modes.def (CC_Zmode): New flags mode. + * aarch64.c (aarch64_select_cc_mode): Only allow NEG when the condition + represents an equality. + (aarch64_get_condition_code): Handle CC_Zmode. + * aarch64.md (compare_neg<mode>): Restrict to equality operations. + +2014-01-10 Andreas Krebbel <Andreas.Krebbel@de.ibm.com> + + * config/s390/s390.c (s390_expand_tbegin): Remove jump over CC + extraction in good case. + +2014-01-10 Richard Biener <rguenther@suse.de> + + PR tree-optimization/59374 + * tree-vect-slp.c (vect_slp_analyze_bb_1): Move dependence + checking after SLP discovery. Mark stmts not participating + in any SLP instance properly. + +2014-01-10 Kyrylo Tkachov <kyrylo.tkachov@arm.com> + + * config/arm/arm.c (arm_new_rtx_costs): Use destination mode + when handling a SET rtx. + +2014-01-10 Kyrylo Tkachov <kyrylo.tkachov@arm.com> + + * config/arm/arm-cores.def (cortex-a53): Specify FL_CRC32. + (cortex-a57): Likewise. + (cortex-a57.cortex-a53): Likewise. Remove redundant flags. + +2014-01-10 Kyrylo Tkachov <kyrylo.tkachov@arm.com> + + * config/arm/arm.c (arm_init_iwmmxt_builtins): Skip + non-iwmmxt builtins. + +2014-01-10 Jan Hubicka <hubicka@ucw.cz> + + PR ipa/58252 + PR ipa/59226 + * ipa-devirt.c record_target_from_binfo): Take as argument + stack of binfos and lookup matching one for virtual inheritance. + (possible_polymorphic_call_targets_1): Update. + +2014-01-10 Huacai Chen <chenhc@lemote.com> + + * config/mips/driver-native.c (host_detect_local_cpu): Handle new + kernel strings for Loongson-2E/2F/3A. + +2014-01-10 Jakub Jelinek <jakub@redhat.com> + + PR middle-end/59670 + * tree-vect-data-refs.c (vect_analyze_data_refs): Check + is_gimple_call before calling gimple_call_internal_p. + +2014-01-09 Steve Ellcey <sellcey@mips.com> + + * Makefile.in (TREE_FLOW_H): Remove. + (TREE_SSA_H): Add file names from tree-flow.h. + * doc/tree-ssa.texi (Annotations): Remove reference to tree-flow.h + * tree.h: Remove tree-flow.h reference. + * hash-table.h: Remove tree-flow.h reference. + * tree-ssa-loop-niter.c (dump_affine_iv): Replace tree-flow.h + reference with tree-ssa-loop.h. + +2014-01-09 Bill Schmidt <wschmidt@linux.vnet.ibm.com> + + * doc/invoke.texi: Add -maltivec={be,le} options, and document + default element-order behavior for -maltivec. + * config/rs6000/rs6000.opt: Add -maltivec={be,le} options. + * config/rs6000/rs6000.c (rs6000_option_override_internal): Ensure + that -maltivec={le,be} implies -maltivec; disallow -maltivec=le + when targeting big endian, at least for now. + * config/rs6000/rs6000.h: Add #define of VECTOR_ELT_ORDER_BIG. + +2014-01-09 Jakub Jelinek <jakub@redhat.com> + + PR middle-end/47735 + * cfgexpand.c (expand_one_var): For SSA_NAMEs, if the underlying + var satisfies use_register_for_decl, just take into account type + alignment, rather than decl alignment. + + PR tree-optimization/59622 + * gimple-fold.c (gimple_fold_call): Fix a typo in message. For + __builtin_unreachable replace the OBJ_TYPE_REF call with a call to + __builtin_unreachable and add if needed a setter of the lhs SSA_NAME. + Don't devirtualize for inplace at all. For targets.length () == 1, + if the call is noreturn and cfun isn't in SSA form yet, clear lhs. + +2014-01-09 H.J. Lu <hongjiu.lu@intel.com> + + * config/i386/i386.md (cpu): Remove the unused btver1. + +2014-01-09 H.J. Lu <hongjiu.lu@intel.com> + + * gdbasan.in: Put a breakpoint on __sanitizer::Report. + +2014-01-09 Jakub Jelinek <jakub@redhat.com> + + PR target/58115 + * tree-core.h (struct target_globals): New forward declaration. + (struct tree_target_option): Add globals field. + * tree.h (TREE_TARGET_GLOBALS): Define. + (prepare_target_option_nodes_for_pch): New prototype. + * target-globals.h (struct target_globals): Define even if + !SWITCHABLE_TARGET. + * tree.c (prepare_target_option_node_for_pch, + prepare_target_option_nodes_for_pch): New functions. + * config/i386/i386.h (SWITCHABLE_TARGET): Define. + * config/i386/i386.c: Include target-globals.h. + (ix86_set_current_function): Instead of doing target_reinit + unconditionally, use save_target_globals_default_opts and + restore_target_globals. + +2014-01-09 Richard Biener <rguenther@suse.de> + + PR tree-optimization/59715 + * tree-cfg.h (split_critical_edges): Declare. + * tree-cfg.c (split_critical_edges): Export. + * tree-ssa-sink.c (execute_sink_code): Split critical edges. + +2014-01-09 Max Ostapenko <m.ostapenko@partner.samsung.com> + + * cfgexpand.c (expand_stack_vars): Optionally disable + asan stack protection. + (expand_used_vars): Likewise. + (partition_stack_vars): Likewise. + * asan.c (asan_emit_stack_protection): Optionally disable + after return stack usage. + (instrument_derefs): Optionally disable memory + access instrumentation. + (instrument_builtin_call): Likewise. + (instrument_strlen_call): Likewise. + (asan_protect_global): Optionally disable + global variables protection. + * doc/invoke.texi: Added doc for new options. + * params.def: Added new options. + * params.h: Likewise. + +2014-01-09 Jakub Jelinek <jakub@redhat.com> + + PR rtl-optimization/59724 + * ifcvt.c (cond_exec_process_if_block): Don't call + flow_find_head_matching_sequence with 0 longest_match. + * cfgcleanup.c (flow_find_head_matching_sequence): Count even + non-active insns if !stop_after. + (try_head_merge_bb): Revert 2014-01-07 changes. + +2014-01-08 Jeff Law <law@redhat.com> + + * ree.c (get_sub_rtx): New function, extracted from... + (merge_def_and_ext): Here. + (combine_reaching_defs): Use get_sub_rtx. + +2014-01-08 Eric Botcazou <ebotcazou@adacore.com> + + * cgraph.h (varpool_variable_node): Do not choke on null node. + +2014-01-08 Catherine Moore <clm@codesourcery.com> + + * config/mips/mips.md (simple_return): Attempt to use JRC for microMIPS. + * config/mips/mips.h (MIPS_CALL): Attempt to use JALS for microMIPS. + +2014-01-08 Richard Sandiford <rdsandiford@googlemail.com> + + PR rtl-optimization/59137 + * reorg.c (steal_delay_list_from_target): Call update_block for + elided insns. + (steal_delay_list_from_fallthrough, relax_delay_slots): Likewise. + +2014-01-08 Bill Schmidt <wschmidt@linux.vnet.ibm.com> + + * config/rs6000/rs6000-c.c (altivec_overloaded_builtins): Remove + two duplicate entries. + +2014-01-08 Richard Sandiford <rdsandiford@googlemail.com> + + Revert: + 2012-10-07 Richard Sandiford <rdsandiford@googlemail.com> + + * config/mips/mips.c (mips_truncated_op_cost): New function. + (mips_rtx_costs): Adjust test for BADDU. + * config/mips/mips.md (*baddu_di<mode>): Push truncates to operands. + + 2012-10-02 Richard Sandiford <rdsandiford@googlemail.com> + + * config/mips/mips.md (*baddu_si_eb, *baddu_si_el): Merge into... + (*baddu_si): ...this new pattern. + +2014-01-08 Jakub Jelinek <jakub@redhat.com> + + PR ipa/59722 + * ipa-prop.c (ipa_analyze_params_uses): Ignore uses in debug stmts. + +2014-01-08 Bernd Edlinger <bernd.edlinger@hotmail.de> + + PR middle-end/57748 + * expr.h (expand_expr_real, expand_expr_real_1): Add new parameter + inner_reference_p. + (expand_expr, expand_normal): Adjust. + * expr.c (expand_expr_real, expand_expr_real_1): Add new parameter + inner_reference_p. Use inner_reference_p to expand inner references. + (store_expr): Adjust. + * cfgexpand.c (expand_call_stmt): Adjust. + +2014-01-08 Rong Xu <xur@google.com> + + * gcov-io.c (gcov_var): Move from gcov-io.h. + (gcov_position): Ditto. + (gcov_is_error): Ditto. + (gcov_rewrite): Ditto. + * gcov-io.h: Refactor. Move gcov_var to gcov-io.h, and libgcov + only part to libgcc/libgcov.h. + +2014-01-08 Marek Polacek <polacek@redhat.com> + + PR middle-end/59669 + * omp-low.c (simd_clone_adjust): Don't crash if def is NULL. + +2014-01-08 Marek Polacek <polacek@redhat.com> + + PR sanitizer/59667 + * ubsan.c (ubsan_type_descriptor): Call strip_array_types on type2. + +2014-01-08 Jakub Jelinek <jakub@redhat.com> + + PR rtl-optimization/59649 + * stor-layout.c (get_mode_bounds): For BImode return + 0 and STORE_FLAG_VALUE. + +2014-01-08 Richard Biener <rguenther@suse.de> + + PR middle-end/59630 + * gimple.h (is_gimple_builtin_call): Remove. + (gimple_builtin_call_types_compatible_p): New. + (gimple_call_builtin_p): New overload. + * gimple.c (is_gimple_builtin_call): Remove. + (validate_call): Rename to ... + (gimple_builtin_call_types_compatible_p): ... this and export. Also + check return types. + (validate_type): New static function. + (gimple_call_builtin_p): New overload and adjust. + * gimple-fold.c (gimple_fold_builtin): Fold the return value. + (gimple_fold_call): Likewise. Use gimple_call_builtin_p. + (gimple_fold_stmt_to_constant_1): Likewise. + * tsan.c (instrument_gimple): Use gimple_call_builtin_p. + +2014-01-08 Richard Biener <rguenther@suse.de> + + PR middle-end/59471 + * gimplify.c (gimplify_expr): Gimplify register-register type + VIEW_CONVERT_EXPRs to separate stmts. + +2014-01-07 Jeff Law <law@redhat.com> + + PR middle-end/53623 + * ree.c (combine_set_extension): Handle case where source + and destination registers in an extension insn are different. + (combine_reaching_defs): Allow source and destination + registers in extension to be different under limited + circumstances. + (add_removable_extension): Remove restriction that the + source and destination registers in the extension are the + same. + (find_and_remove_re): Emit a copy from the extension's + destination to its source after the defining insn if + the source and destination registers are different. + + PR middle-end/59285 + * ifcvt.c (merge_if_block): If we are merging a block with more than + one successor with a block with no successors, remove any BARRIER + after the second block. + +2014-01-07 Dan Xio Qiang <ziyan01@163.com> + + * hw-doloop.c (reorg_loops): Release the bitmap obstack. + +2014-01-07 John David Anglin <danglin@gcc.gnu.org> + + PR target/59652 + * config/pa/pa.c (pa_legitimate_address_p): Return false before reload + for 14-bit register offsets when INT14_OK_STRICT is false. + +2014-01-07 Roland Stigge <stigge@antcom.de> + Michael Meissner <meissner@linux.vnet.ibm.com> + + PR 57386/target + * config/rs6000/rs6000.c (rs6000_legitimate_offset_address_p): + Only check TFmode for SPE constants. Don't check TImode or + TDmode. + +2014-01-07 James Greenhalgh <james.greenhalgh@arm.com> + + * config/aarch64/aarch64-elf.h (ASM_SPEC): Remove identity spec for + -mcpu. + +2014-01-07 Yufeng Zhang <yufeng.zhang@arm.com> + + * config/arm/arm.c (arm_expand_neon_args): Call expand_expr + with EXPAND_MEMORY for NEON_ARG_MEMORY; check if the returned + rtx is const0_rtx or not. + +2014-01-07 Richard Sandiford <rdsandiford@googlemail.com> + + PR target/58115 + * target-globals.c (save_target_globals): Remove this_fn_optab + handling. + * toplev.c: Include optabs.h. + (target_reinit): Temporarily restore the global options if another + set of options are in force. + +2014-01-07 Jakub Jelinek <jakub@redhat.com> + + PR rtl-optimization/58668 + * cfgcleanup.c (flow_find_cross_jump): Don't count + any jumps if dir_p is NULL. Remove p1 variable, use active_insn_p + to determine what is counted. + (flow_find_head_matching_sequence): Use active_insn_p to determine + what is counted. + (try_head_merge_bb): Adjust for the flow_find_head_matching_sequence + counting change. + * ifcvt.c (count_bb_insns): Use active_insn_p && !JUMP_P to + determine what is counted. + + PR tree-optimization/59643 + * tree-predcom.c (split_data_refs_to_components): If one dr is + read and one write, determine_offset fails and the write isn't + in the bad component, just put the read into the bad component. + +2014-01-07 Mike Stump <mikestump@comcast.net> + Jakub Jelinek <jakub@redhat.com> + + PR pch/59436 + * tree-core.h (struct tree_optimization_option): Change optabs + type from unsigned char * to void *. + * optabs.c (init_tree_optimization_optabs): Adjust + TREE_OPTIMIZATION_OPTABS initialization. + +2014-01-06 Jakub Jelinek <jakub@redhat.com> + + PR target/59644 + * config/i386/i386.h (struct machine_function): Add + no_drap_save_restore field. + * config/i386/i386.c (ix86_save_reg): Use + !cfun->machine->no_drap_save_restore instead of + crtl->stack_realign_needed. + (ix86_finalize_stack_realign_flags): Don't clear drap_reg unless + this function clears frame_pointer_needed. Set + cfun->machine->no_drap_save_restore if clearing frame_pointer_needed + and DRAP reg is needed. + +2014-01-06 Marek Polacek <polacek@redhat.com> + + PR c/57773 + * doc/implement-c.texi: Mention that other integer types are + permitted as bit-field types in strictly conforming mode. + +2014-01-06 Felix Yang <fei.yang0953@gmail.com> + + * modulo-sched.c (schedule_reg_moves): Clear distance1_uses if it + is newly allocated. + +2014-01-06 Richard Earnshaw <rearnsha@arm.com> + + * aarch64.c (aarch64_rtx_costs): Fix cost calculation for MADD. + +2014-01-06 Martin Jambor <mjambor@suse.cz> + + PR ipa/59008 + * ipa-cp.c (ipcp_discover_new_direct_edges): Changed param_index type + to int. + * ipa-prop.c (ipa_print_node_params): Fix indentation. + +2014-01-06 Eric Botcazou <ebotcazou@adacore.com> + + PR debug/59350 + PR debug/59510 + * var-tracking.c (add_stores): Preserve the value of the source even if + we don't record the store. + +2014-01-06 Terry Guo <terry.guo@arm.com> + + * config.gcc (arm*-*-*): Check --with-arch against arm-arches.def. + +2014-01-05 Iain Sandoe <iain@codesourcery.com> + + PR bootstrap/59541 + * config/darwin.c (darwin_function_section): Adjust return values to + correspond to optimisation changes made in r206070. + +2014-01-05 Uros Bizjak <ubizjak@gmail.com> + + * config/i386/i386.c (ix86_data_alignment): Calculate max_align + from prefetch_block tune setting. + (nocona_cost): Correct size of prefetch block to 64. + +2014-01-04 Eric Botcazou <ebotcazou@adacore.com> + + * config/arm/arm.c (arm_get_frame_offsets): Revamp long lines. + (arm_expand_epilogue_apcs_frame): Take into account the number of bytes + used to save the static chain register in the computation of the offset + from which the FP registers need to be restored. + +2014-01-04 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/59519 + * tree-vect-loop-manip.c (slpeel_update_phi_nodes_for_guard1): Don't + ICE if get_current_def (current_new_name) is already non-NULL, as long + as it is a phi result of some other phi in *new_exit_bb that has + the same argument. + + * config/i386/sse.md (avx512f_load<mode>_mask): Emit vmovup{s,d} + or vmovdqu* for misaligned_operand. + (<sse>_loadu<ssemodesuffix><avxsizesuffix><mask_name>, + <sse2_avx_avx512f>_loaddqu<mode><mask_name>): Handle <mask_applied>. + * config/i386/i386.c (ix86_expand_special_args_builtin): Set + aligned_mem for AVX512F masked aligned load and store builtins and for + non-temporal moves. + +2014-01-03 Bingfeng Mei <bmei@broadcom.com> PR tree-optimization/59651 - * tree-vect-loop-manip.c (vect_create_cond_for_alias_checks): + * tree-vect-loop-manip.c (vect_create_cond_for_alias_checks): Address range for negative step should be added by TYPE_SIZE_UNIT. 2014-01-03 Andreas Schwab <schwab@linux-m68k.org> @@ -79,20 +595,21 @@ 2014-01-02 Richard Sandiford <rdsandiford@googlemail.com> - Update copyright years + Update copyright years. 2014-01-02 Richard Sandiford <rdsandiford@googlemail.com> * common/config/arc/arc-common.c, config/arc/arc-modes.def, config/arc/arc-protos.h, config/arc/arc.c, config/arc/arc.h, - config/arc/arc.md, config/arc/arc.opt, config/arm/arm_neon_builtins.def, - config/arm/crypto.def, config/i386/avx512cdintrin.h, - config/i386/avx512erintrin.h, config/i386/avx512fintrin.h, - config/i386/avx512pfintrin.h, config/i386/btver2.md, - config/i386/shaintrin.h, config/i386/slm.md, config/linux-protos.h, - config/linux.c, config/winnt-c.c, diagnostic-color.c, - diagnostic-color.h, gimple-ssa-isolate-paths.c, vtable-verify.c, - vtable-verify.h: Use the standard form for the copyright notice. + config/arc/arc.md, config/arc/arc.opt, + config/arm/arm_neon_builtins.def, config/arm/crypto.def, + config/i386/avx512cdintrin.h, config/i386/avx512erintrin.h, + config/i386/avx512fintrin.h, config/i386/avx512pfintrin.h, + config/i386/btver2.md, config/i386/shaintrin.h, config/i386/slm.md, + config/linux-protos.h, config/linux.c, config/winnt-c.c, + diagnostic-color.c, diagnostic-color.h, gimple-ssa-isolate-paths.c, + vtable-verify.c, vtable-verify.h: Use the standard form for the + copyright notice. 2014-01-02 Tobias Burnus <burnus@net-b.de> diff --git a/gcc/ChangeLog-2013 b/gcc/ChangeLog-2013 index 2ffd9593b54e..7cf3c9977528 100644 --- a/gcc/ChangeLog-2013 +++ b/gcc/ChangeLog-2013 @@ -62,19 +62,19 @@ (_mm_roundscale_ss): Ditto. (_mm_roundscale_sd): Ditto. * config/i386/i386-builtin-types.def: New types to support - new built-ins: <V2DF, V2DF, V2DF, INT, INT>, <V4SF, V4SF, V4SF, INT, INT>, - <(V4SF, V4SF, V2DF, INT>, <V2DF, V2DF, V4SF, INT>, - <V4SF, V4SF, V4SF, V4SF, IN>. - * config/i386/i386.c (enum ix86_builtins): Add IX86_BUILTIN_ADDSD_ROUND, - IX86_BUILTIN_ADDSS_ROUND, IX86_BUILTIN_CVTSD2SS_ROUND, - IX86_BUILTIN_CVTSS2SD_ROUND, IX86_BUILTIN_DIVSD_ROUND, - IX86_BUILTIN_GETEXPSD128, IX86_BUILTIN_DIVSS_ROUND, - IX86_BUILTIN_GETEXPSS128, IX86_BUILTIN_GETMANTSD128, - IX86_BUILTIN_GETMANTSS128, IX86_BUILTIN_MAXSD_ROUND, - IX86_BUILTIN_MAXSS_ROUND, IX86_BUILTIN_MINSD_ROUND, - IX86_BUILTIN_MINSS_ROUND, IX86_BUILTIN_MULSD_ROUND, - IX86_BUILTIN_MULSS_ROUND, IX86_BUILTIN_RCP14SD, - IX86_BUILTIN_RCP14SS, IX86_BUILTIN_RNDSCALESD, + new built-ins: <V2DF, V2DF, V2DF, INT, INT>, + <V4SF, V4SF, V4SF, INT, INT>, <(V4SF, V4SF, V2DF, INT>, + <V2DF, V2DF, V4SF, INT>, <V4SF, V4SF, V4SF, V4SF, IN>. + * config/i386/i386.c (enum ix86_builtins): Add + IX86_BUILTIN_ADDSD_ROUND, IX86_BUILTIN_ADDSS_ROUND, + IX86_BUILTIN_CVTSD2SS_ROUND, IX86_BUILTIN_CVTSS2SD_ROUND, + IX86_BUILTIN_DIVSD_ROUND, IX86_BUILTIN_GETEXPSD128, + IX86_BUILTIN_DIVSS_ROUND, IX86_BUILTIN_GETEXPSS128, + IX86_BUILTIN_GETMANTSD128, IX86_BUILTIN_GETMANTSS128, + IX86_BUILTIN_MAXSD_ROUND, IX86_BUILTIN_MAXSS_ROUND, + IX86_BUILTIN_MINSD_ROUND, IX86_BUILTIN_MINSS_ROUND, + IX86_BUILTIN_MULSD_ROUND, IX86_BUILTIN_MULSS_ROUND, + IX86_BUILTIN_RCP14SD, IX86_BUILTIN_RCP14SS, IX86_BUILTIN_RNDSCALESD, IX86_BUILTIN_RNDSCALESS, IX86_BUILTIN_RSQRT14SD, IX86_BUILTIN_RSQRT14SS, IX86_BUILTIN_SCALEFSD, IX86_BUILTIN_SCALEFSS, IX86_BUILTIN_SQRTSD_ROUND, @@ -752,7 +752,6 @@ (ix86_expand_int_vcond): Ditto. (ix86_expand_vec_perm): Ditto. (ix86_expand_sse_unpack): Ditto. - (ix86_constant_alignment): Ditto. (ix86_builtin_vectorized_function): Ditto. (ix86_vectorize_builtin_gather): Ditto. (avx_vpermilp_parallel): Ditto. @@ -773,15 +772,15 @@ (ix86_autovectorize_vector_sizes): Ditto. (ix86_expand_vec_perm_vpermi2): New. (ix86_vector_duplicate_value): Ditto. - (IX86_BUILTIN_SQRTPD512, IX86_BUILTIN_EXP2PS, IX86_BUILTIN_SQRTPS_NR512, - IX86_BUILTIN_GATHER3ALTDIV16SF, IX86_BUILTIN_GATHER3ALTDIV16SI, - IX86_BUILTIN_GATHER3ALTSIV8DF, IX86_BUILTIN_GATHER3ALTSIV8DI, - IX86_BUILTIN_GATHER3DIV16SF, IX86_BUILTIN_GATHER3DIV16SI, - IX86_BUILTIN_GATHER3DIV8DF, IX86_BUILTIN_GATHER3DIV8DI, - IX86_BUILTIN_GATHER3SIV16SF, IX86_BUILTIN_GATHER3SIV16SI, - IX86_BUILTIN_GATHER3SIV8DF, IX86_BUILTIN_CEILPD_VEC_PACK_SFIX512, - IX86_BUILTIN_CPYSGNPS512, IX86_BUILTIN_CPYSGNPD512, - IX86_BUILTIN_FLOORPD_VEC_PACK_SFIX512, + (IX86_BUILTIN_SQRTPD512, IX86_BUILTIN_EXP2PS, + IX86_BUILTIN_SQRTPS_NR512, IX86_BUILTIN_GATHER3ALTDIV16SF, + IX86_BUILTIN_GATHER3ALTDIV16SI, IX86_BUILTIN_GATHER3ALTSIV8DF, + IX86_BUILTIN_GATHER3ALTSIV8DI, IX86_BUILTIN_GATHER3DIV16SF, + IX86_BUILTIN_GATHER3DIV16SI, IX86_BUILTIN_GATHER3DIV8DF, + IX86_BUILTIN_GATHER3DIV8DI, IX86_BUILTIN_GATHER3SIV16SF, + IX86_BUILTIN_GATHER3SIV16SI, IX86_BUILTIN_GATHER3SIV8DF, + IX86_BUILTIN_CEILPD_VEC_PACK_SFIX512, IX86_BUILTIN_CPYSGNPS512, + IX86_BUILTIN_CPYSGNPD512, IX86_BUILTIN_FLOORPD_VEC_PACK_SFIX512, IX86_BUILTIN_ROUNDPD_AZ_VEC_PACK_SFIX512): Ditto. * config/i386/sse.md (*mov<mode>_internal): Disable SSE typeless stores vectors > 128bit (AVX*). @@ -816,10 +815,8 @@ * config/nios2/constraints.md: New file. * config/nios2/t-nios2: New file. * common/config/nios2/nios2-common.c: New file. - * doc/invoke.texi (Nios II options): Document Nios II specific - options. - * doc/md.texi (Nios II family): Document Nios II specific - constraints. + * doc/invoke.texi (Nios II options): Document Nios II specific options. + * doc/md.texi (Nios II family): Document Nios II specific constraints. * doc/extend.texi (Function Specific Option Pragmas): Document Nios II supported target pragma functionality. @@ -1076,8 +1073,8 @@ 2013-12-26 Ganesh Gopalasubramanian <Ganesh.Gopalasubramanian@amd.com> - * config/i386/i386.c (get_builtin_code_for_version): Rename AMD - CPU names M_AMD_BOBCAT to M_AMD_BTVER1 and M_AMD_JAGUAR + * config/i386/i386.c (get_builtin_code_for_version): Rename AMD + CPU names M_AMD_BOBCAT to M_AMD_BTVER1 and M_AMD_JAGUAR to M_AMD_BTVER2. (processor_model): Likewise. (arch_names_table): Likewise. @@ -3857,12 +3854,6 @@ targets like arm-none-eabi. * expr.c (expand_assignment): Handle normal fields like bit regions. -2013-12-02 Bernd Edlinger <bernd.edlinger@hotmail.de> - - PR target/58115 - * function.c (invoke_set_current_function_hook): Call - targetm.set_current_function after setting this_fn_optabs. - 2013-12-02 Richard Biener <rguenther@suse.de> PR tree-optimization/59139 diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index c88e6a62ab2d..ee2701aaa83c 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20140103 +20140113 diff --git a/gcc/Makefile.in b/gcc/Makefile.in index b9d84b24f4ee..7926bd7584f8 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -929,11 +929,10 @@ CPP_ID_DATA_H = $(CPPLIB_H) $(srcdir)/../libcpp/include/cpp-id-data.h CPP_INTERNAL_H = $(srcdir)/../libcpp/internal.h $(CPP_ID_DATA_H) TREE_DUMP_H = tree-dump.h $(SPLAY_TREE_H) $(DUMPFILE_H) TREE_PASS_H = tree-pass.h $(TIMEVAR_H) $(DUMPFILE_H) -TREE_FLOW_H = tree-flow.h tree-flow-inline.h tree-ssa-operands.h \ +TREE_SSA_H = tree-ssa.h tree-ssa-operands.h \ $(BITMAP_H) sbitmap.h $(BASIC_BLOCK_H) $(GIMPLE_H) \ $(HASHTAB_H) $(CGRAPH_H) $(IPA_REFERENCE_H) \ tree-ssa-alias.h wide-int.h -TREE_SSA_H = tree-ssa.h $(TREE_FLOW_H) PRETTY_PRINT_H = pretty-print.h $(INPUT_H) $(OBSTACK_H) TREE_PRETTY_PRINT_H = tree-pretty-print.h $(PRETTY_PRINT_H) GIMPLE_PRETTY_PRINT_H = gimple-pretty-print.h $(TREE_PRETTY_PRINT_H) @@ -3123,7 +3122,9 @@ PLUGIN_HEADERS = $(TREE_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ cppdefault.h flags.h $(MD5_H) params.def params.h prefix.h tree-inline.h \ $(GIMPLE_PRETTY_PRINT_H) realmpfr.h \ $(IPA_PROP_H) $(TARGET_H) $(RTL_H) $(TM_P_H) $(CFGLOOP_H) $(EMIT_RTL_H) \ - version.h stringpool.h + version.h stringpool.h gimplify.h gimple-iterator.h gimple-ssa.h \ + fold-const.h tree-cfg.h tree-into-ssa.h tree-ssanames.h print-tree.h \ + varasm.h context.h # generate the 'build fragment' b-header-vars s-header-vars: Makefile diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 153b42442f24..a0570a59da9d 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,10 @@ +2014-01-12 Eric Botcazou <ebotcazou@adacore.com> + + PR ada/59772 + * gcc-interface/cuintp.c (build_cst_from_int): Use 32-bit integer type + as intermediate type. + (UI_To_gnu): Likewise. + 2014-01-03 Eric Botcazou <ebotcazou@adacore.com> * gnatvsn.ads (Current_Year): Bump to 2014. diff --git a/gcc/ada/gcc-interface/cuintp.c b/gcc/ada/gcc-interface/cuintp.c index 7ef68b628b3f..e9b30b28aa56 100644 --- a/gcc/ada/gcc-interface/cuintp.c +++ b/gcc/ada/gcc-interface/cuintp.c @@ -6,7 +6,7 @@ * * * C Implementation File * * * - * Copyright (C) 1992-2013, Free Software Foundation, Inc. * + * Copyright (C) 1992-2014, Free Software Foundation, Inc. * * * * GNAT is free software; you can redistribute it and/or modify it under * * terms of the GNU General Public License as published by the Free Soft- * @@ -55,7 +55,7 @@ static tree build_cst_from_int (tree type, HOST_WIDE_INT low) { if (SCALAR_FLOAT_TYPE_P (type)) - return convert (type, build_int_cst (NULL_TREE, low)); + return convert (type, build_int_cst (gnat_type_for_size (32, 0), low)); else return build_int_cst_type (type, low); } @@ -89,19 +89,12 @@ UI_To_gnu (Uint Input, tree type) gcc_assert (Length > 0); /* The computations we perform below always require a type at least as - large as an integer not to overflow. REAL types are always fine, but + large as an integer not to overflow. FP types are always fine, but INTEGER or ENUMERAL types we are handed may be too short. We use a base integer type node for the computations in this case and will - convert the final result back to the incoming type later on. - The base integer precision must be superior than 16. */ - - if (TREE_CODE (comp_type) != REAL_TYPE - && TYPE_PRECISION (comp_type) - < TYPE_PRECISION (long_integer_type_node)) - { - comp_type = long_integer_type_node; - gcc_assert (TYPE_PRECISION (comp_type) > 16); - } + convert the final result back to the incoming type later on. */ + if (!SCALAR_FLOAT_TYPE_P (comp_type) && TYPE_PRECISION (comp_type) < 32) + comp_type = gnat_type_for_size (32, 0); gnu_base = build_cst_from_int (comp_type, Base); diff --git a/gcc/asan.c b/gcc/asan.c index e077153a969d..53992a81b189 100644 --- a/gcc/asan.c +++ b/gcc/asan.c @@ -53,6 +53,7 @@ along with GCC; see the file COPYING3. If not see #include "gimple-builder.h" #include "ubsan.h" #include "predict.h" +#include "params.h" /* AddressSanitizer finds out-of-bounds and use-after-free bugs with <2x slowdown on average. @@ -1003,7 +1004,8 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb, str_cst = asan_pp_string (&asan_pp); /* Emit the prologue sequence. */ - if (asan_frame_size > 32 && asan_frame_size <= 65536 && pbase) + if (asan_frame_size > 32 && asan_frame_size <= 65536 && pbase + && ASAN_USE_AFTER_RETURN) { use_after_return_class = floor_log2 (asan_frame_size - 1) - 5; /* __asan_stack_malloc_N guarantees alignment @@ -1239,6 +1241,9 @@ asan_needs_local_alias (tree decl) bool asan_protect_global (tree decl) { + if (!ASAN_GLOBALS) + return false; + rtx rtl, symbol; if (TREE_CODE (decl) == STRING_CST) @@ -1568,6 +1573,11 @@ static void instrument_derefs (gimple_stmt_iterator *iter, tree t, location_t location, bool is_store) { + if (is_store && !ASAN_INSTRUMENT_WRITES) + return; + if (!is_store && !ASAN_INSTRUMENT_READS) + return; + tree type, base; HOST_WIDE_INT size_in_bytes; @@ -1897,6 +1907,9 @@ instrument_strlen_call (gimple_stmt_iterator *iter) static bool instrument_builtin_call (gimple_stmt_iterator *iter) { + if (!ASAN_MEMINTRIN) + return false; + bool iter_advanced_p = false; gimple call = gsi_stmt (*iter); diff --git a/gcc/builtins.c b/gcc/builtins.c index 81bb40775987..3f9af38bbaae 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -434,7 +434,7 @@ get_object_alignment_2 (tree exp, unsigned int *alignp, alignment that can prevail. */ if (offset) { - int trailing_zeros = tree_ctz (offset); + unsigned int trailing_zeros = tree_ctz (offset); if (trailing_zeros < HOST_BITS_PER_INT) { unsigned int inner = (1U << trailing_zeros) * BITS_PER_UNIT; diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index defc0030a640..d9b69b32c419 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,9 @@ +2014-01-09 Jakub Jelinek <jakub@redhat.com> + + PR target/58115 + * c-pch.c (c_common_write_pch): Call + prepare_target_option_nodes_for_pch. + 2014-01-02 Richard Sandiford <rdsandiford@googlemail.com> Update copyright years diff --git a/gcc/c-family/c-pch.c b/gcc/c-family/c-pch.c index e51d5b9409e1..93609b610ff1 100644 --- a/gcc/c-family/c-pch.c +++ b/gcc/c-family/c-pch.c @@ -180,6 +180,8 @@ c_common_write_pch (void) (*debug_hooks->handle_pch) (1); + prepare_target_option_nodes_for_pch (); + cpp_write_pch_deps (parse_in, pch_outfile); gt_pch_save (pch_outfile); diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 6cb79c0fa6f3..d3b338a5b8ea 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,15 @@ +2014-01-09 Balaji V. Iyer <balaji.v.iyer@intel.com> + + PR c++/59631 + * c-parser.c (c_parser_postfix_expression): Replaced consecutive if + statements with if-elseif statements. + +2014-01-06 Marek Polacek <polacek@redhat.com> + + PR c/57773 + * c-decl.c (check_bitfield_type_and_width): Warn for implementation + defined bit-field types only in ISO C. + 2014-01-02 Richard Sandiford <rdsandiford@googlemail.com> Update copyright years diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index 2dee4c248c0a..9c601facad2f 100644 --- a/gcc/c/c-decl.c +++ b/gcc/c/c-decl.c @@ -4840,7 +4840,8 @@ check_bitfield_type_and_width (tree *type, tree *width, tree orig_name) if (!in_system_header_at (input_location) && type_mv != integer_type_node && type_mv != unsigned_type_node - && type_mv != boolean_type_node) + && type_mv != boolean_type_node + && !flag_isoc99) pedwarn (input_location, OPT_Wpedantic, "type of bit-field %qs is a GCC extension", name); diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index 25fa701ebd95..2590c9be05ee 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -7500,7 +7500,7 @@ c_parser_postfix_expression (c_parser *parser) expr = c_parser_postfix_expression (parser); expr.value = error_mark_node; } - if (c_parser_peek_token (parser)->keyword == RID_CILK_SPAWN) + else if (c_parser_peek_token (parser)->keyword == RID_CILK_SPAWN) { error_at (loc, "consecutive %<_Cilk_spawn%> keywords " "are not permitted"); diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c index e2e407bd2dea..77196ee6bf71 100644 --- a/gcc/cfgcleanup.c +++ b/gcc/cfgcleanup.c @@ -1295,7 +1295,6 @@ flow_find_cross_jump (basic_block bb1, basic_block bb2, rtx *f1, rtx *f2, { rtx i1, i2, last1, last2, afterlast1, afterlast2; int ninsns = 0; - rtx p1; enum replace_direction dir, last_dir, afterlast_dir; bool follow_fallthru, did_fallthru; @@ -1323,8 +1322,9 @@ flow_find_cross_jump (basic_block bb1, basic_block bb2, rtx *f1, rtx *f2, || (returnjump_p (i2) && !side_effects_p (PATTERN (i2)))) { last2 = i2; - /* Count everything except for unconditional jump as insn. */ - if (!simplejump_p (i2) && !returnjump_p (i2) && last1) + /* Count everything except for unconditional jump as insn. + Don't count any jumps if dir_p is NULL. */ + if (!simplejump_p (i2) && !returnjump_p (i2) && last1 && dir_p) ninsns++; i2 = PREV_INSN (i2); } @@ -1375,8 +1375,7 @@ flow_find_cross_jump (basic_block bb1, basic_block bb2, rtx *f1, rtx *f2, last1 = i1, last2 = i2; afterlast_dir = last_dir; last_dir = dir; - p1 = PATTERN (i1); - if (!(GET_CODE (p1) == USE || GET_CODE (p1) == CLOBBER)) + if (active_insn_p (i1)) ninsns++; } @@ -1422,7 +1421,8 @@ flow_find_cross_jump (basic_block bb1, basic_block bb2, rtx *f1, rtx *f2, /* Like flow_find_cross_jump, except start looking for a matching sequence from the head of the two blocks. Do not include jumps at the end. If STOP_AFTER is nonzero, stop after finding that many matching - instructions. */ + instructions. If STOP_AFTER is zero, count all INSN_P insns, if it is + non-zero, only count active insns. */ int flow_find_head_matching_sequence (basic_block bb1, basic_block bb2, rtx *f1, @@ -1494,7 +1494,8 @@ flow_find_head_matching_sequence (basic_block bb1, basic_block bb2, rtx *f1, beforelast1 = last1, beforelast2 = last2; last1 = i1, last2 = i2; - ninsns++; + if (!stop_after || active_insn_p (i1)) + ninsns++; } if (i1 == BB_END (bb1) || i2 == BB_END (bb2) diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index 2ba1cf4e36e0..c0cbeb3c0220 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -798,7 +798,7 @@ partition_stack_vars (void) sizes, as the shorter vars wouldn't be adequately protected. Don't do that for "large" (unsupported) alignment objects, those aren't protected anyway. */ - if ((flag_sanitize & SANITIZE_ADDRESS) && isize != jsize + if ((flag_sanitize & SANITIZE_ADDRESS) && ASAN_STACK && isize != jsize && ialign * BITS_PER_UNIT <= MAX_SUPPORTED_STACK_ALIGNMENT) break; @@ -981,7 +981,7 @@ expand_stack_vars (bool (*pred) (size_t), struct stack_vars_data *data) if (alignb * BITS_PER_UNIT <= MAX_SUPPORTED_STACK_ALIGNMENT) { base = virtual_stack_vars_rtx; - if ((flag_sanitize & SANITIZE_ADDRESS) && pred) + if ((flag_sanitize & SANITIZE_ADDRESS) && ASAN_STACK && pred) { HOST_WIDE_INT prev_offset = frame_offset; tree repr_decl = NULL_TREE; @@ -1160,7 +1160,7 @@ defer_stack_allocation (tree var, bool toplevel) /* If stack protection is enabled, *all* stack variables must be deferred, so that we can re-order the strings to the top of the frame. Similarly for Address Sanitizer. */ - if (flag_stack_protect || (flag_sanitize & SANITIZE_ADDRESS)) + if (flag_stack_protect || ((flag_sanitize & SANITIZE_ADDRESS) && ASAN_STACK)) return true; /* We handle "large" alignment via dynamic allocation. We want to handle @@ -1215,8 +1215,11 @@ expand_one_var (tree var, bool toplevel, bool really_expand) we conservatively assume it will be on stack even if VAR is eventually put into register after RA pass. For non-automatic variables, which won't be on stack, we collect alignment of - type and ignore user specified alignment. */ - if (TREE_STATIC (var) || DECL_EXTERNAL (var)) + type and ignore user specified alignment. Similarly for + SSA_NAMEs for which use_register_for_decl returns true. */ + if (TREE_STATIC (var) + || DECL_EXTERNAL (var) + || (TREE_CODE (origvar) == SSA_NAME && use_register_for_decl (var))) align = MINIMUM_ALIGNMENT (TREE_TYPE (var), TYPE_MODE (TREE_TYPE (var)), TYPE_ALIGN (TREE_TYPE (var))); @@ -1820,7 +1823,7 @@ expand_used_vars (void) expand_stack_vars (stack_protect_decl_phase_2, &data); } - if (flag_sanitize & SANITIZE_ADDRESS) + if ((flag_sanitize & SANITIZE_ADDRESS) && ASAN_STACK) /* Phase 3, any partitions that need asan protection in addition to phase 1 and 2. */ expand_stack_vars (asan_decl_phase_3, &data); @@ -2253,7 +2256,7 @@ expand_call_stmt (gimple stmt) if (lhs) expand_assignment (lhs, exp, false); else - expand_expr_real_1 (exp, const0_rtx, VOIDmode, EXPAND_NORMAL, NULL); + expand_expr (exp, const0_rtx, VOIDmode, EXPAND_NORMAL); mark_transaction_restart_calls (stmt); } diff --git a/gcc/cgraph.h b/gcc/cgraph.h index 8b25d947511d..7ce54014e1ef 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -1426,8 +1426,12 @@ varpool_variable_node (varpool_node *node, { varpool_node *n; - n = dyn_cast <varpool_node> (symtab_alias_ultimate_target (node, - availability)); + if (node) + n = dyn_cast <varpool_node> (symtab_alias_ultimate_target (node, + availability)); + else + n = NULL; + if (!n && availability) *availability = AVAIL_NOT_AVAILABLE; return n; diff --git a/gcc/config.gcc b/gcc/config.gcc index bd0fb6359604..23657a5b0f42 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -3476,19 +3476,17 @@ case "${target}" in fi done - case "$with_arch" in - "" \ - | armv[23456] | armv2a | armv3m | armv4t | armv5t \ - | armv5te | armv6j |armv6k | armv6z | armv6zk | armv6-m \ - | armv7 | armv7-a | armv7-r | armv7-m | armv8-a \ - | iwmmxt | ep9312) - # OK - ;; - *) - echo "Unknown arch used in --with-arch=$with_arch" 1>&2 - exit 1 - ;; - esac + # See if it matches any of the entries in arm-arches.def + if [ x"$with_arch" = x ] \ + || grep "^ARM_ARCH(\"$with_arch\"," \ + ${srcdir}/config/arm/arm-arches.def \ + > /dev/null; then + # OK + true + else + echo "Unknown arch used in --with-arch=$with_arch" 1>&2 + exit 1 + fi case "$with_float" in "" \ diff --git a/gcc/config/aarch64/aarch64-elf.h b/gcc/config/aarch64/aarch64-elf.h index 7bcdc13d1404..15ab630de884 100644 --- a/gcc/config/aarch64/aarch64-elf.h +++ b/gcc/config/aarch64/aarch64-elf.h @@ -144,7 +144,6 @@ #define ASM_SPEC "\ %{mbig-endian:-EB} \ %{mlittle-endian:-EL} \ -%{mcpu=*:-mcpu=%*} \ %{march=*:-march=%*} \ %(asm_cpu_spec)" \ ASM_MABI_SPEC diff --git a/gcc/config/aarch64/aarch64-modes.def b/gcc/config/aarch64/aarch64-modes.def index 3a56d622a824..1d2cc7679466 100644 --- a/gcc/config/aarch64/aarch64-modes.def +++ b/gcc/config/aarch64/aarch64-modes.def @@ -24,6 +24,7 @@ CC_MODE (CC_SWP); CC_MODE (CC_ZESWP); /* zero-extend LHS (but swap to make it RHS). */ CC_MODE (CC_SESWP); /* sign-extend LHS (but swap to make it RHS). */ CC_MODE (CC_NZ); /* Only N and Z bits of condition flags are valid. */ +CC_MODE (CC_Z); /* Only Z bit of condition flags is valid. */ /* Vector modes. */ VECTOR_MODES (INT, 8); /* V8QI V4HI V2SI. */ diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 3fd58b961047..9e507b842579 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -3326,17 +3326,24 @@ aarch64_select_cc_mode (RTX_CODE code, rtx x, rtx y) || GET_CODE (x) == NEG)) return CC_NZmode; - /* A compare with a shifted or negated operand. Because of canonicalization, + /* A compare with a shifted operand. Because of canonicalization, the comparison will have to be swapped when we emit the assembly code. */ if ((GET_MODE (x) == SImode || GET_MODE (x) == DImode) && (GET_CODE (y) == REG || GET_CODE (y) == SUBREG) && (GET_CODE (x) == ASHIFT || GET_CODE (x) == ASHIFTRT || GET_CODE (x) == LSHIFTRT - || GET_CODE (x) == ZERO_EXTEND || GET_CODE (x) == SIGN_EXTEND - || GET_CODE (x) == NEG)) + || GET_CODE (x) == ZERO_EXTEND || GET_CODE (x) == SIGN_EXTEND)) return CC_SWPmode; + /* Similarly for a negated operand, but we can only do this for + equalities. */ + if ((GET_MODE (x) == SImode || GET_MODE (x) == DImode) + && (GET_CODE (y) == REG || GET_CODE (y) == SUBREG) + && (code == EQ || code == NE) + && GET_CODE (x) == NEG) + return CC_Zmode; + /* A compare of a mode narrower than SI mode against zero can be done by extending the value in the comparison. */ if ((GET_MODE (x) == QImode || GET_MODE (x) == HImode) @@ -3427,6 +3434,15 @@ aarch64_get_condition_code (rtx x) } break; + case CC_Zmode: + switch (comp_code) + { + case NE: return AARCH64_NE; + case EQ: return AARCH64_EQ; + default: gcc_unreachable (); + } + break; + default: gcc_unreachable (); break; @@ -4643,12 +4659,15 @@ aarch64_rtx_costs (rtx x, int code, int outer ATTRIBUTE_UNUSED, extra_cost->mult[GET_MODE (x) == DImode].extend_add; return true; } + *cost += (rtx_cost (XEXP (op0, 0), MULT, 0, speed) + rtx_cost (XEXP (op0, 1), MULT, 1, speed) + rtx_cost (op1, PLUS, 1, speed)); if (speed) *cost += extra_cost->mult[GET_MODE (x) == DImode].add; + + return true; } *cost += (rtx_cost (new_op0, PLUS, 0, speed) diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index 4e838ee847b8..3b5e92e41629 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -1250,8 +1250,8 @@ ) (define_insn "*compare_neg<mode>" - [(set (reg:CC_SWP CC_REGNUM) - (compare:CC_SWP + [(set (reg:CC_Z CC_REGNUM) + (compare:CC_Z (neg:GPI (match_operand:GPI 0 "register_operand" "r")) (match_operand:GPI 1 "register_operand" "r")))] "" diff --git a/gcc/config/arm/arm-cores.def b/gcc/config/arm/arm-cores.def index d961e250e469..1e97273e51b4 100644 --- a/gcc/config/arm/arm-cores.def +++ b/gcc/config/arm/arm-cores.def @@ -152,8 +152,8 @@ ARM_CORE("marvell-pj4", marvell_pj4, marvell_pj4, 7A, FL_LDSCHED, 9e) ARM_CORE("cortex-a15.cortex-a7", cortexa15cortexa7, cortexa7, 7A, FL_LDSCHED | FL_THUMB_DIV | FL_ARM_DIV, cortex_a15) /* V8 Architecture Processors */ -ARM_CORE("cortex-a53", cortexa53, cortexa53, 8A, FL_LDSCHED, cortex_a53) -ARM_CORE("cortex-a57", cortexa57, cortexa15, 8A, FL_LDSCHED, cortex_a15) +ARM_CORE("cortex-a53", cortexa53, cortexa53, 8A, FL_LDSCHED | FL_CRC32, cortex_a53) +ARM_CORE("cortex-a57", cortexa57, cortexa15, 8A, FL_LDSCHED | FL_CRC32, cortex_a15) /* V8 big.LITTLE implementations */ -ARM_CORE("cortex-a57.cortex-a53", cortexa57cortexa53, cortexa53, 8A, FL_LDSCHED | FL_THUMB_DIV | FL_ARM_DIV, cortex_a15) +ARM_CORE("cortex-a57.cortex-a53", cortexa57cortexa53, cortexa53, 8A, FL_LDSCHED | FL_CRC32, cortex_a15) diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 42450c71c272..0cb16f94b3f3 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -9092,6 +9092,9 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code, { case SET: *cost = 0; + /* SET RTXs don't have a mode so we get it from the destination. */ + mode = GET_MODE (SET_DEST (x)); + if (REG_P (SET_SRC (x)) && REG_P (SET_DEST (x))) { @@ -9106,6 +9109,8 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code, in 16 bits in Thumb mode. */ if (!speed_p && TARGET_THUMB && outer_code == COND_EXEC) *cost >>= 1; + + return true; } if (CONST_INT_P (SET_SRC (x))) @@ -9113,7 +9118,6 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code, /* Handle CONST_INT here, since the value doesn't have a mode and we would otherwise be unable to work out the true cost. */ *cost = rtx_cost (SET_DEST (x), SET, 0, speed_p); - mode = GET_MODE (SET_DEST (x)); outer_code = SET; /* Slightly lower the cost of setting a core reg to a constant. This helps break up chains and allows for better scheduling. */ @@ -20316,8 +20320,10 @@ arm_get_frame_offsets (void) offsets->saved_args = crtl->args.pretend_args_size; /* In Thumb mode this is incorrect, but never used. */ - offsets->frame = offsets->saved_args + (frame_pointer_needed ? 4 : 0) + - arm_compute_static_chain_stack_bytes(); + offsets->frame + = (offsets->saved_args + + arm_compute_static_chain_stack_bytes () + + (frame_pointer_needed ? 4 : 0)); if (TARGET_32BIT) { @@ -20357,9 +20363,10 @@ arm_get_frame_offsets (void) } /* Saved registers include the stack frame. */ - offsets->saved_regs = offsets->saved_args + saved + - arm_compute_static_chain_stack_bytes(); + offsets->saved_regs + = offsets->saved_args + arm_compute_static_chain_stack_bytes () + saved; offsets->soft_frame = offsets->saved_regs + CALLER_INTERWORKING_SLOT_SIZE; + /* A leaf function does not need any stack alignment if it has nothing on the stack. */ if (leaf && frame_size == 0 @@ -24241,7 +24248,7 @@ arm_init_iwmmxt_builtins (void) enum machine_mode mode; tree type; - if (d->name == 0) + if (d->name == 0 || !(d->mask == FL_IWMMXT || d->mask == FL_IWMMXT2)) continue; mode = insn_data[d->icode].operand[1].mode; @@ -24838,7 +24845,11 @@ arm_expand_neon_args (rtx target, int icode, int have_retval, type_mode); } - op[argc] = expand_normal (arg[argc]); + /* Use EXPAND_MEMORY for NEON_ARG_MEMORY to ensure a MEM_P + be returned. */ + op[argc] = expand_expr (arg[argc], NULL_RTX, VOIDmode, + (thisarg == NEON_ARG_MEMORY + ? EXPAND_MEMORY : EXPAND_NORMAL)); switch (thisarg) { @@ -24857,6 +24868,9 @@ arm_expand_neon_args (rtx target, int icode, int have_retval, break; case NEON_ARG_MEMORY: + /* Check if expand failed. */ + if (op[argc] == const0_rtx) + return 0; gcc_assert (MEM_P (op[argc])); PUT_MODE (op[argc], mode[argc]); /* ??? arm_neon.h uses the same built-in functions for signed @@ -27048,7 +27062,10 @@ arm_expand_epilogue_apcs_frame (bool really_return) saved_regs_mask = offsets->saved_regs_mask; /* Find the offset of the floating-point save area in the frame. */ - floats_from_frame = offsets->saved_args - offsets->frame; + floats_from_frame + = (offsets->saved_args + + arm_compute_static_chain_stack_bytes () + - offsets->frame); /* Compute how many core registers saved and how far away the floats are. */ for (i = 0; i <= LAST_ARM_REGNUM; i++) diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index 409589d2dac2..b815488db535 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -189,7 +189,7 @@ extern arm_cc arm_current_cc; #define ARM_INVERSE_CONDITION_CODE(X) ((arm_cc) (((int)X) ^ 1)) -/* The maximaum number of instructions that is beneficial to +/* The maximum number of instructions that is beneficial to conditionally execute. */ #undef MAX_CONDITIONAL_EXECUTE #define MAX_CONDITIONAL_EXECUTE arm_max_conditional_execute () diff --git a/gcc/config/darwin.c b/gcc/config/darwin.c index 95ca5db70027..3c50e24edf26 100644 --- a/gcc/config/darwin.c +++ b/gcc/config/darwin.c @@ -3609,57 +3609,36 @@ darwin_function_section (tree decl, enum node_frequency freq, if (decl && DECL_SECTION_NAME (decl) != NULL_TREE) return get_named_section (decl, NULL, 0); - /* Default when there is no function re-ordering. */ - if (!flag_reorder_functions) - return (weak) - ? darwin_sections[text_coal_section] - : text_section; - - /* Startup code should go to startup subsection unless it is - unlikely executed (this happens especially with function splitting - where we can split away unnecessary parts of static constructors). */ - if (startup && freq != NODE_FREQUENCY_UNLIKELY_EXECUTED) - { - /* If we do have a profile or(and) LTO phase is executed, we do not need - these ELF section. */ - if (!in_lto_p || !flag_profile_values) - return (weak) - ? darwin_sections[text_startup_coal_section] - : darwin_sections[text_startup_section]; - else - return text_section; - } + /* We always put unlikely executed stuff in the cold section. */ + if (freq == NODE_FREQUENCY_UNLIKELY_EXECUTED) + return (weak) ? darwin_sections[text_cold_coal_section] + : darwin_sections[text_cold_section]; + + /* If we have LTO *and* feedback information, then let LTO handle + the function ordering, it makes a better job (for normal, hot, + startup and exit - hence the bailout for cold above). */ + if (in_lto_p && flag_profile_values) + goto default_function_sections; + + /* Non-cold startup code should go to startup subsection. */ + if (startup) + return (weak) ? darwin_sections[text_startup_coal_section] + : darwin_sections[text_startup_section]; /* Similarly for exit. */ - if (exit && freq != NODE_FREQUENCY_UNLIKELY_EXECUTED) - return (weak) - ? darwin_sections[text_exit_coal_section] - : darwin_sections[text_exit_section]; - - /* Group cold functions together, similarly for hot code. */ - switch (freq) - { - case NODE_FREQUENCY_UNLIKELY_EXECUTED: - return (weak) - ? darwin_sections[text_cold_coal_section] - : darwin_sections[text_cold_section]; - break; - case NODE_FREQUENCY_HOT: - { - /* If we do have a profile or(and) LTO phase is executed, we do not need - these ELF section. */ - if (!in_lto_p || !flag_profile_values) - return (weak) - ? darwin_sections[text_hot_coal_section] - : darwin_sections[text_hot_section]; - break; - } - default: - return (weak) - ? darwin_sections[text_coal_section] + if (exit) + return (weak) ? darwin_sections[text_exit_coal_section] + : darwin_sections[text_exit_section]; + + /* Place hot code. */ + if (freq == NODE_FREQUENCY_HOT) + return (weak) ? darwin_sections[text_hot_coal_section] + : darwin_sections[text_hot_section]; + + /* Otherwise, default to the 'normal' non-reordered sections. */ +default_function_sections: + return (weak) ? darwin_sections[text_coal_section] : text_section; - break; - } } /* When a function is partitioned between sections, we need to insert a label diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 1d04a3c64ee9..d10fe9529e47 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -81,6 +81,7 @@ along with GCC; see the file COPYING3. If not see #include "wide-int.h" #include "context.h" #include "pass_manager.h" +#include "target-globals.h" static rtx legitimize_dllimport_symbol (rtx, bool); static rtx legitimize_pe_coff_extern_decl (rtx, bool); @@ -1569,7 +1570,7 @@ struct processor_costs nocona_cost = { 8, /* MMX or SSE register to integer */ 8, /* size of l1 cache. */ 1024, /* size of l2 cache. */ - 128, /* size of prefetch block */ + 64, /* size of prefetch block */ 8, /* number of parallel prefetches */ 1, /* Branch cost */ COSTS_N_INSNS (6), /* cost of FADD and FSUB insns. */ @@ -4869,16 +4870,25 @@ ix86_set_current_function (tree fndecl) { cl_target_option_restore (&global_options, TREE_TARGET_OPTION (new_tree)); - target_reinit (); + if (TREE_TARGET_GLOBALS (new_tree)) + restore_target_globals (TREE_TARGET_GLOBALS (new_tree)); + else + TREE_TARGET_GLOBALS (new_tree) + = save_target_globals_default_opts (); } else if (old_tree) { - struct cl_target_option *def - = TREE_TARGET_OPTION (target_option_current_node); - - cl_target_option_restore (&global_options, def); - target_reinit (); + new_tree = target_option_current_node; + cl_target_option_restore (&global_options, + TREE_TARGET_OPTION (new_tree)); + if (TREE_TARGET_GLOBALS (new_tree)) + restore_target_globals (TREE_TARGET_GLOBALS (new_tree)); + else if (new_tree == target_option_default_node) + restore_target_globals (&default_target_globals); + else + TREE_TARGET_GLOBALS (new_tree) + = save_target_globals_default_opts (); } } } @@ -9282,7 +9292,7 @@ ix86_save_reg (unsigned int regno, bool maybe_eh_return) if (crtl->drap_reg && regno == REGNO (crtl->drap_reg) - && crtl->stack_realign_needed) + && !cfun->machine->no_drap_save_restore) return true; return (df_regs_ever_live_p (regno) @@ -10520,18 +10530,6 @@ ix86_finalize_stack_realign_flags (void) return; } - /* If drap has been set, but it actually isn't live at the start - of the function and !stack_realign, there is no reason to set it up. */ - if (crtl->drap_reg && !stack_realign) - { - basic_block bb = ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb; - if (! REGNO_REG_SET_P (DF_LR_IN (bb), REGNO (crtl->drap_reg))) - { - crtl->drap_reg = NULL_RTX; - crtl->need_drap = false; - } - } - /* If the only reason for frame_pointer_needed is that we conservatively assumed stack realignment might be needed, but in the end nothing that needed the stack alignment had been spilled, clear frame_pointer_needed @@ -10585,6 +10583,8 @@ ix86_finalize_stack_realign_flags (void) crtl->need_drap = false; } } + else + cfun->machine->no_drap_save_restore = true; frame_pointer_needed = false; stack_realign = false; @@ -26466,8 +26466,16 @@ ix86_constant_alignment (tree exp, int align) int ix86_data_alignment (tree type, int align, bool opt) { - int max_align = optimize_size ? BITS_PER_WORD - : MIN (512, MAX_OFILE_ALIGNMENT); + /* A data structure, equal or greater than the size of a cache line + (64 bytes in the Pentium 4 and other recent Intel processors, including + processors based on Intel Core microarchitecture) should be aligned + so that its base address is a multiple of a cache line size. */ + + int max_align + = MIN ((unsigned) ix86_tune_cost->prefetch_block * 8, MAX_OFILE_ALIGNMENT); + + if (max_align < BITS_PER_WORD) + max_align = BITS_PER_WORD; if (opt && AGGREGATE_TYPE_P (type) @@ -34407,6 +34415,9 @@ ix86_expand_special_args_builtin (const struct builtin_description *d, case CODE_FOR_sse2_movntidi: case CODE_FOR_sse_movntq: case CODE_FOR_sse2_movntisi: + case CODE_FOR_avx512f_movntv16sf: + case CODE_FOR_avx512f_movntv8df: + case CODE_FOR_avx512f_movntv8di: aligned_mem = true; break; default: @@ -34431,6 +34442,24 @@ ix86_expand_special_args_builtin (const struct builtin_description *d, klass = load; memory = 0; break; + case VOID_FTYPE_PV8DF_V8DF_QI: + case VOID_FTYPE_PV16SF_V16SF_HI: + case VOID_FTYPE_PV8DI_V8DI_QI: + case VOID_FTYPE_PV16SI_V16SI_HI: + switch (icode) + { + /* These builtins and instructions require the memory + to be properly aligned. */ + case CODE_FOR_avx512f_storev16sf_mask: + case CODE_FOR_avx512f_storev16si_mask: + case CODE_FOR_avx512f_storev8df_mask: + case CODE_FOR_avx512f_storev8di_mask: + aligned_mem = true; + break; + default: + break; + } + /* FALLTHRU */ case VOID_FTYPE_PV8SF_V8SI_V8SF: case VOID_FTYPE_PV4DF_V4DI_V4DF: case VOID_FTYPE_PV4SF_V4SI_V4SF: @@ -34439,10 +34468,6 @@ ix86_expand_special_args_builtin (const struct builtin_description *d, case VOID_FTYPE_PV4DI_V4DI_V4DI: case VOID_FTYPE_PV4SI_V4SI_V4SI: case VOID_FTYPE_PV2DI_V2DI_V2DI: - case VOID_FTYPE_PV8DF_V8DF_QI: - case VOID_FTYPE_PV16SF_V16SF_HI: - case VOID_FTYPE_PV8DI_V8DI_QI: - case VOID_FTYPE_PV16SI_V16SI_HI: case VOID_FTYPE_PDOUBLE_V2DF_QI: case VOID_FTYPE_PFLOAT_V4SF_QI: nargs = 2; @@ -34459,6 +34484,19 @@ ix86_expand_special_args_builtin (const struct builtin_description *d, nargs = 3; klass = load; memory = 0; + switch (icode) + { + /* These builtins and instructions require the memory + to be properly aligned. */ + case CODE_FOR_avx512f_loadv16sf_mask: + case CODE_FOR_avx512f_loadv16si_mask: + case CODE_FOR_avx512f_loadv8df_mask: + case CODE_FOR_avx512f_loadv8di_mask: + aligned_mem = true; + break; + default: + break; + } break; case VOID_FTYPE_UINT_UINT_UINT: case VOID_FTYPE_UINT64_UINT_UINT: diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index cdaab3684e1c..27151f60ffab 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -2419,6 +2419,9 @@ struct GTY(()) machine_function { stack below the return address. */ BOOL_BITFIELD static_chain_on_stack : 1; + /* If true, it is safe to not save/restore DRAP register. */ + BOOL_BITFIELD no_drap_save_restore : 1; + /* During prologue/epilogue generation, the current frame state. Otherwise, the frame state at the end of the prologue. */ struct machine_frame_state fs; @@ -2507,6 +2510,9 @@ extern void debug_dispatch_window (int); #define IX86_HLE_ACQUIRE (1 << 16) #define IX86_HLE_RELEASE (1 << 17) +/* For switching between functions with different target attributes. */ +#define SWITCHABLE_TARGET 1 + /* Local variables: version-control: t diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index de0b2dd771b9..954bbed2f195 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -366,7 +366,7 @@ ;; Processor type. (define_attr "cpu" "none,pentium,pentiumpro,geode,k6,athlon,k8,core2,nehalem, atom,slm,generic,amdfam10,bdver1,bdver2,bdver3,bdver4, - btver1,btver2" + btver2" (const (symbol_ref "ix86_schedule"))) ;; A basic instruction type. Refinements due to arguments to be diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md index 405f9988d9bf..dfc98ba813ad 100644 --- a/gcc/config/i386/sse.md +++ b/gcc/config/i386/sse.md @@ -786,8 +786,12 @@ { case MODE_V8DF: case MODE_V16SF: + if (misaligned_operand (operands[1], <MODE>mode)) + return "vmovu<ssemodesuffix>\t{%1, %0%{%3%}%N2|%0%{%3%}%N2, %1}"; return "vmova<ssemodesuffix>\t{%1, %0%{%3%}%N2|%0%{%3%}%N2, %1}"; default: + if (misaligned_operand (operands[1], <MODE>mode)) + return "vmovdqu<ssescalarsize>\t{%1, %0%{%3%}%N2|%0%{%3%}%N2, %1}"; return "vmovdqa<ssescalarsize>\t{%1, %0%{%3%}%N2|%0%{%3%}%N2, %1}"; } } @@ -936,11 +940,14 @@ false, still emit UNSPEC_LOADU insn to honor user's request for misaligned load. */ if (TARGET_AVX - && misaligned_operand (operands[1], <MODE>mode) - /* FIXME: Revisit after AVX512F merge is completed. */ - && !<mask_applied>) + && misaligned_operand (operands[1], <MODE>mode)) { - emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1])); + rtx src = operands[1]; + if (<mask_applied>) + src = gen_rtx_VEC_MERGE (<MODE>mode, operands[1], + operands[2 * <mask_applied>], + operands[3 * <mask_applied>]); + emit_insn (gen_rtx_SET (VOIDmode, operands[0], src)); DONE; } }) @@ -1046,11 +1053,14 @@ false, still emit UNSPEC_LOADU insn to honor user's request for misaligned load. */ if (TARGET_AVX - && misaligned_operand (operands[1], <MODE>mode) - /* FIXME: Revisit after AVX512F merge is completed. */ - && !<mask_applied>) + && misaligned_operand (operands[1], <MODE>mode)) { - emit_insn (gen_rtx_SET (VOIDmode, operands[0], operands[1])); + rtx src = operands[1]; + if (<mask_applied>) + src = gen_rtx_VEC_MERGE (<MODE>mode, operands[1], + operands[2 * <mask_applied>], + operands[3 * <mask_applied>]); + emit_insn (gen_rtx_SET (VOIDmode, operands[0], src)); DONE; } }) diff --git a/gcc/config/mips/driver-native.c b/gcc/config/mips/driver-native.c index 3f1a8d0151d2..4c2a658c77a7 100644 --- a/gcc/config/mips/driver-native.c +++ b/gcc/config/mips/driver-native.c @@ -58,11 +58,17 @@ host_detect_local_cpu (int argc, const char **argv) if (strncmp (buf, "cpu model", sizeof ("cpu model") - 1) == 0) { if (strstr (buf, "Godson2 V0.2") != NULL - || strstr (buf, "Loongson-2 V0.2") != NULL) + || strstr (buf, "Loongson-2 V0.2") != NULL + || strstr (buf, "Loongson-2E") != NULL) cpu = "loongson2e"; else if (strstr (buf, "Godson2 V0.3") != NULL - || strstr (buf, "Loongson-2 V0.3") != NULL) + || strstr (buf, "Loongson-2 V0.3") != NULL + || strstr (buf, "Loongson-2F") != NULL) cpu = "loongson2f"; + else if (strstr (buf, "Godson3 V0.5") != NULL + || strstr (buf, "Loongson-3 V0.5") != NULL + || strstr (buf, "Loongson-3A") != NULL) + cpu = "loongson3a"; else if (strstr (buf, "SiByte SB1") != NULL) cpu = "sb1"; else if (strstr (buf, "R5000") != NULL) diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index aa1a5ea385ec..617391cdcb11 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -3634,17 +3634,6 @@ mips_set_reg_reg_cost (enum machine_mode mode) } } -/* Return the cost of an operand X that can be trucated for free. - SPEED says whether we're optimizing for size or speed. */ - -static int -mips_truncated_op_cost (rtx x, bool speed) -{ - if (GET_CODE (x) == TRUNCATE) - x = XEXP (x, 0); - return set_src_cost (x, speed); -} - /* Implement TARGET_RTX_COSTS. */ static bool @@ -4037,13 +4026,12 @@ mips_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED, case ZERO_EXTEND: if (outer_code == SET && ISA_HAS_BADDU + && (GET_CODE (XEXP (x, 0)) == TRUNCATE + || GET_CODE (XEXP (x, 0)) == SUBREG) && GET_MODE (XEXP (x, 0)) == QImode - && GET_CODE (XEXP (x, 0)) == PLUS) + && GET_CODE (XEXP (XEXP (x, 0), 0)) == PLUS) { - rtx plus = XEXP (x, 0); - *total = (COSTS_N_INSNS (1) - + mips_truncated_op_cost (XEXP (plus, 0), speed) - + mips_truncated_op_cost (XEXP (plus, 1), speed)); + *total = set_src_cost (XEXP (XEXP (x, 0), 0), speed); return true; } *total = mips_zero_extend_cost (mode, XEXP (x, 0)); diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index acbf6a31d7fc..bc9d301291c6 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -2529,7 +2529,9 @@ typedef struct mips_args { : TARGET_MICROMIPS && !TARGET_INTERLINK_COMPRESSED \ ? "%*" INSN "r%!\t%" #TARGET_OPNO "%/" \ : "%*" INSN "r\t%" #TARGET_OPNO "%/") \ - : MIPS_ABSOLUTE_JUMP ("%*" INSN "\t%" #TARGET_OPNO "%/")) + : TARGET_MICROMIPS && !TARGET_INTERLINK_COMPRESSED \ + ? MIPS_ABSOLUTE_JUMP ("%*" INSN "%!\t%" #TARGET_OPNO "%/") \ + : MIPS_ABSOLUTE_JUMP ("%*" INSN "\t%" #TARGET_OPNO "%/")) \ /* Similar to MIPS_CALL, but this is for MICROMIPS "j" to generate "jrc" when nop is in the delay slot of "jr". */ diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index 4b0e3b6925e0..fb47a890c4c4 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -1312,20 +1312,32 @@ ;; Combiner patterns for unsigned byte-add. -(define_insn "*baddu_si" +(define_insn "*baddu_si_eb" [(set (match_operand:SI 0 "register_operand" "=d") (zero_extend:SI - (plus:QI (match_operand:QI 1 "register_operand" "d") - (match_operand:QI 2 "register_operand" "d"))))] - "ISA_HAS_BADDU" + (subreg:QI + (plus:SI (match_operand:SI 1 "register_operand" "d") + (match_operand:SI 2 "register_operand" "d")) 3)))] + "ISA_HAS_BADDU && BYTES_BIG_ENDIAN" + "baddu\\t%0,%1,%2" + [(set_attr "alu_type" "add")]) + +(define_insn "*baddu_si_el" + [(set (match_operand:SI 0 "register_operand" "=d") + (zero_extend:SI + (subreg:QI + (plus:SI (match_operand:SI 1 "register_operand" "d") + (match_operand:SI 2 "register_operand" "d")) 0)))] + "ISA_HAS_BADDU && !BYTES_BIG_ENDIAN" "baddu\\t%0,%1,%2" [(set_attr "alu_type" "add")]) (define_insn "*baddu_di<mode>" [(set (match_operand:GPR 0 "register_operand" "=d") (zero_extend:GPR - (plus:QI (truncate:QI (match_operand:DI 1 "register_operand" "d")) - (truncate:QI (match_operand:DI 2 "register_operand" "d")))))] + (truncate:QI + (plus:DI (match_operand:DI 1 "register_operand" "d") + (match_operand:DI 2 "register_operand" "d")))))] "ISA_HAS_BADDU && TARGET_64BIT" "baddu\\t%0,%1,%2" [(set_attr "alu_type" "add")]) @@ -6149,7 +6161,12 @@ (define_insn "*<optab>" [(any_return)] "" - "%*j\t$31%/" + { + if (TARGET_MICROMIPS) + return "%*jr%:\t$31"; + else + return "%*j\t$31%/"; + } [(set_attr "type" "jump") (set_attr "mode" "none")]) diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c index 2c4f6bfcaceb..c3755bfa9122 100644 --- a/gcc/config/pa/pa.c +++ b/gcc/config/pa/pa.c @@ -10424,13 +10424,13 @@ pa_legitimate_address_p (enum machine_mode mode, rtx x, bool strict) /* When INT14_OK_STRICT is false, a secondary reload is needed to adjust the displacement of SImode and DImode floating point - instructions. So, we return false when STRICT is true. We + instructions but this may fail when the register also needs + reloading. So, we return false when STRICT is true. We also reject long displacements for float mode addresses since the majority of accesses will use floating point instructions that don't support 14-bit offsets. */ if (!INT14_OK_STRICT - && reload_in_progress - && strict + && (strict || !(reload_in_progress || reload_completed)) && mode != QImode && mode != HImode) return false; @@ -10490,8 +10490,7 @@ pa_legitimate_address_p (enum machine_mode mode, rtx x, bool strict) return true; if (!INT14_OK_STRICT - && reload_in_progress - && strict + && (strict || !(reload_in_progress || reload_completed)) && mode != QImode && mode != HImode) return false; diff --git a/gcc/config/rs6000/rs6000-builtin.def b/gcc/config/rs6000/rs6000-builtin.def index 4bbccbd7d820..b7b67fae1c8f 100644 --- a/gcc/config/rs6000/rs6000-builtin.def +++ b/gcc/config/rs6000/rs6000-builtin.def @@ -1318,7 +1318,7 @@ BU_P8V_AV_2 (VMRGOW, "vmrgow", CONST, p8_vmrgow) BU_P8V_AV_2 (VPKUDUM, "vpkudum", CONST, altivec_vpkudum) BU_P8V_AV_2 (VPKSDSS, "vpksdss", CONST, altivec_vpksdss) BU_P8V_AV_2 (VPKUDUS, "vpkudus", CONST, altivec_vpkudus) -BU_P8V_AV_2 (VPKSDUS, "vpksdus", CONST, altivec_vpkswus) +BU_P8V_AV_2 (VPKSDUS, "vpksdus", CONST, altivec_vpksdus) BU_P8V_AV_2 (VRLD, "vrld", CONST, vrotlv2di3) BU_P8V_AV_2 (VSLD, "vsld", CONST, vashlv2di3) BU_P8V_AV_2 (VSRD, "vsrd", CONST, vlshrv2di3) @@ -1752,6 +1752,14 @@ BU_SPECIAL_X (RS6000_BUILTIN_GET_TB, "__builtin_ppc_get_timebase", BU_SPECIAL_X (RS6000_BUILTIN_MFTB, "__builtin_ppc_mftb", RS6000_BTM_ALWAYS, RS6000_BTC_MISC) +BU_SPECIAL_X (RS6000_BUILTIN_MFFS, "__builtin_mffs", + RS6000_BTM_ALWAYS, RS6000_BTC_MISC) + +RS6000_BUILTIN_X (RS6000_BUILTIN_MTFSF, "__builtin_mtfsf", + RS6000_BTM_ALWAYS, + RS6000_BTC_MISC | RS6000_BTC_UNARY | RS6000_BTC_VOID, + CODE_FOR_rs6000_mtfsf) + /* Darwin CfString builtin. */ BU_SPECIAL_X (RS6000_BUILTIN_CFSTRING, "__builtin_cfstring", RS6000_BTM_ALWAYS, RS6000_BTC_MISC) diff --git a/gcc/config/rs6000/rs6000-c.c b/gcc/config/rs6000/rs6000-c.c index 3f53d44c0877..51968f8b7fda 100644 --- a/gcc/config/rs6000/rs6000-c.c +++ b/gcc/config/rs6000/rs6000-c.c @@ -611,10 +611,6 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = { RS6000_BTI_V4SI, RS6000_BTI_V8HI, 0, 0 }, { ALTIVEC_BUILTIN_VEC_VUPKHSH, ALTIVEC_BUILTIN_VUPKHSH, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V8HI, 0, 0 }, - { ALTIVEC_BUILTIN_VEC_UNPACKH, P8V_BUILTIN_VUPKHSW, - RS6000_BTI_V2DI, RS6000_BTI_V4SI, 0, 0 }, - { ALTIVEC_BUILTIN_VEC_UNPACKH, P8V_BUILTIN_VUPKHSW, - RS6000_BTI_bool_V2DI, RS6000_BTI_bool_V4SI, 0, 0 }, { ALTIVEC_BUILTIN_VEC_VUPKHSH, P8V_BUILTIN_VUPKHSW, RS6000_BTI_V2DI, RS6000_BTI_V4SI, 0, 0 }, { ALTIVEC_BUILTIN_VEC_VUPKHSH, P8V_BUILTIN_VUPKHSW, diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 687f2f20795f..8eeb2d6de95d 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -78,6 +78,7 @@ #include "tree-vectorizer.h" #include "dumpfile.h" #include "cgraph.h" +#include "target-globals.h" #if TARGET_XCOFF #include "xcoffout.h" /* get declarations of xcoff_*_section_name */ #endif @@ -3238,6 +3239,18 @@ rs6000_option_override_internal (bool global_init_p) && !(processor_target_table[tune_index].target_enable & OPTION_MASK_HTM)) rs6000_isa_flags |= ~rs6000_isa_flags_explicit & OPTION_MASK_STRICT_ALIGN; + /* -maltivec={le,be} implies -maltivec. */ + if (rs6000_altivec_element_order != 0) + rs6000_isa_flags |= OPTION_MASK_ALTIVEC; + + /* Disallow -maltivec=le in big endian mode for now. This is not + known to be useful for anyone. */ + if (BYTES_BIG_ENDIAN && rs6000_altivec_element_order == 1) + { + warning (0, N_("-maltivec=le not allowed for big-endian targets")); + rs6000_altivec_element_order = 0; + } + /* Add some warnings for VSX. */ if (TARGET_VSX) { @@ -6324,13 +6337,14 @@ rs6000_legitimate_offset_address_p (enum machine_mode mode, rtx x, break; case TFmode: - case TDmode: - case TImode: - case PTImode: if (TARGET_E500_DOUBLE) return (SPE_CONST_OFFSET_OK (offset) && SPE_CONST_OFFSET_OK (offset + 8)); + /* fall through */ + case TDmode: + case TImode: + case PTImode: extra = 8; if (!worst_case) break; @@ -11450,6 +11464,48 @@ rs6000_expand_zeroop_builtin (enum insn_code icode, rtx target) static rtx +rs6000_expand_mtfsf_builtin (enum insn_code icode, tree exp) +{ + rtx pat; + tree arg0 = CALL_EXPR_ARG (exp, 0); + tree arg1 = CALL_EXPR_ARG (exp, 1); + rtx op0 = expand_normal (arg0); + rtx op1 = expand_normal (arg1); + enum machine_mode mode0 = insn_data[icode].operand[0].mode; + enum machine_mode mode1 = insn_data[icode].operand[1].mode; + + if (icode == CODE_FOR_nothing) + /* Builtin not supported on this processor. */ + return 0; + + /* If we got invalid arguments bail out before generating bad rtl. */ + if (arg0 == error_mark_node || arg1 == error_mark_node) + return const0_rtx; + + if (GET_CODE (op0) != CONST_INT + || INTVAL (op0) > 255 + || INTVAL (op0) < 0) + { + error ("argument 1 must be an 8-bit field value"); + return const0_rtx; + } + + if (! (*insn_data[icode].operand[0].predicate) (op0, mode0)) + op0 = copy_to_mode_reg (mode0, op0); + + if (! (*insn_data[icode].operand[1].predicate) (op1, mode1)) + op1 = copy_to_mode_reg (mode1, op1); + + pat = GEN_FCN (icode) (op0, op1); + if (! pat) + return const0_rtx; + emit_insn (pat); + + return NULL_RTX; +} + + +static rtx rs6000_expand_unop_builtin (enum insn_code icode, tree exp, rtx target) { rtx pat; @@ -13256,6 +13312,12 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, : CODE_FOR_rs6000_mftb_si), target); + case RS6000_BUILTIN_MFFS: + return rs6000_expand_zeroop_builtin (CODE_FOR_rs6000_mffs, target); + + case RS6000_BUILTIN_MTFSF: + return rs6000_expand_mtfsf_builtin (CODE_FOR_rs6000_mtfsf, exp); + case ALTIVEC_BUILTIN_MASK_FOR_LOAD: case ALTIVEC_BUILTIN_MASK_FOR_STORE: { @@ -13563,6 +13625,14 @@ rs6000_init_builtins (void) NULL_TREE); def_builtin ("__builtin_ppc_mftb", ftype, RS6000_BUILTIN_MFTB); + ftype = build_function_type_list (double_type_node, NULL_TREE); + def_builtin ("__builtin_mffs", ftype, RS6000_BUILTIN_MFFS); + + ftype = build_function_type_list (void_type_node, + intSI_type_node, double_type_node, + NULL_TREE); + def_builtin ("__builtin_mtfsf", ftype, RS6000_BUILTIN_MTFSF); + #if TARGET_XCOFF /* AIX libm provides clog as __clog. */ if ((tdecl = builtin_decl_explicit (BUILT_IN_CLOG)) != NULL_TREE) @@ -31188,16 +31258,25 @@ rs6000_set_current_function (tree fndecl) { cl_target_option_restore (&global_options, TREE_TARGET_OPTION (new_tree)); - target_reinit (); + if (TREE_TARGET_GLOBALS (new_tree)) + restore_target_globals (TREE_TARGET_GLOBALS (new_tree)); + else + TREE_TARGET_GLOBALS (new_tree) + = save_target_globals_default_opts (); } else if (old_tree) { - struct cl_target_option *def - = TREE_TARGET_OPTION (target_option_current_node); - - cl_target_option_restore (&global_options, def); - target_reinit (); + new_tree = target_option_current_node; + cl_target_option_restore (&global_options, + TREE_TARGET_OPTION (new_tree)); + if (TREE_TARGET_GLOBALS (new_tree)) + restore_target_globals (TREE_TARGET_GLOBALS (new_tree)); + else if (new_tree == target_option_default_node) + restore_target_globals (&default_target_globals); + else + TREE_TARGET_GLOBALS (new_tree) + = save_target_globals_default_opts (); } } } diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index 9ebe9abd3ad6..fdfe1c911b57 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -468,6 +468,15 @@ extern int rs6000_vector_align[]; ? rs6000_vector_align[(MODE)] \ : (int)GET_MODE_BITSIZE ((MODE))) +/* Determine the element order to use for vector instructions. By + default we use big-endian element order when targeting big-endian, + and little-endian element order when targeting little-endian. For + programs being ported from BE Power to LE Power, it can sometimes + be useful to use big-endian element order when targeting little-endian. + This is set via -maltivec=be, for example. */ +#define VECTOR_ELT_ORDER_BIG \ + (BYTES_BIG_ENDIAN || (rs6000_altivec_element_order == 2)) + /* Alignment options for fields in structures for sub-targets following AIX-like ABI. ALIGN_POWER word-aligns FP doubles (default AIX ABI). @@ -2437,6 +2446,9 @@ extern char rs6000_reg_names[][8]; /* register names (0 vs. %r0). */ #define PRINT_OPERAND_ADDRESS(FILE, ADDR) print_operand_address (FILE, ADDR) +/* For switching between functions with different target attributes. */ +#define SWITCHABLE_TARGET 1 + /* uncomment for disabling the corresponding default options */ /* #define MACHINE_no_sched_interblock */ /* #define MACHINE_no_sched_speculative */ diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 5605dddafdbb..53c34ad09cc6 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -140,6 +140,8 @@ UNSPECV_ISYNC ; isync instruction UNSPECV_MFTB ; move from time base UNSPECV_NLGR ; non-local goto receiver + UNSPECV_MFFS ; Move from FPSCR + UNSPECV_MTFSF ; Move to FPSCR Fields ]) @@ -15587,6 +15589,20 @@ }) +(define_insn "rs6000_mffs" + [(set (match_operand:DF 0 "gpc_reg_operand" "=d") + (unspec_volatile:DF [(const_int 0)] UNSPECV_MFFS))] + "TARGET_HARD_FLOAT && TARGET_FPRS" + "mffs %0") + +(define_insn "rs6000_mtfsf" + [(unspec_volatile [(match_operand:SI 0 "const_int_operand" "i") + (match_operand:DF 1 "gpc_reg_operand" "d")] + UNSPECV_MTFSF)] + "TARGET_HARD_FLOAT && TARGET_FPRS" + "mtfsf %0,%1") + + ;; Power8 fusion support for fusing an addis instruction with a D-form load of ;; a GPR. The addis instruction must be adjacent to the load, and use the same ;; register that is being loaded. The fused ops must be physically adjacent. diff --git a/gcc/config/rs6000/rs6000.opt b/gcc/config/rs6000/rs6000.opt index fdbc70f9cc63..3240a7516bb9 100644 --- a/gcc/config/rs6000/rs6000.opt +++ b/gcc/config/rs6000/rs6000.opt @@ -140,6 +140,14 @@ maltivec Target Report Mask(ALTIVEC) Var(rs6000_isa_flags) Use AltiVec instructions +maltivec=le +Target Report RejectNegative Var(rs6000_altivec_element_order, 1) Save +Generate Altivec instructions using little-endian element order + +maltivec=be +Target Report RejectNegative Var(rs6000_altivec_element_order, 2) +Generate Altivec instructions using big-endian element order + mhard-dfp Target Report Mask(DFP) Var(rs6000_isa_flags) Use decimal floating point instructions diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index 3d480fd631b2..eeccaedfb08c 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -10005,16 +10005,9 @@ s390_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p, void s390_expand_tbegin (rtx dest, rtx tdb, rtx retry, bool clobber_fprs_p) { - const int CC0 = 1 << 3; - const int CC1 = 1 << 2; - const int CC3 = 1 << 0; - rtx abort_label = gen_label_rtx (); - rtx leave_label = gen_label_rtx (); rtx retry_plus_two = gen_reg_rtx (SImode); rtx retry_reg = gen_reg_rtx (SImode); rtx retry_label = NULL_RTX; - rtx jump; - int very_unlikely = REG_BR_PROB_BASE / 100 - 1; if (retry != NULL_RTX) { @@ -10031,38 +10024,25 @@ s390_expand_tbegin (rtx dest, rtx tdb, rtx retry, bool clobber_fprs_p) emit_insn (gen_tbegin_nofloat_1 (gen_rtx_CONST_INT (VOIDmode, TBEGIN_MASK), tdb)); - jump = s390_emit_jump (abort_label, - gen_rtx_NE (VOIDmode, - gen_rtx_REG (CCRAWmode, CC_REGNUM), - gen_rtx_CONST_INT (VOIDmode, CC0))); - - JUMP_LABEL (jump) = abort_label; - LABEL_NUSES (abort_label) = 1; - add_int_reg_note (jump, REG_BR_PROB, very_unlikely); - - /* Initialize CC return value. */ - emit_move_insn (dest, const0_rtx); - - s390_emit_jump (leave_label, NULL_RTX); - LABEL_NUSES (leave_label) = 1; - emit_barrier (); - - /* Abort handler code. */ - - emit_label (abort_label); emit_move_insn (dest, gen_rtx_UNSPEC (SImode, gen_rtvec (1, gen_rtx_REG (CCRAWmode, CC_REGNUM)), UNSPEC_CC_TO_INT)); if (retry != NULL_RTX) { + const int CC0 = 1 << 3; + const int CC1 = 1 << 2; + const int CC3 = 1 << 0; + rtx jump; rtx count = gen_reg_rtx (SImode); + rtx leave_label = gen_label_rtx (); + + /* Exit for success and permanent failures. */ jump = s390_emit_jump (leave_label, gen_rtx_EQ (VOIDmode, gen_rtx_REG (CCRAWmode, CC_REGNUM), - gen_rtx_CONST_INT (VOIDmode, CC1 | CC3))); - LABEL_NUSES (leave_label) = 2; - add_int_reg_note (jump, REG_BR_PROB, very_unlikely); + gen_rtx_CONST_INT (VOIDmode, CC0 | CC1 | CC3))); + LABEL_NUSES (leave_label) = 1; /* CC2 - transient failure. Perform retry with ppa. */ emit_move_insn (count, retry_plus_two); @@ -10073,9 +10053,8 @@ s390_expand_tbegin (rtx dest, rtx tdb, rtx retry, bool clobber_fprs_p) retry_reg)); JUMP_LABEL (jump) = retry_label; LABEL_NUSES (retry_label) = 1; + emit_label (leave_label); } - - emit_label (leave_label); } /* Builtins. */ diff --git a/gcc/config/sh/sh-mem.cc b/gcc/config/sh/sh-mem.cc index 3dca5f084868..e29ff775449b 100644 --- a/gcc/config/sh/sh-mem.cc +++ b/gcc/config/sh/sh-mem.cc @@ -324,7 +324,6 @@ sh_expand_cmpnstr (rtx *operands) rtx addr2 = operands[2]; rtx s1_addr = copy_addr_to_reg (XEXP (addr1, 0)); rtx s2_addr = copy_addr_to_reg (XEXP (addr2, 0)); - rtx tmp0 = gen_reg_rtx (SImode); rtx tmp1 = gen_reg_rtx (SImode); rtx tmp2 = gen_reg_rtx (SImode); @@ -334,98 +333,132 @@ sh_expand_cmpnstr (rtx *operands) rtx L_end_loop_byte = gen_label_rtx (); 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; + int constp = CONST_INT_P (operands[3]); - /* We could still loop on a register count. Not found very - convincing to optimize yet. */ - if (! constp) - return false; - - if (witers > 1) + /* Loop on a register count. */ + if (constp) { - rtx L_loop_long = gen_label_rtx (); - rtx L_end_loop_long = gen_label_rtx (); + rtx tmp0 = gen_reg_rtx (SImode); 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 (addr1, SImode, s1_addr, 0); - addr2 = adjust_automodify_address (addr2, SImode, s2_addr, 0); - - /* word count. Do we have iterations ? */ - 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)); + rtx L_loop_long = gen_label_rtx (); + rtx L_end_loop_long = gen_label_rtx (); + rtx L_small = gen_label_rtx (); - /* 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)); + int align = INTVAL (operands[4]); + int bytes = INTVAL (operands[3]); + int witers = bytes / 4; + + if (witers > 1) + { + addr1 = adjust_automodify_address (addr1, SImode, s1_addr, 0); + addr2 = adjust_automodify_address (addr2, SImode, s2_addr, 0); + + 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); + } + + /* word count. Do we have iterations ? */ + 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, + GET_MODE_SIZE (SImode))); + + /* tmp1 is aligned, OK to load. */ + emit_move_insn (tmp1, addr1); + emit_move_insn (s1_addr, plus_constant (Pmode, s1_addr, + GET_MODE_SIZE (SImode))); + + /* 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. */ + jump = emit_jump_insn (gen_jump_compact (L_small)); + emit_barrier_after (jump); + } + + emit_label (L_end_loop_long); + + /* Found last word. Restart it byte per byte. */ + bytes = 4; + emit_move_insn (s1_addr, plus_constant (Pmode, s1_addr, + -GET_MODE_SIZE (SImode))); + emit_move_insn (s2_addr, plus_constant (Pmode, s2_addr, + -GET_MODE_SIZE (SImode))); + } + + emit_label (L_small); + + gcc_assert (bytes <= 7); + + addr1 = adjust_automodify_address (addr1, QImode, s1_addr, 0); + addr2 = adjust_automodify_address (addr2, QImode, s2_addr, 0); + + while (bytes--) + { + emit_insn (gen_extendqisi2 (tmp1, addr1)); + emit_insn (gen_extendqisi2 (tmp2, addr2)); + + 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); + + addr1 = adjust_address (addr1, QImode, GET_MODE_SIZE (QImode)); + addr2 = adjust_address (addr2, QImode, GET_MODE_SIZE (QImode)); + } + + jump = emit_jump_insn (gen_jump_compact( L_end_loop_byte)); + emit_barrier_after (jump); } - addr1 = adjust_address (addr1, QImode, 0); - addr2 = adjust_address (addr2, QImode, 0); + addr1 = adjust_automodify_address (addr1, QImode, s1_addr, 0); + addr2 = adjust_automodify_address (addr2, QImode, s2_addr, 0); emit_label (L_loop_byte); diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 70211081dbf1..9213de72d1b4 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,61 @@ +2014-01-09 Balaji V. Iyer <balaji.v.iyer@intel.com> + + PR c++/59631 + * parser.c (cp_parser_postfix_expression): Added a new if-statement + and replaced an existing if-statement with else-if statement. + Changed an existing error message wording to match the one from the C + parser. + +2014-01-08 Jason Merrill <jason@redhat.com> + + PR c++/59614 + * class.c (abi_tag_data): Add tags field. + (check_abi_tags): Initialize it. + (find_abi_tags_r): Support collecting missing tags. + (mark_type_abi_tags): Don't look at template args. + (inherit_targ_abi_tags): New. + (check_bases_and_members): Use it. + * cp-tree.h (ABI_TAG_IMPLICIT): New. + * mangle.c (write_abi_tags): Check it. + +2014-01-07 Jason Merrill <jason@redhat.com> + + PR c++/58856 + * pt.c (num_innermost_template_parms): New. + (get_underlying_template): Use it. + + PR c++/58965 + * mangle.c (write_guarded_var_name): Handle null DECL_NAME. + +2014-01-07 Paolo Carlini <paolo.carlini@oracle.com> + + * semantics.c (trait_expr_value, [CPTK_IS_BASE_OF]): Implement + the letter of 20.11.6 about Base and Derived naming the same + class type modulo cv-qualifiers. + +2014-01-06 Adam Butcher <adam@jessamine.co.uk> + + PR c++/59635 + * lambda.c (maybe_add_lambda_conv_op): Handle marking conversion + function as unimplemented for generic lambdas with varargs. + + PR c++/59636 + * parser.c (cp_parser_template_parameter): Early out with + error_mark_node if parameter declaration was not parsed. + + PR c++/59629 + * parser.c (cp_parser_lambda_expression): Save/reset/restore + auto_is_implicit_function_template_parm_p around lambda body. + + PR c++/59638 + * parser.c (cp_parser_init_declarator): Undo fully implicit + template parameter list when declarator is not a function. + +2014-01-03 Marc Glisse <marc.glisse@inria.fr> + + PR c++/58950 + * cvt.c (convert_to_void): Handle VEC_PERM_EXPR and VEC_COND_EXPR. + 2014-01-03 Tobias Burnus <burnus@net-b.de> PR c++/58567 diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 1f07b97a6158..4dbe3a67b8ca 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -1341,14 +1341,20 @@ struct abi_tag_data { tree t; tree subob; + // error_mark_node to get diagnostics; otherwise collect missing tags here + tree tags; }; static tree -find_abi_tags_r (tree *tp, int */*walk_subtrees*/, void *data) +find_abi_tags_r (tree *tp, int *walk_subtrees, void *data) { if (!OVERLOAD_TYPE_P (*tp)) return NULL_TREE; + /* walk_tree shouldn't be walking into any subtrees of a RECORD_TYPE + anyway, but let's make sure of it. */ + *walk_subtrees = false; + if (tree attributes = lookup_attribute ("abi_tag", TYPE_ATTRIBUTES (*tp))) { struct abi_tag_data *p = static_cast<struct abi_tag_data*>(data); @@ -1359,7 +1365,20 @@ find_abi_tags_r (tree *tp, int */*walk_subtrees*/, void *data) tree id = get_identifier (TREE_STRING_POINTER (tag)); if (!IDENTIFIER_MARKED (id)) { - if (TYPE_P (p->subob)) + if (p->tags != error_mark_node) + { + /* We're collecting tags from template arguments. */ + tree str = build_string (IDENTIFIER_LENGTH (id), + IDENTIFIER_POINTER (id)); + p->tags = tree_cons (NULL_TREE, str, p->tags); + ABI_TAG_IMPLICIT (p->tags) = true; + + /* Don't inherit this tag multiple times. */ + IDENTIFIER_MARKED (id) = true; + } + + /* Otherwise we're diagnosing missing tags. */ + else if (TYPE_P (p->subob)) { warning (OPT_Wabi_tag, "%qT does not have the %E abi tag " "that base %qT has", p->t, tag, p->subob); @@ -1398,22 +1417,6 @@ mark_type_abi_tags (tree t, bool val) IDENTIFIER_MARKED (id) = val; } } - - /* Also mark ABI tags from template arguments. */ - if (CLASSTYPE_TEMPLATE_INFO (t)) - { - tree args = CLASSTYPE_TI_ARGS (t); - for (int i = 0; i < TMPL_ARGS_DEPTH (args); ++i) - { - tree level = TMPL_ARGS_LEVEL (args, i+1); - for (int j = 0; j < TREE_VEC_LENGTH (level); ++j) - { - tree arg = TREE_VEC_ELT (level, j); - if (CLASS_TYPE_P (arg)) - mark_type_abi_tags (arg, val); - } - } - } } /* Check that class T has all the abi tags that subobject SUBOB has, or @@ -1425,13 +1428,50 @@ check_abi_tags (tree t, tree subob) mark_type_abi_tags (t, true); tree subtype = TYPE_P (subob) ? subob : TREE_TYPE (subob); - struct abi_tag_data data = { t, subob }; + struct abi_tag_data data = { t, subob, error_mark_node }; cp_walk_tree_without_duplicates (&subtype, find_abi_tags_r, &data); mark_type_abi_tags (t, false); } +void +inherit_targ_abi_tags (tree t) +{ + if (CLASSTYPE_TEMPLATE_INFO (t) == NULL_TREE) + return; + + mark_type_abi_tags (t, true); + + tree args = CLASSTYPE_TI_ARGS (t); + struct abi_tag_data data = { t, NULL_TREE, NULL_TREE }; + for (int i = 0; i < TMPL_ARGS_DEPTH (args); ++i) + { + tree level = TMPL_ARGS_LEVEL (args, i+1); + for (int j = 0; j < TREE_VEC_LENGTH (level); ++j) + { + tree arg = TREE_VEC_ELT (level, j); + data.subob = arg; + cp_walk_tree_without_duplicates (&arg, find_abi_tags_r, &data); + } + } + + // If we found some tags on our template arguments, add them to our + // abi_tag attribute. + if (data.tags) + { + tree attr = lookup_attribute ("abi_tag", TYPE_ATTRIBUTES (t)); + if (attr) + TREE_VALUE (attr) = chainon (data.tags, TREE_VALUE (attr)); + else + TYPE_ATTRIBUTES (t) + = tree_cons (get_identifier ("abi_tag"), data.tags, + TYPE_ATTRIBUTES (t)); + } + + mark_type_abi_tags (t, false); +} + /* Run through the base classes of T, updating CANT_HAVE_CONST_CTOR_P, and NO_CONST_ASN_REF_P. Also set flag bits in T based on properties of the bases. */ @@ -5432,6 +5472,9 @@ check_bases_and_members (tree t) bool saved_nontrivial_dtor; tree fn; + /* Pick up any abi_tags from our template arguments before checking. */ + inherit_targ_abi_tags (t); + /* By default, we use const reference arguments and generate default constructors. */ cant_have_const_ctor = 0; diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index bdae500d374a..96af562f245e 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -65,6 +65,7 @@ c-common.h, not after. TARGET_EXPR_IMPLICIT_P (in TARGET_EXPR) TEMPLATE_PARM_PARAMETER_PACK (in TEMPLATE_PARM_INDEX) ATTR_IS_DEPENDENT (in the TREE_LIST for an attribute) + ABI_TAG_IMPLICIT (in the TREE_LIST for the argument of abi_tag) CONSTRUCTOR_IS_DIRECT_INIT (in CONSTRUCTOR) LAMBDA_EXPR_CAPTURES_THIS_P (in LAMBDA_EXPR) DECLTYPE_FOR_LAMBDA_CAPTURE (in DECLTYPE_TYPE) @@ -2589,6 +2590,10 @@ struct GTY((variable_size)) lang_decl { must be applied at instantiation time. */ #define ATTR_IS_DEPENDENT(NODE) TREE_LANG_FLAG_0 (TREE_LIST_CHECK (NODE)) +/* In a TREE_LIST in the argument of attribute abi_tag, indicates that the tag + was inherited from a template parameter, not explicitly indicated. */ +#define ABI_TAG_IMPLICIT(NODE) TREE_LANG_FLAG_0 (TREE_LIST_CHECK (NODE)) + extern tree decl_shadowed_for_var_lookup (tree); extern void decl_shadowed_for_var_insert (tree, tree); diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index ca8e7632466b..b413ee854e66 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -1402,7 +1402,9 @@ convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain) || code == PREDECREMENT_EXPR || code == PREINCREMENT_EXPR || code == POSTDECREMENT_EXPR - || code == POSTINCREMENT_EXPR))) + || code == POSTINCREMENT_EXPR)) + || code == VEC_PERM_EXPR + || code == VEC_COND_EXPR) && (complain & tf_warning)) warning_at (loc, OPT_Wunused_value, "value computed is not used"); } diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c index 1855716532af..8bb820d0c3b0 100644 --- a/gcc/cp/lambda.c +++ b/gcc/cp/lambda.c @@ -970,7 +970,7 @@ maybe_add_lambda_conv_op (tree type) the conversion op is used. */ if (varargs_function_p (callop)) { - DECL_DELETED_FN (fn) = 1; + DECL_DELETED_FN (STRIP_TEMPLATE (fn)) = 1; return; } diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index b607811df12a..a1ea7c69a84d 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -1339,6 +1339,8 @@ write_abi_tags (tree tags) for (tree t = tags; t; t = TREE_CHAIN (t)) { + if (ABI_TAG_IMPLICIT (t)) + continue; tree str = TREE_VALUE (t); vec_safe_push (vec, str); } @@ -3770,7 +3772,8 @@ mangle_conv_op_name_for_type (const tree type) static void write_guarded_var_name (const tree variable) { - if (strncmp (IDENTIFIER_POINTER (DECL_NAME (variable)), "_ZGR", 4) == 0) + if (DECL_NAME (variable) + && strncmp (IDENTIFIER_POINTER (DECL_NAME (variable)), "_ZGR", 4) == 0) /* The name of a guard variable for a reference temporary should refer to the reference, not the temporary. */ write_string (IDENTIFIER_POINTER (DECL_NAME (variable)) + 4); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index c99c1fcb6454..c3016bcda4b6 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -5803,7 +5803,13 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, postfix_expression = cp_parser_postfix_expression (parser, false, false, false, false, &idk); - if (saved_in_statement & IN_CILK_SPAWN) + if (!flag_enable_cilkplus) + { + error_at (token->location, "-fcilkplus must be enabled to use" + " %<_Cilk_spawn%>"); + cfun->calls_cilk_spawn = 0; + } + else if (saved_in_statement & IN_CILK_SPAWN) { error_at (token->location, "consecutive %<_Cilk_spawn%> keywords " "are not permitted"); @@ -5830,8 +5836,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, finish_expr_stmt (sync_expr); } else - error_at (input_location, "_Cilk_sync cannot be used without enabling " - "Cilk Plus"); + error_at (token->location, "-fcilkplus must be enabled to use" + " %<_Cilk_sync%>"); cp_lexer_consume_token (parser->lexer); break; @@ -8738,6 +8744,8 @@ cp_parser_lambda_expression (cp_parser* parser) = parser->fully_implicit_function_template_p; tree implicit_template_parms = parser->implicit_template_parms; cp_binding_level* implicit_template_scope = parser->implicit_template_scope; + bool auto_is_implicit_function_template_parm_p + = parser->auto_is_implicit_function_template_parm_p; parser->num_template_parameter_lists = 0; parser->in_statement = 0; @@ -8745,6 +8753,7 @@ cp_parser_lambda_expression (cp_parser* parser) parser->fully_implicit_function_template_p = false; parser->implicit_template_parms = 0; parser->implicit_template_scope = 0; + parser->auto_is_implicit_function_template_parm_p = false; /* By virtue of defining a local class, a lambda expression has access to the private variables of enclosing classes. */ @@ -8772,6 +8781,8 @@ cp_parser_lambda_expression (cp_parser* parser) = fully_implicit_function_template_p; parser->implicit_template_parms = implicit_template_parms; parser->implicit_template_scope = implicit_template_scope; + parser->auto_is_implicit_function_template_parm_p + = auto_is_implicit_function_template_parm_p; } pop_deferring_access_checks (); @@ -12977,20 +12988,21 @@ cp_parser_template_parameter (cp_parser* parser, bool *is_non_type, = cp_parser_parameter_declaration (parser, /*template_parm_p=*/true, /*parenthesized_p=*/NULL); + if (!parameter_declarator) + return error_mark_node; + /* If the parameter declaration is marked as a parameter pack, set *IS_PARAMETER_PACK to notify the caller. Also, unmark the declarator's PACK_EXPANSION_P, otherwise we'll get errors from grokdeclarator. */ - if (parameter_declarator - && parameter_declarator->declarator + if (parameter_declarator->declarator && parameter_declarator->declarator->parameter_pack_p) { *is_parameter_pack = true; parameter_declarator->declarator->parameter_pack_p = false; } - if (parameter_declarator - && parameter_declarator->default_argument) + if (parameter_declarator->default_argument) { /* Can happen in some cases of erroneous input (c++/34892). */ if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS)) @@ -13014,8 +13026,7 @@ cp_parser_template_parameter (cp_parser* parser, bool *is_non_type, /* We might end up with a pack expansion as the type of the non-type template parameter, in which case this is a non-type template parameter pack. */ - else if (parameter_declarator - && parameter_declarator->decl_specifiers.type + else if (parameter_declarator->decl_specifiers.type && PACK_EXPANSION_P (parameter_declarator->decl_specifiers.type)) { *is_parameter_pack = true; @@ -16775,6 +16786,15 @@ cp_parser_init_declarator (cp_parser* parser, warning (OPT_Wattributes, "attributes after parenthesized initializer ignored"); + /* A non-template declaration involving a function parameter list containing + an implicit template parameter will have been made into a template. If it + turns out that the resulting declaration is not an actual function then + finish the template declaration here. An error message will already have + been issued. */ + if (parser->fully_implicit_function_template_p) + if (!function_declarator_p (declarator)) + finish_fully_implicit_template (parser, /*member_decl_opt=*/0); + /* For an in-class declaration, use `grokfield' to create the declaration. */ if (member_p) diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 98d7365a7cca..2e7cf60ba7dd 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -5149,6 +5149,15 @@ alias_template_specialization_p (const_tree t) && DECL_ALIAS_TEMPLATE_P (TYPE_TI_TEMPLATE (t))); } +/* Return the number of innermost template parameters in TMPL. */ + +static int +num_innermost_template_parms (tree tmpl) +{ + tree parms = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (tmpl)); + return TREE_VEC_LENGTH (parms); +} + /* Return either TMPL or another template that it is equivalent to under DR 1286: An alias that just changes the name of a template is equivalent to the other template. */ @@ -5164,6 +5173,8 @@ get_underlying_template (tree tmpl) { tree sub = TYPE_TI_TEMPLATE (result); if (PRIMARY_TEMPLATE_P (sub) + && (num_innermost_template_parms (tmpl) + == num_innermost_template_parms (sub)) && same_type_p (result, TREE_TYPE (sub))) { /* The alias type is equivalent to the pattern of the diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 0bb64c7752b5..9f878874e6d7 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -7106,7 +7106,8 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2) case CPTK_IS_BASE_OF: return (NON_UNION_CLASS_TYPE_P (type1) && NON_UNION_CLASS_TYPE_P (type2) - && DERIVED_FROM_P (type1, type2)); + && (same_type_ignoring_top_level_qualifiers_p (type1, type2) + || DERIVED_FROM_P (type1, type2))); case CPTK_IS_CLASS: return (NON_UNION_CLASS_TYPE_P (type1)); diff --git a/gcc/doc/implement-c.texi b/gcc/doc/implement-c.texi index 2ddae637dec5..762ffe018de0 100644 --- a/gcc/doc/implement-c.texi +++ b/gcc/doc/implement-c.texi @@ -479,9 +479,8 @@ by the @option{-funsigned-bitfields} option. @cite{Allowable bit-field types other than @code{_Bool}, @code{signed int}, and @code{unsigned int} (C99 and C11 6.7.2.1).} -No other types are permitted in strictly conforming mode. -@c Would it be better to restrict the pedwarn for other types to C90 -@c mode and document the other types for C99/C11 mode? +Other integer types, such as @code{long int}, and enumerated types are +permitted even in strictly conforming mode. @item @cite{Whether atomic types are permitted for bit-fields (C11 6.7.2.1).} diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index ae4d52976465..9e16b3b14229 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -10065,6 +10065,41 @@ The default choice depends on the target. Set the maximum number of existing candidates that will be considered when seeking a basis for a new straight-line strength reduction candidate. +@item asan-globals +Enable buffer overflow detection for global objects. This kind +of protection is enabled by default if you are using +@option{-fsanitize=address} option. +To disable global objects protection use @option{--param asan-globals=0}. + +@item asan-stack +Enable buffer overflow detection for stack objects. This kind of +protection is enabled by default when using@option{-fsanitize=address}. +To disable stack protection use @option{--param asan-stack=0} option. + +@item asan-instrument-reads +Enable buffer overflow detection for memory reads. This kind of +protection is enabled by default when using @option{-fsanitize=address}. +To disable memory reads protection use +@option{--param asan-instrument-reads=0}. + +@item asan-instrument-writes +Enable buffer overflow detection for memory writes. This kind of +protection is enabled by default when using @option{-fsanitize=address}. +To disable memory writes protection use +@option{--param asan-instrument-writes=0} option. + +@item asan-memintrin +Enable detection for built-in functions. This kind of protection +is enabled by default when using @option{-fsanitize=address}. +To disable built-in functions protection use +@option{--param asan-memintrin=0}. + +@item asan-use-after-return +Enable detection of use-after-return. This kind of protection +is enabled by default when using @option{-fsanitize=address} option. +To disable use-after-return detection use +@option{--param asan-use-after-return=0}. + @end table @end table @@ -18855,6 +18890,38 @@ the AltiVec instruction set. You may also need to set @option{-mabi=altivec} to adjust the current ABI with AltiVec ABI enhancements. +When @option{-maltivec} is used, rather than @option{-maltivec=le} or +@option{-maltivec=be}, the element order for Altivec intrinsics such +as @code{vec_splat}, @code{vec_extract}, and @code{vec_insert} will +match array element order corresponding to the endianness of the +target. That is, element zero identifies the leftmost element in a +vector register when targeting a big-endian platform, and identifies +the rightmost element in a vector register when targeting a +little-endian platform. + +@item -maltivec=be +@opindex maltivec=be +Generate Altivec instructions using big-endian element order, +regardless of whether the target is big- or little-endian. This is +the default when targeting a big-endian platform. + +The element order is used to interpret element numbers in Altivec +intrinsics such as @code{vec_splat}, @code{vec_extract}, and +@code{vec_insert}. By default, these will match array element order +corresponding to the endianness for the target. + +@item -maltivec=le +@opindex maltivec=le +Generate Altivec instructions using little-endian element order, +regardless of whether the target is big- or little-endian. This is +the default when targeting a little-endian platform. This option is +currently ignored when targeting a big-endian platform. + +The element order is used to interpret element numbers in Altivec +intrinsics such as @code{vec_splat}, @code{vec_extract}, and +@code{vec_insert}. By default, these will match array element order +corresponding to the endianness for the target. + @item -mvrsave @itemx -mno-vrsave @opindex mvrsave diff --git a/gcc/doc/tree-ssa.texi b/gcc/doc/tree-ssa.texi index 391dba89e5d2..e0238bd218a9 100644 --- a/gcc/doc/tree-ssa.texi +++ b/gcc/doc/tree-ssa.texi @@ -53,9 +53,6 @@ variable has aliases. All these attributes are stored in data structures called annotations which are then linked to the field @code{ann} in @code{struct tree_common}. -Presently, we define annotations for variables (@code{var_ann_t}). -Annotations are defined and documented in @file{tree-flow.h}. - @node SSA Operands @section SSA Operands diff --git a/gcc/expr.c b/gcc/expr.c index 28d84b46becc..756edbe92362 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -5294,7 +5294,7 @@ store_expr (tree exp, rtx target, int call_param_p, bool nontemporal) temp = expand_expr_real (exp, tmp_target, GET_MODE (target), (call_param_p ? EXPAND_STACK_PARM : EXPAND_NORMAL), - &alt_rtl); + &alt_rtl, false); } /* If TEMP is a VOIDmode constant and the mode of the type of EXP is not @@ -7882,11 +7882,21 @@ expand_constructor (tree exp, rtx target, enum expand_modifier modifier, address, and ALT_RTL is non-NULL, then *ALT_RTL is set to the DECL_RTL of the VAR_DECL. *ALT_RTL is also set if EXP is a COMPOUND_EXPR whose second argument is such a VAR_DECL, and so on - recursively. */ + recursively. + + If INNER_REFERENCE_P is true, we are expanding an inner reference. + In this case, we don't adjust a returned MEM rtx that wouldn't be + sufficiently aligned for its mode; instead, it's up to the caller + to deal with it afterwards. This is used to make sure that unaligned + base objects for which out-of-bounds accesses are supported, for + example record types with trailing arrays, aren't realigned behind + the back of the caller. + The normal operating mode is to pass FALSE for this parameter. */ rtx expand_expr_real (tree exp, rtx target, enum machine_mode tmode, - enum expand_modifier modifier, rtx *alt_rtl) + enum expand_modifier modifier, rtx *alt_rtl, + bool inner_reference_p) { rtx ret; @@ -7898,7 +7908,8 @@ expand_expr_real (tree exp, rtx target, enum machine_mode tmode, return ret ? ret : const0_rtx; } - ret = expand_expr_real_1 (exp, target, tmode, modifier, alt_rtl); + ret = expand_expr_real_1 (exp, target, tmode, modifier, alt_rtl, + inner_reference_p); return ret; } @@ -9209,7 +9220,8 @@ stmt_is_replaceable_p (gimple stmt) rtx expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, - enum expand_modifier modifier, rtx *alt_rtl) + enum expand_modifier modifier, rtx *alt_rtl, + bool inner_reference_p) { rtx op0, op1, temp, decl_rtl; tree type; @@ -9355,7 +9367,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, set_curr_insn_location (gimple_location (g)); r = expand_expr_real (gimple_assign_rhs_to_tree (g), target, - tmode, modifier, NULL); + tmode, modifier, NULL, inner_reference_p); set_curr_insn_location (saved_loc); if (REG_P (r) && !REG_EXPR (r)) set_reg_attrs_for_decl_rtl (SSA_NAME_VAR (exp), r); @@ -9580,7 +9592,8 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, case SAVE_EXPR: { tree val = treeop0; - rtx ret = expand_expr_real_1 (val, target, tmode, modifier, alt_rtl); + rtx ret = expand_expr_real_1 (val, target, tmode, modifier, alt_rtl, + inner_reference_p); if (!SAVE_EXPR_RESOLVED_P (exp)) { @@ -9717,6 +9730,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, MEM_VOLATILE_P (temp) = 1; if (modifier != EXPAND_WRITE && modifier != EXPAND_MEMORY + && !inner_reference_p && mode != BLKmode && align < GET_MODE_ALIGNMENT (mode)) { @@ -9942,15 +9956,16 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, computation, since it will need a temporary and TARGET is known to have to do. This occurs in unchecked conversion in Ada. */ orig_op0 = op0 - = expand_expr (tem, - (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE - && COMPLETE_TYPE_P (TREE_TYPE (tem)) - && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem))) - != INTEGER_CST) - && modifier != EXPAND_STACK_PARM - ? target : NULL_RTX), - VOIDmode, - modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier); + = expand_expr_real (tem, + (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE + && COMPLETE_TYPE_P (TREE_TYPE (tem)) + && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem))) + != INTEGER_CST) + && modifier != EXPAND_STACK_PARM + ? target : NULL_RTX), + VOIDmode, + modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier, + NULL, true); /* If the field has a mode, we want to access it in the field's mode, not the computed mode. @@ -10307,14 +10322,15 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, { /* See the normal_inner_ref case for the rationale. */ orig_op0 - = expand_expr (tem, - (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE - && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem))) - != INTEGER_CST) - && modifier != EXPAND_STACK_PARM - ? target : NULL_RTX), - VOIDmode, - modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier); + = expand_expr_real (tem, + (TREE_CODE (TREE_TYPE (tem)) == UNION_TYPE + && (TREE_CODE (TYPE_SIZE (TREE_TYPE (tem))) + != INTEGER_CST) + && modifier != EXPAND_STACK_PARM + ? target : NULL_RTX), + VOIDmode, + modifier == EXPAND_SUM ? EXPAND_NORMAL : modifier, + NULL, true); if (MEM_P (orig_op0)) { @@ -10341,7 +10357,8 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, } if (!op0) - op0 = expand_expr (treeop0, NULL_RTX, VOIDmode, modifier); + op0 = expand_expr_real (treeop0, NULL_RTX, VOIDmode, modifier, + NULL, inner_reference_p); /* If the input and output modes are both the same, we are done. */ if (mode == GET_MODE (op0)) @@ -10408,50 +10425,53 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, op0 = copy_rtx (op0); set_mem_align (op0, MAX (MEM_ALIGN (op0), TYPE_ALIGN (type))); } - else if (mode != BLKmode - && MEM_ALIGN (op0) < GET_MODE_ALIGNMENT (mode) - /* If the target does have special handling for unaligned - loads of mode then use them. */ - && ((icode = optab_handler (movmisalign_optab, mode)) - != CODE_FOR_nothing)) - { - rtx reg, insn; - - op0 = adjust_address (op0, mode, 0); - /* We've already validated the memory, and we're creating a - new pseudo destination. The predicates really can't - fail. */ - reg = gen_reg_rtx (mode); - - /* Nor can the insn generator. */ - insn = GEN_FCN (icode) (reg, op0); - emit_insn (insn); - return reg; - } - else if (STRICT_ALIGNMENT + else if (modifier != EXPAND_WRITE + && modifier != EXPAND_MEMORY + && !inner_reference_p && mode != BLKmode && MEM_ALIGN (op0) < GET_MODE_ALIGNMENT (mode)) { - tree inner_type = TREE_TYPE (treeop0); - HOST_WIDE_INT temp_size - = MAX (int_size_in_bytes (inner_type), - (HOST_WIDE_INT) GET_MODE_SIZE (mode)); - rtx new_rtx - = assign_stack_temp_for_type (mode, temp_size, type); - rtx new_with_op0_mode - = adjust_address (new_rtx, GET_MODE (op0), 0); - - gcc_assert (!TREE_ADDRESSABLE (exp)); - - if (GET_MODE (op0) == BLKmode) - emit_block_move (new_with_op0_mode, op0, - GEN_INT (GET_MODE_SIZE (mode)), - (modifier == EXPAND_STACK_PARM - ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL)); - else - emit_move_insn (new_with_op0_mode, op0); + /* If the target does have special handling for unaligned + loads of mode then use them. */ + if ((icode = optab_handler (movmisalign_optab, mode)) + != CODE_FOR_nothing) + { + rtx reg, insn; + + op0 = adjust_address (op0, mode, 0); + /* We've already validated the memory, and we're creating a + new pseudo destination. The predicates really can't + fail. */ + reg = gen_reg_rtx (mode); + + /* Nor can the insn generator. */ + insn = GEN_FCN (icode) (reg, op0); + emit_insn (insn); + return reg; + } + else if (STRICT_ALIGNMENT) + { + tree inner_type = TREE_TYPE (treeop0); + HOST_WIDE_INT temp_size + = MAX (int_size_in_bytes (inner_type), + (HOST_WIDE_INT) GET_MODE_SIZE (mode)); + rtx new_rtx + = assign_stack_temp_for_type (mode, temp_size, type); + rtx new_with_op0_mode + = adjust_address (new_rtx, GET_MODE (op0), 0); + + gcc_assert (!TREE_ADDRESSABLE (exp)); + + if (GET_MODE (op0) == BLKmode) + emit_block_move (new_with_op0_mode, op0, + GEN_INT (GET_MODE_SIZE (mode)), + (modifier == EXPAND_STACK_PARM + ? BLOCK_OP_CALL_PARM : BLOCK_OP_NORMAL)); + else + emit_move_insn (new_with_op0_mode, op0); - op0 = new_rtx; + op0 = new_rtx; + } } op0 = adjust_address (op0, mode, 0); @@ -10551,7 +10571,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, /* WITH_SIZE_EXPR expands to its first argument. The caller should have pulled out the size to use in whatever context it needed. */ return expand_expr_real (treeop0, original_target, tmode, - modifier, alt_rtl); + modifier, alt_rtl, inner_reference_p); default: return expand_expr_real_2 (&ops, target, tmode, modifier); diff --git a/gcc/expr.h b/gcc/expr.h index a39b98ea5efb..da5d4a6d56fd 100644 --- a/gcc/expr.h +++ b/gcc/expr.h @@ -41,7 +41,8 @@ along with GCC; see the file COPYING3. If not see is a constant that is not a legitimate address. EXPAND_WRITE means we are only going to write to the resulting rtx. EXPAND_MEMORY means we are interested in a memory result, even if - the memory is constant and we could have propagated a constant value. */ + the memory is constant and we could have propagated a constant value, + or the memory is unaligned on a STRICT_ALIGNMENT target. */ enum expand_modifier {EXPAND_NORMAL = 0, EXPAND_STACK_PARM, EXPAND_SUM, EXPAND_CONST_ADDRESS, EXPAND_INITIALIZER, EXPAND_WRITE, EXPAND_MEMORY}; @@ -437,9 +438,9 @@ extern rtx force_operand (rtx, rtx); /* Work horses for expand_expr. */ extern rtx expand_expr_real (tree, rtx, enum machine_mode, - enum expand_modifier, rtx *); + enum expand_modifier, rtx *, bool); extern rtx expand_expr_real_1 (tree, rtx, enum machine_mode, - enum expand_modifier, rtx *); + enum expand_modifier, rtx *, bool); extern rtx expand_expr_real_2 (sepops, rtx, enum machine_mode, enum expand_modifier); @@ -450,13 +451,13 @@ static inline rtx expand_expr (tree exp, rtx target, enum machine_mode mode, enum expand_modifier modifier) { - return expand_expr_real (exp, target, mode, modifier, NULL); + return expand_expr_real (exp, target, mode, modifier, NULL, false); } static inline rtx expand_normal (tree exp) { - return expand_expr_real (exp, NULL_RTX, VOIDmode, EXPAND_NORMAL, NULL); + return expand_expr_real (exp, NULL_RTX, VOIDmode, EXPAND_NORMAL, NULL, false); } /* At the start of a function, record that we have no previously-pushed diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 202c0479e426..f2f1a853ddfc 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,38 @@ +2014-01-12 Janus Weil <janus@gcc.gnu.org> + + PR fortran/58026 + * decl.c (gfc_match_data_decl): Improve error recovery. + +2014-01-09 Tobias Burnus <burnus@net-b.de> + + * cpp.c (gfc_cpp_handle_option): Add missing break. + * trans-io.c (transfer_expr): Silence unused value warning. + +2014-01-08 Janus Weil <janus@gcc.gnu.org> + + PR fortran/58182 + * resolve.c (gfc_verify_binding_labels): Modify order of checks. + +2014-01-06 Janus Weil <janus@gcc.gnu.org> + + PR fortran/59589 + * class.c (comp_is_finalizable): New function to dermine if a given + component is finalizable. + (finalize_component, generate_finalization_wrapper): Use it. + +2014-01-06 Janus Weil <janus@gcc.gnu.org> + + PR fortran/59023 + PR fortran/59662 + * resolve.c (resolve_global_procedure): Don't apply to c-binding + procedures. + (gfc_verify_binding_labels): Remove duplicate line. + +2014-01-04 Janus Weil <janus@gcc.gnu.org> + + PR fortran/59547 + * class.c (add_proc_comp): Copy pure attribute. + 2014-01-02 Richard Sandiford <rdsandiford@googlemail.com> Update copyright years diff --git a/gcc/fortran/class.c b/gcc/fortran/class.c index 47a308257eba..d3569fd6ba89 100644 --- a/gcc/fortran/class.c +++ b/gcc/fortran/class.c @@ -714,9 +714,11 @@ add_proc_comp (gfc_symbol *vtype, const char *name, gfc_typebound_proc *tb) if (tb->u.specific) { - c->ts.interface = tb->u.specific->n.sym; + gfc_symbol *ifc = tb->u.specific->n.sym; + c->ts.interface = ifc; if (!tb->deferred) c->initializer = gfc_get_variable_expr (tb->u.specific); + c->attr.pure = ifc->attr.pure; } } @@ -785,6 +787,25 @@ has_finalizer_component (gfc_symbol *derived) } +static bool +comp_is_finalizable (gfc_component *comp) +{ + if (comp->attr.allocatable && comp->ts.type != BT_CLASS) + return true; + else if (comp->ts.type == BT_DERIVED && !comp->attr.pointer + && (comp->ts.u.derived->attr.alloc_comp + || has_finalizer_component (comp->ts.u.derived) + || (comp->ts.u.derived->f2k_derived + && comp->ts.u.derived->f2k_derived->finalizers))) + return true; + else if (comp->ts.type == BT_CLASS && CLASS_DATA (comp) + && CLASS_DATA (comp)->attr.allocatable) + return true; + else + return false; +} + + /* Call DEALLOCATE for the passed component if it is allocatable, if it is neither allocatable nor a pointer but has a finalizer, call it. If it is a nonpointer component with allocatable components or has finalizers, walk @@ -801,19 +822,7 @@ finalize_component (gfc_expr *expr, gfc_symbol *derived, gfc_component *comp, gfc_expr *e; gfc_ref *ref; - if (comp->ts.type != BT_DERIVED && comp->ts.type != BT_CLASS - && !comp->attr.allocatable) - return; - - if ((comp->ts.type == BT_DERIVED && comp->attr.pointer) - || (comp->ts.type == BT_CLASS && CLASS_DATA (comp) - && CLASS_DATA (comp)->attr.pointer)) - return; - - if (comp->ts.type == BT_DERIVED && !comp->attr.allocatable - && (comp->ts.u.derived->f2k_derived == NULL - || comp->ts.u.derived->f2k_derived->finalizers == NULL) - && !has_finalizer_component (comp->ts.u.derived)) + if (!comp_is_finalizable (comp)) return; e = gfc_copy_expr (expr); @@ -1460,17 +1469,7 @@ generate_finalization_wrapper (gfc_symbol *derived, gfc_namespace *ns, && ancestor_wrapper && ancestor_wrapper->expr_type != EXPR_NULL) continue; - if (comp->ts.type != BT_CLASS && !comp->attr.pointer - && (comp->attr.allocatable - || (comp->ts.type == BT_DERIVED - && (comp->ts.u.derived->attr.alloc_comp - || has_finalizer_component (comp->ts.u.derived) - || (comp->ts.u.derived->f2k_derived - && comp->ts.u.derived->f2k_derived->finalizers))))) - finalizable_comp = true; - else if (comp->ts.type == BT_CLASS && CLASS_DATA (comp) - && CLASS_DATA (comp)->attr.allocatable) - finalizable_comp = true; + finalizable_comp |= comp_is_finalizable (comp); } /* If there is no new finalizer and no new allocatable, return with diff --git a/gcc/fortran/cpp.c b/gcc/fortran/cpp.c index 37bc13b388ed..68ce91ffdbf5 100644 --- a/gcc/fortran/cpp.c +++ b/gcc/fortran/cpp.c @@ -363,6 +363,7 @@ gfc_cpp_handle_option (size_t scode, const char *arg, int value ATTRIBUTE_UNUSED case OPT_Wdate_time: gfc_cpp_option.warn_date_time = value; + break; case OPT_A: case OPT_D: diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c index e8ac941a0825..8831b1997bd6 100644 --- a/gcc/fortran/decl.c +++ b/gcc/fortran/decl.c @@ -4287,12 +4287,10 @@ gfc_match_data_decl (void) || current_ts.u.derived->attr.zero_comp)) goto ok; - /* Now we have an error, which we signal, and then fix up - because the knock-on is plain and simple confusing. */ - gfc_error_now ("Derived type at %C has not been previously defined " - "and so cannot appear in a derived type definition"); - current_attr.pointer = 1; - goto ok; + gfc_error ("Derived type at %C has not been previously defined " + "and so cannot appear in a derived type definition"); + m = MATCH_ERROR; + goto cleanup; } ok: diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c index 0e80f491abc7..ad088bb73b2e 100644 --- a/gcc/fortran/resolve.c +++ b/gcc/fortran/resolve.c @@ -2351,6 +2351,7 @@ resolve_global_procedure (gfc_symbol *sym, locus *where, if ((sym->attr.if_source == IFSRC_UNKNOWN || sym->attr.if_source == IFSRC_IFBODY) && gsym->type != GSYM_UNKNOWN + && !gsym->binding_label && gsym->ns && gsym->ns->resolved != -1 && gsym->ns->proc_name @@ -10163,7 +10164,6 @@ gfc_verify_binding_labels (gfc_symbol *sym) gsym->where = sym->declared_at; gsym->sym_name = sym->name; gsym->binding_label = sym->binding_label; - gsym->binding_label = sym->binding_label; gsym->ns = sym->ns; gsym->mod_name = module; if (sym->attr.function) @@ -10200,11 +10200,11 @@ gfc_verify_binding_labels (gfc_symbol *sym) && ((gsym->type != GSYM_SUBROUTINE && gsym->type != GSYM_FUNCTION) || (gsym->defined && sym->attr.if_source != IFSRC_IFBODY)) && sym != gsym->ns->proc_name - && (strcmp (gsym->sym_name, sym->name) != 0 - || module != gsym->mod_name + && (module != gsym->mod_name + || strcmp (gsym->sym_name, sym->name) != 0 || (module && strcmp (module, gsym->mod_name) != 0))) { - /* Print an error if the procdure is defined multiple times; we have to + /* Print an error if the procedure is defined multiple times; we have to exclude references to the same procedure via module association or multiple checks for the same procedure. */ gfc_error ("Procedure %s with binding label %s at %L uses the same " diff --git a/gcc/fortran/trans-io.c b/gcc/fortran/trans-io.c index ba27f810d79a..853e77d62f52 100644 --- a/gcc/fortran/trans-io.c +++ b/gcc/fortran/trans-io.c @@ -2152,7 +2152,7 @@ transfer_expr (gfc_se * se, gfc_typespec * ts, tree addr_expr, gfc_code * code) function, if only referenced in an io statement, requires this check (see PR58771). */ if (ts->u.derived->backend_decl == NULL_TREE) - tmp = gfc_typenode_for_spec (ts); + (void) gfc_typenode_for_spec (ts); for (c = ts->u.derived->components; c; c = c->next) { diff --git a/gcc/function.c b/gcc/function.c index 8dcdb3136614..b43e67f65ef6 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -4405,6 +4405,7 @@ invoke_set_current_function_hook (tree fndecl) cl_optimization_restore (&global_options, TREE_OPTIMIZATION (opts)); } + targetm.set_current_function (fndecl); this_fn_optabs = this_target_optabs; if (opts != optimization_default_node) @@ -4414,8 +4415,6 @@ invoke_set_current_function_hook (tree fndecl) this_fn_optabs = (struct target_optabs *) TREE_OPTIMIZATION_OPTABS (opts); } - - targetm.set_current_function (fndecl); } } diff --git a/gcc/gcov-io.c b/gcc/gcov-io.c index ef5120a0c1f3..b710f596e378 100644 --- a/gcc/gcov-io.c +++ b/gcc/gcov-io.c @@ -36,6 +36,61 @@ static const gcov_unsigned_t *gcov_read_words (unsigned); static void gcov_allocate (unsigned); #endif +/* Optimum number of gcov_unsigned_t's read from or written to disk. */ +#define GCOV_BLOCK_SIZE (1 << 10) + +GCOV_LINKAGE struct gcov_var +{ + FILE *file; + gcov_position_t start; /* Position of first byte of block */ + unsigned offset; /* Read/write position within the block. */ + unsigned length; /* Read limit in the block. */ + unsigned overread; /* Number of words overread. */ + int error; /* < 0 overflow, > 0 disk error. */ + int mode; /* < 0 writing, > 0 reading */ +#if IN_LIBGCOV + /* Holds one block plus 4 bytes, thus all coverage reads & writes + fit within this buffer and we always can transfer GCOV_BLOCK_SIZE + to and from the disk. libgcov never backtracks and only writes 4 + or 8 byte objects. */ + gcov_unsigned_t buffer[GCOV_BLOCK_SIZE + 1]; +#else + int endian; /* Swap endianness. */ + /* Holds a variable length block, as the compiler can write + strings and needs to backtrack. */ + size_t alloc; + gcov_unsigned_t *buffer; +#endif +} gcov_var; + +/* Save the current position in the gcov file. */ +static inline gcov_position_t +gcov_position (void) +{ + gcc_assert (gcov_var.mode > 0); + return gcov_var.start + gcov_var.offset; +} + +/* Return nonzero if the error flag is set. */ +static inline int +gcov_is_error (void) +{ + return gcov_var.file ? gcov_var.error : 1; +} + +#if IN_LIBGCOV +/* Move to beginning of file and initialize for writing. */ +GCOV_LINKAGE inline void +gcov_rewrite (void) +{ + gcc_assert (gcov_var.mode > 0); + gcov_var.mode = -1; + gcov_var.start = 0; + gcov_var.offset = 0; + fseek (gcov_var.file, 0L, SEEK_SET); +} +#endif + static inline gcov_unsigned_t from_file (gcov_unsigned_t value) { #if !IN_LIBGCOV diff --git a/gcc/gcov-io.h b/gcc/gcov-io.h index 3d3fd0565872..cbf95cfc5523 100644 --- a/gcc/gcov-io.h +++ b/gcc/gcov-io.h @@ -164,51 +164,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #ifndef GCC_GCOV_IO_H #define GCC_GCOV_IO_H -#if IN_LIBGCOV -/* About the target */ - -#if BITS_PER_UNIT == 8 -typedef unsigned gcov_unsigned_t __attribute__ ((mode (SI))); -typedef unsigned gcov_position_t __attribute__ ((mode (SI))); -#if LONG_LONG_TYPE_SIZE > 32 -typedef signed gcov_type __attribute__ ((mode (DI))); -typedef unsigned gcov_type_unsigned __attribute__ ((mode (DI))); -#else -typedef signed gcov_type __attribute__ ((mode (SI))); -typedef unsigned gcov_type_unsigned __attribute__ ((mode (SI))); -#endif -#else -#if BITS_PER_UNIT == 16 -typedef unsigned gcov_unsigned_t __attribute__ ((mode (HI))); -typedef unsigned gcov_position_t __attribute__ ((mode (HI))); -#if LONG_LONG_TYPE_SIZE > 32 -typedef signed gcov_type __attribute__ ((mode (SI))); -typedef unsigned gcov_type_unsigned __attribute__ ((mode (SI))); -#else -typedef signed gcov_type __attribute__ ((mode (HI))); -typedef unsigned gcov_type_unsigned __attribute__ ((mode (HI))); -#endif -#else -typedef unsigned gcov_unsigned_t __attribute__ ((mode (QI))); -typedef unsigned gcov_position_t __attribute__ ((mode (QI))); -#if LONG_LONG_TYPE_SIZE > 32 -typedef signed gcov_type __attribute__ ((mode (HI))); -typedef unsigned gcov_type_unsigned __attribute__ ((mode (HI))); -#else -typedef signed gcov_type __attribute__ ((mode (QI))); -typedef unsigned gcov_type_unsigned __attribute__ ((mode (QI))); -#endif -#endif -#endif - - -#if defined (TARGET_POSIX_IO) -#define GCOV_LOCKED 1 -#else -#define GCOV_LOCKED 0 -#endif - -#else /* !IN_LIBGCOV */ +#ifndef IN_LIBGCOV /* About the host */ typedef unsigned gcov_unsigned_t; @@ -231,47 +187,9 @@ typedef unsigned HOST_WIDEST_INT gcov_type_unsigned; #define GCOV_LOCKED 0 #endif -#endif /* !IN_LIBGCOV */ - -/* In gcov we want function linkage to be static. In the compiler we want - it extern, so that they can be accessed from elsewhere. In libgcov we - need these functions to be extern, so prefix them with __gcov. In - libgcov they must also be hidden so that the instance in the executable - is not also used in a DSO. */ -#if IN_LIBGCOV - -#include "tconfig.h" - -#define gcov_var __gcov_var -#define gcov_open __gcov_open -#define gcov_close __gcov_close -#define gcov_write_tag_length __gcov_write_tag_length -#define gcov_position __gcov_position -#define gcov_seek __gcov_seek -#define gcov_rewrite __gcov_rewrite -#define gcov_is_error __gcov_is_error -#define gcov_write_unsigned __gcov_write_unsigned -#define gcov_write_counter __gcov_write_counter -#define gcov_write_summary __gcov_write_summary -#define gcov_read_unsigned __gcov_read_unsigned -#define gcov_read_counter __gcov_read_counter -#define gcov_read_summary __gcov_read_summary - -/* Poison these, so they don't accidentally slip in. */ -#pragma GCC poison gcov_write_string gcov_write_tag gcov_write_length -#pragma GCC poison gcov_read_string gcov_sync gcov_time gcov_magic - -#ifdef HAVE_GAS_HIDDEN -#define ATTRIBUTE_HIDDEN __attribute__ ((__visibility__ ("hidden"))) -#else -#define ATTRIBUTE_HIDDEN -#endif - -#else - #define ATTRIBUTE_HIDDEN -#endif +#endif /* !IN_LIBGOCV */ #ifndef GCOV_LINKAGE #define GCOV_LINKAGE extern @@ -442,132 +360,7 @@ struct gcov_summary struct gcov_ctr_summary ctrs[GCOV_COUNTERS_SUMMABLE]; }; -/* Structures embedded in coveraged program. The structures generated - by write_profile must match these. */ - -#if IN_LIBGCOV -/* Information about counters for a single function. */ -struct gcov_ctr_info -{ - gcov_unsigned_t num; /* number of counters. */ - gcov_type *values; /* their values. */ -}; - -/* Information about a single function. This uses the trailing array - idiom. The number of counters is determined from the merge pointer - array in gcov_info. The key is used to detect which of a set of - comdat functions was selected -- it points to the gcov_info object - of the object file containing the selected comdat function. */ - -struct gcov_fn_info -{ - const struct gcov_info *key; /* comdat key */ - gcov_unsigned_t ident; /* unique ident of function */ - gcov_unsigned_t lineno_checksum; /* function lineo_checksum */ - gcov_unsigned_t cfg_checksum; /* function cfg checksum */ - struct gcov_ctr_info ctrs[0]; /* instrumented counters */ -}; - -/* Type of function used to merge counters. */ -typedef void (*gcov_merge_fn) (gcov_type *, gcov_unsigned_t); - -/* Information about a single object file. */ -struct gcov_info -{ - gcov_unsigned_t version; /* expected version number */ - struct gcov_info *next; /* link to next, used by libgcov */ - - gcov_unsigned_t stamp; /* uniquifying time stamp */ - const char *filename; /* output file name */ - - gcov_merge_fn merge[GCOV_COUNTERS]; /* merge functions (null for - unused) */ - - unsigned n_functions; /* number of functions */ - const struct gcov_fn_info *const *functions; /* pointer to pointers - to function information */ -}; - -/* Register a new object file module. */ -extern void __gcov_init (struct gcov_info *) ATTRIBUTE_HIDDEN; - -/* Called before fork, to avoid double counting. */ -extern void __gcov_flush (void) ATTRIBUTE_HIDDEN; - -/* Function to reset all counters to 0. */ -extern void __gcov_reset (void); - -/* Function to enable early write of profile information so far. */ -extern void __gcov_dump (void); - -/* The merge function that just sums the counters. */ -extern void __gcov_merge_add (gcov_type *, unsigned) ATTRIBUTE_HIDDEN; - -/* The merge function to choose the most common value. */ -extern void __gcov_merge_single (gcov_type *, unsigned) ATTRIBUTE_HIDDEN; - -/* The merge function to choose the most common difference between - consecutive values. */ -extern void __gcov_merge_delta (gcov_type *, unsigned) ATTRIBUTE_HIDDEN; - -/* The merge function that just ors the counters together. */ -extern void __gcov_merge_ior (gcov_type *, unsigned) ATTRIBUTE_HIDDEN; - -extern void __gcov_merge_time_profile (gcov_type *, unsigned) ATTRIBUTE_HIDDEN; - -/* The profiler functions. */ -extern void __gcov_interval_profiler (gcov_type *, gcov_type, int, unsigned); -extern void __gcov_pow2_profiler (gcov_type *, gcov_type); -extern void __gcov_one_value_profiler (gcov_type *, gcov_type); -extern void __gcov_indirect_call_profiler (gcov_type*, gcov_type, - void*, void*); -extern void __gcov_indirect_call_profiler_v2 (gcov_type, void *); -extern void __gcov_average_profiler (gcov_type *, gcov_type); -extern void __gcov_ior_profiler (gcov_type *, gcov_type); -extern void __gcov_time_profiler (gcov_type *); - -#ifndef inhibit_libc -/* The wrappers around some library functions.. */ -extern pid_t __gcov_fork (void) ATTRIBUTE_HIDDEN; -extern int __gcov_execl (const char *, char *, ...) ATTRIBUTE_HIDDEN; -extern int __gcov_execlp (const char *, char *, ...) ATTRIBUTE_HIDDEN; -extern int __gcov_execle (const char *, char *, ...) ATTRIBUTE_HIDDEN; -extern int __gcov_execv (const char *, char *const []) ATTRIBUTE_HIDDEN; -extern int __gcov_execvp (const char *, char *const []) ATTRIBUTE_HIDDEN; -extern int __gcov_execve (const char *, char *const [], char *const []) - ATTRIBUTE_HIDDEN; -#endif - -#endif /* IN_LIBGCOV */ - -#if IN_LIBGCOV >= 0 - -/* Optimum number of gcov_unsigned_t's read from or written to disk. */ -#define GCOV_BLOCK_SIZE (1 << 10) - -GCOV_LINKAGE struct gcov_var -{ - FILE *file; - gcov_position_t start; /* Position of first byte of block */ - unsigned offset; /* Read/write position within the block. */ - unsigned length; /* Read limit in the block. */ - unsigned overread; /* Number of words overread. */ - int error; /* < 0 overflow, > 0 disk error. */ - int mode; /* < 0 writing, > 0 reading */ -#if IN_LIBGCOV - /* Holds one block plus 4 bytes, thus all coverage reads & writes - fit within this buffer and we always can transfer GCOV_BLOCK_SIZE - to and from the disk. libgcov never backtracks and only writes 4 - or 8 byte objects. */ - gcov_unsigned_t buffer[GCOV_BLOCK_SIZE + 1]; -#else - int endian; /* Swap endianness. */ - /* Holds a variable length block, as the compiler can write - strings and needs to backtrack. */ - size_t alloc; - gcov_unsigned_t *buffer; -#endif -} gcov_var ATTRIBUTE_HIDDEN; +#if !defined(inhibit_libc) /* Functions for reading and writing gcov files. In libgcov you can open the file for reading then writing. Elsewhere you can open the @@ -578,38 +371,20 @@ GCOV_LINKAGE struct gcov_var you use the functions for reading, then gcov_rewrite then the functions for writing. Your file may become corrupted if you break these invariants. */ -#if IN_LIBGCOV -GCOV_LINKAGE int gcov_open (const char */*name*/) ATTRIBUTE_HIDDEN; -#else + +#if !IN_LIBGCOV GCOV_LINKAGE int gcov_open (const char */*name*/, int /*direction*/); GCOV_LINKAGE int gcov_magic (gcov_unsigned_t, gcov_unsigned_t); #endif -GCOV_LINKAGE int gcov_close (void) ATTRIBUTE_HIDDEN; /* Available everywhere. */ -static gcov_position_t gcov_position (void); -static int gcov_is_error (void); - +GCOV_LINKAGE int gcov_close (void) ATTRIBUTE_HIDDEN; GCOV_LINKAGE gcov_unsigned_t gcov_read_unsigned (void) ATTRIBUTE_HIDDEN; GCOV_LINKAGE gcov_type gcov_read_counter (void) ATTRIBUTE_HIDDEN; GCOV_LINKAGE void gcov_read_summary (struct gcov_summary *) ATTRIBUTE_HIDDEN; - -#if IN_LIBGCOV -/* Available only in libgcov */ -GCOV_LINKAGE void gcov_write_counter (gcov_type) ATTRIBUTE_HIDDEN; -GCOV_LINKAGE void gcov_write_tag_length (gcov_unsigned_t, gcov_unsigned_t) - ATTRIBUTE_HIDDEN; -GCOV_LINKAGE void gcov_write_summary (gcov_unsigned_t /*tag*/, - const struct gcov_summary *) - ATTRIBUTE_HIDDEN; -static void gcov_rewrite (void); -GCOV_LINKAGE void gcov_seek (gcov_position_t /*position*/) ATTRIBUTE_HIDDEN; -#else -/* Available outside libgcov */ GCOV_LINKAGE const char *gcov_read_string (void); GCOV_LINKAGE void gcov_sync (gcov_position_t /*base*/, gcov_unsigned_t /*length */); -#endif #if !IN_GCOV /* Available outside gcov */ @@ -651,37 +426,6 @@ GCOV_LINKAGE void compute_working_sets (const struct gcov_ctr_summary *summary, GCOV_LINKAGE time_t gcov_time (void); #endif -/* Save the current position in the gcov file. */ - -static inline gcov_position_t -gcov_position (void) -{ - gcc_assert (gcov_var.mode > 0); - return gcov_var.start + gcov_var.offset; -} - -/* Return nonzero if the error flag is set. */ - -static inline int -gcov_is_error (void) -{ - return gcov_var.file ? gcov_var.error : 1; -} - -#if IN_LIBGCOV -/* Move to beginning of file and initialize for writing. */ - -static inline void -gcov_rewrite (void) -{ - gcc_assert (gcov_var.mode > 0); - gcov_var.mode = -1; - gcov_var.start = 0; - gcov_var.offset = 0; - fseek (gcov_var.file, 0L, SEEK_SET); -} -#endif - -#endif /* IN_LIBGCOV >= 0 */ +#endif /* !inhibit_libc */ #endif /* GCC_GCOV_IO_H */ diff --git a/gcc/gdbasan.in b/gcc/gdbasan.in index cf05825395b9..3a6fca0a8acc 100644 --- a/gcc/gdbasan.in +++ b/gcc/gdbasan.in @@ -1,3 +1,7 @@ # Put a breakpoint on __asan_report_error to help with debugging buffer # overflow. b __asan_report_error + +# Put a breakpoint on __sanitizer::Report to help with debugging sanitizer +# issues. +b __sanitizer::Report diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index 5d5b361501bb..e3c1a5695cc1 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -879,8 +879,6 @@ gimple_fold_builtin (gimple stmt) int nargs; location_t loc = gimple_location (stmt); - gcc_assert (is_gimple_call (stmt)); - ignore = (gimple_call_lhs (stmt) == NULL); /* First try the generic builtin folder. If that succeeds, return the @@ -890,6 +888,8 @@ gimple_fold_builtin (gimple stmt) { if (ignore) STRIP_NOPS (result); + else + result = fold_convert (gimple_call_return_type (stmt), result); return result; } @@ -1167,7 +1167,7 @@ gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace) (OBJ_TYPE_REF_EXPR (callee))))) { fprintf (dump_file, - "Type inheritnace inconsistent devirtualization of "); + "Type inheritance inconsistent devirtualization of "); print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM); fprintf (dump_file, " to "); print_generic_expr (dump_file, callee, TDF_SLIM); @@ -1177,24 +1177,45 @@ gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace) gimple_call_set_fn (stmt, OBJ_TYPE_REF_EXPR (callee)); changed = true; } - else if (flag_devirtualize && virtual_method_call_p (callee)) + else if (flag_devirtualize && !inplace && virtual_method_call_p (callee)) { bool final; vec <cgraph_node *>targets = possible_polymorphic_call_targets (callee, &final); if (final && targets.length () <= 1) { + tree lhs = gimple_call_lhs (stmt); if (targets.length () == 1) { gimple_call_set_fndecl (stmt, targets[0]->decl); changed = true; + /* If the call becomes noreturn, remove the lhs. */ + if (lhs && (gimple_call_flags (stmt) & ECF_NORETURN)) + { + if (TREE_CODE (lhs) == SSA_NAME) + { + tree var = create_tmp_var (TREE_TYPE (lhs), NULL); + tree def = get_or_create_ssa_default_def (cfun, var); + gimple new_stmt = gimple_build_assign (lhs, def); + gsi_insert_before (gsi, new_stmt, GSI_SAME_STMT); + } + gimple_call_set_lhs (stmt, NULL_TREE); + } } - else if (!inplace) + else { tree fndecl = builtin_decl_implicit (BUILT_IN_UNREACHABLE); gimple new_stmt = gimple_build_call (fndecl, 0); gimple_set_location (new_stmt, gimple_location (stmt)); - gsi_insert_before (gsi, new_stmt, GSI_SAME_STMT); + if (lhs && TREE_CODE (lhs) == SSA_NAME) + { + tree var = create_tmp_var (TREE_TYPE (lhs), NULL); + tree def = get_or_create_ssa_default_def (cfun, var); + gsi_insert_before (gsi, new_stmt, GSI_SAME_STMT); + update_call_from_tree (gsi, def); + } + else + gsi_replace (gsi, new_stmt, true); return true; } } @@ -1206,8 +1227,7 @@ gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace) /* Check for builtins that CCP can handle using information not available in the generic fold routines. */ - callee = gimple_call_fndecl (stmt); - if (callee && DECL_BUILT_IN (callee)) + if (gimple_call_builtin_p (stmt)) { tree result = gimple_fold_builtin (stmt); if (result) @@ -1216,7 +1236,7 @@ gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace) gimplify_and_update_call_from_tree (gsi, result); changed = true; } - else if (DECL_BUILT_IN_CLASS (callee) == BUILT_IN_MD) + else if (gimple_call_builtin_p (stmt, BUILT_IN_MD)) changed |= targetm.gimple_fold_builtin (gsi); } @@ -2726,7 +2746,9 @@ gimple_fold_stmt_to_constant_1 (gimple stmt, tree (*valueize) (tree)) fn = (*valueize) (gimple_call_fn (stmt)); if (TREE_CODE (fn) == ADDR_EXPR && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL - && DECL_BUILT_IN (TREE_OPERAND (fn, 0))) + && DECL_BUILT_IN (TREE_OPERAND (fn, 0)) + && gimple_builtin_call_types_compatible_p (stmt, + TREE_OPERAND (fn, 0))) { tree *args = XALLOCAVEC (tree, gimple_call_num_args (stmt)); tree call, retval; @@ -2738,8 +2760,11 @@ gimple_fold_stmt_to_constant_1 (gimple stmt, tree (*valueize) (tree)) fn, gimple_call_num_args (stmt), args); retval = fold_call_expr (EXPR_LOCATION (call), call, false); if (retval) - /* fold_call_expr wraps the result inside a NOP_EXPR. */ - STRIP_NOPS (retval); + { + /* fold_call_expr wraps the result inside a NOP_EXPR. */ + STRIP_NOPS (retval); + retval = fold_convert (gimple_call_return_type (stmt), retval); + } return retval; } return NULL_TREE; diff --git a/gcc/gimple.c b/gcc/gimple.c index 0330c0cc9f38..4d3b99ed9d23 100644 --- a/gcc/gimple.c +++ b/gcc/gimple.c @@ -2351,27 +2351,37 @@ gimple_ior_addresses_taken (bitmap addresses_taken, gimple stmt) } -/* Return TRUE iff stmt is a call to a built-in function. */ +/* Return true if TYPE1 and TYPE2 are compatible enough for builtin + processing. */ -bool -is_gimple_builtin_call (gimple stmt) -{ - tree callee; - - if (is_gimple_call (stmt) - && (callee = gimple_call_fndecl (stmt)) - && is_builtin_fn (callee) - && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL) - return true; - - return false; +static bool +validate_type (tree type1, tree type2) +{ + if (INTEGRAL_TYPE_P (type1) + && INTEGRAL_TYPE_P (type2)) + ; + else if (POINTER_TYPE_P (type1) + && POINTER_TYPE_P (type2)) + ; + else if (TREE_CODE (type1) + != TREE_CODE (type2)) + return false; + return true; } -/* Return true when STMTs arguments match those of FNDECL. */ +/* Return true when STMTs arguments and return value match those of FNDECL, + a decl of a builtin function. */ -static bool -validate_call (gimple stmt, tree fndecl) +bool +gimple_builtin_call_types_compatible_p (gimple stmt, tree fndecl) { + gcc_checking_assert (DECL_BUILT_IN_CLASS (fndecl) != NOT_BUILT_IN); + + tree ret = gimple_call_lhs (stmt); + if (ret + && !validate_type (TREE_TYPE (ret), TREE_TYPE (TREE_TYPE (fndecl)))) + return false; + tree targs = TYPE_ARG_TYPES (TREE_TYPE (fndecl)); unsigned nargs = gimple_call_num_args (stmt); for (unsigned i = 0; i < nargs; ++i) @@ -2380,14 +2390,7 @@ validate_call (gimple stmt, tree fndecl) if (!targs) return true; tree arg = gimple_call_arg (stmt, i); - if (INTEGRAL_TYPE_P (TREE_TYPE (arg)) - && INTEGRAL_TYPE_P (TREE_VALUE (targs))) - ; - else if (POINTER_TYPE_P (TREE_TYPE (arg)) - && POINTER_TYPE_P (TREE_VALUE (targs))) - ; - else if (TREE_CODE (TREE_TYPE (arg)) - != TREE_CODE (TREE_VALUE (targs))) + if (!validate_type (TREE_TYPE (arg), TREE_VALUE (targs))) return false; targs = TREE_CHAIN (targs); } @@ -2396,6 +2399,19 @@ validate_call (gimple stmt, tree fndecl) return true; } +/* Return true when STMT is builtins call. */ + +bool +gimple_call_builtin_p (gimple stmt) +{ + tree fndecl; + if (is_gimple_call (stmt) + && (fndecl = gimple_call_fndecl (stmt)) != NULL_TREE + && DECL_BUILT_IN_CLASS (fndecl) != NOT_BUILT_IN) + return gimple_builtin_call_types_compatible_p (stmt, fndecl); + return false; +} + /* Return true when STMT is builtins call to CLASS. */ bool @@ -2405,7 +2421,7 @@ gimple_call_builtin_p (gimple stmt, enum built_in_class klass) if (is_gimple_call (stmt) && (fndecl = gimple_call_fndecl (stmt)) != NULL_TREE && DECL_BUILT_IN_CLASS (fndecl) == klass) - return validate_call (stmt, fndecl); + return gimple_builtin_call_types_compatible_p (stmt, fndecl); return false; } @@ -2419,7 +2435,7 @@ gimple_call_builtin_p (gimple stmt, enum built_in_function code) && (fndecl = gimple_call_fndecl (stmt)) != NULL_TREE && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL && DECL_FUNCTION_CODE (fndecl) == code) - return validate_call (stmt, fndecl); + return gimple_builtin_call_types_compatible_p (stmt, fndecl); return false; } diff --git a/gcc/gimple.h b/gcc/gimple.h index df92863699be..0e80d2eb7002 100644 --- a/gcc/gimple.h +++ b/gcc/gimple.h @@ -1253,7 +1253,8 @@ extern tree gimple_unsigned_type (tree); extern tree gimple_signed_type (tree); extern alias_set_type gimple_get_alias_set (tree); extern bool gimple_ior_addresses_taken (bitmap, gimple); -extern bool is_gimple_builtin_call (gimple stmt); +extern bool gimple_builtin_call_types_compatible_p (gimple, tree); +extern bool gimple_call_builtin_p (gimple); extern bool gimple_call_builtin_p (gimple, enum built_in_class); extern bool gimple_call_builtin_p (gimple, enum built_in_function); extern bool gimple_asm_clobbers_memory_p (const_gimple); diff --git a/gcc/gimplify.c b/gcc/gimplify.c index a6e0c75478b0..202d084f09fb 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -7373,12 +7373,22 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, TREE_TYPE (*expr_p)); break; + case VIEW_CONVERT_EXPR: + if (is_gimple_reg_type (TREE_TYPE (*expr_p)) + && is_gimple_reg_type (TREE_TYPE (TREE_OPERAND (*expr_p, 0)))) + { + ret = gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, + post_p, is_gimple_val, fb_rvalue); + recalculate_side_effects (*expr_p); + break; + } + /* Fallthru. */ + case ARRAY_REF: case ARRAY_RANGE_REF: case REALPART_EXPR: case IMAGPART_EXPR: case COMPONENT_REF: - case VIEW_CONVERT_EXPR: ret = gimplify_compound_lval (expr_p, pre_p, post_p, fallback ? fallback : fb_rvalue); break; diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index 2f1c026c9833..6f2f24367aaa 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -3060,6 +3060,9 @@ class Type_conversion_expression : public Expression Expression* do_lower(Gogo*, Named_object*, Statement_inserter*, int); + Expression* + do_flatten(Gogo*, Named_object*, Statement_inserter*); + bool do_is_constant() const; @@ -3203,6 +3206,25 @@ Type_conversion_expression::do_lower(Gogo*, Named_object*, return this; } +// Flatten a type conversion by using a temporary variable for the slice +// in slice to string conversions. + +Expression* +Type_conversion_expression::do_flatten(Gogo*, Named_object*, + Statement_inserter* inserter) +{ + if (this->type()->is_string_type() + && this->expr_->type()->is_slice_type() + && !this->expr_->is_variable()) + { + Temporary_statement* temp = + Statement::make_temporary(NULL, this->expr_, this->location()); + inserter->insert(temp); + this->expr_ = Expression::make_temporary_reference(temp, this->location()); + } + return this; +} + // Return whether a type conversion is a constant. bool @@ -3361,47 +3383,24 @@ Type_conversion_expression::do_get_tree(Translate_context* context) } else if (type->is_string_type() && expr_type->is_slice_type()) { - if (!DECL_P(expr_tree)) - expr_tree = save_expr(expr_tree); - - Type* int_type = Type::lookup_integer_type("int"); - tree int_type_tree = type_to_tree(int_type->get_backend(gogo)); - + Location location = this->location(); Array_type* a = expr_type->array_type(); Type* e = a->element_type()->forwarded(); go_assert(e->integer_type() != NULL); - tree valptr = fold_convert(const_ptr_type_node, - a->value_pointer_tree(gogo, expr_tree)); - tree len = a->length_tree(gogo, expr_tree); - len = fold_convert_loc(this->location().gcc_location(), int_type_tree, - len); + go_assert(this->expr_->is_variable()); + + Runtime::Function code; if (e->integer_type()->is_byte()) - { - static tree byte_array_to_string_fndecl; - ret = Gogo::call_builtin(&byte_array_to_string_fndecl, - this->location(), - "__go_byte_array_to_string", - 2, - type_tree, - const_ptr_type_node, - valptr, - int_type_tree, - len); - } + code = Runtime::BYTE_ARRAY_TO_STRING; else - { - go_assert(e->integer_type()->is_rune()); - static tree int_array_to_string_fndecl; - ret = Gogo::call_builtin(&int_array_to_string_fndecl, - this->location(), - "__go_int_array_to_string", - 2, - type_tree, - const_ptr_type_node, - valptr, - int_type_tree, - len); - } + { + go_assert(e->integer_type()->is_rune()); + code = Runtime::INT_ARRAY_TO_STRING; + } + Expression* valptr = a->get_value_pointer(gogo, this->expr_); + Expression* len = a->get_length(gogo, this->expr_); + Expression* a2s_expr = Runtime::make_call(code, location, 2, valptr, len); + ret = a2s_expr->get_tree(context); } else if (type->is_slice_type() && expr_type->is_string_type()) { @@ -6595,6 +6594,7 @@ Expression::comparison_tree(Translate_context* context, Type* result_type, { std::swap(left_type, right_type); std::swap(left_tree, right_tree); + std::swap(left_expr, right_expr); } if (right_type->is_nil_type()) @@ -6603,7 +6603,8 @@ Expression::comparison_tree(Translate_context* context, Type* result_type, && left_type->array_type()->length() == NULL) { Array_type* at = left_type->array_type(); - left_tree = at->value_pointer_tree(context->gogo(), left_tree); + left_expr = at->get_value_pointer(context->gogo(), left_expr); + left_tree = left_expr->get_tree(context); right_tree = fold_convert(TREE_TYPE(left_tree), null_pointer_node); } else if (left_type->interface_type() != NULL) @@ -7037,6 +7038,9 @@ class Builtin_call_expression : public Call_expression Expression* do_lower(Gogo*, Named_object*, Statement_inserter*, int); + Expression* + do_flatten(Gogo*, Named_object*, Statement_inserter*); + bool do_is_constant() const; @@ -7367,6 +7371,36 @@ Builtin_call_expression::do_lower(Gogo* gogo, Named_object* function, return this; } +// Flatten a builtin call expression. This turns the arguments of copy and +// append into temporary expressions. + +Expression* +Builtin_call_expression::do_flatten(Gogo*, Named_object*, + Statement_inserter* inserter) +{ + if (this->code_ == BUILTIN_APPEND + || this->code_ == BUILTIN_COPY) + { + Location loc = this->location(); + Type* at = this->args()->front()->type(); + for (Expression_list::iterator pa = this->args()->begin(); + pa != this->args()->end(); + ++pa) + { + if ((*pa)->is_nil_expression()) + *pa = Expression::make_slice_composite_literal(at, NULL, loc); + if (!(*pa)->is_variable()) + { + Temporary_statement* temp = + Statement::make_temporary(NULL, *pa, loc); + inserter->insert(temp); + *pa = Expression::make_temporary_reference(temp, loc); + } + } + } + return this; +} + // Lower a make expression. Expression* @@ -8503,7 +8537,8 @@ Builtin_call_expression::do_get_tree(Translate_context* context) return error_mark_node; } this->seen_ = true; - val_tree = arg_type->array_type()->length_tree(gogo, arg_tree); + Expression* len = arg_type->array_type()->get_length(gogo, arg); + val_tree = len->get_tree(context); this->seen_ = false; } else if (arg_type->map_type() != NULL) @@ -8543,8 +8578,9 @@ Builtin_call_expression::do_get_tree(Translate_context* context) return error_mark_node; } this->seen_ = true; - val_tree = arg_type->array_type()->capacity_tree(gogo, - arg_tree); + Expression* cap = + arg_type->array_type()->get_capacity(gogo, arg); + val_tree = cap->get_tree(context); this->seen_ = false; } else if (arg_type->channel_type() != NULL) @@ -8848,9 +8884,11 @@ Builtin_call_expression::do_get_tree(Translate_context* context) Type* arg1_type = arg1->type(); Array_type* at = arg1_type->array_type(); - arg1_tree = save_expr(arg1_tree); - tree arg1_val = at->value_pointer_tree(gogo, arg1_tree); - tree arg1_len = at->length_tree(gogo, arg1_tree); + go_assert(arg1->is_variable()); + Expression* arg1_valptr = at->get_value_pointer(gogo, arg1); + Expression* arg1_len_expr = at->get_length(gogo, arg1); + tree arg1_val = arg1_valptr->get_tree(context); + tree arg1_len = arg1_len_expr->get_tree(context); if (arg1_val == error_mark_node || arg1_len == error_mark_node) return error_mark_node; @@ -8860,9 +8898,11 @@ Builtin_call_expression::do_get_tree(Translate_context* context) if (arg2_type->is_slice_type()) { at = arg2_type->array_type(); - arg2_tree = save_expr(arg2_tree); - arg2_val = at->value_pointer_tree(gogo, arg2_tree); - arg2_len = at->length_tree(gogo, arg2_tree); + go_assert(arg2->is_variable()); + Expression* arg2_valptr = at->get_value_pointer(gogo, arg2); + Expression* arg2_len_expr = at->get_length(gogo, arg2); + arg2_val = arg2_valptr->get_tree(context); + arg2_len = arg2_len_expr->get_tree(context); } else { @@ -8950,23 +8990,15 @@ Builtin_call_expression::do_get_tree(Translate_context* context) } else { - arg2_tree = Expression::convert_for_assignment(context, at, - arg2->type(), - arg2_tree, - location); - if (arg2_tree == error_mark_node) + go_assert(arg2->is_variable()); + arg2_val = + at->get_value_pointer(gogo, arg2)->get_tree(context); + arg2_len = at->get_length(gogo, arg2)->get_tree(context); + Btype* element_btype = element_type->get_backend(gogo); + tree element_type_tree = type_to_tree(element_btype); + if (element_type_tree == error_mark_node) return error_mark_node; - - arg2_tree = save_expr(arg2_tree); - - arg2_val = at->value_pointer_tree(gogo, arg2_tree); - arg2_len = at->length_tree(gogo, arg2_tree); - - Btype* element_btype = element_type->get_backend(gogo); - tree element_type_tree = type_to_tree(element_btype); - if (element_type_tree == error_mark_node) - return error_mark_node; - element_size = TYPE_SIZE_UNIT(element_type_tree); + element_size = TYPE_SIZE_UNIT(element_type_tree); } arg2_val = fold_convert_loc(location.gcc_location(), ptr_type_node, @@ -10371,6 +10403,9 @@ class Array_index_expression : public Expression do_check_types(Gogo*); Expression* + do_flatten(Gogo*, Named_object*, Statement_inserter*); + + Expression* do_copy() { return Expression::make_array_index(this->array_->copy(), @@ -10611,6 +10646,22 @@ Array_index_expression::do_check_types(Gogo*) } } +// Flatten array indexing by using a temporary variable for slices. + +Expression* +Array_index_expression::do_flatten(Gogo*, Named_object*, + Statement_inserter* inserter) +{ + Location loc = this->location(); + if (this->array_->type()->is_slice_type() && !this->array_->is_variable()) + { + Temporary_statement* temp = Statement::make_temporary(NULL, this->array_, loc); + inserter->insert(temp); + this->array_ = Expression::make_temporary_reference(temp, loc); + } + return this; +} + // Return whether this expression is addressable. bool @@ -10643,22 +10694,17 @@ Array_index_expression::do_get_tree(Translate_context* context) go_assert(this->array_->type()->is_error()); return error_mark_node; } + go_assert(!array_type->is_slice_type() || this->array_->is_variable()); tree type_tree = type_to_tree(array_type->get_backend(gogo)); if (type_tree == error_mark_node) return error_mark_node; - tree array_tree = this->array_->get_tree(context); - if (array_tree == error_mark_node) - return error_mark_node; - - if (array_type->length() == NULL && !DECL_P(array_tree)) - array_tree = save_expr(array_tree); - tree length_tree = NULL_TREE; if (this->end_ == NULL || this->end_->is_nil_expression()) { - length_tree = array_type->length_tree(gogo, array_tree); + Expression* len = array_type->get_length(gogo, this->array_); + length_tree = len->get_tree(context); if (length_tree == error_mark_node) return error_mark_node; length_tree = save_expr(length_tree); @@ -10667,7 +10713,8 @@ Array_index_expression::do_get_tree(Translate_context* context) tree capacity_tree = NULL_TREE; if (this->end_ != NULL) { - capacity_tree = array_type->capacity_tree(gogo, array_tree); + Expression* cap = array_type->get_capacity(gogo, this->array_); + capacity_tree = cap->get_tree(context); if (capacity_tree == error_mark_node) return error_mark_node; capacity_tree = save_expr(capacity_tree); @@ -10732,13 +10779,18 @@ Array_index_expression::do_get_tree(Translate_context* context) if (array_type->length() != NULL) { // Fixed array. + tree array_tree = this->array_->get_tree(context); + if (array_tree == error_mark_node) + return error_mark_node; return build4(ARRAY_REF, TREE_TYPE(type_tree), array_tree, start_tree, NULL_TREE, NULL_TREE); } else { // Open array. - tree values = array_type->value_pointer_tree(gogo, array_tree); + Expression* valptr = + array_type->get_value_pointer(gogo, this->array_); + tree values = valptr->get_tree(context); Type* element_type = array_type->element_type(); Btype* belement_type = element_type->get_backend(gogo); tree element_type_tree = type_to_tree(belement_type); @@ -10820,7 +10872,8 @@ Array_index_expression::do_get_tree(Translate_context* context) start_tree), element_size); - tree value_pointer = array_type->value_pointer_tree(gogo, array_tree); + Expression* valptr = array_type->get_value_pointer(gogo, this->array_); + tree value_pointer = valptr->get_tree(context); if (value_pointer == error_mark_node) return error_mark_node; @@ -14133,6 +14186,22 @@ Expression::is_nonconstant_composite_literal() const } } +// Return true if this is a variable or temporary_variable. + +bool +Expression::is_variable() const +{ + switch (this->classification_) + { + case EXPRESSION_VAR_REFERENCE: + case EXPRESSION_TEMPORARY_REFERENCE: + case EXPRESSION_SET_AND_USE_TEMPORARY: + return true; + default: + return false; + } +} + // Return true if this is a reference to a local variable. bool @@ -14574,6 +14643,117 @@ Expression::make_type_info(Type* type, Type_info type_info) return new Type_info_expression(type, type_info); } +// An expression that evaluates to some characteristic of a slice. +// This is used when indexing, bound-checking, or nil checking a slice. + +class Slice_info_expression : public Expression +{ + public: + Slice_info_expression(Expression* slice, Slice_info slice_info, + Location location) + : Expression(EXPRESSION_SLICE_INFO, location), + slice_(slice), slice_info_(slice_info) + { } + + protected: + Type* + do_type(); + + void + do_determine_type(const Type_context*) + { } + + Expression* + do_copy() + { + return new Slice_info_expression(this->slice_->copy(), this->slice_info_, + this->location()); + } + + tree + do_get_tree(Translate_context* context); + + void + do_dump_expression(Ast_dump_context*) const; + + void + do_issue_nil_check() + { this->slice_->issue_nil_check(); } + + private: + // The slice for which we are getting information. + Expression* slice_; + // What information we want. + Slice_info slice_info_; +}; + +// Return the type of the slice info. + +Type* +Slice_info_expression::do_type() +{ + switch (this->slice_info_) + { + case SLICE_INFO_VALUE_POINTER: + return Type::make_pointer_type( + this->slice_->type()->array_type()->element_type()); + case SLICE_INFO_LENGTH: + case SLICE_INFO_CAPACITY: + return Type::lookup_integer_type("int"); + default: + go_unreachable(); + } +} + +// Return slice information in GENERIC. + +tree +Slice_info_expression::do_get_tree(Translate_context* context) +{ + Gogo* gogo = context->gogo(); + + Bexpression* bslice = tree_to_expr(this->slice_->get_tree(context)); + Bexpression* ret; + switch (this->slice_info_) + { + case SLICE_INFO_VALUE_POINTER: + case SLICE_INFO_LENGTH: + case SLICE_INFO_CAPACITY: + ret = gogo->backend()->struct_field_expression(bslice, this->slice_info_, + this->location()); + break; + default: + go_unreachable(); + } + return expr_to_tree(ret); +} + +// Dump ast representation for a type info expression. + +void +Slice_info_expression::do_dump_expression( + Ast_dump_context* ast_dump_context) const +{ + ast_dump_context->ostream() << "sliceinfo("; + this->slice_->dump_expression(ast_dump_context); + ast_dump_context->ostream() << ","; + ast_dump_context->ostream() << + (this->slice_info_ == SLICE_INFO_VALUE_POINTER ? "values" + : this->slice_info_ == SLICE_INFO_LENGTH ? "length" + : this->slice_info_ == SLICE_INFO_CAPACITY ? "capacity " + : "unknown"); + ast_dump_context->ostream() << ")"; +} + +// Make a slice info expression. + +Expression* +Expression::make_slice_info(Expression* slice, Slice_info slice_info, + Location location) +{ + return new Slice_info_expression(slice, slice_info, location); +} + // An expression which evaluates to the offset of a field within a // struct. This, like Type_info_expression, q.v., is only used to // initialize fields of a type descriptor. diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h index e447418b949e..abebbd16961b 100644 --- a/gcc/go/gofrontend/expressions.h +++ b/gcc/go/gofrontend/expressions.h @@ -102,6 +102,7 @@ class Expression EXPRESSION_RECEIVE, EXPRESSION_TYPE_DESCRIPTOR, EXPRESSION_TYPE_INFO, + EXPRESSION_SLICE_INFO, EXPRESSION_STRUCT_FIELD_OFFSET, EXPRESSION_MAP_DESCRIPTOR, EXPRESSION_LABEL_ADDR @@ -339,6 +340,22 @@ class Expression static Expression* make_type_info(Type* type, Type_info); + // Make an expression that evaluates to some characteristic of a + // slice. For simplicity, the enum values must match the field indexes + // in the underlying struct. + enum Slice_info + { + // The underlying data of the slice. + SLICE_INFO_VALUE_POINTER, + // The length of the slice. + SLICE_INFO_LENGTH, + // The capacity of the slice. + SLICE_INFO_CAPACITY + }; + + static Expression* + make_slice_info(Expression* slice, Slice_info, Location); + // Make an expression which evaluates to the offset of a field in a // struct. This is only used for type descriptors, so there is no // location parameter. @@ -544,6 +561,10 @@ class Expression bool is_nonconstant_composite_literal() const; + // Return true if this is a variable or temporary variable. + bool + is_variable() const; + // Return true if this is a reference to a local variable. bool is_local_variable() const; @@ -575,6 +596,18 @@ class Expression int iota_value) { return this->do_lower(gogo, function, inserter, iota_value); } + // Flatten an expression. This is called after order_evaluation. + // FUNCTION is the function we are in; it will be NULL for an + // expression initializing a global variable. INSERTER may be used + // to insert statements before the statement or initializer + // containing this expression; it is normally used to create + // temporary variables. This function must resolve expressions + // which could not be fully parsed into their final form. It + // returns the same Expression or a new one. + Expression* + flatten(Gogo* gogo, Named_object* function, Statement_inserter* inserter) + { return this->do_flatten(gogo, function, inserter); } + // Determine the real type of an expression with abstract integer, // floating point, or complex type. TYPE_CONTEXT describes the // expected type. @@ -698,6 +731,12 @@ class Expression do_lower(Gogo*, Named_object*, Statement_inserter*, int) { return this; } + // Return a flattened expression. + virtual Expression* + do_flatten(Gogo*, Named_object*, Statement_inserter*) + { return this; } + + // Return whether this is a constant expression. virtual bool do_is_constant() const diff --git a/gcc/go/gofrontend/go.cc b/gcc/go/gofrontend/go.cc index 55b4dca85792..26e83a1db64f 100644 --- a/gcc/go/gofrontend/go.cc +++ b/gcc/go/gofrontend/go.cc @@ -119,12 +119,15 @@ go_parse_input_files(const char** filenames, unsigned int filename_count, // Use temporary variables to force order of evaluation. ::gogo->order_evaluations(); + // Flatten the parse tree. + ::gogo->flatten(); + // Build thunks for functions which call recover. ::gogo->build_recover_thunks(); // Convert complicated go and defer statements into simpler ones. ::gogo->simplify_thunk_statements(); - + // Dump ast, use filename[0] as the base name ::gogo->dump_ast(filenames[0]); } diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc index e46bf9c4193d..6ecc6cd0f0f4 100644 --- a/gcc/go/gofrontend/gogo.cc +++ b/gcc/go/gofrontend/gogo.cc @@ -2703,6 +2703,178 @@ Gogo::order_evaluations() this->traverse(&order_eval); } +// Traversal to flatten parse tree after order of evaluation rules are applied. + +class Flatten : public Traverse +{ + public: + Flatten(Gogo* gogo, Named_object* function) + : Traverse(traverse_variables + | traverse_functions + | traverse_statements + | traverse_expressions), + gogo_(gogo), function_(function), inserter_() + { } + + void + set_inserter(const Statement_inserter* inserter) + { this->inserter_ = *inserter; } + + int + variable(Named_object*); + + int + function(Named_object*); + + int + statement(Block*, size_t* pindex, Statement*); + + int + expression(Expression**); + + private: + // General IR. + Gogo* gogo_; + // The function we are traversing. + Named_object* function_; + // Current statement inserter for use by expressions. + Statement_inserter inserter_; +}; + +// Flatten variables. + +int +Flatten::variable(Named_object* no) +{ + if (!no->is_variable()) + return TRAVERSE_CONTINUE; + + if (no->is_variable() && no->var_value()->is_global()) + { + // Global variables can have loops in their initialization + // expressions. This is handled in flatten_init_expression. + no->var_value()->flatten_init_expression(this->gogo_, this->function_, + &this->inserter_); + return TRAVERSE_CONTINUE; + } + + go_assert(!no->var_value()->has_pre_init()); + + return TRAVERSE_SKIP_COMPONENTS; +} + +// Flatten the body of a function. Record the function while flattening it, +// so that we can pass it down when flattening an expression. + +int +Flatten::function(Named_object* no) +{ + go_assert(this->function_ == NULL); + this->function_ = no; + int t = no->func_value()->traverse(this); + this->function_ = NULL; + + if (t == TRAVERSE_EXIT) + return t; + return TRAVERSE_SKIP_COMPONENTS; +} + +// Flatten statement parse trees. + +int +Flatten::statement(Block* block, size_t* pindex, Statement* sorig) +{ + // Because we explicitly traverse the statement's contents + // ourselves, we want to skip block statements here. There is + // nothing to flatten in a block statement. + if (sorig->is_block_statement()) + return TRAVERSE_CONTINUE; + + Statement_inserter hold_inserter(this->inserter_); + this->inserter_ = Statement_inserter(block, pindex); + + // Flatten the expressions first. + int t = sorig->traverse_contents(this); + if (t == TRAVERSE_EXIT) + { + this->inserter_ = hold_inserter; + return t; + } + + // Keep flattening until nothing changes. + Statement* s = sorig; + while (true) + { + Statement* snew = s->flatten(this->gogo_, this->function_, block, + &this->inserter_); + if (snew == s) + break; + s = snew; + t = s->traverse_contents(this); + if (t == TRAVERSE_EXIT) + { + this->inserter_ = hold_inserter; + return t; + } + } + + if (s != sorig) + block->replace_statement(*pindex, s); + + this->inserter_ = hold_inserter; + return TRAVERSE_SKIP_COMPONENTS; +} + +// Flatten expression parse trees. + +int +Flatten::expression(Expression** pexpr) +{ + // Keep flattening until nothing changes. + while (true) + { + Expression* e = *pexpr; + if (e->traverse_subexpressions(this) == TRAVERSE_EXIT) + return TRAVERSE_EXIT; + + Expression* enew = e->flatten(this->gogo_, this->function_, + &this->inserter_); + if (enew == e) + break; + *pexpr = enew; + } + return TRAVERSE_SKIP_COMPONENTS; +} + +// Flatten a block. + +void +Gogo::flatten_block(Named_object* function, Block* block) +{ + Flatten flatten(this, function); + block->traverse(&flatten); +} + +// Flatten an expression. INSERTER may be NULL, in which case the +// expression had better not need to create any temporaries. + +void +Gogo::flatten_expression(Named_object* function, Statement_inserter* inserter, + Expression** pexpr) +{ + Flatten flatten(this, function); + if (inserter != NULL) + flatten.set_inserter(inserter); + flatten.expression(pexpr); +} + +void +Gogo::flatten() +{ + Flatten flatten(this, NULL); + this->traverse(&flatten); +} + // Traversal to convert calls to the predeclared recover function to // pass in an argument indicating whether it can recover from a panic // or not. @@ -4286,10 +4458,11 @@ Variable::Variable(Type* type, Expression* init, bool is_global, backend_(NULL), is_global_(is_global), is_parameter_(is_parameter), is_receiver_(is_receiver), is_varargs_parameter_(false), is_used_(false), is_address_taken_(false), is_non_escaping_address_taken_(false), - seen_(false), init_is_lowered_(false), type_from_init_tuple_(false), - type_from_range_index_(false), type_from_range_value_(false), - type_from_chan_element_(false), is_type_switch_var_(false), - determined_type_(false), in_unique_section_(false) + seen_(false), init_is_lowered_(false), init_is_flattened_(false), + type_from_init_tuple_(false), type_from_range_index_(false), + type_from_range_value_(false), type_from_chan_element_(false), + is_type_switch_var_(false), determined_type_(false), + in_unique_section_(false) { go_assert(type != NULL || init != NULL); go_assert(!is_parameter || init == NULL); @@ -4351,6 +4524,40 @@ Variable::lower_init_expression(Gogo* gogo, Named_object* function, } } +// Flatten the initialization expression after ordering evaluations. + +void +Variable::flatten_init_expression(Gogo* gogo, Named_object* function, + Statement_inserter* inserter) +{ + Named_object* dep = gogo->var_depends_on(this); + if (dep != NULL && dep->is_variable()) + dep->var_value()->flatten_init_expression(gogo, function, inserter); + + if (this->init_ != NULL && !this->init_is_flattened_) + { + if (this->seen_) + { + // We will give an error elsewhere, this is just to prevent + // an infinite loop. + return; + } + this->seen_ = true; + + Statement_inserter global_inserter; + if (this->is_global_) + { + global_inserter = Statement_inserter(gogo, this); + inserter = &global_inserter; + } + + gogo->flatten_expression(function, inserter, &this->init_); + + this->seen_ = false; + this->init_is_flattened_ = true; + } +} + // Get the preinit block. Block* diff --git a/gcc/go/gofrontend/gogo.h b/gcc/go/gofrontend/gogo.h index a9a56815c178..3f2808781b74 100644 --- a/gcc/go/gofrontend/gogo.h +++ b/gcc/go/gofrontend/gogo.h @@ -487,6 +487,14 @@ class Gogo void lower_constant(Named_object*); + // Flatten all the statements in a block. + void + flatten_block(Named_object* function, Block*); + + // Flatten an expression. + void + flatten_expression(Named_object* function, Statement_inserter*, Expression**); + // Create all necessary function descriptors. void create_function_descriptors(); @@ -531,6 +539,10 @@ class Gogo void order_evaluations(); + // Flatten parse tree. + void + flatten(); + // Build thunks for functions which call recover. void build_recover_thunks(); @@ -1447,6 +1459,10 @@ class Variable void lower_init_expression(Gogo*, Named_object*, Statement_inserter*); + // Flatten the initialization expression after ordering evaluations. + void + flatten_init_expression(Gogo*, Named_object*, Statement_inserter*); + // A special case: the init value is used only to determine the // type. This is used if the variable is defined using := with the // comma-ok form of a map index or a receive expression. The init @@ -1580,6 +1596,8 @@ class Variable bool seen_ : 1; // True if we have lowered the initialization expression. bool init_is_lowered_ : 1; + // True if we have flattened the initialization expression. + bool init_is_flattened_ : 1; // True if init is a tuple used to set the type. bool type_from_init_tuple_ : 1; // True if init is a range clause and the type is the index type. diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc index 3a0bc3b9739e..d195ab9845a1 100644 --- a/gcc/go/gofrontend/statements.cc +++ b/gcc/go/gofrontend/statements.cc @@ -246,6 +246,16 @@ Variable_declaration_statement::do_lower(Gogo* gogo, Named_object* function, return this; } +// Flatten the variable's initialization expression. + +Statement* +Variable_declaration_statement::do_flatten(Gogo* gogo, Named_object* function, + Block*, Statement_inserter* inserter) +{ + this->var_->var_value()->flatten_init_expression(gogo, function, inserter); + return this; +} + // Convert a variable declaration to the backend representation. Bstatement* @@ -2461,6 +2471,7 @@ Thunk_statement::build_thunk(Gogo* gogo, const std::string& thunk_name) gogo->add_block(b, location); gogo->lower_block(function, b); + gogo->flatten_block(function, b); // We already ran the determine_types pass, so we need to run it // just for the call statement now. The other types are known. diff --git a/gcc/go/gofrontend/statements.h b/gcc/go/gofrontend/statements.h index b128fa0a8eb1..7d9bcfde8b70 100644 --- a/gcc/go/gofrontend/statements.h +++ b/gcc/go/gofrontend/statements.h @@ -306,6 +306,16 @@ class Statement Statement_inserter* inserter) { return this->do_lower(gogo, function, block, inserter); } + // Flatten a statement. This is called immediately after the order of + // evaluation rules are applied to statements. It returns the same + // Statement or a new one. FUNCTION is the function containing this + // statement. BLOCK is the block containing this statement. + // INSERTER can be used to insert new statements before this one. + Statement* + flatten(Gogo* gogo, Named_object* function, Block* block, + Statement_inserter* inserter) + { return this->do_flatten(gogo, function, block, inserter); } + // Set type information for unnamed constants. void determine_types(); @@ -412,6 +422,12 @@ class Statement do_lower(Gogo*, Named_object*, Block*, Statement_inserter*) { return this; } + // Implemented by the child class: lower this statement to a simpler + // one. + virtual Statement* + do_flatten(Gogo*, Named_object*, Block*, Statement_inserter*) + { return this; } + // Implemented by child class: set type information for unnamed // constants. Any statement which includes an expression needs to // implement this. @@ -583,6 +599,9 @@ class Variable_declaration_statement : public Statement Statement* do_lower(Gogo*, Named_object*, Block*, Statement_inserter*); + Statement* + do_flatten(Gogo*, Named_object*, Block*, Statement_inserter*); + Bstatement* do_get_backend(Translate_context*); diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc index d079565d18bc..2935523dd2aa 100644 --- a/gcc/go/gofrontend/types.cc +++ b/gcc/go/gofrontend/types.cc @@ -6000,84 +6000,53 @@ Array_type::finish_backend_element(Gogo* gogo) } } -// Return a tree for a pointer to the values in ARRAY. +// Return an expression for a pointer to the values in ARRAY. -tree -Array_type::value_pointer_tree(Gogo*, tree array) const +Expression* +Array_type::get_value_pointer(Gogo*, Expression* array) const { - tree ret; if (this->length() != NULL) { // Fixed array. - ret = fold_convert(build_pointer_type(TREE_TYPE(TREE_TYPE(array))), - build_fold_addr_expr(array)); + go_assert(array->type()->array_type() != NULL); + Type* etype = array->type()->array_type()->element_type(); + array = Expression::make_unary(OPERATOR_AND, array, array->location()); + return Expression::make_cast(Type::make_pointer_type(etype), array, + array->location()); } - else - { - // Open array. - tree field = TYPE_FIELDS(TREE_TYPE(array)); - go_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), - "__values") == 0); - ret = fold_build3(COMPONENT_REF, TREE_TYPE(field), array, field, - NULL_TREE); - } - if (TREE_CONSTANT(array)) - TREE_CONSTANT(ret) = 1; - return ret; + + // Open array. + return Expression::make_slice_info(array, + Expression::SLICE_INFO_VALUE_POINTER, + array->location()); } -// Return a tree for the length of the array ARRAY which has this +// Return an expression for the length of the array ARRAY which has this // type. -tree -Array_type::length_tree(Gogo* gogo, tree array) +Expression* +Array_type::get_length(Gogo*, Expression* array) const { if (this->length_ != NULL) - { - if (TREE_CODE(array) == SAVE_EXPR) - return this->get_length_tree(gogo); - else - { - tree len = this->get_length_tree(gogo); - return omit_one_operand(TREE_TYPE(len), len, array); - } - } + return this->length_; // This is an open array. We need to read the length field. - - tree type = TREE_TYPE(array); - go_assert(TREE_CODE(type) == RECORD_TYPE); - - tree field = DECL_CHAIN(TYPE_FIELDS(type)); - go_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__count") == 0); - - tree ret = build3(COMPONENT_REF, TREE_TYPE(field), array, field, NULL_TREE); - if (TREE_CONSTANT(array)) - TREE_CONSTANT(ret) = 1; - return ret; + return Expression::make_slice_info(array, Expression::SLICE_INFO_LENGTH, + array->location()); } -// Return a tree for the capacity of the array ARRAY which has this +// Return an expression for the capacity of the array ARRAY which has this // type. -tree -Array_type::capacity_tree(Gogo* gogo, tree array) +Expression* +Array_type::get_capacity(Gogo*, Expression* array) const { if (this->length_ != NULL) - { - tree len = this->get_length_tree(gogo); - return omit_one_operand(TREE_TYPE(len), len, array); - } + return this->length_; // This is an open array. We need to read the capacity field. - - tree type = TREE_TYPE(array); - go_assert(TREE_CODE(type) == RECORD_TYPE); - - tree field = DECL_CHAIN(DECL_CHAIN(TYPE_FIELDS(type))); - go_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__capacity") == 0); - - return build3(COMPONENT_REF, TREE_TYPE(field), array, field, NULL_TREE); + return Expression::make_slice_info(array, Expression::SLICE_INFO_CAPACITY, + array->location()); } // Export. diff --git a/gcc/go/gofrontend/types.h b/gcc/go/gofrontend/types.h index 9f9659161319..980436a10379 100644 --- a/gcc/go/gofrontend/types.h +++ b/gcc/go/gofrontend/types.h @@ -2312,17 +2312,17 @@ class Array_type : public Type array_has_hidden_fields(const Named_type* within, std::string* reason) const { return this->element_type_->has_hidden_fields(within, reason); } - // Return a tree for the pointer to the values in an array. - tree - value_pointer_tree(Gogo*, tree array) const; + // Return an expression for the pointer to the values in an array. + Expression* + get_value_pointer(Gogo*, Expression* array) const; - // Return a tree for the length of an array with this type. - tree - length_tree(Gogo*, tree array); + // Return an expression for the length of an array with this type. + Expression* + get_length(Gogo*, Expression* array) const; - // Return a tree for the capacity of an array with this type. - tree - capacity_tree(Gogo*, tree array); + // Return an expression for the capacity of an array with this type. + Expression* + get_capacity(Gogo*, Expression* array) const; // Import an array type. static Array_type* diff --git a/gcc/hash-table.h b/gcc/hash-table.h index 2b04067f74a6..034385c19f27 100644 --- a/gcc/hash-table.h +++ b/gcc/hash-table.h @@ -1050,10 +1050,7 @@ hash_table <Descriptor, Allocator>::end () /* Iterate through the elements of hash_table HTAB, using hash_table <....>::iterator ITER, - storing each element in RESULT, which is of type TYPE. - - This macro has this form for compatibility with the - FOR_EACH_HTAB_ELEMENT currently defined in tree-flow.h. */ + storing each element in RESULT, which is of type TYPE. */ #define FOR_EACH_HASH_TABLE_ELEMENT(HTAB, RESULT, TYPE, ITER) \ for ((ITER) = (HTAB).begin (); \ diff --git a/gcc/hw-doloop.c b/gcc/hw-doloop.c index ab4899db6322..cc8f9b775052 100644 --- a/gcc/hw-doloop.c +++ b/gcc/hw-doloop.c @@ -661,6 +661,7 @@ reorg_loops (bool do_reorder, struct hw_doloop_hooks *hooks) } free_loops (loops); + bitmap_obstack_release (&loop_stack); if (dump_file) print_rtl (dump_file, get_insns ()); diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c index 398453547318..51293651e9cc 100644 --- a/gcc/ifcvt.c +++ b/gcc/ifcvt.c @@ -118,7 +118,7 @@ count_bb_insns (const_basic_block bb) while (1) { - if (CALL_P (insn) || NONJUMP_INSN_P (insn)) + if (active_insn_p (insn) && !JUMP_P (insn)) count++; if (insn == BB_END (bb)) @@ -522,7 +522,10 @@ cond_exec_process_if_block (ce_if_block * ce_info, n_insns -= 2 * n_matching; } - if (then_start && else_start) + if (then_start + && else_start + && then_n_insns > n_matching + && else_n_insns > n_matching) { int longest_match = MIN (then_n_insns - n_matching, else_n_insns - n_matching); @@ -3153,6 +3156,20 @@ merge_if_block (struct ce_if_block * ce_info) if (then_bb) { + /* If THEN_BB has no successors, then there's a BARRIER after it. + If COMBO_BB has more than one successor (THEN_BB), then that BARRIER + is no longer needed, and in fact it is incorrect to leave it in + the insn stream. */ + if (EDGE_COUNT (then_bb->succs) == 0 + && EDGE_COUNT (combo_bb->succs) > 1) + { + rtx end = NEXT_INSN (BB_END (then_bb)); + while (end && NOTE_P (end) && !NOTE_INSN_BASIC_BLOCK_P (end)) + end = NEXT_INSN (end); + + if (end && BARRIER_P (end)) + delete_insn (end); + } merge_blocks (combo_bb, then_bb); num_true_changes++; } @@ -3162,6 +3179,20 @@ merge_if_block (struct ce_if_block * ce_info) get their addresses taken. */ if (else_bb) { + /* If ELSE_BB has no successors, then there's a BARRIER after it. + If COMBO_BB has more than one successor (ELSE_BB), then that BARRIER + is no longer needed, and in fact it is incorrect to leave it in + the insn stream. */ + if (EDGE_COUNT (else_bb->succs) == 0 + && EDGE_COUNT (combo_bb->succs) > 1) + { + rtx end = NEXT_INSN (BB_END (else_bb)); + while (end && NOTE_P (end) && !NOTE_INSN_BASIC_BLOCK_P (end)) + end = NEXT_INSN (end); + + if (end && BARRIER_P (end)) + delete_insn (end); + } merge_blocks (combo_bb, else_bb); num_true_changes++; } diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c index 63c50370a0a6..a6a44e6d81ac 100644 --- a/gcc/ipa-cp.c +++ b/gcc/ipa-cp.c @@ -2281,7 +2281,7 @@ ipcp_discover_new_direct_edges (struct cgraph_node *node, { bool agg_contents = ie->indirect_info->agg_contents; bool polymorphic = ie->indirect_info->polymorphic; - bool param_index = ie->indirect_info->param_index; + int param_index = ie->indirect_info->param_index; struct cgraph_edge *cs = ipa_make_edge_direct_to_target (ie, target); found = true; diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c index ff465f9e963f..a9efe584187e 100644 --- a/gcc/ipa-devirt.c +++ b/gcc/ipa-devirt.c @@ -542,7 +542,7 @@ method_class_type (tree t) void build_type_inheritance_graph (void) { - struct cgraph_node *n; + struct symtab_node *n; FILE *inheritance_dump_file; int flags; @@ -554,10 +554,37 @@ 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->decl) + FOR_EACH_SYMBOL (n) + if (is_a <cgraph_node> (n) + && DECL_VIRTUAL_P (n->decl) && symtab_real_symbol_p (n)) get_odr_type (method_class_type (TREE_TYPE (n->decl)), true); + + /* Look also for virtual tables of types that do not define any methods. + + We need it in a case where class B has virtual base of class A + re-defining its virtual method and there is class C with no virtual + methods with B as virtual base. + + Here we output B's virtual method in two variant - for non-virtual + and virtual inheritance. B's virtual table has non-virtual version, + while C's has virtual. + + For this reason we need to know about C in order to include both + variants of B. More correctly, record_target_from_binfo should + add both variants of the method when walking B, but we have no + link in between them. + + We rely on fact that either the method is exported and thus we + assume it is called externally or C is in anonymous namespace and + thus we will see the vtable. */ + + else if (is_a <varpool_node> (n) + && DECL_VIRTUAL_P (n->decl) + && TREE_CODE (DECL_CONTEXT (n->decl)) == RECORD_TYPE + && TYPE_BINFO (DECL_CONTEXT (n->decl)) + && polymorphic_type_binfo_p (TYPE_BINFO (DECL_CONTEXT (n->decl)))) + get_odr_type (DECL_CONTEXT (n->decl), true); if (inheritance_dump_file) { dump_type_inheritance_graph (inheritance_dump_file); @@ -614,10 +641,8 @@ maybe_record_node (vec <cgraph_node *> &nodes, This match what get_binfo_at_offset does, but with offset being unknown. - TYPE_BINFO is binfo holding an virtual table matching - BINFO's type. In the case of single inheritance, this - is binfo of BINFO's type ancestor (vtable is shared), - otherwise it is binfo of BINFO's type. + TYPE_BINFOS is a stack of BINFOS of types with defined + virtual table seen on way from class type to BINFO. MATCHED_VTABLES tracks virtual tables we already did lookup for virtual function in. INSERTED tracks nodes we already @@ -630,7 +655,7 @@ static void record_target_from_binfo (vec <cgraph_node *> &nodes, tree binfo, tree otr_type, - tree type_binfo, + vec <tree> &type_binfos, HOST_WIDE_INT otr_token, tree outer_type, HOST_WIDE_INT offset, @@ -642,10 +667,32 @@ record_target_from_binfo (vec <cgraph_node *> &nodes, int i; tree base_binfo; - gcc_checking_assert (BINFO_VTABLE (type_binfo)); + if (BINFO_VTABLE (binfo)) + type_binfos.safe_push (binfo); if (types_same_for_odr (type, outer_type)) { + int i; + tree type_binfo = NULL; + + /* Lookup BINFO with virtual table. For normal types it is always last + binfo on stack. */ + for (i = type_binfos.length () - 1; i >= 0; i--) + if (BINFO_OFFSET (type_binfos[i]) == BINFO_OFFSET (binfo)) + { + type_binfo = type_binfos[i]; + break; + } + if (BINFO_VTABLE (binfo)) + type_binfos.pop (); + /* If this is duplicated BINFO for base shared by virtual inheritance, + we may not have its associated vtable. This is not a problem, since + we will walk it on the other path. */ + if (!type_binfo) + { + gcc_assert (BINFO_VIRTUAL_P (binfo)); + return; + } tree inner_binfo = get_binfo_at_offset (type_binfo, offset, otr_type); /* For types in anonymous namespace first check if the respective vtable @@ -676,12 +723,11 @@ record_target_from_binfo (vec <cgraph_node *> &nodes, /* Walking bases that have no virtual method is pointless excercise. */ if (polymorphic_type_binfo_p (base_binfo)) record_target_from_binfo (nodes, base_binfo, otr_type, - /* In the case of single inheritance, - the virtual table is shared with - the outer type. */ - BINFO_VTABLE (base_binfo) ? base_binfo : type_binfo, + type_binfos, otr_token, outer_type, offset, inserted, matched_vtables, anonymous); + if (BINFO_VTABLE (binfo)) + type_binfos.pop (); } /* Lookup virtual methods matching OTR_TYPE (with OFFSET and OTR_TOKEN) @@ -701,11 +747,13 @@ possible_polymorphic_call_targets_1 (vec <cgraph_node *> &nodes, { tree binfo = TYPE_BINFO (type->type); unsigned int i; + vec <tree> type_binfos = vNULL; - record_target_from_binfo (nodes, binfo, otr_type, binfo, otr_token, + record_target_from_binfo (nodes, binfo, otr_type, type_binfos, otr_token, outer_type, offset, inserted, matched_vtables, type->anonymous_namespace); + type_binfos.release (); for (i = 0; i < type->derived_types.length (); i++) possible_polymorphic_call_targets_1 (nodes, inserted, matched_vtables, diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c index 2fb224631287..f39e8c132416 100644 --- a/gcc/ipa-prop.c +++ b/gcc/ipa-prop.c @@ -2127,8 +2127,11 @@ ipa_analyze_params_uses (struct cgraph_node *node, FOR_EACH_IMM_USE_FAST (use_p, imm_iter, ddef) if (!is_gimple_call (USE_STMT (use_p))) { - controlled_uses = IPA_UNDESCRIBED_USE; - break; + if (!is_gimple_debug (USE_STMT (use_p))) + { + controlled_uses = IPA_UNDESCRIBED_USE; + break; + } } else controlled_uses++; @@ -3326,6 +3329,7 @@ ipa_print_node_params (FILE *f, struct cgraph_node *node) { int c; + fprintf (f, " "); ipa_dump_param (f, info, i); if (ipa_is_param_used (info, i)) fprintf (f, " used"); diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog index ad51a4746ff9..152fa233e9e7 100644 --- a/gcc/lto/ChangeLog +++ b/gcc/lto/ChangeLog @@ -1,3 +1,14 @@ +2014-01-09 Richard Biener <rguenther@suse.de> + + * lto.c (gimple_canonical_types_compatible_p): Fix comment. + +2014-01-09 Richard Biener <rguenther@suse.de> + + PR lto/45586 + * lto.c (hash_canonical_type): Do not hash TREE_ADDRESSABLE, + TYPE_ALIGN, TYPE_RESTRICT or TYPE_REF_CAN_ALIAS_ALL. + (gimple_canonical_types_compatible_p): Do not compare them either. + 2014-01-02 Richard Sandiford <rdsandiford@googlemail.com> Update copyright years diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c index 6abb4f456b4c..8ec4ae095c8e 100644 --- a/gcc/lto/lto.c +++ b/gcc/lto/lto.c @@ -280,8 +280,6 @@ hash_canonical_type (tree type) only existing types having the same features as the new type will be checked. */ v = iterative_hash_hashval_t (TREE_CODE (type), 0); - v = iterative_hash_hashval_t (TREE_ADDRESSABLE (type), v); - v = iterative_hash_hashval_t (TYPE_ALIGN (type), v); v = iterative_hash_hashval_t (TYPE_MODE (type), v); /* Incorporate common features of numerical types. */ @@ -308,9 +306,7 @@ hash_canonical_type (tree type) pointed to but do not recurse to the pointed-to type. */ if (POINTER_TYPE_P (type)) { - v = iterative_hash_hashval_t (TYPE_REF_CAN_ALIAS_ALL (type), v); v = iterative_hash_hashval_t (TYPE_ADDR_SPACE (TREE_TYPE (type)), v); - v = iterative_hash_hashval_t (TYPE_RESTRICT (type), v); v = iterative_hash_hashval_t (TREE_CODE (TREE_TYPE (type)), v); } @@ -447,9 +443,6 @@ gimple_canonical_types_compatible_p (tree t1, tree t2) if (TREE_CODE (t1) != TREE_CODE (t2)) return false; - if (TREE_ADDRESSABLE (t1) != TREE_ADDRESSABLE (t2)) - return false; - /* Qualifiers do not matter for canonical type comparison purposes. */ /* Void types and nullptr types are always the same. */ @@ -457,9 +450,8 @@ gimple_canonical_types_compatible_p (tree t1, tree t2) || TREE_CODE (t1) == NULLPTR_TYPE) return true; - /* Can't be the same type if they have different alignment, or mode. */ - if (TYPE_ALIGN (t1) != TYPE_ALIGN (t2) - || TYPE_MODE (t1) != TYPE_MODE (t2)) + /* Can't be the same type if they have different mode. */ + if (TYPE_MODE (t1) != TYPE_MODE (t2)) return false; /* Non-aggregate types can be handled cheaply. */ @@ -486,18 +478,10 @@ gimple_canonical_types_compatible_p (tree t1, tree t2) useless_type_conversion_p would do. */ if (POINTER_TYPE_P (t1)) { - /* If the two pointers have different ref-all attributes, - they can't be the same type. */ - if (TYPE_REF_CAN_ALIAS_ALL (t1) != TYPE_REF_CAN_ALIAS_ALL (t2)) - return false; - if (TYPE_ADDR_SPACE (TREE_TYPE (t1)) != TYPE_ADDR_SPACE (TREE_TYPE (t2))) return false; - if (TYPE_RESTRICT (t1) != TYPE_RESTRICT (t2)) - return false; - if (TREE_CODE (TREE_TYPE (t1)) != TREE_CODE (TREE_TYPE (t2))) return false; } diff --git a/gcc/modulo-sched.c b/gcc/modulo-sched.c index 8d63e97078b9..7ba3ddb66989 100644 --- a/gcc/modulo-sched.c +++ b/gcc/modulo-sched.c @@ -766,6 +766,9 @@ schedule_reg_moves (partial_schedule_ptr ps) distance1_uses = distances[1] ? sbitmap_alloc (g->num_nodes) : NULL; + if (distance1_uses) + bitmap_clear (distance1_uses); + /* Every use of the register defined by node may require a different copy of this register, depending on the time the use is scheduled. Record which uses require which move results. */ diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 5daa28178dad..66686692913d 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -7534,12 +7534,21 @@ expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb, loadedi = loaded_val; } + fncode = (enum built_in_function) (BUILT_IN_ATOMIC_LOAD_N + index + 1); + tree loaddecl = builtin_decl_explicit (fncode); + if (loaddecl) + initial + = fold_convert (TREE_TYPE (TREE_TYPE (iaddr)), + build_call_expr (loaddecl, 2, iaddr, + build_int_cst (NULL_TREE, + MEMMODEL_RELAXED))); + else + initial = build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), iaddr, + build_int_cst (TREE_TYPE (iaddr), 0)); + initial - = force_gimple_operand_gsi (&si, - build2 (MEM_REF, TREE_TYPE (TREE_TYPE (iaddr)), - iaddr, - build_int_cst (TREE_TYPE (iaddr), 0)), - true, NULL_TREE, true, GSI_SAME_STMT); + = force_gimple_operand_gsi (&si, initial, true, NULL_TREE, true, + GSI_SAME_STMT); /* Move the value to the LOADEDI temporary. */ if (gimple_in_ssa_p (cfun)) @@ -11535,7 +11544,7 @@ simd_clone_adjust (struct cgraph_node *node) unsigned int alignment = node->simdclone->args[i].alignment; tree orig_arg = node->simdclone->args[i].orig_arg; tree def = ssa_default_def (cfun, orig_arg); - if (!has_zero_uses (def)) + if (def && !has_zero_uses (def)) { tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED); gimple_seq seq = NULL; @@ -11585,7 +11594,7 @@ simd_clone_adjust (struct cgraph_node *node) tree def = ssa_default_def (cfun, orig_arg); gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (orig_arg)) || POINTER_TYPE_P (TREE_TYPE (orig_arg))); - if (!has_zero_uses (def)) + if (def && !has_zero_uses (def)) { iter1 = make_ssa_name (orig_arg, NULL); iter2 = make_ssa_name (orig_arg, NULL); diff --git a/gcc/optabs.c b/gcc/optabs.c index 45c728b5506d..fcd2c7216b44 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -6242,7 +6242,7 @@ init_tree_optimization_optabs (tree optnode) /* If the optabs changed, record it. */ if (memcmp (tmp_optabs, this_target_optabs, sizeof (struct target_optabs))) - TREE_OPTIMIZATION_OPTABS (optnode) = (unsigned char *) tmp_optabs; + TREE_OPTIMIZATION_OPTABS (optnode) = tmp_optabs; else { TREE_OPTIMIZATION_OPTABS (optnode) = NULL; diff --git a/gcc/params.def b/gcc/params.def index af89dd9f3881..abfda73ca874 100644 --- a/gcc/params.def +++ b/gcc/params.def @@ -1049,7 +1049,37 @@ DEFPARAM (PARAM_MAX_SLSR_CANDIDATE_SCAN, "strength reduction", 50, 1, 999999) +DEFPARAM (PARAM_ASAN_STACK, + "asan-stack", + "Enable asan stack protection", + 1, 0, 1) + +DEFPARAM (PARAM_ASAN_GLOBALS, + "asan-globals", + "Enable asan globals protection", + 1, 0, 1) + +DEFPARAM (PARAM_ASAN_INSTRUMENT_WRITES, + "asan-instrument-writes", + "Enable asan store operations protection", + 1, 0, 1) + +DEFPARAM (PARAM_ASAN_INSTRUMENT_READS, + "asan-instrument-reads", + "Enable asan load operations protection", + 1, 0, 1) + +DEFPARAM (PARAM_ASAN_MEMINTRIN, + "asan-memintrin", + "Enable asan builtin functions protection", + 1, 0, 1) + +DEFPARAM (PARAM_ASAN_USE_AFTER_RETURN, + "asan-use-after-return", + "Enable asan builtin functions protection", + 1, 0, 1) /* + Local variables: mode:c End: diff --git a/gcc/params.h b/gcc/params.h index 82870585293c..64f3a0fcbae0 100644 --- a/gcc/params.h +++ b/gcc/params.h @@ -218,5 +218,17 @@ extern void init_param_values (int *params); PARAM_VALUE (PARAM_ALLOW_PACKED_LOAD_DATA_RACES) #define ALLOW_PACKED_STORE_DATA_RACES \ PARAM_VALUE (PARAM_ALLOW_PACKED_STORE_DATA_RACES) +#define ASAN_STACK \ + PARAM_VALUE (PARAM_ASAN_STACK) +#define ASAN_GLOBALS \ + PARAM_VALUE (PARAM_ASAN_GLOBALS) +#define ASAN_INSTRUMENT_READS \ + PARAM_VALUE (PARAM_ASAN_INSTRUMENT_READS) +#define ASAN_INSTRUMENT_WRITES \ + PARAM_VALUE (PARAM_ASAN_INSTRUMENT_WRITES) +#define ASAN_MEMINTRIN \ + PARAM_VALUE (PARAM_ASAN_MEMINTRIN) +#define ASAN_USE_AFTER_RETURN \ + PARAM_VALUE (PARAM_ASAN_USE_AFTER_RETURN) #endif /* ! GCC_PARAMS_H */ diff --git a/gcc/ree.c b/gcc/ree.c index 152cc5aa914c..63cc8cc7c32e 100644 --- a/gcc/ree.c +++ b/gcc/ree.c @@ -282,8 +282,20 @@ static bool combine_set_extension (ext_cand *cand, rtx curr_insn, rtx *orig_set) { rtx orig_src = SET_SRC (*orig_set); - rtx new_reg = gen_rtx_REG (cand->mode, REGNO (SET_DEST (*orig_set))); rtx new_set; + rtx cand_pat = PATTERN (cand->insn); + + /* If the extension's source/destination registers are not the same + then we need to change the original load to reference the destination + of the extension. Then we need to emit a copy from that destination + to the original destination of the load. */ + rtx new_reg; + bool copy_needed + = (REGNO (SET_DEST (cand_pat)) != REGNO (XEXP (SET_SRC (cand_pat), 0))); + if (copy_needed) + new_reg = gen_rtx_REG (cand->mode, REGNO (SET_DEST (cand_pat))); + else + new_reg = gen_rtx_REG (cand->mode, REGNO (SET_DEST (*orig_set))); /* Merge constants by directly moving the constant into the register under some conditions. Recall that RTL constants are sign-extended. */ @@ -342,7 +354,8 @@ combine_set_extension (ext_cand *cand, rtx curr_insn, rtx *orig_set) if (dump_file) { fprintf (dump_file, - "Tentatively merged extension with definition:\n"); + "Tentatively merged extension with definition %s:\n", + (copy_needed) ? "(copy needed)" : ""); print_rtl_single (dump_file, curr_insn); } return true; @@ -567,27 +580,21 @@ make_defs_and_copies_lists (rtx extend_insn, const_rtx set_pat, return ret; } -/* Merge the DEF_INSN with an extension. Calls combine_set_extension - on the SET pattern. */ - -static bool -merge_def_and_ext (ext_cand *cand, rtx def_insn, ext_state *state) +/* If DEF_INSN has single SET expression, possibly buried inside + a PARALLEL, return the address of the SET expression, else + return NULL. This is similar to single_set, except that + single_set allows multiple SETs when all but one is dead. */ +static rtx * +get_sub_rtx (rtx def_insn) { - enum machine_mode ext_src_mode; - enum rtx_code code; - rtx *sub_rtx; - rtx s_expr; - int i; - - ext_src_mode = GET_MODE (XEXP (SET_SRC (cand->expr), 0)); - code = GET_CODE (PATTERN (def_insn)); - sub_rtx = NULL; + enum rtx_code code = GET_CODE (PATTERN (def_insn)); + rtx *sub_rtx = NULL; if (code == PARALLEL) { - for (i = 0; i < XVECLEN (PATTERN (def_insn), 0); i++) + for (int i = 0; i < XVECLEN (PATTERN (def_insn), 0); i++) { - s_expr = XVECEXP (PATTERN (def_insn), 0, i); + rtx s_expr = XVECEXP (PATTERN (def_insn), 0, i); if (GET_CODE (s_expr) != SET) continue; @@ -596,7 +603,7 @@ merge_def_and_ext (ext_cand *cand, rtx def_insn, ext_state *state) else { /* PARALLEL with multiple SETs. */ - return false; + return NULL; } } } @@ -605,10 +612,27 @@ merge_def_and_ext (ext_cand *cand, rtx def_insn, ext_state *state) else { /* It is not a PARALLEL or a SET, what could it be ? */ - return false; + return NULL; } gcc_assert (sub_rtx != NULL); + return sub_rtx; +} + +/* Merge the DEF_INSN with an extension. Calls combine_set_extension + on the SET pattern. */ + +static bool +merge_def_and_ext (ext_cand *cand, rtx def_insn, ext_state *state) +{ + enum machine_mode ext_src_mode; + rtx *sub_rtx; + + ext_src_mode = GET_MODE (XEXP (SET_SRC (cand->expr), 0)); + sub_rtx = get_sub_rtx (def_insn); + + if (sub_rtx == NULL) + return false; if (REG_P (SET_DEST (*sub_rtx)) && (GET_MODE (SET_DEST (*sub_rtx)) == ext_src_mode @@ -662,6 +686,72 @@ combine_reaching_defs (ext_cand *cand, const_rtx set_pat, ext_state *state) if (!outcome) return false; + /* If the destination operand of the extension is a different + register than the source operand, then additional restrictions + are needed. */ + if ((REGNO (SET_DEST (PATTERN (cand->insn))) + != REGNO (XEXP (SET_SRC (PATTERN (cand->insn)), 0)))) + { + /* In theory we could handle more than one reaching def, it + just makes the code to update the insn stream more complex. */ + if (state->defs_list.length () != 1) + return false; + + /* We require the candidate not already be modified. This may + be overly conservative. */ + if (state->modified[INSN_UID (cand->insn)].kind != EXT_MODIFIED_NONE) + return false; + + /* Transformation of + (set (reg1) (expression)) + (set (reg2) (any_extend (reg1))) + into + (set (reg2) (any_extend (expression))) + (set (reg1) (reg2)) + is only valid for scalar integral modes, as it relies on the low + subreg of reg1 to have the value of (expression), which is not true + e.g. for vector modes. */ + if (!SCALAR_INT_MODE_P (GET_MODE (SET_DEST (PATTERN (cand->insn))))) + return false; + + /* There's only one reaching def. */ + rtx def_insn = state->defs_list[0]; + + /* The defining statement must not have been modified either. */ + if (state->modified[INSN_UID (def_insn)].kind != EXT_MODIFIED_NONE) + return false; + + /* The defining statement and candidate insn must be in the same block. + This is merely to keep the test for safety and updating the insn + stream simple. Also ensure that within the block the candidate + follows the defining insn. */ + if (BLOCK_FOR_INSN (cand->insn) != BLOCK_FOR_INSN (def_insn) + || DF_INSN_LUID (def_insn) > DF_INSN_LUID (cand->insn)) + return false; + + /* If there is an overlap between the destination of DEF_INSN and + CAND->insn, then this transformation is not safe. Note we have + to test in the widened mode. */ + rtx *dest_sub_rtx = get_sub_rtx (def_insn); + if (dest_sub_rtx == NULL + || !REG_P (SET_DEST (*dest_sub_rtx))) + return false; + + rtx tmp_reg = gen_rtx_REG (GET_MODE (SET_DEST (PATTERN (cand->insn))), + REGNO (SET_DEST (*dest_sub_rtx))); + if (reg_overlap_mentioned_p (tmp_reg, SET_DEST (PATTERN (cand->insn)))) + return false; + + /* The destination register of the extension insn must not be + used or set between the def_insn and cand->insn exclusive. */ + if (reg_used_between_p (SET_DEST (PATTERN (cand->insn)), + def_insn, cand->insn) + || reg_set_between_p (SET_DEST (PATTERN (cand->insn)), + def_insn, cand->insn)) + return false; + } + + /* If cand->insn has been already modified, update cand->mode to a wider mode if possible, or punt. */ if (state->modified[INSN_UID (cand->insn)].kind != EXT_MODIFIED_NONE) @@ -778,8 +868,7 @@ add_removable_extension (const_rtx expr, rtx insn, if (REG_P (dest) && (code == SIGN_EXTEND || code == ZERO_EXTEND) - && REG_P (XEXP (src, 0)) - && REGNO (dest) == REGNO (XEXP (src, 0))) + && REG_P (XEXP (src, 0))) { struct df_link *defs, *def; ext_cand *cand; @@ -863,6 +952,7 @@ find_and_remove_re (void) int num_re_opportunities = 0, num_realized = 0, i; vec<ext_cand> reinsn_list; auto_vec<rtx> reinsn_del_list; + auto_vec<rtx> reinsn_copy_list; ext_state state; /* Construct DU chain to get all reaching definitions of each @@ -899,11 +989,41 @@ find_and_remove_re (void) if (dump_file) fprintf (dump_file, "Eliminated the extension.\n"); num_realized++; - reinsn_del_list.safe_push (curr_cand->insn); + if (REGNO (SET_DEST (PATTERN (curr_cand->insn))) + != REGNO (XEXP (SET_SRC (PATTERN (curr_cand->insn)), 0))) + { + reinsn_copy_list.safe_push (curr_cand->insn); + reinsn_copy_list.safe_push (state.defs_list[0]); + } + reinsn_del_list.safe_push (curr_cand->insn); state.modified[INSN_UID (curr_cand->insn)].deleted = 1; } } + /* The copy list contains pairs of insns which describe copies we + need to insert into the INSN stream. + + The first insn in each pair is the extension insn, from which + we derive the source and destination of the copy. + + The second insn in each pair is the memory reference where the + extension will ultimately happen. We emit the new copy + immediately after this insn. + + It may first appear that the arguments for the copy are reversed. + Remember that the memory reference will be changed to refer to the + destination of the extention. So we're actually emitting a copy + from the new destination to the old destination. */ + for (unsigned int i = 0; i < reinsn_copy_list.length (); i += 2) + { + rtx curr_insn = reinsn_copy_list[i]; + rtx pat = PATTERN (curr_insn); + rtx new_reg = gen_rtx_REG (GET_MODE (SET_DEST (pat)), + REGNO (XEXP (SET_SRC (pat), 0))); + rtx set = gen_rtx_SET (VOIDmode, new_reg, SET_DEST (pat)); + emit_insn_after (set, reinsn_copy_list[i + 1]); + } + /* Delete all useless extensions here in one sweep. */ FOR_EACH_VEC_ELT (reinsn_del_list, i, curr_insn) delete_insn (curr_insn); diff --git a/gcc/reorg.c b/gcc/reorg.c index 740da4a83c6c..de332323ae1c 100644 --- a/gcc/reorg.c +++ b/gcc/reorg.c @@ -1093,6 +1093,7 @@ steal_delay_list_from_target (rtx insn, rtx condition, rtx seq, int used_annul = 0; int i; struct resources cc_set; + bool *redundant; /* We can't do anything if there are more delay slots in SEQ than we can handle, or if we don't know that it will be a taken branch. @@ -1133,6 +1134,7 @@ steal_delay_list_from_target (rtx insn, rtx condition, rtx seq, return delay_list; #endif + redundant = XALLOCAVEC (bool, XVECLEN (seq, 0)); for (i = 1; i < XVECLEN (seq, 0); i++) { rtx trial = XVECEXP (seq, 0, i); @@ -1154,7 +1156,8 @@ steal_delay_list_from_target (rtx insn, rtx condition, rtx seq, /* If this insn was already done (usually in a previous delay slot), pretend we put it in our delay slot. */ - if (redundant_insn (trial, insn, new_delay_list)) + redundant[i] = redundant_insn (trial, insn, new_delay_list); + if (redundant[i]) continue; /* We will end up re-vectoring this branch, so compute flags @@ -1187,6 +1190,12 @@ steal_delay_list_from_target (rtx insn, rtx condition, rtx seq, return delay_list; } + /* Record the effect of the instructions that were redundant and which + we therefore decided not to copy. */ + for (i = 1; i < XVECLEN (seq, 0); i++) + if (redundant[i]) + update_block (XVECEXP (seq, 0, i), insn); + /* Show the place to which we will be branching. */ *pnew_thread = first_active_target_insn (JUMP_LABEL (XVECEXP (seq, 0, 0))); @@ -1250,6 +1259,7 @@ steal_delay_list_from_fallthrough (rtx insn, rtx condition, rtx seq, /* If this insn was already done, we don't need it. */ if (redundant_insn (trial, insn, delay_list)) { + update_block (trial, insn); delete_from_delay_slot (trial); continue; } @@ -3236,6 +3246,7 @@ relax_delay_slots (rtx first) to reprocess this insn. */ if (redundant_insn (XVECEXP (pat, 0, 1), delay_insn, 0)) { + update_block (XVECEXP (pat, 0, 1), insn); delete_from_delay_slot (XVECEXP (pat, 0, 1)); next = prev_active_insn (next); continue; @@ -3355,6 +3366,7 @@ relax_delay_slots (rtx first) && redirect_with_delay_slots_safe_p (delay_insn, target_label, insn)) { + update_block (XVECEXP (PATTERN (trial), 0, 1), insn); reorg_redirect_jump (delay_insn, target_label); next = insn; continue; diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c index 2c6bc3693a20..66d3c79e3e8b 100644 --- a/gcc/stor-layout.c +++ b/gcc/stor-layout.c @@ -2762,7 +2762,21 @@ get_mode_bounds (enum machine_mode mode, int sign, gcc_assert (size <= HOST_BITS_PER_WIDE_INT); - if (sign) + /* Special case BImode, which has values 0 and STORE_FLAG_VALUE. */ + if (mode == BImode) + { + if (STORE_FLAG_VALUE < 0) + { + min_val = STORE_FLAG_VALUE; + max_val = 0; + } + else + { + min_val = 0; + max_val = STORE_FLAG_VALUE; + } + } + else if (sign) { min_val = -((unsigned HOST_WIDE_INT) 1 << (size - 1)); max_val = ((unsigned HOST_WIDE_INT) 1 << (size - 1)) - 1; diff --git a/gcc/target-globals.c b/gcc/target-globals.c index 2cfe257d567b..8d3eaa89041e 100644 --- a/gcc/target-globals.c +++ b/gcc/target-globals.c @@ -68,30 +68,47 @@ struct target_globals * save_target_globals (void) { struct target_globals *g; - struct target_optabs *saved_this_fn_optabs = this_fn_optabs; - - g = ggc_alloc_target_globals (); - g->flag_state = XCNEW (struct target_flag_state); - g->regs = XCNEW (struct target_regs); + struct target_globals_extra { + struct target_globals g; + struct target_flag_state flag_state; + struct target_optabs optabs; + struct target_cfgloop cfgloop; + struct target_builtins builtins; + struct target_gcse gcse; + struct target_bb_reorder bb_reorder; + struct target_lower_subreg lower_subreg; + } *p; + p = (struct target_globals_extra *) + ggc_internal_cleared_alloc_stat (sizeof (struct target_globals_extra) + PASS_MEM_STAT); + g = (struct target_globals *) p; + g->flag_state = &p->flag_state; + g->regs = ggc_internal_cleared_alloc_stat (sizeof (struct target_regs) + PASS_MEM_STAT); g->rtl = ggc_alloc_cleared_target_rtl (); - g->hard_regs = XCNEW (struct target_hard_regs); - g->reload = XCNEW (struct target_reload); - g->expmed = XCNEW (struct target_expmed); - g->optabs = XCNEW (struct target_optabs); + g->hard_regs + = ggc_internal_cleared_alloc_stat (sizeof (struct target_hard_regs) + PASS_MEM_STAT); + g->reload = ggc_internal_cleared_alloc_stat (sizeof (struct target_reload) + PASS_MEM_STAT); + g->expmed = ggc_internal_cleared_alloc_stat (sizeof (struct target_expmed) + PASS_MEM_STAT); + g->optabs = &p->optabs; g->libfuncs = ggc_alloc_cleared_target_libfuncs (); - g->cfgloop = XCNEW (struct target_cfgloop); - g->ira = XCNEW (struct target_ira); - g->ira_int = XCNEW (struct target_ira_int); - g->lra_int = XCNEW (struct target_lra_int); - g->builtins = XCNEW (struct target_builtins); - g->gcse = XCNEW (struct target_gcse); - g->bb_reorder = XCNEW (struct target_bb_reorder); - g->lower_subreg = XCNEW (struct target_lower_subreg); + g->cfgloop = &p->cfgloop; + g->ira = ggc_internal_cleared_alloc_stat (sizeof (struct target_ira) + PASS_MEM_STAT); + g->ira_int = ggc_internal_cleared_alloc_stat (sizeof (struct target_ira_int) + PASS_MEM_STAT); + g->lra_int = ggc_internal_cleared_alloc_stat (sizeof (struct target_lra_int) + PASS_MEM_STAT); + g->builtins = &p->builtins; + g->gcse = &p->gcse; + g->bb_reorder = &p->bb_reorder; + g->lower_subreg = &p->lower_subreg; restore_target_globals (g); - this_fn_optabs = this_target_optabs; init_reg_sets (); target_reinit (); - this_fn_optabs = saved_this_fn_optabs; return g; } diff --git a/gcc/target-globals.h b/gcc/target-globals.h index b84d2902d9c2..e848a01677c0 100644 --- a/gcc/target-globals.h +++ b/gcc/target-globals.h @@ -37,26 +37,28 @@ extern struct target_builtins *this_target_builtins; extern struct target_gcse *this_target_gcse; extern struct target_bb_reorder *this_target_bb_reorder; extern struct target_lower_subreg *this_target_lower_subreg; +#endif struct GTY(()) target_globals { struct target_flag_state *GTY((skip)) flag_state; - struct target_regs *GTY((skip)) regs; + void *GTY((atomic)) regs; struct target_rtl *rtl; - struct target_hard_regs *GTY((skip)) hard_regs; - struct target_reload *GTY((skip)) reload; - struct target_expmed *GTY((skip)) expmed; + void *GTY((atomic)) hard_regs; + void *GTY((atomic)) reload; + void *GTY((atomic)) expmed; struct target_optabs *GTY((skip)) optabs; struct target_libfuncs *libfuncs; struct target_cfgloop *GTY((skip)) cfgloop; - struct target_ira *GTY((skip)) ira; - struct target_ira_int *GTY((skip)) ira_int; - struct target_lra_int *GTY((skip)) lra_int; + void *GTY((atomic)) ira; + void *GTY((atomic)) ira_int; + void *GTY((atomic)) lra_int; struct target_builtins *GTY((skip)) builtins; struct target_gcse *GTY((skip)) gcse; struct target_bb_reorder *GTY((skip)) bb_reorder; struct target_lower_subreg *GTY((skip)) lower_subreg; }; +#if SWITCHABLE_TARGET extern struct target_globals default_target_globals; extern struct target_globals *save_target_globals (void); @@ -66,17 +68,17 @@ static inline void restore_target_globals (struct target_globals *g) { this_target_flag_state = g->flag_state; - this_target_regs = g->regs; + this_target_regs = (struct target_regs *) g->regs; this_target_rtl = g->rtl; - this_target_hard_regs = g->hard_regs; - this_target_reload = g->reload; - this_target_expmed = g->expmed; + this_target_hard_regs = (struct target_hard_regs *) g->hard_regs; + this_target_reload = (struct target_reload *) g->reload; + this_target_expmed = (struct target_expmed *) g->expmed; this_target_optabs = g->optabs; this_target_libfuncs = g->libfuncs; this_target_cfgloop = g->cfgloop; - this_target_ira = g->ira; - this_target_ira_int = g->ira_int; - this_target_lra_int = g->lra_int; + this_target_ira = (struct target_ira *) g->ira; + this_target_ira_int = (struct target_ira_int *) g->ira_int; + this_target_lra_int = (struct target_lra_int *) g->lra_int; this_target_builtins = g->builtins; this_target_gcse = g->gcse; this_target_bb_reorder = g->bb_reorder; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ebf40341ef5f..126e6f037271 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,408 @@ +2014-01-13 Richard Biener <rguenther@suse.de> + + * g++.dg/lto/lto.exp: Do check_effective_target_lto check before + adjusting mathlib options. + * gfortran.dg/lto/lto.exp: Likewise. + +2014-01-13 Eric Botcazou <ebotcazou@adacore.com> + + * gnat.dg/loop_optimization17.adb: New test. + * gnat.dg/loop_optimization17_pkg.ad[sb]: New helper. + +2014-01-13 Christian Bruel <christian.bruel@st.com> + + * gcc.target/sh/cmpstrn.c: New case. + +2014-01-13 Jakub Jelinek <jakub@redhat.com> + + * gcc.dg/vect/vect-simd-clone-10.c: Add dg-do run. + * gcc.dg/vect/vect-simd-clone-12.c: Likewise. + +2014-01-12 Janus Weil <janus@gcc.gnu.org> + + PR fortran/58026 + * gfortran.dg/alloc_comp_basics_6.f90: New. + +2014-01-11 Steven G. Kargl <kargl@gcc.gnu.org> + + PR fortran/59700 + * gfortran.dg/pr59700.f90: New test. + +2014-01-11 Dominique d'Humieres <dominiq@lps.ens.fr> + + * gfortran.dg/binding_label_tests_10_main.f03: Cleanup mod file. + * gfortran.dg/use_only_3.f90: Likewise. + * gfortran.dg/inquire_10.f90: Delete opened file. + * gfortran.dg/inquire_15.f90: Likewise. + * gfortran.dg/pr16597.f90: Likewise. + * gfortran.dg/open_negative_unit_1.f90: Likewise + test + for PR59419. + +2014-01-10 Jeff Law <law@redhat.com> + + PR middle-end/59743 + * gcc.c-torture/compile/pr59743.c: New test. + +2014-01-10 Jan Hubicka <jh@suse.cz> + + PR ipa/58585 + * g++.dg/torture/pr58585.C: New testcase. + +2014-01-10 Hans-Peter Nilsson <hp@axis.com> + + * gcc.dg/pr46309.c: Disable for cris*-*-*. + +2014-01-10 Eric Botcazou <ebotcazou@adacore.com> + + * gcc.target/arm/neon-nested-apcs.c: Tweak dg directives. + +2014-01-10 Richard Earnshaw <rearnsha@arm.com> + + PR target/59744 + * gcc.target/aarch64/cmn-neg.c: Use equality comparisons. + * gcc.target/aarch64/cmn-neg2.c: New test. + +2014-01-10 Richard Biener <rguenther@suse.de> + + PR tree-optimization/59374 + * gcc.dg/torture/pr59374-3.c: New testcase. + +2014-01-10 Kyrylo Tkachov <kyrylo.tkachov@arm.com> + + * lib/target-supports.exp + (check_effective_target_arm_crypto_ok_nocache): New. + (check_effective_target_arm_crypto_ok): Use above procedure. + (add_options_for_arm_crypto): Use et_arm_crypto_flags. + +2014-01-10 Jan Hubicka <hubicka@ucw.cz> + + PR ipa/58252 + PR ipa/59226 + * g++.dg/ipa/devirt-20.C: New testcase. + * g++.dg/torture/pr58252.C: Likewise. + * g++.dg/torture/pr59226.C: Likewise. + +2014-01-10 Max Ostapenko <m.ostapenko@partner.samsung.com> + + * c-c++-common/asan/no-asan-stack.c: New test. + +2014-01-10 Jakub Jelinek <jakub@redhat.com> + + PR middle-end/59670 + * gcc.dg/pr59670.c: New test. + +2014-01-09 Steve Ellcey <sellcey@mips.com> + + * gcc.dg/delay-slot-1.c: Restrict -mabi=64 to 64 bit processors. + +2014-01-09 Jakub Jelinek <jakub@redhat.com> + + PR middle-end/47735 + * gcc.target/i386/pr47735.c: New test. + + PR tree-optimization/59622 + * g++.dg/opt/pr59622-2.C: New test. + * g++.dg/opt/pr59622-3.C: New test. + * g++.dg/opt/pr59622-4.C: New test. + * g++.dg/opt/pr59622-5.C: New test. + + PR sanitizer/59136 + * c-c++-common/asan/strip-path-prefix-1.c: Allow also the + filename:line instead of (modulename+offset) form with stripped + initial / from the filename. + +2014-01-09 Ian Lance Taylor <iant@google.com> + + * go.test/go-test.exp (go-gc-tests): Skip nilptr tests that test + the other Go compiler. + +2014-01-09 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/59730 + * g++.dg/cpp0x/variadic145.C: New. + +2014-01-09 Uros Bizjak <ubizjak@gmail.com> + + * go.test/go-test.exp (go-gc-tests): Don't run peano.go on systems + which don't support -fsplit-stack. Skip rotate[0123].go tests. + +2014-01-09 Balaji V. Iyer <balaji.v.iyer@intel.com> + + PR testsuite/59524 + * gcc.dg/cilk-plus/cilk-plus.exp: Make sure the cilk keywords tests + are run only if the Cilk library is available/enabled. + * g++.dg/cilk-plus/cilk-plus.exp: Likewise. + * lib/target-supports.exp (check_libcilkrts_available): New function. + +2014-01-09 Balaji V. Iyer <balaji.v.iyer@intel.com> + + PR c++/59631 + * gcc.dg/cilk-plus/cilk-plus.exp: Removed "-fcilkplus" from flags list. + * g++.dg/cilk-plus/cilk-plus.exp: Likewise. + * c-c++-common/cilk-plus/CK/spawnee_inline.c: Replaced second dg-option + with dg-additional-options. + * c-c++-common/cilk-plus/CK/varargs_test.c: Likewise. + * c-c++-common/cilk-plus/CK/steal_check.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/invalid_spawns.c: Added a dg-options tag. + * c-c++-common/cilk-plus/CK/pr59631.c: New testcase. + +2014-01-09 Richard Biener <rguenther@suse.de> + + PR tree-optimization/59715 + * gcc.dg/torture/pr59715.c: New testcase. + +2014-01-09 Max Ostapenko <m.ostapenko@partner.samsung.com> + + * c-c++-common/asan/no-asan-globals.c: New test. + * c-c++-common/asan/no-instrument-reads.c: Likewise. + * c-c++-common/asan/no-instrument-writes.c: Likewise. + * c-c++-common/asan/use-after-return-1.c: Likewise. + * c-c++-common/asan/no-use-after-return.c: Likewise. + +2014-01-08 Eric Botcazou <ebotcazou@adacore.com> + + * gnat.dg/weak2.ad[sb]: New test. + +2014-01-08 Jakub Jelinek <jakub@redhat.com> + + PR middle-end/59471 + * gcc.dg/pr59471.c (foo): Avoid vector type arguments or return + type, use pointers to vector type instead. + +2014-01-08 Catherine Moore <clm@codesourcery.com> + + * gcc.target/mips/umips-branch-3.c: New test. + * gcc.target/mips/umips-branch-4.c: New test. + +2014-01-08 Richard Sandiford <rdsandiford@googlemail.com> + + * gcc.dg/tree-ssa/reassoc-32.c, gcc.dg/tree-ssa/reassoc-33.c, + gcc.dg/tree-ssa/reassoc-34.c, gcc.dg/tree-ssa/reassoc-35.c, + gcc.dg/tree-ssa/reassoc-36.c: Extend -mbranch-cost handling to MIPS. + * gcc.dg/tree-ssa/ssa-ifcombine-ccmp-1.c, + gcc.dg/tree-ssa/ssa-ifcombine-ccmp-4.c, + gcc.dg/tree-ssa/ssa-ifcombine-ccmp-5.c, + gcc.dg/tree-ssa/ssa-ifcombine-ccmp-6.c, + gcc.dg/tree-ssa/vrp87.c, gcc.dg/tree-ssa/forwprop-28.c: Skip for MIPS. + +2014-01-08 Richard Sandiford <rdsandiford@googlemail.com> + + PR rtl-optimization/59137 + * gcc.target/mips/pr59137.c: New test. + +2014-01-08 Uros Bizjak <ubizjak@gmail.com> + + * gcc.target/i386/asm-1.c (dg-options): Remove -m32. + * gcc.target/i386/incoming-5.c (dg-options): Ditto. + * gcc.target/i386/pr55433.c (dg-options): Ditto. + * gcc.target/i386/pr57848.c (dg-options): Ditto. + * gcc.target/i386/pr59099.c (dg-options): Ditto. + Require fpic effective target. + * gcc.target/i386/pr56246.c (dg-do): Compile for fpic target only. + +2014-01-08 Jakub Jelinek <jakub@redhat.com> + + PR ipa/59722 + * gcc.dg/pr59722.c: New test. + +2014-01-08 Bernd Edlinger <bernd.edlinger@hotmail.de> + + PR middle-end/57748 + * gcc.dg/torture/pr57748-3.c: New test. + * gcc.dg/torture/pr57748-4.c: New test. + +2014-01-08 Marek Polacek <polacek@redhat.com> + + PR middle-end/59669 + * gcc.dg/gomp/pr59669-1.c: New test. + * gcc.dg/gomp/pr59669-2.c: New test. + +2014-01-08 Martin Jambor <mjambor@suse.cz> + + PR ipa/59610 + * gcc.dg/ipa/pr59610.c: New test. + +2014-01-08 Janus Weil <janus@gcc.gnu.org> + + PR fortran/58182 + * gfortran.dg/binding_label_tests_26a.f90: New. + * gfortran.dg/binding_label_tests_26b.f90: New. + +2014-01-08 Marek Polacek <polacek@redhat.com> + + PR sanitizer/59667 + * c-c++-common/ubsan/pr59667.c: New test. + +2014-01-08 Richard Biener <rguenther@suse.de> + + PR middle-end/59630 + * gcc.dg/pr59630.c: New testcase. + +2014-01-08 Richard Biener <rguenther@suse.de> + + PR middle-end/59471 + * gcc.dg/pr59471.c: New testcase. + +2014-01-07 Jeff Law <law@redhat.com> + + PR middle-end/53623 + * gcc.target/i386/pr53623.c: New test. + +2014-01-07 Adam Butcher <adam@jessamine.co.uk> + + * g++.dg/cpp1y/pr58500.C: Hoist PR reference to first line and remove + blanks at EOF. + * g++.dg/cpp1y/pr58534.C: Likewise. + * g++.dg/cpp1y/pr58536.C: Likewise. + * g++.dg/cpp1y/pr58548.C: Likewise. + * g++.dg/cpp1y/pr58549.C: Likewise. + * g++.dg/cpp1y/pr58637.C: Likewise. + * g++.dg/cpp1y/pr59112.C: Likewise. + * g++.dg/cpp1y/pr59113.C: Likewise. + * g++.dg/cpp1y/pr59629.C: Likewise. + * g++.dg/cpp1y/pr59635.C: Likewise. + * g++.dg/cpp1y/pr59636.C: Likewise. + * g++.dg/cpp1y/pr59638.C: Likewise. + +2014-01-07 Yufeng Zhang <yufeng.zhang@arm.com> + + * gcc.target/arm/neon/vst1Q_laneu64-1.c: New test. + +2014-01-07 Richard Sandiford <rdsandiford@googlemail.com> + + * gcc.target/i386/intrinsics_4.c (bar): New function. + +2014-01-07 Paolo Carlini <paolo.carlini@oracle.com> + + * g++.dg/ext/is_base_of_incomplete-2.C: New. + +2014-01-07 Jakub Jelinek <jakub@redhat.com> + + PR rtl-optimization/58668 + * gcc.dg/pr58668.c: New test. + + PR tree-optimization/59643 + * gcc.dg/pr59643.c: New test. + * gcc.c-torture/execute/pr59643.c: New test. + +2014-01-06 Janus Weil <janus@gcc.gnu.org> + + PR fortran/59589 + * gfortran.dg/class_allocate_16.f90: New. + +2014-01-06 Jakub Jelinek <jakub@redhat.com> + + PR target/59644 + * gcc.target/i386/pr59644.c: New test. + +2014-01-06 Marek Polacek <polacek@redhat.com> + + PR c/57773 + * gcc.dg/pr57773.c: New test. + +2014-01-06 Adam Butcher <adam@jessamine.co.uk> + + PR c++/59635 + PR c++/59636 + PR c++/59629 + PR c++/59638 + * g++.dg/cpp1y/pr59635.C: New testcase. + * g++.dg/cpp1y/pr59636.C: New testcase. + * g++.dg/cpp1y/pr59629.C: New testcase. + * g++.dg/cpp1y/pr59638.C: New testcase. + +2014-01-06 Martin Jambor <mjambor@suse.cz> + + PR ipa/59008 + * gcc.dg/ipa/pr59008.c: New test. + +2014-01-06 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + * gcc.dg/vect/vect.exp: Add clearcap_ldflags to DEFAULT_VECTCFLAGS + if supported. + +2014-01-06 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + * gcc.target/i386/avx512f-vcmppd-2.c: Add -std=c99. + Require c99_runtime. + * gcc.target/i386/avx512f-vcmpps-2.c: Likewise. + + * gcc.target/i386/avx512f-vfixupimmpd-2.c: Add -std=gnu99. + Require c99_runtime. + * gcc.target/i386/avx512f-vfixupimmps-2.c: Likewise. + * gcc.target/i386/avx512f-vfixupimmsd-2.c: Likewise. + * gcc.target/i386/avx512f-vfixupimmss-2.c: Likewise. + + * gcc.target/i386/avx512f-vgetmantpd-2.c: Add -std=c99. + Require c99_runtime. + Make CALC void static. + * gcc.target/i386/avx512f-vgetmantps-2.c: Likewise. + + * gcc.target/i386/avx512f-vgetmantsd-2.c: Add -std=c99. + Require c99_runtime. + * gcc.target/i386/avx512f-vgetmantss-2.c: Likewise. + +2014-01-06 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + * gcc.target/i386/pr59501-1.c: Require avx effective target. + * gcc.target/i386/pr59501-2.c: Likewise. + * gcc.target/i386/pr59501-3.c: Likewise. + * gcc.target/i386/pr59501-4.c: Likewise. + * gcc.target/i386/pr59501-5.c: Likewise. + * gcc.target/i386/pr59501-6.c: Likewise. + +2014-01-06 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + * gcc.target/i386/pr59390.c: Replace math.h by fma declaration. + * gcc.target/i386/pr59390_1.c: Likewise. + * gcc.target/i386/pr59390_2.c: Likewise. + +2014-01-06 Eric Botcazou <ebotcazou@adacore.com> + + * gcc.dg/pr59350.c: Tweak. + * gcc.dg/pr59350-2.c: New test. + * g++.dg/pr59510.C: Likewise. + +2014-01-06 Janus Weil <janus@gcc.gnu.org> + + PR fortran/59023 + * gfortran.dg/bind_c_procs_2.f90: New. + +2014-01-05 John David Anglin <danglin@gcc.gnu.org> + + * gcc.dg/tree-ssa/reassoc-33.c: Don't run on hppa*-*-*. + * gcc.dg/tree-ssa/reassoc-34.c: Likewise. + * gcc.dg/tree-ssa/reassoc-35.c: Likewise. + * gcc.dg/tree-ssa/reassoc-36.c: Likewise. + * gcc.dg/tree-ssa/forwprop-28.c: Skip compile on hppa*-*-*. + * gcc.dg/tree-ssa/vrp47.c: Likewise. + * gcc.dg/tree-ssa/vrp87.c: Likewise. + +2014-01-04 Eric Botcazou <ebotcazou@adacore.com> + + * gcc.target/arm/neon-nested-apcs.c: New test. + +2014-01-04 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/59519 + * gcc.dg/vect/pr59519-1.c: New test. + * gcc.dg/vect/pr59519-2.c: New test. + + * gcc.target/i386/avx512f-vmovdqu32-1.c: Allow vmovdqu64 instead of + vmovdqu32. + +2014-01-04 Janus Weil <janus@gcc.gnu.org> + + PR fortran/59547 + * gfortran.dg/typebound_proc_32.f90: New. + +2014-01-03 Marc Glisse <marc.glisse@inria.fr> + + PR c++/58950 + * g++.dg/pr58950.C: New file. + 2014-01-03 Tobias Burnus <burnus@net-b.de> PR c++/58567 diff --git a/gcc/testsuite/c-c++-common/asan/no-asan-globals.c b/gcc/testsuite/c-c++-common/asan/no-asan-globals.c new file mode 100644 index 000000000000..70a1f95a3a31 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/no-asan-globals.c @@ -0,0 +1,13 @@ +/* { dg-do assemble } */ +/* { dg-options "-save-temps --param asan-globals=0" } */ + +volatile int ten = 10; + +int main() { + volatile static char XXX[10]; + XXX[ten]; + return 0; +} + +/* { dg-final { scan-assembler-not "__asan_register_globals" } } */ +/* { dg-final { cleanup-saved-temps } } */ diff --git a/gcc/testsuite/c-c++-common/asan/no-asan-stack.c b/gcc/testsuite/c-c++-common/asan/no-asan-stack.c new file mode 100644 index 000000000000..0f65ab3f7acf --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/no-asan-stack.c @@ -0,0 +1,16 @@ +/* { dg-do compile { target { { i?86-*-linux* x86_64-*-linux* } && lp64 } } } */ +/* { dg-options "--param asan-stack=0" } */ +#include <string.h> + +volatile int one = 1; + +int +main () +{ + volatile char a1[] = {one, 2, 3, 4}; + volatile char a2[] = {1, 2*one, 3, 4}; + volatile int res = memcmp ((void *)a1,(void *)a2, 5 + one); + return 0; +} + +/* { dg-final { scan-assembler-not "0x41b58ab3|0x41B58AB3|1102416563" } } */ diff --git a/gcc/testsuite/c-c++-common/asan/no-instrument-reads.c b/gcc/testsuite/c-c++-common/asan/no-instrument-reads.c new file mode 100644 index 000000000000..df75878de2f4 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/no-instrument-reads.c @@ -0,0 +1,13 @@ +/* { dg-do assemble } */ +/* { dg-options "--param asan-instrument-reads=0 -save-temps" } */ + +volatile int ten = 10; + +int main() { + volatile char x[10]; + x[ten]; + return 0; +} + +/* { dg-final { scan-assembler-not "__asan_load" } } */ +/* { dg-final { cleanup-saved-temps } } */ diff --git a/gcc/testsuite/c-c++-common/asan/no-instrument-writes.c b/gcc/testsuite/c-c++-common/asan/no-instrument-writes.c new file mode 100644 index 000000000000..c1500b9fb321 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/no-instrument-writes.c @@ -0,0 +1,13 @@ +/* { dg-do assemble } */ +/* { dg-options "--param asan-instrument-writes=0 -save-temps" } */ + +volatile int ten = 10; + +int main() { + volatile char x[10]; + x[ten] = 1; + return 0; +} + +/* { dg-final { scan-assembler-not "__asan_store" } } */ +/* { dg-final { cleanup-saved-temps } } */ diff --git a/gcc/testsuite/c-c++-common/asan/no-use-after-return.c b/gcc/testsuite/c-c++-common/asan/no-use-after-return.c new file mode 100644 index 000000000000..f326e0caee4e --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/no-use-after-return.c @@ -0,0 +1,13 @@ +/* { dg-do assemble } */ +/* { dg-options "--param asan-use-after-return=0 -save-temps" } */ + +extern void f(char *); + +int main() { + char buf[64]; + f(buf); + return 0; +} + +/* { dg-final { scan-assembler-not "__asan_option_detect_stack_use_after_return" } } */ +/* { dg-final { cleanup-saved-temps } } */ diff --git a/gcc/testsuite/c-c++-common/asan/strip-path-prefix-1.c b/gcc/testsuite/c-c++-common/asan/strip-path-prefix-1.c index ea8e933c03bf..812aa37e2d0e 100644 --- a/gcc/testsuite/c-c++-common/asan/strip-path-prefix-1.c +++ b/gcc/testsuite/c-c++-common/asan/strip-path-prefix-1.c @@ -12,4 +12,4 @@ int main() { } /* { dg-output "heap-use-after-free.*(\n|\r\n|\r)" } */ -/* { dg-output " #0 0x\[0-9a-f\]+ \[(\]\[^/\]\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output " #0 0x\[0-9a-f\]+ \[(\]?\[^/\]\[^\n\r]*(\n|\r\n|\r)" } */ diff --git a/gcc/testsuite/c-c++-common/asan/use-after-return-1.c b/gcc/testsuite/c-c++-common/asan/use-after-return-1.c new file mode 100644 index 000000000000..435637d53231 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/use-after-return-1.c @@ -0,0 +1,53 @@ +/* { dg-do run } */ +/* { dg-set-target-env-var ASAN_OPTIONS "detect_stack_use_after_return=1" } */ +/* { dg-shouldfail "asan" } */ + +#include <stdio.h> +#include <pthread.h> + +#ifndef kSize +# define kSize 1 +#endif + +#ifndef UseThread +# define UseThread 0 +#endif + +__attribute__((noinline)) +char *Ident(char *x) { + fprintf(stderr, "1: %p\n", x); + return x; +} + +__attribute__((noinline)) +char *Func1() { + char local[kSize]; + return Ident(local); +} + +__attribute__((noinline)) +void Func2(char *x) { + fprintf(stderr, "2: %p\n", x); + *x = 1; +} + +void *Thread(void *unused) { + Func2(Func1()); + return NULL; +} + +int main(int argc, char **argv) { +#if UseThread + pthread_t t; + pthread_create(&t, 0, Thread, 0); + pthread_join(t, 0); +#else + Func2(Func1()); +#endif + return 0; +} + +/* { dg-output "WRITE of size 1 at .* thread T0.*" } */ +/* { dg-output " #0.*Func2.*use-after-return-1.c:31.*" } */ +/* { dg-output "is located in stack of thread T0 at offset.*" } */ +/* { dg-output "\'local\' <== Memory access at offset 32 is inside this variable" } */ 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 index 90dd5c130b41..ba9e6193627e 100644 --- a/gcc/testsuite/c-c++-common/cilk-plus/CK/invalid_spawns.c +++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/invalid_spawns.c @@ -1,3 +1,5 @@ +/* { dg-options "-fcilkplus" } */ + extern int foo (); int bar = _Cilk_spawn foo (); /* { dg-error "may only be used inside a function" } */ diff --git a/gcc/testsuite/c-c++-common/cilk-plus/CK/pr59631.c b/gcc/testsuite/c-c++-common/cilk-plus/CK/pr59631.c new file mode 100644 index 000000000000..389ee7c5dab0 --- /dev/null +++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/pr59631.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options " " } */ + +/* Tests the errors when Cilk keywords are used without -fcilkplus. */ + +void foo() +{ + _Cilk_spawn foo(); /* { dg-error "must be enabled to use" } */ +} + +void foo2 () +{ + _Cilk_spawn foo (); /* { dg-error "must be enabled to use" } */ + _Cilk_sync; /* { dg-error "must be enabled to use" } */ +} 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 index 8060c6ceb15c..233a371f140e 100644 --- a/gcc/testsuite/c-c++-common/cilk-plus/CK/spawnee_inline.c +++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/spawnee_inline.c @@ -1,6 +1,6 @@ /* { dg-do run { target { i?86-*-* x86_64-*-* } } } */ /* { dg-options "-fcilkplus -w" } */ -/* { dg-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */ +/* { dg-additional-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */ #include <stdio.h> #include <stdlib.h> 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 index eab9e4206a05..55ec223abb35 100644 --- a/gcc/testsuite/c-c++-common/cilk-plus/CK/spawner_inline.c +++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/spawner_inline.c @@ -1,6 +1,6 @@ /* { dg-do run { target { i?86-*-* x86_64-*-* } } } */ /* { dg-options "-fcilkplus" } */ -/* { dg-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */ +/* { dg-additional-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */ #include <stdlib.h> #define DEFAULT_VALUE 30 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 index ac3795283795..95e6cab02c13 100644 --- a/gcc/testsuite/c-c++-common/cilk-plus/CK/spawning_arg.c +++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/spawning_arg.c @@ -1,6 +1,6 @@ /* { dg-do run { target { i?86-*-* x86_64-*-* } } } */ /* { dg-options "-fcilkplus" } */ -/* { dg-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */ +/* { dg-additional-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */ void f0(volatile int *steal_flag) { 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 index 21d6797857dc..6e2876531c3a 100644 --- a/gcc/testsuite/c-c++-common/cilk-plus/CK/steal_check.c +++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/steal_check.c @@ -1,6 +1,6 @@ /* { dg-do run { target { i?86-*-* x86_64-*-* } } } */ /* { dg-options "-fcilkplus" } */ -/* { dg-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */ +/* { dg-additional-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */ // #include <cilk/cilk_api.h> extern void __cilkrts_set_param (char *, char *); 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 index ab5d63a3f4c6..271460024409 100644 --- a/gcc/testsuite/c-c++-common/cilk-plus/CK/varargs_test.c +++ b/gcc/testsuite/c-c++-common/cilk-plus/CK/varargs_test.c @@ -1,6 +1,6 @@ /* { dg-do run { target { i?86-*-* x86_64-*-* } } } */ /* { dg-options "-fcilkplus" } */ -/* { dg-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */ +/* { dg-additional-options "-lcilkrts" { target { i?86-*-* x86_64-*-* } } } */ #include <stdarg.h> #include <stdlib.h> diff --git a/gcc/testsuite/c-c++-common/ubsan/pr59667.c b/gcc/testsuite/c-c++-common/ubsan/pr59667.c new file mode 100644 index 000000000000..367e3034629d --- /dev/null +++ b/gcc/testsuite/c-c++-common/ubsan/pr59667.c @@ -0,0 +1,15 @@ +/* { dg-do run } */ +/* { dg-options "-fsanitize=undefined" } */ +/* { dg-shouldfail "ubsan" } */ +/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */ + +int +main (void) +{ + unsigned int len = 1; + float (*P)[len][len] = 0; + (*P)[0][0] = 1; + return 0; +} + +/* { dg-output "store to null pointer of type 'float'(\n|\r\n|\r)" } */ diff --git a/gcc/testsuite/g++.dg/abi/abi-tag5.C b/gcc/testsuite/g++.dg/abi/abi-tag5.C index de5580239dd7..95e367ef935f 100644 --- a/gcc/testsuite/g++.dg/abi/abi-tag5.C +++ b/gcc/testsuite/g++.dg/abi/abi-tag5.C @@ -1,6 +1,7 @@ // { dg-options -Wabi-tag } +// { dg-final { scan-assembler "_Z1f1BI1AB3fooE" } } struct __attribute__ ((abi_tag ("foo"))) A { }; template <class T> struct B: T { }; -B<A> b; +void f(B<A>) {} diff --git a/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp b/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp index e201fd227cfd..37b8ccbe70ae 100644 --- a/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp +++ b/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp @@ -47,9 +47,7 @@ dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -g dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -g -O2 -ftree-vectorize -fcilkplus" " " dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -g -O3 -fcilkplus" " " dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -O3 -ftree-vectorize -fcilkplus -g" " " -dg-finish -dg-init dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -fcilkplus" " " dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -O0 -fcilkplus" " " dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -O1 -fcilkplus" " " @@ -61,25 +59,17 @@ dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -g -O1 dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -g -O2 -ftree-vectorize -fcilkplus" " " dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -g -O3 -fcilkplus" " " dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/AN/*.cc]] " -O3 -ftree-vectorize -fcilkplus -g" " " -dg-finish -dg-init -dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/CK/*.cc]] " -fcilkplus" " " -dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/CK/*.cc]] " -O1 -fcilkplus" " " -dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/CK/*.cc]] " -O2 -fcilkplus" " " -dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/CK/*.cc]] " -O3 -fcilkplus" " " -dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/CK/*.cc]] " -g -fcilkplus" " " -dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/CK/*.cc]] " -g -O2 -fcilkplus" " " -dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/CK/*.cc]] " -g -O3 -fcilkplus" " " -dg-finish +if { [check_libcilkrts_available] } { + dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/CK/*.cc]] " -O1 -fcilkplus" " " + dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/CK/*.cc]] " -O3 -fcilkplus" " " + dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/CK/*.cc]] " -g -fcilkplus" " " + dg-runtest [lsort [glob -nocomplain $srcdir/g++.dg/cilk-plus/CK/*.cc]] " -g -O2 -fcilkplus" " " -dg-init -dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -fcilkplus" " " -dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O1 -fcilkplus" " " -dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O2 -fcilkplus" " " -dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O3 -fcilkplus" " " -dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -g -fcilkplus" " " -dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -g -O2 -fcilkplus" " " -dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -g -O3 -fcilkplus" " " + dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O1" " " + dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O3" " " + dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -g" " " + dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -g -O2" " " + } dg-finish unset TEST_EXTRA_LIBS diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-39.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-39.C new file mode 100644 index 000000000000..9fe553861886 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-39.C @@ -0,0 +1,11 @@ +// PR c++/58856 +// { dg-require-effective-target c++11 } + +template <typename T> +struct U1 {}; + +template <typename T1, typename... Ts> +using U2 = U1<T1>; + +template <typename T1, typename... Ts> +using U3 = U2<T1, Ts...>; diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-union3.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-union3.C new file mode 100644 index 000000000000..35f6509df786 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-union3.C @@ -0,0 +1,10 @@ +// PR c++/58965 +// { dg-require-effective-target c++11 } + +void foo() +{ + static union + { + int i = i; + }; +} diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic145.C b/gcc/testsuite/g++.dg/cpp0x/variadic145.C new file mode 100644 index 000000000000..65edda59fd85 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/variadic145.C @@ -0,0 +1,13 @@ +// PR c++/59730 +// { dg-do compile { target c++11 } } + +template <typename> void declval(); +template <typename> void forward(); +template <typename> class D; +template <typename _Functor, typename... _Bound_args> +class D <_Functor(_Bound_args...)> { + template <typename... _Args, decltype(declval<_Functor>)> + void operator()(...) { + 0(forward<_Args>...); + } +}; diff --git a/gcc/testsuite/g++.dg/cpp1y/pr58500.C b/gcc/testsuite/g++.dg/cpp1y/pr58500.C index b9d4a26d4159..7adb1b8ae4c7 100644 --- a/gcc/testsuite/g++.dg/cpp1y/pr58500.C +++ b/gcc/testsuite/g++.dg/cpp1y/pr58500.C @@ -1,8 +1,7 @@ +// PR c++/58500 // { dg-do compile } // { dg-options "-std=gnu++1y" } -// PR c++/58500 - struct A {}; void foo(auto (A::*)()); diff --git a/gcc/testsuite/g++.dg/cpp1y/pr58534.C b/gcc/testsuite/g++.dg/cpp1y/pr58534.C index 4aa4f4301898..3319f6969568 100644 --- a/gcc/testsuite/g++.dg/cpp1y/pr58534.C +++ b/gcc/testsuite/g++.dg/cpp1y/pr58534.C @@ -1,9 +1,7 @@ +// PR c++/58534 // { dg-do compile } // { dg-options "-std=gnu++1y" } -// PR c++/58534 - template<typename> void foo(const auto&) {} template<typename, typename...T> void foo(const auto&, T...) {} - diff --git a/gcc/testsuite/g++.dg/cpp1y/pr58536.C b/gcc/testsuite/g++.dg/cpp1y/pr58536.C index 8050c1957c83..be0043823a0f 100644 --- a/gcc/testsuite/g++.dg/cpp1y/pr58536.C +++ b/gcc/testsuite/g++.dg/cpp1y/pr58536.C @@ -1,12 +1,10 @@ +// PR c++/58536 // { dg-do compile } // { dg-options "-std=gnu++1y" } -// PR c++/58536 - struct A { A(auto); }; A::A(auto) {} - diff --git a/gcc/testsuite/g++.dg/cpp1y/pr58548.C b/gcc/testsuite/g++.dg/cpp1y/pr58548.C index 0ac2e1c341d0..ad6f726a33cc 100644 --- a/gcc/testsuite/g++.dg/cpp1y/pr58548.C +++ b/gcc/testsuite/g++.dg/cpp1y/pr58548.C @@ -1,10 +1,8 @@ +// PR c++/58548 // { dg-do compile } // { dg-options "-std=gnu++1y" } -// PR c++/58548 - void foo(auto) { struct A { int i; }; } - diff --git a/gcc/testsuite/g++.dg/cpp1y/pr58549.C b/gcc/testsuite/g++.dg/cpp1y/pr58549.C index b71bac9975af..b9825b51abc8 100644 --- a/gcc/testsuite/g++.dg/cpp1y/pr58549.C +++ b/gcc/testsuite/g++.dg/cpp1y/pr58549.C @@ -1,10 +1,8 @@ +// PR c++/58549 // { dg-do compile } // { dg-options "-std=gnu++1y" } -// PR c++/58549 - void foo(auto) { void bar(); } - diff --git a/gcc/testsuite/g++.dg/cpp1y/pr58637.C b/gcc/testsuite/g++.dg/cpp1y/pr58637.C index 46200ff1c5dd..29297bb93dbf 100644 --- a/gcc/testsuite/g++.dg/cpp1y/pr58637.C +++ b/gcc/testsuite/g++.dg/cpp1y/pr58637.C @@ -1,7 +1,5 @@ +// PR c++/58637 // { dg-do compile } // { dg-options "-std=gnu++1y" } -// PR c++/58637 - template<> void foo(auto); // { dg-error "auto|not a template" } - diff --git a/gcc/testsuite/g++.dg/cpp1y/pr59112.C b/gcc/testsuite/g++.dg/cpp1y/pr59112.C index e7326ac31130..12fef4b9fac7 100644 --- a/gcc/testsuite/g++.dg/cpp1y/pr59112.C +++ b/gcc/testsuite/g++.dg/cpp1y/pr59112.C @@ -1,8 +1,7 @@ +// PR c++/59112 // { dg-do compile } // { dg-options "-std=gnu++1y" } -// PR c++/59112 - void foo() { struct A diff --git a/gcc/testsuite/g++.dg/cpp1y/pr59113.C b/gcc/testsuite/g++.dg/cpp1y/pr59113.C index f909a76bd358..19bab2cedcc9 100644 --- a/gcc/testsuite/g++.dg/cpp1y/pr59113.C +++ b/gcc/testsuite/g++.dg/cpp1y/pr59113.C @@ -1,8 +1,7 @@ +// PR c++/59113 // { dg-do compile } // { dg-options "-std=gnu++1y" } -// PR c++/59113 - void foo() { void bar(auto) {} // { dg-error "function-definition|auto|not permitted" } diff --git a/gcc/testsuite/g++.dg/cpp1y/pr59629.C b/gcc/testsuite/g++.dg/cpp1y/pr59629.C new file mode 100644 index 000000000000..c0e01c1c75de --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/pr59629.C @@ -0,0 +1,5 @@ +// PR c++/59629 +// { dg-do compile } +// { dg-options "-std=c++1y" } + +void foo(int i = []{ auto 0; }()); // { dg-error "expected|could not convert" } diff --git a/gcc/testsuite/g++.dg/cpp1y/pr59635.C b/gcc/testsuite/g++.dg/cpp1y/pr59635.C new file mode 100644 index 000000000000..16a3481b99dc --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/pr59635.C @@ -0,0 +1,7 @@ +// PR c++/59635 +// { dg-do compile } +// { dg-options "-std=c++1y" } + +auto f = [] (auto, ...) { return 0; }; + +int (*p) (int, ...) = f; // { dg-message "unimplemented" } diff --git a/gcc/testsuite/g++.dg/cpp1y/pr59636.C b/gcc/testsuite/g++.dg/cpp1y/pr59636.C new file mode 100644 index 000000000000..bb7d9b546d44 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/pr59636.C @@ -0,0 +1,5 @@ +// PR c++/59636 +// { dg-do compile } +// { dg-options "-std=c++1y" } + +auto f = []() { return []<>() {}; }; // { dg-error "expected identifier" } diff --git a/gcc/testsuite/g++.dg/cpp1y/pr59638.C b/gcc/testsuite/g++.dg/cpp1y/pr59638.C new file mode 100644 index 000000000000..22af1398a13b --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/pr59638.C @@ -0,0 +1,14 @@ +// PR c++/59638 +// { dg-do compile } +// { dg-options "-std=gnu++1y" } + +void (*a)(auto); // { dg-error "template declaration" } + +void (*b)(auto) = 0; // { dg-error "template declaration" } + +typedef void (*f)(auto); // { dg-error "template declaration" } + +struct A +{ + int i; +}; diff --git a/gcc/testsuite/g++.dg/ext/is_base_of_incomplete-2.C b/gcc/testsuite/g++.dg/ext/is_base_of_incomplete-2.C new file mode 100644 index 000000000000..54862585d099 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/is_base_of_incomplete-2.C @@ -0,0 +1,5 @@ +struct T; + +int check1[__is_base_of(T, T) ? 1 : -1]; +int check2[__is_base_of(T, const T) ? 1 : -1]; +int check3[__is_base_of(volatile T, T) ? 1 : -1]; diff --git a/gcc/testsuite/g++.dg/ipa/devirt-20.C b/gcc/testsuite/g++.dg/ipa/devirt-20.C new file mode 100644 index 000000000000..aee95147a634 --- /dev/null +++ b/gcc/testsuite/g++.dg/ipa/devirt-20.C @@ -0,0 +1,31 @@ +#include <stdlib.h> +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-release_ssa" } */ +namespace { +struct A +{ int a; virtual int foo() {return a;} void bar() {a=7;} }; +struct B +{ int b; virtual int foo2() {return b;} void bar2() {b=9;} }; +struct C : public virtual A, public virtual B { }; +struct D : public virtual B, public virtual A { }; +struct E : public C, public D { void bar2() {b=9;} }; } +int +main(void) +{ + struct E e; + struct C *c = &e; + struct D *d = &e; + struct A *a = &e; + struct B *b = &e; + e.bar(); + e.bar2(); + if (e.foo() + e.foo2() != 16) + abort (); + if (c->foo() + d->foo2() != 16) + abort (); + if (a->foo() + b->foo2() != 16) + abort (); + return 0; +} +/* { dg-final { scan-tree-dump-not "abort" "release_ssa" } } */ +/* { dg-final { cleanup-ipa-dump "release_ssa" } } */ diff --git a/gcc/testsuite/g++.dg/lto/lto.exp b/gcc/testsuite/g++.dg/lto/lto.exp index 9145af782480..4d7d727b9870 100644 --- a/gcc/testsuite/g++.dg/lto/lto.exp +++ b/gcc/testsuite/g++.dg/lto/lto.exp @@ -35,6 +35,11 @@ load_lib target-libpath.exp # Load the language-independent compabibility support procedures. load_lib lto.exp +# If LTO has not been enabled, bail. +if { ![check_effective_target_lto] } { + return +} + g++_init lto_init no-mathlib @@ -42,11 +47,6 @@ lto_init no-mathlib # with other lto tests running at the same time. set sid "cp_lto" -# If LTO has not been enabled, bail. -if { ![check_effective_target_lto] } { - return -} - # Main loop. foreach src [lsort [find $srcdir/$subdir *_0.\[cC\]]] { # If we're only testing specific files and this isn't one of them, skip it. diff --git a/gcc/testsuite/g++.dg/opt/pr59622-2.C b/gcc/testsuite/g++.dg/opt/pr59622-2.C new file mode 100644 index 000000000000..8096eebca40b --- /dev/null +++ b/gcc/testsuite/g++.dg/opt/pr59622-2.C @@ -0,0 +1,21 @@ +// PR tree-optimization/59622 +// { dg-do compile } +// { dg-options "-O2" } + +namespace +{ + struct A + { + A () {} + virtual A *bar (int) = 0; + A *baz (int x) { return bar (x); } + }; +} + +A *a; + +void +foo () +{ + a->baz (0); +} diff --git a/gcc/testsuite/g++.dg/opt/pr59622-3.C b/gcc/testsuite/g++.dg/opt/pr59622-3.C new file mode 100644 index 000000000000..0af86050c23a --- /dev/null +++ b/gcc/testsuite/g++.dg/opt/pr59622-3.C @@ -0,0 +1,21 @@ +// PR tree-optimization/59622 +// { dg-do compile } +// { dg-options "-O2" } + +struct C { int a; int b; }; + +namespace +{ + struct A + { + virtual C foo (); + C bar () { return foo (); } + }; +} + +C +baz () +{ + A a; + return a.bar (); +} diff --git a/gcc/testsuite/g++.dg/opt/pr59622-4.C b/gcc/testsuite/g++.dg/opt/pr59622-4.C new file mode 100644 index 000000000000..f72af1641c86 --- /dev/null +++ b/gcc/testsuite/g++.dg/opt/pr59622-4.C @@ -0,0 +1,23 @@ +// PR tree-optimization/59622 +// { dg-do compile } +// { dg-options "-O2" } + +struct C { int a; int b; }; + +namespace +{ + struct A + { + A () {} + virtual C bar (int) = 0; + C baz (int x) { return bar (x); } + }; +} + +A *a; + +C +foo () +{ + return a->baz (0); +} diff --git a/gcc/testsuite/g++.dg/opt/pr59622-5.C b/gcc/testsuite/g++.dg/opt/pr59622-5.C new file mode 100644 index 000000000000..bcb2591a64c0 --- /dev/null +++ b/gcc/testsuite/g++.dg/opt/pr59622-5.C @@ -0,0 +1,26 @@ +// PR tree-optimization/59622 +// { dg-do compile } +// { dg-options "-O2" } + +namespace +{ + struct A + { + A () {} + virtual A *bar (int); + A *baz (int x) { return bar (x); } + }; + + __attribute__((noreturn)) A *A::bar (int) + { + __builtin_exit (0); + } +} + +A *a; + +void +foo () +{ + a->baz (0); +} diff --git a/gcc/testsuite/g++.dg/pr58950.C b/gcc/testsuite/g++.dg/pr58950.C new file mode 100644 index 000000000000..10a2032440f0 --- /dev/null +++ b/gcc/testsuite/g++.dg/pr58950.C @@ -0,0 +1,8 @@ +/* { dg-do compile } */ +/* { dg-options "-Wall" } */ + +void f(){ + int i __attribute__((vector_size(2*sizeof(int)))) = { 2, 3 }; + __builtin_shuffle (i, i); /* { dg-warning "value computed is not used" } */ + ++i?1:0; /* { dg-warning "value computed is not used" } */ +} diff --git a/gcc/testsuite/g++.dg/pr59510.C b/gcc/testsuite/g++.dg/pr59510.C new file mode 100644 index 000000000000..dcdf860dcf73 --- /dev/null +++ b/gcc/testsuite/g++.dg/pr59510.C @@ -0,0 +1,82 @@ +// PR debug/59510 +// { dg-do compile } +// { dg-options "-O2 -g --param=large-stack-frame-growth=1" } + +template <typename _Iterator> +struct _Iter_base +{ + typedef _Iterator iterator_type; +}; +template <typename _CharT> +struct basic_ostream; +template <typename _CharT> +struct basic_ostringstream; +template <typename _CharT> +struct ostreambuf_iterator; +typedef basic_ostringstream <char>ostringstream; +template <typename _Iterator> struct _Miter_base : _Iter_base <_Iterator> +{ +}; +template <typename _Iterator> +typename _Miter_base <_Iterator>::iterator_type __miter_base (_Iterator); +template <typename _CharT> +ostreambuf_iterator <_CharT> +__copy_move_a2 (ostreambuf_iterator <_CharT>); +template <typename _II, typename _OI> +_OI copy (_II __first, _II __last, _OI __result) +{ + __copy_move_a2 <false> (__first, __miter_base (__last), __result); +} +struct ios_base { + struct _Words { + int *_M_pword; + long _M_iword; + }; + _Words _M_local_word[8]; +}; +template <typename _CharT> +struct basic_streambuf +{ + typedef _CharT char_type; + int sputn (char_type *, int); +}; +template <typename _CharT> +struct ostreambuf_iterator +{ + typedef basic_streambuf <_CharT> streambuf_type; + typedef basic_ostream <_CharT> ostream_type; + streambuf_type *_M_sbuf; + bool _M_failed; + ostreambuf_iterator (ostream_type __s) : _M_sbuf (__s.rdbuf ()), _M_failed () {} + void _M_put (_CharT * __ws, int __len) + { + if (_M_failed && _M_sbuf->sputn (__ws, __len) != __len) _M_failed = true; + } +}; +template <bool, typename _CharT> +void __copy_move_a2 (_CharT * __first,_CharT * __last,ostreambuf_iterator <_CharT> __result) +{ + int __num = __last - __first; + __result._M_put (__first, __num); +} +template <typename _CharT> +struct basic_ios : ios_base +{ + basic_streambuf <_CharT> *rdbuf (); +}; +template <typename _CharT> +struct basic_ostream : public basic_ios <_CharT> +{ +}; +template <typename _CharT> +struct basic_ostringstream : public basic_ostream <_CharT> +{ +}; +void +test01 () { + char data1[] = "foo"; + char *beg1 = data1; + ostringstream oss1; + ostreambuf_iterator <char> out1 (oss1); + out1 = copy (beg1, beg1, out1); +} diff --git a/gcc/testsuite/g++.dg/torture/pr58252.C b/gcc/testsuite/g++.dg/torture/pr58252.C new file mode 100644 index 000000000000..d38a7a7ea4be --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr58252.C @@ -0,0 +1,142 @@ +// { dg-do compile } +// { dg-options "-fpermissive" } +typedef long unsigned int size_t; + typedef bool _CORBA_Boolean; + typedef unsigned int _CORBA_ULong; + template <class T> class _CORBA_Sequence { + public: typedef _CORBA_Sequence<T> T_seq; + inline T_seq &operator= (const T_seq &s) { + for (unsigned long i=0; + i < pd_len; + i++) { + } + } + _CORBA_ULong pd_len; + }; + template <class T> class _CORBA_Unbounded_Sequence : public _CORBA_Sequence<T> { + inline _CORBA_Unbounded_Sequence_WChar() { // { dg-warning "forbids declaration" } + } + }; + class _CORBA_ObjRef_Var_base { + }; + template <class T, class T_Helper> class _CORBA_ObjRef_Var : public _CORBA_ObjRef_Var_base { + public: typedef T* ptr_t; + typedef T* T_ptr; + inline _CORBA_ObjRef_Var() : pd_objref(T_Helper::_nil()) { + } + inline _CORBA_ObjRef_Var(T_ptr p) : pd_objref(p) { + } + private: T_ptr pd_objref; + }; + class omniLocalIdentity; + class omniObjRef { + }; + class omniServant { + public: virtual ~omniServant(); + virtual void* _ptrToInterface(const char* repoId); + }; + namespace CORBA { + class NVList { + }; + class Object { + }; + struct StructMember { + }; + class StructMemberSeq : public _CORBA_Unbounded_Sequence< StructMember > { + }; + class _objref_IRObject : public virtual ::CORBA::Object, public virtual omniObjRef { + }; + class _impl_IRObject : public virtual omniServant { + }; + class _objref_Container; + typedef _objref_Container* Container_ptr; + class _impl_Contained : public virtual _impl_IRObject { + }; + class _objref_ExceptionDef; + typedef _objref_ExceptionDef* ExceptionDef_ptr; + class ExceptionDef_Helper { + public: typedef ExceptionDef_ptr _ptr_type; + static _ptr_type _nil(); + }; + typedef _CORBA_ObjRef_Var<_objref_ExceptionDef, ExceptionDef_Helper> ExceptionDef_var; + class Container { + public: typedef Container_ptr _ptr_type; + static const char* _PD_repoId; + }; + class _objref_Container : public virtual _objref_IRObject { + ExceptionDef_ptr create_exception(const char* id, const char* name, const char* version, const ::CORBA::StructMemberSeq& members); + }; + class _impl_Container : public virtual _impl_IRObject { + public: virtual ~_impl_Container(); + virtual ExceptionDef_ptr create_exception(const char* id, const char* name, const char* version, const ::CORBA::StructMemberSeq& members) = 0; + }; + class _impl_IDLType : public virtual _impl_IRObject { + }; + class _impl_TypedefDef : public virtual _impl_Contained, public virtual _impl_IDLType { + }; + class _impl_StructDef : public virtual _impl_TypedefDef, public virtual _impl_Container { + }; + } + namespace PortableServer { + class ServantBase : public virtual omniServant { + }; + } + namespace POA_CORBA { + class IRObject : public virtual CORBA::_impl_IRObject, public virtual ::PortableServer::ServantBase { + }; + class Contained : public virtual CORBA::_impl_Contained, public virtual IRObject { + }; + class Container : public virtual CORBA::_impl_Container, public virtual IRObject { + }; + class IDLType : public virtual CORBA::_impl_IDLType, public virtual IRObject { + }; + class TypedefDef : public virtual CORBA::_impl_TypedefDef, public virtual Contained, public virtual IDLType { + }; + class StructDef : public virtual CORBA::_impl_StructDef, public virtual TypedefDef, public virtual Container { + public: virtual ~StructDef(); + }; + } + namespace omni { + class omniOrbPOA; + class giopAddress; + } + class omniCallDescriptor { + public: typedef void (*LocalCallFn)(omniCallDescriptor*, omniServant*); + inline omniCallDescriptor(LocalCallFn lcfn, const char* op_, int op_len_, _CORBA_Boolean oneway, const char*const* user_excns_, int n_user_excns_, _CORBA_Boolean is_upcall_) : pd_localCall(lcfn), pd_op(op_), pd_oplen(op_len_), pd_user_excns(user_excns_), pd_n_user_excns(n_user_excns_), pd_is_oneway(oneway), pd_is_upcall(is_upcall_), pd_contains_values(0), pd_first_address_used(0), pd_current_address(0), pd_objref(0), pd_poa(0), pd_localId(0), pd_deadline_secs(0), pd_deadline_nanosecs(0) { + } + private: LocalCallFn pd_localCall; + const char* pd_op; + size_t pd_oplen; + const char*const* pd_user_excns; + int pd_n_user_excns; + _CORBA_Boolean pd_is_oneway; + _CORBA_Boolean pd_is_upcall; + _CORBA_Boolean pd_contains_values; + const omni::giopAddress* pd_first_address_used; + const omni::giopAddress* pd_current_address; + omniObjRef* pd_objref; + omni::omniOrbPOA* pd_poa; + omniLocalIdentity* pd_localId; + unsigned long pd_deadline_secs; + unsigned long pd_deadline_nanosecs; + }; + class _0RL_cd_7963219a43724a61_f2000000 : public omniCallDescriptor { + public: inline _0RL_cd_7963219a43724a61_f2000000(LocalCallFn lcfn,const char* op_,size_t oplen,_CORBA_Boolean upcall=0): omniCallDescriptor(lcfn, op_, oplen, 0, _user_exns, 0, upcall) { + } + static const char* const _user_exns[]; + const char* arg_0; + const char* arg_1; + const char* arg_2; + const CORBA::StructMemberSeq* arg_3; + CORBA::ExceptionDef_var result; + }; + static void _0RL_lcfn_7963219a43724a61_03000000(omniCallDescriptor* cd, omniServant* svnt) { + _0RL_cd_7963219a43724a61_f2000000* tcd = (_0RL_cd_7963219a43724a61_f2000000*)cd; + CORBA::_impl_Container* impl = (CORBA::_impl_Container*) svnt->_ptrToInterface(CORBA::Container::_PD_repoId); + tcd->result = impl->create_exception(tcd->arg_0, tcd->arg_1, tcd->arg_2, *tcd->arg_3); + } + CORBA::ExceptionDef_ptr CORBA::_objref_Container::create_exception(const char* id, const char* name, const char* version, const ::CORBA::StructMemberSeq& members) { + _0RL_cd_7963219a43724a61_f2000000 _call_desc(_0RL_lcfn_7963219a43724a61_03000000, "create_exception", 17); + } + POA_CORBA::StructDef::~StructDef() { + } diff --git a/gcc/testsuite/g++.dg/torture/pr58585.C b/gcc/testsuite/g++.dg/torture/pr58585.C new file mode 100644 index 000000000000..69fcf04ddc1b --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr58585.C @@ -0,0 +1,20 @@ +// { dg-do compile } +// { dg-options "-fpic" { target fpic } } +struct A +{ + virtual void foo() {} + void bar(); +}; +void A::bar() { foo(); } + +struct B : virtual A +{ + virtual void foo() {} + char c; +}; + +struct C : virtual B +{ + C(); +}; +C::C() { bar(); } diff --git a/gcc/testsuite/g++.dg/torture/pr59226.C b/gcc/testsuite/g++.dg/torture/pr59226.C new file mode 100644 index 000000000000..cb0ebbe35f9f --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr59226.C @@ -0,0 +1,27 @@ +// { dg-do compile } +struct A +{ + virtual void foo() {} +}; + +struct B +{ + virtual void foo() {} +}; + +struct C : virtual A {}; + +struct D : virtual A, B +{ + virtual void foo() {} +}; + +struct E : C, D +{ + virtual void foo() {} +}; + +void bar(A* p) +{ + p->foo(); +} diff --git a/gcc/testsuite/gcc.c-torture/compile/pr59743.c b/gcc/testsuite/gcc.c-torture/compile/pr59743.c new file mode 100644 index 000000000000..8dadba594e59 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr59743.c @@ -0,0 +1,23 @@ +/* PR middle-end/59743 */ + +typedef union { + long all; + struct { + int low; + int high; + } s; +} udwords; +int a, b, c, d; +void __udivmoddi4() { + udwords r; + d = __builtin_clz(0); + r.s.low = 0; + for (; d; --d) { + r.s.high = r.s.high << 1 | r.s.low >> a; + r.s.low = r.s.low << b >> 1; + int s = -r.all; + c = s; + r.all--; + } +} + diff --git a/gcc/testsuite/gcc.c-torture/execute/pr59643.c b/gcc/testsuite/gcc.c-torture/execute/pr59643.c new file mode 100644 index 000000000000..e3e8a6a38fca --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr59643.c @@ -0,0 +1,39 @@ +/* PR tree-optimization/59643 */ + +#define N 32 + +__attribute__((noinline, noclone)) void +foo (double *a, double *b, double *c, double d, double e, int n) +{ + int i; + for (i = 1; i < n - 1; i++) + a[i] = d * (b[i] + c[i] + a[i - 1] + a[i + 1]) + e * a[i]; +} + +double expected[] = { + 0.0, 10.0, 44.0, 110.0, 232.0, 490.0, 1020.0, 2078.0, 4152.0, 8314.0, + 16652.0, 33326.0, 66664.0, 133354.0, 266748.0, 533534.0, 1067064.0, + 2134138.0, 4268300.0, 8536622.0, 17073256.0, 34146538.0, 68293116.0, + 136586270.0, 273172536.0, 546345082.0, 1092690188.0, 2185380398.0, + 4370760808.0, 8741521642.0, 17483043324.0, 6.0 +}; + +int +main () +{ + int i; + double a[N], b[N], c[N]; + if (__DBL_MANT_DIG__ <= 35) + return 0; + for (i = 0; i < N; i++) + { + a[i] = (i & 3) * 2.0; + b[i] = (i & 7) - 4; + c[i] = i & 7; + } + foo (a, b, c, 2.0, 3.0, N); + for (i = 0; i < N; i++) + if (a[i] != expected[i]) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/cilk-plus/cilk-plus.exp b/gcc/testsuite/gcc.dg/cilk-plus/cilk-plus.exp index c370ec645e6a..61085fd8f1f1 100644 --- a/gcc/testsuite/gcc.dg/cilk-plus/cilk-plus.exp +++ b/gcc/testsuite/gcc.dg/cilk-plus/cilk-plus.exp @@ -51,13 +51,15 @@ 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 -O3 -std=c99" " " dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/AN/*.c]] " -fcilkplus -g -O0 -std=c99" " " -dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -g -fcilkplus" " " -dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O1 -fcilkplus" " " -dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O2 -std=c99 -fcilkplus" " " -dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O2 -ftree-vectorize -fcilkplus" " " -dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O3 -g -fcilkplus" " " -if { [check_effective_target_lto] } { - dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O3 -flto -g -fcilkplus" " " +if { [check_libcilkrts_available] } { + dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -g " " " + dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O1 " " " + dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O2 -std=c99 " " " + dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O2 -ftree-vectorize " " " + dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O3 -g " " " + if { [check_effective_target_lto] } { + dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/CK/*.c]] " -O3 -flto -g " " " + } } dg-runtest [lsort [glob -nocomplain $srcdir/c-c++-common/cilk-plus/SE/*.c]] " -g" " " diff --git a/gcc/testsuite/gcc.dg/delay-slot-1.c b/gcc/testsuite/gcc.dg/delay-slot-1.c index f3bcd8ec7564..bfc0273e4ff5 100644 --- a/gcc/testsuite/gcc.dg/delay-slot-1.c +++ b/gcc/testsuite/gcc.dg/delay-slot-1.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-O2" } */ -/* { dg-options "-O2 -mabi=64" { target mips-*-linux-* } } */ +/* { dg-options "-O2 -mabi=64" { target { mips*-*-linux* && mips64 } } } */ struct offset_v1 { int k_uniqueness; diff --git a/gcc/testsuite/gcc.dg/gomp/pr59669-1.c b/gcc/testsuite/gcc.dg/gomp/pr59669-1.c new file mode 100644 index 000000000000..c72156d4bd0b --- /dev/null +++ b/gcc/testsuite/gcc.dg/gomp/pr59669-1.c @@ -0,0 +1,9 @@ +/* PR middle-end/59669 */ +/* { dg-do compile } */ +/* { dg-options "-fopenmp" } */ + +#pragma omp declare simd linear(a) +void +foo (int a) +{ +} diff --git a/gcc/testsuite/gcc.dg/gomp/pr59669-2.c b/gcc/testsuite/gcc.dg/gomp/pr59669-2.c new file mode 100644 index 000000000000..f6aad8998f1f --- /dev/null +++ b/gcc/testsuite/gcc.dg/gomp/pr59669-2.c @@ -0,0 +1,9 @@ +/* PR middle-end/59669 */ +/* { dg-do compile } */ +/* { dg-options "-fopenmp" } */ + +#pragma omp declare simd uniform(a) aligned(a:32) +void +bar (int *a) +{ +} diff --git a/gcc/testsuite/gcc.dg/ipa/pr59008.c b/gcc/testsuite/gcc.dg/ipa/pr59008.c new file mode 100644 index 000000000000..b7296724300f --- /dev/null +++ b/gcc/testsuite/gcc.dg/ipa/pr59008.c @@ -0,0 +1,32 @@ +/* { dg-do compile } */ +/* { dg-options "-O3" } */ + +typedef int (*funct)(int, int, int); + +extern int f(int, int, int); +extern int g(int, int, int); +extern int h(int, funct, funct); + +static int baz(int x, int y, int z) +{ + return x + y + z; +} + +static int bar(int n, funct f1, funct f2) +{ + return h(n, f1, f2) + f1(0, 1, 2); +} + +static int foo(int n, funct f1, funct f2) +{ + return bar(n, f1, f2) + f2(0, 1, 2); +} + +int main(void) +{ + return foo(0, f, g) +#ifndef ICE2 + + foo(0, baz, g) +#endif + ; +} diff --git a/gcc/testsuite/gcc.dg/ipa/pr59610.c b/gcc/testsuite/gcc.dg/ipa/pr59610.c new file mode 100644 index 000000000000..fc0933441e82 --- /dev/null +++ b/gcc/testsuite/gcc.dg/ipa/pr59610.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +struct A { int a; }; +extern void *y; + +__attribute__((optimize (0))) void +foo (void *p, struct A x) +{ + foo (y, x); +} diff --git a/gcc/testsuite/gcc.dg/pr46309.c b/gcc/testsuite/gcc.dg/pr46309.c index ee154ccd2f3c..9275015049e2 100644 --- a/gcc/testsuite/gcc.dg/pr46309.c +++ b/gcc/testsuite/gcc.dg/pr46309.c @@ -1,5 +1,5 @@ /* PR tree-optimization/46309 */ -/* { dg-do compile } */ +/* { dg-do compile { target { ! { cris*-*-* } } } } */ /* { dg-options "-O2 -fdump-tree-reassoc-details" } */ /* The transformation depends on BRANCH_COST being greater than 1 (see the notes in the PR), so try to force that. */ diff --git a/gcc/testsuite/gcc.dg/pr57773.c b/gcc/testsuite/gcc.dg/pr57773.c new file mode 100644 index 000000000000..1c309506d108 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr57773.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-std=c99 -Wpedantic" } */ + +enum e { A }; +struct { enum e b: 2; } s1; +struct { signed char b: 2; } s2; +struct { unsigned char b: 2; } s3; +struct { short b: 2; } s4; +struct { unsigned short b: 2; } s5; +struct { long int b: 2; } s6; +struct { unsigned long int b: 2; } s7; +struct { long long int b: 2; } s8; +struct { unsigned long long int b: 2; } s9; diff --git a/gcc/testsuite/gcc.dg/pr58668.c b/gcc/testsuite/gcc.dg/pr58668.c new file mode 100644 index 000000000000..3e09508dc16e --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr58668.c @@ -0,0 +1,25 @@ +/* PR rtl-optimization/58668 */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +/* { dg-additional-options "-mthumb" { target { { arm*-*-* } && arm_thumb2_ok } } } */ + +void *fn1 (void *); +void *fn2 (void *, const char *); +void fn3 (void *); +void fn4 (void *, int); + +void * +test (void *x) +{ + void *a, *b; + if (!(a = fn1 (x))) + return (void *) 0; + if (!(b = fn2 (a, "w"))) + { + fn3 (a); + return (void *) 0; + } + fn3 (a); + fn4 (b, 1); + return b; +} diff --git a/gcc/testsuite/gcc.dg/pr59350-2.c b/gcc/testsuite/gcc.dg/pr59350-2.c new file mode 100644 index 000000000000..2fea85fcf719 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr59350-2.c @@ -0,0 +1,29 @@ +/* PR debug/59350 */ + +/* { dg-do compile } */ +/* { dg-options "-O -g " } */ + +typedef struct +{ + void *v; + int len; + int sign; +} ZVALUE; + +extern int pred (ZVALUE); + +static unsigned long +small_factor (ZVALUE z) +{ + if (z.len > 0) + return 0; + + return pred (z) ? -1 : 0; +} + +unsigned long +zfactor (ZVALUE z) +{ + z.sign = 0; + return small_factor (z); +} diff --git a/gcc/testsuite/gcc.dg/pr59350.c b/gcc/testsuite/gcc.dg/pr59350.c index be186873ac58..fa632454ae1e 100644 --- a/gcc/testsuite/gcc.dg/pr59350.c +++ b/gcc/testsuite/gcc.dg/pr59350.c @@ -1,4 +1,4 @@ -/* PR rtl-optimization/59350 */ +/* PR debug/59350 */ /* Testcase by Ryan Mansfield <rmansfield@qnx.com> */ /* { dg-do compile } */ diff --git a/gcc/testsuite/gcc.dg/pr59471.c b/gcc/testsuite/gcc.dg/pr59471.c new file mode 100644 index 000000000000..7f2a7870a0e2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr59471.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ + +typedef unsigned char uint8x4_t +__attribute__ ((__vector_size__ (4))); + +typedef unsigned short uint16x8_t +__attribute__ ((__vector_size__ (16))); + +typedef unsigned int uint32x4_t +__attribute__ ((__vector_size__ (16))); + +void +foo (uint16x8_t *x, uint8x4_t *y) +{ + *y = (uint8x4_t) ((uint32x4_t) (*x))[0]; +} diff --git a/gcc/testsuite/gcc.dg/pr59630.c b/gcc/testsuite/gcc.dg/pr59630.c new file mode 100644 index 000000000000..6a3c72552f5a --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr59630.c @@ -0,0 +1,8 @@ +/* { dg-do compile } */ +/* { dg-options "-O" } */ + +_Bool foo() +{ + _Bool (*f)(int) = __builtin_abs; /* { dg-warning "" } */ + return f(0); +} diff --git a/gcc/testsuite/gcc.dg/pr59643.c b/gcc/testsuite/gcc.dg/pr59643.c new file mode 100644 index 000000000000..f4df5e5b2212 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr59643.c @@ -0,0 +1,15 @@ +/* PR tree-optimization/59643 */ +/* { dg-do compile } */ +/* { dg-options "-O3 -fdump-tree-pcom-details" } */ + +void +foo (double *a, double *b, double *c, double d, double e, int n) +{ + int i; + for (i = 1; i < n - 1; i++) + a[i] = d * (b[i] + c[i] + a[i - 1] + a[i + 1]) + e * a[i]; +} + +/* { dg-final { scan-tree-dump-times "Before commoning:" 1 "pcom" } } */ +/* { dg-final { scan-tree-dump-times "Unrolling 2 times" 1 "pcom" } } */ +/* { dg-final { cleanup-tree-dump "pcom" } } */ diff --git a/gcc/testsuite/gcc.dg/pr59670.c b/gcc/testsuite/gcc.dg/pr59670.c new file mode 100644 index 000000000000..a68253b4b637 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr59670.c @@ -0,0 +1,15 @@ +/* PR middle-end/59670 */ +/* { dg-do compile } */ +/* { dg-options "-O1 -fopenmp-simd" } */ + +int d[1024]; + +int +foo (int j, int b) +{ + int l, c = 0; +#pragma omp simd reduction(+: c) + for (l = 0; l < b; ++l) + c += d[j + l]; + return c; +} diff --git a/gcc/testsuite/gcc.dg/pr59722.c b/gcc/testsuite/gcc.dg/pr59722.c new file mode 100644 index 000000000000..7626fd22e1d8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr59722.c @@ -0,0 +1,36 @@ +/* PR ipa/59722 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fcompare-debug" } */ + +extern void abrt (const char *, int) __attribute__((noreturn)); +void baz (int *, int *); + +static inline int +bar (void) +{ + return 1; +} + +static inline void +foo (int *x, int y (void)) +{ + while (1) + { + int a = 0; + if (*x) + { + baz (x, &a); + while (a && !y ()) + ; + break; + } + abrt ("", 1); + } +} + +void +test (int x) +{ + foo (&x, bar); + foo (&x, bar); +} diff --git a/gcc/testsuite/gcc.dg/torture/pr57748-3.c b/gcc/testsuite/gcc.dg/torture/pr57748-3.c new file mode 100644 index 000000000000..5ddb6099c2cd --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr57748-3.c @@ -0,0 +1,40 @@ +/* PR middle-end/57748 */ +/* { dg-do run } */ +/* wrong code in expand_expr_real_1. */ + +#include <stdlib.h> + +extern void abort (void); + +typedef long long V + __attribute__ ((vector_size (2 * sizeof (long long)), may_alias)); + +typedef struct S { V a; V b[0]; } P __attribute__((aligned (1))); + +struct __attribute__((packed)) T { char c; P s; }; + +void __attribute__((noinline, noclone)) +check (P *p) +{ + if (p->b[0][0] != 3 || p->b[0][1] != 4) + abort (); +} + +void __attribute__((noinline, noclone)) +foo (struct T *t) +{ + V a = { 3, 4 }; + t->s.b[0] = a; +} + +int +main () +{ + struct T *t = (struct T *) calloc (128, 1); + + foo (t); + check (&t->s); + + free (t); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr57748-4.c b/gcc/testsuite/gcc.dg/torture/pr57748-4.c new file mode 100644 index 000000000000..455cb3d3278b --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr57748-4.c @@ -0,0 +1,40 @@ +/* PR middle-end/57748 */ +/* { dg-do run } */ +/* wrong code in expand_expr_real_1. */ + +#include <stdlib.h> + +extern void abort (void); + +typedef long long V + __attribute__ ((vector_size (2 * sizeof (long long)), may_alias)); + +typedef struct S { V b[1]; } P __attribute__((aligned (1))); + +struct __attribute__((packed)) T { char c; P s; }; + +void __attribute__((noinline, noclone)) +check (P *p) +{ + if (p->b[1][0] != 3 || p->b[1][1] != 4) + abort (); +} + +void __attribute__((noinline, noclone)) +foo (struct T *t) +{ + V a = { 3, 4 }; + t->s.b[1] = a; +} + +int +main () +{ + struct T *t = (struct T *) calloc (128, 1); + + foo (t); + check (&t->s); + + free (t); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr59374-3.c b/gcc/testsuite/gcc.dg/torture/pr59374-3.c new file mode 100644 index 000000000000..ab0014d8f13f --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr59374-3.c @@ -0,0 +1,21 @@ +extern void abort (void); + +static struct X { void *a; void *b; } a, b; + +void __attribute__((noinline)) foo (void) +{ + void *tem = a.b; + a.b = (void *)0; + b.b = tem; + b.a = a.a; + a.a = tem; +} + +int main() +{ + a.b = &a; + foo (); + if (b.b != &a) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr59715.c b/gcc/testsuite/gcc.dg/torture/pr59715.c new file mode 100644 index 000000000000..19c09de55d7e --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr59715.c @@ -0,0 +1,21 @@ +/* { dg-do run } */ + +extern void abort (void); + +int a = 2, b; + +int +main () +{ + int c; + if (!b) + { + b = a; + c = a == 0 ? 1 : 1 % a; + if (c) + b = 0; + } + if (b != 0) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-28.c b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-28.c index 1a4bf4a4444f..59951e2bf810 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-28.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-28.c @@ -1,4 +1,4 @@ -/* { dg-do compile { target { ! "m68k*-*-* mmix*-*-* mep*-*-* bfin*-*-* v850*-*-* picochip*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-* arc*-*-*"} } } */ +/* { dg-do compile { target { ! "m68k*-*-* mmix*-*-* mep*-*-* bfin*-*-* v850*-*-* picochip*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-* arc*-*-* hppa*-*-* mips*-*-*"} } } */ /* { dg-options "-O2 -fdump-tree-forwprop1" } */ /* Skip on ARM Cortex-M, where LOGICAL_OP_NON_SHORT_CIRCUIT is set to false, leading to two conditional jumps when evaluating an && condition. Forwprop1 diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-32.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-32.c index 303b3f32bd9f..865ab0b617c5 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-32.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-32.c @@ -1,7 +1,7 @@ /* { dg-do run { target { ! "m68k*-*-* mmix*-*-* mep*-*-* bfin*-*-* v850*-*-* picochip*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-*"} } } */ /* { dg-options "-O2 -fno-inline -fdump-tree-reassoc1-details" } */ -/* { dg-additional-options "-mbranch-cost=2" { target avr-*-* } } */ +/* { dg-additional-options "-mbranch-cost=2" { target mips*-*-* avr-*-* } } */ int test (int a, int b, int c) diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-33.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-33.c index bb27daa8c14e..6782972365f9 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-33.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-33.c @@ -1,7 +1,7 @@ -/* { dg-do run { target { ! "m68k*-*-* mmix*-*-* mep*-*-* bfin*-*-* v850*-*-* picochip*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-*"} } } */ +/* { dg-do run { target { ! "m68k*-*-* mmix*-*-* mep*-*-* bfin*-*-* v850*-*-* picochip*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-* hppa*-*-*"} } } */ /* { dg-options "-O2 -fno-inline -fdump-tree-reassoc1-details" } */ -/* { dg-additional-options "-mbranch-cost=2" { target avr-*-* } } */ +/* { dg-additional-options "-mbranch-cost=2" { target mips*-*-* avr-*-* } } */ int test (int a, int b, int c) { diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-34.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-34.c index 156e18242222..272455b371db 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-34.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-34.c @@ -1,7 +1,7 @@ -/* { dg-do run { target { ! "m68k*-*-* mmix*-*-* mep*-*-* bfin*-*-* v850*-*-* picochip*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-*"} } } */ +/* { dg-do run { target { ! "m68k*-*-* mmix*-*-* mep*-*-* bfin*-*-* v850*-*-* picochip*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-* hppa*-*-*"} } } */ /* { dg-options "-O2 -fno-inline -fdump-tree-reassoc1-details" } */ -/* { dg-additional-options "-mbranch-cost=2" { target avr-*-* } } */ +/* { dg-additional-options "-mbranch-cost=2" { target mips*-*-* avr-*-* } } */ int test (int a, int b, int c) { diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-35.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-35.c index c486b783dce2..8e03ad6b1a53 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-35.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-35.c @@ -1,7 +1,7 @@ -/* { dg-do run { target { ! "m68k*-*-* mmix*-*-* mep*-*-* bfin*-*-* v850*-*-* picochip*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-*"} } } */ +/* { dg-do run { target { ! "m68k*-*-* mmix*-*-* mep*-*-* bfin*-*-* v850*-*-* picochip*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-* hppa*-*-*"} } } */ /* { dg-options "-O2 -fno-inline -fdump-tree-reassoc1-details" } */ -/* { dg-additional-options "-mbranch-cost=2" { target avr-*-* } } */ +/* { dg-additional-options "-mbranch-cost=2" { target mips*-*-* avr-*-* } } */ int test (unsigned int a, int b, int c) { diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-36.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-36.c index 930dbe289fb4..8bd507ce3acf 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-36.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-36.c @@ -1,7 +1,7 @@ -/* { dg-do run { target { ! "m68k*-*-* mmix*-*-* mep*-*-* bfin*-*-* v850*-*-* picochip*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-*"} } } */ +/* { dg-do run { target { ! "m68k*-*-* mmix*-*-* mep*-*-* bfin*-*-* v850*-*-* picochip*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-* hppa*-*-*"} } } */ /* { dg-options "-O2 -fno-inline -fdump-tree-reassoc1-details" } */ -/* { dg-additional-options "-mbranch-cost=2" { target avr-*-* } } */ +/* { dg-additional-options "-mbranch-cost=2" { target mips*-*-* avr-*-* } } */ int test (int a, int b, int c) { 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 index efc8a7133c9e..4b09c5db09d8 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-1.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-1.c @@ -1,4 +1,4 @@ -/* { dg-do compile { target { ! "m68k*-*-* mmix*-*-* mep*-*-* bfin*-*-* v850*-*-* picochip*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-* arc*-*-*"} } } */ +/* { dg-do compile { target { ! "m68k*-*-* mmix*-*-* mep*-*-* bfin*-*-* v850*-*-* picochip*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-* arc*-*-* mips*-*-*"} } } */ /* { dg-options "-O2 -g -fdump-tree-optimized" } */ /* { dg-additional-options "-mbranch-cost=2" { target avr-*-* } } */ 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 index 3be2310e9b5b..8d42dfb31a05 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-4.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-4.c @@ -1,4 +1,4 @@ -/* { dg-do compile { target { ! "m68k*-*-* mmix*-*-* mep*-*-* bfin*-*-* v850*-*-* picochip*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-* arc*-*-*"} } } */ +/* { dg-do compile { target { ! "m68k*-*-* mmix*-*-* mep*-*-* bfin*-*-* v850*-*-* picochip*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-* arc*-*-* mips*-*-*"} } } */ /* { dg-options "-O2 -g -fdump-tree-optimized" } */ /* { dg-additional-options "-mbranch-cost=2" { target avr-*-* } } */ 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 index c22a0e04c113..858bed1e640e 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-5.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-5.c @@ -1,4 +1,4 @@ -/* { dg-do compile { target { ! "m68k*-*-* mmix*-*-* mep*-*-* bfin*-*-* v850*-*-* picochip*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-* arc*-*-*"} } } */ +/* { dg-do compile { target { ! "m68k*-*-* mmix*-*-* mep*-*-* bfin*-*-* v850*-*-* picochip*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-* arc*-*-* mips*-*-*"} } } */ /* { dg-options "-O2 -g -fdump-tree-optimized" } */ /* { dg-additional-options "-mbranch-cost=2" { target avr-*-* } } */ 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 index aa0970dee7f6..fecb510c0097 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-6.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-ccmp-6.c @@ -1,4 +1,4 @@ -/* { dg-do compile { target { ! "m68k*-*-* mmix*-*-* mep*-*-* bfin*-*-* v850*-*-* picochip*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-* arc*-*-*"} } } */ +/* { dg-do compile { target { ! "m68k*-*-* mmix*-*-* mep*-*-* bfin*-*-* v850*-*-* picochip*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-* arc*-*-* mips*-*-*"} } } */ /* { dg-options "-O2 -g -fdump-tree-optimized" } */ /* { dg-additional-options "-mbranch-cost=2" { target avr-*-* } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp47.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp47.c index 5a09fa0f49d5..cbff587f5dd7 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/vrp47.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp47.c @@ -3,7 +3,7 @@ /* Skip on S/390 and avr. Lower values in BRANCH_COST lead to two conditional jumps when evaluating an && condition. VRP is not able to optimize this. */ -/* { dg-do compile { target { ! "mips*-*-* arc*-*-* s390*-*-* avr-*-* mn10300-*-*" } } } */ +/* { dg-do compile { target { ! "mips*-*-* arc*-*-* s390*-*-* avr-*-* mn10300-*-* hppa*-*-*" } } } */ /* { dg-options "-O2 -fdump-tree-vrp1 -fdump-tree-dom1 -fdump-tree-vrp2" } */ /* { dg-additional-options "-march=i586" { target { { i?86-*-* x86_64-*-* } && ia32 } } } */ /* Skip on ARM Cortex-M, where LOGICAL_OP_NON_SHORT_CIRCUIT is set to false, diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp87.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp87.c index 9aff0a6c46f8..a51d696316d2 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/vrp87.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp87.c @@ -1,7 +1,7 @@ -/* { dg-do compile { target { ! "m68k*-*-* mmix*-*-* mep*-*-* bfin*-*-* v850*-*-* picochip*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-* arc*-*-*"} } } */ +/* { dg-do compile { target { ! "m68k*-*-* mmix*-*-* mep*-*-* bfin*-*-* v850*-*-* picochip*-*-* moxie*-*-* cris*-*-* m32c*-*-* fr30*-*-* mcore*-*-* powerpc*-*-* xtensa*-*-* arc*-*-* hppa*-*-* mips*-*-*"} } } */ /* { dg-options "-O2 -fdump-tree-vrp2-details -fdump-tree-cddce2-details" } */ -/* { dg-additional-options "-mbranch-cost=2" { target avr-*-* } } */ +/* { dg-additional-options "-mbranch-cost=2" { target mips*-*-* avr-*-* } } */ /* Skip on ARM Cortex-M, where LOGICAL_OP_NON_SHORT_CIRCUIT is set to false, leading to two conditional jumps when evaluating an && condition. VRP is not able to optimize this. */ diff --git a/gcc/testsuite/gcc.dg/vect/pr59519-1.c b/gcc/testsuite/gcc.dg/vect/pr59519-1.c new file mode 100644 index 000000000000..428d4ec32e7b --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr59519-1.c @@ -0,0 +1,19 @@ +/* PR tree-optimization/59519 */ +/* { dg-do compile } */ +/* { dg-additional-options "-O3" } */ + +int a, b, c, d; + +void +foo (void) +{ + for (; d; d++) + for (b = 0; b < 14; b++) + { + c |= 1; + if (a) + break; + } +} + +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/pr59519-2.c b/gcc/testsuite/gcc.dg/vect/pr59519-2.c new file mode 100644 index 000000000000..2b109d2557d8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr59519-2.c @@ -0,0 +1,20 @@ +/* PR tree-optimization/59519 */ +/* { dg-do compile } */ +/* { dg-additional-options "-O3" } */ + +struct S { int f0; } d; +int a[8] = { 0 }, b, c, e; + +void +foo (void) +{ + for (; e < 1; e++) + for (b = 0; b < 7; b++) + { + c |= (a[b + 1] != 0); + if (d.f0) + break; + } +} + +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-simd-clone-10.c b/gcc/testsuite/gcc.dg/vect/vect-simd-clone-10.c index 923a9453c25f..93cb9f993c0d 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-simd-clone-10.c +++ b/gcc/testsuite/gcc.dg/vect/vect-simd-clone-10.c @@ -1,3 +1,4 @@ +/* { dg-do run } */ /* { dg-require-effective-target vect_simd_clones } */ /* { dg-additional-options "-fopenmp-simd" } */ /* { dg-additional-options "-mavx" { target avx_runtime } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-simd-clone-12.c b/gcc/testsuite/gcc.dg/vect/vect-simd-clone-12.c index 279abd7c6824..0fd5890e9291 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-simd-clone-12.c +++ b/gcc/testsuite/gcc.dg/vect/vect-simd-clone-12.c @@ -1,3 +1,4 @@ +/* { dg-do run } */ /* { dg-require-effective-target vect_simd_clones } */ /* { dg-additional-options "-fopenmp-simd" } */ /* { dg-additional-options "-mavx" { target avx_runtime } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect.exp b/gcc/testsuite/gcc.dg/vect/vect.exp index b0b7e2237c3a..fa11e7e5eea6 100644 --- a/gcc/testsuite/gcc.dg/vect/vect.exp +++ b/gcc/testsuite/gcc.dg/vect/vect.exp @@ -41,6 +41,28 @@ if ![check_vect_support_and_set_flags] { # These flags are used for all targets. lappend DEFAULT_VECTCFLAGS "-ftree-vectorize" "-fno-vect-cost-model" "-fno-common" +# If the linker used understands -M <mapfile>, pass it to clear hardware +# capabilities set by the Sun assembler. +# Try mapfile syntax v2 first which is the only way to clear hwcap_2 flags. +set clearcap_ldflags "-Wl,-M,$srcdir/gcc.target/i386/clearcapv2.map" + +if ![check_no_compiler_messages mapfilev2 executable { + int main (void) { return 0; } +} $clearcap_ldflags ] { + # If this doesn't work, fall back to the less capable v1 syntax. + set clearcap_ldflags "-Wl,-M,$srcdir/gcc.target/i386/clearcap.map" + + if ![check_no_compiler_messages mapfile executable { + int main (void) { return 0; } + } $clearcap_ldflags ] { + unset clearcap_ldflags + } +} + +if [info exists clearcap_ldflags] { + lappend DEFAULT_VECTCFLAGS $clearcap_ldflags +} + # Initialize `dg'. dg-init diff --git a/gcc/testsuite/gcc.target/aarch64/cmn-neg.c b/gcc/testsuite/gcc.target/aarch64/cmn-neg.c index 05c8bbff5be9..ab264e798efa 100644 --- a/gcc/testsuite/gcc.target/aarch64/cmn-neg.c +++ b/gcc/testsuite/gcc.target/aarch64/cmn-neg.c @@ -6,7 +6,7 @@ extern void abort (void); void __attribute__ ((noinline)) foo_s32 (int a, int b) { - if (a < -b) + if (a == -b) abort (); } /* { dg-final { scan-assembler "cmn\tw\[0-9\]" } } */ @@ -14,7 +14,7 @@ foo_s32 (int a, int b) void __attribute__ ((noinline)) foo_s64 (long long a, long long b) { - if (a < -b) + if (a == -b) abort (); } /* { dg-final { scan-assembler "cmn\tx\[0-9\]" } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/cmn-neg2.c b/gcc/testsuite/gcc.target/aarch64/cmn-neg2.c new file mode 100644 index 000000000000..ca45a53435f9 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/cmn-neg2.c @@ -0,0 +1,34 @@ +/* { dg-do run } */ +/* { dg-options "-O2 --save-temps" } */ + +extern void abort (void); + +/* It's unsafe to use CMN in these comparisons. */ + +void __attribute__ ((noinline)) +foo_s32 (int a, int b) +{ + if (a < -b) + abort (); +} + +void __attribute__ ((noinline)) +foo_s64 (unsigned long long a, unsigned long long b) +{ + if (a > -b) + abort (); +} + + +int +main (void) +{ + int a = 30; + int b = 42; + foo_s32 (a, b); + foo_s64 (a, b); + return 0; +} +/* { dg-final { scan-assembler-not "cmn\t" } } */ + +/* { dg-final { cleanup-saved-temps } } */ diff --git a/gcc/testsuite/gcc.target/arm/neon-nested-apcs.c b/gcc/testsuite/gcc.target/arm/neon-nested-apcs.c new file mode 100644 index 000000000000..cd92d7d33e7a --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/neon-nested-apcs.c @@ -0,0 +1,48 @@ +/* { dg-do run } */ +/* { dg-require-effective-target arm_neon_hw } */ +/* { dg-options "-fno-omit-frame-pointer -mapcs-frame -O" } +/* { dg-add-options arm_neon } */ + +extern void abort (void); + +float data; + +void __attribute__((noinline, noclone)) bar (float f) +{ + data = f; +} + +float __attribute__((noinline, noclone)) foo (float f) +{ + int error_reported = 0; + + void __attribute__((noinline, noclone)) + nested (int a, int b, int c, int d, float f0, float f1, float f2, float f3) + { + float e; + + if (f3 > f2) + e = f3; + else + e = f2; + + if (f0 - f1 > e) + { + error_reported = a + b + c + d; + bar (f0); + bar (e); + } + } + + nested (1, 2, 3, 4, 1.0, 1.0, 3.5, 4.2); + return f + (float)error_reported; +} + +#define PI 3.1415927f + +int main (void) +{ + if (foo (PI) != PI) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.target/arm/neon/vst1Q_laneu64-1.c b/gcc/testsuite/gcc.target/arm/neon/vst1Q_laneu64-1.c new file mode 100644 index 000000000000..5f4c927b6e0a --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/neon/vst1Q_laneu64-1.c @@ -0,0 +1,25 @@ +/* Test the `vst1Q_laneu64' ARM Neon intrinsic. */ + +/* Detect ICE in the case of unaligned memory address. */ + +/* { dg-do compile } */ +/* { dg-require-effective-target arm_neon_ok } */ +/* { dg-add-options arm_neon } */ + +#include "arm_neon.h" + +unsigned char dummy_store[1000]; + +void +foo (char* addr) +{ + uint8x16_t vdata = vld1q_u8 (addr); + vst1q_lane_u64 ((uint64_t*) &dummy_store, vreinterpretq_u64_u8 (vdata), 0); +} + +uint64_t +bar (uint64x2_t vdata) +{ + vdata = vld1q_lane_u64 ((uint64_t*) &dummy_store, vdata, 0); + return vgetq_lane_u64 (vdata, 0); +} diff --git a/gcc/testsuite/gcc.target/i386/asm-1.c b/gcc/testsuite/gcc.target/i386/asm-1.c index 999c5767966d..cd60a09bd7fe 100644 --- a/gcc/testsuite/gcc.target/i386/asm-1.c +++ b/gcc/testsuite/gcc.target/i386/asm-1.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-require-effective-target ia32 } */ -/* { dg-options "-m32" } */ +/* { dg-options "" } */ register unsigned int EAX asm ("r14"); /* { dg-error "register name" } */ diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vcmppd-2.c b/gcc/testsuite/gcc.target/i386/avx512f-vcmppd-2.c index 333a83576b2a..add23d07a19e 100644 --- a/gcc/testsuite/gcc.target/i386/avx512f-vcmppd-2.c +++ b/gcc/testsuite/gcc.target/i386/avx512f-vcmppd-2.c @@ -1,6 +1,7 @@ /* { dg-do run } */ -/* { dg-options "-O2 -mavx512f" } */ +/* { dg-options "-O2 -mavx512f -std=c99" } */ /* { dg-require-effective-target avx512f } */ +/* { dg-require-effective-target c99_runtime } */ #define AVX512F diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vcmpps-2.c b/gcc/testsuite/gcc.target/i386/avx512f-vcmpps-2.c index 5ffd470dbe2f..15c314e2d60e 100644 --- a/gcc/testsuite/gcc.target/i386/avx512f-vcmpps-2.c +++ b/gcc/testsuite/gcc.target/i386/avx512f-vcmpps-2.c @@ -1,6 +1,7 @@ /* { dg-do run } */ -/* { dg-options "-O2 -mavx512f" } */ +/* { dg-options "-O2 -mavx512f -std=c99" } */ /* { dg-require-effective-target avx512f } */ +/* { dg-require-effective-target c99_runtime } */ #define AVX512F diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vfixupimmpd-2.c b/gcc/testsuite/gcc.target/i386/avx512f-vfixupimmpd-2.c index 263fecd5f71b..d4ddd32145b2 100644 --- a/gcc/testsuite/gcc.target/i386/avx512f-vfixupimmpd-2.c +++ b/gcc/testsuite/gcc.target/i386/avx512f-vfixupimmpd-2.c @@ -1,6 +1,7 @@ /* { dg-do run } */ -/* { dg-options "-O2 -mavx512f" } */ +/* { dg-options "-O2 -mavx512f -std=gnu99" } */ /* { dg-require-effective-target avx512f } */ +/* { dg-require-effective-target c99_runtime } */ #define AVX512F diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vfixupimmps-2.c b/gcc/testsuite/gcc.target/i386/avx512f-vfixupimmps-2.c index 9fca53705de0..6c2539d0f4e8 100644 --- a/gcc/testsuite/gcc.target/i386/avx512f-vfixupimmps-2.c +++ b/gcc/testsuite/gcc.target/i386/avx512f-vfixupimmps-2.c @@ -1,6 +1,7 @@ /* { dg-do run } */ -/* { dg-options "-O2 -mavx512f" } */ +/* { dg-options "-O2 -mavx512f -std=gnu99" } */ /* { dg-require-effective-target avx512f } */ +/* { dg-require-effective-target c99_runtime } */ #define AVX512F diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vfixupimmsd-2.c b/gcc/testsuite/gcc.target/i386/avx512f-vfixupimmsd-2.c index ebd288ed2686..1344c7fd1bc8 100644 --- a/gcc/testsuite/gcc.target/i386/avx512f-vfixupimmsd-2.c +++ b/gcc/testsuite/gcc.target/i386/avx512f-vfixupimmsd-2.c @@ -1,6 +1,7 @@ /* { dg-do run } */ -/* { dg-options "-mavx512f -O2" } */ +/* { dg-options "-mavx512f -O2 -std=gnu99" } */ /* { dg-require-effective-target avx512f } */ +/* { dg-require-effective-target c99_runtime } */ #include "avx512f-check.h" #include "avx512f-helper.h" diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vfixupimmss-2.c b/gcc/testsuite/gcc.target/i386/avx512f-vfixupimmss-2.c index 50830b8bd365..25e165ff51dd 100644 --- a/gcc/testsuite/gcc.target/i386/avx512f-vfixupimmss-2.c +++ b/gcc/testsuite/gcc.target/i386/avx512f-vfixupimmss-2.c @@ -1,6 +1,7 @@ /* { dg-do run } */ -/* { dg-options "-mavx512f -O2" } */ +/* { dg-options "-mavx512f -O2 -std=gnu99" } */ /* { dg-require-effective-target avx512f } */ +/* { dg-require-effective-target c99_runtime } */ #include "avx512f-check.h" #include "avx512f-helper.h" diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vgetmantpd-2.c b/gcc/testsuite/gcc.target/i386/avx512f-vgetmantpd-2.c index 473466b1e53a..0209021b8b18 100644 --- a/gcc/testsuite/gcc.target/i386/avx512f-vgetmantpd-2.c +++ b/gcc/testsuite/gcc.target/i386/avx512f-vgetmantpd-2.c @@ -1,6 +1,7 @@ /* { dg-do run } */ -/* { dg-options "-O2 -mavx512f" } */ +/* { dg-options "-O2 -mavx512f -std=c99" } */ /* { dg-require-effective-target avx512f } */ +/* { dg-require-effective-target c99_runtime } */ #define AVX512F @@ -72,6 +73,7 @@ get_norm_mant (double source, int signctrl, int interv) } #endif +void static CALC (double *r, double *s, int interv, int signctrl) { int i; diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vgetmantps-2.c b/gcc/testsuite/gcc.target/i386/avx512f-vgetmantps-2.c index b8ea24d891b8..25e41d182175 100644 --- a/gcc/testsuite/gcc.target/i386/avx512f-vgetmantps-2.c +++ b/gcc/testsuite/gcc.target/i386/avx512f-vgetmantps-2.c @@ -1,6 +1,7 @@ /* { dg-do run } */ -/* { dg-options "-O2 -mavx512f" } */ +/* { dg-options "-O2 -mavx512f -std=c99" } */ /* { dg-require-effective-target avx512f } */ +/* { dg-require-effective-target c99_runtime } */ #define AVX512F @@ -73,6 +74,7 @@ get_norm_mant (float source, int signctrl, int interv) } #endif +void static CALC (float *r, float *s, int interv, int signctrl) { int i; diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vgetmantsd-2.c b/gcc/testsuite/gcc.target/i386/avx512f-vgetmantsd-2.c index 50d98a45df4c..563d3cc221c6 100644 --- a/gcc/testsuite/gcc.target/i386/avx512f-vgetmantsd-2.c +++ b/gcc/testsuite/gcc.target/i386/avx512f-vgetmantsd-2.c @@ -1,6 +1,7 @@ /* { dg-do run } */ -/* { dg-options "-mavx512f -O2" } */ +/* { dg-options "-mavx512f -O2 -std=c99" } */ /* { dg-require-effective-target avx512f } */ +/* { dg-require-effective-target c99_runtime } */ #include "avx512f-check.h" #include "avx512f-helper.h" diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vgetmantss-2.c b/gcc/testsuite/gcc.target/i386/avx512f-vgetmantss-2.c index 291c0df77e79..3ffab4ee1552 100644 --- a/gcc/testsuite/gcc.target/i386/avx512f-vgetmantss-2.c +++ b/gcc/testsuite/gcc.target/i386/avx512f-vgetmantss-2.c @@ -1,6 +1,7 @@ /* { dg-do run } */ -/* { dg-options "-mavx512f -O2" } */ +/* { dg-options "-mavx512f -O2 -std=c99" } */ /* { dg-require-effective-target avx512f } */ +/* { dg-require-effective-target c99_runtime } */ #include "avx512f-check.h" #include "avx512f-helper.h" diff --git a/gcc/testsuite/gcc.target/i386/avx512f-vmovdqu32-1.c b/gcc/testsuite/gcc.target/i386/avx512f-vmovdqu32-1.c index b8af781834e8..79dbf9dd37a0 100644 --- a/gcc/testsuite/gcc.target/i386/avx512f-vmovdqu32-1.c +++ b/gcc/testsuite/gcc.target/i386/avx512f-vmovdqu32-1.c @@ -1,6 +1,6 @@ /* { dg-do compile } */ /* { dg-options "-mavx512f -O2" } */ -/* { dg-final { scan-assembler-times "vmovdqu32\[ \\t\]+\[^\n\]*\\)\[^\n\]*%zmm\[0-9\]\[^\{\]" 1 } } */ +/* { dg-final { scan-assembler-times "vmovdqu\[36\]\[24\]\[ \\t\]+\[^\n\]*\\)\[^\n\]*%zmm\[0-9\]\[^\{\]" 1 } } */ /* { dg-final { scan-assembler-times "vmovdqu32\[ \\t\]+\[^\n\]*\\)\[^\n\]*%zmm\[0-9\]\{%k\[1-7\]\}\[^\{\]" 1 } } */ /* { dg-final { scan-assembler-times "vmovdqu32\[ \\t\]+\[^\n\]*\\)\[^\n\]*%zmm\[0-9\]\{%k\[1-7\]\}\{z\}" 1 } } */ /* { dg-final { scan-assembler-times "vmovdqu32\[ \\t\]+\[^\n\]*%zmm\[0-9\]\[^\n\]*\\)\[^\{\]" 1 } } */ diff --git a/gcc/testsuite/gcc.target/i386/incoming-5.c b/gcc/testsuite/gcc.target/i386/incoming-5.c index 9bbecdb95e13..f68eefcb9094 100644 --- a/gcc/testsuite/gcc.target/i386/incoming-5.c +++ b/gcc/testsuite/gcc.target/i386/incoming-5.c @@ -1,6 +1,6 @@ /* PR middle-end/37009 */ /* { dg-do compile { target { { ! *-*-darwin* } && ia32 } } } */ -/* { dg-options "-m32 -mincoming-stack-boundary=2 -mpreferred-stack-boundary=2" } */ +/* { dg-options "-mincoming-stack-boundary=2 -mpreferred-stack-boundary=2" } */ extern void bar (double *); diff --git a/gcc/testsuite/gcc.target/i386/intrinsics_4.c b/gcc/testsuite/gcc.target/i386/intrinsics_4.c index 4e124c90ef84..e7c074b31cb3 100644 --- a/gcc/testsuite/gcc.target/i386/intrinsics_4.c +++ b/gcc/testsuite/gcc.target/i386/intrinsics_4.c @@ -12,3 +12,10 @@ foo (void) { a[0] = _mm256_and_ps (b[0], c[0]); } + +/* Try again with a combination of target and optimization attributes. */ +void __attribute__((target ("avx"), optimize(3))) +bar (void) +{ + a[0] = _mm256_and_ps (b[0], c[0]); +} diff --git a/gcc/testsuite/gcc.target/i386/pr47735.c b/gcc/testsuite/gcc.target/i386/pr47735.c new file mode 100644 index 000000000000..0d44df4d5c9e --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr47735.c @@ -0,0 +1,16 @@ +/* PR middle-end/47735 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fomit-frame-pointer" } */ + +unsigned +mulh (unsigned a, unsigned b) +{ + unsigned long long l __attribute__ ((aligned (32))) + = ((unsigned long long) a * (unsigned long long) b) >> 32; + return l; +} + +/* No need to dynamically realign the stack here. */ +/* { dg-final { scan-assembler-not "and\[^\n\r]*%\[re\]sp" } } */ +/* Nor use a frame pointer. */ +/* { dg-final { scan-assembler-not "%\[re\]bp" } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr53623.c b/gcc/testsuite/gcc.target/i386/pr53623.c new file mode 100644 index 000000000000..35c578bd618f --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr53623.c @@ -0,0 +1,25 @@ +/* { dg-do compile { target {! ia32 } } } */ +/* { dg-options "-O2 -fdump-rtl-ree" } */ + + +#include <stdint.h> + +typedef (*inst_t)(int64_t rdi, int64_t rsi, int64_t rdx); + +int16_t code[256]; +inst_t dispatch[256]; + +void an_inst(int64_t rdi, int64_t rsi, int64_t rdx) { + rdx = code[rdx]; + uint8_t inst = (uint8_t) rdx; + rdx >>= 8; + dispatch[inst](rdi, rsi, rdx); +} + +int main(void) { + return 0; +} + +/* { dg-final { scan-rtl-dump "copy needed" "ree" } } */ +/* { dg-final { cleanup-rtl-dump "ree" } } */ + diff --git a/gcc/testsuite/gcc.target/i386/pr55433.c b/gcc/testsuite/gcc.target/i386/pr55433.c index b79b16dabdff..6a2602ad424c 100644 --- a/gcc/testsuite/gcc.target/i386/pr55433.c +++ b/gcc/testsuite/gcc.target/i386/pr55433.c @@ -1,5 +1,5 @@ -/* { dg-do compile {target { *-*-darwin* } } } */ -/* { dg-options "-O1 -m32" } */ +/* { dg-do compile { target { *-*-darwin* } } } */ +/* { dg-options "-O1" } */ typedef unsigned long long tick_t; extern int foo(void); diff --git a/gcc/testsuite/gcc.target/i386/pr56246.c b/gcc/testsuite/gcc.target/i386/pr56246.c index 64a2527a5496..b4d527396d65 100644 --- a/gcc/testsuite/gcc.target/i386/pr56246.c +++ b/gcc/testsuite/gcc.target/i386/pr56246.c @@ -1,5 +1,5 @@ /* PR target/56225 */ -/* { dg-do compile { target { ia32 } } } */ +/* { dg-do compile { target { ia32 && fpic } } } */ /* { dg-options "-O2 -fno-omit-frame-pointer -march=i686 -fpic" } */ void NoBarrier_AtomicExchange (long long *ptr) { diff --git a/gcc/testsuite/gcc.target/i386/pr57848.c b/gcc/testsuite/gcc.target/i386/pr57848.c index d26b84c1b487..c686b372824b 100644 --- a/gcc/testsuite/gcc.target/i386/pr57848.c +++ b/gcc/testsuite/gcc.target/i386/pr57848.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O1 -m32" } */ +/* { dg-options "-O1" } */ extern unsigned int __builtin_ia32_crc32si (unsigned int, unsigned int); #pragma GCC target("sse4.2") diff --git a/gcc/testsuite/gcc.target/i386/pr59099.c b/gcc/testsuite/gcc.target/i386/pr59099.c index 7dc12ff3f7c7..cf4a8da7db1c 100644 --- a/gcc/testsuite/gcc.target/i386/pr59099.c +++ b/gcc/testsuite/gcc.target/i386/pr59099.c @@ -1,5 +1,6 @@ /* { dg-do run } */ -/* { dg-options "-O2 -fPIC -m32" } */ +/* { dg-require-effective-target fpic } */ +/* { dg-options "-O2 -fPIC" } */ void (*pfn)(void); diff --git a/gcc/testsuite/gcc.target/i386/pr59390.c b/gcc/testsuite/gcc.target/i386/pr59390.c index 49ce02d1a218..7dc925ae9fbb 100644 --- a/gcc/testsuite/gcc.target/i386/pr59390.c +++ b/gcc/testsuite/gcc.target/i386/pr59390.c @@ -1,7 +1,7 @@ /* { dg-do compile } */ /* { dg-options "-std=c99 -O3" } */ -#include "math.h" +extern double fma (double, double, double); void fun() __attribute__((target("fma"))); void diff --git a/gcc/testsuite/gcc.target/i386/pr59390_1.c b/gcc/testsuite/gcc.target/i386/pr59390_1.c index 2bd32a4ebdbd..632eb6f9a4f2 100644 --- a/gcc/testsuite/gcc.target/i386/pr59390_1.c +++ b/gcc/testsuite/gcc.target/i386/pr59390_1.c @@ -1,7 +1,7 @@ /* { dg-do compile } */ /* { dg-options "-std=c99 -O3" } */ -#include "math.h" +extern double fma (double, double, double); void fun() __attribute__((target("fma"))); __attribute__((target("fma"))) diff --git a/gcc/testsuite/gcc.target/i386/pr59390_2.c b/gcc/testsuite/gcc.target/i386/pr59390_2.c index 55a181a8ad48..6142a085eedb 100644 --- a/gcc/testsuite/gcc.target/i386/pr59390_2.c +++ b/gcc/testsuite/gcc.target/i386/pr59390_2.c @@ -1,7 +1,7 @@ /* { dg-do compile } */ /* { dg-options "-std=c99 -O3 -mfma" } */ -#include "math.h" +extern double fma (double, double, double); void fun() __attribute__((target("fma"))); void diff --git a/gcc/testsuite/gcc.target/i386/pr59501-1.c b/gcc/testsuite/gcc.target/i386/pr59501-1.c index 6a104eef1adc..18db93a9be4f 100644 --- a/gcc/testsuite/gcc.target/i386/pr59501-1.c +++ b/gcc/testsuite/gcc.target/i386/pr59501-1.c @@ -1,6 +1,7 @@ /* PR target/59501 */ /* { dg-do run } */ /* { dg-options "-O2 -mavx -mno-accumulate-outgoing-args" } */ +/* { dg-require-effective-target avx } */ #define CHECK_H "avx-check.h" #define TEST avx_test diff --git a/gcc/testsuite/gcc.target/i386/pr59501-2.c b/gcc/testsuite/gcc.target/i386/pr59501-2.c index 8ce177deb8e4..1d53d2ead6a0 100644 --- a/gcc/testsuite/gcc.target/i386/pr59501-2.c +++ b/gcc/testsuite/gcc.target/i386/pr59501-2.c @@ -1,5 +1,6 @@ /* PR target/59501 */ /* { dg-do run } */ /* { dg-options "-O2 -mavx -maccumulate-outgoing-args" } */ +/* { dg-require-effective-target avx } */ #include "pr59501-1.c" diff --git a/gcc/testsuite/gcc.target/i386/pr59501-3.c b/gcc/testsuite/gcc.target/i386/pr59501-3.c index 0bf5ef6139a3..f27e9b3bb25c 100644 --- a/gcc/testsuite/gcc.target/i386/pr59501-3.c +++ b/gcc/testsuite/gcc.target/i386/pr59501-3.c @@ -1,6 +1,7 @@ /* PR target/59501 */ /* { dg-do run } */ /* { dg-options "-O2 -mavx -mno-accumulate-outgoing-args" } */ +/* { dg-require-effective-target avx } */ #define CHECK_H "avx-check.h" #define TEST avx_test diff --git a/gcc/testsuite/gcc.target/i386/pr59501-4.c b/gcc/testsuite/gcc.target/i386/pr59501-4.c index 43a5ad2428aa..57da1078034b 100644 --- a/gcc/testsuite/gcc.target/i386/pr59501-4.c +++ b/gcc/testsuite/gcc.target/i386/pr59501-4.c @@ -1,5 +1,6 @@ /* PR target/59501 */ /* { dg-do run } */ /* { dg-options "-O2 -mavx -maccumulate-outgoing-args" } */ +/* { dg-require-effective-target avx } */ #include "pr59501-3.c" diff --git a/gcc/testsuite/gcc.target/i386/pr59501-5.c b/gcc/testsuite/gcc.target/i386/pr59501-5.c index f2feca8ec4f0..2ec9f0cb579a 100644 --- a/gcc/testsuite/gcc.target/i386/pr59501-5.c +++ b/gcc/testsuite/gcc.target/i386/pr59501-5.c @@ -1,6 +1,7 @@ /* PR target/59501 */ /* { dg-do run } */ /* { dg-options "-O2 -mavx -mno-accumulate-outgoing-args" } */ +/* { dg-require-effective-target avx } */ #define CHECK_H "avx-check.h" #define TEST avx_test diff --git a/gcc/testsuite/gcc.target/i386/pr59501-6.c b/gcc/testsuite/gcc.target/i386/pr59501-6.c index d0ac2425b902..8d166cef2d71 100644 --- a/gcc/testsuite/gcc.target/i386/pr59501-6.c +++ b/gcc/testsuite/gcc.target/i386/pr59501-6.c @@ -1,5 +1,6 @@ /* PR target/59501 */ /* { dg-do run } */ /* { dg-options "-O2 -mavx -maccumulate-outgoing-args" } */ +/* { dg-require-effective-target avx } */ #include "pr59501-5.c" diff --git a/gcc/testsuite/gcc.target/i386/pr59644.c b/gcc/testsuite/gcc.target/i386/pr59644.c new file mode 100644 index 000000000000..96006b3e338d --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr59644.c @@ -0,0 +1,42 @@ +/* PR target/59644 */ +/* { dg-do run { target lp64 } } */ +/* { dg-options "-O2 -ffreestanding -mno-sse -mpreferred-stack-boundary=3 -maccumulate-outgoing-args -mno-red-zone" } */ + +/* This test uses __builtin_trap () instead of e.g. abort, + because due to -mpreferred-stack-boundary=3 it should not call + any library function from within main (). */ + +#include <stdarg.h> + +__attribute__((noinline, noclone)) +int +bar (int x, int y, int z, int w, const char *fmt, va_list ap) +{ + if (x != 1 || y != 2 || z != 3 || w != 4) + __builtin_trap (); + if (fmt[0] != 'f' || fmt[1] != 'o' || fmt[2] != 'o' || fmt[3]) + __builtin_trap (); + if (va_arg (ap, int) != 5 || va_arg (ap, int) != 6 + || va_arg (ap, long long) != 7LL) + __builtin_trap (); + return 9; +} + +__attribute__((noinline, noclone, optimize ("Os"))) +int +foo (const char *fmt, ...) +{ + va_list ap; + va_start (ap, fmt); + int r = bar (1, 2, 3, 4, fmt, ap); + va_end (ap); + return r; +} + +int +main () +{ + if (foo ("foo", 5, 6, 7LL) != 9) + __builtin_trap (); + return 0; +} diff --git a/gcc/testsuite/gcc.target/mips/pr59137.c b/gcc/testsuite/gcc.target/mips/pr59137.c new file mode 100644 index 000000000000..898650656806 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/pr59137.c @@ -0,0 +1,34 @@ +/* { dg-do run } */ +/* { dg-options "-mno-plt" } */ + +extern void abort (void); + +struct lispstruct +{ + int e; + int t; +}; + +struct lispstruct Cnil_body; +struct lispstruct Ct_body; +int nvalues; + +struct lispstruct * __attribute__ ((noinline)) +fLlistp (struct lispstruct *x0) +{ + if (x0 == &Cnil_body + || (((unsigned long) x0 >= 0x80000000) ? 0 + : (!x0->e ? (x0 != &Cnil_body) : x0->t))) + x0 = &Ct_body; + else + x0 = &Cnil_body; + nvalues = 1; + return x0; +} + +int main () +{ + if (fLlistp ((struct lispstruct *) 0xa0000001) != &Cnil_body) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.target/mips/umips-branch-3.c b/gcc/testsuite/gcc.target/mips/umips-branch-3.c new file mode 100644 index 000000000000..8717362e044b --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/umips-branch-3.c @@ -0,0 +1,10 @@ +/* { dg-options "(-mmicromips)" } */ +/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */ + +void MICROMIPS +foo (void) +{ + return; +} + +/* { dg-final { scan-assembler "\tjrc\t\\\$31\n" } } */ diff --git a/gcc/testsuite/gcc.target/mips/umips-branch-4.c b/gcc/testsuite/gcc.target/mips/umips-branch-4.c new file mode 100644 index 000000000000..b346d11723fa --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/umips-branch-4.c @@ -0,0 +1,12 @@ +/* { dg-options "(-mmicromips)" } */ + +void foo (void); + +int MICROMIPS +a (void) +{ + foo (); + return 0; +} + +/* { dg-final { scan-assembler "\tjals\tfoo\n\tnop" } } */ diff --git a/gcc/testsuite/gcc.target/sh/cmpstrn.c b/gcc/testsuite/gcc.target/sh/cmpstrn.c index bc72b2c51d22..3a1d0d1519ff 100644 --- a/gcc/testsuite/gcc.target/sh/cmpstrn.c +++ b/gcc/testsuite/gcc.target/sh/cmpstrn.c @@ -6,16 +6,23 @@ /* { 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) +/* Test that cmp/str is not used for small lengths. */ +test01(const char *s1) { return __builtin_strncmp (s1, "abcde", 3); } /* Test that the cmp/str loop is used. */ -test02(const char *s1, const char *s2, int n) +test02(const char *s1) { return __builtin_strncmp (s1, "abcdefghi", 8); } +/* Test that no call is generated */ +test03(const char *s1, int n) +{ + return __builtin_strncmp (s1, "abcde", n); +} + + diff --git a/gcc/testsuite/gfortran.dg/alloc_comp_basics_6.f90 b/gcc/testsuite/gfortran.dg/alloc_comp_basics_6.f90 new file mode 100644 index 000000000000..3ed221db24f0 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/alloc_comp_basics_6.f90 @@ -0,0 +1,11 @@ +! { dg-do compile } +! +! PR 58026: Bad error recovery for allocatable component of undeclared type +! +! Contributed by Joost VandeVondele <Joost.VandeVondele@mat.ethz.ch> + + type sysmtx_t + type(ext_complex_t), allocatable :: S(:) ! { dg-error "has not been previously defined" } + end type + +end diff --git a/gcc/testsuite/gfortran.dg/bind_c_procs_2.f90 b/gcc/testsuite/gfortran.dg/bind_c_procs_2.f90 new file mode 100644 index 000000000000..d3e751c3dc5e --- /dev/null +++ b/gcc/testsuite/gfortran.dg/bind_c_procs_2.f90 @@ -0,0 +1,22 @@ +! { dg-do compile } +! +! PR 59023: [4.9 regression] ICE in gfc_search_interface with BIND(C) +! +! Contributed by Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> + + type t + integer hidden + end type + +contains + + subroutine bar + type(t) :: toto + interface + integer function helper() bind(c) + end function + end interface + toto = t(helper()) + end subroutine + +end diff --git a/gcc/testsuite/gfortran.dg/binding_label_tests_10_main.f03 b/gcc/testsuite/gfortran.dg/binding_label_tests_10_main.f03 index 2a4a53ba80da..5216fbedf6ae 100644 --- a/gcc/testsuite/gfortran.dg/binding_label_tests_10_main.f03 +++ b/gcc/testsuite/gfortran.dg/binding_label_tests_10_main.f03 @@ -11,3 +11,4 @@ program main use binding_label_tests_10 ! { dg-error "Variable one from module binding_label_tests_10 with binding label c_one at .1. uses the same global identifier as entity at .2. from module binding_label_tests_10_main" } use binding_label_tests_10_main end program main +! { dg-final { cleanup-modules "binding_label_tests_10" } } diff --git a/gcc/testsuite/gfortran.dg/binding_label_tests_26a.f90 b/gcc/testsuite/gfortran.dg/binding_label_tests_26a.f90 new file mode 100644 index 000000000000..32cf07ae7c4a --- /dev/null +++ b/gcc/testsuite/gfortran.dg/binding_label_tests_26a.f90 @@ -0,0 +1,20 @@ +! { dg-do compile } +! +! PR 58182: [4.9 Regression] ICE with global binding name used as a FUNCTION +! +! Contributed by Andrew Bensons <abensonca@gmail.com> +! +! This file must be compiled BEFORE binding_label_tests_26b.f90, which it +! should be because dejagnu will sort the files. + +module fg +contains + function fffi(f) + interface + function f() bind(c) + end function + end interface + end function +end module + +! { dg-final { keep-modules "" } } diff --git a/gcc/testsuite/gfortran.dg/binding_label_tests_26b.f90 b/gcc/testsuite/gfortran.dg/binding_label_tests_26b.f90 new file mode 100644 index 000000000000..ad8426bc2c6f --- /dev/null +++ b/gcc/testsuite/gfortran.dg/binding_label_tests_26b.f90 @@ -0,0 +1,14 @@ +! { dg-do compile } +! +! PR 58182: [4.9 Regression] ICE with global binding name used as a FUNCTION +! +! Contributed by Andrew Bensons <abensonca@gmail.com> +! +! This file must be compiled AFTER binding_label_tests_26a.f90, which it +! should be because dejagnu will sort the files. + +module f ! { dg-error "uses the same global identifier" } + use fg ! { dg-error "uses the same global identifier" } +end module + +! { dg-final { cleanup-modules "fg f" } } diff --git a/gcc/testsuite/gfortran.dg/class_allocate_16.f90 b/gcc/testsuite/gfortran.dg/class_allocate_16.f90 new file mode 100644 index 000000000000..28776084d866 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/class_allocate_16.f90 @@ -0,0 +1,28 @@ +! { dg-do compile } +! { dg-options "-fdump-tree-original" } +! +! PR 59589: [4.9 Regression] [OOP] Memory leak when deallocating polymorphic +! +! Contributed by Rich Townsend <townsend@astro.wisc.edu> + + implicit none + + type :: foo + real, allocatable :: x(:) + end type + + type :: bar + type(foo) :: f + end type + + class(bar), allocatable :: b + + allocate(bar::b) + allocate(b%f%x(1000000)) + b%f%x = 1. + deallocate(b) + +end + +! { dg-final { scan-tree-dump-times "__builtin_free" 4 "original" } } +! { dg-final { cleanup-tree-dump "original" } } diff --git a/gcc/testsuite/gfortran.dg/inquire_10.f90 b/gcc/testsuite/gfortran.dg/inquire_10.f90 index 090653ecba59..bc7d6e36b387 100644 --- a/gcc/testsuite/gfortran.dg/inquire_10.f90 +++ b/gcc/testsuite/gfortran.dg/inquire_10.f90 @@ -10,6 +10,8 @@ inquire(file=trim(cwd) // '/cseq',number=unit) if (unit /= 23) call abort + close(unit=23, status = 'delete') + inquire(file='foo/../cseq2',number=unit) if (unit >= 0) call abort inquire(file='cseq2',number=unit) diff --git a/gcc/testsuite/gfortran.dg/inquire_15.f90 b/gcc/testsuite/gfortran.dg/inquire_15.f90 index e2aaf9ee17d3..ae94270ca8fa 100644 --- a/gcc/testsuite/gfortran.dg/inquire_15.f90 +++ b/gcc/testsuite/gfortran.dg/inquire_15.f90 @@ -22,6 +22,7 @@ open(99,access="sequential") inquire(99, stream=str) !print *, "str=",str if (str /= "NO") goto 10 +close(99, status="delete") stop 10 close(99, status="delete") call abort diff --git a/gcc/testsuite/gfortran.dg/lto/lto.exp b/gcc/testsuite/gfortran.dg/lto/lto.exp index b848f9fdf3b3..3e329792eff4 100644 --- a/gcc/testsuite/gfortran.dg/lto/lto.exp +++ b/gcc/testsuite/gfortran.dg/lto/lto.exp @@ -34,17 +34,17 @@ load_lib gfortran-dg.exp # Load the language-independent compabibility support procedures. load_lib lto.exp +# If LTO has not been enabled, bail. +if { ![check_effective_target_lto] } { + return +} + lto_init no-mathlib # Define an identifier for use with this suite to avoid name conflicts # with other lto tests running at the same time. set sid "f_lto" -# If LTO has not been enabled, bail. -if { ![check_effective_target_lto] } { - return -} - # Main loop. foreach src [lsort [glob -nocomplain $srcdir/$subdir/*_0.\[fF\]{,90,95,03,08} ]] { # If we're only testing specific files and this isn't one of them, skip it. diff --git a/gcc/testsuite/gfortran.dg/open_negative_unit_1.f90 b/gcc/testsuite/gfortran.dg/open_negative_unit_1.f90 index 6446436c8855..bbcf46b72a6a 100644 --- a/gcc/testsuite/gfortran.dg/open_negative_unit_1.f90 +++ b/gcc/testsuite/gfortran.dg/open_negative_unit_1.f90 @@ -6,6 +6,7 @@ program nutest implicit none + logical l integer id, ios open(newunit=id, file="foo.txt", iostat=ios) @@ -16,6 +17,14 @@ program nutest close(id, status="delete") + open(unit=10, file="foo.txt", status="old", iostat=ios) + if (ios /= 0) call abort + + close(10, status="delete") + open(-10, file="foo.txt", iostat=ios) if (ios == 0) call abort + + inquire(file="foo.txt", exist=l) + if (l) call abort end program nutest diff --git a/gcc/testsuite/gfortran.dg/pr16597.f90 b/gcc/testsuite/gfortran.dg/pr16597.f90 index c29147411a81..fc191efef7c7 100644 --- a/gcc/testsuite/gfortran.dg/pr16597.f90 +++ b/gcc/testsuite/gfortran.dg/pr16597.f90 @@ -19,7 +19,7 @@ open (UNIT=iunit,FORM='unformatted',ACCESS='direct',RECL=strlen) write (iunit, rec=1) 'ABCD' read (iunit, rec=1) string - close (iunit) + close (iunit, status = 'delete') if (string.ne.'ABCD') call abort open (UNIT=iunit,FORM='unformatted',ACCESS='direct',STATUS='scratch',RECL=strlen) diff --git a/gcc/testsuite/gfortran.dg/pr59700.f90 b/gcc/testsuite/gfortran.dg/pr59700.f90 new file mode 100644 index 000000000000..579d8a48c9ae --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr59700.f90 @@ -0,0 +1,40 @@ +! { dg-do run } +! PR59700 Test case by Steve Kargl +program foo + + implicit none + + character(len=80) msg + integer, parameter :: fd = 10 + integer i1, i2, i3, i4 + real x1, x2, x3, x4 + complex c1, c2 + logical a + + open(unit=fd, status='scratch') + write(fd, '(A)') '1 2 3.4 q' + + rewind(fd) + msg = 'ok' + read(fd, *, err=10, iomsg=msg) i1, i2, i3, i4 +10 if (msg /= 'Bad integer for item 3 in list input') call abort + rewind(fd) + msg = 'ok' + read(fd, *, err=20, iomsg=msg) x1, x2, x3, x4 +20 if (msg /= 'Bad real number in item 4 of list input') call abort + rewind(fd) + msg = 'ok' + read(fd, *, err=30, iomsg=msg) i1, x2, x1, a +30 if (msg /= 'Bad logical value while reading item 4') call abort + rewind(fd) + read(fd, *, err=31, iomsg=msg) i1, x2, a, x1 +31 if (msg /= 'Bad repeat count in item 3 of list input') call abort + close(fd) + open(unit=fd, status='scratch') + write(fd, '(A)') '(1, 2) (3.4, q)' + rewind(fd) + msg = 'ok' + read(fd, *, err=40, iomsg=msg) c1, c2 +40 if (msg /= 'Bad floating point number for item 2') call abort + close(fd) +end program foo diff --git a/gcc/testsuite/gfortran.dg/typebound_proc_32.f90 b/gcc/testsuite/gfortran.dg/typebound_proc_32.f90 new file mode 100644 index 000000000000..00ae9c732633 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/typebound_proc_32.f90 @@ -0,0 +1,35 @@ +! { dg-do compile } +! +! PR 59547: [OOP] Problem with using tbp specification function in multiple class procedures +! +! Contributed by <bugs@miller-mohr.de> + +module classes + + implicit none + + type :: base_class + contains + procedure, nopass :: get_num + procedure :: get_array, get_array2 + end type + +contains + + pure integer function get_num() + get_num = 2 + end function + + function get_array( this ) result(array) + class(base_class), intent(in) :: this + integer, dimension( this%get_num() ) :: array + end function + + function get_array2( this ) result(array) + class(base_class), intent(in) :: this + integer, dimension( this%get_num(), this%get_num() ) :: array + end function + +end module + +! { dg-final { cleanup-modules "classes" } } diff --git a/gcc/testsuite/gfortran.dg/use_only_3.f90 b/gcc/testsuite/gfortran.dg/use_only_3.f90 index b264506d4c38..ebb39289fc48 100644 --- a/gcc/testsuite/gfortran.dg/use_only_3.f90 +++ b/gcc/testsuite/gfortran.dg/use_only_3.f90 @@ -32,3 +32,4 @@ subroutine dforceb(c0, i, betae, ipol, bec0, ctabin, gqq, gqqm, qmat, dq2, df) & dq2, gmes end subroutine dforceb +! { dg-final { cleanup-modules "cell_base constants control_flags cvan electrons_base electrons_nose gvecs gvecw ions_base kinds parameters" } } diff --git a/gcc/testsuite/gnat.dg/loop_optimization17.adb b/gcc/testsuite/gnat.dg/loop_optimization17.adb new file mode 100644 index 000000000000..2178b65bf1f0 --- /dev/null +++ b/gcc/testsuite/gnat.dg/loop_optimization17.adb @@ -0,0 +1,22 @@ +-- { dg-do run } +-- { dg-options "-O" } + +with Loop_Optimization17_Pkg; use Loop_Optimization17_Pkg; + +procedure Loop_Optimization17 is + + Data : Arr; + +begin + + Data := (others => (I => 0, + V1 => (others => 0.0), + V2 => (others => 0.0), + S => 0.0)); + + for I in Index_T'Range loop + Object (I).V1 := F (Data (I).V1); + Object (I).V2 := F (Data (I).V2); + end loop; + +end; diff --git a/gcc/testsuite/gnat.dg/loop_optimization17_pkg.adb b/gcc/testsuite/gnat.dg/loop_optimization17_pkg.adb new file mode 100644 index 000000000000..20815af4775f --- /dev/null +++ b/gcc/testsuite/gnat.dg/loop_optimization17_pkg.adb @@ -0,0 +1,5 @@ +package body Loop_Optimization17_Pkg is + + function F (V : Vector) return Vector is begin return V; end; + +end Loop_Optimization17_Pkg; diff --git a/gcc/testsuite/gnat.dg/loop_optimization17_pkg.ads b/gcc/testsuite/gnat.dg/loop_optimization17_pkg.ads new file mode 100644 index 000000000000..5b650dfa8864 --- /dev/null +++ b/gcc/testsuite/gnat.dg/loop_optimization17_pkg.ads @@ -0,0 +1,29 @@ +package Loop_Optimization17_Pkg is + + type vector is array (1..3) of Long_Float; + + type Rec is + record + I : Integer; + V1, V2 : Vector; + S : Long_Float; + end record; + + for Rec use + record + I at 0 range 0 .. 31; + V1 at 4 range 0 .. 191; + V2 at 28 range 0 .. 191; + S at 52 range 0 .. 63; + end record; + for Rec'Alignment use 4; + for Rec'Size use 480; + + type Index_T is range 1 .. 5; + type Arr is array (Index_T) of Rec; + + Object : Arr; + + function F (V : Vector) return Vector; + +end Loop_Optimization17_Pkg; diff --git a/gcc/testsuite/gnat.dg/weak2.adb b/gcc/testsuite/gnat.dg/weak2.adb new file mode 100644 index 000000000000..9e704b50c0da --- /dev/null +++ b/gcc/testsuite/gnat.dg/weak2.adb @@ -0,0 +1,10 @@ +-- { dg-do compile } + +package body Weak2 is + + function F return Integer is + begin + return Var; + end; + +end Weak2; diff --git a/gcc/testsuite/gnat.dg/weak2.ads b/gcc/testsuite/gnat.dg/weak2.ads new file mode 100644 index 000000000000..0a0011a6ecae --- /dev/null +++ b/gcc/testsuite/gnat.dg/weak2.ads @@ -0,0 +1,9 @@ +package Weak2 is + + Var : Integer; + pragma Import (Ada, Var, "var_name"); + pragma Weak_External (Var); + + function F return Integer; + +end Weak2; diff --git a/gcc/testsuite/go.test/go-test.exp b/gcc/testsuite/go.test/go-test.exp index 0f95edc182d3..f1eed08bd3e1 100644 --- a/gcc/testsuite/go.test/go-test.exp +++ b/gcc/testsuite/go.test/go-test.exp @@ -400,17 +400,16 @@ proc go-gc-tests { } { } if { ( [file tail $test] == "select2.go" \ - || [file tail $test] == "stack.go" ) \ + || [file tail $test] == "stack.go" \ + || [file tail $test] == "peano.go" ) \ && ! [check_effective_target_split_stack] } { - # chan/select2.go fails on targets without split stack, - # because they allocate a large stack segment that blows - # out the memory calculations. + # These tests fails on targets without split stack. untested $name continue } - if { [file tail $test] == "rotate.go" } { - # This test produces a temporary file that takes too long + if [string match "*go.test/test/rotate\[0123\].go" $test] { + # These tests produces a temporary file that takes too long # to compile--5 minutes on my laptop without optimization. # When compiling without optimization it tests nothing # useful, since the point of the test is to see whether @@ -1144,6 +1143,10 @@ proc go-gc-tests { } { || $test_line == "// \$G \$D/pkg.go && pack grcS pkg.a pkg.\$A 2> /dev/null && rm pkg.\$A && \$G -I. -u \$D/main.go" } { # This tests the gc -u option, which gccgo does not # support. + } elseif { $test_line == "// errorcheck -0 -N -d=nil" \ + || $test_line == "// errorcheck -0 -d=nil" } { + # This tests gc nil pointer checks using -d=nil, which + # gccgo does not support. } else { clone_output "$name: unrecognized test line: $test_line" unsupported $name diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index 5166679dacd9..159f88f28dd8 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -1035,6 +1035,16 @@ proc check_iconv_available { test_what } { }] $libiconv] } +# Return true if Cilk Library is supported on the target. +proc check_libcilkrts_available { } { + return [ check_no_compiler_messages_nocache libcilkrts_available executable { + int main (void) { + __cilkrts_set_param ("nworkers", "0"); + return 0; + } + } "-fcilkplus -lcilkrts" ] +} + # Return 1 if an ASCII locale is supported on this host, 0 otherwise. proc check_ascii_locale_available { } { @@ -2301,19 +2311,37 @@ proc check_effective_target_arm_unaligned { } { } # Return 1 if this is an ARM target supporting -mfpu=crypto-neon-fp-armv8 -# -mfloat-abi=softfp. -proc check_effective_target_arm_crypto_ok {} { +# -mfloat-abi=softfp or equivalent options. Some multilibs may be +# incompatible with these options. Also set et_arm_crypto_flags to the +# best options to add. + +proc check_effective_target_arm_crypto_ok_nocache { } { + global et_arm_crypto_flags + set et_arm_crypto_flags "" if { [check_effective_target_arm32] } { - return [check_no_compiler_messages arm_crypto_ok object { - int foo (void) - { - __asm__ volatile ("aese.8 q0, q0"); - return 0; - } - } "-mfpu=crypto-neon-fp-armv8 -mfloat-abi=softfp"] - } else { - return 0 + foreach flags {"" "-mfloat-abi=softfp" "-mfpu=crypto-neon-fp-armv8" "-mfpu=crypto-neon-fp-armv8 -mfloat-abi=softfp"} { + if { [check_no_compiler_messages_nocache arm_crypto_ok object { + #include "arm_neon.h" + uint8x16_t + foo (uint8x16_t a, uint8x16_t b) + { + return vaeseq_u8 (a, b); + } + } "$flags"] } { + set et_arm_crypto_flags $flags + return 1 + } + } } + + return 0 +} + +# Return 1 if this is an ARM target supporting -mfpu=crypto-neon-fp-armv8 + +proc check_effective_target_arm_crypto_ok { } { + return [check_cached_effective_target arm_crypto_ok \ + check_effective_target_arm_crypto_ok_nocache] } # Add options for crypto extensions. @@ -2321,7 +2349,8 @@ proc add_options_for_arm_crypto { flags } { if { ! [check_effective_target_arm_crypto_ok] } { return "$flags" } - return "$flags -mfpu=crypto-neon-fp-armv8 -mfloat-abi=softfp" + global et_arm_crypto_flags + return "$flags $et_arm_crypto_flags" } # Add the options needed for NEON. We need either -mfloat-abi=softfp diff --git a/gcc/toplev.c b/gcc/toplev.c index 38e986c15600..c652522a3613 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -78,6 +78,7 @@ along with GCC; see the file COPYING3. If not see #include "diagnostic-color.h" #include "context.h" #include "pass_manager.h" +#include "optabs.h" #if defined(DBX_DEBUGGING_INFO) || defined(XCOFF_DEBUGGING_INFO) #include "dbxout.h" @@ -1752,6 +1753,23 @@ target_reinit (void) { struct rtl_data saved_x_rtl; rtx *saved_regno_reg_rtx; + tree saved_optimization_current_node; + struct target_optabs *saved_this_fn_optabs; + + /* Temporarily switch to the default optimization node, so that + *this_target_optabs is set to the default, not reflecting + whatever a previous function used for the optimize + attribute. */ + saved_optimization_current_node = optimization_current_node; + saved_this_fn_optabs = this_fn_optabs; + if (saved_optimization_current_node != optimization_default_node) + { + optimization_current_node = optimization_default_node; + cl_optimization_restore + (&global_options, + TREE_OPTIMIZATION (optimization_default_node)); + } + this_fn_optabs = this_target_optabs; /* Save *crtl and regno_reg_rtx around the reinitialization to allow target_reinit being called even after prepare_function_start. */ @@ -1769,7 +1787,16 @@ target_reinit (void) /* Reinitialize lang-dependent parts. */ lang_dependent_init_target (); - /* And restore it at the end, as free_after_compilation from + /* Restore the original optimization node. */ + if (saved_optimization_current_node != optimization_default_node) + { + optimization_current_node = saved_optimization_current_node; + cl_optimization_restore (&global_options, + TREE_OPTIMIZATION (optimization_current_node)); + } + this_fn_optabs = saved_this_fn_optabs; + + /* Restore regno_reg_rtx at the end, as free_after_compilation from expand_dummy_function_end clears it. */ if (saved_regno_reg_rtx) { diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index 1d1a58d0f475..83cbda9f3a29 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -161,7 +161,6 @@ static void make_goto_expr_edges (basic_block); static void make_gimple_asm_edges (basic_block); static edge gimple_redirect_edge_and_branch (edge, basic_block); static edge gimple_try_redirect_by_replacing_jump (edge, basic_block); -static unsigned int split_critical_edges (void); /* Various helpers. */ static inline bool stmt_starts_bb_p (gimple, gimple); @@ -7931,7 +7930,7 @@ struct cfg_hooks gimple_cfg_hooks = { /* Split all critical edges. */ -static unsigned int +unsigned int split_critical_edges (void) { basic_block bb; diff --git a/gcc/tree-cfg.h b/gcc/tree-cfg.h index 8d045a4e2dcc..babbd2db2cab 100644 --- a/gcc/tree-cfg.h +++ b/gcc/tree-cfg.h @@ -93,5 +93,6 @@ extern tree gimplify_build1 (gimple_stmt_iterator *, enum tree_code, tree, tree); extern void extract_true_false_edges_from_block (basic_block, edge *, edge *); extern unsigned int execute_fixup_cfg (void); +extern unsigned int split_critical_edges (void); #endif /* _TREE_CFG_H */ diff --git a/gcc/tree-core.h b/gcc/tree-core.h index fac93550e1eb..57af2377fb79 100644 --- a/gcc/tree-core.h +++ b/gcc/tree-core.h @@ -1570,18 +1570,25 @@ struct GTY(()) tree_optimization_option { /* Target optabs for this set of optimization options. This is of type `struct target_optabs *'. */ - unsigned char *GTY ((atomic)) optabs; + void *GTY ((atomic)) optabs; /* The value of this_target_optabs against which the optabs above were generated. */ struct target_optabs *GTY ((skip)) base_optabs; }; +/* Forward declaration, defined in target-globals.h. */ + +struct GTY(()) target_globals; + /* Target options used by a function. */ struct GTY(()) tree_target_option { struct tree_common common; + /* Target globals for the corresponding target option. */ + struct target_globals *globals; + /* The optimization options used by the user. */ struct cl_target_option opts; }; diff --git a/gcc/tree-predcom.c b/gcc/tree-predcom.c index 3eaf81d334d9..35743cbe3bd8 100644 --- a/gcc/tree-predcom.c +++ b/gcc/tree-predcom.c @@ -773,10 +773,37 @@ split_data_refs_to_components (struct loop *loop, bad = component_of (comp_father, n); /* If both A and B are reads, we may ignore unsuitable dependences. */ - if (DR_IS_READ (dra) && DR_IS_READ (drb) - && (ia == bad || ib == bad - || !determine_offset (dra, drb, &dummy_off))) - continue; + if (DR_IS_READ (dra) && DR_IS_READ (drb)) + { + if (ia == bad || ib == bad + || !determine_offset (dra, drb, &dummy_off)) + continue; + } + /* If A is read and B write or vice versa and there is unsuitable + dependence, instead of merging both components into a component + that will certainly not pass suitable_component_p, just put the + read into bad component, perhaps at least the write together with + all the other data refs in it's component will be optimizable. */ + else if (DR_IS_READ (dra) && ib != bad) + { + if (ia == bad) + continue; + else if (!determine_offset (dra, drb, &dummy_off)) + { + merge_comps (comp_father, comp_size, bad, ia); + continue; + } + } + else if (DR_IS_READ (drb) && ia != bad) + { + if (ib == bad) + continue; + else if (!determine_offset (dra, drb, &dummy_off)) + { + merge_comps (comp_father, comp_size, bad, ib); + continue; + } + } merge_comps (comp_father, comp_size, ia, ib); } @@ -2420,6 +2447,7 @@ tree_predictive_commoning_loop (struct loop *loop) if (!components) { free_data_refs (datarefs); + free_affine_expand_cache (&name_expansions); return false; } diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c index d5b08566f6ed..049da5fcdfa8 100644 --- a/gcc/tree-ssa-loop-ivopts.c +++ b/gcc/tree-ssa-loop-ivopts.c @@ -1668,50 +1668,30 @@ constant_multiple_of (tree top, tree bot, widest_int *mul) } } -/* Returns true if memory reference REF with step STEP may be unaligned. */ +/* Return true if memory reference REF with step STEP may be unaligned. */ static bool may_be_unaligned_p (tree ref, tree step) { - tree base; - tree base_type; - HOST_WIDE_INT bitsize; - HOST_WIDE_INT bitpos; - tree toffset; - enum machine_mode mode; - int unsignedp, volatilep; - unsigned base_align; - /* TARGET_MEM_REFs are translated directly to valid MEMs on the target, thus they are not misaligned. */ if (TREE_CODE (ref) == TARGET_MEM_REF) return false; - /* The test below is basically copy of what expr.c:normal_inner_ref - does to check whether the object must be loaded by parts when - STRICT_ALIGNMENT is true. */ - base = get_inner_reference (ref, &bitsize, &bitpos, &toffset, &mode, - &unsignedp, &volatilep, true); - base_type = TREE_TYPE (base); - base_align = get_object_alignment (base); - base_align = MAX (base_align, TYPE_ALIGN (base_type)); + unsigned int align = TYPE_ALIGN (TREE_TYPE (ref)); - if (mode != BLKmode) - { - unsigned mode_align = GET_MODE_ALIGNMENT (mode); - - if (base_align < mode_align - || (bitpos % mode_align) != 0 - || (bitpos % BITS_PER_UNIT) != 0) - return true; - - if (toffset - && (highest_pow2_factor (toffset) * BITS_PER_UNIT) < mode_align) - return true; + unsigned HOST_WIDE_INT bitpos; + unsigned int ref_align; + get_object_alignment_1 (ref, &ref_align, &bitpos); + if (ref_align < align + || (bitpos % align) != 0 + || (bitpos % BITS_PER_UNIT) != 0) + return true; - if ((highest_pow2_factor (step) * BITS_PER_UNIT) < mode_align) - return true; - } + unsigned int trailing_zeros = tree_ctz (step); + if (trailing_zeros < HOST_BITS_PER_INT + && (1U << trailing_zeros) * BITS_PER_UNIT < align) + return true; return false; } @@ -5733,18 +5713,20 @@ iv_ca_extend (struct ivopts_data *data, struct iv_ca *ivs, } /* Try narrowing set IVS by removing CAND. Return the cost of - the new set and store the differences in DELTA. */ + the new set and store the differences in DELTA. START is + the candidate with which we start narrowing. */ static comp_cost iv_ca_narrow (struct ivopts_data *data, struct iv_ca *ivs, - struct iv_cand *cand, struct iv_ca_delta **delta) + struct iv_cand *cand, struct iv_cand *start, + struct iv_ca_delta **delta) { unsigned i, ci; struct iv_use *use; struct cost_pair *old_cp, *new_cp, *cp; bitmap_iterator bi; struct iv_cand *cnd; - comp_cost cost; + comp_cost cost, best_cost, acost; *delta = NULL; for (i = 0; i < n_iv_uses (data); i++) @@ -5755,13 +5737,15 @@ iv_ca_narrow (struct ivopts_data *data, struct iv_ca *ivs, if (old_cp->cand != cand) continue; - new_cp = NULL; + best_cost = iv_ca_cost (ivs); + /* Start narrowing with START. */ + new_cp = get_use_iv_cost (data, use, start); if (data->consider_all_candidates) { EXECUTE_IF_SET_IN_BITMAP (ivs->cands, 0, ci, bi) { - if (ci == cand->id) + if (ci == cand->id || (start && ci == start->id)) continue; cnd = iv_cand (data, ci); @@ -5770,20 +5754,21 @@ iv_ca_narrow (struct ivopts_data *data, struct iv_ca *ivs, if (!cp) continue; - if (!iv_ca_has_deps (ivs, cp)) - continue; - - if (!cheaper_cost_pair (cp, new_cp)) - continue; + iv_ca_set_cp (data, ivs, use, cp); + acost = iv_ca_cost (ivs); - new_cp = cp; + if (compare_costs (acost, best_cost) < 0) + { + best_cost = acost; + new_cp = cp; + } } } else { EXECUTE_IF_AND_IN_BITMAP (use->related_cands, ivs->cands, 0, ci, bi) { - if (ci == cand->id) + if (ci == cand->id || (start && ci == start->id)) continue; cnd = iv_cand (data, ci); @@ -5791,15 +5776,19 @@ iv_ca_narrow (struct ivopts_data *data, struct iv_ca *ivs, cp = get_use_iv_cost (data, use, cnd); if (!cp) continue; - if (!iv_ca_has_deps (ivs, cp)) - continue; - if (!cheaper_cost_pair (cp, new_cp)) - continue; + iv_ca_set_cp (data, ivs, use, cp); + acost = iv_ca_cost (ivs); - new_cp = cp; + if (compare_costs (acost, best_cost) < 0) + { + best_cost = acost; + new_cp = cp; + } } } + /* Restore to old cp for use. */ + iv_ca_set_cp (data, ivs, use, old_cp); if (!new_cp) { @@ -5841,7 +5830,7 @@ iv_ca_prune (struct ivopts_data *data, struct iv_ca *ivs, if (cand == except_cand) continue; - acost = iv_ca_narrow (data, ivs, cand, &act_delta); + acost = iv_ca_narrow (data, ivs, cand, except_cand, &act_delta); if (compare_costs (acost, best_cost) < 0) { diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c index 1637d68974f6..a48ad10424e9 100644 --- a/gcc/tree-ssa-loop-niter.c +++ b/gcc/tree-ssa-loop-niter.c @@ -1309,7 +1309,7 @@ dump_affine_iv (FILE *file, affine_iv *iv) if EVERY_ITERATION is true, we know the test is executed on every iteration. The results (number of iterations and assumptions as described in - comments at struct tree_niter_desc in tree-flow.h) are stored to NITER. + comments at struct tree_niter_desc in tree-ssa-loop.h) are stored to NITER. Returns false if it fails to determine number of iterations, true if it was determined (possibly with some assumptions). */ diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c index 0b940a417046..77d05624ff24 100644 --- a/gcc/tree-ssa-pre.c +++ b/gcc/tree-ssa-pre.c @@ -4798,9 +4798,11 @@ const pass_data pass_data_pre = true, /* has_gate */ true, /* has_execute */ TV_TREE_PRE, /* tv_id */ + /* PROP_no_crit_edges is ensured by placing pass_split_crit_edges before + pass_pre. */ ( PROP_no_crit_edges | PROP_cfg | PROP_ssa ), /* properties_required */ 0, /* properties_provided */ - 0, /* properties_destroyed */ + PROP_no_crit_edges, /* properties_destroyed */ TODO_rebuild_alias, /* todo_flags_start */ TODO_verify_ssa, /* todo_flags_finish */ }; diff --git a/gcc/tree-ssa-sink.c b/gcc/tree-ssa-sink.c index d2de147799dc..6d02975c4dda 100644 --- a/gcc/tree-ssa-sink.c +++ b/gcc/tree-ssa-sink.c @@ -567,7 +567,7 @@ static void execute_sink_code (void) { loop_optimizer_init (LOOPS_NORMAL); - + split_critical_edges (); connect_infinite_loops_to_exit (); memset (&sink_stats, 0, sizeof (sink_stats)); calculate_dominance_info (CDI_DOMINATORS); @@ -604,7 +604,9 @@ const pass_data pass_data_sink_code = true, /* has_gate */ true, /* has_execute */ TV_TREE_SINK, /* tv_id */ - ( PROP_no_crit_edges | PROP_cfg | PROP_ssa ), /* properties_required */ + /* PROP_no_crit_edges is ensured by running split_critical_edges in + execute_sink_code. */ + ( PROP_cfg | PROP_ssa ), /* properties_required */ 0, /* properties_provided */ 0, /* properties_destroyed */ 0, /* todo_flags_start */ diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c index 26b24f9b2962..17c4279938b1 100644 --- a/gcc/tree-vect-data-refs.c +++ b/gcc/tree-vect-data-refs.c @@ -3318,9 +3318,10 @@ again: { gimple def = SSA_NAME_DEF_STMT (off); tree reft = TREE_TYPE (DR_REF (newdr)); - if (gimple_call_internal_p (def) - && gimple_call_internal_fn (def) - == IFN_GOMP_SIMD_LANE) + if (is_gimple_call (def) + && gimple_call_internal_p (def) + && (gimple_call_internal_fn (def) + == IFN_GOMP_SIMD_LANE)) { tree arg = gimple_call_arg (def, 0); gcc_assert (TREE_CODE (arg) == SSA_NAME); diff --git a/gcc/tree-vect-loop-manip.c b/gcc/tree-vect-loop-manip.c index ecb446c02f4c..ebcbfb47c5f2 100644 --- a/gcc/tree-vect-loop-manip.c +++ b/gcc/tree-vect-loop-manip.c @@ -483,7 +483,18 @@ slpeel_update_phi_nodes_for_guard1 (edge guard_edge, struct loop *loop, if (!current_new_name) continue; } - gcc_assert (get_current_def (current_new_name) == NULL_TREE); + tree new_name = get_current_def (current_new_name); + /* Because of peeled_chrec optimization it is possible that we have + set this earlier. Verify the PHI has the same value. */ + if (new_name) + { + gimple phi = SSA_NAME_DEF_STMT (new_name); + gcc_assert (gimple_code (phi) == GIMPLE_PHI + && gimple_bb (phi) == *new_exit_bb + && (PHI_ARG_DEF_FROM_EDGE (phi, single_exit (loop)) + == loop_arg)); + continue; + } set_current_def (current_new_name, PHI_RESULT (new_phi)); } diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c index 2b075dfea96f..372d7db3e70f 100644 --- a/gcc/tree-vect-slp.c +++ b/gcc/tree-vect-slp.c @@ -2110,17 +2110,6 @@ vect_slp_analyze_bb_1 (basic_block bb) vect_pattern_recog (NULL, bb_vinfo); - if (!vect_slp_analyze_data_ref_dependences (bb_vinfo)) - { - if (dump_enabled_p ()) - dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, - "not vectorized: unhandled data dependence " - "in basic block.\n"); - - destroy_bb_vec_info (bb_vinfo); - return NULL; - } - if (!vect_analyze_data_refs_alignment (NULL, bb_vinfo)) { if (dump_enabled_p ()) @@ -2155,6 +2144,29 @@ vect_slp_analyze_bb_1 (basic_block bb) vect_mark_slp_stmts_relevant (SLP_INSTANCE_TREE (instance)); } + /* Mark all the statements that we do not want to vectorize. */ + for (gimple_stmt_iterator gsi = gsi_start_bb (BB_VINFO_BB (bb_vinfo)); + !gsi_end_p (gsi); gsi_next (&gsi)) + { + stmt_vec_info vinfo = vinfo_for_stmt (gsi_stmt (gsi)); + if (STMT_SLP_TYPE (vinfo) != pure_slp) + STMT_VINFO_VECTORIZABLE (vinfo) = false; + } + + /* Analyze dependences. At this point all stmts not participating in + vectorization have to be marked. Dependence analysis assumes + that we either vectorize all SLP instances or none at all. */ + if (!vect_slp_analyze_data_ref_dependences (bb_vinfo)) + { + if (dump_enabled_p ()) + dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, + "not vectorized: unhandled data dependence " + "in basic block.\n"); + + destroy_bb_vec_info (bb_vinfo); + return NULL; + } + if (!vect_verify_datarefs_alignment (NULL, bb_vinfo)) { if (dump_enabled_p ()) diff --git a/gcc/tree.c b/gcc/tree.c index 18e4e369297d..914508e0cd6f 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -11419,6 +11419,28 @@ build_target_option_node (struct gcc_options *opts) return t; } +/* Reset TREE_TARGET_GLOBALS cache for TARGET_OPTION_NODE. + Called through htab_traverse. */ + +static int +prepare_target_option_node_for_pch (void **slot, void *) +{ + tree node = (tree) *slot; + if (TREE_CODE (node) == TARGET_OPTION_NODE) + TREE_TARGET_GLOBALS (node) = NULL; + return 1; +} + +/* Clear TREE_TARGET_GLOBALS of all TARGET_OPTION_NODE trees, + so that they aren't saved during PCH writing. */ + +void +prepare_target_option_nodes_for_pch (void) +{ + htab_traverse (cl_option_hash_table, prepare_target_option_node_for_pch, + NULL); +} + /* Determine the "ultimate origin" of a block. The block may be an inlined instance of an inlined instance of a block which is local to an inline function, so we have to trace all of the way back through the origin chain diff --git a/gcc/tree.h b/gcc/tree.h index 40381646dc80..6cccb3f87542 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -1117,9 +1117,6 @@ extern void protected_set_expr_location (tree, location_t); the given label expression. */ #define LABEL_EXPR_LABEL(NODE) TREE_OPERAND (LABEL_EXPR_CHECK (NODE), 0) -/* VDEF_EXPR accessors are specified in tree-flow.h, along with the other - accessors for SSA operands. */ - /* CATCH_EXPR accessors. */ #define CATCH_TYPES(NODE) TREE_OPERAND (CATCH_EXPR_CHECK (NODE), 0) #define CATCH_BODY(NODE) TREE_OPERAND (CATCH_EXPR_CHECK (NODE), 1) @@ -2698,9 +2695,14 @@ extern tree build_optimization_node (struct gcc_options *opts); #define TREE_TARGET_OPTION(NODE) \ (&TARGET_OPTION_NODE_CHECK (NODE)->target_option.opts) +#define TREE_TARGET_GLOBALS(NODE) \ + (TARGET_OPTION_NODE_CHECK (NODE)->target_option.globals) + /* Return a tree node that encapsulates the target options in OPTS. */ extern tree build_target_option_node (struct gcc_options *opts); +extern void prepare_target_option_nodes_for_pch (void); + #if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007) inline tree diff --git a/gcc/tsan.c b/gcc/tsan.c index 2c053bd9e340..2e32cd2b32f7 100644 --- a/gcc/tsan.c +++ b/gcc/tsan.c @@ -609,7 +609,7 @@ instrument_gimple (gimple_stmt_iterator *gsi) && (gimple_call_fndecl (stmt) != builtin_decl_implicit (BUILT_IN_TSAN_INIT))) { - if (is_gimple_builtin_call (stmt)) + if (gimple_call_builtin_p (stmt, BUILT_IN_NORMAL)) instrument_builtin_call (gsi); return true; } diff --git a/gcc/ubsan.c b/gcc/ubsan.c index 7cc8c180ba83..1841a947b9c6 100644 --- a/gcc/ubsan.c +++ b/gcc/ubsan.c @@ -311,6 +311,9 @@ ubsan_type_descriptor (tree type, bool want_pointer_type_p) type2 = TYPE_METHOD_BASETYPE (type2); } + /* If an array, get its type. */ + type2 = strip_array_types (type2); + if (TYPE_NAME (type2) != NULL) { if (TREE_CODE (TYPE_NAME (type2)) == IDENTIFIER_NODE) diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c index 4d6aed24b0cf..dcbbbd26f782 100644 --- a/gcc/var-tracking.c +++ b/gcc/var-tracking.c @@ -5947,6 +5947,13 @@ add_stores (rtx loc, const_rtx expr, void *cuip) if (type != MO_VAL_SET) goto log_and_return; + v = find_use_val (oloc, mode, cui); + + if (!v) + goto log_and_return; + + resolve = preserve = !cselib_preserved_value_p (v); + /* We cannot track values for multiple-part variables, so we track only locations for tracked parameters passed either by invisible reference or directly in multiple locations. */ @@ -5960,14 +5967,15 @@ add_stores (rtx loc, const_rtx expr, void *cuip) && XEXP (DECL_INCOMING_RTL (REG_EXPR (loc)), 0) != arg_pointer_rtx) || (GET_CODE (DECL_INCOMING_RTL (REG_EXPR (loc))) == PARALLEL && XVECLEN (DECL_INCOMING_RTL (REG_EXPR (loc)), 0) > 1))) - goto log_and_return; - - v = find_use_val (oloc, mode, cui); - - if (!v) - goto log_and_return; - - resolve = preserve = !cselib_preserved_value_p (v); + { + /* Although we don't use the value here, it could be used later by the + mere virtue of its existence as the operand of the reverse operation + that gave rise to it (typically extension/truncation). Make sure it + is preserved as required by vt_expand_var_loc_chain. */ + if (preserve) + preserve_value (v); + goto log_and_return; + } if (loc == stack_pointer_rtx && hard_frame_pointer_adjustment != -1 |