aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog75
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/cgraph.h5
-rw-r--r--gcc/config/aarch64/aarch64-simd.md24
-rw-r--r--gcc/fold-const.cc16
-rw-r--r--gcc/fold-const.h1
-rw-r--r--gcc/fortran/ChangeLog14
-rw-r--r--gcc/fortran/intrinsic.texi2
-rw-r--r--gcc/fortran/primary.cc35
-rw-r--r--gcc/fortran/trans-intrinsic.cc8
-rw-r--r--gcc/symtab.cc15
-rw-r--r--gcc/testsuite/ChangeLog39
-rw-r--r--gcc/testsuite/gcc.dg/fold-vecperm-1.c4
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr122502.c21
-rw-r--r--gcc/testsuite/gcc.target/aarch64/pr121853_1.c64
-rw-r--r--gcc/testsuite/gcc.target/aarch64/pr121853_2.c14
-rw-r--r--gcc/testsuite/gfortran.dg/pdt_65.f03135
-rw-r--r--gcc/tree-scalar-evolution.cc10
18 files changed, 442 insertions, 42 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 53c6bd0..00f62e1 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,78 @@
+2025-10-31 Andrew Pinski <andrew.pinski@oss.qualcomm.com>
+
+ PR tree-optimization/122437
+ * fold-const.h (div_if_zero_remainder): Remove.
+
+2025-10-31 Tamar Christina <tamar.christina@arm.com>
+
+ PR target/121853
+ * config/aarch64/aarch64-simd.md (extendbfsf2): New.
+
+2025-10-31 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/122502
+ * tree-scalar-evolution.cc (final_value_replacement_loop):
+ Avoid folding from within FOR_EACH_IMM_USE_STMT due to active
+ ranger.
+
+2025-10-31 Andrew Pinski <andrew.pinski@oss.qualcomm.com>
+
+ PR tree-optimization/122437
+ * fold-const.cc (div_if_zero_remainder): Remove.
+
+2025-10-31 Andrew Pinski <andrew.pinski@oss.qualcomm.com>
+
+ PR tree-optimization/122497
+ * tree-scalar-evolution.cc (final_value_replacement_loop): Call replace_uses_by
+ only after the replacement statement was created.
+
+2025-10-31 Lulu Cheng <chenglulu@loongson.cn>
+
+ * config/loongarch/lasx.md: Support.
+ * config/loongarch/loongarch.cc
+ (loongarch_expand_vec_widen_hilo): Remove unused code.
+ * config/loongarch/lsx.md: Support.
+
+2025-10-31 Lulu Cheng <chenglulu@loongson.cn>
+
+ * config/loongarch/lasx.md (ILASX_HB): Move to ...
+ * config/loongarch/lsx.md (ILSX_HB): Move to ...
+ * config/loongarch/simd.md (ILSX_HB): ... here.
+ (ILASX_HB): ... here.
+ (IVEC_HB): New iterator.
+ (WVEC_QUARTER): New attr.
+ (wvec_quarter): Likewise.
+ (simdfmt_qw): Likewise.
+ (<su>dot_prod<wvec_quarter><mode>): New template.
+
+2025-10-31 Lulu Cheng <chenglulu@loongson.cn>
+
+ * config/loongarch/lasx.md (hi_lo): Move to ...
+ * config/loongarch/simd.md (hi_lo): ... here.
+ * config/loongarch/loongarch.cc
+ (loongarch_expand_vec_widen_hilo): Add 128-bit data processing.
+ * config/loongarch/lsx.md
+ (vec_widen_<su><optab>_<hi_lo>_<mode>): New define_expand.
+ (vec_widen_<su>mult_<hi_lo>_<mode>): Likewise.
+
+2025-10-31 Lulu Cheng <chenglulu@loongson.cn>
+
+ * config/loongarch/lasx.md (vec_widen_<su>add_hi_<mode>):
+ Move.
+ (vec_widen_<su>add_lo_<mode>): Move.
+ (vec_widen_<su>sub_hi_<mode>): Move.
+ (vec_widen_<su>sub_lo_<mode>): Move.
+ (vec_widen_<su>mult_hi_<mode>): Move.
+ (vec_widen_<su>mult_lo_<mode>): Move.
+ (hi_lo): New define_int_attr.
+ (vec_widen_<su><optab>_<hi_lo>_<mode>): New define_expand.
+ (vec_widen_<su>mult_<hi_lo>_<mode>): Likewise.
+ * config/loongarch/loongarch-protos.h
+ (loongarch_expand_vec_widen_hilo): Modify the function
+ parameter list.
+ * config/loongarch/loongarch.cc
+ (loongarch_expand_vec_widen_hilo): Optimized.
+
2025-10-30 David Faust <david.faust@oracle.com>
PR debug/122248
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index 986fa53..38eec11 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20251031
+20251101
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index a937d0a..aa2207b 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -38,6 +38,8 @@ class ipa_opt_pass_d;
typedef ipa_opt_pass_d *ipa_opt_pass;
/* Toplevel consists of functions, variables and assembly.
+ Make sure toplevel_type_names in symtab.cc is kept in sync
+ with this.
TODO: add labels and CONST_DECLs. */
enum toplevel_type
{
@@ -45,7 +47,8 @@ enum toplevel_type
TOPLEVEL_ASM,
SYMTAB_SYMBOL,
SYMTAB_FUNCTION,
- SYMTAB_VARIABLE
+ SYMTAB_VARIABLE,
+ TOPLEVEL_MAX
};
/* Section names are stored as reference counted strings in GGC safe hashtable
diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md
index a121a18..e7c459d 100644
--- a/gcc/config/aarch64/aarch64-simd.md
+++ b/gcc/config/aarch64/aarch64-simd.md
@@ -3223,6 +3223,7 @@
DONE;
}
)
+
(define_insn "extend<mode><Vwide>2"
[(set (match_operand:<VWIDE> 0 "register_operand" "=w")
(float_extend:<VWIDE>
@@ -3232,6 +3233,29 @@
[(set_attr "type" "neon_fp_cvt_widen_s")]
)
+/* A BF->SF is a shift left of 16, however shifts are expensive and the generic
+ middle-end expansion would force through DI move. Instead use EXT to do the
+ shift to get better throughput and don't go through GPRs. */
+
+(define_expand "extendbfsf2"
+ [(set (match_operand:SF 0 "register_operand" "=w")
+ (float_extend:SF
+ (match_operand:BF 1 "register_operand" "w")))]
+ "TARGET_SIMD"
+{
+ rtx tmp0 = aarch64_gen_shareable_zero (V8BFmode);
+ rtx op0 = force_lowpart_subreg (V8BFmode, operands[1], BFmode);
+ rtx res = gen_reg_rtx (V8BFmode);
+ emit_insn (gen_aarch64_extv8bf (res, tmp0, op0, gen_int_mode (7, SImode)));
+ /* Subregs between floating point modes aren't allowed to change size, so go
+ through V4SFmode. */
+ res = force_lowpart_subreg (V4SFmode, res, V8BFmode);
+ res = force_lowpart_subreg (SFmode, res, V4SFmode);
+ emit_move_insn (operands[0], res);
+ DONE;
+})
+
+
;; Float narrowing operations.
(define_insn "aarch64_float_trunc_rodd_df"
diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc
index 1311c6e..861d73c 100644
--- a/gcc/fold-const.cc
+++ b/gcc/fold-const.cc
@@ -264,22 +264,6 @@ protected_set_expr_location_unshare (tree x, location_t loc)
return x;
}
-/* If ARG2 divides ARG1 with zero remainder, carries out the exact
- division and returns the quotient. Otherwise returns
- NULL_TREE. */
-
-tree
-div_if_zero_remainder (const_tree arg1, const_tree arg2)
-{
- widest_int quo;
-
- if (wi::multiple_of_p (wi::to_widest (arg1), wi::to_widest (arg2),
- SIGNED, &quo))
- return wide_int_to_tree (TREE_TYPE (arg1), quo);
-
- return NULL_TREE;
-}
-
/* This is nonzero if we should defer warnings about undefined
overflow. This facility exists because these warnings are a
special case. The code to estimate loop iterations does not want
diff --git a/gcc/fold-const.h b/gcc/fold-const.h
index 00975dc..87e7ec1 100644
--- a/gcc/fold-const.h
+++ b/gcc/fold-const.h
@@ -153,7 +153,6 @@ extern tree build_simple_mem_ref_loc (location_t, tree);
extern poly_offset_int mem_ref_offset (const_tree);
extern tree build_invariant_address (tree, tree, poly_int64);
extern tree constant_boolean_node (bool, tree);
-extern tree div_if_zero_remainder (const_tree, const_tree);
extern bool tree_swap_operands_p (const_tree, const_tree);
extern enum tree_code swap_tree_comparison (enum tree_code);
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index e7c7907..0d937eb 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,17 @@
+2025-10-31 Yuao Ma <c8ef@outlook.com>
+
+ * intrinsic.texi: Fix typo.
+ * trans-intrinsic.cc (conv_intrinsic_atomic_cas): Remove unreachable
+ code.
+
+2025-10-31 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/122452
+ * primary.cc (gfc_match_rvalue): Give priority to specific
+ procedures in a generic interface with the same name as a
+ PDT template. If found, use as the procedure instead of the
+ constructor generated from the PDT template.
+
2025-10-30 Mikael Morin <mikael@gcc.gnu.org>
* trans-array.cc: Cleanup obsolete comment.
diff --git a/gcc/fortran/intrinsic.texi b/gcc/fortran/intrinsic.texi
index 9012c2a..b2d1e45 100644
--- a/gcc/fortran/intrinsic.texi
+++ b/gcc/fortran/intrinsic.texi
@@ -2239,7 +2239,7 @@ is different, the value is converted to the kind of @var{ATOM}.
program atomic
use iso_fortran_env
logical(atomic_logical_kind) :: atom[*], prev
- call atomic_cas (atom[1], prev, .false., .true.))
+ call atomic_cas (atom[1], prev, .false., .true.)
end program atomic
@end smallexample
diff --git a/gcc/fortran/primary.cc b/gcc/fortran/primary.cc
index 0722c76d..1dcb1c3 100644
--- a/gcc/fortran/primary.cc
+++ b/gcc/fortran/primary.cc
@@ -3835,6 +3835,9 @@ gfc_match_rvalue (gfc_expr **result)
gfc_typespec *ts;
bool implicit_char;
gfc_ref *ref;
+ gfc_symtree *pdt_st;
+ gfc_symbol *found_specific = NULL;
+
m = gfc_match ("%%loc");
if (m == MATCH_YES)
@@ -4082,22 +4085,36 @@ gfc_match_rvalue (gfc_expr **result)
break;
}
+ gfc_gobble_whitespace ();
+ found_specific = NULL;
+
+ /* Even if 'name' is that of a PDT template, priority has to be given to
+ possible specific procedures in the generic interface. */
+ gfc_find_sym_tree (gfc_dt_upper_string (name), NULL, 1, &pdt_st);
+ if (sym->generic && sym->generic->next
+ && gfc_peek_ascii_char() != '(')
+ {
+ gfc_actual_arglist *arg = actual_arglist;
+ for (; arg && pdt_st; arg = arg->next)
+ gfc_resolve_expr (arg->expr);
+ found_specific = gfc_search_interface (sym->generic, 0,
+ &actual_arglist);
+ }
+
/* Check to see if this is a PDT constructor. The format of these
constructors is rather unusual:
name [(type_params)](component_values)
where, component_values excludes the type_params. With the present
gfortran representation this is rather awkward because the two are not
distinguished, other than by their attributes. */
- if (sym->attr.generic)
+ if (sym->attr.generic && pdt_st != NULL && found_specific == NULL)
{
- gfc_symtree *pdt_st;
gfc_symbol *pdt_sym;
gfc_actual_arglist *ctr_arglist = NULL, *tmp;
gfc_component *c;
- /* Obtain the template. */
- gfc_find_sym_tree (gfc_dt_upper_string (name), NULL, 1, &pdt_st);
- if (pdt_st && pdt_st->n.sym && pdt_st->n.sym->attr.pdt_template)
+ /* Use the template. */
+ if (pdt_st->n.sym && pdt_st->n.sym->attr.pdt_template)
{
bool type_spec_list = false;
pdt_sym = pdt_st->n.sym;
@@ -4155,8 +4172,12 @@ gfc_match_rvalue (gfc_expr **result)
tmp = tmp->next;
}
- gfc_find_sym_tree (gfc_dt_lower_string (pdt_sym->name),
- NULL, 1, &symtree);
+ if (found_specific)
+ gfc_find_sym_tree (found_specific->name,
+ NULL, 1, &symtree);
+ else
+ gfc_find_sym_tree (gfc_dt_lower_string (pdt_sym->name),
+ NULL, 1, &symtree);
if (!symtree)
{
gfc_get_ha_sym_tree (gfc_dt_lower_string (pdt_sym->name) ,
diff --git a/gcc/fortran/trans-intrinsic.cc b/gcc/fortran/trans-intrinsic.cc
index 89a03d8..5b9111d3 100644
--- a/gcc/fortran/trans-intrinsic.cc
+++ b/gcc/fortran/trans-intrinsic.cc
@@ -12844,14 +12844,6 @@ conv_intrinsic_atomic_cas (gfc_code *code)
new_val = gfc_build_addr_expr (NULL_TREE, tmp);
}
- /* Convert a constant to a pointer. */
- if (!POINTER_TYPE_P (TREE_TYPE (comp)))
- {
- tmp = gfc_create_var (TREE_TYPE (TREE_TYPE (old)), "comp");
- gfc_add_modify (&block, tmp, fold_convert (TREE_TYPE (tmp), comp));
- comp = gfc_build_addr_expr (NULL_TREE, tmp);
- }
-
gfc_init_se (&argse, NULL);
gfc_get_caf_token_offset (&argse, &token, &offset, caf_decl, atom,
atom_expr);
diff --git a/gcc/symtab.cc b/gcc/symtab.cc
index 20dfe09..fb2aca5 100644
--- a/gcc/symtab.cc
+++ b/gcc/symtab.cc
@@ -873,7 +873,16 @@ symtab_node::dump_referring (FILE *file)
fprintf (file, "\n");
}
-static const char * const symtab_type_names[] = {"symbol", "function", "variable"};
+static const char * const toplevel_type_names[] =
+{
+ "base",
+ "asm",
+ "symbol",
+ "function",
+ "variable",
+};
+
+static_assert (ARRAY_SIZE(toplevel_type_names)==TOPLEVEL_MAX);
/* Dump the visibility of the symbol. */
@@ -889,7 +898,7 @@ symtab_node::get_visibility_string () const
const char *
symtab_node::get_symtab_type_string () const
{
- return symtab_type_names[type];
+ return toplevel_type_names[type];
}
/* Dump base fields of symtab nodes to F. Not to be used directly. */
@@ -904,7 +913,7 @@ symtab_node::dump_base (FILE *f)
fprintf (f, "%s (%s)", dump_asm_name (), name ());
if (dump_flags & TDF_ADDRESS)
dump_addr (f, " @", (void *)this);
- fprintf (f, "\n Type: %s", symtab_type_names[type]);
+ fprintf (f, "\n Type: %s", toplevel_type_names[type]);
if (definition)
fprintf (f, " definition");
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index daf99d1..013121d 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,42 @@
+2025-10-31 Tamar Christina <tamar.christina@arm.com>
+
+ PR target/121853
+ * gcc.target/aarch64/pr121853_1.c: New test.
+ * gcc.target/aarch64/pr121853_2.c: New test.
+
+2025-10-31 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/122452
+ * gfortran.dg/pdt_65.f03: New test.
+
+2025-10-31 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/122502
+ * gcc.dg/torture/pr122502.c: New testcase.
+
+2025-10-31 Andrew Pinski <andrew.pinski@oss.qualcomm.com>
+
+ * gcc.dg/tree-ssa/pr122478.c: Swap `1` and `"optimized"`.
+
+2025-10-31 Andrew Pinski <andrew.pinski@oss.qualcomm.com>
+
+ PR tree-optimization/122497
+ * gcc.dg/torture/pr122497-1.c: New test.
+
+2025-10-31 Lulu Cheng <chenglulu@loongson.cn>
+
+ * gcc.dg/vect/slp-widen-mult-half.c: Remove '-mlasx'.
+ * gcc.dg/vect/tree-vect.h: Check whether the runtime
+ environment supports LSX instructions.
+ * gcc.dg/vect/vect-widen-mult-const-s16.c: Dito.
+ * gcc.dg/vect/vect-widen-mult-const-u16.c: Dito.
+ * gcc.dg/vect/vect-widen-mult-half-u8.c: Dito.
+ * gcc.dg/vect/vect-widen-mult-half.c: Dito.
+ * gcc.dg/vect/vect-widen-mult-u16.c: Dito.
+ * gcc.dg/vect/vect-widen-mult-u8-s16-s32.c: Dito.
+ * gcc.dg/vect/vect-widen-mult-u8-u32.c: Dito.
+ * gcc.dg/vect/vect-widen-mult-u8.c: Dito.
+
2025-10-30 Yap Zhi Heng <yapzhhg@gmail.com>
* rust/compile/tuplepattern-restpattern-typecheck-err.rs: New file.
diff --git a/gcc/testsuite/gcc.dg/fold-vecperm-1.c b/gcc/testsuite/gcc.dg/fold-vecperm-1.c
index 5d4456b..878d392 100644
--- a/gcc/testsuite/gcc.dg/fold-vecperm-1.c
+++ b/gcc/testsuite/gcc.dg/fold-vecperm-1.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-options "-O2 -fdump-tree-forwprop3" } */
typedef int v4si __attribute__((vector_size(16)));
typedef short v8hi __attribute__((vector_size(16)));
@@ -20,4 +20,4 @@ int128 concat (int128 a, int128 b) {
return res;
}
-/* { dg-final { scan-tree-dump-times "VEC_PERM_EXPR" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "VEC_PERM_EXPR" 1 "forwprop3" } } */
diff --git a/gcc/testsuite/gcc.dg/torture/pr122502.c b/gcc/testsuite/gcc.dg/torture/pr122502.c
new file mode 100644
index 0000000..5e2cb2e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr122502.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+
+short int *ts;
+
+void
+c2 (unsigned long long int s4, int ns)
+{
+ short int *b2 = (short int *)&ns;
+
+ while (ns != 0)
+ {
+ int xn;
+
+ for (xn = 0; xn < 3; ++xn)
+ for (*b2 = 0; *b2 < 2; ++*b2)
+ s4 += xn;
+ if (s4 != 0)
+ b2 = ts;
+ ++ns;
+ }
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/pr121853_1.c b/gcc/testsuite/gcc.target/aarch64/pr121853_1.c
new file mode 100644
index 0000000..24b2fdc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/pr121853_1.c
@@ -0,0 +1,64 @@
+/* { dg-do run } */
+/* { dg-additional-options "-O2 -std=c99" } */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+__attribute__ ((noipa))
+float convert(__bf16 value) {
+ return (float)value;
+}
+
+static inline uint32_t f32_bits(float f) {
+ uint32_t u; memcpy(&u, &f, sizeof u); return u;
+}
+static inline __bf16 bf16_from_bits(uint16_t u) {
+ __bf16 b; memcpy(&b, &u, sizeof b); return b;
+}
+
+/* Fixed bf16 inputs (as raw 16-bit payloads) covering edge cases. */
+static const uint16_t inputs[] = {
+ 0x0000, // +0
+ 0x8000, // -0
+ 0x7F80, // +inf
+ 0xFF80, // -inf
+ 0x7FC0, // qNaN (+) (quiet bit set in bf16)
+ 0xFFC0, // qNaN (-)
+ 0x7F01, // sNaN (+) (will be quieted by conversion)
+ 0xFF01, // sNaN (-)
+ 0x0001, // smallest +subnormal
+ 0x007F, // largest +subnormal
+ 0x8001, // smallest -subnormal
+ 0x807F, // largest -subnormal
+ 0x0080, // smallest +normal
+ 0x3F80, // +1.0
+ 0xBF80, // -1.0
+ 0x3F00, // +0.5
+ 0xBF00, // -0.5
+ 0x3FC0, // +1.5
+ 0x7F7F, // max finite +
+ 0xFF7F, // max finite -
+};
+
+int main(void) {
+ const size_t N = sizeof(inputs)/sizeof(inputs[0]);
+ size_t fails = 0;
+
+ for (size_t i = 0; i < N; ++i) {
+ __bf16 in = bf16_from_bits(inputs[i]);
+ float out = convert(in);
+ uint32_t got = f32_bits(out);
+ uint32_t exp = inputs[i] << 16;
+
+ if (got != exp) {
+ printf("FAIL[%zu]: in_bf16=0x%04X exp_f32=0x%08X got_f32=0x%08X\n",
+ i, inputs[i], exp, got);
+ ++fails;
+ }
+ }
+
+ if (fails != 0)
+ __builtin_abort ();
+}
+
diff --git a/gcc/testsuite/gcc.target/aarch64/pr121853_2.c b/gcc/testsuite/gcc.target/aarch64/pr121853_2.c
new file mode 100644
index 0000000..e9fb401
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/pr121853_2.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O1" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+float convert(__bf16 value) {
+ return (float)value;
+}
+
+/*
+** convert:
+** movi v[0-9]+.4s, 0
+** ext v[0-9]+.16b, v[0-9]+.16b, v[0-9]+.16b, #14
+** ret
+*/
diff --git a/gcc/testsuite/gfortran.dg/pdt_65.f03 b/gcc/testsuite/gfortran.dg/pdt_65.f03
new file mode 100644
index 0000000..d5e45c2
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pdt_65.f03
@@ -0,0 +1,135 @@
+! { dg-do compile }
+! { dg-options "-fdump-tree-original" }
+!
+! Test fix for PR122452
+!
+! Contributed by Damian Rouson <damian@archaeologic.codes>
+!
+module kind_parameters_m
+ integer, parameter :: default_real = kind(1e0)
+ integer, parameter :: double_precision = kind(1d0)
+end module
+
+module tensor_m
+ use kind_parameters_m, only : default_real, double_precision
+ implicit none
+
+ private
+ public :: tensor_t
+
+ type tensor_t(k)
+ integer, kind :: k = default_real
+ real(k), allocatable, private :: values_(:)
+ contains
+ generic :: values => default_real_values, double_precision_values
+ procedure, private, non_overridable :: default_real_values, double_precision_values
+ generic :: num_components => default_real_num_components, double_precision_num_components
+ procedure, private :: default_real_num_components, double_precision_num_components
+ end type
+
+ interface tensor_t
+
+ pure module function construct_default_real(values) result(tensor)
+ implicit none
+ real, intent(in) :: values(:)
+ type(tensor_t) tensor
+ end function
+
+ pure module function construct_double_precision(values) result(tensor)
+ implicit none
+ double precision, intent(in) :: values(:)
+ type(tensor_t(double_precision)) tensor
+ end function
+
+ end interface
+
+ interface
+
+ pure module function default_real_values(self) result(tensor_values)
+ implicit none
+ class(tensor_t), intent(in) :: self
+ real, allocatable :: tensor_values(:)
+ end function
+
+ pure module function double_precision_values(self) result(tensor_values)
+ implicit none
+ class(tensor_t(double_precision)), intent(in) :: self
+ double precision, allocatable :: tensor_values(:)
+ end function
+
+ pure module function default_real_num_components(self) result(n)
+ implicit none
+ class(tensor_t), intent(in) :: self
+ integer n
+ end function
+
+ pure module function double_precision_num_components(self) result(n)
+ implicit none
+ class(tensor_t(double_precision)), intent(in) :: self
+ integer n
+ end function
+
+ end interface
+
+end module tensor_m
+
+submodule(tensor_m) tensor_s
+contains
+
+ pure module function construct_default_real(values) result(tensor)
+ implicit none
+ real, intent(in) :: values(:)
+ type(tensor_t) tensor
+ tensor = tensor_t ()(values)
+ end function
+
+ pure module function construct_double_precision(values) result(tensor)
+ implicit none
+ double precision, intent(in) :: values(:)
+ type(tensor_t(double_precision)) tensor
+ tensor = tensor_t (double_precision)(values)
+ end function
+
+ pure module function default_real_values(self) result(tensor_values)
+ implicit none
+ class(tensor_t), intent(in) :: self
+ real, allocatable :: tensor_values(:)
+ tensor_values = self%values_
+ end function
+
+ pure module function double_precision_values(self) result(tensor_values)
+ implicit none
+ class(tensor_t(double_precision)), intent(in) :: self
+ double precision, allocatable :: tensor_values(:)
+ tensor_values = self%values_
+ end function
+
+
+ pure module function default_real_num_components(self) result(n)
+ implicit none
+ class(tensor_t), intent(in) :: self
+ integer n
+ n = default_real
+ end function
+
+ pure module function double_precision_num_components(self) result(n)
+ implicit none
+ class(tensor_t(double_precision)), intent(in) :: self
+ integer n
+ n = double_precision
+ end function
+
+end submodule tensor_s
+
+
+ use tensor_m
+ type(tensor_t(kind(0e0))) :: a
+ type(tensor_t(kind(0D0))) :: b
+ a = tensor_t ([1e0,2e0])
+ print *, a%num_components (), a%values ()
+ b = tensor_t ([3d0,4d0])
+ print *, b%num_components (), b%values ()
+end
+! { dg-final { scan-tree-dump-times "construct_" 4 "original" } }
+! { dg-final { scan-tree-dump-times "_components" 4 "original" } }
+! { dg-final { scan-tree-dump-times "_values" 4 "original" } }
diff --git a/gcc/tree-scalar-evolution.cc b/gcc/tree-scalar-evolution.cc
index 7907893..9f82abc 100644
--- a/gcc/tree-scalar-evolution.cc
+++ b/gcc/tree-scalar-evolution.cc
@@ -3995,11 +3995,17 @@ final_value_replacement_loop (class loop *loop)
{
gimple *use_stmt;
imm_use_iterator imm_iter;
+ auto_vec<gimple *, 4> to_fold;
FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter, rslt)
+ if (!stmt_can_throw_internal (cfun, use_stmt))
+ to_fold.safe_push (use_stmt);
+ /* Delay folding until after the immediate use walk is completed
+ as we have an active ranger and that might walk immediate
+ uses of rslt again. See PR122502. */
+ for (gimple *use_stmt : to_fold)
{
gimple_stmt_iterator gsi = gsi_for_stmt (use_stmt);
- if (!stmt_can_throw_internal (cfun, use_stmt)
- && fold_stmt (&gsi, follow_all_ssa_edges))
+ if (fold_stmt (&gsi, follow_all_ssa_edges))
update_stmt (gsi_stmt (gsi));
}
}