Hi,
As reported in PR56102, arm back end returns wrong rtx cost for pattern
SET/ASHIFT/ASHIFTRT/LSHIFTRT/ROTATERT with multi-word mode. This 
causes GCC skipping the split process in lower-subreg.c, and generating
bigger constant pool.

This patch fixes the issue. Tested on arm-none-eabi/thumb1/O2/Os, ok for
trunk?

Thanks.

2013-03-26  Bin Cheng  <bin.ch...@arm.com>

        PR target/56102
        * config/arm/arm.c (thumb1_rtx_costs, thumb1_size_rtx_costs): Fix
        rtx costs for SET/ASHIFT/ASHIFTRT/LSHIFTRT/ROTATERT patterns with
        mult-word mode.
Index: gcc/config/arm/arm.c
===================================================================
--- gcc/config/arm/arm.c        (revision 195355)
+++ gcc/config/arm/arm.c        (working copy)
@@ -7049,7 +7049,7 @@ static inline int
 thumb1_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer)
 {
   enum machine_mode mode = GET_MODE (x);
-  int total;
+  int total, factor;
 
   switch (code)
     {
@@ -7057,6 +7057,8 @@ thumb1_rtx_costs (rtx x, enum rtx_code code, enum
     case ASHIFTRT:
     case LSHIFTRT:
     case ROTATERT:
+      return (mode == SImode) ? COSTS_N_INSNS (1) : COSTS_N_INSNS (2);
+
     case PLUS:
     case MINUS:
     case COMPARE:
@@ -7080,7 +7082,13 @@ thumb1_rtx_costs (rtx x, enum rtx_code code, enum
       return COSTS_N_INSNS (1) + 16;
 
     case SET:
-      return (COSTS_N_INSNS (1)
+      /* A SET doesn't have a mode, so let's look at the SET_DEST to get
+        the mode for the factor.  */
+      factor = GET_MODE_SIZE (GET_MODE (SET_DEST (x))) / UNITS_PER_WORD;
+      if (factor  == 0)
+       factor = 1;
+
+      return (factor * COSTS_N_INSNS (1)
              + 4 * ((MEM_P (SET_SRC (x)))
                     + MEM_P (SET_DEST (x))));
 
@@ -7777,6 +7785,7 @@ static inline int
 thumb1_size_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer)
 {
   enum machine_mode mode = GET_MODE (x);
+  int factor;
 
   switch (code)
     {
@@ -7784,6 +7793,8 @@ thumb1_size_rtx_costs (rtx x, enum rtx_code code,
     case ASHIFTRT:
     case LSHIFTRT:
     case ROTATERT:
+      return (mode == SImode) ? COSTS_N_INSNS (1) : COSTS_N_INSNS (2);
+
     case PLUS:
     case MINUS:
     case COMPARE:
@@ -7802,7 +7813,13 @@ thumb1_size_rtx_costs (rtx x, enum rtx_code code,
       return COSTS_N_INSNS (1);
 
     case SET:
-      return (COSTS_N_INSNS (1)
+      /* A SET doesn't have a mode, so let's look at the SET_DEST to get
+        the mode for the factor.  */
+      factor = GET_MODE_SIZE (GET_MODE (SET_DEST (x))) / UNITS_PER_WORD;
+      if (factor == 0)
+       factor = 1;
+
+      return (factor * COSTS_N_INSNS (1)
               + 4 * ((MEM_P (SET_SRC (x)))
                      + MEM_P (SET_DEST (x))));
 

Reply via email to