rs6000.c (rs6000_rtx_costs): Calculate cost of constants more accurately.
authorDavid Edelsohn <edelsohn@gnu.org>
Tue, 3 Aug 2004 15:31:38 +0000 (15:31 +0000)
committerDavid Edelsohn <dje@gcc.gnu.org>
Tue, 3 Aug 2004 15:31:38 +0000 (11:31 -0400)
        * config/rs6000/rs6000.c (rs6000_rtx_costs): Calculate cost of
        constants more accurately.  Adjust costs for FMA instructions.
        Add cases for most logical and float operations.  Recurse into
        most operands.

Co-Authored-By: Dale Johannesen <dalej@apple.com>
Co-Authored-By: Roger Sayle <roger@eyesopen.com>
From-SVN: r85488

gcc/ChangeLog
gcc/config/rs6000/rs6000.c

index 94750622f5131c180eb9a07c6ff593964add50eb..8828ae1191c0abb4567317ae34bedc3c66d0878d 100644 (file)
@@ -1,3 +1,12 @@
+2004-08-03  David Edelsohn  <edelsohn@gnu.org>
+           Dale Johannesen  <dalej@apple.com>
+           Roger Sayle  <roger@eyesopen.com>
+
+       * config/rs6000/rs6000.c (rs6000_rtx_costs): Calculate cost of
+       constants more accurately.  Adjust costs for FMA instructions.
+       Add cases for most logical and float operations.  Recurse into
+       most operands.
+
 2004-08-03  Richard Earnshaw  <rearnsha@arm.com>
 
        * config.gcc (strongarm-*, xscale-*): Add t-arm to tmake_files.
index 773ca9ef487a0d8adb47cbfb1502e457b05ae853..1a9cf8d1fe21507e97b0f549753417d67cc25339 100644 (file)
@@ -16517,21 +16517,105 @@ rs6000_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED,
       /* On the RS/6000, if it is valid in the insn, it is free.
         So this always returns 0.  */
     case CONST_INT:
+      if (((outer_code == SET
+           || outer_code == PLUS
+           || outer_code == MINUS)
+          && (CONST_OK_FOR_LETTER_P (INTVAL (x), 'I')
+              || CONST_OK_FOR_LETTER_P (INTVAL (x), 'L')))
+         || ((outer_code == IOR || outer_code == XOR)
+             && (CONST_OK_FOR_LETTER_P (INTVAL (x), 'K')
+                 || CONST_OK_FOR_LETTER_P (INTVAL (x), 'L')))
+         || (outer_code == AND
+             && (CONST_OK_FOR_LETTER_P (INTVAL (x), 'K')
+                 || CONST_OK_FOR_LETTER_P (INTVAL (x), 'L')
+                 || CONST_OK_FOR_LETTER_P (INTVAL (x), 'T')))
+         || outer_code == ASHIFT
+         || outer_code == ASHIFTRT
+         || outer_code == LSHIFTRT
+         || outer_code == ROTATE
+         || outer_code == ROTATERT
+         || (outer_code == MULT
+             && CONST_OK_FOR_LETTER_P (INTVAL (x), 'I'))
+         || (outer_code == COMPARE
+             && (CONST_OK_FOR_LETTER_P (INTVAL (x), 'I')
+                 || CONST_OK_FOR_LETTER_P (INTVAL (x), 'K'))))
+       {
+         *total = 0;
+         return true;
+       }
+      else if ((outer_code == PLUS
+               && reg_or_add_cint64_operand (x, VOIDmode))
+              || (outer_code == MINUS
+                  && reg_or_sub_cint64_operand (x, VOIDmode))
+              || ((outer_code == SET
+                   || outer_code == IOR
+                   || outer_code == XOR)
+                  && (INTVAL (x)
+                      & ~ (unsigned HOST_WIDE_INT) 0xffffffff) == 0))
+       {
+         *total = COSTS_N_INSNS (1);
+         return true;
+       }
+      /* FALLTHRU */
+
+    case CONST_DOUBLE:
+      if (mode == DImode
+         && ((outer_code == AND
+              && (CONST_OK_FOR_LETTER_P (INTVAL (x), 'K')
+                  || CONST_OK_FOR_LETTER_P (INTVAL (x), 'L')
+                  || CONST_OK_FOR_LETTER_P (INTVAL (x), 'S')))
+             || ((outer_code == IOR || outer_code == XOR)
+                 && CONST_DOUBLE_HIGH (x) == 0
+                 && (CONST_DOUBLE_LOW (x)
+                     & ~ (unsigned HOST_WIDE_INT) 0xffff) == 0)))
+       {
+         *total = 0;
+         return true;
+       }
+      else if (mode == DImode
+              && (outer_code == SET
+                  || outer_code == IOR
+                  || outer_code == XOR)
+              && CONST_DOUBLE_HIGH (x) == 0)
+       {
+         *total = COSTS_N_INSNS (1);
+         return true;
+       }
+      /* FALLTHRU */
+
     case CONST:
+    case HIGH:
     case LABEL_REF:
     case SYMBOL_REF:
-    case CONST_DOUBLE:
-    case HIGH:
-      *total = 0;
+    case MEM:
+      /* When optimizing for size, MEM should be slightly more expensive
+        than generating address, e.g., (plus (reg) (const)).
+        L1 cache latecy is about two instructions.  */
+      *total = optimize_size ? COSTS_N_INSNS (1) + 1 : COSTS_N_INSNS (2);
       return true;
 
     case PLUS:
       if (mode == DFmode)
-       *total = GET_CODE (XEXP (x, 0)) == MULT
-                ? rs6000_cost->dmul
-                : rs6000_cost->fp;
+       {
+         if (GET_CODE (XEXP (x, 0)) == MULT)
+           {
+             /* FNMA accounted in outer NEG.  */
+             if (outer_code == NEG)
+               *total = rs6000_cost->dmul - rs6000_cost->fp;
+             else
+               *total = rs6000_cost->dmul;
+           }
+         else
+           *total = rs6000_cost->fp;
+       }
       else if (mode == SFmode)
-       *total = rs6000_cost->fp;
+       {
+         /* FNMA accounted in outer NEG.  */
+         if (outer_code == NEG && GET_CODE (XEXP (x, 0)) == MULT)
+           *total = 0;
+         else
+           *total = rs6000_cost->fp;
+       }
       else if (GET_CODE (XEXP (x, 0)) == MULT)
        {
          /* The rs6000 doesn't have shift-and-add instructions.  */
@@ -16539,21 +16623,31 @@ rs6000_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED,
          *total += COSTS_N_INSNS (1);
        }
       else
-       *total = ((GET_CODE (XEXP (x, 1)) == CONST_INT
-                 && ((unsigned HOST_WIDE_INT) (INTVAL (XEXP (x, 1))
-                                               + 0x8000) >= 0x10000)
-                 && ((INTVAL (XEXP (x, 1)) & 0xffff) != 0))
-                ? COSTS_N_INSNS (2)
-                : COSTS_N_INSNS (1));
-      return true;
+       *total = COSTS_N_INSNS (1);
+      return false;
 
     case MINUS:
       if (mode == DFmode)
-       *total = GET_CODE (XEXP (x, 0)) == MULT
-                ? rs6000_cost->dmul
-                : rs6000_cost->fp;
+       {
+         if (GET_CODE (XEXP (x, 0)) == MULT)
+           {
+             /* FNMA accounted in outer NEG.  */
+             if (outer_code == NEG)
+               *total = 0;
+             else
+               *total = rs6000_cost->dmul;
+           }
+         else
+           *total = rs6000_cost->fp;
+       }
       else if (mode == SFmode)
-       *total = rs6000_cost->fp;
+       {
+         /* FNMA accounted in outer NEG.  */
+         if (outer_code == NEG && GET_CODE (XEXP (x, 0)) == MULT)
+           *total = 0;
+         else
+           *total = rs6000_cost->fp;
+       }
       else if (GET_CODE (XEXP (x, 0)) == MULT)
        {
          /* The rs6000 doesn't have shift-and-sub instructions.  */
@@ -16562,17 +16656,7 @@ rs6000_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED,
        }
       else
         *total = COSTS_N_INSNS (1);
