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] Extracting components of complex constants


Inspired by Scott Ladd's recent evaluation of C99 complex number
handling in GCC, I've done some investigating myself.

The following patch improves the code we generate for the simplest
complex example I could think of.

__complex__ double foo()
{
  return 0.0;
}

Currently, mainline CVS on IA-32 generates the following assembly
with -O2 -fomit-frame-pointer.

        .section        .rodata
        .align 8
.LC0:
        .long   0
        .long   0
        .long   0
        .long   0
        .text
        .p2align 4,,15
foo:
        fldl    .LC0
        movl    4(%esp), %eax
        fstpl   (%eax)
        fldl    .LC0+8
        fstpl   8(%eax)
        ret     $4

The curious thing is that IA-32 has FP instructions to load the
value 0.0 into a floating point register, which isn't getting used.

The issue, it turns out, is that complex values can't be represented
as immediate constants in RTL and are therefore forced to memory.
Unfortunately, this means that requesting the real or imaginary
part of a complex constant currently returns a MEM rather than the
appropriate floating point constant.

This is solved by the patch below that tweaks both gen_realpart and
gen_imagpart to explicitly handle this case, in a method similar to
that used by avoid_constant_pool_reference.  Alas complex constants
aren't placed in the function's constant pool, so the latter can't
be used directly.

This should enable many optimizations on expressions involving
complex constants, but for my original example given above we now
generate the following code with this patch.

        .text
        .p2align 4,,15
foo:
        movl    4(%esp), %eax
        fldz
        fstl    (%eax)
        fstpl   8(%eax)
        ret     $4


The following patch has been tested on i686-pc-linux-gnu with a
full "make bootstrap", all languages except treelang, and regression
tested with a top-level "make -k check" with no new regressions.

Ok for mainline?


2003-05-24  Roger Sayle  <roger@eyesopen.com>

	* emit-rtl.c (gen_realpart): Handle extracting the real part
	of a complex constant, returning a FP or integer constant.
	(gen_imagpart): Likewise, for the imaginary part.


Index: emit-rtl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/emit-rtl.c,v
retrieving revision 1.325
diff -c -3 -p -r1.325 emit-rtl.c
*** emit-rtl.c	17 May 2003 22:21:30 -0000	1.325
--- emit-rtl.c	24 May 2003 02:55:38 -0000
*************** gen_realpart (mode, x)
*** 1302,1307 ****
--- 1302,1328 ----
       enum machine_mode mode;
       rtx x;
  {
+   /* Handle complex constants.  */
+   if (GET_CODE (x) == MEM
+       && GET_CODE (XEXP (x,0)) == SYMBOL_REF
+       && TREE_CONSTANT_POOL_ADDRESS_P (XEXP (x,0)))
+     {
+       tree decl = SYMBOL_REF_DECL (XEXP (x,0));
+       if (decl != NULL_TREE
+ 	  && TREE_CODE (decl) == COMPLEX_CST)
+ 	{
+ 	  tree rpart = TREE_REALPART (decl);
+ 	  switch (TREE_CODE (rpart))
+ 	    {
+ 	    case REAL_CST:
+ 	    case INTEGER_CST:
+ 	      return expand_expr (rpart, NULL_RTX, mode, 0);
+ 	    default:
+ 	      break;
+ 	    }
+ 	}
+     }
+
    if (WORDS_BIG_ENDIAN
        && GET_MODE_BITSIZE (mode) < BITS_PER_WORD
        && REG_P (x)
*************** gen_imagpart (mode, x)
*** 1322,1327 ****
--- 1343,1369 ----
       enum machine_mode mode;
       rtx x;
  {
+   /* Handle complex constants.  */
+   if (GET_CODE (x) == MEM
+       && GET_CODE (XEXP (x,0)) == SYMBOL_REF
+       && TREE_CONSTANT_POOL_ADDRESS_P (XEXP (x,0)))
+     {
+       tree decl = SYMBOL_REF_DECL (XEXP (x,0));
+       if (decl != NULL_TREE
+ 	  && TREE_CODE (decl) == COMPLEX_CST)
+ 	{
+ 	  tree ipart = TREE_IMAGPART (decl);
+ 	  switch (TREE_CODE (ipart))
+ 	    {
+ 	    case REAL_CST:
+ 	    case INTEGER_CST:
+ 	      return expand_expr (ipart, NULL_RTX, mode, 0);
+ 	    default:
+ 	      break;
+ 	    }
+ 	}
+     }
+
    if (WORDS_BIG_ENDIAN)
      return gen_lowpart (mode, x);
    else if (! WORDS_BIG_ENDIAN

Roger
--
Roger Sayle,                         E-mail: roger@eyesopen.com
OpenEye Scientific Software,         WWW: http://www.eyesopen.com/
Suite 1107, 3600 Cerrillos Road,     Tel: (+1) 505-473-7385
Santa Fe, New Mexico, 87507.         Fax: (+1) 505-473-0833


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