]> gcc.gnu.org Git - gcc.git/commitdiff
mn10300: Clean up costing.
authorRichard Henderson <rth@redhat.com>
Tue, 11 Jan 2011 18:52:43 +0000 (10:52 -0800)
committerRichard Henderson <rth@gcc.gnu.org>
Tue, 11 Jan 2011 18:52:43 +0000 (10:52 -0800)
Address, register, memory and rtx costs bore little relation to reality.

From-SVN: r168678

gcc/ChangeLog
gcc/config/mn10300/mn10300-protos.h
gcc/config/mn10300/mn10300.c
gcc/config/mn10300/mn10300.h

index 2785470e00b161add54952f9755608741a8dfe1b..1f80f216960960ecbcf415f1ddfb2aea3f12f733 100644 (file)
@@ -1,5 +1,19 @@
 2011-01-11  Richard Henderson  <rth@redhat.com>
 
+       * config/mn10300/mn10300.c (mn10300_address_cost): Remove forward
+       declaration.  Rewrite for both speed and size.
+       (mn10300_address_cost_1): Remove.
+       (mn10300_register_move_cost): New.
+       (mn10300_memory_move_cost): New.
+       (mn10300_rtx_costs): Rewrite for both speed and size.  Don't handle
+       ZERO_EXTRACT.  Do handle UNSPEC, arithmetic, logicals, compare,
+       extensions, shifts, BSWAP, CLZ.
+       (mn10300_wide_const_load_uses_clr): Remove.
+       (TARGET_REGISTER_MOVE_COST): New.
+       (TARGET_MEMORY_MOVE_COST): New.
+       * config/mn10300/mn10300-protos.h: Update.
+       * config/mn10300/mn10300.h (REGISTER_MOVE_COST): Remove.
+
        * config/mn10300/constraints.md ("R", "T"): Remove constraints.
        * config/mn10300/mn10300.c (mn10300_mask_ok_for_mem_btst): Remove.
        * config/mn10300/mn10300-protos.h: Update.
index 8979eb41d4568ec8f0ab98af4f0105174dfbd326..d6cf850a52ce982b7793767fc39dddded327ad74 100644 (file)
@@ -39,7 +39,6 @@ extern Rclas mn10300_secondary_reload_class (Rclas, Mmode, rtx);
 extern Mmode mn10300_select_cc_mode (rtx);
 extern int   mn10300_store_multiple_operation (rtx, Mmode);
 extern int   mn10300_symbolic_operand (rtx, Mmode);
-extern bool  mn10300_wide_const_load_uses_clr (rtx operands[2]);
 #endif /* RTX_CODE */
 
 extern int   mn10300_can_use_return_insn (void);
index e801c47b3fa2b5f9f60cada4e565ce6c10da0d8f..d39b42785c5439c4d61bcfa0e536a83ccede7bad 100644 (file)
@@ -75,8 +75,6 @@ enum processor_type mn10300_tune_cpu = PROCESSOR_DEFAULT;
                                || df_regs_ever_live_p (16)     \
                                || df_regs_ever_live_p (17)))
 
-static int mn10300_address_cost (rtx, bool);
-
 /* Implement TARGET_OPTION_OPTIMIZATION_TABLE.  */
 static const struct default_options mn10300_option_optimization_table[] =
   {
@@ -2034,180 +2032,340 @@ mn10300_legitimate_constant_p (rtx x)
   return true;
 }
 
+/* For addresses, costs are relative to "MOV (Rm),Rn".  For AM33 this is
+   the 3-byte fully general instruction; for MN103 this is the 2-byte form
+   with an address register.  */
+
 static int
