YunQiang Su <s...@gcc.gnu.org> writes:
> On TRULY_NOOP_TRUNCATION_MODES_P (DImode, SImode)) == true platforms,
> if 31 or above bits is polluted by an bitops, we will need an
> truncate. Let's emit one, and mark let's use the same hardreg
> as in and out, the RTL may like:
>
> (insn 21 20 24 2 (set (subreg/s/u:SI (reg/v:DI 200 [ val ]) 0)
>         (truncate:SI (reg/v:DI 200 [ val ]))) "../xx.c":7:29 -1
>      (nil))
>
> We use /s/u flags to mark it as really needed, as in
> combine_simplify_rtx, this insn may be considered as truncated,
> so let's skip this combination.
>
> gcc/ChangeLog:
>         PR: 104914.
>         * combine.cc (try_combine): Skip combine with truncate if
>       dest is subreg and has /u/s flags on platforms
>       TRULY_NOOP_TRUNCATION_MODES_P (DImode, SImode)) == true.
>       * expr.cc (expand_assignment): Emit a truncate insn, if
>       31+ bits is polluted for SImode.
>
> gcc/testsuite/ChangeLog:
>       PR: 104914.
>       * gcc.target/mips/pr104914.c: New testcase.

Sorry for not looking at this earlier.  I've got a bit lost in the
various threads, so apologies if this has been discussed already
but I think the fix is:

diff --git a/gcc/expr.cc b/gcc/expr.cc
index 4f42c0ff487..9847eba19fe 100644
--- a/gcc/expr.cc
+++ b/gcc/expr.cc
@@ -6275,9 +6275,8 @@ expand_assignment (tree to, tree from, bool nontemporal)
              else
                {
                  rtx to_rtx1
-                   = lowpart_subreg (subreg_unpromoted_mode (to_rtx),
-                                     SUBREG_REG (to_rtx),
-                                     subreg_promoted_mode (to_rtx));
+                   = convert_to_mode (subreg_unpromoted_mode (to_rtx),
+                                      SUBREG_REG (to_rtx), false);
                  result = store_field (to_rtx1, bitsize, bitpos,
                                        bitregion_start, bitregion_end,
                                        mode1, from, get_alias_set (to),

(completely untested apart from the test case).  That should still
produce a subreg on most targets, but generates the required trunc
on MIPS.

Thanks,
Richard

Reply via email to