PR78458 shows a problem in LRA spilling caused by HARD_REGNO_CALLER_SAVE_MODE() returning a bogus mode (IFmode). This patch solves the problem by just returning MODE if MODE is wide enough to save and restore NREGS itself.
This patch passed bootstrap and regtesting on powerpc64le-linux as well as on powerpc64-linux (testsuite run in both 32-bit and 64-bit modes). Joseph has confirmed it fixes his ICE and gets him further in his toolchain build (now ICEs in glibc), which he has separate patches for. Joseph, I copied the testsuite preamble from another SPE test case. Does it look correct to you to catch the bug? Assuming the test case is correct, is this ok for trunk? Peter gcc/ PR target/78458 * config/rs6000/rs6000.h (HARD_REGNO_CALLER_SAVE_MODE): Return MODE if it is at least NREGS wide. gcc/testsuite/ PR target/78458 * gcc.target/powerpc/pr78458.c: New. Index: gcc/config/rs6000/rs6000.h =================================================================== --- gcc/config/rs6000/rs6000.h (revision 241976) +++ gcc/config/rs6000/rs6000.h (working copy) @@ -1279,9 +1279,11 @@ enum data_align { align_abi, align_opt, enough space to account for vectors in FP regs. However, TFmode/TDmode should not use VSX instructions to do a caller save. */ #define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS, MODE) \ - (TARGET_VSX \ - && ((MODE) == VOIDmode || ALTIVEC_OR_VSX_VECTOR_MODE (MODE)) \ - && FP_REGNO_P (REGNO) \ + (NREGS <= rs6000_hard_regno_nregs[MODE][REGNO] \ + ? MODE \ + : TARGET_VSX \ + && ((MODE) == VOIDmode || ALTIVEC_OR_VSX_VECTOR_MODE (MODE)) \ + && FP_REGNO_P (REGNO) \ ? V2DFmode \ : TARGET_E500_DOUBLE && (MODE) == SImode \ ? SImode \ Index: gcc/testsuite/gcc.target/powerpc/pr78458.c =================================================================== --- gcc/testsuite/gcc.target/powerpc/pr78458.c (revision 0) +++ gcc/testsuite/gcc.target/powerpc/pr78458.c (working copy) @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-mcpu=8548 -mspe -mabi=spe -mlra" } */ +/* { dg-skip-if "not an SPE target" { ! powerpc_spe_nocache } { "*" } { "" } } */ + +extern void bar (void); +long double +pr78458 (long double p1) +{ + bar (); + asm volatile ("# clobbers" ::: + "r14", "r15", "r16", "r17", "r18", "r19", + "r20", "r21", "r22", "r23", "r24", "r25", + "r26", "r27", "r28", "r29", "r30", "r31"); + return p1; +}