aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMartin Liska <mliska@suse.cz>2022-01-24 13:35:09 +0100
committerMartin Liska <mliska@suse.cz>2022-01-24 13:35:09 +0100
commit58446a69f792166ea2e12d44d5bb3ef1aa61c00d (patch)
tree7320e828f0d82d1118a138d0bc63fdfbb92c9716 /gcc
parent60af3ff91f0c1f7436624f2e2c8f6fe110c36bb6 (diff)
parent978abe918f8c8deed28e92297d3c0cc39086ad83 (diff)
downloadgcc-58446a69f792166ea2e12d44d5bb3ef1aa61c00d.zip
gcc-58446a69f792166ea2e12d44d5bb3ef1aa61c00d.tar.gz
gcc-58446a69f792166ea2e12d44d5bb3ef1aa61c00d.tar.bz2
Merge branch 'master' into devel/sphinx
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog315
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/analyzer/ChangeLog32
-rw-r--r--gcc/analyzer/constraint-manager.cc172
-rw-r--r--gcc/analyzer/constraint-manager.h15
-rw-r--r--gcc/analyzer/region-model-manager.cc11
-rw-r--r--gcc/analyzer/region-model.cc5
-rw-r--r--gcc/c-family/ChangeLog12
-rw-r--r--gcc/c-family/c-common.cc25
-rw-r--r--gcc/c-family/c-common.h3
-rw-r--r--gcc/c-family/c-format.cc2
-rw-r--r--gcc/common.opt6
-rw-r--r--gcc/common/config/i386/i386-common.cc17
-rw-r--r--gcc/common/config/riscv/riscv-common.cc14
-rw-r--r--gcc/common/config/s390/s390-common.cc14
-rw-r--r--gcc/config.gcc8
-rw-r--r--gcc/config/aarch64/aarch64-builtins.cc7
-rw-r--r--gcc/config/alpha/linux.h25
-rw-r--r--gcc/config/arm/arm-opts.h6
-rw-r--r--gcc/config/arm/arm-protos.h2
-rw-r--r--gcc/config/arm/arm.cc55
-rw-r--r--gcc/config/arm/arm.md71
-rw-r--r--gcc/config/arm/arm.opt22
-rw-r--r--gcc/config/fuchsia.h2
-rw-r--r--gcc/config/glibc-stdint.h3
-rw-r--r--gcc/config/i386/i386.cc2
-rw-r--r--gcc/config/i386/predicates.md2
-rw-r--r--gcc/config/linux.h25
-rw-r--r--gcc/config/riscv/riscv-c.cc3
-rw-r--r--gcc/config/rs6000/linux.h25
-rw-r--r--gcc/config/rs6000/linux64.h25
-rw-r--r--gcc/config/rs6000/rs6000-overload.def4
-rw-r--r--gcc/config/rs6000/rs6000-protos.h1
-rw-r--r--gcc/config/rs6000/rs6000.cc40
-rw-r--r--gcc/config/rs6000/rs6000.md24
-rw-r--r--gcc/config/rs6000/vsx.md12
-rwxr-xr-xgcc/configure18
-rw-r--r--gcc/configure.ac16
-rw-r--r--gcc/cp/ChangeLog83
-rw-r--r--gcc/cp/call.cc32
-rw-r--r--gcc/cp/class.cc4
-rw-r--r--gcc/cp/cp-gimplify.cc6
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/decl.cc55
-rw-r--r--gcc/cp/init.cc2
-rw-r--r--gcc/cp/pt.cc69
-rw-r--r--gcc/cp/semantics.cc42
-rw-r--r--gcc/cp/tree.cc25
-rw-r--r--gcc/doc/generic.texi9
-rw-r--r--gcc/doc/invoke.texi11
-rw-r--r--gcc/doc/options.texi33
-rw-r--r--gcc/fortran/ChangeLog20
-rw-r--r--gcc/fortran/dump-parse-tree.cc4
-rw-r--r--gcc/fortran/gfortran.h3
-rw-r--r--gcc/fortran/lang.opt18
-rw-r--r--gcc/fortran/openmp.cc6
-rw-r--r--gcc/fortran/simplify.cc13
-rw-r--r--gcc/fortran/trans-decl.cc3
-rw-r--r--gcc/fortran/trans-openmp.cc2
-rw-r--r--gcc/fortran/trans-types.cc3
-rw-r--r--gcc/gimple-fold.cc4
-rw-r--r--gcc/gimple-range-path.cc48
-rw-r--r--gcc/gimple-range-path.h3
-rw-r--r--gcc/gimple-ssa-warn-access.cc5
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--gcc/ira.cc14
-rw-r--r--gcc/ira.h7
-rw-r--r--gcc/lra-assigns.cc2
-rw-r--r--gcc/lra-constraints.cc148
-rw-r--r--gcc/lra-int.h8
-rw-r--r--gcc/lra-remat.cc2
-rw-r--r--gcc/lra.cc18
-rw-r--r--gcc/lra.h2
-rw-r--r--gcc/opt-functions.awk7
-rw-r--r--gcc/opt-read.awk4
-rw-r--r--gcc/optabs.cc8
-rw-r--r--gcc/optc-gen.awk2
-rw-r--r--gcc/opts-common.cc180
-rw-r--r--gcc/opts-global.cc6
-rw-r--r--gcc/opts.cc59
-rw-r--r--gcc/opts.h24
-rw-r--r--gcc/testsuite/ChangeLog221
-rw-r--r--gcc/testsuite/c-c++-common/Wformat-pr104148.c33
-rw-r--r--gcc/testsuite/g++.dg/abi/no_unique_address2.C27
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-empty14a.C11
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist127.C39
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept72.C21
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/noexcept73.C13
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/noexcept2.C20
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/class-deduction101.C17
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/class-deduction101a.C22
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/class-deduction101b.C22
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/class-deduction102.C25
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/class-deduction102a.C27
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/class-deduction102b.C30
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/class-deduction103.C22
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/desig20.C20
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/desig21.C48
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/nontype-class51.C26
-rw-r--r--gcc/testsuite/g++.dg/init/new50.C9
-rw-r--r--gcc/testsuite/g++.dg/other/pr88187.C2
-rw-r--r--gcc/testsuite/g++.dg/template/explicit-args6.C2
-rw-r--r--gcc/testsuite/g++.target/arm/pr103676.C32
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/pr104089.c2
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/pr94362-1.c60
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/pr94362-2.c42
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/torture/pr103685.c33
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/torture/pr104159.c18
-rw-r--r--gcc/testsuite/gcc.dg/asan/pr99673.c27
-rw-r--r--gcc/testsuite/gcc.dg/loop-unswitch-6.c32
-rw-r--r--gcc/testsuite/gcc.dg/pr102087_1.c13
-rw-r--r--gcc/testsuite/gcc.dg/pr102478.c29
-rw-r--r--gcc/testsuite/gcc.dg/pr103721-2.c28
-rw-r--r--gcc/testsuite/gcc.dg/pr103721.c25
-rw-r--r--gcc/testsuite/gcc.dg/sancov/pr104158-1.c11
-rw-r--r--gcc/testsuite/gcc.dg/sancov/pr104158-2.c11
-rw-r--r--gcc/testsuite/gcc.dg/sancov/pr104158-3.c11
-rw-r--r--gcc/testsuite/gcc.dg/sancov/pr104158-4.c11
-rw-r--r--gcc/testsuite/gcc.dg/sancov/pr104158-5.c11
-rw-r--r--gcc/testsuite/gcc.dg/sancov/pr104158-6.c11
-rw-r--r--gcc/testsuite/gcc.dg/sancov/pr104158-7.c11
-rw-r--r--gcc/testsuite/gcc.dg/spellcheck-options-24.c5
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr100740.c12
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr100786.c9
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr101508.c13
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr101972.c39
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr102131-1.c16
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr102131-2.c15
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr102131-3.c11
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr102131-4.c15
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr104152.c40
-rw-r--r--gcc/testsuite/gcc.target/aarch64/cpymem-q-reg_1.c4
-rw-r--r--gcc/testsuite/gcc.target/aarch64/spellcheck_1.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/spellcheck_2.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/spellcheck_3.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/spellcheck_7.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/vsqrt-1.c17
-rw-r--r--gcc/testsuite/gcc.target/aarch64/vsqrt-2.c28
-rw-r--r--gcc/testsuite/gcc.target/arm/stack-protector-7.c12
-rw-r--r--gcc/testsuite/gcc.target/arm/stack-protector-8.c7
-rw-r--r--gcc/testsuite/gcc.target/i386/pr104188.c70
-rw-r--r--gcc/testsuite/gcc.target/mips/fix-r4000-2.c4
-rw-r--r--gcc/testsuite/gcc.target/mips/fix-r4000-3.c6
-rw-r--r--gcc/testsuite/gcc.target/mips/fix-r4000-7.c4
-rw-r--r--gcc/testsuite/gcc.target/mips/fix-r4000-8.c6
-rw-r--r--gcc/testsuite/gcc.target/powerpc/builtins-4.c34
-rw-r--r--gcc/testsuite/gcc.target/powerpc/fold-vec-splat-floatdouble.c5
-rw-r--r--gcc/testsuite/gcc.target/riscv/arch-10.c2
-rw-r--r--gcc/testsuite/gcc.target/riscv/arch-12.c2
-rw-r--r--gcc/testsuite/gcc.target/riscv/arch-9.c2
-rw-r--r--gcc/testsuite/gcc.target/riscv/attribute-19.c2
-rw-r--r--gcc/testsuite/gcc.target/riscv/pr104140.c11
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/affinity-clause-3.f902
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/pr102621.f9012
-rw-r--r--gcc/testsuite/gfortran.dg/gomp/pr103695.f9018
-rw-r--r--gcc/testsuite/gfortran.dg/transfer_simplify_11.f902
-rw-r--r--gcc/testsuite/gfortran.dg/transfer_simplify_13.f9034
-rw-r--r--gcc/tree-ssa-loop-niter.cc49
-rw-r--r--gcc/tree-ssa-loop-unswitch.cc50
-rw-r--r--gcc/tree-ssa-math-opts.cc4
-rw-r--r--gcc/tree-ssa-threadbackward.cc4
-rw-r--r--gcc/tree-vect-slp.cc20
-rw-r--r--gcc/tree.def14
-rw-r--r--gcc/value-relation.cc45
-rw-r--r--gcc/value-relation.h3
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.
diff --git a/gcc/ira.cc b/gcc/ira.cc
index f294f03..e3b3c54 100644
--- a/gcc/ira.cc
+++ b/gcc/ira.cc
@@ -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 ();
diff --git a/gcc/ira.h b/gcc/ira.h
index c128273..d19e8cd 100644
--- a/gcc/ira.h
+++ b/gcc/ira.h
@@ -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);
}
diff --git a/gcc/lra.cc b/gcc/lra.cc
index 028d26a..5ef077c 100644
--- a/gcc/lra.cc
+++ b/gcc/lra.cc
@@ -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. */
diff --git a/gcc/lra.h b/gcc/lra.h
index 85713bb..4dd6cac 100644
--- a/gcc/lra.h
+++ b/gcc/lra.h
@@ -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
diff --git a/gcc/opts.h b/gcc/opts.h
index b876c51..a43ce66 100644
--- a/gcc/opts.h
+++ b/gcc/opts.h
@@ -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: