aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/ChangeLog5
-rwxr-xr-xcontrib/gcc-changelog/git_commit.py1
-rw-r--r--gcc/ChangeLog147
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/Makefile.in2
-rw-r--r--gcc/ada/ChangeLog4
-rw-r--r--gcc/ada/gcc-interface/trans.cc2
-rw-r--r--gcc/avoid-store-forwarding.cc100
-rw-r--r--gcc/calls.cc3
-rw-r--r--gcc/common/config/riscv/riscv-common.cc3
-rw-r--r--gcc/config/aarch64/aarch64-cores.def2
-rw-r--r--gcc/config/aarch64/aarch64-sve-builtins.cc3
-rw-r--r--gcc/config/aarch64/aarch64.cc37
-rw-r--r--gcc/config/aarch64/tuning_models/olympus.h210
-rw-r--r--gcc/config/avr/avr.cc19
-rw-r--r--gcc/config/gcn/gcn-opts.h2
-rw-r--r--gcc/config/gcn/gcn-valu.md4
-rw-r--r--gcc/config/gcn/gcn.cc89
-rw-r--r--gcc/config/gcn/gcn.md40
-rw-r--r--gcc/config/i386/i386.cc46
-rw-r--r--gcc/config/loongarch/loongarch.h2
-rw-r--r--gcc/config/nvptx/nvptx.opt45
-rw-r--r--gcc/config/riscv/gen-riscv-mcpu-texi.cc43
-rw-r--r--gcc/config/riscv/gen-riscv-mtune-texi.cc41
-rw-r--r--gcc/config/riscv/riscv-vector-costs.cc12
-rw-r--r--gcc/config/riscv/t-riscv37
-rw-r--r--gcc/config/rs6000/rs6000.cc16
-rw-r--r--gcc/config/xtensa/xtensa.cc46
-rw-r--r--gcc/diagnostics/changes.cc8
-rw-r--r--gcc/diagnostics/context.cc3
-rw-r--r--gcc/diagnostics/html-sink.cc3
-rw-r--r--gcc/diagnostics/output-spec.cc3
-rw-r--r--gcc/diagnostics/sarif-sink.cc3
-rw-r--r--gcc/doc/invoke.texi23
-rw-r--r--gcc/doc/riscv-mcpu.texi69
-rw-r--r--gcc/doc/riscv-mtune.texi59
-rw-r--r--gcc/fortran/ChangeLog23
-rw-r--r--gcc/fortran/trans-array.cc54
-rw-r--r--gcc/fortran/trans-expr.cc35
-rw-r--r--gcc/m2/gm2-compiler/M2GenGCC.mod5
-rw-r--r--gcc/m2/gm2-compiler/M2Range.mod2
-rw-r--r--gcc/m2/gm2-compiler/M2Students.def2
-rw-r--r--gcc/m2/gm2-compiler/M2Students.mod16
-rw-r--r--gcc/m2/gm2-compiler/P2SymBuild.mod2
-rw-r--r--gcc/m2/gm2-libs-iso/LowLong.mod10
-rw-r--r--gcc/m2/gm2-libs-iso/LowReal.mod14
-rw-r--r--gcc/m2/gm2-libs-iso/LowShort.mod14
-rw-r--r--gcc/m2/gm2-libs-iso/Processes.mod8
-rw-r--r--gcc/m2/gm2-libs-iso/RndFile.mod10
-rw-r--r--gcc/m2/gm2-libs/SCmdArgs.mod36
-rw-r--r--gcc/match.pd22
-rw-r--r--gcc/output.h6
-rw-r--r--gcc/simplify-rtx.cc75
-rw-r--r--gcc/testsuite/ChangeLog102
-rw-r--r--gcc/testsuite/c-c++-common/pr121159.c17
-rw-r--r--gcc/testsuite/g++.dg/modules/class-11_a.H4
-rw-r--r--gcc/testsuite/gcc.dg/plugin/must-tail-call-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/pr116906-1.c1
-rw-r--r--gcc/testsuite/gcc.dg/pr116906-2.c1
-rw-r--r--gcc/testsuite/gcc.dg/pr120660.c19
-rw-r--r--gcc/testsuite/gcc.dg/pr78185.c1
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr121236-1.c20
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/cswtch-7.c48
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr120687-1.c16
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr120687-2.c17
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr120687-3.c16
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-recurr-pr121256-2.c49
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-recurr-pr121256.c54
-rw-r--r--gcc/testsuite/gcc.target/aarch64/cmpbr.c40
-rw-r--r--gcc/testsuite/gcc.target/aarch64/saturating_arithmetic_1.c12
-rw-r--r--gcc/testsuite/gcc.target/aarch64/saturating_arithmetic_2.c8
-rw-r--r--gcc/testsuite/gcc.target/i386/pr119795.c26
-rw-r--r--gcc/testsuite/gcc.target/i386/pr121208-1a.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/pr121208-1b.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/pr121208-2a.c17
-rw-r--r--gcc/testsuite/gcc.target/i386/pr121208-2b.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/pr121208-3a.c17
-rw-r--r--gcc/testsuite/gcc.target/i386/pr121208-3b.c4
-rw-r--r--gcc/testsuite/gcc.target/nvptx/march-map=sm_100.c19
-rw-r--r--gcc/testsuite/gcc.target/nvptx/march-map=sm_100a.c19
-rw-r--r--gcc/testsuite/gcc.target/nvptx/march-map=sm_100f.c19
-rw-r--r--gcc/testsuite/gcc.target/nvptx/march-map=sm_101.c19
-rw-r--r--gcc/testsuite/gcc.target/nvptx/march-map=sm_101a.c19
-rw-r--r--gcc/testsuite/gcc.target/nvptx/march-map=sm_101f.c19
-rw-r--r--gcc/testsuite/gcc.target/nvptx/march-map=sm_103.c19
-rw-r--r--gcc/testsuite/gcc.target/nvptx/march-map=sm_103a.c19
-rw-r--r--gcc/testsuite/gcc.target/nvptx/march-map=sm_103f.c19
-rw-r--r--gcc/testsuite/gcc.target/nvptx/march-map=sm_120.c19
-rw-r--r--gcc/testsuite/gcc.target/nvptx/march-map=sm_120a.c19
-rw-r--r--gcc/testsuite/gcc.target/nvptx/march-map=sm_120f.c19
-rw-r--r--gcc/testsuite/gcc.target/nvptx/march-map=sm_121.c19
-rw-r--r--gcc/testsuite/gcc.target/nvptx/march-map=sm_121a.c19
-rw-r--r--gcc/testsuite/gcc.target/nvptx/march-map=sm_121f.c19
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-i16.c23
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-i32.c23
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-i64.c23
-rw-r--r--gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-i8.c23
-rw-r--r--gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-1-u16-from-u32.c11
-rw-r--r--gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-1-u8-from-u16.c11
-rw-r--r--gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-1-u8-from-u32.c11
-rw-r--r--gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-2-u16-from-u64.c11
-rw-r--r--gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-2-u32-from-u64.c11
-rw-r--r--gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-2-u8-from-u64.c11
-rw-r--r--gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u16-from-u32.c16
-rw-r--r--gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u16-from-u64.c2
-rw-r--r--gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u32-from-u64.c2
-rw-r--r--gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u8-from-u16.c16
-rw-r--r--gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u8-from-u32.c16
-rw-r--r--gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u8-from-u64.c2
-rw-r--r--gcc/testsuite/gfortran.dg/assign_13.f9025
-rw-r--r--gcc/testsuite/gfortran.dg/assign_14.f9024
-rw-r--r--gcc/testsuite/gm2/warnings/style/fail/badvarname.mod14
-rw-r--r--gcc/testsuite/gm2/warnings/style/fail/warnings-style-fail.exp44
-rw-r--r--gcc/tree-if-conv.cc60
-rw-r--r--gcc/tree-ssa-reassoc.cc10
-rw-r--r--gcc/tree-switch-conversion.cc11
-rw-r--r--gcc/tree-vect-data-refs.cc2
-rw-r--r--gcc/tree-vect-loop.cc85
-rw-r--r--gcc/tree-vect-patterns.cc1
-rw-r--r--gcc/tree-vect-slp.cc22
-rw-r--r--gcc/tree-vect-stmts.cc139
-rw-r--r--gcc/tree-vectorizer.cc1
-rw-r--r--gcc/tree-vectorizer.h66
-rw-r--r--gcc/varasm.cc50
-rw-r--r--gcc/vec.h4
-rw-r--r--libstdc++-v3/ChangeLog33
-rw-r--r--libstdc++-v3/include/bits/stl_iterator_base_funcs.h68
-rw-r--r--libstdc++-v3/include/debug/bitset11
-rw-r--r--libstdc++-v3/include/std/inplace_vector2
-rw-r--r--libstdc++-v3/include/std/mdspan17
-rw-r--r--libstdc++-v3/testsuite/23_containers/inplace_vector/erasure.cc26
-rw-r--r--libstdc++-v3/testsuite/23_containers/mdspan/accessors/generic.cc59
-rw-r--r--libstdc++-v3/testsuite/24_iterators/operations/cxx20_iterators.cc60
-rw-r--r--libstdc++-v3/testsuite/std/format/ranges/format_kind.cc4
134 files changed, 2814 insertions, 503 deletions
diff --git a/contrib/ChangeLog b/contrib/ChangeLog
index 7a92ede..f4f48e5 100644
--- a/contrib/ChangeLog
+++ b/contrib/ChangeLog
@@ -1,3 +1,8 @@
+2025-07-28 David Malcolm <dmalcolm@redhat.com>
+
+ * gcc-changelog/git_commit.py: Add "diagnostics" to bug
+ components.
+
2025-07-25 David Malcolm <dmalcolm@redhat.com>
* filter-clang-warnings.py: Update for move of
diff --git a/contrib/gcc-changelog/git_commit.py b/contrib/gcc-changelog/git_commit.py
index 80a3276..e0c46be 100755
--- a/contrib/gcc-changelog/git_commit.py
+++ b/contrib/gcc-changelog/git_commit.py
@@ -97,6 +97,7 @@ bug_components = {
'd',
'debug',
'demangler',
+ 'diagnostics',
'driver',
'fastjar',
'fortran',
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a3238a3..332776e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,150 @@
+2025-07-28 Georg-Johann Lay <avr@gjlay.de>
+
+ PR target/121277
+ * config/avr/avr.cc (avr_addr_space_convert): When converting
+ from generic AS to __flashx, don't set bit 23.
+ (avr_convert_to_type): Don't -Waddr-space-convert when NULL
+ is converted to __flashx or to __flash.
+
+2025-07-28 Andrew Pinski <quic_apinski@quicinc.com>
+
+ PR tree-optimization/121236
+ * tree-if-conv.cc (is_cond_scalar_reduction): Instead of phi argument,
+ pass bb and res of the phi.
+ (factor_out_operators): Add iterator for the phi. Remove the phi
+ if this is the first time. Return if we had removed the phi.
+ (predicate_scalar_phi): Add the phi iterator argument.
+ Update call to is_cond_scalar_reduction.
+ Update call to factor_out_operators and set the return value to true
+ when factor_out_operators returns true.
+ (predicate_all_scalar_phis): Don't remove the phi if predicate_scalar_phi
+ already removed it.
+
+2025-07-28 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/121208
+ * config/i386/i386.cc (ix86_tls_get_addr): Issue an error for
+ -mtls-dialect=gnu with no_caller_saved_registers attribute and
+ suggest -mtls-dialect=gnu2.
+
+2025-07-28 Mikael Pettersson <mikpelinux@gmail.com>
+
+ PR other/121260
+ * diagnostics/changes.cc: Correct nesting of namespaces
+ and #if CHECKING_P blocks.
+ * diagnostics/context.cc: Likewise.
+ * diagnostics/html-sink.cc: Likewise.
+ * diagnostics/output-spec.cc: Likewise.
+ * diagnostics/sarif-sink.cc: Likewise.
+
+2025-07-28 Tobias Burnus <tburnus@baylibre.com>
+
+ * config/nvptx/nvptx.opt (march-map=): Add sm_100{,f,a},
+ sm_101{,f,a}, sm_103{,a,f}, sm_120{,a,f} and sm_121{,f,a}.
+
+2025-07-28 Tobias Burnus <tburnus@baylibre.com>
+
+ * config/gcn/gcn.md (atomic_load, atomic_store, atomic_exchange):
+ Fix CDNA3 L2 cache write-back before atomic instructions.
+
+2025-07-28 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-stmts.cc (check_load_store_for_partial_vectors):
+ Make *gs_info const.
+ (vect_build_one_gather_load_call): Likewise.
+ (vect_build_one_scatter_store_call): Likewise.
+ (vect_get_gather_scatter_ops): Likewise.
+ (vect_get_strided_load_store_ops): Likewise.
+
+2025-07-28 Tobias Burnus <tburnus@baylibre.com>
+
+ * config/gcn/gcn.md (define_attr "vcmp"): Add with values
+ vcmp/vcmpx/no.
+ (*movbi, cstoredi4.., cstore<mode>4): Set it.
+ * config/gcn/gcn-valu.md (vec_cmp<mode>...): Likewise.
+ * config/gcn/gcn.cc (gcn_cmpx_insn_p): Remove.
+ (gcn_md_reorg): Add two new conditions for MI300.
+
+2025-07-28 Tobias Burnus <tburnus@baylibre.com>
+
+ * config/gcn/gcn-opts.h (enum hsaco_attr_type): Add comment
+ about 'sc0'.
+ * config/gcn/gcn.cc (gcn_md_reorg): Use gen_nops instead of gen_nop.
+ (print_operand_address): Document 'R' and 'V' in the
+ pre-function comment as well.
+ * config/gcn/gcn.md (nops): Add.
+
+2025-07-28 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/121256
+ * tree-vect-loop.cc (vectorizable_recurr): Build a correct
+ initialization vector for SLP_TREE_LANES > 1.
+
+2025-07-28 Richard Biener <rguenther@suse.de>
+
+ * tree-vectorizer.h (_slp_tree::type): Add.
+ (_slp_tree::u): Likewise.
+ (_stmt_vec_info::type): Remove.
+ (STMT_VINFO_TYPE): Likewise.
+ (SLP_TREE_TYPE): New.
+ * tree-vectorizer.cc (vec_info::new_stmt_vec_info): Do not
+ initialize type.
+ * tree-vect-slp.cc (_slp_tree::_slp_tree): Initialize type.
+ (vect_slp_analyze_node_operations): Adjust.
+ (vect_schedule_slp_node): Likewise.
+ * tree-vect-patterns.cc (vect_init_pattern_stmt): Do not
+ copy STMT_VINFO_TYPE.
+ * tree-vect-loop.cc: Set SLP_TREE_TYPE instead of
+ STMT_VINFO_TYPE everywhere.
+ (vect_create_loop_vinfo): Do not set STMT_VINFO_TYPE on
+ loop conditions.
+ * tree-vect-stmts.cc: Set SLP_TREE_TYPE instead of
+ STMT_VINFO_TYPE everywhere.
+ (vect_analyze_stmt): Adjust.
+ (vect_transform_stmt): Likewise.
+ * config/aarch64/aarch64.cc (aarch64_vector_costs::count_ops):
+ Access SLP_TREE_TYPE instead of STMT_VINFO_TYPE.
+ * config/i386/i386.cc (ix86_vector_costs::add_stmt_cost):
+ Remove non-SLP element-wise load/store matching.
+ * config/rs6000/rs6000.cc
+ (rs6000_cost_data::update_target_cost_per_stmt): Pass in
+ the SLP node. Use that to get at the memory access
+ kind and type.
+ (rs6000_cost_data::add_stmt_cost): Pass down SLP node.
+ * config/riscv/riscv-vector-costs.cc (variable_vectorized_p):
+ Use SLP_TREE_TYPE.
+ (costs::need_additional_vector_vars_p): Likewise.
+ (costs::update_local_live_ranges): Likewise.
+
+2025-07-28 Jennifer Schmitz <jschmitz@nvidia.com>
+ Dhruv Chawla <dhruvc@nvidia.com>
+
+ * config/aarch64/aarch64-cores.def (olympus): Use olympus tuning
+ model.
+ * config/aarch64/aarch64.cc: Include olympus.h.
+ * config/aarch64/tuning_models/olympus.h: New file.
+
+2025-07-28 Lulu Cheng <chenglulu@loongson.cn>
+
+ * config/loongarch/loongarch.h
+ (CASE_VECTOR_SHORTEN_MODE): Delete.
+
+2025-07-28 Takayuki 'January June' Suwa <jjsuwa_sys3175@yahoo.co.jp>
+
+ * config/xtensa/xtensa.cc (xtensa_is_insn_L32R_p):
+ Re-rewrite to more accurately capture insns that could be L32R machine
+ instructions wherever possible, and add comments that help understand
+ the intent of the process.
+
+2025-07-27 Pan Li <pan2.li@intel.com>
+
+ * config/riscv/riscv-v.cc (expand_vx_binary_vxrm_vec_vec_dup):
+ Add new case UNSPEC_VAADD.
+ (expand_vx_binary_vxrm_vec_dup_vec): Ditto.
+ * config/riscv/riscv.cc (riscv_rtx_costs): Ditto.
+ * config/riscv/vector-iterators.md: Add new case UNSPEC_VAADD to
+ iterator.
+
2025-07-27 Nathaniel Shead <nathanieloshead@gmail.com>
PR middle-end/120855
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index bb710d5..5d7eb78 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20250727
+20250729
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 7314a3b..d7d5cbe 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -3720,7 +3720,7 @@ TEXI_GCC_FILES = gcc.texi gcc-common.texi gcc-vers.texi frontends.texi \
contribute.texi compat.texi funding.texi gnu.texi gpl_v3.texi \
fdl.texi contrib.texi cppenv.texi cppopts.texi avr-mmcu.texi \
implement-c.texi implement-cxx.texi gcov-tool.texi gcov-dump.texi \
- lto-dump.texi riscv-ext.texi
+ lto-dump.texi riscv-ext.texi riscv-mcpu.texi riscv-mtune.texi
# we explicitly use $(srcdir)/doc/tm.texi here to avoid confusion with
# the generated tm.texi; the latter might have a more recent timestamp,
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index 6f6a782..821e3c0 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,7 @@
+2025-07-28 Marc PoulhiĂšs <poulhies@adacore.com>
+
+ * gcc-interface/trans.cc (gnat_to_gnu): Fix typo in comment.
+
2025-07-25 David Malcolm <dmalcolm@redhat.com>
* gcc-interface/misc.cc: Make
diff --git a/gcc/ada/gcc-interface/trans.cc b/gcc/ada/gcc-interface/trans.cc
index ef5ec75..fd1d39c 100644
--- a/gcc/ada/gcc-interface/trans.cc
+++ b/gcc/ada/gcc-interface/trans.cc
@@ -8753,7 +8753,7 @@ gnat_to_gnu (Node_Id gnat_node)
/* Set the location information on the result if it's not a simple name
or something that contains a simple name, for example a tag, because
- we don"t want all the references to get the location of the first use.
+ we don't want all the references to get the location of the first use.
Note that we may have no result if we tried to build a CALL_EXPR node
to a procedure with no side-effects and optimization is enabled. */
else if (kind != N_Identifier
diff --git a/gcc/avoid-store-forwarding.cc b/gcc/avoid-store-forwarding.cc
index 785efd2..1de6fd6 100644
--- a/gcc/avoid-store-forwarding.cc
+++ b/gcc/avoid-store-forwarding.cc
@@ -231,20 +231,39 @@ process_store_forwarding (vec<store_fwd_info> &stores, rtx_insn *load_insn,
int move_to_front = -1;
int total_cost = 0;
+ int base_offset_index = -1;
+
+ /* Find the last store that has the same offset the load, in the case that
+ we're eliminating the load. We will try to use it as a base register
+ to avoid bit inserts (see second loop below). We want the last one, as
+ it will be wider and we don't want to overwrite the base register if
+ there are many of them. */
+ if (load_elim)
+ {
+ FOR_EACH_VEC_ELT_REVERSE (stores, i, it)
+ {
+ const bool has_base_offset
+ = known_eq (poly_uint64 (it->offset),
+ subreg_size_lowpart_offset (MEM_SIZE (it->store_mem),
+ load_size));
+ if (has_base_offset)
+ {
+ base_offset_index = i;
+ break;
+ }
+ }
+ }
/* Check if we can emit bit insert instructions for all forwarded stores. */
FOR_EACH_VEC_ELT (stores, i, it)
{
it->mov_reg = gen_reg_rtx (GET_MODE (it->store_mem));
rtx_insn *insns = NULL;
- const bool has_base_offset
- = known_eq (poly_uint64 (it->offset),
- subreg_size_lowpart_offset (MEM_SIZE (it->store_mem),
- load_size));
-
- /* If we're eliminating the load then find the store with zero offset
- and use it as the base register to avoid a bit insert if possible. */
- if (load_elim && has_base_offset)
+
+ /* Check if this is a store with base offset, if we're eliminating the
+ load, and use it as the base register to avoid a bit insert if
+ possible. Load elimination is implied by base_offset_index != -1. */
+ if (i == (unsigned) base_offset_index)
{
start_sequence ();
@@ -437,9 +456,22 @@ store_forwarding_analyzer::avoid_store_forwarding (basic_block bb)
return;
auto_vec<store_fwd_info, 8> store_exprs;
+ auto_vec<rtx> store_exprs_del;
rtx_insn *insn;
unsigned int insn_cnt = 0;
+ /* We are iterating over the basic block's instructions detecting store
+ instructions. Upon reaching a load instruction, we check if any of the
+ previously detected stores could result in store forwarding. In that
+ case, we try to reorder the load and store instructions.
+ We skip this transformation when we encounter complex memory operations,
+ instructions that might throw an exception, instruction dependencies,
+ etc. This is done by clearing the vector of detected stores, while
+ keeping the removed stores in another vector. By doing so, we can check
+ if any of the removed stores operated on the load's address range, when
+ reaching a subsequent store that operates on the same address range,
+ as this would lead to incorrect values on the register that keeps the
+ loaded value. */
FOR_BB_INSNS (bb, insn)
{
if (!NONDEBUG_INSN_P (insn))
@@ -452,6 +484,10 @@ store_forwarding_analyzer::avoid_store_forwarding (basic_block bb)
if (!set || insn_could_throw_p (insn))
{
+ unsigned int i;
+ store_fwd_info *it;
+ FOR_EACH_VEC_ELT (store_exprs, i, it)
+ store_exprs_del.safe_push (it->store_mem);
store_exprs.truncate (0);
continue;
}
@@ -475,6 +511,10 @@ store_forwarding_analyzer::avoid_store_forwarding (basic_block bb)
|| (load_mem && (!MEM_SIZE_KNOWN_P (load_mem)
|| !MEM_SIZE (load_mem).is_constant ())))
{
+ unsigned int i;
+ store_fwd_info *it;
+ FOR_EACH_VEC_ELT (store_exprs, i, it)
+ store_exprs_del.safe_push (it->store_mem);
store_exprs.truncate (0);
continue;
}
@@ -526,6 +566,7 @@ store_forwarding_analyzer::avoid_store_forwarding (basic_block bb)
it->remove = true;
removed_count++;
remove_rest = true;
+ store_exprs_del.safe_push (it->store_mem);
}
}
}
@@ -565,23 +606,46 @@ store_forwarding_analyzer::avoid_store_forwarding (basic_block bb)
it->remove = true;
removed_count++;
remove_rest = true;
+ forwardings.truncate (0);
}
else if (is_store_forwarding (store_mem, load_mem, &off_val))
{
+ unsigned int j;
+ rtx *del_it;
+ bool same_range_as_removed = false;
+
+ /* Check if another store in the load's address range has
+ been deleted due to a constraint violation. In this case
+ we can't forward any other stores that operate in this
+ range, as it would lead to partial update of the register
+ that holds the loaded value. */
+ FOR_EACH_VEC_ELT (store_exprs_del, j, del_it)
+ {
+ rtx del_store_mem = *del_it;
+ same_range_as_removed
+ = is_store_forwarding (del_store_mem, load_mem, NULL);
+ if (same_range_as_removed)
+ break;
+ }
+
/* Check if moving this store after the load is legal. */
bool write_dep = false;
- for (unsigned int j = store_exprs.length () - 1; j != i; j--)
+ if (!same_range_as_removed)
{
- if (!store_exprs[j].forwarded
- && output_dependence (store_mem,
- store_exprs[j].store_mem))
+ unsigned int j = store_exprs.length () - 1;
+ for (; j != i; j--)
{
- write_dep = true;
- break;
+ if (!store_exprs[j].forwarded
+ && output_dependence (store_mem,
+ store_exprs[j].store_mem))
+ {
+ write_dep = true;
+ break;
+ }
}
}
- if (!write_dep)
+ if (!same_range_as_removed && !write_dep)
{
it->forwarded = true;
it->offset = off_val;
@@ -601,6 +665,7 @@ store_forwarding_analyzer::avoid_store_forwarding (basic_block bb)
it->remove = true;
removed_count++;
remove_rest = true;
+ forwardings.truncate (0);
}
}
@@ -608,9 +673,12 @@ store_forwarding_analyzer::avoid_store_forwarding (basic_block bb)
process_store_forwarding (forwardings, insn, load_mem);
}
+ /* Abort in case that we encounter a memory read/write that is not a
+ simple store/load, as we can't make safe assumptions about the
+ side-effects of this. */
if ((writes_mem && !is_simple_store)
|| (reads_mem && !is_simple_load))
- store_exprs.truncate (0);
+ return;
if (removed_count)
{
diff --git a/gcc/calls.cc b/gcc/calls.cc
index e16190c..2711c4e 100644
--- a/gcc/calls.cc
+++ b/gcc/calls.cc
@@ -2589,7 +2589,8 @@ can_implement_as_sibling_call_p (tree exp,
return false;
}
- if (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (addr))))
+ if (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (addr)))
+ && !CALL_EXPR_MUST_TAIL_CALL (exp))
{
maybe_complain_about_tail_call (exp, _("volatile function type"));
return false;
diff --git a/gcc/common/config/riscv/riscv-common.cc b/gcc/common/config/riscv/riscv-common.cc
index 82037a3..da3cb9f 100644
--- a/gcc/common/config/riscv/riscv-common.cc
+++ b/gcc/common/config/riscv/riscv-common.cc
@@ -1606,8 +1606,9 @@ bool
riscv_ext_is_subset (struct cl_target_option *opts,
struct cl_target_option *subset)
{
- for (const auto &[ext_name, ext_info] : riscv_ext_infos)
+ for (const auto &riscv_ext_info : riscv_ext_infos)
{
+ const auto &ext_info = riscv_ext_info.second;
if (ext_info.check_opts (opts) && !ext_info.check_opts (subset))
return false;
}
diff --git a/gcc/config/aarch64/aarch64-cores.def b/gcc/config/aarch64/aarch64-cores.def
index 8040409..6f11cc0 100644
--- a/gcc/config/aarch64/aarch64-cores.def
+++ b/gcc/config/aarch64/aarch64-cores.def
@@ -224,7 +224,7 @@ AARCH64_CORE("neoverse-v3ae", neoversev3ae, cortexa57, V9_2A, (SVE2_BITPERM, RNG
AARCH64_CORE("demeter", demeter, cortexa57, V9A, (I8MM, BF16, SVE2_BITPERM, RNG, MEMTAG, PROFILE), neoversev2, 0x41, 0xd4f, -1)
/* NVIDIA ('N') cores. */
-AARCH64_CORE("olympus", olympus, cortexa57, V9_2A, (SVE2_BITPERM, RNG, LS64, MEMTAG, PROFILE, FAMINMAX, FP8FMA, FP8DOT2, FP8DOT4, LUT, SVE2_AES, SVE2_SHA3, SVE2_SM4), neoversev3, 0x4e, 0x10, -1)
+AARCH64_CORE("olympus", olympus, cortexa57, V9_2A, (SVE2_BITPERM, RNG, LS64, MEMTAG, PROFILE, FAMINMAX, FP8FMA, FP8DOT2, FP8DOT4, LUT, SVE2_AES, SVE2_SHA3, SVE2_SM4), olympus, 0x4e, 0x10, -1)
/* Armv9-A big.LITTLE processors. */
AARCH64_CORE("gb10", gb10, cortexa57, V9_2A, (SVE2_BITPERM, SVE2_AES, SVE2_SHA3, SVE2_SM4, MEMTAG, PROFILE), cortexx925, 0x41, AARCH64_BIG_LITTLE (0xd85, 0xd87), -1)
diff --git a/gcc/config/aarch64/aarch64-sve-builtins.cc b/gcc/config/aarch64/aarch64-sve-builtins.cc
index 2b627a9..01833a8 100644
--- a/gcc/config/aarch64/aarch64-sve-builtins.cc
+++ b/gcc/config/aarch64/aarch64-sve-builtins.cc
@@ -4004,7 +4004,8 @@ rtx
function_expander::get_reg_target ()
{
machine_mode target_mode = result_mode ();
- if (!possible_target || GET_MODE (possible_target) != target_mode)
+ if (!possible_target
+ || !register_operand (possible_target, target_mode))
possible_target = gen_reg_rtx (target_mode);
return possible_target;
}
diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index 4d9d83d..a6d6bed 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -430,6 +430,7 @@ static const struct aarch64_flag_desc aarch64_tuning_flags[] =
#include "tuning_models/neoversev2.h"
#include "tuning_models/neoversev3.h"
#include "tuning_models/neoversev3ae.h"
+#include "tuning_models/olympus.h"
#include "tuning_models/a64fx.h"
#include "tuning_models/fujitsu_monaka.h"
@@ -17720,7 +17721,7 @@ aarch64_vector_costs::count_ops (unsigned int count, vect_cost_for_stmt kind,
{
if (gimple_vuse (SSA_NAME_DEF_STMT (offset)))
{
- if (STMT_VINFO_TYPE (stmt_info) == load_vec_info_type)
+ if (SLP_TREE_TYPE (node) == load_vec_info_type)
ops->loads += count - 1;
else
/* Stores want to count both the index to array and data to
@@ -31963,9 +31964,43 @@ aarch64_test_sysreg_encoding_clashes (void)
static void
aarch64_test_sve_folding ()
{
+ aarch64_target_switcher switcher (AARCH64_FL_SVE);
+
tree res = fold_unary (BIT_NOT_EXPR, ssizetype,
ssize_int (poly_int64 (1, 1)));
ASSERT_TRUE (operand_equal_p (res, ssize_int (poly_int64 (-2, -1))));
+
+ auto build_v16bi = [](bool a, bool b)
+ {
+ rtx_vector_builder builder (VNx16BImode, 2, 1);
+ builder.quick_push (a ? const1_rtx : const0_rtx);
+ builder.quick_push (b ? const1_rtx : const0_rtx);
+ return builder.build ();
+ };
+ rtx v16bi_10 = build_v16bi (1, 0);
+ rtx v16bi_01 = build_v16bi (0, 1);
+
+ for (auto mode : { VNx8BImode, VNx4BImode, VNx2BImode })
+ {
+ rtx reg = gen_rtx_REG (mode, LAST_VIRTUAL_REGISTER + 1);
+ rtx subreg = lowpart_subreg (VNx16BImode, reg, mode);
+ rtx and1 = simplify_gen_binary (AND, VNx16BImode, subreg, v16bi_10);
+ ASSERT_EQ (lowpart_subreg (mode, and1, VNx16BImode), reg);
+ rtx and0 = simplify_gen_binary (AND, VNx16BImode, subreg, v16bi_01);
+ ASSERT_EQ (lowpart_subreg (mode, and0, VNx16BImode), CONST0_RTX (mode));
+
+ rtx ior1 = simplify_gen_binary (IOR, VNx16BImode, subreg, v16bi_10);
+ ASSERT_EQ (lowpart_subreg (mode, ior1, VNx16BImode), CONSTM1_RTX (mode));
+ rtx ior0 = simplify_gen_binary (IOR, VNx16BImode, subreg, v16bi_01);
+ ASSERT_EQ (lowpart_subreg (mode, ior0, VNx16BImode), reg);
+
+ rtx xor1 = simplify_gen_binary (XOR, VNx16BImode, subreg, v16bi_10);
+ ASSERT_RTX_EQ (lowpart_subreg (mode, xor1, VNx16BImode),
+ lowpart_subreg (mode, gen_rtx_NOT (VNx16BImode, subreg),
+ VNx16BImode));
+ rtx xor0 = simplify_gen_binary (XOR, VNx16BImode, subreg, v16bi_01);
+ ASSERT_EQ (lowpart_subreg (mode, xor0, VNx16BImode), reg);
+ }
}
/* Run all target-specific selftests. */
diff --git a/gcc/config/aarch64/tuning_models/olympus.h b/gcc/config/aarch64/tuning_models/olympus.h
new file mode 100644
index 0000000..268789d
--- /dev/null
+++ b/gcc/config/aarch64/tuning_models/olympus.h
@@ -0,0 +1,210 @@
+/* Tuning model description for the NVIDIA Olympus core.
+ Copyright The GNU Toolchain Authors.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GCC is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING3. If not see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_AARCH64_H_OLYMPUS
+#define GCC_AARCH64_H_OLYMPUS
+
+#include "generic.h"
+
+static struct cpu_regmove_cost olympus_regmove_cost =
+{
+ 1, /* GP2GP */
+ /* Spilling to int<->fp instead of memory is recommended so set
+ realistic costs compared to memmov_cost. */
+ 3, /* GP2FP */
+ 3, /* FP2GP */
+ 2 /* FP2FP */
+};
+
+static advsimd_vec_cost olympus_advsimd_vector_cost =
+{
+ 2, /* int_stmt_cost */
+ 2, /* fp_stmt_cost */
+ 2, /* ld2_st2_permute_cost */
+ 2, /* ld3_st3_permute_cost */
+ 3, /* ld4_st4_permute_cost */
+ 2, /* permute_cost */
+ 5, /* reduc_i8_cost */
+ 3, /* reduc_i16_cost */
+ 3, /* reduc_i32_cost */
+ 2, /* reduc_i64_cost */
+ 4, /* reduc_f16_cost */
+ 4, /* reduc_f32_cost */
+ 4, /* reduc_f64_cost */
+ 2, /* store_elt_extra_cost */
+ 8, /* vec_to_scalar_cost */
+ 4, /* scalar_to_vec_cost */
+ 6, /* align_load_cost */
+ 6, /* unalign_load_cost */
+ 1, /* unalign_store_cost */
+ 1 /* store_cost */
+};
+
+static sve_vec_cost olympus_sve_vector_cost =
+{
+ {
+ 2, /* int_stmt_cost */
+ 2, /* fp_stmt_cost */
+ 2, /* ld2_st2_permute_cost */
+ 3, /* ld3_st3_permute_cost */
+ 3, /* ld4_st4_permute_cost */
+ 2, /* permute_cost */
+ 9, /* reduc_i8_cost */
+ 8, /* reduc_i16_cost */
+ 6, /* reduc_i32_cost */
+ 2, /* reduc_i64_cost */
+ 8, /* reduc_f16_cost */
+ 6, /* reduc_f32_cost */
+ 4, /* reduc_f64_cost */
+ 2, /* store_elt_extra_cost */
+ 8, /* vec_to_scalar_cost */
+ 4, /* scalar_to_vec_cost */
+ 4, /* align_load_cost */
+ 6, /* unalign_load_cost */
+ 1, /* unalign_store_cost */
+ 1 /* store_cost */
+ },
+ 3, /* clast_cost */
+ 10, /* fadda_f16_cost */
+ 6, /* fadda_f32_cost */
+ 4, /* fadda_f64_cost */
+ 14, /* gather_load_x32_cost */
+ 12, /* gather_load_x64_cost */
+ 42, /* gather_load_x32_init_cost */
+ 24, /* gather_load_x64_init_cost */
+ 1 /* scatter_store_elt_cost */
+};
+
+static aarch64_scalar_vec_issue_info olympus_scalar_issue_info =
+{
+ 4, /* loads_stores_per_cycle */
+ 2, /* stores_per_cycle */
+ 8, /* general_ops_per_cycle */
+ 0, /* fp_simd_load_general_ops */
+ 1 /* fp_simd_store_general_ops */
+};
+
+static aarch64_advsimd_vec_issue_info olympus_advsimd_issue_info =
+{
+ {
+ 3, /* loads_stores_per_cycle */
+ 2, /* stores_per_cycle */
+ 6, /* general_ops_per_cycle */
+ 0, /* fp_simd_load_general_ops */
+ 1 /* fp_simd_store_general_ops */
+ },
+ 2, /* ld2_st2_general_ops */
+ 2, /* ld3_st3_general_ops */
+ 3 /* ld4_st4_general_ops */
+};
+
+static aarch64_sve_vec_issue_info olympus_sve_issue_info =
+{
+ {
+ {
+ 3, /* loads_stores_per_cycle */
+ 2, /* stores_per_cycle */
+ 6, /* general_ops_per_cycle */
+ 0, /* fp_simd_load_general_ops */
+ 1 /* fp_simd_store_general_ops */
+ },
+ 2, /* ld2_st2_general_ops */
+ 2, /* ld3_st3_general_ops */
+ 3 /* ld4_st4_general_ops */
+ },
+ 2, /* pred_ops_per_cycle */
+ 1, /* while_pred_ops */
+ 0, /* int_cmp_pred_ops */
+ 0, /* fp_cmp_pred_ops */
+ 1, /* gather_scatter_pair_general_ops */
+ 1 /* gather_scatter_pair_pred_ops */
+};
+
+static aarch64_vec_issue_info olympus_vec_issue_info =
+{
+ &olympus_scalar_issue_info,
+ &olympus_advsimd_issue_info,
+ &olympus_sve_issue_info
+};
+
+/* Olympus costs for vector insn classes. */
+static struct cpu_vector_cost olympus_vector_cost =
+{
+ 1, /* scalar_int_stmt_cost */
+ 2, /* scalar_fp_stmt_cost */
+ 4, /* scalar_load_cost */
+ 1, /* scalar_store_cost */
+ 1, /* cond_taken_branch_cost */
+ 1, /* cond_not_taken_branch_cost */
+ &olympus_advsimd_vector_cost, /* advsimd */
+ &olympus_sve_vector_cost, /* sve */
+ &olympus_vec_issue_info /* issue_info */
+};
+
+/* Olympus prefetch settings (which disable prefetch). */
+static cpu_prefetch_tune olympus_prefetch_tune =
+{
+ 0, /* num_slots */
+ -1, /* l1_cache_size */
+ 64, /* l1_cache_line_size */
+ -1, /* l2_cache_size */
+ true, /* prefetch_dynamic_strides */
+ -1, /* minimum_stride */
+ -1 /* default_opt_level */
+};
+
+static struct tune_params olympus_tunings =
+{
+ &cortexa76_extra_costs,
+ &generic_armv9_a_addrcost_table,
+ &olympus_regmove_cost,
+ &olympus_vector_cost,
+ &generic_branch_cost,
+ &generic_approx_modes,
+ SVE_128, /* sve_width */
+ { 4, /* load_int. */
+ 1, /* store_int. */
+ 6, /* load_fp. */
+ 3, /* store_fp. */
+ 5, /* load_pred. */
+ 1 /* store_pred. */
+ }, /* memmov_cost. */
+ 10, /* issue_rate */
+ AARCH64_FUSE_NEOVERSE_BASE, /* fusible_ops */
+ "32:16", /* function_align. */
+ "4", /* jump_align. */
+ "32:16", /* loop_align. */
+ 8, /* int_reassoc_width. */
+ 6, /* fp_reassoc_width. */
+ 4, /* fma_reassoc_width. */
+ 6, /* vec_reassoc_width. */
+ 2, /* min_div_recip_mul_sf. */
+ 2, /* min_div_recip_mul_df. */
+ 0, /* max_case_values. */
+ tune_params::AUTOPREFETCHER_WEAK, /* autoprefetcher_model. */
+ (AARCH64_EXTRA_TUNE_BASE
+ | AARCH64_EXTRA_TUNE_CSE_SVE_VL_CONSTANTS
+ | AARCH64_EXTRA_TUNE_MATCHED_VECTOR_THROUGHPUT
+ | AARCH64_EXTRA_TUNE_AVOID_PRED_RMW), /* tune_flags. */
+ &olympus_prefetch_tune,
+ AARCH64_LDP_STP_POLICY_ALWAYS, /* ldp_policy_model. */
+ AARCH64_LDP_STP_POLICY_ALWAYS /* stp_policy_model. */
+};
+
+#endif /* GCC_AARCH64_H_OLYMPUS. */
diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc
index c469297..9468446 100644
--- a/gcc/config/avr/avr.cc
+++ b/gcc/config/avr/avr.cc
@@ -14984,10 +14984,11 @@ avr_addr_space_convert (rtx src, tree type_old, tree type_new)
/* Linearize memory: RAM has bit 23 set. When as_new = __flashx then
this is basically UB since __flashx mistreats RAM addresses, but there
- is no way to bail out. (Though -Waddr-space-convert will tell.) */
+ is no way to bail out. (Though -Waddr-space-convert will tell.)
+ ...but PR121277 is confusing, in particular when NULL is coming in. */
int msb = ADDR_SPACE_GENERIC_P (as_old)
- ? 0x80
+ ? as_new == ADDR_SPACE_MEMX ? 0x80 : 0x00
: avr_addrspace[as_old].segment;
src = force_reg (Pmode, src);
@@ -15085,10 +15086,16 @@ avr_convert_to_type (tree type, tree expr)
const char *name_old = avr_addrspace[as_old].name;
const char *name_new = avr_addrspace[as_new].name;
- warning (OPT_Waddr_space_convert,
- "conversion from address space %qs to address space %qs",
- ADDR_SPACE_GENERIC_P (as_old) ? "generic" : name_old,
- ADDR_SPACE_GENERIC_P (as_new) ? "generic" : name_new);
+ // Be relaxed when NULL is used, and when 0x0 stands for
+ // address 0x0.
+ bool nowarn = (expr == null_pointer_node
+ && (as_new == ADDR_SPACE_FLASHX
+ || as_new == ADDR_SPACE_FLASH));
+ if (!nowarn)
+ warning (OPT_Waddr_space_convert,
+ "conversion from address space %qs to address space %qs",
+ ADDR_SPACE_GENERIC_P (as_old) ? "generic" : name_old,
+ ADDR_SPACE_GENERIC_P (as_new) ? "generic" : name_new);
return fold_build1_loc (loc, ADDR_SPACE_CONVERT_EXPR, type, expr);
}
diff --git a/gcc/config/gcn/gcn-opts.h b/gcc/config/gcn/gcn-opts.h
index fe68678..0287400 100644
--- a/gcc/config/gcn/gcn-opts.h
+++ b/gcc/config/gcn/gcn-opts.h
@@ -92,6 +92,8 @@ enum hsaco_attr_type
/* Whether to use the 'globally coherent' (glc) or the 'scope' (sc0) flag
for non-scalar memory operations. The string starts on purpose with a space.
Note: for scalar memory operations (i.e. 's_...'), 'glc' is still used.
+ Note: on atomics, glc/sc0 denotes whether the pre-op operation should
+ be used.
CDNA3 also uses 'nt' instead of 'slc' and 'sc1' instead of 'scc'; however,
there is no non-scalar user so far. */
#define TARGET_GLC_NAME (TARGET_CDNA3 ? " sc0" : " glc")
diff --git a/gcc/config/gcn/gcn-valu.md b/gcc/config/gcn/gcn-valu.md
index 0994329..a34d2e3 100644
--- a/gcc/config/gcn/gcn-valu.md
+++ b/gcc/config/gcn/gcn-valu.md
@@ -3938,6 +3938,7 @@
v_cmpx%E1\t%2, %3
v_cmpx%E1\t%2, %3"
[(set_attr "type" "vopc,vopc,vopc,vopc,vop3a,vop3a,vopc,vopc")
+ (set_attr "vcmp" "vcmp,vcmp,vcmpx,vcmpx,vcmp,vcmp,vcmpx,vcmpx")
(set_attr "length" "4,8,4,8,8,8,4,8")
(set_attr "rdna" "*,*,no,no,*,*,yes,yes")])
@@ -3992,6 +3993,7 @@
v_cmpx%E1\t%2, %3
v_cmpx%E1\t%2, %3"
[(set_attr "type" "vopc,vopc,vopc,vopc,vop3a,vop3a,vopc,vopc")
+ (set_attr "vcmp" "vcmp,vcmp,vcmpx,vcmpx,vcmp,vcmp,vcmpx,vcmpx")
(set_attr "length" "4,8,4,8,8,8,4,8")
(set_attr "rdna" "*,*,no,no,*,*,yes,yes")])
@@ -4050,6 +4052,7 @@
v_cmpx%E1\t%2, %3
v_cmpx%E1\t%2, %3"
[(set_attr "type" "vopc,vopc,vopc,vopc,vop3a,vopc,vopc")
+ (set_attr "vcmp" "vcmp,vcmp,vcmpx,vcmpx,vcmp,vcmpx,vcmpx")
(set_attr "length" "4,8,4,8,8,4,8")
(set_attr "rdna" "*,*,no,no,*,yes,yes")])
@@ -4073,6 +4076,7 @@
v_cmpx%E1\t%2, %3
v_cmpx%E1\t%2, %3"
[(set_attr "type" "vopc,vopc,vopc,vopc,vop3a,vopc,vopc")
+ (set_attr "vcmp" "vcmp,vcmp,vcmpx,vcmpx,vcmp,vcmpx,vcmpx")
(set_attr "length" "4,8,4,8,8,4,8")
(set_attr "rdna" "*,*,no,no,*,yes,yes")])
diff --git a/gcc/config/gcn/gcn.cc b/gcc/config/gcn/gcn.cc
index 8959118..557568c 100644
--- a/gcc/config/gcn/gcn.cc
+++ b/gcc/config/gcn/gcn.cc
@@ -5792,42 +5792,6 @@ gcn_libc_has_function (enum function_class fn_class,
/* }}} */
/* {{{ md_reorg pass. */
-/* Identify V_CMPX from the "type" attribute;
- note: this will also match 'v_cmp %E1 vcc'. */
-
-static bool
-gcn_cmpx_insn_p (attr_type type)
-{
- switch (type)
- {
- case TYPE_VOPC:
- return true;
- case TYPE_MUBUF:
- case TYPE_MTBUF:
- case TYPE_FLAT:
- case TYPE_VOP3P_MAI:
- case TYPE_UNKNOWN:
- case TYPE_SOP1:
- case TYPE_SOP2:
- case TYPE_SOPK:
- case TYPE_SOPC:
- case TYPE_SOPP:
- case TYPE_SMEM:
- case TYPE_DS:
- case TYPE_VOP2:
- case TYPE_VOP1:
- case TYPE_VOP3A:
- case TYPE_VOP3B:
- case TYPE_VOP_SDWA:
- case TYPE_VOP_DPP:
- case TYPE_MULT:
- case TYPE_VMULT:
- return false;
- }
- gcc_unreachable ();
- return false;
-}
-
/* Identify VMEM instructions from their "type" attribute. */
static bool
@@ -6356,19 +6320,59 @@ gcn_md_reorg (void)
reg_class_contents[(int)VCC_CONDITIONAL_REG])))
nops_rqd = ivccwait - prev_insn->age;
+ /* NOTE: The following condition for adding wait state exists, but
+ GCC does not access the special registers using their SGPR#.
+ Thus, no action is required here. The following wait-state
+ condition exists at least for VEGA/gfx900+ to CDNA3:
+ Mixed use of VCC: alias vs. SGPR# - v_readlane,
+ v_readfirstlane, v_cmp, v_add_*i/u, v_sub_*i/u, v_div_*scale
+ followed by VALU reads VCC as constant requires 1 wait state.
+ (As carry-in, it requires none.)
+ [VCC can be accessed by name or logical SGPR that holds it.] */
+
+ /* Testing indicates that CDNA3 requires an s_nop between
+ e.g. 'v_cmp_eq_u64 vcc, v[4:5], v[8:9]' and 'v_mov_b32 v0, vcc_lo'.
+ Thus: add it between v_cmp writing VCC and VALU read of VCC. */
+ if (TARGET_CDNA3_NOPS
+ && (prev_insn->age + nops_rqd) < 1
+ && iunit == UNIT_VECTOR
+ && (hard_reg_set_intersect_p
+ (depregs, reg_class_contents[(int)VCC_CONDITIONAL_REG]))
+ && get_attr_vcmp (prev_insn->insn) == VCMP_VCMP)
+ nops_rqd = 1 - prev_insn->age;
+
+ /* CDNA3: VALU writes SGPR/VCC: v_readlane, v_readfirstlane, v_cmp,
+ v_add_*i/u, v_sub_*i/u, v_div_*scale - followed by:
+ - VALU reads SGPR as constant requires 1 waite state
+ - VALU reads SGPR as carry-in requires no waite state
+ - v_readlane/v_writelane reads SGPR as lane select requires 4 wait
+ states. */
+ if (TARGET_CDNA3_NOPS
+ && (prev_insn->age + nops_rqd) < 4
+ && iunit == UNIT_VECTOR
+ && prev_insn->unit == UNIT_VECTOR
+ && hard_reg_set_intersect_p
+ (depregs, reg_class_contents[(int) SGPR_SRC_REGS]))
+ {
+ if (get_attr_laneselect (insn) != LANESELECT_NO)
+ nops_rqd = 4 - prev_insn->age;
+ else if ((prev_insn->age + nops_rqd) < 1)
+ nops_rqd = 1 - prev_insn->age;
+ }
+
/* CDNA3: v_cmpx followed by
- V_readlane, v_readfirstlane, v_writelane requires 4 wait states
- VALU reads EXEC as constant requires 2 wait states
- other VALU requires no wait state */
if (TARGET_CDNA3_NOPS
&& (prev_insn->age + nops_rqd) < 4
- && gcn_cmpx_insn_p (prev_insn->type)
+ && get_attr_vcmp (prev_insn->insn) == VCMP_VCMPX
&& get_attr_laneselect (insn) != LANESELECT_NO)
nops_rqd = 4 - prev_insn->age;
else if (TARGET_CDNA3_NOPS
&& (prev_insn->age + nops_rqd) < 2
&& iunit == UNIT_VECTOR
- && gcn_cmpx_insn_p (prev_insn->type)
+ && get_attr_vcmp (prev_insn->insn) == VCMP_VCMPX
&& TEST_HARD_REG_BIT (ireads, EXECZ_REG))
nops_rqd = 2 - prev_insn->age;
@@ -6436,8 +6440,8 @@ gcn_md_reorg (void)
}
/* Insert the required number of NOPs. */
- for (int i = nops_rqd; i > 0; i--)
- emit_insn_after (gen_nop (), last_insn);
+ if (nops_rqd > 0)
+ emit_insn_after (gen_nops (GEN_INT (nops_rqd-1)), last_insn);
/* Age the previous instructions. We can also ignore writes to
registers subsequently overwritten. */
@@ -7283,6 +7287,11 @@ print_operand_address (FILE *file, rtx mem)
H - print second part of a multi-reg value (high-part of 2-reg value)
J - print third part of a multi-reg value
K - print fourth part of a multi-reg value
+ R Print a scalar register number as an integer. Temporary hack.
+ V - Print a vector register number as an integer. Temporary hack.
+
+ Additionally, the standard builtin c, n, a, and l exist; see gccint's
+ "Output Templates and Operand Substitution" for details.
*/
void
diff --git a/gcc/config/gcn/gcn.md b/gcc/config/gcn/gcn.md
index fad42e6..4130cf6 100644
--- a/gcc/config/gcn/gcn.md
+++ b/gcc/config/gcn/gcn.md
@@ -324,6 +324,11 @@
"store,storex34,load,atomic,atomicwait,cmpswapx2,no"
(const_string "no"))
+; Identify v_cmp and v_cmpx instructions for "Manually Inserted Wait State"
+; handling.
+
+(define_attr "vcmp" "vcmp,vcmpx,no" (const_string "no"))
+
; Identify instructions that require "Manually Inserted Wait State" if
; a previous instruction writes to VCC. The number gives the number of NOPs.
@@ -424,6 +429,15 @@
"s_nop\t0x0"
[(set_attr "type" "sopp")])
+; Variant of 'nop' that accepts a count argument.
+; s_nop accepts 0x0 to 0xf for 1 to 16 nops; however,
+; as %0 prints decimals, only 0 to 9 (= 1 to 10 nops) can be used.
+(define_insn "nops"
+ [(match_operand 0 "const_int_operand")]
+ ""
+ "s_nop\t0x%0"
+ [(set_attr "type" "sopp")])
+
; FIXME: What should the value of the immediate be? Zero is disallowed, so
; pick 1 for now.
(define_insn "trap"
@@ -566,6 +580,7 @@
[(set_attr "type" "sop1,vop1,vop3a,sopk,vopc,mult,smem,smem,smem,flat,flat,
flat,flat,flat,flat")
(set_attr "flatmemaccess" "*,*,*,*,*,*,*,*,*,load,load,store,load,load,store")
+ (set_attr "vcmp" "*,*,*,*,vcmp,*,*,*,*,*,*,*,*,*,*")
(set_attr "exec" "*,*,none,*,*,*,*,*,*,*,*,*,*,*,*")
(set_attr "length" "4,4,4,4,4,8,12,12,12,12,12,12,12,12,12")
(set_attr "xnack" "*,*,*,*,*,*,off,on,*,off,on,*,off,on,*")
@@ -1089,6 +1104,7 @@
s_cmp%D1\t%2, %3
v_cmp%E1\tvcc, %2, %3"
[(set_attr "type" "sopc,vopc")
+ (set_attr "vcmp" "vcmp")
(set_attr "length" "8")])
(define_insn "cstoredi4_vector"
@@ -1099,6 +1115,7 @@
""
"v_cmp%E1\tvcc, %2, %3"
[(set_attr "type" "vopc")
+ (set_attr "vcmp" "vcmp")
(set_attr "length" "8")])
(define_expand "cbranchdi4"
@@ -1125,6 +1142,7 @@
""
"v_cmp%E1\tvcc, %2, %3"
[(set_attr "type" "vopc")
+ (set_attr "vcmp" "vcmp")
(set_attr "length" "8")])
(define_expand "cbranch<mode>4"
@@ -2165,7 +2183,7 @@
? "buffer_gl1_inv\;buffer_gl0_inv\;flat_load%o0\t%0, %A1%O1 %G1\;"
"s_waitcnt\t0\;buffer_gl1_inv\;buffer_gl0_inv"
: TARGET_TARGET_SC_CACHE
- ? "buffer_inv sc1\;flat_load%o0\t%0, %A1%O1 %G1\;"
+ ? "buffer_wbl2\tsc0\;s_waitcnt\t0\;flat_load%o0\t%0, %A1%O1 %G1\;"
"s_waitcnt\t0\;buffer_inv sc1"
: "buffer_wbinvl1_vol\;flat_load%o0\t%0, %A1%O1 %G1\;"
"s_waitcnt\t0\;buffer_wbinvl1_vol");
@@ -2177,7 +2195,7 @@
? "buffer_gl1_inv\;buffer_gl0_inv\;global_load%o0\t%0, %A1%O1 %G1\;"
"s_waitcnt\tvmcnt(0)\;buffer_gl1_inv\;buffer_gl0_inv"
: TARGET_TARGET_SC_CACHE
- ? "buffer_inv sc1\;global_load%o0\t%0, %A1%O1 %G1\;"
+ ? "buffer_wbl2\tsc0\;s_waitcnt\tvmcnt(0)\;global_load%o0\t%0, %A1%O1 %G1\;"
"s_waitcnt\tvmcnt(0)\;buffer_inv sc1"
: "buffer_wbinvl1_vol\;global_load%o0\t%0, %A1%O1 %G1\;"
"s_waitcnt\tvmcnt(0)\;buffer_wbinvl1_vol");
@@ -2224,7 +2242,7 @@
: TARGET_WBINVL1_CACHE
? "buffer_wbinvl1_vol\;flat_store%o1\t%A0, %1%O0 %G1"
: TARGET_TARGET_SC_CACHE
- ? "buffer_inv sc1\;flat_store%o1\t%A0, %1%O0 %G1"
+ ? "buffer_wbl2\tsc0\;s_waitcnt\t0\;flat_store%o1\t%A0, %1%O0 %G1"
: "error: cache architectire unspecified");
case 2:
return (TARGET_GLn_CACHE
@@ -2232,7 +2250,7 @@
: TARGET_WBINVL1_CACHE
? "buffer_wbinvl1_vol\;global_store%o1\t%A0, %1%O0 %G1"
: TARGET_TARGET_SC_CACHE
- ? "buffer_inv sc1\;global_store%o1\t%A0, %1%O0 %G1"
+ ? "buffer_wbl2\tsc0\;s_waitcnt\tvmcnt(0)\;global_store%o1\t%A0, %1%O0 %G1"
: "error: cache architecture unspecified");
}
break;
@@ -2252,7 +2270,8 @@
? "buffer_wbinvl1_vol\;flat_store%o1\t%A0, %1%O0 %G1\;"
"s_waitcnt\t0\;buffer_wbinvl1_vol"
: TARGET_TARGET_SC_CACHE
- ? "buffer_inv sc1\;flat_store%o1\t%A0, %1%O0 %G1\;"
+ ? "buffer_wbl2\tsc0\;s_waitcnt\t0\;"
+ "flat_store%o1\t%A0, %1%O0 %G1\;"
"s_waitcnt\t0\;buffer_inv sc1"
: "error: cache architecture unspecified");
case 2:
@@ -2263,7 +2282,8 @@
? "buffer_wbinvl1_vol\;global_store%o1\t%A0, %1%O0 %G1\;"
"s_waitcnt\tvmcnt(0)\;buffer_wbinvl1_vol"
: TARGET_TARGET_SC_CACHE
- ? "buffer_inv sc1\;global_store%o1\t%A0, %1%O0 %G1\;"
+ ? "buffer_wbl2\tsc0\;s_waitcnt\tvmcnt(0)\;"
+ "global_store%o1\t%A0, %1%O0 %G1\;"
"s_waitcnt\tvmcnt(0)\;buffer_inv sc1"
: "error: cache architecture unspecified");
}
@@ -2347,7 +2367,7 @@
? "buffer_wbinvl1_vol\;flat_atomic_swap<X>\t%0, %1, %2 %G1\;"
"s_waitcnt\t0"
: TARGET_TARGET_SC_CACHE
- ? "buffer_inv sc1\;flat_atomic_swap<X>\t%0, %1, %2 %G1\;"
+ ? "buffer_wbl2\tsc0\;s_waitcnt\t0\;flat_atomic_swap<X>\t%0, %1, %2 %G1\;"
"s_waitcnt\t0"
: "error: cache architecture unspecified");
case 2:
@@ -2360,7 +2380,7 @@
"global_atomic_swap<X>\t%0, %A1, %2%O1 %G1\;"
"s_waitcnt\tvmcnt(0)"
: TARGET_TARGET_SC_CACHE
- ? "buffer_inv sc1\;"
+ ? "buffer_wbl2\tsc0\;s_waitcnt\tvmcnt(0)\;"
"global_atomic_swap<X>\t%0, %A1, %2%O1 %G1\;"
"s_waitcnt\tvmcnt(0)"
: "error: cache architecture unspecified");
@@ -2382,7 +2402,7 @@
? "buffer_wbinvl1_vol\;flat_atomic_swap<X>\t%0, %1, %2 %G1\;"
"s_waitcnt\t0\;buffer_wbinvl1_vol"
: TARGET_TARGET_SC_CACHE
- ? "buffer_inv sc1\;flat_atomic_swap<X>\t%0, %1, %2 %G1\;"
+ ? "buffer_wbl2\tsc0\;s_waitcnt\t0\;flat_atomic_swap<X>\t%0, %1, %2 %G1\;"
"s_waitcnt\t0\;buffer_inv sc1"
: "error: cache architecture unspecified");
case 2:
@@ -2395,7 +2415,7 @@
"global_atomic_swap<X>\t%0, %A1, %2%O1 %G1\;"
"s_waitcnt\tvmcnt(0)\;buffer_wbinvl1_vol"
: TARGET_TARGET_SC_CACHE
- ? "buffer_inv sc1\;"
+ ? "buffer_wbl2\tsc0\;s_waitcnt\tvmcnt(0)\;"
"global_atomic_swap<X>\t%0, %A1, %2%O1 %G1\;"
"s_waitcnt\tvmcnt(0)\;buffer_inv sc1"
: "error: cache architecture unspecified");
diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index 4682db85..0f0acae 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -12442,6 +12442,28 @@ static GTY(()) rtx ix86_tls_symbol;
static rtx
ix86_tls_get_addr (void)
{
+ if (cfun->machine->call_saved_registers
+ == TYPE_NO_CALLER_SAVED_REGISTERS)
+ {
+ /* __tls_get_addr doesn't preserve vector registers. When a
+ function with no_caller_saved_registers attribute calls
+ __tls_get_addr, YMM and ZMM registers will be clobbered.
+ Issue an error and suggest -mtls-dialect=gnu2 in this case. */
+ if (cfun->machine->func_type == TYPE_NORMAL)
+ error (G_("%<-mtls-dialect=gnu2%> must be used with a function"
+ " with the %<no_caller_saved_registers%> attribute"));
+ else
+ error (cfun->machine->func_type == TYPE_EXCEPTION
+ ? G_("%<-mtls-dialect=gnu2%> must be used with an"
+ " exception service routine")
+ : G_("%<-mtls-dialect=gnu2%> must be used with an"
+ " interrupt service routine"));
+ /* Don't issue the same error twice. */
+ cfun->machine->func_type = TYPE_NORMAL;
+ cfun->machine->call_saved_registers
+ = TYPE_DEFAULT_CALL_SAVED_REGISTERS;
+ }
+
if (!ix86_tls_symbol)
{
const char *sym
@@ -26128,23 +26150,15 @@ ix86_vector_costs::add_stmt_cost (int count, vect_cost_for_stmt kind,
(AGU and load ports). Try to account for this by scaling the
construction cost by the number of elements involved. */
if ((kind == vec_construct || kind == vec_to_scalar)
- && ((stmt_info
- && (STMT_VINFO_TYPE (stmt_info) == load_vec_info_type
- || STMT_VINFO_TYPE (stmt_info) == store_vec_info_type)
- && ((STMT_VINFO_MEMORY_ACCESS_TYPE (stmt_info) == VMAT_ELEMENTWISE
- && (TREE_CODE (DR_STEP (STMT_VINFO_DATA_REF (stmt_info)))
+ && ((node
+ && (((SLP_TREE_MEMORY_ACCESS_TYPE (node) == VMAT_ELEMENTWISE
+ || (SLP_TREE_MEMORY_ACCESS_TYPE (node) == VMAT_STRIDED_SLP
+ && SLP_TREE_LANES (node) == 1))
+ && (TREE_CODE (DR_STEP (STMT_VINFO_DATA_REF
+ (SLP_TREE_REPRESENTATIVE (node))))
!= INTEGER_CST))
- || (STMT_VINFO_MEMORY_ACCESS_TYPE (stmt_info)
- == VMAT_GATHER_SCATTER)))
- || (node
- && (((SLP_TREE_MEMORY_ACCESS_TYPE (node) == VMAT_ELEMENTWISE
- || (SLP_TREE_MEMORY_ACCESS_TYPE (node) == VMAT_STRIDED_SLP
- && SLP_TREE_LANES (node) == 1))
- && (TREE_CODE (DR_STEP (STMT_VINFO_DATA_REF
- (SLP_TREE_REPRESENTATIVE (node))))
- != INTEGER_CST))
- || (SLP_TREE_MEMORY_ACCESS_TYPE (node)
- == VMAT_GATHER_SCATTER)))))
+ || (SLP_TREE_MEMORY_ACCESS_TYPE (node)
+ == VMAT_GATHER_SCATTER)))))
{
stmt_cost = ix86_builtin_vectorization_cost (kind, vectype, misalign);
stmt_cost *= (TYPE_VECTOR_SUBPARTS (vectype) + 1);
diff --git a/gcc/config/loongarch/loongarch.h b/gcc/config/loongarch/loongarch.h
index d897763..5fc8665 100644
--- a/gcc/config/loongarch/loongarch.h
+++ b/gcc/config/loongarch/loongarch.h
@@ -823,8 +823,6 @@ typedef struct {
#define CASE_VECTOR_MODE Pmode
-#define CASE_VECTOR_SHORTEN_MODE(MIN, MAX, BODY) Pmode
-
/* Define this as 1 if `char' should by default be signed; else as 0. */
#ifndef DEFAULT_SIGNED_CHAR
#define DEFAULT_SIGNED_CHAR 1
diff --git a/gcc/config/nvptx/nvptx.opt b/gcc/config/nvptx/nvptx.opt
index d326ca4..9796839 100644
--- a/gcc/config/nvptx/nvptx.opt
+++ b/gcc/config/nvptx/nvptx.opt
@@ -120,6 +120,51 @@ Target RejectNegative Alias(misa=,sm_89)
march-map=sm_90a
Target RejectNegative Alias(misa=,sm_89)
+march-map=sm_100
+Target RejectNegative Alias(misa=,sm_89)
+
+march-map=sm_100f
+Target RejectNegative Alias(misa=,sm_89)
+
+march-map=sm_100a
+Target RejectNegative Alias(misa=,sm_89)
+
+march-map=sm_101
+Target RejectNegative Alias(misa=,sm_89)
+
+march-map=sm_101f
+Target RejectNegative Alias(misa=,sm_89)
+
+march-map=sm_101a
+Target RejectNegative Alias(misa=,sm_89)
+
+march-map=sm_103
+Target RejectNegative Alias(misa=,sm_89)
+
+march-map=sm_103f
+Target RejectNegative Alias(misa=,sm_89)
+
+march-map=sm_103a
+Target RejectNegative Alias(misa=,sm_89)
+
+march-map=sm_120
+Target RejectNegative Alias(misa=,sm_89)
+
+march-map=sm_120f
+Target RejectNegative Alias(misa=,sm_89)
+
+march-map=sm_120a
+Target RejectNegative Alias(misa=,sm_89)
+
+march-map=sm_121
+Target RejectNegative Alias(misa=,sm_89)
+
+march-map=sm_121f
+Target RejectNegative Alias(misa=,sm_89)
+
+march-map=sm_121a
+Target RejectNegative Alias(misa=,sm_89)
+
Enum
Name(ptx_version) Type(enum ptx_version)
Known PTX ISA versions (for use with the -mptx= option):
diff --git a/gcc/config/riscv/gen-riscv-mcpu-texi.cc b/gcc/config/riscv/gen-riscv-mcpu-texi.cc
new file mode 100644
index 0000000..9681438
--- /dev/null
+++ b/gcc/config/riscv/gen-riscv-mcpu-texi.cc
@@ -0,0 +1,43 @@
+#include <string>
+#include <vector>
+#include <stdio.h>
+
+int
+main ()
+{
+ puts ("@c Copyright (C) 2025 Free Software Foundation, Inc.");
+ puts ("@c This is part of the GCC manual.");
+ puts ("@c For copying conditions, see the file gcc/doc/include/fdl.texi.");
+ puts ("");
+ puts ("@c This file is generated automatically using");
+ puts ("@c gcc/config/riscv/gen-riscv-mcpu-texi.cc from:");
+ puts ("@c gcc/config/riscv/riscv-cores.def");
+ puts ("");
+ puts ("@c Please *DO NOT* edit manually.");
+ puts ("");
+ puts ("@samp{Core Name}");
+ puts ("");
+ puts ("@opindex mcpu");
+ puts ("@item -mcpu=@var{processor-string}");
+ puts ("Use architecture of and optimize the output for the given processor, specified");
+ puts ("by particular CPU name. Permissible values for this option are:");
+ puts ("");
+ puts ("");
+
+ std::vector<std::string> coreNames;
+
+#define RISCV_CORE(CORE_NAME, ARCH, MICRO_ARCH) \
+ coreNames.push_back (CORE_NAME);
+#include "riscv-cores.def"
+#undef RISCV_CORE
+
+ for (size_t i = 0; i < coreNames.size(); ++i) {
+ if (i == coreNames.size() - 1) {
+ printf("@samp{%s}.\n", coreNames[i].c_str());
+ } else {
+ printf("@samp{%s},\n\n", coreNames[i].c_str());
+ }
+ }
+
+ return 0;
+}
diff --git a/gcc/config/riscv/gen-riscv-mtune-texi.cc b/gcc/config/riscv/gen-riscv-mtune-texi.cc
new file mode 100644
index 0000000..1bdfe2a
--- /dev/null
+++ b/gcc/config/riscv/gen-riscv-mtune-texi.cc
@@ -0,0 +1,41 @@
+#include <string>
+#include <vector>
+#include <stdio.h>
+
+int
+main ()
+{
+ puts ("@c Copyright (C) 2025 Free Software Foundation, Inc.");
+ puts ("@c This is part of the GCC manual.");
+ puts ("@c For copying conditions, see the file gcc/doc/include/fdl.texi.");
+ puts ("");
+ puts ("@c This file is generated automatically using");
+ puts ("@c gcc/config/riscv/gen-riscv-mtune-texi.cc from:");
+ puts ("@c gcc/config/riscv/riscv-cores.def");
+ puts ("");
+ puts ("@c Please *DO NOT* edit manually.");
+ puts ("");
+ puts ("@samp{Tune Name}");
+ puts ("");
+ puts ("@opindex mtune");
+ puts ("@item -mtune=@var{processor-string}");
+ puts ("Optimize the output for the given processor, specified by microarchitecture or");
+ puts ("particular CPU name. Permissible values for this option are:");
+ puts ("");
+ puts ("");
+
+ std::vector<std::string> tuneNames;
+
+#define RISCV_TUNE(TUNE_NAME, PIPELINE_MODEL, TUNE_INFO) \
+ tuneNames.push_back (TUNE_NAME);
+#include "riscv-cores.def"
+#undef RISCV_TUNE
+
+ for (size_t i = 0; i < tuneNames.size(); ++i) {
+ printf("@samp{%s},\n\n", tuneNames[i].c_str());
+ }
+
+ puts ("and all valid options for @option{-mcpu=}.");
+
+ return 0;
+}
diff --git a/gcc/config/riscv/riscv-vector-costs.cc b/gcc/config/riscv/riscv-vector-costs.cc
index df924fa..1c6bc25 100644
--- a/gcc/config/riscv/riscv-vector-costs.cc
+++ b/gcc/config/riscv/riscv-vector-costs.cc
@@ -275,13 +275,13 @@ loop_invariant_op_p (class loop *loop,
/* Return true if the variable should be counted into liveness. */
static bool
variable_vectorized_p (class loop *loop, stmt_vec_info stmt_info,
- slp_tree node ATTRIBUTE_UNUSED, tree var, bool lhs_p)
+ slp_tree node, tree var, bool lhs_p)
{
if (!var)
return false;
gimple *stmt = STMT_VINFO_STMT (stmt_info);
stmt_info = vect_stmt_to_vectorize (stmt_info);
- enum stmt_vec_info_type type = STMT_VINFO_TYPE (stmt_info);
+ enum stmt_vec_info_type type = SLP_TREE_TYPE (node);
if (is_gimple_call (stmt) && gimple_call_internal_p (stmt))
{
if (gimple_call_internal_fn (stmt) == IFN_MASK_STORE
@@ -602,9 +602,9 @@ get_store_value (gimple *stmt)
/* Return true if additional vector vars needed. */
bool
costs::need_additional_vector_vars_p (stmt_vec_info stmt_info,
- slp_tree node ATTRIBUTE_UNUSED)
+ slp_tree node)
{
- enum stmt_vec_info_type type = STMT_VINFO_TYPE (stmt_info);
+ enum stmt_vec_info_type type = SLP_TREE_TYPE (node);
if (type == load_vec_info_type || type == store_vec_info_type)
{
if (STMT_VINFO_GATHER_SCATTER_P (stmt_info)
@@ -694,7 +694,7 @@ costs::update_local_live_ranges (
if (!node)
continue;
- if (STMT_VINFO_TYPE (stmt_info) == undef_vec_info_type)
+ if (SLP_TREE_TYPE (*node) == undef_vec_info_type)
continue;
for (j = 0; j < gimple_phi_num_args (phi); j++)
@@ -773,7 +773,7 @@ costs::update_local_live_ranges (
slp_tree *node = vinfo_slp_map.get (stmt_info);
if (!node)
continue;
- enum stmt_vec_info_type type = STMT_VINFO_TYPE (stmt_info);
+ enum stmt_vec_info_type type = SLP_TREE_TYPE (*node);
if (need_additional_vector_vars_p (stmt_info, *node))
{
/* For non-adjacent load/store STMT, we will potentially
diff --git a/gcc/config/riscv/t-riscv b/gcc/config/riscv/t-riscv
index 7aac56a..a7eaa8b 100644
--- a/gcc/config/riscv/t-riscv
+++ b/gcc/config/riscv/t-riscv
@@ -229,8 +229,41 @@ s-riscv-ext.texi: build/gen-riscv-ext-texi$(build_exeext)
$(SHELL) $(srcdir)/../move-if-change tmp-riscv-ext.texi $(srcdir)/doc/riscv-ext.texi
$(STAMP) s-riscv-ext.texi
-# Run `riscv-regen' after you changed or added anything from riscv-ext*.def
+RISCV_CORES_DEFS = \
+ $(srcdir)/config/riscv/riscv-cores.def
+
+build/gen-riscv-mtune-texi.o: $(srcdir)/config/riscv/gen-riscv-mtune-texi.cc \
+ $(RISCV_CORES_DEFS)
+ $(CXX_FOR_BUILD) $(CXXFLAGS_FOR_BUILD) -c $< -o $@
+
+build/gen-riscv-mcpu-texi.o: $(srcdir)/config/riscv/gen-riscv-mcpu-texi.cc \
+ $(RISCV_CORES_DEFS)
+ $(CXX_FOR_BUILD) $(CXXFLAGS_FOR_BUILD) -c $< -o $@
+
+build/gen-riscv-mtune-texi$(build_exeext): build/gen-riscv-mtune-texi.o
+ $(LINKER_FOR_BUILD) $(BUILD_LINKERFLAGS) $(BUILD_LDFLAGS) -o $@ $<
+
+build/gen-riscv-mcpu-texi$(build_exeext): build/gen-riscv-mcpu-texi.o
+ $(LINKER_FOR_BUILD) $(BUILD_LINKERFLAGS) $(BUILD_LDFLAGS) -o $@ $<
+
+$(srcdir)/doc/riscv-mtune.texi: $(RISCV_CORES_DEFS)
+$(srcdir)/doc/riscv-mtune.texi: s-riscv-mtune.texi ; @true
+
+$(srcdir)/doc/riscv-mcpu.texi: $(RISCV_CORES_DEFS)
+$(srcdir)/doc/riscv-mcpu.texi: s-riscv-mcpu.texi ; @true
+
+s-riscv-mtune.texi: build/gen-riscv-mtune-texi$(build_exeext)
+ $(RUN_GEN) build/gen-riscv-mtune-texi$(build_exeext) > tmp-riscv-mtune.texi
+ $(SHELL) $(srcdir)/../move-if-change tmp-riscv-mtune.texi $(srcdir)/doc/riscv-mtune.texi
+ $(STAMP) s-riscv-mtune.texi
+
+s-riscv-mcpu.texi: build/gen-riscv-mcpu-texi$(build_exeext)
+ $(RUN_GEN) build/gen-riscv-mcpu-texi$(build_exeext) > tmp-riscv-mcpu.texi
+ $(SHELL) $(srcdir)/../move-if-change tmp-riscv-mcpu.texi $(srcdir)/doc/riscv-mcpu.texi
+ $(STAMP) s-riscv-mcpu.texi
+
+# Run `riscv-regen' after you changed or added anything from riscv-ext*.def and riscv-cores*.def
.PHONY: riscv-regen
-riscv-regen: s-riscv-ext.texi s-riscv-ext.opt
+riscv-regen: s-riscv-ext.texi s-riscv-ext.opt s-riscv-mtune.texi s-riscv-mcpu.texi
diff --git a/gcc/config/rs6000/rs6000.cc b/gcc/config/rs6000/rs6000.cc
index 16227e5..1c60695 100644
--- a/gcc/config/rs6000/rs6000.cc
+++ b/gcc/config/rs6000/rs6000.cc
@@ -5174,6 +5174,7 @@ public:
protected:
void update_target_cost_per_stmt (vect_cost_for_stmt, stmt_vec_info,
+ slp_tree node,
vect_cost_model_location, unsigned int);
void density_test (loop_vec_info);
void adjust_vect_cost_per_loop (loop_vec_info);
@@ -5321,6 +5322,7 @@ rs6000_adjust_vect_cost_per_stmt (enum vect_cost_for_stmt kind,
void
rs6000_cost_data::update_target_cost_per_stmt (vect_cost_for_stmt kind,
stmt_vec_info stmt_info,
+ slp_tree node,
vect_cost_model_location where,
unsigned int orig_count)
{
@@ -5381,12 +5383,12 @@ rs6000_cost_data::update_target_cost_per_stmt (vect_cost_for_stmt kind,
or may not need to apply. When finalizing the cost of the loop,
the extra penalty is applied when the load density heuristics
are satisfied. */
- if (kind == vec_construct && stmt_info
- && STMT_VINFO_TYPE (stmt_info) == load_vec_info_type
- && (STMT_VINFO_MEMORY_ACCESS_TYPE (stmt_info) == VMAT_ELEMENTWISE
- || STMT_VINFO_MEMORY_ACCESS_TYPE (stmt_info) == VMAT_STRIDED_SLP))
+ if (kind == vec_construct && node
+ && SLP_TREE_TYPE (node) == load_vec_info_type
+ && (SLP_TREE_MEMORY_ACCESS_TYPE (node) == VMAT_ELEMENTWISE
+ || SLP_TREE_MEMORY_ACCESS_TYPE (node) == VMAT_STRIDED_SLP))
{
- tree vectype = STMT_VINFO_VECTYPE (stmt_info);
+ tree vectype = SLP_TREE_VECTYPE (node);
unsigned int nunits = vect_nunits_for_cost (vectype);
/* As PR103702 shows, it's possible that vectorizer wants to do
costings for only one unit here, it's no need to do any
@@ -5415,7 +5417,7 @@ rs6000_cost_data::update_target_cost_per_stmt (vect_cost_for_stmt kind,
unsigned
rs6000_cost_data::add_stmt_cost (int count, vect_cost_for_stmt kind,
- stmt_vec_info stmt_info, slp_tree,
+ stmt_vec_info stmt_info, slp_tree node,
tree vectype, int misalign,
vect_cost_model_location where)
{
@@ -5433,7 +5435,7 @@ rs6000_cost_data::add_stmt_cost (int count, vect_cost_for_stmt kind,
retval = adjust_cost_for_freq (stmt_info, where, count * stmt_cost);
m_costs[where] += retval;
- update_target_cost_per_stmt (kind, stmt_info, where, orig_count);
+ update_target_cost_per_stmt (kind, stmt_info, node, where, orig_count);
}
return retval;
diff --git a/gcc/config/xtensa/xtensa.cc b/gcc/config/xtensa/xtensa.cc
index 02554c5..d75cba4 100644
--- a/gcc/config/xtensa/xtensa.cc
+++ b/gcc/config/xtensa/xtensa.cc
@@ -4702,25 +4702,49 @@ static bool
xtensa_is_insn_L32R_p (const rtx_insn *insn)
{
rtx pat, dest, src;
+ machine_mode mode;
- /* "PATTERN (insn)" can be used without checking, see insn_cost()
- in gcc/rtlanal.cc. */
+ /* RTX insns that are not "(set (reg) ...)" cannot become L32R instructions:
+ - it is permitted to apply PATTERN() to the insn without validation.
+ See insn_cost() in gcc/rtlanal.cc.
+ - it is used register_operand() instead of REG() to identify things that
+ don't look like REGs but will eventually become so as well. */
if (GET_CODE (pat = PATTERN (insn)) != SET
|| ! register_operand (dest = SET_DEST (pat), VOIDmode))
return false;
+ /* If the source is a reference to a literal pool entry, then the insn
+ obviously corresponds to an L32R instruction. */
if (constantpool_mem_p (src = SET_SRC (pat)))
return true;
- /* Return true if:
- - CONST16 instruction is not configured, and
- - the source is some constant, and also
- - negation of "the source is integer and fits into the immediate
- field". */
- return (!TARGET_CONST16
- && CONSTANT_P (src)
- && ! ((GET_MODE (dest) == SImode || GET_MODE (dest) == HImode)
- && CONST_INT_P (src) && xtensa_simm12b (INTVAL (src))));
+ /* Similarly, an insn whose source is not a constant obviously does not
+ correspond to L32R. */
+ if (! CONSTANT_P (src))
+ return false;
+
+ /* If the source is a CONST_INT whose value fits into signed 12 bits, then
+ the insn corresponds to a MOVI instruction (rather than an L32R one),
+ regardless of the configuration of TARGET_CONST16 or
+ TARGET_AUTOLITPOOLS. Note that the destination register can be non-
+ SImode. */
+ if (((mode = GET_MODE (dest)) == SImode
+ || mode == HImode || mode == SFmode)
+ && CONST_INT_P (src) && xtensa_simm12b (INTVAL (src)))
+ return false;
+
+ /* If TARGET_CONST16 is configured, constants of the remaining forms
+ correspond to pairs of CONST16 instructions, not L32R. */
+ if (TARGET_CONST16)
+ return false;
+
+ /* The last remaining form of constant is one of the following:
+ - CONST_INTs with large values
+ - floating-point constants
+ - symbolic constants
+ and is all handled by a relaxed MOVI instruction, which is later
+ converted to an L32R instruction by the assembler. */
+ return true;
}
/* Compute a relative costs of RTL insns. This is necessary in order to
diff --git a/gcc/diagnostics/changes.cc b/gcc/diagnostics/changes.cc
index 290d602..e1caab0 100644
--- a/gcc/diagnostics/changes.cc
+++ b/gcc/diagnostics/changes.cc
@@ -1850,8 +1850,13 @@ run_all_tests ()
}
} // namespace diagnostics::changes::selftest
+
+#endif /* CHECKING_P */
+
} // namespace diagnostics::changes
+#if CHECKING_P
+
namespace selftest { // diagnostics::selftest
/* Run all of the selftests within this file. */
@@ -1863,6 +1868,7 @@ changes_cc_tests ()
}
} // namespace selftest
-} // namespace diagnostics
#endif /* CHECKING_P */
+
+} // namespace diagnostics
diff --git a/gcc/diagnostics/context.cc b/gcc/diagnostics/context.cc
index 0dbc148..85f7d2a 100644
--- a/gcc/diagnostics/context.cc
+++ b/gcc/diagnostics/context.cc
@@ -2130,10 +2130,11 @@ context_cc_tests ()
}
} // namespace diagnostics::selftest
-} // namespace diagnostics
#endif /* #if CHECKING_P */
+} // namespace diagnostics
+
#if __GNUC__ >= 10
# pragma GCC diagnostic pop
#endif
diff --git a/gcc/diagnostics/html-sink.cc b/gcc/diagnostics/html-sink.cc
index 07e7187..13d6309 100644
--- a/gcc/diagnostics/html-sink.cc
+++ b/gcc/diagnostics/html-sink.cc
@@ -1702,6 +1702,7 @@ html_sink_cc_tests ()
}
} // namespace selftest
-} // namespace diagnostics
#endif /* CHECKING_P */
+
+} // namespace diagnostics
diff --git a/gcc/diagnostics/output-spec.cc b/gcc/diagnostics/output-spec.cc
index 08128a9..83f128c 100644
--- a/gcc/diagnostics/output-spec.cc
+++ b/gcc/diagnostics/output-spec.cc
@@ -846,6 +846,7 @@ output_spec_cc_tests ()
}
} // namespace diagnostics::selftest
-} // namespace diagnostics
#endif /* #if CHECKING_P */
+
+} // namespace diagnostics
diff --git a/gcc/diagnostics/sarif-sink.cc b/gcc/diagnostics/sarif-sink.cc
index 05c0a8e..4738ae9 100644
--- a/gcc/diagnostics/sarif-sink.cc
+++ b/gcc/diagnostics/sarif-sink.cc
@@ -5072,6 +5072,7 @@ sarif_sink_cc_tests ()
}
} // namespace diagnostics::selftest
-} // namespace diagnostics
#endif /* CHECKING_P */
+
+} // namespace diagnostics
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 0980230..e442a9c 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -31370,31 +31370,14 @@ When the RISC-V specifications define an extension as depending on other
extensions, GCC will implicitly add the dependent extensions to the enabled
extension set if they weren't added explicitly.
-@opindex mcpu
-@item -mcpu=@var{processor-string}
-Use architecture of and optimize the output for the given processor, specified
-by particular CPU name.
-Permissible values for this option are: @samp{mips-p8700}, @samp{sifive-e20},
-@samp{sifive-e21}, @samp{sifive-e24}, @samp{sifive-e31}, @samp{sifive-e34},
-@samp{sifive-e76}, @samp{sifive-s21}, @samp{sifive-s51}, @samp{sifive-s54},
-@samp{sifive-s76}, @samp{sifive-u54}, @samp{sifive-u74}, @samp{sifive-x280},
-@samp{sifive-xp450}, @samp{sifive-x670}, @samp{thead-c906}, @samp{tt-ascalon-d8},
-@samp{xiangshan-nanhu}, @samp{xiangshan-kunminghu}, @samp{xt-c908}, @samp{xt-c908v},
-@samp{xt-c910}, @samp{xt-c910v2}, @samp{xt-c920}, @samp{xt-c920v2}.
+@include riscv-mcpu.texi
Note that @option{-mcpu} does not override @option{-march} or @option{-mtune}.
-@opindex mtune
-@item -mtune=@var{processor-string}
-Optimize the output for the given processor, specified by microarchitecture or
-particular CPU name. Permissible values for this option are:
-@samp{generic-ooo}, @samp{mips-p8700}, @samp{rocket}, @samp{sifive-3-series},
-@samp{sifive-5-series}, @samp{sifive-7-series}, @samp{size},
-@samp{sifive-p400-series}, @samp{sifive-p600-series}, and all valid options for
-@option{-mcpu=}.
+@include riscv-mtune.texi
When @option{-mtune=} is not specified, use the setting from @option{-mcpu},
-the default is @samp{rocket} if both are not specified.
+the default is @samp{generic} if both are not specified.
The @samp{size} choice is not intended for use by end-users. This is used
when @option{-Os} is specified. It overrides the instruction cost info
diff --git a/gcc/doc/riscv-mcpu.texi b/gcc/doc/riscv-mcpu.texi
new file mode 100644
index 0000000..6753e51
--- /dev/null
+++ b/gcc/doc/riscv-mcpu.texi
@@ -0,0 +1,69 @@
+@c Copyright (C) 2025 Free Software Foundation, Inc.
+@c This is part of the GCC manual.
+@c For copying conditions, see the file gcc/doc/include/fdl.texi.
+
+@c This file is generated automatically using
+@c gcc/config/riscv/gen-riscv-mcpu-texi.cc from:
+@c gcc/config/riscv/riscv-cores.def
+
+@c Please *DO NOT* edit manually.
+
+@samp{Core Name}
+
+@opindex mcpu
+@item -mcpu=@var{processor-string}
+Use architecture of and optimize the output for the given processor, specified
+by particular CPU name. Permissible values for this option are:
+
+
+@samp{sifive-e20},
+
+@samp{sifive-e21},
+
+@samp{sifive-e24},
+
+@samp{sifive-e31},
+
+@samp{sifive-e34},
+
+@samp{sifive-e76},
+
+@samp{sifive-s21},
+
+@samp{sifive-s51},
+
+@samp{sifive-s54},
+
+@samp{sifive-s76},
+
+@samp{sifive-u54},
+
+@samp{sifive-u74},
+
+@samp{sifive-x280},
+
+@samp{sifive-p450},
+
+@samp{sifive-p670},
+
+@samp{thead-c906},
+
+@samp{xt-c908},
+
+@samp{xt-c908v},
+
+@samp{xt-c910},
+
+@samp{xt-c910v2},
+
+@samp{xt-c920},
+
+@samp{xt-c920v2},
+
+@samp{tt-ascalon-d8},
+
+@samp{xiangshan-nanhu},
+
+@samp{xiangshan-kunminghu},
+
+@samp{mips-p8700}.
diff --git a/gcc/doc/riscv-mtune.texi b/gcc/doc/riscv-mtune.texi
new file mode 100644
index 0000000..a2a4d3e
--- /dev/null
+++ b/gcc/doc/riscv-mtune.texi
@@ -0,0 +1,59 @@
+@c Copyright (C) 2025 Free Software Foundation, Inc.
+@c This is part of the GCC manual.
+@c For copying conditions, see the file gcc/doc/include/fdl.texi.
+
+@c This file is generated automatically using
+@c gcc/config/riscv/gen-riscv-mtune-texi.cc from:
+@c gcc/config/riscv/riscv-cores.def
+
+@c Please *DO NOT* edit manually.
+
+@samp{Tune Name}
+
+@opindex mtune
+@item -mtune=@var{processor-string}
+Optimize the output for the given processor, specified by microarchitecture or
+particular CPU name. Permissible values for this option are:
+
+
+@samp{generic},
+
+@samp{rocket},
+
+@samp{sifive-3-series},
+
+@samp{sifive-5-series},
+
+@samp{sifive-7-series},
+
+@samp{sifive-p400-series},
+
+@samp{sifive-p600-series},
+
+@samp{tt-ascalon-d8},
+
+@samp{thead-c906},
+
+@samp{xt-c908},
+
+@samp{xt-c908v},
+
+@samp{xt-c910},
+
+@samp{xt-c910v2},
+
+@samp{xt-c920},
+
+@samp{xt-c920v2},
+
+@samp{xiangshan-nanhu},
+
+@samp{xiangshan-kunminghu},
+
+@samp{generic-ooo},
+
+@samp{size},
+
+@samp{mips-p8700},
+
+and all valid options for @option{-mcpu=}.
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 4c7e8d1..52bd14c 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,26 @@
+2025-07-27 Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/121185
+ * trans-expr.cc (gfc_trans_assignment_1): Use the same condition
+ to set the is_alloc_lhs flag and to decide to generate
+ reallocation code. Add explicit call to gfc_fix_class_refs
+ before evaluating the condition.
+
+2025-07-27 Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/121185
+ * trans-array.cc (set_factored_descriptor_value): Also trigger
+ the saving of the previously selected reference on encountering
+ an INDIRECT_REF. Extract the saving code...
+ (save_ref): ... here as a new function.
+
+2025-07-27 Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/121185
+ * trans-expr.cc (gfc_get_class_from_expr): Give up class
+ container lookup on the second COMPONENT_REF after an array
+ descriptor.
+
2025-07-25 David Malcolm <dmalcolm@redhat.com>
* error.cc: Make diagnostics::context::m_source_printing private.
diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc
index fffa6db..6b759d1 100644
--- a/gcc/fortran/trans-array.cc
+++ b/gcc/fortran/trans-array.cc
@@ -3478,6 +3478,29 @@ substitute_subexpr_in_expr (tree target, tree replacement, tree expr)
}
+/* Save REF to a fresh variable in all of REPLACEMENT_ROOTS, appending extra
+ code to CODE. Before returning, add REF to REPLACEMENT_ROOTS and clear
+ REF. */
+
+static void
+save_ref (tree &code, tree &ref, vec<tree> &replacement_roots)
+{
+ stmtblock_t tmp_block;
+ gfc_init_block (&tmp_block);
+ tree var = gfc_evaluate_now (ref, &tmp_block);
+ gfc_add_expr_to_block (&tmp_block, code);
+ code = gfc_finish_block (&tmp_block);
+
+ unsigned i;
+ tree repl_root;
+ FOR_EACH_VEC_ELT (replacement_roots, i, repl_root)
+ substitute_subexpr_in_expr (ref, var, repl_root);
+
+ replacement_roots.safe_push (ref);
+ ref = NULL_TREE;
+}
+
+
/* Save the descriptor reference VALUE to storage pointed by DESC_PTR. Before
that, try to factor subexpressions of VALUE to variables, adding extra code
to BLOCK.
@@ -3492,11 +3515,8 @@ set_factored_descriptor_value (tree *desc_ptr, tree value, stmtblock_t *block)
/* As the reference is processed from outer to inner, variable definitions
will be generated in reversed order, so can't be put directly in BLOCK.
We use TMP_BLOCK instead. */
- stmtblock_t tmp_block;
tree accumulated_code = NULL_TREE;
- gfc_init_block (&tmp_block);
-
/* The current candidate to factoring. */
tree saveable_ref = NULL_TREE;
@@ -3526,8 +3546,18 @@ set_factored_descriptor_value (tree *desc_ptr, tree value, stmtblock_t *block)
if (!maybe_reallocatable)
{
+ if (saveable_ref != NULL_TREE && saveable_ref != data_ref)
+ {
+ /* A reference worth saving has been seen, and now the pointer
+ to the current reference is also worth saving. If the
+ previous reference to save wasn't the current one, do save
+ it now. Otherwise drop it as we prefer saving the
+ pointer. */
+ save_ref (accumulated_code, saveable_ref, replacement_roots);
+ }
+
/* Don't evaluate the pointer to a variable yet; do it only if the
- variable would be significantly more simple than the reference
+ variable would be significantly more simple than the reference
it replaces. That is if the reference contains anything
different from NOPs, COMPONENTs and DECLs. */
saveable_ref = next_ref;
@@ -3552,20 +3582,8 @@ set_factored_descriptor_value (tree *desc_ptr, tree value, stmtblock_t *block)
}
if (saveable_ref != NULL_TREE)
- {
- /* We have seen a reference worth saving. Do it now. */
- tree var = gfc_evaluate_now (saveable_ref, &tmp_block);
- gfc_add_expr_to_block (&tmp_block, accumulated_code);
- accumulated_code = gfc_finish_block (&tmp_block);
-
- unsigned i;
- tree repl_root;
- FOR_EACH_VEC_ELT (replacement_roots, i, repl_root)
- substitute_subexpr_in_expr (saveable_ref, var, repl_root);
-
- replacement_roots.safe_push (saveable_ref);
- saveable_ref = NULL_TREE;
- }
+ /* We have seen a reference worth saving. Do it now. */
+ save_ref (accumulated_code, saveable_ref, replacement_roots);
if (TREE_CODE (data_ref) != ARRAY_REF)
break;
diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index 7c76215..0db7ba3 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -714,6 +714,8 @@ gfc_get_class_from_expr (tree expr)
{
tree tmp;
tree type;
+ bool array_descr_found = false;
+ bool comp_after_descr_found = false;
for (tmp = expr; tmp; tmp = TREE_OPERAND (tmp, 0))
{
@@ -725,6 +727,8 @@ gfc_get_class_from_expr (tree expr)
{
if (GFC_CLASS_TYPE_P (type))
return tmp;
+ if (GFC_DESCRIPTOR_TYPE_P (type))
+ array_descr_found = true;
if (type != TYPE_CANONICAL (type))
type = TYPE_CANONICAL (type);
else
@@ -732,6 +736,23 @@ gfc_get_class_from_expr (tree expr)
}
if (VAR_P (tmp) || TREE_CODE (tmp) == PARM_DECL)
break;
+
+ /* Avoid walking up the reference chain too far. For class arrays, the
+ array descriptor is a direct component (through a pointer) of the class
+ container. So there is exactly one COMPONENT_REF between a class
+ container and its child array descriptor. After seeing an array
+ descriptor, we can give up on the second COMPONENT_REF we see, if no
+ class container was found until that point. */
+ if (array_descr_found)
+ {
+ if (comp_after_descr_found)
+ {
+ if (TREE_CODE (tmp) == COMPONENT_REF)
+ return NULL_TREE;
+ }
+ else if (TREE_CODE (tmp) == COMPONENT_REF)
+ comp_after_descr_found = true;
+ }
}
if (POINTER_TYPE_P (TREE_TYPE (tmp)))
@@ -12871,9 +12892,16 @@ gfc_trans_assignment_1 (gfc_expr * expr1, gfc_expr * expr2, bool init_flag,
gfc_init_se (&lse, NULL);
gfc_init_se (&rse, NULL);
+ gfc_fix_class_refs (expr1);
+
+ realloc_flag = flag_realloc_lhs
+ && gfc_is_reallocatable_lhs (expr1)
+ && expr2->rank
+ && !is_runtime_conformable (expr1, expr2);
+
/* Walk the lhs. */
lss = gfc_walk_expr (expr1);
- if (gfc_is_reallocatable_lhs (expr1))
+ if (realloc_flag)
{
lss->no_bounds_check = 1;
lss->is_alloc_lhs = 1;
@@ -12924,11 +12952,6 @@ gfc_trans_assignment_1 (gfc_expr * expr1, gfc_expr * expr2, bool init_flag,
assoc_assign = is_assoc_assign (expr1, expr2);
- realloc_flag = flag_realloc_lhs
- && gfc_is_reallocatable_lhs (expr1)
- && expr2->rank
- && !is_runtime_conformable (expr1, expr2);
-
/* Only analyze the expressions for coarray properties, when in coarray-lib
mode. Avoid false-positive uninitialized diagnostics with initializing
the codimension flag unconditionally. */
diff --git a/gcc/m2/gm2-compiler/M2GenGCC.mod b/gcc/m2/gm2-compiler/M2GenGCC.mod
index 4a9ced3..2507c53 100644
--- a/gcc/m2/gm2-compiler/M2GenGCC.mod
+++ b/gcc/m2/gm2-compiler/M2GenGCC.mod
@@ -2903,9 +2903,6 @@ END CheckStop ;
*)
PROCEDURE FoldBecomes (p: WalkAction; bb: BasicBlock; quad: CARDINAL) ;
-VAR
- op : QuadOperator ;
- des, op2, expr: CARDINAL ;
BEGIN
IF DeclaredOperandsBecomes (p, quad)
THEN
@@ -8154,8 +8151,6 @@ VAR
rightpos,
typepos,
indrxpos : CARDINAL ;
- length,
- newstr : tree ;
location : location_t ;
BEGIN
GetQuadOtok (quad, indrxpos, op, left, type, right,
diff --git a/gcc/m2/gm2-compiler/M2Range.mod b/gcc/m2/gm2-compiler/M2Range.mod
index dcac2ba..f1516d3 100644
--- a/gcc/m2/gm2-compiler/M2Range.mod
+++ b/gcc/m2/gm2-compiler/M2Range.mod
@@ -1869,14 +1869,12 @@ END FoldTypeAssign ;
PROCEDURE FoldTypeIndrX (q: CARDINAL; tokenNo: CARDINAL; des, expr: CARDINAL; r: CARDINAL) ;
VAR
- desType,
exprType: CARDINAL ;
BEGIN
(* Need to skip over a variable or temporary in des and expr so
long as expr is not a procedure. In the case of des = *expr,
both expr and des will be variables due to the property of
indirection. *)
- desType := GetType (des) ;
IF IsProcedure (expr)
THEN
(* Must not GetType for a procedure as it gives the return type. *)
diff --git a/gcc/m2/gm2-compiler/M2Students.def b/gcc/m2/gm2-compiler/M2Students.def
index 7d67a0a..a3ecdcd 100644
--- a/gcc/m2/gm2-compiler/M2Students.def
+++ b/gcc/m2/gm2-compiler/M2Students.def
@@ -39,7 +39,7 @@ EXPORT QUALIFIED StudentVariableCheck, CheckVariableAgainstKeyword ;
as a keyword except for its case.
*)
-PROCEDURE CheckVariableAgainstKeyword (name: Name) ;
+PROCEDURE CheckVariableAgainstKeyword (tok: CARDINAL; name: Name) ;
(*
diff --git a/gcc/m2/gm2-compiler/M2Students.mod b/gcc/m2/gm2-compiler/M2Students.mod
index e539eb0..3df160a 100644
--- a/gcc/m2/gm2-compiler/M2Students.mod
+++ b/gcc/m2/gm2-compiler/M2Students.mod
@@ -25,7 +25,7 @@ IMPLEMENTATION MODULE M2Students ;
FROM SymbolTable IMPORT FinalSymbol, IsVar, IsProcedure, IsModule,
GetMainModule, IsType, NulSym, IsRecord, GetSymName, GetNth, GetNthProcedure, GetDeclaredMod, NoOfParam ;
FROM NameKey IMPORT GetKey, WriteKey, MakeKey, IsSameExcludingCase, NulName, makekey, KeyToCharStar ;
-FROM M2MetaError IMPORT MetaErrorString0, MetaError2 ;
+FROM M2MetaError IMPORT MetaErrorStringT0, MetaError2 ;
FROM Lists IMPORT List, InitList, IsItemInList, IncludeItemIntoList ;
FROM M2Reserved IMPORT IsReserved, toktype ;
FROM DynamicStrings IMPORT String, InitString, KillString, ToUpper, InitStringCharStar, string, Mark, ToUpper, Dup ;
@@ -78,11 +78,11 @@ END IsNotADuplicateName ;
as a keyword except for its case.
*)
-PROCEDURE CheckVariableAgainstKeyword (name: Name) ;
+PROCEDURE CheckVariableAgainstKeyword (tok: CARDINAL; name: Name) ;
BEGIN
IF StyleChecking
THEN
- PerformVariableKeywordCheck (name)
+ PerformVariableKeywordCheck (tok, name)
END
END CheckVariableAgainstKeyword ;
@@ -91,7 +91,7 @@ END CheckVariableAgainstKeyword ;
PerformVariableKeywordCheck - performs the check and constructs the metaerror notes if appropriate.
*)
-PROCEDURE PerformVariableKeywordCheck (name: Name) ;
+PROCEDURE PerformVariableKeywordCheck (tok: CARDINAL; name: Name) ;
VAR
upper : Name ;
token : toktype ;
@@ -105,9 +105,11 @@ BEGIN
THEN
IF IsNotADuplicateName (name)
THEN
- MetaErrorString0 (Sprintf2 (Mark (InitString ('either the identifier has the same name as a keyword or alternatively a keyword has the wrong case ({%%K%s} and {!%%O:{%%K%s}})')),
- upperS, orig)) ;
- MetaErrorString0 (Sprintf1 (Mark (InitString ('the symbol name {!%%O:{%%K%s}} is legal as an identifier, however as such it might cause confusion and is considered bad programming practice')), orig))
+ MetaErrorStringT0 (tok,
+ Sprintf2 (Mark (InitString ('either the identifier has the same name as a keyword or alternatively a keyword has the wrong case ({%%K%s} and {!%%O:{%%K%s}})')),
+ upperS, orig)) ;
+ MetaErrorStringT0 (tok,
+ Sprintf1 (Mark (InitString ('the symbol name {!%%O:{%%K%s}} is legal as an identifier, however as such it might cause confusion and is considered bad programming practice')), orig))
END
END ;
upperS := KillString (upperS) ;
diff --git a/gcc/m2/gm2-compiler/P2SymBuild.mod b/gcc/m2/gm2-compiler/P2SymBuild.mod
index 3bb3e47..54e624f 100644
--- a/gcc/m2/gm2-compiler/P2SymBuild.mod
+++ b/gcc/m2/gm2-compiler/P2SymBuild.mod
@@ -1179,8 +1179,8 @@ BEGIN
PopT (n) ;
i := 1 ;
WHILE i <= n DO
- CheckVariableAgainstKeyword (OperandT (n+1-i)) ;
tok := OperandTok (n+1-i) ;
+ CheckVariableAgainstKeyword (tok, OperandT (n+1-i)) ;
Var := MakeVar (tok, OperandT (n+1-i)) ;
AtAddress := OperandA (n+1-i) ;
IF AtAddress # NulSym
diff --git a/gcc/m2/gm2-libs-iso/LowLong.mod b/gcc/m2/gm2-libs-iso/LowLong.mod
index 92c7d91..f611923 100644
--- a/gcc/m2/gm2-libs-iso/LowLong.mod
+++ b/gcc/m2/gm2-libs-iso/LowLong.mod
@@ -182,7 +182,7 @@ BEGIN
IF n<0
THEN
(* exception raised *)
- RAISE(except, ORD(badparam),
+ RAISE(exceptSrc, ORD(badparam),
'LowLong.trunc: cannot truncate to a negative number of digits') ;
RETURN x
ELSE
@@ -230,7 +230,7 @@ BEGIN
IF n<0
THEN
(* exception raised *)
- RAISE(except, ORD(badparam),
+ RAISE(exceptSrc, ORD(badparam),
'LowLong.round: cannot round to a negative number of digits') ;
RETURN x
ELSE
@@ -287,12 +287,12 @@ END currentMode ;
PROCEDURE IsLowException () : BOOLEAN ;
BEGIN
- RETURN( IsExceptionalExecution() AND IsCurrentSource(except) )
+ RETURN( IsExceptionalExecution () AND IsCurrentSource (exceptSrc) )
END IsLowException ;
VAR
- except: ExceptionSource ;
+ exceptSrc: ExceptionSource ;
BEGIN
- AllocateSource(except)
+ AllocateSource (exceptSrc)
END LowLong.
diff --git a/gcc/m2/gm2-libs-iso/LowReal.mod b/gcc/m2/gm2-libs-iso/LowReal.mod
index 580f36b..6d9ea00 100644
--- a/gcc/m2/gm2-libs-iso/LowReal.mod
+++ b/gcc/m2/gm2-libs-iso/LowReal.mod
@@ -183,8 +183,8 @@ BEGIN
IF n<0
THEN
(* exception raised *)
- RAISE(except, ORD(badparam),
- 'LowReal.trunc: cannot truncate to a negative number of digits') ;
+ RAISE (exceptSrc, ORD(badparam),
+ 'LowReal.trunc: cannot truncate to a negative number of digits') ;
RETURN x
ELSE
r := dtoa(x, maxsignificant, 100, point, sign) ;
@@ -231,8 +231,8 @@ BEGIN
IF n<0
THEN
(* exception raised *)
- RAISE(except, ORD(badparam),
- 'LowReal.round: cannot round to a negative number of digits') ;
+ RAISE (exceptSrc, ORD(badparam),
+ 'LowReal.round: cannot round to a negative number of digits') ;
RETURN x
ELSE
s := RealToFloatString(x, n) ;
@@ -288,12 +288,12 @@ END currentMode ;
PROCEDURE IsLowException () : BOOLEAN ;
BEGIN
- RETURN( IsExceptionalExecution() AND IsCurrentSource(except) )
+ RETURN( IsExceptionalExecution () AND IsCurrentSource (exceptSrc) )
END IsLowException ;
VAR
- except: ExceptionSource ;
+ exceptSrc: ExceptionSource ;
BEGIN
- AllocateSource(except)
+ AllocateSource (exceptSrc)
END LowReal.
diff --git a/gcc/m2/gm2-libs-iso/LowShort.mod b/gcc/m2/gm2-libs-iso/LowShort.mod
index 8531a88..62e4887 100644
--- a/gcc/m2/gm2-libs-iso/LowShort.mod
+++ b/gcc/m2/gm2-libs-iso/LowShort.mod
@@ -183,8 +183,8 @@ BEGIN
IF n<0
THEN
(* exception raised *)
- RAISE(except, ORD(badparam),
- 'LowLong.trunc: cannot truncate to a negative number of digits') ;
+ RAISE (exceptSrc, ORD(badparam),
+ 'LowLong.trunc: cannot truncate to a negative number of digits') ;
RETURN x
ELSE
r := dtoa(x, maxsignificant, 100, point, sign) ;
@@ -231,8 +231,8 @@ BEGIN
IF n<0
THEN
(* exception raised *)
- RAISE(except, ORD(badparam),
- 'LowLong.round: cannot round to a negative number of digits') ;
+ RAISE (exceptSrc, ORD(badparam),
+ 'LowLong.round: cannot round to a negative number of digits') ;
RETURN x
ELSE
s := RealToFloatString(x, n) ;
@@ -288,12 +288,12 @@ END currentMode ;
PROCEDURE IsLowException () : BOOLEAN ;
BEGIN
- RETURN( IsExceptionalExecution() AND IsCurrentSource(except) )
+ RETURN( IsExceptionalExecution () AND IsCurrentSource (exceptSrc) )
END IsLowException ;
VAR
- except: ExceptionSource ;
+ exceptSrc: ExceptionSource ;
BEGIN
- AllocateSource(except)
+ AllocateSource (exceptSrc)
END LowShort.
diff --git a/gcc/m2/gm2-libs-iso/Processes.mod b/gcc/m2/gm2-libs-iso/Processes.mod
index 8ef22c0..b0c1b69 100644
--- a/gcc/m2/gm2-libs-iso/Processes.mod
+++ b/gcc/m2/gm2-libs-iso/Processes.mod
@@ -441,7 +441,7 @@ PROCEDURE Wait ;
VAR
calling,
best : ProcessId ;
- from : COROUTINE ;
+ fromCor: COROUTINE ;
BEGIN
IF debugging
THEN
@@ -451,17 +451,17 @@ BEGIN
OnWaitingQueue (calling) ;
best := chooseProcess () ;
currentId := best ;
- from := calling^.context ;
+ fromCor := calling^.context ;
IF debugging
THEN
displayProcesses ("Wait about to perform IOTRANSFER")
END ;
- IOTRANSFER (from, currentId^.context) ;
+ IOTRANSFER (fromCor, currentId^.context) ;
IF debugging
THEN
displayProcesses ("Wait after IOTRANSFER")
END ;
- currentId^.context := from ;
+ currentId^.context := fromCor ;
currentId := calling ;
OnReadyQueue (calling) ;
IF debugging
diff --git a/gcc/m2/gm2-libs-iso/RndFile.mod b/gcc/m2/gm2-libs-iso/RndFile.mod
index e04cd8f..0a2264a 100644
--- a/gcc/m2/gm2-libs-iso/RndFile.mod
+++ b/gcc/m2/gm2-libs-iso/RndFile.mod
@@ -398,9 +398,9 @@ PROCEDURE EndPos (cid: ChanId): FilePos;
position after which there have been no writes.
*)
VAR
- d : DeviceTablePtr ;
- end,
- old: FilePos ;
+ d : DeviceTablePtr ;
+ endP,
+ old : FilePos ;
BEGIN
IF IsRndFile(cid)
THEN
@@ -410,9 +410,9 @@ BEGIN
old := CurrentPos(cid) ;
FIO.SetPositionFromEnd(RTio.GetFile(cid), 0) ;
checkErrno(dev, d) ;
- end := CurrentPos(cid) ;
+ endP := CurrentPos(cid) ;
FIO.SetPositionFromBeginning(RTio.GetFile(cid), old) ;
- RETURN( end )
+ RETURN( endP )
END
ELSE
RAISEdevException(cid, did, IOChan.wrongDevice,
diff --git a/gcc/m2/gm2-libs/SCmdArgs.mod b/gcc/m2/gm2-libs/SCmdArgs.mod
index ed76fc4..8443d5f 100644
--- a/gcc/m2/gm2-libs/SCmdArgs.mod
+++ b/gcc/m2/gm2-libs/SCmdArgs.mod
@@ -132,26 +132,27 @@ PROCEDURE GetArg (CmdLine: String;
VAR
i : CARDINAL ;
sn,
- start, end: INTEGER ;
+ startPos,
+ endPos : INTEGER ;
ch : CHAR ;
BEGIN
i := 0 ;
- start := 0 ;
- end := Length(CmdLine) ;
+ startPos := 0 ;
+ endPos := Length(CmdLine) ;
WHILE i<n DO
- start := skipWhite(CmdLine, start, end) ;
- sn := skipNextArg(CmdLine, start, end) ;
- IF sn<end
+ startPos := skipWhite(CmdLine, startPos, endPos) ;
+ sn := skipNextArg(CmdLine, startPos, endPos) ;
+ IF sn<endPos
THEN
- start := sn ;
+ startPos := sn ;
INC(i)
ELSE
RETURN( FALSE )
END
END ;
- start := skipWhite(CmdLine, start, end) ;
- sn := skipNextArg(CmdLine, start, end) ;
- Argi := Slice(CmdLine, start, sn) ;
+ startPos := skipWhite(CmdLine, startPos, endPos) ;
+ sn := skipNextArg(CmdLine, startPos, endPos) ;
+ Argi := Slice(CmdLine, startPos, sn) ;
RETURN( TRUE )
END GetArg ;
@@ -165,17 +166,18 @@ PROCEDURE Narg (CmdLine: String) : CARDINAL ;
VAR
n : CARDINAL ;
s,
- start, end: INTEGER ;
+ startPos,
+ endPos : INTEGER ;
BEGIN
n := 0 ;
- start := 0 ;
- end := Length(CmdLine) ;
+ startPos := 0 ;
+ endPos := Length(CmdLine) ;
LOOP
- start := skipWhite(CmdLine, start, end) ;
- s := skipNextArg(CmdLine, start, end) ;
- IF s<end
+ startPos := skipWhite(CmdLine, startPos, endPos) ;
+ s := skipNextArg(CmdLine, startPos, endPos) ;
+ IF s<endPos
THEN
- start := s ;
+ startPos := s ;
INC(n)
ELSE
RETURN( n )
diff --git a/gcc/match.pd b/gcc/match.pd
index 4903552..82e6e29 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -3595,22 +3595,34 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
return (T)x;
}
while WT is uint128_t, T is uint8_t, uint16_t, uint32_t or uint64_t. */
- (convert@4 (min (widen_mult:c@3 (convert@5 (convert @0))
- (convert@6 (convert @1)))
+ (convert (min (widen_mult:c@3 (convert@4 (convert @0))
+ (convert@5 (convert @1)))
INTEGER_CST@2))
- (if (types_match (type, @0, @1) && types_match (type, @4))
+ (if (types_match (type, @0, @1))
(with
{
unsigned prec = TYPE_PRECISION (type);
unsigned widen_prec = TYPE_PRECISION (TREE_TYPE (@3));
+ unsigned cvt4_prec = TYPE_PRECISION (TREE_TYPE (@4));
unsigned cvt5_prec = TYPE_PRECISION (TREE_TYPE (@5));
- unsigned cvt6_prec = TYPE_PRECISION (TREE_TYPE (@6));
wide_int c2 = wi::to_wide (@2);
wide_int max = wi::mask (prec, false, widen_prec);
bool c2_is_max_p = wi::eq_p (c2, max);
- bool widen_mult_p = cvt5_prec == cvt6_prec && widen_prec == cvt6_prec * 2;
+ bool widen_mult_p = cvt4_prec == cvt5_prec && widen_prec == cvt5_prec * 2;
}
(if (widen_prec > prec && c2_is_max_p && widen_mult_p)))))
+ (match (unsigned_integer_sat_mul @0 @1)
+ (convert (min (mult:c@3 (convert @0) (convert @1)) INTEGER_CST@2))
+ (if (types_match (type, @0, @1))
+ (with
+ {
+ unsigned prec = TYPE_PRECISION (type);
+ unsigned widen_prec = TYPE_PRECISION (TREE_TYPE (@3));
+ wide_int c2 = wi::to_wide (@2);
+ wide_int max = wi::mask (prec, false, widen_prec);
+ bool c2_is_max_p = wi::eq_p (c2, max);
+ }
+ (if (widen_prec > prec && c2_is_max_p)))))
)
/* The boundary condition for case 10: IMM = 1:
diff --git a/gcc/output.h b/gcc/output.h
index 0c329ff..51c2d36 100644
--- a/gcc/output.h
+++ b/gcc/output.h
@@ -545,6 +545,9 @@ extern GTY(()) section *bss_noswitch_section;
extern GTY(()) section *in_section;
extern GTY(()) bool in_cold_section_p;
+/* MAX bit alignment for mergable sections. */
+#define MAX_ALIGN_MERGABLE 256
+
extern section *get_unnamed_section (unsigned int, void (*) (const char *),
const char *);
extern section *get_section (const char *, unsigned int, tree,
@@ -557,6 +560,9 @@ extern rtx get_section_anchor (struct object_block *, HOST_WIDE_INT,
extern section *mergeable_constant_section (machine_mode,
unsigned HOST_WIDE_INT,
unsigned int);
+extern section *mergeable_constant_section (unsigned HOST_WIDE_INT,
+ unsigned HOST_WIDE_INT,
+ unsigned int);
extern section *function_section (tree);
extern section *unlikely_text_section (void);
extern section *current_function_section (void);
diff --git a/gcc/simplify-rtx.cc b/gcc/simplify-rtx.cc
index cbe61b4..125048d 100644
--- a/gcc/simplify-rtx.cc
+++ b/gcc/simplify-rtx.cc
@@ -8394,9 +8394,45 @@ simplify_context::simplify_subreg (machine_mode outermode, rtx op,
&& VECTOR_MODE_P (innermode)
&& known_eq (GET_MODE_NUNITS (outermode), GET_MODE_NUNITS (innermode))
&& known_eq (GET_MODE_UNIT_SIZE (outermode),
- GET_MODE_UNIT_SIZE (innermode)))
+ GET_MODE_UNIT_SIZE (innermode)))
return simplify_gen_relational (GET_CODE (op), outermode, innermode,
XEXP (op, 0), XEXP (op, 1));
+
+ /* Distribute lowpart subregs through logic ops in cases where one term
+ disappears.
+
+ (subreg:M1 (and:M2 X C1)) -> (subreg:M1 X)
+ (subreg:M1 (ior:M2 X C1)) -> (subreg:M1 C1)
+ (subreg:M1 (xor:M2 X C1)) -> (subreg:M1 (not:M2 X))
+
+ if M2 is no smaller than M1 and (subreg:M1 C1) is all-ones.
+
+ (subreg:M1 (and:M2 X C2)) -> (subreg:M1 C2)
+ (subreg:M1 (ior/xor:M2 X C2)) -> (subreg:M1 X)
+
+ if M2 is no smaller than M1 and (subreg:M1 C2) is zero. */
+ if (known_ge (innersize, outersize)
+ && GET_MODE_CLASS (outermode) == GET_MODE_CLASS (innermode)
+ && (GET_CODE (op) == AND || GET_CODE (op) == IOR || GET_CODE (op) == XOR)
+ && CONSTANT_P (XEXP (op, 1)))
+ {
+ rtx op1_subreg = simplify_subreg (outermode, XEXP (op, 1), innermode, 0);
+ if (op1_subreg == CONSTM1_RTX (outermode))
+ {
+ if (GET_CODE (op) == IOR)
+ return op1_subreg;
+ rtx op0 = XEXP (op, 0);
+ if (GET_CODE (op) == XOR)
+ op0 = simplify_gen_unary (NOT, innermode, op0, innermode);
+ return simplify_gen_subreg (outermode, op0, innermode, 0);
+ }
+
+ if (op1_subreg == CONST0_RTX (outermode))
+ return (GET_CODE (op) == AND
+ ? op1_subreg
+ : simplify_gen_subreg (outermode, XEXP (op, 0), innermode, 0));
+ }
+
return NULL_RTX;
}
@@ -8668,6 +8704,43 @@ test_scalar_int_ext_ops (machine_mode bmode, machine_mode smode)
lowpart_subreg (bmode, sreg, smode),
bmode),
sreg);
+
+ /* Test extensions, followed by logic ops, followed by truncations. */
+ rtx bsubreg = lowpart_subreg (bmode, sreg, smode);
+ rtx smask = gen_int_mode (GET_MODE_MASK (smode), bmode);
+ rtx inv_smask = gen_int_mode (~GET_MODE_MASK (smode), bmode);
+ ASSERT_RTX_EQ (lowpart_subreg (smode,
+ simplify_gen_binary (AND, bmode,
+ bsubreg, smask),
+ bmode),
+ sreg);
+ ASSERT_RTX_EQ (lowpart_subreg (smode,
+ simplify_gen_binary (AND, bmode,
+ bsubreg, inv_smask),
+ bmode),
+ const0_rtx);
+ ASSERT_RTX_EQ (lowpart_subreg (smode,
+ simplify_gen_binary (IOR, bmode,
+ bsubreg, smask),
+ bmode),
+ constm1_rtx);
+ ASSERT_RTX_EQ (lowpart_subreg (smode,
+ simplify_gen_binary (IOR, bmode,
+ bsubreg, inv_smask),
+ bmode),
+ sreg);
+ ASSERT_RTX_EQ (lowpart_subreg (smode,
+ simplify_gen_binary (XOR, bmode,
+ bsubreg, smask),
+ bmode),
+ lowpart_subreg (smode,
+ gen_rtx_NOT (bmode, bsubreg),
+ bmode));
+ ASSERT_RTX_EQ (lowpart_subreg (smode,
+ simplify_gen_binary (XOR, bmode,
+ bsubreg, inv_smask),
+ bmode),
+ sreg);
}
/* Verify more simplifications of integer extension/truncation.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 3b5f40c..bd12ca6 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,105 @@
+2025-07-28 Andrew Pinski <quic_apinski@quicinc.com>
+
+ PR tree-optimization/121236
+ * gcc.dg/torture/pr121236-1.c: New test.
+
+2025-07-28 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/121208
+ * gcc.target/i386/pr121208-1a.c: New test.
+ * gcc.target/i386/pr121208-1b.c: Likewise.
+ * gcc.target/i386/pr121208-2a.c: Likewise.
+ * gcc.target/i386/pr121208-2b.c: Likewise.
+ * gcc.target/i386/pr121208-3a.c: Likewise.
+ * gcc.target/i386/pr121208-3b.c: Likewise.
+
+2025-07-28 Thomas Schwinge <tschwinge@baylibre.com>
+
+ * gcc.target/nvptx/march-map=sm_100.c: New.
+ * gcc.target/nvptx/march-map=sm_100a.c: Likewise.
+ * gcc.target/nvptx/march-map=sm_100f.c: Likewise.
+ * gcc.target/nvptx/march-map=sm_101.c: Likewise.
+ * gcc.target/nvptx/march-map=sm_101a.c: Likewise.
+ * gcc.target/nvptx/march-map=sm_101f.c: Likewise.
+ * gcc.target/nvptx/march-map=sm_103.c: Likewise.
+ * gcc.target/nvptx/march-map=sm_103a.c: Likewise.
+ * gcc.target/nvptx/march-map=sm_103f.c: Likewise.
+ * gcc.target/nvptx/march-map=sm_120.c: Likewise.
+ * gcc.target/nvptx/march-map=sm_120a.c: Likewise.
+ * gcc.target/nvptx/march-map=sm_120f.c: Likewise.
+ * gcc.target/nvptx/march-map=sm_121.c: Likewise.
+ * gcc.target/nvptx/march-map=sm_121a.c: Likewise.
+ * gcc.target/nvptx/march-map=sm_121f.c: Likewise.
+
+2025-07-28 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/121256
+ * gcc.dg/vect/vect-recurr-pr121256.c: New testcase.
+ * gcc.dg/vect/vect-recurr-pr121256-2.c: Likewise.
+
+2025-07-27 Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/121185
+ * gfortran.dg/assign_14.f90: New test.
+
+2025-07-27 Mikael Morin <mikael@gcc.gnu.org>
+
+ PR fortran/121185
+ * gfortran.dg/assign_13.f90: New test.
+
+2025-07-27 Pan Li <pan2.li@intel.com>
+
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-i16.c: New test.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-i32.c: New test.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-i64.c: New test.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-i8.c: New test.
+
+2025-07-27 Pan Li <pan2.li@intel.com>
+
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i16.c: Add asm check.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i32.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i64.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-4-i8.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i16.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i32.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i64.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-5-i8.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-5-u8.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i16.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i32.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i64.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-6-i8.c: Ditto.
+
+2025-07-27 Pan Li <pan2.li@intel.com>
+
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i16.c: Add asm check.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i32.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i64.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-1-i8.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i16.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i32.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i64.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-2-i8.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i16.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i32.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i64.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx-3-i8.c: Ditto.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx_binary.h: Add test helper
+ macros.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx_binary_data.h: Add test
+ data for run test.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-i16.c: New test.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-i32.c: New test.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-i64.c: New test.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vx_vaadd-run-1-i8.c: New test.
+
+2025-07-27 Pan Li <pan2.li@intel.com>
+
+ * gcc.target/riscv/rvv/autovec/vx_vf/vf_vfwnmacc-run-1-f16.c:
+ Add zvfh requirements and options.
+ * gcc.target/riscv/rvv/autovec/vx_vf/vf_vfwnmsac-run-1-f16.c:
+ Ditto.
+
2025-07-27 Nathaniel Shead <nathanieloshead@gmail.com>
* g++.dg/modules/class-11_a.H: New test.
diff --git a/gcc/testsuite/c-c++-common/pr121159.c b/gcc/testsuite/c-c++-common/pr121159.c
new file mode 100644
index 0000000..c8c5d67
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr121159.c
@@ -0,0 +1,17 @@
+/* PR middle-end/121159 */
+/* { dg-do compile { target musttail } } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-times "foo \\\(\[^\n\r]*\\\); \\\[tail call\\\] \\\[must tail call\\\]" 1 "optimized" } } */
+
+[[noreturn, gnu::noipa]] void
+foo (void)
+{
+ for (;;)
+ ;
+}
+
+void
+bar (void)
+{
+ [[gnu::musttail]] return foo ();
+}
diff --git a/gcc/testsuite/g++.dg/modules/class-11_a.H b/gcc/testsuite/g++.dg/modules/class-11_a.H
index f7bbf9d..799dbdd 100644
--- a/gcc/testsuite/g++.dg/modules/class-11_a.H
+++ b/gcc/testsuite/g++.dg/modules/class-11_a.H
@@ -20,7 +20,7 @@ struct pr106381 {
struct L1 : pr106381 {
char x; // { dg-warning "offset" "" { target c++14 } }
};
-static_assert(sizeof(L1) == sizeof(pr106381));
+static_assert(sizeof(L1) == sizeof(pr106381), "");
struct pr120012 {
@@ -33,4 +33,4 @@ struct pr120012 {
struct L2 : pr120012 {
unsigned char y; // { dg-warning "offset" "" { target c++20 } }
};
-static_assert(sizeof(L2) > sizeof(pr120012));
+static_assert(sizeof(L2) > sizeof(pr120012), "");
diff --git a/gcc/testsuite/gcc.dg/plugin/must-tail-call-2.c b/gcc/testsuite/gcc.dg/plugin/must-tail-call-2.c
index d51d15c..6f65f4a 100644
--- a/gcc/testsuite/gcc.dg/plugin/must-tail-call-2.c
+++ b/gcc/testsuite/gcc.dg/plugin/must-tail-call-2.c
@@ -55,5 +55,5 @@ volatile fn_ptr_t fn_ptr;
void
test_5 (void)
{
- fn_ptr (); /* { dg-error "cannot tail-call: " } */
+ fn_ptr ();
}
diff --git a/gcc/testsuite/gcc.dg/pr116906-1.c b/gcc/testsuite/gcc.dg/pr116906-1.c
index 7187507..ee60ad6 100644
--- a/gcc/testsuite/gcc.dg/pr116906-1.c
+++ b/gcc/testsuite/gcc.dg/pr116906-1.c
@@ -1,3 +1,4 @@
+/* { dg-do run } */
/* { dg-require-effective-target alarm } */
/* { dg-require-effective-target signal } */
/* { dg-options "-O2" } */
diff --git a/gcc/testsuite/gcc.dg/pr116906-2.c b/gcc/testsuite/gcc.dg/pr116906-2.c
index 41a352b..4172ec3 100644
--- a/gcc/testsuite/gcc.dg/pr116906-2.c
+++ b/gcc/testsuite/gcc.dg/pr116906-2.c
@@ -1,3 +1,4 @@
+/* { dg-do run } */
/* { dg-require-effective-target alarm } */
/* { dg-require-effective-target signal } */
/* { dg-options "-O2 -fno-tree-ch" } */
diff --git a/gcc/testsuite/gcc.dg/pr120660.c b/gcc/testsuite/gcc.dg/pr120660.c
new file mode 100644
index 0000000..6e8c5e8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr120660.c
@@ -0,0 +1,19 @@
+/* { dg-do run } */
+/* { dg-options "-O -favoid-store-forwarding" } */
+
+int c;
+
+short
+foo (short s)
+{
+ __builtin_memset (&s, c, 1);
+ return s;
+}
+
+int
+main ()
+{
+ short x = foo (0x1111);
+ if (x != 0x1100 && x != 0x0011)
+ __builtin_abort();
+}
diff --git a/gcc/testsuite/gcc.dg/pr78185.c b/gcc/testsuite/gcc.dg/pr78185.c
index ada8b1b..4c3af4f 100644
--- a/gcc/testsuite/gcc.dg/pr78185.c
+++ b/gcc/testsuite/gcc.dg/pr78185.c
@@ -1,3 +1,4 @@
+/* { dg-do run } */
/* { dg-require-effective-target alarm } */
/* { dg-require-effective-target signal } */
/* { dg-options "-O" } */
diff --git a/gcc/testsuite/gcc.dg/torture/pr121236-1.c b/gcc/testsuite/gcc.dg/torture/pr121236-1.c
new file mode 100644
index 0000000..2b397e3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr121236-1.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* PR tree-optimization/121236 */
+
+
+unsigned func_26(short *p_27, int gg, int p) {
+ unsigned l_184 = 0;
+ unsigned m = 0;
+ for (int g_59 = 0; g_59 < 10; g_59++)
+ {
+ if (gg)
+ l_184--;
+ else
+ {
+ m |= l_184 |= p;
+ (l_184)--;
+ }
+ }
+ return m;
+}
+
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/cswtch-7.c b/gcc/testsuite/gcc.dg/tree-ssa/cswtch-7.c
new file mode 100644
index 0000000..7b797807
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/cswtch-7.c
@@ -0,0 +1,48 @@
+/* PR tree-optimization/120523 */
+/* PR tree-optimization/120451 */
+/* { dg-do compile { target elf } } */
+/* { dg-options "-O2" } */
+
+void foo (int, int);
+
+__attribute__((noinline, noclone)) void
+f1 (int v, int w)
+{
+ int i, j;
+ if (w)
+ {
+ i = 129;
+ j = i - 1;
+ goto lab;
+ }
+ switch (v)
+ {
+ case 170:
+ j = 7;
+ i = 27;
+ break;
+ case 171:
+ i = 8;
+ j = 122;
+ break;
+ case 172:
+ i = 21;
+ j = -19;
+ break;
+ case 173:
+ i = 18;
+ j = 17;
+ break;
+ case 174:
+ i = 33;
+ j = 55;
+ break;
+ default:
+ __builtin_abort ();
+ }
+
+ lab:
+ foo (i, j);
+}
+
+/* { dg-final { scan-assembler ".rodata.cst32" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/pr120687-1.c b/gcc/testsuite/gcc.dg/vect/pr120687-1.c
new file mode 100644
index 0000000..ce9cf63
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr120687-1.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_int } */
+
+unsigned
+frd (unsigned *p, unsigned *lastone)
+{
+ unsigned sum = 0;
+ for (; p <= lastone; p += 16)
+ sum += p[0] + p[1] + p[2] + p[3] + p[4] + p[5] + p[6] + p[7]
+ + p[8] + p[9] + p[10] + p[11] + p[12] + p[13] + p[14] + p[15];
+ return sum;
+}
+
+/* { dg-final { scan-tree-dump "reduction: detected reduction chain" "vect" } } */
+/* { dg-final { scan-tree-dump-not "SLP discovery of reduction chain failed" "vect" } } */
+/* { dg-final { scan-tree-dump "optimized: loop vectorized" "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/pr120687-2.c b/gcc/testsuite/gcc.dg/vect/pr120687-2.c
new file mode 100644
index 0000000..dfc6dc7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr120687-2.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_float } */
+/* { dg-additional-options "-ffast-math" } */
+
+float
+frd (float *p, float *lastone)
+{
+ float sum = 0;
+ for (; p <= lastone; p += 16)
+ sum += p[0] + p[1] + p[2] + p[3] + p[4] + p[5] + p[6] + p[7]
+ + p[8] + p[9] + p[10] + p[11] + p[12] + p[13] + p[14] + p[15];
+ return sum;
+}
+
+/* { dg-final { scan-tree-dump "reduction: detected reduction chain" "vect" } } */
+/* { dg-final { scan-tree-dump-not "SLP discovery of reduction chain failed" "vect" } } */
+/* { dg-final { scan-tree-dump "optimized: loop vectorized" "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/pr120687-3.c b/gcc/testsuite/gcc.dg/vect/pr120687-3.c
new file mode 100644
index 0000000..f20a66a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr120687-3.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_double } */
+/* { dg-additional-options "-ffast-math" } */
+
+float
+frd (float *p, float *lastone)
+{
+ float sum = 0;
+ for (; p <= lastone; p += 2)
+ sum += p[0] + p[1];
+ return sum;
+}
+
+/* { dg-final { scan-tree-dump "reduction: detected reduction chain" "vect" } } */
+/* { dg-final { scan-tree-dump-not "SLP discovery of reduction chain failed" "vect" } } */
+/* { dg-final { scan-tree-dump "optimized: loop vectorized" "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-recurr-pr121256-2.c b/gcc/testsuite/gcc.dg/vect/vect-recurr-pr121256-2.c
new file mode 100644
index 0000000..7350fd9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-recurr-pr121256-2.c
@@ -0,0 +1,49 @@
+/* { dg-additional-options "-mavx2" { target avx2_runtime } } */
+
+#include "tree-vect.h"
+
+#define B 0
+#define G 1
+#define R 2
+
+int red = 153;
+int green = 66;
+int blue = 187;
+
+static void __attribute__((noipa))
+sub_left_prediction_bgr32(int *restrict dst, int *restrict src)
+{
+ for (int i = 0; i < 8; i++) {
+ int rt = src[i * 3 + R];
+ int gt = src[i * 3 + G];
+ int bt = src[i * 3 + B];
+
+ dst[i * 3 + R] = rt - red;
+ dst[i * 3 + G] = gt - green;
+ dst[i * 3 + B] = bt - blue;
+
+ red = rt;
+ green = gt;
+ blue = bt;
+ }
+}
+
+int main()
+{
+ int dst[8*3];
+ int src[8*3] = { 160, 73, 194, 17, 33, 99, 0, 12, 283, 87, 73, 11,
+ 9, 7, 1, 23, 19, 13, 77, 233, 97, 78, 2, 5 };
+ int dst2[8*3] = {-27, 7, 41, -143, -40, -95, -17, -21, 184, 87, 61,
+ -272, -78, -66, -10, 14, 12, 12, 54, 214, 84, 1, -231, -92};
+
+ check_vect ();
+
+ sub_left_prediction_bgr32(dst, src);
+
+#pragma GCC novector
+ for (int i = 0; i < 8*3; ++i)
+ if (dst[i] != dst2[i])
+ __builtin_abort();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/vect/vect-recurr-pr121256.c b/gcc/testsuite/gcc.dg/vect/vect-recurr-pr121256.c
new file mode 100644
index 0000000..c895e94
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-recurr-pr121256.c
@@ -0,0 +1,54 @@
+/* { dg-additional-options "-mavx2" { target avx2_runtime } } */
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include "tree-vect.h"
+
+#define B 0
+#define G 1
+#define R 2
+#define A 3
+
+int red = 153;
+int green = 66;
+int blue = 187;
+int alpha = 255;
+
+static void __attribute__((noipa))
+sub_left_prediction_bgr32(uint8_t *restrict dst, uint8_t *restrict src, int w)
+{
+ for (int i = 0; i < 8; i++) {
+ int rt = src[i * 4 + R];
+ int gt = src[i * 4 + G];
+ int bt = src[i * 4 + B];
+ int at = src[i * 4 + A];
+
+ dst[i * 4 + R] = rt - red;
+ dst[i * 4 + G] = gt - green;
+ dst[i * 4 + B] = bt - blue;
+ dst[i * 4 + A] = at - alpha;
+
+ red = rt;
+ green = gt;
+ blue = bt;
+ alpha = at;
+ }
+}
+
+int main()
+{
+ check_vect ();
+
+ uint8_t *dst = calloc(36, sizeof(uint8_t));
+ uint8_t *src = calloc(36, sizeof(uint8_t));
+
+ src[R] = 160;
+ src[G] = 73;
+ src[B] = 194;
+ src[A] = 255;
+
+ sub_left_prediction_bgr32(dst, src, 33);
+ if (dst[R] != 7 || dst[B] != 7 || dst[A] != 0)
+ __builtin_abort();
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/cmpbr.c b/gcc/testsuite/gcc.target/aarch64/cmpbr.c
index a86af9d..34630f9 100644
--- a/gcc/testsuite/gcc.target/aarch64/cmpbr.c
+++ b/gcc/testsuite/gcc.target/aarch64/cmpbr.c
@@ -121,7 +121,7 @@ FAR_BRANCH(u64, 42);
/*
** u8_x0_eq_x1:
-** cbbeq w1, w0, .L([0-9]+)
+** cbbeq (?:w1, w0|w0, w1), .L([0-9]+)
** b not_taken
** .L\1:
** b taken
@@ -129,7 +129,7 @@ FAR_BRANCH(u64, 42);
/*
** u8_x0_ne_x1:
-** cbbne w1, w0, .L([0-9]+)
+** cbbne (?:w1, w0|w0, w1), .L([0-9]+)
** b not_taken
** .L\1:
** b taken
@@ -137,7 +137,7 @@ FAR_BRANCH(u64, 42);
/*
** u8_x0_ult_x1:
-** cbbhi w1, w0, .L([0-9]+)
+** (?:cbbhi w1, w0|cbblo w0, w1), .L([0-9]+)
** b not_taken
** .L\1:
** b taken
@@ -145,7 +145,7 @@ FAR_BRANCH(u64, 42);
/*
** u8_x0_ule_x1:
-** cbbhs w1, w0, .L([0-9]+)
+** (?:cbbhs w1, w0|cbbls w0, w1), .L([0-9]+)
** b not_taken
** .L\1:
** b taken
@@ -153,7 +153,7 @@ FAR_BRANCH(u64, 42);
/*
** u8_x0_ugt_x1:
-** cbblo w1, w0, .L([0-9]+)
+** (?:cbblo w1, w0|cbbhi w0, w1), .L([0-9]+)
** b not_taken
** .L\1:
** b taken
@@ -161,7 +161,7 @@ FAR_BRANCH(u64, 42);
/*
** u8_x0_uge_x1:
-** cbbls w1, w0, .L([0-9]+)
+** (?:cbbls w1, w0|cbbhs w0, w1), .L([0-9]+)
** b not_taken
** .L\1:
** b taken
@@ -169,7 +169,7 @@ FAR_BRANCH(u64, 42);
/*
** i8_x0_slt_x1:
-** cbbgt w1, w0, .L([0-9]+)
+** (?:cbbgt w1, w0|cbblt w0, w1), .L([0-9]+)
** b not_taken
** .L\1:
** b taken
@@ -177,7 +177,7 @@ FAR_BRANCH(u64, 42);
/*
** i8_x0_sle_x1:
-** cbbge w1, w0, .L([0-9]+)
+** (?:cbbge w1, w0|cbble w0, w1), .L([0-9]+)
** b not_taken
** .L\1:
** b taken
@@ -185,7 +185,7 @@ FAR_BRANCH(u64, 42);
/*
** i8_x0_sgt_x1:
-** cbblt w1, w0, .L([0-9]+)
+** (?:cbblt w1, w0|cbbgt w0, w1), .L([0-9]+)
** b not_taken
** .L\1:
** b taken
@@ -193,7 +193,7 @@ FAR_BRANCH(u64, 42);
/*
** i8_x0_sge_x1:
-** cbble w1, w0, .L([0-9]+)
+** (?:cbble w1, w0|cbbge w0, w1), .L([0-9]+)
** b not_taken
** .L\1:
** b taken
@@ -201,7 +201,7 @@ FAR_BRANCH(u64, 42);
/*
** u16_x0_eq_x1:
-** cbheq w1, w0, .L([0-9]+)
+** cbheq (?:w1, w0|w0, w1), .L([0-9]+)
** b not_taken
** .L\1:
** b taken
@@ -209,7 +209,7 @@ FAR_BRANCH(u64, 42);
/*
** u16_x0_ne_x1:
-** cbhne w0|w1, w1|w0, .L([0-9]+)
+** cbhne (?:w1, w0|w0, w1), .L([0-9]+)
** b not_taken
** .L\1:
** b taken
@@ -217,7 +217,7 @@ FAR_BRANCH(u64, 42);
/*
** u16_x0_ult_x1:
-** cbhhi w1, w0, .L([0-9]+)
+** (?:cbhhi w1, w0|cbhlo w0, w1), .L([0-9]+)
** b not_taken
** .L\1:
** b taken
@@ -225,7 +225,7 @@ FAR_BRANCH(u64, 42);
/*
** u16_x0_ule_x1:
-** cbhhs w1, w0, .L([0-9]+)
+** (?:cbhhs w1, w0|cbhls w0, w1), .L([0-9]+)
** b not_taken
** .L\1:
** b taken
@@ -233,7 +233,7 @@ FAR_BRANCH(u64, 42);
/*
** u16_x0_ugt_x1:
-** cbhlo w1, w0, .L([0-9]+)
+** (?:cbhlo w1, w0|cbhhi w0, w1), .L([0-9]+)
** b not_taken
** .L\1:
** b taken
@@ -241,7 +241,7 @@ FAR_BRANCH(u64, 42);
/*
** u16_x0_uge_x1:
-** cbhls w1, w0, .L([0-9]+)
+** (?:cbhls w1, w0|cbhhs w0, w1), .L([0-9]+)
** b not_taken
** .L\1:
** b taken
@@ -249,7 +249,7 @@ FAR_BRANCH(u64, 42);
/*
** i16_x0_slt_x1:
-** cbhgt w1, w0, .L([0-9]+)
+** (?:cbhgt w1, w0|cbhlt w0, w1), .L([0-9]+)
** b not_taken
** .L\1:
** b taken
@@ -257,7 +257,7 @@ FAR_BRANCH(u64, 42);
/*
** i16_x0_sle_x1:
-** cbhge w1, w0, .L([0-9]+)
+** (?:cbhge w1, w0|cbhle w0, w1), .L([0-9]+)
** b not_taken
** .L\1:
** b taken
@@ -265,7 +265,7 @@ FAR_BRANCH(u64, 42);
/*
** i16_x0_sgt_x1:
-** cbhlt w1, w0, .L([0-9]+)
+** (?:cbhlt w1, w0|cbhgt w0, w1), .L([0-9]+)
** b not_taken
** .L\1:
** b taken
@@ -273,7 +273,7 @@ FAR_BRANCH(u64, 42);
/*
** i16_x0_sge_x1:
-** cbhle w1, w0, .L([0-9]+)
+** (?:cbhle w1, w0|cbhge w0, w1), .L([0-9]+)
** b not_taken
** .L\1:
** b taken
diff --git a/gcc/testsuite/gcc.target/aarch64/saturating_arithmetic_1.c b/gcc/testsuite/gcc.target/aarch64/saturating_arithmetic_1.c
index acd2e11..8fc1569 100644
--- a/gcc/testsuite/gcc.target/aarch64/saturating_arithmetic_1.c
+++ b/gcc/testsuite/gcc.target/aarch64/saturating_arithmetic_1.c
@@ -4,24 +4,24 @@
/*
** uadd:
-** dup v([0-9]+).8b, w1
-** dup v([0-9]+).8b, w0
+** dup v([0-9]+).8b, w[01]
+** dup v([0-9]+).8b, w[01]
** uqadd b([0-9]+), (?:b\2, b\1|b\1, b\2)
** umov w0, v\3.b\[0\]
** ret
*/
/*
** uadd2:
-** dup v([0-9]+).8b, w1
-** dup v([0-9]+).8b, w0
+** dup v([0-9]+).8b, w[01]
+** dup v([0-9]+).8b, w[01]
** uqadd b([0-9]+), (?:b\2, b\1|b\1, b\2)
** umov w0, v\3.b\[0\]
** ret
*/
/*
** usub: { xfail *-*-* }
-** dup v([0-9]+).8b, w1
-** dup v([0-9]+).8b, w0
+** dup v([0-9]+).8b, w[01]
+** dup v([0-9]+).8b, w[01]
** uqsub b([0-9]+), b\1, b\2
** umov w0, v\3.b\[0\]
** ret
diff --git a/gcc/testsuite/gcc.target/aarch64/saturating_arithmetic_2.c b/gcc/testsuite/gcc.target/aarch64/saturating_arithmetic_2.c
index 86c88f8..dd0fefa 100644
--- a/gcc/testsuite/gcc.target/aarch64/saturating_arithmetic_2.c
+++ b/gcc/testsuite/gcc.target/aarch64/saturating_arithmetic_2.c
@@ -4,16 +4,16 @@
/*
** uadd:
-** dup v([0-9]+).4h, w1
-** dup v([0-9]+).4h, w0
+** dup v([0-9]+).4h, w[01]
+** dup v([0-9]+).4h, w[01]
** uqadd h([0-9]+), (?:h\2, h\1|h\1, h\2)
** umov w0, v\3.h\[0\]
** ret
*/
/*
** uadd2:
-** dup v([0-9]+).4h, w1
-** dup v([0-9]+).4h, w0
+** dup v([0-9]+).4h, w[01]
+** dup v([0-9]+).4h, w[01]
** uqadd h([0-9]+), (?:h\2, h\1|h\1, h\2)
** umov w0, v\3.h\[0\]
** ret
diff --git a/gcc/testsuite/gcc.target/i386/pr119795.c b/gcc/testsuite/gcc.target/i386/pr119795.c
new file mode 100644
index 0000000..03c91cc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr119795.c
@@ -0,0 +1,26 @@
+/* { dg-do run } */
+/* { dg-options "-O -fschedule-insns -favoid-store-forwarding" } */
+
+unsigned a, b, c;
+
+void
+foo (_BitInt(2) b2, unsigned _BitInt(255) by, unsigned _BitInt(5) b5,
+ unsigned _BitInt(256) *ret)
+{
+ unsigned _BitInt(255) bx = b2;
+ by += 0x80000000000000000000000000000000wb;
+ __builtin_memmove (&b, &c, 3);
+ unsigned d = b;
+ unsigned e = __builtin_stdc_rotate_right (0x1uwb % b5, a);
+ unsigned _BitInt(256) r = by + bx + d + e;
+ *ret = r;
+}
+
+int
+main ()
+{
+ unsigned _BitInt(256) x;
+ foo (0, -1, 2, &x);
+ if (x != 0x80000000000000000000000000000000wb)
+ __builtin_abort();
+} \ No newline at end of file
diff --git a/gcc/testsuite/gcc.target/i386/pr121208-1a.c b/gcc/testsuite/gcc.target/i386/pr121208-1a.c
new file mode 100644
index 0000000..ac851cb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr121208-1a.c
@@ -0,0 +1,15 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fPIC -mtls-dialect=gnu" } */
+
+extern __thread int bar;
+extern void func (void);
+
+__attribute__((no_caller_saved_registers))
+void
+foo (int error)
+{
+ bar = 1; /* { dg-error -mtls-dialect=gnu2 } */
+ if (error == 0)
+ func ();
+ bar = 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr121208-1b.c b/gcc/testsuite/gcc.target/i386/pr121208-1b.c
new file mode 100644
index 0000000..b97ac71
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr121208-1b.c
@@ -0,0 +1,4 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fPIC -mtls-dialect=gnu2" } */
+
+#include "pr121208-1a.c"
diff --git a/gcc/testsuite/gcc.target/i386/pr121208-2a.c b/gcc/testsuite/gcc.target/i386/pr121208-2a.c
new file mode 100644
index 0000000..c1891ae
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr121208-2a.c
@@ -0,0 +1,17 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fPIC -mtls-dialect=gnu" } */
+
+typedef unsigned int uword_t __attribute__ ((mode (__word__)));
+extern __thread int bar;
+extern void func (void);
+
+__attribute__((target("general-regs-only")))
+__attribute__((interrupt))
+void
+foo (void *frame, uword_t error)
+{
+ bar = 1; /* { dg-error -mtls-dialect=gnu2 } */
+ if (error == 0)
+ func ();
+ bar = 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr121208-2b.c b/gcc/testsuite/gcc.target/i386/pr121208-2b.c
new file mode 100644
index 0000000..269b120
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr121208-2b.c
@@ -0,0 +1,4 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fPIC -mtls-dialect=gnu2" } */
+
+#include "pr121208-2a.c"
diff --git a/gcc/testsuite/gcc.target/i386/pr121208-3a.c b/gcc/testsuite/gcc.target/i386/pr121208-3a.c
new file mode 100644
index 0000000..26fe687
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr121208-3a.c
@@ -0,0 +1,17 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fPIC -mtls-dialect=gnu" } */
+
+typedef unsigned int uword_t __attribute__ ((mode (__word__)));
+extern __thread int bar;
+extern void func (void);
+
+__attribute__((target("general-regs-only")))
+__attribute__((interrupt))
+void
+foo (void *frame)
+{
+ bar = 1; /* { dg-error -mtls-dialect=gnu2 } */
+ if (frame == 0)
+ func ();
+ bar = 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr121208-3b.c b/gcc/testsuite/gcc.target/i386/pr121208-3b.c
new file mode 100644
index 0000000..b672d75
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr121208-3b.c
@@ -0,0 +1,4 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -fPIC -mtls-dialect=gnu2" } */
+
+#include "pr121208-3a.c"
diff --git a/gcc/testsuite/gcc.target/nvptx/march-map=sm_100.c b/gcc/testsuite/gcc.target/nvptx/march-map=sm_100.c
new file mode 100644
index 0000000..e759a11
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nvptx/march-map=sm_100.c
@@ -0,0 +1,19 @@
+/* { dg-do assemble } */
+/* { dg-options {-march-map=sm_100 -mptx=_} } */
+/* { dg-additional-options -save-temps } */
+/* { dg-final { scan-assembler-times {(?n)^ \.version 7\.8$} 1 } } */
+/* { dg-final { scan-assembler-times {(?n)^ \.target sm_89$} 1 } } */
+
+#if __PTX_ISA_VERSION_MAJOR__ != 7
+#error wrong value for __PTX_ISA_VERSION_MAJOR__
+#endif
+
+#if __PTX_ISA_VERSION_MINOR__ != 8
+#error wrong value for __PTX_ISA_VERSION_MINOR__
+#endif
+
+#if __PTX_SM__ != 890
+#error wrong value for __PTX_SM__
+#endif
+
+int dummy;
diff --git a/gcc/testsuite/gcc.target/nvptx/march-map=sm_100a.c b/gcc/testsuite/gcc.target/nvptx/march-map=sm_100a.c
new file mode 100644
index 0000000..153ed1e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nvptx/march-map=sm_100a.c
@@ -0,0 +1,19 @@
+/* { dg-do assemble } */
+/* { dg-options {-march-map=sm_100a -mptx=_} } */
+/* { dg-additional-options -save-temps } */
+/* { dg-final { scan-assembler-times {(?n)^ \.version 7\.8$} 1 } } */
+/* { dg-final { scan-assembler-times {(?n)^ \.target sm_89$} 1 } } */
+
+#if __PTX_ISA_VERSION_MAJOR__ != 7
+#error wrong value for __PTX_ISA_VERSION_MAJOR__
+#endif
+
+#if __PTX_ISA_VERSION_MINOR__ != 8
+#error wrong value for __PTX_ISA_VERSION_MINOR__
+#endif
+
+#if __PTX_SM__ != 890
+#error wrong value for __PTX_SM__
+#endif
+
+int dummy;
diff --git a/gcc/testsuite/gcc.target/nvptx/march-map=sm_100f.c b/gcc/testsuite/gcc.target/nvptx/march-map=sm_100f.c
new file mode 100644
index 0000000..9bb9127
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nvptx/march-map=sm_100f.c
@@ -0,0 +1,19 @@
+/* { dg-do assemble } */
+/* { dg-options {-march-map=sm_100f -mptx=_} } */
+/* { dg-additional-options -save-temps } */
+/* { dg-final { scan-assembler-times {(?n)^ \.version 7\.8$} 1 } } */
+/* { dg-final { scan-assembler-times {(?n)^ \.target sm_89$} 1 } } */
+
+#if __PTX_ISA_VERSION_MAJOR__ != 7
+#error wrong value for __PTX_ISA_VERSION_MAJOR__
+#endif
+
+#if __PTX_ISA_VERSION_MINOR__ != 8
+#error wrong value for __PTX_ISA_VERSION_MINOR__
+#endif
+
+#if __PTX_SM__ != 890
+#error wrong value for __PTX_SM__
+#endif
+
+int dummy;
diff --git a/gcc/testsuite/gcc.target/nvptx/march-map=sm_101.c b/gcc/testsuite/gcc.target/nvptx/march-map=sm_101.c
new file mode 100644
index 0000000..06b3ceb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nvptx/march-map=sm_101.c
@@ -0,0 +1,19 @@
+/* { dg-do assemble } */
+/* { dg-options {-march-map=sm_101 -mptx=_} } */
+/* { dg-additional-options -save-temps } */
+/* { dg-final { scan-assembler-times {(?n)^ \.version 7\.8$} 1 } } */
+/* { dg-final { scan-assembler-times {(?n)^ \.target sm_89$} 1 } } */
+
+#if __PTX_ISA_VERSION_MAJOR__ != 7
+#error wrong value for __PTX_ISA_VERSION_MAJOR__
+#endif
+
+#if __PTX_ISA_VERSION_MINOR__ != 8
+#error wrong value for __PTX_ISA_VERSION_MINOR__
+#endif
+
+#if __PTX_SM__ != 890
+#error wrong value for __PTX_SM__
+#endif
+
+int dummy;
diff --git a/gcc/testsuite/gcc.target/nvptx/march-map=sm_101a.c b/gcc/testsuite/gcc.target/nvptx/march-map=sm_101a.c
new file mode 100644
index 0000000..0cca3f3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nvptx/march-map=sm_101a.c
@@ -0,0 +1,19 @@
+/* { dg-do assemble } */
+/* { dg-options {-march-map=sm_101a -mptx=_} } */
+/* { dg-additional-options -save-temps } */
+/* { dg-final { scan-assembler-times {(?n)^ \.version 7\.8$} 1 } } */
+/* { dg-final { scan-assembler-times {(?n)^ \.target sm_89$} 1 } } */
+
+#if __PTX_ISA_VERSION_MAJOR__ != 7
+#error wrong value for __PTX_ISA_VERSION_MAJOR__
+#endif
+
+#if __PTX_ISA_VERSION_MINOR__ != 8
+#error wrong value for __PTX_ISA_VERSION_MINOR__
+#endif
+
+#if __PTX_SM__ != 890
+#error wrong value for __PTX_SM__
+#endif
+
+int dummy;
diff --git a/gcc/testsuite/gcc.target/nvptx/march-map=sm_101f.c b/gcc/testsuite/gcc.target/nvptx/march-map=sm_101f.c
new file mode 100644
index 0000000..9548be5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nvptx/march-map=sm_101f.c
@@ -0,0 +1,19 @@
+/* { dg-do assemble } */
+/* { dg-options {-march-map=sm_101f -mptx=_} } */
+/* { dg-additional-options -save-temps } */
+/* { dg-final { scan-assembler-times {(?n)^ \.version 7\.8$} 1 } } */
+/* { dg-final { scan-assembler-times {(?n)^ \.target sm_89$} 1 } } */
+
+#if __PTX_ISA_VERSION_MAJOR__ != 7
+#error wrong value for __PTX_ISA_VERSION_MAJOR__
+#endif
+
+#if __PTX_ISA_VERSION_MINOR__ != 8
+#error wrong value for __PTX_ISA_VERSION_MINOR__
+#endif
+
+#if __PTX_SM__ != 890
+#error wrong value for __PTX_SM__
+#endif
+
+int dummy;
diff --git a/gcc/testsuite/gcc.target/nvptx/march-map=sm_103.c b/gcc/testsuite/gcc.target/nvptx/march-map=sm_103.c
new file mode 100644
index 0000000..5731249
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nvptx/march-map=sm_103.c
@@ -0,0 +1,19 @@
+/* { dg-do assemble } */
+/* { dg-options {-march-map=sm_103 -mptx=_} } */
+/* { dg-additional-options -save-temps } */
+/* { dg-final { scan-assembler-times {(?n)^ \.version 7\.8$} 1 } } */
+/* { dg-final { scan-assembler-times {(?n)^ \.target sm_89$} 1 } } */
+
+#if __PTX_ISA_VERSION_MAJOR__ != 7
+#error wrong value for __PTX_ISA_VERSION_MAJOR__
+#endif
+
+#if __PTX_ISA_VERSION_MINOR__ != 8
+#error wrong value for __PTX_ISA_VERSION_MINOR__
+#endif
+
+#if __PTX_SM__ != 890
+#error wrong value for __PTX_SM__
+#endif
+
+int dummy;
diff --git a/gcc/testsuite/gcc.target/nvptx/march-map=sm_103a.c b/gcc/testsuite/gcc.target/nvptx/march-map=sm_103a.c
new file mode 100644
index 0000000..aea501e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nvptx/march-map=sm_103a.c
@@ -0,0 +1,19 @@
+/* { dg-do assemble } */
+/* { dg-options {-march-map=sm_103a -mptx=_} } */
+/* { dg-additional-options -save-temps } */
+/* { dg-final { scan-assembler-times {(?n)^ \.version 7\.8$} 1 } } */
+/* { dg-final { scan-assembler-times {(?n)^ \.target sm_89$} 1 } } */
+
+#if __PTX_ISA_VERSION_MAJOR__ != 7
+#error wrong value for __PTX_ISA_VERSION_MAJOR__
+#endif
+
+#if __PTX_ISA_VERSION_MINOR__ != 8
+#error wrong value for __PTX_ISA_VERSION_MINOR__
+#endif
+
+#if __PTX_SM__ != 890
+#error wrong value for __PTX_SM__
+#endif
+
+int dummy;
diff --git a/gcc/testsuite/gcc.target/nvptx/march-map=sm_103f.c b/gcc/testsuite/gcc.target/nvptx/march-map=sm_103f.c
new file mode 100644
index 0000000..59d8987
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nvptx/march-map=sm_103f.c
@@ -0,0 +1,19 @@
+/* { dg-do assemble } */
+/* { dg-options {-march-map=sm_103f -mptx=_} } */
+/* { dg-additional-options -save-temps } */
+/* { dg-final { scan-assembler-times {(?n)^ \.version 7\.8$} 1 } } */
+/* { dg-final { scan-assembler-times {(?n)^ \.target sm_89$} 1 } } */
+
+#if __PTX_ISA_VERSION_MAJOR__ != 7
+#error wrong value for __PTX_ISA_VERSION_MAJOR__
+#endif
+
+#if __PTX_ISA_VERSION_MINOR__ != 8
+#error wrong value for __PTX_ISA_VERSION_MINOR__
+#endif
+
+#if __PTX_SM__ != 890
+#error wrong value for __PTX_SM__
+#endif
+
+int dummy;
diff --git a/gcc/testsuite/gcc.target/nvptx/march-map=sm_120.c b/gcc/testsuite/gcc.target/nvptx/march-map=sm_120.c
new file mode 100644
index 0000000..d28a671
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nvptx/march-map=sm_120.c
@@ -0,0 +1,19 @@
+/* { dg-do assemble } */
+/* { dg-options {-march-map=sm_120 -mptx=_} } */
+/* { dg-additional-options -save-temps } */
+/* { dg-final { scan-assembler-times {(?n)^ \.version 7\.8$} 1 } } */
+/* { dg-final { scan-assembler-times {(?n)^ \.target sm_89$} 1 } } */
+
+#if __PTX_ISA_VERSION_MAJOR__ != 7
+#error wrong value for __PTX_ISA_VERSION_MAJOR__
+#endif
+
+#if __PTX_ISA_VERSION_MINOR__ != 8
+#error wrong value for __PTX_ISA_VERSION_MINOR__
+#endif
+
+#if __PTX_SM__ != 890
+#error wrong value for __PTX_SM__
+#endif
+
+int dummy;
diff --git a/gcc/testsuite/gcc.target/nvptx/march-map=sm_120a.c b/gcc/testsuite/gcc.target/nvptx/march-map=sm_120a.c
new file mode 100644
index 0000000..613dd65
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nvptx/march-map=sm_120a.c
@@ -0,0 +1,19 @@
+/* { dg-do assemble } */
+/* { dg-options {-march-map=sm_120a -mptx=_} } */
+/* { dg-additional-options -save-temps } */
+/* { dg-final { scan-assembler-times {(?n)^ \.version 7\.8$} 1 } } */
+/* { dg-final { scan-assembler-times {(?n)^ \.target sm_89$} 1 } } */
+
+#if __PTX_ISA_VERSION_MAJOR__ != 7
+#error wrong value for __PTX_ISA_VERSION_MAJOR__
+#endif
+
+#if __PTX_ISA_VERSION_MINOR__ != 8
+#error wrong value for __PTX_ISA_VERSION_MINOR__
+#endif
+
+#if __PTX_SM__ != 890
+#error wrong value for __PTX_SM__
+#endif
+
+int dummy;
diff --git a/gcc/testsuite/gcc.target/nvptx/march-map=sm_120f.c b/gcc/testsuite/gcc.target/nvptx/march-map=sm_120f.c
new file mode 100644
index 0000000..1b23350
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nvptx/march-map=sm_120f.c
@@ -0,0 +1,19 @@
+/* { dg-do assemble } */
+/* { dg-options {-march-map=sm_120f -mptx=_} } */
+/* { dg-additional-options -save-temps } */
+/* { dg-final { scan-assembler-times {(?n)^ \.version 7\.8$} 1 } } */
+/* { dg-final { scan-assembler-times {(?n)^ \.target sm_89$} 1 } } */
+
+#if __PTX_ISA_VERSION_MAJOR__ != 7
+#error wrong value for __PTX_ISA_VERSION_MAJOR__
+#endif
+
+#if __PTX_ISA_VERSION_MINOR__ != 8
+#error wrong value for __PTX_ISA_VERSION_MINOR__
+#endif
+
+#if __PTX_SM__ != 890
+#error wrong value for __PTX_SM__
+#endif
+
+int dummy;
diff --git a/gcc/testsuite/gcc.target/nvptx/march-map=sm_121.c b/gcc/testsuite/gcc.target/nvptx/march-map=sm_121.c
new file mode 100644
index 0000000..240332b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nvptx/march-map=sm_121.c
@@ -0,0 +1,19 @@
+/* { dg-do assemble } */
+/* { dg-options {-march-map=sm_121 -mptx=_} } */
+/* { dg-additional-options -save-temps } */
+/* { dg-final { scan-assembler-times {(?n)^ \.version 7\.8$} 1 } } */
+/* { dg-final { scan-assembler-times {(?n)^ \.target sm_89$} 1 } } */
+
+#if __PTX_ISA_VERSION_MAJOR__ != 7
+#error wrong value for __PTX_ISA_VERSION_MAJOR__
+#endif
+
+#if __PTX_ISA_VERSION_MINOR__ != 8
+#error wrong value for __PTX_ISA_VERSION_MINOR__
+#endif
+
+#if __PTX_SM__ != 890
+#error wrong value for __PTX_SM__
+#endif
+
+int dummy;
diff --git a/gcc/testsuite/gcc.target/nvptx/march-map=sm_121a.c b/gcc/testsuite/gcc.target/nvptx/march-map=sm_121a.c
new file mode 100644
index 0000000..1e7fb70
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nvptx/march-map=sm_121a.c
@@ -0,0 +1,19 @@
+/* { dg-do assemble } */
+/* { dg-options {-march-map=sm_121a -mptx=_} } */
+/* { dg-additional-options -save-temps } */
+/* { dg-final { scan-assembler-times {(?n)^ \.version 7\.8$} 1 } } */
+/* { dg-final { scan-assembler-times {(?n)^ \.target sm_89$} 1 } } */
+
+#if __PTX_ISA_VERSION_MAJOR__ != 7
+#error wrong value for __PTX_ISA_VERSION_MAJOR__
+#endif
+
+#if __PTX_ISA_VERSION_MINOR__ != 8
+#error wrong value for __PTX_ISA_VERSION_MINOR__
+#endif
+
+#if __PTX_SM__ != 890
+#error wrong value for __PTX_SM__
+#endif
+
+int dummy;
diff --git a/gcc/testsuite/gcc.target/nvptx/march-map=sm_121f.c b/gcc/testsuite/gcc.target/nvptx/march-map=sm_121f.c
new file mode 100644
index 0000000..2cbec51
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nvptx/march-map=sm_121f.c
@@ -0,0 +1,19 @@
+/* { dg-do assemble } */
+/* { dg-options {-march-map=sm_121f -mptx=_} } */
+/* { dg-additional-options -save-temps } */
+/* { dg-final { scan-assembler-times {(?n)^ \.version 7\.8$} 1 } } */
+/* { dg-final { scan-assembler-times {(?n)^ \.target sm_89$} 1 } } */
+
+#if __PTX_ISA_VERSION_MAJOR__ != 7
+#error wrong value for __PTX_ISA_VERSION_MAJOR__
+#endif
+
+#if __PTX_ISA_VERSION_MINOR__ != 8
+#error wrong value for __PTX_ISA_VERSION_MINOR__
+#endif
+
+#if __PTX_SM__ != 890
+#error wrong value for __PTX_SM__
+#endif
+
+int dummy;
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-i16.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-i16.c
new file mode 100644
index 0000000..2b87321
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-i16.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64d -mrvv-vector-bits=zvl --param=gpr2vr-cost=0 " } */
+
+#define VL 8
+
+#include "vx-fixed-vxrm.h"
+
+#define VT vint16m1_t
+#define T int16_t
+#define ELEM_SIZE 16
+#define SUFFIX i16
+#define FUNC __riscv_vaadd_vv_i16m1
+
+DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_RNU, FUNC)
+DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_RNE, FUNC)
+DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_RDN, FUNC)
+DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_ROD, FUNC)
+
+/* { dg-final { scan-assembler-times {csrwi\s+vxrm,0} 1 } } */
+/* { dg-final { scan-assembler-times {csrwi\s+vxrm,1} 1 } } */
+/* { dg-final { scan-assembler-times {csrwi\s+vxrm,2} 1 } } */
+/* { dg-final { scan-assembler-times {csrwi\s+vxrm,3} 1 } } */
+/* { dg-final { scan-assembler-times {vaadd.vx} 4 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-i32.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-i32.c
new file mode 100644
index 0000000..b95699b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-i32.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64d -mrvv-vector-bits=zvl --param=gpr2vr-cost=0 " } */
+
+#define VL 4
+
+#include "vx-fixed-vxrm.h"
+
+#define VT vint32m1_t
+#define T int32_t
+#define ELEM_SIZE 32
+#define SUFFIX i32
+#define FUNC __riscv_vaadd_vv_i32m1
+
+DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_RNU, FUNC)
+DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_RNE, FUNC)
+DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_RDN, FUNC)
+DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_ROD, FUNC)
+
+/* { dg-final { scan-assembler-times {csrwi\s+vxrm,0} 1 } } */
+/* { dg-final { scan-assembler-times {csrwi\s+vxrm,1} 1 } } */
+/* { dg-final { scan-assembler-times {csrwi\s+vxrm,2} 1 } } */
+/* { dg-final { scan-assembler-times {csrwi\s+vxrm,3} 1 } } */
+/* { dg-final { scan-assembler-times {vaadd.vx} 4 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-i64.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-i64.c
new file mode 100644
index 0000000..48b6010
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-i64.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64d -mrvv-vector-bits=zvl --param=gpr2vr-cost=0 " } */
+
+#define VL 2
+
+#include "vx-fixed-vxrm.h"
+
+#define VT vint64m1_t
+#define T int64_t
+#define ELEM_SIZE 64
+#define SUFFIX i64
+#define FUNC __riscv_vaadd_vv_i64m1
+
+DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_RNU, FUNC)
+DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_RNE, FUNC)
+DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_RDN, FUNC)
+DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_ROD, FUNC)
+
+/* { dg-final { scan-assembler-times {csrwi\s+vxrm,0} 1 } } */
+/* { dg-final { scan-assembler-times {csrwi\s+vxrm,1} 1 } } */
+/* { dg-final { scan-assembler-times {csrwi\s+vxrm,2} 1 } } */
+/* { dg-final { scan-assembler-times {csrwi\s+vxrm,3} 1 } } */
+/* { dg-final { scan-assembler-times {vaadd.vx} 4 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-i8.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-i8.c
new file mode 100644
index 0000000..d07a625
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/vx_vf/vx-fixed-vxrm-1-i8.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gcv -mabi=lp64d -mrvv-vector-bits=zvl --param=gpr2vr-cost=0 " } */
+
+#define VL 16
+
+#include "vx-fixed-vxrm.h"
+
+#define VT vint8m1_t
+#define T int8_t
+#define ELEM_SIZE 8
+#define SUFFIX i8
+#define FUNC __riscv_vaadd_vv_i8m1
+
+DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_RNU, FUNC)
+DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_RNE, FUNC)
+DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_RDN, FUNC)
+DEF_FIXED_BINARY_VX_WRAP(VT, T, ELEM_SIZE, SUFFIX, __RISCV_VXRM_ROD, FUNC)
+
+/* { dg-final { scan-assembler-times {csrwi\s+vxrm,0} 1 } } */
+/* { dg-final { scan-assembler-times {csrwi\s+vxrm,1} 1 } } */
+/* { dg-final { scan-assembler-times {csrwi\s+vxrm,2} 1 } } */
+/* { dg-final { scan-assembler-times {csrwi\s+vxrm,3} 1 } } */
+/* { dg-final { scan-assembler-times {vaadd.vx} 4 } } */
diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-1-u16-from-u32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-1-u16-from-u32.c
new file mode 100644
index 0000000..7409232
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-1-u16-from-u32.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -fdump-tree-optimized" } */
+
+#include "sat_arith.h"
+
+#define NT uint16_t
+#define WT uint32_t
+
+DEF_SAT_U_MUL_FMT_1_WRAP(NT, WT)
+
+/* { dg-final { scan-tree-dump-times ".SAT_MUL" 1 "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-1-u8-from-u16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-1-u8-from-u16.c
new file mode 100644
index 0000000..ec79e5d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-1-u8-from-u16.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -fdump-tree-optimized" } */
+
+#include "sat_arith.h"
+
+#define NT uint8_t
+#define WT uint16_t
+
+DEF_SAT_U_MUL_FMT_1_WRAP(NT, WT)
+
+/* { dg-final { scan-tree-dump-times ".SAT_MUL" 1 "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-1-u8-from-u32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-1-u8-from-u32.c
new file mode 100644
index 0000000..eb95184
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-1-u8-from-u32.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -fdump-tree-optimized" } */
+
+#include "sat_arith.h"
+
+#define NT uint8_t
+#define WT uint32_t
+
+DEF_SAT_U_MUL_FMT_1_WRAP(NT, WT)
+
+/* { dg-final { scan-tree-dump-times ".SAT_MUL" 1 "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-2-u16-from-u64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-2-u16-from-u64.c
new file mode 100644
index 0000000..b1d33a9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-2-u16-from-u64.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -fdump-tree-optimized" } */
+
+#include "sat_arith.h"
+
+#define NT uint16_t
+#define WT uint64_t
+
+DEF_SAT_U_MUL_FMT_1_WRAP(NT, WT)
+
+/* { dg-final { scan-tree-dump-times ".SAT_MUL" 1 "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-2-u32-from-u64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-2-u32-from-u64.c
new file mode 100644
index 0000000..af5ffecf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-2-u32-from-u64.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -fdump-tree-optimized" } */
+
+#include "sat_arith.h"
+
+#define NT uint32_t
+#define WT uint64_t
+
+DEF_SAT_U_MUL_FMT_1_WRAP(NT, WT)
+
+/* { dg-final { scan-tree-dump-times ".SAT_MUL" 1 "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-2-u8-from-u64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-2-u8-from-u64.c
new file mode 100644
index 0000000..d65cab0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-2-u8-from-u64.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -fdump-tree-optimized" } */
+
+#include "sat_arith.h"
+
+#define NT uint8_t
+#define WT uint64_t
+
+DEF_SAT_U_MUL_FMT_1_WRAP(NT, WT)
+
+/* { dg-final { scan-tree-dump-times ".SAT_MUL" 1 "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u16-from-u32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u16-from-u32.c
new file mode 100644
index 0000000..e212391
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u16-from-u32.c
@@ -0,0 +1,16 @@
+/* { dg-do run { target { rv32 || rv64 } } } */
+/* { dg-additional-options "-std=c99" } */
+
+#include "sat_arith.h"
+#include "sat_arith_data.h"
+
+#define NT uint16_t
+#define WT uint32_t
+#define NAME usmul
+#define DATA TEST_BINARY_DATA_WRAP(NT, NAME)
+#define T TEST_BINARY_STRUCT_DECL_WRAP(NT, NAME)
+#define RUN_BINARY(x, y) RUN_SAT_U_MUL_FMT_1_WRAP(NT, WT, x, y)
+
+DEF_SAT_U_MUL_FMT_1_WRAP(NT, WT)
+
+#include "scalar_sat_binary_run_xxx.h"
diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u16-from-u64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u16-from-u64.c
index 065afb8..79d3fb3 100644
--- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u16-from-u64.c
+++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u16-from-u64.c
@@ -1,4 +1,4 @@
-/* { dg-do run { target { rv32 } } } */
+/* { dg-do run { target { rv32 || rv64 } } } */
/* { dg-additional-options "-std=c99" } */
#include "sat_arith.h"
diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u32-from-u64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u32-from-u64.c
index 062bbc9..ad63db3 100644
--- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u32-from-u64.c
+++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u32-from-u64.c
@@ -1,4 +1,4 @@
-/* { dg-do run { target { rv32 } } } */
+/* { dg-do run { target { rv32 || rv64 } } } */
/* { dg-additional-options "-std=c99" } */
#include "sat_arith.h"
diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u8-from-u16.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u8-from-u16.c
new file mode 100644
index 0000000..f5a0ab5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u8-from-u16.c
@@ -0,0 +1,16 @@
+/* { dg-do run { target { rv32 || rv64 } } } */
+/* { dg-additional-options "-std=c99" } */
+
+#include "sat_arith.h"
+#include "sat_arith_data.h"
+
+#define NT uint8_t
+#define WT uint16_t
+#define NAME usmul
+#define DATA TEST_BINARY_DATA_WRAP(NT, NAME)
+#define T TEST_BINARY_STRUCT_DECL_WRAP(NT, NAME)
+#define RUN_BINARY(x, y) RUN_SAT_U_MUL_FMT_1_WRAP(NT, WT, x, y)
+
+DEF_SAT_U_MUL_FMT_1_WRAP(NT, WT)
+
+#include "scalar_sat_binary_run_xxx.h"
diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u8-from-u32.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u8-from-u32.c
new file mode 100644
index 0000000..32074a4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u8-from-u32.c
@@ -0,0 +1,16 @@
+/* { dg-do run { target { rv32 || rv64 } } } */
+/* { dg-additional-options "-std=c99" } */
+
+#include "sat_arith.h"
+#include "sat_arith_data.h"
+
+#define NT uint8_t
+#define WT uint32_t
+#define NAME usmul
+#define DATA TEST_BINARY_DATA_WRAP(NT, NAME)
+#define T TEST_BINARY_STRUCT_DECL_WRAP(NT, NAME)
+#define RUN_BINARY(x, y) RUN_SAT_U_MUL_FMT_1_WRAP(NT, WT, x, y)
+
+DEF_SAT_U_MUL_FMT_1_WRAP(NT, WT)
+
+#include "scalar_sat_binary_run_xxx.h"
diff --git a/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u8-from-u64.c b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u8-from-u64.c
index e6f632b..16ca905 100644
--- a/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u8-from-u64.c
+++ b/gcc/testsuite/gcc.target/riscv/sat/sat_u_mul-run-1-u8-from-u64.c
@@ -1,4 +1,4 @@
-/* { dg-do run { target { rv32 } } } */
+/* { dg-do run { target { rv32 || rv64 } } } */
/* { dg-additional-options "-std=c99" } */
#include "sat_arith.h"
diff --git a/gcc/testsuite/gfortran.dg/assign_13.f90 b/gcc/testsuite/gfortran.dg/assign_13.f90
new file mode 100644
index 0000000..262ade0
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/assign_13.f90
@@ -0,0 +1,25 @@
+! { dg-do run }
+!
+! PR fortran/121185
+! The assignment to Y%X in CHECK_T was using a polymorphic array access on the
+! left hand side, using the virtual table of Y.
+
+program p
+ implicit none
+ type t
+ complex, allocatable :: x(:)
+ end type t
+ real :: trace = 2.
+ type(t) :: z
+ z%x = [1,2] * trace
+ call check_t (z)
+contains
+ subroutine check_t (y)
+ class(t) :: y
+ ! print *, y% x
+ if (any(y%x /= [2., 4.])) error stop 11
+ y%x = y%x / trace
+ ! print *, y% x
+ if (any(y%x /= [1., 2.])) error stop 12
+ end subroutine
+end
diff --git a/gcc/testsuite/gfortran.dg/assign_14.f90 b/gcc/testsuite/gfortran.dg/assign_14.f90
new file mode 100644
index 0000000..33b46b9
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/assign_14.f90
@@ -0,0 +1,24 @@
+! { dg-do compile }
+! { dg-additional-options {-fdump-tree-original} }
+!
+! PR fortran/121185
+! Check that an intermediary variable is used to reference component a.
+! { dg-final { scan-tree-dump-not {->b->a} original } }
+
+program p
+ implicit none
+ type t
+ integer, allocatable :: a(:)
+ end type t
+ type u
+ type(t), allocatable :: b
+ end type u
+ type v
+ type(u), allocatable :: c
+ end type v
+ type(v) :: z
+ z%c = u()
+ z%c%b = t()
+ z%c%b%a = [1,2]
+ z%c%b%a = z%c%b%a * 2
+end
diff --git a/gcc/testsuite/gm2/warnings/style/fail/badvarname.mod b/gcc/testsuite/gm2/warnings/style/fail/badvarname.mod
new file mode 100644
index 0000000..e589b0d
--- /dev/null
+++ b/gcc/testsuite/gm2/warnings/style/fail/badvarname.mod
@@ -0,0 +1,14 @@
+MODULE badvarname ;
+
+
+PROCEDURE Foo ;
+VAR
+ end: CARDINAL ;
+BEGIN
+ end := 1
+END Foo ;
+
+
+BEGIN
+ Foo
+END badvarname.
diff --git a/gcc/testsuite/gm2/warnings/style/fail/warnings-style-fail.exp b/gcc/testsuite/gm2/warnings/style/fail/warnings-style-fail.exp
new file mode 100644
index 0000000..f44ed80
--- /dev/null
+++ b/gcc/testsuite/gm2/warnings/style/fail/warnings-style-fail.exp
@@ -0,0 +1,44 @@
+# Expect driver script for GCC Regression Tests
+# Copyright (C) 2025 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# This file was written by Gaius Mulley (gaius.mulley@southwales.ac.uk)
+# for GNU Modula-2.
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+# load support procs
+load_lib gm2-torture.exp
+
+gm2_init_pim "${srcdir}/gm2/warnings/style/fail"
+
+global TORTURE_OPTIONS
+
+set old_options $TORTURE_OPTIONS
+set TORTURE_OPTIONS { { -O0 -g -Werror=style } }
+
+foreach testcase [lsort [glob -nocomplain $srcdir/$subdir/*.mod]] {
+ # If we're only testing specific files and this isn't one of them, skip it.
+ if ![runtest_file_p $runtests $testcase] then {
+ continue
+ }
+
+ gm2-torture-fail $testcase
+}
+
+set TORTURE_OPTIONS $old_options
diff --git a/gcc/tree-if-conv.cc b/gcc/tree-if-conv.cc
index ba25c19..a8b800b 100644
--- a/gcc/tree-if-conv.cc
+++ b/gcc/tree-if-conv.cc
@@ -1755,7 +1755,7 @@ strip_nop_cond_scalar_reduction (bool has_nop, tree op)
EXTENDED is true if PHI has > 2 arguments. */
static bool
-is_cond_scalar_reduction (gimple *phi, gimple **reduc, tree arg_0, tree arg_1,
+is_cond_scalar_reduction (basic_block bb, tree phi_res, gimple **reduc, tree arg_0, tree arg_1,
tree *op0, tree *op1, bool extended, bool* has_nop,
gimple **nop_reduc)
{
@@ -1763,7 +1763,6 @@ is_cond_scalar_reduction (gimple *phi, gimple **reduc, tree arg_0, tree arg_1,
gimple *stmt;
gimple *header_phi = NULL;
enum tree_code reduction_op;
- basic_block bb = gimple_bb (phi);
class loop *loop = bb->loop_father;
edge latch_e = loop_latch_edge (loop);
imm_use_iterator imm_iter;
@@ -1791,7 +1790,7 @@ is_cond_scalar_reduction (gimple *phi, gimple **reduc, tree arg_0, tree arg_1,
if (gimple_bb (header_phi) != loop->header)
return false;
- if (PHI_ARG_DEF_FROM_EDGE (header_phi, latch_e) != PHI_RESULT (phi))
+ if (PHI_ARG_DEF_FROM_EDGE (header_phi, latch_e) != phi_res)
return false;
if (gimple_code (stmt) != GIMPLE_ASSIGN
@@ -1889,7 +1888,7 @@ is_cond_scalar_reduction (gimple *phi, gimple **reduc, tree arg_0, tree arg_1,
continue;
if (use_stmt == SSA_NAME_DEF_STMT (r_op1))
continue;
- if (use_stmt != phi)
+ if (use_stmt != SSA_NAME_DEF_STMT (phi_res))
return false;
}
}
@@ -2199,8 +2198,8 @@ commutative:
and *RES to the new values if the factoring happened.
Loops until all of the factoring is completed. */
-static void
-factor_out_operators (tree *res, gimple_stmt_iterator *gsi,
+static bool
+factor_out_operators (gimple_stmt_iterator *pgsi, tree *res, gimple_stmt_iterator *gsi,
tree *arg0, tree *arg1, gphi *phi)
{
gimple_match_op arg0_op, arg1_op;
@@ -2208,28 +2207,28 @@ factor_out_operators (tree *res, gimple_stmt_iterator *gsi,
again:
if (TREE_CODE (*arg0) != SSA_NAME || TREE_CODE (*arg1) != SSA_NAME)
- return;
+ return repeated;
if (operand_equal_p (*arg0, *arg1))
- return;
+ return repeated;
/* If either args have > 1 use, then this transformation actually
increases the number of expressions evaluated at runtime. */
if (repeated
? (!has_zero_uses (*arg0) || !has_zero_uses (*arg1))
: (!has_single_use (*arg0) || !has_single_use (*arg1)))
- return;
+ return repeated;
gimple *arg0_def_stmt = SSA_NAME_DEF_STMT (*arg0);
if (!gimple_extract_op (arg0_def_stmt, &arg0_op))
- return;
+ return repeated;
/* At this point there should be no ssa names occuring in abnormals. */
gcc_assert (!arg0_op.operands_occurs_in_abnormal_phi ());
gimple *arg1_def_stmt = SSA_NAME_DEF_STMT (*arg1);
if (!gimple_extract_op (arg1_def_stmt, &arg1_op))
- return;
+ return repeated;
/* At this point there should be no ssa names occuring in abnormals. */
gcc_assert (!arg1_op.operands_occurs_in_abnormal_phi ());
@@ -2238,15 +2237,15 @@ again:
or the number operands. */
if (arg1_op.code != arg0_op.code
|| arg1_op.num_ops != arg0_op.num_ops)
- return;
+ return repeated;
tree new_arg0, new_arg1;
int opnum = find_different_opnum (arg0_op, arg1_op, &new_arg0, &new_arg1);
if (opnum == -1)
- return;
+ return repeated;
if (!types_compatible_p (TREE_TYPE (new_arg0), TREE_TYPE (new_arg1)))
- return;
+ return repeated;
tree new_res = make_ssa_name (TREE_TYPE (new_arg0), NULL);
/* Create the operation stmt if possible and insert it. */
@@ -2262,7 +2261,7 @@ again:
if (!result)
{
release_ssa_name (new_res);
- return;
+ return repeated;
}
gsi_insert_seq_before (gsi, seq, GSI_CONTINUE_LINKING);
@@ -2277,6 +2276,10 @@ again:
fprintf (dump_file, ".\n");
}
+ /* Remove the phi and move to the next phi arg if needed. */
+ if (!repeated)
+ remove_phi_node (pgsi, false);
+
/* Remove the old operation(s) that has single use. */
gimple_stmt_iterator gsi_for_def;
@@ -2400,8 +2403,9 @@ cmp_arg_entry (const void *p1, const void *p2, void * /* data. */)
vectorization. */
-static void
-predicate_scalar_phi (gphi *phi, gimple_stmt_iterator *gsi, bool loop_versioned)
+static bool
+predicate_scalar_phi (gimple_stmt_iterator *phi_gsi, gphi *phi,
+ gimple_stmt_iterator *gsi, bool loop_versioned)
{
gimple *new_stmt = NULL, *reduc, *nop_reduc;
tree rhs, res, arg0, arg1, op0, op1, scev;
@@ -2411,10 +2415,11 @@ predicate_scalar_phi (gphi *phi, gimple_stmt_iterator *gsi, bool loop_versioned)
basic_block bb;
unsigned int i;
bool has_nop;
+ bool removed_phi = false;
res = gimple_phi_result (phi);
if (virtual_operand_p (res))
- return;
+ return removed_phi;
if ((rhs = degenerate_phi_result (phi))
|| ((scev = analyze_scalar_evolution (gimple_bb (phi)->loop_father,
@@ -2431,7 +2436,7 @@ predicate_scalar_phi (gphi *phi, gimple_stmt_iterator *gsi, bool loop_versioned)
new_stmt = gimple_build_assign (res, rhs);
gsi_insert_before (gsi, new_stmt, GSI_SAME_STMT);
update_stmt (new_stmt);
- return;
+ return removed_phi;
}
bb = gimple_bb (phi);
@@ -2477,9 +2482,13 @@ predicate_scalar_phi (gphi *phi, gimple_stmt_iterator *gsi, bool loop_versioned)
/* Factor out operand if possible. This can only be done easily
for PHI with 2 elements. */
- factor_out_operators (&res, gsi, &arg0, &arg1, phi);
+ if (factor_out_operators (phi_gsi, &res, gsi, &arg0, &arg1, phi))
+ {
+ phi = nullptr;
+ removed_phi = true;
+ }
- if (is_cond_scalar_reduction (phi, &reduc, arg0, arg1,
+ if (is_cond_scalar_reduction (bb, res, &reduc, arg0, arg1,
&op0, &op1, false, &has_nop,
&nop_reduc))
{
@@ -2508,7 +2517,7 @@ predicate_scalar_phi (gphi *phi, gimple_stmt_iterator *gsi, bool loop_versioned)
fprintf (dump_file, "new phi replacement stmt\n");
print_gimple_stmt (dump_file, new_stmt, 0, TDF_SLIM);
}
- return;
+ return removed_phi;
}
/* Create hashmap for PHI node which contain vector of argument indexes
@@ -2576,7 +2585,7 @@ predicate_scalar_phi (gphi *phi, gimple_stmt_iterator *gsi, bool loop_versioned)
/* Gimplify the condition to a valid cond-expr conditonal operand. */
cond = force_gimple_operand_gsi (gsi, unshare_expr (cond), true,
NULL_TREE, true, GSI_SAME_STMT);
- if (!(is_cond_scalar_reduction (phi, &reduc, arg0 , arg1,
+ if (!(is_cond_scalar_reduction (bb, res, &reduc, arg0 , arg1,
&op0, &op1, true, &has_nop, &nop_reduc)))
rhs = fold_build_cond_expr (TREE_TYPE (res), unshare_expr (cond),
swap ? arg1 : arg0,
@@ -2606,6 +2615,7 @@ predicate_scalar_phi (gphi *phi, gimple_stmt_iterator *gsi, bool loop_versioned)
fprintf (dump_file, "new extended phi replacement stmt\n");
print_gimple_stmt (dump_file, new_stmt, 0, TDF_SLIM);
}
+ return removed_phi;
}
/* Replaces in LOOP all the scalar phi nodes other than those in the
@@ -2642,8 +2652,8 @@ predicate_all_scalar_phis (class loop *loop, bool loop_versioned)
gsi_next (&phi_gsi);
else
{
- predicate_scalar_phi (phi, &gsi, loop_versioned);
- remove_phi_node (&phi_gsi, false);
+ if (!predicate_scalar_phi (&phi_gsi, phi, &gsi, loop_versioned))
+ remove_phi_node (&phi_gsi, false);
}
}
}
diff --git a/gcc/tree-ssa-reassoc.cc b/gcc/tree-ssa-reassoc.cc
index 3c38f3d..c140f76 100644
--- a/gcc/tree-ssa-reassoc.cc
+++ b/gcc/tree-ssa-reassoc.cc
@@ -7167,9 +7167,10 @@ reassociate_bb (basic_block bb)
/* If the target support FMA, rank_ops_for_fma will detect if
the chain has fmas and rearrange the ops if so. */
- if (direct_internal_fn_supported_p (IFN_FMA,
- TREE_TYPE (lhs),
- opt_type)
+ if (!reassoc_insert_powi_p
+ && direct_internal_fn_supported_p (IFN_FMA,
+ TREE_TYPE (lhs),
+ opt_type)
&& (rhs_code == PLUS_EXPR || rhs_code == MINUS_EXPR))
{
mult_num = rank_ops_for_fma (&ops);
@@ -7200,7 +7201,8 @@ reassociate_bb (basic_block bb)
to make sure the ones that get the double
binary op are chosen wisely. */
int len = ops.length ();
- if (len >= 3
+ if (!reassoc_insert_powi_p
+ && len >= 3
&& (!has_fma
/* width > 1 means ranking ops results in better
parallelism. Check current value to avoid
diff --git a/gcc/tree-switch-conversion.cc b/gcc/tree-switch-conversion.cc
index d088287..04b357f 100644
--- a/gcc/tree-switch-conversion.cc
+++ b/gcc/tree-switch-conversion.cc
@@ -55,6 +55,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
#include "hwint.h"
#include "internal-fn.h"
#include "diagnostic-core.h"
+#include "output.h"
/* ??? For lang_hooks.types.type_for_mode, but is there a word_mode
type in the GIMPLE type system that is language-independent? */
@@ -1033,6 +1034,16 @@ switch_conversion::build_one_array (int num, tree arr_index_type,
/* The decl is mergable since we don't take the address ever and
just reading from it. */
DECL_MERGEABLE (decl) = 1;
+
+ /* Increase the alignments as needed. */
+ if (tree_to_uhwi (DECL_SIZE (decl)) > DECL_ALIGN (decl))
+ {
+ unsigned HOST_WIDE_INT s = tree_to_uhwi (DECL_SIZE (decl));
+ /* Only support up to the max supported for merging. */
+ if (s <= MAX_ALIGN_MERGABLE)
+ SET_DECL_ALIGN (decl, HOST_WIDE_INT_1U << ceil_log2 (s));
+ }
+
if (offloading_function_p (cfun->decl))
DECL_ATTRIBUTES (decl)
= tree_cons (get_identifier ("omp declare target"), NULL_TREE,
diff --git a/gcc/tree-vect-data-refs.cc b/gcc/tree-vect-data-refs.cc
index 3bf2852..e7919b7 100644
--- a/gcc/tree-vect-data-refs.cc
+++ b/gcc/tree-vect-data-refs.cc
@@ -4542,7 +4542,6 @@ vect_describe_gather_scatter_call (stmt_vec_info stmt_info,
(call, internal_fn_alias_ptr_index (info->ifn));
info->offset = gimple_call_arg
(call, internal_fn_offset_index (info->ifn));
- info->offset_dt = vect_unknown_def_type;
info->offset_vectype = NULL_TREE;
info->scale = TREE_INT_CST_LOW (gimple_call_arg
(call, internal_fn_scale_index (info->ifn)));
@@ -4872,7 +4871,6 @@ vect_check_gather_scatter (stmt_vec_info stmt_info, loop_vec_info loop_vinfo,
get_object_alignment (DR_REF (dr)));
info->offset = off;
- info->offset_dt = vect_unknown_def_type;
info->offset_vectype = offset_vectype;
info->scale = scale;
info->element_type = TREE_TYPE (vectype);
diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc
index 2ee023f..80b5a0a 100644
--- a/gcc/tree-vect-loop.cc
+++ b/gcc/tree-vect-loop.cc
@@ -1919,7 +1919,6 @@ vect_create_loop_vinfo (class loop *loop, vec_info_shared *shared,
for (gcond *cond : info->conds)
{
stmt_vec_info loop_cond_info = loop_vinfo->lookup_stmt (cond);
- STMT_VINFO_TYPE (loop_cond_info) = loop_exit_ctrl_vec_info_type;
/* Mark the statement as a condition. */
STMT_VINFO_DEF_TYPE (loop_cond_info) = vect_condition_def;
}
@@ -1936,9 +1935,6 @@ vect_create_loop_vinfo (class loop *loop, vec_info_shared *shared,
if (info->inner_loop_cond)
{
- stmt_vec_info inner_loop_cond_info
- = loop_vinfo->lookup_stmt (info->inner_loop_cond);
- STMT_VINFO_TYPE (inner_loop_cond_info) = loop_exit_ctrl_vec_info_type;
/* If we have an estimate on the number of iterations of the inner
loop use that to limit the scale for costing, otherwise use
--param vect-inner-loop-cost-factor literally. */
@@ -7151,7 +7147,7 @@ vectorizable_lane_reducing (loop_vec_info loop_vinfo, stmt_vec_info stmt_info,
}
/* Transform via vect_transform_reduction. */
- STMT_VINFO_TYPE (stmt_info) = reduc_vec_info_type;
+ SLP_TREE_TYPE (slp_node) = reduc_vec_info_type;
return true;
}
@@ -7253,18 +7249,17 @@ vectorizable_reduction (loop_vec_info loop_vinfo,
}
/* Analysis for double-reduction is done on the outer
loop PHI, nested cycles have no further restrictions. */
- STMT_VINFO_TYPE (stmt_info) = cycle_phi_info_type;
+ SLP_TREE_TYPE (slp_node) = cycle_phi_info_type;
}
else
- STMT_VINFO_TYPE (stmt_info) = reduc_vec_info_type;
+ SLP_TREE_TYPE (slp_node) = reduc_vec_info_type;
return true;
}
- stmt_vec_info orig_stmt_of_analysis = stmt_info;
stmt_vec_info phi_info = stmt_info;
if (!is_a <gphi *> (stmt_info->stmt))
{
- STMT_VINFO_TYPE (stmt_info) = reduc_vec_info_type;
+ SLP_TREE_TYPE (slp_node) = reduc_vec_info_type;
return true;
}
if (STMT_VINFO_DEF_TYPE (stmt_info) == vect_double_reduction_def)
@@ -8074,7 +8069,7 @@ vectorizable_reduction (loop_vec_info loop_vinfo,
&& reduction_type == FOLD_LEFT_REDUCTION)
dump_printf_loc (MSG_NOTE, vect_location,
"using an in-order (fold-left) reduction.\n");
- STMT_VINFO_TYPE (orig_stmt_of_analysis) = cycle_phi_info_type;
+ SLP_TREE_TYPE (slp_node) = cycle_phi_info_type;
/* All but single defuse-cycle optimized and fold-left reductions go
through their own vectorizable_* routines. */
@@ -8770,7 +8765,7 @@ vectorizable_lc_phi (loop_vec_info loop_vinfo,
return false;
}
- STMT_VINFO_TYPE (stmt_info) = lc_phi_info_type;
+ SLP_TREE_TYPE (slp_node) = lc_phi_info_type;
return true;
}
@@ -8855,7 +8850,7 @@ vectorizable_phi (vec_info *,
if (gimple_phi_num_args (as_a <gphi *> (stmt_info->stmt)) > 1)
record_stmt_cost (cost_vec, SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node),
vector_stmt, stmt_info, vectype, 0, vect_body);
- STMT_VINFO_TYPE (stmt_info) = phi_info_type;
+ SLP_TREE_TYPE (slp_node) = phi_info_type;
return true;
}
@@ -8970,6 +8965,33 @@ vectorizable_recurr (loop_vec_info loop_vinfo, stmt_vec_info stmt_info,
return false;
}
+ /* We need to be able to build a { ..., a, b } init vector with
+ dist number of distinct trailing values. Always possible
+ when dist == 1 or when nunits is constant or when the initializations
+ are uniform. */
+ tree uniform_initval = NULL_TREE;
+ edge pe = loop_preheader_edge (LOOP_VINFO_LOOP (loop_vinfo));
+ for (stmt_vec_info s : SLP_TREE_SCALAR_STMTS (slp_node))
+ {
+ gphi *phi = as_a <gphi *> (s->stmt);
+ if (! uniform_initval)
+ uniform_initval = PHI_ARG_DEF_FROM_EDGE (phi, pe);
+ else if (! operand_equal_p (uniform_initval,
+ PHI_ARG_DEF_FROM_EDGE (phi, pe)))
+ {
+ uniform_initval = NULL_TREE;
+ break;
+ }
+ }
+ if (!uniform_initval && !nunits.is_constant ())
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "cannot build initialization vector for "
+ "first order recurrence\n");
+ return false;
+ }
+
/* First-order recurrence autovectorization needs to handle permutation
with indices = [nunits-1, nunits, nunits+1, ...]. */
vec_perm_builder sel (nunits, 1, 3);
@@ -9016,25 +9038,42 @@ vectorizable_recurr (loop_vec_info loop_vinfo, stmt_vec_info stmt_info,
"prologue_cost = %d .\n", inside_cost,
prologue_cost);
- STMT_VINFO_TYPE (stmt_info) = recurr_info_type;
+ SLP_TREE_TYPE (slp_node) = recurr_info_type;
return true;
}
- edge pe = loop_preheader_edge (LOOP_VINFO_LOOP (loop_vinfo));
- basic_block bb = gimple_bb (phi);
- tree preheader = PHI_ARG_DEF_FROM_EDGE (phi, pe);
- if (!useless_type_conversion_p (TREE_TYPE (vectype), TREE_TYPE (preheader)))
+ tree vec_init;
+ if (! uniform_initval)
{
- gimple_seq stmts = NULL;
- preheader = gimple_convert (&stmts, TREE_TYPE (vectype), preheader);
- gsi_insert_seq_on_edge_immediate (pe, stmts);
+ vec<constructor_elt, va_gc> *v = NULL;
+ vec_alloc (v, nunits.to_constant ());
+ for (unsigned i = 0; i < nunits.to_constant () - dist; ++i)
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
+ build_zero_cst (TREE_TYPE (vectype)));
+ for (stmt_vec_info s : SLP_TREE_SCALAR_STMTS (slp_node))
+ {
+ gphi *phi = as_a <gphi *> (s->stmt);
+ tree preheader = PHI_ARG_DEF_FROM_EDGE (phi, pe);
+ if (!useless_type_conversion_p (TREE_TYPE (vectype),
+ TREE_TYPE (preheader)))
+ {
+ gimple_seq stmts = NULL;
+ preheader = gimple_convert (&stmts,
+ TREE_TYPE (vectype), preheader);
+ gsi_insert_seq_on_edge_immediate (pe, stmts);
+ }
+ CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, preheader);
+ }
+ vec_init = build_constructor (vectype, v);
}
- tree vec_init = build_vector_from_val (vectype, preheader);
+ else
+ vec_init = uniform_initval;
vec_init = vect_init_vector (loop_vinfo, stmt_info, vec_init, vectype, NULL);
/* Create the vectorized first-order PHI node. */
tree vec_dest = vect_get_new_vect_var (vectype,
vect_simple_var, "vec_recur_");
+ basic_block bb = gimple_bb (phi);
gphi *new_phi = create_phi_node (vec_dest, bb);
add_phi_arg (new_phi, vec_init, pe, UNKNOWN_LOCATION);
@@ -9552,7 +9591,7 @@ vectorizable_nonlinear_induction (loop_vec_info loop_vinfo,
"prologue_cost = %d. \n", inside_cost,
prologue_cost);
- STMT_VINFO_TYPE (stmt_info) = induc_vec_info_type;
+ SLP_TREE_TYPE (slp_node) = induc_vec_info_type;
DUMP_VECT_SCOPE ("vectorizable_nonlinear_induction");
return true;
}
@@ -9853,7 +9892,7 @@ vectorizable_induction (loop_vec_info loop_vinfo,
"prologue_cost = %d .\n", inside_cost,
prologue_cost);
- STMT_VINFO_TYPE (stmt_info) = induc_vec_info_type;
+ SLP_TREE_TYPE (slp_node) = induc_vec_info_type;
DUMP_VECT_SCOPE ("vectorizable_induction");
return true;
}
diff --git a/gcc/tree-vect-patterns.cc b/gcc/tree-vect-patterns.cc
index f0ddbf9..ffb320f 100644
--- a/gcc/tree-vect-patterns.cc
+++ b/gcc/tree-vect-patterns.cc
@@ -130,7 +130,6 @@ vect_init_pattern_stmt (vec_info *vinfo, gimple *pattern_stmt,
STMT_VINFO_RELATED_STMT (pattern_stmt_info) = orig_stmt_info;
STMT_VINFO_DEF_TYPE (pattern_stmt_info)
= STMT_VINFO_DEF_TYPE (orig_stmt_info);
- STMT_VINFO_TYPE (pattern_stmt_info) = STMT_VINFO_TYPE (orig_stmt_info);
if (!STMT_VINFO_VECTYPE (pattern_stmt_info))
{
gcc_assert (!vectype
diff --git a/gcc/tree-vect-slp.cc b/gcc/tree-vect-slp.cc
index c0636d8..a9c7105 100644
--- a/gcc/tree-vect-slp.cc
+++ b/gcc/tree-vect-slp.cc
@@ -130,6 +130,8 @@ _slp_tree::_slp_tree ()
this->failed = NULL;
this->max_nunits = 1;
this->lanes = 0;
+ SLP_TREE_TYPE (this) = undef_vec_info_type;
+ this->u.undef = NULL;
}
/* Tear down a SLP node. */
@@ -4948,6 +4950,9 @@ vect_analyze_slp (vec_info *vinfo, unsigned max_tree_size,
max_tree_size, &limit,
force_single_lane))
{
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "SLP discovery of reduction chain failed\n");
/* Dissolve reduction chain group. */
stmt_vec_info vinfo = first_element;
stmt_vec_info last = NULL;
@@ -8259,8 +8264,7 @@ vect_slp_analyze_node_operations (vec_info *vinfo, slp_tree node,
/* Masked loads can have an undefined (default SSA definition)
else operand. We do not need to cost it. */
vec<tree> ops = SLP_TREE_SCALAR_OPS (child);
- if ((STMT_VINFO_TYPE (SLP_TREE_REPRESENTATIVE (node))
- == load_vec_info_type)
+ if (SLP_TREE_TYPE (node) == load_vec_info_type
&& ((ops.length ()
&& TREE_CODE (ops[0]) == SSA_NAME
&& SSA_NAME_IS_DEFAULT_DEF (ops[0])
@@ -8271,8 +8275,7 @@ vect_slp_analyze_node_operations (vec_info *vinfo, slp_tree node,
/* For shifts with a scalar argument we don't need
to cost or code-generate anything.
??? Represent this more explicitely. */
- gcc_assert ((STMT_VINFO_TYPE (SLP_TREE_REPRESENTATIVE (node))
- == shift_vec_info_type)
+ gcc_assert (SLP_TREE_TYPE (node) == shift_vec_info_type
&& j == 1);
continue;
}
@@ -11308,9 +11311,9 @@ vect_schedule_slp_node (vec_info *vinfo,
si = gsi_for_stmt (last_stmt_info->stmt);
}
else if (SLP_TREE_CODE (node) != VEC_PERM_EXPR
- && (STMT_VINFO_TYPE (stmt_info) == cycle_phi_info_type
- || STMT_VINFO_TYPE (stmt_info) == induc_vec_info_type
- || STMT_VINFO_TYPE (stmt_info) == phi_info_type))
+ && (SLP_TREE_TYPE (node) == cycle_phi_info_type
+ || SLP_TREE_TYPE (node) == induc_vec_info_type
+ || SLP_TREE_TYPE (node) == phi_info_type))
{
/* For PHI node vectorization we do not use the insertion iterator. */
si = gsi_none ();
@@ -11330,8 +11333,7 @@ vect_schedule_slp_node (vec_info *vinfo,
last scalar def here. */
if (SLP_TREE_VEC_DEFS (child).is_empty ())
{
- gcc_assert (STMT_VINFO_TYPE (SLP_TREE_REPRESENTATIVE (child))
- == cycle_phi_info_type);
+ gcc_assert (SLP_TREE_TYPE (child) == cycle_phi_info_type);
gphi *phi = as_a <gphi *>
(vect_find_last_scalar_stmt_in_slp (child)->stmt);
if (!last_stmt)
@@ -11482,7 +11484,7 @@ vect_schedule_slp_node (vec_info *vinfo,
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location,
"------>vectorizing SLP permutation node\n");
- /* ??? the transform kind is stored to STMT_VINFO_TYPE which might
+ /* ??? the transform kind was stored to STMT_VINFO_TYPE which might
be shared with different SLP nodes (but usually it's the same
operation apart from the case the stmt is only there for denoting
the actual scalar lane defs ...). So do not call vect_transform_stmt
diff --git a/gcc/tree-vect-stmts.cc b/gcc/tree-vect-stmts.cc
index aa2657a..4cf6c3b 100644
--- a/gcc/tree-vect-stmts.cc
+++ b/gcc/tree-vect-stmts.cc
@@ -1422,7 +1422,7 @@ check_load_store_for_partial_vectors (loop_vec_info loop_vinfo, tree vectype,
int group_size,
vect_memory_access_type
memory_access_type,
- gather_scatter_info *gs_info,
+ const gather_scatter_info *gs_info,
tree scalar_mask,
vec<int> *elsvals = nullptr)
{
@@ -1676,7 +1676,6 @@ vect_truncate_gather_scatter_offset (stmt_vec_info stmt_info, tree vectype,
get_object_alignment (DR_REF (dr)));
gs_info->element_type = TREE_TYPE (vectype);
gs_info->offset = fold_convert (offset_type, step);
- gs_info->offset_dt = vect_constant_def;
gs_info->scale = scale;
gs_info->memory_type = memory_type;
return true;
@@ -2229,22 +2228,23 @@ get_group_load_store_type (vec_info *vinfo, stmt_vec_info stmt_info,
*memory_access_type = VMAT_GATHER_SCATTER;
else if (STMT_VINFO_GATHER_SCATTER_P (stmt_info))
{
- tree offset;
- slp_tree offset_node;
*memory_access_type = VMAT_GATHER_SCATTER;
if (!vect_check_gather_scatter (stmt_info, loop_vinfo, gs_info,
elsvals))
gcc_unreachable ();
+ slp_tree offset_node = SLP_TREE_CHILDREN (slp_node)[0];
+ tree offset_vectype = SLP_TREE_VECTYPE (offset_node);
+ gs_info->offset_vectype = offset_vectype;
/* When using internal functions, we rely on pattern recognition
to convert the type of the offset to the type that the target
requires, with the result being a call to an internal function.
If that failed for some reason (e.g. because another pattern
took priority), just handle cases in which the offset already
has the right type. */
- else if (GATHER_SCATTER_IFN_P (*gs_info)
- && !is_gimple_call (stmt_info->stmt)
- && !tree_nop_conversion_p (TREE_TYPE (gs_info->offset),
- TREE_TYPE (gs_info->offset_vectype)))
+ if (GATHER_SCATTER_IFN_P (*gs_info)
+ && !is_gimple_call (stmt_info->stmt)
+ && !tree_nop_conversion_p (TREE_TYPE (gs_info->offset),
+ offset_vectype))
{
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
@@ -2252,23 +2252,12 @@ get_group_load_store_type (vec_info *vinfo, stmt_vec_info stmt_info,
vls_type == VLS_LOAD ? "gather" : "scatter");
return false;
}
- else if (!vect_is_simple_use (vinfo, slp_node, 0, &offset, &offset_node,
- &gs_info->offset_dt,
- &gs_info->offset_vectype))
- {
- if (dump_enabled_p ())
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "%s index use not simple.\n",
- vls_type == VLS_LOAD ? "gather" : "scatter");
- return false;
- }
else if (GATHER_SCATTER_EMULATED_P (*gs_info))
{
if (!TYPE_VECTOR_SUBPARTS (vectype).is_constant ()
- || !TYPE_VECTOR_SUBPARTS (gs_info->offset_vectype).is_constant ()
- || VECTOR_BOOLEAN_TYPE_P (gs_info->offset_vectype)
- || !constant_multiple_p (TYPE_VECTOR_SUBPARTS
- (gs_info->offset_vectype),
+ || !TYPE_VECTOR_SUBPARTS (offset_vectype).is_constant ()
+ || VECTOR_BOOLEAN_TYPE_P (offset_vectype)
+ || !constant_multiple_p (TYPE_VECTOR_SUBPARTS (offset_vectype),
TYPE_VECTOR_SUBPARTS (vectype)))
{
if (dump_enabled_p ())
@@ -2771,7 +2760,7 @@ static gimple *
vect_build_one_gather_load_call (vec_info *vinfo, stmt_vec_info stmt_info,
tree vectype,
gimple_stmt_iterator *gsi,
- gather_scatter_info *gs_info,
+ const gather_scatter_info *gs_info,
tree ptr, tree offset, tree mask)
{
tree arglist = TYPE_ARG_TYPES (TREE_TYPE (gs_info->decl));
@@ -2869,7 +2858,7 @@ vect_build_one_gather_load_call (vec_info *vinfo, stmt_vec_info stmt_info,
static gimple *
vect_build_one_scatter_store_call (vec_info *vinfo, stmt_vec_info stmt_info,
gimple_stmt_iterator *gsi,
- gather_scatter_info *gs_info,
+ const gather_scatter_info *gs_info,
tree ptr, tree offset, tree oprnd, tree mask)
{
tree rettype = TREE_TYPE (TREE_TYPE (gs_info->decl));
@@ -2950,8 +2939,8 @@ vect_build_one_scatter_store_call (vec_info *vinfo, stmt_vec_info stmt_info,
containing loop. */
static void
-vect_get_gather_scatter_ops (class loop *loop,
- slp_tree slp_node, gather_scatter_info *gs_info,
+vect_get_gather_scatter_ops (class loop *loop, slp_tree slp_node,
+ const gather_scatter_info *gs_info,
tree *dataref_ptr, vec<tree> *vec_offset)
{
gimple_seq stmts = NULL;
@@ -2979,7 +2968,7 @@ static void
vect_get_strided_load_store_ops (stmt_vec_info stmt_info, tree vectype,
loop_vec_info loop_vinfo,
gimple_stmt_iterator *gsi,
- gather_scatter_info *gs_info,
+ const gather_scatter_info *gs_info,
tree *dataref_bump, tree *vec_offset,
vec_loop_lens *loop_lens)
{
@@ -3158,7 +3147,7 @@ vectorizable_bswap (vec_info *vinfo,
return false;
}
- STMT_VINFO_TYPE (stmt_info) = call_vec_info_type;
+ SLP_TREE_TYPE (slp_node) = call_vec_info_type;
DUMP_VECT_SCOPE ("vectorizable_bswap");
record_stmt_cost (cost_vec,
1, vector_stmt, stmt_info, 0, vect_prologue);
@@ -3487,7 +3476,7 @@ vectorizable_call (vec_info *vinfo,
"incompatible vector types for invariants\n");
return false;
}
- STMT_VINFO_TYPE (stmt_info) = call_vec_info_type;
+ SLP_TREE_TYPE (slp_node) = call_vec_info_type;
DUMP_VECT_SCOPE ("vectorizable_call");
vect_model_simple_cost (vinfo, 1, slp_node, cost_vec);
@@ -4282,7 +4271,7 @@ vectorizable_simd_clone_call (vec_info *vinfo, stmt_vec_info stmt_info,
LOOP_VINFO_CAN_USE_PARTIAL_VECTORS_P (loop_vinfo) = false;
}
- STMT_VINFO_TYPE (stmt_info) = call_simd_clone_vec_info_type;
+ SLP_TREE_TYPE (slp_node) = call_simd_clone_vec_info_type;
DUMP_VECT_SCOPE ("vectorizable_simd_clone_call");
/* vect_model_simple_cost (vinfo, 1, slp_node, cost_vec); */
return true;
@@ -5427,13 +5416,13 @@ vectorizable_conversion (vec_info *vinfo,
DUMP_VECT_SCOPE ("vectorizable_conversion");
if (modifier == NONE)
{
- STMT_VINFO_TYPE (stmt_info) = type_conversion_vec_info_type;
+ SLP_TREE_TYPE (slp_node) = type_conversion_vec_info_type;
vect_model_simple_cost (vinfo, (1 + multi_step_cvt),
slp_node, cost_vec);
}
else if (modifier == NARROW_SRC || modifier == NARROW_DST)
{
- STMT_VINFO_TYPE (stmt_info) = type_demotion_vec_info_type;
+ SLP_TREE_TYPE (slp_node) = type_demotion_vec_info_type;
/* The final packing step produces one vector result per copy. */
unsigned int nvectors = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node);
vect_model_promotion_demotion_cost (stmt_info, dt, nvectors,
@@ -5442,7 +5431,7 @@ vectorizable_conversion (vec_info *vinfo,
}
else
{
- STMT_VINFO_TYPE (stmt_info) = type_promotion_vec_info_type;
+ SLP_TREE_TYPE (slp_node) = type_promotion_vec_info_type;
/* The initial unpacking step produces two vector results
per copy. MULTI_STEP_CVT is 0 for a single conversion,
so >> MULTI_STEP_CVT divides by 2^(number of steps - 1). */
@@ -5777,7 +5766,7 @@ vectorizable_assignment (vec_info *vinfo,
"incompatible vector types for invariants\n");
return false;
}
- STMT_VINFO_TYPE (stmt_info) = assignment_vec_info_type;
+ SLP_TREE_TYPE (slp_node) = assignment_vec_info_type;
DUMP_VECT_SCOPE ("vectorizable_assignment");
if (!vect_nop_conversion_p (stmt_info))
vect_model_simple_cost (vinfo, 1, slp_node, cost_vec);
@@ -6122,7 +6111,7 @@ vectorizable_shift (vec_info *vinfo,
gcc_assert ((TREE_CODE (SLP_TREE_SCALAR_OPS (slp_op1)[i])
== INTEGER_CST));
}
- STMT_VINFO_TYPE (stmt_info) = shift_vec_info_type;
+ SLP_TREE_TYPE (slp_node) = shift_vec_info_type;
DUMP_VECT_SCOPE ("vectorizable_shift");
vect_model_simple_cost (vinfo, 1, slp_node, cost_vec);
return true;
@@ -6541,7 +6530,7 @@ vectorizable_operation (vec_info *vinfo,
return false;
}
- STMT_VINFO_TYPE (stmt_info) = op_vec_info_type;
+ SLP_TREE_TYPE (slp_node) = op_vec_info_type;
DUMP_VECT_SCOPE ("vectorizable_operation");
vect_model_simple_cost (vinfo, 1, slp_node, cost_vec);
if (using_emulated_vectors_p)
@@ -7974,7 +7963,7 @@ vectorizable_store (vec_info *vinfo,
dump_printf_loc (MSG_NOTE, vect_location,
"Vectorizing an unaligned access.\n");
- STMT_VINFO_TYPE (stmt_info) = store_vec_info_type;
+ SLP_TREE_TYPE (slp_node) = store_vec_info_type;
}
gcc_assert (memory_access_type == SLP_TREE_MEMORY_ACCESS_TYPE (stmt_info));
@@ -9572,7 +9561,7 @@ vectorizable_load (vec_info *vinfo,
if (memory_access_type == VMAT_LOAD_STORE_LANES)
vinfo->any_known_not_updated_vssa = true;
- STMT_VINFO_TYPE (stmt_info) = load_vec_info_type;
+ SLP_TREE_TYPE (slp_node) = load_vec_info_type;
}
else
{
@@ -10211,29 +10200,6 @@ vectorizable_load (vec_info *vinfo,
tree bump;
tree vec_offset = NULL_TREE;
- if (STMT_VINFO_GATHER_SCATTER_P (stmt_info))
- {
- aggr_type = NULL_TREE;
- bump = NULL_TREE;
- }
- else if (memory_access_type == VMAT_GATHER_SCATTER)
- {
- aggr_type = elem_type;
- if (!costing_p)
- vect_get_strided_load_store_ops (stmt_info, vectype, loop_vinfo,
- gsi, &gs_info,
- &bump, &vec_offset, loop_lens);
- }
- else
- {
- if (memory_access_type == VMAT_LOAD_STORE_LANES)
- aggr_type = build_array_type_nelts (elem_type, group_size * nunits);
- else
- aggr_type = vectype;
- if (!costing_p)
- bump = vect_get_data_ptr_increment (vinfo, gsi, dr_info, aggr_type,
- memory_access_type, loop_lens);
- }
auto_vec<tree> vec_offsets;
auto_vec<tree> vec_masks;
@@ -10248,6 +10214,11 @@ vectorizable_load (vec_info *vinfo,
gcc_assert (alignment_support_scheme == dr_aligned
|| alignment_support_scheme == dr_unaligned_supported);
+ aggr_type = build_array_type_nelts (elem_type, group_size * nunits);
+ if (!costing_p)
+ bump = vect_get_data_ptr_increment (vinfo, gsi, dr_info, aggr_type,
+ memory_access_type, loop_lens);
+
unsigned int inside_cost = 0, prologue_cost = 0;
/* For costing some adjacent vector loads, we'd like to cost with
the total number of them once instead of cost each one by one. */
@@ -10409,20 +10380,31 @@ vectorizable_load (vec_info *vinfo,
{
gcc_assert (!grouped_load && !slp_perm);
- unsigned int inside_cost = 0, prologue_cost = 0;
-
/* 1. Create the vector or array pointer update chain. */
- if (!costing_p)
+ if (STMT_VINFO_GATHER_SCATTER_P (stmt_info))
{
- if (STMT_VINFO_GATHER_SCATTER_P (stmt_info))
+ aggr_type = NULL_TREE;
+ bump = NULL_TREE;
+ if (!costing_p)
vect_get_gather_scatter_ops (loop, slp_node, &gs_info, &dataref_ptr,
&vec_offsets);
- else
- dataref_ptr
- = vect_create_data_ref_ptr (vinfo, first_stmt_info, aggr_type,
- at_loop, offset, &dummy, gsi,
- &ptr_incr, false, bump);
}
+ else
+ {
+ aggr_type = elem_type;
+ if (!costing_p)
+ {
+ vect_get_strided_load_store_ops (stmt_info, vectype, loop_vinfo,
+ gsi, &gs_info,
+ &bump, &vec_offset, loop_lens);
+ dataref_ptr
+ = vect_create_data_ref_ptr (vinfo, first_stmt_info, aggr_type,
+ at_loop, offset, &dummy, gsi,
+ &ptr_incr, false, bump);
+ }
+ }
+
+ unsigned int inside_cost = 0, prologue_cost = 0;
gimple *new_stmt = NULL;
for (i = 0; i < vec_num; i++)
@@ -10744,6 +10726,11 @@ vectorizable_load (vec_info *vinfo,
return true;
}
+ aggr_type = vectype;
+ if (!costing_p)
+ bump = vect_get_data_ptr_increment (vinfo, gsi, dr_info, aggr_type,
+ memory_access_type, loop_lens);
+
poly_uint64 group_elt = 0;
unsigned int inside_cost = 0, prologue_cost = 0;
/* For costing some adjacent vector loads, we'd like to cost with
@@ -11749,7 +11736,7 @@ vectorizable_condition (vec_info *vinfo,
}
}
- STMT_VINFO_TYPE (stmt_info) = condition_vec_info_type;
+ SLP_TREE_TYPE (slp_node) = condition_vec_info_type;
vect_model_simple_cost (vinfo, 1, slp_node, cost_vec, kind);
return true;
}
@@ -12256,7 +12243,7 @@ vectorizable_comparison (vec_info *vinfo,
return false;
if (cost_vec)
- STMT_VINFO_TYPE (stmt_info) = comparison_vec_info_type;
+ SLP_TREE_TYPE (slp_node) = comparison_vec_info_type;
return true;
}
@@ -12657,8 +12644,8 @@ vect_analyze_stmt (vec_info *vinfo,
/* Stmts that are (also) "live" (i.e. - that are used out of the loop)
need extra handling, except for vectorizable reductions. */
if (!bb_vinfo
- && STMT_VINFO_TYPE (stmt_info) != reduc_vec_info_type
- && (STMT_VINFO_TYPE (stmt_info) != lc_phi_info_type
+ && SLP_TREE_TYPE (node) != reduc_vec_info_type
+ && (SLP_TREE_TYPE (node) != lc_phi_info_type
|| STMT_VINFO_DEF_TYPE (stmt_info) == vect_internal_def)
&& (!node->ldst_lanes || SLP_TREE_CODE (node) == VEC_PERM_EXPR)
&& !can_vectorize_live_stmts (as_a <loop_vec_info> (vinfo),
@@ -12694,7 +12681,7 @@ vect_transform_stmt (vec_info *vinfo,
tree saved_vectype = STMT_VINFO_VECTYPE (stmt_info);
STMT_VINFO_VECTYPE (stmt_info) = SLP_TREE_VECTYPE (slp_node);
- switch (STMT_VINFO_TYPE (stmt_info))
+ switch (SLP_TREE_TYPE (slp_node))
{
case type_demotion_vec_info_type:
case type_promotion_vec_info_type:
@@ -12811,7 +12798,7 @@ vect_transform_stmt (vec_info *vinfo,
done = true;
}
- if (STMT_VINFO_TYPE (stmt_info) != store_vec_info_type
+ if (SLP_TREE_TYPE (slp_node) != store_vec_info_type
&& (!slp_node->ldst_lanes
|| SLP_TREE_CODE (slp_node) == VEC_PERM_EXPR))
{
diff --git a/gcc/tree-vectorizer.cc b/gcc/tree-vectorizer.cc
index 066c8a8..f992856 100644
--- a/gcc/tree-vectorizer.cc
+++ b/gcc/tree-vectorizer.cc
@@ -715,7 +715,6 @@ vec_info::new_stmt_vec_info (gimple *stmt)
stmt_vec_info res = XCNEW (class _stmt_vec_info);
res->stmt = stmt;
- STMT_VINFO_TYPE (res) = undef_vec_info_type;
STMT_VINFO_RELEVANT (res) = vect_unused_in_scope;
STMT_VINFO_VECTORIZABLE (res) = true;
STMT_VINFO_REDUC_TYPE (res) = TREE_CODE_REDUCTION;
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index e8be608..203e5ad 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -205,6 +205,32 @@ enum vect_memory_access_type {
VMAT_GATHER_SCATTER
};
+/*-----------------------------------------------------------------*/
+/* Info on vectorized defs. */
+/*-----------------------------------------------------------------*/
+enum stmt_vec_info_type {
+ undef_vec_info_type = 0,
+ load_vec_info_type,
+ store_vec_info_type,
+ shift_vec_info_type,
+ op_vec_info_type,
+ call_vec_info_type,
+ call_simd_clone_vec_info_type,
+ assignment_vec_info_type,
+ condition_vec_info_type,
+ comparison_vec_info_type,
+ reduc_vec_info_type,
+ induc_vec_info_type,
+ type_promotion_vec_info_type,
+ type_demotion_vec_info_type,
+ type_conversion_vec_info_type,
+ cycle_phi_info_type,
+ lc_phi_info_type,
+ phi_info_type,
+ recurr_info_type,
+ loop_exit_ctrl_vec_info_type
+};
+
/************************************************************************
SLP
************************************************************************/
@@ -279,6 +305,13 @@ struct _slp_tree {
for loop vectorization. */
vect_memory_access_type memory_access_type;
+ /* The kind of operation as determined by analysis and a tagged
+ union with kind specific data. */
+ enum stmt_vec_info_type type;
+ union {
+ void *undef;
+ } u;
+
/* If not NULL this is a cached failed SLP discovery attempt with
the lanes that failed during SLP discovery as 'false'. This is
a copy of the matches array. */
@@ -364,6 +397,7 @@ public:
#define SLP_TREE_LANES(S) (S)->lanes
#define SLP_TREE_CODE(S) (S)->code
#define SLP_TREE_MEMORY_ACCESS_TYPE(S) (S)->memory_access_type
+#define SLP_TREE_TYPE(S) (S)->type
enum vect_partial_vector_style {
vect_partial_vectors_none,
@@ -1211,32 +1245,6 @@ public:
#define BB_VINFO_DATAREFS(B) (B)->shared->datarefs
#define BB_VINFO_DDRS(B) (B)->shared->ddrs
-/*-----------------------------------------------------------------*/
-/* Info on vectorized defs. */
-/*-----------------------------------------------------------------*/
-enum stmt_vec_info_type {
- undef_vec_info_type = 0,
- load_vec_info_type,
- store_vec_info_type,
- shift_vec_info_type,
- op_vec_info_type,
- call_vec_info_type,
- call_simd_clone_vec_info_type,
- assignment_vec_info_type,
- condition_vec_info_type,
- comparison_vec_info_type,
- reduc_vec_info_type,
- induc_vec_info_type,
- type_promotion_vec_info_type,
- type_demotion_vec_info_type,
- type_conversion_vec_info_type,
- cycle_phi_info_type,
- lc_phi_info_type,
- phi_info_type,
- recurr_info_type,
- loop_exit_ctrl_vec_info_type
-};
-
/* Indicates whether/how a variable is used in the scope of loop/basic
block. */
enum vect_relevant {
@@ -1329,8 +1337,6 @@ typedef struct data_reference *dr_p;
class _stmt_vec_info {
public:
- enum stmt_vec_info_type type;
-
/* Indicates whether this stmts is part of a computation whose result is
used outside the loop. */
bool live;
@@ -1555,9 +1561,6 @@ struct gather_scatter_info {
being added to the base. */
int scale;
- /* The definition type for the vectorized offset. */
- enum vect_def_type offset_dt;
-
/* The type of the vectorized offset. */
tree offset_vectype;
@@ -1569,7 +1572,6 @@ struct gather_scatter_info {
};
/* Access Functions. */
-#define STMT_VINFO_TYPE(S) (S)->type
#define STMT_VINFO_STMT(S) (S)->stmt
#define STMT_VINFO_RELEVANT(S) (S)->relevant
#define STMT_VINFO_LIVE_P(S) (S)->live
diff --git a/gcc/varasm.cc b/gcc/varasm.cc
index 8266282..000ad9e 100644
--- a/gcc/varasm.cc
+++ b/gcc/varasm.cc
@@ -871,7 +871,7 @@ mergeable_string_section (tree decl ATTRIBUTE_UNUSED,
if (HAVE_GAS_SHF_MERGE && flag_merge_constants
&& TREE_CODE (decl) == STRING_CST
&& TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
- && align <= 256
+ && align <= MAX_ALIGN_MERGABLE
&& (len = int_size_in_bytes (TREE_TYPE (decl))) > 0
&& TREE_STRING_LENGTH (decl) == len)
{
@@ -885,7 +885,7 @@ mergeable_string_section (tree decl ATTRIBUTE_UNUSED,
mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (TREE_TYPE (decl)));
modesize = GET_MODE_BITSIZE (mode);
- if (modesize >= 8 && modesize <= 256
+ if (modesize >= 8 && modesize <= MAX_ALIGN_MERGABLE
&& (modesize & (modesize - 1)) == 0)
{
if (align < modesize)
@@ -919,16 +919,14 @@ mergeable_string_section (tree decl ATTRIBUTE_UNUSED,
/* Return the section to use for constant merging. */
section *
-mergeable_constant_section (machine_mode mode ATTRIBUTE_UNUSED,
- unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED,
- unsigned int flags ATTRIBUTE_UNUSED)
+mergeable_constant_section (unsigned HOST_WIDE_INT size_bits,
+ unsigned HOST_WIDE_INT align,
+ unsigned int flags)
{
if (HAVE_GAS_SHF_MERGE && flag_merge_constants
- && mode != VOIDmode
- && mode != BLKmode
- && known_le (GET_MODE_BITSIZE (mode), align)
+ && size_bits <= align
&& align >= 8
- && align <= 256
+ && align <= MAX_ALIGN_MERGABLE
&& (align & (align - 1)) == 0)
{
const char *prefix = function_mergeable_rodata_prefix ();
@@ -940,6 +938,38 @@ mergeable_constant_section (machine_mode mode ATTRIBUTE_UNUSED,
}
return readonly_data_section;
}
+
+
+/* Return the section to use for constant merging. Like the above
+ but the size stored as a tree. */
+static section *
+mergeable_constant_section (tree size_bits,
+ unsigned HOST_WIDE_INT align,
+ unsigned int flags)
+{
+ if (!size_bits || !tree_fits_uhwi_p (size_bits))
+ return readonly_data_section;
+ return mergeable_constant_section (tree_to_uhwi (size_bits), align, flags);
+}
+
+
+/* Return the section to use for constant merging. Like the above
+ but given a mode rather than the size. */
+
+section *
+mergeable_constant_section (machine_mode mode,
+ unsigned HOST_WIDE_INT align,
+ unsigned int flags)
+{
+ /* If the mode is unknown (BLK or VOID), then return a non mergable section. */
+ if (mode == BLKmode || mode == VOIDmode)
+ return readonly_data_section;
+ unsigned HOST_WIDE_INT size;
+ if (!GET_MODE_BITSIZE (mode).is_constant (&size))
+ return readonly_data_section;
+ return mergeable_constant_section (size, align, flags);
+}
+
/* Given NAME, a putative register name, discard any customary prefixes. */
@@ -7453,7 +7483,7 @@ default_elf_select_section (tree decl, int reloc,
case SECCAT_RODATA_MERGE_STR_INIT:
return mergeable_string_section (DECL_INITIAL (decl), align, 0);
case SECCAT_RODATA_MERGE_CONST:
- return mergeable_constant_section (DECL_MODE (decl), align, 0);
+ return mergeable_constant_section (DECL_SIZE (decl), align, 0);
case SECCAT_SRODATA:
sname = ".sdata2";
break;
diff --git a/gcc/vec.h b/gcc/vec.h
index 9604edb..0ea7a49 100644
--- a/gcc/vec.h
+++ b/gcc/vec.h
@@ -2514,6 +2514,10 @@ public:
return false;
if (lhs.size () != rhs.size ())
return false;
+ /* Case where either is a NULL pointer and therefore, as both are valid,
+ both are empty slices with length 0. */
+ if (lhs.size () == 0)
+ return true;
return memcmp (lhs.begin (), rhs.begin (), lhs.size ()) == 0;
}
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 9b6504b..b48632f 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,36 @@
+2025-07-28 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/102181
+ * include/bits/stl_iterator_base_funcs.h (distance, advance):
+ Check C++20 iterator concepts and handle appropriately.
+ (__detail::__iter_category_converts_to_concept): New concept.
+ (__detail::__promotable_iterator): New concept.
+ * testsuite/24_iterators/operations/cxx20_iterators.cc: New
+ test.
+
+2025-07-28 Nathan Myers <ncm@cantrip.org>
+
+ PR libstdc++/119742
+ * include/debug/bitset: Add new ctor.
+
+2025-07-28 Luc Grosheintz <luc.grosheintz@gmail.com>
+
+ * include/std/mdspan: Small stylistic adjustments.
+
+2025-07-28 Luc Grosheintz <luc.grosheintz@gmail.com>
+
+ * testsuite/23_containers/mdspan/accessors/generic.cc: Refactor
+ test_ctor.
+
+2025-07-28 Tomasz KamiƄski <tkaminsk@redhat.com>
+
+ PR libstdc++/121196
+ * include/std/inplace_vector (std::erase): Provide default argument
+ for _Up parameter.
+ * testsuite/23_containers/inplace_vector/erasure.cc: Add test for
+ using braces-init-list as arguments to erase_if and use function
+ to verify content of inplace_vector
+
2025-07-25 Tuur Martens <tuurmartens4@gmail.com>
* include/bits/unordered_map.h: Rectify referencing of
diff --git a/libstdc++-v3/include/bits/stl_iterator_base_funcs.h b/libstdc++-v3/include/bits/stl_iterator_base_funcs.h
index 637159f..f78e535 100644
--- a/libstdc++-v3/include/bits/stl_iterator_base_funcs.h
+++ b/libstdc++-v3/include/bits/stl_iterator_base_funcs.h
@@ -130,6 +130,28 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
__distance(_OutputIterator, _OutputIterator, output_iterator_tag) = delete;
#endif
+#ifdef __glibcxx_concepts
+namespace __detail
+{
+ // Satisfied if ITER_TRAITS(Iter)::iterator_category is valid and is
+ // at least as strong as ITER_TRAITS(Iter)::iterator_concept.
+ template<typename _Iter>
+ concept __iter_category_converts_to_concept
+ = convertible_to<typename __iter_traits<_Iter>::iterator_category,
+ typename __iter_traits<_Iter>::iterator_concept>;
+
+ // Satisfied if the type is a C++20 iterator that defines iterator_concept,
+ // and its iterator_concept is stronger than its iterator_category (if any).
+ // Used by std::distance and std::advance to detect iterators which should
+ // dispatch based on their C++20 concept not their C++17 category.
+ template<typename _Iter>
+ concept __promotable_iterator
+ = input_iterator<_Iter>
+ && requires { typename __iter_traits<_Iter>::iterator_concept; }
+ && ! __iter_category_converts_to_concept<_Iter>;
+} // namespace __detail
+#endif
+
/**
* @brief A generalization of pointer arithmetic.
* @param __first An input iterator.
@@ -149,6 +171,24 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
typename iterator_traits<_InputIterator>::difference_type
distance(_InputIterator __first, _InputIterator __last)
{
+#ifdef __glibcxx_concepts
+ // A type which satisfies the C++20 random_access_iterator concept might
+ // have input_iterator_tag as its iterator_category type, which would
+ // mean we select the O(n) __distance. Or a C++20 std::input_iterator
+ // that is not a Cpp17InputIterator might have output_iterator_tag as
+ // its iterator_category type and then calling __distance with
+ // std::__iterator_category(__first) would be ill-formed.
+ // So for C++20 iterator types we can just choose to do the right thing.
+ if constexpr (__detail::__promotable_iterator<_InputIterator>)
+ {
+ if constexpr (random_access_iterator<_InputIterator>)
+ return __last - __first;
+ else
+ return std::__distance(std::move(__first), std::move(__last),
+ input_iterator_tag());
+ }
+ else // assume it meets the Cpp17InputIterator requirements:
+#endif
// concept requirements -- taken care of in __distance
return std::__distance(__first, __last,
std::__iterator_category(__first));
@@ -221,9 +261,31 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
inline _GLIBCXX17_CONSTEXPR void
advance(_InputIterator& __i, _Distance __n)
{
- // concept requirements -- taken care of in __advance
- typename iterator_traits<_InputIterator>::difference_type __d = __n;
- std::__advance(__i, __d, std::__iterator_category(__i));
+#ifdef __glibcxx_concepts
+ // A type which satisfies the C++20 bidirectional_iterator concept might
+ // have input_iterator_tag as its iterator_category type, which would
+ // mean we select the __advance overload which cannot move backwards.
+ // A C++20 random_access_iterator we might select the O(n) __advance
+ // if it doesn't meet the Cpp17RandomAccessIterator requirements.
+ // So for C++20 iterator types we can just choose to do the right thing.
+ if constexpr (__detail::__promotable_iterator<_InputIterator>
+ && ranges::__detail::__is_integer_like<_Distance>)
+ {
+ auto __d = static_cast<iter_difference_t<_InputIterator>>(__n);
+ if constexpr (random_access_iterator<_InputIterator>)
+ std::__advance(__i, __d, random_access_iterator_tag());
+ else if constexpr (bidirectional_iterator<_InputIterator>)
+ std::__advance(__i, __d, bidirectional_iterator_tag());
+ else
+ std::__advance(__i, __d, input_iterator_tag());
+ }
+ else // assume it meets the Cpp17InputIterator requirements:
+#endif
+ {
+ // concept requirements -- taken care of in __advance
+ typename iterator_traits<_InputIterator>::difference_type __d = __n;
+ std::__advance(__i, __d, std::__iterator_category(__i));
+ }
}
#if __cplusplus >= 201103L
diff --git a/libstdc++-v3/include/debug/bitset b/libstdc++-v3/include/debug/bitset
index ad9b7b5..e4d3e66 100644
--- a/libstdc++-v3/include/debug/bitset
+++ b/libstdc++-v3/include/debug/bitset
@@ -164,6 +164,17 @@ namespace __debug
_CharT __zero, _CharT __one = _CharT('1'))
: _Base(__str, __pos, __n, __zero, __one) { }
+#ifdef __cpp_lib_bitset // ... from string_view
+ template<class _CharT, class _Traits>
+ constexpr explicit
+ bitset(std::basic_string_view<_CharT, _Traits> __s,
+ std::basic_string_view<_CharT, _Traits>::size_type __position = 0,
+ std::basic_string_view<_CharT, _Traits>::size_type __n =
+ std::basic_string_view<_CharT, _Traits>::npos,
+ _CharT __zero = _CharT('0'), _CharT __one = _CharT('1'))
+ : _Base(__s, __position, __n, __zero, __one) { }
+#endif
+
_GLIBCXX23_CONSTEXPR
bitset(const _Base& __x) : _Base(__x) { }
diff --git a/libstdc++-v3/include/std/inplace_vector b/libstdc++-v3/include/std/inplace_vector
index 290cf6e..b5a81be 100644
--- a/libstdc++-v3/include/std/inplace_vector
+++ b/libstdc++-v3/include/std/inplace_vector
@@ -1354,7 +1354,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
- template<typename _Tp, size_t _Nm, typename _Up>
+ template<typename _Tp, size_t _Nm, typename _Up = _Tp>
constexpr size_t
erase(inplace_vector<_Tp, _Nm>& __cont, const _Up& __value)
{
diff --git a/libstdc++-v3/include/std/mdspan b/libstdc++-v3/include/std/mdspan
index 055778d..5e79d4b 100644
--- a/libstdc++-v3/include/std/mdspan
+++ b/libstdc++-v3/include/std/mdspan
@@ -159,9 +159,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
static constexpr span<const size_t>
_S_static_extents(size_t __begin, size_t __end) noexcept
- {
- return {_Extents.data() + __begin, _Extents.data() + __end};
- }
+ { return {_Extents.data() + __begin, _Extents.data() + __end}; }
constexpr span<const _IndexType>
_M_dynamic_extents(size_t __begin, size_t __end) const noexcept
@@ -185,10 +183,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
concept
__valid_static_extent = _Extent == dynamic_extent
|| _Extent <= numeric_limits<_IndexType>::max();
- }
- namespace __mdspan
- {
template<typename _Extents>
constexpr span<const size_t>
__static_extents(size_t __begin = 0, size_t __end = _Extents::rank())
@@ -199,9 +194,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
constexpr span<const typename _Extents::index_type>
__dynamic_extents(const _Extents& __exts, size_t __begin = 0,
size_t __end = _Extents::rank()) noexcept
- {
- return __exts._M_exts._M_dynamic_extents(__begin, __end);
- }
+ { return __exts._M_exts._M_dynamic_extents(__begin, __end); }
}
template<typename _IndexType, size_t... _Extents>
@@ -1248,9 +1241,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
[[nodiscard]]
constexpr bool
empty() const noexcept
- {
- return __mdspan::__empty(extents());
- }
+ { return __mdspan::__empty(extents()); }
friend constexpr void
swap(mdspan& __x, mdspan& __y) noexcept
@@ -1299,7 +1290,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
constexpr bool
is_strided() const noexcept(noexcept(_M_mapping.is_strided()))
- { return _M_mapping. is_strided(); }
+ { return _M_mapping.is_strided(); }
constexpr index_type
stride(rank_type __r) const { return _M_mapping.stride(__r); }
diff --git a/libstdc++-v3/testsuite/23_containers/inplace_vector/erasure.cc b/libstdc++-v3/testsuite/23_containers/inplace_vector/erasure.cc
index c7fda09..8fb56e9 100644
--- a/libstdc++-v3/testsuite/23_containers/inplace_vector/erasure.cc
+++ b/libstdc++-v3/testsuite/23_containers/inplace_vector/erasure.cc
@@ -2,18 +2,38 @@
#include <inplace_vector>
#include <testsuite_hooks.h>
+#include <span>
+
+template<typename T, size_t N>
+constexpr bool
+eq(const std::inplace_vector<T, N>& l, std::span<const T> r) {
+ if (l.size() != r.size())
+ return false;
+ for (auto i = 0u; i < l.size(); ++i)
+ if (l[i] != r[i])
+ return false;
+ return true;
+};
constexpr void
test_erase()
{
- std::inplace_vector<int, 15> c{1, 2, 3, 4, 5, 6, 5, 4, 3, 2, 1, 4, 4, 9};
+ std::inplace_vector<int, 15> c{1, 0, 3, 4, 5, 6, 5, 4, 3, 0, 1, 4, 4, 9};
std::erase(c, 4);
VERIFY( c.size() == 10 );
std::erase(c, 1);
VERIFY( c.size() == 8 );
std::erase(c, 9);
VERIFY( c.size() == 7 );
- VERIFY( (c == std::inplace_vector<int, 15>{2, 3, 5, 6, 5, 3, 2}) );
+ VERIFY( eq(c, {0, 3, 5, 6, 5, 3, 0}) );
+
+ std::erase(c, {});
+ VERIFY( c.size() == 5 );
+ VERIFY( eq(c, {3, 5, 6, 5, 3}) );
+
+ std::erase(c, {5});
+ VERIFY( c.size() == 3 );
+ VERIFY( eq(c, {3, 6, 3}) );
std::inplace_vector<int, 0> e;
std::erase(e, 10);
@@ -29,7 +49,7 @@ test_erase_if()
std::erase_if(c, [](int i) { return i == 4; });
VERIFY( c.size() == 8 );
std::erase_if(c, [](int i) { return i & 1; });
- VERIFY( (c == std::inplace_vector<int, 15>{2, 2}) );
+ VERIFY( eq(c, {2, 2}) );
std::inplace_vector<int, 0> e;
std::erase_if(e, [](int i) { return i > 5; });
diff --git a/libstdc++-v3/testsuite/23_containers/mdspan/accessors/generic.cc b/libstdc++-v3/testsuite/23_containers/mdspan/accessors/generic.cc
index c335035..66009ad 100644
--- a/libstdc++-v3/testsuite/23_containers/mdspan/accessors/generic.cc
+++ b/libstdc++-v3/testsuite/23_containers/mdspan/accessors/generic.cc
@@ -29,44 +29,59 @@ class Base
class Derived : public Base
{ };
-template<template<typename T> typename Accessor>
+template<typename RhsAccessor, typename LhsAccessor, bool ExpectConvertible>
+ constexpr void
+ check_convertible()
+ {
+ RhsAccessor rhs;
+ [[maybe_unused]] LhsAccessor lhs(rhs);
+ static_assert(std::is_nothrow_constructible_v<LhsAccessor, RhsAccessor>);
+ static_assert(std::is_convertible_v<RhsAccessor, LhsAccessor> == ExpectConvertible);
+ }
+
+template<template<typename T> typename LhsAccessor,
+ template<typename T> typename RhsAccessor = LhsAccessor,
+ bool ExpectConvertible = true>
constexpr bool
test_ctor()
{
// T -> T
- static_assert(std::is_nothrow_constructible_v<Accessor<double>,
- Accessor<double>>);
- static_assert(std::is_convertible_v<Accessor<double>, Accessor<double>>);
+ check_convertible<RhsAccessor<double>, LhsAccessor<double>,
+ ExpectConvertible>();
// T -> const T
- static_assert(std::is_convertible_v<Accessor<double>,
- Accessor<const double>>);
- static_assert(std::is_convertible_v<Accessor<Derived>,
- Accessor<const Derived>>);
+ check_convertible<RhsAccessor<double>, LhsAccessor<const double>,
+ ExpectConvertible>();
+ check_convertible<RhsAccessor<Derived>, LhsAccessor<const Derived>,
+ ExpectConvertible>();
// const T -> T
- static_assert(!std::is_constructible_v<Accessor<double>,
- Accessor<const double>>);
- static_assert(!std::is_constructible_v<Accessor<Derived>,
- Accessor<const Derived>>);
+ static_assert(!std::is_constructible_v<LhsAccessor<double>,
+ RhsAccessor<const double>>);
+ static_assert(!std::is_constructible_v<LhsAccessor<Derived>,
+ RhsAccessor<const Derived>>);
// T <-> volatile T
- static_assert(std::is_convertible_v<Accessor<int>, Accessor<volatile int>>);
- static_assert(!std::is_constructible_v<Accessor<int>,
- Accessor<volatile int>>);
+ check_convertible<RhsAccessor<int>, LhsAccessor<volatile int>,
+ ExpectConvertible>();
+ static_assert(!std::is_constructible_v<LhsAccessor<int>,
+ RhsAccessor<volatile int>>);
// size difference
- static_assert(!std::is_constructible_v<Accessor<char>, Accessor<int>>);
+ static_assert(!std::is_constructible_v<LhsAccessor<char>,
+ RhsAccessor<int>>);
// signedness
- static_assert(!std::is_constructible_v<Accessor<int>,
- Accessor<unsigned int>>);
- static_assert(!std::is_constructible_v<Accessor<unsigned int>,
- Accessor<int>>);
+ static_assert(!std::is_constructible_v<LhsAccessor<int>,
+ RhsAccessor<unsigned int>>);
+ static_assert(!std::is_constructible_v<LhsAccessor<unsigned int>,
+ RhsAccessor<int>>);
// Derived <-> Base
- static_assert(!std::is_constructible_v<Accessor<Base>, Accessor<Derived>>);
- static_assert(!std::is_constructible_v<Accessor<Derived>, Accessor<Base>>);
+ static_assert(!std::is_constructible_v<LhsAccessor<Base>,
+ RhsAccessor<Derived>>);
+ static_assert(!std::is_constructible_v<LhsAccessor<Derived>,
+ RhsAccessor<Base>>);
return true;
}
diff --git a/libstdc++-v3/testsuite/24_iterators/operations/cxx20_iterators.cc b/libstdc++-v3/testsuite/24_iterators/operations/cxx20_iterators.cc
new file mode 100644
index 0000000..b613c37
--- /dev/null
+++ b/libstdc++-v3/testsuite/24_iterators/operations/cxx20_iterators.cc
@@ -0,0 +1,60 @@
+// { dg-do run { target c++20 } }
+
+#include <ranges>
+#include <testsuite_iterators.h>
+#include <testsuite_hooks.h>
+
+// Bug 102181 std::advance and std::views::iota<std::int64_t> don't work
+void
+test_pr102181()
+{
+#ifdef __SIZEOF_INT128__
+ using type = unsigned __int128;
+#else
+ using type = unsigned long;
+#endif
+ auto v = std::ranges::iota_view(type(0), type(10));
+ auto b = v.begin();
+ VERIFY( std::distance(b, std::next(b)) == 1 );
+ std::advance(b, std::iter_difference_t<decltype(b)>(1));
+ VERIFY( *b == 1 );
+ VERIFY( std::distance(b, v.end()) == 9 );
+}
+
+// https://stackoverflow.com/questions/68100775/rangesviewtransform-produces-an-inputiterator-preventing-the-use-of-stdpre
+void
+test_transform_view_iterator()
+{
+ int a[] = {0, 1, 2, 3};
+ __gnu_test::random_access_container<int> rr(a);
+ auto rx = std::ranges::views::transform(rr, std::identity{});
+ auto re = rx.end();
+ VERIFY( *std::prev(re) == 3 );
+ VERIFY( std::distance(rx.begin(), re) == 4 );
+
+ __gnu_test::bidirectional_container<int> br(a);
+ auto bx = std::ranges::views::transform(br, std::identity{});
+ auto be = bx.end();
+ VERIFY( *std::prev(be) == 3 );
+ VERIFY( std::distance(bx.begin(), be) == 4 );
+
+ __gnu_test::forward_container<int> fr(a);
+ auto fx = std::ranges::views::transform(br, std::identity{});
+ auto fb = fx.begin();
+ VERIFY( *std::next(fb) == 1 );
+ VERIFY( std::distance(fb, fx.end()) == 4 );
+
+ __gnu_test::test_input_range<int> ir(a);
+ auto ix = std::ranges::views::transform(ir, std::identity{});
+ auto ii = ix.begin();
+ std::advance(ii, 1);
+ VERIFY( *ii == 1 );
+ // N.B. cannot use std::distance or std::next here because there is no
+ // iterator_traits<decltype(ii)>::difference_type for this iterator.
+}
+
+int main()
+{
+ test_pr102181();
+ test_transform_view_iterator();
+}
diff --git a/libstdc++-v3/testsuite/std/format/ranges/format_kind.cc b/libstdc++-v3/testsuite/std/format/ranges/format_kind.cc
index 14b9ff2..1450fba 100644
--- a/libstdc++-v3/testsuite/std/format/ranges/format_kind.cc
+++ b/libstdc++-v3/testsuite/std/format/ranges/format_kind.cc
@@ -75,7 +75,9 @@ void test_override()
CustFormat<int, std::range_format::set> setf{1, 2, 3};
VERIFY( std::format("{}", setf) == "{1, 2, 3}" );
- // TODO test map once formatter for pair is implenented
+ CustFormat<std::pair<int, int>, std::range_format::map> mapf
+ {{1, 11}, {2, 22}, {3, 33}};
+ VERIFY( std::format("{}", mapf) == "{1: 11, 2: 22, 3: 33}" );
CustFormat<char, std::range_format::string> stringf{'a', 'b', 'c', 'd'};
VERIFY( std::format("{}", stringf) == "abcd" );