Patch (rs6000): fix TFmode addressing

Dale Johannesen dalej@apple.com
Sat Jun 19 20:56:00 GMT 2004


The rs6000 currently allows [reg+reg] addressing mode for TFmode 
(128-bit
long double) objects.  I think this is just wrong, as any access to 
them involves
adding small constants.  This disallows it, analogous to current code 
for TImode.
Bootstrapped and tested on Darwin; testcase at bottom.

2004-06-19  Dale Johannesen  <dalej@apple.com>

         * config/rs6000/rs6000.c (rs6000_legitimate_address): Disallow
         [reg+reg] mode for TFmode memory accesses.
         (rs6000_eliminate_indexed_memrefs): New.
         (rs6000_emit_move): Call preceding for TImode and TFmode.

Index: rs6000.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.c,v
retrieving revision 1.650
diff -u -d -b -w -c -3 -p -r1.650 rs6000.c
*** rs6000.c    11 Jun 2004 18:41:44 -0000      1.650
--- rs6000.c    19 Jun 2004 18:26:09 -0000
*************** rs6000_legitimize_reload_address (rtx x,
*** 3328,3334 ****
      word aligned.

      For modes spanning multiple registers (DFmode in 32-bit GPRs,
!    32-bit DImode, TImode), indexed addressing cannot be used because
      adjacent memory cells are accessed by adding word-sized offsets
      during assembly output.  */
   int
--- 3327,3333 ----
      word aligned.

      For modes spanning multiple registers (DFmode in 32-bit GPRs,
!    32-bit DImode, TImode, TFmode), indexed addressing cannot be used 
because
      adjacent memory cells are accessed by adding word-sized offsets
      during assembly output.  */
   int
*************** rs6000_legitimate_address (enum machine_
*** 3356,3364 ****
            || XEXP (x, 0) == arg_pointer_rtx)
         && GET_CODE (XEXP (x, 1)) == CONST_INT)
       return 1;
     if (legitimate_offset_address_p (mode, x, reg_ok_strict))
       return 1;
     if (mode != TImode
         && ((TARGET_HARD_FLOAT && TARGET_FPRS)
           || TARGET_POWERPC64
           || (mode != DFmode && mode != TFmode))
--- 3355,3364 ----
            || XEXP (x, 0) == arg_pointer_rtx)
         && GET_CODE (XEXP (x, 1)) == CONST_INT)
       return 1;
     if (legitimate_offset_address_p (mode, x, reg_ok_strict))
       return 1;
     if (mode != TImode
+       && mode != TFmode
         && ((TARGET_HARD_FLOAT && TARGET_FPRS)
           || TARGET_POWERPC64
           || (mode != DFmode && mode != TFmode))
*************** rs6000_emit_set_long_const (rtx dest, HO
*** 3653,3658 ****
--- 3653,3679 ----
     return dest;
   }

+ /* Helper for the following.  Get rid of [r+r] memory refs
+    in cases where it won't work (TImode, TFmode).  */
+
+ static void
+ rs6000_eliminate_indexed_memrefs (rtx operands[2])
+ {
+   if (GET_CODE (operands[0]) == MEM
+       && GET_CODE (XEXP (operands[0], 0)) != REG
+       && ! reload_in_progress)
+     operands[0]
+       = replace_equiv_address (operands[0],
+                              copy_addr_to_reg (XEXP (operands[0], 
0)));
+
+   if (GET_CODE (operands[1]) == MEM
+       && GET_CODE (XEXP (operands[1], 0)) != REG
+       && ! reload_in_progress)
+     operands[1]
+       = replace_equiv_address (operands[1],
+                              copy_addr_to_reg (XEXP (operands[1], 
0)));
+ }
+
   /* Emit a move from SOURCE to DEST in mode MODE.  */
   void
   rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
*************** rs6000_emit_move (rtx dest, rtx source,
*** 3790,3795 ****
--- 3811,3819 ----
         break;

       case TFmode:
+       rs6000_eliminate_indexed_memrefs (operands);
+       /* fall through */
+
       case DFmode:
       case SFmode:
         if (CONSTANT_P (operands[1])
*************** rs6000_emit_move (rtx dest, rtx source,
*** 3972,3990 ****
         break;

       case TImode:
!       if (GET_CODE (operands[0]) == MEM
!         && GET_CODE (XEXP (operands[0], 0)) != REG
!         && ! reload_in_progress)
!       operands[0]
!         = replace_equiv_address (operands[0],
!                                  copy_addr_to_reg (XEXP (operands[0], 
0)));

-       if (GET_CODE (operands[1]) == MEM
-         && GET_CODE (XEXP (operands[1], 0)) != REG
-         && ! reload_in_progress)
-       operands[1]
-         = replace_equiv_address (operands[1],
-                                  copy_addr_to_reg (XEXP (operands[1], 
0)));
         if (TARGET_POWER)
         {
           emit_insn (gen_rtx_PARALLEL (VOIDmode,
--- 3996,4003 ----
         break;

       case TImode:
!       rs6000_eliminate_indexed_memrefs (operands);

         if (TARGET_POWER)
         {
           emit_insn (gen_rtx_PARALLEL (VOIDmode,


/* { dg-options "-Os -mlong-double-128" } */
/* { dg-do compile { target rs6000-*-* powerpc-*-* } } */
/* Make sure compiler doesn't generate [reg+reg] address mode
    for long doubles. */
union arg {
   int intarg;
   long double longdoublearg;
};
long double d;
int va(int n, union arg **argtable)
{
   (*argtable)[n].longdoublearg = d;
}



More information about the Gcc-patches mailing list