rs6000.c (invalid_e500_subreg, [...]): Handle DDmode and TDmode similarly to DFmode...
authorPeter Bergner <bergner@vnet.ibm.com>
Mon, 19 Nov 2007 19:50:47 +0000 (13:50 -0600)
committerPeter Bergner <bergner@gcc.gnu.org>
Mon, 19 Nov 2007 19:50:47 +0000 (13:50 -0600)
* config/rs6000/rs6000.c (invalid_e500_subreg,
rs6000_legitimate_offset_address_p, legitimate_lo_sum_address_p,
rs6000_legitimize_address, rs6000_legitimize_reload_address,
rs6000_legitimate_address, function_arg_advance,
spe_build_register_parallel, rs6000_spe_function_arg,
rs6000_split_multireg_move, spe_func_has_64bit_regs_p,
emit_frame_save, gen_frame_mem_offset, rs6000_function_value,
rs6000_libcall_value, rs6000_dwarf_register_span): Handle DDmode and
TDmode similarly to DFmode and TFmode.
* config/rs6000/rs6000.h (LOCAL_ALIGNMENT, MEMBER_TYPE_FORCES_BLK,
DATA_ALIGNMENT, CLASS_MAX_NREGS, CANNOT_CHANGE_MODE_CLASS): Likewise.

* gcc.dg/dfp/ddmode-ice.c: New test.

From-SVN: r130296

gcc/ChangeLog
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/dfp/ddmode-ice.c [new file with mode: 0644]

index 2cc6f6f..713450c 100644 (file)
@@ -1,3 +1,17 @@
+2007-11-19  Peter Bergner  <bergner@vnet.ibm.com>
+
+       * config/rs6000/rs6000.c (invalid_e500_subreg,
+       rs6000_legitimate_offset_address_p, legitimate_lo_sum_address_p,
+       rs6000_legitimize_address, rs6000_legitimize_reload_address,
+       rs6000_legitimate_address, function_arg_advance,
+       spe_build_register_parallel, rs6000_spe_function_arg,
+       rs6000_split_multireg_move, spe_func_has_64bit_regs_p,
+       emit_frame_save, gen_frame_mem_offset, rs6000_function_value,
+       rs6000_libcall_value, rs6000_dwarf_register_span): Handle DDmode and
+       TDmode similarly to DFmode and TFmode.
+       * config/rs6000/rs6000.h (LOCAL_ALIGNMENT, MEMBER_TYPE_FORCES_BLK,
+       DATA_ALIGNMENT, CLASS_MAX_NREGS, CANNOT_CHANGE_MODE_CLASS): Likewise.
+
 2007-11-19  Eric Botcazou  <ebotcazou@adacore.com>
 
        * stor-layout.c (lang_adjust_rli): Delete.
index 3dc6c15..15bebb1 100644 (file)
@@ -3115,13 +3115,16 @@ invalid_e500_subreg (rtx op, enum machine_mode mode)
          && (mode == SImode || mode == DImode || mode == TImode)
          && REG_P (SUBREG_REG (op))
          && (GET_MODE (SUBREG_REG (op)) == DFmode
-             || GET_MODE (SUBREG_REG (op)) == TFmode))
+             || GET_MODE (SUBREG_REG (op)) == TFmode
+             || GET_MODE (SUBREG_REG (op)) == DDmode
+             || GET_MODE (SUBREG_REG (op)) == TDmode))
        return true;
 
       /* Reject (subreg:DF (reg:DI)); likewise with subreg:TF and
         reg:TI.  */
       if (GET_CODE (op) == SUBREG
-         && (mode == DFmode || mode == TFmode)
+         && (mode == DFmode || mode == TFmode
+             || mode == DDmode || mode == TDmode)
          && REG_P (SUBREG_REG (op))
          && (GET_MODE (SUBREG_REG (op)) == DImode
              || GET_MODE (SUBREG_REG (op)) == TImode))
@@ -3390,12 +3393,12 @@ rs6000_legitimate_offset_address_p (enum machine_mode mode, rtx x, int strict)
       break;
 
     case TFmode:
+    case TDmode:
       if (TARGET_E500_DOUBLE)
        return (SPE_CONST_OFFSET_OK (offset)
                && SPE_CONST_OFFSET_OK (offset + 8));
 
     case TImode:
-    case TDmode:
       if (mode == TFmode || mode == TDmode || !TARGET_POWERPC64)
        extra = 12;
       else if (offset & 3)
@@ -3474,6 +3477,7 @@ legitimate_lo_sum_address_p (enum machine_mode mode, rtx x, int strict)
     return false;
   /* Restrict addressing for DI because of our SUBREG hackery.  */
   if (TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode
+                            || mode == DDmode || mode == TDmode
                             || mode == DImode))
     return false;
   x = XEXP (x, 1);
@@ -3488,7 +3492,8 @@ legitimate_lo_sum_address_p (enum machine_mode mode, rtx x, int strict)
        return false;
       if (GET_MODE_BITSIZE (mode) > 64
          || (GET_MODE_BITSIZE (mode) > 32 && !TARGET_POWERPC64
-             && !(TARGET_HARD_FLOAT && TARGET_FPRS && mode == DFmode)))
+             && !(TARGET_HARD_FLOAT && TARGET_FPRS
+                  && (mode == DFmode || mode == DDmode))))
        return false;
 
       return CONSTANT_P (x);
@@ -3610,7 +3615,8 @@ rs6000_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
           && CONSTANT_P (x)
           && GET_MODE_NUNITS (mode) == 1
           && (GET_MODE_BITSIZE (mode) <= 32
-              || ((TARGET_HARD_FLOAT && TARGET_FPRS) && mode == DFmode)))
+              || ((TARGET_HARD_FLOAT && TARGET_FPRS)
+                  && (mode == DFmode || mode == DDmode))))
     {
       rtx reg = gen_reg_rtx (Pmode);
       emit_insn (gen_elf_high (reg, x));
@@ -3624,7 +3630,8 @@ rs6000_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
           && GET_CODE (x) != CONST_INT
           && GET_CODE (x) != CONST_DOUBLE
           && CONSTANT_P (x)
-          && ((TARGET_HARD_FLOAT && TARGET_FPRS) || mode != DFmode)
+          && ((TARGET_HARD_FLOAT && TARGET_FPRS)
+              || (mode != DFmode && mode != DDmode))
           && mode != DImode
           && mode != TImode)
     {
@@ -3980,6 +3987,7 @@ rs6000_legitimize_reload_address (rtx x, enum machine_mode mode,
       && GET_CODE (XEXP (x, 1)) == CONST_INT
       && !SPE_VECTOR_MODE (mode)
       && !(TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode
+                                 || mode == DDmode || mode == TDmode
                                  || mode == DImode))
       && !ALTIVEC_VECTOR_MODE (mode))
     {
@@ -4021,12 +4029,12 @@ rs6000_legitimize_reload_address (rtx x, enum machine_mode mode,
       && !flag_pic
 #endif
       /* Don't do this for TFmode or TDmode, since the result isn't offsettable.
-        The same goes for DImode without 64-bit gprs and DFmode
+        The same goes for DImode without 64-bit gprs and DFmode and DDmode
         without fprs.  */
       && mode != TFmode
       && mode != TDmode
       && (mode != DImode || TARGET_POWERPC64)
-      && (mode != DFmode || TARGET_POWERPC64
+      && ((mode != DFmode && mode != DDmode) || TARGET_POWERPC64
          || (TARGET_FPRS && TARGET_HARD_FLOAT)))
     {
 #if TARGET_MACHO
@@ -4089,11 +4097,11 @@ rs6000_legitimize_reload_address (rtx x, enum machine_mode mode,
    refers to a constant pool entry of an address (or the sum of it
    plus a constant), a short (16-bit signed) constant plus a register,
    the sum of two registers, or a register indirect, possibly with an
-   auto-increment.  For DFmode and DImode with a constant plus register,
-   we must ensure that both words are addressable or PowerPC64 with offset
-   word aligned.
+   auto-increment.  For DFmode, DDmode and DImode with a constant plus
+   register, we must ensure that both words are addressable or PowerPC64
+   with offset word aligned.
 
-   For modes spanning multiple registers (DFmode in 32-bit GPRs,
+   For modes spanning multiple registers (DFmode and DDmode in 32-bit GPRs,
    32-bit DImode, TImode, TFmode, TDmode), indexed addressing cannot be used
    because adjacent memory cells are accessed by adding word-sized offsets
    during assembly output.  */
@@ -4118,8 +4126,8 @@ rs6000_legitimate_address (enum machine_mode mode, rtx x, int reg_ok_strict)
       && mode != TFmode
       && mode != TDmode
       /* Restrict addressing for DI because of our SUBREG hackery.  */
-      && !(TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode
-                                 || mode == DImode))
+      && !(TARGET_E500_DOUBLE
+          && (mode == DFmode || mode == DDmode || mode == DImode))
       && TARGET_UPDATE
       && legitimate_indirect_address_p (XEXP (x, 0), reg_ok_strict))
     return 1;
@@ -4142,7 +4150,7 @@ rs6000_legitimate_address (enum machine_mode mode, rtx x, int reg_ok_strict)
       && mode != TDmode
       && ((TARGET_HARD_FLOAT && TARGET_FPRS)
          || TARGET_POWERPC64
-         || ((mode != DFmode || TARGET_E500_DOUBLE) && mode != TFmode))
+         || ((mode != DFmode && mode != DDmode) || TARGET_E500_DOUBLE))
       && (TARGET_POWERPC64 || mode != DImode)
       && legitimate_indexed_address_p (x, reg_ok_strict))
     return 1;
@@ -4152,12 +4160,13 @@ rs6000_legitimate_address (enum machine_mode mode, rtx x, int reg_ok_strict)
       && mode != TDmode
       && ((TARGET_HARD_FLOAT && TARGET_FPRS)
          || TARGET_POWERPC64
-         || ((mode != DFmode || TARGET_E500_DOUBLE) && mode != TFmode))
+         || ((mode != DFmode && mode != DDmode) || TARGET_E500_DOUBLE))
       && (TARGET_POWERPC64 || mode != DImode)
       && !ALTIVEC_VECTOR_MODE (mode)
       && !SPE_VECTOR_MODE (mode)
       /* Restrict addressing for DI because of our SUBREG hackery.  */
