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]

[PATCH] Fix PR middle-end/18776


Hi Richard,

Your "complex" patches have introduced a few problems on SPARC 64-bit, related 
to the handling of SCmode values, which have prevented libgfortran from 
building since then.  They originate in SCmode values being automatically 
redirected to the bit-field manipulation routines by write_complex_part and 
read_complex_part.  This yields awful initial RTL (00.expand.0) for code 
using _Complex float , for example:

typedef _Complex float cf;

cf foo(cf a)
{
  cf b = a;
  return b;
}

Moreover, this kind of RTL appears to be prone to confusing liveness analysis, 
leading to some fun in subsequent passes.


On the SPARC we really want to manipulate SFmode values directly, even in 
64-bit mode, because 32-bit is the base granularity of the FP regs.  I have 
waited a little before proposing these modifications in order to see if other 
64-bit platforms would be affected by similar problems, but apparently not, 
so they are a bit SPARC-oriented.

The first modification is to use a subreg in write_complex_part and 
read_complex_part if the original object is a hard reg that spans an even 
number of registers.  I think this is good enough a discriminant on the 
SPARC, but we might need to test something like reg_raw_mode elsewhere.
This greatly helps the RTL expanders at function boundaries and is sufficient 
to fix the libgfortran problem and almost all the regressions in the 
testsuite.

The second modification is to also use a subreg if the original object is a 
MEM and the natural size of registers that can hold the mode of the value is 
the size of the mode.  It's the REGMODE_NATURAL_SIZE target macro, which is 
only defined to something useful on the SPARC.  This greatly helps the load 
and store operations.

I've attached the initial RTL (00.expand.1) produced with both modifications.

Bootstrapped/regtested on sparc-sun-solaris2.8, sparc64-sun-solaris2.9 and 
amd64-mandrake-linux-gnu.


2004-12-19  Eric Botcazou  <ebotcazou@libertysurf.fr>

	PR middle-end/18776
	* expr.c (write_complex_part): Use a subreg if the original object
	is a hard reg that spans an even number of regs or a MEM for which
	the natural size of registers that can hold the mode of its value is the
	size of the mode.
	(read_complex_part): Likewise.


-- 
Eric Botcazou
Index: expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expr.c,v
retrieving revision 1.760
diff -u -p -r1.760 expr.c
--- expr.c	12 Dec 2004 21:12:43 -0000	1.760
+++ expr.c	18 Dec 2004 18:49:58 -0000
@@ -2598,7 +2598,19 @@ write_complex_part (rtx cplx, rtx val, b
      will work.  This special case is important, since store_bit_field
      wants to operate on integer modes, and there's rarely an OImode to
      correspond to TCmode.  */
-  if (ibitsize >= BITS_PER_WORD)
+  if (ibitsize >= BITS_PER_WORD
+      /* The following 2 special cases are important for SCmode regs on
+	 64-bit platforms where the natural size of floating-point regs
+	 is 32-bit, e.g. the SPARC.  */
+      /* For hard regs we have exact predicates.  Assume we can split
+	 the original object if it spans an even number of hard regs.  */
+      || (GET_CODE (cplx) == REG
+	  && REGNO (cplx) < FIRST_PSEUDO_REGISTER
+	  && hard_regno_nregs[REGNO (cplx)][cmode] % 2 == 0)
+      /* For MEMs we operate in IMODE if we know that the natural size
+	 of registers that can hold it is precisely its size.  */
+      || (GET_CODE (cplx) == MEM
+	  && REGMODE_NATURAL_SIZE (imode) == GET_MODE_SIZE (imode)))
     {
       rtx part = simplify_gen_subreg (imode, cplx, cmode,
 				      imag_p ? GET_MODE_SIZE (imode) : 0);
@@ -2640,7 +2652,19 @@ read_complex_part (rtx cplx, bool imag_p
      will work.  This special case is important, since extract_bit_field
      wants to operate on integer modes, and there's rarely an OImode to
      correspond to TCmode.  */
-  if (ibitsize >= BITS_PER_WORD)
+  if (ibitsize >= BITS_PER_WORD
+      /* The following 2 special cases are important for SCmode regs on
+	 64-bit platforms where the natural size of floating-point regs
+	 is 32-bit, e.g. the SPARC.  */
+      /* For hard regs we have exact predicates.  Assume we can split
+	 the original object if it spans an even number of hard regs.  */
+      || (GET_CODE (cplx) == REG
+	  && REGNO (cplx) < FIRST_PSEUDO_REGISTER
+	  && hard_regno_nregs[REGNO (cplx)][cmode] % 2 == 0)
+      /* For MEMs we operate in IMODE if we know the natural size
+	 of registers that can hold it is precisely its size.  */
+      || (GET_CODE (cplx) == MEM
+	  && REGMODE_NATURAL_SIZE (imode) == GET_MODE_SIZE (imode)))
     {
       rtx ret = simplify_gen_subreg (imode, cplx, cmode,
 				     imag_p ? GET_MODE_SIZE (imode) : 0);

Attachment: complex_move.c.00.expand.0
Description: Text document

Attachment: complex_move.c.00.expand.1
Description: Text document


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