This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RFA: Fix mode-mismatch ICE in shift_returned_value


This is an RFA for the patch I posted yesterday in relation to
Eric's single-element-array ICE.

To recap: on big-endian MIPS targets, when using the n32 & n64 ABIs,
single-element float arrays are returned in the high part of the 64-bit
return register.  It's then up to calls.c:shift_returned_value() to
shift the value right and provide the SFmode rtx that the rest of GCC
expects.

Unfortunately, shift_returned_value() doesn't handle non-integer modes
correctly.  It tries to do a direct convert_move() from DImode to the
return type's TYPE_MODE, which is certainly not what we want for SFmode,
and which ICEs.

This patch makes it convert to the equivalent integer mode instead.
It then adjusts this converted rtx so that it has the appropriate
TYPE_MODE.

For avoidance of doubt: this isn't an ABI change, since it doesn't
affect the decision about where the value is returned, or the shift
operation itself.  It simply changes the mode of an internal rtx
operation so that it uses an integer mode of the same size.

Bootstrapped & regression tested on mips64-linux-gnu (a big-endian
target that includes n32 & n64 multilibs).  Eric also reports that
it fixes his testcase.  OK to install?  OK for 3.4.2 after an
appropriate grace period?

Richard


	* calls.c (shift_returned_value): Fix handling of non-integer
	TYPE_MODEs.

testsuite/
	* gcc.c-torture/compile/20040624-1.c: New test.

Index: calls.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/calls.c,v
retrieving revision 1.315.2.5
diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.315.2.5 calls.c
*** calls.c	15 Mar 2004 23:22:42 -0000	1.315.2.5
--- calls.c	24 Jun 2004 07:11:45 -0000
*************** shift_returned_value (tree type, rtx *va
*** 2043,2051 ****
  	       - BITS_PER_UNIT * int_size_in_bytes (type));
        if (shift > 0)
  	{
  	  *value = expand_binop (GET_MODE (*value), lshr_optab, *value,
  				 GEN_INT (shift), 0, 1, OPTAB_WIDEN);
! 	  *value = convert_to_mode (TYPE_MODE (type), *value, 0);
  	  return true;
  	}
      }
--- 2043,2059 ----
  	       - BITS_PER_UNIT * int_size_in_bytes (type));
        if (shift > 0)
  	{
+ 	  /* Shift the value into the low part of the register.  */
  	  *value = expand_binop (GET_MODE (*value), lshr_optab, *value,
  				 GEN_INT (shift), 0, 1, OPTAB_WIDEN);
! 
! 	  /* Truncate it to the type's mode, or its integer equivalent.
! 	     This is subject to TRULY_NOOP_TRUNCATION.  */
! 	  *value = convert_to_mode (int_mode_for_mode (TYPE_MODE (type)),
! 				    *value, 0);
! 
! 	  /* Now convert it to the final form.  */
! 	  *value = gen_lowpart (TYPE_MODE (type), *value);
  	  return true;
  	}
      }
*** /dev/null	Fri Apr 23 00:21:55 2004
--- testsuite/gcc.c-torture/compile/20040624-1.c	Thu Jun 24 08:11:36 2004
***************
*** 0 ****
--- 1,3 ----
+ struct s { float f[1]; };
+ struct s foo();
+ float bar() { return foo().f[0]; }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]