re PR target/40457 (use stm and ldm to access consecutive memory words)
authorBernd Schmidt <bernds@codesourcery.com>
Wed, 29 Sep 2010 20:06:55 +0000 (20:06 +0000)
committerBernd Schmidt <bernds@gcc.gnu.org>
Wed, 29 Sep 2010 20:06:55 +0000 (20:06 +0000)
PR target/40457
* postreload.c (move2add_use_add2_insn): Use full_costs for
comparison.
(move2add_use_add3_insn): Likewise.
(reload_cse_move2add): Likewise.
* rtlanal.c (get_full_rtx_cost): New function.
* rtl.h (struct full_rtx_costs): New.
(init_costs_to_max, init_costs_to_zero, costs_lt_p,
costs_add_n_insns): New inline functions.
(get_full_rtx_cost): Declare.

testsuite/
PR target/40457
* gcc.target/arm/pr40457-3.c: New test.

From-SVN: r164732

gcc/ChangeLog
gcc/postreload.c
gcc/rtl.h
gcc/rtlanal.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/arm/pr40457-3.c [new file with mode: 0644]

index a0da8d874d06997c85d35e8506b831836c8b925a..0c3f9ce9ff731b13a1d54fa950d9ea4e62ef2355 100644 (file)
@@ -1,3 +1,16 @@
+2010-09-29  Bernd Schmidt  <bernds@codesourcery.com>
+
+       PR target/40457
+       * postreload.c (move2add_use_add2_insn): Use full_costs for
+       comparison.
+       (move2add_use_add3_insn): Likewise.
+       (reload_cse_move2add): Likewise.
+       * rtlanal.c (get_full_rtx_cost): New function.
+       * rtl.h (struct full_rtx_costs): New.
+       (init_costs_to_max, init_costs_to_zero, costs_lt_p,
+       costs_add_n_insns): New inline functions.
+       (get_full_rtx_cost): Declare.
+
 2010-09-29  Kai Tietz  <kai.tietz@onevision.com>
 
        * config/i386/mingw32.h (TARGET_64BIT): replaced by
index 0a70b2031a54fc9c735080d7ab2bdb625f23a7eb..1fc9bfc50f621bcb96541d004cd509efd50c9e3a 100644 (file)
@@ -1645,39 +1645,45 @@ move2add_use_add2_insn (rtx reg, rtx sym, rtx off, rtx insn)
       if (INTVAL (off) == reg_offset [regno])
        changed = validate_change (insn, &SET_SRC (pat), reg, 0);
     }
-  else if (rtx_cost (new_src, PLUS, speed) < rtx_cost (src, SET, speed)
-          && have_add2_insn (reg, new_src))
+  else
     {
+      struct full_rtx_costs oldcst, newcst;
       rtx tem = gen_rtx_PLUS (GET_MODE (reg), reg, new_src);
-      changed = validate_change (insn, &SET_SRC (pat), tem, 0);
-    }
-  else if (sym == NULL_RTX && GET_MODE (reg) != BImode)
-    {
-      enum machine_mode narrow_mode;
-      for (narrow_mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
-          narrow_mode != VOIDmode
-            && narrow_mode != GET_MODE (reg);
-          narrow_mode = GET_MODE_WIDER_MODE (narrow_mode))
+
+      get_full_rtx_cost (pat, SET, &oldcst);
+      SET_SRC (pat) = tem;
+      get_full_rtx_cost (pat, SET, &newcst);
+      SET_SRC (pat) = src;
+
+      if (costs_lt_p (&newcst, &oldcst, speed)
+         && have_add2_insn (reg, new_src))
+       changed = validate_change (insn, &SET_SRC (pat), tem, 0);       
+      else if (sym == NULL_RTX && GET_MODE (reg) != BImode)
        {
-         if (have_insn_for (STRICT_LOW_PART, narrow_mode)
-             && ((reg_offset[regno]
-                  & ~GET_MODE_MASK (narrow_mode))
-                 == (INTVAL (off)
-                     & ~GET_MODE_MASK (narrow_mode))))
+         enum machine_mode narrow_mode;
+         for (narrow_mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
+              narrow_mode != VOIDmode
+                && narrow_mode != GET_MODE (reg);
+              narrow_mode = GET_MODE_WIDER_MODE (narrow_mode))
            {
-             rtx narrow_reg = gen_rtx_REG (narrow_mode,
-                                           REGNO (reg));
-             rtx narrow_src = gen_int_mode (INTVAL (off),
-                                            narrow_mode);
-             rtx new_set =
-               gen_rtx_SET (VOIDmode,
-                            gen_rtx_STRICT_LOW_PART (VOIDmode,
-                                                     narrow_reg),
-                            narrow_src);
-             changed = validate_change (insn, &PATTERN (insn),
-                                        new_set, 0);
-             if (changed)
-               break;
+             if (have_insn_for (STRICT_LOW_PART, narrow_mode)
+                 && ((reg_offset[regno] & ~GET_MODE_MASK (narrow_mode))
+                     == (INTVAL (off) & ~GET_MODE_MASK (narrow_mode))))
+               {
+                 rtx narrow_reg = gen_rtx_REG (narrow_mode,
+                                               REGNO (reg));
+                 rtx narrow_src = gen_int_mode (INTVAL (off),
+                                                narrow_mode);
+                 rtx new_set
+                   = gen_rtx_SET (VOIDmode,
+                                  gen_rtx_STRICT_LOW_PART (VOIDmode,
+                                                           narrow_reg),
+                                  narrow_src);
+                 changed = validate_change (insn, &PATTERN (insn),
+                                            new_set, 0);
+                 if (changed)
+                   break;
+               }
            }
        }
     }
