On Fri, 6 Mar 2026, Jakub Jelinek wrote:
> Hi!
>
> The first testcase below ICEs e.g. with -O2 on s390x-linux, the
> second with -O2 -m32 on x86_64-linux. We have
> <bb 2> [local count: 1073741824]:
> if (x_4(D) != 0)
> goto <bb 3>; [33.00%]
> else
> goto <bb 4>; [67.00%]
>
> <bb 3> [local count: 354334800]:
> _7 = qux (42);
> foo (0, &<retval>, _7);
>
> <bb 4> [local count: 1073741824]:
> return <retval>;
> on a target where <retval> has gimple reg type but is
> aggregate_value_p and TREE_ADDRESSABLE too.
> fnsplit splits this into
> <bb 2> [local count: 354334800]:
> _1 = qux (42);
> foo (0, &<retval>, _1);
>
> <bb 3> [local count: 354334800]:
> return <retval>;
> in the *.part.0 function and
> if (x_4(D) != 0)
> goto <bb 3>; [33.00%]
> else
> goto <bb 4>; [67.00%]
>
> <bb 3> [local count: 354334800]:
> <retval> = _Z3bari.part.0 ();
>
> <bb 4> [local count: 1073741824]:
> return <retval>;
> in the original function. Now, dunno if already that isn't
> invalid because <retval> has TREE_ADDRESSABLE set in the latter, but
> at least it is accepted by tree-cfg.cc verification.
> tree lhs = gimple_call_lhs (stmt);
> if (lhs
> && (!is_gimple_reg (lhs)
> && (!is_gimple_lvalue (lhs)
> || verify_types_in_gimple_reference
> (TREE_CODE (lhs) == WITH_SIZE_EXPR
> ? TREE_OPERAND (lhs, 0) : lhs, true))))
> {
> error ("invalid LHS in gimple call");
> return true;
> }
> While lhs is not is_gimple_reg, it is is_gimple_lvalue here.
> Now, inlining of the *.part.0 fn back into the original results
> in
> <retval> = a;
> statement which already is diagnosed by verify_gimple_assign_single:
> case VAR_DECL:
> case PARM_DECL:
> if (!is_gimple_reg (lhs)
> && !is_gimple_reg (rhs1)
> && is_gimple_reg_type (TREE_TYPE (lhs)))
> {
> error ("invalid RHS for gimple memory store: %qs", code_name);
> debug_generic_stmt (lhs);
> debug_generic_stmt (rhs1);
> return true;
> }
> __float128/long double are is_gimple_reg_type, but both operands
> aren't is_gimple_reg.
>
> The following patch fixes it by doing separate load and store, i.e.
> _42 = a;
> <retval> = 42;
> in this case. If we want to change verify_gimple_assign to disallow
> !is_gimple_reg (lhs) for is_gimple_reg_type (TREE_TYPE (lhs)), we'd
> need to change fnsplit instead, but I'd be afraid such a change would
> be more stage1 material (and certainly nothing that should be
> even backported to release branches).
I think we want to do this for consistency, can you open a bugreport
tracking this issue?
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
OK.
Richard.
> 2026-03-05 Jakub Jelinek <[email protected]>
>
> PR tree-optimization/124135
> * tree-inline.cc (expand_call_inline): If both gimple_call_lhs (stmt)
> and use_retvar aren't gimple regs but have gimple reg type, use
> separate load of use_retva into SSA_NAME and then store of it
> into gimple_call_lhs (stmt).
>
> * g++.dg/torture/pr124135-1.C: New test.
> * g++.dg/torture/pr124135-2.C: New test.
>
> --- gcc/tree-inline.cc.jj 2026-02-17 15:56:32.000000000 +0100
> +++ gcc/tree-inline.cc 2026-03-05 18:39:59.590916480 +0100
> @@ -5336,7 +5336,20 @@ expand_call_inline (basic_block bb, gimp
> if (use_retvar && gimple_call_lhs (stmt))
> {
> gimple *old_stmt = stmt;
> - stmt = gimple_build_assign (gimple_call_lhs (stmt), use_retvar);
> + tree lhs = gimple_call_lhs (stmt);
> + if (!is_gimple_reg (lhs)
> + && !is_gimple_reg (use_retvar)
> + && is_gimple_reg_type (TREE_TYPE (lhs)))
> + {
> + /* If both lhs and use_retvar aren't gimple regs, yet have
> + gimple reg type, copy through a temporary SSA_NAME. */
> + gimple *g = gimple_build_assign (make_ssa_name (TREE_TYPE (lhs)),
> + use_retvar);
> + gimple_set_location (g, gimple_location (old_stmt));
> + gsi_insert_before (&stmt_gsi, g, GSI_SAME_STMT);
> + use_retvar = gimple_assign_lhs (g);
> + }
> + stmt = gimple_build_assign (lhs, use_retvar);
> gimple_set_location (stmt, gimple_location (old_stmt));
> gsi_replace (&stmt_gsi, stmt, false);
> maybe_clean_or_replace_eh_stmt (old_stmt, stmt);
> --- gcc/testsuite/g++.dg/torture/pr124135-1.C.jj 2026-03-05
> 18:44:28.110424486 +0100
> +++ gcc/testsuite/g++.dg/torture/pr124135-1.C 2026-03-05 18:44:54.106989715
> +0100
> @@ -0,0 +1,20 @@
> +// PR tree-optimization/124135
> +// { dg-do compile }
> +
> +void foo (char, long double *, int);
> +int qux (int);
> +
> +long double
> +bar (int x)
> +{
> + long double a;
> + if (x)
> + foo (0, &a, qux (42));
> + return a;
> +}
> +
> +void
> +baz (int x)
> +{
> + bar (x);
> +}
> --- gcc/testsuite/g++.dg/torture/pr124135-2.C.jj 2026-03-05
> 18:45:43.132169811 +0100
> +++ gcc/testsuite/g++.dg/torture/pr124135-2.C 2026-03-05 18:46:23.855488751
> +0100
> @@ -0,0 +1,27 @@
> +// PR tree-optimization/124135
> +// { dg-do compile }
> +
> +#ifdef __SIZEOF_FLOAT128__
> +void foo (char, __float128 *, int);
> +int qux (int);
> +
> +__float128
> +bar (int x)
> +{
> + __float128 a;
> + if (x)
> + foo (0, &a, qux (42));
> + return a;
> +}
> +
> +void
> +baz (int x)
> +{
> + bar (x);
> +}
> +#else
> +void
> +baz ()
> +{
> +}
> +#endif
>
> Jakub
>
>
--
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Jochen Jaser, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)