From f737b65af9bb992407e7f4e580286e3f981f14e8 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Mon, 27 Oct 2025 18:11:25 +0800 Subject: [PATCH 01/29] x86: Compile builtin-copysign-8b.c with -mtune=generic Compile builtin-copysign-8b.c with -mtune=generic so that it passes with $ make check-gcc RUNTESTFLAGS="i386.exp=builtin-copysign-8b.c --target_board='unix{-m64\ -march=cascadelake}'" PR target/122323 * gcc.target/i386/builtin-copysign-8b.c: Add -mtune=generic. Signed-off-by: H.J. Lu (cherry picked from commit 3ce0b19b87e9146c47343aab5088d144e739ce57) --- gcc/testsuite/gcc.target/i386/builtin-copysign-8b.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/testsuite/gcc.target/i386/builtin-copysign-8b.c b/gcc/testsuite/gcc.target/i386/builtin-copysign-8b.c index 8f0cb27a2464..dc9e46121de0 100644 --- a/gcc/testsuite/gcc.target/i386/builtin-copysign-8b.c +++ b/gcc/testsuite/gcc.target/i386/builtin-copysign-8b.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-O2 -mno-avx512f -mavx" } */ +/* { dg-options "-O2 -mno-avx512f -mavx -mtune=generic" } */ /* Keep labels and directives ('.cfi_startproc', '.cfi_endproc'). */ /* { dg-final { check-function-bodies "**" "" "" { target { ! ia32 } } {^\t?\.} } } */ From f3d0c95570d59bef636625c8ed4c68a1884bab1b Mon Sep 17 00:00:00 2001 From: Tamar Christina Date: Fri, 17 Oct 2025 15:43:04 +0100 Subject: [PATCH 02/29] AArch64: Extend intrinsics framework to account for merging predications without gp [PR121604] In PR121604 the problem was noted that currently the SVE intrinsics infrastructure assumes that for any predicated operation that the GP is at the first argument position which has a svbool_t or for a unary merging operation that it's in the second position. However you have intrinsics like fmov_lane which have an svbool_t but it's not a GP. You also have instructions like BRKB which work only on predicates so it incorrectly determines the first operand to be the GP, while that's the inactive lanes. However during apply_predication we do have the information about where the GP is. This patch re-organizes the code to record this information into the function_instance such that folders have access to this information. For functions that are outliers like pmov_lane we can now override the availability of the intrinsics having a GP. gcc/ChangeLog: PR target/121604 * config/aarch64/aarch64-sve-builtins-shapes.cc (apply_predication): Store gp_index. (struct pmov_to_vector_lane_def): Mark instruction as has no GP. * config/aarch64/aarch64-sve-builtins.h (function_instance::gp_value, function_instance::inactive_values, function_instance::gp_index, function_shape::has_gp_argument_p): New. * config/aarch64/aarch64-sve-builtins.cc (gimple_folder::fold_pfalse): Simplify code and use GP helpers. gcc/testsuite/ChangeLog: PR target/121604 * gcc.target/aarch64/sve/pr121604_brk.c: New test. * gcc.target/aarch64/sve2/pr121604_pmov.c: New test. Co-authored-by: Jennifer Schmitz (cherry picked from commit d1965b1fd8938f35f78be503e36b98b406751e21) --- .../aarch64/aarch64-sve-builtins-shapes.cc | 28 ++++++++++++- gcc/config/aarch64/aarch64-sve-builtins.cc | 22 +++++----- gcc/config/aarch64/aarch64-sve-builtins.h | 40 +++++++++++++++++++ .../gcc.target/aarch64/sve/pr121604_brk.c | 25 ++++++++++++ .../gcc.target/aarch64/sve2/pr121604_pmov.c | 16 ++++++++ 5 files changed, 117 insertions(+), 14 deletions(-) create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/pr121604_brk.c create mode 100644 gcc/testsuite/gcc.target/aarch64/sve2/pr121604_pmov.c diff --git a/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc b/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc index af23a154d0e8..8349221797b3 100644 --- a/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc +++ b/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc @@ -21,7 +21,10 @@ #include "system.h" #include "coretypes.h" #include "tm.h" +#include "basic-block.h" #include "tree.h" +#include "function.h" +#include "gimple.h" #include "rtl.h" #include "tm_p.h" #include "memmodel.h" @@ -68,23 +71,36 @@ za_group_is_pure_overload (const function_group_info &group) types in ARGUMENT_TYPES. RETURN_TYPE is the type returned by the function. */ static void -apply_predication (const function_instance &instance, tree return_type, +apply_predication (function_instance &instance, tree return_type, vec &argument_types) { + /* Initially mark the function as not being predicated. */ + instance.gp_index = -1; + /* There are currently no SME ZA instructions that have both merging and unpredicated forms, so for simplicity, the predicates are always included in the original format string. */ if (instance.pred != PRED_none && instance.pred != PRED_za_m) { argument_types.quick_insert (0, instance.gp_type ()); + instance.gp_index = 0; /* For unary merge operations, the first argument is a vector with the same type as the result. For unary_convert_narrowt it also provides the "bottom" half of active elements, and is present for all types of predication. */ auto nargs = argument_types.length () - 1; if (instance.shape->has_merge_argument_p (instance, nargs)) - argument_types.quick_insert (0, return_type); + { + argument_types.quick_insert (0, return_type); + instance.gp_index = 1; + } } + + /* In this case the predicate type we added above is a non-governing + predicate operand (and there is no GP), so update the gp_index value + accordingly. */ + if (!instance.shape->has_gp_argument_p (instance)) + instance.gp_index = -1; } /* Parse and move past an element type in FORMAT and return it as a type @@ -3301,6 +3317,14 @@ struct pmov_to_vector_lane_def : public overloaded_base<0> but it doesn't currently have the necessary information. */ return c.require_immediate_range (1, 1, bytes - 1); } + + /* This function has a predicate argument, and is a merging instruction, but + the predicate is not a GP. */ + bool + has_gp_argument_p (const function_instance &) const override + { + return false; + } }; SHAPE (pmov_to_vector_lane) diff --git a/gcc/config/aarch64/aarch64-sve-builtins.cc b/gcc/config/aarch64/aarch64-sve-builtins.cc index 24feb7ce1578..ad0d38934e21 100644 --- a/gcc/config/aarch64/aarch64-sve-builtins.cc +++ b/gcc/config/aarch64/aarch64-sve-builtins.cc @@ -3630,24 +3630,22 @@ gimple_folder::redirect_pred_x () gimple * gimple_folder::fold_pfalse () { - if (pred == PRED_none) + tree gp = gp_value (call); + /* If there isn't a GP then we can't do any folding as the instruction isn't + predicated. */ + if (!gp) return nullptr; - tree arg0 = gimple_call_arg (call, 0); + if (pred == PRED_m) { - /* Unary function shapes with _m predication are folded to the - inactive vector (arg0), while other function shapes are folded - to op1 (arg1). */ - tree arg1 = gimple_call_arg (call, 1); - if (is_pfalse (arg1)) - return fold_call_to (arg0); - if (is_pfalse (arg0)) - return fold_call_to (arg1); + tree val = inactive_values (call); + if (is_pfalse (gp)) + return fold_call_to (val); return nullptr; } - if ((pred == PRED_x || pred == PRED_z) && is_pfalse (arg0)) + if ((pred == PRED_x || pred == PRED_z) && is_pfalse (gp)) return fold_call_to (build_zero_cst (TREE_TYPE (lhs))); - if (pred == PRED_implicit && is_pfalse (arg0)) + if (pred == PRED_implicit && is_pfalse (gp)) { unsigned int flags = call_properties (); /* Folding to lhs = {0, ...} is not appropriate for intrinsics with diff --git a/gcc/config/aarch64/aarch64-sve-builtins.h b/gcc/config/aarch64/aarch64-sve-builtins.h index c145b8065ae3..7e1539a0c722 100644 --- a/gcc/config/aarch64/aarch64-sve-builtins.h +++ b/gcc/config/aarch64/aarch64-sve-builtins.h @@ -402,6 +402,8 @@ public: bool could_trap_p () const; vector_type_index gp_type_index () const; + tree gp_value (gcall *) const; + tree inactive_values (gcall *) const; tree gp_type () const; unsigned int vectors_per_tuple () const; @@ -435,6 +437,7 @@ public: group_suffix_index group_suffix_id; predication_index pred; fpm_mode_index fpm_mode; + int gp_index; }; class registered_function; @@ -800,6 +803,8 @@ public: virtual bool has_merge_argument_p (const function_instance &, unsigned int) const; + virtual bool has_gp_argument_p (const function_instance &) const; + virtual bool explicit_type_suffix_p (unsigned int) const = 0; /* True if the group suffix is present in overloaded names. @@ -948,6 +953,33 @@ function_instance::gp_type () const return acle_vector_types[0][gp_type_index ()]; } +/* Return the tree value that should be used as the governing predicate of + this function. If none then return NULL_TREE. */ +inline tree +function_instance::gp_value (gcall *call) const +{ + if (gp_index < 0) + return NULL_TREE; + + return gimple_call_arg (call, gp_index); +} + +/* Return the tree value that should be used for the inactive lanes should this + function be a predicated function with a gp. Otherwise return NULL_TREE. */ +inline tree +function_instance::inactive_values (gcall *call) const +{ + if (gp_index < 0) + return NULL_TREE; + + /* Function is unary with m predicate. */ + if (gp_index == 1) + return gimple_call_arg (call, 0); + + /* Else the inactive values are the next element. */ + return gimple_call_arg (call, 1); +} + /* If the function operates on tuples of vectors, return the number of vectors in the tuples, otherwise return 1. */ inline unsigned int @@ -1122,6 +1154,14 @@ function_shape::has_merge_argument_p (const function_instance &instance, return nargs == 1 && instance.pred == PRED_m; } +/* Return true if INSTANCE has an predicate argument that can be used as the global + predicate. */ +inline bool +function_shape::has_gp_argument_p (const function_instance &instance) const +{ + return instance.pred != PRED_none; +} + /* Return the mode of the result of a call. */ inline machine_mode function_expander::result_mode () const diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pr121604_brk.c b/gcc/testsuite/gcc.target/aarch64/sve/pr121604_brk.c new file mode 100644 index 000000000000..a474a20554d3 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/pr121604_brk.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +/* { dg-final { check-function-bodies "**" "" "" } } */ + +#include + +/* +** foo: +** ptrue p0\.b, all +** brkb p0\.b, p0/z, p0\.b +** ret +*/ +svbool_t foo () { + return svbrkb_b_m (svpfalse (), svptrue_b8 (), svptrue_b8 ()); +} + +/* +** bar: +** ptrue p0\.b, all +** brka p0\.b, p0/z, p0\.b +** ret +*/ +svbool_t bar () { + return svbrka_b_m (svpfalse (), svptrue_b8 (), svptrue_b8 ()); +} diff --git a/gcc/testsuite/gcc.target/aarch64/sve2/pr121604_pmov.c b/gcc/testsuite/gcc.target/aarch64/sve2/pr121604_pmov.c new file mode 100644 index 000000000000..16844ee4add3 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve2/pr121604_pmov.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -march=armv8.2-a+sve2p1" } */ +/* { dg-final { check-function-bodies "**" "" "" } } */ + +#include + +/* +** f: +** pfalse p([0-7]+)\.b +** mov z0\.b, #-1 +** pmov z0\[1\], p\1\.d +** ret +*/ +svuint64_t f () { + return svpmov_lane_u64_m (svdup_u64 (~0UL), svpfalse (), 1); +} From 9b1141fa8fc981f99cfabfbcc3cc23269d359c69 Mon Sep 17 00:00:00 2001 From: Jeff Law Date: Mon, 13 Oct 2025 14:33:10 -0600 Subject: [PATCH 03/29] [RISC-V][PR target/120674] Avoid division by zero in dwarf emitter when vector is not enabled This is a RISC-V specific failure in the dwarf2 emitter. When vector is not enabled riscv_convert_vector_chunks sets the riscv_vector_chunks poly_int to [1, 0]. riscv_dwarf_poly_indeterminite_value pulls out that 0 coefficient and uses that as FACTOR triggering a divide by zero here: > /* Add COEFF * ((REGNO / FACTOR) - BIAS) to the value: > add COEFF * (REGNO / FACTOR) now and subtract > COEFF * BIAS from the final constant part. */ > constant -= coeff * bias; > add_loc_descr (&ret, new_reg_loc_descr (regno, 0)); > if (coeff % factor == 0) > coeff /= factor; > else > { > int amount = exact_log2 (factor); > gcc_assert (amount >= 0); > add_loc_descr (&ret, int_loc_descriptor (amount)); > add_loc_descr (&ret, new_loc_descr (DW_OP_shr, 0, 0)); > } Per Robin's recommendation this patch adjusts riscv_dwarf_poly_indeterminite_value to never set FACTOR to 0, but instead detect this case and adjust its value to 1. That fixes the ICE and looks good across the board in my tester. Waiting on pre-commit CI, of course. PR target/120674 gcc/ * config/riscv/riscv.cc (riscv_dwarf_poly_indeterminite_value): Do not set FACTOR to zero, for that case use one instead. gcc/testsuite * gcc.target/riscv/pr120674.c: New test. (cherry picked from commit a92369a6be95c8df1525b02635b9e7c16fc3640e) --- gcc/config/riscv/riscv.cc | 7 +++++++ gcc/testsuite/gcc.target/riscv/pr120674.c | 6 ++++++ 2 files changed, 13 insertions(+) create mode 100644 gcc/testsuite/gcc.target/riscv/pr120674.c diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index 472c2e60d9f5..314524ac1c87 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -11809,6 +11809,13 @@ riscv_dwarf_poly_indeterminate_value (unsigned int i, unsigned int *factor, */ gcc_assert (i == 1); *factor = BYTES_PER_RISCV_VECTOR.coeffs[1]; + + /* The factor will be zero if vector is not enabled. That ultimately + causes problems in the dwarf2 emitter as the factor is used for + a division, causing a divide by zero. */ + if (*factor == 0) + *factor = 1; + *offset = 1; return RISCV_DWARF_VLENB; } diff --git a/gcc/testsuite/gcc.target/riscv/pr120674.c b/gcc/testsuite/gcc.target/riscv/pr120674.c new file mode 100644 index 000000000000..ec8835feb24d --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/pr120674.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-additional-options "-g -w -march=rv32gcv -mabi=ilp32" { target rv32 } } */ +/* { dg-additional-options "-g -w -march=rv64gcv -mabi=lp64d" { target rv64 } } */ + +#pragma riscv intrinsic "vector" +void GB_AxB_saxpy5_unrolled_rvv() { vfloat64m8_t vc; } From e55dcff97708a4937dc4d8736b8b3074ebbff6f3 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Mon, 27 Oct 2025 17:43:17 +0100 Subject: [PATCH 04/29] phiopt: Fix up DEBUG_EXPR_DECL creation in spaceship_replacement [PR122394] The following testcase ICEs in gcc 15 (and is at least latent in 12-14 too), because the DEBUG_EXPR_DECL has incorrect mode. It has TREE_TYPE (orig_use_lhs) type, but TYPE_MODE (type) rather than TYPE_MODE (TREE_TYPE (orig_use_lhs)) where the two types are sometimes the same, but sometimes different (same if !has_cast_debug_uses, different otherwise). Though, there wouldn't be the this issue if it used the proper API to create the DEBUG_EXPR_DECL which takes care of everything. This is the sole spot that doesn't use that API. Doesn't affect the trunk because the code has been removed and replaced with different stuff after the libstdc++ ABI change in r16-3474. Before r15-5557 the mode has been always wrong because this was done only for has_cast_debug_uses. And the bug has been introduced with r12-5490. Enough archeology, while it could be fixed by changing the second SET_DECL_MODE argument, I think it is better to use build_debug_expr_decl. 2025-10-27 Jakub Jelinek PR tree-optimization/122394 * tree-ssa-phiopt.cc (spaceship_replacement): Use build_debug_expr_decl instead of manually building DEBUG_EXPR_DECL and getting SET_DECL_MODE wrong. * g++.dg/opt/pr122394.C: New test. --- gcc/testsuite/g++.dg/opt/pr122394.C | 20 ++++++++++++++++++++ gcc/tree-ssa-phiopt.cc | 6 ++---- 2 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/g++.dg/opt/pr122394.C diff --git a/gcc/testsuite/g++.dg/opt/pr122394.C b/gcc/testsuite/g++.dg/opt/pr122394.C new file mode 100644 index 000000000000..1f84bebd74c2 --- /dev/null +++ b/gcc/testsuite/g++.dg/opt/pr122394.C @@ -0,0 +1,20 @@ +// PR tree-optimization/122394 +// { dg-do compile { target c++23 } } +// { dg-options "-O1 -g" } + +#include + +struct A { + friend auto operator<=> (A, A) = default; + double a; +}; +void foo (); +A b, c; + +void +bar () +{ + bool d = c >= b; + if (d) + foo (); +} diff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc index aaebae6b38c0..3e0ad9d3bb09 100644 --- a/gcc/tree-ssa-phiopt.cc +++ b/gcc/tree-ssa-phiopt.cc @@ -2995,10 +2995,8 @@ spaceship_replacement (basic_block cond_bb, basic_block middle_bb, if (has_cast_debug_uses || (HONOR_NANS (TREE_TYPE (lhs1)) && !is_cast)) { - tree temp3 = make_node (DEBUG_EXPR_DECL); - DECL_ARTIFICIAL (temp3) = 1; - TREE_TYPE (temp3) = TREE_TYPE (orig_use_lhs); - SET_DECL_MODE (temp3, TYPE_MODE (type)); + tree temp3 + = build_debug_expr_decl (TREE_TYPE (orig_use_lhs)); if (has_cast_debug_uses) t = fold_convert (TREE_TYPE (temp3), temp2); else From 18540d2241c3550e5368d342685f5fb3d1130a4d Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Tue, 28 Oct 2025 00:33:02 +0000 Subject: [PATCH 05/29] Daily bump. --- gcc/ChangeLog | 32 ++++++++++++++++++++++++++++++++ gcc/DATESTAMP | 2 +- gcc/testsuite/ChangeLog | 31 +++++++++++++++++++++++++++++++ 3 files changed, 64 insertions(+), 1 deletion(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d2d239191580..624d726b4821 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,35 @@ +2025-10-27 Jakub Jelinek + + PR tree-optimization/122394 + * tree-ssa-phiopt.cc (spaceship_replacement): Use + build_debug_expr_decl instead of manually building DEBUG_EXPR_DECL + and getting SET_DECL_MODE wrong. + +2025-10-27 Jeff Law + + Backported from master: + 2025-10-13 Jeff Law + + PR target/120674 + * config/riscv/riscv.cc (riscv_dwarf_poly_indeterminite_value): Do not + set FACTOR to zero, for that case use one instead. + +2025-10-27 Tamar Christina + + Backported from master: + 2025-10-17 Tamar Christina + Jennifer Schmitz + + PR target/121604 + * config/aarch64/aarch64-sve-builtins-shapes.cc (apply_predication): + Store gp_index. + (struct pmov_to_vector_lane_def): Mark instruction as has no GP. + * config/aarch64/aarch64-sve-builtins.h (function_instance::gp_value, + function_instance::inactive_values, function_instance::gp_index, + function_shape::has_gp_argument_p): New. + * config/aarch64/aarch64-sve-builtins.cc (gimple_folder::fold_pfalse): + Simplify code and use GP helpers. + 2025-10-26 LIU Hao Backported from master: diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 6e95effb6d93..0bfc1e9884d3 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20251027 +20251028 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 89f374afaf80..dbe976777497 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,34 @@ +2025-10-27 Jakub Jelinek + + PR tree-optimization/122394 + * g++.dg/opt/pr122394.C: New test. + +2025-10-27 Jeff Law + + Backported from master: + 2025-10-13 Jeff Law + + PR target/120674 + * gcc.target/riscv/pr120674.c: New test. + +2025-10-27 Tamar Christina + + Backported from master: + 2025-10-17 Tamar Christina + Jennifer Schmitz + + PR target/121604 + * gcc.target/aarch64/sve/pr121604_brk.c: New test. + * gcc.target/aarch64/sve2/pr121604_pmov.c: New test. + +2025-10-27 H.J. Lu + + Backported from master: + 2025-10-27 H.J. Lu + + PR target/122323 + * gcc.target/i386/builtin-copysign-8b.c: Add -mtune=generic. + 2025-10-26 Alexandre Oliva Backported from master: From fc900b25fa353849649a6a221ead2da580408820 Mon Sep 17 00:00:00 2001 From: Nathaniel Shead Date: Sat, 18 Oct 2025 23:43:14 +1100 Subject: [PATCH 06/29] c++/modules: Use containing type as key for all member lambdas [PR122310] The ICE in the linked PR occurs because we first stream the lambda type before its keyed decl has been streamed, but the key decl's type depends on the lambda. And so when streaming the key decl to check for an existing decl to merge with, merging the key decl itself crashes because its type has only been partially streamed. This patch fixes the issue by generalising the existing FIELD_DECL handling to any class member using the outermost containing TYPE_DECL as its key type. This way we can guarantee that the key decl has been streamed before the lambda type is otherwise needed. PR c++/122310 gcc/cp/ChangeLog: * module.cc (get_keyed_decl_scope): New function. (trees_out::get_merge_kind): Use it. (trees_out::key_mergeable): Use it. (maybe_key_decl): Key to the containing type for all members. gcc/testsuite/ChangeLog: * g++.dg/modules/lambda-12.h: New test. * g++.dg/modules/lambda-12_a.H: New test. * g++.dg/modules/lambda-12_b.C: New test. Signed-off-by: Nathaniel Shead Reviewed-by: Jason Merrill (cherry picked from commit 8212abbeffa69f143808e126f40c67f3eb7e7844) --- gcc/cp/module.cc | 77 ++++++++++++++-------- gcc/testsuite/g++.dg/modules/lambda-12.h | 27 ++++++++ gcc/testsuite/g++.dg/modules/lambda-12_a.H | 5 ++ gcc/testsuite/g++.dg/modules/lambda-12_b.C | 5 ++ 4 files changed, 87 insertions(+), 27 deletions(-) create mode 100644 gcc/testsuite/g++.dg/modules/lambda-12.h create mode 100644 gcc/testsuite/g++.dg/modules/lambda-12_a.H create mode 100644 gcc/testsuite/g++.dg/modules/lambda-12_b.C diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index 2f19b2b485dd..8c64a82f7ed8 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -2789,6 +2789,8 @@ vec *post_load_decls; typedef hash_map> keyed_map_t; static keyed_map_t *keyed_table; +static tree get_keyed_decl_scope (tree); + /* Instantiations of temploid friends imported from another module need to be attached to the same module as the temploid. This maps these decls to the temploid they are instantiated from, as there is @@ -11275,20 +11277,12 @@ trees_out::get_merge_kind (tree decl, depset *dep) if (DECL_IMPLICIT_TYPEDEF_P (STRIP_TEMPLATE (decl)) && LAMBDA_TYPE_P (TREE_TYPE (decl))) { - if (tree scope = LAMBDA_TYPE_EXTRA_SCOPE (TREE_TYPE (decl))) - { - /* Lambdas attached to fields are keyed to its class. */ - if (TREE_CODE (scope) == FIELD_DECL) - scope = TYPE_NAME (DECL_CONTEXT (scope)); - if (DECL_LANG_SPECIFIC (scope) - && DECL_MODULE_KEYED_DECLS_P (scope)) - { - mk = MK_keyed; - break; - } - } - /* Lambdas not attached to any mangling scope are TU-local. */ - mk = MK_unique; + if (get_keyed_decl_scope (decl)) + mk = MK_keyed; + else + /* Lambdas not attached to any mangling scope are TU-local + and so cannot be deduplicated. */ + mk = MK_unique; break; } @@ -11589,16 +11583,9 @@ trees_out::key_mergeable (int tag, merge_kind mk, tree decl, tree inner, case MK_keyed: { - gcc_checking_assert (LAMBDA_TYPE_P (TREE_TYPE (inner))); - tree scope = LAMBDA_TYPE_EXTRA_SCOPE (TREE_TYPE (inner)); - gcc_checking_assert (TREE_CODE (scope) == VAR_DECL - || TREE_CODE (scope) == FIELD_DECL - || TREE_CODE (scope) == PARM_DECL - || TREE_CODE (scope) == TYPE_DECL - || TREE_CODE (scope) == CONCEPT_DECL); - /* Lambdas attached to fields are keyed to the class. */ - if (TREE_CODE (scope) == FIELD_DECL) - scope = TYPE_NAME (DECL_CONTEXT (scope)); + tree scope = get_keyed_decl_scope (inner); + gcc_checking_assert (scope); + auto *root = keyed_table->get (scope); unsigned ix = root->length (); /* If we don't find it, we'll write a really big number @@ -20916,9 +20903,21 @@ maybe_key_decl (tree ctx, tree decl) && TREE_CODE (ctx) != CONCEPT_DECL) return; - /* For fields, key it to the containing type to handle deduplication - correctly. */ - if (TREE_CODE (ctx) == FIELD_DECL) + /* For members, key it to the containing type to handle deduplication + correctly. For fields, this is necessary as FIELD_DECLs have no + dep and so would only be streamed after the lambda type, defeating + our ability to merge them. + + Other class-scope key decls might depend on the type of the lambda + but be within the same cluster; we need to ensure that we never + first see the key decl while streaming the lambda type as merging + would then fail when comparing the partially-streamed lambda type + of the key decl with the existing (PR c++/122310). + + Perhaps sort_cluster can be adjusted to handle this better, but + this is a simple workaround (and might down on the number of + entries in keyed_table as a bonus). */ + while (DECL_CLASS_SCOPE_P (ctx)) ctx = TYPE_NAME (DECL_CONTEXT (ctx)); if (!keyed_table) @@ -20933,6 +20932,30 @@ maybe_key_decl (tree ctx, tree decl) vec.safe_push (decl); } +/* Find the scope that the lambda DECL is keyed to, if any. */ + +static tree +get_keyed_decl_scope (tree decl) +{ + gcc_checking_assert (LAMBDA_TYPE_P (TREE_TYPE (decl))); + tree scope = LAMBDA_TYPE_EXTRA_SCOPE (TREE_TYPE (decl)); + if (!scope) + return NULL_TREE; + + gcc_checking_assert (TREE_CODE (scope) == VAR_DECL + || TREE_CODE (scope) == FIELD_DECL + || TREE_CODE (scope) == PARM_DECL + || TREE_CODE (scope) == TYPE_DECL + || TREE_CODE (scope) == CONCEPT_DECL); + + while (DECL_CLASS_SCOPE_P (scope)) + scope = TYPE_NAME (DECL_CONTEXT (scope)); + + gcc_checking_assert (DECL_LANG_SPECIFIC (scope) + && DECL_MODULE_KEYED_DECLS_P (scope)); + return scope; +} + /* DECL is an instantiated friend that should be attached to the same module that ORIG is. */ diff --git a/gcc/testsuite/g++.dg/modules/lambda-12.h b/gcc/testsuite/g++.dg/modules/lambda-12.h new file mode 100644 index 000000000000..4dd329d47605 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/lambda-12.h @@ -0,0 +1,27 @@ +// PR c++/122310 +struct Foo { + constexpr static inline auto do_nothing = [](auto && ...){}; + using TNothing = decltype(do_nothing); +}; + +template +struct X { + struct Inner { + union MoreInner { + static constexpr auto x = []{}; +#if __cplusplus >= 202002L + static decltype([]{}) y; +#endif + }; + }; + + using A = decltype(Inner::MoreInner::x); +#if __cplusplus >= 202002L + using B = decltype(Inner::MoreInner::y); +#endif +}; + +inline X::A* a{}; +#if __cplusplus >= 202002L +inline X::B* b{}; +#endif diff --git a/gcc/testsuite/g++.dg/modules/lambda-12_a.H b/gcc/testsuite/g++.dg/modules/lambda-12_a.H new file mode 100644 index 000000000000..83f5d150367f --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/lambda-12_a.H @@ -0,0 +1,5 @@ +// PR c++/122310 +// { dg-additional-options "-fmodule-header" } +// { dg-module-cmi {} } + +#include "lambda-12.h" diff --git a/gcc/testsuite/g++.dg/modules/lambda-12_b.C b/gcc/testsuite/g++.dg/modules/lambda-12_b.C new file mode 100644 index 000000000000..c24d9398a45d --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/lambda-12_b.C @@ -0,0 +1,5 @@ +// PR c++/122310 +// { dg-additional-options "-fmodules -fno-module-lazy" } + +#include "lambda-12.h" +import "lambda-12_a.H"; From df569c064eac2f30c6f19fe5db931cdad0b2abcb Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Fri, 10 Oct 2025 10:25:25 -0400 Subject: [PATCH 07/29] c++: base-specifier name lookup is type-only [PR122192] The r13-6098 change to make TYPENAME_TYPE no longer always ignore non-type bindings needs another exception: base-specifiers that are represented as TYPENAME_TYPE, for which lookup must be type-only (by [class.derived.general]/2). This patch fixes this by giving such TYPENAME_TYPEs a tag type of class_type rather than typename_type so that we treat them like elaborated-type-specifiers (another type-only lookup situation). PR c++/122192 gcc/cp/ChangeLog: * decl.cc (make_typename_type): Document base-specifier as another type-only lookup case. * parser.cc (cp_parser_class_name): Propagate tag_type to make_typename_type instead of hardcoding typename_type. (cp_parser_base_specifier): Pass class_type instead of typename_type as tag_type to cp_parser_class_name. gcc/testsuite/ChangeLog: * g++.dg/template/dependent-base6.C: New test. Reviewed-by: Jason Merrill (cherry picked from commit 49ddf362f0a7c1fdeb62f13a852a2fdec9d6fe6d) --- gcc/cp/decl.cc | 4 +++- gcc/cp/parser.cc | 5 ++--- gcc/testsuite/g++.dg/template/dependent-base6.C | 12 ++++++++++++ 3 files changed, 17 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/g++.dg/template/dependent-base6.C diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index 9cf75936d7af..6d70502aae11 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -4546,7 +4546,9 @@ make_typename_type (tree context, tree name, enum tag_types tag_type, - the tag corresponds to a class-key or 'enum' so [basic.lookup.elab] applies, or - the tag corresponds to scope_type or tf_qualifying_scope is - set so [basic.lookup.qual]/1 applies. + set so [basic.lookup.qual]/1 applies, or + - we're inside a base-specifier so [class.derived.general]/2 applies; + the tag will already be class_type in that case. TODO: If we'd set/track the scope_type tag thoroughly on all TYPENAME_TYPEs that are followed by :: then we wouldn't need the tf_qualifying_scope flag. */ diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 7f1f62c76e7c..d5ba1bf3c1c5 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -27406,8 +27406,7 @@ cp_parser_class_name (cp_parser *parser, /* If this is a typename, create a TYPENAME_TYPE. */ if (typename_p && decl != error_mark_node) { - decl = make_typename_type (scope, decl, typename_type, - /*complain=*/tf_error); + decl = make_typename_type (scope, decl, tag_type, /*complain=*/tf_error); if (decl != error_mark_node) decl = TYPE_NAME (decl); } @@ -29748,7 +29747,7 @@ cp_parser_base_specifier (cp_parser* parser) type = cp_parser_class_name (parser, class_scope_p, template_p, - typename_type, + class_type, /*check_dependency_p=*/true, /*class_head_p=*/false, /*is_declaration=*/true); diff --git a/gcc/testsuite/g++.dg/template/dependent-base6.C b/gcc/testsuite/g++.dg/template/dependent-base6.C new file mode 100644 index 000000000000..b4bc5c279a58 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/dependent-base6.C @@ -0,0 +1,12 @@ +// PR c++/122192 +// Verify name lookup within a base-specifier is type-only. + +struct A { + int B; + struct B { }; +}; + +struct S1 : A::B { }; // OK + +template struct S2 : T::B { }; // OK, used to fail +template struct S2; From 402d57846c9acca15ff80e192e3ede1f179eb8f2 Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Tue, 14 Oct 2025 12:56:23 -0400 Subject: [PATCH 08/29] c++: mem-initializer-id qualified name lookup is type-only [PR122192] Since a mem-initializer needs to be able to initialize any base class, lookup for which is type-only, we in turn need to make mem-initializer-id qualified name lookup type-only too. PR c++/122192 gcc/cp/ChangeLog: * parser.cc (cp_parser_mem_initializer_id): Pass class_type instead of typename_type to cp_parser_class_name in the nested-name-specifier case. gcc/testsuite/ChangeLog: * g++.dg/template/dependent-base6.C: Verify mem-initializer-id qualified name lookup is type-only too. Reported-by: Vincent X Reviewed-by: Jason Merrill (cherry picked from commit 97da8fece19caf0277c2be523520d09252821973) --- gcc/cp/parser.cc | 2 +- gcc/testsuite/g++.dg/template/dependent-base6.C | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index d5ba1bf3c1c5..c208e3862e71 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -18374,7 +18374,7 @@ cp_parser_mem_initializer_id (cp_parser* parser) return cp_parser_class_name (parser, /*typename_keyword_p=*/true, /*template_keyword_p=*/template_p, - typename_type, + class_type, /*check_dependency_p=*/true, /*class_head_p=*/false, /*is_declaration=*/true); diff --git a/gcc/testsuite/g++.dg/template/dependent-base6.C b/gcc/testsuite/g++.dg/template/dependent-base6.C index b4bc5c279a58..9f2a7a23923f 100644 --- a/gcc/testsuite/g++.dg/template/dependent-base6.C +++ b/gcc/testsuite/g++.dg/template/dependent-base6.C @@ -8,5 +8,7 @@ struct A { struct S1 : A::B { }; // OK -template struct S2 : T::B { }; // OK, used to fail +template struct S2 : T::B { // OK, used to fail + S2() : T::B() { } // Also OK +}; template struct S2; From aad838904a616615d97f362a4a7cc738039d8d35 Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Wed, 29 Oct 2025 00:25:03 +0000 Subject: [PATCH 09/29] Daily bump. --- gcc/DATESTAMP | 2 +- gcc/cp/ChangeLog | 34 ++++++++++++++++++++++++++++++++++ gcc/testsuite/ChangeLog | 27 +++++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 1 deletion(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 0bfc1e9884d3..aa425f410a08 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20251028 +20251029 diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 92be4b2ba451..23f2bfa21f2a 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,37 @@ +2025-10-28 Patrick Palka + + Backported from master: + 2025-10-14 Patrick Palka + + PR c++/122192 + * parser.cc (cp_parser_mem_initializer_id): Pass class_type + instead of typename_type to cp_parser_class_name in the + nested-name-specifier case. + +2025-10-28 Patrick Palka + + Backported from master: + 2025-10-10 Patrick Palka + + PR c++/122192 + * decl.cc (make_typename_type): Document base-specifier as + another type-only lookup case. + * parser.cc (cp_parser_class_name): Propagate tag_type to + make_typename_type instead of hardcoding typename_type. + (cp_parser_base_specifier): Pass class_type instead of + typename_type as tag_type to cp_parser_class_name. + +2025-10-28 Nathaniel Shead + + Backported from master: + 2025-10-27 Nathaniel Shead + + PR c++/122310 + * module.cc (get_keyed_decl_scope): New function. + (trees_out::get_merge_kind): Use it. + (trees_out::key_mergeable): Use it. + (maybe_key_decl): Key to the containing type for all members. + 2025-10-14 Jason Merrill Backported from master: diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index dbe976777497..f3126dca8385 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,30 @@ +2025-10-28 Patrick Palka + + Backported from master: + 2025-10-14 Patrick Palka + + PR c++/122192 + * g++.dg/template/dependent-base6.C: Verify mem-initializer-id + qualified name lookup is type-only too. + +2025-10-28 Patrick Palka + + Backported from master: + 2025-10-10 Patrick Palka + + PR c++/122192 + * g++.dg/template/dependent-base6.C: New test. + +2025-10-28 Nathaniel Shead + + Backported from master: + 2025-10-27 Nathaniel Shead + + PR c++/122310 + * g++.dg/modules/lambda-12.h: New test. + * g++.dg/modules/lambda-12_a.H: New test. + * g++.dg/modules/lambda-12_b.C: New test. + 2025-10-27 Jakub Jelinek PR tree-optimization/122394 From f092f60ee0f044b8c73f9c22ab0a0a88a91f40e6 Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Thu, 30 Oct 2025 00:26:13 +0000 Subject: [PATCH 10/29] Daily bump. --- gcc/DATESTAMP | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index aa425f410a08..e82e384a4b58 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20251029 +20251030 From f558f45deeae1bd9396231da41c96f695a28bf0c Mon Sep 17 00:00:00 2001 From: Guo Jie Date: Wed, 29 Oct 2025 16:38:54 +0800 Subject: [PATCH 11/29] LoongArch: Standard instruction template fnmam4 correction The current implementation of the fnmam4 instruction template requires the third source operand to be assigned the same hard register as the target operand, but the constraint is not documented in the instruction manual or standard template definitions. The current constraint will generate additional data dependencies and extra instructions. gcc/ChangeLog: * config/loongarch/lasx.md (fnma4): Remove. * config/loongarch/lsx.md (fnma4): Remove. * config/loongarch/simd.md (fnma4): Simplify and correct. gcc/testsuite/ChangeLog: * gcc.target/loongarch/fnmam4-vec.c: New test. (cherry picked from commit 7811fb6fa35fd3c3694eba34fbfc992eed1d3e67) --- gcc/config/loongarch/lasx.md | 10 ---------- gcc/config/loongarch/lsx.md | 10 ---------- gcc/config/loongarch/simd.md | 11 +++++++++++ gcc/testsuite/gcc.target/loongarch/fnmam4-vec.c | 14 ++++++++++++++ 4 files changed, 25 insertions(+), 20 deletions(-) create mode 100644 gcc/testsuite/gcc.target/loongarch/fnmam4-vec.c diff --git a/gcc/config/loongarch/lasx.md b/gcc/config/loongarch/lasx.md index 3d71f30a54be..9df572beb9e1 100644 --- a/gcc/config/loongarch/lasx.md +++ b/gcc/config/loongarch/lasx.md @@ -993,16 +993,6 @@ [(set_attr "type" "simd_fmadd") (set_attr "mode" "")]) -(define_insn "fnma4" - [(set (match_operand:FLASX 0 "register_operand" "=f") - (fma:FLASX (neg:FLASX (match_operand:FLASX 1 "register_operand" "f")) - (match_operand:FLASX 2 "register_operand" "f") - (match_operand:FLASX 3 "register_operand" "0")))] - "ISA_HAS_LASX" - "xvfnmsub.\t%u0,%u1,%u2,%u0" - [(set_attr "type" "simd_fmadd") - (set_attr "mode" "")]) - (define_expand "sqrt2" [(set (match_operand:FLASX 0 "register_operand") (sqrt:FLASX (match_operand:FLASX 1 "register_operand")))] diff --git a/gcc/config/loongarch/lsx.md b/gcc/config/loongarch/lsx.md index fb0236ba0f1b..cf48a16b69ea 100644 --- a/gcc/config/loongarch/lsx.md +++ b/gcc/config/loongarch/lsx.md @@ -852,16 +852,6 @@ [(set_attr "type" "simd_fmadd") (set_attr "mode" "")]) -(define_insn "fnma4" - [(set (match_operand:FLSX 0 "register_operand" "=f") - (fma:FLSX (neg:FLSX (match_operand:FLSX 1 "register_operand" "f")) - (match_operand:FLSX 2 "register_operand" "f") - (match_operand:FLSX 3 "register_operand" "0")))] - "ISA_HAS_LSX" - "vfnmsub.\t%w0,%w1,%w2,%w0" - [(set_attr "type" "simd_fmadd") - (set_attr "mode" "")]) - (define_expand "sqrt2" [(set (match_operand:FLSX 0 "register_operand") (sqrt:FLSX (match_operand:FLSX 1 "register_operand")))] diff --git a/gcc/config/loongarch/simd.md b/gcc/config/loongarch/simd.md index 4156b269f9ad..88ab138a8c66 100644 --- a/gcc/config/loongarch/simd.md +++ b/gcc/config/loongarch/simd.md @@ -431,6 +431,17 @@ [(set_attr "type" "simd_int_arith") (set_attr "mode" "")]) +;; vfnmsub.{s/d} +(define_insn "fnma4" + [(set (match_operand:FVEC 0 "register_operand" "=f") + (fma:FVEC (neg:FVEC (match_operand:FVEC 1 "register_operand" "f")) + (match_operand:FVEC 2 "register_operand" "f") + (match_operand:FVEC 3 "register_operand" "f")))] + "!HONOR_SIGNED_ZEROS (mode)" + "vfnmsub.\t%0,%1,%2,%3" + [(set_attr "type" "simd_fmadd") + (set_attr "mode" "")]) + ;; vfcmp.*.{s/d} with defined RTX code ;; There are no fcmp.{sugt/suge/cgt/cge}.{s/d} menmonics in GAS, so we have ;; to reverse the operands ourselves :(. diff --git a/gcc/testsuite/gcc.target/loongarch/fnmam4-vec.c b/gcc/testsuite/gcc.target/loongarch/fnmam4-vec.c new file mode 100644 index 000000000000..09693039deb3 --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/fnmam4-vec.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-Ofast -mlasx -ftree-vectorize" } */ +/* { dg-require-effective-target loongarch_asx } */ + +void +foo (float *u, float x, float *y, float z) +{ + int i; + for (i = 0; i < 1024; i++) + *(u++) = (x - y[i] * z); +} + +/* { dg-final { scan-assembler-not "\tvori.b"} } */ +/* { dg-final { scan-assembler-not "\txvori.b"} } */ From b54cc5a91ae07c551f3e8e9d7b2d89843a83fd08 Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Fri, 31 Oct 2025 00:28:14 +0000 Subject: [PATCH 12/29] Daily bump. --- gcc/ChangeLog | 9 +++++++++ gcc/DATESTAMP | 2 +- gcc/testsuite/ChangeLog | 7 +++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 624d726b4821..4e24865e9d1b 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2025-10-30 Guo Jie + + Backported from master: + 2025-10-30 Guo Jie + + * config/loongarch/lasx.md (fnma4): Remove. + * config/loongarch/lsx.md (fnma4): Remove. + * config/loongarch/simd.md (fnma4): Simplify and correct. + 2025-10-27 Jakub Jelinek PR tree-optimization/122394 diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index e82e384a4b58..986fa53aa44a 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20251030 +20251031 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f3126dca8385..3a01c2f8fd53 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2025-10-30 Guo Jie + + Backported from master: + 2025-10-30 Guo Jie + + * gcc.target/loongarch/fnmam4-vec.c: New test. + 2025-10-28 Patrick Palka Backported from master: From c250cb592dd2fa189136a7fa0e25460395244403 Mon Sep 17 00:00:00 2001 From: Jinyang He Date: Wed, 29 Oct 2025 16:07:35 +0800 Subject: [PATCH 13/29] LoongArch: Only allow valid binary op when optimize conditional move It is wrong that optimize from `if (cond) dest op= 1 << shift` to `dest op= (cond ? 1 : 0) << shift` when `dest op 0 != dest`. Like `and`, `mul` or `div`. And in this optimization `mul` and `div` is optimized to shift. gcc/ChangeLog: * config/loongarch/loongarch.cc (loongarch_expand_conditional_move): Only allow valid binary op when optimize conditional move. gcc/testsuite/ChangeLog: * gcc.target/loongarch/conditional-move-opt-1.c: Remove mul. * gcc.target/loongarch/conditional-move-opt-2.c: Remove and. * gcc.target/loongarch/conditional-move-opt-3.c: New test. Co-Authored-By: Peng Fan (cherry picked from commit 824eae920f0f64dd7687c969a2436b129161fdc9) --- gcc/config/loongarch/loongarch.cc | 26 ++++++++++++++++--- .../loongarch/conditional-move-opt-1.c | 4 +-- .../loongarch/conditional-move-opt-2.c | 2 +- .../loongarch/conditional-move-opt-3.c | 14 ++++++++++ 4 files changed, 40 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/gcc.target/loongarch/conditional-move-opt-3.c diff --git a/gcc/config/loongarch/loongarch.cc b/gcc/config/loongarch/loongarch.cc index 3cfc0cf1b829..b3189f3101de 100644 --- a/gcc/config/loongarch/loongarch.cc +++ b/gcc/config/loongarch/loongarch.cc @@ -5437,12 +5437,32 @@ loongarch_expand_conditional_move (rtx *operands) } } + auto is_binary_op_0_keep_orig = [](enum rtx_code code) + { + switch (code) + { + case PLUS: + case MINUS: + case IOR: + case XOR: + case ROTATE: + case ROTATERT: + case ASHIFT: + case ASHIFTRT: + case LSHIFTRT: + return true; + default: + return false; + } + }; + /* Check if the optimization conditions are met. */ if (value_if_true_insn && value_if_false_insn - /* Make sure that value_if_false and var are the same. */ - && BINARY_P (value_if_true_insn_src - = SET_SRC (single_set (value_if_true_insn))) + /* Make sure that the orig value OP 0 keep orig. */ + && (value_if_true_insn_src + = SET_SRC (single_set (value_if_true_insn))) + && is_binary_op_0_keep_orig ( GET_CODE (value_if_true_insn_src)) /* Make sure that both value_if_true and value_if_false has the same var. */ && rtx_equal_p (XEXP (value_if_true_insn_src, 0), diff --git a/gcc/testsuite/gcc.target/loongarch/conditional-move-opt-1.c b/gcc/testsuite/gcc.target/loongarch/conditional-move-opt-1.c index ed13471aa90a..47802aa9688d 100644 --- a/gcc/testsuite/gcc.target/loongarch/conditional-move-opt-1.c +++ b/gcc/testsuite/gcc.target/loongarch/conditional-move-opt-1.c @@ -27,7 +27,7 @@ void test_lt () { if (lm < ln) - lr *= (1 << 16); + lr += (1 << 16); lr += lm; } @@ -35,7 +35,7 @@ void test_le () { if (lm <= ln) - lr = lm * ((long)1 << 32); + lr = lm + ((long)1 << 32); else lr = lm; lr += lm; diff --git a/gcc/testsuite/gcc.target/loongarch/conditional-move-opt-2.c b/gcc/testsuite/gcc.target/loongarch/conditional-move-opt-2.c index ac72d4d933ad..743fd5e670e2 100644 --- a/gcc/testsuite/gcc.target/loongarch/conditional-move-opt-2.c +++ b/gcc/testsuite/gcc.target/loongarch/conditional-move-opt-2.c @@ -29,7 +29,7 @@ void test_lez () { if (lm <= 0) - lr &= (1 << 16); + lr |= (1 << 16); lr += lm; } diff --git a/gcc/testsuite/gcc.target/loongarch/conditional-move-opt-3.c b/gcc/testsuite/gcc.target/loongarch/conditional-move-opt-3.c new file mode 100644 index 000000000000..95887980cc5f --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/conditional-move-opt-3.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +/* { dg-final { scan-assembler "maskeqz" } } */ +/* { dg-final { scan-assembler "masknez" } } */ + +extern long lm, ln, lr; + +void +test_and () +{ + if (lm < 0) + lr &= (1 << 16); + lr += lm; +} From 5b7639b0de2f1d610e16eec628033fe3650d4763 Mon Sep 17 00:00:00 2001 From: Tamar Christina Date: Mon, 27 Oct 2025 17:55:38 +0000 Subject: [PATCH 14/29] vect: Fix operand swapping on complex multiplication detection [PR122408] For SUBROUTINE a( j, b, c, d ) !GCC$ ATTRIBUTES noinline :: a COMPLEX*16 b COMPLEX*16 c( * ), d( * ) DO k = 1, j c( k ) = - b * CONJG( d( k ) ) END DO END we incorrectly generate .IFN_COMPLEX_MUL instead of .IFN_COMPLEX_MUL_CONJ. The issue happens because in the call to vect_validate_multiplication the operand vectors are passed by reference and so the stripping of the NEGATE_EXPR after matching modifies the input vector. If validation fail we flip the operands and try again. But we've already stipped the negates and so if we match we would match a normal multiply. This fixes the API by marking the operands as const and instead pass an explicit output vec that's to be used. This also reduces the number of copies we were doing. With this we now correctly detect .IFN_COMPLEX_MUL_CONJ. Weirdly enough I couldn't reproduce this with any C example because they get reassociated differently and always succeed on the first attempt. Fortran is easy to trigger though so new fortran tests added. gcc/ChangeLog: PR tree-optimization/122408 * tree-vect-slp-patterns.cc (vect_validate_multiplication): Cleanup and document interface. (complex_mul_pattern::matches, complex_fms_pattern::matches): Update to new interface. gcc/testsuite/ChangeLog: PR tree-optimization/122408 * gfortran.target/aarch64/pr122408_1.f90: New test. * gfortran.target/aarch64/pr122408_2.f90: New test. (cherry picked from commit c5fa3d4c88fc4f8799318e463c47941eb52b7546) --- .../gfortran.target/aarch64/pr122408_1.f90 | 61 ++++++++ .../gfortran.target/aarch64/pr122408_2.f90 | 140 ++++++++++++++++++ gcc/tree-vect-slp-patterns.cc | 75 ++++++---- 3 files changed, 244 insertions(+), 32 deletions(-) create mode 100644 gcc/testsuite/gfortran.target/aarch64/pr122408_1.f90 create mode 100644 gcc/testsuite/gfortran.target/aarch64/pr122408_2.f90 diff --git a/gcc/testsuite/gfortran.target/aarch64/pr122408_1.f90 b/gcc/testsuite/gfortran.target/aarch64/pr122408_1.f90 new file mode 100644 index 000000000000..8a3416231ff1 --- /dev/null +++ b/gcc/testsuite/gfortran.target/aarch64/pr122408_1.f90 @@ -0,0 +1,61 @@ +! { dg-do compile } +! { dg-additional-options "-O2 -march=armv8.3-a" } + +subroutine c_add_ab(n, a, c, b) ! C += A * B + use iso_fortran_env, only: real64 + implicit none + !GCC$ ATTRIBUTES noinline :: c_add_ab + integer, intent(in) :: n + complex(real64), intent(in) :: a + complex(real64), intent(inout) :: c(*) + complex(real64), intent(in) :: b(*) + integer :: k + do k = 1, n + c(k) = c(k) + a * b(k) + end do +end subroutine c_add_ab + +subroutine c_sub_ab(n, a, c, b) ! C -= A * B + use iso_fortran_env, only: real64 + implicit none + !GCC$ ATTRIBUTES noinline :: c_sub_ab + integer, intent(in) :: n + complex(real64), intent(in) :: a + complex(real64), intent(inout) :: c(*) + complex(real64), intent(in) :: b(*) + integer :: k + do k = 1, n + c(k) = c(k) - a * b(k) + end do +end subroutine c_sub_ab + +subroutine c_add_a_conjb(n, a, c, b) ! C += A * conj(B) + use iso_fortran_env, only: real64 + implicit none + !GCC$ ATTRIBUTES noinline :: c_add_a_conjb + integer, intent(in) :: n + complex(real64), intent(in) :: a + complex(real64), intent(inout) :: c(*) + complex(real64), intent(in) :: b(*) + integer :: k + do k = 1, n + c(k) = c(k) + a * conjg(b(k)) + end do +end subroutine c_add_a_conjb + +subroutine c_sub_a_conjb(n, a, c, b) ! C -= A * conj(B) + use iso_fortran_env, only: real64 + implicit none + !GCC$ ATTRIBUTES noinline :: c_sub_a_conjb + integer, intent(in) :: n + complex(real64), intent(in) :: a + complex(real64), intent(inout) :: c(*) + complex(real64), intent(in) :: b(*) + integer :: k + do k = 1, n + c(k) = c(k) - a * conjg(b(k)) + end do +end subroutine c_sub_a_conjb + +! { dg-final { scan-assembler-times {fcmla\s+v[0-9]+.2d, v[0-9]+.2d, v[0-9]+.2d, #0} 2 } } +! { dg-final { scan-assembler-times {fcmla\s+v[0-9]+.2d, v[0-9]+.2d, v[0-9]+.2d, #270} 2 } } diff --git a/gcc/testsuite/gfortran.target/aarch64/pr122408_2.f90 b/gcc/testsuite/gfortran.target/aarch64/pr122408_2.f90 new file mode 100644 index 000000000000..feb6dc14af8a --- /dev/null +++ b/gcc/testsuite/gfortran.target/aarch64/pr122408_2.f90 @@ -0,0 +1,140 @@ +! { dg-do run } +! { dg-additional-options "-O2" } +! { dg-additional-options "-O2 -march=armv8.3-a" { target arm_v8_3a_complex_neon_hw } } + +module util + use iso_fortran_env, only: real64, int64 + implicit none +contains + pure logical function bitwise_eq(x, y) + complex(real64), intent(in) :: x, y + integer(int64) :: xr, xi, yr, yi + xr = transfer(real(x,kind=real64), 0_int64) + xi = transfer(aimag(x), 0_int64) + yr = transfer(real(y,kind=real64), 0_int64) + yi = transfer(aimag(y), 0_int64) + bitwise_eq = (xr == yr) .and. (xi == yi) + end function bitwise_eq + + subroutine check_equal(tag, got, ref, nfail) + character(*), intent(in) :: tag + complex(real64), intent(in) :: got(:), ref(:) + integer, intent(inout) :: nfail + integer :: i + do i = 1, size(got) + if (.not. bitwise_eq(got(i), ref(i))) then + nfail = nfail + 1 + write(*,'(A,": mismatch at i=",I0, " got=",2ES16.8," ref=",2ES16.8)') & + trim(tag), i, real(got(i)), aimag(got(i)), real(ref(i)), aimag(ref(i)) + end if + end do + end subroutine check_equal +end module util + +module fcmla_ops + use iso_fortran_env, only: real64 + implicit none +contains + subroutine c_add_ab(n, a, c, b) ! C += A * B + !GCC$ ATTRIBUTES noinline :: c_add_ab + integer, intent(in) :: n + complex(real64), intent(in) :: a + complex(real64), intent(inout) :: c(*) + complex(real64), intent(in) :: b(*) + integer :: k + do k = 1, n + c(k) = c(k) + a * b(k) + end do + end subroutine c_add_ab + + subroutine c_sub_ab(n, a, c, b) ! C -= A * B + !GCC$ ATTRIBUTES noinline :: c_sub_ab + integer, intent(in) :: n + complex(real64), intent(in) :: a + complex(real64), intent(inout) :: c(*) + complex(real64), intent(in) :: b(*) + integer :: k + do k = 1, n + c(k) = c(k) - a * b(k) + end do + end subroutine c_sub_ab + + subroutine c_add_a_conjb(n, a, c, b) ! C += A * conj(B) + !GCC$ ATTRIBUTES noinline :: c_add_a_conjb + integer, intent(in) :: n + complex(real64), intent(in) :: a + complex(real64), intent(inout) :: c(*) + complex(real64), intent(in) :: b(*) + integer :: k + do k = 1, n + c(k) = c(k) + a * conjg(b(k)) + end do + end subroutine c_add_a_conjb + + subroutine c_sub_a_conjb(n, a, c, b) ! C -= A * conj(B) + !GCC$ ATTRIBUTES noinline :: c_sub_a_conjb + integer, intent(in) :: n + complex(real64), intent(in) :: a + complex(real64), intent(inout) :: c(*) + complex(real64), intent(in) :: b(*) + integer :: k + do k = 1, n + c(k) = c(k) - a * conjg(b(k)) + end do + end subroutine c_sub_a_conjb +end module fcmla_ops + +program fcmla_accum_pairs + use iso_fortran_env, only: real64 + use util + use fcmla_ops + implicit none + + integer, parameter :: n = 4 + complex(real64) :: a, b(n), c0(n) + complex(real64) :: c_add_ab_got(n), c_add_ab_ref(n) + complex(real64) :: c_sub_ab_got(n), c_sub_ab_ref(n) + complex(real64) :: c_add_conjb_got(n), c_add_conjb_ref(n) + complex(real64) :: c_sub_conjb_got(n), c_sub_conjb_ref(n) + integer :: i, fails + + ! Constants (include a signed-zero lane) + a = cmplx( 2.0_real64, -3.0_real64, kind=real64) + b(1) = cmplx( 1.5_real64, -2.0_real64, kind=real64) + b(2) = cmplx(-4.0_real64, 5.0_real64, kind=real64) + b(3) = cmplx(-0.0_real64, 0.0_real64, kind=real64) + b(4) = cmplx( 0.25_real64, 3.0_real64, kind=real64) + + c0(1) = cmplx( 1.0_real64, -2.0_real64, kind=real64) + c0(2) = cmplx( 3.0_real64, -4.0_real64, kind=real64) + c0(3) = cmplx(-5.0_real64, 6.0_real64, kind=real64) + c0(4) = cmplx( 0.0_real64, 0.0_real64, kind=real64) + + ! Run each form + c_add_ab_got = c0; call c_add_ab (n, a, c_add_ab_got, b) + c_sub_ab_got = c0; call c_sub_ab (n, a, c_sub_ab_got, b) + c_add_conjb_got = c0; call c_add_a_conjb(n, a, c_add_conjb_got, b) + c_sub_conjb_got = c0; call c_sub_a_conjb(n, a, c_sub_conjb_got, b) + + ! Scalar references + do i = 1, n + c_add_ab_ref(i) = c0(i) + a * b(i) + c_sub_ab_ref(i) = c0(i) - a * b(i) + c_add_conjb_ref(i) = c0(i) + a * conjg(b(i)) + c_sub_conjb_ref(i) = c0(i) - a * conjg(b(i)) + end do + + ! Bitwise checks + fails = 0 + call check_equal("C += A*B ", c_add_ab_got, c_add_ab_ref, fails) + call check_equal("C -= A*B ", c_sub_ab_got, c_sub_ab_ref, fails) + call check_equal("C += A*conj(B) ", c_add_conjb_got, c_add_conjb_ref, fails) + call check_equal("C -= A*conj(B) ", c_sub_conjb_got, c_sub_conjb_ref, fails) + + if (fails == 0) then + stop 0 + else + stop 1 + end if +end program fcmla_accum_pairs + diff --git a/gcc/tree-vect-slp-patterns.cc b/gcc/tree-vect-slp-patterns.cc index c0dff90d9baf..cebd9aa1c13c 100644 --- a/gcc/tree-vect-slp-patterns.cc +++ b/gcc/tree-vect-slp-patterns.cc @@ -847,15 +847,23 @@ compatible_complex_nodes_p (slp_compat_nodes_map_t *compat_cache, return true; } + +/* Check to see if the oprands to two multiplies, 2 each in LEFT_OP and + RIGHT_OP match a complex multiplication or complex multiply-and-accumulate + or complex multiply-and-subtract pattern. Do this using the permute cache + PERM_CACHE and the combination compatibility list COMPAT_CACHE. If + the operation is successful the macthing operands are returned in OPS and + _STATUS indicates if the operation matched includes a conjugate of one of the + operands. If the operation succeeds True is returned, otherwise False and + the values in ops are meaningless. */ static inline bool vect_validate_multiplication (slp_tree_to_load_perm_map_t *perm_cache, slp_compat_nodes_map_t *compat_cache, - vec &left_op, - vec &right_op, - bool subtract, + const vec &left_op, + const vec &right_op, + bool subtract, vec &ops, enum _conj_status *_status) { - auto_vec ops; enum _conj_status stats = CONJ_NONE; /* The complex operations can occur in two layouts and two permute sequences @@ -886,31 +894,31 @@ vect_validate_multiplication (slp_tree_to_load_perm_map_t *perm_cache, bool neg0 = vect_match_expression_p (right_op[0], NEGATE_EXPR); bool neg1 = vect_match_expression_p (right_op[1], NEGATE_EXPR); + /* Create the combined inputs after remapping and flattening. */ + ops.create (4); + ops.safe_splice (left_op); + ops.safe_splice (right_op); + /* Determine which style we're looking at. We only have different ones whenever a conjugate is involved. */ if (neg0 && neg1) ; else if (neg0) { - right_op[0] = SLP_TREE_CHILDREN (right_op[0])[0]; + ops[2] = SLP_TREE_CHILDREN (right_op[0])[0]; stats = CONJ_FST; if (subtract) perm = 0; } else if (neg1) { - right_op[1] = SLP_TREE_CHILDREN (right_op[1])[0]; + ops[3] = SLP_TREE_CHILDREN (right_op[1])[0]; stats = CONJ_SND; perm = 1; } *_status = stats; - /* Flatten the inputs after we've remapped them. */ - ops.create (4); - ops.safe_splice (left_op); - ops.safe_splice (right_op); - /* Extract out the elements to check. */ slp_tree op0 = ops[styles[style][0]]; slp_tree op1 = ops[styles[style][1]]; @@ -1073,15 +1081,16 @@ complex_mul_pattern::matches (complex_operation_t op, return IFN_LAST; enum _conj_status status; + auto_vec res_ops; if (!vect_validate_multiplication (perm_cache, compat_cache, left_op, - right_op, false, &status)) + right_op, false, res_ops, &status)) { /* Try swapping the order and re-trying since multiplication is commutative. */ std::swap (left_op[0], left_op[1]); std::swap (right_op[0], right_op[1]); if (!vect_validate_multiplication (perm_cache, compat_cache, left_op, - right_op, false, &status)) + right_op, false, res_ops, &status)) return IFN_LAST; } @@ -1109,24 +1118,24 @@ complex_mul_pattern::matches (complex_operation_t op, if (add0) ops->quick_push (add0); - complex_perm_kinds_t kind = linear_loads_p (perm_cache, left_op[0]); + complex_perm_kinds_t kind = linear_loads_p (perm_cache, res_ops[0]); if (kind == PERM_EVENODD || kind == PERM_TOP) { - ops->quick_push (left_op[1]); - ops->quick_push (right_op[1]); - ops->quick_push (left_op[0]); + ops->quick_push (res_ops[1]); + ops->quick_push (res_ops[3]); + ops->quick_push (res_ops[0]); } else if (kind == PERM_EVENEVEN && status != CONJ_SND) { - ops->quick_push (left_op[0]); - ops->quick_push (right_op[0]); - ops->quick_push (left_op[1]); + ops->quick_push (res_ops[0]); + ops->quick_push (res_ops[2]); + ops->quick_push (res_ops[1]); } else { - ops->quick_push (left_op[0]); - ops->quick_push (right_op[1]); - ops->quick_push (left_op[1]); + ops->quick_push (res_ops[0]); + ops->quick_push (res_ops[3]); + ops->quick_push (res_ops[1]); } return ifn; @@ -1298,15 +1307,17 @@ complex_fms_pattern::matches (complex_operation_t op, return IFN_LAST; enum _conj_status status; + auto_vec res_ops; if (!vect_validate_multiplication (perm_cache, compat_cache, right_op, - left_op, true, &status)) + left_op, true, res_ops, &status)) { /* Try swapping the order and re-trying since multiplication is commutative. */ std::swap (left_op[0], left_op[1]); std::swap (right_op[0], right_op[1]); + auto_vec res_ops; if (!vect_validate_multiplication (perm_cache, compat_cache, right_op, - left_op, true, &status)) + left_op, true, res_ops, &status)) return IFN_LAST; } @@ -1321,20 +1332,20 @@ complex_fms_pattern::matches (complex_operation_t op, ops->truncate (0); ops->create (4); - complex_perm_kinds_t kind = linear_loads_p (perm_cache, right_op[0]); + complex_perm_kinds_t kind = linear_loads_p (perm_cache, res_ops[2]); if (kind == PERM_EVENODD) { ops->quick_push (l0node[0]); - ops->quick_push (right_op[0]); - ops->quick_push (right_op[1]); - ops->quick_push (left_op[1]); + ops->quick_push (res_ops[2]); + ops->quick_push (res_ops[3]); + ops->quick_push (res_ops[1]); } else { ops->quick_push (l0node[0]); - ops->quick_push (right_op[1]); - ops->quick_push (right_op[0]); - ops->quick_push (left_op[0]); + ops->quick_push (res_ops[3]); + ops->quick_push (res_ops[2]); + ops->quick_push (res_ops[0]); } return ifn; From 0186567e505055abdc94601f5491150ecd13fa70 Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Sat, 1 Nov 2025 00:25:36 +0000 Subject: [PATCH 15/29] Daily bump. --- gcc/ChangeLog | 21 +++++++++++++++++++++ gcc/DATESTAMP | 2 +- gcc/testsuite/ChangeLog | 19 +++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4e24865e9d1b..90fa0bf788b5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,24 @@ +2025-10-31 Tamar Christina + + Backported from master: + 2025-10-27 Tamar Christina + + PR tree-optimization/122408 + * tree-vect-slp-patterns.cc (vect_validate_multiplication): Cleanup and + document interface. + (complex_mul_pattern::matches, complex_fms_pattern::matches): Update to + new interface. + +2025-10-31 Jinyang He + + Backported from master: + 2025-10-30 Jinyang He + Peng Fan + + * config/loongarch/loongarch.cc + (loongarch_expand_conditional_move): Only allow valid binary + op when optimize conditional move. + 2025-10-30 Guo Jie Backported from master: diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 986fa53aa44a..38eec118b91c 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20251031 +20251101 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 3a01c2f8fd53..c164282c9e1f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,22 @@ +2025-10-31 Tamar Christina + + Backported from master: + 2025-10-27 Tamar Christina + + PR tree-optimization/122408 + * gfortran.target/aarch64/pr122408_1.f90: New test. + * gfortran.target/aarch64/pr122408_2.f90: New test. + +2025-10-31 Jinyang He + + Backported from master: + 2025-10-30 Jinyang He + Peng Fan + + * gcc.target/loongarch/conditional-move-opt-1.c: Remove mul. + * gcc.target/loongarch/conditional-move-opt-2.c: Remove and. + * gcc.target/loongarch/conditional-move-opt-3.c: New test. + 2025-10-30 Guo Jie Backported from master: From fad7547a50166f21fe4445af073e6b58e1a8473d Mon Sep 17 00:00:00 2001 From: Nathaniel Shead Date: Sat, 1 Nov 2025 22:59:33 +1100 Subject: [PATCH 16/29] c++/modules: Stream BASELINK_OPTYPE [PR122381] This is used in template conversion operators to determine what type the user requested. PR c++/122381 gcc/cp/ChangeLog: * module.cc (trees_out::core_vals): Write BASELINK_OPTYPE (aka TREE_CHAIN). (trees_in::core_vals): Read it. gcc/testsuite/ChangeLog: * g++.dg/modules/convop-2_a.H: New test. * g++.dg/modules/convop-2_b.C: New test. Signed-off-by: Nathaniel Shead (cherry picked from commit b466450c6d502557921f03527cc165fb3402aaa9) --- gcc/cp/module.cc | 2 ++ gcc/testsuite/g++.dg/modules/convop-2_a.H | 10 ++++++++++ gcc/testsuite/g++.dg/modules/convop-2_b.C | 5 +++++ 3 files changed, 17 insertions(+) create mode 100644 gcc/testsuite/g++.dg/modules/convop-2_a.H create mode 100644 gcc/testsuite/g++.dg/modules/convop-2_b.C diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index 8c64a82f7ed8..632dc47552a6 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -6690,6 +6690,7 @@ trees_out::core_vals (tree t) WT (((lang_tree_node *)t)->baselink.binfo); WT (((lang_tree_node *)t)->baselink.functions); WT (((lang_tree_node *)t)->baselink.access_binfo); + WT (((lang_tree_node *)t)->baselink.common.chain); break; case CONSTRAINT_INFO: @@ -7259,6 +7260,7 @@ trees_in::core_vals (tree t) RT (((lang_tree_node *)t)->baselink.binfo); RTU (((lang_tree_node *)t)->baselink.functions); RT (((lang_tree_node *)t)->baselink.access_binfo); + RT (((lang_tree_node *)t)->baselink.common.chain); break; case CONSTRAINT_INFO: diff --git a/gcc/testsuite/g++.dg/modules/convop-2_a.H b/gcc/testsuite/g++.dg/modules/convop-2_a.H new file mode 100644 index 000000000000..62bb2101f691 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/convop-2_a.H @@ -0,0 +1,10 @@ +// PR c++/122381 +// { dg-additional-options "-fmodule-header" } +// { dg-module-cmi {} } + +template struct color_ref { + operator int() const { return 0; } + int foo(color_ref x) { + return x.operator int(); + } +}; diff --git a/gcc/testsuite/g++.dg/modules/convop-2_b.C b/gcc/testsuite/g++.dg/modules/convop-2_b.C new file mode 100644 index 000000000000..d1e829ec70ca --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/convop-2_b.C @@ -0,0 +1,5 @@ +// PR c++/122381 +// { dg-additional-options "-fmodules" } + +import "convop-2_a.H"; +template struct color_ref; From 696bfbab0a46ccc263cffd88254582d236a84278 Mon Sep 17 00:00:00 2001 From: Harald Anlauf Date: Thu, 23 Oct 2025 21:21:04 +0200 Subject: [PATCH 17/29] Fortran: fix TRANSFER of subarray component references [PR122386] Commit r16-518 introduced a change that fixed inquiry references of complex arrays as argument to the TRANSFER intrinsic by forcing a temporary. The solution taken however turned out not to be generalizable to component references of nested derived-type arrays. A better way is the revert that patch and force the generation of a temporary when the SOURCE expression is a not simply-contiguous array. PR fortran/122386 gcc/fortran/ChangeLog: * dependency.cc (gfc_ref_needs_temporary_p): Revert r16-518. * trans-intrinsic.cc (gfc_conv_intrinsic_transfer): Force temporary for SOURCE not being a simply-contiguous array. gcc/testsuite/ChangeLog: * gfortran.dg/transfer_array_subref_2.f90: New test. (cherry picked from commit 2febf3b968329aceeeea7805af98ed98a8c67e75) --- gcc/fortran/dependency.cc | 6 +-- gcc/fortran/trans-intrinsic.cc | 7 ++- .../gfortran.dg/transfer_array_subref_2.f90 | 52 +++++++++++++++++++ 3 files changed, 59 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/gfortran.dg/transfer_array_subref_2.f90 diff --git a/gcc/fortran/dependency.cc b/gcc/fortran/dependency.cc index aa8a57a80e0e..57c0c49391bd 100644 --- a/gcc/fortran/dependency.cc +++ b/gcc/fortran/dependency.cc @@ -944,12 +944,8 @@ gfc_ref_needs_temporary_p (gfc_ref *ref) types), not in characters. */ return subarray_p; - case REF_INQUIRY: - /* Within an array reference, inquiry references of complex - variables generally need a temporary. */ - return subarray_p; - case REF_COMPONENT: + case REF_INQUIRY: break; } diff --git a/gcc/fortran/trans-intrinsic.cc b/gcc/fortran/trans-intrinsic.cc index d748dd72569b..75099ad7cb50 100644 --- a/gcc/fortran/trans-intrinsic.cc +++ b/gcc/fortran/trans-intrinsic.cc @@ -8541,13 +8541,18 @@ gfc_conv_intrinsic_transfer (gfc_se * se, gfc_expr * expr) } else { + bool simply_contiguous = gfc_is_simply_contiguous (arg->expr, + false, true); argse.want_pointer = 0; + /* A non-contiguous SOURCE needs packing. */ + if (!simply_contiguous) + argse.force_tmp = 1; gfc_conv_expr_descriptor (&argse, arg->expr); source = gfc_conv_descriptor_data_get (argse.expr); source_type = gfc_get_element_type (TREE_TYPE (argse.expr)); /* Repack the source if not simply contiguous. */ - if (!gfc_is_simply_contiguous (arg->expr, false, true)) + if (!simply_contiguous) { tmp = gfc_build_addr_expr (NULL_TREE, argse.expr); diff --git a/gcc/testsuite/gfortran.dg/transfer_array_subref_2.f90 b/gcc/testsuite/gfortran.dg/transfer_array_subref_2.f90 new file mode 100644 index 000000000000..9ff519866dc8 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/transfer_array_subref_2.f90 @@ -0,0 +1,52 @@ +! { dg-do run } +! { dg-additional-options "-O2 -fdump-tree-optimized" } +! +! PR fortran/122386 - passing of component ref of nested DT array to TRANSFER + +program main + implicit none + integer, parameter :: dp = 4 + + type cx + real(dp) :: re, im + end type cx + + type complex_wrap1 + type(cx) :: z(2) + end type complex_wrap1 + + type complex_wrap2 + type(cx), dimension(:), allocatable :: z + end type complex_wrap2 + + type(complex_wrap1) :: x = complex_wrap1([cx(1,2), cx(3,4)]) + type(complex_wrap2) :: w + + w%z = x%z + + ! The following statements should get optimized away... + if (size (transfer ( x%z%re ,[1.0_dp])) /= 2) error stop 1 + if (size (transfer ((x%z%re),[1.0_dp])) /= 2) error stop 2 + if (size (transfer ([x%z%re],[1.0_dp])) /= 2) error stop 3 + if (size (transfer ( x%z%im ,[1.0_dp])) /= 2) error stop 4 + if (size (transfer ((x%z%im),[1.0_dp])) /= 2) error stop 5 + if (size (transfer ([x%z%im],[1.0_dp])) /= 2) error stop 6 + + ! ... while the following may not: + if (any (transfer ( x%z%re ,[1.0_dp]) /= x%z%re)) stop 7 + if (any (transfer ( x%z%im ,[1.0_dp]) /= x%z%im)) stop 8 + + if (size (transfer ( w%z%re ,[1.0_dp])) /= 2) stop 11 + if (size (transfer ((w%z%re),[1.0_dp])) /= 2) stop 12 + if (size (transfer ([w%z%re],[1.0_dp])) /= 2) stop 13 + if (size (transfer ( w%z%im ,[1.0_dp])) /= 2) stop 14 + if (size (transfer ((w%z%im),[1.0_dp])) /= 2) stop 15 + if (size (transfer ([w%z%im],[1.0_dp])) /= 2) stop 16 + + if (any (transfer ( w%z%re ,[1.0_dp]) /= x%z%re)) stop 17 + if (any (transfer ( w%z%im ,[1.0_dp]) /= x%z%im)) stop 18 + + deallocate (w%z) +end program main + +! { dg-final { scan-tree-dump-not "_gfortran_error_stop_numeric" "optimized" } } From 31d3f96b790c76df14e6328fd600d616ca969abd Mon Sep 17 00:00:00 2001 From: Harald Anlauf Date: Fri, 24 Oct 2025 21:33:08 +0200 Subject: [PATCH 18/29] Fortran: IS_CONTIGUOUS and pointers to non-contiguous targets [PR114023] PR fortran/114023 gcc/fortran/ChangeLog: * trans-expr.cc (gfc_trans_pointer_assignment): Always set dtype when remapping a pointer. For unlimited polymorphic LHS use elem_len from RHS. * trans-intrinsic.cc (gfc_conv_is_contiguous_expr): Extend inline generated code for IS_CONTIGUOUS for pointer arguments to detect when span differs from the element size. gcc/testsuite/ChangeLog: * gfortran.dg/is_contiguous_5.f90: New test. (cherry picked from commit 3f8b6373f48af0eabbc2efe04df8f6856add3111) --- gcc/fortran/trans-expr.cc | 24 +++- gcc/fortran/trans-intrinsic.cc | 22 ++- gcc/testsuite/gfortran.dg/is_contiguous_5.f90 | 126 ++++++++++++++++++ 3 files changed, 165 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/gfortran.dg/is_contiguous_5.f90 diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc index 08fc524f8578..23d40991dd14 100644 --- a/gcc/fortran/trans-expr.cc +++ b/gcc/fortran/trans-expr.cc @@ -11222,21 +11222,33 @@ gfc_trans_pointer_assignment (gfc_expr * expr1, gfc_expr * expr2) int dim; gcc_assert (remap->u.ar.dimen == expr1->rank); + /* Always set dtype. */ + tree dtype = gfc_conv_descriptor_dtype (desc); + tmp = gfc_get_dtype (TREE_TYPE (desc)); + gfc_add_modify (&block, dtype, tmp); + + /* For unlimited polymorphic LHS use elem_len from RHS. */ + if (UNLIMITED_POLY (expr1) && expr2->ts.type != BT_CLASS) + { + tree elem_len; + tmp = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&expr2->ts)); + elem_len = fold_convert (gfc_array_index_type, tmp); + elem_len = gfc_evaluate_now (elem_len, &block); + tmp = gfc_conv_descriptor_elem_len (desc); + gfc_add_modify (&block, tmp, + fold_convert (TREE_TYPE (tmp), elem_len)); + } + if (rank_remap) { /* Do rank remapping. We already have the RHS's descriptor converted in rse and now have to build the correct LHS descriptor for it. */ - tree dtype, data, span; + tree data, span; tree offs, stride; tree lbound, ubound; - /* Set dtype. */ - dtype = gfc_conv_descriptor_dtype (desc); - tmp = gfc_get_dtype (TREE_TYPE (desc)); - gfc_add_modify (&block, dtype, tmp); - /* Copy data pointer. */ data = gfc_conv_descriptor_data_get (rse.expr); gfc_conv_descriptor_data_set (&block, desc, data); diff --git a/gcc/fortran/trans-intrinsic.cc b/gcc/fortran/trans-intrinsic.cc index 75099ad7cb50..4b68f5759488 100644 --- a/gcc/fortran/trans-intrinsic.cc +++ b/gcc/fortran/trans-intrinsic.cc @@ -2315,10 +2315,14 @@ gfc_conv_is_contiguous_expr (gfc_se *se, gfc_expr *arg) int i; tree fncall0; gfc_array_spec *as; + gfc_symbol *sym = NULL; if (arg->ts.type == BT_CLASS) gfc_add_class_array_ref (arg); + if (arg->expr_type == EXPR_VARIABLE) + sym = arg->symtree->n.sym; + ss = gfc_walk_expr (arg); gcc_assert (ss != gfc_ss_terminator); gfc_init_se (&argse, NULL); @@ -2341,7 +2345,7 @@ gfc_conv_is_contiguous_expr (gfc_se *se, gfc_expr *arg) fncall0 = build_call_expr_loc (input_location, gfor_fndecl_is_contiguous0, 1, desc); se->expr = fncall0; - se->expr = convert (logical_type_node, se->expr); + se->expr = convert (boolean_type_node, se->expr); } else { @@ -2373,6 +2377,22 @@ gfc_conv_is_contiguous_expr (gfc_se *se, gfc_expr *arg) } se->expr = cond; } + + /* A pointer that does not have the CONTIGUOUS attribute needs to be checked + if it points to an array whose span differs from the element size. */ + if (as && sym && IS_POINTER(sym) && !sym->attr.contiguous) + { + tree span = gfc_conv_descriptor_span_get (desc); + tmp = fold_convert (TREE_TYPE (span), + gfc_conv_descriptor_elem_len (desc)); + cond = fold_build2_loc (input_location, EQ_EXPR, boolean_type_node, + span, tmp); + se->expr = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR, + boolean_type_node, cond, + convert (boolean_type_node, se->expr)); + } + + gfc_free_ss_chain (ss); } diff --git a/gcc/testsuite/gfortran.dg/is_contiguous_5.f90 b/gcc/testsuite/gfortran.dg/is_contiguous_5.f90 new file mode 100644 index 000000000000..091e43b55c2d --- /dev/null +++ b/gcc/testsuite/gfortran.dg/is_contiguous_5.f90 @@ -0,0 +1,126 @@ +! { dg-do run } +! PR fortran/114023 - IS_CONTIGUOUS and pointers to non-contiguous targets +! +! Based on testcase by Federico Perini + +program main + implicit none + complex, parameter :: cvals(*) = [(1,-1),(2,-2),(3,-3)] + complex , target :: cref(size(cvals)) = cvals ! Reference + complex, allocatable, target :: carr(:) ! Test + + type cx + real :: re, im + end type cx + type(cx), parameter :: tvals(*) = [cx(1,-1),cx(2,-2),cx(3,-3)] + real, parameter :: expect(*) = tvals% re + type(cx) , target :: tref(size(cvals)) = tvals ! Reference + type(cx), allocatable, target :: tarr(:) + + real, pointer :: rr1(:), rr2(:), rr3(:), rr4(:) + class(*), pointer :: cp1(:), cp2(:), cp3(:), cp4(:) + + carr = cvals + tarr = tvals + + if (any (expect /= [1,2,3])) error stop 90 + + ! REAL pointer to non-contiguous effective target + rr1(1:3) => cref%re + rr2 => cref%re + rr3(1:3) => carr%re + rr4 => carr%re + + if (is_contiguous (rr1)) stop 1 + if (my_contiguous_real (rr1)) stop 2 + if (is_contiguous (cref(1:3)%re)) stop 3 +! if (my_contiguous_real (cref(1:3)%re)) stop 4 ! pr122397 + + if (is_contiguous (rr3)) stop 6 + if (my_contiguous_real (rr3)) stop 7 + if (is_contiguous (carr(1:3)%re)) stop 8 +! if (my_contiguous_real (carr(1:3)%re)) stop 9 + + if (is_contiguous (rr2)) stop 11 + if (my_contiguous_real (rr2)) stop 12 + if (is_contiguous (cref%re)) stop 13 +! if (my_contiguous_real (cref%re)) stop 14 + + if (is_contiguous (rr4)) stop 16 + if (my_contiguous_real (rr4)) stop 17 + if (is_contiguous (carr%re)) stop 18 +! if (my_contiguous_real (carr%re)) stop 19 + + rr1(1:3) => tref%re + rr2 => tref%re + rr3(1:3) => tarr%re + rr4 => tarr%re + + if (is_contiguous (rr1)) stop 21 + if (my_contiguous_real (rr1)) stop 22 + if (is_contiguous (tref(1:3)%re)) stop 23 +! if (my_contiguous_real (tref(1:3)%re)) stop 24 + + if (is_contiguous (rr3)) stop 26 + if (my_contiguous_real (rr3)) stop 27 + if (is_contiguous (tarr(1:3)%re)) stop 28 +! if (my_contiguous_real (tarr(1:3)%re)) stop 29 + + if (is_contiguous (rr2)) stop 31 + if (my_contiguous_real (rr2)) stop 32 + if (is_contiguous (tref%re)) stop 33 +! if (my_contiguous_real (tref%re)) stop 34 + + if (is_contiguous (rr4)) stop 36 + if (my_contiguous_real (rr4)) stop 37 + if (is_contiguous (tarr%re)) stop 38 +! if (my_contiguous_real (tarr%re)) stop 39 + + ! Unlimited polymorphic pointer to non-contiguous effective target + cp1(1:3) => cref%re + cp2 => cref%re + cp3(1:3) => carr%re + cp4 => carr%re + + if (is_contiguous (cp1)) stop 41 + if (my_contiguous_poly (cp1)) stop 42 + if (is_contiguous (cp2)) stop 43 + if (my_contiguous_poly (cp2)) stop 44 + if (is_contiguous (cp3)) stop 45 + if (my_contiguous_poly (cp3)) stop 46 + if (is_contiguous (cp4)) stop 47 + if (my_contiguous_poly (cp4)) stop 48 + + cp1(1:3) => tref%re + cp2 => tref%re + cp3(1:3) => tarr%re + cp4 => tarr%re + + if (is_contiguous (cp1)) stop 51 + if (my_contiguous_poly (cp1)) stop 52 + if (is_contiguous (cp2)) stop 53 + if (my_contiguous_poly (cp2)) stop 54 + if (is_contiguous (cp3)) stop 55 + if (my_contiguous_poly (cp3)) stop 56 + if (is_contiguous (cp4)) stop 57 + if (my_contiguous_poly (cp4)) stop 58 + + deallocate (carr, tarr) +contains + pure logical function my_contiguous_real (x) result (res) + real, pointer, intent(in) :: x(:) + res = is_contiguous (x) + if (any (x /= expect)) error stop 97 + end function my_contiguous_real + + pure logical function my_contiguous_poly (x) result (res) + class(*), pointer, intent(in) :: x(:) + res = is_contiguous (x) + select type (x) + type is (real) + if (any (x /= expect)) error stop 98 + class default + error stop 99 + end select + end function my_contiguous_poly +end From 1429b8a2e93ee853b4e3ae701f8167708e61f653 Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Sun, 2 Nov 2025 00:27:20 +0000 Subject: [PATCH 19/29] Daily bump. --- gcc/DATESTAMP | 2 +- gcc/cp/ChangeLog | 10 ++++++++++ gcc/fortran/ChangeLog | 23 +++++++++++++++++++++++ gcc/testsuite/ChangeLog | 25 +++++++++++++++++++++++++ 4 files changed, 59 insertions(+), 1 deletion(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 38eec118b91c..befd7357351d 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20251101 +20251102 diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 23f2bfa21f2a..27614bb44474 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2025-11-01 Nathaniel Shead + + Backported from master: + 2025-11-01 Nathaniel Shead + + PR c++/122381 + * module.cc (trees_out::core_vals): Write BASELINK_OPTYPE (aka + TREE_CHAIN). + (trees_in::core_vals): Read it. + 2025-10-28 Patrick Palka Backported from master: diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 5e36c6bdd41e..4e8a3e7c0aa8 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,26 @@ +2025-11-01 Harald Anlauf + + Backported from master: + 2025-10-25 Harald Anlauf + + PR fortran/114023 + * trans-expr.cc (gfc_trans_pointer_assignment): Always set dtype + when remapping a pointer. For unlimited polymorphic LHS use + elem_len from RHS. + * trans-intrinsic.cc (gfc_conv_is_contiguous_expr): Extend inline + generated code for IS_CONTIGUOUS for pointer arguments to detect + when span differs from the element size. + +2025-11-01 Harald Anlauf + + Backported from master: + 2025-10-24 Harald Anlauf + + PR fortran/122386 + * dependency.cc (gfc_ref_needs_temporary_p): Revert r16-518. + * trans-intrinsic.cc (gfc_conv_intrinsic_transfer): Force temporary + for SOURCE not being a simply-contiguous array. + 2025-10-25 Harald Anlauf Backported from master: diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c164282c9e1f..91238e7e862a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,28 @@ +2025-11-01 Harald Anlauf + + Backported from master: + 2025-10-25 Harald Anlauf + + PR fortran/114023 + * gfortran.dg/is_contiguous_5.f90: New test. + +2025-11-01 Harald Anlauf + + Backported from master: + 2025-10-24 Harald Anlauf + + PR fortran/122386 + * gfortran.dg/transfer_array_subref_2.f90: New test. + +2025-11-01 Nathaniel Shead + + Backported from master: + 2025-11-01 Nathaniel Shead + + PR c++/122381 + * g++.dg/modules/convop-2_a.H: New test. + * g++.dg/modules/convop-2_b.C: New test. + 2025-10-31 Tamar Christina Backported from master: From 59213fd40fe5f272f603f5b8303d2c371f05c7a5 Mon Sep 17 00:00:00 2001 From: Nathaniel Shead Date: Sun, 26 Oct 2025 22:27:33 +1100 Subject: [PATCH 20/29] c++/modules: Track all static class variables [PR122421] The linker error in the PR is caused because when a static is defined out of the class body, it doesn't yet have a definition and so read_var_def (which would otherwise have noted it) never gets called. This instead moves the responsibility for noting class-scope variables to read_class_def. PR c++/122421 gcc/cp/ChangeLog: * module.cc (trees_in::read_var_def): Don't handle class-scope variables anymore. (trees_in::read_class_def): Handle them here instead. gcc/testsuite/ChangeLog: * g++.dg/modules/inst-6_a.C: New test. * g++.dg/modules/inst-6_b.C: New test. Signed-off-by: Nathaniel Shead Reviewed-by: Jason Merrill (cherry picked from commit fd5c057c2d01346d69119f88ca94debf27842e4e) --- gcc/cp/module.cc | 15 +++++++++------ gcc/testsuite/g++.dg/modules/inst-6_a.C | 14 ++++++++++++++ gcc/testsuite/g++.dg/modules/inst-6_b.C | 12 ++++++++++++ 3 files changed, 35 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/g++.dg/modules/inst-6_a.C create mode 100644 gcc/testsuite/g++.dg/modules/inst-6_b.C diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index 632dc47552a6..eed84706686b 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -12848,12 +12848,11 @@ trees_in::read_var_def (tree decl, tree maybe_template) if (DECL_EXPLICIT_INSTANTIATION (decl) && !DECL_EXTERNAL (decl)) setup_explicit_instantiation_definition_linkage (decl); - if (DECL_IMPLICIT_INSTANTIATION (decl) - || (DECL_EXPLICIT_INSTANTIATION (decl) - && !DECL_EXTERNAL (decl)) - || (DECL_CLASS_SCOPE_P (decl) - && !DECL_VTABLE_OR_VTT_P (decl) - && !DECL_TEMPLATE_INFO (decl))) + /* Class static data members are handled in read_class_def. */ + if (!DECL_CLASS_SCOPE_P (decl) + && (DECL_IMPLICIT_INSTANTIATION (decl) + || (DECL_EXPLICIT_INSTANTIATION (decl) + && !DECL_EXTERNAL (decl)))) note_vague_linkage_variable (decl); } if (!dyn_init) @@ -13267,6 +13266,10 @@ trees_in::read_class_def (tree defn, tree maybe_template) DECL_ACCESS (d) = tree_cons (type, access, list); } } + + if (TREE_CODE (decl) == VAR_DECL + && TREE_CODE (maybe_template) != TEMPLATE_DECL) + note_vague_linkage_variable (decl); } } diff --git a/gcc/testsuite/g++.dg/modules/inst-6_a.C b/gcc/testsuite/g++.dg/modules/inst-6_a.C new file mode 100644 index 000000000000..7f35cc161bfc --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/inst-6_a.C @@ -0,0 +1,14 @@ +// PR c++/122421 +// { dg-additional-options "-fmodules" } +// { dg-module-cmi M } + +export module M; + +export template struct Type { + static const int arr[3]; +}; + +extern template const int Type::arr[3]; +template const int Type::arr[] = { 42, 43, 44 }; + +export Type ti; diff --git a/gcc/testsuite/g++.dg/modules/inst-6_b.C b/gcc/testsuite/g++.dg/modules/inst-6_b.C new file mode 100644 index 000000000000..5a8092ccb148 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/inst-6_b.C @@ -0,0 +1,12 @@ +// PR c++/122421 +// { dg-additional-options "-fmodules" } + +import M; + +int main() { + const int& a = Type::arr[0]; + const int& b = Type::arr[0]; +} + +// { dg-final { scan-assembler {_ZNW1M4TypeIiE3arrE:} } } +// { dg-final { scan-assembler-not {_ZNW1M4TypeIdE3arrE:} } } From 567744aae7b4ace90c1fb6d27f53c179bdd7e33f Mon Sep 17 00:00:00 2001 From: Georg-Johann Lay Date: Sat, 1 Nov 2025 17:33:13 +0100 Subject: [PATCH 21/29] AVR: PR122505 - Fix bloated mulpsi3 in the wake of hacking around PR118012. Since the PR118012 work-around patch, there is an SImode insn also for the non-MUL case, but there is no mulpsi3. This makes the middle-end use the mulsi3 insn for 24-bit multipications like in: __uint24 mul24 (__uint24 a, __uint24 b) { return a * b; } which will be compiled to: mul24: push r28 ; 34 [c=4 l=1] pushqi1/0 push r29 ; 35 [c=4 l=1] pushqi1/0 in r28,__SP_L__ ; 47 [c=4 l=2] *movhi/7 in r29,__SP_H__ sbiw r28,8 ; 48 [c=8 l=1] *addhi3/2 in __tmp_reg__,__SREG__ ; 38 [c=8 l=5] movhi_sp_r/2 cli out __SP_H__,r29 out __SREG__,__tmp_reg__ out __SP_L__,r28 /* prologue: function */ /* frame size = 8 */ /* stack size = 10 */ std Y+1,r22 ; 49 [c=4 l=1] movqi_insn/2 std Y+2,r23 ; 50 [c=4 l=1] movqi_insn/2 std Y+3,r24 ; 51 [c=4 l=1] movqi_insn/2 std Y+5,r18 ; 52 [c=4 l=1] movqi_insn/2 std Y+6,r19 ; 53 [c=4 l=1] movqi_insn/2 std Y+7,r20 ; 54 [c=4 l=1] movqi_insn/2 ldd r18,Y+1 ; 55 [c=4 l=1] movqi_insn/3 ldd r19,Y+2 ; 56 [c=4 l=1] movqi_insn/3 ldd r20,Y+3 ; 57 [c=4 l=1] movqi_insn/3 ldd r21,Y+4 ; 58 [c=4 l=1] movqi_insn/3 ldd r22,Y+5 ; 59 [c=4 l=1] movqi_insn/3 ldd r23,Y+6 ; 60 [c=4 l=1] movqi_insn/3 ldd r24,Y+7 ; 61 [c=4 l=1] movqi_insn/3 ldd r25,Y+8 ; 62 [c=4 l=1] movqi_insn/3 call __mulsi3 ; 33 [c=20 l=2] *mulsi3_call_pr118012 /* epilogue start */ adiw r28,8 ; 63 [c=8 l=1] *addhi3/2 in __tmp_reg__,__SREG__ ; 42 [c=8 l=5] movhi_sp_r/2 cli out __SP_H__,r29 out __SREG__,__tmp_reg__ out __SP_L__,r28 pop r29 ; 43 [c=4 l=1] popqi pop r28 ; 44 [c=4 l=1] popqi ret where the expected code is simply: mul24: call __mulpsi3 ; 9 [c=20 l=2] call_value_insn/1 /* epilogue start */ ret ; 24 [c=0 l=1] return The patch just allows the mulpsi3 insn for the non-MUL case, except for AVR_TINY which passes the 2nd argument on the stack so no insn can be used. The change might be beneficial even in the absence of PR118012 because the __mulpsi3 footprint is leaner than a libcall. PR tree-optimization/118012 PR tree-optimization/122505 gcc/ * config/avr/avr.md (mulpsi3): Also allow the insn condition in the case where avropt_pr118012 && !AVR_TINY. (*mulpsi3): Handle split for the !AVR_HAVE_MUL case. (*mulpsi3-nomul.libgcc_split, *mulpsi3-nomul.libgcc): New insns. (cherry picked from commit ad8de026441c3e57c4761b1c595ace92ed21c254) --- gcc/config/avr/avr.md | 72 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 65 insertions(+), 7 deletions(-) diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md index 3ca0efbbe759..6788e9d82a1d 100644 --- a/gcc/config/avr/avr.md +++ b/gcc/config/avr/avr.md @@ -4091,9 +4091,17 @@ (match_operand:PSI 2 "nonmemory_operand" ""))) (clobber (reg:HI 26)) (clobber (reg:DI 18))])] - "AVR_HAVE_MUL" + "AVR_HAVE_MUL + || (avropt_pr118012 + /* AVR_TINY passes args on the stack, so we cannot work + around PR118012 like this. */ + && ! AVR_TINY)" { - if (s8_operand (operands[2], PSImode)) + if (!AVR_HAVE_MUL) + { + operands[2] = force_reg (PSImode, operands[2]); + } + else if (s8_operand (operands[2], PSImode)) { rtx reg = force_reg (QImode, gen_int_mode (INTVAL (operands[2]), QImode)); emit_insn (gen_mulsqipsi3 (operands[0], reg, operands[1])); @@ -4198,7 +4206,9 @@ (match_operand:PSI 2 "pseudo_register_or_const_int_operand" "rn"))) (clobber (reg:HI 26)) (clobber (reg:DI 18))] - "AVR_HAVE_MUL && !reload_completed" + "!reload_completed + && (AVR_HAVE_MUL + || (avropt_pr118012 && !AVR_TINY))" { gcc_unreachable(); } "&& 1" [(set (reg:PSI 18) @@ -4208,13 +4218,30 @@ (parallel [(set (reg:PSI 22) (mult:PSI (reg:PSI 22) (reg:PSI 18))) - (clobber (reg:QI 21)) - (clobber (reg:QI 25)) - (clobber (reg:HI 26))]) + (clobber (match_dup 3)) + (clobber (match_dup 4)) + (clobber (match_dup 5))]) (set (match_dup 0) (reg:PSI 22))] { - if (s8_operand (operands[2], PSImode)) + if (AVR_HAVE_MUL) + { + operands[3] = gen_rtx_REG (QImode, REG_21); + operands[4] = gen_rtx_REG (QImode, REG_25); + operands[5] = gen_rtx_REG (HImode, REG_26); + } + else + { + operands[3] = gen_rtx_REG (SImode, REG_18); + operands[4] = gen_rtx_SCRATCH (QImode); + operands[5] = gen_rtx_SCRATCH (HImode); + } + + if (!AVR_HAVE_MUL) + { + operands[2] = force_reg (PSImode, operands[2]); + } + else if (s8_operand (operands[2], PSImode)) { rtx reg = force_reg (QImode, gen_int_mode (INTVAL (operands[2]), QImode)); emit_insn (gen_mulsqipsi3 (operands[0], reg, operands[1])); @@ -4273,6 +4300,37 @@ "%~call __mulpsi3" [(set_attr "type" "xcall")]) +(define_insn_and_split "*mulpsi3-nomul.libgcc_split" + [(set (reg:PSI 22) + (mult:PSI (reg:PSI 22) + (reg:PSI 18))) + (clobber (reg:SI 18)) + (clobber (scratch:QI)) + (clobber (scratch:HI))] + "!AVR_HAVE_MUL && avropt_pr118012 && !AVR_TINY" + "#" + "&& reload_completed" + [(parallel [(set (reg:PSI 22) + (mult:PSI (reg:PSI 22) + (reg:PSI 18))) + (clobber (reg:SI 18)) + (clobber (scratch:QI)) + (clobber (scratch:HI)) + (clobber (reg:CC REG_CC))])]) + +(define_insn "*mulpsi3-nomul.libgcc" + [(set (reg:PSI 22) + (mult:PSI (reg:PSI 22) + (reg:PSI 18))) + (clobber (reg:SI 18)) + (clobber (scratch:QI)) + (clobber (scratch:HI)) + (clobber (reg:CC REG_CC))] + "reload_completed + && !AVR_HAVE_MUL && avropt_pr118012 && !AVR_TINY" + "%~call __mulpsi3" + [(set_attr "type" "xcall")]) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; 24-bit signed/unsigned division and modulo. From a56bab18b048d0edf8f8d81735982dee8b08bc78 Mon Sep 17 00:00:00 2001 From: Georg-Johann Lay Date: Sun, 2 Nov 2025 15:12:59 +0100 Subject: [PATCH 22/29] AVR: target/122527 -- Don't use __load_N to load from __flash1. This patch fixes a case where a 3 byte or 4 byte load from __flash1 uses __load_3/4 to read the value, which is wrong. This only occured when the device has ELPM but not ELPMx (avr31). PR target/122527 gcc/ * config/avr/avr.cc (avr_load_libgcc_p): Return false if the address-space is not ADDR_SPACE_FLASH. (avr_out_lpm_no_lpmx [addr=REG]): Handle sizes of 3 and 4 bytes. (cherry picked from commit 0b2c031cca4017c5f87af519f0977b33b4bcb284) --- gcc/config/avr/avr.cc | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/gcc/config/avr/avr.cc b/gcc/config/avr/avr.cc index cf80d5a15551..2b625e637170 100644 --- a/gcc/config/avr/avr.cc +++ b/gcc/config/avr/avr.cc @@ -3293,7 +3293,8 @@ avr_load_libgcc_p (rtx op) return (n_bytes > 2 && !AVR_HAVE_LPMX - && avr_mem_flash_p (op)); + && avr_mem_flash_p (op) + && MEM_ADDR_SPACE (op) == ADDR_SPACE_FLASH); } @@ -3645,6 +3646,46 @@ avr_out_lpm_no_lpmx (rtx_insn *insn, rtx *xop, int *plen) avr_asm_len ("sbiw %2,1", xop, plen, 1); break; /* 2 */ + + /* cases 3 and 4 are only needed with ELPM but no ELPMx. */ + + case 3: + if (REGNO (dest) == REG_Z - 2 + && !reg_unused_after (insn, all_regs_rtx[REG_31])) + avr_asm_len ("push r31", xop, plen, 1); + + avr_asm_len ("%4lpm $ mov %A0,%3 $ adiw %2,1", xop, plen, 3); + avr_asm_len ("%4lpm $ mov %B0,%3 $ adiw %2,1", xop, plen, 3); + avr_asm_len ("%4lpm $ mov %C0,%3", xop, plen, 2); + + if (REGNO (dest) == REG_Z - 2) + { + if (!reg_unused_after (insn, all_regs_rtx[REG_31])) + avr_asm_len ("pop r31", xop, plen, 1); + } + else if (!reg_unused_after (insn, addr)) + avr_asm_len ("sbiw %2,2", xop, plen, 1); + + break; /* 3 */ + + case 4: + avr_asm_len ("%4lpm $ mov %A0,%3 $ adiw %2,1", xop, plen, 3); + avr_asm_len ("%4lpm $ mov %B0,%3 $ adiw %2,1", xop, plen, 3); + if (REGNO (dest) != REG_Z - 2) + { + avr_asm_len ("%4lpm $ mov %C0,%3 $ adiw %2,1", xop, plen, 3); + avr_asm_len ("%4lpm $ mov %D0,%3", xop, plen, 2); + if (!reg_unused_after (insn, addr)) + avr_asm_len ("sbiw %2,3", xop, plen, 1); + } + else + { + avr_asm_len ("%4lpm $ push %3 $ adiw %2,1", xop, plen, 3); + avr_asm_len ("%4lpm $ mov %D0,%3", xop, plen, 2); + avr_asm_len ("pop $C0", xop, plen, 1); + } + + break; /* 4 */ } break; /* REG */ From e3f926be483a9c8a0b852fdbca5b4f2ca3df65fc Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Mon, 3 Nov 2025 00:26:17 +0000 Subject: [PATCH 23/29] Daily bump. --- gcc/ChangeLog | 22 ++++++++++++++++++++++ gcc/DATESTAMP | 2 +- gcc/cp/ChangeLog | 10 ++++++++++ gcc/testsuite/ChangeLog | 9 +++++++++ 4 files changed, 42 insertions(+), 1 deletion(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 90fa0bf788b5..af8c24da51d6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,25 @@ +2025-11-02 Georg-Johann Lay + + Backported from master: + 2025-11-02 Georg-Johann Lay + + PR target/122527 + * config/avr/avr.cc (avr_load_libgcc_p): Return false if + the address-space is not ADDR_SPACE_FLASH. + (avr_out_lpm_no_lpmx [addr=REG]): Handle sizes of 3 and 4 bytes. + +2025-11-02 Georg-Johann Lay + + Backported from master: + 2025-11-02 Georg-Johann Lay + + PR tree-optimization/118012 + PR tree-optimization/122505 + * config/avr/avr.md (mulpsi3): Also allow the insn condition + in the case where avropt_pr118012 && !AVR_TINY. + (*mulpsi3): Handle split for the !AVR_HAVE_MUL case. + (*mulpsi3-nomul.libgcc_split, *mulpsi3-nomul.libgcc): New insns. + 2025-10-31 Tamar Christina Backported from master: diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index befd7357351d..2bb6e40da9a3 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20251102 +20251103 diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 27614bb44474..8cc3c79e347e 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2025-11-02 Nathaniel Shead + + Backported from master: + 2025-11-02 Nathaniel Shead + + PR c++/122421 + * module.cc (trees_in::read_var_def): Don't handle class-scope + variables anymore. + (trees_in::read_class_def): Handle them here instead. + 2025-11-01 Nathaniel Shead Backported from master: diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 91238e7e862a..76e16807516e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2025-11-02 Nathaniel Shead + + Backported from master: + 2025-11-02 Nathaniel Shead + + PR c++/122421 + * g++.dg/modules/inst-6_a.C: New test. + * g++.dg/modules/inst-6_b.C: New test. + 2025-11-01 Harald Anlauf Backported from master: From f70ea624d1435027da9bb54d42f53caff68d97e2 Mon Sep 17 00:00:00 2001 From: Andrew Pinski Date: Wed, 15 Oct 2025 09:59:25 -0700 Subject: [PATCH 24/29] riscv: Fix gimple folding of the vset* intrinsics [PR122270] The problem here is that when the backend folds the vset intrinsics, it tries to keep the lhs of the new statement to be the same as the old statement due to the check in gsi_replace. The problem is with a MEM_REF vset::fold was unsharing the new lhs here and using the original lhs in the other new statement. This meant the check in gsi_replace would fail. This fixes that oversight by switching around which statement gets the unshared version. Note the comment in vset::fold was already correct just not matching the code: /* Replace the call with two statements: a copy of the full tuple to the call result, followed by an update of the individual vector. The fold routines expect the replacement statement to have the same lhs as the original call, so return the copy statement rather than the field update. */ Changes since v1: * v2: Fix testcase. PR target/122270 gcc/ChangeLog: * config/riscv/riscv-vector-builtins-bases.cc (vset::fold): Use the unshare_expr for the statement that will be added seperately rather the one which will be used for the replacement. gcc/testsuite/ChangeLog: * gcc.target/riscv/rvv/base/pr122270-1.c: New test. Signed-off-by: Andrew Pinski (cherry picked from commit 42f5f1004ff16ab25b97d3315a365614c68c6201) --- gcc/config/riscv/riscv-vector-builtins-bases.cc | 5 +++-- gcc/testsuite/gcc.target/riscv/rvv/base/pr122270-1.c | 10 ++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/pr122270-1.c diff --git a/gcc/config/riscv/riscv-vector-builtins-bases.cc b/gcc/config/riscv/riscv-vector-builtins-bases.cc index bf5172c6e041..5ccb872df639 100644 --- a/gcc/config/riscv/riscv-vector-builtins-bases.cc +++ b/gcc/config/riscv/riscv-vector-builtins-bases.cc @@ -1792,12 +1792,13 @@ public: The fold routines expect the replacement statement to have the same lhs as the original call, so return the copy statement rather than the field update. */ - gassign *copy = gimple_build_assign (unshare_expr (f.lhs), rhs_tuple); + gassign *copy = gimple_build_assign (f.lhs, rhs_tuple); /* Get a reference to the individual vector. */ tree field = tuple_type_field (TREE_TYPE (f.lhs)); tree lhs_array - = build3 (COMPONENT_REF, TREE_TYPE (field), f.lhs, field, NULL_TREE); + = build3 (COMPONENT_REF, TREE_TYPE (field), unshare_expr (f.lhs), + field, NULL_TREE); tree lhs_vector = build4 (ARRAY_REF, TREE_TYPE (rhs_vector), lhs_array, index, NULL_TREE, NULL_TREE); gassign *update = gimple_build_assign (lhs_vector, rhs_vector); diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/pr122270-1.c b/gcc/testsuite/gcc.target/riscv/rvv/base/pr122270-1.c new file mode 100644 index 000000000000..a026a7e16d7e --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/pr122270-1.c @@ -0,0 +1,10 @@ +/* { dg-options "" } */ +/* { dg-do compile } */ +/* { dg-add-options riscv_v } */ +/* PR target/122270 */ + +#include "riscv_vector.h" + +void a(vfloat32m1_t b, vfloat32m1x4_t *c) { + *c = __riscv_vset_v_f32m1_f32m1x4(*c, 3, b); +} From 33eebbfdc25e9d7a0e7411ee83bc86a0dd64d755 Mon Sep 17 00:00:00 2001 From: Jeff Law Date: Sat, 1 Nov 2025 08:30:41 -0600 Subject: [PATCH 25/29] [PR rtl-optimization/122321][RISC-V] Bounds check another access to ira_reg_equiv array So another case where we're indexing into the ira_reg_equiv array without checking bounds. I sincerely hope we're not playing wack-a-mole here, but two failures in a couple months for the same core problem is worrisome. Bootstrapped and regression tested on x86_64 and riscv64 as well as run through all the embedded targets in my tester without regressions. PR rtl-optimization/122321 gcc/ * lra-constraints.cc (update_equiv): Make sure REGNO is in ira_reg_equiv before trying to update ira_reg_equiv. gcc/testsuite/ * gcc.target/riscv/rvv/autovec/pr122321.c: New test. (cherry picked from commit ac3eeb987ad04923ddc57a9dc9bd4ec98146a981) --- gcc/lra-constraints.cc | 5 + .../gcc.target/riscv/rvv/autovec/pr122321.c | 150 ++++++++++++++++++ 2 files changed, 155 insertions(+) create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/autovec/pr122321.c diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc index 0cc9b3dbcb27..ed0fdcab14e4 100644 --- a/gcc/lra-constraints.cc +++ b/gcc/lra-constraints.cc @@ -522,6 +522,11 @@ update_equiv (int regno) { rtx x; + /* If REGNO is beyond the length of the equivalence array structure, + then there's nothing to update. */ + if (regno >= ira_reg_equiv_len) + return; + if ((x = ira_reg_equiv[regno].memory) != NULL_RTX) ira_reg_equiv[regno].memory = simplify_replace_fn_rtx (x, NULL_RTX, loc_equivalence_callback, diff --git a/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr122321.c b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr122321.c new file mode 100644 index 000000000000..0e34bc1f1f5a --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/autovec/pr122321.c @@ -0,0 +1,150 @@ +/* { dg-do compile } */ +/* { dg-options "-march=rv64gcv -mabi=lp64d -w -O0" { target rv64 } } */ +/* { dg-options "-march=rv32gcv -mabi=ilp32 -w -O0" { target rv32 } } */ + + +typedef int a; +typedef signed char b; +typedef char c; +typedef short d; +typedef unsigned short e; +typedef a f; +typedef unsigned g; +typedef long h; +h j, k, l, m, n, o; +int p, q, r, s; +short t; +volatile a u; +a v[]; +char w, x; +a *y, *z; +a **aa; +__attribute__((always_inline)) b __attribute__((vector_size(16))) +ab(f __attribute__((vector_size(8 * sizeof(f)))), d ac, + d __attribute__((vector_size(2 * sizeof(d)))), d) { + return __builtin_shufflevector( + (b __attribute__((vector_size(16)))) __builtin_convertvector( + (d __attribute__((vector_size(16 *sizeof(d))))){ + ac, ac, ac, ac, ac, ac, ac, ac, ac, ac, ac, ac, ac}, + c __attribute__((vector_size(16)))) | + __builtin_convertvector( + (d __attribute__((vector_size(16 *sizeof(d))))){ + ac, ac, ac, ac, ac, ac, ac, ac, ac, ac, ac, ac, ac}, + c __attribute__((vector_size(16)))), + __builtin_convertvector( + (d __attribute__((vector_size(16 *sizeof(d))))){ + ac, ac, ac, ac, ac, ac, ac, ac, ac, ac, ac, ac, ac}, + b __attribute__((vector_size(16)))), + 3, 21, 0, 2, 2, 7, 1, 8, 4, 0, 8, 0, 8, 9, 5, 6); +} +__attribute__((always_inline)) g +ad(d ae, h __attribute__((vector_size(32 * sizeof(h))))) { + g f = 6318; + return (8 ? ae / 786856318u : 0) & ae; +} +a(af)(a, int); +void(ag)(long); +char(ah)(char, char); +char(ai)(char); +short(aj)(short, short); +int ak(long, int *, int *, char, int); +void al(signed, a *, int *, long); +char am(int *, short, short); +void an(int *, long, int); +void ao(int, int *, a *); +a ap() { + int *aq, *ar, *as; + short at; + char au, av, aw = 2; + long ax, ay, az = j; + int ba, i; + g __attribute__((vector_size(16 * sizeof(g)))) bb = {80}; + b __attribute__((vector_size(4))) bc = {6}; + int bd[1]; + char *be = &w; + int bf, bg = q; + a **bh[] = { + &y, &z, &z, &y, &y, &y, &y, &y, &z, &z, &y, &z, &y, &y, &y, &y, &z, &y, + &z, &y, &y, &y, &z, &z, &z, &y, &z, &z, &z, &y, &z, &z, &y, &z, &z, &y, + &z, &z, &z, &y, 0, &z, 0, &y, 0, &y, &y, &z, &z, &y, &y, 0, &z, 0, + &z, 0, &y, &z, &z, 0, &z, 0, &z, &z, &z, &y, &z, &z, &y, &z, &z, &y, + 0, &z, 0, &z, &z, &y, 0, &z, 0, &y, 0, &y, &y, &z, &z, &y, &y, 0, + &z, 0, &z, 0, &y, &z, &z, 0, &z, 0, &z, &z, &z, &y, &z, &z, &y, &z, + &z, &y, 0, &z, 0, &z, &z, &y, 0, &z, 0, &y, 0, &y, &y, &z, &z, &y, + &y, 0, &z, 0, &z, 0, &y, &z, &z, 0, &z, 0, &z, &z, &z, &y, &z, &z, + &y, &z, &z, &y, 0, &z, 0, &z, &z, &y, 0, &z, 0, &y, 0, &y, &y, &z, + &z, &y, &y, 0, &z, 0, &z, 0, &y, &z, &z, 0, 0, &z, 0, &z, &z, &z, + &y, &z, &z, &y, &z, &z, &y, 0, &z, 0, 0, &z, &z}; + for (; i; i++) + bd[i] = p; + h __attribute__((vector_size(32 * sizeof(h)))) + bi = {2681, 2681, 2681, 2681, 2681, 2681, 2681, 2681, 2681, 2681, 2681, + 2681, 2681, 2681, 2681, 2681, 2681, 2681, 2681, 2681, 2681, 2681, + 2681, 2681, 2681, 2681, 2681, 2681, 2681, 2681, 2681, 2681}, + bj = __builtin_convertvector( + (c __attribute__((vector_size(32)))){ + aw, aw, aw, aw, aw, aw, aw, aw, aw, aw, aw, aw, aw, aw, aw, aw, + aw, aw, aw, aw, aw, aw, aw, aw, aw, aw, aw, aw, aw, aw, aw, aw}, + h __attribute__((vector_size(32 * sizeof(h))))), + bk = __builtin_convertvector( + __builtin_shufflevector(bb, bb, 4, 8, 7, 9, 1, 10, 4, 7, 0, 4, 3, 5, 6, 7, + 6, 2, 2, 20, 6, 4, 7, 7, 9, 7, 4, 9, 8, 6, 1, 0, + 6, 9), + h __attribute__((vector_size(32 * sizeof(h))))); + bb = __builtin_convertvector( + ab(__builtin_shufflevector( + __builtin_shufflevector( + __builtin_convertvector( + __builtin_shufflevector(bb, bb, 1, 31, 8, 2, 3, 7, 4, 0, 7, + 3, 4, 6, 7, 1, 9, 3, 8, 7, 1, 8, 5, + 3, 9, 9, 0, 3, 2, 8, 5, 2, 5, 3), + f __attribute__((vector_size(32 * sizeof(f))))), + (f __attribute__((vector_size(32 * sizeof(f))))){ + 800761418310502961587690471176286910032020044212442466872080013589354162852207417903424527024812447907811618435019152886919380169872910001752451018659493155196043018716516518746289614523948734758456011127254301274351182132760058399143431214610613191313926994549901191890929084305862034120561651877003645}, + 32, 44), + (f __attribute__((vector_size(2 * sizeof(f))))){o}, 1, 0, 3, 0, 2, + 1, 3, 3), + ad(__builtin_clzg((g)aw, (f)bb[9]), + (h __attribute__((vector_size(32 * sizeof(h))))){ + bi[0] ?: bk[0], bi[1] ? 1 : bk[1], bi[2] ? 2 : bk[2], + bi[3] ? 3 : bk[3], bi[4] ? 4 : bk[4], bi[5] ? 5 : bk[5], + bi[6] ? 6 : bk[6], bi[7] ? 7 : bk[7], bi[8] ? 8 : bk[8], + bi[9] ? 9 : bk[9], bi[0] ? 10 : bk[0], bi[1] ? 1 : bk[1], + bi[2] ? 2 : bk[2], bi[3] ? 3 : bk[3], bi[4] ? 4 : bk[4], + bi[5] ? 5 : bk[5], bi[6] ? 6 : bk[6], bi[7] ? 7 : bk[7], + bi[8] ? 8 : bk[8], bi[9] ? 9 : bk[9], bi[0] ? 20 : bk[0], + bi[1] ? 1 : bk[1], bi[2] ? 2 : bk[2], bi[3] ? 3 : bk[3], + bi[4] ? bj[4] : 4, bi[5] ?: 5, bi[6] ?: 6, + bi[7] ? 0 : 7, bi[8] ?: 8, bi[9] ? 0 : 9, + bi[0] ? 0 : 30, bi[1] ?: 1}), + (d __attribute__((vector_size(2 * sizeof(d))))) + __builtin_shufflevector( + __builtin_convertvector( + __builtin_shufflevector(bb, bb, 2, 7, 21, 6), + e __attribute__((vector_size(4 * sizeof(e))))), + __builtin_convertvector( + (c __attribute__((vector_size(4)))){aw, aw}, + e __attribute__((vector_size(4 * sizeof(e))))), + 5, 1) + + (__builtin_convertvector( + __builtin_shufflevector(bb, bb, 4, 5), + e __attribute__((vector_size(2 * sizeof(e))))) <= + __builtin_convertvector( + (c __attribute__((vector_size(2)))){aw}, + e __attribute__((vector_size(2 * sizeof(e)))))), + n ? bb[5] << n : aw), + g __attribute__((vector_size(16 * sizeof(g))))); + ag(aw & t); + at = aj(aw, v[1]); + au = ah(at, aw); + ba = af((1 == ax != aw) <= aw <= au, aw); + ao(0, &bd[0], &r); + o = ay; + an(aq, aw, k); + av = am(ar, l, k); + *be = ai(*be); + al(x, as, &bd[0], aw); + bg = ak(u, &s, &bf, aw, aw); + as = *aa; + return m; +} From 7503954945b71d13e28acd457301978b3b6482cc Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Tue, 4 Nov 2025 00:26:35 +0000 Subject: [PATCH 26/29] Daily bump. --- gcc/ChangeLog | 19 +++++++++++++++++++ gcc/DATESTAMP | 2 +- gcc/testsuite/ChangeLog | 16 ++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index af8c24da51d6..fb9b2fea6973 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,22 @@ +2025-11-03 Jeff Law + + Backported from master: + 2025-11-01 Jeff Law + + PR rtl-optimization/122321 + * lra-constraints.cc (update_equiv): Make sure REGNO is in + ira_reg_equiv before trying to update ira_reg_equiv. + +2025-11-03 Andrew Pinski + + Backported from master: + 2025-10-26 Andrew Pinski + + PR target/122270 + * config/riscv/riscv-vector-builtins-bases.cc (vset::fold): Use the + unshare_expr for the statement that will be added seperately rather + the one which will be used for the replacement. + 2025-11-02 Georg-Johann Lay Backported from master: diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 2bb6e40da9a3..23733dc657b2 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20251103 +20251104 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 76e16807516e..ab6c960e3467 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,19 @@ +2025-11-03 Jeff Law + + Backported from master: + 2025-11-01 Jeff Law + + PR rtl-optimization/122321 + * gcc.target/riscv/rvv/autovec/pr122321.c: New test. + +2025-11-03 Andrew Pinski + + Backported from master: + 2025-10-26 Andrew Pinski + + PR target/122270 + * gcc.target/riscv/rvv/base/pr122270-1.c: New test. + 2025-11-02 Nathaniel Shead Backported from master: From 934b2d4ad4470b0acf8711d7406c65490877ac52 Mon Sep 17 00:00:00 2001 From: Nathaniel Shead Date: Thu, 16 Oct 2025 22:51:23 +1100 Subject: [PATCH 27/29] c++: Don't constrain template visibility using no-linkage variables [PR122253] When finding the minimal visibility of a template, any reference to a dependent automatic variable will cause the instantiation to be marked as internal linkage. However, when processing the template decl we don't yet know whether that should actually be the case, as a given instantiation may not require referencing the local decl in its mangling. This patch fixes the issue by checking for no-linkage decls first, in which case we just constrain using the type of the entity. We can't use a check for lk_external/lk_internal in the other cases, as instantiations referring to internal types can still have external linkage as determined by the language, but should still constrain the visibility of any declarations that refer to them. PR c++/122253 gcc/cp/ChangeLog: * decl2.cc (min_vis_expr_r): Don't mark no-linkage declarations as VISIBILITY_ANON. gcc/testsuite/ChangeLog: * g++.dg/modules/internal-16.C: New test. Signed-off-by: Nathaniel Shead Reviewed-by: Patrick Palka Reviewed-by: Jason Merrill (cherry picked from commit f062a6b7985fcee82e02b626aada4e0824850bd0) --- gcc/cp/decl2.cc | 7 ++++- gcc/testsuite/g++.dg/modules/internal-16.C | 30 ++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/modules/internal-16.C diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc index 63a5a21511df..4a29c4a0b1c0 100644 --- a/gcc/cp/decl2.cc +++ b/gcc/cp/decl2.cc @@ -2862,7 +2862,12 @@ min_vis_expr_r (tree *tp, int */*walk_subtrees*/, void *data) break; } addressable: - if (! TREE_PUBLIC (t)) + if (decl_linkage (t) == lk_none) + tpvis = type_visibility (TREE_TYPE (t)); + /* Decls that have had their visibility constrained will report + as external linkage, but we still want to transitively constrain + if we refer to them, so just check TREE_PUBLIC instead. */ + else if (!TREE_PUBLIC (t)) tpvis = VISIBILITY_ANON; else tpvis = DECL_VISIBILITY (t); diff --git a/gcc/testsuite/g++.dg/modules/internal-16.C b/gcc/testsuite/g++.dg/modules/internal-16.C new file mode 100644 index 000000000000..4a928ae801bb --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/internal-16.C @@ -0,0 +1,30 @@ +// PR c++/122253 +// { dg-additional-options "-fmodules -Wtemplate-names-tu-local" } + +export module M; + +template struct ic {}; +struct S { + constexpr operator int() const { return 5; } + constexpr int operator&() const { return 8; } +}; + +template inline void a(T) { + T a; + static T b; + ic{}; + ic{}; + ic<&a>{}; + ic<&b>{}; +} + +template inline auto b(T x) { + return [&](auto y) { + return [=](auto z) { + return ic<(int)x + (int)&y + (int)z>{}; + }; + }; +} + +template void a(S); +ic<5 + 8 + 5> x = b(S{})(S{})(S{}); From 3c42004d6e1524ce18f9f456b1cf8a78d54fc0b2 Mon Sep 17 00:00:00 2001 From: Bob Duff Date: Wed, 20 Aug 2025 14:07:14 -0400 Subject: [PATCH 28/29] Ada: Fix visibility bug related to target name This patch fixes the following bug: If the right-hand side of an expression contains a target name (i.e. "@"), and also contains a reference to a user-defined operator that is directly visible because of a "use type" clause on a renaming of the package where the operator is declared, the compiler gives an incorrect error saying that the renamed package is not visible. It turns out that setting Entity of resolved nodes is unnecessary and wrong; the fix is to simply remove that code. gcc/ada/ChangeLog: PR ada/118208 * exp_ch5.adb (Expand_Assign_With_Target_Names.Replace_Target): Remove code setting Entity to Empty. * sinfo.ads (Has_Target_Names): Improve comment: add "@" to clarify what "target name" means, and remove the content-free phrase "and must be expanded accordingly." --- gcc/ada/exp_ch5.adb | 17 ++--------------- gcc/ada/sinfo.ads | 2 +- 2 files changed, 3 insertions(+), 16 deletions(-) diff --git a/gcc/ada/exp_ch5.adb b/gcc/ada/exp_ch5.adb index 3d8a542c24e0..bdd7d19dcc0e 100644 --- a/gcc/ada/exp_ch5.adb +++ b/gcc/ada/exp_ch5.adb @@ -2254,7 +2254,8 @@ package body Exp_Ch5 is function Replace_Target (N : Node_Id) return Traverse_Result; -- Replace occurrences of the target name by the proper entity: either -- the entity of the LHS in simple cases, or the formal of the - -- constructed procedure otherwise. + -- constructed procedure otherwise. Mark all nodes as Analyzed=False + -- so reanalysis will occur. -------------------- -- Replace_Target -- @@ -2264,20 +2265,6 @@ package body Exp_Ch5 is begin if Nkind (N) = N_Target_Name then Rewrite (N, New_Occurrence_Of (Ent, Sloc (N))); - - -- The expression will be reanalyzed when the enclosing assignment - -- is reanalyzed, so reset the entity, which may be a temporary - -- created during analysis, e.g. a loop variable for an iterated - -- component association. However, if entity is callable then - -- resolution has established its proper identity (including in - -- rewritten prefixed calls) so we must preserve it. - - elsif Is_Entity_Name (N) then - if Present (Entity (N)) - and then not Is_Overloadable (Entity (N)) - then - Set_Entity (N, Empty); - end if; end if; Set_Analyzed (N, False); diff --git a/gcc/ada/sinfo.ads b/gcc/ada/sinfo.ads index d22f1030d427..1ad81715a2bc 100644 --- a/gcc/ada/sinfo.ads +++ b/gcc/ada/sinfo.ads @@ -1477,7 +1477,7 @@ package Sinfo is -- Has_Target_Names -- Present in assignment statements. Indicates that the RHS contains - -- target names (see AI12-0125-3) and must be expanded accordingly. + -- target names ("@" -- see AI12-0125-3). -- Has_Wide_Character -- Present in string literals, set if any wide character (i.e. character From cc39aed963b5c6044baf37c074413b6273303419 Mon Sep 17 00:00:00 2001 From: GCC Administrator Date: Wed, 5 Nov 2025 00:26:25 +0000 Subject: [PATCH 29/29] Daily bump. --- gcc/DATESTAMP | 2 +- gcc/ada/ChangeLog | 11 +++++++++++ gcc/cp/ChangeLog | 9 +++++++++ gcc/testsuite/ChangeLog | 8 ++++++++ 4 files changed, 29 insertions(+), 1 deletion(-) diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP index 23733dc657b2..7b0f631f939e 100644 --- a/gcc/DATESTAMP +++ b/gcc/DATESTAMP @@ -1 +1 @@ -20251104 +20251105 diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 9401a29c06ad..abfd31509254 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,14 @@ +2025-11-04 Bob Duff + + PR ada/118208 + * exp_ch5.adb + (Expand_Assign_With_Target_Names.Replace_Target): + Remove code setting Entity to Empty. + * sinfo.ads (Has_Target_Names): + Improve comment: add "@" to clarify what "target name" + means, and remove the content-free phrase "and must + be expanded accordingly." + 2025-10-24 Eric Botcazou PR ada/118782 diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 8cc3c79e347e..70a0a5cc0afc 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +2025-11-04 Nathaniel Shead + + Backported from master: + 2025-11-04 Nathaniel Shead + + PR c++/122253 + * decl2.cc (min_vis_expr_r): Don't mark no-linkage declarations + as VISIBILITY_ANON. + 2025-11-02 Nathaniel Shead Backported from master: diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ab6c960e3467..b0478074412c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2025-11-04 Nathaniel Shead + + Backported from master: + 2025-11-04 Nathaniel Shead + + PR c++/122253 + * g++.dg/modules/internal-16.C: New test. + 2025-11-03 Jeff Law Backported from master: