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

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

https://gcc.gnu.org/g:20a4465989b7de0e44491d59f10b29812f2bb88c

commit r17-3651-g20a4465989b7de0e44491d59f10b29812f2bb88c
Author: Dimitar Dimitrov <[email protected]>
Date:   Mon Jun 15 23:02:12 2026 +0300

    i386: Reject 16-bit modes for SSE1 registers [PR125746]

    16-bit modes are not supported by SSE registers without SSE2.
    When asm register variable is declared with such mode, register
    allocation fails with an ICE:

      pr104974.c:5:1: internal compiler error: in gen_rtx_SUBREG, at
emit-rtl.cc:1047
      ...
      0xe4aad9 emit_spill_move
              /home/mjires/git/GCC/master/gcc/lra-constraints.cc:1373

    Here LRA attempts to create a paradoxical subreg for a spill move:
       (subreg:SI (reg/v:HI 21 xmm1))

    Before the tightened checks  in r16-718-geb2ea476db2182, this
    paradoxical subreg was valid.  But when the checks were tightened,
    REG_CAN_CHANGE_MODE_P started being called to ensure the hardware
    register can change from the inner subreg mode to the outer subreg mode.
    In this case - HI and SI modes, which is rejected by
    ix86_can_change_mode_class.

    Thus the subreg generated by LRA was declared invalid, resulting in ICE.

    Fix by modifying ix86_hard_regno_mode_ok to start rejecting 16-bit modes
    as invalid for SSE hardware registers when SSE2 is not available.  There
    are no functional changes if SSE2 is enabled.

    This change is mostly not affecting code generation.  I built ffmpeg
    with and without this patch, with  "-msse -mno-sse2" options for GCC,
    and in some rare occasions LRA resulted in different register
    allocations.  This seems to be caused by targetm.modes_tieable_p,
    which calls the function patched with this fix: ix86_hard_regno_mode_ok.
    I'm not sufficiently familiar with x86 to judge whether the difference
    in code generation is a performance regression.

    Boostrapped and regtested x86_64-pc-linux-gnu for C and C++.

    I ran coremark with "-msse -mno-sse2 -O3", and I did not detect
    performance regression.

            PR target/125746

    gcc/ChangeLog:

            * config/i386/i386.cc (ix86_hard_regno_mode_ok): For SSEv1,
            reject 16-bit modes.

    gcc/testsuite/ChangeLog:

            * gcc.target/i386/pr125746.c: New test.

    Signed-off-by: Dimitar Dimitrov <[email protected]>

Reply via email to