]> git.ipfire.org Git - thirdparty/gcc.git/commit
PR middle-end/118608: Fix lack of sign extension on MIPS64 with -Os
authorRoger Sayle <roger@nextmovesoftware.com>
Tue, 3 Feb 2026 17:43:59 +0000 (17:43 +0000)
committerRoger Sayle <roger@nextmovesoftware.com>
Tue, 3 Feb 2026 17:48:06 +0000 (17:48 +0000)
commita9e48eca3a6eef2348c2827ed67b9cbb3f5f82ce
treec90df108f1afa473a643daab7ec4b36b0e775c6d
parenta70bdd86984c0b6cd8520e30ec713e3101c5d45f
PR middle-end/118608: Fix lack of sign extension on MIPS64 with -Os

Here is a refreshed version of my patch from February 2025, for resolving
PR middle-end/118608, a wrong code on valid regression where the middle-end
is failing to keep values suitably sign-extended (MIPS64 is a rare
targetm.mode_rep_extended target, as well as being BYTES_BIG_ENDIAN).

This fix requires three independent tweaks, one in each source file.
The first tweak is that the logic in my triggering patch for determining
whether store_field updates the most significant bit needs to be updated
to handle BYTES_BIG_ENDIAN.  Of the two insertions in the bugzilla test
case, we were generating the sign extension after the wrong one.
The second tweak was that this explicit sign-extension was then being
eliminated during combine by simplify-rtx that believed the explicit
TRUNCATE wasn't required.  This patch updates truncated_to_mode to
understand that on mode_rep_extended targets, TRUNCATE is used instead
of SUBREG because it isn't a no-op.  Finally, the third tweak is
that the MIPS backend requires a small change to recognize (and split)
*extenddi_truncatesi when TARGET_64BIT and !ISA_HAS_EXTS.

On mips64-elf with -mabi=64 the following are now generated for prepareNeedle:

-O2
        sll     $5,$5,16
        jr      $31
        or      $2,$5,$4

-Os
        dsll    $5,$5,16
        or      $2,$4,$5
        dsll    $2,$2,32
        jr      $31
        dsra    $2,$2,32

-O2 -march=octeon2
        move    $2,$0
        ins     $2,$5,16,16
        jr      $31
        ins     $2,$4,0,16

-Os -march=octeon2
        move    $2,$0
        dins    $2,$4,0,16
        dins    $2,$5,16,16
        jr      $31
        sll     $2,$2,0

Many thanks to Mateusz Marciniec and Jeff Law for additional testing.

gcc/ChangeLog
PR middle-end/118608
* expr.cc (store_field_updates_msb_p): New helper function that
now also handles BYTES_BIG_ENDIAN targets.
(expand_assignment): Use the above function when deciding to emit
a required sign/zero extension.
* rtlanal.cc (truncated_to_mode): Call targetm.mode_rep_extended
to check whether an explicit TRUNCATE is required (i.e. performs
an extension) on this target.
* config/mips/mips.md (*extenddi_truncate<mode>): Handle all
SUBDI modes, not just SHORT modes.

gcc/testsuite/ChangeLog
PR middle-end/118608
* gcc.target/mips/pr118608-1.c: New test case.
* gcc.target/mips/pr118608-2.c: Likewise.
* gcc.target/mips/pr118608-3.c: Likewise.
* gcc.target/mips/pr118608-4.c: Likewise.
gcc/config/mips/mips.md
gcc/expr.cc
gcc/rtlanal.cc
gcc/testsuite/gcc.target/mips/pr118608-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/pr118608-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/pr118608-3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/pr118608-4.c [new file with mode: 0644]