-      && !(TARGET_E500_DOUBLE && (mode == DFmode || mode == DImode))
+      && !(TARGET_E500_DOUBLE
+          && (mode == DFmode || mode == DDmode || mode == DImode))
       && TARGET_UPDATE
       && legitimate_indirect_address_p (XEXP (x, 0), reg_ok_strict)
       && (rs6000_legitimate_offset_address_p (mode, XEXP (x, 1), reg_ok_strict)
@@ -5407,7 +5416,8 @@ function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
          else
            {
              cum->fregno = FP_ARG_V4_MAX_REG + 1;
-             if (mode == DFmode || mode == TFmode || mode == DDmode || mode == TDmode)
+             if (mode == DFmode || mode == TFmode
+                 || mode == DDmode || mode == TDmode)
                cum->words += cum->words & 1;
              cum->words += rs6000_arg_size (mode, type);
            }
@@ -5490,12 +5500,14 @@ spe_build_register_parallel (enum machine_mode mode, int gregno)
   switch (mode)
     {
     case DFmode:
+    case DDmode:
       r1 = gen_rtx_REG (DImode, gregno);
       r1 = gen_rtx_EXPR_LIST (VOIDmode, r1, const0_rtx);
       return gen_rtx_PARALLEL (mode, gen_rtvec (1, r1));
 
     case DCmode:
     case TFmode:
+    case TDmode:
       r1 = gen_rtx_REG (DImode, gregno);
       r1 = gen_rtx_EXPR_LIST (VOIDmode, r1, const0_rtx);
       r3 = gen_rtx_REG (DImode, gregno + 2);
@@ -5527,13 +5539,14 @@ rs6000_spe_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
 
   /* On E500 v2, double arithmetic is done on the full 64-bit GPR, but
      are passed and returned in a pair of GPRs for ABI compatibility.  */
-  if (TARGET_E500_DOUBLE && (mode == DFmode || mode == DCmode
-                            || mode == TFmode || mode == TCmode))
+  if (TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode
+                            || mode == DDmode || mode == TDmode
+                            || mode == DCmode || mode == TCmode))
     {
       int n_words = rs6000_arg_size (mode, type);
 
       /* Doubles go in an odd/even register pair (r5/r6, etc).  */
-      if (mode == DFmode)
+      if (mode == DFmode || mode == DDmode)
        gregno += (1 - gregno) & 1;
 
       /* Multi-reg args are not split between registers and stack.  */
@@ -13718,8 +13731,8 @@ rs6000_split_multireg_move (rtx dst, rtx src)
     reg_mode = DECIMAL_FLOAT_MODE_P (mode) ? DDmode : DFmode;
   else if (ALTIVEC_REGNO_P (reg))
     reg_mode = V16QImode;
-  else if (TARGET_E500_DOUBLE && mode == TFmode)
-    reg_mode = DFmode;
+  else if (TARGET_E500_DOUBLE && (mode == TFmode || mode == TDmode))
+    reg_mode = DECIMAL_FLOAT_MODE_P (mode) ? DDmode : DFmode;
   else
     reg_mode = word_mode;
   reg_mode_size = GET_MODE_SIZE (reg_mode);
@@ -14458,7 +14471,8 @@ spe_func_has_64bit_regs_p (void)
 
              if (SPE_VECTOR_MODE (mode))
                return true;
-             if (TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode))
+             if (TARGET_E500_DOUBLE && (mode == DFmode || mode == TFmode
+                                        || mode == DDmode || mode == TDmode))
                return true;
            }
        }
