diff options
author | Martin Liska <mliska@suse.cz> | 2022-01-24 13:35:09 +0100 |
---|---|---|
committer | Martin Liska <mliska@suse.cz> | 2022-01-24 13:35:09 +0100 |
commit | 58446a69f792166ea2e12d44d5bb3ef1aa61c00d (patch) | |
tree | 7320e828f0d82d1118a138d0bc63fdfbb92c9716 /gcc | |
parent | 60af3ff91f0c1f7436624f2e2c8f6fe110c36bb6 (diff) | |
parent | 978abe918f8c8deed28e92297d3c0cc39086ad83 (diff) | |
download | gcc-58446a69f792166ea2e12d44d5bb3ef1aa61c00d.zip gcc-58446a69f792166ea2e12d44d5bb3ef1aa61c00d.tar.gz gcc-58446a69f792166ea2e12d44d5bb3ef1aa61c00d.tar.bz2 |
Merge branch 'master' into devel/sphinx
Diffstat (limited to 'gcc')
165 files changed, 3306 insertions, 465 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a8837ed..3a7842c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,318 @@ +2022-01-23 Andrew Pinski <apinski@marvell.com> + + PR target/64821 + * config/aarch64/aarch64-builtins.cc + (aarch64_general_gimple_fold_builtin): Handle + __builtin_aarch64_sqrt* and simplify into SQRT internal + function. + +2022-01-22 Jakub Jelinek <jakub@redhat.com> + + PR other/104176 + * opts-global.cc (handle_common_deferred_options): Quote + --enable-plugin in diagnostics to avoid -Werror=format-diag. + +2022-01-21 Michael Meissner <meissner@the-meissners.org> + + PR target/104136 + * config/rs6000/rs6000-protos.h (prefixed_xxsplti_p): Delete. + * config/rs6000/rs6000.cc (prefixed_xxsplti_p): Delete. + * config/rs6000/rs6000.md (prefixed attribute): Delete section + that sets the prefixed attribute for xxspltiw, xxspltidp, and + xxsplti32dx instructions. + (movsf_hardfloat): Explicitly set the prefixed attribute + when xxspltiw and xxspltidp instructions are generated. + (mov<mode>_hardfloat32): Likewise. + (mov<mode>_hardfloat64): Likewise. + * config/rs6000/vsx.md (vsx_mov<mode>_64bit): Explicitly set the + prefixed attribute for xxspltiw and xxspltidp instructions. + (vsx_mov<mode>_32bit): Likewise. + +2022-01-21 H.J. Lu <hjl.tools@gmail.com> + + PR bootstrap/104170 + * common/config/i386/i386-common.cc (ix86_supports_split_stack): + Return true only on glibc. + * config/i386/gnu-user-common.h (STACK_CHECK_STATIC_BUILTIN): + Revert commit c163647ffbc. + * config/i386/gnu.h (TARGET_LIBC_PROVIDES_SSP): Likewise. + +2022-01-21 Sören Tempel <soeren@soeren-tempel.net> + + * common/config/s390/s390-common.cc (s390_supports_split_stack): + Only support split-stack on glibc targets. + * config/i386/gnu-user-common.h (STACK_CHECK_STATIC_BUILTIN): Ditto. + * config/i386/gnu.h (defined): Ditto. + +2022-01-21 Bill Schmidt <wschmidt@linux.ibm.com> + + * config/rs6000/rs6000-overload.def (VEC_SLDW): Add instances for + vector float and vector double. + +2022-01-21 Bill Seurer <seurer@gcc.gnu.org> + + * config/rs6000/rs6000.cc (rs6000_get_function_versions_dispatcher): + Fix mention of ifunc in string. + +2022-01-21 Roger Sayle <roger@nextmovesoftware.com> + + PR middle-end/104140 + * tree-ssa-math-opts.cc (convert_mult_to_highpart): Check that the + operands of the widening multiplication are either both signed or + both unsigned, and abort the conversion if mismatched. + * doc/generic.texi (WIDEN_MULT_EXPR): Describe expression node. + (MULT_HIGHPART_EXPR): Clarify that operands must have the same + signedness. + * tree.def (MULT_HIGHPART_EXPR): Document both operands must have + integer types with the same precision and signedness. + (WIDEN_MULT_EXPR): Document that operands must have integer types + with the same precision, but possibly differing signedness. + * config/riscv/riscv-c.cc (riscv_cpu_cpp_builtins): Defend against + riscv_current_subset_list returning a NULL pointer (empty list). + +2022-01-21 Vladimir N. Makarov <vmakarov@redhat.com> + + PR target/103676 + * ira.h (struct target_ira): Add member + x_ira_exclude_class_mode_regs. + (ira_exclude_class_mode_regs): New macro. + * lra.h (lra_create_new_reg): Add arg exclude_start_hard_regs and + move from here ... + * lra-int.h: ... to here. + (lra_create_new_reg_with_unique_value): Add arg + exclude_start_hard_regs. + (class lra_reg): Add member exclude_start_hard_regs. + * lra-assigns.cc (find_hard_regno_for_1): Setup + impossible_start_hard_regs from exclude_start_hard_regs. + * lra-constraints.cc (get_reload_reg): Add arg exclude_start_hard_regs and pass + it lra_create_new_reg[_with_unique_value]. + (match_reload): Ditto. + (check_and_process_move): Pass NULL + exclude_start_hard_regs to lra_create_new_reg_with_unique_value. + (goal_alt_exclude_start_hard_regs): New static variable. + (process_addr_reg, simplify_operand_subreg): Pass NULL + exclude_start_hard_regs to lra_create_new_reg_with_unique_value + and get_reload_reg. + (process_alt_operands): Setup goal_alt_exclude_start_hard_regs. + Use this_alternative_exclude_start_hard_regs additionally to find + winning operand alternative. + (base_to_reg, base_plus_disp_to_reg, index_part_to_reg): Pass NULL + exclude_start_hard_regs to lra_create_new_reg. + (process_address_1, emit_inc): Ditto. + (curr_insn_transform): Pass exclude_start_hard_regs value to + lra_create_new_reg, get_reload_reg, match_reload. + (inherit_reload_reg, split_reg): Pass NULL exclude_start_hard_regs + to lra_create_new_reg. + (process_invariant_for_inheritance): Ditto. + * lra-remat.cc (update_scratch_ops): Ditto. + * lra.cc (lra_create_new_reg_with_unique_value): Add arg + exclude_start_hard_regs. Setup the corresponding member of + lra reg info. + (lra_create_new_reg): Add arg exclude_start_hard_regs and pass it + to lra_create_new_reg_with_unique_value. + (initialize_lra_reg_info_element): Initialize member + exclude_start_hard_regs. + (get_scratch_reg): Pass NULL to lra_create_new_reg. + * ira.cc (setup_prohibited_class_mode_regs): Rename to + setup_prohibited_and_exclude_class_mode_regs and calculate + ira_exclude_class_mode_regs. + +2022-01-21 Martin Liska <mliska@suse.cz> + + * configure.ac: Detect ld_is_mold and use it for + comdat_group=yes and gcc_cv_ld_hidden=yes. + * configure: Regenerate. + +2022-01-21 Richard Biener <rguenther@suse.de> + + PR tree-optimization/100089 + * tree-vect-slp.cc (vect_slp_region): Reject BB vectorization + of if-converted loops with unvectorized COND_EXPRs for + all but the unlimited cost models. + +2022-01-21 Ard Biesheuvel <ardb@kernel.org> + + * config/arm/arm-opts.h (enum stack_protector_guard): New. + * config/arm/arm-protos.h (arm_stack_protect_tls_canary_mem): + New. + * config/arm/arm.cc (TARGET_STACK_PROTECT_GUARD): Define. + (arm_option_override_internal): Handle and put in error checks. + for stack protector guard options. + (arm_option_reconfigure_globals): Likewise. + (arm_stack_protect_tls_canary_mem): New. + (arm_stack_protect_guard): New. + * config/arm/arm.md (stack_protect_set): New. + (stack_protect_set_tls): Likewise. + (stack_protect_test): Likewise. + (stack_protect_test_tls): Likewise. + (reload_tp_hard): Likewise. + * config/arm/arm.opt (-mstack-protector-guard): New + (-mstack-protector-guard-offset): New. + * doc/invoke.texi: Document new options. + +2022-01-21 Richard Biener <rguenther@suse.de> + + PR tree-optimization/104156 + * tree-ssa-loop-unswitch.cc (tree_unswitch_outer_loop): + Collect and reset debug stmts with out-of-loop uses when + hoisting guards. + (find_loop_guard): Adjust. + (empty_bb_without_guard_p): Likewise. Ignore debug stmts. + (used_outside_loop_p): Push debug uses to a vector of + debug stmts to reset. + (hoist_guard): Adjust -fopt-info category. + +2022-01-21 Richard Biener <rguenther@suse.de> + + PR tree-optimization/104152 + * tree-vect-slp.cc (vect_build_slp_tree_2): Add missing + can_duplicate_and_interleave_p check. + +2022-01-21 Jakub Jelinek <jakub@redhat.com> + + * gimple-ssa-warn-access.cc (pass_waccess::warn_invalid_pointer): + Avoid passing var to warning_at when the format string doesn't + refer to it. + +2022-01-21 Aldy Hernandez <aldyh@redhat.com> + + PR tree-optimization/103721 + * gimple-range-path.cc + (path_range_query::relations_may_be_invalidated): New. + (path_range_query::compute_ranges_in_block): Reset relations if + they may be invalidated. + (path_range_query::maybe_register_phi_relation): Exit if relations + may be invalidated on incoming edge. + (path_range_query::compute_phi_relations): Pass incoming PHI edge + to maybe_register_phi_relation. + * gimple-range-path.h (relations_may_be_invalidated): New. + (maybe_register_phi_relation): Pass edge instead of tree. + * tree-ssa-threadbackward.cc (back_threader::back_threader): + Mark DFS edges. + * value-relation.cc (path_oracle::path_oracle): Call + mark_dfs_back_edges. + (path_oracle::register_relation): Add SSA names to m_registered + bitmap. + (path_oracle::reset_path): Clear m_registered bitmap. + * value-relation.h (path_oracle::set_root_oracle): New. + +2022-01-21 Jakub Jelinek <jakub@redhat.com> + + PR rtl-optimization/102478 + * optabs.cc (prepare_cmp_insn): If !can_create_pseudo_p (), don't + force_reg constants and for -fnon-call-exceptions fail if copy_to_reg + would be needed. + +2022-01-20 Richard Biener <rguenther@suse.de> + + PR middle-end/100786 + * gimple-fold.cc (get_symbol_constant_value): Only return + values of compatible type to the symbol. + +2022-01-20 Andrew MacLeod <amacleod@redhat.com> + + * value-relation.cc (relation_oracle::valid_equivs): Query and add + if valid members of a set. + (equiv_oracle::register_equiv): Call valid_equivs rather than + bitmap direct operations. + (path_oracle::register_equiv): Ditto. + * value-relation.h (relation_oracle::valid_equivs): New prototype. + +2022-01-20 Richard Biener <rguenther@suse.de> + + PR target/100784 + * config/i386/i386.cc (ix86_gimple_fold_builtin): Check for + LHS before folding __builtin_ia32_shufpd and friends. + +2022-01-20 Richard Earnshaw <rearnsha@arm.com> + + * config/arm/crypto.md (aes_op_protect): Allow moves from core + registers and from memory. + (aes_op_protect_misalign_load): New pattern. + (aes_op_protect_neon_vld1v16qi): New pattern. + +2022-01-20 Richard Earnshaw <rearnsha@arm.com> + + * config/arm/crypto.md (crypto_<CRYPTO_AESMC:crypto_pattern>_protected): + New pattern. + (aarch32_crypto_aese_fused_protected): Likewise. + (aarch32_crypto_aesd_fused_protected): Likewise. + +2022-01-20 Richard Earnshaw <rearnsha@arm.com> + + * config/arm/crypto.md (crypto_<CRYPTO_AES:crypto_pattern>): Convert + to define_expand. Add mitigation for the Cortex-A AES erratum + when enabled. + (*crypto_<CRYPTO_AES:crypto_pattern>_insn): New pattern, based + on original crypto_<CRYPTO_AES:crypto_pattern> insn. + (aes_op_protect): New pattern. + * config/arm/unspecs.md (unspec): Add UNSPEC_AES_PROTECT. + +2022-01-20 Richard Earnshaw <rearnsha@arm.com> + + * config/arm/arm-cpus.in (quirk_aes_1742098): New quirk feature + (ALL_QUIRKS): Add it. + (cortex-a57, cortex-a72): Enable it. + (cortex-a57.cortex-a53, cortex-a72.cortex-a53): Likewise. + * config/arm/arm.opt (mfix-cortex-a57-aes-1742098): New command-line + option. + (mfix-cortex-a72-aes-1655431): New option alias. + * config/arm/arm.cc (arm_option_override): Handle default settings + for AES erratum switch. + * doc/invoke.texi (Arm Options): Document new options. + +2022-01-20 Richard Earnshaw <rearnsha@arm.com> + + * config/arm/crypto.md (crypto_<CYRPTO_AES:crypto_pattern>): Use + <crypto_mode> rather than hard-coding the mode. + (crypto_<CRYPTO_AESMC:crypto_pattern>): Fix white space. + (crypto_<CRYPTO_AES:crypto_pattern>): Likewise. + (*aarch32_crypto_aese_fused): Likewise. + (*aarch32_crypto_aesd_fused): Likewise. + (crypto_<CRYPTO_BINARY:crypto_pattern>): Likewise. + (crypto_<CRYPTO_TERNARY:crypto_pattern>): Likewise. + (crypto_sha1h_lb): Likewise. + (crypto_vmullp64): Likewise. + (crypto_<CRYPTO_SELECTING:crypto_pattern>): Likewise. + (crypto_<CRYPTO_SELECTING:crypto_pattern>_lb): Likewise. + +2022-01-20 Richard Earnshaw <rearnsha@arm.com> + + * config/arm/crypto.md (crypto_<CRYPTO_AESMC:crypto_pattern>): Add + iterator to pattern name to disambiguate. + (crypto_<CRYPTO_AES:crypto_pattern>): Likewise. + (crypto_<CRYPTO_BINARY:crypto_pattern>): Likewise. + (crypto_<CRYPTO_TERNARY:crypto_pattern>): Likewise. + (crypto_<CRYPTO_SELECTING:crypto_pattern>): Likewise. + (crypto_<CRYPTO_SELECTING:crypto_pattern>_lb): Likewise. + +2022-01-20 Martin Liska <mliska@suse.cz> + + PR bootstrap/104135 + * emit-rtl.cc (make_insn_raw): Fix -Wformat-diag warnings. + * rtl.cc: Partially disable -Wformat-diag for RTL checking + error messages. + +2022-01-20 Jakub Jelinek <jakub@redhat.com> + + PR debug/103874 + * dwarf2out.cc (index_rnglists): For !HAVE_AS_LEB128 and + block_num > 0, index entry even if !have_multiple_function_sections. + +2022-01-20 liuhongt <hongtao.liu@intel.com> + + PR target/103771 + * tree-vect-stmts.cc (supportable_narrowing_operation): Enhance + integral mode mask pack by multi steps which takes + vec_pack_sbool_trunc_optab as start when elements number is + less than BITS_PER_UNITS. + +2022-01-20 Richard Biener <rguenther@suse.de> + + PR tree-optimization/104114 + * tree-vect-generic.cc (expand_vector_piecewise): Do not diagnose + single element vector decomposition. + 2022-01-19 Robin Dapp <rdapp@linux.ibm.com> * ifcvt.cc (noce_convert_multiple_sets_1): New function. diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 261c631..da164bf 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20220120 +20220124 diff --git a/gcc/analyzer/ChangeLog b/gcc/analyzer/ChangeLog index df4a511..4df447d 100644 --- a/gcc/analyzer/ChangeLog +++ b/gcc/analyzer/ChangeLog @@ -1,3 +1,35 @@ +2022-01-22 David Malcolm <dmalcolm@redhat.com> + + PR analyzer/104159 + * region-model-manager.cc + (region_model_manager::get_or_create_cast): Bail out if the types + are the same. Don't attempt to handle casts involving vector + types. + +2022-01-20 David Malcolm <dmalcolm@redhat.com> + + PR analyzer/94362 + * constraint-manager.cc (bound::ensure_closed): Convert param to + enum bound_kind. + (range::constrained_to_single_element): Likewise. + (range::add_bound): New. + (constraint_manager::add_constraint): Handle SVAL + OFFSET + compared to a constant. + (constraint_manager::get_ec_bounds): Rewrite in terms of + range::add_bound. + (constraint_manager::eval_condition): Reject if range::add_bound + fails. + (selftest::test_constant_comparisons): Add test coverage for + various impossible combinations of integer comparisons. + * constraint-manager.h (enum bound_kind): New. + (struct bound): Likewise. + (bound::ensure_closed): Convert to param to enum bound_kind. + (struct range): Convert to... + (class range): ...this, making fields private. + (range::add_bound): New decls. + * region-model.cc (region_model::add_constraint): Fail if + constraint_manager::add_constraint fails. + 2022-01-18 David Malcolm <dmalcolm@redhat.com> PR analyzer/104089 diff --git a/gcc/analyzer/constraint-manager.cc b/gcc/analyzer/constraint-manager.cc index 568e715..7c4a85b 100644 --- a/gcc/analyzer/constraint-manager.cc +++ b/gcc/analyzer/constraint-manager.cc @@ -117,7 +117,7 @@ minus_one (tree cst) closed one. */ void -bound::ensure_closed (bool is_upper) +bound::ensure_closed (enum bound_kind bound_kind) { if (!m_closed) { @@ -125,7 +125,7 @@ bound::ensure_closed (bool is_upper) For example, convert 3 < x into 4 <= x, and convert x < 5 into x <= 4. */ gcc_assert (CONSTANT_CLASS_P (m_constant)); - m_constant = fold_build2 (is_upper ? MINUS_EXPR : PLUS_EXPR, + m_constant = fold_build2 (bound_kind == BK_UPPER ? MINUS_EXPR : PLUS_EXPR, TREE_TYPE (m_constant), m_constant, integer_one_node); gcc_assert (CONSTANT_CLASS_P (m_constant)); @@ -205,8 +205,8 @@ range::constrained_to_single_element () return NULL_TREE; /* Convert any open bounds to closed bounds. */ - m_lower_bound.ensure_closed (false); - m_upper_bound.ensure_closed (true); + m_lower_bound.ensure_closed (BK_LOWER); + m_upper_bound.ensure_closed (BK_UPPER); // Are they equal? tree comparison = fold_binary (EQ_EXPR, boolean_type_node, @@ -301,6 +301,80 @@ range::above_upper_bound (tree rhs_const) const m_upper_bound.m_constant).is_true (); } +/* Attempt to add B to the bound of the given kind of this range. + Return true if feasible; false if infeasible. */ + +bool +range::add_bound (bound b, enum bound_kind bound_kind) +{ + b.ensure_closed (bound_kind); + + switch (bound_kind) + { + default: + gcc_unreachable (); + case BK_LOWER: + /* Discard redundant bounds. */ + if (m_lower_bound.m_constant) + { + m_lower_bound.ensure_closed (BK_LOWER); + if (!tree_int_cst_lt (b.m_constant, + m_lower_bound.m_constant)) + return true; + } + m_lower_bound = b; + break; + case BK_UPPER: + /* Discard redundant bounds. */ + if (m_upper_bound.m_constant) + { + m_upper_bound.ensure_closed (BK_UPPER); + if (tree_int_cst_le (b.m_constant, + m_upper_bound.m_constant)) + return true; + } + m_upper_bound = b; + break; + } + if (m_lower_bound.m_constant + && m_upper_bound.m_constant) + { + m_lower_bound.ensure_closed (BK_LOWER); + m_upper_bound.ensure_closed (BK_UPPER); + + /* Reject LOWER <= V <= UPPER when LOWER > UPPER. */ + if (!tree_int_cst_le (m_lower_bound.m_constant, + m_upper_bound.m_constant)) + return false; + } + return true; +} + +/* Attempt to add (RANGE OP RHS_CONST) as a bound to this range. + Return true if feasible; false if infeasible. */ + +bool +range::add_bound (enum tree_code op, tree rhs_const) +{ + switch (op) + { + default: + return true; + case LT_EXPR: + /* "V < RHS_CONST" */ + return add_bound (bound (rhs_const, false), BK_UPPER); + case LE_EXPR: + /* "V <= RHS_CONST" */ + return add_bound (bound (rhs_const, true), BK_UPPER); + case GE_EXPR: + /* "V >= RHS_CONST" */ + return add_bound (bound (rhs_const, true), BK_LOWER); + case GT_EXPR: + /* "V > RHS_CONST" */ + return add_bound (bound (rhs_const, false), BK_LOWER); + } +} + /* struct bounded_range. */ bounded_range::bounded_range (const_tree lower, const_tree upper) @@ -1718,6 +1792,27 @@ constraint_manager::add_constraint (const svalue *lhs, return false; } + /* If adding + (SVAL + OFFSET) > CST, + then that can imply: + SVAL > (CST - OFFSET). */ + if (const binop_svalue *lhs_binop = lhs->dyn_cast_binop_svalue ()) + if (tree rhs_cst = rhs->maybe_get_constant ()) + if (tree offset = lhs_binop->get_arg1 ()->maybe_get_constant ()) + if ((op == GT_EXPR || op == LT_EXPR + || op == GE_EXPR || op == LE_EXPR) + && lhs_binop->get_op () == PLUS_EXPR) + { + tree offset_of_cst = fold_build2 (MINUS_EXPR, TREE_TYPE (rhs_cst), + rhs_cst, offset); + const svalue *implied_lhs = lhs_binop->get_arg0 (); + enum tree_code implied_op = op; + const svalue *implied_rhs + = m_mgr->get_or_create_constant_svalue (offset_of_cst); + if (!add_constraint (implied_lhs, implied_op, implied_rhs)) + return false; + } + add_unknown_constraint (lhs_ec_id, op, rhs_ec_id); return true; } @@ -2241,12 +2336,12 @@ constraint_manager::get_ec_bounds (equiv_class_id ec_id) const case CONSTRAINT_LT: /* We have "EC_ID < OTHER_CST". */ - result.m_upper_bound = bound (other_cst, false); + result.add_bound (bound (other_cst, false), BK_UPPER); break; case CONSTRAINT_LE: /* We have "EC_ID <= OTHER_CST". */ - result.m_upper_bound = bound (other_cst, true); + result.add_bound (bound (other_cst, true), BK_UPPER); break; } } @@ -2263,13 +2358,13 @@ constraint_manager::get_ec_bounds (equiv_class_id ec_id) const case CONSTRAINT_LT: /* We have "OTHER_CST < EC_ID" i.e. "EC_ID > OTHER_CST". */ - result.m_lower_bound = bound (other_cst, false); + result.add_bound (bound (other_cst, false), BK_LOWER); break; case CONSTRAINT_LE: /* We have "OTHER_CST <= EC_ID" i.e. "EC_ID >= OTHER_CST". */ - result.m_lower_bound = bound (other_cst, true); + result.add_bound (bound (other_cst, true), BK_LOWER); break; } } @@ -2350,7 +2445,15 @@ constraint_manager::eval_condition (equiv_class_id lhs_ec, /* Look at existing bounds on LHS_EC. */ range lhs_bounds = get_ec_bounds (lhs_ec); - return lhs_bounds.eval_condition (op, rhs_const); + tristate result = lhs_bounds.eval_condition (op, rhs_const); + if (result.is_known ()) + return result; + + /* Also reject if range::add_bound fails. */ + if (!lhs_bounds.add_bound (op, rhs_const)) + return tristate (false); + + return tristate::unknown (); } /* Evaluate the condition LHS OP RHS, without modifying this @@ -3452,6 +3555,7 @@ test_transitivity () static void test_constant_comparisons () { + tree int_1 = build_int_cst (integer_type_node, 1); tree int_3 = build_int_cst (integer_type_node, 3); tree int_4 = build_int_cst (integer_type_node, 4); tree int_5 = build_int_cst (integer_type_node, 5); @@ -3462,6 +3566,8 @@ test_constant_comparisons () tree a = build_global_decl ("a", integer_type_node); tree b = build_global_decl ("b", integer_type_node); + tree a_plus_one = build2 (PLUS_EXPR, integer_type_node, a, int_1); + /* Given a >= 1024, then a <= 1023 should be impossible. */ { region_model_manager mgr; @@ -3562,6 +3668,54 @@ test_constant_comparisons () ASSERT_CONDITION_UNKNOWN (model, f, EQ_EXPR, float_4); ASSERT_CONDITION_UNKNOWN (model, f, EQ_EXPR, int_4); } + + /* "a > 3 && a <= 3" should be impossible. */ + { + region_model_manager mgr; + region_model model (&mgr); + ADD_SAT_CONSTRAINT (model, a, GT_EXPR, int_3); + ADD_UNSAT_CONSTRAINT (model, a, LE_EXPR, int_3); + } + + /* "(a + 1) > 3 && a < 3" should be impossible. */ + { + region_model_manager mgr; + { + region_model model (&mgr); + ADD_SAT_CONSTRAINT (model, a_plus_one, GT_EXPR, int_3); + ADD_UNSAT_CONSTRAINT (model, a, LT_EXPR, int_3); + } + { + region_model model (&mgr); + ADD_SAT_CONSTRAINT (model, a, LT_EXPR, int_3); + ADD_UNSAT_CONSTRAINT (model, a_plus_one, GT_EXPR, int_3); + } + } + + /* "3 < a < 4" should be impossible for integer a. */ + { + region_model_manager mgr; + { + region_model model (&mgr); + ADD_SAT_CONSTRAINT (model, int_3, LT_EXPR, a); + ADD_UNSAT_CONSTRAINT (model, a, LT_EXPR, int_4); + } + { + region_model model (&mgr); + ADD_SAT_CONSTRAINT (model, a, LT_EXPR, int_4); + ADD_UNSAT_CONSTRAINT (model, int_3, LT_EXPR, a); + } + { + region_model model (&mgr); + ADD_SAT_CONSTRAINT (model, a, GT_EXPR, int_3); + ADD_UNSAT_CONSTRAINT (model, int_4, GT_EXPR, a); + } + { + region_model model (&mgr); + ADD_SAT_CONSTRAINT (model, int_4, GT_EXPR, a); + ADD_UNSAT_CONSTRAINT (model, a, GT_EXPR, int_3); + } + } } /* Verify various lower-level implementation details about diff --git a/gcc/analyzer/constraint-manager.h b/gcc/analyzer/constraint-manager.h index e93fa7f..f67c764 100644 --- a/gcc/analyzer/constraint-manager.h +++ b/gcc/analyzer/constraint-manager.h @@ -25,6 +25,12 @@ namespace ana { class constraint_manager; +enum bound_kind +{ + BK_LOWER, + BK_UPPER +}; + /* One of the end-points of a range. */ struct bound @@ -33,7 +39,7 @@ struct bound bound (tree constant, bool closed) : m_constant (constant), m_closed (closed) {} - void ensure_closed (bool is_upper); + void ensure_closed (enum bound_kind bound_kind); const char * get_relation_as_str () const; @@ -44,8 +50,9 @@ struct bound /* A range of values, used for determining if a value has been constrained to just one possible constant value. */ -struct range +class range { +public: range () : m_lower_bound (), m_upper_bound () {} range (const bound &lower, const bound &upper) : m_lower_bound (lower), m_upper_bound (upper) {} @@ -60,6 +67,10 @@ struct range bool below_lower_bound (tree rhs_const) const; bool above_upper_bound (tree rhs_const) const; + bool add_bound (bound b, enum bound_kind bound_kind); + bool add_bound (enum tree_code op, tree rhs_const); + +private: bound m_lower_bound; bound m_upper_bound; }; diff --git a/gcc/analyzer/region-model-manager.cc b/gcc/analyzer/region-model-manager.cc index bb93526..e765e7f 100644 --- a/gcc/analyzer/region-model-manager.cc +++ b/gcc/analyzer/region-model-manager.cc @@ -497,6 +497,17 @@ const svalue * region_model_manager::get_or_create_cast (tree type, const svalue *arg) { gcc_assert (type); + + /* No-op if the types are the same. */ + if (type == arg->get_type ()) + return arg; + + /* Don't attempt to handle casts involving vector types for now. */ + if (TREE_CODE (type) == VECTOR_TYPE + || (arg->get_type () + && TREE_CODE (arg->get_type ()) == VECTOR_TYPE)) + return get_or_create_unknown_svalue (type); + enum tree_code op = get_code_for_cast (type, arg->get_type ()); return get_or_create_unaryop (type, op, arg); } diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc index b58d089..f6b7f98 100644 --- a/gcc/analyzer/region-model.cc +++ b/gcc/analyzer/region-model.cc @@ -2801,8 +2801,9 @@ region_model::add_constraint (const svalue *lhs, if (add_constraints_from_binop (lhs, op, rhs, &out, ctxt)) return out; - /* Store the constraint. */ - m_constraints->add_constraint (lhs, op, rhs); + /* Attempt to store the constraint. */ + if (!m_constraints->add_constraint (lhs, op, rhs)) + return false; /* Notify the context, if any. This exists so that the state machines in a program_state can be notified about the condition, and so can diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 2cfebb2..5595c8d 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,15 @@ +2022-01-21 Jakub Jelinek <jakub@redhat.com> + + PR c++/104148 + * c-common.h (check_function_arguments_recurse): Add for_format + arg. + * c-common.cc (check_function_nonnull): Pass false to + check_function_arguments_recurse's last argument. + (check_function_arguments_recurse): Add for_format argument, + if true, don't stop on warning_suppressed_p. + * c-format.cc (check_format_info): Pass true to + check_function_arguments_recurse's last argument. + 2022-01-19 David Malcolm <dmalcolm@redhat.com> * c-common.cc (c_common_c_tests): Rename to... diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc index f56f6df..bf0749b 100644 --- a/gcc/c-family/c-common.cc +++ b/gcc/c-family/c-common.cc @@ -5592,7 +5592,7 @@ check_function_nonnull (nonnull_arg_ctx &ctx, int nargs, tree *argarray) firstarg = 1; if (!closure) check_function_arguments_recurse (check_nonnull_arg, &ctx, argarray[0], - firstarg); + firstarg, OPT_Wnonnull); } tree attrs = lookup_attribute ("nonnull", TYPE_ATTRIBUTES (ctx.fntype)); @@ -5611,7 +5611,7 @@ check_function_nonnull (nonnull_arg_ctx &ctx, int nargs, tree *argarray) if (a != NULL_TREE) for (int i = firstarg; i < nargs; i++) check_function_arguments_recurse (check_nonnull_arg, &ctx, argarray[i], - i + 1); + i + 1, OPT_Wnonnull); else { /* Walk the argument list. If we encounter an argument number we @@ -5627,7 +5627,8 @@ check_function_nonnull (nonnull_arg_ctx &ctx, int nargs, tree *argarray) if (a != NULL_TREE) check_function_arguments_recurse (check_nonnull_arg, &ctx, - argarray[i], i + 1); + argarray[i], i + 1, + OPT_Wnonnull); } } return ctx.warned_p; @@ -6095,14 +6096,16 @@ check_function_arguments (location_t loc, const_tree fndecl, const_tree fntype, /* Generic argument checking recursion routine. PARAM is the argument to be checked. PARAM_NUM is the number of the argument. CALLBACK is invoked - once the argument is resolved. CTX is context for the callback. */ + once the argument is resolved. CTX is context for the callback. + OPT is the warning for which this is done. */ void check_function_arguments_recurse (void (*callback) (void *, tree, unsigned HOST_WIDE_INT), void *ctx, tree param, - unsigned HOST_WIDE_INT param_num) + unsigned HOST_WIDE_INT param_num, + opt_code opt) { - if (warning_suppressed_p (param)) + if (opt != OPT_Wformat_ && warning_suppressed_p (param)) return; if (CONVERT_EXPR_P (param) @@ -6111,7 +6114,8 @@ check_function_arguments_recurse (void (*callback) { /* Strip coercion. */ check_function_arguments_recurse (callback, ctx, - TREE_OPERAND (param, 0), param_num); + TREE_OPERAND (param, 0), param_num, + opt); return; } @@ -6148,7 +6152,8 @@ check_function_arguments_recurse (void (*callback) if (i == format_num) { check_function_arguments_recurse (callback, ctx, - inner_arg, param_num); + inner_arg, param_num, + opt); found_format_arg = true; break; } @@ -6170,10 +6175,10 @@ check_function_arguments_recurse (void (*callback) /* Check both halves of the conditional expression. */ check_function_arguments_recurse (callback, ctx, TREE_OPERAND (param, 1), - param_num); + param_num, opt); check_function_arguments_recurse (callback, ctx, TREE_OPERAND (param, 2), - param_num); + param_num, opt); return; } } diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 28c73fe..a8d6f82 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -853,7 +853,8 @@ extern void check_function_arguments_recurse (void (*) (void *, tree, unsigned HOST_WIDE_INT), void *, tree, - unsigned HOST_WIDE_INT); + unsigned HOST_WIDE_INT, + opt_code); extern bool check_builtin_function_arguments (location_t, vec<location_t>, tree, tree, int, tree *); extern void check_function_format (const_tree, tree, int, tree *, diff --git a/gcc/c-family/c-format.cc b/gcc/c-family/c-format.cc index a2affda..98f28c0 100644 --- a/gcc/c-family/c-format.cc +++ b/gcc/c-family/c-format.cc @@ -1531,7 +1531,7 @@ check_format_info (function_format_info *info, tree params, format_ctx.arglocs = arglocs; check_function_arguments_recurse (check_format_arg, &format_ctx, - format_tree, arg_num); + format_tree, arg_num, OPT_Wformat_); location_t loc = format_ctx.res->format_string_loc; diff --git a/gcc/common.opt b/gcc/common.opt index fe7bcf6..d923327 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -223,10 +223,6 @@ unsigned int flag_sanitize Variable unsigned int flag_sanitize_recover = (SANITIZE_UNDEFINED | SANITIZE_UNDEFINED_NONDEFAULT | SANITIZE_KERNEL_ADDRESS | SANITIZE_KERNEL_HWADDRESS) & ~(SANITIZE_UNREACHABLE | SANITIZE_RETURN) -; What the coverage sanitizers should instrument -Variable -unsigned int flag_sanitize_coverage - ; Flag whether a prefix has been added to dump_base_name Variable bool dump_base_name_prefixed = false @@ -1076,7 +1072,7 @@ Common Driver Joined Select what to sanitize. fsanitize-coverage= -Common Joined RejectNegative Enum(sanitize_coverage) +Common Joined Enum(sanitize_coverage) Var(flag_sanitize_coverage) EnumBitSet Select type of coverage sanitization. Enum diff --git a/gcc/common/config/i386/i386-common.cc b/gcc/common/config/i386/i386-common.cc index cae0b88..607e9f2 100644 --- a/gcc/common/config/i386/i386-common.cc +++ b/gcc/common/config/i386/i386-common.cc @@ -1714,16 +1714,21 @@ ix86_option_init_struct (struct gcc_options *opts) field in the TCB, so they cannot be used together. */ static bool -ix86_supports_split_stack (bool report ATTRIBUTE_UNUSED, +ix86_supports_split_stack (bool report, struct gcc_options *opts ATTRIBUTE_UNUSED) { +#if defined(TARGET_THREAD_SPLIT_STACK_OFFSET) && defined(OPTION_GLIBC_P) + if (!OPTION_GLIBC_P (opts)) +#endif + { + if (report) + error ("%<-fsplit-stack%> currently only supported on GNU/Linux"); + return false; + } + bool ret = true; -#ifndef TARGET_THREAD_SPLIT_STACK_OFFSET - if (report) - error ("%<-fsplit-stack%> currently only supported on GNU/Linux"); - ret = false; -#else +#ifdef TARGET_THREAD_SPLIT_STACK_OFFSET if (!HAVE_GAS_CFI_PERSONALITY_DIRECTIVE) { if (report) diff --git a/gcc/common/config/riscv/riscv-common.cc b/gcc/common/config/riscv/riscv-common.cc index 25f5670..a904893 100644 --- a/gcc/common/config/riscv/riscv-common.cc +++ b/gcc/common/config/riscv/riscv-common.cc @@ -488,6 +488,7 @@ riscv_subset_list::to_string (bool version_p) const bool skip_zifencei = false; bool skip_zicsr = false; + bool i2p0 = false; /* For RISC-V ISA version 2.2 or earlier version, zicsr and zifencei is included in the base ISA. */ @@ -497,6 +498,13 @@ riscv_subset_list::to_string (bool version_p) const skip_zicsr = true; } + for (subset = m_head; subset != NULL; subset = subset->next) + if (subset->name == "i") + { + i2p0 = subset->major_version == 2 && subset->minor_version == 0; + break; + } + #ifndef HAVE_AS_MISA_SPEC /* Skip since older binutils doesn't recognize zicsr. */ skip_zicsr = true; @@ -509,10 +517,12 @@ riscv_subset_list::to_string (bool version_p) const for (subset = m_head; subset != NULL; subset = subset->next) { - if (subset->implied_p && skip_zifencei && subset->name == "zifencei") + if (((subset->implied_p && skip_zifencei) || i2p0) && + subset->name == "zifencei") continue; - if (subset->implied_p && skip_zicsr && subset->name == "zicsr") + if (((subset->implied_p && skip_zicsr) || i2p0) && + subset->name == "zicsr") continue; /* For !version_p, we only separate extension with underline for diff --git a/gcc/common/config/s390/s390-common.cc b/gcc/common/config/s390/s390-common.cc index 6ed2f89..caec2f1 100644 --- a/gcc/common/config/s390/s390-common.cc +++ b/gcc/common/config/s390/s390-common.cc @@ -116,13 +116,21 @@ s390_handle_option (struct gcc_options *opts ATTRIBUTE_UNUSED, /* -fsplit-stack uses a field in the TCB, available with glibc-2.23. We don't verify it, since earlier versions just have padding at - its place, which works just as well. */ + its place, which works just as well. For other libc implementations + we disable the feature entirely to avoid corrupting the TCB. */ static bool -s390_supports_split_stack (bool report ATTRIBUTE_UNUSED, +s390_supports_split_stack (bool report, struct gcc_options *opts ATTRIBUTE_UNUSED) { - return true; +#ifdef OPTION_GLIBC_P + if (OPTION_GLIBC_P (opts)) + return true; +#endif + + if (report) + error ("%<-fsplit-stack%> currently only supported on GNU/Linux"); + return false; } #undef TARGET_DEFAULT_TARGET_FLAGS diff --git a/gcc/config.gcc b/gcc/config.gcc index 2c4266c..90aec3f 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -4641,12 +4641,12 @@ case "${target}" in esac case "${with_isa_spec}" in - ""|default|2.2) - tm_defines="${tm_defines} TARGET_DEFAULT_ISA_SPEC=ISA_SPEC_CLASS_2P2" - ;; - 20191213 | 201912) + ""|default|20191213|201912) tm_defines="${tm_defines} TARGET_DEFAULT_ISA_SPEC=ISA_SPEC_CLASS_20191213" ;; + 2.2) + tm_defines="${tm_defines} TARGET_DEFAULT_ISA_SPEC=ISA_SPEC_CLASS_2P2" + ;; 20190608 | 201906) tm_defines="${tm_defines} TARGET_DEFAULT_ISA_SPEC=ISA_SPEC_CLASS_20190608" ;; diff --git a/gcc/config/aarch64/aarch64-builtins.cc b/gcc/config/aarch64/aarch64-builtins.cc index b7f338d..5217dbd 100644 --- a/gcc/config/aarch64/aarch64-builtins.cc +++ b/gcc/config/aarch64/aarch64-builtins.cc @@ -2820,6 +2820,13 @@ aarch64_general_gimple_fold_builtin (unsigned int fcode, gcall *stmt, gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt)); break; + /* Lower sqrt builtins to gimple/internal function sqrt. */ + BUILTIN_VHSDF_DF (UNOP, sqrt, 2, FP) + new_stmt = gimple_build_call_internal (IFN_SQRT, + 1, args[0]); + gimple_call_set_lhs (new_stmt, gimple_call_lhs (stmt)); + break; + /*lower store and load neon builtins to gimple. */ BUILTIN_VALL_F16 (LOAD1, ld1, 0, LOAD) BUILTIN_VDQ_I (LOAD1_U, ld1, 0, LOAD) diff --git a/gcc/config/alpha/linux.h b/gcc/config/alpha/linux.h index 9ab501c..14ced5f 100644 --- a/gcc/config/alpha/linux.h +++ b/gcc/config/alpha/linux.h @@ -58,18 +58,23 @@ along with GCC; see the file COPYING3. If not see #define WCHAR_TYPE "int" #ifdef SINGLE_LIBC -#define OPTION_GLIBC (DEFAULT_LIBC == LIBC_GLIBC) -#define OPTION_UCLIBC (DEFAULT_LIBC == LIBC_UCLIBC) -#define OPTION_BIONIC (DEFAULT_LIBC == LIBC_BIONIC) -#undef OPTION_MUSL -#define OPTION_MUSL (DEFAULT_LIBC == LIBC_MUSL) +#define OPTION_GLIBC_P(opts) (DEFAULT_LIBC == LIBC_GLIBC) +#define OPTION_UCLIBC_P(opts) (DEFAULT_LIBC == LIBC_UCLIBC) +#define OPTION_BIONIC_P(opts) (DEFAULT_LIBC == LIBC_BIONIC) +#undef OPTION_MUSL_P +#define OPTION_MUSL_P(opts) (DEFAULT_LIBC == LIBC_MUSL) #else -#define OPTION_GLIBC (linux_libc == LIBC_GLIBC) -#define OPTION_UCLIBC (linux_libc == LIBC_UCLIBC) -#define OPTION_BIONIC (linux_libc == LIBC_BIONIC) -#undef OPTION_MUSL -#define OPTION_MUSL (linux_libc == LIBC_MUSL) +#define OPTION_GLIBC_P(opts) ((opts)->x_linux_libc == LIBC_GLIBC) +#define OPTION_UCLIBC_P(opts) ((opts)->x_linux_libc == LIBC_UCLIBC) +#define OPTION_BIONIC_P(opts) ((opts)->x_linux_libc == LIBC_BIONIC) +#undef OPTION_MUSL_P +#define OPTION_MUSL_P(opts) ((opts)->x_linux_libc == LIBC_MUSL) #endif +#define OPTION_GLIBC OPTION_GLIBC_P (&global_options) +#define OPTION_UCLIBC OPTION_UCLIBC_P (&global_options) +#define OPTION_BIONIC OPTION_BIONIC_P (&global_options) +#undef OPTION_MUSL +#define OPTION_MUSL OPTION_MUSL_P (&global_options) /* Determine what functions are present at the runtime; this includes full c99 runtime and sincos. */ diff --git a/gcc/config/arm/arm-opts.h b/gcc/config/arm/arm-opts.h index c50d5e5..24d12fa 100644 --- a/gcc/config/arm/arm-opts.h +++ b/gcc/config/arm/arm-opts.h @@ -69,4 +69,10 @@ enum arm_tls_type { TLS_GNU, TLS_GNU2 }; + +/* Where to get the canary for the stack protector. */ +enum stack_protector_guard { + SSP_TLSREG, /* per-thread canary in TLS register */ + SSP_GLOBAL /* global canary */ +}; #endif diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h index cd55a9f..881c72c 100644 --- a/gcc/config/arm/arm-protos.h +++ b/gcc/config/arm/arm-protos.h @@ -195,6 +195,8 @@ extern void arm_split_atomic_op (enum rtx_code, rtx, rtx, rtx, rtx, rtx, rtx); extern rtx arm_load_tp (rtx); extern bool arm_coproc_builtin_available (enum unspecv); extern bool arm_coproc_ldc_stc_legitimate_address (rtx); +extern rtx arm_stack_protect_tls_canary_mem (bool); + #if defined TREE_CODE extern void arm_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree); diff --git a/gcc/config/arm/arm.cc b/gcc/config/arm/arm.cc index 04354b3..663f459 100644 --- a/gcc/config/arm/arm.cc +++ b/gcc/config/arm/arm.cc @@ -829,6 +829,9 @@ static const struct attribute_spec arm_attribute_table[] = #undef TARGET_MD_ASM_ADJUST #define TARGET_MD_ASM_ADJUST arm_md_asm_adjust + +#undef TARGET_STACK_PROTECT_GUARD +#define TARGET_STACK_PROTECT_GUARD arm_stack_protect_guard /* Obstack for minipool constant handling. */ static struct obstack minipool_obstack; @@ -3176,6 +3179,26 @@ arm_option_override_internal (struct gcc_options *opts, if (TARGET_THUMB2_P (opts->x_target_flags)) opts->x_inline_asm_unified = true; + if (arm_stack_protector_guard == SSP_GLOBAL + && opts->x_arm_stack_protector_guard_offset_str) + { + error ("incompatible options %'-mstack-protector-guard=global%' and" + "%'-mstack-protector-guard-offset=%qs%'", + arm_stack_protector_guard_offset_str); + } + + if (opts->x_arm_stack_protector_guard_offset_str) + { + char *end; + const char *str = arm_stack_protector_guard_offset_str; + errno = 0; + long offs = strtol (arm_stack_protector_guard_offset_str, &end, 0); + if (!*str || *end || errno) + error ("%qs is not a valid offset in %qs", str, + "-mstack-protector-guard-offset="); + arm_stack_protector_guard_offset = offs; + } + #ifdef SUBTARGET_OVERRIDE_INTERNAL_OPTIONS SUBTARGET_OVERRIDE_INTERNAL_OPTIONS; #endif @@ -3852,6 +3875,9 @@ arm_option_reconfigure_globals (void) else target_thread_pointer = TP_SOFT; } + + if (!TARGET_HARD_TP && arm_stack_protector_guard == SSP_TLSREG) + error("%'-mstack-protector-guard=tls%' needs a hardware TLS register"); } /* Perform some validation between the desired architecture and the rest of the @@ -8117,6 +8143,23 @@ legitimize_pic_address (rtx orig, machine_mode mode, rtx reg, rtx pic_reg, } +/* Generate insns that produce the address of the stack canary */ +rtx +arm_stack_protect_tls_canary_mem (bool reload) +{ + rtx tp = gen_reg_rtx (SImode); + if (reload) + emit_insn (gen_reload_tp_hard (tp)); + else + emit_insn (gen_load_tp_hard (tp)); + + rtx reg = gen_reg_rtx (SImode); + rtx offset = GEN_INT (arm_stack_protector_guard_offset); + emit_set_insn (reg, gen_rtx_PLUS (SImode, tp, offset)); + return gen_rtx_MEM (SImode, reg); +} + + /* Whether a register is callee saved or not. This is necessary because high registers are marked as caller saved when optimizing for size on Thumb-1 targets despite being callee saved in order to avoid using them. */ @@ -34084,6 +34127,18 @@ arm_run_selftests (void) #define TARGET_RUN_TARGET_SELFTESTS selftest::arm_run_selftests #endif /* CHECKING_P */ +/* Implement TARGET_STACK_PROTECT_GUARD. In case of a + global variable based guard use the default else + return a null tree. */ +static tree +arm_stack_protect_guard (void) +{ + if (arm_stack_protector_guard == SSP_GLOBAL) + return default_stack_protect_guard (); + + return NULL_TREE; +} + /* Worker function for TARGET_MD_ASM_ADJUST, while in thumb1 mode. Unlike the arm version, we do NOT implement asm flag outputs. */ diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index 90756fb..60468f6 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -9183,7 +9183,7 @@ UNSPEC_SP_SET)) (clobber (match_scratch:SI 2 "")) (clobber (match_scratch:SI 3 ""))])] - "" + "arm_stack_protector_guard == SSP_GLOBAL" "" ) @@ -9267,7 +9267,7 @@ (clobber (match_scratch:SI 3 "")) (clobber (match_scratch:SI 4 "")) (clobber (reg:CC CC_REGNUM))])] - "" + "arm_stack_protector_guard == SSP_GLOBAL" "" ) @@ -9361,6 +9361,64 @@ (set_attr "arch" "t,32")] ) +(define_expand "stack_protect_set" + [(match_operand:SI 0 "memory_operand") + (match_operand:SI 1 "memory_operand")] + "arm_stack_protector_guard == SSP_TLSREG" + " +{ + operands[1] = arm_stack_protect_tls_canary_mem (false /* reload */); + emit_insn (gen_stack_protect_set_tls (operands[0], operands[1])); + DONE; +}" +) + +;; DO NOT SPLIT THIS PATTERN. It is important for security reasons that the +;; canary value does not live beyond the life of this sequence. +(define_insn "stack_protect_set_tls" + [(set (match_operand:SI 0 "memory_operand" "=m") + (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] + UNSPEC_SP_SET)) + (set (match_scratch:SI 2 "=&r") (const_int 0))] + "" + "ldr\\t%2, %1\;str\\t%2, %0\;mov\t%2, #0" + [(set_attr "length" "12") + (set_attr "conds" "unconditional") + (set_attr "type" "multiple")] +) + +(define_expand "stack_protect_test" + [(match_operand:SI 0 "memory_operand") + (match_operand:SI 1 "memory_operand") + (match_operand:SI 2)] + "arm_stack_protector_guard == SSP_TLSREG" + " +{ + operands[1] = arm_stack_protect_tls_canary_mem (true /* reload */); + emit_insn (gen_stack_protect_test_tls (operands[0], operands[1])); + + rtx cc_reg = gen_rtx_REG (CC_Zmode, CC_REGNUM); + rtx eq = gen_rtx_EQ (CC_Zmode, cc_reg, const0_rtx); + emit_jump_insn (gen_arm_cond_branch (operands[2], eq, cc_reg)); + DONE; +}" +) + +(define_insn "stack_protect_test_tls" + [(set (reg:CC_Z CC_REGNUM) + (compare:CC_Z (unspec:SI [(match_operand:SI 0 "memory_operand" "m") + (match_operand:SI 1 "memory_operand" "m")] + UNSPEC_SP_TEST) + (const_int 0))) + (clobber (match_scratch:SI 2 "=&r")) + (clobber (match_scratch:SI 3 "=&r"))] + "" + "ldr\t%2, %0\;ldr\t%3, %1\;eors\t%2, %3, %2\;mov\t%3, #0" + [(set_attr "length" "16") + (set_attr "conds" "set") + (set_attr "type" "multiple")] +) + (define_expand "casesi" [(match_operand:SI 0 "s_register_operand") ; index to jump on (match_operand:SI 1 "const_int_operand") ; lower bound @@ -12133,6 +12191,15 @@ (set_attr "type" "mrs")] ) +;; Used by the TLS register based stack protector +(define_insn "reload_tp_hard" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec_volatile:SI [(const_int 0)] VUNSPEC_MRC))] + "TARGET_HARD_TP" + "mrc\\tp15, 0, %0, c13, c0, 3\\t@ reload_tp_hard" + [(set_attr "type" "mrs")] +) + ;; Doesn't clobber R1-R3. Must use r0 for the first operand. (define_insn "load_tp_soft_fdpic" [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS)) diff --git a/gcc/config/arm/arm.opt b/gcc/config/arm/arm.opt index 2a4f165..cc16534 100644 --- a/gcc/config/arm/arm.opt +++ b/gcc/config/arm/arm.opt @@ -321,3 +321,25 @@ Generate code which uses the core registers only (r0-r14). mfdpic Target Mask(FDPIC) Enable Function Descriptor PIC mode. + +mstack-protector-guard= +Target RejectNegative Joined Enum(stack_protector_guard) Var(arm_stack_protector_guard) Init(SSP_GLOBAL) +Use given stack-protector guard. + +Enum +Name(stack_protector_guard) Type(enum stack_protector_guard) +Valid arguments to -mstack-protector-guard=: + +EnumValue +Enum(stack_protector_guard) String(tls) Value(SSP_TLSREG) + +EnumValue +Enum(stack_protector_guard) String(global) Value(SSP_GLOBAL) + +mstack-protector-guard-offset= +Target Joined RejectNegative String Var(arm_stack_protector_guard_offset_str) +Use an immediate to offset from the TLS register. This option is for use with +fstack-protector-guard=tls and not for use in user-land code. + +TargetVariable +long arm_stack_protector_guard_offset = 0 diff --git a/gcc/config/fuchsia.h b/gcc/config/fuchsia.h index e013265..0baf6f1f 100644 --- a/gcc/config/fuchsia.h +++ b/gcc/config/fuchsia.h @@ -52,6 +52,8 @@ along with GCC; see the file COPYING3. If not see /* We are using MUSL as our libc. */ #undef OPTION_MUSL #define OPTION_MUSL 1 +#undef OPTION_MUSL_P +#define OPTION_MUSL_P(opts) 1 #ifndef TARGET_SUB_OS_CPP_BUILTINS #define TARGET_SUB_OS_CPP_BUILTINS() diff --git a/gcc/config/glibc-stdint.h b/gcc/config/glibc-stdint.h index 1161616..a3652d0 100644 --- a/gcc/config/glibc-stdint.h +++ b/gcc/config/glibc-stdint.h @@ -27,6 +27,9 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #ifndef OPTION_MUSL #define OPTION_MUSL 0 #endif +#ifndef OPTION_MUSL_P +#define OPTION_MUSL_P(opts) 0 +#endif #define SIG_ATOMIC_TYPE "int" diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index af82886..ad5a5ca 100644 --- a/gcc/config/i386/i386.cc +++ b/gcc/config/i386/i386.cc @@ -18710,7 +18710,7 @@ ix86_gimple_fold_builtin (gimple_stmt_iterator *gsi) gimple_call_arg (stmt, n_args - 1))) break; arg2 = gimple_call_arg (stmt, 2); - if (TREE_CODE (arg2) == INTEGER_CST) + if (TREE_CODE (arg2) == INTEGER_CST && gimple_call_lhs (stmt)) { unsigned HOST_WIDE_INT shuffle_mask = TREE_INT_CST_LOW (arg2); /* Check valid imm, refer to gcc.target/i386/testimm-10.c. */ diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md index eae6ab5..a8cc17a 100644 --- a/gcc/config/i386/predicates.md +++ b/gcc/config/i386/predicates.md @@ -1157,6 +1157,8 @@ (ior (match_test "TARGET_AVX512VL") (match_test "GET_MODE_SIZE (GET_MODE (op)) == 64"))) (match_test "VALID_BCST_MODE_P (GET_MODE_INNER (GET_MODE (op)))") + (match_test "GET_MODE (XEXP (op, 0)) + == GET_MODE_INNER (GET_MODE (op))") (match_test "memory_operand (XEXP (op, 0), GET_MODE (XEXP (op, 0)))"))) ; Return true when OP is bcst_mem_operand or vector_memory_operand. diff --git a/gcc/config/linux.h b/gcc/config/linux.h index 2e888e3..74f7079 100644 --- a/gcc/config/linux.h +++ b/gcc/config/linux.h @@ -29,18 +29,23 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see /* C libraries supported on Linux. */ #ifdef SINGLE_LIBC -#define OPTION_GLIBC (DEFAULT_LIBC == LIBC_GLIBC) -#define OPTION_UCLIBC (DEFAULT_LIBC == LIBC_UCLIBC) -#define OPTION_BIONIC (DEFAULT_LIBC == LIBC_BIONIC) -#undef OPTION_MUSL -#define OPTION_MUSL (DEFAULT_LIBC == LIBC_MUSL) +#define OPTION_GLIBC_P(opts) (DEFAULT_LIBC == LIBC_GLIBC) +#define OPTION_UCLIBC_P(opts) (DEFAULT_LIBC == LIBC_UCLIBC) +#define OPTION_BIONIC_P(opts) (DEFAULT_LIBC == LIBC_BIONIC) +#undef OPTION_MUSL_P +#define OPTION_MUSL_P(opts) (DEFAULT_LIBC == LIBC_MUSL) #else -#define OPTION_GLIBC (linux_libc == LIBC_GLIBC) -#define OPTION_UCLIBC (linux_libc == LIBC_UCLIBC) -#define OPTION_BIONIC (linux_libc == LIBC_BIONIC) -#undef OPTION_MUSL -#define OPTION_MUSL (linux_libc == LIBC_MUSL) +#define OPTION_GLIBC_P(opts) ((opts)->x_linux_libc == LIBC_GLIBC) +#define OPTION_UCLIBC_P(opts) ((opts)->x_linux_libc == LIBC_UCLIBC) +#define OPTION_BIONIC_P(opts) ((opts)->x_linux_libc == LIBC_BIONIC) +#undef OPTION_MUSL_P +#define OPTION_MUSL_P(opts) ((opts)->x_linux_libc == LIBC_MUSL) #endif +#define OPTION_GLIBC OPTION_GLIBC_P (&global_options) +#define OPTION_UCLIBC OPTION_UCLIBC_P (&global_options) +#define OPTION_BIONIC OPTION_BIONIC_P (&global_options) +#undef OPTION_MUSL +#define OPTION_MUSL OPTION_MUSL_P (&global_options) #define GNU_USER_TARGET_OS_CPP_BUILTINS() \ do { \ diff --git a/gcc/config/riscv/riscv-c.cc b/gcc/config/riscv/riscv-c.cc index 211472f..73c62f4 100644 --- a/gcc/config/riscv/riscv-c.cc +++ b/gcc/config/riscv/riscv-c.cc @@ -108,6 +108,9 @@ riscv_cpu_cpp_builtins (cpp_reader *pfile) builtin_define_with_int_value ("__riscv_arch_test", 1); const riscv_subset_list *subset_list = riscv_current_subset_list (); + if (!subset_list) + return; + size_t max_ext_len = 0; /* Figure out the max length of extension name for reserving buffer. */ diff --git a/gcc/config/rs6000/linux.h b/gcc/config/rs6000/linux.h index e6a3223..8c9039a 100644 --- a/gcc/config/rs6000/linux.h +++ b/gcc/config/rs6000/linux.h @@ -27,18 +27,23 @@ #define NO_PROFILE_COUNTERS 1 #ifdef SINGLE_LIBC -#define OPTION_GLIBC (DEFAULT_LIBC == LIBC_GLIBC) -#define OPTION_UCLIBC (DEFAULT_LIBC == LIBC_UCLIBC) -#define OPTION_BIONIC (DEFAULT_LIBC == LIBC_BIONIC) -#undef OPTION_MUSL -#define OPTION_MUSL (DEFAULT_LIBC == LIBC_MUSL) +#define OPTION_GLIBC_P(opts) (DEFAULT_LIBC == LIBC_GLIBC) +#define OPTION_UCLIBC_P(opts) (DEFAULT_LIBC == LIBC_UCLIBC) +#define OPTION_BIONIC_P(opts) (DEFAULT_LIBC == LIBC_BIONIC) +#undef OPTION_MUSL_P +#define OPTION_MUSL_P(opts) (DEFAULT_LIBC == LIBC_MUSL) #else -#define OPTION_GLIBC (linux_libc == LIBC_GLIBC) -#define OPTION_UCLIBC (linux_libc == LIBC_UCLIBC) -#define OPTION_BIONIC (linux_libc == LIBC_BIONIC) -#undef OPTION_MUSL -#define OPTION_MUSL (linux_libc == LIBC_MUSL) +#define OPTION_GLIBC_P(opts) ((opts)->x_linux_libc == LIBC_GLIBC) +#define OPTION_UCLIBC_P(opts) ((opts)->x_linux_libc == LIBC_UCLIBC) +#define OPTION_BIONIC_P(opts) ((opts)->x_linux_libc == LIBC_BIONIC) +#undef OPTION_MUSL_P +#define OPTION_MUSL_P(opts) ((opts)->x_linux_libc == LIBC_MUSL) #endif +#define OPTION_GLIBC OPTION_GLIBC_P (&global_options) +#define OPTION_UCLIBC OPTION_UCLIBC_P (&global_options) +#define OPTION_BIONIC OPTION_BIONIC_P (&global_options) +#undef OPTION_MUSL +#define OPTION_MUSL OPTION_MUSL_P (&global_options) /* Determine what functions are present at the runtime; this includes full c99 runtime and sincos. */ diff --git a/gcc/config/rs6000/linux64.h b/gcc/config/rs6000/linux64.h index d617f346..b2a7afa 100644 --- a/gcc/config/rs6000/linux64.h +++ b/gcc/config/rs6000/linux64.h @@ -265,18 +265,23 @@ extern int dot_symbols; #define OS_MISSING_POWERPC64 !TARGET_64BIT #ifdef SINGLE_LIBC -#define OPTION_GLIBC (DEFAULT_LIBC == LIBC_GLIBC) -#define OPTION_UCLIBC (DEFAULT_LIBC == LIBC_UCLIBC) -#define OPTION_BIONIC (DEFAULT_LIBC == LIBC_BIONIC) -#undef OPTION_MUSL -#define OPTION_MUSL (DEFAULT_LIBC == LIBC_MUSL) +#define OPTION_GLIBC_P(opts) (DEFAULT_LIBC == LIBC_GLIBC) +#define OPTION_UCLIBC_P(opts) (DEFAULT_LIBC == LIBC_UCLIBC) +#define OPTION_BIONIC_P(opts) (DEFAULT_LIBC == LIBC_BIONIC) +#undef OPTION_MUSL_P +#define OPTION_MUSL_P(opts) (DEFAULT_LIBC == LIBC_MUSL) #else -#define OPTION_GLIBC (linux_libc == LIBC_GLIBC) -#define OPTION_UCLIBC (linux_libc == LIBC_UCLIBC) -#define OPTION_BIONIC (linux_libc == LIBC_BIONIC) -#undef OPTION_MUSL -#define OPTION_MUSL (linux_libc == LIBC_MUSL) +#define OPTION_GLIBC_P(opts) ((opts)->x_linux_libc == LIBC_GLIBC) +#define OPTION_UCLIBC_P(opts) ((opts)->x_linux_libc == LIBC_UCLIBC) +#define OPTION_BIONIC_P(opts) ((opts)->x_linux_libc == LIBC_BIONIC) +#undef OPTION_MUSL_P +#define OPTION_MUSL_P(opts) ((opts)->x_linux_libc == LIBC_MUSL) #endif +#define OPTION_GLIBC OPTION_GLIBC_P (&global_options) +#define OPTION_UCLIBC OPTION_UCLIBC_P (&global_options) +#define OPTION_BIONIC OPTION_BIONIC_P (&global_options) +#undef OPTION_MUSL +#define OPTION_MUSL OPTION_MUSL_P (&global_options) /* Determine what functions are present at the runtime; this includes full c99 runtime and sincos. */ diff --git a/gcc/config/rs6000/rs6000-overload.def b/gcc/config/rs6000/rs6000-overload.def index e279153..7d030ab 100644 --- a/gcc/config/rs6000/rs6000-overload.def +++ b/gcc/config/rs6000/rs6000-overload.def @@ -3401,6 +3401,10 @@ XXSLDWI_2DI XXSLDWI_VSLL vull __builtin_vec_sldw (vull, vull, const int); XXSLDWI_2DI XXSLDWI_VULL + vf __builtin_vec_sldw (vf, vf, const int); + XXSLDWI_4SF XXSLDWI_VF + vd __builtin_vec_sldw (vd, vd, const int); + XXSLDWI_2DF XXSLDWI_VD [VEC_SLL, vec_sll, __builtin_vec_sll] vsc __builtin_vec_sll (vsc, vuc); diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index e322ac0..3ea0102 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -199,7 +199,6 @@ enum non_prefixed_form reg_to_non_prefixed (rtx reg, machine_mode mode); extern bool prefixed_load_p (rtx_insn *); extern bool prefixed_store_p (rtx_insn *); extern bool prefixed_paddi_p (rtx_insn *); -extern bool prefixed_xxsplti_p (rtx_insn *); extern void rs6000_asm_output_opcode (FILE *); extern void output_pcrel_opt_reloc (rtx); extern void rs6000_final_prescan_insn (rtx_insn *, rtx [], int); diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc index 0882ecb..943f53e 100644 --- a/gcc/config/rs6000/rs6000.cc +++ b/gcc/config/rs6000/rs6000.cc @@ -25082,7 +25082,7 @@ rs6000_get_function_versions_dispatcher (void *decl) else { error_at (DECL_SOURCE_LOCATION (default_node->decl), - "multiversioning needs ifunc which is not supported " + "multiversioning needs %<ifunc%> which is not supported " "on this target"); } #endif @@ -26609,44 +26609,6 @@ prefixed_paddi_p (rtx_insn *insn) return (iform == INSN_FORM_PCREL_EXTERNAL || iform == INSN_FORM_PCREL_LOCAL); } -/* Whether an instruction is a prefixed XXSPLTI* instruction. This is called - from the prefixed attribute processing. */ - -bool -prefixed_xxsplti_p (rtx_insn *insn) -{ - rtx set = single_set (insn); - if (!set) - return false; - - rtx dest = SET_DEST (set); - rtx src = SET_SRC (set); - machine_mode mode = GET_MODE (dest); - - if (!REG_P (dest) && !SUBREG_P (dest)) - return false; - - if (GET_CODE (src) == UNSPEC) - { - int unspec = XINT (src, 1); - return (unspec == UNSPEC_XXSPLTIW - || unspec == UNSPEC_XXSPLTIDP - || unspec == UNSPEC_XXSPLTI32DX); - } - - vec_const_128bit_type vsx_const; - if (vec_const_128bit_to_bytes (src, mode, &vsx_const)) - { - if (constant_generates_xxspltiw (&vsx_const)) - return true; - - if (constant_generates_xxspltidp (&vsx_const)) - return true; - } - - return false; -} - /* Whether the next instruction needs a 'p' prefix issued before the instruction is printed out. */ static bool prepend_p_to_next_insn; diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 59531b6..4e22118 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -315,11 +315,6 @@ (eq_attr "type" "integer,add") (if_then_else (match_test "prefixed_paddi_p (insn)") (const_string "yes") - (const_string "no")) - - (eq_attr "type" "vecperm") - (if_then_else (match_test "prefixed_xxsplti_p (insn)") - (const_string "yes") (const_string "no"))] (const_string "no"))) @@ -7857,7 +7852,11 @@ (set_attr "isa" "*, *, p9v, p8v, *, p9v, p8v, *, *, *, *, *, - *, *, *, *, p10")]) + *, *, *, *, p10") + (set_attr "prefixed" + "*, *, *, *, *, *, + *, *, *, *, *, *, + *, *, *, *, yes")]) ;; LWZ LFIWZX STW STFIWX MTVSRWZ MFVSRWZ ;; FMR MR MT%0 MF%1 NOP @@ -8159,7 +8158,11 @@ (set_attr "isa" "*, *, *, p9v, p9v, p7v, p7v, *, *, *, - *, *, *, p10")]) + *, *, *, p10") + (set_attr "prefixed" + "*, *, *, *, *, + *, *, *, *, *, + *, *, *, yes")]) ;; STW LWZ MR G-const H-const F-const @@ -8232,7 +8235,12 @@ "*, *, *, p9v, p9v, p7v, p7v, *, *, *, *, *, *, *, *, - *, p8v, p8v, p10")]) + *, p8v, p8v, p10") + (set_attr "prefixed" + "*, *, *, *, *, + *, *, *, *, *, + *, *, *, *, *, + *, *, *, *")]) ;; STD LD MR MT<SPR> MF<SPR> G-const ;; H-const F-const Special diff --git a/gcc/config/rs6000/vsx.md b/gcc/config/rs6000/vsx.md index e84ffb6..c8c891e 100644 --- a/gcc/config/rs6000/vsx.md +++ b/gcc/config/rs6000/vsx.md @@ -1237,7 +1237,12 @@ "<VSisa>, <VSisa>, <VSisa>, *, *, *, *, *, *, *, p9v, *, p10, p10, - <VSisa>, *, *, *, *")]) + <VSisa>, *, *, *, *") + (set_attr "prefixed" + "*, *, *, *, *, *, + *, *, *, *, *, *, + *, yes, + *, *, *, *, *")]) ;; VSX store VSX load VSX move GPR load GPR store GPR move ;; LXVKQ XXSPLTI* @@ -1276,6 +1281,11 @@ "<VSisa>, <VSisa>, <VSisa>, *, *, *, p10, p10, p9v, *, <VSisa>, *, *, + *, *") + (set_attr "prefixed" + "*, *, *, *, *, *, + *, yes, + *, *, *, *, *, *, *")]) ;; Explicit load/store expanders for the builtin functions diff --git a/gcc/configure b/gcc/configure index 3b228c3..bd4d472 100755 --- a/gcc/configure +++ b/gcc/configure @@ -23236,6 +23236,20 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_is_gold" >&5 $as_echo "$ld_is_gold" >&6; } +# Check to see if we are using mold instead of ld +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using mold" >&5 +$as_echo_n "checking whether we are using mold... " >&6; } +ld_is_mold=no +if test x$gcc_cv_ld != x; then + if $gcc_cv_ld --version 2>/dev/null | sed 1q \ + | grep "mold" > /dev/null; then + ld_is_mold=yes + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_is_mold" >&5 +$as_echo "$ld_is_mold" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking gold linker with split stack support as non default" >&5 $as_echo_n "checking gold linker with split stack support as non default... " >&6; } # Check to see if default ld is not gold, but gold is @@ -24118,6 +24132,8 @@ else gcc_cv_ld_hidden=yes if test x"$ld_is_gold" = xyes; then : + elif test x"$ld_is_mold" = xyes; then + : elif echo "$ld_ver" | grep GNU > /dev/null; then if test 0"$ld_date" -lt 20020404; then if test -n "$ld_date"; then @@ -25197,6 +25213,8 @@ $as_echo "$gcc_cv_as_comdat_group_group" >&6; } fi if test x"$ld_is_gold" = xyes; then comdat_group=yes +elif test x"$ld_is_mold" = xyes; then + comdat_group=yes elif test $in_tree_ld = yes ; then comdat_group=no if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 16 -o "$gcc_cv_gld_major_version" -gt 2 \ diff --git a/gcc/configure.ac b/gcc/configure.ac index 472d1c8..1171c94 100644 --- a/gcc/configure.ac +++ b/gcc/configure.ac @@ -2671,6 +2671,18 @@ if test x$gcc_cv_ld != x; then fi AC_MSG_RESULT($ld_is_gold) +# Check to see if we are using mold instead of ld +AC_MSG_CHECKING(whether we are using mold) +ld_is_mold=no +if test x$gcc_cv_ld != x; then + if $gcc_cv_ld --version 2>/dev/null | sed 1q \ + | grep "mold" > /dev/null; then + ld_is_mold=yes + fi +fi +AC_MSG_RESULT($ld_is_mold) + + AC_MSG_CHECKING(gold linker with split stack support as non default) # Check to see if default ld is not gold, but gold is # available and has support for split stack. If gcc was configured @@ -3069,6 +3081,8 @@ else gcc_cv_ld_hidden=yes if test x"$ld_is_gold" = xyes; then : + elif test x"$ld_is_mold" = xyes; then + : elif echo "$ld_ver" | grep GNU > /dev/null; then if test 0"$ld_date" -lt 20020404; then if test -n "$ld_date"; then @@ -3538,6 +3552,8 @@ else fi if test x"$ld_is_gold" = xyes; then comdat_group=yes +elif test x"$ld_is_mold" = xyes; then + comdat_group=yes elif test $in_tree_ld = yes ; then comdat_group=no if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 16 -o "$gcc_cv_gld_major_version" -gt 2 \ diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index e366eed..1aadfa9 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,86 @@ +2022-01-23 Will Wray <wjwray@gmail.com> + + PR c++/55227 + * decl.cc (reshape_init_r): Only call has_designator_check when + first_initializer_p or for the inner constructor element. + (cp_complete_array_type): Call reshape_init on braced-init-list. + +2022-01-23 Jason Merrill <jason@redhat.com> + + PR c++/104182 + * cp-gimplify.cc (cp_genericize_target_expr): Make sure nothing + has set DECL_INITIAL on a TARGET_EXPR slot. + * tree.cc (is_local_temp): Don't check DECL_CONTEXT. + +2022-01-23 Jason Merrill <jason@redhat.com> + + PR c++/101072 + * cp-tree.h (build_implicit_conv_flags): Declare. + * call.cc (build_implicit_conv_flags): Split out from... + (perform_implicit_conversion_flags): ...here. + * decl.cc (check_initializer): Use it. + * pt.cc (tsubst_copy_and_build): Remove TARGET_EXPR handling. + * semantics.cc (finish_compound_literal): Don't treat + scalar values like CONSTRUCTORs. + +2022-01-21 Jason Merrill <jason@redhat.com> + + * semantics.cc (find_failing_clause): Return expr if not + decomposable. + (finish_static_assert): Show constant values in failing + comparison. + +2022-01-21 Jason Merrill <jason@redhat.com> + + PR c++/104084 + PR c++/20040 + * init.cc (build_new_1): Only pull out TARGET_EXPR_INITIAL if + alloc_expr is a TARGET_EXPR. + +2022-01-21 Marek Polacek <polacek@redhat.com> + + PR c++/101715 + * tree.cc (fixup_deferred_exception_variants): Remove duplicate + variants after parsing the exception specifications. + +2022-01-21 Jason Merrill <jason@redhat.com> + + PR c++/104139 + PR c++/103681 + * class.cc (end_of_class): Use base_binfo. + +2022-01-20 Jason Merrill <jason@redhat.com> + + PR c++/101405 + * decl.cc (reshape_init_class): Reject designator for a member of + another class. + +2022-01-20 Patrick Palka <ppalka@redhat.com> + + PR c++/91911 + PR c++/103672 + * pt.cc (keep_template_parm): Punt on a level 0 template parm. + (tsubst_decl) <case VAR_DECL>: Remove !CHECKING_P safeguard. + (tsubst) <case TEMPLATE_TYPE_PARM>: Handle CTAD placeholders + specially. + (make_auto_1): Add defaulted 'level' parameter. + (make_template_placeholder): Pass 0 as 'level' to make_auto_1. + +2022-01-20 Patrick Palka <ppalka@redhat.com> + + * decl.cc (grokdeclarator): Diagnose a CTAD placeholder as + function return type even when !funcdecl_p. + +2022-01-20 Martin Liska <mliska@suse.cz> + + PR c++/104134 + * error.cc (dump_aggr_type): Partially disable the warning. + +2022-01-20 Jason Merrill <jason@redhat.com> + + PR c++/102300 + * parser.cc (cp_parser_template_name): Use dependent_scope_p. + 2022-01-19 David Malcolm <dmalcolm@redhat.com> * cp-lang.cc (selftest::run_cp_tests): Update calls for .c to .cc diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc index d4a07a7..f7f861c 100644 --- a/gcc/cp/call.cc +++ b/gcc/cp/call.cc @@ -12638,6 +12638,25 @@ can_convert_arg_bad (tree to, tree from, tree arg, int flags, return t != NULL; } +/* Return an IMPLICIT_CONV_EXPR from EXPR to TYPE with bits set from overload + resolution FLAGS. */ + +tree +build_implicit_conv_flags (tree type, tree expr, int flags) +{ + /* In a template, we are only concerned about determining the + type of non-dependent expressions, so we do not have to + perform the actual conversion. But for initializers, we + need to be able to perform it at instantiation + (or instantiate_non_dependent_expr) time. */ + expr = build1 (IMPLICIT_CONV_EXPR, type, expr); + if (!(flags & LOOKUP_ONLYCONVERTING)) + IMPLICIT_CONV_EXPR_DIRECT_INIT (expr) = true; + if (flags & LOOKUP_NO_NARROWING) + IMPLICIT_CONV_EXPR_BRACED_INIT (expr) = true; + return expr; +} + /* Convert EXPR to TYPE. Return the converted expression. Note that we allow bad conversions here because by the time we get to @@ -12674,18 +12693,7 @@ perform_implicit_conversion_flags (tree type, tree expr, expr = error_mark_node; } else if (processing_template_decl && conv->kind != ck_identity) - { - /* In a template, we are only concerned about determining the - type of non-dependent expressions, so we do not have to - perform the actual conversion. But for initializers, we - need to be able to perform it at instantiation - (or instantiate_non_dependent_expr) time. */ - expr = build1 (IMPLICIT_CONV_EXPR, type, expr); - if (!(flags & LOOKUP_ONLYCONVERTING)) - IMPLICIT_CONV_EXPR_DIRECT_INIT (expr) = true; - if (flags & LOOKUP_NO_NARROWING) - IMPLICIT_CONV_EXPR_BRACED_INIT (expr) = true; - } + expr = build_implicit_conv_flags (type, expr, flags); else { /* Give a conversion call the same location as expr. */ diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc index e5cc6f1..5db3722 100644 --- a/gcc/cp/class.cc +++ b/gcc/cp/class.cc @@ -6414,8 +6414,8 @@ end_of_class (tree t, eoc_mode mode) { if (mode == eoc_nv_or_dsize) /* For dsize, don't count trailing empty bases. */ - offset = size_binop (PLUS_EXPR, BINFO_OFFSET (binfo), - CLASSTYPE_SIZE_UNIT (BINFO_TYPE (binfo))); + offset = size_binop (PLUS_EXPR, BINFO_OFFSET (base_binfo), + CLASSTYPE_SIZE_UNIT (BINFO_TYPE (base_binfo))); else offset = end_of_base (base_binfo); if (tree_int_cst_lt (result, offset)) diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc index 0166ef6..d1c653c 100644 --- a/gcc/cp/cp-gimplify.cc +++ b/gcc/cp/cp-gimplify.cc @@ -931,13 +931,9 @@ static void cp_genericize_target_expr (tree *stmt_p) { tree slot = TARGET_EXPR_SLOT (*stmt_p); - /* If TARGET_EXPR is created for some global var initializer, the slot - will have NULL and so is_local_temp will return false for it. If - this is a ssdf, set DECL_CONTEXT now. */ - if (DECL_CONTEXT (slot) == NULL_TREE) - DECL_CONTEXT (slot) = current_function_decl; cp_genericize_init (&TARGET_EXPR_INITIAL (*stmt_p), TARGET_EXPR_INITIAL (*stmt_p), slot); + gcc_assert (!DECL_INITIAL (slot)); } /* Genericization context. */ diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 186c544..b9eb71f 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -6599,6 +6599,7 @@ extern tree strip_top_quals (tree); extern bool reference_related_p (tree, tree); extern bool reference_compatible_p (tree, tree); extern int remaining_arguments (tree); +extern tree build_implicit_conv_flags (tree, tree, int); extern tree perform_implicit_conversion (tree, tree, tsubst_flags_t); extern tree perform_implicit_conversion_flags (tree, tree, tsubst_flags_t, int); extern tree build_converted_constant_expr (tree, tree, tsubst_flags_t); diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index 2dade75..22d3dd1 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -6569,16 +6569,22 @@ reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p, tree ictx = DECL_CONTEXT (field); if (!same_type_ignoring_top_level_qualifiers_p (ictx, type)) { - gcc_assert (ANON_AGGR_TYPE_P (ictx)); /* Find the anon aggr that is a direct member of TYPE. */ - while (true) + while (ANON_AGGR_TYPE_P (ictx)) { tree cctx = TYPE_CONTEXT (ictx); if (same_type_ignoring_top_level_qualifiers_p (cctx, type)) - break; + goto found; ictx = cctx; } - /* And then the TYPE member with that anon aggr type. */ + + /* Not found, e.g. FIELD is a member of a base class. */ + if (complain & tf_error) + error ("%qD is not a direct member of %qT", field, type); + return error_mark_node; + + found: + /* Now find the TYPE member with that anon aggr type. */ tree aafield = TYPE_FIELDS (type); for (; aafield; aafield = TREE_CHAIN (aafield)) if (TREE_TYPE (aafield) == ictx) @@ -6811,6 +6817,7 @@ reshape_init_r (tree type, reshape_iter *d, tree first_initializer_p, { tree str_init = init; tree stripped_str_init = stripped_init; + reshape_iter stripd = {}; /* Strip one level of braces if and only if they enclose a single element (as allowed by [dcl.init.string]). */ @@ -6818,7 +6825,8 @@ reshape_init_r (tree type, reshape_iter *d, tree first_initializer_p, && TREE_CODE (stripped_str_init) == CONSTRUCTOR && CONSTRUCTOR_NELTS (stripped_str_init) == 1) { - str_init = (*CONSTRUCTOR_ELTS (stripped_str_init))[0].value; + stripd.cur = CONSTRUCTOR_ELT (stripped_str_init, 0); + str_init = stripd.cur->value; stripped_str_init = tree_strip_any_location_wrapper (str_init); } @@ -6827,7 +6835,8 @@ reshape_init_r (tree type, reshape_iter *d, tree first_initializer_p, array types (one value per array element). */ if (TREE_CODE (stripped_str_init) == STRING_CST) { - if (has_designator_problem (d, complain)) + if ((first_initializer_p && has_designator_problem (d, complain)) + || (stripd.cur && has_designator_problem (&stripd, complain))) return error_mark_node; d->cur++; return str_init; @@ -7229,7 +7238,12 @@ check_initializer (tree decl, tree init, int flags, vec<tree, va_gc> **cleanups) /* In C++20, the call to build_aggr_init could have created an INIT_EXPR with a CONSTRUCTOR as the RHS to handle A(1, 2). */ - init = TREE_OPERAND (init_code, 1); + tree rhs = TREE_OPERAND (init_code, 1); + if (processing_template_decl && TREE_CODE (rhs) == TARGET_EXPR) + /* Avoid leaking TARGET_EXPR into template trees. */ + rhs = build_implicit_conv_flags (type, init, flags); + init = rhs; + init_code = NULL_TREE; /* Don't call digest_init; it's unnecessary and will complain about aggregate initialization of non-aggregate classes. */ @@ -9544,22 +9558,11 @@ cp_complete_array_type (tree *ptype, tree initial_value, bool do_default) if (initial_value) { /* An array of character type can be initialized from a - brace-enclosed string constant. - - FIXME: this code is duplicated from reshape_init. Probably - we should just call reshape_init here? */ - if (char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (*ptype))) - && TREE_CODE (initial_value) == CONSTRUCTOR - && !vec_safe_is_empty (CONSTRUCTOR_ELTS (initial_value))) - { - vec<constructor_elt, va_gc> *v = CONSTRUCTOR_ELTS (initial_value); - tree value = (*v)[0].value; - STRIP_ANY_LOCATION_WRAPPER (value); - - if (TREE_CODE (value) == STRING_CST - && v->length () == 1) - initial_value = value; - } + brace-enclosed string constant so call reshape_init to + remove the optional braces from a braced string literal. */ + if (BRACE_ENCLOSED_INITIALIZER_P (initial_value)) + initial_value = reshape_init (*ptype, initial_value, + tf_warning_or_error); /* If any of the elements are parameter packs, we can't actually complete this type now because the array size is dependent. */ @@ -12647,11 +12650,11 @@ grokdeclarator (const cp_declarator *declarator, if (!tmpl) if (tree late_auto = type_uses_auto (late_return_type)) tmpl = CLASS_PLACEHOLDER_TEMPLATE (late_auto); - if (tmpl && funcdecl_p) + if (tmpl) { - if (!dguide_name_p (unqualified_id)) + if (!funcdecl_p || !dguide_name_p (unqualified_id)) { - error_at (declarator->id_loc, "deduced class " + error_at (typespec_loc, "deduced class " "type %qD in function return type", DECL_NAME (tmpl)); inform (DECL_SOURCE_LOCATION (tmpl), diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc index 668a84d..1f04783 100644 --- a/gcc/cp/init.cc +++ b/gcc/cp/init.cc @@ -3786,7 +3786,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts, if (cookie_expr) rval = build2 (COMPOUND_EXPR, TREE_TYPE (rval), cookie_expr, rval); - if (rval == data_addr) + if (rval == data_addr && TREE_CODE (alloc_expr) == TARGET_EXPR) /* If we don't have an initializer or a cookie, strip the TARGET_EXPR and return the call (which doesn't need to be adjusted). */ rval = TARGET_EXPR_INITIAL (alloc_expr); diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 60bc35a..bba62a5 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -10660,7 +10660,7 @@ keep_template_parm (tree t, void* data) int level; int index; template_parm_level_and_index (t, &level, &index); - if (level > ftpi->max_depth) + if (level == 0 || level > ftpi->max_depth) return 0; if (TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM) @@ -14799,20 +14799,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) && VAR_HAD_UNKNOWN_BOUND (t) && type != error_mark_node) type = strip_array_domain (type); - tree sub_args = args; - if (tree auto_node = type_uses_auto (type)) - { - /* Mask off any template args past the variable's context so we - don't replace the auto with an unrelated argument. */ - int nouter = TEMPLATE_TYPE_LEVEL (auto_node) - 1; - int extra = TMPL_ARGS_DEPTH (args) - nouter; - if (extra > 0) - /* This should never happen with the new lambda instantiation - model, but keep the handling just in case. */ - gcc_assert (!CHECKING_P), - sub_args = strip_innermost_template_args (args, extra); - } - type = tsubst (type, sub_args, complain, in_decl); + type = tsubst (type, args, complain, in_decl); /* Substituting the type might have recursively instantiated this same alias (c++/86171). */ if (gen_tmpl && DECL_ALIAS_TEMPLATE_P (gen_tmpl) @@ -15564,6 +15551,19 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) } case TEMPLATE_TYPE_PARM: + if (template_placeholder_p (t)) + { + tree tmpl = CLASS_PLACEHOLDER_TEMPLATE (t); + tmpl = tsubst_copy (tmpl, args, complain, in_decl); + if (TREE_CODE (tmpl) == TEMPLATE_TEMPLATE_PARM) + tmpl = TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (tmpl); + + if (tmpl != CLASS_PLACEHOLDER_TEMPLATE (t)) + return make_template_placeholder (tmpl); + else + return t; + } + /* Fall through. */ case TEMPLATE_TEMPLATE_PARM: case BOUND_TEMPLATE_TEMPLATE_PARM: case TEMPLATE_PARM_INDEX: @@ -15737,7 +15737,6 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) of a constrained placeholder. */; else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM && !PLACEHOLDER_TYPE_CONSTRAINTS_INFO (t) - && !CLASS_PLACEHOLDER_TEMPLATE (t) && (arg = TEMPLATE_TYPE_PARM_INDEX (t), r = TEMPLATE_PARM_DESCENDANTS (arg)) && (TEMPLATE_PARM_LEVEL (r) @@ -15756,19 +15755,10 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) TYPE_REFERENCE_TO (r) = NULL_TREE; if (TREE_CODE (t) == TEMPLATE_TYPE_PARM) - { + if (tree ci = PLACEHOLDER_TYPE_CONSTRAINTS_INFO (t)) /* Propagate constraints on placeholders since they are only instantiated during satisfaction. */ - if (tree ci = PLACEHOLDER_TYPE_CONSTRAINTS_INFO (t)) - PLACEHOLDER_TYPE_CONSTRAINTS_INFO (r) = ci; - else if (tree pl = CLASS_PLACEHOLDER_TEMPLATE (t)) - { - pl = tsubst_copy (pl, args, complain, in_decl); - if (TREE_CODE (pl) == TEMPLATE_TEMPLATE_PARM) - pl = TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (pl); - CLASS_PLACEHOLDER_TEMPLATE (r) = pl; - } - } + PLACEHOLDER_TYPE_CONSTRAINTS_INFO (r) = ci; if (TREE_CODE (r) == TEMPLATE_TEMPLATE_PARM) /* We have reduced the level of the template @@ -21161,15 +21151,6 @@ tsubst_copy_and_build (tree t, RETURN (build_lambda_object (r)); } - case TARGET_EXPR: - /* We can get here for a constant initializer of non-dependent type. - FIXME stop folding in cp_parser_initializer_clause. */ - { - tree r = get_target_expr_sfinae (RECUR (TARGET_EXPR_INITIAL (t)), - complain); - RETURN (r); - } - case TRANSACTION_EXPR: RETURN (tsubst_expr(t, args, complain, in_decl, integral_constant_expression_p)); @@ -28492,18 +28473,18 @@ make_args_non_dependent (vec<tree, va_gc> *args) } /* Returns a type which represents 'auto' or 'decltype(auto)'. We use a - TEMPLATE_TYPE_PARM with a level one deeper than the actual template - parms. If set_canonical is true, we set TYPE_CANONICAL on it. */ + TEMPLATE_TYPE_PARM with a level one deeper than the actual template parms, + by default. If set_canonical is true, we set TYPE_CANONICAL on it. */ static tree -make_auto_1 (tree name, bool set_canonical) +make_auto_1 (tree name, bool set_canonical, + int level = current_template_depth + 1) { tree au = cxx_make_type (TEMPLATE_TYPE_PARM); TYPE_NAME (au) = build_decl (input_location, TYPE_DECL, name, au); TYPE_STUB_DECL (au) = TYPE_NAME (au); TEMPLATE_TYPE_PARM_INDEX (au) = build_template_parm_index - (0, current_template_depth + 1, current_template_depth + 1, - TYPE_NAME (au), NULL_TREE); + (0, level, level, TYPE_NAME (au), NULL_TREE); if (set_canonical) TYPE_CANONICAL (au) = canonical_type_parameter (au); DECL_ARTIFICIAL (TYPE_NAME (au)) = 1; @@ -28526,12 +28507,14 @@ make_auto (void) return make_auto_1 (auto_identifier, true); } -/* Return a C++17 deduction placeholder for class template TMPL. */ +/* Return a C++17 deduction placeholder for class template TMPL. + There are represented as an 'auto' with the special level 0 and + CLASS_PLACEHOLDER_TEMPLATE set. */ tree make_template_placeholder (tree tmpl) { - tree t = make_auto_1 (auto_identifier, false); + tree t = make_auto_1 (auto_identifier, false, /*level=*/0); CLASS_PLACEHOLDER_TEMPLATE (t) = tmpl; /* Our canonical type depends on the placeholder. */ TYPE_CANONICAL (t) = canonical_type_parameter (t); diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc index 8e22944..07c2b33 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -3272,12 +3272,17 @@ finish_compound_literal (tree type, tree compound_literal, /* Represent other compound literals with TARGET_EXPR so we produce a prvalue, and can elide copies. */ - if (!VECTOR_TYPE_P (type)) + if (TREE_CODE (compound_literal) == CONSTRUCTOR + || TREE_CODE (compound_literal) == VEC_INIT_EXPR) { /* The CONSTRUCTOR is now an initializer, not a compound literal. */ - TREE_HAS_CONSTRUCTOR (compound_literal) = false; + if (TREE_CODE (compound_literal) == CONSTRUCTOR) + TREE_HAS_CONSTRUCTOR (compound_literal) = false; compound_literal = get_target_expr_sfinae (compound_literal, complain); } + else + /* For e.g. int{42} just make sure it's a prvalue. */ + compound_literal = rvalue (compound_literal); return compound_literal; } @@ -11062,9 +11067,10 @@ find_failing_clause_r (tree expr) static tree find_failing_clause (tree expr) { - if (TREE_CODE (expr) != TRUTH_ANDIF_EXPR) - return NULL_TREE; - return find_failing_clause_r (expr); + if (TREE_CODE (expr) == TRUTH_ANDIF_EXPR) + if (tree e = find_failing_clause_r (expr)) + expr = e; + return expr; } /* Build a STATIC_ASSERT for a static assertion with the condition @@ -11134,9 +11140,9 @@ finish_static_assert (tree condition, tree message, location_t location, tree bad = find_failing_clause (orig_condition); /* If not, or its location is unusable, fall back to the previous location. */ - location_t cloc = location; - if (cp_expr_location (bad) != UNKNOWN_LOCATION) - cloc = cp_expr_location (bad); + location_t cloc = cp_expr_loc_or_loc (bad, location); + /* Nobody wants to see the artificial (bool) cast. */ + bad = tree_strip_nop_conversions (bad); /* Report the error. */ if (len == 0) @@ -11144,16 +11150,22 @@ finish_static_assert (tree condition, tree message, location_t location, else error_at (cloc, "static assertion failed: %s", TREE_STRING_POINTER (message)); - if (show_expr_p) - inform (cloc, "%qE evaluates to false", - /* Nobody wants to see the artificial (bool) cast. */ - (bad ? tree_strip_nop_conversions (bad) : orig_condition)); /* Actually explain the failure if this is a concept check or a requires-expression. */ - if (concept_check_p (orig_condition) - || TREE_CODE (orig_condition) == REQUIRES_EXPR) - diagnose_constraints (location, orig_condition, NULL_TREE); + if (concept_check_p (bad) + || TREE_CODE (bad) == REQUIRES_EXPR) + diagnose_constraints (location, bad, NULL_TREE); + else if (COMPARISON_CLASS_P (bad) + && ARITHMETIC_TYPE_P (TREE_TYPE (TREE_OPERAND (bad, 0)))) + { + tree op0 = fold_non_dependent_expr (TREE_OPERAND (bad, 0)); + tree op1 = fold_non_dependent_expr (TREE_OPERAND (bad, 1)); + tree cond = build2 (TREE_CODE (bad), boolean_type_node, op0, op1); + inform (cloc, "the comparison reduces to %qE", cond); + } + else if (show_expr_p) + inform (cloc, "%qE evaluates to false", bad); } else if (condition && condition != error_mark_node) { diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc index bcd44e7..5d453e4 100644 --- a/gcc/cp/tree.cc +++ b/gcc/cp/tree.cc @@ -557,8 +557,7 @@ bool is_local_temp (tree decl) { return (VAR_P (decl) && DECL_ARTIFICIAL (decl) - && !TREE_STATIC (decl) - && DECL_FUNCTION_SCOPE_P (decl)); + && !TREE_STATIC (decl)); } /* Set various status flags when building an AGGR_INIT_EXPR object T. */ @@ -2804,8 +2803,9 @@ fixup_deferred_exception_variants (tree type, tree raises) /* Though sucky, this walk will process the canonical variants first. */ + tree prev = NULL_TREE; for (tree variant = TYPE_MAIN_VARIANT (type); - variant; variant = TYPE_NEXT_VARIANT (variant)) + variant; prev = variant, variant = TYPE_NEXT_VARIANT (variant)) if (TYPE_RAISES_EXCEPTIONS (variant) == original) { gcc_checking_assert (variant != TYPE_MAIN_VARIANT (type)); @@ -2815,18 +2815,27 @@ fixup_deferred_exception_variants (tree type, tree raises) cp_cv_quals var_quals = TYPE_QUALS (variant); cp_ref_qualifier rqual = type_memfn_rqual (variant); + /* If VARIANT would become a dup (cp_check_qualified_type-wise) + of an existing variant in the variant list of TYPE after its + exception specification has been parsed, elide it. Otherwise, + build_cp_fntype_variant could use it, leading to "canonical + types differ for identical types." */ tree v = TYPE_MAIN_VARIANT (type); for (; v; v = TYPE_NEXT_VARIANT (v)) - if (TYPE_CANONICAL (v) == v - && cp_check_qualified_type (v, variant, var_quals, - rqual, cr, false)) - break; + if (cp_check_qualified_type (v, variant, var_quals, + rqual, cr, false)) + { + /* The main variant will not match V, so PREV will never + be null. */ + TYPE_NEXT_VARIANT (prev) = TYPE_NEXT_VARIANT (variant); + break; + } TYPE_RAISES_EXCEPTIONS (variant) = raises; if (!v) v = build_cp_fntype_variant (TYPE_CANONICAL (variant), rqual, cr, false); - TYPE_CANONICAL (variant) = v; + TYPE_CANONICAL (variant) = TYPE_CANONICAL (v); } else TYPE_RAISES_EXCEPTIONS (variant) = raises; diff --git a/gcc/doc/generic.texi b/gcc/doc/generic.texi index 3e5b06a..e5f9d1b 100644 --- a/gcc/doc/generic.texi +++ b/gcc/doc/generic.texi @@ -1318,6 +1318,7 @@ The type of the node specifies the alignment of the access. @tindex PLUS_EXPR @tindex MINUS_EXPR @tindex MULT_EXPR +@tindex WIDEN_MULT_EXPR @tindex MULT_HIGHPART_EXPR @tindex RDIV_EXPR @tindex TRUNC_DIV_EXPR @@ -1532,10 +1533,18 @@ one operand is of floating type and the other is of integral type. The behavior of these operations on signed arithmetic overflow is controlled by the @code{flag_wrapv} and @code{flag_trapv} variables. +@item WIDEN_MULT_EXPR +This node represents a widening multiplication. The operands have +integral types with same @var{b} bits of precision, producing an +integral type result with at least @math{2@var{b}} bits of precision. +The behaviour is equivalent to extending both operands, possibly of +different signedness, to the result type, then multiplying them. + @item MULT_HIGHPART_EXPR This node represents the ``high-part'' of a widening multiplication. For an integral type with @var{b} bits of precision, the result is the most significant @var{b} bits of the full @math{2@var{b}} product. +Both operands must have the same precision and same signedness. @item RDIV_EXPR This node represents a floating point division operation. diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 810d618..ce3d78d 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -786,6 +786,7 @@ Objective-C and Objective-C++ Dialects}. -mpure-code @gol -mcmse @gol -mfix-cmse-cve-2021-35465 @gol +-mstack-protector-guard=@var{guard} -mstack-protector-guard-offset=@var{offset} @gol -mfdpic} @emph{AVR Options} @@ -21325,6 +21326,16 @@ enabled by default when the option @option{-mcpu=} is used with @code{cortex-m33}, @code{cortex-m35p} or @code{cortex-m55}. The option @option{-mno-fix-cmse-cve-2021-35465} can be used to disable the mitigation. +@item -mstack-protector-guard=@var{guard} +@itemx -mstack-protector-guard-offset=@var{offset} +@opindex mstack-protector-guard +@opindex mstack-protector-guard-offset +Generate stack protection code using canary at @var{guard}. Supported +locations are @samp{global} for a global canary or @samp{tls} for a +canary accessible via the TLS register. The option +@option{-mstack-protector-guard-offset=} is for use with +@option{-fstack-protector-guard=tls} and not for use in user-land code. + @item -mfdpic @itemx -mno-fdpic @opindex mfdpic diff --git a/gcc/doc/options.texi b/gcc/doc/options.texi index d552b64..50674938 100644 --- a/gcc/doc/options.texi +++ b/gcc/doc/options.texi @@ -132,6 +132,21 @@ be accepted by the driver. This is used for cases such as @option{-march=native} that are processed by the driver so that @samp{gcc -v} shows how the options chosen depended on the system on which the compiler was run. + +@item Set(@var{number}) +This property is optional, required for enumerations used in +@code{EnumSet} options. @var{number} should be decimal number between +1 and 64 inclusive and divides the enumeration into a set of +sets of mutually exclusive arguments. Arguments with the same +@var{number} can't be specified together in the same option, but +arguments with different @var{number} can. @var{value} needs to be +chosen such that a mask of all @var{value} values from the same set +@var{number} bitwise ored doesn't overlap with masks for other sets. +When @code{-foption=arg_from_set1,arg_from_set4} and +@code{-fno-option=arg_from_set3} are used, the effect is that previous +value of the @code{Var} will get bits from set 1 and 4 masks cleared, +ored @code{Value} of @code{arg_from_set1} and @code{arg_from_set4} +and then will get bits from set 3 mask cleared. @end table @item @@ -396,6 +411,24 @@ with the corresponding @samp{Enum} record. The string is checked and converted to the integer specified in the corresponding @samp{EnumValue} record before being passed to option handlers. +@item EnumSet +Must be used together with the @code{Enum(@var{name})} property. +Corresponding @samp{Enum} record must use @code{Set} properties. +The option's argument is either a string from the set like for +@code{Enum(@var{name})}, but with a slightly different behavior that +the whole @code{Var} isn't overwritten, but only the bits in all the +enumeration values with the same set bitwise ored together. +Or option's argument can be a comma separated list of strings where +each string is from a different @code{Set(@var{number})}. + +@item EnumBitSet +Must be used together with the @code{Enum(@var{name})} property. +Similar to @samp{EnumSet}, but corresponding @samp{Enum} record must +not use @code{Set} properties, each @code{EnumValue} should have +@code{Value} that is a power of 2, each value is treated as its own +set and its value as the set's mask, so there are no mutually +exclusive arguments. + @item Defer The option should be stored in a vector, specified with @code{Var}, for later processing. diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index e044230..ea90c19 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,23 @@ +2022-01-22 Harald Anlauf <anlauf@gmx.de> + + PR fortran/104127 + * simplify.cc (gfc_simplify_transfer): Ensure that the result + typespec is set up for TRANSFER with MOLD of type CHARACTER + including character length even if the result is a zero-sized + array. + +2022-01-20 Sandra Loosemore <sandra@codesourcery.com> + + PR fortran/103695 + PR fortran/102621 + * gfortran.h (struct gfc_namespace) Add omp_affinity_iterator + field. + * dump-parse-tree.cc (show_iterator): Use it. + * openmp.cc (gfc_match_iterator): Likewise. + (resolve_omp_clauses): Likewise. + * trans-decl.cc (gfc_finish_var_decl): Likewise. + * trans-openmp.cc (handle_iterator): Likewise. + 2022-01-18 Harald Anlauf <anlauf@gmx.de> PR fortran/103692 diff --git a/gcc/fortran/dump-parse-tree.cc b/gcc/fortran/dump-parse-tree.cc index a618ae2..3112cae 100644 --- a/gcc/fortran/dump-parse-tree.cc +++ b/gcc/fortran/dump-parse-tree.cc @@ -1302,10 +1302,10 @@ show_code (int level, gfc_code *c) static void show_iterator (gfc_namespace *ns) { - for (gfc_symbol *sym = ns->proc_name; sym; sym = sym->tlink) + for (gfc_symbol *sym = ns->omp_affinity_iterators; sym; sym = sym->tlink) { gfc_constructor *c; - if (sym != ns->proc_name) + if (sym != ns->omp_affinity_iterators) fputc (',', dumpfile); fputs (sym->name, dumpfile); fputc ('=', dumpfile); diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index 00a558a..993879f 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -2107,6 +2107,9 @@ typedef struct gfc_namespace /* !$ACC ROUTINE clauses. */ gfc_omp_clauses *oacc_routine_clauses; + /* !$ACC TASK AFFINITY iterator symbols. */ + gfc_symbol *omp_affinity_iterators; + /* !$ACC ROUTINE names. */ gfc_oacc_routine_name *oacc_routine_names; diff --git a/gcc/fortran/lang.opt b/gcc/fortran/lang.opt index ab92e0e..cf39712 100644 --- a/gcc/fortran/lang.opt +++ b/gcc/fortran/lang.opt @@ -421,23 +421,29 @@ Fortran Produce a warning at runtime if a array temporary has been created for a procedure argument. fconvert= -Fortran RejectNegative Joined Enum(gfc_convert) Var(flag_convert) Init(GFC_FLAG_CONVERT_NATIVE) --fconvert=<big-endian|little-endian|native|swap> The endianness used for unformatted files. +Fortran RejectNegative Joined Enum(gfc_convert) EnumSet Var(flag_convert) Init(GFC_FLAG_CONVERT_NATIVE) +-fconvert=<big-endian|little-endian|native|swap|r16_ieee|r16_ibm> The endianness used for unformatted files. Enum Name(gfc_convert) Type(enum gfc_convert) UnknownError(Unrecognized option to endianness value: %qs) EnumValue -Enum(gfc_convert) String(big-endian) Value(GFC_FLAG_CONVERT_BIG) +Enum(gfc_convert) String(big-endian) Value(GFC_FLAG_CONVERT_BIG) Set(1) EnumValue -Enum(gfc_convert) String(little-endian) Value(GFC_FLAG_CONVERT_LITTLE) +Enum(gfc_convert) String(little-endian) Value(GFC_FLAG_CONVERT_LITTLE) Set(1) EnumValue -Enum(gfc_convert) String(native) Value(GFC_FLAG_CONVERT_NATIVE) +Enum(gfc_convert) String(native) Value(GFC_FLAG_CONVERT_NATIVE) Set(1) EnumValue -Enum(gfc_convert) String(swap) Value(GFC_FLAG_CONVERT_SWAP) +Enum(gfc_convert) String(swap) Value(GFC_FLAG_CONVERT_SWAP) Set(1) + +EnumValue +Enum(gfc_convert) String(r16_ieee) Value(GFC_FLAG_CONVERT_R16_IEEE) Set(2) + +EnumValue +Enum(gfc_convert) String(r16_ibm) Value(GFC_FLAG_CONVERT_R16_IBM) Set(2) fcray-pointer Fortran Var(flag_cray_pointer) diff --git a/gcc/fortran/openmp.cc b/gcc/fortran/openmp.cc index 9b73b9f..073e5a1 100644 --- a/gcc/fortran/openmp.cc +++ b/gcc/fortran/openmp.cc @@ -1123,7 +1123,7 @@ gfc_match_iterator (gfc_namespace **ns, bool permit_var) if (last) last->tlink = sym; else - (*ns)->proc_name = sym; + (*ns)->omp_affinity_iterators = sym; last = sym; sym->declared_at = prev_loc; sym->ts = ts; @@ -6832,8 +6832,8 @@ resolve_omp_clauses (gfc_code *code, gfc_omp_clauses *omp_clauses, && n->u2.ns && !n->u2.ns->resolved) { n->u2.ns->resolved = 1; - for (gfc_symbol *sym = n->u2.ns->proc_name; sym; - sym = sym->tlink) + for (gfc_symbol *sym = n->u2.ns->omp_affinity_iterators; + sym; sym = sym->tlink) { gfc_constructor *c; c = gfc_constructor_first (sym->value->value.constructor); diff --git a/gcc/fortran/simplify.cc b/gcc/fortran/simplify.cc index 3881370..8604162 100644 --- a/gcc/fortran/simplify.cc +++ b/gcc/fortran/simplify.cc @@ -8162,7 +8162,18 @@ gfc_simplify_transfer (gfc_expr *source, gfc_expr *mold, gfc_expr *size) set even for array expressions, in order to pass this information into gfc_target_interpret_expr. */ if (result->ts.type == BT_CHARACTER && gfc_is_constant_expr (mold_element)) - result->value.character.length = mold_element->value.character.length; + { + result->value.character.length = mold_element->value.character.length; + + /* Let the typespec of the result inherit the string length. + This is crucial if a resulting array has size zero. */ + if (mold_element->ts.u.cl->length) + result->ts.u.cl->length = gfc_copy_expr (mold_element->ts.u.cl->length); + else + result->ts.u.cl->length = + gfc_get_int_expr (gfc_charlen_int_kind, NULL, + mold_element->value.character.length); + } /* Set the number of elements in the result, and determine its size. */ diff --git a/gcc/fortran/trans-decl.cc b/gcc/fortran/trans-decl.cc index 1112ca9..6493cc2 100644 --- a/gcc/fortran/trans-decl.cc +++ b/gcc/fortran/trans-decl.cc @@ -647,6 +647,9 @@ gfc_finish_var_decl (tree decl, gfc_symbol * sym) && sym->ns->proc_name->attr.flavor == FL_LABEL) /* This is a BLOCK construct. */ add_decl_as_local (decl); + else if (sym->ns->omp_affinity_iterators) + /* This is a block-local iterator. */ + add_decl_as_local (decl); else gfc_add_decl_to_parent_function (decl); } diff --git a/gcc/fortran/trans-openmp.cc b/gcc/fortran/trans-openmp.cc index 9eabf68..d5a6b2d 100644 --- a/gcc/fortran/trans-openmp.cc +++ b/gcc/fortran/trans-openmp.cc @@ -2483,7 +2483,7 @@ static tree handle_iterator (gfc_namespace *ns, stmtblock_t *iter_block, tree block) { tree list = NULL_TREE; - for (gfc_symbol *sym = ns->proc_name; sym; sym = sym->tlink) + for (gfc_symbol *sym = ns->omp_affinity_iterators; sym; sym = sym->tlink) { gfc_constructor *c; gfc_se se; diff --git a/gcc/fortran/trans-types.cc b/gcc/fortran/trans-types.cc index a56337b..3cdc529 100644 --- a/gcc/fortran/trans-types.cc +++ b/gcc/fortran/trans-types.cc @@ -527,6 +527,9 @@ gfc_init_kinds (void) } } } + else if ((flag_convert & (GFC_CONVERT_R16_IEEE | GFC_CONVERT_R16_IBM)) != 0) + gfc_fatal_error ("%<-fconvert=r16_ieee%> or %<-fconvert=r16_ibm%> not " + "supported on this architecture"); /* Choose the default integer kind. We choose 4 unless the user directs us otherwise. Even if the user specified that the default integer kind is 8, diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc index 08d3cc2..3639aa2 100644 --- a/gcc/gimple-fold.cc +++ b/gcc/gimple-fold.cc @@ -291,7 +291,9 @@ get_symbol_constant_value (tree sym) if (val) { val = canonicalize_constructor_val (unshare_expr (val), sym); - if (val && is_gimple_min_invariant (val)) + if (val + && is_gimple_min_invariant (val) + && useless_type_conversion_p (TREE_TYPE (sym), TREE_TYPE (val))) return val; else return NULL_TREE; diff --git a/gcc/gimple-range-path.cc b/gcc/gimple-range-path.cc index a1bcca0..3ee4989 100644 --- a/gcc/gimple-range-path.cc +++ b/gcc/gimple-range-path.cc @@ -400,6 +400,19 @@ path_range_query::compute_ranges_in_phis (basic_block bb) bitmap_ior_into (m_has_cache_entry, phi_set); } +// Return TRUE if relations may be invalidated after crossing edge E. + +bool +path_range_query::relations_may_be_invalidated (edge e) +{ + // As soon as the path crosses a back edge, we can encounter + // definitions of SSA_NAMEs that may have had a use in the path + // already, so this will then be a new definition. The relation + // code is all designed around seeing things in dominator order, and + // crossing a back edge in the path violates this assumption. + return (e->flags & EDGE_DFS_BACK); +} + // Compute ranges defined in the current block, or exported to the // next block. @@ -440,6 +453,22 @@ path_range_query::compute_ranges_in_block (basic_block bb) // Solve imports that are exported to the next block. basic_block next = next_bb (); edge e = find_edge (bb, next); + + if (m_resolve && relations_may_be_invalidated (e)) + { + if (DEBUG_SOLVER) + fprintf (dump_file, + "Resetting relations as they may be invalidated in %d->%d.\n", + e->src->index, e->dest->index); + + path_oracle *p = get_path_oracle (); + p->reset_path (); + // ?? Instead of nuking the root oracle altogether, we could + // reset the path oracle to search for relations from the top of + // the loop with the root oracle. Something for future development. + p->set_root_oracle (nullptr); + } + EXECUTE_IF_SET_IN_BITMAP (m_imports, 0, i, bi) { tree name = ssa_name (i); @@ -742,9 +771,19 @@ path_range_query::range_of_stmt (irange &r, gimple *stmt, tree) return true; } +// If possible, register the relation on the incoming edge E into PHI. + void -path_range_query::maybe_register_phi_relation (gphi *phi, tree arg) +path_range_query::maybe_register_phi_relation (gphi *phi, edge e) { + tree arg = gimple_phi_arg_def (phi, e->dest_idx); + + if (!gimple_range_ssa_p (arg)) + return; + + if (relations_may_be_invalidated (e)) + return; + basic_block bb = gimple_bb (phi); tree result = gimple_phi_result (phi); @@ -754,7 +793,7 @@ path_range_query::maybe_register_phi_relation (gphi *phi, tree arg) return; if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, " from bb%d:", bb->index); + fprintf (dump_file, "maybe_register_phi_relation in bb%d:", bb->index); get_path_oracle ()->killing_def (result); m_oracle->register_relation (entry_bb (), EQ_EXPR, arg, result); @@ -787,10 +826,7 @@ path_range_query::compute_phi_relations (basic_block bb, basic_block prev) for (size_t i = 0; i < nargs; ++i) if (e_in == gimple_phi_arg_edge (phi, i)) { - tree arg = gimple_phi_arg_def (phi, i); - - if (gimple_range_ssa_p (arg)) - maybe_register_phi_relation (phi, arg); + maybe_register_phi_relation (phi, e_in); break; } } diff --git a/gcc/gimple-range-path.h b/gcc/gimple-range-path.h index f090b7c..1820626 100644 --- a/gcc/gimple-range-path.h +++ b/gcc/gimple-range-path.h @@ -63,10 +63,11 @@ private: void ssa_range_in_phi (irange &r, gphi *phi); void compute_outgoing_relations (basic_block bb, basic_block next); void compute_phi_relations (basic_block bb, basic_block prev); - void maybe_register_phi_relation (gphi *, tree arg); + void maybe_register_phi_relation (gphi *, edge e); bool add_to_imports (tree name, bitmap imports); bool import_p (tree name); bool ssa_defined_in_bb (tree name, basic_block bb); + bool relations_may_be_invalidated (edge); // Path navigation. void set_path (const vec<basic_block> &); diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc index c36cd5d..8bc33ee 100644 --- a/gcc/gimple-ssa-warn-access.cc +++ b/gcc/gimple-ssa-warn-access.cc @@ -3953,15 +3953,14 @@ pass_waccess::warn_invalid_pointer (tree ref, gimple *use_stmt, "may be used") : G_("using dangling pointer %qE to an unnamed " "temporary")), - ref, var)) + ref)) || (!ref && warning_at (use_loc, OPT_Wdangling_pointer_, (maybe ? G_("dangling pointer to an unnamed temporary " "may be used") : G_("using a dangling pointer to an unnamed " - "temporary")), - var))) + "temporary"))))) { inform (DECL_SOURCE_LOCATION (var), "unnamed temporary defined here"); diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 9cc6a1c..a42d88d 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -799e9807c36fc661b14dfff136369556f09a5ebf +7d510bf5fcec9b0ccc0282f4193a80c0a164df63 The first line of this file holds the git revision number of the last merge done from the gofrontend repository. @@ -1465,10 +1465,11 @@ setup_reg_class_nregs (void) -/* Set up IRA_PROHIBITED_CLASS_MODE_REGS and IRA_CLASS_SINGLETON. - This function is called once IRA_CLASS_HARD_REGS has been initialized. */ +/* Set up IRA_PROHIBITED_CLASS_MODE_REGS, IRA_EXCLUDE_CLASS_MODE_REGS, and + IRA_CLASS_SINGLETON. This function is called once IRA_CLASS_HARD_REGS has + been initialized. */ static void -setup_prohibited_class_mode_regs (void) +setup_prohibited_and_exclude_class_mode_regs (void) { int j, k, hard_regno, cl, last_hard_regno, count; @@ -1480,6 +1481,7 @@ setup_prohibited_class_mode_regs (void) count = 0; last_hard_regno = -1; CLEAR_HARD_REG_SET (ira_prohibited_class_mode_regs[cl][j]); + CLEAR_HARD_REG_SET (ira_exclude_class_mode_regs[cl][j]); for (k = ira_class_hard_regs_num[cl] - 1; k >= 0; k--) { hard_regno = ira_class_hard_regs[cl][k]; @@ -1492,6 +1494,10 @@ setup_prohibited_class_mode_regs (void) last_hard_regno = hard_regno; count++; } + else + { + SET_HARD_REG_BIT (ira_exclude_class_mode_regs[cl][j], hard_regno); + } } ira_class_singleton[cl][j] = (count == 1 ? last_hard_regno : -1); } @@ -1707,7 +1713,7 @@ ira_init (void) setup_alloc_regs (flag_omit_frame_pointer != 0); setup_class_subset_and_memory_move_costs (); setup_reg_class_nregs (); - setup_prohibited_class_mode_regs (); + setup_prohibited_and_exclude_class_mode_regs (); find_reg_classes (); clarify_prohibited_class_mode_regs (); setup_hard_regno_aclass (); @@ -117,6 +117,11 @@ struct target_ira the allocation of given register class whose targetm.hard_regno_mode_ok values for given mode are false. */ HARD_REG_SET x_ira_prohibited_class_mode_regs[N_REG_CLASSES][NUM_MACHINE_MODES]; + + /* When an allocatable hard register in given mode can not be placed in given + register class, it is in the set of the following array element. It can + happen only when given mode requires more one hard register. */ + HARD_REG_SET x_ira_exclude_class_mode_regs[N_REG_CLASSES][NUM_MACHINE_MODES]; }; extern struct target_ira default_target_ira; @@ -164,6 +169,8 @@ extern struct target_ira *this_target_ira; (this_target_ira->x_ira_no_alloc_regs) #define ira_prohibited_class_mode_regs \ (this_target_ira->x_ira_prohibited_class_mode_regs) +#define ira_exclude_class_mode_regs \ + (this_target_ira->x_ira_exclude_class_mode_regs) /* Major structure describing equivalence info for a pseudo. */ struct ira_reg_equiv_s diff --git a/gcc/lra-assigns.cc b/gcc/lra-assigns.cc index cacf6be..c1d40ea 100644 --- a/gcc/lra-assigns.cc +++ b/gcc/lra-assigns.cc @@ -550,7 +550,7 @@ find_hard_regno_for_1 (int regno, int *cost, int try_only_hard_regno, sparseset_clear_bit (conflict_reload_and_inheritance_pseudos, regno); val = lra_reg_info[regno].val; offset = lra_reg_info[regno].offset; - CLEAR_HARD_REG_SET (impossible_start_hard_regs); + impossible_start_hard_regs = lra_reg_info[regno].exclude_start_hard_regs; EXECUTE_IF_SET_IN_SPARSESET (live_range_hard_reg_pseudos, conflict_regno) { conflict_hr = live_pseudos_reg_renumber[conflict_regno]; diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc index e3d1d51..9cee174 100644 --- a/gcc/lra-constraints.cc +++ b/gcc/lra-constraints.cc @@ -625,16 +625,16 @@ canonicalize_reload_addr (rtx addr) return addr; } -/* Create a new pseudo using MODE, RCLASS, ORIGINAL or reuse an existing - reload pseudo. Don't reuse an existing reload pseudo if IN_SUBREG_P - is true and the reused pseudo should be wrapped up in a SUBREG. - The result pseudo is returned through RESULT_REG. Return TRUE if we - created a new pseudo, FALSE if we reused an existing reload pseudo. - Use TITLE to describe new registers for debug purposes. */ +/* Create a new pseudo using MODE, RCLASS, EXCLUDE_START_HARD_REGS, ORIGINAL or + reuse an existing reload pseudo. Don't reuse an existing reload pseudo if + IN_SUBREG_P is true and the reused pseudo should be wrapped up in a SUBREG. + The result pseudo is returned through RESULT_REG. Return TRUE if we created + a new pseudo, FALSE if we reused an existing reload pseudo. Use TITLE to + describe new registers for debug purposes. */ static bool get_reload_reg (enum op_type type, machine_mode mode, rtx original, - enum reg_class rclass, bool in_subreg_p, - const char *title, rtx *result_reg) + enum reg_class rclass, HARD_REG_SET *exclude_start_hard_regs, + bool in_subreg_p, const char *title, rtx *result_reg) { int i, regno; enum reg_class new_class; @@ -672,7 +672,8 @@ get_reload_reg (enum op_type type, machine_mode mode, rtx original, return false; } *result_reg - = lra_create_new_reg_with_unique_value (mode, original, rclass, title); + = lra_create_new_reg_with_unique_value (mode, original, rclass, + exclude_start_hard_regs, title); return true; } /* Prevent reuse value of expression with side effects, @@ -723,7 +724,8 @@ get_reload_reg (enum op_type type, machine_mode mode, rtx original, } *result_reg = (unique_p ? lra_create_new_reg_with_unique_value - : lra_create_new_reg) (mode, original, rclass, title); + : lra_create_new_reg) (mode, original, rclass, + exclude_start_hard_regs, title); lra_assert (curr_insn_input_reloads_num < LRA_MAX_INSN_RELOADS); curr_insn_input_reloads[curr_insn_input_reloads_num].input = original; curr_insn_input_reloads[curr_insn_input_reloads_num].match_p = false; @@ -991,17 +993,17 @@ check_conflict_input_operands (int regno, signed char *ins) return true; } -/* Generate reloads for matching OUT and INS (array of input operand - numbers with end marker -1) with reg class GOAL_CLASS, considering - output operands OUTS (similar array to INS) needing to be in different - registers. Add input and output reloads correspondingly to the lists - *BEFORE and *AFTER. OUT might be negative. In this case we generate +/* Generate reloads for matching OUT and INS (array of input operand numbers + with end marker -1) with reg class GOAL_CLASS and EXCLUDE_START_HARD_REGS, + considering output operands OUTS (similar array to INS) needing to be in + different registers. Add input and output reloads correspondingly to the + lists *BEFORE and *AFTER. OUT might be negative. In this case we generate input reloads for matched input operands INS. EARLY_CLOBBER_P is a flag that the output operand is early clobbered for chosen alternative. */ static void match_reload (signed char out, signed char *ins, signed char *outs, - enum reg_class goal_class, rtx_insn **before, - rtx_insn **after, bool early_clobber_p) + enum reg_class goal_class, HARD_REG_SET *exclude_start_hard_regs, + rtx_insn **before, rtx_insn **after, bool early_clobber_p) { bool out_conflict; int i, in; @@ -1020,8 +1022,9 @@ match_reload (signed char out, signed char *ins, signed char *outs, if (partial_subreg_p (outmode, inmode)) { reg = new_in_reg - = lra_create_new_reg_with_unique_value (inmode, in_rtx, - goal_class, ""); + = lra_create_new_reg_with_unique_value (inmode, in_rtx, goal_class, + exclude_start_hard_regs, + ""); new_out_reg = gen_lowpart_SUBREG (outmode, reg); LRA_SUBREG_P (new_out_reg) = 1; /* If the input reg is dying here, we can use the same hard @@ -1038,7 +1041,9 @@ match_reload (signed char out, signed char *ins, signed char *outs, { reg = new_out_reg = lra_create_new_reg_with_unique_value (outmode, out_rtx, - goal_class, ""); + goal_class, + exclude_start_hard_regs, + ""); new_in_reg = gen_lowpart_SUBREG (inmode, reg); /* NEW_IN_REG is non-paradoxical subreg. We don't want NEW_OUT_REG living above. We add clobber clause for @@ -1121,9 +1126,11 @@ match_reload (signed char out, signed char *ins, signed char *outs, && (out < 0 || regno_val_use_in (REGNO (in_rtx), out_rtx) == NULL_RTX) && !out_conflict - ? lra_create_new_reg (inmode, in_rtx, goal_class, "") - : lra_create_new_reg_with_unique_value (outmode, out_rtx, - goal_class, "")); + ? lra_create_new_reg (inmode, in_rtx, goal_class, + exclude_start_hard_regs, "") + : lra_create_new_reg_with_unique_value (outmode, out_rtx, goal_class, + exclude_start_hard_regs, + "")); } /* In operand can be got from transformations before processing insn constraints. One example of such transformations is subreg @@ -1360,7 +1367,7 @@ check_and_process_move (bool *change_p, bool *sec_mem_p ATTRIBUTE_UNUSED) new_reg = NULL_RTX; if (secondary_class != NO_REGS) new_reg = lra_create_new_reg_with_unique_value (GET_MODE (src), NULL_RTX, - secondary_class, + secondary_class, NULL, "secondary"); start_sequence (); if (sri.icode == CODE_FOR_nothing) @@ -1373,7 +1380,7 @@ check_and_process_move (bool *change_p, bool *sec_mem_p ATTRIBUTE_UNUSED) (insn_data[sri.icode].operand[2].constraint)); scratch_reg = (lra_create_new_reg_with_unique_value (insn_data[sri.icode].operand[2].mode, NULL_RTX, - scratch_class, "scratch")); + scratch_class, NULL, "scratch")); emit_insn (GEN_FCN (sri.icode) (new_reg != NULL_RTX ? new_reg : dest, src, scratch_reg)); } @@ -1401,6 +1408,9 @@ check_and_process_move (bool *change_p, bool *sec_mem_p ATTRIBUTE_UNUSED) /* The chosen reg classes which should be used for the corresponding operands. */ static enum reg_class goal_alt[MAX_RECOG_OPERANDS]; +/* Hard registers which cannot be a start hard register for the corresponding + operands. */ +static HARD_REG_SET goal_alt_exclude_start_hard_regs[MAX_RECOG_OPERANDS]; /* True if the operand should be the same as another operand and that other operand does not need a reload. */ static bool goal_alt_match_win[MAX_RECOG_OPERANDS]; @@ -1492,7 +1502,8 @@ process_addr_reg (rtx *loc, bool check_only_p, rtx_insn **before, rtx_insn **aft return true; /* Always reload memory in an address even if the target supports such addresses. */ - new_reg = lra_create_new_reg_with_unique_value (mode, reg, cl, "address"); + new_reg = lra_create_new_reg_with_unique_value (mode, reg, cl, NULL, + "address"); before_p = true; } else @@ -1518,7 +1529,8 @@ process_addr_reg (rtx *loc, bool check_only_p, rtx_insn **before, rtx_insn **aft return true; reg = *loc; if (get_reload_reg (after == NULL ? OP_IN : OP_INOUT, - mode, reg, cl, subreg_p, "address", &new_reg)) + mode, reg, cl, NULL, + subreg_p, "address", &new_reg)) before_p = true; } else if (new_class != NO_REGS && rclass != new_class) @@ -1673,7 +1685,8 @@ simplify_operand_subreg (int nop, machine_mode reg_mode) enum reg_class rclass = (enum reg_class) targetm.preferred_reload_class (reg, ALL_REGS); if (get_reload_reg (curr_static_id->operand[nop].type, innermode, - reg, rclass, TRUE, "slow/invalid mem", &new_reg)) + reg, rclass, NULL, + TRUE, "slow/invalid mem", &new_reg)) { bool insert_before, insert_after; bitmap_set_bit (&lra_subreg_reload_pseudos, REGNO (new_reg)); @@ -1692,7 +1705,8 @@ simplify_operand_subreg (int nop, machine_mode reg_mode) rclass = (enum reg_class) targetm.preferred_reload_class (reg, ALL_REGS); if (get_reload_reg (curr_static_id->operand[nop].type, mode, reg, - rclass, TRUE, "slow/invalid mem", &new_reg)) + rclass, NULL, + TRUE, "slow/invalid mem", &new_reg)) { bool insert_before, insert_after; bitmap_set_bit (&lra_subreg_reload_pseudos, REGNO (new_reg)); @@ -1776,7 +1790,8 @@ simplify_operand_subreg (int nop, machine_mode reg_mode) = (enum reg_class) targetm.preferred_reload_class (reg, ALL_REGS); if (get_reload_reg (curr_static_id->operand[nop].type, reg_mode, reg, - rclass, TRUE, "subreg reg", &new_reg)) + rclass, NULL, + TRUE, "subreg reg", &new_reg)) { bool insert_before, insert_after; bitmap_set_bit (&lra_subreg_reload_pseudos, REGNO (new_reg)); @@ -1849,7 +1864,8 @@ simplify_operand_subreg (int nop, machine_mode reg_mode) = (enum reg_class) targetm.preferred_reload_class (reg, ALL_REGS); if (get_reload_reg (curr_static_id->operand[nop].type, mode, reg, - rclass, TRUE, "paradoxical subreg", &new_reg)) + rclass, NULL, + TRUE, "paradoxical subreg", &new_reg)) { rtx subreg; bool insert_before, insert_after; @@ -2032,6 +2048,7 @@ process_alt_operands (int only_alternative) int early_clobbered_nops[MAX_RECOG_OPERANDS]; enum reg_class curr_alt[MAX_RECOG_OPERANDS]; HARD_REG_SET curr_alt_set[MAX_RECOG_OPERANDS]; + HARD_REG_SET curr_alt_exclude_start_hard_regs[MAX_RECOG_OPERANDS]; bool curr_alt_match_win[MAX_RECOG_OPERANDS]; bool curr_alt_win[MAX_RECOG_OPERANDS]; bool curr_alt_offmemok[MAX_RECOG_OPERANDS]; @@ -2133,6 +2150,7 @@ process_alt_operands (int only_alternative) bool constmemok; enum reg_class this_alternative, this_costly_alternative; HARD_REG_SET this_alternative_set, this_costly_alternative_set; + HARD_REG_SET this_alternative_exclude_start_hard_regs; bool this_alternative_match_win, this_alternative_win; bool this_alternative_offmemok; bool scratch_p; @@ -2169,6 +2187,7 @@ process_alt_operands (int only_alternative) pairs and there is no accurate intermediate class. */ CLEAR_HARD_REG_SET (this_alternative_set); CLEAR_HARD_REG_SET (this_costly_alternative_set); + CLEAR_HARD_REG_SET (this_alternative_exclude_start_hard_regs); this_alternative_win = false; this_alternative_match_win = false; this_alternative_offmemok = false; @@ -2393,6 +2412,8 @@ process_alt_operands (int only_alternative) badop = false; this_alternative = curr_alt[m]; this_alternative_set = curr_alt_set[m]; + this_alternative_exclude_start_hard_regs + = curr_alt_exclude_start_hard_regs[m]; winreg = this_alternative != NO_REGS; break; } @@ -2478,6 +2499,8 @@ process_alt_operands (int only_alternative) break; this_alternative = reg_class_subunion[this_alternative][cl]; this_alternative_set |= reg_class_contents[cl]; + this_alternative_exclude_start_hard_regs + |= ira_exclude_class_mode_regs[cl][mode]; if (costly_p) { this_costly_alternative @@ -2489,7 +2512,10 @@ process_alt_operands (int only_alternative) { if (hard_regno[nop] >= 0 && in_hard_reg_set_p (this_alternative_set, - mode, hard_regno[nop])) + mode, hard_regno[nop]) + && !TEST_HARD_REG_BIT + (this_alternative_exclude_start_hard_regs, + hard_regno[nop])) win = true; else if (hard_regno[nop] < 0 && in_class_p (op, this_alternative, NULL)) @@ -3001,6 +3027,8 @@ process_alt_operands (int only_alternative) } curr_alt[nop] = this_alternative; curr_alt_set[nop] = this_alternative_set; + curr_alt_exclude_start_hard_regs[nop] + = this_alternative_exclude_start_hard_regs; curr_alt_win[nop] = this_alternative_win; curr_alt_match_win[nop] = this_alternative_match_win; curr_alt_offmemok[nop] = this_alternative_offmemok; @@ -3200,6 +3228,8 @@ process_alt_operands (int only_alternative) goal_alt_match_win[nop] = curr_alt_match_win[nop]; goal_alt_matches[nop] = curr_alt_matches[nop]; goal_alt[nop] = curr_alt[nop]; + goal_alt_exclude_start_hard_regs[nop] + = curr_alt_exclude_start_hard_regs[nop]; goal_alt_offmemok[nop] = curr_alt_offmemok[nop]; } goal_alt_dont_inherit_ops_num = curr_alt_dont_inherit_ops_num; @@ -3236,8 +3266,8 @@ base_to_reg (struct address_info *ad) lra_assert (ad->disp == ad->disp_term); cl = base_reg_class (ad->mode, ad->as, ad->base_outer_code, get_index_code (ad)); - new_reg = lra_create_new_reg (GET_MODE (*ad->base), NULL_RTX, - cl, "base"); + new_reg = lra_create_new_reg (GET_MODE (*ad->base), NULL_RTX, cl, NULL, + "base"); new_inner = simplify_gen_binary (PLUS, GET_MODE (new_reg), new_reg, ad->disp_term == NULL ? const0_rtx @@ -3265,8 +3295,8 @@ base_plus_disp_to_reg (struct address_info *ad, rtx disp) lra_assert (ad->base == ad->base_term); cl = base_reg_class (ad->mode, ad->as, ad->base_outer_code, get_index_code (ad)); - new_reg = lra_create_new_reg (GET_MODE (*ad->base_term), NULL_RTX, - cl, "base + disp"); + new_reg = lra_create_new_reg (GET_MODE (*ad->base_term), NULL_RTX, cl, NULL, + "base + disp"); lra_emit_add (new_reg, *ad->base_term, disp); return new_reg; } @@ -3279,7 +3309,7 @@ index_part_to_reg (struct address_info *ad) rtx new_reg; new_reg = lra_create_new_reg (GET_MODE (*ad->index), NULL_RTX, - INDEX_REG_CLASS, "index term"); + INDEX_REG_CLASS, NULL, "index term"); expand_mult (GET_MODE (*ad->index), *ad->index_term, GEN_INT (get_index_scale (ad)), new_reg, 1); return new_reg; @@ -3576,7 +3606,7 @@ process_address_1 (int nop, bool check_only_p, SCRATCH, SCRATCH); rtx addr = *ad.inner; - new_reg = lra_create_new_reg (Pmode, NULL_RTX, cl, "addr"); + new_reg = lra_create_new_reg (Pmode, NULL_RTX, cl, NULL, "addr"); if (HAVE_lo_sum) { /* addr => lo_sum (new_base, addr), case (2) above. */ @@ -3639,7 +3669,7 @@ process_address_1 (int nop, bool check_only_p, GET_CODE (*ad.index)); lra_assert (INDEX_REG_CLASS != NO_REGS); - new_reg = lra_create_new_reg (Pmode, NULL_RTX, cl, "disp"); + new_reg = lra_create_new_reg (Pmode, NULL_RTX, cl, NULL, "disp"); lra_emit_move (new_reg, *ad.disp); *ad.inner = simplify_gen_binary (PLUS, GET_MODE (new_reg), new_reg, *ad.index); @@ -3744,7 +3774,7 @@ process_address_1 (int nop, bool check_only_p, SCRATCH, SCRATCH); rtx addr = *ad.inner; - new_reg = lra_create_new_reg (Pmode, NULL_RTX, cl, "addr"); + new_reg = lra_create_new_reg (Pmode, NULL_RTX, cl, NULL, "addr"); /* addr => new_base. */ lra_emit_move (new_reg, addr); *ad.inner = new_reg; @@ -3820,7 +3850,7 @@ emit_inc (enum reg_class new_rclass, rtx in, rtx value, poly_int64 inc_amount) if (! post && REG_P (incloc)) result = incloc; else - result = lra_create_new_reg (GET_MODE (value), value, new_rclass, + result = lra_create_new_reg (GET_MODE (value), value, new_rclass, NULL, "INC/DEC result"); if (real_in != result) @@ -4202,8 +4232,8 @@ curr_insn_transform (bool check_only_p) rld = partial_subreg_p (GET_MODE (src), GET_MODE (dest)) ? src : dest; rld_mode = GET_MODE (rld); sec_mode = targetm.secondary_memory_needed_mode (rld_mode); - new_reg = lra_create_new_reg (sec_mode, NULL_RTX, - NO_REGS, "secondary"); + new_reg = lra_create_new_reg (sec_mode, NULL_RTX, NO_REGS, NULL, + "secondary"); /* If the mode is changed, it should be wider. */ lra_assert (!partial_subreg_p (sec_mode, rld_mode)); if (sec_mode != rld_mode) @@ -4458,7 +4488,8 @@ curr_insn_transform (bool check_only_p) input registers. This is the easiest way to avoid creation of non-existing register conflicts in lra-lives.cc. */ - match_reload (i, goal_alt_matched[i], outputs, goal_alt[i], &before, + match_reload (i, goal_alt_matched[i], outputs, goal_alt[i], + &goal_alt_exclude_start_hard_regs[i], &before, &after, TRUE); } continue; @@ -4488,7 +4519,8 @@ curr_insn_transform (bool check_only_p) new_reg = emit_inc (rclass, *loc, *loc, /* This value does not matter for MODIFY. */ GET_MODE_SIZE (GET_MODE (op))); - else if (get_reload_reg (OP_IN, Pmode, *loc, rclass, FALSE, + else if (get_reload_reg (OP_IN, Pmode, *loc, rclass, + NULL, FALSE, "offsetable address", &new_reg)) { rtx addr = *loc; @@ -4562,6 +4594,7 @@ curr_insn_transform (bool check_only_p) } old = *loc; if (get_reload_reg (type, mode, old, goal_alt[i], + &goal_alt_exclude_start_hard_regs[i], loc != curr_id->operand_loc[i], "", &new_reg) && type != OP_OUT) { @@ -4603,7 +4636,8 @@ curr_insn_transform (bool check_only_p) match_inputs[0] = i; match_inputs[1] = -1; match_reload (goal_alt_matched[i][0], match_inputs, outputs, - goal_alt[i], &before, &after, + goal_alt[i], &goal_alt_exclude_start_hard_regs[i], + &before, &after, curr_static_id->operand_alternative [goal_alt_number * n_operands + goal_alt_matched[i][0]] .earlyclobber); @@ -4617,9 +4651,10 @@ curr_insn_transform (bool check_only_p) && (curr_static_id->operand[goal_alt_matched[i][0]].type == OP_IN)) /* Generate reloads for output and matched inputs. */ - match_reload (i, goal_alt_matched[i], outputs, goal_alt[i], &before, - &after, curr_static_id->operand_alternative - [goal_alt_number * n_operands + i].earlyclobber); + match_reload (i, goal_alt_matched[i], outputs, goal_alt[i], + &goal_alt_exclude_start_hard_regs[i], &before, &after, + curr_static_id->operand_alternative + [goal_alt_number * n_operands + i].earlyclobber); else if (curr_static_id->operand[i].type == OP_IN && (curr_static_id->operand[goal_alt_matched[i][0]].type == OP_IN)) @@ -4629,8 +4664,9 @@ curr_insn_transform (bool check_only_p) for (j = 0; (k = goal_alt_matched[i][j]) >= 0; j++) match_inputs[j + 1] = k; match_inputs[j + 1] = -1; - match_reload (-1, match_inputs, outputs, goal_alt[i], &before, - &after, false); + match_reload (-1, match_inputs, outputs, goal_alt[i], + &goal_alt_exclude_start_hard_regs[i], + &before, &after, false); } else /* We must generate code in any case when function @@ -5535,7 +5571,7 @@ inherit_reload_reg (bool def_p, int original_regno, return false; } new_reg = lra_create_new_reg (GET_MODE (original_reg), original_reg, - rclass, "inheritance"); + rclass, NULL, "inheritance"); start_sequence (); if (def_p) lra_emit_move (original_reg, new_reg); @@ -5824,7 +5860,7 @@ split_reg (bool before_p, int original_regno, rtx_insn *insn, mode = HARD_REGNO_CALLER_SAVE_MODE (hard_regno, hard_regno_nregs (hard_regno, mode), mode); - new_reg = lra_create_new_reg (mode, NULL_RTX, NO_REGS, "save"); + new_reg = lra_create_new_reg (mode, NULL_RTX, NO_REGS, NULL, "save"); } else { @@ -5866,7 +5902,7 @@ split_reg (bool before_p, int original_regno, rtx_insn *insn, } return false; } - new_reg = lra_create_new_reg (mode, original_reg, rclass, "split"); + new_reg = lra_create_new_reg (mode, original_reg, rclass, NULL, "split"); reg_renumber[REGNO (new_reg)] = hard_regno; } int new_regno = REGNO (new_reg); @@ -6152,8 +6188,8 @@ process_invariant_for_inheritance (rtx dst_reg, rtx invariant_rtx) if (lra_dump_file != NULL) fprintf (lra_dump_file, " [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[\n"); - new_reg = lra_create_new_reg (dst_mode, dst_reg, - cl, "invariant inheritance"); + new_reg = lra_create_new_reg (dst_mode, dst_reg, cl, NULL, + "invariant inheritance"); bitmap_set_bit (&lra_inheritance_pseudos, REGNO (new_reg)); bitmap_set_bit (&check_only_regs, REGNO (new_reg)); lra_reg_info[REGNO (new_reg)].restore_rtx = PATTERN (insn); diff --git a/gcc/lra-int.h b/gcc/lra-int.h index 8ad0b4a..04baefe 100644 --- a/gcc/lra-int.h +++ b/gcc/lra-int.h @@ -73,6 +73,9 @@ public: /* The following fields are defined only for pseudos. */ /* Hard registers with which the pseudo conflicts. */ HARD_REG_SET conflict_hard_regs; + /* Pseudo allocno class hard registers which cannot be a start hard register + of the pseudo. */ + HARD_REG_SET exclude_start_hard_regs; /* We assign hard registers to reload pseudos which can occur in few places. So two hard register preferences are enough for them. The following fields define the preferred hard registers. If @@ -292,8 +295,11 @@ extern void lra_push_insn_and_update_insn_regno_info (rtx_insn *); extern rtx_insn *lra_pop_insn (void); extern unsigned int lra_insn_stack_length (void); +extern rtx lra_create_new_reg (machine_mode, rtx, enum reg_class, HARD_REG_SET *, + const char *); extern rtx lra_create_new_reg_with_unique_value (machine_mode, rtx, - enum reg_class, const char *); + enum reg_class, HARD_REG_SET *, + const char *); extern void lra_set_regno_unique_value (int); extern void lra_invalidate_insn_data (rtx_insn *); extern void lra_set_insn_deleted (rtx_insn *); diff --git a/gcc/lra-remat.cc b/gcc/lra-remat.cc index ad3f1a2..5079eb5 100644 --- a/gcc/lra-remat.cc +++ b/gcc/lra-remat.cc @@ -1039,7 +1039,7 @@ update_scratch_ops (rtx_insn *remat_insn) if (! ira_former_scratch_p (regno)) continue; *loc = lra_create_new_reg (GET_MODE (*loc), *loc, - lra_get_allocno_class (regno), + lra_get_allocno_class (regno), NULL, "scratch pseudo copy"); ira_register_new_scratch_op (remat_insn, i, id->icode); } @@ -179,7 +179,9 @@ expand_reg_data (int old) will have unique held value. */ rtx lra_create_new_reg_with_unique_value (machine_mode md_mode, rtx original, - enum reg_class rclass, const char *title) + enum reg_class rclass, + HARD_REG_SET *exclude_start_hard_regs, + const char *title) { machine_mode mode; rtx new_reg; @@ -214,19 +216,23 @@ lra_create_new_reg_with_unique_value (machine_mode md_mode, rtx original, } expand_reg_data (max_reg_num ()); setup_reg_classes (REGNO (new_reg), rclass, NO_REGS, rclass); + if (exclude_start_hard_regs != NULL) + lra_reg_info[REGNO (new_reg)].exclude_start_hard_regs + = *exclude_start_hard_regs; return new_reg; } /* Analogous to the previous function but also inherits value of ORIGINAL. */ rtx -lra_create_new_reg (machine_mode md_mode, rtx original, - enum reg_class rclass, const char *title) +lra_create_new_reg (machine_mode md_mode, rtx original, enum reg_class rclass, + HARD_REG_SET *exclude_start_hard_regs, const char *title) { rtx new_reg; new_reg - = lra_create_new_reg_with_unique_value (md_mode, original, rclass, title); + = lra_create_new_reg_with_unique_value (md_mode, original, rclass, + exclude_start_hard_regs, title); if (original != NULL_RTX && REG_P (original)) lra_assign_reg_val (REGNO (original), REGNO (new_reg)); return new_reg; @@ -1319,6 +1325,7 @@ initialize_lra_reg_info_element (int i) lra_reg_info[i].no_stack_p = false; #endif CLEAR_HARD_REG_SET (lra_reg_info[i].conflict_hard_regs); + CLEAR_HARD_REG_SET (lra_reg_info[i].exclude_start_hard_regs); lra_reg_info[i].preferred_hard_regno1 = -1; lra_reg_info[i].preferred_hard_regno2 = -1; lra_reg_info[i].preferred_hard_regno_profit1 = 0; @@ -2042,7 +2049,8 @@ lra_substitute_pseudo_within_insn (rtx_insn *insn, int old_regno, static rtx get_scratch_reg (rtx original) { - return lra_create_new_reg (GET_MODE (original), original, ALL_REGS, NULL); + return lra_create_new_reg (GET_MODE (original), original, ALL_REGS, + NULL, NULL); } /* Remove all insn scratches in INSN. */ @@ -34,8 +34,6 @@ lra_get_allocno_class (int regno) return reg_allocno_class (regno); } -extern rtx lra_create_new_reg (machine_mode, rtx, enum reg_class, - const char *); extern rtx lra_eliminate_regs (rtx, machine_mode, rtx); extern void lra (FILE *); extern void lra_init_once (void); diff --git a/gcc/opt-functions.awk b/gcc/opt-functions.awk index 198f18c..5b0bc66 100644 --- a/gcc/opt-functions.awk +++ b/gcc/opt-functions.awk @@ -297,7 +297,12 @@ function var_set(flags) } if (flag_set_p("Enum.*", flags)) { en = opt_args("Enum", flags); - return enum_index[en] ", CLVC_ENUM, 0" + if (flag_set_p("EnumSet", flags)) + return enum_index[en] ", CLVC_ENUM, CLEV_SET" + else if (flag_set_p("EnumBitSet", flags)) + return enum_index[en] ", CLVC_ENUM, CLEV_BITSET" + else + return enum_index[en] ", CLVC_ENUM, CLEV_NORMAL" } if (var_type(flags) == "const char *") return "0, CLVC_STRING, 0" diff --git a/gcc/opt-read.awk b/gcc/opt-read.awk index 6ae4db9..ce3617c 100644 --- a/gcc/opt-read.awk +++ b/gcc/opt-read.awk @@ -97,10 +97,14 @@ BEGIN { enum_name = opt_args_non_empty("Enum", props) string = opt_args_non_empty("String", props) value = opt_args_non_empty("Value", props) + set = opt_args("Set", props) val_flags = "0" val_flags = val_flags \ test_flag("Canonical", props, "| CL_ENUM_CANONICAL") \ test_flag("DriverOnly", props, "| CL_ENUM_DRIVER_ONLY") + if (set != "") + val_flags = val_flags "| ((" set \ + ") << CL_ENUM_SET_SHIFT)" enum_data[enum_name] = enum_data[enum_name] \ " { " quote string quote ", " value ", " val_flags \ " },\n" diff --git a/gcc/optabs.cc b/gcc/optabs.cc index 2486e14..3d8fa3a 100644 --- a/gcc/optabs.cc +++ b/gcc/optabs.cc @@ -4398,12 +4398,14 @@ prepare_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size, /* If we are optimizing, force expensive constants into a register. */ if (CONSTANT_P (x) && optimize && (rtx_cost (x, mode, COMPARE, 0, optimize_insn_for_speed_p ()) - > COSTS_N_INSNS (1))) + > COSTS_N_INSNS (1)) + && can_create_pseudo_p ()) x = force_reg (mode, x); if (CONSTANT_P (y) && optimize && (rtx_cost (y, mode, COMPARE, 1, optimize_insn_for_speed_p ()) - > COSTS_N_INSNS (1))) + > COSTS_N_INSNS (1)) + && can_create_pseudo_p ()) y = force_reg (mode, y); /* Don't let both operands fail to indicate the mode. */ @@ -4472,6 +4474,8 @@ prepare_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size, compare and branch in different basic blocks. */ if (cfun->can_throw_non_call_exceptions) { + if (!can_create_pseudo_p () && (may_trap_p (x) || may_trap_p (y))) + goto fail; if (may_trap_p (x)) x = copy_to_reg (x); if (may_trap_p (y)) diff --git a/gcc/optc-gen.awk b/gcc/optc-gen.awk index 8a66126..5f7946c 100644 --- a/gcc/optc-gen.awk +++ b/gcc/optc-gen.awk @@ -348,6 +348,8 @@ for (i = 0; i < n_opts; i++) { alias_data = "NULL, NULL, N_OPTS" if (flag_set_p("Enum.*", flags[i])) { if (!flag_set_p("RejectNegative", flags[i]) \ + && !flag_set_p("EnumSet", flags[i]) \ + && !flag_set_p("EnumBitSet", flags[i]) \ && opts[i] ~ "^[Wfgm]") print "#error Enum allowing negative form" } diff --git a/gcc/opts-common.cc b/gcc/opts-common.cc index 37d2e5f..1663be1 100644 --- a/gcc/opts-common.cc +++ b/gcc/opts-common.cc @@ -289,26 +289,29 @@ enum_arg_ok_for_language (const struct cl_enum_arg *enum_arg, return (lang_mask & CL_DRIVER) || !(enum_arg->flags & CL_ENUM_DRIVER_ONLY); } -/* Look up ARG in ENUM_ARGS for language LANG_MASK, returning true and - storing the value in *VALUE if found, and returning false without +/* Look up ARG in ENUM_ARGS for language LANG_MASK, returning the cl_enum_arg + index and storing the value in *VALUE if found, and returning -1 without modifying *VALUE if not found. */ -static bool +static int enum_arg_to_value (const struct cl_enum_arg *enum_args, - const char *arg, HOST_WIDE_INT *value, + const char *arg, size_t len, HOST_WIDE_INT *value, unsigned int lang_mask) { unsigned int i; for (i = 0; enum_args[i].arg != NULL; i++) - if (strcmp (arg, enum_args[i].arg) == 0 + if ((len + ? (strncmp (arg, enum_args[i].arg, len) == 0 + && enum_args[i].arg[len] == '\0') + : strcmp (arg, enum_args[i].arg) == 0) && enum_arg_ok_for_language (&enum_args[i], lang_mask)) { *value = enum_args[i].value; - return true; + return i; } - return false; + return -1; } /* Look up ARG in the enum used by option OPT_INDEX for language @@ -324,8 +327,8 @@ opt_enum_arg_to_value (size_t opt_index, const char *arg, gcc_assert (option->var_type == CLVC_ENUM); HOST_WIDE_INT wideval; - if (enum_arg_to_value (cl_enums[option->var_enum].values, arg, - &wideval, lang_mask)) + if (enum_arg_to_value (cl_enums[option->var_enum].values, arg, 0, + &wideval, lang_mask) >= 0) { *value = wideval; return true; @@ -534,7 +537,7 @@ decode_cmdline_option (const char *const *argv, unsigned int lang_mask, { size_t opt_index; const char *arg = 0; - HOST_WIDE_INT value = 1; + HOST_WIDE_INT value = 1, mask = 0; unsigned int result = 1, i, extra_args, separate_args = 0; int adjust_len = 0; size_t total_len; @@ -808,8 +811,67 @@ decode_cmdline_option (const char *const *argv, unsigned int lang_mask, { const struct cl_enum *e = &cl_enums[option->var_enum]; - gcc_assert (value == 1); - if (enum_arg_to_value (e->values, arg, &value, lang_mask)) + gcc_assert (option->var_value != CLEV_NORMAL || value == 1); + if (option->var_value != CLEV_NORMAL) + { + const char *p = arg; + HOST_WIDE_INT sum_value = 0; + unsigned HOST_WIDE_INT used_sets = 0; + do + { + const char *q = strchr (p, ','); + HOST_WIDE_INT this_value = 0; + if (q && q == p) + { + errors |= CL_ERR_ENUM_SET_ARG; + break; + } + int idx = enum_arg_to_value (e->values, p, q ? q - p : 0, + &this_value, lang_mask); + if (idx < 0) + { + errors |= CL_ERR_ENUM_SET_ARG; + break; + } + + HOST_WIDE_INT this_mask = 0; + if (option->var_value == CLEV_SET) + { + unsigned set = e->values[idx].flags >> CL_ENUM_SET_SHIFT; + gcc_checking_assert (set >= 1 + && set <= HOST_BITS_PER_WIDE_INT); + if ((used_sets & (HOST_WIDE_INT_1U << (set - 1))) != 0) + { + errors |= CL_ERR_ENUM_SET_ARG; + break; + } + used_sets |= HOST_WIDE_INT_1U << (set - 1); + + for (int i = 0; e->values[i].arg != NULL; i++) + if (set == (e->values[i].flags >> CL_ENUM_SET_SHIFT)) + this_mask |= e->values[i].value; + } + else + { + gcc_assert (option->var_value == CLEV_BITSET + && ((e->values[idx].flags >> CL_ENUM_SET_SHIFT) + == 0)); + this_mask = this_value; + } + + sum_value |= this_value; + mask |= this_mask; + if (q == NULL) + break; + p = q + 1; + } + while (1); + if (value == 1) + value = sum_value; + else + gcc_checking_assert (value == 0); + } + else if (enum_arg_to_value (e->values, arg, 0, &value, lang_mask) >= 0) { const char *carg = NULL; @@ -825,6 +887,7 @@ decode_cmdline_option (const char *const *argv, unsigned int lang_mask, decoded->opt_index = opt_index; decoded->arg = arg; decoded->value = value; + decoded->mask = mask; decoded->errors = errors; decoded->warn_message = warn_message; @@ -958,6 +1021,7 @@ decode_cmdline_options_to_array (unsigned int argc, const char **argv, opt_array[0].canonical_option[2] = NULL; opt_array[0].canonical_option[3] = NULL; opt_array[0].value = 1; + opt_array[0].mask = 0; opt_array[0].errors = 0; num_decoded_options = 1; @@ -1167,13 +1231,14 @@ handle_option (struct gcc_options *opts, size_t opt_index = decoded->opt_index; const char *arg = decoded->arg; HOST_WIDE_INT value = decoded->value; + HOST_WIDE_INT mask = decoded->mask; const struct cl_option *option = &cl_options[opt_index]; void *flag_var = option_flag_var (opt_index, opts); size_t i; if (flag_var) set_option (opts, (generated_p ? NULL : opts_set), - opt_index, value, arg, kind, loc, dc); + opt_index, value, arg, kind, loc, dc, mask); for (i = 0; i < handlers->num_handlers; i++) if (option->flags & handlers->handlers[i].mask) @@ -1222,6 +1287,7 @@ generate_option (size_t opt_index, const char *arg, HOST_WIDE_INT value, decoded->warn_message = NULL; decoded->arg = arg; decoded->value = value; + decoded->mask = 0; decoded->errors = (option_ok_for_language (option, lang_mask) ? 0 : CL_ERR_WRONG_LANG); @@ -1260,6 +1326,7 @@ generate_option_input_file (const char *file, decoded->canonical_option[2] = NULL; decoded->canonical_option[3] = NULL; decoded->value = 1; + decoded->mask = 0; decoded->errors = 0; } @@ -1342,6 +1409,82 @@ cmdline_handle_error (location_t loc, const struct cl_option *option, return true; } + if (errors & CL_ERR_ENUM_SET_ARG) + { + const struct cl_enum *e = &cl_enums[option->var_enum]; + const char *p = arg; + unsigned HOST_WIDE_INT used_sets = 0; + const char *second_opt = NULL; + size_t second_opt_len = 0; + errors = 0; + do + { + const char *q = strchr (p, ','); + HOST_WIDE_INT this_value = 0; + if (q && q == p) + { + arg = ""; + errors = CL_ERR_ENUM_ARG; + break; + } + int idx = enum_arg_to_value (e->values, p, q ? q - p : 0, + &this_value, lang_mask); + if (idx < 0) + { + if (q == NULL) + q = strchr (p, '\0'); + char *narg = XALLOCAVEC (char, (q - p) + 1); + memcpy (narg, p, q - p); + narg[q - p] = '\0'; + arg = narg; + errors = CL_ERR_ENUM_ARG; + break; + } + + if (option->var_value == CLEV_BITSET) + { + if (q == NULL) + break; + p = q + 1; + continue; + } + + unsigned set = e->values[idx].flags >> CL_ENUM_SET_SHIFT; + gcc_checking_assert (set >= 1 && set <= HOST_BITS_PER_WIDE_INT); + if ((used_sets & (HOST_WIDE_INT_1U << (set - 1))) != 0) + { + if (q == NULL) + q = strchr (p, '\0'); + if (second_opt == NULL) + { + used_sets = HOST_WIDE_INT_1U << (set - 1); + second_opt = p; + second_opt_len = q - p; + p = arg; + continue; + } + char *args = XALLOCAVEC (char, (q - p) + 1 + second_opt_len + 1); + memcpy (args, p, q - p); + args[q - p] = '\0'; + memcpy (args + (q - p) + 1, second_opt, second_opt_len); + args[(q - p) + 1 + second_opt_len] = '\0'; + error_at (loc, "invalid argument in option %qs", opt); + if (strcmp (args, args + (q - p) + 1) == 0) + inform (loc, "%qs specified multiple times in the same option", + args); + else + inform (loc, "%qs is mutually exclusive with %qs and cannot be" + " specified together", args, args + (q - p) + 1); + return true; + } + used_sets |= HOST_WIDE_INT_1U << (set - 1); + if (q == NULL) + break; + p = q + 1; + } + while (1); + } + if (errors & CL_ERR_ENUM_ARG) { const struct cl_enum *e = &cl_enums[option->var_enum]; @@ -1441,7 +1584,8 @@ read_cmdline_option (struct gcc_options *opts, void set_option (struct gcc_options *opts, struct gcc_options *opts_set, int opt_index, HOST_WIDE_INT value, const char *arg, int kind, - location_t loc, diagnostic_context *dc) + location_t loc, diagnostic_context *dc, + HOST_WIDE_INT mask /* = 0 */) { const struct cl_option *option = &cl_options[opt_index]; void *flag_var = option_flag_var (opt_index, opts); @@ -1550,7 +1694,10 @@ set_option (struct gcc_options *opts, struct gcc_options *opts_set, { const struct cl_enum *e = &cl_enums[option->var_enum]; - e->set (flag_var, value); + if (mask) + e->set (flag_var, value | (e->get (flag_var) & ~mask)); + else + e->set (flag_var, value); if (set_flag_var) e->set (set_flag_var, 1); } @@ -1767,7 +1914,8 @@ control_warning_option (unsigned int opt_index, int kind, const char *arg, { const struct cl_enum *e = &cl_enums[option->var_enum]; - if (enum_arg_to_value (e->values, arg, &value, lang_mask)) + if (enum_arg_to_value (e->values, arg, 0, &value, + lang_mask) >= 0) { const char *carg = NULL; diff --git a/gcc/opts-global.cc b/gcc/opts-global.cc index 0a17896..a18c769 100644 --- a/gcc/opts-global.cc +++ b/gcc/opts-global.cc @@ -417,7 +417,8 @@ handle_common_deferred_options (void) #ifdef ENABLE_PLUGIN add_new_plugin (opt->arg); #else - error ("plugin support is disabled; configure with --enable-plugin"); + error ("plugin support is disabled; configure with " + "%<--enable-plugin%>"); #endif break; @@ -425,7 +426,8 @@ handle_common_deferred_options (void) #ifdef ENABLE_PLUGIN parse_plugin_arg_opt (opt->arg); #else - error ("plugin support is disabled; configure with --enable-plugin"); + error ("plugin support is disabled; configure with " + "%<--enable-plugin%>"); #endif break; diff --git a/gcc/opts.cc b/gcc/opts.cc index dfdc4d7..f21c821 100644 --- a/gcc/opts.cc +++ b/gcc/opts.cc @@ -2621,10 +2621,6 @@ common_handle_option (struct gcc_options *opts, &= ~(SANITIZE_UNDEFINED | SANITIZE_UNDEFINED_NONDEFAULT); break; - case OPT_fsanitize_coverage_: - opts->x_flag_sanitize_coverage = value; - break; - case OPT_O: case OPT_Os: case OPT_Ofast: @@ -3709,12 +3705,67 @@ test_get_option_html_page () #endif } +/* Verify EnumSet and EnumBitSet requirements. */ + +static void +test_enum_sets () +{ + for (unsigned i = 0; i < cl_options_count; ++i) + if (cl_options[i].var_type == CLVC_ENUM + && cl_options[i].var_value != CLEV_NORMAL) + { + const struct cl_enum *e = &cl_enums[cl_options[i].var_enum]; + unsigned HOST_WIDE_INT used_sets = 0; + unsigned HOST_WIDE_INT mask = 0; + unsigned highest_set = 0; + for (unsigned j = 0; e->values[j].arg; ++j) + { + unsigned set = e->values[j].flags >> CL_ENUM_SET_SHIFT; + if (cl_options[i].var_value == CLEV_BITSET) + { + /* For EnumBitSet Set shouldn't be used and Value should + be a power of two. */ + ASSERT_TRUE (set == 0); + ASSERT_TRUE (pow2p_hwi (e->values[j].value)); + continue; + } + /* Test that enumerators referenced in EnumSet have all + Set(n) on them within the valid range. */ + ASSERT_TRUE (set >= 1 && set <= HOST_BITS_PER_WIDE_INT); + highest_set = MAX (set, highest_set); + used_sets |= HOST_WIDE_INT_1U << (set - 1); + } + if (cl_options[i].var_value == CLEV_BITSET) + continue; + /* If there is just one set, no point to using EnumSet. */ + ASSERT_TRUE (highest_set >= 2); + /* Test that there are no gaps in between the sets. */ + if (highest_set == HOST_BITS_PER_WIDE_INT) + ASSERT_TRUE (used_sets == HOST_WIDE_INT_M1U); + else + ASSERT_TRUE (used_sets == (HOST_WIDE_INT_1U << highest_set) - 1); + for (unsigned int j = 1; j <= highest_set; ++j) + { + unsigned HOST_WIDE_INT this_mask = 0; + for (unsigned k = 0; e->values[k].arg; ++k) + { + unsigned set = e->values[j].flags >> CL_ENUM_SET_SHIFT; + if (set == j) + this_mask |= e->values[j].value; + } + ASSERT_TRUE ((mask & this_mask) == 0); + mask |= this_mask; + } + } +} + /* Run all of the selftests within this file. */ void opts_cc_tests () { test_get_option_html_page (); + test_enum_sets (); } } // namespace selftest @@ -52,6 +52,18 @@ enum cl_var_type { CLVC_DEFER }; +/* Values for var_value member of CLVC_ENUM. */ +enum cl_enum_var_value { + /* Enum without EnumSet or EnumBitSet. */ + CLEV_NORMAL, + + /* EnumSet. */ + CLEV_SET, + + /* EnumBitSet. */ + CLEV_BITSET +}; + struct cl_option { /* Text of the option, including initial '-'. */ @@ -170,6 +182,7 @@ extern const unsigned int cl_lang_count; /* Flags for an enumerated option argument. */ #define CL_ENUM_CANONICAL (1 << 0) /* Canonical for this value. */ #define CL_ENUM_DRIVER_ONLY (1 << 1) /* Only accepted in the driver. */ +#define CL_ENUM_SET_SHIFT 2 /* Shift for enum set. */ /* Structure describing an enumerated option argument. */ @@ -226,6 +239,7 @@ extern const unsigned int cl_enums_count; #define CL_ERR_NEGATIVE (1 << 6) /* Negative form of option not permitted (together with OPT_SPECIAL_unknown). */ +#define CL_ERR_ENUM_SET_ARG (1 << 7) /* Bad argument of enumerated set. */ /* Structure describing the result of decoding an option. */ @@ -260,9 +274,14 @@ struct cl_decoded_option /* For a boolean option, 1 for the true case and 0 for the "no-" case. For an unsigned integer option, the value of the - argument. 1 in all other cases. */ + argument. For enum the value of the enumerator corresponding + to argument string. 1 in all other cases. */ HOST_WIDE_INT value; + /* For EnumSet the value mask. Variable should be changed to + value | (prev_value & ~mask). */ + HOST_WIDE_INT mask; + /* Any flags describing errors detected in this option. */ int errors; }; @@ -374,7 +393,8 @@ extern bool get_option_state (struct gcc_options *, int, extern void set_option (struct gcc_options *opts, struct gcc_options *opts_set, int opt_index, HOST_WIDE_INT value, const char *arg, - int kind, location_t loc, diagnostic_context *dc); + int kind, location_t loc, diagnostic_context *dc, + HOST_WIDE_INT = 0); extern void *option_flag_var (int opt_index, struct gcc_options *opts); bool handle_generated_option (struct gcc_options *opts, struct gcc_options *opts_set, diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a28ed32..6d22984 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,224 @@ +2022-01-23 Will Wray <wjwray@gmail.com> + + PR c++/55227 + * g++.dg/cpp2a/desig21.C: New test. + +2022-01-23 Andrew Pinski <apinski@marvell.com> + + PR target/64821 + * gcc.target/aarch64/vsqrt-1.c: New test. + * gcc.target/aarch64/vsqrt-2.c: New test. + +2022-01-23 Jason Merrill <jason@redhat.com> + + PR c++/104182 + * g++.dg/cpp0x/initlist127.C: New test. + +2022-01-23 Jason Merrill <jason@redhat.com> + + PR c++/101072 + * g++.dg/cpp0x/constexpr-empty14a.C: New test. + +2022-01-22 David Malcolm <dmalcolm@redhat.com> + + PR analyzer/104150 + * gcc.dg/analyzer/pr104089.c: Add "dg-add-options float16" + and "dg-require-effective-target float16" directives. + +2022-01-22 David Malcolm <dmalcolm@redhat.com> + + PR analyzer/104159 + * gcc.dg/analyzer/torture/pr104159.c: New test. + +2022-01-22 Harald Anlauf <anlauf@gmx.de> + + PR fortran/104127 + * gfortran.dg/transfer_simplify_11.f90: Fix logic. + * gfortran.dg/transfer_simplify_13.f90: New test. + +2022-01-22 Michael Meissner <meissner@the-meissners.org> + + PR testsuite/103763 + * gcc.target/powerpc/fold-vec-splat-floatdouble.c: Fix insn regex + on power10. + +2022-01-21 Jakub Jelinek <jakub@redhat.com> + + PR c++/104148 + * c-c++-common/Wformat-pr104148.c: New test. + +2022-01-21 Jason Merrill <jason@redhat.com> + + * g++.dg/template/explicit-args6.C: Add expected message. + +2022-01-21 Jason Merrill <jason@redhat.com> + + PR c++/104084 + PR c++/20040 + * g++.dg/init/new50.C: New test. + +2022-01-21 Bill Schmidt <wschmidt@linux.ibm.com> + + * gcc.target/powerpc/builtins-4.c: Add two test variants. Adjust + assembler counts. + +2022-01-21 Roger Sayle <roger@nextmovesoftware.com> + + PR middle-end/104140 + * gcc.target/riscv/pr104140.c: New test case. + +2022-01-21 Vladimir N. Makarov <vmakarov@redhat.com> + + PR target/103676 + * g++.target/arm/pr103676.C: New. + +2022-01-21 Marek Polacek <polacek@redhat.com> + + PR c++/101715 + * g++.dg/cpp0x/noexcept72.C: New test. + * g++.dg/cpp0x/noexcept73.C: New test. + +2022-01-21 Jason Merrill <jason@redhat.com> + + PR c++/104139 + PR c++/103681 + * g++.dg/abi/no_unique_address2.C: Adjust to detect this on x86-64. + +2022-01-21 Richard Biener <rguenther@suse.de> + + PR sanitizer/99673 + * gcc.dg/asan/pr99673.c: New testcase. + +2022-01-21 Ard Biesheuvel <ardb@kernel.org> + + * gcc.target/arm/stack-protector-7.c: New test. + * gcc.target/arm/stack-protector-8.c: New test. + +2022-01-21 Richard Earnshaw <rearnsha@arm.com> + + * gcc.target/aarch64/spellcheck_1.c: Adjust tests for new output. + * gcc.target/aarch64/spellcheck_2.c: Likewise. + * gcc.target/aarch64/spellcheck_3.c: Likewise. + * gcc.target/aarch64/spellcheck_7.c: Likewise. + +2022-01-21 Richard Biener <rguenther@suse.de> + + PR tree-optimization/104156 + * gcc.dg/loop-unswitch-6.c: New testcase. + +2022-01-21 Richard Biener <rguenther@suse.de> + + PR tree-optimization/104152 + * gcc.dg/vect/pr104152.c: New testcase. + +2022-01-21 Aldy Hernandez <aldyh@redhat.com> + + * gcc.dg/pr103721-2.c: New test. + * gcc.dg/pr103721.c: New test. + +2022-01-21 Jakub Jelinek <jakub@redhat.com> + + PR rtl-optimization/102478 + * gcc.dg/pr102478.c: New test. + +2022-01-21 Jeff Law <jeffreyalaw@gmail.com> + + * gcc.target/mips/fix-r4000-2.c: Update expected output. + * gcc.target/mips/fix-r4000-3.c: Update expected output. Add + -fexpensive-optimizations for consistency in output. + * gcc.target/mips/fix-r4000-7.c: Update expected output. + * gcc.target/mips/fix-r4000-8.c: Update expected output. + +2022-01-20 David Malcolm <dmalcolm@redhat.com> + + PR analyzer/94362 + * gcc.dg/analyzer/pr94362-1.c: New test. + * gcc.dg/analyzer/pr94362-2.c: New test. + +2022-01-20 David Malcolm <dmalcolm@redhat.com> + + PR analyzer/103685 + * gcc.dg/analyzer/torture/pr103685.c: New test. + +2022-01-20 Sandra Loosemore <sandra@codesourcery.com> + + PR fortran/103695 + PR fortran/102621 + * gfortran.dg/gomp/affinity-clause-3.f90: Adjust pattern. + * gfortran.dg/gomp/pr102621.f90: New. + * gfortran.dg/gomp/pr103695.f90: New. + +2022-01-20 Jason Merrill <jason@redhat.com> + + PR c++/101405 + * g++.dg/cpp2a/desig20.C: New test. + +2022-01-20 Marek Polacek <polacek@redhat.com> + + PR c++/102338 + * g++.dg/cpp1y/noexcept2.C: New test. + +2022-01-20 Patrick Palka <ppalka@redhat.com> + + PR c++/103631 + * g++.dg/cpp2a/nontype-class51.C: New test. + +2022-01-20 Richard Biener <rguenther@suse.de> + + PR middle-end/100786 + * gcc.dg/torture/pr100786.c: New testcase. + +2022-01-20 Richard Earnshaw <rearnsha@arm.com> + + PR target/102517 + * gcc.target/aarch64/cpymem-q-reg_1.c: Allow ld1 and st1 for the + memcpy expansion. + +2022-01-20 Patrick Palka <ppalka@redhat.com> + + PR c++/91911 + PR c++/103672 + * g++.dg/cpp1z/class-deduction101.C: New test. + * g++.dg/cpp1z/class-deduction101a.C: New test. + * g++.dg/cpp1z/class-deduction101b.C: New test. + * g++.dg/cpp1z/class-deduction102.C: New test. + * g++.dg/cpp1z/class-deduction102a.C: New test. + * g++.dg/cpp1z/class-deduction102b.C: New test. + * g++.dg/cpp1z/class-deduction103.C: New test. + +2022-01-20 Patrick Palka <ppalka@redhat.com> + + * g++.dg/other/pr88187.C: Adjust expected C++17 diagnostic. + +2022-01-20 Richard Earnshaw <rearnsha@arm.com> + + * gcc.target/arm/crypto-vaese-erratum1.c: New test. + +2022-01-20 Jakub Jelinek <jakub@redhat.com> + + PR debug/103874 + * gcc.dg/debug/dwarf2/pr103874.c: New test. + +2022-01-20 Jakub Jelinek <jakub@redhat.com> + + * g++.dg/opt/pr47639.C: Add -Wno-psabi to dg-options. + +2022-01-20 liuhongt <hongtao.liu@intel.com> + + * gcc.target/i386/mask-pack-prefer128.c: New test. + * gcc.target/i386/mask-pack-prefer256.c: New test. + * gcc.target/i386/pr103771.c: New test. + +2022-01-20 Jason Merrill <jason@redhat.com> + + PR c++/102300 + * g++.dg/parse/no-typename1.C: Remove expected error. + * g++.dg/template/nested7.C: New test. + +2022-01-20 David Edelsohn <dje.gcc@gmail.com> + + * gcc.target/powerpc/sldoi_to_mov.c: Require VSX. + 2022-01-19 Robin Dapp <rdapp@linux.ibm.com> * gcc.dg/ifcvt-4.c: Remove s390-specific check. diff --git a/gcc/testsuite/c-c++-common/Wformat-pr104148.c b/gcc/testsuite/c-c++-common/Wformat-pr104148.c new file mode 100644 index 0000000..6786463 --- /dev/null +++ b/gcc/testsuite/c-c++-common/Wformat-pr104148.c @@ -0,0 +1,33 @@ +/* PR c++/104148 */ +/* { dg-do compile } */ +/* { dg-options "-Wformat" } */ + +char *foo (const char *) __attribute__((format_arg(1))); +void bar (const char *, ...) __attribute__((format(printf, 1, 2))); + +void +baz (int x) +{ + bar ("%ld", x); /* { dg-warning "format '%ld' expects argument of type 'long int', but argument 2 has type 'int'" } */ + bar (x ? "%ld" : "%ld", x); /* { dg-warning "format '%ld' expects argument of type 'long int', but argument 2 has type 'int'" } */ + bar (x ? "%ld" : "%lld", x); /* { dg-warning "format '%ld' expects argument of type 'long int', but argument 2 has type 'int'" } */ + /* { dg-warning "format '%lld' expects argument of type 'long long int', but argument 2 has type 'int'" "" { target *-*-* } .-1 } */ + bar (foo ("%ld"), x); /* { dg-warning "format '%ld' expects argument of type 'long int', but argument 2 has type 'int'" } */ + bar (x ? foo ("%ld") : "%ld", x); /* { dg-warning "format '%ld' expects argument of type 'long int', but argument 2 has type 'int'" } */ + bar (x ? foo ("%ld") : "%lld", x); /* { dg-warning "format '%ld' expects argument of type 'long int', but argument 2 has type 'int'" } */ + /* { dg-warning "format '%lld' expects argument of type 'long long int', but argument 2 has type 'int'" "" { target *-*-* } .-1 } */ + bar (foo (x ? "%ld" : "%ld"), x); /* { dg-warning "format '%ld' expects argument of type 'long int', but argument 2 has type 'int'" } */ + bar (foo (x ? "%ld" : "%lld"), x); /* { dg-warning "format '%ld' expects argument of type 'long int', but argument 2 has type 'int'" } */ + /* { dg-warning "format '%lld' expects argument of type 'long long int', but argument 2 has type 'int'" "" { target *-*-* } .-1 } */ + bar (("%ld"), x); /* { dg-warning "format '%ld' expects argument of type 'long int', but argument 2 has type 'int'" } */ + bar ((x ? "%ld" : "%ld"), x); /* { dg-warning "format '%ld' expects argument of type 'long int', but argument 2 has type 'int'" } */ + bar ((x ? "%ld" : "%lld"), x); /* { dg-warning "format '%ld' expects argument of type 'long int', but argument 2 has type 'int'" } */ + /* { dg-warning "format '%lld' expects argument of type 'long long int', but argument 2 has type 'int'" "" { target *-*-* } .-1 } */ + bar ((foo ("%ld")), x); /* { dg-warning "format '%ld' expects argument of type 'long int', but argument 2 has type 'int'" } */ + bar ((x ? foo ("%ld") : "%ld"), x); /* { dg-warning "format '%ld' expects argument of type 'long int', but argument 2 has type 'int'" } */ + bar ((x ? foo ("%ld") : "%lld"), x); /* { dg-warning "format '%ld' expects argument of type 'long int', but argument 2 has type 'int'" } */ + /* { dg-warning "format '%lld' expects argument of type 'long long int', but argument 2 has type 'int'" "" { target *-*-* } .-1 } */ + bar ((foo (x ? "%ld" : "%ld")), x); /* { dg-warning "format '%ld' expects argument of type 'long int', but argument 2 has type 'int'" } */ + bar ((foo (x ? "%ld" : "%lld")), x); /* { dg-warning "format '%ld' expects argument of type 'long int', but argument 2 has type 'int'" } */ + /* { dg-warning "format '%lld' expects argument of type 'long long int', but argument 2 has type 'int'" "" { target *-*-* } .-1 } */ +} diff --git a/gcc/testsuite/g++.dg/abi/no_unique_address2.C b/gcc/testsuite/g++.dg/abi/no_unique_address2.C index bef6d5b..3bb3f76 100644 --- a/gcc/testsuite/g++.dg/abi/no_unique_address2.C +++ b/gcc/testsuite/g++.dg/abi/no_unique_address2.C @@ -41,3 +41,30 @@ struct B4 #define SA(X) static_assert ((X), #X) SA (sizeof (B2) == sizeof (B1)); SA (sizeof (B3) == sizeof (B4)); + +namespace N2 +{ + // C as big as _vptr to test PR c++/104139 + struct C + { + long c; + }; + + struct D: virtual C + { + virtual void f(); + }; + + struct B3: D + { + char c2; + }; + + struct B4 + { + D d [[no_unique_address]]; + char c2; + }; + + SA (sizeof (B3) == sizeof (B4)); +} diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-empty14a.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-empty14a.C new file mode 100644 index 0000000..df34cfc --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-empty14a.C @@ -0,0 +1,11 @@ +// PR c++/101072 +// { dg-do compile { target c++11 } } +// { dg-additional-options -fno-elide-constructors } + +struct S {}; + +template <class T> void +foo (S s) +{ + constexpr S x = s; +} diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist127.C b/gcc/testsuite/g++.dg/cpp0x/initlist127.C new file mode 100644 index 0000000..ebe5924 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/initlist127.C @@ -0,0 +1,39 @@ +// PR c++/104182 +// { dg-do run { target c++11 } } + +#include <initializer_list> + +int b; + +struct stringy { + const char *p; + stringy(const char *p): p(p) { ++b; } + const char& operator[](int i) const { return p[i]; } + ~stringy() { --b; } +}; + +struct S +{ + int A; + stringy B; +}; + +struct veccy { + S s; + veccy (const std::initializer_list<S> &l): s(*l.begin()) {} + const S& operator[](int i) const { return s; } +}; + +struct V +{ + veccy v; +}; + +static const V v{ { { { 237, "2" } } } }; + +int main() +{ + if (v.v[0].A != 237 || v.v[0].B[0] != '2') + __builtin_abort(); + return 0; +} diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept72.C b/gcc/testsuite/g++.dg/cpp0x/noexcept72.C new file mode 100644 index 0000000..f1455b3 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/noexcept72.C @@ -0,0 +1,21 @@ +// PR c++/101715 +// { dg-do compile { target c++11 } } + +template <typename T> struct S { + S<T> bar() noexcept(T::value); // #1 + S<T> foo() noexcept(T::value); // #2 +}; + +template <typename T> S<T> S<T>::foo() noexcept(T::value) {} // #3 + +template <typename T> struct S2 { + S2<T> bar1() noexcept(T::value); + S2<T> bar2() noexcept(T::value); + S2<T> bar3() noexcept(T::value); + S2<T> bar4() noexcept(T::value); + S2<T> bar5() noexcept(T::value); + S2<T> baz() noexcept(T::value2); + S2<T> foo() noexcept(T::value); +}; + +template <typename T> S2<T> S2<T>::foo() noexcept(T::value) {} diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept73.C b/gcc/testsuite/g++.dg/cpp0x/noexcept73.C new file mode 100644 index 0000000..24524f3 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/noexcept73.C @@ -0,0 +1,13 @@ +// PR c++/101715 +// { dg-do compile { target c++11 } } + +template <typename T> struct S { }; + +template<typename T> +struct A +{ + A& foo(A&&) noexcept((S<T>::value)); + A& assign(A&&) noexcept((S<T>::value)); +}; +template<typename T> +A<T>& A<T>::foo(A&&) noexcept((S<T>::value)) {} diff --git a/gcc/testsuite/g++.dg/cpp1y/noexcept2.C b/gcc/testsuite/g++.dg/cpp1y/noexcept2.C new file mode 100644 index 0000000..38dd05c --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/noexcept2.C @@ -0,0 +1,20 @@ +// PR c++/102338 +// { dg-do compile { target c++14 } } + +struct S { + template<typename T> + static auto f(T&& t) noexcept { + return true; + } + + template<typename T, typename... Ts> + static auto f(T&& t, Ts&& ... ts) noexcept(noexcept(f(ts...))) { + return f(ts...); + } + +}; + +int main() { + S::f(true, 0, 5u); + return 0; +} diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction101.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction101.C new file mode 100644 index 0000000..379eb96 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction101.C @@ -0,0 +1,17 @@ +// PR c++/91911 +// { dg-do compile { target c++17 } } + +template<class T> +struct span { + using value_type = T; + span(T); +}; + +template<class T> +using SpanType = decltype(span{T()}); + +template<class T> +using ConstSpanType = span<const typename SpanType<T>::value_type>; + +using type = ConstSpanType<int>; +using type = span<const int>; diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction101a.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction101a.C new file mode 100644 index 0000000..97869e6 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction101a.C @@ -0,0 +1,22 @@ +// PR c++/91911 +// { dg-do compile { target c++17 } } +// A variant of class-deduction101.C where SpanType has more levels than +// ConstSpanType. + +template<class T> +struct span { + using value_type = T; + span(T); +}; + +template<class> +struct A { + template<class T> + using SpanType = decltype(span{T()}); +}; + +template<class T> +using ConstSpanType = span<const typename A<int>::SpanType<const T>::value_type>; + +using type = ConstSpanType<int>; +using type = span<const int>; diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction101b.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction101b.C new file mode 100644 index 0000000..a823c9c --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction101b.C @@ -0,0 +1,22 @@ +// PR c++/91911 +// { dg-do compile { target c++17 } } +// A variant of class-deduction101.C where SpanType has fewer levels than +// ConstSpanType. + +template<class T> +struct span { + using value_type = T; + span(T); +}; + +template<class T> +using SpanType = decltype(span{T()}); + +template<class> +struct B { + template<class T> + using ConstSpanType = span<const typename SpanType<T>::value_type>; +}; + +using type = B<int>::ConstSpanType<int>; +using type = span<const int>; diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction102.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction102.C new file mode 100644 index 0000000..2050478 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction102.C @@ -0,0 +1,25 @@ +// PR c++/98077 +// { dg-do compile { target c++17 } } + +template<class R> +struct function { + template<class T> function(T); + using type = R; +}; + +template<class T> function(T) -> function<decltype(T()())>; + +template<class T> +struct CallableTrait; + +template<class R> +struct CallableTrait<function<R>> { using ReturnType = R; }; + +template<class F> +using CallableTraitT = CallableTrait<decltype(function{F()})>; + +template<class F> +using ReturnType = typename CallableTraitT<F>::ReturnType; + +using type = ReturnType<int(*)()>; +using type = int; diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction102a.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction102a.C new file mode 100644 index 0000000..7a4b684 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction102a.C @@ -0,0 +1,27 @@ +// PR c++/98077 +// { dg-do compile { target c++17 } } +// A variant of class-deduction102.C where the template placeholder is a template +// template parameter. + +template<class R> +struct function { + template<class T> function(T); + using type = R; +}; + +template<class T> function(T) -> function<decltype(T()())>; + +template<class T> +struct CallableTrait; + +template<class R> +struct CallableTrait<function<R>> { using ReturnType = R; }; + +template<class F, template<class> class Tmpl> +using CallableTraitT = CallableTrait<decltype(Tmpl{F()})>; + +template<class F, template<class> class Tmpl> +using ReturnType = typename CallableTraitT<F, Tmpl>::ReturnType; + +using type = ReturnType<int(*)(), function>; +using type = int; diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction102b.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction102b.C new file mode 100644 index 0000000..64e3f8c --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction102b.C @@ -0,0 +1,30 @@ +// PR c++/98077 +// { dg-do compile { target c++17 } } +// A variant of class-deduction102.C where the template placeholder is a template +// template parameter and ReturnType has more levels than CallableTraitT. + +template<class R> +struct function { + template<class T> function(T); + using type = R; +}; + +template<class T> function(T) -> function<decltype(T()())>; + +template<class T> +struct CallableTrait; + +template<class R> +struct CallableTrait<function<R>> { using ReturnType = R; }; + +template<class F, template<class> class Tmpl> +using CallableTraitT = CallableTrait<decltype(Tmpl{F()})>; + +template<class> +struct A { + template<class F, template<class> class Tmpl> + using ReturnType = typename CallableTraitT<F, Tmpl>::ReturnType; +}; + +using type = A<int>::ReturnType<int(*)(), function>; +using type = int; diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction103.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction103.C new file mode 100644 index 0000000..a1a3808 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction103.C @@ -0,0 +1,22 @@ +// PR c++/103672 +// { dg-do compile { target c++17 } } + +template<class T> +struct unique { + template<class... Args> + T* operator()(Args&&... args); +}; + +template<template<class...> class T, class... Args> +using deduced_type = decltype(T{Args{}...}); + +template<template<class> class F, template<class...> class T, class... Args> +auto make(Args&&... args) { + return F<deduced_type<T, Args...>>{}(args...); +} + +template<class A, class B> +struct Foo { Foo(A,B); }; + +using type = decltype(make<unique, Foo>(1, 2)); +using type = Foo<int, int>*; diff --git a/gcc/testsuite/g++.dg/cpp2a/desig20.C b/gcc/testsuite/g++.dg/cpp2a/desig20.C new file mode 100644 index 0000000..0ceda7c --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/desig20.C @@ -0,0 +1,20 @@ +// PR c++/101405 +// { dg-do compile { target c++20 } } + +struct A { + int const a = 1; + int const b = 2; +}; + +struct B : A { + using A::a; + using A::b; + int const c = 3; + int const d = 4; +}; + +int main() +{ + [[maybe_unused]] B b = + { .a = 10, .d = 42 }; // { dg-error "not a direct member" } +} diff --git a/gcc/testsuite/g++.dg/cpp2a/desig21.C b/gcc/testsuite/g++.dg/cpp2a/desig21.C new file mode 100644 index 0000000..daadfa5 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/desig21.C @@ -0,0 +1,48 @@ +// PR c++/55227 +// Test designated initializer for char array by string constant + +// { dg-options "" } + +struct C {char a[2];}; + +/* Case a, designated, unbraced, string-literal of the exact same size + as the initialized char array; valid and accepted before and after. */ +C a = {.a="a"}; + +/* Cases b,c,d, designated, braced or mimatched-size, string literal, + previously rejected; "C99 designator 'a' outside aggregate initializer". */ +C b = {.a=""}; +C c = {.a={""}}; +C d = {.a={"a"}}; + +/* Case e, designated char array field and braced, designated array element(s) + (with GNU [N]= extension) valid and accepted before and after. */ +C e = {.a={[0]='a'}}; + +/* Cases f,g,h, braced string literal, 'designated' within inner braces; + invalid, previously accepted as positional with 'designator' ignored. */ +C f = {{[0]="a"}}; // { dg-error "C99 designator .0. outside aggregate initializer" } +C g = {{.a="a"}}; // { dg-error "C99 designator .a. outside aggregate initializer" } +C h = {{.b="a"}}; // { dg-error "C99 designator .b. outside aggregate initializer" } + +char a2[][10] = { [0] = { "aaa" } }; + +struct D { C c; int a[8]; }; + +D x = { .c {.a={"a"}}, .a={1,2,3,4,5,6,7,8} }; + +struct A { union { int a; char c[4]; }; }; + +A non = { .c = "c++" }; + +template <class T> +void t() +{ + C ca[] = { {.a=""}, {.a={""}}, }; + +} + +void u() +{ + return t<void>(); +} diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class51.C b/gcc/testsuite/g++.dg/cpp2a/nontype-class51.C new file mode 100644 index 0000000..1501aa1 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class51.C @@ -0,0 +1,26 @@ +// PR c++/103631 +// { dg-do compile { target c++20 } } + +template<class Target, template<auto> class T> +constexpr bool is_specialize_value_v = false; + +template<template<auto> class T, auto Ts> +constexpr bool is_specialize_value_v<T<Ts>, T> = true; + +template<class Target, template<auto> class T> +concept specialize_value = is_specialize_value_v<Target, T>; + +template<int> struct Test { }; + +template<Test> +struct A { + template<class T> void f(T) requires specialize_value<T, A>; +}; + +int main() { + A<Test<0>{}> a0; + A<Test<1>{}> a1; + a0.f(a0); + a0.f(a1); + a0.f(0); // { dg-error "no match" } +} diff --git a/gcc/testsuite/g++.dg/init/new50.C b/gcc/testsuite/g++.dg/init/new50.C new file mode 100644 index 0000000..981d231 --- /dev/null +++ b/gcc/testsuite/g++.dg/init/new50.C @@ -0,0 +1,9 @@ +// PR c++/104084 + +int nothrow; +struct MaxAlignedAllocable { + void *operator new[](__SIZE_TYPE__, int); + void operator delete[](void *); + long Resize_size; + void Resize() { new (nothrow) MaxAlignedAllocable[Resize_size]; } +}; diff --git a/gcc/testsuite/g++.dg/other/pr88187.C b/gcc/testsuite/g++.dg/other/pr88187.C index 13466d3..7812e3fd 100644 --- a/gcc/testsuite/g++.dg/other/pr88187.C +++ b/gcc/testsuite/g++.dg/other/pr88187.C @@ -4,4 +4,4 @@ template <int> struct A; void f (A ()); // { dg-error "6:variable or field 'f' declared void" "" { target c++14_down } } // { dg-error "missing template arguments before '\\(' token" "" { target c++14_down } .-1 } - // { dg-error "placeholder .A. not permitted in this context" "" { target c++17 } .-2 } + // { dg-error "deduced class type 'A' in function return type" "" { target c++17 } .-2 } diff --git a/gcc/testsuite/g++.dg/template/explicit-args6.C b/gcc/testsuite/g++.dg/template/explicit-args6.C index d853564..311a767 100644 --- a/gcc/testsuite/g++.dg/template/explicit-args6.C +++ b/gcc/testsuite/g++.dg/template/explicit-args6.C @@ -20,6 +20,8 @@ constexpr unsigned frob() { static_assert(N == 1, "user-friendly diagnostic"); // { dg-error "user-friendly" } + // dg-message { "-1 == 1" "" { target *-*-* } .-1 } + // narrowing check, reject negative values return unsigned{N}; // { dg-prune-output "narrowing" } } // { dg-prune-output "flows off the end" } diff --git a/gcc/testsuite/g++.target/arm/pr103676.C b/gcc/testsuite/g++.target/arm/pr103676.C new file mode 100644 index 0000000..1607564 --- /dev/null +++ b/gcc/testsuite/g++.target/arm/pr103676.C @@ -0,0 +1,32 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target arm_thumb1_ok } */ +/* { dg-additional-options "-mcpu=cortex-m7 -mthumb -O2" } */ + +typedef unsigned long long uint64_t; +struct timer { + int active; + uint64_t expire; + void *arg; +}; +int irq_disable(); +void irq_restore(int); +static inline uint64_t h(const uint64_t *p64) +{ + uint64_t tmp; + asm( + "ldrd %Q[r], %R[r], %[p]\n" + : [r]"=lh"(tmp) + : [p]"m"(*p64) + : "memory" + ); + return tmp; +} +uint64_t monotonic; +void timer_callout(timer *tmr, uint64_t nsec, void *arg) +{ + const int s = irq_disable(); + if (tmr->active) + tmr->arg = arg; + tmr->expire = h(&monotonic) + 100000 + (nsec == 1 ? 0 : nsec); + irq_restore(s); +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr104089.c b/gcc/testsuite/gcc.dg/analyzer/pr104089.c index c517704..3bf637e 100644 --- a/gcc/testsuite/gcc.dg/analyzer/pr104089.c +++ b/gcc/testsuite/gcc.dg/analyzer/pr104089.c @@ -1,3 +1,5 @@ +/* { dg-add-options float16 } */ +/* { dg-require-effective-target float16 } */ /* { dg-additional-options "-frounding-math" } */ volatile _Float16 true_min = 5.96046447753906250000000000000000000e-8F16; diff --git a/gcc/testsuite/gcc.dg/analyzer/pr94362-1.c b/gcc/testsuite/gcc.dg/analyzer/pr94362-1.c new file mode 100644 index 0000000..1302ced --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr94362-1.c @@ -0,0 +1,60 @@ +/* { dg-additional-options "-Wno-analyzer-too-complex" } */ +/* TODO: remove the need for -Wno-analyzer-too-complex. */ + +typedef struct evp_pkey_asn1_method_st EVP_PKEY_ASN1_METHOD; +typedef struct engine_st ENGINE; +struct stack_st_EVP_PKEY_ASN1_METHOD; +struct evp_pkey_asn1_method_st { + unsigned long pkey_flags; +}; + +const EVP_PKEY_ASN1_METHOD *ENGINE_pkey_asn1_find_str(ENGINE **pe, + const char *str, int len); +extern int +sk_EVP_PKEY_ASN1_METHOD_num(const struct stack_st_EVP_PKEY_ASN1_METHOD *sk); +extern const EVP_PKEY_ASN1_METHOD * +sk_EVP_PKEY_ASN1_METHOD_value(const struct stack_st_EVP_PKEY_ASN1_METHOD *sk, + int idx); +extern const EVP_PKEY_ASN1_METHOD hmac_asn1_meth; +static const EVP_PKEY_ASN1_METHOD *standard_methods[] = {&hmac_asn1_meth}; +static struct stack_st_EVP_PKEY_ASN1_METHOD *app_methods = ((void *)0); + +int EVP_PKEY_asn1_get_count(void) { + int num = (sizeof(standard_methods) / sizeof((standard_methods)[0])); + if (app_methods) + num += sk_EVP_PKEY_ASN1_METHOD_num(app_methods); + return num; +} + +const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_get0(int idx) { + int num = (sizeof(standard_methods) / sizeof((standard_methods)[0])); + if (idx < 0) + return ((void *)0); + if (idx < num) + return standard_methods[idx]; + idx -= num; + return sk_EVP_PKEY_ASN1_METHOD_value(app_methods, idx); +} + +const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find_str(ENGINE **pe, const char *str, + int len) { + int i; + const EVP_PKEY_ASN1_METHOD *ameth = ((void *)0); + + if (pe) { + ENGINE *e; + ameth = ENGINE_pkey_asn1_find_str(&e, str, len); + if (ameth) { + *pe = e; + return ameth; + } + *pe = ((void *)0); + } + for (i = EVP_PKEY_asn1_get_count(); i-- > 0;) { + ameth = EVP_PKEY_asn1_get0(i); + if (ameth->pkey_flags & 0x1) + continue; + return ameth; + } + return ((void *)0); +} diff --git a/gcc/testsuite/gcc.dg/analyzer/pr94362-2.c b/gcc/testsuite/gcc.dg/analyzer/pr94362-2.c new file mode 100644 index 0000000..301d2ed --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr94362-2.c @@ -0,0 +1,42 @@ +/* Verify that we consider various paths to be impossible, + using functions to thwart early optimizations. */ + +#include "analyzer-decls.h" + +void test_1 (int idx) +{ + if (idx > 0) + if (idx - 1 < 0) + __analyzer_dump_path (); /* { dg-bogus "" } */ +} + +static int called_by_test_1a (int idx) +{ + return idx - 1; +} + +void test_1a (int idx) +{ + if (idx > 0) + if (called_by_test_1a (idx) < 0) + __analyzer_dump_path (); /* { dg-bogus "" } */ +} + +void test_2 (int idx) +{ + if (idx + 1 > 0) + if (idx < 0) + __analyzer_dump_path (); /* { dg-bogus "" } */ +} + +static int called_by_test_2a (int idx) +{ + return idx + 1; +} + +void test_2a (int idx) +{ + if (called_by_test_2a (idx) > 0) + if (idx < 0) + __analyzer_dump_path (); /* { dg-bogus "" } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/torture/pr103685.c b/gcc/testsuite/gcc.dg/analyzer/torture/pr103685.c new file mode 100644 index 0000000..1b22248 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/torture/pr103685.c @@ -0,0 +1,33 @@ +typedef struct ec_key_st EC_KEY; +typedef struct ec_group_st EC_GROUP; +typedef struct R3410_ec { + int nid; + EC_GROUP *group; +} R3410_ec_params; +extern R3410_ec_params R3410_2012_512_paramset[]; + +static R3410_ec_params *gost_nid2params(int nid) { + R3410_ec_params *params; + + params = R3410_2012_512_paramset; + while (params->nid != 0) { + if (params->nid == nid) + return params; + params++; + } + + return ((void *)0); +} + +int fill_GOST_EC_params(EC_KEY *eckey, int nid) { + R3410_ec_params *params = gost_nid2params(nid); + if (!eckey || !params) { + return 0; + } + + if (params->group) { + return 1; + } + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/analyzer/torture/pr104159.c b/gcc/testsuite/gcc.dg/analyzer/torture/pr104159.c new file mode 100644 index 0000000..ad85d08 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/torture/pr104159.c @@ -0,0 +1,18 @@ +/* { dg-additional-options "-Wno-analyzer-use-of-uninitialized-value -Wno-psabi" } */ + +typedef int __attribute__((__vector_size__(4))) T; +typedef unsigned __attribute__((__vector_size__(4))) U; +typedef unsigned __attribute__((__vector_size__(16))) V; +typedef unsigned long __attribute__((__vector_size__(16))) W; + +U u; +T t; + +void +foo(W w) { + U u = __builtin_shufflevector((V)w, u, 0); + t = (T){} + u + u; + foo((W){}); + for (;;) + ; +} diff --git a/gcc/testsuite/gcc.dg/asan/pr99673.c b/gcc/testsuite/gcc.dg/asan/pr99673.c new file mode 100644 index 0000000..05857fd --- /dev/null +++ b/gcc/testsuite/gcc.dg/asan/pr99673.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-Wstringop-overread" } */ + +struct B { + int i; + struct A { + short sa[8]; + } a[2]; +}; + +struct C { + char n, ax[]; +}; + +struct D { int i, j, k; }; + +int f (const short[8]); + +void g (struct C *pc, struct D *pd, int i) +{ + struct B *pb = (void *)pc->ax; + pd->i = pb->i; + + const short *psa = pb->a[i].sa; + if (f (psa)) + return; +} diff --git a/gcc/testsuite/gcc.dg/loop-unswitch-6.c b/gcc/testsuite/gcc.dg/loop-unswitch-6.c new file mode 100644 index 0000000..f70b629 --- /dev/null +++ b/gcc/testsuite/gcc.dg/loop-unswitch-6.c @@ -0,0 +1,32 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -funswitch-loops -g -fcompare-debug -fdump-tree-unswitch-details" } */ + +short a, d; +int b, c; +static int e() { + int f = -2L, g = 9, h = 0; + for (; h < 2; h++) + if (a <= 5) { + g = 0; + if (c && a) + break; + if (c - 1) + goto i; + } + if (b) { + int *j[] = {&f}; + if (d) + for (; f < 9; f++) + if (g) + for (; f; f++) + ; + i: + while (f) { + a--; + break; + } + } +} +int main() { e(); } + +/* { dg-final { scan-tree-dump-times "Guard hoisted" 1 "unswitch" } } */ diff --git a/gcc/testsuite/gcc.dg/pr102087_1.c b/gcc/testsuite/gcc.dg/pr102087_1.c new file mode 100644 index 0000000..ba4efe3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr102087_1.c @@ -0,0 +1,13 @@ +/* PR tree-optimization/102087 */ +/* { dg-do compile } */ +/* { dg-options "-O3 -fprefetch-loop-arrays -w" { target x86_64-*-* powerpc*-*-* } } */ + +char **Gif_ClipImage_gfi_0; +int Gif_ClipImage_gfi_1, Gif_ClipImage_y, Gif_ClipImage_shift; +void Gif_ClipImage() { + Gif_ClipImage_y = Gif_ClipImage_gfi_1 - 1; + for (; Gif_ClipImage_y >= Gif_ClipImage_shift; Gif_ClipImage_y++) + Gif_ClipImage_gfi_0[Gif_ClipImage_shift] = + Gif_ClipImage_gfi_0[Gif_ClipImage_y]; +} + diff --git a/gcc/testsuite/gcc.dg/pr102478.c b/gcc/testsuite/gcc.dg/pr102478.c new file mode 100644 index 0000000..43bc49b --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr102478.c @@ -0,0 +1,29 @@ +/* PR rtl-optimization/102478 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-if-conversion -Wno-div-by-zero" } */ + +unsigned a, b, c; + +void +foo (void) +{ + c |= __builtin_expect (65535 / a, 0) && 0 / 0; + b = 0; +} + +void +bar (void) +{ + if (a <= 65535) + __builtin_trap (); + b = 0; +} + +void +baz (void) +{ + if (a > 65535) + b = 0; + else + __builtin_trap (); +} diff --git a/gcc/testsuite/gcc.dg/pr103721-2.c b/gcc/testsuite/gcc.dg/pr103721-2.c new file mode 100644 index 0000000..aefa1f0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr103721-2.c @@ -0,0 +1,28 @@ +// { dg-do run } +// { dg-options "-O2" } + +extern void abort (); +struct S { int x; } a[10]; +struct S *b; + +int +main () +{ + int i, j = 0; + struct S *q = a; + + for (i = 100; --i > 0; ) + { + struct S *p; + j++; + if (j >= 10) + j = 0; + p = &a[j]; + + if (p == q) + abort (); + __atomic_thread_fence (__ATOMIC_SEQ_CST); + q = p; + } + return 0; +} diff --git a/gcc/testsuite/gcc.dg/pr103721.c b/gcc/testsuite/gcc.dg/pr103721.c new file mode 100644 index 0000000..6ec2e44 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr103721.c @@ -0,0 +1,25 @@ +// { dg-do run } +// { dg-options "-O2" } + +int ipos = 0; +int f (int world) +{ + int searchVolume = world; + int currentVolume = 0; + while (currentVolume != searchVolume && searchVolume) { + currentVolume = searchVolume; + if (ipos != 0) + searchVolume = 0; + else + searchVolume = 1; + } + return (currentVolume); +} +int main() +{ + const int i = f (1111); + __builtin_printf ("%d\n", (int)(i)); + if (i != 1) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/sancov/pr104158-1.c b/gcc/testsuite/gcc.dg/sancov/pr104158-1.c new file mode 100644 index 0000000..2a31879 --- /dev/null +++ b/gcc/testsuite/gcc.dg/sancov/pr104158-1.c @@ -0,0 +1,11 @@ +/* PR sanitizer/104158 */ +/* { dg-do compile } */ +/* { dg-options "-fsanitize-coverage=trace-cmp -fdump-tree-optimized" } */ +/* { dg-final { scan-tree-dump "__sanitizer_cov_trace_cmp" "optimized" } } */ +/* { dg-final { scan-tree-dump-not "__sanitizer_cov_trace_pc" "optimized" } } */ + +int +foo (int a, int b) +{ + return a == b; +} diff --git a/gcc/testsuite/gcc.dg/sancov/pr104158-2.c b/gcc/testsuite/gcc.dg/sancov/pr104158-2.c new file mode 100644 index 0000000..b143504 --- /dev/null +++ b/gcc/testsuite/gcc.dg/sancov/pr104158-2.c @@ -0,0 +1,11 @@ +/* PR sanitizer/104158 */ +/* { dg-do compile } */ +/* { dg-options "-fsanitize-coverage=trace-pc -fdump-tree-optimized" } */ +/* { dg-final { scan-tree-dump-not "__sanitizer_cov_trace_cmp" "optimized" } } */ +/* { dg-final { scan-tree-dump "__sanitizer_cov_trace_pc" "optimized" } } */ + +int +foo (int a, int b) +{ + return a == b; +} diff --git a/gcc/testsuite/gcc.dg/sancov/pr104158-3.c b/gcc/testsuite/gcc.dg/sancov/pr104158-3.c new file mode 100644 index 0000000..e2a1cfb --- /dev/null +++ b/gcc/testsuite/gcc.dg/sancov/pr104158-3.c @@ -0,0 +1,11 @@ +/* PR sanitizer/104158 */ +/* { dg-do compile } */ +/* { dg-options "-fsanitize-coverage=trace-cmp,trace-pc -fdump-tree-optimized" } */ +/* { dg-final { scan-tree-dump "__sanitizer_cov_trace_cmp" "optimized" } } */ +/* { dg-final { scan-tree-dump "__sanitizer_cov_trace_pc" "optimized" } } */ + +int +foo (int a, int b) +{ + return a == b; +} diff --git a/gcc/testsuite/gcc.dg/sancov/pr104158-4.c b/gcc/testsuite/gcc.dg/sancov/pr104158-4.c new file mode 100644 index 0000000..9c2e722 --- /dev/null +++ b/gcc/testsuite/gcc.dg/sancov/pr104158-4.c @@ -0,0 +1,11 @@ +/* PR sanitizer/104158 */ +/* { dg-do compile } */ +/* { dg-options "-fsanitize-coverage=trace-pc,trace-cmp -fdump-tree-optimized" } */ +/* { dg-final { scan-tree-dump "__sanitizer_cov_trace_cmp" "optimized" } } */ +/* { dg-final { scan-tree-dump "__sanitizer_cov_trace_pc" "optimized" } } */ + +int +foo (int a, int b) +{ + return a == b; +} diff --git a/gcc/testsuite/gcc.dg/sancov/pr104158-5.c b/gcc/testsuite/gcc.dg/sancov/pr104158-5.c new file mode 100644 index 0000000..5b130d0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/sancov/pr104158-5.c @@ -0,0 +1,11 @@ +/* PR sanitizer/104158 */ +/* { dg-do compile } */ +/* { dg-options "-fsanitize-coverage=trace-cmp -fsanitize-coverage=trace-pc -fno-sanitize-coverage=trace-cmp -fdump-tree-optimized" } */ +/* { dg-final { scan-tree-dump-not "__sanitizer_cov_trace_cmp" "optimized" } } */ +/* { dg-final { scan-tree-dump "__sanitizer_cov_trace_pc" "optimized" } } */ + +int +foo (int a, int b) +{ + return a == b; +} diff --git a/gcc/testsuite/gcc.dg/sancov/pr104158-6.c b/gcc/testsuite/gcc.dg/sancov/pr104158-6.c new file mode 100644 index 0000000..3eed1d7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/sancov/pr104158-6.c @@ -0,0 +1,11 @@ +/* PR sanitizer/104158 */ +/* { dg-do compile } */ +/* { dg-options "-fsanitize-coverage=trace-cmp -fsanitize-coverage=trace-pc -fno-sanitize-coverage=trace-pc,trace-cmp -fdump-tree-optimized" } */ +/* { dg-final { scan-tree-dump-not "__sanitizer_cov_trace_cmp" "optimized" } } */ +/* { dg-final { scan-tree-dump-not "__sanitizer_cov_trace_pc" "optimized" } } */ + +int +foo (int a, int b) +{ + return a == b; +} diff --git a/gcc/testsuite/gcc.dg/sancov/pr104158-7.c b/gcc/testsuite/gcc.dg/sancov/pr104158-7.c new file mode 100644 index 0000000..7fc5b73 --- /dev/null +++ b/gcc/testsuite/gcc.dg/sancov/pr104158-7.c @@ -0,0 +1,11 @@ +/* PR sanitizer/104158 */ +/* { dg-do compile } */ +/* { dg-options "-fsanitize-coverage=trace-cmp,trace-cmp -fdump-tree-optimized" } */ +/* { dg-final { scan-tree-dump "__sanitizer_cov_trace_cmp" "optimized" } } */ +/* { dg-final { scan-tree-dump-not "__sanitizer_cov_trace_pc" "optimized" } } */ + +int +foo (int a, int b) +{ + return a == b; +} diff --git a/gcc/testsuite/gcc.dg/spellcheck-options-24.c b/gcc/testsuite/gcc.dg/spellcheck-options-24.c new file mode 100644 index 0000000..1bd6cc2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/spellcheck-options-24.c @@ -0,0 +1,5 @@ +/* { dg-do compile } */ +/* { dg-options "-fsanitize-coverage=trace-pc,tracecmp" } */ + +/* { dg-error "unrecognized argument in option '-fsanitize-coverage=trace-pc,tracecmp'" "" { target *-*-* } 0 } */ +/* { dg-message "valid arguments to '-fsanitize-coverage=' are: trace-cmp trace-pc; did you mean 'trace-cmp'?" "" { target *-*-* } 0 } */ diff --git a/gcc/testsuite/gcc.dg/torture/pr100740.c b/gcc/testsuite/gcc.dg/torture/pr100740.c new file mode 100644 index 0000000..a85855e --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr100740.c @@ -0,0 +1,12 @@ +/* { dg-do run } */ + +unsigned a, b; +int main() +{ + unsigned c = 0; + for (a = 0; a < 2; a++) + for (b = 0; b < 2; b++) + if (++c < a) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr100786.c b/gcc/testsuite/gcc.dg/torture/pr100786.c new file mode 100644 index 0000000..42f4e48 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr100786.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ + +const double a = 0; +extern int b __attribute__((alias("a"))); +void inc() { b++; } + +const int a2 = 0; +extern double b2 __attribute__((alias("a2"))); +void inc2() { b2+=1; } diff --git a/gcc/testsuite/gcc.dg/torture/pr101508.c b/gcc/testsuite/gcc.dg/torture/pr101508.c new file mode 100644 index 0000000..e1cb264 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr101508.c @@ -0,0 +1,13 @@ +/* { dg-do run } */ + +int +main () +{ + unsigned i; + for (i = 0; i < 3; ++i) + { + if (i > i * 2) + __builtin_abort (); + } + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr101972.c b/gcc/testsuite/gcc.dg/torture/pr101972.c new file mode 100644 index 0000000..3adb482 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr101972.c @@ -0,0 +1,39 @@ +/* { dg-do run } */ +/* { dg-require-effective-target int32plus } */ + +int a, b, c, d, f; +static short e = 63891; +char g = 30; +unsigned h(int i, int j) { return i << j; } +int *l(int *); +void m() +{ + a = 0; + for (; a >= 0; a--) + { + int *k = &b; + *k = e < 0; + } + c = b; + l(&c); +} +int *l(int *i) +{ + d = 2; + for (; d <= 6; d++) + { + if (h(d, *i) <= d) + ; + else + continue; + g = 0; + return &f; + } + return (void *)0; +} +int main() +{ + m(); + if (g != 30) + __builtin_abort (); +} diff --git a/gcc/testsuite/gcc.dg/torture/pr102131-1.c b/gcc/testsuite/gcc.dg/torture/pr102131-1.c new file mode 100644 index 0000000..5ff576d --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr102131-1.c @@ -0,0 +1,16 @@ +/* { dg-do run } */ + +int a; +int main() +{ + unsigned b = 0; + int c = 1; + for (; b < 3; b++) + { + while (c < b) + __builtin_abort (); + for (a = 0; a < 3; a++) + c++; + } + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr102131-2.c b/gcc/testsuite/gcc.dg/torture/pr102131-2.c new file mode 100644 index 0000000..830c72c --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr102131-2.c @@ -0,0 +1,15 @@ +/* { dg-do run } */ + +int a; +int main() +{ + unsigned b = 0; + int c = 1; + for (;b < 3; b++) + { + if (c < b) + __builtin_abort (); + c+=3; + } + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr102131-3.c b/gcc/testsuite/gcc.dg/torture/pr102131-3.c new file mode 100644 index 0000000..aed10c9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr102131-3.c @@ -0,0 +1,11 @@ +/* { dg-do run } */ + +int a; +int main() +{ + unsigned b = 0; + for (a = 2; a < 8; a += 2) + if (++b > a) + __builtin_abort(); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/torture/pr102131-4.c b/gcc/testsuite/gcc.dg/torture/pr102131-4.c new file mode 100644 index 0000000..c63c08b --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr102131-4.c @@ -0,0 +1,15 @@ +/* { dg-do run } */ +/* { dg-require-effective-target int32plus } */ + +unsigned a; +int main() +{ + unsigned b = 1; + for (; b < 4; b++) { + a = (a ^ 2000000000) * -b; + if (b > a) + __builtin_abort (); + a = 3000000000; + } + return 0; +} diff --git a/gcc/testsuite/gcc.dg/vect/pr104152.c b/gcc/testsuite/gcc.dg/vect/pr104152.c new file mode 100644 index 0000000..3a313c3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr104152.c @@ -0,0 +1,40 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-Ofast" } */ +/* { dg-additional-options "-march=armv8.2-a+sve" { target aarch64-*-* } } */ + +#define M_PI 3.14f +#define NK 24 +#define DIM 3 + +typedef float rvec_ [3]; + +static rvec_ v0[NK] = { + { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 }, { 1, 1, 0 }, { 1, -1, 0 }, + { 1, 0, 1 }, { 1, 0, -1 }, { 0, 1, 1 }, { 0, 1, -1 }, { 1, 1, 1 }, + { 1, 1, -1 }, { 1, -1, 1 }, { -1, 1, 1 }, { 2, 0, 0 }, { 0, 2, 0 }, + { 0, 0, 2 }, { 3, 0, 0 }, { 0, 3, 0 }, { 0, 0, 3 }, { 4, 0, 0 }, + { 0, 4, 0 }, { 0, 0, 4 } }; + +static inline float iprod__(const rvec_ a, const rvec_ b) +{ + return (a[0] * b[0] + a[1] * b[1] + a[2] * b[2]); +} + +int badaboum(rvec_ cm_mol, float **tc) +{ + float sx; + int k, d; + rvec_ kfac[3]; + + for (k = 0; k < DIM; k++) + for (d = 0; d < DIM; d++) + kfac[k][d] = M_PI * v0[k][d] / v0[d][d]; + + for (k = 0; k < DIM; k++) + { + sx = __builtin_sinf(iprod__(kfac[k], cm_mol)); + tc[k][0] += sx * iprod__(v0[k], cm_mol); + } + + return 0; +} diff --git a/gcc/testsuite/gcc.target/aarch64/cpymem-q-reg_1.c b/gcc/testsuite/gcc.target/aarch64/cpymem-q-reg_1.c index df5f67e..45f3f0a 100644 --- a/gcc/testsuite/gcc.target/aarch64/cpymem-q-reg_1.c +++ b/gcc/testsuite/gcc.target/aarch64/cpymem-q-reg_1.c @@ -10,7 +10,7 @@ foo (void) __builtin_memcpy (dst, src, N * sizeof (int)); } -/* { dg-final { scan-assembler {ldp\tq[0-9]*} } } */ +/* { dg-final { scan-assembler {ldp\tq[0-9]*|ld1\t{v[0-9]*\.16b - v[0-9]*\.16b}} } } */ /* { dg-final { scan-assembler-not {ldp\tx[0-9]*} } } */ -/* { dg-final { scan-assembler {stp\tq[0-9]*} } } */ +/* { dg-final { scan-assembler {stp\tq[0-9]*|st1\t{v[0-9]*\.16b - v[0-9]*\.16b}} } } */ /* { dg-final { scan-assembler-not {stp\tx[0-9]*} } } */ diff --git a/gcc/testsuite/gcc.target/aarch64/spellcheck_1.c b/gcc/testsuite/gcc.target/aarch64/spellcheck_1.c index a0795c1c..8654674 100644 --- a/gcc/testsuite/gcc.target/aarch64/spellcheck_1.c +++ b/gcc/testsuite/gcc.target/aarch64/spellcheck_1.c @@ -4,6 +4,6 @@ __attribute__((target ("arch=armv8-a-typo"))) void foo () { /* { dg-message "valid arguments are: \[^\n\r]*(; did you mean 'armv*'?)?" "" { target *-*-* } .-1 } */ - /* { dg-error "invalid name \\(\"armv8-a-typo\"\\) in 'target\\(\"arch=\"\\)' pragma or attribute" "" { target *-*-* } .-2 } */ + /* { dg-error "invalid name \\('armv8-a-typo'\\) in 'target\\(\"arch=\"\\)' pragma or attribute" "" { target *-*-* } .-2 } */ /* { dg-error "pragma or attribute 'target\\(\"arch=armv8-a-typo\"\\)' is not valid" "" { target *-*-* } .-3 } */ } diff --git a/gcc/testsuite/gcc.target/aarch64/spellcheck_2.c b/gcc/testsuite/gcc.target/aarch64/spellcheck_2.c index 70096f8..1cc2c05 100644 --- a/gcc/testsuite/gcc.target/aarch64/spellcheck_2.c +++ b/gcc/testsuite/gcc.target/aarch64/spellcheck_2.c @@ -4,6 +4,6 @@ __attribute__((target ("cpu=cortex-a57-typo"))) void foo () { /* { dg-message "valid arguments are: \[^\n\r]*; did you mean 'cortex-a57'?" "" { target *-*-* } .-1 } */ - /* { dg-error "invalid name \\(\"cortex-a57-typo\"\\) in 'target\\(\"cpu=\"\\)' pragma or attribute" "" { target *-*-* } .-2 } */ + /* { dg-error "invalid name \\('cortex-a57-typo'\\) in 'target\\(\"cpu=\"\\)' pragma or attribute" "" { target *-*-* } .-2 } */ /* { dg-error "pragma or attribute 'target\\(\"cpu=cortex-a57-typo\"\\)' is not valid" "" { target *-*-* } .-3 } */ } diff --git a/gcc/testsuite/gcc.target/aarch64/spellcheck_3.c b/gcc/testsuite/gcc.target/aarch64/spellcheck_3.c index 20dff2b..9953872 100644 --- a/gcc/testsuite/gcc.target/aarch64/spellcheck_3.c +++ b/gcc/testsuite/gcc.target/aarch64/spellcheck_3.c @@ -4,6 +4,6 @@ __attribute__((target ("tune=cortex-a57-typo"))) void foo () { /* { dg-message "valid arguments are: \[^\n\r]*; did you mean 'cortex-a57'?" "" { target *-*-* } .-1 } */ - /* { dg-error "invalid name \\(\"cortex-a57-typo\"\\) in 'target\\(\"tune=\"\\)' pragma or attribute" "" { target *-*-* } .-2 } */ + /* { dg-error "invalid name \\('cortex-a57-typo'\\) in 'target\\(\"tune=\"\\)' pragma or attribute" "" { target *-*-* } .-2 } */ /* { dg-error "pragma or attribute 'target\\(\"tune=cortex-a57-typo\"\\)' is not valid" "" { target *-*-* } .-3 } */ } diff --git a/gcc/testsuite/gcc.target/aarch64/spellcheck_7.c b/gcc/testsuite/gcc.target/aarch64/spellcheck_7.c index 1d31950..1e1cbec 100644 --- a/gcc/testsuite/gcc.target/aarch64/spellcheck_7.c +++ b/gcc/testsuite/gcc.target/aarch64/spellcheck_7.c @@ -9,4 +9,4 @@ foo () } /* { dg-error "invalid feature modifier .typo. in .-march=armv8-a\\+typo." "" { target *-*-* } 0 } */ -/* { dg-message "valid arguments are: \[^\n\r]*;'?" "" { target *-*-* } 0 } */ +/* { dg-message "valid arguments are: \[^\n\r]*" "" { target *-*-* } 0 } */ diff --git a/gcc/testsuite/gcc.target/aarch64/vsqrt-1.c b/gcc/testsuite/gcc.target/aarch64/vsqrt-1.c new file mode 100644 index 0000000..e614c7d --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/vsqrt-1.c @@ -0,0 +1,17 @@ +/* PR target/64821 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* Check that we constant fold sqrt(4.0) into 2.0. */ +/* { dg-final { scan-tree-dump-not " \\\.SQRT" "optimized" } } */ +/* { dg-final { scan-tree-dump " 2\\\.0e\\\+0" "optimized" } } */ +/* { dg-final { scan-assembler-not "fsqrt" } } */ +/* We should produce a fmov to d0 with 2.0 but currently don't, see PR 103959. */ +/* { dg-final { scan-assembler-times "\n\tfmov\td0, 2.0e.0" 1 { xfail *-*-* } } } */ + +#include <arm_neon.h> + +float64x1_t f64(void) +{ + float64x1_t a = (float64x1_t){4.0}; + return vsqrt_f64 (a); +} diff --git a/gcc/testsuite/gcc.target/aarch64/vsqrt-2.c b/gcc/testsuite/gcc.target/aarch64/vsqrt-2.c new file mode 100644 index 0000000..4dea4da --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/vsqrt-2.c @@ -0,0 +1,28 @@ +/* PR target/64821 */ +/* { dg-do compile } */ +/* { dg-options "-fdump-tree-optimized" } */ +#include <arm_neon.h> + +/* Check that we lower __builtin_aarch64_sqrt* into the internal function SQRT. */ +/* { dg-final { scan-tree-dump-times " __builtin_aarch64_sqrt" 0 "optimized" } } */ +/* { dg-final { scan-tree-dump-times " \\\.SQRT " 4 "optimized" } } */ + +float64x1_t f64(float64x1_t a) +{ + return vsqrt_f64 (a); +} + +float64x2_t f64q(float64x2_t a) +{ + return vsqrtq_f64 (a); +} + +float32x2_t f32(float32x2_t a) +{ + return vsqrt_f32 (a); +} + +float32x4_t f32q(float32x4_t a) +{ + return vsqrtq_f32 (a); +} diff --git a/gcc/testsuite/gcc.target/arm/stack-protector-7.c b/gcc/testsuite/gcc.target/arm/stack-protector-7.c new file mode 100644 index 0000000..2173bc5 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/stack-protector-7.c @@ -0,0 +1,12 @@ +/* { dg-require-effective-target arm_hard_vfp_ok } */ +/* { dg-require-effective-target arm_arch_v7a_ok } */ +/* { dg-do compile } */ +/* { dg-options "-march=armv7-a -mfpu=vfp -fstack-protector-all -Os -mstack-protector-guard=tls -mstack-protector-guard-offset=1296 -mtp=cp15" } */ + +#include "stack-protector-5.c" + +/* See the comment in stack-protector-5.c. */ +/* { dg-final { scan-assembler-times {\tstr\t} 1 } } */ +/* Expect two TLS register accesses and two occurrences of the offset */ +/* { dg-final { scan-assembler-times {\tmrc\t} 2 } } */ +/* { dg-final { scan-assembler-times {1296} 2 } } */ diff --git a/gcc/testsuite/gcc.target/arm/stack-protector-8.c b/gcc/testsuite/gcc.target/arm/stack-protector-8.c new file mode 100644 index 0000000..ea5ef32 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/stack-protector-8.c @@ -0,0 +1,7 @@ +/* { dg-require-effective-target arm_hard_vfp_ok } */ +/* { dg-require-effective-target arm_arch_v7a_ok } */ +/* { dg-do compile } */ +/* { dg-error "needs a hardware TLS register" "missing error when using TLS stack protector without hardware TLS register" { target *-*-* } 0 } */ +/* { dg-options "-fstack-protector-all -Os -mstack-protector-guard=tls -mtp=soft" } */ + +int foo; diff --git a/gcc/testsuite/gcc.target/i386/pr104188.c b/gcc/testsuite/gcc.target/i386/pr104188.c new file mode 100644 index 0000000..c6f615b --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr104188.c @@ -0,0 +1,70 @@ +/* { dg-do run { target avx512f } } */ +/* { dg-options "-O2 -mfpmath=sse" } */ + +#include <x86intrin.h> + +union U { + float m[4][4]; + __m128 r[4]; + __m512 s; +}; + +__attribute__((noipa, target("avx512f"))) +void +foo (union U *x, union U *a, union U *b) +{ + __m512 c = _mm512_loadu_ps (&a->s); + __m512 d = _mm512_broadcast_f32x4 (b->r[0]); + __m512 e = _mm512_broadcast_f32x4 (b->r[1]); + __m512 f = _mm512_broadcast_f32x4 (b->r[2]); + __m512 g = _mm512_broadcast_f32x4 (b->r[3]); + __m512 h = _mm512_mul_ps (_mm512_permute_ps (c, 0x00), d); + h = _mm512_fmadd_ps (_mm512_permute_ps (c, 0x55), e, h); + h = _mm512_fmadd_ps (_mm512_permute_ps (c, 0xaa), f, h); + h = _mm512_fmadd_ps (_mm512_permute_ps (c, 0xff), g, h); + _mm512_storeu_ps (&x->s, h); +} + +__attribute__((noipa, target("avx512f"))) +void +do_test (void) +{ + union U a = { .m = { { 1.0f, 2.0f, 3.0f, 4.0f }, + { 5.0f, 6.0f, 7.0f, 8.0f }, + { 9.0f, 10.0f, 11.0f, 12.0f }, + { 13.0f, 14.0f, 15.0f, 16.0f } } }; + union U b = { .m = { { 17.0f, 18.0f, 19.0f, 20.0f }, + { 21.0f, 22.0f, 23.0f, 24.0f }, + { 25.0f, 26.0f, 27.0f, 28.0f }, + { 29.0f, 30.0f, 31.0f, 32.0f } } }; + union U c; + foo (&c, &a, &b); + if (c.m[0][0] != 250.0f + || c.m[0][1] != 260.0f + || c.m[0][2] != 270.0f + || c.m[0][3] != 280.0f) + __builtin_abort (); + if (c.m[1][0] != 618.0f + || c.m[1][1] != 644.0f + || c.m[1][2] != 670.0f + || c.m[1][3] != 696.0f) + __builtin_abort (); + if (c.m[2][0] != 986.0f + || c.m[2][1] != 1028.0f + || c.m[2][2] != 1070.0f + || c.m[2][3] != 1112.0f) + __builtin_abort (); + if (c.m[3][0] != 1354.0f + || c.m[3][1] != 1412.0f + || c.m[3][2] != 1470.0f + || c.m[3][3] != 1528.0f) + __builtin_abort (); +} + +int +main () +{ + if (__builtin_cpu_supports ("avx512f")) + do_test (); + return 0; +} diff --git a/gcc/testsuite/gcc.target/mips/fix-r4000-2.c b/gcc/testsuite/gcc.target/mips/fix-r4000-2.c index 4290d5f..e0e65d6 100644 --- a/gcc/testsuite/gcc.target/mips/fix-r4000-2.c +++ b/gcc/testsuite/gcc.target/mips/fix-r4000-2.c @@ -4,6 +4,4 @@ typedef int int32_t; typedef long long int64_t; NOMIPS16 int32_t foo (int32_t x, int32_t y) { return ((int64_t) x * y) >> 32; } -/* ??? A highpart pattern would be a better choice, but we currently - don't use them. */ -/* { dg-final { scan-assembler "[concat {\tmult\t\$[45],\$[45][^\n]+mulsidi3_32bit_r4000\n\tmflo\t\$3\n\tmfhi\t\$2\n}]" } } */ +/* { dg-final { scan-assembler "[concat {\tmult\t\$[45],\$[45][^\n]+smulsi3_highpart_internal\n\tmfhi\t\$2\n}]" } } */ diff --git a/gcc/testsuite/gcc.target/mips/fix-r4000-3.c b/gcc/testsuite/gcc.target/mips/fix-r4000-3.c index 5bc8fc8..ec9d655 100644 --- a/gcc/testsuite/gcc.target/mips/fix-r4000-3.c +++ b/gcc/testsuite/gcc.target/mips/fix-r4000-3.c @@ -1,8 +1,6 @@ -/* { dg-options "-mips1 -mfix-r4000 -dp -EB" } */ +/* { dg-options "-mips1 -mfix-r4000 -dp -EB -fexpensive-optimizations" } */ /* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */ typedef unsigned int uint32_t; typedef unsigned long long uint64_t; NOMIPS16 uint32_t foo (uint32_t x, uint32_t y) { return ((uint64_t) x * y) >> 32; } -/* ??? A highpart pattern would be a better choice, but we currently - don't use them. */ -/* { dg-final { scan-assembler "[concat {\tmultu\t\$[45],\$[45][^\n]+umulsidi3_32bit_r4000\n\tmflo\t\$3\n\tmfhi\t\$2\n}]" } } */ +/* { dg-final { scan-assembler "[concat {\tmultu\t\$[45],\$[45][^\n]+umulsi3_highpart_internal\n\tmfhi\t\$2\n}]" } } */ diff --git a/gcc/testsuite/gcc.target/mips/fix-r4000-7.c b/gcc/testsuite/gcc.target/mips/fix-r4000-7.c index 25178db..9b10577 100644 --- a/gcc/testsuite/gcc.target/mips/fix-r4000-7.c +++ b/gcc/testsuite/gcc.target/mips/fix-r4000-7.c @@ -4,6 +4,4 @@ typedef long long int64_t; typedef int int128_t __attribute__((mode(TI))); NOMIPS16 int64_t foo (int64_t x, int64_t y) { return ((int128_t) x * y) >> 64; } -/* ??? A highpart pattern would be a better choice, but we currently - don't use them. */ -/* { dg-final { scan-assembler "[concat {\tdmult\t\$[45],\$[45][^\n]+mulditi3_r4000\n\tmflo\t\$3\n\tmfhi\t\$2\n}]" } } */ +/* { dg-final { scan-assembler "[concat {\tdmult\t\$[45],\$[45][^\n]+smuldi3_highpart_internal\n\tmfhi\t\$2\n}]" } } */ diff --git a/gcc/testsuite/gcc.target/mips/fix-r4000-8.c b/gcc/testsuite/gcc.target/mips/fix-r4000-8.c index eae1488..1ce35df 100644 --- a/gcc/testsuite/gcc.target/mips/fix-r4000-8.c +++ b/gcc/testsuite/gcc.target/mips/fix-r4000-8.c @@ -1,8 +1,6 @@ -/* { dg-options "-march=r4000 -mfix-r4000 -mgp64 -dp -EB" } */ +/* { dg-options "-march=r4000 -mfix-r4000 -mgp64 -dp -EB -fexpensive-optimizations" } */ /* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */ typedef unsigned long long uint64_t; typedef unsigned int uint128_t __attribute__((mode(TI))); NOMIPS16 uint64_t foo (uint64_t x, uint64_t y) { return ((uint128_t) x * y) >> 64; } -/* ??? A highpart pattern would be a better choice, but we currently - don't use them. */ -/* { dg-final { scan-assembler "[concat {\tdmultu\t\$[45],\$[45][^\n]+umulditi3_r4000\n\tmflo\t\$3\n\tmfhi\t\$2\n}]" } } */ +/* { dg-final { scan-assembler "[concat {\tdmultu\t\$[45],\$[45][^\n]+umuldi3_highpart_internal\n\tmfhi\t\$2\n}]" } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/builtins-4.c b/gcc/testsuite/gcc.target/powerpc/builtins-4.c index 4e3b543..f65e582 100644 --- a/gcc/testsuite/gcc.target/powerpc/builtins-4.c +++ b/gcc/testsuite/gcc.target/powerpc/builtins-4.c @@ -119,6 +119,18 @@ test_vul_sldw_vul_vul (vector unsigned long long x, return vec_sldw (x, y, 3); } +vector float +test_vf_sldw_vf_vf (vector float x, vector float y) +{ + return vec_sldw (x, y, 3); +} + +vector double +test_vd_sldw_vd_vd (vector double x, vector double y) +{ + return vec_sldw (x, y, 1); +} + vector signed int long long test_sll_vsill_vsill_vuc (vector signed long long int x, vector unsigned char y) @@ -146,14 +158,16 @@ test_sll_vuill_vuill_vuc (vector unsigned long long int x, test_slo_vsll_slo_vsll_vuc 1 vslo test_slo_vull_slo_vull_vsc 1 vslo test_slo_vull_slo_vull_vuc 1 vslo - test_vsc_sldw_vsc_vsc 1 xxlor - test_vuc_sldw_vuc_vuc 1 xxlor - test_vssi_sldw_vssi_vssi 1 xxlor - test_vusi_sldw_vusi_vusi 1 xxlor - test_vsi_sldw_vsi_vsi 1 xxlor - test_vui_sldw_vui_vui 1 xxlor - test_vsl_sldw_vsl_vsl 1 xxlor - test_vul_sldw_vul_vul 1 xxlor + test_vsc_sldw_vsc_vsc 1 xxlor, 1 xxsldwi + test_vuc_sldw_vuc_vuc 1 xxlor, 1 xxsldwi + test_vssi_sldw_vssi_vssi 1 xxlor, 1 xxsldwi + test_vusi_sldw_vusi_vusi 1 xxlor, 1 xxsldwi + test_vsi_sldw_vsi_vsi 1 xxlor, 1 xxsldwi + test_vui_sldw_vui_vui 1 xxlor, 1 xxsldwi + test_vsl_sldw_vsl_vsl 1 xxlor, 1 xxsldwi + test_vul_sldw_vul_vul 1 xxlor, 1 xxsldwi + test_vf_sldw_vf_vf 1 xxlor, 1 xxsldwi + test_vd_sldw_vd_vd 1 xxlor, 1 xxsldwi test_sll_vsill_vsill_vuc 1 vsl test_sll_vuill_vuill_vuc 1 vsl */ @@ -161,6 +175,6 @@ test_sll_vuill_vuill_vuc (vector unsigned long long int x, /* { dg-final { scan-assembler-times "xvnabssp" 1 } } */ /* { dg-final { scan-assembler-times "xvnabsdp" 1 } } */ /* { dg-final { scan-assembler-times "vslo" 4 } } */ -/* { dg-final { scan-assembler-times "xxlor" 30 } } */ +/* { dg-final { scan-assembler-times "xxlor" 32 } } */ /* { dg-final { scan-assembler-times {\mvsl\M} 5 } } */ - +/* { dg-final { scan-assembler-times {\mxxsldwi\M} 10 } } */ diff --git a/gcc/testsuite/gcc.target/powerpc/fold-vec-splat-floatdouble.c b/gcc/testsuite/gcc.target/powerpc/fold-vec-splat-floatdouble.c index b95fa32..01f1b0d 100644 --- a/gcc/testsuite/gcc.target/powerpc/fold-vec-splat-floatdouble.c +++ b/gcc/testsuite/gcc.target/powerpc/fold-vec-splat-floatdouble.c @@ -21,12 +21,11 @@ vector double test_dc () { const vector double y = { 3.0, 5.0 }; return vec_splat (y, 0b00001); } /* If the source vector is a known constant, we will generate a load or possibly - XXSPLTIW. */ -/* { dg-final { scan-assembler-times {\mlvx\M|\mlxvd2x\M|\mlxv\M|\mplxv\M|\mxxspltiw\M} 2 } } */ + XXSPLTIW/XXSPLTIDP. */ +/* { dg-final { scan-assembler-times {\mlvx\M|\mlxvd2x\M|\mlxv\M|\mplxv\M|\mxxspltiw\M|\mxxspltidp\M} 2 } } */ /* For float types, we generate a splat. */ /* { dg-final { scan-assembler-times {\mvspltw\M|\mxxspltw\M} 3 } } */ /* For double types, we will generate xxpermdi instructions. */ /* { dg-final { scan-assembler-times "xxpermdi" 2 } } */ - diff --git a/gcc/testsuite/gcc.target/riscv/arch-10.c b/gcc/testsuite/gcc.target/riscv/arch-10.c index 47dbda3..1052f2e 100644 --- a/gcc/testsuite/gcc.target/riscv/arch-10.c +++ b/gcc/testsuite/gcc.target/riscv/arch-10.c @@ -3,4 +3,4 @@ int foo() { } -/* { dg-error "Extension `f' appear more than one time." "" { target *-*-* } 0 } */ +/* { dg-error "extension 'f' appear more than one time" "" { target *-*-* } 0 } */ diff --git a/gcc/testsuite/gcc.target/riscv/arch-12.c b/gcc/testsuite/gcc.target/riscv/arch-12.c index 29e16c3..5ee9a1d 100644 --- a/gcc/testsuite/gcc.target/riscv/arch-12.c +++ b/gcc/testsuite/gcc.target/riscv/arch-12.c @@ -1,4 +1,4 @@ /* { dg-do compile } */ /* { dg-options "-O2 -march=rv64im1p2p3 -mabi=lp64" } */ int foo() {} -/* { dg-error "'-march=rv64im1p2p3': For 'm1p2p\\?', version number with more than 2 level is not supported." "" { target *-*-* } 0 } */ +/* { dg-error "'-march=rv64im1p2p3': for 'm1p2p\\?', version number with more than 2 level is not supported" "" { target *-*-* } 0 } */ diff --git a/gcc/testsuite/gcc.target/riscv/arch-9.c b/gcc/testsuite/gcc.target/riscv/arch-9.c index 74e6410..d00e99d 100644 --- a/gcc/testsuite/gcc.target/riscv/arch-9.c +++ b/gcc/testsuite/gcc.target/riscv/arch-9.c @@ -3,4 +3,4 @@ int foo() { } -/* { dg-warning "version of `g` will be omitted, please specify version for individual extension." "" { target *-*-* } 0 } */ +/* { dg-warning "version of 'g' will be omitted, please specify version for individual extension" "" { target *-*-* } 0 } */ diff --git a/gcc/testsuite/gcc.target/riscv/attribute-19.c b/gcc/testsuite/gcc.target/riscv/attribute-19.c index 18f68d9..562f808 100644 --- a/gcc/testsuite/gcc.target/riscv/attribute-19.c +++ b/gcc/testsuite/gcc.target/riscv/attribute-19.c @@ -1,4 +1,4 @@ /* { dg-do compile } */ -/* { dg-options "-mriscv-attribute -march=rv64imp0p9 -mabi=lp64" } */ +/* { dg-options "-mriscv-attribute -march=rv64imp0p9 -mabi=lp64 -misa-spec=2.2" } */ int foo() {} /* { dg-final { scan-assembler ".attribute arch, \"rv64i2p0_m2p0_p0p9\"" } } */ diff --git a/gcc/testsuite/gcc.target/riscv/pr104140.c b/gcc/testsuite/gcc.target/riscv/pr104140.c new file mode 100644 index 0000000..648e131 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/pr104140.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=rv32im -mabi=ilp32" } */ +int x; +unsigned u, v; +void f (void) +{ + long long y = x; + u = y * v >> 32; +} +void g (void) { f (); } + diff --git a/gcc/testsuite/gfortran.dg/gomp/affinity-clause-3.f90 b/gcc/testsuite/gfortran.dg/gomp/affinity-clause-3.f90 index 3fd39fe..eebe4dd 100644 --- a/gcc/testsuite/gfortran.dg/gomp/affinity-clause-3.f90 +++ b/gcc/testsuite/gfortran.dg/gomp/affinity-clause-3.f90 @@ -11,4 +11,4 @@ subroutine foo !$omp end task end ! { dg-final { scan-tree-dump-times "= ibar \\(&C\\." 3 "gimple" } } -! { dg-final { scan-tree-dump-times "= ibar \\(j\\." 1 "gimple" } } +! { dg-final { scan-tree-dump-times "= ibar \\(&j" 1 "gimple" } } diff --git a/gcc/testsuite/gfortran.dg/gomp/pr102621.f90 b/gcc/testsuite/gfortran.dg/gomp/pr102621.f90 new file mode 100644 index 0000000..ca1e2d4 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/pr102621.f90 @@ -0,0 +1,12 @@ +! This program used to ICE in convert_nonlocal_reference_op due to +! incorrect scoping of AFFINITY clause iterator variables. + +program p + integer :: a(8) + !$omp task affinity (iterator(j=1:8) : a(j)) + !$omp end task +contains + integer function f(x) + class(*) :: x + end +end diff --git a/gcc/testsuite/gfortran.dg/gomp/pr103695.f90 b/gcc/testsuite/gfortran.dg/gomp/pr103695.f90 new file mode 100644 index 0000000..cc9764e --- /dev/null +++ b/gcc/testsuite/gfortran.dg/gomp/pr103695.f90 @@ -0,0 +1,18 @@ +! This test case used to ICE in verify_ssa due to the iterator variable j +! incorrectly being inserted into program scope. + +program p + integer :: i + do i = 1, 3 + call sub (s(i)) + end do +contains + function s(n) result(z) + integer, target, intent(in) :: n + integer, pointer :: z + integer :: a(8), b(8), c(8) + !$omp task affinity (iterator(j=1:8) : a(j), b(j), c(j)) + !$omp end task + z => n + end +end diff --git a/gcc/testsuite/gfortran.dg/transfer_simplify_11.f90 b/gcc/testsuite/gfortran.dg/transfer_simplify_11.f90 index 0911f9d..409e476 100644 --- a/gcc/testsuite/gfortran.dg/transfer_simplify_11.f90 +++ b/gcc/testsuite/gfortran.dg/transfer_simplify_11.f90 @@ -4,5 +4,5 @@ integer, parameter :: N = 2 character(len=1) :: chr(N) chr = transfer(repeat("x",ncopies=N),[character(len=1) ::], N) - if (chr(1) /= 'x' .and. chr(2) /= 'x') STOP 1 + if (chr(1) /= 'x' .or. chr(2) /= 'x') STOP 1 end diff --git a/gcc/testsuite/gfortran.dg/transfer_simplify_13.f90 b/gcc/testsuite/gfortran.dg/transfer_simplify_13.f90 new file mode 100644 index 0000000..bafb046 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/transfer_simplify_13.f90 @@ -0,0 +1,34 @@ +! { dg-do compile } +! { dg-options "-fdump-tree-original" } +! PR fortran/104127 - ICE in get_array_charlen +! Contributed by G.Steinmetz + +program p + character(4) :: mold = "XYZ" + integer :: i = 0 + integer, parameter :: l1 = len (transfer('ab', 'xyz', size=0)) + integer, parameter :: s1 = size (transfer('ab', 'xyz', size=0)) + integer, parameter :: l4 = len (transfer(4_'abcd', 4_'xy', size=0)) + integer, parameter :: s4 = size (transfer(4_'abcd', 4_'xy', size=0)) + integer, parameter :: l2 = len (transfer('ab', mold, size=0)) + integer, parameter :: l3 = len (transfer('ab', mold, size=1)) + integer, parameter :: l5 = len (transfer('ab',['xyz'], size=0)) + integer, parameter :: s5 = size (transfer('ab',['xyz'], size=0)) + call sub0 ( transfer('a', 'y', size=0) ) + call sub1 ([transfer('a', 'y', size=0)]) + call sub2 ([transfer('a',['y'],size=0)]) + call sub3 ( transfer('a', 'y', size=1) ) + call sub4 ([transfer('a', 'y', size=1)]) + call sub5 ( transfer('a', 'y', size=i) ) + call sub6 ( transfer(1_'abcd', 1_'xy' , size=0)) + call sub7 ( transfer(1_'abcd',[1_'xy'], size=0)) + call sub8 ( transfer(4_'abcd', 4_'xy' , size=0)) + call sub9 ( transfer(4_'abcd',[4_'xy'], size=0)) + print *, transfer('abcd', 'xy', size=0) + if (l1 /= 3 .or. s1 /= 0) stop 1 + if (l4 /= 2 .or. s4 /= 0) stop 2 + if (l2 /= 4 .or. l3 /= 4) stop 3 + if (l5 /= 3 .or. s5 /= 0) stop 4 +end + +! { dg-final { scan-tree-dump-not "_gfortran_stop_numeric" "original" } } diff --git a/gcc/tree-ssa-loop-niter.cc b/gcc/tree-ssa-loop-niter.cc index b767056..04c2095 100644 --- a/gcc/tree-ssa-loop-niter.cc +++ b/gcc/tree-ssa-loop-niter.cc @@ -1579,8 +1579,21 @@ number_of_iterations_until_wrap (class loop *loop, tree type, affine_iv *iv0, { IVbase - STEP, +, STEP } != bound Here, biasing IVbase by 1 step makes 'bound' be the value before wrap. */ - niter->control.base = fold_build2 (MINUS_EXPR, niter_type, - niter->control.base, niter->control.step); + tree base_type = TREE_TYPE (niter->control.base); + if (POINTER_TYPE_P (base_type)) + { + tree utype = unsigned_type_for (base_type); + niter->control.base + = fold_build2 (MINUS_EXPR, utype, + fold_convert (utype, niter->control.base), + fold_convert (utype, niter->control.step)); + niter->control.base = fold_convert (base_type, niter->control.base); + } + else + niter->control.base + = fold_build2 (MINUS_EXPR, base_type, niter->control.base, + niter->control.step); + span = fold_build2 (MULT_EXPR, niter_type, niter->niter, fold_convert (niter_type, niter->control.step)); niter->bound = fold_build2 (PLUS_EXPR, niter_type, span, @@ -1881,7 +1894,8 @@ number_of_iterations_cond (class loop *loop, provided that either below condition is satisfied: a) the test is NE_EXPR; - b) iv0.step - iv1.step is integer and iv0/iv1 don't overflow. + b) iv0 and iv1 do not overflow and iv0.step - iv1.step is of + the same sign and of less or equal magnitude than iv0.step This rarely occurs in practice, but it is simple enough to manage. */ if (!integer_zerop (iv0->step) && !integer_zerop (iv1->step)) @@ -1890,17 +1904,28 @@ number_of_iterations_cond (class loop *loop, tree step = fold_binary_to_constant (MINUS_EXPR, step_type, iv0->step, iv1->step); - /* No need to check sign of the new step since below code takes care - of this well. */ - if (code != NE_EXPR - && (TREE_CODE (step) != INTEGER_CST - || !iv0->no_overflow || !iv1->no_overflow)) - return false; + /* For code other than NE_EXPR we have to ensure moving the evolution + of IV1 to that of IV0 does not introduce overflow. */ + if (TREE_CODE (step) != INTEGER_CST + || !iv0->no_overflow || !iv1->no_overflow) + { + if (code != NE_EXPR) + return false; + iv0->no_overflow = false; + } + /* If the new step of IV0 has changed sign or is of greater + magnitude then we do not know whether IV0 does overflow + and thus the transform is not valid for code other than NE_EXPR */ + else if (tree_int_cst_sign_bit (step) != tree_int_cst_sign_bit (iv0->step) + || wi::gtu_p (wi::abs (wi::to_widest (step)), + wi::abs (wi::to_widest (iv0->step)))) + { + if (code != NE_EXPR) + return false; + iv0->no_overflow = false; + } iv0->step = step; - if (!POINTER_TYPE_P (type)) - iv0->no_overflow = false; - iv1->step = build_int_cst (step_type, 0); iv1->no_overflow = true; } diff --git a/gcc/tree-ssa-loop-unswitch.cc b/gcc/tree-ssa-loop-unswitch.cc index a405119..2927f30 100644 --- a/gcc/tree-ssa-loop-unswitch.cc +++ b/gcc/tree-ssa-loop-unswitch.cc @@ -79,9 +79,10 @@ static class loop *tree_unswitch_loop (class loop *, basic_block, tree); static bool tree_unswitch_single_loop (class loop *, int); static tree tree_may_unswitch_on (basic_block, class loop *); static bool tree_unswitch_outer_loop (class loop *); -static edge find_loop_guard (class loop *); -static bool empty_bb_without_guard_p (class loop *, basic_block); -static bool used_outside_loop_p (class loop *, tree); +static edge find_loop_guard (class loop *, vec<gimple *>&); +static bool empty_bb_without_guard_p (class loop *, basic_block, + vec<gimple *>&); +static bool used_outside_loop_p (class loop *, tree, vec<gimple *>&); static void hoist_guard (class loop *, edge); static bool check_exit_phi (class loop *); static tree get_vop_from_header (class loop *); @@ -536,11 +537,18 @@ tree_unswitch_outer_loop (class loop *loop) } bool changed = false; - while ((guard = find_loop_guard (loop))) + auto_vec<gimple *> dbg_to_reset; + while ((guard = find_loop_guard (loop, dbg_to_reset))) { if (! changed) rewrite_virtuals_into_loop_closed_ssa (loop); hoist_guard (loop, guard); + for (gimple *debug_stmt : dbg_to_reset) + { + gimple_debug_bind_reset_value (debug_stmt); + update_stmt (debug_stmt); + } + dbg_to_reset.truncate (0); changed = true; } return changed; @@ -551,7 +559,7 @@ tree_unswitch_outer_loop (class loop *loop) otherwise returns NULL. */ static edge -find_loop_guard (class loop *loop) +find_loop_guard (class loop *loop, vec<gimple *> &dbg_to_reset) { basic_block header = loop->header; edge guard_edge, te, fe; @@ -688,7 +696,7 @@ find_loop_guard (class loop *loop) guard_edge = NULL; goto end; } - if (!empty_bb_without_guard_p (loop, bb)) + if (!empty_bb_without_guard_p (loop, bb, dbg_to_reset)) { if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc, @@ -699,7 +707,7 @@ find_loop_guard (class loop *loop) } if (dump_enabled_p ()) - dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc, + dump_printf_loc (MSG_NOTE, loc, "suitable to hoist\n"); end: if (body) @@ -713,10 +721,12 @@ end: are noy used outside of the loop. KNOWN_INVARIANTS is a set of ssa names we know to be invariant, and PROCESSED is a set of ssa names for that we already tested whether they - are invariant or not. */ + are invariant or not. Uses in debug stmts outside of the loop are + pushed to DBG_TO_RESET. */ static bool -empty_bb_without_guard_p (class loop *loop, basic_block bb) +empty_bb_without_guard_p (class loop *loop, basic_block bb, + vec<gimple *> &dbg_to_reset) { basic_block exit_bb = single_exit (loop)->src; bool may_be_used_outside = (bb == exit_bb @@ -736,7 +746,7 @@ empty_bb_without_guard_p (class loop *loop, basic_block bb) if (virtual_operand_p (name)) continue; - if (used_outside_loop_p (loop, name)) + if (used_outside_loop_p (loop, name, dbg_to_reset)) return false; } } @@ -745,6 +755,9 @@ empty_bb_without_guard_p (class loop *loop, basic_block bb) !gsi_end_p (gsi); gsi_next (&gsi)) { gimple *stmt = gsi_stmt (gsi); + if (is_gimple_debug (stmt)) + continue; + if (gimple_has_side_effects (stmt)) return false; @@ -754,17 +767,18 @@ empty_bb_without_guard_p (class loop *loop, basic_block bb) FOR_EACH_SSA_TREE_OPERAND (name, stmt, op_iter, SSA_OP_DEF) { if (may_be_used_outside - && used_outside_loop_p (loop, name)) + && used_outside_loop_p (loop, name, dbg_to_reset)) return false; } } return true; } -/* Return true if NAME is used outside of LOOP. */ +/* Return true if NAME is used outside of LOOP. Pushes debug stmts that + have such uses to DBG_TO_RESET but do not consider such uses. */ static bool -used_outside_loop_p (class loop *loop, tree name) +used_outside_loop_p (class loop *loop, tree name, vec<gimple *> &dbg_to_reset) { imm_use_iterator it; use_operand_p use; @@ -773,7 +787,11 @@ used_outside_loop_p (class loop *loop, tree name) { gimple *stmt = USE_STMT (use); if (!flow_bb_inside_loop_p (loop, gimple_bb (stmt))) - return true; + { + if (!is_gimple_debug (stmt)) + return true; + dbg_to_reset.safe_push (stmt); + } } return false; @@ -847,7 +865,7 @@ hoist_guard (class loop *loop, edge guard) char buffer[64]; guard->probability.dump (buffer); - dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc, + dump_printf_loc (MSG_NOTE, loc, "Moving guard %i->%i (prob %s) to bb %i, " "new preheader is %i\n", guard->src->index, guard->dest->index, @@ -949,7 +967,7 @@ hoist_guard (class loop *loop, edge guard) } if (dump_enabled_p ()) - dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc, + dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc, "Guard hoisted\n"); free (body); diff --git a/gcc/tree-ssa-math-opts.cc b/gcc/tree-ssa-math-opts.cc index 3d7104a..ac27775 100644 --- a/gcc/tree-ssa-math-opts.cc +++ b/gcc/tree-ssa-math-opts.cc @@ -4608,6 +4608,10 @@ convert_mult_to_highpart (gassign *stmt, gimple_stmt_iterator *gsi) if (bits < prec || bits >= 2 * prec) return false; + /* For the time being, require operands to have the same sign. */ + if (unsignedp != TYPE_UNSIGNED (TREE_TYPE (mop2))) + return false; + machine_mode mode = TYPE_MODE (optype); optab tab = unsignedp ? umul_highpart_optab : smul_highpart_optab; if (optab_handler (tab, mode) == CODE_FOR_nothing) diff --git a/gcc/tree-ssa-threadbackward.cc b/gcc/tree-ssa-threadbackward.cc index d685b65..3ca65b3 100644 --- a/gcc/tree-ssa-threadbackward.cc +++ b/gcc/tree-ssa-threadbackward.cc @@ -144,6 +144,10 @@ back_threader::back_threader (function *fun, unsigned flags, bool first) m_flags = flags; m_solver = new path_range_query (flags & BT_RESOLVE); m_last_stmt = NULL; + + // The path solver needs EDGE_DFS_BACK in resolving mode. + if (flags & BT_RESOLVE) + mark_dfs_back_edges (); } back_threader::~back_threader () diff --git a/gcc/tree-vect-slp.cc b/gcc/tree-vect-slp.cc index c3a1681..926106c 100644 --- a/gcc/tree-vect-slp.cc +++ b/gcc/tree-vect-slp.cc @@ -1926,8 +1926,17 @@ vect_build_slp_tree_2 (vec_info *vinfo, slp_tree node, if (dt == vect_constant_def || dt == vect_external_def) { - /* We can always build those. Might want to sort last - or defer building. */ + /* Check whether we can build the invariant. If we can't + we never will be able to. */ + tree type = TREE_TYPE (chains[0][n].op); + if (!GET_MODE_SIZE (vinfo->vector_mode).is_constant () + && (TREE_CODE (type) == BOOLEAN_TYPE + || !can_duplicate_and_interleave_p (vinfo, group_size, + type))) + { + matches[0] = false; + goto out; + } vec<tree> ops; ops.create (group_size); for (lane = 0; lane < group_size; ++lane) @@ -5897,9 +5906,8 @@ vect_slp_region (vec<basic_block> bbs, vec<data_reference_p> datarefs, profitable_subgraphs.safe_push (instance); } - /* When we're vectorizing an if-converted loop body with the - very-cheap cost model make sure we vectorized all if-converted - code. */ + /* When we're vectorizing an if-converted loop body make sure + we vectorized all if-converted code. */ if (!profitable_subgraphs.is_empty () && orig_loop) { @@ -5915,7 +5923,7 @@ vect_slp_region (vec<basic_block> bbs, vec<data_reference_p> datarefs, gimple_set_visited (gsi_stmt (gsi), false); continue; } - if (flag_vect_cost_model != VECT_COST_MODEL_VERY_CHEAP) + if (flag_vect_cost_model == VECT_COST_MODEL_UNLIMITED) continue; if (gassign *ass = dyn_cast <gassign *> (gsi_stmt (gsi))) diff --git a/gcc/tree.def b/gcc/tree.def index bd43dbc..62650b6 100644 --- a/gcc/tree.def +++ b/gcc/tree.def @@ -700,7 +700,9 @@ DEFTREECODE (POINTER_PLUS_EXPR, "pointer_plus_expr", tcc_binary, 2) DEFTREECODE (POINTER_DIFF_EXPR, "pointer_diff_expr", tcc_binary, 2) /* Highpart multiplication. For an integral type with precision B, - returns bits [2B-1, B] of the full 2*B product. */ + returns bits [2B-1, B] of the full 2*B product. Both operands + and the result should have integer types of the same precision + and signedness. */ DEFTREECODE (MULT_HIGHPART_EXPR, "mult_highpart_expr", tcc_binary, 2) /* Division for integer result that rounds the quotient toward zero. */ @@ -1349,10 +1351,12 @@ DEFTREECODE (WIDEN_SUM_EXPR, "widen_sum_expr", tcc_binary, 2) DEFTREECODE (SAD_EXPR, "sad_expr", tcc_expression, 3) /* Widening multiplication. - The two arguments are of type t1. - The result is of type t2, such that t2 is at least twice - the size of t1. WIDEN_MULT_EXPR is equivalent to first widening (promoting) - the arguments from type t1 to type t2, and then multiplying them. */ + The two arguments are of type t1 and t2, both integral types that + have the same precision, but possibly different signedness. + The result is of integral type t3, such that t3 is at least twice + the size of t1/t2. WIDEN_MULT_EXPR is equivalent to first widening + (promoting) the arguments from type t1 to type t3, and from t2 to + type t3 and then multiplying them. */ DEFTREECODE (WIDEN_MULT_EXPR, "widen_mult_expr", tcc_binary, 2) /* Widening multiply-accumulate. diff --git a/gcc/value-relation.cc b/gcc/value-relation.cc index 32ca693..077ab42 100644 --- a/gcc/value-relation.cc +++ b/gcc/value-relation.cc @@ -188,6 +188,23 @@ relation_transitive (relation_kind r1, relation_kind r2) return rr_transitive_table[r1 - VREL_FIRST][r2 - VREL_FIRST]; } +// Given an equivalence set EQUIV, set all the bits in B that are still valid +// members of EQUIV in basic block BB. + +void +relation_oracle::valid_equivs (bitmap b, const_bitmap equivs, basic_block bb) +{ + unsigned i; + bitmap_iterator bi; + EXECUTE_IF_SET_IN_BITMAP (equivs, 0, i, bi) + { + tree ssa = ssa_name (i); + const_bitmap ssa_equiv = equiv_set (ssa, bb); + if (ssa_equiv == equivs) + bitmap_set_bit (b, i); + } +} + // ------------------------------------------------------------------------- // The very first element in the m_equiv chain is actually just a summary @@ -364,7 +381,7 @@ equiv_oracle::register_equiv (basic_block bb, unsigned v, equiv_chain *equiv) // Otherwise create an equivalence for this block which is a copy // of equiv, the add V to the set. bitmap b = BITMAP_ALLOC (&m_bitmaps); - bitmap_copy (b, equiv->m_names); + valid_equivs (b, equiv->m_names, bb); bitmap_set_bit (b, v); return b; } @@ -378,32 +395,32 @@ bitmap equiv_oracle::register_equiv (basic_block bb, equiv_chain *equiv_1, equiv_chain *equiv_2) { - // If equiv_1 is alreayd in BB, use it as the combined set. + // If equiv_1 is already in BB, use it as the combined set. if (equiv_1->m_bb == bb) { - bitmap_ior_into (equiv_1->m_names, equiv_2->m_names); + valid_equivs (equiv_1->m_names, equiv_2->m_names, bb); // Its hard to delete from a single linked list, so // just clear the second one. if (equiv_2->m_bb == bb) bitmap_clear (equiv_2->m_names); else - // Ensure equiv_2s names are in the summary for BB. - bitmap_ior_into (m_equiv[bb->index]->m_names, equiv_2->m_names); + // Ensure the new names are in the summary for BB. + bitmap_ior_into (m_equiv[bb->index]->m_names, equiv_1->m_names); return NULL; } // If equiv_2 is in BB, use it for the combined set. if (equiv_2->m_bb == bb) { - bitmap_ior_into (equiv_2->m_names, equiv_1->m_names); - // Add equiv_1 names into the summary. - bitmap_ior_into (m_equiv[bb->index]->m_names, equiv_1->m_names); + valid_equivs (equiv_2->m_names, equiv_1->m_names, bb); + // Ensure the new names are in the summary. + bitmap_ior_into (m_equiv[bb->index]->m_names, equiv_2->m_names); return NULL; } // At this point, neither equivalence is from this block. bitmap b = BITMAP_ALLOC (&m_bitmaps); - bitmap_copy (b, equiv_1->m_names); - bitmap_ior_into (b, equiv_2->m_names); + valid_equivs (b, equiv_1->m_names, bb); + valid_equivs (b, equiv_2->m_names, bb); return b; } @@ -1234,7 +1251,7 @@ relation_oracle::debug () const path_oracle::path_oracle (relation_oracle *oracle) { - m_root = oracle; + set_root_oracle (oracle); bitmap_obstack_initialize (&m_bitmaps); obstack_init (&m_chain_obstack); @@ -1289,8 +1306,8 @@ path_oracle::register_equiv (basic_block bb, tree ssa1, tree ssa2) // Don't mess around, simply create a new record and insert it first. bitmap b = BITMAP_ALLOC (&m_bitmaps); - bitmap_copy (b, equiv_1); - bitmap_ior_into (b, equiv_2); + valid_equivs (b, equiv_1, bb); + valid_equivs (b, equiv_2, bb); equiv_chain *ptr = (equiv_chain *) obstack_alloc (&m_chain_obstack, sizeof (equiv_chain)); @@ -1368,7 +1385,7 @@ path_oracle::register_relation (basic_block bb, relation_kind k, tree ssa1, value_relation vr (k, ssa1, ssa2); fprintf (dump_file, " Registering value_relation (path_oracle) "); vr.dump (dump_file); - fprintf (dump_file, " (bb%d)\n", bb->index); + fprintf (dump_file, " (root: bb%d)\n", bb->index); } if (k == EQ_EXPR) diff --git a/gcc/value-relation.h b/gcc/value-relation.h index 44d0796..6f47133 100644 --- a/gcc/value-relation.h +++ b/gcc/value-relation.h @@ -96,6 +96,8 @@ public: virtual void dump (FILE *, basic_block) const = 0; virtual void dump (FILE *) const = 0; void debug () const; +protected: + void valid_equivs (bitmap b, const_bitmap equivs, basic_block bb); }; // This class represents an equivalency set, and contains a link to the next @@ -227,6 +229,7 @@ public: relation_kind query_relation (basic_block, tree, tree); relation_kind query_relation (basic_block, const_bitmap, const_bitmap); void reset_path (); + void set_root_oracle (relation_oracle *oracle) { m_root = oracle; } void dump (FILE *, basic_block) const; void dump (FILE *) const; private: |