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

--- Comment #17 from Roger Sayle <roger at nextmovesoftware dot com> ---
I think this patch might resolve the problem (or move it somewhere else):

diff --git a/gcc/expr.cc b/gcc/expr.cc
index 9fef2bf6585..218bca905f5 100644
--- a/gcc/expr.cc
+++ b/gcc/expr.cc
@@ -6274,10 +6274,7 @@ expand_assignment (tree to, tree from, bool nontemporal)
                result = store_expr (from, to_rtx, 0, nontemporal, false);
              else
                {
-                 rtx to_rtx1
-                   = lowpart_subreg (subreg_unpromoted_mode (to_rtx),
-                                     SUBREG_REG (to_rtx),
-                                     subreg_promoted_mode (to_rtx));
+                 rtx to_rtx1 = gen_reg_rtx (subreg_unpromoted_mode (to_rtx));
                  result = store_field (to_rtx1, bitsize, bitpos,
                                        bitregion_start, bitregion_end,
                                        mode1, from, get_alias_set (to),

The motivation/solution comes from a comment in expmed.cc:
/* If the destination is a paradoxical subreg such that we need a
   truncate to the inner mode, perform the insertion on a temporary and
   truncate the result to the original destination.  Note that we can't
   just truncate the paradoxical subreg as (truncate:N (subreg:W (reg:N
   X) 0)) is (reg:N X).  */

The same caveat applies to extensions on MIPS, so we should use a new
pseudo temporary register rather than update the SUBREG in place.

If someone could confirm this fixes the issue on MIPS, I'll try to come up
with a milder form of this fix that checks TARGET_MODE_REP_EXTENDED that'll
limit the churn/impact on other targets.

Reply via email to