diff mbox

[ARM] Fix ICE on Ada code with -mbig-endian -mhard-float

Message ID 3790654.AGgIZLrLrs@polaris
State New
Headers show

Commit Message

Eric Botcazou Dec. 21, 2015, 4:24 p.m. UTC
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  <ebotcazou@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.

Comments

Eric Botcazou Dec. 22, 2015, 7:39 a.m. UTC | #1
> the attached Ada testcase triggers an ICE with -mbig-endian -mhard-float:

And here it is.
Richard Earnshaw (lists) Dec. 23, 2015, 11:34 a.m. UTC | #2
On 21/12/15 16:24, Eric Botcazou wrote:
> 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  <ebotcazou@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.
> 
> 

OK.

R.
diff mbox

Patch

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;