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;
+}

Reply via email to