aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog28
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/config/i386/i386-expand.cc44
-rw-r--r--gcc/config/i386/i386.cc51
-rw-r--r--gcc/config/mips/mips.cc3
-rw-r--r--gcc/config/riscv/vector.md22
-rw-r--r--gcc/cp/ChangeLog19
-rw-r--r--gcc/cp/constexpr.cc63
-rw-r--r--gcc/cp/init.cc4
-rw-r--r--gcc/except.cc9
-rw-r--r--gcc/testsuite/ChangeLog28
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/constexpr-new24.C4
-rw-r--r--gcc/testsuite/g++.dg/eh/pr119507.C19
-rw-r--r--gcc/testsuite/gcc.dg/memcpy-4.c7
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-cse-2.c2
-rw-r--r--gcc/testsuite/gcc.target/i386/recip-vec-divf-fma.c12
-rw-r--r--gcc/testsuite/gcc.target/mips/clear-cache-1.c2
-rw-r--r--gcc/testsuite/gcc.target/mips/memcpy-2.c12
-rw-r--r--gcc/testsuite/gcc.target/powerpc/power11-3.c1
-rw-r--r--gcc/vec.h8
-rw-r--r--libgcobol/ChangeLog7
-rw-r--r--libgcobol/config.h.in3
-rwxr-xr-xlibgcobol/configure74
-rw-r--r--libgcobol/configure.ac3
-rw-r--r--libgcobol/intrinsic.cc2
25 files changed, 343 insertions, 86 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 4a2a79f..5b54c5a 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,31 @@
+2025-04-21 Jan Hubicka <hubicka@ucw.cz>
+
+ PR target/119879
+ * config/i386/i386.cc (fp_conversion_stmt_cost): Inline to ...
+ (ix86_vector_costs::add_stmt_cost): ... here; fix handling of NOP_EXPR.
+
+2025-04-21 Matthew Fortune <matthew.fortune@imgtec.com>
+
+ * config/mips/mips.cc (mips_option_override): Error out for
+ -mmicromips -mmsa.
+
+2025-04-21 Andrew Pinski <quic_apinski@quicinc.com>
+
+ PR middle-end/119507
+ * except.cc (switch_to_exception_section): Don't use the cached section if
+ the current function is in comdat.
+
+2025-04-21 Andrew Pinski <quic_apinski@quicinc.com>
+
+ * vec.h (array_slice::begin): Assert that the
+ slice is valid.
+ (array_slice::end): Likewise.
+
+2025-04-21 hongtao.liu <hongtao.liu@intel.com>
+
+ * config/i386/i386-expand.cc (ix86_emit_swdivsf): Generate 2
+ FMA instructions when TARGET_FMA.
+
2025-04-19 Jeff Law <jlaw@ventanamicro.com>
PR target/119865
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index 2aaf995..fa0255d 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20250421
+20250422
diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc
index cdfd94d..36f71eb 100644
--- a/gcc/config/i386/i386-expand.cc
+++ b/gcc/config/i386/i386-expand.cc
@@ -19256,8 +19256,6 @@ ix86_emit_swdivsf (rtx res, rtx a, rtx b, machine_mode mode)
e1 = gen_reg_rtx (mode);
x1 = gen_reg_rtx (mode);
- /* a / b = a * ((rcp(b) + rcp(b)) - (b * rcp(b) * rcp (b))) */
-
b = force_reg (mode, b);
/* x0 = rcp(b) estimate */
@@ -19270,20 +19268,42 @@ ix86_emit_swdivsf (rtx res, rtx a, rtx b, machine_mode mode)
emit_insn (gen_rtx_SET (x0, gen_rtx_UNSPEC (mode, gen_rtvec (1, b),
UNSPEC_RCP)));
- /* e0 = x0 * b */
- emit_insn (gen_rtx_SET (e0, gen_rtx_MULT (mode, x0, b)));
+ unsigned vector_size = GET_MODE_SIZE (mode);
+
+ /* (a - (rcp(b) * a * b)) * rcp(b) + rcp(b) * a
+ N-R step with 2 fma implementation. */
+ if (TARGET_FMA
+ || (TARGET_AVX512F && vector_size == 64)
+ || (TARGET_AVX512VL && (vector_size == 32 || vector_size == 16)))
+ {
+ /* e0 = x0 * a */
+ emit_insn (gen_rtx_SET (e0, gen_rtx_MULT (mode, x0, a)));
+ /* e1 = e0 * b - a */
+ emit_insn (gen_rtx_SET (e1, gen_rtx_FMA (mode, e0, b,
+ gen_rtx_NEG (mode, a))));
+ /* res = - e1 * x0 + e0 */
+ emit_insn (gen_rtx_SET (res, gen_rtx_FMA (mode,
+ gen_rtx_NEG (mode, e1),
+ x0, e0)));
+ }
+ else
+ /* a / b = a * ((rcp(b) + rcp(b)) - (b * rcp(b) * rcp (b))) */
+ {
+ /* e0 = x0 * b */
+ emit_insn (gen_rtx_SET (e0, gen_rtx_MULT (mode, x0, b)));
- /* e0 = x0 * e0 */
- emit_insn (gen_rtx_SET (e0, gen_rtx_MULT (mode, x0, e0)));
+ /* e1 = x0 + x0 */
+ emit_insn (gen_rtx_SET (e1, gen_rtx_PLUS (mode, x0, x0)));
- /* e1 = x0 + x0 */
- emit_insn (gen_rtx_SET (e1, gen_rtx_PLUS (mode, x0, x0)));
+ /* e0 = x0 * e0 */
+ emit_insn (gen_rtx_SET (e0, gen_rtx_MULT (mode, x0, e0)));
- /* x1 = e1 - e0 */
- emit_insn (gen_rtx_SET (x1, gen_rtx_MINUS (mode, e1, e0)));
+ /* x1 = e1 - e0 */
+ emit_insn (gen_rtx_SET (x1, gen_rtx_MINUS (mode, e1, e0)));
- /* res = a * x1 */
- emit_insn (gen_rtx_SET (res, gen_rtx_MULT (mode, a, x1)));
+ /* res = a * x1 */
+ emit_insn (gen_rtx_SET (res, gen_rtx_MULT (mode, a, x1)));
+ }
}
/* Output code to perform a Newton-Rhapson approximation of a
diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index 28603c2..d15f91d 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -25257,32 +25257,6 @@ ix86_vectorize_create_costs (vec_info *vinfo, bool costing_for_scalar)
return new ix86_vector_costs (vinfo, costing_for_scalar);
}
-/* Return cost of statement doing FP conversion. */
-
-static unsigned
-fp_conversion_stmt_cost (machine_mode mode, gimple *stmt, bool scalar_p)
-{
- int outer_size
- = tree_to_uhwi
- (TYPE_SIZE
- (TREE_TYPE (gimple_assign_lhs (stmt))));
- int inner_size
- = tree_to_uhwi
- (TYPE_SIZE
- (TREE_TYPE (gimple_assign_rhs1 (stmt))));
- int stmt_cost = vec_fp_conversion_cost
- (ix86_tune_cost, GET_MODE_BITSIZE (mode));
- /* VEC_PACK_TRUNC_EXPR: If inner size is greater than outer size we will end
- up doing two conversions and packing them. */
- if (!scalar_p && inner_size > outer_size)
- {
- int n = inner_size / outer_size;
- stmt_cost = stmt_cost * n
- + (n - 1) * ix86_vec_cost (mode, ix86_cost->sse_op);
- }
- return stmt_cost;
-}
-
unsigned
ix86_vector_costs::add_stmt_cost (int count, vect_cost_for_stmt kind,
stmt_vec_info stmt_info, slp_tree node,
@@ -25394,8 +25368,8 @@ ix86_vector_costs::add_stmt_cost (int count, vect_cost_for_stmt kind,
TREE_TYPE (gimple_assign_rhs1 (stmt_info->stmt))))
stmt_cost = 0;
else if (fp)
- stmt_cost = fp_conversion_stmt_cost (mode, stmt_info->stmt,
- scalar_p);
+ stmt_cost = vec_fp_conversion_cost
+ (ix86_tune_cost, GET_MODE_BITSIZE (mode));
break;
case BIT_IOR_EXPR:
@@ -25439,7 +25413,26 @@ ix86_vector_costs::add_stmt_cost (int count, vect_cost_for_stmt kind,
if (kind == vec_promote_demote
&& fp && FLOAT_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (stmt_info->stmt))))
- stmt_cost = fp_conversion_stmt_cost (mode, stmt_info->stmt, scalar_p);
+ {
+ int outer_size
+ = tree_to_uhwi
+ (TYPE_SIZE
+ (TREE_TYPE (gimple_assign_lhs (stmt_info->stmt))));
+ int inner_size
+ = tree_to_uhwi
+ (TYPE_SIZE
+ (TREE_TYPE (gimple_assign_rhs1 (stmt_info->stmt))));
+ int stmt_cost = vec_fp_conversion_cost
+ (ix86_tune_cost, GET_MODE_BITSIZE (mode));
+ /* VEC_PACK_TRUNC_EXPR: If inner size is greater than outer size we will end
+ up doing two conversions and packing them. */
+ if (inner_size > outer_size)
+ {
+ int n = inner_size / outer_size;
+ stmt_cost = stmt_cost * n
+ + (n - 1) * ix86_vec_cost (mode, ix86_cost->sse_op);
+ }
+ }
/* If we do elementwise loads into a vector then we are bound by
latency and execution resources for the many scalar loads
diff --git a/gcc/config/mips/mips.cc b/gcc/config/mips/mips.cc
index 24a28dc..0d3d026 100644
--- a/gcc/config/mips/mips.cc
+++ b/gcc/config/mips/mips.cc
@@ -20678,6 +20678,9 @@ mips_option_override (void)
"-mcompact-branches=never");
}
+ if (is_micromips && TARGET_MSA)
+ error ("unsupported combination: %s", "-mmicromips -mmsa");
+
/* Require explicit relocs for MIPS R6 onwards. This enables simplification
of the compact branch and jump support through the backend. */
if (!TARGET_EXPLICIT_RELOCS && mips_isa_rev >= 6)
diff --git a/gcc/config/riscv/vector.md b/gcc/config/riscv/vector.md
index 51eb64f..3ab4d76 100644
--- a/gcc/config/riscv/vector.md
+++ b/gcc/config/riscv/vector.md
@@ -2136,18 +2136,34 @@
(match_operand 7 "const_int_operand")
(reg:SI VL_REGNUM)
(reg:SI VTYPE_REGNUM)] UNSPEC_VPREDICATE)
- (vec_duplicate:V_VLS
- (match_operand:<VEL> 3 "direct_broadcast_operand"))
+ ;; (vec_duplicate:V_VLS ;; wrapper activated by wrap_vec_dup below.
+ (match_operand:<VEL> 3 "direct_broadcast_operand") ;; )
(match_operand:V_VLS 2 "vector_merge_operand")))]
"TARGET_VECTOR"
{
/* Transform vmv.v.x/vfmv.v.f (avl = 1) into vmv.s.x since vmv.s.x/vfmv.s.f
has better chances to do vsetvl fusion in vsetvl pass. */
+ bool wrap_vec_dup = true;
+ rtx vec_cst = NULL_RTX;
if (riscv_vector::splat_to_scalar_move_p (operands))
{
operands[1] = riscv_vector::gen_scalar_move_mask (<VM>mode);
operands[3] = force_reg (<VEL>mode, operands[3]);
}
+ else if (immediate_operand (operands[3], <VEL>mode)
+ && (vec_cst = gen_const_vec_duplicate (<MODE>mode, operands[3]))
+ && (/* -> pred_broadcast<mode>_zero */
+ (vector_least_significant_set_mask_operand (operands[1],
+ <VM>mode)
+ && vector_const_0_operand (vec_cst, <MODE>mode))
+ || (/* pred_broadcast<mode>_imm */
+ vector_all_trues_mask_operand (operands[1], <VM>mode)
+ && vector_const_int_or_double_0_operand (vec_cst,
+ <MODE>mode))))
+ {
+ operands[3] = vec_cst;
+ wrap_vec_dup = false;
+ }
/* Handle vmv.s.x instruction (Wb1 mask) which has memory scalar. */
else if (satisfies_constraint_Wdm (operands[3]))
{
@@ -2191,6 +2207,8 @@
;
else
operands[3] = force_reg (<VEL>mode, operands[3]);
+ if (wrap_vec_dup)
+ operands[3] = gen_rtx_VEC_DUPLICATE (<MODE>mode, operands[3]);
})
(define_insn_and_split "*pred_broadcast<mode>"
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 6975efb..e85a710 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,22 @@
+2025-04-21 Jason Merrill <jason@redhat.com>
+
+ * constexpr.cc (cxx_eval_outermost_constant_expr): Move
+ verify_constant later.
+
+2025-04-21 Jason Merrill <jason@redhat.com>
+
+ PR c++/118775
+ * constexpr.cc (cxx_eval_call_expression): Add assert.
+ (fold_to_constant): Handle processing_template_decl.
+ * init.cc (build_new_1): Use fold_to_constant.
+
+2025-04-21 Jason Merrill <jason@redhat.com>
+
+ PR c++/99456
+ * constexpr.cc (cxx_eval_constant_expression): Check strict
+ instead of manifestly_const_eval.
+ (maybe_constant_init_1): Be strict for static constexpr vars.
+
2025-04-19 Jason Merrill <jason@redhat.com>
* coroutines.cc (coro_build_expr_stmt)
diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index f56c5c4..8a11e62 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -2956,12 +2956,11 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
gcc_assert (arg0);
if (new_op_p)
{
- /* FIXME: We should not get here; the VERIFY_CONSTANT above
- should have already caught it. But currently a conversion
- from pointer type to arithmetic type is only considered
- non-constant for CONVERT_EXPRs, not NOP_EXPRs. */
if (!tree_fits_uhwi_p (arg0))
{
+ /* We should not get here; the VERIFY_CONSTANT above
+ should have already caught it. */
+ gcc_checking_assert (false);
if (!ctx->quiet)
error_at (loc, "cannot allocate array: size not constant");
*non_constant_p = true;
@@ -8479,7 +8478,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
if (TREE_CODE (t) == CONVERT_EXPR
&& ARITHMETIC_TYPE_P (type)
&& INDIRECT_TYPE_P (TREE_TYPE (op))
- && ctx->manifestly_const_eval == mce_true)
+ && ctx->strict)
{
if (!ctx->quiet)
error_at (loc,
@@ -9228,11 +9227,6 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
if (r == void_node && !constexpr_dtor && ctx.ctor)
r = ctx.ctor;
- if (!constexpr_dtor)
- verify_constant (r, allow_non_constant, &non_constant_p, &overflow_p);
- else
- DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (object) = true;
-
unsigned int i;
tree cleanup;
/* Evaluate the cleanups. */
@@ -9251,15 +9245,6 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
non_constant_p = true;
}
- if (TREE_CODE (r) == CONSTRUCTOR && CONSTRUCTOR_NO_CLEARING (r))
- {
- if (!allow_non_constant)
- error ("%qE is not a constant expression because it refers to "
- "an incompletely initialized variable", t);
- TREE_CONSTANT (r) = false;
- non_constant_p = true;
- }
-
if (!non_constant_p && cxx_dialect >= cxx20
&& !global_ctx.heap_vars.is_empty ())
{
@@ -9316,6 +9301,21 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
non_constant_p = true;
}
+ if (!non_constant_p && !constexpr_dtor)
+ verify_constant (r, allow_non_constant, &non_constant_p, &overflow_p);
+
+ /* After verify_constant because reduced_constant_expression_p can unset
+ CONSTRUCTOR_NO_CLEARING. */
+ if (!non_constant_p
+ && TREE_CODE (r) == CONSTRUCTOR && CONSTRUCTOR_NO_CLEARING (r))
+ {
+ if (!allow_non_constant)
+ error ("%qE is not a constant expression because it refers to "
+ "an incompletely initialized variable", t);
+ TREE_CONSTANT (r) = false;
+ non_constant_p = true;
+ }
+
if (non_constant_p)
/* If we saw something bad, go back to our argument. The wrapping below is
only for the cases of TREE_CONSTANT argument or overflow. */
@@ -9332,13 +9332,17 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
if (non_constant_p && !allow_non_constant)
return error_mark_node;
- else if (constexpr_dtor)
- return r;
else if (non_constant_p && TREE_CONSTANT (r))
r = mark_non_constant (r);
else if (non_constant_p)
return t;
+ if (constexpr_dtor)
+ {
+ DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (object) = true;
+ return r;
+ }
+
/* Check we are not trying to return the wrong type. */
if (!same_type_ignoring_top_level_qualifiers_p (type, TREE_TYPE (r)))
{
@@ -9490,6 +9494,9 @@ fold_simple (tree t)
tree
fold_to_constant (tree t)
{
+ if (processing_template_decl)
+ return t;
+
tree r = fold (t);
if (CONSTANT_CLASS_P (r) && !TREE_OVERFLOW (r))
return r;
@@ -9747,16 +9754,26 @@ maybe_constant_init_1 (tree t, tree decl, bool allow_non_constant,
{
/* [basic.start.static] allows constant-initialization of variables with
static or thread storage duration even if it isn't required, but we
- shouldn't bend the rules the same way for automatic variables. */
+ shouldn't bend the rules the same way for automatic variables.
+
+ But still enforce the requirements of constexpr/constinit.
+ [dcl.constinit] "If a variable declared with the constinit specifier
+ has dynamic initialization, the program is ill-formed, even if the
+ implementation would perform that initialization as a static
+ initialization." */
bool is_static = (decl && DECL_P (decl)
&& (TREE_STATIC (decl) || DECL_EXTERNAL (decl)));
+ bool strict = (!is_static
+ || (decl && DECL_P (decl)
+ && (DECL_DECLARED_CONSTEXPR_P (decl)
+ || DECL_DECLARED_CONSTINIT_P (decl))));
if (is_static)
manifestly_const_eval = mce_true;
if (cp_unevaluated_operand && manifestly_const_eval != mce_true)
return fold_to_constant (t);
- t = cxx_eval_outermost_constant_expr (t, allow_non_constant, !is_static,
+ t = cxx_eval_outermost_constant_expr (t, allow_non_constant, strict,
manifestly_const_eval,
false, decl);
}
diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc
index e589e45..062a493 100644
--- a/gcc/cp/init.cc
+++ b/gcc/cp/init.cc
@@ -3405,7 +3405,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
errval = throw_bad_array_new_length ();
if (outer_nelts_check != NULL_TREE)
size = build3 (COND_EXPR, sizetype, outer_nelts_check, size, errval);
- size = cp_fully_fold (size);
+ size = fold_to_constant (size);
/* Create the argument list. */
vec_safe_insert (*placement, 0, size);
/* Do name-lookup to find the appropriate operator. */
@@ -3462,7 +3462,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
outer_nelts_check = NULL_TREE;
}
- size = cp_fully_fold (size);
+ size = fold_to_constant (size);
/* If size is zero e.g. due to type having zero size, try to
preserve outer_nelts for constant expression evaluation
purposes. */
diff --git a/gcc/except.cc b/gcc/except.cc
index 205811c..0fe1e09 100644
--- a/gcc/except.cc
+++ b/gcc/except.cc
@@ -2949,7 +2949,14 @@ switch_to_exception_section (const char * ARG_UNUSED (fnname))
{
section *s;
- if (exception_section)
+ if (exception_section
+ /* Don't use the cached section for comdat if it will be different. */
+#ifdef HAVE_LD_EH_GC_SECTIONS
+ && !(targetm_common.have_named_sections
+ && DECL_COMDAT_GROUP (current_function_decl)
+ && HAVE_COMDAT_GROUP)
+#endif
+ )
s = exception_section;
else
{
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 521176a..4c219bd 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,31 @@
+2025-04-21 Jason Merrill <jason@redhat.com>
+
+ PR c++/118775
+ * g++.dg/cpp2a/constexpr-new24.C: Adjust diagnostic.
+
+2025-04-21 Andrew Bennett <andrew.bennett@imgtec.com>
+
+ * gcc.dg/memcpy-4.c: Remove mips specific code.
+ * gcc.target/mips/memcpy-2.c: New test.
+
+2025-04-21 Matthew Fortune <matthew.fortune@imgtec.com>
+
+ * gcc.target/mips/clear-cache-1.c: Also allow jrc.
+
+2025-04-21 Matthew Fortune <matthew.fortune@imgtec.com>
+
+ * gcc.dg/tree-ssa/ssa-dom-cse-2.c: Do not check output for
+ MIPS lp64 abi.
+
+2025-04-21 Andrew Pinski <quic_apinski@quicinc.com>
+
+ PR middle-end/119507
+ * g++.dg/eh/pr119507.C: New test.
+
+2025-04-21 hongtao.liu <hongtao.liu@intel.com>
+
+ * gcc.target/i386/recip-vec-divf-fma.c: New test.
+
2025-04-20 H.J. Lu <hjl.tools@gmail.com>
PR target/117863
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-new24.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-new24.C
index ee62f18..17c9f54 100644
--- a/gcc/testsuite/g++.dg/cpp2a/constexpr-new24.C
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-new24.C
@@ -6,14 +6,14 @@ int a;
constexpr char *
f1 ()
{
- constexpr auto p = new char[(long int) &a]; // { dg-error "size not constant" }
+ constexpr auto p = new char[(long int) &a]; // { dg-error "conversion from pointer" }
return p;
}
constexpr char *
f2 ()
{
- auto p = new char[(long int) &a]; // { dg-error "size not constant" }
+ auto p = new char[(long int) &a]; // { dg-error "conversion from pointer" }
return p;
}
diff --git a/gcc/testsuite/g++.dg/eh/pr119507.C b/gcc/testsuite/g++.dg/eh/pr119507.C
new file mode 100644
index 0000000..c68536f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/eh/pr119507.C
@@ -0,0 +1,19 @@
+// { dg-do compile { target comdat_group } }
+// ARM EABI has its own exception handling data handling and does not use gcc_except_table
+// { dg-skip-if "!TARGET_EXCEPTION_DATA" { arm_eabi } }
+// Force off function sections
+// Force on exceptions
+// { dg-options "-fno-function-sections -fexceptions" }
+// PR middle-end/119507
+
+
+inline int comdat() { try { throw 1; } catch (int) { return 1; } return 0; }
+int another_func_with_exception() { try { throw 1; } catch (int) { return 1; } return 0; }
+inline int comdat1() { try { throw 1; } catch (int) { return 1; } return 0; }
+int foo() { return comdat() + comdat1(); }
+
+// Make sure the gcc puts the exception table for both comdat and comdat1 in their own section
+// { dg-final { scan-assembler-times ".section\[\t \]\[^\n\]*.gcc_except_table._Z6comdatv" 1 } }
+// { dg-final { scan-assembler-times ".section\[\t \]\[^\n\]*.gcc_except_table._Z7comdat1v" 1 } }
+// There should be 3 exception tables,
+// { dg-final { scan-assembler-times ".section\[\t \]\[^\n\]*.gcc_except_table" 3 } }
diff --git a/gcc/testsuite/gcc.dg/memcpy-4.c b/gcc/testsuite/gcc.dg/memcpy-4.c
index 4c726f0..b17b369 100644
--- a/gcc/testsuite/gcc.dg/memcpy-4.c
+++ b/gcc/testsuite/gcc.dg/memcpy-4.c
@@ -1,13 +1,8 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-rtl-expand" } */
+/* { dg-options "-O2" } */
-#ifdef __mips
-__attribute__((nomips16))
-#endif
void
f1 (char *p)
{
__builtin_memcpy (p, "12345", 5);
}
-
-/* { dg-final { scan-rtl-dump "mem/u.*mem/u" "expand" { target mips*-*-* } } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-cse-2.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-cse-2.c
index a879d30..6fa52f6 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-cse-2.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-cse-2.c
@@ -27,4 +27,4 @@ foo ()
but the loop reads only one element at a time, and DOM cannot resolve these.
The same happens on powerpc depending on the SIMD support available. */
-/* { dg-final { scan-tree-dump "return 28;" "optimized" { xfail { { alpha*-*-* hppa*64*-*-* nvptx*-*-* mmix-knuth-mmixware } || { { { lp64 && { powerpc*-*-* sparc*-*-* riscv*-*-* } } || aarch64_sve } || { arm*-*-* && { ! arm_neon } } } } } } } */
+/* { dg-final { scan-tree-dump "return 28;" "optimized" { xfail { { alpha*-*-* hppa*64*-*-* nvptx*-*-* mmix-knuth-mmixware } || { { { lp64 && { mips*-*-* powerpc*-*-* sparc*-*-* riscv*-*-* } } || aarch64_sve } || { arm*-*-* && { ! arm_neon } } } } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/recip-vec-divf-fma.c b/gcc/testsuite/gcc.target/i386/recip-vec-divf-fma.c
new file mode 100644
index 0000000..ad9e07b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/recip-vec-divf-fma.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-Ofast -mfma -mavx2" } */
+/* { dg-final { scan-assembler-times {(?n)vfn?m(add|sub)[1-3]*ps} 2 } } */
+
+typedef float v4sf __attribute__((vector_size(16)));
+/* (a - (rcp(b) * a * b)) * rcp(b) + rcp(b) * a */
+
+v4sf
+foo (v4sf a, v4sf b)
+{
+ return a / b;
+}
diff --git a/gcc/testsuite/gcc.target/mips/clear-cache-1.c b/gcc/testsuite/gcc.target/mips/clear-cache-1.c
index f1554f5..cd11c66 100644
--- a/gcc/testsuite/gcc.target/mips/clear-cache-1.c
+++ b/gcc/testsuite/gcc.target/mips/clear-cache-1.c
@@ -1,7 +1,7 @@
/* { dg-do compile } */
/* { dg-options "-msynci isa_rev>=2" } */
/* { dg-final { scan-assembler "\tsynci\t" } } */
-/* { dg-final { scan-assembler "\tjr.hb\t" } } */
+/* { dg-final { scan-assembler "\tjrc?.hb\t" } } */
/* { dg-final { scan-assembler-not "_flush_cache|mips_sync_icache|_cacheflush" } } */
NOMIPS16 void f()
diff --git a/gcc/testsuite/gcc.target/mips/memcpy-2.c b/gcc/testsuite/gcc.target/mips/memcpy-2.c
new file mode 100644
index 0000000..df0cd18
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/memcpy-2.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "isa_rev<=5 -fdump-rtl-expand" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-Os" } { "" } } */
+
+__attribute__((nomips16))
+void
+f1 (char *p)
+{
+ __builtin_memcpy (p, "12345", 5);
+}
+
+/* { dg-final { scan-rtl-dump "mem/u.*mem/u" "expand" } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/power11-3.c b/gcc/testsuite/gcc.target/powerpc/power11-3.c
index fa1aedd..56bf881 100644
--- a/gcc/testsuite/gcc.target/powerpc/power11-3.c
+++ b/gcc/testsuite/gcc.target/powerpc/power11-3.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-mdejagnu-cpu=power8 -O2" } */
+/* { dg-require-ifunc "" } */
/* Check if we can set the power11 target via a target_clones attribute. */
diff --git a/gcc/vec.h b/gcc/vec.h
index 915df06..eae4b0f 100644
--- a/gcc/vec.h
+++ b/gcc/vec.h
@@ -2395,11 +2395,11 @@ public:
array_slice (vec<OtherT, A, vl_embed> *v)
: m_base (v ? v->address () : nullptr), m_size (v ? v->length () : 0) {}
- iterator begin () { return m_base; }
- iterator end () { return m_base + m_size; }
+ iterator begin () { gcc_checking_assert (is_valid ()); return m_base; }
+ iterator end () { gcc_checking_assert (is_valid ()); return m_base + m_size; }
- const_iterator begin () const { return m_base; }
- const_iterator end () const { return m_base + m_size; }
+ const_iterator begin () const { gcc_checking_assert (is_valid ()); return m_base; }
+ const_iterator end () const { gcc_checking_assert (is_valid ()); return m_base + m_size; }
value_type &front ();
value_type &back ();
diff --git a/libgcobol/ChangeLog b/libgcobol/ChangeLog
index 6a0e961..9de1714 100644
--- a/libgcobol/ChangeLog
+++ b/libgcobol/ChangeLog
@@ -1,3 +1,10 @@
+2025-04-21 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * configure.ac: Check for struct tm.tm_zone.
+ * configure, config.h.in: Regenerate.
+ * intrinsic.cc (__gg__formatted_current_date): Guard tm.tm_zone
+ use with HAVE_STRUCT_TM_TM_ZONE.
+
2025-04-15 Andreas Schwab <schwab@suse.de>
* configure.tgt: Set LIBGCOBOL_SUPPORTED for riscv64-*-linux* with
diff --git a/libgcobol/config.h.in b/libgcobol/config.h.in
index 6a53279..fdf5e3e 100644
--- a/libgcobol/config.h.in
+++ b/libgcobol/config.h.in
@@ -72,6 +72,9 @@
/* Define to 1 if you have the `strtof128' function. */
#undef HAVE_STRTOF128
+/* Define to 1 if `tm_zone' is a member of `struct tm'. */
+#undef HAVE_STRUCT_TM_TM_ZONE
+
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
diff --git a/libgcobol/configure b/libgcobol/configure
index e83119d..6821591 100755
--- a/libgcobol/configure
+++ b/libgcobol/configure
@@ -2449,6 +2449,63 @@ $as_echo "$ac_res" >&6; }
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
} # ac_fn_cxx_check_func
+
+# ac_fn_cxx_check_member LINENO AGGR MEMBER VAR INCLUDES
+# ------------------------------------------------------
+# Tries to find if the field MEMBER exists in type AGGR, after including
+# INCLUDES, setting cache variable VAR accordingly.
+ac_fn_cxx_check_member ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5
+$as_echo_n "checking for $2.$3... " >&6; }
+if eval \${$4+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$5
+int
+main ()
+{
+static $2 ac_aggr;
+if (ac_aggr.$3)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ eval "$4=yes"
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$5
+int
+main ()
+{
+static $2 ac_aggr;
+if (sizeof ac_aggr.$3)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ eval "$4=yes"
+else
+ eval "$4=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$4
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_cxx_check_member
cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
@@ -11693,7 +11750,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11696 "configure"
+#line 11753 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -11799,7 +11856,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11802 "configure"
+#line 11859 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -17434,6 +17491,19 @@ $as_echo "#define USE_IEC_60559 1" >>confdefs.h
+# struct tm tm_zone is a POSIX.1-2024 addition.
+ac_fn_cxx_check_member "$LINENO" "struct tm" "tm_zone" "ac_cv_member_struct_tm_tm_zone" "#include <time.h>
+"
+if test "x$ac_cv_member_struct_tm_tm_zone" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_TM_TM_ZONE 1
+_ACEOF
+
+
+fi
+
+
if test "${multilib}" = "yes"; then
multilib_arg="--enable-multilib"
else
diff --git a/libgcobol/configure.ac b/libgcobol/configure.ac
index a1e9513..4bb6905 100644
--- a/libgcobol/configure.ac
+++ b/libgcobol/configure.ac
@@ -231,6 +231,9 @@ elif test "${ENABLE_LIBQUADMATH_SUPPORT}" = "default" ; then
fi
LIBGCOBOL_CHECK_FLOAT128
+# struct tm tm_zone is a POSIX.1-2024 addition.
+AC_CHECK_MEMBERS([struct tm.tm_zone],,,[#include <time.h>])
+
if test "${multilib}" = "yes"; then
multilib_arg="--enable-multilib"
else
diff --git a/libgcobol/intrinsic.cc b/libgcobol/intrinsic.cc
index 181b053..97f2bdc 100644
--- a/libgcobol/intrinsic.cc
+++ b/libgcobol/intrinsic.cc
@@ -1482,7 +1482,9 @@ __gg__formatted_current_date( cblc_field_t *dest, // Destination string
__gg__clock_gettime(CLOCK_REALTIME, &ts);
struct tm tm = {};
+#ifdef HAVE_STRUCT_TM_TM_ZONE
tm.tm_zone = "GMT";
+#endif
if( is_zulu )
{
gmtime_r(&ts.tv_sec, &tm);