Only allow e500 double in SPE_SIMD_REGNO_P registers.
authorJoseph Myers <joseph@codesourcery.com>
Sat, 25 Oct 2014 00:23:17 +0000 (01:23 +0100)
committerJoseph Myers <jsm28@gcc.gnu.org>
Sat, 25 Oct 2014 00:23:17 +0000 (01:23 +0100)
rs6000_hard_regno_nregs_internal allows SPE vectors in single
registers satisfying SPE_SIMD_REGNO_P (i.e. register numbers 0 to
31).  However, the corresponding test for e500 double treats all
registers as being able to store a 64-bit value, rather than just
those GPRs.

Logically this inconsistency is wrong; in addition, it causes problems
unwinding from signal handlers.  linux-unwind.h uses
ARG_POINTER_REGNUM as a place to store the return address from a
signal handler, but this logic in rs6000_hard_regno_nregs_internal
results in that being considered an 8-byte register, resulting in
assertion failures.
(<https://gcc.gnu.org/ml/gcc-patches/2014-09/msg02625.html> first
needs to be applied for unwinding to work in general on e500.)  This
patch makes rs6000_hard_regno_nregs_internal handle the e500 double
case consistently with SPE vectors.

Tested with no regressions with cross to powerpc-linux-gnuspe (given
the aforementioned patch applied).  Failures of signal handling
unwinding tests such as gcc.dg/cleanup-{8,9,10,11}.c are fixed by this
patch.

* config/rs6000/rs6000.c (rs6000_hard_regno_nregs_internal): Do
not allow e500 double in registers not satisyfing
SPE_SIMD_REGNO_P.

From-SVN: r216688

gcc/ChangeLog
gcc/config/rs6000/rs6000.c

index bc6908db3b1853d52636250ef517d8c806ea4735..2b94c2b40a6e77d05fadd36ad307bec40c2f1b23 100644 (file)
@@ -1,3 +1,9 @@
+2014-10-25  Joseph Myers  <joseph@codesourcery.com>
+
+       * config/rs6000/rs6000.c (rs6000_hard_regno_nregs_internal): Do
+       not allow e500 double in registers not satisyfing
+       SPE_SIMD_REGNO_P.
+
 2014-10-24  Aldy Hernandez  <aldyh@redhat.com>
 
        * dwarf2out.c (declare_in_namespace): Only emit external
index 2f14c2b6c3e3335fb065fa6043f7d27a7aae72de..a5e5bcf1fef169a161a73d7c13097b992aa5ca69 100644 (file)
@@ -1721,7 +1721,7 @@ rs6000_hard_regno_nregs_internal (int regno, enum machine_mode mode)
      SCmode so as to pass the value correctly in a pair of
      registers.  */
   else if (TARGET_E500_DOUBLE && FLOAT_MODE_P (mode) && mode != SCmode
-          && !DECIMAL_FLOAT_MODE_P (mode))
+          && !DECIMAL_FLOAT_MODE_P (mode) && SPE_SIMD_REGNO_P (regno))
     reg_size = UNITS_PER_FP_WORD;
 
   else