@@ -15274,7 +15288,7 @@ emit_frame_save (rtx frame_reg, rtx frame_ptr, enum machine_mode mode,
 
   /* Some cases that need register indexed addressing.  */
   if ((TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
-      || (TARGET_E500_DOUBLE && mode == DFmode)
+      || (TARGET_E500_DOUBLE && (mode == DFmode || mode == DDmode))
       || (TARGET_SPE_ABI
          && SPE_VECTOR_MODE (mode)
          && !SPE_CONST_OFFSET_OK (offset)))
@@ -15314,7 +15328,7 @@ gen_frame_mem_offset (enum machine_mode mode, rtx reg, int offset)
   int_rtx = GEN_INT (offset);
 
   if ((TARGET_SPE_ABI && SPE_VECTOR_MODE (mode))
-      || (TARGET_E500_DOUBLE && mode == DFmode))
+      || (TARGET_E500_DOUBLE && (mode == DFmode || mode == DDmode)))
     {
       offset_rtx = gen_rtx_REG (Pmode, FIXED_SCRATCH);
       emit_move_insn (offset_rtx, int_rtx);
@@ -21521,8 +21535,8 @@ rs6000_function_value (const_tree valtype, const_tree func ATTRIBUTE_UNUSED)
           && ALTIVEC_VECTOR_MODE (mode))
     regno = ALTIVEC_ARG_RETURN;
   else if (TARGET_E500_DOUBLE && TARGET_HARD_FLOAT
-          && (mode == DFmode || mode == DCmode
-              || mode == TFmode || mode == TCmode))
+          && (mode == DFmode || mode == DDmode || mode == DCmode
+              || mode == TFmode || mode == TDmode || mode == TCmode))
     return spe_build_register_parallel (mode, GP_ARG_RETURN);
   else
     regno = GP_ARG_RETURN;