@@ -1705,11 +1711,18 @@ move2add_use_add3_insn (rtx reg, rtx sym, rtx off, rtx insn)
   rtx pat = PATTERN (insn);
   rtx src = SET_SRC (pat);
   int regno = REGNO (reg);
-  int min_cost = INT_MAX;
   int min_regno = 0;
   bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn));
   int i;
   bool changed = false;
+  struct full_rtx_costs oldcst, newcst, mincst;
+  rtx plus_expr;
+
+  init_costs_to_max (&mincst);
+  get_full_rtx_cost (pat, SET, &oldcst);
+
+  plus_expr = gen_rtx_PLUS (GET_MODE (reg), reg, const0_rtx);
+  SET_SRC (pat) = plus_expr;
 
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     if (reg_set_luid[i] > move2add_last_label_luid
@@ -1728,22 +1741,25 @@ move2add_use_add3_insn (rtx reg, rtx sym, rtx off, rtx insn)
           no-op moves.  */
        if (new_src == const0_rtx)
          {
-           min_cost = 0;
+           init_costs_to_zero (&mincst);
            min_regno = i;
            break;
          }
        else
          {
-           int cost = rtx_cost (new_src, PLUS, speed);
-           if (cost < min_cost)
+           XEXP (plus_expr, 1) = new_src;
+           get_full_rtx_cost (pat, SET, &newcst);
+
+           if (costs_lt_p (&newcst, &mincst, speed))
              {
-               min_cost = cost;
+               mincst = newcst;
                min_regno = i;
              }
          }
       }
+  SET_SRC (pat) = src;
 
