diff options
694 files changed, 16548 insertions, 4801 deletions
diff --git a/ChangeLog b/ChangeLog index 5f576400655..522743a09c4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,10 @@ -2013-11-18 Jan Hubicka <jh@suse.cz> +2013-12-03 Bill Schmidt <wschmidt@linux.vnet.ibm.com> - * config/bootstrap-lto.mk: Use -ffat-lto-objects. + * MAINTAINERS: Add self as SLSR maintainer. + +2013-11-18 Jan Hubicka <hubicka@ucw.cz> + + * MAINTAINERS: Update my email address. 2013-11-15 David Edelsohn <dje.gcc@gmail.com> @@ -216,7 +220,6 @@ 2013-01-23 Shenghou Ma <minux.ma@gmail.com> - * config/isl.m4: don't echo $CFLAGS for ISL_CHECK_VERSION. * configure: Re-generate. 2013-01-15 Richard Biener <rguenther@suse.de> diff --git a/MAINTAINERS b/MAINTAINERS index a325a350c0c..c51ac0f02fc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -66,7 +66,7 @@ h8 port Kazu Hirata kazu@codesourcery.com hppa port Jeff Law law@redhat.com hppa port John David Anglin dave.anglin@nrc-cnrc.gc.ca i386 port Richard Henderson rth@redhat.com -i386 port Jan Hubicka jh@suse.cz +i386 port Jan Hubicka hubicka@ucw.cz i386 port Uros Bizjak ubizjak@gmail.com ia64 port Jim Wilson wilson@tuliptree.org ia64 port Steve Ellcey sellcey@mips.com @@ -112,7 +112,7 @@ tilegx port Walter Lee walt@tilera.com tilepro port Walter Lee walt@tilera.com v850 port Nick Clifton nickc@redhat.com vax port Matt Thomas matt@3am-software.com -x86-64 port Jan Hubicka jh@suse.cz +x86-64 port Jan Hubicka hubicka@ucw.cz xstormy16 port Nick Clifton nickc@redhat.com xtensa port Sterling Augustine augustine.sterling@gmail.com @@ -188,7 +188,7 @@ scheduler (+ haifa) Vladimir Makarov vmakarov@redhat.com modulo-scheduler Ayal Zaks zaks@il.ibm.com reorg Jeff Law law@redhat.com caller-save.c Jeff Law law@redhat.com -callgraph Jan Hubicka jh@suse.cz +callgraph Jan Hubicka hubicka@ucw.cz debugging code Jim Wilson wilson@tuliptree.org dwarf debugging code Jason Merrill jason@redhat.com dwarf debugging code Cary Coutant ccoutant@google.com @@ -222,9 +222,9 @@ docs co-maintainer Joseph Myers joseph@codesourcery.com docstring relicensing Diego Novillo dnovillo@google.com docstring relicensing Gerald Pfeifer gerald@pfeifer.com docstring relicensing Joseph Myers joseph@codesourcery.com -predict.def Jan Hubicka jh@suse.cz +predict.def Jan Hubicka hubicka@ucw.cz contrib/regression Geoff Keating geoffk@geoffk.org -gcov Jan Hubicka jh@suse.cz +gcov Jan Hubicka hubicka@ucw.cz gcov Nathan Sidwell nathan@codesourcery.com option handling Neil Booth neil@daikokuya.co.uk option handling Joseph Myers joseph@codesourcery.com @@ -240,7 +240,7 @@ code sinking Daniel Berlin dberlin@dberlin.org tree browser/unparser Sebastian Pop sebastian.pop@amd.com scev, data dependence Daniel Berlin dberlin@dberlin.org scev, data dependence Sebastian Pop sebastian.pop@amd.com -profile feedback Jan Hubicka jh@suse.cz +profile feedback Jan Hubicka hubicka@ucw.cz type-safe vectors Nathan Sidwell nathan@codesourcery.com alias analysis Daniel Berlin dberlin@dberlin.org reload Ulrich Weigand uweigand@de.ibm.com @@ -256,6 +256,7 @@ testsuite Mike Stump mikestump@comcast.net testsuite Janis Johnson janisjo@codesourcery.com register allocation Vladimir Makarov vmakarov@redhat.com gdbhooks.py David Malcolm dmalcolm@redhat.com +SLSR Bill Schmidt wschmidt@linux.vnet.ibm.com Note that individuals who maintain parts of the compiler need approval to check in changes outside of the parts of the compiler they maintain. diff --git a/config/ChangeLog b/config/ChangeLog index 313572db18a..7d000625c76 100644 --- a/config/ChangeLog +++ b/config/ChangeLog @@ -1,7 +1,21 @@ +2013-11-29 Marek Polacek <polacek@redhat.com> + + * bootstrap-ubsan.mk (POSTSTAGE1_LDFLAGS): Remove -lpthread -ldl. + Add -B$$r/prev-$(TARGET_SUBDIR)/libsanitizer/. + +2013-11-29 H.J. Lu <hongjiu.lu@intel.com> + + * bootstrap-asan.mk (POSTSTAGE1_LDFLAGS): Add + -B$$r/prev-$(TARGET_SUBDIR)/libsanitizer/. + 2013-11-19 Marek Polacek <polacek@redhat.com> * bootstrap-ubsan.mk (POSTSTAGE1_LDFLAGS): Add -ldl. +2013-11-18 Jan Hubicka <jh@suse.cz> + + * bootstrap-lto.mk: Use -ffat-lto-objects. + 2013-11-15 Andreas Schwab <schwab@linux-m68k.org> * picflag.m4 (m68k-*-*): Use default PIC flag. @@ -26,6 +40,10 @@ * bootstrap-asan.mk (POSTSTAGE1_LDFLAGS): Add -B$$r/prev-$(TARGET_SUBDIR)/libsanitizer/asan/. +2013-01-23 Shenghou Ma <minux.ma@gmail.com> + + * isl.m4: don't echo $CFLAGS for ISL_CHECK_VERSION. + 2013-01-15 Richard Biener <rguenther@suse.de> PR other/55973 diff --git a/config/bootstrap-asan.mk b/config/bootstrap-asan.mk index e3f34f5ad49..fbef02125dc 100644 --- a/config/bootstrap-asan.mk +++ b/config/bootstrap-asan.mk @@ -3,5 +3,6 @@ STAGE2_CFLAGS += -fsanitize=address STAGE3_CFLAGS += -fsanitize=address POSTSTAGE1_LDFLAGS += -fsanitize=address -static-libasan \ + -B$$r/prev-$(TARGET_SUBDIR)/libsanitizer/ \ -B$$r/prev-$(TARGET_SUBDIR)/libsanitizer/asan/ \ -B$$r/prev-$(TARGET_SUBDIR)/libsanitizer/asan/.libs diff --git a/config/bootstrap-ubsan.mk b/config/bootstrap-ubsan.mk index 0cd8b172b0f..d2615e8f807 100644 --- a/config/bootstrap-ubsan.mk +++ b/config/bootstrap-ubsan.mk @@ -2,6 +2,7 @@ STAGE2_CFLAGS += -fsanitize=undefined STAGE3_CFLAGS += -fsanitize=undefined -POSTSTAGE1_LDFLAGS += -fsanitize=undefined -static-libubsan -lpthread -ldl \ +POSTSTAGE1_LDFLAGS += -fsanitize=undefined -static-libubsan \ + -B$$r/prev-$(TARGET_SUBDIR)/libsanitizer/ \ -B$$r/prev-$(TARGET_SUBDIR)/libsanitizer/ubsan/ \ -B$$r/prev-$(TARGET_SUBDIR)/libsanitizer/ubsan/.libs diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 76769b25a05..92a8651c562 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,1864 @@ +2013-12-04 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/59355 + * ipa-devirt.c (gate_ipa_devirt): Return false if + !flag_devirtualize. + * opts.c (common_handle_option): Fix comment spelling. + +2013-12-04 Yufeng Zhang <yufeng.zhang@arm.com> + + * gimple-ssa-strength-reduction.c: Include tree-affine.h. + (name_expansions): New static variable. + (alt_base_map): Ditto. + (get_alternative_base): New function. + (find_basis_for_candidate): For CAND_REF, optionally call + find_basis_for_base_expr with the returned value from + get_alternative_base. + (record_potential_basis): Add new parameter 'base' of type 'tree'; + add an assertion of non-NULL base; use base to set node->base_expr. + (alloc_cand_and_find_basis): Update; call record_potential_basis + for CAND_REF with the returned value from get_alternative_base. + (replace_refs): Dump details on the replacing. + (execute_strength_reduction): Call pointer_map_create for + alt_base_map; call free_affine_expand_cache with &name_expansions. + +2013-12-03 Wei Mi <wmi@google.com> + + PR rtl-optimization/59020 + * sched-deps.c (try_group_insn): Move it from haifa-sched.c to here. + (sched_analyze_insn): Call try_group_insn. + (sched_analyze): Cleanup SCHED_GROUP_P before start the analysis. + * haifa-sched.c (try_group_insn): Moved to sched-deps.c. + (group_insns_for_macro_fusion): Removed. + (sched_init): Remove calling group_insns_for_macro_fusion. + +2013-12-03 Peter Bergner <bergner@vnet.ibm.com> + + * config/rs6000/htmintrin.h (_TEXASR_INSTRUCTION_FETCH_CONFLICT): Fix + typo in macro name. + (_TEXASRU_INSTRUCTION_FETCH_CONFLICT): Likewise. + +2013-12-03 Vladimir Makarov <vmakarov@redhat.com> + + * config/aarch64/aarch64.c (aarch64_frame_pointer_required): Check + LR_REGNUM. + (aarch64_can_eliminate): Don't check elimination source when + frame_pointer_required is false. + +2013-12-03 Senthil Kumar Selvaraj <senthil_kumar.selvaraj@atmel.com> + + * config/avr/avr.c (avr_option_override): Warn if asked to generate + position independent code. + * config/avr/avr.h: Modify LINK_SPEC to reject -shared. + +2013-12-03 H.J. Lu <hongjiu.lu@intel.com> + + PR target/59363 + * config/i386/i386.c (emit_memset): Adjust destination address + after gen_strset. + (expand_setmem_epilogue): Likewise. + +2013-12-03 Marek Polacek <polacek@redhat.com> + + PR middle-end/56344 + * calls.c (expand_call): Disallow passing huge arguments + by value. + +2013-12-03 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/59362 + * tree-object-size.c (object_sizes): Change into array of + vec<unsigned HOST_WIDE_INT>. + (compute_builtin_object_size): Check computed bitmap for + non-NULL instead of object_sizes. Call safe_grow on object_sizes + vector if new SSA_NAMEs appeared. + (init_object_sizes): Check computed bitmap for non-NULL. + Call safe_grow on object_sizes elements instead of initializing + it with XNEWVEC. + (fini_object_sizes): Call release on object_sizes elements, don't + set it to NULL. + + PR middle-end/59011 + * gimplify.c (nonlocal_vla_vars): New variable. + (gimplify_var_or_parm_decl): Put VAR_DECLs for VLAs into + nonlocal_vla_vars chain. + (gimplify_body): Call declare_vars on nonlocal_vla_vars chain + if outer_bind has DECL_INITIAL (current_function_decl) block. + + PR target/58864 + * dojump.c (save_pending_stack_adjust, restore_pending_stack_adjust): + New functions. + * expr.h (struct saved_pending_stack_adjust): New type. + (save_pending_stack_adjust, restore_pending_stack_adjust): New + prototypes. + * optabs.c (emit_conditional_move): Call save_pending_stack_adjust + and get_last_insn before do_pending_stack_adjust, call + restore_pending_stack_adjust after delete_insns_since. + * expr.c (expand_expr_real_2): Don't call do_pending_stack_adjust + before calling emit_conditional_move. + * expmed.c (expand_sdiv_pow2): Likewise. + * calls.c (expand_call): Use {save,restore}_pending_stack_adjust. + +2013-12-02 Jeff Law <law@redhat.com> + + PR tree-optimization/59322 + * tree-ssa-threadedge.c (create_edge_and_update_destination_phis): + Remove code which copied jump threading paths. + +2013-12-02 Sriraman Tallam <tmsriram@google.com> + + PR target/58944 + * config/i386/i386.opt (ix86_arch_string): Mark this variable + for saving in cl_target_option. + (ix86_tune_string): Ditto. + (ix86_cmodel): Ditto. + (ix86_abi): Ditto. + (ix86_asm_dialect): Ditto. + (ix86_branch_cost): Ditto. + (ix86_dump_tunes): Ditto. + (ix86_force_align_arg_pointer): Ditto. + (ix86_force_drap): Ditto. + (ix86_incoming_stack_boundary_arg): Ditto. + (ix86_pmode): Ditto. + (ix86_preferred_stack_boundary_arg): Ditto. + (ix86_recip_name): Ditto. + (ix86_regparm): Ditto. + (ix86_section_threshold): Ditto. + (ix86_sse2avx): Ditto. + (ix86_stack_protector_guard): Ditto. + (ix86_stringop_alg): Ditto. + (ix86_tls_dialect): Ditto. + (ix86_tune_ctrl_string): Ditto. + (ix86_tune_memcpy_strategy): Ditto. + (ix86_tune_memset_strategy): Ditto. + (ix86_tune_no_default): Ditto. + (ix86_veclibabi_type): Ditto. + * config/i386/i386.c + (function_specific_save): Save the above variables + in gcc_options to cl_target_option. + (function_specific_restore): Do the reverse done in + function_specific_save. + (ix86_valid_target_attribute_tree): Change ix86_arch_string + and ix86_tune_string to use the opts structure. + (ix86_option_override_internal):Change + ix86_incoming_stack_boundary_arg to + opts->x_ix86_incoming_stack_boundary_arg + +2013-12-02 Joern Rennecke <joern.rennecke@embecosm.com> + + * config/epiphany/epiphany.h: Wrap rtl_opt_pass declarations + in #ifndef IN_LIBGCC2 / #endif. + +2013-12-02 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/59358 + * tree-vrp.c (union_ranges): To check for the partially + overlapping ranges or adjacent ranges, also compare *vr0max + with vr1max. + +2013-12-02 Sterling Augustine <saugustine@google.com> + + * dwarf2out.c (output_pubnames): Use comp_unit_die ()->die_offset + when there isn't a skeleton die. + +2013-12-02 Marek Polacek <polacek@redhat.com> + + PR sanitizer/59353 + * doc/invoke.texi: Document -fsanitize=return. + +2013-12-02 Tobias Burnus <burnus@net-b.de> + Manuel López-Ibáñez <manu@gcc.gnu.org> + + PR middle-end/59257 + * doc/invoke.texi: Add missing @opindex. + (-fsanitize=): Use @gcctabopt instead of @itemize. + +2013-12-02 Bernd Edlinger <bernd.edlinger@hotmail.de> + + Fix C++0x memory model for unaligned fields in packed, aligned(4) + structures with -fno-strict-volatile-bitfields on STRICT_ALIGNMENT + 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 + * tree-ssa-loop-niter.c (chain_of_csts_start): Properly match + code in get_val_for. + (get_val_for): Use gcc_checking_asserts. + +2013-12-02 Richard Biener <rguenther@suse.de> + + PR middle-end/59199 + * tree-ssa-operands.c (opf_implicit): Remove. + (opf_address_taken): New flag. + (get_expr_operands): Remove early out, pass down + opf_address_taken for ADDR_EXPRs, add a use operand only + for non-opf_address_taken bases. + (get_indirect_ref_operands): Rename to ... + (get_mem_ref_operands): ... this. + (get_asm_expr_operands): Rename to ... + (get_asm_stmt_operands): ... this. + +2013-12-02 Yuri Rumyantsev <ysrumyan@gmail.com> + + * ipa-inline.c (check_callers): Add missed pointer de-reference. + +2013-12-02 Eric Botcazou <ebotcazou@adacore.com> + + PR tree-optimization/59356 + * tree-dfa.h (get_addr_base_and_unit_offset_1) <case ARRAY_REF>: Do the + offset computation using the precision of the index type. + +2013-12-02 Yvan Roux <yvan.roux@linaro.org> + + PR target/58785 + * config/arm/arm.c (arm_preferred_reload_class): Only return LO_REGS + when rclass is GENERAL_REGS. + +2013-12-02 Ganesh Gopalasubramanian <Ganesh.Gopalasubramanian@amd.com> + + * loop-unroll.c (decide_unroll_constant_iterations): Check macro + TARGET_LOOP_UNROLL_ADJUST while deciding unroll factor. + +2013-12-01 Eric Botcazou <ebotcazou@adacore.com> + + * config/i386/winnt.c (i386_pe_asm_named_section): Be prepared for an + identifier node. + +2013-12-01 Bernd Edlinger <bernd.edlinger@hotmail.de> + + * expr.c (emit_group_store): Fix off-by-one BITFIELD_END argument. + +2013-11-30 Paulo Matos <pmatos@broadcom.com> + Eric Botcazou <ebotcazou@adacore.com> + + * combine.c (reg_nonzero_bits_for_combine): Apply mask transformation + as applied to nonzero_sign_valid when last_set_mode has less precision + than mode. + +2013-11-30 Tobias Burnus <burnus@net-b.de> + + PR sanitizer/59275 + * doc/invoke.texi (-fsanitize=address,leak): Mention the associated + environment variable and link to a list with flags. + (-fsanitize=thread): Ditto and update link. + +2013-11-29 Vladimir Makarov <vmakarov@redhat.com> + + PR rtl-optimization/59340 + * lra.c (check_rtl): Use recog_memoized instead of insn_invalid_p. + + Revert + 2013-11-20 Robert Suchanek <Robert.Suchanek@imgtec.com> + + * lra.c (lra): Set lra_in_progress before check_rtl call. + * recog.c (insn_invalid_p): Add !lra_in_progress to prevent + adding clobber regs when LRA is running. + +2013-11-29 Kyrylo Tkachov <kyrylo.tkachov@arm.com> + + PR target/59289 + * config/arm/arm.c (cortexa15_extra_costs): Adjust costs. + +2013-11-29 Richard Biener <rguenther@suse.de> + + PR middle-end/59208 + * tree-ssa-operands.h (fini_ssa_operands, verify_ssa_operands, + free_stmt_operands, update_stmt_operands): Add struct function + argument. + * tree-ssa-operands.c: Remove uses of cfun, propagate struct + function argument from fini_ssa_operands, verify_ssa_operands, + free_stmt_operands and update_stmt_operands everywhere. + * tree-ssanames.h (release_ssa_name_fn): New. + (release_ssa_name): Inline wrapper around release_ssa_name_fn. + * tree-ssanames.c (release_ssa_name): Rename to ... + (release_ssa_name_fn): ... this and add struct function argument. + * gimple-ssa.h (update_stmt, update_stmt_if_modified): Adjust. + (update_stmt_fn): New function. + * tree-cfg.c (move_block_to_fn): Adjust. + * tree-if-conv.c (free_bb_predicate): Likewise. + * tree-ssa.c (verify_ssa): Likewise. + (delete_tree_ssa): Likewise. + * gimple-pretty-print.c (dump_gimple_mem_ops): Remove guard. + * cgraph.c (cgraph_redirect_edge_call_stmt_to_callee): Call + update_stmt_fn instead of update_stmt. + +2013-11-29 Yvan Roux <yvan.roux@linaro.org> + + * config/arm/arm.h (THUMB_SECONDARY_INPUT_RELOAD_CLASS): Return NO_REGS + for LRA. + +2013-11-29 Yvan Roux <yvan.roux@linaro.org> + + * config/arm/arm.md (store_minmaxsi): Use only when + optimize_function_for_size_p. + +2013-11-29 Jakub Jelinek <jakub@redhat.com> + Yury Gribov <y.gribov@samsung.com> + + PR sanitizer/59063 + * config/gnu-user.h: Removed old code for setting up sanitizer + libs. + * gcc.c: Using libsanitizer spec instead of explicit libs. + +2013-11-29 Ilya Enkovich <ilya.enkovich@intel.com> + + Reverted: + 2013-11-20 Ilya Enkovich <ilya.enkovich@intel.com> + * cgraph.h (varpool_node): Add need_bounds_init field. + * lto-cgraph.c (lto_output_varpool_node): Output + need_bounds_init value. + (input_varpool_node): Read need_bounds_init value. + * varpool.c (dump_varpool_node): Dump need_bounds_init field. + + Reverted: + 2013-11-20 Ilya Enkovich <ilya.enkovich@intel.com> + * dbxout.c (dbxout_type): Ignore POINTER_BOUNDS_TYPE. + * dwarf2out.c (gen_subprogram_die): Ignore bound args. + (gen_type_die_with_usage): Skip pointer bounds. + (dwarf2out_global_decl): Likewise. + + Reverted: + 2013-11-18 Ilya Enkovich <ilya.enkovich@intel.com> + * builtin-types.def (BT_FN_PTR_CONST_PTR_VAR): New. + * chkp-builtins.def (BUILT_IN_CHKP_BIND_BOUNDS): New. + * cfgexpand.c (expand_call_stmt): Expand BUILT_IN_CHKP_BIND_BOUNDS. + * gimple.c (gimple_call_get_nobnd_arg_index): Remove. + * gimple.h (gf_mask): Add GF_CALL_WITH_BOUNDS. + (gimple_call_with_bounds_p): New. + (gimple_call_set_with_bounds): New. + (gimple_call_num_nobnd_args): Remove. + (gimple_call_nobnd_arg): Remove. + * tree.h (CALL_WITH_BOUNDS_P): New. + * rtl.h (CALL_EXPR_WITH_BOUNDS_P): New. + + Reverted: + 2013-11-08 Ilya Enkovich <ilya.enkovich@intel.com> + * common.opt (fcheck-pointer-bounds): Move to ... + * c-family/c.opt: ... here. + * langhooks-def.h (LANG_HOOKS_CHKP_SUPPORTED): Remove. + (LANG_HOOKS_INITIALIZER): Remove LANG_HOOKS_CHKP_SUPPORTED. + * langhooks.h (lang_hooks): Remove chkp_supported field. + * toplev.c (process_options): Remove chkp_supported check. + + Reverted: + 2013-10-30 Ilya Enkovich <ilya.enkovich@intel.com> + * tree-core.h (tree_index): Add TI_POINTER_BOUNDS_TYPE. + * tree.h (POINTER_BOUNDS_P): New. + (BOUNDED_TYPE_P): New. + (BOUNDED_P): New. + (pointer_bounds_type_node): New. + * tree.c (build_common_tree_nodes): Initialize + pointer_bounds_type_node. + * gimple.h (gimple_call_get_nobnd_arg_index): New. + (gimple_call_num_nobnd_args): New. + (gimple_call_nobnd_arg): New. + (gimple_return_retbnd): New. + (gimple_return_set_retbnd): New + * gimple.c (gimple_build_return): Increase number of ops + for return statement. + (gimple_call_get_nobnd_arg_index): New. + * gimple-pretty-print.c (dump_gimple_return): Print second op. + + Reverted: + 2013-10-30 Ilya Enkovich <ilya.enkovich@intel.com> + * ipa.c (cgraph_build_static_cdtor_1): Support contructors + with "chkp ctor" and "bnd_legacy" attributes. + * gimplify.c (gimplify_init_constructor): Avoid infinite + loop during gimplification of bounds initializer. + + Reverted: + 2013-10-30 Ilya Enkovich <ilya.enkovich@intel.com> + * c-family/c-common.c (handle_bnd_variable_size_attribute): New. + (handle_bnd_legacy): New. + (c_common_attribute_table): Add bnd_variable_size and bnd_legacy. + * doc/extend.texi: Document bnd_variable_size and bnd_legacy + attributes. + + Reverted: + 2013-10-29 Ilya Enkovich <ilya.enkovich@intel.com> + * builtin-types.def (BT_FN_VOID_CONST_PTR): New. + (BT_FN_PTR_CONST_PTR): New. + (BT_FN_CONST_PTR_CONST_PTR): New. + (BT_FN_PTR_CONST_PTR_SIZE): New. + (BT_FN_PTR_CONST_PTR_CONST_PTR): New. + (BT_FN_VOID_PTRPTR_CONST_PTR): New. + (BT_FN_VOID_CONST_PTR_SIZE): New. + (BT_FN_PTR_CONST_PTR_CONST_PTR_SIZE): New. + * chkp-builtins.def: New. + * builtins.def: include chkp-builtins.def. + (DEF_CHKP_BUILTIN): New. + * builtins.c (expand_builtin): Support BUILT_IN_CHKP_INIT_PTR_BOUNDS, + BUILT_IN_CHKP_NULL_PTR_BOUNDS, BUILT_IN_CHKP_COPY_PTR_BOUNDS, + BUILT_IN_CHKP_CHECK_PTR_LBOUNDS, BUILT_IN_CHKP_CHECK_PTR_UBOUNDS, + BUILT_IN_CHKP_CHECK_PTR_BOUNDS, BUILT_IN_CHKP_SET_PTR_BOUNDS, + BUILT_IN_CHKP_NARROW_PTR_BOUNDS, BUILT_IN_CHKP_STORE_PTR_BOUNDS, + BUILT_IN_CHKP_GET_PTR_LBOUND, BUILT_IN_CHKP_GET_PTR_UBOUND, + BUILT_IN_CHKP_BNDMK, BUILT_IN_CHKP_BNDSTX, BUILT_IN_CHKP_BNDCL, + BUILT_IN_CHKP_BNDCU, BUILT_IN_CHKP_BNDLDX, BUILT_IN_CHKP_BNDRET, + BUILT_IN_CHKP_INTERSECT, BUILT_IN_CHKP_ARG_BND, BUILT_IN_CHKP_NARROW, + BUILT_IN_CHKP_EXTRACT_LOWER, BUILT_IN_CHKP_EXTRACT_UPPER. + * common.opt (fcheck-pointer-bounds): New. + * toplev.c (process_options): Check Pointer Bounds Checker is + supported. + * doc/extend.texi: Document Pointer Bounds Checker built-in functions. + + Reverted: + 2013-10-30 Ilya Enkovich <ilya.enkovich@intel.com> + * target.def (builtin_chkp_function): New. + (chkp_bound_type): New. + (chkp_bound_mode): New. + (fn_abi_va_list_bounds_size): New. + (load_bounds_for_arg): New. + (store_bounds_for_arg): New. + * targhooks.h (default_load_bounds_for_arg): New. + (default_store_bounds_for_arg): New. + (default_fn_abi_va_list_bounds_size): New. + (default_chkp_bound_type): New. + (default_chkp_bound_mode): New. + (default_builtin_chkp_function): New. + * targhooks.c (default_load_bounds_for_arg): New. + (default_store_bounds_for_arg): New. + (default_fn_abi_va_list_bounds_size): New. + (default_chkp_bound_type): New. + (default_chkp_bound_mode); New. + (default_builtin_chkp_function): New. + * doc/tm.texi.in (TARGET_FN_ABI_VA_LIST_BOUNDS_SIZE): New. + (TARGET_LOAD_BOUNDS_FOR_ARG): New. + (TARGET_STORE_BOUNDS_FOR_ARG): New. + (TARGET_BUILTIN_CHKP_FUNCTION): New. + (TARGET_CHKP_BOUND_TYPE): New. + (TARGET_CHKP_BOUND_MODE): New. + * doc/tm.texi: Regenerated. + * langhooks.h (lang_hooks): Add chkp_supported field. + * langhooks-def.h (LANG_HOOKS_CHKP_SUPPORTED): New. + (LANG_HOOKS_INITIALIZER); Add LANG_HOOKS_CHKP_SUPPORTED. + + Reverted: + 2013-10-24 Ilya Enkovich <ilya.enkovich@intel.com> + * config/i386/constraints.md (B): New. + (Ti): New. + (Tb): New. + * config/i386/i386-c.c (ix86_target_macros_internal): Add __MPX__. + * config/i386/i386-modes.def (BND32): New. + (BND64): New. + * config/i386/i386-protos.h (ix86_bnd_prefixed_insn_p): New. + * config/i386/i386.c (isa_opts): Add mmpx. + (regclass_map): Add bound registers. + (dbx_register_map): Likewise. + (dbx64_register_map): Likewise. + (svr4_dbx_register_map): Likewise. + (PTA_MPX): New. + (ix86_option_override_internal): Support MPX ISA. + (ix86_conditional_register_usage): Support bound registers. + (print_reg): Likewise. + (ix86_code_end): Add MPX bnd prefix. + (output_set_got): Likewise. + (ix86_output_call_insn): Likewise. + (ix86_print_operand): Add '!' (MPX bnd) print prefix support. + (ix86_print_operand_punct_valid_p): Likewise. + (ix86_print_operand_address): Support UNSPEC_BNDMK_ADDR and + UNSPEC_BNDMK_ADDR. + (ix86_class_likely_spilled_p): Add bound regs support. + (ix86_hard_regno_mode_ok): Likewise. + (x86_order_regs_for_local_alloc): Likewise. + (ix86_bnd_prefixed_insn_p): New. + * config/i386/i386.h (FIRST_PSEUDO_REGISTER): Fix to new value. + (FIXED_REGISTERS): Add bound registers. + (CALL_USED_REGISTERS): Likewise. + (REG_ALLOC_ORDER): Likewise. + (HARD_REGNO_NREGS): Likewise. + (TARGET_MPX): New. + (VALID_BND_REG_MODE): New. + (FIRST_BND_REG): New. + (LAST_BND_REG): New. + (reg_class): Add BND_REGS. + (REG_CLASS_NAMES): Likewise. + (REG_CLASS_CONTENTS): Likewise. + (BND_REGNO_P): New. + (ANY_BND_REG_P): New. + (BNDmode): New. + (HI_REGISTER_NAMES): Add bound registers. + * config/i386/i386.md (UNSPEC_BNDMK): New. + (UNSPEC_BNDMK_ADDR): New. + (UNSPEC_BNDSTX): New. + (UNSPEC_BNDLDX): New. + (UNSPEC_BNDLDX_ADDR): New. + (UNSPEC_BNDCL): New. + (UNSPEC_BNDCU): New. + (UNSPEC_BNDCN): New. + (UNSPEC_MPX_FENCE): New. + (BND0_REG): New. + (BND1_REG): New. + (type): Add mpxmov, mpxmk, mpxchk, mpxld, mpxst. + (length_immediate): Likewise. + (prefix_0f): Likewise. + (memory): Likewise. + (prefix_rep): Check for bnd prefix. + (length_nobnd): New. + (length): Use length_nobnd if specified. + (BND): New. + (bnd_ptr): New. + (BNDCHECK): New. + (bndcheck): New. + (*jcc_1): Add bnd prefix and rename length attr to length_nobnd. + (*jcc_2): Likewise. + (jump): Likewise. + (simple_return_internal): Likewise. + (simple_return_pop_internal): Likewise. + (*indirect_jump): Add MPX bnd prefix. + (*tablejump_1): Likewise. + (simple_return_internal_long): Likewise. + (simple_return_indirect_internal): Likewise. + (<mode>_mk): New. + (*<mode>_mk): New. + (mov<mode>): New. + (*mov<mode>_internal_mpx): New. + (<mode>_<bndcheck>): New. + (*<mode>_<bndcheck>): New. + (<mode>_ldx): New. + (*<mode>_ldx): New. + (<mode>_stx): New. + (*<mode>_stx): New. + * config/i386/predicates.md (lea_address_operand): Rename to... + (address_no_seg_operand): ... this. + (address_mpx_no_base_operand): New. + (address_mpx_no_index_operand): New. + (bnd_mem_operator): New. + * config/i386/i386.opt (mmpx): New. + * doc/invoke.texi: Add documentation for the flags -mmpx, -mno-mpx. + * doc/rtl.texi Add documentation for BND32mode and BND64mode. + + Reverted: + 2013-10-24 Ilya Enkovich <ilya.enkovich@intel.com> + * mode-classes.def (MODE_POINTER_BOUNDS): New. + * tree.def (POINTER_BOUNDS_TYPE): New. + * genmodes.c (complete_mode): Support MODE_POINTER_BOUNDS. + (POINTER_BOUNDS_MODE): New. + (make_pointer_bounds_mode): New. + * machmode.h (POINTER_BOUNDS_MODE_P): New. + * stor-layout.c (int_mode_for_mode): Support MODE_POINTER_BOUNDS. + (layout_type): Support POINTER_BOUNDS_TYPE. + * tree-pretty-print.c (dump_generic_node): Support POINTER_BOUNDS_TYPE. + * tree.c (build_int_cst_wide): Support POINTER_BOUNDS_TYPE. + (type_contains_placeholder_1): Likewise. + * tree.h (POINTER_BOUNDS_TYPE_P): New. + * varasm.c (output_constant): Support POINTER_BOUNDS_TYPE. + * doc/rtl.texi (MODE_POINTER_BOUNDS): New. + +2013-11-29 Richard Biener <rguenther@suse.de> + + PR middle-end/59338 + * tree-cfg.c (verify_expr): Restrict bounds verification of + BIT_FIELD_REF arguments to non-aggregate typed base objects. + +2013-11-29 Richard Biener <rguenther@suse.de> + + PR tree-optimization/59334 + * tree-ssa-dce.c (eliminate_unnecessary_stmts): Fix bug + in previous commit. + +2013-11-29 Jakub Jelinek <jakub@redhat.com> + Richard Biener <rguenther@suse.de> + + PR lto/59326 + * omp-low.c (simd_clone_create): Return NULL if for definition + !cgraph_function_with_gimple_body_p (old_node). Call cgraph_get_body + before calling cgraph_function_versioning. + (expand_simd_clones): Look for "omp declare simd" attribute first. + Don't check targetm.simd_clone.compute_vecsize_and_simdlen here. + Punt if node->global.inlined_to. + (pass_omp_simd_clone::gate): Also enable if in_lto_p && !flag_wpa. + Disable pass if targetm.simd_clone.compute_vecsize_and_simdlen is NULL. + * lto-streamer-out.c (hash_tree): Handle OMP_CLAUSE. + +2013-11-29 Jakub Jelinek <jakub@redhat.com> + + PR lto/59326 + * tree-core.h (enum omp_clause_schedule_kind): Add + OMP_CLAUSE_SCHEDULE_LAST. + (enum omp_clause_default_kind): Add OMP_CLAUSE_DEFAULT_LAST. + (enum omp_clause_depend_kind): Add OMP_CLAUSE_DEPEND_LAST. + (enum omp_clause_map_kind): Add OMP_CLAUSE_MAP_LAST. + (enum omp_clause_proc_bind_kind): Add OMP_CLAUSE_PROC_BIND_LAST. + * lto-streamer-out.c (lto_is_streamable): Allow streaming + OMP_CLAUSE. + (DFS_write_tree_body): Handle OMP_CLAUSE. + * tree-streamer-out.c (pack_ts_omp_clause_value_fields): New + function. + (streamer_pack_tree_bitfields): Call it for OMP_CLAUSE. + (write_ts_omp_clause_tree_pointers): New function. + (streamer_write_tree_body): Call it for OMP_CLAUSE. + (streamer_write_tree_header): For OMP_CLAUSE stream OMP_CLAUSE_CODE. + * tree-streamer-in.c (unpack_ts_omp_clause_value_fields): New + function. + (unpack_value_fields): Call it for OMP_CLAUSE. + (streamer_alloc_tree): Handle OMP_CLAUSE. + (lto_input_ts_omp_clause_tree_pointers): New function. + (streamer_read_tree_body): Call it for OMP_CLAUSE. + +2013-11-29 Joseph Myers <joseph@codesourcery.com> + + * doc/implement-c.texi: Document C11 implementation-defined + behavior. Refer to -ffp-contract=fast for contraction behavior. + * doc/invoke.texi (-std=c99, std=c11): Update description of + completeness. + (-std=gnu99): Don't mention as future default. + (-std=gnu11): Mention as intended future default. + * doc/standards.texi: Update descriptions of C99 and C11 support. + Limit statement about C99 facilities for freestanding + implementations to some platforms only. + +2013-11-28 Jakub Jelinek <jakub@redhat.com> + + PR middle-end/59327 + * cfgexpand.c (expand_used_vars): Avoid warning on 32-bit + HWI hosts. + +2013-11-28 Vladimir Makarov <vmakarov@redhat.com> + + PR target/57293 + * ira.h (ira_setup_eliminable_regset): Remove parameter. + * ira.c (ira_setup_eliminable_regset): Ditto. Add + SUPPORTS_STACK_ALIGNMENT for crtl->stack_realign_needed. + Don't call lra_init_elimination. + (ira): Call ira_setup_eliminable_regset without arguments. + * loop-invariant.c (calculate_loop_reg_pressure): Remove argument + from ira_setup_eliminable_regset call. + * gcse.c (calculate_bb_reg_pressure): Ditto. + * haifa-sched.c (sched_init): Ditto. + * lra.h (lra_init_elimination): Remove the prototype. + * lra-int.h (lra_insn_recog_data): New member sp_offset. Move + used_insn_alternative upper. + (lra_eliminate_regs_1): Add one more parameter. + (lra-eliminate): Ditto. + * lra.c (lra_invalidate_insn_data): Set sp_offset. + (setup_sp_offset): New. + (lra_process_new_insns): Call setup_sp_offset. + (lra): Add argument to lra_eliminate calls. + * lra-constraints.c (get_equiv_substitution): Rename to get_equiv. + (get_equiv_with_elimination): New. + (process_addr_reg): Call get_equiv_with_elimination instead of + get_equiv_substitution. + (equiv_address_substitution): Ditto. + (loc_equivalence_change_p): Ditto. + (loc_equivalence_callback, lra_constraints): Ditto. + (curr_insn_transform): Ditto. Print the sp offset + (process_alt_operands): Prevent stack pointer reloads. + (lra_constraints): Remove one argument from lra_eliminate call. + Move it up. Mark used hard regs bfore it. Use + get_equiv_with_elimination instead of get_equiv_substitution. + * lra-eliminations.c (lra_eliminate_regs_1): Add parameter and + assert for param values combination. Use sp offset. Add argument + to lra_eliminate_regs_1 calls. + (lra_eliminate_regs): Add argument to lra_eliminate_regs_1 call. + (curr_sp_change): New static var. + (mark_not_eliminable): Add parameter. Update curr_sp_change. + Don't prevent elimination to sp if we can calculate its change. + Pass the argument to mark_not_eliminable calls. + (eliminate_regs_in_insn): Add a parameter. Use sp offset. Add + argument to lra_eliminate_regs_1 call. + (update_reg_eliminate): Move calculation of hard regs for spill + lower. Switch off lra_in_progress temporarily to generate regs + involved into elimination. + (lra_init_elimination): Rename to init_elimination. Make it + static. Set up insn sp offset, check the offsets at the end of + BBs. + (process_insn_for_elimination): Add parameter. Pass its value to + eliminate_regs_in_insn. + (lra_eliminate): : Add parameter. Pass its value to + process_insn_for_elimination. Add assert for param values + combination. Call init_elimination. Don't update offsets in + equivalence substitutions. + * lra-spills.c (assign_mem_slot): Don't call lra_eliminate_regs_1 + for created stack slot. + (remove_pseudos): Call lra_eliminate_regs_1 before changing memory + onto stack slot. + +2013-11-28 Kyrylo Tkachov <kyrylo.tkachov@arm.com> + + * config/arm/iterators.md (vrint_conds): New int attribute. + * config/arm/vfp.md (<vrint_pattern><SDF:mode>2): Set conds attribute. + (smax<mode>3): Likewise. + (smin<mode>3): Likewise. + +2013-11-28 Richard Sandiford <rdsandiford@googlemail.com> + + * tree-core.h (tree_base): Document use of static_flag for SSA_NAME. + * tree.h (SSA_NAME_ANTI_RANGE_P, SSA_NAME_RANGE_TYPE): New macros. + * tree-ssanames.h (set_range_info): Add range_type argument. + (duplicate_ssa_name_range_info): Likewise. + * tree-ssanames.c (set_range_info): Take the range type as argument + and store it in SSA_NAME_ANTI_RANGE_P. + (duplicate_ssa_name_range_info): Likewise. + (get_range_info): Use SSA_NAME_ANTI_RANGE_P. + (set_nonzero_bits): Update call to set_range_info. + (duplicate_ssa_name_fn): Update call to duplicate_ssa_name_range_info. + * tree-ssa-copy.c (fini_copy_prop): Likewise. + * tree-vrp.c (remove_range_assertions): Update call to set_range_info. + (vrp_finalize): Likewise, passing anti-ranges directly. + +2013-11-28 Richard Biener <rguenther@suse.de> + + PR tree-optimization/59330 + * tree-ssa-dce.c (eliminate_unnecessary_stmts): Simplify + and fix delayed marking of free calls not necessary. + +2013-11-28 Andrew MacLeod <amacleod@redhat.com> + + * tree-ssa-propagate.c (valid_gimple_call_p): Pass TREE_TYPE to + is_gimple_reg_type. + * ipa-prop.c (determine_known_aggregate_parts): Likewise. + +2013-11-28 Terry Guo <terry.guo@arm.com> + + * config/arm/arm.c (v7m_extra_costs): New table. + (arm_v7m_tune): Use it. + +2013-11-28 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + * config/sol2.h (TIME_LIBRARY): Define. + +2013-11-28 Richard Biener <rguenther@suse.de> + + PR lto/59323 + * lto-streamer-out.c (tree_is_indexable): TYPE_DECLs and + CONST_DECLs in function context are not indexable. + +2013-11-28 Chung-Ju Wu <jasonwucj@gmail.com> + + * config/nds32/nds32.c (nds32_rtx_costs): Adjust MULT cost if it is + not optimized for size. + +2013-11-28 Jakub Jelinek <jakub@redhat.com> + + * cfgexpand.c (struct stack_vars_data): Add asan_base and asan_alignb + fields. + (expand_stack_vars): For -fsanitize=address, use (and set initially) + data->asan_base as base for vars and update asan_alignb. + (expand_used_vars): Initialize data.asan_base and data.asan_alignb. + Pass them to asan_emit_stack_protection. + * asan.c (asan_detect_stack_use_after_return): New variable. + (asan_emit_stack_protection): Add pbase and alignb arguments. + Implement use after return sanitization. + * asan.h (asan_emit_stack_protection): Adjust prototype. + (ASAN_STACK_MAGIC_USE_AFTER_RET, ASAN_STACK_RETIRED_MAGIC): Define. + +2013-11-28 Sergey Ostanevich <sergos.gnu@gmail.com> + + * common.opt: Introduced a new option -fsimd-cost-model. + * doc/invoke.texi: Introduced a new openmp-simd warning and + a new -fsimd-cost-model option. + * tree-vectorizer.h (unlimited_cost_model): Interface updated + to rely on the particular loop info. + * tree-vect-data-refs.c (vect_peeling_hash_insert): Ditto. + (vect_peeling_hash_choose_best_peeling): Ditto. + (vect_enhance_data_refs_alignment): Ditto. + * tree-vect-slp.c (vect_slp_analyze_bb_1): Ditto. + * tree-vect-loop.c (vect_estimate_min_profitable_iters): Ditto + plus added openmp-simd warining. + +2013-11-27 H.J. Lu <hongjiu.lu@intel.com> + + PR rtl-optimization/59311 + * dwarf2cfi.c (dwf_regno): Assert reg isn't pseudo register. + * lra-spills.c (spill_pseudos): Handle REG_XXX notes. + +2013-11-27 Eric Botcazou <ebotcazou@adacore.com> + + * var-tracking.c (track_expr_p): Do not track declarations for parts + of tracked parameters. + (add_stores): Do not track values for tracked parameters passed in + multiple locations. + (vt_get_decl_and_offset): Handle PARALLEL. + (vt_add_function_parameter): Handle parameters with incoming PARALLEL. + +2013-11-27 Jeff Law <law@redhat.com> + + * tree-ssa-threadupdate.c (thread_through_all_blocks): Do not + clobber the loop structure thread_block was unsuccessful. If + thread_block was unsuccessful, cleanup appropriately. + +2013-11-27 Chen Liqin <liqin.gcc@gmail.com> + + * config/score/score.h (REG_CLASS_FROM_LETTER): Delete. + (score_char_to_class): Likewise. + +2013-11-27 Kenneth Zadeck <zadeck@naturalbridge.com> + + * fold-const.c (int_const_binop_1): Make INT_MIN % -1 return 0 with the + overflow bit set. + +2013-11-27 Richard Biener <rguenther@suse.de> + + PR middle-end/58723 + * cgraphbuild.c (build_cgraph_edges): Do not build edges + for internal calls. + (rebuild_cgraph_edges): Likewise. + * ipa-inline-analysis.c (estimate_function_body_sizes): + Skip internal calls. + * tree-inline.c (estimate_num_insns): Estimate size of internal + calls as 0. + (gimple_expand_calls_inline): Do not try inline-expanding + internal calls. + * lto-streamer-in.c (input_cfg): Stream loop safelen, + force_vect and simduid. + (input_struct_function_base): Stream has_force_vect_loops + and has_simduid_loops. + (input_function): Adjust. + * lto-streamer-out.c (output_cfg): Stream loop safelen, + force_vect and simduid. + (output_struct_function_base): Stream has_force_vect_loops + and has_simduid_loops. + +2013-11-27 Kai Tietz <ktietz@redhat.com> + + * config/i386/winnt.c (i386_pe_section_type_flags): Use const + pointer cast. + +2013-11-27 Kugan Vivekanandarajah <kuganv@linaro.org> + + * doc/tm.texi.in (TARGET_HAS_NO_HW_DIVIDE): Define. + * doc/tm.texi (TARGET_HAS_NO_HW_DIVIDE): Regenerate. + +2013-11-27 Marek Polacek <polacek@redhat.com> + + PR sanitizer/59306 + * ubsan.c (instrument_null): Use gimple_store_p/gimple_assign_load_p + instead of walk_gimple_op. + (ubsan_pass): Adjust. Call instrument_null only if SANITIZE_NULL. + +2013-11-27 Aldy Hernandez <aldyh@redhat.com> + Jakub Jelinek <jakub@redhat.com> + + * cgraph.h (enum cgraph_simd_clone_arg_type): New. + (struct cgraph_simd_clone_arg, struct cgraph_simd_clone): New. + (struct cgraph_node): Add simdclone and simd_clones fields. + * config/i386/i386.c (ix86_simd_clone_compute_vecsize_and_simdlen, + ix86_simd_clone_adjust, ix86_simd_clone_usable): New functions. + (TARGET_SIMD_CLONE_COMPUTE_VECSIZE_AND_SIMDLEN, + TARGET_SIMD_CLONE_ADJUST, TARGET_SIMD_CLONE_USABLE): Define. + * doc/tm.texi.in (TARGET_SIMD_CLONE_COMPUTE_VECSIZE_AND_SIMDLEN, + TARGET_SIMD_CLONE_ADJUST, TARGET_SIMD_CLONE_USABLE): Add. + * doc/tm.texi: Regenerated. + * ggc.h (ggc_alloc_cleared_simd_clone_stat): New function. + * ipa-cp.c (determine_versionability): Fail if "omp declare simd" + attribute is present. + * omp-low.c: Include pretty-print.h, ipa-prop.h and tree-eh.h. + (simd_clone_vector_of_formal_parm_types): New function. + (simd_clone_struct_alloc, simd_clone_struct_copy, + simd_clone_vector_of_formal_parm_types, simd_clone_clauses_extract, + simd_clone_compute_base_data_type, simd_clone_mangle, + simd_clone_create, simd_clone_adjust_return_type, + create_tmp_simd_array, simd_clone_adjust_argument_types, + simd_clone_init_simd_arrays): New functions. + (struct modify_stmt_info): New type. + (ipa_simd_modify_stmt_ops, ipa_simd_modify_function_body, + simd_clone_adjust, expand_simd_clones, ipa_omp_simd_clone): New + functions. + (pass_data_omp_simd_clone): New variable. + (pass_omp_simd_clone): New class. + (make_pass_omp_simd_clone): New function. + * passes.def (pass_omp_simd_clone): New. + * target.def (TARGET_SIMD_CLONE_COMPUTE_VECSIZE_AND_SIMDLEN, + TARGET_SIMD_CLONE_ADJUST, TARGET_SIMD_CLONE_USABLE): New target + hooks. + * target.h (struct cgraph_node, struct cgraph_simd_node): Declare. + * tree-core.h (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE): Document. + * tree.h (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE): Define. + * tree-pass.h (make_pass_omp_simd_clone): New prototype. + * tree-vect-data-refs.c: Include cgraph.h. + (vect_analyze_data_refs): Inline by hand find_data_references_in_loop + and find_data_references_in_bb, if find_data_references_in_stmt + fails, still allow calls to #pragma omp declare simd functions + in #pragma omp simd loops unless they contain data references among + the call arguments or in lhs. + * tree-vect-loop.c (vect_determine_vectorization_factor): Handle + calls with no lhs. + (vect_transform_loop): Allow NULL STMT_VINFO_VECTYPE for calls without + lhs. + * tree-vectorizer.h (enum stmt_vec_info_type): Add + call_simd_clone_vec_info_type. + (struct _stmt_vec_info): Add simd_clone_fndecl field. + (STMT_VINFO_SIMD_CLONE_FNDECL): Define. + * tree-vect-stmts.c: Include tree-ssa-loop.h, + tree-scalar-evolution.h and cgraph.h. + (vectorizable_call): Handle calls without lhs. Assert + !stmt_can_throw_internal instead of failing for it. Don't update + EH stuff. + (struct simd_call_arg_info): New. + (vectorizable_simd_clone_call): New function. + (vect_transform_stmt): Call it. + (vect_analyze_stmt): Likewise. Allow NULL STMT_VINFO_VECTYPE for + calls without lhs. + * ipa-prop.c (ipa_add_new_function): Only call ipa_analyze_node + if cgraph_function_with_gimple_body_p is true. + +2013-11-27 Tom de Vries <tom@codesourcery.com> + Marc Glisse <marc.glisse@inria.fr> + + PR middle-end/59037 + * fold-const.c (fold_indirect_ref_1): Don't create out-of-bounds + BIT_FIELD_REF. + * gimple-fold.c (gimple_fold_indirect_ref): Same. + * tree-cfg.c (verify_expr): Give error if BIT_FIELD_REF is + out-of-bounds. + +2013-11-27 Eric Botcazou <ebotcazou@adacore.com> + + PR middle-end/59138 + * expr.c (emit_group_store): Don't write past the end of the structure. + (store_bit_field): Fix formatting. + +2013-11-27 Richard Biener <rguenther@suse.de> + + PR tree-optimization/59288 + * tree-vect-loop.c (get_initial_def_for_induction): Do not + re-analyze the PHI but use STMT_VINFO_LOOP_PHI_EVOLUTION_PART. + +2013-11-27 Marek Polacek <polacek@redhat.com> + + * ubsan.c (ubsan_type_descriptor): If varpool_get_node returns NULL + for a decl, recreate that decl. Save into the hash table VAR_DECLs + rather than ADDR_EXPRs. + +2013-11-27 Alexander Ivchenko <alexander.ivchenko@intel.com> + + * config/ia64/hpux.h (TARGET_LIBC_HAS_FUNCTION): Fix typo. + +2013-11-26 David Malcolm <dmalcolm@redhat.com> + + * gengtype.c (struct seen_tag): New. + (already_seen_tag): New. + (mark_tag_as_seen): New. + (walk_subclasses): Support having multiple subclasses using the + same tag by tracking which tags have already been seen, and using + this to avoid adding duplicate cases to the "switch" statement. + The call to already_seen_tag introduces an O(N^2) when running + gengtype on N, the number of tags, due to the repeated linear + search, but currently max(N) is relatively small (the number of + GSS codes, which is 26). + (walk_type): Pass in a seen_tag for use by the walk_subclasses + recursion. + + * gimple.def (GIMPLE_OMP_ATOMIC_STORE, GIMPLE_OMP_RETURN): Rename + underlying GSS values for these codes (from GSS_OMP_ATOMIC_STORE to + GSS_OMP_ATOMIC_STORE_LAYOUT) to make clear that although + GIMPLE_OMP_RETURN happens to share the data layout of + GIMPLE_OMP_ATOMIC_STORE, they are not otherwise related. + (GIMPLE_OMP_PARALLEL, GIMPLE_OMP_TARGET): Likewise, rename + underlying GSS value from GSS_OMP_PARALLEL to + GSS_OMP_PARALLEL_LAYOUT to make clear that these gimple codes are + not directly related; they merely share in-memory layout. + (GIMPLE_OMP_SINGLE, GIMPLE_OMP_TEAMS): Likewise, rename GSS values + for these two codes from GSS_OMP_SINGLE to GSS_OMP_SINGLE_LAYOUT. + + * gsstruct.def (GSS_OMP_PARALLEL, gimple_statement_omp_parallel): + Rename to... + (GSS_OMP_PARALLEL_LAYOUT, gimple_statement_omp_parallel_layout): + ...these. + (GSS_OMP_SINGLE, gimple_statement_omp_single): Rename to... + (GSS_OMP_SINGLE_LAYOUT, gimple_statement_omp_single_layout): + ...these. + (GSS_OMP_ATOMIC_STORE, gimple_statement_omp_atomic_store): Rename + to... + (GSS_OMP_ATOMIC_STORE_LAYOUT, gimple_statement_omp_atomic_store): + ...these. + + * gimple.h (gimple_statement_resx): New subclass of + gimple_statement_eh_ctrl, with the invariant that + stmt->code == GIMPLE_RESX. + (gimple_statement_eh_dispatch): New subclass of + gimple_statement_eh_ctrl, with the invariant that + stmt->code == GIMPLE_EH_DISPATH. + + (gimple_statement_omp_parallel): The existing class expressed + a layout (GSS_OMP_PARALLEL), but the codes with that layout + are not all related, so it makes more sense for this class to + express a *code* (GIMPLE_OMP_PARALLEL). GSS_OMP_PARALLEL has + been renamed to GSS_OMP_PARALLEL_LAYOUT to express this, so + rename the existing gimple_statement_omp_parallel class to... + (gimple_statement_omp_parallel_layout): ...this, expressing + a statement of structure layout GSS_OMP_PARALLEL_LAYOUT. + (gimple_statement_omp_taskreg): New subclass of + gimple_statement_omp_parallel_layout, expressing the invariant + that the code is one of GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK, + as used by the various gimple_omp_taskreg_ accessors. + (gimple_statement_omp_parallel): Reintroduce this class, this time + as a subclass of gimple_statement_omp_taskreg to express the + invariant stmt->code == GIMPLE_OMP_PARALLEL. + (gimple_statement_omp_target) New class, subclassing + gimple_statement_omp_parallel_layout, to express the invariant + stmt->code == GIMPLE_OMP_TARGET. + (gimple_statement_omp_task): Update to inherit from + gimple_statement_omp_taskreg rather than + gimple_statement_omp_parallel. + + (gimple_statement_omp_single): Rename to... + (gimple_statement_omp_single_layout): ...this, expressing the + invariant that the layout is GSS_OMP_SINGLE_LAYOUT. + (gimple_statement_omp_single): ...and reintroduce this name as + a subclass of gimple_statement_omp_single_layout, expressing + the invariant that code == GIMPLE_OMP_SINGLE. + (gimple_statement_omp_teams): New class, subclassing + gimple_statement_omp_single_layout, for the code GIMPLE_OMP_TEAMS. + + (gimple_statement_omp_atomic_store): Rename to... + (gimple_statement_omp_atomic_store_layout): ...this, expressing + the invariant that the layout is GSS_OMP_ATOMIC_STORE_LAYOUT. + (gimple_statement_omp_atomic_store): ...and reintroduce this + name as a subclass of gimple_statement_omp_atomic_store_layout + with code == GIMPLE_OMP_ATOMIC_STORE. + (gimple_statement_omp_return): New class, subclassing + gimple_statement_omp_atomic_store_layout for the code + GIMPLE_OMP_RETURN. + + (is_a_helper <gimple_statement_eh_ctrl>::test): Delete. + (is_a_helper <gimple_statement_resx>::test): New. + (is_a_helper <gimple_statement_eh_dispatch>::test): New. + (is_a_helper <gimple_statement_omp_atomic_store>::test): Only + check for GIMPLE_OMP_ATOMIC_STORE, not for GIMPLE_OMP_RETURN. + (is_a_helper <gimple_statement_omp_return>::test): New. + (is_a_helper <gimple_statement_omp_taskreg>::test): New. + (is_a_helper <gimple_statement_omp_parallel>::test): Only check + for GIMPLE_OMP_PARALLEL, not for GIMPLE_OMP_TASK or + GIMPLE_OMP_TARGET. + (is_a_helper <gimple_statement_omp_target>::test): New. + (is_a_helper <gimple_statement_omp_single>::test): Only check + for GIMPLE_OMP_SINGLE, not for GIMPLE_OMP_TEAMS. + (is_a_helper <gimple_statement_omp_teams>::test): New. + + (is_a_helper <const gimple_statement_eh_ctrl>::test): Delete. + (is_a_helper <const gimple_statement_resx>::test): New. + (is_a_helper <const gimple_statement_eh_dispatch>::test): New. + (is_a_helper <const gimple_statement_omp_atomic_store>::test): Only + check for GIMPLE_OMP_ATOMIC_STORE, not for GIMPLE_OMP_RETURN. + (is_a_helper <const gimple_statement_omp_return>::test): New. + (is_a_helper <const gimple_statement_omp_taskreg>::test): New. + (is_a_helper <const gimple_statement_omp_parallel>::test): Only + check for GIMPLE_OMP_PARALLEL, not for GIMPLE_OMP_TASK or + GIMPLE_OMP_TARGET. + (is_a_helper <const gimple_statement_omp_target>::test): New. + (is_a_helper <const gimple_statement_omp_single>::test): Only + check for GIMPLE_OMP_SINGLE, not for GIMPLE_OMP_TEAMS. + (is_a_helper <const gimple_statement_omp_teams>::test): New. + + (gimple_omp_return_set_lhs, gimple_omp_return_lhs, + gimple_omp_return_lhs_ptr): Replace bogus downcasts to + gimple_statement_omp_atomic_store with downcasts to + gimple_statement_omp_return, thus requiring that the code be + GIMPLE_OMP_RETURN. + (gimple_resx_region, gimple_resx_set_region): Replace bogus + downcasts to gimple_statement_eh_ctrl with downcasts to + gimple_statement_resx, thus requiring that the code be + GIMPLE_RESX. + (gimple_eh_dispatch_region, gimple_eh_dispatch_set_region): + Replace bogus downcasts to const gimple_statement_eh_ctrl with + downcasts to gimple_statement_eh_dispatch, thus requiring that + the code be GIMPLE_EH_DISPATCH. + (gimple_omp_taskreg_clauses, gimple_omp_taskreg_clauses_ptr) + gimple_omp_taskreg_set_clauses, gimple_omp_taskreg_child_fn, + gimple_omp_taskreg_child_fn_ptr, gimple_omp_taskreg_set_child_fn, + gimple_omp_taskreg_data_arg, gimple_omp_taskreg_data_arg_ptr, + gimple_omp_taskreg_set_data_arg): Replace bogus downcasts to + gimple_statement_omp_parallel with downcasts to + gimple_statement_omp_taskreg, thus requiring that the code be + either GIMPLE_OMP_PARALLEL or GIMPLE_OMP_TASK. + (gimple_omp_target_clauses, gimple_omp_target_clauses_ptr + gimple_omp_target_set_clauses, gimple_omp_target_child_fn + gimple_omp_target_child_fn_ptr, gimple_omp_target_set_child_fn + gimple_omp_target_data_arg, gimple_omp_target_data_arg_ptr + gimple_omp_target_set_data_arg): Replace bogus downcasts to + gimple_statement_omp_parallel with downcasts to + gimple_statement_omp_target, thus requiring that the code be + GIMPLE_OMP_TARGET. + (gimple_omp_teams_clauses, gimple_omp_teams_clauses_ptr + gimple_omp_teams_set_clauses): Replace bogus downcasts to + gimple_statement_omp_single with downcasts to + gimple_statement_omp_teams, thus requiring that the code be + GIMPLE_OMP_TEAMS. + + * gimple.c (gimple_build_resx): Fix bogus as_a<> to use + gimple_statement_resx. + (gimple_build_eh_dispatch): Fix bogus as_a<> to use + gimple_statement_eh_dispatch. + +2013-11-26 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/59014 + * tree-vrp.c (register_edge_assert_for_1): Don't look + through conversions from non-integral types or through + narrowing conversions. + + PR target/59229 + * config/i386/i386.c (device_alg): Fix up formatting. + (ix86_expand_set_or_movmem): Handle max_size < epilogue_size_needed + similarly to count && count < epilogue_size_needed. Fix up + comment typo. + * builtins.c (determine_block_size): Fix comment typo. + + PR sanitizer/59258 + * ubsan.c (ubsan_source_location): Don't add any location + to ADDR_EXPR in the ctor. Revert 2013-11-22 change. + (ubsan_create_data): Strip block info from LOC. + + PR middle-end/59273 + * tree-vect-generic.c (optimize_vector_constructor): Don't optimize + if there isn't optab handler for the corresponding vector PLUS_EXPR. + + PR rtl-optimization/59166 + * ira.c (find_moveable_pseudos): Use DF_REF_REAL_LOC instead of + DF_REF_LOC in validate_change call. + (split_live_ranges_for_shrink_wrap): Likewise. + + PR middle-end/59150 + * omp-low.c (lower_rec_input_clause): For reduction with placeholder + of references to constant size types in simd loops, defer emitting + initializer for the new_var, emit it later on only if not using + SIMD arrays for it. + + PR middle-end/59152 + * omp-low.c (expand_omp_for_static_chunk): Don't set loop->latch + for the inner loop if collapse_bb is non-NULL. + (expand_omp_simd): Use cont_bb rather than e->dest as latch. + +2013-11-26 Yufeng Zhang <yufeng.zhang@arm.com> + + * config/arm/arm.c (arm_legitimize_address): Check xop1 is not + a constant immediate before force_reg. + +2013-11-26 Richard Biener <rguenther@suse.de> + + PR tree-optimization/59245 + * tree-vrp.c (set_value_range): Assert that we don't have + overflowed constants (but our infinities). + (set_value_range_to_value): Drop all overflow flags. + (vrp_visit_phi_node): Likewise. + (vrp_visit_assignment_or_call): Use set_value_range_to_value + to set a constant range. + +2013-11-26 Kyrylo Tkachov <kyrylo.tkachov@arm.com> + + PR target/59290 + * config/arm/arm.md (*zextendsidi_negsi): New pattern. + * config/arm/arm.c (arm_new_rtx_costs): Initialise cost correctly + for zero_extend case. + +2013-11-26 H.J. Lu <hongjiu.lu@intel.com> + + PR bootstrap/55552 + * configure.ac (install_gold_as_default): New. Set to yes for + --disable-ld or --enable-gold=default. + (gcc_cv_ld_gold_srcdir): New. + (gcc_cv_ld): Also check in-tree gold if install_gold_as_default + is yes. + (ORIGINAL_LD_BFD_FOR_TARGET): New AC_SUBST. + (ORIGINAL_LD_GOLD_FOR_TARGET): Likewise. + * configure: Regenerated. + + * exec-tool.in (ORIGINAL_LD_BFD_FOR_TARGET): New variable. + (ORIGINAL_LD_GOLD_FOR_TARGET): Likewise. + (original) [collect-ld && -fuse-ld=bfd]: Set to + $ORIGINAL_LD_BFD_FOR_TARGET. + (original) [collect-ld && -fuse-ld=gold]: Set to + $ORIGINAL_LD_GOLD_FOR_TARGET. + (dir) [collect-ld && ../gold/ld-new]: Set to gold. + (fast_install) [collect-ld && ../gold/ld-new]: Set to yes. + +2013-11-26 Terry Guo <terry.guo@arm.com> + + * config/arm/arm.c (require_pic_register): Handle high pic base + register for thumb-1. + (arm_load_pic_register): Also initialize high pic base register. + * doc/invoke.texi: Update documentation for option -mpic-register. + +2013-11-26 Oleg Endo <olegendo@gcc.gnu.org> + + PR target/58314 + PR target/50751 + * config/sh/sh.c (max_mov_insn_displacement, disp_addr_displacement): + Prefix function names with 'sh_'. Make them non-static. + * config/sh/sh-protos.h (sh_disp_addr_displacement, + sh_max_mov_insn_displacement): Add declarations. + * config/sh/constraints.md (Q): Reject QImode. + (Sdd): Use match_code "mem". + (Snd): Fix erroneous matching of non-memory operands. + * config/sh/predicates.md (short_displacement_mem_operand): New + predicate. + (general_movsrc_operand): Disallow PC relative QImode loads. + * config/sh/sh.md (*mov<mode>_reg_reg): Remove it. + (*movqi, *movhi): Merge both insns into... + (*mov<mode>): ... this new insn. Replace generic 'm' constraints with + 'Snd' and 'Sdd' constraints. Calculate insn length dynamically based + on the operand types. + +2013-11-26 Joern Rennecke <joern.rennecke@embecosm.com> + + * config/epiphany/epiphany.c (epiphany_expand_prologue): + Remove unused variable save_config. + (epiphany_compute_frame_size): Avoid signed/unsigned comparison in + assert. + +2013-11-26 James Greenhalgh <james.greenhalgh@arm.com> + + * config/aarch64/arm_neon.h (vtbx1_<psu>8): Emulate behaviour + using other intrinsics. + (vtbx3_<psu>8): Likewise. + +2013-11-26 James Greenhalgh <james.greenhalgh@arm.com> + + * config/aarch64/aarch64-builtins.c + (aarch64_types_bsl_p_qualifiers): New. + (aarch64_types_bsl_s_qualifiers): Likewise. + (aarch64_types_bsl_u_qualifiers): Likewise. + (TYPES_BSL_P): Likewise. + (TYPES_BSL_S): Likewise. + (TYPES_BSL_U): Likewise. + (BUILTIN_VALLDIF): Likewise. + (BUILTIN_VDQQH): Likewise. + * config/aarch64/aarch64-simd-builtins.def (simd_bsl): New. + * config/aarch64/aarch64-simd.md + (aarch64_simd_bsl<mode>_internal): Handle more modes. + (aarch64_simd_bsl<mode>): Likewise. + * config/aarch64/arm_neon.h + (vbsl<q>_<fpsu><8,16,32,64): Implement using builtins. + * config/aarch64/iterators.md (VALLDIF): New. + (Vbtype): Handle more modes. + +2013-11-26 James Greenhalgh <james.greenhalgh@arm.com> + + * config/aarch64/aarch64-builtins.c + (aarch64_type_qualifiers): Add qualifier_poly. + (aarch64_build_scalar_type): Also build Poly types. + (aarch64_build_vector_type): Likewise. + (aarch64_build_type): Likewise. + (aarch64_build_signed_type): New. + (aarch64_build_unsigned_type): Likewise. + (aarch64_build_poly_type): Likewise. + (aarch64_init_simd_builtins): Also handle Poly types. + +2013-11-26 James Greenhalgh <james.greenhalgh@arm.com> + + * config/aarch64/aarch64-builtins.c + (VAR1): Use new naming scheme for aarch64_builtins. + (aarch64_builtin_vectorized_function): Use new + aarch64_builtins names. + +2013-11-26 Richard Biener <rguenther@suse.de> + + PR tree-optimization/59287 + * tree-ssa-structalias.c (get_constraint_for_component_ref): + Remove no longer necessary special-casing of union accesses. + +2013-11-26 Richard Biener <rguenther@suse.de> + + * pretty-print.c (output_buffer::~output_buffer): Really + free the obstacks. + +2013-11-25 Jeff Law <law@redhat.com> + + * tree-ssa-threadupdate.c (thread_through_all_blocks): Selectively + invalidate loop information. + +2013-11-25 Oleg Endo <olegendo@gcc.gnu.org> + + * config/sh/sh.md (doloop_end_split): Add missing SI mode. + +2013-11-25 Oleg Endo <olegendo@gcc.gnu.org> + + PR target/53976 + PR target/59243 + * config/sh/sh_optimize_sett_clrt.cc (struct ccreg_value): Update + comments. + (sh_optimize_sett_clrt::find_last_ccreg_values): Check stack of + previously visited basic blocks before recursing instead of only one + basic block. + +2013-11-25 Kyrylo Tkachov <kyrylo.tkachov@arm.com> + + * config/aarch64/aarch64.c (cortexa53_tuning): New struct. + * config/aarch64/aarch64-cores.def (cortex-a53): + Use cortexa53 tuning struct. + +2013-11-25 Andrew Macleod <amacleod@redhat.com> + + PR bootstrap/59260 + * fold-const.c: Include hash-table.h. + +2013-11-25 Marek Polacek <polacek@redhat.com> + + PR sanitizer/59258 + * ubsan.c (ubsan_create_data): Increase the size of the fields array. + +2013-11-25 Richard Biener <rguenther@suse.de> + + * tree-dfa.c: Remove unused convert.h include. + +2013-11-25 Terry Guo <terry.guo@arm.com> + + * doc/invoke.texi (-mslow-flash-data): Document new option. + * config/arm/arm.opt (mslow-flash-data): New option. + * config/arm/arm-protos.h (arm_max_const_double_inline_cost): Declare + it. + * config/arm/arm.h (TARGET_USE_MOVT): Always true when literal pools + are disabled. + (arm_disable_literal_pool): Declare it. + * config/arm/arm.c (arm_disable_literal_pool): New variable. + (arm_option_override): Handle new option. + (thumb2_legitimate_address_p): Don't allow symbol references when + literal pools are disabled. + (arm_max_const_double_inline_cost): New function. + * config/arm/arm.md (types.md): Include it before ... + (use_literal_pool): New attribute. + (enabled): Use new attribute. + (split pattern): Replace symbol+offset with MOVW/MOVT. + +2013-11-24 Steven Bosscher <steven@gcc.gnu.org> + + PR bootstrap/59279 + Revert previous commit. + +2013-11-24 Steven Bosscher <steven@gcc.gnu.org> + + * jump.c (reset_insn_reg_label_operand_notes): New function, + split out from ... + (init_label_info): ... here. Reset LABEL_NUSES in cfglayout mode. + * cfgcleanup.c (delete_dead_jump_tables_between): New function, + split out from ... + (delete_dead_jumptables): ... here. Handle cfglayout mode. + (cleanup_cfg): Delete dead jump tables in cfglayout mode if an + expensive CFG cleanup is called for. + * cfgrtl.c (fixup_reorder_chain): Remove BARRIERs from fallthru paths. + (cfg_layout_finalize): Delete dead jump tables before re-building + the insns chain. + * ira.c (ira): Rebuild jump labels *after* deleting unreachable + basic blocks, not before. + * loop-init.c (rtl_loop_done): Call for an expensive CFG cleanup. + + * modulo-sched.c (sms_schedule): Do not look for BARRIERs in the + insns chain of a scheduling extended basic block, they cannot appear + there in cfglayout mode. + +2013-11-24 Tobias Burnus <burnus@net-b.de> + + * doc/invoke.texi (-fsanitize=leak): Add link to the wiki page. + +2013-11-24 Bill Schmidt <wschmidt@linux.vnet.ibm.com> + + * config/rs6000/rs6000.c (rs6000_expand_vec_perm_const_1): Correct + for little endian. + +2013-11-24 H.J. Lu <hongjiu.lu@intel.com> + + * graphite-sese-to-poly.c: Don't include extra "expr.h". + +2013-11-23 Eric Botcazou <ebotcazou@adacore.com> + + * cilk-common.c (expand_builtin_cilk_detach): Dereference worker. + +2013-11-23 David Edelson <dje.gcc@gmail.com> + Andrew Dixie <andrewd@gentrack.com> + + PR target/33704 + * config/rs6000/aix.h (COLLECT_SHARED_INIT_FUNC): Define. + (COLLECT_SHARED_FINI_FUNC): Define. + + * collect2.c (aix_shared_initname): Declare. + (aix_shared_fininame): Declare. + (symkind): Add SYM_AIXI and SYM_AIXD. + (scanfilter_masks): Add SCAN_AIXI and SCAN_AIXD. + (struct names special): Add GLOBAL__AIXI_ and GLOBAL__AIXD_. + (aixlazy_flag): Parse. + (extract_init_priority): SYM_AIXI and SYM_AIXD have highest priority. + (scan_prog_file, COFF): Handle SYM_AIXI and SYM_AIXD. + +2013-11-23 David Edelsohn <dje.gcc@gmail.com> + + * config/rs6000/rs6000.c (IN_NAMED_SECTION): New macro. + (rs6000_xcoff_select_section): Place decls with stricter alignment + into named sections. + (rs6000_xcoff_unique_section): Allow unique sections for + uninitialized data with strict alignment. + +2013-11-23 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/59154 + * tree-ssa-reassoc.c (maybe_optimize_range_tests): When changing + rhs1 of a cast and new_op is invariant, fold_convert it. + * tree-ssa-forwprop.c (ssa_forward_propagate_and_combine): Only call + simplify_conversion_from_bitmask if rhs1 is a SSA_NAME. + +2013-11-23 Uros Bizjak <ubizjak@gmail.com> + + PR target/56788 + * config/i386/i386.c (bdesc_multi_arg) <IX86_BUILTIN_VFRCZSS>: + Declare as MULTI_ARG_1_SF instruction. + <IX86_BUILTIN_VFRCZSD>: Decleare as MULTI_ARG_1_DF instruction. + * config/i386/sse.md (*xop_vmfrcz<mode>2): Rename + from *xop_vmfrcz_<mode>. + * config/i386/xopintrin.h (_mm_frcz_ss): Use __builtin_ia32_movss + to merge scalar result with __A. + (_mm_frcz_sd): Use __builtin_ia32_movsd to merge scalar + result with __A. + +2013-11-23 Eric Botcazou <ebotcazou@adacore.com> + + * gimplify.h (recalculate_side_effects): Delete. + * gimplify.c (recalculate_side_effects): Make static and add comment. + +2013-11-23 Richard Sandiford <rdsandiford@googlemail.com> + + * config/sh/sh.md: Use nonimmediate_operand rather than general_operand + for the destination of a define_peephole2. Likewise register_operand + rather than arith_reg_operand. Remove constraints from + define_peephole2s. + +2013-11-23 Richard Sandiford <rdsandiford@googlemail.com> + + * config/mn10300/mn10300-protos.h (mn10300_store_multiple_operation): + Delete. + (mn10300_store_multiple_operation_p): Declare. + * config/mn10300/mn10300.c (mn10300_store_multiple_operation): + Rename to... + (mn10300_store_multiple_operation_p): ...this and remove mode + argument. + * config/mn10300/predicates.md (mn10300_store_multiple_operation): + Define. + +2013-11-23 Richard Sandiford <rdsandiford@googlemail.com> + + * config/bfin/bfin-protos.h (push_multiple_operation): Delete. + (pop_multiple_operation): Delete. + (analyze_push_multiple_operation): Declare. + (analyze_pop_multiple_operation): Declare. + * config/bfin/bfin.c (push_multiple_operation): Rename to... + (analyze_push_multiple_operation): ...this and remove mode argument. + (pop_multiple_operation): Rename to... + (analyze_pop_multiple_operation): ...this and remove mode argument. + * config/bfin/predicates.md (push_multiple_operation): Define. + (pop_multiple_operation): Likewise. + +2013-11-23 Alan Modra <amodra@gmail.com> + + * config/rs6000/vsx.md (fusion peepholes): Disable when !TARGET_VSX. + +2013-11-22 Jakub Jelinek <jakub@redhat.com> + + PR sanitizer/59061 + * common.opt (static-liblsan): Add. + * config/gnu-user.h (STATIC_LIBLSAN_LIBS, STATIC_LIBUBSAN_LIBS): + Define. + * flag-types.h (enum sanitize_code): Add SANITIZE_LEAK. Renumber + SANITIZE_SHIFT, SANITIZE_DIVIDE, SANITIZE_UNREACHABLE, SANITIZE_VLA, + SANITIZE_RETURN. + * opts.c (common_handle_option): Handle -fsanitize=leak. + * gcc.c (ADD_STATIC_LIBLSAN_LIBS, LIBLSAN_SPEC): Define. + (LIBUBSAN_SPEC): Don't test LIBUBSAN_EARLY_SPEC. + (LIBUBSAN_EARLY_SPEC): Remove. + (SANITIZER_EARLY_SPEC): Don't do anything for libubsan. + (SANITIZER_SPEC): Add -fsanitize=leak handling. + (sanitize_spec_function): Handle %sanitize(leak). + * doc/invoke.texi (-static-liblsan, -fsanitize=leak): Document. + +2013-11-22 Aldy Hernandez <aldyh@redhat.com> + Jakub Jelinek <jakub@redhat.com> + + * ipa.c (symtab_remove_unreachable_nodes): Fix up comment typos. + * ipa-prop.c (get_vector_of_formal_parm_types): Renamed to ... + (ipa_get_vector_of_formal_parm_types): ... this. No longer static. + (ipa_modify_formal_parameters): Adjust caller. Remove + synth_parm_prefix argument. Use operator enum instead of bit fields. + Add assert for properly handling vector of references. Handle + creating brand new parameters. + (ipa_modify_call_arguments): Use operator enum instead of bit + fields. + (ipa_combine_adjustments): Same. Assert that IPA_PARM_OP_NEW is not + used. + (ipa_modify_expr, get_ssa_base_param, ipa_get_adjustment_candidate): + New functions. + (ipa_dump_param_adjustments): Rename reduction to new_decl. + Use operator enum instead of bit fields. + * ipa-prop.h (enum ipa_parm_op): New. + (struct ipa_parm_adjustment): New field op. Rename reduction + to new_decl, new_arg_prefix to arg_prefix and remove remove_param + and copy_param. + (ipa_modify_formal_parameters): Remove last argument. + (ipa_get_vector_of_formal_parm_types, ipa_modify_expr, + ipa_get_adjustment_candidate): New prototypes. + * tree-sra.c (turn_representatives_into_adjustments): Use operator + enum. Set arg_prefix. + (get_adjustment_for_base): Use operator enum. + (sra_ipa_modify_expr): Rename to ipa_modify_expr and move to + ipa-prop.c. + (sra_ipa_modify_assign): Rename sra_ipa_modify_expr to ipa_modify_expr. + (ipa_sra_modify_function_body): Same. No longer static. + (sra_ipa_reset_debug_stmts): Use operator enum. + (modify_function): Do not pass prefix argument. + +2013-11-22 Jakub Jelinek <jakub@redhat.com> + + * ubsan.c (ubsan_source_location): Don't crash on unknown locations. + (ubsan_pass): Ignore clobber stmts. + + * sanitizer.def (BUILT_IN_UBSAN_HANDLE_MISSING_RETURN): New built-in. + * opts.c (common_handle_option): Add -fsanitize=return. + * flag-types.h (enum sanitize_code): Add SANITIZE_RETURN and + or it into SANITIZE_UNDEFINED. + + * sanitizer.def (BUILT_IN_ASAN_BEFORE_DYNAMIC_INIT, + BUILT_IN_ASAN_AFTER_DYNAMIC_INIT): New. + * asan.c (instrument_derefs): Handle also VAR_DECL loads/stores. + Don't instrument accesses to VAR_DECLs which are known to fit + into their bounds and the vars are known to have shadow bytes + indicating allowed access. + (asan_dynamic_init_call): New function. + (asan_add_global): If vnode->dynamically_initialized, + set __has_dynamic_init to 1 instead of 0. + (initialize_sanitizer_builtins): Add BT_FN_VOID_CONST_PTR var. + * asan.h (asan_dynamic_init_call): New prototype. + * cgraph.h (varpool_node): Add dynamically_initialized bitfield. + +2013-11-22 Martin Jambor <mjambor@suse.cz> + + PR rtl-optimization/10474 + * ira.c (interesting_dest_for_shprep_1): New function. + (interesting_dest_for_shprep): Use interesting_dest_for_shprep_1, + also check parallels. + +2013-11-22 Jeff Law <law@redhat.com> + + * tree-ssa-threadedge.c (record_temporary_equivalence): Handle + NULL for RHS, which we used to invalidate equivalences. + (record_temporary_equivalences_from_phis): New bitmap arguments + and a boolean indicating if we have passed a backedge. If we + have passed a backedge, then set the appropriate bit in the + bitmaps for the SRC & DEST of PHIs creating equivalences. + (invalidate_equivalences, dummy_simplify): New functions. + (cond_arg_set_in_b): Remove. + (record_temporary_equivalences_from_stmts_at_dest): New bitmap + arguments and a boolean indicating if we have passed a backedge. + If we have passed a backedge, then perform invalidations as needed. + (thread_around_empty_blocks): If we have seen a backedge, then + use the dummy simplify routine. + (thread_through_normal_block): Likewise. Pass bitmaps and + backedge status to children. Do not pessimize so much when + traversing backedges in the CFG. + (thread_across_edge): Manage the SRC_MAP/DST_MAP bitmaps. + If we have seen a backedge, then use the dummy simplify routine. + Do not pessimize so much when traversing backedges. + +2013-11-22 Hans-Peter Nilsson <hp@axis.com> + + * config/cris/cris.c (cris_atomic_align_for_mode): New function. + (TARGET_ATOMIC_ALIGN_FOR_MODE): Define. + +2013-11-22 Yuri Rumyantsev <ysrumyan@gmail.com> + + * config/i386/i386.c(processor_alias_table): Enable PTA_AES, + PTA_PCLMUL and PTA_RDRND for Silvermont. + * config/i386/driver-i386.c (host_detect_local_cpu): Set up cpu + for Silvermont. + + * doc/invoke.texi: Mention AES, PCLMUL and RDRND for Silvermont. + +2013-11-22 Andrew MacLeod <amacleod@redhat.com> + + * hooks.h (hook_uint_mode_0): Add Prototype. + * hooks.c (hook_uint_mode_0): New default function. + * target.def (atomic_align_for_mode): New target hook. + * tree.c (build_atomic_base): Add alignment override parameter. + (build_common_tree_nodes): Use atomic alignment override. + * doc/tm.texi.in (TARGET_ATOMIC_ALIGN_FOR_MODE): Define. + * doc/tm.texi (TARGET_ATOMIC_ALIGN_FOR_MODE): Add description. + +2013-11-22 Andrew MacLeod <amacleod@redhat.com> + + * gimple.h: Remove all includes. + (recalculate_side_effects): Move prototype to gimplify.h. + * Makefile.in (PLUGIN_HEADERS): Add flattened gimple.h includes. + * gengtype.c (open_base_files): Add gimple.h include list. + * gimplify.h (recalculate_side_effects): Relocate prototype here. + * gimple.c: Adjust include list. + (recalculate_side_effects): Move to gimplify.c. + * gimplify.c: Adjust include list. + (recalculate_side_effects): Relocate from gimple.c. + * alias.c: Add required include files removed from gimple.h. + * asan.c: Likewise. + * builtins.c: Likewise. + * calls.c: Likewise. + * cfgexpand.c: Likewise. + * cfgloop.c: Likewise. + * cfgloopmanip.c: Likewise. + * cgraphbuild.c: Likewise. + * cgraph.c: Likewise. + * cgraphclones.c: Likewise. + * cgraphunit.c: Likewise. + * cilk-common.c: Likewise. + * data-streamer.c: Likewise. + * data-streamer-in.c: Likewise. + * data-streamer-out.c: Likewise. + * dse.c: Likewise. + * dwarf2out.c: Likewise. + * emit-rtl.c: Likewise. + * except.c: Likewise. + * expr.c: Likewise. + * fold-const.c: Likewise. + * function.c: Likewise. + * gimple-builder.c: Likewise. + * gimple-expr.c: Likewise. + * gimple-fold.c: Likewise. + * gimple-iterator.c: Likewise. + * gimple-low.c: Likewise. + * gimple-pretty-print.c: Likewise. + * gimple-ssa-isolate-paths.c: Likewise. + * gimple-ssa-strength-reduction.c: Likewise. + * gimple-streamer-in.c: Likewise. + * gimple-streamer-out.c: Likewise. + * gimple-walk.c: Likewise. + * gimplify-me.c: Likewise. + * graphite-blocking.c: Likewise. + * graphite.c: Likewise. + * graphite-clast-to-gimple.c: Likewise. + * graphite-dependences.c: Likewise. + * graphite-interchange.c: Likewise. + * graphite-optimize-isl.c: Likewise. + * graphite-poly.c: Likewise. + * graphite-scop-detection.c: Likewise. + * graphite-sese-to-poly.c: Likewise. + * internal-fn.c: Likewise. + * ipa.c: Likewise. + * ipa-cp.c: Likewise. + * ipa-devirt.c: Likewise. + * ipa-inline-analysis.c: Likewise. + * ipa-inline.c: Likewise. + * ipa-profile.c: Likewise. + * ipa-prop.c: Likewise. + * ipa-pure-const.c: Likewise. + * ipa-reference.c: Likewise. + * ipa-split.c: Likewise. + * ipa-utils.c: Likewise. + * langhooks.c: Likewise. + * lto-cgraph.c: Likewise. + * lto-compress.c: Likewise. + * lto-opts.c: Likewise. + * lto-section-in.c: Likewise. + * lto-section-out.c: Likewise. + * lto-streamer.c: Likewise. + * lto-streamer-in.c: Likewise. + * lto-streamer-out.c: Likewise. + * omp-low.c: Likewise. + * opts-global.c: Likewise. + * passes.c: Likewise. + * predict.c: Likewise. + * profile.c: Likewise. + * sese.c: Likewise. + * stmt.c: Likewise. + * stor-layout.c: Likewise. + * symtab.c: Likewise. + * targhooks.c: Likewise. + * toplev.c: Likewise. + * tracer.c: Likewise. + * trans-mem.c: Likewise. + * tree-affine.c: Likewise. + * tree.c: Likewise. + * tree-call-cdce.c: Likewise. + * tree-cfg.c: Likewise. + * tree-cfgcleanup.c: Likewise. + * tree-chrec.c: Likewise. + * tree-complex.c: Likewise. + * tree-data-ref.c: Likewise. + * tree-dfa.c: Likewise. + * tree-eh.c: Likewise. + * tree-emutls.c: Likewise. + * tree-if-conv.c: Likewise. + * tree-inline.c: Likewise. + * tree-into-ssa.c: Likewise. + * tree-loop-distribution.c: Likewise. + * tree-nested.c: Likewise. + * tree-nrv.c: Likewise. + * tree-object-size.c: Likewise. + * tree-outof-ssa.c: Likewise. + * tree-parloops.c: Likewise. + * tree-phinodes.c: Likewise. + * tree-predcom.c: Likewise. + * tree-pretty-print.c: Likewise. + * tree-profile.c: Likewise. + * tree-scalar-evolution.c: Likewise. + * tree-sra.c: Likewise. + * tree-ssa-address.c: Likewise. + * tree-ssa-alias.c: Likewise. + * tree-ssa.c: Likewise. + * tree-ssa-ccp.c: Likewise. + * tree-ssa-coalesce.c: Likewise. + * tree-ssa-copy.c: Likewise. + * tree-ssa-copyrename.c: Likewise. + * tree-ssa-dce.c: Likewise. + * tree-ssa-dom.c: Likewise. + * tree-ssa-dse.c: Likewise. + * tree-ssa-forwprop.c: Likewise. + * tree-ssa-ifcombine.c: Likewise. + * tree-ssa-live.c: Likewise. + * tree-ssa-loop.c: Likewise. + * tree-ssa-loop-ch.c: Likewise. + * tree-ssa-loop-im.c: Likewise. + * tree-ssa-loop-ivcanon.c: Likewise. + * tree-ssa-loop-ivopts.c: Likewise. + * tree-ssa-loop-manip.c: Likewise. + * tree-ssa-loop-niter.c: Likewise. + * tree-ssa-loop-prefetch.c: Likewise. + * tree-ssa-loop-unswitch.c: Likewise. + * tree-ssa-math-opts.c: Likewise. + * tree-ssanames.c: Likewise. + * tree-ssa-operands.c: Likewise. + * tree-ssa-phiopt.c: Likewise. + * tree-ssa-phiprop.c: Likewise. + * tree-ssa-pre.c: Likewise. + * tree-ssa-propagate.c: Likewise. + * tree-ssa-reassoc.c: Likewise. + * tree-ssa-sccvn.c: Likewise. + * tree-ssa-sink.c: Likewise. + * tree-ssa-strlen.c: Likewise. + * tree-ssa-structalias.c: Likewise. + * tree-ssa-tail-merge.c: Likewise. + * tree-ssa-ter.c: Likewise. + * tree-ssa-threadedge.c: Likewise. + * tree-ssa-threadupdate.c: Likewise. + * tree-ssa-uncprop.c: Likewise. + * tree-ssa-uninit.c: Likewise. + * tree-stdarg.c: Likewise. + * tree-streamer.c: Likewise. + * tree-streamer-in.c: Likewise. + * tree-streamer-out.c: Likewise. + * tree-switch-conversion.c: Likewise. + * tree-tailcall.c: Likewise. + * tree-vect-data-refs.c: Likewise. + * tree-vect-generic.c: Likewise. + * tree-vect-loop.c: Likewise. + * tree-vect-loop-manip.c: Likewise. + * tree-vectorizer.c: Likewise. + * tree-vect-patterns.c: Likewise. + * tree-vect-slp.c: Likewise. + * tree-vect-stmts.c: Likewise. + * tree-vrp.c: Likewise. + * tsan.c: Likewise. + * ubsan.c: Likewise. + * value-prof.c: Likewise. + * varpool.c: Likewise. + * var-tracking.c: Likewise. + * vtable-verify.c: Likewise. + * config/darwin.c: Likewise. + * config/aarch64/aarch64-builtins.c: Likewise. + * config/aarch64/aarch64.c: Likewise. + * config/alpha/alpha.c: Likewise. + * config/i386/i386.c: Likewise. + * config/i386/winnt.c: Likewise. + * config/ia64/ia64.c: Likewise. + * config/m32c/m32c.c: Likewise. + * config/mep/mep.c: Likewise. + * config/mips/mips.c: Likewise. + * config/rs6000/rs6000.c: Likewise. + * config/s390/s390.c: Likewise. + * config/sh/sh.c: Likewise. + * config/sparc/sparc.c: Likewise. + * config/spu/spu.c: Likewise. + * config/stormy16/stormy16.c: Likewise. + * config/tilegx/tilegx.c: Likewise. + * config/tilepro/tilepro.c: Likewise. + * config/xtensa/xtensa.c: Likewise. + +2013-11-22 Richard Earnshaw <rearnsha@arm.com> + + PR target/59216 + * arm.md (negdi_extendsidi): Fix invalid split. + +2013-11-22 Alex Velenko <Alex.Velenko@arm.com> + + * config/aarch64/arm_neon.h (vmov_n_f32): Implemented in C. + (vmov_n_f64): Likewise. + (vmov_n_p8): Likewise. + (vmov_n_p16): Likewise. + (vmov_n_s8): Likewise. + (vmov_n_s16): Likewise. + (vmov_n_s32): Likewise. + (vmov_n_s64): Likewise. + (vmov_n_u8): Likewise. + (vmov_n_u16): Likewise. + (vmov_n_u32): Likewise. + (vmov_n_u64): Likewise. + (vmovq_n_f32): Likewise. + (vmovq_n_f64): Likewise. + (vmovq_n_p8): Likewise. + (vmovq_n_p16): Likewise. + (vmovq_n_s8): Likewise. + (vmovq_n_s16): Likewise. + (vmovq_n_s32): Likewise. + (vmovq_n_s64): Likewise. + (vmovq_n_u8): Likewise. + (vmovq_n_u16): Likewise. + (vmovq_n_u32): Likewise. + (vmovq_n_u64): Likewise. + +2013-11-22 Tejas Belagod <tejas.belagod@arm.com> + + * config/aarch64/aarch64-simd.md (vec_pack_trunc_<mode>, + vec_pack_trunc_v2df, vec_pack_trunc_df): Swap for big-endian. + (reduc_<sur>plus_<mode>): Factorize V2DI into this. + (reduc_<sur>plus_<mode>): Change this to reduc_splus_<mode> for floats + and also change to float UNSPEC. + (reduc_maxmin_uns>_<mode>): Remove V2DI. + * config/aarch64/arm_neon.h (vaddv<q>_<suf><8,16,32,64>, + vmaxv<q>_<suf><8,16,32,64>, vminv<q>_<suf><8,16,32,64>): Fix up scalar + result access for big-endian. + (__LANE0): New macro used to fix up lane access of 'across-lanes' + intrinsics for big-endian. + * config/aarch64/iterators.md (VDQV): Add V2DI. + (VDQV_S): New. + (vp): New mode attribute. + +2013-11-22 Tejas Belagod <tejas.belagod@arm.com> + + * config/aarch64/aarch64-simd.md (vec_pack_trunc_<mode>, + vec_pack_trunc_v2df, vec_pack_trunc_df): Swap source ops for + big-endian. + +2013-11-22 Tejas Belagod <tejas.belagod@arm.com> + + * config/aarch64/aarch64-simd.md (aarch64_simd_vec_set<mode>): Adjust + for big-endian element order. + (aarch64_simd_vec_setv2di): Likewise. + (*aarch64_get_lane_extend<GPI:mode><VDQQH:mode>, + *aarch64_get_lane_zero_extendsi<mode>, aarch64_get_lane): Likewise. + (vec_extract): Expand using aarch64_get_lane. + * config/aarch64/aarch64.h (ENDIAN_LANE_N): New. + +2013-11-22 Tejas Belagod <tejas.belagod@arm.com> + + * config/aarch64/aarch64-simd.md (*aarch64_simd_mov<mode>): Fix loads + and stores to be ABI compliant. + +2013-11-22 David Malcolm <dmalcolm@redhat.com> + + * input.h (input_line): Remove. + (input_filename): Likewise. + (in_system_header): Likewise. + * tree.h (EXPR_LOC_OR_HERE): Remove. + * config/bfin/bfin.c (output_file_start): Remove use of + input_filename macro. + * builtins.c (c_strlen): Remove use of EXPR_LOC_OR_HERE macro. + * gimplify.c (internal_get_tmp_var): Likewise. + EXPR_LOC_OR_HERE macro. + (shortcut_cond_expr): Likewise. + * tree-diagnostic.c (diagnostic_report_current_function): Remove + use of input_filename macro. + * tree.c (get_file_function_name): Likewise. + 2013-11-22 Kenneth Zadeck <zadeck@naturalbridge.com> * store-layout.c (place-field): Fix hwi test and accessor mismatch. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 09dcb0d83d3..c026c978121 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20131122 +20131204 diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 958118d9c83..645911a3556 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -3107,7 +3107,9 @@ installdirs: $(mkinstalldirs) $(DESTDIR)$(man7dir) PLUGIN_HEADERS = $(TREE_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ - toplev.h $(DIAGNOSTIC_CORE_H) $(BASIC_BLOCK_H) $(GIMPLE_H) $(TREE_PASS_H) $(GCC_PLUGIN_H) \ + toplev.h $(DIAGNOSTIC_CORE_H) $(BASIC_BLOCK_H) pointer-set.h $(HASH_TABLE_H) \ + tree-ssa-alias.h $(INTERNAL_FN_H) gimple-fold.h tree-eh.h gimple-expr.h \ + gimple.h is-a.h $(TREE_PASS_H) $(GCC_PLUGIN_H) \ $(GGC_H) $(TREE_DUMP_H) $(PRETTY_PRINT_H) $(OPTS_H) $(PARAMS_H) \ $(tm_file_list) $(tm_include_list) $(tm_p_file_list) $(tm_p_include_list) \ $(host_xm_file_list) $(host_xm_include_list) $(xm_include_list) \ diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 906bd7e4f51..f1f73169933 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,27 @@ +2013-11-29 Eric Botcazou <ebotcazou@adacore.com> + + PR ada/54040 + PR ada/59346 + * s-osinte-hpux.ads (timespec): Change type of tv_nsec field to time_t. + * s-osinte-kfreebsd-gnu.ads (timespec): Likewise. + * s-osinte-solaris-posix.ads (timespec): Likewise. + +2013-11-23 Eric Botcazou <ebotcazou@adacore.com> + + * gcc-interface/trans.c (Loop_Statement_to_gnu): Set TREE_SIDE_EFFECTS + on the conditional expression directly. + +2013-11-22 Andrew MacLeod <amacleod@redhat.com> + + * gcc-interface/trans.c: Add required include files from gimple.h. + +2013-11-22 David Malcolm <dmalcolm@redhat.com> + + * gcc-interface/utils2.c (build_call_raise): Remove use of + input_line macro. + (build_call_raise_range): Likewise. + (build_call_raise_column): Likewise. + 2013-11-20 Kenneth Zadeck <zadeck@naturalbridge.com> Mike Stump <mikestump@comcast.net> Richard Sandiford <rdsandiford@googlemail.com> diff --git a/gcc/ada/gcc-interface/trans.c b/gcc/ada/gcc-interface/trans.c index 53e66780f84..e533de6dcbf 100644 --- a/gcc/ada/gcc-interface/trans.c +++ b/gcc/ada/gcc-interface/trans.c @@ -33,13 +33,12 @@ #include "stmt.h" #include "varasm.h" #include "flags.h" -#include "ggc.h" #include "output.h" #include "libfuncs.h" /* For set_stack_check_libfunc. */ #include "tree-iterator.h" -#include "gimple.h" -#include "gimplify.h" #include "pointer-set.h" +#include "gimple-expr.h" +#include "gimplify.h" #include "bitmap.h" #include "cgraph.h" #include "diagnostic.h" @@ -2809,8 +2808,8 @@ Loop_Statement_to_gnu (Node_Id gnat_node) if (gnu_cond_expr) { COND_EXPR_THEN (gnu_cond_expr) = gnu_loop_stmt; + TREE_SIDE_EFFECTS (gnu_cond_expr) = 1; gnu_result = gnu_cond_expr; - recalculate_side_effects (gnu_cond_expr); } else gnu_result = gnu_loop_stmt; diff --git a/gcc/ada/gcc-interface/utils2.c b/gcc/ada/gcc-interface/utils2.c index 184a223ff13..224a87d8777 100644 --- a/gcc/ada/gcc-interface/utils2.c +++ b/gcc/ada/gcc-interface/utils2.c @@ -1715,7 +1715,8 @@ build_call_raise (int msg, Node_Id gnat_node, char kind) filename = build_string (len, str); line_number = (gnat_node != Empty && Sloc (gnat_node) != No_Location) - ? Get_Logical_Line_Number (Sloc(gnat_node)) : input_line; + ? Get_Logical_Line_Number (Sloc(gnat_node)) + : LOCATION_LINE (input_location); TREE_TYPE (filename) = build_array_type (unsigned_char_type_node, build_index_type (size_int (len))); @@ -1761,7 +1762,7 @@ build_call_raise_range (int msg, Node_Id gnat_node, } else { - line_number = input_line; + line_number = LOCATION_LINE (input_location); column_number = 0; } @@ -1811,7 +1812,7 @@ build_call_raise_column (int msg, Node_Id gnat_node) } else { - line_number = input_line; + line_number = LOCATION_LINE (input_location); column_number = 0; } diff --git a/gcc/ada/s-osinte-hpux.ads b/gcc/ada/s-osinte-hpux.ads index b916b8db940..396844c68a3 100644 --- a/gcc/ada/s-osinte-hpux.ads +++ b/gcc/ada/s-osinte-hpux.ads @@ -7,7 +7,7 @@ -- S p e c -- -- -- -- Copyright (C) 1991-1994, Florida State University -- --- Copyright (C) 1995-2012, Free Software Foundation, Inc. -- +-- Copyright (C) 1995-2013, 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- -- @@ -522,7 +522,7 @@ private type timespec is record tv_sec : time_t; - tv_nsec : long; + tv_nsec : time_t; end record; pragma Convention (C, timespec); diff --git a/gcc/ada/s-osinte-kfreebsd-gnu.ads b/gcc/ada/s-osinte-kfreebsd-gnu.ads index 406cf0bab27..f57fe9fea07 100644 --- a/gcc/ada/s-osinte-kfreebsd-gnu.ads +++ b/gcc/ada/s-osinte-kfreebsd-gnu.ads @@ -6,8 +6,8 @@ -- -- -- S p e c -- -- -- --- Copyright (C) 1991-1994, Florida State University -- --- Copyright (C) 1995-2005,2008,2012 Free Software Foundation, Inc. -- +-- Copyright (C) 1991-1994, Florida State University -- +-- Copyright (C) 1995-2013, 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- -- @@ -492,7 +492,7 @@ private type timespec is record tv_sec : time_t; - tv_nsec : long; + tv_nsec : time_t; end record; pragma Convention (C, timespec); diff --git a/gcc/ada/s-osinte-solaris-posix.ads b/gcc/ada/s-osinte-solaris-posix.ads index eb17bd4e25f..7aa20f11598 100644 --- a/gcc/ada/s-osinte-solaris-posix.ads +++ b/gcc/ada/s-osinte-solaris-posix.ads @@ -7,7 +7,7 @@ -- S p e c -- -- -- -- Copyright (C) 1991-1994, Florida State University -- --- Copyright (C) 1995-2011, Free Software Foundation, Inc. -- +-- Copyright (C) 1995-2013, 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- -- @@ -513,7 +513,7 @@ private type timespec is record tv_sec : time_t; - tv_nsec : long; + tv_nsec : time_t; end record; pragma Convention (C, timespec); diff --git a/gcc/alias.c b/gcc/alias.c index 67b9b80c28b..97815f00fba 100644 --- a/gcc/alias.c +++ b/gcc/alias.c @@ -32,12 +32,10 @@ along with GCC; see the file COPYING3. If not see #include "emit-rtl.h" #include "regs.h" #include "hard-reg-set.h" -#include "basic-block.h" #include "flags.h" #include "diagnostic-core.h" #include "cselib.h" #include "splay-tree.h" -#include "ggc.h" #include "langhooks.h" #include "timevar.h" #include "dumpfile.h" @@ -45,6 +43,9 @@ along with GCC; see the file COPYING3. If not see #include "df.h" #include "tree-ssa-alias.h" #include "pointer-set.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-ssa.h" diff --git a/gcc/asan.c b/gcc/asan.c index d44aa636c55..2245d6dd807 100644 --- a/gcc/asan.c +++ b/gcc/asan.c @@ -23,6 +23,12 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "tree.h" +#include "hash-table.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "gimple-iterator.h" @@ -42,7 +48,6 @@ along with GCC; see the file COPYING3. If not see #include "output.h" #include "tm_p.h" #include "langhooks.h" -#include "hash-table.h" #include "alloc-pool.h" #include "cfgloop.h" #include "gimple-builder.h" @@ -219,7 +224,7 @@ along with GCC; see the file COPYING3. If not see // Name of the module where the global variable is declared. const void *__module_name; - // This is always set to NULL for now. + // 1 if it has dynamic initialization, 0 otherwise. uptr __has_dynamic_init; } @@ -232,6 +237,9 @@ alias_set_type asan_shadow_set = -1; alias set is used for all shadow memory accesses. */ static GTY(()) tree shadow_ptr_types[2]; +/* Decl for __asan_option_detect_stack_use_after_return. */ +static GTY(()) tree asan_detect_stack_use_after_return; + /* Hashtable support for memory references used by gimple statements. */ @@ -945,20 +953,26 @@ asan_function_start (void) and DECLS is an array of representative decls for each var partition. LENGTH is the length of the OFFSETS array, DECLS array is LENGTH / 2 - 1 elements long (OFFSETS include gap before the first variable as well - as gaps after each stack variable). */ + as gaps after each stack variable). PBASE is, if non-NULL, some pseudo + register which stack vars DECL_RTLs are based on. Either BASE should be + assigned to PBASE, when not doing use after return protection, or + corresponding address based on __asan_stack_malloc* return value. */ rtx -asan_emit_stack_protection (rtx base, HOST_WIDE_INT *offsets, tree *decls, - int length) +asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb, + HOST_WIDE_INT *offsets, tree *decls, int length) { - rtx shadow_base, shadow_mem, ret, mem; + rtx shadow_base, shadow_mem, ret, mem, orig_base, lab; char buf[30]; unsigned char shadow_bytes[4]; - HOST_WIDE_INT base_offset = offsets[length - 1], offset, prev_offset; + HOST_WIDE_INT base_offset = offsets[length - 1]; + HOST_WIDE_INT base_align_bias = 0, offset, prev_offset; + HOST_WIDE_INT asan_frame_size = offsets[0] - base_offset; HOST_WIDE_INT last_offset, last_size; int l; unsigned char cur_shadow_byte = ASAN_STACK_MAGIC_LEFT; tree str_cst, decl, id; + int use_after_return_class = -1; if (shadow_ptr_types[0] == NULL_TREE) asan_init_shadow_ptr_types (); @@ -988,10 +1002,67 @@ asan_emit_stack_protection (rtx base, HOST_WIDE_INT *offsets, tree *decls, str_cst = asan_pp_string (&asan_pp); /* Emit the prologue sequence. */ + if (asan_frame_size > 32 && asan_frame_size <= 65536 && pbase) + { + use_after_return_class = floor_log2 (asan_frame_size - 1) - 5; + /* __asan_stack_malloc_N guarantees alignment + N < 6 ? (64 << N) : 4096 bytes. */ + if (alignb > (use_after_return_class < 6 + ? (64U << use_after_return_class) : 4096U)) + use_after_return_class = -1; + else if (alignb > ASAN_RED_ZONE_SIZE && (asan_frame_size & (alignb - 1))) + base_align_bias = ((asan_frame_size + alignb - 1) + & ~(alignb - HOST_WIDE_INT_1)) - asan_frame_size; + } + if (use_after_return_class == -1 && pbase) + emit_move_insn (pbase, base); base = expand_binop (Pmode, add_optab, base, - gen_int_mode (base_offset, Pmode), + gen_int_mode (base_offset - base_align_bias, Pmode), NULL_RTX, 1, OPTAB_DIRECT); + orig_base = NULL_RTX; + if (use_after_return_class != -1) + { + if (asan_detect_stack_use_after_return == NULL_TREE) + { + id = get_identifier ("__asan_option_detect_stack_use_after_return"); + decl = build_decl (BUILTINS_LOCATION, VAR_DECL, id, + integer_type_node); + SET_DECL_ASSEMBLER_NAME (decl, id); + TREE_ADDRESSABLE (decl) = 1; + DECL_ARTIFICIAL (decl) = 1; + DECL_IGNORED_P (decl) = 1; + DECL_EXTERNAL (decl) = 1; + TREE_STATIC (decl) = 1; + TREE_PUBLIC (decl) = 1; + TREE_USED (decl) = 1; + asan_detect_stack_use_after_return = decl; + } + orig_base = gen_reg_rtx (Pmode); + emit_move_insn (orig_base, base); + ret = expand_normal (asan_detect_stack_use_after_return); + lab = gen_label_rtx (); + int very_likely = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1); + emit_cmp_and_jump_insns (ret, const0_rtx, EQ, NULL_RTX, + VOIDmode, 0, lab, very_likely); + snprintf (buf, sizeof buf, "__asan_stack_malloc_%d", + use_after_return_class); + ret = init_one_libfunc (buf); + rtx addr = convert_memory_address (ptr_mode, base); + ret = emit_library_call_value (ret, NULL_RTX, LCT_NORMAL, ptr_mode, 2, + GEN_INT (asan_frame_size + + base_align_bias), + TYPE_MODE (pointer_sized_int_node), + addr, ptr_mode); + ret = convert_memory_address (Pmode, ret); + emit_move_insn (base, ret); + emit_label (lab); + emit_move_insn (pbase, expand_binop (Pmode, add_optab, base, + gen_int_mode (base_align_bias + - base_offset, Pmode), + NULL_RTX, 1, OPTAB_DIRECT)); + } mem = gen_rtx_MEM (ptr_mode, base); + mem = adjust_address (mem, VOIDmode, base_align_bias); emit_move_insn (mem, gen_int_mode (ASAN_STACK_FRAME_MAGIC, ptr_mode)); mem = adjust_address (mem, VOIDmode, GET_MODE_SIZE (ptr_mode)); emit_move_insn (mem, expand_normal (str_cst)); @@ -1015,10 +1086,10 @@ asan_emit_stack_protection (rtx base, HOST_WIDE_INT *offsets, tree *decls, shadow_base = expand_binop (Pmode, lshr_optab, base, GEN_INT (ASAN_SHADOW_SHIFT), NULL_RTX, 1, OPTAB_DIRECT); - shadow_base = expand_binop (Pmode, add_optab, shadow_base, - gen_int_mode (targetm.asan_shadow_offset (), - Pmode), - NULL_RTX, 1, OPTAB_DIRECT); + shadow_base + = plus_constant (Pmode, shadow_base, + targetm.asan_shadow_offset () + + (base_align_bias >> ASAN_SHADOW_SHIFT)); gcc_assert (asan_shadow_set != -1 && (ASAN_RED_ZONE_SIZE >> ASAN_SHADOW_SHIFT) == 4); shadow_mem = gen_rtx_MEM (SImode, shadow_base); @@ -1069,6 +1140,47 @@ asan_emit_stack_protection (rtx base, HOST_WIDE_INT *offsets, tree *decls, /* Construct epilogue sequence. */ start_sequence (); + lab = NULL_RTX; + if (use_after_return_class != -1) + { + rtx lab2 = gen_label_rtx (); + char c = (char) ASAN_STACK_MAGIC_USE_AFTER_RET; + int very_likely = REG_BR_PROB_BASE - (REG_BR_PROB_BASE / 2000 - 1); + emit_cmp_and_jump_insns (orig_base, base, EQ, NULL_RTX, + VOIDmode, 0, lab2, very_likely); + shadow_mem = gen_rtx_MEM (BLKmode, shadow_base); + set_mem_alias_set (shadow_mem, asan_shadow_set); + mem = gen_rtx_MEM (ptr_mode, base); + mem = adjust_address (mem, VOIDmode, base_align_bias); + emit_move_insn (mem, gen_int_mode (ASAN_STACK_RETIRED_MAGIC, ptr_mode)); + unsigned HOST_WIDE_INT sz = asan_frame_size >> ASAN_SHADOW_SHIFT; + if (use_after_return_class < 5 + && can_store_by_pieces (sz, builtin_memset_read_str, &c, + BITS_PER_UNIT, true)) + store_by_pieces (shadow_mem, sz, builtin_memset_read_str, &c, + BITS_PER_UNIT, true, 0); + else if (use_after_return_class >= 5 + || !set_storage_via_setmem (shadow_mem, + GEN_INT (sz), + gen_int_mode (c, QImode), + BITS_PER_UNIT, BITS_PER_UNIT, + -1, sz, sz, sz)) + { + snprintf (buf, sizeof buf, "__asan_stack_free_%d", + use_after_return_class); + ret = init_one_libfunc (buf); + rtx addr = convert_memory_address (ptr_mode, base); + rtx orig_addr = convert_memory_address (ptr_mode, orig_base); + emit_library_call (ret, LCT_NORMAL, ptr_mode, 3, addr, ptr_mode, + GEN_INT (asan_frame_size + base_align_bias), + TYPE_MODE (pointer_sized_int_node), + orig_addr, ptr_mode); + } + lab = gen_label_rtx (); + emit_jump (lab); + emit_label (lab2); + } + shadow_mem = gen_rtx_MEM (BLKmode, shadow_base); set_mem_alias_set (shadow_mem, asan_shadow_set); prev_offset = base_offset; @@ -1101,6 +1213,8 @@ asan_emit_stack_protection (rtx base, HOST_WIDE_INT *offsets, tree *decls, } do_pending_stack_adjust (); + if (lab) + emit_label (lab); ret = get_insns (); end_sequence (); @@ -1466,7 +1580,9 @@ instrument_derefs (gimple_stmt_iterator *iter, tree t, case COMPONENT_REF: case INDIRECT_REF: case MEM_REF: + case VAR_DECL: break; + /* FALLTHRU */ default: return; } @@ -1480,8 +1596,8 @@ instrument_derefs (gimple_stmt_iterator *iter, tree t, tree offset; enum machine_mode mode; int volatilep = 0, unsignedp = 0; - get_inner_reference (t, &bitsize, &bitpos, &offset, - &mode, &unsignedp, &volatilep, false); + tree inner = get_inner_reference (t, &bitsize, &bitpos, &offset, + &mode, &unsignedp, &volatilep, false); if (bitpos % (size_in_bytes * BITS_PER_UNIT) || bitsize != size_in_bytes * BITS_PER_UNIT) { @@ -1496,6 +1612,34 @@ instrument_derefs (gimple_stmt_iterator *iter, tree t, return; } + if (TREE_CODE (inner) == VAR_DECL + && offset == NULL_TREE + && bitpos >= 0 + && DECL_SIZE (inner) + && tree_fits_shwi_p (DECL_SIZE (inner)) + && bitpos + bitsize <= tree_to_shwi (DECL_SIZE (inner))) + { + if (DECL_THREAD_LOCAL_P (inner)) + return; + if (!TREE_STATIC (inner)) + { + /* Automatic vars in the current function will be always + accessible. */ + if (decl_function_context (inner) == current_function_decl) + return; + } + /* Always instrument external vars, they might be dynamically + initialized. */ + else if (!DECL_EXTERNAL (inner)) + { + /* For static vars if they are known not to be dynamically + initialized, they will be always accessible. */ + struct varpool_node *vnode = varpool_get_node (inner); + if (vnode && !vnode->dynamically_initialized) + return; + } + } + base = build_fold_addr_expr (t); if (!has_mem_ref_been_instrumented (base, size_in_bytes)) { @@ -1954,6 +2098,34 @@ transform_statements (void) } /* Build + __asan_before_dynamic_init (module_name) + or + __asan_after_dynamic_init () + call. */ + +tree +asan_dynamic_init_call (bool after_p) +{ + tree fn = builtin_decl_implicit (after_p + ? BUILT_IN_ASAN_AFTER_DYNAMIC_INIT + : BUILT_IN_ASAN_BEFORE_DYNAMIC_INIT); + tree module_name_cst = NULL_TREE; + if (!after_p) + { + pretty_printer module_name_pp; + pp_string (&module_name_pp, main_input_filename); + + if (shadow_ptr_types[0] == NULL_TREE) + asan_init_shadow_ptr_types (); + module_name_cst = asan_pp_string (&module_name_pp); + module_name_cst = fold_convert (const_ptr_type_node, + module_name_cst); + } + + return build_call_expr (fn, after_p ? 0 : 1, module_name_cst); +} + +/* Build struct __asan_global { const void *__beg; @@ -2042,7 +2214,10 @@ asan_add_global (tree decl, tree type, vec<constructor_elt, va_gc> *v) fold_convert (const_ptr_type_node, str_cst)); CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE, fold_convert (const_ptr_type_node, module_name_cst)); - CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE, build_int_cst (uptr, 0)); + struct varpool_node *vnode = varpool_get_node (decl); + int has_dynamic_init = vnode ? vnode->dynamically_initialized : 0; + CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE, + build_int_cst (uptr, has_dynamic_init)); init = build_constructor (type, vinner); CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init); } @@ -2059,6 +2234,8 @@ initialize_sanitizer_builtins (void) tree BT_FN_VOID = build_function_type_list (void_type_node, NULL_TREE); tree BT_FN_VOID_PTR = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE); + tree BT_FN_VOID_CONST_PTR + = build_function_type_list (void_type_node, const_ptr_type_node, NULL_TREE); tree BT_FN_VOID_PTR_PTR = build_function_type_list (void_type_node, ptr_type_node, ptr_type_node, NULL_TREE); diff --git a/gcc/asan.h b/gcc/asan.h index e56468424c9..42383c48525 100644 --- a/gcc/asan.h +++ b/gcc/asan.h @@ -23,9 +23,11 @@ along with GCC; see the file COPYING3. If not see extern void asan_function_start (void); extern void asan_finish_file (void); -extern rtx asan_emit_stack_protection (rtx, HOST_WIDE_INT *, tree *, int); +extern rtx asan_emit_stack_protection (rtx, rtx, unsigned int, HOST_WIDE_INT *, + tree *, int); extern bool asan_protect_global (tree); extern void initialize_sanitizer_builtins (void); +extern tree asan_dynamic_init_call (bool); /* Alias set for accessing the shadow memory. */ extern alias_set_type asan_shadow_set; @@ -48,8 +50,10 @@ extern alias_set_type asan_shadow_set; #define ASAN_STACK_MAGIC_MIDDLE 0xf2 #define ASAN_STACK_MAGIC_RIGHT 0xf3 #define ASAN_STACK_MAGIC_PARTIAL 0xf4 +#define ASAN_STACK_MAGIC_USE_AFTER_RET 0xf5 -#define ASAN_STACK_FRAME_MAGIC 0x41b58ab3 +#define ASAN_STACK_FRAME_MAGIC 0x41b58ab3 +#define ASAN_STACK_RETIRED_MAGIC 0x45e0360e /* Return true if DECL should be guarded on the stack. */ diff --git a/gcc/builtin-types.def b/gcc/builtin-types.def index e7bfaf943d4..e1054088cee 100644 --- a/gcc/builtin-types.def +++ b/gcc/builtin-types.def @@ -234,8 +234,6 @@ DEF_FUNCTION_TYPE_1 (BT_FN_UINT16_UINT16, BT_UINT16, BT_UINT16) DEF_FUNCTION_TYPE_1 (BT_FN_UINT32_UINT32, BT_UINT32, BT_UINT32) DEF_FUNCTION_TYPE_1 (BT_FN_UINT64_UINT64, BT_UINT64, BT_UINT64) DEF_FUNCTION_TYPE_1 (BT_FN_BOOL_INT, BT_BOOL, BT_INT) -DEF_FUNCTION_TYPE_1 (BT_FN_PTR_CONST_PTR, BT_PTR, BT_CONST_PTR) -DEF_FUNCTION_TYPE_1 (BT_FN_CONST_PTR_CONST_PTR, BT_CONST_PTR, BT_CONST_PTR) DEF_POINTER_TYPE (BT_PTR_FN_VOID_PTR, BT_FN_VOID_PTR) @@ -349,10 +347,6 @@ DEF_FUNCTION_TYPE_2 (BT_FN_BOOL_SIZE_CONST_VPTR, BT_BOOL, BT_SIZE, BT_CONST_VOLATILE_PTR) DEF_FUNCTION_TYPE_2 (BT_FN_BOOL_INT_BOOL, BT_BOOL, BT_INT, BT_BOOL) DEF_FUNCTION_TYPE_2 (BT_FN_VOID_UINT_UINT, BT_VOID, BT_UINT, BT_UINT) -DEF_FUNCTION_TYPE_2 (BT_FN_PTR_CONST_PTR_SIZE, BT_PTR, BT_CONST_PTR, BT_SIZE) -DEF_FUNCTION_TYPE_2 (BT_FN_PTR_CONST_PTR_CONST_PTR, BT_PTR, BT_CONST_PTR, BT_CONST_PTR) -DEF_FUNCTION_TYPE_2 (BT_FN_VOID_PTRPTR_CONST_PTR, BT_VOID, BT_PTR_PTR, BT_CONST_PTR) -DEF_FUNCTION_TYPE_2 (BT_FN_VOID_CONST_PTR_SIZE, BT_VOID, BT_CONST_PTR, BT_SIZE) DEF_POINTER_TYPE (BT_PTR_FN_VOID_PTR_PTR, BT_FN_VOID_PTR_PTR) @@ -435,7 +429,6 @@ DEF_FUNCTION_TYPE_3 (BT_FN_VOID_VPTR_I2_INT, BT_VOID, BT_VOLATILE_PTR, BT_I2, BT DEF_FUNCTION_TYPE_3 (BT_FN_VOID_VPTR_I4_INT, BT_VOID, BT_VOLATILE_PTR, BT_I4, BT_INT) DEF_FUNCTION_TYPE_3 (BT_FN_VOID_VPTR_I8_INT, BT_VOID, BT_VOLATILE_PTR, BT_I8, BT_INT) DEF_FUNCTION_TYPE_3 (BT_FN_VOID_VPTR_I16_INT, BT_VOID, BT_VOLATILE_PTR, BT_I16, BT_INT) -DEF_FUNCTION_TYPE_3 (BT_FN_PTR_CONST_PTR_CONST_PTR_SIZE, BT_PTR, BT_CONST_PTR, BT_CONST_PTR, BT_SIZE) DEF_FUNCTION_TYPE_4 (BT_FN_SIZE_CONST_PTR_SIZE_SIZE_FILEPTR, BT_SIZE, BT_CONST_PTR, BT_SIZE, BT_SIZE, BT_FILEPTR) @@ -542,8 +535,6 @@ DEF_FUNCTION_TYPE_VAR_1 (BT_FN_INT_CONST_STRING_VAR, BT_INT, BT_CONST_STRING) DEF_FUNCTION_TYPE_VAR_1 (BT_FN_UINT32_UINT32_VAR, BT_UINT32, BT_UINT32) -DEF_FUNCTION_TYPE_VAR_1 (BT_FN_PTR_CONST_PTR_VAR, - BT_PTR, BT_CONST_PTR) DEF_FUNCTION_TYPE_VAR_2 (BT_FN_INT_FILEPTR_CONST_STRING_VAR, BT_INT, BT_FILEPTR, BT_CONST_STRING) diff --git a/gcc/builtins.c b/gcc/builtins.c index ddca5471810..91a6beab89d 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -30,6 +30,11 @@ along with GCC; see the file COPYING3. If not see #include "varasm.h" #include "tree-object-size.h" #include "realmpfr.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "flags.h" #include "regs.h" @@ -47,7 +52,6 @@ along with GCC; see the file COPYING3. If not see #include "tm_p.h" #include "target.h" #include "langhooks.h" -#include "basic-block.h" #include "tree-ssanames.h" #include "tree-dfa.h" #include "value-prof.h" @@ -588,7 +592,7 @@ c_strlen (tree src, int only_value) && (only_value || !TREE_SIDE_EFFECTS (TREE_OPERAND (src, 0)))) return c_strlen (TREE_OPERAND (src, 1), only_value); - loc = EXPR_LOC_OR_HERE (src); + loc = EXPR_LOC_OR_LOC (src, input_location); src = string_constant (src, &offset_node); if (src == 0) @@ -3149,7 +3153,7 @@ determine_block_size (tree len, rtx len_rtx, } else if (range_type == VR_ANTI_RANGE) { - /* Anti range 0...N lets us to determine minmal size to N+1. */ + /* Anti range 0...N lets us to determine minimal size to N+1. */ if (min == 0) { if (wi::fits_uhwi_p (max) && max.to_uhwi () + 1 != 0) @@ -3159,7 +3163,7 @@ determine_block_size (tree len, rtx len_rtx, int n; if (n < 100) - memcpy (a,b, n) + memcpy (a, b, n) Produce anti range allowing negative values of N. We still can use the information and make a guess that N is not negative. @@ -5789,18 +5793,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, && fcode != BUILT_IN_EXECVE && fcode != BUILT_IN_ALLOCA && fcode != BUILT_IN_ALLOCA_WITH_ALIGN - && fcode != BUILT_IN_FREE - && fcode != BUILT_IN_CHKP_SET_PTR_BOUNDS - && fcode != BUILT_IN_CHKP_INIT_PTR_BOUNDS - && fcode != BUILT_IN_CHKP_NULL_PTR_BOUNDS - && fcode != BUILT_IN_CHKP_COPY_PTR_BOUNDS - && fcode != BUILT_IN_CHKP_NARROW_PTR_BOUNDS - && fcode != BUILT_IN_CHKP_STORE_PTR_BOUNDS - && fcode != BUILT_IN_CHKP_CHECK_PTR_LBOUNDS - && fcode != BUILT_IN_CHKP_CHECK_PTR_UBOUNDS - && fcode != BUILT_IN_CHKP_CHECK_PTR_BOUNDS - && fcode != BUILT_IN_CHKP_GET_PTR_LBOUND - && fcode != BUILT_IN_CHKP_GET_PTR_UBOUND) + && fcode != BUILT_IN_FREE) return expand_call (exp, target, ignore); /* The built-in function expanders test for target == const0_rtx @@ -6852,51 +6845,6 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, expand_builtin_cilk_pop_frame (exp); return const0_rtx; - case BUILT_IN_CHKP_INIT_PTR_BOUNDS: - case BUILT_IN_CHKP_NULL_PTR_BOUNDS: - case BUILT_IN_CHKP_COPY_PTR_BOUNDS: - return expand_normal (CALL_EXPR_ARG (exp, 0)); - - case BUILT_IN_CHKP_CHECK_PTR_LBOUNDS: - case BUILT_IN_CHKP_CHECK_PTR_UBOUNDS: - case BUILT_IN_CHKP_CHECK_PTR_BOUNDS: - case BUILT_IN_CHKP_SET_PTR_BOUNDS: - case BUILT_IN_CHKP_NARROW_PTR_BOUNDS: - case BUILT_IN_CHKP_STORE_PTR_BOUNDS: - case BUILT_IN_CHKP_GET_PTR_LBOUND: - case BUILT_IN_CHKP_GET_PTR_UBOUND: - /* We allow user CHKP builtins if Pointer Bounds - Checker is off. */ - if (!flag_check_pointer_bounds) - { - if (fcode == BUILT_IN_CHKP_SET_PTR_BOUNDS - || fcode == BUILT_IN_CHKP_NARROW_PTR_BOUNDS) - return expand_normal (CALL_EXPR_ARG (exp, 0)); - else if (fcode == BUILT_IN_CHKP_GET_PTR_LBOUND) - return expand_normal (size_zero_node); - else if (fcode == BUILT_IN_CHKP_GET_PTR_UBOUND) - return expand_normal (size_int (-1)); - else - return const0_rtx; - } - /* FALLTHROUGH */ - - case BUILT_IN_CHKP_BNDMK: - case BUILT_IN_CHKP_BNDSTX: - case BUILT_IN_CHKP_BNDCL: - case BUILT_IN_CHKP_BNDCU: - case BUILT_IN_CHKP_BNDLDX: - case BUILT_IN_CHKP_BNDRET: - case BUILT_IN_CHKP_INTERSECT: - case BUILT_IN_CHKP_ARG_BND: - case BUILT_IN_CHKP_NARROW: - case BUILT_IN_CHKP_EXTRACT_LOWER: - case BUILT_IN_CHKP_EXTRACT_UPPER: - /* Software implementation of pointers checker is NYI. - Target support is required. */ - error ("Your target platform does not support -fcheck-pointers"); - break; - default: /* just do library call, if unknown builtin */ break; } diff --git a/gcc/builtins.def b/gcc/builtins.def index 3082548731d..3e3deaa5780 100644 --- a/gcc/builtins.def +++ b/gcc/builtins.def @@ -176,12 +176,6 @@ along with GCC; see the file COPYING3. If not see DEF_BUILTIN (ENUM, NAME, BUILT_IN_NORMAL, BT_FN_INT_VAR, BT_LAST, \ false, false, false, ATTRS, false, flag_enable_cilkplus) -/* Builtin used by the implementation of Pointer Bounds Checker. */ -#undef DEF_CHKP_BUILTIN -#define DEF_CHKP_BUILTIN(ENUM, NAME, TYPE, ATTRS) \ - DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \ - true, true, false, ATTRS, true, true) - /* Define an attribute list for math functions that are normally "impure" because some of them may write into global memory for `errno'. If !flag_errno_math they are instead "const". */ @@ -876,6 +870,3 @@ DEF_GCC_BUILTIN (BUILT_IN_LINE, "LINE", BT_FN_INT, ATTR_NOTHROW_LEAF_LIST) /* Cilk Plus builtins. */ #include "cilkplus.def" - -/* Pointer Bounds Checker builtins. */ -#include "chkp-builtins.def" diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 4c5c153943e..616a74209c0 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,45 @@ +2013-11-29 H.J. Lu <hongjiu.lu@intel.com> + + PR c/59309 + * cilk.c (gimplify_cilk_spawn): Properly handle function without + arguments. + +2013-11-29 Jakub Jelinek <jakub@redhat.com> + + PR c/59280 + * c-common.c (get_priority): If TREE_VALUE (args) is IDENTIFIER_NODE, + goto invalid. If it is error_mark_node, don't issue further + diagnostics. + +2013-11-28 Sergey Ostanevich <sergos.gnu@gmail.com> + + * c.opt (Wopenmp-simd): New. + +2013-11-22 Jakub Jelinek <jakub@redhat.com> + + * c-ubsan.h (ubsan_instrument_return): New prototype. + * c-ubsan.c (ubsan_instrument_return): New function. + +2013-11-22 Andrew MacLeod <amacleod@redhat.com> + + * c-common.c: Add required include files from gimple.h. + * c-gimplify.c: Likewise + * cilk.c: Likewise + +2013-11-22 David Malcolm <dmalcolm@redhat.com> + + * c-common.c (unsafe_conversion_p): Remove use of + EXPR_LOC_OR_HERE macro. + (conversion_warning): Likewise. + (warnings_for_convert_and_check): Likewise. + (warn_for_collisions_1): Likewise. + (shorten_compare): Likewise, and remove use of in_system_header + macro, using the location from the former. + * c-lex.c (dump_one_header): Remove use of input_filename macro. + (cb_def_pragma): Remove use of in_system_header macro. + (lex_string): Likewise. + * c-pragma.c (handle_pragma_float_const_decimal64): Likewise. + 2013-11-20 Kenneth Zadeck <zadeck@naturalbridge.com> Mike Stump <mikestump@comcast.net> Richard Sandiford <rdsandiford@googlemail.com> diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index e5e93894a84..c0fc8bea293 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -32,7 +32,6 @@ along with GCC; see the file COPYING3. If not see #include "trans-mem.h" #include "flags.h" #include "c-pragma.h" -#include "ggc.h" #include "c-common.h" #include "c-objc.h" #include "tm_p.h" @@ -49,7 +48,6 @@ along with GCC; see the file COPYING3. If not see #include "opts.h" #include "cgraph.h" #include "target-def.h" -#include "gimple.h" #include "gimplify.h" #include "wide-int-print.h" @@ -385,8 +383,6 @@ static tree handle_omp_declare_simd_attribute (tree *, tree, tree, int, bool *); static tree handle_omp_declare_target_attribute (tree *, tree, tree, int, bool *); -static tree handle_bnd_variable_size_attribute (tree *, tree, tree, int, bool *); -static tree handle_bnd_legacy (tree *, tree, tree, int, bool *); static void check_function_nonnull (tree, int, tree *); static void check_nonnull_arg (void *, tree, unsigned HOST_WIDE_INT); @@ -774,10 +770,6 @@ const struct attribute_spec c_common_attribute_table[] = handle_omp_declare_simd_attribute, false }, { "omp declare target", 0, 0, true, false, false, handle_omp_declare_target_attribute, false }, - { "bnd_variable_size", 0, 0, true, false, false, - handle_bnd_variable_size_attribute, false }, - { "bnd_legacy", 0, 0, true, false, false, - handle_bnd_legacy, false }, { NULL, 0, 0, false, false, false, NULL, false } }; @@ -2553,7 +2545,7 @@ unsafe_conversion_p (tree type, tree expr, bool produce_warns) { enum conversion_safety give_warning = SAFE_CONVERSION; /* is 0 or false */ tree expr_type = TREE_TYPE (expr); - location_t loc = EXPR_LOC_OR_HERE (expr); + location_t loc = EXPR_LOC_OR_LOC (expr, input_location); if (TREE_CODE (expr) == REAL_CST || TREE_CODE (expr) == INTEGER_CST) { @@ -2719,7 +2711,7 @@ static void conversion_warning (tree type, tree expr) { tree expr_type = TREE_TYPE (expr); - location_t loc = EXPR_LOC_OR_HERE (expr); + location_t loc = EXPR_LOC_OR_LOC (expr, input_location); enum conversion_safety conversion_kind; if (!warn_conversion && !warn_sign_conversion && !warn_float_conversion) @@ -2792,7 +2784,7 @@ conversion_warning (tree type, tree expr) void warnings_for_convert_and_check (tree type, tree expr, tree result) { - location_t loc = EXPR_LOC_OR_HERE (expr); + location_t loc = EXPR_LOC_OR_LOC (expr, input_location); if (TREE_CODE (expr) == INTEGER_CST && (TREE_CODE (type) == INTEGER_TYPE @@ -3002,7 +2994,7 @@ warn_for_collisions_1 (tree written, tree writer, struct tlist *list, && (!only_writes || list->writer)) { warned_ids = new_tlist (warned_ids, written, NULL_TREE); - warning_at (EXPR_LOC_OR_HERE (writer), + warning_at (EXPR_LOC_OR_LOC (writer, input_location), OPT_Wsequence_point, "operation on %qE may be undefined", list->expr); } @@ -4000,7 +3992,7 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr, int real1, real2; tree primop0, primop1; enum tree_code code = *rescode_ptr; - location_t loc = EXPR_LOC_OR_HERE (op0); + location_t loc = EXPR_LOC_OR_LOC (op0, input_location); /* Throw away any conversions to wider types already present in the operands. */ @@ -4291,7 +4283,7 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr, the comparison isn't an issue, so suppress the warning. */ bool warn = - warn_type_limits && !in_system_header + warn_type_limits && !in_system_header_at (loc) && c_inhibit_evaluation_warnings == 0 && !(TREE_CODE (primop0) == INTEGER_CST && !TREE_OVERFLOW (convert (c_common_signed_type (type), @@ -7001,6 +6993,10 @@ get_priority (tree args, bool is_destructor) } arg = TREE_VALUE (args); + if (TREE_CODE (arg) == IDENTIFIER_NODE) + goto invalid; + if (arg == error_mark_node) + return DEFAULT_INIT_PRIORITY; arg = default_conversion (arg); if (!tree_fits_shwi_p (arg) || !INTEGRAL_TYPE_P (TREE_TYPE (arg))) @@ -8031,38 +8027,6 @@ handle_fnspec_attribute (tree *node ATTRIBUTE_UNUSED, tree ARG_UNUSED (name), return NULL_TREE; } -/* Handle a "bnd_variable_size" attribute; arguments as in - struct attribute_spec.handler. */ - -static tree -handle_bnd_variable_size_attribute (tree *node, tree name, tree ARG_UNUSED (args), - int ARG_UNUSED (flags), bool *no_add_attrs) -{ - if (TREE_CODE (*node) != FIELD_DECL) - { - warning (OPT_Wattributes, "%qE attribute ignored", name); - *no_add_attrs = true; - } - - return NULL_TREE; -} - -/* Handle a "bnd_legacy" attribute; arguments as in - struct attribute_spec.handler. */ - -static tree -handle_bnd_legacy (tree *node, tree name, tree ARG_UNUSED (args), - int ARG_UNUSED (flags), bool *no_add_attrs) -{ - if (TREE_CODE (*node) != FUNCTION_DECL) - { - warning (OPT_Wattributes, "%qE attribute ignored", name); - *no_add_attrs = true; - } - - return NULL_TREE; -} - /* Handle a "warn_unused" attribute; arguments as in struct attribute_spec.handler. */ diff --git a/gcc/c-family/c-gimplify.c b/gcc/c-family/c-gimplify.c index d3c304e1137..d047c65b4ee 100644 --- a/gcc/c-family/c-gimplify.c +++ b/gcc/c-family/c-gimplify.c @@ -29,6 +29,11 @@ along with GCC; see the file COPYING3. If not see #include "tm.h" #include "tree.h" #include "c-common.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "tree-inline.h" diff --git a/gcc/c-family/c-lex.c b/gcc/c-family/c-lex.c index 4594a5ac1b9..0c6027e864e 100644 --- a/gcc/c-family/c-lex.c +++ b/gcc/c-family/c-lex.c @@ -148,7 +148,7 @@ dump_one_header (splay_tree_node n, void * ARG_UNUSED (dummy)) void dump_time_statistics (void) { - struct c_fileinfo *file = get_fileinfo (input_filename); + struct c_fileinfo *file = get_fileinfo (LOCATION_FILE (input_location)); int this_time = get_run_time (); file->time += this_time - body_time; @@ -244,7 +244,7 @@ cb_def_pragma (cpp_reader *pfile, source_location loc) /* Issue a warning message if we have been asked to do so. Ignore unknown pragmas in system headers unless an explicit -Wunknown-pragmas has been given. */ - if (warn_unknown_pragmas > in_system_header) + if (warn_unknown_pragmas > in_system_header_at (input_location)) { const unsigned char *space, *name; const cpp_token *s; @@ -1070,7 +1070,7 @@ lex_string (const cpp_token *tok, tree *valp, bool objc_string, bool translate) if (concats) strs = XOBFINISH (&str_ob, cpp_string *); - if (concats && !objc_string && !in_system_header) + if (concats && !objc_string && !in_system_header_at (input_location)) warning (OPT_Wtraditional, "traditional C rejects string constant concatenation"); diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c index 70fb39ae9cf..64a5b667499 100644 --- a/gcc/c-family/c-pragma.c +++ b/gcc/c-family/c-pragma.c @@ -1121,7 +1121,7 @@ handle_pragma_float_const_decimal64 (cpp_reader *ARG_UNUSED (dummy)) { if (c_dialect_cxx ()) { - if (warn_unknown_pragmas > in_system_header) + if (warn_unknown_pragmas > in_system_header_at (input_location)) warning (OPT_Wunknown_pragmas, "%<#pragma STDC FLOAT_CONST_DECIMAL64%> is not supported" " for C++"); @@ -1130,7 +1130,7 @@ handle_pragma_float_const_decimal64 (cpp_reader *ARG_UNUSED (dummy)) if (!targetm.decimal_float_supported_p ()) { - if (warn_unknown_pragmas > in_system_header) + if (warn_unknown_pragmas > in_system_header_at (input_location)) warning (OPT_Wunknown_pragmas, "%<#pragma STDC FLOAT_CONST_DECIMAL64%> is not supported" " on this target"); diff --git a/gcc/c-family/c-ubsan.c b/gcc/c-family/c-ubsan.c index 7a09e7b9596..a2769352be4 100644 --- a/gcc/c-family/c-ubsan.c +++ b/gcc/c-family/c-ubsan.c @@ -179,3 +179,14 @@ ubsan_instrument_vla (location_t loc, tree size) return t; } + +/* Instrument missing return in C++ functions returning non-void. */ + +tree +ubsan_instrument_return (location_t loc) +{ + tree data = ubsan_create_data ("__ubsan_missing_return_data", loc, + NULL, NULL_TREE); + tree t = builtin_decl_explicit (BUILT_IN_UBSAN_HANDLE_MISSING_RETURN); + return build_call_expr_loc (loc, t, 1, build_fold_addr_expr_loc (loc, data)); +} diff --git a/gcc/c-family/c-ubsan.h b/gcc/c-family/c-ubsan.h index fdf27d9e21e..9b91bad8cdc 100644 --- a/gcc/c-family/c-ubsan.h +++ b/gcc/c-family/c-ubsan.h @@ -24,5 +24,6 @@ along with GCC; see the file COPYING3. If not see extern tree ubsan_instrument_division (location_t, tree, tree); extern tree ubsan_instrument_shift (location_t, enum tree_code, tree, tree); extern tree ubsan_instrument_vla (location_t, tree); +extern tree ubsan_instrument_return (location_t); #endif /* GCC_C_UBSAN_H */ diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index ac678855414..bfca1e0e6f6 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -596,6 +596,10 @@ Wold-style-definition C ObjC Var(warn_old_style_definition) Warning Warn if an old-style parameter definition is used +Wopenmp-simd +C C++ Var(warn_openmp_simd) Warning LangEnabledBy(C C++,Wall) +Warn if a simd directive is overridden by the vectorizer cost model + Woverlength-strings C ObjC C++ ObjC++ Var(warn_overlength_strings) Warning LangEnabledBy(C ObjC C++ ObjC++,Wpedantic) Warn if a string is longer than the maximum portable length specified by the standard @@ -858,11 +862,6 @@ fcanonical-system-headers C ObjC C++ ObjC++ Where shorter, use canonicalized paths to systems headers. -fcheck-pointer-bounds -C ObjC C++ ObjC++ LTO Report Var(flag_check_pointer_bounds) -Add Pointer Bounds Checker instrumentation. fchkp-* flags are used to -control instrumentation. - fcilkplus C ObjC C++ ObjC++ LTO Report Var(flag_enable_cilkplus) Init(0) Enable Cilk Plus diff --git a/gcc/c-family/cilk.c b/gcc/c-family/cilk.c index a663c457302..ab3f121f601 100644 --- a/gcc/c-family/cilk.c +++ b/gcc/c-family/cilk.c @@ -27,7 +27,8 @@ along with GCC; see the file COPYING3. If not see #include "stringpool.h" #include "calls.h" #include "langhooks.h" -#include "gimple.h" +#include "pointer-set.h" +#include "gimple-expr.h" #include "gimplify.h" #include "tree-iterator.h" #include "tree-inline.h" @@ -755,7 +756,10 @@ gimplify_cilk_spawn (tree *spawn_p, gimple_seq *before ATTRIBUTE_UNUSED, /* This should give the number of parameters. */ total_args = list_length (new_args); - arg_array = XNEWVEC (tree, total_args); + if (total_args) + arg_array = XNEWVEC (tree, total_args); + else + arg_array = NULL; ii_args = new_args; for (ii = 0; ii < total_args; ii++) @@ -769,7 +773,7 @@ gimplify_cilk_spawn (tree *spawn_p, gimple_seq *before ATTRIBUTE_UNUSED, call1 = cilk_call_setjmp (cfun->cilk_frame_decl); - if (*arg_array == NULL_TREE) + if (arg_array == NULL || *arg_array == NULL_TREE) call2 = build_call_expr (function, 0); else call2 = build_call_expr_loc_array (EXPR_LOCATION (*spawn_p), function, diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 92dbcee4809..b97e65ec249 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,68 @@ +2013-12-03 Marek Polacek <polacek@redhat.com> + + PR c/59351 + * c-decl.c (build_compound_literal): Allow compound literals with + empty initial value. + +2013-12-02 Joseph Myers <joseph@codesourcery.com> + + PR c/58235 + * c-typeck.c (build_modify_expr): Diagnose assignment to + expression with array type. + +2013-11-29 Joseph Myers <joseph@codesourcery.com> + + PR c/42262 + * c-typeck.c (process_init_element): Do not treat a string as + initializing a whole array when used with a designator for an + individual element. + +2013-11-29 Joseph Myers <joseph@codesourcery.com> + + PR c/57574 + * c-decl.c (merge_decls): Clear DECL_EXTERNAL for a definition of + an inline function following a static declaration. + +2013-11-28 Jakub Jelinek <jakub@redhat.com> + + PR c/59310 + * c-parser.c (c_parser_omp_target): Copy "#pragma omp target" + to p_name before calling c_parser_omp_teams instead of after. + (c_parser_cilk_simd): Remove wrong ATTRIBUTE_UNUSED from parser + argument. Remove unused p_name variable. + +2013-11-27 Aldy Hernandez <aldyh@redhat.com> + Jakub Jelinek <jakub@redhat.com> + + * c-decl.c (c_builtin_function_ext_scope): Avoid binding if + external_scope is NULL. + +2013-11-27 Tom de Vries <tom@codesourcery.com> + Marc Glisse <marc.glisse@inria.fr> + + PR c++/59032 + * c-typeck.c (build_unary_op): Allow vector increment and decrement. + +2013-11-22 Andrew MacLeod <amacleod@redhat.com> + + * c-typeck.c: Add required include files from gimple.h. + +2013-11-22 David Malcolm <dmalcolm@redhat.com> + + * c-decl.c (define_label, shadow_tag_warned) + (check_bitfield_type_and_width, grokdeclarator, grokparms, + store_parm_decls_newstyle, store_parm_decls_oldstyle) + (declspecs_add_type): Remove use of in_system_header macro. + * c-parser.c (c_parser_unary_expression): Likewise. + * c-typeck.c (store_init_value, process_init_element) + (c_start_case): Likewise. + + * c-decl.c (build_enumerator): Remove use of EXPR_LOC_OR_HERE + macro. + + * c-parser.c (c_parser_set_source_position_from_token): Remove + reference to in_system_header from comment. + 2013-11-18 Richard Sandiford <rdsandiford@googlemail.com> * c-decl.c (grokdeclarator): Update comment to refer to diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index d2d54b0079d..d31361b33a3 100644 --- a/gcc/c/c-decl.c +++ b/gcc/c/c-decl.c @@ -2343,6 +2343,14 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype) && !current_function_decl) DECL_EXTERNAL (newdecl) = 0; + /* An inline definition following a static declaration is not + DECL_EXTERNAL. */ + if (new_is_definition + && (DECL_DECLARED_INLINE_P (newdecl) + || DECL_DECLARED_INLINE_P (olddecl)) + && !TREE_PUBLIC (olddecl)) + DECL_EXTERNAL (newdecl) = 0; + if (DECL_EXTERNAL (newdecl)) { TREE_STATIC (newdecl) = TREE_STATIC (olddecl); @@ -3328,7 +3336,7 @@ define_label (location_t location, tree name) bind_label (name, label, current_function_scope, label_vars); } - if (!in_system_header && lookup_name (name)) + if (!in_system_header_at (input_location) && lookup_name (name)) warning_at (location, OPT_Wtraditional, "traditional C lacks a separate namespace " "for labels, identifier %qE conflicts", name); @@ -3646,8 +3654,9 @@ c_builtin_function_ext_scope (tree decl) const char *name = IDENTIFIER_POINTER (id); C_DECL_BUILTIN_PROTOTYPE (decl) = prototype_p (type); - bind (id, decl, external_scope, /*invisible=*/false, /*nested=*/false, - UNKNOWN_LOCATION); + if (external_scope) + bind (id, decl, external_scope, /*invisible=*/false, /*nested=*/false, + UNKNOWN_LOCATION); /* Builtins in the implementation namespace are made visible without needing to be explicitly declared. See push_file_scope. */ @@ -3762,7 +3771,7 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned) } else { - if (warned != 1 && !in_system_header) + if (warned != 1 && !in_system_header_at (input_location)) { pedwarn (input_location, 0, "useless type name in empty declaration"); @@ -3770,7 +3779,8 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned) } } } - else if (warned != 1 && !in_system_header && declspecs->typedef_p) + else if (warned != 1 && !in_system_header_at (input_location) + && declspecs->typedef_p) { pedwarn (input_location, 0, "useless type name in empty declaration"); warned = 1; @@ -3802,30 +3812,34 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned) warned = 1; } - if (!warned && !in_system_header && declspecs->storage_class != csc_none) + if (!warned && !in_system_header_at (input_location) + && declspecs->storage_class != csc_none) { warning (0, "useless storage class specifier in empty declaration"); warned = 2; } - if (!warned && !in_system_header && declspecs->thread_p) + if (!warned && !in_system_header_at (input_location) && declspecs->thread_p) { warning (0, "useless %qs in empty declaration", declspecs->thread_gnu_p ? "__thread" : "_Thread_local"); warned = 2; } - if (!warned && !in_system_header && (declspecs->const_p - || declspecs->volatile_p - || declspecs->atomic_p - || declspecs->restrict_p - || declspecs->address_space)) + if (!warned + && !in_system_header_at (input_location) + && (declspecs->const_p + || declspecs->volatile_p + || declspecs->atomic_p + || declspecs->restrict_p + || declspecs->address_space)) { warning (0, "useless type qualifier in empty declaration"); warned = 2; } - if (!warned && !in_system_header && declspecs->alignas_p) + if (!warned && !in_system_header_at (input_location) + && declspecs->alignas_p) { warning (0, "useless %<_Alignas%> in empty declaration"); warned = 2; @@ -4679,7 +4693,9 @@ build_compound_literal (location_t loc, tree type, tree init, bool non_const) { int failure = complete_array_type (&TREE_TYPE (decl), DECL_INITIAL (decl), true); - gcc_assert (!failure); + /* If complete_array_type returns 3, it means that the + initial value of the compound literal is empty. Allow it. */ + gcc_assert (failure == 0 || failure == 3); type = TREE_TYPE (decl); TREE_TYPE (DECL_INITIAL (decl)) = type; @@ -4821,7 +4837,7 @@ check_bitfield_type_and_width (tree *type, tree *width, tree orig_name) } type_mv = TYPE_MAIN_VARIANT (*type); - if (!in_system_header + if (!in_system_header_at (input_location) && type_mv != integer_type_node && type_mv != unsigned_type_node && type_mv != boolean_type_node) @@ -5071,7 +5087,7 @@ grokdeclarator (const struct c_declarator *declarator, /* Diagnose defaulting to "int". */ - if (declspecs->default_int_p && !in_system_header) + if (declspecs->default_int_p && !in_system_header_at (input_location)) { /* Issue a warning if this is an ISO C 99 program or if -Wreturn-type and this is a function, or if -Wimplicit; @@ -5351,7 +5367,8 @@ grokdeclarator (const struct c_declarator *declarator, type = error_mark_node; } - if (pedantic && !in_system_header && flexible_array_type_p (type)) + if (pedantic && !in_system_header_at (input_location) + && flexible_array_type_p (type)) pedwarn (loc, OPT_Wpedantic, "invalid use of structure with flexible array member"); @@ -5529,7 +5546,8 @@ grokdeclarator (const struct c_declarator *declarator, flexible_array_member = (t->kind == cdk_id); } if (flexible_array_member - && pedantic && !flag_isoc99 && !in_system_header) + && pedantic && !flag_isoc99 + && !in_system_header_at (input_location)) pedwarn (loc, OPT_Wpedantic, "ISO C90 does not support flexible array members"); @@ -6383,7 +6401,8 @@ grokparms (struct c_arg_info *arg_info, bool funcdef_flag) error ("%<[*]%> not allowed in other than function prototype scope"); } - if (arg_types == 0 && !funcdef_flag && !in_system_header) + if (arg_types == 0 && !funcdef_flag + && !in_system_header_at (input_location)) warning (OPT_Wstrict_prototypes, "function declaration isn%'t a prototype"); @@ -7783,7 +7802,7 @@ build_enumerator (location_t decl_loc, location_t loc, /* Set basis for default for next value. */ the_enum->enum_next_value - = build_binary_op (EXPR_LOC_OR_HERE (value), + = build_binary_op (EXPR_LOC_OR_LOC (value, input_location), PLUS_EXPR, value, integer_one_node, 0); the_enum->enum_overflow = tree_int_cst_lt (the_enum->enum_next_value, value); @@ -8057,7 +8076,8 @@ store_parm_decls_newstyle (tree fndecl, const struct c_arg_info *arg_info) warning if we got here because ARG_INFO_TYPES was error_mark_node (this happens when a function definition has just an ellipsis in its parameter list). */ - else if (!in_system_header && !current_function_scope + else if (!in_system_header_at (input_location) + && !current_function_scope && arg_info->types != error_mark_node) warning_at (DECL_SOURCE_LOCATION (fndecl), OPT_Wtraditional, "traditional C rejects ISO C style function definitions"); @@ -8111,7 +8131,7 @@ store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info) tree parmids = arg_info->parms; struct pointer_set_t *seen_args = pointer_set_create (); - if (!in_system_header) + if (!in_system_header_at (input_location)) warning_at (DECL_SOURCE_LOCATION (fndecl), OPT_Wold_style_definition, "old-style function definition"); @@ -9469,7 +9489,7 @@ declspecs_add_type (location_t loc, struct c_declspecs *specs, error_at (loc, "%<__int128%> is not supported for this target"); return specs; } - if (!in_system_header) + if (!in_system_header_at (input_location)) pedwarn (loc, OPT_Wpedantic, "ISO C does not support %<__int128%> type"); diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index d08d1d0bcf1..fb3b01cd4a2 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -775,8 +775,7 @@ c_parser_consume_pragma (c_parser *parser) parser->in_pragma = true; } -/* Update the globals input_location and in_system_header from - TOKEN. */ +/* Update the global input_location from TOKEN. */ static inline void c_parser_set_source_position_from_token (c_token *token) { @@ -6301,7 +6300,7 @@ c_parser_unary_expression (c_parser *parser) ret.value = build_indirect_ref (op_loc, op.value, RO_UNARY_STAR); return ret; case CPP_PLUS: - if (!c_dialect_objc () && !in_system_header) + if (!c_dialect_objc () && !in_system_header_at (input_location)) warning_at (op_loc, OPT_Wtraditional, "traditional C rejects the unary plus operator"); @@ -12530,10 +12529,10 @@ c_parser_omp_target (c_parser *parser, enum pragma_context context) "parallel for simd")]; c_parser_consume_token (parser); + strcpy (p_name, "#pragma omp target"); if (!flag_openmp) /* flag_openmp_simd */ return c_parser_omp_teams (loc, parser, p_name, OMP_TARGET_CLAUSE_MASK, cclauses); - strcpy (p_name, "#pragma omp target"); keep_next_level (); tree block = c_begin_compound_stmt (true); tree ret = c_parser_omp_teams (loc, parser, p_name, @@ -13567,10 +13566,8 @@ c_parser_cilk_all_clauses (c_parser *parser) loops. */ static void -c_parser_cilk_simd (c_parser *parser ATTRIBUTE_UNUSED) +c_parser_cilk_simd (c_parser *parser) { - char p_name[100]; - strcpy (p_name, "#pragma omp"); tree clauses = c_parser_cilk_all_clauses (parser); tree block = c_begin_compound_stmt (true); location_t loc = c_parser_peek_token (parser)->location; diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index 7a0d664cc86..d3753fbcca6 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -40,7 +40,9 @@ along with GCC; see the file COPYING3. If not see #include "target.h" #include "tree-iterator.h" #include "bitmap.h" -#include "gimple.h" +#include "pointer-set.h" +#include "basic-block.h" +#include "gimple-expr.h" #include "gimplify.h" #include "tree-inline.h" #include "omp-low.h" @@ -3981,7 +3983,7 @@ build_unary_op (location_t location, if (typecode != POINTER_TYPE && typecode != FIXED_POINT_TYPE && typecode != INTEGER_TYPE && typecode != REAL_TYPE - && typecode != COMPLEX_TYPE) + && typecode != COMPLEX_TYPE && typecode != VECTOR_TYPE) { if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR) error_at (location, "wrong type argument to increment"); @@ -4046,7 +4048,9 @@ build_unary_op (location_t location, } else { - inc = integer_one_node; + inc = VECTOR_TYPE_P (argtype) + ? build_one_cst (argtype) + : integer_one_node; inc = convert (argtype, inc); } @@ -5200,6 +5204,14 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype, if (TREE_CODE (lhs) == ERROR_MARK || TREE_CODE (rhs) == ERROR_MARK) return error_mark_node; + /* Ensure an error for assigning a non-lvalue array to an array in + C90. */ + if (TREE_CODE (lhstype) == ARRAY_TYPE) + { + error_at (location, "assignment to expression with array type"); + return error_mark_node; + } + /* For ObjC properties, defer this check. */ if (!objc_is_property_ref (lhs) && !lvalue_or_else (location, lhs, lv_assign)) return error_mark_node; @@ -6184,7 +6196,7 @@ store_init_value (location_t init_loc, tree decl, tree init, tree origtype) /* Store the expression if valid; else report error. */ - if (!in_system_header + if (!in_system_header_at (input_location) && AGGREGATE_TYPE_P (TREE_TYPE (decl)) && !TREE_STATIC (decl)) warning (OPT_Wtraditional, "traditional C rejects automatic " "aggregate initialization"); @@ -8501,6 +8513,7 @@ process_init_element (struct c_expr value, bool implicit, tree orig_value = value.value; int string_flag = orig_value != 0 && TREE_CODE (orig_value) == STRING_CST; bool strict_string = value.original_code == STRING_CST; + bool was_designated = designator_depth != 0; designator_depth = 0; designator_erroneous = 0; @@ -8509,6 +8522,7 @@ process_init_element (struct c_expr value, bool implicit, char x[] = {"foo"}; */ if (string_flag && constructor_type + && !was_designated && TREE_CODE (constructor_type) == ARRAY_TYPE && INTEGRAL_TYPE_P (TREE_TYPE (constructor_type)) && integer_zerop (constructor_unfilled_index)) @@ -8687,7 +8701,7 @@ process_init_element (struct c_expr value, bool implicit, again on the assumption that this must be conditional on __STDC__ anyway (and we've already complained about the member-designator already). */ - if (!in_system_header && !constructor_designated + if (!in_system_header_at (input_location) && !constructor_designated && !(value.value && (integer_zerop (value.value) || real_zerop (value.value)))) warning (OPT_Wtraditional, "traditional C rejects initialization " @@ -9288,7 +9302,7 @@ c_start_case (location_t switch_loc, { tree type = TYPE_MAIN_VARIANT (orig_type); - if (!in_system_header + if (!in_system_header_at (input_location) && (type == long_integer_type_node || type == long_unsigned_type_node)) warning_at (switch_cond_loc, diff --git a/gcc/calls.c b/gcc/calls.c index 726ba23c3fc..3963bc29754 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -27,6 +27,11 @@ along with GCC; see the file COPYING3. If not see #include "varasm.h" #include "stringpool.h" #include "attribs.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "flags.h" #include "expr.h" @@ -2667,8 +2672,7 @@ expand_call (tree exp, rtx target, int ignore) recursion "call". That way we know any adjustment after the tail recursion call can be ignored if we indeed use the tail call expansion. */ - int save_pending_stack_adjust = 0; - int save_stack_pointer_delta = 0; + saved_pending_stack_adjust save; rtx insns; rtx before_call, next_arg_reg, after_args; @@ -2676,8 +2680,7 @@ expand_call (tree exp, rtx target, int ignore) { /* State variables we need to save and restore between iterations. */ - save_pending_stack_adjust = pending_stack_adjust; - save_stack_pointer_delta = stack_pointer_delta; + save_pending_stack_adjust (&save); } if (pass) flags &= ~ECF_SIBCALL; @@ -3042,6 +3045,15 @@ expand_call (tree exp, rtx target, int ignore) { rtx before_arg = get_last_insn (); + /* We don't allow passing huge (> 2^30 B) arguments + by value. It would cause an overflow later on. */ + if (adjusted_args_size.constant + >= (1 << (HOST_BITS_PER_INT - 2))) + { + sorry ("passing too large argument on stack"); + continue; + } + if (store_one_arg (&args[i], argblock, flags, adjusted_args_size.var != 0, reg_parm_stack_space) @@ -3433,8 +3445,7 @@ expand_call (tree exp, rtx target, int ignore) /* Restore the pending stack adjustment now that we have finished generating the sibling call sequence. */ - pending_stack_adjust = save_pending_stack_adjust; - stack_pointer_delta = save_stack_pointer_delta; + restore_pending_stack_adjust (&save); /* Prepare arg structure for next iteration. */ for (i = 0; i < num_actuals; i++) diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c index d431c8dea5e..853ace2c2a1 100644 --- a/gcc/cfgexpand.c +++ b/gcc/cfgexpand.c @@ -35,6 +35,12 @@ along with GCC; see the file COPYING3. If not see #include "expr.h" #include "langhooks.h" #include "bitmap.h" +#include "pointer-set.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimple-walk.h" @@ -884,6 +890,12 @@ struct stack_vars_data /* Vector of partition representative decls in between the paddings. */ vec<tree> asan_decl_vec; + + /* Base pseudo register for Address Sanitizer protected automatic vars. */ + rtx asan_base; + + /* Alignment needed for the Address Sanitizer protected automatic vars. */ + unsigned int asan_alignb; }; /* A subroutine of expand_used_vars. Give each partition representative @@ -968,6 +980,7 @@ expand_stack_vars (bool (*pred) (size_t), struct stack_vars_data *data) alignb = stack_vars[i].alignb; if (alignb * BITS_PER_UNIT <= MAX_SUPPORTED_STACK_ALIGNMENT) { + base = virtual_stack_vars_rtx; if ((flag_sanitize & SANITIZE_ADDRESS) && pred) { HOST_WIDE_INT prev_offset = frame_offset; @@ -996,10 +1009,13 @@ expand_stack_vars (bool (*pred) (size_t), struct stack_vars_data *data) if (repr_decl == NULL_TREE) repr_decl = stack_vars[i].decl; data->asan_decl_vec.safe_push (repr_decl); + data->asan_alignb = MAX (data->asan_alignb, alignb); + if (data->asan_base == NULL) + data->asan_base = gen_reg_rtx (Pmode); + base = data->asan_base; } else offset = alloc_stack_frame_space (stack_vars[i].size, alignb); - base = virtual_stack_vars_rtx; base_align = crtl->max_used_stack_slot_alignment; } else @@ -1786,6 +1802,8 @@ expand_used_vars (void) data.asan_vec = vNULL; data.asan_decl_vec = vNULL; + data.asan_base = NULL_RTX; + data.asan_alignb = 0; /* Reorder decls to be protected by iterating over the variables array multiple times, and allocating out of each phase in turn. */ @@ -1810,16 +1828,25 @@ expand_used_vars (void) if (!data.asan_vec.is_empty ()) { HOST_WIDE_INT prev_offset = frame_offset; - HOST_WIDE_INT offset - = alloc_stack_frame_space (ASAN_RED_ZONE_SIZE, - ASAN_RED_ZONE_SIZE); + HOST_WIDE_INT offset, sz, redzonesz; + redzonesz = ASAN_RED_ZONE_SIZE; + sz = data.asan_vec[0] - prev_offset; + if (data.asan_alignb > ASAN_RED_ZONE_SIZE + && data.asan_alignb <= 4096 + && sz + ASAN_RED_ZONE_SIZE >= (int) data.asan_alignb) + redzonesz = ((sz + ASAN_RED_ZONE_SIZE + data.asan_alignb - 1) + & ~(data.asan_alignb - HOST_WIDE_INT_1)) - sz; + offset + = alloc_stack_frame_space (redzonesz, ASAN_RED_ZONE_SIZE); data.asan_vec.safe_push (prev_offset); data.asan_vec.safe_push (offset); var_end_seq = asan_emit_stack_protection (virtual_stack_vars_rtx, + data.asan_base, + data.asan_alignb, data.asan_vec.address (), - data.asan_decl_vec. address (), + data.asan_decl_vec.address (), data.asan_vec.length ()); } @@ -2159,21 +2186,11 @@ expand_call_stmt (gimple stmt) return; } - decl = gimple_call_fndecl (stmt); - builtin_p = decl && DECL_BUILT_IN (decl); - - /* Bind bounds call is expanded as assignment. */ - if (builtin_p - && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL - && DECL_FUNCTION_CODE (decl) == BUILT_IN_CHKP_BIND_BOUNDS) - { - expand_assignment (gimple_call_lhs (stmt), - gimple_call_arg (stmt, 0), false); - return; - } - exp = build_vl_exp (CALL_EXPR, gimple_call_num_args (stmt) + 3); + CALL_EXPR_FN (exp) = gimple_call_fn (stmt); + decl = gimple_call_fndecl (stmt); + builtin_p = decl && DECL_BUILT_IN (decl); /* If this is not a builtin function, the function type through which the call is made may be different from the type of the function. */ diff --git a/gcc/cfgloop.c b/gcc/cfgloop.c index 447302a5934..94238badacf 100644 --- a/gcc/cfgloop.c +++ b/gcc/cfgloop.c @@ -28,11 +28,14 @@ along with GCC; see the file COPYING3. If not see #include "diagnostic-core.h" #include "flags.h" #include "tree.h" +#include "pointer-set.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimple-ssa.h" -#include "pointer-set.h" -#include "ggc.h" #include "dumpfile.h" static void flow_loops_cfg_dump (FILE *); diff --git a/gcc/cfgloopmanip.c b/gcc/cfgloopmanip.c index 6baa15afade..7a6b20172f4 100644 --- a/gcc/cfgloopmanip.c +++ b/gcc/cfgloopmanip.c @@ -25,6 +25,10 @@ along with GCC; see the file COPYING3. If not see #include "basic-block.h" #include "cfgloop.h" #include "tree.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimplify-me.h" diff --git a/gcc/cgraph.c b/gcc/cgraph.c index cfbd79edc76..854fd357983 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -36,12 +36,14 @@ along with GCC; see the file COPYING3. If not see #include "hashtab.h" #include "toplev.h" #include "flags.h" -#include "ggc.h" #include "debug.h" #include "target.h" -#include "basic-block.h" #include "cgraph.h" #include "intl.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "tree-eh.h" +#include "gimple-expr.h" #include "gimple.h" #include "gimple-iterator.h" #include "timevar.h" @@ -1465,7 +1467,7 @@ cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *e) { new_stmt = e->call_stmt; gimple_call_set_fndecl (new_stmt, e->callee->decl); - update_stmt (new_stmt); + update_stmt_fn (DECL_STRUCT_FUNCTION (e->caller->decl), new_stmt); } cgraph_set_call_stmt_including_clones (e->caller, e->call_stmt, new_stmt, false); diff --git a/gcc/cgraph.h b/gcc/cgraph.h index 15719fb6872..0d8166a961f 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -256,6 +256,99 @@ struct GTY(()) cgraph_clone_info bitmap combined_args_to_skip; }; +enum cgraph_simd_clone_arg_type +{ + SIMD_CLONE_ARG_TYPE_VECTOR, + SIMD_CLONE_ARG_TYPE_UNIFORM, + SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP, + SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP, + SIMD_CLONE_ARG_TYPE_MASK +}; + +/* Function arguments in the original function of a SIMD clone. + Supplementary data for `struct simd_clone'. */ + +struct GTY(()) cgraph_simd_clone_arg { + /* Original function argument as it originally existed in + DECL_ARGUMENTS. */ + tree orig_arg; + + /* orig_arg's function (or for extern functions type from + TYPE_ARG_TYPES). */ + tree orig_type; + + /* If argument is a vector, this holds the vector version of + orig_arg that after adjusting the argument types will live in + DECL_ARGUMENTS. Otherwise, this is NULL. + + This basically holds: + vector(simdlen) __typeof__(orig_arg) new_arg. */ + tree vector_arg; + + /* vector_arg's type (or for extern functions new vector type. */ + tree vector_type; + + /* If argument is a vector, this holds the array where the simd + argument is held while executing the simd clone function. This + is a local variable in the cloned function. Its content is + copied from vector_arg upon entry to the clone. + + This basically holds: + __typeof__(orig_arg) simd_array[simdlen]. */ + tree simd_array; + + /* A SIMD clone's argument can be either linear (constant or + variable), uniform, or vector. */ + enum cgraph_simd_clone_arg_type arg_type; + + /* For arg_type SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP this is + the constant linear step, if arg_type is + SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP, this is index of + the uniform argument holding the step, otherwise 0. */ + HOST_WIDE_INT linear_step; + + /* Variable alignment if available, otherwise 0. */ + unsigned int alignment; +}; + +/* Specific data for a SIMD function clone. */ + +struct GTY(()) cgraph_simd_clone { + /* Number of words in the SIMD lane associated with this clone. */ + unsigned int simdlen; + + /* Number of annotated function arguments in `args'. This is + usually the number of named arguments in FNDECL. */ + unsigned int nargs; + + /* Max hardware vector size in bits for integral vectors. */ + unsigned int vecsize_int; + + /* Max hardware vector size in bits for floating point vectors. */ + unsigned int vecsize_float; + + /* The mangling character for a given vector size. This is is used + to determine the ISA mangling bit as specified in the Intel + Vector ABI. */ + unsigned char vecsize_mangle; + + /* True if this is the masked, in-branch version of the clone, + otherwise false. */ + unsigned int inbranch : 1; + + /* True if this is a Cilk Plus variant. */ + unsigned int cilk_elemental : 1; + + /* Doubly linked list of SIMD clones. */ + struct cgraph_node *prev_clone, *next_clone; + + /* Original cgraph node the SIMD clones were created for. */ + struct cgraph_node *origin; + + /* Annotated function arguments for the original function. */ + struct cgraph_simd_clone_arg GTY((length ("%h.nargs"))) args[1]; +}; + /* The cgraph data structure. Each function decl has assigned cgraph_node listing callees and callers. */ @@ -284,6 +377,12 @@ public: /* Declaration node used to be clone of. */ tree former_clone_of; + /* If this is a SIMD clone, this points to the SIMD specific + information for it. */ + struct cgraph_simd_clone *simdclone; + /* If this function has SIMD clones, this points to the first clone. */ + struct cgraph_node *simd_clones; + /* Interprocedural passes scheduled to have their transform functions applied next time we execute local pass on them. We maintain it per-function in order to allow IPA passes to introduce new functions. */ @@ -529,9 +628,9 @@ public: /* Set when variable is scheduled to be assembled. */ unsigned output : 1; - /* Set when variable has statically initialized pointer - or is a static bounds variable and needs initalization. */ - unsigned need_bounds_init : 1; + /* Set if the variable is dynamically initialized, except for + function local statics. */ + unsigned dynamically_initialized : 1; }; /* Every top level asm statement is put into a asm_node. */ diff --git a/gcc/cgraphbuild.c b/gcc/cgraphbuild.c index 21f6ebe8d09..9a63982d9cb 100644 --- a/gcc/cgraphbuild.c +++ b/gcc/cgraphbuild.c @@ -23,11 +23,17 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tm.h" #include "tree.h" +#include "pointer-set.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimple-walk.h" #include "langhooks.h" -#include "pointer-set.h" #include "intl.h" #include "tree-pass.h" #include "ipa-utils.h" @@ -329,6 +335,8 @@ build_cgraph_edges (void) if (decl) cgraph_create_edge (node, cgraph_get_create_node (decl), stmt, bb->count, freq); + else if (gimple_call_internal_p (stmt)) + ; else cgraph_create_indirect_edge (node, stmt, gimple_call_flags (stmt), @@ -458,6 +466,8 @@ rebuild_cgraph_edges (void) if (decl) cgraph_create_edge (node, cgraph_get_create_node (decl), stmt, bb->count, freq); + else if (gimple_call_internal_p (stmt)) + ; else cgraph_create_indirect_edge (node, stmt, gimple_call_flags (stmt), diff --git a/gcc/cgraphclones.c b/gcc/cgraphclones.c index 795a321ae57..90ef90183b4 100644 --- a/gcc/cgraphclones.c +++ b/gcc/cgraphclones.c @@ -73,15 +73,19 @@ along with GCC; see the file COPYING3. If not see #include "stringpool.h" #include "function.h" #include "emit-rtl.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "bitmap.h" #include "tree-cfg.h" #include "tree-inline.h" #include "langhooks.h" -#include "pointer-set.h" #include "toplev.h" #include "flags.h" -#include "ggc.h" #include "debug.h" #include "target.h" #include "diagnostic.h" diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index b10d75531b0..2cbed673212 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -167,6 +167,12 @@ along with GCC; see the file COPYING3. If not see #include "stringpool.h" #include "output.h" #include "rtl.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "gimple-iterator.h" @@ -177,10 +183,8 @@ along with GCC; see the file COPYING3. If not see #include "tree-ssa.h" #include "tree-inline.h" #include "langhooks.h" -#include "pointer-set.h" #include "toplev.h" #include "flags.h" -#include "ggc.h" #include "debug.h" #include "target.h" #include "diagnostic.h" diff --git a/gcc/chkp-builtins.def b/gcc/chkp-builtins.def deleted file mode 100644 index b920950d603..00000000000 --- a/gcc/chkp-builtins.def +++ /dev/null @@ -1,76 +0,0 @@ -/* This file contains the definitions and documentation for the - builtins used in the GNU compiler. - Copyright (C) 2013 Free Software Foundation, Inc. - -This file is part of GCC. - -GCC is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 3, or (at your option) any later -version. - -GCC is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING3. If not see -<http://www.gnu.org/licenses/>. */ - -/* Before including this file, you should define macros: - - DEF_BUILTIN_STUB(ENUM, NAME) - DEF_CHKP_BUILTIN(ENUM, NAME, TYPE, ATTRS) - - See builtins.def for details. */ - -/* Following builtins are used by compiler for Pointer Bounds Checker - instrumentation. Currently these generic builtins are not - implemented and target has to provide his own version. See - builtin_chkp_function target hook documentation for more details. */ -DEF_BUILTIN_STUB (BUILT_IN_CHKP_BNDMK, "__chkp_bndmk") -DEF_BUILTIN_STUB (BUILT_IN_CHKP_BNDSTX, "__chkp_bndstx") -DEF_BUILTIN_STUB (BUILT_IN_CHKP_BNDCL, "__chkp_bndcl") -DEF_BUILTIN_STUB (BUILT_IN_CHKP_BNDCU, "__chkp_bndcu") -DEF_BUILTIN_STUB (BUILT_IN_CHKP_BNDLDX, "__chkp_bndldx") -DEF_BUILTIN_STUB (BUILT_IN_CHKP_BNDRET, "__chkp_bndret") -DEF_BUILTIN_STUB (BUILT_IN_CHKP_INTERSECT, "__chkp_intersect") -DEF_BUILTIN_STUB (BUILT_IN_CHKP_ARG_BND, "__chkp_arg_bnd") -DEF_BUILTIN_STUB (BUILT_IN_CHKP_SIZEOF, "__chkp_sizeof") -DEF_BUILTIN_STUB (BUILT_IN_CHKP_EXTRACT_LOWER, "__chkp_extract_lower") -DEF_BUILTIN_STUB (BUILT_IN_CHKP_EXTRACT_UPPER, "__chkp_extract_upper") -DEF_BUILTIN_STUB (BUILT_IN_CHKP_NARROW, "__chkp_narrow") - -/* Builtins to bind bounds to call arguments. */ -DEF_CHKP_BUILTIN (BUILT_IN_CHKP_BIND_BOUNDS, "__chkp_bind_bounds", BT_FN_PTR_CONST_PTR_VAR, ATTR_CONST_NOTHROW_LEAF_LIST) - -/* Pointer Bounds Checker builtins for users. Only - BUILT_IN_CHKP_SET_PTR_BOUNDS may be redefined - by target. Other builtins calls are expanded - in the Pointer Bounds Checker pass. */ -DEF_CHKP_BUILTIN (BUILT_IN_CHKP_SET_PTR_BOUNDS, "__bnd_set_ptr_bounds", BT_FN_PTR_CONST_PTR_SIZE, ATTR_CONST_NOTHROW_LEAF_LIST) -DEF_CHKP_BUILTIN (BUILT_IN_CHKP_INIT_PTR_BOUNDS, "__bnd_init_ptr_bounds", BT_FN_PTR_CONST_PTR, ATTR_CONST_NOTHROW_LEAF_LIST) -DEF_CHKP_BUILTIN (BUILT_IN_CHKP_NULL_PTR_BOUNDS, "__bnd_null_ptr_bounds", BT_FN_PTR_CONST_PTR, ATTR_CONST_NOTHROW_LEAF_LIST) -DEF_CHKP_BUILTIN (BUILT_IN_CHKP_COPY_PTR_BOUNDS, "__bnd_copy_ptr_bounds", BT_FN_PTR_CONST_PTR_CONST_PTR, ATTR_CONST_NOTHROW_LEAF_LIST) -DEF_CHKP_BUILTIN (BUILT_IN_CHKP_NARROW_PTR_BOUNDS, "__bnd_narrow_ptr_bounds", BT_FN_PTR_CONST_PTR_CONST_PTR_SIZE, ATTR_CONST_NOTHROW_LEAF_LIST) -DEF_CHKP_BUILTIN (BUILT_IN_CHKP_STORE_PTR_BOUNDS, "__bnd_store_ptr_bounds", BT_FN_VOID_PTRPTR_CONST_PTR, ATTR_NOTHROW_LEAF_LIST) -DEF_CHKP_BUILTIN (BUILT_IN_CHKP_CHECK_PTR_LBOUNDS, "__bnd_chk_ptr_lbounds", BT_FN_VOID_CONST_PTR, ATTR_NOTHROW_LEAF_LIST) -DEF_CHKP_BUILTIN (BUILT_IN_CHKP_CHECK_PTR_UBOUNDS, "__bnd_chk_ptr_ubounds", BT_FN_VOID_CONST_PTR, ATTR_NOTHROW_LEAF_LIST) -DEF_CHKP_BUILTIN (BUILT_IN_CHKP_CHECK_PTR_BOUNDS, "__bnd_chk_ptr_bounds", BT_FN_VOID_CONST_PTR_SIZE, ATTR_NOTHROW_LEAF_LIST) -DEF_CHKP_BUILTIN (BUILT_IN_CHKP_GET_PTR_LBOUND, "__bnd_get_ptr_lbound", BT_FN_CONST_PTR_CONST_PTR, ATTR_CONST_NOTHROW_LEAF_LIST) -DEF_CHKP_BUILTIN (BUILT_IN_CHKP_GET_PTR_UBOUND, "__bnd_get_ptr_ubound", BT_FN_CONST_PTR_CONST_PTR, ATTR_CONST_NOTHROW_LEAF_LIST) - -/* Pointer Bounds Checker specific versions of string functions. */ -DEF_CHKP_BUILTIN (BUILT_IN_CHKP_MEMCPY_NOBND, "chkp_memcpy_nobnd", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_RET1_NOTHROW_NONNULL_LEAF) -DEF_CHKP_BUILTIN (BUILT_IN_CHKP_MEMCPY_NOCHK, "chkp_memcpy_nochk", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_RET1_NOTHROW_NONNULL_LEAF) -DEF_CHKP_BUILTIN (BUILT_IN_CHKP_MEMCPY_NOBND_NOCHK, "chkp_memcpy_nobnd_nochk", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_RET1_NOTHROW_NONNULL_LEAF) -DEF_CHKP_BUILTIN (BUILT_IN_CHKP_MEMMOVE_NOBND, "chkp_memmove_nobnd", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_RET1_NOTHROW_NONNULL_LEAF) -DEF_CHKP_BUILTIN (BUILT_IN_CHKP_MEMMOVE_NOCHK, "chkp_memmove_nochk", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_RET1_NOTHROW_NONNULL_LEAF) -DEF_CHKP_BUILTIN (BUILT_IN_CHKP_MEMMOVE_NOBND_NOCHK, "chkp_memmove_nobnd_nochk", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_RET1_NOTHROW_NONNULL_LEAF) -DEF_CHKP_BUILTIN (BUILT_IN_CHKP_MEMPCPY_NOBND, "chkp_mempcpy_nobnd", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_NOTHROW_NONNULL_LEAF) -DEF_CHKP_BUILTIN (BUILT_IN_CHKP_MEMPCPY_NOCHK, "chkp_mempcpy_nochk", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_NOTHROW_NONNULL_LEAF) -DEF_CHKP_BUILTIN (BUILT_IN_CHKP_MEMPCPY_NOBND_NOCHK, "chkp_mempcpy_nobnd_nochk", BT_FN_PTR_PTR_CONST_PTR_SIZE, ATTR_NOTHROW_NONNULL_LEAF) -DEF_CHKP_BUILTIN (BUILT_IN_CHKP_MEMSET_NOBND, "chkp_memset_nobnd", BT_FN_PTR_PTR_INT_SIZE, ATTR_RET1_NOTHROW_NONNULL_LEAF) -DEF_CHKP_BUILTIN (BUILT_IN_CHKP_MEMSET_NOCHK, "chkp_memset_nochk", BT_FN_PTR_PTR_INT_SIZE, ATTR_RET1_NOTHROW_NONNULL_LEAF) -DEF_CHKP_BUILTIN (BUILT_IN_CHKP_MEMSET_NOBND_NOCHK, "chkp_memset_nobnd_nochk", BT_FN_PTR_PTR_INT_SIZE, ATTR_RET1_NOTHROW_NONNULL_LEAF) diff --git a/gcc/cilk-common.c b/gcc/cilk-common.c index bdea617a2e8..52b37852273 100644 --- a/gcc/cilk-common.c +++ b/gcc/cilk-common.c @@ -31,7 +31,6 @@ along with GCC; see the file COPYING3. If not see #include "optabs.h" #include "recog.h" #include "tree-iterator.h" -#include "gimple.h" #include "gimplify.h" #include "cilk.h" @@ -329,7 +328,7 @@ expand_builtin_cilk_detach (tree exp) tree parent = cilk_dot (fptr, CILK_TI_FRAME_PARENT, 0); tree worker = cilk_dot (fptr, CILK_TI_FRAME_WORKER, 0); - tree tail = cilk_dot (worker, CILK_TI_WORKER_TAIL, 1); + tree tail = cilk_arrow (worker, CILK_TI_WORKER_TAIL, 1); rtx wreg = expand_expr (worker, NULL_RTX, Pmode, EXPAND_NORMAL); if (GET_CODE (wreg) != REG) diff --git a/gcc/collect2.c b/gcc/collect2.c index 84cf6b476e4..95f817d307a 100644 --- a/gcc/collect2.c +++ b/gcc/collect2.c @@ -182,6 +182,7 @@ static int strip_flag; /* true if -s */ static int export_flag; /* true if -bE */ static int aix64_flag; /* true if -b64 */ static int aixrtl_flag; /* true if -brtl */ +static int aixlazy_flag; /* true if -blazy */ #endif enum lto_mode_d { @@ -215,6 +216,13 @@ static const char *strip_file_name; /* pathname of strip */ const char *c_file_name; /* pathname of gcc */ static char *initname, *fininame; /* names of init and fini funcs */ + +#ifdef TARGET_AIX_VERSION +static char *aix_shared_initname; +static char *aix_shared_fininame; /* init/fini names as per the scheme + described in config/rs6000/aix.h */ +#endif + static struct head constructors; /* list of constructors found */ static struct head destructors; /* list of destructors found */ #ifdef COLLECT_EXPORT_LIST @@ -279,7 +287,9 @@ typedef enum { SYM_DTOR = 2, /* destructor */ SYM_INIT = 3, /* shared object routine that calls all the ctors */ SYM_FINI = 4, /* shared object routine that calls all the dtors */ - SYM_DWEH = 5 /* DWARF exception handling table */ + SYM_DWEH = 5, /* DWARF exception handling table */ + SYM_AIXI = 6, + SYM_AIXD = 7 } symkind; static symkind is_ctor_dtor (const char *); @@ -340,6 +350,8 @@ enum scanfilter_masks { SCAN_INIT = 1 << SYM_INIT, SCAN_FINI = 1 << SYM_FINI, SCAN_DWEH = 1 << SYM_DWEH, + SCAN_AIXI = 1 << SYM_AIXI, + SCAN_AIXD = 1 << SYM_AIXD, SCAN_ALL = ~0 }; @@ -589,6 +601,10 @@ is_ctor_dtor (const char *s) { "GLOBAL__F_", sizeof ("GLOBAL__F_")-1, SYM_DWEH, 0 }, { "GLOBAL__FI_", sizeof ("GLOBAL__FI_")-1, SYM_INIT, 0 }, { "GLOBAL__FD_", sizeof ("GLOBAL__FD_")-1, SYM_FINI, 0 }, +#ifdef TARGET_AIX_VERSION + { "GLOBAL__AIXI_", sizeof ("GLOBAL__AIXI_")-1, SYM_AIXI, 0 }, + { "GLOBAL__AIXD_", sizeof ("GLOBAL__AIXD_")-1, SYM_AIXD, 0 }, +#endif { NULL, 0, SYM_REGULAR, 0 } }; @@ -1034,6 +1050,8 @@ main (int argc, char **argv) aixrtl_flag = 1; else if (strcmp (argv[i], "-bnortl") == 0) aixrtl_flag = 0; + else if (strcmp (argv[i], "-blazy") == 0) + aixlazy_flag = 1; #endif } vflag = debug; @@ -1728,6 +1746,11 @@ main (int argc, char **argv) if (! exports.first) *ld2++ = concat ("-bE:", export_file, NULL); +#ifdef TARGET_AIX_VERSION + add_to_list (&exports, aix_shared_initname); + add_to_list (&exports, aix_shared_fininame); +#endif + #ifndef LD_INIT_SWITCH add_to_list (&exports, initname); add_to_list (&exports, fininame); @@ -2020,6 +2043,19 @@ extract_init_priority (const char *name) { int pos = 0, pri; +#ifdef TARGET_AIX_VERSION + /* Run dependent module initializers before any constructors in this + module. */ + switch (is_ctor_dtor (name)) + { + case SYM_AIXI: + case SYM_AIXD: + return INT_MIN; + default: + break; + } +#endif + while (name[pos] == '_') ++pos; pos += 10; /* strlen ("GLOBAL__X_") */ @@ -2180,11 +2216,22 @@ write_c_file_stat (FILE *stream, const char *name ATTRIBUTE_UNUSED) initname = concat ("_GLOBAL__FI_", prefix, NULL); fininame = concat ("_GLOBAL__FD_", prefix, NULL); +#ifdef TARGET_AIX_VERSION + aix_shared_initname = concat ("_GLOBAL__AIXI_", prefix, NULL); + aix_shared_fininame = concat ("_GLOBAL__AIXD_", prefix, NULL); +#endif free (prefix); /* Write the tables as C code. */ + /* This count variable is used to prevent multiple calls to the + constructors/destructors. + This guard against multiple calls is important on AIX as the initfini + functions are deliberately invoked multiple times as part of the + mechanisms GCC uses to order constructors across different dependent + shared libraries (see config/rs6000/aix.h). + */ fprintf (stream, "static int count;\n"); fprintf (stream, "typedef void entry_pt();\n"); write_list_with_asm (stream, "extern entry_pt ", constructors.first); @@ -2531,6 +2578,7 @@ scan_prog_file (const char *prog_name, scanpass which_pass, *end = '\0'; + switch (is_ctor_dtor (name)) { case SYM_CTOR: @@ -2892,6 +2940,25 @@ scan_prog_file (const char *prog_name, scanpass which_pass, switch (is_ctor_dtor (name)) { +#if TARGET_AIX_VERSION + /* Add AIX shared library initalisers/finalisers + to the constructors/destructors list of the + current module. */ + case SYM_AIXI: + if (! (filter & SCAN_CTOR)) + break; + if (is_shared && !aixlazy_flag) + add_to_list (&constructors, name); + break; + + case SYM_AIXD: + if (! (filter & SCAN_DTOR)) + break; + if (is_shared && !aixlazy_flag) + add_to_list (&destructors, name); + break; +#endif + case SYM_CTOR: if (! (filter & SCAN_CTOR)) break; diff --git a/gcc/combine.c b/gcc/combine.c index 1c6dc85e006..0f4030e53ce 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -9465,7 +9465,13 @@ reg_nonzero_bits_for_combine (const_rtx x, enum machine_mode mode, (DF_LR_IN (ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb), REGNO (x))))) { - *nonzero &= rsp->last_set_nonzero_bits; + unsigned HOST_WIDE_INT mask = rsp->last_set_nonzero_bits; + + if (GET_MODE_PRECISION (rsp->last_set_mode) < GET_MODE_PRECISION (mode)) + /* We don't know anything about the upper bits. */ + mask |= GET_MODE_MASK (mode) ^ GET_MODE_MASK (rsp->last_set_mode); + + *nonzero &= mask; return NULL; } @@ -9498,6 +9504,7 @@ reg_nonzero_bits_for_combine (const_rtx x, enum machine_mode mode, if (GET_MODE_PRECISION (GET_MODE (x)) < GET_MODE_PRECISION (mode)) /* We don't know anything about the upper bits. */ mask |= GET_MODE_MASK (mode) ^ GET_MODE_MASK (GET_MODE (x)); + *nonzero &= mask; } diff --git a/gcc/common.opt b/gcc/common.opt index 2216d6e0392..9ece6832467 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -2300,6 +2300,10 @@ fvect-cost-model= Common Joined RejectNegative Enum(vect_cost_model) Var(flag_vect_cost_model) Init(VECT_COST_MODEL_DEFAULT) Specifies the cost model for vectorization +fsimd-cost-model= +Common Joined RejectNegative Enum(vect_cost_model) Var(flag_simd_cost_model) Init(VECT_COST_MODEL_UNLIMITED) +Specifies the vectorization cost model for code marked with a simd directive + Enum Name(vect_cost_model) Type(enum vect_cost_model) UnknownError(unknown vectorizer cost model %qs) @@ -2654,6 +2658,9 @@ Driver static-libtsan Driver +static-liblsan +Driver + static-libubsan Driver diff --git a/gcc/config/aarch64/aarch64-builtins.c b/gcc/config/aarch64/aarch64-builtins.c index fec7b222529..1bc3cc5e96d 100644 --- a/gcc/config/aarch64/aarch64-builtins.c +++ b/gcc/config/aarch64/aarch64-builtins.c @@ -33,6 +33,17 @@ #include "langhooks.h" #include "diagnostic-core.h" #include "optabs.h" +#include "pointer-set.h" +#include "hash-table.h" +#include "vec.h" +#include "ggc.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" @@ -113,7 +124,9 @@ enum aarch64_type_qualifiers /* qualifier_pointer | qualifier_map_mode */ qualifier_pointer_map_mode = 0x84, /* qualifier_const_pointer | qualifier_map_mode */ - qualifier_const_pointer_map_mode = 0x86 + qualifier_const_pointer_map_mode = 0x86, + /* Polynomial types. */ + qualifier_poly = 0x100 }; typedef struct @@ -168,6 +181,22 @@ aarch64_types_load1_qualifiers[SIMD_MAX_BUILTIN_ARGS] #define TYPES_LOAD1 (aarch64_types_load1_qualifiers) #define TYPES_LOADSTRUCT (aarch64_types_load1_qualifiers) +static enum aarch64_type_qualifiers +aarch64_types_bsl_p_qualifiers[SIMD_MAX_BUILTIN_ARGS] + = { qualifier_poly, qualifier_unsigned, + qualifier_poly, qualifier_poly }; +#define TYPES_BSL_P (aarch64_types_bsl_p_qualifiers) +static enum aarch64_type_qualifiers +aarch64_types_bsl_s_qualifiers[SIMD_MAX_BUILTIN_ARGS] + = { qualifier_none, qualifier_unsigned, + qualifier_none, qualifier_none }; +#define TYPES_BSL_S (aarch64_types_bsl_s_qualifiers) +static enum aarch64_type_qualifiers +aarch64_types_bsl_u_qualifiers[SIMD_MAX_BUILTIN_ARGS] + = { qualifier_unsigned, qualifier_unsigned, + qualifier_unsigned, qualifier_unsigned }; +#define TYPES_BSL_U (aarch64_types_bsl_u_qualifiers) + /* The first argument (return type) of a store should be void type, which we represent with qualifier_void. Their first operand will be a DImode pointer to the location to store to, so we must use @@ -242,6 +271,9 @@ aarch64_types_store1_qualifiers[SIMD_MAX_BUILTIN_ARGS] #define BUILTIN_VALLDI(T, N, MAP) \ VAR11 (T, N, MAP, v8qi, v16qi, v4hi, v8hi, v2si, \ v4si, v2di, v2sf, v4sf, v2df, di) +#define BUILTIN_VALLDIF(T, N, MAP) \ + VAR12 (T, N, MAP, v8qi, v16qi, v4hi, v8hi, v2si, \ + v4si, v2di, v2sf, v4sf, v2df, di, df) #define BUILTIN_VB(T, N, MAP) \ VAR2 (T, N, MAP, v8qi, v16qi) #define BUILTIN_VD(T, N, MAP) \ @@ -266,6 +298,8 @@ aarch64_types_store1_qualifiers[SIMD_MAX_BUILTIN_ARGS] VAR6 (T, N, MAP, v8qi, v16qi, v4hi, v8hi, v2si, v4si) #define BUILTIN_VDQV(T, N, MAP) \ VAR5 (T, N, MAP, v8qi, v16qi, v4hi, v8hi, v4si) +#define BUILTIN_VDQQH(T, N, MAP) \ + VAR4 (T, N, MAP, v8qi, v16qi, v4hi, v8hi) #define BUILTIN_VDQ_BHSI(T, N, MAP) \ VAR6 (T, N, MAP, v8qi, v16qi, v4hi, v8hi, v2si, v4si) #define BUILTIN_VDQ_I(T, N, MAP) \ @@ -309,7 +343,7 @@ static aarch64_simd_builtin_datum aarch64_simd_builtin_data[] = { #undef VAR1 #define VAR1(T, N, MAP, A) \ - AARCH64_SIMD_BUILTIN_##N##A, + AARCH64_SIMD_BUILTIN_##T##_##N##A, enum aarch64_builtins { @@ -329,7 +363,9 @@ static GTY(()) tree aarch64_builtin_decls[AARCH64_BUILTIN_MAX]; /* Return a tree for a signed or unsigned argument of either the mode specified by MODE, or the inner mode of MODE. */ tree -aarch64_build_scalar_type (enum machine_mode mode, bool unsigned_p) +aarch64_build_scalar_type (enum machine_mode mode, + bool unsigned_p, + bool poly_p) { #undef INT_TYPES #define INT_TYPES \ @@ -346,6 +382,7 @@ aarch64_build_scalar_type (enum machine_mode mode, bool unsigned_p) /* Statically declare all the possible types we might need. */ #undef AARCH64_TYPE_BUILDER #define AARCH64_TYPE_BUILDER(X) \ + static tree X##_aarch64_type_node_p = NULL; \ static tree X##_aarch64_type_node_s = NULL; \ static tree X##_aarch64_type_node_u = NULL; @@ -366,6 +403,11 @@ aarch64_build_scalar_type (enum machine_mode mode, bool unsigned_p) ? X##_aarch64_type_node_u \ : X##_aarch64_type_node_u \ = make_unsigned_type (GET_MODE_PRECISION (mode))); \ + else if (poly_p) \ + return (X##_aarch64_type_node_p \ + ? X##_aarch64_type_node_p \ + : X##_aarch64_type_node_p \ + = make_unsigned_type (GET_MODE_PRECISION (mode))); \ else \ return (X##_aarch64_type_node_s \ ? X##_aarch64_type_node_s \ @@ -400,7 +442,9 @@ aarch64_build_scalar_type (enum machine_mode mode, bool unsigned_p) } tree -aarch64_build_vector_type (enum machine_mode mode, bool unsigned_p) +aarch64_build_vector_type (enum machine_mode mode, + bool unsigned_p, + bool poly_p) { tree eltype; @@ -420,7 +464,8 @@ aarch64_build_vector_type (enum machine_mode mode, bool unsigned_p) #undef AARCH64_TYPE_BUILDER #define AARCH64_TYPE_BUILDER(X) \ static tree X##_aarch64_type_node_s = NULL; \ - static tree X##_aarch64_type_node_u = NULL; + static tree X##_aarch64_type_node_u = NULL; \ + static tree X##_aarch64_type_node_p = NULL; VECTOR_TYPES @@ -435,20 +480,28 @@ aarch64_build_vector_type (enum machine_mode mode, bool unsigned_p) : X##_aarch64_type_node_u \ = build_vector_type_for_mode (aarch64_build_scalar_type \ (GET_MODE_INNER (mode), \ - unsigned_p), mode); \ + unsigned_p, poly_p), mode); \ + else if (poly_p) \ + return X##_aarch64_type_node_p \ + ? X##_aarch64_type_node_p \ + : X##_aarch64_type_node_p \ + = build_vector_type_for_mode (aarch64_build_scalar_type \ + (GET_MODE_INNER (mode), \ + unsigned_p, poly_p), mode); \ else \ return X##_aarch64_type_node_s \ ? X##_aarch64_type_node_s \ : X##_aarch64_type_node_s \ = build_vector_type_for_mode (aarch64_build_scalar_type \ (GET_MODE_INNER (mode), \ - unsigned_p), mode); \ + unsigned_p, poly_p), mode); \ break; switch (mode) { default: - eltype = aarch64_build_scalar_type (GET_MODE_INNER (mode), unsigned_p); + eltype = aarch64_build_scalar_type (GET_MODE_INNER (mode), + unsigned_p, poly_p); return build_vector_type_for_mode (eltype, mode); break; VECTOR_TYPES @@ -456,12 +509,30 @@ aarch64_build_vector_type (enum machine_mode mode, bool unsigned_p) } tree -aarch64_build_type (enum machine_mode mode, bool unsigned_p) +aarch64_build_type (enum machine_mode mode, bool unsigned_p, bool poly_p) { if (VECTOR_MODE_P (mode)) - return aarch64_build_vector_type (mode, unsigned_p); + return aarch64_build_vector_type (mode, unsigned_p, poly_p); else - return aarch64_build_scalar_type (mode, unsigned_p); + return aarch64_build_scalar_type (mode, unsigned_p, poly_p); +} + +tree +aarch64_build_signed_type (enum machine_mode mode) +{ + return aarch64_build_type (mode, false, false); +} + +tree +aarch64_build_unsigned_type (enum machine_mode mode) +{ + return aarch64_build_type (mode, true, false); +} + +tree +aarch64_build_poly_type (enum machine_mode mode) +{ + return aarch64_build_type (mode, false, true); } static void @@ -469,32 +540,30 @@ aarch64_init_simd_builtins (void) { unsigned int i, fcode = AARCH64_SIMD_BUILTIN_BASE + 1; - /* In order that 'poly' types mangle correctly they must not share - a base tree with the other scalar types, thus we must generate them - as a special case. */ - tree aarch64_simd_polyQI_type_node = - make_signed_type (GET_MODE_PRECISION (QImode)); - tree aarch64_simd_polyHI_type_node = - make_signed_type (GET_MODE_PRECISION (HImode)); - - /* Scalar type nodes. */ - tree aarch64_simd_intQI_type_node = aarch64_build_type (QImode, false); - tree aarch64_simd_intHI_type_node = aarch64_build_type (HImode, false); - tree aarch64_simd_intSI_type_node = aarch64_build_type (SImode, false); - tree aarch64_simd_intDI_type_node = aarch64_build_type (DImode, false); - tree aarch64_simd_intTI_type_node = aarch64_build_type (TImode, false); - tree aarch64_simd_intEI_type_node = aarch64_build_type (EImode, false); - tree aarch64_simd_intOI_type_node = aarch64_build_type (OImode, false); - tree aarch64_simd_intCI_type_node = aarch64_build_type (CImode, false); - tree aarch64_simd_intXI_type_node = aarch64_build_type (XImode, false); - tree aarch64_simd_intUQI_type_node = aarch64_build_type (QImode, true); - tree aarch64_simd_intUHI_type_node = aarch64_build_type (HImode, true); - tree aarch64_simd_intUSI_type_node = aarch64_build_type (SImode, true); - tree aarch64_simd_intUDI_type_node = aarch64_build_type (DImode, true); + /* Signed scalar type nodes. */ + tree aarch64_simd_intQI_type_node = aarch64_build_signed_type (QImode); + tree aarch64_simd_intHI_type_node = aarch64_build_signed_type (HImode); + tree aarch64_simd_intSI_type_node = aarch64_build_signed_type (SImode); + tree aarch64_simd_intDI_type_node = aarch64_build_signed_type (DImode); + tree aarch64_simd_intTI_type_node = aarch64_build_signed_type (TImode); + tree aarch64_simd_intEI_type_node = aarch64_build_signed_type (EImode); + tree aarch64_simd_intOI_type_node = aarch64_build_signed_type (OImode); + tree aarch64_simd_intCI_type_node = aarch64_build_signed_type (CImode); + tree aarch64_simd_intXI_type_node = aarch64_build_signed_type (XImode); + + /* Unsigned scalar type nodes. */ + tree aarch64_simd_intUQI_type_node = aarch64_build_unsigned_type (QImode); + tree aarch64_simd_intUHI_type_node = aarch64_build_unsigned_type (HImode); + tree aarch64_simd_intUSI_type_node = aarch64_build_unsigned_type (SImode); + tree aarch64_simd_intUDI_type_node = aarch64_build_unsigned_type (DImode); + + /* Poly scalar type nodes. */ + tree aarch64_simd_polyQI_type_node = aarch64_build_poly_type (QImode); + tree aarch64_simd_polyHI_type_node = aarch64_build_poly_type (HImode); /* Float type nodes. */ - tree aarch64_simd_float_type_node = aarch64_build_type (SFmode, false); - tree aarch64_simd_double_type_node = aarch64_build_type (DFmode, false); + tree aarch64_simd_float_type_node = aarch64_build_signed_type (SFmode); + tree aarch64_simd_double_type_node = aarch64_build_signed_type (DFmode); /* Define typedefs which exactly correspond to the modes we are basing vector types on. If you change these names you'll need to change @@ -592,6 +661,11 @@ aarch64_init_simd_builtins (void) type_signature[arg_num] = 'u'; print_type_signature_p = true; } + else if (qualifiers & qualifier_poly) + { + type_signature[arg_num] = 'p'; + print_type_signature_p = true; + } else type_signature[arg_num] = 's'; @@ -610,7 +684,8 @@ aarch64_init_simd_builtins (void) op_mode = GET_MODE_INNER (op_mode); eltype = aarch64_build_type (op_mode, - qualifiers & qualifier_unsigned); + qualifiers & qualifier_unsigned, + qualifiers & qualifier_poly); /* Add qualifiers. */ if (qualifiers & qualifier_const) @@ -886,11 +961,11 @@ aarch64_builtin_vectorized_function (tree fndecl, tree type_out, tree type_in) #define AARCH64_CHECK_BUILTIN_MODE(C, N) 1 #define AARCH64_FIND_FRINT_VARIANT(N) \ (AARCH64_CHECK_BUILTIN_MODE (2, D) \ - ? aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_##N##v2df] \ + ? aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_##N##v2df] \ : (AARCH64_CHECK_BUILTIN_MODE (4, S) \ - ? aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_##N##v4sf] \ + ? aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_##N##v4sf] \ : (AARCH64_CHECK_BUILTIN_MODE (2, S) \ - ? aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_##N##v2sf] \ + ? aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_##N##v2sf] \ : NULL_TREE))) if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL) { @@ -926,7 +1001,7 @@ aarch64_builtin_vectorized_function (tree fndecl, tree type_out, tree type_in) case BUILT_IN_CLZ: { if (AARCH64_CHECK_BUILTIN_MODE (4, S)) - return aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_clzv4si]; + return aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_UNOP_clzv4si]; return NULL_TREE; } #undef AARCH64_CHECK_BUILTIN_MODE @@ -936,47 +1011,47 @@ aarch64_builtin_vectorized_function (tree fndecl, tree type_out, tree type_in) case BUILT_IN_LFLOOR: case BUILT_IN_IFLOORF: { - tree new_tree = NULL_TREE; + enum aarch64_builtins builtin; if (AARCH64_CHECK_BUILTIN_MODE (2, D)) - new_tree = - aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_lfloorv2dfv2di]; + builtin = AARCH64_SIMD_BUILTIN_UNOP_lfloorv2dfv2di; else if (AARCH64_CHECK_BUILTIN_MODE (4, S)) - new_tree = - aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_lfloorv4sfv4si]; + builtin = AARCH64_SIMD_BUILTIN_UNOP_lfloorv4sfv4si; else if (AARCH64_CHECK_BUILTIN_MODE (2, S)) - new_tree = - aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_lfloorv2sfv2si]; - return new_tree; + builtin = AARCH64_SIMD_BUILTIN_UNOP_lfloorv2sfv2si; + else + return NULL_TREE; + + return aarch64_builtin_decls[builtin]; } case BUILT_IN_LCEIL: case BUILT_IN_ICEILF: { - tree new_tree = NULL_TREE; + enum aarch64_builtins builtin; if (AARCH64_CHECK_BUILTIN_MODE (2, D)) - new_tree = - aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_lceilv2dfv2di]; + builtin = AARCH64_SIMD_BUILTIN_UNOP_lceilv2dfv2di; else if (AARCH64_CHECK_BUILTIN_MODE (4, S)) - new_tree = - aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_lceilv4sfv4si]; + builtin = AARCH64_SIMD_BUILTIN_UNOP_lceilv4sfv4si; else if (AARCH64_CHECK_BUILTIN_MODE (2, S)) - new_tree = - aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_lceilv2sfv2si]; - return new_tree; + builtin = AARCH64_SIMD_BUILTIN_UNOP_lceilv2sfv2si; + else + return NULL_TREE; + + return aarch64_builtin_decls[builtin]; } case BUILT_IN_LROUND: case BUILT_IN_IROUNDF: { - tree new_tree = NULL_TREE; + enum aarch64_builtins builtin; if (AARCH64_CHECK_BUILTIN_MODE (2, D)) - new_tree = - aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_lroundv2dfv2di]; + builtin = AARCH64_SIMD_BUILTIN_UNOP_lroundv2dfv2di; else if (AARCH64_CHECK_BUILTIN_MODE (4, S)) - new_tree = - aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_lroundv4sfv4si]; + builtin = AARCH64_SIMD_BUILTIN_UNOP_lroundv4sfv4si; else if (AARCH64_CHECK_BUILTIN_MODE (2, S)) - new_tree = - aarch64_builtin_decls[AARCH64_SIMD_BUILTIN_lroundv2sfv2si]; - return new_tree; + builtin = AARCH64_SIMD_BUILTIN_UNOP_lroundv2sfv2si; + else + return NULL_TREE; + + return aarch64_builtin_decls[builtin]; } default: @@ -989,7 +1064,7 @@ aarch64_builtin_vectorized_function (tree fndecl, tree type_out, tree type_in) #undef VAR1 #define VAR1(T, N, MAP, A) \ - case AARCH64_SIMD_BUILTIN_##N##A: + case AARCH64_SIMD_BUILTIN_##T##_##N##A: tree aarch64_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED, tree *args, diff --git a/gcc/config/aarch64/aarch64-cores.def b/gcc/config/aarch64/aarch64-cores.def index 51c1ff803b0..b631dbed924 100644 --- a/gcc/config/aarch64/aarch64-cores.def +++ b/gcc/config/aarch64/aarch64-cores.def @@ -34,5 +34,5 @@ This list currently contains example CPUs that implement AArch64, and therefore serves as a template for adding more CPUs in the future. */ -AARCH64_CORE("cortex-a53", cortexa53, 8, AARCH64_FL_FPSIMD, generic) +AARCH64_CORE("cortex-a53", cortexa53, 8, AARCH64_FL_FPSIMD, cortexa53) AARCH64_CORE("cortex-a57", cortexa15, 8, AARCH64_FL_FPSIMD, generic) diff --git a/gcc/config/aarch64/aarch64-simd-builtins.def b/gcc/config/aarch64/aarch64-simd-builtins.def index c18b150a1f5..1dc3c1fe33f 100644 --- a/gcc/config/aarch64/aarch64-simd-builtins.def +++ b/gcc/config/aarch64/aarch64-simd-builtins.def @@ -362,3 +362,8 @@ /* Implemented by fma<mode>4. */ BUILTIN_VDQF (TERNOP, fma, 4) + /* Implemented by aarch64_simd_bsl<mode>. */ + BUILTIN_VDQQH (BSL_P, simd_bsl, 0) + BUILTIN_VSDQ_I_DI (BSL_U, simd_bsl, 0) + BUILTIN_VALLDIF (BSL_S, simd_bsl, 0) + diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md index b9ebdf54431..158b3dca6da 100644 --- a/gcc/config/aarch64/aarch64-simd.md +++ b/gcc/config/aarch64/aarch64-simd.md @@ -85,17 +85,17 @@ (define_insn "*aarch64_simd_mov<mode>" [(set (match_operand:VD 0 "aarch64_simd_nonimmediate_operand" - "=w, Utv, w, ?r, ?w, ?r, w") + "=w, m, w, ?r, ?w, ?r, w") (match_operand:VD 1 "aarch64_simd_general_operand" - "Utv, w, w, w, r, r, Dn"))] + "m, w, w, w, r, r, Dn"))] "TARGET_SIMD && (register_operand (operands[0], <MODE>mode) || register_operand (operands[1], <MODE>mode))" { switch (which_alternative) { - case 0: return "ld1\t{%0.<Vtype>}, %1"; - case 1: return "st1\t{%1.<Vtype>}, %0"; + case 0: return "ldr\\t%d0, %1"; + case 1: return "str\\t%d1, %0"; case 2: return "orr\t%0.<Vbtype>, %1.<Vbtype>, %1.<Vbtype>"; case 3: return "umov\t%0, %1.d[0]"; case 4: return "ins\t%0.d[0], %1"; @@ -113,9 +113,9 @@ (define_insn "*aarch64_simd_mov<mode>" [(set (match_operand:VQ 0 "aarch64_simd_nonimmediate_operand" - "=w, Utv, w, ?r, ?w, ?r, w") + "=w, m, w, ?r, ?w, ?r, w") (match_operand:VQ 1 "aarch64_simd_general_operand" - "Utv, w, w, w, r, r, Dn"))] + "m, w, w, w, r, r, Dn"))] "TARGET_SIMD && (register_operand (operands[0], <MODE>mode) || register_operand (operands[1], <MODE>mode))" @@ -123,9 +123,9 @@ switch (which_alternative) { case 0: - return "ld1\t{%0.<Vtype>}, %1"; + return "ldr\\t%q0, %1"; case 1: - return "st1\t{%1.<Vtype>}, %0"; + return "str\\t%q1, %0"; case 2: return "orr\t%0.<Vbtype>, %1.<Vbtype>, %1.<Vbtype>"; case 3: @@ -428,9 +428,19 @@ (match_operand:VQ_S 3 "register_operand" "0,0") (match_operand:SI 2 "immediate_operand" "i,i")))] "TARGET_SIMD" - "@ - ins\t%0.<Vetype>[%p2], %w1 - ins\\t%0.<Vetype>[%p2], %1.<Vetype>[0]" + { + int elt = ENDIAN_LANE_N (<MODE>mode, exact_log2 (INTVAL (operands[2]))); + operands[2] = GEN_INT ((HOST_WIDE_INT) 1 << elt); + switch (which_alternative) + { + case 0: + return "ins\\t%0.<Vetype>[%p2], %w1"; + case 1: + return "ins\\t%0.<Vetype>[%p2], %1.<Vetype>[0]"; + default: + gcc_unreachable (); + } + } [(set_attr "type" "neon_from_gp<q>, neon_ins<q>")] ) @@ -692,9 +702,19 @@ (match_operand:V2DI 3 "register_operand" "0,0") (match_operand:SI 2 "immediate_operand" "i,i")))] "TARGET_SIMD" - "@ - ins\t%0.d[%p2], %1 - ins\\t%0.d[%p2], %1.d[0]" + { + int elt = ENDIAN_LANE_N (V2DImode, exact_log2 (INTVAL (operands[2]))); + operands[2] = GEN_INT ((HOST_WIDE_INT) 1 << elt); + switch (which_alternative) + { + case 0: + return "ins\\t%0.d[%p2], %1"; + case 1: + return "ins\\t%0.d[%p2], %1.d[0]"; + default: + gcc_unreachable (); + } + } [(set_attr "type" "neon_from_gp, neon_ins_q")] ) @@ -719,7 +739,12 @@ (match_operand:VDQF 3 "register_operand" "0") (match_operand:SI 2 "immediate_operand" "i")))] "TARGET_SIMD" - "ins\t%0.<Vetype>[%p2], %1.<Vetype>[0]"; + { + int elt = ENDIAN_LANE_N (<MODE>mode, exact_log2 (INTVAL (operands[2]))); + + operands[2] = GEN_INT ((HOST_WIDE_INT)1 << elt); + return "ins\t%0.<Vetype>[%p2], %1.<Vetype>[0]"; + } [(set_attr "type" "neon_ins<q>")] ) @@ -891,9 +916,11 @@ "TARGET_SIMD" { rtx tempreg = gen_reg_rtx (<VDBL>mode); + int lo = BYTES_BIG_ENDIAN ? 2 : 1; + int hi = BYTES_BIG_ENDIAN ? 1 : 2; - emit_insn (gen_move_lo_quad_<Vdbl> (tempreg, operands[1])); - emit_insn (gen_move_hi_quad_<Vdbl> (tempreg, operands[2])); + emit_insn (gen_move_lo_quad_<Vdbl> (tempreg, operands[lo])); + emit_insn (gen_move_hi_quad_<Vdbl> (tempreg, operands[hi])); emit_insn (gen_aarch64_simd_vec_pack_trunc_<Vdbl> (operands[0], tempreg)); DONE; }) @@ -906,7 +933,12 @@ (truncate:<VNARROWQ> (match_operand:VQN 1 "register_operand" "w")) (truncate:<VNARROWQ> (match_operand:VQN 2 "register_operand" "w"))))] "TARGET_SIMD" - "xtn\\t%0.<Vntype>, %1.<Vtype>\;xtn2\\t%0.<V2ntype>, %2.<Vtype>" + { + if (BYTES_BIG_ENDIAN) + return "xtn\\t%0.<Vntype>, %2.<Vtype>\;xtn2\\t%0.<V2ntype>, %1.<Vtype>"; + else + return "xtn\\t%0.<Vntype>, %1.<Vtype>\;xtn2\\t%0.<V2ntype>, %2.<Vtype>"; + } [(set_attr "type" "multiple") (set_attr "length" "8")] ) @@ -1444,9 +1476,12 @@ "TARGET_SIMD" { rtx tmp = gen_reg_rtx (V2SFmode); - emit_insn (gen_aarch64_float_truncate_lo_v2sf (tmp, operands[1])); + int lo = BYTES_BIG_ENDIAN ? 2 : 1; + int hi = BYTES_BIG_ENDIAN ? 1 : 2; + + emit_insn (gen_aarch64_float_truncate_lo_v2sf (tmp, operands[lo])); emit_insn (gen_aarch64_float_truncate_hi_v4sf (operands[0], - tmp, operands[2])); + tmp, operands[hi])); DONE; } ) @@ -1462,8 +1497,11 @@ "TARGET_SIMD" { rtx tmp = gen_reg_rtx (V2SFmode); - emit_insn (gen_move_lo_quad_v2df (tmp, operands[1])); - emit_insn (gen_move_hi_quad_v2df (tmp, operands[2])); + int lo = BYTES_BIG_ENDIAN ? 2 : 1; + int hi = BYTES_BIG_ENDIAN ? 1 : 2; + + emit_insn (gen_move_lo_quad_v2df (tmp, operands[lo])); + emit_insn (gen_move_hi_quad_v2df (tmp, operands[hi])); emit_insn (gen_aarch64_float_truncate_lo_v2sf (operands[0], tmp)); DONE; } @@ -1519,19 +1557,10 @@ (unspec:VDQV [(match_operand:VDQV 1 "register_operand" "w")] SUADDV))] "TARGET_SIMD" - "addv\\t%<Vetype>0, %1.<Vtype>" + "add<VDQV:vp>\\t%<Vetype>0, %1.<Vtype>" [(set_attr "type" "neon_reduc_add<q>")] ) -(define_insn "reduc_<sur>plus_v2di" - [(set (match_operand:V2DI 0 "register_operand" "=w") - (unspec:V2DI [(match_operand:V2DI 1 "register_operand" "w")] - SUADDV))] - "TARGET_SIMD" - "addp\\t%d0, %1.2d" - [(set_attr "type" "neon_reduc_add_q")] -) - (define_insn "reduc_<sur>plus_v2si" [(set (match_operand:V2SI 0 "register_operand" "=w") (unspec:V2SI [(match_operand:V2SI 1 "register_operand" "w")] @@ -1541,10 +1570,10 @@ [(set_attr "type" "neon_reduc_add")] ) -(define_insn "reduc_<sur>plus_<mode>" +(define_insn "reduc_splus_<mode>" [(set (match_operand:V2F 0 "register_operand" "=w") (unspec:V2F [(match_operand:V2F 1 "register_operand" "w")] - SUADDV))] + UNSPEC_FADDV))] "TARGET_SIMD" "faddp\\t%<Vetype>0, %1.<Vtype>" [(set_attr "type" "neon_fp_reduc_add_<Vetype><q>")] @@ -1559,15 +1588,14 @@ [(set_attr "type" "neon_fp_reduc_add_s_q")] ) -(define_expand "reduc_<sur>plus_v4sf" +(define_expand "reduc_splus_v4sf" [(set (match_operand:V4SF 0 "register_operand") (unspec:V4SF [(match_operand:V4SF 1 "register_operand")] - SUADDV))] + UNSPEC_FADDV))] "TARGET_SIMD" { - rtx tmp = gen_reg_rtx (V4SFmode); - emit_insn (gen_aarch64_addpv4sf (tmp, operands[1])); - emit_insn (gen_aarch64_addpv4sf (operands[0], tmp)); + emit_insn (gen_aarch64_addpv4sf (operands[0], operands[1])); + emit_insn (gen_aarch64_addpv4sf (operands[0], operands[0])); DONE; }) @@ -1582,23 +1610,14 @@ ;; 'across lanes' max and min ops. (define_insn "reduc_<maxmin_uns>_<mode>" - [(set (match_operand:VDQV 0 "register_operand" "=w") - (unspec:VDQV [(match_operand:VDQV 1 "register_operand" "w")] + [(set (match_operand:VDQV_S 0 "register_operand" "=w") + (unspec:VDQV_S [(match_operand:VDQV_S 1 "register_operand" "w")] MAXMINV))] "TARGET_SIMD" "<maxmin_uns_op>v\\t%<Vetype>0, %1.<Vtype>" [(set_attr "type" "neon_reduc_minmax<q>")] ) -(define_insn "reduc_<maxmin_uns>_v2di" - [(set (match_operand:V2DI 0 "register_operand" "=w") - (unspec:V2DI [(match_operand:V2DI 1 "register_operand" "w")] - MAXMINV))] - "TARGET_SIMD" - "<maxmin_uns_op>p\\t%d0, %1.2d" - [(set_attr "type" "neon_reduc_minmax_q")] -) - (define_insn "reduc_<maxmin_uns>_v2si" [(set (match_operand:V2SI 0 "register_operand" "=w") (unspec:V2SI [(match_operand:V2SI 1 "register_operand" "w")] @@ -1643,15 +1662,15 @@ ;; bif op0, op1, mask (define_insn "aarch64_simd_bsl<mode>_internal" - [(set (match_operand:VALL 0 "register_operand" "=w,w,w") - (ior:VALL - (and:VALL + [(set (match_operand:VALLDIF 0 "register_operand" "=w,w,w") + (ior:VALLDIF + (and:VALLDIF (match_operand:<V_cmp_result> 1 "register_operand" " 0,w,w") - (match_operand:VALL 2 "register_operand" " w,w,0")) - (and:VALL + (match_operand:VALLDIF 2 "register_operand" " w,w,0")) + (and:VALLDIF (not:<V_cmp_result> (match_dup:<V_cmp_result> 1)) - (match_operand:VALL 3 "register_operand" " w,0,w")) + (match_operand:VALLDIF 3 "register_operand" " w,0,w")) ))] "TARGET_SIMD" "@ @@ -1662,10 +1681,10 @@ ) (define_expand "aarch64_simd_bsl<mode>" - [(match_operand:VALL 0 "register_operand") + [(match_operand:VALLDIF 0 "register_operand") (match_operand:<V_cmp_result> 1 "register_operand") - (match_operand:VALL 2 "register_operand") - (match_operand:VALL 3 "register_operand")] + (match_operand:VALLDIF 2 "register_operand") + (match_operand:VALLDIF 3 "register_operand")] "TARGET_SIMD" { /* We can't alias operands together if they have different modes. */ @@ -2022,7 +2041,10 @@ (match_operand:VDQQH 1 "register_operand" "w") (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))] "TARGET_SIMD" - "smov\\t%<GPI:w>0, %1.<VDQQH:Vetype>[%2]" + { + operands[2] = GEN_INT (ENDIAN_LANE_N (<MODE>mode, INTVAL (operands[2]))); + return "smov\\t%<GPI:w>0, %1.<VDQQH:Vetype>[%2]"; + } [(set_attr "type" "neon_to_gp<q>")] ) @@ -2033,22 +2055,36 @@ (match_operand:VDQQH 1 "register_operand" "w") (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))] "TARGET_SIMD" - "umov\\t%w0, %1.<Vetype>[%2]" + { + operands[2] = GEN_INT (ENDIAN_LANE_N (<MODE>mode, INTVAL (operands[2]))); + return "umov\\t%w0, %1.<Vetype>[%2]"; + } [(set_attr "type" "neon_to_gp<q>")] ) ;; Lane extraction of a value, neither sign nor zero extension ;; is guaranteed so upper bits should be considered undefined. (define_insn "aarch64_get_lane<mode>" - [(set (match_operand:<VEL> 0 "register_operand" "=r, w") + [(set (match_operand:<VEL> 0 "aarch64_simd_nonimmediate_operand" "=r, w, Utv") (vec_select:<VEL> - (match_operand:VALL 1 "register_operand" "w, w") - (parallel [(match_operand:SI 2 "immediate_operand" "i, i")])))] + (match_operand:VALL 1 "register_operand" "w, w, w") + (parallel [(match_operand:SI 2 "immediate_operand" "i, i, i")])))] "TARGET_SIMD" - "@ - umov\\t%<vwcore>0, %1.<Vetype>[%2] - dup\\t%<Vetype>0, %1.<Vetype>[%2]" - [(set_attr "type" "neon_to_gp<q>, neon_dup<q>")] + { + operands[2] = GEN_INT (ENDIAN_LANE_N (<MODE>mode, INTVAL (operands[2]))); + switch (which_alternative) + { + case 0: + return "umov\\t%<vwcore>0, %1.<Vetype>[%2]"; + case 1: + return "dup\\t%<Vetype>0, %1.<Vetype>[%2]"; + case 2: + return "st1\\t{%1.<Vetype>}[%2], %0"; + default: + gcc_unreachable (); + } + } + [(set_attr "type" "neon_to_gp<q>, neon_dup<q>, neon_store1_one_lane<q>")] ) (define_expand "aarch64_get_lanedi" @@ -4028,16 +4064,13 @@ ;; Standard pattern name vec_extract<mode>. -(define_insn "vec_extract<mode>" - [(set (match_operand:<VEL> 0 "aarch64_simd_nonimmediate_operand" "=r, w, Utv") - (vec_select:<VEL> - (match_operand:VALL 1 "register_operand" "w, w, w") - (parallel [(match_operand:SI 2 "immediate_operand" "i,i,i")])))] +(define_expand "vec_extract<mode>" + [(match_operand:<VEL> 0 "aarch64_simd_nonimmediate_operand" "") + (match_operand:VALL 1 "register_operand" "") + (match_operand:SI 2 "immediate_operand" "")] "TARGET_SIMD" - "@ - umov\\t%<vw>0, %1.<Vetype>[%2] - dup\\t%<Vetype>0, %1.<Vetype>[%2] - st1\\t{%1.<Vetype>}[%2], %0" - [(set_attr "type" "neon_to_gp<q>, neon_dup<q>, neon_store1_one_lane<q>")] -) - +{ + emit_insn + (gen_aarch64_get_lane<mode> (operands[0], operands[1], operands[2])); + DONE; +}) diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index bb278d55bba..28080fdca3d 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -46,6 +46,16 @@ #include "recog.h" #include "langhooks.h" #include "diagnostic-core.h" +#include "pointer-set.h" +#include "hash-table.h" +#include "vec.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "optabs.h" @@ -214,6 +224,15 @@ static const struct tune_params generic_tunings = NAMED_PARAM (memmov_cost, 4) }; +static const struct tune_params cortexa53_tunings = +{ + &cortexa53_extra_costs, + &generic_addrcost_table, + &generic_regmove_cost, + &generic_vector_cost, + NAMED_PARAM (memmov_cost, 4) +}; + /* A processor implementing AArch64. */ struct processor { @@ -1684,7 +1703,7 @@ aarch64_frame_pointer_required (void) if (flag_omit_frame_pointer && !faked_omit_frame_pointer) return false; else if (flag_omit_leaf_frame_pointer) - return !crtl->is_leaf; + return !crtl->is_leaf || df_regs_ever_live_p (LR_REGNUM); return true; } @@ -4107,7 +4126,7 @@ aarch64_can_eliminate (const int from, const int to) of faked_omit_frame_pointer here (which is true when we always wish to keep non-leaf frame pointers but only wish to keep leaf frame pointers when LR is clobbered). */ - if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM + if (to == STACK_POINTER_REGNUM && df_regs_ever_live_p (LR_REGNUM) && faked_omit_frame_pointer) return false; diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h index 228115f50fc..cead022c3c0 100644 --- a/gcc/config/aarch64/aarch64.h +++ b/gcc/config/aarch64/aarch64.h @@ -854,4 +854,7 @@ extern enum aarch64_code_model aarch64_cmodel; ((MODE) == V4SImode || (MODE) == V8HImode || (MODE) == V16QImode \ || (MODE) == V4SFmode || (MODE) == V2DImode || mode == V2DFmode) +#define ENDIAN_LANE_N(mode, n) \ + (BYTES_BIG_ENDIAN ? GET_MODE_NUNITS (mode) - 1 - n : n) + #endif /* GCC_AARCH64_H */ diff --git a/gcc/config/aarch64/arm_neon.h b/gcc/config/aarch64/arm_neon.h index c33e4a963b7..03549bd7a27 100644 --- a/gcc/config/aarch64/arm_neon.h +++ b/gcc/config/aarch64/arm_neon.h @@ -4839,259 +4839,6 @@ vaddlvq_u32 (uint32x4_t a) return result; } -__extension__ static __inline float32x2_t __attribute__ ((__always_inline__)) -vbsl_f32 (uint32x2_t a, float32x2_t b, float32x2_t c) -{ - float32x2_t result; - __asm__ ("bsl %0.8b, %2.8b, %3.8b" - : "=w"(result) - : "0"(a), "w"(b), "w"(c) - : /* No clobbers */); - return result; -} - -__extension__ static __inline poly8x8_t __attribute__ ((__always_inline__)) -vbsl_p8 (uint8x8_t a, poly8x8_t b, poly8x8_t c) -{ - poly8x8_t result; - __asm__ ("bsl %0.8b, %2.8b, %3.8b" - : "=w"(result) - : "0"(a), "w"(b), "w"(c) - : /* No clobbers */); - return result; -} - -__extension__ static __inline poly16x4_t __attribute__ ((__always_inline__)) -vbsl_p16 (uint16x4_t a, poly16x4_t b, poly16x4_t c) -{ - poly16x4_t result; - __asm__ ("bsl %0.8b, %2.8b, %3.8b" - : "=w"(result) - : "0"(a), "w"(b), "w"(c) - : /* No clobbers */); - return result; -} - -__extension__ static __inline int8x8_t __attribute__ ((__always_inline__)) -vbsl_s8 (uint8x8_t a, int8x8_t b, int8x8_t c) -{ - int8x8_t result; - __asm__ ("bsl %0.8b, %2.8b, %3.8b" - : "=w"(result) - : "0"(a), "w"(b), "w"(c) - : /* No clobbers */); - return result; -} - -__extension__ static __inline int16x4_t __attribute__ ((__always_inline__)) -vbsl_s16 (uint16x4_t a, int16x4_t b, int16x4_t c) -{ - int16x4_t result; - __asm__ ("bsl %0.8b, %2.8b, %3.8b" - : "=w"(result) - : "0"(a), "w"(b), "w"(c) - : /* No clobbers */); - return result; -} - -__extension__ static __inline int32x2_t __attribute__ ((__always_inline__)) -vbsl_s32 (uint32x2_t a, int32x2_t b, int32x2_t c) -{ - int32x2_t result; - __asm__ ("bsl %0.8b, %2.8b, %3.8b" - : "=w"(result) - : "0"(a), "w"(b), "w"(c) - : /* No clobbers */); - return result; -} - -__extension__ static __inline int64x1_t __attribute__ ((__always_inline__)) -vbsl_s64 (uint64x1_t a, int64x1_t b, int64x1_t c) -{ - int64x1_t result; - __asm__ ("bsl %0.8b, %2.8b, %3.8b" - : "=w"(result) - : "0"(a), "w"(b), "w"(c) - : /* No clobbers */); - return result; -} - -__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__)) -vbsl_u8 (uint8x8_t a, uint8x8_t b, uint8x8_t c) -{ - uint8x8_t result; - __asm__ ("bsl %0.8b, %2.8b, %3.8b" - : "=w"(result) - : "0"(a), "w"(b), "w"(c) - : /* No clobbers */); - return result; -} - -__extension__ static __inline uint16x4_t __attribute__ ((__always_inline__)) -vbsl_u16 (uint16x4_t a, uint16x4_t b, uint16x4_t c) -{ - uint16x4_t result; - __asm__ ("bsl %0.8b, %2.8b, %3.8b" - : "=w"(result) - : "0"(a), "w"(b), "w"(c) - : /* No clobbers */); - return result; -} - -__extension__ static __inline uint32x2_t __attribute__ ((__always_inline__)) -vbsl_u32 (uint32x2_t a, uint32x2_t b, uint32x2_t c) -{ - uint32x2_t result; - __asm__ ("bsl %0.8b, %2.8b, %3.8b" - : "=w"(result) - : "0"(a), "w"(b), "w"(c) - : /* No clobbers */); - return result; -} - -__extension__ static __inline uint64x1_t __attribute__ ((__always_inline__)) -vbsl_u64 (uint64x1_t a, uint64x1_t b, uint64x1_t c) -{ - uint64x1_t result; - __asm__ ("bsl %0.8b, %2.8b, %3.8b" - : "=w"(result) - : "0"(a), "w"(b), "w"(c) - : /* No clobbers */); - return result; -} - -__extension__ static __inline float32x4_t __attribute__ ((__always_inline__)) -vbslq_f32 (uint32x4_t a, float32x4_t b, float32x4_t c) -{ - float32x4_t result; - __asm__ ("bsl %0.16b, %2.16b, %3.16b" - : "=w"(result) - : "0"(a), "w"(b), "w"(c) - : /* No clobbers */); - return result; -} - -__extension__ static __inline float64x2_t __attribute__ ((__always_inline__)) -vbslq_f64 (uint64x2_t a, float64x2_t b, float64x2_t c) -{ - float64x2_t result; - __asm__ ("bsl %0.16b, %2.16b, %3.16b" - : "=w"(result) - : "0"(a), "w"(b), "w"(c) - : /* No clobbers */); - return result; -} - -__extension__ static __inline poly8x16_t __attribute__ ((__always_inline__)) -vbslq_p8 (uint8x16_t a, poly8x16_t b, poly8x16_t c) -{ - poly8x16_t result; - __asm__ ("bsl %0.16b, %2.16b, %3.16b" - : "=w"(result) - : "0"(a), "w"(b), "w"(c) - : /* No clobbers */); - return result; -} - -__extension__ static __inline poly16x8_t __attribute__ ((__always_inline__)) -vbslq_p16 (uint16x8_t a, poly16x8_t b, poly16x8_t c) -{ - poly16x8_t result; - __asm__ ("bsl %0.16b, %2.16b, %3.16b" - : "=w"(result) - : "0"(a), "w"(b), "w"(c) - : /* No clobbers */); - return result; -} - -__extension__ static __inline int8x16_t __attribute__ ((__always_inline__)) -vbslq_s8 (uint8x16_t a, int8x16_t b, int8x16_t c) -{ - int8x16_t result; - __asm__ ("bsl %0.16b, %2.16b, %3.16b" - : "=w"(result) - : "0"(a), "w"(b), "w"(c) - : /* No clobbers */); - return result; -} - -__extension__ static __inline int16x8_t __attribute__ ((__always_inline__)) -vbslq_s16 (uint16x8_t a, int16x8_t b, int16x8_t c) -{ - int16x8_t result; - __asm__ ("bsl %0.16b, %2.16b, %3.16b" - : "=w"(result) - : "0"(a), "w"(b), "w"(c) - : /* No clobbers */); - return result; -} - -__extension__ static __inline int32x4_t __attribute__ ((__always_inline__)) -vbslq_s32 (uint32x4_t a, int32x4_t b, int32x4_t c) -{ - int32x4_t result; - __asm__ ("bsl %0.16b, %2.16b, %3.16b" - : "=w"(result) - : "0"(a), "w"(b), "w"(c) - : /* No clobbers */); - return result; -} - -__extension__ static __inline int64x2_t __attribute__ ((__always_inline__)) -vbslq_s64 (uint64x2_t a, int64x2_t b, int64x2_t c) -{ - int64x2_t result; - __asm__ ("bsl %0.16b, %2.16b, %3.16b" - : "=w"(result) - : "0"(a), "w"(b), "w"(c) - : /* No clobbers */); - return result; -} - -__extension__ static __inline uint8x16_t __attribute__ ((__always_inline__)) -vbslq_u8 (uint8x16_t a, uint8x16_t b, uint8x16_t c) -{ - uint8x16_t result; - __asm__ ("bsl %0.16b, %2.16b, %3.16b" - : "=w"(result) - : "0"(a), "w"(b), "w"(c) - : /* No clobbers */); - return result; -} - -__extension__ static __inline uint16x8_t __attribute__ ((__always_inline__)) -vbslq_u16 (uint16x8_t a, uint16x8_t b, uint16x8_t c) -{ - uint16x8_t result; - __asm__ ("bsl %0.16b, %2.16b, %3.16b" - : "=w"(result) - : "0"(a), "w"(b), "w"(c) - : /* No clobbers */); - return result; -} - -__extension__ static __inline uint32x4_t __attribute__ ((__always_inline__)) -vbslq_u32 (uint32x4_t a, uint32x4_t b, uint32x4_t c) -{ - uint32x4_t result; - __asm__ ("bsl %0.16b, %2.16b, %3.16b" - : "=w"(result) - : "0"(a), "w"(b), "w"(c) - : /* No clobbers */); - return result; -} - -__extension__ static __inline uint64x2_t __attribute__ ((__always_inline__)) -vbslq_u64 (uint64x2_t a, uint64x2_t b, uint64x2_t c) -{ - uint64x2_t result; - __asm__ ("bsl %0.16b, %2.16b, %3.16b" - : "=w"(result) - : "0"(a), "w"(b), "w"(c) - : /* No clobbers */); - return result; -} - __extension__ static __inline int8x8_t __attribute__ ((__always_inline__)) vcls_s8 (int8x8_t a) { @@ -8314,127 +8061,6 @@ vmlsq_u32 (uint32x4_t a, uint32x4_t b, uint32x4_t c) return result; } -__extension__ static __inline float32x2_t __attribute__ ((__always_inline__)) -vmov_n_f32 (float32_t a) -{ - float32x2_t result; - __asm__ ("dup %0.2s, %w1" - : "=w"(result) - : "r"(a) - : /* No clobbers */); - return result; -} - -__extension__ static __inline poly8x8_t __attribute__ ((__always_inline__)) -vmov_n_p8 (uint32_t a) -{ - poly8x8_t result; - __asm__ ("dup %0.8b,%w1" - : "=w"(result) - : "r"(a) - : /* No clobbers */); - return result; -} - -__extension__ static __inline poly16x4_t __attribute__ ((__always_inline__)) -vmov_n_p16 (uint32_t a) -{ - poly16x4_t result; - __asm__ ("dup %0.4h,%w1" - : "=w"(result) - : "r"(a) - : /* No clobbers */); - return result; -} - -__extension__ static __inline int8x8_t __attribute__ ((__always_inline__)) -vmov_n_s8 (int32_t a) -{ - int8x8_t result; - __asm__ ("dup %0.8b,%w1" - : "=w"(result) - : "r"(a) - : /* No clobbers */); - return result; -} - -__extension__ static __inline int16x4_t __attribute__ ((__always_inline__)) -vmov_n_s16 (int32_t a) -{ - int16x4_t result; - __asm__ ("dup %0.4h,%w1" - : "=w"(result) - : "r"(a) - : /* No clobbers */); - return result; -} - -__extension__ static __inline int32x2_t __attribute__ ((__always_inline__)) -vmov_n_s32 (int32_t a) -{ - int32x2_t result; - __asm__ ("dup %0.2s,%w1" - : "=w"(result) - : "r"(a) - : /* No clobbers */); - return result; -} - -__extension__ static __inline int64x1_t __attribute__ ((__always_inline__)) -vmov_n_s64 (int64_t a) -{ - int64x1_t result; - __asm__ ("ins %0.d[0],%x1" - : "=w"(result) - : "r"(a) - : /* No clobbers */); - return result; -} - -__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__)) -vmov_n_u8 (uint32_t a) -{ - uint8x8_t result; - __asm__ ("dup %0.8b,%w1" - : "=w"(result) - : "r"(a) - : /* No clobbers */); - return result; -} - -__extension__ static __inline uint16x4_t __attribute__ ((__always_inline__)) -vmov_n_u16 (uint32_t a) -{ - uint16x4_t result; - __asm__ ("dup %0.4h,%w1" - : "=w"(result) - : "r"(a) - : /* No clobbers */); - return result; -} - -__extension__ static __inline uint32x2_t __attribute__ ((__always_inline__)) -vmov_n_u32 (uint32_t a) -{ - uint32x2_t result; - __asm__ ("dup %0.2s,%w1" - : "=w"(result) - : "r"(a) - : /* No clobbers */); - return result; -} - -__extension__ static __inline uint64x1_t __attribute__ ((__always_inline__)) -vmov_n_u64 (uint64_t a) -{ - uint64x1_t result; - __asm__ ("ins %0.d[0],%x1" - : "=w"(result) - : "r"(a) - : /* No clobbers */); - return result; -} - __extension__ static __inline int16x8_t __attribute__ ((__always_inline__)) vmovl_high_s8 (int8x16_t a) { @@ -8699,133 +8325,6 @@ vmovn_u64 (uint64x2_t a) return result; } -__extension__ static __inline float32x4_t __attribute__ ((__always_inline__)) -vmovq_n_f32 (float32_t a) -{ - float32x4_t result; - __asm__ ("dup %0.4s, %w1" - : "=w"(result) - : "r"(a) - : /* No clobbers */); - return result; -} - -__extension__ static __inline float64x2_t __attribute__ ((__always_inline__)) -vmovq_n_f64 (float64_t a) -{ - return (float64x2_t) {a, a}; -} - -__extension__ static __inline poly8x16_t __attribute__ ((__always_inline__)) -vmovq_n_p8 (uint32_t a) -{ - poly8x16_t result; - __asm__ ("dup %0.16b,%w1" - : "=w"(result) - : "r"(a) - : /* No clobbers */); - return result; -} - -__extension__ static __inline poly16x8_t __attribute__ ((__always_inline__)) -vmovq_n_p16 (uint32_t a) -{ - poly16x8_t result; - __asm__ ("dup %0.8h,%w1" - : "=w"(result) - : "r"(a) - : /* No clobbers */); - return result; -} - -__extension__ static __inline int8x16_t __attribute__ ((__always_inline__)) -vmovq_n_s8 (int32_t a) -{ - int8x16_t result; - __asm__ ("dup %0.16b,%w1" - : "=w"(result) - : "r"(a) - : /* No clobbers */); - return result; -} - -__extension__ static __inline int16x8_t __attribute__ ((__always_inline__)) -vmovq_n_s16 (int32_t a) -{ - int16x8_t result; - __asm__ ("dup %0.8h,%w1" - : "=w"(result) - : "r"(a) - : /* No clobbers */); - return result; -} - -__extension__ static __inline int32x4_t __attribute__ ((__always_inline__)) -vmovq_n_s32 (int32_t a) -{ - int32x4_t result; - __asm__ ("dup %0.4s,%w1" - : "=w"(result) - : "r"(a) - : /* No clobbers */); - return result; -} - -__extension__ static __inline int64x2_t __attribute__ ((__always_inline__)) -vmovq_n_s64 (int64_t a) -{ - int64x2_t result; - __asm__ ("dup %0.2d,%x1" - : "=w"(result) - : "r"(a) - : /* No clobbers */); - return result; -} - -__extension__ static __inline uint8x16_t __attribute__ ((__always_inline__)) -vmovq_n_u8 (uint32_t a) -{ - uint8x16_t result; - __asm__ ("dup %0.16b,%w1" - : "=w"(result) - : "r"(a) - : /* No clobbers */); - return result; -} - -__extension__ static __inline uint16x8_t __attribute__ ((__always_inline__)) -vmovq_n_u16 (uint32_t a) -{ - uint16x8_t result; - __asm__ ("dup %0.8h,%w1" - : "=w"(result) - : "r"(a) - : /* No clobbers */); - return result; -} - -__extension__ static __inline uint32x4_t __attribute__ ((__always_inline__)) -vmovq_n_u32 (uint32_t a) -{ - uint32x4_t result; - __asm__ ("dup %0.4s,%w1" - : "=w"(result) - : "r"(a) - : /* No clobbers */); - return result; -} - -__extension__ static __inline uint64x2_t __attribute__ ((__always_inline__)) -vmovq_n_u64 (uint64_t a) -{ - uint64x2_t result; - __asm__ ("dup %0.2d,%x1" - : "=w"(result) - : "r"(a) - : /* No clobbers */); - return result; -} - __extension__ static __inline float32x2_t __attribute__ ((__always_inline__)) vmul_n_f32 (float32x2_t a, float32_t b) { @@ -15636,54 +15135,6 @@ vtbl4_p8 (poly8x8x4_t tab, uint8x8_t idx) } __extension__ static __inline int8x8_t __attribute__ ((__always_inline__)) -vtbx1_s8 (int8x8_t r, int8x8_t tab, int8x8_t idx) -{ - int8x8_t result; - int8x8_t tmp1; - int8x16_t temp = vcombine_s8 (tab, vcreate_s8 (__AARCH64_UINT64_C (0x0))); - __asm__ ("movi %0.8b, 8\n\t" - "cmhs %0.8b, %3.8b, %0.8b\n\t" - "tbl %1.8b, {%2.16b}, %3.8b\n\t" - "bsl %0.8b, %4.8b, %1.8b\n\t" - : "+w"(result), "=&w"(tmp1) - : "w"(temp), "w"(idx), "w"(r) - : /* No clobbers */); - return result; -} - -__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__)) -vtbx1_u8 (uint8x8_t r, uint8x8_t tab, uint8x8_t idx) -{ - uint8x8_t result; - uint8x8_t tmp1; - uint8x16_t temp = vcombine_u8 (tab, vcreate_u8 (__AARCH64_UINT64_C (0x0))); - __asm__ ("movi %0.8b, 8\n\t" - "cmhs %0.8b, %3.8b, %0.8b\n\t" - "tbl %1.8b, {%2.16b}, %3.8b\n\t" - "bsl %0.8b, %4.8b, %1.8b\n\t" - : "+w"(result), "=&w"(tmp1) - : "w"(temp), "w"(idx), "w"(r) - : /* No clobbers */); - return result; -} - -__extension__ static __inline poly8x8_t __attribute__ ((__always_inline__)) -vtbx1_p8 (poly8x8_t r, poly8x8_t tab, uint8x8_t idx) -{ - poly8x8_t result; - poly8x8_t tmp1; - poly8x16_t temp = vcombine_p8 (tab, vcreate_p8 (__AARCH64_UINT64_C (0x0))); - __asm__ ("movi %0.8b, 8\n\t" - "cmhs %0.8b, %3.8b, %0.8b\n\t" - "tbl %1.8b, {%2.16b}, %3.8b\n\t" - "bsl %0.8b, %4.8b, %1.8b\n\t" - : "+w"(result), "=&w"(tmp1) - : "w"(temp), "w"(idx), "w"(r) - : /* No clobbers */); - return result; -} - -__extension__ static __inline int8x8_t __attribute__ ((__always_inline__)) vtbx2_s8 (int8x8_t r, int8x8x2_t tab, int8x8_t idx) { int8x8_t result = r; @@ -15720,63 +15171,6 @@ vtbx2_p8 (poly8x8_t r, poly8x8x2_t tab, uint8x8_t idx) } __extension__ static __inline int8x8_t __attribute__ ((__always_inline__)) -vtbx3_s8 (int8x8_t r, int8x8x3_t tab, int8x8_t idx) -{ - int8x8_t result; - int8x8_t tmp1; - int8x16x2_t temp; - temp.val[0] = vcombine_s8 (tab.val[0], tab.val[1]); - temp.val[1] = vcombine_s8 (tab.val[2], vcreate_s8 (__AARCH64_UINT64_C (0x0))); - __asm__ ("ld1 {v16.16b - v17.16b}, %2\n\t" - "movi %0.8b, 24\n\t" - "cmhs %0.8b, %3.8b, %0.8b\n\t" - "tbl %1.8b, {v16.16b - v17.16b}, %3.8b\n\t" - "bsl %0.8b, %4.8b, %1.8b\n\t" - : "+w"(result), "=&w"(tmp1) - : "Q"(temp), "w"(idx), "w"(r) - : "v16", "v17", "memory"); - return result; -} - -__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__)) -vtbx3_u8 (uint8x8_t r, uint8x8x3_t tab, uint8x8_t idx) -{ - uint8x8_t result; - uint8x8_t tmp1; - uint8x16x2_t temp; - temp.val[0] = vcombine_u8 (tab.val[0], tab.val[1]); - temp.val[1] = vcombine_u8 (tab.val[2], vcreate_u8 (__AARCH64_UINT64_C (0x0))); - __asm__ ("ld1 {v16.16b - v17.16b}, %2\n\t" - "movi %0.8b, 24\n\t" - "cmhs %0.8b, %3.8b, %0.8b\n\t" - "tbl %1.8b, {v16.16b - v17.16b}, %3.8b\n\t" - "bsl %0.8b, %4.8b, %1.8b\n\t" - : "+w"(result), "=&w"(tmp1) - : "Q"(temp), "w"(idx), "w"(r) - : "v16", "v17", "memory"); - return result; -} - -__extension__ static __inline poly8x8_t __attribute__ ((__always_inline__)) -vtbx3_p8 (poly8x8_t r, poly8x8x3_t tab, uint8x8_t idx) -{ - poly8x8_t result; - poly8x8_t tmp1; - poly8x16x2_t temp; - temp.val[0] = vcombine_p8 (tab.val[0], tab.val[1]); - temp.val[1] = vcombine_p8 (tab.val[2], vcreate_p8 (__AARCH64_UINT64_C (0x0))); - __asm__ ("ld1 {v16.16b - v17.16b}, %2\n\t" - "movi %0.8b, 24\n\t" - "cmhs %0.8b, %3.8b, %0.8b\n\t" - "tbl %1.8b, {v16.16b - v17.16b}, %3.8b\n\t" - "bsl %0.8b, %4.8b, %1.8b\n\t" - : "+w"(result), "=&w"(tmp1) - : "Q"(temp), "w"(idx), "w"(r) - : "v16", "v17", "memory"); - return result; -} - -__extension__ static __inline int8x8_t __attribute__ ((__always_inline__)) vtbx4_s8 (int8x8_t r, int8x8x4_t tab, int8x8_t idx) { int8x8_t result = r; @@ -15913,118 +15307,272 @@ vaddd_u64 (uint64x1_t __a, uint64x1_t __b) return __a + __b; } +#if __AARCH64EB__ +#define __LANE0(__t) ((__t) - 1) +#else +#define __LANE0(__t) 0 +#endif + /* vaddv */ __extension__ static __inline int8_t __attribute__ ((__always_inline__)) vaddv_s8 (int8x8_t __a) { - return vget_lane_s8 (__builtin_aarch64_reduc_splus_v8qi (__a), 0); + return vget_lane_s8 (__builtin_aarch64_reduc_splus_v8qi (__a), __LANE0 (8)); } __extension__ static __inline int16_t __attribute__ ((__always_inline__)) vaddv_s16 (int16x4_t __a) { - return vget_lane_s16 (__builtin_aarch64_reduc_splus_v4hi (__a), 0); + return vget_lane_s16 (__builtin_aarch64_reduc_splus_v4hi (__a), __LANE0 (4)); } __extension__ static __inline int32_t __attribute__ ((__always_inline__)) vaddv_s32 (int32x2_t __a) { - return vget_lane_s32 (__builtin_aarch64_reduc_splus_v2si (__a), 0); + return vget_lane_s32 (__builtin_aarch64_reduc_splus_v2si (__a), __LANE0 (2)); } __extension__ static __inline uint8_t __attribute__ ((__always_inline__)) vaddv_u8 (uint8x8_t __a) { return vget_lane_u8 ((uint8x8_t) - __builtin_aarch64_reduc_uplus_v8qi ((int8x8_t) __a), 0); + __builtin_aarch64_reduc_uplus_v8qi ((int8x8_t) __a), + __LANE0 (8)); } __extension__ static __inline uint16_t __attribute__ ((__always_inline__)) vaddv_u16 (uint16x4_t __a) { return vget_lane_u16 ((uint16x4_t) - __builtin_aarch64_reduc_uplus_v4hi ((int16x4_t) __a), 0); + __builtin_aarch64_reduc_uplus_v4hi ((int16x4_t) __a), + __LANE0 (4)); } __extension__ static __inline uint32_t __attribute__ ((__always_inline__)) vaddv_u32 (uint32x2_t __a) { return vget_lane_u32 ((uint32x2_t) - __builtin_aarch64_reduc_uplus_v2si ((int32x2_t) __a), 0); + __builtin_aarch64_reduc_uplus_v2si ((int32x2_t) __a), + __LANE0 (2)); } __extension__ static __inline int8_t __attribute__ ((__always_inline__)) vaddvq_s8 (int8x16_t __a) { - return vgetq_lane_s8 (__builtin_aarch64_reduc_splus_v16qi (__a), 0); + return vgetq_lane_s8 (__builtin_aarch64_reduc_splus_v16qi (__a), + __LANE0 (16)); } __extension__ static __inline int16_t __attribute__ ((__always_inline__)) vaddvq_s16 (int16x8_t __a) { - return vgetq_lane_s16 (__builtin_aarch64_reduc_splus_v8hi (__a), 0); + return vgetq_lane_s16 (__builtin_aarch64_reduc_splus_v8hi (__a), __LANE0 (8)); } __extension__ static __inline int32_t __attribute__ ((__always_inline__)) vaddvq_s32 (int32x4_t __a) { - return vgetq_lane_s32 (__builtin_aarch64_reduc_splus_v4si (__a), 0); + return vgetq_lane_s32 (__builtin_aarch64_reduc_splus_v4si (__a), __LANE0 (4)); } __extension__ static __inline int64_t __attribute__ ((__always_inline__)) vaddvq_s64 (int64x2_t __a) { - return vgetq_lane_s64 (__builtin_aarch64_reduc_splus_v2di (__a), 0); + return vgetq_lane_s64 (__builtin_aarch64_reduc_splus_v2di (__a), __LANE0 (2)); } __extension__ static __inline uint8_t __attribute__ ((__always_inline__)) vaddvq_u8 (uint8x16_t __a) { return vgetq_lane_u8 ((uint8x16_t) - __builtin_aarch64_reduc_uplus_v16qi ((int8x16_t) __a), 0); + __builtin_aarch64_reduc_uplus_v16qi ((int8x16_t) __a), + __LANE0 (16)); } __extension__ static __inline uint16_t __attribute__ ((__always_inline__)) vaddvq_u16 (uint16x8_t __a) { return vgetq_lane_u16 ((uint16x8_t) - __builtin_aarch64_reduc_uplus_v8hi ((int16x8_t) __a), 0); + __builtin_aarch64_reduc_uplus_v8hi ((int16x8_t) __a), + __LANE0 (8)); } __extension__ static __inline uint32_t __attribute__ ((__always_inline__)) vaddvq_u32 (uint32x4_t __a) { return vgetq_lane_u32 ((uint32x4_t) - __builtin_aarch64_reduc_uplus_v4si ((int32x4_t) __a), 0); + __builtin_aarch64_reduc_uplus_v4si ((int32x4_t) __a), + __LANE0 (4)); } __extension__ static __inline uint64_t __attribute__ ((__always_inline__)) vaddvq_u64 (uint64x2_t __a) { return vgetq_lane_u64 ((uint64x2_t) - __builtin_aarch64_reduc_uplus_v2di ((int64x2_t) __a), 0); + __builtin_aarch64_reduc_uplus_v2di ((int64x2_t) __a), + __LANE0 (2)); } __extension__ static __inline float32_t __attribute__ ((__always_inline__)) vaddv_f32 (float32x2_t __a) { - float32x2_t t = __builtin_aarch64_reduc_splus_v2sf (__a); - return vget_lane_f32 (t, 0); + float32x2_t __t = __builtin_aarch64_reduc_splus_v2sf (__a); + return vget_lane_f32 (__t, __LANE0 (2)); } __extension__ static __inline float32_t __attribute__ ((__always_inline__)) vaddvq_f32 (float32x4_t __a) { - float32x4_t t = __builtin_aarch64_reduc_splus_v4sf (__a); - return vgetq_lane_f32 (t, 0); + float32x4_t __t = __builtin_aarch64_reduc_splus_v4sf (__a); + return vgetq_lane_f32 (__t, __LANE0 (4)); } __extension__ static __inline float64_t __attribute__ ((__always_inline__)) vaddvq_f64 (float64x2_t __a) { - float64x2_t t = __builtin_aarch64_reduc_splus_v2df (__a); - return vgetq_lane_f64 (t, 0); + float64x2_t __t = __builtin_aarch64_reduc_splus_v2df (__a); + return vgetq_lane_f64 (__t, __LANE0 (2)); +} + +/* vbsl */ + +__extension__ static __inline float32x2_t __attribute__ ((__always_inline__)) +vbsl_f32 (uint32x2_t __a, float32x2_t __b, float32x2_t __c) +{ + return __builtin_aarch64_simd_bslv2sf_suss (__a, __b, __c); +} + +__extension__ static __inline poly8x8_t __attribute__ ((__always_inline__)) +vbsl_p8 (uint8x8_t __a, poly8x8_t __b, poly8x8_t __c) +{ + return __builtin_aarch64_simd_bslv8qi_pupp (__a, __b, __c); +} + +__extension__ static __inline poly16x4_t __attribute__ ((__always_inline__)) +vbsl_p16 (uint16x4_t __a, poly16x4_t __b, poly16x4_t __c) +{ + return __builtin_aarch64_simd_bslv4hi_pupp (__a, __b, __c); +} + +__extension__ static __inline int8x8_t __attribute__ ((__always_inline__)) +vbsl_s8 (uint8x8_t __a, int8x8_t __b, int8x8_t __c) +{ + return __builtin_aarch64_simd_bslv8qi_suss (__a, __b, __c); +} + +__extension__ static __inline int16x4_t __attribute__ ((__always_inline__)) +vbsl_s16 (uint16x4_t __a, int16x4_t __b, int16x4_t __c) +{ + return __builtin_aarch64_simd_bslv4hi_suss (__a, __b, __c); +} + +__extension__ static __inline int32x2_t __attribute__ ((__always_inline__)) +vbsl_s32 (uint32x2_t __a, int32x2_t __b, int32x2_t __c) +{ + return __builtin_aarch64_simd_bslv2si_suss (__a, __b, __c); +} + +__extension__ static __inline int64x1_t __attribute__ ((__always_inline__)) +vbsl_s64 (uint64x1_t __a, int64x1_t __b, int64x1_t __c) +{ + return __builtin_aarch64_simd_bsldi_suss (__a, __b, __c); +} + +__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__)) +vbsl_u8 (uint8x8_t __a, uint8x8_t __b, uint8x8_t __c) +{ + return __builtin_aarch64_simd_bslv8qi_uuuu (__a, __b, __c); +} + +__extension__ static __inline uint16x4_t __attribute__ ((__always_inline__)) +vbsl_u16 (uint16x4_t __a, uint16x4_t __b, uint16x4_t __c) +{ + return __builtin_aarch64_simd_bslv4hi_uuuu (__a, __b, __c); +} + +__extension__ static __inline uint32x2_t __attribute__ ((__always_inline__)) +vbsl_u32 (uint32x2_t __a, uint32x2_t __b, uint32x2_t __c) +{ + return __builtin_aarch64_simd_bslv2si_uuuu (__a, __b, __c); +} + +__extension__ static __inline uint64x1_t __attribute__ ((__always_inline__)) +vbsl_u64 (uint64x1_t __a, uint64x1_t __b, uint64x1_t __c) +{ + return __builtin_aarch64_simd_bsldi_uuuu (__a, __b, __c); +} + +__extension__ static __inline float32x4_t __attribute__ ((__always_inline__)) +vbslq_f32 (uint32x4_t __a, float32x4_t __b, float32x4_t __c) +{ + return __builtin_aarch64_simd_bslv4sf_suss (__a, __b, __c); +} + +__extension__ static __inline float64x2_t __attribute__ ((__always_inline__)) +vbslq_f64 (uint64x2_t __a, float64x2_t __b, float64x2_t __c) +{ + return __builtin_aarch64_simd_bslv2df_suss (__a, __b, __c); +} + +__extension__ static __inline poly8x16_t __attribute__ ((__always_inline__)) +vbslq_p8 (uint8x16_t __a, poly8x16_t __b, poly8x16_t __c) +{ + return __builtin_aarch64_simd_bslv16qi_pupp (__a, __b, __c); +} + +__extension__ static __inline poly16x8_t __attribute__ ((__always_inline__)) +vbslq_p16 (uint16x8_t __a, poly16x8_t __b, poly16x8_t __c) +{ + return __builtin_aarch64_simd_bslv8hi_pupp (__a, __b, __c); +} + +__extension__ static __inline int8x16_t __attribute__ ((__always_inline__)) +vbslq_s8 (uint8x16_t __a, int8x16_t __b, int8x16_t __c) +{ + return __builtin_aarch64_simd_bslv16qi_suss (__a, __b, __c); +} + +__extension__ static __inline int16x8_t __attribute__ ((__always_inline__)) +vbslq_s16 (uint16x8_t __a, int16x8_t __b, int16x8_t __c) +{ + return __builtin_aarch64_simd_bslv8hi_suss (__a, __b, __c); +} + +__extension__ static __inline int32x4_t __attribute__ ((__always_inline__)) +vbslq_s32 (uint32x4_t __a, int32x4_t __b, int32x4_t __c) +{ + return __builtin_aarch64_simd_bslv4si_suss (__a, __b, __c); +} + +__extension__ static __inline int64x2_t __attribute__ ((__always_inline__)) +vbslq_s64 (uint64x2_t __a, int64x2_t __b, int64x2_t __c) +{ + return __builtin_aarch64_simd_bslv2di_suss (__a, __b, __c); +} + +__extension__ static __inline uint8x16_t __attribute__ ((__always_inline__)) +vbslq_u8 (uint8x16_t __a, uint8x16_t __b, uint8x16_t __c) +{ + return __builtin_aarch64_simd_bslv16qi_uuuu (__a, __b, __c); +} + +__extension__ static __inline uint16x8_t __attribute__ ((__always_inline__)) +vbslq_u16 (uint16x8_t __a, uint16x8_t __b, uint16x8_t __c) +{ + return __builtin_aarch64_simd_bslv8hi_uuuu (__a, __b, __c); +} + +__extension__ static __inline uint32x4_t __attribute__ ((__always_inline__)) +vbslq_u32 (uint32x4_t __a, uint32x4_t __b, uint32x4_t __c) +{ + return __builtin_aarch64_simd_bslv4si_uuuu (__a, __b, __c); +} + +__extension__ static __inline uint64x2_t __attribute__ ((__always_inline__)) +vbslq_u64 (uint64x2_t __a, uint64x2_t __b, uint64x2_t __c) +{ + return __builtin_aarch64_simd_bslv2di_uuuu (__a, __b, __c); } /* vcage */ @@ -20265,97 +19813,106 @@ vmaxnmq_f64 (float64x2_t __a, float64x2_t __b) __extension__ static __inline float32_t __attribute__ ((__always_inline__)) vmaxv_f32 (float32x2_t __a) { - return vget_lane_f32 (__builtin_aarch64_reduc_smax_nan_v2sf (__a), 0); + return vget_lane_f32 (__builtin_aarch64_reduc_smax_nan_v2sf (__a), + __LANE0 (2)); } __extension__ static __inline int8_t __attribute__ ((__always_inline__)) vmaxv_s8 (int8x8_t __a) { - return vget_lane_s8 (__builtin_aarch64_reduc_smax_v8qi (__a), 0); + return vget_lane_s8 (__builtin_aarch64_reduc_smax_v8qi (__a), __LANE0 (8)); } __extension__ static __inline int16_t __attribute__ ((__always_inline__)) vmaxv_s16 (int16x4_t __a) { - return vget_lane_s16 (__builtin_aarch64_reduc_smax_v4hi (__a), 0); + return vget_lane_s16 (__builtin_aarch64_reduc_smax_v4hi (__a), __LANE0 (4)); } __extension__ static __inline int32_t __attribute__ ((__always_inline__)) vmaxv_s32 (int32x2_t __a) { - return vget_lane_s32 (__builtin_aarch64_reduc_smax_v2si (__a), 0); + return vget_lane_s32 (__builtin_aarch64_reduc_smax_v2si (__a), __LANE0 (2)); } __extension__ static __inline uint8_t __attribute__ ((__always_inline__)) vmaxv_u8 (uint8x8_t __a) { return vget_lane_u8 ((uint8x8_t) - __builtin_aarch64_reduc_umax_v8qi ((int8x8_t) __a), 0); + __builtin_aarch64_reduc_umax_v8qi ((int8x8_t) __a), + __LANE0 (8)); } __extension__ static __inline uint16_t __attribute__ ((__always_inline__)) vmaxv_u16 (uint16x4_t __a) { return vget_lane_u16 ((uint16x4_t) - __builtin_aarch64_reduc_umax_v4hi ((int16x4_t) __a), 0); + __builtin_aarch64_reduc_umax_v4hi ((int16x4_t) __a), + __LANE0 (4)); } __extension__ static __inline uint32_t __attribute__ ((__always_inline__)) vmaxv_u32 (uint32x2_t __a) { return vget_lane_u32 ((uint32x2_t) - __builtin_aarch64_reduc_umax_v2si ((int32x2_t) __a), 0); + __builtin_aarch64_reduc_umax_v2si ((int32x2_t) __a), + __LANE0 (2)); } __extension__ static __inline float32_t __attribute__ ((__always_inline__)) vmaxvq_f32 (float32x4_t __a) { - return vgetq_lane_f32 (__builtin_aarch64_reduc_smax_nan_v4sf (__a), 0); + return vgetq_lane_f32 (__builtin_aarch64_reduc_smax_nan_v4sf (__a), + __LANE0 (4)); } __extension__ static __inline float64_t __attribute__ ((__always_inline__)) vmaxvq_f64 (float64x2_t __a) { - return vgetq_lane_f64 (__builtin_aarch64_reduc_smax_nan_v2df (__a), 0); + return vgetq_lane_f64 (__builtin_aarch64_reduc_smax_nan_v2df (__a), + __LANE0 (2)); } __extension__ static __inline int8_t __attribute__ ((__always_inline__)) vmaxvq_s8 (int8x16_t __a) { - return vgetq_lane_s8 (__builtin_aarch64_reduc_smax_v16qi (__a), 0); + return vgetq_lane_s8 (__builtin_aarch64_reduc_smax_v16qi (__a), __LANE0 (16)); } __extension__ static __inline int16_t __attribute__ ((__always_inline__)) vmaxvq_s16 (int16x8_t __a) { - return vgetq_lane_s16 (__builtin_aarch64_reduc_smax_v8hi (__a), 0); + return vgetq_lane_s16 (__builtin_aarch64_reduc_smax_v8hi (__a), __LANE0 (8)); } __extension__ static __inline int32_t __attribute__ ((__always_inline__)) vmaxvq_s32 (int32x4_t __a) { - return vgetq_lane_s32 (__builtin_aarch64_reduc_smax_v4si (__a), 0); + return vgetq_lane_s32 (__builtin_aarch64_reduc_smax_v4si (__a), __LANE0 (4)); } __extension__ static __inline uint8_t __attribute__ ((__always_inline__)) vmaxvq_u8 (uint8x16_t __a) { return vgetq_lane_u8 ((uint8x16_t) - __builtin_aarch64_reduc_umax_v16qi ((int8x16_t) __a), 0); + __builtin_aarch64_reduc_umax_v16qi ((int8x16_t) __a), + __LANE0 (16)); } __extension__ static __inline uint16_t __attribute__ ((__always_inline__)) vmaxvq_u16 (uint16x8_t __a) { return vgetq_lane_u16 ((uint16x8_t) - __builtin_aarch64_reduc_umax_v8hi ((int16x8_t) __a), 0); + __builtin_aarch64_reduc_umax_v8hi ((int16x8_t) __a), + __LANE0 (8)); } __extension__ static __inline uint32_t __attribute__ ((__always_inline__)) vmaxvq_u32 (uint32x4_t __a) { return vgetq_lane_u32 ((uint32x4_t) - __builtin_aarch64_reduc_umax_v4si ((int32x4_t) __a), 0); + __builtin_aarch64_reduc_umax_v4si ((int32x4_t) __a), + __LANE0 (4)); } /* vmaxnmv */ @@ -20363,19 +19920,20 @@ vmaxvq_u32 (uint32x4_t __a) __extension__ static __inline float32_t __attribute__ ((__always_inline__)) vmaxnmv_f32 (float32x2_t __a) { - return vget_lane_f32 (__builtin_aarch64_reduc_smax_v2sf (__a), 0); + return vget_lane_f32 (__builtin_aarch64_reduc_smax_v2sf (__a), + __LANE0 (2)); } __extension__ static __inline float32_t __attribute__ ((__always_inline__)) vmaxnmvq_f32 (float32x4_t __a) { - return vgetq_lane_f32 (__builtin_aarch64_reduc_smax_v4sf (__a), 0); + return vgetq_lane_f32 (__builtin_aarch64_reduc_smax_v4sf (__a), __LANE0 (4)); } __extension__ static __inline float64_t __attribute__ ((__always_inline__)) vmaxnmvq_f64 (float64x2_t __a) { - return vgetq_lane_f64 (__builtin_aarch64_reduc_smax_v2df (__a), 0); + return vgetq_lane_f64 (__builtin_aarch64_reduc_smax_v2df (__a), __LANE0 (2)); } /* vmin */ @@ -20501,97 +20059,107 @@ vminnmq_f64 (float64x2_t __a, float64x2_t __b) __extension__ static __inline float32_t __attribute__ ((__always_inline__)) vminv_f32 (float32x2_t __a) { - return vget_lane_f32 (__builtin_aarch64_reduc_smin_nan_v2sf (__a), 0); + return vget_lane_f32 (__builtin_aarch64_reduc_smin_nan_v2sf (__a), + __LANE0 (2)); } __extension__ static __inline int8_t __attribute__ ((__always_inline__)) vminv_s8 (int8x8_t __a) { - return vget_lane_s8 (__builtin_aarch64_reduc_smin_v8qi (__a), 0); + return vget_lane_s8 (__builtin_aarch64_reduc_smin_v8qi (__a), + __LANE0 (8)); } __extension__ static __inline int16_t __attribute__ ((__always_inline__)) vminv_s16 (int16x4_t __a) { - return vget_lane_s16 (__builtin_aarch64_reduc_smin_v4hi (__a), 0); + return vget_lane_s16 (__builtin_aarch64_reduc_smin_v4hi (__a), __LANE0 (4)); } __extension__ static __inline int32_t __attribute__ ((__always_inline__)) vminv_s32 (int32x2_t __a) { - return vget_lane_s32 (__builtin_aarch64_reduc_smin_v2si (__a), 0); + return vget_lane_s32 (__builtin_aarch64_reduc_smin_v2si (__a), __LANE0 (2)); } __extension__ static __inline uint8_t __attribute__ ((__always_inline__)) vminv_u8 (uint8x8_t __a) { return vget_lane_u8 ((uint8x8_t) - __builtin_aarch64_reduc_umin_v8qi ((int8x8_t) __a), 0); + __builtin_aarch64_reduc_umin_v8qi ((int8x8_t) __a), + __LANE0 (8)); } __extension__ static __inline uint16_t __attribute__ ((__always_inline__)) vminv_u16 (uint16x4_t __a) { return vget_lane_u16 ((uint16x4_t) - __builtin_aarch64_reduc_umin_v4hi ((int16x4_t) __a), 0); + __builtin_aarch64_reduc_umin_v4hi ((int16x4_t) __a), + __LANE0 (4)); } __extension__ static __inline uint32_t __attribute__ ((__always_inline__)) vminv_u32 (uint32x2_t __a) { return vget_lane_u32 ((uint32x2_t) - __builtin_aarch64_reduc_umin_v2si ((int32x2_t) __a), 0); + __builtin_aarch64_reduc_umin_v2si ((int32x2_t) __a), + __LANE0 (2)); } __extension__ static __inline float32_t __attribute__ ((__always_inline__)) vminvq_f32 (float32x4_t __a) { - return vgetq_lane_f32 (__builtin_aarch64_reduc_smin_nan_v4sf (__a), 0); + return vgetq_lane_f32 (__builtin_aarch64_reduc_smin_nan_v4sf (__a), + __LANE0 (4)); } __extension__ static __inline float64_t __attribute__ ((__always_inline__)) vminvq_f64 (float64x2_t __a) { - return vgetq_lane_f64 (__builtin_aarch64_reduc_smin_nan_v2df (__a), 0); + return vgetq_lane_f64 (__builtin_aarch64_reduc_smin_nan_v2df (__a), + __LANE0 (2)); } __extension__ static __inline int8_t __attribute__ ((__always_inline__)) vminvq_s8 (int8x16_t __a) { - return vgetq_lane_s8 (__builtin_aarch64_reduc_smin_v16qi (__a), 0); + return vgetq_lane_s8 (__builtin_aarch64_reduc_smin_v16qi (__a), __LANE0 (16)); } __extension__ static __inline int16_t __attribute__ ((__always_inline__)) vminvq_s16 (int16x8_t __a) { - return vgetq_lane_s16 (__builtin_aarch64_reduc_smin_v8hi (__a), 0); + return vgetq_lane_s16 (__builtin_aarch64_reduc_smin_v8hi (__a), __LANE0 (8)); } __extension__ static __inline int32_t __attribute__ ((__always_inline__)) vminvq_s32 (int32x4_t __a) { - return vgetq_lane_s32 (__builtin_aarch64_reduc_smin_v4si (__a), 0); + return vgetq_lane_s32 (__builtin_aarch64_reduc_smin_v4si (__a), __LANE0 (4)); } __extension__ static __inline uint8_t __attribute__ ((__always_inline__)) vminvq_u8 (uint8x16_t __a) { return vgetq_lane_u8 ((uint8x16_t) - __builtin_aarch64_reduc_umin_v16qi ((int8x16_t) __a), 0); + __builtin_aarch64_reduc_umin_v16qi ((int8x16_t) __a), + __LANE0 (16)); } __extension__ static __inline uint16_t __attribute__ ((__always_inline__)) vminvq_u16 (uint16x8_t __a) { return vgetq_lane_u16 ((uint16x8_t) - __builtin_aarch64_reduc_umin_v8hi ((int16x8_t) __a), 0); + __builtin_aarch64_reduc_umin_v8hi ((int16x8_t) __a), + __LANE0 (8)); } __extension__ static __inline uint32_t __attribute__ ((__always_inline__)) vminvq_u32 (uint32x4_t __a) { return vgetq_lane_u32 ((uint32x4_t) - __builtin_aarch64_reduc_umin_v4si ((int32x4_t) __a), 0); + __builtin_aarch64_reduc_umin_v4si ((int32x4_t) __a), + __LANE0 (4)); } /* vminnmv */ @@ -20599,19 +20167,19 @@ vminvq_u32 (uint32x4_t __a) __extension__ static __inline float32_t __attribute__ ((__always_inline__)) vminnmv_f32 (float32x2_t __a) { - return vget_lane_f32 (__builtin_aarch64_reduc_smin_v2sf (__a), 0); + return vget_lane_f32 (__builtin_aarch64_reduc_smin_v2sf (__a), __LANE0 (2)); } __extension__ static __inline float32_t __attribute__ ((__always_inline__)) vminnmvq_f32 (float32x4_t __a) { - return vgetq_lane_f32 (__builtin_aarch64_reduc_smin_v4sf (__a), 0); + return vgetq_lane_f32 (__builtin_aarch64_reduc_smin_v4sf (__a), __LANE0 (4)); } __extension__ static __inline float64_t __attribute__ ((__always_inline__)) vminnmvq_f64 (float64x2_t __a) { - return vgetq_lane_f64 (__builtin_aarch64_reduc_smin_v2df (__a), 0); + return vgetq_lane_f64 (__builtin_aarch64_reduc_smin_v2df (__a), __LANE0 (2)); } /* vmla */ @@ -20949,6 +20517,152 @@ vmlsq_laneq_u32 (uint32x4_t __a, uint32x4_t __b, return (__a - (__b * __aarch64_vgetq_lane_u32 (__c, __lane))); } +/* vmov_n_ */ + +__extension__ static __inline float32x2_t __attribute__ ((__always_inline__)) +vmov_n_f32 (float32_t __a) +{ + return vdup_n_f32 (__a); +} + +__extension__ static __inline float64x1_t __attribute__ ((__always_inline__)) +vmov_n_f64 (float64_t __a) +{ + return __a; +} + +__extension__ static __inline poly8x8_t __attribute__ ((__always_inline__)) +vmov_n_p8 (poly8_t __a) +{ + return vdup_n_p8 (__a); +} + +__extension__ static __inline poly16x4_t __attribute__ ((__always_inline__)) +vmov_n_p16 (poly16_t __a) +{ + return vdup_n_p16 (__a); +} + +__extension__ static __inline int8x8_t __attribute__ ((__always_inline__)) +vmov_n_s8 (int8_t __a) +{ + return vdup_n_s8 (__a); +} + +__extension__ static __inline int16x4_t __attribute__ ((__always_inline__)) +vmov_n_s16 (int16_t __a) +{ + return vdup_n_s16 (__a); +} + +__extension__ static __inline int32x2_t __attribute__ ((__always_inline__)) +vmov_n_s32 (int32_t __a) +{ + return vdup_n_s32 (__a); +} + +__extension__ static __inline int64x1_t __attribute__ ((__always_inline__)) +vmov_n_s64 (int64_t __a) +{ + return __a; +} + +__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__)) +vmov_n_u8 (uint8_t __a) +{ + return vdup_n_u8 (__a); +} + +__extension__ static __inline uint16x4_t __attribute__ ((__always_inline__)) +vmov_n_u16 (uint16_t __a) +{ + return vdup_n_u16 (__a); +} + +__extension__ static __inline uint32x2_t __attribute__ ((__always_inline__)) +vmov_n_u32 (uint32_t __a) +{ + return vdup_n_u32 (__a); +} + +__extension__ static __inline uint64x1_t __attribute__ ((__always_inline__)) +vmov_n_u64 (uint64_t __a) +{ + return __a; +} + +__extension__ static __inline float32x4_t __attribute__ ((__always_inline__)) +vmovq_n_f32 (float32_t __a) +{ + return vdupq_n_f32 (__a); +} + +__extension__ static __inline float64x2_t __attribute__ ((__always_inline__)) +vmovq_n_f64 (float64_t __a) +{ + return vdupq_n_f64 (__a); +} + +__extension__ static __inline poly8x16_t __attribute__ ((__always_inline__)) +vmovq_n_p8 (poly8_t __a) +{ + return vdupq_n_p8 (__a); +} + +__extension__ static __inline poly16x8_t __attribute__ ((__always_inline__)) +vmovq_n_p16 (poly16_t __a) +{ + return vdupq_n_p16 (__a); +} + +__extension__ static __inline int8x16_t __attribute__ ((__always_inline__)) +vmovq_n_s8 (int8_t __a) +{ + return vdupq_n_s8 (__a); +} + +__extension__ static __inline int16x8_t __attribute__ ((__always_inline__)) +vmovq_n_s16 (int16_t __a) +{ + return vdupq_n_s16 (__a); +} + +__extension__ static __inline int32x4_t __attribute__ ((__always_inline__)) +vmovq_n_s32 (int32_t __a) +{ + return vdupq_n_s32 (__a); +} + +__extension__ static __inline int64x2_t __attribute__ ((__always_inline__)) +vmovq_n_s64 (int64_t __a) +{ + return vdupq_n_s64 (__a); +} + +__extension__ static __inline uint8x16_t __attribute__ ((__always_inline__)) +vmovq_n_u8 (uint8_t __a) +{ + return vdupq_n_u8 (__a); +} + +__extension__ static __inline uint16x8_t __attribute__ ((__always_inline__)) +vmovq_n_u16 (uint16_t __a) +{ + return vdupq_n_u16 (__a); +} + +__extension__ static __inline uint32x4_t __attribute__ ((__always_inline__)) +vmovq_n_u32 (uint32_t __a) +{ + return vdupq_n_u32 (__a); +} + +__extension__ static __inline uint64x2_t __attribute__ ((__always_inline__)) +vmovq_n_u64 (uint64_t __a) +{ + return vdupq_n_u64 (__a); +} + /* vmul_lane */ __extension__ static __inline float32x2_t __attribute__ ((__always_inline__)) @@ -25101,6 +24815,66 @@ vsubd_u64 (uint64x1_t __a, uint64x1_t __b) return __a - __b; } +/* vtbx1 */ + +__extension__ static __inline int8x8_t __attribute__ ((__always_inline__)) +vtbx1_s8 (int8x8_t __r, int8x8_t __tab, int8x8_t __idx) +{ + uint8x8_t __mask = vclt_u8 (vreinterpret_u8_s8 (__idx), + vmov_n_u8 (8)); + int8x8_t __tbl = vtbl1_s8 (__tab, __idx); + + return vbsl_s8 (__mask, __tbl, __r); +} + +__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__)) +vtbx1_u8 (uint8x8_t __r, uint8x8_t __tab, uint8x8_t __idx) +{ + uint8x8_t __mask = vclt_u8 (__idx, vmov_n_u8 (8)); + uint8x8_t __tbl = vtbl1_u8 (__tab, __idx); + + return vbsl_u8 (__mask, __tbl, __r); +} + +__extension__ static __inline poly8x8_t __attribute__ ((__always_inline__)) +vtbx1_p8 (poly8x8_t __r, poly8x8_t __tab, uint8x8_t __idx) +{ + uint8x8_t __mask = vclt_u8 (__idx, vmov_n_u8 (8)); + poly8x8_t __tbl = vtbl1_p8 (__tab, __idx); + + return vbsl_p8 (__mask, __tbl, __r); +} + +/* vtbx3 */ + +__extension__ static __inline int8x8_t __attribute__ ((__always_inline__)) +vtbx3_s8 (int8x8_t __r, int8x8x3_t __tab, int8x8_t __idx) +{ + uint8x8_t __mask = vclt_u8 (vreinterpret_u8_s8 (__idx), + vmov_n_u8 (24)); + int8x8_t __tbl = vtbl3_s8 (__tab, __idx); + + return vbsl_s8 (__mask, __tbl, __r); +} + +__extension__ static __inline uint8x8_t __attribute__ ((__always_inline__)) +vtbx3_u8 (uint8x8_t __r, uint8x8x3_t __tab, uint8x8_t __idx) +{ + uint8x8_t __mask = vclt_u8 (__idx, vmov_n_u8 (24)); + uint8x8_t __tbl = vtbl3_u8 (__tab, __idx); + + return vbsl_u8 (__mask, __tbl, __r); +} + +__extension__ static __inline poly8x8_t __attribute__ ((__always_inline__)) +vtbx3_p8 (poly8x8_t __r, poly8x8x3_t __tab, uint8x8_t __idx) +{ + uint8x8_t __mask = vclt_u8 (__idx, vmov_n_u8 (24)); + poly8x8_t __tbl = vtbl3_p8 (__tab, __idx); + + return vbsl_p8 (__mask, __tbl, __r); +} + /* vtrn */ __extension__ static __inline float32x2x2_t __attribute__ ((__always_inline__)) @@ -25444,6 +25218,8 @@ __INTERLEAVE_LIST (zip) /* End of optimal implementations in approved order. */ +#undef __LANE0 + #undef __aarch64_vget_lane_any #undef __aarch64_vget_lane_f32 #undef __aarch64_vget_lane_f64 diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md index 50bdac9b6a8..43279ad2c0c 100644 --- a/gcc/config/aarch64/iterators.md +++ b/gcc/config/aarch64/iterators.md @@ -107,8 +107,15 @@ ;; All vector modes and DI. (define_mode_iterator VALLDI [V8QI V16QI V4HI V8HI V2SI V4SI V2DI V2SF V4SF V2DF DI]) +;; All vector modes and DI and DF. +(define_mode_iterator VALLDIF [V8QI V16QI V4HI V8HI V2SI V4SI + V2DI V2SF V4SF V2DF DI DF]) + ;; Vector modes for Integer reduction across lanes. -(define_mode_iterator VDQV [V8QI V16QI V4HI V8HI V4SI]) +(define_mode_iterator VDQV [V8QI V16QI V4HI V8HI V4SI V2DI]) + +;; Vector modes(except V2DI) for Integer reduction across lanes. +(define_mode_iterator VDQV_S [V8QI V16QI V4HI V8HI V4SI]) ;; All double integer narrow-able modes. (define_mode_iterator VDN [V4HI V2SI DI]) @@ -360,7 +367,8 @@ (V4HI "8b") (V8HI "16b") (V2SI "8b") (V4SI "16b") (V2DI "16b") (V2SF "8b") - (V4SF "16b") (V2DF "16b")]) + (V4SF "16b") (V2DF "16b") + (DI "8b") (DF "8b")]) ;; Define element mode for each vector mode. (define_mode_attr VEL [(V8QI "QI") (V16QI "QI") @@ -585,6 +593,12 @@ (V2DF "_q") (QI "") (HI "") (SI "") (DI "") (SF "") (DF "")]) +(define_mode_attr vp [(V8QI "v") (V16QI "v") + (V4HI "v") (V8HI "v") + (V2SI "p") (V4SI "v") + (V2DI "p") (V2DF "p") + (V2SF "p") (V4SF "v")]) + ;; ------------------------------------------------------------------- ;; Code Iterators ;; ------------------------------------------------------------------- diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c index c55835e7fe1..4c55c16197b 100644 --- a/gcc/config/alpha/alpha.c +++ b/gcc/config/alpha/alpha.c @@ -51,6 +51,16 @@ along with GCC; see the file COPYING3. If not see #include "debug.h" #include "langhooks.h" #include "splay-tree.h" +#include "pointer-set.h" +#include "hash-table.h" +#include "vec.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "gimple-ssa.h" diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h index 944cf100d9a..c5b16daae4f 100644 --- a/gcc/config/arm/arm-protos.h +++ b/gcc/config/arm/arm-protos.h @@ -121,6 +121,7 @@ extern rtx arm_gen_compare_reg (RTX_CODE, rtx, rtx, rtx); extern rtx arm_gen_return_addr_mask (void); extern void arm_reload_in_hi (rtx *); extern void arm_reload_out_hi (rtx *); +extern int arm_max_const_double_inline_cost (void); extern int arm_const_double_inline_cost (rtx); extern bool arm_const_double_by_parts (rtx); extern bool arm_const_double_by_immediates (rtx); diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 25e4f2a69c9..7251ebdab3c 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -869,6 +869,9 @@ int arm_arch_thumb_hwdiv; than core registers. */ int prefer_neon_for_64bits = 0; +/* Nonzero if we shouldn't use literal pools. */ +bool arm_disable_literal_pool = false; + /* In case of a PRE_INC, POST_INC, PRE_DEC, POST_DEC memory reference, we must report the mode of the memory reference from TARGET_PRINT_OPERAND to TARGET_PRINT_OPERAND_ADDRESS. */ @@ -1165,94 +1168,194 @@ const struct cpu_cost_table cortexa15_extra_costs = { /* ALU */ { - COSTS_N_INSNS (1), /* Arith. */ - COSTS_N_INSNS (1), /* Logical. */ - COSTS_N_INSNS (1), /* Shift. */ - COSTS_N_INSNS (1), /* Shift_reg. */ + 0, /* Arith. */ + 0, /* Logical. */ + 0, /* Shift. */ + 0, /* Shift_reg. */ COSTS_N_INSNS (1), /* Arith_shift. */ COSTS_N_INSNS (1), /* Arith_shift_reg. */ COSTS_N_INSNS (1), /* Log_shift. */ COSTS_N_INSNS (1), /* Log_shift_reg. */ - COSTS_N_INSNS (1), /* Extend. */ - COSTS_N_INSNS (2), /* Extend_arith. */ - COSTS_N_INSNS (2), /* Bfi. */ - COSTS_N_INSNS (1), /* Bfx. */ - COSTS_N_INSNS (1), /* Clz. */ - COSTS_N_INSNS (1), /* non_exec. */ + 0, /* Extend. */ + COSTS_N_INSNS (1), /* Extend_arith. */ + COSTS_N_INSNS (1), /* Bfi. */ + 0, /* Bfx. */ + 0, /* Clz. */ + 0, /* non_exec. */ true /* non_exec_costs_exec. */ }, /* MULT SImode */ { { - COSTS_N_INSNS (3), /* Simple. */ - COSTS_N_INSNS (4), /* Flag_setting. */ - COSTS_N_INSNS (3), /* Extend. */ - COSTS_N_INSNS (4), /* Add. */ - COSTS_N_INSNS (4), /* Extend_add. */ - COSTS_N_INSNS (19) /* Idiv. */ + COSTS_N_INSNS (2), /* Simple. */ + COSTS_N_INSNS (3), /* Flag_setting. */ + COSTS_N_INSNS (2), /* Extend. */ + COSTS_N_INSNS (2), /* Add. */ + COSTS_N_INSNS (2), /* Extend_add. */ + COSTS_N_INSNS (18) /* Idiv. */ }, /* MULT DImode */ { 0, /* Simple (N/A). */ 0, /* Flag_setting (N/A). */ - COSTS_N_INSNS (4), /* Extend. */ + COSTS_N_INSNS (3), /* Extend. */ 0, /* Add (N/A). */ - COSTS_N_INSNS (6), /* Extend_add. */ + COSTS_N_INSNS (3), /* Extend_add. */ 0 /* Idiv (N/A). */ } }, /* LD/ST */ { - COSTS_N_INSNS (4), /* Load. */ - COSTS_N_INSNS (4), /* Load_sign_extend. */ - COSTS_N_INSNS (4), /* Ldrd. */ - COSTS_N_INSNS (5), /* Ldm_1st. */ + COSTS_N_INSNS (3), /* Load. */ + COSTS_N_INSNS (3), /* Load_sign_extend. */ + COSTS_N_INSNS (3), /* Ldrd. */ + COSTS_N_INSNS (4), /* Ldm_1st. */ 1, /* Ldm_regs_per_insn_1st. */ 2, /* Ldm_regs_per_insn_subsequent. */ - COSTS_N_INSNS (5), /* Loadf. */ - COSTS_N_INSNS (5), /* Loadd. */ + COSTS_N_INSNS (4), /* Loadf. */ + COSTS_N_INSNS (4), /* Loadd. */ + 0, /* Load_unaligned. */ + 0, /* Store. */ + 0, /* Strd. */ + COSTS_N_INSNS (1), /* Stm_1st. */ + 1, /* Stm_regs_per_insn_1st. */ + 2, /* Stm_regs_per_insn_subsequent. */ + 0, /* Storef. */ + 0, /* Stored. */ + 0 /* Store_unaligned. */ + }, + { + /* FP SFmode */ + { + COSTS_N_INSNS (17), /* Div. */ + COSTS_N_INSNS (4), /* Mult. */ + COSTS_N_INSNS (8), /* Mult_addsub. */ + COSTS_N_INSNS (8), /* Fma. */ + COSTS_N_INSNS (4), /* Addsub. */ + COSTS_N_INSNS (2), /* Fpconst. */ + COSTS_N_INSNS (2), /* Neg. */ + COSTS_N_INSNS (5), /* Compare. */ + COSTS_N_INSNS (4), /* Widen. */ + COSTS_N_INSNS (4), /* Narrow. */ + COSTS_N_INSNS (4), /* Toint. */ + COSTS_N_INSNS (4), /* Fromint. */ + COSTS_N_INSNS (4) /* Roundint. */ + }, + /* FP DFmode */ + { + COSTS_N_INSNS (31), /* Div. */ + COSTS_N_INSNS (4), /* Mult. */ + COSTS_N_INSNS (8), /* Mult_addsub. */ + COSTS_N_INSNS (8), /* Fma. */ + COSTS_N_INSNS (4), /* Addsub. */ + COSTS_N_INSNS (2), /* Fpconst. */ + COSTS_N_INSNS (2), /* Neg. */ + COSTS_N_INSNS (2), /* Compare. */ + COSTS_N_INSNS (4), /* Widen. */ + COSTS_N_INSNS (4), /* Narrow. */ + COSTS_N_INSNS (4), /* Toint. */ + COSTS_N_INSNS (4), /* Fromint. */ + COSTS_N_INSNS (4) /* Roundint. */ + } + }, + /* Vector */ + { + COSTS_N_INSNS (1) /* Alu. */ + } +}; + +const struct cpu_cost_table v7m_extra_costs = +{ + /* ALU */ + { + 0, /* Arith. */ + 0, /* Logical. */ + 0, /* Shift. */ + 0, /* Shift_reg. */ + 0, /* Arith_shift. */ + COSTS_N_INSNS (1), /* Arith_shift_reg. */ + 0, /* Log_shift. */ + COSTS_N_INSNS (1), /* Log_shift_reg. */ + 0, /* Extend. */ + COSTS_N_INSNS (1), /* Extend_arith. */ + 0, /* Bfi. */ + 0, /* Bfx. */ + 0, /* Clz. */ + COSTS_N_INSNS (1), /* non_exec. */ + false /* non_exec_costs_exec. */ + }, + { + /* MULT SImode */ + { + COSTS_N_INSNS (1), /* Simple. */ + COSTS_N_INSNS (1), /* Flag_setting. */ + COSTS_N_INSNS (2), /* Extend. */ + COSTS_N_INSNS (1), /* Add. */ + COSTS_N_INSNS (3), /* Extend_add. */ + COSTS_N_INSNS (8) /* Idiv. */ + }, + /* MULT DImode */ + { + 0, /* Simple (N/A). */ + 0, /* Flag_setting (N/A). */ + COSTS_N_INSNS (2), /* Extend. */ + 0, /* Add (N/A). */ + COSTS_N_INSNS (3), /* Extend_add. */ + 0 /* Idiv (N/A). */ + } + }, + /* LD/ST */ + { + COSTS_N_INSNS (2), /* Load. */ + 0, /* Load_sign_extend. */ + COSTS_N_INSNS (3), /* Ldrd. */ + COSTS_N_INSNS (2), /* Ldm_1st. */ + 1, /* Ldm_regs_per_insn_1st. */ + 1, /* Ldm_regs_per_insn_subsequent. */ + COSTS_N_INSNS (2), /* Loadf. */ + COSTS_N_INSNS (3), /* Loadd. */ COSTS_N_INSNS (1), /* Load_unaligned. */ - COSTS_N_INSNS (1), /* Store. */ - COSTS_N_INSNS (1), /* Strd. */ + COSTS_N_INSNS (2), /* Store. */ + COSTS_N_INSNS (3), /* Strd. */ COSTS_N_INSNS (2), /* Stm_1st. */ 1, /* Stm_regs_per_insn_1st. */ - 2, /* Stm_regs_per_insn_subsequent. */ - COSTS_N_INSNS (1), /* Storef. */ - COSTS_N_INSNS (1), /* Stored. */ - COSTS_N_INSNS (1) /* Store_unaligned. */ + 1, /* Stm_regs_per_insn_subsequent. */ + COSTS_N_INSNS (2), /* Storef. */ + COSTS_N_INSNS (3), /* Stored. */ + COSTS_N_INSNS (1) /* Store_unaligned. */ }, { /* FP SFmode */ { - COSTS_N_INSNS (18), /* Div. */ - COSTS_N_INSNS (5), /* Mult. */ - COSTS_N_INSNS (3), /* Mult_addsub. */ - COSTS_N_INSNS (13), /* Fma. */ - COSTS_N_INSNS (5), /* Addsub. */ - COSTS_N_INSNS (5), /* Fpconst. */ - COSTS_N_INSNS (3), /* Neg. */ - COSTS_N_INSNS (3), /* Compare. */ - COSTS_N_INSNS (3), /* Widen. */ - COSTS_N_INSNS (3), /* Narrow. */ - COSTS_N_INSNS (3), /* Toint. */ - COSTS_N_INSNS (3), /* Fromint. */ - COSTS_N_INSNS (3) /* Roundint. */ + COSTS_N_INSNS (7), /* Div. */ + COSTS_N_INSNS (2), /* Mult. */ + COSTS_N_INSNS (5), /* Mult_addsub. */ + COSTS_N_INSNS (3), /* Fma. */ + COSTS_N_INSNS (1), /* Addsub. */ + 0, /* Fpconst. */ + 0, /* Neg. */ + 0, /* Compare. */ + 0, /* Widen. */ + 0, /* Narrow. */ + 0, /* Toint. */ + 0, /* Fromint. */ + 0 /* Roundint. */ }, /* FP DFmode */ { - COSTS_N_INSNS (32), /* Div. */ + COSTS_N_INSNS (15), /* Div. */ COSTS_N_INSNS (5), /* Mult. */ - COSTS_N_INSNS (3), /* Mult_addsub. */ - COSTS_N_INSNS (13), /* Fma. */ - COSTS_N_INSNS (5), /* Addsub. */ - COSTS_N_INSNS (3), /* Fpconst. */ - COSTS_N_INSNS (3), /* Neg. */ - COSTS_N_INSNS (3), /* Compare. */ - COSTS_N_INSNS (3), /* Widen. */ - COSTS_N_INSNS (3), /* Narrow. */ - COSTS_N_INSNS (3), /* Toint. */ - COSTS_N_INSNS (3), /* Fromint. */ - COSTS_N_INSNS (3) /* Roundint. */ + COSTS_N_INSNS (7), /* Mult_addsub. */ + COSTS_N_INSNS (7), /* Fma. */ + COSTS_N_INSNS (3), /* Addsub. */ + 0, /* Fpconst. */ + 0, /* Neg. */ + 0, /* Compare. */ + 0, /* Widen. */ + 0, /* Narrow. */ + 0, /* Toint. */ + 0, /* Fromint. */ + 0 /* Roundint. */ } }, /* Vector */ @@ -1470,7 +1573,7 @@ const struct tune_params arm_cortex_a9_tune = const struct tune_params arm_v7m_tune = { arm_9e_rtx_costs, - &generic_extra_costs, + &v7m_extra_costs, NULL, /* Sched adj cost. */ 1, /* Constant limit. */ 5, /* Max cond insns. */ @@ -2573,6 +2676,16 @@ arm_option_override (void) if (TARGET_APCS_FRAME) flag_shrink_wrap = false; + /* We only support -mslow-flash-data on armv7-m targets. */ + if (target_slow_flash_data + && ((!(arm_arch7 && !arm_arch_notm) && !arm_arch7em) + || (TARGET_THUMB1 || flag_pic || TARGET_NEON))) + error ("-mslow-flash-data only supports non-pic code on armv7-m targets"); + + /* Currently, for slow flash data, we just disable literal pools. */ + if (target_slow_flash_data) + arm_disable_literal_pool = true; + /* Register global variables with the garbage collector. */ arm_add_gc_roots (); } @@ -5904,7 +6017,8 @@ require_pic_register (void) if (!crtl->uses_pic_offset_table) { gcc_assert (can_create_pseudo_p ()); - if (arm_pic_register != INVALID_REGNUM) + if (arm_pic_register != INVALID_REGNUM + && !(TARGET_THUMB1 && arm_pic_register > LAST_LO_REGNUM)) { if (!cfun->machine->pic_reg) cfun->machine->pic_reg = gen_rtx_REG (Pmode, arm_pic_register); @@ -5930,7 +6044,12 @@ require_pic_register (void) crtl->uses_pic_offset_table = 1; start_sequence (); - arm_load_pic_register (0UL); + if (TARGET_THUMB1 && arm_pic_register != INVALID_REGNUM + && arm_pic_register > LAST_LO_REGNUM) + emit_move_insn (cfun->machine->pic_reg, + gen_rtx_REG (Pmode, arm_pic_register)); + else + arm_load_pic_register (0UL); seq = get_insns (); end_sequence (); @@ -6189,6 +6308,14 @@ arm_load_pic_register (unsigned long saved_regs ATTRIBUTE_UNUSED) emit_insn (gen_movsi (pic_offset_table_rtx, pic_tmp)); emit_insn (gen_pic_add_dot_plus_four (pic_reg, pic_reg, labelno)); } + else if (arm_pic_register != INVALID_REGNUM + && arm_pic_register > LAST_LO_REGNUM + && REGNO (pic_reg) <= LAST_LO_REGNUM) + { + emit_insn (gen_pic_load_addr_unified (pic_reg, pic_rtx, labelno)); + emit_move_insn (gen_rtx_REG (Pmode, arm_pic_register), pic_reg); + emit_use (gen_rtx_REG (Pmode, arm_pic_register)); + } else emit_insn (gen_pic_load_addr_unified (pic_reg, pic_rtx, labelno)); } @@ -6417,6 +6544,25 @@ thumb2_legitimate_address_p (enum machine_mode mode, rtx x, int strict_p) && thumb2_legitimate_index_p (mode, xop0, strict_p))); } + /* Normally we can assign constant values to target registers without + the help of constant pool. But there are cases we have to use constant + pool like: + 1) assign a label to register. + 2) sign-extend a 8bit value to 32bit and then assign to register. + + Constant pool access in format: + (set (reg r0) (mem (symbol_ref (".LC0")))) + will cause the use of literal pool (later in function arm_reorg). + So here we mark such format as an invalid format, then the compiler + will adjust it into: + (set (reg r0) (symbol_ref (".LC0"))) + (set (reg r0) (mem (reg r0))). + No extra register is required, and (mem (reg r0)) won't cause the use + of literal pools. */ + else if (arm_disable_literal_pool && code == SYMBOL_REF + && CONSTANT_POOL_ADDRESS_P (x)) + return 0; + else if (GET_MODE_CLASS (mode) != MODE_FLOAT && code == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x) @@ -6834,10 +6980,7 @@ arm_preferred_reload_class (rtx x ATTRIBUTE_UNUSED, reg_class_t rclass) return rclass; else { - if (rclass == GENERAL_REGS - || rclass == HI_REGS - || rclass == NO_REGS - || rclass == STACK_REG) + if (rclass == GENERAL_REGS) return LO_REGS; else return rclass; @@ -7072,7 +7215,8 @@ arm_legitimize_address (rtx x, rtx orig_x, enum machine_mode mode) if (CONSTANT_P (xop0) && !symbol_mentioned_p (xop0)) xop0 = force_reg (SImode, xop0); - if (CONSTANT_P (xop1) && !symbol_mentioned_p (xop1)) + if (CONSTANT_P (xop1) && !CONST_INT_P (xop1) + && !symbol_mentioned_p (xop1)) xop1 = force_reg (SImode, xop1); if (ARM_BASE_REGISTER_RTX_P (xop0) @@ -10084,6 +10228,8 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code, if (speed_p) *cost += 2 * extra_cost->alu.shift; } + else /* GET_MODE (XEXP (x, 0)) == SImode. */ + *cost = COSTS_N_INSNS (1); /* Widening beyond 32-bits requires one more insn. */ if (mode == DImode) @@ -16222,6 +16368,19 @@ push_minipool_fix (rtx insn, HOST_WIDE_INT address, rtx *loc, minipool_fix_tail = fix; } +/* Return maximum allowed cost of synthesizing a 64-bit constant VAL inline. + Returns the number of insns needed, or 99 if we always want to synthesize + the value. */ +int +arm_max_const_double_inline_cost () +{ + /* Let the value get synthesized to avoid the use of literal pools. */ + if (arm_disable_literal_pool) + return 99; + + return ((optimize_size || arm_ld_sched) ? 3 : 4); +} + /* Return the cost of synthesizing a 64-bit constant VAL inline. Returns the number of insns needed, or 99 if we don't know how to do it. */ diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index dbd841ec842..8b8b80e19d3 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -329,7 +329,9 @@ extern void (*arm_lang_output_object_attributes_hook)(void); /* Should MOVW/MOVT be used in preference to a constant pool. */ #define TARGET_USE_MOVT \ - (arm_arch_thumb2 && !optimize_size && !current_tune->prefer_constant_pool) + (arm_arch_thumb2 \ + && (arm_disable_literal_pool \ + || (!optimize_size && !current_tune->prefer_constant_pool))) /* We could use unified syntax for arm mode, but for now we just use it for Thumb-2. */ @@ -554,6 +556,11 @@ extern int arm_arch_thumb_hwdiv; than core registers. */ extern int prefer_neon_for_64bits; +/* Nonzero if we shouldn't use literal pools. */ +#ifndef USED_FOR_TARGET +extern bool arm_disable_literal_pool; +#endif + #ifndef TARGET_DEFAULT #define TARGET_DEFAULT (MASK_APCS_FRAME) #endif @@ -1270,11 +1277,12 @@ enum reg_class /* Must leave BASE_REGS reloads alone */ #define THUMB_SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X) \ - ((CLASS) != LO_REGS && (CLASS) != BASE_REGS \ - ? ((true_regnum (X) == -1 ? LO_REGS \ - : (true_regnum (X) + HARD_REGNO_NREGS (0, MODE) > 8) ? LO_REGS \ - : NO_REGS)) \ - : NO_REGS) + (lra_in_progress ? NO_REGS \ + : ((CLASS) != LO_REGS && (CLASS) != BASE_REGS \ + ? ((true_regnum (X) == -1 ? LO_REGS \ + : (true_regnum (X) + HARD_REGNO_NREGS (0, MODE) > 8) ? LO_REGS \ + : NO_REGS)) \ + : NO_REGS)) #define THUMB_SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, X) \ ((CLASS) != LO_REGS && (CLASS) != BASE_REGS \ diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index a26550a476a..841c624d485 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -82,6 +82,9 @@ ;; Processor type. This is created automatically from arm-cores.def. (include "arm-tune.md") +;; Instruction classification types +(include "types.md") + ; IS_THUMB is set to 'yes' when we are generating Thumb code, and 'no' when ; generating ARM code. This is used to control the length of some insn ; patterns that share the same RTL in both ARM and Thumb code. @@ -191,6 +194,12 @@ (const_string "yes")] (const_string "no"))) +(define_attr "use_literal_pool" "no,yes" + (cond [(and (eq_attr "type" "f_loads,f_loadd") + (match_test "CONSTANT_P (operands[1])")) + (const_string "yes")] + (const_string "no"))) + ; Allows an insn to disable certain alternatives for reasons other than ; arch support. (define_attr "insn_enabled" "no,yes" @@ -210,6 +219,10 @@ (match_test "arm_restrict_it")) (const_string "no") + (and (eq_attr "use_literal_pool" "yes") + (match_test "arm_disable_literal_pool")) + (const_string "no") + (eq_attr "arch_enabled" "no") (const_string "no") @@ -245,9 +258,6 @@ (set_attr "length" "4") (set_attr "pool_range" "250")]) -;; Instruction classification types -(include "types.md") - ; Load scheduling, set from the arm_ld_sched variable ; initialized by arm_option_override() (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched"))) @@ -3716,7 +3726,7 @@ [(match_operand:SI 1 "s_register_operand" "r") (match_operand:SI 2 "s_register_operand" "r")])) (clobber (reg:CC CC_REGNUM))] - "TARGET_32BIT && optimize_insn_for_size_p()" + "TARGET_32BIT && optimize_function_for_size_p (cfun)" "* operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode, operands[1], operands[2]); @@ -4708,49 +4718,94 @@ "TARGET_32BIT && TARGET_HARD_FLOAT && TARGET_VFP_DOUBLE" "") +(define_insn_and_split "*zextendsidi_negsi" + [(set (match_operand:DI 0 "s_register_operand" "=r") + (zero_extend:DI (neg:SI (match_operand:SI 1 "s_register_operand" "r"))))] + "TARGET_32BIT" + "#" + "" + [(set (match_dup 2) + (neg:SI (match_dup 1))) + (set (match_dup 3) + (const_int 0))] + { + operands[2] = gen_lowpart (SImode, operands[0]); + operands[3] = gen_highpart (SImode, operands[0]); + } + [(set_attr "length" "8") + (set_attr "type" "multiple")] +) + ;; Negate an extended 32-bit value. (define_insn_and_split "*negdi_extendsidi" - [(set (match_operand:DI 0 "s_register_operand" "=r,&r,l,&l") - (neg:DI (sign_extend:DI (match_operand:SI 1 "s_register_operand" "0,r,0,l")))) + [(set (match_operand:DI 0 "s_register_operand" "=l,r") + (neg:DI (sign_extend:DI + (match_operand:SI 1 "s_register_operand" "l,r")))) (clobber (reg:CC CC_REGNUM))] "TARGET_32BIT" - "#" ; rsb\\t%Q0, %1, #0\;asr\\t%R0, %Q0, #31 + "#" "&& reload_completed" [(const_int 0)] { - operands[2] = gen_highpart (SImode, operands[0]); - operands[0] = gen_lowpart (SImode, operands[0]); - rtx tmp = gen_rtx_SET (VOIDmode, - operands[0], - gen_rtx_MINUS (SImode, - const0_rtx, - operands[1])); - if (TARGET_ARM) - { - emit_insn (tmp); - } - else - { - /* Set the flags, to emit the short encoding in Thumb2. */ - rtx flags = gen_rtx_SET (VOIDmode, - gen_rtx_REG (CCmode, CC_REGNUM), - gen_rtx_COMPARE (CCmode, - const0_rtx, - operands[1])); - emit_insn (gen_rtx_PARALLEL (VOIDmode, - gen_rtvec (2, - flags, - tmp))); - } - emit_insn (gen_rtx_SET (VOIDmode, - operands[2], - gen_rtx_ASHIFTRT (SImode, - operands[0], - GEN_INT (31)))); - DONE; + rtx low = gen_lowpart (SImode, operands[0]); + rtx high = gen_highpart (SImode, operands[0]); + + if (reg_overlap_mentioned_p (low, operands[1])) + { + /* Input overlaps the low word of the output. Use: + asr Rhi, Rin, #31 + rsbs Rlo, Rin, #0 + rsc Rhi, Rhi, #0 (thumb2: sbc Rhi, Rhi, Rhi, lsl #1). */ + rtx cc_reg = gen_rtx_REG (CC_Cmode, CC_REGNUM); + + emit_insn (gen_rtx_SET (VOIDmode, high, + gen_rtx_ASHIFTRT (SImode, operands[1], + GEN_INT (31)))); + + emit_insn (gen_subsi3_compare (low, const0_rtx, operands[1])); + if (TARGET_ARM) + emit_insn (gen_rtx_SET (VOIDmode, high, + gen_rtx_MINUS (SImode, + gen_rtx_MINUS (SImode, + const0_rtx, + high), + gen_rtx_LTU (SImode, + cc_reg, + const0_rtx)))); + else + { + rtx two_x = gen_rtx_ASHIFT (SImode, high, GEN_INT (1)); + emit_insn (gen_rtx_SET (VOIDmode, high, + gen_rtx_MINUS (SImode, + gen_rtx_MINUS (SImode, + high, + two_x), + gen_rtx_LTU (SImode, + cc_reg, + const0_rtx)))); + } + } + else + { + /* No overlap, or overlap on high word. Use: + rsb Rlo, Rin, #0 + bic Rhi, Rlo, Rin + asr Rhi, Rhi, #31 + Flags not needed for this sequence. */ + emit_insn (gen_rtx_SET (VOIDmode, low, + gen_rtx_NEG (SImode, operands[1]))); + emit_insn (gen_rtx_SET (VOIDmode, high, + gen_rtx_AND (SImode, + gen_rtx_NOT (SImode, operands[1]), + low))); + emit_insn (gen_rtx_SET (VOIDmode, high, + gen_rtx_ASHIFTRT (SImode, high, + GEN_INT (31)))); + } + DONE; } - [(set_attr "length" "8,8,4,4") - (set_attr "arch" "a,a,t2,t2") + [(set_attr "length" "12") + (set_attr "arch" "t2,*") (set_attr "type" "multiple")] ) @@ -6022,7 +6077,7 @@ "TARGET_32BIT && reload_completed && (arm_const_double_inline_cost (operands[1]) - <= ((optimize_size || arm_ld_sched) ? 3 : 4))" + <= arm_max_const_double_inline_cost ())" [(const_int 0)] " arm_split_constant (SET, SImode, curr_insn, @@ -6285,6 +6340,47 @@ " ) +;; A normal way to do (symbol + offset) requires three instructions at least +;; (depends on how big the offset is) as below: +;; movw r0, #:lower16:g +;; movw r0, #:upper16:g +;; adds r0, #4 +;; +;; A better way would be: +;; movw r0, #:lower16:g+4 +;; movw r0, #:upper16:g+4 +;; +;; The limitation of this way is that the length of offset should be a 16-bit +;; signed value, because current assembler only supports REL type relocation for +;; such case. If the more powerful RELA type is supported in future, we should +;; update this pattern to go with better way. +(define_split + [(set (match_operand:SI 0 "arm_general_register_operand" "") + (const:SI (plus:SI (match_operand:SI 1 "general_operand" "") + (match_operand:SI 2 "const_int_operand" ""))))] + "TARGET_THUMB2 + && arm_disable_literal_pool + && reload_completed + && GET_CODE (operands[1]) == SYMBOL_REF" + [(clobber (const_int 0))] + " + int offset = INTVAL (operands[2]); + + if (offset < -0x8000 || offset > 0x7fff) + { + arm_emit_movpair (operands[0], operands[1]); + emit_insn (gen_rtx_SET (SImode, operands[0], + gen_rtx_PLUS (SImode, operands[0], operands[2]))); + } + else + { + rtx op = gen_rtx_CONST (SImode, + gen_rtx_PLUS (SImode, operands[1], operands[2])); + arm_emit_movpair (operands[0], op); + } + " +) + ;; Split symbol_refs at the later stage (after cprop), instead of generating ;; movt/movw pair directly at expand. Otherwise corresponding high_sum ;; and lo_sum would be merged back into memory load at cprop. However, diff --git a/gcc/config/arm/arm.opt b/gcc/config/arm/arm.opt index fa0839a9e12..24e5b062c0b 100644 --- a/gcc/config/arm/arm.opt +++ b/gcc/config/arm/arm.opt @@ -271,3 +271,7 @@ Enable unaligned word and halfword accesses to packed data. mneon-for-64bits Target Report RejectNegative Var(use_neon_for_64bits) Init(0) Use Neon to perform 64-bits operations rather than core registers. + +mslow-flash-data +Target Report Var(target_slow_flash_data) Init(0) +Assume loading data from flash is slower than fetching instructions. diff --git a/gcc/config/arm/iterators.md b/gcc/config/arm/iterators.md index 38777b89a87..66779a7b7fa 100644 --- a/gcc/config/arm/iterators.md +++ b/gcc/config/arm/iterators.md @@ -511,6 +511,10 @@ (UNSPEC_VRINTA "no") (UNSPEC_VRINTM "no") (UNSPEC_VRINTR "yes") (UNSPEC_VRINTX "yes")]) +(define_int_attr vrint_conds [(UNSPEC_VRINTZ "nocond") (UNSPEC_VRINTP "unconditional") + (UNSPEC_VRINTA "unconditional") (UNSPEC_VRINTM "unconditional") + (UNSPEC_VRINTR "nocond") (UNSPEC_VRINTX "nocond")]) + (define_int_attr nvrint_variant [(UNSPEC_NVRINTZ "z") (UNSPEC_NVRINTP "p") (UNSPEC_NVRINTA "a") (UNSPEC_NVRINTM "m") (UNSPEC_NVRINTX "x") (UNSPEC_NVRINTN "n")]) diff --git a/gcc/config/arm/vfp.md b/gcc/config/arm/vfp.md index 22b63251a87..6d0515a92b1 100644 --- a/gcc/config/arm/vfp.md +++ b/gcc/config/arm/vfp.md @@ -1277,7 +1277,8 @@ "vrint<vrint_variant>%?.<V_if_elem>\\t%<V_reg>0, %<V_reg>1" [(set_attr "predicable" "<vrint_predicable>") (set_attr "predicable_short_it" "no") - (set_attr "type" "f_rint<vfp_type>")] + (set_attr "type" "f_rint<vfp_type>") + (set_attr "conds" "<vrint_conds>")] ) ;; MIN_EXPR and MAX_EXPR eventually map to 'smin' and 'smax' in RTL. @@ -1293,7 +1294,8 @@ (match_operand:SDF 2 "register_operand" "<F_constraint>")))] "TARGET_HARD_FLOAT && TARGET_FPU_ARMV8 <vfp_double_cond>" "vmaxnm.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2" - [(set_attr "type" "f_minmax<vfp_type>")] + [(set_attr "type" "f_minmax<vfp_type>") + (set_attr "conds" "unconditional")] ) (define_insn "smin<mode>3" @@ -1302,7 +1304,8 @@ (match_operand:SDF 2 "register_operand" "<F_constraint>")))] "TARGET_HARD_FLOAT && TARGET_FPU_ARMV8 <vfp_double_cond>" "vminnm.<V_if_elem>\\t%<V_reg>0, %<V_reg>1, %<V_reg>2" - [(set_attr "type" "f_minmax<vfp_type>")] + [(set_attr "type" "f_minmax<vfp_type>") + (set_attr "conds" "unconditional")] ) ;; Unimplemented insns: diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c index e94e0d7bac8..729cc51cb5f 100644 --- a/gcc/config/avr/avr.c +++ b/gcc/config/avr/avr.c @@ -314,6 +314,15 @@ avr_option_override (void) flag_omit_frame_pointer = 0; } + if (flag_pic == 1) + warning (OPT_fpic, "-fpic is not supported"); + if (flag_pic == 2) + warning (OPT_fPIC, "-fPIC is not supported"); + if (flag_pie == 1) + warning (OPT_fpie, "-fpie is not supported"); + if (flag_pie == 2) + warning (OPT_fPIE, "-fPIE is not supported"); + avr_current_device = &avr_mcu_types[avr_mcu_index]; avr_current_arch = &avr_arch_types[avr_current_device->arch]; diff --git a/gcc/config/avr/avr.h b/gcc/config/avr/avr.h index f223a6148ee..079752ae430 100644 --- a/gcc/config/avr/avr.h +++ b/gcc/config/avr/avr.h @@ -522,7 +522,8 @@ extern const char *avr_device_to_sp8 (int argc, const char **argv); mmcu=at90can64*|\ mmcu=at90usb64*:--pmem-wrap-around=64k}}}\ %:device_to_ld(%{mmcu=*:%*})\ -%:device_to_data_start(%{mmcu=*:%*})" +%:device_to_data_start(%{mmcu=*:%*})\ +%{shared:%eshared is not supported}" #define LIB_SPEC \ "%{!mmcu=at90s1*:%{!mmcu=attiny11:%{!mmcu=attiny12:%{!mmcu=attiny15:%{!mmcu=attiny28: -lc }}}}}" diff --git a/gcc/config/bfin/bfin-protos.h b/gcc/config/bfin/bfin-protos.h index 91f03b198f9..1123845d364 100644 --- a/gcc/config/bfin/bfin-protos.h +++ b/gcc/config/bfin/bfin-protos.h @@ -105,8 +105,8 @@ extern rtx bfin_va_arg (tree, tree); extern void bfin_expand_prologue (void); extern void bfin_expand_epilogue (int, int, bool); -extern int push_multiple_operation (rtx, enum machine_mode); -extern int pop_multiple_operation (rtx, enum machine_mode); +extern int analyze_push_multiple_operation (rtx); +extern int analyze_pop_multiple_operation (rtx); extern void output_push_multiple (rtx, rtx *); extern void output_pop_multiple (rtx, rtx *); extern int bfin_hard_regno_rename_ok (unsigned int, unsigned int); diff --git a/gcc/config/bfin/bfin.c b/gcc/config/bfin/bfin.c index 88fe426dd43..60da450976a 100644 --- a/gcc/config/bfin/bfin.c +++ b/gcc/config/bfin/bfin.c @@ -105,7 +105,7 @@ output_file_start (void) FILE *file = asm_out_file; int i; - fprintf (file, ".file \"%s\";\n", input_filename); + fprintf (file, ".file \"%s\";\n", LOCATION_FILE (input_location)); for (i = 0; arg_regs[i] >= 0; i++) ; @@ -2992,7 +2992,7 @@ static int first_preg_to_save, first_dreg_to_save; static int n_regs_to_save; int -push_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) +analyze_push_multiple_operation (rtx op) { int lastdreg = 8, lastpreg = 6; int i, group; @@ -3063,7 +3063,7 @@ push_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) } int -pop_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) +analyze_pop_multiple_operation (rtx op) { int lastdreg = 8, lastpreg = 6; int i, group; @@ -3132,7 +3132,7 @@ output_push_multiple (rtx insn, rtx *operands) int ok; /* Validate the insn again, and compute first_[dp]reg_to_save. */ - ok = push_multiple_operation (PATTERN (insn), VOIDmode); + ok = analyze_push_multiple_operation (PATTERN (insn)); gcc_assert (ok); if (first_dreg_to_save == 8) @@ -3156,7 +3156,7 @@ output_pop_multiple (rtx insn, rtx *operands) int ok; /* Validate the insn again, and compute first_[dp]reg_to_save. */ - ok = pop_multiple_operation (PATTERN (insn), VOIDmode); + ok = analyze_pop_multiple_operation (PATTERN (insn)); gcc_assert (ok); if (first_dreg_to_save == 8) @@ -4135,8 +4135,8 @@ workaround_rts_anomaly (void) if (GET_CODE (pat) == PARALLEL) { - if (push_multiple_operation (pat, VOIDmode) - || pop_multiple_operation (pat, VOIDmode)) + if (analyze_push_multiple_operation (pat) + || analyze_pop_multiple_operation (pat)) this_cycles = n_regs_to_save; } else diff --git a/gcc/config/bfin/predicates.md b/gcc/config/bfin/predicates.md index cdb2c414be9..8d9e13d5aca 100644 --- a/gcc/config/bfin/predicates.md +++ b/gcc/config/bfin/predicates.md @@ -239,3 +239,11 @@ gcc_assert (REG_P (op)); return IREG_P (op); }) + +(define_predicate "push_multiple_operation" + (and (match_code "parallel") + (match_test "analyze_push_multiple_operation (op)"))) + +(define_predicate "pop_multiple_operation" + (and (match_code "parallel") + (match_test "analyze_pop_multiple_operation (op)"))) diff --git a/gcc/config/cris/cris.c b/gcc/config/cris/cris.c index 2d2a108031d..235b6c652cf 100644 --- a/gcc/config/cris/cris.c +++ b/gcc/config/cris/cris.c @@ -93,6 +93,8 @@ static int cris_reg_overlap_mentioned_p (rtx, rtx); static enum machine_mode cris_promote_function_mode (const_tree, enum machine_mode, int *, const_tree, int); +static unsigned int cris_atomic_align_for_mode (enum machine_mode); + static void cris_print_base (rtx, FILE *); static void cris_print_index (rtx, FILE *); @@ -227,6 +229,9 @@ int cris_cpu_version = CRIS_DEFAULT_CPU_VERSION; #undef TARGET_PROMOTE_FUNCTION_MODE #define TARGET_PROMOTE_FUNCTION_MODE cris_promote_function_mode +#undef TARGET_ATOMIC_ALIGN_FOR_MODE +#define TARGET_ATOMIC_ALIGN_FOR_MODE cris_atomic_align_for_mode + #undef TARGET_STRUCT_VALUE_RTX #define TARGET_STRUCT_VALUE_RTX cris_struct_value_rtx #undef TARGET_SETUP_INCOMING_VARARGS @@ -4019,6 +4024,14 @@ cris_promote_function_mode (const_tree type ATTRIBUTE_UNUSED, return CRIS_PROMOTED_MODE (mode, *punsignedp, type); } +/* Atomic types require alignment to be at least their "natural" size. */ + +static unsigned int +cris_atomic_align_for_mode (enum machine_mode mode) +{ + return GET_MODE_BITSIZE (mode); +} + /* Let's assume all functions return in r[CRIS_FIRST_ARG_REG] for the time being. */ diff --git a/gcc/config/darwin.c b/gcc/config/darwin.c index 50fb3f05f1f..ba2d94b8925 100644 --- a/gcc/config/darwin.c +++ b/gcc/config/darwin.c @@ -48,6 +48,16 @@ along with GCC; see the file COPYING3. If not see #include "df.h" #include "debug.h" #include "obstack.h" +#include "pointer-set.h" +#include "hash-table.h" +#include "vec.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "lto-streamer.h" diff --git a/gcc/config/epiphany/epiphany.c b/gcc/config/epiphany/epiphany.c index c264cdaee78..2a6ef107401 100644 --- a/gcc/config/epiphany/epiphany.c +++ b/gcc/config/epiphany/epiphany.c @@ -1133,7 +1133,7 @@ epiphany_compute_frame_size (int size /* # of var. bytes allocated. */) if (total_size + reg_size <= (unsigned) epiphany_stack_offset) { gcc_assert (first_slot < 0); - gcc_assert (reg_size == 0 || reg_size == epiphany_stack_offset); + gcc_assert (reg_size == 0 || (int) reg_size == epiphany_stack_offset); last_slot_offset = EPIPHANY_STACK_ALIGN (total_size + reg_size); } else @@ -1694,7 +1694,6 @@ epiphany_expand_prologue (void) int interrupt_p; enum epiphany_function_type fn_type; rtx addr, mem, off, reg; - rtx save_config; if (!current_frame_info.initialized) epiphany_compute_frame_size (get_frame_size ()); diff --git a/gcc/config/epiphany/epiphany.h b/gcc/config/epiphany/epiphany.h index f16ab85dde9..faa255574e1 100644 --- a/gcc/config/epiphany/epiphany.h +++ b/gcc/config/epiphany/epiphany.h @@ -929,8 +929,10 @@ enum }; extern int epiphany_normal_fp_rounding; +#ifndef IN_LIBGCC2 extern rtl_opt_pass *make_pass_mode_switch_use (gcc::context *ctxt); extern rtl_opt_pass *make_pass_resolve_sw_modes (gcc::context *ctxt); +#endif /* This will need to be adjusted when FP_CONTRACT_ON is properly implemented. */ diff --git a/gcc/config/gnu-user.h b/gcc/config/gnu-user.h index 6f6915842b9..60eb30dd127 100644 --- a/gcc/config/gnu-user.h +++ b/gcc/config/gnu-user.h @@ -126,11 +126,3 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see LD_STATIC_OPTION " --whole-archive -ltsan --no-whole-archive " \ LD_DYNAMIC_OPTION "}}%{!static-libtsan:-ltsan}" #endif - -/* Additional libraries needed by -static-libasan. */ -#undef STATIC_LIBASAN_LIBS -#define STATIC_LIBASAN_LIBS "-ldl -lpthread" - -/* Additional libraries needed by -static-libtsan. */ -#undef STATIC_LIBTSAN_LIBS -#define STATIC_LIBTSAN_LIBS "-ldl -lpthread" diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md index 7289ae493b0..0bc53aabcb4 100644 --- a/gcc/config/i386/constraints.md +++ b/gcc/config/i386/constraints.md @@ -18,7 +18,7 @@ ;; <http://www.gnu.org/licenses/>. ;;; Unused letters: -;;; H +;;; B H ;;; h j ;; Integer register constraints. @@ -91,9 +91,6 @@ (define_register_constraint "x" "TARGET_SSE ? SSE_REGS : NO_REGS" "Any SSE register.") -(define_register_constraint "B" "TARGET_MPX ? BND_REGS : NO_REGS" - "@internal Any bound register.") - ;; We use the Y prefix to denote any number of conditional register sets: ;; z First SSE register. ;; i SSE2 inter-unit moves to SSE register enabled @@ -239,8 +236,6 @@ ;; T prefix is used for different address constraints ;; v - VSIB address ;; s - address with no segment register -;; i - address with no index and no rip -;; b - address with no base and no rip (define_address_constraint "Tv" "VSIB address operand" @@ -249,11 +244,3 @@ (define_address_constraint "Ts" "Address operand without segment register" (match_operand 0 "address_no_seg_operand")) - -(define_address_constraint "Ti" - "MPX address operand without index" - (match_operand 0 "address_mpx_no_index_operand")) - -(define_address_constraint "Tb" - "MPX address operand without base" - (match_operand 0 "address_mpx_no_base_operand")) diff --git a/gcc/config/i386/driver-i386.c b/gcc/config/i386/driver-i386.c index a4a1f40548a..0b8af3f4ffd 100644 --- a/gcc/config/i386/driver-i386.c +++ b/gcc/config/i386/driver-i386.c @@ -646,6 +646,11 @@ const char *host_detect_local_cpu (int argc, const char **argv) /* Atom. */ cpu = "atom"; break; + case 0x37: + case 0x4d: + /* Silvermont. */ + cpu = "slm"; + break; case 0x0f: /* Merom. */ case 0x17: diff --git a/gcc/config/i386/i386-c.c b/gcc/config/i386/i386-c.c index 18c2929d10f..ff1a17a9d11 100644 --- a/gcc/config/i386/i386-c.c +++ b/gcc/config/i386/i386-c.c @@ -372,8 +372,6 @@ ix86_target_macros_internal (HOST_WIDE_INT isa_flag, def_or_undef (parse_in, "__SSE_MATH__"); if ((fpmath & FPMATH_SSE) && (isa_flag & OPTION_MASK_ISA_SSE2)) def_or_undef (parse_in, "__SSE2_MATH__"); - if (isa_flag & OPTION_MASK_ISA_MPX) - def_or_undef (parse_in, "__MPX__"); } diff --git a/gcc/config/i386/i386-modes.def b/gcc/config/i386/i386-modes.def index a73730e08e2..e0b8fc826ab 100644 --- a/gcc/config/i386/i386-modes.def +++ b/gcc/config/i386/i386-modes.def @@ -87,9 +87,6 @@ VECTOR_MODE (INT, DI, 1); /* V1DI */ VECTOR_MODE (INT, SI, 1); /* V1SI */ VECTOR_MODE (INT, QI, 2); /* V2QI */ -POINTER_BOUNDS_MODE (BND32, 8); -POINTER_BOUNDS_MODE (BND64, 16); - INT_MODE (OI, 32); INT_MODE (XI, 64); diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index bceb8f2ef6d..73feef25144 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -243,8 +243,6 @@ extern void ix86_expand_sse2_mulv4si3 (rtx, rtx, rtx); extern void ix86_expand_sse2_mulvxdi3 (rtx, rtx, rtx); extern void ix86_expand_sse2_abs (rtx, rtx); -extern bool ix86_bnd_prefixed_insn_p (rtx); - /* In i386-c.c */ extern void ix86_target_macros (void); extern void ix86_register_pragmas (void); diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index bdde693769f..548aec74093 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -52,6 +52,16 @@ along with GCC; see the file COPYING3. If not see #include "langhooks.h" #include "reload.h" #include "cgraph.h" +#include "pointer-set.h" +#include "hash-table.h" +#include "vec.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "dwarf2.h" @@ -2038,8 +2048,6 @@ enum reg_class const regclass_map[FIRST_PSEUDO_REGISTER] = /* Mask registers. */ MASK_REGS, MASK_EVEX_REGS, MASK_EVEX_REGS, MASK_EVEX_REGS, MASK_EVEX_REGS, MASK_EVEX_REGS, MASK_EVEX_REGS, MASK_EVEX_REGS, - /* MPX bound registers */ - BND_REGS, BND_REGS, BND_REGS, BND_REGS, }; /* The "default" register map used in 32bit mode. */ @@ -2056,7 +2064,6 @@ int const dbx_register_map[FIRST_PSEUDO_REGISTER] = -1, -1, -1, -1, -1, -1, -1, -1, /* AVX-512 registers 16-23*/ -1, -1, -1, -1, -1, -1, -1, -1, /* AVX-512 registers 24-31*/ 93, 94, 95, 96, 97, 98, 99, 100, /* Mask registers */ - 101, 102, 103, 104, /* bound registers */ }; /* The "default" register map used in 64bit mode. */ @@ -2073,7 +2080,6 @@ int const dbx64_register_map[FIRST_PSEUDO_REGISTER] = 67, 68, 69, 70, 71, 72, 73, 74, /* AVX-512 registers 16-23 */ 75, 76, 77, 78, 79, 80, 81, 82, /* AVX-512 registers 24-31 */ 118, 119, 120, 121, 122, 123, 124, 125, /* Mask registers */ - 126, 127, 128, 129, /* bound registers */ }; /* Define the register numbers to be used in Dwarf debugging information. @@ -2142,7 +2148,6 @@ int const svr4_dbx_register_map[FIRST_PSEUDO_REGISTER] = -1, -1, -1, -1, -1, -1, -1, -1, /* AVX-512 registers 16-23*/ -1, -1, -1, -1, -1, -1, -1, -1, /* AVX-512 registers 24-31*/ 93, 94, 95, 96, 97, 98, 99, 100, /* Mask registers */ - -1, -1, -1, -1, /* bound registers */ }; /* Define parameter passing and return registers. */ @@ -2574,7 +2579,6 @@ ix86_target_string (HOST_WIDE_INT isa, int flags, const char *arch, { "-mrtm", OPTION_MASK_ISA_RTM }, { "-mxsave", OPTION_MASK_ISA_XSAVE }, { "-mxsaveopt", OPTION_MASK_ISA_XSAVEOPT }, - { "-mmpx", OPTION_MASK_ISA_MPX }, }; /* Flag options. */ @@ -3069,7 +3073,6 @@ ix86_option_override_internal (bool main_args_p, #define PTA_AVX512ER (HOST_WIDE_INT_1 << 41) #define PTA_AVX512PF (HOST_WIDE_INT_1 << 42) #define PTA_AVX512CD (HOST_WIDE_INT_1 << 43) -#define PTA_MPX (HOST_WIDE_INT_1 << 44) /* if this reaches 64, need to widen struct pta flags below */ @@ -3138,8 +3141,8 @@ ix86_option_override_internal (bool main_args_p, | PTA_SSSE3 | PTA_CX16 | PTA_MOVBE | PTA_FXSR}, {"slm", PROCESSOR_SLM, CPU_SLM, PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3 | PTA_SSSE3 - | PTA_SSE4_1 | PTA_SSE4_2 | PTA_CX16 | PTA_POPCNT | PTA_MOVBE - | PTA_FXSR}, + | PTA_SSE4_1 | PTA_SSE4_2 | PTA_CX16 | PTA_POPCNT | PTA_AES + | PTA_PCLMUL | PTA_RDRND | PTA_MOVBE | PTA_FXSR}, {"geode", PROCESSOR_GEODE, CPU_GEODE, PTA_MMX | PTA_3DNOW | PTA_3DNOW_A | PTA_PREFETCH_SSE | PTA_PRFCHW}, {"k6", PROCESSOR_K6, CPU_K6, PTA_MMX}, @@ -3864,16 +3867,16 @@ ix86_option_override_internal (bool main_args_p, ix86_incoming_stack_boundary = ix86_default_incoming_stack_boundary; if (opts_set->x_ix86_incoming_stack_boundary_arg) { - if (ix86_incoming_stack_boundary_arg + if (opts->x_ix86_incoming_stack_boundary_arg < (TARGET_64BIT_P (opts->x_ix86_isa_flags) ? 4 : 2) - || ix86_incoming_stack_boundary_arg > 12) + || opts->x_ix86_incoming_stack_boundary_arg > 12) error ("-mincoming-stack-boundary=%d is not between %d and 12", - ix86_incoming_stack_boundary_arg, + opts->x_ix86_incoming_stack_boundary_arg, TARGET_64BIT_P (opts->x_ix86_isa_flags) ? 4 : 2); else { ix86_user_incoming_stack_boundary - = (1 << ix86_incoming_stack_boundary_arg) * BITS_PER_UNIT; + = (1 << opts->x_ix86_incoming_stack_boundary_arg) * BITS_PER_UNIT; ix86_incoming_stack_boundary = ix86_user_incoming_stack_boundary; } @@ -4262,11 +4265,6 @@ ix86_conditional_register_usage (void) for (i = FIRST_MASK_REG; i <= LAST_MASK_REG; i++) fixed_regs[i] = call_used_regs[i] = 1, reg_names[i] = ""; } - - /* If MPX is disabled, squash the registers. */ - if (! TARGET_MPX) - for (i = FIRST_BND_REG; i <= LAST_BND_REG; i++) - fixed_regs[i] = call_used_regs[i] = 1, reg_names[i] = ""; } @@ -4285,6 +4283,30 @@ ix86_function_specific_save (struct cl_target_option *ptr, ptr->x_ix86_isa_flags_explicit = opts->x_ix86_isa_flags_explicit; ptr->x_ix86_target_flags_explicit = opts->x_ix86_target_flags_explicit; ptr->x_recip_mask_explicit = opts->x_recip_mask_explicit; + ptr->x_ix86_arch_string = opts->x_ix86_arch_string; + ptr->x_ix86_tune_string = opts->x_ix86_tune_string; + ptr->x_ix86_cmodel = opts->x_ix86_cmodel; + ptr->x_ix86_abi = opts->x_ix86_abi; + ptr->x_ix86_asm_dialect = opts->x_ix86_asm_dialect; + ptr->x_ix86_branch_cost = opts->x_ix86_branch_cost; + ptr->x_ix86_dump_tunes = opts->x_ix86_dump_tunes; + ptr->x_ix86_force_align_arg_pointer = opts->x_ix86_force_align_arg_pointer; + ptr->x_ix86_force_drap = opts->x_ix86_force_drap; + ptr->x_ix86_incoming_stack_boundary_arg = opts->x_ix86_incoming_stack_boundary_arg; + ptr->x_ix86_pmode = opts->x_ix86_pmode; + ptr->x_ix86_preferred_stack_boundary_arg = opts->x_ix86_preferred_stack_boundary_arg; + ptr->x_ix86_recip_name = opts->x_ix86_recip_name; + ptr->x_ix86_regparm = opts->x_ix86_regparm; + ptr->x_ix86_section_threshold = opts->x_ix86_section_threshold; + ptr->x_ix86_sse2avx = opts->x_ix86_sse2avx; + ptr->x_ix86_stack_protector_guard = opts->x_ix86_stack_protector_guard; + ptr->x_ix86_stringop_alg = opts->x_ix86_stringop_alg; + ptr->x_ix86_tls_dialect = opts->x_ix86_tls_dialect; + ptr->x_ix86_tune_ctrl_string = opts->x_ix86_tune_ctrl_string; + ptr->x_ix86_tune_memcpy_strategy = opts->x_ix86_tune_memcpy_strategy; + ptr->x_ix86_tune_memset_strategy = opts->x_ix86_tune_memset_strategy; + ptr->x_ix86_tune_no_default = opts->x_ix86_tune_no_default; + ptr->x_ix86_veclibabi_type = opts->x_ix86_veclibabi_type; /* The fields are char but the variables are not; make sure the values fit in the fields. */ @@ -4314,6 +4336,30 @@ ix86_function_specific_restore (struct gcc_options *opts, opts->x_ix86_isa_flags_explicit = ptr->x_ix86_isa_flags_explicit; opts->x_ix86_target_flags_explicit = ptr->x_ix86_target_flags_explicit; opts->x_recip_mask_explicit = ptr->x_recip_mask_explicit; + opts->x_ix86_arch_string = ptr->x_ix86_arch_string; + opts->x_ix86_tune_string = ptr->x_ix86_tune_string; + opts->x_ix86_cmodel = ptr->x_ix86_cmodel; + opts->x_ix86_abi = ptr->x_ix86_abi; + opts->x_ix86_asm_dialect = ptr->x_ix86_asm_dialect; + opts->x_ix86_branch_cost = ptr->x_ix86_branch_cost; + opts->x_ix86_dump_tunes = ptr->x_ix86_dump_tunes; + opts->x_ix86_force_align_arg_pointer = ptr->x_ix86_force_align_arg_pointer; + opts->x_ix86_force_drap = ptr->x_ix86_force_drap; + opts->x_ix86_incoming_stack_boundary_arg = ptr->x_ix86_incoming_stack_boundary_arg; + opts->x_ix86_pmode = ptr->x_ix86_pmode; + opts->x_ix86_preferred_stack_boundary_arg = ptr->x_ix86_preferred_stack_boundary_arg; + opts->x_ix86_recip_name = ptr->x_ix86_recip_name; + opts->x_ix86_regparm = ptr->x_ix86_regparm; + opts->x_ix86_section_threshold = ptr->x_ix86_section_threshold; + opts->x_ix86_sse2avx = ptr->x_ix86_sse2avx; + opts->x_ix86_stack_protector_guard = ptr->x_ix86_stack_protector_guard; + opts->x_ix86_stringop_alg = ptr->x_ix86_stringop_alg; + opts->x_ix86_tls_dialect = ptr->x_ix86_tls_dialect; + opts->x_ix86_tune_ctrl_string = ptr->x_ix86_tune_ctrl_string; + opts->x_ix86_tune_memcpy_strategy = ptr->x_ix86_tune_memcpy_strategy; + opts->x_ix86_tune_memset_strategy = ptr->x_ix86_tune_memset_strategy; + opts->x_ix86_tune_no_default = ptr->x_ix86_tune_no_default; + opts->x_ix86_veclibabi_type = ptr->x_ix86_veclibabi_type; /* Recreate the arch feature tests if the arch changed */ if (old_arch != ix86_arch) @@ -4628,8 +4674,8 @@ ix86_valid_target_attribute_tree (tree args, struct gcc_options *opts, struct gcc_options *opts_set) { - const char *orig_arch_string = ix86_arch_string; - const char *orig_tune_string = ix86_tune_string; + const char *orig_arch_string = opts->x_ix86_arch_string; + const char *orig_tune_string = opts->x_ix86_tune_string; enum fpmath_unit orig_fpmath_set = opts_set->x_ix86_fpmath; int orig_tune_defaulted = ix86_tune_defaulted; int orig_arch_specified = ix86_arch_specified; @@ -8989,7 +9035,7 @@ ix86_code_end (void) xops[0] = gen_rtx_REG (Pmode, regno); xops[1] = gen_rtx_MEM (Pmode, stack_pointer_rtx); output_asm_insn ("mov%z0\t{%1, %0|%0, %1}", xops); - output_asm_insn ("%!ret", NULL); + fputs ("\tret\n", asm_out_file); final_end_function (); init_insn_lengths (); free_after_compilation (cfun); @@ -9047,7 +9093,7 @@ output_set_got (rtx dest, rtx label) xops[2] = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (name)); xops[2] = gen_rtx_MEM (QImode, xops[2]); - output_asm_insn ("%!call\t%X2", xops); + output_asm_insn ("call\t%X2", xops); #if TARGET_MACHO /* Output the Mach-O "canonical" pic base label name ("Lxx$pb") here. @@ -14415,7 +14461,7 @@ print_reg (rtx x, int code, FILE *file) case 8: case 4: case 12: - if (! ANY_FP_REG_P (x) && ! ANY_BND_REG_P (x)) + if (! ANY_FP_REG_P (x)) putc (code == 8 && TARGET_64BIT ? 'r' : 'e', file); /* FALLTHRU */ case 16: @@ -14538,7 +14584,6 @@ get_some_local_dynamic_name (void) ~ -- print "i" if TARGET_AVX2, "f" otherwise. @ -- print a segment register of thread base pointer load ^ -- print addr32 prefix if TARGET_64BIT and Pmode != word_mode - ! -- print MPX prefix for jxx/call/ret instructions if required. */ void @@ -15038,11 +15083,6 @@ ix86_print_operand (FILE *file, rtx x, int code) fputs ("addr32 ", file); return; - case '!': - if (ix86_bnd_prefixed_insn_p (NULL_RTX)) - fputs ("bnd ", file); - return; - default: output_operand_lossage ("invalid operand code '%c'", code); } @@ -15185,7 +15225,7 @@ static bool ix86_print_operand_punct_valid_p (unsigned char code) { return (code == '@' || code == '*' || code == '+' || code == '&' - || code == ';' || code == '~' || code == '^' || code == '!'); + || code == ';' || code == '~' || code == '^'); } /* Print a memory operand whose address is ADDR. */ @@ -15215,25 +15255,6 @@ ix86_print_operand_address (FILE *file, rtx addr) ok = ix86_decompose_address (XVECEXP (addr, 0, 0), &parts); code = 'q'; } - else if (GET_CODE (addr) == UNSPEC && XINT (addr, 1) == UNSPEC_BNDMK_ADDR) - { - ok = ix86_decompose_address (XVECEXP (addr, 0, 1), &parts); - gcc_assert (parts.base == NULL_RTX || parts.index == NULL_RTX); - if (parts.base != NULL_RTX) - { - parts.index = parts.base; - parts.scale = 1; - } - parts.base = XVECEXP (addr, 0, 0); - addr = XVECEXP (addr, 0, 0); - } - else if (GET_CODE (addr) == UNSPEC && XINT (addr, 1) == UNSPEC_BNDLDX_ADDR) - { - ok = ix86_decompose_address (XVECEXP (addr, 0, 0), &parts); - gcc_assert (parts.index == NULL_RTX); - parts.index = XVECEXP (addr, 0, 1); - addr = XVECEXP (addr, 0, 0); - } else ok = ix86_decompose_address (addr, &parts); @@ -22834,6 +22855,8 @@ emit_memset (rtx destmem, rtx destptr, rtx promoted_val, if (piece_size <= GET_MODE_SIZE (word_mode)) { emit_insn (gen_strset (destptr, dst, promoted_val)); + dst = adjust_automodify_address_nv (dst, move_mode, destptr, + piece_size); continue; } @@ -22903,14 +22926,18 @@ expand_setmem_epilogue (rtx destmem, rtx destptr, rtx value, rtx vec_value, { dest = change_address (destmem, DImode, destptr); emit_insn (gen_strset (destptr, dest, value)); + dest = adjust_automodify_address_nv (dest, DImode, destptr, 8); emit_insn (gen_strset (destptr, dest, value)); } else { dest = change_address (destmem, SImode, destptr); emit_insn (gen_strset (destptr, dest, value)); + dest = adjust_automodify_address_nv (dest, SImode, destptr, 4); emit_insn (gen_strset (destptr, dest, value)); + dest = adjust_automodify_address_nv (dest, SImode, destptr, 8); emit_insn (gen_strset (destptr, dest, value)); + dest = adjust_automodify_address_nv (dest, SImode, destptr, 12); emit_insn (gen_strset (destptr, dest, value)); } emit_label (label); @@ -22928,6 +22955,7 @@ expand_setmem_epilogue (rtx destmem, rtx destptr, rtx value, rtx vec_value, { dest = change_address (destmem, SImode, destptr); emit_insn (gen_strset (destptr, dest, value)); + dest = adjust_automodify_address_nv (dest, SImode, destptr, 4); emit_insn (gen_strset (destptr, dest, value)); } emit_label (label); @@ -23444,7 +23472,8 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, /* If expected size is not known but max size is small enough so inline version is a win, set expected size into the range. */ - if (max > 1 && (unsigned HOST_WIDE_INT)max >= max_size && expected_size == -1) + if (max > 1 && (unsigned HOST_WIDE_INT) max >= max_size + && expected_size == -1) expected_size = min_size / 2 + max_size / 2; /* If user specified the algorithm, honnor it if possible. */ @@ -23743,7 +23772,7 @@ ix86_expand_set_or_movmem (rtx dst, rtx src, rtx count_exp, rtx val_exp, bool noalign; enum machine_mode move_mode = VOIDmode; int unroll_factor = 1; - /* TODO: Once vlaue ranges are available, fill in proper data. */ + /* TODO: Once value ranges are available, fill in proper data. */ unsigned HOST_WIDE_INT min_size = 0; unsigned HOST_WIDE_INT max_size = -1; unsigned HOST_WIDE_INT probable_max_size = -1; @@ -23958,21 +23987,19 @@ ix86_expand_set_or_movmem (rtx dst, rtx src, rtx count_exp, rtx val_exp, loop variant. */ if (issetmem && epilogue_size_needed > 2 && !promoted_val) force_loopy_epilogue = true; - if (count) + if ((count && count < (unsigned HOST_WIDE_INT) epilogue_size_needed) + || max_size < (unsigned HOST_WIDE_INT) epilogue_size_needed) { - if (count < (unsigned HOST_WIDE_INT)epilogue_size_needed) - { - /* If main algorithm works on QImode, no epilogue is needed. - For small sizes just don't align anything. */ - if (size_needed == 1) - desired_align = align; - else - goto epilogue; - } + /* If main algorithm works on QImode, no epilogue is needed. + For small sizes just don't align anything. */ + if (size_needed == 1) + desired_align = align; + else + goto epilogue; } - else if (min_size < (unsigned HOST_WIDE_INT)epilogue_size_needed) + else if (!count + && min_size < (unsigned HOST_WIDE_INT) epilogue_size_needed) { - gcc_assert (max_size >= (unsigned HOST_WIDE_INT)epilogue_size_needed); label = gen_label_rtx (); emit_cmp_and_jump_insns (count_exp, GEN_INT (epilogue_size_needed), @@ -24543,13 +24570,13 @@ ix86_output_call_insn (rtx insn, rtx call_op) if (SIBLING_CALL_P (insn)) { if (direct_p) - xasm = "%!jmp\t%P0"; + xasm = "jmp\t%P0"; /* SEH epilogue detection requires the indirect branch case to include REX.W. */ else if (TARGET_SEH) - xasm = "%!rex.W jmp %A0"; + xasm = "rex.W jmp %A0"; else - xasm = "%!jmp\t%A0"; + xasm = "jmp\t%A0"; output_asm_insn (xasm, &call_op); return ""; @@ -24586,9 +24613,9 @@ ix86_output_call_insn (rtx insn, rtx call_op) } if (direct_p) - xasm = "%!call\t%P0"; + xasm = "call\t%P0"; else - xasm = "%!call\t%A0"; + xasm = "call\t%A0"; output_asm_insn (xasm, &call_op); @@ -29179,8 +29206,8 @@ static const struct builtin_description bdesc_multi_arg[] = { OPTION_MASK_ISA_XOP, CODE_FOR_xop_shlv8hi3, "__builtin_ia32_vpshlw", IX86_BUILTIN_VPSHLW, UNKNOWN, (int)MULTI_ARG_2_HI }, { OPTION_MASK_ISA_XOP, CODE_FOR_xop_shlv16qi3, "__builtin_ia32_vpshlb", IX86_BUILTIN_VPSHLB, UNKNOWN, (int)MULTI_ARG_2_QI }, - { OPTION_MASK_ISA_XOP, CODE_FOR_xop_vmfrczv4sf2, "__builtin_ia32_vfrczss", IX86_BUILTIN_VFRCZSS, UNKNOWN, (int)MULTI_ARG_2_SF }, - { OPTION_MASK_ISA_XOP, CODE_FOR_xop_vmfrczv2df2, "__builtin_ia32_vfrczsd", IX86_BUILTIN_VFRCZSD, UNKNOWN, (int)MULTI_ARG_2_DF }, + { OPTION_MASK_ISA_XOP, CODE_FOR_xop_vmfrczv4sf2, "__builtin_ia32_vfrczss", IX86_BUILTIN_VFRCZSS, UNKNOWN, (int)MULTI_ARG_1_SF }, + { OPTION_MASK_ISA_XOP, CODE_FOR_xop_vmfrczv2df2, "__builtin_ia32_vfrczsd", IX86_BUILTIN_VFRCZSD, UNKNOWN, (int)MULTI_ARG_1_DF }, { OPTION_MASK_ISA_XOP, CODE_FOR_xop_frczv4sf2, "__builtin_ia32_vfrczps", IX86_BUILTIN_VFRCZPS, UNKNOWN, (int)MULTI_ARG_1_SF }, { OPTION_MASK_ISA_XOP, CODE_FOR_xop_frczv2df2, "__builtin_ia32_vfrczpd", IX86_BUILTIN_VFRCZPD, UNKNOWN, (int)MULTI_ARG_1_DF }, { OPTION_MASK_ISA_XOP, CODE_FOR_xop_frczv8sf2, "__builtin_ia32_vfrczps256", IX86_BUILTIN_VFRCZPS256, UNKNOWN, (int)MULTI_ARG_1_SF2 }, @@ -34753,7 +34780,6 @@ ix86_class_likely_spilled_p (reg_class_t rclass) case SSE_FIRST_REG: case FP_TOP_REG: case FP_SECOND_REG: - case BND_REGS: return true; default: @@ -35102,8 +35128,6 @@ ix86_hard_regno_mode_ok (int regno, enum machine_mode mode) return VALID_FP_MODE_P (mode); if (MASK_REGNO_P (regno)) return VALID_MASK_REG_MODE (mode); - if (BND_REGNO_P (regno)) - return VALID_BND_REG_MODE (mode); if (SSE_REGNO_P (regno)) { /* We implement the move patterns for all vector modes into and @@ -35917,10 +35941,6 @@ x86_order_regs_for_local_alloc (void) for (i = FIRST_MASK_REG; i <= LAST_MASK_REG; i++) reg_alloc_order [pos++] = i; - /* MPX bound registers. */ - for (i = FIRST_BND_REG; i <= LAST_BND_REG; i++) - reg_alloc_order [pos++] = i; - /* x87 registers. */ if (TARGET_SSE_MATH) for (i = FIRST_STACK_REG; i <= LAST_STACK_REG; i++) @@ -42419,18 +42439,6 @@ ix86_expand_sse2_mulvxdi3 (rtx op0, rtx op1, rtx op2) gen_rtx_MULT (mode, op1, op2)); } -/* Return 1 if control tansfer instruction INSN - should be encoded with bnd prefix. - If insn is NULL then return 1 when control - transfer instructions should be prefixed with - bnd by default for current function. */ - -bool -ix86_bnd_prefixed_insn_p (rtx insn ATTRIBUTE_UNUSED) -{ - return false; -} - /* Calculate integer abs() using only SSE2 instructions. */ void @@ -43681,6 +43689,184 @@ ix86_memmodel_check (unsigned HOST_WIDE_INT val) return val; } +/* Set CLONEI->vecsize_mangle, CLONEI->vecsize_int, + CLONEI->vecsize_float and if CLONEI->simdlen is 0, also + CLONEI->simdlen. Return 0 if SIMD clones shouldn't be emitted, + or number of vecsize_mangle variants that should be emitted. */ + +static int +ix86_simd_clone_compute_vecsize_and_simdlen (struct cgraph_node *node, + struct cgraph_simd_clone *clonei, + tree base_type, int num) +{ + int ret = 1; + + if (clonei->simdlen + && (clonei->simdlen < 2 + || clonei->simdlen > 16 + || (clonei->simdlen & (clonei->simdlen - 1)) != 0)) + { + warning_at (DECL_SOURCE_LOCATION (node->decl), 0, + "unsupported simdlen %d\n", clonei->simdlen); + return 0; + } + + tree ret_type = TREE_TYPE (TREE_TYPE (node->decl)); + if (TREE_CODE (ret_type) != VOID_TYPE) + switch (TYPE_MODE (ret_type)) + { + case QImode: + case HImode: + case SImode: + case DImode: + case SFmode: + case DFmode: + /* case SCmode: */ + /* case DCmode: */ + break; + default: + warning_at (DECL_SOURCE_LOCATION (node->decl), 0, + "unsupported return type %qT for simd\n", ret_type); + return 0; + } + + tree t; + int i; + + for (t = DECL_ARGUMENTS (node->decl), i = 0; t; t = DECL_CHAIN (t), i++) + /* FIXME: Shouldn't we allow such arguments if they are uniform? */ + switch (TYPE_MODE (TREE_TYPE (t))) + { + case QImode: + case HImode: + case SImode: + case DImode: + case SFmode: + case DFmode: + /* case SCmode: */ + /* case DCmode: */ + break; + default: + warning_at (DECL_SOURCE_LOCATION (node->decl), 0, + "unsupported argument type %qT for simd\n", TREE_TYPE (t)); + return 0; + } + + if (clonei->cilk_elemental) + { + /* Parse here processor clause. If not present, default to 'b'. */ + clonei->vecsize_mangle = 'b'; + } + else if (!TREE_PUBLIC (node->decl)) + { + /* If the function isn't exported, we can pick up just one ISA + for the clones. */ + if (TARGET_AVX2) + clonei->vecsize_mangle = 'd'; + else if (TARGET_AVX) + clonei->vecsize_mangle = 'c'; + else + clonei->vecsize_mangle = 'b'; + ret = 1; + } + else + { + clonei->vecsize_mangle = "bcd"[num]; + ret = 3; + } + switch (clonei->vecsize_mangle) + { + case 'b': + clonei->vecsize_int = 128; + clonei->vecsize_float = 128; + break; + case 'c': + clonei->vecsize_int = 128; + clonei->vecsize_float = 256; + break; + case 'd': + clonei->vecsize_int = 256; + clonei->vecsize_float = 256; + break; + } + if (clonei->simdlen == 0) + { + if (SCALAR_INT_MODE_P (TYPE_MODE (base_type))) + clonei->simdlen = clonei->vecsize_int; + else + clonei->simdlen = clonei->vecsize_float; + clonei->simdlen /= GET_MODE_BITSIZE (TYPE_MODE (base_type)); + if (clonei->simdlen > 16) + clonei->simdlen = 16; + } + return ret; +} + +/* Add target attribute to SIMD clone NODE if needed. */ + +static void +ix86_simd_clone_adjust (struct cgraph_node *node) +{ + const char *str = NULL; + gcc_assert (node->decl == cfun->decl); + switch (node->simdclone->vecsize_mangle) + { + case 'b': + if (!TARGET_SSE2) + str = "sse2"; + break; + case 'c': + if (!TARGET_AVX) + str = "avx"; + break; + case 'd': + if (!TARGET_AVX2) + str = "avx2"; + break; + default: + gcc_unreachable (); + } + if (str == NULL) + return; + push_cfun (NULL); + tree args = build_tree_list (NULL_TREE, build_string (strlen (str), str)); + bool ok = ix86_valid_target_attribute_p (node->decl, NULL, args, 0); + gcc_assert (ok); + pop_cfun (); + ix86_previous_fndecl = NULL_TREE; + ix86_set_current_function (node->decl); +} + +/* If SIMD clone NODE can't be used in a vectorized loop + in current function, return -1, otherwise return a badness of using it + (0 if it is most desirable from vecsize_mangle point of view, 1 + slightly less desirable, etc.). */ + +static int +ix86_simd_clone_usable (struct cgraph_node *node) +{ + switch (node->simdclone->vecsize_mangle) + { + case 'b': + if (!TARGET_SSE2) + return -1; + if (!TARGET_AVX) + return 0; + return TARGET_AVX2 ? 2 : 1; + case 'c': + if (!TARGET_AVX) + return -1; + return TARGET_AVX2 ? 1 : 0; + break; + case 'd': + if (!TARGET_AVX2) + return -1; + return 0; + default: + gcc_unreachable (); + } +} + /* Implement TARGET_FLOAT_EXCEPTIONS_ROUNDING_SUPPORTED_P. */ static bool @@ -44169,6 +44355,18 @@ ix86_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update) #undef TARGET_SPILL_CLASS #define TARGET_SPILL_CLASS ix86_spill_class +#undef TARGET_SIMD_CLONE_COMPUTE_VECSIZE_AND_SIMDLEN +#define TARGET_SIMD_CLONE_COMPUTE_VECSIZE_AND_SIMDLEN \ + ix86_simd_clone_compute_vecsize_and_simdlen + +#undef TARGET_SIMD_CLONE_ADJUST +#define TARGET_SIMD_CLONE_ADJUST \ + ix86_simd_clone_adjust + +#undef TARGET_SIMD_CLONE_USABLE +#define TARGET_SIMD_CLONE_USABLE \ + ix86_simd_clone_usable + #undef TARGET_FLOAT_EXCEPTIONS_ROUNDING_SUPPORTED_P #define TARGET_FLOAT_EXCEPTIONS_ROUNDING_SUPPORTED_P \ ix86_float_exceptions_rounding_supported_p diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index 2fd5fddbdc6..113c75e0813 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -128,8 +128,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #define TARGET_XSAVE_P(x) TARGET_ISA_XSAVE_P(x) #define TARGET_XSAVEOPT TARGET_ISA_XSAVEOPT #define TARGET_XSAVEOPT_P(x) TARGET_ISA_XSAVEOPT_P(x) -#define TARGET_MPX TARGET_ISA_MPX -#define TARGET_MPX_P(x) TARGET_ISA_MPX_P(x) #define TARGET_LP64 TARGET_ABI_64 #define TARGET_LP64_P(x) TARGET_ABI_64_P(x) @@ -960,7 +958,7 @@ enum target_cpu_default eliminated during reloading in favor of either the stack or frame pointer. */ -#define FIRST_PSEUDO_REGISTER 81 +#define FIRST_PSEUDO_REGISTER 77 /* Number of hardware registers that go into the DWARF-2 unwind info. If not defined, equals FIRST_PSEUDO_REGISTER. */ @@ -992,9 +990,7 @@ enum target_cpu_default /*xmm24,xmm25,xmm26,xmm27,xmm28,xmm29,xmm30,xmm31*/ \ 0, 0, 0, 0, 0, 0, 0, 0, \ /* k0, k1, k2, k3, k4, k5, k6, k7*/ \ - 0, 0, 0, 0, 0, 0, 0, 0, \ -/* b0, b1, b2, b3*/ \ - 0, 0, 0, 0 } + 0, 0, 0, 0, 0, 0, 0, 0 } /* 1 for registers not available across function calls. These must include the FIXED_REGISTERS and also any @@ -1028,9 +1024,7 @@ enum target_cpu_default /*xmm24,xmm25,xmm26,xmm27,xmm28,xmm29,xmm30,xmm31*/ \ 6, 6, 6, 6, 6, 6, 6, 6, \ /* k0, k1, k2, k3, k4, k5, k6, k7*/ \ - 1, 1, 1, 1, 1, 1, 1, 1, \ -/* b0, b1, b2, b3*/ \ - 1, 1, 1, 1 } + 1, 1, 1, 1, 1, 1, 1, 1 } /* Order in which to allocate registers. Each register must be listed once, even those in FIXED_REGISTERS. List frame pointer @@ -1046,8 +1040,7 @@ enum target_cpu_default 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, \ 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, \ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, \ - 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, \ - 78, 79, 80 } + 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76 } /* ADJUST_REG_ALLOC_ORDER is a macro which permits reg_alloc_order to be rearranged based on a particular function. When using sse math, @@ -1069,7 +1062,6 @@ enum target_cpu_default #define HARD_REGNO_NREGS(REGNO, MODE) \ (STACK_REGNO_P (REGNO) || SSE_REGNO_P (REGNO) || MMX_REGNO_P (REGNO) \ - || BND_REGNO_P (REGNO) \ ? (COMPLEX_MODE_P (MODE) ? 2 : 1) \ : ((MODE) == XFmode \ ? (TARGET_64BIT ? 2 : 3) \ @@ -1119,9 +1111,6 @@ enum target_cpu_default || (MODE) == V2SImode || (MODE) == SImode \ || (MODE) == V4HImode || (MODE) == V8QImode) -#define VALID_BND_REG_MODE(MODE) \ - (TARGET_64BIT ? (MODE) == BND64mode : (MODE) == BND32mode) - #define VALID_DFP_MODE_P(MODE) \ ((MODE) == SDmode || (MODE) == DDmode || (MODE) == TDmode) @@ -1228,9 +1217,6 @@ enum target_cpu_default #define FIRST_MASK_REG (LAST_EXT_REX_SSE_REG + 1) /*69*/ #define LAST_MASK_REG (FIRST_MASK_REG + 7) /*76*/ -#define FIRST_BND_REG (LAST_MASK_REG + 1) /*77*/ -#define LAST_BND_REG (FIRST_BND_REG + 3) /*80*/ - /* Override this in other tm.h files to cope with various OS lossage requiring a frame pointer. */ #ifndef SUBTARGET_FRAME_POINTER_REQUIRED @@ -1311,7 +1297,6 @@ enum reg_class SSE_FIRST_REG, SSE_REGS, EVEX_SSE_REGS, - BND_REGS, ALL_SSE_REGS, MMX_REGS, FP_TOP_SSE_REGS, @@ -1369,7 +1354,6 @@ enum reg_class "SSE_FIRST_REG", \ "SSE_REGS", \ "EVEX_SSE_REGS", \ - "BND_REGS", \ "ALL_SSE_REGS", \ "MMX_REGS", \ "FP_TOP_SSE_REGS", \ @@ -1389,38 +1373,37 @@ enum reg_class TARGET_CONDITIONAL_REGISTER_USAGE. */ #define REG_CLASS_CONTENTS \ -{ { 0x00, 0x0, 0x0 }, \ - { 0x01, 0x0, 0x0 }, /* AREG */ \ - { 0x02, 0x0, 0x0 }, /* DREG */ \ - { 0x04, 0x0, 0x0 }, /* CREG */ \ - { 0x08, 0x0, 0x0 }, /* BREG */ \ - { 0x10, 0x0, 0x0 }, /* SIREG */ \ - { 0x20, 0x0, 0x0 }, /* DIREG */ \ - { 0x03, 0x0, 0x0 }, /* AD_REGS */ \ - { 0x0f, 0x0, 0x0 }, /* Q_REGS */ \ - { 0x1100f0, 0x1fe0, 0x0 }, /* NON_Q_REGS */ \ - { 0x7f, 0x1fe0, 0x0 }, /* INDEX_REGS */ \ - { 0x1100ff, 0x0, 0x0 }, /* LEGACY_REGS */ \ - { 0x07, 0x0, 0x0 }, /* CLOBBERED_REGS */ \ - { 0x1100ff, 0x1fe0, 0x0 }, /* GENERAL_REGS */ \ - { 0x100, 0x0, 0x0 }, /* FP_TOP_REG */ \ - { 0x0200, 0x0, 0x0 }, /* FP_SECOND_REG */ \ - { 0xff00, 0x0, 0x0 }, /* FLOAT_REGS */ \ - { 0x200000, 0x0, 0x0 }, /* SSE_FIRST_REG */ \ -{ 0x1fe00000, 0x1fe000, 0x0 }, /* SSE_REGS */ \ - { 0x0,0xffe00000, 0x1f }, /* EVEX_SSE_REGS */ \ - { 0x0, 0x0,0x1e000 }, /* BND_REGS */ \ -{ 0x1fe00000,0xffffe000, 0x1f }, /* ALL_SSE_REGS */ \ -{ 0xe0000000, 0x1f, 0x0 }, /* MMX_REGS */ \ -{ 0x1fe00100,0xffffe000, 0x1f }, /* FP_TOP_SSE_REG */ \ -{ 0x1fe00200,0xffffe000, 0x1f }, /* FP_SECOND_SSE_REG */ \ -{ 0x1fe0ff00,0xffffe000, 0x1f }, /* FLOAT_SSE_REGS */ \ -{ 0x11ffff, 0x1fe0, 0x0 }, /* FLOAT_INT_REGS */ \ -{ 0x1ff100ff,0xffffffe0, 0x1f }, /* INT_SSE_REGS */ \ -{ 0x1ff1ffff,0xffffffe0, 0x1f }, /* FLOAT_INT_SSE_REGS */ \ - { 0x0, 0x0, 0x1fc0 }, /* MASK_EVEX_REGS */ \ - { 0x0, 0x0, 0x1fe0 }, /* MASK_REGS */ \ -{ 0xffffffff,0xffffffff, 0x1fff } \ +{ { 0x00, 0x0, 0x0 }, \ + { 0x01, 0x0, 0x0 }, /* AREG */ \ + { 0x02, 0x0, 0x0 }, /* DREG */ \ + { 0x04, 0x0, 0x0 }, /* CREG */ \ + { 0x08, 0x0, 0x0 }, /* BREG */ \ + { 0x10, 0x0, 0x0 }, /* SIREG */ \ + { 0x20, 0x0, 0x0 }, /* DIREG */ \ + { 0x03, 0x0, 0x0 }, /* AD_REGS */ \ + { 0x0f, 0x0, 0x0 }, /* Q_REGS */ \ + { 0x1100f0, 0x1fe0, 0x0 }, /* NON_Q_REGS */ \ + { 0x7f, 0x1fe0, 0x0 }, /* INDEX_REGS */ \ + { 0x1100ff, 0x0, 0x0 }, /* LEGACY_REGS */ \ + { 0x07, 0x0, 0x0 }, /* CLOBBERED_REGS */ \ + { 0x1100ff, 0x1fe0, 0x0 }, /* GENERAL_REGS */ \ + { 0x100, 0x0, 0x0 }, /* FP_TOP_REG */ \ + { 0x0200, 0x0, 0x0 }, /* FP_SECOND_REG */ \ + { 0xff00, 0x0, 0x0 }, /* FLOAT_REGS */ \ + { 0x200000, 0x0, 0x0 }, /* SSE_FIRST_REG */ \ +{ 0x1fe00000, 0x1fe000, 0x0 }, /* SSE_REGS */ \ + { 0x0,0xffe00000, 0x1f }, /* EVEX_SSE_REGS */ \ +{ 0x1fe00000,0xffffe000, 0x1f }, /* ALL_SSE_REGS */ \ +{ 0xe0000000, 0x1f, 0x0 }, /* MMX_REGS */ \ +{ 0x1fe00100,0xffffe000, 0x1f }, /* FP_TOP_SSE_REG */ \ +{ 0x1fe00200,0xffffe000, 0x1f }, /* FP_SECOND_SSE_REG */ \ +{ 0x1fe0ff00,0xffffe000, 0x1f }, /* FLOAT_SSE_REGS */ \ +{ 0x11ffff, 0x1fe0, 0x0 }, /* FLOAT_INT_REGS */ \ +{ 0x1ff100ff,0xffffffe0, 0x1f }, /* INT_SSE_REGS */ \ +{ 0x1ff1ffff,0xffffffe0, 0x1f }, /* FLOAT_INT_SSE_REGS */ \ + { 0x0, 0x0,0x1fc0 }, /* MASK_EVEX_REGS */ \ + { 0x0, 0x0,0x1fe0 }, /* MASK_REGS */ \ +{ 0xffffffff,0xffffffff,0x1fff } \ } /* The same information, inverted: @@ -1496,9 +1479,6 @@ enum reg_class #define CC_REG_P(X) (REG_P (X) && CC_REGNO_P (REGNO (X))) #define CC_REGNO_P(X) ((X) == FLAGS_REG || (X) == FPSR_REG) -#define BND_REGNO_P(N) IN_RANGE ((N), FIRST_BND_REG, LAST_BND_REG) -#define ANY_BND_REG_P(X) (REG_P (X) && BND_REGNO_P (REGNO (X))) - /* The class value for index registers, and the one for base regs. */ #define INDEX_REG_CLASS INDEX_REGS @@ -1943,9 +1923,6 @@ do { \ between pointers and any other objects of this machine mode. */ #define Pmode (ix86_pmode == PMODE_DI ? DImode : SImode) -/* Specify the machine mode that bounds have. */ -#define BNDmode (ix86_pmode == PMODE_DI ? BND64mode : BND32mode) - /* A C expression whose value is zero if pointers that need to be extended from being `POINTER_SIZE' bits wide to `Pmode' are sign-extended and greater then zero if they are zero-extended and less then zero if the @@ -2056,8 +2033,7 @@ do { \ "xmm20", "xmm21", "xmm22", "xmm23", \ "xmm24", "xmm25", "xmm26", "xmm27", \ "xmm28", "xmm29", "xmm30", "xmm31", \ - "k0", "k1", "k2", "k3", "k4", "k5", "k6", "k7", \ - "bnd0", "bnd1", "bnd2", "bnd3" } + "k0", "k1", "k2", "k3", "k4", "k5", "k6", "k7" } #define REGISTER_NAMES HI_REGISTER_NAMES diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 8178f9b9ab0..6976124d4a8 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -63,7 +63,6 @@ ;; ~ -- print "i" if TARGET_AVX2, "f" otherwise. ;; @ -- print a segment register of thread base pointer load ;; ^ -- print addr32 prefix if TARGET_64BIT and Pmode != word_mode -;; ! -- print MPX prefix for jxx/call/ret instructions if required. (define_c_enum "unspec" [ ;; Relocation specifiers @@ -179,16 +178,6 @@ ;; For BMI2 support UNSPEC_PDEP UNSPEC_PEXT - - UNSPEC_BNDMK - UNSPEC_BNDMK_ADDR - UNSPEC_BNDSTX - UNSPEC_BNDLDX - UNSPEC_BNDLDX_ADDR - UNSPEC_BNDCL - UNSPEC_BNDCU - UNSPEC_BNDCN - UNSPEC_MPX_FENCE ]) (define_c_enum "unspecv" [ @@ -353,8 +342,6 @@ (MASK5_REG 74) (MASK6_REG 75) (MASK7_REG 76) - (BND0_REG 77) - (BND1_REG 78) ]) ;; Insns whose names begin with "x86_" are emitted by gen_FOO calls @@ -389,8 +376,7 @@ ssecvt,ssecvt1,sseicvt,sseins, sseshuf,sseshuf1,ssemuladd,sse4arg, lwp,mskmov,msklog, - mmx,mmxmov,mmxadd,mmxmul,mmxcmp,mmxcvt,mmxshft, - mpxmov,mpxmk,mpxchk,mpxld,mpxst" + mmx,mmxmov,mmxadd,mmxmul,mmxcmp,mmxcvt,mmxshft" (const_string "other")) ;; Main data type used by the insn @@ -419,8 +405,7 @@ ;; The (bounding maximum) length of an instruction immediate. (define_attr "length_immediate" "" (cond [(eq_attr "type" "incdec,setcc,icmov,str,lea,other,multi,idiv,leave, - bitmanip,imulx,msklog,mskmov,mpxmk,mpxmov,mpxchk, - mpxld,mpxst") + bitmanip,imulx,msklog,mskmov") (const_int 0) (eq_attr "unit" "i387,sse,mmx") (const_int 0) @@ -475,17 +460,13 @@ (const_int 0) (and (eq_attr "unit" "sse") (eq_attr "mode" "SF,DF")) (const_int 1) - (and (eq_attr "type" "ibr,call,callv") - (match_test "ix86_bnd_prefixed_insn_p (insn)")) - (const_int 1) ] (const_int 0))) ;; Set when 0f opcode prefix is used. (define_attr "prefix_0f" "" (if_then_else - (ior (eq_attr "type" "imovx,setcc,icmov,bitmanip,msklog,mskmov, - mpxmk,mpxmov,mpxchk,mpxld,mpxst") + (ior (eq_attr "type" "imovx,setcc,icmov,bitmanip,msklog,mskmov") (eq_attr "unit" "sse,mmx")) (const_int 1) (const_int 0))) @@ -588,19 +569,12 @@ ] (const_int 1))) -;; When this attribute is set, calculate total insn length from -;; length_nobnd attribute, prefixed with eventual bnd prefix byte -(define_attr "length_nobnd" "" (const_int 0)) - ;; The (bounding maximum) length of an instruction in bytes. ;; ??? fistp and frndint are in fact fldcw/{fistp,frndint}/fldcw sequences. ;; Later we may want to split them and compute proper length as for ;; other insns. (define_attr "length" "" - (cond [(eq_attr "length_nobnd" "!0") - (plus (symbol_ref ("ix86_bnd_prefixed_insn_p (insn)")) - (attr "length_nobnd")) - (eq_attr "type" "other,multi,fistp,frndint") + (cond [(eq_attr "type" "other,multi,fistp,frndint") (const_int 16) (eq_attr "type" "fcmp") (const_int 4) @@ -641,16 +615,12 @@ (define_attr "memory" "none,load,store,both,unknown" (cond [(eq_attr "type" "other,multi,str,lwp") (const_string "unknown") - (eq_attr "type" "lea,fcmov,fpspc,mpxmk,mpxchk") + (eq_attr "type" "lea,fcmov,fpspc") (const_string "none") (eq_attr "type" "fistp,leave") (const_string "both") (eq_attr "type" "frndint") (const_string "load") - (eq_attr "type" "mpxld") - (const_string "load") - (eq_attr "type" "mpxst") - (const_string "store") (eq_attr "type" "push") (if_then_else (match_operand 1 "memory_operand") (const_string "both") @@ -696,7 +666,7 @@ fmov,fcmp,fsgn, sse,ssemov,ssecmp,ssecomi,ssecvt,ssecvt1,sseicvt, sselog1,sseshuf1,sseadd1,sseiadd1,sseishft1, - mmx,mmxmov,mmxcmp,mmxcvt,mskmov,msklog,mpxmov") + mmx,mmxmov,mmxcmp,mmxcvt,mskmov,msklog") (match_operand 2 "memory_operand")) (const_string "load") (and (eq_attr "type" "icmov,ssemuladd,sse4arg") @@ -935,21 +905,6 @@ (define_mode_iterator DWIH [(SI "!TARGET_64BIT") (DI "TARGET_64BIT")]) -;; Bound modes. -(define_mode_iterator BND [(BND32 "!TARGET_LP64") - (BND64 "TARGET_LP64")]) - -;; Pointer mode corresponding to bound mode. -(define_mode_attr bnd_ptr [(BND32 "SI") (BND64 "DI")]) - -;; MPX check types -(define_int_iterator BNDCHECK [UNSPEC_BNDCL UNSPEC_BNDCU UNSPEC_BNDCN]) - -;; Check name -(define_int_attr bndcheck [(UNSPEC_BNDCL "cl") - (UNSPEC_BNDCU "cu") - (UNSPEC_BNDCN "cn")]) - ;; Instruction suffix for integer modes. (define_mode_attr imodesuffix [(QI "b") (HI "w") (SI "l") (DI "q")]) @@ -10799,10 +10754,10 @@ (label_ref (match_operand 0)) (pc)))] "" - "%!%+j%C1\t%l0" + "%+j%C1\t%l0" [(set_attr "type" "ibr") (set_attr "modrm" "0") - (set (attr "length_nobnd") + (set (attr "length") (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -126)) (lt (minus (match_dup 0) (pc)) @@ -10817,10 +10772,10 @@ (pc) (label_ref (match_operand 0))))] "" - "%!%+j%c1\t%l0" + "%+j%c1\t%l0" [(set_attr "type" "ibr") (set_attr "modrm" "0") - (set (attr "length_nobnd") + (set (attr "length") (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -126)) (lt (minus (match_dup 0) (pc)) @@ -11283,9 +11238,9 @@ [(set (pc) (label_ref (match_operand 0)))] "" - "%!jmp\t%l0" + "jmp\t%l0" [(set_attr "type" "ibr") - (set (attr "length_nobnd") + (set (attr "length") (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -126)) (lt (minus (match_dup 0) (pc)) @@ -11305,7 +11260,7 @@ (define_insn "*indirect_jump" [(set (pc) (match_operand:W 0 "indirect_branch_operand" "rw"))] "" - "%!jmp\t%A0" + "jmp\t%A0" [(set_attr "type" "ibr") (set_attr "length_immediate" "0")]) @@ -11354,7 +11309,7 @@ [(set (pc) (match_operand:W 0 "indirect_branch_operand" "rw")) (use (label_ref (match_operand 1)))] "" - "%!jmp\t%A0" + "jmp\t%A0" [(set_attr "type" "ibr") (set_attr "length_immediate" "0")]) @@ -11741,8 +11696,8 @@ (define_insn "simple_return_internal" [(simple_return)] "reload_completed" - "%!ret" - [(set_attr "length_nobnd" "1") + "ret" + [(set_attr "length" "1") (set_attr "atom_unit" "jeu") (set_attr "length_immediate" "0") (set_attr "modrm" "0")]) @@ -11754,12 +11709,7 @@ [(simple_return) (unspec [(const_int 0)] UNSPEC_REP)] "reload_completed" -{ - if (ix86_bnd_prefixed_insn_p (insn)) - return "%!ret"; - - return "rep%; ret"; -} + "rep%; ret" [(set_attr "length" "2") (set_attr "atom_unit" "jeu") (set_attr "length_immediate" "0") @@ -11770,8 +11720,8 @@ [(simple_return) (use (match_operand:SI 0 "const_int_operand"))] "reload_completed" - "%!ret\t%0" - [(set_attr "length_nobnd" "3") + "ret\t%0" + [(set_attr "length" "3") (set_attr "atom_unit" "jeu") (set_attr "length_immediate" "2") (set_attr "modrm" "0")]) @@ -11780,7 +11730,7 @@ [(simple_return) (use (match_operand:SI 0 "register_operand" "r"))] "reload_completed" - "%!jmp\t%A0" + "jmp\t%A0" [(set_attr "type" "ibr") (set_attr "length_immediate" "0")]) @@ -18333,131 +18283,6 @@ [(set_attr "type" "other") (set_attr "length" "3")]) -;; MPX instructions - -(define_expand "<mode>_mk" - [(set (match_operand:BND 0 "register_operand") - (unspec:BND - [(mem:<bnd_ptr> - (match_par_dup 3 - [(match_operand:<bnd_ptr> 1 "register_operand") - (match_operand:<bnd_ptr> 2 "address_mpx_no_base_operand")]))] - UNSPEC_BNDMK))] - "TARGET_MPX" -{ - operands[3] = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, operands[1], - operands[2]), - UNSPEC_BNDMK_ADDR); -}) - -(define_insn "*<mode>_mk" - [(set (match_operand:BND 0 "register_operand" "=B") - (unspec:BND - [(match_operator:<bnd_ptr> 3 "bnd_mem_operator" - [(unspec:<bnd_ptr> - [(match_operand:<bnd_ptr> 1 "register_operand" "r") - (match_operand:<bnd_ptr> 2 "address_mpx_no_base_operand" "Tb")] - UNSPEC_BNDMK_ADDR)])] - UNSPEC_BNDMK))] - "TARGET_MPX" - "bndmk\t{%3, %0|%0, %3}" - [(set_attr "type" "mpxmk")]) - -(define_expand "mov<mode>" - [(set (match_operand:BND 0 "general_operand") - (match_operand:BND 1 "general_operand"))] - "TARGET_MPX" -{ - ix86_expand_move (<MODE>mode, operands);DONE; -}) - -(define_insn "*mov<mode>_internal_mpx" - [(set (match_operand:BND 0 "nonimmediate_operand" "=B,m") - (match_operand:BND 1 "general_operand" "Bm,B"))] - "TARGET_MPX" - "bndmov\t{%1, %0|%0, %1}" - [(set_attr "type" "mpxmov")]) - -(define_expand "<mode>_<bndcheck>" - [(parallel [(unspec [(match_operand:BND 0 "register_operand") - (match_operand:<bnd_ptr> 1 "address_no_seg_operand")] BNDCHECK) - (set (match_dup 2) - (unspec:BLK [(match_dup 2)] UNSPEC_MPX_FENCE))])] - "TARGET_MPX" -{ - operands[2] = gen_rtx_MEM (BLKmode, operands[1]); - MEM_VOLATILE_P (operands[2]) = 1; -}) - -(define_insn "*<mode>_<bndcheck>" - [(parallel [(unspec [(match_operand:BND 0 "register_operand" "B") - (match_operand:<bnd_ptr> 1 "address_no_seg_operand" "Ts")] BNDCHECK) - (set (match_operand:BLK 2 "bnd_mem_operator") - (unspec:BLK [(match_dup 2)] UNSPEC_MPX_FENCE))])] - "TARGET_MPX" - "bnd<bndcheck>\t{%a1, %0|%0, %a1}" - [(set_attr "type" "mpxchk")]) - -(define_expand "<mode>_ldx" - [(parallel [(set:BND (match_operand:BND 0 "register_operand") - (unspec:BND - [(mem:<bnd_ptr> - (match_par_dup 3 - [(match_operand:<bnd_ptr> 1 "address_mpx_no_index_operand") - (match_operand:<bnd_ptr> 2 "register_operand")]))] - UNSPEC_BNDLDX)) - (use (mem:BLK (match_dup 1)))])] - "TARGET_MPX" -{ - operands[3] = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, operands[1], - operands[2]), - UNSPEC_BNDLDX_ADDR); -}) - -(define_insn "*<mode>_ldx" - [(parallel [(set:BND (match_operand:BND 0 "register_operand" "=B") - (unspec:BND - [(match_operator:<bnd_ptr> 3 "bnd_mem_operator" - [(unspec:<bnd_ptr> - [(match_operand:<bnd_ptr> 1 "address_mpx_no_index_operand" "Ti") - (match_operand:<bnd_ptr> 2 "register_operand" "l")] - UNSPEC_BNDLDX_ADDR)])] - UNSPEC_BNDLDX)) - (use (mem:BLK (match_dup 1)))])] - "TARGET_MPX" - "bndldx\t{%3, %0|%0, %3}" - [(set_attr "type" "mpxld")]) - -(define_expand "<mode>_stx" - [(parallel [(unspec [(mem:<bnd_ptr> - (match_par_dup 3 - [(match_operand:<bnd_ptr> 0 "address_mpx_no_index_operand") - (match_operand:<bnd_ptr> 1 "register_operand")])) - (match_operand:BND 2 "register_operand")] UNSPEC_BNDSTX) - (set (match_dup 4) - (unspec:BLK [(match_dup 4)] UNSPEC_MPX_FENCE))])] - "TARGET_MPX" -{ - operands[3] = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, operands[0], - operands[1]), - UNSPEC_BNDLDX_ADDR); - operands[4] = gen_rtx_MEM (BLKmode, operands[0]); - MEM_VOLATILE_P (operands[4]) = 1; -}) - -(define_insn "*<mode>_stx" - [(parallel [(unspec [(match_operator:<bnd_ptr> 3 "bnd_mem_operator" - [(unspec:<bnd_ptr> - [(match_operand:<bnd_ptr> 0 "address_mpx_no_index_operand" "Ti") - (match_operand:<bnd_ptr> 1 "register_operand" "l")] - UNSPEC_BNDLDX_ADDR)]) - (match_operand:BND 2 "register_operand" "B")] UNSPEC_BNDSTX) - (set (match_operand:BLK 4 "bnd_mem_operator") - (unspec:BLK [(match_dup 4)] UNSPEC_MPX_FENCE))])] - "TARGET_MPX" - "bndstx\t{%2, %3|%3, %2}" - [(set_attr "type" "mpxst")]) - (include "mmx.md") (include "sse.md") (include "sync.md") diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt index c4f9c8cb28e..1704c526746 100644 --- a/gcc/config/i386/i386.opt +++ b/gcc/config/i386/i386.opt @@ -48,6 +48,14 @@ unsigned char arch TargetSave unsigned char tune +;; -march= processor-string +TargetSave +const char *x_ix86_arch_string + +;; -mtune= processor-string +TargetSave +const char *x_ix86_tune_string + ;; CPU schedule model TargetSave unsigned char schedule @@ -76,6 +84,94 @@ unsigned char tune_defaulted TargetSave unsigned char arch_specified +;; -mcmodel= model +TargetSave +enum cmodel x_ix86_cmodel + +;; -mabi= +TargetSave +enum calling_abi x_ix86_abi + +;; -masm= +TargetSave +enum asm_dialect x_ix86_asm_dialect + +;; -mbranch-cost= +TargetSave +int x_ix86_branch_cost + +;; -mdump-tune-features= +TargetSave +int x_ix86_dump_tunes + +;; -mstackrealign= +TargetSave +int x_ix86_force_align_arg_pointer + +;; -mforce-drap= +TargetSave +int x_ix86_force_drap + +;; -mincoming-stack-boundary= +TargetSave +int x_ix86_incoming_stack_boundary_arg + +;; -maddress-mode= +TargetSave +enum pmode x_ix86_pmode + +;; -mpreferred-stack-boundary= +TargetSave +int x_ix86_preferred_stack_boundary_arg + +;; -mrecip= +TargetSave +const char *x_ix86_recip_name + +;; -mregparm= +TargetSave +int x_ix86_regparm + +;; -mlarge-data-threshold= +TargetSave +int x_ix86_section_threshold + +;; -msse2avx= +TargetSave +int x_ix86_sse2avx + +;; -mstack-protector-guard= +TargetSave +enum stack_protector_guard x_ix86_stack_protector_guard + +;; -mstringop-strategy= +TargetSave +enum stringop_alg x_ix86_stringop_alg + +;; -mtls-dialect= +TargetSave +enum tls_dialect x_ix86_tls_dialect + +;; -mtune-ctrl= +TargetSave +const char *x_ix86_tune_ctrl_string + +;; -mmemcpy-strategy= +TargetSave +const char *x_ix86_tune_memcpy_strategy + +;; -mmemset-strategy= +TargetSave +const char *x_ix86_tune_memset_strategy + +;; -mno-default= +TargetSave +int x_ix86_tune_no_default + +;; -mveclibabi= +TargetSave +enum ix86_veclibabi x_ix86_veclibabi_type + ;; x86 options m128bit-long-double Target RejectNegative Report Mask(128BIT_LONG_DOUBLE) Save @@ -669,10 +765,6 @@ mrtm Target Report Mask(ISA_RTM) Var(ix86_isa_flags) Save Support RTM built-in functions and code generation -mmpx -Target Report Mask(ISA_MPX) Var(ix86_isa_flags) Save -Support MPX code generation - mstack-protector-guard= Target RejectNegative Joined Enum(stack_protector_guard) Var(ix86_stack_protector_guard) Init(SSP_TLS) Use given stack-protector guard diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md index 66ac52fd8c4..b86201924c3 100644 --- a/gcc/config/i386/predicates.md +++ b/gcc/config/i386/predicates.md @@ -982,74 +982,9 @@ return true; }) -;; Return true if op is valid MPX address operand without base -(define_predicate "address_mpx_no_base_operand" - (match_operand 0 "address_operand") -{ - struct ix86_address parts; - int ok; - - ok = ix86_decompose_address (op, &parts); - gcc_assert (ok); - - if (parts.index && parts.base) - return false; - - if (parts.seg != SEG_DEFAULT) - return false; - - /* Do not support (%rip). */ - if (parts.disp && flag_pic && TARGET_64BIT - && SYMBOLIC_CONST (parts.disp)) - { - if (GET_CODE (parts.disp) != CONST - || GET_CODE (XEXP (parts.disp, 0)) != PLUS - || GET_CODE (XEXP (XEXP (parts.disp, 0), 0)) != UNSPEC - || !CONST_INT_P (XEXP (XEXP (parts.disp, 0), 1)) - || (XINT (XEXP (XEXP (parts.disp, 0), 0), 1) != UNSPEC_DTPOFF - && XINT (XEXP (XEXP (parts.disp, 0), 0), 1) != UNSPEC_NTPOFF)) - return false; - } - - return true; -}) - -;; Return true if op is valid MPX address operand without index -(define_predicate "address_mpx_no_index_operand" - (match_operand 0 "address_operand") -{ - struct ix86_address parts; - int ok; - - ok = ix86_decompose_address (op, &parts); - gcc_assert (ok); - - if (parts.index) - return false; - - if (parts.seg != SEG_DEFAULT) - return false; - - /* Do not support (%rip). */ - if (parts.disp && flag_pic && TARGET_64BIT - && SYMBOLIC_CONST (parts.disp) - && (GET_CODE (parts.disp) != CONST - || GET_CODE (XEXP (parts.disp, 0)) != PLUS - || GET_CODE (XEXP (XEXP (parts.disp, 0), 0)) != UNSPEC - || !CONST_INT_P (XEXP (XEXP (parts.disp, 0), 1)) - || (XINT (XEXP (XEXP (parts.disp, 0), 0), 1) != UNSPEC_DTPOFF - && XINT (XEXP (XEXP (parts.disp, 0), 0), 1) != UNSPEC_NTPOFF))) - return false; - - return true; -}) - (define_predicate "vsib_mem_operator" (match_code "mem")) -(define_predicate "bnd_mem_operator" - (match_code "mem")) - ;; Return true if the rtx is known to be at least 32 bits aligned. (define_predicate "aligned_operand" (match_operand 0 "general_operand") diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md index 6d6e16efcc8..7a47f27e94e 100644 --- a/gcc/config/i386/sse.md +++ b/gcc/config/i386/sse.md @@ -13193,7 +13193,6 @@ [(set_attr "type" "ssecvt1") (set_attr "mode" "<MODE>")]) -;; scalar insns (define_expand "xop_vmfrcz<mode>2" [(set (match_operand:VF_128 0 "register_operand") (vec_merge:VF_128 @@ -13203,11 +13202,9 @@ (match_dup 3) (const_int 1)))] "TARGET_XOP" -{ - operands[3] = CONST0_RTX (<MODE>mode); -}) + "operands[3] = CONST0_RTX (<MODE>mode);") -(define_insn "*xop_vmfrcz_<mode>" +(define_insn "*xop_vmfrcz<mode>2" [(set (match_operand:VF_128 0 "register_operand" "=x") (vec_merge:VF_128 (unspec:VF_128 diff --git a/gcc/config/i386/winnt.c b/gcc/config/i386/winnt.c index 2c1677eec88..55b38d7b4af 100644 --- a/gcc/config/i386/winnt.c +++ b/gcc/config/i386/winnt.c @@ -37,6 +37,16 @@ along with GCC; see the file COPYING3. If not see #include "ggc.h" #include "target.h" #include "except.h" +#include "pointer-set.h" +#include "hash-table.h" +#include "vec.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "lto-streamer.h" @@ -488,7 +498,7 @@ i386_pe_section_type_flags (tree decl, const char *name, int reloc) flags |= SECTION_LINKONCE; /* See if we already have an entry for this section. */ - slot = htab.find_slot ((unsigned int *)name, INSERT); + slot = htab.find_slot ((const unsigned int *)name, INSERT); if (!*slot) { *slot = (unsigned int *) xmalloc (sizeof (unsigned int)); @@ -555,8 +565,9 @@ i386_pe_asm_named_section (const char *name, unsigned int flags, sets 'discard' characteristic, rather than telling linker to warn of size or content mismatch, so do the same. */ bool discard = (flags & SECTION_CODE) - || lookup_attribute ("selectany", - DECL_ATTRIBUTES (decl)); + || (TREE_CODE (decl) != IDENTIFIER_NODE + && lookup_attribute ("selectany", + DECL_ATTRIBUTES (decl))); fprintf (asm_out_file, "\t.linkonce %s\n", (discard ? "discard" : "same_size")); } diff --git a/gcc/config/i386/xopintrin.h b/gcc/config/i386/xopintrin.h index e0d148a0818..49cea8ec645 100644 --- a/gcc/config/i386/xopintrin.h +++ b/gcc/config/i386/xopintrin.h @@ -747,13 +747,17 @@ _mm_frcz_pd (__m128d __A) extern __inline __m128 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_frcz_ss (__m128 __A, __m128 __B) { - return (__m128) __builtin_ia32_vfrczss ((__v4sf)__A, (__v4sf)__B); + return (__m128) __builtin_ia32_movss ((__v4sf)__A, + (__v4sf) + __builtin_ia32_vfrczss ((__v4sf)__B)); } extern __inline __m128d __attribute__((__gnu_inline__, __always_inline__, __artificial__)) _mm_frcz_sd (__m128d __A, __m128d __B) { - return (__m128d) __builtin_ia32_vfrczsd ((__v2df)__A, (__v2df)__B); + return (__m128d) __builtin_ia32_movsd ((__v2df)__A, + (__v2df) + __builtin_ia32_vfrczsd ((__v2df)__B)); } extern __inline __m256 __attribute__((__gnu_inline__, __always_inline__, __artificial__)) diff --git a/gcc/config/ia64/hpux.h b/gcc/config/ia64/hpux.h index 517132c8e63..4fc80ee37a5 100644 --- a/gcc/config/ia64/hpux.h +++ b/gcc/config/ia64/hpux.h @@ -182,7 +182,7 @@ do { \ /* ia64 HPUX has the float and long double forms of math functions. We redefine this hook so the version from elfos.h header won't be used. */ #undef TARGET_LIBC_HAS_FUNCTION -#define TARGET_LIBC_HAS_FUNCTION default_c99_libc_has_function +#define TARGET_LIBC_HAS_FUNCTION default_libc_has_function #undef TARGET_INIT_LIBFUNCS #define TARGET_INIT_LIBFUNCS ia64_hpux_init_libfuncs diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c index 71bc666b685..df4a4b02d4c 100644 --- a/gcc/config/ia64/ia64.c +++ b/gcc/config/ia64/ia64.c @@ -53,6 +53,15 @@ along with GCC; see the file COPYING3. If not see #include "tm_p.h" #include "hash-table.h" #include "langhooks.h" +#include "pointer-set.h" +#include "vec.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "intl.h" diff --git a/gcc/config/m32c/m32c.c b/gcc/config/m32c/m32c.c index ec30b8d7f9b..a75b43fd3e6 100644 --- a/gcc/config/m32c/m32c.c +++ b/gcc/config/m32c/m32c.c @@ -48,6 +48,16 @@ #include "target-def.h" #include "tm_p.h" #include "langhooks.h" +#include "pointer-set.h" +#include "hash-table.h" +#include "vec.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "df.h" #include "tm-constrs.h" diff --git a/gcc/config/mep/mep.c b/gcc/config/mep/mep.c index 6ce6c530077..22a093e6ab7 100644 --- a/gcc/config/mep/mep.c +++ b/gcc/config/mep/mep.c @@ -51,6 +51,16 @@ along with GCC; see the file COPYING3. If not see #include "target-def.h" #include "langhooks.h" #include "df.h" +#include "pointer-set.h" +#include "hash-table.h" +#include "vec.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "opts.h" diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 0aeb35aa6d6..36ba6df7a4c 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -54,6 +54,15 @@ along with GCC; see the file COPYING3. If not see #include "common/common-target.h" #include "langhooks.h" #include "sched-int.h" +#include "pointer-set.h" +#include "vec.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "bitmap.h" diff --git a/gcc/config/mn10300/mn10300-protos.h b/gcc/config/mn10300/mn10300-protos.h index 8487064bd04..9044b73b871 100644 --- a/gcc/config/mn10300/mn10300-protos.h +++ b/gcc/config/mn10300/mn10300-protos.h @@ -32,7 +32,7 @@ extern void mn10300_print_operand (FILE *, rtx, int); extern void mn10300_print_operand_address (FILE *, rtx); extern void mn10300_print_reg_list (FILE *, int); extern enum machine_mode mn10300_select_cc_mode (enum rtx_code, rtx, rtx); -extern int mn10300_store_multiple_operation (rtx, enum machine_mode); +extern int mn10300_store_multiple_operation_p (rtx); extern int mn10300_symbolic_operand (rtx, enum machine_mode); extern void mn10300_split_cbranch (enum machine_mode, rtx, rtx); extern int mn10300_split_and_operand_count (rtx); diff --git a/gcc/config/mn10300/mn10300.c b/gcc/config/mn10300/mn10300.c index 7304e8638c7..c23f7c7c792 100644 --- a/gcc/config/mn10300/mn10300.c +++ b/gcc/config/mn10300/mn10300.c @@ -1240,8 +1240,7 @@ mn10300_expand_epilogue (void) registers it saves. Return 0 otherwise. */ int -mn10300_store_multiple_operation (rtx op, - enum machine_mode mode ATTRIBUTE_UNUSED) +mn10300_store_multiple_operation_p (rtx op) { int count; int mask; diff --git a/gcc/config/mn10300/predicates.md b/gcc/config/mn10300/predicates.md index 6ce5016bbb7..6ad0c68bcd6 100644 --- a/gcc/config/mn10300/predicates.md +++ b/gcc/config/mn10300/predicates.md @@ -67,3 +67,7 @@ (define_predicate "liw_operand" (ior (match_operand 0 "register_operand") (match_test "satisfies_constraint_O (op)"))) + +(define_predicate "mn10300_store_multiple_operation" + (and (match_code "parallel") + (match_test "mn10300_store_multiple_operation_p (op)"))) diff --git a/gcc/config/nds32/nds32.c b/gcc/config/nds32/nds32.c index 8582bbb218a..217f42eb43f 100644 --- a/gcc/config/nds32/nds32.c +++ b/gcc/config/nds32/nds32.c @@ -2471,7 +2471,7 @@ performance_cost: break; case MULT: - *total = COSTS_N_INSNS (5); + *total = COSTS_N_INSNS (1); break; case DIV: diff --git a/gcc/config/rs6000/aix.h b/gcc/config/rs6000/aix.h index a11bd57284d..1a879da49cc 100644 --- a/gcc/config/rs6000/aix.h +++ b/gcc/config/rs6000/aix.h @@ -47,6 +47,35 @@ collect has a chance to see them, so scan the object files directly. */ #define COLLECT_EXPORT_LIST +/* On AIX, initialisers specified with -binitfini are called in breadth-first + order. + e.g. if a.out depends on lib1.so, the init function for a.out is called before + the init function for lib1.so. + + To ensure global C++ constructors in linked libraries are run before global + C++ constructors from the current module, there is additional symbol scanning + logic in collect2. + + The global initialiser/finaliser functions are named __GLOBAL_AIXI_{libname} + and __GLOBAL_AIXD_{libname} and are exported from each shared library. + + collect2 will detect these symbols when they exist in shared libraries that + the current program is being linked against. All such initiliser functions + will be called prior to the constructors of the current program, and + finaliser functions called after destructors. + + Reference counting generated by collect2 will ensure that constructors are + only invoked once in the case of multiple dependencies on a library. + + -binitfini is still used in parallel to this solution. + This handles the case where a library is loaded through dlopen(), and also + handles the option -blazy. +*/ +#define COLLECT_SHARED_INIT_FUNC(STREAM, FUNC) \ + fprintf ((STREAM), "void %s() {\n\t%s();\n}\n", aix_shared_initname, (FUNC)) +#define COLLECT_SHARED_FINI_FUNC(STREAM, FUNC) \ + fprintf ((STREAM), "void %s() {\n\t%s();\n}\n", aix_shared_fininame, (FUNC)) + #if HAVE_AS_REF /* Issue assembly directives that create a reference to the given DWARF table identifier label from the current function section. This is defined to diff --git a/gcc/config/rs6000/htmintrin.h b/gcc/config/rs6000/htmintrin.h index 10f3e2e40a2..212cc92f851 100644 --- a/gcc/config/rs6000/htmintrin.h +++ b/gcc/config/rs6000/htmintrin.h @@ -99,9 +99,9 @@ typedef uintptr_t tfhar_t; #define _TEXASRU_IMPLEMENTAION_SPECIFIC(TEXASRU) \ _TEXASRU_EXTRACT_BITS(TEXASRU, 15, 1) -#define _TEXASR_INSRUCTION_FETCH_CONFLICT(TEXASR) \ +#define _TEXASR_INSTRUCTION_FETCH_CONFLICT(TEXASR) \ _TEXASR_EXTRACT_BITS(TEXASR, 16, 1) -#define _TEXASRU_INSRUCTION_FETCH_CONFLICT(TEXASRU) \ +#define _TEXASRU_INSTRUCTION_FETCH_CONFLICT(TEXASRU) \ _TEXASRU_EXTRACT_BITS(TEXASRU, 16, 1) #define _TEXASR_ABORT(TEXASR) \ diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index ffccecbccd4..00143a7ed74 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -56,6 +56,16 @@ #include "reload.h" #include "cfgloop.h" #include "sched-int.h" +#include "pointer-set.h" +#include "hash-table.h" +#include "vec.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "gimple-iterator.h" @@ -28579,10 +28589,23 @@ rs6000_xcoff_asm_named_section (const char *name, unsigned int flags, name, suffix[smclass], flags & SECTION_ENTSIZE); } +#define IN_NAMED_SECTION(DECL) \ + ((TREE_CODE (DECL) == FUNCTION_DECL || TREE_CODE (DECL) == VAR_DECL) \ + && DECL_SECTION_NAME (DECL) != NULL_TREE) + static section * rs6000_xcoff_select_section (tree decl, int reloc, - unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED) + unsigned HOST_WIDE_INT align) { + /* Place variables with alignment stricter than BIGGEST_ALIGNMENT into + named section. */ + if (align > BIGGEST_ALIGNMENT) + { + resolve_unique_section (decl, reloc, true); + if (IN_NAMED_SECTION (decl)) + return get_named_section (decl, NULL, reloc); + } + if (decl_readonly_section (decl, reloc)) { if (TREE_PUBLIC (decl)) @@ -28620,10 +28643,12 @@ rs6000_xcoff_unique_section (tree decl, int reloc ATTRIBUTE_UNUSED) { const char *name; - /* Use select_section for private and uninitialized data. */ + /* Use select_section for private data and uninitialized data with + alignment <= BIGGEST_ALIGNMENT. */ if (!TREE_PUBLIC (decl) || DECL_COMMON (decl) - || DECL_INITIAL (decl) == NULL_TREE + || (DECL_INITIAL (decl) == NULL_TREE + && DECL_ALIGN (decl) <= BIGGEST_ALIGNMENT) || DECL_INITIAL (decl) == error_mark_node || (flag_zero_initialized_in_bss && initializer_zerop (DECL_INITIAL (decl)))) @@ -30023,6 +30048,21 @@ rs6000_expand_vec_perm_const_1 (rtx target, rtx op0, rtx op1, gcc_assert (GET_MODE_NUNITS (vmode) == 2); dmode = mode_for_vector (GET_MODE_INNER (vmode), 4); + /* For little endian, swap operands and invert/swap selectors + to get the correct xxpermdi. The operand swap sets up the + inputs as a little endian array. The selectors are swapped + because they are defined to use big endian ordering. The + selectors are inverted to get the correct doublewords for + little endian ordering. */ + if (!BYTES_BIG_ENDIAN) + { + int n; + perm0 = 3 - perm0; + perm1 = 3 - perm1; + n = perm0, perm0 = perm1, perm1 = n; + x = op0, op0 = op1, op1 = x; + } + x = gen_rtx_VEC_CONCAT (dmode, op0, op1); v = gen_rtvec (2, GEN_INT (perm0), GEN_INT (perm1)); x = gen_rtx_VEC_SELECT (vmode, x, gen_rtx_PARALLEL (VOIDmode, v)); diff --git a/gcc/config/rs6000/vsx.md b/gcc/config/rs6000/vsx.md index 977ef963411..9eba6752e80 100644 --- a/gcc/config/rs6000/vsx.md +++ b/gcc/config/rs6000/vsx.md @@ -1895,7 +1895,7 @@ (set (match_operand:VSX_M2 2 "vsx_register_operand" "") (mem:VSX_M2 (plus:P (match_dup 0) (match_operand:P 3 "int_reg_operand" ""))))] - "TARGET_P8_FUSION" + "TARGET_VSX && TARGET_P8_FUSION" "li %0,%1\t\t\t# vector load fusion\;lx<VSX_M2:VSm>x %x2,%0,%3" [(set_attr "length" "8") (set_attr "type" "vecload")]) @@ -1906,7 +1906,7 @@ (set (match_operand:VSX_M2 2 "vsx_register_operand" "") (mem:VSX_M2 (plus:P (match_operand:P 3 "int_reg_operand" "") (match_dup 0))))] - "TARGET_P8_FUSION" + "TARGET_VSX && TARGET_P8_FUSION" "li %0,%1\t\t\t# vector load fusion\;lx<VSX_M2:VSm>x %x2,%0,%3" [(set_attr "length" "8") (set_attr "type" "vecload")]) diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index 62d162ab087..a435b2dcbdc 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -52,6 +52,16 @@ along with GCC; see the file COPYING3. If not see #include "debug.h" #include "langhooks.h" #include "optabs.h" +#include "pointer-set.h" +#include "hash-table.h" +#include "vec.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "df.h" diff --git a/gcc/config/score/score.h b/gcc/config/score/score.h index 8235df54743..5ab78752c39 100644 --- a/gcc/config/score/score.h +++ b/gcc/config/score/score.h @@ -395,9 +395,6 @@ enum reg_class /* The class value for index registers. */ #define INDEX_REG_CLASS NO_REGS -extern enum reg_class score_char_to_class[256]; -#define REG_CLASS_FROM_LETTER(C) score_char_to_class[(unsigned char) (C)] - /* Addressing modes, and classification of registers for them. */ #define REGNO_MODE_OK_FOR_BASE_P(REGNO, MODE) \ score_regno_mode_ok_for_base_p (REGNO, 1) diff --git a/gcc/config/sh/constraints.md b/gcc/config/sh/constraints.md index 59bf6b5addf..df7823764e5 100644 --- a/gcc/config/sh/constraints.md +++ b/gcc/config/sh/constraints.md @@ -221,6 +221,7 @@ (define_constraint "Q" "A pc relative load operand." (and (match_code "mem") + (match_test "GET_MODE (op) != QImode") (match_test "IS_PC_RELATIVE_LOAD_ADDR_P (XEXP (op, 0))"))) (define_constraint "Bsc" @@ -295,13 +296,15 @@ (define_memory_constraint "Sdd" "A memory reference that uses displacement addressing." - (and (match_test "MEM_P (op) && GET_CODE (XEXP (op, 0)) == PLUS") + (and (match_code "mem") + (match_test "GET_CODE (XEXP (op, 0)) == PLUS") (match_test "REG_P (XEXP (XEXP (op, 0), 0))") (match_test "CONST_INT_P (XEXP (XEXP (op, 0), 1))"))) (define_memory_constraint "Snd" "A memory reference that excludes displacement addressing." - (match_test "! satisfies_constraint_Sdd (op)")) + (and (match_code "mem") + (match_test "! satisfies_constraint_Sdd (op)"))) (define_memory_constraint "Sbv" "A memory reference, as used in SH2A bclr.b, bset.b, etc." diff --git a/gcc/config/sh/predicates.md b/gcc/config/sh/predicates.md index 2643481a827..2aff6ad9e84 100644 --- a/gcc/config/sh/predicates.md +++ b/gcc/config/sh/predicates.md @@ -421,6 +421,12 @@ XEXP (XEXP (op, 0), 1), TARGET_SH2A, true)"))) +;; Returns true if OP is a displacement address that can fit into a +;; 16 bit (non-SH2A) memory load / store insn. +(define_predicate "short_displacement_mem_operand" + (match_test "sh_disp_addr_displacement (op) + <= sh_max_mov_insn_displacement (GET_MODE (op), false)")) + ;; Returns 1 if the operand can be used in an SH2A movu.{b|w} insn. (define_predicate "zero_extend_movu_operand" (and (match_operand 0 "displacement_mem_operand") @@ -445,6 +451,11 @@ if (t_reg_operand (op, mode)) return 0; + /* Disallow PC relative QImode loads, since these is no insn to do that + and an imm8 load should be used instead. */ + if (IS_PC_RELATIVE_LOAD_ADDR_P (op) && GET_MODE (op) == QImode) + return false; + if (MEM_P (op)) { rtx inside = XEXP (op, 0); diff --git a/gcc/config/sh/sh-protos.h b/gcc/config/sh/sh-protos.h index 11877e58b52..fade1b4c387 100644 --- a/gcc/config/sh/sh-protos.h +++ b/gcc/config/sh/sh-protos.h @@ -162,6 +162,8 @@ extern bool sh_vector_mode_supported_p (enum machine_mode); extern bool sh_cfun_trap_exit_p (void); extern rtx sh_find_equiv_gbr_addr (rtx cur_insn, rtx mem); extern int sh_eval_treg_value (rtx op); +extern HOST_WIDE_INT sh_disp_addr_displacement (rtx mem_op); +extern int sh_max_mov_insn_displacement (machine_mode mode, bool consider_sh2a); /* Result value of sh_find_set_of_reg. */ struct set_of_reg diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index 6981ab6229a..3e907b24a9d 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -52,6 +52,14 @@ along with GCC; see the file COPYING3. If not see #include "sched-int.h" #include "params.h" #include "ggc.h" +#include "pointer-set.h" +#include "hash-table.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "cfgloop.h" @@ -308,9 +316,7 @@ static rtx sh_trampoline_adjust_address (rtx); static void sh_conditional_register_usage (void); static bool sh_legitimate_constant_p (enum machine_mode, rtx); static int mov_insn_size (enum machine_mode, bool); -static int max_mov_insn_displacement (enum machine_mode, bool); static int mov_insn_alignment_mask (enum machine_mode, bool); -static HOST_WIDE_INT disp_addr_displacement (rtx); static bool sequence_insn_p (rtx); static void sh_canonicalize_comparison (int *, rtx *, rtx *, bool); static void sh_canonicalize_comparison (enum rtx_code&, rtx&, rtx&, @@ -3574,8 +3580,8 @@ mov_insn_size (enum machine_mode mode, bool consider_sh2a) /* Determine the maximum possible displacement for a move insn for the specified mode. */ -static int -max_mov_insn_displacement (enum machine_mode mode, bool consider_sh2a) +int +sh_max_mov_insn_displacement (machine_mode mode, bool consider_sh2a) { /* The 4 byte displacement move insns are the same as the 2 byte versions but take a 12 bit displacement. All we need to do is to @@ -3611,8 +3617,8 @@ mov_insn_alignment_mask (enum machine_mode mode, bool consider_sh2a) } /* Return the displacement value of a displacement address. */ -static inline HOST_WIDE_INT -disp_addr_displacement (rtx x) +HOST_WIDE_INT +sh_disp_addr_displacement (rtx x) { gcc_assert (satisfies_constraint_Sdd (x)); return INTVAL (XEXP (XEXP (x, 0), 1)); @@ -3649,12 +3655,12 @@ sh_address_cost (rtx x, enum machine_mode mode, HImode and QImode loads/stores with displacement put pressure on R0 which will most likely require another reg copy. Thus account a higher cost for that. */ - if (offset > 0 && offset <= max_mov_insn_displacement (mode, false)) + if (offset > 0 && offset <= sh_max_mov_insn_displacement (mode, false)) return (mode == HImode || mode == QImode) ? 2 : 1; /* The displacement would fit into a 4 byte move insn (SH2A). */ if (TARGET_SH2A - && offset > 0 && offset <= max_mov_insn_displacement (mode, true)) + && offset > 0 && offset <= sh_max_mov_insn_displacement (mode, true)) return 2; /* The displacement is probably out of range and will require extra @@ -10167,7 +10173,7 @@ sh_legitimate_index_p (enum machine_mode mode, rtx op, bool consider_sh2a, else { const HOST_WIDE_INT offset = INTVAL (op); - const int max_disp = max_mov_insn_displacement (mode, consider_sh2a); + const int max_disp = sh_max_mov_insn_displacement (mode, consider_sh2a); const int align_mask = mov_insn_alignment_mask (mode, consider_sh2a); /* If the mode does not support any displacement always return false. @@ -10353,7 +10359,7 @@ sh_find_mov_disp_adjust (enum machine_mode mode, HOST_WIDE_INT offset) effectively disable the small displacement insns. */ const int mode_sz = GET_MODE_SIZE (mode); const int mov_insn_sz = mov_insn_size (mode, false); - const int max_disp = max_mov_insn_displacement (mode, false); + const int max_disp = sh_max_mov_insn_displacement (mode, false); const int max_disp_next = max_disp + mov_insn_sz; HOST_WIDE_INT align_modifier = offset > 127 ? mov_insn_sz : 0; HOST_WIDE_INT offset_adjust; @@ -13113,7 +13119,8 @@ sh_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i, the insns must have the appropriate alternatives. */ if ((mode == QImode || mode == HImode) && rclass != R0_REGS && satisfies_constraint_Sdd (x) - && disp_addr_displacement (x) <= max_mov_insn_displacement (mode, false)) + && sh_disp_addr_displacement (x) + <= sh_max_mov_insn_displacement (mode, false)) return R0_REGS; /* When reload is trying to address a QImode or HImode subreg on the stack, diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md index 8cc9195c988..f79157996d6 100644 --- a/gcc/config/sh/sh.md +++ b/gcc/config/sh/sh.md @@ -6065,7 +6065,7 @@ label: (define_peephole2 [(set (match_operand:SI 0 "arith_reg_dest" "") (zero_extend:SI (match_operand 1 "displacement_mem_operand" ""))) - (set (match_operand 2 "general_operand" "") + (set (match_operand 2 "nonimmediate_operand" "") (match_operand 3 "arith_reg_operand" ""))] "TARGET_SH2A && REGNO (operands[0]) == REGNO (operands[3]) @@ -6993,34 +6993,9 @@ label: prepare_move_operands (operands, QImode); }) -;; If movqi_reg_reg is specified as an alternative of movqi, movqi will be -;; selected to copy QImode regs. If one of them happens to be allocated -;; on the stack, reload will stick to movqi insn and generate wrong -;; displacement addressing because of the generic m alternatives. -;; With the movqi_reg_reg being specified before movqi it will be initially -;; picked to load/store regs. If the regs regs are on the stack reload -;; try other insns and not stick to movqi_reg_reg, unless there were spilled -;; pseudos in which case 'm' constraints pertain. -;; The same applies to the movhi variants. -;; -;; Notice, that T bit is not allowed as a mov src operand here. This is to -;; avoid things like (set (reg:QI) (subreg:QI (reg:SI T_REG) 0)), which -;; introduces zero extensions after T bit stores and redundant reg copies. -;; -;; FIXME: We can't use 'arith_reg_operand' (which disallows T_REG) as a -;; predicate for the mov src operand because reload will have trouble -;; reloading MAC subregs otherwise. For that probably special patterns -;; would be required. -(define_insn "*mov<mode>_reg_reg" - [(set (match_operand:QIHI 0 "arith_reg_dest" "=r,m,*z") - (match_operand:QIHI 1 "register_operand" "r,*z,m"))] - "TARGET_SH1 && !t_reg_operand (operands[1], VOIDmode)" - "@ - mov %1,%0 - mov.<bw> %1,%0 - mov.<bw> %1,%0" - [(set_attr "type" "move,store,load")]) - +;; Specifying the displacement addressing load / store patterns separately +;; before the generic movqi / movhi pattern allows controlling the order +;; in which load / store insns are selected in a more fine grained way. ;; FIXME: The non-SH2A and SH2A variants should be combined by adding ;; "enabled" attribute as it is done in other targets. (define_insn "*mov<mode>_store_mem_disp04" @@ -7070,38 +7045,44 @@ label: [(set_attr "type" "load") (set_attr "length" "2,2,4")]) -;; The m constraints basically allow any kind of addresses to be used with any -;; source/target register as the other operand. This is not true for -;; displacement addressing modes on anything but SH2A. That's why the -;; specialized load/store insns are specified above. -(define_insn "*movqi" - [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,m,r,l") - (match_operand:QI 1 "general_movsrc_operand" "i,m,r,l,r"))] +;; The order of the constraint alternatives is important here. +;; Q/r has to come first, otherwise PC relative loads might wrongly get +;; placed into delay slots. Since there is no QImode PC relative load, the +;; Q constraint and general_movsrc_operand will reject it for QImode. +;; The Snd alternatives should come before Sdd in order to avoid a preference +;; of using r0 als the register operand for addressing modes other than +;; displacement addressing. +;; The Sdd alternatives allow only r0 as register operand, even though on +;; SH2A any register could be allowed by switching to a 32 bit insn. +;; Generally sticking to the r0 is preferrable, since it generates smaller +;; code. Obvious r0 reloads can then be eliminated with a peephole on SH2A. +(define_insn "*mov<mode>" + [(set (match_operand:QIHI 0 "general_movdst_operand" + "=r,r,r,Snd,r, Sdd,z, r,l") + (match_operand:QIHI 1 "general_movsrc_operand" + "Q,r,i,r, Snd,z, Sdd,l,r"))] "TARGET_SH1 - && (arith_reg_operand (operands[0], QImode) - || arith_reg_operand (operands[1], QImode))" + && (arith_reg_operand (operands[0], <MODE>mode) + || arith_reg_operand (operands[1], <MODE>mode))" "@ + mov.<bw> %1,%0 mov %1,%0 - mov.b %1,%0 - mov.b %1,%0 - sts %1,%0 - lds %1,%0" - [(set_attr "type" "movi8,load,store,prget,prset")]) - -(define_insn "*movhi" - [(set (match_operand:HI 0 "general_movdst_operand" "=r,r,r,m,r,l") - (match_operand:HI 1 "general_movsrc_operand" "Q,i,m,r,l,r"))] - "TARGET_SH1 - && (arith_reg_operand (operands[0], HImode) - || arith_reg_operand (operands[1], HImode))" - "@ - mov.w %1,%0 mov %1,%0 - mov.w %1,%0 - mov.w %1,%0 + mov.<bw> %1,%0 + mov.<bw> %1,%0 + mov.<bw> %1,%0 + mov.<bw> %1,%0 sts %1,%0 lds %1,%0" - [(set_attr "type" "pcload,movi8,load,store,prget,prset")]) + [(set_attr "type" "pcload,move,movi8,store,load,store,load,prget,prset") + (set (attr "length") + (cond [(and (match_operand 0 "displacement_mem_operand") + (not (match_operand 0 "short_displacement_mem_operand"))) + (const_int 4) + (and (match_operand 1 "displacement_mem_operand") + (not (match_operand 1 "short_displacement_mem_operand"))) + (const_int 4)] + (const_int 2)))]) (define_insn "*movqi_media" [(set (match_operand:QI 0 "general_movdst_operand" "=r,r,r,m") @@ -8801,7 +8782,7 @@ label: (label_ref (match_operand 1 "" "")) (pc))) (set (match_operand:SI 0 "arith_reg_dest" "=r") - (plus (match_dup 2) (const_int -1))) + (plus:SI (match_dup 2) (const_int -1))) (clobber (reg:SI T_REG))] "TARGET_SH2" "#" @@ -13700,13 +13681,13 @@ label: ;; ------------------------------------------------------------------------- ;; This matches cases where the bit in a memory location is set. (define_peephole2 - [(set (match_operand:SI 0 "arith_reg_operand" "r,r") - (sign_extend:SI (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv"))) + [(set (match_operand:SI 0 "register_operand") + (sign_extend:SI (match_operand:QI 1 "bitwise_memory_operand"))) (set (match_dup 0) (ior:SI (match_dup 0) - (match_operand:SI 2 "const_int_operand" "Pso,Pso"))) + (match_operand:SI 2 "const_int_operand"))) (set (match_dup 1) - (match_operand 3 "arith_reg_operand" "r,r"))] + (match_operand 3 "arith_reg_operand"))] "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_Pso (operands[2]) && REGNO (operands[0]) == REGNO (operands[3])" @@ -13716,13 +13697,13 @@ label: ;; This matches cases where the bit in a memory location is cleared. (define_peephole2 - [(set (match_operand:SI 0 "arith_reg_operand" "r,r") - (sign_extend:SI (match_operand:QI 1 "bitwise_memory_operand" "Sbw,Sbv"))) + [(set (match_operand:SI 0 "register_operand") + (sign_extend:SI (match_operand:QI 1 "bitwise_memory_operand"))) (set (match_dup 0) (and:SI (match_dup 0) - (match_operand:SI 2 "const_int_operand" "Psz,Psz"))) + (match_operand:SI 2 "const_int_operand"))) (set (match_dup 1) - (match_operand 3 "arith_reg_operand" "r,r"))] + (match_operand 3 "arith_reg_operand"))] "TARGET_SH2A && TARGET_BITOPS && satisfies_constraint_Psz (operands[2]) && REGNO (operands[0]) == REGNO (operands[3])" diff --git a/gcc/config/sh/sh_optimize_sett_clrt.cc b/gcc/config/sh/sh_optimize_sett_clrt.cc index abb75672e86..fc58bf9efdf 100644 --- a/gcc/config/sh/sh_optimize_sett_clrt.cc +++ b/gcc/config/sh/sh_optimize_sett_clrt.cc @@ -29,6 +29,7 @@ along with GCC; see the file COPYING3. If not see #include "target.h" #include <vector> +#include <algorithm> /* This pass tries to eliminate unnecessary sett or clrt instructions in cases @@ -87,16 +88,15 @@ private: struct ccreg_value { // The insn at which the ccreg value was determined. + // Might be NULL_RTX if e.g. an unknown value is recorded for an + // empty basic block. rtx insn; // The basic block where the insn was discovered. - // Notice that the CFG might be invalid at late RTL stages and - // BLOCK_FOR_INSN might return null. Thus the basic block are recorded - // here while traversing them. basic_block bb; - // The value of ccreg. If NULL_RTX, the value is not known, e.g. if the - // ccreg is clobbered. + // The value of ccreg. If NULL_RTX, the exact value is not known, but + // the ccreg is changed in some way (e.g. clobbered). rtx value; }; @@ -113,7 +113,7 @@ private: // start insn. void find_last_ccreg_values (rtx start_insn, basic_block bb, std::vector<ccreg_value>& values_out, - basic_block prev_visited_bb = NULL) const; + std::vector<basic_block>& prev_visited_bb) const; // Given a cbranch insn, its basic block and another basic block, determine // the value to which the ccreg will be set after jumping/falling through to @@ -199,6 +199,10 @@ sh_optimize_sett_clrt::execute (void) std::vector<ccreg_value> ccreg_values; ccreg_values.reserve (32); + // Something for recording visited basic blocks to avoid infinite recursion. + std::vector<basic_block> visited_bbs; + visited_bbs.reserve (32); + // Look for insns that set the ccreg to a constant value and see if it can // be optimized. basic_block bb; @@ -221,7 +225,9 @@ sh_optimize_sett_clrt::execute (void) log_msg ("\n"); ccreg_values.clear (); - find_last_ccreg_values (PREV_INSN (i), bb, ccreg_values); + visited_bbs.clear (); + find_last_ccreg_values (PREV_INSN (i), bb, ccreg_values, + visited_bbs); log_msg ("number of ccreg values collected: %u\n", (unsigned int)ccreg_values.size ()); @@ -307,12 +313,16 @@ void sh_optimize_sett_clrt ::find_last_ccreg_values (rtx start_insn, basic_block bb, std::vector<ccreg_value>& values_out, - basic_block prev_visited_bb) const + std::vector<basic_block>& prev_visited_bb) const { - if (start_insn == NULL_RTX) - return; - - log_msg ("looking for ccreg values in [bb %d]\n", bb->index); + // FIXME: For larger CFGs this will unnecessarily re-visit basic blocks. + // Once a basic block has been visited, the result should be stored in + // some container so that it can be looked up quickly eliminating the + // re-visits. + log_msg ("looking for ccreg values in [bb %d] ", bb->index); + if (!prev_visited_bb.empty ()) + log_msg ("(prev visited [bb %d])", prev_visited_bb.back ()->index); + log_msg ("\n"); for (rtx i = start_insn; i != NULL_RTX && i != PREV_INSN (BB_HEAD (bb)); i = PREV_INSN (i)) @@ -341,7 +351,7 @@ sh_optimize_sett_clrt return; } - if (any_condjump_p (i) && onlyjump_p (i) && prev_visited_bb != NULL) + if (any_condjump_p (i) && onlyjump_p (i) && !prev_visited_bb.empty ()) { // For a conditional branch the ccreg value will be a known constant // of either 0 or STORE_FLAG_VALUE after branching/falling through @@ -353,10 +363,11 @@ sh_optimize_sett_clrt ccreg_value v; v.insn = i; v.bb = bb; - v.value = GEN_INT (sh_cbranch_ccreg_value (i, bb, prev_visited_bb)); + v.value = GEN_INT (sh_cbranch_ccreg_value (i, bb, + prev_visited_bb.back ())); log_msg (" branches to [bb %d] with ccreg value ", - prev_visited_bb->index); + prev_visited_bb.back ()->index); log_rtx (v.value); log_msg ("\n"); @@ -370,26 +381,35 @@ sh_optimize_sett_clrt // In this case, check the predecessor basic blocks. unsigned int pred_bb_count = 0; - // If the current basic block is the same as the previous one, it's a loop. - // Don't try to recurse again, as this will result in an infinite loop. - if (bb != prev_visited_bb) - for (edge_iterator ei = ei_start (bb->preds); !ei_end_p (ei); ei_next (&ei)) - { - basic_block pred_bb = ei_edge (ei)->src; - if (pred_bb->index == ENTRY_BLOCK) - continue; + // If the current basic block is not in the stack of previously visited + // basic blocks yet, we can recursively check the predecessor basic blocks. + // Otherwise we have a loop in the CFG and recursing again will result in + // an infinite loop. + if (std::find (prev_visited_bb.rbegin (), prev_visited_bb.rend (), bb) + == prev_visited_bb.rend ()) + { + prev_visited_bb.push_back (bb); - pred_bb_count += 1; - find_last_ccreg_values (BB_END (pred_bb), pred_bb, values_out, bb); - } + for (edge_iterator ei = ei_start (bb->preds); !ei_end_p (ei); + ei_next (&ei)) + { + basic_block pred_bb = ei_edge (ei)->src; + pred_bb_count += 1; + find_last_ccreg_values (BB_END (pred_bb), pred_bb, values_out, + prev_visited_bb); + } + + prev_visited_bb.pop_back (); + } + else + log_msg ("loop detected for [bb %d]\n", bb->index); log_msg ("[bb %d] pred_bb_count = %u\n", bb->index, pred_bb_count); - // If here, we've walked up all the predecessor basic blocks without finding - // anything setcc related. Add an entry for the last insn of the current - // basic block with the ccreg value being set to unknown (NULL_RTX). if (pred_bb_count == 0) { + // If we haven't checked a single predecessor basic block, the current + // basic block is probably a leaf block and we don't know the ccreg value. log_msg ("unknown ccreg value for [bb %d]\n", bb->index); ccreg_value v; diff --git a/gcc/config/sol2.h b/gcc/config/sol2.h index 749e16830e3..abd7342aef5 100644 --- a/gcc/config/sol2.h +++ b/gcc/config/sol2.h @@ -163,6 +163,9 @@ along with GCC; see the file COPYING3. If not see #undef LINK_ARCH_SPEC #define LINK_ARCH_SPEC LINK_ARCH32_SPEC +/* C++11 programs need -lrt for nanosleep. */ +#define TIME_LIBRARY "rt" + #ifndef USE_GLD /* With Sun ld, -rdynamic is a no-op. */ #define RDYNAMIC_SPEC "" diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c index 410c8eeee03..abca70a47b0 100644 --- a/gcc/config/sparc/sparc.c +++ b/gcc/config/sparc/sparc.c @@ -50,6 +50,16 @@ along with GCC; see the file COPYING3. If not see #include "target.h" #include "target-def.h" #include "common/common-target.h" +#include "pointer-set.h" +#include "hash-table.h" +#include "vec.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "langhooks.h" diff --git a/gcc/config/spu/spu.c b/gcc/config/spu/spu.c index 315f1b3617f..5b8aef179c8 100644 --- a/gcc/config/spu/spu.c +++ b/gcc/config/spu/spu.c @@ -49,6 +49,14 @@ #include "sched-int.h" #include "params.h" #include "machmode.h" +#include "pointer-set.h" +#include "hash-table.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "tm-constrs.h" diff --git a/gcc/config/stormy16/stormy16.c b/gcc/config/stormy16/stormy16.c index d5a1fc6ad86..941595e1cca 100644 --- a/gcc/config/stormy16/stormy16.c +++ b/gcc/config/stormy16/stormy16.c @@ -47,11 +47,21 @@ #include "target-def.h" #include "tm_p.h" #include "langhooks.h" +#include "pointer-set.h" +#include "hash-table.h" +#include "vec.h" +#include "ggc.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "df.h" #include "reload.h" -#include "ggc.h" static rtx emit_addhi3_postreload (rtx, rtx, rtx); static void xstormy16_asm_out_constructor (rtx, int); diff --git a/gcc/config/tilegx/tilegx.c b/gcc/config/tilegx/tilegx.c index 809beefa305..c2f9e070a29 100644 --- a/gcc/config/tilegx/tilegx.c +++ b/gcc/config/tilegx/tilegx.c @@ -40,6 +40,17 @@ #include "dwarf2.h" #include "timevar.h" #include "tree.h" +#include "pointer-set.h" +#include "hash-table.h" +#include "vec.h" +#include "ggc.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "stringpool.h" #include "stor-layout.h" diff --git a/gcc/config/tilepro/tilepro.c b/gcc/config/tilepro/tilepro.c index 9fe1b104f57..31bc4908965 100644 --- a/gcc/config/tilepro/tilepro.c +++ b/gcc/config/tilepro/tilepro.c @@ -41,6 +41,17 @@ #include "dwarf2.h" #include "timevar.h" #include "tree.h" +#include "pointer-set.h" +#include "hash-table.h" +#include "vec.h" +#include "ggc.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "stringpool.h" #include "stor-layout.h" diff --git a/gcc/config/xtensa/xtensa.c b/gcc/config/xtensa/xtensa.c index 9e6bb23818f..4564290acb2 100644 --- a/gcc/config/xtensa/xtensa.c +++ b/gcc/config/xtensa/xtensa.c @@ -50,6 +50,14 @@ along with GCC; see the file COPYING3. If not see #include "target.h" #include "target-def.h" #include "langhooks.h" +#include "pointer-set.h" +#include "hash-table.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "df.h" diff --git a/gcc/configure b/gcc/configure index c9bbd653e52..fdf0cd0819b 100755 --- a/gcc/configure +++ b/gcc/configure @@ -682,6 +682,8 @@ gcc_cv_readelf gcc_cv_objdump ORIGINAL_NM_FOR_TARGET gcc_cv_nm +ORIGINAL_LD_GOLD_FOR_TARGET +ORIGINAL_LD_BFD_FOR_TARGET ORIGINAL_LD_FOR_TARGET ORIGINAL_PLUGIN_LD_FOR_TARGET gcc_cv_ld @@ -911,6 +913,8 @@ enable_static with_pic enable_fast_install enable_libtool_lock +enable_ld +enable_gold with_plugin_ld enable_gnu_indirect_function enable_initfini_array @@ -1624,6 +1628,8 @@ Optional Features: --enable-fast-install[=PKGS] optimize for fast installation [default=yes] --disable-libtool-lock avoid locking (might break parallel builds) + --enable-ld[=ARG] build ld [ARG={default,yes,no}] + --enable-gold[=ARG] build gold [ARG={default,yes,no}] --enable-gnu-indirect-function enable the use of the @gnu_indirect_function to glibc systems @@ -17913,7 +17919,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 17916 "configure" +#line 17922 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -18019,7 +18025,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 18022 "configure" +#line 18028 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -21397,6 +21403,39 @@ $as_echo "$gcc_cv_as" >&6; } in_tree_gas=no fi +default_ld= +# Check whether --enable-ld was given. +if test "${enable_ld+set}" = set; then : + enableval=$enable_ld; case "${enableval}" in + no) + default_ld=ld.gold + ;; + esac +fi + + +# Check whether --enable-gold was given. +if test "${enable_gold+set}" = set; then : + enableval=$enable_gold; case "${enableval}" in + default) + install_gold_as_default=yes + ;; + yes) + if test x${default_ld} != x; then + install_gold_as_default=yes + fi + ;; + no) + ;; + *) + as_fn_error "invalid --enable-gold argument" "$LINENO" 5 + ;; + esac +else + install_gold_as_default=no +fi + + # Identify the linker which will work hand-in-glove with the newly # built GCC, so that we can examine its features. This is the linker # which will be driven by the driver program. @@ -21407,6 +21446,7 @@ fi gcc_cv_gld_major_version= gcc_cv_gld_minor_version= gcc_cv_ld_gld_srcdir=`echo $srcdir | sed -e 's,/gcc$,,'`/ld +gcc_cv_ld_gold_srcdir=`echo $srcdir | sed -e 's,/gcc$,,'`/gold gcc_cv_ld_bfd_srcdir=`echo $srcdir | sed -e 's,/gcc$,,'`/bfd if test "${gcc_cv_ld+set}" = set; then : @@ -21415,6 +21455,11 @@ else if test -x "$DEFAULT_LINKER"; then gcc_cv_ld="$DEFAULT_LINKER" +elif test $install_gold_as_default = yes \ + && test -f $gcc_cv_ld_gold_srcdir/configure.ac \ + && test -f ../gold/Makefile \ + && test x$build = x$host; then + gcc_cv_ld=../gold/ld-new$build_exeext elif test -f $gcc_cv_ld_gld_srcdir/configure.in \ && test -f ../ld/Makefile \ && test x$build = x$host; then @@ -21544,12 +21589,20 @@ $as_echo "newly built ld" >&6; } esac gcc_cv_gld_major_version=`expr "$gcc_cv_gld_version" : "VERSION=\([0-9]*\)"` gcc_cv_gld_minor_version=`expr "$gcc_cv_gld_version" : "VERSION=[0-9]*\.\([0-9]*\)"` + ORIGINAL_LD_BFD_FOR_TARGET=../ld/ld-new$build_exeext + ORIGINAL_LD_GOLD_FOR_TARGET=../gold/ld-new$build_exeext else { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld" >&5 $as_echo "$gcc_cv_ld" >&6; } in_tree_ld=no + gcc_cvs_ld_program=`dirname $gcc_cv_ld`/`basename $gcc_cv_ld $host_exeext` + ORIGINAL_LD_BFD_FOR_TARGET=${gcc_cvs_ld_program}.bfd$host_exeext + ORIGINAL_LD_GOLD_FOR_TARGET=${gcc_cvs_ld_program}.gold$host_exeext fi + + + # Figure out what nm we will be using. gcc_cv_binutils_srcdir=`echo $srcdir | sed -e 's,/gcc$,,'`/binutils if test "${gcc_cv_nm+set}" = set; then : diff --git a/gcc/configure.ac b/gcc/configure.ac index 5935a6ede94..91a22d58cf7 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -2016,6 +2016,34 @@ else in_tree_gas=no fi +default_ld= +AC_ARG_ENABLE(ld, +[[ --enable-ld[=ARG] build ld [ARG={default,yes,no}]]], +[case "${enableval}" in + no) + default_ld=ld.gold + ;; + esac]) + +AC_ARG_ENABLE(gold, +[[ --enable-gold[=ARG] build gold [ARG={default,yes,no}]]], +[case "${enableval}" in + default) + install_gold_as_default=yes + ;; + yes) + if test x${default_ld} != x; then + install_gold_as_default=yes + fi + ;; + no) + ;; + *) + AC_MSG_ERROR([invalid --enable-gold argument]) + ;; + esac], +[install_gold_as_default=no]) + # Identify the linker which will work hand-in-glove with the newly # built GCC, so that we can examine its features. This is the linker # which will be driven by the driver program. @@ -2026,11 +2054,17 @@ fi gcc_cv_gld_major_version= gcc_cv_gld_minor_version= gcc_cv_ld_gld_srcdir=`echo $srcdir | sed -e 's,/gcc$,,'`/ld +gcc_cv_ld_gold_srcdir=`echo $srcdir | sed -e 's,/gcc$,,'`/gold gcc_cv_ld_bfd_srcdir=`echo $srcdir | sed -e 's,/gcc$,,'`/bfd AS_VAR_SET_IF(gcc_cv_ld,, [ if test -x "$DEFAULT_LINKER"; then gcc_cv_ld="$DEFAULT_LINKER" +elif test $install_gold_as_default = yes \ + && test -f $gcc_cv_ld_gold_srcdir/configure.ac \ + && test -f ../gold/Makefile \ + && test x$build = x$host; then + gcc_cv_ld=../gold/ld-new$build_exeext elif test -f $gcc_cv_ld_gld_srcdir/configure.in \ && test -f ../ld/Makefile \ && test x$build = x$host; then @@ -2112,11 +2146,19 @@ changequote(,)dnl gcc_cv_gld_major_version=`expr "$gcc_cv_gld_version" : "VERSION=\([0-9]*\)"` gcc_cv_gld_minor_version=`expr "$gcc_cv_gld_version" : "VERSION=[0-9]*\.\([0-9]*\)"` changequote([,])dnl + ORIGINAL_LD_BFD_FOR_TARGET=../ld/ld-new$build_exeext + ORIGINAL_LD_GOLD_FOR_TARGET=../gold/ld-new$build_exeext else AC_MSG_RESULT($gcc_cv_ld) in_tree_ld=no + gcc_cvs_ld_program=`dirname $gcc_cv_ld`/`basename $gcc_cv_ld $host_exeext` + ORIGINAL_LD_BFD_FOR_TARGET=${gcc_cvs_ld_program}.bfd$host_exeext + ORIGINAL_LD_GOLD_FOR_TARGET=${gcc_cvs_ld_program}.gold$host_exeext fi +AC_SUBST(ORIGINAL_LD_BFD_FOR_TARGET) +AC_SUBST(ORIGINAL_LD_GOLD_FOR_TARGET) + # Figure out what nm we will be using. gcc_cv_binutils_srcdir=`echo $srcdir | sed -e 's,/gcc$,,'`/binutils AS_VAR_SET_IF(gcc_cv_nm,, [ diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 5e769c30eec..e2fc2a2d125 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,214 @@ +2013-11-29 Marek Polacek <polacek@redhat.com> + + PR sanitizer/59331 + * decl.c (compute_array_index_type): Don't build COMPOUND_EXPR for + instrumentation. + +2013-11-28 Jakub Jelinek <jakub@redhat.com> + + PR c++/59297 + * semantics.c (finish_omp_atomic): Call finish_expr_stmt + rather than add_stmt. + +2013-11-28 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + * g++spec.c (TIMELIB): Define. + (WITHLIBC, SKIPOPT): Adjust values. + (lang_specific_driver): Add TIME_LIBRARY if not passed explicitly. + +2013-11-28 Jakub Jelinek <jakub@redhat.com> + + PR c/59310 + * parser.c (cp_parser_omp_target): Call keep_next_level only + if flag_openmp. + +2013-11-27 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/58647 + * semantics.c (cxx_eval_constant_expression, [COMPONENT_REF]): + Handle function COMPONENT_REFs. + +2013-11-27 Aldy Hernandez <aldyh@redhat.com> + Jakub Jelinek <jakub@redhat.com> + + * semantics.c (finish_omp_clauses): For #pragma omp declare simd + linear clause step call maybe_constant_value. + +2013-11-27 Tom de Vries <tom@codesourcery.com> + Marc Glisse <marc.glisse@inria.fr> + + PR c++/59032 + * typeck.c (cp_build_unary_op): Allow vector increment and decrement. + +2013-11-27 Tom de Vries <tom@codesourcery.com> + Marc Glisse <marc.glisse@inria.fr> + + PR middle-end/59037 + * semantics.c (cxx_fold_indirect_ref): Don't create out-of-bounds + BIT_FIELD_REF. + +2013-11-26 Jakub Jelinek <jakub@redhat.com> + + PR c++/58874 + * parser.c (cp_parser_late_parsing_for_member): For OpenMP UDRs + pass 2 instead of 0 to finish_function. + +2013-11-26 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/58700 + * decl.c (grokdeclarator): Don't try to pass declarator->id_loc + to build_lang_decl_loc when declarator is null. + +2013-11-26 Paolo Carlini <paolo.carlini@oracle.com> + + * cvt.c (cp_convert_and_check): Avoid calling cp_convert + unnecessarily. + +2013-11-25 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/54485 + * decl.c (duplicate_decls): Enforce 8.3.6/6 about default arguments + for member functions of class templates. + +2013-11-25 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/58607 + * semantics.c (check_constexpr_ctor_body): Check for BIND_EXPR_VARS. + +2013-11-25 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/58810 + * decl.c (grokdeclarator): Don't handle qualified free functions here, + leave the diagnostic to grokfndecl. + +2013-11-25 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/59080 + * pt.c (unify): Don't call unify_array_domain with a NULL_TREE + third argument. + + PR c++/59096 + * pt.c (apply_late_template_attributes): Check that TREE_VALUE + isn't NULL_TREE in the attribute_takes_identifier_p case. + +2013-11-25 Adam Butcher <adam@jessamine.co.uk> + + PR c++/59112 + PR c++/59113 + * parser.c (cp_parser_parameter_declaration_clause): Disallow implicit + function templates in local functions unless defining a lambda. + +2013-11-23 Easwaran Raman <eraman@google.com> + + PR c++/59031 + * call.c (build_new_method_call_1): Comnpare function context + with BASELINK_BINFO type rather than instance type before + marking the call with LOOKUP_NONVIRTUAL. + +2013-11-23 Jason Merrill <jason@redhat.com> + + PR c++/58868 + * init.c (build_aggr_init): Don't clobber the type of init + if we got an INIT_EXPR back from build_vec_init. + (build_vec_init): Do digest_init on trivial initialization. + +2013-11-23 Alexander Ivchenko <alexander.ivchenko@intel.com> + + PR c++/58525 + * call.c (build_operator_new_call): Add flag_exceptions check. + * decl.c (compute_array_index_type): Ditto. + * init.c (build_new_1): Ditto. + (build_vec_init): Ditto. + +2013-11-22 Jakub Jelinek <jakub@redhat.com> + + * cp-gimplify.c: Include target.h and c-family/c-ubsan.h. + (cp_ubsan_maybe_instrument_return): New function. + (cp_genericize): Call it if -fsanitize=return. + + * decl2.c: Include asan.h. + (one_static_initialization_or_destruction): If -fsanitize=address, + init is non-NULL and guard is NULL, set + vnode->dynamically_initialized. + (do_static_initialization_or_destruction): Call + __asan_{before,after}_dynamic_init around the static initialization. + +2013-11-22 Andrew MacLeod <amacleod@redhat.com> + + * class.c: Add required include files from gimple.h. + * cp-gimplify.c: Likewise + * decl2.c: Likewise + * init.c: Likewise + * optimize.c: Likewise + * pt.c: Likewise + * semantics.c: Likewise + * tree.c: Likewise + * typeck.c: Likewise + * vtable-class-hierarchy.c: Likewise + +2013-11-22 David Malcolm <dmalcolm@redhat.com> + + * call.c (build_integral_nontype_arg_conv): Remove use of + EXPR_LOC_OR_HERE macro. + (convert_like_real): Likewise. + (convert_arg_to_ellipsis): Likewise. + (build_cxx_call): Likewise. + (perform_implicit_conversion_flags): Likewise. + (initialize_reference): Likewise. + * cvt.c (cp_convert_to_pointer): Likewise. + (convert_to_reference): Likewise. + (ocp_convert): Likewise. + (convert_to_void): Likewise. + * decl.c (pop_label): Update comment. + (pop_switch): Remove use of EXPR_LOC_OR_HERE macro. + (check_tag_decl): Remove use of in_system_header macro. + (make_rtl_for_nonlocal_decl): Remove use of input_filename + macro. + (compute_array_index_type): Remove use of in_system_header + macro. + (grokdeclarator): Likewise. + * error.c (dump_global_iord): Remove use of input_filename + macro. + (location_of): Remove use of EXPR_LOC_OR_HERE macro. + (maybe_warn_cpp0x): Remove use of in_system_header macro. + * init.c (build_new_1): Remove use of EXPR_LOC_OR_HERE macro. + * lex.c (handle_pragma_interface): Remove use of input_filename + macro. + (handle_pragma_implementation): Likewise. + (cxx_make_type): Likewise. + (in_main_input_context): Likewise. + * name-lookup.c (push_binding_level): Remove use of + input_line macro. + (leave_scope): Likewise. + (resume_scope): Likewise. + * parser.c (cp_parser_unqualified_id): Remove use of + in_system_header macro. + (cp_parser_cast_expression): Likewise. + (cp_parser_declaration_seq_opt): Likewise. + (cp_parser_enumerator_list): Likewise. + (cp_parser_parameter_declaration_clause): Likewise. + (cp_parser_exception_specification_opt): Likewise. + * pt.c (unify_arg_conversion): Remove use of EXPR_LOC_OR_HERE + macro. + (convert_nontype_argument): Likewise. + (push_tinst_level): Remove use of in_system_header macro. + (tsubst_copy_and_build): Remove use of EXPR_LOC_OR_HERE + macros. + (do_decl_instantiation): Remove use of in_system_header macro. + (do_type_instantiation): Likewise. + * semantics.c (finish_call_expr): Remove use of EXPR_LOC_OR_HERE + macro. + (begin_class_definition): Remove use of input_filename macro. + (cxx_eval_call_expression): Remove use of EXPR_LOC_OR_HERE + macro. + (cxx_eval_constant_expression): Likewise. + (potential_constant_expression_1): Likewise. + * typeck.c (decay_conversion): Likewise. + (rationalize_conditional_expr): Likewise. + (build_x_compound_expr_from_list): Likewise. + (convert_for_assignment): Likewise. + * typeck2.c (check_narrowing): Likewise. + 2013-11-22 Trevor Saunders <tsaunders@mozilla.com> * parser.c, semantics.c: Change some local variables from vec to diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 00ebed4320e..ec99995ddd8 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -3688,7 +3688,7 @@ build_integral_nontype_arg_conv (tree type, tree expr, tsubst_flags_t complain) conversion *conv; void *p; tree t; - location_t loc = EXPR_LOC_OR_HERE (expr); + location_t loc = EXPR_LOC_OR_LOC (expr, input_location); if (error_operand_p (expr)) return error_mark_node; @@ -3957,7 +3957,7 @@ build_operator_new_call (tree fnname, vec<tree, va_gc> **args, if (size_check != NULL_TREE) { tree errval = TYPE_MAX_VALUE (sizetype); - if (cxx_dialect >= cxx11) + if (cxx_dialect >= cxx11 && flag_exceptions) errval = throw_bad_array_new_length (); *size = fold_build3 (COND_EXPR, sizetype, size_check, original_size, errval); @@ -5851,7 +5851,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, tree totype = convs->type; diagnostic_t diag_kind; int flags; - location_t loc = EXPR_LOC_OR_HERE (expr); + location_t loc = EXPR_LOC_OR_LOC (expr, input_location); if (convs->bad_p && !(complain & tf_error)) return error_mark_node; @@ -6264,7 +6264,7 @@ tree convert_arg_to_ellipsis (tree arg, tsubst_flags_t complain) { tree arg_type; - location_t loc = EXPR_LOC_OR_HERE (arg); + location_t loc = EXPR_LOC_OR_LOC (arg, input_location); /* [expr.call] @@ -7167,7 +7167,7 @@ build_cxx_call (tree fn, int nargs, tree *argarray, int optimize_sav; /* Remember roughly where this call is. */ - location_t loc = EXPR_LOC_OR_HERE (fn); + location_t loc = EXPR_LOC_OR_LOC (fn, input_location); fn = build_call_a (fn, nargs, argarray); SET_EXPR_LOCATION (fn, loc); @@ -7513,7 +7513,7 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args, struct z_candidate *candidates = 0, *cand; tree explicit_targs = NULL_TREE; tree basetype = NULL_TREE; - tree access_binfo; + tree access_binfo, binfo; tree optype; tree first_mem_arg = NULL_TREE; tree name; @@ -7552,6 +7552,7 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args, if (!conversion_path) conversion_path = BASELINK_BINFO (fns); access_binfo = BASELINK_ACCESS_BINFO (fns); + binfo = BASELINK_BINFO (fns); optype = BASELINK_OPTYPE (fns); fns = BASELINK_FUNCTIONS (fns); if (TREE_CODE (fns) == TEMPLATE_ID_EXPR) @@ -7798,13 +7799,13 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args, { /* Optimize away vtable lookup if we know that this function can't be overridden. We need to check if - the context and the instance type are the same, + the context and the type where we found fn are the same, actually FN might be defined in a different class type because of a using-declaration. In this case, we do not want to perform a non-virtual call. */ if (DECL_VINDEX (fn) && ! (flags & LOOKUP_NONVIRTUAL) && same_type_ignoring_top_level_qualifiers_p - (DECL_CONTEXT (fn), TREE_TYPE (instance)) + (DECL_CONTEXT (fn), BINFO_TYPE (binfo)) && resolves_to_fixed_type_p (instance, 0)) flags |= LOOKUP_NONVIRTUAL; if (explicit_targs) @@ -8978,7 +8979,7 @@ perform_implicit_conversion_flags (tree type, tree expr, { conversion *conv; void *p; - location_t loc = EXPR_LOC_OR_HERE (expr); + location_t loc = EXPR_LOC_OR_LOC (expr, input_location); if (error_operand_p (expr)) return error_mark_node; @@ -9294,7 +9295,7 @@ initialize_reference (tree type, tree expr, { conversion *conv; void *p; - location_t loc = EXPR_LOC_OR_HERE (expr); + location_t loc = EXPR_LOC_OR_LOC (expr, input_location); if (type == error_mark_node || error_operand_p (expr)) return error_mark_node; diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 027d235e83d..6b2efbf43cb 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -29,7 +29,8 @@ along with GCC; see the file COPYING3. If not see #include "stringpool.h" #include "stor-layout.h" #include "attribs.h" -#include "gimple.h" +#include "pointer-set.h" +#include "hash-table.h" #include "cp-tree.h" #include "flags.h" #include "toplev.h" @@ -38,9 +39,6 @@ along with GCC; see the file COPYING3. If not see #include "cgraph.h" #include "dumpfile.h" #include "splay-tree.h" -#include "pointer-set.h" -#include "hash-table.h" -#include "gimple.h" #include "gimplify.h" #include "wide-int.h" diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c index e2629464dd9..b1270a187f1 100644 --- a/gcc/cp/cp-gimplify.c +++ b/gcc/cp/cp-gimplify.c @@ -28,12 +28,19 @@ along with GCC; see the file COPYING3. If not see #include "cp-tree.h" #include "c-family/c-common.h" #include "tree-iterator.h" +#include "pointer-set.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "hashtab.h" -#include "pointer-set.h" #include "flags.h" #include "splay-tree.h" +#include "target.h" +#include "c-family/c-ubsan.h" /* Forward declarations. */ @@ -1173,6 +1180,59 @@ cp_genericize_tree (tree* t_p) wtd.bind_expr_stack.release (); } +/* If a function that should end with a return in non-void + function doesn't obviously end with return, add ubsan + instrmentation code to verify it at runtime. */ + +static void +cp_ubsan_maybe_instrument_return (tree fndecl) +{ + if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl))) + || DECL_CONSTRUCTOR_P (fndecl) + || DECL_DESTRUCTOR_P (fndecl) + || !targetm.warn_func_return (fndecl)) + return; + + tree t = DECL_SAVED_TREE (fndecl); + while (t) + { + switch (TREE_CODE (t)) + { + case BIND_EXPR: + t = BIND_EXPR_BODY (t); + continue; + case TRY_FINALLY_EXPR: + t = TREE_OPERAND (t, 0); + continue; + case STATEMENT_LIST: + { + tree_stmt_iterator i = tsi_last (t); + if (!tsi_end_p (i)) + { + t = tsi_stmt (i); + continue; + } + } + break; + case RETURN_EXPR: + return; + default: + break; + } + break; + } + if (t == NULL_TREE) + return; + t = DECL_SAVED_TREE (fndecl); + if (TREE_CODE (t) == BIND_EXPR + && TREE_CODE (BIND_EXPR_BODY (t)) == STATEMENT_LIST) + { + tree_stmt_iterator i = tsi_last (BIND_EXPR_BODY (t)); + t = ubsan_instrument_return (DECL_SOURCE_LOCATION (fndecl)); + tsi_link_after (&i, t, TSI_NEW_STMT); + } +} + void cp_genericize (tree fndecl) { @@ -1235,6 +1295,9 @@ cp_genericize (tree fndecl) walk_tree's hash functionality. */ cp_genericize_tree (&DECL_SAVED_TREE (fndecl)); + if (flag_sanitize & SANITIZE_RETURN) + cp_ubsan_maybe_instrument_return (fndecl); + /* Do everything else. */ c_genericize (fndecl); diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 4e26bd501b4..1fc4b59d846 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -359,7 +359,8 @@ struct GTY(()) tree_overload { /* Returns true iff NODE is a BASELINK. */ #define BASELINK_P(NODE) \ (TREE_CODE (NODE) == BASELINK) -/* The BINFO indicating the base from which the BASELINK_FUNCTIONS came. */ +/* The BINFO indicating the base in which lookup found the + BASELINK_FUNCTIONS. */ #define BASELINK_BINFO(NODE) \ (((struct tree_baselink*) BASELINK_CHECK (NODE))->binfo) /* The functions referred to by the BASELINK; either a FUNCTION_DECL, diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index 6d0e34156ff..1ba07876683 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -79,7 +79,7 @@ cp_convert_to_pointer (tree type, tree expr, tsubst_flags_t complain) tree intype = TREE_TYPE (expr); enum tree_code form; tree rval; - location_t loc = EXPR_LOC_OR_HERE (expr); + location_t loc = EXPR_LOC_OR_LOC (expr, input_location); if (intype == error_mark_node) return error_mark_node; @@ -414,7 +414,7 @@ convert_to_reference (tree reftype, tree expr, int convtype, tree rval = NULL_TREE; tree rval_as_conversion = NULL_TREE; bool can_convert_intype_to_type; - location_t loc = EXPR_LOC_OR_HERE (expr); + location_t loc = EXPR_LOC_OR_LOC (expr, input_location); if (TREE_CODE (type) == FUNCTION_TYPE && TREE_TYPE (expr) == unknown_type_node) @@ -629,7 +629,8 @@ cp_convert_and_check (tree type, tree expr, tsubst_flags_t complain) { tree folded = maybe_constant_value (expr); tree stripped = folded; - tree folded_result = cp_convert (type, folded, complain); + tree folded_result + = folded != expr ? cp_convert (type, folded, complain) : result; /* maybe_constant_value wraps an INTEGER_CST with TREE_OVERFLOW in a NOP_EXPR so that it isn't TREE_CONSTANT anymore. */ @@ -655,7 +656,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags, enum tree_code code = TREE_CODE (type); const char *invalid_conv_diag; tree e1; - location_t loc = EXPR_LOC_OR_HERE (expr); + location_t loc = EXPR_LOC_OR_LOC (expr, input_location); if (error_operand_p (e) || type == error_mark_node) return error_mark_node; @@ -911,7 +912,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags, tree convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain) { - location_t loc = EXPR_LOC_OR_HERE (expr); + location_t loc = EXPR_LOC_OR_LOC (expr, input_location); if (expr == error_mark_node || TREE_TYPE (expr) == error_mark_node) diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index babfc8893b8..8e0546e0bef 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -377,7 +377,8 @@ pop_label (tree label, tree old_value) location_t location; error ("label %q+D used but not defined", label); - location = input_location; /* FIXME want (input_filename, (line)0) */ + location = input_location; + /* FIXME want (LOCATION_FILE (input_location), (line)0) */ /* Avoid crashing later. */ define_label (location, DECL_NAME (label)); } @@ -1704,25 +1705,47 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) if (TREE_CODE (TREE_TYPE (newdecl)) == METHOD_TYPE) t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2); - for (; t1 && t1 != void_list_node; - t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2), i++) - if (TREE_PURPOSE (t1) && TREE_PURPOSE (t2)) - { - if (1 == simple_cst_equal (TREE_PURPOSE (t1), - TREE_PURPOSE (t2))) + if (TREE_CODE (TREE_TYPE (newdecl)) == METHOD_TYPE + && CLASSTYPE_TEMPLATE_INFO (CP_DECL_CONTEXT (newdecl))) + { + /* C++11 8.3.6/6. + Default arguments for a member function of a class template + shall be specified on the initial declaration of the member + function within the class template. */ + for (; t2 && t2 != void_list_node; t2 = TREE_CHAIN (t2)) + if (TREE_PURPOSE (t2)) { - permerror (input_location, "default argument given for parameter %d of %q#D", - i, newdecl); - permerror (input_location, "after previous specification in %q+#D", olddecl); + permerror (input_location, + "redeclaration of %q#D may not have default " + "arguments", newdecl); + break; } - else + } + else + { + for (; t1 && t1 != void_list_node; + t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2), i++) + if (TREE_PURPOSE (t1) && TREE_PURPOSE (t2)) { - error ("default argument given for parameter %d of %q#D", - i, newdecl); - error ("after previous specification in %q+#D", - olddecl); + if (1 == simple_cst_equal (TREE_PURPOSE (t1), + TREE_PURPOSE (t2))) + { + permerror (input_location, + "default argument given for parameter %d " + "of %q#D", i, newdecl); + permerror (input_location, + "after previous specification in %q+#D", + olddecl); + } + else + { + error ("default argument given for parameter %d " + "of %q#D", i, newdecl); + error ("after previous specification in %q+#D", + olddecl); + } } - } + } } } @@ -3093,7 +3116,7 @@ pop_switch (void) location_t switch_location; /* Emit warnings as needed. */ - switch_location = EXPR_LOC_OR_HERE (cs->switch_stmt); + switch_location = EXPR_LOC_OR_LOC (cs->switch_stmt, input_location); if (!processing_template_decl) c_do_switch_warnings (cs->cases, switch_location, SWITCH_STMT_TYPE (cs->switch_stmt), @@ -4242,7 +4265,7 @@ check_tag_decl (cp_decl_specifier_seq *declspecs, error ("multiple types in one declaration"); else if (declspecs->redefined_builtin_type) { - if (!in_system_header) + if (!in_system_header_at (input_location)) permerror (declspecs->locations[ds_redefined_builtin_type_spec], "redeclaration of C++ built-in type %qT", declspecs->redefined_builtin_type); @@ -4293,7 +4316,8 @@ check_tag_decl (cp_decl_specifier_seq *declspecs, /* Anonymous unions are objects, so they can have specifiers. */; SET_ANON_AGGR_TYPE_P (declared_type); - if (TREE_CODE (declared_type) != UNION_TYPE && !in_system_header) + if (TREE_CODE (declared_type) != UNION_TYPE + && !in_system_header_at (input_location)) pedwarn (input_location, OPT_Wpedantic, "ISO C++ prohibits anonymous structs"); } @@ -5847,7 +5871,7 @@ make_rtl_for_nonlocal_decl (tree decl, tree init, const char* asmspec) /* We try to defer namespace-scope static constants so that they are not emitted into the object file unnecessarily. */ - filename = input_filename; + filename = LOCATION_FILE (input_location); if (!DECL_VIRTUAL_P (decl) && TREE_READONLY (decl) && DECL_INITIAL (decl) != NULL_TREE @@ -8310,7 +8334,7 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain) indicated by the state of complain), so that another substitution can be found. */ return error_mark_node; - else if (in_system_header) + else if (in_system_header_at (input_location)) /* Allow them in system headers because glibc uses them. */; else if (name) pedwarn (input_location, OPT_Wpedantic, "ISO C++ forbids zero-size array %qD", name); @@ -8392,7 +8416,7 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain) stabilize_vla_size (itype); - if (cxx_dialect >= cxx1y) + if (cxx_dialect >= cxx1y && flag_exceptions) { /* If the VLA bound is larger than half the address space, or less than zero, throw std::bad_array_length. */ @@ -8411,8 +8435,7 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain) LE_EXPR rather than LT_EXPR. */ tree t = fold_build2 (PLUS_EXPR, TREE_TYPE (itype), itype, build_one_cst (TREE_TYPE (itype))); - t = fold_build2 (COMPOUND_EXPR, TREE_TYPE (t), - ubsan_instrument_vla (input_location, t), t); + t = ubsan_instrument_vla (input_location, t); finish_expr_stmt (t); } } @@ -9097,7 +9120,7 @@ grokdeclarator (const cp_declarator *declarator, if (type_was_error_mark_node) /* We've already issued an error, don't complain more. */; - else if (in_system_header || flag_ms_extensions) + else if (in_system_header_at (input_location) || flag_ms_extensions) /* Allow it, sigh. */; else if (! is_main) permerror (input_location, "ISO C++ forbids declaration of %qs with no type", name); @@ -9120,7 +9143,7 @@ grokdeclarator (const cp_declarator *declarator, error ("%<__int128%> is not supported by this target"); explicit_int128 = false; } - else if (pedantic && ! in_system_header) + else if (pedantic && ! in_system_header_at (input_location)) pedwarn (input_location, OPT_Wpedantic, "ISO C++ does not support %<__int128%> for %qs", name); } @@ -10255,21 +10278,6 @@ grokdeclarator (const cp_declarator *declarator, if (decl_context != TYPENAME) { - /* A cv-qualifier-seq shall only be part of the function type - for a non-static member function. A ref-qualifier shall only - .... /same as above/ [dcl.fct] */ - if ((type_memfn_quals (type) != TYPE_UNQUALIFIED - || type_memfn_rqual (type) != REF_QUAL_NONE) - && (current_class_type == NULL_TREE || staticp) ) - { - error (staticp - ? G_("qualified function types cannot be used to " - "declare static member functions") - : G_("qualified function types cannot be used to " - "declare free functions")); - type = TYPE_MAIN_VARIANT (type); - } - /* The qualifiers on the function type become the qualifiers on the non-static member function. */ memfn_quals |= type_memfn_quals (type); @@ -10629,7 +10637,9 @@ grokdeclarator (const cp_declarator *declarator, { /* C++ allows static class members. All other work for this is done by grokfield. */ - decl = build_lang_decl_loc (declarator->id_loc, + decl = build_lang_decl_loc (declarator + ? declarator->id_loc + : input_location, VAR_DECL, unqualified_id, type); set_linkage_for_static_data_member (decl); /* Even if there is an in-class initialization, DECL diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 93c75cbf4d6..0e37a5d246c 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -36,7 +36,7 @@ along with GCC; see the file COPYING3. If not see #include "attribs.h" #include "stor-layout.h" #include "calls.h" -#include "gimple.h" +#include "pointer-set.h" #include "flags.h" #include "cp-tree.h" #include "decl.h" @@ -51,10 +51,10 @@ along with GCC; see the file COPYING3. If not see #include "c-family/c-pragma.h" #include "dumpfile.h" #include "intl.h" -#include "pointer-set.h" #include "splay-tree.h" #include "langhooks.h" #include "c-family/c-ada-spec.h" +#include "asan.h" extern cpp_reader *parse_in; @@ -3462,7 +3462,15 @@ one_static_initialization_or_destruction (tree decl, tree init, bool initp) if (initp) { if (init) - finish_expr_stmt (init); + { + finish_expr_stmt (init); + if (flag_sanitize & SANITIZE_ADDRESS) + { + struct varpool_node *vnode = varpool_get_node (decl); + if (vnode) + vnode->dynamically_initialized = 1; + } + } /* If we're using __cxa_atexit, register a function that calls the destructor for the object. */ @@ -3504,6 +3512,16 @@ do_static_initialization_or_destruction (tree vars, bool initp) tf_warning_or_error); finish_if_stmt_cond (cond, init_if_stmt); + /* To make sure dynamic construction doesn't access globals from other + compilation units where they might not be yet constructed, for + -fsanitize=address insert __asan_before_dynamic_init call that + prevents access to either all global variables that need construction + in other compilation units, or at least those that haven't been + initialized yet. Variables that need dynamic construction in + the current compilation unit are kept accessible. */ + if (flag_sanitize & SANITIZE_ADDRESS) + finish_expr_stmt (asan_dynamic_init_call (/*after_p=*/false)); + node = vars; do { tree decl = TREE_VALUE (node); @@ -3552,6 +3570,11 @@ do_static_initialization_or_destruction (tree vars, bool initp) } while (node); + /* Revert what __asan_before_dynamic_init did by calling + __asan_after_dynamic_init. */ + if (flag_sanitize & SANITIZE_ADDRESS) + finish_expr_stmt (asan_dynamic_init_call (/*after_p=*/true)); + /* Finish up the init/destruct if-stmt body. */ finish_then_clause (init_if_stmt); finish_if_stmt (init_if_stmt); diff --git a/gcc/cp/error.c b/gcc/cp/error.c index 5481523868d..72aa936c129 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -924,7 +924,7 @@ dump_global_iord (cxx_pretty_printer *pp, tree t) else gcc_unreachable (); - pp_printf (pp, p, input_filename); + pp_printf (pp, p, LOCATION_FILE (input_location)); } static void @@ -2804,7 +2804,7 @@ location_of (tree t) if (DECL_P (t)) return DECL_SOURCE_LOCATION (t); - return EXPR_LOC_OR_HERE (t); + return EXPR_LOC_OR_LOC (t, input_location); } /* Now the interfaces from error et al to dump_type et al. Each takes an @@ -3463,7 +3463,7 @@ cp_printer (pretty_printer *pp, text_info *text, const char *spec, void maybe_warn_cpp0x (cpp0x_warn_str str) { - if ((cxx_dialect == cxx98) && !in_system_header) + if ((cxx_dialect == cxx98) && !in_system_header_at (input_location)) /* We really want to suppress this warning in system headers, because libstdc++ uses variadic templates even when we aren't in C++0x mode. */ diff --git a/gcc/cp/g++spec.c b/gcc/cp/g++spec.c index b896eead001..93f94602c92 100644 --- a/gcc/cp/g++spec.c +++ b/gcc/cp/g++spec.c @@ -28,10 +28,12 @@ along with GCC; see the file COPYING3. If not see #define LANGSPEC (1<<1) /* This bit is set if they did `-lm' or `-lmath'. */ #define MATHLIB (1<<2) +/* This bit is set if they did `-lrt' or equivalent. */ +#define TIMELIB (1<<3) /* This bit is set if they did `-lc'. */ -#define WITHLIBC (1<<3) +#define WITHLIBC (1<<4) /* Skip this option. */ -#define SKIPOPT (1<<4) +#define SKIPOPT (1<<5) #ifndef MATH_LIBRARY #define MATH_LIBRARY "m" @@ -40,6 +42,10 @@ along with GCC; see the file COPYING3. If not see #define MATH_LIBRARY_PROFILE MATH_LIBRARY #endif +#ifndef TIME_LIBRARY +#define TIME_LIBRARY "" +#endif + #ifndef LIBSTDCXX #define LIBSTDCXX "stdc++" #endif @@ -83,16 +89,22 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options, /* "-lm" or "-lmath" if it appears on the command line. */ const struct cl_decoded_option *saw_math = NULL; + /* "-lrt" or eqivalent if it appears on the command line. */ + const struct cl_decoded_option *saw_time = NULL; + /* "-lc" if it appears on the command line. */ const struct cl_decoded_option *saw_libc = NULL; /* An array used to flag each argument that needs a bit set for - LANGSPEC, MATHLIB, or WITHLIBC. */ + LANGSPEC, MATHLIB, TIMELIB, or WITHLIBC. */ int *args; /* By default, we throw on the math library if we have one. */ int need_math = (MATH_LIBRARY[0] != '\0'); + /* By default, we throw on the time library if we have one. */ + int need_time = (TIME_LIBRARY[0] != '\0'); + /* True if we saw -static. */ int static_link = 0; @@ -136,6 +148,11 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options, args[i] |= MATHLIB; need_math = 0; } + else if (strcmp (arg, TIME_LIBRARY) == 0) + { + args[i] |= TIMELIB; + need_time = 0; + } else if (strcmp (arg, "c") == 0) args[i] |= WITHLIBC; else @@ -268,6 +285,12 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options, saw_math = &decoded_options[i]; } + if (!saw_time && (args[i] & TIMELIB) && library > 0) + { + --j; + saw_time = &decoded_options[i]; + } + if (!saw_libc && (args[i] & WITHLIBC) && library > 0) { --j; @@ -352,6 +375,15 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options, added_libraries++; j++; } + if (saw_time) + new_decoded_options[j++] = *saw_time; + else if (library > 0 && need_time) + { + generate_option (OPT_l, TIME_LIBRARY, 1, CL_DRIVER, + &new_decoded_options[j]); + added_libraries++; + j++; + } if (saw_libc) new_decoded_options[j++] = *saw_libc; if (shared_libgcc && !static_link) diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 7b6f4e28e19..86b690349d2 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -30,7 +30,6 @@ along with GCC; see the file COPYING3. If not see #include "cp-tree.h" #include "flags.h" #include "target.h" -#include "gimple.h" #include "gimplify.h" #include "wide-int.h" @@ -1509,7 +1508,8 @@ build_aggr_init (tree exp, tree init, int flags, tsubst_flags_t complain) TREE_READONLY (exp) = was_const; TREE_THIS_VOLATILE (exp) = was_volatile; TREE_TYPE (exp) = type; - if (init) + /* Restore the type of init unless it was used directly. */ + if (init && TREE_CODE (stmt_expr) != INIT_EXPR) TREE_TYPE (init) = itype; return stmt_expr; } @@ -2319,7 +2319,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts, { if (complain & tf_error) { - error_at (EXPR_LOC_OR_HERE (inner_nelts), + error_at (EXPR_LOC_OR_LOC (inner_nelts, input_location), "array size in operator new must be constant"); cxx_constant_value(inner_nelts); } @@ -2347,7 +2347,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts, && !TREE_CONSTANT (maybe_constant_value (outer_nelts))) { if (complain & tf_warning_or_error) - pedwarn(EXPR_LOC_OR_HERE (outer_nelts), OPT_Wvla, + pedwarn(EXPR_LOC_OR_LOC (outer_nelts, input_location), OPT_Wvla, "ISO C++ does not support variable-length array types"); else return error_mark_node; @@ -2527,7 +2527,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts, } /* Perform the overflow check. */ tree errval = TYPE_MAX_VALUE (sizetype); - if (cxx_dialect >= cxx11) + if (cxx_dialect >= cxx11 && flag_exceptions) errval = throw_bad_array_new_length (); if (outer_nelts_check != NULL_TREE) size = fold_build3 (COND_EXPR, sizetype, outer_nelts_check, @@ -3397,7 +3397,8 @@ build_vec_init (tree base, tree maxindex, tree init, is big enough for all the initializers. */ if (init && TREE_CODE (init) == CONSTRUCTOR && CONSTRUCTOR_NELTS (init) > 0 - && !TREE_CONSTANT (maxindex)) + && !TREE_CONSTANT (maxindex) + && flag_exceptions) length_check = fold_build2 (LT_EXPR, boolean_type_node, maxindex, size_int (CONSTRUCTOR_NELTS (init) - 1)); @@ -3419,6 +3420,8 @@ build_vec_init (tree base, tree maxindex, tree init, brace-enclosed initializers. In this case, digest_init and store_constructor will handle the semantics for us. */ + if (BRACE_ENCLOSED_INITIALIZER_P (init)) + init = digest_init (atype, init, complain); stmt_expr = build2 (INIT_EXPR, atype, base, init); if (length_check) stmt_expr = build3 (COND_EXPR, atype, length_check, diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index 5d8a313f38b..2d517a4c7fe 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -352,18 +352,18 @@ handle_pragma_interface (cpp_reader* /*dfile*/) if (fname == error_mark_node) return; else if (fname == 0) - filename = lbasename (input_filename); + filename = lbasename (LOCATION_FILE (input_location)); else filename = TREE_STRING_POINTER (fname); - finfo = get_fileinfo (input_filename); + finfo = get_fileinfo (LOCATION_FILE (input_location)); if (impl_file_chain == 0) { /* If this is zero at this point, then we are auto-implementing. */ if (main_input_filename == 0) - main_input_filename = input_filename; + main_input_filename = LOCATION_FILE (input_location); } finfo->interface_only = interface_strcmp (filename); @@ -397,7 +397,7 @@ handle_pragma_implementation (cpp_reader* /*dfile*/) if (main_input_filename) filename = main_input_filename; else - filename = input_filename; + filename = LOCATION_FILE (input_location); filename = lbasename (filename); } else @@ -683,7 +683,8 @@ cxx_make_type (enum tree_code code) /* Set up some flags that give proper default behavior. */ if (RECORD_OR_UNION_CODE_P (code)) { - struct c_fileinfo *finfo = get_fileinfo (input_filename); + struct c_fileinfo *finfo = \ + get_fileinfo (LOCATION_FILE (input_location)); SET_CLASSTYPE_INTERFACE_UNKNOWN_X (t, finfo->interface_unknown); CLASSTYPE_INTERFACE_ONLY (t) = finfo->interface_only; } @@ -711,5 +712,5 @@ in_main_input_context (void) return filename_cmp (main_input_filename, LOCATION_FILE (tl->locus)) == 0; else - return filename_cmp (main_input_filename, input_filename) == 0; + return filename_cmp (main_input_filename, LOCATION_FILE (input_location)) == 0; } diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index d0c024a120f..f527638e713 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -1504,7 +1504,8 @@ push_binding_level (cp_binding_level *scope) { scope->binding_depth = binding_depth; indent (binding_depth); - cp_binding_level_debug (scope, input_line, "push"); + cp_binding_level_debug (scope, LOCATION_LINE (input_location), + "push"); binding_depth++; } } @@ -1590,7 +1591,8 @@ leave_scope (void) if (ENABLE_SCOPE_CHECKING) { indent (--binding_depth); - cp_binding_level_debug (scope, input_line, "leave"); + cp_binding_level_debug (scope, LOCATION_LINE (input_location), + "leave"); } /* Move one nesting level up. */ @@ -1639,7 +1641,7 @@ resume_scope (cp_binding_level* b) { b->binding_depth = binding_depth; indent (binding_depth); - cp_binding_level_debug (b, input_line, "resume"); + cp_binding_level_debug (b, LOCATION_LINE (input_location), "resume"); binding_depth++; } } diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c index b8df1347c33..f1b09bfd55e 100644 --- a/gcc/cp/optimize.c +++ b/gcc/cp/optimize.c @@ -35,7 +35,7 @@ along with GCC; see the file COPYING3. If not see #include "langhooks.h" #include "diagnostic-core.h" #include "dumpfile.h" -#include "gimple.h" +#include "pointer-set.h" #include "tree-iterator.h" #include "cgraph.h" diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index bc86697793c..bd4ead74dc8 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -5088,7 +5088,8 @@ cp_parser_unqualified_id (cp_parser* parser, { /* 17.6.3.3.5 */ const char *name = UDLIT_OP_SUFFIX (id); - if (name[0] != '_' && !in_system_header && declarator_p) + if (name[0] != '_' && !in_system_header_at (input_location) + && declarator_p) warning (0, "literal operator suffixes not preceded by %<_%>" " are reserved for future standardization"); } @@ -7686,7 +7687,7 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p, /* Warn about old-style casts, if so requested. */ if (warn_old_style_cast - && !in_system_header + && !in_system_header_at (input_location) && !VOID_TYPE_P (type) && current_lang_name != lang_name_c) warning (OPT_Wold_style_cast, "use of old-style cast"); @@ -10765,7 +10766,7 @@ cp_parser_declaration_seq_opt (cp_parser* parser) /* A declaration consisting of a single semicolon is invalid. Allow it unless we're being pedantic. */ cp_lexer_consume_token (parser->lexer); - if (!in_system_header) + if (!in_system_header_at (input_location)) pedwarn (input_location, OPT_Wpedantic, "extra %<;%>"); continue; } @@ -15527,7 +15528,7 @@ cp_parser_enumerator_list (cp_parser* parser, tree type) /* If the next token is a `}', there is a trailing comma. */ if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE)) { - if (cxx_dialect < cxx11 && !in_system_header) + if (cxx_dialect < cxx11 && !in_system_header_at (input_location)) pedwarn (input_location, OPT_Wpedantic, "comma at end of enumerator list"); break; @@ -18041,7 +18042,9 @@ cp_parser_parameter_declaration_clause (cp_parser* parser) (void) cleanup; if (!processing_specialization) - parser->auto_is_implicit_function_template_parm_p = true; + if (!current_function_decl + || (current_class_type && LAMBDA_TYPE_P (current_class_type))) + parser->auto_is_implicit_function_template_parm_p = true; /* Peek at the next token. */ token = cp_lexer_peek_token (parser->lexer); @@ -18056,7 +18059,8 @@ cp_parser_parameter_declaration_clause (cp_parser* parser) /* There are no parameters. */ { #ifndef NO_IMPLICIT_EXTERN_C - if (in_system_header && current_class_type == NULL + if (in_system_header_at (input_location) + && current_class_type == NULL && current_lang_name == lang_name_c) return NULL_TREE; else @@ -20793,7 +20797,7 @@ cp_parser_exception_specification_opt (cp_parser* parser) #if 0 /* Enable this once a lot of code has transitioned to noexcept? */ - if (cxx_dialect >= cxx11 && !in_system_header) + if (cxx_dialect >= cxx11 && !in_system_header_at (input_location)) warning (OPT_Wdeprecated, "dynamic exception specifications are " "deprecated in C++0x; use %<noexcept%> instead"); #endif @@ -23271,7 +23275,7 @@ cp_parser_late_parsing_for_member (cp_parser* parser, tree member_function) { parser->lexer->in_pragma = true; cp_parser_omp_declare_reduction_exprs (member_function, parser); - finish_function (0); + finish_function (/*inline*/2); cp_check_omp_declare_reduction (member_function); } else @@ -29964,10 +29968,10 @@ cp_parser_omp_target (cp_parser *parser, cp_token *pragma_tok, cp_lexer_consume_token (parser->lexer); strcpy (p_name, "#pragma omp target"); - keep_next_level (true); if (!flag_openmp) /* flag_openmp_simd */ return cp_parser_omp_teams (parser, pragma_tok, p_name, OMP_TARGET_CLAUSE_MASK, cclauses); + keep_next_level (true); tree sb = begin_omp_structured_block (); unsigned save = cp_parser_begin_omp_structured_block (parser); tree ret = cp_parser_omp_teams (parser, pragma_tok, p_name, diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index bbf8f550f3e..b58c7556e2e 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -46,7 +46,6 @@ along with GCC; see the file COPYING3. If not see #include "timevar.h" #include "tree-iterator.h" #include "type-utils.h" -#include "gimple.h" #include "gimplify.h" /* The type of functions taking a tree, and some additional data, and @@ -5437,7 +5436,7 @@ unify_arg_conversion (bool explain_p, tree to_type, tree from_type, tree arg) { if (explain_p) - inform (EXPR_LOC_OR_HERE (arg), + inform (EXPR_LOC_OR_LOC (arg, input_location), " cannot convert %qE (type %qT) to type %qT", arg, from_type, to_type); return 1; @@ -5677,7 +5676,7 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain) return NULL_TREE; expr = cxx_constant_value (expr); if (errorcount > errs || warningcount + werrorcount > warns) - inform (EXPR_LOC_OR_HERE (expr), + inform (EXPR_LOC_OR_LOC (expr, input_location), "in template argument for type %qT ", type); if (expr == error_mark_node) return NULL_TREE; @@ -8093,7 +8092,7 @@ push_tinst_level (tree d) new_level->decl = d; new_level->locus = input_location; new_level->errors = errorcount+sorrycount; - new_level->in_system_header_p = in_system_header; + new_level->in_system_header_p = in_system_header_at (input_location); new_level->next = current_tinst_level; current_tinst_level = new_level; @@ -8625,7 +8624,8 @@ apply_late_template_attributes (tree *decl_p, tree attributes, int attr_flags, pass it through tsubst. Attributes like mode, format, cleanup and several target specific attributes expect it unmodified. */ - else if (attribute_takes_identifier_p (get_attribute_name (t))) + else if (attribute_takes_identifier_p (get_attribute_name (t)) + && TREE_VALUE (t)) { tree chain = tsubst_expr (TREE_CHAIN (TREE_VALUE (t)), args, complain, @@ -14505,7 +14505,7 @@ tsubst_copy_and_build (tree t, fn = TREE_OPERAND (fn, 1); if (is_overloaded_fn (fn)) fn = get_first_fn (fn); - if (permerror (EXPR_LOC_OR_HERE (t), + if (permerror (EXPR_LOC_OR_LOC (t, input_location), "%qD was not declared in this scope, " "and no declarations were found by " "argument-dependent lookup at the point " @@ -14515,15 +14515,17 @@ tsubst_copy_and_build (tree t, /* Can't say anything more. */; else if (DECL_CLASS_SCOPE_P (fn)) { - inform (EXPR_LOC_OR_HERE (t), + location_t loc = EXPR_LOC_OR_LOC (t, + input_location); + inform (loc, "declarations in dependent base %qT are " "not found by unqualified lookup", DECL_CLASS_CONTEXT (fn)); if (current_class_ptr) - inform (EXPR_LOC_OR_HERE (t), + inform (loc, "use %<this->%D%> instead", function); else - inform (EXPR_LOC_OR_HERE (t), + inform (loc, "use %<%T::%D%> instead", current_class_name, function); } @@ -17209,8 +17211,9 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, /* Also deduce from the length of the initializer list. */ tree max = size_int (CONSTRUCTOR_NELTS (arg)); tree idx = compute_array_index_type (NULL_TREE, max, tf_none); - return unify_array_domain (tparms, targs, TYPE_DOMAIN (parm), - idx, explain_p); + if (TYPE_DOMAIN (parm) != NULL_TREE) + return unify_array_domain (tparms, targs, TYPE_DOMAIN (parm), + idx, explain_p); } /* If the std::initializer_list<T> deduction worked, replace the @@ -18807,7 +18810,7 @@ do_decl_instantiation (tree decl, tree storage) ; else if (storage == ridpointers[(int) RID_EXTERN]) { - if (!in_system_header && (cxx_dialect == cxx98)) + if (!in_system_header_at (input_location) && (cxx_dialect == cxx98)) pedwarn (input_location, OPT_Wpedantic, "ISO C++ 1998 forbids the use of %<extern%> on explicit " "instantiations"); @@ -18900,7 +18903,7 @@ do_type_instantiation (tree t, tree storage, tsubst_flags_t complain) if (storage != NULL_TREE) { - if (!in_system_header) + if (!in_system_header_at (input_location)) { if (storage == ridpointers[(int) RID_EXTERN]) { diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index cd5a91d2c60..7c1b18e11f8 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -43,12 +43,11 @@ along with GCC; see the file COPYING3. If not see #include "diagnostic.h" #include "cgraph.h" #include "tree-iterator.h" -#include "vec.h" #include "target.h" -#include "gimple.h" +#include "pointer-set.h" +#include "hash-table.h" #include "gimplify.h" #include "bitmap.h" -#include "hash-table.h" #include "omp-low.h" static bool verify_constant (tree, bool, bool *, bool *); @@ -2146,7 +2145,7 @@ finish_call_expr (tree fn, vec<tree, va_gc> **args, bool disallow_virtual, && type_dependent_expression_p (current_class_ref))) { result = build_nt_call_vec (fn, *args); - SET_EXPR_LOCATION (result, EXPR_LOC_OR_HERE (fn)); + SET_EXPR_LOCATION (result, EXPR_LOC_OR_LOC (fn, input_location)); KOENIG_LOOKUP_P (result) = koenig_p; if (cfun) { @@ -2721,7 +2720,8 @@ begin_class_definition (tree t) before. */ if (! TYPE_ANONYMOUS_P (t)) { - struct c_fileinfo *finfo = get_fileinfo (input_filename); + struct c_fileinfo *finfo = \ + get_fileinfo (LOCATION_FILE (input_location)); CLASSTYPE_INTERFACE_ONLY (t) = finfo->interface_only; SET_CLASSTYPE_INTERFACE_UNKNOWN_X (t, finfo->interface_unknown); @@ -5202,6 +5202,8 @@ finish_omp_clauses (tree clauses) t = mark_rvalue_use (t); if (!processing_template_decl) { + if (TREE_CODE (OMP_CLAUSE_DECL (c)) == PARM_DECL) + t = maybe_constant_value (t); t = fold_build_cleanup_point_expr (TREE_TYPE (t), t); if (TREE_CODE (TREE_TYPE (OMP_CLAUSE_DECL (c))) == POINTER_TYPE) @@ -6546,7 +6548,7 @@ finish_omp_atomic (enum tree_code code, enum tree_code opcode, tree lhs, stmt = build2 (OMP_ATOMIC, void_type_node, integer_zero_node, stmt); OMP_ATOMIC_SEQ_CST (stmt) = seq_cst; } - add_stmt (stmt); + finish_expr_stmt (stmt); } void @@ -7596,6 +7598,11 @@ check_constexpr_ctor_body (tree last, tree list) break; if (TREE_CODE (t) == BIND_EXPR) { + if (BIND_EXPR_VARS (t)) + { + ok = false; + break; + } if (!check_constexpr_ctor_body (last, BIND_EXPR_BODY (t))) return false; else @@ -8266,7 +8273,7 @@ cxx_eval_call_expression (const constexpr_call *old_call, tree t, bool allow_non_constant, bool addr, bool *non_constant_p, bool *overflow_p) { - location_t loc = EXPR_LOC_OR_HERE (t); + location_t loc = EXPR_LOC_OR_LOC (t, input_location); tree fun = get_function_named_in_call (t); tree result; constexpr_call new_call = { NULL, NULL, NULL, 0 }; @@ -9117,7 +9124,7 @@ cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base) unsigned HOST_WIDE_INT indexi = offset * BITS_PER_UNIT; tree index = bitsize_int (indexi); - if (offset/part_widthi <= TYPE_VECTOR_SUBPARTS (op00type)) + if (offset / part_widthi < TYPE_VECTOR_SUBPARTS (op00type)) return fold_build3_loc (loc, BIT_FIELD_REF, type, op00, part_width, index); @@ -9596,6 +9603,16 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t, break; case COMPONENT_REF: + if (is_overloaded_fn (t)) + { + /* We can only get here in checking mode via + build_non_dependent_expr, because any expression that + calls or takes the address of the function will have + pulled a FUNCTION_DECL out of the COMPONENT_REF. */ + gcc_checking_assert (allow_non_constant); + *non_constant_p = true; + return t; + } r = cxx_eval_component_reference (call, t, allow_non_constant, addr, non_constant_p, overflow_p); break; @@ -9647,7 +9664,7 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t, && !integer_zerop (op)) { if (!allow_non_constant) - error_at (EXPR_LOC_OR_HERE (t), + error_at (EXPR_LOC_OR_LOC (t, input_location), "reinterpret_cast from integer to pointer"); *non_constant_p = true; return t; @@ -9693,7 +9710,7 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t, case EXPR_STMT: case OFFSET_REF: if (!allow_non_constant) - error_at (EXPR_LOC_OR_HERE (t), + error_at (EXPR_LOC_OR_LOC (t, input_location), "expression %qE is not a constant-expression", t); *non_constant_p = true; break; @@ -9966,7 +9983,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) { if (flags & tf_error) { - error_at (EXPR_LOC_OR_HERE (t), + error_at (EXPR_LOC_OR_LOC (t, input_location), "call to non-constexpr function %qD", fun); explain_invalid_constexpr_fn (fun); } @@ -10058,7 +10075,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) && !integer_zerop (from)) { if (flags & tf_error) - error_at (EXPR_LOC_OR_HERE (t), + error_at (EXPR_LOC_OR_LOC (t, input_location), "reinterpret_cast from integer to pointer"); return false; } diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 2e3b58650d4..c3f57d1a2c2 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -33,9 +33,9 @@ along with GCC; see the file COPYING3. If not see #include "convert.h" #include "cgraph.h" #include "splay-tree.h" -#include "gimple.h" -#include "gimplify.h" #include "hash-table.h" +#include "gimple-expr.h" +#include "gimplify.h" #include "wide-int.h" static tree bot_manip (tree *, int *, void *); diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index c9ddbe9ba24..9f9f7b6775b 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -31,7 +31,6 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "stor-layout.h" #include "varasm.h" -#include "gimple.h" #include "cp-tree.h" #include "flags.h" #include "diagnostic.h" @@ -1883,7 +1882,7 @@ decay_conversion (tree exp, tsubst_flags_t complain) { tree type; enum tree_code code; - location_t loc = EXPR_LOC_OR_HERE (exp); + location_t loc = EXPR_LOC_OR_LOC (exp, input_location); type = TREE_TYPE (exp); if (type == error_mark_node) @@ -2133,6 +2132,8 @@ static tree rationalize_conditional_expr (enum tree_code code, tree t, tsubst_flags_t complain) { + location_t loc = EXPR_LOC_OR_LOC (t, input_location); + /* For MIN_EXPR or MAX_EXPR, fold-const.c has arranged things so that the first operand is always the one to be used if both operands are equal, so we know what conditional expression this used to be. */ @@ -2145,8 +2146,8 @@ rationalize_conditional_expr (enum tree_code code, tree t, gcc_assert (!TREE_SIDE_EFFECTS (op0) && !TREE_SIDE_EFFECTS (op1)); return - build_conditional_expr (EXPR_LOC_OR_HERE (t), - build_x_binary_op (EXPR_LOC_OR_HERE (t), + build_conditional_expr (loc, + build_x_binary_op (loc, (TREE_CODE (t) == MIN_EXPR ? LE_EXPR : GE_EXPR), op0, TREE_CODE (op0), @@ -2159,7 +2160,7 @@ rationalize_conditional_expr (enum tree_code code, tree t, } return - build_conditional_expr (EXPR_LOC_OR_HERE (t), TREE_OPERAND (t, 0), + build_conditional_expr (loc, TREE_OPERAND (t, 0), cp_build_unary_op (code, TREE_OPERAND (t, 1), 0, complain), cp_build_unary_op (code, TREE_OPERAND (t, 2), 0, @@ -5747,7 +5748,9 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert, inc = cxx_sizeof_nowarn (TREE_TYPE (argtype)); } else - inc = integer_one_node; + inc = VECTOR_TYPE_P (argtype) + ? build_one_cst (argtype) + : integer_one_node; inc = cp_convert (argtype, inc, complain); @@ -6042,8 +6045,9 @@ build_x_compound_expr_from_list (tree list, expr_list_kind exp, && !CONSTRUCTOR_IS_DIRECT_INIT (expr)) { if (complain & tf_error) - pedwarn (EXPR_LOC_OR_HERE (expr), 0, "list-initializer for " - "non-class type must not be parenthesized"); + pedwarn (EXPR_LOC_OR_LOC (expr, input_location), 0, + "list-initializer for non-class type must not " + "be parenthesized"); else return error_mark_node; } @@ -8101,7 +8105,7 @@ convert_for_assignment (tree type, tree rhs, && TREE_CODE (TREE_TYPE (rhs)) != BOOLEAN_TYPE && (complain & tf_warning)) { - location_t loc = EXPR_LOC_OR_HERE (rhs); + location_t loc = EXPR_LOC_OR_LOC (rhs, input_location); warning_at (loc, OPT_Wparentheses, "suggest parentheses around assignment used as truth value"); diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 5040226fbe2..333343b8969 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -897,11 +897,11 @@ check_narrowing (tree type, tree init) if (!ok) { if (cxx_dialect >= cxx11) - pedwarn (EXPR_LOC_OR_HERE (init), OPT_Wnarrowing, + pedwarn (EXPR_LOC_OR_LOC (init, input_location), OPT_Wnarrowing, "narrowing conversion of %qE from %qT to %qT inside { }", init, ftype, type); else - warning_at (EXPR_LOC_OR_HERE (init), OPT_Wnarrowing, + warning_at (EXPR_LOC_OR_LOC (init, input_location), OPT_Wnarrowing, "narrowing conversion of %qE from %qT to %qT inside { } " "is ill-formed in C++11", init, ftype, type); } diff --git a/gcc/cp/vtable-class-hierarchy.c b/gcc/cp/vtable-class-hierarchy.c index 32f9541e43d..b6637248951 100644 --- a/gcc/cp/vtable-class-hierarchy.c +++ b/gcc/cp/vtable-class-hierarchy.c @@ -118,7 +118,6 @@ along with GCC; see the file COPYING3. If not see #include "cgraph.h" #include "tree-iterator.h" #include "vtable-verify.h" -#include "gimple.h" #include "gimplify.h" #include "stringpool.h" #include "stor-layout.h" diff --git a/gcc/data-streamer-in.c b/gcc/data-streamer-in.c index 84242486941..39ae5010a39 100644 --- a/gcc/data-streamer-in.c +++ b/gcc/data-streamer-in.c @@ -25,6 +25,11 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "diagnostic.h" #include "tree.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "data-streamer.h" diff --git a/gcc/data-streamer-out.c b/gcc/data-streamer-out.c index fbbe0db2759..01fb36a88ae 100644 --- a/gcc/data-streamer-out.c +++ b/gcc/data-streamer-out.c @@ -24,6 +24,11 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "tree.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "data-streamer.h" diff --git a/gcc/data-streamer.c b/gcc/data-streamer.c index 675b5093314..3b697e5b280 100644 --- a/gcc/data-streamer.c +++ b/gcc/data-streamer.c @@ -23,6 +23,11 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "tree.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "data-streamer.h" diff --git a/gcc/dbxout.c b/gcc/dbxout.c index bbd8be07eac..5da1e0d0e8a 100644 --- a/gcc/dbxout.c +++ b/gcc/dbxout.c @@ -2315,10 +2315,6 @@ dbxout_type (tree type, int full) dbxout_type (TREE_TYPE (type), 0); break; - case POINTER_BOUNDS_TYPE: - /* No debug info for pointer bounds type supported yet. */ - break; - default: gcc_unreachable (); } diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index d1fbcc39274..da2c63ef00b 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -82,7 +82,6 @@ extensions, accepted by GCC in C90 mode and in C++. * x86 specific memory model extensions for transactional memory:: x86 memory models. * Object Size Checking:: Built-in functions for limited buffer overflow checking. -* Pointer Bounds Checker builtins:: Built-in functions for Pointer Bounds Checker. * Cilk Plus Builtins:: Built-in functions for the Cilk Plus language extension. * Other Builtins:: Other built-in functions. * Target Builtins:: Built-in functions specific to particular targets. @@ -2167,7 +2166,7 @@ attributes are currently defined for functions on all targets: @code{returns_nonnull}, @code{gnu_inline}, @code{externally_visible}, @code{hot}, @code{cold}, @code{artificial}, @code{no_sanitize_address}, @code{no_address_safety_analysis}, -@code{no_sanitize_undefined}, @code{bnd_legacy}, +@code{no_sanitize_undefined}, @code{error} and @code{warning}. Several other attributes are defined for functions on particular target systems. Other attributes, including @code{section} are @@ -3611,12 +3610,6 @@ The @code{no_sanitize_undefined} attribute on functions is used to inform the compiler that it should not check for undefined behavior in the function when compiling with the @option{-fsanitize=undefined} option. -@item bnd_legacy -@cindex @code{bnd_legacy} function attribute -The @code{bnd_legacy} attribute on functions is used to inform -compiler that function should not be instrumented when compiled -with @option{-fcheck-pointers} option. - @item regparm (@var{number}) @cindex @code{regparm} attribute @cindex functions that are passed arguments in registers on the 386 @@ -5410,12 +5403,12 @@ placed in either the @code{.bss_below100} section or the The keyword @code{__attribute__} allows you to specify special attributes of @code{struct} and @code{union} types when you define such types. This keyword is followed by an attribute specification -inside double parentheses. Eight attributes are currently defined for +inside double parentheses. Seven attributes are currently defined for types: @code{aligned}, @code{packed}, @code{transparent_union}, -@code{unused}, @code{deprecated}, @code{visibility}, @code{may_alias} -and @code{bnd_variable_size}. Other attributes are defined for -functions (@pxref{Function Attributes}) and for variables -(@pxref{Variable Attributes}). +@code{unused}, @code{deprecated}, @code{visibility}, and +@code{may_alias}. Other attributes are defined for functions +(@pxref{Function Attributes}) and for variables (@pxref{Variable +Attributes}). You may also specify any one of these attributes with @samp{__} preceding and following its keyword. This allows you to use these @@ -5707,35 +5700,6 @@ and caught in another, the class must have default visibility. Otherwise the two shared objects are unable to use the same typeinfo node and exception handling will break. -@item bnd_variable_size -When applied to a structure field, this attribute tells Pointer -Bounds Checker that the size of this field should not be computed -using static type information. It may be used to mark variable -sized static array fields placed at the end of a structure. - -@smallexample -struct S -@{ - int size; - char data[1]; -@} -S *p = (S *)malloc (sizeof(S) + 100); -p->data[10] = 0; //Bounds violation -@end smallexample - -By using an attribute for a field we may avoid bound violation -we most probably do not want to see: - -@smallexample -struct S -@{ - int size; - char data[1] __attribute__((bnd_variable_size)); -@} -S *p = (S *)malloc (sizeof(S) + 100); -p->data[10] = 0; //OK -@end smallexample - @end table To specify multiple attributes, separate them by commas within the @@ -7871,176 +7835,6 @@ format string @var{fmt}. If the compiler is able to optimize them to @code{fputc} etc.@: functions, it does, otherwise the checking function is called and the @var{flag} argument passed to it. -@node Pointer Bounds Checker builtins -@section Pointer Bounds Checker Built-in Functions -@findex __builtin___bnd_set_ptr_bounds -@findex __builtin___bnd_narrow_ptr_bounds -@findex __builtin___bnd_copy_ptr_bounds -@findex __builtin___bnd_init_ptr_bounds -@findex __builtin___bnd_null_ptr_bounds -@findex __builtin___bnd_store_ptr_bounds -@findex __builtin___bnd_chk_ptr_lbounds -@findex __builtin___bnd_chk_ptr_ubounds -@findex __builtin___bnd_chk_ptr_bounds -@findex __builtin___bnd_get_ptr_lbound -@findex __builtin___bnd_get_ptr_ubound - -GCC provides a set of built-in functions to control Pointer Bounds Checker -instrumentation. Note that all Pointer Bounds Checker builtins are allowed -to use even if you compile with Pointer Bounds Checker off. But functions -behavior may differ in such case. - -@deftypefn {Built-in Function} void * __builtin___bnd_set_ptr_bounds (const void * @var{q}, size_t @var{size}) - -This built-in function returns a new pointer with the value of @var{q}, and -associate it with the bounds [@var{q}, @var{q}+@var{size}-1]. With Pointer -Bounds Checker off built-in function just returns the first argument. - -@smallexample -extern void *__wrap_malloc (size_t n) -@{ - void *p = (void *)__real_malloc (n); - if (!p) return __builtin___bnd_null_ptr_bounds (p); - return __builtin___bnd_set_ptr_bounds (p, n); -@} -@end smallexample - -@end deftypefn - -@deftypefn {Built-in Function} void * __builtin___bnd_narrow_ptr_bounds (const void * @var{p}, const void * @var{q}, size_t @var{size}) - -This built-in function returns a new pointer with the value of @var{p} -and associate it with the narrowed bounds formed by the intersection -of bounds associated with @var{q} and the [@var{p}, @var{p} + @var{size} - 1]. -With Pointer Bounds Checker off built-in function just returns the first -argument. - -@smallexample -void init_objects (object *objs, size_t size) -@{ - size_t i; - /* Initialize objects one-by-one passing pointers with bounds of an object, - not the full array of objects. */ - for (i = 0; i < size; i++) - init_object (__builtin___bnd_narrow_ptr_bounds (objs + i, objs, sizeof(object))); -@} -@end smallexample - -@end deftypefn - -@deftypefn {Built-in Function} void * __builtin___bnd_copy_ptr_bounds (const void * @var{q}, const void * @var{r}) - -This built-in function returns a new pointer with the value of @var{q}, -and associate it with the bounds already associated with pointer @var{r}. -With Pointer Bounds Checker off built-in function just returns the first -argument. - -@smallexample -/* Here is a way to get pointer to object's field but - still with the full object's bounds. */ -int *field_ptr = __builtin___bnd_copy_ptr_bounds (&objptr->int_filed, objptr); -@end smallexample - -@end deftypefn - -@deftypefn {Built-in Function} void * __builtin___bnd_init_ptr_bounds (const void * @var{q}) - -This built-in function returns a new pointer with the value of @var{q}, and -associate it with INIT (allowing full memory access) bounds. With Pointer -Bounds Checker off built-in function just returns the first argument. - -@end deftypefn - -@deftypefn {Built-in Function} void * __builtin___bnd_null_ptr_bounds (const void * @var{q}) - -This built-in function returns a new pointer with the value of @var{q}, and -associate it with NULL (allowing no memory access) bounds. With Pointer -Bounds Checker off built-in function just returns the first argument. - -@end deftypefn - -@deftypefn {Built-in Function} void __builtin___bnd_store_ptr_bounds (const void ** @var{ptr_addr}, const void * @var{ptr_val}) - -This built-in function stores the bounds associated with pointer @var{ptr_val} -and location @var{ptr_addr} into Bounds Table. This can be useful to propagate -bounds from legacy code without touching the associated pointer's memory when -pointers were copied as integers. With Pointer Bounds Checker off built-in -function call is ignored. - -@end deftypefn - -@deftypefn {Built-in Function} void __builtin___bnd_chk_ptr_lbounds (const void * @var{q}) - -This built-in function checks if the pointer @var{q} is within the lower -bound of its associated bounds. With Pointer Bounds Checker off built-in -function call is ignored. - -@smallexample -extern void *__wrap_memset (void *dst, int c, size_t len) -@{ - if (len > 0) - @{ - __builtin___bnd_chk_ptr_lbounds (dst); - __builtin___bnd_chk_ptr_ubounds ((char *)dst + len - 1); - __real_memset (dst, c, len); - @} - return dst; -@} -@end smallexample - -@end deftypefn - -@deftypefn {Built-in Function} void __builtin___bnd_chk_ptr_ubounds (const void * @var{q}) - -This built-in function checks if the pointer @var{q} is within the upper -bound of its associated bounds. With Pointer Bounds Checker off built-in -function call is ignored. - -@end deftypefn - -@deftypefn {Built-in Function} void __builtin___bnd_chk_ptr_bounds (const void * @var{q}, size_t @var{size}) - -This built-in function checks if [@var{q}, @var{q} + @var{size} - 1] is within -the lower and upper bounds associated with @var{q}. With Pointer Bounds Checker -off built-in function call is ignored. - -@smallexample -extern void *__wrap_memcpy (void *dst, const void *src, size_t n) -@{ - if (n > 0) - @{ - __bnd_chk_ptr_bounds (dst, n); - __bnd_chk_ptr_bounds (src, n); - __real_memcpy (dst, src, n); - @} - return dst; -@} -@end smallexample - -@end deftypefn - -@deftypefn {Built-in Function} const void * __builtin___bnd_get_ptr_lbound (const void * @var{q}) - -This built-in function returns the lower bound (which is a pointer) associated -with the pointer @var{q}. This is at least useful for debugging using printf. -With Pointer Bounds Checker off built-in function returns 0. - -@smallexample -void *lb = __builtin___bnd_get_ptr_lbound (q); -void *ub = __builtin___bnd_get_ptr_ubound (q); -printf ("q = %p lb(q) = %p ub(q) = %p", q, lb, ub); -@end smallexample - -@end deftypefn - -@deftypefn {Built-in Function} const void * __builtin___bnd_get_ptr_ubound (const void * @var{q}) - -This built-in function returns the upper bound (which is a pointer) associated -with the pointer @var{q}. With Pointer Bounds Checker off built-in function -returns -1. - -@end deftypefn - @node Cilk Plus Builtins @section Cilk Plus C/C++ language extension Built-in Functions. diff --git a/gcc/doc/implement-c.texi b/gcc/doc/implement-c.texi index 6efcfea4716..974546c1ca8 100644 --- a/gcc/doc/implement-c.texi +++ b/gcc/doc/implement-c.texi @@ -9,9 +9,9 @@ A conforming implementation of ISO C is required to document its choice of behavior in each of the areas that are designated ``implementation defined''. The following lists all such areas, -along with the section numbers from the ISO/IEC 9899:1990 and ISO/IEC -9899:1999 standards. Some areas are only implementation-defined in -one version of the standard. +along with the section numbers from the ISO/IEC 9899:1990, ISO/IEC +9899:1999 and ISO/IEC 9899:2011 standards. Some areas are only +implementation-defined in one version of the standard. Some choices depend on the externally determined ABI for the platform (including standard character encodings) which GCC follows; these are @@ -47,14 +47,15 @@ a freestanding environment); refer to their documentation for details. @itemize @bullet @item -@cite{How a diagnostic is identified (C90 3.7, C99 3.10, C90 and C99 5.1.1.3).} +@cite{How a diagnostic is identified (C90 3.7, C99 and C11 3.10, C90, +C99 and C11 5.1.1.3).} Diagnostics consist of all the output sent to stderr by GCC@. @item @cite{Whether each nonempty sequence of white-space characters other than new-line is retained or replaced by one space character in translation -phase 3 (C90 and C99 5.1.1.2).} +phase 3 (C90, C99 and C11 5.1.1.2).} @xref{Implementation-defined behavior, , Implementation-defined behavior, cpp, The C Preprocessor}. @@ -70,7 +71,8 @@ of the C library, and are not defined by GCC itself. @itemize @bullet @item @cite{The mapping between physical source file multibyte characters -and the source character set in translation phase 1 (C90 and C99 5.1.1.2).} +and the source character set in translation phase 1 (C90, C99 and C11 +5.1.1.2).} @xref{Implementation-defined behavior, , Implementation-defined behavior, cpp, The C Preprocessor}. @@ -83,14 +85,14 @@ behavior, cpp, The C Preprocessor}. @itemize @bullet @item @cite{Which additional multibyte characters may appear in identifiers -and their correspondence to universal character names (C99 6.4.2).} +and their correspondence to universal character names (C99 and C11 6.4.2).} @xref{Implementation-defined behavior, , Implementation-defined behavior, cpp, The C Preprocessor}. @item @cite{The number of significant initial characters in an identifier -(C90 6.1.2, C90 and C99 5.2.4.1, C99 6.4.2).} +(C90 6.1.2, C90, C99 and C11 5.2.4.1, C99 and C11 6.4.2).} For internal names, all characters are significant. For external names, the number of significant characters are defined by the linker; for @@ -100,7 +102,7 @@ almost all targets, all characters are significant. @cite{Whether case distinctions are significant in an identifier with external linkage (C90 6.1.2).} -This is a property of the linker. C99 requires that case distinctions +This is a property of the linker. C99 and C11 require that case distinctions are always significant in identifiers with external linkage and systems without this property are not supported by GCC@. @@ -111,33 +113,34 @@ systems without this property are not supported by GCC@. @itemize @bullet @item -@cite{The number of bits in a byte (C90 3.4, C99 3.6).} +@cite{The number of bits in a byte (C90 3.4, C99 and C11 3.6).} Determined by ABI@. @item -@cite{The values of the members of the execution character set (C90 -and C99 5.2.1).} +@cite{The values of the members of the execution character set (C90, +C99 and C11 5.2.1).} Determined by ABI@. @item @cite{The unique value of the member of the execution character set produced -for each of the standard alphabetic escape sequences (C90 and C99 5.2.2).} +for each of the standard alphabetic escape sequences (C90, C99 and C11 +5.2.2).} Determined by ABI@. @item @cite{The value of a @code{char} object into which has been stored any character other than a member of the basic execution character set -(C90 6.1.2.5, C99 6.2.5).} +(C90 6.1.2.5, C99 and C11 6.2.5).} Determined by ABI@. @item @cite{Which of @code{signed char} or @code{unsigned char} has the same range, representation, and behavior as ``plain'' @code{char} (C90 -6.1.2.5, C90 6.2.1.1, C99 6.2.5, C99 6.3.1.1).} +6.1.2.5, C90 6.2.1.1, C99 and C11 6.2.5, C99 and C11 6.3.1.1).} @opindex fsigned-char @opindex funsigned-char @@ -148,23 +151,25 @@ Options Controlling C Dialect}. @item @cite{The mapping of members of the source character set (in character constants and string literals) to members of the execution character -set (C90 6.1.3.4, C99 6.4.4.4, C90 and C99 5.1.1.2).} +set (C90 6.1.3.4, C99 and C11 6.4.4.4, C90, C99 and C11 5.1.1.2).} Determined by ABI@. @item @cite{The value of an integer character constant containing more than one character or containing a character or escape sequence that does not map -to a single-byte execution character (C90 6.1.3.4, C99 6.4.4.4).} +to a single-byte execution character (C90 6.1.3.4, C99 and C11 6.4.4.4).} @xref{Implementation-defined behavior, , Implementation-defined behavior, cpp, The C Preprocessor}. @item @cite{The value of a wide character constant containing more than one -multibyte character, or containing a multibyte character or escape -sequence not represented in the extended execution character set (C90 -6.1.3.4, C99 6.4.4.4).} +multibyte character or a single multibyte character that maps to +multiple members of the extended execution character set, or +containing a multibyte character or escape sequence not represented in +the extended execution character set (C90 6.1.3.4, C99 and C11 +6.4.4.4).} @xref{Implementation-defined behavior, , Implementation-defined behavior, cpp, The C Preprocessor}. @@ -173,24 +178,44 @@ behavior, cpp, The C Preprocessor}. @cite{The current locale used to convert a wide character constant consisting of a single multibyte character that maps to a member of the extended execution character set into a corresponding wide character code (C90 -6.1.3.4, C99 6.4.4.4).} +6.1.3.4, C99 and C11 6.4.4.4).} @xref{Implementation-defined behavior, , Implementation-defined behavior, cpp, The C Preprocessor}. @item +@cite{Whether differently-prefixed wide string literal tokens can be +concatenated and, if so, the treatment of the resulting multibyte +character sequence (C11 6.4.5).} + +Such tokens may not be concatenated. + +@item @cite{The current locale used to convert a wide string literal into -corresponding wide character codes (C90 6.1.4, C99 6.4.5).} +corresponding wide character codes (C90 6.1.4, C99 and C11 6.4.5).} @xref{Implementation-defined behavior, , Implementation-defined behavior, cpp, The C Preprocessor}. @item @cite{The value of a string literal containing a multibyte character or escape -sequence not represented in the execution character set (C90 6.1.4, C99 6.4.5).} +sequence not represented in the execution character set (C90 6.1.4, +C99 and C11 6.4.5).} @xref{Implementation-defined behavior, , Implementation-defined behavior, cpp, The C Preprocessor}. + +@item +@cite{The encoding of any of @code{wchar_t}, @code{char16_t}, and +@code{char32_t} where the corresponding standard encoding macro +(@code{__STDC_ISO_10646__}, @code{__STDC_UTF_16__}, or +@code{__STDC_UTF_32__}) is not defined (C11 6.10.8.2).} + +@xref{Implementation-defined behavior, , Implementation-defined +behavior, cpp, The C Preprocessor}. @code{char16_t} and +@code{char32_t} literals are always encoded in UTF-16 and UTF-32 +respectively. + @end itemize @node Integers implementation @@ -198,7 +223,8 @@ behavior, cpp, The C Preprocessor}. @itemize @bullet @item -@cite{Any extended integer types that exist in the implementation (C99 6.2.5).} +@cite{Any extended integer types that exist in the implementation (C99 +and C11 6.2.5).} GCC does not support any extended integer types. @c The __mode__ attribute might create types of precisions not @@ -211,14 +237,14 @@ GCC does not support any extended integer types. @item @cite{Whether signed integer types are represented using sign and magnitude, two's complement, or one's complement, and whether the extraordinary value -is a trap representation or an ordinary value (C99 6.2.6.2).} +is a trap representation or an ordinary value (C99 and C11 6.2.6.2).} GCC supports only two's complement integer types, and all bit patterns are ordinary values. @item @cite{The rank of any extended integer type relative to another extended -integer type with the same precision (C99 6.3.1.1).} +integer type with the same precision (C99 and C11 6.3.1.1).} GCC does not support any extended integer types. @c If it did, there would only be one of each precision and signedness. @@ -226,28 +252,28 @@ GCC does not support any extended integer types. @item @cite{The result of, or the signal raised by, converting an integer to a signed integer type when the value cannot be represented in an object of -that type (C90 6.2.1.2, C99 6.3.1.3).} +that type (C90 6.2.1.2, C99 and C11 6.3.1.3).} For conversion to a type of width @math{N}, the value is reduced modulo @math{2^N} to be within range of the type; no signal is raised. @item @cite{The results of some bitwise operations on signed integers (C90 -6.3, C99 6.5).} +6.3, C99 and C11 6.5).} Bitwise operators act on the representation of the value including both the sign and value bits, where the sign bit is considered immediately above the highest-value value bit. Signed @samp{>>} acts on negative numbers by sign extension. -GCC does not use the latitude given in C99 only to treat certain +GCC does not use the latitude given in C99 and C11 only to treat certain aspects of signed @samp{<<} as undefined, but this is subject to change. @item @cite{The sign of the remainder on integer division (C90 6.3.5).} -GCC always follows the C99 requirement that the result of division is +GCC always follows the C99 and C11 requirement that the result of division is truncated towards zero. @end itemize @@ -259,33 +285,33 @@ truncated towards zero. @item @cite{The accuracy of the floating-point operations and of the library functions in @code{<math.h>} and @code{<complex.h>} that return floating-point -results (C90 and C99 5.2.4.2.2).} +results (C90, C99 and C11 5.2.4.2.2).} The accuracy is unknown. @item @cite{The rounding behaviors characterized by non-standard values of @code{FLT_ROUNDS} @gol -(C90 and C99 5.2.4.2.2).} +(C90, C99 and C11 5.2.4.2.2).} GCC does not use such values. @item @cite{The evaluation methods characterized by non-standard negative -values of @code{FLT_EVAL_METHOD} (C99 5.2.4.2.2).} +values of @code{FLT_EVAL_METHOD} (C99 and C11 5.2.4.2.2).} GCC does not use such values. @item @cite{The direction of rounding when an integer is converted to a floating-point number that cannot exactly represent the original -value (C90 6.2.1.3, C99 6.3.1.4).} +value (C90 6.2.1.3, C99 and C11 6.3.1.4).} C99 Annex F is followed. @item @cite{The direction of rounding when a floating-point number is -converted to a narrower floating-point number (C90 6.2.1.4, C99 +converted to a narrower floating-point number (C90 6.2.1.4, C99 and C11 6.3.1.5).} C99 Annex F is followed. @@ -293,38 +319,42 @@ C99 Annex F is followed. @item @cite{How the nearest representable value or the larger or smaller representable value immediately adjacent to the nearest representable -value is chosen for certain floating constants (C90 6.1.3.1, C99 +value is chosen for certain floating constants (C90 6.1.3.1, C99 and C11 6.4.4.2).} C99 Annex F is followed. @item @cite{Whether and how floating expressions are contracted when not -disallowed by the @code{FP_CONTRACT} pragma (C99 6.5).} +disallowed by the @code{FP_CONTRACT} pragma (C99 and C11 6.5).} -Expressions are currently only contracted if +Expressions are currently only contracted if @option{-ffp-contract=fast}, @option{-funsafe-math-optimizations} or @option{-ffast-math} are used. This is subject to change. @item -@cite{The default state for the @code{FENV_ACCESS} pragma (C99 7.6.1).} +@cite{The default state for the @code{FENV_ACCESS} pragma (C99 and C11 +7.6.1).} This pragma is not implemented, but the default is to ``off'' unless @option{-frounding-math} is used in which case it is ``on''. @item @cite{Additional floating-point exceptions, rounding modes, environments, -and classifications, and their macro names (C99 7.6, C99 7.12).} +and classifications, and their macro names (C99 and C11 7.6, C99 and +C11 7.12).} This is dependent on the implementation of the C library, and is not defined by GCC itself. @item -@cite{The default state for the @code{FP_CONTRACT} pragma (C99 7.12.2).} +@cite{The default state for the @code{FP_CONTRACT} pragma (C99 and C11 +7.12.2).} This pragma is not implemented. Expressions are currently only -contracted if @option{-funsafe-math-optimizations} or -@option{-ffast-math} are used. This is subject to change. +contracted if @option{-ffp-contract=fast}, +@option{-funsafe-math-optimizations} or @option{-ffast-math} are used. +This is subject to change. @item @cite{Whether the ``inexact'' floating-point exception can be raised @@ -350,7 +380,7 @@ defined by GCC itself. @itemize @bullet @item @cite{The result of converting a pointer to an integer or -vice versa (C90 6.3.4, C99 6.3.2.3).} +vice versa (C90 6.3.4, C99 and C11 6.3.2.3).} A cast from pointer to integer discards most-significant bits if the pointer representation is larger than the integer type, @@ -373,11 +403,11 @@ When casting from pointer to integer and back again, the resulting pointer must reference the same object as the original pointer, otherwise the behavior is undefined. That is, one may not use integer arithmetic to avoid the undefined behavior of pointer arithmetic as proscribed in -C99 6.5.6/8. +C99 and C11 6.5.6/8. @item @cite{The size of the result of subtracting two pointers to elements -of the same array (C90 6.3.6, C99 6.5.6).} +of the same array (C90 6.3.6, C99 and C11 6.5.6).} The value is as specified in the standard and the type is determined by the ABI@. @@ -390,7 +420,7 @@ by the ABI@. @itemize @bullet @item @cite{The extent to which suggestions made by using the @code{register} -storage-class specifier are effective (C90 6.5.1, C99 6.7.1).} +storage-class specifier are effective (C90 6.5.1, C99 and C11 6.7.1).} The @code{register} specifier affects code generation only in these ways: @@ -415,7 +445,7 @@ in registers unless they are marked @code{register}. @item @cite{The extent to which suggestions made by using the inline function -specifier are effective (C99 6.7.4).} +specifier are effective (C99 and C11 6.7.4).} GCC will not inline any functions if the @option{-fno-inline} option is used or if @option{-O0} is used. Otherwise, GCC may still be unable to @@ -439,7 +469,7 @@ may be a trap representation. @item @cite{Whether a ``plain'' @code{int} bit-field is treated as a @code{signed int} bit-field or as an @code{unsigned int} bit-field -(C90 6.5.2, C90 6.5.2.1, C99 6.7.2, C99 6.7.2.1).} +(C90 6.5.2, C90 6.5.2.1, C99 and C11 6.7.2, C99 and C11 6.7.2.1).} @opindex funsigned-bitfields By default it is treated as @code{signed int} but this may be changed @@ -447,33 +477,38 @@ by the @option{-funsigned-bitfields} option. @item @cite{Allowable bit-field types other than @code{_Bool}, @code{signed int}, -and @code{unsigned int} (C99 6.7.2.1).} +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 mode? +@c mode and document the other types for C99/C11 mode? + +@item +@cite{Whether atomic types are permitted for bit-fields (C11 6.7.2.1).} + +Atomic types are not permitted for bit-fields. @item @cite{Whether a bit-field can straddle a storage-unit boundary (C90 -6.5.2.1, C99 6.7.2.1).} +6.5.2.1, C99 and C11 6.7.2.1).} Determined by ABI@. @item @cite{The order of allocation of bit-fields within a unit (C90 -6.5.2.1, C99 6.7.2.1).} +6.5.2.1, C99 and C11 6.7.2.1).} Determined by ABI@. @item @cite{The alignment of non-bit-field members of structures (C90 -6.5.2.1, C99 6.7.2.1).} +6.5.2.1, C99 and C11 6.7.2.1).} Determined by ABI@. @item @cite{The integer type compatible with each enumerated type (C90 -6.5.2.2, C99 6.7.2.2).} +6.5.2.2, C99 and C11 6.7.2.2).} @opindex fshort-enums Normally, the type is @code{unsigned int} if there are no negative @@ -501,7 +536,7 @@ determined by the ABI@. @itemize @bullet @item @cite{What constitutes an access to an object that has volatile-qualified -type (C90 6.5.3, C99 6.7.3).} +type (C90 6.5.3, C99 and C11 6.7.3).} Such an object is normally accessed by pointers and used for accessing hardware. In most expressions, it is intuitively obvious what is a read @@ -575,45 +610,49 @@ implementation-defined behavior. @itemize @bullet @item +@cite{The locations within @code{#pragma} directives where header name +preprocessing tokens are recognized (C11 6.4, C11 6.4.7).} + +@item @cite{How sequences in both forms of header names are mapped to headers -or external source file names (C90 6.1.7, C99 6.4.7).} +or external source file names (C90 6.1.7, C99 and C11 6.4.7).} @item @cite{Whether the value of a character constant in a constant expression that controls conditional inclusion matches the value of the same character -constant in the execution character set (C90 6.8.1, C99 6.10.1).} +constant in the execution character set (C90 6.8.1, C99 and C11 6.10.1).} @item @cite{Whether the value of a single-character character constant in a constant expression that controls conditional inclusion may have a -negative value (C90 6.8.1, C99 6.10.1).} +negative value (C90 6.8.1, C99 and C11 6.10.1).} @item @cite{The places that are searched for an included @samp{<>} delimited header, and how the places are specified or the header is -identified (C90 6.8.2, C99 6.10.2).} +identified (C90 6.8.2, C99 and C11 6.10.2).} @item @cite{How the named source file is searched for in an included @samp{""} -delimited header (C90 6.8.2, C99 6.10.2).} +delimited header (C90 6.8.2, C99 and C11 6.10.2).} @item @cite{The method by which preprocessing tokens (possibly resulting from macro expansion) in a @code{#include} directive are combined into a header -name (C90 6.8.2, C99 6.10.2).} +name (C90 6.8.2, C99 and C11 6.10.2).} @item @cite{The nesting limit for @code{#include} processing (C90 6.8.2, C99 -6.10.2).} +and C11 6.10.2).} @item @cite{Whether the @samp{#} operator inserts a @samp{\} character before the @samp{\} character that begins a universal character name in a -character constant or string literal (C99 6.10.3.2).} +character constant or string literal (C99 and C11 6.10.3.2).} @item @cite{The behavior on each recognized non-@code{STDC #pragma} -directive (C90 6.8.6, C99 6.10.6).} +directive (C90 6.8.6, C99 and C11 6.10.6).} @xref{Pragmas, , Pragmas, cpp, The C Preprocessor}, for details of pragmas accepted by GCC on all targets. @xref{Pragmas, , Pragmas @@ -622,7 +661,7 @@ Accepted by GCC}, for details of target-specific pragmas. @item @cite{The definitions for @code{__DATE__} and @code{__TIME__} when respectively, the date and time of translation are not available (C90 -6.8.8, C99 6.10.8).} +6.8.8, C99 6.10.8, C11 6.10.8.1).} @end itemize @@ -635,7 +674,7 @@ of the C library, and are not defined by GCC itself. @itemize @bullet @item @cite{The null pointer constant to which the macro @code{NULL} expands -(C90 7.1.6, C99 7.17).} +(C90 7.1.6, C99 7.17, C11 7.19).} In @code{<stddef.h>}, @code{NULL} expands to @code{((void *)0)}. GCC does not provide the other headers which define @code{NULL} and some @@ -650,19 +689,44 @@ library implementations may use other definitions in those headers. @item @cite{The values or expressions assigned to the macros specified in the headers @code{<float.h>}, @code{<limits.h>}, and @code{<stdint.h>} -(C90 and C99 5.2.4.2, C99 7.18.2, C99 7.18.3).} +(C90, C99 and C11 5.2.4.2, C99 7.18.2, C99 7.18.3, C11 7.20.2, C11 7.20.3).} Determined by ABI@. @item +@cite{The result of attempting to indirectly access an object with +automatic or thread storage duration from a thread other than the one +with which it is associated (C11 6.2.4).} + +Such accesses are supported, subject to the same requirements for +synchronization for concurrent accesses as for concurrent accesses to +any object. + +@item @cite{The number, order, and encoding of bytes in any object -(when not explicitly specified in this International Standard) (C99 6.2.6.1).} +(when not explicitly specified in this International Standard) (C99 +and C11 6.2.6.1).} Determined by ABI@. @item -@cite{The value of the result of the @code{sizeof} operator (C90 -6.3.3.4, C99 6.5.3.4).} +@cite{Whether any extended alignments are supported and the contexts +in which they are supported (C11 6.2.8).} + +Extended alignments up to @math{2^{28}} (bytes) are supported for +objects of automatic storage duration. Alignments supported for +objects of static and thread storage duration are determined by the +ABI. + +@item +@cite{Valid alignment values other than those returned by an _Alignof +expression for fundamental types, if any (C11 6.2.8).} + +Valid alignments are powers of 2 up to and including @math{2^{28}}. + +@item +@cite{The value of the result of the @code{sizeof} and @code{_Alignof} +operators (C90 6.3.3.4, C99 and C11 6.5.3.4).} Determined by ABI@. diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 6adfc98a22b..b30e889764d 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -256,7 +256,7 @@ Objective-C and Objective-C++ Dialects}. -Wlogical-op -Wlong-long @gol -Wmain -Wmaybe-uninitialized -Wmissing-braces -Wmissing-field-initializers @gol -Wmissing-include-dirs @gol --Wno-multichar -Wnonnull -Wno-overflow @gol +-Wno-multichar -Wnonnull -Wno-overflow -Wopenmp-simd @gol -Woverlength-strings -Wpacked -Wpacked-bitfield-compat -Wpadded @gol -Wparentheses -Wpedantic-ms-format -Wno-pedantic-ms-format @gol -Wpointer-arith -Wno-pointer-to-int-cast @gol @@ -455,7 +455,7 @@ Objective-C and Objective-C++ Dialects}. @gccoptlist{@var{object-file-name} -l@var{library} @gol -nostartfiles -nodefaultlibs -nostdlib -pie -rdynamic @gol -s -static -static-libgcc -static-libstdc++ @gol --static-libasan -static-libtsan -static-libubsan @gol +-static-libasan -static-libtsan -static-liblsan -static-libubsan @gol -shared -shared-libgcc -symbolic @gol -T @var{script} -Wl,@var{option} -Xlinker @var{option} @gol -u @var{symbol}} @@ -533,6 +533,7 @@ Objective-C and Objective-C++ Dialects}. -mfix-cortex-m3-ldrd @gol -munaligned-access @gol -mneon-for-64bits @gol +-mslow-flash-data @gol -mrestrict-it} @emph{AVR Options} @@ -668,7 +669,7 @@ Objective-C and Objective-C++ Dialects}. -mavx2 -mavx512f -mavx512pf -mavx512er -mavx512cd @gol -maes -mpclmul -mfsgsbase -mrdrnd -mf16c -mfma @gol -msse4a -m3dnow -mpopcnt -mabm -mbmi -mtbm -mfma4 -mxop -mlzcnt @gol --mbmi2 -mfxsr -mxsave -mxsaveopt -mrtm -mlwp -mmpx -mthreads @gol +-mbmi2 -mfxsr -mxsave -mxsaveopt -mrtm -mlwp -mthreads @gol -mno-align-stringops -minline-all-stringops @gol -minline-stringops-dynamically -mstringop-strategy=@var{alg} @gol -mmemcpy-strategy=@var{strategy} -mmemset-strategy=@var{strategy} @@ -1500,6 +1501,7 @@ This invokes all subprograms of @command{gcc} under @samp{gdb --args cc1 @dots{}}. @item -fplugin=@var{name}.so +@opindex fplugin Load the plugin code in file @var{name}.so, assumed to be a shared object to be dlopen'd by the compiler. The base name of the shared object file is used to identify the plugin for the @@ -1509,15 +1511,18 @@ Each plugin should define the callback functions specified in the Plugins API. @item -fplugin-arg-@var{name}-@var{key}=@var{value} +@opindex fplugin-arg Define an argument called @var{key} with a value of @var{value} for the plugin called @var{name}. @item -fdump-ada-spec@r{[}-slim@r{]} +@opindex fdump-ada-spec For C and C++ source and include files, generate corresponding Ada specs. @xref{Generating Ada Bindings for C and C++ headers,,, gnat_ugn, GNAT User's Guide}, which provides detailed documentation on this feature. @item -fdump-go-spec=@var{file} +@opindex fdump-go-spec For input files in any language, generate corresponding Go declarations in @var{file}. This generates Go @code{const}, @code{type}, @code{var}, and @code{func} declarations which may be a @@ -1653,16 +1658,24 @@ ISO C90 as modified in amendment 1. @itemx c9x @itemx iso9899:1999 @itemx iso9899:199x -ISO C99. Note that this standard is not yet fully supported; see +ISO C99. This standard is substantially completely supported, modulo +bugs, extended identifiers (supported except for corner cases when +@option{-fextended-identifiers} is used) and floating-point issues +(mainly but not entirely relating to optional C99 features from +Annexes F and G). See @w{@uref{http://gcc.gnu.org/c99status.html}} for more information. The names @samp{c9x} and @samp{iso9899:199x} are deprecated. @item c11 @itemx c1x @itemx iso9899:2011 -ISO C11, the 2011 revision of the ISO C standard. -Support is incomplete and experimental. The name @samp{c1x} is -deprecated. +ISO C11, the 2011 revision of the ISO C standard. This standard is +substantially completely supported, modulo bugs, extended identifiers +(supported except for corner cases when +@option{-fextended-identifiers} is used), floating-point issues +(mainly but not entirely relating to optional C11 features from +Annexes F and G) and the optional Annexes K (Bounds-checking +interfaces) and L (Analyzability). The name @samp{c1x} is deprecated. @item gnu90 @itemx gnu89 @@ -1671,13 +1684,12 @@ is the default for C code. @item gnu99 @itemx gnu9x -GNU dialect of ISO C99. When ISO C99 is fully implemented in GCC, -this will become the default. The name @samp{gnu9x} is deprecated. +GNU dialect of ISO C99. The name @samp{gnu9x} is deprecated. @item gnu11 @itemx gnu1x -GNU dialect of ISO C11. Support is incomplete and experimental. The -name @samp{gnu1x} is deprecated. +GNU dialect of ISO C11. This is intended to become the default in a +future release of GCC. The name @samp{gnu1x} is deprecated. @item c++98 @itemx c++03 @@ -1751,6 +1763,7 @@ arguments followed by their declarations is also provided, inside comments, after the declaration. @item -fallow-parameterless-variadic-functions +@opindex fallow-parameterless-variadic-functions Accept variadic functions without named parameters. Although it is possible to define such a function, this is not very @@ -2392,7 +2405,7 @@ Note: This feature APPENDS data to the log file. If you want a fresh log file, be sure to delete any existing one. @item -fvtv-counts -@opindex (fvtv-counts) +@opindex fvtv-counts This is a debugging flag. When used in conjunction with @option{-fvtable-verify=std} or @option{-fvtable-verify=preinit}, this causes the compiler to keep track of the total number of virtual calls @@ -3320,6 +3333,7 @@ Options} and @ref{Objective-C and Objective-C++ Dialect Options}. -Wmaybe-uninitialized @gol -Wmissing-braces @r{(only for C/ObjC)} @gol -Wnonnull @gol +-Wopenmp-simd @gol -Wparentheses @gol -Wpointer-sign @gol -Wreorder @gol @@ -3490,6 +3504,8 @@ Options,,Options Controlling C Dialect}. @table @gcctabopt @item -Wformat=1 @itemx -Wformat +@opindex Wformat +@opindex Wformat=1 Option @option{-Wformat} is equivalent to @option{-Wformat=1}, and @option{-Wno-format} is equivalent to @option{-Wformat=0}. Since @option{-Wformat} also checks for null format arguments for several @@ -3528,6 +3544,7 @@ The C standard specifies that zero-length formats are allowed. @item -Wformat=2 +@opindex Wformat=2 Enable @option{-Wformat} plus additional format checks. Currently equivalent to @option{-Wformat -Wformat-nonliteral -Wformat-security -Wformat-y2k}. @@ -4814,6 +4831,12 @@ attribute. @opindex Woverflow Do not warn about compile-time overflow in constant expressions. +@item -Wopenmp-simd +@opindex Wopenm-simd +Warn if the vectorizer cost model overrides the OpenMP or the Cilk Plus +simd directive set by user. The @option{-fsimd-cost-model=unlimited} can +be used to relax the cost model. + @item -Woverride-init @r{(C and Objective-C only)} @opindex Woverride-init @opindex Wno-override-init @@ -5258,55 +5281,89 @@ many times it is given. This is mainly intended to be used with @option{-fcompare-debug}. @item -fsanitize=address +@opindex fsanitize=address Enable AddressSanitizer, a fast memory error detector. Memory access instructions will be instrumented to detect out-of-bounds and use-after-free bugs. -See @uref{http://code.google.com/p/address-sanitizer/} for more details. +See @uref{http://code.google.com/p/address-sanitizer/} for +more details. The run-time behavior can be influenced using the +@env{ASAN_OPTIONS} environment variable; see +@url{https://code.google.com/p/address-sanitizer/wiki/Flags#Run-time_flags} for +a list of supported options. @item -fsanitize=thread +@opindex fsanitize=thread Enable ThreadSanitizer, a fast data race detector. Memory access instructions will be instrumented to detect -data race bugs. -See @uref{http://code.google.com/p/data-race-test/wiki/ThreadSanitizer} for more details. +data race bugs. See @uref{http://code.google.com/p/thread-sanitizer/} for more +details. The run-time behavior can be influenced using the @env{TSAN_OPTIONS} +environment variable; see +@url{https://code.google.com/p/thread-sanitizer/wiki/Flags} for a list of +supported options. + +@item -fsanitize=leak +@opindex fsanitize=leak +Enable LeakSanitizer, a memory leak detector. +This option only matters for linking of executables and if neither +@option{-fsanitize=address} nor @option{-fsanitize=thread} is used. In that +case it will link the executable against a library that overrides @code{malloc} +and other allocator functions. See +@uref{https://code.google.com/p/address-sanitizer/wiki/LeakSanitizer} for more +details. The run-time behavior can be influenced using the +@env{LSAN_OPTIONS} environment variable. @item -fsanitize=undefined +@opindex fsanitize=undefined Enable UndefinedBehaviorSanitizer, a fast undefined behavior detector. Various computations will be instrumented to detect undefined behavior at runtime. Current suboptions are: -@itemize @bullet +@table @gcctabopt -@item @option{-fsanitize=shift} +@item -fsanitize=shift +@opindex fsanitize=shift This option enables checking that the result of a shift operation is not undefined. Note that what exactly is considered undefined differs slightly between C and C++, as well as between ISO C90 and C99, etc. -@item @option{-fsanitize=integer-divide-by-zero} +@item -fsanitize=integer-divide-by-zero +@opindex fsanitize=integer-divide-by-zero Detect integer division by zero as well as @code{INT_MIN / -1} division. -@item @option{-fsanitize=unreachable} +@item -fsanitize=unreachable +@opindex fsanitize=unreachable With this option, the compiler will turn the @code{__builtin_unreachable} call into a diagnostics message call instead. When reaching the @code{__builtin_unreachable} call, the behavior is undefined. -@item @option{-fsanitize=vla-bound} +@item -fsanitize=vla-bound +@opindex fsanitize=vla-bound This option instructs the compiler to check that the size of a variable length array is positive. This option does not have any effect in @option{-std=c++1y} mode, as the standard requires the exception be thrown instead. -@item @option{-fsanitize=null} +@item -fsanitize=null +@opindex fsanitize=null This option enables pointer checking. Particularly, the application built with this option turned on will issue an error message when it tries to dereference a NULL pointer, or if a reference (possibly an rvalue reference) is bound to a NULL pointer. -@end itemize +@item -fsanitize=return +@opindex fsanitize=return + +This option enables return statement checking. Programs +built with this option turned on will issue an error message +when the end of a non-void function is reached without actually +returning a value. This option works in C++ only. + +@end table While @option{-ftrapv} causes traps for signed overflows to be emitted, @option{-fsanitize=undefined} gives a diagnostic message. @@ -5368,6 +5425,7 @@ information about each symbol. This option only makes sense when generating DWARF 2 debugging information with @option{-gdwarf-2}. @item -femit-struct-debug-baseonly +@opindex femit-struct-debug-baseonly Emit debug information for struct-like types only when the base name of the compilation source file matches the base name of file in which the struct is defined. @@ -5380,6 +5438,7 @@ See @option{-femit-struct-debug-detailed} for more detailed control. This option works only with DWARF 2. @item -femit-struct-debug-reduced +@opindex femit-struct-debug-reduced Emit debug information for struct-like types only when the base name of the compilation source file matches the base name of file in which the type is defined, @@ -5710,6 +5769,7 @@ Here are some examples showing uses of these options. @itemx -fdump-rtl-@var{pass} @itemx -fdump-rtl-@var{pass}=@var{filename} @opindex d +@opindex fdump-rtl-@var{pass} Says to make debugging dumps during compilation at times specified by @var{letters}. This is used for debugging the RTL-based passes of the compiler. The file names for most of the dumps are made by appending @@ -7998,6 +8058,7 @@ variable names which more closely resemble the original variables. This flag is enabled by default at @option{-O} and higher. @item -ftree-coalesce-inlined-vars +@opindex ftree-coalesce-inlined-vars Tell the copyrename pass (see @option{-ftree-copyrename}) to attempt to combine small user-defined variables too, but only if they were inlined from other functions. It is a more limited form of @@ -8008,6 +8069,7 @@ contain the expected values in a debugging session. This was the default in GCC versions older than 4.7. @item -ftree-coalesce-vars +@opindex ftree-coalesce-vars Tell the copyrename pass (see @option{-ftree-copyrename}) to attempt to combine small user-defined variables too, instead of just compiler temporaries. This may severely limit the ability to debug an optimized @@ -8060,6 +8122,14 @@ is equal to the @code{dynamic} model. The default cost model depends on other optimization flags and is either @code{dynamic} or @code{cheap}. +@item -fsimd-cost-model=@var{model} +@opindex fsimd-cost-model +Alter the cost model used for vectorization of loops marked with the OpenMP +or Cilk Plus simd directive. The @var{model} argument should be one of +@code{unlimited}, @code{dynamic}, @code{cheap}. All values of @var{model} +have the same meaning as described in @option{-fvect-cost-model} and by +default a cost model defined with @option{-fvect-cost-model} is used. + @item -ftree-vrp @opindex ftree-vrp Perform Value Range Propagation on trees. This is similar to the @@ -8651,9 +8721,11 @@ the comparison operation before register allocation is complete. Enabled at levels @option{-O}, @option{-O2}, @option{-O3}, @option{-Os}. @item -fuse-ld=bfd +@opindex fuse-ld=bfd Use the @command{bfd} linker instead of the default linker. @item -fuse-ld=gold +@opindex fuse-ld=gold Use the @command{gold} linker instead of the default linker. @item -fcprop-registers @@ -10210,6 +10282,7 @@ for the languages used in the program, or using the option @file{libgcc}. @item -static-libasan +@opindex static-libasan When the @option{-fsanitize=address} option is used to link a program, the GCC driver automatically links against @option{libasan}. If @file{libasan} is available as a shared library, and the @option{-static} @@ -10219,6 +10292,7 @@ driver to link @file{libasan} statically, without necessarily linking other libraries statically. @item -static-libtsan +@opindex static-libtsan When the @option{-fsanitize=thread} option is used to link a program, the GCC driver automatically links against @option{libtsan}. If @file{libtsan} is available as a shared library, and the @option{-static} @@ -10227,7 +10301,18 @@ option is not used, then this links against the shared version of driver to link @file{libtsan} statically, without necessarily linking other libraries statically. +@item -static-liblsan +@opindex static-liblsan +When the @option{-fsanitize=leak} option is used to link a program, +the GCC driver automatically links against @option{liblsan}. If +@file{liblsan} is available as a shared library, and the @option{-static} +option is not used, then this links against the shared version of +@file{liblsan}. The @option{-static-liblsan} option directs the GCC +driver to link @file{liblsan} statically, without necessarily linking +other libraries statically. + @item -static-libubsan +@opindex static-libubsan When the @option{-fsanitize=undefined} option is used to link a program, the GCC driver automatically links against @option{libubsan}. If @file{libubsan} is available as a shared library, and the @option{-static} @@ -10237,6 +10322,7 @@ driver to link @file{libubsan} statically, without necessarily linking other libraries statically. @item -static-libstdc++ +@opindex static-libstdc++ When the @command{g++} program is used to link a C++ program, it normally automatically links against @option{libstdc++}. If @file{libstdc++} is available as a shared library, and the @@ -10329,6 +10415,7 @@ If you really need to change the search order for system directories, use the @option{-nostdinc} and/or @option{-isystem} options. @item -iplugindir=@var{dir} +@opindex iplugindir= Set the directory to search for plugins that are passed by @option{-fplugin=@var{name}} instead of @option{-fplugin=@var{path}/@var{name}.so}. This option is not meant @@ -11778,7 +11865,7 @@ Enable Rcw constraint handling - ccfsm condexec mostly depends on this. This is the default. @item -msize-level=@var{level} -@ opindex msize-level +@opindex msize-level Fine-tune size optimization with regards to instruction lengths and alignment. The recognized values for @var{level} are: @table @samp @@ -12196,8 +12283,11 @@ before execution begins. @item -mpic-register=@var{reg} @opindex mpic-register -Specify the register to be used for PIC addressing. The default is R10 -unless stack-checking is enabled, when R9 is used. +Specify the register to be used for PIC addressing. +For standard PIC base case, the default will be any suitable register +determined by compiler. For single PIC base case, the default is +@samp{R9} if target is EABI based or stack-checking is enabled, +otherwise the default is @samp{R10}. @item -mpic-data-is-text-relative @opindex mpic-data-is-text-relative @@ -12326,6 +12416,13 @@ Enables using Neon to handle scalar 64-bits operations. This is disabled by default since the cost of moving data from core registers to Neon is high. +@item -mslow-flash-data +@opindex mslow-flash-data +Assume loading data from flash is slower than fetching instruction. +Therefore literal load is minimized for better performance. +This option is only supported when compiling for ARMv7 M-profile and +off by default. + @item -mrestrict-it @opindex mrestrict-it Restricts generation of IT blocks to conform to the rules of ARMv8. @@ -14535,7 +14632,7 @@ instruction set support. @item slm Intel Silvermont CPU with 64-bit extensions, MOVBE, MMX, SSE, SSE2, SSE3, SSSE3, -SSE4.1, SSE4.2 and POPCNT instruction set support. +SSE4.1, SSE4.2, POPCNT, AES, PCLMUL and RDRND instruction set support. @item k6 AMD K6 CPU with MMX instruction set support. @@ -15038,8 +15135,6 @@ preferred alignment to @option{-mpreferred-stack-boundary=2}. @itemx -mrtm @itemx -mtbm @itemx -mno-tbm -@itemx -mmpx -@itemx -mno-mpx @opindex mmmx @opindex mno-mmx @opindex msse @@ -15049,7 +15144,7 @@ preferred alignment to @option{-mpreferred-stack-boundary=2}. These switches enable or disable the use of instructions in the MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, AVX, AVX2, AVX512F, AVX512PF, AVX512ER, AVX512CD, AES, PCLMUL, FSGSBASE, RDRND, F16C, FMA, SSE4A, FMA4, XOP, LWP, ABM, BMI, BMI2, -FXSR, XSAVE, XSAVEOPT, LZCNT, RTM, MPX or 3DNow!@: +FXSR, XSAVE, XSAVEOPT, LZCNT, RTM or 3DNow!@: extended instruction sets. These extensions are also available as built-in functions: see @ref{X86 Built-in Functions}, for details of the functions enabled and diff --git a/gcc/doc/rtl.texi b/gcc/doc/rtl.texi index 25659954ad3..a7e98af4a86 100644 --- a/gcc/doc/rtl.texi +++ b/gcc/doc/rtl.texi @@ -1295,12 +1295,6 @@ These modes stand for a complex number represented as a pair of integer values. The integer values are in @code{QImode}, @code{HImode}, @code{SImode}, @code{DImode}, @code{TImode}, and @code{OImode}, respectively. - -@findex BND32mode -@findex BND64mode -@item BND32mode BND64mode -These modes stand for bounds for pointer of 32 and 64 bit size respectively. -Mode size is double pointer mode size. @end table The machine description defines @code{Pmode} as a C macro which expands @@ -1388,12 +1382,6 @@ any @code{CC_MODE} modes listed in the @file{@var{machine}-modes.def}. @xref{Jump Patterns}, also see @ref{Condition Code}. -@findex MODE_POINTER_BOUNDS -@item MODE_POINTER_BOUNDS -Pointer bounds modes. Used to represent values of pointer bounds type. -Operations in these modes may be executed as NOPs depending on hardware -features and environment setup. - @findex MODE_RANDOM @item MODE_RANDOM This is a catchall mode class for modes which don't fit into the above diff --git a/gcc/doc/standards.texi b/gcc/doc/standards.texi index e8be08fb905..3c1f480f3de 100644 --- a/gcc/doc/standards.texi +++ b/gcc/doc/standards.texi @@ -85,8 +85,8 @@ as @dfn{AMD1}; the amended standard is sometimes known as @dfn{C94} or @option{-pedantic} to receive all required diagnostics). A new edition of the ISO C standard was published in 1999 as ISO/IEC -9899:1999, and is commonly known as @dfn{C99}. GCC has incomplete -support for this standard version; see +9899:1999, and is commonly known as @dfn{C99}. GCC has substantially +complete support for this standard version; see @uref{http://gcc.gnu.org/c99status.html} for details. To select this standard, use @option{-std=c99} or @option{-std=iso9899:1999}. (While in development, drafts of this standard version were referred to as @@ -97,8 +97,8 @@ Corrigenda published in 2001, 2004 and 2007. GCC does not support the uncorrected version. A fourth version of the C standard, known as @dfn{C11}, was published -in 2011 as ISO/IEC 9899:2011. GCC has limited incomplete support for -parts of this standard, enabled with @option{-std=c11} or +in 2011 as ISO/IEC 9899:2011. GCC has substantially complete support +for this standard, enabled with @option{-std=c11} or @option{-std=iso9899:2011}. (While in development, drafts of this standard version were referred to as @dfn{C1X}.) @@ -111,10 +111,9 @@ select an extended version of the C language explicitly with @option{-std=gnu90} (for C90 with GNU extensions), @option{-std=gnu99} (for C99 with GNU extensions) or @option{-std=gnu11} (for C11 with GNU extensions). The default, if no C language dialect -options are given, is @option{-std=gnu90}; this will change to -@option{-std=gnu99} or @option{-std=gnu11} in some future release when -the C99 or C11 support is -complete. Some features that are part of the C99 standard are +options are given, is @option{-std=gnu90}; this is intended to change +to @option{-std=gnu11} in some future release. Some features that are +part of the C99 standard are accepted as extensions in C90 mode, and some features that are part of the C11 standard are accepted as extensions in C90 and C99 modes. @@ -156,7 +155,7 @@ your own arrangements for linking and startup. GCC does not provide the library facilities required only of hosted implementations, nor yet all the facilities required by C99 of -freestanding implementations; to use the facilities of a hosted +freestanding implementations on all platforms; to use the facilities of a hosted environment, you will need to find them elsewhere (for example, in the GNU C library). @xref{Standard Libraries,,Standard Libraries}. diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 12b0724d308..f3775a95573 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -4338,13 +4338,6 @@ This hook returns the va_list type of the calling convention specified by The default version of this hook returns @code{va_list_type_node}. @end deftypefn -@deftypefn {Target Hook} tree TARGET_FN_ABI_VA_LIST_BOUNDS_SIZE (tree @var{fndecl}) -This hook returns size for @code{va_list} object in function specified -by @var{fndecl}. This hook is used by Pointer Bounds Checker to build bounds -for @code{va_list} object. Return @code{integer_zero_node} if no bounds -should be used (e.g. @code{va_list} is a scalar pointer to the stack). -@end deftypefn - @deftypefn {Target Hook} tree TARGET_CANONICAL_VA_LIST_TYPE (tree @var{type}) This hook returns the va_list type of the calling convention specified by the type of @var{type}. If @var{type} is not a valid va_list type, it returns @@ -5162,26 +5155,6 @@ defined, then define this hook to return @code{true} if Otherwise, you should not define this hook. @end deftypefn -@deftypefn {Target Hook} rtx TARGET_LOAD_BOUNDS_FOR_ARG (rtx @var{slot}, rtx @var{arg}, rtx @var{slot_no}) -This hook is used by expand pass to emit insn to load bounds of -@var{arg} passed in @var{slot}. Expand pass uses this hook in case -bounds of @var{arg} are not passed in register. If @var{slot} is a -memory, then bounds are loaded as for regular pointer loaded from -memory. If @var{slot} is not a memory then @var{slot_no} is an integer -constant holding number of the target dependent special slot which -should be used to obtain bounds. Hook returns RTX holding loaded bounds. -@end deftypefn - -@deftypefn {Target Hook} void TARGET_STORE_BOUNDS_FOR_ARG (rtx @var{arg}, rtx @var{slot}, rtx @var{bounds}, rtx @var{slot_no}) -This hook is used by expand pass to emit insns to store @var{bounds} of -@var{arg} passed in @var{slot}. Expand pass uses this hook in case -@var{bounds} of @var{arg} are not passed in register. If @var{slot} is a -memory, then @var{bounds} are stored as for regular pointer stored in -memory. If @var{slot} is not a memory then @var{slot_no} is an integer -constant holding number of the target dependent special slot which -should be used to store @var{bounds}. -@end deftypefn - @node Trampolines @section Trampolines for Nested Functions @cindex trampolines for nested functions @@ -5365,6 +5338,14 @@ If this macro evaluates to @code{false} the comparison functions return in @file{libgcc.a}, you do not need to define this macro. @end defmac +@defmac TARGET_HAS_NO_HW_DIVIDE +This macro should be defined if the target has no hardware divide +instructions. If this macro is defined, GCC will use an algorithm which +make use of simple logical and arithmetic operations for 64-bit +division. If the macro is not defined, GCC will use an algorithm which +make use of a 64-bit by 32-bit divide primitive. +@end defmac + @cindex @code{EDOM}, implicit usage @findex matherr @defmac TARGET_EDOM @@ -5818,6 +5799,26 @@ The default is @code{NULL_TREE} which means to not vectorize gather loads. @end deftypefn +@deftypefn {Target Hook} int TARGET_SIMD_CLONE_COMPUTE_VECSIZE_AND_SIMDLEN (struct cgraph_node *@var{}, struct cgraph_simd_clone *@var{}, @var{tree}, @var{int}) +This hook should set @var{vecsize_mangle}, @var{vecsize_int}, @var{vecsize_float} +fields in @var{simd_clone} structure pointed by @var{clone_info} argument and also +@var{simdlen} field if it was previously 0. +The hook should return 0 if SIMD clones shouldn't be emitted, +or number of @var{vecsize_mangle} variants that should be emitted. +@end deftypefn + +@deftypefn {Target Hook} void TARGET_SIMD_CLONE_ADJUST (struct cgraph_node *@var{}) +This hook should add implicit @code{attribute(target("..."))} attribute +to SIMD clone @var{node} if needed. +@end deftypefn + +@deftypefn {Target Hook} int TARGET_SIMD_CLONE_USABLE (struct cgraph_node *@var{}) +This hook should return -1 if SIMD clone @var{node} shouldn't be used +in vectorized loops in current function, or non-negative number if it is +usable. In that case, the smaller the number is, the more desirable it is +to use it. +@end deftypefn + @node Anchored Addresses @section Anchored Addresses @cindex anchored addresses @@ -10937,96 +10938,6 @@ ignored. This function should return the result of the call to the built-in function. @end deftypefn -@deftypefn {Target Hook} tree TARGET_BUILTIN_CHKP_FUNCTION (unsigned @var{fcode}) -This hook allows target to redefine built-in functions used by -Pointer Bounds Checker for code instrumentation. Hook should return -fndecl of function implementing generic builtin whose code is -passed in @var{fcode}. Currently following built-in functions are -obtained using this hook: -@deftypefn {Built-in Function} bnd __chkp_bndmk (const void *@var{lb}, size_t @var{size}) -Function code - BUILT_IN_CHKP_BNDMK. This built-in function is used -by Pointer Bounds Checker to create bound values. @var{lb} holds low -bound of the resulting bounds. @var{size} holds size of created bounds. -@end deftypefn - -@deftypefn {Built-in Function} void __chkp_bndstx (const void **@var{loc}, const void *@var{ptr}, bnd @var{b}) -Function code - @code{BUILT_IN_CHKP_BNDSTX}. This built-in function is used -by Pointer Bounds Checker to store bounds @var{b} for pointer @var{ptr} -stored by address @var{loc}. -@end deftypefn - -@deftypefn {Built-in Function} bnd __chkp_bndldx (const void **@var{loc}, const void *@var{ptr}) -Function code - @code{BUILT_IN_CHKP_BNDLDX}. This built-in function is used -by Pointer Bounds Checker to get bounds of pointer @var{ptr} loaded by -address @var{loc}. -@end deftypefn - -@deftypefn {Built-in Function} void __chkp_bndcl (bnd @var{b}, const void *@var{ptr}) -Function code - @code{BUILT_IN_CHKP_BNDCL}. This built-in function is used -by Pointer Bounds Checker to perform check for pointer @var{ptr} against -lower bound of bounds @var{b}. -@end deftypefn - -@deftypefn {Built-in Function} void __chkp_bndcu (bnd @var{b}, const void *@var{ptr}) -Function code - @code{BUILT_IN_CHKP_BNDCU}. This built-in function is used -by Pointer Bounds Checker to perform check for pointer @var{ptr} against -upper bound of bounds @var{b}. -@end deftypefn - -@deftypefn {Built-in Function} bnd __chkp_bndret (void *@var{ptr}) -Function code - @code{BUILT_IN_CHKP_BNDRET}. This built-in function is used -by Pointer Bounds Checker to obtain bounds returned by call statement. -@var{ptr} passed to buil-in is @code{SSA_NAME} returned by call. -@end deftypefn - -@deftypefn {Built-in Function} bnd __chkp_arg_bnd (void *@var{arg}) -Function code - @code{BUILT_IN_CHKP_ARG_BND}. This built-in function is -used by Pointer Bounds Checker to obtain bounds passed for input argument. -@var{arg} is default @code{SSA_NAME} of the @code{PARM_DECL} whose -bounds we want to obtain. -@end deftypefn - -@deftypefn {Built-in Function} bnd __chkp_intersect (bnd @var{b1}, bnd @var{b2}) -Function code - @code{BUILT_IN_CHKP_INTERSECT}. This built-in function -returns intersection of bounds @var{b1} and @var{b2}. -@end deftypefn - -@deftypefn {Built-in Function} bnd __chkp_narrow (const void *@var{ptr}, bnd @var{b}, size_t @var{s}) -Function code - @code{BUILT_IN_CHKP_NARROW}. This built-in function -returns intersection of bounds @var{b} and -[@var{ptr}, @var{ptr} + @var{s} - @code{1}]. -@end deftypefn - -@deftypefn {Built-in Function} void *__chkp_set_bounds (const void *@var{ptr}, size_t @var{s}) -Function code - @code{BUILT_IN_CHKP_SET_PTR_BOUNDS}. This built-in function -returns @var{ptr} with bounds [@var{ptr}, @var{ptr} + @var{s} - @code{1}]. -@end deftypefn - -@deftypefn {Built-in Function} size_t __chkp_sizeof (const void *@var{ptr}) -Function code - @code{BUILT_IN_CHKP_SIZEOF}. This built-in function -returns size of object referenced by @var{ptr}. @var{ptr} is always -@code{ADDR_EXPR} of @code{VAR_DECL}. This built-in is used by -Pointer Boudns Checker when bounds of object cannot be computed statically -(e.g. object has incomplete type). -@end deftypefn - -@deftypefn {Built-in Function} const void *__chkp_extract_lower (bnd @var{b}) -Function code - @code{BUILT_IN_CHKP_EXTRACT_LOWER}. This built-in function -returns lower bound of bounds @var{b}. -@end deftypefn - -@deftypefn {Built-in Function} const void *__chkp_extract_upper (bnd @var{b}) -Function code - @code{BUILT_IN_CHKP_EXTRACT_UPPER}. This built-in function -returns upper bound of bounds @var{b}. -@end deftypefn -@end deftypefn -@deftypefn {Target Hook} tree TARGET_CHKP_BOUND_TYPE (void) -Return type to be used for bounds -@end deftypefn -@deftypefn {Target Hook} {enum machine_mode} TARGET_CHKP_BOUND_MODE (void) -Return mode to be used for bounds. -@end deftypefn - @deftypefn {Target Hook} tree TARGET_RESOLVE_OVERLOADED_BUILTIN (unsigned int @var{loc}, tree @var{fndecl}, void *@var{arglist}) Select a replacement for a machine specific built-in function that was set up by @samp{TARGET_INIT_BUILTINS}. This is done @@ -11488,6 +11399,10 @@ The support includes the assembler, linker and dynamic linker. The default value of this hook is based on target's libc. @end deftypefn +@deftypefn {Target Hook} {unsigned int} TARGET_ATOMIC_ALIGN_FOR_MODE (enum machine_mode @var{mode}) +If defined, this function returns an appropriate alignment in bits for an atomic object of machine_mode @var{mode}. If 0 is returned then the default alignment for the specified mode is used. +@end deftypefn + @deftypefn {Target Hook} void TARGET_ATOMIC_ASSIGN_EXPAND_FENV (tree *@var{hold}, tree *@var{clear}, tree *@var{update}) ISO C11 requires atomic compound assignments that may raise floating-point exceptions to raise exceptions corresponding to the arithmetic operation whose result was successfully stored in a compare-and-exchange sequence. This requires code equivalent to calls to @code{feholdexcept}, @code{feclearexcept} and @code{feupdateenv} to be generated at appropriate points in the compare-and-exchange sequence. This hook should set @code{*@var{hold}} to an expression equivalent to the call to @code{feholdexcept}, @code{*@var{clear}} to an expression equivalent to the call to @code{feclearexcept} and @code{*@var{update}} to an expression equivalent to the call to @code{feupdateenv}. The three expressions are @code{NULL_TREE} on entry to the hook and may be left as @code{NULL_TREE} if no code is required in a particular place. The default implementation leaves all three expressions as @code{NULL_TREE}. The @code{__atomic_feraiseexcept} function from @code{libatomic} may be of use as part of the code generated in @code{*@var{update}}. @end deftypefn diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index 55e96bbef4f..3d6a9d03dc1 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -3696,8 +3696,6 @@ stack. @hook TARGET_FN_ABI_VA_LIST -@hook TARGET_FN_ABI_VA_LIST_BOUNDS_SIZE - @hook TARGET_CANONICAL_VA_LIST_TYPE @hook TARGET_GIMPLIFY_VA_ARG_EXPR @@ -4068,10 +4066,6 @@ These machine description macros help implement varargs: @hook TARGET_PRETEND_OUTGOING_VARARGS_NAMED -@hook TARGET_LOAD_BOUNDS_FOR_ARG - -@hook TARGET_STORE_BOUNDS_FOR_ARG - @node Trampolines @section Trampolines for Nested Functions @cindex trampolines for nested functions @@ -4205,6 +4199,14 @@ If this macro evaluates to @code{false} the comparison functions return in @file{libgcc.a}, you do not need to define this macro. @end defmac +@defmac TARGET_HAS_NO_HW_DIVIDE +This macro should be defined if the target has no hardware divide +instructions. If this macro is defined, GCC will use an algorithm which +make use of simple logical and arithmetic operations for 64-bit +division. If the macro is not defined, GCC will use an algorithm which +make use of a 64-bit by 32-bit divide primitive. +@end defmac + @cindex @code{EDOM}, implicit usage @findex matherr @defmac TARGET_EDOM @@ -4422,6 +4424,12 @@ address; but often a machine-dependent strategy can generate better code. @hook TARGET_VECTORIZE_BUILTIN_GATHER +@hook TARGET_SIMD_CLONE_COMPUTE_VECSIZE_AND_SIMDLEN + +@hook TARGET_SIMD_CLONE_ADJUST + +@hook TARGET_SIMD_CLONE_USABLE + @node Anchored Addresses @section Anchored Addresses @cindex anchored addresses @@ -8184,10 +8192,6 @@ to by @var{ce_info}. @hook TARGET_EXPAND_BUILTIN -@hook TARGET_BUILTIN_CHKP_FUNCTION -@hook TARGET_CHKP_BOUND_TYPE -@hook TARGET_CHKP_BOUND_MODE - @hook TARGET_RESOLVE_OVERLOADED_BUILTIN @hook TARGET_FOLD_BUILTIN @@ -8395,6 +8399,8 @@ and the associated definitions of those functions. @hook TARGET_HAS_IFUNC_P +@hook TARGET_ATOMIC_ALIGN_FOR_MODE + @hook TARGET_ATOMIC_ASSIGN_EXPAND_FENV @defmac TARGET_SUPPORTS_WIDE_INT diff --git a/gcc/dojump.c b/gcc/dojump.c index 51c3c8ce26a..bb99df37816 100644 --- a/gcc/dojump.c +++ b/gcc/dojump.c @@ -96,6 +96,29 @@ do_pending_stack_adjust (void) pending_stack_adjust = 0; } } + +/* Remember pending_stack_adjust/stack_pointer_delta. + To be used around code that may call do_pending_stack_adjust (), + but the generated code could be discarded e.g. using delete_insns_since. */ + +void +save_pending_stack_adjust (saved_pending_stack_adjust *save) +{ + save->x_pending_stack_adjust = pending_stack_adjust; + save->x_stack_pointer_delta = stack_pointer_delta; +} + +/* Restore the saved pending_stack_adjust/stack_pointer_delta. */ + +void +restore_pending_stack_adjust (saved_pending_stack_adjust *save) +{ + if (inhibit_defer_pop == 0) + { + pending_stack_adjust = save->x_pending_stack_adjust; + stack_pointer_delta = save->x_stack_pointer_delta; + } +} /* Expand conditional expressions. */ diff --git a/gcc/dse.c b/gcc/dse.c index 6584ea35bbe..2d8ce1e4d78 100644 --- a/gcc/dse.c +++ b/gcc/dse.c @@ -47,6 +47,11 @@ along with GCC; see the file COPYING3. If not see #include "dbgcnt.h" #include "target.h" #include "params.h" +#include "pointer-set.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-ssa.h" diff --git a/gcc/dwarf2cfi.c b/gcc/dwarf2cfi.c index 19276e23a20..b8e25bc9964 100644 --- a/gcc/dwarf2cfi.c +++ b/gcc/dwarf2cfi.c @@ -906,6 +906,7 @@ notice_eh_throw (rtx insn) static inline unsigned dwf_regno (const_rtx reg) { + gcc_assert (REGNO (reg) < FIRST_PSEUDO_REGISTER); return DWARF_FRAME_REGNUM (REGNO (reg)); } diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index d722f4c6cd8..e9588edd447 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -66,7 +66,7 @@ along with GCC; see the file COPYING3. If not see #include "varasm.h" #include "function.h" #include "emit-rtl.h" -#include "gimple.h" +#include "hash-table.h" #include "version.h" #include "flags.h" #include "hard-reg-set.h" @@ -81,7 +81,6 @@ along with GCC; see the file COPYING3. If not see #include "dwarf2out.h" #include "dwarf2asm.h" #include "toplev.h" -#include "ggc.h" #include "md5.h" #include "tm_p.h" #include "diagnostic.h" @@ -90,7 +89,6 @@ along with GCC; see the file COPYING3. If not see #include "target.h" #include "common/common-target.h" #include "langhooks.h" -#include "hash-table.h" #include "cgraph.h" #include "input.h" #include "ira.h" @@ -9429,7 +9427,7 @@ output_pubnames (vec<pubname_entry, va_gc> *names) if (type_node != NULL) die_offset = (type_node->skeleton_die != NULL ? type_node->skeleton_die->die_offset - : 0); + : comp_unit_die ()->die_offset); } output_pubname (die_offset, pub); @@ -18462,7 +18460,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die) gen_formal_parameter_pack_die (generic_decl_parm, parm, subr_die, &parm); - else if (parm && !POINTER_BOUNDS_P (parm)) + else if (parm) { dw_die_ref parm_die = gen_decl_die (parm, NULL, subr_die); @@ -18474,8 +18472,6 @@ gen_subprogram_die (tree decl, dw_die_ref context_die) parm = DECL_CHAIN (parm); } - else if (parm) - parm = DECL_CHAIN (parm); if (generic_decl_parm) generic_decl_parm = DECL_CHAIN (generic_decl_parm); @@ -19973,7 +19969,6 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die, case FIXED_POINT_TYPE: case COMPLEX_TYPE: case BOOLEAN_TYPE: - case POINTER_BOUNDS_TYPE: /* No DIEs needed for fundamental types. */ break; @@ -20624,8 +20619,7 @@ dwarf2out_global_decl (tree decl) declarations, file-scope (extern) function declarations (which had no corresponding body) and file-scope tagged type declarations and definitions which have not yet been forced out. */ - if ((TREE_CODE (decl) != FUNCTION_DECL || !DECL_INITIAL (decl)) - && !POINTER_BOUNDS_P (decl)) + if (TREE_CODE (decl) != FUNCTION_DECL || !DECL_INITIAL (decl)) dwarf2out_decl (decl); } diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index c3d4f21a43b..96984ac1ea9 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -39,7 +39,8 @@ along with GCC; see the file COPYING3. If not see #include "rtl.h" #include "tree.h" #include "varasm.h" -#include "gimple.h" +#include "basic-block.h" +#include "tree-eh.h" #include "tm_p.h" #include "flags.h" #include "function.h" @@ -51,14 +52,11 @@ along with GCC; see the file COPYING3. If not see #include "insn-config.h" #include "recog.h" #include "bitmap.h" -#include "basic-block.h" -#include "ggc.h" #include "debug.h" #include "langhooks.h" #include "df.h" #include "params.h" #include "target.h" -#include "tree-eh.h" struct target_rtl default_target_rtl; #if SWITCHABLE_TARGET diff --git a/gcc/except.c b/gcc/except.c index f7dc193ce47..e4b8cad06af 100644 --- a/gcc/except.c +++ b/gcc/except.c @@ -124,7 +124,6 @@ along with GCC; see the file COPYING3. If not see #include "insn-config.h" #include "except.h" #include "hard-reg-set.h" -#include "basic-block.h" #include "output.h" #include "dwarf2asm.h" #include "dwarf2out.h" @@ -132,7 +131,6 @@ along with GCC; see the file COPYING3. If not see #include "toplev.h" #include "hash-table.h" #include "intl.h" -#include "ggc.h" #include "tm_p.h" #include "target.h" #include "common/common-target.h" @@ -141,7 +139,7 @@ along with GCC; see the file COPYING3. If not see #include "diagnostic.h" #include "tree-pretty-print.h" #include "tree-pass.h" -#include "gimple.h" +#include "pointer-set.h" #include "cfgloop.h" /* Provide defaults for stuff that may not be defined when using diff --git a/gcc/exec-tool.in b/gcc/exec-tool.in index 6722ce52030..76d0ef65ab1 100644 --- a/gcc/exec-tool.in +++ b/gcc/exec-tool.in @@ -21,6 +21,8 @@ ORIGINAL_AS_FOR_TARGET="@ORIGINAL_AS_FOR_TARGET@" ORIGINAL_LD_FOR_TARGET="@ORIGINAL_LD_FOR_TARGET@" +ORIGINAL_LD_BFD_FOR_TARGET="@ORIGINAL_LD_BFD_FOR_TARGET@" +ORIGINAL_LD_GOLD_FOR_TARGET="@ORIGINAL_LD_GOLD_FOR_TARGET@" ORIGINAL_PLUGIN_LD_FOR_TARGET="@ORIGINAL_PLUGIN_LD_FOR_TARGET@" ORIGINAL_NM_FOR_TARGET="@ORIGINAL_NM_FOR_TARGET@" exeext=@host_exeext@ @@ -36,15 +38,32 @@ case "$invoked" in dir=gas ;; collect-ld) - # when using a linker plugin, gcc will always pass '-plugin' as the - # first or second option to the linker. - if test x"$1" = "x-plugin" || test x"$2" = "x-plugin"; then - original=$ORIGINAL_PLUGIN_LD_FOR_TARGET + # Check -fuse-ld=bfd and -fuse-ld=gold + case " $* " in + *\ -fuse-ld=bfd\ *) + original=$ORIGINAL_LD_BFD_FOR_TARGET + ;; + *\ -fuse-ld=gold\ *) + original=$ORIGINAL_LD_GOLD_FOR_TARGET + ;; + *) + # when using a linker plugin, gcc will always pass '-plugin' as the + # first or second option to the linker. + if test x"$1" = "x-plugin" || test x"$2" = "x-plugin"; then + original=$ORIGINAL_PLUGIN_LD_FOR_TARGET + else + original=$ORIGINAL_LD_FOR_TARGET + fi + ;; + esac + prog=ld-new$exeext + if test "$original" = ../gold/ld-new$exeext; then + dir=gold + # No need to handle relink since gold doesn't use libtool. + fast_install=yes else - original=$ORIGINAL_LD_FOR_TARGET + dir=ld fi - prog=ld-new$exeext - dir=ld id=ld ;; nm) diff --git a/gcc/expmed.c b/gcc/expmed.c index 8c13687ff41..deb78962938 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -3689,11 +3689,6 @@ expand_sdiv_pow2 (enum machine_mode mode, rtx op0, HOST_WIDE_INT d) { rtx temp2; - /* ??? emit_conditional_move forces a stack adjustment via - compare_from_rtx so, if the sequence is discarded, it will - be lost. Do it now instead. */ - do_pending_stack_adjust (); - start_sequence (); temp2 = copy_to_mode_reg (mode, op0); temp = expand_binop (mode, add_optab, temp2, gen_int_mode (d - 1, mode), diff --git a/gcc/expr.c b/gcc/expr.c index ec6391d29b0..cded0bd521a 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -47,6 +47,11 @@ along with GCC; see the file COPYING3. If not see #include "intl.h" #include "tm_p.h" #include "tree-iterator.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-ssa.h" #include "cgraph.h" @@ -2026,12 +2031,14 @@ emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, int ssize) HOST_WIDE_INT bytepos = INTVAL (XEXP (XVECEXP (src, 0, i), 1)); enum machine_mode mode = GET_MODE (tmps[i]); unsigned int bytelen = GET_MODE_SIZE (mode); - unsigned int adj_bytelen = bytelen; + unsigned int adj_bytelen; rtx dest = dst; /* Handle trailing fragments that run over the size of the struct. */ if (ssize >= 0 && bytepos + (HOST_WIDE_INT) bytelen > ssize) adj_bytelen = ssize - bytepos; + else + adj_bytelen = bytelen; if (GET_CODE (dst) == CONCAT) { @@ -2072,6 +2079,7 @@ emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, int ssize) } } + /* Handle trailing fragments that run over the size of the struct. */ if (ssize >= 0 && bytepos + (HOST_WIDE_INT) bytelen > ssize) { /* store_bit_field always takes its value from the lsb. @@ -2089,16 +2097,22 @@ emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, int ssize) tmps[i] = expand_shift (RSHIFT_EXPR, mode, tmps[i], shift, tmps[i], 0); } - bytelen = adj_bytelen; + + /* Make sure not to write past the end of the struct. */ + store_bit_field (dest, + adj_bytelen * BITS_PER_UNIT, bytepos * BITS_PER_UNIT, + bytepos * BITS_PER_UNIT, ssize * BITS_PER_UNIT - 1, + VOIDmode, tmps[i]); } /* Optimize the access just a bit. */ - if (MEM_P (dest) - && (! SLOW_UNALIGNED_ACCESS (mode, MEM_ALIGN (dest)) - || MEM_ALIGN (dest) >= GET_MODE_ALIGNMENT (mode)) - && bytepos * BITS_PER_UNIT % GET_MODE_ALIGNMENT (mode) == 0 - && bytelen == GET_MODE_SIZE (mode)) + else if (MEM_P (dest) + && (!SLOW_UNALIGNED_ACCESS (mode, MEM_ALIGN (dest)) + || MEM_ALIGN (dest) >= GET_MODE_ALIGNMENT (mode)) + && bytepos * BITS_PER_UNIT % GET_MODE_ALIGNMENT (mode) == 0 + && bytelen == GET_MODE_SIZE (mode)) emit_move_insn (adjust_address (dest, mode, bytepos), tmps[i]); + else store_bit_field (dest, bytelen * BITS_PER_UNIT, bytepos * BITS_PER_UNIT, 0, 0, mode, tmps[i]); @@ -4741,8 +4755,7 @@ expand_assignment (tree to, tree from, bool nontemporal) expand_insn (icode, 2, ops); } else - store_bit_field (mem, GET_MODE_BITSIZE (mode), - 0, 0, 0, mode, reg); + store_bit_field (mem, GET_MODE_BITSIZE (mode), 0, 0, 0, mode, reg); return; } @@ -4781,6 +4794,17 @@ expand_assignment (tree to, tree from, bool nontemporal) if (TREE_CODE (to) == COMPONENT_REF && DECL_BIT_FIELD_TYPE (TREE_OPERAND (to, 1))) get_bit_range (&bitregion_start, &bitregion_end, to, &bitpos, &offset); + /* The C++ memory model naturally applies to byte-aligned fields. + However, if we do not have a DECL_BIT_FIELD_TYPE but BITPOS or + BITSIZE are not byte-aligned, there is no need to limit the range + we can access. This can occur with packed structures in Ada. */ + else if (bitsize > 0 + && bitsize % BITS_PER_UNIT == 0 + && bitpos % BITS_PER_UNIT == 0) + { + bitregion_start = bitpos; + bitregion_end = bitpos + bitsize - 1; + } to_rtx = expand_expr (tem, NULL_RTX, VOIDmode, EXPAND_WRITE); @@ -8751,12 +8775,6 @@ expand_expr_real_2 (sepops ops, rtx target, enum machine_mode tmode, { rtx insn; - /* ??? Same problem as in expmed.c: emit_conditional_move - forces a stack adjustment via compare_from_rtx, and we - lose the stack adjustment if the sequence we are about - to create is discarded. */ - do_pending_stack_adjust (); - start_sequence (); /* Try to emit the conditional move. */ diff --git a/gcc/expr.h b/gcc/expr.h index a2cd6690bfe..e734ef44016 100644 --- a/gcc/expr.h +++ b/gcc/expr.h @@ -473,6 +473,28 @@ extern void clear_pending_stack_adjust (void); /* Pop any previously-pushed arguments that have not been popped yet. */ extern void do_pending_stack_adjust (void); +/* Struct for saving/restoring of pending_stack_adjust/stack_pointer_delta + values. */ + +struct saved_pending_stack_adjust +{ + /* Saved value of pending_stack_adjust. */ + int x_pending_stack_adjust; + + /* Saved value of stack_pointer_delta. */ + int x_stack_pointer_delta; +}; + +/* Remember pending_stack_adjust/stack_pointer_delta. + To be used around code that may call do_pending_stack_adjust (), + but the generated code could be discarded e.g. using delete_insns_since. */ + +extern void save_pending_stack_adjust (saved_pending_stack_adjust *); + +/* Restore the saved pending_stack_adjust/stack_pointer_delta. */ + +extern void restore_pending_stack_adjust (saved_pending_stack_adjust *); + /* Return the tree node and offset if a given argument corresponds to a string constant. */ extern tree string_constant (tree, tree *); diff --git a/gcc/flag-types.h b/gcc/flag-types.h index 528c88a370c..5ba909766fe 100644 --- a/gcc/flag-types.h +++ b/gcc/flag-types.h @@ -206,14 +206,17 @@ enum sanitize_code { SANITIZE_ADDRESS = 1 << 0, /* ThreadSanitizer. */ SANITIZE_THREAD = 1 << 1, + /* LeakSanitizer. */ + SANITIZE_LEAK = 1 << 2, /* UndefinedBehaviorSanitizer. */ - SANITIZE_SHIFT = 1 << 2, - SANITIZE_DIVIDE = 1 << 3, - SANITIZE_UNREACHABLE = 1 << 4, - SANITIZE_VLA = 1 << 5, - SANITIZE_NULL = 1 << 6, + SANITIZE_SHIFT = 1 << 3, + SANITIZE_DIVIDE = 1 << 4, + SANITIZE_UNREACHABLE = 1 << 5, + SANITIZE_VLA = 1 << 6, + SANITIZE_NULL = 1 << 7, + SANITIZE_RETURN = 1 << 8, SANITIZE_UNDEFINED = SANITIZE_SHIFT | SANITIZE_DIVIDE | SANITIZE_UNREACHABLE - | SANITIZE_VLA | SANITIZE_NULL + | SANITIZE_VLA | SANITIZE_NULL | SANITIZE_RETURN }; /* flag_vtable_verify initialization levels. */ diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 5f8b05dbe12..7ea6470ac99 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -56,13 +56,18 @@ along with GCC; see the file COPYING3. If not see #include "target.h" #include "diagnostic-core.h" #include "intl.h" -#include "ggc.h" -#include "hash-table.h" #include "langhooks.h" #include "md5.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "tree-dfa.h" +#include "hash-table.h" /* Required for ENABLE_FOLD_CHECKING. */ /* Nonzero if we are folding constants inside an initializer; zero otherwise. */ @@ -16528,7 +16533,7 @@ fold_indirect_ref_1 (location_t loc, tree type, tree op0) unsigned HOST_WIDE_INT indexi = offset * BITS_PER_UNIT; tree index = bitsize_int (indexi); - if (offset/part_widthi <= TYPE_VECTOR_SUBPARTS (op00type)) + if (offset / part_widthi < TYPE_VECTOR_SUBPARTS (op00type)) return fold_build3_loc (loc, BIT_FIELD_REF, type, op00, part_width, index); diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 26e58bef0f0..a92561cf565 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,54 @@ +2013-12-01 Paul Thomas <pault@gcc.gnu.org> + + PR fortran/57354 + * trans-array.c (gfc_conv_resolve_dependencies): For other than + SS_SECTION, do a dependency check if the lhs is liable to be + reallocated. + +2013-12-01 Paul Thomas <pault@gcc.gnu.org> + + PR fortran/58410 + * trans-array.c (gfc_alloc_allocatable_for_assignment): Do not + use the array bounds of an unallocated array but set its size + to zero instead. + +2013-12-01 Paul Thomas <pault@gcc.gnu.org> + + PR fortran/34547 + * resolve.c (resolve_transfer): EXPR_NULL is always in an + invalid context in a transfer statement. + +2013-11-28 Sergey Ostanevich <sergos.gnu@gmail.com> + + * lang.opt (Wopenmp-simd): New. + +2013-11-25 Janus Weil <janus@gcc.gnu.org> + + PR fortran/59143 + * interface.c (get_expr_storage_size): Handle array-valued type-bound + procedures. + +2013-11-24 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> + + * scanner.c (gfc_open_intrinsic_module): Remove function. + * gfortran.h (gfc_open_intrinsic_module): Remove prototype. + +2013-11-23 Janus Weil <janus@gcc.gnu.org> + + PR fortran/59228 + * interface.c (compare_parameter): Check for array spec. + +2013-11-22 Andrew MacLeod <amacleod@redhat.com> + + * trans.c: Add required include files from gimple.h. + * trans-expr.c: Likewise + * trans-openmp.c: Likewise + +2013-11-22 David Malcolm <dmalcolm@redhat.com> + + * trans.c (trans_runtime_error_vararg): Remove use of input_line + macro. + 2013-11-17 Andrew MacLeod <amacleod@redhat.com> * fortran/trans-intrinsic.c: Include tree-nested.h. diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index af5e68c13ab..ff3ffb5a1c3 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -2397,7 +2397,6 @@ void gfc_add_include_path (const char *, bool, bool, bool); void gfc_add_intrinsic_modules_path (const char *); void gfc_release_include_path (void); FILE *gfc_open_included_file (const char *, bool, bool); -FILE *gfc_open_intrinsic_module (const char *); int gfc_at_end (void); int gfc_at_eof (void); diff --git a/gcc/fortran/interface.c b/gcc/fortran/interface.c index 0504c904b96..da3db7e096c 100644 --- a/gcc/fortran/interface.c +++ b/gcc/fortran/interface.c @@ -2092,7 +2092,7 @@ compare_parameter (gfc_symbol *formal, gfc_expr *actual, && (actual->symtree->n.sym->attr.asynchronous || actual->symtree->n.sym->attr.volatile_) && (formal->attr.asynchronous || formal->attr.volatile_) - && actual->rank && !gfc_is_simply_contiguous (actual, true) + && actual->rank && formal->as && !gfc_is_simply_contiguous (actual, true) && ((formal->as->type != AS_ASSUMED_SHAPE && formal->as->type != AS_ASSUMED_RANK && !formal->attr.pointer) || formal->attr.contiguous)) @@ -2426,6 +2426,24 @@ get_expr_storage_size (gfc_expr *e) - mpz_get_si (ref->u.ar.as->lower[i]->value.integer)); } } + else if (ref->type == REF_COMPONENT && ref->u.c.component->attr.function + && ref->u.c.component->attr.proc_pointer + && ref->u.c.component->attr.dimension) + { + /* Array-valued procedure-pointer components. */ + gfc_array_spec *as = ref->u.c.component->as; + for (i = 0; i < as->rank; i++) + { + if (!as->upper[i] || !as->lower[i] + || as->upper[i]->expr_type != EXPR_CONSTANT + || as->lower[i]->expr_type != EXPR_CONSTANT) + return 0; + + elements = elements + * (mpz_get_si (as->upper[i]->value.integer) + - mpz_get_si (as->lower[i]->value.integer) + 1L); + } + } } if (substrlen) diff --git a/gcc/fortran/lang.opt b/gcc/fortran/lang.opt index 5e09cbd1459..0d328c84a63 100644 --- a/gcc/fortran/lang.opt +++ b/gcc/fortran/lang.opt @@ -257,6 +257,10 @@ Wintrinsics-std Fortran Warning Warn on intrinsics not part of the selected standard +Wopenmp-simd +Fortran +; Documented in C + Wreal-q-constant Fortran Warning Warn about real-literal-constants with 'q' exponent-letter diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c index 4befb9fdda4..d16347d034e 100644 --- a/gcc/fortran/resolve.c +++ b/gcc/fortran/resolve.c @@ -8247,10 +8247,11 @@ resolve_transfer (gfc_code *code) && exp->value.op.op == INTRINSIC_PARENTHESES) exp = exp->value.op.op1; - if (exp && exp->expr_type == EXPR_NULL && exp->ts.type == BT_UNKNOWN) + if (exp && exp->expr_type == EXPR_NULL + && code->ext.dt) { - gfc_error ("NULL intrinsic at %L in data transfer statement requires " - "MOLD=", &exp->where); + gfc_error ("Invalid context for NULL () intrinsic at %L", + &exp->where); return; } diff --git a/gcc/fortran/scanner.c b/gcc/fortran/scanner.c index 882e2d5e06f..e0650ba7ee0 100644 --- a/gcc/fortran/scanner.c +++ b/gcc/fortran/scanner.c @@ -465,24 +465,6 @@ gfc_open_included_file (const char *name, bool include_cwd, bool module) return f; } -FILE * -gfc_open_intrinsic_module (const char *name) -{ - FILE *f = NULL; - - if (IS_ABSOLUTE_PATH (name)) - { - f = gfc_open_file (name); - if (f && gfc_cpp_makedep ()) - gfc_cpp_add_dep (name, true); - } - - if (!f) - f = open_included_file (name, intrinsic_modules_dirs, true, true); - - return f; -} - /* Test to see if we're at the end of the main source file. */ diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c index 5b3cd1f6eb1..fc7ed1b2f0c 100644 --- a/gcc/fortran/trans-array.c +++ b/gcc/fortran/trans-array.c @@ -4336,10 +4336,18 @@ gfc_conv_resolve_dependencies (gfc_loopinfo * loop, gfc_ss * dest, for (ss = rss; ss != gfc_ss_terminator; ss = ss->next) { + ss_expr = ss->info->expr; + if (ss->info->type != GFC_SS_SECTION) - continue; + { + if (gfc_option.flag_realloc_lhs + && dest_expr != ss_expr + && gfc_is_reallocatable_lhs (dest_expr) + && ss_expr->rank) + nDepend = gfc_check_dependency (dest_expr, ss_expr, true); - ss_expr = ss->info->expr; + continue; + } if (dest_expr->symtree->n.sym != ss_expr->symtree->n.sym) { @@ -8061,6 +8069,7 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop, tree size1; tree size2; tree array1; + tree cond_null; tree cond; tree tmp; tree tmp2; @@ -8136,9 +8145,9 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop, jump_label2 = gfc_build_label_decl (NULL_TREE); /* Allocate if data is NULL. */ - cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, + cond_null = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, array1, build_int_cst (TREE_TYPE (array1), 0)); - tmp = build3_v (COND_EXPR, cond, + tmp = build3_v (COND_EXPR, cond_null, build1_v (GOTO_EXPR, jump_label1), build_empty_stmt (input_location)); gfc_add_expr_to_block (&fblock, tmp); @@ -8190,13 +8199,25 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop, tmp = build1_v (LABEL_EXPR, jump_label1); gfc_add_expr_to_block (&fblock, tmp); - size1 = gfc_conv_descriptor_size (desc, expr1->rank); + /* If the lhs has not been allocated, its bounds will not have been + initialized and so its size is set to zero. */ + size1 = gfc_create_var (gfc_array_index_type, NULL); + gfc_init_block (&alloc_block); + gfc_add_modify (&alloc_block, size1, gfc_index_zero_node); + gfc_init_block (&realloc_block); + gfc_add_modify (&realloc_block, size1, + gfc_conv_descriptor_size (desc, expr1->rank)); + tmp = build3_v (COND_EXPR, cond_null, + gfc_finish_block (&alloc_block), + gfc_finish_block (&realloc_block)); + gfc_add_expr_to_block (&fblock, tmp); - /* Get the rhs size. Fix both sizes. */ + /* Get the rhs size and fix it. */ if (expr2) desc2 = rss->info->data.array.descriptor; else desc2 = NULL_TREE; + size2 = gfc_index_one_node; for (n = 0; n < expr2->rank; n++) { @@ -8210,8 +8231,6 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop, gfc_array_index_type, tmp, size2); } - - size1 = gfc_evaluate_now (size1, &fblock); size2 = gfc_evaluate_now (size2, &fblock); cond = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c index bb5cfadd0f7..8d81f2b3216 100644 --- a/gcc/fortran/trans-expr.c +++ b/gcc/fortran/trans-expr.c @@ -39,7 +39,6 @@ along with GCC; see the file COPYING3. If not see /* Only for gfc_trans_assign and gfc_trans_pointer_assign. */ #include "trans-stmt.h" #include "dependency.h" -#include "gimple.h" #include "gimplify.h" #include "wide-int.h" diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c index d23af17d81e..e0c992e35f7 100644 --- a/gcc/fortran/trans-openmp.c +++ b/gcc/fortran/trans-openmp.c @@ -23,7 +23,7 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "tree.h" -#include "gimple.h" +#include "gimple-expr.h" #include "gimplify.h" /* For create_tmp_var_raw. */ #include "stringpool.h" #include "diagnostic-core.h" /* For internal_error. */ diff --git a/gcc/fortran/trans.c b/gcc/fortran/trans.c index 204cbff3247..9e57058d56e 100644 --- a/gcc/fortran/trans.c +++ b/gcc/fortran/trans.c @@ -23,7 +23,6 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tree.h" #include "gimple-expr.h" /* For create_tmp_var_raw. */ -#include "gimple.h" #include "stringpool.h" #include "tree-iterator.h" #include "diagnostic-core.h" /* For internal_error. */ @@ -424,7 +423,7 @@ trans_runtime_error_vararg (bool error, locus* where, const char* msgid, } else asprintf (&message, "In file '%s', around line %d", - gfc_source_file, input_line + 1); + gfc_source_file, LOCATION_LINE (input_location) + 1); arg = gfc_build_addr_expr (pchar_type_node, gfc_build_localized_cstring_const (message)); diff --git a/gcc/function.c b/gcc/function.c index 3789352a7dc..2c8d781e2c0 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -51,14 +51,12 @@ along with GCC; see the file COPYING3. If not see #include "insn-config.h" #include "recog.h" #include "output.h" -#include "basic-block.h" #include "hashtab.h" -#include "ggc.h" #include "tm_p.h" #include "langhooks.h" #include "target.h" #include "common/common-target.h" -#include "gimple.h" +#include "gimple-expr.h" #include "gimplify.h" #include "tree-pass.h" #include "predict.h" @@ -4407,7 +4405,6 @@ 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) @@ -4417,6 +4414,8 @@ 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/gcc.c b/gcc/gcc.c index dff7477f54e..b895f226ad0 100644 --- a/gcc/gcc.c +++ b/gcc/gcc.c @@ -535,20 +535,16 @@ proper position among the other output files. */ #define STACK_SPLIT_SPEC " %{fsplit-stack: --wrap=pthread_create}" #ifndef LIBASAN_SPEC -#ifdef STATIC_LIBASAN_LIBS -#define ADD_STATIC_LIBASAN_LIBS \ - " %{static-libasan:" STATIC_LIBASAN_LIBS "}" -#else -#define ADD_STATIC_LIBASAN_LIBS -#endif +#define STATIC_LIBASAN_LIBS \ + " %{static-libasan:%:include(libsanitizer.spec)%(link_libasan)}" #ifdef LIBASAN_EARLY_SPEC -#define LIBASAN_SPEC ADD_STATIC_LIBASAN_LIBS +#define LIBASAN_SPEC STATIC_LIBASAN_LIBS #elif defined(HAVE_LD_STATIC_DYNAMIC) #define LIBASAN_SPEC "%{static-libasan:" LD_STATIC_OPTION \ "} -lasan %{static-libasan:" LD_DYNAMIC_OPTION "}" \ - ADD_STATIC_LIBASAN_LIBS + STATIC_LIBASAN_LIBS #else -#define LIBASAN_SPEC "-lasan" ADD_STATIC_LIBASAN_LIBS +#define LIBASAN_SPEC "-lasan" STATIC_LIBASAN_LIBS #endif #endif @@ -557,20 +553,16 @@ proper position among the other output files. */ #endif #ifndef LIBTSAN_SPEC -#ifdef STATIC_LIBTSAN_LIBS -#define ADD_STATIC_LIBTSAN_LIBS \ - " %{static-libtsan:" STATIC_LIBTSAN_LIBS "}" -#else -#define ADD_STATIC_LIBTSAN_LIBS -#endif +#define STATIC_LIBTSAN_LIBS \ + " %{static-libtsan:%:include(libsanitizer.spec)%(link_libtsan)}" #ifdef LIBTSAN_EARLY_SPEC -#define LIBTSAN_SPEC ADD_STATIC_LIBTSAN_LIBS +#define LIBTSAN_SPEC STATIC_LIBTSAN_LIBS #elif defined(HAVE_LD_STATIC_DYNAMIC) #define LIBTSAN_SPEC "%{static-libtsan:" LD_STATIC_OPTION \ "} -ltsan %{static-libtsan:" LD_DYNAMIC_OPTION "}" \ - ADD_STATIC_LIBTSAN_LIBS + STATIC_LIBTSAN_LIBS #else -#define LIBTSAN_SPEC "-ltsan" ADD_STATIC_LIBTSAN_LIBS +#define LIBTSAN_SPEC "-ltsan" STATIC_LIBTSAN_LIBS #endif #endif @@ -578,28 +570,30 @@ proper position among the other output files. */ #define LIBTSAN_EARLY_SPEC "" #endif -#ifndef LIBUBSAN_SPEC -#ifdef STATIC_LIBUBSAN_LIBS -#define ADD_STATIC_LIBUBSAN_LIBS \ - " %{static-libubsan:" STATIC_LIBUBSAN_LIBS "}" +#ifndef LIBLSAN_SPEC +#define STATIC_LIBLSAN_LIBS \ + " %{static-liblsan:%:include(libsanitizer.spec)%(link_liblsan)}" +#ifdef HAVE_LD_STATIC_DYNAMIC +#define LIBLSAN_SPEC "%{!shared:%{static-liblsan:" LD_STATIC_OPTION \ + "} -llsan %{static-liblsan:" LD_DYNAMIC_OPTION "}" \ + STATIC_LIBLSAN_LIBS "}" #else -#define ADD_STATIC_LIBUBSAN_LIBS +#define LIBLSAN_SPEC "%{!shared:-llsan" STATIC_LIBLSAN_LIBS "}" #endif -#ifdef LIBUBSAN_EARLY_SPEC -#define LIBUBSAN_SPEC ADD_STATIC_LIBUBSAN_LIBS -#elif defined(HAVE_LD_STATIC_DYNAMIC) +#endif + +#ifndef LIBUBSAN_SPEC +#define STATIC_LIBUBSAN_LIBS \ + " %{static-libubsan:%:include(libsanitizer.spec)%(link_libubsan)}" +#ifdef HAVE_LD_STATIC_DYNAMIC #define LIBUBSAN_SPEC "%{static-libubsan:" LD_STATIC_OPTION \ "} -lubsan %{static-libubsan:" LD_DYNAMIC_OPTION "}" \ - ADD_STATIC_LIBUBSAN_LIBS + STATIC_LIBUBSAN_LIBS #else -#define LIBUBSAN_SPEC "-lubsan" ADD_STATIC_LIBUBSAN_LIBS +#define LIBUBSAN_SPEC "-lubsan" STATIC_LIBUBSAN_LIBS #endif #endif -#ifndef LIBUBSAN_EARLY_SPEC -#define LIBUBSAN_EARLY_SPEC "" -#endif - /* config.h can define LIBGCC_SPEC to override how and when libgcc.a is included. */ #ifndef LIBGCC_SPEC @@ -723,8 +717,7 @@ proper position among the other output files. */ #ifndef SANITIZER_EARLY_SPEC #define SANITIZER_EARLY_SPEC "\ %{!nostdlib:%{!nodefaultlibs:%{%:sanitize(address):" LIBASAN_EARLY_SPEC "} \ - %{%:sanitize(thread):" LIBTSAN_EARLY_SPEC "} \ - %{%:sanitize(undefined):" LIBUBSAN_EARLY_SPEC "}}}" + %{%:sanitize(thread):" LIBTSAN_EARLY_SPEC "}}}" #endif /* Linker command line options for -fsanitize= late on the command line. */ @@ -735,7 +728,8 @@ proper position among the other output files. */ %{%:sanitize(thread):%e-fsanitize=address is incompatible with -fsanitize=thread}}\ %{%:sanitize(thread):" LIBTSAN_SPEC "\ %{!pie:%{!shared:%e-fsanitize=thread linking must be done with -pie or -shared}}}\ - %{%:sanitize(undefined):" LIBUBSAN_SPEC "}}}" + %{%:sanitize(undefined):" LIBUBSAN_SPEC "}\ + %{%:sanitize(leak):" LIBLSAN_SPEC "}}}" #endif /* This is the spec to use, once the code for creating the vtable @@ -8123,7 +8117,10 @@ sanitize_spec_function (int argc, const char **argv) return (flag_sanitize & SANITIZE_THREAD) ? "" : NULL; if (strcmp (argv[0], "undefined") == 0) return (flag_sanitize & SANITIZE_UNDEFINED) ? "" : NULL; - + if (strcmp (argv[0], "leak") == 0) + return ((flag_sanitize + & (SANITIZE_ADDRESS | SANITIZE_LEAK | SANITIZE_THREAD)) + == SANITIZE_LEAK) ? "" : NULL; return NULL; } diff --git a/gcc/gcse.c b/gcc/gcse.c index 3012c4d1d36..2c1ca21586e 100644 --- a/gcc/gcse.c +++ b/gcc/gcse.c @@ -3509,7 +3509,7 @@ calculate_bb_reg_pressure (void) bitmap_iterator bi; - ira_setup_eliminable_regset (false); + ira_setup_eliminable_regset (); curr_regs_live = BITMAP_ALLOC (®_obstack); FOR_EACH_BB (bb) { diff --git a/gcc/gengtype.c b/gcc/gengtype.c index 0c0195c1606..33684331a93 100644 --- a/gcc/gengtype.c +++ b/gcc/gengtype.c @@ -1768,6 +1768,9 @@ open_base_files (void) "tree.h", "rtl.h", "wide-int.h", "function.h", "insn-config.h", "expr.h", "hard-reg-set.h", "basic-block.h", "cselib.h", "insn-addr.h", "optabs.h", "libfuncs.h", "debug.h", "ggc.h", "cgraph.h", + "pointer-set.h", "hash-table.h", "vec.h", "ggc.h", "basic-block.h", + "tree-ssa-alias.h", "internal-fn.h", "gimple-fold.h", "tree-eh.h", + "gimple-expr.h", "is-a.h", "gimple.h", "gimple-iterator.h", "gimple-ssa.h", "tree-cfg.h", "tree-phinodes.h", "ssa-iterators.h", "stringpool.h", "tree-ssanames.h", "tree-ssa-loop.h", "tree-ssa-loop-ivopts.h", "tree-ssa-loop-manip.h", @@ -2653,15 +2656,48 @@ get_string_option (options_p opt, const char *key) return NULL; } +/* Machinery for avoiding duplicate tags within switch statements. */ +struct seen_tag +{ + const char *tag; + struct seen_tag *next; +}; + +int +already_seen_tag (struct seen_tag *seen_tags, const char *tag) +{ + /* Linear search, so O(n^2), but n is currently small. */ + while (seen_tags) + { + if (!strcmp (seen_tags->tag, tag)) + return 1; + seen_tags = seen_tags->next; + } + /* Not yet seen this tag. */ + return 0; +} + +void +mark_tag_as_seen (struct seen_tag **seen_tags, const char *tag) +{ + /* Add to front of linked list. */ + struct seen_tag *new_node = XCNEW (struct seen_tag); + new_node->tag = tag; + new_node->next = *seen_tags; + *seen_tags = new_node; +} + static void -walk_subclasses (type_p base, struct walk_type_data *d) +walk_subclasses (type_p base, struct walk_type_data *d, + struct seen_tag **seen_tags) { for (type_p sub = base->u.s.first_subclass; sub != NULL; sub = sub->u.s.next_sibling_class) { const char *type_tag = get_string_option (sub->u.s.opt, "tag"); - if (type_tag) + if (type_tag && !already_seen_tag (*seen_tags, type_tag)) { + mark_tag_as_seen (seen_tags, type_tag); oprintf (d->of, "%*scase %s:\n", d->indent, "", type_tag); d->indent += 2; oprintf (d->of, "%*s{\n", d->indent, ""); @@ -2677,7 +2713,7 @@ walk_subclasses (type_p base, struct walk_type_data *d) oprintf (d->of, "%*sbreak;\n", d->indent, ""); d->indent -= 2; } - walk_subclasses (sub, d); + walk_subclasses (sub, d, seen_tags); } } @@ -3224,7 +3260,8 @@ walk_type (type_p t, struct walk_type_data *d) else if (desc) { /* Add cases to handle subclasses. */ - walk_subclasses (t, d); + struct seen_tag *tags = NULL; + walk_subclasses (t, d, &tags); /* Ensure that if someone forgets a "tag" option that we don't silent fail to traverse that subclass's fields. */ diff --git a/gcc/genmodes.c b/gcc/genmodes.c index 6f0fba85ec4..26386eace85 100644 --- a/gcc/genmodes.c +++ b/gcc/genmodes.c @@ -333,7 +333,6 @@ complete_mode (struct mode_data *m) break; case MODE_INT: - case MODE_POINTER_BOUNDS: case MODE_FLOAT: case MODE_DECIMAL_FLOAT: case MODE_FRACT: @@ -535,19 +534,6 @@ make_special_mode (enum mode_class cl, const char *name, new_mode (cl, name, file, line); } -#define POINTER_BOUNDS_MODE(N, Y) \ - make_pointer_bounds_mode (#N, Y, __FILE__, __LINE__) - -static void ATTRIBUTE_UNUSED -make_pointer_bounds_mode (const char *name, - unsigned int bytesize, - const char *file, unsigned int line) -{ - struct mode_data *m = new_mode (MODE_POINTER_BOUNDS, name, file, line); - m->bytesize = bytesize; -} - - #define INT_MODE(N, Y) FRACTIONAL_INT_MODE (N, -1U, Y) #define FRACTIONAL_INT_MODE(N, B, Y) \ make_int_mode (#N, B, Y, __FILE__, __LINE__) diff --git a/gcc/ggc.h b/gcc/ggc.h index bb8f939513d..f9033445270 100644 --- a/gcc/ggc.h +++ b/gcc/ggc.h @@ -276,4 +276,11 @@ ggc_alloc_cleared_gimple_statement_stat (size_t s MEM_STAT_DECL) ggc_internal_cleared_alloc_stat (s PASS_MEM_STAT); } +static inline struct simd_clone * +ggc_alloc_cleared_simd_clone_stat (size_t s MEM_STAT_DECL) +{ + return (struct simd_clone *) + ggc_internal_cleared_alloc_stat (s PASS_MEM_STAT); +} + #endif diff --git a/gcc/gimple-builder.c b/gcc/gimple-builder.c index 17cd2e1b887..a670c7ec505 100644 --- a/gcc/gimple-builder.c +++ b/gcc/gimple-builder.c @@ -22,6 +22,11 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tree.h" #include "stringpool.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "tree-ssanames.h" diff --git a/gcc/gimple-expr.c b/gcc/gimple-expr.c index 77660a34c6d..45fe5c27d69 100644 --- a/gcc/gimple-expr.c +++ b/gcc/gimple-expr.c @@ -24,6 +24,13 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tm.h" #include "tree.h" +#include "pointer-set.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "stringpool.h" #include "gimplify.h" diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index f95980784b7..d7cd1a38964 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -31,6 +31,12 @@ along with GCC; see the file COPYING3. If not see #include "function.h" #include "dumpfile.h" #include "bitmap.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "gimple-iterator.h" @@ -3414,7 +3420,7 @@ gimple_fold_indirect_ref (tree t) unsigned HOST_WIDE_INT indexi = offset * BITS_PER_UNIT; tree index = bitsize_int (indexi); if (offset / part_widthi - <= TYPE_VECTOR_SUBPARTS (TREE_TYPE (addrtype))) + < TYPE_VECTOR_SUBPARTS (TREE_TYPE (addrtype))) return fold_build3 (BIT_FIELD_REF, type, TREE_OPERAND (addr, 0), part_width, index); } diff --git a/gcc/gimple-iterator.c b/gcc/gimple-iterator.c index a3e74fe5012..9f51e6cf07a 100644 --- a/gcc/gimple-iterator.c +++ b/gcc/gimple-iterator.c @@ -23,6 +23,12 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tm.h" #include "tree.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimple-ssa.h" diff --git a/gcc/gimple-low.c b/gcc/gimple-low.c index 71f8dfec3f8..19f2ef8c63f 100644 --- a/gcc/gimple-low.c +++ b/gcc/gimple-low.c @@ -25,6 +25,11 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "tree-nested.h" #include "calls.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "tree-iterator.h" diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c index 7458647057a..419eabca10b 100644 --- a/gcc/gimple-pretty-print.c +++ b/gcc/gimple-pretty-print.c @@ -29,6 +29,12 @@ along with GCC; see the file COPYING3. If not see #include "gimple-pretty-print.h" #include "hashtab.h" #include "bitmap.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimple-ssa.h" @@ -541,12 +547,11 @@ dump_gimple_assign (pretty_printer *buffer, gimple gs, int spc, int flags) static void dump_gimple_return (pretty_printer *buffer, gimple gs, int spc, int flags) { - tree t, t2; + tree t; t = gimple_return_retval (gs); - t2 = gimple_return_retbnd (gs); if (flags & TDF_RAW) - dump_gimple_fmt (buffer, spc, flags, "%G <%T %T>", gs, t, t2); + dump_gimple_fmt (buffer, spc, flags, "%G <%T>", gs, t); else { pp_string (buffer, "return"); @@ -555,11 +560,6 @@ dump_gimple_return (pretty_printer *buffer, gimple gs, int spc, int flags) pp_space (buffer); dump_generic_node (buffer, t, spc, flags, false); } - if (t2) - { - pp_string (buffer, ", "); - dump_generic_node (buffer, t2, spc, flags, false); - } pp_semicolon (buffer); } } @@ -2015,10 +2015,6 @@ dump_gimple_mem_ops (pretty_printer *buffer, gimple gs, int spc, int flags) tree vdef = gimple_vdef (gs); tree vuse = gimple_vuse (gs); - if (!ssa_operands_active (DECL_STRUCT_FUNCTION (current_function_decl)) - || !gimple_references_memory_p (gs)) - return; - if (vdef != NULL_TREE) { pp_string (buffer, "# "); diff --git a/gcc/gimple-ssa-isolate-paths.c b/gcc/gimple-ssa-isolate-paths.c index 1b7e3ff7d76..440d2ed86d9 100644 --- a/gcc/gimple-ssa-isolate-paths.c +++ b/gcc/gimple-ssa-isolate-paths.c @@ -26,6 +26,10 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "flags.h" #include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimple-walk.h" diff --git a/gcc/gimple-ssa-strength-reduction.c b/gcc/gimple-ssa-strength-reduction.c index 516756fd75f..6dbb36c1ec0 100644 --- a/gcc/gimple-ssa-strength-reduction.c +++ b/gcc/gimple-ssa-strength-reduction.c @@ -37,12 +37,18 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "tree.h" +#include "pointer-set.h" +#include "hash-table.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimplify-me.h" #include "stor-layout.h" #include "expr.h" -#include "basic-block.h" #include "tree-pass.h" #include "cfgloop.h" #include "gimple-pretty-print.h" @@ -53,11 +59,10 @@ along with GCC; see the file COPYING3. If not see #include "stringpool.h" #include "tree-ssanames.h" #include "domwalk.h" -#include "pointer-set.h" #include "expmed.h" #include "params.h" -#include "hash-table.h" #include "tree-ssa-address.h" +#include "tree-affine.h" #include "wide-int-print.h" /* Information about a strength reduction candidate. Each statement @@ -426,6 +431,42 @@ cand_chain_hasher::equal (const value_type *chain1, const compare_type *chain2) /* Hash table embodying a mapping from base exprs to chains of candidates. */ static hash_table <cand_chain_hasher> base_cand_map; +/* Pointer map used by tree_to_aff_combination_expand. */ +static struct pointer_map_t *name_expansions; +/* Pointer map embodying a mapping from bases to alternative bases. */ +static struct pointer_map_t *alt_base_map; + +/* Given BASE, use the tree affine combiniation facilities to + find the underlying tree expression for BASE, with any + immediate offset excluded. */ + +static tree +get_alternative_base (tree base) +{ + tree *result = (tree *) pointer_map_contains (alt_base_map, base); + + if (result == NULL) + { + tree expr; + aff_tree aff; + + tree_to_aff_combination_expand (base, TREE_TYPE (base), + &aff, &name_expansions); + aff.offset = 0; + expr = aff_combination_to_tree (&aff); + + result = (tree *) pointer_map_insert (alt_base_map, base); + gcc_assert (!*result); + + if (expr == base) + *result = NULL; + else + *result = expr; + } + + return *result; +} + /* Look in the candidate table for a CAND_PHI that defines BASE and return it if found; otherwise return NULL. */ @@ -446,8 +487,9 @@ find_phi_def (tree base) } /* Helper routine for find_basis_for_candidate. May be called twice: - once for the candidate's base expr, and optionally again for the - candidate's phi definition. */ + once for the candidate's base expr, and optionally again either for + the candidate's phi definition or for a CAND_REF's alternative base + expression. */ static slsr_cand_t find_basis_for_base_expr (slsr_cand_t c, tree base_expr) @@ -524,6 +566,13 @@ find_basis_for_candidate (slsr_cand_t c) } } + if (!basis && c->kind == CAND_REF) + { + tree alt_base_expr = get_alternative_base (c->base_expr); + if (alt_base_expr) + basis = find_basis_for_base_expr (c, alt_base_expr); + } + if (basis) { c->sibling = basis->dependent; @@ -534,17 +583,21 @@ find_basis_for_candidate (slsr_cand_t c) return 0; } -/* Record a mapping from the base expression of C to C itself, indicating that - C may potentially serve as a basis using that base expression. */ +/* Record a mapping from BASE to C, indicating that C may potentially serve + as a basis using that base expression. BASE may be the same as + C->BASE_EXPR; alternatively BASE can be a different tree that share the + underlining expression of C->BASE_EXPR. */ static void -record_potential_basis (slsr_cand_t c) +record_potential_basis (slsr_cand_t c, tree base) { cand_chain_t node; cand_chain **slot; + gcc_assert (base); + node = (cand_chain_t) obstack_alloc (&chain_obstack, sizeof (cand_chain)); - node->base_expr = c->base_expr; + node->base_expr = base; node->cand = c; node->next = NULL; slot = base_cand_map.find_slot (node, INSERT); @@ -560,10 +613,18 @@ record_potential_basis (slsr_cand_t c) } /* Allocate storage for a new candidate and initialize its fields. - Attempt to find a basis for the candidate. */ + Attempt to find a basis for the candidate. + + For CAND_REF, an alternative base may also be recorded and used + to find a basis. This helps cases where the expression hidden + behind BASE (which is usually an SSA_NAME) has immediate offset, + e.g. + + a2[i][j] = 1; + a2[i + 20][j] = 2; */ static slsr_cand_t -alloc_cand_and_find_basis (enum cand_kind kind, gimple gs, tree base, +alloc_cand_and_find_basis (enum cand_kind kind, gimple gs, tree base, const widest_int &index, tree stride, tree ctype, unsigned savings) { @@ -589,7 +650,13 @@ alloc_cand_and_find_basis (enum cand_kind kind, gimple gs, tree base, else c->basis = find_basis_for_candidate (c); - record_potential_basis (c); + record_potential_basis (c, base); + if (kind == CAND_REF) + { + tree alt_base = get_alternative_base (base); + if (alt_base) + record_potential_basis (c, alt_base); + } return c; } @@ -1843,6 +1910,12 @@ replace_ref (tree *expr, slsr_cand_t c) static void replace_refs (slsr_cand_t c) { + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fputs ("Replacing reference: ", dump_file); + print_gimple_stmt (dump_file, c->cand_stmt, 0, 0); + } + if (gimple_vdef (c->cand_stmt)) { tree *lhs = gimple_assign_lhs_ptr (c->cand_stmt); @@ -1854,6 +1927,13 @@ replace_refs (slsr_cand_t c) replace_ref (rhs, c); } + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fputs ("With: ", dump_file); + print_gimple_stmt (dump_file, c->cand_stmt, 0, 0); + fputs ("\n", dump_file); + } + if (c->sibling) replace_refs (lookup_cand (c->sibling)); @@ -3520,6 +3600,9 @@ execute_strength_reduction (void) /* Allocate the mapping from base expressions to candidate chains. */ base_cand_map.create (500); + /* Allocate the mapping from bases to alternative bases. */ + alt_base_map = pointer_map_create (); + /* Initialize the loop optimizer. We need to detect flow across back edges, and this gives us dominator information as well. */ loop_optimizer_init (AVOID_CFG_MODIFICATIONS); @@ -3535,6 +3618,9 @@ execute_strength_reduction (void) dump_cand_chains (); } + pointer_map_destroy (alt_base_map); + free_affine_expand_cache (&name_expansions); + /* Analyze costs and make appropriate replacements. */ analyze_candidates_and_replace (); diff --git a/gcc/gimple-ssa.h b/gcc/gimple-ssa.h index 50b48bb6228..8290af285fb 100644 --- a/gcc/gimple-ssa.h +++ b/gcc/gimple-ssa.h @@ -141,7 +141,7 @@ update_stmt (gimple s) if (gimple_has_ops (s)) { gimple_set_modified (s, true); - update_stmt_operands (s); + update_stmt_operands (cfun, s); } } @@ -151,7 +151,19 @@ static inline void update_stmt_if_modified (gimple s) { if (gimple_modified_p (s)) - update_stmt_operands (s); + update_stmt_operands (cfun, s); +} + +/* Mark statement S as modified, and update it. */ + +static inline void +update_stmt_fn (struct function *fn, gimple s) +{ + if (gimple_has_ops (s)) + { + gimple_set_modified (s, true); + update_stmt_operands (fn, s); + } } diff --git a/gcc/gimple-streamer-in.c b/gcc/gimple-streamer-in.c index a5c8dd8fd39..57b0d871a5a 100644 --- a/gcc/gimple-streamer-in.c +++ b/gcc/gimple-streamer-in.c @@ -24,6 +24,12 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "diagnostic.h" #include "tree.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimple-ssa.h" diff --git a/gcc/gimple-streamer-out.c b/gcc/gimple-streamer-out.c index 0d6b6a6ae95..0520eb20f0a 100644 --- a/gcc/gimple-streamer-out.c +++ b/gcc/gimple-streamer-out.c @@ -23,6 +23,12 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "tree.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimple-ssa.h" diff --git a/gcc/gimple-walk.c b/gcc/gimple-walk.c index 22f4584a673..4d59ae078c3 100644 --- a/gcc/gimple-walk.c +++ b/gcc/gimple-walk.c @@ -25,6 +25,11 @@ along with GCC; see the file COPYING3. If not see #include "tm.h" #include "tree.h" #include "stmt.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimple-walk.h" diff --git a/gcc/gimple.c b/gcc/gimple.c index 25f1296a36d..e9e38785cc2 100644 --- a/gcc/gimple.c +++ b/gcc/gimple.c @@ -28,9 +28,13 @@ along with GCC; see the file COPYING3. If not see #include "calls.h" #include "stmt.h" #include "stor-layout.h" -#include "ggc.h" #include "hard-reg-set.h" #include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimple-walk.h" @@ -176,7 +180,7 @@ gimple_build_with_ops_stat (enum gimple_code code, unsigned subcode, gimple gimple_build_return (tree retval) { - gimple s = gimple_build_with_ops (GIMPLE_RETURN, ERROR_MARK, 2); + gimple s = gimple_build_with_ops (GIMPLE_RETURN, ERROR_MARK, 1); if (retval) gimple_return_set_retval (s, retval); return s; @@ -697,8 +701,8 @@ gimple_build_wce (gimple_seq cleanup) gimple gimple_build_resx (int region) { - gimple_statement_eh_ctrl *p = - as_a <gimple_statement_eh_ctrl> ( + gimple_statement_resx *p = + as_a <gimple_statement_resx> ( gimple_build_with_ops (GIMPLE_RESX, ERROR_MARK, 0)); p->region = region; return p; @@ -747,8 +751,8 @@ gimple_build_switch (tree index, tree default_label, vec<tree> args) gimple gimple_build_eh_dispatch (int region) { - gimple_statement_eh_ctrl *p = - as_a <gimple_statement_eh_ctrl> ( + gimple_statement_eh_dispatch *p = + as_a <gimple_statement_eh_dispatch> ( gimple_build_with_ops (GIMPLE_EH_DISPATCH, ERROR_MARK, 0)); p->region = region; return p; @@ -1950,57 +1954,6 @@ const unsigned char gimple_rhs_class_table[] = { #undef DEFTREECODE #undef END_OF_BASE_TREE_CODES -void -recalculate_side_effects (tree t) -{ - enum tree_code code = TREE_CODE (t); - int len = TREE_OPERAND_LENGTH (t); - int i; - - switch (TREE_CODE_CLASS (code)) - { - case tcc_expression: - switch (code) - { - case INIT_EXPR: - case MODIFY_EXPR: - case VA_ARG_EXPR: - case PREDECREMENT_EXPR: - case PREINCREMENT_EXPR: - case POSTDECREMENT_EXPR: - case POSTINCREMENT_EXPR: - /* All of these have side-effects, no matter what their - operands are. */ - return; - - default: - break; - } - /* Fall through. */ - - case tcc_comparison: /* a comparison expression */ - case tcc_unary: /* a unary arithmetic expression */ - case tcc_binary: /* a binary arithmetic expression */ - case tcc_reference: /* a reference */ - case tcc_vl_exp: /* a function call */ - TREE_SIDE_EFFECTS (t) = TREE_THIS_VOLATILE (t); - for (i = 0; i < len; ++i) - { - tree op = TREE_OPERAND (t, i); - if (op && TREE_SIDE_EFFECTS (op)) - TREE_SIDE_EFFECTS (t) = 1; - } - break; - - case tcc_constant: - /* No side-effects. */ - return; - - default: - gcc_unreachable (); - } -} - /* Canonicalize a tree T for use in a COND_EXPR as conditional. Returns a canonicalized tree that is valid for a COND_EXPR or NULL_TREE, if we failed to create one. */ diff --git a/gcc/gimple.def b/gcc/gimple.def index 07370aedd29..ff1ef4307ed 100644 --- a/gcc/gimple.def +++ b/gcc/gimple.def @@ -221,7 +221,7 @@ DEFGSCODE(GIMPLE_NOP, "gimple_nop", GSS_BASE) DEFGSCODE(GIMPLE_OMP_ATOMIC_LOAD, "gimple_omp_atomic_load", GSS_OMP_ATOMIC_LOAD) DEFGSCODE(GIMPLE_OMP_ATOMIC_STORE, "gimple_omp_atomic_store", - GSS_OMP_ATOMIC_STORE) + GSS_OMP_ATOMIC_STORE_LAYOUT) /* GIMPLE_OMP_CONTINUE marks the location of the loop or sections iteration in partially lowered OpenMP code. */ @@ -300,7 +300,7 @@ DEFGSCODE(GIMPLE_OMP_ORDERED, "gimple_omp_ordered", GSS_OMP) DATA_ARG is a local variable in the parent function containing data to be shared with CHILD_FN. This is used to implement all the data sharing clauses. */ -DEFGSCODE(GIMPLE_OMP_PARALLEL, "gimple_omp_parallel", GSS_OMP_PARALLEL) +DEFGSCODE(GIMPLE_OMP_PARALLEL, "gimple_omp_parallel", GSS_OMP_PARALLEL_LAYOUT) /* GIMPLE_OMP_TASK <BODY, CLAUSES, CHILD_FN, DATA_ARG, COPY_FN, ARG_SIZE, ARG_ALIGN> represents @@ -329,7 +329,7 @@ DEFGSCODE(GIMPLE_OMP_PARALLEL, "gimple_omp_parallel", GSS_OMP_PARALLEL) DEFGSCODE(GIMPLE_OMP_TASK, "gimple_omp_task", GSS_OMP_TASK) /* OMP_RETURN marks the end of an OpenMP directive. */ -DEFGSCODE(GIMPLE_OMP_RETURN, "gimple_omp_return", GSS_OMP_ATOMIC_STORE) +DEFGSCODE(GIMPLE_OMP_RETURN, "gimple_omp_return", GSS_OMP_ATOMIC_STORE_LAYOUT) /* OMP_SECTION <BODY> represents #pragma omp section. BODY is the sequence of statements in the section body. */ @@ -351,7 +351,7 @@ DEFGSCODE(GIMPLE_OMP_SECTIONS_SWITCH, "gimple_omp_sections_switch", GSS_BASE) /* GIMPLE_OMP_SINGLE <BODY, CLAUSES> represents #pragma omp single BODY is the sequence of statements inside the single section. CLAUSES is an OMP_CLAUSE chain holding the associated clauses. */ -DEFGSCODE(GIMPLE_OMP_SINGLE, "gimple_omp_single", GSS_OMP_SINGLE) +DEFGSCODE(GIMPLE_OMP_SINGLE, "gimple_omp_single", GSS_OMP_SINGLE_LAYOUT) /* GIMPLE_OMP_TARGET <BODY, CLAUSES, CHILD_FN> represents #pragma omp target {,data,update} @@ -364,12 +364,12 @@ DEFGSCODE(GIMPLE_OMP_SINGLE, "gimple_omp_single", GSS_OMP_SINGLE) DATA_ARG is a vec of 3 local variables in the parent function containing data to be mapped to CHILD_FN. This is used to implement the MAP clauses. */ -DEFGSCODE(GIMPLE_OMP_TARGET, "gimple_omp_target", GSS_OMP_PARALLEL) +DEFGSCODE(GIMPLE_OMP_TARGET, "gimple_omp_target", GSS_OMP_PARALLEL_LAYOUT) /* GIMPLE_OMP_TEAMS <BODY, CLAUSES> represents #pragma omp teams BODY is the sequence of statements inside the single section. CLAUSES is an OMP_CLAUSE chain holding the associated clauses. */ -DEFGSCODE(GIMPLE_OMP_TEAMS, "gimple_omp_teams", GSS_OMP_SINGLE) +DEFGSCODE(GIMPLE_OMP_TEAMS, "gimple_omp_teams", GSS_OMP_SINGLE_LAYOUT) /* GIMPLE_PREDICT <PREDICT, OUTCOME> specifies a hint for branch prediction. diff --git a/gcc/gimple.h b/gcc/gimple.h index 0eb23fc39e8..a97a5e8b2d4 100644 --- a/gcc/gimple.h +++ b/gcc/gimple.h @@ -22,18 +22,6 @@ along with GCC; see the file COPYING3. If not see #ifndef GCC_GIMPLE_H #define GCC_GIMPLE_H -#include "pointer-set.h" -#include "hash-table.h" -#include "vec.h" -#include "ggc.h" -#include "basic-block.h" -#include "tree-ssa-alias.h" -#include "internal-fn.h" -#include "gimple-fold.h" -#include "tree-eh.h" -#include "gimple-expr.h" -#include "is-a.h" - typedef gimple gimple_seq_node; /* For each block, the PHI nodes that need to be rewritten are stored into @@ -102,7 +90,6 @@ enum gf_mask { GF_CALL_NOTHROW = 1 << 4, GF_CALL_ALLOCA_FOR_VAR = 1 << 5, GF_CALL_INTERNAL = 1 << 6, - GF_CALL_WITH_BOUNDS = 1 << 7, GF_OMP_PARALLEL_COMBINED = 1 << 0, GF_OMP_FOR_KIND_MASK = 3 << 0, GF_OMP_FOR_KIND_FOR = 0 << 0, @@ -420,6 +407,20 @@ struct GTY((tag("GSS_EH_CTRL"))) int region; }; +struct GTY((tag("GSS_EH_CTRL"))) + gimple_statement_resx : public gimple_statement_eh_ctrl +{ + /* No extra fields; adds invariant: + stmt->code == GIMPLE_RESX. */ +}; + +struct GTY((tag("GSS_EH_CTRL"))) + gimple_statement_eh_dispatch : public gimple_statement_eh_ctrl +{ + /* No extra fields; adds invariant: + stmt->code == GIMPLE_EH_DISPATH. */ +}; + /* GIMPLE_TRY */ @@ -547,10 +548,9 @@ struct GTY((tag("GSS_OMP_FOR"))) }; -/* GIMPLE_OMP_PARALLEL */ - -struct GTY((tag("GSS_OMP_PARALLEL"))) - gimple_statement_omp_parallel : public gimple_statement_omp +/* GIMPLE_OMP_PARALLEL, GIMPLE_OMP_TARGET */ +struct GTY((tag("GSS_OMP_PARALLEL_LAYOUT"))) + gimple_statement_omp_parallel_layout : public gimple_statement_omp { /* [ WORD 1-7 ] : base class */ @@ -567,11 +567,35 @@ struct GTY((tag("GSS_OMP_PARALLEL"))) tree data_arg; }; +/* GIMPLE_OMP_PARALLEL or GIMPLE_TASK */ +struct GTY((tag("GSS_OMP_PARALLEL_LAYOUT"))) + gimple_statement_omp_taskreg : public gimple_statement_omp_parallel_layout +{ + /* No extra fields; adds invariant: + stmt->code == GIMPLE_OMP_PARALLEL + || stmt->code == GIMPLE_OMP_TASK. */ +}; + + +/* GIMPLE_OMP_PARALLEL */ +struct GTY((tag("GSS_OMP_PARALLEL_LAYOUT"))) + gimple_statement_omp_parallel : public gimple_statement_omp_taskreg +{ + /* No extra fields; adds invariant: + stmt->code == GIMPLE_OMP_PARALLEL. */ +}; + +struct GTY((tag("GSS_OMP_PARALLEL_LAYOUT"))) + gimple_statement_omp_target : public gimple_statement_omp_parallel_layout +{ + /* No extra fields; adds invariant: + stmt->code == GIMPLE_OMP_TARGET. */ +}; /* GIMPLE_OMP_TASK */ struct GTY((tag("GSS_OMP_TASK"))) - gimple_statement_omp_task : public gimple_statement_omp_parallel + gimple_statement_omp_task : public gimple_statement_omp_taskreg { /* [ WORD 1-10 ] : base class */ @@ -623,10 +647,10 @@ struct GTY((tag("GSS_OMP_CONTINUE"))) tree control_use; }; -/* GIMPLE_OMP_SINGLE, GIMPLE_OMP_TARGET, GIMPLE_OMP_TEAMS */ +/* GIMPLE_OMP_SINGLE, GIMPLE_OMP_TEAMS */ -struct GTY((tag("GSS_OMP_SINGLE"))) - gimple_statement_omp_single : public gimple_statement_omp +struct GTY((tag("GSS_OMP_SINGLE_LAYOUT"))) + gimple_statement_omp_single_layout : public gimple_statement_omp { /* [ WORD 1-7 ] : base class */ @@ -634,6 +658,20 @@ struct GTY((tag("GSS_OMP_SINGLE"))) tree clauses; }; +struct GTY((tag("GSS_OMP_SINGLE_LAYOUT"))) + gimple_statement_omp_single : public gimple_statement_omp_single_layout +{ + /* No extra fields; adds invariant: + stmt->code == GIMPLE_OMP_SINGLE. */ +}; + +struct GTY((tag("GSS_OMP_SINGLE_LAYOUT"))) + gimple_statement_omp_teams : public gimple_statement_omp_single_layout +{ + /* No extra fields; adds invariant: + stmt->code == GIMPLE_OMP_TEAMS. */ +}; + /* GIMPLE_OMP_ATOMIC_LOAD. Note: This is based on gimple_statement_base, not g_s_omp, because g_s_omp @@ -651,8 +689,8 @@ struct GTY((tag("GSS_OMP_ATOMIC_LOAD"))) /* GIMPLE_OMP_ATOMIC_STORE. See note on GIMPLE_OMP_ATOMIC_LOAD. */ -struct GTY((tag("GSS_OMP_ATOMIC_STORE"))) - gimple_statement_omp_atomic_store : public gimple_statement_base +struct GTY((tag("GSS_OMP_ATOMIC_STORE_LAYOUT"))) + gimple_statement_omp_atomic_store_layout : public gimple_statement_base { /* [ WORD 1-6 ] : base class */ @@ -660,6 +698,22 @@ struct GTY((tag("GSS_OMP_ATOMIC_STORE"))) tree val; }; +struct GTY((tag("GSS_OMP_ATOMIC_STORE_LAYOUT"))) + gimple_statement_omp_atomic_store : + public gimple_statement_omp_atomic_store_layout +{ + /* No extra fields; adds invariant: + stmt->code == GIMPLE_OMP_ATOMIC_STORE. */ +}; + +struct GTY((tag("GSS_OMP_ATOMIC_STORE_LAYOUT"))) + gimple_statement_omp_return : + public gimple_statement_omp_atomic_store_layout +{ + /* No extra fields; adds invariant: + stmt->code == GIMPLE_OMP_RETURN. */ +}; + /* GIMPLE_TRANSACTION. */ /* Bits to be stored in the GIMPLE_TRANSACTION subcode. */ @@ -742,9 +796,17 @@ is_a_helper <gimple_statement_catch>::test (gimple gs) template <> template <> inline bool -is_a_helper <gimple_statement_eh_ctrl>::test (gimple gs) +is_a_helper <gimple_statement_resx>::test (gimple gs) +{ + return gs->code == GIMPLE_RESX; +} + +template <> +template <> +inline bool +is_a_helper <gimple_statement_eh_dispatch>::test (gimple gs) { - return gs->code == GIMPLE_RESX || gs->code == GIMPLE_EH_DISPATCH; + return gs->code == GIMPLE_EH_DISPATCH; } template <> @@ -784,7 +846,15 @@ template <> inline bool is_a_helper <gimple_statement_omp_atomic_store>::test (gimple gs) { - return gs->code == GIMPLE_OMP_ATOMIC_STORE || gs->code == GIMPLE_OMP_RETURN; + return gs->code == GIMPLE_OMP_ATOMIC_STORE; +} + +template <> +template <> +inline bool +is_a_helper <gimple_statement_omp_return>::test (gimple gs) +{ + return gs->code == GIMPLE_OMP_RETURN; } template <> @@ -814,9 +884,25 @@ is_a_helper <gimple_statement_omp_for>::test (gimple gs) template <> template <> inline bool +is_a_helper <gimple_statement_omp_taskreg>::test (gimple gs) +{ + return gs->code == GIMPLE_OMP_PARALLEL || gs->code == GIMPLE_OMP_TASK; +} + +template <> +template <> +inline bool is_a_helper <gimple_statement_omp_parallel>::test (gimple gs) { - return gs->code == GIMPLE_OMP_PARALLEL || gs->code == GIMPLE_OMP_TASK || gs->code == GIMPLE_OMP_TARGET; + return gs->code == GIMPLE_OMP_PARALLEL; +} + +template <> +template <> +inline bool +is_a_helper <gimple_statement_omp_target>::test (gimple gs) +{ + return gs->code == GIMPLE_OMP_TARGET; } template <> @@ -832,7 +918,15 @@ template <> inline bool is_a_helper <gimple_statement_omp_single>::test (gimple gs) { - return gs->code == GIMPLE_OMP_SINGLE || gs->code == GIMPLE_OMP_TEAMS; + return gs->code == GIMPLE_OMP_SINGLE; +} + +template <> +template <> +inline bool +is_a_helper <gimple_statement_omp_teams>::test (gimple gs) +{ + return gs->code == GIMPLE_OMP_TEAMS; } template <> @@ -910,9 +1004,17 @@ is_a_helper <const gimple_statement_catch>::test (const_gimple gs) template <> template <> inline bool -is_a_helper <const gimple_statement_eh_ctrl>::test (const_gimple gs) +is_a_helper <const gimple_statement_resx>::test (const_gimple gs) +{ + return gs->code == GIMPLE_RESX; +} + +template <> +template <> +inline bool +is_a_helper <const gimple_statement_eh_dispatch>::test (const_gimple gs) { - return gs->code == GIMPLE_RESX || gs->code == GIMPLE_EH_DISPATCH; + return gs->code == GIMPLE_EH_DISPATCH; } template <> @@ -936,7 +1038,15 @@ template <> inline bool is_a_helper <const gimple_statement_omp_atomic_store>::test (const_gimple gs) { - return gs->code == GIMPLE_OMP_ATOMIC_STORE || gs->code == GIMPLE_OMP_RETURN; + return gs->code == GIMPLE_OMP_ATOMIC_STORE; +} + +template <> +template <> +inline bool +is_a_helper <const gimple_statement_omp_return>::test (const_gimple gs) +{ + return gs->code == GIMPLE_OMP_RETURN; } template <> @@ -966,9 +1076,25 @@ is_a_helper <const gimple_statement_omp_for>::test (const_gimple gs) template <> template <> inline bool +is_a_helper <const gimple_statement_omp_taskreg>::test (const_gimple gs) +{ + return gs->code == GIMPLE_OMP_PARALLEL || gs->code == GIMPLE_OMP_TASK; +} + +template <> +template <> +inline bool is_a_helper <const gimple_statement_omp_parallel>::test (const_gimple gs) { - return gs->code == GIMPLE_OMP_PARALLEL || gs->code == GIMPLE_OMP_TASK || gs->code == GIMPLE_OMP_TARGET; + return gs->code == GIMPLE_OMP_PARALLEL; +} + +template <> +template <> +inline bool +is_a_helper <const gimple_statement_omp_target>::test (const_gimple gs) +{ + return gs->code == GIMPLE_OMP_TARGET; } template <> @@ -984,7 +1110,15 @@ template <> inline bool is_a_helper <const gimple_statement_omp_single>::test (const_gimple gs) { - return gs->code == GIMPLE_OMP_SINGLE || gs->code == GIMPLE_OMP_TEAMS; + return gs->code == GIMPLE_OMP_SINGLE; +} + +template <> +template <> +inline bool +is_a_helper <const gimple_statement_omp_teams>::test (const_gimple gs) +{ + return gs->code == GIMPLE_OMP_TEAMS; } template <> @@ -1112,7 +1246,6 @@ bool gimple_could_trap_p (gimple); bool gimple_assign_rhs_could_trap_p (gimple); extern void dump_gimple_statistics (void); unsigned get_gimple_rhs_num_ops (enum tree_code); -extern void recalculate_side_effects (tree); extern tree canonicalize_cond_expr_cond (tree); gimple gimple_call_copy_skip_args (gimple, bitmap); extern bool gimple_compare_field_offset (tree, tree); @@ -1766,9 +1899,9 @@ gimple_omp_return_nowait_p (const_gimple g) static inline void gimple_omp_return_set_lhs (gimple g, tree lhs) { - gimple_statement_omp_atomic_store *omp_atomic_store_stmt = - as_a <gimple_statement_omp_atomic_store> (g); - omp_atomic_store_stmt->val = lhs; + gimple_statement_omp_return *omp_return_stmt = + as_a <gimple_statement_omp_return> (g); + omp_return_stmt->val = lhs; } @@ -1777,9 +1910,9 @@ gimple_omp_return_set_lhs (gimple g, tree lhs) static inline tree gimple_omp_return_lhs (const_gimple g) { - const gimple_statement_omp_atomic_store *omp_atomic_store_stmt = - as_a <const gimple_statement_omp_atomic_store> (g); - return omp_atomic_store_stmt->val; + const gimple_statement_omp_return *omp_return_stmt = + as_a <const gimple_statement_omp_return> (g); + return omp_return_stmt->val; } @@ -1788,9 +1921,9 @@ gimple_omp_return_lhs (const_gimple g) static inline tree * gimple_omp_return_lhs_ptr (gimple g) { - gimple_statement_omp_atomic_store *omp_atomic_store_stmt = - as_a <gimple_statement_omp_atomic_store> (g); - return &omp_atomic_store_stmt->val; + gimple_statement_omp_return *omp_return_stmt = + as_a <gimple_statement_omp_return> (g); + return &omp_return_stmt->val; } @@ -2301,31 +2434,6 @@ gimple_call_internal_p (const_gimple gs) } -/* Return true if call GS is marked as instrumented by - Pointer Bounds Checker. */ - -static inline bool -gimple_call_with_bounds_p (const_gimple gs) -{ - GIMPLE_CHECK (gs, GIMPLE_CALL); - return (gs->subcode & GF_CALL_WITH_BOUNDS) != 0; -} - - -/* If INSTRUMENTED_P is true, marm statement GS as instrumented by - Pointer Bounds Checker. */ - -static inline void -gimple_call_set_with_bounds (gimple gs, bool with_bounds) -{ - GIMPLE_CHECK (gs, GIMPLE_CALL); - if (with_bounds) - gs->subcode |= GF_CALL_WITH_BOUNDS; - else - gs->subcode &= ~GF_CALL_WITH_BOUNDS; -} - - /* Return the target of internal call GS. */ static inline enum internal_fn @@ -3793,9 +3901,9 @@ gimple_phi_arg_has_location (gimple gs, size_t i) static inline int gimple_resx_region (const_gimple gs) { - const gimple_statement_eh_ctrl *eh_ctrl_stmt = - as_a <const gimple_statement_eh_ctrl> (gs); - return eh_ctrl_stmt->region; + const gimple_statement_resx *resx_stmt = + as_a <const gimple_statement_resx> (gs); + return resx_stmt->region; } /* Set REGION to be the region number for GIMPLE_RESX GS. */ @@ -3803,9 +3911,8 @@ gimple_resx_region (const_gimple gs) static inline void gimple_resx_set_region (gimple gs, int region) { - gimple_statement_eh_ctrl *eh_ctrl_stmt = - as_a <gimple_statement_eh_ctrl> (gs); - eh_ctrl_stmt->region = region; + gimple_statement_resx *resx_stmt = as_a <gimple_statement_resx> (gs); + resx_stmt->region = region; } /* Return the region number for GIMPLE_EH_DISPATCH GS. */ @@ -3813,9 +3920,9 @@ gimple_resx_set_region (gimple gs, int region) static inline int gimple_eh_dispatch_region (const_gimple gs) { - const gimple_statement_eh_ctrl *eh_ctrl_stmt = - as_a <const gimple_statement_eh_ctrl> (gs); - return eh_ctrl_stmt->region; + const gimple_statement_eh_dispatch *eh_dispatch_stmt = + as_a <const gimple_statement_eh_dispatch> (gs); + return eh_dispatch_stmt->region; } /* Set REGION to be the region number for GIMPLE_EH_DISPATCH GS. */ @@ -3823,9 +3930,9 @@ gimple_eh_dispatch_region (const_gimple gs) static inline void gimple_eh_dispatch_set_region (gimple gs, int region) { - gimple_statement_eh_ctrl *eh_ctrl_stmt = - as_a <gimple_statement_eh_ctrl> (gs); - eh_ctrl_stmt->region = region; + gimple_statement_eh_dispatch *eh_dispatch_stmt = + as_a <gimple_statement_eh_dispatch> (gs); + eh_dispatch_stmt->region = region; } /* Return the number of labels associated with the switch statement GS. */ @@ -4663,9 +4770,9 @@ gimple_omp_task_set_data_arg (gimple gs, tree data_arg) static inline tree gimple_omp_taskreg_clauses (const_gimple gs) { - const gimple_statement_omp_parallel *omp_parallel_stmt = - as_a <const gimple_statement_omp_parallel> (gs); - return omp_parallel_stmt->clauses; + const gimple_statement_omp_taskreg *omp_taskreg_stmt = + as_a <const gimple_statement_omp_taskreg> (gs); + return omp_taskreg_stmt->clauses; } @@ -4674,9 +4781,9 @@ gimple_omp_taskreg_clauses (const_gimple gs) static inline tree * gimple_omp_taskreg_clauses_ptr (gimple gs) { - gimple_statement_omp_parallel *omp_parallel_stmt = - as_a <gimple_statement_omp_parallel> (gs); - return &omp_parallel_stmt->clauses; + gimple_statement_omp_taskreg *omp_taskreg_stmt = + as_a <gimple_statement_omp_taskreg> (gs); + return &omp_taskreg_stmt->clauses; } @@ -4686,9 +4793,9 @@ gimple_omp_taskreg_clauses_ptr (gimple gs) static inline void gimple_omp_taskreg_set_clauses (gimple gs, tree clauses) { - gimple_statement_omp_parallel *omp_parallel_stmt = - as_a <gimple_statement_omp_parallel> (gs); - omp_parallel_stmt->clauses = clauses; + gimple_statement_omp_taskreg *omp_taskreg_stmt = + as_a <gimple_statement_omp_taskreg> (gs); + omp_taskreg_stmt->clauses = clauses; } @@ -4697,9 +4804,9 @@ gimple_omp_taskreg_set_clauses (gimple gs, tree clauses) static inline tree gimple_omp_taskreg_child_fn (const_gimple gs) { - const gimple_statement_omp_parallel *omp_parallel_stmt = - as_a <const gimple_statement_omp_parallel> (gs); - return omp_parallel_stmt->child_fn; + const gimple_statement_omp_taskreg *omp_taskreg_stmt = + as_a <const gimple_statement_omp_taskreg> (gs); + return omp_taskreg_stmt->child_fn; } /* Return a pointer to the child function used to hold the body of @@ -4708,9 +4815,9 @@ gimple_omp_taskreg_child_fn (const_gimple gs) static inline tree * gimple_omp_taskreg_child_fn_ptr (gimple gs) { - gimple_statement_omp_parallel *omp_parallel_stmt = - as_a <gimple_statement_omp_parallel> (gs); - return &omp_parallel_stmt->child_fn; + gimple_statement_omp_taskreg *omp_taskreg_stmt = + as_a <gimple_statement_omp_taskreg> (gs); + return &omp_taskreg_stmt->child_fn; } @@ -4719,9 +4826,9 @@ gimple_omp_taskreg_child_fn_ptr (gimple gs) static inline void gimple_omp_taskreg_set_child_fn (gimple gs, tree child_fn) { - gimple_statement_omp_parallel *omp_parallel_stmt = - as_a <gimple_statement_omp_parallel> (gs); - omp_parallel_stmt->child_fn = child_fn; + gimple_statement_omp_taskreg *omp_taskreg_stmt = + as_a <gimple_statement_omp_taskreg> (gs); + omp_taskreg_stmt->child_fn = child_fn; } @@ -4731,9 +4838,9 @@ gimple_omp_taskreg_set_child_fn (gimple gs, tree child_fn) static inline tree gimple_omp_taskreg_data_arg (const_gimple gs) { - const gimple_statement_omp_parallel *omp_parallel_stmt = - as_a <const gimple_statement_omp_parallel> (gs); - return omp_parallel_stmt->data_arg; + const gimple_statement_omp_taskreg *omp_taskreg_stmt = + as_a <const gimple_statement_omp_taskreg> (gs); + return omp_taskreg_stmt->data_arg; } @@ -4742,9 +4849,9 @@ gimple_omp_taskreg_data_arg (const_gimple gs) static inline tree * gimple_omp_taskreg_data_arg_ptr (gimple gs) { - gimple_statement_omp_parallel *omp_parallel_stmt = - as_a <gimple_statement_omp_parallel> (gs); - return &omp_parallel_stmt->data_arg; + gimple_statement_omp_taskreg *omp_taskreg_stmt = + as_a <gimple_statement_omp_taskreg> (gs); + return &omp_taskreg_stmt->data_arg; } @@ -4753,9 +4860,9 @@ gimple_omp_taskreg_data_arg_ptr (gimple gs) static inline void gimple_omp_taskreg_set_data_arg (gimple gs, tree data_arg) { - gimple_statement_omp_parallel *omp_parallel_stmt = - as_a <gimple_statement_omp_parallel> (gs); - omp_parallel_stmt->data_arg = data_arg; + gimple_statement_omp_taskreg *omp_taskreg_stmt = + as_a <gimple_statement_omp_taskreg> (gs); + omp_taskreg_stmt->data_arg = data_arg; } @@ -4896,9 +5003,9 @@ gimple_omp_single_set_clauses (gimple gs, tree clauses) static inline tree gimple_omp_target_clauses (const_gimple gs) { - const gimple_statement_omp_parallel *omp_parallel_stmt = - as_a <const gimple_statement_omp_parallel> (gs); - return omp_parallel_stmt->clauses; + const gimple_statement_omp_target *omp_target_stmt = + as_a <const gimple_statement_omp_target> (gs); + return omp_target_stmt->clauses; } @@ -4907,9 +5014,9 @@ gimple_omp_target_clauses (const_gimple gs) static inline tree * gimple_omp_target_clauses_ptr (gimple gs) { - gimple_statement_omp_parallel *omp_parallel_stmt = - as_a <gimple_statement_omp_parallel> (gs); - return &omp_parallel_stmt->clauses; + gimple_statement_omp_target *omp_target_stmt = + as_a <gimple_statement_omp_target> (gs); + return &omp_target_stmt->clauses; } @@ -4918,9 +5025,9 @@ gimple_omp_target_clauses_ptr (gimple gs) static inline void gimple_omp_target_set_clauses (gimple gs, tree clauses) { - gimple_statement_omp_parallel *omp_parallel_stmt = - as_a <gimple_statement_omp_parallel> (gs); - omp_parallel_stmt->clauses = clauses; + gimple_statement_omp_target *omp_target_stmt = + as_a <gimple_statement_omp_target> (gs); + omp_target_stmt->clauses = clauses; } @@ -4950,9 +5057,9 @@ gimple_omp_target_set_kind (gimple g, int kind) static inline tree gimple_omp_target_child_fn (const_gimple gs) { - const gimple_statement_omp_parallel *omp_parallel_stmt = - as_a <const gimple_statement_omp_parallel> (gs); - return omp_parallel_stmt->child_fn; + const gimple_statement_omp_target *omp_target_stmt = + as_a <const gimple_statement_omp_target> (gs); + return omp_target_stmt->child_fn; } /* Return a pointer to the child function used to hold the body of @@ -4961,9 +5068,9 @@ gimple_omp_target_child_fn (const_gimple gs) static inline tree * gimple_omp_target_child_fn_ptr (gimple gs) { - gimple_statement_omp_parallel *omp_parallel_stmt = - as_a <gimple_statement_omp_parallel> (gs); - return &omp_parallel_stmt->child_fn; + gimple_statement_omp_target *omp_target_stmt = + as_a <gimple_statement_omp_target> (gs); + return &omp_target_stmt->child_fn; } @@ -4972,9 +5079,9 @@ gimple_omp_target_child_fn_ptr (gimple gs) static inline void gimple_omp_target_set_child_fn (gimple gs, tree child_fn) { - gimple_statement_omp_parallel *omp_parallel_stmt = - as_a <gimple_statement_omp_parallel> (gs); - omp_parallel_stmt->child_fn = child_fn; + gimple_statement_omp_target *omp_target_stmt = + as_a <gimple_statement_omp_target> (gs); + omp_target_stmt->child_fn = child_fn; } @@ -4984,9 +5091,9 @@ gimple_omp_target_set_child_fn (gimple gs, tree child_fn) static inline tree gimple_omp_target_data_arg (const_gimple gs) { - const gimple_statement_omp_parallel *omp_parallel_stmt = - as_a <const gimple_statement_omp_parallel> (gs); - return omp_parallel_stmt->data_arg; + const gimple_statement_omp_target *omp_target_stmt = + as_a <const gimple_statement_omp_target> (gs); + return omp_target_stmt->data_arg; } @@ -4995,9 +5102,9 @@ gimple_omp_target_data_arg (const_gimple gs) static inline tree * gimple_omp_target_data_arg_ptr (gimple gs) { - gimple_statement_omp_parallel *omp_parallel_stmt = - as_a <gimple_statement_omp_parallel> (gs); - return &omp_parallel_stmt->data_arg; + gimple_statement_omp_target *omp_target_stmt = + as_a <gimple_statement_omp_target> (gs); + return &omp_target_stmt->data_arg; } @@ -5006,9 +5113,9 @@ gimple_omp_target_data_arg_ptr (gimple gs) static inline void gimple_omp_target_set_data_arg (gimple gs, tree data_arg) { - gimple_statement_omp_parallel *omp_parallel_stmt = - as_a <gimple_statement_omp_parallel> (gs); - omp_parallel_stmt->data_arg = data_arg; + gimple_statement_omp_target *omp_target_stmt = + as_a <gimple_statement_omp_target> (gs); + omp_target_stmt->data_arg = data_arg; } @@ -5017,9 +5124,9 @@ gimple_omp_target_set_data_arg (gimple gs, tree data_arg) static inline tree gimple_omp_teams_clauses (const_gimple gs) { - const gimple_statement_omp_single *omp_single_stmt = - as_a <const gimple_statement_omp_single> (gs); - return omp_single_stmt->clauses; + const gimple_statement_omp_teams *omp_teams_stmt = + as_a <const gimple_statement_omp_teams> (gs); + return omp_teams_stmt->clauses; } @@ -5028,9 +5135,9 @@ gimple_omp_teams_clauses (const_gimple gs) static inline tree * gimple_omp_teams_clauses_ptr (gimple gs) { - gimple_statement_omp_single *omp_single_stmt = - as_a <gimple_statement_omp_single> (gs); - return &omp_single_stmt->clauses; + gimple_statement_omp_teams *omp_teams_stmt = + as_a <gimple_statement_omp_teams> (gs); + return &omp_teams_stmt->clauses; } @@ -5039,9 +5146,9 @@ gimple_omp_teams_clauses_ptr (gimple gs) static inline void gimple_omp_teams_set_clauses (gimple gs, tree clauses) { - gimple_statement_omp_single *omp_single_stmt = - as_a <gimple_statement_omp_single> (gs); - omp_single_stmt->clauses = clauses; + gimple_statement_omp_teams *omp_teams_stmt = + as_a <gimple_statement_omp_teams> (gs); + omp_teams_stmt->clauses = clauses; } @@ -5406,26 +5513,6 @@ gimple_return_set_retval (gimple gs, tree retval) } -/* Return the return bounds for GIMPLE_RETURN GS. */ - -static inline tree -gimple_return_retbnd (const_gimple gs) -{ - GIMPLE_CHECK (gs, GIMPLE_RETURN); - return gimple_op (gs, 1); -} - - -/* Set RETVAL to be the return bounds for GIMPLE_RETURN GS. */ - -static inline void -gimple_return_set_retbnd (gimple gs, tree retval) -{ - GIMPLE_CHECK (gs, GIMPLE_RETURN); - gimple_set_op (gs, 1, retval); -} - - /* Returns true when the gimple statement STMT is any of the OpenMP types. */ #define CASE_GIMPLE_OMP \ diff --git a/gcc/gimplify-me.c b/gcc/gimplify-me.c index 92542a9a2e9..9dce585ee61 100644 --- a/gcc/gimplify-me.c +++ b/gcc/gimplify-me.c @@ -27,6 +27,12 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "stmt.h" #include "stor-layout.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimplify.h" diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 2b6de3e1732..2e8c657acf7 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -25,6 +25,15 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tree.h" #include "expr.h" +#include "pointer-set.h" +#include "hash-table.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "gimple-iterator.h" @@ -515,7 +524,7 @@ internal_get_tmp_var (tree val, gimple_seq *pre_p, gimple_seq *post_p, mod = build2 (INIT_EXPR, TREE_TYPE (t), t, unshare_expr (val)); - SET_EXPR_LOCATION (mod, EXPR_LOC_OR_HERE (val)); + SET_EXPR_LOCATION (mod, EXPR_LOC_OR_LOC (val, input_location)); /* gimplify_modify_expr might want to reduce this further. */ gimplify_and_add (mod, pre_p); @@ -1680,6 +1689,9 @@ gimplify_conversion (tree *expr_p) /* Nonlocal VLAs seen in the current function. */ static struct pointer_set_t *nonlocal_vlas; +/* The VAR_DECLs created for nonlocal VLAs for debug info purposes. */ +static tree nonlocal_vla_vars; + /* Gimplify a VAR_DECL or PARM_DECL. Return GS_OK if we expanded a DECL_VALUE_EXPR, and it's worth re-examining things. */ @@ -1728,14 +1740,13 @@ gimplify_var_or_parm_decl (tree *expr_p) ctx = ctx->outer_context; if (!ctx && !pointer_set_insert (nonlocal_vlas, decl)) { - tree copy = copy_node (decl), block; + tree copy = copy_node (decl); lang_hooks.dup_lang_specific_decl (copy); SET_DECL_RTL (copy, 0); TREE_USED (copy) = 1; - block = DECL_INITIAL (current_function_decl); - DECL_CHAIN (copy) = BLOCK_VARS (block); - BLOCK_VARS (block) = copy; + DECL_CHAIN (copy) = nonlocal_vla_vars; + nonlocal_vla_vars = copy; SET_DECL_VALUE_EXPR (copy, unshare_expr (value_expr)); DECL_HAS_VALUE_EXPR_P (copy) = 1; } @@ -1748,6 +1759,59 @@ gimplify_var_or_parm_decl (tree *expr_p) return GS_ALL_DONE; } +/* Recalculate the value of the TREE_SIDE_EFFECTS flag for T. */ + +static void +recalculate_side_effects (tree t) +{ + enum tree_code code = TREE_CODE (t); + int len = TREE_OPERAND_LENGTH (t); + int i; + + switch (TREE_CODE_CLASS (code)) + { + case tcc_expression: + switch (code) + { + case INIT_EXPR: + case MODIFY_EXPR: + case VA_ARG_EXPR: + case PREDECREMENT_EXPR: + case PREINCREMENT_EXPR: + case POSTDECREMENT_EXPR: + case POSTINCREMENT_EXPR: + /* All of these have side-effects, no matter what their + operands are. */ + return; + + default: + break; + } + /* Fall through. */ + + case tcc_comparison: /* a comparison expression */ + case tcc_unary: /* a unary arithmetic expression */ + case tcc_binary: /* a binary arithmetic expression */ + case tcc_reference: /* a reference */ + case tcc_vl_exp: /* a function call */ + TREE_SIDE_EFFECTS (t) = TREE_THIS_VOLATILE (t); + for (i = 0; i < len; ++i) + { + tree op = TREE_OPERAND (t, i); + if (op && TREE_SIDE_EFFECTS (op)) + TREE_SIDE_EFFECTS (t) = 1; + } + break; + + case tcc_constant: + /* No side-effects. */ + return; + + default: + gcc_unreachable (); + } +} + /* Gimplify the COMPONENT_REF, ARRAY_REF, REALPART_EXPR or IMAGPART_EXPR node *EXPR_P. @@ -2514,7 +2578,7 @@ shortcut_cond_expr (tree expr) while (TREE_CODE (pred) == TRUTH_ANDIF_EXPR) { /* Keep the original source location on the first 'if'. */ - location_t locus = EXPR_LOC_OR_HERE (expr); + location_t locus = EXPR_LOC_OR_LOC (expr, input_location); TREE_OPERAND (expr, 0) = TREE_OPERAND (pred, 1); /* Set the source location of the && on the second 'if'. */ if (EXPR_HAS_LOCATION (pred)) @@ -2536,7 +2600,7 @@ shortcut_cond_expr (tree expr) while (TREE_CODE (pred) == TRUTH_ORIF_EXPR) { /* Keep the original source location on the first 'if'. */ - location_t locus = EXPR_LOC_OR_HERE (expr); + location_t locus = EXPR_LOC_OR_LOC (expr, input_location); TREE_OPERAND (expr, 0) = TREE_OPERAND (pred, 1); /* Set the source location of the || on the second 'if'. */ if (EXPR_HAS_LOCATION (pred)) @@ -2600,7 +2664,7 @@ shortcut_cond_expr (tree expr) /* If there was nothing else in our arms, just forward the label(s). */ if (!then_se && !else_se) return shortcut_cond_r (pred, true_label_p, false_label_p, - EXPR_LOC_OR_HERE (expr)); + EXPR_LOC_OR_LOC (expr, input_location)); /* If our last subexpression already has a terminal label, reuse it. */ if (else_se) @@ -2632,7 +2696,7 @@ shortcut_cond_expr (tree expr) jump_over_else = block_may_fallthru (then_); pred = shortcut_cond_r (pred, true_label_p, false_label_p, - EXPR_LOC_OR_HERE (expr)); + EXPR_LOC_OR_LOC (expr, input_location)); expr = NULL; append_to_statement_list (pred, &expr); @@ -3712,19 +3776,10 @@ gimplify_init_constructor (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, individual element initialization. Also don't do this for small all-zero initializers (which aren't big enough to merit clearing), and don't try to make bitwise copies of - TREE_ADDRESSABLE types. - - We cannot apply such transformation when compiling chkp static - initializer because creation of initializer image in the memory - will require static initialization of bounds for it. It should - result in another gimplification of similar initializer and we - may fall into infinite loop. */ + TREE_ADDRESSABLE types. */ if (valid_const_initializer && !(cleared || num_nonzero_elements == 0) - && !TREE_ADDRESSABLE (type) - && (!current_function_decl - || !lookup_attribute ("chkp ctor", - DECL_ATTRIBUTES (current_function_decl)))) + && !TREE_ADDRESSABLE (type)) { HOST_WIDE_INT size = int_size_in_bytes (type); unsigned int align; @@ -8509,6 +8564,21 @@ gimplify_body (tree fndecl, bool do_parms) if (nonlocal_vlas) { + if (nonlocal_vla_vars) + { + /* tree-nested.c may later on call declare_vars (..., true); + which relies on BLOCK_VARS chain to be the tail of the + gimple_bind_vars chain. Ensure we don't violate that + assumption. */ + if (gimple_bind_block (outer_bind) + == DECL_INITIAL (current_function_decl)) + declare_vars (nonlocal_vla_vars, outer_bind, true); + else + BLOCK_VARS (DECL_INITIAL (current_function_decl)) + = chainon (BLOCK_VARS (DECL_INITIAL (current_function_decl)), + nonlocal_vla_vars); + nonlocal_vla_vars = NULL_TREE; + } pointer_set_destroy (nonlocal_vlas); nonlocal_vlas = NULL; } diff --git a/gcc/go/ChangeLog b/gcc/go/ChangeLog index 918862ef8fe..a7dafac8e74 100644 --- a/gcc/go/ChangeLog +++ b/gcc/go/ChangeLog @@ -1,3 +1,13 @@ +2013-11-23 Ian Lance Taylor <iant@google.com> + + * go-gcc.cc (Gcc_backend::function_type): Add result_struct + parameter. + +2013-11-22 Andrew MacLeod <amacleod@redhat.com> + + * go-gcc.cc: Add required include files from gimple.h. + * go-lang.c: Likewise + 2013-11-18 Richard Sandiford <rdsandiford@googlemail.com> * gofrontend/expressions.cc: Replace tree_low_cst (..., 0) with diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc index 578aff0b27a..183a9a3b3ad 100644 --- a/gcc/go/go-gcc.cc +++ b/gcc/go/go-gcc.cc @@ -29,7 +29,8 @@ #include "stor-layout.h" #include "varasm.h" #include "tree-iterator.h" -#include "gimple.h" +#include "basic-block.h" +#include "gimple-expr.h" #include "toplev.h" #include "output.h" #include "real.h" @@ -157,6 +158,7 @@ class Gcc_backend : public Backend function_type(const Btyped_identifier&, const std::vector<Btyped_identifier>&, const std::vector<Btyped_identifier>&, + Btype*, const Location); Btype* @@ -492,7 +494,8 @@ Btype* Gcc_backend::function_type(const Btyped_identifier& receiver, const std::vector<Btyped_identifier>& parameters, const std::vector<Btyped_identifier>& results, - Location location) + Btype* result_struct, + Location) { tree args = NULL_TREE; tree* pp = &args; @@ -527,29 +530,8 @@ Gcc_backend::function_type(const Btyped_identifier& receiver, result = results.front().btype->get_tree(); else { - result = make_node(RECORD_TYPE); - tree field_trees = NULL_TREE; - pp = &field_trees; - for (std::vector<Btyped_identifier>::const_iterator p = results.begin(); - p != results.end(); - ++p) - { - const std::string name = (p->name.empty() - ? "UNNAMED" - : p->name); - tree name_tree = get_identifier_from_string(name); - tree field_type_tree = p->btype->get_tree(); - if (field_type_tree == error_mark_node) - return this->error_type(); - gcc_assert(TYPE_SIZE(field_type_tree) != NULL_TREE); - tree field = build_decl(location.gcc_location(), FIELD_DECL, - name_tree, field_type_tree); - DECL_CONTEXT(field) = result; - *pp = field; - pp = &DECL_CHAIN(field); - } - TYPE_FIELDS(result) = field_trees; - layout_type(result); + gcc_assert(result_struct != NULL); + result = result_struct->get_tree(); } if (result == error_mark_node) return this->error_type(); diff --git a/gcc/go/go-lang.c b/gcc/go/go-lang.c index 93a0446efe6..580b1b802dc 100644 --- a/gcc/go/go-lang.c +++ b/gcc/go/go-lang.c @@ -23,10 +23,10 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "opts.h" #include "tree.h" -#include "gimple.h" +#include "basic-block.h" +#include "gimple-expr.h" #include "gimplify.h" #include "stor-layout.h" -#include "ggc.h" #include "toplev.h" #include "debug.h" #include "options.h" diff --git a/gcc/go/gofrontend/backend.h b/gcc/go/gofrontend/backend.h index 6f2c321e09e..8344da40120 100644 --- a/gcc/go/gofrontend/backend.h +++ b/gcc/go/gofrontend/backend.h @@ -101,11 +101,15 @@ class Backend // is provided so that the names are available. This should return // not the type of a Go function (which is a pointer to a struct) // but the type of a C function pointer (which will be used as the - // type of the first field of the struct). + // type of the first field of the struct). If there is more than + // one result, RESULT_STRUCT is a struct type to hold the results, + // and RESULTS may be ignored; if there are zero or one results, + // RESULT_STRUCT is NULL. virtual Btype* function_type(const Btyped_identifier& receiver, const std::vector<Btyped_identifier>& parameters, const std::vector<Btyped_identifier>& results, + Btype* result_struct, Location location) = 0; // Get a struct type. @@ -121,10 +125,11 @@ class Backend // NAME is the name of the type, and the location is where the named // type is defined. This function is also used for unnamed function // types with multiple results, in which case the type has no name - // and NAME will be empty. FOR_FUNCTION is true if this is for a Go - // function type, which corresponds to a C/C++ pointer to function - // type. The return value will later be passed as the first - // parameter to set_placeholder_pointer_type or + // and NAME will be empty. FOR_FUNCTION is true if this is for a C + // pointer to function type. A Go func type is represented as a + // pointer to a struct, and the first field of the struct is a C + // pointer to function. The return value will later be passed as + // the first parameter to set_placeholder_pointer_type or // set_placeholder_function_type. virtual Btype* placeholder_pointer_type(const std::string& name, Location, diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index 14c10d66a04..4f9368ed255 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -13,8 +13,7 @@ #include "tree.h" #include "stringpool.h" #include "stor-layout.h" -#include "gimple.h" -#include "gimplify.h" +#include "gimple-expr.h" #include "tree-iterator.h" #include "convert.h" #include "real.h" @@ -9864,8 +9863,11 @@ Call_expression::do_get_tree(Translate_context* context) fndecl = TREE_OPERAND(fndecl, 0); // Add a type cast in case the type of the function is a recursive - // type which refers to itself. - if (!DECL_P(fndecl) || !DECL_IS_BUILTIN(fndecl)) + // type which refers to itself. We don't do this for an interface + // method because 1) an interface method never refers to itself, so + // we always have a function type here; 2) we pass an extra first + // argument to an interface method, so fnfield_type is not correct. + if ((!DECL_P(fndecl) || !DECL_IS_BUILTIN(fndecl)) && !is_interface_method) fn = fold_convert_loc(location.gcc_location(), fnfield_type, fn); // This is to support builtin math functions when using 80387 math. diff --git a/gcc/go/gofrontend/gogo-tree.cc b/gcc/go/gofrontend/gogo-tree.cc index 001d24d238d..fcceffb2977 100644 --- a/gcc/go/gofrontend/gogo-tree.cc +++ b/gcc/go/gofrontend/gogo-tree.cc @@ -11,7 +11,7 @@ #include "stringpool.h" #include "stor-layout.h" #include "varasm.h" -#include "gimple.h" +#include "gimple-expr.h" #include "gimplify.h" #include "tree-iterator.h" #include "cgraph.h" diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc index 7451a7bcff6..8c5d038a0b1 100644 --- a/gcc/go/gofrontend/types.cc +++ b/gcc/go/gofrontend/types.cc @@ -9,8 +9,6 @@ #include "toplev.h" #include "intl.h" #include "tree.h" -#include "gimple.h" -#include "gimplify.h" #include "real.h" #include "convert.h" @@ -1061,8 +1059,9 @@ Type::get_backend_placeholder(Gogo* gogo) { case TYPE_FUNCTION: { + // A Go function type is a pointer to a struct type. Location loc = this->function_type()->location(); - bt = gogo->backend()->placeholder_pointer_type("", loc, true); + bt = gogo->backend()->placeholder_pointer_type("", loc, false); } break; @@ -1155,7 +1154,7 @@ Type::finish_backend(Gogo* gogo, Btype *placeholder) case TYPE_FUNCTION: { Btype* bt = this->do_get_backend(gogo); - if (!gogo->backend()->set_placeholder_function_type(placeholder, bt)) + if (!gogo->backend()->set_placeholder_pointer_type(placeholder, bt)) go_assert(saw_errors()); } break; @@ -1834,7 +1833,9 @@ Type::write_specific_type_functions(Gogo* gogo, Named_type* name, bloc); gogo->start_block(bloc); - if (this->struct_type() != NULL) + if (name != NULL && name->real_type()->named_type() != NULL) + this->write_named_hash(gogo, name, hash_fntype, equal_fntype); + else if (this->struct_type() != NULL) this->struct_type()->write_hash_function(gogo, name, hash_fntype, equal_fntype); else if (this->array_type() != NULL) @@ -1852,7 +1853,9 @@ Type::write_specific_type_functions(Gogo* gogo, Named_type* name, false, bloc); gogo->start_block(bloc); - if (this->struct_type() != NULL) + if (name != NULL && name->real_type()->named_type() != NULL) + this->write_named_equal(gogo, name); + else if (this->struct_type() != NULL) this->struct_type()->write_equal_function(gogo, name); else if (this->array_type() != NULL) this->array_type()->write_equal_function(gogo, name); @@ -1865,6 +1868,100 @@ Type::write_specific_type_functions(Gogo* gogo, Named_type* name, gogo->finish_function(bloc); } +// Write a hash function that simply calls the hash function for a +// named type. This is used when one named type is defined as +// another. This ensures that this case works when the other named +// type is defined in another package and relies on calling hash +// functions defined only in that package. + +void +Type::write_named_hash(Gogo* gogo, Named_type* name, + Function_type* hash_fntype, Function_type* equal_fntype) +{ + Location bloc = Linemap::predeclared_location(); + + Named_type* base_type = name->real_type()->named_type(); + go_assert(base_type != NULL); + + // The pointer to the type we are going to hash. This is an + // unsafe.Pointer. + Named_object* key_arg = gogo->lookup("key", NULL); + go_assert(key_arg != NULL); + + // The size of the type we are going to hash. + Named_object* keysz_arg = gogo->lookup("key_size", NULL); + go_assert(keysz_arg != NULL); + + Named_object* hash_fn; + Named_object* equal_fn; + name->real_type()->type_functions(gogo, base_type, hash_fntype, equal_fntype, + &hash_fn, &equal_fn); + + // Call the hash function for the base type. + Expression* key_ref = Expression::make_var_reference(key_arg, bloc); + Expression* keysz_ref = Expression::make_var_reference(keysz_arg, bloc); + Expression_list* args = new Expression_list(); + args->push_back(key_ref); + args->push_back(keysz_ref); + Expression* func = Expression::make_func_reference(hash_fn, NULL, bloc); + Expression* call = Expression::make_call(func, args, false, bloc); + + // Return the hash of the base type. + Expression_list* vals = new Expression_list(); + vals->push_back(call); + Statement* s = Statement::make_return_statement(vals, bloc); + gogo->add_statement(s); +} + +// Write an equality function that simply calls the equality function +// for a named type. This is used when one named type is defined as +// another. This ensures that this case works when the other named +// type is defined in another package and relies on calling equality +// functions defined only in that package. + +void +Type::write_named_equal(Gogo* gogo, Named_type* name) +{ + Location bloc = Linemap::predeclared_location(); + + // The pointers to the types we are going to compare. These have + // type unsafe.Pointer. + Named_object* key1_arg = gogo->lookup("key1", NULL); + Named_object* key2_arg = gogo->lookup("key2", NULL); + go_assert(key1_arg != NULL && key2_arg != NULL); + + Named_type* base_type = name->real_type()->named_type(); + go_assert(base_type != NULL); + + // Build temporaries with the base type. + Type* pt = Type::make_pointer_type(base_type); + + Expression* ref = Expression::make_var_reference(key1_arg, bloc); + ref = Expression::make_cast(pt, ref, bloc); + Temporary_statement* p1 = Statement::make_temporary(pt, ref, bloc); + gogo->add_statement(p1); + + ref = Expression::make_var_reference(key2_arg, bloc); + ref = Expression::make_cast(pt, ref, bloc); + Temporary_statement* p2 = Statement::make_temporary(pt, ref, bloc); + gogo->add_statement(p2); + + // Compare the values for equality. + Expression* t1 = Expression::make_temporary_reference(p1, bloc); + t1 = Expression::make_unary(OPERATOR_MULT, t1, bloc); + + Expression* t2 = Expression::make_temporary_reference(p2, bloc); + t2 = Expression::make_unary(OPERATOR_MULT, t2, bloc); + + Expression* cond = Expression::make_binary(OPERATOR_EQEQ, t1, t2, bloc); + + // Return the equality comparison. + Expression_list* vals = new Expression_list(); + vals->push_back(cond); + Statement* s = Statement::make_return_statement(vals, bloc); + gogo->add_statement(s); +} + // Return a composite literal for the type descriptor for a plain type // of kind RUNTIME_TYPE_KIND named NAME. @@ -3380,6 +3477,48 @@ Function_type::do_hash_for_method(Gogo* gogo) const return ret; } +// Hash result parameters. + +unsigned int +Function_type::Results_hash::operator()(const Typed_identifier_list* t) const +{ + unsigned int hash = 0; + for (Typed_identifier_list::const_iterator p = t->begin(); + p != t->end(); + ++p) + { + hash <<= 2; + hash = Type::hash_string(p->name(), hash); + hash += p->type()->hash_for_method(NULL); + } + return hash; +} + +// Compare result parameters so that can map identical result +// parameters to a single struct type. + +bool +Function_type::Results_equal::operator()(const Typed_identifier_list* a, + const Typed_identifier_list* b) const +{ + if (a->size() != b->size()) + return false; + Typed_identifier_list::const_iterator pa = a->begin(); + for (Typed_identifier_list::const_iterator pb = b->begin(); + pb != b->end(); + ++pa, ++pb) + { + if (pa->name() != pb->name() + || !Type::are_identical(pa->type(), pb->type(), true, NULL)) + return false; + } + return true; +} + +// Hash from results to a backend struct type. + +Function_type::Results_structs Function_type::results_structs; + // Get the backend representation for a function type. Btype* @@ -3418,12 +3557,14 @@ Function_type::get_backend_fntype(Gogo* gogo) } std::vector<Backend::Btyped_identifier> bresults; + Btype* bresult_struct = NULL; if (this->results_ != NULL) { bresults.resize(this->results_->size()); size_t i = 0; for (Typed_identifier_list::const_iterator p = - this->results_->begin(); p != this->results_->end(); + this->results_->begin(); + p != this->results_->end(); ++p, ++i) { bresults[i].name = Gogo::unpack_hidden_name(p->name()); @@ -3431,10 +3572,42 @@ Function_type::get_backend_fntype(Gogo* gogo) bresults[i].location = p->location(); } go_assert(i == bresults.size()); + + if (this->results_->size() > 1) + { + // Use the same results struct for all functions that + // return the same set of results. This is useful to + // unify calls to interface methods with other calls. + std::pair<Typed_identifier_list*, Btype*> val; + val.first = this->results_; + val.second = NULL; + std::pair<Results_structs::iterator, bool> ins = + Function_type::results_structs.insert(val); + if (ins.second) + { + // Build a new struct type. + Struct_field_list* sfl = new Struct_field_list; + for (Typed_identifier_list::const_iterator p = + this->results_->begin(); + p != this->results_->end(); + ++p) + { + Typed_identifier tid = *p; + if (tid.name().empty()) + tid = Typed_identifier("UNNAMED", tid.type(), + tid.location()); + sfl->push_back(Struct_field(tid)); + } + Struct_type* st = Type::make_struct_type(sfl, + this->location()); + ins.first->second = st->get_backend(gogo); + } + bresult_struct = ins.first->second; + } } this->fnbtype_ = gogo->backend()->function_type(breceiver, bparameters, - bresults, + bresults, bresult_struct, this->location()); } @@ -7136,18 +7309,18 @@ Interface_type::get_backend_empty_interface_type(Gogo* gogo) return empty_interface_type; } -// Return the fields of a non-empty interface type. This is not -// declared in types.h so that types.h doesn't have to #include -// backend.h. +// Return a pointer to the backend representation of the method table. -static void -get_backend_interface_fields(Gogo* gogo, Interface_type* type, - bool use_placeholder, - std::vector<Backend::Btyped_identifier>* bfields) +Btype* +Interface_type::get_backend_methods(Gogo* gogo) { - Location loc = type->location(); + if (this->bmethods_ != NULL && !this->bmethods_is_placeholder_) + return this->bmethods_; + + Location loc = this->location(); - std::vector<Backend::Btyped_identifier> mfields(type->methods()->size() + 1); + std::vector<Backend::Btyped_identifier> + mfields(this->all_methods_->size() + 1); Type* pdt = Type::make_type_descriptor_ptr_type(); mfields[0].name = "__type_descriptor"; @@ -7156,8 +7329,8 @@ get_backend_interface_fields(Gogo* gogo, Interface_type* type, std::string last_name = ""; size_t i = 1; - for (Typed_identifier_list::const_iterator p = type->methods()->begin(); - p != type->methods()->end(); + for (Typed_identifier_list::const_iterator p = this->all_methods_->begin(); + p != this->all_methods_->end(); ++p, ++i) { // The type of the method in Go only includes the parameters. @@ -7188,21 +7361,56 @@ get_backend_interface_fields(Gogo* gogo, Interface_type* type, ft->location()); mfields[i].name = Gogo::unpack_hidden_name(p->name()); - mfields[i].btype = (use_placeholder - ? mft->get_backend_placeholder(gogo) - : mft->get_backend(gogo)); + mfields[i].btype = mft->get_backend_fntype(gogo); mfields[i].location = loc; + // Sanity check: the names should be sorted. go_assert(p->name() > last_name); last_name = p->name(); } - Btype* methods = gogo->backend()->struct_type(mfields); + Btype* st = gogo->backend()->struct_type(mfields); + Btype* ret = gogo->backend()->pointer_type(st); + + if (this->bmethods_ != NULL && this->bmethods_is_placeholder_) + gogo->backend()->set_placeholder_pointer_type(this->bmethods_, ret); + this->bmethods_ = ret; + this->bmethods_is_placeholder_ = false; + return ret; +} + +// Return a placeholder for the pointer to the backend methods table. + +Btype* +Interface_type::get_backend_methods_placeholder(Gogo* gogo) +{ + if (this->bmethods_ == NULL) + { + Location loc = this->location(); + this->bmethods_ = gogo->backend()->placeholder_pointer_type("", loc, + false); + this->bmethods_is_placeholder_ = true; + } + return this->bmethods_; +} + +// Return the fields of a non-empty interface type. This is not +// declared in types.h so that types.h doesn't have to #include +// backend.h. + +static void +get_backend_interface_fields(Gogo* gogo, Interface_type* type, + bool use_placeholder, + std::vector<Backend::Btyped_identifier>* bfields) +{ + Location loc = type->location(); bfields->resize(2); (*bfields)[0].name = "__methods"; - (*bfields)[0].btype = gogo->backend()->pointer_type(methods); + (*bfields)[0].btype = (use_placeholder + ? type->get_backend_methods_placeholder(gogo) + : type->get_backend_methods(gogo)); (*bfields)[0].location = loc; Type* vt = Type::make_pointer_type(Type::make_void_type()); @@ -7243,7 +7451,7 @@ Interface_type::do_get_backend(Gogo* gogo) void Interface_type::finish_backend_methods(Gogo* gogo) { - if (!this->interface_type()->is_empty()) + if (!this->is_empty()) { const Typed_identifier_list* methods = this->methods(); if (methods != NULL) @@ -7253,6 +7461,10 @@ Interface_type::finish_backend_methods(Gogo* gogo) ++p) p->type()->get_backend(gogo); } + + // Getting the backend methods now will set the placeholder + // pointer. + this->get_backend_methods(gogo); } } @@ -8544,14 +8756,14 @@ Named_type::do_get_backend(Gogo* gogo) if (this->seen_in_get_backend_) { this->is_circular_ = true; - return gogo->backend()->circular_pointer_type(bt, true); + return gogo->backend()->circular_pointer_type(bt, false); } this->seen_in_get_backend_ = true; bt1 = Type::get_named_base_btype(gogo, base); this->seen_in_get_backend_ = false; if (this->is_circular_) - bt1 = gogo->backend()->circular_pointer_type(bt, true); - if (!gogo->backend()->set_placeholder_function_type(bt, bt1)) + bt1 = gogo->backend()->circular_pointer_type(bt, false); + if (!gogo->backend()->set_placeholder_pointer_type(bt, bt1)) bt = gogo->backend()->error_type(); return bt; diff --git a/gcc/go/gofrontend/types.h b/gcc/go/gofrontend/types.h index 12a7c8579b2..1bd8ce6cf8f 100644 --- a/gcc/go/gofrontend/types.h +++ b/gcc/go/gofrontend/types.h @@ -1138,6 +1138,13 @@ class Type Function_type* equal_fntype, Named_object** hash_fn, Named_object** equal_fn); + void + write_named_hash(Gogo*, Named_type*, Function_type* hash_fntype, + Function_type* equal_fntype); + + void + write_named_equal(Gogo*, Named_type*); + // Build a composite literal for the uncommon type information. Expression* uncommon_type_constructor(Gogo*, Type* uncommon_type, @@ -1840,6 +1847,27 @@ class Function_type : public Type type_descriptor_params(Type*, const Typed_identifier*, const Typed_identifier_list*); + // A mapping from a list of result types to a backend struct type. + class Results_hash + { + public: + unsigned int + operator()(const Typed_identifier_list*) const; + }; + + class Results_equal + { + public: + bool + operator()(const Typed_identifier_list*, + const Typed_identifier_list*) const; + }; + + typedef Unordered_map_hash(Typed_identifier_list*, Btype*, + Results_hash, Results_equal) Results_structs; + + static Results_structs results_structs; + // The receiver name and type. This will be NULL for a normal // function, non-NULL for a method. Typed_identifier* receiver_; @@ -2552,8 +2580,9 @@ class Interface_type : public Type Interface_type(Typed_identifier_list* methods, Location location) : Type(TYPE_INTERFACE), parse_methods_(methods), all_methods_(NULL), location_(location), - interface_btype_(NULL), assume_identical_(NULL), - methods_are_finalized_(false), seen_(false) + interface_btype_(NULL), bmethods_(NULL), assume_identical_(NULL), + methods_are_finalized_(false), bmethods_is_placeholder_(false), + seen_(false) { go_assert(methods == NULL || !methods->empty()); } // The location where the interface type was defined. @@ -2620,6 +2649,15 @@ class Interface_type : public Type static Btype* get_backend_empty_interface_type(Gogo*); + // Get a pointer to the backend representation of the method table. + Btype* + get_backend_methods(Gogo*); + + // Return a placeholder for the backend representation of the + // pointer to the method table. + Btype* + get_backend_methods_placeholder(Gogo*); + // Finish the backend representation of the method types. void finish_backend_methods(Gogo*); @@ -2686,11 +2724,15 @@ class Interface_type : public Type Location location_; // The backend representation of this type during backend conversion. Btype* interface_btype_; + // The backend representation of the pointer to the method table. + Btype* bmethods_; // A list of interface types assumed to be identical during // interface comparison. mutable Assume_identical* assume_identical_; // Whether the methods have been finalized. bool methods_are_finalized_; + // Whether the bmethods_ field is a placeholder. + bool bmethods_is_placeholder_; // Used to avoid endless recursion in do_mangled_name. mutable bool seen_; }; diff --git a/gcc/graphite-blocking.c b/gcc/graphite-blocking.c index da457d20da1..38e610d6d86 100644 --- a/gcc/graphite-blocking.c +++ b/gcc/graphite-blocking.c @@ -35,6 +35,11 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "tree.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "tree-ssa-loop.h" diff --git a/gcc/graphite-clast-to-gimple.c b/gcc/graphite-clast-to-gimple.c index 4d273353371..b1414324a28 100644 --- a/gcc/graphite-clast-to-gimple.c +++ b/gcc/graphite-clast-to-gimple.c @@ -36,6 +36,11 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "diagnostic-core.h" #include "tree.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimplify-me.h" diff --git a/gcc/graphite-dependences.c b/gcc/graphite-dependences.c index f9f7004cb1d..c0d769c7dd6 100644 --- a/gcc/graphite-dependences.c +++ b/gcc/graphite-dependences.c @@ -34,6 +34,11 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "tree.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "tree-ssa-loop.h" diff --git a/gcc/graphite-interchange.c b/gcc/graphite-interchange.c index 8690313da35..8ec021bf52b 100644 --- a/gcc/graphite-interchange.c +++ b/gcc/graphite-interchange.c @@ -36,6 +36,11 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "tree.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "tree-ssa-loop.h" diff --git a/gcc/graphite-optimize-isl.c b/gcc/graphite-optimize-isl.c index 2260c507f86..19f8bd1b48a 100644 --- a/gcc/graphite-optimize-isl.c +++ b/gcc/graphite-optimize-isl.c @@ -33,6 +33,11 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "tree.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "tree-ssa-loop.h" diff --git a/gcc/graphite-poly.c b/gcc/graphite-poly.c index d75359e8537..6b3cd67042f 100644 --- a/gcc/graphite-poly.c +++ b/gcc/graphite-poly.c @@ -36,6 +36,11 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "diagnostic-core.h" #include "tree.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "tree-ssa-loop.h" diff --git a/gcc/graphite-scop-detection.c b/gcc/graphite-scop-detection.c index 15c4c0f99ea..a8db98d2706 100644 --- a/gcc/graphite-scop-detection.c +++ b/gcc/graphite-scop-detection.c @@ -32,6 +32,11 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "tree.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimple-ssa.h" diff --git a/gcc/graphite-sese-to-poly.c b/gcc/graphite-sese-to-poly.c index efe14b39d53..532af1f0771 100644 --- a/gcc/graphite-sese-to-poly.c +++ b/gcc/graphite-sese-to-poly.c @@ -34,6 +34,11 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "tree.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimplify.h" @@ -56,7 +61,6 @@ along with GCC; see the file COPYING3. If not see #include "domwalk.h" #include "sese.h" #include "tree-ssa-propagate.h" -#include "expr.h" #ifdef HAVE_cloog #include "expr.h" diff --git a/gcc/graphite.c b/gcc/graphite.c index f87aede8420..e46710ca939 100644 --- a/gcc/graphite.c +++ b/gcc/graphite.c @@ -48,6 +48,11 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "diagnostic-core.h" #include "tree.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "tree-cfg.h" diff --git a/gcc/gsstruct.def b/gcc/gsstruct.def index 91738f40950..82f1f52a6f5 100644 --- a/gcc/gsstruct.def +++ b/gcc/gsstruct.def @@ -43,11 +43,11 @@ DEFGSSTRUCT(GSS_WCE, gimple_statement_wce, false) DEFGSSTRUCT(GSS_OMP, gimple_statement_omp, false) DEFGSSTRUCT(GSS_OMP_CRITICAL, gimple_statement_omp_critical, false) DEFGSSTRUCT(GSS_OMP_FOR, gimple_statement_omp_for, false) -DEFGSSTRUCT(GSS_OMP_PARALLEL, gimple_statement_omp_parallel, false) +DEFGSSTRUCT(GSS_OMP_PARALLEL_LAYOUT, gimple_statement_omp_parallel_layout, false) DEFGSSTRUCT(GSS_OMP_TASK, gimple_statement_omp_task, false) DEFGSSTRUCT(GSS_OMP_SECTIONS, gimple_statement_omp_sections, false) -DEFGSSTRUCT(GSS_OMP_SINGLE, gimple_statement_omp_single, false) +DEFGSSTRUCT(GSS_OMP_SINGLE_LAYOUT, gimple_statement_omp_single_layout, false) DEFGSSTRUCT(GSS_OMP_CONTINUE, gimple_statement_omp_continue, false) DEFGSSTRUCT(GSS_OMP_ATOMIC_LOAD, gimple_statement_omp_atomic_load, false) -DEFGSSTRUCT(GSS_OMP_ATOMIC_STORE, gimple_statement_omp_atomic_store, false) +DEFGSSTRUCT(GSS_OMP_ATOMIC_STORE_LAYOUT, gimple_statement_omp_atomic_store, false) DEFGSSTRUCT(GSS_TRANSACTION, gimple_statement_transaction, false) diff --git a/gcc/haifa-sched.c b/gcc/haifa-sched.c index 380244094fb..8d47eb93d53 100644 --- a/gcc/haifa-sched.c +++ b/gcc/haifa-sched.c @@ -6553,50 +6553,6 @@ setup_sched_dump (void) ? stderr : dump_file); } -/* Try to group comparison and the following conditional jump INSN if - they're already adjacent. This is to prevent scheduler from scheduling - them apart. */ - -static void -try_group_insn (rtx insn) -{ - unsigned int condreg1, condreg2; - rtx cc_reg_1; - rtx prev; - - if (!any_condjump_p (insn)) - return; - - targetm.fixed_condition_code_regs (&condreg1, &condreg2); - cc_reg_1 = gen_rtx_REG (CCmode, condreg1); - prev = prev_nonnote_nondebug_insn (insn); - if (!reg_referenced_p (cc_reg_1, PATTERN (insn)) - || !prev - || !modified_in_p (cc_reg_1, prev)) - return; - - /* Different microarchitectures support macro fusions for different - combinations of insn pairs. */ - if (!targetm.sched.macro_fusion_pair_p - || !targetm.sched.macro_fusion_pair_p (prev, insn)) - return; - - SCHED_GROUP_P (insn) = 1; -} - -/* If the last cond jump and the cond register defining insn are consecutive - before scheduling, we want them to be in a schedule group. This is good - for performance on microarchitectures supporting macro-fusion. */ - -static void -group_insns_for_macro_fusion () -{ - basic_block bb; - - FOR_EACH_BB (bb) - try_group_insn (BB_END (bb)); -} - /* Initialize some global state for the scheduler. This function works with the common data shared between all the schedulers. It is called from the scheduler specific initialization routine. */ @@ -6623,7 +6579,7 @@ sched_init (void) sched_pressure = SCHED_PRESSURE_NONE; if (sched_pressure != SCHED_PRESSURE_NONE) - ira_setup_eliminable_regset (false); + ira_setup_eliminable_regset (); /* Initialize SPEC_INFO. */ if (targetm.sched.set_sched_flags) @@ -6725,11 +6681,6 @@ sched_init (void) } curr_state = xmalloc (dfa_state_size); - - /* Group compare and branch insns for macro-fusion. */ - if (targetm.sched.macro_fusion_p - && targetm.sched.macro_fusion_p ()) - group_insns_for_macro_fusion (); } static void haifa_init_only_bb (basic_block, basic_block); diff --git a/gcc/hooks.c b/gcc/hooks.c index 50c1250f2cb..79c4b632e92 100644 --- a/gcc/hooks.c +++ b/gcc/hooks.c @@ -359,6 +359,13 @@ hook_rtx_tree_int_null (tree a ATTRIBUTE_UNUSED, int b ATTRIBUTE_UNUSED) return NULL; } +/* Generic hook that takes a machine mode and returns an unsigned int 0. */ +unsigned int +hook_uint_mode_0 (enum machine_mode m ATTRIBUTE_UNUSED) +{ + return 0; +} + /* Generic hook that takes three trees and returns the last one as is. */ tree hook_tree_tree_tree_tree_3rd_identity (tree a ATTRIBUTE_UNUSED, diff --git a/gcc/hooks.h b/gcc/hooks.h index 38a5fd414ed..eef8c2c37a0 100644 --- a/gcc/hooks.h +++ b/gcc/hooks.h @@ -93,6 +93,7 @@ extern tree hook_tree_tree_tree_tree_3rd_identity (tree, tree, tree); extern tree hook_tree_tree_int_treep_bool_null (tree, int, tree *, bool); extern unsigned hook_uint_void_0 (void); +extern unsigned int hook_uint_mode_0 (enum machine_mode); extern bool default_can_output_mi_thunk_no_vcall (const_tree, HOST_WIDE_INT, HOST_WIDE_INT, const_tree); diff --git a/gcc/input.h b/gcc/input.h index 8fdc7b28d92..55bd4260b0a 100644 --- a/gcc/input.h +++ b/gcc/input.h @@ -57,11 +57,8 @@ extern location_t input_location; ((tree) ((IS_ADHOC_LOC (LOC)) ? get_data_from_adhoc_loc (line_table, (LOC)) \ : NULL)) -#define input_line LOCATION_LINE (input_location) -#define input_filename LOCATION_FILE (input_location) #define in_system_header_at(LOC) \ ((linemap_location_in_system_header_p (line_table, LOC))) -#define in_system_header (in_system_header_at (input_location)) void dump_line_table_statistics (void); diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c index 867747041ae..9ae917ba0ac 100644 --- a/gcc/internal-fn.c +++ b/gcc/internal-fn.c @@ -25,6 +25,11 @@ along with GCC; see the file COPYING3. If not see #include "stor-layout.h" #include "expr.h" #include "optabs.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" /* The names of each internal function, indexed by function number. */ diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c index d0fa8db55d9..6fd7e9cfb95 100644 --- a/gcc/ipa-cp.c +++ b/gcc/ipa-cp.c @@ -104,7 +104,8 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "tree.h" -#include "gimple.h" +#include "gimple-fold.h" +#include "gimple-expr.h" #include "target.h" #include "ipa-prop.h" #include "bitmap.h" @@ -429,6 +430,13 @@ determine_versionability (struct cgraph_node *node) reason = "not a tree_versionable_function"; else if (cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE) reason = "insufficient body availability"; + else if (lookup_attribute ("omp declare simd", DECL_ATTRIBUTES (node->decl))) + { + /* Ideally we should clone the SIMD clones themselves and create + vector copies of them, so IPA-cp and SIMD clones can happily + coexist, but that may not be worth the effort. */ + reason = "function has SIMD clones"; + } if (reason && dump_file && !node->alias && !node->thunk.thunk_p) fprintf (dump_file, "Function %s/%i is not versionable, reason: %s.\n", diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c index 41e530082be..f272ccca812 100644 --- a/gcc/ipa-devirt.c +++ b/gcc/ipa-devirt.c @@ -115,12 +115,15 @@ along with GCC; see the file COPYING3. If not see #include "cgraph.h" #include "expr.h" #include "tree-pass.h" -#include "ggc.h" #include "pointer-set.h" #include "target.h" #include "hash-table.h" #include "tree-pretty-print.h" #include "ipa-utils.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "gimple-expr.h" #include "gimple.h" #include "ipa-inline.h" #include "diagnostic.h" @@ -1588,12 +1591,14 @@ ipa_devirt (void) return ndevirtualized ? TODO_remove_functions : 0; } -/* Gate for IPCP optimization. */ +/* Gate for speculative IPA devirtualization optimization. */ static bool gate_ipa_devirt (void) { - return flag_devirtualize_speculatively && optimize; + return (flag_devirtualize + && flag_devirtualize_speculatively + && optimize); } namespace { diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c index 3d95de144f9..ad6fe8febb6 100644 --- a/gcc/ipa-inline-analysis.c +++ b/gcc/ipa-inline-analysis.c @@ -80,7 +80,11 @@ along with GCC; see the file COPYING3. If not see #include "params.h" #include "tree-pass.h" #include "coverage.h" -#include "ggc.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimple-ssa.h" @@ -2498,7 +2502,8 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early) } - if (is_gimple_call (stmt)) + if (is_gimple_call (stmt) + && !gimple_call_internal_p (stmt)) { struct cgraph_edge *edge = cgraph_edge (node, stmt); struct inline_edge_summary *es = inline_edge_summary (edge); diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c index 54ec74ee191..38157caf829 100644 --- a/gcc/ipa-inline.c +++ b/gcc/ipa-inline.c @@ -106,9 +106,13 @@ along with GCC; see the file COPYING3. If not see #include "intl.h" #include "tree-pass.h" #include "coverage.h" -#include "ggc.h" #include "rtl.h" #include "bitmap.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-ssa.h" #include "ipa-prop.h" @@ -758,7 +762,7 @@ check_callers (struct cgraph_node *node, void *has_hot_call) { if (!can_inline_edge_p (e, true)) return true; - if (!has_hot_call && cgraph_maybe_hot_edge_p (e)) + if (!(*(bool *)has_hot_call) && cgraph_maybe_hot_edge_p (e)) *(bool *)has_hot_call = true; } return false; diff --git a/gcc/ipa-profile.c b/gcc/ipa-profile.c index 7ae001cc5e2..ef9e2422492 100644 --- a/gcc/ipa-profile.c +++ b/gcc/ipa-profile.c @@ -51,14 +51,15 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "cgraph.h" #include "tree-pass.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" #include "gimple.h" #include "gimple-iterator.h" -#include "ggc.h" #include "flags.h" #include "target.h" #include "tree-iterator.h" #include "ipa-utils.h" -#include "hash-table.h" #include "profile.h" #include "params.h" #include "value-prof.h" diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c index 39534425c53..acc01fcfbbb 100644 --- a/gcc/ipa-prop.c +++ b/gcc/ipa-prop.c @@ -21,6 +21,13 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "tree.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "expr.h" #include "stor-layout.h" @@ -30,7 +37,6 @@ along with GCC; see the file COPYING3. If not see #include "gimplify-me.h" #include "gimple-walk.h" #include "langhooks.h" -#include "ggc.h" #include "target.h" #include "ipa-prop.h" #include "bitmap.h" @@ -1418,7 +1424,7 @@ determine_known_aggregate_parts (gimple call, tree arg, lhs = gimple_assign_lhs (stmt); rhs = gimple_assign_rhs1 (stmt); - if (!is_gimple_reg_type (rhs) + if (!is_gimple_reg_type (TREE_TYPE (rhs)) || TREE_CODE (lhs) == BIT_FIELD_REF || contains_bitfld_component_ref_p (lhs)) break; @@ -3211,7 +3217,8 @@ ipa_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst, static void ipa_add_new_function (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED) { - ipa_analyze_node (node); + if (cgraph_function_with_gimple_body_p (node)) + ipa_analyze_node (node); } /* Register our cgraph hooks if they are not already there. */ @@ -3355,8 +3362,8 @@ ipa_get_vector_of_formal_parms (tree fndecl) /* Return a heap allocated vector containing types of formal parameters of function type FNTYPE. */ -static inline vec<tree> -get_vector_of_formal_parm_types (tree fntype) +vec<tree> +ipa_get_vector_of_formal_parm_types (tree fntype) { vec<tree> types; int count = 0; @@ -3378,32 +3385,22 @@ get_vector_of_formal_parm_types (tree fntype) base_index field. */ void -ipa_modify_formal_parameters (tree fndecl, ipa_parm_adjustment_vec adjustments, - const char *synth_parm_prefix) +ipa_modify_formal_parameters (tree fndecl, ipa_parm_adjustment_vec adjustments) { - vec<tree> oparms, otypes; - tree orig_type, new_type = NULL; - tree old_arg_types, t, new_arg_types = NULL; - tree parm, *link = &DECL_ARGUMENTS (fndecl); - int i, len = adjustments.length (); - tree new_reversed = NULL; - bool care_for_types, last_parm_void; - - if (!synth_parm_prefix) - synth_parm_prefix = "SYNTH"; - - oparms = ipa_get_vector_of_formal_parms (fndecl); - orig_type = TREE_TYPE (fndecl); - old_arg_types = TYPE_ARG_TYPES (orig_type); + vec<tree> oparms = ipa_get_vector_of_formal_parms (fndecl); + tree orig_type = TREE_TYPE (fndecl); + tree old_arg_types = TYPE_ARG_TYPES (orig_type); /* The following test is an ugly hack, some functions simply don't have any arguments in their type. This is probably a bug but well... */ - care_for_types = (old_arg_types != NULL_TREE); + bool care_for_types = (old_arg_types != NULL_TREE); + bool last_parm_void; + vec<tree> otypes; if (care_for_types) { last_parm_void = (TREE_VALUE (tree_last (old_arg_types)) == void_type_node); - otypes = get_vector_of_formal_parm_types (orig_type); + otypes = ipa_get_vector_of_formal_parm_types (orig_type); if (last_parm_void) gcc_assert (oparms.length () + 1 == otypes.length ()); else @@ -3415,16 +3412,23 @@ ipa_modify_formal_parameters (tree fndecl, ipa_parm_adjustment_vec adjustments, otypes.create (0); } - for (i = 0; i < len; i++) + int len = adjustments.length (); + tree *link = &DECL_ARGUMENTS (fndecl); + tree new_arg_types = NULL; + for (int i = 0; i < len; i++) { struct ipa_parm_adjustment *adj; gcc_assert (link); adj = &adjustments[i]; - parm = oparms[adj->base_index]; + tree parm; + if (adj->op == IPA_PARM_OP_NEW) + parm = NULL; + else + parm = oparms[adj->base_index]; adj->base = parm; - if (adj->copy_param) + if (adj->op == IPA_PARM_OP_COPY) { if (care_for_types) new_arg_types = tree_cons (NULL_TREE, otypes[adj->base_index], @@ -3432,7 +3436,7 @@ ipa_modify_formal_parameters (tree fndecl, ipa_parm_adjustment_vec adjustments, *link = parm; link = &DECL_CHAIN (parm); } - else if (!adj->remove_param) + else if (adj->op != IPA_PARM_OP_REMOVE) { tree new_parm; tree ptype; @@ -3447,8 +3451,8 @@ ipa_modify_formal_parameters (tree fndecl, ipa_parm_adjustment_vec adjustments, new_parm = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL_TREE, ptype); - DECL_NAME (new_parm) = create_tmp_var_name (synth_parm_prefix); - + const char *prefix = adj->arg_prefix ? adj->arg_prefix : "SYNTH"; + DECL_NAME (new_parm) = create_tmp_var_name (prefix); DECL_ARTIFICIAL (new_parm) = 1; DECL_ARG_TYPE (new_parm) = ptype; DECL_CONTEXT (new_parm) = fndecl; @@ -3456,17 +3460,20 @@ ipa_modify_formal_parameters (tree fndecl, ipa_parm_adjustment_vec adjustments, DECL_IGNORED_P (new_parm) = 1; layout_decl (new_parm, 0); - adj->base = parm; - adj->reduction = new_parm; + if (adj->op == IPA_PARM_OP_NEW) + adj->base = NULL; + else + adj->base = parm; + adj->new_decl = new_parm; *link = new_parm; - link = &DECL_CHAIN (new_parm); } } *link = NULL_TREE; + tree new_reversed = NULL; if (care_for_types) { new_reversed = nreverse (new_arg_types); @@ -3484,8 +3491,9 @@ ipa_modify_formal_parameters (tree fndecl, ipa_parm_adjustment_vec adjustments, Exception is METHOD_TYPEs must have THIS argument. When we are asked to remove it, we need to build new FUNCTION_TYPE instead. */ + tree new_type = NULL; if (TREE_CODE (orig_type) != METHOD_TYPE - || (adjustments[0].copy_param + || (adjustments[0].op == IPA_PARM_OP_COPY && adjustments[0].base_index == 0)) { new_type = build_distinct_type_copy (orig_type); @@ -3509,7 +3517,7 @@ ipa_modify_formal_parameters (tree fndecl, ipa_parm_adjustment_vec adjustments, /* This is a new type, not a copy of an old type. Need to reassociate variants. We can handle everything except the main variant lazily. */ - t = TYPE_MAIN_VARIANT (orig_type); + tree t = TYPE_MAIN_VARIANT (orig_type); if (orig_type != t) { TYPE_MAIN_VARIANT (new_type) = t; @@ -3558,13 +3566,13 @@ ipa_modify_call_arguments (struct cgraph_edge *cs, gimple stmt, adj = &adjustments[i]; - if (adj->copy_param) + if (adj->op == IPA_PARM_OP_COPY) { tree arg = gimple_call_arg (stmt, adj->base_index); vargs.quick_push (arg); } - else if (!adj->remove_param) + else if (adj->op != IPA_PARM_OP_REMOVE) { tree expr, base, off; location_t loc; @@ -3682,7 +3690,7 @@ ipa_modify_call_arguments (struct cgraph_edge *cs, gimple stmt, NULL, true, GSI_SAME_STMT); vargs.quick_push (expr); } - if (!adj->copy_param && MAY_HAVE_DEBUG_STMTS) + if (adj->op != IPA_PARM_OP_COPY && MAY_HAVE_DEBUG_STMTS) { unsigned int ix; tree ddecl = NULL_TREE, origin = DECL_ORIGIN (adj->base), arg; @@ -3757,6 +3765,124 @@ ipa_modify_call_arguments (struct cgraph_edge *cs, gimple stmt, free_dominance_info (CDI_DOMINATORS); } +/* If the expression *EXPR should be replaced by a reduction of a parameter, do + so. ADJUSTMENTS is a pointer to a vector of adjustments. CONVERT + specifies whether the function should care about type incompatibility the + current and new expressions. If it is false, the function will leave + incompatibility issues to the caller. Return true iff the expression + was modified. */ + +bool +ipa_modify_expr (tree *expr, bool convert, + ipa_parm_adjustment_vec adjustments) +{ + struct ipa_parm_adjustment *cand + = ipa_get_adjustment_candidate (&expr, &convert, adjustments, false); + if (!cand) + return false; + + tree src; + if (cand->by_ref) + src = build_simple_mem_ref (cand->new_decl); + else + src = cand->new_decl; + + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, "About to replace expr "); + print_generic_expr (dump_file, *expr, 0); + fprintf (dump_file, " with "); + print_generic_expr (dump_file, src, 0); + fprintf (dump_file, "\n"); + } + + if (convert && !useless_type_conversion_p (TREE_TYPE (*expr), cand->type)) + { + tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*expr), src); + *expr = vce; + } + else + *expr = src; + return true; +} + +/* If T is an SSA_NAME, return NULL if it is not a default def or + return its base variable if it is. If IGNORE_DEFAULT_DEF is true, + the base variable is always returned, regardless if it is a default + def. Return T if it is not an SSA_NAME. */ + +static tree +get_ssa_base_param (tree t, bool ignore_default_def) +{ + if (TREE_CODE (t) == SSA_NAME) + { + if (ignore_default_def || SSA_NAME_IS_DEFAULT_DEF (t)) + return SSA_NAME_VAR (t); + else + return NULL_TREE; + } + return t; +} + +/* Given an expression, return an adjustment entry specifying the + transformation to be done on EXPR. If no suitable adjustment entry + was found, returns NULL. + + If IGNORE_DEFAULT_DEF is set, consider SSA_NAMEs which are not a + default def, otherwise bail on them. + + If CONVERT is non-NULL, this function will set *CONVERT if the + expression provided is a component reference. ADJUSTMENTS is the + adjustments vector. */ + +ipa_parm_adjustment * +ipa_get_adjustment_candidate (tree **expr, bool *convert, + ipa_parm_adjustment_vec adjustments, + bool ignore_default_def) +{ + if (TREE_CODE (**expr) == BIT_FIELD_REF + || TREE_CODE (**expr) == IMAGPART_EXPR + || TREE_CODE (**expr) == REALPART_EXPR) + { + *expr = &TREE_OPERAND (**expr, 0); + if (convert) + *convert = true; + } + + HOST_WIDE_INT offset, size, max_size; + tree base = get_ref_base_and_extent (**expr, &offset, &size, &max_size); + if (!base || size == -1 || max_size == -1) + return NULL; + + if (TREE_CODE (base) == MEM_REF) + { + offset += mem_ref_offset (base).to_short_addr () * BITS_PER_UNIT; + base = TREE_OPERAND (base, 0); + } + + base = get_ssa_base_param (base, ignore_default_def); + if (!base || TREE_CODE (base) != PARM_DECL) + return NULL; + + struct ipa_parm_adjustment *cand = NULL; + unsigned int len = adjustments.length (); + for (unsigned i = 0; i < len; i++) + { + struct ipa_parm_adjustment *adj = &adjustments[i]; + + if (adj->base == base + && (adj->offset == offset || adj->op == IPA_PARM_OP_REMOVE)) + { + cand = adj; + break; + } + } + + if (!cand || cand->op == IPA_PARM_OP_COPY || cand->op == IPA_PARM_OP_REMOVE) + return NULL; + return cand; +} + /* Return true iff BASE_INDEX is in ADJUSTMENTS more than once. */ static bool @@ -3802,10 +3928,14 @@ ipa_combine_adjustments (ipa_parm_adjustment_vec inner, struct ipa_parm_adjustment *n; n = &inner[i]; - if (n->remove_param) + if (n->op == IPA_PARM_OP_REMOVE) removals++; else - tmp.quick_push (*n); + { + /* FIXME: Handling of new arguments are not implemented yet. */ + gcc_assert (n->op != IPA_PARM_OP_NEW); + tmp.quick_push (*n); + } } adjustments.create (outlen + removals); @@ -3816,27 +3946,32 @@ ipa_combine_adjustments (ipa_parm_adjustment_vec inner, struct ipa_parm_adjustment *in = &tmp[out->base_index]; memset (&r, 0, sizeof (r)); - gcc_assert (!in->remove_param); - if (out->remove_param) + gcc_assert (in->op != IPA_PARM_OP_REMOVE); + if (out->op == IPA_PARM_OP_REMOVE) { if (!index_in_adjustments_multiple_times_p (in->base_index, tmp)) { - r.remove_param = true; + r.op = IPA_PARM_OP_REMOVE; adjustments.quick_push (r); } continue; } + else + { + /* FIXME: Handling of new arguments are not implemented yet. */ + gcc_assert (out->op != IPA_PARM_OP_NEW); + } r.base_index = in->base_index; r.type = out->type; /* FIXME: Create nonlocal value too. */ - if (in->copy_param && out->copy_param) - r.copy_param = true; - else if (in->copy_param) + if (in->op == IPA_PARM_OP_COPY && out->op == IPA_PARM_OP_COPY) + r.op = IPA_PARM_OP_COPY; + else if (in->op == IPA_PARM_OP_COPY) r.offset = out->offset; - else if (out->copy_param) + else if (out->op == IPA_PARM_OP_COPY) r.offset = in->offset; else r.offset = in->offset + out->offset; @@ -3847,7 +3982,7 @@ ipa_combine_adjustments (ipa_parm_adjustment_vec inner, { struct ipa_parm_adjustment *n = &inner[i]; - if (n->remove_param) + if (n->op == IPA_PARM_OP_REMOVE) adjustments.quick_push (*n); } @@ -3884,10 +4019,10 @@ ipa_dump_param_adjustments (FILE *file, ipa_parm_adjustment_vec adjustments, fprintf (file, ", base: "); print_generic_expr (file, adj->base, 0); } - if (adj->reduction) + if (adj->new_decl) { - fprintf (file, ", reduction: "); - print_generic_expr (file, adj->reduction, 0); + fprintf (file, ", new_decl: "); + print_generic_expr (file, adj->new_decl, 0); } if (adj->new_ssa_base) { @@ -3895,9 +4030,9 @@ ipa_dump_param_adjustments (FILE *file, ipa_parm_adjustment_vec adjustments, print_generic_expr (file, adj->new_ssa_base, 0); } - if (adj->copy_param) + if (adj->op == IPA_PARM_OP_COPY) fprintf (file, ", copy_param"); - else if (adj->remove_param) + else if (adj->op == IPA_PARM_OP_REMOVE) fprintf (file, ", remove_param"); else fprintf (file, ", offset %li", (long) adj->offset); diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h index 4da22a1c05d..2fb00afcac2 100644 --- a/gcc/ipa-prop.h +++ b/gcc/ipa-prop.h @@ -609,6 +609,27 @@ extern alloc_pool ipcp_values_pool; extern alloc_pool ipcp_sources_pool; extern alloc_pool ipcp_agg_lattice_pool; +/* Operation to be performed for the parameter in ipa_parm_adjustment + below. */ +enum ipa_parm_op { + IPA_PARM_OP_NONE, + + /* This describes a brand new parameter. + + The field `type' should be set to the new type, `arg_prefix' + should be set to the string prefix for the new DECL_NAME, and + `new_decl' will ultimately hold the newly created argument. */ + IPA_PARM_OP_NEW, + + /* This new parameter is an unmodified parameter at index base_index. */ + IPA_PARM_OP_COPY, + + /* This adjustment describes a parameter that is about to be removed + completely. Most users will probably need to book keep those so that they + don't leave behinfd any non default def ssa names belonging to them. */ + IPA_PARM_OP_REMOVE +}; + /* Structure to describe transformations of formal parameters and actual arguments. Each instance describes one new parameter and they are meant to be stored in a vector. Additionally, most users will probably want to store @@ -632,10 +653,11 @@ struct ipa_parm_adjustment arguments. */ tree alias_ptr_type; - /* The new declaration when creating/replacing a parameter. Created by - ipa_modify_formal_parameters, useful for functions modifying the body - accordingly. */ - tree reduction; + /* The new declaration when creating/replacing a parameter. Created + by ipa_modify_formal_parameters, useful for functions modifying + the body accordingly. For brand new arguments, this is the newly + created argument. */ + tree new_decl; /* New declaration of a substitute variable that we may use to replace all non-default-def ssa names when a parm decl is going away. */ @@ -645,22 +667,19 @@ struct ipa_parm_adjustment is NULL), this is going to be its nonlocalized vars value. */ tree nonlocal_value; + /* This holds the prefix to be used for the new DECL_NAME. */ + const char *arg_prefix; + /* Offset into the original parameter (for the cases when the new parameter is a component of an original one). */ HOST_WIDE_INT offset; - /* Zero based index of the original parameter this one is based on. (ATM - there is no way to insert a new parameter out of the blue because there is - no need but if it arises the code can be easily exteded to do so.) */ + /* Zero based index of the original parameter this one is based on. */ int base_index; - /* This new parameter is an unmodified parameter at index base_index. */ - unsigned copy_param : 1; - - /* This adjustment describes a parameter that is about to be removed - completely. Most users will probably need to book keep those so that they - don't leave behinfd any non default def ssa names belonging to them. */ - unsigned remove_param : 1; + /* Whether this parameter is a new parameter, a copy of an old one, + or one about to be removed. */ + enum ipa_parm_op op; /* The parameter is to be passed by reference. */ unsigned by_ref : 1; @@ -671,8 +690,8 @@ typedef struct ipa_parm_adjustment ipa_parm_adjustment_t; typedef vec<ipa_parm_adjustment_t> ipa_parm_adjustment_vec; vec<tree> ipa_get_vector_of_formal_parms (tree fndecl); -void ipa_modify_formal_parameters (tree fndecl, ipa_parm_adjustment_vec, - const char *); +vec<tree> ipa_get_vector_of_formal_parm_types (tree fntype); +void ipa_modify_formal_parameters (tree fndecl, ipa_parm_adjustment_vec); void ipa_modify_call_arguments (struct cgraph_edge *, gimple, ipa_parm_adjustment_vec); ipa_parm_adjustment_vec ipa_combine_adjustments (ipa_parm_adjustment_vec, @@ -690,6 +709,10 @@ tree ipa_value_from_jfunc (struct ipa_node_params *info, struct ipa_jump_func *jfunc); unsigned int ipcp_transform_function (struct cgraph_node *node); void ipa_dump_param (FILE *, struct ipa_node_params *info, int i); +bool ipa_modify_expr (tree *, bool, ipa_parm_adjustment_vec); +ipa_parm_adjustment *ipa_get_adjustment_candidate (tree **, bool *, + ipa_parm_adjustment_vec, + bool); /* From tree-sra.c: */ diff --git a/gcc/ipa-pure-const.c b/gcc/ipa-pure-const.c index ed96c3c21ff..d84b35fd716 100644 --- a/gcc/ipa-pure-const.c +++ b/gcc/ipa-pure-const.c @@ -38,6 +38,12 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "print-tree.h" #include "calls.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimple-walk.h" @@ -46,8 +52,6 @@ along with GCC; see the file COPYING3. If not see #include "tree-inline.h" #include "tree-pass.h" #include "langhooks.h" -#include "pointer-set.h" -#include "ggc.h" #include "ipa-utils.h" #include "flags.h" #include "diagnostic.h" diff --git a/gcc/ipa-reference.c b/gcc/ipa-reference.c index 27208deb519..9e4eb0022fc 100644 --- a/gcc/ipa-reference.c +++ b/gcc/ipa-reference.c @@ -42,12 +42,15 @@ along with GCC; see the file COPYING3. If not see #include "tm.h" #include "tree.h" #include "calls.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "tree-inline.h" #include "tree-pass.h" -#include "pointer-set.h" #include "splay-tree.h" -#include "ggc.h" #include "ipa-utils.h" #include "ipa-reference.h" #include "flags.h" diff --git a/gcc/ipa-split.c b/gcc/ipa-split.c index 2e8a062da6b..d2e2d6f3d19 100644 --- a/gcc/ipa-split.c +++ b/gcc/ipa-split.c @@ -78,6 +78,11 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "tree.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "stringpool.h" #include "expr.h" diff --git a/gcc/ipa-utils.c b/gcc/ipa-utils.c index 1aa239d3b7d..312d75ddbfd 100644 --- a/gcc/ipa-utils.c +++ b/gcc/ipa-utils.c @@ -23,13 +23,16 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tm.h" #include "tree.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "tree-inline.h" #include "dumpfile.h" #include "langhooks.h" -#include "pointer-set.h" #include "splay-tree.h" -#include "ggc.h" #include "ipa-utils.h" #include "ipa-reference.h" #include "flags.h" diff --git a/gcc/ipa.c b/gcc/ipa.c index 3950d4eb856..520a5bbdaec 100644 --- a/gcc/ipa.c +++ b/gcc/ipa.c @@ -26,11 +26,10 @@ along with GCC; see the file COPYING3. If not see #include "stringpool.h" #include "cgraph.h" #include "tree-pass.h" -#include "gimple.h" +#include "pointer-set.h" +#include "gimple-expr.h" #include "gimplify.h" -#include "ggc.h" #include "flags.h" -#include "pointer-set.h" #include "target.h" #include "tree-iterator.h" #include "ipa-utils.h" @@ -247,7 +246,7 @@ walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets, hope calls to them will be devirtualized. Again we remove them after inlining. In late optimization some - devirtualization may happen, but it is not importnat since we won't inline + devirtualization may happen, but it is not important since we won't inline the call. In theory early opts and IPA should work out all important cases. - virtual clones needs bodies of their origins for later materialization; @@ -275,7 +274,7 @@ walk_polymorphic_call_targets (pointer_set_t *reachable_call_targets, by reachable symbols or origins of clones). The queue is represented as linked list by AUX pointer terminated by 1. - A the end we keep all reachable symbols. For symbols in boundary we always + At the end we keep all reachable symbols. For symbols in boundary we always turn definition into a declaration, but we may keep function body around based on body_needed_for_clonning @@ -427,6 +426,19 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file) enqueue_node (cnode, &first, reachable); } } + + } + /* If any reachable function has simd clones, mark them as + reachable as well. */ + if (cnode->simd_clones) + { + cgraph_node *next; + for (next = cnode->simd_clones; + next; + next = next->simdclone->next_clone) + if (in_boundary_p + || !pointer_set_insert (reachable, next)) + enqueue_node (next, &first, reachable); } } /* When we see constructor of external variable, keep referred nodes in the @@ -1263,11 +1275,9 @@ make_pass_ipa_whole_program_visibility (gcc::context *ctxt) } /* Generate and emit a static constructor or destructor. WHICH must - be one of 'I' (for a constructor), 'D' (for a destructor), 'P' - (for chp static vars constructor) or 'B' (for chkp static bounds - constructor). BODY is a STATEMENT_LIST containing GENERIC - statements. PRIORITY is the initialization priority for this - constructor or destructor. + be one of 'I' (for a constructor) or 'D' (for a destructor). BODY + is a STATEMENT_LIST containing GENERIC statements. PRIORITY is the + initialization priority for this constructor or destructor. FINAL specify whether the externally visible name for collect2 should be produced. */ @@ -1326,20 +1336,6 @@ cgraph_build_static_cdtor_1 (char which, tree body, int priority, bool final) DECL_STATIC_CONSTRUCTOR (decl) = 1; decl_init_priority_insert (decl, priority); break; - case 'P': - DECL_STATIC_CONSTRUCTOR (decl) = 1; - DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("chkp ctor"), - NULL, - NULL_TREE); - decl_init_priority_insert (decl, priority); - break; - case 'B': - DECL_STATIC_CONSTRUCTOR (decl) = 1; - DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("bnd_legacy"), - NULL, - NULL_TREE); - decl_init_priority_insert (decl, priority); - break; case 'D': DECL_STATIC_DESTRUCTOR (decl) = 1; decl_fini_priority_insert (decl, priority); @@ -1357,11 +1353,9 @@ cgraph_build_static_cdtor_1 (char which, tree body, int priority, bool final) } /* Generate and emit a static constructor or destructor. WHICH must - be one of 'I' (for a constructor), 'D' (for a destructor), 'P' - (for chkp static vars constructor) or 'B' (for chkp static bounds - constructor). BODY is a STATEMENT_LIST containing GENERIC - statements. PRIORITY is the initialization priority for this - constructor or destructor. */ + be one of 'I' (for a constructor) or 'D' (for a destructor). BODY + is a STATEMENT_LIST containing GENERIC statements. PRIORITY is the + initialization priority for this constructor or destructor. */ void cgraph_build_static_cdtor (char which, tree body, int priority) diff --git a/gcc/ira.c b/gcc/ira.c index 93a2bbdc90e..b3477ae9162 100644 --- a/gcc/ira.c +++ b/gcc/ira.c @@ -2380,11 +2380,10 @@ compute_regs_asm_clobbered (void) } -/* Set up ELIMINABLE_REGSET, IRA_NO_ALLOC_REGS, and REGS_EVER_LIVE. - If the function is called from IRA (not from the insn scheduler or - RTL loop invariant motion), FROM_IRA_P is true. */ +/* Set up ELIMINABLE_REGSET, IRA_NO_ALLOC_REGS, and + REGS_EVER_LIVE. */ void -ira_setup_eliminable_regset (bool from_ira_p) +ira_setup_eliminable_regset (void) { #ifdef ELIMINABLE_REGS int i; @@ -2401,16 +2400,16 @@ ira_setup_eliminable_regset (bool from_ira_p) if the stack pointer is moving. */ || (flag_stack_check && STACK_CHECK_MOVING_SP) || crtl->accesses_prior_frames - || crtl->stack_realign_needed + || (SUPPORTS_STACK_ALIGNMENT && crtl->stack_realign_needed) /* We need a frame pointer for all Cilk Plus functions that use Cilk keywords. */ || (flag_enable_cilkplus && cfun->is_cilk_function) || targetm.frame_pointer_required ()); - if (from_ira_p && ira_use_lra_p) - /* It can change FRAME_POINTER_NEEDED. We call it only from IRA - because it is expensive. */ - lra_init_elimination (); + /* The chance that FRAME_POINTER_NEEDED is changed from inspecting + RTL is very small. So if we use frame pointer for RA and RTL + actually prevents this, we will spill pseudos assigned to the + frame pointer in LRA. */ if (frame_pointer_needed) df_set_regs_ever_live (HARD_FRAME_POINTER_REGNUM, true); @@ -4812,7 +4811,7 @@ find_moveable_pseudos (void) { rtx def_reg = DF_REF_REG (def); rtx newreg = ira_create_new_reg (def_reg); - if (validate_change (def_insn, DF_REF_LOC (def), newreg, 0)) + if (validate_change (def_insn, DF_REF_REAL_LOC (def), newreg, 0)) { unsigned nregno = REGNO (newreg); emit_insn_before (gen_move_insn (def_reg, newreg), use_insn); @@ -4847,17 +4846,13 @@ find_moveable_pseudos (void) free_dominance_info (CDI_DOMINATORS); } - -/* If insn is interesting for parameter range-splitting shring-wrapping - preparation, i.e. it is a single set from a hard register to a pseudo, which - is live at CALL_DOM, return the destination. Otherwise return NULL. */ +/* If SET pattern SET is an assignment from a hard register to a pseudo which + is live at CALL_DOM (if non-NULL, otherwise this check is omitted), return + the destination. Otherwise return NULL. */ static rtx -interesting_dest_for_shprep (rtx insn, basic_block call_dom) +interesting_dest_for_shprep_1 (rtx set, basic_block call_dom) { - rtx set = single_set (insn); - if (!set) - return NULL; rtx src = SET_SRC (set); rtx dest = SET_DEST (set); if (!REG_P (src) || !HARD_REGISTER_P (src) @@ -4867,6 +4862,41 @@ interesting_dest_for_shprep (rtx insn, basic_block call_dom) return dest; } +/* If insn is interesting for parameter range-splitting shring-wrapping + preparation, i.e. it is a single set from a hard register to a pseudo, which + is live at CALL_DOM (if non-NULL, otherwise this check is omitted), or a + parallel statement with only one such statement, return the destination. + Otherwise return NULL. */ + +static rtx +interesting_dest_for_shprep (rtx insn, basic_block call_dom) +{ + if (!INSN_P (insn)) + return NULL; + rtx pat = PATTERN (insn); + if (GET_CODE (pat) == SET) + return interesting_dest_for_shprep_1 (pat, call_dom); + + if (GET_CODE (pat) != PARALLEL) + return NULL; + rtx ret = NULL; + for (int i = 0; i < XVECLEN (pat, 0); i++) + { + rtx sub = XVECEXP (pat, 0, i); + if (GET_CODE (sub) == USE || GET_CODE (sub) == CLOBBER) + continue; + if (GET_CODE (sub) != SET + || side_effects_p (sub)) + return NULL; + rtx dest = interesting_dest_for_shprep_1 (sub, call_dom); + if (dest && ret) + return NULL; + if (dest) + ret = dest; + } + return ret; +} + /* Split live ranges of pseudos that are loaded from hard registers in the first BB in a BB that dominates all non-sibling call if such a BB can be found and is not in a loop. Return true if the function has made any @@ -5003,7 +5033,7 @@ split_live_ranges_for_shrink_wrap (void) rtx newreg = NULL_RTX; df_ref use, next; - for (use = DF_REG_USE_CHAIN (REGNO(dest)); use; use = next) + for (use = DF_REG_USE_CHAIN (REGNO (dest)); use; use = next) { rtx uin = DF_REF_INSN (use); next = DF_REF_NEXT_REG (use); @@ -5014,7 +5044,7 @@ split_live_ranges_for_shrink_wrap (void) { if (!newreg) newreg = ira_create_new_reg (dest); - validate_change (uin, DF_REF_LOC (use), newreg, true); + validate_change (uin, DF_REF_REAL_LOC (use), newreg, true); } } @@ -5260,7 +5290,7 @@ ira (FILE *f) find_moveable_pseudos (); max_regno_before_ira = max_reg_num (); - ira_setup_eliminable_regset (true); + ira_setup_eliminable_regset (); ira_overall_cost = ira_reg_cost = ira_mem_cost = 0; ira_load_cost = ira_store_cost = ira_shuffle_cost = 0; diff --git a/gcc/ira.h b/gcc/ira.h index f71c8012443..3a1824b3369 100644 --- a/gcc/ira.h +++ b/gcc/ira.h @@ -178,7 +178,7 @@ extern struct ira_reg_equiv *ira_reg_equiv; extern void ira_init_once (void); extern void ira_init (void); extern void ira_finish_once (void); -extern void ira_setup_eliminable_regset (bool); +extern void ira_setup_eliminable_regset (void); extern rtx ira_eliminate_regs (rtx, enum machine_mode); extern void ira_set_pseudo_classes (bool, FILE *); extern void ira_implicitly_set_insn_hard_regs (HARD_REG_SET *); diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog index 0e277e4bf40..3b8a95a6baf 100644 --- a/gcc/java/ChangeLog +++ b/gcc/java/ChangeLog @@ -1,3 +1,17 @@ +2013-11-22 Andrew MacLeod <amacleod@redhat.com> + + * java-gimplify.c: Add required include files from gimple.h. + +2013-11-22 David Malcolm <dmalcolm@redhat.com> + + * class.c (maybe_layout_super_class): Update comment. + * decl.c (java_add_stmt): Remove use of input_filename macro. + * jcf-parse.c (set_source_filename): Remove use of + input_filename macro. + (parse_class_file): Remove use of input_line and input_filename + macros. + (java_parse_file): Remove use of input_filename macro. + 2013-11-18 Richard Sandiford <rdsandiford@googlemail.com> * class.c, expr.c: Replace tree_low_cst (..., 0) with tree_to_shwi diff --git a/gcc/java/class.c b/gcc/java/class.c index 58bc92f94d9..532c9c1d94f 100644 --- a/gcc/java/class.c +++ b/gcc/java/class.c @@ -2415,7 +2415,7 @@ maybe_layout_super_class (tree super_class, tree this_class ATTRIBUTE_UNUSED) } /* safe_layout_class just makes sure that we can load a class without - disrupting the current_class, input_file, input_line, etc, information + disrupting the current_class, input_location, etc, information about the class processed currently. */ void diff --git a/gcc/java/decl.c b/gcc/java/decl.c index 70e21b071f0..39b76a5cea0 100644 --- a/gcc/java/decl.c +++ b/gcc/java/decl.c @@ -2018,7 +2018,7 @@ java_add_stmt (tree new_stmt) tree stmts = current_binding_level->stmts; tree_stmt_iterator i; - if (input_filename) + if (LOCATION_FILE (input_location)) walk_tree (&new_stmt, set_input_location, NULL, NULL); if (stmts == NULL) diff --git a/gcc/java/java-gimplify.c b/gcc/java/java-gimplify.c index f2d0460ae31..cf1f97007ed 100644 --- a/gcc/java/java-gimplify.c +++ b/gcc/java/java-gimplify.c @@ -27,6 +27,11 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */ #include "tree.h" #include "java-tree.h" #include "dumpfile.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" diff --git a/gcc/java/jcf-parse.c b/gcc/java/jcf-parse.c index fbd332cb7c0..5c84ddb711d 100644 --- a/gcc/java/jcf-parse.c +++ b/gcc/java/jcf-parse.c @@ -314,13 +314,14 @@ set_source_filename (JCF *jcf, int index) { tree sfname_id = get_name_constant (jcf, index); const char *sfname = IDENTIFIER_POINTER (sfname_id); - const char *old_filename = input_filename; + const char *old_filename = LOCATION_FILE (input_location); int new_len = IDENTIFIER_LENGTH (sfname_id); if (old_filename != NULL) { int old_len = strlen (old_filename); - /* Use the current input_filename (derived from the class name) - if it has a directory prefix, but otherwise matches sfname. */ + /* Use the filename from current input_location (derived from the + class name) if it has a directory prefix, but otherwise matches + sfname. */ if (old_len > new_len && filename_cmp (sfname, old_filename + old_len - new_len) == 0 && (old_filename[old_len - new_len - 1] == '/' @@ -1560,7 +1561,8 @@ parse_class_file (void) linemap_add (line_table, LC_ENTER, 0, loc.file, loc.line); } file_start_location = input_location; - (*debug_hooks->start_source_file) (input_line, input_filename); + (*debug_hooks->start_source_file) (LOCATION_LINE (input_location), + LOCATION_FILE (input_location)); java_mark_class_local (current_class); @@ -1618,7 +1620,8 @@ parse_class_file (void) for (ptr += 2; --i >= 0; ptr += 4) { int line = GET_u2 (ptr); - /* Set initial input_line to smallest linenumber. + /* Set initial line of input_location to smallest + * linenumber. * Needs to be set before init_function_start. */ if (min_line == 0 || line < min_line) min_line = line; @@ -1748,7 +1751,7 @@ java_parse_file (void) int avail = 2000; finput = fopen (main_input_filename, "r"); if (finput == NULL) - fatal_error ("can%'t open %s: %m", input_filename); + fatal_error ("can%'t open %s: %m", LOCATION_FILE (input_location)); list = XNEWVEC (char, avail); next = list; for (;;) @@ -1767,7 +1770,8 @@ java_parse_file (void) if (count == 0) { if (! feof (finput)) - fatal_error ("error closing %s: %m", input_filename); + fatal_error ("error closing %s: %m", + LOCATION_FILE (input_location)); *next = '\0'; break; } diff --git a/gcc/langhooks.c b/gcc/langhooks.c index 4b72f2a6238..7fe349d4f2c 100644 --- a/gcc/langhooks.c +++ b/gcc/langhooks.c @@ -28,7 +28,6 @@ along with GCC; see the file COPYING3. If not see #include "stringpool.h" #include "attribs.h" #include "tree-inline.h" -#include "gimple.h" #include "gimplify.h" #include "rtl.h" #include "insn-config.h" @@ -36,7 +35,6 @@ along with GCC; see the file COPYING3. If not see #include "langhooks.h" #include "target.h" #include "langhooks-def.h" -#include "ggc.h" #include "diagnostic.h" #include "tree-diagnostic.h" #include "cgraph.h" diff --git a/gcc/loop-invariant.c b/gcc/loop-invariant.c index efe2e7a9f16..9f1fc07900c 100644 --- a/gcc/loop-invariant.c +++ b/gcc/loop-invariant.c @@ -1823,7 +1823,7 @@ calculate_loop_reg_pressure (void) bitmap_initialize (&LOOP_DATA (loop)->regs_ref, ®_obstack); bitmap_initialize (&LOOP_DATA (loop)->regs_live, ®_obstack); } - ira_setup_eliminable_regset (false); + ira_setup_eliminable_regset (); bitmap_initialize (&curr_regs_live, ®_obstack); FOR_EACH_BB (bb) { diff --git a/gcc/loop-unroll.c b/gcc/loop-unroll.c index c0d61b2e22d..b8df05b390a 100644 --- a/gcc/loop-unroll.c +++ b/gcc/loop-unroll.c @@ -664,6 +664,9 @@ decide_unroll_constant_iterations (struct loop *loop, int flags) if (nunroll > (unsigned) PARAM_VALUE (PARAM_MAX_UNROLL_TIMES)) nunroll = PARAM_VALUE (PARAM_MAX_UNROLL_TIMES); + if (targetm.loop_unroll_adjust) + nunroll = targetm.loop_unroll_adjust (nunroll, loop); + /* Skip big loops. */ if (nunroll <= 1) { diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c index 4c88cca669d..bb5242a962a 100644 --- a/gcc/lra-constraints.c +++ b/gcc/lra-constraints.c @@ -318,7 +318,7 @@ in_mem_p (int regno) /* If we have decided to substitute X with another value, return that value, otherwise return X. */ static rtx -get_equiv_substitution (rtx x) +get_equiv (rtx x) { int regno; rtx res; @@ -337,6 +337,19 @@ get_equiv_substitution (rtx x) gcc_unreachable (); } +/* If we have decided to substitute X with the equivalent value, + return that value after elimination for INSN, otherwise return + X. */ +static rtx +get_equiv_with_elimination (rtx x, rtx insn) +{ + rtx res = get_equiv (x); + + if (x == res || CONSTANT_P (res)) + return res; + return lra_eliminate_regs_1 (insn, res, GET_MODE (res), false, false, true); +} + /* Set up curr_operand_mode. */ static void init_curr_operand_mode (void) @@ -1101,7 +1114,7 @@ process_addr_reg (rtx *loc, rtx *before, rtx *after, enum reg_class cl) { regno = REGNO (reg); rclass = get_reg_class (regno); - if ((*loc = get_equiv_substitution (reg)) != reg) + if ((*loc = get_equiv_with_elimination (reg, curr_insn)) != reg) { if (lra_dump_file != NULL) { @@ -2007,6 +2020,13 @@ process_alt_operands (int only_alternative) int const_to_mem = 0; bool no_regs_p; + /* Never do output reload of stack pointer. It makes + impossible to do elimination when SP is changed in + RTL. */ + if (op == stack_pointer_rtx && ! frame_pointer_needed + && curr_static_id->operand[nop].type != OP_IN) + goto fail; + /* If this alternative asks for a specific reg class, see if there is at least one allocatable register in that class. */ no_regs_p @@ -2517,7 +2537,7 @@ equiv_address_substitution (struct address_info *ad) else { base_reg = *base_term; - new_base_reg = get_equiv_substitution (base_reg); + new_base_reg = get_equiv_with_elimination (base_reg, curr_insn); } index_term = strip_subreg (ad->index_term); if (index_term == NULL) @@ -2525,7 +2545,7 @@ equiv_address_substitution (struct address_info *ad) else { index_reg = *index_term; - new_index_reg = get_equiv_substitution (index_reg); + new_index_reg = get_equiv_with_elimination (index_reg, curr_insn); } if (base_reg == new_base_reg && index_reg == new_index_reg) return false; @@ -3055,7 +3075,7 @@ curr_insn_transform (void) if (GET_CODE (old) == SUBREG) old = SUBREG_REG (old); - subst = get_equiv_substitution (old); + subst = get_equiv_with_elimination (old, curr_insn); if (subst != old) { subst = copy_rtx (subst); @@ -3260,6 +3280,9 @@ curr_insn_transform (void) if (INSN_CODE (curr_insn) >= 0 && (p = get_insn_name (INSN_CODE (curr_insn))) != NULL) fprintf (lra_dump_file, " {%s}", p); + if (curr_id->sp_offset != 0) + fprintf (lra_dump_file, " (sp_off=%" HOST_WIDE_INT_PRINT "d)", + curr_id->sp_offset); fprintf (lra_dump_file, "\n"); } @@ -3638,7 +3661,7 @@ loc_equivalence_change_p (rtx *loc) if (code == SUBREG) { reg = SUBREG_REG (x); - if ((subst = get_equiv_substitution (reg)) != reg + if ((subst = get_equiv_with_elimination (reg, curr_insn)) != reg && GET_MODE (subst) == VOIDmode) { /* We cannot reload debug location. Simplify subreg here @@ -3648,7 +3671,7 @@ loc_equivalence_change_p (rtx *loc) return true; } } - if (code == REG && (subst = get_equiv_substitution (x)) != x) + if (code == REG && (subst = get_equiv_with_elimination (x, curr_insn)) != x) { *loc = subst; return true; @@ -3676,7 +3699,7 @@ loc_equivalence_callback (rtx loc, const_rtx, void *) if (!REG_P (loc)) return NULL_RTX; - rtx subst = get_equiv_substitution (loc); + rtx subst = get_equiv_with_elimination (loc, curr_insn); if (subst != loc) return subst; @@ -3848,21 +3871,27 @@ lra_constraints (bool first_p) lra_risky_transformations_p = false; new_insn_uid_start = get_max_uid (); new_regno_start = first_p ? lra_constraint_new_regno_start : max_reg_num (); + /* Mark used hard regs for target stack size calulations. */ + for (i = FIRST_PSEUDO_REGISTER; i < new_regno_start; i++) + if (lra_reg_info[i].nrefs != 0 + && (hard_regno = lra_get_regno_hard_regno (i)) >= 0) + { + int j, nregs; + + nregs = hard_regno_nregs[hard_regno][lra_reg_info[i].biggest_mode]; + for (j = 0; j < nregs; j++) + df_set_regs_ever_live (hard_regno + j, true); + } + /* Do elimination before the equivalence processing as we can spill + some pseudos during elimination. */ + lra_eliminate (false, first_p); bitmap_initialize (&equiv_insn_bitmap, ®_obstack); for (i = FIRST_PSEUDO_REGISTER; i < new_regno_start; i++) if (lra_reg_info[i].nrefs != 0) { ira_reg_equiv[i].profitable_p = true; reg = regno_reg_rtx[i]; - if ((hard_regno = lra_get_regno_hard_regno (i)) >= 0) - { - int j, nregs; - - nregs = hard_regno_nregs[hard_regno][lra_reg_info[i].biggest_mode]; - for (j = 0; j < nregs; j++) - df_set_regs_ever_live (hard_regno + j, true); - } - else if ((x = get_equiv_substitution (reg)) != reg) + if (lra_get_regno_hard_regno (i) < 0 && (x = get_equiv (reg)) != reg) { bool pseudo_p = contains_reg_p (x, false, false); @@ -3911,7 +3940,7 @@ lra_constraints (bool first_p) ira_reg_equiv[i].defined_p = false; if (contains_reg_p (x, false, true)) ira_reg_equiv[i].profitable_p = false; - if (get_equiv_substitution (reg) != reg) + if (get_equiv (reg) != reg) bitmap_ior_into (&equiv_insn_bitmap, &lra_reg_info[i].insn_bitmap); } } @@ -3919,7 +3948,6 @@ lra_constraints (bool first_p) substituted by their equivalences. */ EXECUTE_IF_SET_IN_BITMAP (&equiv_insn_bitmap, 0, uid, bi) lra_push_insn_by_uid (uid); - lra_eliminate (false); min_len = lra_insn_stack_length (); new_insns_num = 0; last_bb = NULL; @@ -3973,7 +4001,7 @@ lra_constraints (bool first_p) if (GET_CODE (dest_reg) == SUBREG) dest_reg = SUBREG_REG (dest_reg); if ((REG_P (dest_reg) - && (x = get_equiv_substitution (dest_reg)) != dest_reg + && (x = get_equiv (dest_reg)) != dest_reg /* Remove insns which set up a pseudo whose value can not be changed. Such insns might be not in init_insns because we don't update equiv data @@ -3993,8 +4021,7 @@ lra_constraints (bool first_p) || in_list_p (curr_insn, ira_reg_equiv [REGNO (dest_reg)].init_insns))) - || (((x = get_equiv_substitution (SET_SRC (set))) - != SET_SRC (set)) + || (((x = get_equiv (SET_SRC (set))) != SET_SRC (set)) && in_list_p (curr_insn, ira_reg_equiv [REGNO (SET_SRC (set))].init_insns))) diff --git a/gcc/lra-eliminations.c b/gcc/lra-eliminations.c index 2eddb9dd85a..915e3a0677f 100644 --- a/gcc/lra-eliminations.c +++ b/gcc/lra-eliminations.c @@ -286,10 +286,11 @@ get_elimination (rtx reg) } /* Scan X and replace any eliminable registers (such as fp) with a - replacement (such as sp) if SUBST_P, plus an offset. The offset is + replacement (such as sp) if SUBST_P, plus an offset. The offset is a change in the offset between the eliminable register and its substitution if UPDATE_P, or the full offset if FULL_P, or - otherwise zero. + otherwise zero. If FULL_P, we also use the SP offsets for + elimination to SP. MEM_MODE is the mode of an enclosing MEM. We need this to know how much to adjust a register for, e.g., PRE_DEC. Also, if we are @@ -298,10 +299,10 @@ get_elimination (rtx reg) outside a MEM. In addition, we need to record the fact that a hard register is referenced outside a MEM. - Alternatively, INSN may be a note (an EXPR_LIST or INSN_LIST). - That's used when we eliminate in expressions stored in notes. */ + If we make full substitution to SP for non-null INSN, add the insn + sp offset. */ rtx -lra_eliminate_regs_1 (rtx x, enum machine_mode mem_mode, +lra_eliminate_regs_1 (rtx insn, rtx x, enum machine_mode mem_mode, bool subst_p, bool update_p, bool full_p) { enum rtx_code code = GET_CODE (x); @@ -311,6 +312,7 @@ lra_eliminate_regs_1 (rtx x, enum machine_mode mem_mode, const char *fmt; int copied = 0; + gcc_assert (!update_p || !full_p); if (! current_function_decl) return x; @@ -338,7 +340,12 @@ lra_eliminate_regs_1 (rtx x, enum machine_mode mem_mode, if (update_p) return plus_constant (Pmode, to, ep->offset - ep->previous_offset); else if (full_p) - return plus_constant (Pmode, to, ep->offset); + return plus_constant (Pmode, to, + ep->offset + - (insn != NULL_RTX + && ep->to_rtx == stack_pointer_rtx + ? lra_get_insn_recog_data (insn)->sp_offset + : 0)); else return to; } @@ -359,6 +366,8 @@ lra_eliminate_regs_1 (rtx x, enum machine_mode mem_mode, offset = (update_p ? ep->offset - ep->previous_offset : ep->offset); + if (full_p && insn != NULL_RTX && ep->to_rtx == stack_pointer_rtx) + offset -= lra_get_insn_recog_data (insn)->sp_offset; if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) == -offset) return to; @@ -384,9 +393,9 @@ lra_eliminate_regs_1 (rtx x, enum machine_mode mem_mode, an address operand of a load-address insn. */ { - rtx new0 = lra_eliminate_regs_1 (XEXP (x, 0), mem_mode, + rtx new0 = lra_eliminate_regs_1 (insn, XEXP (x, 0), mem_mode, subst_p, update_p, full_p); - rtx new1 = lra_eliminate_regs_1 (XEXP (x, 1), mem_mode, + rtx new1 = lra_eliminate_regs_1 (insn, XEXP (x, 1), mem_mode, subst_p, update_p, full_p); if (new0 != XEXP (x, 0) || new1 != XEXP (x, 1)) @@ -412,10 +421,16 @@ lra_eliminate_regs_1 (rtx x, enum machine_mode mem_mode, (ep->offset - ep->previous_offset) * INTVAL (XEXP (x, 1))); else if (full_p) - return - plus_constant (Pmode, - gen_rtx_MULT (Pmode, to, XEXP (x, 1)), - ep->offset * INTVAL (XEXP (x, 1))); + { + HOST_WIDE_INT offset = ep->offset; + + if (insn != NULL_RTX && ep->to_rtx == stack_pointer_rtx) + offset -= lra_get_insn_recog_data (insn)->sp_offset; + return + plus_constant (Pmode, + gen_rtx_MULT (Pmode, to, XEXP (x, 1)), + offset * INTVAL (XEXP (x, 1))); + } else return gen_rtx_MULT (Pmode, to, XEXP (x, 1)); } @@ -435,10 +450,10 @@ lra_eliminate_regs_1 (rtx x, enum machine_mode mem_mode, case GE: case GT: case GEU: case GTU: case LE: case LT: case LEU: case LTU: { - rtx new0 = lra_eliminate_regs_1 (XEXP (x, 0), mem_mode, + rtx new0 = lra_eliminate_regs_1 (insn, XEXP (x, 0), mem_mode, subst_p, update_p, full_p); rtx new1 = XEXP (x, 1) - ? lra_eliminate_regs_1 (XEXP (x, 1), mem_mode, + ? lra_eliminate_regs_1 (insn, XEXP (x, 1), mem_mode, subst_p, update_p, full_p) : 0; if (new0 != XEXP (x, 0) || new1 != XEXP (x, 1)) @@ -451,7 +466,7 @@ lra_eliminate_regs_1 (rtx x, enum machine_mode mem_mode, eliminate it. */ if (XEXP (x, 0)) { - new_rtx = lra_eliminate_regs_1 (XEXP (x, 0), mem_mode, + new_rtx = lra_eliminate_regs_1 (insn, XEXP (x, 0), mem_mode, subst_p, update_p, full_p); if (new_rtx != XEXP (x, 0)) { @@ -460,7 +475,7 @@ lra_eliminate_regs_1 (rtx x, enum machine_mode mem_mode, REG_DEAD note for the stack or frame pointer. */ if (REG_NOTE_KIND (x) == REG_DEAD) return (XEXP (x, 1) - ? lra_eliminate_regs_1 (XEXP (x, 1), mem_mode, + ? lra_eliminate_regs_1 (insn, XEXP (x, 1), mem_mode, subst_p, update_p, full_p) : NULL_RTX); @@ -477,7 +492,7 @@ lra_eliminate_regs_1 (rtx x, enum machine_mode mem_mode, strictly needed, but it simplifies the code. */ if (XEXP (x, 1)) { - new_rtx = lra_eliminate_regs_1 (XEXP (x, 1), mem_mode, + new_rtx = lra_eliminate_regs_1 (insn, XEXP (x, 1), mem_mode, subst_p, update_p, full_p); if (new_rtx != XEXP (x, 1)) return @@ -504,7 +519,8 @@ lra_eliminate_regs_1 (rtx x, enum machine_mode mem_mode, if (GET_CODE (XEXP (x, 1)) == PLUS && XEXP (XEXP (x, 1), 0) == XEXP (x, 0)) { - rtx new_rtx = lra_eliminate_regs_1 (XEXP (XEXP (x, 1), 1), mem_mode, + rtx new_rtx = lra_eliminate_regs_1 (insn, XEXP (XEXP (x, 1), 1), + mem_mode, subst_p, update_p, full_p); if (new_rtx != XEXP (XEXP (x, 1), 1)) @@ -528,14 +544,14 @@ lra_eliminate_regs_1 (rtx x, enum machine_mode mem_mode, case POPCOUNT: case PARITY: case BSWAP: - new_rtx = lra_eliminate_regs_1 (XEXP (x, 0), mem_mode, + new_rtx = lra_eliminate_regs_1 (insn, XEXP (x, 0), mem_mode, subst_p, update_p, full_p); if (new_rtx != XEXP (x, 0)) return gen_rtx_fmt_e (code, GET_MODE (x), new_rtx); return x; case SUBREG: - new_rtx = lra_eliminate_regs_1 (SUBREG_REG (x), mem_mode, + new_rtx = lra_eliminate_regs_1 (insn, SUBREG_REG (x), mem_mode, subst_p, update_p, full_p); if (new_rtx != SUBREG_REG (x)) @@ -563,12 +579,12 @@ lra_eliminate_regs_1 (rtx x, enum machine_mode mem_mode, return replace_equiv_address_nv (x, - lra_eliminate_regs_1 (XEXP (x, 0), GET_MODE (x), + lra_eliminate_regs_1 (insn, XEXP (x, 0), GET_MODE (x), subst_p, update_p, full_p)); case USE: /* Handle insn_list USE that a call to a pure function may generate. */ - new_rtx = lra_eliminate_regs_1 (XEXP (x, 0), VOIDmode, + new_rtx = lra_eliminate_regs_1 (insn, XEXP (x, 0), VOIDmode, subst_p, update_p, full_p); if (new_rtx != XEXP (x, 0)) return gen_rtx_USE (GET_MODE (x), new_rtx); @@ -589,7 +605,7 @@ lra_eliminate_regs_1 (rtx x, enum machine_mode mem_mode, { if (*fmt == 'e') { - new_rtx = lra_eliminate_regs_1 (XEXP (x, i), mem_mode, + new_rtx = lra_eliminate_regs_1 (insn, XEXP (x, i), mem_mode, subst_p, update_p, full_p); if (new_rtx != XEXP (x, i) && ! copied) { @@ -603,7 +619,7 @@ lra_eliminate_regs_1 (rtx x, enum machine_mode mem_mode, int copied_vec = 0; for (j = 0; j < XVECLEN (x, i); j++) { - new_rtx = lra_eliminate_regs_1 (XVECEXP (x, i, j), mem_mode, + new_rtx = lra_eliminate_regs_1 (insn, XVECEXP (x, i, j), mem_mode, subst_p, update_p, full_p); if (new_rtx != XVECEXP (x, i, j) && ! copied_vec) { @@ -631,16 +647,21 @@ rtx lra_eliminate_regs (rtx x, enum machine_mode mem_mode, rtx insn ATTRIBUTE_UNUSED) { - return lra_eliminate_regs_1 (x, mem_mode, true, false, true); + return lra_eliminate_regs_1 (NULL_RTX, x, mem_mode, true, false, true); } +/* Stack pointer offset before the current insn relative to one at the + func start. RTL insns can change SP explicitly. We keep the + changes from one insn to another through this variable. */ +static HOST_WIDE_INT curr_sp_change; + /* Scan rtx X for references to elimination source or target registers in contexts that would prevent the elimination from happening. Update the table of eliminables to reflect the changed state. MEM_MODE is the mode of an enclosing MEM rtx, or VOIDmode if not within a MEM. */ static void -mark_not_eliminable (rtx x) +mark_not_eliminable (rtx x, enum machine_mode mem_mode) { enum rtx_code code = GET_CODE (x); struct elim_table *ep; @@ -655,17 +676,40 @@ mark_not_eliminable (rtx x) case POST_DEC: case POST_MODIFY: case PRE_MODIFY: - if (REG_P (XEXP (x, 0)) && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER) - /* If we modify the source of an elimination rule, disable - it. Do the same if it is the source and not the hard frame - register. */ - for (ep = reg_eliminate; - ep < ®_eliminate[NUM_ELIMINABLE_REGS]; + if (XEXP (x, 0) == stack_pointer_rtx + && ((code != PRE_MODIFY && code != POST_MODIFY) + || (GET_CODE (XEXP (x, 1)) == PLUS + && XEXP (x, 0) == XEXP (XEXP (x, 1), 0) + && CONST_INT_P (XEXP (XEXP (x, 1), 1))))) + { + int size = GET_MODE_SIZE (mem_mode); + +#ifdef PUSH_ROUNDING + /* If more bytes than MEM_MODE are pushed, account for + them. */ + size = PUSH_ROUNDING (size); +#endif + if (code == PRE_DEC || code == POST_DEC) + curr_sp_change -= size; + else if (code == PRE_INC || code == POST_INC) + curr_sp_change += size; + else if (code == PRE_MODIFY || code == POST_MODIFY) + curr_sp_change += INTVAL (XEXP (XEXP (x, 1), 1)); + } + else if (REG_P (XEXP (x, 0)) + && REGNO (XEXP (x, 0)) >= FIRST_PSEUDO_REGISTER) + { + /* If we modify the source of an elimination rule, disable + it. Do the same if it is the destination and not the + hard frame register. */ + for (ep = reg_eliminate; + ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++) - if (ep->from_rtx == XEXP (x, 0) - || (ep->to_rtx == XEXP (x, 0) - && ep->to_rtx != hard_frame_pointer_rtx)) - setup_can_eliminate (ep, false); + if (ep->from_rtx == XEXP (x, 0) + || (ep->to_rtx == XEXP (x, 0) + && ep->to_rtx != hard_frame_pointer_rtx)) + setup_can_eliminate (ep, false); + } return; case USE: @@ -697,12 +741,22 @@ mark_not_eliminable (rtx x) return; case SET: - /* Check for setting a hard register that we know about. */ - if (REG_P (SET_DEST (x)) && REGNO (SET_DEST (x)) < FIRST_PSEUDO_REGISTER) + if (SET_DEST (x) == stack_pointer_rtx + && GET_CODE (SET_SRC (x)) == PLUS + && XEXP (SET_SRC (x), 0) == SET_DEST (x) + && CONST_INT_P (XEXP (SET_SRC (x), 1))) + { + curr_sp_change += INTVAL (XEXP (SET_SRC (x), 1)); + return; + } + if (! REG_P (SET_DEST (x)) + || REGNO (SET_DEST (x)) >= FIRST_PSEUDO_REGISTER) + mark_not_eliminable (SET_DEST (x), mem_mode); + else { /* See if this is setting the replacement hard register for an elimination. - + If DEST is the hard frame pointer, we do nothing because we assume that all assignments to the frame pointer are for non-local gotos and are being done at a time when @@ -711,22 +765,21 @@ mark_not_eliminable (rtx x) even a fake frame pointer) with either the real frame pointer or the stack pointer. Assignments to the hard frame pointer must not prevent this elimination. */ - for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++) if (ep->to_rtx == SET_DEST (x) - && SET_DEST (x) != hard_frame_pointer_rtx - && (! (SUPPORTS_STACK_ALIGNMENT && stack_realign_fp - && REGNO (ep->to_rtx) == STACK_POINTER_REGNUM) - || GET_CODE (SET_SRC (x)) != PLUS - || XEXP (SET_SRC (x), 0) != SET_DEST (x) - || ! CONST_INT_P (XEXP (SET_SRC (x), 1)))) + && SET_DEST (x) != hard_frame_pointer_rtx) setup_can_eliminate (ep, false); } + + mark_not_eliminable (SET_SRC (x), mem_mode); + return; - mark_not_eliminable (SET_DEST (x)); - mark_not_eliminable (SET_SRC (x)); + case MEM: + /* Our only special processing is to pass the mode of the MEM to + our recursive call. */ + mark_not_eliminable (XEXP (x, 0), GET_MODE (x)); return; default: @@ -737,10 +790,10 @@ mark_not_eliminable (rtx x) for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++) { if (*fmt == 'e') - mark_not_eliminable (XEXP (x, i)); + mark_not_eliminable (XEXP (x, i), mem_mode); else if (*fmt == 'E') for (j = 0; j < XVECLEN (x, i); j++) - mark_not_eliminable (XVECEXP (x, i, j)); + mark_not_eliminable (XVECEXP (x, i, j), mem_mode); } } @@ -778,13 +831,14 @@ remove_reg_equal_offset_note (rtx insn, rtx what) delete the insn as dead it if it is setting an eliminable register. If REPLACE_P is false, just update the offsets while keeping the - base register the same. Attach the note about used elimination for + base register the same. If FIRST_P, use the sp offset for + elimination to sp. Attach the note about used elimination for insns setting frame pointer to update elimination easy (without parsing already generated elimination insns to find offset previously used) in future. */ static void -eliminate_regs_in_insn (rtx insn, bool replace_p) +eliminate_regs_in_insn (rtx insn, bool replace_p, bool first_p) { int icode = recog_memoized (insn); rtx old_set = single_set (insn); @@ -914,6 +968,8 @@ eliminate_regs_in_insn (rtx insn, bool replace_p) if (! replace_p) { offset += (ep->offset - ep->previous_offset); + if (first_p && ep->to_rtx == stack_pointer_rtx) + offset -= lra_get_insn_recog_data (insn)->sp_offset; offset = trunc_int_for_mode (offset, GET_MODE (plus_cst_src)); } @@ -985,8 +1041,9 @@ eliminate_regs_in_insn (rtx insn, bool replace_p) /* Companion to the above plus substitution, we can allow invariants as the source of a plain move. */ substed_operand[i] - = lra_eliminate_regs_1 (*id->operand_loc[i], VOIDmode, - replace_p, ! replace_p, false); + = lra_eliminate_regs_1 (insn, *id->operand_loc[i], VOIDmode, + replace_p, ! replace_p && ! first_p, + first_p); if (substed_operand[i] != orig_operand[i]) validate_p = true; } @@ -1054,7 +1111,7 @@ spill_pseudos (HARD_REG_SET set) } /* Update all offsets and possibility for elimination on eliminable - registers. Spill pseudos assigned to registers which became + registers. Spill pseudos assigned to registers which are uneliminable, update LRA_NO_ALLOC_REGS and ELIMINABLE_REG_SET. Add insns to INSNS_WITH_CHANGED_OFFSETS containing eliminable hard registers whose offsets should be changed. Return true if any @@ -1069,7 +1126,6 @@ update_reg_eliminate (bitmap insns_with_changed_offsets) /* Clear self elimination offsets. */ for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++) self_elim_offsets[ep->from] = 0; - CLEAR_HARD_REG_SET (temp_hard_reg_set); for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++) { /* If it is a currently used elimination: update the previous @@ -1096,6 +1152,9 @@ update_reg_eliminate (bitmap insns_with_changed_offsets) fprintf (lra_dump_file, " Elimination %d to %d is not possible anymore\n", ep->from, ep->to); + /* If after processing RTL we decides that SP can be used as + a result of elimination, it can not be changed. */ + gcc_assert (ep->to_rtx != stack_pointer_rtx); /* Mark that is not eliminable anymore. */ elimination_map[ep->from] = NULL; for (ep1 = ep + 1; ep1 < ®_eliminate[NUM_ELIMINABLE_REGS]; ep1++) @@ -1106,9 +1165,6 @@ update_reg_eliminate (bitmap insns_with_changed_offsets) if (lra_dump_file != NULL) fprintf (lra_dump_file, " Using elimination %d to %d now\n", ep1->from, ep1->to); - /* Prevent the hard register into which we eliminate now - from the usage for pseudos. */ - SET_HARD_REG_BIT (temp_hard_reg_set, ep1->to); lra_assert (ep1->previous_offset == 0); ep1->previous_offset = ep->offset; } @@ -1121,7 +1177,6 @@ update_reg_eliminate (bitmap insns_with_changed_offsets) fprintf (lra_dump_file, " %d is not eliminable at all\n", ep->from); self_elim_offsets[ep->from] = -ep->offset; - SET_HARD_REG_BIT (temp_hard_reg_set, ep->from); if (ep->offset != 0) bitmap_ior_into (insns_with_changed_offsets, &lra_reg_info[ep->from].insn_bitmap); @@ -1134,23 +1189,33 @@ update_reg_eliminate (bitmap insns_with_changed_offsets) INITIAL_FRAME_POINTER_OFFSET (ep->offset); #endif } - IOR_HARD_REG_SET (lra_no_alloc_regs, temp_hard_reg_set); - AND_COMPL_HARD_REG_SET (eliminable_regset, temp_hard_reg_set); - spill_pseudos (temp_hard_reg_set); setup_elimination_map (); result = false; + CLEAR_HARD_REG_SET (temp_hard_reg_set); for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++) - if (elimination_map[ep->from] == ep && ep->previous_offset != ep->offset) + if (elimination_map[ep->from] == NULL) + SET_HARD_REG_BIT (temp_hard_reg_set, ep->from); + else if (elimination_map[ep->from] == ep) { - bitmap_ior_into (insns_with_changed_offsets, - &lra_reg_info[ep->from].insn_bitmap); - - /* Update offset when the eliminate offset have been - changed. */ - lra_update_reg_val_offset (lra_reg_info[ep->from].val, - ep->offset - ep->previous_offset); - result = true; + /* Prevent the hard register into which we eliminate from + the usage for pseudos. */ + if (ep->from != ep->to) + SET_HARD_REG_BIT (temp_hard_reg_set, ep->to); + if (ep->previous_offset != ep->offset) + { + bitmap_ior_into (insns_with_changed_offsets, + &lra_reg_info[ep->from].insn_bitmap); + + /* Update offset when the eliminate offset have been + changed. */ + lra_update_reg_val_offset (lra_reg_info[ep->from].val, + ep->offset - ep->previous_offset); + result = true; + } } + IOR_HARD_REG_SET (lra_no_alloc_regs, temp_hard_reg_set); + AND_COMPL_HARD_REG_SET (eliminable_regset, temp_hard_reg_set); + spill_pseudos (temp_hard_reg_set); return result; } @@ -1194,31 +1259,54 @@ init_elim_table (void) setup_can_eliminate (®_eliminate[0], ! frame_pointer_needed); #endif - /* Count the number of eliminable registers and build the FROM and TO - REG rtx's. Note that code in gen_rtx_REG will cause, e.g., - gen_rtx_REG (Pmode, STACK_POINTER_REGNUM) to equal stack_pointer_rtx. - We depend on this. */ + /* Build the FROM and TO REG rtx's. Note that code in gen_rtx_REG + will cause, e.g., gen_rtx_REG (Pmode, STACK_POINTER_REGNUM) to + equal stack_pointer_rtx. We depend on this. Threfore we switch + off that we are in LRA temporarily. */ + lra_in_progress = 0; for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++) { ep->from_rtx = gen_rtx_REG (Pmode, ep->from); ep->to_rtx = gen_rtx_REG (Pmode, ep->to); eliminable_reg_rtx[ep->from] = ep->from_rtx; } + lra_in_progress = 1; } -/* Entry function for initialization of elimination once per - function. */ -void -lra_init_elimination (void) +/* Function for initialization of elimination once per function. It + sets up sp offset for each insn. */ +static void +init_elimination (void) { + bool stop_to_sp_elimination_p; basic_block bb; rtx insn; + struct elim_table *ep; init_elim_table (); FOR_EACH_BB (bb) - FOR_BB_INSNS (bb, insn) - if (NONDEBUG_INSN_P (insn)) - mark_not_eliminable (PATTERN (insn)); + { + curr_sp_change = 0; + stop_to_sp_elimination_p = false; + FOR_BB_INSNS (bb, insn) + if (INSN_P (insn)) + { + lra_get_insn_recog_data (insn)->sp_offset = curr_sp_change; + if (NONDEBUG_INSN_P (insn)) + { + mark_not_eliminable (PATTERN (insn), VOIDmode); + if (curr_sp_change != 0 + && find_reg_note (insn, REG_LABEL_OPERAND, NULL_RTX)) + stop_to_sp_elimination_p = true; + } + } + if (! frame_pointer_needed + && (curr_sp_change != 0 || stop_to_sp_elimination_p) + && bb->succs && bb->succs->length () != 0) + for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++) + if (ep->to == STACK_POINTER_REGNUM) + setup_can_eliminate (ep, false); + } setup_elimination_map (); } @@ -1237,12 +1325,13 @@ lra_eliminate_reg_if_possible (rtx *loc) *loc = ep->to_rtx; } -/* Do (final if FINAL_P) elimination in INSN. Add the insn for - subsequent processing in the constraint pass, update the insn info. */ +/* Do (final if FINAL_P or first if FIRST_P) elimination in INSN. Add + the insn for subsequent processing in the constraint pass, update + the insn info. */ static void -process_insn_for_elimination (rtx insn, bool final_p) +process_insn_for_elimination (rtx insn, bool final_p, bool first_p) { - eliminate_regs_in_insn (insn, final_p); + eliminate_regs_in_insn (insn, final_p, first_p); if (! final_p) { /* Check that insn changed its code. This is a case when a move @@ -1262,20 +1351,23 @@ process_insn_for_elimination (rtx insn, bool final_p) } /* Entry function to do final elimination if FINAL_P or to update - elimination register offsets. */ + elimination register offsets (FIRST_P if we are doing it the first + time). */ void -lra_eliminate (bool final_p) +lra_eliminate (bool final_p, bool first_p) { - int i; unsigned int uid; - rtx mem_loc, invariant; bitmap_head insns_with_changed_offsets; bitmap_iterator bi; struct elim_table *ep; - int regs_num = max_reg_num (); + + gcc_assert (! final_p || ! first_p); timevar_push (TV_LRA_ELIMINATE); + if (first_p) + init_elimination (); + bitmap_initialize (&insns_with_changed_offsets, ®_obstack); if (final_p) { @@ -1299,28 +1391,11 @@ lra_eliminate (bool final_p) fprintf (lra_dump_file, "New elimination table:\n"); print_elim_table (lra_dump_file); } - for (i = FIRST_PSEUDO_REGISTER; i < regs_num; i++) - if (lra_reg_info[i].nrefs != 0) - { - mem_loc = ira_reg_equiv[i].memory; - if (mem_loc != NULL_RTX) - mem_loc = lra_eliminate_regs_1 (mem_loc, VOIDmode, - final_p, ! final_p, false); - ira_reg_equiv[i].memory = mem_loc; - invariant = ira_reg_equiv[i].invariant; - if (invariant != NULL_RTX) - invariant = lra_eliminate_regs_1 (invariant, VOIDmode, - final_p, ! final_p, false); - ira_reg_equiv[i].invariant = invariant; - if (lra_dump_file != NULL - && (mem_loc != NULL_RTX || invariant != NULL)) - fprintf (lra_dump_file, - "Updating elimination of equiv for reg %d\n", i); - } EXECUTE_IF_SET_IN_BITMAP (&insns_with_changed_offsets, 0, uid, bi) /* A dead insn can be deleted in process_insn_for_elimination. */ if (lra_insn_recog_data[uid] != NULL) - process_insn_for_elimination (lra_insn_recog_data[uid]->insn, final_p); + process_insn_for_elimination (lra_insn_recog_data[uid]->insn, + final_p, first_p); bitmap_clear (&insns_with_changed_offsets); lra_eliminate_done: diff --git a/gcc/lra-int.h b/gcc/lra-int.h index c545d9d354f..6d8d80fc592 100644 --- a/gcc/lra-int.h +++ b/gcc/lra-int.h @@ -207,6 +207,12 @@ struct lra_insn_recog_data { /* The insn code. */ int icode; + /* The alternative should be used for the insn, -1 if invalid, or we + should try to use any alternative, or the insn is a debug + insn. */ + int used_insn_alternative; + /* SP offset before the insn relative to one at the func start. */ + HOST_WIDE_INT sp_offset; /* The insn itself. */ rtx insn; /* Common data for insns with the same ICODE. Asm insns (their @@ -222,10 +228,6 @@ struct lra_insn_recog_data int *arg_hard_regs; /* Alternative enabled for the insn. NULL for debug insns. */ bool *alternative_enabled_p; - /* The alternative should be used for the insn, -1 if invalid, or we - should try to use any alternative, or the insn is a debug - insn. */ - int used_insn_alternative; /* The following member value is always NULL for a debug insn. */ struct lra_insn_reg *regs; }; @@ -377,8 +379,8 @@ extern void lra_final_code_change (void); extern void lra_debug_elim_table (void); extern int lra_get_elimination_hard_regno (int); -extern rtx lra_eliminate_regs_1 (rtx, enum machine_mode, bool, bool, bool); -extern void lra_eliminate (bool); +extern rtx lra_eliminate_regs_1 (rtx, rtx, enum machine_mode, bool, bool, bool); +extern void lra_eliminate (bool, bool); extern void lra_eliminate_reg_if_possible (rtx *); diff --git a/gcc/lra-spills.c b/gcc/lra-spills.c index 4ab10c25b98..6bebb92fd83 100644 --- a/gcc/lra-spills.c +++ b/gcc/lra-spills.c @@ -163,7 +163,6 @@ assign_mem_slot (int i) x = assign_stack_local (mode, total_size, min_align > inherent_align || total_size > inherent_size ? -1 : 0); - x = lra_eliminate_regs_1 (x, GET_MODE (x), false, false, true); stack_slot = x; /* Cancel the big-endian correction done in assign_stack_local. Get the address of the beginning of the slot. This is so we @@ -430,8 +429,15 @@ remove_pseudos (rtx *loc, rtx insn) into scratches back. */ && ! lra_former_scratch_p (i)) { - hard_reg = spill_hard_reg[i]; - *loc = copy_rtx (hard_reg != NULL_RTX ? hard_reg : pseudo_slots[i].mem); + if ((hard_reg = spill_hard_reg[i]) != NULL_RTX) + *loc = copy_rtx (hard_reg); + else + { + rtx x = lra_eliminate_regs_1 (insn, pseudo_slots[i].mem, + GET_MODE (pseudo_slots[i].mem), + false, false, true); + *loc = x != pseudo_slots[i].mem ? x : copy_rtx (x); + } return; } @@ -477,9 +483,30 @@ spill_pseudos (void) FOR_BB_INSNS (bb, insn) if (bitmap_bit_p (&changed_insns, INSN_UID (insn))) { + rtx *link_loc, link; remove_pseudos (&PATTERN (insn), insn); if (CALL_P (insn)) remove_pseudos (&CALL_INSN_FUNCTION_USAGE (insn), insn); + for (link_loc = ®_NOTES (insn); + (link = *link_loc) != NULL_RTX; + link_loc = &XEXP (link, 1)) + { + switch (REG_NOTE_KIND (link)) + { + case REG_FRAME_RELATED_EXPR: + case REG_CFA_DEF_CFA: + case REG_CFA_ADJUST_CFA: + case REG_CFA_OFFSET: + case REG_CFA_REGISTER: + case REG_CFA_EXPRESSION: + case REG_CFA_RESTORE: + case REG_CFA_SET_VDRAP: + remove_pseudos (&XEXP (link, 0), insn); + break; + default: + break; + } + } if (lra_dump_file != NULL) fprintf (lra_dump_file, "Changing spilled pseudos to memory in insn #%u\n", diff --git a/gcc/lra.c b/gcc/lra.c index f4791a2de8b..d21d8646a61 100644 --- a/gcc/lra.c +++ b/gcc/lra.c @@ -207,7 +207,8 @@ lra_set_regno_unique_value (int regno) lra_reg_info[regno].val = get_new_reg_value (); } -/* Invalidate INSN related info used by LRA. */ +/* Invalidate INSN related info used by LRA. The info should never be + used after that. */ void lra_invalidate_insn_data (rtx insn) { @@ -1273,17 +1274,24 @@ lra_update_insn_recog_data (rtx insn) int n; unsigned int uid = INSN_UID (insn); struct lra_static_insn_data *insn_static_data; + HOST_WIDE_INT sp_offset = 0; check_and_expand_insn_recog_data (uid); if ((data = lra_insn_recog_data[uid]) != NULL && data->icode != INSN_CODE (insn)) { + sp_offset = data->sp_offset; invalidate_insn_data_regno_info (data, insn, get_insn_freq (insn)); invalidate_insn_recog_data (uid); data = NULL; } if (data == NULL) - return lra_get_insn_recog_data (insn); + { + data = lra_get_insn_recog_data (insn); + /* Initiate or restore SP offset. */ + data->sp_offset = sp_offset; + return data; + } insn_static_data = data->insn_static_data; data->used_insn_alternative = -1; if (DEBUG_INSN_P (insn)) @@ -1837,6 +1845,20 @@ push_insns (rtx from, rtx to) lra_push_insn (insn); } +/* Set up sp offset for insn in range [FROM, LAST]. The offset is + taken from the next BB insn after LAST or zero if there in such + insn. */ +static void +setup_sp_offset (rtx from, rtx last) +{ + rtx before = next_nonnote_insn_bb (last); + HOST_WIDE_INT offset = (before == NULL_RTX || ! INSN_P (before) + ? 0 : lra_get_insn_recog_data (before)->sp_offset); + + for (rtx insn = from; insn != NEXT_INSN (last); insn = NEXT_INSN (insn)) + lra_get_insn_recog_data (insn)->sp_offset = offset; +} + /* Emit insns BEFORE before INSN and insns AFTER after INSN. Put the insns onto the stack. Print about emitting the insns with TITLE. */ @@ -1845,7 +1867,9 @@ lra_process_new_insns (rtx insn, rtx before, rtx after, const char *title) { rtx last; - if (lra_dump_file != NULL && (before != NULL_RTX || after != NULL_RTX)) + if (before == NULL_RTX && after == NULL_RTX) + return; + if (lra_dump_file != NULL) { dump_insn_slim (lra_dump_file, insn); if (before != NULL_RTX) @@ -1864,6 +1888,7 @@ lra_process_new_insns (rtx insn, rtx before, rtx after, const char *title) { emit_insn_before (before, insn); push_insns (PREV_INSN (insn), PREV_INSN (before)); + setup_sp_offset (before, PREV_INSN (insn)); } if (after != NULL_RTX) { @@ -1871,6 +1896,7 @@ lra_process_new_insns (rtx insn, rtx before, rtx after, const char *title) ; emit_insn_after (after, insn); push_insns (last, insn); + setup_sp_offset (after, last); } } @@ -2040,8 +2066,9 @@ check_rtl (bool final_p) correctly decomposed. LRA can generate reloads for decomposable addresses. The decomposition code checks the correctness of the addresses. So we don't need to check - the addresses here. */ - if (insn_invalid_p (insn, false)) + the addresses here. Don't call insn_invalid_p here, it can + change the code at this stage. */ + if (recog_memoized (insn) < 0 && asm_noperands (PATTERN (insn)) < 0) fatal_insn_not_found (insn); } } @@ -2240,14 +2267,13 @@ lra (FILE *f) init_insn_recog_data (); - /* We can not set up reload_in_progress because it prevents new - pseudo creation. */ - lra_in_progress = 1; - #ifdef ENABLE_CHECKING + /* Some quick check on RTL generated by previous passes. */ check_rtl (false); #endif + lra_in_progress = 1; + lra_live_range_iter = lra_coalesce_iter = 0; lra_constraint_iter = lra_constraint_iter_after_spill = 0; lra_inheritance_iter = lra_undo_inheritance_iter = 0; @@ -2314,7 +2340,7 @@ lra (FILE *f) For example, rs6000 can make RS6000_PIC_OFFSET_TABLE_REGNUM uneliminable if we started to use a constant pool. */ - lra_eliminate (false); + lra_eliminate (false, false); /* Do inheritance only for regular algorithms. */ if (! lra_simple_p) lra_inheritance (); @@ -2368,13 +2394,13 @@ lra (FILE *f) lra_spill (); /* Assignment of stack slots changes elimination offsets for some eliminations. So update the offsets here. */ - lra_eliminate (false); + lra_eliminate (false, false); lra_constraint_new_regno_start = max_reg_num (); lra_constraint_new_insn_uid_start = get_max_uid (); lra_constraint_iter_after_spill = 0; } restore_scratches (); - lra_eliminate (true); + lra_eliminate (true, false); lra_final_code_change (); lra_in_progress = 0; if (live_p) diff --git a/gcc/lra.h b/gcc/lra.h index 06dee292e95..31388694586 100644 --- a/gcc/lra.h +++ b/gcc/lra.h @@ -33,7 +33,6 @@ lra_get_allocno_class (int regno) extern rtx lra_create_new_reg (enum machine_mode, rtx, enum reg_class, const char *); -extern void lra_init_elimination (void); extern rtx lra_eliminate_regs (rtx, enum machine_mode, rtx); extern void lra (FILE *); extern void lra_init_once (void); diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c index 0f1a1c5e9a0..6f2773c70ba 100644 --- a/gcc/lto-cgraph.c +++ b/gcc/lto-cgraph.c @@ -26,6 +26,11 @@ along with GCC; see the file COPYING3. If not see #include "tm.h" #include "tree.h" #include "stringpool.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "expr.h" #include "flags.h" @@ -33,15 +38,11 @@ along with GCC; see the file COPYING3. If not see #include "input.h" #include "hashtab.h" #include "langhooks.h" -#include "basic-block.h" #include "bitmap.h" #include "function.h" -#include "ggc.h" #include "diagnostic-core.h" #include "except.h" -#include "vec.h" #include "timevar.h" -#include "pointer-set.h" #include "lto-streamer.h" #include "data-streamer.h" #include "tree-streamer.h" @@ -580,7 +581,6 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, struct varpool_node && boundary_p && !DECL_EXTERNAL (node->decl), 1); /* in_other_partition. */ } - bp_pack_value (&bp, node->need_bounds_init, 1); streamer_write_bitpack (&bp); if (node->same_comdat_group && !boundary_p) { @@ -1151,7 +1151,6 @@ input_varpool_node (struct lto_file_decl_data *file_data, node->analyzed = bp_unpack_value (&bp, 1); node->used_from_other_partition = bp_unpack_value (&bp, 1); node->in_other_partition = bp_unpack_value (&bp, 1); - node->need_bounds_init = bp_unpack_value (&bp, 1); if (node->in_other_partition) { DECL_EXTERNAL (node->decl) = 1; diff --git a/gcc/lto-compress.c b/gcc/lto-compress.c index 3a67616cf8b..737323fb106 100644 --- a/gcc/lto-compress.c +++ b/gcc/lto-compress.c @@ -28,6 +28,11 @@ along with GCC; see the file COPYING3. If not see #include <zlib.h> #include "coretypes.h" #include "tree.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "diagnostic-core.h" #include "langhooks.h" diff --git a/gcc/lto-opts.c b/gcc/lto-opts.c index 2cb536bfc55..df5d8f165fd 100644 --- a/gcc/lto-opts.c +++ b/gcc/lto-opts.c @@ -23,10 +23,13 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "tree.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "hashtab.h" -#include "ggc.h" -#include "vec.h" #include "bitmap.h" #include "flags.h" #include "opts.h" diff --git a/gcc/lto-section-in.c b/gcc/lto-section-in.c index e4f0aedfa0f..8d778bbb0df 100644 --- a/gcc/lto-section-in.c +++ b/gcc/lto-section-in.c @@ -24,22 +24,23 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tm.h" #include "tree.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "expr.h" #include "flags.h" #include "params.h" #include "input.h" #include "hashtab.h" -#include "basic-block.h" #include "function.h" -#include "ggc.h" #include "diagnostic-core.h" #include "except.h" -#include "vec.h" #include "timevar.h" #include "lto-streamer.h" #include "lto-compress.h" -#include "ggc.h" /* Section names. These must correspond to the values of enum lto_section_type. */ diff --git a/gcc/lto-section-out.c b/gcc/lto-section-out.c index 4a2867376d5..2cc705c3a2a 100644 --- a/gcc/lto-section-out.c +++ b/gcc/lto-section-out.c @@ -24,17 +24,18 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tm.h" #include "tree.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "expr.h" #include "params.h" #include "input.h" #include "hashtab.h" -#include "basic-block.h" #include "function.h" -#include "ggc.h" #include "except.h" -#include "vec.h" -#include "pointer-set.h" #include "langhooks.h" #include "data-streamer.h" #include "lto-streamer.h" diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c index f2a3c0fd869..3fbe820d23e 100644 --- a/gcc/lto-streamer-in.c +++ b/gcc/lto-streamer-in.c @@ -33,6 +33,10 @@ along with GCC; see the file COPYING3. If not see #include "input.h" #include "hashtab.h" #include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimple-ssa.h" @@ -43,11 +47,9 @@ along with GCC; see the file COPYING3. If not see #include "tree-ssa.h" #include "tree-pass.h" #include "function.h" -#include "ggc.h" #include "diagnostic.h" #include "except.h" #include "debug.h" -#include "vec.h" #include "ipa-utils.h" #include "data-streamer.h" #include "gimple-streamer.h" @@ -596,7 +598,8 @@ make_new_block (struct function *fn, unsigned int index) /* Read the CFG for function FN from input block IB. */ static void -input_cfg (struct lto_input_block *ib, struct function *fn, +input_cfg (struct lto_input_block *ib, struct data_in *data_in, + struct function *fn, int count_materialization_scale) { unsigned int bb_count; @@ -724,6 +727,11 @@ input_cfg (struct lto_input_block *ib, struct function *fn, loop->nb_iterations_estimate = widest_int::from_array (a, len); } + /* Read OMP SIMD related info. */ + loop->safelen = streamer_read_hwi (ib); + loop->force_vect = streamer_read_hwi (ib); + loop->simduid = stream_read_tree (ib, data_in); + place_new_loop (fn, loop); /* flow_loops_find doesn't like loops not in the tree, hook them @@ -887,6 +895,8 @@ input_struct_function_base (struct function *fn, struct data_in *data_in, fn->has_nonlocal_label = bp_unpack_value (&bp, 1); fn->calls_alloca = bp_unpack_value (&bp, 1); fn->calls_setjmp = bp_unpack_value (&bp, 1); + fn->has_force_vect_loops = bp_unpack_value (&bp, 1); + fn->has_simduid_loops = bp_unpack_value (&bp, 1); fn->va_list_fpr_size = bp_unpack_value (&bp, 8); fn->va_list_gpr_size = bp_unpack_value (&bp, 8); @@ -933,7 +943,7 @@ input_function (tree fn_decl, struct data_in *data_in, if (!node) node = cgraph_create_node (fn_decl); input_struct_function_base (fn, data_in, ib); - input_cfg (ib_cfg, fn, node->count_materialization_scale); + input_cfg (ib_cfg, data_in, fn, node->count_materialization_scale); /* Read all the SSA names. */ input_ssa_names (ib, data_in, fn); diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c index a06f38639eb..6b78f4b02a3 100644 --- a/gcc/lto-streamer-out.c +++ b/gcc/lto-streamer-out.c @@ -33,16 +33,18 @@ along with GCC; see the file COPYING3. If not see #include "input.h" #include "hashtab.h" #include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimple-ssa.h" #include "tree-ssanames.h" #include "tree-pass.h" #include "function.h" -#include "ggc.h" #include "diagnostic-core.h" #include "except.h" -#include "vec.h" #include "lto-symtab.h" #include "lto-streamer.h" #include "data-streamer.h" @@ -133,8 +135,10 @@ tree_is_indexable (tree t) definition. */ if (TREE_CODE (t) == PARM_DECL || TREE_CODE (t) == RESULT_DECL) return variably_modified_type_p (TREE_TYPE (DECL_CONTEXT (t)), NULL_TREE); - else if (TREE_CODE (t) == VAR_DECL && decl_function_context (t) - && !TREE_STATIC (t)) + else if (((TREE_CODE (t) == VAR_DECL && !TREE_STATIC (t)) + || TREE_CODE (t) == TYPE_DECL + || TREE_CODE (t) == CONST_DECL) + && decl_function_context (t)) return false; else if (TREE_CODE (t) == DEBUG_EXPR_DECL) return false; @@ -295,7 +299,6 @@ lto_is_streamable (tree expr) && code != BIND_EXPR && code != WITH_CLEANUP_EXPR && code != STATEMENT_LIST - && code != OMP_CLAUSE && (code == CASE_LABEL_EXPR || code == DECL_EXPR || TREE_CODE_CLASS (code) != tcc_statement); @@ -665,6 +668,14 @@ DFS_write_tree_body (struct output_block *ob, } } + if (code == OMP_CLAUSE) + { + int i; + for (i = 0; i < omp_clause_num_ops[OMP_CLAUSE_CODE (expr)]; i++) + DFS_follow_tree_edge (OMP_CLAUSE_OPERAND (expr, i)); + DFS_follow_tree_edge (OMP_CLAUSE_CHAIN (expr)); + } + #undef DFS_follow_tree_edge } @@ -1052,6 +1063,39 @@ hash_tree (struct streamer_tree_cache_d *cache, tree t) } } + if (code == OMP_CLAUSE) + { + int i; + + v = iterative_hash_host_wide_int (OMP_CLAUSE_CODE (t), v); + switch (OMP_CLAUSE_CODE (t)) + { + case OMP_CLAUSE_DEFAULT: + v = iterative_hash_host_wide_int (OMP_CLAUSE_DEFAULT_KIND (t), v); + break; + case OMP_CLAUSE_SCHEDULE: + v = iterative_hash_host_wide_int (OMP_CLAUSE_SCHEDULE_KIND (t), v); + break; + case OMP_CLAUSE_DEPEND: + v = iterative_hash_host_wide_int (OMP_CLAUSE_DEPEND_KIND (t), v); + break; + case OMP_CLAUSE_MAP: + v = iterative_hash_host_wide_int (OMP_CLAUSE_MAP_KIND (t), v); + break; + case OMP_CLAUSE_PROC_BIND: + v = iterative_hash_host_wide_int (OMP_CLAUSE_PROC_BIND_KIND (t), v); + break; + case OMP_CLAUSE_REDUCTION: + v = iterative_hash_host_wide_int (OMP_CLAUSE_REDUCTION_CODE (t), v); + break; + default: + break; + } + for (i = 0; i < omp_clause_num_ops[OMP_CLAUSE_CODE (t)]; i++) + visit (OMP_CLAUSE_OPERAND (t, i)); + visit (OMP_CLAUSE_CHAIN (t)); + } + return v; #undef visit @@ -1653,6 +1697,11 @@ output_cfg (struct output_block *ob, struct function *fn) for (i = 0; i < len; i++) streamer_write_hwi (ob, loop->nb_iterations_estimate.elt (i)); } + + /* Write OMP SIMD related info. */ + streamer_write_hwi (ob, loop->safelen); + streamer_write_hwi (ob, loop->force_vect); + stream_write_tree (ob, loop->simduid, true); } ob->main_stream = tmp_stream; @@ -1746,6 +1795,8 @@ output_struct_function_base (struct output_block *ob, struct function *fn) bp_pack_value (&bp, fn->has_nonlocal_label, 1); bp_pack_value (&bp, fn->calls_alloca, 1); bp_pack_value (&bp, fn->calls_setjmp, 1); + bp_pack_value (&bp, fn->has_force_vect_loops, 1); + bp_pack_value (&bp, fn->has_simduid_loops, 1); bp_pack_value (&bp, fn->va_list_fpr_size, 8); bp_pack_value (&bp, fn->va_list_gpr_size, 8); diff --git a/gcc/lto-streamer.c b/gcc/lto-streamer.c index 1540e4c4be8..20192b73497 100644 --- a/gcc/lto-streamer.c +++ b/gcc/lto-streamer.c @@ -27,10 +27,14 @@ along with GCC; see the file COPYING3. If not see #include "toplev.h" #include "flags.h" #include "tree.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "bitmap.h" #include "diagnostic-core.h" -#include "vec.h" #include "tree-streamer.h" #include "lto-streamer.h" #include "streamer-hooks.h" diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog index 1b83f22046a..6d6ebf6717d 100644 --- a/gcc/lto/ChangeLog +++ b/gcc/lto/ChangeLog @@ -1,3 +1,24 @@ +2013-11-29 Jakub Jelinek <jakub@redhat.com> + Richard Biener <rguenther@suse.de> + + PR lto/59326 + * lto.c (compare_tree_sccs_1): Handle OMP_CLAUSE. + +2013-11-29 Jakub Jelinek <jakub@redhat.com> + + PR lto/59326 + * lto.c (mentions_vars_p_omp_clause): New function. + (mentions_vars_p): Call it for OMP_CLAUSE. Remove break; + after return stmts. + +2013-11-22 Andrew MacLeod <amacleod@redhat.com> + + * lto.c: Add required include files from gimple.h. + * lto-lang.c: Likewise + * lto-object.c: Likewise + * lto-partition.c: Likewise + * lto-symtab.c: Likewise + 2013-11-18 Trevor Saunders <tsaunders@mozilla.com> * lto-partition.c lto-symtab.c lto.c Adjust. diff --git a/gcc/lto/lto-lang.c b/gcc/lto/lto-lang.c index a5f5d44bd58..3e843ec8166 100644 --- a/gcc/lto/lto-lang.c +++ b/gcc/lto/lto-lang.c @@ -33,6 +33,11 @@ along with GCC; see the file COPYING3. If not see #include "lto-tree.h" #include "lto.h" #include "tree-inline.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "diagnostic-core.h" #include "toplev.h" @@ -1302,6 +1307,5 @@ lto_tree_node_structure (union lang_tree_node *t ATTRIBUTE_UNUSED) return TS_LTO_GENERIC; } -#include "ggc.h" #include "gtype-lto.h" #include "gt-lto-lto-lang.h" diff --git a/gcc/lto/lto-object.c b/gcc/lto/lto-object.c index 19f10ccb978..b4518bb55b9 100644 --- a/gcc/lto/lto-object.c +++ b/gcc/lto/lto-object.c @@ -22,6 +22,11 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "tree.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "diagnostic-core.h" #include "lto.h" diff --git a/gcc/lto/lto-partition.c b/gcc/lto/lto-partition.c index 42d78307ded..95ec7fabf86 100644 --- a/gcc/lto/lto-partition.c +++ b/gcc/lto/lto-partition.c @@ -23,6 +23,11 @@ along with GCC; see the file COPYING3. If not see #include "toplev.h" #include "tree.h" #include "gcc-symtab.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "tm.h" #include "cgraph.h" diff --git a/gcc/lto/lto-symtab.c b/gcc/lto/lto-symtab.c index 7c7075e50fc..87d6332ab2b 100644 --- a/gcc/lto/lto-symtab.c +++ b/gcc/lto/lto-symtab.c @@ -23,8 +23,12 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "diagnostic-core.h" #include "tree.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" -#include "ggc.h" #include "hashtab.h" #include "plugin-api.h" #include "lto-streamer.h" diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c index c43fe8476ec..e529fdbe2bf 100644 --- a/gcc/lto/lto.c +++ b/gcc/lto/lto.c @@ -28,16 +28,17 @@ along with GCC; see the file COPYING3. If not see #include "diagnostic-core.h" #include "tm.h" #include "cgraph.h" -#include "ggc.h" #include "tree-ssa-operands.h" #include "tree-pass.h" #include "langhooks.h" -#include "vec.h" #include "bitmap.h" -#include "pointer-set.h" #include "ipa-prop.h" #include "common.h" #include "debug.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "lto.h" #include "lto-tree.h" @@ -903,6 +904,19 @@ mentions_vars_p_expr (tree t) return false; } +/* Check presence of pointers to decls in fields of an OMP_CLAUSE T. */ + +static bool +mentions_vars_p_omp_clause (tree t) +{ + int i; + if (mentions_vars_p_common (t)) + return true; + for (i = omp_clause_num_ops[OMP_CLAUSE_CODE (t)] - 1; i >= 0; --i) + CHECK_VAR (OMP_CLAUSE_OPERAND (t, i)); + return false; +} + /* Check presence of pointers to decls that needs later fixup in T. */ static bool @@ -921,7 +935,6 @@ mentions_vars_p (tree t) case FIELD_DECL: return mentions_vars_p_field_decl (t); - break; case LABEL_DECL: case CONST_DECL: @@ -930,27 +943,21 @@ mentions_vars_p (tree t) case IMPORTED_DECL: case NAMESPACE_DECL: return mentions_vars_p_decl_common (t); - break; case VAR_DECL: return mentions_vars_p_decl_with_vis (t); - break; case TYPE_DECL: return mentions_vars_p_decl_non_common (t); - break; case FUNCTION_DECL: return mentions_vars_p_function (t); - break; case TREE_BINFO: return mentions_vars_p_binfo (t); - break; case PLACEHOLDER_EXPR: return mentions_vars_p_common (t); - break; case BLOCK: case TRANSLATION_UNIT_DECL: @@ -960,7 +967,9 @@ mentions_vars_p (tree t) case CONSTRUCTOR: return mentions_vars_p_constructor (t); - break; + + case OMP_CLAUSE: + return mentions_vars_p_omp_clause (t); default: if (TYPE_P (t)) @@ -1401,6 +1410,36 @@ compare_tree_sccs_1 (tree t1, tree t2, tree **map) TREE_STRING_LENGTH (t1)) != 0) return false; + if (code == OMP_CLAUSE) + { + compare_values (OMP_CLAUSE_CODE); + switch (OMP_CLAUSE_CODE (t1)) + { + case OMP_CLAUSE_DEFAULT: + compare_values (OMP_CLAUSE_DEFAULT_KIND); + break; + case OMP_CLAUSE_SCHEDULE: + compare_values (OMP_CLAUSE_SCHEDULE_KIND); + break; + case OMP_CLAUSE_DEPEND: + compare_values (OMP_CLAUSE_DEPEND_KIND); + break; + case OMP_CLAUSE_MAP: + compare_values (OMP_CLAUSE_MAP_KIND); + break; + case OMP_CLAUSE_PROC_BIND: + compare_values (OMP_CLAUSE_PROC_BIND_KIND); + break; + case OMP_CLAUSE_REDUCTION: + compare_values (OMP_CLAUSE_REDUCTION_CODE); + compare_values (OMP_CLAUSE_REDUCTION_GIMPLE_INIT); + compare_values (OMP_CLAUSE_REDUCTION_GIMPLE_MERGE); + break; + default: + break; + } + } + #undef compare_values @@ -1624,6 +1663,16 @@ compare_tree_sccs_1 (tree t1, tree t2, tree **map) } } + if (code == OMP_CLAUSE) + { + int i; + + for (i = 0; i < omp_clause_num_ops[OMP_CLAUSE_CODE (t1)]; i++) + compare_tree_edges (OMP_CLAUSE_OPERAND (t1, i), + OMP_CLAUSE_OPERAND (t2, i)); + compare_tree_edges (OMP_CLAUSE_CHAIN (t1), OMP_CLAUSE_CHAIN (t2)); + } + #undef compare_tree_edges return true; diff --git a/gcc/machmode.h b/gcc/machmode.h index 71c72525b4a..da0923a81a2 100644 --- a/gcc/machmode.h +++ b/gcc/machmode.h @@ -174,9 +174,6 @@ extern const unsigned char mode_class[NUM_MACHINE_MODES]; || CLASS == MODE_ACCUM \ || CLASS == MODE_UACCUM) -#define POINTER_BOUNDS_MODE_P(MODE) \ - (GET_MODE_CLASS (MODE) == MODE_POINTER_BOUNDS) - /* Get the size in bytes and bits of an object of mode MODE. */ extern CONST_MODE_SIZE unsigned char mode_size[NUM_MACHINE_MODES]; diff --git a/gcc/mode-classes.def b/gcc/mode-classes.def index a94fd614603..7207ef7712b 100644 --- a/gcc/mode-classes.def +++ b/gcc/mode-classes.def @@ -22,7 +22,6 @@ along with GCC; see the file COPYING3. If not see DEF_MODE_CLASS (MODE_CC), /* condition code in a register */ \ DEF_MODE_CLASS (MODE_INT), /* integer */ \ DEF_MODE_CLASS (MODE_PARTIAL_INT), /* integer with padding bits */ \ - DEF_MODE_CLASS (MODE_POINTER_BOUNDS), /* bounds */ \ DEF_MODE_CLASS (MODE_FRACT), /* signed fractional number */ \ DEF_MODE_CLASS (MODE_UFRACT), /* unsigned fractional number */ \ DEF_MODE_CLASS (MODE_ACCUM), /* signed accumulator */ \ diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog index 000ba9e71b1..6ec2ef5fa70 100644 --- a/gcc/objc/ChangeLog +++ b/gcc/objc/ChangeLog @@ -1,3 +1,7 @@ +2013-11-22 Andrew MacLeod <amacleod@redhat.com> + + * objc/objc-act.c: Add required include files from gimple.h. + 2013-11-18 Richard Sandiford <rdsandiford@googlemail.com> * objc-encoding.c: Replace tree_low_cst (..., 1) with tree_to_uhwi diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c index 2c152c7e312..0cf93d4002c 100644 --- a/gcc/objc/objc-act.c +++ b/gcc/objc/objc-act.c @@ -45,7 +45,6 @@ along with GCC; see the file COPYING3. If not see #include "input.h" #include "function.h" #include "toplev.h" -#include "ggc.h" #include "debug.h" #include "c-family/c-target.h" #include "diagnostic-core.h" @@ -64,7 +63,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-pretty-print.h" /* For enum gimplify_status */ -#include "gimple.h" +#include "gimple-expr.h" #include "gimplify.h" /* For encode_method_prototype(). */ diff --git a/gcc/omp-low.c b/gcc/omp-low.c index d26139cdd1f..ad13532f932 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -29,6 +29,13 @@ along with GCC; see the file COPYING3. If not see #include "stringpool.h" #include "stor-layout.h" #include "rtl.h" +#include "pointer-set.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "gimple-iterator.h" @@ -52,7 +59,6 @@ along with GCC; see the file COPYING3. If not see #include "function.h" #include "expr.h" #include "tree-pass.h" -#include "ggc.h" #include "except.h" #include "splay-tree.h" #include "optabs.h" @@ -61,7 +67,10 @@ along with GCC; see the file COPYING3. If not see #include "omp-low.h" #include "gimple-low.h" #include "tree-cfgcleanup.h" +#include "pretty-print.h" +#include "ipa-prop.h" #include "tree-nested.h" +#include "tree-eh.h" /* Lowering of OpenMP parallel and workshare constructs proceeds in two @@ -3177,15 +3186,26 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist, } else if (TREE_CONSTANT (x)) { - const char *name = NULL; - if (DECL_NAME (var)) - name = IDENTIFIER_POINTER (DECL_NAME (new_var)); - - x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)), - name); - gimple_add_tmp_var (x); - TREE_ADDRESSABLE (x) = 1; - x = build_fold_addr_expr_loc (clause_loc, x); + /* For reduction with placeholder in SIMD loop, + defer adding the initialization of the reference, + because if we decide to use SIMD array for it, + the initilization could cause expansion ICE. */ + if (c_kind == OMP_CLAUSE_REDUCTION + && OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) + && is_simd) + x = NULL_TREE; + else + { + const char *name = NULL; + if (DECL_NAME (var)) + name = IDENTIFIER_POINTER (DECL_NAME (new_var)); + + x = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (new_var)), + name); + gimple_add_tmp_var (x); + TREE_ADDRESSABLE (x) = 1; + x = build_fold_addr_expr_loc (clause_loc, x); + } } else { @@ -3193,8 +3213,11 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist, x = build_call_expr_loc (clause_loc, atmp, 1, x); } - x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x); - gimplify_assign (new_var, x, ilist); + if (x) + { + x = fold_convert_loc (clause_loc, TREE_TYPE (new_var), x); + gimplify_assign (new_var, x, ilist); + } new_var = build_simple_mem_ref_loc (clause_loc, new_var); } @@ -3492,6 +3515,29 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist, } break; } + /* If this is a reference to constant size reduction var + with placeholder, we haven't emitted the initializer + for it because it is undesirable if SIMD arrays are used. + But if they aren't used, we need to emit the deferred + initialization now. */ + else if (is_reference (var) && is_simd) + { + tree z + = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (new_vard))); + if (TREE_CONSTANT (z)) + { + const char *name = NULL; + if (DECL_NAME (var)) + name = IDENTIFIER_POINTER (DECL_NAME (new_vard)); + + z = create_tmp_var_raw + (TREE_TYPE (TREE_TYPE (new_vard)), name); + gimple_add_tmp_var (z); + TREE_ADDRESSABLE (z) = 1; + z = build_fold_addr_expr_loc (clause_loc, z); + gimplify_assign (new_vard, z, ilist); + } + } x = lang_hooks.decls.omp_clause_default_ctor (c, new_var, unshare_expr (x)); if (x) @@ -6483,7 +6529,8 @@ expand_omp_for_static_chunk (struct omp_region *region, { struct loop *loop = alloc_loop (); loop->header = body_bb; - loop->latch = cont_bb; + if (collapse_bb == NULL) + loop->latch = cont_bb; add_loop (loop, trip_loop); } } @@ -6763,7 +6810,7 @@ expand_omp_simd (struct omp_region *region, struct omp_for_data *fd) { struct loop *loop = alloc_loop (); loop->header = l1_bb; - loop->latch = e->dest; + loop->latch = cont_bb; add_loop (loop, l1_bb->loop_father); if (safelen == NULL_TREE) loop->safelen = INT_MAX; @@ -10569,5 +10616,1170 @@ make_pass_diagnose_omp_blocks (gcc::context *ctxt) { return new pass_diagnose_omp_blocks (ctxt); } + +/* SIMD clone supporting code. */ + +/* Allocate a fresh `simd_clone' and return it. NARGS is the number + of arguments to reserve space for. */ + +static struct cgraph_simd_clone * +simd_clone_struct_alloc (int nargs) +{ + struct cgraph_simd_clone *clone_info; + size_t len = (sizeof (struct cgraph_simd_clone) + + nargs * sizeof (struct cgraph_simd_clone_arg)); + clone_info = (struct cgraph_simd_clone *) + ggc_internal_cleared_alloc_stat (len PASS_MEM_STAT); + return clone_info; +} + +/* Make a copy of the `struct cgraph_simd_clone' in FROM to TO. */ + +static inline void +simd_clone_struct_copy (struct cgraph_simd_clone *to, + struct cgraph_simd_clone *from) +{ + memcpy (to, from, (sizeof (struct cgraph_simd_clone) + + from->nargs * sizeof (struct cgraph_simd_clone_arg))); +} + +/* Return vector of parameter types of function FNDECL. This uses + TYPE_ARG_TYPES if available, otherwise falls back to types of + DECL_ARGUMENTS types. */ + +vec<tree> +simd_clone_vector_of_formal_parm_types (tree fndecl) +{ + if (TYPE_ARG_TYPES (TREE_TYPE (fndecl))) + return ipa_get_vector_of_formal_parm_types (TREE_TYPE (fndecl)); + vec<tree> args = ipa_get_vector_of_formal_parms (fndecl); + unsigned int i; + tree arg; + FOR_EACH_VEC_ELT (args, i, arg) + args[i] = TREE_TYPE (args[i]); + return args; +} + +/* Given a simd function in NODE, extract the simd specific + information from the OMP clauses passed in CLAUSES, and return + the struct cgraph_simd_clone * if it should be cloned. *INBRANCH_SPECIFIED + is set to TRUE if the `inbranch' or `notinbranch' clause specified, + otherwise set to FALSE. */ + +static struct cgraph_simd_clone * +simd_clone_clauses_extract (struct cgraph_node *node, tree clauses, + bool *inbranch_specified) +{ + vec<tree> args = simd_clone_vector_of_formal_parm_types (node->decl); + tree t; + int n; + *inbranch_specified = false; + + n = args.length (); + if (n > 0 && args.last () == void_type_node) + n--; + + /* To distinguish from an OpenMP simd clone, Cilk Plus functions to + be cloned have a distinctive artificial label in addition to "omp + declare simd". */ + bool cilk_clone + = (flag_enable_cilkplus + && lookup_attribute ("cilk plus elemental", + DECL_ATTRIBUTES (node->decl))); + + /* Allocate one more than needed just in case this is an in-branch + clone which will require a mask argument. */ + struct cgraph_simd_clone *clone_info = simd_clone_struct_alloc (n + 1); + clone_info->nargs = n; + clone_info->cilk_elemental = cilk_clone; + + if (!clauses) + { + args.release (); + return clone_info; + } + clauses = TREE_VALUE (clauses); + if (!clauses || TREE_CODE (clauses) != OMP_CLAUSE) + return clone_info; + + for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t)) + { + switch (OMP_CLAUSE_CODE (t)) + { + case OMP_CLAUSE_INBRANCH: + clone_info->inbranch = 1; + *inbranch_specified = true; + break; + case OMP_CLAUSE_NOTINBRANCH: + clone_info->inbranch = 0; + *inbranch_specified = true; + break; + case OMP_CLAUSE_SIMDLEN: + clone_info->simdlen + = TREE_INT_CST_LOW (OMP_CLAUSE_SIMDLEN_EXPR (t)); + break; + case OMP_CLAUSE_LINEAR: + { + tree decl = OMP_CLAUSE_DECL (t); + tree step = OMP_CLAUSE_LINEAR_STEP (t); + int argno = TREE_INT_CST_LOW (decl); + if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (t)) + { + clone_info->args[argno].arg_type + = SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP; + clone_info->args[argno].linear_step = tree_to_shwi (step); + gcc_assert (clone_info->args[argno].linear_step >= 0 + && clone_info->args[argno].linear_step < n); + } + else + { + if (POINTER_TYPE_P (args[argno])) + step = fold_convert (ssizetype, step); + if (!tree_fits_shwi_p (step)) + { + warning_at (OMP_CLAUSE_LOCATION (t), 0, + "ignoring large linear step"); + args.release (); + return NULL; + } + else if (integer_zerop (step)) + { + warning_at (OMP_CLAUSE_LOCATION (t), 0, + "ignoring zero linear step"); + args.release (); + return NULL; + } + else + { + clone_info->args[argno].arg_type + = SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP; + clone_info->args[argno].linear_step = tree_to_shwi (step); + } + } + break; + } + case OMP_CLAUSE_UNIFORM: + { + tree decl = OMP_CLAUSE_DECL (t); + int argno = tree_to_uhwi (decl); + clone_info->args[argno].arg_type + = SIMD_CLONE_ARG_TYPE_UNIFORM; + break; + } + case OMP_CLAUSE_ALIGNED: + { + tree decl = OMP_CLAUSE_DECL (t); + int argno = tree_to_uhwi (decl); + clone_info->args[argno].alignment + = TREE_INT_CST_LOW (OMP_CLAUSE_ALIGNED_ALIGNMENT (t)); + break; + } + default: + break; + } + } + args.release (); + return clone_info; +} + +/* Given a SIMD clone in NODE, calculate the characteristic data + type and return the coresponding type. The characteristic data + type is computed as described in the Intel Vector ABI. */ + +static tree +simd_clone_compute_base_data_type (struct cgraph_node *node, + struct cgraph_simd_clone *clone_info) +{ + tree type = integer_type_node; + tree fndecl = node->decl; + + /* a) For non-void function, the characteristic data type is the + return type. */ + if (TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE) + type = TREE_TYPE (TREE_TYPE (fndecl)); + + /* b) If the function has any non-uniform, non-linear parameters, + then the characteristic data type is the type of the first + such parameter. */ + else + { + vec<tree> map = simd_clone_vector_of_formal_parm_types (fndecl); + for (unsigned int i = 0; i < clone_info->nargs; ++i) + if (clone_info->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR) + { + type = map[i]; + break; + } + map.release (); + } + + /* c) If the characteristic data type determined by a) or b) above + is struct, union, or class type which is pass-by-value (except + for the type that maps to the built-in complex data type), the + characteristic data type is int. */ + if (RECORD_OR_UNION_TYPE_P (type) + && !aggregate_value_p (type, NULL) + && TREE_CODE (type) != COMPLEX_TYPE) + return integer_type_node; + + /* d) If none of the above three classes is applicable, the + characteristic data type is int. */ + + return type; + + /* e) For Intel Xeon Phi native and offload compilation, if the + resulting characteristic data type is 8-bit or 16-bit integer + data type, the characteristic data type is int. */ + /* Well, we don't handle Xeon Phi yet. */ +} + +static tree +simd_clone_mangle (struct cgraph_node *node, + struct cgraph_simd_clone *clone_info) +{ + char vecsize_mangle = clone_info->vecsize_mangle; + char mask = clone_info->inbranch ? 'M' : 'N'; + unsigned int simdlen = clone_info->simdlen; + unsigned int n; + pretty_printer pp; + + gcc_assert (vecsize_mangle && simdlen); + + pp_string (&pp, "_ZGV"); + pp_character (&pp, vecsize_mangle); + pp_character (&pp, mask); + pp_decimal_int (&pp, simdlen); + + for (n = 0; n < clone_info->nargs; ++n) + { + struct cgraph_simd_clone_arg arg = clone_info->args[n]; + + if (arg.arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM) + pp_character (&pp, 'u'); + else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP) + { + gcc_assert (arg.linear_step != 0); + pp_character (&pp, 'l'); + if (arg.linear_step > 1) + pp_unsigned_wide_integer (&pp, arg.linear_step); + else if (arg.linear_step < 0) + { + pp_character (&pp, 'n'); + pp_unsigned_wide_integer (&pp, (-(unsigned HOST_WIDE_INT) + arg.linear_step)); + } + } + else if (arg.arg_type == SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP) + { + pp_character (&pp, 's'); + pp_unsigned_wide_integer (&pp, arg.linear_step); + } + else + pp_character (&pp, 'v'); + if (arg.alignment) + { + pp_character (&pp, 'a'); + pp_decimal_int (&pp, arg.alignment); + } + } + + pp_underscore (&pp); + pp_string (&pp, + IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (node->decl))); + const char *str = pp_formatted_text (&pp); + + /* If there already is a SIMD clone with the same mangled name, don't + add another one. This can happen e.g. for + #pragma omp declare simd + #pragma omp declare simd simdlen(8) + int foo (int, int); + if the simdlen is assumed to be 8 for the first one, etc. */ + for (struct cgraph_node *clone = node->simd_clones; clone; + clone = clone->simdclone->next_clone) + if (strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (clone->decl)), + str) == 0) + return NULL_TREE; + + return get_identifier (str); +} + +/* Create a simd clone of OLD_NODE and return it. */ + +static struct cgraph_node * +simd_clone_create (struct cgraph_node *old_node) +{ + struct cgraph_node *new_node; + if (old_node->definition) + { + if (!cgraph_function_with_gimple_body_p (old_node)) + return NULL; + cgraph_get_body (old_node); + new_node = cgraph_function_versioning (old_node, vNULL, NULL, NULL, + false, NULL, NULL, "simdclone"); + } + else + { + tree old_decl = old_node->decl; + tree new_decl = copy_node (old_node->decl); + DECL_NAME (new_decl) = clone_function_name (old_decl, "simdclone"); + SET_DECL_ASSEMBLER_NAME (new_decl, DECL_NAME (new_decl)); + SET_DECL_RTL (new_decl, NULL); + DECL_STATIC_CONSTRUCTOR (new_decl) = 0; + DECL_STATIC_DESTRUCTOR (new_decl) = 0; + new_node + = cgraph_copy_node_for_versioning (old_node, new_decl, vNULL, NULL); + cgraph_call_function_insertion_hooks (new_node); + } + if (new_node == NULL) + return new_node; + + TREE_PUBLIC (new_node->decl) = TREE_PUBLIC (old_node->decl); + + /* The function cgraph_function_versioning () will force the new + symbol local. Undo this, and inherit external visability from + the old node. */ + new_node->local.local = old_node->local.local; + new_node->externally_visible = old_node->externally_visible; + + return new_node; +} + +/* Adjust the return type of the given function to its appropriate + vector counterpart. Returns a simd array to be used throughout the + function as a return value. */ + +static tree +simd_clone_adjust_return_type (struct cgraph_node *node) +{ + tree fndecl = node->decl; + tree orig_rettype = TREE_TYPE (TREE_TYPE (fndecl)); + unsigned int veclen; + tree t; + + /* Adjust the function return type. */ + if (orig_rettype == void_type_node) + return NULL_TREE; + TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl)); + if (INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl))) + || POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl)))) + veclen = node->simdclone->vecsize_int; + else + veclen = node->simdclone->vecsize_float; + veclen /= GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl)))); + if (veclen > node->simdclone->simdlen) + veclen = node->simdclone->simdlen; + if (veclen == node->simdclone->simdlen) + TREE_TYPE (TREE_TYPE (fndecl)) + = build_vector_type (TREE_TYPE (TREE_TYPE (fndecl)), + node->simdclone->simdlen); + else + { + t = build_vector_type (TREE_TYPE (TREE_TYPE (fndecl)), veclen); + t = build_array_type_nelts (t, node->simdclone->simdlen / veclen); + TREE_TYPE (TREE_TYPE (fndecl)) = t; + } + if (!node->definition) + return NULL_TREE; + + t = DECL_RESULT (fndecl); + /* Adjust the DECL_RESULT. */ + gcc_assert (TREE_TYPE (t) != void_type_node); + TREE_TYPE (t) = TREE_TYPE (TREE_TYPE (fndecl)); + relayout_decl (t); + + tree atype = build_array_type_nelts (orig_rettype, + node->simdclone->simdlen); + if (veclen != node->simdclone->simdlen) + return build1 (VIEW_CONVERT_EXPR, atype, t); + + /* Set up a SIMD array to use as the return value. */ + tree retval = create_tmp_var_raw (atype, "retval"); + gimple_add_tmp_var (retval); + return retval; +} + +/* Each vector argument has a corresponding array to be used locally + as part of the eventual loop. Create such temporary array and + return it. + + PREFIX is the prefix to be used for the temporary. + + TYPE is the inner element type. + + SIMDLEN is the number of elements. */ + +static tree +create_tmp_simd_array (const char *prefix, tree type, int simdlen) +{ + tree atype = build_array_type_nelts (type, simdlen); + tree avar = create_tmp_var_raw (atype, prefix); + gimple_add_tmp_var (avar); + return avar; +} + +/* Modify the function argument types to their corresponding vector + counterparts if appropriate. Also, create one array for each simd + argument to be used locally when using the function arguments as + part of the loop. + + NODE is the function whose arguments are to be adjusted. + + Returns an adjustment vector that will be filled describing how the + argument types will be adjusted. */ + +static ipa_parm_adjustment_vec +simd_clone_adjust_argument_types (struct cgraph_node *node) +{ + vec<tree> args; + ipa_parm_adjustment_vec adjustments; + + if (node->definition) + args = ipa_get_vector_of_formal_parms (node->decl); + else + args = simd_clone_vector_of_formal_parm_types (node->decl); + adjustments.create (args.length ()); + unsigned i, j, veclen; + struct ipa_parm_adjustment adj; + for (i = 0; i < node->simdclone->nargs; ++i) + { + memset (&adj, 0, sizeof (adj)); + tree parm = args[i]; + tree parm_type = node->definition ? TREE_TYPE (parm) : parm; + adj.base_index = i; + adj.base = parm; + + node->simdclone->args[i].orig_arg = node->definition ? parm : NULL_TREE; + node->simdclone->args[i].orig_type = parm_type; + + if (node->simdclone->args[i].arg_type != SIMD_CLONE_ARG_TYPE_VECTOR) + { + /* No adjustment necessary for scalar arguments. */ + adj.op = IPA_PARM_OP_COPY; + } + else + { + if (INTEGRAL_TYPE_P (parm_type) || POINTER_TYPE_P (parm_type)) + veclen = node->simdclone->vecsize_int; + else + veclen = node->simdclone->vecsize_float; + veclen /= GET_MODE_BITSIZE (TYPE_MODE (parm_type)); + if (veclen > node->simdclone->simdlen) + veclen = node->simdclone->simdlen; + adj.arg_prefix = "simd"; + adj.type = build_vector_type (parm_type, veclen); + node->simdclone->args[i].vector_type = adj.type; + for (j = veclen; j < node->simdclone->simdlen; j += veclen) + { + adjustments.safe_push (adj); + if (j == veclen) + { + memset (&adj, 0, sizeof (adj)); + adj.op = IPA_PARM_OP_NEW; + adj.arg_prefix = "simd"; + adj.base_index = i; + adj.type = node->simdclone->args[i].vector_type; + } + } + + if (node->definition) + node->simdclone->args[i].simd_array + = create_tmp_simd_array (IDENTIFIER_POINTER (DECL_NAME (parm)), + parm_type, node->simdclone->simdlen); + } + adjustments.safe_push (adj); + } + + if (node->simdclone->inbranch) + { + tree base_type + = simd_clone_compute_base_data_type (node->simdclone->origin, + node->simdclone); + + memset (&adj, 0, sizeof (adj)); + adj.op = IPA_PARM_OP_NEW; + adj.arg_prefix = "mask"; + + adj.base_index = i; + if (INTEGRAL_TYPE_P (base_type) || POINTER_TYPE_P (base_type)) + veclen = node->simdclone->vecsize_int; + else + veclen = node->simdclone->vecsize_float; + veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type)); + if (veclen > node->simdclone->simdlen) + veclen = node->simdclone->simdlen; + adj.type = build_vector_type (base_type, veclen); + adjustments.safe_push (adj); + + for (j = veclen; j < node->simdclone->simdlen; j += veclen) + adjustments.safe_push (adj); + + /* We have previously allocated one extra entry for the mask. Use + it and fill it. */ + struct cgraph_simd_clone *sc = node->simdclone; + sc->nargs++; + if (node->definition) + { + sc->args[i].orig_arg + = build_decl (UNKNOWN_LOCATION, PARM_DECL, NULL, base_type); + sc->args[i].simd_array + = create_tmp_simd_array ("mask", base_type, sc->simdlen); + } + sc->args[i].orig_type = base_type; + sc->args[i].arg_type = SIMD_CLONE_ARG_TYPE_MASK; + } + + if (node->definition) + ipa_modify_formal_parameters (node->decl, adjustments); + else + { + tree new_arg_types = NULL_TREE, new_reversed; + bool last_parm_void = false; + if (args.length () > 0 && args.last () == void_type_node) + last_parm_void = true; + + gcc_assert (TYPE_ARG_TYPES (TREE_TYPE (node->decl))); + j = adjustments.length (); + for (i = 0; i < j; i++) + { + struct ipa_parm_adjustment *adj = &adjustments[i]; + tree ptype; + if (adj->op == IPA_PARM_OP_COPY) + ptype = args[adj->base_index]; + else + ptype = adj->type; + new_arg_types = tree_cons (NULL_TREE, ptype, new_arg_types); + } + new_reversed = nreverse (new_arg_types); + if (last_parm_void) + { + if (new_reversed) + TREE_CHAIN (new_arg_types) = void_list_node; + else + new_reversed = void_list_node; + } + + tree new_type = build_distinct_type_copy (TREE_TYPE (node->decl)); + TYPE_ARG_TYPES (new_type) = new_reversed; + TREE_TYPE (node->decl) = new_type; + + adjustments.release (); + } + args.release (); + return adjustments; +} + +/* Initialize and copy the function arguments in NODE to their + corresponding local simd arrays. Returns a fresh gimple_seq with + the instruction sequence generated. */ + +static gimple_seq +simd_clone_init_simd_arrays (struct cgraph_node *node, + ipa_parm_adjustment_vec adjustments) +{ + gimple_seq seq = NULL; + unsigned i = 0, j = 0, k; + + for (tree arg = DECL_ARGUMENTS (node->decl); + arg; + arg = DECL_CHAIN (arg), i++, j++) + { + if (adjustments[j].op == IPA_PARM_OP_COPY) + continue; + + node->simdclone->args[i].vector_arg = arg; + + tree array = node->simdclone->args[i].simd_array; + if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)) == node->simdclone->simdlen) + { + tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array))); + tree ptr = build_fold_addr_expr (array); + tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr, + build_int_cst (ptype, 0)); + t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg); + gimplify_and_add (t, &seq); + } + else + { + unsigned int simdlen = TYPE_VECTOR_SUBPARTS (TREE_TYPE (arg)); + tree ptype = build_pointer_type (TREE_TYPE (TREE_TYPE (array))); + for (k = 0; k < node->simdclone->simdlen; k += simdlen) + { + tree ptr = build_fold_addr_expr (array); + int elemsize; + if (k) + { + arg = DECL_CHAIN (arg); + j++; + } + elemsize + = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (arg)))); + tree t = build2 (MEM_REF, TREE_TYPE (arg), ptr, + build_int_cst (ptype, k * elemsize)); + t = build2 (MODIFY_EXPR, TREE_TYPE (t), t, arg); + gimplify_and_add (t, &seq); + } + } + } + return seq; +} + +/* Callback info for ipa_simd_modify_stmt_ops below. */ + +struct modify_stmt_info { + ipa_parm_adjustment_vec adjustments; + gimple stmt; + /* True if the parent statement was modified by + ipa_simd_modify_stmt_ops. */ + bool modified; +}; + +/* Callback for walk_gimple_op. + + Adjust operands from a given statement as specified in the + adjustments vector in the callback data. */ + +static tree +ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data) +{ + struct walk_stmt_info *wi = (struct walk_stmt_info *) data; + if (!SSA_VAR_P (*tp)) + { + /* Make sure we treat subtrees as a RHS. This makes sure that + when examining the `*foo' in *foo=x, the `foo' get treated as + a use properly. */ + wi->is_lhs = false; + wi->val_only = true; + if (TYPE_P (*tp)) + *walk_subtrees = 0; + return NULL_TREE; + } + struct modify_stmt_info *info = (struct modify_stmt_info *) wi->info; + struct ipa_parm_adjustment *cand + = ipa_get_adjustment_candidate (&tp, NULL, info->adjustments, true); + if (!cand) + return NULL_TREE; + + tree t = *tp; + tree repl = make_ssa_name (TREE_TYPE (t), NULL); + + gimple stmt; + gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt); + if (wi->is_lhs) + { + stmt = gimple_build_assign (unshare_expr (cand->new_decl), repl); + gsi_insert_after (&gsi, stmt, GSI_SAME_STMT); + SSA_NAME_DEF_STMT (repl) = info->stmt; + } + else + { + /* You'd think we could skip the extra SSA variable when + wi->val_only=true, but we may have `*var' which will get + replaced into `*var_array[iter]' and will likely be something + not gimple. */ + stmt = gimple_build_assign (repl, unshare_expr (cand->new_decl)); + gsi_insert_before (&gsi, stmt, GSI_SAME_STMT); + } + + if (!useless_type_conversion_p (TREE_TYPE (*tp), TREE_TYPE (repl))) + { + tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*tp), repl); + *tp = vce; + } + else + *tp = repl; + + info->modified = true; + wi->is_lhs = false; + wi->val_only = true; + return NULL_TREE; +} + +/* Traverse the function body and perform all modifications as + described in ADJUSTMENTS. At function return, ADJUSTMENTS will be + modified such that the replacement/reduction value will now be an + offset into the corresponding simd_array. + + This function will replace all function argument uses with their + corresponding simd array elements, and ajust the return values + accordingly. */ + +static void +ipa_simd_modify_function_body (struct cgraph_node *node, + ipa_parm_adjustment_vec adjustments, + tree retval_array, tree iter) +{ + basic_block bb; + unsigned int i, j; + + /* Re-use the adjustments array, but this time use it to replace + every function argument use to an offset into the corresponding + simd_array. */ + for (i = 0, j = 0; i < node->simdclone->nargs; ++i, ++j) + { + if (!node->simdclone->args[i].vector_arg) + continue; + + tree basetype = TREE_TYPE (node->simdclone->args[i].orig_arg); + tree vectype = TREE_TYPE (node->simdclone->args[i].vector_arg); + adjustments[j].new_decl + = build4 (ARRAY_REF, + basetype, + node->simdclone->args[i].simd_array, + iter, + NULL_TREE, NULL_TREE); + if (adjustments[j].op == IPA_PARM_OP_NONE + && TYPE_VECTOR_SUBPARTS (vectype) < node->simdclone->simdlen) + j += node->simdclone->simdlen / TYPE_VECTOR_SUBPARTS (vectype) - 1; + } + + struct modify_stmt_info info; + info.adjustments = adjustments; + + FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl)) + { + gimple_stmt_iterator gsi; + + gsi = gsi_start_bb (bb); + while (!gsi_end_p (gsi)) + { + gimple stmt = gsi_stmt (gsi); + info.stmt = stmt; + struct walk_stmt_info wi; + + memset (&wi, 0, sizeof (wi)); + info.modified = false; + wi.info = &info; + walk_gimple_op (stmt, ipa_simd_modify_stmt_ops, &wi); + + if (gimple_code (stmt) == GIMPLE_RETURN) + { + tree retval = gimple_return_retval (stmt); + if (!retval) + { + gsi_remove (&gsi, true); + continue; + } + + /* Replace `return foo' with `retval_array[iter] = foo'. */ + tree ref = build4 (ARRAY_REF, TREE_TYPE (retval), + retval_array, iter, NULL, NULL); + stmt = gimple_build_assign (ref, retval); + gsi_replace (&gsi, stmt, true); + info.modified = true; + } + + if (info.modified) + { + update_stmt (stmt); + if (maybe_clean_eh_stmt (stmt)) + gimple_purge_dead_eh_edges (gimple_bb (stmt)); + } + gsi_next (&gsi); + } + } +} + +/* Adjust the argument types in NODE to their appropriate vector + counterparts. */ + +static void +simd_clone_adjust (struct cgraph_node *node) +{ + push_cfun (DECL_STRUCT_FUNCTION (node->decl)); + + targetm.simd_clone.adjust (node); + + tree retval = simd_clone_adjust_return_type (node); + ipa_parm_adjustment_vec adjustments + = simd_clone_adjust_argument_types (node); + + push_gimplify_context (); + + gimple_seq seq = simd_clone_init_simd_arrays (node, adjustments); + + /* Adjust all uses of vector arguments accordingly. Adjust all + return values accordingly. */ + tree iter = create_tmp_var (unsigned_type_node, "iter"); + tree iter1 = make_ssa_name (iter, NULL); + tree iter2 = make_ssa_name (iter, NULL); + ipa_simd_modify_function_body (node, adjustments, retval, iter1); + + /* Initialize the iteration variable. */ + basic_block entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun)); + basic_block body_bb = split_block_after_labels (entry_bb)->dest; + gimple_stmt_iterator gsi = gsi_after_labels (entry_bb); + /* Insert the SIMD array and iv initialization at function + entry. */ + gsi_insert_seq_before (&gsi, seq, GSI_NEW_STMT); + + pop_gimplify_context (NULL); + + /* Create a new BB right before the original exit BB, to hold the + iteration increment and the condition/branch. */ + basic_block orig_exit = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), 0)->src; + basic_block incr_bb = create_empty_bb (orig_exit); + /* The succ of orig_exit was EXIT_BLOCK_PTR_FOR_FN (cfun), with an empty + flag. Set it now to be a FALLTHRU_EDGE. */ + gcc_assert (EDGE_COUNT (orig_exit->succs) == 1); + EDGE_SUCC (orig_exit, 0)->flags |= EDGE_FALLTHRU; + for (unsigned i = 0; + i < EDGE_COUNT (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds); ++i) + { + edge e = EDGE_PRED (EXIT_BLOCK_PTR_FOR_FN (cfun), i); + redirect_edge_succ (e, incr_bb); + } + edge e = make_edge (incr_bb, EXIT_BLOCK_PTR_FOR_FN (cfun), 0); + e->probability = REG_BR_PROB_BASE; + gsi = gsi_last_bb (incr_bb); + gimple g = gimple_build_assign_with_ops (PLUS_EXPR, iter2, iter1, + build_int_cst (unsigned_type_node, + 1)); + gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING); + + /* Mostly annotate the loop for the vectorizer (the rest is done below). */ + struct loop *loop = alloc_loop (); + cfun->has_force_vect_loops = true; + loop->safelen = node->simdclone->simdlen; + loop->force_vect = true; + loop->header = body_bb; + add_bb_to_loop (incr_bb, loop); + + /* Branch around the body if the mask applies. */ + if (node->simdclone->inbranch) + { + gimple_stmt_iterator gsi = gsi_last_bb (loop->header); + tree mask_array + = node->simdclone->args[node->simdclone->nargs - 1].simd_array; + tree mask = make_ssa_name (TREE_TYPE (TREE_TYPE (mask_array)), NULL); + tree aref = build4 (ARRAY_REF, + TREE_TYPE (TREE_TYPE (mask_array)), + mask_array, iter1, + NULL, NULL); + g = gimple_build_assign (mask, aref); + gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING); + int bitsize = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (aref))); + if (!INTEGRAL_TYPE_P (TREE_TYPE (aref))) + { + aref = build1 (VIEW_CONVERT_EXPR, + build_nonstandard_integer_type (bitsize, 0), mask); + mask = make_ssa_name (TREE_TYPE (aref), NULL); + g = gimple_build_assign (mask, aref); + gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING); + } + + g = gimple_build_cond (EQ_EXPR, mask, build_zero_cst (TREE_TYPE (mask)), + NULL, NULL); + gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING); + make_edge (loop->header, incr_bb, EDGE_TRUE_VALUE); + FALLTHRU_EDGE (loop->header)->flags = EDGE_FALSE_VALUE; + } + + /* Generate the condition. */ + g = gimple_build_cond (LT_EXPR, + iter2, + build_int_cst (unsigned_type_node, + node->simdclone->simdlen), + NULL, NULL); + gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING); + e = split_block (incr_bb, gsi_stmt (gsi)); + basic_block latch_bb = e->dest; + basic_block new_exit_bb = e->dest; + new_exit_bb = split_block (latch_bb, NULL)->dest; + loop->latch = latch_bb; + + redirect_edge_succ (FALLTHRU_EDGE (latch_bb), body_bb); + + make_edge (incr_bb, new_exit_bb, EDGE_FALSE_VALUE); + /* The successor of incr_bb is already pointing to latch_bb; just + change the flags. + make_edge (incr_bb, latch_bb, EDGE_TRUE_VALUE); */ + FALLTHRU_EDGE (incr_bb)->flags = EDGE_TRUE_VALUE; + + gimple phi = create_phi_node (iter1, body_bb); + edge preheader_edge = find_edge (entry_bb, body_bb); + edge latch_edge = single_succ_edge (latch_bb); + add_phi_arg (phi, build_zero_cst (unsigned_type_node), preheader_edge, + UNKNOWN_LOCATION); + add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION); + + /* Generate the new return. */ + gsi = gsi_last_bb (new_exit_bb); + if (retval + && TREE_CODE (retval) == VIEW_CONVERT_EXPR + && TREE_CODE (TREE_OPERAND (retval, 0)) == RESULT_DECL) + retval = TREE_OPERAND (retval, 0); + else if (retval) + { + retval = build1 (VIEW_CONVERT_EXPR, + TREE_TYPE (TREE_TYPE (node->decl)), + retval); + retval = force_gimple_operand_gsi (&gsi, retval, true, NULL, + false, GSI_CONTINUE_LINKING); + } + g = gimple_build_return (retval); + gsi_insert_after (&gsi, g, GSI_CONTINUE_LINKING); + + /* Handle aligned clauses by replacing default defs of the aligned + uniform args with __builtin_assume_aligned (arg_N(D), alignment) + lhs. Handle linear by adding PHIs. */ + for (unsigned i = 0; i < node->simdclone->nargs; i++) + if (node->simdclone->args[i].alignment + && node->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_UNIFORM + && (node->simdclone->args[i].alignment + & (node->simdclone->args[i].alignment - 1)) == 0 + && TREE_CODE (TREE_TYPE (node->simdclone->args[i].orig_arg)) + == POINTER_TYPE) + { + unsigned int alignment = node->simdclone->args[i].alignment; + tree orig_arg = node->simdclone->args[i].orig_arg; + tree def = ssa_default_def (cfun, orig_arg); + if (!has_zero_uses (def)) + { + tree fn = builtin_decl_explicit (BUILT_IN_ASSUME_ALIGNED); + gimple_seq seq = NULL; + bool need_cvt = false; + gimple call + = gimple_build_call (fn, 2, def, size_int (alignment)); + g = call; + if (!useless_type_conversion_p (TREE_TYPE (orig_arg), + ptr_type_node)) + need_cvt = true; + tree t = make_ssa_name (need_cvt ? ptr_type_node : orig_arg, NULL); + gimple_call_set_lhs (g, t); + gimple_seq_add_stmt_without_update (&seq, g); + if (need_cvt) + { + t = make_ssa_name (orig_arg, NULL); + g = gimple_build_assign_with_ops (NOP_EXPR, t, + gimple_call_lhs (g), + NULL_TREE); + gimple_seq_add_stmt_without_update (&seq, g); + } + gsi_insert_seq_on_edge_immediate + (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)), seq); + + entry_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun)); + int freq = compute_call_stmt_bb_frequency (current_function_decl, + entry_bb); + cgraph_create_edge (node, cgraph_get_create_node (fn), + call, entry_bb->count, freq); + + imm_use_iterator iter; + use_operand_p use_p; + gimple use_stmt; + tree repl = gimple_get_lhs (g); + FOR_EACH_IMM_USE_STMT (use_stmt, iter, def) + if (is_gimple_debug (use_stmt) || use_stmt == call) + continue; + else + FOR_EACH_IMM_USE_ON_STMT (use_p, iter) + SET_USE (use_p, repl); + } + } + else if (node->simdclone->args[i].arg_type + == SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP) + { + tree orig_arg = node->simdclone->args[i].orig_arg; + 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)) + { + iter1 = make_ssa_name (orig_arg, NULL); + iter2 = make_ssa_name (orig_arg, NULL); + phi = create_phi_node (iter1, body_bb); + add_phi_arg (phi, def, preheader_edge, UNKNOWN_LOCATION); + add_phi_arg (phi, iter2, latch_edge, UNKNOWN_LOCATION); + enum tree_code code = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg)) + ? PLUS_EXPR : POINTER_PLUS_EXPR; + tree addtype = INTEGRAL_TYPE_P (TREE_TYPE (orig_arg)) + ? TREE_TYPE (orig_arg) : sizetype; + tree addcst + = build_int_cst (addtype, node->simdclone->args[i].linear_step); + g = gimple_build_assign_with_ops (code, iter2, iter1, addcst); + gsi = gsi_last_bb (incr_bb); + gsi_insert_before (&gsi, g, GSI_SAME_STMT); + + imm_use_iterator iter; + use_operand_p use_p; + gimple use_stmt; + FOR_EACH_IMM_USE_STMT (use_stmt, iter, def) + if (use_stmt == phi) + continue; + else + FOR_EACH_IMM_USE_ON_STMT (use_p, iter) + SET_USE (use_p, iter1); + } + } + + calculate_dominance_info (CDI_DOMINATORS); + add_loop (loop, loop->header->loop_father); + update_ssa (TODO_update_ssa); + + pop_cfun (); +} + +/* If the function in NODE is tagged as an elemental SIMD function, + create the appropriate SIMD clones. */ + +static void +expand_simd_clones (struct cgraph_node *node) +{ + tree attr = lookup_attribute ("omp declare simd", + DECL_ATTRIBUTES (node->decl)); + if (attr == NULL_TREE + || node->global.inlined_to + || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl))) + return; + + /* Ignore + #pragma omp declare simd + extern int foo (); + in C, there we don't know the argument types at all. */ + if (!node->definition + && TYPE_ARG_TYPES (TREE_TYPE (node->decl)) == NULL_TREE) + return; + + do + { + /* Start with parsing the "omp declare simd" attribute(s). */ + bool inbranch_clause_specified; + struct cgraph_simd_clone *clone_info + = simd_clone_clauses_extract (node, TREE_VALUE (attr), + &inbranch_clause_specified); + if (clone_info == NULL) + continue; + + int orig_simdlen = clone_info->simdlen; + tree base_type = simd_clone_compute_base_data_type (node, clone_info); + /* The target can return 0 (no simd clones should be created), + 1 (just one ISA of simd clones should be created) or higher + count of ISA variants. In that case, clone_info is initialized + for the first ISA variant. */ + int count + = targetm.simd_clone.compute_vecsize_and_simdlen (node, clone_info, + base_type, 0); + if (count == 0) + continue; + + /* Loop over all COUNT ISA variants, and if !INBRANCH_CLAUSE_SPECIFIED, + also create one inbranch and one !inbranch clone of it. */ + for (int i = 0; i < count * 2; i++) + { + struct cgraph_simd_clone *clone = clone_info; + if (inbranch_clause_specified && (i & 1) != 0) + continue; + + if (i != 0) + { + clone = simd_clone_struct_alloc (clone_info->nargs + - clone_info->inbranch + + ((i & 1) != 0)); + simd_clone_struct_copy (clone, clone_info); + /* Undo changes targetm.simd_clone.compute_vecsize_and_simdlen + and simd_clone_adjust_argument_types did to the first + clone's info. */ + clone->nargs -= clone_info->inbranch; + clone->simdlen = orig_simdlen; + /* And call the target hook again to get the right ISA. */ + targetm.simd_clone.compute_vecsize_and_simdlen (node, clone, + base_type, + i / 2); + if ((i & 1) != 0) + clone->inbranch = 1; + } + + /* simd_clone_mangle might fail if such a clone has been created + already. */ + tree id = simd_clone_mangle (node, clone); + if (id == NULL_TREE) + continue; + + /* Only when we are sure we want to create the clone actually + clone the function (or definitions) or create another + extern FUNCTION_DECL (for prototypes without definitions). */ + struct cgraph_node *n = simd_clone_create (node); + if (n == NULL) + continue; + + n->simdclone = clone; + clone->origin = node; + clone->next_clone = NULL; + if (node->simd_clones == NULL) + { + clone->prev_clone = n; + node->simd_clones = n; + } + else + { + clone->prev_clone = node->simd_clones->simdclone->prev_clone; + clone->prev_clone->simdclone->next_clone = n; + node->simd_clones->simdclone->prev_clone = n; + } + change_decl_assembler_name (n->decl, id); + /* And finally adjust the return type, parameters and for + definitions also function body. */ + if (node->definition) + simd_clone_adjust (n); + else + { + simd_clone_adjust_return_type (n); + simd_clone_adjust_argument_types (n); + } + } + } + while ((attr = lookup_attribute ("omp declare simd", TREE_CHAIN (attr)))); +} + +/* Entry point for IPA simd clone creation pass. */ + +static unsigned int +ipa_omp_simd_clone (void) +{ + struct cgraph_node *node; + FOR_EACH_FUNCTION (node) + expand_simd_clones (node); + return 0; +} + +namespace { + +const pass_data pass_data_omp_simd_clone = +{ + SIMPLE_IPA_PASS, /* type */ + "simdclone", /* name */ + OPTGROUP_NONE, /* optinfo_flags */ + true, /* has_gate */ + true, /* has_execute */ + TV_NONE, /* tv_id */ + ( PROP_ssa | PROP_cfg ), /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + 0, /* todo_flags_finish */ +}; + +class pass_omp_simd_clone : public simple_ipa_opt_pass +{ +public: + pass_omp_simd_clone(gcc::context *ctxt) + : simple_ipa_opt_pass(pass_data_omp_simd_clone, ctxt) + {} + + /* opt_pass methods: */ + bool gate () { return ((flag_openmp || flag_openmp_simd + || flag_enable_cilkplus || (in_lto_p && !flag_wpa)) + && (targetm.simd_clone.compute_vecsize_and_simdlen + != NULL)); } + unsigned int execute () { return ipa_omp_simd_clone (); } +}; + +} // anon namespace + +simple_ipa_opt_pass * +make_pass_omp_simd_clone (gcc::context *ctxt) +{ + return new pass_omp_simd_clone (ctxt); +} #include "gt-omp-low.h" diff --git a/gcc/optabs.c b/gcc/optabs.c index d81ac89e87e..074149ab61f 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -4563,8 +4563,10 @@ emit_conditional_move (rtx target, enum rtx_code code, rtx op0, rtx op1, if (!COMPARISON_P (comparison)) return NULL_RTX; - do_pending_stack_adjust (); + saved_pending_stack_adjust save; + save_pending_stack_adjust (&save); last = get_last_insn (); + do_pending_stack_adjust (); prepare_cmp_insn (XEXP (comparison, 0), XEXP (comparison, 1), GET_CODE (comparison), NULL_RTX, unsignedp, OPTAB_WIDEN, &comparison, &cmode); @@ -4584,6 +4586,7 @@ emit_conditional_move (rtx target, enum rtx_code code, rtx op0, rtx op1, } } delete_insns_since (last); + restore_pending_stack_adjust (&save); return NULL_RTX; } diff --git a/gcc/opts-global.c b/gcc/opts-global.c index af603b956e3..841a79b6122 100644 --- a/gcc/opts-global.c +++ b/gcc/opts-global.c @@ -24,8 +24,12 @@ along with GCC; see the file COPYING3. If not see #include "diagnostic.h" #include "opts.h" #include "flags.h" -#include "ggc.h" #include "tree.h" /* Required by langhooks.h. */ +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "langhooks.h" #include "tm.h" /* Required by rtl.h. */ diff --git a/gcc/opts.c b/gcc/opts.c index 5a9d7c81a72..a0a6c53128c 100644 --- a/gcc/opts.c +++ b/gcc/opts.c @@ -1450,6 +1450,7 @@ common_handle_option (struct gcc_options *opts, { { "address", SANITIZE_ADDRESS, sizeof "address" - 1 }, { "thread", SANITIZE_THREAD, sizeof "thread" - 1 }, + { "leak", SANITIZE_LEAK, sizeof "leak" - 1 }, { "shift", SANITIZE_SHIFT, sizeof "shift" - 1 }, { "integer-divide-by-zero", SANITIZE_DIVIDE, sizeof "integer-divide-by-zero" - 1 }, @@ -1457,6 +1458,7 @@ common_handle_option (struct gcc_options *opts, { "unreachable", SANITIZE_UNREACHABLE, sizeof "unreachable" - 1 }, { "vla-bound", SANITIZE_VLA, sizeof "vla-bound" - 1 }, + { "return", SANITIZE_RETURN, sizeof "return" - 1 }, { "null", SANITIZE_NULL, sizeof "null" - 1 }, { NULL, 0, 0 } }; @@ -1707,7 +1709,7 @@ common_handle_option (struct gcc_options *opts, if (!opts_set->x_flag_tree_loop_distribute_patterns) opts->x_flag_tree_loop_distribute_patterns = value; /* Indirect call profiling should do all useful transformations - speculative devirutalization does. */ + speculative devirtualization does. */ if (!opts_set->x_flag_devirtualize_speculatively && opts->x_flag_value_profile_transformations) opts->x_flag_devirtualize_speculatively = false; diff --git a/gcc/passes.c b/gcc/passes.c index fee1513b404..ea89d7a2cfb 100644 --- a/gcc/passes.c +++ b/gcc/passes.c @@ -27,7 +27,6 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tm.h" #include "line-map.h" -#include "hash-table.h" #include "input.h" #include "tree.h" #include "varasm.h" @@ -46,7 +45,6 @@ along with GCC; see the file COPYING3. If not see #include "expr.h" #include "basic-block.h" #include "intl.h" -#include "ggc.h" #include "graph.h" #include "regs.h" #include "diagnostic-core.h" @@ -61,6 +59,10 @@ along with GCC; see the file COPYING3. If not see #include "coverage.h" #include "value-prof.h" #include "tree-inline.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-ssa.h" #include "tree-cfg.h" diff --git a/gcc/passes.def b/gcc/passes.def index a9411fa0baa..65c00bbbb41 100644 --- a/gcc/passes.def +++ b/gcc/passes.def @@ -117,6 +117,7 @@ along with GCC; see the file COPYING3. If not see compiled unit. */ INSERT_PASSES_AFTER (all_late_ipa_passes) NEXT_PASS (pass_ipa_pta); + NEXT_PASS (pass_omp_simd_clone); TERMINATE_PASS_LIST () /* These passes are run after IPA passes on every function that is being diff --git a/gcc/predict.c b/gcc/predict.c index afe78c6411e..df97eb06731 100644 --- a/gcc/predict.c +++ b/gcc/predict.c @@ -51,6 +51,11 @@ along with GCC; see the file COPYING3. If not see #include "params.h" #include "target.h" #include "cfgloop.h" +#include "pointer-set.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimple-ssa.h" @@ -60,11 +65,9 @@ along with GCC; see the file COPYING3. If not see #include "ssa-iterators.h" #include "tree-ssa-loop-niter.h" #include "tree-ssa-loop.h" -#include "ggc.h" #include "tree-pass.h" #include "tree-scalar-evolution.h" #include "cfgloop.h" -#include "pointer-set.h" /* real constants: 0, 1, 1-1/REG_BR_PROB_BASE, REG_BR_PROB_BASE, 1/REG_BR_PROB_BASE, 0.5, BB_FREQ_MAX. */ diff --git a/gcc/pretty-print.c b/gcc/pretty-print.c index 8cec71b762a..955a4c45f7b 100644 --- a/gcc/pretty-print.c +++ b/gcc/pretty-print.c @@ -50,8 +50,8 @@ output_buffer::output_buffer () output_buffer::~output_buffer () { - obstack_free (&chunk_obstack, obstack_finish (&chunk_obstack)); - obstack_free (&formatted_obstack, obstack_finish (&formatted_obstack)); + obstack_free (&chunk_obstack, NULL); + obstack_free (&formatted_obstack, NULL); } /* A pointer to the formatted diagnostic message. */ diff --git a/gcc/profile.c b/gcc/profile.c index 1d0e78ab4dc..9aec3cb06b3 100644 --- a/gcc/profile.c +++ b/gcc/profile.c @@ -61,6 +61,10 @@ along with GCC; see the file COPYING3. If not see #include "coverage.h" #include "value-prof.h" #include "tree.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "tree-cfg.h" diff --git a/gcc/recog.c b/gcc/recog.c index 404d7a7355b..30d5eb6fd43 100644 --- a/gcc/recog.c +++ b/gcc/recog.c @@ -315,8 +315,7 @@ insn_invalid_p (rtx insn, bool in_group) int icode = recog (pat, insn, (GET_CODE (pat) == SET && ! reload_completed - && ! reload_in_progress - && ! lra_in_progress) + && ! reload_in_progress) ? &num_clobbers : 0); int is_asm = icode < 0 && asm_noperands (PATTERN (insn)) >= 0; diff --git a/gcc/rtl.h b/gcc/rtl.h index 51c3bb91b54..3b8cdacbd8e 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -278,8 +278,7 @@ struct GTY((chain_next ("RTX_NEXT (&%h)"), In a CODE_LABEL, part of the two-bit alternate entry field. 1 in a CONCAT is VAL_EXPR_IS_COPIED in var-tracking.c. 1 in a VALUE is SP_BASED_VALUE_P in cselib.c. - 1 in a SUBREG generated by LRA for reload insns. - 1 in a CALL for calls instrumented by Pointer Bounds Checker. */ + 1 in a SUBREG generated by LRA for reload insns. */ unsigned int jump : 1; /* In a CODE_LABEL, part of the two-bit alternate entry field. 1 in a MEM if it cannot trap. @@ -1594,10 +1593,6 @@ do { \ #define LRA_SUBREG_P(RTX) \ (RTL_FLAG_CHECK1 ("LRA_SUBREG_P", (RTX), SUBREG)->jump) -/* True if call is instrumented by Pointer Bounds Checker. */ -#define CALL_EXPR_WITH_BOUNDS_P(RTX) \ - (RTL_FLAG_CHECK1 ("CALL_EXPR_WITH_BOUNDS_P", (RTX), CALL)->jump) - /* Access various components of an ASM_OPERANDS rtx. */ #define ASM_OPERANDS_TEMPLATE(RTX) XCSTR (RTX, 0, ASM_OPERANDS) diff --git a/gcc/sanitizer.def b/gcc/sanitizer.def index 9c59778f9f4..5bf1e3cebe6 100644 --- a/gcc/sanitizer.def +++ b/gcc/sanitizer.def @@ -60,6 +60,12 @@ DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_UNREGISTER_GLOBALS, DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_HANDLE_NO_RETURN, "__asan_handle_no_return", BT_FN_VOID, ATTR_TMPURE_NOTHROW_LEAF_LIST) +DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_BEFORE_DYNAMIC_INIT, + "__asan_before_dynamic_init", + BT_FN_VOID_CONST_PTR, ATTR_NOTHROW_LEAF_LIST) +DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_AFTER_DYNAMIC_INIT, + "__asan_after_dynamic_init", + BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST) /* Thread Sanitizer */ DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_INIT, "__tsan_init", @@ -297,6 +303,10 @@ DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE, "__ubsan_handle_builtin_unreachable", BT_FN_VOID_PTR, ATTR_COLD_NORETURN_NOTHROW_LEAF_LIST) +DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_MISSING_RETURN, + "__ubsan_handle_missing_return", + BT_FN_VOID_PTR, + ATTR_NORETURN_NOTHROW_LEAF_LIST) DEF_SANITIZER_BUILTIN(BUILT_IN_UBSAN_HANDLE_VLA_BOUND_NOT_POSITIVE, "__ubsan_handle_vla_bound_not_positive", BT_FN_VOID_PTR_PTR, diff --git a/gcc/sched-deps.c b/gcc/sched-deps.c index 287b826cfc6..f818a83ea2e 100644 --- a/gcc/sched-deps.c +++ b/gcc/sched-deps.c @@ -2820,6 +2820,37 @@ sched_analyze_2 (struct deps_desc *deps, rtx x, rtx insn) sched_deps_info->finish_rhs (); } +/* Try to group comparison and the following conditional jump INSN if + they're already adjacent. This is to prevent scheduler from scheduling + them apart. */ + +static void +try_group_insn (rtx insn) +{ + unsigned int condreg1, condreg2; + rtx cc_reg_1; + rtx prev; + + if (!any_condjump_p (insn)) + return; + + targetm.fixed_condition_code_regs (&condreg1, &condreg2); + cc_reg_1 = gen_rtx_REG (CCmode, condreg1); + prev = prev_nonnote_nondebug_insn (insn); + if (!reg_referenced_p (cc_reg_1, PATTERN (insn)) + || !prev + || !modified_in_p (cc_reg_1, prev)) + return; + + /* Different microarchitectures support macro fusions for different + combinations of insn pairs. */ + if (!targetm.sched.macro_fusion_pair_p + || !targetm.sched.macro_fusion_pair_p (prev, insn)) + return; + + SCHED_GROUP_P (insn) = 1; +} + /* Analyze an INSN with pattern X to find all dependencies. */ static void sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn) @@ -2843,6 +2874,11 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn) can_start_lhs_rhs_p = (NONJUMP_INSN_P (insn) && code == SET); + /* Group compare and branch insns for macro-fusion. */ + if (targetm.sched.macro_fusion_p + && targetm.sched.macro_fusion_p ()) + try_group_insn (insn); + if (may_trap_p (x)) /* Avoid moving trapping instructions across function calls that might not always return. */ @@ -3733,6 +3769,10 @@ sched_analyze (struct deps_desc *deps, rtx head, rtx tail) { /* And initialize deps_lists. */ sd_init_insn (insn); + /* Clean up SCHED_GROUP_P which may be set by last + scheduler pass. */ + if (SCHED_GROUP_P (insn)) + SCHED_GROUP_P (insn) = 0; } deps_analyze_insn (deps, insn); diff --git a/gcc/sese.c b/gcc/sese.c index 2fe77392bd4..7e59ac8d909 100644 --- a/gcc/sese.c +++ b/gcc/sese.c @@ -25,6 +25,13 @@ along with GCC; see the file COPYING3. If not see #include "hash-table.h" #include "tree.h" #include "tree-pretty-print.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "gimple-iterator.h" diff --git a/gcc/stmt.c b/gcc/stmt.c index f7d5b4b945b..3cc058e723e 100644 --- a/gcc/stmt.c +++ b/gcc/stmt.c @@ -43,16 +43,20 @@ along with GCC; see the file COPYING3. If not see #include "machmode.h" #include "diagnostic-core.h" #include "output.h" -#include "ggc.h" #include "langhooks.h" #include "predict.h" #include "optabs.h" #include "target.h" +#include "pointer-set.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "regs.h" #include "alloc-pool.h" #include "pretty-print.h" -#include "pointer-set.h" #include "params.h" #include "dumpfile.h" diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c index 839a7c2e01a..32bc2852b61 100644 --- a/gcc/stor-layout.c +++ b/gcc/stor-layout.c @@ -33,7 +33,6 @@ along with GCC; see the file COPYING3. If not see #include "function.h" #include "expr.h" #include "diagnostic-core.h" -#include "ggc.h" #include "target.h" #include "langhooks.h" #include "regs.h" @@ -41,7 +40,6 @@ along with GCC; see the file COPYING3. If not see #include "cgraph.h" #include "tree-inline.h" #include "tree-dump.h" -#include "gimple.h" #include "gimplify.h" /* Data type for the expressions representing sizes of data types. @@ -388,7 +386,6 @@ int_mode_for_mode (enum machine_mode mode) case MODE_VECTOR_ACCUM: case MODE_VECTOR_UFRACT: case MODE_VECTOR_UACCUM: - case MODE_POINTER_BOUNDS: mode = mode_for_size (GET_MODE_BITSIZE (mode), MODE_INT, 0); break; @@ -2127,14 +2124,6 @@ layout_type (tree type) SET_TYPE_MODE (type, VOIDmode); break; - case POINTER_BOUNDS_TYPE: - SET_TYPE_MODE (type, - mode_for_size (TYPE_PRECISION (type), - MODE_POINTER_BOUNDS, 0)); - TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (TYPE_MODE (type))); - TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (TYPE_MODE (type))); - break; - case OFFSET_TYPE: TYPE_SIZE (type) = bitsize_int (POINTER_SIZE); TYPE_SIZE_UNIT (type) = size_int (POINTER_SIZE / BITS_PER_UNIT); diff --git a/gcc/symtab.c b/gcc/symtab.c index 851264d954a..dc700e7c735 100644 --- a/gcc/symtab.c +++ b/gcc/symtab.c @@ -28,11 +28,15 @@ along with GCC; see the file COPYING3. If not see #include "varasm.h" #include "function.h" #include "emit-rtl.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "tree-inline.h" #include "langhooks.h" #include "hashtab.h" -#include "ggc.h" #include "cgraph.h" #include "diagnostic.h" #include "timevar.h" diff --git a/gcc/target.def b/gcc/target.def index de75e8d0bd8..6f282326ea3 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -1521,6 +1521,36 @@ hook_int_uint_mode_1) HOOK_VECTOR_END (sched) +/* Functions relating to OpenMP and Cilk Plus SIMD clones. */ +#undef HOOK_PREFIX +#define HOOK_PREFIX "TARGET_SIMD_CLONE_" +HOOK_VECTOR (TARGET_SIMD_CLONE, simd_clone) + +DEFHOOK +(compute_vecsize_and_simdlen, +"This hook should set @var{vecsize_mangle}, @var{vecsize_int}, @var{vecsize_float}\n\ +fields in @var{simd_clone} structure pointed by @var{clone_info} argument and also\n\ +@var{simdlen} field if it was previously 0.\n\ +The hook should return 0 if SIMD clones shouldn't be emitted,\n\ +or number of @var{vecsize_mangle} variants that should be emitted.", +int, (struct cgraph_node *, struct cgraph_simd_clone *, tree, int), NULL) + +DEFHOOK +(adjust, +"This hook should add implicit @code{attribute(target(\"...\"))} attribute\n\ +to SIMD clone @var{node} if needed.", +void, (struct cgraph_node *), NULL) + +DEFHOOK +(usable, +"This hook should return -1 if SIMD clone @var{node} shouldn't be used\n\ +in vectorized loops in current function, or non-negative number if it is\n\ +usable. In that case, the smaller the number is, the more desirable it is\n\ +to use it.", +int, (struct cgraph_node *), NULL) + +HOOK_VECTOR_END (simd_clone) + /* Functions relating to vectorization. */ #undef HOOK_PREFIX #define HOOK_PREFIX "TARGET_VECTORIZE_" @@ -2048,104 +2078,6 @@ built-in function.", (tree exp, rtx target, rtx subtarget, enum machine_mode mode, int ignore), default_expand_builtin) -DEFHOOK -(builtin_chkp_function, - "This hook allows target to redefine built-in functions used by\n\ -Pointer Bounds Checker for code instrumentation. Hook should return\n\ -fndecl of function implementing generic builtin whose code is\n\ -passed in @var{fcode}. Currently following built-in functions are\n\ -obtained using this hook:\n\ -@deftypefn {Built-in Function} bnd __chkp_bndmk (const void *@var{lb}, size_t @var{size})\n\ -Function code - BUILT_IN_CHKP_BNDMK. This built-in function is used\n\ -by Pointer Bounds Checker to create bound values. @var{lb} holds low\n\ -bound of the resulting bounds. @var{size} holds size of created bounds.\n\ -@end deftypefn\n\ -\n\ -@deftypefn {Built-in Function} void __chkp_bndstx (const void **@var{loc}, const void *@var{ptr}, bnd @var{b})\n\ -Function code - @code{BUILT_IN_CHKP_BNDSTX}. This built-in function is used\n\ -by Pointer Bounds Checker to store bounds @var{b} for pointer @var{ptr}\n\ -stored by address @var{loc}.\n\ -@end deftypefn\n\ -\n\ -@deftypefn {Built-in Function} bnd __chkp_bndldx (const void **@var{loc}, const void *@var{ptr})\n\ -Function code - @code{BUILT_IN_CHKP_BNDLDX}. This built-in function is used\n\ -by Pointer Bounds Checker to get bounds of pointer @var{ptr} loaded by\n\ -address @var{loc}.\n\ -@end deftypefn\n\ -\n\ -@deftypefn {Built-in Function} void __chkp_bndcl (bnd @var{b}, const void *@var{ptr})\n\ -Function code - @code{BUILT_IN_CHKP_BNDCL}. This built-in function is used\n\ -by Pointer Bounds Checker to perform check for pointer @var{ptr} against\n\ -lower bound of bounds @var{b}.\n\ -@end deftypefn\n\ -\n\ -@deftypefn {Built-in Function} void __chkp_bndcu (bnd @var{b}, const void *@var{ptr})\n\ -Function code - @code{BUILT_IN_CHKP_BNDCU}. This built-in function is used\n\ -by Pointer Bounds Checker to perform check for pointer @var{ptr} against\n\ -upper bound of bounds @var{b}.\n\ -@end deftypefn\n\ -\n\ -@deftypefn {Built-in Function} bnd __chkp_bndret (void *@var{ptr})\n\ -Function code - @code{BUILT_IN_CHKP_BNDRET}. This built-in function is used\n\ -by Pointer Bounds Checker to obtain bounds returned by call statement.\n\ -@var{ptr} passed to buil-in is @code{SSA_NAME} returned by call.\n\ -@end deftypefn\n\ -\n\ -@deftypefn {Built-in Function} bnd __chkp_arg_bnd (void *@var{arg})\n\ -Function code - @code{BUILT_IN_CHKP_ARG_BND}. This built-in function is\n\ -used by Pointer Bounds Checker to obtain bounds passed for input argument.\n\ -@var{arg} is default @code{SSA_NAME} of the @code{PARM_DECL} whose\n\ -bounds we want to obtain.\n\ -@end deftypefn\n\ -\n\ -@deftypefn {Built-in Function} bnd __chkp_intersect (bnd @var{b1}, bnd @var{b2})\n\ -Function code - @code{BUILT_IN_CHKP_INTERSECT}. This built-in function\n\ -returns intersection of bounds @var{b1} and @var{b2}.\n\ -@end deftypefn\n\ -\n\ -@deftypefn {Built-in Function} bnd __chkp_narrow (const void *@var{ptr}, bnd @var{b}, size_t @var{s})\n\ -Function code - @code{BUILT_IN_CHKP_NARROW}. This built-in function\n\ -returns intersection of bounds @var{b} and\n\ -[@var{ptr}, @var{ptr} + @var{s} - @code{1}].\n\ -@end deftypefn\n\ -\n\ -@deftypefn {Built-in Function} void *__chkp_set_bounds (const void *@var{ptr}, size_t @var{s})\n\ -Function code - @code{BUILT_IN_CHKP_SET_PTR_BOUNDS}. This built-in function\n\ -returns @var{ptr} with bounds [@var{ptr}, @var{ptr} + @var{s} - @code{1}].\n\ -@end deftypefn\n\ -\n\ -@deftypefn {Built-in Function} size_t __chkp_sizeof (const void *@var{ptr})\n\ -Function code - @code{BUILT_IN_CHKP_SIZEOF}. This built-in function\n\ -returns size of object referenced by @var{ptr}. @var{ptr} is always\n\ -@code{ADDR_EXPR} of @code{VAR_DECL}. This built-in is used by\n\ -Pointer Boudns Checker when bounds of object cannot be computed statically\n\ -(e.g. object has incomplete type).\n\ -@end deftypefn\n\ -\n\ -@deftypefn {Built-in Function} const void *__chkp_extract_lower (bnd @var{b})\n\ -Function code - @code{BUILT_IN_CHKP_EXTRACT_LOWER}. This built-in function\n\ -returns lower bound of bounds @var{b}.\n\ -@end deftypefn\n\ -\n\ -@deftypefn {Built-in Function} const void *__chkp_extract_upper (bnd @var{b})\n\ -Function code - @code{BUILT_IN_CHKP_EXTRACT_UPPER}. This built-in function\n\ -returns upper bound of bounds @var{b}.\n\ -@end deftypefn", - tree, (unsigned fcode), - default_builtin_chkp_function) - -DEFHOOK -(chkp_bound_type, - "Return type to be used for bounds", - tree, (void), - default_chkp_bound_type) - -DEFHOOK -(chkp_bound_mode, - "Return mode to be used for bounds.", - enum machine_mode, (void), - default_chkp_bound_mode) - /* Select a replacement for a target-specific builtin. This is done *before* regular type checking, and so allows the target to implement a crude form of function overloading. The result is a @@ -3396,15 +3328,6 @@ The default version of this hook returns @code{va_list_type_node}.", tree, (tree fndecl), std_fn_abi_va_list) -DEFHOOK -(fn_abi_va_list_bounds_size, - "This hook returns size for @code{va_list} object in function specified\n\ -by @var{fndecl}. This hook is used by Pointer Bounds Checker to build bounds\n\ -for @code{va_list} object. Return @code{integer_zero_node} if no bounds\n\ -should be used (e.g. @code{va_list} is a scalar pointer to the stack).", - tree, (tree fndecl), - default_fn_abi_va_list_bounds_size) - /* Get the __builtin_va_list type dependent on input type. */ DEFHOOK (canonical_va_list_type, @@ -3853,30 +3776,6 @@ not generate any instructions in this case.", default_setup_incoming_varargs) DEFHOOK -(load_bounds_for_arg, - "This hook is used by expand pass to emit insn to load bounds of\n\ -@var{arg} passed in @var{slot}. Expand pass uses this hook in case\n\ -bounds of @var{arg} are not passed in register. If @var{slot} is a\n\ -memory, then bounds are loaded as for regular pointer loaded from\n\ -memory. If @var{slot} is not a memory then @var{slot_no} is an integer\n\ -constant holding number of the target dependent special slot which\n\ -should be used to obtain bounds. Hook returns RTX holding loaded bounds.", - rtx, (rtx slot, rtx arg, rtx slot_no), - default_load_bounds_for_arg) - -DEFHOOK -(store_bounds_for_arg, - "This hook is used by expand pass to emit insns to store @var{bounds} of\n\ -@var{arg} passed in @var{slot}. Expand pass uses this hook in case\n\ -@var{bounds} of @var{arg} are not passed in register. If @var{slot} is a\n\ -memory, then @var{bounds} are stored as for regular pointer stored in\n\ -memory. If @var{slot} is not a memory then @var{slot_no} is an integer\n\ -constant holding number of the target dependent special slot which\n\ -should be used to store @var{bounds}.", - void, (rtx arg, rtx slot, rtx bounds, rtx slot_no), - default_store_bounds_for_arg) - -DEFHOOK (strict_argument_naming, "Define this hook to return @code{true} if the location where a function\n\ argument is passed depends on whether or not it is a named argument.\n\ @@ -5297,6 +5196,17 @@ DEFHOOKPOD @code{bool} @code{true}.", unsigned char, 1) +/* Return an unsigned int representing the alignment (in bits) of the atomic + type which maps to machine MODE. This allows alignment to be overridden + as needed. */ +DEFHOOK +(atomic_align_for_mode, +"If defined, this function returns an appropriate alignment in bits for an\ + atomic object of machine_mode @var{mode}. If 0 is returned then the\ + default alignment for the specified mode is used. ", + unsigned int, (enum machine_mode mode), + hook_uint_mode_0) + DEFHOOK (atomic_assign_expand_fenv, "ISO C11 requires atomic compound assignments that may raise floating-point\ diff --git a/gcc/target.h b/gcc/target.h index 19522e25750..68873bd1385 100644 --- a/gcc/target.h +++ b/gcc/target.h @@ -93,6 +93,8 @@ extern bool target_default_pointer_address_modes_p (void); struct stdarg_info; struct spec_info_def; struct hard_reg_set_container; +struct cgraph_node; +struct cgraph_simd_clone; /* The struct used by the secondary_reload target hook. */ typedef struct secondary_reload_info diff --git a/gcc/targhooks.c b/gcc/targhooks.c index c383520314f..5b914e7df41 100644 --- a/gcc/targhooks.c +++ b/gcc/targhooks.c @@ -62,7 +62,6 @@ along with GCC; see the file COPYING3. If not see #include "target.h" #include "tm_p.h" #include "target-def.h" -#include "ggc.h" #include "hard-reg-set.h" #include "regs.h" #include "reload.h" @@ -70,11 +69,11 @@ along with GCC; see the file COPYING3. If not see #include "recog.h" #include "intl.h" #include "opts.h" -#include "gimple.h" +#include "tree-ssa-alias.h" +#include "gimple-expr.h" #include "gimplify.h" #include "stringpool.h" #include "tree-ssanames.h" -#include "tree-ssa-alias.h" #include "insn-codes.h" @@ -1572,28 +1571,6 @@ default_member_type_forces_blk (const_tree, enum machine_mode) { return false; } -rtx -default_load_bounds_for_arg (rtx addr ATTRIBUTE_UNUSED, - rtx ptr ATTRIBUTE_UNUSED, - rtx bnd ATTRIBUTE_UNUSED) -{ - gcc_unreachable (); -} - -void -default_store_bounds_for_arg (rtx val ATTRIBUTE_UNUSED, - rtx addr ATTRIBUTE_UNUSED, - rtx bounds ATTRIBUTE_UNUSED, - rtx to ATTRIBUTE_UNUSED) -{ - gcc_unreachable (); -} - -tree -default_fn_abi_va_list_bounds_size (tree fndecl ATTRIBUTE_UNUSED) -{ - return integer_zero_node; -} /* Default version of canonicalize_comparison. */ @@ -1719,27 +1696,6 @@ std_gimplify_va_arg_expr (tree valist, tree type, gimple_seq *pre_p, return build_va_arg_indirect_ref (addr); } -tree -default_chkp_bound_type (void) -{ - tree res = make_node (POINTER_BOUNDS_TYPE); - TYPE_PRECISION (res) = TYPE_PRECISION (size_type_node) * 2; - layout_type (res); - return res; -} - -enum machine_mode -default_chkp_bound_mode (void) -{ - return VOIDmode; -} - -tree -default_builtin_chkp_function (unsigned int fcode ATTRIBUTE_UNUSED) -{ - return NULL_TREE; -} - /* An implementation of TARGET_CAN_USE_DOLOOP_P for targets that do not support nested low-overhead loops. */ diff --git a/gcc/targhooks.h b/gcc/targhooks.h index aed57788bad..0d8a30e43c4 100644 --- a/gcc/targhooks.h +++ b/gcc/targhooks.h @@ -206,13 +206,6 @@ extern bool default_member_type_forces_blk (const_tree, enum machine_mode); extern void default_atomic_assign_expand_fenv (tree *, tree *, tree *); extern tree build_va_arg_indirect_ref (tree); extern tree std_gimplify_va_arg_expr (tree, tree, gimple_seq *, gimple_seq *); - -extern rtx default_load_bounds_for_arg (rtx, rtx, rtx); -extern void default_store_bounds_for_arg (rtx, rtx, rtx, rtx); -extern tree default_fn_abi_va_list_bounds_size (tree); -extern tree default_chkp_bound_type (void); -extern enum machine_mode default_chkp_bound_mode (void); -extern tree default_builtin_chkp_function (unsigned int); extern bool can_use_doloop_if_innermost (const widest_int &, const widest_int &, unsigned int, bool); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 3095cffa11d..e35854179d2 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,519 @@ +2013-12-04 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/59355 + * g++.dg/ipa/pr59355.C: New test. + +2013-12-04 Yufeng Zhang <yufeng.zhang@arm.com> + + * gcc.dg/tree-ssa/slsr-39.c: Update. + * gcc.dg/tree-ssa/slsr-41.c: New test. + +2013-12-03 Adhemerval Zanella <azanella@linux.vnet.ibm.com> + + * gcc.target/powerpc/pr57363.c: New test. + +2013-12-03 Wei Mi <wmi@google.com> + + PR rtl-optimization/59020 + * testsuite/gcc.dg/pr59020.c: New. + * testsuite/gcc.dg/macro-fusion-1.c: New. + * testsuite/gcc.dg/macro-fusion-2.c: New. + +2013-12-03 Yury Gribov <y.gribov@samsung.com> + + PR sanitizer/59063 + * lib/asan-dg.exp: Don't add anything to flags if libsanitizer + has not been found. + * lib/ubsan-dg.exp: Likewise. Append to flags also + -B${gccpath}/libsanitizer/. + +2013-12-03 Bill Schmidt <wschmidt@linux.vnet.ibm.com> + + * gcc.dg/vect/costmodel/ppc/costmodel-slp-34.c: Skip for little + endian. + +2013-12-03 H.J. Lu <hongjiu.lu@intel.com> + + PR target/59363 + * gcc.target/i386/pr59363.c: New file. + +2013-12-03 Marek Polacek <polacek@redhat.com> + + PR c/59351 + * gcc.dg/pr59351.c: New test. + +2013-12-03 Chung-Ju Wu <jasonwucj@gmail.com> + + * gcc.dg/20020312-2.c: Add __nds32__ case. + * gcc.dg/builtin-apply2.c: Skip for nds32*-*-*. + * gcc.dg/sibcall-3.c: Expected fail for nds32*-*-*. + * gcc.dg/sibcall-4.c: Expected fail for nds32*-*-*. + * gcc.dg/stack-usage-1.c (SIZE): Define case for __nds32__. + * gcc.dg/torture/pr37868.c: Skip for nds32*-*-*. + * gcc.dg/torture/stackalign/builtin-apply-2.c: Skip for nds32*-*-*. + * gcc.dg/tree-ssa/20040204-1.c: Expected fail for nds32*-*-*. + * gcc.dg/tree-ssa/pr42585.c: Skip for nds32*-*-*. + * gcc.dg/tree-ssa/sra-12.c: Skip for nds32*-*-*. + * gcc.target/nds32: New nds32 specific directory and testcases. + * lib/target-supports.exp (check_profiling_available): Check for + nds32*-*-elf. + +2013-12-03 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/59362 + * gcc.c-torture/compile/pr59362.c: New test. + + PR middle-end/59011 + * gcc.dg/pr59011.c: New test. + + PR target/58864 + * g++.dg/opt/pr58864.C: New test. + +2013-12-02 Jeff Law <law@redhat.com> + + PR tree-optimization/59322 + * gcc.c-torture/compile/pr59322.c: New test. + +2013-12-02 Sriraman Tallam <tmsriram@google.com> + + PR target/58944 + * testsuite/gcc.target/i386/pr58944.c: New test. + +2013-12-02 Joseph Myers <joseph@codesourcery.com> + + PR c/58235 + * gcc.dg/c90-array-lval-8.c: New test. + +2013-12-02 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/59358 + * gcc.c-torture/execute/pr59358.c: New test. + + PR lto/59326 + * gcc.target/i386/i386.exp (check_effective_target_avx2): Move to... + * lib/target-supports.exp (check_effective_target_avx2): ... here. + (check_effective_target_vect_simd_clones): New. + * gcc.dg/vect/vect-simd-clone-1.c: Add dg-require-effective-target + vect_simd_clones. + * gcc.dg/vect/vect-simd-clone-2.c: Likewise. + * gcc.dg/vect/vect-simd-clone-3.c: Likewise. + * gcc.dg/vect/vect-simd-clone-4.c: Likewise. + * gcc.dg/vect/vect-simd-clone-5.c: Likewise. + * gcc.dg/vect/vect-simd-clone-6.c: Likewise. + * gcc.dg/vect/vect-simd-clone-7.c: Likewise. + * gcc.dg/vect/vect-simd-clone-8.c: Likewise. + * gcc.dg/vect/vect-simd-clone-9.c: Likewise. + * gcc.dg/vect/vect-simd-clone-10.c: Likewise. + * gcc.dg/vect/vect-simd-clone-11.c: Likewise. + * gcc.dg/vect/vect-simd-clone-12.c: Likewise. + +2013-12-02 Bernd Edlinger <bernd.edlinger@hotmail.de> + + * gcc.dg/pr56997-4.c: New testcase. + +2013-12-02 Marek Polacek <polacek@redhat.com> + + * c-c++-common/ubsan/vla-1.c: Split the tests into individual + functions. + +2013-12-02 Richard Biener <rguenther@suse.de> + + PR tree-optimization/59139 + * gcc.dg/torture/pr59139.c: New testcase. + +2013-12-02 Eric Botcazou <ebotcazou@adacore.com> + + * gnat.dg/opt30.adb: New test. + +2013-12-01 Paul Thomas <pault@gcc.gnu.org> + + PR fortran/57354 + * gfortran.dg/realloc_on_assign_23.f90 : New test + +2013-12-01 Paul Thomas <pault@gcc.gnu.org> + + PR fortran/34547 + * gfortran.dg/null_5.f90 : Include new error. + * gfortran.dg/null_6.f90 : Include new error. + +2013-11-29 Marek Polacek <polacek@redhat.com> + + PR sanitizer/59331 + * g++.dg/ubsan/pr59331.C: New test. + * g++.dg/ubsan/cxx1y-vla.C: Enable -Wall -Wno-unused-variable. + Disable the -w option. + * c-c++-common/ubsan/vla-1.c: Likewise. + * c-c++-common/ubsan/vla-2.c: Likewise. + * c-c++-common/ubsan/vla-3.c: Don't use the -w option. + +2013-11-29 Joseph Myers <joseph@codesourcery.com> + + PR c/42262 + * gcc.dg/c99-init-5.c, gcc.dg/c99-init-6.c: New tests. + +2013-11-29 H.J. Lu <hongjiu.lu@intel.com> + + * lib/asan-dg.exp (asan_link_flags): Properly add path to + libsanitizer.spec to cflags. + +2013-11-29 Richard Biener <rguenther@suse.de> + + PR middle-end/59208 + * g++.dg/torture/pr59208.C: New testcase. + +2013-11-29 Jakub Jelinek <jakub@redhat.com> + Yury Gribov <y.gribov@samsung.com> + + PR sanitizer/59063 + * c-c++-common/asan/pr59063-1.c: New test. + * c-c++-common/asan/pr59063-2.c: Likewise. + * lib/asan-dg.exp: Add path to libsanitizer.spec to cflags. + * lib/ubsan-dg.exp: Likewise. + +2013-11-29 Eric Botcazou <ebotcazou@adacore.com> + + * gnat.dg/opt29.ad[sb]: New test. + +2013-11-29 Richard Biener <rguenther@suse.de> + + PR middle-end/59338 + * gcc.dg/torture/pr59338.c: New testcase. + +2013-11-29 Jakub Jelinek <jakub@redhat.com> + + PR lto/59326 + * gcc.dg/vect/vect-simd-clone-12.c: New test. + * gcc.dg/vect/vect-simd-clone-12a.c: New test. + * gcc.dg/vect/vect-simd-clone-10a.c: Remove extern keywords. + + PR c/59280 + * c-c++-common/pr59280.c: New test. + +2013-11-29 Zhenqiang Chen <zhenqiang.chen@linaro.org> + + * gcc.target/arm/lp1243022.c: Skip target arm-neon. + +2013-11-29 Joseph Myers <joseph@codesourcery.com> + + PR c/57574 + * gcc.dg/inline-35.c: New test. + +2013-11-28 Jakub Jelinek <jakub@redhat.com> + + PR c++/59297 + * g++.dg/gomp/pr59297.C: New test. + +2013-11-28 Vladimir Makarov <vmakarov@redhat.com> + + PR target/57293 + * gcc.target/i386/pr57293.c: New. + +2013-11-28 Kyrylo Tkachov <kyrylo.tkachov@arm.com> + + * gcc.target/arm/vrinta-ce.c: New testcase. + +2013-11-28 Richard Biener <rguenther@suse.de> + + PR lto/59323 + * gcc.dg/lto/pr59323-2_0.c: New testcase. + +2013-11-28 Richard Biener <rguenther@suse.de> + + PR tree-optimization/59330 + * gcc.dg/torture/pr59330.c: New testcase. + +2013-11-28 Richard Biener <rguenther@suse.de> + + PR lto/59323 + * gcc.dg/lto/pr59323_0.c: New testcase. + +2013-11-28 Jakub Jelinek <jakub@redhat.com> + + PR middle-end/57393 + PR tree-optimization/58018 + PR tree-optimization/58131 + * gcc.dg/torture/pr57393-1.c: New test. + * gcc.dg/torture/pr57393-2.c: New test. + * gcc.dg/torture/pr57393-3.c: New test. + * gcc.dg/torture/pr58018.c: New test. + * gcc.dg/torture/pr58131.c: New test. + * gfortran.dg/pr57393-1.f90: New test. + * gfortran.dg/pr57393-2.f90: New test. + +2013-11-27 Bill Schmidt <wschmidt@linux.vnet.ibm.com> + + * gfortran.dg/nan_7.f90: Disable for little endian PowerPC. + +2013-11-27 Eric Botcazou <ebotcazou@adacore.com> + + * gcc.dg/guality/param-3.c: New test. + +2013-11-27 Uros Bizjak <ubizjak@gmail.com> + Ganesh Gopalasubramanian <Ganesh.Gopalasubramanian@amd.com> + + PR target/56788 + * gcc.target/i386/xop-frczX.c: New test. + +2013-11-27 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/59014 + * gcc.c-torture/execute/pr59014-2.c: New test. + +2013-11-27 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/58647 + * g++.dg/parse/crash66.C: New. + +2013-11-27 Kenneth Zadeck <zadeck@naturalbridge.com> + + * gcc.dg/c90-const-expr-8.c: Look for overflow on INT_MIN % -1. + * gcc.dg/c99-const-expr-8.c: Look for overflow on INT_MIN % -1. + +2013-11-27 Marek Polacek <polacek@redhat.com> + + PR sanitizer/59306 + * g++.dg/ubsan/pr59306.C: New test. + +2013-11-27 Aldy Hernandez <aldyh@redhat.com> + Jakub Jelinek <jakub@redhat.com> + + * g++.dg/gomp/declare-simd-1.C (f38): Make sure + simdlen is a power of two. + * gcc.dg/gomp/simd-clones-2.c: Compile on all targets. + Remove -msse2. Adjust regexps for name mangling changes. + * gcc.dg/gomp/simd-clones-3.c: Likewise. + * gcc.dg/vect/vect-simd-clone-1.c: New test. + * gcc.dg/vect/vect-simd-clone-2.c: New test. + * gcc.dg/vect/vect-simd-clone-3.c: New test. + * gcc.dg/vect/vect-simd-clone-4.c: New test. + * gcc.dg/vect/vect-simd-clone-5.c: New test. + * gcc.dg/vect/vect-simd-clone-6.c: New test. + * gcc.dg/vect/vect-simd-clone-7.c: New test. + * gcc.dg/vect/vect-simd-clone-8.c: New test. + * gcc.dg/vect/vect-simd-clone-9.c: New test. + * gcc.dg/vect/vect-simd-clone-10.c: New test. + * gcc.dg/vect/vect-simd-clone-10.h: New file. + * gcc.dg/vect/vect-simd-clone-10a.c: New file. + * gcc.dg/vect/vect-simd-clone-11.c: New test. + +2013-11-27 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + * gcc.dg/cilk-plus/cilk-plus.exp: Append to ld_library_path. + Call set_ld_library_path_env_vars. + * g++.dg/cilk-plus/cilk-plus.exp: Likewise. + +2013-11-27 Tom de Vries <tom@codesourcery.com> + Marc Glisse <marc.glisse@inria.fr> + + PR c++/59032 + * c-c++-common/pr59032.c: New testcase. + +2013-11-27 Tom de Vries <tom@codesourcery.com> + Marc Glisse <marc.glisse@inria.fr> + + PR middle-end/59037 + * c-c++-common/pr59037.c: New testcase. + +2013-11-27 Eric Botcazou <ebotcazou@adacore.com> + + * gcc.c-torture/execute/20131127-1.c: New test. + +2013-11-27 Richard Biener <rguenther@suse.de> + + PR tree-optimization/59288 + * gcc.dg/torture/pr59288.c: New testcase. + +2013-11-27 Marek Polacek <polacek@redhat.com> + + * c-c++-common/ubsan/undefined-1.c: New test. + +2013-11-26 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/59014 + * gcc.c-torture/execute/pr59014.c: New test. + + PR target/59229 + * gcc.c-torture/execute/pr59229.c: New test. + + PR rtl-optimization/59166 + * gcc.dg/torture/pr59166.c: New test. + + PR c++/58874 + * g++.dg/gomp/pr58874.C: New test. + + PR middle-end/59150 + * g++.dg/gomp/pr59150.C: New test. + + PR middle-end/59152 + * c-c++-common/gomp/pr59152.c: New test. + +2013-11-26 Uros Bizjak <ubizjak@gmail.com> + + * gcc.dg/gomp/openmp-simd-1.c: Cleanup original tree dump. + * gcc.dg/gomp/openmp-simd-2.c: Ditto. + * g++.dg/gomp/openmp-simd-1.C: Ditto. + * g++.dg/gomp/openmp-simd-2.C: Ditto. + * gfortran.dg/c_loc_test_22.f90: Ditto. + * gcc.dg/tree-ssa/attr-alias-2.c: Cleanup optimized tree dump. + * gcc.dg/tree-ssa/isolate-5.c: Ditto. + * gcc.dg/tree-ssa/pr57361.c: Cleanup dse1 tree dump. + * gcc.dg/vect/vect-124.c: Cleanup vect tree dump. + * gcc.dg/pr57518.c: Cleanup ira rtl dump. + * gcc.dg/tree-prof/cold_partition_label.c: Cleanup saved temps. + +2013-11-26 Yufeng Zhang <yufeng.zhang@arm.com> + + * gcc.target/arm/20131120.c: New test. + +2013-11-26 Richard Biener <rguenther@suse.de> + + PR tree-optimization/59245 + * gcc.dg/torture/pr59245.c: New testcase. + +2013-11-26 Kyrylo Tkachov <kyrylo.tkachov@arm.com> + + PR target/59290 + * gcc.target/arm/negdi-2.c: Scan more general register names. + +2013-11-26 Terry Guo <terry.guo@arm.com> + + * gcc.target/arm/thumb1-pic-high-reg.c: New case. + * gcc.target/arm/thumb1-pic-single-base.c: New case. + +2013-11-26 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/58700 + * g++.dg/parse/bitfield4.C: New. + +2013-11-26 Richard Biener <rguenther@suse.de> + + PR tree-optimization/59287 + * gcc.dg/tree-ssa/alias-29.c: New testcase. + +2013-11-25 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/54485 + * g++.dg/other/default8.C: New. + * g++.dg/tc1/dr217.C: Remove xfail. + * g++.dg/other/default5.C: Adjust. + * g++.old-deja/g++.mike/p1989.C: Likewise. + +2013-11-25 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/58607 + * g++.dg/cpp0x/constexpr-ice9.C: New. + +2013-11-25 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/58810 + * g++.dg/other/cv_func3.C: New. + * g++.dg/other/cv_func.C: Adjust. + * g++.dg/parse/fn-typedef2.C: Likewise. + +2013-11-25 Marek Polacek <polacek@redhat.com> + + PR sanitizer/59250 + * g++.dg/ubsan/pr59250.C: New test. + +2013-11-25 Janus Weil <janus@gcc.gnu.org> + + PR fortran/59143 + * gfortran.dg/typebound_proc_30.f90: New. + +2013-11-25 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/59080 + * g++.dg/cpp0x/initlist75.C: New. + + PR c++/59096 + * g++.dg/cpp0x/gen-attrs-57.C: New. + +2013-11-25 Adam Butcher <adam@jessamine.co.uk> + + PR c++/59112 + PR c++/59113 + * g++.dg/cpp1y/pr58533.C: Updated testcase. + * g++.dg/cpp1y/pr59112.C: New testcase. + * g++.dg/cpp1y/pr59113.C: New testcase. + +2013-11-25 Terry Guo <terry.guo@arm.com> + + * gcc.target/arm/thumb2-slow-flash-data.c: New. + +2013-11-23 Uros Bizjak <ubizjak@gmail.com> + + * gcc.dg/float-exact-1.c: Use dg-add-options ieee. + [LDBL_MANT_DIG == 113]: Fix wrong variable name. + +2013-11-23 Janus Weil <janus@gcc.gnu.org> + + PR fortran/59228 + * gfortran.dg/asynchronous_4.f90: New. + +2013-11-22 Jakub Jelinek <jakub@redhat.com> + + * c-c++-common/asan/no-redundant-instrumentation-7.c: Fix + cleanup-tree-dump directive. + +2013-11-22 Jan Hubicka <jh@suse.cz> + + * gcc.dg/20081223-1.c: Add -ffat-lto-objects. + * gcc.dg/vect/vect.exp: Add -ffat-lto-objects. + +2013-11-22 Jakub Jelinek <jakub@redhat.com> + + * g++.dg/ubsan/return-1.C: New test. + * g++.dg/ubsan/return-2.C: New test. + + * c-c++-common/asan/no-redundant-instrumentation-1.c: Tweak to avoid + optimizing away some __asan_report* calls. + +2013-11-22 Martin Jambor <mjambor@suse.cz> + + * gcc.dg/pr10474.c: Also test ppc64. + * gcc.dg/ira-shrinkwrap-prep-1.c: Also test ppc64, change all ints + to longs. + * gcc.dg/ira-shrinkwrap-prep-2.c: Likewise. + +2013-11-22 Michael Meissner <meissner@linux.vnet.ibm.com> + + PR target/59054 + * gcc.target/powerpc/direct-move.h (VSX_REG_ATTR): Allow test to + specify an appropriate register class for VSX operations. + (load_vsx): Use it. + (load_gpr_to_vsx): Likewise. + (load_vsx_to_gpr): Likewise. + * gcc.target/powerpc/direct-move-vint1.c: Use an appropriate + register class for VSX registers that the type can handle. Remove + checks for explicit number of instructions generated, just check + if the instruction is generated. + * gcc.target/powerpc/direct-move-vint2.c: Likewise. + * gcc.target/powerpc/direct-move-float1.c: Likewise. + * gcc.target/powerpc/direct-move-float2.c: Likewise. + * gcc.target/powerpc/direct-move-double1.c: Likewise. + * gcc.target/powerpc/direct-move-double2.c: Likewise. + * gcc.target/powerpc/direct-move-long1.c: Likewise. + * gcc.target/powerpc/direct-move-long2.c: Likewise. + + * gcc.target/powerpc/pr59054.c: Remove duplicate code. + + * gcc.target/powerpc/bool3-av.c: Limit to 64-bit mode for now. + * gcc.target/powerpc/bool3-p7.c: Likewise. + * gcc.target/powerpc/bool3-p8.c: Likewise. + + * gcc.target/powerpc/p8vector-ldst.c: Just check that the + appropriate instructions are generated, don't check the count. + +2013-11-22 Richard Earnshaw <rearnsha@arm.com> + + PR target/59216 + * gcc.target/arm/negdi-4.c: Delete invalid test. + * gcc.dg/torture/pr59216.c: New test. + +2013-11-22 Alex Velenko <Alex.Velenko@arm.com> + + * gcc.target/aarch64/vmov_n_1.c: New testcase. + 2013-11-22 Richard Biener <rguenther@suse.de> * gcc.dg/torture/20131122-0.c: New testcase. diff --git a/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-1.c b/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-1.c index 6cf644195d6..fa52e0ca85d 100644 --- a/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-1.c +++ b/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-1.c @@ -6,7 +6,7 @@ /* { dg-do compile } */ /* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */ -static char tab[4] = {0}; +extern char tab[4]; static int test0 () @@ -27,12 +27,14 @@ test0 () return t0 + t1; } -static int -test1 () +__attribute__((noinline, noclone)) static int +test1 (int i) { + char foo[4] = {}; + /*__builtin___asan_report_store1 called 1 time here to instrument the initialization. */ - char foo[4] = {1}; + foo[i] = 1; /*__builtin___asan_report_store1 called 2 times here to instrument the store to the memory region of tab. */ @@ -45,7 +47,7 @@ test1 () /* There are 2 calls to __builtin___asan_report_store1 and 2 calls to __builtin___asan_report_load1 to instrument the store to (subset of) the memory region of tab. */ - __builtin_memcpy (&tab[1], foo, 3); + __builtin_memcpy (&tab[1], foo + i, 3); /* This should not generate a __builtin___asan_report_load1 because the reference to tab[1] has been already instrumented above. */ @@ -58,7 +60,7 @@ test1 () int main () { - return test0 () && test1 (); + return test0 () && test1 (0); } /* { dg-final { scan-tree-dump-times "__builtin___asan_report_store1" 7 "asan0" } } */ diff --git a/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-7.c b/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-7.c index 075e9cfb868..bf40a037679 100644 --- a/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-7.c +++ b/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-7.c @@ -20,4 +20,4 @@ foo (int *a, char *b, char *c) /* { dg-final { scan-tree-dump-times "__builtin___asan_report_load" 6 "asan0" } } */ /* { dg-final { scan-tree-dump-not "__builtin___asan_report_store" "asan0" } } */ -/* { dg-final { cleanup-tree-dump "asan" } } */ +/* { dg-final { cleanup-tree-dump "asan0" } } */ diff --git a/gcc/testsuite/c-c++-common/asan/pr59063-1.c b/gcc/testsuite/c-c++-common/asan/pr59063-1.c new file mode 100644 index 00000000000..a4e01f76f3a --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/pr59063-1.c @@ -0,0 +1,11 @@ +/* { dg-do run } */ + +#include <time.h> +static int weak_gettime (clockid_t clk_id, struct timespec *tp) + __attribute__((__weakref__("clock_gettime"))); +int main() { + if (!clock_gettime) + return 0; + struct timespec ts; + return weak_gettime(CLOCK_MONOTONIC, &ts); +} diff --git a/gcc/testsuite/c-c++-common/asan/pr59063-2.c b/gcc/testsuite/c-c++-common/asan/pr59063-2.c new file mode 100644 index 00000000000..64354ea7831 --- /dev/null +++ b/gcc/testsuite/c-c++-common/asan/pr59063-2.c @@ -0,0 +1,12 @@ +/* { dg-do run } */ +/* { dg-options "-static-libasan" } */ + +#include <time.h> +static int weak_gettime (clockid_t clk_id, struct timespec *tp) + __attribute__((__weakref__("clock_gettime"))); +int main() { + if (!clock_gettime) + return 0; + struct timespec ts; + return weak_gettime(CLOCK_MONOTONIC, &ts); +} diff --git a/gcc/testsuite/c-c++-common/gomp/pr59152.c b/gcc/testsuite/c-c++-common/gomp/pr59152.c new file mode 100644 index 00000000000..bcccb1be349 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/pr59152.c @@ -0,0 +1,40 @@ +/* PR middle-end/59152 */ +/* { dg-do compile } */ +/* { dg-options "-fopenmp -fipa-pure-const" } */ + +extern int b[]; +void +foo (void) +{ + unsigned long v1, v2, v3; + #pragma omp parallel for schedule(static, 32) collapse(3) + for (v1 = 0; v1 < 20; v1 += 2) + for (v2 = __LONG_MAX__; v2 > __LONG_MAX__ - 30; v2 -= 3) + for (v3 = 10; v3 > 0; v3--) + #pragma omp atomic + b[v3]++; +} + +void +bar (void) +{ + unsigned long v1, v2, v3; + #pragma omp parallel for schedule(static) collapse(3) + for (v1 = 0; v1 < 20; v1 += 2) + for (v2 = __LONG_MAX__; v2 > __LONG_MAX__ - 30; v2 -= 3) + for (v3 = 10; v3 > 0; v3--) + #pragma omp atomic + b[v3]++; +} + +void +baz (void) +{ + unsigned long v1, v2, v3; + #pragma omp parallel for schedule(runtime) collapse(3) + for (v1 = 0; v1 < 20; v1 += 2) + for (v2 = __LONG_MAX__; v2 > __LONG_MAX__ - 30; v2 -= 3) + for (v3 = 10; v3 > 0; v3--) + #pragma omp atomic + b[v3]++; +} diff --git a/gcc/testsuite/c-c++-common/pr59032.c b/gcc/testsuite/c-c++-common/pr59032.c new file mode 100644 index 00000000000..327f5aeb6bc --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr59032.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +void +foo() +{ + float v __attribute__((vector_size(8))); + v++; +} + +void +foo2 () +{ + float v __attribute__((vector_size(8))); + ++v; +} + +void +foo3 () +{ + float v __attribute__((vector_size(8))); + v--; +} + +void +foo4 () +{ + float v __attribute__((vector_size(8))); + --v; +} diff --git a/gcc/testsuite/c-c++-common/pr59037.c b/gcc/testsuite/c-c++-common/pr59037.c new file mode 100644 index 00000000000..fae13c2fa94 --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr59037.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-O3" } */ + +typedef int v4si __attribute__ ((vector_size (16))); + +int +main (int argc, char** argv) +{ + v4si x = {0,1,2,3}; + x = (v4si) {(x)[3], (x)[2], (x)[1], (x)[0]}; + return x[4]; +} diff --git a/gcc/testsuite/c-c++-common/pr59280.c b/gcc/testsuite/c-c++-common/pr59280.c new file mode 100644 index 00000000000..779f0fb858f --- /dev/null +++ b/gcc/testsuite/c-c++-common/pr59280.c @@ -0,0 +1,4 @@ +/* PR c/59280 */ +/* { dg-do compile } */ + +void bar (char *) __attribute__((constructor(foo))); /* { dg-error "constructor priorities must be integers|was not declared|constructor priorities are not supported" } */ diff --git a/gcc/testsuite/c-c++-common/ubsan/undefined-1.c b/gcc/testsuite/c-c++-common/ubsan/undefined-1.c new file mode 100644 index 00000000000..1229b711fe9 --- /dev/null +++ b/gcc/testsuite/c-c++-common/ubsan/undefined-1.c @@ -0,0 +1,26 @@ +/* { dg-do run } */ +/* { dg-options "-fsanitize=undefined" } */ +/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */ + +int +foo (int x, int y) +{ + const int z = 2; + if (z & 1) + return x << y; + return 0; +} + +int +bar (int x, int y) +{ + return x + y; +} + +int +main (void) +{ + foo (3, 2); + bar (12, 42); + return 0; +} diff --git a/gcc/testsuite/c-c++-common/ubsan/vla-1.c b/gcc/testsuite/c-c++-common/ubsan/vla-1.c index 6c1d81e9d22..ca538ed8693 100644 --- a/gcc/testsuite/c-c++-common/ubsan/vla-1.c +++ b/gcc/testsuite/c-c++-common/ubsan/vla-1.c @@ -1,33 +1,104 @@ /* { dg-do run } */ -/* { dg-options "-fsanitize=vla-bound -w" } */ +/* { dg-options "-fsanitize=vla-bound -Wall -Wno-unused-variable" } */ -static int +typedef long int V; +int x = -1; +double di = -3.2; +V v = -6; + +static int __attribute__ ((noinline, noclone)) bar (void) { - return -42; + return -4; } -typedef long int V; -int -main (void) +static void __attribute__ ((noinline, noclone)) +fn1 (void) { - int x = -1; - double di = -3.2; - V v = -666; - int a[x]; - int aa[x][x]; - int aaa[x][x][x]; +} + +static void __attribute__ ((noinline, noclone)) +fn2 (void) +{ + int a[x][x]; +} + +static void __attribute__ ((noinline, noclone)) +fn3 (void) +{ + int a[x][x][x]; +} + +static void __attribute__ ((noinline, noclone)) +fn4 (void) +{ int b[x - 4]; +} + +static void __attribute__ ((noinline, noclone)) +fn5 (void) +{ int c[(int) di]; +} + +static void __attribute__ ((noinline, noclone)) +fn6 (void) +{ int d[1 + x]; +} + +static void __attribute__ ((noinline, noclone)) +fn7 (void) +{ int e[1 ? x : -1]; +} + +static void __attribute__ ((noinline, noclone)) +fn8 (void) +{ int f[++x]; +} + +static void __attribute__ ((noinline, noclone)) +fn9 (void) +{ int g[(signed char) --x]; +} + +static void __attribute__ ((noinline, noclone)) +fn10 (void) +{ int h[(++x, --x, x)]; +} + +static void __attribute__ ((noinline, noclone)) +fn11 (void) +{ int i[v]; +} + +static void __attribute__ ((noinline, noclone)) +fn12 (void) +{ int j[bar ()]; +} +int +main (void) +{ + fn1 (); + fn2 (); + fn3 (); + fn4 (); + fn5 (); + fn6 (); + fn7 (); + fn8 (); + fn9 (); + fn10 (); + fn11 (); + fn12 (); return 0; } @@ -44,5 +115,5 @@ main (void) /* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value 0(\n|\r\n|\r)" } */ /* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value -1(\n|\r\n|\r)" } */ /* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value -1(\n|\r\n|\r)" } */ -/* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value -666(\n|\r\n|\r)" } */ -/* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value -42(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value -6(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*variable length array bound evaluates to non-positive value -4(\n|\r\n|\r)" } */ diff --git a/gcc/testsuite/c-c++-common/ubsan/vla-2.c b/gcc/testsuite/c-c++-common/ubsan/vla-2.c index 2fbeb7113b8..c62ced91348 100644 --- a/gcc/testsuite/c-c++-common/ubsan/vla-2.c +++ b/gcc/testsuite/c-c++-common/ubsan/vla-2.c @@ -1,5 +1,5 @@ /* { dg-do run } */ -/* { dg-options "-fsanitize=vla-bound -w" } */ +/* { dg-options "-fsanitize=vla-bound -Wall -Wno-unused-variable" } */ int main (void) diff --git a/gcc/testsuite/c-c++-common/ubsan/vla-3.c b/gcc/testsuite/c-c++-common/ubsan/vla-3.c index 20dd38b79a7..5e10af0b593 100644 --- a/gcc/testsuite/c-c++-common/ubsan/vla-3.c +++ b/gcc/testsuite/c-c++-common/ubsan/vla-3.c @@ -1,5 +1,5 @@ /* { dg-do run } */ -/* { dg-options "-fsanitize=vla-bound -w" } */ +/* { dg-options "-fsanitize=vla-bound" } */ /* Don't instrument the arrays here. */ int diff --git a/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp b/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp index a66ec44f297..707d17ec5e4 100644 --- a/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp +++ b/gcc/testsuite/g++.dg/cilk-plus/cilk-plus.exp @@ -31,7 +31,8 @@ dg-finish set library_var [get_multilibs] # Pointing the ld_library_path to the Cilk Runtime library binaries. -set ld_library_path "${library_var}/libcilkrts/.libs" +append ld_library_path ":${library_var}/libcilkrts/.libs" +set_ld_library_path_env_vars global TEST_EXTRA_LIBS set TEST_EXTRA_LIBS "-L${library_var}/libcilkrts/.libs" diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ice9.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ice9.C new file mode 100644 index 00000000000..50de3720b26 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ice9.C @@ -0,0 +1,7 @@ +// PR c++/58607 +// { dg-do compile { target c++11 } } + +struct A +{ + constexpr A() { i; } // { dg-error "declared|empty body" } +}; diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-57.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-57.C new file mode 100644 index 00000000000..12b4f4c84e5 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-57.C @@ -0,0 +1,9 @@ +// PR c++/59096 +// { dg-do compile { target c++11 } } + +template<typename T> struct A +{ + typedef T B [[mode]]; // { dg-warning "ignored" } +}; + +A<int>::B b; diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist75.C b/gcc/testsuite/g++.dg/cpp0x/initlist75.C new file mode 100644 index 00000000000..f185401c20a --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/initlist75.C @@ -0,0 +1,6 @@ +// PR c++/59080 +// { dg-require-effective-target c++11 } + +#include <initializer_list> + +auto foo[] = {}; // { dg-error "auto|unable to deduce" } diff --git a/gcc/testsuite/g++.dg/cpp1y/pr58533.C b/gcc/testsuite/g++.dg/cpp1y/pr58533.C index e1855d78e08..9bcd7716697 100644 --- a/gcc/testsuite/g++.dg/cpp1y/pr58533.C +++ b/gcc/testsuite/g++.dg/cpp1y/pr58533.C @@ -3,5 +3,5 @@ void foo() { - void (*fp)(auto); // { dg-error "template" } + void (*fp)(auto); // { dg-error "auto|not permitted" } } diff --git a/gcc/testsuite/g++.dg/cpp1y/pr59112.C b/gcc/testsuite/g++.dg/cpp1y/pr59112.C new file mode 100644 index 00000000000..e7326ac3113 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/pr59112.C @@ -0,0 +1,12 @@ +// { dg-do compile } +// { dg-options "-std=gnu++1y" } + +// PR c++/59112 + +void foo() +{ + struct A + { + A(auto) {} // { dg-error "auto|not permitted" } + }; +} diff --git a/gcc/testsuite/g++.dg/cpp1y/pr59113.C b/gcc/testsuite/g++.dg/cpp1y/pr59113.C new file mode 100644 index 00000000000..f909a76bd35 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/pr59113.C @@ -0,0 +1,11 @@ +// { dg-do compile } +// { dg-options "-std=gnu++1y" } + +// PR c++/59113 + +void foo() +{ + void bar(auto) {} // { dg-error "function-definition|auto|not permitted" } +} + +auto i = 0; diff --git a/gcc/testsuite/g++.dg/gomp/declare-simd-1.C b/gcc/testsuite/g++.dg/gomp/declare-simd-1.C index e9be161948e..4b2812fb6e6 100644 --- a/gcc/testsuite/g++.dg/gomp/declare-simd-1.C +++ b/gcc/testsuite/g++.dg/gomp/declare-simd-1.C @@ -239,5 +239,5 @@ struct D void f38 (D &d) { - d.f37 <12> (6); + d.f37 <16> (6); } diff --git a/gcc/testsuite/g++.dg/gomp/openmp-simd-1.C b/gcc/testsuite/g++.dg/gomp/openmp-simd-1.C index fedb186fedf..e8e057a6166 100644 --- a/gcc/testsuite/g++.dg/gomp/openmp-simd-1.C +++ b/gcc/testsuite/g++.dg/gomp/openmp-simd-1.C @@ -44,3 +44,4 @@ void foo(int n, float *a, float *b) /* { dg-final { scan-tree-dump-not "omp teams" "original" } } */ /* { dg-final { scan-tree-dump-not "omp target" "original" } } */ /* { dg-final { scan-tree-dump-not "omp parallel" "original" } } */ +/* { dg-final { cleanup-tree-dump "original" } } */ diff --git a/gcc/testsuite/g++.dg/gomp/openmp-simd-2.C b/gcc/testsuite/g++.dg/gomp/openmp-simd-2.C index e31c1ebecf9..ad9b441f21d 100644 --- a/gcc/testsuite/g++.dg/gomp/openmp-simd-2.C +++ b/gcc/testsuite/g++.dg/gomp/openmp-simd-2.C @@ -42,3 +42,4 @@ void bar(int n, float *a, float *b) /* { dg-final { scan-tree-dump-times "pragma omp simd safelen\\(64\\)" 1 "original" } } */ /* { dg-final { scan-tree-dump-not "omp parallel" "original" } } */ /* { dg-final { scan-tree-dump-not "omp for" "original" } } */ +/* { dg-final { cleanup-tree-dump "original" } } */ diff --git a/gcc/testsuite/g++.dg/gomp/pr58874.C b/gcc/testsuite/g++.dg/gomp/pr58874.C new file mode 100644 index 00000000000..be3f53e4467 --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/pr58874.C @@ -0,0 +1,14 @@ +// PR c++/58874 +// { dg-do compile } +// { dg-options "-fopenmp" } + +struct A +{ + template<int> struct B + { + #pragma omp declare reduction (x : int : omp_out |= omp_in) + }; +}; + +#pragma omp declare reduction (y : long : omp_out |= omp_in) \ + initializer (omp_priv = 0) diff --git a/gcc/testsuite/g++.dg/gomp/pr59150.C b/gcc/testsuite/g++.dg/gomp/pr59150.C new file mode 100644 index 00000000000..103edb64918 --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/pr59150.C @@ -0,0 +1,25 @@ +// PR middle-end/59150 +// { dg-do compile } +// { dg-options "-O -fopenmp-simd -fno-tree-ccp -fno-tree-copy-prop -fno-tree-dce" } + +#pragma omp declare reduction (foo: int: omp_out += omp_in) initializer (omp_priv = 0) + +int +foo () +{ + int i, v, &u = v; + #pragma omp simd reduction (foo:u) + for (i = 0; i < 1024; i++) + u = i; + return u; +} + +int +bar () +{ + int i, v, &u = v; + #pragma omp simd reduction (foo:u) safelen(1) + for (i = 0; i < 1024; i++) + u = i; + return u; +} diff --git a/gcc/testsuite/g++.dg/gomp/pr59297.C b/gcc/testsuite/g++.dg/gomp/pr59297.C new file mode 100644 index 00000000000..330ed2e00b1 --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/pr59297.C @@ -0,0 +1,25 @@ +// PR c++/59297 +// { dg-do compile } +// { dg-options "-fopenmp" } + +template <typename T> +struct A +{ + ~A (); + const T &operator[] (int) const; +}; + +struct B +{ + int &operator () (A <int>); +}; + +void +foo (B &x, int &z) +{ + A<A<int> > y; + #pragma omp atomic + x (y[0]) += 1; + #pragma omp atomic + z += x(y[1]); +} diff --git a/gcc/testsuite/g++.dg/inherit/virtual11.C b/gcc/testsuite/g++.dg/inherit/virtual11.C new file mode 100644 index 00000000000..04c24129343 --- /dev/null +++ b/gcc/testsuite/g++.dg/inherit/virtual11.C @@ -0,0 +1,17 @@ +// PR c++/59031 +// { dg-do compile } +// { dg-options "-fdump-tree-gimple " } +class B { + public: + virtual int add (int a, int b) {return a+ b;} +}; + +class D : public B { +}; + +int foo (int a, int b) { + D d; + return d.add(a, b); +} +// { dg-final { scan-tree-dump-not "OBJ_TYPE_REF" "gimple" } } +// { dg-final { cleanup-tree-dump "gimple" } } diff --git a/gcc/testsuite/g++.dg/ipa/pr59355.C b/gcc/testsuite/g++.dg/ipa/pr59355.C new file mode 100644 index 00000000000..907c6d74501 --- /dev/null +++ b/gcc/testsuite/g++.dg/ipa/pr59355.C @@ -0,0 +1,14 @@ +// PR tree-optimization/59355 +// { dg-do compile } +// { dg-options "-O2 -fno-devirtualize" } + +struct S +{ + virtual void bar (); +}; + +void +foo (S *s) +{ + s->bar (); +} diff --git a/gcc/testsuite/g++.dg/opt/pr58864.C b/gcc/testsuite/g++.dg/opt/pr58864.C new file mode 100644 index 00000000000..b8587f298a0 --- /dev/null +++ b/gcc/testsuite/g++.dg/opt/pr58864.C @@ -0,0 +1,21 @@ +// PR target/58864 +// { dg-do compile } +// { dg-options "-Os" } +// { dg-additional-options "-march=i686" { target { { i?86-*-* x86_64-*-* } && ia32 } } } + +struct A { A (); ~A (); }; +struct B { B (); }; + +float d, e; + +void +foo () +{ + A a; + float c = d; + while (1) + { + B b; + e = c ? -c : 0; + } +} diff --git a/gcc/testsuite/g++.dg/other/cv_func.C b/gcc/testsuite/g++.dg/other/cv_func.C index 941cb8d53d8..2eb9f039a5a 100644 --- a/gcc/testsuite/g++.dg/other/cv_func.C +++ b/gcc/testsuite/g++.dg/other/cv_func.C @@ -3,7 +3,7 @@ typedef int FIC(int) const; typedef int FI(int); -FIC f; // { dg-error "qualified" } +FIC f; // { dg-error "cv-qualifier" } struct S { FIC f; // OK diff --git a/gcc/testsuite/g++.dg/other/cv_func3.C b/gcc/testsuite/g++.dg/other/cv_func3.C new file mode 100644 index 00000000000..0fd47882f2a --- /dev/null +++ b/gcc/testsuite/g++.dg/other/cv_func3.C @@ -0,0 +1,10 @@ +// PR c++/58810 + +typedef int F() const; + +F f; // { dg-error "cv-qualifier" } + +struct A +{ + friend F f; // { dg-error "cv-qualifier" } +}; diff --git a/gcc/testsuite/g++.dg/other/default5.C b/gcc/testsuite/g++.dg/other/default5.C index d5bae344c44..87acb765e6d 100644 --- a/gcc/testsuite/g++.dg/other/default5.C +++ b/gcc/testsuite/g++.dg/other/default5.C @@ -43,5 +43,5 @@ template<int> struct B void F2(int, int, int = 0); }; -template<int N> void B<N>::F1(int, int = 0, int) {} -template<int N> void B<N>::F2(int = 0, int, int) {} // { dg-error "default" } +template<int N> void B<N>::F1(int, int = 0, int) {} // { dg-error "default arguments" } +template<int N> void B<N>::F2(int = 0, int, int) {} // { dg-error "default arguments|parameter 2" } diff --git a/gcc/testsuite/g++.dg/other/default8.C b/gcc/testsuite/g++.dg/other/default8.C new file mode 100644 index 00000000000..255a661356c --- /dev/null +++ b/gcc/testsuite/g++.dg/other/default8.C @@ -0,0 +1,43 @@ +// PR c++54485 + +template<typename T> +class K1 +{ + int fn(int, int); + int gn(int, int); +}; + +template<typename T> +int K1<T>::fn (int a, int b = 3) // { dg-error "default arguments" } +{ + return a - b; +} + +template<typename T> +int K1<T>::gn (int a = 1, int b = 3) // { dg-error "default arguments" } +{ + return a - b; +} + +template<typename T> +class K2 +{ + template<typename U> + int fn(int, int); + template<typename U> + int gn(int, int); +}; + +template<typename T> +template<typename U> +int K2<T>::fn (int a, int b = 3) // { dg-error "default arguments" } +{ + return a - b; +} + +template<typename T> +template<typename U> +int K2<T>::gn (int a = 1, int b = 3) // { dg-error "default arguments" } +{ + return a - b; +} diff --git a/gcc/testsuite/g++.dg/parse/bitfield4.C b/gcc/testsuite/g++.dg/parse/bitfield4.C new file mode 100644 index 00000000000..e10fa5f3342 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/bitfield4.C @@ -0,0 +1,6 @@ +// PR c++/58700 + +struct A +{ + static int : 4; // { dg-error "bit-field" } +}; diff --git a/gcc/testsuite/g++.dg/parse/crash66.C b/gcc/testsuite/g++.dg/parse/crash66.C new file mode 100644 index 00000000000..ceedd2be243 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/crash66.C @@ -0,0 +1,11 @@ +// PR c++/58647 + +struct A +{ + static void foo(); +}; + +template<typename> void bar() +{ + A().foo; +} diff --git a/gcc/testsuite/g++.dg/parse/fn-typedef2.C b/gcc/testsuite/g++.dg/parse/fn-typedef2.C index c9c7f060d01..6bb83024b9f 100644 --- a/gcc/testsuite/g++.dg/parse/fn-typedef2.C +++ b/gcc/testsuite/g++.dg/parse/fn-typedef2.C @@ -4,4 +4,4 @@ typedef void ft() const; typedef void V; typedef V ft() const; -ft f; // { dg-error "qualified" } +ft f; // { dg-error "cv-qualifier" } diff --git a/gcc/testsuite/g++.dg/plugin/selfassign.c b/gcc/testsuite/g++.dg/plugin/selfassign.c index cdab74a19ae..be5a204c901 100644 --- a/gcc/testsuite/g++.dg/plugin/selfassign.c +++ b/gcc/testsuite/g++.dg/plugin/selfassign.c @@ -11,6 +11,17 @@ #include "stringpool.h" #include "toplev.h" #include "basic-block.h" +#include "pointer-set.h" +#include "hash-table.h" +#include "vec.h" +#include "ggc.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "tree.h" diff --git a/gcc/testsuite/g++.dg/tc1/dr217.C b/gcc/testsuite/g++.dg/tc1/dr217.C index cfa2803974d..099359b216a 100644 --- a/gcc/testsuite/g++.dg/tc1/dr217.C +++ b/gcc/testsuite/g++.dg/tc1/dr217.C @@ -10,5 +10,5 @@ struct S }; template <class T> -void S<T>::foo (int = 0) // { dg-error "" "default arguments for parameters of member functions of class templates can be specified in the initial declaration only" { xfail *-*-* } } +void S<T>::foo (int = 0) // { dg-error "" "default arguments for parameters of member functions of class templates can be specified in the initial declaration only" } { } diff --git a/gcc/testsuite/g++.dg/torture/pr59208.C b/gcc/testsuite/g++.dg/torture/pr59208.C new file mode 100644 index 00000000000..3dc110c55e3 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr59208.C @@ -0,0 +1,25 @@ +// { dg-do compile } +class A { +public: + A(); + A(int *); +}; +class B {}; +class C : B { +public: + virtual void m_fn1(); + void operator+=(int) { m_fn1(); } +}; +enum DebuggerType {}; +C a; +DebuggerType b; +void operator==(A &, const A &); +static A get_dbx_doc(A &p1) { p1 == 0; } + +void add_button() { + A c; + switch (b) + case 0: + get_dbx_doc(c); + a += 0; +} diff --git a/gcc/testsuite/g++.dg/ubsan/cxx1y-vla.C b/gcc/testsuite/g++.dg/ubsan/cxx1y-vla.C index 350db3f3473..7023c70cea0 100644 --- a/gcc/testsuite/g++.dg/ubsan/cxx1y-vla.C +++ b/gcc/testsuite/g++.dg/ubsan/cxx1y-vla.C @@ -1,5 +1,5 @@ /* { dg-do run } */ -/* { dg-options "-fsanitize=vla-bound -w -std=c++1y" } */ +/* { dg-options "-fsanitize=vla-bound -Wall -Wno-unused-variable -std=c++1y" } */ /* { dg-shouldfail "ubsan" } */ int diff --git a/gcc/testsuite/g++.dg/ubsan/pr59250.C b/gcc/testsuite/g++.dg/ubsan/pr59250.C new file mode 100644 index 00000000000..48513068826 --- /dev/null +++ b/gcc/testsuite/g++.dg/ubsan/pr59250.C @@ -0,0 +1,19 @@ +// PR sanitizer/59250 +// { dg-do compile } +// { dg-options "-fsanitize=undefined" } +// { dg-skip-if "" { *-*-* } { "-flto" } { "" } } + +struct E { + int i; +}; + +struct S { + const char *s; + S (const char *); + static E *e; +}; + +S::S (const char *) : s (0) +{ + e = new E (); +} diff --git a/gcc/testsuite/g++.dg/ubsan/pr59306.C b/gcc/testsuite/g++.dg/ubsan/pr59306.C new file mode 100644 index 00000000000..426e6a5bd5f --- /dev/null +++ b/gcc/testsuite/g++.dg/ubsan/pr59306.C @@ -0,0 +1,14 @@ +// { dg-do compile } +// { dg-options "-fsanitize=undefined" } +// { dg-skip-if "" { *-*-* } { "-flto" } { "" } } + +class A { + void bar (void (A::*) (int)); + void foo (int); + void B (); +}; + +void A::B() +{ + bar (&A::foo); +} diff --git a/gcc/testsuite/g++.dg/ubsan/pr59331.C b/gcc/testsuite/g++.dg/ubsan/pr59331.C new file mode 100644 index 00000000000..1bb3666efbf --- /dev/null +++ b/gcc/testsuite/g++.dg/ubsan/pr59331.C @@ -0,0 +1,8 @@ +/* { dg-do compile } */ +/* { dg-options "-fsanitize=vla-bound -Wall -Wno-unused-variable" } */ + +void foo(int i) +{ + /* Don't warn here with "value computed is not used". */ + char a[i]; +} diff --git a/gcc/testsuite/g++.dg/ubsan/return-1.C b/gcc/testsuite/g++.dg/ubsan/return-1.C new file mode 100644 index 00000000000..43791b9e33f --- /dev/null +++ b/gcc/testsuite/g++.dg/ubsan/return-1.C @@ -0,0 +1,27 @@ +// { dg-do run } +// { dg-options "-fsanitize=return" } +// { dg-shouldfail "ubsan" } + +struct S { S (); ~S (); }; + +S::S () {} +S::~S () {} + +int +foo (int x) +{ + S a; + { + S b; + if (x) + return 1; + } +} + +int +main () +{ + foo (0); +} + +// { dg-output "execution reached the end of a value-returning function without returning a value" } diff --git a/gcc/testsuite/g++.dg/ubsan/return-2.C b/gcc/testsuite/g++.dg/ubsan/return-2.C new file mode 100644 index 00000000000..c7380f03ed6 --- /dev/null +++ b/gcc/testsuite/g++.dg/ubsan/return-2.C @@ -0,0 +1,25 @@ +// { dg-do run } +// { dg-options "-fsanitize=return" } + +struct S { S (); ~S (); }; + +S::S () {} +S::~S () {} + +int +foo (int x) +{ + S a; + { + S b; + if (x) + return 1; + } +} + +int +main () +{ + foo (1); + foo (14); +} diff --git a/gcc/testsuite/g++.old-deja/g++.mike/p1989.C b/gcc/testsuite/g++.old-deja/g++.mike/p1989.C index 487f609a145..fdede63e406 100644 --- a/gcc/testsuite/g++.old-deja/g++.mike/p1989.C +++ b/gcc/testsuite/g++.old-deja/g++.mike/p1989.C @@ -108,7 +108,7 @@ List_DL<T>::prepend(const T& item) template<class T> void -List_DL<T>::insert(const T& item, Pix x, bool before = TRUE) +List_DL<T>::insert(const T& item, Pix x, bool before = TRUE) // { dg-error "default arguments" } { link<T> *l = (link<T> *) x; diff --git a/gcc/testsuite/gcc.c-torture/compile/pr59322.c b/gcc/testsuite/gcc.c-torture/compile/pr59322.c new file mode 100644 index 00000000000..918d6bdb18e --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr59322.c @@ -0,0 +1,16 @@ + +int a, b, d; +short c; + +int +foo () +{ + for (b = 0; b; b = a) + for (c = 18; c < 10; c++) + { + d = c; + if (d) + return 0; + } + return 0; +} diff --git a/gcc/testsuite/gcc.c-torture/compile/pr59362.c b/gcc/testsuite/gcc.c-torture/compile/pr59362.c new file mode 100644 index 00000000000..3e78f76bc5f --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr59362.c @@ -0,0 +1,21 @@ +/* PR tree-optimization/59362 */ + +char * +foo (char *r, int s) +{ + r = __builtin___stpcpy_chk (r, "abc", __builtin_object_size (r, 1)); + if (s) + r = __builtin___stpcpy_chk (r, "d", __builtin_object_size (r, 1)); + return r; +} + +char *a; +long int b; + +void +bar (void) +{ + b = __builtin_object_size (0, 0); + a = __builtin___stpcpy_chk (0, "", b); + b = __builtin_object_size (a, 0); +} diff --git a/gcc/testsuite/gcc.c-torture/execute/20131127-1.c b/gcc/testsuite/gcc.c-torture/execute/20131127-1.c new file mode 100644 index 00000000000..8ec49657741 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/20131127-1.c @@ -0,0 +1,34 @@ +/* PR middle-end/59138 */ +/* Testcase by John Regehr <regehr@cs.utah.edu> */ + +extern void abort (void); + +#pragma pack(1) + +struct S0 { + int f0; + int f1; + int f2; + short f3; +}; + +short a = 1; + +struct S0 b = { 1 }, c, d, e; + +struct S0 fn1() { return c; } + +void fn2 (void) +{ + b = fn1 (); + a = 0; + d = e; +} + +int main (void) +{ + fn2 (); + if (a != 0) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.c-torture/execute/pr59014-2.c b/gcc/testsuite/gcc.c-torture/execute/pr59014-2.c new file mode 100644 index 00000000000..18da0059eab --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr59014-2.c @@ -0,0 +1,23 @@ +/* PR tree-optimization/59014 */ + +__attribute__((noinline, noclone)) long long int +foo (long long int x, long long int y) +{ + if (((int) x | (int) y) != 0) + return 6; + return x + y; +} + +int +main () +{ + if (sizeof (long long) == sizeof (int)) + return 0; + int shift_half = sizeof (int) * __CHAR_BIT__ / 2; + long long int x = (3LL << shift_half) << shift_half; + long long int y = (5LL << shift_half) << shift_half; + long long int z = foo (x, y); + if (z != ((8LL << shift_half) << shift_half)) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.c-torture/execute/pr59014.c b/gcc/testsuite/gcc.c-torture/execute/pr59014.c new file mode 100644 index 00000000000..10bf81a462f --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr59014.c @@ -0,0 +1,25 @@ +/* PR tree-optimization/59014 */ + +int a = 2, b, c, d; + +int +foo () +{ + for (;; c++) + if ((b > 0) | (a & 1)) + ; + else + { + d = a; + return 0; + } +} + +int +main () +{ + foo (); + if (d != 2) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.c-torture/execute/pr59229.c b/gcc/testsuite/gcc.c-torture/execute/pr59229.c new file mode 100644 index 00000000000..d2a776778de --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr59229.c @@ -0,0 +1,29 @@ +int i; + +__attribute__((noinline, noclone)) void +bar (char *p) +{ + if (i < 1 || i > 6) + __builtin_abort (); + if (__builtin_memcmp (p, "abcdefg", i + 1) != 0) + __builtin_abort (); + __builtin_memset (p, ' ', 7); +} + +__attribute__((noinline, noclone)) void +foo (char *p, unsigned long l) +{ + if (l < 1 || l > 6) + return; + char buf[7]; + __builtin_memcpy (buf, p, l + 1); + bar (buf); +} + +int +main () +{ + for (i = 0; i < 16; i++) + foo ("abcdefghijklmnop", i); + return 0; +} diff --git a/gcc/testsuite/gcc.c-torture/execute/pr59358.c b/gcc/testsuite/gcc.c-torture/execute/pr59358.c new file mode 100644 index 00000000000..674026d6258 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr59358.c @@ -0,0 +1,44 @@ +/* PR tree-optimization/59358 */ + +__attribute__((noinline, noclone)) int +foo (int *x, int y) +{ + int z = *x; + if (y > z && y <= 16) + while (y > z) + z *= 2; + return z; +} + +int +main () +{ + int i; + for (i = 1; i < 17; i++) + { + int j = foo (&i, 16); + int k; + if (i >= 8 && i <= 15) + k = 16 + (i - 8) * 2; + else if (i >= 4 && i <= 7) + k = 16 + (i - 4) * 4; + else if (i == 3) + k = 24; + else + k = 16; + if (j != k) + __builtin_abort (); + j = foo (&i, 7); + if (i >= 7) + k = i; + else if (i >= 4) + k = 8 + (i - 4) * 2; + else if (i == 3) + k = 12; + else + k = 8; + if (j != k) + __builtin_abort (); + } + return 0; +} diff --git a/gcc/testsuite/gcc.dg/20020312-2.c b/gcc/testsuite/gcc.dg/20020312-2.c index 299910047f5..7562a8d65f6 100644 --- a/gcc/testsuite/gcc.dg/20020312-2.c +++ b/gcc/testsuite/gcc.dg/20020312-2.c @@ -52,6 +52,8 @@ extern void abort (void); /* No pic register. */ #elif defined(__moxie__) /* No pic register. */ +#elif defined(__nds32__) +/* No pic register. */ #elif defined(__hppa__) /* PIC register is %r27 or %r19, but is used even without -fpic. */ #elif defined(__pdp11__) diff --git a/gcc/testsuite/gcc.dg/20081223-1.c b/gcc/testsuite/gcc.dg/20081223-1.c index 6bfbd17556f..e5184e044e7 100644 --- a/gcc/testsuite/gcc.dg/20081223-1.c +++ b/gcc/testsuite/gcc.dg/20081223-1.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-flto" { target lto } } */ +/* { dg-options "-flto -ffat-lto-objects" { target lto } } */ typedef struct foo_ foo_t; foo_t bar; /* { dg-error "storage size of 'bar' isn't known" } */ diff --git a/gcc/testsuite/gcc.dg/builtin-apply2.c b/gcc/testsuite/gcc.dg/builtin-apply2.c index 869f337a9a5..3ae2adc6e07 100644 --- a/gcc/testsuite/gcc.dg/builtin-apply2.c +++ b/gcc/testsuite/gcc.dg/builtin-apply2.c @@ -1,5 +1,5 @@ /* { dg-do run } */ -/* { dg-skip-if "Variadic funcs have all args on stack. Normal funcs have args in registers." { "aarch64*-*-* avr-*-* " } { "*" } { "" } } */ +/* { dg-skip-if "Variadic funcs have all args on stack. Normal funcs have args in registers." { "aarch64*-*-* avr-*-* nds32*-*-*" } { "*" } { "" } } */ /* { dg-skip-if "Variadic funcs use Base AAPCS. Normal funcs use VFP variant." { arm*-*-* && arm_hf_eabi } { "*" } { "" } } */ /* PR target/12503 */ diff --git a/gcc/testsuite/gcc.dg/c90-array-lval-8.c b/gcc/testsuite/gcc.dg/c90-array-lval-8.c new file mode 100644 index 00000000000..bc5b7b21b8a --- /dev/null +++ b/gcc/testsuite/gcc.dg/c90-array-lval-8.c @@ -0,0 +1,20 @@ +/* Test for non-lvalue arrays: test that they cannot be assigned to + array variables. PR 58235. */ +/* { dg-do compile } */ +/* { dg-options "-std=iso9899:1990 -pedantic-errors" } */ + +struct s { char c[1]; } x; +struct s f (void) { return x; } + +void +g (void) +{ + char c[1]; + c = f ().c; /* { dg-error "array" } */ +} + +void +h (void) +{ + char c[1] = f ().c; /* { dg-error "array" } */ +} diff --git a/gcc/testsuite/gcc.dg/c90-const-expr-8.c b/gcc/testsuite/gcc.dg/c90-const-expr-8.c index 4923bc68046..b6aba7b1d87 100644 --- a/gcc/testsuite/gcc.dg/c90-const-expr-8.c +++ b/gcc/testsuite/gcc.dg/c90-const-expr-8.c @@ -23,5 +23,6 @@ enum e { /* { dg-error "3:overflow in constant expression" "constant" { target *-*-* } 22 } */ E6 = 0 * !-INT_MIN, /* { dg-warning "13:integer overflow in expression" } */ /* { dg-error "8:not an integer constant" "constant" { target *-*-* } 24 } */ - E7 = INT_MIN % -1 /* Not an overflow. */ + E7 = INT_MIN % -1 /* { dg-warning "16:integer overflow in expression" } */ + /* { dg-error "1:overflow in constant expression" "constant" { target *-*-* } 28 } */ }; diff --git a/gcc/testsuite/gcc.dg/c99-const-expr-8.c b/gcc/testsuite/gcc.dg/c99-const-expr-8.c index e84fa7b4db0..1ddd9ed91ce 100644 --- a/gcc/testsuite/gcc.dg/c99-const-expr-8.c +++ b/gcc/testsuite/gcc.dg/c99-const-expr-8.c @@ -23,5 +23,6 @@ enum e { /* { dg-error "overflow in constant expression" "constant" { target *-*-* } 22 } */ E6 = 0 * !-INT_MIN, /* { dg-warning "integer overflow in expression" } */ /* { dg-error "not an integer constant" "constant" { target *-*-* } 24 } */ - E7 = INT_MIN % -1 /* Not an overflow. */ + E7 = INT_MIN % -1 /* { dg-warning "16:integer overflow in expression" } */ + /* { dg-error "1:overflow in constant expression" "constant" { target *-*-* } 28 } */ }; diff --git a/gcc/testsuite/gcc.dg/c99-init-5.c b/gcc/testsuite/gcc.dg/c99-init-5.c new file mode 100644 index 00000000000..17bacd90c6a --- /dev/null +++ b/gcc/testsuite/gcc.dg/c99-init-5.c @@ -0,0 +1,9 @@ +/* Test for designated initializers: string constants used with + designator in character array should not initialize the array as a + whole. */ +/* { dg-do compile } */ +/* { dg-options "-std=iso9899:1999 -pedantic-errors" } */ + +char g[] = { [7] = "abcd" }; /* { dg-error "initial" } */ +char h[10][10] = { [1][1] = "abcd" }; /* { dg-error "initial" } */ +char i[10][10] = { [1] = "abcd" }; diff --git a/gcc/testsuite/gcc.dg/c99-init-6.c b/gcc/testsuite/gcc.dg/c99-init-6.c new file mode 100644 index 00000000000..6328f82676f --- /dev/null +++ b/gcc/testsuite/gcc.dg/c99-init-6.c @@ -0,0 +1,6 @@ +/* Test for designated initializers: invalid uses of string constants + should not ICE. PR 42262. */ +/* { dg-do compile } */ +/* { dg-options "-std=iso9899:1999 -pedantic-errors" } */ + +int a[] = { [0 ... 1] = "", [0] = "" }; /* { dg-error "initial" } */ diff --git a/gcc/testsuite/gcc.dg/cilk-plus/cilk-plus.exp b/gcc/testsuite/gcc.dg/cilk-plus/cilk-plus.exp index dc66fcb4c0c..39abbba3fbc 100644 --- a/gcc/testsuite/gcc.dg/cilk-plus/cilk-plus.exp +++ b/gcc/testsuite/gcc.dg/cilk-plus/cilk-plus.exp @@ -26,7 +26,8 @@ if { ![check_effective_target_cilkplus] } { set library_var [get_multilibs] # Pointing the ld_library_path to the Cilk Runtime library binaries. -set ld_library_path "${library_var}/libcilkrts/.libs" +append ld_library_path ":${library_var}/libcilkrts/.libs" +set_ld_library_path_env_vars global TEST_EXTRA_LIBS set TEST_EXTRA_LIBS "-L${library_var}/libcilkrts/.libs" diff --git a/gcc/testsuite/gcc.dg/float-exact-1.c b/gcc/testsuite/gcc.dg/float-exact-1.c index 7e8f3f153ae..d22e70b354b 100644 --- a/gcc/testsuite/gcc.dg/float-exact-1.c +++ b/gcc/testsuite/gcc.dg/float-exact-1.c @@ -2,6 +2,7 @@ floating-point contents expressed in decimal. PR 21718. */ /* { dg-do run } */ /* { dg-options "-w" } */ +/* { dg-add-options ieee } */ /* For float (if IEEE binary32), double (if IEEE binary64) and long double (if IEEE binary64, x86 extended or IEEE binary128) we test @@ -2292,7 +2293,7 @@ static const long double ld1c = 182358152808745703724362178773168996492870519432472065091133\ 11767578125001e-4966L; /* 0x1.8p-16494 */ -static const long double ld2ae = 0x1p-16494L, ld2be = 0x2p-16494L, ld1ce = 0x2p-16494L; +static const long double ld2ae = 0x1p-16494L, ld2be = 0x2p-16494L, ld2ce = 0x2p-16494L; static const long double ld2a = 9.7127626791570376663866584373414698287493540070520215145348\ 265837955593101861790565265072369149749103838172122152721795\ diff --git a/gcc/testsuite/gcc.dg/gomp/openmp-simd-1.c b/gcc/testsuite/gcc.dg/gomp/openmp-simd-1.c index fedb186fedf..e8e057a6166 100644 --- a/gcc/testsuite/gcc.dg/gomp/openmp-simd-1.c +++ b/gcc/testsuite/gcc.dg/gomp/openmp-simd-1.c @@ -44,3 +44,4 @@ void foo(int n, float *a, float *b) /* { dg-final { scan-tree-dump-not "omp teams" "original" } } */ /* { dg-final { scan-tree-dump-not "omp target" "original" } } */ /* { dg-final { scan-tree-dump-not "omp parallel" "original" } } */ +/* { dg-final { cleanup-tree-dump "original" } } */ diff --git a/gcc/testsuite/gcc.dg/gomp/openmp-simd-2.c b/gcc/testsuite/gcc.dg/gomp/openmp-simd-2.c index e66806845b7..94afced248f 100644 --- a/gcc/testsuite/gcc.dg/gomp/openmp-simd-2.c +++ b/gcc/testsuite/gcc.dg/gomp/openmp-simd-2.c @@ -40,3 +40,4 @@ void bar(int n, float *a, float *b) /* { dg-final { scan-tree-dump-times "pragma omp simd safelen\\(64\\)" 1 "original" } } */ /* { dg-final { scan-tree-dump-not "omp parallel" "original" } } */ /* { dg-final { scan-tree-dump-not "omp for" "original" } } */ +/* { dg-final { cleanup-tree-dump "original" } } */ diff --git a/gcc/testsuite/gcc.dg/gomp/simd-clones-1.c b/gcc/testsuite/gcc.dg/gomp/simd-clones-1.c new file mode 100644 index 00000000000..486b67a637a --- /dev/null +++ b/gcc/testsuite/gcc.dg/gomp/simd-clones-1.c @@ -0,0 +1,33 @@ +/* { dg-do compile } */ +/* { dg-options "-fopenmp -fdump-tree-optimized -O3" } */ + +/* Test that functions that have SIMD clone counterparts are not + cloned by IPA-cp. For example, special_add() below has SIMD clones + created for it. However, if IPA-cp later decides to clone a + specialization of special_add(x, 666) when analyzing fillit(), we + will forever keep the vectorizer from using the SIMD versions of + special_add in a loop. + + If IPA-CP gets taught how to adjust the SIMD clones as well, this + test could be removed. */ + +#pragma omp declare simd simdlen(4) +static int __attribute__ ((noinline)) +special_add (int x, int y) +{ + if (y == 666) + return x + y + 123; + else + return x + y; +} + +void fillit(int *tot) +{ + int i; + + for (i=0; i < 10000; ++i) + tot[i] = special_add (i, 666); +} + +/* { dg-final { scan-tree-dump-not "special_add.constprop" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/gomp/simd-clones-2.c b/gcc/testsuite/gcc.dg/gomp/simd-clones-2.c new file mode 100644 index 00000000000..030ae6cb19b --- /dev/null +++ b/gcc/testsuite/gcc.dg/gomp/simd-clones-2.c @@ -0,0 +1,26 @@ +/* { dg-options "-fopenmp -fdump-tree-optimized -O" } */ + +#pragma omp declare simd inbranch uniform(c) linear(b:66) +#pragma omp declare simd notinbranch aligned(c:32) +int addit(int a, int b, int *c) +{ + return a + b; +} + +#pragma omp declare simd uniform(a) aligned(a:32) linear(k:1) notinbranch +float setArray(float *a, float x, int k) +{ + a[k] = a[k] + x; + return a[k]; +} + +/* { dg-final { scan-tree-dump "_ZGVbN4ua32vl_setArray" "optimized" { target i?86-*-* x86_64-*-* } } } */ +/* { dg-final { scan-tree-dump "_ZGVbN4vvva32_addit" "optimized" { target i?86-*-* x86_64-*-* } } } */ +/* { dg-final { scan-tree-dump "_ZGVbM4vl66u_addit" "optimized" { target i?86-*-* x86_64-*-* } } } */ +/* { dg-final { scan-tree-dump "_ZGVcN8ua32vl_setArray" "optimized" { target i?86-*-* x86_64-*-* } } } */ +/* { dg-final { scan-tree-dump "_ZGVcN4vvva32_addit" "optimized" { target i?86-*-* x86_64-*-* } } } */ +/* { dg-final { scan-tree-dump "_ZGVcM4vl66u_addit" "optimized" { target i?86-*-* x86_64-*-* } } } */ +/* { dg-final { scan-tree-dump "_ZGVdN8ua32vl_setArray" "optimized" { target i?86-*-* x86_64-*-* } } } */ +/* { dg-final { scan-tree-dump "_ZGVdN8vvva32_addit" "optimized" { target i?86-*-* x86_64-*-* } } } */ +/* { dg-final { scan-tree-dump "_ZGVdM8vl66u_addit" "optimized" { target i?86-*-* x86_64-*-* } } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/gomp/simd-clones-3.c b/gcc/testsuite/gcc.dg/gomp/simd-clones-3.c new file mode 100644 index 00000000000..98e767c3ae3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/gomp/simd-clones-3.c @@ -0,0 +1,18 @@ +/* { dg-options "-fopenmp -fdump-tree-optimized -O2" } */ + +/* Test that if there is no *inbranch clauses, that both the masked and + the unmasked version are created. */ + +#pragma omp declare simd +int addit(int a, int b, int c) +{ + return a + b; +} + +/* { dg-final { scan-tree-dump "_ZGVbN4vvv_addit" "optimized" { target i?86-*-* x86_64-*-* } } } */ +/* { dg-final { scan-tree-dump "_ZGVbM4vvv_addit" "optimized" { target i?86-*-* x86_64-*-* } } } */ +/* { dg-final { scan-tree-dump "_ZGVcN4vvv_addit" "optimized" { target i?86-*-* x86_64-*-* } } } */ +/* { dg-final { scan-tree-dump "_ZGVcM4vvv_addit" "optimized" { target i?86-*-* x86_64-*-* } } } */ +/* { dg-final { scan-tree-dump "_ZGVdN8vvv_addit" "optimized" { target i?86-*-* x86_64-*-* } } } */ +/* { dg-final { scan-tree-dump "_ZGVdM8vvv_addit" "optimized" { target i?86-*-* x86_64-*-* } } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/gomp/simd-clones-4.c b/gcc/testsuite/gcc.dg/gomp/simd-clones-4.c new file mode 100644 index 00000000000..893f44e690f --- /dev/null +++ b/gcc/testsuite/gcc.dg/gomp/simd-clones-4.c @@ -0,0 +1,11 @@ +/* { dg-do compile { target i?86-*-* x86_64-*-* } } */ +/* { dg-options "-fopenmp" } */ + +#pragma omp declare simd simdlen(4) notinbranch +int f2 (int a, int b) +{ + if (a > 5) + return a + b; + else + return a - b; +} diff --git a/gcc/testsuite/gcc.dg/gomp/simd-clones-5.c b/gcc/testsuite/gcc.dg/gomp/simd-clones-5.c new file mode 100644 index 00000000000..801c24f34af --- /dev/null +++ b/gcc/testsuite/gcc.dg/gomp/simd-clones-5.c @@ -0,0 +1,12 @@ +/* { dg-do compile { target i?86-*-* x86_64-*-* } } */ +/* { dg-options "-fopenmp -w" } */ + +/* ?? The -w above is to inhibit the following warning for now: + a.c:2:6: warning: AVX vector argument without AVX enabled changes + the ABI [enabled by default]. */ + +#pragma omp declare simd notinbranch simdlen(4) +void foo (int *a) +{ + *a = 555; +} diff --git a/gcc/testsuite/gcc.dg/gomp/simd-clones-6.c b/gcc/testsuite/gcc.dg/gomp/simd-clones-6.c new file mode 100644 index 00000000000..8818594bfac --- /dev/null +++ b/gcc/testsuite/gcc.dg/gomp/simd-clones-6.c @@ -0,0 +1,11 @@ +/* { dg-do compile { target i?86-*-* x86_64-*-* } } */ +/* { dg-options "-fopenmp" } */ + +/* Test that array subscripts are properly adjusted. */ + +int array[1000]; +#pragma omp declare simd notinbranch simdlen(4) +void foo (int i) +{ + array[i] = 555; +} diff --git a/gcc/testsuite/gcc.dg/gomp/simd-clones-7.c b/gcc/testsuite/gcc.dg/gomp/simd-clones-7.c new file mode 100644 index 00000000000..ef6fa113c1a --- /dev/null +++ b/gcc/testsuite/gcc.dg/gomp/simd-clones-7.c @@ -0,0 +1,16 @@ +/* { dg-do compile { target i?86-*-* x86_64-*-* } } */ +/* { dg-options "-fopenmp -w" } */ + +int array[1000]; + +#pragma omp declare simd notinbranch simdlen(4) +void foo (int *a, int b) +{ + a[b] = 555; +} + +#pragma omp declare simd notinbranch simdlen(4) +void bar (int *a) +{ + *a = 555; +} diff --git a/gcc/testsuite/gcc.dg/guality/param-3.c b/gcc/testsuite/gcc.dg/guality/param-3.c new file mode 100644 index 00000000000..a3b5adb5a0b --- /dev/null +++ b/gcc/testsuite/gcc.dg/guality/param-3.c @@ -0,0 +1,33 @@ +/* { dg-do run } */ +/* { dg-options "-g" } */ +/* { dg-skip-if "" { *-*-* } { "*" } { "-O0" "-O1" } } */ + +typedef __UINTPTR_TYPE__ uintptr_t; + +__attribute__((noinline, noclone)) int +sub (int a, int b) +{ + return a - b; +} + +typedef struct { uintptr_t pa; uintptr_t pb; } fatp_t + __attribute__ ((aligned (2 * __alignof__ (uintptr_t)))); + +__attribute__((noinline, noclone)) void +foo (fatp_t str, int a, int b) +{ + int i = sub (a, b); + if (i == 0) /* BREAK */ + foo (str, a - 1, b); +} + +int +main (void) +{ + fatp_t ptr = { 31415927, 27182818 }; + foo (ptr, 1, 2); + return 0; +} + +/* { dg-final { gdb-test 20 "str.pa" "31415927" } } */ +/* { dg-final { gdb-test 20 "str.pb" "27182818" } } */ diff --git a/gcc/testsuite/gcc.dg/inline-35.c b/gcc/testsuite/gcc.dg/inline-35.c new file mode 100644 index 00000000000..ebbb8df2fe1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/inline-35.c @@ -0,0 +1,19 @@ +/* A function definition of an inline function following a static + declaration does not make an inline definition in C99/C11 terms. + PR 57574. */ +/* { dg-do compile } */ +/* { dg-options "-std=c99 -pedantic-errors" } */ + +static int n; + +static inline int f1 (void); +inline int f1 (void) { return n; } + +static int f2 (void); +inline int f2 (void) { return n; } + +static inline int f3 (void); +int f3 (void) { return n; } + +static int f4 (void); +int f4 (void) { return n; } diff --git a/gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-1.c b/gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-1.c index 4fc00b292dc..54d3e761573 100644 --- a/gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-1.c +++ b/gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-1.c @@ -1,18 +1,18 @@ -/* { dg-do compile { target { x86_64-*-* && lp64 } } } */ +/* { dg-do compile { target { { x86_64-*-* && lp64 } || { powerpc*-*-* && lp64 } } } } */ /* { dg-options "-O3 -fdump-rtl-ira -fdump-rtl-pro_and_epilogue" } */ -int __attribute__((noinline, noclone)) -foo (int a) +long __attribute__((noinline, noclone)) +foo (long a) { return a + 5; } -static int g; +static long g; -int __attribute__((noinline, noclone)) -bar (int a) +long __attribute__((noinline, noclone)) +bar (long a) { - int r; + long r; if (a) { diff --git a/gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-2.c b/gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-2.c index bb725e1651c..ed08494cfa0 100644 --- a/gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-2.c +++ b/gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-2.c @@ -1,18 +1,18 @@ -/* { dg-do compile { target { x86_64-*-* && lp64 } } } */ +/* { dg-do compile { target { { x86_64-*-* && lp64 } || { powerpc*-*-* && lp64 } } } } */ /* { dg-options "-O3 -fdump-rtl-ira -fdump-rtl-pro_and_epilogue" } */ -int __attribute__((noinline, noclone)) -foo (int a) +long __attribute__((noinline, noclone)) +foo (long a) { return a + 5; } -static int g; +static long g; -int __attribute__((noinline, noclone)) -bar (int a) +long __attribute__((noinline, noclone)) +bar (long a) { - int r; + long r; if (a) { diff --git a/gcc/testsuite/gcc.dg/lto/pr59323-2_0.c b/gcc/testsuite/gcc.dg/lto/pr59323-2_0.c new file mode 100644 index 00000000000..938a89d6a28 --- /dev/null +++ b/gcc/testsuite/gcc.dg/lto/pr59323-2_0.c @@ -0,0 +1,37 @@ +/* { dg-lto-do link } */ +/* { dg-lto-options { { -O2 -g -flto } } } */ +/* { dg-extra-ld-options { -r -nostdlib } } */ + +extern void bar(void); + +int main(int argc, char **argv) +{ + int i; + + if (argc == 1) { + extern void bar (); + + bar(); + + { + extern void bar (); + + asm goto ("" : : : : lab); +lab: + ; + } + } + + { + extern void bar (); + + int foo(void) + { + return argv[0][0]; + } + + i = foo(); + } + + return i; +} diff --git a/gcc/testsuite/gcc.dg/lto/pr59323_0.c b/gcc/testsuite/gcc.dg/lto/pr59323_0.c new file mode 100644 index 00000000000..b5910589158 --- /dev/null +++ b/gcc/testsuite/gcc.dg/lto/pr59323_0.c @@ -0,0 +1,37 @@ +/* { dg-lto-do link } */ +/* { dg-lto-options { { -O2 -g -flto } } } */ +/* { dg-extra-ld-options { -r -nostdlib } } */ + +extern void bar(void); + +int main(int argc, char **argv) +{ + int i; + + if (argc == 1) { + enum { X }; + + bar(); + + { + enum { X }; + + asm goto ("" : : : : lab); +lab: + ; + } + } + + { + enum { X }; + + int foo(void) + { + return argv[0][0]; + } + + i = foo(); + } + + return i; +} diff --git a/gcc/testsuite/gcc.dg/macro-fusion-1.c b/gcc/testsuite/gcc.dg/macro-fusion-1.c new file mode 100644 index 00000000000..4ac98668bdc --- /dev/null +++ b/gcc/testsuite/gcc.dg/macro-fusion-1.c @@ -0,0 +1,13 @@ +/* { dg-do compile { target i?86-*-* x86_64-*-* } } */ +/* { dg-options "-O2 -mtune=corei7 -fdump-rtl-sched2" } */ +/* { dg-final { scan-rtl-dump-not "compare.*insn.*jump_insn.*jump_insn" "sched2" } } */ + +int a[100]; + +double bar (double sum) +{ + int i; + for (i = 0; i < 1000000; i++) + sum += (0.5 + (a[i%100] - 128)); + return sum; +} diff --git a/gcc/testsuite/gcc.dg/macro-fusion-2.c b/gcc/testsuite/gcc.dg/macro-fusion-2.c new file mode 100644 index 00000000000..638350d9926 --- /dev/null +++ b/gcc/testsuite/gcc.dg/macro-fusion-2.c @@ -0,0 +1,16 @@ +/* { dg-do compile { target i?86-*-* x86_64-*-* } } */ +/* { dg-options "-O2 -mtune=corei7-avx -fdump-rtl-sched2" } */ +/* { dg-final { scan-rtl-dump-not "compare.*insn.*jump_insn.*jump_insn" "sched2" } } */ + +int a[100]; + +double bar (double sum) +{ + int i = 100000; + while (i != 0) + { + sum += (0.5 + (a[i%100] - 128)); + i--; + } + return sum; +} diff --git a/gcc/testsuite/gcc.dg/plugin/finish_unit_plugin.c b/gcc/testsuite/gcc.dg/plugin/finish_unit_plugin.c index 72d724063e4..c04d96d8232 100644 --- a/gcc/testsuite/gcc.dg/plugin/finish_unit_plugin.c +++ b/gcc/testsuite/gcc.dg/plugin/finish_unit_plugin.c @@ -9,6 +9,17 @@ #include "tree.h" #include "toplev.h" #include "basic-block.h" +#include "pointer-set.h" +#include "hash-table.h" +#include "vec.h" +#include "ggc.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "tree.h" #include "tree-pass.h" diff --git a/gcc/testsuite/gcc.dg/plugin/ggcplug.c b/gcc/testsuite/gcc.dg/plugin/ggcplug.c index eb61ece4522..d441528e9de 100644 --- a/gcc/testsuite/gcc.dg/plugin/ggcplug.c +++ b/gcc/testsuite/gcc.dg/plugin/ggcplug.c @@ -8,6 +8,17 @@ #include "tree.h" #include "toplev.h" #include "basic-block.h" +#include "pointer-set.h" +#include "hash-table.h" +#include "vec.h" +#include "ggc.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "tree.h" #include "tree-pass.h" diff --git a/gcc/testsuite/gcc.dg/plugin/one_time_plugin.c b/gcc/testsuite/gcc.dg/plugin/one_time_plugin.c index 1e601a63c90..f80719a4ff0 100644 --- a/gcc/testsuite/gcc.dg/plugin/one_time_plugin.c +++ b/gcc/testsuite/gcc.dg/plugin/one_time_plugin.c @@ -6,6 +6,17 @@ #include "tree.h" #include "tm.h" #include "toplev.h" +#include "pointer-set.h" +#include "hash-table.h" +#include "vec.h" +#include "ggc.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "tree-pass.h" #include "intl.h" diff --git a/gcc/testsuite/gcc.dg/plugin/selfassign.c b/gcc/testsuite/gcc.dg/plugin/selfassign.c index cdab74a19ae..be5a204c901 100644 --- a/gcc/testsuite/gcc.dg/plugin/selfassign.c +++ b/gcc/testsuite/gcc.dg/plugin/selfassign.c @@ -11,6 +11,17 @@ #include "stringpool.h" #include "toplev.h" #include "basic-block.h" +#include "pointer-set.h" +#include "hash-table.h" +#include "vec.h" +#include "ggc.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "tree.h" diff --git a/gcc/testsuite/gcc.dg/plugin/start_unit_plugin.c b/gcc/testsuite/gcc.dg/plugin/start_unit_plugin.c index 39f44626a55..e83476b63fd 100644 --- a/gcc/testsuite/gcc.dg/plugin/start_unit_plugin.c +++ b/gcc/testsuite/gcc.dg/plugin/start_unit_plugin.c @@ -14,6 +14,17 @@ #include "stringpool.h" #include "toplev.h" #include "basic-block.h" +#include "pointer-set.h" +#include "hash-table.h" +#include "vec.h" +#include "ggc.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "tree.h" #include "tree-pass.h" diff --git a/gcc/testsuite/gcc.dg/pr10474.c b/gcc/testsuite/gcc.dg/pr10474.c index 08324d83a1d..77ccc4606ed 100644 --- a/gcc/testsuite/gcc.dg/pr10474.c +++ b/gcc/testsuite/gcc.dg/pr10474.c @@ -1,4 +1,4 @@ -/* { dg-do compile { target { x86_64-*-* && lp64 } } } */ +/* { dg-do compile { target { { x86_64-*-* && lp64 } || { powerpc*-*-* && lp64 } } } } */ /* { dg-options "-O3 -fdump-rtl-pro_and_epilogue" } */ void f(int *i) diff --git a/gcc/testsuite/gcc.dg/pr56997-4.c b/gcc/testsuite/gcc.dg/pr56997-4.c new file mode 100644 index 00000000000..38f6248d2ed --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr56997-4.c @@ -0,0 +1,23 @@ +/* Test volatile access to unaligned field. */ +/* { dg-do compile } */ +/* { dg-options "-fno-strict-volatile-bitfields -fdump-rtl-final" } */ + +#define test_type unsigned short + +typedef struct s{ + unsigned char Prefix[1]; + volatile test_type Type; +}__attribute((__packed__,__aligned__(4))) ss; + +extern volatile ss v; + +void +foo (test_type u) +{ + v.Type = u; +} + +/* The C++ memory model forbids data store race conditions outside the + unaligned data member, therefore only QI or HI access is allowed, no SI. */ +/* { dg-final { scan-rtl-dump-not "mem/v(/.)*:SI" "final" } } */ +/* { dg-final { cleanup-rtl-dump "final" } } */ diff --git a/gcc/testsuite/gcc.dg/pr57518.c b/gcc/testsuite/gcc.dg/pr57518.c index 8eb714d8c55..94ef82db8e3 100644 --- a/gcc/testsuite/gcc.dg/pr57518.c +++ b/gcc/testsuite/gcc.dg/pr57518.c @@ -2,7 +2,6 @@ /* { dg-do compile } */ /* { dg-options "-O2 -fdump-rtl-ira" } */ -/* { dg-final { scan-rtl-dump-not "REG_EQUIV\[^\n\]*mem\[^\n\]*\"ip\".*subreg" "ira" } } */ char ip[10]; int total; @@ -13,3 +12,6 @@ void foo() { t = ip[2]; total = t & 0x3; } + +/* { dg-final { scan-rtl-dump-not "REG_EQUIV\[^\n\]*mem\[^\n\]*\"ip\".*subreg" "ira" } } */ +/* { dg-final { cleanup-rtl-dump "ira" } } */ diff --git a/gcc/testsuite/gcc.dg/pr59011.c b/gcc/testsuite/gcc.dg/pr59011.c new file mode 100644 index 00000000000..2fb8187ad55 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr59011.c @@ -0,0 +1,22 @@ +/* PR middle-end/59011 */ +/* { dg-do compile } */ +/* { dg-options "-std=gnu99" } */ + +void +foo (int m) +{ + int a[m]; + void + bar (void) + { + { + int + baz (void) + { + return a[0]; + } + } + a[0] = 42; + } + bar (); +} diff --git a/gcc/testsuite/gcc.dg/pr59020.c b/gcc/testsuite/gcc.dg/pr59020.c new file mode 100644 index 00000000000..696c9df9ac1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr59020.c @@ -0,0 +1,15 @@ +/* PR rtl-optimization/59020 */ + +/* { dg-do compile { target i?86-*-* x86_64-*-* } } */ +/* { dg-options "-O2 -fmodulo-sched -fno-inline -march=corei7" } */ + +int a, b, d; +unsigned c; + +void f() +{ + unsigned q; + for(; a; a++) + if(((c %= d && 1) ? : 1) & 1) + for(; b; q++); +} diff --git a/gcc/testsuite/gcc.dg/pr59351.c b/gcc/testsuite/gcc.dg/pr59351.c new file mode 100644 index 00000000000..384058f4041 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr59351.c @@ -0,0 +1,8 @@ +/* { dg-do compile } */ +/* { dg-options "-std=c99 -Wpedantic" } */ + +unsigned int +foo (void) +{ + return sizeof ((int[]) {}); /* { dg-warning "ISO C forbids empty initializer braces" } */ +} diff --git a/gcc/testsuite/gcc.dg/sibcall-3.c b/gcc/testsuite/gcc.dg/sibcall-3.c index c4460e2e522..e02a410e6d9 100644 --- a/gcc/testsuite/gcc.dg/sibcall-3.c +++ b/gcc/testsuite/gcc.dg/sibcall-3.c @@ -5,7 +5,7 @@ Copyright (C) 2002 Free Software Foundation Inc. Contributed by Hans-Peter Nilsson <hp@bitrange.com> */ -/* { dg-do run { xfail { { cris-*-* crisv32-*-* h8300-*-* hppa*64*-*-* m32r-*-* mcore-*-* mn10300-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa*-*-* } || { arm*-*-* && { ! arm32 } } } } } */ +/* { dg-do run { xfail { { cris-*-* crisv32-*-* h8300-*-* hppa*64*-*-* m32r-*-* mcore-*-* mn10300-*-* nds32*-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa*-*-* } || { arm*-*-* && { ! arm32 } } } } } */ /* -mlongcall disables sibcall patterns. */ /* { dg-skip-if "" { powerpc*-*-* } { "-mlongcall" } { "" } } */ /* { dg-options "-O2 -foptimize-sibling-calls" } */ diff --git a/gcc/testsuite/gcc.dg/sibcall-4.c b/gcc/testsuite/gcc.dg/sibcall-4.c index 4f468f6595e..a66ed079862 100644 --- a/gcc/testsuite/gcc.dg/sibcall-4.c +++ b/gcc/testsuite/gcc.dg/sibcall-4.c @@ -5,7 +5,7 @@ Copyright (C) 2002 Free Software Foundation Inc. Contributed by Hans-Peter Nilsson <hp@bitrange.com> */ -/* { dg-do run { xfail { { cris-*-* crisv32-*-* h8300-*-* hppa*64*-*-* m32r-*-* mcore-*-* mn10300-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa*-*-* } || { arm*-*-* && { ! arm32 } } } } } */ +/* { dg-do run { xfail { { cris-*-* crisv32-*-* h8300-*-* hppa*64*-*-* m32r-*-* mcore-*-* mn10300-*-* nds32*-*-* xstormy16-*-* v850*-*-* vax-*-* xtensa*-*-* } || { arm*-*-* && { ! arm32 } } } } } */ /* -mlongcall disables sibcall patterns. */ /* { dg-skip-if "" { powerpc*-*-* } { "-mlongcall" } { "" } } */ /* { dg-options "-O2 -foptimize-sibling-calls" } */ diff --git a/gcc/testsuite/gcc.dg/stack-usage-1.c b/gcc/testsuite/gcc.dg/stack-usage-1.c index 78807bacd30..7956efc4089 100644 --- a/gcc/testsuite/gcc.dg/stack-usage-1.c +++ b/gcc/testsuite/gcc.dg/stack-usage-1.c @@ -38,6 +38,9 @@ # else # define SIZE 248 # endif +#elif defined (__nds32__) +# define SIZE 248 /* 256 - 8 bytes, only $fp and padding bytes are saved in + the register save area under O0 optimization level. */ #elif defined (__powerpc64__) || defined (__ppc64__) || defined (__POWERPC64__) \ || defined (__PPC64__) # if _CALL_ELF == 2 diff --git a/gcc/testsuite/gcc.dg/torture/pr37868.c b/gcc/testsuite/gcc.dg/torture/pr37868.c index cc9c24f49bb..5204c5a5941 100644 --- a/gcc/testsuite/gcc.dg/torture/pr37868.c +++ b/gcc/testsuite/gcc.dg/torture/pr37868.c @@ -1,6 +1,6 @@ /* { dg-do run } */ /* { dg-options "-fno-strict-aliasing" } */ -/* { dg-skip-if "unaligned access" { arc*-*-* epiphany-*-* sparc*-*-* sh*-*-* tic6x-*-* } "*" "" } */ +/* { dg-skip-if "unaligned access" { arc*-*-* epiphany-*-* nds32*-*-* sparc*-*-* sh*-*-* tic6x-*-* } "*" "" } */ extern void abort (void); #if (__SIZEOF_INT__ <= 2) diff --git a/gcc/testsuite/gcc.dg/torture/pr57393-1.c b/gcc/testsuite/gcc.dg/torture/pr57393-1.c new file mode 100644 index 00000000000..e62d44df484 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr57393-1.c @@ -0,0 +1,15 @@ +/* PR middle-end/57393 */ +/* { dg-do compile } */ +/* { dg-additional-options "-g -ffast-math" } */ + +extern void bar (double); + +struct S { int n; }; + +void +foo (struct S s, double a, int i, int j, int k) +{ + struct S t; + bar (s.n * a * i * j); + t.n = s.n * a * i * k; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr57393-2.c b/gcc/testsuite/gcc.dg/torture/pr57393-2.c new file mode 100644 index 00000000000..b9b12ffa557 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr57393-2.c @@ -0,0 +1,16 @@ +/* PR middle-end/57393 */ +/* { dg-do compile } */ + +char a; + +foo (int **p) +{ + int b; + for (;;) + { + int c[1] = { 0 }; + unsigned *d = &c[0]; + for (b = 7; b; b--) + **p &= --*d >= a; + } +} diff --git a/gcc/testsuite/gcc.dg/torture/pr57393-3.c b/gcc/testsuite/gcc.dg/torture/pr57393-3.c new file mode 100644 index 00000000000..34cece06cbd --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr57393-3.c @@ -0,0 +1,20 @@ +/* PR middle-end/57393 */ +/* { dg-do compile } */ + +int a, b, c; +void foo (void); + +int +bar (void) +{ + for (;;) + { + foo (); + int d = a = 0; + for (; a < 7; ++a) + { + d--; + b &= c <= d; + } + } +} diff --git a/gcc/testsuite/gcc.dg/torture/pr58018.c b/gcc/testsuite/gcc.dg/torture/pr58018.c new file mode 100644 index 00000000000..52c8e83fa0d --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr58018.c @@ -0,0 +1,22 @@ +/* PR tree-optimization/58018 */ +/* { dg-do compile } */ + +int a, b, c, d, e; + +void +bar (int p) +{ + int f = b; + e &= p <= (f ^= 0); +} + +void +foo () +{ + for (; d; d++) + { + bar (a && c); + bar (0); + bar (1); + } +} diff --git a/gcc/testsuite/gcc.dg/torture/pr58131.c b/gcc/testsuite/gcc.dg/torture/pr58131.c new file mode 100644 index 00000000000..3f68d4c5286 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr58131.c @@ -0,0 +1,22 @@ +/* PR tree-optimization/58131 */ +/* { dg-do compile } */ + +short a; +int b, c, d[1][4][2]; + +void +foo (void) +{ + int *e; + for (b = 1; ; b--) + { + if (*e) + break; + for (c = 2; c >= 0; c--) + { + *e |= d[0][3][b] != a; + int *f = &d[0][3][b]; + *f = 0; + } + } +} diff --git a/gcc/testsuite/gcc.dg/torture/pr59139.c b/gcc/testsuite/gcc.dg/torture/pr59139.c new file mode 100644 index 00000000000..4ec9177ffe7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr59139.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ + +int a, b, c, d, e; +int fn1(p1, p2) { return p2 == 0 ? p1 : 1 % p2; } + +void fn2() +{ + c = 0; + for (;; c = (unsigned short)c) + { + b = 2; + for (; b; b = a) + { + e = fn1(2, c && 1); + d = c == 0 ? e : c; + if (d) + return; + } + } +} diff --git a/gcc/testsuite/gcc.dg/torture/pr59166.c b/gcc/testsuite/gcc.dg/torture/pr59166.c new file mode 100644 index 00000000000..d29ec33e0f9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr59166.c @@ -0,0 +1,37 @@ +/* PR rtl-optimization/59166 */ +/* { dg-additional-options "-fcompare-debug" } */ + +int a, b, c, f, g; + +void +foo () +{ + for (; b; b++) + for (; f; f = g) + for (; a;) + ; +} + +static int +bar (int p) +{ + short d; + if (c) + { + for (; f; f = g); + foo (); + d = p; + char e = d; + if (p) + return 1; + } + return p; +} + +int +main () +{ + bar (0); + bar (g); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr59216.c b/gcc/testsuite/gcc.dg/torture/pr59216.c new file mode 100644 index 00000000000..0de51bac95b --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr59216.c @@ -0,0 +1,32 @@ +/* { dg-do run } */ + +#include <limits.h> + +extern void abort (void); +extern void exit (int); + +long long __attribute__((noinline)) f(int a) +{ + return -(long long) a; +} + +int +main() +{ + if (f(0) != 0) + abort (); + + if (f(1) != -(long long)1) + abort (); + + if (f(-1) != -(long long)-1) + abort (); + + if (f(INT_MIN) != -(long long)INT_MIN) + abort (); + + if (f(INT_MAX) != -(long long)INT_MAX) + abort (); + + exit (0); +} diff --git a/gcc/testsuite/gcc.dg/torture/pr59245.c b/gcc/testsuite/gcc.dg/torture/pr59245.c new file mode 100644 index 00000000000..e5b9a0fb487 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr59245.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ + +int a, b, c, e, g; +char d[5], f; + +int +fn1 () +{ + if (b) + { + g = 0; + return 0; + } + for (f = 0; f != 1; f--) + ; + return 0; +} + +void +fn2 () +{ + d[4] = -1; + for (a = 4; a; a--) + { + fn1 (); + e = c < -2147483647 - 1 - d[a] ? c : 0; + } +} diff --git a/gcc/testsuite/gcc.dg/torture/pr59288.c b/gcc/testsuite/gcc.dg/torture/pr59288.c new file mode 100644 index 00000000000..8331e73289c --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr59288.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ + +void +baz (int *d) +{ + long int i, j, k; + for (i = 0, j = 0, k = 0; i < 512; i = (int) i + 1, j = (int) j + 1, k = (int) k + 3) + d[i] = j ^ (i * 3) ^ (2 * k + 2); +} diff --git a/gcc/testsuite/gcc.dg/torture/pr59330.c b/gcc/testsuite/gcc.dg/torture/pr59330.c new file mode 100644 index 00000000000..74b832ea314 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr59330.c @@ -0,0 +1,17 @@ +/* { dg-do run } */ + +void free(void *ptr) +{ +} + +void *foo(void) +{ + return 0; +} + +int main(void) +{ + void *p = foo(); + free(p); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr59338.c b/gcc/testsuite/gcc.dg/torture/pr59338.c new file mode 100644 index 00000000000..481c84d4ee7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr59338.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ + +typedef enum +{ + XYZZY, +} enumType; + +typedef struct +{ + unsigned char More : 1; +} tResp; + +typedef struct +{ + enumType QueryType; + union + { + tResp l[0]; + } u; +} tQResp; + +void test(void) +{ + tQResp *qResp = (0); + if (qResp->u.l[0].More == 0) + return; +} diff --git a/gcc/testsuite/gcc.dg/torture/stackalign/builtin-apply-2.c b/gcc/testsuite/gcc.dg/torture/stackalign/builtin-apply-2.c index ed81e808309..8eba13aed67 100644 --- a/gcc/testsuite/gcc.dg/torture/stackalign/builtin-apply-2.c +++ b/gcc/testsuite/gcc.dg/torture/stackalign/builtin-apply-2.c @@ -10,6 +10,7 @@ avr: Variadic funcs don't pass arguments in registers, while normal funcs do. */ /* { dg-skip-if "Variadic funcs use different argument passing from normal funcs" { arm_hf_eabi || { avr-*-* } } "*" "" } */ +/* { dg-skip-if "Variadic funcs have all args on stack. Normal funcs have args in registers." { nds32*-*-* } "*" "" } */ #define INTEGER_ARG 5 diff --git a/gcc/testsuite/gcc.dg/tree-prof/cold_partition_label.c b/gcc/testsuite/gcc.dg/tree-prof/cold_partition_label.c index 9dc75668e8d..a03aad7f6d8 100644 --- a/gcc/testsuite/gcc.dg/tree-prof/cold_partition_label.c +++ b/gcc/testsuite/gcc.dg/tree-prof/cold_partition_label.c @@ -1,7 +1,7 @@ /* Test case to check if function foo gets split and the cold function gets a label. */ /* { dg-require-effective-target freorder } */ -/* { dg-options "-O2 -freorder-blocks-and-partition --save-temps" } */ +/* { dg-options "-O2 -freorder-blocks-and-partition -save-temps" } */ #define SIZE 10000 @@ -34,3 +34,5 @@ main (int argc, char *argv[]) foo (argc); return 0; } + +/* { dg-final-use { cleanup-saved-temps } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20040204-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20040204-1.c index 470b585fd53..8518dfb1a8b 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/20040204-1.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/20040204-1.c @@ -33,5 +33,5 @@ void test55 (int x, int y) that the && should be emitted (based on BRANCH_COST). Fix this by teaching dom to look through && and register all components as true. */ -/* { dg-final { scan-tree-dump-times "link_error" 0 "optimized" { xfail { ! "alpha*-*-* arm*-*-* powerpc*-*-* cris-*-* crisv32-*-* hppa*-*-* i?86-*-* mmix-*-* mips*-*-* m68k*-*-* moxie-*-* sparc*-*-* spu-*-* x86_64-*-*" } } } } */ +/* { dg-final { scan-tree-dump-times "link_error" 0 "optimized" { xfail { ! "alpha*-*-* arm*-*-* powerpc*-*-* cris-*-* crisv32-*-* hppa*-*-* i?86-*-* mmix-*-* mips*-*-* m68k*-*-* moxie-*-* nds32*-*-* sparc*-*-* spu-*-* x86_64-*-*" } } } } */ /* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-29.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-29.c new file mode 100644 index 00000000000..4d57ca8f8f0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-29.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-optimized" } */ + +union X { + int i; + void *p; +}; +void bar (int); + +int * __attribute__((noinline,noclone)) +baz (int *p) { return p; } + +void foo (union X *x) +{ + struct Y { int i; } ystruct = {}; + ystruct.i = * baz (&ystruct.i); + bar (x->i); +} + +/* DSE and then DCE should be able to remove all uses of ystruct. + Formerly the union access for the parameter to bar let 'anything' + escape which made the call to bar possibly use ystruct and thus + prevent the store to ystruct.i from being eliminated. The call to + baz makes sure that ystruct has its address taken. */ + +/* { dg-final { scan-tree-dump-not "ystruct" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/attr-alias-2.c b/gcc/testsuite/gcc.dg/tree-ssa/attr-alias-2.c index 6d95a1582e2..89477d92f23 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/attr-alias-2.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/attr-alias-2.c @@ -8,3 +8,4 @@ main() return b+a; } /* { dg-final { scan-tree-dump "return 8" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/isolate-5.c b/gcc/testsuite/gcc.dg/tree-ssa/isolate-5.c index ee587d2320d..4d01d5c6399 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/isolate-5.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/isolate-5.c @@ -1,8 +1,6 @@ - /* { dg-do compile } */ /* { dg-options "-O2 -fdump-tree-isolate-paths -fdump-tree-optimized" } */ - struct demangle_component { @@ -11,7 +9,6 @@ struct demangle_component }; - struct d_info { struct demangle_component *comps; @@ -19,7 +16,6 @@ struct d_info int num_comps; }; - static struct demangle_component * d_make_empty (struct d_info *di) { @@ -31,8 +27,6 @@ d_make_empty (struct d_info *di) return p; } - - struct demangle_component * d_type (struct d_info *di) { @@ -55,8 +49,4 @@ d_type (struct d_info *di) /* { dg-final { scan-tree-dump-times "\\.type" 1 "optimized"} } */ /* { dg-final { scan-tree-dump-times "->zzz" 1 "isolate-paths"} } */ /* { dg-final { cleanup-tree-dump "isolate-paths" } } */ -/* { dg-final { cleanup-tree-dump "optimized-paths" } } */ - - - - +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr42585.c b/gcc/testsuite/gcc.dg/tree-ssa/pr42585.c index bea55496aeb..a970c855b88 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr42585.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr42585.c @@ -35,6 +35,6 @@ Cyc_string_ungetc (int ignore, struct _fat_ptr *sptr) /* Whether the structs are totally scalarized or not depends on the MOVE_RATIO macro definition in the back end. The scalarization will not take place when using small values for MOVE_RATIO. */ -/* { dg-final { scan-tree-dump-times "struct _fat_ptr _ans" 0 "optimized" { target { ! "arm*-*-* avr-*-* powerpc*-*-* s390*-*-* sh*-*-*" } } } } */ -/* { dg-final { scan-tree-dump-times "struct _fat_ptr _T2" 0 "optimized" { target { ! "arm*-*-* avr-*-* powerpc*-*-* s390*-*-* sh*-*-*" } } } } */ +/* { dg-final { scan-tree-dump-times "struct _fat_ptr _ans" 0 "optimized" { target { ! "arm*-*-* avr-*-* nds32*-*-* powerpc*-*-* s390*-*-* sh*-*-*" } } } } */ +/* { dg-final { scan-tree-dump-times "struct _fat_ptr _T2" 0 "optimized" { target { ! "arm*-*-* avr-*-* nds32*-*-* powerpc*-*-* s390*-*-* sh*-*-*" } } } } */ /* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr57361.c b/gcc/testsuite/gcc.dg/tree-ssa/pr57361.c index 81f27b3cd1f..bc265db6ff4 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr57361.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr57361.c @@ -7,3 +7,4 @@ void f (struct A *a) { } /* { dg-final { scan-tree-dump "Deleted dead store" "dse1"} } */ +/* { dg-final { cleanup-tree-dump "dse1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/slsr-39.c b/gcc/testsuite/gcc.dg/tree-ssa/slsr-39.c index 8cc279857c2..c1462195c9d 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/slsr-39.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/slsr-39.c @@ -6,7 +6,7 @@ *PINDEX: C1 + (C2 * C3) + C4 */ /* { dg-do compile } */ -/* { dg-options "-O2 -fdump-tree-slsr" } */ +/* { dg-options "-O2 -fdump-tree-slsr-details" } */ typedef int arr_2[50][50]; @@ -22,5 +22,5 @@ void foo (arr_2 a2, int v1) return; } -/* { dg-final { scan-tree-dump-times "MEM" 4 "slsr" } } */ +/* { dg-final { scan-tree-dump-times "Replacing reference: " 4 "slsr" } } */ /* { dg-final { cleanup-tree-dump "slsr" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/slsr-41.c b/gcc/testsuite/gcc.dg/tree-ssa/slsr-41.c new file mode 100644 index 00000000000..2c9d90880b8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/slsr-41.c @@ -0,0 +1,24 @@ +/* Verify straight-line strength reduction in using + alternative base expr to record and look for the + potential candidate. */ + +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-slsr-details" } */ + +typedef int arr_2[50][50]; + +void foo (arr_2 a2, int v1) +{ + int i, j; + + i = v1 + 5; + j = i; + a2 [i-10] [j] = 2; + a2 [i] [j++] = i; + a2 [i+20] [j++] = i; + a2 [i-3] [i-1] += 1; + return; +} + +/* { dg-final { scan-tree-dump-times "Replacing reference: " 5 "slsr" } } */ +/* { dg-final { cleanup-tree-dump "slsr" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/sra-12.c b/gcc/testsuite/gcc.dg/tree-ssa/sra-12.c index 1ad3f492422..59e5e6af6d9 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/sra-12.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/sra-12.c @@ -21,5 +21,5 @@ int foo (struct S *p) *p = l; } -/* { dg-final { scan-tree-dump-times "l;" 0 "release_ssa" { target { ! "avr*-*-*" } } } } */ +/* { dg-final { scan-tree-dump-times "l;" 0 "release_ssa" { target { ! "avr*-*-* nds32*-*-*" } } } } */ /* { dg-final { cleanup-tree-dump "release_ssa" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-slp-34.c b/gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-slp-34.c index 376c7e4ee07..f3d169b0324 100644 --- a/gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-slp-34.c +++ b/gcc/testsuite/gcc.dg/vect/costmodel/ppc/costmodel-slp-34.c @@ -1,4 +1,5 @@ /* { dg-require-effective-target vect_int } */ +/* { dg-skip-if "cost too high" { powerpc*le-*-* } { "*" } { "" } } */ #include <stdarg.h> #include "../../tree-vect.h" diff --git a/gcc/testsuite/gcc.dg/vect/vect-124.c b/gcc/testsuite/gcc.dg/vect/vect-124.c index dc81c3169c7..f659b94baba 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-124.c +++ b/gcc/testsuite/gcc.dg/vect/vect-124.c @@ -26,3 +26,5 @@ main () abort (); return 0; } + +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-simd-clone-1.c b/gcc/testsuite/gcc.dg/vect/vect-simd-clone-1.c new file mode 100644 index 00000000000..9fdd0563889 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-simd-clone-1.c @@ -0,0 +1,59 @@ +/* { dg-require-effective-target vect_simd_clones } */ +/* { dg-additional-options "-fopenmp-simd" } */ +/* { dg-additional-options "-mavx" { target avx_runtime } } */ + +#include "tree-vect.h" + +#ifndef N +#define N 1024 +#endif + +int array[N]; + +#pragma omp declare simd simdlen(4) notinbranch +#pragma omp declare simd simdlen(4) notinbranch uniform(b) linear(c:3) +#pragma omp declare simd simdlen(8) notinbranch +#pragma omp declare simd simdlen(8) notinbranch uniform(b) linear(c:3) +__attribute__((noinline)) int +foo (int a, int b, int c) +{ + if (a < 30) + return 5; + return a + b + c; +} + +__attribute__((noinline, noclone)) void +bar () +{ + int i; +#pragma omp simd + for (i = 0; i < N; ++i) + array[i] = foo (i, 123, i * 3); +} + +__attribute__((noinline, noclone)) void +baz () +{ + int i; +#pragma omp simd + for (i = 0; i < N; ++i) + array[i] = foo (i, array[i], i * 3); +} + +int +main () +{ + int i; + check_vect (); + bar (); + for (i = 0; i < N; i++) + if (array[i] != (i < 30 ? 5 : i * 4 + 123)) + abort (); + baz (); + for (i = 0; i < N; i++) + if (array[i] != (i < 30 ? 5 : i * 8 + 123)) + abort (); + return 0; +} + +/* { 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 new file mode 100644 index 00000000000..923a9453c25 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-simd-clone-10.c @@ -0,0 +1,84 @@ +/* { dg-require-effective-target vect_simd_clones } */ +/* { dg-additional-options "-fopenmp-simd" } */ +/* { dg-additional-options "-mavx" { target avx_runtime } } */ +/* { dg-additional-sources vect-simd-clone-10a.c } */ + +#include "tree-vect.h" + +#ifndef N +#define N 1024 +#endif + +int a[N], b[N]; +long int c[N]; +unsigned char d[N]; + +#include "vect-simd-clone-10.h" + +__attribute__((noinline)) void +fn1 (void) +{ + int i; + #pragma omp simd + for (i = 0; i < N; i++) + a[i] = foo (c[i], a[i], b[i]) + 6; + #pragma omp simd + for (i = 0; i < N; i++) + c[i] = bar (a[i], b[i], c[i]) * 2; +} + +__attribute__((noinline)) void +fn2 (void) +{ + int i; + #pragma omp simd + for (i = 0; i < N; i++) + { + a[i] = foo (c[i], a[i], b[i]) + 6; + d[i]++; + } + #pragma omp simd + for (i = 0; i < N; i++) + { + c[i] = bar (a[i], b[i], c[i]) * 2; + d[i] /= 2; + } +} + +__attribute__((noinline)) void +fn3 (void) +{ + int i; + for (i = 0; i < N; i++) + { + a[i] = i * 2; + b[i] = 17 + (i % 37); + c[i] = (i & 63); + d[i] = 16 + i; + } +} + +int +main () +{ + int i; + check_vect (); + fn3 (); + fn1 (); + for (i = 0; i < N; i++) + if (a[i] != i * 2 + 23 + (i % 37) + (i & 63) + || b[i] != 17 + (i % 37) + || c[i] != i * 4 + 80 + 4 * (i % 37) + 4 * (i & 63)) + abort (); + fn3 (); + fn2 (); + for (i = 0; i < N; i++) + if (a[i] != i * 2 + 23 + (i % 37) + (i & 63) + || b[i] != 17 + (i % 37) + || c[i] != i * 4 + 80 + 4 * (i % 37) + 4 * (i & 63) + || d[i] != ((unsigned char) (17 + i)) / 2) + abort (); + return 0; +} + +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-simd-clone-10.h b/gcc/testsuite/gcc.dg/vect/vect-simd-clone-10.h new file mode 100644 index 00000000000..ac3b81f8616 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-simd-clone-10.h @@ -0,0 +1,4 @@ +#pragma omp declare simd notinbranch +extern int foo (long int a, int b, int c); +#pragma omp declare simd notinbranch +extern long int bar (int a, int b, long int c); diff --git a/gcc/testsuite/gcc.dg/vect/vect-simd-clone-10a.c b/gcc/testsuite/gcc.dg/vect/vect-simd-clone-10a.c new file mode 100644 index 00000000000..1314039643f --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-simd-clone-10a.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ + +#include "vect-simd-clone-10.h" + +#pragma omp declare simd notinbranch +int +foo (long int a, int b, int c) +{ + return a + b + c; +} + +#pragma omp declare simd notinbranch +long int +bar (int a, int b, long int c) +{ + return a + b + c; +} diff --git a/gcc/testsuite/gcc.dg/vect/vect-simd-clone-11.c b/gcc/testsuite/gcc.dg/vect/vect-simd-clone-11.c new file mode 100644 index 00000000000..a04530e251e --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-simd-clone-11.c @@ -0,0 +1,67 @@ +/* { dg-require-effective-target vect_simd_clones } */ +/* { dg-additional-options "-fopenmp-simd" } */ +/* { dg-additional-options "-mavx" { target avx_runtime } } */ + +#include "tree-vect.h" + +#ifndef N +#define N 1024 +#endif + +int a[N] __attribute__((aligned (32))); + +#pragma omp declare simd linear(a) linear(b:3) linear(c:6) notinbranch +__attribute__((noinline)) int +foo (int a, int b, int c) +{ + return a ^ (b * 512) ^ (c * 512 * 512); +} + +__attribute__((noinline, noclone)) void +bar (int *d) +{ + int i, j, k; + for (i = 0, j = 0, k = 0; i < N / 2; i++, j++, k += 3) + d[i] = foo (j, i * 3, 2 * k + 2); +} + +#if 0 +__attribute__((noinline, noclone)) void +baz (int *d) +{ + long int i, j, k; + for (i = 0, j = 0, k = 0; i < N / 2; + i = (int) i + 1, j = (int) j + 1, k = (int) k + 3) + d[i] = foo (j, i * 3, 2 * k + 2); +} +#endif + +int +main () +{ + int i; + check_vect (); + if (sizeof (int) * __CHAR_BIT__ < 32) + return 0; + bar (a + 7); + for (i = 0; i < N / 2; i++) + if (a[i + 7] != (i ^ (i * 3 * 512) ^ (((i * 6) + 2) * 512 * 512))) + abort (); + bar (a); + for (i = 0; i < N / 2; i++) + if (a[i] != (i ^ (i * 3 * 512) ^ (((i * 6) + 2) * 512 * 512))) + abort (); +#if 0 + baz (a + 7); + for (i = 0; i < N / 2; i++) + if (a[i + 7] != (i ^ (i * 3 * 512) ^ (((i * 6) + 2) * 512 * 512))) + abort (); + baz (a); + for (i = 0; i < N / 2; i++) + if (a[i] != (i ^ (i * 3 * 512) ^ (((i * 6) + 2) * 512 * 512))) + abort (); +#endif + return 0; +} + +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-simd-clone-12.c b/gcc/testsuite/gcc.dg/vect/vect-simd-clone-12.c new file mode 100644 index 00000000000..279abd7c682 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-simd-clone-12.c @@ -0,0 +1,8 @@ +/* { dg-require-effective-target vect_simd_clones } */ +/* { dg-additional-options "-fopenmp-simd" } */ +/* { dg-additional-options "-mavx" { target avx_runtime } } */ +/* { dg-additional-sources vect-simd-clone-12a.c } */ + +#include "vect-simd-clone-10.c" + +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-simd-clone-12a.c b/gcc/testsuite/gcc.dg/vect/vect-simd-clone-12a.c new file mode 100644 index 00000000000..fcd04614e97 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-simd-clone-12a.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ + +#include "vect-simd-clone-10.h" + +#pragma omp declare simd notinbranch +__attribute__((noinline)) int +foo (long int a, int b, int c) +{ + return a + b + c; +} + +#pragma omp declare simd notinbranch +__attribute__((noinline)) long int +bar (int a, int b, long int c) +{ + return a + b + c; +} diff --git a/gcc/testsuite/gcc.dg/vect/vect-simd-clone-2.c b/gcc/testsuite/gcc.dg/vect/vect-simd-clone-2.c new file mode 100644 index 00000000000..0eae49db97a --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-simd-clone-2.c @@ -0,0 +1,53 @@ +/* { dg-require-effective-target vect_simd_clones } */ +/* { dg-additional-options "-fopenmp-simd" } */ +/* { dg-additional-options "-mavx" { target avx_runtime } } */ + +#include "tree-vect.h" + +#ifndef N +#define N 1024 +#endif + +int array[N] __attribute__((aligned (32))); + +#pragma omp declare simd simdlen(4) notinbranch aligned(a:16) uniform(a) linear(b) +#pragma omp declare simd simdlen(4) notinbranch aligned(a:32) uniform(a) linear(b) +#pragma omp declare simd simdlen(8) notinbranch aligned(a:16) uniform(a) linear(b) +#pragma omp declare simd simdlen(8) notinbranch aligned(a:32) uniform(a) linear(b) +__attribute__((noinline)) void +foo (int *a, int b, int c) +{ + a[b] = c; +} + +__attribute__((noinline, noclone)) void +bar () +{ + int i; +#pragma omp simd + for (i = 0; i < N; ++i) + foo (array, i, i * array[i]); +} + +__attribute__((noinline, noclone)) void +baz () +{ + int i; + for (i = 0; i < N; i++) + array[i] = 5 * (i & 7); +} + +int +main () +{ + int i; + check_vect (); + baz (); + bar (); + for (i = 0; i < N; i++) + if (array[i] != 5 * (i & 7) * i) + abort (); + return 0; +} + +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-simd-clone-3.c b/gcc/testsuite/gcc.dg/vect/vect-simd-clone-3.c new file mode 100644 index 00000000000..857c6f783e3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-simd-clone-3.c @@ -0,0 +1,46 @@ +/* { dg-require-effective-target vect_simd_clones } */ +/* { dg-additional-options "-fopenmp-simd" } */ +/* { dg-additional-options "-mavx" { target avx_runtime } } */ + +#include "tree-vect.h" + +#ifndef N +#define N 1024 +#endif + +int d[N], e[N]; + +#pragma omp declare simd simdlen(4) notinbranch uniform(b) linear(c:3) +__attribute__((noinline)) int +foo (int a, int b, int c) +{ + if (a < 30) + return 5; + return a + b + c; +} + +__attribute__((noinline, noclone)) void +bar () +{ + int i; +#pragma omp simd + for (i = 0; i < N; ++i) + { + d[i] = foo (i, 123, i * 3); + e[i] = e[i] + i; + } +} + +int +main () +{ + int i; + check_vect (); + bar (); + for (i = 0; i < N; i++) + if (d[i] != (i < 30 ? 5 : i * 4 + 123) || e[i] != i) + abort (); + return 0; +} + +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-simd-clone-4.c b/gcc/testsuite/gcc.dg/vect/vect-simd-clone-4.c new file mode 100644 index 00000000000..c64f1b0bfe5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-simd-clone-4.c @@ -0,0 +1,49 @@ +/* { dg-require-effective-target vect_simd_clones } */ +/* { dg-additional-options "-fopenmp-simd" } */ +/* { dg-additional-options "-mavx" { target avx_runtime } } */ + +#include "tree-vect.h" + +#ifndef N +#define N 1024 +#endif + +float d[N]; +int e[N]; +unsigned short f[N]; + +#pragma omp declare simd simdlen(8) notinbranch uniform(b) +__attribute__((noinline)) float +foo (float a, float b, float c) +{ + if (a < 30) + return 5.0f; + return a + b + c; +} + +__attribute__((noinline, noclone)) void +bar () +{ + int i; +#pragma omp simd + for (i = 0; i < N; ++i) + { + d[i] = foo (i, 123, i * 3); + e[i] = e[i] * 3; + f[i] = f[i] + 1; + } +} + +int +main () +{ + int i; + check_vect (); + bar (); + for (i = 0; i < N; i++) + if (d[i] != (i < 30 ? 5.0f : i * 4 + 123.0f) || e[i] || f[i] != 1) + abort (); + return 0; +} + +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-simd-clone-5.c b/gcc/testsuite/gcc.dg/vect/vect-simd-clone-5.c new file mode 100644 index 00000000000..1d2b067a7d5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-simd-clone-5.c @@ -0,0 +1,44 @@ +/* { dg-require-effective-target vect_simd_clones } */ +/* { dg-additional-options "-fopenmp-simd" } */ +/* { dg-additional-options "-mavx" { target avx_runtime } } */ + +#include "tree-vect.h" + +#ifndef N +#define N 1024 +#endif + +int d[N], e[N]; + +#pragma omp declare simd simdlen(4) notinbranch uniform(b) linear(c:3) +__attribute__((noinline)) long long int +foo (int a, int b, int c) +{ + return a + b + c; +} + +__attribute__((noinline, noclone)) void +bar () +{ + int i; +#pragma omp simd + for (i = 0; i < N; ++i) + { + d[i] = foo (i, 123, i * 3); + e[i] = e[i] + i; + } +} + +int +main () +{ + int i; + check_vect (); + bar (); + for (i = 0; i < N; i++) + if (d[i] != i * 4 + 123 || e[i] != i) + abort (); + return 0; +} + +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-simd-clone-6.c b/gcc/testsuite/gcc.dg/vect/vect-simd-clone-6.c new file mode 100644 index 00000000000..26995da86e3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-simd-clone-6.c @@ -0,0 +1,75 @@ +/* { dg-require-effective-target vect_simd_clones } */ +/* { dg-additional-options "-fopenmp-simd" } */ +/* { dg-additional-options "-mavx" { target avx_runtime } } */ + +#include "tree-vect.h" + +#ifndef N +#define N 1024 +#endif + +int a[N]; +long long int b[N]; +short c[N]; + +#pragma omp declare simd +#pragma omp declare simd uniform(b) linear(c:3) +__attribute__((noinline)) short +foo (int a, long long int b, short c) +{ + return a + b + c; +} + +__attribute__((noinline, noclone)) void +bar (int x) +{ + int i; + if (x == 0) + { + #pragma omp simd + for (i = 0; i < N; i++) + c[i] = foo (a[i], b[i], c[i]); + } + else + { + #pragma omp simd + for (i = 0; i < N; i++) + c[i] = foo (a[i], x, i * 3); + } +} + +__attribute__((noinline, noclone)) void +baz (void) +{ + int i; + for (i = 0; i < N; i++) + { + a[i] = 2 * i; + b[i] = -7 * i + 6; + c[i] = (i & 31) << 4; + } +} + +int +main () +{ + int i; + check_vect (); + baz (); + bar (0); + for (i = 0; i < N; i++) + if (a[i] != 2 * i || b[i] != 6 - 7 * i + || c[i] != 6 - 5 * i + ((i & 31) << 4)) + abort (); + else + a[i] = c[i]; + bar (17); + for (i = 0; i < N; i++) + if (a[i] != 6 - 5 * i + ((i & 31) << 4) + || b[i] != 6 - 7 * i + || c[i] != 23 - 2 * i + ((i & 31) << 4)) + abort (); + return 0; +} + +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-simd-clone-7.c b/gcc/testsuite/gcc.dg/vect/vect-simd-clone-7.c new file mode 100644 index 00000000000..2745c5e41d1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-simd-clone-7.c @@ -0,0 +1,75 @@ +/* { dg-require-effective-target vect_simd_clones } */ +/* { dg-additional-options "-fopenmp-simd" } */ +/* { dg-additional-options "-mavx" { target avx_runtime } } */ + +#include "tree-vect.h" + +#ifndef N +#define N 1024 +#endif + +int a[N]; +long long int b[N]; +short c[N]; + +#pragma omp declare simd +#pragma omp declare simd uniform(b) linear(c:3) +__attribute__((noinline)) short +foo (int a, long long int b, int c) +{ + return a + b + c; +} + +__attribute__((noinline, noclone)) void +bar (int x) +{ + int i; + if (x == 0) + { + #pragma omp simd + for (i = 0; i < N; i++) + c[i] = foo (a[i], b[i], c[i]); + } + else + { + #pragma omp simd + for (i = 0; i < N; i++) + c[i] = foo (a[i], x, i * 3); + } +} + +__attribute__((noinline, noclone)) void +baz (void) +{ + int i; + for (i = 0; i < N; i++) + { + a[i] = 2 * i; + b[i] = -7 * i + 6; + c[i] = (i & 31) << 4; + } +} + +int +main () +{ + int i; + check_vect (); + baz (); + bar (0); + for (i = 0; i < N; i++) + if (a[i] != 2 * i || b[i] != 6 - 7 * i + || c[i] != 6 - 5 * i + ((i & 31) << 4)) + abort (); + else + a[i] = c[i]; + bar (17); + for (i = 0; i < N; i++) + if (a[i] != 6 - 5 * i + ((i & 31) << 4) + || b[i] != 6 - 7 * i + || c[i] != 23 - 2 * i + ((i & 31) << 4)) + abort (); + return 0; +} + +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-simd-clone-8.c b/gcc/testsuite/gcc.dg/vect/vect-simd-clone-8.c new file mode 100644 index 00000000000..e0b09b645d4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-simd-clone-8.c @@ -0,0 +1,95 @@ +/* { dg-require-effective-target vect_simd_clones } */ +/* { dg-additional-options "-fopenmp-simd" } */ +/* { dg-additional-options "-mavx" { target avx_runtime } } */ + +#include "tree-vect.h" + +#ifndef N +#define N 1024 +#endif + +int a[N], b[N]; +long int c[N]; +unsigned char d[N]; + +#pragma omp declare simd simdlen(8) notinbranch +__attribute__((noinline)) int +foo (long int a, int b, int c) +{ + return a + b + c; +} + +#pragma omp declare simd simdlen(8) notinbranch +__attribute__((noinline)) long int +bar (int a, int b, long int c) +{ + return a + b + c; +} + +__attribute__((noinline)) void +fn1 (void) +{ + int i; + #pragma omp simd + for (i = 0; i < N; i++) + a[i] = foo (c[i], a[i], b[i]) + 6; + #pragma omp simd + for (i = 0; i < N; i++) + c[i] = bar (a[i], b[i], c[i]) * 2; +} + +__attribute__((noinline)) void +fn2 (void) +{ + int i; + #pragma omp simd + for (i = 0; i < N; i++) + { + a[i] = foo (c[i], a[i], b[i]) + 6; + d[i]++; + } + #pragma omp simd + for (i = 0; i < N; i++) + { + c[i] = bar (a[i], b[i], c[i]) * 2; + d[i] /= 2; + } +} + +__attribute__((noinline)) void +fn3 (void) +{ + int i; + for (i = 0; i < N; i++) + { + a[i] = i * 2; + b[i] = 17 + (i % 37); + c[i] = (i & 63); + d[i] = 16 + i; + } +} + +int +main () +{ + int i; + check_vect (); + fn3 (); + fn1 (); + for (i = 0; i < N; i++) + if (a[i] != i * 2 + 23 + (i % 37) + (i & 63) + || b[i] != 17 + (i % 37) + || c[i] != i * 4 + 80 + 4 * (i % 37) + 4 * (i & 63)) + abort (); + fn3 (); + fn2 (); + for (i = 0; i < N; i++) + if (a[i] != i * 2 + 23 + (i % 37) + (i & 63) + || b[i] != 17 + (i % 37) + || c[i] != i * 4 + 80 + 4 * (i % 37) + 4 * (i & 63) + || d[i] != ((unsigned char) (17 + i)) / 2) + abort (); + return 0; +} + +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-simd-clone-9.c b/gcc/testsuite/gcc.dg/vect/vect-simd-clone-9.c new file mode 100644 index 00000000000..0c5ff4fa438 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-simd-clone-9.c @@ -0,0 +1,95 @@ +/* { dg-require-effective-target vect_simd_clones } */ +/* { dg-additional-options "-fopenmp-simd" } */ +/* { dg-additional-options "-mavx" { target avx_runtime } } */ + +#include "tree-vect.h" + +#ifndef N +#define N 1024 +#endif + +int a[N], b[N]; +long int c[N]; +unsigned char d[N]; + +#pragma omp declare simd notinbranch +__attribute__((noinline)) static int +foo (long int a, int b, int c) +{ + return a + b + c; +} + +#pragma omp declare simd notinbranch +__attribute__((noinline)) static long int +bar (int a, int b, long int c) +{ + return a + b + c; +} + +__attribute__((noinline)) void +fn1 (void) +{ + int i; + #pragma omp simd + for (i = 0; i < N; i++) + a[i] = foo (c[i], a[i], b[i]) + 6; + #pragma omp simd + for (i = 0; i < N; i++) + c[i] = bar (a[i], b[i], c[i]) * 2; +} + +__attribute__((noinline)) void +fn2 (void) +{ + int i; + #pragma omp simd + for (i = 0; i < N; i++) + { + a[i] = foo (c[i], a[i], b[i]) + 6; + d[i]++; + } + #pragma omp simd + for (i = 0; i < N; i++) + { + c[i] = bar (a[i], b[i], c[i]) * 2; + d[i] /= 2; + } +} + +__attribute__((noinline)) void +fn3 (void) +{ + int i; + for (i = 0; i < N; i++) + { + a[i] = i * 2; + b[i] = 17 + (i % 37); + c[i] = (i & 63); + d[i] = 16 + i; + } +} + +int +main () +{ + int i; + check_vect (); + fn3 (); + fn1 (); + for (i = 0; i < N; i++) + if (a[i] != i * 2 + 23 + (i % 37) + (i & 63) + || b[i] != 17 + (i % 37) + || c[i] != i * 4 + 80 + 4 * (i % 37) + 4 * (i & 63)) + abort (); + fn3 (); + fn2 (); + for (i = 0; i < N; i++) + if (a[i] != i * 2 + 23 + (i % 37) + (i & 63) + || b[i] != 17 + (i % 37) + || c[i] != i * 4 + 80 + 4 * (i % 37) + 4 * (i & 63) + || d[i] != ((unsigned char) (17 + i)) / 2) + abort (); + return 0; +} + +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect.exp b/gcc/testsuite/gcc.dg/vect/vect.exp index bea7ee0064b..796f83ea4e0 100644 --- a/gcc/testsuite/gcc.dg/vect/vect.exp +++ b/gcc/testsuite/gcc.dg/vect/vect.exp @@ -76,7 +76,7 @@ lappend VECT_SLP_CFLAGS "-fdump-tree-slp-details" # Main loop. set VECT_ADDITIONAL_FLAGS [list ""] if { [check_effective_target_lto] } { - lappend VECT_ADDITIONAL_FLAGS "-flto" + lappend VECT_ADDITIONAL_FLAGS "-flto -ffat-lto-objects" } foreach flags $VECT_ADDITIONAL_FLAGS { dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/pr*.\[cS\]]] \ diff --git a/gcc/testsuite/gcc.target/aarch64/vmov_n_1.c b/gcc/testsuite/gcc.target/aarch64/vmov_n_1.c new file mode 100644 index 00000000000..b9d094a044a --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/vmov_n_1.c @@ -0,0 +1,349 @@ +/* Test vmov_n works correctly. */ +/* { dg-do run } */ +/* { dg-options "-O3 --save-temps" } */ + +#include <arm_neon.h> + +extern void abort (void); + +#define INHIB_OPTIMIZATION asm volatile ("" : : : "memory") + +#define CONCAT(a, b) a##b +#define CONCAT1(a, b) CONCAT (a, b) +#define REG_INFEX64 _ +#define REG_INFEX128 q_ +#define REG_INFEX(reg_len) REG_INFEX##reg_len +#define POSTFIX_N(reg_len, data_len, data_type) \ + CONCAT1 (REG_INFEX (reg_len), n_##data_type##data_len) +#define LANE_POSTFIX(reg_len, data_len, data_type) \ + CONCAT1 (REG_INFEX (reg_len),lane_##data_type##data_len) + +/* Test values consist of bytes with following hex values. + For example: + TEST1 for int16_t will be 0xaaaa + TEST1 for int32_t will be 0xaaaaaaaa + etc. */ + +#define TEST1h aa +#define TEST2h 55 +#define TEST3h ff +#define TEST4h 00 +#define TEST5h cc +#define TEST6h 33 + +#define TESTh_8(x) TEST##x##h +#define TESTh_16(x) CONCAT1 (TESTh_8 (x), TESTh_8 (x)) +#define TESTh_32(x) CONCAT1 (TESTh_16 (x), TESTh_16 (x)) +#define TESTh_64(x) CONCAT1 (TESTh_32 (x), TESTh_32 (x)) + +#define TEST_8(x) CONCAT1 (0x, TESTh_8 (x)) +#define TEST_16(x) CONCAT1 (0x, TESTh_16 (x)) +#define TEST_32(x) CONCAT1 (0x, TESTh_32 (x)) +#define TEST_64(x) CONCAT1 (0x, TESTh_64 (x)) + +#define TEST(test, data_len) \ + CONCAT1 (TEST, _##data_len) (test) + +#define GET_ELEMENT(reg_len, data_len, data_type) \ + CONCAT1 (vget, LANE_POSTFIX (reg_len, data_len, data_type)) + +#define VMOV_INST(reg_len, data_len, data_type) \ + CONCAT1 (vmov, POSTFIX_N (reg_len, data_len, data_type)) + +#define VMOV_OBSCURE_INST(reg_len, data_len, data_type) \ + CONCAT1 (VMOV_INST (reg_len, data_len, data_type), _obscure) + +#define RUN_TEST(reg_len, data_len, data_type, \ + test, n, a, b, c) \ +{ \ + int i; \ + INHIB_OPTIMIZATION; \ + (a) = TEST (test, data_len); \ + INHIB_OPTIMIZATION; \ + (b) = VMOV_OBSCURE_INST (reg_len, data_len, data_type) (&(a)); \ + (c) = TEST (test, data_len); \ + for (i = 0; i < n; i++) \ + { \ + INHIB_OPTIMIZATION; \ + a = GET_ELEMENT (reg_len, data_len, data_type) (b, i); \ + if ((a) != (c)) \ + return 1; \ + } \ +} + +#define TYPE_f32 float32_t +#define TYPE_64_f32 float32x2_t +#define TYPE_128_f32 float32x4_t + +#define TYPE_f64 float64_t +#define TYPE_64_f64 float64x1_t +#define TYPE_128_f64 float64x2_t + +#define TYPE_s8 int8_t +#define TYPE_64_s8 int8x8_t +#define TYPE_128_s8 int8x16_t + +#define TYPE_s16 int16_t +#define TYPE_64_s16 int16x4_t +#define TYPE_128_s16 int16x8_t + +#define TYPE_s32 int32_t +#define TYPE_64_s32 int32x2_t +#define TYPE_128_s32 int32x4_t + +#define TYPE_s64 int64_t +#define TYPE_64_s64 int64x1_t +#define TYPE_128_s64 int64x2_t + +#define TYPE_u8 uint8_t +#define TYPE_64_u8 uint8x8_t +#define TYPE_128_u8 uint8x16_t + +#define TYPE_u16 uint16_t +#define TYPE_64_u16 uint16x4_t +#define TYPE_128_u16 uint16x8_t + +#define TYPE_u32 uint32_t +#define TYPE_64_u32 uint32x2_t +#define TYPE_128_u32 uint32x4_t + +#define TYPE_u64 uint64_t +#define TYPE_64_u64 uint64x1_t +#define TYPE_128_u64 uint64x2_t + +#define TYPE_p8 poly8_t +#define TYPE_64_p8 poly8x8_t +#define TYPE_128_p8 poly8x16_t + +#define TYPE_p16 poly16_t +#define TYPE_64_p16 poly16x4_t +#define TYPE_128_p16 poly16x8_t + +#define DIV64_8 8 +#define DIV64_16 4 +#define DIV64_32 2 +#define DIV64_64 1 + +#define DIV128_8 16 +#define DIV128_16 8 +#define DIV128_32 4 +#define DIV128_64 2 + +#define DIV(reg_len, data_len) \ +CONCAT1 (CONCAT1 (DIV, reg_len), \ + CONCAT1 (_, data_len)) + +#define VECTOR_TYPE(reg_len, data_len, data_type) \ +CONCAT1 (CONCAT1 (CONCAT1 (TYPE_,reg_len), \ + CONCAT1 (_,data_type)), \ + data_len) + +#define SIMPLE_TYPE(data_len, data_type) \ +CONCAT1 (TYPE_, \ + CONCAT1 (data_type, \ + data_len)) + +#define OBSCURE_FUNC_NAME(reg_len, data_type, data_len) \ +CONCAT1 (CONCAT1 (vmov, \ + POSTFIX_N (reg_len, data_len, data_type)), \ + _obscure) + +#define OBSCURE_FUNC(reg_len, data_len, data_type) \ +VECTOR_TYPE (reg_len, data_len, data_type) \ +__attribute__ ((noinline)) \ +OBSCURE_FUNC_NAME (reg_len, data_type, data_len) \ + (SIMPLE_TYPE (data_len, data_type) *ap) \ +{ \ + SIMPLE_TYPE (data_len, data_type) register a; \ + INHIB_OPTIMIZATION; \ + a = *ap; \ + INHIB_OPTIMIZATION; \ + return VMOV_INST (reg_len, data_len, data_type) (a); \ +} + +#define TESTFUNC_NAME(reg_len, data_type, data_len) \ +CONCAT1 (test_vmov, \ + POSTFIX_N (reg_len, data_len, data_type)) + +#define TESTFUNC(reg_len, data_len, data_type) \ +int \ +TESTFUNC_NAME (reg_len, data_type, data_len) () \ +{ \ + SIMPLE_TYPE (data_len, data_type) a; \ + VECTOR_TYPE (reg_len, data_len, data_type) b; \ + SIMPLE_TYPE (data_len, data_type) c; \ + \ + RUN_TEST (reg_len, data_len, data_type, 1, \ + DIV (reg_len, data_len), a, b, c); \ + RUN_TEST (reg_len, data_len, data_type, 2, \ + DIV (reg_len, data_len), a, b, c); \ + RUN_TEST (reg_len, data_len, data_type, 3, \ + DIV (reg_len, data_len), a, b, c); \ + RUN_TEST (reg_len, data_len, data_type, 4, \ + DIV (reg_len, data_len), a, b, c); \ + RUN_TEST (reg_len, data_len, data_type, 5, \ + DIV (reg_len, data_len), a, b, c); \ + RUN_TEST (reg_len, data_len, data_type, 6, \ + DIV (reg_len, data_len), a, b, c); \ + return 0; \ +} + +OBSCURE_FUNC (64, 32, f) +TESTFUNC (64, 32, f) +/* "dup Vd.2s, Rn" is less preferable then "dup Vd.2s, Vn.s[lane]". */ +/* { dg-final { scan-assembler-times "dup\\tv\[0-9\]+\.2s, v\[0-9\]+\.s\\\[\[0-9\]+\\\]" 1 } } */ + +OBSCURE_FUNC (64, 64, f) +TESTFUNC (64, 64, f) +/* "fmov Dd, Rn" is generated instead of "dup Dd, Rn". + No assembley scan included. */ + +OBSCURE_FUNC (64, 8, p) +TESTFUNC (64, 8, p) +/* Generates "dup Vd.8b, Rn". Scan found near s8 version. */ + +OBSCURE_FUNC (64, 16, p) +TESTFUNC (64, 16, p) +/* Generates "dup Vd.4h, Rn". Scan found near s16 version. */ + +OBSCURE_FUNC (64, 8, s) +TESTFUNC (64, 8, s) +/* { dg-final { scan-assembler-times "dup\\tv\[0-9\]+\.8b, w\[0-9\]+" 3 } } */ + +OBSCURE_FUNC (64, 16, s) +TESTFUNC (64, 16, s) +/* { dg-final { scan-assembler-times "dup\\tv\[0-9\]+\.4h, w\[0-9\]+" 3 } } */ + +OBSCURE_FUNC (64, 32, s) +TESTFUNC (64, 32, s) +/* { dg-final { scan-assembler-times "dup\\tv\[0-9\]+\.2s, w\[0-9\]+" 2 } } */ + +OBSCURE_FUNC (64, 64, s) +TESTFUNC (64, 64, s) +/* "fmov Dd, Rn" is generated instead of "dup Dd, Rn". + No assembley scan included. */ + +OBSCURE_FUNC (64, 8, u) +TESTFUNC (64, 8, u) +/* Generates "dup Vd.8b, Rn". Scan found near s8 version. */ + +OBSCURE_FUNC (64, 16, u) +TESTFUNC (64, 16, u) +/* Generates "dup Vd.4h, Rn". Scan found near s16 version. */ + +OBSCURE_FUNC (64, 32, u) +TESTFUNC (64, 32, u) +/* Generates "dup Vd.2s, Rn". Scan found near s32 version. */ + +OBSCURE_FUNC (64, 64, u) +TESTFUNC (64, 64, u) +/* "fmov Dd, Rn" is generated instead of "dup Dd, Rn". + No assembley scan included. */ + +OBSCURE_FUNC (128, 32, f) +TESTFUNC (128, 32, f) +/* "dup Vd.4s, Rn" is less preferable then "dup Vd.4s, Vn.s[lane]". */ +/* { dg-final { scan-assembler-times "dup\\tv\[0-9\]+\.4s, v\[0-9\]+\.s\\\[\[0-9\]+\\\]" 1 } } */ + +OBSCURE_FUNC (128, 64, f) +TESTFUNC (128, 64, f) +/* "dup Vd.2d, Rn" is less preferable then "dup Vd.2d, Vn.d[lane]". */ +/* { dg-final { scan-assembler-times "dup\\tv\[0-9\]+\.2d, v\[0-9\]+\.d\\\[\[0-9\]+\\\]" 1 } } */ + +OBSCURE_FUNC (128, 8, p) +TESTFUNC (128, 8, p) +/* Generates "dup Vd.16b, Rn". Scan found near s8 version. */ + +OBSCURE_FUNC (128, 16, p) +TESTFUNC (128, 16, p) +/* Generates "dup Vd.8h, Rn". Scan found near s16 version. */ + +OBSCURE_FUNC (128, 8, s) +TESTFUNC (128, 8, s) +/* { dg-final { scan-assembler-times "dup\\tv\[0-9\]+\.16b, w\[0-9\]+" 3 } } */ + +OBSCURE_FUNC (128, 16, s) +TESTFUNC (128, 16, s) +/* { dg-final { scan-assembler-times "dup\\tv\[0-9\]+\.8h, w\[0-9\]+" 3 } } */ + +OBSCURE_FUNC (128, 32, s) +TESTFUNC (128, 32, s) +/* { dg-final { scan-assembler-times "dup\\tv\[0-9\]+\.4s, w\[0-9\]+" 2 } } */ + +OBSCURE_FUNC (128, 64, s) +TESTFUNC (128, 64, s) +/* { dg-final { scan-assembler-times "dup\\tv\[0-9\]+\.2d, x\[0-9\]+" 2 } } */ + +OBSCURE_FUNC (128, 8, u) +TESTFUNC (128, 8, u) +/* Generates "dup Vd.16b, Rn". Scan found near s8 version. */ + +OBSCURE_FUNC (128, 16, u) +TESTFUNC (128, 16, u) +/* Generates "dup Vd.8h, Rn". Scan found near s16 version. */ + +OBSCURE_FUNC (128, 32, u) +TESTFUNC (128, 32, u) +/* Generates "dup Vd.4s, Rn". Scan found near s32 version. */ + +OBSCURE_FUNC (128, 64, u) +TESTFUNC (128, 64, u) +/* Generates "dup Vd.2d, Rn". Scan found near s64 version. */ + +int +main (int argc, char **argv) +{ + if (test_vmov_n_f32 ()) + abort (); + if (test_vmov_n_f64 ()) + abort (); + if (test_vmov_n_p8 ()) + abort (); + if (test_vmov_n_p16 ()) + abort (); + if (test_vmov_n_s8 ()) + abort (); + if (test_vmov_n_s16 ()) + abort (); + if (test_vmov_n_s32 ()) + abort (); + if (test_vmov_n_s64 ()) + abort (); + if (test_vmov_n_u8 ()) + abort (); + if (test_vmov_n_u16 ()) + abort (); + if (test_vmov_n_u32 ()) + abort (); + if (test_vmov_n_u64 ()) + abort (); + + if (test_vmovq_n_f32 ()) + abort (); + if (test_vmovq_n_f64 ()) + abort (); + if (test_vmovq_n_p8 ()) + abort (); + if (test_vmovq_n_p16 ()) + abort (); + if (test_vmovq_n_s8 ()) + abort (); + if (test_vmovq_n_s16 ()) + abort (); + if (test_vmovq_n_s32 ()) + abort (); + if (test_vmovq_n_s64 ()) + abort (); + if (test_vmovq_n_u8 ()) + abort (); + if (test_vmovq_n_u16 ()) + abort (); + if (test_vmovq_n_u32 ()) + abort (); + if (test_vmovq_n_u64 ()) + abort (); + + return 0; +} + +/* { dg-final { cleanup-saved-temps } } */ diff --git a/gcc/testsuite/gcc.target/arm/20131120.c b/gcc/testsuite/gcc.target/arm/20131120.c new file mode 100644 index 00000000000..c370ae60cd8 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/20131120.c @@ -0,0 +1,14 @@ +/* Check that CONST_INT is not forced into REG before PLUS. */ +/* { dg-do compile { target { arm_arm_ok || arm_thumb2_ok} } } */ +/* { dg-options "-O2 -fdump-rtl-expand" } */ + +typedef int Arr2[50][50]; + +void +foo (Arr2 a2, int i) +{ + a2[i+20][i] = 1; +} + +/* { dg-final { scan-rtl-dump-not "\\\(set \\\(reg:SI \[0-9\]*\\\)\[\n\r\]+\[ \t]*\\\(const_int 4000" "expand" } } */ +/* { dg-final { cleanup-rtl-dump "expand" } } */ diff --git a/gcc/testsuite/gcc.target/arm/lp1243022.c b/gcc/testsuite/gcc.target/arm/lp1243022.c index 91a544d1b7d..cb405908e05 100644 --- a/gcc/testsuite/gcc.target/arm/lp1243022.c +++ b/gcc/testsuite/gcc.target/arm/lp1243022.c @@ -1,7 +1,7 @@ /* { dg-do compile { target arm_thumb2 } } */ /* { dg-options "-O2 -fdump-rtl-subreg2" } */ -/* { dg-final { scan-rtl-dump "REG_INC" "subreg2" } } */ +/* { dg-final { scan-rtl-dump "REG_INC" "subreg2" { target { ! arm_neon } } } } */ /* { dg-final { cleanup-rtl-dump "subreg2" } } */ struct device; typedef unsigned int __u32; diff --git a/gcc/testsuite/gcc.target/arm/negdi-2.c b/gcc/testsuite/gcc.target/arm/negdi-2.c index 96bbcab337e..4444c20ea9c 100644 --- a/gcc/testsuite/gcc.target/arm/negdi-2.c +++ b/gcc/testsuite/gcc.target/arm/negdi-2.c @@ -11,6 +11,6 @@ Expected output: rsb r0, r0, #0 mov r1, #0 */ -/* { dg-final { scan-assembler-times "rsb\\tr0, r0, #0" 1 { target { arm_nothumb } } } } */ -/* { dg-final { scan-assembler-times "negs\\tr0, r0" 1 { target { ! arm_nothumb } } } } */ +/* { dg-final { scan-assembler-times "rsb\\t...?, ...?, #0" 1 { target { arm_nothumb } } } } */ +/* { dg-final { scan-assembler-times "negs\\t...?, ...?" 1 { target { ! arm_nothumb } } } } */ /* { dg-final { scan-assembler-times "mov" 1 } } */ diff --git a/gcc/testsuite/gcc.target/arm/negdi-4.c b/gcc/testsuite/gcc.target/arm/negdi-4.c deleted file mode 100644 index dc3deaad5ad..00000000000 --- a/gcc/testsuite/gcc.target/arm/negdi-4.c +++ /dev/null @@ -1,16 +0,0 @@ -/* { dg-do compile } */ -/* { dg-require-effective-target arm32 } */ -/* { dg-options "-O2" } */ - -signed long long negdi_extendsidi (signed int x) -{ - return -((signed long long) x); -} -/* -Expected output: - rsbs r0, r0, #0 - mov r1, r0, asr #31 -*/ -/* { dg-final { scan-assembler-times "rsb" 1 } } */ -/* { dg-final { scan-assembler-times "asr" 1 } } */ -/* { dg-final { scan-assembler-times "rsc" 0 } } */ diff --git a/gcc/testsuite/gcc.target/arm/thumb1-pic-high-reg.c b/gcc/testsuite/gcc.target/arm/thumb1-pic-high-reg.c new file mode 100644 index 00000000000..df269fc8476 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/thumb1-pic-high-reg.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_thumb1_ok } */ +/* { dg-options "-mthumb -fpic -mpic-register=9" } */ + +int g_test; + +int +foo (int par) +{ + g_test = par; +} diff --git a/gcc/testsuite/gcc.target/arm/thumb1-pic-single-base.c b/gcc/testsuite/gcc.target/arm/thumb1-pic-single-base.c new file mode 100644 index 00000000000..6e9b2570a4a --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/thumb1-pic-single-base.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_thumb1_ok } */ +/* { dg-options "-mthumb -fpic -msingle-pic-base" } */ + +int g_test; + +int +foo (int par) +{ + g_test = par; +} diff --git a/gcc/testsuite/gcc.target/arm/thumb2-slow-flash-data.c b/gcc/testsuite/gcc.target/arm/thumb2-slow-flash-data.c new file mode 100644 index 00000000000..9852ea5d0bd --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/thumb2-slow-flash-data.c @@ -0,0 +1,74 @@ +/* The option -mslow-flash-data is just for performance tuning, it + doesn't totally disable the use of literal pools. But for below + simple cases, the use of literal pool should be replaced by + movw/movt or read-only constant pool. */ + +/* { dg-do compile } */ +/* { dg-require-effective-target arm_cortex_m } */ +/* { dg-require-effective-target arm_thumb2_ok } */ +/* { dg-options "-O2 -mthumb -mslow-flash-data" } */ + +float sf; +double df; +long long l; +static char *p = "Hello World"; + +float +testsf (float *p) +{ + if (*p > 1.1234f) + return 2.1234f; + else + return 3.1234f; +} + +double +testdf (double *p) +{ + if (*p > 4.1234) + return 2.1234; + else + return 3.1234; +} + +long long +testll (long long *p) +{ + if (*p > 0x123456789ABCDEFll) + return 0x111111111ll; + else + return 0x222222222ll; +} + +char * +testchar () +{ + return p + 4; +} + +int +foo (int a, int b) +{ + int i; + volatile *labelref = &&label1; + + if (a > b) + { + while (i < b) + { + a += *labelref; + i += 1; + } + goto *labelref; + } + else + b = b + 3; + + a = a * b; + +label1: + return a + b; +} + +/* { dg-final { scan-assembler-times "movt" 13 } } */ +/* { dg-final { scan-assembler-times "movt.*LC0\\+4" 1 } } */ diff --git a/gcc/testsuite/gcc.target/arm/vrinta-ce.c b/gcc/testsuite/gcc.target/arm/vrinta-ce.c new file mode 100644 index 00000000000..71c5b3b0e37 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/vrinta-ce.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_v8_vfp_ok } */ +/* { dg-options "-O2 -marm -march=armv8-a" } */ +/* { dg-add-options arm_v8_vfp } */ + +double foo (double a) +{ + if (a > 3.0) + return __builtin_round (a); + + return 0.0; +} + +/* { dg-final { scan-assembler-times "vrinta.f64\td\[0-9\]+" 1 } } */ + diff --git a/gcc/testsuite/gcc.target/i386/i386.exp b/gcc/testsuite/gcc.target/i386/i386.exp index 15f744cf2de..c7c26766bc2 100644 --- a/gcc/testsuite/gcc.target/i386/i386.exp +++ b/gcc/testsuite/gcc.target/i386/i386.exp @@ -209,18 +209,6 @@ proc check_effective_target_lzcnt { } { } "-mlzcnt" ] } -# Return 1 if avx2 instructions can be compiled. -proc check_effective_target_avx2 { } { - return [check_no_compiler_messages avx2 object { - typedef long long __v4di __attribute__ ((__vector_size__ (32))); - __v4di - mm256_is32_andnotsi256 (__v4di __X, __v4di __Y) - { - return __builtin_ia32_andnotsi256 (__X, __Y); - } - } "-O0 -mavx2" ] -} - # Return 1 if bmi instructions can be compiled. proc check_effective_target_bmi { } { return [check_no_compiler_messages bmi object { diff --git a/gcc/testsuite/gcc.target/i386/pr57293.c b/gcc/testsuite/gcc.target/i386/pr57293.c new file mode 100644 index 00000000000..fa016d55f25 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr57293.c @@ -0,0 +1,20 @@ +/* { dg-do compile { target { ia32 } } } */ +/* { dg-options "-O2 -fomit-frame-pointer" } */ +/* { dg-final { scan-assembler-not "%ebp" } } */ + +__attribute__((__noinline__, __noclone__, __stdcall__)) void g(int a) +{ + __builtin_printf("in g(): %d\n", a); +} + +__attribute__((__noinline__, __noclone__, __thiscall__)) void h(int a, int b) +{ + __builtin_printf("in h(): %d %d\n", a, b); +} + +void f() +{ + g(0); + h(0, 1); + __builtin_puts("in f()"); +} diff --git a/gcc/testsuite/gcc.target/i386/pr57410.c b/gcc/testsuite/gcc.target/i386/pr57410.c new file mode 100644 index 00000000000..6ca65d00030 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr57410.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fpeel-loops" } */ + +extern char outbuffer[]; +extern char buffer[]; + +void foo(int j) +{ + unsigned i, fp = fp; + for (i = 0; i < 6; i++) + buffer[j++] = outbuffer[fp - i]; +} diff --git a/gcc/testsuite/gcc.target/i386/pr58944.c b/gcc/testsuite/gcc.target/i386/pr58944.c new file mode 100644 index 00000000000..8164cf99508 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr58944.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-Wunused-macros -march=native" } */ + +#pragma GCC push_options +#pragma GCC target("xsaveopt") +void fn1(void) {} +#pragma GCC pop_options + +/* { dg-prune-output "macro \"__code_model_" } */ +/* { dg-prune-output "macro \"__XSAVE__\" is not used" } */ +/* { dg-prune-output "macro \"__XSAVEOPT__\" is not used" } */ diff --git a/gcc/testsuite/gcc.target/i386/pr59363.c b/gcc/testsuite/gcc.target/i386/pr59363.c new file mode 100644 index 00000000000..a4e12403543 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr59363.c @@ -0,0 +1,24 @@ +/* PR target/59363 */ +/* { dg-do run } */ +/* { dg-options "-O2 -mtune=amdfam10" } */ + +typedef struct { + int ctxlen; + long interhunkctxlen; + int flags; + long find_func; + void *find_func_priv; + int hunk_func; +} xdemitconf_t; + +__attribute__((noinline)) +int xdi_diff(xdemitconf_t *xecfg) { + if (xecfg->hunk_func == 0) + __builtin_abort(); + return 0; +} +int main() { + xdemitconf_t xecfg = {0}; + xecfg.hunk_func = 1; + return xdi_diff(&xecfg); +} diff --git a/gcc/testsuite/gcc.target/i386/xop-frczX.c b/gcc/testsuite/gcc.target/i386/xop-frczX.c new file mode 100644 index 00000000000..931b5ce397b --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/xop-frczX.c @@ -0,0 +1,60 @@ +/* { dg-do run } */ +/* { dg-require-effective-target xop } */ +/* { dg-options "-O2 -mxop" } */ + +#include "xop-check.h" + +#include <x86intrin.h> + +void +check_mm_vmfrcz_sd (__m128d __A, __m128d __B) +{ + union128d a, b, c; + double d[2]; + + a.x = __A; + b.x = __B; + c.x = _mm_frcz_sd (__A, __B); + d[0] = b.a[0] - (int)b.a[0] ; + d[1] = a.a[1]; + if (check_union128d (c, d)) + abort (); +} + +void +check_mm_vmfrcz_ss (__m128 __A, __m128 __B) +{ + union128 a, b, c; + float f[4]; + + a.x = __A; + b.x = __B; + c.x = _mm_frcz_ss (__A, __B); + f[0] = b.a[0] - (int)b.a[0] ; + f[1] = a.a[1]; + f[2] = a.a[2]; + f[3] = a.a[3]; + if (check_union128 (c, f)) + abort (); +} + +static void +xop_test (void) +{ + union128 a, b; + union128d c,d; + int i; + + for (i = 0; i < 4; i++) + { + a.a[i] = i + 3.5; + b.a[i] = i + 7.9; + } + for (i = 0; i < 2; i++) + { + c.a[i] = i + 3.5; + d.a[i] = i + 7.987654321; + } + check_mm_vmfrcz_ss (a.x, b.x); + check_mm_vmfrcz_sd (c.x, d.x); +} diff --git a/gcc/testsuite/gcc.target/nds32/basic-main.c b/gcc/testsuite/gcc.target/nds32/basic-main.c new file mode 100644 index 00000000000..6fdbc357fbd --- /dev/null +++ b/gcc/testsuite/gcc.target/nds32/basic-main.c @@ -0,0 +1,9 @@ +/* This is a basic main function test program. */ + +/* { dg-do run } */ +/* { dg-options "-O0" } */ + +int main(void) +{ + return 0; +} diff --git a/gcc/testsuite/gcc.target/nds32/builtin-isb.c b/gcc/testsuite/gcc.target/nds32/builtin-isb.c new file mode 100644 index 00000000000..e65061bae0d --- /dev/null +++ b/gcc/testsuite/gcc.target/nds32/builtin-isb.c @@ -0,0 +1,11 @@ +/* Verify that we generate isb instruction with builtin function. */ + +/* { dg-do compile } */ +/* { dg-options "-O0" } */ +/* { dg-final { scan-assembler "\\tisb" } } */ + +void +test (void) +{ + __builtin_nds32_isb (); +} diff --git a/gcc/testsuite/gcc.target/nds32/builtin-isync.c b/gcc/testsuite/gcc.target/nds32/builtin-isync.c new file mode 100644 index 00000000000..3160e4ad385 --- /dev/null +++ b/gcc/testsuite/gcc.target/nds32/builtin-isync.c @@ -0,0 +1,12 @@ +/* Verify that we generate isync instruction with builtin function. */ + +/* { dg-do compile } */ +/* { dg-options "-O0" } */ +/* { dg-final { scan-assembler "\\tisync" } } */ + +void +test (void) +{ + int *addr = (int *) 0x53000000; + __builtin_nds32_isync (addr); +} diff --git a/gcc/testsuite/gcc.target/nds32/builtin-mfsr-mtsr.c b/gcc/testsuite/gcc.target/nds32/builtin-mfsr-mtsr.c new file mode 100644 index 00000000000..db4c55845c0 --- /dev/null +++ b/gcc/testsuite/gcc.target/nds32/builtin-mfsr-mtsr.c @@ -0,0 +1,17 @@ +/* Verify that we generate mfsr/mtsr instruction with builtin function. */ + +/* { dg-do compile } */ +/* { dg-options "-O0" } */ +/* { dg-final { scan-assembler "\\tmfsr" } } */ +/* { dg-final { scan-assembler "\\tmtsr" } } */ + +#include <nds32_intrinsic.h> + +void +test (void) +{ + int ipsw_value; + + ipsw_value = __builtin_nds32_mfsr (__NDS32_REG_IPSW__); + __builtin_nds32_mtsr (ipsw_value, __NDS32_REG_IPSW__); +} diff --git a/gcc/testsuite/gcc.target/nds32/builtin-mfusr-mtusr.c b/gcc/testsuite/gcc.target/nds32/builtin-mfusr-mtusr.c new file mode 100644 index 00000000000..3cfaab95114 --- /dev/null +++ b/gcc/testsuite/gcc.target/nds32/builtin-mfusr-mtusr.c @@ -0,0 +1,17 @@ +/* Verify that we generate mfusr/mtusr instruction with builtin function. */ + +/* { dg-do compile } */ +/* { dg-options "-O0" } */ +/* { dg-final { scan-assembler "\\tmfusr" } } */ +/* { dg-final { scan-assembler "\\tmtusr" } } */ + +#include <nds32_intrinsic.h> + +void +test (void) +{ + int itype_value; + + itype_value = __builtin_nds32_mfusr (__NDS32_REG_ITYPE__); + __builtin_nds32_mtusr (itype_value, __NDS32_REG_ITYPE__); +} diff --git a/gcc/testsuite/gcc.target/nds32/builtin-setgie-dis.c b/gcc/testsuite/gcc.target/nds32/builtin-setgie-dis.c new file mode 100644 index 00000000000..2dceed98ac8 --- /dev/null +++ b/gcc/testsuite/gcc.target/nds32/builtin-setgie-dis.c @@ -0,0 +1,11 @@ +/* Verify that we generate setgie.d instruction with builtin function. */ + +/* { dg-do compile } */ +/* { dg-options "-O0" } */ +/* { dg-final { scan-assembler "\\tsetgie.d" } } */ + +void +test (void) +{ + __builtin_nds32_setgie_dis (); +} diff --git a/gcc/testsuite/gcc.target/nds32/builtin-setgie-en.c b/gcc/testsuite/gcc.target/nds32/builtin-setgie-en.c new file mode 100644 index 00000000000..892887019c9 --- /dev/null +++ b/gcc/testsuite/gcc.target/nds32/builtin-setgie-en.c @@ -0,0 +1,11 @@ +/* Verify that we generate setgie.e instruction with builtin function. */ + +/* { dg-do compile } */ +/* { dg-options "-O0" } */ +/* { dg-final { scan-assembler "\\tsetgie.e" } } */ + +void +test (void) +{ + __builtin_nds32_setgie_en (); +} diff --git a/gcc/testsuite/gcc.target/nds32/nds32.exp b/gcc/testsuite/gcc.target/nds32/nds32.exp new file mode 100644 index 00000000000..e88d0222729 --- /dev/null +++ b/gcc/testsuite/gcc.target/nds32/nds32.exp @@ -0,0 +1,45 @@ +# Target test cases of Andes NDS32 cpu for GNU compiler +# Copyright (C) 2012-2013 Free Software Foundation, Inc. +# Contributed by Andes Technology Corporation. +# +# This file is part of GCC. +# +# GCC is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published +# by the Free Software Foundation; either version 3, or (at your +# option) any later version. +# +# GCC is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +# License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# <http://www.gnu.org/licenses/>. + +# GCC testsuite that uses the `dg.exp' driver. + +# Exit immediately if this isn't a nds32 target. +if ![istarget nds32*-*-*] then { + return +} + +# Load support procs. +load_lib gcc-dg.exp + +# If a testcase doesn't have special options, use these. +global DEFAULT_CFLAGS +if ![info exists DEFAULT_CFLAGS] then { + set DEFAULT_CFLAGS " -ansi -pedantic-errors" +} + +# Initialize `dg'. +dg-init + +# Main loop. +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]] \ + "" $DEFAULT_CFLAGS + +# All done. +dg-finish diff --git a/gcc/testsuite/gcc.target/powerpc/bool3-av.c b/gcc/testsuite/gcc.target/powerpc/bool3-av.c index 4ef82c8cd97..d4aac786b2c 100644 --- a/gcc/testsuite/gcc.target/powerpc/bool3-av.c +++ b/gcc/testsuite/gcc.target/powerpc/bool3-av.c @@ -1,4 +1,4 @@ -/* { dg-do compile { target { powerpc*-*-* } } } */ +/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */ /* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ /* { dg-require-effective-target powerpc_altivec_ok } */ /* { dg-options "-O2 -mcpu=power6 -mabi=altivec -maltivec -mno-vsx" } */ diff --git a/gcc/testsuite/gcc.target/powerpc/bool3-p7.c b/gcc/testsuite/gcc.target/powerpc/bool3-p7.c index a077ba5aea7..34e3c9e79dd 100644 --- a/gcc/testsuite/gcc.target/powerpc/bool3-p7.c +++ b/gcc/testsuite/gcc.target/powerpc/bool3-p7.c @@ -1,4 +1,4 @@ -/* { dg-do compile { target { powerpc*-*-* } } } */ +/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */ /* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ /* { dg-require-effective-target powerpc_vsx_ok } */ /* { dg-options "-O2 -mcpu=power7" } */ diff --git a/gcc/testsuite/gcc.target/powerpc/bool3-p8.c b/gcc/testsuite/gcc.target/powerpc/bool3-p8.c index 361a0452d7d..e1b2dfa7ee2 100644 --- a/gcc/testsuite/gcc.target/powerpc/bool3-p8.c +++ b/gcc/testsuite/gcc.target/powerpc/bool3-p8.c @@ -1,4 +1,4 @@ -/* { dg-do compile { target { powerpc*-*-* } } } */ +/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */ /* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ /* { dg-require-effective-target powerpc_p8vector_ok } */ /* { dg-options "-O2 -mcpu=power8" } */ diff --git a/gcc/testsuite/gcc.target/powerpc/direct-move-double1.c b/gcc/testsuite/gcc.target/powerpc/direct-move-double1.c index 534a04a937b..2569ac84369 100644 --- a/gcc/testsuite/gcc.target/powerpc/direct-move-double1.c +++ b/gcc/testsuite/gcc.target/powerpc/direct-move-double1.c @@ -3,13 +3,14 @@ /* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */ /* { dg-require-effective-target powerpc_p8vector_ok } */ /* { dg-options "-mcpu=power8 -O2" } */ -/* { dg-final { scan-assembler-times "mtvsrd" 1 } } */ -/* { dg-final { scan-assembler-times "mfvsrd" 1 } } */ +/* { dg-final { scan-assembler "mtvsrd" } } */ +/* { dg-final { scan-assembler "mfvsrd" } } */ -/* Check code generation for direct move for long types. */ +/* Check code generation for direct move for double types. */ #define TYPE double #define IS_FLOAT 1 #define NO_ALTIVEC 1 +#define VSX_REG_ATTR "ws" #include "direct-move.h" diff --git a/gcc/testsuite/gcc.target/powerpc/direct-move-double2.c b/gcc/testsuite/gcc.target/powerpc/direct-move-double2.c index 750debfc0df..c8702204b70 100644 --- a/gcc/testsuite/gcc.target/powerpc/direct-move-double2.c +++ b/gcc/testsuite/gcc.target/powerpc/direct-move-double2.c @@ -10,5 +10,6 @@ #define IS_FLOAT 1 #define NO_ALTIVEC 1 #define DO_MAIN +#define VSX_REG_ATTR "ws" #include "direct-move.h" diff --git a/gcc/testsuite/gcc.target/powerpc/direct-move-float1.c b/gcc/testsuite/gcc.target/powerpc/direct-move-float1.c index ff1e97c0d43..524c0eead43 100644 --- a/gcc/testsuite/gcc.target/powerpc/direct-move-float1.c +++ b/gcc/testsuite/gcc.target/powerpc/direct-move-float1.c @@ -3,15 +3,16 @@ /* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */ /* { dg-require-effective-target powerpc_p8vector_ok } */ /* { dg-options "-mcpu=power8 -O2" } */ -/* { dg-final { scan-assembler-times "mtvsrd" 2 } } */ -/* { dg-final { scan-assembler-times "mfvsrd" 2 } } */ -/* { dg-final { scan-assembler-times "xscvdpspn" 2 } } */ -/* { dg-final { scan-assembler-times "xscvspdpn" 2 } } */ +/* { dg-final { scan-assembler "mtvsrd" } } */ +/* { dg-final { scan-assembler "mfvsrd" } } */ +/* { dg-final { scan-assembler "xscvdpspn" } } */ +/* { dg-final { scan-assembler "xscvspdpn" } } */ -/* Check code generation for direct move for long types. */ +/* Check code generation for direct move for float types. */ #define TYPE float #define IS_FLOAT 1 #define NO_ALTIVEC 1 +#define VSX_REG_ATTR "ww" #include "direct-move.h" diff --git a/gcc/testsuite/gcc.target/powerpc/direct-move-float2.c b/gcc/testsuite/gcc.target/powerpc/direct-move-float2.c index ace728ff6d4..352e76166d0 100644 --- a/gcc/testsuite/gcc.target/powerpc/direct-move-float2.c +++ b/gcc/testsuite/gcc.target/powerpc/direct-move-float2.c @@ -10,5 +10,6 @@ #define IS_FLOAT 1 #define NO_ALTIVEC 1 #define DO_MAIN +#define VSX_REG_ATTR "ww" #include "direct-move.h" diff --git a/gcc/testsuite/gcc.target/powerpc/direct-move-long1.c b/gcc/testsuite/gcc.target/powerpc/direct-move-long1.c index 907e802c72b..0a78f9cb258 100644 --- a/gcc/testsuite/gcc.target/powerpc/direct-move-long1.c +++ b/gcc/testsuite/gcc.target/powerpc/direct-move-long1.c @@ -3,13 +3,14 @@ /* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */ /* { dg-require-effective-target powerpc_p8vector_ok } */ /* { dg-options "-mcpu=power8 -O2" } */ -/* { dg-final { scan-assembler-times "mtvsrd" 1 } } */ -/* { dg-final { scan-assembler-times "mfvsrd" 2 } } */ +/* { dg-final { scan-assembler "mtvsrd" } } */ +/* { dg-final { scan-assembler "mfvsrd" } } */ /* Check code generation for direct move for long types. */ #define TYPE long #define IS_INT 1 #define NO_ALTIVEC 1 +#define VSX_REG_ATTR "d" #include "direct-move.h" diff --git a/gcc/testsuite/gcc.target/powerpc/direct-move-long2.c b/gcc/testsuite/gcc.target/powerpc/direct-move-long2.c index fba613e4548..cee9e0e0f1d 100644 --- a/gcc/testsuite/gcc.target/powerpc/direct-move-long2.c +++ b/gcc/testsuite/gcc.target/powerpc/direct-move-long2.c @@ -10,5 +10,6 @@ #define IS_INT 1 #define NO_ALTIVEC 1 #define DO_MAIN +#define VSX_REG_ATTR "d" #include "direct-move.h" diff --git a/gcc/testsuite/gcc.target/powerpc/direct-move-vint1.c b/gcc/testsuite/gcc.target/powerpc/direct-move-vint1.c index cdfa18857f1..3067b9a8e62 100644 --- a/gcc/testsuite/gcc.target/powerpc/direct-move-vint1.c +++ b/gcc/testsuite/gcc.target/powerpc/direct-move-vint1.c @@ -3,11 +3,12 @@ /* { dg-skip-if "" { powerpc*-*-*spe* } { "*" } { "" } } */ /* { dg-require-effective-target powerpc_p8vector_ok } */ /* { dg-options "-mcpu=power8 -O2" } */ -/* { dg-final { scan-assembler-times "mtvsrd" 4 } } */ -/* { dg-final { scan-assembler-times "mfvsrd" 4 } } */ +/* { dg-final { scan-assembler "mtvsrd" } } */ +/* { dg-final { scan-assembler "mfvsrd" } } */ -/* Check code generation for direct move for long types. */ +/* Check code generation for direct move for vector types. */ #define TYPE vector int +#define VSX_REG_ATTR "wa" #include "direct-move.h" diff --git a/gcc/testsuite/gcc.target/powerpc/direct-move-vint2.c b/gcc/testsuite/gcc.target/powerpc/direct-move-vint2.c index 5c0c9abdac5..0d8264faf71 100644 --- a/gcc/testsuite/gcc.target/powerpc/direct-move-vint2.c +++ b/gcc/testsuite/gcc.target/powerpc/direct-move-vint2.c @@ -8,5 +8,6 @@ #define TYPE vector int #define DO_MAIN +#define VSX_REG_ATTR "wa" #include "direct-move.h" diff --git a/gcc/testsuite/gcc.target/powerpc/direct-move.h b/gcc/testsuite/gcc.target/powerpc/direct-move.h index c1709e6c7ef..6a5b7ba1806 100644 --- a/gcc/testsuite/gcc.target/powerpc/direct-move.h +++ b/gcc/testsuite/gcc.target/powerpc/direct-move.h @@ -3,6 +3,10 @@ #include <math.h> extern void abort (void); +#ifndef VSX_REG_ATTR +#define VSX_REG_ATTR "wa" +#endif + void __attribute__((__noinline__)) copy (TYPE *a, TYPE *b) { @@ -44,7 +48,7 @@ void __attribute__((__noinline__)) load_vsx (TYPE *a, TYPE *b) { TYPE c = *a; - __asm__ ("# vsx, reg = %x0" : "+wa" (c)); + __asm__ ("# vsx, reg = %x0" : "+" VSX_REG_ATTR (c)); *b = c; } #endif @@ -57,7 +61,7 @@ load_gpr_to_vsx (TYPE *a, TYPE *b) TYPE d; __asm__ ("# gpr, reg = %0" : "+b" (c)); d = c; - __asm__ ("# vsx, reg = %x0" : "+wa" (d)); + __asm__ ("# vsx, reg = %x0" : "+" VSX_REG_ATTR (d)); *b = d; } #endif @@ -68,7 +72,7 @@ load_vsx_to_gpr (TYPE *a, TYPE *b) { TYPE c = *a; TYPE d; - __asm__ ("# vsx, reg = %x0" : "+wa" (c)); + __asm__ ("# vsx, reg = %x0" : "+" VSX_REG_ATTR (c)); d = c; __asm__ ("# gpr, reg = %0" : "+b" (d)); *b = d; diff --git a/gcc/testsuite/gcc.target/powerpc/p8vector-ldst.c b/gcc/testsuite/gcc.target/powerpc/p8vector-ldst.c index d0b3eb09ef7..33f19991f76 100644 --- a/gcc/testsuite/gcc.target/powerpc/p8vector-ldst.c +++ b/gcc/testsuite/gcc.target/powerpc/p8vector-ldst.c @@ -36,7 +36,7 @@ void store_df (double *p, double d) *p = d; } -/* { dg-final { scan-assembler-times "lxsspx" 2 } } */ -/* { dg-final { scan-assembler-times "lxsdx" 1 } } */ -/* { dg-final { scan-assembler-times "stxsspx" 1 } } */ -/* { dg-final { scan-assembler-times "stxsdx" 1 } } */ +/* { dg-final { scan-assembler "lxsspx" } } */ +/* { dg-final { scan-assembler "lxsdx" } } */ +/* { dg-final { scan-assembler "stxsspx" } } */ +/* { dg-final { scan-assembler "stxsdx" } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/pr57363.c b/gcc/testsuite/gcc.target/powerpc/pr57363.c new file mode 100644 index 00000000000..45ea3f3fe61 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr57363.c @@ -0,0 +1,19 @@ +/* { dg-do run { target { powerpc*-*-linux* } } } */ +/* { dg-options "-mlong-double-128" } */ + +/* Check if adding a qNAN and a normal long double does not generate a + inexact exception. */ + +#define _GNU_SOURCE +#include <fenv.h> + +int main(void) +{ + double x = __builtin_nan (""); + long double y = 1.1L; + + feenableexcept (FE_INEXACT); + feclearexcept (FE_ALL_EXCEPT); + x = x + y; + return fetestexcept(FE_INEXACT); +} diff --git a/gcc/testsuite/gcc.target/powerpc/pr59054.c b/gcc/testsuite/gcc.target/powerpc/pr59054.c index 0379aeee635..052f238ba0e 100644 --- a/gcc/testsuite/gcc.target/powerpc/pr59054.c +++ b/gcc/testsuite/gcc.target/powerpc/pr59054.c @@ -4,15 +4,3 @@ /* { dg-options "-mcpu=power7 -O0 -m64" } */ long foo (void) { return 0; } - -/* { dg-final { scan-assembler-not "xxlor" } } */ -/* { dg-final { scan-assembler-not "stfd" } } */ -/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */ -/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */ -/* { dg-require-effective-target powerpc_vsx_ok } */ -/* { dg-options "-mcpu=power7 -O0 -m64" } */ - -long foo (void) { return 0; } - -/* { dg-final { scan-assembler-not "xxlor" } } */ -/* { dg-final { scan-assembler-not "stfd" } } */ diff --git a/gcc/testsuite/gfortran.dg/asynchronous_4.f90 b/gcc/testsuite/gfortran.dg/asynchronous_4.f90 new file mode 100644 index 00000000000..ca6cd6c0265 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/asynchronous_4.f90 @@ -0,0 +1,22 @@ +! { dg-do compile } +! +! PR 59228: ICE with assumed type and ASYNCHRONOUS +! +! Contributed by Valery Weber <valeryweber@hotmail.com> + + IMPLICIT NONE + + interface + subroutine test(base) + TYPE(*), ASYNCHRONOUS :: base + end subroutine + end interface + +CONTAINS + + SUBROUTINE foo ( data ) + REAL, DIMENSION( : ), ASYNCHRONOUS :: data + CALL test ( data ) ! { dg-error "Rank mismatch in argument" } + END SUBROUTINE + +END diff --git a/gcc/testsuite/gfortran.dg/c_loc_test_22.f90 b/gcc/testsuite/gfortran.dg/c_loc_test_22.f90 index 5263060be75..2eea2a52777 100644 --- a/gcc/testsuite/gfortran.dg/c_loc_test_22.f90 +++ b/gcc/testsuite/gfortran.dg/c_loc_test_22.f90 @@ -21,4 +21,4 @@ end ! { dg-final { scan-tree-dump-times "parm.\[0-9\]+.data = \\(void .\\) &\\(.yyy.\[0-9\]+\\)\\\[D.\[0-9\]+ \\* 4\\\];" 1 "original" } } ! { dg-final { scan-tree-dump-times "D.\[0-9\]+ = parm.\[0-9\]+.data;\[^;]+ptr\[1-4\] = D.\[0-9\]+;" 4 "original" } } -! { dg-final { cleanup-tree-dump "optimized" } } +! { dg-final { cleanup-tree-dump "original" } } diff --git a/gcc/testsuite/gfortran.dg/nan_7.f90 b/gcc/testsuite/gfortran.dg/nan_7.f90 index 12c7b3ce40f..4c2f62eeaed 100644 --- a/gcc/testsuite/gfortran.dg/nan_7.f90 +++ b/gcc/testsuite/gfortran.dg/nan_7.f90 @@ -2,6 +2,7 @@ ! { dg-options "-fno-range-check" } ! { dg-require-effective-target fortran_real_16 } ! { dg-require-effective-target fortran_integer_16 } +! { dg-skip-if "" { "powerpc*le-*-*" } { "*" } { "" } } ! PR47293 NAN not correctly read character(len=200) :: str real(16) :: r diff --git a/gcc/testsuite/gfortran.dg/null_5.f90 b/gcc/testsuite/gfortran.dg/null_5.f90 index 886a6a1ff8b..50b41c3e8bf 100644 --- a/gcc/testsuite/gfortran.dg/null_5.f90 +++ b/gcc/testsuite/gfortran.dg/null_5.f90 @@ -34,7 +34,7 @@ subroutine test_PR34547_1 () end subroutine test_PR34547_1 subroutine test_PR34547_2 () - print *, null () ! { dg-error "in data transfer statement requires MOLD" } + print *, null () ! { dg-error "Invalid context" } end subroutine test_PR34547_2 subroutine test_PR34547_3 () diff --git a/gcc/testsuite/gfortran.dg/null_6.f90 b/gcc/testsuite/gfortran.dg/null_6.f90 index dd517cfa3e2..6b8f21e63bc 100644 --- a/gcc/testsuite/gfortran.dg/null_6.f90 +++ b/gcc/testsuite/gfortran.dg/null_6.f90 @@ -30,5 +30,5 @@ end subroutine test_PR50375_2 subroutine test_PR34547_3 () integer, allocatable :: i(:) - print *, NULL(i) + print *, NULL(i) ! { dg-error "Invalid context for NULL" } end subroutine test_PR34547_3 diff --git a/gcc/testsuite/gfortran.dg/pr57393-1.f90 b/gcc/testsuite/gfortran.dg/pr57393-1.f90 new file mode 100644 index 00000000000..6b2cb1b3fe6 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr57393-1.f90 @@ -0,0 +1,38 @@ +! PR middle-end/57393 +! { dg-do compile } +! { dg-options "-g -O2 -ffast-math" } + +SUBROUTINE pr57393(nn,e,g,t0,t1,t2,t3,t4,t5,t6,t7,& + t8,t9,t10,t11,t12,t13,t14,t15,& + t16,t17,t18,t19,t20,t21,t22,t23,& + t24,t25,t26,t27,t28,t29,t30,& + t31,t32,t33,t34,t35,t36,t37,t38,& + t39,t40,t41,t42,t43,t44,t45,t46,t47) + IMPLICIT REAL*8 (t) + INTEGER, PARAMETER :: dp=8 + REAL(kind=dp) :: e(nn) + DO ii=1,nn + t48 = 0.1955555555e2_dp * t1 * t2 + & + 0.6000000000e1_dp * t3 * t4 * t5 + t49 = 0.1620000000e3_dp * t6 * t7 * t8 + & + 0.1080000000e3_dp * t6 * t9 * t5 - & + 0.6000000000e1_dp * t10 * t20 * t21 * t55 - & + 0.2400000000e2_dp * t10 * t11 * t12 - & + 0.1200000000e2_dp * t13 * t14 * t15 + t50 = t49 + t16 + t51 = (3 * t17 * t18 * t19) + & + (t22 * t23 * t19) + (t50 * t19) - & + 0.3333333336e0_dp * t24 * t25 + t52 = 0.1555555556e1_dp * t26 * t27 * t12 + & + (t51 + t28 + t29 + t30) * & + 0.3125000000e0_dp * t31 * t32 * t33 * t34 + t53 = -0.1000000001e1_dp * t35 * t36 * t5 - & + (t37 + t38 + t39 + t52) - & + 0.8333333340e-1_dp * t40 * t41 * t42 + t54 = -0.1000000001e1_dp * t43 * t44 * t45 - & + t47 * (t46 + t53) + IF (g >= 3 .OR. g == -3) THEN + e(ii) = e(ii) + t54 * t0 + END IF + END DO +END SUBROUTINE pr57393 diff --git a/gcc/testsuite/gfortran.dg/pr57393-2.f90 b/gcc/testsuite/gfortran.dg/pr57393-2.f90 new file mode 100644 index 00000000000..fafa8f900f1 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr57393-2.f90 @@ -0,0 +1,10 @@ +! PR middle-end/57393 +! { dg-do compile } +! { dg-options "-g -O2" } + +SUBROUTINE pr57393 ( a1, a2, a3, a4, a5, a6, a7 ) + COMPLEX(kind=8), DIMENSION(:), INTENT(IN) :: a1 + INTEGER, DIMENSION(:), INTENT(IN) :: a2, a3, a5, a6 + COMPLEX(kind=8), DIMENSION(:), INTENT(INOUT) :: a4 + a4(a6(1)+1:a6(1)+a5(1))=a1(a3(1)+1:a3(1)+a2(1)) +END SUBROUTINE pr57393 diff --git a/gcc/testsuite/gfortran.dg/realloc_on_assign_23.f90 b/gcc/testsuite/gfortran.dg/realloc_on_assign_23.f90 new file mode 100644 index 00000000000..f9897f17401 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/realloc_on_assign_23.f90 @@ -0,0 +1,30 @@ +! { dg-do run } +! +! PR fortran/57354 +! +! Contributed by Vladimir Fuka <vladimir.fuka@gmail.com> +! + type t + integer,allocatable :: i + end type + + type(t) :: e + type(t), allocatable :: a(:) + integer :: chksum = 0 + + do i=1,3 ! Was 100 in original + e%i = i + chksum = chksum + i + if (.not.allocated(a)) then + a = [e] + else + call foo + end if + end do + + if (sum ([(a(i)%i, i=1,size(a))]) .ne. chksum) call abort +contains + subroutine foo + a = [a, e] + end subroutine +end diff --git a/gcc/testsuite/gfortran.dg/typebound_proc_30.f90 b/gcc/testsuite/gfortran.dg/typebound_proc_30.f90 new file mode 100644 index 00000000000..09b07261089 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/typebound_proc_30.f90 @@ -0,0 +1,38 @@ +! { dg-do compile } +! +! PR 59143: [OOP] Bogus warning with array-valued type-bound procedure +! +! Contributed by Jürgen Reuter <juergen.reuter@desy.de> + +module phs_single + + type :: phs_single_t + contains + procedure, nopass :: d1, d2 + end type + +contains + + subroutine evaluate (phs) + class(phs_single_t) :: phs + call func1 (phs%d1 ()) + call func1 (phs%d2 (2)) + end subroutine + + subroutine func1 (p) + real :: p(2) + end subroutine + + function d1 () + real :: d1(2) + d1 = 1. + end function + + function d2 (n) + real :: d2(n) + d2 = 1. + end function + +end module + +! { dg-final { cleanup-modules "phs_single" } } diff --git a/gcc/testsuite/gnat.dg/opt29.adb b/gcc/testsuite/gnat.dg/opt29.adb new file mode 100644 index 00000000000..64f2baef3d0 --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt29.adb @@ -0,0 +1,13 @@ +-- { dg-do compile }
+-- { dg-options "-O" }
+
+package body Opt29 is
+
+ procedure Proc (T : Rec) is
+ begin
+ if Derived2 (T.F2.all).Id = T.F1.Id then
+ raise Program_Error;
+ end if;
+ end;
+
+end Opt29;
diff --git a/gcc/testsuite/gnat.dg/opt29.ads b/gcc/testsuite/gnat.dg/opt29.ads new file mode 100644 index 00000000000..c809b1c4193 --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt29.ads @@ -0,0 +1,28 @@ +package Opt29 is
+
+ type Word is mod 2**16;
+
+ type PID is record
+ W1, W2: Word;
+ end record;
+
+ type Root1 is tagged record
+ Id: PID;
+ end record;
+ type Root1_Ptr is access all Root1'Class;
+
+ type Root2 is tagged null record;
+ type Root2_Ptr is access all Root2'class;
+
+ type Derived2 is new Root2 with record
+ Id: PID;
+ end record;
+
+ type Rec is record
+ F1: Root1_Ptr;
+ F2: Root2_Ptr;
+ end record;
+
+ procedure Proc (T : Rec);
+
+end Opt29;
diff --git a/gcc/testsuite/gnat.dg/opt30.adb b/gcc/testsuite/gnat.dg/opt30.adb new file mode 100644 index 00000000000..12139c555c4 --- /dev/null +++ b/gcc/testsuite/gnat.dg/opt30.adb @@ -0,0 +1,20 @@ +-- { dg-do run } +-- { dg-options "-O" } + +procedure Opt30 is + + function Id_I (I : Integer) return Integer is + begin + return I; + end; + + A : array (Integer range -4..4) of Integer; + +begin + A := (-ID_I(4), -ID_I(3), -ID_I(2), -ID_I(1), ID_I(100), + ID_I(1), ID_I(2), ID_I(3), ID_I(4)); + A(-4..0) := A(0..4); + if A /= (100, 1, 2, 3, 4, 1, 2, 3, 4) then + raise Program_Error; + end if; +end; diff --git a/gcc/testsuite/lib/asan-dg.exp b/gcc/testsuite/lib/asan-dg.exp index e0bf2da2e78..8990677d51e 100644 --- a/gcc/testsuite/lib/asan-dg.exp +++ b/gcc/testsuite/lib/asan-dg.exp @@ -41,6 +41,7 @@ proc asan_link_flags { paths } { if { $gccpath != "" } { if { [file exists "${gccpath}/libsanitizer/asan/.libs/libasan.a"] || [file exists "${gccpath}/libsanitizer/asan/.libs/libasan.${shlib_ext}"] } { + append flags " -B${gccpath}/libsanitizer/ " append flags " -B${gccpath}/libsanitizer/asan/ " append flags " -L${gccpath}/libsanitizer/asan/.libs " append ld_library_path ":${gccpath}/libsanitizer/asan/.libs" diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index 104818d327e..642c3448bda 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -530,6 +530,7 @@ proc check_profiling_available { test_what } { || [istarget mn10300-*-elf*] || [istarget moxie-*-elf*] || [istarget msp430-*-*] + || [istarget nds32*-*-elf] || [istarget picochip-*-*] || [istarget powerpc-*-eabi*] || [istarget powerpc-*-elf] @@ -2146,6 +2147,32 @@ proc check_effective_target_vect_floatuint_cvt { } { return $et_vect_floatuint_cvt_saved } +# Return 1 if the target supports #pragma omp declare simd, 0 otherwise. +# +# This won't change for different subtargets so cache the result. + +proc check_effective_target_vect_simd_clones { } { + global et_vect_simd_clones_saved + + if [info exists et_vect_simd_clones_saved] { + verbose "check_effective_target_vect_simd_clones: using cached result" 2 + } else { + set et_vect_simd_clones_saved 0 + if { [istarget i?86-*-*] || [istarget x86_64-*-*] } { + # On i?86/x86_64 #pragma omp declare simd builds a sse2, avx and + # avx2 clone. Only the right clone for the specified arch will be + # chosen, but still we need to at least be able to assemble + # avx2. + if { [check_effective_target_avx2] } { + set et_vect_simd_clones_saved 1 + } + } + } + + verbose "check_effective_target_vect_simd_clones: returning $et_vect_simd_clones_saved" 2 + return $et_vect_simd_clones_saved +} + # Return 1 if this is a AArch64 target supporting big endian proc check_effective_target_aarch64_big_endian { } { return [check_no_compiler_messages aarch64_big_endian assembly { @@ -5106,6 +5133,18 @@ proc check_effective_target_avx { } { } "-O2 -mavx" ] } +# Return 1 if avx2 instructions can be compiled. +proc check_effective_target_avx2 { } { + return [check_no_compiler_messages avx2 object { + typedef long long __v4di __attribute__ ((__vector_size__ (32))); + __v4di + mm256_is32_andnotsi256 (__v4di __X, __v4di __Y) + { + return __builtin_ia32_andnotsi256 (__X, __Y); + } + } "-O0 -mavx2" ] +} + # Return 1 if sse instructions can be compiled. proc check_effective_target_sse { } { return [check_no_compiler_messages sse object { diff --git a/gcc/testsuite/lib/ubsan-dg.exp b/gcc/testsuite/lib/ubsan-dg.exp index 4ec5fdfad67..aa01988f976 100644 --- a/gcc/testsuite/lib/ubsan-dg.exp +++ b/gcc/testsuite/lib/ubsan-dg.exp @@ -32,6 +32,7 @@ proc ubsan_link_flags { paths } { if { $gccpath != "" } { if { [file exists "${gccpath}/libsanitizer/ubsan/.libs/libubsan.a"] || [file exists "${gccpath}/libsanitizer/ubsan/.libs/libubsan.${shlib_ext}"] } { + append flags " -B${gccpath}/libsanitizer/ " append flags " -B${gccpath}/libsanitizer/ubsan/ " append flags " -L${gccpath}/libsanitizer/ubsan/.libs" append ld_library_path ":${gccpath}/libsanitizer/ubsan/.libs" diff --git a/gcc/toplev.c b/gcc/toplev.c index 5fedcea9002..91a08ae1d7c 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -46,9 +46,7 @@ along with GCC; see the file COPYING3. If not see #include "function.h" #include "toplev.h" #include "expr.h" -#include "basic-block.h" #include "intl.h" -#include "ggc.h" #include "regs.h" #include "timevar.h" #include "diagnostic.h" @@ -72,8 +70,10 @@ along with GCC; see the file COPYING3. If not see #include "alloc-pool.h" #include "asan.h" #include "tsan.h" -#include "gimple.h" #include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "gimple.h" #include "plugin.h" #include "diagnostic-color.h" #include "context.h" @@ -1284,12 +1284,6 @@ process_options (void) "and -ftree-loop-linear)"); #endif - if (flag_check_pointer_bounds) - { - if (targetm.chkp_bound_mode () == VOIDmode) - error ("-fcheck-pointers is not supported for this target"); - } - /* One region RA really helps to decrease the code size. */ if (flag_ira_region == IRA_REGION_AUTODETECT) flag_ira_region diff --git a/gcc/tracer.c b/gcc/tracer.c index 1ff89c56b75..996895006f4 100644 --- a/gcc/tracer.c +++ b/gcc/tracer.c @@ -46,6 +46,10 @@ #include "params.h" #include "coverage.h" #include "tree-pass.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "tree-cfg.h" diff --git a/gcc/trans-mem.c b/gcc/trans-mem.c index 9e6f4d9cec7..31dee7678d2 100644 --- a/gcc/trans-mem.c +++ b/gcc/trans-mem.c @@ -22,6 +22,12 @@ #include "coretypes.h" #include "hash-table.h" #include "tree.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "calls.h" #include "function.h" diff --git a/gcc/tree-affine.c b/gcc/tree-affine.c index 615ae98f1b9..d97a426c9e4 100644 --- a/gcc/tree-affine.c +++ b/gcc/tree-affine.c @@ -25,6 +25,11 @@ along with GCC; see the file COPYING3. If not see #include "tree-pretty-print.h" #include "pointer-set.h" #include "tree-affine.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "flags.h" diff --git a/gcc/tree-call-cdce.c b/gcc/tree-call-cdce.c index 72be0a9cd3f..df0c4894130 100644 --- a/gcc/tree-call-cdce.c +++ b/gcc/tree-call-cdce.c @@ -26,6 +26,10 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "stor-layout.h" #include "gimple-pretty-print.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimple-ssa.h" diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index 9ec7b4aa33e..177a049aaf6 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -31,8 +31,14 @@ along with GCC; see the file COPYING3. If not see #include "basic-block.h" #include "flags.h" #include "function.h" -#include "ggc.h" #include "gimple-pretty-print.h" +#include "pointer-set.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimplify-me.h" @@ -57,7 +63,6 @@ along with GCC; see the file COPYING3. If not see #include "cfgloop.h" #include "tree-ssa-propagate.h" #include "value-prof.h" -#include "pointer-set.h" #include "tree-inline.h" #include "target.h" #include "tree-ssa-live.h" @@ -2709,15 +2714,18 @@ verify_expr (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED) if (TREE_CODE (t) == BIT_FIELD_REF) { - if (!tree_fits_uhwi_p (TREE_OPERAND (t, 1)) - || !tree_fits_uhwi_p (TREE_OPERAND (t, 2))) + tree t0 = TREE_OPERAND (t, 0); + tree t1 = TREE_OPERAND (t, 1); + tree t2 = TREE_OPERAND (t, 2); + if (!tree_fits_uhwi_p (t1) + || !tree_fits_uhwi_p (t2)) { error ("invalid position or size operand to BIT_FIELD_REF"); return t; } if (INTEGRAL_TYPE_P (TREE_TYPE (t)) && (TYPE_PRECISION (TREE_TYPE (t)) - != tree_to_uhwi (TREE_OPERAND (t, 1)))) + != tree_to_uhwi (t1))) { error ("integral result type precision does not match " "field size of BIT_FIELD_REF"); @@ -2726,12 +2734,20 @@ verify_expr (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED) else if (!INTEGRAL_TYPE_P (TREE_TYPE (t)) && TYPE_MODE (TREE_TYPE (t)) != BLKmode && (GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (t))) - != tree_to_uhwi (TREE_OPERAND (t, 1)))) + != tree_to_uhwi (t1))) { error ("mode precision of non-integral result does not " "match field size of BIT_FIELD_REF"); return t; } + if (!AGGREGATE_TYPE_P (TREE_TYPE (t0)) + && (tree_to_uhwi (t1) + tree_to_uhwi (t2) + > tree_to_uhwi (TYPE_SIZE (TREE_TYPE (t0))))) + { + error ("position plus size exceeds size of referenced object in " + "BIT_FIELD_REF"); + return t; + } } t = TREE_OPERAND (t, 0); @@ -6526,7 +6542,7 @@ move_block_to_fn (struct function *dest_cfun, basic_block bb, /* We cannot leave any operands allocated from the operand caches of the current function. */ - free_stmt_operands (stmt); + free_stmt_operands (cfun, stmt); push_cfun (dest_cfun); update_stmt (stmt); pop_cfun (); diff --git a/gcc/tree-cfgcleanup.c b/gcc/tree-cfgcleanup.c index 5ae70abc29e..ab8a394a150 100644 --- a/gcc/tree-cfgcleanup.c +++ b/gcc/tree-cfgcleanup.c @@ -27,8 +27,12 @@ along with GCC; see the file COPYING3. If not see #include "diagnostic-core.h" #include "flags.h" #include "function.h" -#include "ggc.h" #include "langhooks.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "gimple-iterator.h" diff --git a/gcc/tree-chrec.c b/gcc/tree-chrec.c index 91a14e41f53..8f101ee0f0a 100644 --- a/gcc/tree-chrec.c +++ b/gcc/tree-chrec.c @@ -29,7 +29,8 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "tree-pretty-print.h" #include "cfgloop.h" -#include "gimple.h" +#include "basic-block.h" +#include "gimple-expr.h" #include "tree-ssa-loop-ivopts.h" #include "tree-ssa-loop-niter.h" #include "tree-chrec.h" diff --git a/gcc/tree-complex.c b/gcc/tree-complex.c index 7bc3458165f..80a978e52dd 100644 --- a/gcc/tree-complex.c +++ b/gcc/tree-complex.c @@ -24,6 +24,12 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "stor-layout.h" #include "flags.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "gimple-iterator.h" diff --git a/gcc/tree-core.h b/gcc/tree-core.h index e31d9b38f23..704c70c28ed 100644 --- a/gcc/tree-core.h +++ b/gcc/tree-core.h @@ -350,7 +350,8 @@ enum omp_clause_schedule_kind { OMP_CLAUSE_SCHEDULE_DYNAMIC, OMP_CLAUSE_SCHEDULE_GUIDED, OMP_CLAUSE_SCHEDULE_AUTO, - OMP_CLAUSE_SCHEDULE_RUNTIME + OMP_CLAUSE_SCHEDULE_RUNTIME, + OMP_CLAUSE_SCHEDULE_LAST }; enum omp_clause_default_kind { @@ -358,7 +359,8 @@ enum omp_clause_default_kind { OMP_CLAUSE_DEFAULT_SHARED, OMP_CLAUSE_DEFAULT_NONE, OMP_CLAUSE_DEFAULT_PRIVATE, - OMP_CLAUSE_DEFAULT_FIRSTPRIVATE + OMP_CLAUSE_DEFAULT_FIRSTPRIVATE, + OMP_CLAUSE_DEFAULT_LAST }; /* There is a TYPE_QUAL value for each type qualifier. They can be @@ -455,8 +457,6 @@ enum tree_index { TI_FILEPTR_TYPE, TI_POINTER_SIZED_TYPE, - TI_POINTER_BOUNDS_TYPE, - TI_DFLOAT32_TYPE, TI_DFLOAT64_TYPE, TI_DFLOAT128_TYPE, @@ -926,6 +926,9 @@ struct GTY(()) tree_base { CALL_ALLOCA_FOR_VAR_P in CALL_EXPR + OMP_CLAUSE_LINEAR_VARIABLE_STRIDE in + OMP_CLAUSE_LINEAR + side_effects_flag: TREE_SIDE_EFFECTS in @@ -1127,7 +1130,8 @@ enum omp_clause_depend_kind { OMP_CLAUSE_DEPEND_IN, OMP_CLAUSE_DEPEND_OUT, - OMP_CLAUSE_DEPEND_INOUT + OMP_CLAUSE_DEPEND_INOUT, + OMP_CLAUSE_DEPEND_LAST }; enum omp_clause_map_kind @@ -1139,7 +1143,8 @@ enum omp_clause_map_kind /* The following kind is an internal only map kind, used for pointer based array sections. OMP_CLAUSE_SIZE for these is not the pointer size, which is implicitly POINTER_SIZE / BITS_PER_UNIT, but the bias. */ - OMP_CLAUSE_MAP_POINTER + OMP_CLAUSE_MAP_POINTER, + OMP_CLAUSE_MAP_LAST }; enum omp_clause_proc_bind_kind @@ -1149,7 +1154,8 @@ enum omp_clause_proc_bind_kind OMP_CLAUSE_PROC_BIND_TRUE = 1, OMP_CLAUSE_PROC_BIND_MASTER = 2, OMP_CLAUSE_PROC_BIND_CLOSE = 3, - OMP_CLAUSE_PROC_BIND_SPREAD = 4 + OMP_CLAUSE_PROC_BIND_SPREAD = 4, + OMP_CLAUSE_PROC_BIND_LAST }; struct GTY(()) tree_exp { diff --git a/gcc/tree-data-ref.c b/gcc/tree-data-ref.c index 4fc7e8210f1..db394e5449d 100644 --- a/gcc/tree-data-ref.c +++ b/gcc/tree-data-ref.c @@ -79,6 +79,11 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "expr.h" #include "gimple-pretty-print.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "tree-ssa-loop-niter.h" diff --git a/gcc/tree-dfa.c b/gcc/tree-dfa.c index 1ed9d8f53d0..aed65dfdb2f 100644 --- a/gcc/tree-dfa.c +++ b/gcc/tree-dfa.c @@ -23,16 +23,18 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tm.h" #include "hashtab.h" -#include "pointer-set.h" #include "tree.h" #include "stor-layout.h" #include "tm_p.h" #include "basic-block.h" -#include "ggc.h" #include "langhooks.h" #include "flags.h" #include "function.h" #include "tree-pretty-print.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimple-walk.h" @@ -45,7 +47,6 @@ along with GCC; see the file COPYING3. If not see #include "tree-dfa.h" #include "tree-inline.h" #include "tree-pass.h" -#include "convert.h" #include "params.h" /* Build and maintain data flow information for trees. */ diff --git a/gcc/tree-dfa.h b/gcc/tree-dfa.h index ab7dd19f09f..13811a07edf 100644 --- a/gcc/tree-dfa.h +++ b/gcc/tree-dfa.h @@ -102,11 +102,10 @@ get_addr_base_and_unit_offset_1 (tree exp, HOST_WIDE_INT *poffset, && (unit_size = array_ref_element_size (exp), TREE_CODE (unit_size) == INTEGER_CST)) { - HOST_WIDE_INT hindex = TREE_INT_CST_LOW (index); - - hindex -= TREE_INT_CST_LOW (low_bound); - hindex *= TREE_INT_CST_LOW (unit_size); - byte_offset += hindex; + offset_int woffset + = offset_int::from (wi::sub (index, low_bound), SIGNED); + woffset *= wi::to_offset (unit_size); + byte_offset += woffset.to_shwi (); } else return NULL_TREE; diff --git a/gcc/tree-diagnostic.c b/gcc/tree-diagnostic.c index 087cf6acb71..2942365e3cf 100644 --- a/gcc/tree-diagnostic.c +++ b/gcc/tree-diagnostic.c @@ -39,7 +39,8 @@ diagnostic_report_current_function (diagnostic_context *context, diagnostic_info *diagnostic) { diagnostic_report_current_module (context, diagnostic->location); - lang_hooks.print_error_function (context, input_filename, diagnostic); + lang_hooks.print_error_function (context, LOCATION_FILE (input_location), + diagnostic); } static void diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c index 778c0a798b1..85dc79f458d 100644 --- a/gcc/tree-eh.c +++ b/gcc/tree-eh.c @@ -29,6 +29,12 @@ along with GCC; see the file COPYING3. If not see #include "function.h" #include "except.h" #include "pointer-set.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimple-ssa.h" @@ -43,7 +49,6 @@ along with GCC; see the file COPYING3. If not see #include "tree-inline.h" #include "tree-pass.h" #include "langhooks.h" -#include "ggc.h" #include "diagnostic-core.h" #include "target.h" #include "cfgloop.h" diff --git a/gcc/tree-emutls.c b/gcc/tree-emutls.c index 7f0c0a1981a..9ba25fc4676 100644 --- a/gcc/tree-emutls.c +++ b/gcc/tree-emutls.c @@ -23,6 +23,11 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "stor-layout.h" #include "varasm.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimple-walk.h" diff --git a/gcc/tree-if-conv.c b/gcc/tree-if-conv.c index cf08386ed3c..7f6a1503085 100644 --- a/gcc/tree-if-conv.c +++ b/gcc/tree-if-conv.c @@ -89,6 +89,11 @@ along with GCC; see the file COPYING3. If not see #include "flags.h" #include "basic-block.h" #include "gimple-pretty-print.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "gimple-iterator.h" @@ -207,7 +212,7 @@ free_bb_predicate (basic_block bb) gimple_stmt_iterator i; for (i = gsi_start (stmts); !gsi_end_p (i); gsi_next (&i)) - free_stmt_operands (gsi_stmt (i)); + free_stmt_operands (cfun, gsi_stmt (i)); } free (bb->aux); diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index e905ab8ebf1..4ae912a875a 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -36,6 +36,13 @@ along with GCC; see the file COPYING3. If not see #include "basic-block.h" #include "tree-iterator.h" #include "intl.h" +#include "pointer-set.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "gimple-iterator.h" @@ -55,7 +62,6 @@ along with GCC; see the file COPYING3. If not see #include "tree-pretty-print.h" #include "except.h" #include "debug.h" -#include "pointer-set.h" #include "ipa-prop.h" #include "value-prof.h" #include "tree-pass.h" @@ -3789,12 +3795,16 @@ estimate_num_insns (gimple stmt, eni_weights *weights) case GIMPLE_CALL: { - tree decl = gimple_call_fndecl (stmt); + tree decl; struct cgraph_node *node = NULL; /* Do not special case builtins where we see the body. This just confuse inliner. */ - if (!decl || !(node = cgraph_get_node (decl)) || node->definition) + if (gimple_call_internal_p (stmt)) + return 0; + else if (!(decl = gimple_call_fndecl (stmt)) + || !(node = cgraph_get_node (decl)) + || node->definition) ; /* For buitins that are likely expanded to nothing or inlined do not account operand costs. */ @@ -4415,6 +4425,7 @@ gimple_expand_calls_inline (basic_block bb, copy_body_data *id) gimple stmt = gsi_stmt (gsi); if (is_gimple_call (stmt) + && !gimple_call_internal_p (stmt) && expand_call_inline (bb, stmt, id)) return true; } diff --git a/gcc/tree-into-ssa.c b/gcc/tree-into-ssa.c index 41c0896b97c..0067cfe61e8 100644 --- a/gcc/tree-into-ssa.c +++ b/gcc/tree-into-ssa.c @@ -29,6 +29,11 @@ along with GCC; see the file COPYING3. If not see #include "basic-block.h" #include "function.h" #include "gimple-pretty-print.h" +#include "hash-table.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimple-ssa.h" @@ -42,7 +47,6 @@ along with GCC; see the file COPYING3. If not see #include "tree-dfa.h" #include "tree-ssa.h" #include "tree-inline.h" -#include "hash-table.h" #include "tree-pass.h" #include "cfgloop.h" #include "domwalk.h" diff --git a/gcc/tree-loop-distribution.c b/gcc/tree-loop-distribution.c index 6121236f99b..abf69f42669 100644 --- a/gcc/tree-loop-distribution.c +++ b/gcc/tree-loop-distribution.c @@ -45,6 +45,11 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "tree.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimplify-me.h" diff --git a/gcc/tree-nested.c b/gcc/tree-nested.c index 868c8fd0e1f..2d6a56dcabd 100644 --- a/gcc/tree-nested.c +++ b/gcc/tree-nested.c @@ -28,6 +28,12 @@ #include "function.h" #include "tree-dump.h" #include "tree-inline.h" +#include "pointer-set.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "gimple-iterator.h" @@ -38,7 +44,6 @@ #include "tree-cfg.h" #include "expr.h" /* FIXME: For STACK_SAVEAREA_MODE and SAVE_NONLOCAL. */ #include "langhooks.h" -#include "pointer-set.h" #include "gimple-low.h" diff --git a/gcc/tree-nrv.c b/gcc/tree-nrv.c index 035428aaec3..b42993d727b 100644 --- a/gcc/tree-nrv.c +++ b/gcc/tree-nrv.c @@ -25,6 +25,10 @@ along with GCC; see the file COPYING3. If not see #include "function.h" #include "basic-block.h" #include "tree-pretty-print.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimple-walk.h" diff --git a/gcc/tree-object-size.c b/gcc/tree-object-size.c index ced1f60f1e4..5bb520fbf83 100644 --- a/gcc/tree-object-size.c +++ b/gcc/tree-object-size.c @@ -27,6 +27,12 @@ along with GCC; see the file COPYING3. If not see #include "diagnostic-core.h" #include "gimple-pretty-print.h" #include "bitmap.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimple-ssa.h" @@ -72,7 +78,7 @@ static void check_for_plus_in_loops_1 (struct object_size_info *, tree, the subobject (innermost array or field with address taken). object_sizes[2] is lower bound for number of bytes till the end of the object and object_sizes[3] lower bound for subobject. */ -static unsigned HOST_WIDE_INT *object_sizes[4]; +static vec<unsigned HOST_WIDE_INT> object_sizes[4]; /* Bitmaps what object sizes have been computed already. */ static bitmap computed[4]; @@ -500,7 +506,7 @@ compute_builtin_object_size (tree ptr, int object_size_type) if (TREE_CODE (ptr) == SSA_NAME && POINTER_TYPE_P (TREE_TYPE (ptr)) - && object_sizes[object_size_type] != NULL) + && computed[object_size_type] != NULL) { if (!bitmap_bit_p (computed[object_size_type], SSA_NAME_VERSION (ptr))) { @@ -508,6 +514,8 @@ compute_builtin_object_size (tree ptr, int object_size_type) bitmap_iterator bi; unsigned int i; + if (num_ssa_names > object_sizes[object_size_type].length ()) + object_sizes[object_size_type].safe_grow (num_ssa_names); if (dump_file) { fprintf (dump_file, "Computing %s %sobject size for ", @@ -1169,12 +1177,12 @@ init_object_sizes (void) { int object_size_type; - if (object_sizes[0]) + if (computed[0]) return; for (object_size_type = 0; object_size_type <= 3; object_size_type++) { - object_sizes[object_size_type] = XNEWVEC (unsigned HOST_WIDE_INT, num_ssa_names); + object_sizes[object_size_type].safe_grow (num_ssa_names); computed[object_size_type] = BITMAP_ALLOC (NULL); } @@ -1191,9 +1199,8 @@ fini_object_sizes (void) for (object_size_type = 0; object_size_type <= 3; object_size_type++) { - free (object_sizes[object_size_type]); + object_sizes[object_size_type].release (); BITMAP_FREE (computed[object_size_type]); - object_sizes[object_size_type] = NULL; } } diff --git a/gcc/tree-outof-ssa.c b/gcc/tree-outof-ssa.c index 9a7a73f4079..8df3026309d 100644 --- a/gcc/tree-outof-ssa.c +++ b/gcc/tree-outof-ssa.c @@ -24,11 +24,15 @@ along with GCC; see the file COPYING3. If not see #include "tm.h" #include "tree.h" #include "stor-layout.h" -#include "ggc.h" #include "basic-block.h" #include "gimple-pretty-print.h" #include "bitmap.h" #include "sbitmap.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimple-ssa.h" diff --git a/gcc/tree-parloops.c b/gcc/tree-parloops.c index 78b35df1b3a..a56145dbebe 100644 --- a/gcc/tree-parloops.c +++ b/gcc/tree-parloops.c @@ -23,6 +23,11 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "tree.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "gimple-iterator.h" diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h index 02d71cd3961..4d570b19fc8 100644 --- a/gcc/tree-pass.h +++ b/gcc/tree-pass.h @@ -472,6 +472,7 @@ extern ipa_opt_pass_d *make_pass_ipa_reference (gcc::context *ctxt); extern ipa_opt_pass_d *make_pass_ipa_pure_const (gcc::context *ctxt); extern simple_ipa_opt_pass *make_pass_ipa_pta (gcc::context *ctxt); extern simple_ipa_opt_pass *make_pass_ipa_tm (gcc::context *ctxt); +extern simple_ipa_opt_pass *make_pass_omp_simd_clone (gcc::context *ctxt); extern ipa_opt_pass_d *make_pass_ipa_profile (gcc::context *ctxt); extern ipa_opt_pass_d *make_pass_ipa_cdtor_merge (gcc::context *ctxt); diff --git a/gcc/tree-phinodes.c b/gcc/tree-phinodes.c index bf024ac976c..b9c5b43ea57 100644 --- a/gcc/tree-phinodes.c +++ b/gcc/tree-phinodes.c @@ -22,8 +22,11 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tm.h" #include "tree.h" -#include "ggc.h" #include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimple-ssa.h" diff --git a/gcc/tree-predcom.c b/gcc/tree-predcom.c index f257d526960..0270e35885c 100644 --- a/gcc/tree-predcom.c +++ b/gcc/tree-predcom.c @@ -191,6 +191,12 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "tm_p.h" #include "cfgloop.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "gimple-iterator.h" @@ -208,7 +214,6 @@ along with GCC; see the file COPYING3. If not see #include "expr.h" #include "tree-dfa.h" #include "tree-ssa.h" -#include "ggc.h" #include "tree-data-ref.h" #include "tree-scalar-evolution.h" #include "tree-chrec.h" diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c index fc1b31aa696..3ed215228f6 100644 --- a/gcc/tree-pretty-print.c +++ b/gcc/tree-pretty-print.c @@ -27,7 +27,8 @@ along with GCC; see the file COPYING3. If not see #include "expr.h" #include "tree-pretty-print.h" #include "hashtab.h" -#include "gimple.h" +#include "pointer-set.h" +#include "gimple-expr.h" #include "cgraph.h" #include "langhooks.h" #include "tree-iterator.h" @@ -869,7 +870,6 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags, break; case VOID_TYPE: - case POINTER_BOUNDS_TYPE: case INTEGER_TYPE: case REAL_TYPE: case FIXED_POINT_TYPE: diff --git a/gcc/tree-profile.c b/gcc/tree-profile.c index 0adc51a51aa..537c246c630 100644 --- a/gcc/tree-profile.c +++ b/gcc/tree-profile.c @@ -34,6 +34,10 @@ along with GCC; see the file COPYING3. If not see #include "diagnostic-core.h" #include "coverage.h" #include "tree.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "varasm.h" #include "tree-nested.h" diff --git a/gcc/tree-scalar-evolution.c b/gcc/tree-scalar-evolution.c index de05f644b0e..ada942df389 100644 --- a/gcc/tree-scalar-evolution.c +++ b/gcc/tree-scalar-evolution.c @@ -258,8 +258,12 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tree.h" #include "expr.h" -#include "hash-table.h" #include "gimple-pretty-print.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "gimple-iterator.h" diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c index 0e21cb80fac..0890613852b 100644 --- a/gcc/tree-sra.c +++ b/gcc/tree-sra.c @@ -78,6 +78,13 @@ along with GCC; see the file COPYING3. If not see #include "alloc-pool.h" #include "tm.h" #include "tree.h" +#include "pointer-set.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "stor-layout.h" #include "gimplify.h" @@ -4274,9 +4281,10 @@ turn_representatives_into_adjustments (vec<access_p> representatives, adj.base_index = get_param_index (parm, parms); adj.base = parm; if (!repr) - adj.copy_param = 1; + adj.op = IPA_PARM_OP_COPY; else - adj.remove_param = 1; + adj.op = IPA_PARM_OP_REMOVE; + adj.arg_prefix = "ISRA"; adjustments.quick_push (adj); } else @@ -4296,6 +4304,7 @@ turn_representatives_into_adjustments (vec<access_p> representatives, adj.by_ref = (POINTER_TYPE_P (TREE_TYPE (repr->base)) && (repr->grp_maybe_modified || repr->grp_not_necessarilly_dereferenced)); + adj.arg_prefix = "ISRA"; adjustments.quick_push (adj); } } @@ -4426,7 +4435,7 @@ get_adjustment_for_base (ipa_parm_adjustment_vec adjustments, tree base) struct ipa_parm_adjustment *adj; adj = &adjustments[i]; - if (!adj->copy_param && adj->base == base) + if (adj->op != IPA_PARM_OP_COPY && adj->base == base) return adj; } @@ -4490,84 +4499,6 @@ replace_removed_params_ssa_names (gimple stmt, return true; } -/* If the expression *EXPR should be replaced by a reduction of a parameter, do - so. ADJUSTMENTS is a pointer to a vector of adjustments. CONVERT - specifies whether the function should care about type incompatibility the - current and new expressions. If it is false, the function will leave - incompatibility issues to the caller. Return true iff the expression - was modified. */ - -static bool -sra_ipa_modify_expr (tree *expr, bool convert, - ipa_parm_adjustment_vec adjustments) -{ - int i, len; - struct ipa_parm_adjustment *adj, *cand = NULL; - HOST_WIDE_INT offset, size, max_size; - tree base, src; - - len = adjustments.length (); - - if (TREE_CODE (*expr) == BIT_FIELD_REF - || TREE_CODE (*expr) == IMAGPART_EXPR - || TREE_CODE (*expr) == REALPART_EXPR) - { - expr = &TREE_OPERAND (*expr, 0); - convert = true; - } - - base = get_ref_base_and_extent (*expr, &offset, &size, &max_size); - if (!base || size == -1 || max_size == -1) - return false; - - if (TREE_CODE (base) == MEM_REF) - { - offset += mem_ref_offset (base).to_short_addr () * BITS_PER_UNIT; - base = TREE_OPERAND (base, 0); - } - - base = get_ssa_base_param (base); - if (!base || TREE_CODE (base) != PARM_DECL) - return false; - - for (i = 0; i < len; i++) - { - adj = &adjustments[i]; - - if (adj->base == base - && (adj->offset == offset || adj->remove_param)) - { - cand = adj; - break; - } - } - if (!cand || cand->copy_param || cand->remove_param) - return false; - - if (cand->by_ref) - src = build_simple_mem_ref (cand->reduction); - else - src = cand->reduction; - - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, "About to replace expr "); - print_generic_expr (dump_file, *expr, 0); - fprintf (dump_file, " with "); - print_generic_expr (dump_file, src, 0); - fprintf (dump_file, "\n"); - } - - if (convert && !useless_type_conversion_p (TREE_TYPE (*expr), cand->type)) - { - tree vce = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (*expr), src); - *expr = vce; - } - else - *expr = src; - return true; -} - /* If the statement pointed to by STMT_PTR contains any expressions that need to replaced with a different one as noted by ADJUSTMENTS, do so. Handle any potential type incompatibilities (GSI is used to accommodate conversion @@ -4588,8 +4519,8 @@ sra_ipa_modify_assign (gimple *stmt_ptr, gimple_stmt_iterator *gsi, rhs_p = gimple_assign_rhs1_ptr (stmt); lhs_p = gimple_assign_lhs_ptr (stmt); - any = sra_ipa_modify_expr (rhs_p, false, adjustments); - any |= sra_ipa_modify_expr (lhs_p, false, adjustments); + any = ipa_modify_expr (rhs_p, false, adjustments); + any |= ipa_modify_expr (lhs_p, false, adjustments); if (any) { tree new_rhs = NULL_TREE; @@ -4635,7 +4566,7 @@ sra_ipa_modify_assign (gimple *stmt_ptr, gimple_stmt_iterator *gsi, /* Traverse the function body and all modifications as described in ADJUSTMENTS. Return true iff the CFG has been changed. */ -static bool +bool ipa_sra_modify_function_body (ipa_parm_adjustment_vec adjustments) { bool cfg_changed = false; @@ -4661,7 +4592,7 @@ ipa_sra_modify_function_body (ipa_parm_adjustment_vec adjustments) case GIMPLE_RETURN: t = gimple_return_retval_ptr (stmt); if (*t != NULL_TREE) - modified |= sra_ipa_modify_expr (t, true, adjustments); + modified |= ipa_modify_expr (t, true, adjustments); break; case GIMPLE_ASSIGN: @@ -4674,13 +4605,13 @@ ipa_sra_modify_function_body (ipa_parm_adjustment_vec adjustments) for (i = 0; i < gimple_call_num_args (stmt); i++) { t = gimple_call_arg_ptr (stmt, i); - modified |= sra_ipa_modify_expr (t, true, adjustments); + modified |= ipa_modify_expr (t, true, adjustments); } if (gimple_call_lhs (stmt)) { t = gimple_call_lhs_ptr (stmt); - modified |= sra_ipa_modify_expr (t, false, adjustments); + modified |= ipa_modify_expr (t, false, adjustments); modified |= replace_removed_params_ssa_names (stmt, adjustments); } @@ -4690,12 +4621,12 @@ ipa_sra_modify_function_body (ipa_parm_adjustment_vec adjustments) for (i = 0; i < gimple_asm_ninputs (stmt); i++) { t = &TREE_VALUE (gimple_asm_input_op (stmt, i)); - modified |= sra_ipa_modify_expr (t, true, adjustments); + modified |= ipa_modify_expr (t, true, adjustments); } for (i = 0; i < gimple_asm_noutputs (stmt); i++) { t = &TREE_VALUE (gimple_asm_output_op (stmt, i)); - modified |= sra_ipa_modify_expr (t, false, adjustments); + modified |= ipa_modify_expr (t, false, adjustments); } break; @@ -4741,7 +4672,7 @@ sra_ipa_reset_debug_stmts (ipa_parm_adjustment_vec adjustments) use_operand_p use_p; adj = &adjustments[i]; - if (adj->copy_param || !is_gimple_reg (adj->base)) + if (adj->op == IPA_PARM_OP_COPY || !is_gimple_reg (adj->base)) continue; name = ssa_default_def (cfun, adj->base); vexpr = NULL; @@ -4924,7 +4855,7 @@ modify_function (struct cgraph_node *node, ipa_parm_adjustment_vec adjustments) redirect_callers.release (); push_cfun (DECL_STRUCT_FUNCTION (new_node->decl)); - ipa_modify_formal_parameters (current_function_decl, adjustments, "ISRA"); + ipa_modify_formal_parameters (current_function_decl, adjustments); cfg_changed = ipa_sra_modify_function_body (adjustments); sra_ipa_reset_debug_stmts (adjustments); convert_callers (new_node, node->decl, adjustments); diff --git a/gcc/tree-ssa-address.c b/gcc/tree-ssa-address.c index a4e82580e5a..e810b3b79a2 100644 --- a/gcc/tree-ssa-address.c +++ b/gcc/tree-ssa-address.c @@ -29,6 +29,10 @@ along with GCC; see the file COPYING3. If not see #include "tm_p.h" #include "basic-block.h" #include "tree-pretty-print.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimplify-me.h" @@ -47,7 +51,6 @@ along with GCC; see the file COPYING3. If not see #include "rtl.h" #include "recog.h" #include "expr.h" -#include "ggc.h" #include "target.h" #include "expmed.h" #include "tree-ssa-address.h" diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c index 303c85f16d6..49cc379c47a 100644 --- a/gcc/tree-ssa-alias.c +++ b/gcc/tree-ssa-alias.c @@ -27,12 +27,16 @@ along with GCC; see the file COPYING3. If not see #include "target.h" #include "basic-block.h" #include "timevar.h" /* for TV_ALIAS_STMT_WALK */ -#include "ggc.h" #include "langhooks.h" #include "flags.h" #include "function.h" #include "tree-pretty-print.h" #include "dumpfile.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-ssa.h" #include "stringpool.h" @@ -41,8 +45,6 @@ along with GCC; see the file COPYING3. If not see #include "tree-dfa.h" #include "tree-inline.h" #include "params.h" -#include "vec.h" -#include "pointer-set.h" #include "alloc-pool.h" #include "tree-ssa-alias.h" #include "ipa-reference.h" diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c index acd7fa15120..473ee9227bc 100644 --- a/gcc/tree-ssa-ccp.c +++ b/gcc/tree-ssa-ccp.c @@ -129,6 +129,13 @@ along with GCC; see the file COPYING3. If not see #include "basic-block.h" #include "function.h" #include "gimple-pretty-print.h" +#include "hash-table.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "gimple-iterator.h" @@ -146,7 +153,6 @@ along with GCC; see the file COPYING3. If not see #include "diagnostic-core.h" #include "dbgcnt.h" #include "params.h" -#include "hash-table.h" #include "wide-int-print.h" diff --git a/gcc/tree-ssa-coalesce.c b/gcc/tree-ssa-coalesce.c index d6fbb1cc27f..70158d58d37 100644 --- a/gcc/tree-ssa-coalesce.c +++ b/gcc/tree-ssa-coalesce.c @@ -27,6 +27,12 @@ along with GCC; see the file COPYING3. If not see #include "tree-pretty-print.h" #include "bitmap.h" #include "dumpfile.h" +#include "hash-table.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimple-ssa.h" @@ -34,7 +40,6 @@ along with GCC; see the file COPYING3. If not see #include "ssa-iterators.h" #include "stringpool.h" #include "tree-ssanames.h" -#include "hash-table.h" #include "tree-ssa-live.h" #include "tree-ssa-coalesce.h" #include "diagnostic-core.h" diff --git a/gcc/tree-ssa-copy.c b/gcc/tree-ssa-copy.c index b171aa5dd1d..0dd5e147f3e 100644 --- a/gcc/tree-ssa-copy.c +++ b/gcc/tree-ssa-copy.c @@ -27,6 +27,10 @@ along with GCC; see the file COPYING3. If not see #include "basic-block.h" #include "function.h" #include "gimple-pretty-print.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimple-ssa.h" diff --git a/gcc/tree-ssa-copyrename.c b/gcc/tree-ssa-copyrename.c index 361b4c32fd7..90e070fb995 100644 --- a/gcc/tree-ssa-copyrename.c +++ b/gcc/tree-ssa-copyrename.c @@ -23,10 +23,14 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tm.h" #include "tree.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "flags.h" -#include "basic-block.h" #include "function.h" #include "tree-pretty-print.h" #include "bitmap.h" diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c index 0c8110fb71a..8fc6fce3ec2 100644 --- a/gcc/tree-ssa-dce.c +++ b/gcc/tree-ssa-dce.c @@ -51,6 +51,11 @@ along with GCC; see the file COPYING3. If not see #include "calls.h" #include "gimple-pretty-print.h" #include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "gimple-iterator.h" @@ -1186,26 +1191,19 @@ eliminate_unnecessary_stmts (void) stats.total++; /* We can mark a call to free as not necessary if the - defining statement of its argument is an allocation - function and that is not necessary itself. */ - if (gimple_call_builtin_p (stmt, BUILT_IN_FREE)) + defining statement of its argument is not necessary + (and thus is getting removed). */ + if (gimple_plf (stmt, STMT_NECESSARY) + && gimple_call_builtin_p (stmt, BUILT_IN_FREE)) { tree ptr = gimple_call_arg (stmt, 0); - tree callee2; - gimple def_stmt; - if (TREE_CODE (ptr) != SSA_NAME) - continue; - def_stmt = SSA_NAME_DEF_STMT (ptr); - if (!is_gimple_call (def_stmt) - || gimple_plf (def_stmt, STMT_NECESSARY)) - continue; - callee2 = gimple_call_fndecl (def_stmt); - if (callee2 == NULL_TREE - || DECL_BUILT_IN_CLASS (callee2) != BUILT_IN_NORMAL - || (DECL_FUNCTION_CODE (callee2) != BUILT_IN_MALLOC - && DECL_FUNCTION_CODE (callee2) != BUILT_IN_CALLOC)) - continue; - gimple_set_plf (stmt, STMT_NECESSARY, false); + if (TREE_CODE (ptr) == SSA_NAME) + { + gimple def_stmt = SSA_NAME_DEF_STMT (ptr); + if (!gimple_nop_p (def_stmt) + && !gimple_plf (def_stmt, STMT_NECESSARY)) + gimple_set_plf (stmt, STMT_NECESSARY, false); + } } /* If GSI is not necessary then remove it. */ diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c index a286c105615..82005afa0c9 100644 --- a/gcc/tree-ssa-dom.c +++ b/gcc/tree-ssa-dom.c @@ -31,6 +31,12 @@ along with GCC; see the file COPYING3. If not see #include "cfgloop.h" #include "function.h" #include "gimple-pretty-print.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimple-ssa.h" diff --git a/gcc/tree-ssa-dse.c b/gcc/tree-ssa-dse.c index 905ef21761c..a51f7615c72 100644 --- a/gcc/tree-ssa-dse.c +++ b/gcc/tree-ssa-dse.c @@ -21,12 +21,15 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "tm.h" -#include "ggc.h" #include "tree.h" #include "tm_p.h" #include "basic-block.h" #include "gimple-pretty-print.h" #include "bitmap.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimple-ssa.h" diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c index ffaa95f6fe9..7557b17bd3a 100644 --- a/gcc/tree-ssa-forwprop.c +++ b/gcc/tree-ssa-forwprop.c @@ -26,6 +26,12 @@ along with GCC; see the file COPYING3. If not see #include "tm_p.h" #include "basic-block.h" #include "gimple-pretty-print.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "gimple-iterator.h" @@ -3544,7 +3550,8 @@ ssa_forward_propagate_and_combine (void) { tree outer_type = TREE_TYPE (gimple_assign_lhs (stmt)); tree inner_type = TREE_TYPE (gimple_assign_rhs1 (stmt)); - if (INTEGRAL_TYPE_P (outer_type) + if (TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME + && INTEGRAL_TYPE_P (outer_type) && INTEGRAL_TYPE_P (inner_type) && (TYPE_PRECISION (outer_type) <= TYPE_PRECISION (inner_type))) diff --git a/gcc/tree-ssa-ifcombine.c b/gcc/tree-ssa-ifcombine.c index 9d243753666..3a6ea796bac 100644 --- a/gcc/tree-ssa-ifcombine.c +++ b/gcc/tree-ssa-ifcombine.c @@ -30,6 +30,11 @@ along with GCC; see the file COPYING3. If not see #include "stor-layout.h" #include "basic-block.h" #include "tree-pretty-print.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimplify-me.h" diff --git a/gcc/tree-ssa-live.c b/gcc/tree-ssa-live.c index e46f20af0af..8ad5d9a9b93 100644 --- a/gcc/tree-ssa-live.c +++ b/gcc/tree-ssa-live.c @@ -27,6 +27,11 @@ along with GCC; see the file COPYING3. If not see #include "gimple-pretty-print.h" #include "bitmap.h" #include "sbitmap.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimple-ssa.h" diff --git a/gcc/tree-ssa-loop-ch.c b/gcc/tree-ssa-loop-ch.c index df45c286790..07da4918ce8 100644 --- a/gcc/tree-ssa-loop-ch.c +++ b/gcc/tree-ssa-loop-ch.c @@ -24,6 +24,10 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "tm_p.h" #include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimple-ssa.h" diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c index c975a97b896..b96899dc24c 100644 --- a/gcc/tree-ssa-loop-im.c +++ b/gcc/tree-ssa-loop-im.c @@ -25,6 +25,13 @@ along with GCC; see the file COPYING3. If not see #include "tm_p.h" #include "basic-block.h" #include "gimple-pretty-print.h" +#include "pointer-set.h" +#include "hash-table.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "gimple-iterator.h" @@ -43,9 +50,7 @@ along with GCC; see the file COPYING3. If not see #include "params.h" #include "tree-pass.h" #include "flags.h" -#include "hash-table.h" #include "tree-affine.h" -#include "pointer-set.h" #include "tree-ssa-propagate.h" #include "trans-mem.h" diff --git a/gcc/tree-ssa-loop-ivcanon.c b/gcc/tree-ssa-loop-ivcanon.c index b2edef5fc29..579122698b4 100644 --- a/gcc/tree-ssa-loop-ivcanon.c +++ b/gcc/tree-ssa-loop-ivcanon.c @@ -40,6 +40,12 @@ along with GCC; see the file COPYING3. If not see #include "tm_p.h" #include "basic-block.h" #include "gimple-pretty-print.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimple-ssa.h" diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c index aa944007fe1..54ecfad9210 100644 --- a/gcc/tree-ssa-loop-ivopts.c +++ b/gcc/tree-ssa-loop-ivopts.c @@ -70,6 +70,13 @@ along with GCC; see the file COPYING3. If not see #include "tm_p.h" #include "basic-block.h" #include "gimple-pretty-print.h" +#include "pointer-set.h" +#include "hash-table.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "gimple-iterator.h" @@ -90,10 +97,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-ssa.h" #include "cfgloop.h" #include "tree-pass.h" -#include "ggc.h" #include "insn-config.h" -#include "pointer-set.h" -#include "hash-table.h" #include "tree-chrec.h" #include "tree-scalar-evolution.h" #include "cfgloop.h" diff --git a/gcc/tree-ssa-loop-manip.c b/gcc/tree-ssa-loop-manip.c index 031b7c757e6..e1d55ffbeed 100644 --- a/gcc/tree-ssa-loop-manip.c +++ b/gcc/tree-ssa-loop-manip.c @@ -24,6 +24,10 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "tm_p.h" #include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "gimple-iterator.h" diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c index 7720698ee82..4c151e5bc88 100644 --- a/gcc/tree-ssa-loop-niter.c +++ b/gcc/tree-ssa-loop-niter.c @@ -28,6 +28,11 @@ along with GCC; see the file COPYING3. If not see #include "basic-block.h" #include "gimple-pretty-print.h" #include "intl.h" +#include "pointer-set.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "gimple-iterator.h" @@ -40,7 +45,6 @@ along with GCC; see the file COPYING3. If not see #include "tree-ssa-loop.h" #include "dumpfile.h" #include "cfgloop.h" -#include "ggc.h" #include "tree-chrec.h" #include "tree-scalar-evolution.h" #include "tree-data-ref.h" @@ -2160,7 +2164,8 @@ chain_of_csts_start (struct loop *loop, tree x) return NULL; } - if (gimple_code (stmt) != GIMPLE_ASSIGN) + if (gimple_code (stmt) != GIMPLE_ASSIGN + || gimple_assign_rhs_class (stmt) == GIMPLE_TERNARY_RHS) return NULL; code = gimple_assign_rhs_code (stmt); @@ -2228,7 +2233,7 @@ get_val_for (tree x, tree base) { gimple stmt; - gcc_assert (is_gimple_min_invariant (base)); + gcc_checking_assert (is_gimple_min_invariant (base)); if (!x) return base; @@ -2237,7 +2242,7 @@ get_val_for (tree x, tree base) if (gimple_code (stmt) == GIMPLE_PHI) return base; - gcc_assert (is_gimple_assign (stmt)); + gcc_checking_assert (is_gimple_assign (stmt)); /* STMT must be either an assignment of a single SSA name or an expression involving an SSA name and a constant. Try to fold that diff --git a/gcc/tree-ssa-loop-prefetch.c b/gcc/tree-ssa-loop-prefetch.c index f2b4e95f873..8cb74d58bb1 100644 --- a/gcc/tree-ssa-loop-prefetch.c +++ b/gcc/tree-ssa-loop-prefetch.c @@ -26,6 +26,10 @@ along with GCC; see the file COPYING3. If not see #include "tm_p.h" #include "basic-block.h" #include "tree-pretty-print.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "gimple-iterator.h" diff --git a/gcc/tree-ssa-loop-unswitch.c b/gcc/tree-ssa-loop-unswitch.c index 27f52b28025..200b076c691 100644 --- a/gcc/tree-ssa-loop-unswitch.c +++ b/gcc/tree-ssa-loop-unswitch.c @@ -24,6 +24,10 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "tm_p.h" #include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "gimple-ssa.h" diff --git a/gcc/tree-ssa-loop.c b/gcc/tree-ssa-loop.c index 20454f2edf4..3bbe7bf2b93 100644 --- a/gcc/tree-ssa-loop.c +++ b/gcc/tree-ssa-loop.c @@ -24,6 +24,10 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "tm_p.h" #include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "tree-ssa-loop-ivopts.h" diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c index 87d2c023ed3..d1b88d918bb 100644 --- a/gcc/tree-ssa-math-opts.c +++ b/gcc/tree-ssa-math-opts.c @@ -90,6 +90,12 @@ along with GCC; see the file COPYING3. If not see #include "tm.h" #include "flags.h" #include "tree.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimplify-me.h" @@ -105,7 +111,6 @@ along with GCC; see the file COPYING3. If not see #include "tree-ssa.h" #include "tree-pass.h" #include "alloc-pool.h" -#include "basic-block.h" #include "target.h" #include "gimple-pretty-print.h" diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c index 3508b34b77a..84ec0024d5d 100644 --- a/gcc/tree-ssa-operands.c +++ b/gcc/tree-ssa-operands.c @@ -28,6 +28,11 @@ along with GCC; see the file COPYING3. If not see #include "function.h" #include "gimple-pretty-print.h" #include "bitmap.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-ssa.h" #include "tree-phinodes.h" @@ -37,7 +42,6 @@ along with GCC; see the file COPYING3. If not see #include "tree-inline.h" #include "timevar.h" #include "dumpfile.h" -#include "ggc.h" #include "timevar.h" #include "langhooks.h" #include "diagnostic-core.h" @@ -101,17 +105,15 @@ along with GCC; see the file COPYING3. If not see VUSE for 'b'. */ #define opf_no_vops (1 << 1) -/* Operand is an implicit reference. This is used to distinguish - explicit assignments in the form of MODIFY_EXPR from - clobbering sites like function calls or ASM_EXPRs. */ -#define opf_implicit (1 << 2) - /* Operand is in a place where address-taken does not imply addressable. */ #define opf_non_addressable (1 << 3) /* Operand is in a place where opf_non_addressable does not apply. */ #define opf_not_non_addressable (1 << 4) +/* Operand is having its address taken. */ +#define opf_address_taken (1 << 5) + /* Array for building all the use operands. */ static vec<tree> build_uses; @@ -125,7 +127,7 @@ static tree build_vuse; compilations of multiple functions. */ static bitmap_obstack operands_bitmap_obstack; -static void get_expr_operands (gimple, tree *, int); +static void get_expr_operands (struct function *, gimple, tree *, int); /* Number of functions with initialized ssa_operands. */ static int n_initialized = 0; @@ -213,7 +215,7 @@ init_ssa_operands (struct function *fn) /* Dispose of anything required by the operand routines. */ void -fini_ssa_operands (void) +fini_ssa_operands (struct function *fn) { struct ssa_operand_memory_d *ptr; @@ -224,49 +226,49 @@ fini_ssa_operands (void) build_vuse = NULL_TREE; } - gimple_ssa_operands (cfun)->free_uses = NULL; + gimple_ssa_operands (fn)->free_uses = NULL; - while ((ptr = gimple_ssa_operands (cfun)->operand_memory) != NULL) + while ((ptr = gimple_ssa_operands (fn)->operand_memory) != NULL) { - gimple_ssa_operands (cfun)->operand_memory - = gimple_ssa_operands (cfun)->operand_memory->next; + gimple_ssa_operands (fn)->operand_memory + = gimple_ssa_operands (fn)->operand_memory->next; ggc_free (ptr); } - gimple_ssa_operands (cfun)->ops_active = false; + gimple_ssa_operands (fn)->ops_active = false; if (!n_initialized) bitmap_obstack_release (&operands_bitmap_obstack); - cfun->gimple_df->vop = NULL_TREE; + fn->gimple_df->vop = NULL_TREE; } /* Return memory for an operand of size SIZE. */ static inline void * -ssa_operand_alloc (unsigned size) +ssa_operand_alloc (struct function *fn, unsigned size) { char *ptr; gcc_assert (size == sizeof (struct use_optype_d)); - if (gimple_ssa_operands (cfun)->operand_memory_index + size - >= gimple_ssa_operands (cfun)->ssa_operand_mem_size) + if (gimple_ssa_operands (fn)->operand_memory_index + size + >= gimple_ssa_operands (fn)->ssa_operand_mem_size) { struct ssa_operand_memory_d *ptr; - switch (gimple_ssa_operands (cfun)->ssa_operand_mem_size) + switch (gimple_ssa_operands (fn)->ssa_operand_mem_size) { case OP_SIZE_INIT: - gimple_ssa_operands (cfun)->ssa_operand_mem_size = OP_SIZE_1; + gimple_ssa_operands (fn)->ssa_operand_mem_size = OP_SIZE_1; break; case OP_SIZE_1: - gimple_ssa_operands (cfun)->ssa_operand_mem_size = OP_SIZE_2; + gimple_ssa_operands (fn)->ssa_operand_mem_size = OP_SIZE_2; break; case OP_SIZE_2: case OP_SIZE_3: - gimple_ssa_operands (cfun)->ssa_operand_mem_size = OP_SIZE_3; + gimple_ssa_operands (fn)->ssa_operand_mem_size = OP_SIZE_3; break; default: gcc_unreachable (); @@ -274,16 +276,16 @@ ssa_operand_alloc (unsigned size) ptr = ggc_alloc_ssa_operand_memory_d (sizeof (void *) - + gimple_ssa_operands (cfun)->ssa_operand_mem_size); + + gimple_ssa_operands (fn)->ssa_operand_mem_size); - ptr->next = gimple_ssa_operands (cfun)->operand_memory; - gimple_ssa_operands (cfun)->operand_memory = ptr; - gimple_ssa_operands (cfun)->operand_memory_index = 0; + ptr->next = gimple_ssa_operands (fn)->operand_memory; + gimple_ssa_operands (fn)->operand_memory = ptr; + gimple_ssa_operands (fn)->operand_memory_index = 0; } - ptr = &(gimple_ssa_operands (cfun)->operand_memory - ->mem[gimple_ssa_operands (cfun)->operand_memory_index]); - gimple_ssa_operands (cfun)->operand_memory_index += size; + ptr = &(gimple_ssa_operands (fn)->operand_memory + ->mem[gimple_ssa_operands (fn)->operand_memory_index]); + gimple_ssa_operands (fn)->operand_memory_index += size; return ptr; } @@ -291,18 +293,18 @@ ssa_operand_alloc (unsigned size) /* Allocate a USE operand. */ static inline struct use_optype_d * -alloc_use (void) +alloc_use (struct function *fn) { struct use_optype_d *ret; - if (gimple_ssa_operands (cfun)->free_uses) + if (gimple_ssa_operands (fn)->free_uses) { - ret = gimple_ssa_operands (cfun)->free_uses; - gimple_ssa_operands (cfun)->free_uses - = gimple_ssa_operands (cfun)->free_uses->next; + ret = gimple_ssa_operands (fn)->free_uses; + gimple_ssa_operands (fn)->free_uses + = gimple_ssa_operands (fn)->free_uses->next; } else ret = (struct use_optype_d *) - ssa_operand_alloc (sizeof (struct use_optype_d)); + ssa_operand_alloc (fn, sizeof (struct use_optype_d)); return ret; } @@ -310,11 +312,11 @@ alloc_use (void) /* Adds OP to the list of uses of statement STMT after LAST. */ static inline use_optype_p -add_use_op (gimple stmt, tree *op, use_optype_p last) +add_use_op (struct function *fn, gimple stmt, tree *op, use_optype_p last) { use_optype_p new_use; - new_use = alloc_use (); + new_use = alloc_use (fn); USE_OP_PTR (new_use)->use = op; link_imm_use_stmt (USE_OP_PTR (new_use), *op, stmt); last->next = new_use; @@ -328,7 +330,7 @@ add_use_op (gimple stmt, tree *op, use_optype_p last) TODO -- Make build_defs vec of tree *. */ static inline void -finalize_ssa_defs (gimple stmt) +finalize_ssa_defs (struct function *fn, gimple stmt) { /* Pre-pend the vdef we may have built. */ if (build_vdef != NULL_TREE) @@ -348,7 +350,7 @@ finalize_ssa_defs (gimple stmt) if (TREE_CODE (gimple_vdef (stmt)) == SSA_NAME) { unlink_stmt_vdef (stmt); - release_ssa_name (gimple_vdef (stmt)); + release_ssa_name_fn (fn, gimple_vdef (stmt)); } gimple_set_vdef (stmt, NULL_TREE); } @@ -357,8 +359,8 @@ finalize_ssa_defs (gimple stmt) if (gimple_vdef (stmt) && TREE_CODE (gimple_vdef (stmt)) != SSA_NAME) { - cfun->gimple_df->rename_vops = 1; - cfun->gimple_df->ssa_renaming_needed = 1; + fn->gimple_df->rename_vops = 1; + fn->gimple_df->ssa_renaming_needed = 1; } } @@ -367,7 +369,7 @@ finalize_ssa_defs (gimple stmt) TODO -- Make build_uses vec of tree *. */ static inline void -finalize_ssa_uses (gimple stmt) +finalize_ssa_uses (struct function *fn, gimple stmt) { unsigned new_i; struct use_optype_d new_list; @@ -401,8 +403,8 @@ finalize_ssa_uses (gimple stmt) { for (ptr = old_ops; ptr; ptr = ptr->next) delink_imm_use (USE_OP_PTR (ptr)); - old_ops->next = gimple_ssa_operands (cfun)->free_uses; - gimple_ssa_operands (cfun)->free_uses = old_ops; + old_ops->next = gimple_ssa_operands (fn)->free_uses; + gimple_ssa_operands (fn)->free_uses = old_ops; } /* If we added a VUSE, make sure to set the operand if it is not already @@ -410,16 +412,16 @@ finalize_ssa_uses (gimple stmt) if (build_vuse != NULL_TREE && gimple_vuse (stmt) == NULL_TREE) { - gimple_set_vuse (stmt, gimple_vop (cfun)); - cfun->gimple_df->rename_vops = 1; - cfun->gimple_df->ssa_renaming_needed = 1; + gimple_set_vuse (stmt, gimple_vop (fn)); + fn->gimple_df->rename_vops = 1; + fn->gimple_df->ssa_renaming_needed = 1; } /* Now create nodes for all the new nodes. */ for (new_i = 0; new_i < build_uses.length (); new_i++) { tree *op = (tree *) build_uses[new_i]; - last = add_use_op (stmt, op, last); + last = add_use_op (fn, stmt, op, last); } /* Now set the stmt's operands. */ @@ -442,10 +444,10 @@ cleanup_build_arrays (void) /* Finalize all the build vectors, fill the new ones into INFO. */ static inline void -finalize_ssa_stmt_operands (gimple stmt) +finalize_ssa_stmt_operands (struct function *fn, gimple stmt) { - finalize_ssa_defs (stmt); - finalize_ssa_uses (stmt); + finalize_ssa_defs (fn, stmt); + finalize_ssa_uses (fn, stmt); cleanup_build_arrays (); } @@ -505,7 +507,8 @@ append_vuse (tree var) /* Add virtual operands for STMT. FLAGS is as in get_expr_operands. */ static void -add_virtual_operand (gimple stmt ATTRIBUTE_UNUSED, int flags) +add_virtual_operand (struct function *fn, + gimple stmt ATTRIBUTE_UNUSED, int flags) { /* Add virtual operands to the stmt, unless the caller has specifically requested not to do that (used when adding operands inside an @@ -516,9 +519,9 @@ add_virtual_operand (gimple stmt ATTRIBUTE_UNUSED, int flags) gcc_assert (!is_gimple_debug (stmt)); if (flags & opf_def) - append_vdef (gimple_vop (cfun)); + append_vdef (gimple_vop (fn)); else - append_vuse (gimple_vop (cfun)); + append_vuse (gimple_vop (fn)); } @@ -528,7 +531,7 @@ add_virtual_operand (gimple stmt ATTRIBUTE_UNUSED, int flags) added to virtual operands. */ static void -add_stmt_operand (tree *var_p, gimple stmt, int flags) +add_stmt_operand (struct function *fn, tree *var_p, gimple stmt, int flags) { tree var = *var_p; @@ -542,7 +545,7 @@ add_stmt_operand (tree *var_p, gimple stmt, int flags) else append_use (var_p); if (DECL_P (*var_p)) - cfun->gimple_df->ssa_renaming_needed = 1; + fn->gimple_df->ssa_renaming_needed = 1; } else { @@ -552,7 +555,7 @@ add_stmt_operand (tree *var_p, gimple stmt, int flags) gimple_set_has_volatile_ops (stmt, true); /* The variable is a memory access. Add virtual operands. */ - add_virtual_operand (stmt, flags); + add_virtual_operand (fn, stmt, flags); } } @@ -592,7 +595,8 @@ mark_address_taken (tree ref) FLAGS is as in get_expr_operands. */ static void -get_indirect_ref_operands (gimple stmt, tree expr, int flags) +get_mem_ref_operands (struct function *fn, + gimple stmt, tree expr, int flags) { tree *pptr = &TREE_OPERAND (expr, 0); @@ -601,10 +605,10 @@ get_indirect_ref_operands (gimple stmt, tree expr, int flags) gimple_set_has_volatile_ops (stmt, true); /* Add the VOP. */ - add_virtual_operand (stmt, flags); + add_virtual_operand (fn, stmt, flags); /* If requested, add a USE operand for the base pointer. */ - get_expr_operands (stmt, pptr, + get_expr_operands (fn, stmt, pptr, opf_non_addressable | opf_use | (flags & (opf_no_vops|opf_not_non_addressable))); } @@ -613,18 +617,21 @@ get_indirect_ref_operands (gimple stmt, tree expr, int flags) /* A subroutine of get_expr_operands to handle TARGET_MEM_REF. */ static void -get_tmr_operands (gimple stmt, tree expr, int flags) +get_tmr_operands (struct function *fn, gimple stmt, tree expr, int flags) { if (!(flags & opf_no_vops) && TREE_THIS_VOLATILE (expr)) gimple_set_has_volatile_ops (stmt, true); /* First record the real operands. */ - get_expr_operands (stmt, &TMR_BASE (expr), opf_use | (flags & opf_no_vops)); - get_expr_operands (stmt, &TMR_INDEX (expr), opf_use | (flags & opf_no_vops)); - get_expr_operands (stmt, &TMR_INDEX2 (expr), opf_use | (flags & opf_no_vops)); - - add_virtual_operand (stmt, flags); + get_expr_operands (fn, stmt, + &TMR_BASE (expr), opf_use | (flags & opf_no_vops)); + get_expr_operands (fn, stmt, + &TMR_INDEX (expr), opf_use | (flags & opf_no_vops)); + get_expr_operands (fn, stmt, + &TMR_INDEX2 (expr), opf_use | (flags & opf_no_vops)); + + add_virtual_operand (fn, stmt, flags); } @@ -632,7 +639,7 @@ get_tmr_operands (gimple stmt, tree expr, int flags) escape, add them to the VDEF/VUSE lists for it. */ static void -maybe_add_call_vops (gimple stmt) +maybe_add_call_vops (struct function *fn, gimple stmt) { int call_flags = gimple_call_flags (stmt); @@ -645,9 +652,9 @@ maybe_add_call_vops (gimple stmt) A 'noreturn' function might, but since we don't return anyway there is no point in recording that. */ if (!(call_flags & (ECF_PURE | ECF_CONST | ECF_NORETURN))) - add_virtual_operand (stmt, opf_def); + add_virtual_operand (fn, stmt, opf_def); else if (!(call_flags & ECF_CONST)) - add_virtual_operand (stmt, opf_use); + add_virtual_operand (fn, stmt, opf_use); } } @@ -655,7 +662,7 @@ maybe_add_call_vops (gimple stmt) /* Scan operands in the ASM_EXPR stmt referred to in INFO. */ static void -get_asm_expr_operands (gimple stmt) +get_asm_stmt_operands (struct function *fn, gimple stmt) { size_t i, noutputs; const char **oconstraints; @@ -682,7 +689,8 @@ get_asm_expr_operands (gimple stmt) if (!allows_reg && allows_mem) mark_address_taken (TREE_VALUE (link)); - get_expr_operands (stmt, &TREE_VALUE (link), opf_def | opf_not_non_addressable); + get_expr_operands (fn, stmt, + &TREE_VALUE (link), opf_def | opf_not_non_addressable); } /* Gather all input operands. */ @@ -698,12 +706,12 @@ get_asm_expr_operands (gimple stmt) if (!allows_reg && allows_mem) mark_address_taken (TREE_VALUE (link)); - get_expr_operands (stmt, &TREE_VALUE (link), opf_not_non_addressable); + get_expr_operands (fn, stmt, &TREE_VALUE (link), opf_not_non_addressable); } /* Clobber all memory and addressable symbols for asm ("" : : : "memory"); */ if (gimple_asm_clobbers_memory_p (stmt)) - add_virtual_operand (stmt, opf_def); + add_virtual_operand (fn, stmt, opf_def); } @@ -712,7 +720,7 @@ get_asm_expr_operands (gimple stmt) interpret the operands found. */ static void -get_expr_operands (gimple stmt, tree *expr_p, int flags) +get_expr_operands (struct function *fn, gimple stmt, tree *expr_p, int flags) { enum tree_code code; enum tree_code_class codeclass; @@ -740,26 +748,22 @@ get_expr_operands (gimple stmt, tree *expr_p, int flags) && !is_gimple_debug (stmt)) mark_address_taken (TREE_OPERAND (expr, 0)); - /* If the address is invariant, there may be no interesting - variable references inside. */ - if (is_gimple_min_invariant (expr)) - return; - /* Otherwise, there may be variables referenced inside but there should be no VUSEs created, since the referenced objects are not really accessed. The only operands that we should find here are ARRAY_REF indices which will always be real operands (GIMPLE does not allow non-registers as array indices). */ flags |= opf_no_vops; - get_expr_operands (stmt, &TREE_OPERAND (expr, 0), - flags | opf_not_non_addressable); + get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 0), + flags | opf_not_non_addressable | opf_address_taken); return; case SSA_NAME: case VAR_DECL: case PARM_DECL: case RESULT_DECL: - add_stmt_operand (expr_p, stmt, flags); + if (!(flags & opf_address_taken)) + add_stmt_operand (fn, expr_p, stmt, flags); return; case DEBUG_EXPR_DECL: @@ -767,11 +771,11 @@ get_expr_operands (gimple stmt, tree *expr_p, int flags) return; case MEM_REF: - get_indirect_ref_operands (stmt, expr, flags); + get_mem_ref_operands (fn, stmt, expr, flags); return; case TARGET_MEM_REF: - get_tmr_operands (stmt, expr, flags); + get_tmr_operands (fn, stmt, expr, flags); return; case ARRAY_REF: @@ -784,20 +788,20 @@ get_expr_operands (gimple stmt, tree *expr_p, int flags) && TREE_THIS_VOLATILE (expr)) gimple_set_has_volatile_ops (stmt, true); - get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags); + get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 0), flags); if (code == COMPONENT_REF) { if (!(flags & opf_no_vops) && TREE_THIS_VOLATILE (TREE_OPERAND (expr, 1))) gimple_set_has_volatile_ops (stmt, true); - get_expr_operands (stmt, &TREE_OPERAND (expr, 2), uflags); + get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 2), uflags); } else if (code == ARRAY_REF || code == ARRAY_RANGE_REF) { - get_expr_operands (stmt, &TREE_OPERAND (expr, 1), uflags); - get_expr_operands (stmt, &TREE_OPERAND (expr, 2), uflags); - get_expr_operands (stmt, &TREE_OPERAND (expr, 3), uflags); + get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 1), uflags); + get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 2), uflags); + get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 3), uflags); } return; @@ -806,16 +810,16 @@ get_expr_operands (gimple stmt, tree *expr_p, int flags) case WITH_SIZE_EXPR: /* WITH_SIZE_EXPR is a pass-through reference to its first argument, and an rvalue reference to its second argument. */ - get_expr_operands (stmt, &TREE_OPERAND (expr, 1), uflags); - get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags); + get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 1), uflags); + get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 0), flags); return; case COND_EXPR: case VEC_COND_EXPR: case VEC_PERM_EXPR: - get_expr_operands (stmt, &TREE_OPERAND (expr, 0), uflags); - get_expr_operands (stmt, &TREE_OPERAND (expr, 1), uflags); - get_expr_operands (stmt, &TREE_OPERAND (expr, 2), uflags); + get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 0), uflags); + get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 1), uflags); + get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 2), uflags); return; case CONSTRUCTOR: @@ -835,7 +839,7 @@ get_expr_operands (gimple stmt, tree *expr_p, int flags) for (idx = 0; vec_safe_iterate (CONSTRUCTOR_ELTS (expr), idx, &ce); idx++) - get_expr_operands (stmt, &ce->value, uflags); + get_expr_operands (fn, stmt, &ce->value, uflags); return; } @@ -848,7 +852,7 @@ get_expr_operands (gimple stmt, tree *expr_p, int flags) case VIEW_CONVERT_EXPR: do_unary: - get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags); + get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 0), flags); return; case COMPOUND_EXPR: @@ -856,8 +860,8 @@ get_expr_operands (gimple stmt, tree *expr_p, int flags) case ASSERT_EXPR: do_binary: { - get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags); - get_expr_operands (stmt, &TREE_OPERAND (expr, 1), flags); + get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 0), flags); + get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 1), flags); return; } @@ -867,9 +871,9 @@ get_expr_operands (gimple stmt, tree *expr_p, int flags) case WIDEN_MULT_MINUS_EXPR: case FMA_EXPR: { - get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags); - get_expr_operands (stmt, &TREE_OPERAND (expr, 1), flags); - get_expr_operands (stmt, &TREE_OPERAND (expr, 2), flags); + get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 0), flags); + get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 1), flags); + get_expr_operands (fn, stmt, &TREE_OPERAND (expr, 2), flags); return; } @@ -903,7 +907,7 @@ get_expr_operands (gimple stmt, tree *expr_p, int flags) build_* operand vectors will have potential operands in them. */ static void -parse_ssa_operands (gimple stmt) +parse_ssa_operands (struct function *fn, gimple stmt) { enum gimple_code code = gimple_code (stmt); size_t i, n, start = 0; @@ -911,32 +915,32 @@ parse_ssa_operands (gimple stmt) switch (code) { case GIMPLE_ASM: - get_asm_expr_operands (stmt); + get_asm_stmt_operands (fn, stmt); break; case GIMPLE_TRANSACTION: /* The start of a transaction is a memory barrier. */ - add_virtual_operand (stmt, opf_def | opf_use); + add_virtual_operand (fn, stmt, opf_def | opf_use); break; case GIMPLE_DEBUG: if (gimple_debug_bind_p (stmt) && gimple_debug_bind_has_value_p (stmt)) - get_expr_operands (stmt, gimple_debug_bind_get_value_ptr (stmt), + get_expr_operands (fn, stmt, gimple_debug_bind_get_value_ptr (stmt), opf_use | opf_no_vops); break; case GIMPLE_RETURN: - append_vuse (gimple_vop (cfun)); + append_vuse (gimple_vop (fn)); goto do_default; case GIMPLE_CALL: /* Add call-clobbered operands, if needed. */ - maybe_add_call_vops (stmt); + maybe_add_call_vops (fn, stmt); /* FALLTHRU */ case GIMPLE_ASSIGN: - get_expr_operands (stmt, gimple_op_ptr (stmt, 0), opf_def); + get_expr_operands (fn, stmt, gimple_op_ptr (stmt, 0), opf_def); start = 1; /* FALLTHRU */ @@ -944,7 +948,7 @@ parse_ssa_operands (gimple stmt) do_default: n = gimple_num_ops (stmt); for (i = start; i < n; i++) - get_expr_operands (stmt, gimple_op_ptr (stmt, i), opf_use); + get_expr_operands (fn, stmt, gimple_op_ptr (stmt, i), opf_use); break; } } @@ -953,20 +957,20 @@ parse_ssa_operands (gimple stmt) /* Create an operands cache for STMT. */ static void -build_ssa_operands (gimple stmt) +build_ssa_operands (struct function *fn, gimple stmt) { /* Initially assume that the statement has no volatile operands. */ gimple_set_has_volatile_ops (stmt, false); start_ssa_stmt_operands (); - parse_ssa_operands (stmt); - finalize_ssa_stmt_operands (stmt); + parse_ssa_operands (fn, stmt); + finalize_ssa_stmt_operands (fn, stmt); } /* Verifies SSA statement operands. */ DEBUG_FUNCTION bool -verify_ssa_operands (gimple stmt) +verify_ssa_operands (struct function *fn, gimple stmt) { use_operand_p use_p; def_operand_p def_p; @@ -978,7 +982,7 @@ verify_ssa_operands (gimple stmt) /* build_ssa_operands w/o finalizing them. */ gimple_set_has_volatile_ops (stmt, false); start_ssa_stmt_operands (); - parse_ssa_operands (stmt); + parse_ssa_operands (fn, stmt); /* Now verify the built operands are the same as present in STMT. */ def = gimple_vdef (stmt); @@ -1055,7 +1059,7 @@ verify_ssa_operands (gimple stmt) the stmt operand lists. */ void -free_stmt_operands (gimple stmt) +free_stmt_operands (struct function *fn, gimple stmt) { use_optype_p uses = gimple_use_ops (stmt), last_use; @@ -1064,8 +1068,8 @@ free_stmt_operands (gimple stmt) for (last_use = uses; last_use->next; last_use = last_use->next) delink_imm_use (USE_OP_PTR (last_use)); delink_imm_use (USE_OP_PTR (last_use)); - last_use->next = gimple_ssa_operands (cfun)->free_uses; - gimple_ssa_operands (cfun)->free_uses = uses; + last_use->next = gimple_ssa_operands (fn)->free_uses; + gimple_ssa_operands (fn)->free_uses = uses; gimple_set_use_ops (stmt, NULL); } @@ -1080,11 +1084,11 @@ free_stmt_operands (gimple stmt) /* Get the operands of statement STMT. */ void -update_stmt_operands (gimple stmt) +update_stmt_operands (struct function *fn, gimple stmt) { /* If update_stmt_operands is called before SSA is initialized, do nothing. */ - if (!ssa_operands_active (cfun)) + if (!ssa_operands_active (fn)) return; timevar_push (TV_TREE_OPS); @@ -1093,10 +1097,10 @@ update_stmt_operands (gimple stmt) split_bbs_on_noreturn_calls during cfg cleanup. */ if (is_gimple_call (stmt) && gimple_call_noreturn_p (stmt)) - vec_safe_push (MODIFIED_NORETURN_CALLS (cfun), stmt); + vec_safe_push (MODIFIED_NORETURN_CALLS (fn), stmt); gcc_assert (gimple_modified_p (stmt)); - build_ssa_operands (stmt); + build_ssa_operands (fn, stmt); gimple_set_modified (stmt, false); timevar_pop (TV_TREE_OPS); @@ -1113,8 +1117,6 @@ swap_ssa_operands (gimple stmt, tree *exp0, tree *exp1) op0 = *exp0; op1 = *exp1; - gcc_checking_assert (ssa_operands_active (cfun)); - if (op0 != op1) { /* Attempt to preserve the relative positions of these two operands in diff --git a/gcc/tree-ssa-operands.h b/gcc/tree-ssa-operands.h index 759b155a3e7..2d838005955 100644 --- a/gcc/tree-ssa-operands.h +++ b/gcc/tree-ssa-operands.h @@ -91,10 +91,10 @@ struct GTY(()) ssa_operands { extern bool ssa_operands_active (struct function *); extern void init_ssa_operands (struct function *fn); -extern void fini_ssa_operands (void); -extern bool verify_ssa_operands (gimple stmt); -extern void free_stmt_operands (gimple); -extern void update_stmt_operands (gimple); +extern void fini_ssa_operands (struct function *); +extern bool verify_ssa_operands (struct function *, gimple stmt); +extern void free_stmt_operands (struct function *, gimple); +extern void update_stmt_operands (struct function *, gimple); extern void swap_ssa_operands (gimple, tree *, tree *); extern bool verify_imm_links (FILE *f, tree var); diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c index 61e4dbde35e..6f8d30e6b34 100644 --- a/gcc/tree-ssa-phiopt.c +++ b/gcc/tree-ssa-phiopt.c @@ -22,12 +22,16 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "hash-table.h" #include "tm.h" -#include "ggc.h" #include "tree.h" #include "stor-layout.h" #include "flags.h" #include "tm_p.h" #include "basic-block.h" +#include "pointer-set.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "gimple-iterator.h" @@ -42,7 +46,6 @@ along with GCC; see the file COPYING3. If not see #include "tree-dfa.h" #include "tree-pass.h" #include "langhooks.h" -#include "pointer-set.h" #include "domwalk.h" #include "cfgloop.h" #include "tree-data-ref.h" diff --git a/gcc/tree-ssa-phiprop.c b/gcc/tree-ssa-phiprop.c index 389423b04c4..763d562344c 100644 --- a/gcc/tree-ssa-phiprop.c +++ b/gcc/tree-ssa-phiprop.c @@ -26,6 +26,11 @@ along with GCC; see the file COPYING3. If not see #include "tm_p.h" #include "basic-block.h" #include "gimple-pretty-print.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "gimple-iterator.h" diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c index cea3e2ccd97..ff616f36a32 100644 --- a/gcc/tree-ssa-pre.c +++ b/gcc/tree-ssa-pre.c @@ -27,6 +27,13 @@ along with GCC; see the file COPYING3. If not see #include "basic-block.h" #include "gimple-pretty-print.h" #include "tree-inline.h" +#include "hash-table.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "gimple-iterator.h" @@ -42,7 +49,6 @@ along with GCC; see the file COPYING3. If not see #include "expr.h" #include "tree-dfa.h" #include "tree-ssa.h" -#include "hash-table.h" #include "tree-iterator.h" #include "alloc-pool.h" #include "obstack.h" diff --git a/gcc/tree-ssa-propagate.c b/gcc/tree-ssa-propagate.c index b45ff4755c2..783b6513e30 100644 --- a/gcc/tree-ssa-propagate.c +++ b/gcc/tree-ssa-propagate.c @@ -30,6 +30,12 @@ #include "gimple-pretty-print.h" #include "dumpfile.h" #include "sbitmap.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "gimple-iterator.h" @@ -42,7 +48,6 @@ #include "tree-ssa.h" #include "tree-ssa-propagate.h" #include "langhooks.h" -#include "vec.h" #include "value-prof.h" /* This file implements a generic value propagation engine based on @@ -662,7 +667,7 @@ valid_gimple_call_p (tree expr) for (i = 0; i < nargs; i++) { tree arg = CALL_EXPR_ARG (expr, i); - if (is_gimple_reg_type (arg)) + if (is_gimple_reg_type (TREE_TYPE (arg))) { if (!is_gimple_val (arg)) return false; diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c index 0f1dfcd5b2f..3e7839fd4cc 100644 --- a/gcc/tree-ssa-reassoc.c +++ b/gcc/tree-ssa-reassoc.c @@ -30,6 +30,13 @@ along with GCC; see the file COPYING3. If not see #include "basic-block.h" #include "gimple-pretty-print.h" #include "tree-inline.h" +#include "pointer-set.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimplify-me.h" @@ -47,9 +54,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-iterator.h" #include "tree-pass.h" #include "alloc-pool.h" -#include "vec.h" #include "langhooks.h" -#include "pointer-set.h" #include "cfgloop.h" #include "flags.h" #include "target.h" @@ -2930,9 +2935,15 @@ maybe_optimize_range_tests (gimple stmt) tree new_lhs = make_ssa_name (TREE_TYPE (lhs), NULL); enum tree_code rhs_code = gimple_assign_rhs_code (cast_stmt); - gimple g - = gimple_build_assign_with_ops (rhs_code, new_lhs, - new_op, NULL_TREE); + gimple g; + if (is_gimple_min_invariant (new_op)) + { + new_op = fold_convert (TREE_TYPE (lhs), new_op); + g = gimple_build_assign (new_lhs, new_op); + } + else + g = gimple_build_assign_with_ops (rhs_code, new_lhs, + new_op, NULL_TREE); gimple_stmt_iterator gsi = gsi_for_stmt (cast_stmt); gimple_set_uid (g, gimple_uid (cast_stmt)); gimple_set_visited (g, true); diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c index 136b95a0bfb..454d355ac28 100644 --- a/gcc/tree-ssa-sccvn.c +++ b/gcc/tree-ssa-sccvn.c @@ -27,6 +27,13 @@ along with GCC; see the file COPYING3. If not see #include "basic-block.h" #include "gimple-pretty-print.h" #include "tree-inline.h" +#include "hash-table.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "gimple-ssa.h" @@ -38,7 +45,6 @@ along with GCC; see the file COPYING3. If not see #include "tree-dfa.h" #include "tree-ssa.h" #include "dumpfile.h" -#include "hash-table.h" #include "alloc-pool.h" #include "flags.h" #include "cfgloop.h" diff --git a/gcc/tree-ssa-sink.c b/gcc/tree-ssa-sink.c index 305882dd06f..947a58a13d1 100644 --- a/gcc/tree-ssa-sink.c +++ b/gcc/tree-ssa-sink.c @@ -27,6 +27,10 @@ along with GCC; see the file COPYING3. If not see #include "basic-block.h" #include "gimple-pretty-print.h" #include "tree-inline.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimple-ssa.h" diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c index 514b1b829e2..3f88ff65c81 100644 --- a/gcc/tree-ssa-strlen.c +++ b/gcc/tree-ssa-strlen.c @@ -25,6 +25,13 @@ along with GCC; see the file COPYING3. If not see #include "stor-layout.h" #include "hash-table.h" #include "bitmap.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "gimple-iterator.h" diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c index 482b69e0727..b08a20e2694 100644 --- a/gcc/tree-ssa-structalias.c +++ b/gcc/tree-ssa-structalias.c @@ -22,7 +22,6 @@ #include "system.h" #include "coretypes.h" #include "tm.h" -#include "ggc.h" #include "obstack.h" #include "bitmap.h" #include "sbitmap.h" @@ -31,6 +30,12 @@ #include "tree.h" #include "stor-layout.h" #include "stmt.h" +#include "pointer-set.h" +#include "hash-table.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimple-ssa.h" @@ -42,14 +47,12 @@ #include "tree-dfa.h" #include "tree-inline.h" #include "diagnostic-core.h" -#include "hash-table.h" #include "function.h" #include "tree-pass.h" #include "alloc-pool.h" #include "splay-tree.h" #include "params.h" #include "alias.h" -#include "pointer-set.h" /* The idea behind this analyzer is to generate set constraints from the program, then solve the resulting constraints in order to generate the @@ -3159,29 +3162,6 @@ get_constraint_for_component_ref (tree t, vec<ce_s> *results, return; } - /* Handle type-punning through unions. If we are extracting a pointer - from a union via a possibly type-punning access that pointer - points to anything, similar to a conversion of an integer to - a pointer. */ - if (!lhs_p) - { - tree u; - for (u = t; - TREE_CODE (u) == COMPONENT_REF || TREE_CODE (u) == ARRAY_REF; - u = TREE_OPERAND (u, 0)) - if (TREE_CODE (u) == COMPONENT_REF - && TREE_CODE (TREE_TYPE (TREE_OPERAND (u, 0))) == UNION_TYPE) - { - struct constraint_expr temp; - - temp.offset = 0; - temp.var = anything_id; - temp.type = ADDRESSOF; - results->safe_push (temp); - return; - } - } - t = get_ref_base_and_extent (t, &bitpos, &bitsize, &bitmaxsize); /* Pretend to take the address of the base, we'll take care of diff --git a/gcc/tree-ssa-tail-merge.c b/gcc/tree-ssa-tail-merge.c index 2e1df69b7bd..d722a9bedfb 100644 --- a/gcc/tree-ssa-tail-merge.c +++ b/gcc/tree-ssa-tail-merge.c @@ -196,6 +196,12 @@ along with GCC; see the file COPYING3. If not see #include "basic-block.h" #include "flags.h" #include "function.h" +#include "hash-table.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimple-ssa.h" @@ -203,9 +209,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-phinodes.h" #include "ssa-iterators.h" #include "tree-into-ssa.h" -#include "tree-ssa-alias.h" #include "params.h" -#include "hash-table.h" #include "gimple-pretty-print.h" #include "tree-ssa-sccvn.h" #include "tree-dump.h" diff --git a/gcc/tree-ssa-ter.c b/gcc/tree-ssa-ter.c index 9b9e655b726..fa6a248c5ac 100644 --- a/gcc/tree-ssa-ter.c +++ b/gcc/tree-ssa-ter.c @@ -26,6 +26,11 @@ along with GCC; see the file COPYING3. If not see #include "tree.h" #include "gimple-pretty-print.h" #include "bitmap.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimple-ssa.h" diff --git a/gcc/tree-ssa-threadedge.c b/gcc/tree-ssa-threadedge.c index 7600d7b9914..cb6accf08f4 100644 --- a/gcc/tree-ssa-threadedge.c +++ b/gcc/tree-ssa-threadedge.c @@ -30,6 +30,11 @@ along with GCC; see the file COPYING3. If not see #include "function.h" #include "timevar.h" #include "dumpfile.h" +#include "pointer-set.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimple-ssa.h" @@ -170,7 +175,8 @@ record_temporary_equivalence (tree x, tree y, vec<tree> *stack) { tree prev_x = SSA_NAME_VALUE (x); - if (TREE_CODE (y) == SSA_NAME) + /* Y may be NULL if we are invalidating entries in the table. */ + if (y && TREE_CODE (y) == SSA_NAME) { tree tmp = SSA_NAME_VALUE (y); y = tmp ? tmp : y; @@ -186,10 +192,16 @@ record_temporary_equivalence (tree x, tree y, vec<tree> *stack) edge E. Record unwind information for the equivalences onto STACK. If a PHI which prevents threading is encountered, then return FALSE - indicating we should not thread this edge, else return TRUE. */ + indicating we should not thread this edge, else return TRUE. + + If SRC_MAP/DST_MAP exist, then mark the source and destination SSA_NAMEs + of any equivalences recorded. We use this to make invalidation after + traversing back edges less painful. */ static bool -record_temporary_equivalences_from_phis (edge e, vec<tree> *stack) +record_temporary_equivalences_from_phis (edge e, vec<tree> *stack, + bool backedge_seen, + bitmap src_map, bitmap dst_map) { gimple_stmt_iterator gsi; @@ -217,6 +229,14 @@ record_temporary_equivalences_from_phis (edge e, vec<tree> *stack) stmt_count++; record_temporary_equivalence (dst, src, stack); + + /* If we have crossed a backedge, then start recording equivalences + we might need to invalidate. */ + if (backedge_seen && TREE_CODE (src) == SSA_NAME) + { + bitmap_set_bit (src_map, SSA_NAME_VERSION (src)); + bitmap_set_bit (dst_map, SSA_NAME_VERSION (dst)); + } } return true; } @@ -271,6 +291,34 @@ fold_assignment_stmt (gimple stmt) } } +/* A new value has been assigned to LHS. If necessary, invalidate any + equivalences that are no longer valid. */ +static void +invalidate_equivalences (tree lhs, vec<tree> *stack, + bitmap src_map, bitmap dst_map) +{ + /* SRC_MAP contains the source SSA_NAMEs for equivalences created by PHI + nodes. If an entry in SRC_MAP changes, there's some destination that + has been recorded as equivalent to the source and that equivalency + needs to be eliminated. */ + if (bitmap_bit_p (src_map, SSA_NAME_VERSION (lhs))) + { + unsigned int i; + bitmap_iterator bi; + + /* We know that the LHS of STMT was used as the RHS in an equivalency + created by a PHI. All the LHS of such PHIs were recorded into DST_MAP. + So we can iterate over them to see if any have the LHS of STMT as + an equivalence, and if so, remove the equivalence as it is no longer + valid. */ + EXECUTE_IF_SET_IN_BITMAP (dst_map, 0, i, bi) + { + if (SSA_NAME_VALUE (ssa_name (i)) == lhs) + record_temporary_equivalence (ssa_name (i), NULL_TREE, stack); + } + } +} + /* Try to simplify each statement in E->dest, ultimately leading to a simplification of the COND_EXPR at the end of E->dest. @@ -292,7 +340,10 @@ static gimple record_temporary_equivalences_from_stmts_at_dest (edge e, vec<tree> *stack, tree (*simplify) (gimple, - gimple)) + gimple), + bool backedge_seen, + bitmap src_map, + bitmap dst_map) { gimple stmt = NULL; gimple_stmt_iterator gsi; @@ -369,7 +420,15 @@ record_temporary_equivalences_from_stmts_at_dest (edge e, if (fndecl && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_OBJECT_SIZE || DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CONSTANT_P)) - continue; + { + if (backedge_seen) + { + tree lhs = gimple_get_lhs (stmt); + record_temporary_equivalence (lhs, NULL_TREE, stack); + invalidate_equivalences (lhs, stack, src_map, dst_map); + } + continue; + } } /* At this point we have a statement which assigns an RHS to an @@ -433,15 +492,36 @@ record_temporary_equivalences_from_stmts_at_dest (edge e, } /* Record the context sensitive equivalence if we were able - to simplify this statement. */ + to simplify this statement. + + If we have traversed a backedge at some point during threading, + then always enter something here. Either a real equivalence, + or a NULL_TREE equivalence which is effectively invalidation of + prior equivalences. */ if (cached_lhs && (TREE_CODE (cached_lhs) == SSA_NAME || is_gimple_min_invariant (cached_lhs))) record_temporary_equivalence (gimple_get_lhs (stmt), cached_lhs, stack); + else if (backedge_seen) + record_temporary_equivalence (gimple_get_lhs (stmt), NULL_TREE, stack); + + if (backedge_seen) + invalidate_equivalences (gimple_get_lhs (stmt), stack, + src_map, dst_map); } return stmt; } +/* Once we have passed a backedge in the CFG when threading, we do not want to + utilize edge equivalences for simplification purpose. They are no longer + necessarily valid. We use this callback rather than the ones provided by + DOM/VRP to achieve that effect. */ +static tree +dummy_simplify (gimple stmt1 ATTRIBUTE_UNUSED, gimple stmt2 ATTRIBUTE_UNUSED) +{ + return NULL_TREE; +} + /* Simplify the control statement at the end of the block E->dest. To avoid allocating memory unnecessarily, a scratch GIMPLE_COND @@ -581,44 +661,6 @@ simplify_control_stmt_condition (edge e, return cached_lhs; } -/* Return TRUE if the statement at the end of e->dest depends on - the output of any statement in BB. Otherwise return FALSE. - - This is used when we are threading a backedge and need to ensure - that temporary equivalences from BB do not affect the condition - in e->dest. */ - -static bool -cond_arg_set_in_bb (edge e, basic_block bb) -{ - ssa_op_iter iter; - use_operand_p use_p; - gimple last = last_stmt (e->dest); - - /* E->dest does not have to end with a control transferring - instruction. This can occur when we try to extend a jump - threading opportunity deeper into the CFG. In that case - it is safe for this check to return false. */ - if (!last) - return false; - - if (gimple_code (last) != GIMPLE_COND - && gimple_code (last) != GIMPLE_GOTO - && gimple_code (last) != GIMPLE_SWITCH) - return false; - - FOR_EACH_SSA_USE_OPERAND (use_p, last, iter, SSA_OP_USE | SSA_OP_VUSE) - { - tree use = USE_FROM_PTR (use_p); - - if (TREE_CODE (use) == SSA_NAME - && gimple_code (SSA_NAME_DEF_STMT (use)) != GIMPLE_PHI - && gimple_bb (SSA_NAME_DEF_STMT (use)) == bb) - return true; - } - return false; -} - /* Copy debug stmts from DEST's chain of single predecessors up to SRC, so that we don't lose the bindings as PHI nodes are introduced when DEST gains new predecessors. */ @@ -805,6 +847,8 @@ thread_around_empty_blocks (edge taken_edge, path->safe_push (x); bitmap_set_bit (visited, taken_edge->dest->index); *backedge_seen_p |= ((taken_edge->flags & EDGE_DFS_BACK) != 0); + if (*backedge_seen_p) + simplify = dummy_simplify; return thread_around_empty_blocks (taken_edge, dummy_cond, handle_dominating_asserts, @@ -827,6 +871,13 @@ thread_around_empty_blocks (edge taken_edge, && gimple_code (stmt) != GIMPLE_SWITCH) return false; + /* If we have traversed a backedge, then we do not want to look + at certain expressions in the table that can not be relied upon. + Luckily the only code that looked at those expressions is the + SIMPLIFY callback, which we replace if we can no longer use it. */ + if (*backedge_seen_p) + simplify = dummy_simplify; + /* Extract and simplify the condition. */ cond = simplify_control_stmt_condition (taken_edge, stmt, dummy_cond, simplify, handle_dominating_asserts); @@ -846,6 +897,8 @@ thread_around_empty_blocks (edge taken_edge, = new jump_thread_edge (taken_edge, EDGE_NO_COPY_SRC_BLOCK); path->safe_push (x); *backedge_seen_p |= ((taken_edge->flags & EDGE_DFS_BACK) != 0); + if (*backedge_seen_p) + simplify = dummy_simplify; thread_around_empty_blocks (taken_edge, dummy_cond, @@ -896,24 +949,28 @@ thread_through_normal_block (edge e, tree (*simplify) (gimple, gimple), vec<jump_thread_edge *> *path, bitmap visited, - bool *backedge_seen_p) + bool *backedge_seen_p, + bitmap src_map, + bitmap dst_map) { - /* If we have crossed a backedge, then we want to verify that the COND_EXPR, - SWITCH_EXPR or GOTO_EXPR at the end of e->dest is not affected - by any statements in e->dest. If it is affected, then it is not - safe to thread this edge. */ - if (*backedge_seen_p - && cond_arg_set_in_bb (e, e->dest)) - return false; + /* If we have traversed a backedge, then we do not want to look + at certain expressions in the table that can not be relied upon. + Luckily the only code that looked at those expressions is the + SIMPLIFY callback, which we replace if we can no longer use it. */ + if (*backedge_seen_p) + simplify = dummy_simplify; /* PHIs create temporary equivalences. */ - if (!record_temporary_equivalences_from_phis (e, stack)) + if (!record_temporary_equivalences_from_phis (e, stack, *backedge_seen_p, + src_map, dst_map)) return false; /* Now walk each statement recording any context sensitive temporary equivalences we can detect. */ gimple stmt - = record_temporary_equivalences_from_stmts_at_dest (e, stack, simplify); + = record_temporary_equivalences_from_stmts_at_dest (e, stack, simplify, + *backedge_seen_p, + src_map, dst_map); if (!stmt) return false; @@ -955,25 +1012,24 @@ thread_through_normal_block (edge e, = new jump_thread_edge (taken_edge, EDGE_COPY_SRC_BLOCK); path->safe_push (x); *backedge_seen_p |= ((taken_edge->flags & EDGE_DFS_BACK) != 0); + if (*backedge_seen_p) + simplify = dummy_simplify; /* See if we can thread through DEST as well, this helps capture secondary effects of threading without having to re-run DOM or - VRP. */ - if (!*backedge_seen_p - || ! cond_arg_set_in_bb (taken_edge, e->dest)) - { - /* We don't want to thread back to a block we have already - visited. This may be overly conservative. */ - bitmap_set_bit (visited, dest->index); - bitmap_set_bit (visited, e->dest->index); - thread_around_empty_blocks (taken_edge, - dummy_cond, - handle_dominating_asserts, - simplify, - visited, - path, - backedge_seen_p); - } + VRP. + + We don't want to thread back to a block we have already + visited. This may be overly conservative. */ + bitmap_set_bit (visited, dest->index); + bitmap_set_bit (visited, e->dest->index); + thread_around_empty_blocks (taken_edge, + dummy_cond, + handle_dominating_asserts, + simplify, + visited, + path, + backedge_seen_p); return true; } } @@ -1015,6 +1071,8 @@ thread_across_edge (gimple dummy_cond, tree (*simplify) (gimple, gimple)) { bitmap visited = BITMAP_ALLOC (NULL); + bitmap src_map = BITMAP_ALLOC (NULL); + bitmap dst_map = BITMAP_ALLOC (NULL); bool backedge_seen; stmt_count = 0; @@ -1024,14 +1082,19 @@ thread_across_edge (gimple dummy_cond, bitmap_set_bit (visited, e->src->index); bitmap_set_bit (visited, e->dest->index); backedge_seen = ((e->flags & EDGE_DFS_BACK) != 0); + if (backedge_seen) + simplify = dummy_simplify; + if (thread_through_normal_block (e, dummy_cond, handle_dominating_asserts, stack, simplify, path, visited, - &backedge_seen)) + &backedge_seen, src_map, dst_map)) { propagate_threaded_block_debug_into (path->last ()->e->dest, e->dest); remove_temporary_equivalences (stack); BITMAP_FREE (visited); + BITMAP_FREE (src_map); + BITMAP_FREE (dst_map); register_jump_thread (path); return; } @@ -1066,15 +1129,26 @@ thread_across_edge (gimple dummy_cond, { remove_temporary_equivalences (stack); BITMAP_FREE (visited); + BITMAP_FREE (src_map); + BITMAP_FREE (dst_map); return; } + /* We need to restore the state of the maps to this point each loop + iteration. */ + bitmap src_map_copy = BITMAP_ALLOC (NULL); + bitmap dst_map_copy = BITMAP_ALLOC (NULL); + bitmap_copy (src_map_copy, src_map); + bitmap_copy (dst_map_copy, dst_map); + /* Look at each successor of E->dest to see if we can thread through it. */ FOR_EACH_EDGE (taken_edge, ei, e->dest->succs) { /* Push a fresh marker so we can unwind the equivalences created for each of E->dest's successors. */ stack->safe_push (NULL_TREE); + bitmap_copy (src_map, src_map_copy); + bitmap_copy (dst_map, dst_map_copy); /* Avoid threading to any block we have already visited. */ bitmap_clear (visited); @@ -1093,23 +1167,25 @@ thread_across_edge (gimple dummy_cond, found = false; backedge_seen = ((e->flags & EDGE_DFS_BACK) != 0); backedge_seen |= ((taken_edge->flags & EDGE_DFS_BACK) != 0); - if (!backedge_seen - || ! cond_arg_set_in_bb (path->last ()->e, e->dest)) - found = thread_around_empty_blocks (taken_edge, - dummy_cond, - handle_dominating_asserts, - simplify, - visited, - path, - &backedge_seen); - - if (!found - && (!backedge_seen - || ! cond_arg_set_in_bb (path->last ()->e, e->dest))) + if (backedge_seen) + simplify = dummy_simplify; + found = thread_around_empty_blocks (taken_edge, + dummy_cond, + handle_dominating_asserts, + simplify, + visited, + path, + &backedge_seen); + + if (backedge_seen) + simplify = dummy_simplify; + + if (!found) found = thread_through_normal_block (path->last ()->e, dummy_cond, handle_dominating_asserts, stack, simplify, path, visited, - &backedge_seen); + &backedge_seen, + src_map, dst_map); /* If we were able to thread through a successor of E->dest, then record the jump threading opportunity. */ @@ -1128,6 +1204,10 @@ thread_across_edge (gimple dummy_cond, remove_temporary_equivalences (stack); } BITMAP_FREE (visited); + BITMAP_FREE (src_map); + BITMAP_FREE (dst_map); + BITMAP_FREE (src_map_copy); + BITMAP_FREE (dst_map_copy); } remove_temporary_equivalences (stack); diff --git a/gcc/tree-ssa-threadupdate.c b/gcc/tree-ssa-threadupdate.c index 60c1815d529..ad727a1afec 100644 --- a/gcc/tree-ssa-threadupdate.c +++ b/gcc/tree-ssa-threadupdate.c @@ -24,6 +24,11 @@ along with GCC; see the file COPYING3. If not see #include "flags.h" #include "basic-block.h" #include "function.h" +#include "hash-table.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimple-ssa.h" @@ -33,7 +38,6 @@ along with GCC; see the file COPYING3. If not see #include "ssa-iterators.h" #include "dumpfile.h" #include "cfgloop.h" -#include "hash-table.h" #include "dbgcnt.h" #include "tree-cfg.h" #include "tree-pass.h" @@ -417,27 +421,22 @@ create_edge_and_update_destination_phis (struct redirection_data *rd, e->probability = REG_BR_PROB_BASE; e->count = bb->count; - /* We have to copy path -- which means creating a new vector as well - as all the jump_thread_edge entries. */ - if (rd->path->last ()->e->aux) - { - vec<jump_thread_edge *> *path = THREAD_PATH (rd->path->last ()->e); - vec<jump_thread_edge *> *copy = new vec<jump_thread_edge *> (); + /* We used to copy the thread path here. That was added in 2007 + and dutifully updated through the representation changes in 2013. - /* Sadly, the elements of the vector are pointers and need to - be copied as well. */ - for (unsigned int i = 0; i < path->length (); i++) - { - jump_thread_edge *x - = new jump_thread_edge ((*path)[i]->e, (*path)[i]->type); - copy->safe_push (x); - } - e->aux = (void *)copy; - } - else - { - e->aux = NULL; - } + In 2013 we added code to thread from an interior node through + the backedge to another interior node. That runs after the code + to thread through loop headers from outside the loop. + + The latter may delete edges in the CFG, including those + which appeared in the jump threading path we copied here. Thus + we'd end up using a dangling pointer. + + After reviewing the 2007/2011 code, I can't see how anything + depended on copying the AUX field and clearly copying the jump + threading path is problematical due to embedded edge pointers. + It has been removed. */ + e->aux = NULL; /* If there are any PHI nodes at the destination of the outgoing edge from the duplicate block, then we will need to add a new argument @@ -1575,7 +1574,6 @@ thread_through_all_blocks (bool may_peel_loop_headers) bitmap_iterator bi; bitmap threaded_blocks; struct loop *loop; - bool totally_clobbered_loops = false; /* We must know about loops in order to preserve them. */ gcc_assert (current_loops != NULL); @@ -1671,9 +1669,22 @@ thread_through_all_blocks (bool may_peel_loop_headers) /* Our path is still valid, thread it. */ if (e->aux) { - totally_clobbered_loops - |= thread_block ((*path)[0]->e->dest, false); - e->aux = NULL; + struct loop *loop = (*path)[0]->e->dest->loop_father; + + if (thread_block ((*path)[0]->e->dest, false)) + { + /* This jump thread likely totally scrambled this loop. + So arrange for it to be fixed up. */ + loop->header = NULL; + loop->latch = NULL; + e->aux = NULL; + } + else + { + delete_jump_thread_path (path); + e->aux = NULL; + ei_next (&ei); + } } } else @@ -1696,32 +1707,7 @@ thread_through_all_blocks (bool may_peel_loop_headers) threaded_blocks = NULL; paths.release (); - /* If we made changes to the CFG that might have totally messed - up the loop structure, then drop the old loop structure and - rebuild. */ - if (totally_clobbered_loops) - { - /* Release the current loop structures, they are totally - clobbered at this point. */ - loop_optimizer_finalize (); - current_loops = NULL; - - /* Similarly for dominance information. */ - free_dominance_info (CDI_DOMINATORS); - free_dominance_info (CDI_POST_DOMINATORS); - - /* Before we can rebuild the loop structures, we need dominators, - which requires no unreachable code. So remove unreachable code. */ - delete_unreachable_blocks (); - - /* Now rebuild the loop structures. */ - cfun->curr_properties &= ~PROP_loops; - loop_optimizer_init (AVOID_CFG_MODIFICATIONS); - cfun->curr_properties |= PROP_loops; - retval = 1; - } - - if (retval && current_loops) + if (retval) loops_state_set (LOOPS_NEED_FIXUP); return retval; diff --git a/gcc/tree-ssa-uncprop.c b/gcc/tree-ssa-uncprop.c index 62ffe421f29..44194b83ae6 100644 --- a/gcc/tree-ssa-uncprop.c +++ b/gcc/tree-ssa-uncprop.c @@ -27,6 +27,11 @@ along with GCC; see the file COPYING3. If not see #include "tm_p.h" #include "basic-block.h" #include "function.h" +#include "hash-table.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimple-ssa.h" diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c index 967b167727f..0f11a43d398 100644 --- a/gcc/tree-ssa-uninit.c +++ b/gcc/tree-ssa-uninit.c @@ -30,6 +30,10 @@ along with GCC; see the file COPYING3. If not see #include "gimple-pretty-print.h" #include "bitmap.h" #include "pointer-set.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimple-ssa.h" diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c index 550381ae94d..9b31a712935 100644 --- a/gcc/tree-ssa.c +++ b/gcc/tree-ssa.c @@ -26,12 +26,16 @@ along with GCC; see the file COPYING3. If not see #include "flags.h" #include "tm_p.h" #include "target.h" -#include "ggc.h" #include "langhooks.h" #include "basic-block.h" #include "function.h" #include "gimple-pretty-print.h" #include "pointer-set.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "gimple-iterator.h" @@ -1038,7 +1042,7 @@ verify_ssa (bool check_modified_stmt) goto err; } - if (verify_ssa_operands (stmt)) + if (verify_ssa_operands (cfun, stmt)) { print_gimple_stmt (stderr, stmt, 0, TDF_VOPS); goto err; @@ -1191,7 +1195,7 @@ delete_tree_ssa (void) /* We no longer maintain the SSA operand cache at this point. */ if (ssa_operands_active (cfun)) - fini_ssa_operands (); + fini_ssa_operands (cfun); htab_delete (cfun->gimple_df->default_defs); cfun->gimple_df->default_defs = NULL; diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c index 4c04a8c8af5..be358e1d97d 100644 --- a/gcc/tree-ssanames.c +++ b/gcc/tree-ssanames.c @@ -23,6 +23,11 @@ along with GCC; see the file COPYING3. If not see #include "tm.h" #include "tree.h" #include "stor-layout.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-ssa.h" #include "tree-phinodes.h" @@ -286,7 +291,7 @@ get_nonzero_bits (const_tree name) other fields must be assumed clobbered. */ void -release_ssa_name (tree var) +release_ssa_name_fn (struct function *fn, tree var) { if (!var) return; @@ -326,7 +331,7 @@ release_ssa_name (tree var) while (imm->next != imm) delink_imm_use (imm->next); - (*SSANAMES (cfun))[SSA_NAME_VERSION (var)] = NULL_TREE; + (*SSANAMES (fn))[SSA_NAME_VERSION (var)] = NULL_TREE; memset (var, 0, tree_size (var)); imm->prev = imm; @@ -348,7 +353,7 @@ release_ssa_name (tree var) SSA_NAME_IN_FREE_LIST (var) = 1; /* And finally put it on the free list. */ - vec_safe_push (FREE_SSANAMES (cfun), var); + vec_safe_push (FREE_SSANAMES (fn), var); } } diff --git a/gcc/tree-ssanames.h b/gcc/tree-ssanames.h index 23c988cb2a2..027137bf3a8 100644 --- a/gcc/tree-ssanames.h +++ b/gcc/tree-ssanames.h @@ -80,7 +80,7 @@ extern void init_ssanames (struct function *, int); extern void fini_ssanames (void); extern void ssanames_print_statistics (void); extern tree make_ssa_name_fn (struct function *, tree, gimple); -extern void release_ssa_name (tree); +extern void release_ssa_name_fn (struct function *, tree); extern bool get_ptr_info_alignment (struct ptr_info_def *, unsigned int *, unsigned int *); extern void mark_ptr_info_alignment_unknown (struct ptr_info_def *); @@ -126,6 +126,14 @@ duplicate_ssa_name (tree var, gimple stmt) return duplicate_ssa_name_fn (cfun, var, stmt); } +/* Release the SSA name NAME used in function cfun. */ + +static inline void +release_ssa_name (tree name) +{ + release_ssa_name_fn (cfun, name); +} + /* Return an anonymous SSA_NAME node for type TYPE defined in statement STMT in function cfun. Arrange so that it uses NAME in dumps. */ diff --git a/gcc/tree-stdarg.c b/gcc/tree-stdarg.c index 982937462db..5a22cfd6d96 100644 --- a/gcc/tree-stdarg.c +++ b/gcc/tree-stdarg.c @@ -28,6 +28,11 @@ along with GCC; see the file COPYING3. If not see #include "gimple-pretty-print.h" #include "target.h" #include "bitmap.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimple-walk.h" diff --git a/gcc/tree-streamer-in.c b/gcc/tree-streamer-in.c index a70c7670551..5513623eb49 100644 --- a/gcc/tree-streamer-in.c +++ b/gcc/tree-streamer-in.c @@ -25,6 +25,11 @@ along with GCC; see the file COPYING3. If not see #include "diagnostic.h" #include "tree.h" #include "stringpool.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "tree-streamer.h" #include "data-streamer.h" @@ -421,6 +426,48 @@ unpack_ts_optimization (struct bitpack_d *bp, tree expr) } +/* Unpack all the non-pointer fields of the TS_OMP_CLAUSE + structure of expression EXPR from bitpack BP. */ + +static void +unpack_ts_omp_clause_value_fields (struct data_in *data_in, + struct bitpack_d *bp, tree expr) +{ + OMP_CLAUSE_LOCATION (expr) = stream_input_location (bp, data_in); + switch (OMP_CLAUSE_CODE (expr)) + { + case OMP_CLAUSE_DEFAULT: + OMP_CLAUSE_DEFAULT_KIND (expr) + = bp_unpack_enum (bp, omp_clause_default_kind, + OMP_CLAUSE_DEFAULT_LAST); + break; + case OMP_CLAUSE_SCHEDULE: + OMP_CLAUSE_SCHEDULE_KIND (expr) + = bp_unpack_enum (bp, omp_clause_schedule_kind, + OMP_CLAUSE_SCHEDULE_LAST); + break; + case OMP_CLAUSE_DEPEND: + OMP_CLAUSE_DEPEND_KIND (expr) + = bp_unpack_enum (bp, omp_clause_depend_kind, OMP_CLAUSE_DEPEND_LAST); + break; + case OMP_CLAUSE_MAP: + OMP_CLAUSE_MAP_KIND (expr) + = bp_unpack_enum (bp, omp_clause_map_kind, OMP_CLAUSE_MAP_LAST); + break; + case OMP_CLAUSE_PROC_BIND: + OMP_CLAUSE_PROC_BIND_KIND (expr) + = bp_unpack_enum (bp, omp_clause_proc_bind_kind, + OMP_CLAUSE_PROC_BIND_LAST); + break; + case OMP_CLAUSE_REDUCTION: + OMP_CLAUSE_REDUCTION_CODE (expr) + = bp_unpack_enum (bp, tree_code, MAX_TREE_CODES); + break; + default: + break; + } +} + /* Unpack all the non-pointer fields in EXPR into a bit pack. */ static void @@ -489,6 +536,9 @@ unpack_value_fields (struct data_in *data_in, struct bitpack_d *bp, tree expr) if (length > 0) vec_safe_grow (CONSTRUCTOR_ELTS (expr), length); } + + if (code == OMP_CLAUSE) + unpack_ts_omp_clause_value_fields (data_in, bp, expr); } @@ -580,6 +630,12 @@ streamer_alloc_tree (struct lto_input_block *ib, struct data_in *data_in, unsigned HOST_WIDE_INT nargs = streamer_read_uhwi (ib); return build_vl_exp (CALL_EXPR, nargs + 3); } + else if (code == OMP_CLAUSE) + { + enum omp_clause_code subcode + = (enum omp_clause_code) streamer_read_uhwi (ib); + return build_omp_clause (UNKNOWN_LOCATION, subcode); + } else { /* For all other nodes, materialize the tree with a raw @@ -962,6 +1018,22 @@ lto_input_ts_constructor_tree_pointers (struct lto_input_block *ib, } +/* Read all pointer fields in the TS_OMP_CLAUSE structure of EXPR from + input block IB. DATA_IN contains tables and descriptors for the + file being read. */ + +static void +lto_input_ts_omp_clause_tree_pointers (struct lto_input_block *ib, + struct data_in *data_in, tree expr) +{ + int i; + + for (i = 0; i < omp_clause_num_ops[OMP_CLAUSE_CODE (expr)]; i++) + OMP_CLAUSE_OPERAND (expr, i) = stream_read_tree (ib, data_in); + OMP_CLAUSE_CHAIN (expr) = stream_read_tree (ib, data_in); +} + + /* Read all pointer fields in EXPR from input block IB. DATA_IN contains tables and descriptors for the file being read. */ @@ -1023,6 +1095,9 @@ streamer_read_tree_body (struct lto_input_block *ib, struct data_in *data_in, if (CODE_CONTAINS_STRUCT (code, TS_CONSTRUCTOR)) lto_input_ts_constructor_tree_pointers (ib, data_in, expr); + + if (code == OMP_CLAUSE) + lto_input_ts_omp_clause_tree_pointers (ib, data_in, expr); } diff --git a/gcc/tree-streamer-out.c b/gcc/tree-streamer-out.c index c7dca47a35a..c1dab1447e0 100644 --- a/gcc/tree-streamer-out.c +++ b/gcc/tree-streamer-out.c @@ -26,6 +26,11 @@ along with GCC; see the file COPYING3. If not see #include "diagnostic.h" #include "tree.h" #include "stor-layout.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "tree-streamer.h" #include "data-streamer.h" @@ -388,6 +393,46 @@ pack_ts_optimization (struct bitpack_d *bp, tree expr) } +/* Pack all the non-pointer fields of the TS_OMP_CLAUSE structure + of expression EXPR into bitpack BP. */ + +static void +pack_ts_omp_clause_value_fields (struct output_block *ob, + struct bitpack_d *bp, tree expr) +{ + stream_output_location (ob, bp, OMP_CLAUSE_LOCATION (expr)); + switch (OMP_CLAUSE_CODE (expr)) + { + case OMP_CLAUSE_DEFAULT: + bp_pack_enum (bp, omp_clause_default_kind, OMP_CLAUSE_DEFAULT_LAST, + OMP_CLAUSE_DEFAULT_KIND (expr)); + break; + case OMP_CLAUSE_SCHEDULE: + bp_pack_enum (bp, omp_clause_schedule_kind, OMP_CLAUSE_SCHEDULE_LAST, + OMP_CLAUSE_SCHEDULE_KIND (expr)); + break; + case OMP_CLAUSE_DEPEND: + bp_pack_enum (bp, omp_clause_depend_kind, OMP_CLAUSE_DEPEND_LAST, + OMP_CLAUSE_DEPEND_KIND (expr)); + break; + case OMP_CLAUSE_MAP: + bp_pack_enum (bp, omp_clause_map_kind, OMP_CLAUSE_MAP_LAST, + OMP_CLAUSE_MAP_KIND (expr)); + break; + case OMP_CLAUSE_PROC_BIND: + bp_pack_enum (bp, omp_clause_proc_bind_kind, OMP_CLAUSE_PROC_BIND_LAST, + OMP_CLAUSE_PROC_BIND_KIND (expr)); + break; + case OMP_CLAUSE_REDUCTION: + bp_pack_enum (bp, tree_code, MAX_TREE_CODES, + OMP_CLAUSE_REDUCTION_CODE (expr)); + break; + default: + break; + } +} + + /* Pack all the bitfields in EXPR into a bit pack. */ void @@ -449,6 +494,9 @@ streamer_pack_tree_bitfields (struct output_block *ob, if (CODE_CONTAINS_STRUCT (code, TS_CONSTRUCTOR)) bp_pack_var_len_unsigned (bp, CONSTRUCTOR_NELTS (expr)); + + if (code == OMP_CLAUSE) + pack_ts_omp_clause_value_fields (ob, bp, expr); } @@ -851,6 +899,29 @@ write_ts_constructor_tree_pointers (struct output_block *ob, tree expr, } } + +/* Write all pointer fields in the TS_OMP_CLAUSE structure of EXPR + to output block OB. If REF_P is true, write a reference to EXPR's + pointer fields. */ + +static void +write_ts_omp_clause_tree_pointers (struct output_block *ob, tree expr, + bool ref_p) +{ + int i; + for (i = 0; i < omp_clause_num_ops[OMP_CLAUSE_CODE (expr)]; i++) + stream_write_tree (ob, OMP_CLAUSE_OPERAND (expr, i), ref_p); + if (OMP_CLAUSE_CODE (expr) == OMP_CLAUSE_REDUCTION) + { + /* We don't stream these right now, handle it if streaming + of them is needed. */ + gcc_assert (OMP_CLAUSE_REDUCTION_GIMPLE_INIT (expr) == NULL); + gcc_assert (OMP_CLAUSE_REDUCTION_GIMPLE_MERGE (expr) == NULL); + } + stream_write_tree (ob, OMP_CLAUSE_CHAIN (expr), ref_p); +} + + /* Write all pointer fields in EXPR to output block OB. If REF_P is true, the leaves of EXPR are emitted as references. */ @@ -913,6 +984,9 @@ streamer_write_tree_body (struct output_block *ob, tree expr, bool ref_p) if (CODE_CONTAINS_STRUCT (code, TS_CONSTRUCTOR)) write_ts_constructor_tree_pointers (ob, expr, ref_p); + + if (code == OMP_CLAUSE) + write_ts_omp_clause_tree_pointers (ob, expr, ref_p); } @@ -961,6 +1035,8 @@ streamer_write_tree_header (struct output_block *ob, tree expr) streamer_write_uhwi (ob, BINFO_N_BASE_BINFOS (expr)); else if (TREE_CODE (expr) == CALL_EXPR) streamer_write_uhwi (ob, call_expr_nargs (expr)); + else if (TREE_CODE (expr) == OMP_CLAUSE) + streamer_write_uhwi (ob, OMP_CLAUSE_CODE (expr)); else if (CODE_CONTAINS_STRUCT (code, TS_INT_CST)) { gcc_checking_assert (TREE_INT_CST_NUNITS (expr)); diff --git a/gcc/tree-streamer.c b/gcc/tree-streamer.c index 8534f4a9b8b..aa06b0bbfe6 100644 --- a/gcc/tree-streamer.c +++ b/gcc/tree-streamer.c @@ -24,6 +24,11 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "tree.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "streamer-hooks.h" #include "tree-streamer.h" diff --git a/gcc/tree-switch-conversion.c b/gcc/tree-switch-conversion.c index fc0b5749407..93a3bff6595 100644 --- a/gcc/tree-switch-conversion.c +++ b/gcc/tree-switch-conversion.c @@ -33,6 +33,10 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "varasm.h" #include "stor-layout.h" #include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "gimple-iterator.h" diff --git a/gcc/tree-tailcall.c b/gcc/tree-tailcall.c index 9a30400c0d9..37603b2757c 100644 --- a/gcc/tree-tailcall.c +++ b/gcc/tree-tailcall.c @@ -26,6 +26,10 @@ along with GCC; see the file COPYING3. If not see #include "tm_p.h" #include "basic-block.h" #include "function.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimplify-me.h" diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c index f8c84427831..f7f95b3492c 100644 --- a/gcc/tree-vect-data-refs.c +++ b/gcc/tree-vect-data-refs.c @@ -24,13 +24,17 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "dumpfile.h" #include "tm.h" -#include "ggc.h" #include "tree.h" #include "stor-layout.h" #include "tm_p.h" #include "target.h" #include "basic-block.h" #include "gimple-pretty-print.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "gimple-iterator.h" @@ -49,6 +53,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-scalar-evolution.h" #include "tree-vectorizer.h" #include "diagnostic-core.h" +#include "cgraph.h" /* Need to include rtl.h, expr.h, etc. for optabs. */ #include "expr.h" #include "optabs.h" @@ -1092,7 +1097,8 @@ vect_peeling_hash_insert (loop_vec_info loop_vinfo, struct data_reference *dr, *new_slot = slot; } - if (!supportable_dr_alignment && unlimited_cost_model ()) + if (!supportable_dr_alignment + && unlimited_cost_model (LOOP_VINFO_LOOP (loop_vinfo))) slot->count += VECT_MAX_COST; } @@ -1202,7 +1208,7 @@ vect_peeling_hash_choose_best_peeling (loop_vec_info loop_vinfo, res.peel_info.dr = NULL; res.body_cost_vec = stmt_vector_for_cost (); - if (!unlimited_cost_model ()) + if (!unlimited_cost_model (LOOP_VINFO_LOOP (loop_vinfo))) { res.inside_cost = INT_MAX; res.outside_cost = INT_MAX; @@ -1431,7 +1437,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo) vectorization factor. We do this automtically for cost model, since we calculate cost for every peeling option. */ - if (unlimited_cost_model ()) + if (unlimited_cost_model (LOOP_VINFO_LOOP (loop_vinfo))) possible_npeel_number = vf /nelements; /* Handle the aligned case. We may decide to align some other @@ -1439,7 +1445,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo) if (DR_MISALIGNMENT (dr) == 0) { npeel_tmp = 0; - if (unlimited_cost_model ()) + if (unlimited_cost_model (LOOP_VINFO_LOOP (loop_vinfo))) possible_npeel_number++; } @@ -3161,10 +3167,11 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo, if (loop_vinfo) { + basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo); + loop = LOOP_VINFO_LOOP (loop_vinfo); - if (!find_loop_nest (loop, &LOOP_VINFO_LOOP_NEST (loop_vinfo)) - || find_data_references_in_loop - (loop, &LOOP_VINFO_DATAREFS (loop_vinfo))) + datarefs = LOOP_VINFO_DATAREFS (loop_vinfo); + if (!find_loop_nest (loop, &LOOP_VINFO_LOOP_NEST (loop_vinfo))) { if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, @@ -3173,7 +3180,57 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo, return false; } - datarefs = LOOP_VINFO_DATAREFS (loop_vinfo); + for (i = 0; i < loop->num_nodes; i++) + { + gimple_stmt_iterator gsi; + + for (gsi = gsi_start_bb (bbs[i]); !gsi_end_p (gsi); gsi_next (&gsi)) + { + gimple stmt = gsi_stmt (gsi); + if (!find_data_references_in_stmt (loop, stmt, &datarefs)) + { + if (is_gimple_call (stmt) && loop->safelen) + { + tree fndecl = gimple_call_fndecl (stmt), op; + if (fndecl != NULL_TREE) + { + struct cgraph_node *node = cgraph_get_node (fndecl); + if (node != NULL && node->simd_clones != NULL) + { + unsigned int j, n = gimple_call_num_args (stmt); + for (j = 0; j < n; j++) + { + op = gimple_call_arg (stmt, j); + if (DECL_P (op) + || (REFERENCE_CLASS_P (op) + && get_base_address (op))) + break; + } + op = gimple_call_lhs (stmt); + /* Ignore #pragma omp declare simd functions + if they don't have data references in the + call stmt itself. */ + if (j == n + && !(op + && (DECL_P (op) + || (REFERENCE_CLASS_P (op) + && get_base_address (op))))) + continue; + } + } + } + LOOP_VINFO_DATAREFS (loop_vinfo) = datarefs; + if (dump_enabled_p ()) + dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, + "not vectorized: loop contains function " + "calls or data references that cannot " + "be analyzed\n"); + return false; + } + } + } + + LOOP_VINFO_DATAREFS (loop_vinfo) = datarefs; } else { diff --git a/gcc/tree-vect-generic.c b/gcc/tree-vect-generic.c index 367992671af..8bb04cf9f11 100644 --- a/gcc/tree-vect-generic.c +++ b/gcc/tree-vect-generic.c @@ -24,6 +24,12 @@ along with GCC; see the file COPYING3. If not see #include "stor-layout.h" #include "tm.h" #include "langhooks.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimplify-me.h" @@ -34,7 +40,6 @@ along with GCC; see the file COPYING3. If not see #include "tree-iterator.h" #include "tree-pass.h" #include "flags.h" -#include "ggc.h" #include "diagnostic.h" #include "target.h" @@ -1006,9 +1011,14 @@ optimize_vector_constructor (gimple_stmt_iterator *gsi) tree *cst; gimple g; tree base = NULL_TREE; + optab op; if (nelts <= 2 || CONSTRUCTOR_NELTS (rhs) != nelts) return; + op = optab_for_tree_code (PLUS_EXPR, type, optab_default); + if (op == unknown_optab + || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing) + return; FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (rhs), i, elt) if (TREE_CODE (elt->value) != SSA_NAME || TREE_CODE (TREE_TYPE (elt->value)) == VECTOR_TYPE) diff --git a/gcc/tree-vect-loop-manip.c b/gcc/tree-vect-loop-manip.c index 22d936e4ada..63e7025fc6c 100644 --- a/gcc/tree-vect-loop-manip.c +++ b/gcc/tree-vect-loop-manip.c @@ -24,10 +24,13 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "dumpfile.h" #include "tm.h" -#include "ggc.h" #include "tree.h" #include "basic-block.h" #include "gimple-pretty-print.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "gimple-iterator.h" diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c index ab8e0f234a4..1037cac1dca 100644 --- a/gcc/tree-vect-loop.c +++ b/gcc/tree-vect-loop.c @@ -24,11 +24,14 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "dumpfile.h" #include "tm.h" -#include "ggc.h" #include "tree.h" #include "stor-layout.h" #include "basic-block.h" #include "gimple-pretty-print.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "gimple-iterator.h" @@ -373,6 +376,19 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo) if (gimple_get_lhs (stmt) == NULL_TREE) { + if (is_gimple_call (stmt)) + { + /* Ignore calls with no lhs. These must be calls to + #pragma omp simd functions, and what vectorization factor + it really needs can't be determined until + vectorizable_simd_clone_call. */ + if (!analyze_pattern_stmt && gsi_end_p (pattern_def_si)) + { + pattern_def_seq = NULL; + gsi_next (&si); + } + continue; + } if (dump_enabled_p ()) { dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, @@ -2700,7 +2716,7 @@ vect_estimate_min_profitable_iters (loop_vec_info loop_vinfo, void *target_cost_data = LOOP_VINFO_TARGET_COST_DATA (loop_vinfo); /* Cost model disabled. */ - if (unlimited_cost_model ()) + if (unlimited_cost_model (LOOP_VINFO_LOOP (loop_vinfo))) { dump_printf_loc (MSG_NOTE, vect_location, "cost model disabled.\n"); *ret_min_profitable_niters = 0; @@ -2933,6 +2949,10 @@ vect_estimate_min_profitable_iters (loop_vec_info loop_vinfo, /* vector version will never be profitable. */ else { + if (LOOP_VINFO_LOOP (loop_vinfo)->force_vect) + warning_at (vect_location, OPT_Wopenmp_simd, "vectorization " + "did not happen for a simd loop"); + if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, "cost model: the vector iteration cost = %d " @@ -3196,7 +3216,6 @@ get_initial_def_for_induction (gimple iv_phi) struct loop *iv_loop; basic_block new_bb; tree new_vec, vec_init, vec_step, t; - tree access_fn; tree new_var; tree new_name; gimple init_stmt, induction_phi, new_stmt; @@ -3204,7 +3223,6 @@ get_initial_def_for_induction (gimple iv_phi) tree init_expr, step_expr; int vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo); int i; - bool ok; int ncopies; tree expr; stmt_vec_info phi_info = vinfo_for_stmt (iv_phi); @@ -3233,13 +3251,12 @@ get_initial_def_for_induction (gimple iv_phi) latch_e = loop_latch_edge (iv_loop); loop_arg = PHI_ARG_DEF_FROM_EDGE (iv_phi, latch_e); - access_fn = analyze_scalar_evolution (iv_loop, PHI_RESULT (iv_phi)); - gcc_assert (access_fn); - STRIP_NOPS (access_fn); - ok = vect_is_simple_iv_evolution (iv_loop->num, access_fn, - &init_expr, &step_expr); - gcc_assert (ok); + step_expr = STMT_VINFO_LOOP_PHI_EVOLUTION_PART (phi_info); + gcc_assert (step_expr != NULL_TREE); + pe = loop_preheader_edge (iv_loop); + init_expr = PHI_ARG_DEF_FROM_EDGE (iv_phi, + loop_preheader_edge (iv_loop)); vectype = get_vectype_for_scalar_type (TREE_TYPE (init_expr)); resvectype = get_vectype_for_scalar_type (TREE_TYPE (PHI_RESULT (iv_phi))); @@ -3250,6 +3267,16 @@ get_initial_def_for_induction (gimple iv_phi) gcc_assert (phi_info); gcc_assert (ncopies >= 1); + /* Convert the step to the desired type. */ + step_expr = force_gimple_operand (fold_convert (TREE_TYPE (vectype), + step_expr), + &stmts, true, NULL_TREE); + if (stmts) + { + new_bb = gsi_insert_seq_on_edge_immediate (pe, stmts); + gcc_assert (!new_bb); + } + /* Find the first insertion point in the BB. */ si = gsi_after_labels (bb); @@ -3259,9 +3286,7 @@ get_initial_def_for_induction (gimple iv_phi) /* iv_loop is nested in the loop to be vectorized. init_expr had already been created during vectorization of previous stmts. We obtain it from the STMT_VINFO_VEC_STMT of the defining stmt. */ - tree iv_def = PHI_ARG_DEF_FROM_EDGE (iv_phi, - loop_preheader_edge (iv_loop)); - vec_init = vect_get_vec_def_for_operand (iv_def, iv_phi, NULL); + vec_init = vect_get_vec_def_for_operand (init_expr, iv_phi, NULL); /* If the initial value is not of proper type, convert it. */ if (!useless_type_conversion_p (vectype, TREE_TYPE (vec_init))) { @@ -5691,7 +5716,6 @@ vect_transform_loop (loop_vec_info loop_vinfo) int vectorization_factor = LOOP_VINFO_VECT_FACTOR (loop_vinfo); bool grouped_store; bool slp_scheduled = false; - unsigned int nunits; gimple stmt, pattern_stmt; gimple_seq pattern_def_seq = NULL; gimple_stmt_iterator pattern_def_si = gsi_none (); @@ -5949,16 +5973,18 @@ vect_transform_loop (loop_vec_info loop_vinfo) transform_pattern_stmt = false; } - gcc_assert (STMT_VINFO_VECTYPE (stmt_info)); - nunits = (unsigned int) TYPE_VECTOR_SUBPARTS ( - STMT_VINFO_VECTYPE (stmt_info)); - if (!STMT_SLP_TYPE (stmt_info) - && nunits != (unsigned int) vectorization_factor - && dump_enabled_p ()) - /* For SLP VF is set according to unrolling factor, and not to - vector size, hence for SLP this print is not valid. */ - dump_printf_loc (MSG_NOTE, vect_location, - "multiple-types.\n"); + if (STMT_VINFO_VECTYPE (stmt_info)) + { + unsigned int nunits + = (unsigned int) + TYPE_VECTOR_SUBPARTS (STMT_VINFO_VECTYPE (stmt_info)); + if (!STMT_SLP_TYPE (stmt_info) + && nunits != (unsigned int) vectorization_factor + && dump_enabled_p ()) + /* For SLP VF is set according to unrolling factor, and not + to vector size, hence for SLP this print is not valid. */ + dump_printf_loc (MSG_NOTE, vect_location, "multiple-types.\n"); + } /* SLP. Schedule all the SLP instances when the first SLP stmt is reached. */ diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c index ebfe10ee321..d8a1785a4c7 100644 --- a/gcc/tree-vect-patterns.c +++ b/gcc/tree-vect-patterns.c @@ -22,12 +22,16 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "tm.h" -#include "ggc.h" #include "tree.h" #include "stor-layout.h" #include "target.h" #include "basic-block.h" #include "gimple-pretty-print.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "gimple-iterator.h" diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c index c2e49124168..2387c0d9dfc 100644 --- a/gcc/tree-vect-slp.c +++ b/gcc/tree-vect-slp.c @@ -24,12 +24,15 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "dumpfile.h" #include "tm.h" -#include "ggc.h" #include "tree.h" #include "stor-layout.h" #include "target.h" #include "basic-block.h" #include "gimple-pretty-print.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimple-ssa.h" @@ -2173,7 +2176,7 @@ vect_slp_analyze_bb_1 (basic_block bb) } /* Cost model: check if the vectorization is worthwhile. */ - if (!unlimited_cost_model () + if (!unlimited_cost_model (NULL) && !vect_bb_vectorization_profitable_p (bb_vinfo)) { if (dump_enabled_p ()) diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c index 1aede48dc77..5d0ccb6bcff 100644 --- a/gcc/tree-vect-stmts.c +++ b/gcc/tree-vect-stmts.c @@ -24,12 +24,16 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "dumpfile.h" #include "tm.h" -#include "ggc.h" #include "tree.h" #include "stor-layout.h" #include "target.h" #include "basic-block.h" #include "gimple-pretty-print.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "gimple-iterator.h" @@ -42,12 +46,15 @@ along with GCC; see the file COPYING3. If not see #include "tree-ssanames.h" #include "tree-ssa-loop-manip.h" #include "cfgloop.h" +#include "tree-ssa-loop.h" +#include "tree-scalar-evolution.h" #include "expr.h" #include "recog.h" /* FIXME: for insn_data */ #include "optabs.h" #include "diagnostic-core.h" #include "tree-vectorizer.h" #include "dumpfile.h" +#include "cgraph.h" /* For lang_hooks.types.type_for_mode. */ #include "langhooks.h" @@ -1731,11 +1738,11 @@ vectorizable_call (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt, if (!is_gimple_call (stmt)) return false; - if (TREE_CODE (gimple_call_lhs (stmt)) != SSA_NAME) + if (gimple_call_lhs (stmt) == NULL_TREE + || TREE_CODE (gimple_call_lhs (stmt)) != SSA_NAME) return false; - if (stmt_can_throw_internal (stmt)) - return false; + gcc_checking_assert (!stmt_can_throw_internal (stmt)); vectype_out = STMT_VINFO_VECTYPE (stmt_info); @@ -2078,10 +2085,6 @@ vectorizable_call (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt, vargs.release (); - /* Update the exception handling table with the vector stmt if necessary. */ - if (maybe_clean_or_replace_eh_stmt (stmt, *vec_stmt)) - gimple_purge_dead_eh_edges (gimple_bb (stmt)); - /* The call in STMT might prevent it from being removed in dce. We however cannot remove it here, due to the way the ssa name it defines is mapped to the new definition. So just replace @@ -2105,6 +2108,603 @@ vectorizable_call (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt, } +struct simd_call_arg_info +{ + tree vectype; + tree op; + enum vect_def_type dt; + HOST_WIDE_INT linear_step; + unsigned int align; +}; + +/* Function vectorizable_simd_clone_call. + + Check if STMT performs a function call that can be vectorized + by calling a simd clone of the function. + If VEC_STMT is also passed, vectorize the STMT: create a vectorized + stmt to replace it, put it in VEC_STMT, and insert it at BSI. + Return FALSE if not a vectorizable STMT, TRUE otherwise. */ + +static bool +vectorizable_simd_clone_call (gimple stmt, gimple_stmt_iterator *gsi, + gimple *vec_stmt, slp_tree slp_node) +{ + tree vec_dest; + tree scalar_dest; + tree op, type; + tree vec_oprnd0 = NULL_TREE; + stmt_vec_info stmt_info = vinfo_for_stmt (stmt), prev_stmt_info; + tree vectype; + unsigned int nunits; + loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info); + bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info); + struct loop *loop = loop_vinfo ? LOOP_VINFO_LOOP (loop_vinfo) : NULL; + tree fndecl, new_temp, def; + gimple def_stmt; + gimple new_stmt = NULL; + int ncopies, j; + vec<simd_call_arg_info> arginfo = vNULL; + vec<tree> vargs = vNULL; + size_t i, nargs; + tree lhs, rtype, ratype; + vec<constructor_elt, va_gc> *ret_ctor_elts; + + /* Is STMT a vectorizable call? */ + if (!is_gimple_call (stmt)) + return false; + + fndecl = gimple_call_fndecl (stmt); + if (fndecl == NULL_TREE) + return false; + + struct cgraph_node *node = cgraph_get_node (fndecl); + if (node == NULL || node->simd_clones == NULL) + return false; + + if (!STMT_VINFO_RELEVANT_P (stmt_info) && !bb_vinfo) + return false; + + if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def) + return false; + + if (gimple_call_lhs (stmt) + && TREE_CODE (gimple_call_lhs (stmt)) != SSA_NAME) + return false; + + gcc_checking_assert (!stmt_can_throw_internal (stmt)); + + vectype = STMT_VINFO_VECTYPE (stmt_info); + + if (loop_vinfo && nested_in_vect_loop_p (loop, stmt)) + return false; + + /* FORNOW */ + if (slp_node || PURE_SLP_STMT (stmt_info)) + return false; + + /* Process function arguments. */ + nargs = gimple_call_num_args (stmt); + + /* Bail out if the function has zero arguments. */ + if (nargs == 0) + return false; + + arginfo.create (nargs); + + for (i = 0; i < nargs; i++) + { + simd_call_arg_info thisarginfo; + affine_iv iv; + + thisarginfo.linear_step = 0; + thisarginfo.align = 0; + thisarginfo.op = NULL_TREE; + + op = gimple_call_arg (stmt, i); + if (!vect_is_simple_use_1 (op, stmt, loop_vinfo, bb_vinfo, + &def_stmt, &def, &thisarginfo.dt, + &thisarginfo.vectype) + || thisarginfo.dt == vect_uninitialized_def) + { + if (dump_enabled_p ()) + dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location, + "use not simple.\n"); + arginfo.release (); + return false; + } + + if (thisarginfo.dt == vect_constant_def + || thisarginfo.dt == vect_external_def) + gcc_assert (thisarginfo.vectype == NULL_TREE); + else + gcc_assert (thisarginfo.vectype != NULL_TREE); + + if (thisarginfo.dt != vect_constant_def + && thisarginfo.dt != vect_external_def + && loop_vinfo + && TREE_CODE (op) == SSA_NAME + && simple_iv (loop, loop_containing_stmt (stmt), op, &iv, false) + && tree_fits_shwi_p (iv.step)) + { + thisarginfo.linear_step = tree_to_shwi (iv.step); + thisarginfo.op = iv.base; + } + else if ((thisarginfo.dt == vect_constant_def + || thisarginfo.dt == vect_external_def) + && POINTER_TYPE_P (TREE_TYPE (op))) + thisarginfo.align = get_pointer_alignment (op) / BITS_PER_UNIT; + + arginfo.quick_push (thisarginfo); + } + + unsigned int badness = 0; + struct cgraph_node *bestn = NULL; + if (STMT_VINFO_SIMD_CLONE_FNDECL (stmt_info)) + bestn = cgraph_get_node (STMT_VINFO_SIMD_CLONE_FNDECL (stmt_info)); + else + for (struct cgraph_node *n = node->simd_clones; n != NULL; + n = n->simdclone->next_clone) + { + unsigned int this_badness = 0; + if (n->simdclone->simdlen + > (unsigned) LOOP_VINFO_VECT_FACTOR (loop_vinfo) + || n->simdclone->nargs != nargs) + continue; + if (n->simdclone->simdlen + < (unsigned) LOOP_VINFO_VECT_FACTOR (loop_vinfo)) + this_badness += (exact_log2 (LOOP_VINFO_VECT_FACTOR (loop_vinfo)) + - exact_log2 (n->simdclone->simdlen)) * 1024; + if (n->simdclone->inbranch) + this_badness += 2048; + int target_badness = targetm.simd_clone.usable (n); + if (target_badness < 0) + continue; + this_badness += target_badness * 512; + /* FORNOW: Have to add code to add the mask argument. */ + if (n->simdclone->inbranch) + continue; + for (i = 0; i < nargs; i++) + { + switch (n->simdclone->args[i].arg_type) + { + case SIMD_CLONE_ARG_TYPE_VECTOR: + if (!useless_type_conversion_p + (n->simdclone->args[i].orig_type, + TREE_TYPE (gimple_call_arg (stmt, i)))) + i = -1; + else if (arginfo[i].dt == vect_constant_def + || arginfo[i].dt == vect_external_def + || arginfo[i].linear_step) + this_badness += 64; + break; + case SIMD_CLONE_ARG_TYPE_UNIFORM: + if (arginfo[i].dt != vect_constant_def + && arginfo[i].dt != vect_external_def) + i = -1; + break; + case SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP: + if (arginfo[i].dt == vect_constant_def + || arginfo[i].dt == vect_external_def + || (arginfo[i].linear_step + != n->simdclone->args[i].linear_step)) + i = -1; + break; + case SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP: + /* FORNOW */ + i = -1; + break; + case SIMD_CLONE_ARG_TYPE_MASK: + gcc_unreachable (); + } + if (i == (size_t) -1) + break; + if (n->simdclone->args[i].alignment > arginfo[i].align) + { + i = -1; + break; + } + if (arginfo[i].align) + this_badness += (exact_log2 (arginfo[i].align) + - exact_log2 (n->simdclone->args[i].alignment)); + } + if (i == (size_t) -1) + continue; + if (bestn == NULL || this_badness < badness) + { + bestn = n; + badness = this_badness; + } + } + + if (bestn == NULL) + { + arginfo.release (); + return false; + } + + for (i = 0; i < nargs; i++) + if ((arginfo[i].dt == vect_constant_def + || arginfo[i].dt == vect_external_def) + && bestn->simdclone->args[i].arg_type == SIMD_CLONE_ARG_TYPE_VECTOR) + { + arginfo[i].vectype + = get_vectype_for_scalar_type (TREE_TYPE (gimple_call_arg (stmt, + i))); + if (arginfo[i].vectype == NULL + || (TYPE_VECTOR_SUBPARTS (arginfo[i].vectype) + > bestn->simdclone->simdlen)) + { + arginfo.release (); + return false; + } + } + + fndecl = bestn->decl; + nunits = bestn->simdclone->simdlen; + ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits; + + /* If the function isn't const, only allow it in simd loops where user + has asserted that at least nunits consecutive iterations can be + performed using SIMD instructions. */ + if ((loop == NULL || (unsigned) loop->safelen < nunits) + && gimple_vuse (stmt)) + { + arginfo.release (); + return false; + } + + /* Sanity check: make sure that at least one copy of the vectorized stmt + needs to be generated. */ + gcc_assert (ncopies >= 1); + + if (!vec_stmt) /* transformation not required. */ + { + STMT_VINFO_SIMD_CLONE_FNDECL (stmt_info) = bestn->decl; + STMT_VINFO_TYPE (stmt_info) = call_simd_clone_vec_info_type; + if (dump_enabled_p ()) + dump_printf_loc (MSG_NOTE, vect_location, + "=== vectorizable_simd_clone_call ===\n"); +/* vect_model_simple_cost (stmt_info, ncopies, dt, NULL, NULL); */ + arginfo.release (); + return true; + } + + /** Transform. **/ + + if (dump_enabled_p ()) + dump_printf_loc (MSG_NOTE, vect_location, "transform call.\n"); + + /* Handle def. */ + scalar_dest = gimple_call_lhs (stmt); + vec_dest = NULL_TREE; + rtype = NULL_TREE; + ratype = NULL_TREE; + if (scalar_dest) + { + vec_dest = vect_create_destination_var (scalar_dest, vectype); + rtype = TREE_TYPE (TREE_TYPE (fndecl)); + if (TREE_CODE (rtype) == ARRAY_TYPE) + { + ratype = rtype; + rtype = TREE_TYPE (ratype); + } + } + + prev_stmt_info = NULL; + for (j = 0; j < ncopies; ++j) + { + /* Build argument list for the vectorized call. */ + if (j == 0) + vargs.create (nargs); + else + vargs.truncate (0); + + for (i = 0; i < nargs; i++) + { + unsigned int k, l, m, o; + tree atype; + op = gimple_call_arg (stmt, i); + switch (bestn->simdclone->args[i].arg_type) + { + case SIMD_CLONE_ARG_TYPE_VECTOR: + atype = bestn->simdclone->args[i].vector_type; + o = nunits / TYPE_VECTOR_SUBPARTS (atype); + for (m = j * o; m < (j + 1) * o; m++) + { + if (TYPE_VECTOR_SUBPARTS (atype) + < TYPE_VECTOR_SUBPARTS (arginfo[i].vectype)) + { + unsigned int prec = GET_MODE_BITSIZE (TYPE_MODE (atype)); + k = (TYPE_VECTOR_SUBPARTS (arginfo[i].vectype) + / TYPE_VECTOR_SUBPARTS (atype)); + gcc_assert ((k & (k - 1)) == 0); + if (m == 0) + vec_oprnd0 + = vect_get_vec_def_for_operand (op, stmt, NULL); + else + { + vec_oprnd0 = arginfo[i].op; + if ((m & (k - 1)) == 0) + vec_oprnd0 + = vect_get_vec_def_for_stmt_copy (arginfo[i].dt, + vec_oprnd0); + } + arginfo[i].op = vec_oprnd0; + vec_oprnd0 + = build3 (BIT_FIELD_REF, atype, vec_oprnd0, + size_int (prec), + bitsize_int ((m & (k - 1)) * prec)); + new_stmt + = gimple_build_assign (make_ssa_name (atype, NULL), + vec_oprnd0); + vect_finish_stmt_generation (stmt, new_stmt, gsi); + vargs.safe_push (gimple_assign_lhs (new_stmt)); + } + else + { + k = (TYPE_VECTOR_SUBPARTS (atype) + / TYPE_VECTOR_SUBPARTS (arginfo[i].vectype)); + gcc_assert ((k & (k - 1)) == 0); + vec<constructor_elt, va_gc> *ctor_elts; + if (k != 1) + vec_alloc (ctor_elts, k); + else + ctor_elts = NULL; + for (l = 0; l < k; l++) + { + if (m == 0 && l == 0) + vec_oprnd0 + = vect_get_vec_def_for_operand (op, stmt, NULL); + else + vec_oprnd0 + = vect_get_vec_def_for_stmt_copy (arginfo[i].dt, + arginfo[i].op); + arginfo[i].op = vec_oprnd0; + if (k == 1) + break; + CONSTRUCTOR_APPEND_ELT (ctor_elts, NULL_TREE, + vec_oprnd0); + } + if (k == 1) + vargs.safe_push (vec_oprnd0); + else + { + vec_oprnd0 = build_constructor (atype, ctor_elts); + new_stmt + = gimple_build_assign (make_ssa_name (atype, NULL), + vec_oprnd0); + vect_finish_stmt_generation (stmt, new_stmt, gsi); + vargs.safe_push (gimple_assign_lhs (new_stmt)); + } + } + } + break; + case SIMD_CLONE_ARG_TYPE_UNIFORM: + vargs.safe_push (op); + break; + case SIMD_CLONE_ARG_TYPE_LINEAR_CONSTANT_STEP: + if (j == 0) + { + gimple_seq stmts; + arginfo[i].op + = force_gimple_operand (arginfo[i].op, &stmts, true, + NULL_TREE); + if (stmts != NULL) + { + basic_block new_bb; + edge pe = loop_preheader_edge (loop); + new_bb = gsi_insert_seq_on_edge_immediate (pe, stmts); + gcc_assert (!new_bb); + } + tree phi_res = copy_ssa_name (op, NULL); + gimple new_phi = create_phi_node (phi_res, loop->header); + set_vinfo_for_stmt (new_phi, + new_stmt_vec_info (new_phi, loop_vinfo, + NULL)); + add_phi_arg (new_phi, arginfo[i].op, + loop_preheader_edge (loop), UNKNOWN_LOCATION); + enum tree_code code + = POINTER_TYPE_P (TREE_TYPE (op)) + ? POINTER_PLUS_EXPR : PLUS_EXPR; + tree type = POINTER_TYPE_P (TREE_TYPE (op)) + ? sizetype : TREE_TYPE (op); + widest_int cst + = wi::mul (bestn->simdclone->args[i].linear_step, + ncopies * nunits); + tree tcst = wide_int_to_tree (type, cst); + tree phi_arg = copy_ssa_name (op, NULL); + new_stmt = gimple_build_assign_with_ops (code, phi_arg, + phi_res, tcst); + gimple_stmt_iterator si = gsi_after_labels (loop->header); + gsi_insert_after (&si, new_stmt, GSI_NEW_STMT); + set_vinfo_for_stmt (new_stmt, + new_stmt_vec_info (new_stmt, loop_vinfo, + NULL)); + add_phi_arg (new_phi, phi_arg, loop_latch_edge (loop), + UNKNOWN_LOCATION); + arginfo[i].op = phi_res; + vargs.safe_push (phi_res); + } + else + { + enum tree_code code + = POINTER_TYPE_P (TREE_TYPE (op)) + ? POINTER_PLUS_EXPR : PLUS_EXPR; + tree type = POINTER_TYPE_P (TREE_TYPE (op)) + ? sizetype : TREE_TYPE (op); + widest_int cst + = wi::mul (bestn->simdclone->args[i].linear_step, + j * nunits); + tree tcst = wide_int_to_tree (type, cst); + new_temp = make_ssa_name (TREE_TYPE (op), NULL); + new_stmt + = gimple_build_assign_with_ops (code, new_temp, + arginfo[i].op, tcst); + vect_finish_stmt_generation (stmt, new_stmt, gsi); + vargs.safe_push (new_temp); + } + break; + case SIMD_CLONE_ARG_TYPE_LINEAR_VARIABLE_STEP: + default: + gcc_unreachable (); + } + } + + new_stmt = gimple_build_call_vec (fndecl, vargs); + if (vec_dest) + { + gcc_assert (ratype || TYPE_VECTOR_SUBPARTS (rtype) == nunits); + if (ratype) + new_temp = create_tmp_var (ratype, NULL); + else if (TYPE_VECTOR_SUBPARTS (vectype) + == TYPE_VECTOR_SUBPARTS (rtype)) + new_temp = make_ssa_name (vec_dest, new_stmt); + else + new_temp = make_ssa_name (rtype, new_stmt); + gimple_call_set_lhs (new_stmt, new_temp); + } + vect_finish_stmt_generation (stmt, new_stmt, gsi); + + if (vec_dest) + { + if (TYPE_VECTOR_SUBPARTS (vectype) < nunits) + { + unsigned int k, l; + unsigned int prec = GET_MODE_BITSIZE (TYPE_MODE (vectype)); + k = nunits / TYPE_VECTOR_SUBPARTS (vectype); + gcc_assert ((k & (k - 1)) == 0); + for (l = 0; l < k; l++) + { + tree t; + if (ratype) + { + t = build_fold_addr_expr (new_temp); + t = build2 (MEM_REF, vectype, t, + build_int_cst (TREE_TYPE (t), + l * prec / BITS_PER_UNIT)); + } + else + t = build3 (BIT_FIELD_REF, vectype, new_temp, + size_int (prec), bitsize_int (l * prec)); + new_stmt + = gimple_build_assign (make_ssa_name (vectype, NULL), t); + vect_finish_stmt_generation (stmt, new_stmt, gsi); + if (j == 0 && l == 0) + STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt; + else + STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt; + + prev_stmt_info = vinfo_for_stmt (new_stmt); + } + + if (ratype) + { + tree clobber = build_constructor (ratype, NULL); + TREE_THIS_VOLATILE (clobber) = 1; + new_stmt = gimple_build_assign (new_temp, clobber); + vect_finish_stmt_generation (stmt, new_stmt, gsi); + } + continue; + } + else if (TYPE_VECTOR_SUBPARTS (vectype) > nunits) + { + unsigned int k = (TYPE_VECTOR_SUBPARTS (vectype) + / TYPE_VECTOR_SUBPARTS (rtype)); + gcc_assert ((k & (k - 1)) == 0); + if ((j & (k - 1)) == 0) + vec_alloc (ret_ctor_elts, k); + if (ratype) + { + unsigned int m, o = nunits / TYPE_VECTOR_SUBPARTS (rtype); + for (m = 0; m < o; m++) + { + tree tem = build4 (ARRAY_REF, rtype, new_temp, + size_int (m), NULL_TREE, NULL_TREE); + new_stmt + = gimple_build_assign (make_ssa_name (rtype, NULL), + tem); + vect_finish_stmt_generation (stmt, new_stmt, gsi); + CONSTRUCTOR_APPEND_ELT (ret_ctor_elts, NULL_TREE, + gimple_assign_lhs (new_stmt)); + } + tree clobber = build_constructor (ratype, NULL); + TREE_THIS_VOLATILE (clobber) = 1; + new_stmt = gimple_build_assign (new_temp, clobber); + vect_finish_stmt_generation (stmt, new_stmt, gsi); + } + else + CONSTRUCTOR_APPEND_ELT (ret_ctor_elts, NULL_TREE, new_temp); + if ((j & (k - 1)) != k - 1) + continue; + vec_oprnd0 = build_constructor (vectype, ret_ctor_elts); + new_stmt + = gimple_build_assign (make_ssa_name (vec_dest, NULL), + vec_oprnd0); + vect_finish_stmt_generation (stmt, new_stmt, gsi); + + if ((unsigned) j == k - 1) + STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt; + else + STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt; + + prev_stmt_info = vinfo_for_stmt (new_stmt); + continue; + } + else if (ratype) + { + tree t = build_fold_addr_expr (new_temp); + t = build2 (MEM_REF, vectype, t, + build_int_cst (TREE_TYPE (t), 0)); + new_stmt + = gimple_build_assign (make_ssa_name (vec_dest, NULL), t); + vect_finish_stmt_generation (stmt, new_stmt, gsi); + tree clobber = build_constructor (ratype, NULL); + TREE_THIS_VOLATILE (clobber) = 1; + vect_finish_stmt_generation (stmt, + gimple_build_assign (new_temp, + clobber), gsi); + } + } + + if (j == 0) + STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt; + else + STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt; + + prev_stmt_info = vinfo_for_stmt (new_stmt); + } + + vargs.release (); + + /* The call in STMT might prevent it from being removed in dce. + We however cannot remove it here, due to the way the ssa name + it defines is mapped to the new definition. So just replace + rhs of the statement with something harmless. */ + + if (slp_node) + return true; + + if (scalar_dest) + { + type = TREE_TYPE (scalar_dest); + if (is_pattern_stmt_p (stmt_info)) + lhs = gimple_call_lhs (STMT_VINFO_RELATED_STMT (stmt_info)); + else + lhs = gimple_call_lhs (stmt); + new_stmt = gimple_build_assign (lhs, build_zero_cst (type)); + } + else + new_stmt = gimple_build_nop (); + set_vinfo_for_stmt (new_stmt, stmt_info); + set_vinfo_for_stmt (stmt, NULL); + STMT_VINFO_STMT (stmt_info) = new_stmt; + gsi_replace (gsi, new_stmt, false); + unlink_stmt_vdef (stmt); + + return true; +} + + /* Function vect_gen_widened_results_half Create a vector stmt whose code, type, number of arguments, and result @@ -5815,7 +6415,9 @@ vect_analyze_stmt (gimple stmt, bool *need_to_vectorize, slp_tree node) if (STMT_VINFO_RELEVANT_P (stmt_info)) { gcc_assert (!VECTOR_MODE_P (TYPE_MODE (gimple_expr_type (stmt)))); - gcc_assert (STMT_VINFO_VECTYPE (stmt_info)); + gcc_assert (STMT_VINFO_VECTYPE (stmt_info) + || (is_gimple_call (stmt) + && gimple_call_lhs (stmt) == NULL_TREE)); *need_to_vectorize = true; } @@ -5823,7 +6425,8 @@ vect_analyze_stmt (gimple stmt, bool *need_to_vectorize, slp_tree node) if (!bb_vinfo && (STMT_VINFO_RELEVANT_P (stmt_info) || STMT_VINFO_DEF_TYPE (stmt_info) == vect_reduction_def)) - ok = (vectorizable_conversion (stmt, NULL, NULL, NULL) + ok = (vectorizable_simd_clone_call (stmt, NULL, NULL, NULL) + || vectorizable_conversion (stmt, NULL, NULL, NULL) || vectorizable_shift (stmt, NULL, NULL, NULL) || vectorizable_operation (stmt, NULL, NULL, NULL) || vectorizable_assignment (stmt, NULL, NULL, NULL) @@ -5835,7 +6438,8 @@ vect_analyze_stmt (gimple stmt, bool *need_to_vectorize, slp_tree node) else { if (bb_vinfo) - ok = (vectorizable_conversion (stmt, NULL, NULL, node) + ok = (vectorizable_simd_clone_call (stmt, NULL, NULL, node) + || vectorizable_conversion (stmt, NULL, NULL, node) || vectorizable_shift (stmt, NULL, NULL, node) || vectorizable_operation (stmt, NULL, NULL, node) || vectorizable_assignment (stmt, NULL, NULL, node) @@ -5963,6 +6567,11 @@ vect_transform_stmt (gimple stmt, gimple_stmt_iterator *gsi, stmt = gsi_stmt (*gsi); break; + case call_simd_clone_vec_info_type: + done = vectorizable_simd_clone_call (stmt, gsi, &vec_stmt, slp_node); + stmt = gsi_stmt (*gsi); + break; + case reduc_vec_info_type: done = vectorizable_reduction (stmt, gsi, &vec_stmt, slp_node); gcc_assert (done); diff --git a/gcc/tree-vectorizer.c b/gcc/tree-vectorizer.c index 7416aaa6135..c11f8a8c1b7 100644 --- a/gcc/tree-vectorizer.c +++ b/gcc/tree-vectorizer.c @@ -59,10 +59,14 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "dumpfile.h" #include "tm.h" -#include "ggc.h" #include "tree.h" #include "stor-layout.h" #include "tree-pretty-print.h" +#include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimple-walk.h" @@ -74,7 +78,6 @@ along with GCC; see the file COPYING3. If not see #include "cfgloop.h" #include "tree-vectorizer.h" #include "tree-pass.h" -#include "hash-table.h" #include "tree-ssa-propagate.h" #include "dbgcnt.h" diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h index 58884f85502..4427d6a7b33 100644 --- a/gcc/tree-vectorizer.h +++ b/gcc/tree-vectorizer.h @@ -443,6 +443,7 @@ enum stmt_vec_info_type { shift_vec_info_type, op_vec_info_type, call_vec_info_type, + call_simd_clone_vec_info_type, assignment_vec_info_type, condition_vec_info_type, reduc_vec_info_type, @@ -565,6 +566,9 @@ typedef struct _stmt_vec_info { of this stmt. */ vec<dr_p> same_align_refs; + /* Selected SIMD clone's function decl. */ + tree simd_clone_fndecl; + /* Classify the def of this stmt. */ enum vect_def_type def_type; @@ -633,6 +637,7 @@ typedef struct _stmt_vec_info { #define STMT_VINFO_RELATED_STMT(S) (S)->related_stmt #define STMT_VINFO_PATTERN_DEF_SEQ(S) (S)->pattern_def_seq #define STMT_VINFO_SAME_ALIGN_REFS(S) (S)->same_align_refs +#define STMT_VINFO_SIMD_CLONE_FNDECL(S) (S)->simd_clone_fndecl #define STMT_VINFO_DEF_TYPE(S) (S)->def_type #define STMT_VINFO_GROUP_FIRST_ELEMENT(S) (S)->first_element #define STMT_VINFO_GROUP_NEXT_ELEMENT(S) (S)->next_element @@ -910,9 +915,12 @@ known_alignment_for_access_p (struct data_reference *data_ref_info) /* Return true if the vect cost model is unlimited. */ static inline bool -unlimited_cost_model () +unlimited_cost_model (loop_p loop) { - return flag_vect_cost_model == VECT_COST_MODEL_UNLIMITED; + if (loop != NULL && loop->force_vect + && flag_simd_cost_model != VECT_COST_MODEL_DEFAULT) + return flag_simd_cost_model == VECT_COST_MODEL_UNLIMITED; + return (flag_vect_cost_model == VECT_COST_MODEL_UNLIMITED); } /* Source location */ diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index 7f3bc0f9843..77254d83c1a 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -22,12 +22,17 @@ along with GCC; see the file COPYING3. If not see #include "system.h" #include "coretypes.h" #include "tm.h" -#include "ggc.h" #include "flags.h" #include "tree.h" #include "stor-layout.h" #include "calls.h" #include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-fold.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimple-walk.h" @@ -437,6 +442,9 @@ set_value_range (value_range_t *vr, enum value_range_type t, tree min, gcc_assert (min && max); + gcc_assert ((!TREE_OVERFLOW_P (min) || is_overflow_infinity (min)) + && (!TREE_OVERFLOW_P (max) || is_overflow_infinity (max))); + if (INTEGRAL_TYPE_P (TREE_TYPE (min)) && t == VR_ANTI_RANGE) gcc_assert (!vrp_val_is_min (min) || !vrp_val_is_max (max)); @@ -612,7 +620,8 @@ static inline void set_value_range_to_value (value_range_t *vr, tree val, bitmap equiv) { gcc_assert (is_gimple_min_invariant (val)); - val = avoid_overflow_infinity (val); + if (TREE_OVERFLOW_P (val)) + val = drop_tree_overflow (val); set_value_range (vr, VR_RANGE, val, val, equiv); } @@ -5353,9 +5362,13 @@ register_edge_assert_for_1 (tree op, enum tree_code code, } else if (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (op_def))) { - /* Recurse through the type conversion. */ - retval |= register_edge_assert_for_1 (gimple_assign_rhs1 (op_def), - code, e, bsi); + /* Recurse through the type conversion, unless it is a narrowing + conversion or conversion from non-integral type. */ + tree rhs = gimple_assign_rhs1 (op_def); + if (INTEGRAL_TYPE_P (TREE_TYPE (rhs)) + && (TYPE_PRECISION (TREE_TYPE (rhs)) + <= TYPE_PRECISION (TREE_TYPE (op)))) + retval |= register_edge_assert_for_1 (rhs, code, e, bsi); } return retval; @@ -6657,8 +6670,8 @@ vrp_visit_assignment_or_call (gimple stmt, tree *output_p) /* Try folding the statement to a constant first. */ tree tem = gimple_fold_stmt_to_constant (stmt, vrp_valueize); - if (tem && !is_overflow_infinity (tem)) - set_value_range (&new_vr, VR_RANGE, tem, tem, NULL); + if (tem) + set_value_range_to_value (&new_vr, tem, NULL); /* Then dispatch to value-range extracting functions. */ else if (code == GIMPLE_CALL) extract_range_basic (&new_vr, stmt); @@ -7676,7 +7689,8 @@ union_ranges (enum value_range_type *vr0type, } else if ((operand_less_p (vr1min, *vr0max) == 1 || operand_equal_p (vr1min, *vr0max, 0)) - && operand_less_p (*vr0min, vr1min) == 1) + && operand_less_p (*vr0min, vr1min) == 1 + && operand_less_p (*vr0max, vr1max) == 1) { /* [ ( ] ) or [ ]( ) */ if (*vr0type == VR_RANGE @@ -7712,7 +7726,8 @@ union_ranges (enum value_range_type *vr0type, } else if ((operand_less_p (*vr0min, vr1max) == 1 || operand_equal_p (*vr0min, vr1max, 0)) - && operand_less_p (vr1min, *vr0min) == 1) + && operand_less_p (vr1min, *vr0min) == 1 + && operand_less_p (vr1max, *vr0max) == 1) { /* ( [ ) ] or ( )[ ] */ if (*vr0type == VR_RANGE @@ -8268,7 +8283,7 @@ vrp_visit_phi_node (gimple phi) } else { - if (is_overflow_infinity (arg)) + if (TREE_OVERFLOW_P (arg)) arg = drop_tree_overflow (arg); vr_arg.type = VR_RANGE; diff --git a/gcc/tree.c b/gcc/tree.c index 0196a32c4d1..99128992431 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -41,7 +41,6 @@ along with GCC; see the file COPYING3. If not see #include "function.h" #include "obstack.h" #include "toplev.h" /* get_random_seed */ -#include "ggc.h" #include "hashtab.h" #include "filenames.h" #include "output.h" @@ -52,6 +51,11 @@ along with GCC; see the file COPYING3. If not see #include "tree-iterator.h" #include "basic-block.h" #include "bitmap.h" +#include "pointer-set.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimplify.h" @@ -63,7 +67,6 @@ along with GCC; see the file COPYING3. If not see #include "expr.h" #include "tree-dfa.h" #include "params.h" -#include "pointer-set.h" #include "tree-pass.h" #include "langhooks-def.h" #include "diagnostic.h" @@ -1230,8 +1233,7 @@ wide_int_to_tree (tree type, const wide_int_ref &pcst) case POINTER_TYPE: case REFERENCE_TYPE: - case POINTER_BOUNDS_TYPE: - /* Cache NULL pointer and zero bounds. */ + /* Cache NULL pointer. */ if (hwi == 0) { limit = 1; @@ -3299,7 +3301,6 @@ type_contains_placeholder_1 (const_tree type) switch (TREE_CODE (type)) { case VOID_TYPE: - case POINTER_BOUNDS_TYPE: case COMPLEX_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE: @@ -9053,7 +9054,7 @@ get_file_function_name (const char *type) { const char *file = main_input_filename; if (! file) - file = input_filename; + file = LOCATION_FILE (input_location); /* Just use the file's basename, because the full pathname might be quite long. */ p = q = ASTRDUP (lbasename (file)); @@ -9070,7 +9071,7 @@ get_file_function_name (const char *type) if (! name) name = ""; if (! file) - file = input_filename; + file = LOCATION_FILE (input_location); len = strlen (file); q = (char *) alloca (9 + 17 + len + 1); @@ -9511,10 +9512,11 @@ make_or_reuse_accum_type (unsigned size, int unsignedp, int satp) during initialization of data types to create the 5 basic atomic types. The generic build_variant_type function requires these to already be set up in order to function properly, so cannot be - called from there. */ + called from there. If ALIGN is non-zero, then ensure alignment is + overridden to this value. */ static tree -build_atomic_base (tree type) +build_atomic_base (tree type, unsigned int align) { tree t; @@ -9525,6 +9527,9 @@ build_atomic_base (tree type) t = build_variant_type_copy (type); set_type_quals (t, TYPE_QUAL_ATOMIC); + if (align) + TYPE_ALIGN (t) = align; + return t; } @@ -9610,14 +9615,21 @@ build_common_tree_nodes (bool signed_char, bool short_double) /* Don't call build_qualified type for atomics. That routine does special processing for atomics, and until they are initialized - it's better not to make that call. */ - - atomicQI_type_node = build_atomic_base (unsigned_intQI_type_node); - atomicHI_type_node = build_atomic_base (unsigned_intHI_type_node); - atomicSI_type_node = build_atomic_base (unsigned_intSI_type_node); - atomicDI_type_node = build_atomic_base (unsigned_intDI_type_node); - atomicTI_type_node = build_atomic_base (unsigned_intTI_type_node); - + it's better not to make that call. + + Check to see if there is a target override for atomic types. */ + + atomicQI_type_node = build_atomic_base (unsigned_intQI_type_node, + targetm.atomic_align_for_mode (QImode)); + atomicHI_type_node = build_atomic_base (unsigned_intHI_type_node, + targetm.atomic_align_for_mode (HImode)); + atomicSI_type_node = build_atomic_base (unsigned_intSI_type_node, + targetm.atomic_align_for_mode (SImode)); + atomicDI_type_node = build_atomic_base (unsigned_intDI_type_node, + targetm.atomic_align_for_mode (DImode)); + atomicTI_type_node = build_atomic_base (unsigned_intTI_type_node, + targetm.atomic_align_for_mode (TImode)); + access_public_node = get_identifier ("public"); access_protected_node = get_identifier ("protected"); access_private_node = get_identifier ("private"); @@ -9640,8 +9652,6 @@ build_common_tree_nodes (bool signed_char, bool short_double) void_type_node = make_node (VOID_TYPE); layout_type (void_type_node); - pointer_bounds_type_node = targetm.chkp_bound_type (); - /* We are not going to have real types in C with less than byte alignment, so we might as well not have any types that claim to have it. */ TYPE_ALIGN (void_type_node) = BITS_PER_UNIT; diff --git a/gcc/tree.def b/gcc/tree.def index bad9a6ab78d..96649fb372c 100644 --- a/gcc/tree.def +++ b/gcc/tree.def @@ -232,11 +232,6 @@ DEFTREECODE (QUAL_UNION_TYPE, "qual_union_type", tcc_type, 0) /* The void type in C */ DEFTREECODE (VOID_TYPE, "void_type", tcc_type, 0) -/* Type to hold bounds for a pointer. - Has TYPE_PRECISION component to specify number of bits used - by this type. */ -DEFTREECODE (POINTER_BOUNDS_TYPE, "pointer_bounds_type", tcc_type, 0) - /* Type of functions. Special fields: TREE_TYPE type of value returned. TYPE_ARG_TYPES list of types of arguments expected. diff --git a/gcc/tree.h b/gcc/tree.h index 79e38afacf2..45470b737cc 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -558,21 +558,6 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int, /* Nonzero if this type is a complete type. */ #define COMPLETE_TYPE_P(NODE) (TYPE_SIZE (NODE) != NULL_TREE) -/* Nonzero if this type is a pointer bounds type. */ -#define POINTER_BOUNDS_TYPE_P(NODE) \ - (TREE_CODE (NODE) == POINTER_BOUNDS_TYPE) - -/* Nonzero if this node has a pointer bounds type. */ -#define POINTER_BOUNDS_P(NODE) \ - (POINTER_BOUNDS_TYPE_P (TREE_TYPE (NODE))) - -/* Nonzero if this type supposes bounds existence. */ -#define BOUNDED_TYPE_P(type) (POINTER_TYPE_P (type)) - -/* Nonzero for objects with bounded type. */ -#define BOUNDED_P(node) \ - BOUNDED_TYPE_P (TREE_TYPE (node)) - /* Nonzero if this type is the (possibly qualified) void type. */ #define VOID_TYPE_P(NODE) (TREE_CODE (NODE) == VOID_TYPE) @@ -849,9 +834,6 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int, #define CALL_ALLOCA_FOR_VAR_P(NODE) \ (CALL_EXPR_CHECK (NODE)->base.protected_flag) -/* In a CALL_EXPR, means call was instrumented by Pointer Bounds Checker. */ -#define CALL_WITH_BOUNDS_P(NODE) (CALL_EXPR_CHECK (NODE)->base.deprecated_flag) - /* In a type, nonzero means that all objects of the type are guaranteed by the language or front-end to be properly aligned, so we can indicate that a MEM of this type is aligned at least to the alignment of the type, even if it @@ -1050,8 +1032,6 @@ extern void omp_clause_range_check_failed (const_tree, const char *, int, != UNKNOWN_LOCATION) /* The location to be used in a diagnostic about this expression. Do not use this macro if the location will be assigned to other expressions. */ -#define EXPR_LOC_OR_HERE(NODE) (EXPR_HAS_LOCATION (NODE) \ - ? (NODE)->exp.locus : input_location) #define EXPR_LOC_OR_LOC(NODE, LOCUS) (EXPR_HAS_LOCATION (NODE) \ ? (NODE)->exp.locus : (LOCUS)) #define EXPR_FILENAME(NODE) LOCATION_FILE (EXPR_CHECK ((NODE))->exp.locus) @@ -1352,6 +1332,10 @@ extern void protected_set_expr_location (tree, location_t); #define OMP_CLAUSE_LINEAR_NO_COPYOUT(NODE) \ TREE_PRIVATE (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_LINEAR)) +/* True if a LINEAR clause has a stride that is variable. */ +#define OMP_CLAUSE_LINEAR_VARIABLE_STRIDE(NODE) \ + TREE_PROTECTED (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_LINEAR)) + #define OMP_CLAUSE_LINEAR_STEP(NODE) \ OMP_CLAUSE_OPERAND (OMP_CLAUSE_SUBCODE_CHECK (NODE, OMP_CLAUSE_LINEAR), 1) @@ -3273,8 +3257,6 @@ tree_operand_check_code (const_tree __t, enum tree_code __code, int __i, #define complex_double_type_node global_trees[TI_COMPLEX_DOUBLE_TYPE] #define complex_long_double_type_node global_trees[TI_COMPLEX_LONG_DOUBLE_TYPE] -#define pointer_bounds_type_node global_trees[TI_POINTER_BOUNDS_TYPE] - #define void_type_node global_trees[TI_VOID_TYPE] /* The C type `void *'. */ #define ptr_type_node global_trees[TI_PTR_TYPE] diff --git a/gcc/tsan.c b/gcc/tsan.c index 9330074ce30..4efcfe565aa 100644 --- a/gcc/tsan.c +++ b/gcc/tsan.c @@ -27,6 +27,10 @@ along with GCC; see the file COPYING3. If not see #include "intl.h" #include "tm.h" #include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "gimple-iterator.h" diff --git a/gcc/ubsan.c b/gcc/ubsan.c index de5dc40d659..e33e62a028a 100644 --- a/gcc/ubsan.c +++ b/gcc/ubsan.c @@ -26,12 +26,14 @@ along with GCC; see the file COPYING3. If not see #include "stringpool.h" #include "cgraph.h" #include "tree-pass.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimple-ssa.h" #include "gimple-walk.h" #include "hashtab.h" -#include "pointer-set.h" #include "output.h" #include "tm_p.h" #include "toplev.h" @@ -233,7 +235,7 @@ ubsan_source_location (location_t loc) build_index_type (size_int (len))); TREE_READONLY (str) = 1; TREE_STATIC (str) = 1; - str = build_fold_addr_expr_loc (loc, str); + str = build_fold_addr_expr (str); tree ctor = build_constructor_va (type, 3, NULL_TREE, str, NULL_TREE, build_int_cst (unsigned_type_node, xloc.line), NULL_TREE, @@ -270,8 +272,12 @@ ubsan_type_descriptor (tree type, bool want_pointer_type_p) type = TYPE_MAIN_VARIANT (type); tree decl = decl_for_type_lookup (type); - if (decl != NULL_TREE) - return decl; + /* It is possible that some of the earlier created DECLs were found + unused, in that case they weren't emitted and varpool_get_node + returns NULL node on them. But now we really need them. Thus, + renew them here. */ + if (decl != NULL_TREE && varpool_get_node (decl)) + return build_fold_addr_expr (decl); tree dtype = ubsan_type_descriptor_type (); tree type2 = type; @@ -370,11 +376,10 @@ ubsan_type_descriptor (tree type, bool want_pointer_type_p) DECL_INITIAL (decl) = ctor; rest_of_decl_compilation (decl, 1, 0); - /* Save the address of the VAR_DECL into the hash table. */ - decl = build_fold_addr_expr (decl); + /* Save the VAR_DECL into the hash table. */ decl_for_type_insert (type, decl); - return decl; + return build_fold_addr_expr (decl); } /* Create a structure for the ubsan library. NAME is a name of the new @@ -388,7 +393,7 @@ ubsan_create_data (const char *name, location_t loc, { va_list args; tree ret, t; - tree fields[3]; + tree fields[5]; vec<tree, va_gc> *saved_args = NULL; size_t i = 0; @@ -396,6 +401,7 @@ ubsan_create_data (const char *name, location_t loc, tree td_type = ubsan_type_descriptor_type (); TYPE_READONLY (td_type) = 1; td_type = build_pointer_type (td_type); + loc = LOCATION_LOCUS (loc); /* Create the structure type. */ ret = make_node (RECORD_TYPE); @@ -426,7 +432,7 @@ ubsan_create_data (const char *name, location_t loc, { /* We have to add two more decls. */ fields[i] = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE, - pointer_sized_int_node); + pointer_sized_int_node); DECL_CONTEXT (fields[i]) = ret; DECL_CHAIN (fields[i - 1]) = fields[i]; i++; @@ -608,24 +614,22 @@ instrument_mem_ref (tree t, gimple_stmt_iterator *iter, bool is_lhs) gsi_insert_before (iter, g, GSI_SAME_STMT); } -/* Callback function for the pointer instrumentation. */ +/* Perform the pointer instrumentation. */ -static tree -instrument_null (tree *tp, int * /*walk_subtree*/, void *data) +static void +instrument_null (gimple_stmt_iterator gsi, bool is_lhs) { - tree t = *tp; + gimple stmt = gsi_stmt (gsi); + tree t = is_lhs ? gimple_get_lhs (stmt) : gimple_assign_rhs1 (stmt); + t = get_base_address (t); const enum tree_code code = TREE_CODE (t); - struct walk_stmt_info *wi = (struct walk_stmt_info *) data; - if (code == MEM_REF && TREE_CODE (TREE_OPERAND (t, 0)) == SSA_NAME) - instrument_mem_ref (TREE_OPERAND (t, 0), &wi->gsi, wi->is_lhs); + instrument_mem_ref (TREE_OPERAND (t, 0), &gsi, is_lhs); else if (code == ADDR_EXPR && POINTER_TYPE_P (TREE_TYPE (t)) && TREE_CODE (TREE_TYPE (TREE_TYPE (t))) == METHOD_TYPE) - instrument_member_call (&wi->gsi); - - return NULL_TREE; + instrument_member_call (&gsi); } /* Gate and execute functions for ubsan pass. */ @@ -640,17 +644,21 @@ ubsan_pass (void) { for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);) { - struct walk_stmt_info wi; gimple stmt = gsi_stmt (gsi); - if (is_gimple_debug (stmt)) + if (is_gimple_debug (stmt) || gimple_clobber_p (stmt)) { gsi_next (&gsi); continue; } - memset (&wi, 0, sizeof (wi)); - wi.gsi = gsi; - walk_gimple_op (stmt, instrument_null, &wi); + if (flag_sanitize & SANITIZE_NULL) + { + if (gimple_store_p (stmt)) + instrument_null (gsi, true); + if (gimple_assign_load_p (stmt)) + instrument_null (gsi, false); + } + gsi_next (&gsi); } } diff --git a/gcc/value-prof.c b/gcc/value-prof.c index cfa752fc6df..e40b0ada7f1 100644 --- a/gcc/value-prof.c +++ b/gcc/value-prof.c @@ -34,7 +34,11 @@ along with GCC; see the file COPYING3. If not see #include "recog.h" #include "optabs.h" #include "regs.h" -#include "ggc.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "tree-eh.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimplify.h" #include "gimple-iterator.h" @@ -51,7 +55,6 @@ along with GCC; see the file COPYING3. If not see #include "gcov-io.h" #include "timevar.h" #include "dumpfile.h" -#include "pointer-set.h" #include "profile.h" #include "data-streamer.h" #include "builtins.h" diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c index ca85127917d..b0cf3fb3069 100644 --- a/gcc/var-tracking.c +++ b/gcc/var-tracking.c @@ -93,17 +93,17 @@ #include "tree.h" #include "varasm.h" #include "stor-layout.h" -#include "gimple.h" +#include "pointer-set.h" +#include "hash-table.h" +#include "basic-block.h" #include "tm_p.h" #include "hard-reg-set.h" -#include "basic-block.h" #include "flags.h" #include "insn-config.h" #include "reload.h" #include "sbitmap.h" #include "alloc-pool.h" #include "fibheap.h" -#include "hash-table.h" #include "regs.h" #include "expr.h" #include "tree-pass.h" @@ -115,7 +115,6 @@ #include "params.h" #include "diagnostic.h" #include "tree-pretty-print.h" -#include "pointer-set.h" #include "recog.h" #include "tm_p.h" #include "alias.h" @@ -5089,6 +5088,11 @@ track_expr_p (tree expr, bool need_rtl) &maxsize); if (!DECL_P (innerdecl) || DECL_IGNORED_P (innerdecl) + /* Do not track declarations for parts of tracked parameters + since we want to track them as a whole instead. */ + || (TREE_CODE (innerdecl) == PARM_DECL + && DECL_MODE (innerdecl) != BLKmode + && TREE_CODE (TREE_TYPE (innerdecl)) != UNION_TYPE) || TREE_STATIC (innerdecl) || bitsize <= 0 || bitpos + bitsize > 256 @@ -5943,6 +5947,20 @@ add_stores (rtx loc, const_rtx expr, void *cuip) if (type != MO_VAL_SET) goto log_and_return; + /* 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. */ + if (track_p + && REG_P (loc) + && REG_EXPR (loc) + && TREE_CODE (REG_EXPR (loc)) == PARM_DECL + && DECL_MODE (REG_EXPR (loc)) != BLKmode + && ((MEM_P (DECL_INCOMING_RTL (REG_EXPR (loc))) + && 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) @@ -9465,6 +9483,32 @@ vt_get_decl_and_offset (rtx rtl, tree *declp, HOST_WIDE_INT *offsetp) return true; } } + else if (GET_CODE (rtl) == PARALLEL) + { + tree decl = NULL_TREE; + HOST_WIDE_INT offset = MAX_VAR_PARTS; + int len = XVECLEN (rtl, 0), i; + + for (i = 0; i < len; i++) + { + rtx reg = XEXP (XVECEXP (rtl, 0, i), 0); + if (!REG_P (reg) || !REG_ATTRS (reg)) + break; + if (!decl) + decl = REG_EXPR (reg); + if (REG_EXPR (reg) != decl) + break; + if (REG_OFFSET (reg) < offset) + offset = REG_OFFSET (reg); + } + + if (i == len) + { + *declp = decl; + *offsetp = offset; + return true; + } + } else if (MEM_P (rtl)) { if (MEM_ATTRS (rtl)) @@ -9550,6 +9594,28 @@ vt_add_function_parameter (tree parm) p.outgoing = incoming; vec_safe_push (windowed_parm_regs, p); } + else if (GET_CODE (incoming) == PARALLEL) + { + rtx outgoing + = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (XVECLEN (incoming, 0))); + int i; + + for (i = 0; i < XVECLEN (incoming, 0); i++) + { + rtx reg = XEXP (XVECEXP (incoming, 0, i), 0); + parm_reg_t p; + p.incoming = reg; + reg = gen_rtx_REG_offset (reg, GET_MODE (reg), + OUTGOING_REGNO (REGNO (reg)), 0); + p.outgoing = reg; + XVECEXP (outgoing, 0, i) + = gen_rtx_EXPR_LIST (VOIDmode, reg, + XEXP (XVECEXP (incoming, 0, i), 1)); + vec_safe_push (windowed_parm_regs, p); + } + + incoming = outgoing; + } else if (MEM_P (incoming) && REG_P (XEXP (incoming, 0)) && HARD_REGISTER_P (XEXP (incoming, 0))) @@ -9683,6 +9749,20 @@ vt_add_function_parameter (tree parm) } } } + else if (GET_CODE (incoming) == PARALLEL && !dv_onepart_p (dv)) + { + int i; + + for (i = 0; i < XVECLEN (incoming, 0); i++) + { + rtx reg = XEXP (XVECEXP (incoming, 0, i), 0); + offset = REG_OFFSET (reg); + gcc_assert (REGNO (reg) < FIRST_PSEUDO_REGISTER); + attrs_list_insert (&out->regs[REGNO (reg)], dv, offset, reg); + set_variable_part (out, reg, dv, offset, + VAR_INIT_STATUS_INITIALIZED, NULL, INSERT); + } + } else if (MEM_P (incoming)) { incoming = var_lowpart (mode, incoming); diff --git a/gcc/varasm.c b/gcc/varasm.c index f627fe9b771..b6ebd9c1295 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -4696,7 +4696,6 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align) case REFERENCE_TYPE: case OFFSET_TYPE: case FIXED_POINT_TYPE: - case POINTER_BOUNDS_TYPE: case NULLPTR_TYPE: if (! assemble_integer (expand_expr (exp, NULL_RTX, VOIDmode, EXPAND_INITIALIZER), diff --git a/gcc/varpool.c b/gcc/varpool.c index f79cf49cc55..1e469b3a253 100644 --- a/gcc/varpool.c +++ b/gcc/varpool.c @@ -28,12 +28,11 @@ along with GCC; see the file COPYING3. If not see #include "langhooks.h" #include "diagnostic-core.h" #include "hashtab.h" -#include "ggc.h" #include "timevar.h" #include "debug.h" #include "target.h" #include "output.h" -#include "gimple.h" +#include "gimple-expr.h" #include "flags.h" /* List of hooks triggered on varpool_node events. */ @@ -205,8 +204,6 @@ dump_varpool_node (FILE *f, struct varpool_node *node) fprintf (f, " initialized"); if (node->output) fprintf (f, " output"); - if (node->need_bounds_init) - fprintf (f, " need-bounds-init"); if (TREE_READONLY (node->decl)) fprintf (f, " read-only"); if (ctor_for_folding (node->decl) != error_mark_node) diff --git a/gcc/vtable-verify.c b/gcc/vtable-verify.c index 8d692e62e11..46c5621509d 100644 --- a/gcc/vtable-verify.c +++ b/gcc/vtable-verify.c @@ -138,6 +138,10 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tree.h" #include "basic-block.h" +#include "tree-ssa-alias.h" +#include "internal-fn.h" +#include "gimple-expr.h" +#include "is-a.h" #include "gimple.h" #include "gimple-iterator.h" #include "gimple-ssa.h" diff --git a/include/ChangeLog b/include/ChangeLog index a43d36758d6..9109c7694e6 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,7 @@ +2013-12-04 Richard Sandiford <rdsandiford@googlemail.com> + + * longlong.h: New file. + 2013-10-29 Marc Glisse <marc.glisse@inria.fr> PR tree-optimization/58689 diff --git a/libgcc/longlong.h b/include/longlong.h index 5f00e548a70..5f00e548a70 100644 --- a/libgcc/longlong.h +++ b/include/longlong.h diff --git a/libbacktrace/ChangeLog b/libbacktrace/ChangeLog index 79ac1178f80..3b86043fbfb 100644 --- a/libbacktrace/ChangeLog +++ b/libbacktrace/ChangeLog @@ -1,3 +1,12 @@ +2013-11-27 Ian Lance Taylor <iant@google.com> + + * dwarf.c (find_address_ranges): New static function, broken out + of build_address_map. + (build_address_map): Call it. + * btest.c (check): Check for missing filename or function, rather + than crashing. + (f3): Check that enough frames were returned. + 2013-11-19 Jakub Jelinek <jakub@redhat.com> * backtrace.h (backtrace_syminfo_callback): Add symsize argument. diff --git a/libbacktrace/btest.c b/libbacktrace/btest.c index 22b08e05030..17fea3061f5 100644 --- a/libbacktrace/btest.c +++ b/libbacktrace/btest.c @@ -129,6 +129,13 @@ check (const char *name, int index, const struct info *all, int want_lineno, { if (*failed) return; + if (all[index].filename == NULL || all[index].function == NULL) + { + fprintf (stderr, "%s: [%d]: missing file name or function name\n", + name, index); + *failed = 1; + return; + } if (strcmp (base (all[index].filename), "btest.c") != 0) { fprintf (stderr, "%s: [%d]: got %s expected test.c\n", name, index, @@ -310,6 +317,14 @@ f3 (int f1line, int f2line) data.failed = 1; } + if (data.index < 3) + { + fprintf (stderr, + "test1: not enough frames; got %zu, expected at least 3\n", + data.index); + data.failed = 1; + } + check ("test1", 0, all, f3line, "f3", &data.failed); check ("test1", 1, all, f2line, "f2", &data.failed); check ("test1", 2, all, f1line, "test1", &data.failed); diff --git a/libbacktrace/dwarf.c b/libbacktrace/dwarf.c index 0aba2d3f574..f9c3b3723e7 100644 --- a/libbacktrace/dwarf.c +++ b/libbacktrace/dwarf.c @@ -1235,54 +1235,24 @@ add_unit_ranges (struct backtrace_state *state, uintptr_t base_address, return 1; } -/* Build a mapping from address ranges to the compilation units where - the line number information for that range can be found. Returns 1 - on success, 0 on failure. */ +/* Find the address range covered by a compilation unit, reading from + UNIT_BUF and adding values to U. Returns 1 if all data could be + read, 0 if there is some error. */ static int -build_address_map (struct backtrace_state *state, uintptr_t base_address, - const unsigned char *dwarf_info, size_t dwarf_info_size, - const unsigned char *dwarf_abbrev, size_t dwarf_abbrev_size, - const unsigned char *dwarf_ranges, size_t dwarf_ranges_size, - const unsigned char *dwarf_str, size_t dwarf_str_size, - int is_bigendian, backtrace_error_callback error_callback, - void *data, struct unit_addrs_vector *addrs) +find_address_ranges (struct backtrace_state *state, uintptr_t base_address, + struct dwarf_buf *unit_buf, + const unsigned char *dwarf_str, size_t dwarf_str_size, + const unsigned char *dwarf_ranges, + size_t dwarf_ranges_size, + int is_bigendian, backtrace_error_callback error_callback, + void *data, struct unit *u, + struct unit_addrs_vector *addrs) { - struct dwarf_buf info; - struct abbrevs abbrevs; - - memset (&addrs->vec, 0, sizeof addrs->vec); - addrs->count = 0; - - /* Read through the .debug_info section. FIXME: Should we use the - .debug_aranges section? gdb and addr2line don't use it, but I'm - not sure why. */ - - info.name = ".debug_info"; - info.start = dwarf_info; - info.buf = dwarf_info; - info.left = dwarf_info_size; - info.is_bigendian = is_bigendian; - info.error_callback = error_callback; - info.data = data; - info.reported_underflow = 0; - - memset (&abbrevs, 0, sizeof abbrevs); - while (info.left > 0) + while (unit_buf->left > 0) { - const unsigned char *unit_data_start; - uint64_t len; - int is_dwarf64; - struct dwarf_buf unit_buf; - int version; - uint64_t abbrev_offset; - const struct abbrev *abbrev; - int addrsize; - const unsigned char *unit_data; - size_t unit_data_len; - size_t unit_data_offset; uint64_t code; - size_t i; + const struct abbrev *abbrev; uint64_t lowpc; int have_lowpc; uint64_t highpc; @@ -1290,57 +1260,15 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address, int highpc_is_relative; uint64_t ranges; int have_ranges; - uint64_t lineoff; - int have_lineoff; - const char *filename; - const char *comp_dir; - - if (info.reported_underflow) - goto fail; - - unit_data_start = info.buf; - - is_dwarf64 = 0; - len = read_uint32 (&info); - if (len == 0xffffffff) - { - len = read_uint64 (&info); - is_dwarf64 = 1; - } - - unit_buf = info; - unit_buf.left = len; - - if (!advance (&info, len)) - goto fail; - - version = read_uint16 (&unit_buf); - if (version < 2 || version > 4) - { - dwarf_buf_error (&unit_buf, "unrecognized DWARF version"); - goto fail; - } - - abbrev_offset = read_offset (&unit_buf, is_dwarf64); - if (!read_abbrevs (state, abbrev_offset, dwarf_abbrev, dwarf_abbrev_size, - is_bigendian, error_callback, data, &abbrevs)) - goto fail; - - addrsize = read_byte (&unit_buf); - - unit_data = unit_buf.buf; - unit_data_len = unit_buf.left; - unit_data_offset = unit_buf.buf - unit_data_start; + size_t i; - /* We only look at the first attribute in the compilation unit. - In practice this will be a DW_TAG_compile_unit which will - tell us the PC range and where to find the line number - information. */ + code = read_uleb128 (unit_buf); + if (code == 0) + return 1; - code = read_uleb128 (&unit_buf); - abbrev = lookup_abbrev (&abbrevs, code, error_callback, data); + abbrev = lookup_abbrev (&u->abbrevs, code, error_callback, data); if (abbrev == NULL) - goto fail; + return 0; lowpc = 0; have_lowpc = 0; @@ -1349,18 +1277,14 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address, highpc_is_relative = 0; ranges = 0; have_ranges = 0; - lineoff = 0; - have_lineoff = 0; - filename = NULL; - comp_dir = NULL; for (i = 0; i < abbrev->num_attrs; ++i) { struct attr_val val; - if (!read_attribute (abbrev->attrs[i].form, &unit_buf, is_dwarf64, - version, addrsize, dwarf_str, dwarf_str_size, - &val)) - goto fail; + if (!read_attribute (abbrev->attrs[i].form, unit_buf, + u->is_dwarf64, u->version, u->addrsize, + dwarf_str, dwarf_str_size, &val)) + return 0; switch (abbrev->attrs[i].name) { @@ -1371,6 +1295,7 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address, have_lowpc = 1; } break; + case DW_AT_high_pc: if (val.encoding == ATTR_VAL_ADDRESS) { @@ -1384,6 +1309,7 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address, highpc_is_relative = 1; } break; + case DW_AT_ranges: if (val.encoding == ATTR_VAL_UINT || val.encoding == ATTR_VAL_REF_SECTION) @@ -1392,73 +1318,46 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address, have_ranges = 1; } break; + case DW_AT_stmt_list: - if (val.encoding == ATTR_VAL_UINT - || val.encoding == ATTR_VAL_REF_SECTION) - { - lineoff = val.u.uint; - have_lineoff = 1; - } + if (abbrev->tag == DW_TAG_compile_unit + && (val.encoding == ATTR_VAL_UINT + || val.encoding == ATTR_VAL_REF_SECTION)) + u->lineoff = val.u.uint; break; + case DW_AT_name: - if (val.encoding == ATTR_VAL_STRING) - filename = val.u.string; + if (abbrev->tag == DW_TAG_compile_unit + && val.encoding == ATTR_VAL_STRING) + u->filename = val.u.string; break; + case DW_AT_comp_dir: - if (val.encoding == ATTR_VAL_STRING) - comp_dir = val.u.string; + if (abbrev->tag == DW_TAG_compile_unit + && val.encoding == ATTR_VAL_STRING) + u->comp_dir = val.u.string; break; + default: break; } } - if (unit_buf.reported_underflow) - goto fail; - - if (((have_lowpc && have_highpc) || have_ranges) && have_lineoff) + if (abbrev->tag == DW_TAG_compile_unit + || abbrev->tag == DW_TAG_subprogram) { - struct unit *u; - struct unit_addrs a; - - u = ((struct unit *) - backtrace_alloc (state, sizeof *u, error_callback, data)); - if (u == NULL) - goto fail; - u->unit_data = unit_data; - u->unit_data_len = unit_data_len; - u->unit_data_offset = unit_data_offset; - u->version = version; - u->is_dwarf64 = is_dwarf64; - u->addrsize = addrsize; - u->filename = filename; - u->comp_dir = comp_dir; - u->abs_filename = NULL; - u->lineoff = lineoff; - u->abbrevs = abbrevs; - memset (&abbrevs, 0, sizeof abbrevs); - - /* The actual line number mappings will be read as - needed. */ - u->lines = NULL; - u->lines_count = 0; - u->function_addrs = NULL; - u->function_addrs_count = 0; - if (have_ranges) { if (!add_unit_ranges (state, base_address, u, ranges, lowpc, is_bigendian, dwarf_ranges, - dwarf_ranges_size, error_callback, data, - addrs)) - { - free_abbrevs (state, &u->abbrevs, error_callback, data); - backtrace_free (state, u, sizeof *u, error_callback, data); - goto fail; - } + dwarf_ranges_size, error_callback, + data, addrs)) + return 0; } - else + else if (have_lowpc && have_highpc) { + struct unit_addrs a; + if (highpc_is_relative) highpc += lowpc; a.low = lowpc; @@ -1467,17 +1366,146 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address, if (!add_unit_addr (state, base_address, a, error_callback, data, addrs)) - { - free_abbrevs (state, &u->abbrevs, error_callback, data); - backtrace_free (state, u, sizeof *u, error_callback, data); - goto fail; - } + return 0; } + + /* If we found the PC range in the DW_TAG_compile_unit, we + can stop now. */ + if (abbrev->tag == DW_TAG_compile_unit + && (have_ranges || (have_lowpc && have_highpc))) + return 1; } - else + + if (abbrev->has_children) { - free_abbrevs (state, &abbrevs, error_callback, data); - memset (&abbrevs, 0, sizeof abbrevs); + if (!find_address_ranges (state, base_address, unit_buf, + dwarf_str, dwarf_str_size, + dwarf_ranges, dwarf_ranges_size, + is_bigendian, error_callback, data, + u, addrs)) + return 0; + } + } + + return 1; +} + +/* Build a mapping from address ranges to the compilation units where + the line number information for that range can be found. Returns 1 + on success, 0 on failure. */ + +static int +build_address_map (struct backtrace_state *state, uintptr_t base_address, + const unsigned char *dwarf_info, size_t dwarf_info_size, + const unsigned char *dwarf_abbrev, size_t dwarf_abbrev_size, + const unsigned char *dwarf_ranges, size_t dwarf_ranges_size, + const unsigned char *dwarf_str, size_t dwarf_str_size, + int is_bigendian, backtrace_error_callback error_callback, + void *data, struct unit_addrs_vector *addrs) +{ + struct dwarf_buf info; + struct abbrevs abbrevs; + + memset (&addrs->vec, 0, sizeof addrs->vec); + addrs->count = 0; + + /* Read through the .debug_info section. FIXME: Should we use the + .debug_aranges section? gdb and addr2line don't use it, but I'm + not sure why. */ + + info.name = ".debug_info"; + info.start = dwarf_info; + info.buf = dwarf_info; + info.left = dwarf_info_size; + info.is_bigendian = is_bigendian; + info.error_callback = error_callback; + info.data = data; + info.reported_underflow = 0; + + memset (&abbrevs, 0, sizeof abbrevs); + while (info.left > 0) + { + const unsigned char *unit_data_start; + uint64_t len; + int is_dwarf64; + struct dwarf_buf unit_buf; + int version; + uint64_t abbrev_offset; + int addrsize; + struct unit *u; + + if (info.reported_underflow) + goto fail; + + unit_data_start = info.buf; + + is_dwarf64 = 0; + len = read_uint32 (&info); + if (len == 0xffffffff) + { + len = read_uint64 (&info); + is_dwarf64 = 1; + } + + unit_buf = info; + unit_buf.left = len; + + if (!advance (&info, len)) + goto fail; + + version = read_uint16 (&unit_buf); + if (version < 2 || version > 4) + { + dwarf_buf_error (&unit_buf, "unrecognized DWARF version"); + goto fail; + } + + abbrev_offset = read_offset (&unit_buf, is_dwarf64); + if (!read_abbrevs (state, abbrev_offset, dwarf_abbrev, dwarf_abbrev_size, + is_bigendian, error_callback, data, &abbrevs)) + goto fail; + + addrsize = read_byte (&unit_buf); + + u = ((struct unit *) + backtrace_alloc (state, sizeof *u, error_callback, data)); + if (u == NULL) + goto fail; + u->unit_data = unit_buf.buf; + u->unit_data_len = unit_buf.left; + u->unit_data_offset = unit_buf.buf - unit_data_start; + u->version = version; + u->is_dwarf64 = is_dwarf64; + u->addrsize = addrsize; + u->filename = NULL; + u->comp_dir = NULL; + u->abs_filename = NULL; + u->lineoff = 0; + u->abbrevs = abbrevs; + memset (&abbrevs, 0, sizeof abbrevs); + + /* The actual line number mappings will be read as needed. */ + u->lines = NULL; + u->lines_count = 0; + u->function_addrs = NULL; + u->function_addrs_count = 0; + + if (!find_address_ranges (state, base_address, &unit_buf, + dwarf_str, dwarf_str_size, + dwarf_ranges, dwarf_ranges_size, + is_bigendian, error_callback, data, + u, addrs)) + { + free_abbrevs (state, &u->abbrevs, error_callback, data); + backtrace_free (state, u, sizeof *u, error_callback, data); + goto fail; + } + + if (unit_buf.reported_underflow) + { + free_abbrevs (state, &u->abbrevs, error_callback, data); + backtrace_free (state, u, sizeof *u, error_callback, data); + goto fail; } } if (info.reported_underflow) diff --git a/libcilkrts/ChangeLog b/libcilkrts/ChangeLog index abcd198a635..6785d37ff53 100644 --- a/libcilkrts/ChangeLog +++ b/libcilkrts/ChangeLog @@ -1,3 +1,8 @@ +2013-11-25 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + * configure.ac (GCC_LIBSTDCXX_RAW_CXX_FLAGS): Remove. + * configure: Regenerate. + 2013-11-22 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> * configure.ac (libcilkrts_cv_have_attribute_visibility): Check diff --git a/libcilkrts/configure b/libcilkrts/configure index d60ac410a83..91da0a83a2c 100644 --- a/libcilkrts/configure +++ b/libcilkrts/configure @@ -682,9 +682,6 @@ am__isrc INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM -LIBSTDCXX_RAW_CXX_LDFLAGS -LIBSTDCXX_RAW_CXX_CXXFLAGS -target_noncanonical target_os target_vendor target_cpu @@ -2372,34 +2369,6 @@ test -n "$target_alias" && target_alias=${target_alias-$host_alias} - case ${build_alias} in - "") build_noncanonical=${build} ;; - *) build_noncanonical=${build_alias} ;; -esac - - case ${host_alias} in - "") host_noncanonical=${build_noncanonical} ;; - *) host_noncanonical=${host_alias} ;; -esac - - case ${target_alias} in - "") target_noncanonical=${host_noncanonical} ;; - *) target_noncanonical=${target_alias} ;; -esac - - - - - - LIBSTDCXX_RAW_CXX_CXXFLAGS="\ - -I\$(top_builddir)/../libstdc++-v3/include \ - -I\$(top_builddir)/../libstdc++-v3/include/\$(target_noncanonical) \ - -I\$(top_srcdir)/../libstdc++-v3/libsupc++" - LIBSTDCXX_RAW_CXX_LDFLAGS="\ - \$(top_builddir)/../libstdc++-v3/src/libstdc++.la" - - - am__api_version='1.11' # Find a good install program. We prefer a C program (faster), @@ -11087,7 +11056,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11090 "configure" +#line 11059 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -11193,7 +11162,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11196 "configure" +#line 11165 "configure" #include "confdefs.h" #if HAVE_DLFCN_H diff --git a/libcilkrts/configure.ac b/libcilkrts/configure.ac index 84588db4224..30fac992172 100644 --- a/libcilkrts/configure.ac +++ b/libcilkrts/configure.ac @@ -39,7 +39,6 @@ AC_PREREQ([2.64]) AC_CANONICAL_SYSTEM target_alias=${target_alias-$host_alias} AC_SUBST(target_alias) -GCC_LIBSTDCXX_RAW_CXX_FLAGS AM_INIT_AUTOMAKE(foreign no-dist) AM_MAINTAINER_MODE diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index b5224f1989e..94f69caaaf5 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,53 @@ +2013-12-04 Richard Sandiford <rdsandiford@googlemail.com> + + * longlong.h: Delete (moved to include/). + +2013-12-03 Adhemerval Zanella <azanella@linux.vnet.ibm.com> + + * config/rs6000/ibm-ldouble.c (__gcc_qadd): Fix add + of normal number and qNaN to not raise an inexact exception. + +2013-11-28 Uros Bizjak <ubizjak@gmail.com> + + * config/i386/32/sfp-machine.h (__FP_FRAC_ADDI_4): New macro. + +2013-11-28 Matthew Leach <matthew.leach@arm.com> + + * config/aarch64/linux-unwind.h (aarch64_fallback_frame_state): Check + for correct opcodes on BE. + +2013-11-27 Uros Bizjak <ubizjak@gmail.com> + + * soft-fp/op-4.h: Update from glibc. + +2013-11-27 Kugan Vivekanandarajah <kuganv@linaro.org> + + * libgcc2.c (__udivmoddi4): Define new implementation when + TARGET_HAS_NO_HW_DIVIDE is defined, for processors without any + divide instructions. + +2013-11-25 Oleg Endo <olegendo@gcc.gnu.org> + + * config/sh/crt1.S (start): Don't do VBR_SETUP for SH2E. + +2013-11-25 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + * config/t-softfp (soft-fp-objects-base): New variable. + (soft-fp-objects): Use it. + +2013-11-23 David Edelson <dje.gcc@gmail.com> + Andrew Dixie <andrewd@gentrack.com> + + PR target/33704 + * config/rs6000/aixinitfini.c: New file. + * config/rs6000/t-aix-cxa (LIB2ADD_ST): Add aixinitfini.c. + * config/rs6000/libgcc-aix-cxa.ver (GCC_4.9): Add libgcc initfini + symbols. + +2013-11-22 Yuri Rumyantsev <ysrumyan@gmail.com> + + * config/i386/cpuinfo.c (get_intel_cpu): Add Silvermont cases. + 2013-11-18 Jan Hubicka <jh@suse.cz> * libgcov-driver.c (run_accounted): Make global level static. diff --git a/libgcc/config/aarch64/linux-unwind.h b/libgcc/config/aarch64/linux-unwind.h index fde4d1495e7..8b0d7fe39e1 100644 --- a/libgcc/config/aarch64/linux-unwind.h +++ b/libgcc/config/aarch64/linux-unwind.h @@ -25,6 +25,19 @@ #include <signal.h> #include <sys/ucontext.h> + +/* Since insns are always stored LE, on a BE system the opcodes will + be loaded byte-reversed. Therefore, define two sets of opcodes, + one for LE and one for BE. */ + +#if __AARCH64EB__ +#define MOVZ_X8_8B 0x681180d2 +#define SVC_0 0x010000d4 +#else +#define MOVZ_X8_8B 0xd2801168 +#define SVC_0 0xd4000001 +#endif + #define MD_FALLBACK_FRAME_STATE_FOR aarch64_fallback_frame_state static _Unwind_Reason_Code @@ -55,7 +68,7 @@ aarch64_fallback_frame_state (struct _Unwind_Context *context, 0xd2801168 movz x8, #0x8b 0xd4000001 svc 0x0 */ - if (pc[0] != 0xd2801168 || pc[1] != 0xd4000001) + if (pc[0] != MOVZ_X8_8B || pc[1] != SVC_0) { return _URC_END_OF_STACK; } diff --git a/libgcc/config/i386/32/sfp-machine.h b/libgcc/config/i386/32/sfp-machine.h index b9eb16633eb..1fa282d7afe 100644 --- a/libgcc/config/i386/32/sfp-machine.h +++ b/libgcc/config/i386/32/sfp-machine.h @@ -63,6 +63,16 @@ "g" ((USItype) (y1)), \ "2" ((USItype) (x0)), \ "g" ((USItype) (y0))) +#define __FP_FRAC_ADDI_4(x3,x2,x1,x0,i) \ + __asm__ ("add{l} {%4,%3|%3,%4}\n\t" \ + "adc{l} {$0,%2|%2,0}\n\t" \ + "adc{l} {$0,%1|%1,0}\n\t" \ + "adc{l} {$0,%0|%0,0}" \ + : "+r" ((USItype) (x3)), \ + "+&r" ((USItype) (x2)), \ + "+&r" ((USItype) (x1)), \ + "+&r" ((USItype) (x0)) \ + : "g" ((USItype) (i))) #define _FP_MUL_MEAT_S(R,X,Y) \ diff --git a/libgcc/config/i386/cpuinfo.c b/libgcc/config/i386/cpuinfo.c index 1c744f12344..1a891e0c52f 100644 --- a/libgcc/config/i386/cpuinfo.c +++ b/libgcc/config/i386/cpuinfo.c @@ -170,6 +170,11 @@ get_intel_cpu (unsigned int family, unsigned int model, unsigned int brand_id) /* Atom. */ __cpu_model.__cpu_type = INTEL_ATOM; break; + case 0x37: + case 0x4d: + /* Silvermont. */ + __cpu_model.__cpu_type = INTEL_SLM; + break; case 0x1a: case 0x1e: case 0x1f: diff --git a/libgcc/config/rs6000/aixinitfini.c b/libgcc/config/rs6000/aixinitfini.c new file mode 100644 index 00000000000..e95575820e2 --- /dev/null +++ b/libgcc/config/rs6000/aixinitfini.c @@ -0,0 +1,33 @@ +/* FIXME: rename this file */ + +/* + Artificially create _GLOBAL_AIX[ID]_shr_o symbols in libgcc.a. + + This means that libstdc++.a can invoke these symbols and they are resolved + regardless of whether libstdc++.a is linked against libgcc_s.a or libgcc.a. + + The symbols are created in libgcc_s.a by collect2 as there are exception + frames to register for LIB2_DIVMOD_FUNCS. + + The symbols are NOT created by collect2 for libgcc.a, because libgcc.a is + a 'real' archive containing objects and collect2 is not invoked. + + libstdc++.a is linked against libgcc.a when handling the command line + options '-static-libgcc -static-libstdc++'. +*/ + +void _GLOBAL__AIXI_shr_o (void); +void _GLOBAL__AIXD_shr_o (void); + +void +_GLOBAL__AIXI_shr_o (void) +{ + return; +} + +void +_GLOBAL__AIXD_shr_o (void) +{ + return; +} + diff --git a/libgcc/config/rs6000/ibm-ldouble.c b/libgcc/config/rs6000/ibm-ldouble.c index 28e02e995d4..7ca900c7830 100644 --- a/libgcc/config/rs6000/ibm-ldouble.c +++ b/libgcc/config/rs6000/ibm-ldouble.c @@ -104,6 +104,8 @@ __gcc_qadd (double a, double aa, double c, double cc) if (nonfinite (z)) { + if (fabs (z) != inf()) + return z; z = cc + aa + c + a; if (nonfinite (z)) return z; diff --git a/libgcc/config/rs6000/libgcc-aix-cxa.ver b/libgcc/config/rs6000/libgcc-aix-cxa.ver index 083067d141b..f89df2312a3 100644 --- a/libgcc/config/rs6000/libgcc-aix-cxa.ver +++ b/libgcc/config/rs6000/libgcc-aix-cxa.ver @@ -2,3 +2,8 @@ GCC_4.8 { __cxa_atexit __cxa_finalize } + +GCC_4.9 { + _GLOBAL__AIXI_shr_o + _GLOBAL__AIXD_shr_o +} diff --git a/libgcc/config/rs6000/t-aix-cxa b/libgcc/config/rs6000/t-aix-cxa index 4ef818558a7..4755c20c964 100644 --- a/libgcc/config/rs6000/t-aix-cxa +++ b/libgcc/config/rs6000/t-aix-cxa @@ -1,6 +1,8 @@ LIB2ADDEH += $(srcdir)/config/rs6000/cxa_atexit.c \ $(srcdir)/config/rs6000/cxa_finalize.c +LIB2ADD_ST += $(srcdir)/config/rs6000/aixinitfini.c + SHLIB_MAPFILES += $(srcdir)/config/rs6000/libgcc-aix-cxa.ver crtcxa.o: $(srcdir)/config/rs6000/crtcxa.c diff --git a/libgcc/config/sh/crt1.S b/libgcc/config/sh/crt1.S index 0b9e0858f72..5bbf016e68b 100644 --- a/libgcc/config/sh/crt1.S +++ b/libgcc/config/sh/crt1.S @@ -697,7 +697,7 @@ profiling_enabled: start: mov.l stack_k,r15 -#if defined (__SH3__) || (defined (__SH_FPU_ANY__) && ! defined (__SH2A__)) || defined (__SH4_NOFPU__) +#if defined (__SH3__) || (defined (__SH_FPU_ANY__) && ! defined (__SH2E__) && ! defined (__SH2A__)) || defined (__SH4_NOFPU__) #define VBR_SETUP ! before zeroing the bss ... ! if the vbr is already set to vbr_start then the program has been restarted diff --git a/libgcc/config/t-softfp b/libgcc/config/t-softfp index 6d0c38bcc5e..cabda6e5705 100644 --- a/libgcc/config/t-softfp +++ b/libgcc/config/t-softfp @@ -88,8 +88,10 @@ endif # for the functions in the soft-fp files have not been brought across # from glibc. -soft-fp-objects = $(addsuffix $(objext), $(softfp_file_list)) \ - $(addsuffix _s$(objext), $(softfp_file_list)) +soft-fp-objects-base = $(basename $(notdir $(softfp_file_list))) + +soft-fp-objects = $(addsuffix $(objext), $(soft-fp-objects-base)) \ + $(addsuffix _s$(objext), $(soft-fp-objects-base)) $(soft-fp-objects) : INTERNAL_CFLAGS += -Wno-missing-prototypes -Wno-type-limits diff --git a/libgcc/libgcc2.c b/libgcc/libgcc2.c index bec411be0b5..8c4cc6a316c 100644 --- a/libgcc/libgcc2.c +++ b/libgcc/libgcc2.c @@ -934,6 +934,74 @@ __parityDI2 (UDWtype x) #endif #ifdef L_udivmoddi4 +#ifdef TARGET_HAS_NO_HW_DIVIDE + +#if (defined (L_udivdi3) || defined (L_divdi3) || \ + defined (L_umoddi3) || defined (L_moddi3)) +static inline __attribute__ ((__always_inline__)) +#endif +UDWtype +__udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp) +{ + UDWtype q = 0, r = n, y = d; + UWtype lz1, lz2, i, k; + + /* Implements align divisor shift dividend method. This algorithm + aligns the divisor under the dividend and then perform number of + test-subtract iterations which shift the dividend left. Number of + iterations is k + 1 where k is the number of bit positions the + divisor must be shifted left to align it under the dividend. + quotient bits can be saved in the rightmost positions of the dividend + as it shifts left on each test-subtract iteration. */ + + if (y <= r) + { + lz1 = __builtin_clzll (d); + lz2 = __builtin_clzll (n); + + k = lz1 - lz2; + y = (y << k); + + /* Dividend can exceed 2 ^ (width − 1) − 1 but still be less than the + aligned divisor. Normal iteration can drops the high order bit + of the dividend. Therefore, first test-subtract iteration is a + special case, saving its quotient bit in a separate location and + not shifting the dividend. */ + if (r >= y) + { + r = r - y; + q = (1ULL << k); + } + + if (k > 0) + { + y = y >> 1; + + /* k additional iterations where k regular test subtract shift + dividend iterations are done. */ + i = k; + do + { + if (r >= y) + r = ((r - y) << 1) + 1; + else + r = (r << 1); + i = i - 1; + } while (i != 0); + + /* First quotient bit is combined with the quotient bits resulting + from the k regular iterations. */ + q = q + r; + r = r >> k; + q = q - (r << k); + } + } + + if (rp) + *rp = r; + return q; +} +#else #if (defined (L_udivdi3) || defined (L_divdi3) || \ defined (L_umoddi3) || defined (L_moddi3)) @@ -1152,6 +1220,7 @@ __udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp) return ww.ll; } #endif +#endif #ifdef L_divdi3 DWtype diff --git a/libgcc/soft-fp/op-4.h b/libgcc/soft-fp/op-4.h index 3515bdc497b..6c6b4611662 100644 --- a/libgcc/soft-fp/op-4.h +++ b/libgcc/soft-fp/op-4.h @@ -709,7 +709,7 @@ else if (rsize <= 2*_FP_W_TYPE_SIZE) \ { \ r = X##_f[1]; \ - r <<= _FP_W_TYPE_SIZE; \ + r = (rsize <= _FP_W_TYPE_SIZE ? 0 : r << _FP_W_TYPE_SIZE); \ r += X##_f[0]; \ } \ else \ @@ -717,11 +717,11 @@ /* I'm feeling lazy so we deal with int == 3words (implausible)*/ \ /* and int == 4words as a single case. */ \ r = X##_f[3]; \ - r <<= _FP_W_TYPE_SIZE; \ + r = (rsize <= _FP_W_TYPE_SIZE ? 0 : r << _FP_W_TYPE_SIZE); \ r += X##_f[2]; \ - r <<= _FP_W_TYPE_SIZE; \ + r = (rsize <= _FP_W_TYPE_SIZE ? 0 : r << _FP_W_TYPE_SIZE); \ r += X##_f[1]; \ - r <<= _FP_W_TYPE_SIZE; \ + r = (rsize <= _FP_W_TYPE_SIZE ? 0 : r << _FP_W_TYPE_SIZE); \ r += X##_f[0]; \ } \ } \ diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog index 5bded877e0f..a428205e562 100644 --- a/libgfortran/ChangeLog +++ b/libgfortran/ChangeLog @@ -1,3 +1,9 @@ +2013-12-01 Uros Bizjak <ubizjak@gmail.com> + + PR libfortran/59313 + * intrinsics/erfc_scaled.c (erfc_scaled_r16): Also provide for + quadruple precision long double variant. + 2013-11-20 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> * intrinsics/erfc_scaled.c (erfc_scaled_r16): Don't define if diff --git a/libgfortran/intrinsics/erfc_scaled.c b/libgfortran/intrinsics/erfc_scaled.c index f69e1fc7357..0498508a5bb 100644 --- a/libgfortran/intrinsics/erfc_scaled.c +++ b/libgfortran/intrinsics/erfc_scaled.c @@ -45,17 +45,34 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #include "erfc_scaled_inc.c" #endif -#if defined(HAVE_GFC_REAL_16) && defined(GFC_REAL_16_IS_LONG_DOUBLE) -#undef KIND -#define KIND 16 -#include "erfc_scaled_inc.c" -#endif +#ifdef HAVE_GFC_REAL_16 +/* For quadruple-precision, netlib's implementation is + not accurate enough. We provide another one. */ #ifdef GFC_REAL_16_IS_FLOAT128 -/* For quadruple-precision (__float128), netlib's implementation is - not accurate enough. We provide another one. */ +# define _THRESH -106.566990228185312813205074546585730Q +# define _M_2_SQRTPI M_2_SQRTPIq +# define _INF __builtin_infq() +# define _ERFC(x) erfcq(x) +# define _EXP(x) expq(x) + +#else + +# define _THRESH -106.566990228185312813205074546585730L +# define _M_2_SQRTPI M_2_SQRTPIl +# define _INF __builtin_infl() +# ifdef HAVE_ERFCL +# define _ERFC(x) erfcl(x) +# endif +# ifdef HAVE_EXPL +# define _EXP(x) expl(x) +# endif + +#endif + +#if defined(_ERFC) && defined(_EXP) extern GFC_REAL_16 erfc_scaled_r16 (GFC_REAL_16); export_proto(erfc_scaled_r16); @@ -63,15 +80,15 @@ export_proto(erfc_scaled_r16); GFC_REAL_16 erfc_scaled_r16 (GFC_REAL_16 x) { - if (x < -106.566990228185312813205074546585730Q) + if (x < _THRESH) { - return __builtin_infq(); + return _INF; } if (x < 12) { /* Compute directly as ERFC_SCALED(x) = ERFC(x) * EXP(X**2). This is not perfect, but much better than netlib. */ - return erfcq(x) * expq(x * x); + return _ERFC(x) * _EXP(x * x); } else { @@ -97,9 +114,10 @@ erfc_scaled_r16 (GFC_REAL_16 x) n++; } - return (1 + sum) / x * (M_2_SQRTPIq / 2); + return (1 + sum) / x * (_M_2_SQRTPI / 2); } } #endif +#endif diff --git a/libgfortran/intrinsics/erfc_scaled_inc.c b/libgfortran/intrinsics/erfc_scaled_inc.c index 107d91a6c9d..b643edf43a4 100644 --- a/libgfortran/intrinsics/erfc_scaled_inc.c +++ b/libgfortran/intrinsics/erfc_scaled_inc.c @@ -39,7 +39,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see # define EXP(x) exp(x) # define TRUNC(x) trunc(x) -#elif (KIND == 10) || (KIND == 16 && defined(GFC_REAL_16_IS_LONG_DOUBLE)) +#elif (KIND == 10) # ifdef HAVE_EXPL # define EXP(x) expl(x) diff --git a/libgo/MERGE b/libgo/MERGE index 28586372b0e..14d78eae0e9 100644 --- a/libgo/MERGE +++ b/libgo/MERGE @@ -1,4 +1,4 @@ -7ebbddd21330 +65bf677ab8d8 The first line of this file holds the Mercurial revision number of the last merge done from the master library sources. diff --git a/libgo/Makefile.am b/libgo/Makefile.am index 92fe175cd78..0851b71e02e 100644 --- a/libgo/Makefile.am +++ b/libgo/Makefile.am @@ -488,6 +488,7 @@ runtime_files = \ runtime/go-unsafe-newarray.c \ runtime/go-unsafe-pointer.c \ runtime/go-unwind.c \ + runtime/go-varargs.c \ runtime/chan.c \ runtime/cpuprof.c \ runtime/env_posix.c \ diff --git a/libgo/Makefile.in b/libgo/Makefile.in index edbc2e1ff8a..ca9df103620 100644 --- a/libgo/Makefile.in +++ b/libgo/Makefile.in @@ -212,10 +212,10 @@ am__objects_6 = go-append.lo go-assert.lo go-assert-interface.lo \ go-type-float.lo go-type-identity.lo go-type-interface.lo \ go-type-string.lo go-typedesc-equal.lo go-typestring.lo \ go-unsafe-new.lo go-unsafe-newarray.lo go-unsafe-pointer.lo \ - go-unwind.lo chan.lo cpuprof.lo env_posix.lo lfstack.lo \ - $(am__objects_1) mcache.lo mcentral.lo $(am__objects_2) \ - mfinal.lo mfixalloc.lo mgc0.lo mheap.lo msize.lo \ - $(am__objects_3) panic.lo parfor.lo print.lo proc.lo \ + go-unwind.lo go-varargs.lo chan.lo cpuprof.lo env_posix.lo \ + lfstack.lo $(am__objects_1) mcache.lo mcentral.lo \ + $(am__objects_2) mfinal.lo mfixalloc.lo mgc0.lo mheap.lo \ + msize.lo $(am__objects_3) panic.lo parfor.lo print.lo proc.lo \ runtime.lo signal_unix.lo thread.lo yield.lo $(am__objects_4) \ iface.lo malloc.lo map.lo mprof.lo netpoll.lo reflect.lo \ runtime1.lo sema.lo sigqueue.lo string.lo time.lo \ @@ -819,6 +819,7 @@ runtime_files = \ runtime/go-unsafe-newarray.c \ runtime/go-unsafe-pointer.c \ runtime/go-unwind.c \ + runtime/go-varargs.c \ runtime/chan.c \ runtime/cpuprof.c \ runtime/env_posix.c \ @@ -2451,6 +2452,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-unsafe-newarray.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-unsafe-pointer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-unwind.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/go-varargs.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/iface.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lfstack.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lock_futex.Plo@am__quote@ @@ -2979,6 +2981,13 @@ go-unwind.lo: runtime/go-unwind.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-unwind.lo `test -f 'runtime/go-unwind.c' || echo '$(srcdir)/'`runtime/go-unwind.c +go-varargs.lo: runtime/go-varargs.c +@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT go-varargs.lo -MD -MP -MF $(DEPDIR)/go-varargs.Tpo -c -o go-varargs.lo `test -f 'runtime/go-varargs.c' || echo '$(srcdir)/'`runtime/go-varargs.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/go-varargs.Tpo $(DEPDIR)/go-varargs.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='runtime/go-varargs.c' object='go-varargs.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o go-varargs.lo `test -f 'runtime/go-varargs.c' || echo '$(srcdir)/'`runtime/go-varargs.c + chan.lo: runtime/chan.c @am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT chan.lo -MD -MP -MF $(DEPDIR)/chan.Tpo -c -o chan.lo `test -f 'runtime/chan.c' || echo '$(srcdir)/'`runtime/chan.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/chan.Tpo $(DEPDIR)/chan.Plo diff --git a/libgo/config.h.in b/libgo/config.h.in index 8af626d6208..73854351c76 100644 --- a/libgo/config.h.in +++ b/libgo/config.h.in @@ -177,6 +177,9 @@ /* Define to 1 if the system has the type `off64_t'. */ #undef HAVE_OFF64_T +/* Define to 1 if you have the `open64' function. */ +#undef HAVE_OPEN64 + /* Define to 1 if you have the `openat' function. */ #undef HAVE_OPENAT diff --git a/libgo/config/libtool.m4 b/libgo/config/libtool.m4 index a8321ede5a8..f1ffebf99cd 100644 --- a/libgo/config/libtool.m4 +++ b/libgo/config/libtool.m4 @@ -1239,10 +1239,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) x86_64-*linux*) LD="${LD-ld} -m elf_i386" ;; - powerpc64le-*) + powerpc64le-*linux*) LD="${LD-ld} -m elf32lppclinux" ;; - powerpc64-*) + powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) @@ -1261,10 +1261,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; - powerpcle-*) + powerpcle-*linux*) LD="${LD-ld} -m elf64lppc" ;; - powerpc-*) + powerpc-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) diff --git a/libgo/configure b/libgo/configure index 35bf82088fd..46bb6066fb3 100755 --- a/libgo/configure +++ b/libgo/configure @@ -6521,10 +6521,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) x86_64-*linux*) LD="${LD-ld} -m elf_i386" ;; - powerpc64le-*) + powerpc64le-*linux*) LD="${LD-ld} -m elf32lppclinux" ;; - powerpc64-*) + powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) @@ -6543,10 +6543,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; - powerpcle-*) + powerpcle-*linux*) LD="${LD-ld} -m elf64lppc" ;; - powerpc-*) + powerpc-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) @@ -14718,7 +14718,7 @@ else fi -for ac_func in accept4 dup3 epoll_create1 faccessat fallocate fchmodat fchownat futimesat getxattr inotify_add_watch inotify_init inotify_init1 inotify_rm_watch listxattr mkdirat mknodat openat pipe2 removexattr renameat setxattr sync_file_range splice tee unlinkat unshare utimensat +for ac_func in accept4 dup3 epoll_create1 faccessat fallocate fchmodat fchownat futimesat getxattr inotify_add_watch inotify_init inotify_init1 inotify_rm_watch listxattr mkdirat mknodat open64 openat pipe2 removexattr renameat setxattr sync_file_range splice tee unlinkat unshare utimensat do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" diff --git a/libgo/configure.ac b/libgo/configure.ac index 0ffcaf9af03..b43a1580749 100644 --- a/libgo/configure.ac +++ b/libgo/configure.ac @@ -506,7 +506,7 @@ AC_CHECK_FUNCS(strerror_r strsignal wait4 mincore setenv dl_iterate_phdr) AM_CONDITIONAL(HAVE_STRERROR_R, test "$ac_cv_func_strerror_r" = yes) AM_CONDITIONAL(HAVE_WAIT4, test "$ac_cv_func_wait4" = yes) -AC_CHECK_FUNCS(accept4 dup3 epoll_create1 faccessat fallocate fchmodat fchownat futimesat getxattr inotify_add_watch inotify_init inotify_init1 inotify_rm_watch listxattr mkdirat mknodat openat pipe2 removexattr renameat setxattr sync_file_range splice tee unlinkat unshare utimensat) +AC_CHECK_FUNCS(accept4 dup3 epoll_create1 faccessat fallocate fchmodat fchownat futimesat getxattr inotify_add_watch inotify_init inotify_init1 inotify_rm_watch listxattr mkdirat mknodat open64 openat pipe2 removexattr renameat setxattr sync_file_range splice tee unlinkat unshare utimensat) AC_TYPE_OFF_T AC_CHECK_TYPES([loff_t]) diff --git a/libgo/go/database/sql/driver/driver.go b/libgo/go/database/sql/driver/driver.go index d7ca94f7809..0828e63c656 100644 --- a/libgo/go/database/sql/driver/driver.go +++ b/libgo/go/database/sql/driver/driver.go @@ -140,8 +140,8 @@ type Stmt interface { } // ColumnConverter may be optionally implemented by Stmt if the -// the statement is aware of its own columns' types and can -// convert from any type to a driver Value. +// statement is aware of its own columns' types and can convert from +// any type to a driver Value. type ColumnConverter interface { // ColumnConverter returns a ValueConverter for the provided // column index. If the type of a specific column isn't known diff --git a/libgo/go/database/sql/sql.go b/libgo/go/database/sql/sql.go index f7b4f8cdab8..dddf5a3f257 100644 --- a/libgo/go/database/sql/sql.go +++ b/libgo/go/database/sql/sql.go @@ -201,7 +201,7 @@ type DB struct { connRequests *list.List // of connRequest numOpen int pendingOpens int - // Used to sygnal the need for new connections + // Used to signal the need for new connections // a goroutine running connectionOpener() reads on this chan and // maybeOpenNewConnections sends on the chan (one send per needed connection) // It is closed during db.Close(). The close tells the connectionOpener @@ -1637,7 +1637,16 @@ func (r *Row) Scan(dest ...interface{}) error { // A Result summarizes an executed SQL command. type Result interface { + // LastInsertId returns the integer generated by the database + // in response to a command. Typically this will be from an + // "auto increment" column when inserting a new row. Not all + // databases support this feature, and the syntax of such + // statements varies. LastInsertId() (int64, error) + + // RowsAffected returns the number of rows affected by an + // update, insert, or delete. Not every database or database + // driver may support this. RowsAffected() (int64, error) } diff --git a/libgo/go/debug/dwarf/const.go b/libgo/go/debug/dwarf/const.go index ebe9a71a0c5..68503c742f6 100644 --- a/libgo/go/debug/dwarf/const.go +++ b/libgo/go/debug/dwarf/const.go @@ -207,9 +207,8 @@ const ( formRef8 format = 0x14 formRefUdata format = 0x15 formIndirect format = 0x16 - // following are defined in DWARF 4 formSecOffset format = 0x17 - formExprLoc format = 0x18 + formExprloc format = 0x18 formFlagPresent format = 0x19 formRefSig8 format = 0x20 ) diff --git a/libgo/go/debug/dwarf/entry.go b/libgo/go/debug/dwarf/entry.go index 4775283ca3a..e0d3229fb49 100644 --- a/libgo/go/debug/dwarf/entry.go +++ b/libgo/go/debug/dwarf/entry.go @@ -185,29 +185,15 @@ func (b *buf) entry(atab abbrevTable, ubase Offset) *Entry { case formUdata: val = int64(b.uint()) - // exprloc - case formExprLoc: - val = b.bytes(int(b.uint())) - // flag case formFlag: val = b.uint8() == 1 + // New in DWARF 4. case formFlagPresent: // The attribute is implicitly indicated as present, and no value is // encoded in the debugging information entry itself. val = true - // lineptr, loclistptr, macptr, rangelistptr - case formSecOffset: - is64, known := b.format.dwarf64() - if !known { - b.error("unknown size for DW_FORM_sec_offset") - } else if is64 { - val = Offset(b.uint64()) - } else { - val = Offset(b.uint32()) - } - // reference to other entry case formRefAddr: vers := b.format.version() @@ -235,8 +221,6 @@ func (b *buf) entry(atab abbrevTable, ubase Offset) *Entry { val = Offset(b.uint64()) + ubase case formRefUdata: val = Offset(b.uint()) + ubase - case formRefSig8: - val = b.uint64() // string case formString: @@ -253,6 +237,30 @@ func (b *buf) entry(atab abbrevTable, ubase Offset) *Entry { b.err = b1.err return nil } + + // lineptr, loclistptr, macptr, rangelistptr + // New in DWARF 4, but clang can generate them with -gdwarf-2. + // Section reference, replacing use of formData4 and formData8. + case formSecOffset: + is64, known := b.format.dwarf64() + if !known { + b.error("unknown size for DW_FORM_sec_offset") + } else if is64 { + val = int64(b.uint64()) + } else { + val = int64(b.uint32()) + } + + // exprloc + // New in DWARF 4. + case formExprloc: + val = b.bytes(int(b.uint())) + + // reference + // New in DWARF 4. + case formRefSig8: + // 64-bit type signature. + val = b.uint64() } e.Field[i].Val = val } diff --git a/libgo/go/encoding/gob/doc.go b/libgo/go/encoding/gob/doc.go index 28f0c05a5c5..d0acaba1adc 100644 --- a/libgo/go/encoding/gob/doc.go +++ b/libgo/go/encoding/gob/doc.go @@ -86,13 +86,13 @@ Functions and channels will not be sent in a gob. Attempting to encode such a va at top the level will fail. A struct field of chan or func type is treated exactly like an unexported field and is ignored. -Gob can encode a value of any type implementing the GobEncoder, -encoding.BinaryMarshaler, or encoding.TextMarshaler interfaces by calling the -corresponding method, in that order of preference. +Gob can encode a value of any type implementing the GobEncoder or +encoding.BinaryMarshaler interfaces by calling the corresponding method, +in that order of preference. -Gob can decode a value of any type implementing the GobDecoder, -encoding.BinaryUnmarshaler, or encoding.TextUnmarshaler interfaces by calling -the corresponding method, again in that order of preference. +Gob can decode a value of any type implementing the GobDecoder or +encoding.BinaryUnmarshaler interfaces by calling the corresponding method, +again in that order of preference. Encoding Details diff --git a/libgo/go/encoding/gob/gobencdec_test.go b/libgo/go/encoding/gob/gobencdec_test.go index 301551db48a..0193e2b67d4 100644 --- a/libgo/go/encoding/gob/gobencdec_test.go +++ b/libgo/go/encoding/gob/gobencdec_test.go @@ -11,6 +11,7 @@ import ( "errors" "fmt" "io" + "net" "strings" "testing" "time" @@ -767,3 +768,17 @@ func TestGobEncodePtrError(t *testing.T) { t.Fatalf("expected nil, got %v", err2) } } + +func TestNetIP(t *testing.T) { + // Encoding of net.IP{1,2,3,4} in Go 1.1. + enc := []byte{0x07, 0x0a, 0x00, 0x04, 0x01, 0x02, 0x03, 0x04} + + var ip net.IP + err := NewDecoder(bytes.NewReader(enc)).Decode(&ip) + if err != nil { + t.Fatalf("decode: %v", err) + } + if ip.String() != "1.2.3.4" { + t.Errorf("decoded to %v, want 1.2.3.4", ip.String()) + } +} diff --git a/libgo/go/encoding/gob/type.go b/libgo/go/encoding/gob/type.go index 65bf17b7f02..cad14527953 100644 --- a/libgo/go/encoding/gob/type.go +++ b/libgo/go/encoding/gob/type.go @@ -88,18 +88,25 @@ func validUserType(rt reflect.Type) (ut *userTypeInfo, err error) { ut.externalEnc, ut.encIndir = xGob, indir } else if ok, indir := implementsInterface(ut.user, binaryMarshalerInterfaceType); ok { ut.externalEnc, ut.encIndir = xBinary, indir - } else if ok, indir := implementsInterface(ut.user, textMarshalerInterfaceType); ok { - ut.externalEnc, ut.encIndir = xText, indir } + // NOTE(rsc): Would like to allow MarshalText here, but results in incompatibility + // with older encodings for net.IP. See golang.org/issue/6760. + // } else if ok, indir := implementsInterface(ut.user, textMarshalerInterfaceType); ok { + // ut.externalEnc, ut.encIndir = xText, indir + // } + if ok, indir := implementsInterface(ut.user, gobDecoderInterfaceType); ok { ut.externalDec, ut.decIndir = xGob, indir } else if ok, indir := implementsInterface(ut.user, binaryUnmarshalerInterfaceType); ok { ut.externalDec, ut.decIndir = xBinary, indir - } else if ok, indir := implementsInterface(ut.user, textUnmarshalerInterfaceType); ok { - ut.externalDec, ut.decIndir = xText, indir } + // See note above. + // } else if ok, indir := implementsInterface(ut.user, textUnmarshalerInterfaceType); ok { + // ut.externalDec, ut.decIndir = xText, indir + // } + userTypeCache[rt] = ut return } diff --git a/libgo/go/encoding/xml/read.go b/libgo/go/encoding/xml/read.go index da7ad3baedc..8890508f855 100644 --- a/libgo/go/encoding/xml/read.go +++ b/libgo/go/encoding/xml/read.go @@ -53,7 +53,7 @@ import ( // Unmarshal records the attribute value in that field. // // * If the XML element contains character data, that data is -// accumulated in the first struct field that has tag "chardata". +// accumulated in the first struct field that has tag ",chardata". // The struct field may have type []byte or string. // If there is no such field, the character data is discarded. // diff --git a/libgo/go/go/doc/synopsis.go b/libgo/go/go/doc/synopsis.go index d1ad86c7416..c90080b7cc1 100644 --- a/libgo/go/go/doc/synopsis.go +++ b/libgo/go/go/doc/synopsis.go @@ -22,6 +22,9 @@ func firstSentenceLen(s string) int { if q == ' ' && p == '.' && (!unicode.IsUpper(pp) || unicode.IsUpper(ppp)) { return i } + if p == '。' || p == '.' { + return i + } ppp, pp, p = pp, p, q } return len(s) diff --git a/libgo/go/go/doc/synopsis_test.go b/libgo/go/go/doc/synopsis_test.go index fd7081a07c2..59b253cb8dc 100644 --- a/libgo/go/go/doc/synopsis_test.go +++ b/libgo/go/go/doc/synopsis_test.go @@ -28,6 +28,8 @@ var tests = []struct { {"P. Q. ", 8, "P. Q."}, {"Package Καλημέρα κόσμε.", 36, "Package Καλημέρα κόσμε."}, {"Package こんにちは 世界\n", 31, "Package こんにちは 世界"}, + {"Package こんにちは。世界", 26, "Package こんにちは。"}, + {"Package 안녕.世界", 17, "Package 안녕."}, {"Package foo does bar.", 21, "Package foo does bar."}, {"Copyright 2012 Google, Inc. Package foo does bar.", 27, ""}, {"All Rights reserved. Package foo does bar.", 20, ""}, diff --git a/libgo/go/net/hosts_test.go b/libgo/go/net/hosts_test.go index 064e7e43282..b07ed0baa94 100644 --- a/libgo/go/net/hosts_test.go +++ b/libgo/go/net/hosts_test.go @@ -53,6 +53,19 @@ func TestLookupStaticHost(t *testing.T) { hostsPath = p } +// https://code.google.com/p/go/issues/detail?id=6646 +func TestSingleLineHostsFile(t *testing.T) { + p := hostsPath + hostsPath = "testdata/hosts_singleline" + + ips := lookupStaticHost("odin") + if len(ips) != 1 || ips[0] != "127.0.0.2" { + t.Errorf("lookupStaticHost = %v, want %v", ips, []string{"127.0.0.2"}) + } + + hostsPath = p +} + func TestLookupHost(t *testing.T) { // Can't depend on this to return anything in particular, // but if it does return something, make sure it doesn't diff --git a/libgo/go/net/http/httputil/dump.go b/libgo/go/net/http/httputil/dump.go index 0b003566165..265499fb00d 100644 --- a/libgo/go/net/http/httputil/dump.go +++ b/libgo/go/net/http/httputil/dump.go @@ -45,13 +45,27 @@ func (c *dumpConn) SetDeadline(t time.Time) error { return nil } func (c *dumpConn) SetReadDeadline(t time.Time) error { return nil } func (c *dumpConn) SetWriteDeadline(t time.Time) error { return nil } +type neverEnding byte + +func (b neverEnding) Read(p []byte) (n int, err error) { + for i := range p { + p[i] = byte(b) + } + return len(p), nil +} + // DumpRequestOut is like DumpRequest but includes // headers that the standard http.Transport adds, // such as User-Agent. func DumpRequestOut(req *http.Request, body bool) ([]byte, error) { save := req.Body + dummyBody := false if !body || req.Body == nil { req.Body = nil + if req.ContentLength != 0 { + req.Body = ioutil.NopCloser(io.LimitReader(neverEnding('x'), req.ContentLength)) + dummyBody = true + } } else { var err error save, req.Body, err = drainBody(req.Body) @@ -99,7 +113,19 @@ func DumpRequestOut(req *http.Request, body bool) ([]byte, error) { if err != nil { return nil, err } - return buf.Bytes(), nil + dump := buf.Bytes() + + // If we used a dummy body above, remove it now. + // TODO: if the req.ContentLength is large, we allocate memory + // unnecessarily just to slice it off here. But this is just + // a debug function, so this is acceptable for now. We could + // discard the body earlier if this matters. + if dummyBody { + if i := bytes.Index(dump, []byte("\r\n\r\n")); i >= 0 { + dump = dump[:i+4] + } + } + return dump, nil } // delegateReader is a reader that delegates to another reader, diff --git a/libgo/go/net/http/httputil/dump_test.go b/libgo/go/net/http/httputil/dump_test.go index 3e87c27bc36..987a820487d 100644 --- a/libgo/go/net/http/httputil/dump_test.go +++ b/libgo/go/net/http/httputil/dump_test.go @@ -20,6 +20,7 @@ type dumpTest struct { WantDump string WantDumpOut string + NoBody bool // if true, set DumpRequest{,Out} body to false } var dumpTests = []dumpTest{ @@ -83,6 +84,31 @@ var dumpTests = []dumpTest{ "User-Agent: Go 1.1 package http\r\n" + "Accept-Encoding: gzip\r\n\r\n", }, + + // Request with Body, but Dump requested without it. + { + Req: http.Request{ + Method: "POST", + URL: &url.URL{ + Scheme: "http", + Host: "post.tld", + Path: "/", + }, + ContentLength: 6, + ProtoMajor: 1, + ProtoMinor: 1, + }, + + Body: []byte("abcdef"), + + WantDumpOut: "POST / HTTP/1.1\r\n" + + "Host: post.tld\r\n" + + "User-Agent: Go 1.1 package http\r\n" + + "Content-Length: 6\r\n" + + "Accept-Encoding: gzip\r\n\r\n", + + NoBody: true, + }, } func TestDumpRequest(t *testing.T) { @@ -105,7 +131,7 @@ func TestDumpRequest(t *testing.T) { if tt.WantDump != "" { setBody() - dump, err := DumpRequest(&tt.Req, true) + dump, err := DumpRequest(&tt.Req, !tt.NoBody) if err != nil { t.Errorf("DumpRequest #%d: %s", i, err) continue @@ -118,7 +144,7 @@ func TestDumpRequest(t *testing.T) { if tt.WantDumpOut != "" { setBody() - dump, err := DumpRequestOut(&tt.Req, true) + dump, err := DumpRequestOut(&tt.Req, !tt.NoBody) if err != nil { t.Errorf("DumpRequestOut #%d: %s", i, err) continue diff --git a/libgo/go/net/parse.go b/libgo/go/net/parse.go index 7c87b42f6d9..6056de248e0 100644 --- a/libgo/go/net/parse.go +++ b/libgo/go/net/parse.go @@ -54,7 +54,7 @@ func (f *file) readLine() (s string, ok bool) { if n >= 0 { f.data = f.data[0 : ln+n] } - if err == io.EOF { + if err == io.EOF || err == io.ErrUnexpectedEOF { f.atEOF = true } } diff --git a/libgo/go/net/testdata/hosts_singleline b/libgo/go/net/testdata/hosts_singleline new file mode 100644 index 00000000000..5f5f74a3fad --- /dev/null +++ b/libgo/go/net/testdata/hosts_singleline @@ -0,0 +1 @@ +127.0.0.2 odin
\ No newline at end of file diff --git a/libgo/go/net/textproto/reader.go b/libgo/go/net/textproto/reader.go index 56ece5b087c..b0c07413c19 100644 --- a/libgo/go/net/textproto/reader.go +++ b/libgo/go/net/textproto/reader.go @@ -574,13 +574,10 @@ func canonicalMIMEHeaderKey(a []byte) string { // and upper case after each dash. // (Host, User-Agent, If-Modified-Since). // MIME headers are ASCII only, so no Unicode issues. - if a[i] == ' ' { - a[i] = '-' - upper = true - continue - } c := a[i] - if upper && 'a' <= c && c <= 'z' { + if c == ' ' { + c = '-' + } else if upper && 'a' <= c && c <= 'z' { c -= toLower } else if !upper && 'A' <= c && c <= 'Z' { c += toLower diff --git a/libgo/go/net/textproto/reader_test.go b/libgo/go/net/textproto/reader_test.go index f27042d4e9d..cc12912b634 100644 --- a/libgo/go/net/textproto/reader_test.go +++ b/libgo/go/net/textproto/reader_test.go @@ -25,6 +25,10 @@ var canonicalHeaderKeyTests = []canonicalHeaderKeyTest{ {"user-agent", "User-Agent"}, {"USER-AGENT", "User-Agent"}, {"üser-agenT", "üser-Agent"}, // non-ASCII unchanged + + // This caused a panic due to mishandling of a space: + {"C Ontent-Transfer-Encoding", "C-Ontent-Transfer-Encoding"}, + {"foo bar", "Foo-Bar"}, } func TestCanonicalMIMEHeaderKey(t *testing.T) { diff --git a/libgo/go/net/url/url.go b/libgo/go/net/url/url.go index 597cb51c883..3b3787202b7 100644 --- a/libgo/go/net/url/url.go +++ b/libgo/go/net/url/url.go @@ -558,8 +558,8 @@ func parseQuery(m Values, query string) (err error) { return err } -// Encode encodes the values into ``URL encoded'' form. -// e.g. "foo=bar&bar=baz" +// Encode encodes the values into ``URL encoded'' form +// ("bar=baz&foo=quux") sorted by key. func (v Values) Encode() string { if v == nil { return "" diff --git a/libgo/go/os/file_unix.go b/libgo/go/os/file_unix.go index 79eeaec5023..e8e42569bb3 100644 --- a/libgo/go/os/file_unix.go +++ b/libgo/go/os/file_unix.go @@ -176,14 +176,11 @@ func (f *File) readdir(n int) (fi []FileInfo, err error) { fi = make([]FileInfo, len(names)) for i, filename := range names { fip, lerr := lstat(dirname + filename) - if lerr == nil { - fi[i] = fip - } else { + if lerr != nil { fi[i] = &fileStat{name: filename} - if err == nil { - err = lerr - } + continue } + fi[i] = fip } return fi, err } diff --git a/libgo/go/os/os_unix_test.go b/libgo/go/os/os_unix_test.go index 80d57aa4222..b0fc0256de4 100644 --- a/libgo/go/os/os_unix_test.go +++ b/libgo/go/os/os_unix_test.go @@ -92,8 +92,8 @@ func TestReaddirWithBadLstat(t *testing.T) { defer func() { *LstatP = Lstat }() dirs, err := handle.Readdir(-1) - if err != ErrInvalid { - t.Fatalf("Expected Readdir to return ErrInvalid, got %v", err) + if err != nil { + t.Fatalf("Expected Readdir to return no error, got %v", err) } foundfail := false for _, dir := range dirs { diff --git a/libgo/go/reflect/makefunc_386.S b/libgo/go/reflect/makefunc_386.S index 5878bc44c56..3f10cba23b0 100644 --- a/libgo/go/reflect/makefunc_386.S +++ b/libgo/go/reflect/makefunc_386.S @@ -26,8 +26,11 @@ reflect.makeFuncStub: esp uint32 // 0x0 eax uint32 // 0x4 st0 uint64 // 0x8 + sr int32 // 0x10 } - */ + The sr field is set by the function to a non-zero value if + the function takes a struct hidden pointer that must be + popped off the stack. */ pushl %ebp .LCFI0: @@ -73,12 +76,19 @@ reflect.makeFuncStub: movsd -16(%ebp), %xmm0 #endif + movl -8(%ebp), %edx + addl $36, %esp popl %ebx .LCFI3: popl %ebp .LCFI4: + + testl %edx,%edx + jne 1f ret +1: + ret $4 .LFE1: #ifdef __ELF__ .size reflect.makeFuncStub, . - reflect.makeFuncStub diff --git a/libgo/go/reflect/makefuncgo_386.go b/libgo/go/reflect/makefuncgo_386.go index 0fac1f488a4..7559af6f6ac 100644 --- a/libgo/go/reflect/makefuncgo_386.go +++ b/libgo/go/reflect/makefuncgo_386.go @@ -16,6 +16,7 @@ type i386Regs struct { esp uint32 eax uint32 // Value to return in %eax. st0 uint64 // Value to return in %st(0). + sr int32 // Set to non-zero if hidden struct pointer. } // MakeFuncStubGo implements the 386 calling convention for MakeFunc. @@ -56,10 +57,12 @@ func MakeFuncStubGo(regs *i386Regs, c *makeFuncImpl) { in := make([]Value, 0, len(ftyp.in)) ap := uintptr(regs.esp) + regs.sr = 0 var retPtr unsafe.Pointer if retStruct { retPtr = *(*unsafe.Pointer)(unsafe.Pointer(ap)) ap += ptrSize + regs.sr = 1 } for _, rt := range ftyp.in { diff --git a/libgo/go/runtime/pprof/pprof_test.go b/libgo/go/runtime/pprof/pprof_test.go index bdbbf42f028..52d63b2e229 100644 --- a/libgo/go/runtime/pprof/pprof_test.go +++ b/libgo/go/runtime/pprof/pprof_test.go @@ -8,6 +8,7 @@ import ( "bytes" "fmt" "hash/crc32" + "math/big" "os/exec" "regexp" "runtime" @@ -123,6 +124,10 @@ func testCPUProfile(t *testing.T, need []string, f func()) { } }) + if len(need) == 0 { + return + } + var total uintptr for i, name := range need { total += have[i] @@ -237,6 +242,26 @@ func TestGoroutineSwitch(t *testing.T) { } } +// Test that profiling of division operations is okay, especially on ARM. See issue 6681. +func TestMathBigDivide(t *testing.T) { + testCPUProfile(t, nil, func() { + t := time.After(5 * time.Second) + pi := new(big.Int) + for { + for i := 0; i < 100; i++ { + n := big.NewInt(2646693125139304345) + d := big.NewInt(842468587426513207) + pi.Div(n, d) + } + select { + case <-t: + return + default: + } + } + }) +} + // Operating systems that are expected to fail the tests. See issue 6047. var badOS = map[string]bool{ "darwin": true, diff --git a/libgo/go/strings/replace.go b/libgo/go/strings/replace.go index f63b1792c56..54c9323e048 100644 --- a/libgo/go/strings/replace.go +++ b/libgo/go/strings/replace.go @@ -364,17 +364,18 @@ func makeSingleStringReplacer(pattern string, value string) *singleStringReplace func (r *singleStringReplacer) Replace(s string) string { var buf []byte - i := 0 + i, matched := 0, false for { match := r.finder.next(s[i:]) if match == -1 { break } + matched = true buf = append(buf, s[i:i+match]...) buf = append(buf, r.value...) i += match + len(r.finder.pattern) } - if buf == nil { + if !matched { return s } buf = append(buf, s[i:]...) diff --git a/libgo/go/strings/replace_test.go b/libgo/go/strings/replace_test.go index d33dea95b09..82e4b6ef08e 100644 --- a/libgo/go/strings/replace_test.go +++ b/libgo/go/strings/replace_test.go @@ -261,10 +261,21 @@ func TestReplacer(t *testing.T) { testCases = append(testCases, testCase{abcMatcher, "", ""}, testCase{abcMatcher, "ab", "ab"}, + testCase{abcMatcher, "abc", "[match]"}, testCase{abcMatcher, "abcd", "[match]d"}, testCase{abcMatcher, "cabcabcdabca", "c[match][match]d[match]a"}, ) + // Issue 6659 cases (more single string replacer) + + noHello := NewReplacer("Hello", "") + testCases = append(testCases, + testCase{noHello, "Hello", ""}, + testCase{noHello, "Hellox", "x"}, + testCase{noHello, "xHello", "x"}, + testCase{noHello, "xHellox", "xx"}, + ) + // No-arg test cases. nop := NewReplacer() diff --git a/libgo/go/syscall/exec_unix.go b/libgo/go/syscall/exec_unix.go index c31b8d5c4f6..0cfedb71cf6 100644 --- a/libgo/go/syscall/exec_unix.go +++ b/libgo/go/syscall/exec_unix.go @@ -30,7 +30,7 @@ import ( //chdir(path *byte) _C_int //sysnb raw_fcntl(fd int, cmd int, arg int) (val int, err Errno) -//fcntl(fd _C_int, cmd _C_int, arg _C_int) _C_int +//__go_fcntl(fd _C_int, cmd _C_int, arg _C_int) _C_int //sysnb raw_close(fd int) (err Errno) //close(fd _C_int) _C_int diff --git a/libgo/go/syscall/libcall_linux.go b/libgo/go/syscall/libcall_linux.go index 60eecd9ef89..d5bedd06aac 100644 --- a/libgo/go/syscall/libcall_linux.go +++ b/libgo/go/syscall/libcall_linux.go @@ -9,7 +9,7 @@ package syscall import "unsafe" //sys Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) -//openat(dirfd _C_int, path *byte, flags _C_int, mode Mode_t) _C_int +//__go_openat(dirfd _C_int, path *byte, flags _C_int, mode Mode_t) _C_int //sys futimesat(dirfd int, path *byte, times *[2]Timeval) (err error) //futimesat(dirfd _C_int, path *byte, times *[2]Timeval) _C_int diff --git a/libgo/go/syscall/libcall_posix.go b/libgo/go/syscall/libcall_posix.go index 91ff59b6cfa..8f5b0207583 100644 --- a/libgo/go/syscall/libcall_posix.go +++ b/libgo/go/syscall/libcall_posix.go @@ -206,7 +206,7 @@ func FDZero(set *FdSet) { //fchown(fd _C_int, uid Uid_t, gid Gid_t) _C_int //sys fcntl(fd int, cmd int, arg int) (val int, err error) -//fcntl(fd _C_int, cmd _C_int, arg _C_int) _C_int +//__go_fcntl(fd _C_int, cmd _C_int, arg _C_int) _C_int //sys Fdatasync(fd int) (err error) //fdatasync(fd _C_int) _C_int diff --git a/libgo/go/syscall/libcall_posix_largefile.go b/libgo/go/syscall/libcall_posix_largefile.go index 1ad76920474..fced6e57dde 100644 --- a/libgo/go/syscall/libcall_posix_largefile.go +++ b/libgo/go/syscall/libcall_posix_largefile.go @@ -19,7 +19,7 @@ package syscall //mmap64(addr *byte, length Size_t, prot _C_int, flags _C_int, fd _C_int, offset Offset_t) *byte //sys Open(path string, mode int, perm uint32) (fd int, err error) -//open64(path *byte, mode _C_int, perm Mode_t) _C_int +//__go_open64(path *byte, mode _C_int, perm Mode_t) _C_int //sys Pread(fd int, p []byte, offset int64) (n int, err error) //pread64(fd _C_int, buf *byte, count Size_t, offset Offset_t) Ssize_t diff --git a/libgo/go/syscall/libcall_posix_regfile.go b/libgo/go/syscall/libcall_posix_regfile.go index 5766e0c15f8..6c98e29873c 100644 --- a/libgo/go/syscall/libcall_posix_regfile.go +++ b/libgo/go/syscall/libcall_posix_regfile.go @@ -20,7 +20,7 @@ package syscall //mmap(addr *byte, length Size_t, prot _C_int, flags _C_int, fd _C_int, offset Offset_t) *byte //sys Open(path string, mode int, perm uint32) (fd int, err error) -//open(path *byte, mode _C_int, perm Mode_t) _C_int +//__go_open(path *byte, mode _C_int, perm Mode_t) _C_int //sys Pread(fd int, p []byte, offset int64) (n int, err error) //pread(fd _C_int, buf *byte, count Size_t, offset Offset_t) Ssize_t diff --git a/libgo/go/syscall/socket.go b/libgo/go/syscall/socket.go index 29c70559cce..f4dba36908e 100644 --- a/libgo/go/syscall/socket.go +++ b/libgo/go/syscall/socket.go @@ -25,7 +25,7 @@ type RawSockaddrAny struct { Pad [96]int8 } -const SizeofSockaddrAny = 0x1c +const SizeofSockaddrAny = 0x6c type SockaddrInet4 struct { Port int diff --git a/libgo/go/testing/testing.go b/libgo/go/testing/testing.go index 5019e076269..52dc166dd93 100644 --- a/libgo/go/testing/testing.go +++ b/libgo/go/testing/testing.go @@ -73,17 +73,19 @@ // // Example functions without output comments are compiled but not executed. // -// The naming convention to declare examples for a function F, a type T and +// The naming convention to declare examples for the package, a function F, a type T and // method M on type T are: // +// func Example() { ... } // func ExampleF() { ... } // func ExampleT() { ... } // func ExampleT_M() { ... } // -// Multiple example functions for a type/function/method may be provided by +// Multiple example functions for a package/type/function/method may be provided by // appending a distinct suffix to the name. The suffix must start with a // lower-case letter. // +// func Example_suffix() { ... } // func ExampleF_suffix() { ... } // func ExampleT_suffix() { ... } // func ExampleT_M_suffix() { ... } diff --git a/libgo/go/time/export_test.go b/libgo/go/time/export_test.go index dbd553af49d..6cd535f6b19 100644 --- a/libgo/go/time/export_test.go +++ b/libgo/go/time/export_test.go @@ -18,4 +18,7 @@ func ForceUSPacificForTesting() { localOnce.Do(initTestingZone) } -var ParseTimeZone = parseTimeZone +var ( + ForceZipFileForTesting = forceZipFileForTesting + ParseTimeZone = parseTimeZone +) diff --git a/libgo/go/time/time_test.go b/libgo/go/time/time_test.go index 22b751c5255..53ae97ea0af 100644 --- a/libgo/go/time/time_test.go +++ b/libgo/go/time/time_test.go @@ -578,6 +578,18 @@ func TestParseInSydney(t *testing.T) { } } +func TestLoadLocationZipFile(t *testing.T) { + t.Skip("gccgo does not use the zip file") + + ForceZipFileForTesting(true) + defer ForceZipFileForTesting(false) + + _, err := LoadLocation("Australia/Sydney") + if err != nil { + t.Fatal(err) + } +} + var rubyTests = []ParseTest{ {"RubyDate", RubyDate, "Thu Feb 04 21:00:57 -0800 2010", true, true, 1, 0}, // Ignore the time zone in the test. If it parses, it'll be OK. diff --git a/libgo/go/time/zoneinfo_plan9.go b/libgo/go/time/zoneinfo_plan9.go index 6855238dc84..0e8f3811bed 100644 --- a/libgo/go/time/zoneinfo_plan9.go +++ b/libgo/go/time/zoneinfo_plan9.go @@ -154,3 +154,7 @@ func loadLocation(name string) (*Location, error) { } return nil, errors.New("unknown time zone " + name) } + +func forceZipFileForTesting(zipOnly bool) { + // We only use the zip file anyway. +} diff --git a/libgo/go/time/zoneinfo_unix.go b/libgo/go/time/zoneinfo_unix.go index 72070253a78..1a4d115b932 100644 --- a/libgo/go/time/zoneinfo_unix.go +++ b/libgo/go/time/zoneinfo_unix.go @@ -28,7 +28,19 @@ var zoneDirs = []string{ "/usr/share/zoneinfo/", "/usr/share/lib/zoneinfo/", "/usr/lib/locale/TZ/", - runtime.GOROOT() + "/lib/time/zoneinfo/", + runtime.GOROOT() + "/lib/time/zoneinfo.zip", +} + +var origZoneDirs = zoneDirs + +func forceZipFileForTesting(zipOnly bool) { + zoneDirs = make([]string, len(origZoneDirs)) + copy(zoneDirs, origZoneDirs) + if zipOnly { + for i := 0; i < len(zoneDirs)-1; i++ { + zoneDirs[i] = "/XXXNOEXIST" + } + } } func initLocal() { diff --git a/libgo/go/time/zoneinfo_windows.go b/libgo/go/time/zoneinfo_windows.go index 1e18ad295df..be4e5c13ff0 100644 --- a/libgo/go/time/zoneinfo_windows.go +++ b/libgo/go/time/zoneinfo_windows.go @@ -264,3 +264,7 @@ func loadLocation(name string) (*Location, error) { } return nil, errors.New("unknown time zone " + name) } + +func forceZipFileForTesting(zipOnly bool) { + // We only use the zip file anyway. +} diff --git a/libgo/runtime/go-callers.c b/libgo/runtime/go-callers.c index 291dfd0d666..ae411d9c83a 100644 --- a/libgo/runtime/go-callers.c +++ b/libgo/runtime/go-callers.c @@ -11,6 +11,13 @@ #include "runtime.h" #include "array.h" +/* This is set to non-zero when calling backtrace_full. This is used + to avoid getting hanging on a recursive lock in dl_iterate_phdr on + older versions of glibc when a SIGPROF signal arrives while + collecting a backtrace. */ + +uint32 runtime_in_callers; + /* Argument passed to callback function. */ struct callers_data @@ -111,8 +118,10 @@ runtime_callers (int32 skip, Location *locbuf, int32 m) data.skip = skip + 1; data.index = 0; data.max = m; + runtime_xadd (&runtime_in_callers, 1); backtrace_full (__go_get_backtrace_state (), 0, callback, error_callback, &data); + runtime_xadd (&runtime_in_callers, -1); return data.index; } diff --git a/libgo/runtime/go-int-array-to-string.c b/libgo/runtime/go-int-array-to-string.c index d93fe651d95..f37213125a2 100644 --- a/libgo/runtime/go-int-array-to-string.c +++ b/libgo/runtime/go-int-array-to-string.c @@ -30,6 +30,8 @@ __go_int_array_to_string (const void* p, intgo len) if (v < 0 || v > 0x10ffff) v = 0xfffd; + else if (0xd800 <= v && v <= 0xdfff) + v = 0xfffd; if (v <= 0x7f) slen += 1; @@ -56,6 +58,8 @@ __go_int_array_to_string (const void* p, intgo len) character. */ if (v < 0 || v > 0x10ffff) v = 0xfffd; + else if (0xd800 <= v && v <= 0xdfff) + v = 0xfffd; if (v <= 0x7f) *s++ = v; diff --git a/libgo/runtime/go-signal.c b/libgo/runtime/go-signal.c index 4f0dcc78c17..1624122dace 100644 --- a/libgo/runtime/go-signal.c +++ b/libgo/runtime/go-signal.c @@ -218,7 +218,7 @@ runtime_sighandler (int sig, Siginfo *info, G *g; g = runtime_g (); - runtime_traceback (g); + runtime_traceback (); runtime_tracebackothers (g); /* The gc library calls runtime_dumpregs here, and provides @@ -252,7 +252,7 @@ sig_panic_leadin (int sig) /* The signal handler blocked signals; unblock them. */ i = sigfillset (&clear); __go_assert (i == 0); - i = sigprocmask (SIG_UNBLOCK, &clear, NULL); + i = pthread_sigmask (SIG_UNBLOCK, &clear, NULL); __go_assert (i == 0); } diff --git a/libgo/runtime/go-varargs.c b/libgo/runtime/go-varargs.c new file mode 100644 index 00000000000..682c08d64d4 --- /dev/null +++ b/libgo/runtime/go-varargs.c @@ -0,0 +1,47 @@ +/* go-varargs.c -- functions for calling C varargs functions. + + Copyright 2013 The Go Authors. All rights reserved. + Use of this source code is governed by a BSD-style + license that can be found in the LICENSE file. */ + +#include "config.h" + +#include <sys/types.h> +#include <fcntl.h> + +/* The syscall package calls C functions. The Go compiler can not + represent a C varargs functions. On some systems it's important + that the declaration of a function match the call. This function + holds non-varargs C functions that the Go code can call. */ + +int +__go_open (char *path, int mode, mode_t perm) +{ + return open (path, mode, perm); +} + +int +__go_fcntl (int fd, int cmd, int arg) +{ + return fcntl (fd, cmd, arg); +} + +#ifdef HAVE_OPEN64 + +int +__go_open64 (char *path, int mode, mode_t perm) +{ + return open64 (path, mode, perm); +} + +#endif + +#ifdef HAVE_OPENAT + +int +__go_openat (int fd, char *path, int flags, mode_t mode) +{ + return openat (fd, path, flags, mode); +} + +#endif diff --git a/libgo/runtime/proc.c b/libgo/runtime/proc.c index de2a54bfa5e..19afee3cd7a 100644 --- a/libgo/runtime/proc.c +++ b/libgo/runtime/proc.c @@ -208,9 +208,9 @@ runtime_newosproc(M *mp) #endif sigemptyset(&old); - sigprocmask(SIG_BLOCK, &clear, &old); + pthread_sigmask(SIG_BLOCK, &clear, &old); ret = pthread_create(&tid, &attr, runtime_mstart, mp); - sigprocmask(SIG_SETMASK, &old, nil); + pthread_sigmask(SIG_SETMASK, &old, nil); if (ret != 0) runtime_throw("pthread_create"); @@ -2454,6 +2454,15 @@ runtime_sigprof() return; } n = 0; + + if(runtime_atomicload(&runtime_in_callers) > 0) { + // If SIGPROF arrived while already fetching runtime + // callers we can have trouble on older systems + // because the unwind library calls dl_iterate_phdr + // which was not recursive in the past. + traceback = false; + } + if(traceback) { n = runtime_callers(0, prof.locbuf, nelem(prof.locbuf)); for(i = 0; i < n; i++) diff --git a/libgo/runtime/runtime.c b/libgo/runtime/runtime.c index 56fc045eac8..8fbc916fcfa 100644 --- a/libgo/runtime/runtime.c +++ b/libgo/runtime/runtime.c @@ -256,7 +256,7 @@ runtime_minit(void) runtime_signalstack(m->gsignalstack, m->gsignalstacksize); if (sigemptyset(&sigs) != 0) runtime_throw("sigemptyset"); - sigprocmask(SIG_SETMASK, &sigs, nil); + pthread_sigmask(SIG_SETMASK, &sigs, nil); } // Called from dropm to undo the effect of an minit. diff --git a/libgo/runtime/runtime.h b/libgo/runtime/runtime.h index e82e83231e6..da2416335ec 100644 --- a/libgo/runtime/runtime.h +++ b/libgo/runtime/runtime.h @@ -453,7 +453,7 @@ enum { }; void runtime_hashinit(void); -void runtime_traceback(); +void runtime_traceback(void); void runtime_tracebackothers(G*); /* @@ -776,6 +776,7 @@ extern struct backtrace_state *__go_get_backtrace_state(void); extern _Bool __go_file_line(uintptr, String*, String*, intgo *); extern byte* runtime_progname(); extern void runtime_main(void*); +extern uint32 runtime_in_callers; int32 getproccount(void); diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog index 5a0aba8f0b2..825ddd2d1fa 100644 --- a/libiberty/ChangeLog +++ b/libiberty/ChangeLog @@ -1,3 +1,26 @@ +2013-11-22 Cary Coutant <ccoutant@google.com> + + PR other/59195 + * cp-demangle.c (struct d_info_checkpoint): New struct. + (struct d_print_info): Add current_template field. + (d_operator_name): Set flag when processing a conversion + operator. + (cplus_demangle_type): When processing <template-args> for + a conversion operator, backtrack if necessary. + (d_expression_1): Renamed from d_expression. + (d_expression): New wrapper around d_expression_1. + (d_checkpoint): New function. + (d_backtrack): New function. + (d_print_init): Initialize current_template. + (d_print_comp): Set current_template. + (d_print_cast): Put current_template in scope for + printing conversion operator name. + (cplus_demangle_init_info): Initialize is_expression and + is_conversion. + * cp-demangle.h (struct d_info): Add is_expression and + is_conversion fields. + * testsuite/demangle-expected: New test cases. + 2013-11-15 Andreas Schwab <schwab@linux-m68k.org> * configure: Regenerate. diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c index cbe4d8c9f63..029151e320a 100644 --- a/libiberty/cp-demangle.c +++ b/libiberty/cp-demangle.c @@ -287,6 +287,19 @@ struct d_saved_scope struct d_print_template *templates; }; +/* Checkpoint structure to allow backtracking. This holds copies + of the fields of struct d_info that need to be restored + if a trial parse needs to be backtracked over. */ + +struct d_info_checkpoint +{ + const char *n; + int next_comp; + int next_sub; + int did_subs; + int expansion; +}; + enum { D_PRINT_BUFFER_LENGTH = 256 }; struct d_print_info { @@ -318,6 +331,8 @@ struct d_print_info struct d_saved_scope *saved_scopes; /* Number of saved scopes in the above array. */ int num_saved_scopes; + /* The nearest enclosing template, if any. */ + const struct demangle_component *current_template; }; #ifdef CP_DEMANGLE_DEBUG @@ -444,6 +459,10 @@ d_add_substitution (struct d_info *, struct demangle_component *); static struct demangle_component *d_substitution (struct d_info *, int); +static void d_checkpoint (struct d_info *, struct d_info_checkpoint *); + +static void d_backtrack (struct d_info *, struct d_info_checkpoint *); + static void d_growable_string_init (struct d_growable_string *, size_t); static inline void @@ -1734,8 +1753,15 @@ d_operator_name (struct d_info *di) if (c1 == 'v' && IS_DIGIT (c2)) return d_make_extended_operator (di, c2 - '0', d_source_name (di)); else if (c1 == 'c' && c2 == 'v') - return d_make_comp (di, DEMANGLE_COMPONENT_CAST, - cplus_demangle_type (di), NULL); + { + struct demangle_component *type; + int was_conversion = di->is_conversion; + + di->is_conversion = ! di->is_expression; + type = cplus_demangle_type (di); + di->is_conversion = was_conversion; + return d_make_comp (di, DEMANGLE_COMPONENT_CAST, type, NULL); + } else { /* LOW is the inclusive lower bound. */ @@ -2284,13 +2310,61 @@ cplus_demangle_type (struct d_info *di) ret = d_template_param (di); if (d_peek_char (di) == 'I') { - /* This is <template-template-param> <template-args>. The - <template-template-param> part is a substitution + /* This may be <template-template-param> <template-args>. + If this is the type for a conversion operator, we can + have a <template-template-param> here only by following + a derivation like this: + + <nested-name> + -> <template-prefix> <template-args> + -> <prefix> <template-unqualified-name> <template-args> + -> <unqualified-name> <template-unqualified-name> <template-args> + -> <source-name> <template-unqualified-name> <template-args> + -> <source-name> <operator-name> <template-args> + -> <source-name> cv <type> <template-args> + -> <source-name> cv <template-template-param> <template-args> <template-args> + + where the <template-args> is followed by another. + Otherwise, we must have a derivation like this: + + <nested-name> + -> <template-prefix> <template-args> + -> <prefix> <template-unqualified-name> <template-args> + -> <unqualified-name> <template-unqualified-name> <template-args> + -> <source-name> <template-unqualified-name> <template-args> + -> <source-name> <operator-name> <template-args> + -> <source-name> cv <type> <template-args> + -> <source-name> cv <template-param> <template-args> + + where we need to leave the <template-args> to be processed + by d_prefix (following the <template-prefix>). + + The <template-template-param> part is a substitution candidate. */ - if (! d_add_substitution (di, ret)) - return NULL; - ret = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, ret, - d_template_args (di)); + if (! di->is_conversion) + { + if (! d_add_substitution (di, ret)) + return NULL; + ret = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, ret, + d_template_args (di)); + } + else + { + struct demangle_component *args; + struct d_info_checkpoint checkpoint; + + d_checkpoint (di, &checkpoint); + args = d_template_args (di); + if (d_peek_char (di) == 'I') + { + if (! d_add_substitution (di, ret)) + return NULL; + ret = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, ret, + args); + } + else + d_backtrack (di, &checkpoint); + } } break; @@ -2976,8 +3050,8 @@ op_is_new_cast (struct demangle_component *op) ::= <expr-primary> */ -static struct demangle_component * -d_expression (struct d_info *di) +static inline struct demangle_component * +d_expression_1 (struct d_info *di) { char peek; @@ -3005,7 +3079,7 @@ d_expression (struct d_info *di) { d_advance (di, 2); return d_make_comp (di, DEMANGLE_COMPONENT_PACK_EXPANSION, - d_expression (di), NULL); + d_expression_1 (di), NULL); } else if (peek == 'f' && d_peek_next_char (di) == 'p') { @@ -3110,7 +3184,7 @@ d_expression (struct d_info *di) && d_check_char (di, '_')) operand = d_exprlist (di, 'E'); else - operand = d_expression (di); + operand = d_expression_1 (di); if (suffix) /* Indicate the suffix variant for d_print_comp. */ @@ -3130,7 +3204,7 @@ d_expression (struct d_info *di) if (op_is_new_cast (op)) left = cplus_demangle_type (di); else - left = d_expression (di); + left = d_expression_1 (di); if (!strcmp (code, "cl")) right = d_exprlist (di, 'E'); else if (!strcmp (code, "dt") || !strcmp (code, "pt")) @@ -3141,7 +3215,7 @@ d_expression (struct d_info *di) right, d_template_args (di)); } else - right = d_expression (di); + right = d_expression_1 (di); return d_make_comp (di, DEMANGLE_COMPONENT_BINARY, op, d_make_comp (di, @@ -3157,9 +3231,9 @@ d_expression (struct d_info *di) if (!strcmp (code, "qu")) { /* ?: expression. */ - first = d_expression (di); - second = d_expression (di); - third = d_expression (di); + first = d_expression_1 (di); + second = d_expression_1 (di); + third = d_expression_1 (di); } else if (code[0] == 'n') { @@ -3183,7 +3257,7 @@ d_expression (struct d_info *di) else if (d_peek_char (di) == 'i' && d_peek_next_char (di) == 'l') /* initializer-list. */ - third = d_expression (di); + third = d_expression_1 (di); else return NULL; } @@ -3203,6 +3277,18 @@ d_expression (struct d_info *di) } } +static struct demangle_component * +d_expression (struct d_info *di) +{ + struct demangle_component *ret; + int was_expression = di->is_expression; + + di->is_expression = 1; + ret = d_expression_1 (di); + di->is_expression = was_expression; + return ret; +} + /* <expr-primary> ::= L <type> <(value) number> E ::= L <type> <(value) float> E ::= L <mangled-name> E @@ -3588,6 +3674,26 @@ d_substitution (struct d_info *di, int prefix) } } +static void +d_checkpoint (struct d_info *di, struct d_info_checkpoint *checkpoint) +{ + checkpoint->n = di->n; + checkpoint->next_comp = di->next_comp; + checkpoint->next_sub = di->next_sub; + checkpoint->did_subs = di->did_subs; + checkpoint->expansion = di->expansion; +} + +static void +d_backtrack (struct d_info *di, struct d_info_checkpoint *checkpoint) +{ + di->n = checkpoint->n; + di->next_comp = checkpoint->next_comp; + di->next_sub = checkpoint->next_sub; + di->did_subs = checkpoint->did_subs; + di->expansion = checkpoint->expansion; +} + /* Initialize a growable string. */ static void @@ -3684,6 +3790,7 @@ d_print_init (struct d_print_info *dpi, demangle_callbackref callback, dpi->saved_scopes = NULL; dpi->num_saved_scopes = 0; + dpi->current_template = NULL; } /* Free a print information structure. */ @@ -4165,6 +4272,12 @@ d_print_comp (struct d_print_info *dpi, int options, { struct d_print_mod *hold_dpm; struct demangle_component *dcl; + const struct demangle_component *hold_current; + + /* This template may need to be referenced by a cast operator + contained in its subtree. */ + hold_current = dpi->current_template; + dpi->current_template = dc; /* Don't push modifiers into a template definition. Doing so could give the wrong definition for a template argument. @@ -4201,6 +4314,7 @@ d_print_comp (struct d_print_info *dpi, int options, } dpi->modifiers = hold_dpm; + dpi->current_template = hold_current; return; } @@ -5418,28 +5532,32 @@ static void d_print_cast (struct d_print_info *dpi, int options, const struct demangle_component *dc) { - if (d_left (dc)->type != DEMANGLE_COMPONENT_TEMPLATE) - d_print_comp (dpi, options, d_left (dc)); - else - { - struct d_print_mod *hold_dpm; - struct d_print_template dpt; - - /* It appears that for a templated cast operator, we need to put - the template parameters in scope for the operator name, but - not for the parameters. The effect is that we need to handle - the template printing here. */ - - hold_dpm = dpi->modifiers; - dpi->modifiers = NULL; + struct d_print_template dpt; + /* For a cast operator, we need the template parameters from + the enclosing template in scope for processing the type. */ + if (dpi->current_template != NULL) + { dpt.next = dpi->templates; dpi->templates = &dpt; - dpt.template_decl = d_left (dc); + dpt.template_decl = dpi->current_template; + } + if (d_left (dc)->type != DEMANGLE_COMPONENT_TEMPLATE) + { + d_print_comp (dpi, options, d_left (dc)); + if (dpi->current_template != NULL) + dpi->templates = dpt.next; + } + else + { d_print_comp (dpi, options, d_left (d_left (dc))); - dpi->templates = dpt.next; + /* For a templated cast operator, we need to remove the template + parameters from scope after printing the operator name, + so we need to handle the template printing here. */ + if (dpi->current_template != NULL) + dpi->templates = dpt.next; if (d_last_char (dpi) == '<') d_append_char (dpi, ' '); @@ -5450,8 +5568,6 @@ d_print_cast (struct d_print_info *dpi, int options, if (d_last_char (dpi) == '>') d_append_char (dpi, ' '); d_append_char (dpi, '>'); - - dpi->modifiers = hold_dpm; } } @@ -5484,6 +5600,8 @@ cplus_demangle_init_info (const char *mangled, int options, size_t len, di->last_name = NULL; di->expansion = 0; + di->is_expression = 0; + di->is_conversion = 0; } /* Internal implementation for the demangler. If MANGLED is a g++ v3 ABI diff --git a/libiberty/cp-demangle.h b/libiberty/cp-demangle.h index ae635beb4cc..6fce0252dc4 100644 --- a/libiberty/cp-demangle.h +++ b/libiberty/cp-demangle.h @@ -122,6 +122,11 @@ struct d_info mangled name to the demangled name, such as standard substitutions and builtin types. */ int expansion; + /* Non-zero if we are parsing an expression. */ + int is_expression; + /* Non-zero if we are parsing the type operand of a conversion + operator, but not when in an expression. */ + int is_conversion; }; /* To avoid running past the ending '\0', don't: diff --git a/libiberty/testsuite/demangle-expected b/libiberty/testsuite/demangle-expected index ae872078d91..3ff08e6e5f2 100644 --- a/libiberty/testsuite/demangle-expected +++ b/libiberty/testsuite/demangle-expected @@ -4297,3 +4297,23 @@ void f<int>() --format=gnu-v3 _ZSt7forwardIRN1x14refobjiteratorINS0_3refINS0_4mime30multipart_section_processorObjIZ15get_body_parserIZZN14mime_processor21make_section_iteratorERKNS2_INS3_10sectionObjENS0_10ptrrefBaseEEEbENKUlvE_clEvEUlSB_bE_ZZNS6_21make_section_iteratorESB_bENKSC_clEvEUlSB_E0_ENS1_INS2_INS0_20outputrefiteratorObjIiEES8_EEEERKSsSB_OT_OT0_EUlmE_NS3_32make_multipart_default_discarderISP_EEEES8_EEEEEOT_RNSt16remove_referenceISW_E4typeE x::refobjiterator<x::ref<x::mime::multipart_section_processorObj<x::refobjiterator<x::ref<x::outputrefiteratorObj<int>, x::ptrrefBase> > get_body_parser<mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)#1}, mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&)#2}>(std::string const&, x::ref<x::mime::sectionObj, x::ptrrefBase> const&, mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)#1}&&, mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&)#2}&&)::{lambda(unsigned long)#1}, x::mime::make_multipart_default_discarder<mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)#1}&&> >, x::ptrrefBase> >& std::forward<x::refobjiterator<x::ref<x::mime::multipart_section_processorObj<x::refobjiterator<x::ref<x::outputrefiteratorObj<int>, x::ptrrefBase> > get_body_parser<mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)#1}, mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&)#2}>(std::string const&, x::ref<x::mime::sectionObj, x::ptrrefBase> const&, mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)#1}&&, mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&)#2}&&)::{lambda(unsigned long)#1}, x::mime::make_multipart_default_discarder<mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)#1}&&> >, x::ptrrefBase> >&>(std::remove_reference<x::mime::multipart_section_processorObj<x::refobjiterator<x::ref<x::outputrefiteratorObj<int>, x::ptrrefBase> > get_body_parser<mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)#1}, mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&)#2}>(std::string const&, x::ref<x::mime::sectionObj, x::ptrrefBase> const&, mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)#1}&&, mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&)#2}&&)::{lambda(unsigned long)#1}, x::mime::make_multipart_default_discarder<mime_processor::make_section_iterator(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)::{lambda()#1}::operator()() const::{lambda(x::ref<x::mime::sectionObj, x::ptrrefBase> const&, bool)#1}&&> > >::type&) +# +--format=gnu-v3 --no-params +_ZNK7strings8internal8SplitterINS_9delimiter5AnyOfENS_9SkipEmptyEEcvT_ISt6vectorI12basic_stringIcSt11char_traitsIcESaIcEESaISD_EEvEEv +strings::internal::Splitter<strings::delimiter::AnyOf, strings::SkipEmpty>::operator std::vector<basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<basic_string<char, std::char_traits<char>, std::allocator<char> > > ><std::vector<basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<basic_string<char, std::char_traits<char>, std::allocator<char> > > >, void>() const +strings::internal::Splitter<strings::delimiter::AnyOf, strings::SkipEmpty>::operator std::vector<basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<basic_string<char, std::char_traits<char>, std::allocator<char> > > ><std::vector<basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<basic_string<char, std::char_traits<char>, std::allocator<char> > > >, void> +# +--format=gnu-v3 --no-params +_ZN1AcvT_I1CEEv +A::operator C<C>() +A::operator C<C> +# +--format=gnu-v3 --no-params +_ZN1AcvPT_I1CEEv +A::operator C*<C>() +A::operator C*<C> +# +--format=gnu-v3 --no-params +_ZN1AcvT_IiEI1CEEv +A::operator C<int><C>() +A::operator C<int><C> diff --git a/libjava/classpath/ChangeLog.gcj b/libjava/classpath/ChangeLog.gcj index 63955543ca8..62e985b9734 100644 --- a/libjava/classpath/ChangeLog.gcj +++ b/libjava/classpath/ChangeLog.gcj @@ -1,3 +1,9 @@ +2013-11-29 Matthias Klose <doko@ubuntu.com> + + * native/jni/gtk-peer/gnu_java_awt_peer_gtk_FreetypeGlyphVector.c, + native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkFontPeer.c: + Fix freetype includes. + 2013-04-16 Andreas Schwab <schwab@suse.de> * native/fdlibm/ieeefp.h: Add support for aarch64. diff --git a/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_FreetypeGlyphVector.c b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_FreetypeGlyphVector.c index cb7bf43dcb4..e74678ef6cd 100644 --- a/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_FreetypeGlyphVector.c +++ b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_FreetypeGlyphVector.c @@ -42,8 +42,9 @@ exception statement from your version. */ #include <pango/pango.h> #include <pango/pangoft2.h> #include <pango/pangofc-font.h> -#include <freetype/ftglyph.h> -#include <freetype/ftoutln.h> +#include <ft2build.h> +#include FT_GLYPH_H +#include FT_OUTLINE_H #include "jcl.h" #include "gdkfont.h" #include "gnu_java_awt_peer_gtk_FreetypeGlyphVector.h" diff --git a/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkFontPeer.c b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkFontPeer.c index 771b23e3738..cfd988c4a52 100644 --- a/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkFontPeer.c +++ b/libjava/classpath/native/jni/gtk-peer/gnu_java_awt_peer_gtk_GdkFontPeer.c @@ -39,10 +39,11 @@ #include <pango/pango.h> #include <pango/pangoft2.h> #include <pango/pangofc-font.h> -#include <freetype/ftglyph.h> -#include <freetype/ftoutln.h> -#include <freetype/fttypes.h> -#include <freetype/tttables.h> +#include <ft2build.h> +#include FT_GLYPH_H +#include FT_OUTLINE_H +#include FT_TYPES_H +#include FT_TRUETYPE_TABLES_H #include "gdkfont.h" #include "gtkpeer.h" #include "gnu_java_awt_peer_gtk_GdkFontPeer.h" diff --git a/libquadmath/ChangeLog b/libquadmath/ChangeLog index d3c17f67d5d..804a3d54551 100644 --- a/libquadmath/ChangeLog +++ b/libquadmath/ChangeLog @@ -1,3 +1,9 @@ +2013-12-04 Richard Sandiford <rdsandiford@googlemail.com> + + * Makefile.am (AM_CPPFLAGS): Define. + * Makefile.in: Regenerate. + * printf/gmp-impl.h: Remove path from longlong.h include. + 2013-09-20 Alan Modra <amodra@gmail.com> * configure: Regenerate. diff --git a/libquadmath/Makefile.am b/libquadmath/Makefile.am index 6c97ee81c5c..6519731b9b9 100644 --- a/libquadmath/Makefile.am +++ b/libquadmath/Makefile.am @@ -6,6 +6,7 @@ AUTOMAKE_OPTIONS = 1.8 foreign ## Skip over everything if the quadlib is not available: if BUILD_LIBQUADMATH ACLOCAL_AMFLAGS = -I .. -I ../config +AM_CPPFLAGS = -I $(top_srcdir)/../include ## May be used by toolexeclibdir. gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER) diff --git a/libquadmath/Makefile.in b/libquadmath/Makefile.in index 92c5d256d5a..331780931af 100644 --- a/libquadmath/Makefile.in +++ b/libquadmath/Makefile.in @@ -310,6 +310,7 @@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AUTOMAKE_OPTIONS = 1.8 foreign @BUILD_LIBQUADMATH_TRUE@ACLOCAL_AMFLAGS = -I .. -I ../config +@BUILD_LIBQUADMATH_TRUE@AM_CPPFLAGS = -I $(top_srcdir)/../include @BUILD_LIBQUADMATH_TRUE@gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER) @BUILD_LIBQUADMATH_TRUE@@LIBQUAD_USE_SYMVER_FALSE@version_arg = @BUILD_LIBQUADMATH_TRUE@@LIBQUAD_USE_SYMVER_GNU_TRUE@@LIBQUAD_USE_SYMVER_TRUE@version_arg = -Wl,--version-script=$(srcdir)/quadmath.map diff --git a/libquadmath/printf/gmp-impl.h b/libquadmath/printf/gmp-impl.h index 0f1419277de..969574c853a 100644 --- a/libquadmath/printf/gmp-impl.h +++ b/libquadmath/printf/gmp-impl.h @@ -60,7 +60,7 @@ typedef unsigned int UHWtype; #define attribute_hidden #endif -#include "../../libgcc/longlong.h" +#include "longlong.h" /* Copy NLIMBS *limbs* from SRC to DST. */ #define MPN_COPY_INCR(DST, SRC, NLIMBS) \ diff --git a/libsanitizer/ChangeLog b/libsanitizer/ChangeLog index 9afe7970a28..8404d51a053 100644 --- a/libsanitizer/ChangeLog +++ b/libsanitizer/ChangeLog @@ -1,3 +1,47 @@ +2013-11-29 Jakub Jelinek <jakub@redhat.com> + Yury Gribov <y.gribov@samsung.com> + + PR sanitizer/59063 + * libsanitizer.spec.in: Add spec file to hold link flags for + various sanitizer libs. + * configure.ac: Check whether clock_* routines come from librt. + * asan/Makefile.am (libasan_la_LDFLAGS): Libs now come from + configure.ac. + * tsan/Makefile.am (libtsan_la_LDFLAGS): Likewise. + * ubsan/Makefile.am (libubsan_la_LDFLAGS): Likewise. + * lsan/Makefile.am (liblsan_la_LDFLAGS): Likewise. + * asan/Makefile.in: Regenerate. + * interception/Makefile.in: Regenerate. + * lsan/Makefile.in: Regenerate. + * sanitizer_common/Makefile.in: Regenerate. + * tsan/Makefile.in: Regenerate. + * ubsan/Makefile.in: Regenerate. + * Makefile.in: Regenerate. + * configure: Regenerate. + +2013-11-28 Jakub Jelinek <jakub@redhat.com> + Yury Gribov <y.gribov@samsung.com> + + PR sanitizer/59106 + * ubsan/Makefile.am (AM_CXXFLAGS): Disable -frtti for files that + don't need it. + * ubsan/Makefile.in: Regenerated. + +2013-11-22 Jakub Jelinek <jakub@redhat.com> + + PR sanitizer/59061 + * configure.tgt: Set LSAN_SUPPORTED=yes for x86_64-linux. + * configure.ac (LSAN_SUPPORTED): New AM_CONDITIONAL. + * configure: Regenerated. + * lsan/Makefile.am (toolexeclib_LTLIBRARIES, lsan_files, + liblsan_la_SOURCES, liblsan_la_LIBADD, liblsan_la_LDFLAGS): Add. + * lsan/Makefile.in: Regenerated. + +2013-11-22 Mike Stump <mikestump@comcast.net> + + * sanitizer_common/sanitizer_linux.cc (__sanitizer): Grab one + change from upstream to fix build. + 2013-11-18 Yury Gribov <y.gribov@samsung.com> PR sanitizer/59106 diff --git a/libsanitizer/Makefile.am b/libsanitizer/Makefile.am index 15c11ecb2d7..6c3e5b053a2 100644 --- a/libsanitizer/Makefile.am +++ b/libsanitizer/Makefile.am @@ -50,5 +50,7 @@ AM_MAKEFLAGS = \ MAKEOVERRIDES= +nodist_toolexeclib_HEADERS = libsanitizer.spec + ## ################################################################ diff --git a/libsanitizer/Makefile.in b/libsanitizer/Makefile.in index 47a8771c783..9424c59fe37 100644 --- a/libsanitizer/Makefile.in +++ b/libsanitizer/Makefile.in @@ -14,6 +14,7 @@ # PARTICULAR PURPOSE. @SET_MAKE@ + VPATH = @srcdir@ pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ @@ -37,7 +38,7 @@ target_triplet = @target@ subdir = . DIST_COMMON = ChangeLog $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/configure $(am__configure_deps) \ - $(srcdir)/../mkinstalldirs + $(srcdir)/../mkinstalldirs $(srcdir)/libsanitizer.spec.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/../config/acx.m4 \ $(top_srcdir)/../config/depstand.m4 \ @@ -54,7 +55,7 @@ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs -CONFIG_CLEAN_FILES = +CONFIG_CLEAN_FILES = libsanitizer.spec CONFIG_CLEAN_VPATH_FILES = SOURCES = MULTISRCTOP = @@ -70,6 +71,29 @@ RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ install-pdf-recursive install-ps-recursive install-recursive \ installcheck-recursive installdirs-recursive pdf-recursive \ ps-recursive uninstall-recursive +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__installdirs = "$(DESTDIR)$(toolexeclibdir)" +HEADERS = $(nodist_toolexeclib_HEADERS) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \ @@ -183,6 +207,10 @@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ +link_libasan = @link_libasan@ +link_liblsan = @link_liblsan@ +link_libtsan = @link_libtsan@ +link_libubsan = @link_libubsan@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ @@ -252,6 +280,7 @@ AM_MAKEFLAGS = \ "DESTDIR=$(DESTDIR)" MAKEOVERRIDES = +nodist_toolexeclib_HEADERS = libsanitizer.spec all: all-recursive .SUFFIXES: @@ -289,6 +318,8 @@ $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) $(am__aclocal_m4_deps): +libsanitizer.spec: $(top_builddir)/config.status $(srcdir)/libsanitizer.spec.in + cd $(top_builddir) && $(SHELL) ./config.status $@ mostlyclean-libtool: -rm -f *.lo @@ -315,6 +346,26 @@ distclean-multi: $(MULTICLEAN) $(AM_MAKEFLAGS) DO=distclean multi-clean # $(MAKE) maintainer-clean-multi: $(MULTICLEAN) $(AM_MAKEFLAGS) DO=maintainer-clean multi-clean # $(MAKE) +install-nodist_toolexeclibHEADERS: $(nodist_toolexeclib_HEADERS) + @$(NORMAL_INSTALL) + test -z "$(toolexeclibdir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibdir)" + @list='$(nodist_toolexeclib_HEADERS)'; test -n "$(toolexeclibdir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(toolexeclibdir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(toolexeclibdir)" || exit $$?; \ + done + +uninstall-nodist_toolexeclibHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(nodist_toolexeclib_HEADERS)'; test -n "$(toolexeclibdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(toolexeclibdir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(toolexeclibdir)" && rm -f $$files # This directory's subdirectories are mostly independent; you can cd # into them and run `make' without going through this Makefile. @@ -452,9 +503,12 @@ distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags check-am: all-am check: check-recursive -all-am: Makefile all-multi +all-am: Makefile all-multi $(HEADERS) installdirs: installdirs-recursive installdirs-am: + for dir in "$(DESTDIR)$(toolexeclibdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done install: install-recursive install-exec: install-exec-recursive install-data: install-data-recursive @@ -508,7 +562,7 @@ install-dvi: install-dvi-recursive install-dvi-am: -install-exec-am: install-multi +install-exec-am: install-multi install-nodist_toolexeclibHEADERS install-html: install-html-recursive @@ -548,7 +602,7 @@ ps: ps-recursive ps-am: -uninstall-am: +uninstall-am: uninstall-nodist_toolexeclibHEADERS .MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) all-multi \ clean-multi ctags-recursive distclean-multi install-am \ @@ -563,12 +617,14 @@ uninstall-am: install-am install-data install-data-am install-dvi \ install-dvi-am install-exec install-exec-am install-html \ install-html-am install-info install-info-am install-man \ - install-multi install-pdf install-pdf-am install-ps \ - install-ps-am install-strip installcheck installcheck-am \ - installdirs installdirs-am maintainer-clean \ - maintainer-clean-generic maintainer-clean-multi mostlyclean \ - mostlyclean-generic mostlyclean-libtool mostlyclean-multi pdf \ - pdf-am ps ps-am tags tags-recursive uninstall uninstall-am + install-multi install-nodist_toolexeclibHEADERS install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs installdirs-am \ + maintainer-clean maintainer-clean-generic \ + maintainer-clean-multi mostlyclean mostlyclean-generic \ + mostlyclean-libtool mostlyclean-multi pdf pdf-am ps ps-am tags \ + tags-recursive uninstall uninstall-am \ + uninstall-nodist_toolexeclibHEADERS # Tell versions [3.59,3.63) of GNU make to not export all variables. diff --git a/libsanitizer/asan/Makefile.am b/libsanitizer/asan/Makefile.am index 0e1ee111a79..58defae04b7 100644 --- a/libsanitizer/asan/Makefile.am +++ b/libsanitizer/asan/Makefile.am @@ -43,7 +43,7 @@ libasan_la_LIBADD = $(top_builddir)/sanitizer_common/libsanitizer_common.la $(to endif libasan_la_LIBADD += $(LIBSTDCXX_RAW_CXX_LDFLAGS) -libasan_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version` -lpthread -ldl +libasan_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version` $(link_libasan) libasan_preinit.o: asan_preinit.o cp $< $@ diff --git a/libsanitizer/asan/Makefile.in b/libsanitizer/asan/Makefile.in index c6044744e1d..e86d7b5b34b 100644 --- a/libsanitizer/asan/Makefile.in +++ b/libsanitizer/asan/Makefile.in @@ -224,6 +224,10 @@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ +link_libasan = @link_libasan@ +link_liblsan = @link_liblsan@ +link_libtsan = @link_libtsan@ +link_libubsan = @link_libubsan@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ @@ -289,7 +293,7 @@ libasan_la_SOURCES = $(asan_files) @USING_MAC_INTERPOSE_TRUE@libasan_la_LIBADD = $(top_builddir)/sanitizer_common/libsanitizer_common.la \ @USING_MAC_INTERPOSE_TRUE@ $(top_builddir)/lsan/libsanitizer_lsan.la \ @USING_MAC_INTERPOSE_TRUE@ $(LIBSTDCXX_RAW_CXX_LDFLAGS) -libasan_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version` -lpthread -ldl +libasan_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version` $(link_libasan) # Work around what appears to be a GNU make bug handling MAKEFLAGS # values defined in terms of make variables, as is the case for CC and diff --git a/libsanitizer/configure b/libsanitizer/configure index 5e425d1d9e3..e5c320604d3 100755 --- a/libsanitizer/configure +++ b/libsanitizer/configure @@ -606,6 +606,12 @@ LTLIBOBJS LIBOBJS USING_MAC_INTERPOSE_FALSE USING_MAC_INTERPOSE_TRUE +link_liblsan +link_libubsan +link_libtsan +link_libasan +LSAN_SUPPORTED_FALSE +LSAN_SUPPORTED_TRUE TSAN_SUPPORTED_FALSE TSAN_SUPPORTED_TRUE enable_static @@ -11117,7 +11123,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11120 "configure" +#line 11126 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -11223,7 +11229,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11226 "configure" +#line 11232 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -14523,6 +14529,7 @@ fi # Get target configury. unset TSAN_SUPPORTED +unset LSAN_SUPPORTED . ${srcdir}/configure.tgt if test "x$TSAN_SUPPORTED" = "xyes"; then TSAN_SUPPORTED_TRUE= @@ -14532,6 +14539,97 @@ else TSAN_SUPPORTED_FALSE= fi + if test "x$LSAN_SUPPORTED" = "xyes"; then + LSAN_SUPPORTED_TRUE= + LSAN_SUPPORTED_FALSE='#' +else + LSAN_SUPPORTED_TRUE='#' + LSAN_SUPPORTED_FALSE= +fi + + +# Check for functions needed. +for ac_func in clock_getres clock_gettime clock_settime +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +eval as_val=\$$as_ac_var + if test "x$as_val" = x""yes; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + +# Common libraries that we need to link against for all sanitizer libs. +link_sanitizer_common='-lpthread -ldl' + +# Set up the set of additional libraries that we need to link against for libasan. +link_libasan=$link_sanitizer_common + + +# Set up the set of additional libraries that we need to link against for libtsan. +link_libtsan=$link_sanitizer_common + + +# Set up the set of additional libraries that we need to link against for libubsan. +link_libubsan=$link_sanitizer_common + + +# Set up the set of additional libraries that we need to link against for liblsan. +link_liblsan=$link_sanitizer_common + + +# At least for glibc, clock_gettime is in librt. But don't pull that +# in if it still doesn't give us the function we want. This +# test is copied from libgomp. +if test $ac_cv_func_clock_gettime = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5 +$as_echo_n "checking for clock_gettime in -lrt... " >&6; } +if test "${ac_cv_lib_rt_clock_gettime+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lrt $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char clock_gettime (); +int +main () +{ +return clock_gettime (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_rt_clock_gettime=yes +else + ac_cv_lib_rt_clock_gettime=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_gettime" >&5 +$as_echo "$ac_cv_lib_rt_clock_gettime" >&6; } +if test "x$ac_cv_lib_rt_clock_gettime" = x""yes; then : + link_libasan="-lrt $link_libasan" +link_libtsan="-lrt $link_libtsan" +# Other sanitizers do not override clock_* API + +fi + +fi case "$host" in *-*-darwin*) MAC_INTERPOSE=true ; enable_static=no ;; @@ -14546,7 +14644,7 @@ else fi -ac_config_files="$ac_config_files Makefile" +ac_config_files="$ac_config_files Makefile libsanitizer.spec" ac_config_files="$ac_config_files interception/Makefile sanitizer_common/Makefile lsan/Makefile asan/Makefile ubsan/Makefile" @@ -14722,6 +14820,10 @@ if test -z "${TSAN_SUPPORTED_TRUE}" && test -z "${TSAN_SUPPORTED_FALSE}"; then as_fn_error "conditional \"TSAN_SUPPORTED\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${LSAN_SUPPORTED_TRUE}" && test -z "${LSAN_SUPPORTED_FALSE}"; then + as_fn_error "conditional \"LSAN_SUPPORTED\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${USING_MAC_INTERPOSE_TRUE}" && test -z "${USING_MAC_INTERPOSE_FALSE}"; then as_fn_error "conditional \"USING_MAC_INTERPOSE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 @@ -15677,6 +15779,7 @@ do "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "libsanitizer.spec") CONFIG_FILES="$CONFIG_FILES libsanitizer.spec" ;; "interception/Makefile") CONFIG_FILES="$CONFIG_FILES interception/Makefile" ;; "sanitizer_common/Makefile") CONFIG_FILES="$CONFIG_FILES sanitizer_common/Makefile" ;; "lsan/Makefile") CONFIG_FILES="$CONFIG_FILES lsan/Makefile" ;; diff --git a/libsanitizer/configure.ac b/libsanitizer/configure.ac index 0b2d8132fb6..7f9327904da 100644 --- a/libsanitizer/configure.ac +++ b/libsanitizer/configure.ac @@ -78,8 +78,43 @@ fi # Get target configury. unset TSAN_SUPPORTED +unset LSAN_SUPPORTED . ${srcdir}/configure.tgt AM_CONDITIONAL(TSAN_SUPPORTED, [test "x$TSAN_SUPPORTED" = "xyes"]) +AM_CONDITIONAL(LSAN_SUPPORTED, [test "x$LSAN_SUPPORTED" = "xyes"]) + +# Check for functions needed. +AC_CHECK_FUNCS(clock_getres clock_gettime clock_settime) + +# Common libraries that we need to link against for all sanitizer libs. +link_sanitizer_common='-lpthread -ldl' + +# Set up the set of additional libraries that we need to link against for libasan. +link_libasan=$link_sanitizer_common +AC_SUBST(link_libasan) + +# Set up the set of additional libraries that we need to link against for libtsan. +link_libtsan=$link_sanitizer_common +AC_SUBST(link_libtsan) + +# Set up the set of additional libraries that we need to link against for libubsan. +link_libubsan=$link_sanitizer_common +AC_SUBST(link_libubsan) + +# Set up the set of additional libraries that we need to link against for liblsan. +link_liblsan=$link_sanitizer_common +AC_SUBST(link_liblsan) + +# At least for glibc, clock_gettime is in librt. But don't pull that +# in if it still doesn't give us the function we want. This +# test is copied from libgomp. +if test $ac_cv_func_clock_gettime = no; then + AC_CHECK_LIB(rt, clock_gettime, + [link_libasan="-lrt $link_libasan" +link_libtsan="-lrt $link_libtsan" +# Other sanitizers do not override clock_* API +]) +fi case "$host" in *-*-darwin*) MAC_INTERPOSE=true ; enable_static=no ;; @@ -87,7 +122,7 @@ case "$host" in esac AM_CONDITIONAL(USING_MAC_INTERPOSE, $MAC_INTERPOSE) -AC_CONFIG_FILES([Makefile]) +AC_CONFIG_FILES([Makefile libsanitizer.spec]) AC_CONFIG_FILES(AC_FOREACH([DIR], [interception sanitizer_common lsan asan ubsan], [DIR/Makefile ]), [cat > vpsed$$ << \_EOF diff --git a/libsanitizer/configure.tgt b/libsanitizer/configure.tgt index bdfc22e3718..b17ed73258d 100644 --- a/libsanitizer/configure.tgt +++ b/libsanitizer/configure.tgt @@ -23,6 +23,7 @@ case "${target}" in x86_64-*-linux* | i?86-*-linux*) if test x$ac_cv_sizeof_void_p = x8; then TSAN_SUPPORTED=yes + LSAN_SUPPORTED=yes fi ;; powerpc*-*-linux*) diff --git a/libsanitizer/interception/Makefile.in b/libsanitizer/interception/Makefile.in index f3a2f41c033..52a06d63458 100644 --- a/libsanitizer/interception/Makefile.in +++ b/libsanitizer/interception/Makefile.in @@ -181,6 +181,10 @@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ +link_libasan = @link_libasan@ +link_liblsan = @link_liblsan@ +link_libtsan = @link_libtsan@ +link_libubsan = @link_libubsan@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ diff --git a/libsanitizer/libsanitizer.spec.in b/libsanitizer/libsanitizer.spec.in new file mode 100644 index 00000000000..a4fa87d8dfc --- /dev/null +++ b/libsanitizer/libsanitizer.spec.in @@ -0,0 +1,11 @@ +# This spec file is read by gcc when linking. It is used to specify the +# standard libraries we need in order to link with various sanitizer libs. + +*link_libasan: @link_libasan@ + +*link_libtsan: @link_libtsan@ + +*link_libubsan: @link_libubsan@ + +*link_liblsan: @link_liblsan@ + diff --git a/libsanitizer/lsan/Makefile.am b/libsanitizer/lsan/Makefile.am index 3d500f3240c..36fd6058841 100644 --- a/libsanitizer/lsan/Makefile.am +++ b/libsanitizer/lsan/Makefile.am @@ -9,13 +9,27 @@ AM_CXXFLAGS += $(LIBSTDCXX_RAW_CXX_CXXFLAGS) ACLOCAL_AMFLAGS = -I m4 noinst_LTLIBRARIES = libsanitizer_lsan.la +if LSAN_SUPPORTED +toolexeclib_LTLIBRARIES = liblsan.la +endif sanitizer_lsan_files = \ lsan_common.cc \ lsan_common_linux.cc +lsan_files = \ + $(sanitizer_lsan_files) \ + lsan.cc \ + lsan_allocator.cc \ + lsan_interceptors.cc \ + lsan_thread.cc + libsanitizer_lsan_la_SOURCES = $(sanitizer_lsan_files) +liblsan_la_SOURCES = $(lsan_files) +liblsan_la_LIBADD = $(top_builddir)/sanitizer_common/libsanitizer_common.la $(top_builddir)/interception/libinterception.la $(LIBSTDCXX_RAW_CXX_LDFLAGS) +liblsan_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version` $(link_liblsan) + # Work around what appears to be a GNU make bug handling MAKEFLAGS # values defined in terms of make variables, as is the case for CC and # friends when we are called from the top level Makefile. diff --git a/libsanitizer/lsan/Makefile.in b/libsanitizer/lsan/Makefile.in index c5c07e71eb7..9296b7048ab 100644 --- a/libsanitizer/lsan/Makefile.in +++ b/libsanitizer/lsan/Makefile.in @@ -53,9 +53,44 @@ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = -LTLIBRARIES = $(noinst_LTLIBRARIES) -libsanitizer_lsan_la_LIBADD = +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__installdirs = "$(DESTDIR)$(toolexeclibdir)" +LTLIBRARIES = $(noinst_LTLIBRARIES) $(toolexeclib_LTLIBRARIES) +am__DEPENDENCIES_1 = +liblsan_la_DEPENDENCIES = \ + $(top_builddir)/sanitizer_common/libsanitizer_common.la \ + $(top_builddir)/interception/libinterception.la \ + $(am__DEPENDENCIES_1) am__objects_1 = lsan_common.lo lsan_common_linux.lo +am__objects_2 = $(am__objects_1) lsan.lo lsan_allocator.lo \ + lsan_interceptors.lo lsan_thread.lo +am_liblsan_la_OBJECTS = $(am__objects_2) +liblsan_la_OBJECTS = $(am_liblsan_la_OBJECTS) +liblsan_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ + $(CXXFLAGS) $(liblsan_la_LDFLAGS) $(LDFLAGS) -o $@ +@LSAN_SUPPORTED_TRUE@am_liblsan_la_rpath = -rpath $(toolexeclibdir) +libsanitizer_lsan_la_LIBADD = am_libsanitizer_lsan_la_OBJECTS = $(am__objects_1) libsanitizer_lsan_la_OBJECTS = $(am_libsanitizer_lsan_la_OBJECTS) DEFAULT_INCLUDES = -I.@am__isrc@ @@ -71,7 +106,7 @@ CXXLD = $(CXX) CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ -SOURCES = $(libsanitizer_lsan_la_SOURCES) +SOURCES = $(liblsan_la_SOURCES) $(libsanitizer_lsan_la_SOURCES) ETAGS = etags CTAGS = ctags ACLOCAL = @ACLOCAL@ @@ -180,6 +215,10 @@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ +link_libasan = @link_libasan@ +link_liblsan = @link_liblsan@ +link_libtsan = @link_libtsan@ +link_libubsan = @link_libubsan@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ @@ -215,11 +254,22 @@ AM_CXXFLAGS = -Wall -W -Wno-unused-parameter -Wwrite-strings -pedantic \ -Wno-variadic-macros $(LIBSTDCXX_RAW_CXX_CXXFLAGS) ACLOCAL_AMFLAGS = -I m4 noinst_LTLIBRARIES = libsanitizer_lsan.la +@LSAN_SUPPORTED_TRUE@toolexeclib_LTLIBRARIES = liblsan.la sanitizer_lsan_files = \ lsan_common.cc \ lsan_common_linux.cc +lsan_files = \ + $(sanitizer_lsan_files) \ + lsan.cc \ + lsan_allocator.cc \ + lsan_interceptors.cc \ + lsan_thread.cc + libsanitizer_lsan_la_SOURCES = $(sanitizer_lsan_files) +liblsan_la_SOURCES = $(lsan_files) +liblsan_la_LIBADD = $(top_builddir)/sanitizer_common/libsanitizer_common.la $(top_builddir)/interception/libinterception.la $(LIBSTDCXX_RAW_CXX_LDFLAGS) +liblsan_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version` $(link_liblsan) # Work around what appears to be a GNU make bug handling MAKEFLAGS # values defined in terms of make variables, as is the case for CC and @@ -303,6 +353,39 @@ clean-noinstLTLIBRARIES: echo "rm -f \"$${dir}/so_locations\""; \ rm -f "$${dir}/so_locations"; \ done +install-toolexeclibLTLIBRARIES: $(toolexeclib_LTLIBRARIES) + @$(NORMAL_INSTALL) + test -z "$(toolexeclibdir)" || $(MKDIR_P) "$(DESTDIR)$(toolexeclibdir)" + @list='$(toolexeclib_LTLIBRARIES)'; test -n "$(toolexeclibdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(toolexeclibdir)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(toolexeclibdir)"; \ + } + +uninstall-toolexeclibLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(toolexeclib_LTLIBRARIES)'; test -n "$(toolexeclibdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(toolexeclibdir)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(toolexeclibdir)/$$f"; \ + done + +clean-toolexeclibLTLIBRARIES: + -test -z "$(toolexeclib_LTLIBRARIES)" || rm -f $(toolexeclib_LTLIBRARIES) + @list='$(toolexeclib_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +liblsan.la: $(liblsan_la_OBJECTS) $(liblsan_la_DEPENDENCIES) + $(liblsan_la_LINK) $(am_liblsan_la_rpath) $(liblsan_la_OBJECTS) $(liblsan_la_LIBADD) $(LIBS) libsanitizer_lsan.la: $(libsanitizer_lsan_la_OBJECTS) $(libsanitizer_lsan_la_DEPENDENCIES) $(CXXLINK) $(libsanitizer_lsan_la_OBJECTS) $(libsanitizer_lsan_la_LIBADD) $(LIBS) @@ -312,8 +395,12 @@ mostlyclean-compile: distclean-compile: -rm -f *.tab.c +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lsan.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lsan_allocator.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lsan_common.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lsan_common_linux.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lsan_interceptors.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lsan_thread.Plo@am__quote@ .cc.o: @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @@ -397,6 +484,9 @@ check-am: all-am check: check-am all-am: Makefile $(LTLIBRARIES) installdirs: + for dir in "$(DESTDIR)$(toolexeclibdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done install: install-am install-exec: install-exec-am install-data: install-data-am @@ -425,7 +515,7 @@ maintainer-clean-generic: clean: clean-am clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ - mostlyclean-am + clean-toolexeclibLTLIBRARIES mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) @@ -451,7 +541,7 @@ install-dvi: install-dvi-am install-dvi-am: -install-exec-am: +install-exec-am: install-toolexeclibLTLIBRARIES install-html: install-html-am @@ -491,22 +581,24 @@ ps: ps-am ps-am: -uninstall-am: +uninstall-am: uninstall-toolexeclibLTLIBRARIES .MAKE: install-am install-strip .PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ - clean-libtool clean-noinstLTLIBRARIES ctags distclean \ - distclean-compile distclean-generic distclean-libtool \ - distclean-tags dvi dvi-am html html-am info info-am install \ - install-am install-data install-data-am install-dvi \ - install-dvi-am install-exec install-exec-am install-html \ - install-html-am install-info install-info-am install-man \ - install-pdf install-pdf-am install-ps install-ps-am \ - install-strip installcheck installcheck-am installdirs \ - maintainer-clean maintainer-clean-generic mostlyclean \ - mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ - pdf pdf-am ps ps-am tags uninstall uninstall-am + clean-libtool clean-noinstLTLIBRARIES \ + clean-toolexeclibLTLIBRARIES ctags distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags dvi dvi-am \ + html html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-html install-html-am install-info \ + install-info-am install-man install-pdf install-pdf-am \ + install-ps install-ps-am install-strip \ + install-toolexeclibLTLIBRARIES installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \ + uninstall-am uninstall-toolexeclibLTLIBRARIES # Tell versions [3.59,3.63) of GNU make to not export all variables. diff --git a/libsanitizer/sanitizer_common/Makefile.in b/libsanitizer/sanitizer_common/Makefile.in index b54465388ce..9bbdfd6acfe 100644 --- a/libsanitizer/sanitizer_common/Makefile.in +++ b/libsanitizer/sanitizer_common/Makefile.in @@ -192,6 +192,10 @@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ +link_libasan = @link_libasan@ +link_liblsan = @link_liblsan@ +link_libtsan = @link_libtsan@ +link_libubsan = @link_libubsan@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ diff --git a/libsanitizer/sanitizer_common/sanitizer_linux.cc b/libsanitizer/sanitizer_common/sanitizer_linux.cc index 2763313015a..ddc65465ef7 100644 --- a/libsanitizer/sanitizer_common/sanitizer_linux.cc +++ b/libsanitizer/sanitizer_common/sanitizer_linux.cc @@ -785,7 +785,6 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, * %r8 = new_tls, * %r10 = child_tidptr) */ - ".cfi_endproc\n" "syscall\n" /* if (%rax != 0) @@ -795,8 +794,9 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, "jnz 1f\n" /* In the child. Terminate unwind chain. */ - ".cfi_startproc\n" - ".cfi_undefined %%rip;\n" + // XXX: We should also terminate the CFI unwind chain + // here. Unfortunately clang 3.2 doesn't support the + // necessary CFI directives, so we skip that part. "xorq %%rbp,%%rbp\n" /* Call "fn(arg)". */ diff --git a/libsanitizer/tsan/Makefile.am b/libsanitizer/tsan/Makefile.am index 6fc4d0ea0ff..9b039d229d7 100644 --- a/libsanitizer/tsan/Makefile.am +++ b/libsanitizer/tsan/Makefile.am @@ -39,7 +39,7 @@ tsan_files = \ libtsan_la_SOURCES = $(tsan_files) libtsan_la_LIBADD = $(top_builddir)/sanitizer_common/libsanitizer_common.la $(top_builddir)/interception/libinterception.la $(LIBSTDCXX_RAW_CXX_LDFLAGS) -libtsan_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version` -lpthread -ldl +libtsan_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version` $(link_libtsan) # Work around what appears to be a GNU make bug handling MAKEFLAGS # values defined in terms of make variables, as is the case for CC and diff --git a/libsanitizer/tsan/Makefile.in b/libsanitizer/tsan/Makefile.in index bac430be35d..eb5c7e7a84b 100644 --- a/libsanitizer/tsan/Makefile.in +++ b/libsanitizer/tsan/Makefile.in @@ -231,6 +231,10 @@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ +link_libasan = @link_libasan@ +link_liblsan = @link_liblsan@ +link_libtsan = @link_libtsan@ +link_libubsan = @link_libubsan@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ @@ -295,7 +299,7 @@ tsan_files = \ libtsan_la_SOURCES = $(tsan_files) libtsan_la_LIBADD = $(top_builddir)/sanitizer_common/libsanitizer_common.la $(top_builddir)/interception/libinterception.la $(LIBSTDCXX_RAW_CXX_LDFLAGS) -libtsan_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version` -lpthread -ldl +libtsan_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version` $(link_libtsan) # Work around what appears to be a GNU make bug handling MAKEFLAGS # values defined in terms of make variables, as is the case for CC and diff --git a/libsanitizer/ubsan/Makefile.am b/libsanitizer/ubsan/Makefile.am index e98984a757b..24e405bd146 100644 --- a/libsanitizer/ubsan/Makefile.am +++ b/libsanitizer/ubsan/Makefile.am @@ -4,7 +4,7 @@ AM_CPPFLAGS = -I $(top_srcdir) -I $(top_srcdir)/include gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER) DEFS = -D_GNU_SOURCE -D_DEBUG -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -AM_CXXFLAGS = -Wall -W -Wno-unused-parameter -Wwrite-strings -pedantic -Wno-long-long -fPIC -fno-builtin -fno-exceptions -fomit-frame-pointer -funwind-tables -fvisibility=hidden -Wno-variadic-macros +AM_CXXFLAGS = -Wall -W -Wno-unused-parameter -Wwrite-strings -pedantic -Wno-long-long -fPIC -fno-builtin -fno-exceptions -fno-rtti -fomit-frame-pointer -funwind-tables -fvisibility=hidden -Wno-variadic-macros AM_CXXFLAGS += $(LIBSTDCXX_RAW_CXX_CXXFLAGS) ACLOCAL_AMFLAGS = -I m4 @@ -23,7 +23,10 @@ if !USING_MAC_INTERPOSE libubsan_la_LIBADD += $(top_builddir)/interception/libinterception.la endif libubsan_la_LIBADD += $(LIBSTDCXX_RAW_CXX_LDFLAGS) -libubsan_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version` -lpthread -ldl +libubsan_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version` $(link_libubsan) + +# Use special rules for files that require RTTI support. +ubsan_handlers_cxx.% ubsan_type_hash.% : AM_CXXFLAGS += -frtti # Work around what appears to be a GNU make bug handling MAKEFLAGS # values defined in terms of make variables, as is the case for CC and diff --git a/libsanitizer/ubsan/Makefile.in b/libsanitizer/ubsan/Makefile.in index 68125387540..dcb04c72d4d 100644 --- a/libsanitizer/ubsan/Makefile.in +++ b/libsanitizer/ubsan/Makefile.in @@ -210,6 +210,10 @@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ +link_libasan = @link_libasan@ +link_liblsan = @link_liblsan@ +link_libtsan = @link_libtsan@ +link_libubsan = @link_libubsan@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ @@ -240,7 +244,7 @@ AM_CPPFLAGS = -I $(top_srcdir) -I $(top_srcdir)/include # May be used by toolexeclibdir. gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER) AM_CXXFLAGS = -Wall -W -Wno-unused-parameter -Wwrite-strings -pedantic \ - -Wno-long-long -fPIC -fno-builtin -fno-exceptions \ + -Wno-long-long -fPIC -fno-builtin -fno-exceptions -fno-rtti \ -fomit-frame-pointer -funwind-tables -fvisibility=hidden \ -Wno-variadic-macros $(LIBSTDCXX_RAW_CXX_CXXFLAGS) ACLOCAL_AMFLAGS = -I m4 @@ -256,7 +260,7 @@ libubsan_la_SOURCES = $(ubsan_files) libubsan_la_LIBADD = \ $(top_builddir)/sanitizer_common/libsanitizer_common.la \ $(am__append_1) $(LIBSTDCXX_RAW_CXX_LDFLAGS) -libubsan_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version` -lpthread -ldl +libubsan_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version` $(link_libubsan) # Work around what appears to be a GNU make bug handling MAKEFLAGS # values defined in terms of make variables, as is the case for CC and @@ -575,6 +579,9 @@ uninstall-am: uninstall-toolexeclibLTLIBRARIES tags uninstall uninstall-am uninstall-toolexeclibLTLIBRARIES +# Use special rules for files that require RTTI support. +ubsan_handlers_cxx.% ubsan_type_hash.% : AM_CXXFLAGS += -frtti + # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 3580a88d65c..912b89fd0d1 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,9 +1,59 @@ +2013-12-03 Jonathan Wakely <jwakely.gcc@gmail.com> + + * include/std/fstream (basic_filebuf::open): Use preformatted text + for table in Doxygen comment. + +2013-12-03 Tim Shen <timshen91@gmail.com> + + * regex_compiler.h: Add todo comment. + * regex_executor.tcc: Likewise. + +2013-11-29 Matthias Klose <doko@ubuntu.com> + + * testsuite/experimental/string_view/requirements/exception, + testsuite/experimental/string_view/capacity/wchar_t, + testsuite/experimental/string_view/capacity/char: Remove empty dirs. + +2013-11-27 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE> + + * testsuite/ext/random/hypergeometric_distribution/operators/values.cc: + Use dg-require-cmath instead. + + * testsuite/ext/random/hypergeometric_distribution/operators/values.cc + (test01): Wrap in _GLIBCXX_USE_C99_MATH_TR1. + +2013-11-22 François Dumont <fdumont@gcc.gnu.org> + + * include/debug/safe_local_iterator.h (_Safe_local_iterator<>): + Remove _M_bucket, use same information in normal local_iterator. + (operator==): Remove redundant _M_can_compare check. + * include/debug/safe_local_iterator.tcc: Adapt. + * include/debug/unordered_set: Likewise. + * include/debug/unordered_map: Likewise. + +2013-11-22 Jakub Jelinek <jakub@redhat.com> + + * testsuite/Makefile.am (check_DEJAGNU_normal_targets): Add 10. + (check-DEJAGNU): Add normal10, run 28_regex/[ab]* + tests as another separate job. + * testsuite/Makefile.in: Regenerated. + 2013-11-22 Jonathan Wakely <jwakely.gcc@gmail.com> * acinclude.m4 (libtool_VERSION): Bump. * configure: Regenerate. * doc/xml/manual/abi.xml: Update version information. + PR libstdc++/59247 + * include/bits/c++config (_GLIBCXX_INLINE_VERSION): Declare namespace + std::experimental::__7 as inline. + * include/bits/regex.h (_GLIBCXX_BEGIN_NAMESPACE_VERSION): Do not + enclose namespace __detail. + * include/bits/regex.tcc (_GLIBCXX_BEGIN_NAMESPACE_VERSION): Likewise. + * include/std/iomanip (_GLIBCXX_BEGIN_NAMESPACE_VERSION): Likewise. + * include/ext/pb_ds/tag_and_trait.hpp (detail): Fix comment. + * testsuite/ext/profile/mutex_extensions_neg.cc: Adjust line number. + 2013-11-22 Paolo Carlini <paolo.carlini@oracle.com> * testsuite/ext/random/hypergeometric_distribution/operators/ diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config index aca8484e222..b00bc41d634 100644 --- a/libstdc++-v3/include/bits/c++config +++ b/libstdc++-v3/include/bits/c++config @@ -169,6 +169,8 @@ namespace placeholders { } namespace regex_constants { } namespace this_thread { } + + namespace experimental { } } namespace abi { } @@ -222,6 +224,8 @@ namespace std namespace regex_constants { inline namespace __7 { } } namespace this_thread { inline namespace __7 { } } + namespace experimental { inline namespace __7 { } } + namespace __detail { inline namespace __7 { } } } diff --git a/libstdc++-v3/include/bits/regex.h b/libstdc++-v3/include/bits/regex.h index 84b8cf1dd4f..9f8a0ebf3fe 100644 --- a/libstdc++-v3/include/bits/regex.h +++ b/libstdc++-v3/include/bits/regex.h @@ -30,8 +30,6 @@ namespace std _GLIBCXX_VISIBILITY(default) { -_GLIBCXX_BEGIN_NAMESPACE_VERSION - namespace __detail { _GLIBCXX_BEGIN_NAMESPACE_VERSION @@ -53,6 +51,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_END_NAMESPACE_VERSION } +_GLIBCXX_BEGIN_NAMESPACE_VERSION + /** * @addtogroup regex * @{ diff --git a/libstdc++-v3/include/bits/regex.tcc b/libstdc++-v3/include/bits/regex.tcc index 2ac095d9881..f58b32d296a 100644 --- a/libstdc++-v3/include/bits/regex.tcc +++ b/libstdc++-v3/include/bits/regex.tcc @@ -37,8 +37,6 @@ namespace std _GLIBCXX_VISIBILITY(default) { -_GLIBCXX_BEGIN_NAMESPACE_VERSION - namespace __detail { _GLIBCXX_BEGIN_NAMESPACE_VERSION @@ -137,6 +135,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_END_NAMESPACE_VERSION } +_GLIBCXX_BEGIN_NAMESPACE_VERSION + template<typename _Ch_type> template<typename _Fwd_iter> typename regex_traits<_Ch_type>::string_type diff --git a/libstdc++-v3/include/bits/regex_compiler.h b/libstdc++-v3/include/bits/regex_compiler.h index b9f81272bb9..5759d48c5e5 100644 --- a/libstdc++-v3/include/bits/regex_compiler.h +++ b/libstdc++-v3/include/bits/regex_compiler.h @@ -237,6 +237,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION }; /// Matches a character range (bracket expression) + // TODO: Convert used _M_flags fields to template parameters, including + // collate and icase. Avoid using std::set, could use flat_set + // (sorted vector and binary search) instead; use an fixed sized (256) + // vector<bool> for char specialization if necessary. template<typename _TraitsT> struct _BracketMatcher { diff --git a/libstdc++-v3/include/bits/regex_executor.tcc b/libstdc++-v3/include/bits/regex_executor.tcc index 22fd67cfa3b..150adb4f2df 100644 --- a/libstdc++-v3/include/bits/regex_executor.tcc +++ b/libstdc++-v3/include/bits/regex_executor.tcc @@ -162,6 +162,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return false; } + // TODO: Use a function vector to dispatch, instead of using switch-case. template<typename _BiIter, typename _Alloc, typename _TraitsT, bool __dfs_mode> template<bool __match_mode> diff --git a/libstdc++-v3/include/debug/safe_local_iterator.h b/libstdc++-v3/include/debug/safe_local_iterator.h index 6724798b377..5b8d2efc99c 100644 --- a/libstdc++-v3/include/debug/safe_local_iterator.h +++ b/libstdc++-v3/include/debug/safe_local_iterator.h @@ -58,9 +58,6 @@ namespace __gnu_debug /// The underlying iterator _Iterator _M_current; - /// The bucket this local iterator belongs to - size_type _M_bucket; - /// Determine if this is a constant iterator. bool _M_constant() const @@ -89,10 +86,8 @@ namespace __gnu_debug * @pre @p seq is not NULL * @post this is not singular */ - _Safe_local_iterator(const _Iterator& __i, size_type __bucket, - const _Sequence* __seq) - : _Safe_local_iterator_base(__seq, _M_constant()), _M_current(__i), - _M_bucket(__bucket) + _Safe_local_iterator(const _Iterator& __i, const _Sequence* __seq) + : _Safe_local_iterator_base(__seq, _M_constant()), _M_current(__i) { _GLIBCXX_DEBUG_VERIFY(!this->_M_singular(), _M_message(__msg_init_singular) @@ -104,12 +99,12 @@ namespace __gnu_debug */ _Safe_local_iterator(const _Safe_local_iterator& __x) : _Safe_local_iterator_base(__x, _M_constant()), - _M_current(__x._M_current), _M_bucket(__x._M_bucket) + _M_current(__x._M_current) { // _GLIBCXX_RESOLVE_LIB_DEFECTS // DR 408. Is vector<reverse_iterator<char*> > forbidden? _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() - || __x._M_current == _Iterator(), + || __x.base() == _Iterator(), _M_message(__msg_init_copy_singular) ._M_iterator(*this, "this") ._M_iterator(__x, "other")); @@ -127,7 +122,7 @@ namespace __gnu_debug typename _Sequence::local_iterator::iterator_type>::__value, _Sequence>::__type>& __x) : _Safe_local_iterator_base(__x, _M_constant()), - _M_current(__x.base()), _M_bucket(__x._M_bucket) + _M_current(__x.base()) { // _GLIBCXX_RESOLVE_LIB_DEFECTS // DR 408. Is vector<reverse_iterator<char*> > forbidden? @@ -147,12 +142,11 @@ namespace __gnu_debug // _GLIBCXX_RESOLVE_LIB_DEFECTS // DR 408. Is vector<reverse_iterator<char*> > forbidden? _GLIBCXX_DEBUG_VERIFY(!__x._M_singular() - || __x._M_current == _Iterator(), + || __x.base() == _Iterator(), _M_message(__msg_copy_singular) ._M_iterator(*this, "this") ._M_iterator(__x, "other")); _M_current = __x._M_current; - _M_bucket = __x._M_bucket; this->_M_attach(__x._M_sequence); return *this; } @@ -225,7 +219,7 @@ namespace __gnu_debug * @brief Return the bucket */ size_type - bucket() const { return _M_bucket; } + bucket() const { return _M_current._M_bucket; } /** * @brief Conversion to underlying non-debug iterator to allow @@ -266,19 +260,20 @@ namespace __gnu_debug _M_get_sequence() const { return static_cast<_Sequence*>(_M_sequence); } - /// Is this iterator equal to the sequence's begin() iterator? + /// Is this iterator equal to the sequence's begin(bucket) iterator? bool _M_is_begin() const - { return base() == _M_get_sequence()->_M_base().begin(_M_bucket); } + { return base() == _M_get_sequence()->_M_base().begin(bucket()); } - /// Is this iterator equal to the sequence's end() iterator? + /// Is this iterator equal to the sequence's end(bucket) iterator? bool _M_is_end() const - { return base() == _M_get_sequence()->_M_base().end(_M_bucket); } + { return base() == _M_get_sequence()->_M_base().end(bucket()); } /// Is this iterator part of the same bucket as the other one? - template <typename _Other> - bool _M_in_same_bucket(const _Safe_local_iterator<_Other, - _Sequence>& __other) const - { return _M_bucket == __other.bucket(); } + template<typename _Other> + bool + _M_in_same_bucket(const _Safe_local_iterator<_Other, + _Sequence>& __other) const + { return bucket() == __other.bucket(); } }; template<typename _IteratorL, typename _IteratorR, typename _Sequence> @@ -286,7 +281,7 @@ namespace __gnu_debug operator==(const _Safe_local_iterator<_IteratorL, _Sequence>& __lhs, const _Safe_local_iterator<_IteratorR, _Sequence>& __rhs) { - _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), + _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(), _M_message(__msg_iter_compare_bad) ._M_iterator(__lhs, "lhs") ._M_iterator(__rhs, "rhs")); @@ -294,10 +289,6 @@ namespace __gnu_debug _M_message(__msg_compare_different) ._M_iterator(__lhs, "lhs") ._M_iterator(__rhs, "rhs")); - _GLIBCXX_DEBUG_VERIFY(__lhs._M_can_compare(__rhs), - _M_message(__msg_compare_different) - ._M_iterator(__lhs, "lhs") - ._M_iterator(__rhs, "rhs")); _GLIBCXX_DEBUG_VERIFY(__lhs._M_in_same_bucket(__rhs), _M_message(__msg_local_iter_compare_bad) ._M_iterator(__lhs, "lhs") @@ -310,7 +301,7 @@ namespace __gnu_debug operator==(const _Safe_local_iterator<_Iterator, _Sequence>& __lhs, const _Safe_local_iterator<_Iterator, _Sequence>& __rhs) { - _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), + _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(), _M_message(__msg_iter_compare_bad) ._M_iterator(__lhs, "lhs") ._M_iterator(__rhs, "rhs")); @@ -350,7 +341,7 @@ namespace __gnu_debug operator!=(const _Safe_local_iterator<_Iterator, _Sequence>& __lhs, const _Safe_local_iterator<_Iterator, _Sequence>& __rhs) { - _GLIBCXX_DEBUG_VERIFY(! __lhs._M_singular() && ! __rhs._M_singular(), + _GLIBCXX_DEBUG_VERIFY(!__lhs._M_singular() && !__rhs._M_singular(), _M_message(__msg_iter_compare_bad) ._M_iterator(__lhs, "lhs") ._M_iterator(__rhs, "rhs")); diff --git a/libstdc++-v3/include/debug/safe_local_iterator.tcc b/libstdc++-v3/include/debug/safe_local_iterator.tcc index 6633bdb7794..bef22fcaf46 100644 --- a/libstdc++-v3/include/debug/safe_local_iterator.tcc +++ b/libstdc++-v3/include/debug/safe_local_iterator.tcc @@ -38,7 +38,7 @@ namespace __gnu_debug { if (!_M_can_compare(__rhs)) return false; - if (_M_bucket != __rhs._M_bucket) + if (bucket() != __rhs.bucket()) return false; /* Determine if we can order the iterators without the help of diff --git a/libstdc++-v3/include/debug/unordered_map b/libstdc++-v3/include/debug/unordered_map index cbde903d8b8..c4be6ea79b3 100644 --- a/libstdc++-v3/include/debug/unordered_map +++ b/libstdc++-v3/include/debug/unordered_map @@ -208,42 +208,42 @@ namespace __debug begin(size_type __b) { __glibcxx_check_bucket_index(__b); - return local_iterator(_Base::begin(__b), __b, this); + return local_iterator(_Base::begin(__b), this); } local_iterator end(size_type __b) { __glibcxx_check_bucket_index(__b); - return local_iterator(_Base::end(__b), __b, this); + return local_iterator(_Base::end(__b), this); } const_local_iterator begin(size_type __b) const { __glibcxx_check_bucket_index(__b); - return const_local_iterator(_Base::begin(__b), __b, this); + return const_local_iterator(_Base::begin(__b), this); } const_local_iterator end(size_type __b) const { __glibcxx_check_bucket_index(__b); - return const_local_iterator(_Base::end(__b), __b, this); + return const_local_iterator(_Base::end(__b), this); } const_local_iterator cbegin(size_type __b) const { __glibcxx_check_bucket_index(__b); - return const_local_iterator(_Base::cbegin(__b), __b, this); + return const_local_iterator(_Base::cbegin(__b), this); } const_local_iterator cend(size_type __b) const { __glibcxx_check_bucket_index(__b); - return const_local_iterator(_Base::cend(__b), __b, this); + return const_local_iterator(_Base::cend(__b), this); } size_type @@ -664,42 +664,42 @@ namespace __debug begin(size_type __b) { __glibcxx_check_bucket_index(__b); - return local_iterator(_Base::begin(__b), __b, this); + return local_iterator(_Base::begin(__b), this); } local_iterator end(size_type __b) { __glibcxx_check_bucket_index(__b); - return local_iterator(_Base::end(__b), __b, this); + return local_iterator(_Base::end(__b), this); } const_local_iterator begin(size_type __b) const { __glibcxx_check_bucket_index(__b); - return const_local_iterator(_Base::begin(__b), __b, this); + return const_local_iterator(_Base::begin(__b), this); } const_local_iterator end(size_type __b) const { __glibcxx_check_bucket_index(__b); - return const_local_iterator(_Base::end(__b), __b, this); + return const_local_iterator(_Base::end(__b), this); } const_local_iterator cbegin(size_type __b) const { __glibcxx_check_bucket_index(__b); - return const_local_iterator(_Base::cbegin(__b), __b, this); + return const_local_iterator(_Base::cbegin(__b), this); } const_local_iterator cend(size_type __b) const { __glibcxx_check_bucket_index(__b); - return const_local_iterator(_Base::cend(__b), __b, this); + return const_local_iterator(_Base::cend(__b), this); } size_type diff --git a/libstdc++-v3/include/debug/unordered_set b/libstdc++-v3/include/debug/unordered_set index 66898e243b1..4923be8c7ea 100644 --- a/libstdc++-v3/include/debug/unordered_set +++ b/libstdc++-v3/include/debug/unordered_set @@ -207,42 +207,42 @@ namespace __debug begin(size_type __b) { __glibcxx_check_bucket_index(__b); - return local_iterator(_Base::begin(__b), __b, this); + return local_iterator(_Base::begin(__b), this); } local_iterator end(size_type __b) { __glibcxx_check_bucket_index(__b); - return local_iterator(_Base::end(__b), __b, this); + return local_iterator(_Base::end(__b), this); } const_local_iterator begin(size_type __b) const { __glibcxx_check_bucket_index(__b); - return const_local_iterator(_Base::begin(__b), __b, this); + return const_local_iterator(_Base::begin(__b), this); } const_local_iterator end(size_type __b) const { __glibcxx_check_bucket_index(__b); - return const_local_iterator(_Base::end(__b), __b, this); + return const_local_iterator(_Base::end(__b), this); } const_local_iterator cbegin(size_type __b) const { __glibcxx_check_bucket_index(__b); - return const_local_iterator(_Base::cbegin(__b), __b, this); + return const_local_iterator(_Base::cbegin(__b), this); } const_local_iterator cend(size_type __b) const { __glibcxx_check_bucket_index(__b); - return const_local_iterator(_Base::cend(__b), __b, this); + return const_local_iterator(_Base::cend(__b), this); } size_type @@ -658,42 +658,42 @@ namespace __debug begin(size_type __b) { __glibcxx_check_bucket_index(__b); - return local_iterator(_Base::begin(__b), __b, this); + return local_iterator(_Base::begin(__b), this); } local_iterator end(size_type __b) { __glibcxx_check_bucket_index(__b); - return local_iterator(_Base::end(__b), __b, this); + return local_iterator(_Base::end(__b), this); } const_local_iterator begin(size_type __b) const { __glibcxx_check_bucket_index(__b); - return const_local_iterator(_Base::begin(__b), __b, this); + return const_local_iterator(_Base::begin(__b), this); } const_local_iterator end(size_type __b) const { __glibcxx_check_bucket_index(__b); - return const_local_iterator(_Base::end(__b), __b, this); + return const_local_iterator(_Base::end(__b), this); } const_local_iterator cbegin(size_type __b) const { __glibcxx_check_bucket_index(__b); - return const_local_iterator(_Base::cbegin(__b), __b, this); + return const_local_iterator(_Base::cbegin(__b), this); } const_local_iterator cend(size_type __b) const { __glibcxx_check_bucket_index(__b); - return const_local_iterator(_Base::cend(__b), __b, this); + return const_local_iterator(_Base::cend(__b), this); } size_type diff --git a/libstdc++-v3/include/ext/pb_ds/tag_and_trait.hpp b/libstdc++-v3/include/ext/pb_ds/tag_and_trait.hpp index 90bda95d208..3d16e5229e4 100644 --- a/libstdc++-v3/include/ext/pb_ds/tag_and_trait.hpp +++ b/libstdc++-v3/include/ext/pb_ds/tag_and_trait.hpp @@ -447,7 +447,7 @@ namespace __gnu_pbds template<typename Key, typename Mapped, typename _Alloc, typename Tag, typename Policy_Tl = null_type> struct container_base_dispatch; - } // namespace __detail + } // namespace detail //@} } // namespace __gnu_pbds diff --git a/libstdc++-v3/include/std/fstream b/libstdc++-v3/include/std/fstream index 48e5c3d85d6..701247a9cc3 100644 --- a/libstdc++-v3/include/std/fstream +++ b/libstdc++-v3/include/std/fstream @@ -238,9 +238,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * given in @a __mode. * * Table 92, adapted here, gives the relation between openmode - * combinations and the equivalent fopen() flags. + * combinations and the equivalent @c fopen() flags. * (NB: lines app, in|out|app, in|app, binary|app, binary|in|out|app, * and binary|in|app per DR 596) + * <pre> * +---------------------------------------------------------+ * | ios_base Flag combination stdio equivalent | * |binary in out trunc app | @@ -265,6 +266,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * | + + + + a+b | * | + + + a+b | * +---------------------------------------------------------+ + * </pre> */ __filebuf_type* open(const char* __s, ios_base::openmode __mode); diff --git a/libstdc++-v3/include/std/iomanip b/libstdc++-v3/include/std/iomanip index 47284e82a5a..e135d08be33 100644 --- a/libstdc++-v3/include/std/iomanip +++ b/libstdc++-v3/include/std/iomanip @@ -336,7 +336,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if __cplusplus > 201103L +_GLIBCXX_END_NAMESPACE_VERSION namespace __detail { + _GLIBCXX_BEGIN_NAMESPACE_VERSION /** * @brief Struct for delimited strings. @@ -447,8 +449,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __is; } - + _GLIBCXX_END_NAMESPACE_VERSION } // namespace __detail +_GLIBCXX_BEGIN_NAMESPACE_VERSION /** * @brief Manipulator for quoted strings. diff --git a/libstdc++-v3/testsuite/Makefile.am b/libstdc++-v3/testsuite/Makefile.am index 4c92fef3c78..0faa8505de8 100644 --- a/libstdc++-v3/testsuite/Makefile.am +++ b/libstdc++-v3/testsuite/Makefile.am @@ -101,7 +101,7 @@ new-abi-baseline: @test ! -f $*/site.exp || mv $*/site.exp $*/site.bak @mv $*/site.exp.tmp $*/site.exp -check_DEJAGNU_normal_targets = $(patsubst %,check-DEJAGNUnormal%,0 1 2 3 4 5 6 7 8 9) +check_DEJAGNU_normal_targets = $(patsubst %,check-DEJAGNUnormal%,0 1 2 3 4 5 6 7 8 9 10) $(check_DEJAGNU_normal_targets): check-DEJAGNUnormal%: normal%/site.exp # Run the testsuite in normal mode. @@ -111,16 +111,16 @@ check-DEJAGNU $(check_DEJAGNU_normal_targets): check-DEJAGNU%: site.exp if [ -z "$*$(filter-out --target_board=%, $(RUNTESTFLAGS))" ] \ && [ "$(filter -j, $(MFLAGS))" = "-j" ]; then \ $(MAKE) $(AM_MAKEFLAGS) $(check_DEJAGNU_normal_targets); \ - for idx in 0 1 2 3 4 5 6 7 8 9; do \ + for idx in 0 1 2 3 4 5 6 7 8 9 10; do \ mv -f normal$$idx/libstdc++.sum normal$$idx/libstdc++.sum.sep; \ mv -f normal$$idx/libstdc++.log normal$$idx/libstdc++.log.sep; \ done; \ mv -f libstdc++.sum libstdc++.sum.sep; \ mv -f libstdc++.log libstdc++.log.sep; \ $(SHELL) $(srcdir)/../../contrib/dg-extract-results.sh \ - libstdc++.sum.sep normal[0-9]/libstdc++.sum.sep > libstdc++.sum; \ + libstdc++.sum.sep normal[0-9]*/libstdc++.sum.sep > libstdc++.sum; \ $(SHELL) $(srcdir)/../../contrib/dg-extract-results.sh -L \ - libstdc++.log.sep normal[0-9]/libstdc++.log.sep > libstdc++.log; \ + libstdc++.log.sep normal[0-9]*/libstdc++.log.sep > libstdc++.log; \ exit 0; \ fi; \ srcdir=`$(am__cd) $(srcdir) && pwd`; export srcdir; \ @@ -150,10 +150,12 @@ check-DEJAGNU $(check_DEJAGNU_normal_targets): check-DEJAGNU%: site.exp normal6) \ dirs="`cd $$srcdir; echo 2[459]_*/*`";; \ normal7) \ - dirs="`cd $$srcdir; echo 2[68]_*/*`";; \ + dirs="`cd $$srcdir; echo 26_*/* 28_*/[c-z]*`";; \ normal8) \ dirs="`cd $$srcdir; echo 27_*/*`";; \ normal9) \ + dirs="`cd $$srcdir; echo 28_*/[ab]*`";; \ + normal10) \ dirs="`cd $$srcdir; echo t*/*`";; \ esac; \ if [ -n "$*" ]; then cd "$*"; fi; \ diff --git a/libstdc++-v3/testsuite/Makefile.in b/libstdc++-v3/testsuite/Makefile.in index 779e932ea27..7a923f36d95 100644 --- a/libstdc++-v3/testsuite/Makefile.in +++ b/libstdc++-v3/testsuite/Makefile.in @@ -301,7 +301,7 @@ lists_of_files = \ extract_symvers = $(glibcxx_builddir)/scripts/extract_symvers baseline_subdir := $(shell $(CXX) $(baseline_subdir_switch)) -check_DEJAGNU_normal_targets = $(patsubst %,check-DEJAGNUnormal%,0 1 2 3 4 5 6 7 8 9) +check_DEJAGNU_normal_targets = $(patsubst %,check-DEJAGNUnormal%,0 1 2 3 4 5 6 7 8 9 10) # Runs the testsuite, but in compile only mode. # Can be used to test sources with non-GNU FE's at various warning @@ -562,16 +562,16 @@ check-DEJAGNU $(check_DEJAGNU_normal_targets): check-DEJAGNU%: site.exp if [ -z "$*$(filter-out --target_board=%, $(RUNTESTFLAGS))" ] \ && [ "$(filter -j, $(MFLAGS))" = "-j" ]; then \ $(MAKE) $(AM_MAKEFLAGS) $(check_DEJAGNU_normal_targets); \ - for idx in 0 1 2 3 4 5 6 7 8 9; do \ + for idx in 0 1 2 3 4 5 6 7 8 9 10; do \ mv -f normal$$idx/libstdc++.sum normal$$idx/libstdc++.sum.sep; \ mv -f normal$$idx/libstdc++.log normal$$idx/libstdc++.log.sep; \ done; \ mv -f libstdc++.sum libstdc++.sum.sep; \ mv -f libstdc++.log libstdc++.log.sep; \ $(SHELL) $(srcdir)/../../contrib/dg-extract-results.sh \ - libstdc++.sum.sep normal[0-9]/libstdc++.sum.sep > libstdc++.sum; \ + libstdc++.sum.sep normal[0-9]*/libstdc++.sum.sep > libstdc++.sum; \ $(SHELL) $(srcdir)/../../contrib/dg-extract-results.sh -L \ - libstdc++.log.sep normal[0-9]/libstdc++.log.sep > libstdc++.log; \ + libstdc++.log.sep normal[0-9]*/libstdc++.log.sep > libstdc++.log; \ exit 0; \ fi; \ srcdir=`$(am__cd) $(srcdir) && pwd`; export srcdir; \ @@ -601,10 +601,12 @@ check-DEJAGNU $(check_DEJAGNU_normal_targets): check-DEJAGNU%: site.exp normal6) \ dirs="`cd $$srcdir; echo 2[459]_*/*`";; \ normal7) \ - dirs="`cd $$srcdir; echo 2[68]_*/*`";; \ + dirs="`cd $$srcdir; echo 26_*/* 28_*/[c-z]*`";; \ normal8) \ dirs="`cd $$srcdir; echo 27_*/*`";; \ normal9) \ + dirs="`cd $$srcdir; echo 28_*/[ab]*`";; \ + normal10) \ dirs="`cd $$srcdir; echo t*/*`";; \ esac; \ if [ -n "$*" ]; then cd "$*"; fi; \ diff --git a/libstdc++-v3/testsuite/ext/profile/mutex_extensions_neg.cc b/libstdc++-v3/testsuite/ext/profile/mutex_extensions_neg.cc index 23c551b0b6e..a691e8d16f2 100644 --- a/libstdc++-v3/testsuite/ext/profile/mutex_extensions_neg.cc +++ b/libstdc++-v3/testsuite/ext/profile/mutex_extensions_neg.cc @@ -25,4 +25,4 @@ #include <vector> -// { dg-error "multiple inlined namespaces" "" { target *-*-* } 275 } +// { dg-error "multiple inlined namespaces" "" { target *-*-* } 279 } diff --git a/libstdc++-v3/testsuite/ext/random/hypergeometric_distribution/operators/values.cc b/libstdc++-v3/testsuite/ext/random/hypergeometric_distribution/operators/values.cc index 5a1e37975af..5f762d32a1b 100644 --- a/libstdc++-v3/testsuite/ext/random/hypergeometric_distribution/operators/values.cc +++ b/libstdc++-v3/testsuite/ext/random/hypergeometric_distribution/operators/values.cc @@ -1,5 +1,6 @@ // { dg-options "-std=gnu++11" } // { dg-require-cstdint "" } +// { dg-require-cmath "" } // // 2013-11-18 Edward M. Smith-Rowland <3dw4rd@verizon.net> // diff --git a/maintainer-scripts/ChangeLog b/maintainer-scripts/ChangeLog index 8f18264fa6c..867d0ca4771 100644 --- a/maintainer-scripts/ChangeLog +++ b/maintainer-scripts/ChangeLog @@ -1,3 +1,8 @@ +2013-12-02 Gerald Pfeifer <gerald@pfeifer.com> + + * update_web_docs_svn: Work around makeinfo generated file names + and references with "_002d" instead of "-". + 2013-04-12 Jakub Jelinek <jakub@redhat.com> * crontab: Disable snapshots from gcc-4_6-branch. diff --git a/maintainer-scripts/update_web_docs_svn b/maintainer-scripts/update_web_docs_svn index cfc33c42bf5..8a5883eeca7 100755 --- a/maintainer-scripts/update_web_docs_svn +++ b/maintainer-scripts/update_web_docs_svn @@ -172,6 +172,19 @@ for file in $MANUALS; do fi done +# Work around makeinfo generated file names and references with +# "_002d" instead of "-". +find . -name '*.html' | while read f; do + # Do this for the contents of each file. + sed -i -e 's/_002d/-/g' "$f" + # And rename files if necessary. + ff=`echo $f | sed -e 's/_002d/-/g'`; + if [ "$f" != "$ff" ]; then + printf "Renaming %s to %s\n" "$f" "$ff" + mv "$f" "$ff" + fi +done + # Then build a gzipped copy of each of the resulting .html, .ps and .tar files for file in */*.html *.ps *.pdf *.tar; do cat $file | gzip --best > $file.gz |