Commit 22939744 by Bernd Schmidt Committed by Bernd Schmidt

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
parent 0f23bc16
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> 2010-09-29 Kai Tietz <kai.tietz@onevision.com>
* config/i386/mingw32.h (TARGET_64BIT): replaced by * config/i386/mingw32.h (TARGET_64BIT): replaced by
...@@ -1645,39 +1645,45 @@ move2add_use_add2_insn (rtx reg, rtx sym, rtx off, rtx insn) ...@@ -1645,39 +1645,45 @@ move2add_use_add2_insn (rtx reg, rtx sym, rtx off, rtx insn)
if (INTVAL (off) == reg_offset [regno]) if (INTVAL (off) == reg_offset [regno])
changed = validate_change (insn, &SET_SRC (pat), reg, 0); changed = validate_change (insn, &SET_SRC (pat), reg, 0);
} }
else if (rtx_cost (new_src, PLUS, speed) < rtx_cost (src, SET, speed) else
&& have_add2_insn (reg, new_src))
{ {
struct full_rtx_costs oldcst, newcst;
rtx tem = gen_rtx_PLUS (GET_MODE (reg), reg, new_src); rtx tem = gen_rtx_PLUS (GET_MODE (reg), reg, new_src);
changed = validate_change (insn, &SET_SRC (pat), tem, 0);
} get_full_rtx_cost (pat, SET, &oldcst);
else if (sym == NULL_RTX && GET_MODE (reg) != BImode) SET_SRC (pat) = tem;
{ get_full_rtx_cost (pat, SET, &newcst);
enum machine_mode narrow_mode; SET_SRC (pat) = src;
for (narrow_mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
narrow_mode != VOIDmode if (costs_lt_p (&newcst, &oldcst, speed)
&& narrow_mode != GET_MODE (reg); && have_add2_insn (reg, new_src))
narrow_mode = GET_MODE_WIDER_MODE (narrow_mode)) 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) enum machine_mode narrow_mode;
&& ((reg_offset[regno] for (narrow_mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
& ~GET_MODE_MASK (narrow_mode)) narrow_mode != VOIDmode
== (INTVAL (off) && narrow_mode != GET_MODE (reg);
& ~GET_MODE_MASK (narrow_mode)))) narrow_mode = GET_MODE_WIDER_MODE (narrow_mode))
{ {
rtx narrow_reg = gen_rtx_REG (narrow_mode, if (have_insn_for (STRICT_LOW_PART, narrow_mode)
REGNO (reg)); && ((reg_offset[regno] & ~GET_MODE_MASK (narrow_mode))
rtx narrow_src = gen_int_mode (INTVAL (off), == (INTVAL (off) & ~GET_MODE_MASK (narrow_mode))))
narrow_mode); {
rtx new_set = rtx narrow_reg = gen_rtx_REG (narrow_mode,
gen_rtx_SET (VOIDmode, REGNO (reg));
gen_rtx_STRICT_LOW_PART (VOIDmode, rtx narrow_src = gen_int_mode (INTVAL (off),
narrow_reg), narrow_mode);
narrow_src); rtx new_set
changed = validate_change (insn, &PATTERN (insn), = gen_rtx_SET (VOIDmode,
new_set, 0); gen_rtx_STRICT_LOW_PART (VOIDmode,
if (changed) narrow_reg),
break; 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) ...@@ -1705,11 +1711,18 @@ move2add_use_add3_insn (rtx reg, rtx sym, rtx off, rtx insn)
rtx pat = PATTERN (insn); rtx pat = PATTERN (insn);
rtx src = SET_SRC (pat); rtx src = SET_SRC (pat);
int regno = REGNO (reg); int regno = REGNO (reg);
int min_cost = INT_MAX;
int min_regno = 0; int min_regno = 0;
bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn)); bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn));
int i; int i;
bool changed = false; 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++) for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (reg_set_luid[i] > move2add_last_label_luid 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) ...@@ -1728,22 +1741,25 @@ move2add_use_add3_insn (rtx reg, rtx sym, rtx off, rtx insn)
no-op moves. */ no-op moves. */
if (new_src == const0_rtx) if (new_src == const0_rtx)
{ {
min_cost = 0; init_costs_to_zero (&mincst);
min_regno = i; min_regno = i;
break; break;
} }
else else
{ {
int cost = rtx_cost (new_src, PLUS, speed); XEXP (plus_expr, 1) = new_src;
if (cost < min_cost) get_full_rtx_cost (pat, SET, &newcst);
if (costs_lt_p (&newcst, &mincst, speed))
{ {
min_cost = cost; mincst = newcst;
min_regno = i; min_regno = i;
} }
} }
} }
SET_SRC (pat) = src;
if (min_cost < rtx_cost (src, SET, speed)) if (costs_lt_p (&mincst, &oldcst, speed))
{ {
rtx tem; rtx tem;
...@@ -1879,18 +1895,26 @@ reload_cse_move2add (rtx first) ...@@ -1879,18 +1895,26 @@ reload_cse_move2add (rtx first)
/* See above why we create (set (reg) (reg)) here. */ /* See above why we create (set (reg) (reg)) here. */
success success
= validate_change (next, &SET_SRC (set), reg, 0); = validate_change (next, &SET_SRC (set), reg, 0);
else if ((rtx_cost (new_src, PLUS, speed) else
< COSTS_N_INSNS (1) + rtx_cost (src3, SET, speed))
&& have_add2_insn (reg, new_src))
{ {
rtx newpat = gen_rtx_SET (VOIDmode, rtx old_src = SET_SRC (set);
reg, struct full_rtx_costs oldcst, newcst;
gen_rtx_PLUS (GET_MODE (reg), rtx tem = gen_rtx_PLUS (GET_MODE (reg), reg, new_src);
reg,
new_src)); get_full_rtx_cost (set, SET, &oldcst);
success SET_SRC (set) = tem;
= validate_change (next, &PATTERN (next), get_full_rtx_cost (tem, SET, &newcst);
newpat, 0); 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) if (success)
delete_insn (insn); delete_insn (insn);
......
...@@ -1123,9 +1123,57 @@ rhs_regno (const_rtx x) ...@@ -1123,9 +1123,57 @@ rhs_regno (const_rtx x)
not to use an rtx with this cost under any circumstances. */ not to use an rtx with this cost under any circumstances. */
#define MAX_COST INT_MAX #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 void init_rtlanal (void);
extern int rtx_cost (rtx, enum rtx_code, bool); extern int rtx_cost (rtx, enum rtx_code, bool);
extern int address_cost (rtx, enum machine_mode, addr_space_t, 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 (const_rtx);
extern unsigned int subreg_lsb_1 (enum machine_mode, enum machine_mode, extern unsigned int subreg_lsb_1 (enum machine_mode, enum machine_mode,
unsigned int); unsigned int);
......
...@@ -3589,6 +3589,17 @@ rtx_cost (rtx x, enum rtx_code outer_code ATTRIBUTE_UNUSED, bool speed) ...@@ -3589,6 +3589,17 @@ rtx_cost (rtx x, enum rtx_code outer_code ATTRIBUTE_UNUSED, bool speed)
return total; 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. /* Return cost of address expression X.
Expect that X is properly formed address reference. Expect that X is properly formed address reference.
......
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> 2010-09-29 Nathan Sidwell <nathan@codesourcery.com>
* lib/target-supports-dg.exp (dg-require-ifunc): Remove extraneous * lib/target-supports-dg.exp (dg-require-ifunc): Remove extraneous
......
/* { dg-options "-Os" } */
/* { dg-do compile } */
void foo(int* p)
{
p[0] = 1;
p[1] = 0;
}
/* { dg-final { scan-assembler "stm" } } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment