diff options
author | David Malcolm <dmalcolm@redhat.com> | 2014-11-19 11:15:14 -0500 |
---|---|---|
committer | David Malcolm <dmalcolm@redhat.com> | 2014-11-19 11:16:49 -0500 |
commit | 91b959f6dd1c7cd4ecdf7368cb022730ae08d667 (patch) | |
tree | 5368eda05ee3b4a07666ca0e96c7c9821d420c32 | |
parent | cf2cd094c5c77adb40a2f3f69021ee0b6f8534ab (diff) | |
parent | aec08e4dc853a1460f6965fb75fdbacb517bd868 (diff) | |
download | gcc-91b959f6dd1c7cd4ecdf7368cb022730ae08d667.tar.gz |
Merge branch 'master' r217725-r217783 into gimple-classes-v2-option-3
Merger of changes on trunk r217725 (2014-11-18) to
r217783 (2014-11-19) into the branch.
gcc/ChangeLog.gimple-classes:
* gimple.c (gimple_build_assign_with_ops): Strengthen return type
of new overload, from gimple to gassign *.
Conflicts:
gcc/gimple-ssa-strength-reduction.c
gcc/gimple.h
gcc/omp-low.c
gcc/tree-ssa-math-opts.c
112 files changed, 1754 insertions, 611 deletions
diff --git a/ChangeLog b/ChangeLog index 0d93365e311..f155d54b359 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,32 @@ +2014-11-19 Maxim Kuvyrkov <maxim.kuvyrkov@linaro.org> + + * MAINTAINERS (OS Port Maintainers): Add overdue maintainership note + from 2 years ago. + +2014-11-19 Alex Velenko <Alex.Velenko@arm.com> + + Revert: + 2014-11-19 Alex Velenko <Alex.Velenko@arm.com> + + * MAINTAINERS (Write After Approval): Added myself as line map + maintainer. + +2014-11-19 Renlin Li <Renlin.Li@arm.com> + + Revert: + 2014-11-19 Renlin Li <Renlin.Li@arm.com> + + * MAINTAINERS (Write After Approval): Added myself. + +2014-11-19 Renlin Li <Renlin.Li@arm.com> + + * MAINTAINERS (Write After Approval): Added myself. + +2014-11-19 Alex Velenko <Alex.Velenko@arm.com> + + * MAINTAINERS (Write After Approval): Added myself as line map + maintainer. + 2014-11-17 Dodji Seketeli <dodji@redhat.com> * MAINTAINERS (Various Maintainers): Added myself as line map diff --git a/MAINTAINERS b/MAINTAINERS index 56e68c5e7ab..b0cf9da458b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -121,6 +121,7 @@ xtensa port Sterling Augustine <augustine.sterling@gmail.com> OS Port Maintainers (OS alphabetical order) aix David Edelsohn <dje.gcc@gmail.com> +Android sub-port Maxim Kuvyrkov <maxim.kuvyrkov@linaro.org> darwin port Mike Stump <mikestump@comcast.net> darwin port Eric Christopher <echristo@gmail.com> darwin port Stan Shebs <stanshebs@earthlink.net> diff --git a/config/ChangeLog b/config/ChangeLog index 6f27566974d..ab3a773049d 100644 --- a/config/ChangeLog +++ b/config/ChangeLog @@ -1,3 +1,9 @@ +2014-11-17 Bob Dunlop <bob.dunlop@xyzzy.org.uk> + + * mt-ospace (CFLAGS_FOR_TARGET): Append -g -Os rather than + overwriting. + (CXXFLAGS_FOR_TARGET): Similarly. + 2014-11-17 H.J. Lu <hongjiu.lu@intel.com> PR bootstrap/63888 diff --git a/config/mt-ospace b/config/mt-ospace index 7f091041d8a..ce29ff4315d 100644 --- a/config/mt-ospace +++ b/config/mt-ospace @@ -1,3 +1,3 @@ # Build libraries optimizing for space, not speed. - CFLAGS_FOR_TARGET = -g -Os - CXXFLAGS_FOR_TARGET = -g -Os + CFLAGS_FOR_TARGET += -g -Os + CXXFLAGS_FOR_TARGET += -g -Os diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4a825c17310..e20f8cbe896 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,264 @@ +2014-11-19 Renlin Li <Renlin.Li@arm.com> + + PR middle-end/63762 + * ira.c (ira): Update preferred class. + +2014-11-19 Jakub Jelinek <jakub@redhat.com> + + * gimple.h (gimple_build_assign_with_ops): Add unary arg overload. + (gimple_assign_set_rhs_with_ops_1): Renamed to ... + (gimple_assign_set_rhs_with_ops): ... this. Adjust binary arg + inline overload to use it. Add unary arg overload. + * gimple.c (gimple_build_assign_with_ops): New unary arg overload. + (gimple_assign_set_rhs_from_tree): Use + gimple_assign_set_rhs_with_ops instead of + gimple_assign_set_rhs_with_ops_1. + (gimple_assign_set_rhs_with_ops_1): Renamed to ... + (gimple_assign_set_rhs_with_ops): ... this. + * ipa-split.c (split_function): Remove last NULL argument + from gimple_build_assign_with_ops call. + * tree-ssa-loop-im.c + (move_computations_dom_walker::before_dom_children): Likewise. + * tsan.c (instrument_builtin_call): Likewise. + * tree-vect-stmts.c (vect_init_vector, vectorizable_mask_load_store, + vectorizable_conversion, vectorizable_load): Likewise. + * tree-vect-loop.c (vect_is_simple_reduction_1, + get_initial_def_for_induction): Likewise. + * tree-loop-distribution.c (generate_memset_builtin): Likewise. + * tree-vect-patterns.c (vect_handle_widen_op_by_const, + vect_recog_widen_mult_pattern, vect_operation_fits_smaller_type, + vect_recog_over_widening_pattern, vect_recog_rotate_pattern, + vect_recog_vector_vector_shift_pattern, vect_recog_divmod_pattern, + vect_recog_mixed_size_cond_pattern, adjust_bool_pattern_cast, + adjust_bool_pattern, vect_recog_bool_pattern): Likewise. + * tree-ssa-phiopt.c (conditional_replacement, abs_replacement, + neg_replacement): Likewise. + * asan.c (build_shadow_mem_access, maybe_create_ssa_name, + maybe_cast_to_ptrmode, asan_expand_check_ifn): Likewise. + * tree-vect-slp.c (vect_get_constant_vectors): Likewise. + * omp-low.c (lower_rec_input_clauses, expand_omp_for_generic, + expand_omp_for_static_nochunk, expand_omp_for_static_chunk, + simd_clone_adjust): Likewise. + * tree-vect-loop-manip.c (vect_create_cond_for_align_checks): Likewise. + * gimple-ssa-strength-reduction.c (introduce_cast_before_cand, + replace_one_candidate): Likewise. + * gimple-builder.c (build_type_cast): Likewise. + * tree-ssa-forwprop.c (simplify_rotate): Likewise. + (forward_propagate_addr_expr_1): Remove last NULL argument + from gimple_assign_set_rhs_with_ops call. + (simplify_vector_constructor): Use gimple_assign_set_rhs_with_ops + instead of gimple_assign_set_rhs_with_ops_1. + * tree-ssa-reassoc.c (maybe_optimize_range_tests): Remove last NULL + argument from gimple_build_assign_with_ops call. + (repropagate_negates): Remove last NULL argument from + gimple_assign_set_rhs_with_ops call. + * ubsan.c (ubsan_expand_null_ifn, ubsan_expand_objsize_ifn): Remove + last NULL argument from gimple_build_assign_with_ops call. + (instrument_bool_enum_load): Likewise. Remove last NULL argument + from gimple_assign_set_rhs_with_ops call. + * tree-ssa-math-opts.c (build_and_insert_cast, convert_mult_to_fma): + Remove last NULL argument from gimple_build_assign_with_ops call. + (bswap_replace): Likewise. Use gimple_assign_set_rhs_with_ops instead + of gimple_assign_set_rhs_with_ops_1. + (convert_plusminus_to_widen): Use gimple_assign_set_rhs_with_ops + instead of gimple_assign_set_rhs_with_ops_1. + * gimple-fold.c (replace_stmt_with_simplification): Likewise. + (rewrite_to_defined_overflow, gimple_build): Remove last NULL argument + from gimple_build_assign_with_ops call. + * tree-ssa-strlen.c (handle_pointer_plus): Remove last NULL argument + from gimple_assign_set_rhs_with_ops call. + * tree-vrp.c (simplify_truth_ops_using_ranges, + simplify_bit_ops_using_ranges): Remove last NULL argument from + gimple_assign_set_rhs_with_ops call. + (simplify_float_conversion_using_ranges, + simplify_internal_call_using_ranges): Remove last NULL argument from + gimple_build_assign_with_ops call. + +2014-11-19 Wilco Dijkstra <wdijkstr@arm.com> + + PR target/61915 + * config/aarch64/aarch64.c (generic_regmove_cost): Increase FP move + cost. + +2014-11-19 Marek Polacek <polacek@redhat.com> + + PR sanitizer/63690 + * ubsan.c (instrument_object_size): Check for MEM_REF. + +2014-11-19 Ilya Verbin <ilya.verbin@intel.com> + + PR regression/63868 + * cgraph.c (cgraph_node::create): Guard g->have_offload with + ifdef ENABLE_OFFLOADING. + * omp-low.c (create_omp_child_function): Likewise. + (expand_omp_target): Guard node->mark_force_output and offload_funcs + with ifdef ENABLE_OFFLOADING. + * varpool.c (varpool_node::get_create): Guard g->have_offload and + offload_vars with ifdef ENABLE_OFFLOADING. + +2014-11-19 Felix Yang <felix.yang@huawei.com> + Shanyao Chen <chenshanyao@huawei.com> + + PR target/59593 + * config/arm/arm.md (define_attr "arch"): Add v6t2. + (define_attr "arch_enabled"): Add test for the above. + (*movhi_insn_arch4): Add new alternative. + +2014-11-19 Richard Henderson <rth@redhat.com> + + * c-family/c-common.c (c_common_reswords): Add + __builtin_call_with_static_chain. + * c-family/c-common.h (RID_BUILTIN_CALL_WITH_STATIC_CHAIN): New. + * c/c-parser.c (c_parser_postfix_expression): Handle it. + * doc/extend.texi (__builtin_call_with_static_chain): Document it. + + * calls.c (prepare_call_address): Allow decl or type for first arg. + (expand_call): Pass type to prepare_call_address if no decl. + * gimple-fold.c (gimple_fold_call): Eliminate the static chain if + the function doesn't use it; fold it otherwise. + * gimplify.c (gimplify_call_expr): Gimplify the static chain. + * tree-cfg.c (verify_gimple_call): Allow a static chain on indirect + function calls. + + * targhooks.c (default_static_chain): Remove check for + DECL_STATIC_CHAIN. + * config/moxie/moxie.c (moxie_static_chain): Likewise. + * config/i386/i386.c (ix86_static_chain): Allow decl or type + as the first argument. + * config/xtensa/xtensa.c (xtensa_static_chain): Change the name + of the unused first parameter. + * doc/tm.texi (TARGET_STATIC_CHAIN): Document the first parameter + may be a type. + * target.def (static_chain): Likewise. + +2014-11-19 Renlin Li <renlin.li@arm.com> + + * config/aarch64/aarch64.h (TARGET_CPU_CPP_BUILTINS): Define __ARM_FP_FAST, + __ARM_FEATURE_FMA, __ARM_FP, __ARM_FEATURE_NUMERIC_MAXMIN, __ARM_NEON_FP. + +2014-11-19 Marek Polacek <polacek@redhat.com> + + PR sanitizer/63879 + * fold-const.c (negate_expr_p) <case NEGATE_EXPR>: Return + !TYPE_OVERFLOW_SANITIZED. + (fold_negate_expr) <case INTEGER_CST>: Fold when overflow + does not trap and when overflow wraps, or when SANITIZE_SI_OVERFLOW + is 0. + +2014-11-19 Ilya Tocar <ilya.tocar@intel.com> + + * collect2.c (main): Don't call fatal_error before + diagnostic_initialize. + * lto-wrapper.c (main): Likewise. + +2014-11-19 Tom de Vries <tom@codesourcery.com> + + PR tree-optimization/62167 + * tree-ssa-tail-merge.c (stmt_local_def): Handle statements with vuse + conservatively. + (gimple_equal_p): Don't use vn_valueize to compare for lhs equality of + assigns. + +2014-11-19 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/63915 + * tree-vect-stmts.c (vectorizable_simd_clone_call): Pass + true instead of false as last argument to gsi_replace. + + PR sanitizer/63520 + * internal-fn.c (expand_ubsan_result_store): New function. + (expand_addsub_overflow, expand_neg_overflow, expand_mul_overflow): + Use it instead of just emit_move_insn. + +2014-11-19 Richard Biener <rguenther@suse.de> + + PR tree-optimization/63844 + * omp-low.c (fixup_child_record_type): Use a restrict qualified + referece type for the receiver parameter. + +2014-11-19 Jakub Jelinek <jakub@redhat.com> + + PR sanitizer/63913 + * ubsan.c: Include tree-eh.h. + (instrument_bool_enum_load): Handle loads that can throw. + + PR rtl-optimization/63843 + * simplify-rtx.c (simplify_binary_operation_1) <case ASHIFTRT>: For + optimization of ashiftrt of subreg of lshiftrt, check that code + is ASHIFTRT. + +2014-11-18 Andrew MacLeod <amacleod@redhat.com> + + * attribs.c (decl_attributes): Remove always true condition, + TREE_TYPE(x) will never compare equal to a TYPE_DECL. + +2014-11-18 James Greenhalgh <james.greenhalgh@arm.com> + + PR target/63937 + * target.def (use_by_pieces_infrastructure_p): Take unsigned + HOST_WIDE_INT as the size parameter. + * targhooks.c (default_use_by_pieces_infrastructure_p): Likewise. + * targhooks.h (default_use_by_pieces_infrastructure_p): Likewise. + * config/arc/arc.c (arc_use_by_pieces_infrastructure_p)): Likewise. + * config/mips/mips.c (mips_use_by_pieces_infrastructure_p)): Likewise. + * config/s390/s390.c (s390_use_by_pieces_infrastructure_p)): Likewise. + * config/sh/sh.c (sh_use_by_pieces_infrastructure_p)): Likewise. + * config/aarch64/aarch64.c + (aarch64_use_by_pieces_infrastructure_p)): Likewise. + * doc/tm.texi: Regenerate. + +2014-11-18 Jan Hubicka <hubicka@ucw.cz> + + * ipa-cp.c (ipcp_cloning_candidate_p): Use opt_for_fn. + (ipa_value_from_jfunc, ipa_context_from_jfunc): Skip sanity check. + (ipa_get_indirect_edge_target_1): Use opt_for_fn. + (good_cloning_opportunity_p): Likewise. + (ipa-cp gate): Enable ipa-cp with LTO. + * ipa-profile.c (ipa_propagate_frequency): Use opt_for_fn. + * ipa.c (symbol_table::remove_unreachable_nodes): Always build type + inheritance. + * ipa-inline-transform.c (inline_transform): Check if there are inlines + to apply even at -O0. + * cgraphunit.c (cgraph_node::finalize_function): Use opt_for_fn. + (analyze_functions): Build type inheritance graph. + * ipa-inline.c (can_inline_edge_p): Use opt_for_fn. + (want_early_inline_function_p, want_inline_small_function_p): + Likewise. + (check_callers): Likewise. + (edge_badness): Likewise. + (inline_small_functions): Always be ready for indirect inlining + to happend. + (ipa_inline): Always use want_inline_function_to_all_callers_p. + (early_inline_small_functions): Use opt_for_fn. + * ipa-inline-analysis.c (estimate_function_body_sizes): use opt_for_fn. + (estimate_function_body_sizes): Likewise. + (compute_inline_parameters): Likewise. + (estimate_edge_devirt_benefit): Likewise. + (inline_analyze_function): Likewise. + * ipa-devirt.c (ipa_devirt): Likewise. + (gate): Use in_lto_p. + * ipa-prop.c (ipa_func_spec_opts_forbid_analysis_p): Use opt_for_fn. + (try_make_edge_direct_virtual_call): Likewise. + (update_indirect_edges_after_inlining): Likewise. + (ipa_free_all_structures_after_ipa_cp): Add in_lto_p check. + * common.opt (findirect-inlining): Turn into optimization. + * ipa-pure-const.c (add_new_function): Use opt_for_fn. + (pure_const_generate_summary): Likewise. + (gate_pure_const): Always enable with in_lto_p. + +2014-11-18 Maciej W. Rozycki <macro@codesourcery.com> + + * config/mips/mips.md (compression): Add `micromips32' setting. + (enabled, length): Handle it. + (shift_compression): Replace `micromips' with `micromips32' in + the `compression' attribute. + (*add<mode>3, sub<mode>3): Likewise. + +2014-11-18 Maciej W. Rozycki <macro@codesourcery.com> + + * gcc/config/mips/mips.md (*jump_absolute): Use a branch when in + range, a jump otherwise. + 2014-11-18 Kyrylo Tkachov <kyrylo.tkachov@arm.com> * config/arm/cortex-a15-neon.md (cortex_a15_vfp_to_from_gp): diff --git a/gcc/ChangeLog.gimple-classes b/gcc/ChangeLog.gimple-classes index 93c03acc7f3..52d1150c4d4 100644 --- a/gcc/ChangeLog.gimple-classes +++ b/gcc/ChangeLog.gimple-classes @@ -1,3 +1,8 @@ +2014-11-19 David Malcolm <dmalcolm@redhat.com> + + * gimple.c (gimple_build_assign_with_ops): Strengthen return type + of new overload, from gimple to gassign *. + 2014-11-18 David Malcolm <dmalcolm@redhat.com> * cgraphbuild.c (pass_build_cgraph_edges::execute): Fix linebreak diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 347fa0198ca..1f93cf44076 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20141118 +20141119 diff --git a/gcc/asan.c b/gcc/asan.c index b794b3cb678..be28ede0fb8 100644 --- a/gcc/asan.c +++ b/gcc/asan.c @@ -1600,15 +1600,14 @@ build_shadow_mem_access (gimple_stmt_iterator *gsi, location_t location, g = gimple_build_assign_with_ops (NOP_EXPR, make_ssa_name (shadow_ptr_type, NULL), - gimple_assign_lhs (g), NULL_TREE); + gimple_assign_lhs (g)); gimple_set_location (g, location); gsi_insert_after (gsi, g, GSI_NEW_STMT); t = build2 (MEM_REF, shadow_type, gimple_assign_lhs (g), build_int_cst (shadow_ptr_type, 0)); g = gimple_build_assign_with_ops (MEM_REF, - make_ssa_name (shadow_type, NULL), - t, NULL_TREE); + make_ssa_name (shadow_type, NULL), t); gimple_set_location (g, location); gsi_insert_after (gsi, g, GSI_NEW_STMT); return gimple_assign_lhs (g); @@ -1626,7 +1625,7 @@ maybe_create_ssa_name (location_t loc, tree base, gimple_stmt_iterator *iter, gimple g = gimple_build_assign_with_ops (TREE_CODE (base), make_ssa_name (TREE_TYPE (base), NULL), - base, NULL_TREE); + base); gimple_set_location (g, loc); if (before_p) gsi_insert_before (iter, g, GSI_SAME_STMT); @@ -1646,8 +1645,8 @@ maybe_cast_to_ptrmode (location_t loc, tree len, gimple_stmt_iterator *iter, return len; gimple g = gimple_build_assign_with_ops (NOP_EXPR, - make_ssa_name (pointer_sized_int_node, NULL), - len, NULL); + make_ssa_name (pointer_sized_int_node, + NULL), len); gimple_set_location (g, loc); if (before_p) gsi_insert_before (iter, g, GSI_SAME_STMT); @@ -2537,8 +2536,7 @@ asan_expand_check_ifn (gimple_stmt_iterator *iter, bool use_calls) gimple g = gimple_build_assign_with_ops (NOP_EXPR, make_ssa_name (pointer_sized_int_node, - NULL), - base, NULL_TREE); + NULL), base); gimple_set_location (g, loc); gsi_insert_before (iter, g, GSI_SAME_STMT); tree base_addr = gimple_assign_lhs (g); @@ -2552,8 +2550,7 @@ asan_expand_check_ifn (gimple_stmt_iterator *iter, bool use_calls) gcc_assert (nargs == 2); g = gimple_build_assign_with_ops (NOP_EXPR, make_ssa_name (pointer_sized_int_node, - NULL), - len, NULL_TREE); + NULL), len); gimple_set_location (g, loc); gsi_insert_before (iter, g, GSI_SAME_STMT); tree sz_arg = gimple_assign_lhs (g); @@ -2612,8 +2609,7 @@ asan_expand_check_ifn (gimple_stmt_iterator *iter, bool use_calls) g = gimple_build_assign_with_ops (NOP_EXPR, make_ssa_name (pointer_sized_int_node, - NULL), - base, NULL_TREE); + NULL), base); gimple_set_location (g, loc); gsi_insert_before (&gsi, g, GSI_NEW_STMT); tree base_addr = gimple_assign_lhs (g); diff --git a/gcc/attribs.c b/gcc/attribs.c index 427a0f63f3d..fe847034897 100644 --- a/gcc/attribs.c +++ b/gcc/attribs.c @@ -502,11 +502,7 @@ decl_attributes (tree *node, tree attributes, int flags) if (spec->type_required && DECL_P (*anode)) { anode = &TREE_TYPE (*anode); - /* Allow ATTR_FLAG_TYPE_IN_PLACE for the type's naming decl. */ - if (!(TREE_CODE (*anode) == TYPE_DECL - && *anode == TYPE_NAME (TYPE_MAIN_VARIANT - (TREE_TYPE (*anode))))) - flags &= ~(int) ATTR_FLAG_TYPE_IN_PLACE; + flags &= ~(int) ATTR_FLAG_TYPE_IN_PLACE; } if (spec->function_type_required && TREE_CODE (*anode) != FUNCTION_TYPE diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index fa0518a63eb..cc6771a1bf5 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,14 @@ +2014-11-18 Jakub Jelinek <jakub@redhat.com> + + PR sanitizer/63813 + * c-ubsan.c (ubsan_maybe_instrument_reference_or_call): Change type + argument to ptype, set type to TREE_TYPE (ptype). Don't call + get_pointer_alignment for non-pointers. Use ptype, or if it is + reference type, corresponding pointer type, as type of kind + argument. + (ubsan_maybe_instrument_reference, + ubsan_maybe_instrument_member_call): Adjust callers. + 2014-11-15 Marek Polacek <polacek@redhat.com> PR middle-end/63884 diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 839111a2122..95b6b1b93e0 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -453,6 +453,8 @@ const struct c_common_resword c_common_reswords[] = { "__attribute__", RID_ATTRIBUTE, 0 }, { "__auto_type", RID_AUTO_TYPE, D_CONLY }, { "__bases", RID_BASES, D_CXXONLY }, + { "__builtin_call_with_static_chain", + RID_BUILTIN_CALL_WITH_STATIC_CHAIN, D_CONLY }, { "__builtin_choose_expr", RID_CHOOSE_EXPR, D_CONLY }, { "__builtin_complex", RID_BUILTIN_COMPLEX, D_CONLY }, { "__builtin_shuffle", RID_BUILTIN_SHUFFLE, 0 }, diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index ca6fc8beaf8..7e53923a551 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -101,7 +101,7 @@ enum rid RID_EXTENSION, RID_IMAGPART, RID_REALPART, RID_LABEL, RID_CHOOSE_EXPR, RID_TYPES_COMPATIBLE_P, RID_BUILTIN_COMPLEX, RID_BUILTIN_SHUFFLE, RID_DFLOAT32, RID_DFLOAT64, RID_DFLOAT128, - RID_FRACT, RID_ACCUM, RID_AUTO_TYPE, + RID_FRACT, RID_ACCUM, RID_AUTO_TYPE, RID_BUILTIN_CALL_WITH_STATIC_CHAIN, /* C11 */ RID_ALIGNAS, RID_GENERIC, diff --git a/gcc/c-family/c-ubsan.c b/gcc/c-family/c-ubsan.c index ab16799b0c9..90b03f23e73 100644 --- a/gcc/c-family/c-ubsan.c +++ b/gcc/c-family/c-ubsan.c @@ -383,18 +383,19 @@ ubsan_maybe_instrument_array_ref (tree *expr_p, bool ignore_off_by_one) } static tree -ubsan_maybe_instrument_reference_or_call (location_t loc, tree op, tree type, +ubsan_maybe_instrument_reference_or_call (location_t loc, tree op, tree ptype, enum ubsan_null_ckind ckind) { - tree orig_op = op; - bool instrument = false; - unsigned int mina = 0; - if (current_function_decl == NULL_TREE || lookup_attribute ("no_sanitize_undefined", DECL_ATTRIBUTES (current_function_decl))) return NULL_TREE; + tree type = TREE_TYPE (ptype); + tree orig_op = op; + bool instrument = false; + unsigned int mina = 0; + if (flag_sanitize & SANITIZE_ALIGNMENT) { mina = min_align_of_type (type); @@ -431,13 +432,20 @@ ubsan_maybe_instrument_reference_or_call (location_t loc, tree op, tree type, } else if (flag_sanitize & SANITIZE_NULL) instrument = true; - if (mina && mina > get_pointer_alignment (op) / BITS_PER_UNIT) - instrument = true; + if (mina && mina > 1) + { + if (!POINTER_TYPE_P (TREE_TYPE (op)) + || mina > get_pointer_alignment (op) / BITS_PER_UNIT) + instrument = true; + } } if (!instrument) return NULL_TREE; op = save_expr (orig_op); - tree kind = build_int_cst (TREE_TYPE (op), ckind); + gcc_assert (POINTER_TYPE_P (ptype)); + if (TREE_CODE (ptype) == REFERENCE_TYPE) + ptype = build_pointer_type (TREE_TYPE (ptype)); + tree kind = build_int_cst (ptype, ckind); tree align = build_int_cst (pointer_sized_int_node, mina); tree call = build_call_expr_internal_loc (loc, IFN_UBSAN_NULL, void_type_node, @@ -453,7 +461,7 @@ ubsan_maybe_instrument_reference (tree stmt) { tree op = TREE_OPERAND (stmt, 0); op = ubsan_maybe_instrument_reference_or_call (EXPR_LOCATION (stmt), op, - TREE_TYPE (TREE_TYPE (stmt)), + TREE_TYPE (stmt), UBSAN_REF_BINDING); if (op) TREE_OPERAND (stmt, 0) = op; @@ -471,7 +479,7 @@ ubsan_maybe_instrument_member_call (tree stmt, bool is_ctor) || !POINTER_TYPE_P (TREE_TYPE (op))) return; op = ubsan_maybe_instrument_reference_or_call (EXPR_LOCATION (stmt), op, - TREE_TYPE (TREE_TYPE (op)), + TREE_TYPE (op), is_ctor ? UBSAN_CTOR_CALL : UBSAN_MEMBER_CALL); if (op) diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index f90f6af776e..8a4fd39fe80 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -7414,6 +7414,46 @@ c_parser_postfix_expression (c_parser *parser) = comptypes (e1, e2) ? integer_one_node : integer_zero_node; } break; + case RID_BUILTIN_CALL_WITH_STATIC_CHAIN: + { + vec<c_expr_t, va_gc> *cexpr_list; + c_expr_t *e2_p; + tree chain_value; + + c_parser_consume_token (parser); + if (!c_parser_get_builtin_args (parser, + "__builtin_call_with_static_chain", + &cexpr_list, false)) + { + expr.value = error_mark_node; + break; + } + if (vec_safe_length (cexpr_list) != 2) + { + error_at (loc, "wrong number of arguments to " + "%<__builtin_call_with_static_chain%>"); + expr.value = error_mark_node; + break; + } + + expr = (*cexpr_list)[0]; + e2_p = &(*cexpr_list)[1]; + *e2_p = convert_lvalue_to_rvalue (loc, *e2_p, true, true); + chain_value = e2_p->value; + mark_exp_read (chain_value); + + if (TREE_CODE (expr.value) != CALL_EXPR) + error_at (loc, "first argument to " + "%<__builtin_call_with_static_chain%> " + "must be a call expression"); + else if (TREE_CODE (TREE_TYPE (chain_value)) != POINTER_TYPE) + error_at (loc, "second argument to " + "%<__builtin_call_with_static_chain%> " + "must be a pointer type"); + else + CALL_EXPR_STATIC_CHAIN (expr.value) = chain_value; + break; + } case RID_BUILTIN_COMPLEX: { vec<c_expr_t, va_gc> *cexpr_list; diff --git a/gcc/calls.c b/gcc/calls.c index 7f55aafa734..c64c0eb6bf7 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -197,7 +197,7 @@ static void restore_fixed_argument_area (rtx, rtx, int, int); CALL_INSN_FUNCTION_USAGE information. */ rtx -prepare_call_address (tree fndecl, rtx funexp, rtx static_chain_value, +prepare_call_address (tree fndecl_or_type, rtx funexp, rtx static_chain_value, rtx *call_fusage, int reg_parm_seen, int sibcallp) { /* Make a valid memory address and copy constants through pseudo-regs, @@ -217,12 +217,13 @@ prepare_call_address (tree fndecl, rtx funexp, rtx static_chain_value, #endif } - if (static_chain_value != 0) + if (static_chain_value != 0 + && (TREE_CODE (fndecl_or_type) != FUNCTION_DECL + || DECL_STATIC_CHAIN (fndecl_or_type))) { rtx chain; - gcc_assert (fndecl); - chain = targetm.calls.static_chain (fndecl, false); + chain = targetm.calls.static_chain (fndecl_or_type, false); static_chain_value = convert_memory_address (Pmode, static_chain_value); emit_move_insn (chain, static_chain_value); @@ -3278,8 +3279,9 @@ expand_call (tree exp, rtx target, int ignore) } after_args = get_last_insn (); - funexp = prepare_call_address (fndecl, funexp, static_chain_value, - &call_fusage, reg_parm_seen, pass == 0); + funexp = prepare_call_address (fndecl ? fndecl : fntype, funexp, + static_chain_value, &call_fusage, + reg_parm_seen, pass == 0); load_register_parameters (args, num_actuals, &call_fusage, flags, pass == 0, &sibcall_failure); diff --git a/gcc/cgraph.c b/gcc/cgraph.c index d7fd636703c..5323468b8f5 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -500,7 +500,9 @@ cgraph_node::create (tree decl) && lookup_attribute ("omp declare target", DECL_ATTRIBUTES (decl))) { node->offloadable = 1; +#ifdef ENABLE_OFFLOADING g->have_offload = true; +#endif } node->register_symbol (); diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index 3ac18bfee70..2fd99a7c098 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -450,7 +450,7 @@ cgraph_node::finalize_function (tree decl, bool no_collect) declared inline and nested functions. These were optimized out in the original implementation and it is unclear whether we want to change the behavior here. */ - if ((!optimize + if ((!opt_for_fn (decl, optimize) && !node->cpp_implicit_alias && !DECL_DISREGARD_INLINE_LIMITS (decl) && !DECL_DECLARED_INLINE_P (decl) @@ -929,8 +929,7 @@ analyze_functions (void) FOR_EACH_SYMBOL (node) if (node->cpp_implicit_alias) node->fixup_same_cpp_alias_visibility (node->get_alias_target ()); - if (optimize && flag_devirtualize) - build_type_inheritance_graph (); + build_type_inheritance_graph (); /* Analysis adds static variables that in turn adds references to new functions. So we need to iterate the process until it stabilize. */ @@ -1001,7 +1000,8 @@ analyze_functions (void) for (edge = cnode->callees; edge; edge = edge->next_callee) if (edge->callee->definition) enqueue_node (edge->callee); - if (optimize && opt_for_fn (cnode->decl, flag_devirtualize)) + if (opt_for_fn (cnode->decl, optimize) + && opt_for_fn (cnode->decl, flag_devirtualize)) { cgraph_edge *next; @@ -1046,8 +1046,7 @@ analyze_functions (void) symtab->process_new_functions (); } } - if (optimize && flag_devirtualize) - update_type_inheritance_graph (); + update_type_inheritance_graph (); /* Collect entry points to the unit. */ if (symtab->dump_file) diff --git a/gcc/collect2.c b/gcc/collect2.c index 7c067ffcafb..9c3a1c55727 100644 --- a/gcc/collect2.c +++ b/gcc/collect2.c @@ -955,9 +955,6 @@ main (int argc, char **argv) signal (SIGCHLD, SIG_DFL); #endif - if (atexit (collect_atexit) != 0) - fatal_error ("atexit failed"); - /* Unlock the stdio streams. */ unlock_std_streams (); @@ -965,6 +962,9 @@ main (int argc, char **argv) diagnostic_initialize (global_dc, 0); + if (atexit (collect_atexit) != 0) + fatal_error ("atexit failed"); + /* Do not invoke xcalloc before this point, since locale needs to be set first, in case a diagnostic is issued. */ diff --git a/gcc/common.opt b/gcc/common.opt index 3a6d7e10c2c..41c8d4ed76d 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -1392,7 +1392,7 @@ Common Report Var(flag_inhibit_size_directive) Do not generate .size directives findirect-inlining -Common Report Var(flag_indirect_inlining) +Common Report Var(flag_indirect_inlining) Optimization Perform indirect inlining ; General flag to enable inlining. Specifying -fno-inline will disable diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 4fec21ec88c..38321237eb3 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -229,8 +229,10 @@ __extension__ static const struct cpu_regmove_cost generic_regmove_cost = { NAMED_PARAM (GP2GP, 1), - NAMED_PARAM (GP2FP, 2), - NAMED_PARAM (FP2GP, 2), + /* Avoid the use of slow int<->fp moves for spilling by setting + their cost higher than memmov_cost. */ + NAMED_PARAM (GP2FP, 5), + NAMED_PARAM (FP2GP, 5), NAMED_PARAM (FP2FP, 2) }; @@ -10196,7 +10198,7 @@ aarch64_asan_shadow_offset (void) } static bool -aarch64_use_by_pieces_infrastructure_p (unsigned int size, +aarch64_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT size, unsigned int align, enum by_pieces_operation op, bool speed_p) diff --git a/gcc/config/aarch64/aarch64.h b/gcc/config/aarch64/aarch64.h index c046b43c662..bbe33a92983 100644 --- a/gcc/config/aarch64/aarch64.h +++ b/gcc/config/aarch64/aarch64.h @@ -38,6 +38,8 @@ builtin_define ("__ARM_FEATURE_CLZ"); \ builtin_define ("__ARM_FEATURE_IDIV"); \ builtin_define ("__ARM_FEATURE_UNALIGNED"); \ + if (flag_unsafe_math_optimizations) \ + builtin_define ("__ARM_FP_FAST"); \ builtin_define ("__ARM_PCS_AAPCS64"); \ builtin_define_with_int_value \ ("__ARM_SIZEOF_WCHAR_T", WCHAR_TYPE_SIZE / 8); \ @@ -52,10 +54,19 @@ else \ builtin_define ("__AARCH64EL__"); \ \ - if (TARGET_SIMD) \ - builtin_define ("__ARM_NEON"); \ - \ - if (TARGET_CRC32) \ + if (TARGET_FLOAT) \ + { \ + builtin_define ("__ARM_FEATURE_FMA"); \ + builtin_define_with_int_value ("__ARM_FP", 0x0C); \ + } \ + if (TARGET_SIMD) \ + { \ + builtin_define ("__ARM_FEATURE_NUMERIC_MAXMIN"); \ + builtin_define ("__ARM_NEON"); \ + builtin_define_with_int_value ("__ARM_NEON_FP", 0x0C);\ + } \ + \ + if (TARGET_CRC32) \ builtin_define ("__ARM_FEATURE_CRC32"); \ \ switch (aarch64_cmodel) \ diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c index 0f3825e10e5..764f7366c9a 100644 --- a/gcc/config/arc/arc.c +++ b/gcc/config/arc/arc.c @@ -416,7 +416,7 @@ static void output_short_suffix (FILE *file); static bool arc_frame_pointer_required (void); -static bool arc_use_by_pieces_infrastructure_p (unsigned int, +static bool arc_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT, unsigned int, enum by_pieces_operation op, bool); @@ -9374,7 +9374,7 @@ arc_legitimize_reload_address (rtx *p, machine_mode mode, int opnum, /* Implement TARGET_USE_BY_PIECES_INFRASTRUCTURE_P. */ static bool -arc_use_by_pieces_infrastructure_p (unsigned int size, +arc_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT size, unsigned int align, enum by_pieces_operation op, bool speed_p) diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index b9880b42301..3a6e0b04914 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -125,9 +125,10 @@ ; This can be "a" for ARM, "t" for either of the Thumbs, "32" for ; TARGET_32BIT, "t1" or "t2" to specify a specific Thumb mode. "v6" ; for ARM or Thumb-2 with arm_arch6, and nov6 for ARM without -; arm_arch6. This attribute is used to compute attribute "enabled", -; use type "any" to enable an alternative in all cases. -(define_attr "arch" "any,a,t,32,t1,t2,v6,nov6,neon_for_64bits,avoid_neon_for_64bits,iwmmxt,iwmmxt2,armv6_or_vfpv3" +; arm_arch6. "v6t2" for Thumb-2 with arm_arch6. This attribute is +; used to compute attribute "enabled", use type "any" to enable an +; alternative in all cases. +(define_attr "arch" "any,a,t,32,t1,t2,v6,nov6,v6t2,neon_for_64bits,avoid_neon_for_64bits,iwmmxt,iwmmxt2,armv6_or_vfpv3" (const_string "any")) (define_attr "arch_enabled" "no,yes" @@ -162,6 +163,10 @@ (match_test "TARGET_32BIT && !arm_arch6")) (const_string "yes") + (and (eq_attr "arch" "v6t2") + (match_test "TARGET_32BIT && arm_arch6 && arm_arch_thumb2")) + (const_string "yes") + (and (eq_attr "arch" "avoid_neon_for_64bits") (match_test "TARGET_NEON") (not (match_test "TARGET_PREFER_NEON_64BITS"))) @@ -6288,8 +6293,8 @@ ;; Pattern to recognize insn generated default case above (define_insn "*movhi_insn_arch4" - [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r") - (match_operand:HI 1 "general_operand" "rIk,K,r,mi"))] + [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m,r") + (match_operand:HI 1 "general_operand" "rIk,K,n,r,mi"))] "TARGET_ARM && arm_arch4 && (register_operand (operands[0], HImode) @@ -6297,16 +6302,19 @@ "@ mov%?\\t%0, %1\\t%@ movhi mvn%?\\t%0, #%B1\\t%@ movhi + movw%?\\t%0, %1\\t%@ movhi str%(h%)\\t%1, %0\\t%@ movhi ldr%(h%)\\t%0, %1\\t%@ movhi" [(set_attr "predicable" "yes") - (set_attr "pool_range" "*,*,*,256") - (set_attr "neg_pool_range" "*,*,*,244") + (set_attr "pool_range" "*,*,*,*,256") + (set_attr "neg_pool_range" "*,*,*,*,244") + (set_attr "arch" "*,*,v6t2,*,*") (set_attr_alternative "type" [(if_then_else (match_operand 1 "const_int_operand" "") (const_string "mov_imm" ) (const_string "mov_reg")) (const_string "mvn_imm") + (const_string "mov_imm") (const_string "store1") (const_string "load1")])] ) diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 3166e0378a2..3b41de2e4f6 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -27356,13 +27356,10 @@ ix86_minimum_alignment (tree exp, machine_mode mode, This is a register, unless all free registers are used by arguments. */ static rtx -ix86_static_chain (const_tree fndecl, bool incoming_p) +ix86_static_chain (const_tree fndecl_or_type, bool incoming_p) { unsigned regno; - if (!DECL_STATIC_CHAIN (fndecl)) - return NULL; - if (TARGET_64BIT) { /* We always use R10 in 64-bit mode. */ @@ -27370,13 +27367,23 @@ ix86_static_chain (const_tree fndecl, bool incoming_p) } else { - tree fntype; + const_tree fntype, fndecl; unsigned int ccvt; /* By default in 32-bit mode we use ECX to pass the static chain. */ regno = CX_REG; - fntype = TREE_TYPE (fndecl); + if (TREE_CODE (fndecl_or_type) == FUNCTION_DECL) + { + fntype = TREE_TYPE (fndecl_or_type); + fndecl = fndecl_or_type; + } + else + { + fntype = fndecl_or_type; + fndecl = NULL; + } + ccvt = ix86_get_callcvt (fntype); if ((ccvt & IX86_CALLCVT_FASTCALL) != 0) { diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 02268f3247e..db58d076e53 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -7235,7 +7235,7 @@ mips_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED) /* Implement TARGET_USE_MOVE_BY_PIECES_INFRASTRUCTURE_P. */ bool -mips_use_by_pieces_infrastructure_p (unsigned int size, +mips_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT size, unsigned int align, enum by_pieces_operation op, bool speed_p) diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index 647bf853c22..65c0a3f18fe 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -429,7 +429,7 @@ (const_string "yes") (const_string "no"))) -(define_attr "compression" "none,all,micromips" +(define_attr "compression" "none,all,micromips32,micromips" (const_string "none")) (define_attr "enabled" "no,yes" @@ -440,7 +440,7 @@ || TARGET_O32_FP64A_ABI") (eq_attr "dword_mode" "yes")) (const_string "no") - (and (eq_attr "compression" "micromips") + (and (eq_attr "compression" "micromips32,micromips") (match_test "!TARGET_MICROMIPS")) (const_string "no")] (const_string "yes"))) @@ -526,7 +526,9 @@ ;; but there are special cases for branches (which must be handled here) ;; and for compressed single instructions. (define_attr "length" "" - (cond [(and (eq_attr "compression" "micromips,all") + (cond [(and (ior (eq_attr "compression" "micromips,all") + (and (eq_attr "compression" "micromips32") + (eq_attr "mode" "SI,SF"))) (eq_attr "dword_mode" "no") (match_test "TARGET_MICROMIPS")) (const_int 2) @@ -979,8 +981,8 @@ (xor "xori") (and "andi")]) -(define_code_attr shift_compression [(ashift "micromips") - (lshiftrt "micromips") +(define_code_attr shift_compression [(ashift "micromips32") + (lshiftrt "micromips32") (ashiftrt "none")]) ;; <fcond> is the c.cond.fmt condition associated with a particular code. @@ -1163,7 +1165,7 @@ return "<d>addiu\t%0,%1,%2"; } [(set_attr "alu_type" "add") - (set_attr "compression" "micromips,*,micromips,micromips,micromips,micromips,*") + (set_attr "compression" "micromips32,*,micromips32,micromips32,micromips32,micromips32,*") (set_attr "mode" "<MODE>")]) (define_insn "*add<mode>3_mips16" @@ -1381,7 +1383,7 @@ "" "<d>subu\t%0,%1,%2" [(set_attr "alu_type" "sub") - (set_attr "compression" "micromips,*") + (set_attr "compression" "micromips32,*") (set_attr "mode" "<MODE>")]) (define_insn "*subsi3_extended" @@ -5955,14 +5957,12 @@ (label_ref (match_operand 0)))] "!TARGET_MIPS16 && TARGET_ABSOLUTE_JUMPS" { - /* Use a branch for microMIPS. The assembler will choose - a 16-bit branch, a 32-bit branch, or a 32-bit jump. */ - if (TARGET_MICROMIPS && !TARGET_ABICALLS_PIC2) + if (get_attr_length (insn) <= 8) return "%*b\t%l0%/"; else return MIPS_ABSOLUTE_JUMP ("%*j\t%l0%/"); } - [(set_attr "type" "jump")]) + [(set_attr "type" "branch")]) (define_insn "*jump_pic" [(set (pc) diff --git a/gcc/config/moxie/moxie.c b/gcc/config/moxie/moxie.c index d4688d9c2f8..148d26be1f5 100644 --- a/gcc/config/moxie/moxie.c +++ b/gcc/config/moxie/moxie.c @@ -528,13 +528,10 @@ moxie_arg_partial_bytes (cumulative_args_t cum_v, /* Worker function for TARGET_STATIC_CHAIN. */ static rtx -moxie_static_chain (const_tree fndecl, bool incoming_p) +moxie_static_chain (const_tree ARG_UNUSED (fndecl_or_type), bool incoming_p) { rtx addr, mem; - if (!DECL_STATIC_CHAIN (fndecl)) - return NULL; - if (incoming_p) addr = plus_constant (Pmode, arg_pointer_rtx, 2 * UNITS_PER_WORD); else diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index 31527624be4..ae3ffd12db1 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -12036,7 +12036,7 @@ s390_option_override (void) /* Implement TARGET_USE_BY_PIECES_INFRASTRUCTURE_P. */ static bool -s390_use_by_pieces_infrastructure_p (unsigned int size, +s390_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT size, unsigned int align ATTRIBUTE_UNUSED, enum by_pieces_operation op ATTRIBUTE_UNUSED, bool speed_p ATTRIBUTE_UNUSED) diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index 5bac2afbcbc..e4491210522 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -338,7 +338,7 @@ static void sh_conditional_register_usage (void); static bool sh_legitimate_constant_p (machine_mode, rtx); static int mov_insn_size (machine_mode, bool); static int mov_insn_alignment_mask (machine_mode, bool); -static bool sh_use_by_pieces_infrastructure_p (unsigned int, +static bool sh_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT, unsigned int, enum by_pieces_operation, bool); @@ -13680,7 +13680,7 @@ sh_mode_priority (int entity ATTRIBUTE_UNUSED, int n) /* Implement TARGET_USE_BY_PIECES_INFRASTRUCTURE_P. */ static bool -sh_use_by_pieces_infrastructure_p (unsigned int size, +sh_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT size, unsigned int align, enum by_pieces_operation op, bool speed_p) diff --git a/gcc/config/xtensa/xtensa.c b/gcc/config/xtensa/xtensa.c index 159a1a76468..a0025a51331 100644 --- a/gcc/config/xtensa/xtensa.c +++ b/gcc/config/xtensa/xtensa.c @@ -3626,7 +3626,7 @@ xtensa_function_value_regno_p (const unsigned int regno) expressions that denote where they are stored. */ static rtx -xtensa_static_chain (const_tree ARG_UNUSED (fndecl), bool incoming_p) +xtensa_static_chain (const_tree ARG_UNUSED (fndecl_or_type), bool incoming_p) { rtx base = incoming_p ? arg_pointer_rtx : stack_pointer_rtx; return gen_frame_mem (Pmode, plus_constant (Pmode, base, diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 117355975fa..5769d2af30e 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,39 @@ 2014-11-18 Jason Merrill <jason@redhat.com> + PR c++/63924 + * constexpr.c (cxx_eval_constant_expression) [PARM_DECL]: A load + from a variable of empty class type is constant. + + * constexpr.c (cxx_eval_statement_list): Handle statement-expressions. + (potential_constant_expression_1): Handle STMT_EXPR. + + * constexpr.c (cxx_eval_constant_expression): Give jump_target a + default argument. + (lots): Omit NULL jump_target arguments. + + * constexpr.c (struct constexpr_ctx): Add quiet field. + (cxx_eval_outermost_constant_expr, is_sub_constant_expr): Set it. + (lots): Replace allow_non_constant parameter with ctx->quiet. + + PR c++/63940 + * constexpr.c (cxx_eval_binary_expression): Don't assume the + expression was already folded. + (cxx_eval_unary_expression): Likewise. + +2014-11-18 Marc Glisse <marc.glisse@inria.fr> + + PR libstdc++/43622 + * rtti.c (emit_support_tinfos): Handle __float128. + +2014-11-18 Jason Merrill <jason@redhat.com> + + PR c++/63925 + * constexpr.c (cxx_eval_increment_expression): Use POINTER_PLUS_EXPR. + + PR c++/63934 + * constexpr.c (cxx_eval_call_expression): Check DECL_CONSTRUCTOR_P + rather than VOID_TYPE_P. + * pt.c (instantiate_template_1): Use tsubst_aggr_type for context. PR c++/58102 diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 2f0708b40ec..1303fdc4d08 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -36,7 +36,7 @@ along with GCC; see the file COPYING3. If not see static bool verify_constant (tree, bool, bool *, bool *); #define VERIFY_CONSTANT(X) \ do { \ - if (verify_constant ((X), allow_non_constant, non_constant_p, overflow_p)) \ + if (verify_constant ((X), ctx->quiet, non_constant_p, overflow_p)) \ return t; \ } while (0) @@ -863,6 +863,7 @@ struct constexpr_ctx { hash_map<tree,tree> *values; tree ctor; tree object; + bool quiet; }; /* A table of all constexpr calls that have been evaluated by the @@ -871,7 +872,7 @@ struct constexpr_ctx { static GTY (()) hash_table<constexpr_call_hasher> *constexpr_call_table; static tree cxx_eval_constant_expression (const constexpr_ctx *, tree, - bool, bool, bool *, bool *, tree *); + bool, bool *, bool *, tree * = NULL); /* Compute a hash value for a constexpr call representation. */ @@ -982,7 +983,7 @@ lookup_parameter_binding (const constexpr_call *call, tree t) static tree cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, - bool allow_non_constant, bool addr, + bool addr, bool *non_constant_p, bool *overflow_p) { const int nargs = call_expr_nargs (t); @@ -992,10 +993,9 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, for (i = 0; i < nargs; ++i) { args[i] = cxx_eval_constant_expression (ctx, CALL_EXPR_ARG (t, i), - allow_non_constant, addr, - non_constant_p, overflow_p, - NULL); - if (allow_non_constant && *non_constant_p) + addr, + non_constant_p, overflow_p); + if (ctx->quiet && *non_constant_p) return t; } if (*non_constant_p) @@ -1034,7 +1034,6 @@ adjust_temp_type (tree type, tree temp) static void cxx_bind_parameters_in_call (const constexpr_ctx *ctx, tree t, constexpr_call *new_call, - bool allow_non_constant, bool *non_constant_p, bool *overflow_p) { const int nargs = call_expr_nargs (t); @@ -1067,11 +1066,11 @@ cxx_bind_parameters_in_call (const constexpr_ctx *ctx, tree t, type = TREE_TYPE (type); x = convert_from_reference (x); } - arg = cxx_eval_constant_expression (ctx, x, allow_non_constant, + arg = cxx_eval_constant_expression (ctx, x, TREE_CODE (type) == REFERENCE_TYPE, - non_constant_p, overflow_p, NULL); + non_constant_p, overflow_p); /* Don't VERIFY_CONSTANT here. */ - if (*non_constant_p && allow_non_constant) + if (*non_constant_p && ctx->quiet) return; /* Just discard ellipsis args after checking their constantitude. */ if (!parms) @@ -1134,7 +1133,7 @@ cx_error_context (void) static tree cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, - bool allow_non_constant, bool addr, + bool addr, bool *non_constant_p, bool *overflow_p) { location_t loc = EXPR_LOC_OR_LOC (t, input_location); @@ -1148,16 +1147,16 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, if (TREE_CODE (fun) != FUNCTION_DECL) { /* Might be a constexpr function pointer. */ - fun = cxx_eval_constant_expression (ctx, fun, allow_non_constant, + fun = cxx_eval_constant_expression (ctx, fun, /*addr*/false, non_constant_p, - overflow_p, NULL); + overflow_p); STRIP_NOPS (fun); if (TREE_CODE (fun) == ADDR_EXPR) fun = TREE_OPERAND (fun, 0); } if (TREE_CODE (fun) != FUNCTION_DECL) { - if (!allow_non_constant && !*non_constant_p) + if (!ctx->quiet && !*non_constant_p) error_at (loc, "expression %qE does not designate a constexpr " "function", fun); *non_constant_p = true; @@ -1166,11 +1165,11 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, if (DECL_CLONED_FUNCTION_P (fun)) fun = DECL_CLONED_FUNCTION (fun); if (is_builtin_fn (fun)) - return cxx_eval_builtin_function_call (ctx, t, allow_non_constant, + return cxx_eval_builtin_function_call (ctx, t, addr, non_constant_p, overflow_p); if (!DECL_DECLARED_CONSTEXPR_P (fun)) { - if (!allow_non_constant) + if (!ctx->quiet) { error_at (loc, "call to non-constexpr function %qD", fun); explain_invalid_constexpr_fn (fun); @@ -1185,9 +1184,9 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, if (call_expr_nargs (t) == 2) { tree arg = convert_from_reference (get_nth_callarg (t, 1)); - return cxx_eval_constant_expression (ctx, arg, allow_non_constant, + return cxx_eval_constant_expression (ctx, arg, addr, non_constant_p, - overflow_p, NULL); + overflow_p); } else if (TREE_CODE (t) == AGGR_INIT_EXPR && AGGR_INIT_ZERO_FIRST (t)) @@ -1202,7 +1201,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, new_call.fundef = retrieve_constexpr_fundef (fun); if (new_call.fundef == NULL || new_call.fundef->body == NULL) { - if (!allow_non_constant) + if (!ctx->quiet) { if (DECL_INITIAL (fun)) { @@ -1232,7 +1231,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, } cxx_bind_parameters_in_call (ctx, t, &new_call, - allow_non_constant, non_constant_p, overflow_p); + non_constant_p, overflow_p); if (*non_constant_p) return t; @@ -1257,7 +1256,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, so that we can detect circular dependencies. */ else if (entry->result == NULL) { - if (!allow_non_constant) + if (!ctx->quiet) error ("call has circular dependency"); *non_constant_p = true; entry->result = result = error_mark_node; @@ -1265,7 +1264,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, if (!depth_ok) { - if (!allow_non_constant) + if (!ctx->quiet) error ("constexpr evaluation depth exceeds maximum of %d (use " "-fconstexpr-depth= to increase the maximum)", max_constexpr_depth); @@ -1282,8 +1281,8 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, new_ctx.call = &new_call; result = (cxx_eval_constant_expression (&new_ctx, new_call.fundef->body, - allow_non_constant, addr, - non_constant_p, overflow_p, NULL)); + addr, + non_constant_p, overflow_p)); } else { @@ -1324,11 +1323,11 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, ctx->values->put (res, NULL_TREE); tree jump_target = NULL_TREE; - cxx_eval_constant_expression (ctx, body, allow_non_constant, + cxx_eval_constant_expression (ctx, body, addr, non_constant_p, overflow_p, &jump_target); - if (VOID_TYPE_P (TREE_TYPE (res))) + if (DECL_CONSTRUCTOR_P (fun)) /* This can be null for a subobject constructor call, in which case what we care about is the initialization side-effects rather than the value. We could get at the @@ -1340,7 +1339,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, result = *ctx->values->get (slot ? slot : res); if (result == NULL_TREE) { - if (!allow_non_constant) + if (!ctx->quiet) error ("constexpr call flows off the end " "of the function"); *non_constant_p = true; @@ -1367,7 +1366,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, { /* If this was a call to initialize an object, set the type of the CONSTRUCTOR to the type of that object. */ - if (DECL_CONSTRUCTOR_P (fun)) + if (DECL_CONSTRUCTOR_P (fun) && !use_new_call) { tree ob_arg = get_nth_callarg (t, 0); STRIP_NOPS (ob_arg); @@ -1452,18 +1451,25 @@ verify_constant (tree t, bool allow_non_constant, bool *non_constant_p, static tree cxx_eval_unary_expression (const constexpr_ctx *ctx, tree t, - bool allow_non_constant, bool addr, + bool addr, bool *non_constant_p, bool *overflow_p) { tree r; tree orig_arg = TREE_OPERAND (t, 0); - tree arg = cxx_eval_constant_expression (ctx, orig_arg, allow_non_constant, - addr, non_constant_p, overflow_p, - NULL); + tree arg = cxx_eval_constant_expression (ctx, orig_arg, + addr, non_constant_p, overflow_p); VERIFY_CONSTANT (arg); - if (arg == orig_arg) - return t; - r = fold_build1 (TREE_CODE (t), TREE_TYPE (t), arg); + location_t loc = EXPR_LOCATION (t); + enum tree_code code = TREE_CODE (t); + tree type = TREE_TYPE (t); + r = fold_unary_loc (loc, code, type, arg); + if (r == NULL_TREE) + { + if (arg == orig_arg) + r = t; + else + r = build1_loc (loc, code, type, arg); + } VERIFY_CONSTANT (r); return r; } @@ -1473,7 +1479,7 @@ cxx_eval_unary_expression (const constexpr_ctx *ctx, tree t, static tree cxx_eval_binary_expression (const constexpr_ctx *ctx, tree t, - bool allow_non_constant, bool addr, + bool addr, bool *non_constant_p, bool *overflow_p) { tree r; @@ -1481,16 +1487,25 @@ cxx_eval_binary_expression (const constexpr_ctx *ctx, tree t, tree orig_rhs = TREE_OPERAND (t, 1); tree lhs, rhs; lhs = cxx_eval_constant_expression (ctx, orig_lhs, - allow_non_constant, addr, - non_constant_p, overflow_p, NULL); + addr, + non_constant_p, overflow_p); VERIFY_CONSTANT (lhs); rhs = cxx_eval_constant_expression (ctx, orig_rhs, - allow_non_constant, addr, - non_constant_p, overflow_p, NULL); + addr, + non_constant_p, overflow_p); VERIFY_CONSTANT (rhs); - if (lhs == orig_lhs && rhs == orig_rhs) - return t; - r = fold_build2 (TREE_CODE (t), TREE_TYPE (t), lhs, rhs); + + location_t loc = EXPR_LOCATION (t); + enum tree_code code = TREE_CODE (t); + tree type = TREE_TYPE (t); + r = fold_binary_loc (loc, code, type, lhs, rhs); + if (r == NULL_TREE) + { + if (lhs == orig_lhs && rhs == orig_rhs) + r = t; + else + r = build2_loc (loc, code, type, lhs, rhs); + } VERIFY_CONSTANT (r); return r; } @@ -1501,23 +1516,22 @@ cxx_eval_binary_expression (const constexpr_ctx *ctx, tree t, static tree cxx_eval_conditional_expression (const constexpr_ctx *ctx, tree t, - bool allow_non_constant, bool addr, + bool addr, bool *non_constant_p, bool *overflow_p, tree *jump_target) { tree val = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), - allow_non_constant, addr, - non_constant_p, overflow_p, - NULL); + addr, + non_constant_p, overflow_p); VERIFY_CONSTANT (val); /* Don't VERIFY_CONSTANT the other operands. */ if (integer_zerop (val)) return cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 2), - allow_non_constant, addr, + addr, non_constant_p, overflow_p, jump_target); return cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1), - allow_non_constant, addr, + addr, non_constant_p, overflow_p, jump_target); } @@ -1527,13 +1541,13 @@ cxx_eval_conditional_expression (const constexpr_ctx *ctx, tree t, static tree cxx_eval_array_reference (const constexpr_ctx *ctx, tree t, - bool allow_non_constant, bool addr, + bool addr, bool *non_constant_p, bool *overflow_p) { tree oldary = TREE_OPERAND (t, 0); tree ary = cxx_eval_constant_expression (ctx, oldary, - allow_non_constant, addr, - non_constant_p, overflow_p, NULL); + addr, + non_constant_p, overflow_p); tree index, oldidx; HOST_WIDE_INT i; tree elem_type; @@ -1542,8 +1556,8 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree t, return t; oldidx = TREE_OPERAND (t, 1); index = cxx_eval_constant_expression (ctx, oldidx, - allow_non_constant, false, - non_constant_p, overflow_p, NULL); + false, + non_constant_p, overflow_p); VERIFY_CONSTANT (index); if (addr && ary == oldary && index == oldidx) return t; @@ -1573,19 +1587,18 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree t, initializer, it's value-initialized. */ tree val = build_value_init (elem_type, tf_warning_or_error); return cxx_eval_constant_expression (ctx, val, - allow_non_constant, addr, - non_constant_p, overflow_p, - NULL); + addr, + non_constant_p, overflow_p); } - if (!allow_non_constant) + if (!ctx->quiet) error ("array subscript out of bound"); *non_constant_p = true; return t; } else if (tree_int_cst_lt (index, integer_zero_node)) { - if (!allow_non_constant) + if (!ctx->quiet) error ("negative array subscript"); *non_constant_p = true; return t; @@ -1611,7 +1624,7 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree t, static tree cxx_eval_component_reference (const constexpr_ctx *ctx, tree t, - bool allow_non_constant, bool addr, + bool addr, bool *non_constant_p, bool *overflow_p) { unsigned HOST_WIDE_INT i; @@ -1620,8 +1633,8 @@ cxx_eval_component_reference (const constexpr_ctx *ctx, tree t, tree part = TREE_OPERAND (t, 1); tree orig_whole = TREE_OPERAND (t, 0); tree whole = cxx_eval_constant_expression (ctx, orig_whole, - allow_non_constant, addr, - non_constant_p, overflow_p, NULL); + addr, + non_constant_p, overflow_p); if (whole == orig_whole) return t; if (addr) @@ -1631,13 +1644,13 @@ cxx_eval_component_reference (const constexpr_ctx *ctx, tree t, CONSTRUCTOR. */ if (!*non_constant_p && TREE_CODE (whole) != CONSTRUCTOR) { - if (!allow_non_constant) + if (!ctx->quiet) error ("%qE is not a constant expression", orig_whole); *non_constant_p = true; } if (DECL_MUTABLE_P (part)) { - if (!allow_non_constant) + if (!ctx->quiet) error ("mutable %qD is not usable in a constant expression", part); *non_constant_p = true; } @@ -1658,7 +1671,7 @@ cxx_eval_component_reference (const constexpr_ctx *ctx, tree t, && CONSTRUCTOR_NELTS (whole) > 0) { /* DR 1188 says we don't have to deal with this. */ - if (!allow_non_constant) + if (!ctx->quiet) error ("accessing %qD member instead of initialized %qD member in " "constant expression", part, CONSTRUCTOR_ELT (whole, 0)->index); *non_constant_p = true; @@ -1670,7 +1683,7 @@ cxx_eval_component_reference (const constexpr_ctx *ctx, tree t, /* 'whole' is part of the aggregate initializer we're currently building; if there's no initializer for this member yet, that's an error. */ - if (!allow_non_constant) + if (!ctx->quiet) error ("accessing uninitialized member %qD", part); *non_constant_p = true; return t; @@ -1679,8 +1692,8 @@ cxx_eval_component_reference (const constexpr_ctx *ctx, tree t, /* If there's no explicit init for this field, it's value-initialized. */ value = build_value_init (TREE_TYPE (t), tf_warning_or_error); return cxx_eval_constant_expression (ctx, value, - allow_non_constant, addr, - non_constant_p, overflow_p, NULL); + addr, + non_constant_p, overflow_p); } /* Subroutine of cxx_eval_constant_expression. @@ -1689,7 +1702,7 @@ cxx_eval_component_reference (const constexpr_ctx *ctx, tree t, static tree cxx_eval_bit_field_ref (const constexpr_ctx *ctx, tree t, - bool allow_non_constant, bool addr, + bool addr, bool *non_constant_p, bool *overflow_p) { tree orig_whole = TREE_OPERAND (t, 0); @@ -1697,8 +1710,8 @@ cxx_eval_bit_field_ref (const constexpr_ctx *ctx, tree t, bool fld_seen = false; HOST_WIDE_INT istart, isize; tree whole = cxx_eval_constant_expression (ctx, orig_whole, - allow_non_constant, addr, - non_constant_p, overflow_p, NULL); + addr, + non_constant_p, overflow_p); tree start, field, value; unsigned HOST_WIDE_INT i; @@ -1710,7 +1723,7 @@ cxx_eval_bit_field_ref (const constexpr_ctx *ctx, tree t, && TREE_CODE (whole) != VECTOR_CST && TREE_CODE (whole) != CONSTRUCTOR) { - if (!allow_non_constant) + if (!ctx->quiet) error ("%qE is not a constant expression", orig_whole); *non_constant_p = true; } @@ -1775,20 +1788,20 @@ cxx_eval_bit_field_ref (const constexpr_ctx *ctx, tree t, static tree cxx_eval_logical_expression (const constexpr_ctx *ctx, tree t, tree bailout_value, tree continue_value, - bool allow_non_constant, bool addr, + bool addr, bool *non_constant_p, bool *overflow_p) { tree r; tree lhs = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), - allow_non_constant, addr, - non_constant_p, overflow_p, NULL); + addr, + non_constant_p, overflow_p); VERIFY_CONSTANT (lhs); if (tree_int_cst_equal (lhs, bailout_value)) return lhs; gcc_assert (tree_int_cst_equal (lhs, continue_value)); r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1), - allow_non_constant, addr, non_constant_p, - overflow_p, NULL); + addr, non_constant_p, + overflow_p); VERIFY_CONSTANT (r); return r; } @@ -1909,7 +1922,7 @@ verify_ctor_sanity (const constexpr_ctx *ctx, tree type) static tree cxx_eval_bare_aggregate (const constexpr_ctx *ctx, tree t, - bool allow_non_constant, bool addr, + bool addr, bool *non_constant_p, bool *overflow_p) { vec<constructor_elt, va_gc> *v = CONSTRUCTOR_ELTS (t); @@ -1930,11 +1943,10 @@ cxx_eval_bare_aggregate (const constexpr_ctx *ctx, tree t, initializers can refer to it. */ CONSTRUCTOR_APPEND_ELT (*p, index, new_ctx.ctor); tree elt = cxx_eval_constant_expression (&new_ctx, value, - allow_non_constant, addr, - non_constant_p, overflow_p, - NULL); + addr, + non_constant_p, overflow_p); /* Don't VERIFY_CONSTANT here. */ - if (allow_non_constant && *non_constant_p) + if (ctx->quiet && *non_constant_p) break; if (elt != value) changed = true; @@ -1990,7 +2002,7 @@ cxx_eval_bare_aggregate (const constexpr_ctx *ctx, tree t, static tree cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init, - bool value_init, bool allow_non_constant, bool addr, + bool value_init, bool addr, bool *non_constant_p, bool *overflow_p) { tree elttype = TREE_TYPE (atype); @@ -2041,7 +2053,7 @@ cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init, eltinit = cp_build_array_ref (input_location, init, idx, tf_warning_or_error); eltinit = cxx_eval_vec_init_1 (&new_ctx, elttype, eltinit, value_init, - allow_non_constant, addr, + addr, non_constant_p, overflow_p); } else if (pre_init) @@ -2049,8 +2061,8 @@ cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init, /* Initializing an element using value or default initialization we just pre-built above. */ eltinit = (cxx_eval_constant_expression - (&new_ctx, init, allow_non_constant, - addr, non_constant_p, overflow_p, NULL)); + (&new_ctx, init, + addr, non_constant_p, overflow_p)); } else { @@ -2063,10 +2075,10 @@ cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init, eltinit = move (eltinit); eltinit = force_rvalue (eltinit, tf_warning_or_error); eltinit = (cxx_eval_constant_expression - (&new_ctx, eltinit, allow_non_constant, addr, - non_constant_p, overflow_p, NULL)); + (&new_ctx, eltinit, addr, + non_constant_p, overflow_p)); } - if (*non_constant_p && !allow_non_constant) + if (*non_constant_p && !ctx->quiet) break; if (new_ctx.ctor != ctx->ctor) { @@ -2088,14 +2100,14 @@ cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init, static tree cxx_eval_vec_init (const constexpr_ctx *ctx, tree t, - bool allow_non_constant, bool addr, + bool addr, bool *non_constant_p, bool *overflow_p) { tree atype = TREE_TYPE (t); tree init = VEC_INIT_EXPR_INIT (t); tree r = cxx_eval_vec_init_1 (ctx, atype, init, VEC_INIT_EXPR_VALUE_INIT (t), - allow_non_constant, addr, non_constant_p, overflow_p); + addr, non_constant_p, overflow_p); if (*non_constant_p) return t; else @@ -2295,13 +2307,13 @@ cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base) static tree cxx_eval_indirect_ref (const constexpr_ctx *ctx, tree t, - bool allow_non_constant, bool addr, + bool addr, bool *non_constant_p, bool *overflow_p) { tree orig_op0 = TREE_OPERAND (t, 0); - tree op0 = cxx_eval_constant_expression (ctx, orig_op0, allow_non_constant, + tree op0 = cxx_eval_constant_expression (ctx, orig_op0, /*addr*/false, non_constant_p, - overflow_p, NULL); + overflow_p); bool empty_base = false; tree r; @@ -2313,8 +2325,8 @@ cxx_eval_indirect_ref (const constexpr_ctx *ctx, tree t, &empty_base); if (r) - r = cxx_eval_constant_expression (ctx, r, allow_non_constant, - addr, non_constant_p, overflow_p, NULL); + r = cxx_eval_constant_expression (ctx, r, + addr, non_constant_p, overflow_p); else { tree sub = op0; @@ -2326,7 +2338,7 @@ cxx_eval_indirect_ref (const constexpr_ctx *ctx, tree t, gcc_assert (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (TREE_TYPE (sub)), TREE_TYPE (t))); /* DR 1188 says we don't have to deal with this. */ - if (!allow_non_constant) + if (!ctx->quiet) error ("accessing value of %qE through a %qT glvalue in a " "constant expression", build_fold_indirect_ref (sub), TREE_TYPE (t)); @@ -2405,7 +2417,7 @@ non_const_var_error (tree r) static tree cxx_eval_trinary_expression (const constexpr_ctx *ctx, tree t, - bool allow_non_constant, bool addr, + bool addr, bool *non_constant_p, bool *overflow_p) { int i; @@ -2415,9 +2427,8 @@ cxx_eval_trinary_expression (const constexpr_ctx *ctx, tree t, for (i = 0; i < 3; i++) { args[i] = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, i), - allow_non_constant, addr, - non_constant_p, overflow_p, - NULL); + addr, + non_constant_p, overflow_p); VERIFY_CONSTANT (args[i]); } @@ -2441,7 +2452,7 @@ var_in_constexpr_fn (tree t) static tree cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, - bool allow_non_constant, bool addr, + bool addr, bool *non_constant_p, bool *overflow_p) { constexpr_ctx new_ctx = *ctx; @@ -2449,8 +2460,8 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, /* First we figure out where we're storing to. */ tree target = TREE_OPERAND (t, 0); target = cxx_eval_constant_expression (ctx, target, - allow_non_constant, true, - non_constant_p, overflow_p, NULL); + true, + non_constant_p, overflow_p); if (*non_constant_p) return t; @@ -2482,7 +2493,7 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, { /* A constant-expression cannot modify objects from outside the constant-expression. */ - if (!allow_non_constant) + if (!ctx->quiet) error ("modification of %qD is not a constant-expression", object); *non_constant_p = true; return t; @@ -2525,8 +2536,8 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, } tree init = cxx_eval_constant_expression (&new_ctx, TREE_OPERAND (t, 1), - allow_non_constant, false, - non_constant_p, overflow_p, NULL); + false, + non_constant_p, overflow_p); if (target == object) /* The hash table might have moved since the get earlier. */ ctx->values->put (object, init); @@ -2545,7 +2556,7 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t, static tree cxx_eval_increment_expression (const constexpr_ctx *ctx, tree t, - bool allow_non_constant, bool addr, + bool addr, bool *non_constant_p, bool *overflow_p) { enum tree_code code = TREE_CODE (t); @@ -2555,25 +2566,34 @@ cxx_eval_increment_expression (const constexpr_ctx *ctx, tree t, gcc_assert (TREE_CONSTANT (offset)); /* The operand as an lvalue. */ - op = cxx_eval_constant_expression (ctx, op, allow_non_constant, true, - non_constant_p, overflow_p, NULL); + op = cxx_eval_constant_expression (ctx, op, true, + non_constant_p, overflow_p); /* The operand as an rvalue. */ tree val = rvalue (op); - val = cxx_eval_constant_expression (ctx, val, allow_non_constant, false, - non_constant_p, overflow_p, NULL); + val = cxx_eval_constant_expression (ctx, val, false, + non_constant_p, overflow_p); VERIFY_CONSTANT (val); /* The modified value. */ bool inc = (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR); - tree mod = fold_build2 (inc ? PLUS_EXPR : MINUS_EXPR, - type, val, offset); + tree mod; + if (POINTER_TYPE_P (type)) + { + /* The middle end requires pointers to use POINTER_PLUS_EXPR. */ + offset = convert_to_ptrofftype (offset); + if (!inc) + offset = fold_build1 (NEGATE_EXPR, TREE_TYPE (offset), offset); + mod = fold_build2 (POINTER_PLUS_EXPR, type, val, offset); + } + else + mod = fold_build2 (inc ? PLUS_EXPR : MINUS_EXPR, type, val, offset); VERIFY_CONSTANT (mod); /* Storing the modified value. */ tree store = build2 (MODIFY_EXPR, type, op, mod); - cxx_eval_constant_expression (ctx, store, allow_non_constant, - true, non_constant_p, overflow_p, NULL); + cxx_eval_constant_expression (ctx, store, + true, non_constant_p, overflow_p); /* And the value of the expression. */ if (code == PREINCREMENT_EXPR || code == PREDECREMENT_EXPR) @@ -2660,12 +2680,19 @@ label_matches (tree *jump_target, tree_stmt_iterator i, static tree cxx_eval_statement_list (const constexpr_ctx *ctx, tree t, - bool allow_non_constant, bool *non_constant_p, bool *overflow_p, tree *jump_target) { tree_stmt_iterator i; tree_stmt_iterator default_label = tree_stmt_iterator(); + tree local_target; + /* In a statement-expression we want to return the last value. */ + tree r = NULL_TREE; + if (!jump_target) + { + local_target = NULL_TREE; + jump_target = &local_target; + } for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i)) { reenter: @@ -2680,10 +2707,9 @@ cxx_eval_statement_list (const constexpr_ctx *ctx, tree t, else continue; } - cxx_eval_constant_expression (ctx, stmt, - allow_non_constant, false, - non_constant_p, overflow_p, - jump_target); + r = cxx_eval_constant_expression (ctx, stmt, false, + non_constant_p, overflow_p, + jump_target); if (*non_constant_p) break; if (returns (jump_target) || breaks (jump_target)) @@ -2695,7 +2721,7 @@ cxx_eval_statement_list (const constexpr_ctx *ctx, tree t, *jump_target = NULL_TREE; goto reenter; } - return NULL_TREE; + return r; } /* Evaluate a LOOP_EXPR for side-effects. Handles break and return @@ -2703,14 +2729,13 @@ cxx_eval_statement_list (const constexpr_ctx *ctx, tree t, static tree cxx_eval_loop_expr (const constexpr_ctx *ctx, tree t, - bool allow_non_constant, bool *non_constant_p, bool *overflow_p, tree *jump_target) { tree body = TREE_OPERAND (t, 0); while (true) { - cxx_eval_statement_list (ctx, body, allow_non_constant, + cxx_eval_statement_list (ctx, body, non_constant_p, overflow_p, jump_target); if (returns (jump_target) || breaks (jump_target)) break; @@ -2725,18 +2750,17 @@ cxx_eval_loop_expr (const constexpr_ctx *ctx, tree t, static tree cxx_eval_switch_expr (const constexpr_ctx *ctx, tree t, - bool allow_non_constant, bool *non_constant_p, bool *overflow_p, tree *jump_target) { tree cond = TREE_OPERAND (t, 0); - cond = cxx_eval_constant_expression (ctx, cond, allow_non_constant, false, - non_constant_p, overflow_p, NULL); + cond = cxx_eval_constant_expression (ctx, cond, false, + non_constant_p, overflow_p); VERIFY_CONSTANT (cond); *jump_target = cond; tree body = TREE_OPERAND (t, 1); - cxx_eval_statement_list (ctx, body, allow_non_constant, + cxx_eval_statement_list (ctx, body, non_constant_p, overflow_p, jump_target); if (breaks (jump_target) || switches (jump_target)) *jump_target = NULL_TREE; @@ -2750,7 +2774,7 @@ cxx_eval_switch_expr (const constexpr_ctx *ctx, tree t, static tree cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, - bool allow_non_constant, bool addr, + bool addr, bool *non_constant_p, bool *overflow_p, tree *jump_target) { @@ -2766,7 +2790,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, { if (TREE_CODE (t) == PTRMEM_CST) t = cplus_expand_constant (t); - else if (TREE_OVERFLOW (t) && (!flag_permissive || allow_non_constant)) + else if (TREE_OVERFLOW (t) && (!flag_permissive || ctx->quiet)) *overflow_p = true; return t; } @@ -2798,7 +2822,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, r = *p; if (DECL_P (r)) { - if (!allow_non_constant) + if (!ctx->quiet) non_const_var_error (r); *non_constant_p = true; } @@ -2821,9 +2845,15 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, r = *p; else if (addr) /* Defer in case this is only used for its type. */; + else if (is_empty_class (TREE_TYPE (t))) + { + /* If the class is empty, we aren't actually loading anything. */ + r = build_constructor (TREE_TYPE (t), NULL); + TREE_CONSTANT (r) = true; + } else { - if (!allow_non_constant) + if (!ctx->quiet) error ("%qE is not a constant expression", t); *non_constant_p = true; } @@ -2831,7 +2861,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, case CALL_EXPR: case AGGR_INIT_EXPR: - r = cxx_eval_call_expression (ctx, t, allow_non_constant, addr, + r = cxx_eval_call_expression (ctx, t, addr, non_constant_p, overflow_p); break; @@ -2852,9 +2882,8 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, if (tree init = DECL_INITIAL (r)) { init = cxx_eval_constant_expression (ctx, init, - allow_non_constant, false, - non_constant_p, overflow_p, - NULL); + false, + non_constant_p, overflow_p); ctx->values->put (r, init); } else if (ctx == &new_ctx) @@ -2867,7 +2896,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, case TARGET_EXPR: if (!literal_type_p (TREE_TYPE (t))) { - if (!allow_non_constant) + if (!ctx->quiet) { error ("temporary of non-literal type %qT in a " "constant expression", TREE_TYPE (t)); @@ -2891,8 +2920,8 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, /* Pass false for 'addr' because this indicates initialization of a temporary. */ r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1), - allow_non_constant, false, - non_constant_p, overflow_p, NULL); + false, + non_constant_p, overflow_p); if (!*non_constant_p) /* Adjust the type of the result to the type of the temporary. */ r = adjust_temp_type (TREE_TYPE (t), r); @@ -2904,26 +2933,26 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, /* In C++11 constexpr evaluation we are looking for the value, not the side-effect of the initialization. */ r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1), - allow_non_constant, false, - non_constant_p, overflow_p, NULL); + false, + non_constant_p, overflow_p); break; } /* else fall through */ case MODIFY_EXPR: - r = cxx_eval_store_expression (ctx, t, allow_non_constant, addr, + r = cxx_eval_store_expression (ctx, t, addr, non_constant_p, overflow_p); break; case SCOPE_REF: r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1), - allow_non_constant, addr, - non_constant_p, overflow_p, NULL); + addr, + non_constant_p, overflow_p); break; case RETURN_EXPR: r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), - allow_non_constant, addr, - non_constant_p, overflow_p, NULL); + addr, + non_constant_p, overflow_p); *jump_target = t; break; @@ -2935,7 +2964,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, case EXPR_STMT: case EH_SPEC_BLOCK: r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), - allow_non_constant, addr, + addr, non_constant_p, overflow_p, jump_target); break; @@ -2944,7 +2973,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, check for a constant operand or result; an address can be constant without its operand being, and vice versa. */ case INDIRECT_REF: - r = cxx_eval_indirect_ref (ctx, t, allow_non_constant, addr, + r = cxx_eval_indirect_ref (ctx, t, addr, non_constant_p, overflow_p); break; @@ -2952,10 +2981,8 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, { tree oldop = TREE_OPERAND (t, 0); tree op = cxx_eval_constant_expression (ctx, oldop, - allow_non_constant, /*addr*/true, - non_constant_p, overflow_p, - NULL); + non_constant_p, overflow_p); /* Don't VERIFY_CONSTANT here. */ if (*non_constant_p) return t; @@ -2976,7 +3003,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, case BIT_NOT_EXPR: case TRUTH_NOT_EXPR: case FIXED_CONVERT_EXPR: - r = cxx_eval_unary_expression (ctx, t, allow_non_constant, addr, + r = cxx_eval_unary_expression (ctx, t, addr, non_constant_p, overflow_p); break; @@ -3005,17 +3032,17 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, STRIP_NOPS (op1); if ((TREE_CODE (op0) == TARGET_EXPR && op1 == TARGET_EXPR_SLOT (op0)) || TREE_CODE (op1) == EMPTY_CLASS_EXPR) - r = cxx_eval_constant_expression (ctx, op0, allow_non_constant, + r = cxx_eval_constant_expression (ctx, op0, addr, non_constant_p, overflow_p, jump_target); else { /* Check that the LHS is constant and then discard it. */ - cxx_eval_constant_expression (ctx, op0, allow_non_constant, + cxx_eval_constant_expression (ctx, op0, false, non_constant_p, overflow_p, jump_target); op1 = TREE_OPERAND (t, 1); - r = cxx_eval_constant_expression (ctx, op1, allow_non_constant, + r = cxx_eval_constant_expression (ctx, op1, addr, non_constant_p, overflow_p, jump_target); } @@ -3061,7 +3088,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, case LTGT_EXPR: case RANGE_EXPR: case COMPLEX_EXPR: - r = cxx_eval_binary_expression (ctx, t, allow_non_constant, addr, + r = cxx_eval_binary_expression (ctx, t, addr, non_constant_p, overflow_p); break; @@ -3071,7 +3098,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, case TRUTH_ANDIF_EXPR: r = cxx_eval_logical_expression (ctx, t, boolean_false_node, boolean_true_node, - allow_non_constant, addr, + addr, non_constant_p, overflow_p); break; @@ -3079,12 +3106,12 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, case TRUTH_ORIF_EXPR: r = cxx_eval_logical_expression (ctx, t, boolean_true_node, boolean_false_node, - allow_non_constant, addr, + addr, non_constant_p, overflow_p); break; case ARRAY_REF: - r = cxx_eval_array_reference (ctx, t, allow_non_constant, addr, + r = cxx_eval_array_reference (ctx, t, addr, non_constant_p, overflow_p); break; @@ -3095,28 +3122,28 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, 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 || errorcount); + gcc_checking_assert (ctx->quiet || errorcount); *non_constant_p = true; return t; } - r = cxx_eval_component_reference (ctx, t, allow_non_constant, addr, + r = cxx_eval_component_reference (ctx, t, addr, non_constant_p, overflow_p); break; case BIT_FIELD_REF: - r = cxx_eval_bit_field_ref (ctx, t, allow_non_constant, addr, + r = cxx_eval_bit_field_ref (ctx, t, addr, non_constant_p, overflow_p); break; case COND_EXPR: case VEC_COND_EXPR: - r = cxx_eval_conditional_expression (ctx, t, allow_non_constant, addr, + r = cxx_eval_conditional_expression (ctx, t, addr, non_constant_p, overflow_p, jump_target); break; case CONSTRUCTOR: - r = cxx_eval_bare_aggregate (ctx, t, allow_non_constant, addr, + r = cxx_eval_bare_aggregate (ctx, t, addr, non_constant_p, overflow_p); break; @@ -3126,13 +3153,13 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, be NULL, meaning default-initialization, or it will be an lvalue or xvalue of the same type, meaning direct-initialization from the corresponding member. */ - r = cxx_eval_vec_init (ctx, t, allow_non_constant, addr, + r = cxx_eval_vec_init (ctx, t, addr, non_constant_p, overflow_p); break; case FMA_EXPR: case VEC_PERM_EXPR: - r = cxx_eval_trinary_expression (ctx, t, allow_non_constant, addr, + r = cxx_eval_trinary_expression (ctx, t, addr, non_constant_p, overflow_p); break; @@ -3142,16 +3169,15 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, { tree oldop = TREE_OPERAND (t, 0); tree op = cxx_eval_constant_expression (ctx, oldop, - allow_non_constant, addr, - non_constant_p, overflow_p, - NULL); + addr, + non_constant_p, overflow_p); if (*non_constant_p) return t; if (POINTER_TYPE_P (TREE_TYPE (t)) && TREE_CODE (op) == INTEGER_CST && !integer_zerop (op)) { - if (!allow_non_constant) + if (!ctx->quiet) error_at (EXPR_LOC_OR_LOC (t, input_location), "reinterpret_cast from integer to pointer"); *non_constant_p = true; @@ -3178,12 +3204,12 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, case STATEMENT_LIST: new_ctx = *ctx; new_ctx.ctor = new_ctx.object = NULL_TREE; - return cxx_eval_statement_list (&new_ctx, t, allow_non_constant, + return cxx_eval_statement_list (&new_ctx, t, non_constant_p, overflow_p, jump_target); case BIND_EXPR: return cxx_eval_constant_expression (ctx, BIND_EXPR_BODY (t), - allow_non_constant, addr, + addr, non_constant_p, overflow_p, jump_target); @@ -3191,7 +3217,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, case POSTINCREMENT_EXPR: case PREDECREMENT_EXPR: case POSTDECREMENT_EXPR: - return cxx_eval_increment_expression (ctx, t, allow_non_constant, + return cxx_eval_increment_expression (ctx, t, addr, non_constant_p, overflow_p); case LAMBDA_EXPR: @@ -3208,7 +3234,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, case NON_DEPENDENT_EXPR: case BASELINK: case OFFSET_REF: - if (!allow_non_constant) + if (!ctx->quiet) error_at (EXPR_LOC_OR_LOC (t, input_location), "expression %qE is not a constant-expression", t); *non_constant_p = true; @@ -3220,7 +3246,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, /* A placeholder without a referent. We can get here when checking whether NSDMIs are noexcept, or in massage_init_elt; just say it's non-constant for now. */ - gcc_assert (allow_non_constant); + gcc_assert (ctx->quiet); *non_constant_p = true; break; } @@ -3233,8 +3259,8 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, gcc_assert (same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (t), TREE_TYPE (ctor))); return cxx_eval_constant_expression - (ctx, ctor, allow_non_constant, addr, - non_constant_p, overflow_p, NULL); + (ctx, ctor, addr, + non_constant_p, overflow_p); } break; @@ -3244,12 +3270,12 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, break; case LOOP_EXPR: - cxx_eval_loop_expr (ctx, t, allow_non_constant, + cxx_eval_loop_expr (ctx, t, non_constant_p, overflow_p, jump_target); break; case SWITCH_EXPR: - cxx_eval_switch_expr (ctx, t, allow_non_constant, + cxx_eval_switch_expr (ctx, t, non_constant_p, overflow_p, jump_target); break; @@ -3275,7 +3301,7 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant, { bool non_constant_p = false; bool overflow_p = false; - constexpr_ctx ctx = { NULL, NULL, NULL, NULL }; + constexpr_ctx ctx = { NULL, NULL, NULL, NULL, allow_non_constant }; hash_map<tree,tree> map; ctx.values = ↦ tree type = initialized_type (t); @@ -3310,8 +3336,8 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant, r = TARGET_EXPR_INITIAL (r); } - r = cxx_eval_constant_expression (&ctx, r, allow_non_constant, - false, &non_constant_p, &overflow_p, NULL); + r = cxx_eval_constant_expression (&ctx, r, + false, &non_constant_p, &overflow_p); verify_constant (r, allow_non_constant, &non_constant_p, &overflow_p); @@ -3384,11 +3410,11 @@ is_sub_constant_expr (tree t) { bool non_constant_p = false; bool overflow_p = false; - constexpr_ctx ctx = { NULL, NULL, NULL, NULL }; + constexpr_ctx ctx = { NULL, NULL, NULL, NULL, true }; hash_map <tree, tree> map; ctx.values = ↦ - cxx_eval_constant_expression (&ctx, t, true, false, &non_constant_p, - &overflow_p, NULL); + cxx_eval_constant_expression (&ctx, t, false, &non_constant_p, + &overflow_p); return !non_constant_p && !overflow_p; } @@ -3872,6 +3898,9 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) return false; return true; + case STMT_EXPR: + return potential_constant_expression_1 (STMT_EXPR_STMT (t), rval, flags); + case LAMBDA_EXPR: case DYNAMIC_CAST_EXPR: case PSEUDO_DTOR_EXPR: @@ -3887,7 +3916,6 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) /* GCC internal stuff. */ case VA_ARG_EXPR: case OBJ_TYPE_REF: - case STMT_EXPR: case TRANSACTION_EXPR: case ASM_EXPR: fail: diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c index 0d6dd960003..aef71f27bc5 100644 --- a/gcc/cp/rtti.c +++ b/gcc/cp/rtti.c @@ -1547,6 +1547,8 @@ emit_support_tinfos (void) emit_support_tinfo_1 (int_n_trees[ix].signed_type); emit_support_tinfo_1 (int_n_trees[ix].unsigned_type); } + for (tree t = registered_builtin_types; t; t = TREE_CHAIN (t)) + emit_support_tinfo_1 (TREE_VALUE (t)); } /* Finish a type info decl. DECL_PTR is a pointer to an unemitted diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index d10a815a977..7178c9a7e8e 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -8913,6 +8913,7 @@ in the Cilk Plus language manual which can be found at @node Other Builtins @section Other Built-in Functions Provided by GCC @cindex built-in functions +@findex __builtin_call_with_static_chain @findex __builtin_fpclassify @findex __builtin_isfinite @findex __builtin_isnormal @@ -9501,6 +9502,18 @@ depending on the arguments' types. For example: @end deftypefn +@deftypefn {Built-in Function} @var{type} __builtin_call_with_static_chain (@var{call_exp}, @var{pointer_exp}) + +The @var{call_exp} expression must be a function call, and the +@var{pointer_exp} expression must be a pointer. The @var{pointer_exp} +is passed to the function call in the target's static chain location. +The result of builtin is the result of the function call. + +@emph{Note:} This builtin is only available for C@. +This builtin can be used to call Go closures from C. + +@end deftypefn + @deftypefn {Built-in Function} @var{type} __builtin_choose_expr (@var{const_exp}, @var{exp1}, @var{exp2}) You can use the built-in function @code{__builtin_choose_expr} to diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index c09c51030ef..5b9da4776a1 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -3462,7 +3462,7 @@ If the static chain is passed in memory, these macros should not be defined; instead, the @code{TARGET_STATIC_CHAIN} hook should be used. @end defmac -@deftypefn {Target Hook} rtx TARGET_STATIC_CHAIN (const_tree @var{fndecl}, bool @var{incoming_p}) +@deftypefn {Target Hook} rtx TARGET_STATIC_CHAIN (const_tree @var{fndecl_or_type}, bool @var{incoming_p}) This hook replaces the use of @code{STATIC_CHAIN_REGNUM} et al for targets that may use different static chain locations for different nested functions. This may be required if the target has function @@ -6205,7 +6205,7 @@ optimized for speed rather than size. If you don't define this, a reasonable default is used. @end defmac -@deftypefn {Target Hook} bool TARGET_USE_BY_PIECES_INFRASTRUCTURE_P (unsigned int @var{size}, unsigned int @var{alignment}, enum by_pieces_operation @var{op}, bool @var{speed_p}) +@deftypefn {Target Hook} bool TARGET_USE_BY_PIECES_INFRASTRUCTURE_P (unsigned HOST_WIDE_INT @var{size}, unsigned int @var{alignment}, enum by_pieces_operation @var{op}, bool @var{speed_p}) GCC will attempt several strategies when asked to copy between two areas of memory, or to set, clear or store to memory, for example when copying a @code{struct}. The @code{by_pieces} infrastructure diff --git a/gcc/fold-const.c b/gcc/fold-const.c index f6fb8af8084..9183430205b 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -408,9 +408,11 @@ negate_expr_p (tree t) && TYPE_OVERFLOW_WRAPS (type)); case FIXED_CST: - case NEGATE_EXPR: return true; + case NEGATE_EXPR: + return !TYPE_OVERFLOW_SANITIZED (type); + case REAL_CST: /* We want to canonicalize to positive real constants. Pretend that only negative ones can be easily negated. */ @@ -555,7 +557,8 @@ fold_negate_expr (location_t loc, tree t) tem = fold_negate_const (t, type); if (TREE_OVERFLOW (tem) == TREE_OVERFLOW (t) || (!TYPE_OVERFLOW_TRAPS (type) - && (flag_sanitize & SANITIZE_SI_OVERFLOW) == 0)) + && TYPE_OVERFLOW_WRAPS (type)) + || (flag_sanitize & SANITIZE_SI_OVERFLOW) == 0) return tem; break; diff --git a/gcc/gimple-builder.c b/gcc/gimple-builder.c index a7c6c4e9635..c5c9938b81a 100644 --- a/gcc/gimple-builder.c +++ b/gcc/gimple-builder.c @@ -120,7 +120,7 @@ build_type_cast (tree to_type, tree op, tree lhs) { if (lhs == NULL_TREE) lhs = make_ssa_name (to_type, NULL); - return gimple_build_assign_with_ops (NOP_EXPR, lhs, op, NULL_TREE); + return gimple_build_assign_with_ops (NOP_EXPR, lhs, op); } gassign * diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index fb87b7f053f..8e0c9e055ef 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -2723,6 +2723,27 @@ gimple_fold_call (gimple_stmt_iterator *gsi, bool inplace) } } + /* Check for indirect calls that became direct calls, and then + no longer require a static chain. */ + if (gimple_call_chain (stmt)) + { + tree fn = gimple_call_fndecl (stmt); + if (fn && !DECL_STATIC_CHAIN (fn)) + { + gimple_call_set_chain (stmt, NULL); + changed = true; + } + else + { + tree tmp = maybe_fold_reference (gimple_call_chain (stmt), false); + if (tmp) + { + gimple_call_set_chain (stmt, tmp); + changed = true; + } + } + } + if (inplace) return changed; @@ -2962,8 +2983,7 @@ replace_stmt_with_simplification (gimple_stmt_iterator *gsi, maybe_build_generic_op (rcode, TREE_TYPE (gimple_assign_lhs (stmt)), &ops[0], ops[1], ops[2]); - gimple_assign_set_rhs_with_ops_1 (gsi, rcode, - ops[0], ops[1], ops[2]); + gimple_assign_set_rhs_with_ops (gsi, rcode, ops[0], ops[1], ops[2]); if (dump_file && (dump_flags & TDF_DETAILS)) { fprintf (dump_file, "gimple_simplified to "); @@ -5627,8 +5647,8 @@ rewrite_to_defined_overflow (gimple stmt) if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR) gimple_assign_set_rhs_code (stmt, PLUS_EXPR); gimple_seq_add_stmt (&stmts, stmt); - gimple cvt = gimple_build_assign_with_ops - (NOP_EXPR, lhs, gimple_assign_lhs (stmt), NULL_TREE); + gimple cvt = gimple_build_assign_with_ops (NOP_EXPR, lhs, + gimple_assign_lhs (stmt)); gimple_seq_add_stmt (&stmts, cvt); return stmts; @@ -5658,10 +5678,9 @@ gimple_build (gimple_seq *seq, location_t loc, || code == IMAGPART_EXPR || code == VIEW_CONVERT_EXPR) stmt = gimple_build_assign_with_ops (code, res, - build1 (code, type, - op0), NULL_TREE); + build1 (code, type, op0)); else - stmt = gimple_build_assign_with_ops (code, res, op0, NULL_TREE); + stmt = gimple_build_assign_with_ops (code, res, op0); gimple_set_location (stmt, loc); gimple_seq_add_stmt_without_update (seq, stmt); } @@ -5716,8 +5735,7 @@ gimple_build (gimple_seq *seq, location_t loc, if (code == BIT_FIELD_REF) stmt = gimple_build_assign_with_ops (code, res, build3 (BIT_FIELD_REF, type, - op0, op1, op2), - NULL_TREE); + op0, op1, op2)); else stmt = gimple_build_assign_with_ops (code, res, op0, op1, op2); gimple_set_location (stmt, loc); diff --git a/gcc/gimple-ssa-strength-reduction.c b/gcc/gimple-ssa-strength-reduction.c index b49e819a39e..e719129df24 100644 --- a/gcc/gimple-ssa-strength-reduction.c +++ b/gcc/gimple-ssa-strength-reduction.c @@ -3264,8 +3264,7 @@ introduce_cast_before_cand (slsr_cand_t c, tree to_type, tree from_expr) gimple_stmt_iterator gsi = gsi_for_stmt (c->cand_stmt); cast_lhs = make_temp_ssa_name (to_type, NULL, "slsr"); - cast_stmt = gimple_build_assign_with_ops (NOP_EXPR, cast_lhs, - from_expr, NULL_TREE); + cast_stmt = gimple_build_assign_with_ops (NOP_EXPR, cast_lhs, from_expr); gimple_set_location (cast_stmt, gimple_location (c->cand_stmt)); gsi_insert_before (&gsi, cast_stmt, GSI_SAME_STMT); @@ -3434,10 +3433,8 @@ replace_one_candidate (slsr_cand_t c, unsigned i, tree basis_name) else { gimple_stmt_iterator gsi = gsi_for_stmt (c->cand_stmt); - gassign *cast_stmt - = gimple_build_assign_with_ops (NOP_EXPR, lhs, - basis_name, - NULL_TREE); + gassign *cast_stmt = gimple_build_assign_with_ops (NOP_EXPR, lhs, + basis_name); gimple_set_location (cast_stmt, gimple_location (c->cand_stmt)); gsi_replace (&gsi, cast_stmt, false); c->cand_stmt = cast_stmt; diff --git a/gcc/gimple.c b/gcc/gimple.c index 6b908bfd1a1..69cac22a2b3 100644 --- a/gcc/gimple.c +++ b/gcc/gimple.c @@ -453,6 +453,14 @@ gimple_build_assign_with_ops (enum tree_code subcode, tree lhs, tree op1, PASS_MEM_STAT); } +gassign * +gimple_build_assign_with_ops (enum tree_code subcode, tree lhs, tree op1 + MEM_STAT_DECL) +{ + return gimple_build_assign_with_ops (subcode, lhs, op1, NULL_TREE, NULL_TREE + PASS_MEM_STAT); +} + /* Build a GIMPLE_COND statement. @@ -1569,7 +1577,7 @@ gimple_assign_set_rhs_from_tree (gimple_stmt_iterator *gsi, tree expr) tree op1, op2, op3; extract_ops_from_tree_1 (expr, &subcode, &op1, &op2, &op3); - gimple_assign_set_rhs_with_ops_1 (gsi, subcode, op1, op2, op3); + gimple_assign_set_rhs_with_ops (gsi, subcode, op1, op2, op3); } @@ -1580,8 +1588,8 @@ gimple_assign_set_rhs_from_tree (gimple_stmt_iterator *gsi, tree expr) did not have enough operand slots. */ void -gimple_assign_set_rhs_with_ops_1 (gimple_stmt_iterator *gsi, enum tree_code code, - tree op1, tree op2, tree op3) +gimple_assign_set_rhs_with_ops (gimple_stmt_iterator *gsi, enum tree_code code, + tree op1, tree op2, tree op3) { unsigned new_rhs_ops = get_gimple_rhs_num_ops (code); gimple stmt = gsi_stmt (*gsi); diff --git a/gcc/gimple.h b/gcc/gimple.h index baf45811a5a..7f319056a60 100644 --- a/gcc/gimple.h +++ b/gcc/gimple.h @@ -1300,10 +1300,11 @@ gcall *gimple_build_call_from_tree (tree); gassign *gimple_build_assign_stat (tree, tree MEM_STAT_DECL); #define gimple_build_assign(l,r) gimple_build_assign_stat (l, r MEM_STAT_INFO) gassign *gimple_build_assign_with_ops (enum tree_code, tree, - tree, tree, - tree CXX_MEM_STAT_INFO); + tree, tree, tree CXX_MEM_STAT_INFO); gassign *gimple_build_assign_with_ops (enum tree_code, tree, - tree, tree CXX_MEM_STAT_INFO); + tree, tree CXX_MEM_STAT_INFO); +gassign *gimple_build_assign_with_ops (enum tree_code, tree, + tree CXX_MEM_STAT_INFO); gcond *gimple_build_cond (enum tree_code, tree, tree, tree, tree); gcond *gimple_build_cond_from_tree (tree, tree, tree); void gimple_cond_set_condition_from_tree (gcond *, tree); @@ -1369,8 +1370,8 @@ bool gimple_assign_ssa_name_copy_p (gimple); bool gimple_assign_unary_nop_p (gimple); void gimple_set_bb (gimple, basic_block); void gimple_assign_set_rhs_from_tree (gimple_stmt_iterator *, tree); -void gimple_assign_set_rhs_with_ops_1 (gimple_stmt_iterator *, enum tree_code, - tree, tree, tree); +void gimple_assign_set_rhs_with_ops (gimple_stmt_iterator *, enum tree_code, + tree, tree, tree); tree gimple_get_lhs (const_gimple); void gimple_set_lhs (gimple, tree); gimple gimple_copy (gimple); @@ -2448,14 +2449,24 @@ gimple_assign_set_rhs3 (gimple gs, tree rhs) gimple_set_op (gs, 3, rhs); } -/* A wrapper around gimple_assign_set_rhs_with_ops_1, for callers which expect - to see only a maximum of two operands. */ +/* A wrapper around 3 operand gimple_assign_set_rhs_with_ops, for callers + which expect to see only two operands. */ static inline void gimple_assign_set_rhs_with_ops (gimple_stmt_iterator *gsi, enum tree_code code, tree op1, tree op2) { - gimple_assign_set_rhs_with_ops_1 (gsi, code, op1, op2, NULL); + gimple_assign_set_rhs_with_ops (gsi, code, op1, op2, NULL); +} + +/* A wrapper around 3 operand gimple_assign_set_rhs_with_ops, for callers + which expect to see only one operands. */ + +static inline void +gimple_assign_set_rhs_with_ops (gimple_stmt_iterator *gsi, enum tree_code code, + tree op1) +{ + gimple_assign_set_rhs_with_ops (gsi, code, op1, NULL, NULL); } /* Returns true if GS is a nontemporal move. */ diff --git a/gcc/gimplify.c b/gcc/gimplify.c index a985315dccd..8e3dd834a01 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -2432,7 +2432,7 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value) } } - /* Finally, gimplify the function arguments. */ + /* Gimplify the function arguments. */ if (nargs > 0) { for (i = (PUSH_ARGS_REVERSED ? nargs - 1 : 0); @@ -2454,6 +2454,21 @@ gimplify_call_expr (tree *expr_p, gimple_seq *pre_p, bool want_value) } } + /* Gimplify the static chain. */ + if (CALL_EXPR_STATIC_CHAIN (*expr_p)) + { + if (fndecl && !DECL_STATIC_CHAIN (fndecl)) + CALL_EXPR_STATIC_CHAIN (*expr_p) = NULL; + else + { + enum gimplify_status t; + t = gimplify_arg (&CALL_EXPR_STATIC_CHAIN (*expr_p), pre_p, + EXPR_LOCATION (*expr_p)); + if (t == GS_ERROR) + ret = GS_ERROR; + } + } + /* Verify the function result. */ if (want_value && fndecl && VOID_TYPE_P (TREE_TYPE (TREE_TYPE (fnptrtype)))) diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc index 7c318ab1b89..453db9af9c1 100644 --- a/gcc/go/gofrontend/gogo.cc +++ b/gcc/go/gofrontend/gogo.cc @@ -1018,11 +1018,11 @@ class Var_init { public: Var_init() - : var_(NULL), init_(NULL) + : var_(NULL), init_(NULL), dep_count_(0) { } Var_init(Named_object* var, Bstatement* init) - : var_(var), init_(init) + : var_(var), init_(init), dep_count_(0) { } // Return the variable. @@ -1035,13 +1035,38 @@ class Var_init init() const { return this->init_; } + // Return the number of remaining dependencies. + size_t + dep_count() const + { return this->dep_count_; } + + // Increment the number of dependencies. + void + add_dependency() + { ++this->dep_count_; } + + // Decrement the number of dependencies. + void + remove_dependency() + { --this->dep_count_; } + private: // The variable being initialized. Named_object* var_; // The initialization statement. Bstatement* init_; + // The number of initializations this is dependent on. A variable + // initialization should not be emitted if any of its dependencies + // have not yet been resolved. + size_t dep_count_; }; +// For comparing Var_init keys in a map. + +inline bool +operator<(const Var_init& v1, const Var_init& v2) +{ return v1.var()->name() < v2.var()->name(); } + typedef std::list<Var_init> Var_inits; // Sort the variable initializations. The rule we follow is that we @@ -1052,14 +1077,21 @@ typedef std::list<Var_init> Var_inits; static void sort_var_inits(Gogo* gogo, Var_inits* var_inits) { + if (var_inits->empty()) + return; + typedef std::pair<Named_object*, Named_object*> No_no; typedef std::map<No_no, bool> Cache; Cache cache; - Var_inits ready; - while (!var_inits->empty()) + // A mapping from a variable initialization to a set of + // variable initializations that depend on it. + typedef std::map<Var_init, std::set<Var_init*> > Init_deps; + Init_deps init_deps; + for (Var_inits::iterator p1 = var_inits->begin(); + p1 != var_inits->end(); + ++p1) { - Var_inits::iterator p1 = var_inits->begin(); Named_object* var = p1->var(); Expression* init = var->var_value()->init(); Block* preinit = var->var_value()->preinit(); @@ -1067,11 +1099,13 @@ sort_var_inits(Gogo* gogo, Var_inits* var_inits) // Start walking through the list to see which variables VAR // needs to wait for. - Var_inits::iterator p2 = p1; - ++p2; - - for (; p2 != var_inits->end(); ++p2) + for (Var_inits::iterator p2 = var_inits->begin(); + p2 != var_inits->end(); + ++p2) { + if (var == p2->var()) + continue; + Named_object* p2var = p2->var(); No_no key(var, p2var); std::pair<Cache::iterator, bool> ins = @@ -1080,6 +1114,10 @@ sort_var_inits(Gogo* gogo, Var_inits* var_inits) ins.first->second = expression_requires(init, preinit, dep, p2var); if (ins.first->second) { + // VAR depends on P2VAR. + init_deps[*p2].insert(&(*p1)); + p1->add_dependency(); + // Check for cycles. key = std::make_pair(p2var, var); ins = cache.insert(std::make_pair(key, false)); @@ -1100,36 +1138,66 @@ sort_var_inits(Gogo* gogo, Var_inits* var_inits) p2var->message_name().c_str()); p2 = var_inits->end(); } - else - { - // We can't emit P1 until P2 is emitted. Move P1. - Var_inits::iterator p3 = p2; - ++p3; - var_inits->splice(p3, *var_inits, p1); - } - break; } } + } - if (p2 == var_inits->end()) + // If there are no dependencies then the declaration order is sorted. + if (!init_deps.empty()) + { + // Otherwise, sort variable initializations by emitting all variables with + // no dependencies in declaration order. VAR_INITS is already in + // declaration order. + Var_inits ready; + while (!var_inits->empty()) { - // VAR does not depends upon any other initialization expressions. - - // Check for a loop of VAR on itself. We only do this if - // INIT is not NULL and there is no dependency; when INIT is - // NULL, it means that PREINIT sets VAR, which we will - // interpret as a loop. - if (init != NULL && dep == NULL - && expression_requires(init, preinit, NULL, var)) - error_at(var->location(), - "initialization expression for %qs depends upon itself", - var->message_name().c_str()); - ready.splice(ready.end(), *var_inits, p1); + Var_inits::iterator v1;; + for (v1 = var_inits->begin(); v1 != var_inits->end(); ++v1) + { + if (v1->dep_count() == 0) + break; + } + go_assert(v1 != var_inits->end()); + + // V1 either has no dependencies or its dependencies have already + // been emitted, add it to READY next. When V1 is emitted, remove + // a dependency from each V that depends on V1. + ready.splice(ready.end(), *var_inits, v1); + + Init_deps::iterator p1 = init_deps.find(*v1); + if (p1 != init_deps.end()) + { + std::set<Var_init*> resolved = p1->second; + for (std::set<Var_init*>::iterator pv = resolved.begin(); + pv != resolved.end(); + ++pv) + (*pv)->remove_dependency(); + init_deps.erase(p1); + } } + var_inits->swap(ready); + go_assert(init_deps.empty()); } - // Now READY is the list in the desired initialization order. - var_inits->swap(ready); + // VAR_INITS is in the correct order. For each VAR in VAR_INITS, + // check for a loop of VAR on itself. We only do this if + // INIT is not NULL and there is no dependency; when INIT is + // NULL, it means that PREINIT sets VAR, which we will + // interpret as a loop. + for (Var_inits::const_iterator p = var_inits->begin(); + p != var_inits->end(); + ++p) + { + Named_object* var = p->var(); + Expression* init = var->var_value()->init(); + Block* preinit = var->var_value()->preinit(); + Named_object* dep = gogo->var_depends_on(var->var_value()); + if (init != NULL && dep == NULL + && expression_requires(init, preinit, NULL, var)) + error_at(var->location(), + "initialization expression for %qs depends upon itself", + var->message_name().c_str()); + } } // Write out the global definitions. diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c index 8bf43d937be..0ba20245d67 100644 --- a/gcc/internal-fn.c +++ b/gcc/internal-fn.c @@ -395,6 +395,21 @@ expand_arith_overflow_result_store (tree lhs, rtx target, write_complex_part (target, lres, false); } +/* Helper for expand_*_overflow. Store RES into TARGET. */ + +static void +expand_ubsan_result_store (rtx target, rtx res) +{ + if (GET_CODE (target) == SUBREG && SUBREG_PROMOTED_VAR_P (target)) + /* If this is a scalar in a register that is stored in a wider mode + than the declared mode, compute the result into its declared mode + and then convert to the wider mode. Our value is the computed + expression. */ + convert_move (SUBREG_REG (target), res, SUBREG_PROMOTED_SIGN (target)); + else + emit_move_insn (target, res); +} + /* Add sub/add overflow checking to the statement STMT. CODE says whether the operation is +, or -. */ @@ -809,7 +824,7 @@ expand_addsub_overflow (location_t loc, tree_code code, tree lhs, if (lhs) { if (is_ubsan) - emit_move_insn (target, res); + expand_ubsan_result_store (target, res); else { if (do_xor) @@ -904,7 +919,7 @@ expand_neg_overflow (location_t loc, tree lhs, tree arg1, bool is_ubsan) if (lhs) { if (is_ubsan) - emit_move_insn (target, res); + expand_ubsan_result_store (target, res); else expand_arith_overflow_result_store (lhs, target, mode, res); } @@ -1590,7 +1605,7 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1, if (lhs) { if (is_ubsan) - emit_move_insn (target, res); + expand_ubsan_result_store (target, res); else expand_arith_overflow_result_store (lhs, target, mode, res); } diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c index e598241c01d..f97912ba72d 100644 --- a/gcc/ipa-cp.c +++ b/gcc/ipa-cp.c @@ -566,7 +566,7 @@ ipcp_cloning_candidate_p (struct cgraph_node *node) gcc_checking_assert (node->has_gimple_body_p ()); - if (!flag_ipa_cp_clone) + if (!opt_for_fn (node->decl, flag_ipa_cp_clone)) { if (dump_file) fprintf (dump_file, "Not considering %s for cloning; " @@ -902,10 +902,7 @@ ipa_value_from_jfunc (struct ipa_node_params *info, struct ipa_jump_func *jfunc) ipcp_lattice<tree> *lat; if (!info->lattices) - { - gcc_checking_assert (!flag_ipa_cp); - return NULL_TREE; - } + return NULL_TREE; lat = ipa_get_scalar_lat (info, idx); if (!lat->is_single_const ()) return NULL_TREE; @@ -967,10 +964,7 @@ ipa_context_from_jfunc (ipa_node_params *info, cgraph_edge *cs, int csidx, else { if (!info->lattices) - { - gcc_checking_assert (!flag_ipa_cp); - return ctx; - } + return ctx; ipcp_lattice<ipa_polymorphic_call_context> *lat; lat = ipa_get_poly_ctx_lat (info, srcidx); if (!lat->is_single_const ()) @@ -1786,7 +1780,7 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie, return NULL_TREE; } - if (!flag_devirtualize) + if (!opt_for_fn (ie->caller->decl, flag_devirtualize)) return NULL_TREE; gcc_assert (!ie->indirect_info->agg_contents); @@ -1884,8 +1878,8 @@ ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie, struct cgraph_node *node; if (*speculative) return target; - if (!flag_devirtualize_speculatively || ie->speculative - || !ie->maybe_hot_p ()) + if (!opt_for_fn (ie->caller->decl, flag_devirtualize_speculatively) + || ie->speculative || !ie->maybe_hot_p ()) return NULL; node = try_speculative_devirtualization (ie->indirect_info->otr_type, ie->indirect_info->otr_token, @@ -2003,7 +1997,7 @@ good_cloning_opportunity_p (struct cgraph_node *node, int time_benefit, int freq_sum, gcov_type count_sum, int size_cost) { if (time_benefit == 0 - || !flag_ipa_cp_clone + || !opt_for_fn (node->decl, flag_ipa_cp_clone) || !optimize_function_for_speed_p (DECL_STRUCT_FUNCTION (node->decl))) return false; @@ -4315,7 +4309,7 @@ public: { /* FIXME: We should remove the optimize check after we ensure we never run IPA passes when not optimizing. */ - return flag_ipa_cp && optimize; + return (flag_ipa_cp && optimize) || in_lto_p; } virtual unsigned int execute (function *) { return ipcp_driver (); } diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c index 5e1f5713122..99475f6b640 100644 --- a/gcc/ipa-devirt.c +++ b/gcc/ipa-devirt.c @@ -2818,6 +2818,8 @@ ipa_devirt (void) FOR_EACH_DEFINED_FUNCTION (n) { bool update = false; + if (!opt_for_fn (n->decl, flag_devirtualize)) + continue; if (dump_file && n->indirect_calls) fprintf (dump_file, "\n\nProcesing function %s/%i\n", n->name (), n->order); @@ -2846,7 +2848,7 @@ ipa_devirt (void) npolymorphic++; - if (!flag_devirtualize_speculatively) + if (!opt_for_fn (n->decl, flag_devirtualize_speculatively)) continue; if (!e->maybe_hot_p ()) @@ -3116,6 +3118,10 @@ public: /* opt_pass methods: */ virtual bool gate (function *) { + /* In LTO, always run the IPA passes and decide on function basis if the + pass is enabled. */ + if (in_lto_p) + return true; return (flag_devirtualize && (flag_devirtualize_speculatively || (warn_suggest_final_methods diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c index 548fd85a18a..2f2993ce299 100644 --- a/gcc/ipa-inline-analysis.c +++ b/gcc/ipa-inline-analysis.c @@ -2474,7 +2474,7 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early) info->conds = NULL; info->entry = NULL; - if (optimize && !early) + if (opt_for_fn (node->decl, optimize) && !early) { calculate_dominance_info (CDI_DOMINATORS); loop_optimizer_init (LOOPS_NORMAL | LOOPS_HAVE_RECORDED_EXITS); @@ -2817,7 +2817,7 @@ estimate_function_body_sizes (struct cgraph_node *node, bool early) inline_summary (node)->self_time = time; inline_summary (node)->self_size = size; nonconstant_names.release (); - if (optimize && !early) + if (opt_for_fn (node->decl, optimize) && !early) { loop_optimizer_finalize (); free_dominance_info (CDI_DOMINATORS); @@ -2874,8 +2874,9 @@ compute_inline_parameters (struct cgraph_node *node, bool early) info->stack_frame_offset = 0; /* Can this function be inlined at all? */ - if (!optimize && !lookup_attribute ("always_inline", - DECL_ATTRIBUTES (node->decl))) + if (!opt_for_fn (node->decl, optimize) + && !lookup_attribute ("always_inline", + DECL_ATTRIBUTES (node->decl))) info->inlinable = false; else info->inlinable = tree_inlinable_function_p (node->decl); @@ -2992,7 +2993,7 @@ estimate_edge_devirt_benefit (struct cgraph_edge *ie, if (!known_vals.exists () && !known_contexts.exists ()) return false; - if (!flag_indirect_inlining) + if (!opt_for_fn (ie->caller->decl, flag_indirect_inlining)) return false; target = ipa_get_indirect_edge_target (ie, known_vals, known_contexts, @@ -3988,7 +3989,7 @@ inline_analyze_function (struct cgraph_node *node) if (dump_file) fprintf (dump_file, "\nAnalyzing function: %s/%u\n", node->name (), node->order); - if (optimize && !node->thunk.thunk_p) + if (opt_for_fn (node->decl, optimize) && !node->thunk.thunk_p) inline_indirect_intraprocedural_analysis (node); compute_inline_parameters (node, false); if (!optimize) diff --git a/gcc/ipa-inline-transform.c b/gcc/ipa-inline-transform.c index dbc56c599b0..9b806c1bf66 100644 --- a/gcc/ipa-inline-transform.c +++ b/gcc/ipa-inline-transform.c @@ -467,6 +467,7 @@ inline_transform (struct cgraph_node *node) { unsigned int todo = 0; struct cgraph_edge *e, *next; + bool has_inline = false; /* FIXME: Currently the pass manager is adding inline transform more than once to some clones. This needs revisiting after WPA cleanups. */ @@ -480,13 +481,15 @@ inline_transform (struct cgraph_node *node) for (e = node->callees; e; e = next) { + if (!e->inline_failed) + has_inline = true; next = e->next_callee; e->redirect_call_stmt_to_callee (); } node->remove_all_references (); timevar_push (TV_INTEGRATION); - if (node->callees && optimize) + if (node->callees && (optimize || has_inline)) todo = optimize_inline_calls (current_function_decl); timevar_pop (TV_INTEGRATION); diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c index ca50ad5268c..72c0715dc56 100644 --- a/gcc/ipa-inline.c +++ b/gcc/ipa-inline.c @@ -378,18 +378,10 @@ can_inline_edge_p (struct cgraph_edge *e, bool report, optimization attribute. */ else if (caller_tree != callee_tree) { - struct cl_optimization *caller_opt - = TREE_OPTIMIZATION ((caller_tree) - ? caller_tree - : optimization_default_node); - - struct cl_optimization *callee_opt - = TREE_OPTIMIZATION ((callee_tree) - ? callee_tree - : optimization_default_node); - - if (((caller_opt->x_optimize > callee_opt->x_optimize) - || (caller_opt->x_optimize_size != callee_opt->x_optimize_size)) + if (((opt_for_fn (e->caller->decl, optimize) + > opt_for_fn (e->callee->decl, optimize)) + || (opt_for_fn (e->caller->decl, optimize_size) + != opt_for_fn (e->callee->decl, optimize_size))) /* gcc.dg/pr43564.c. Look at forced inline even in -O0. */ && !DECL_DISREGARD_INLINE_LIMITS (e->callee->decl)) { @@ -469,7 +461,7 @@ want_early_inline_function_p (struct cgraph_edge *e) else if (flag_auto_profile && afdo_callsite_hot_enough_for_early_inline (e)) ; else if (!DECL_DECLARED_INLINE_P (callee->decl) - && !flag_inline_small_functions) + && !opt_for_fn (e->caller->decl, flag_inline_small_functions)) { e->inline_failed = CIF_FUNCTION_NOT_INLINE_CANDIDATE; report_inline_failed_reason (e); @@ -587,7 +579,7 @@ want_inline_small_function_p (struct cgraph_edge *e, bool report) if (DECL_DISREGARD_INLINE_LIMITS (callee->decl)) ; else if (!DECL_DECLARED_INLINE_P (callee->decl) - && !flag_inline_small_functions) + && !opt_for_fn (e->caller->decl, flag_inline_small_functions)) { e->inline_failed = CIF_FUNCTION_NOT_INLINE_CANDIDATE; want_inline = false; @@ -639,7 +631,7 @@ want_inline_small_function_p (struct cgraph_edge *e, bool report) want_inline = false; } else if (!DECL_DECLARED_INLINE_P (callee->decl) - && !flag_inline_functions) + && !opt_for_fn (e->caller->decl, flag_inline_functions)) { /* growth_likely_positive is expensive, always test it last. */ if (growth >= MAX_INLINE_INSNS_SINGLE @@ -816,6 +808,8 @@ check_callers (struct cgraph_node *node, void *has_hot_call) struct cgraph_edge *e; for (e = node->callers; e; e = e->next_caller) { + if (!opt_for_fn (e->caller->decl, flag_inline_functions_called_once)) + return true; if (!can_inline_edge_p (e, true)) return true; if (!(*(bool *)has_hot_call) && e->maybe_hot_p ()) @@ -1010,6 +1004,8 @@ edge_badness (struct cgraph_edge *edge, bool dump) compensated by the inline hints. */ + /* TODO: We ought suport mixing units where some functions are profiled + and some not. */ else if (flag_guess_branch_prob) { badness = (relative_time_benefit (callee_info, edge, edge_time) @@ -1575,8 +1571,7 @@ inline_small_functions (void) int initial_size = 0; struct cgraph_node **order = XCNEWVEC (cgraph_node *, symtab->cgraph_count); struct cgraph_edge_hook_list *edge_removal_hook_holder; - if (flag_indirect_inlining) - new_indirect_edges.create (8); + new_indirect_edges.create (8); edge_removal_hook_holder = symtab->add_edge_removal_hook (&heap_edge_removal_hook, &edge_heap); @@ -1773,7 +1768,8 @@ inline_small_functions (void) if (where->global.inlined_to) where = where->global.inlined_to; if (!recursive_inlining (edge, - flag_indirect_inlining + opt_for_fn (edge->caller->decl, + flag_indirect_inlining) ? &new_indirect_edges : NULL)) { edge->inline_failed = CIF_RECURSIVE_INLINING; @@ -1783,7 +1779,7 @@ inline_small_functions (void) reset_edge_caches (where); /* Recursive inliner inlines all recursive calls of the function at once. Consequently we need to update all callee keys. */ - if (flag_indirect_inlining) + if (opt_for_fn (edge->caller->decl, flag_indirect_inlining)) add_new_edges_to_heap (&edge_heap, new_indirect_edges); update_callee_keys (&edge_heap, where, updated_nodes); bitmap_clear (updated_nodes); @@ -1821,8 +1817,7 @@ inline_small_functions (void) gcc_checking_assert (!callee->global.inlined_to); inline_call (edge, true, &new_indirect_edges, &overall_size, true); - if (flag_indirect_inlining) - add_new_edges_to_heap (&edge_heap, new_indirect_edges); + add_new_edges_to_heap (&edge_heap, new_indirect_edges); reset_edge_caches (edge->callee); reset_node_growth_cache (callee); @@ -2246,8 +2241,7 @@ ipa_inline (void) reset_edge_caches (where); inline_update_overall_summary (where); } - if (flag_inline_functions_called_once - && want_inline_function_to_all_callers_p (node, cold)) + if (want_inline_function_to_all_callers_p (node, cold)) { int num_calls = 0; node->call_for_symbol_thunks_and_aliases (sum_callers, &num_calls, @@ -2345,8 +2339,8 @@ early_inline_small_functions (struct cgraph_node *node) /* Do not consider functions not declared inline. */ if (!DECL_DECLARED_INLINE_P (callee->decl) - && !flag_inline_small_functions - && !flag_inline_functions) + && !opt_for_fn (node->decl, flag_inline_small_functions) + && !opt_for_fn (node->decl, flag_inline_functions)) continue; if (dump_file) diff --git a/gcc/ipa-profile.c b/gcc/ipa-profile.c index 99d13098534..340d033b6a5 100644 --- a/gcc/ipa-profile.c +++ b/gcc/ipa-profile.c @@ -418,7 +418,8 @@ ipa_propagate_frequency (struct cgraph_node *node) nor about virtuals. */ if (!node->local.local || node->alias - || (flag_devirtualize && DECL_VIRTUAL_P (node->decl))) + || (opt_for_fn (node->decl, flag_devirtualize) + && DECL_VIRTUAL_P (node->decl))) return false; gcc_assert (node->analyzed); if (dump_file && (dump_flags & TDF_DETAILS)) @@ -754,7 +755,7 @@ public: {} /* opt_pass methods: */ - virtual bool gate (function *) { return flag_ipa_profile; } + virtual bool gate (function *) { return flag_ipa_profile || in_lto_p; } virtual unsigned int execute (function *) { return ipa_profile (); } }; // class pass_ipa_profile diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c index 6a70e161828..2e0016bfbe6 100644 --- a/gcc/ipa-prop.c +++ b/gcc/ipa-prop.c @@ -168,12 +168,10 @@ static bool ipa_func_spec_opts_forbid_analysis_p (struct cgraph_node *node) { tree fs_opts = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (node->decl); - struct cl_optimization *os; if (!fs_opts) return false; - os = TREE_OPTIMIZATION (fs_opts); - return !os->x_optimize || !os->x_flag_ipa_cp; + return !opt_for_fn (node->decl, optimize) || !opt_for_fn (node->decl, flag_ipa_cp); } /* Return index of the formal whose tree is PTREE in function which corresponds @@ -2899,13 +2897,14 @@ try_make_edge_direct_virtual_call (struct cgraph_edge *ie, tree target = NULL; bool speculative = false; - if (!flag_devirtualize) + if (!opt_for_fn (ie->caller->decl, flag_devirtualize)) return NULL; gcc_assert (!ie->indirect_info->by_ref); /* Try to do lookup via known virtual table pointer value. */ - if (!ie->indirect_info->vptr_changed || flag_devirtualize_speculatively) + if (!ie->indirect_info->vptr_changed + || opt_for_fn (ie->caller->decl, flag_devirtualize_speculatively)) { tree vtable; unsigned HOST_WIDE_INT offset; @@ -2956,7 +2955,7 @@ try_make_edge_direct_virtual_call (struct cgraph_edge *ie, else target = ipa_impossible_devirt_target (ie, NULL_TREE); } - else if (!target && flag_devirtualize_speculatively + else if (!target && opt_for_fn (ie->caller->decl, flag_devirtualize_speculatively) && !ie->speculative && ie->maybe_hot_p ()) { cgraph_node *n; @@ -3028,7 +3027,7 @@ update_indirect_edges_after_inlining (struct cgraph_edge *cs, param_index = ici->param_index; jfunc = ipa_get_ith_jump_func (top, param_index); - if (!flag_indirect_inlining) + if (!opt_for_fn (node->decl, flag_indirect_inlining)) new_direct_edge = NULL; else if (ici->polymorphic) { @@ -3582,7 +3581,7 @@ ipa_unregister_cgraph_hooks (void) void ipa_free_all_structures_after_ipa_cp (void) { - if (!optimize) + if (!optimize && !in_lto_p) { ipa_free_all_edge_args (); ipa_free_all_node_params (); diff --git a/gcc/ipa-pure-const.c b/gcc/ipa-pure-const.c index d03b27fbd1c..9c016c1d586 100644 --- a/gcc/ipa-pure-const.c +++ b/gcc/ipa-pure-const.c @@ -914,7 +914,8 @@ add_new_function (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED) static declarations. We do not need to scan them more than once since all we would be interested in are the addressof operations. */ - if (node->get_availability () > AVAIL_INTERPOSABLE) + if (node->get_availability () > AVAIL_INTERPOSABLE + && opt_for_fn (node->decl, flag_ipa_pure_const)) set_function_state (node, analyze_function (node, true)); } @@ -984,7 +985,8 @@ pure_const_generate_summary (void) when function got cloned and the clone is AVAILABLE. */ FOR_EACH_DEFINED_FUNCTION (node) - if (node->get_availability () >= AVAIL_INTERPOSABLE) + if (node->get_availability () >= AVAIL_INTERPOSABLE + && opt_for_fn (node->decl, flag_ipa_pure_const)) set_function_state (node, analyze_function (node, true)); } @@ -1595,9 +1597,7 @@ execute (function *) static bool gate_pure_const (void) { - return (flag_ipa_pure_const - /* Don't bother doing anything if the program has errors. */ - && !seen_error ()); + return flag_ipa_pure_const || in_lto_p; } pass_ipa_pure_const::pass_ipa_pure_const(gcc::context *ctxt) diff --git a/gcc/ipa-split.c b/gcc/ipa-split.c index 309cb6d7280..134b33ff64f 100644 --- a/gcc/ipa-split.c +++ b/gcc/ipa-split.c @@ -1587,7 +1587,7 @@ split_function (struct split_point *split_point) tree tem = create_tmp_reg (restype, NULL); tem = make_ssa_name (tem, call); cpy = gimple_build_assign_with_ops (NOP_EXPR, retval, - tem, NULL_TREE); + tem); gsi_insert_after (&gsi, cpy, GSI_NEW_STMT); retval = tem; } diff --git a/gcc/ipa.c b/gcc/ipa.c index a6086d808b0..54b30aab83c 100644 --- a/gcc/ipa.c +++ b/gcc/ipa.c @@ -304,8 +304,7 @@ symbol_table::remove_unreachable_nodes (bool before_inlining_p, FILE *file) hash_set<void *> reachable_call_targets; timevar_push (TV_IPA_UNREACHABLE); - if (optimize && flag_devirtualize) - build_type_inheritance_graph (); + build_type_inheritance_graph (); if (file) fprintf (file, "\nReclaiming functions:"); #ifdef ENABLE_CHECKING @@ -391,7 +390,8 @@ symbol_table::remove_unreachable_nodes (bool before_inlining_p, FILE *file) { struct cgraph_edge *e; /* Keep alive possible targets for devirtualization. */ - if (optimize && flag_devirtualize) + if (opt_for_fn (cnode->decl, optimize) + && opt_for_fn (cnode->decl, flag_devirtualize)) { struct cgraph_edge *next; for (e = cnode->indirect_calls; e; e = next) diff --git a/gcc/ira.c b/gcc/ira.c index 9c9e71d1be1..e610d358177 100644 --- a/gcc/ira.c +++ b/gcc/ira.c @@ -5263,7 +5263,18 @@ ira (FILE *f) ira_allocno_iterator ai; FOR_EACH_ALLOCNO (a, ai) - ALLOCNO_REGNO (a) = REGNO (ALLOCNO_EMIT_DATA (a)->reg); + { + int old_regno = ALLOCNO_REGNO (a); + int new_regno = REGNO (ALLOCNO_EMIT_DATA (a)->reg); + + ALLOCNO_REGNO (a) = new_regno; + + if (old_regno != new_regno) + setup_reg_classes (new_regno, reg_preferred_class (old_regno), + reg_alternate_class (old_regno), + reg_allocno_class (old_regno)); + } + } else { diff --git a/gcc/lto-wrapper.c b/gcc/lto-wrapper.c index 951a2ddc787..6b417821295 100644 --- a/gcc/lto-wrapper.c +++ b/gcc/lto-wrapper.c @@ -1314,13 +1314,13 @@ main (int argc, char *argv[]) xmalloc_set_program_name (progname); - if (atexit (lto_wrapper_cleanup) != 0) - fatal_error ("atexit failed"); - gcc_init_libintl (); diagnostic_initialize (global_dc, 0); + if (atexit (lto_wrapper_cleanup) != 0) + fatal_error ("atexit failed"); + if (signal (SIGINT, SIG_IGN) != SIG_IGN) signal (SIGINT, fatal_signal); #ifdef SIGHUP diff --git a/gcc/omp-low.c b/gcc/omp-low.c index bc4233ac237..15aa140770c 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -1517,7 +1517,8 @@ fixup_child_record_type (omp_context *ctx) layout_type (type); } - TREE_TYPE (ctx->receiver_decl) = build_pointer_type (type); + TREE_TYPE (ctx->receiver_decl) + = build_qualified_type (build_reference_type (type), TYPE_QUAL_RESTRICT); } /* Instantiate decls as necessary in CTX to satisfy the data sharing @@ -1961,7 +1962,9 @@ create_omp_child_function (omp_context *ctx, bool task_copy) if (is_targetreg_ctx (octx)) { cgraph_node::get_create (decl)->offloadable = 1; +#ifdef ENABLE_OFFLOADING g->have_offload = true; +#endif break; } } @@ -3843,8 +3846,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist, OMP_CLAUSE_CHAIN (c) = gimple_omp_for_clauses (ctx->stmt); gimple_omp_for_set_clauses (ctx->stmt, c); g = gimple_build_assign_with_ops (INTEGER_CST, lane, - build_int_cst (unsigned_type_node, 0), - NULL_TREE); + build_int_cst (unsigned_type_node, 0)); gimple_seq_add_stmt (ilist, g); for (int i = 0; i < 2; i++) if (llist[i]) @@ -3855,7 +3857,7 @@ lower_rec_input_clauses (tree clauses, gimple_seq *ilist, gimple_seq *dlist, gimple_seq *seq = i == 0 ? ilist : dlist; gimple_seq_add_stmt (seq, g); tree t = build_int_cst (unsigned_type_node, 0); - g = gimple_build_assign_with_ops (INTEGER_CST, idx, t, NULL_TREE); + g = gimple_build_assign_with_ops (INTEGER_CST, idx, t); gimple_seq_add_stmt (seq, g); tree body = create_artificial_label (UNKNOWN_LOCATION); tree header = create_artificial_label (UNKNOWN_LOCATION); @@ -5854,8 +5856,7 @@ expand_omp_for_generic (struct omp_region *region, if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (iend))) assign_stmt = gimple_build_assign (fd->loop.v, iend); else - assign_stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, iend, - NULL_TREE); + assign_stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, iend); gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING); } if (fd->collapse > 1) @@ -6275,8 +6276,7 @@ expand_omp_for_static_nochunk (struct omp_region *region, if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e))) assign_stmt = gimple_build_assign (fd->loop.v, e); else - assign_stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, e, - NULL_TREE); + assign_stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, e); gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING); } if (fd->collapse > 1) @@ -6666,8 +6666,7 @@ expand_omp_for_static_chunk (struct omp_region *region, if (useless_type_conversion_p (TREE_TYPE (fd->loop.v), TREE_TYPE (e))) assign_stmt = gimple_build_assign (fd->loop.v, e); else - assign_stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, e, - NULL_TREE); + assign_stmt = gimple_build_assign_with_ops (NOP_EXPR, fd->loop.v, e); gsi_insert_after (&gsi, assign_stmt, GSI_CONTINUE_LINKING); } if (fd->collapse > 1) @@ -8303,7 +8302,6 @@ expand_omp_target (struct omp_region *region) if (kind == GF_OMP_TARGET_KIND_REGION) { unsigned srcidx, dstidx, num; - struct cgraph_node *node; /* If the target region needs data sent from the parent function, then the very first statement (except possible @@ -8430,18 +8428,22 @@ expand_omp_target (struct omp_region *region) DECL_STRUCT_FUNCTION (child_fn)->curr_properties = cfun->curr_properties; cgraph_node::add_new_function (child_fn, true); +#ifdef ENABLE_OFFLOADING /* Add the new function to the offload table. */ vec_safe_push (offload_funcs, child_fn); +#endif /* Fix the callgraph edges for child_cfun. Those for cfun will be fixed in a following pass. */ push_cfun (child_cfun); cgraph_edge::rebuild_edges (); +#ifdef ENABLE_OFFLOADING /* Prevent IPA from removing child_fn as unreachable, since there are no refs from the parent function to child_fn in offload LTO mode. */ - node = cgraph_node::get (child_fn); + struct cgraph_node *node = cgraph_node::get (child_fn); node->mark_force_output (); +#endif /* Some EH regions might become dead, see PR34608. If pass_cleanup_cfg isn't the first pass to happen with the @@ -12241,8 +12243,7 @@ simd_clone_adjust (struct cgraph_node *node) { t = make_ssa_name (orig_arg, NULL); g = gimple_build_assign_with_ops (NOP_EXPR, t, - gimple_call_lhs (g), - NULL_TREE); + gimple_call_lhs (g)); gimple_seq_add_stmt_without_update (&seq, g); } gsi_insert_seq_on_edge_immediate @@ -12546,7 +12547,7 @@ omp_finish_file (void) varpool_node::finalize_decl (vars_decl); varpool_node::finalize_decl (funcs_decl); - } + } else { for (unsigned i = 0; i < num_funcs; i++) diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index 8094c7584ac..022e36fe7c0 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -3105,43 +3105,42 @@ simplify_binary_operation_1 (enum rtx_code code, machine_mode mode, && ! side_effects_p (op1)) return op0; /* Given: - scalar modes M1, M2 - scalar constants c1, c2 - size (M2) > size (M1) - c1 == size (M2) - size (M1) - optimize: - (ashiftrt:M1 (subreg:M1 (lshiftrt:M2 (reg:M2) - (const_int <c1>)) - <low_part>) - (const_int <c2>)) - to: - (subreg:M1 (ashiftrt:M2 (reg:M2) - (const_int <c1 + c2>)) - <low_part>). */ - if (!VECTOR_MODE_P (mode) - && SUBREG_P (op0) - && CONST_INT_P (op1) - && (GET_CODE (SUBREG_REG (op0)) == LSHIFTRT) - && !VECTOR_MODE_P (GET_MODE (SUBREG_REG (op0))) - && CONST_INT_P (XEXP (SUBREG_REG (op0), 1)) - && (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op0))) - > GET_MODE_BITSIZE (mode)) - && (INTVAL (XEXP (SUBREG_REG (op0), 1)) - == (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op0))) - - GET_MODE_BITSIZE (mode))) - && subreg_lowpart_p (op0)) - { - rtx tmp = GEN_INT (INTVAL (XEXP (SUBREG_REG (op0), 1)) - + INTVAL (op1)); - machine_mode inner_mode = GET_MODE (SUBREG_REG (op0)); - tmp = simplify_gen_binary (ASHIFTRT, - GET_MODE (SUBREG_REG (op0)), - XEXP (SUBREG_REG (op0), 0), - tmp); - return simplify_gen_subreg (mode, tmp, inner_mode, - subreg_lowpart_offset (mode, - inner_mode)); - } + scalar modes M1, M2 + scalar constants c1, c2 + size (M2) > size (M1) + c1 == size (M2) - size (M1) + optimize: + (ashiftrt:M1 (subreg:M1 (lshiftrt:M2 (reg:M2) (const_int <c1>)) + <low_part>) + (const_int <c2>)) + to: + (subreg:M1 (ashiftrt:M2 (reg:M2) (const_int <c1 + c2>)) + <low_part>). */ + if (code == ASHIFTRT + && !VECTOR_MODE_P (mode) + && SUBREG_P (op0) + && CONST_INT_P (op1) + && GET_CODE (SUBREG_REG (op0)) == LSHIFTRT + && !VECTOR_MODE_P (GET_MODE (SUBREG_REG (op0))) + && CONST_INT_P (XEXP (SUBREG_REG (op0), 1)) + && (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op0))) + > GET_MODE_BITSIZE (mode)) + && (INTVAL (XEXP (SUBREG_REG (op0), 1)) + == (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op0))) + - GET_MODE_BITSIZE (mode))) + && subreg_lowpart_p (op0)) + { + rtx tmp = GEN_INT (INTVAL (XEXP (SUBREG_REG (op0), 1)) + + INTVAL (op1)); + machine_mode inner_mode = GET_MODE (SUBREG_REG (op0)); + tmp = simplify_gen_binary (ASHIFTRT, + GET_MODE (SUBREG_REG (op0)), + XEXP (SUBREG_REG (op0), 0), + tmp); + return simplify_gen_subreg (mode, tmp, inner_mode, + subreg_lowpart_offset (mode, + inner_mode)); + } canonicalize_shift: if (SHIFT_COUNT_TRUNCATED && CONST_INT_P (op1)) { diff --git a/gcc/target.def b/gcc/target.def index 3ccb028a61e..dc48ae6912e 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -3314,7 +3314,7 @@ the body of the memory operation.\n\ Returning true for higher values of @code{size} may also cause an increase\n\ in code size, for example where the number of insns emitted to perform a\n\ move would be greater than that of a library call.", - bool, (unsigned int size, unsigned int alignment, + bool, (unsigned HOST_WIDE_INT size, unsigned int alignment, enum by_pieces_operation op, bool speed_p), default_use_by_pieces_infrastructure_p) @@ -4516,8 +4516,8 @@ false for naked functions. The default implementation always returns true.", bool, (void), hook_bool_void_true) -/* Return an rtx for the static chain for FNDECL. If INCOMING_P is true, - then it should be for the callee; otherwise for the caller. */ +/* Return an rtx for the static chain for FNDECL_OR_TYPE. If INCOMING_P + is true, then it should be for the callee; otherwise for the caller. */ DEFHOOK (static_chain, "This hook replaces the use of @code{STATIC_CHAIN_REGNUM} et al for\n\ @@ -4539,7 +4539,7 @@ will be at an offset from the frame pointer.\n\ The variables @code{stack_pointer_rtx}, @code{frame_pointer_rtx}, and\n\ @code{arg_pointer_rtx} will have been initialized and should be used\n\ to refer to those items.", - rtx, (const_tree fndecl, bool incoming_p), + rtx, (const_tree fndecl_or_type, bool incoming_p), default_static_chain) /* Fill in the trampoline at MEM with a call to FNDECL and a diff --git a/gcc/targhooks.c b/gcc/targhooks.c index 7b1b5dcfee4..42fd82e692b 100644 --- a/gcc/targhooks.c +++ b/gcc/targhooks.c @@ -841,11 +841,8 @@ default_internal_arg_pointer (void) } rtx -default_static_chain (const_tree fndecl, bool incoming_p) +default_static_chain (const_tree ARG_UNUSED (fndecl_or_type), bool incoming_p) { - if (!DECL_STATIC_CHAIN (fndecl)) - return NULL; - if (incoming_p) { #ifdef STATIC_CHAIN_INCOMING_REGNUM @@ -1430,7 +1427,7 @@ get_move_ratio (bool speed_p ATTRIBUTE_UNUSED) a call to memcpy emitted. */ bool -default_use_by_pieces_infrastructure_p (unsigned int size, +default_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT size, unsigned int alignment, enum by_pieces_operation op, bool speed_p) diff --git a/gcc/targhooks.h b/gcc/targhooks.h index faadd23c887..9734220dea2 100644 --- a/gcc/targhooks.h +++ b/gcc/targhooks.h @@ -181,7 +181,7 @@ extern int default_memory_move_cost (machine_mode, reg_class_t, bool); extern int default_register_move_cost (machine_mode, reg_class_t, reg_class_t); -extern bool default_use_by_pieces_infrastructure_p (unsigned int, +extern bool default_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT, unsigned int, enum by_pieces_operation, bool); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 840faa9914a..f5fb9db873f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,83 @@ +2014-11-19 Renlin Li <Renlin.Li@arm.com> + + PR middle-end/63762 + * gcc.dg/pr63762.c: New test. + +2014-11-19 Marek Polacek <polacek@redhat.com> + + PR sanitizer/63690 + * gcc.dg/ubsan/pr63690.c: New test. + +2014-11-19 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> + + PR sanitizer/62132 + * c-c++-common/asan/misalign-1.c: Pass -fno-omit-frame-pointer on + darwin, adjust dg-output. + * c-c++-common/asan/misalign-2.c: Likewise. + +2014-11-19 Richard Henderson <rth@redhat.com> + + * gcc.dg/cwsc0.c: New test. + * gcc.dg/cwsc1.c: New test. + +2014-11-19 Marek Polacek <polacek@redhat.com> + + PR sanitizer/63879 + * c-c++-common/ubsan/pr63879-1.c: New test. + * c-c++-common/ubsan/pr63879-2.c: New test. + +2014-11-19 Tom de Vries <tom@codesourcery.com> + + PR tree-optimization/62167 + * gcc.dg/pr51879-12.c: Add xfails. + * gcc.dg/pr62167-run.c: New test. + * gcc.dg/pr62167.c: New test. + +2014-11-19 Jakub Jelinek <jakub@redhat.com> + + PR tree-optimization/63915 + * c-c++-common/gomp/pr60823-4.c: New test. + + PR sanitizer/63520 + * c-c++-common/ubsan/pr63520.c: New test. + +2014-11-19 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/57654 + * g++.dg/cpp0x/constexpr-ref7.C: New. + +2014-11-19 Jakub Jelinek <jakub@redhat.com> + + PR sanitizer/63913 + * g++.dg/ubsan/pr63913.C: New test. + +2014-11-19 Andreas Schwab <schwab@suse.de> + + * gcc.dg/pure-2.c: Update line numbers. + +2014-11-19 Jakub Jelinek <jakub@redhat.com> + + PR rtl-optimization/63843 + * gcc.c-torture/execute/pr63843.c: New test. + +2014-11-18 James Greenhalgh <james.greenhalgh@arm.com> + + PR target/63937 + * gcc.dg/memset-2.c: New. + +2014-11-18 Jakub Jelinek <jakub@redhat.com> + + PR sanitizer/63813 + * g++.dg/ubsan/pr63813.C: New test. + + PR tree-optimization/61042 + * gcc.c-torture/compile/pr61042.c: New test. + +2014-11-18 Maciej W. Rozycki <macro@codesourcery.com> + + * gcc.dg/atomic/c11-atomic-exec-5.c (dg-timeout-factor): New + setting. + 2014-11-18 Paolo Carlini <paolo.carlini@oracle.com> PR c++/55942 diff --git a/gcc/testsuite/c-c++-common/asan/misalign-1.c b/gcc/testsuite/c-c++-common/asan/misalign-1.c index 0c5b6e0c754..cec87a8ce6f 100644 --- a/gcc/testsuite/c-c++-common/asan/misalign-1.c +++ b/gcc/testsuite/c-c++-common/asan/misalign-1.c @@ -1,5 +1,6 @@ /* { dg-do run { target { ilp32 || lp64 } } } */ /* { dg-options "-O2" } */ +/* { dg-additional-options "-fno-omit-frame-pointer" { target *-*-darwin* } } */ /* { dg-shouldfail "asan" } */ struct S { int i; } __attribute__ ((packed)); @@ -38,5 +39,5 @@ main () /* { dg-output "ERROR: AddressSanitizer:\[^\n\r]*on address\[^\n\r]*" } */ /* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */ /* { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */ -/* { dg-output " #0 0x\[0-9a-f\]+ (in _*foo(\[^\n\r]*misalign-1.c:10|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ -/* { dg-output " #1 0x\[0-9a-f\]+ (in _*main (\[^\n\r]*misalign-1.c:34|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */ +/* { dg-output " #0 0x\[0-9a-f\]+ (in _*foo(\[^\n\r]*misalign-1.c:1\[01]|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output " #1 0x\[0-9a-f\]+ (in _*main (\[^\n\r]*misalign-1.c:3\[45]|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */ diff --git a/gcc/testsuite/c-c++-common/asan/misalign-2.c b/gcc/testsuite/c-c++-common/asan/misalign-2.c index 7fbe299cc54..f99127edb27 100644 --- a/gcc/testsuite/c-c++-common/asan/misalign-2.c +++ b/gcc/testsuite/c-c++-common/asan/misalign-2.c @@ -1,5 +1,6 @@ /* { dg-do run { target { ilp32 || lp64 } } } */ /* { dg-options "-O2" } */ +/* { dg-additional-options "-fno-omit-frame-pointer" { target *-*-darwin* } } */ /* { dg-shouldfail "asan" } */ struct S { int i; } __attribute__ ((packed)); @@ -38,5 +39,5 @@ main () /* { dg-output "ERROR: AddressSanitizer:\[^\n\r]*on address\[^\n\r]*" } */ /* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */ /* { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */ -/* { dg-output " #0 0x\[0-9a-f\]+ (in _*baz(\[^\n\r]*misalign-2.c:22|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ -/* { dg-output " #1 0x\[0-9a-f\]+ (in _*main (\[^\n\r]*misalign-2.c:34|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */ +/* { dg-output " #0 0x\[0-9a-f\]+ (in _*baz(\[^\n\r]*misalign-2.c:2\[23]|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output " #1 0x\[0-9a-f\]+ (in _*main (\[^\n\r]*misalign-2.c:3\[45]|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */ diff --git a/gcc/testsuite/c-c++-common/gomp/pr60823-4.c b/gcc/testsuite/c-c++-common/gomp/pr60823-4.c new file mode 100644 index 00000000000..a9bc0fa2591 --- /dev/null +++ b/gcc/testsuite/c-c++-common/gomp/pr60823-4.c @@ -0,0 +1,7 @@ +/* PR tree-optimization/63915 */ +/* { dg-do run } */ +/* { dg-require-effective-target vect_simd_clones } */ +/* { dg-options "-O2 -fopenmp-simd" } */ +/* { dg-additional-options "-fpic" { target fpic } } */ + +#include "pr60823-2.c" diff --git a/gcc/testsuite/c-c++-common/ubsan/pr63520.c b/gcc/testsuite/c-c++-common/ubsan/pr63520.c new file mode 100644 index 00000000000..66da668dbb8 --- /dev/null +++ b/gcc/testsuite/c-c++-common/ubsan/pr63520.c @@ -0,0 +1,16 @@ +/* PR sanitizer/63520 */ +/* { dg-do compile } */ +/* { dg-options "-fsanitize=undefined" } */ + +int a; + +void +foo (void) +{ + while (1) + { + if (a == 1) + break; + a -= 1; + } +} diff --git a/gcc/testsuite/c-c++-common/ubsan/pr63879-1.c b/gcc/testsuite/c-c++-common/ubsan/pr63879-1.c new file mode 100644 index 00000000000..2035849a8ce --- /dev/null +++ b/gcc/testsuite/c-c++-common/ubsan/pr63879-1.c @@ -0,0 +1,23 @@ +/* PR sanitizer/63879 */ +/* { dg-do compile } */ +/* { dg-options "-fsanitize=undefined" } */ + +struct A +{ + int inode; +} * a; +int b, c; +void +fn1 () +{ + int d = 0; + while (b) + { + if (a->inode) + d++; + a = 0; + } + c = d - 1; + for (; c >= 0; c--) + ; +} diff --git a/gcc/testsuite/c-c++-common/ubsan/pr63879-2.c b/gcc/testsuite/c-c++-common/ubsan/pr63879-2.c new file mode 100644 index 00000000000..34eb8e79d67 --- /dev/null +++ b/gcc/testsuite/c-c++-common/ubsan/pr63879-2.c @@ -0,0 +1,13 @@ +/* PR sanitizer/63879 */ +/* { dg-do compile } */ +/* { dg-options "-fsanitize=undefined" } */ + +int a; +void +fn1 () +{ + int b = 2; + for (; a;) + while (b >= 0) + b--; +} diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-empty8.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-empty8.C new file mode 100644 index 00000000000..8c1414af558 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-empty8.C @@ -0,0 +1,7 @@ +// PR c++/63924 +// { dg-do compile { target c++11 } } + +struct A { }; +constexpr bool f(A a) { return true; } +template <bool B> constexpr bool g() { return true; } +constexpr bool g(A a) { return g<f(a)>(); } diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ref7.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ref7.C new file mode 100644 index 00000000000..72c8d089d77 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ref7.C @@ -0,0 +1,11 @@ +// PR c++/57654 +// { dg-do compile { target c++11 } } + +int i; + +constexpr int & iref = i; +constexpr int & irefref = iref; + +class A { + static constexpr int & irefref = iref; +}; diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-stmtexpr2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-stmtexpr2.C new file mode 100644 index 00000000000..34ca9fa9974 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-stmtexpr2.C @@ -0,0 +1,12 @@ +// { dg-do compile { target c++11 } } +// { dg-options "" } + +#define SA(X) static_assert((X),#X) + +template <class T> +constexpr T f (T t) +{ + return ({ t+1; }); +} + +SA(f(42) == 43); diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-incr1.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-incr1.C index 2b099c821e0..ecd7c047c85 100644 --- a/gcc/testsuite/g++.dg/cpp1y/constexpr-incr1.C +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-incr1.C @@ -1,4 +1,5 @@ // { dg-do compile { target c++14 } } +#define SA(X) static_assert((X),#X) constexpr int f (int i) { @@ -8,6 +9,15 @@ constexpr int f (int i) return x; } +constexpr int* g (int* p) +{ + ++p; + return p; +} + constexpr int i = f(42); -#define SA(X) static_assert((X),#X) SA(i==44); + +int array[4]; +constexpr int* p = g(array); +SA(p == &array[1]); diff --git a/gcc/testsuite/g++.dg/ubsan/pr63813.C b/gcc/testsuite/g++.dg/ubsan/pr63813.C new file mode 100644 index 00000000000..6ca5b2d18c9 --- /dev/null +++ b/gcc/testsuite/g++.dg/ubsan/pr63813.C @@ -0,0 +1,12 @@ +// PR sanitizer/63813 +// { dg-do compile } +// { dg-options "-fsanitize=undefined -O1" } + +struct A {}; +struct B { long foo () const; A &bar () const; }; + +A & +B::bar () const +{ + return *reinterpret_cast <A *> (foo ()); +} diff --git a/gcc/testsuite/g++.dg/ubsan/pr63913.C b/gcc/testsuite/g++.dg/ubsan/pr63913.C new file mode 100644 index 00000000000..34dceb4d844 --- /dev/null +++ b/gcc/testsuite/g++.dg/ubsan/pr63913.C @@ -0,0 +1,12 @@ +// PR sanitizer/63913 +// { dg-do compile } +// { dg-options "-fsanitize=bool -fnon-call-exceptions" } + +struct B { B (); ~B (); }; + +double +foo (bool *x) +{ + B b; + return *x; +} diff --git a/gcc/testsuite/gcc.c-torture/compile/pr61042.c b/gcc/testsuite/gcc.c-torture/compile/pr61042.c new file mode 100644 index 00000000000..43a4319096a --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr61042.c @@ -0,0 +1,10 @@ +/* PR tree-optimization/61042 */ + +int a, b, c[1], d, f; + +void +foo () +{ + for (; b; b++) + c[0] = c[f] && (d = a); +} diff --git a/gcc/testsuite/gcc.c-torture/execute/pr63843.c b/gcc/testsuite/gcc.c-torture/execute/pr63843.c new file mode 100644 index 00000000000..9f6c7b06c39 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr63843.c @@ -0,0 +1,31 @@ +/* PR rtl-optimization/63843 */ + +static inline __attribute__ ((always_inline)) +unsigned short foo (unsigned short v) +{ + return (v << 8) | (v >> 8); +} + +unsigned short __attribute__ ((noinline, noclone, hot)) +bar (unsigned char *x) +{ + unsigned int a; + unsigned short b; + __builtin_memcpy (&a, &x[0], sizeof (a)); + a ^= 0x80808080U; + __builtin_memcpy (&x[0], &a, sizeof (a)); + __builtin_memcpy (&b, &x[2], sizeof (b)); + return foo (b); +} + +int +main () +{ + unsigned char x[8] = { 0x01, 0x01, 0x01, 0x01 }; + if (__CHAR_BIT__ == 8 + && sizeof (short) == 2 + && sizeof (int) == 4 + && bar (x) != 0x8181U) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-5.c b/gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-5.c index d8bddfd9961..c4c4842c524 100644 --- a/gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-5.c +++ b/gcc/testsuite/gcc.dg/atomic/c11-atomic-exec-5.c @@ -9,6 +9,7 @@ /* { dg-additional-options "-D_XOPEN_SOURCE=600" { target *-*-solaris2.1[0-9]* } } */ /* { dg-require-effective-target fenv_exceptions } */ /* { dg-require-effective-target pthread } */ +/* { dg-timeout-factor 2 } */ #include <fenv.h> #include <float.h> diff --git a/gcc/testsuite/gcc.dg/cwsc0.c b/gcc/testsuite/gcc.dg/cwsc0.c new file mode 100644 index 00000000000..3d92222bf9c --- /dev/null +++ b/gcc/testsuite/gcc.dg/cwsc0.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ + +#include <stddef.h> + +void foo(void); +void test(int (*f)(void), char *p) +{ + __builtin_call_with_static_chain(f(), p); + __builtin_call_with_static_chain(p, f()); /* { dg-error "must be a call" } */ + __builtin_call_with_static_chain(f() + 1, p); /* { dg-error "must be a call" } */ + __builtin_call_with_static_chain(f(), 0); /* { dg-error "must be a pointer" } */ + __builtin_call_with_static_chain(f(), NULL); + __builtin_call_with_static_chain(foo, p); /* { dg-error "must be a call" } */ + __builtin_call_with_static_chain(foo(), p); + __builtin_call_with_static_chain(foo(), foo); +} diff --git a/gcc/testsuite/gcc.dg/cwsc1.c b/gcc/testsuite/gcc.dg/cwsc1.c new file mode 100644 index 00000000000..e793e26116a --- /dev/null +++ b/gcc/testsuite/gcc.dg/cwsc1.c @@ -0,0 +1,46 @@ +/* { dg-do run } */ +/* { dg-options "-O" } */ + +#if defined(__x86_64__) +# define CHAIN "%r10" +#elif defined(__i386__) +# define CHAIN "%ecx" +#elif defined(__aarch64__) +# define CHAIN "x18" +#elif defined(__alpha__) +# define CHAIN "$1" +#elif defined(__arm__) +# define CHAIN "ip" +#elif defined(__powerpc__) +# define CHAIN "11" +#elif defined(__s390__) +# define CHAIN "%r0" +#elif defined(__sparc__) +# ifdef __arch64__ +# define CHAIN "%g5" +# else +# define CHAIN "%g2" +# endif +#endif + +#ifdef CHAIN +void *__attribute__((noinline, noclone)) foo(void) +{ + register void *chain __asm__(CHAIN); + return chain; +} + +void * (*ptr)(void) = foo; +extern void abort(void); + +int main() +{ + char c; + void *x = __builtin_call_with_static_chain(ptr(), &c); + if (x != &c) + abort(); + return 0; +} +#else +int main() { return 0; } +#endif diff --git a/gcc/testsuite/gcc.dg/memset-2.c b/gcc/testsuite/gcc.dg/memset-2.c new file mode 100644 index 00000000000..fb4debc6d2c --- /dev/null +++ b/gcc/testsuite/gcc.dg/memset-2.c @@ -0,0 +1,11 @@ +/* PR target/63937 */ +/* { dg-do compile { target lp64 } } */ +/* { dg-options "-O2" } */ + +void +foo (char *p) +{ + p = __builtin_assume_aligned (p, 64); + __builtin_memset (p, 0, 0x100000001ULL); +} + diff --git a/gcc/testsuite/gcc.dg/pr51879-12.c b/gcc/testsuite/gcc.dg/pr51879-12.c index 8126505f384..85e2687da17 100644 --- a/gcc/testsuite/gcc.dg/pr51879-12.c +++ b/gcc/testsuite/gcc.dg/pr51879-12.c @@ -24,6 +24,6 @@ foo (int y) baz (a); } -/* { dg-final { scan-tree-dump-times "bar \\(" 1 "pre"} } */ -/* { dg-final { scan-tree-dump-times "bar2 \\(" 1 "pre"} } */ +/* { dg-final { scan-tree-dump-times "bar \\(" 1 "pre" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump-times "bar2 \\(" 1 "pre" { xfail *-*-* } } } */ /* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/pr62167-run.c b/gcc/testsuite/gcc.dg/pr62167-run.c new file mode 100644 index 00000000000..37214a3ecee --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr62167-run.c @@ -0,0 +1,47 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-tail-merge" } */ + +struct node +{ + struct node *next; + struct node *prev; +}; + +struct node node; + +struct head +{ + struct node *first; +}; + +struct head heads[5]; + +int k = 2; + +struct head *head = &heads[2]; + +int +main () +{ + struct node *p; + + node.next = (void*)0; + + node.prev = (void *)head; + + head->first = &node; + + struct node *n = head->first; + + struct head *h = &heads[k]; + + heads[2].first = n->next; + + if ((void*)n->prev == (void *)h) + p = h->first; + else + /* Dead tbaa-unsafe load from ((struct node *)&heads[2])->next. */ + p = n->prev->next; + + return !(p == (void*)0); +} diff --git a/gcc/testsuite/gcc.dg/pr62167.c b/gcc/testsuite/gcc.dg/pr62167.c new file mode 100644 index 00000000000..f8c31a0792f --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr62167.c @@ -0,0 +1,50 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-tail-merge -fdump-tree-pre" } */ + +struct node +{ + struct node *next; + struct node *prev; +}; + +struct node node; + +struct head +{ + struct node *first; +}; + +struct head heads[5]; + +int k = 2; + +struct head *head = &heads[2]; + +int +main () +{ + struct node *p; + + node.next = (void*)0; + + node.prev = (void *)head; + + head->first = &node; + + struct node *n = head->first; + + struct head *h = &heads[k]; + + heads[2].first = n->next; + + if ((void*)n->prev == (void *)h) + p = h->first; + else + /* Dead tbaa-unsafe load from ((struct node *)&heads[2])->next. */ + p = n->prev->next; + + return !(p == (void*)0); +} + +/* { dg-final { scan-tree-dump-not "Removing basic block" "pre"} } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/pr63762.c b/gcc/testsuite/gcc.dg/pr63762.c new file mode 100644 index 00000000000..df110676eca --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr63762.c @@ -0,0 +1,77 @@ +/* PR middle-end/63762 */ +/* { dg-do assemble } */ +/* { dg-options "-O2" } */ + +#include <stdlib.h> + +void *astFree (); +void *astMalloc (); +void astNegate (void *); +int astGetNegated (void *); +void astGetRegionBounds (void *, double *, double *); +int astResampleF (void *, ...); + +extern int astOK; + +int +MaskF (int inside, int ndim, const int lbnd[], const int ubnd[], + float in[], float val) +{ + + void *used_region; + float *c, *d, *out, *tmp_out; + double *lbndgd, *ubndgd; + int *lbndg, *ubndg, idim, ipix, nax, nin, nout, npix, npixg, result = 0; + if (!astOK) return result; + lbndg = astMalloc (sizeof (int)*(size_t) ndim); + ubndg = astMalloc (sizeof (int)*(size_t) ndim); + lbndgd = astMalloc (sizeof (double)*(size_t) ndim); + ubndgd = astMalloc (sizeof (double)*(size_t) ndim); + if (astOK) + { + astGetRegionBounds (used_region, lbndgd, ubndgd); + npix = 1; + npixg = 1; + for (idim = 0; idim < ndim; idim++) + { + lbndg[ idim ] = lbnd[ idim ]; + ubndg[ idim ] = ubnd[ idim ]; + npix *= (ubnd[ idim ] - lbnd[ idim ] + 1); + if (npixg >= 0) npixg *= (ubndg[ idim ] - lbndg[ idim ] + 1); + } + if (npixg <= 0 && astOK) + { + if ((inside != 0) == (astGetNegated( used_region ) != 0)) + { + c = in; + for (ipix = 0; ipix < npix; ipix++) *(c++) = val; + result = npix; + } + } + else if (npixg > 0 && astOK) + { + if ((inside != 0) == (astGetNegated (used_region) != 0)) + { + tmp_out = astMalloc (sizeof (float)*(size_t) npix); + if (tmp_out) + { + c = tmp_out; + for (ipix = 0; ipix < npix; ipix++) *(c++) = val; + result = npix - npixg; + } + out = tmp_out; + } + else + { + tmp_out = NULL; + out = in; + } + if (inside) astNegate (used_region); + result += astResampleF (used_region, ndim, lbnd, ubnd, in, NULL, + NULL, NULL, 0, 0.0, 100, val, ndim, + lbnd, ubnd, lbndg, ubndg, out, NULL); + if (inside) astNegate (used_region); + } + } + return result; +} diff --git a/gcc/testsuite/gcc.dg/pure-2.c b/gcc/testsuite/gcc.dg/pure-2.c index 638bd7c550d..fe6e2bce695 100644 --- a/gcc/testsuite/gcc.dg/pure-2.c +++ b/gcc/testsuite/gcc.dg/pure-2.c @@ -8,14 +8,14 @@ extern int v; /* Trivial. */ int foo1(int a) /* { dg-bogus "normally" "detect pure candidate" } */ -{ /* { dg-warning "pure" "detect pure candidate" { target *-*-* } "9" } */ +{ /* { dg-warning "pure" "detect pure candidate" { target *-*-* } "10" } */ return v; } /* Loops known to be normally and extern const calls should be safe. */ int __attribute__ ((noinline)) foo2(int n) /* { dg-bogus "normally" "detect pure candidate" } */ -{ /* { dg-warning "pure" "detect pure candidate" { target *-*-* } "16" } */ +{ /* { dg-warning "pure" "detect pure candidate" { target *-*-* } "17" } */ int ret = 0; int i; for (i=0; i<n; i++) @@ -53,6 +53,6 @@ foo4(int n) /* { dg-warning "pure\[^\n\]* normally" "detect pure candidate" } * int foo5(int n) /* { dg-bogus "normally" "detect pure candidate" } */ -{ /* { dg-warning "pure" "detect pure candidate" { target *-*-* } "54" } */ +{ /* { dg-warning "pure" "detect pure candidate" { target *-*-* } "55" } */ return foo2(n); } diff --git a/gcc/testsuite/gcc.dg/ubsan/pr63690.c b/gcc/testsuite/gcc.dg/ubsan/pr63690.c new file mode 100644 index 00000000000..be8600f3fae --- /dev/null +++ b/gcc/testsuite/gcc.dg/ubsan/pr63690.c @@ -0,0 +1,18 @@ +/* PR sanitizer/63690 */ +/* { dg-do compile } */ +/* { dg-options "-fsanitize=undefined" } */ + +void +foo (void) +{ + (*"c")++; +} +/* PR sanitizer/63690 */ +/* { dg-do compile } */ +/* { dg-options "-fsanitize=undefined" } */ + +void +foo (void) +{ + (*"c")++; +} diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index a95749541b1..e78554f5721 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -3347,22 +3347,14 @@ verify_gimple_call (gcall *stmt) return true; } - /* If there is a static chain argument, this should not be an indirect - call, and the decl should have DECL_STATIC_CHAIN set. */ - if (gimple_call_chain (stmt)) + /* If there is a static chain argument, the call should either be + indirect, or the decl should have DECL_STATIC_CHAIN set. */ + if (gimple_call_chain (stmt) + && fndecl + && !DECL_STATIC_CHAIN (fndecl)) { - if (!gimple_call_fndecl (stmt)) - { - error ("static chain in indirect gimple call"); - return true; - } - fn = TREE_OPERAND (fn, 0); - - if (!DECL_STATIC_CHAIN (fn)) - { - error ("static chain with function that doesn%'t use one"); - return true; - } + error ("static chain with function that doesn%'t use one"); + return true; } /* ??? The C frontend passes unpromoted arguments in case it diff --git a/gcc/tree-loop-distribution.c b/gcc/tree-loop-distribution.c index 31ea04c3a0b..7aa7e31755b 100644 --- a/gcc/tree-loop-distribution.c +++ b/gcc/tree-loop-distribution.c @@ -822,9 +822,8 @@ generate_memset_builtin (struct loop *loop, partition_t partition) val = fold_convert (integer_type_node, val); else if (!useless_type_conversion_p (integer_type_node, TREE_TYPE (val))) { - gimple cstmt; tree tem = make_ssa_name (integer_type_node, NULL); - cstmt = gimple_build_assign_with_ops (NOP_EXPR, tem, val, NULL_TREE); + gimple cstmt = gimple_build_assign_with_ops (NOP_EXPR, tem, val); gsi_insert_after (&gsi, cstmt, GSI_CONTINUE_LINKING); val = tem; } diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c index 4f70b2e3148..43f4f2a05e0 100644 --- a/gcc/tree-ssa-forwprop.c +++ b/gcc/tree-ssa-forwprop.c @@ -757,10 +757,9 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs, if (useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (new_def_rhs))) gimple_assign_set_rhs_with_ops (use_stmt_gsi, TREE_CODE (new_def_rhs), - new_def_rhs, NULL_TREE); + new_def_rhs); else if (is_gimple_min_invariant (new_def_rhs)) - gimple_assign_set_rhs_with_ops (use_stmt_gsi, NOP_EXPR, - new_def_rhs, NULL_TREE); + gimple_assign_set_rhs_with_ops (use_stmt_gsi, NOP_EXPR, new_def_rhs); else return false; gcc_assert (gsi_stmt (*use_stmt_gsi) == use_stmt); @@ -1725,8 +1724,7 @@ simplify_rotate (gimple_stmt_iterator *gsi) { g = gimple_build_assign_with_ops (NOP_EXPR, make_ssa_name (TREE_TYPE (def_arg2[0]), - NULL), - rotcnt, NULL_TREE); + NULL), rotcnt); gsi_insert_before (gsi, g, GSI_SAME_STMT); rotcnt = gimple_assign_lhs (g); } @@ -1740,7 +1738,7 @@ simplify_rotate (gimple_stmt_iterator *gsi) { gsi_insert_before (gsi, g, GSI_SAME_STMT); g = gimple_build_assign_with_ops (NOP_EXPR, gimple_assign_lhs (stmt), - lhs, NULL_TREE); + lhs); } gsi_replace (gsi, g, false); return true; @@ -2055,7 +2053,7 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi) for (i = 0; i < nelts; i++) mask_elts[i] = build_int_cst (TREE_TYPE (mask_type), sel[i]); op2 = build_vector (mask_type, mask_elts); - gimple_assign_set_rhs_with_ops_1 (gsi, VEC_PERM_EXPR, orig, orig, op2); + gimple_assign_set_rhs_with_ops (gsi, VEC_PERM_EXPR, orig, orig, op2); } update_stmt (gsi_stmt (*gsi)); return true; diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c index 6f64f4a801f..0e806f4b682 100644 --- a/gcc/tree-ssa-loop-im.c +++ b/gcc/tree-ssa-loop-im.c @@ -1217,7 +1217,7 @@ move_computations_dom_walker::before_dom_children (basic_block bb) tree arg = PHI_ARG_DEF (stmt, 0); new_stmt = gimple_build_assign_with_ops (TREE_CODE (arg), gimple_phi_result (stmt), - arg, NULL_TREE); + arg); } else { diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c index 219029084c5..f9c30bf72b6 100644 --- a/gcc/tree-ssa-math-opts.c +++ b/gcc/tree-ssa-math-opts.c @@ -1130,8 +1130,7 @@ build_and_insert_cast (gimple_stmt_iterator *gsi, location_t loc, tree type, tree val) { tree result = make_ssa_name (type, NULL); - gassign *stmt - = gimple_build_assign_with_ops (NOP_EXPR, result, val, NULL_TREE); + gassign *stmt = gimple_build_assign_with_ops (NOP_EXPR, result, val); gimple_set_location (stmt, loc); gsi_insert_before (gsi, stmt, GSI_SAME_STMT); return result; @@ -2261,13 +2260,11 @@ bswap_replace (gimple cur_stmt, gimple src_stmt, tree fndecl, tree bswap_type, load_stmt = gimple_build_assign (val_tmp, val_expr); gimple_set_vuse (load_stmt, n->vuse); gsi_insert_before (&gsi, load_stmt, GSI_SAME_STMT); - gimple_assign_set_rhs_with_ops_1 (&gsi, NOP_EXPR, val_tmp, - NULL_TREE, NULL_TREE); + gimple_assign_set_rhs_with_ops (&gsi, NOP_EXPR, val_tmp); } else { - gimple_assign_set_rhs_with_ops_1 (&gsi, MEM_REF, val_expr, - NULL_TREE, NULL_TREE); + gimple_assign_set_rhs_with_ops (&gsi, MEM_REF, val_expr); gimple_set_vuse (cur_stmt, n->vuse); } update_stmt (cur_stmt); @@ -2321,8 +2318,7 @@ bswap_replace (gimple cur_stmt, gimple src_stmt, tree fndecl, tree bswap_type, { gimple convert_stmt; tmp = make_temp_ssa_name (bswap_type, NULL, "bswapsrc"); - convert_stmt = gimple_build_assign_with_ops (NOP_EXPR, tmp, src, - NULL); + convert_stmt = gimple_build_assign_with_ops (NOP_EXPR, tmp, src); gsi_insert_before (&gsi, convert_stmt, GSI_SAME_STMT); } @@ -2336,7 +2332,7 @@ bswap_replace (gimple cur_stmt, gimple src_stmt, tree fndecl, tree bswap_type, { gimple convert_stmt; tmp = make_temp_ssa_name (bswap_type, NULL, "bswapdst"); - convert_stmt = gimple_build_assign_with_ops (NOP_EXPR, tgt, tmp, NULL); + convert_stmt = gimple_build_assign_with_ops (NOP_EXPR, tgt, tmp); gsi_insert_after (&gsi, convert_stmt, GSI_SAME_STMT); } @@ -2975,8 +2971,8 @@ convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple stmt, if (TREE_CODE (mult_rhs2) == INTEGER_CST) mult_rhs2 = fold_convert (type2, mult_rhs2); - gimple_assign_set_rhs_with_ops_1 (gsi, wmult_code, mult_rhs1, mult_rhs2, - add_rhs); + gimple_assign_set_rhs_with_ops (gsi, wmult_code, mult_rhs1, mult_rhs2, + add_rhs); update_stmt (gsi_stmt (*gsi)); widen_mul_stats.maccs_inserted++; return true; @@ -3180,8 +3176,7 @@ convert_mult_to_fma (gimple mul_stmt, tree op1, tree op2) fma_stmt = gimple_build_assign_with_ops (FMA_EXPR, gimple_assign_lhs (use_stmt), - mulop1, op2, - addop); + mulop1, op2, addop); gsi_replace (&gsi, fma_stmt, true); widen_mul_stats.fmas_inserted++; } diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c index 191845e0cdf..6ee2c39e618 100644 --- a/gcc/tree-ssa-phiopt.c +++ b/gcc/tree-ssa-phiopt.c @@ -538,7 +538,7 @@ conditional_replacement (basic_block cond_bb, basic_block middle_bb, new_var2 = make_ssa_name (TREE_TYPE (result), NULL); new_stmt = gimple_build_assign_with_ops (CONVERT_EXPR, new_var2, - new_var, NULL); + new_var); gsi_insert_before (&gsi, new_stmt, GSI_SAME_STMT); new_var = new_var2; @@ -1258,7 +1258,7 @@ abs_replacement (basic_block cond_bb, basic_block middle_bb, lhs = result; /* Build the modify expression with abs expression. */ - new_stmt = gimple_build_assign_with_ops (ABS_EXPR, lhs, rhs, NULL); + new_stmt = gimple_build_assign_with_ops (ABS_EXPR, lhs, rhs); gsi = gsi_last_bb (cond_bb); gsi_insert_before (&gsi, new_stmt, GSI_NEW_STMT); @@ -1268,7 +1268,7 @@ abs_replacement (basic_block cond_bb, basic_block middle_bb, /* Get the right GSI. We want to insert after the recently added ABS_EXPR statement (which we know is the first statement in the block. */ - new_stmt = gimple_build_assign_with_ops (NEGATE_EXPR, result, lhs, NULL); + new_stmt = gimple_build_assign_with_ops (NEGATE_EXPR, result, lhs); gsi_insert_after (&gsi, new_stmt, GSI_NEW_STMT); } @@ -1392,12 +1392,12 @@ neg_replacement (basic_block cond_bb, basic_block middle_bb, logical and arithmetic operations on it. */ tree cond_val_converted = make_ssa_name (TREE_TYPE (rhs), NULL); new_stmt = gimple_build_assign_with_ops (NOP_EXPR, cond_val_converted, - cond_val, NULL_TREE); + cond_val); gsi_insert_after (&gsi, new_stmt, GSI_NEW_STMT); tree neg_cond_val_converted = make_ssa_name (TREE_TYPE (rhs), NULL); new_stmt = gimple_build_assign_with_ops (NEGATE_EXPR, neg_cond_val_converted, - cond_val_converted, NULL_TREE); + cond_val_converted); gsi_insert_after (&gsi, new_stmt, GSI_NEW_STMT); tree tmp = make_ssa_name (TREE_TYPE (rhs), NULL); diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c index 76af82858f2..df99f0dea67 100644 --- a/gcc/tree-ssa-reassoc.c +++ b/gcc/tree-ssa-reassoc.c @@ -3307,7 +3307,7 @@ maybe_optimize_range_tests (gimple stmt) } else g = gimple_build_assign_with_ops (rhs_code, new_lhs, - new_op, NULL_TREE); + new_op); gimple_stmt_iterator gsi = gsi_for_stmt (cast_stmt); gimple_set_uid (g, gimple_uid (cast_stmt)); gimple_set_visited (g, true); @@ -4217,10 +4217,11 @@ repropagate_negates (void) tree b = gimple_assign_rhs2 (user); gimple_stmt_iterator gsi = gsi_for_stmt (feed); gimple_stmt_iterator gsi2 = gsi_for_stmt (user); - tree x = make_ssa_name (TREE_TYPE (gimple_assign_lhs (feed)), NULL); + tree x = make_ssa_name (TREE_TYPE (gimple_assign_lhs (feed)), + NULL); gimple g = gimple_build_assign_with_ops (PLUS_EXPR, x, a, b); gsi_insert_before (&gsi2, g, GSI_SAME_STMT); - gimple_assign_set_rhs_with_ops (&gsi2, NEGATE_EXPR, x, NULL); + gimple_assign_set_rhs_with_ops (&gsi2, NEGATE_EXPR, x); user = gsi_stmt (gsi2); update_stmt (user); reassoc_remove_stmt (&gsi); diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c index 5bd6c7624b9..c02e6128aa7 100644 --- a/gcc/tree-ssa-strlen.c +++ b/gcc/tree-ssa-strlen.c @@ -1816,7 +1816,7 @@ handle_pointer_plus (gimple_stmt_iterator *gsi) enum tree_code rhs_code = useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (si->endptr)) ? SSA_NAME : NOP_EXPR; - gimple_assign_set_rhs_with_ops (gsi, rhs_code, si->endptr, NULL_TREE); + gimple_assign_set_rhs_with_ops (gsi, rhs_code, si->endptr); gcc_assert (gsi_stmt (*gsi) == stmt); update_stmt (stmt); } diff --git a/gcc/tree-ssa-tail-merge.c b/gcc/tree-ssa-tail-merge.c index b294bf9f5ab..230a4223dbd 100644 --- a/gcc/tree-ssa-tail-merge.c +++ b/gcc/tree-ssa-tail-merge.c @@ -326,7 +326,8 @@ stmt_local_def (gimple stmt) if (gimple_vdef (stmt) != NULL_TREE || gimple_has_side_effects (stmt) - || gimple_could_trap_p_1 (stmt, false, false)) + || gimple_could_trap_p_1 (stmt, false, false) + || gimple_vuse (stmt) != NULL_TREE) return false; def_p = SINGLE_SSA_DEF_OPERAND (stmt, SSA_OP_DEF); @@ -1175,7 +1176,8 @@ gimple_equal_p (same_succ same_succ, gimple s1, gimple s2) gimple_assign_rhs1 (s2))); else if (TREE_CODE (lhs1) == SSA_NAME && TREE_CODE (lhs2) == SSA_NAME) - return vn_valueize (lhs1) == vn_valueize (lhs2); + return operand_equal_p (gimple_assign_rhs1 (s1), + gimple_assign_rhs1 (s2), 0); return false; case GIMPLE_COND: diff --git a/gcc/tree-vect-loop-manip.c b/gcc/tree-vect-loop-manip.c index cb76ade69d7..64ccaa3becf 100644 --- a/gcc/tree-vect-loop-manip.c +++ b/gcc/tree-vect-loop-manip.c @@ -2158,7 +2158,7 @@ vect_create_cond_for_align_checks (loop_vec_info loop_vinfo, sprintf (tmp_name, "addr2int%d", i); addr_tmp_name = make_temp_ssa_name (int_ptrsize_type, NULL, tmp_name); addr_stmt = gimple_build_assign_with_ops (NOP_EXPR, addr_tmp_name, - addr_base, NULL_TREE); + addr_base); gimple_seq_add_stmt (cond_expr_stmt_list, addr_stmt); /* The addresses are OR together. */ diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c index 41907facf8e..a4f9501b29e 100644 --- a/gcc/tree-vect-loop.c +++ b/gcc/tree-vect-loop.c @@ -2504,7 +2504,7 @@ vect_is_simple_reduction_1 (loop_vec_info loop_info, gimple phi, tree rhs = gimple_assign_rhs2 (def_stmt); tree negrhs = make_ssa_name (TREE_TYPE (rhs), NULL); gimple negate_stmt = gimple_build_assign_with_ops (NEGATE_EXPR, negrhs, - rhs, NULL); + rhs); gimple_stmt_iterator gsi = gsi_for_stmt (def_stmt); set_vinfo_for_stmt (negate_stmt, new_stmt_vec_info (negate_stmt, loop_info, NULL)); @@ -3383,7 +3383,7 @@ get_initial_def_for_induction (gimple iv_phi) new_stmt = gimple_build_assign_with_ops (VIEW_CONVERT_EXPR, vect_get_new_vect_var (vectype, vect_simple_var, "vec_iv_"), - build1 (VIEW_CONVERT_EXPR, vectype, vec_init), NULL_TREE); + build1 (VIEW_CONVERT_EXPR, vectype, vec_init)); vec_init = make_ssa_name (gimple_assign_lhs (new_stmt), new_stmt); gimple_assign_set_lhs (new_stmt, vec_init); new_bb = gsi_insert_on_edge_immediate (loop_preheader_edge (iv_loop), @@ -3559,7 +3559,7 @@ get_initial_def_for_induction (gimple iv_phi) vect_get_new_vect_var (resvectype, vect_simple_var, "vec_iv_"), build1 (VIEW_CONVERT_EXPR, resvectype, - gimple_assign_lhs (new_stmt)), NULL_TREE); + gimple_assign_lhs (new_stmt))); gimple_assign_set_lhs (new_stmt, make_ssa_name (gimple_assign_lhs (new_stmt), new_stmt)); @@ -3626,7 +3626,7 @@ get_initial_def_for_induction (gimple iv_phi) new_stmt = gimple_build_assign_with_ops (VIEW_CONVERT_EXPR, vect_get_new_vect_var (resvectype, vect_simple_var, "vec_iv_"), - build1 (VIEW_CONVERT_EXPR, resvectype, induc_def), NULL_TREE); + build1 (VIEW_CONVERT_EXPR, resvectype, induc_def)); induc_def = make_ssa_name (gimple_assign_lhs (new_stmt), new_stmt); gimple_assign_set_lhs (new_stmt, induc_def); si = gsi_after_labels (bb); diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c index aedfde0c191..f2bce3cbaa5 100644 --- a/gcc/tree-vect-patterns.c +++ b/gcc/tree-vect-patterns.c @@ -760,8 +760,7 @@ vect_handle_widen_op_by_const (gimple stmt, enum tree_code code, /* Create a_T = (NEW_TYPE) a_t; */ *oprnd = gimple_assign_rhs1 (def_stmt); new_oprnd = make_ssa_name (new_type, NULL); - new_stmt = gimple_build_assign_with_ops (NOP_EXPR, new_oprnd, *oprnd, - NULL_TREE); + new_stmt = gimple_build_assign_with_ops (NOP_EXPR, new_oprnd, *oprnd); STMT_VINFO_RELATED_STMT (vinfo_for_stmt (def_stmt)) = new_stmt; stmts->safe_push (def_stmt); *oprnd = new_oprnd; @@ -935,7 +934,7 @@ vect_recog_widen_mult_pattern (vec<gimple> *stmts, tree old_oprnd = gimple_assign_rhs1 (def_stmt); tree new_oprnd = make_ssa_name (half_type0, NULL); new_stmt = gimple_build_assign_with_ops (NOP_EXPR, new_oprnd, - old_oprnd, NULL_TREE); + old_oprnd); *oprnd = new_oprnd; } @@ -1032,8 +1031,7 @@ vect_recog_widen_mult_pattern (vec<gimple> *stmts, pattern_stmt = gimple_build_assign_with_ops (NOP_EXPR, vect_recog_temp_ssa_var (type, NULL), - gimple_assign_lhs (pattern_stmt), - NULL_TREE); + gimple_assign_lhs (pattern_stmt)); } if (dump_enabled_p ()) @@ -1443,7 +1441,7 @@ vect_operation_fits_smaller_type (gimple stmt, tree def, tree *new_type, oprnd = gimple_assign_rhs1 (def_stmt); new_oprnd = make_ssa_name (interm_type, NULL); new_stmt = gimple_build_assign_with_ops (NOP_EXPR, new_oprnd, - oprnd, NULL_TREE); + oprnd); STMT_VINFO_RELATED_STMT (vinfo_for_stmt (def_stmt)) = new_stmt; stmts->safe_push (def_stmt); oprnd = new_oprnd; @@ -1462,7 +1460,7 @@ vect_operation_fits_smaller_type (gimple stmt, tree def, tree *new_type, /* Create a type conversion HALF_TYPE->INTERM_TYPE. */ new_oprnd = make_ssa_name (interm_type, NULL); new_stmt = gimple_build_assign_with_ops (NOP_EXPR, new_oprnd, - oprnd, NULL_TREE); + oprnd); oprnd = new_oprnd; *new_def_stmt = new_stmt; } @@ -1594,7 +1592,7 @@ vect_recog_over_widening_pattern (vec<gimple> *stmts, /* Create NEW_TYPE->USE_TYPE conversion. */ new_oprnd = make_ssa_name (use_type, NULL); pattern_stmt = gimple_build_assign_with_ops (NOP_EXPR, new_oprnd, - var, NULL_TREE); + var); STMT_VINFO_RELATED_STMT (vinfo_for_stmt (use_stmt)) = pattern_stmt; *type_in = get_vectype_for_scalar_type (new_type); @@ -1946,8 +1944,7 @@ vect_recog_rotate_pattern (vec<gimple> *stmts, tree *type_in, tree *type_out) if (def == NULL_TREE) { def = vect_recog_temp_ssa_var (type, NULL); - def_stmt = gimple_build_assign_with_ops (NOP_EXPR, def, oprnd1, - NULL_TREE); + def_stmt = gimple_build_assign_with_ops (NOP_EXPR, def, oprnd1); if (ext_def) { basic_block new_bb @@ -1977,8 +1974,7 @@ vect_recog_rotate_pattern (vec<gimple> *stmts, tree *type_in, tree *type_out) if (vecstype == NULL_TREE) return NULL; def2 = vect_recog_temp_ssa_var (stype, NULL); - def_stmt = gimple_build_assign_with_ops (NEGATE_EXPR, def2, def, - NULL_TREE); + def_stmt = gimple_build_assign_with_ops (NEGATE_EXPR, def2, def); if (ext_def) { basic_block new_bb @@ -2151,8 +2147,7 @@ vect_recog_vector_vector_shift_pattern (vec<gimple> *stmts, if (def == NULL_TREE) { def = vect_recog_temp_ssa_var (TREE_TYPE (oprnd0), NULL); - def_stmt = gimple_build_assign_with_ops (NOP_EXPR, def, oprnd1, - NULL_TREE); + def_stmt = gimple_build_assign_with_ops (NOP_EXPR, def, oprnd1); new_pattern_def_seq (stmt_vinfo, def_stmt); } @@ -2350,8 +2345,7 @@ vect_recog_divmod_pattern (vec<gimple> *stmts, append_pattern_def_seq (stmt_vinfo, def_stmt); signmask = vect_recog_temp_ssa_var (itype, NULL); def_stmt - = gimple_build_assign_with_ops (NOP_EXPR, signmask, var, - NULL_TREE); + = gimple_build_assign_with_ops (NOP_EXPR, signmask, var); append_pattern_def_seq (stmt_vinfo, def_stmt); } def_stmt @@ -2613,8 +2607,7 @@ vect_recog_divmod_pattern (vec<gimple> *stmts, if (msb != 1) def_stmt = gimple_build_assign_with_ops (INTEGER_CST, - t4, build_int_cst (itype, msb), - NULL_TREE); + t4, build_int_cst (itype, msb)); else def_stmt = gimple_build_assign_with_ops (RSHIFT_EXPR, t4, oprnd0, @@ -2809,7 +2802,7 @@ vect_recog_mixed_size_cond_pattern (vec<gimple> *stmts, tree *type_in, pattern_stmt = gimple_build_assign_with_ops (NOP_EXPR, vect_recog_temp_ssa_var (type, NULL), - gimple_assign_lhs (def_stmt), NULL_TREE); + gimple_assign_lhs (def_stmt)); new_pattern_def_seq (stmt_vinfo, def_stmt); def_stmt_info = new_stmt_vec_info (def_stmt, loop_vinfo, bb_vinfo); @@ -2923,8 +2916,7 @@ adjust_bool_pattern_cast (tree type, tree var) cast_stmt = gimple_build_assign_with_ops (NOP_EXPR, vect_recog_temp_ssa_var (type, NULL), - gimple_assign_lhs (pattern_stmt), - NULL_TREE); + gimple_assign_lhs (pattern_stmt)); STMT_VINFO_RELATED_STMT (stmt_vinfo) = cast_stmt; return gimple_assign_lhs (cast_stmt); } @@ -2961,7 +2953,7 @@ adjust_bool_pattern (tree var, tree out_type, tree trueval, pattern_stmt = gimple_build_assign_with_ops (SSA_NAME, vect_recog_temp_ssa_var (itype, NULL), - irhs1, NULL_TREE); + irhs1); break; case BIT_NOT_EXPR: @@ -3209,10 +3201,10 @@ vect_recog_bool_pattern (vec<gimple> *stmts, tree *type_in, lhs = vect_recog_temp_ssa_var (TREE_TYPE (lhs), NULL); if (useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs))) pattern_stmt - = gimple_build_assign_with_ops (SSA_NAME, lhs, rhs, NULL_TREE); + = gimple_build_assign_with_ops (SSA_NAME, lhs, rhs); else pattern_stmt - = gimple_build_assign_with_ops (NOP_EXPR, lhs, rhs, NULL_TREE); + = gimple_build_assign_with_ops (NOP_EXPR, lhs, rhs); *type_out = vectype; *type_in = vectype; stmts->safe_push (last_stmt); @@ -3278,12 +3270,12 @@ vect_recog_bool_pattern (vec<gimple> *stmts, tree *type_in, { tree rhs2 = vect_recog_temp_ssa_var (TREE_TYPE (lhs), NULL); gimple cast_stmt - = gimple_build_assign_with_ops (NOP_EXPR, rhs2, rhs, NULL_TREE); + = gimple_build_assign_with_ops (NOP_EXPR, rhs2, rhs); new_pattern_def_seq (stmt_vinfo, cast_stmt); rhs = rhs2; } pattern_stmt - = gimple_build_assign_with_ops (SSA_NAME, lhs, rhs, NULL_TREE); + = gimple_build_assign_with_ops (SSA_NAME, lhs, rhs); pattern_stmt_info = new_stmt_vec_info (pattern_stmt, loop_vinfo, bb_vinfo); set_vinfo_for_stmt (pattern_stmt, pattern_stmt_info); diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c index efb3b4c0fb3..829f74aaea8 100644 --- a/gcc/tree-vect-slp.c +++ b/gcc/tree-vect-slp.c @@ -2610,7 +2610,7 @@ vect_get_constant_vectors (tree op, slp_tree slp_node, op); init_stmt = gimple_build_assign_with_ops (VIEW_CONVERT_EXPR, - new_temp, op, NULL_TREE); + new_temp, op); gimple_seq_add_stmt (&ctor_seq, init_stmt); op = new_temp; } diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c index c153f422587..e80ac95a7fe 100644 --- a/gcc/tree-vect-stmts.c +++ b/gcc/tree-vect-stmts.c @@ -1333,8 +1333,7 @@ vect_init_vector (gimple stmt, tree val, tree type, gimple_stmt_iterator *gsi) { new_temp = make_ssa_name (TREE_TYPE (type), NULL); init_stmt = gimple_build_assign_with_ops (NOP_EXPR, - new_temp, val, - NULL_TREE); + new_temp, val); vect_init_vector_1 (stmt, init_stmt, gsi); val = new_temp; } @@ -1970,8 +1969,7 @@ vectorizable_mask_load_store (gimple stmt, gimple_stmt_iterator *gsi, var = make_ssa_name (var, NULL); op = build1 (VIEW_CONVERT_EXPR, idxtype, op); new_stmt - = gimple_build_assign_with_ops (VIEW_CONVERT_EXPR, var, - op, NULL_TREE); + = gimple_build_assign_with_ops (VIEW_CONVERT_EXPR, var, op); vect_finish_stmt_generation (stmt, new_stmt, gsi); op = var; } @@ -2001,7 +1999,7 @@ vectorizable_mask_load_store (gimple stmt, gimple_stmt_iterator *gsi, mask_op = build1 (VIEW_CONVERT_EXPR, masktype, mask_op); new_stmt = gimple_build_assign_with_ops (VIEW_CONVERT_EXPR, var, - mask_op, NULL_TREE); + mask_op); vect_finish_stmt_generation (stmt, new_stmt, gsi); mask_op = var; } @@ -2022,8 +2020,7 @@ vectorizable_mask_load_store (gimple stmt, gimple_stmt_iterator *gsi, var = make_ssa_name (vec_dest, NULL); op = build1 (VIEW_CONVERT_EXPR, vectype, op); new_stmt - = gimple_build_assign_with_ops (VIEW_CONVERT_EXPR, var, op, - NULL_TREE); + = gimple_build_assign_with_ops (VIEW_CONVERT_EXPR, var, op); } else { @@ -3197,7 +3194,7 @@ vectorizable_simd_clone_call (gimple stmt, gimple_stmt_iterator *gsi, 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); + gsi_replace (gsi, new_stmt, true); unlink_stmt_vdef (stmt); return true; @@ -3792,7 +3789,7 @@ vectorizable_conversion (gimple stmt, gimple_stmt_iterator *gsi, { gcc_assert (TREE_CODE_LENGTH (code1) == unary_op); new_stmt = gimple_build_assign_with_ops (code1, vec_dest, - vop0, NULL); + vop0); new_temp = make_ssa_name (vec_dest, new_stmt); gimple_assign_set_lhs (new_stmt, new_temp); } @@ -3904,8 +3901,7 @@ vectorizable_conversion (gimple stmt, gimple_stmt_iterator *gsi, gcc_assert (TREE_CODE_LENGTH (codecvt1) == unary_op); new_temp = make_ssa_name (vec_dest, NULL); new_stmt = gimple_build_assign_with_ops (codecvt1, - new_temp, - vop0, NULL); + new_temp, vop0); } vect_finish_stmt_generation (stmt, new_stmt, gsi); @@ -3962,7 +3958,7 @@ vectorizable_conversion (gimple stmt, gimple_stmt_iterator *gsi, gcc_assert (TREE_CODE_LENGTH (codecvt1) == unary_op); new_temp = make_ssa_name (vec_dest, NULL); new_stmt = gimple_build_assign_with_ops (codecvt1, new_temp, - vop0, NULL); + vop0); } vect_finish_stmt_generation (stmt, new_stmt, gsi); @@ -5960,8 +5956,7 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt, var = make_ssa_name (var, NULL); op = build1 (VIEW_CONVERT_EXPR, idxtype, op); new_stmt - = gimple_build_assign_with_ops (VIEW_CONVERT_EXPR, var, - op, NULL_TREE); + = gimple_build_assign_with_ops (VIEW_CONVERT_EXPR, var, op); vect_finish_stmt_generation (stmt, new_stmt, gsi); op = var; } @@ -5980,8 +5975,7 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt, var = make_ssa_name (vec_dest, NULL); op = build1 (VIEW_CONVERT_EXPR, vectype, op); new_stmt - = gimple_build_assign_with_ops (VIEW_CONVERT_EXPR, var, op, - NULL_TREE); + = gimple_build_assign_with_ops (VIEW_CONVERT_EXPR, var, op); } else { diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index 62ec3f24bcd..bcf4c2ba60c 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -8880,8 +8880,7 @@ simplify_truth_ops_using_ranges (gimple_stmt_iterator *gsi, gimple stmt) if (integer_zerop (op1)) gimple_assign_set_rhs_with_ops (gsi, need_conversion - ? NOP_EXPR : TREE_CODE (op0), - op0, NULL_TREE); + ? NOP_EXPR : TREE_CODE (op0), op0); /* For A != B we substitute A ^ B. Either with conversion. */ else if (need_conversion) { @@ -8889,7 +8888,7 @@ simplify_truth_ops_using_ranges (gimple_stmt_iterator *gsi, gimple stmt) gassign *newop = gimple_build_assign_with_ops (BIT_XOR_EXPR, tem, op0, op1); gsi_insert_before (gsi, newop, GSI_SAME_STMT); - gimple_assign_set_rhs_with_ops (gsi, NOP_EXPR, tem, NULL_TREE); + gimple_assign_set_rhs_with_ops (gsi, NOP_EXPR, tem); } /* Or without. */ else @@ -9109,7 +9108,7 @@ simplify_bit_ops_using_ranges (gimple_stmt_iterator *gsi, gimple stmt) if (op == NULL_TREE) return false; - gimple_assign_set_rhs_with_ops (gsi, TREE_CODE (op), op, NULL); + gimple_assign_set_rhs_with_ops (gsi, TREE_CODE (op), op); update_stmt (gsi_stmt (*gsi)); return true; } @@ -9613,7 +9612,7 @@ simplify_float_conversion_using_ranges (gimple_stmt_iterator *gsi, gimple stmt) float conversion. */ tem = make_ssa_name (build_nonstandard_integer_type (GET_MODE_PRECISION (mode), 0), NULL); - conv = gimple_build_assign_with_ops (NOP_EXPR, tem, rhs1, NULL_TREE); + conv = gimple_build_assign_with_ops (NOP_EXPR, tem, rhs1); gsi_insert_before (gsi, conv, GSI_SAME_STMT); gimple_assign_set_rhs1 (stmt, tem); update_stmt (stmt); @@ -9687,8 +9686,7 @@ simplify_internal_call_using_ranges (gimple_stmt_iterator *gsi, gimple stmt) else if (!useless_type_conversion_p (utype, TREE_TYPE (op0))) { g = gimple_build_assign_with_ops (NOP_EXPR, - make_ssa_name (utype, NULL), - op0, NULL_TREE); + make_ssa_name (utype, NULL), op0); gimple_set_location (g, loc); gsi_insert_before (gsi, g, GSI_SAME_STMT); op0 = gimple_assign_lhs (g); @@ -9698,8 +9696,7 @@ simplify_internal_call_using_ranges (gimple_stmt_iterator *gsi, gimple stmt) else if (!useless_type_conversion_p (utype, TREE_TYPE (op1))) { g = gimple_build_assign_with_ops (NOP_EXPR, - make_ssa_name (utype, NULL), - op1, NULL_TREE); + make_ssa_name (utype, NULL), op1); gimple_set_location (g, loc); gsi_insert_before (gsi, g, GSI_SAME_STMT); op1 = gimple_assign_lhs (g); @@ -9712,7 +9709,7 @@ simplify_internal_call_using_ranges (gimple_stmt_iterator *gsi, gimple stmt) { g = gimple_build_assign_with_ops (NOP_EXPR, make_ssa_name (type, NULL), - gimple_assign_lhs (g), NULL_TREE); + gimple_assign_lhs (g)); gimple_set_location (g, loc); gsi_insert_before (gsi, g, GSI_SAME_STMT); } diff --git a/gcc/tsan.c b/gcc/tsan.c index 53f30a1b833..763f57383be 100644 --- a/gcc/tsan.c +++ b/gcc/tsan.c @@ -501,8 +501,7 @@ instrument_builtin_call (gimple_stmt_iterator *gsi) TREE_TYPE (args[1]))) { tree var = make_ssa_name (TREE_TYPE (lhs), NULL); - g = gimple_build_assign_with_ops (NOP_EXPR, var, - args[1], NULL_TREE); + g = gimple_build_assign_with_ops (NOP_EXPR, var, args[1]); gsi_insert_after (gsi, g, GSI_NEW_STMT); args[1] = var; } @@ -516,8 +515,7 @@ instrument_builtin_call (gimple_stmt_iterator *gsi) gimple_call_lhs (stmt), args[1]); gsi_insert_after (gsi, g, GSI_NEW_STMT); - g = gimple_build_assign_with_ops (BIT_NOT_EXPR, lhs, var, - NULL_TREE); + g = gimple_build_assign_with_ops (BIT_NOT_EXPR, lhs, var); } else g = gimple_build_assign_with_ops (tsan_atomic_table[i].code, @@ -560,7 +558,7 @@ instrument_builtin_call (gimple_stmt_iterator *gsi) g = gimple_build_assign_with_ops (NOP_EXPR, make_ssa_name (TREE_TYPE (t), NULL), - args[1], NULL_TREE); + args[1]); gsi_insert_before (gsi, g, GSI_SAME_STMT); args[1] = gimple_assign_lhs (g); } diff --git a/gcc/ubsan.c b/gcc/ubsan.c index db79d4b9e15..5da0b180928 100644 --- a/gcc/ubsan.c +++ b/gcc/ubsan.c @@ -67,6 +67,7 @@ along with GCC; see the file COPYING3. If not see #include "dfp.h" #include "builtins.h" #include "tree-object-size.h" +#include "tree-eh.h" /* Map from a tree to a VAR_DECL tree. */ @@ -735,8 +736,7 @@ ubsan_expand_null_ifn (gimple_stmt_iterator *gsip) if (compare_tree_int (align, ptralign) == 1) { check_align = make_ssa_name (pointer_sized_int_node, NULL); - g = gimple_build_assign_with_ops (NOP_EXPR, check_align, - ptr, NULL_TREE); + g = gimple_build_assign_with_ops (NOP_EXPR, check_align, ptr); gimple_set_location (g, loc); gsi_insert_before (&gsi, g, GSI_SAME_STMT); } @@ -933,7 +933,7 @@ ubsan_expand_objsize_ifn (gimple_stmt_iterator *gsi) ? BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH : BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT; tree p = make_ssa_name (pointer_sized_int_node, NULL); - g = gimple_build_assign_with_ops (NOP_EXPR, p, ptr, NULL_TREE); + g = gimple_build_assign_with_ops (NOP_EXPR, p, ptr); gimple_set_location (g, loc); gsi_insert_before (gsi, g, GSI_SAME_STMT); g = gimple_build_call (builtin_decl_explicit (bcode), 2, data, p); @@ -1159,7 +1159,9 @@ instrument_bool_enum_load (gimple_stmt_iterator *gsi) || TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME) return; + bool can_throw = stmt_could_throw_p (stmt); location_t loc = gimple_location (stmt); + tree lhs = gimple_assign_lhs (stmt); tree ptype = build_pointer_type (TREE_TYPE (rhs)); tree atype = reference_alias_ptr_type (rhs); gimple g = gimple_build_assign (make_ssa_name (ptype, NULL), @@ -1169,9 +1171,24 @@ instrument_bool_enum_load (gimple_stmt_iterator *gsi) tree mem = build2 (MEM_REF, utype, gimple_assign_lhs (g), build_int_cst (atype, 0)); tree urhs = make_ssa_name (utype, NULL); - g = gimple_build_assign (urhs, mem); - gimple_set_location (g, loc); - gsi_insert_before (gsi, g, GSI_SAME_STMT); + if (can_throw) + { + gimple_assign_set_lhs (stmt, urhs); + g = gimple_build_assign_with_ops (NOP_EXPR, lhs, urhs); + gimple_set_location (g, loc); + edge e = find_fallthru_edge (gimple_bb (stmt)->succs); + gsi_insert_on_edge_immediate (e, g); + gimple_assign_set_rhs_from_tree (gsi, mem); + update_stmt (stmt); + *gsi = gsi_for_stmt (g); + g = stmt; + } + else + { + g = gimple_build_assign (urhs, mem); + gimple_set_location (g, loc); + gsi_insert_before (gsi, g, GSI_SAME_STMT); + } minv = fold_convert (utype, minv); maxv = fold_convert (utype, maxv); if (!integer_zerop (minv)) @@ -1193,8 +1210,11 @@ instrument_bool_enum_load (gimple_stmt_iterator *gsi) gimple_set_location (g, loc); gsi_insert_after (gsi, g, GSI_NEW_STMT); - gimple_assign_set_rhs_with_ops (&gsi2, NOP_EXPR, urhs, NULL_TREE); - update_stmt (stmt); + if (!can_throw) + { + gimple_assign_set_rhs_with_ops (&gsi2, NOP_EXPR, urhs); + update_stmt (stmt); + } gsi2 = gsi_after_labels (then_bb); if (flag_sanitize_undefined_trap_on_error) @@ -1518,7 +1538,13 @@ instrument_object_size (gimple_stmt_iterator *gsi, bool is_lhs) return; bool decl_p = DECL_P (inner); - tree base = decl_p ? inner : TREE_OPERAND (inner, 0); + tree base; + if (decl_p) + base = inner; + else if (TREE_CODE (inner) == MEM_REF) + base = TREE_OPERAND (inner, 0); + else + return; tree ptr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (t)), t); while (TREE_CODE (base) == SSA_NAME) diff --git a/gcc/varpool.c b/gcc/varpool.c index 80dd496a49a..50f2e6e755a 100644 --- a/gcc/varpool.c +++ b/gcc/varpool.c @@ -171,9 +171,11 @@ varpool_node::get_create (tree decl) && lookup_attribute ("omp declare target", DECL_ATTRIBUTES (decl))) { node->offloadable = 1; +#ifdef ENABLE_OFFLOADING g->have_offload = true; if (!in_lto_p) vec_safe_push (offload_vars, decl); +#endif } node->register_symbol (); diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog index 737cd2476b6..5e6d3bf29ea 100644 --- a/libgomp/ChangeLog +++ b/libgomp/ChangeLog @@ -1,3 +1,9 @@ +2014-11-19 Uros Bizjak <ubizjak@gmail.com> + + * testsuite/libgomp.c/examples-4/e.53.5.c: Require + vect_simd_clones effective target. + * testsuite/libgomp.fortran/examples-4/e.53.5.f90: Ditto. + 2014-11-14 Jakub Jelinek <jakub@redhat.com> * libgomp.c/examples-4/e.54.2.c (main): Use N / 8 instead diff --git a/libgomp/testsuite/libgomp.c/examples-4/e.53.5.c b/libgomp/testsuite/libgomp.c/examples-4/e.53.5.c index 3bcd753dbbb..2b16dbed6b2 100644 --- a/libgomp/testsuite/libgomp.c/examples-4/e.53.5.c +++ b/libgomp/testsuite/libgomp.c/examples-4/e.53.5.c @@ -1,4 +1,4 @@ -/* { dg-do run } */ +/* { dg-do run { target vect_simd_clones } } */ /* { dg-options "-O2" } */ /* { dg-additional-options "-msse2" { target sse2_runtime } } */ /* { dg-additional-options "-mavx" { target avx_runtime } } */ diff --git a/libgomp/testsuite/libgomp.fortran/examples-4/e.53.5.f90 b/libgomp/testsuite/libgomp.fortran/examples-4/e.53.5.f90 index 304c9fb2ada..06eae0a6992 100644 --- a/libgomp/testsuite/libgomp.fortran/examples-4/e.53.5.f90 +++ b/libgomp/testsuite/libgomp.fortran/examples-4/e.53.5.f90 @@ -1,4 +1,4 @@ -! { dg-do run } +! { dg-do run { target vect_simd_clones } } ! { dg-options "-O2" } ! { dg-additional-options "-msse2" { target sse2_runtime } } ! { dg-additional-options "-mavx" { target avx_runtime } } diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 857c05e163e..c0e17389558 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,12 @@ +2014-11-18 Marc Glisse <marc.glisse@inria.fr> + + PR libstdc++/43622 + * config/abi/pre/float128.ver: New file. + * configure.ac: Use float128.ver when relevant. + * configure: Regenerate. + * testsuite/util/testsuite_abi.cc (check_version): Accept new + CXXABI_FLOAT128 version. + 2014-11-17 Jason Merrill <jason@redhat.com> * include/backward/binders.h: Suppress -Wdeprecated-declarations. diff --git a/libstdc++-v3/config/abi/pre/float128.ver b/libstdc++-v3/config/abi/pre/float128.ver new file mode 100644 index 00000000000..26c62c70be0 --- /dev/null +++ b/libstdc++-v3/config/abi/pre/float128.ver @@ -0,0 +1,10 @@ +# Appended to version file. + +CXXABI_FLOAT128 { + + # typeinfo and typeinfo name for __float128 + _ZT[IS]g; + _ZT[IS]Pg; + _ZT[IS]PKg; + +}; diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure index 6a57537b87c..5fcb705b363 100755 --- a/libstdc++-v3/configure +++ b/libstdc++-v3/configure @@ -15710,6 +15710,9 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $ ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test "$enable_float128" = yes; then + port_specific_symbol_files="$port_specific_symbol_files \$(top_srcdir)/config/abi/pre/float128.ver" +fi # Checks for compiler support that doesn't require linking. diff --git a/libstdc++-v3/configure.ac b/libstdc++-v3/configure.ac index eb826e4133f..135d536e1b2 100644 --- a/libstdc++-v3/configure.ac +++ b/libstdc++-v3/configure.ac @@ -153,6 +153,9 @@ GLIBCXX_ENABLE_THREADS GLIBCXX_ENABLE_ATOMIC_BUILTINS GLIBCXX_ENABLE_DECIMAL_FLOAT GLIBCXX_ENABLE_INT128_FLOAT128 +if test "$enable_float128" = yes; then + port_specific_symbol_files="$port_specific_symbol_files \$(top_srcdir)/config/abi/pre/float128.ver" +fi # Checks for compiler support that doesn't require linking. GLIBCXX_CHECK_COMPILER_FEATURES diff --git a/libstdc++-v3/testsuite/util/testsuite_abi.cc b/libstdc++-v3/testsuite/util/testsuite_abi.cc index 06991144dc1..15b05dcb957 100644 --- a/libstdc++-v3/testsuite/util/testsuite_abi.cc +++ b/libstdc++-v3/testsuite/util/testsuite_abi.cc @@ -213,6 +213,7 @@ check_version(symbol& test, bool added) known_versions.push_back("CXXABI_1.3.8"); known_versions.push_back("CXXABI_1.3.9"); known_versions.push_back("CXXABI_TM_1"); + known_versions.push_back("CXXABI_FLOAT128"); } compat_list::iterator begin = known_versions.begin(); compat_list::iterator end = known_versions.end(); @@ -230,16 +231,18 @@ check_version(symbol& test, bool added) // Check that added symbols are added in the latest pre-release version. bool latestp = (test.version_name == "GLIBCXX_3.4.21" || test.version_name == "CXXABI_1.3.9" + || test.version_name == "CXXABI_FLOAT128" || test.version_name == "CXXABI_TM_1"); if (added && !latestp) test.version_status = symbol::incompatible; // Check that long double compatibility symbols demangled as - // __float128 are put into some _LDBL_ version name. + // __float128 and regular __float128 symbols are put into some _LDBL_ + // or _FLOAT128 version name. if (added && test.demangled_name.find("__float128") != std::string::npos) { - // Has to be in _LDBL_ version name. - if (test.version_name.find("_LDBL_") == std::string::npos) + if (test.version_name.find("_LDBL_") == std::string::npos + && test.version_name.find("_FLOAT128") == std::string::npos) test.version_status = symbol::incompatible; } |