OSDN Git Service

PR target/19597
authorsayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 9 Feb 2005 14:43:28 +0000 (14:43 +0000)
committersayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 9 Feb 2005 14:43:28 +0000 (14:43 +0000)
* config/avr/avr.c (default_rtx_costs): Delete.
(avr_operand_rtx_cost): New function.
(avr_rtx_costs): Completely rewrite.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@94766 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/avr/avr.c

index 13f8d9a..b8675fb 100644 (file)
@@ -1,3 +1,10 @@
+2005-02-09  Roger Sayle  <roger@eyesopen.com>
+
+       PR target/19597
+       * config/avr/avr.c (default_rtx_costs): Delete.
+       (avr_operand_rtx_cost): New function.
+       (avr_rtx_costs): Completely rewrite.
+
 2005-02-08  Hans-Peter Nilsson  <hp@axis.com>
 
        PR target/19806
index fffb7ba..42dbf02 100644 (file)
@@ -74,7 +74,7 @@ static unsigned int avr_section_type_flags (tree, const char *, int);
 static void avr_reorg (void);
 static void avr_asm_out_ctor (rtx, int);
 static void avr_asm_out_dtor (rtx, int);
-static int default_rtx_costs (rtx, enum rtx_code, enum rtx_code);
+static int avr_operand_rtx_cost (rtx, enum machine_mode, enum rtx_code);
 static bool avr_rtx_costs (rtx, int, int, int *);
 static int avr_address_cost (rtx);
 static bool avr_return_in_memory (tree, tree);
@@ -4820,110 +4820,558 @@ order_regs_for_local_alloc (void)
       reg_alloc_order[i] = order[i];
 }
 
-/* Calculate the cost of X code of the expression in which it is contained,
-   found in OUTER_CODE */
+
+/* Mutually recursive subroutine of avr_rtx_cost for calculating the
+   cost of an RTX operand given its context.  X is the rtx of the
+   operand, MODE is its mode, and OUTER is the rtx_code of this
+   operand's parent operator.  */
 
 static int
-default_rtx_costs (rtx X, enum rtx_code code, enum rtx_code outer_code)
+avr_operand_rtx_cost (rtx x, enum machine_mode mode, enum rtx_code outer)
 {
-  int cost=0;
+  enum rtx_code code = GET_CODE (x);
+  int total;
+
   switch (code)
     {
-    case SYMBOL_REF:
-    case LABEL_REF:
-      cost = 2 * GET_MODE_SIZE (GET_MODE (X));
-      break;
-    case MEM:
-      if (outer_code != SET)
-       cost = 1;
-      if (GET_CODE (XEXP (X,0)) == SYMBOL_REF)
-       cost += 2 * GET_MODE_SIZE (GET_MODE (X));
-      else
-       cost += GET_MODE_SIZE (GET_MODE (X));
-      break;
+    case REG:
+    case SUBREG:
+      return 0;
+
     case CONST_INT:
-      cost = 0;
-      break;
-    case SIGN_EXTEND:
-      if (outer_code == SET)
-       cost = GET_MODE_SIZE (GET_MODE (X));
-      else
-       cost = -GET_MODE_SIZE (GET_MODE (X));
-      break;
-    case ZERO_EXTEND:
-      if (outer_code == SET)
-       cost = GET_MODE_SIZE (GET_MODE (X));
-      else
-       cost = -1;
-      break;
-    case PLUS:
-    case MINUS:
-      if (outer_code == SET)
-       {
-         if (X == stack_pointer_rtx)
-           cost = -10;
-         else if (GET_CODE (XEXP (X,1)) == CONST_INT)
-           cost = (INTVAL (XEXP (X,1)) <= 63 ? 1 :
-                    GET_MODE_SIZE (GET_MODE (X)));
-         else
-           cost = GET_MODE_SIZE (GET_MODE (X));
-       }
-      break;
-    case COMPARE:
-      if (GET_CODE (XEXP (X,1)) == CONST_INT)
-       cost = GET_MODE_SIZE (GET_MODE (XEXP (X,0)));
-      break;
+    case CONST_DOUBLE:
+      return COSTS_N_INSNS (GET_MODE_SIZE (mode));
+
     default:
       break;
     }
-  return cost;
+
+  total = 0;
+  avr_rtx_costs (x, code, outer, &total);
+  return total;
 }
 
+/* The AVR backend's rtx_cost function.  X is rtx expression whose cost
+   is to be calculated.  Return true if the complete cost has been
+   computed, and false if subexpressions should be scanned.  In either
+   case, *TOTAL contains the cost result.  */
+
 static bool
 avr_rtx_costs (rtx x, int code, int outer_code, int *total)
 {
-  int cst;
+  enum machine_mode mode = GET_MODE (x);
+  HOST_WIDE_INT val;
 
   switch (code)
     {
     case CONST_INT:
-      if (outer_code == PLUS
-         || outer_code == IOR
-         || outer_code == AND
-         || outer_code == MINUS
-         || outer_code == SET
-         || INTVAL (x) == 0)
+    case CONST_DOUBLE:
+      /* Immediate constants are as cheap as registers.  */
+      *total = 0;
+      return true;
+
+    case MEM:
+    case CONST:
+    case LABEL_REF:
+    case SYMBOL_REF:
+      *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
+      return true;
+
+    case NEG:
+      switch (mode)
        {
-          *total = 2;
-         return true;
+       case QImode:
+       case SFmode:
+         *total = COSTS_N_INSNS (1);
+         break;
+
+       case HImode:
+         *total = COSTS_N_INSNS (3);
+         break;
+
+       case SImode:
+         *total = COSTS_N_INSNS (7);
+         break;
+
+       default:
+         return false;
        }
-      if (outer_code == COMPARE
-         && INTVAL (x) >= 0
-         && INTVAL (x) <= 255)
+      *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
+      return true;
+
+    case ABS:
+      switch (mode)
        {
-         *total = 2;
-         return true;
+       case QImode:
+       case SFmode:
+         *total = COSTS_N_INSNS (1);
+         break;
+
+       default:
+         return false;
        }
-      /* FALLTHRU */
+      *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
+      return true;
 
-    case CONST:
-    case LABEL_REF:
-    case SYMBOL_REF:
-    case CONST_DOUBLE:
-      *total = 4;
+    case NOT:
+      *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
+      *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
       return true;
 
-    default:
-      cst = default_rtx_costs (x, code, outer_code);
-      if (cst > 0)
+    case ZERO_EXTEND:
+      *total = COSTS_N_INSNS (GET_MODE_SIZE (mode)
+                             - GET_MODE_SIZE (GET_MODE (XEXP (x, 0))));
+      *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
+      return true;
+
+    case SIGN_EXTEND:
+      *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) + 2
+                             - GET_MODE_SIZE (GET_MODE (XEXP (x, 0))));
+      *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
+      return true;
+
+    case PLUS:
+      switch (mode)
+       {
+       case QImode:
+         *total = COSTS_N_INSNS (1);
+         if (GET_CODE (XEXP (x, 1)) != CONST_INT)
+           *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+         break;
+
+       case HImode:
+         if (GET_CODE (XEXP (x, 1)) != CONST_INT)
+           {
+             *total = COSTS_N_INSNS (2);
+             *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+           }
+         else if (INTVAL (XEXP (x, 1)) >= -63 && INTVAL (XEXP (x, 1)) <= 63)
+           *total = COSTS_N_INSNS (1);
+         else
+           *total = COSTS_N_INSNS (2);
+         break;
+
+       case SImode:
+         if (GET_CODE (XEXP (x, 1)) != CONST_INT)
+           {
+             *total = COSTS_N_INSNS (4);
+             *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+           }
+         else if (INTVAL (XEXP (x, 1)) >= -63 && INTVAL (XEXP (x, 1)) <= 63)
+           *total = COSTS_N_INSNS (1);
+         else
+           *total = COSTS_N_INSNS (4);
+         break;
+
+       default:
+         return false;
+       }
+      *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
+      return true;
+
+    case MINUS:
+    case AND:
+    case IOR:
+      *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
+      *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
+      if (GET_CODE (XEXP (x, 1)) != CONST_INT)
+          *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+      return true;
+
+    case XOR:
+      *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
+      *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
+      *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+      return true;
+
+    case MULT:
+      switch (mode)
+       {
+       case QImode:
+         if (AVR_ENHANCED)
+           *total = COSTS_N_INSNS (optimize_size ? 3 : 4);
+         else if (optimize_size)
+           *total = COSTS_N_INSNS (AVR_MEGA ? 2 : 1);
+         else
+           return false;
+
+       case HImode:
+         if (AVR_ENHANCED)
+           *total = COSTS_N_INSNS (optimize_size ? 7 : 10);
+         else if (optimize_size)
+           *total = COSTS_N_INSNS (AVR_MEGA ? 2 : 1);
+         else
+           return false;
+
+       default:
+         return false;
+       }
+      *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
+      *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+      return true;
+
+    case DIV:
+    case MOD:
+    case UDIV:
+    case UMOD:
+      if (optimize_size)
+       *total = COSTS_N_INSNS (AVR_MEGA ? 2 : 1);
+      else
+       return false;
+      *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
+      *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+      return true;
+
+    case ASHIFT:
+      switch (mode)
+       {
+       case QImode:
+         if (GET_CODE (XEXP (x, 1)) != CONST_INT)
+           {
+             *total = COSTS_N_INSNS (optimize_size ? 4 : 17);
+             *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+           }
+         else
+           {
+             val = INTVAL (XEXP (x, 1));
+             if (val == 7)
+               *total = COSTS_N_INSNS (3);
+             else if (val >= 0 && val <= 7)
+               *total = COSTS_N_INSNS (val);
+             else
+               *total = COSTS_N_INSNS (1);
+           }
+         break;
+
+       case HImode:
+         if (GET_CODE (XEXP (x, 1)) != CONST_INT)
+           {
+             *total = COSTS_N_INSNS (optimize_size ? 5 : 41);
+             *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+           }
+         else
+           switch (INTVAL (XEXP (x, 1)))
+             {
+             case 0:
+               *total = 0;
+               break;
+             case 1:
+             case 8:
+               *total = COSTS_N_INSNS (2);
+               break;
+             case 9:
+               *total = COSTS_N_INSNS (3);
+               break;
+             case 2:
+             case 3:
+             case 10:
+             case 15:
+               *total = COSTS_N_INSNS (4);
+               break;
+             case 7:
+             case 11:
+             case 12:
+               *total = COSTS_N_INSNS (5);
+               break;
+             case 4:
+               *total = COSTS_N_INSNS (optimize_size ? 5 : 8);
+               break;
+             case 6:
+               *total = COSTS_N_INSNS (optimize_size ? 5 : 9);
+               break;
+             case 5:
+               *total = COSTS_N_INSNS (optimize_size ? 5 : 10);
+               break;
+             default:
+               *total = COSTS_N_INSNS (optimize_size ? 5 : 41);
+               *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+             }
+         break;
+
+       case SImode:
+         if (GET_CODE (XEXP (x, 1)) != CONST_INT)
+           {
+             *total = COSTS_N_INSNS (optimize_size ? 7 : 113);
+             *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+           }
+         else
+           switch (INTVAL (XEXP (x, 1)))
+             {
+             case 0:
+               *total = 0;
+               break;
+             case 24:
+               *total = COSTS_N_INSNS (3);
+               break;
+             case 1:
+             case 8:
+             case 16:
+               *total = COSTS_N_INSNS (4);
+               break;
+             case 31:
+               *total = COSTS_N_INSNS (6);
+               break;
+             case 2:
+               *total = COSTS_N_INSNS (optimize_size ? 7 : 8);
+               break;
+             default:
+               *total = COSTS_N_INSNS (optimize_size ? 7 : 113);
+               *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+             }
+         break;
+
+       default:
+         return false;
+       }
+      *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
+      return true;
+
+    case ASHIFTRT:
+      switch (mode)
+       {
+       case QImode:
+         if (GET_CODE (XEXP (x, 1)) != CONST_INT)
+           {
+             *total = COSTS_N_INSNS (optimize_size ? 4 : 17);
+             *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+           }
+         else
+           {
+             val = INTVAL (XEXP (x, 1));
+             if (val == 6)
+               *total = COSTS_N_INSNS (4);
+             else if (val == 7)
+               *total = COSTS_N_INSNS (2);
+             else if (val >= 0 && val <= 7)
+               *total = COSTS_N_INSNS (val);
+             else
+               *total = COSTS_N_INSNS (1);
+           }
+         break;
+
+       case HImode:
+         if (GET_CODE (XEXP (x, 1)) != CONST_INT)
+           {
+             *total = COSTS_N_INSNS (optimize_size ? 5 : 41);
+             *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+           }
+         else
+           switch (INTVAL (XEXP (x, 1)))
+             {
+             case 0:
+               *total = 0;
+               break;
+             case 1:
+               *total = COSTS_N_INSNS (2);
+               break;
+             case 15:
+               *total = COSTS_N_INSNS (3);
+               break;
+             case 2:
+             case 7:
+              case 8:
+              case 9:
+               *total = COSTS_N_INSNS (4);
+               break;
+              case 10:
+             case 14:
+               *total = COSTS_N_INSNS (5);
+               break;
+              case 11:
+                *total = COSTS_N_INSNS (optimize_size ? 5 : 6);
+               break;
+              case 12:
+                *total = COSTS_N_INSNS (optimize_size ? 5 : 7);
+               break;
+              case 6:
+             case 13:
+                *total = COSTS_N_INSNS (optimize_size ? 5 : 8);
+               break;
+             default:
+               *total = COSTS_N_INSNS (optimize_size ? 5 : 41);
+               *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+             }
+         break;
+
+       case SImode:
+         if (GET_CODE (XEXP (x, 1)) != CONST_INT)
+           {
+             *total = COSTS_N_INSNS (optimize_size ? 7 : 113);
+             *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+           }
+         else
+           switch (INTVAL (XEXP (x, 1)))
+             {
+             case 0:
+               *total = 0;
+               break;
+             case 1:
+               *total = COSTS_N_INSNS (4);
+               break;
+             case 8:
+             case 16:
+             case 24:
+               *total = COSTS_N_INSNS (6);
+               break;
+             case 2:
+               *total = COSTS_N_INSNS (optimize_size ? 7 : 8);
+               break;
+             case 31:
+               *total = COSTS_N_INSNS (AVR_ENHANCED ? 4 : 5);
+               break;
+             default:
+               *total = COSTS_N_INSNS (optimize_size ? 7 : 113);
+               *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+             }
+         break;
+
+       default:
+         return false;
+       }
+      *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
+      return true;
+
+    case LSHIFTRT:
+      switch (mode)
+       {
+       case QImode:
+         if (GET_CODE (XEXP (x, 1)) != CONST_INT)
+           {
+             *total = COSTS_N_INSNS (optimize_size ? 4 : 17);
+             *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+           }
+         else
+           {
+             val = INTVAL (XEXP (x, 1));
+             if (val == 7)
+               *total = COSTS_N_INSNS (3);
+             else if (val >= 0 && val <= 7)
+               *total = COSTS_N_INSNS (val);
+             else
+               *total = COSTS_N_INSNS (1);
+           }
+         break;
+
+       case HImode:
+         if (GET_CODE (XEXP (x, 1)) != CONST_INT)
+           {
+             *total = COSTS_N_INSNS (optimize_size ? 5 : 41);
+             *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+           }
+         else
+           switch (INTVAL (XEXP (x, 1)))
+             {
+             case 0:
+               *total = 0;
+               break;
+             case 1:
+             case 8:
+               *total = COSTS_N_INSNS (2);
+               break;
+             case 9:
+               *total = COSTS_N_INSNS (3);
+               break;
+             case 2:
+             case 10:
+             case 15:
+               *total = COSTS_N_INSNS (4);
+               break;
+             case 7:
+              case 11:
+               *total = COSTS_N_INSNS (5);
+               break;
+             case 3:
+             case 12:
+             case 13:
+             case 14:
+               *total = COSTS_N_INSNS (optimize_size ? 5 : 6);
+               break;
+             case 4:
+               *total = COSTS_N_INSNS (optimize_size ? 5 : 7);
+               break;
+             case 5:
+             case 6:
+               *total = COSTS_N_INSNS (optimize_size ? 5 : 9);
+               break;
+             default:
+               *total = COSTS_N_INSNS (optimize_size ? 5 : 41);
+               *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+             }
+         break;
+
+       case SImode:
+         if (GET_CODE (XEXP (x, 1)) != CONST_INT)
+           {
+             *total = COSTS_N_INSNS (optimize_size ? 7 : 113);
+             *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+           }
+         else
+           switch (INTVAL (XEXP (x, 1)))
+             {
+             case 0:
+               *total = 0;
+               break;
+             case 1:
+               *total = COSTS_N_INSNS (4);
+               break;
+             case 2:
+               *total = COSTS_N_INSNS (optimize_size ? 7 : 8);
+               break;
+             case 8:
+             case 16:
+             case 24:
+               *total = COSTS_N_INSNS (4);
+               break;
+             case 31:
+               *total = COSTS_N_INSNS (6);
+               break;
+             default:
+               *total = COSTS_N_INSNS (optimize_size ? 7 : 113);
+               *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+             }
+         break;
+
+       default:
+         return false;
+       }
+      *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
+      return true;
+
+    case COMPARE:
+      switch (GET_MODE (XEXP (x, 0)))
        {
-         *total = cst;
-         return true;
+       case QImode:
+         *total = COSTS_N_INSNS (1);
+         if (GET_CODE (XEXP (x, 1)) != CONST_INT)
+           *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+         break;
+
+        case HImode:
+         *total = COSTS_N_INSNS (2);
+         if (GET_CODE (XEXP (x, 1)) != CONST_INT)
+            *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+         else if (INTVAL (XEXP (x, 1)) != 0)
+           *total += COSTS_N_INSNS (1);
+          break;
+
+        case SImode:
+          *total = COSTS_N_INSNS (4);
+          if (GET_CODE (XEXP (x, 1)) != CONST_INT)
+            *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
+         else if (INTVAL (XEXP (x, 1)) != 0)
+           *total += COSTS_N_INSNS (3);
+          break;
+
+       default:
+         return false;
        }
-      else if (cst < 0)
-       *total += -cst;
-      return false;
+      *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
+      return true;
+
+    default:
+      break;
     }
+  return false;
 }
 
 /* Calculate the cost of a memory address.  */