arm.c (arm_size_rtx_costs): New function.
authorRichard Earnshaw <rearnsha@arm.com>
Wed, 18 Aug 2004 22:23:57 +0000 (22:23 +0000)
committerRichard Earnshaw <rearnsha@gcc.gnu.org>
Wed, 18 Aug 2004 22:23:57 +0000 (22:23 +0000)
* arm.c (arm_size_rtx_costs): New function.
(arm_override_options): Use it if optimizing for space.

From-SVN: r86211

gcc/ChangeLog
gcc/config/arm/arm.c

index 48597b531c2746610bc139963316c9f6e4758386..d781d3e966a2e372aa2a766c584bedb78f93c403 100644 (file)
@@ -1,3 +1,8 @@
+2004-08-18  Richard Earnshaw  <rearnsha@arm.com>
+
+       * arm.c (arm_size_rtx_costs): New function.
+       (arm_override_options): Use it if optimizing for space.
+
 2004-08-18  Richard Henderson  <rth@redhat.com>
 
        * emit-rtl.c (gen_const_mem): New.
index ed6445fff0a8ab10d8668bee6f37fee1bd3762c8..bcb3c533f7231a64ee415b3b5eb7b8a7337208ba 100644 (file)
@@ -127,6 +127,7 @@ static void arm_internal_label (FILE *, const char *, unsigned long);
 static void arm_output_mi_thunk (FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT,
                                 tree);
 static int arm_rtx_costs_1 (rtx, enum rtx_code, enum rtx_code);
+static bool arm_size_rtx_costs (rtx, int, int, int *);
 static bool arm_slowmul_rtx_costs (rtx, int, int, int *);
 static bool arm_fastmul_rtx_costs (rtx, int, int, int *);
 static bool arm_xscale_rtx_costs (rtx, int, int, int *);
@@ -870,7 +871,10 @@ arm_override_options (void)
     abort ();
   
   tune_flags = all_cores[(int)arm_tune].flags;
-  targetm.rtx_costs = all_cores[(int)arm_tune].rtx_costs;
+  if (optimize_size)
+    targetm.rtx_costs = arm_size_rtx_costs;
+  else
+    targetm.rtx_costs = all_cores[(int)arm_tune].rtx_costs;
 
   /* Make sure that the processor choice does not conflict with any of the
      other command line choices.  */
@@ -3938,6 +3942,227 @@ arm_rtx_costs_1 (rtx x, enum rtx_code code, enum rtx_code outer)
     }
 }
 
+/* RTX costs when optimizing for size.  */
+static bool
+arm_size_rtx_costs (rtx x, int code, int outer_code, int *total)
+{
+  enum machine_mode mode = GET_MODE (x);
+
+  if (TARGET_THUMB)
+    {
+      /* XXX TBD.  For now, use the standard costs.  */
+      *total = thumb_rtx_costs (x, code, outer_code);
+      return true;
+    }
+
+  switch (code)
+    {
+    case MEM:
+      /* A memory access costs 1 insn if the mode is small, or the address is 
+        a single register, otherwise it costs one insn per word.  */
+      if (REG_P (XEXP (x, 0)))
+       *total = COSTS_N_INSNS (1);
+      else
+       *total = COSTS_N_INSNS (ARM_NUM_REGS (mode));
+      return true;
+
+    case DIV:
+    case MOD:
+    case UDIV:
+    case UMOD:
+      /* Needs a libcall, so it costs about this.  */
+      *total = COSTS_N_INSNS (2);
+      return false;
+
+    case ROTATE:
+      if (mode == SImode && GET_CODE (XEXP (x, 1)) == REG)
+       {
+         *total = COSTS_N_INSNS (2) + rtx_cost (XEXP (x, 0), code);
+         return true;
+       }
+      /* Fall through */
+    case ROTATERT:
+    case ASHIFT:
+    case LSHIFTRT:
+    case ASHIFTRT:
+      if (mode == DImode && GET_CODE (XEXP (x, 1)) == CONST_INT)
+       {
+         *total = COSTS_N_INSNS (3) + rtx_cost (XEXP (x, 0), code);
+         return true;
+       }
+      else if (mode == SImode)
+       {
+         *total = COSTS_N_INSNS (1) + rtx_cost (XEXP (x, 0), code);
+         /* Slightly disparage register shifts, but not by much.  */
+         if (GET_CODE (XEXP (x, 1)) != CONST_INT)
+           *total += 1 + rtx_cost (XEXP (x, 1), code);
+         return true;
+       }
+
+      /* Needs a libcall.  */
+      *total = COSTS_N_INSNS (2);
+      return false;
+
+    case MINUS:
+      if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT)
+       {
+         *total = COSTS_N_INSNS (1);
+         return false;
+       }
+
+      if (mode == SImode)
+       {
+         enum rtx_code subcode0 = GET_CODE (XEXP (x, 0));
+         enum rtx_code subcode1 = GET_CODE (XEXP (x, 1));
+
+         if (subcode0 == ROTATE || subcode0 == ROTATERT || subcode0 == ASHIFT
+             || subcode0 == LSHIFTRT || subcode0 == ASHIFTRT
+             || subcode1 == ROTATE || subcode1 == ROTATERT
+             || subcode1 == ASHIFT || subcode1 == LSHIFTRT
+             || subcode1 == ASHIFTRT)
+           {
+             /* It's just the cost of the two operands.  */
+             *total = 0;
+             return false;
+           }
+
+         *total = COSTS_N_INSNS (1);
+         return false;
+       }
+
+      *total = COSTS_N_INSNS (ARM_NUM_REGS (mode));
+      return false;
+
+    case PLUS: 
+      if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT)
+       {
+         *total = COSTS_N_INSNS (1);
+         return false;
+       }
+
+      /* Fall through */
+    case AND: case XOR: case IOR:
+      if (mode == SImode)
+       {
+         enum rtx_code subcode = GET_CODE (XEXP (x, 0));
+
+         if (subcode == ROTATE || subcode == ROTATERT || subcode == ASHIFT
+             || subcode == LSHIFTRT || subcode == ASHIFTRT
+             || (code == AND && subcode == NOT))
+           {
+             /* It's just the cost of the two operands.  */
+             *total = 0;
+             return false;
+           }
+       }
+
+      *total = COSTS_N_INSNS (ARM_NUM_REGS (mode));
+      return false;
+
+    case MULT:
+      *total = COSTS_N_INSNS (ARM_NUM_REGS (mode));
+      return false;
+
+    case NEG:
+      if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT)
+       *total = COSTS_N_INSNS (1);
+      /* Fall through */
+    case NOT:
+      *total = COSTS_N_INSNS (ARM_NUM_REGS (mode));
+
+      return false;
+
+    case IF_THEN_ELSE:
+      *total = 0;
+      return false;
+
+    case COMPARE:
+      if (cc_register (XEXP (x, 0), VOIDmode))
+       * total = 0;
+      else
+       *total = COSTS_N_INSNS (1);
+      return false;
+
+    case ABS:
+      if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT)
+       *total = COSTS_N_INSNS (1);
+      else
+       *total = COSTS_N_INSNS (1 + ARM_NUM_REGS (mode));
+      return false;
+
+    case SIGN_EXTEND:
+      *total = 0;
+      if (GET_MODE_SIZE (GET_MODE (XEXP (x, 0))) < 4)
+       {
+         if (!(arm_arch4 && MEM_P (XEXP (x, 0))))
+           *total += COSTS_N_INSNS (arm_arch6 ? 1 : 2);
+       }
+      if (mode == DImode)
+       *total += COSTS_N_INSNS (1);
+      return false;
+
+    case ZERO_EXTEND:
+      *total = 0;
+      if (!(arm_arch4 && MEM_P (XEXP (x, 0))))
+       {
+         switch (GET_MODE (XEXP (x, 0)))
+           {
+           case QImode:
+             *total += COSTS_N_INSNS (1);
+             break;
+
+           case HImode:
+             *total += COSTS_N_INSNS (arm_arch6 ? 1 : 2);
+             
+           case SImode:
+             break;
+
+           default:
+             *total += COSTS_N_INSNS (2);
+           }
+       }
+
+      if (mode == DImode)
+       *total += COSTS_N_INSNS (1);
+
+      return false;
+
+    case CONST_INT:                                            
+      if (const_ok_for_arm (INTVAL (x)))                       
+       *total = COSTS_N_INSNS (outer_code == SET ? 1 : 0);
+      else if (const_ok_for_arm (~INTVAL (x)))
+       *total = COSTS_N_INSNS (outer_code == AND ? 0 : 1);
+      else if (const_ok_for_arm (-INTVAL (x)))
+       {
+         if (outer_code == COMPARE || outer_code == PLUS
+             || outer_code == MINUS)
+           *total = 0;
+         else
+           *total = COSTS_N_INSNS (1);
+       }
+      else
+       *total = COSTS_N_INSNS (2);
+      return true;
+      
+    case CONST:                                                        
+    case LABEL_REF:                                            
+    case SYMBOL_REF:                                           
+      *total = COSTS_N_INSNS (2);
+      return true;
+      
+    case CONST_DOUBLE:
+      *total = COSTS_N_INSNS (4);
+      return true;
+
+    default:
+      if (mode != VOIDmode)
+       *total = COSTS_N_INSNS (ARM_NUM_REGS (mode));
+      else
+       *total = COSTS_N_INSNS (4); /* How knows?  */
+      return false;
+    }
+}
+
 /* RTX costs for cores with a slow MUL implementation.  */
 
 static bool
@@ -11581,7 +11806,7 @@ arm_final_prescan_insn (rtx insn)
 }
 
 /* Returns true if REGNO is a valid register
-   for holding a quantity of tyoe MODE.  */
+   for holding a quantity of type MODE.  */
 int
 arm_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode)
 {