https://gcc.gnu.org/bugzilla/show_bug.cgi?id=124135

--- Comment #21 from GCC Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Jakub Jelinek <[email protected]>:

https://gcc.gnu.org/g:46520c0d388611586452cce8843d0d466eb4bb10

commit r16-7924-g46520c0d388611586452cce8843d0d466eb4bb10
Author: Jakub Jelinek <[email protected]>
Date:   Fri Mar 6 10:32:00 2026 +0100

    tree-inline: Fix up ICE on !is_gimple_reg is_gimple_reg_type copying
[PR124135]

    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).

    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.

Reply via email to