summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBernd Schmidt <bernds@codesourcery.com>2010-09-29 20:06:55 +0000
committerBernd Schmidt <bernds@gcc.gnu.org>2010-09-29 20:06:55 +0000
commit2293974419a6541fb6425249f1340e96a3fb0766 (patch)
tree8cdfbb3965dc10b464f100060d3e2a0a64d4bd57
parent0f23bc16605864cf7f41fab13a522004c3ee8c3a (diff)
downloadgcc-2293974419a6541fb6425249f1340e96a3fb0766.tar.gz
re PR target/40457 (use stm and ldm to access consecutive memory words)
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
-rw-r--r--gcc/ChangeLog13
-rw-r--r--gcc/postreload.c116
-rw-r--r--gcc/rtl.h48
-rw-r--r--gcc/rtlanal.c11
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.target/arm/pr40457-3.c10
6 files changed, 157 insertions, 46 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a0da8d874d0..0c3f9ce9ff7 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/postreload.c b/gcc/postreload.c
index 0a70b2031a5..1fc9bfc50f6 100644
--- a/gcc/postreload.c
+++ b/gcc/postreload.c
@@ -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);
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 3aba4735642..1f13f2a84eb 100644
--- 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);
diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index d34dc806009..930828ac2eb 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -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);
+}
+
/* Return cost of address expression X.
Expect that X is properly formed address reference.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 76ae3a1eff3..2a5b94f6903 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 00000000000..9bd5a17befe
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/pr40457-3.c
@@ -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" } } */