-  if (min_cost < rtx_cost (src, SET, speed))
+  if (costs_lt_p (&mincst, &oldcst, speed))
     {
       rtx tem;
 
@@ -1879,18 +1895,26 @@ reload_cse_move2add (rtx first)
                        /* See above why we create (set (reg) (reg)) here.  */
                        success
                          = validate_change (next, &SET_SRC (set), reg, 0);
-                     else if ((rtx_cost (new_src, PLUS, speed)
-                               < COSTS_N_INSNS (1) + rtx_cost (src3, SET, speed))
-                              && have_add2_insn (reg, new_src))
+                     else
                        {
-                         rtx newpat = gen_rtx_SET (VOIDmode,
-                                                   reg,
-                                                   gen_rtx_PLUS (GET_MODE (reg),
-                                                                 reg,
-                                                                 new_src));
-                         success
-                           = validate_change (next, &PATTERN (next),
-                                              newpat, 0);
+                         rtx old_src = SET_SRC (set);
+                         struct full_rtx_costs oldcst, newcst;
+                         rtx tem = gen_rtx_PLUS (GET_MODE (reg), reg, new_src);
+
+                         get_full_rtx_cost (set, SET, &oldcst);
+                         SET_SRC (set) = tem;
+                         get_full_rtx_cost (tem, SET, &newcst);
+                         SET_SRC (set) = old_src;
+                         costs_add_n_insns (&oldcst, 1);
+
+                         if (costs_lt_p (&newcst, &oldcst, speed)
+                             && have_add2_insn (reg, new_src))
+                           {
+                             rtx newpat = gen_rtx_SET (VOIDmode, reg, tem);
+                             success
+                               = validate_change (next, &PATTERN (next),
+                                                  newpat, 0);
+                           }
                        }
                      if (success)
                        delete_insn (insn);
index 3aba473564289f133a81aacbb626417a371b7726..1f13f2a84eb8ab3485f364213b67adb717a470bb 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -1123,9 +1123,57 @@ rhs_regno (const_rtx x)
    not to use an rtx with this cost under any circumstances.  */
 #define MAX_COST INT_MAX
 
+/* A structure to hold all available cost information about an rtl
+   expression.  */
+struct full_rtx_costs
+{
+  int speed;
+  int size;
+};
+
+/* Initialize a full_rtx_costs structure C to the maximum cost.  */
+static inline void
+init_costs_to_max (struct full_rtx_costs *c)
+{
+  c->speed = MAX_COST;
+  c->size = MAX_COST;
+}
+
+/* Initialize a full_rtx_costs structure C to zero cost.  */
+static inline void
+init_costs_to_zero (struct full_rtx_costs *c)
+{
+  c->speed = 0;
+  c->size = 0;
+}
+
+/* Compare two full_rtx_costs structures A and B, returning true
+   if A < B when optimizing for speed.  */
+static inline bool
+costs_lt_p (struct full_rtx_costs *a, struct full_rtx_costs *b,
+           bool speed)
+{
+  if (speed)
+    return (a->speed < b->speed
+           || (a->speed == b->speed && a->size < b->size));
+  else
+    return (a->size < b->size
+           || (a->size == b->size && a->speed < b->speed));
+}
+
+/* Increase both members of the full_rtx_costs structure C by the
+   cost of N insns.  */
+static inline void
+costs_add_n_insns (struct full_rtx_costs *c, int n)
+{
+  c->speed += COSTS_N_INSNS (n);
+  c->size += COSTS_N_INSNS (n);
+}
+
 extern void init_rtlanal (void);
 extern int rtx_cost (rtx, enum rtx_code, bool);
 extern int address_cost (rtx, enum machine_mode, addr_space_t, bool);
+extern void get_full_rtx_cost (rtx, enum rtx_code, struct full_rtx_costs *);
 extern unsigned int subreg_lsb (const_rtx);
 extern unsigned int subreg_lsb_1 (enum machine_mode, enum machine_mode,
                                  unsigned int);
index d34dc8060090cefbc85d7572df382811ec22f5d4..930828ac2eb2c73488c0a036dfb9fcac3262fef2 100644 (file)
@@ -3589,6 +3589,17 @@ rtx_cost (rtx x, enum rtx_code outer_code ATTRIBUTE_UNUSED, bool speed)
 
   return total;
 }
+
+/* Fill in the structure C with information about both speed and size rtx
+   costs for X, with outer code OUTER.  */
+
+void
+get_full_rtx_cost (rtx x, enum rtx_code outer, struct full_rtx_costs *c)
+{
+  c->speed = rtx_cost (x, outer, true);
+  c->size = rtx_cost (x, outer, false);
+}
+
 \f
 /* Return cost of address expression X.
    Expect that X is properly formed address reference.
index 76ae3a1eff38eacda151545ca192b98462efd02b..2a5b94f69038ee2eca1d2db6780601d2f7888e3f 100644 (file)
@@ -1,3 +1,8 @@
+2010-09-29  Bernd Schmidt  <bernds@codesourcery.com>
+
+       PR target/40457
+       * gcc.target/arm/pr40457-3.c: New test.
+
 2010-09-29  Nathan Sidwell  <nathan@codesourcery.com>
 
        * lib/target-supports-dg.exp (dg-require-ifunc): Remove extraneous
diff --git a/gcc/testsuite/gcc.target/arm/pr40457-3.c b/gcc/testsuite/gcc.target/arm/pr40457-3.c
new file mode 100644 (file)
index 0000000..9bd5a17
--- /dev/null
@@ -0,0 +1,10 @@
+/* { dg-options "-Os" }  */
+/* { dg-do compile } */
+
+void foo(int* p)
+{
+  p[0] = 1;
+  p[1] = 0;
+}
+
+/* { dg-final { scan-assembler "stm" } } */