-      return true;
-
-    case AND:
-    case IOR:
-    case XOR:
-      *total = ((GET_CODE (XEXP (x, 1)) == CONST_INT
-                && (INTVAL (XEXP (x, 1)) & (~ (HOST_WIDE_INT) 0xffff)) != 0
-                && ((INTVAL (XEXP (x, 1)) & 0xffff) != 0))
-               ? COSTS_N_INSNS (2)
-               : COSTS_N_INSNS (1));
-      return true;
+      return false;
 
     case MULT:
       if (GET_CODE (XEXP (x, 1)) == CONST_INT)
@@ -16583,6 +16667,10 @@ rs6000_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED,
          else
            *total = rs6000_cost->mulsi_const;
        }
+      /* FMA accounted in outer PLUS/MINUS.  */
+      else if ((mode == DFmode || mode == SFmode)
+              && (outer_code == PLUS || outer_code == MINUS))
+       *total = 0;
       else if (mode == DFmode)
        *total = rs6000_cost->dmul;
       else if (mode == SFmode)
@@ -16591,7 +16679,7 @@ rs6000_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED,
        *total = rs6000_cost->muldi;
       else
        *total = rs6000_cost->mulsi;
-      return true;
+      return false;
 
     case DIV:
     case MOD:
@@ -16599,13 +16687,13 @@ rs6000_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED,
        {
          *total = mode == DFmode ? rs6000_cost->ddiv
                                  : rs6000_cost->sdiv;
-         return true;
+         return false;
        }
       if (GET_CODE (XEXP (x, 1)) == CONST_INT
          && exact_log2 (INTVAL (XEXP (x, 1))) >= 0)
        {
          *total = COSTS_N_INSNS (2);
-         return true;
+         return false;
        }
       /* FALLTHRU */
 
@@ -16615,35 +16703,60 @@ rs6000_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED,
        *total = rs6000_cost->divdi;
       else
        *total = rs6000_cost->divsi;
-      return true;
+      return false;
 
     case FFS:
       *total = COSTS_N_INSNS (4);
-      return true;
-
-    case NEG:
-    case ABS:
-      if (FLOAT_MODE_P (mode))
-       *total = rs6000_cost->fp;
-      else
-       *total = COSTS_N_INSNS (1);
-      return true;
-
-    case MEM:
-      /* MEM should be slightly more expensive than (plus (reg) (const)).  */
-      *total = COSTS_N_INSNS (1) + 1;
-      return true;
+      return false;
 
     case NOT:
+      if (outer_code == AND || outer_code == IOR || outer_code == XOR)
+       {
+         *total = 0;
+         return false;
+       }
+      /* FALLTHRU */
+
+    case AND:
+    case IOR:
+    case XOR:
+    case ASHIFT:
+    case ASHIFTRT:
+    case LSHIFTRT:
+    case ROTATE:
+    case ROTATERT:
     case SIGN_EXTEND:
     case ZERO_EXTEND:
-    case COMPARE:
+      if (outer_code == TRUNCATE
+         && GET_CODE (XEXP (x, 0)) == MULT)
+       {
+         if (mode == DImode)
+           *total = rs6000_cost->muldi;
+         else
+           *total = rs6000_cost->mulsi;
+         return true;
+       }
       *total = COSTS_N_INSNS (1);
-      break;
+      return false;
 
+    case COMPARE:
+    case NEG:
+    case ABS:
+      if (!FLOAT_MODE_P (mode))
+       {
+         *total = COSTS_N_INSNS (1);
+         return false;
+       }
+      /* FALLTHRU */
+
+    case FLOAT:
+    case UNSIGNED_FLOAT:
+    case FIX:
+    case UNSIGNED_FIX:
+    case FLOAT_EXTEND:
     case FLOAT_TRUNCATE:
       *total = rs6000_cost->fp;
-      return true;
+      return false;
 
     case UNSPEC:
       switch (XINT (x, 1))
@@ -16664,6 +16777,13 @@ rs6000_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED,
          *total = COSTS_N_INSNS (1);
          return true;
        }
+      else if (FLOAT_MODE_P (mode)
+              && TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS)
+       {
+         *total = rs6000_cost->fp;
+         return false;
+       }
+
       break;
 
     default: