On Mon, Aug 24, 2026 at 8:55 PM Dimitar Dimitrov <[email protected]> wrote: > > 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.
OK. Thanks, Uros. > > Signed-off-by: Dimitar Dimitrov <[email protected]> > --- > gcc/config/i386/i386.cc | 4 ++++ > gcc/testsuite/gcc.target/i386/pr125746.c | 10 ++++++++++ > 2 files changed, 14 insertions(+) > create mode 100644 gcc/testsuite/gcc.target/i386/pr125746.c > > diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc > index 4b5380f0b05..7cfbb6dfdf8 100644 > --- a/gcc/config/i386/i386.cc > +++ b/gcc/config/i386/i386.cc > @@ -21865,6 +21865,10 @@ ix86_hard_regno_mode_ok (unsigned int regno, > machine_mode mode) > if (EXT_REX_SSE_REGNO_P (regno)) > return false; > > + /* Without SSE2, 16-bit moves are not supported. */ > + if (!TARGET_SSE2 && GET_MODE_SIZE (mode) == GET_MODE_SIZE (HImode)) > + return false; > + > /* OImode and AVX modes are available only when AVX is enabled. */ > return ((TARGET_AVX > && VALID_AVX256_REG_OR_OI_MODE (mode)) > diff --git a/gcc/testsuite/gcc.target/i386/pr125746.c > b/gcc/testsuite/gcc.target/i386/pr125746.c > new file mode 100644 > index 00000000000..87b336dc5d6 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/i386/pr125746.c > @@ -0,0 +1,10 @@ > +/* { dg-do compile } */ > +/* { dg-options "-msse -mno-sse2" } */ > + > +void > +foo() > +{ > + register short b __asm("%xmm1") = 0; /* { dg-error "register specified for > 'b' isn't suitable for data type" } */ > + > + asm("" : "+v"(b)); > +} > -- > 2.55.0 >