@@ -21583,8 +21597,8 @@ rs6000_libcall_value (enum machine_mode mode)
   else if (COMPLEX_MODE_P (mode) && targetm.calls.split_complex_arg)
     return rs6000_complex_function_value (mode);
   else if (TARGET_E500_DOUBLE && TARGET_HARD_FLOAT
-          && (mode == DFmode || mode == DCmode
-              || mode == TFmode || mode == TCmode))
+          && (mode == DFmode || mode == DDmode || mode == DCmode
+              || mode == TFmode || mode == TDmode || mode == TCmode))
     return spe_build_register_parallel (mode, GP_ARG_RETURN);
   else
     regno = GP_ARG_RETURN;
@@ -21642,7 +21656,8 @@ rs6000_dwarf_register_span (rtx reg)
 
   if (TARGET_SPE
       && (SPE_VECTOR_MODE (GET_MODE (reg))
-         || (TARGET_E500_DOUBLE && GET_MODE (reg) == DFmode)))
+         || (TARGET_E500_DOUBLE
+             && (GET_MODE (reg) == DFmode || GET_MODE (reg) == DDmode))))
     ;
   else
     return NULL_RTX;
index 4b27085..7fb2002 100644 (file)
@@ -559,7 +559,8 @@ extern enum rs6000_nop_insertion rs6000_sched_insert_nops;
    that the object would ordinarily have.  */
 #define LOCAL_ALIGNMENT(TYPE, ALIGN)                           \
   ((TARGET_ALTIVEC && TREE_CODE (TYPE) == VECTOR_TYPE) ? 128 : \
-    (TARGET_E500_DOUBLE && TYPE_MODE (TYPE) == DFmode) ? 64 : \
+    (TARGET_E500_DOUBLE                                                \
+     && (TYPE_MODE (TYPE) == DFmode || TYPE_MODE (TYPE) == DDmode)) ? 64 : \
     ((TARGET_SPE && TREE_CODE (TYPE) == VECTOR_TYPE \
      && SPE_VECTOR_MODE (TYPE_MODE (TYPE))) || (TARGET_PAIRED_FLOAT \
         && TREE_CODE (TYPE) == VECTOR_TYPE \
@@ -585,7 +586,7 @@ extern enum rs6000_nop_insertion rs6000_sched_insert_nops;
    fit into 1, whereas DI still needs two.  */
 #define MEMBER_TYPE_FORCES_BLK(FIELD, MODE) \
   ((TARGET_SPE && TREE_CODE (TREE_TYPE (FIELD)) == VECTOR_TYPE) \
-   || (TARGET_E500_DOUBLE && (MODE) == DFmode))
+   || (TARGET_E500_DOUBLE && ((MODE) == DFmode || (MODE) == DDmode)))
 
 /* A bit-field declared as `int' forces `int' alignment for the struct.  */
 #define PCC_BITFIELD_TYPE_MATTERS 1
@@ -604,7 +605,8 @@ extern enum rs6000_nop_insertion rs6000_sched_insert_nops;
 #define DATA_ALIGNMENT(TYPE, ALIGN)            \
   (TREE_CODE (TYPE) == VECTOR_TYPE ? ((TARGET_SPE_ABI \
    || TARGET_PAIRED_FLOAT) ? 64 : 128) \
-   : (TARGET_E500_DOUBLE && TYPE_MODE (TYPE) == DFmode) ? 64 \
+   : (TARGET_E500_DOUBLE                       \
+      && (TYPE_MODE (TYPE) == DFmode || TYPE_MODE (TYPE) == DDmode)) ? 64 \
    : TREE_CODE (TYPE) == ARRAY_TYPE            \
    && TYPE_MODE (TREE_TYPE (TYPE)) == QImode   \
    && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
@@ -1178,7 +1180,8 @@ enum reg_class
 #define CLASS_MAX_NREGS(CLASS, MODE)                                   \
  (((CLASS) == FLOAT_REGS)                                              \
   ? ((GET_MODE_SIZE (MODE) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD) \
-  : (TARGET_E500_DOUBLE && (CLASS) == GENERAL_REGS && (MODE) == DFmode) \
+  : (TARGET_E500_DOUBLE && (CLASS) == GENERAL_REGS                     \
+     && ((MODE) == DFmode || (MODE) == DDmode))                                \
   ? 1                                                                   \
   : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
 
@@ -1192,6 +1195,8 @@ enum reg_class
    : (((TARGET_E500_DOUBLE                                             \
        && ((((TO) == DFmode) + ((FROM) == DFmode)) == 1                \
            || (((TO) == TFmode) + ((FROM) == TFmode)) == 1             \
+           || (((TO) == DDmode) + ((FROM) == DDmode)) == 1             \
+           || (((TO) == TDmode) + ((FROM) == TDmode)) == 1             \
            || (((TO) == DImode) + ((FROM) == DImode)) == 1))           \
        || (TARGET_SPE                                                  \
           && (SPE_VECTOR_MODE (FROM) + SPE_VECTOR_MODE (TO)) == 1))    \
@@ -1717,11 +1722,11 @@ typedef struct rs6000_args
    refers to a constant pool entry of an address (or the sum of it
    plus a constant), a short (16-bit signed) constant plus a register,
    the sum of two registers, or a register indirect, possibly with an
-   auto-increment.  For DFmode and DImode with a constant plus register,
-   we must ensure that both words are addressable or PowerPC64 with offset
-   word aligned.
+   auto-increment.  For DFmode, DDmode and DImode with a constant plus
+   register, we must ensure that both words are addressable or PowerPC64
+   with offset word aligned.
 
-   For modes spanning multiple registers (DFmode in 32-bit GPRs,
+   For modes spanning multiple registers (DFmode and DDmode 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.  */
index b084877..9284fb7 100644 (file)
@@ -1,3 +1,7 @@
+2007-11-19  Peter Bergner  <bergner@vnet.ibm.com>
+
+       * gcc.dg/dfp/ddmode-ice.c: New test.
+
 2007-11-19  Eric Botcazou  <ebotcazou@libertysurf.fr>
 
        PR tree-optimization/34036
diff --git a/gcc/testsuite/gcc.dg/dfp/ddmode-ice.c b/gcc/testsuite/gcc.dg/dfp/ddmode-ice.c
new file mode 100644 (file)
index 0000000..979dabe
--- /dev/null
@@ -0,0 +1,54 @@
+/* { dg-do compile } */
+/* { dg-options "-std=gnu99 -O1" } */
+
+/* This used to result in an ICE.  */
+
+_Decimal64 y[258][258];
+_Decimal64 dd[258][258];
+_Decimal64 ry[258][258];
+_Decimal64
+foo (void)
+{
+  int i;
+  int j;
+  int m;
+  int im;
+  int jm;
+  int ip;
+  int jp;
+  int i2m;
+  int i1p;
+  _Decimal64 a;
+  _Decimal64 b;
+  _Decimal64 c;
+  _Decimal64 qi;
+  _Decimal64 qj;
+  _Decimal64 xx;
+  _Decimal64 yx;
+  _Decimal64 xy;
+  _Decimal64 yy;
+  _Decimal64 rel;
+  _Decimal64 qxx;
+  _Decimal64 qyy;
+  _Decimal64 qxy;
+  do
+    {
+      jp = j + 1;
+      for (i = i1p; i <= i2m; i++)
+       {
+         ip = i + 1;
+         yx = y[ip][j] - y[im][j];
+         yy = y[i][jp] - y[i][jm];
+         a = 0.25dd * (xy * xy + yy * yy);
+         b = 0.25dd * (xx * xx + yx * yx);
+         c = 0.125dd * (xx * xy + yx * yy);
+         qj = 0.0dd;
+         dd[i][m] = b + a * rel + b;
+         qxx = y[ip][j] - 2.0dd * y[i][j] + y[im][j];
+         qyy = y[i][jp] - 2.0dd * y[i][j] + y[i][jm];
+         qxy = y[ip][jp] - y[ip][jm] - y[im][jp] + y[im][jm];
+         ry[i][m] = a * qxx + b * qyy - c * qxy + yx * qi + yy * qj;
+       }
+    }
+  while (1);
+}