-mn10300_address_cost_1 (rtx x, int *unsig)
+mn10300_address_cost (rtx x, bool speed)
 {
+  HOST_WIDE_INT i;
+  rtx base, index;
+
   switch (GET_CODE (x))
     {
+    case CONST:
+    case SYMBOL_REF:
+    case LABEL_REF:
+      /* We assume all of these require a 32-bit constant, even though
+        some symbol and label references can be relaxed.  */
+      return speed ? 1 : 4;
+
     case REG:
-      switch (REGNO_REG_CLASS (REGNO (x)))
+    case SUBREG:
+    case POST_INC:
+      return 0;
+
+    case POST_MODIFY:
+      /* Assume any symbolic offset is a 32-bit constant.  */
+      i = (CONST_INT_P (XEXP (x, 1)) ? INTVAL (XEXP (x, 1)) : 0x12345678);
+      if (IN_RANGE (i, -128, 127))
+       return speed ? 0 : 1;
+      if (speed)
+       return 1;
+      if (IN_RANGE (i, -0x800000, 0x7fffff))
+       return 3;
+      return 4;
+
+    case PLUS:
+      base = XEXP (x, 0);
+      index = XEXP (x, 1);
+      if (register_operand (index, SImode))
        {
-       case SP_REGS:
-         *unsig = 1;
-         return 0;
+         /* Attempt to minimize the number of registers in the address.
+            This is similar to what other ports do.  */
+         if (register_operand (base, SImode))
+           return 1;
 
-       case ADDRESS_REGS:
-         return 1;
+         base = XEXP (x, 1);
+         index = XEXP (x, 0);
+       }
 
-       case DATA_REGS:
-       case EXTENDED_REGS:
-       case FP_REGS:
-         return 3;
+      /* Assume any symbolic offset is a 32-bit constant.  */
+      i = (CONST_INT_P (XEXP (x, 1)) ? INTVAL (XEXP (x, 1)) : 0x12345678);
+      if (IN_RANGE (i, -128, 127))
+       return speed ? 0 : 1;
+      if (IN_RANGE (i, -32768, 32767))
+       return speed ? 0 : 2;
+      return speed ? 2 : 6;
 
-       case NO_REGS:
-         return 5;
+    default:
+      return rtx_cost (x, MEM, speed);
+    }
+}
 
-       default:
-         gcc_unreachable ();
-       }
+/* Implement the TARGET_REGISTER_MOVE_COST hook.
 
-    case PLUS:
-    case MINUS:
-    case ASHIFT:
-    case AND:
-    case IOR:
-      return (mn10300_address_cost_1 (XEXP (x, 0), unsig)
-             + mn10300_address_cost_1 (XEXP (x, 1), unsig));
+   Recall that the base value of 2 is required by assumptions elsewhere
+   in the body of the compiler, and that cost 2 is special-cased as an
+   early exit from reload meaning no work is required.  */
 
-    case EXPR_LIST:
-    case SUBREG:
-    case MEM:
-      return mn10300_address_cost (XEXP (x, 0), !optimize_size);
+static int
+mn10300_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
+                           reg_class_t ifrom, reg_class_t ito)
+{
+  enum reg_class from = (enum reg_class) ifrom;
+  enum reg_class to = (enum reg_class) ito;
+  enum reg_class scratch, test;
+
+  /* Simplify the following code by unifying the fp register classes.  */
+  if (to == FP_ACC_REGS)
+    to = FP_REGS;
+  if (from == FP_ACC_REGS)
+    from = FP_REGS;
+
+  /* Diagnose invalid moves by costing them as two moves.  */
+
+  scratch = NO_REGS;
+  test = from;
+  if (to == SP_REGS)
+    scratch = (TARGET_AM33 ? GENERAL_REGS : ADDRESS_REGS);
+  else if (to == FP_REGS && to != from)
+    scratch = GENERAL_REGS;
+  else
+    {
+      test = to;
+      if (from == SP_REGS)
+       scratch = (TARGET_AM33 ? GENERAL_REGS : ADDRESS_REGS);
+      else if (from == FP_REGS && to != from)
+       scratch = GENERAL_REGS;
+    }
+  if (scratch != NO_REGS && !reg_class_subset_p (test, scratch))
+    return (mn10300_register_move_cost (VOIDmode, from, scratch)
+           + mn10300_register_move_cost (VOIDmode, scratch, to));
 
-    case ZERO_EXTEND:
-      *unsig = 1;
-      return mn10300_address_cost_1 (XEXP (x, 0), unsig);
+  /* From here on, all we need consider are legal combinations.  */
 
-    case CONST_INT:
-      if (INTVAL (x) == 0)
-       return 0;
-      if (INTVAL (x) + (*unsig ? 0 : 0x80) < 0x100)
-       return 1;
-      if (INTVAL (x) + (*unsig ? 0 : 0x8000) < 0x10000)
-       return 3;
-      if (INTVAL (x) + (*unsig ? 0 : 0x800000) < 0x1000000)
-       return 5;
-      return 7;
+  if (optimize_size)
+    {
+      /* The scale here is bytes * 2.  */
 
-    case CONST:
-    case SYMBOL_REF:
-    case LABEL_REF:
-      return 8;
+      if (from == to && (to == ADDRESS_REGS || to == DATA_REGS))
+       return 2;
 
-    default:
-      gcc_unreachable ();
+      if (from == SP_REGS)
+       return (to == ADDRESS_REGS ? 2 : 6);
+
+      /* For MN103, all remaining legal moves are two bytes.  */
+      if (TARGET_AM33)
+       return 4;
+
+      if (to == SP_REGS)
+       return (from == ADDRESS_REGS ? 4 : 6);
+
+      if ((from == ADDRESS_REGS || from == DATA_REGS)
+          && (to == ADDRESS_REGS || to == DATA_REGS))
+       return 4;
+
+      if (to == EXTENDED_REGS)
+       return (to == from ? 6 : 4);
 
+      /* What's left are SP_REGS, FP_REGS, or combinations of the above.  */
+      return 6;
+    }
+  else
+    {
+      /* The scale here is cycles * 2.  */
+
+      if (to == FP_REGS)
+       return 8;
+      if (from == FP_REGS)
+       return 4;
+
+      /* All legal moves between integral registers are single cycle.  */
+      return 2;
     }
 }
 
