Hi,

the attached Ada testcase triggers an ICE with -mbig-endian -mhard-float:

eric@polaris:~/build/gcc/arm-linux-gnueabi> gcc/xgcc -Bgcc -S p.adb -I 
gcc/ada/rts -mbig-endian -mhard-float
+===========================GNAT BUG DETECTED==============================+
| 6.0.0 20151220 (experimental) [trunk revision 231856] (arm-linux-gnueabi) 
GCC error:|
| in emit_move_multi_word, at expr.c:3452    

because the middle-end is trying to copy an OImode value from VFP registers 
and the back-end refuses it in big-endian mode:

  In big-endian mode, modes greater than word size (i.e. DFmode) are stored in
  VFP registers in little-endian order.  We can't describe that accurately to
  GCC, so avoid taking subregs of such values.
  The only exception is going from a 128-bit to a 64-bit type.  In that case
  the data layout happens to be consistent for big-endian, so we explicitly
  allow that case.  */
#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS)               \
  (TARGET_VFP && TARGET_BIG_END                                 \
   && !(GET_MODE_SIZE (FROM) == 16 && GET_MODE_SIZE (TO) == 8)  \
   && (GET_MODE_SIZE (FROM) > UNITS_PER_WORD                    \
       || GET_MODE_SIZE (TO) > UNITS_PER_WORD)                  \
   && reg_classes_intersect_p (VFP_REGS, (CLASS)))

That's very likely not reproducible in the C family of languages because the
code generates a RECORD_TYPE with OImode.  The other thing to note is that 
this works for TImode because, in this case, the back-end returns a PARALLEL 
instead of a bare REG for the return value register.

Hence the attached patch, which extends this treatment to all integer modes 
larger than TImode.  Tested on arm-none-eabi, OK for the mainline?


2015-12-21  Eric Botcazou  <ebotca...@adacore.com>

        * config/arm/arm.c (aapcs_vfp_allocate_return_reg): Treat all integer
        modes larger than TImode as TImode if NEON is not enabled.


-- 
Eric Botcazou
Index: config/arm/arm.c
===================================================================
--- config/arm/arm.c	(revision 231856)
+++ config/arm/arm.c	(working copy)
@@ -5846,7 +5846,10 @@ aapcs_vfp_allocate_return_reg (enum arm_
   if (!use_vfp_abi (pcs_variant, false))
     return NULL;
 
-  if (mode == BLKmode || (mode == TImode && !TARGET_NEON))
+  if (mode == BLKmode
+      || (GET_MODE_CLASS (mode) == MODE_INT
+	  && GET_MODE_SIZE (mode) >= GET_MODE_SIZE (TImode)
+	  && !TARGET_NEON))
     {
       int count;
       machine_mode ag_mode;

Reply via email to