+/* Implement the TARGET_MEMORY_MOVE_COST hook.
+
+   Given lack of the form of the address, this must be speed-relative,
+   though we should never be less expensive than a size-relative register
+   move cost above.  This is not a problem.  */
+
 static int
-mn10300_address_cost (rtx x, bool speed ATTRIBUTE_UNUSED)
+mn10300_memory_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED, 
+                         reg_class_t iclass, bool in ATTRIBUTE_UNUSED)
 {
-  int s = 0;
-  return mn10300_address_cost_1 (x, &s);
+  enum reg_class rclass = (enum reg_class) iclass;
+
+  if (rclass == FP_REGS)
+    return 8;
+  return 6;
 }
 
+/* Implement the TARGET_RTX_COSTS hook.
+
+   Speed-relative costs are relative to COSTS_N_INSNS, which is intended
+   to represent cycles.  Size-relative costs are in bytes.  */
+
 static bool
-mn10300_rtx_costs (rtx x, int code, int outer_code, int *total,
-                  bool speed ATTRIBUTE_UNUSED)
+mn10300_rtx_costs (rtx x, int code, int outer_code, int *ptotal, bool speed)
 {
+  /* This value is used for SYMBOL_REF etc where we want to pretend
+     we have a full 32-bit constant.  */
+  HOST_WIDE_INT i = 0x12345678;
+  int total;
+
   switch (code)
     {
     case CONST_INT:
-      /* Zeros are extremely cheap.  */
-      if (INTVAL (x) == 0 && (outer_code == SET || outer_code == COMPARE))
-       *total = 0;
-      /* If it fits in 8 bits, then it's still relatively cheap.  */
-      else if (INT_8_BITS (INTVAL (x)))
-       *total = 1;
-      /* This is the "base" cost, includes constants where either the
-        upper or lower 16bits are all zeros.  */
-      else if (INT_16_BITS (INTVAL (x))
-              || (INTVAL (x) & 0xffff) == 0
-              || (INTVAL (x) & 0xffff0000) == 0)
-       *total = 2;
+      i = INTVAL (x);
+    do_int_costs:
+      if (speed)
+       {
+         if (outer_code == SET)
+           {
+             /* 16-bit integer loads have latency 1, 32-bit loads 2.  */
+             if (IN_RANGE (i, -32768, 32767))
+               total = COSTS_N_INSNS (1);
+             else
+               total = COSTS_N_INSNS (2);
+           }
+         else
+           {
+             /* 16-bit integer operands don't affect latency;
+                24-bit and 32-bit operands add a cycle.  */
+             if (IN_RANGE (i, -32768, 32767))
+               total = 0;
+             else
+               total = COSTS_N_INSNS (1);
+           }
+       }
       else
-       *total = 4;
-      return true;
+       {
+         if (outer_code == SET)
+           {
+             if (i == 0)
+               total = 1;
+             else if (IN_RANGE (i, -128, 127))
+               total = 2;
+             else if (IN_RANGE (i, -32768, 32767))
+               total = 3;
+             else
+               total = 6;
+           }
+         else
+           {
+             /* Reference here is ADD An,Dn, vs ADD imm,Dn.  */
+             if (IN_RANGE (i, -128, 127))
+               total = 0;
+             else if (IN_RANGE (i, -32768, 32767))
+               total = 2;
+             else if (TARGET_AM33 && IN_RANGE (i, -0x01000000, 0x00ffffff))
+               total = 3;
+             else
+               total = 4;
+           }
+       }
+      goto alldone;
 
     case CONST:
     case LABEL_REF:
     case SYMBOL_REF:
-      /* These are more costly than a CONST_INT, but we can relax them,
-        so they're less costly than a CONST_DOUBLE.  */
-      *total = 6;
-      return true;
-
     case CONST_DOUBLE:
-      /* We don't optimize CONST_DOUBLEs well nor do we relax them well,
-        so their cost is very high.  */
-      *total = 8;
-      return true;
-
-    case ZERO_EXTRACT:
-      /* This is cheap, we can use btst.  */
-      if (outer_code == COMPARE)
-       *total = 0;
-      return false;
+      /* We assume all of these require a 32-bit constant, even though
+        some symbol and label references can be relaxed.  */
+      goto do_int_costs;
 
-   /* ??? This probably needs more work.  */
-    case MOD:
-    case DIV:
-    case MULT:
-      *total = 8;
-      return true;
+    case UNSPEC:
+      switch (XINT (x, 1))
+       {
+       case UNSPEC_PIC:
+       case UNSPEC_GOT:
+       case UNSPEC_GOTOFF:
+       case UNSPEC_PLT:
+       case UNSPEC_GOTSYM_OFF:
+         /* The PIC unspecs also resolve to a 32-bit constant.  */
+         goto do_int_costs;
 
-    default:
-      return false;
-    }
-}
+       default:
+         /* Assume any non-listed unspec is some sort of arithmetic.  */
+         goto do_arith_costs;
+       }
 
-/* Check whether a constant used to initialize a DImode or DFmode can
-   use a clr instruction.  The code here must be kept in sync with
-   movdf and movdi.  */
+    case PLUS:
+      /* Notice the size difference of INC and INC4.  */
+      if (!speed && outer_code == SET && CONST_INT_P (XEXP (x, 1)))
+       {
+         i = INTVAL (XEXP (x, 1));
+         if (i == 1 || i == 4)
+           {
+             total = 1 + rtx_cost (XEXP (x, 0), PLUS, speed);
+             goto alldone;
+           }
+       }
+      goto do_arith_costs;
+       
+    case MINUS:
+    case AND:
+    case IOR:
+    case XOR:
+    case NOT:
+    case NEG:
+    case ZERO_EXTEND:
+    case SIGN_EXTEND:
+    case COMPARE:
+    case BSWAP:
+    case CLZ:
+    do_arith_costs:
+      total = (speed ? COSTS_N_INSNS (1) : 2);
+      break;
 
-bool
-mn10300_wide_const_load_uses_clr (rtx operands[2])
-{
-  long val[2] = {0, 0};
+    case ASHIFT:
+      /* Notice the size difference of ASL2 and variants.  */
+      if (!speed && CONST_INT_P (XEXP (x, 1)))
+       switch (INTVAL (XEXP (x, 1)))
+         {
+         case 1:
+         case 2:
+           total = 1;
+           goto alldone;
+         case 3:
+         case 4:
+           total = 2;
+           goto alldone;
+         }
+      /* FALLTHRU */
 
-  if ((! REG_P (operands[0]))
-      || REGNO_REG_CLASS (REGNO (operands[0])) != DATA_REGS)
-    return false;
+    case ASHIFTRT:
+    case LSHIFTRT:
+      total = (speed ? COSTS_N_INSNS (1) : 3);
+      goto alldone;
 
-  switch (GET_CODE (operands[1]))
-    {
-    case CONST_INT:
-      {
-       rtx low, high;
-       split_double (operands[1], &low, &high);
-       val[0] = INTVAL (low);
-       val[1] = INTVAL (high);
-      }
+    case MULT:
+      total = (speed ? COSTS_N_INSNS (3) : 2);
       break;
 
-    case CONST_DOUBLE:
-      if (GET_MODE (operands[1]) == DFmode)
-       {
-         REAL_VALUE_TYPE rv;
-
-         REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]);
-         REAL_VALUE_TO_TARGET_DOUBLE (rv, val);
-       }
-      else if (GET_MODE (operands[1]) == VOIDmode
-              || GET_MODE (operands[1]) == DImode)
-       {
-         val[0] = CONST_DOUBLE_LOW (operands[1]);
-         val[1] = CONST_DOUBLE_HIGH (operands[1]);
-       }
+    case DIV:
+    case UDIV:
+    case MOD:
+    case UMOD:
+      total = (speed ? COSTS_N_INSNS (39)
+               /* Include space to load+retrieve MDR.  */
+               : code == MOD || code == UMOD ? 6 : 4);
       break;
 
+    case MEM:
+      total = mn10300_address_cost (XEXP (x, 0), speed);
+      if (speed)
+       total = COSTS_N_INSNS (2 + total);
+      goto alldone;
+
     default:
-      return false;
+      /* Probably not implemented.  Assume external call.  */
+      total = (speed ? COSTS_N_INSNS (10) : 7);
+      break;
     }
 
-  return val[0] == 0 || val[1] == 0;
+  *ptotal = total;
+  return false;
+
+ alldone:
+  *ptotal = total;
+  return true;
 }
+
 /* If using PIC, mark a SYMBOL_REF for a non-global symbol so that we
    may access it using GOTOFF instead of GOT.  */
 
@@ -2502,10 +2660,14 @@ mn10300_conditional_register_usage (void)
 #undef  TARGET_LEGITIMIZE_ADDRESS
 #define TARGET_LEGITIMIZE_ADDRESS mn10300_legitimize_address
 
+#undef  TARGET_ADDRESS_COST
+#define TARGET_ADDRESS_COST  mn10300_address_cost
+#undef  TARGET_REGISTER_MOVE_COST
+#define TARGET_REGISTER_MOVE_COST  mn10300_register_move_cost
+#undef  TARGET_MEMORY_MOVE_COST
+#define TARGET_MEMORY_MOVE_COST  mn10300_memory_move_cost
 #undef  TARGET_RTX_COSTS
 #define TARGET_RTX_COSTS mn10300_rtx_costs
-#undef  TARGET_ADDRESS_COST
-#define TARGET_ADDRESS_COST mn10300_address_cost
 
 #undef  TARGET_ASM_FILE_START
 #define TARGET_ASM_FILE_START mn10300_file_start
index bdd6b6f813fcfd74f58b9f1df51432d72774c58d..ef79245b4cfca9a46226e09b3ea53eeb65e9870d 100644 (file)
@@ -600,19 +600,6 @@ struct cum_arg
 #define SELECT_CC_MODE(OP, X, Y)  mn10300_select_cc_mode (X)
 #define REVERSIBLE_CC_MODE(MODE)  0
 \f
-#define REGISTER_MOVE_COST(MODE, CLASS1, CLASS2) \
-  ((CLASS1 == CLASS2 && (CLASS1 == ADDRESS_REGS || CLASS1 == DATA_REGS)) ? 2 :\
-   ((CLASS1 == ADDRESS_REGS || CLASS1 == DATA_REGS) && \
-    (CLASS2 == ADDRESS_REGS || CLASS2 == DATA_REGS)) ? 4 : \
-   (CLASS1 == SP_REGS && CLASS2 == ADDRESS_REGS) ? 2 : \
-   (CLASS1 == ADDRESS_REGS && CLASS2 == SP_REGS) ? 4 : \
-   ! TARGET_AM33 ? 6 : \
-   (CLASS1 == SP_REGS || CLASS2 == SP_REGS) ? 6 : \
-   (CLASS1 == CLASS2 && CLASS1 == EXTENDED_REGS) ? 6 : \
-   (CLASS1 == FP_REGS || CLASS2 == FP_REGS) ? 6 : \
-   (CLASS1 == EXTENDED_REGS || CLASS2 == EXTENDED_REGS) ? 4 : \
-   4)
-
 /* Nonzero if access to memory by bytes or half words is no faster
    than accessing full words.  */
 #define SLOW_BYTE_ACCESS 1
This page took 0.226258 seconds and 5 git commands to generate.