cse.c (CSE_ADDRESS_COST): Remove.
* cse.c (CSE_ADDRESS_COST): Remove. (find_best_addr): Add new parameter "MODE", use address_cost instead of CSE_ADDRESS_COST (address_cost): New. (fold_rtx): Update call of find_best_addr. * rtl.h (address_cost): Declare. * loop.c (general_induction_var): Add new parameter "MODE", use address_cost instead of ADDRESS_COST (init_loop): Use address_cost instead of ADDRESS_COST. (check_insn_for_givs): Update call of general_induction_var. (find_mem_givs): Likewise. (consec_sets_giv): Likewise. * config/i386/i386.h (ADDRESS_COST): Call ix86_address_cost. * i386.c (ix86_address_cost): New. * i386-protos.h (ix86_address_cost): Declare. From-SVN: r33486
This commit is contained in:
parent
5e849f6e86
commit
01329426bf
7 changed files with 143 additions and 54 deletions
|
@ -1,3 +1,21 @@
|
|||
Thu Apr 27 16:55:28 MET DST 2000 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* cse.c (CSE_ADDRESS_COST): Remove.
|
||||
(find_best_addr): Add new parameter "MODE", use address_cost instead
|
||||
of CSE_ADDRESS_COST
|
||||
(address_cost): New.
|
||||
(fold_rtx): Update call of find_best_addr.
|
||||
* rtl.h (address_cost): Declare.
|
||||
* loop.c (general_induction_var): Add new parameter "MODE", use
|
||||
address_cost instead of ADDRESS_COST
|
||||
(init_loop): Use address_cost instead of ADDRESS_COST.
|
||||
(check_insn_for_givs): Update call of general_induction_var.
|
||||
(find_mem_givs): Likewise.
|
||||
(consec_sets_giv): Likewise.
|
||||
* config/i386/i386.h (ADDRESS_COST): Call ix86_address_cost.
|
||||
* i386.c (ix86_address_cost): New.
|
||||
* i386-protos.h (ix86_address_cost): Declare.
|
||||
|
||||
Thu Apr 27 11:45:16 2000 Alexandre Oliva <aoliva@cygnus.com>
|
||||
|
||||
* config/mn10300/mn10300.md (movqi): Simplify. Prefer data
|
||||
|
|
|
@ -108,6 +108,7 @@ extern void ix86_split_ashldi PARAMS ((rtx *, rtx));
|
|||
extern void ix86_split_ashrdi PARAMS ((rtx *, rtx));
|
||||
extern void ix86_split_lshrdi PARAMS ((rtx *, rtx));
|
||||
extern void ix86_expand_strlensi_unroll_1 PARAMS ((rtx, rtx, rtx));
|
||||
extern int ix86_address_cost PARAMS ((rtx));
|
||||
|
||||
extern rtx assign_386_stack_local PARAMS ((enum machine_mode, int));
|
||||
extern int ix86_attr_length_default PARAMS ((rtx));
|
||||
|
|
|
@ -2253,7 +2253,65 @@ ix86_decompose_address (addr, out)
|
|||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Return cost of the memory address x.
|
||||
For i386, it is better to use a complex address than let gcc copy
|
||||
the address into a reg and make a new pseudo. But not if the address
|
||||
requires to two regs - that would mean more pseudos with longer
|
||||
lifetimes. */
|
||||
int
|
||||
ix86_address_cost (x)
|
||||
rtx x;
|
||||
{
|
||||
struct ix86_address parts;
|
||||
int cost = 1;
|
||||
|
||||
if (!ix86_decompose_address (x, &parts))
|
||||
abort ();
|
||||
|
||||
/* More complex memory references are better. */
|
||||
if (parts.disp && parts.disp != const0_rtx)
|
||||
cost--;
|
||||
|
||||
/* Attempt to minimize number of registers in the address. */
|
||||
if ((parts.base
|
||||
&& (!REG_P (parts.base) || REGNO (parts.base) >= FIRST_PSEUDO_REGISTER))
|
||||
|| (parts.index
|
||||
&& (!REG_P (parts.index)
|
||||
|| REGNO (parts.index) >= FIRST_PSEUDO_REGISTER)))
|
||||
cost++;
|
||||
|
||||
if (parts.base
|
||||
&& (!REG_P (parts.base) || REGNO (parts.base) >= FIRST_PSEUDO_REGISTER)
|
||||
&& parts.index
|
||||
&& (!REG_P (parts.index) || REGNO (parts.index) >= FIRST_PSEUDO_REGISTER)
|
||||
&& parts.base != parts.index)
|
||||
cost++;
|
||||
|
||||
/* AMD-K6 don't like addresses with ModR/M set to 00_xxx_100b,
|
||||
since it's predecode logic can't detect the length of instructions
|
||||
and it degenerates to vector decoded. Increase cost of such
|
||||
addresses here. The penalty is minimally 2 cycles. It may be worthwhile
|
||||
to split such addresses or even refuse such addresses at all.
|
||||
|
||||
Following addressing modes are affected:
|
||||
[base+scale*index]
|
||||
[scale*index+disp]
|
||||
[base+index]
|
||||
|
||||
The first and last case may be avoidable by explicitly coding the zero in
|
||||
memory address, but I don't have AMD-K6 machine handy to check this
|
||||
theory. */
|
||||
|
||||
if (TARGET_K6
|
||||
&& ((!parts.disp && parts.base && parts.index && parts.scale != 1)
|
||||
|| (parts.disp && !parts.base && parts.index && parts.scale != 1)
|
||||
|| (!parts.disp && parts.base && parts.index && parts.scale == 1)))
|
||||
cost += 10;
|
||||
|
||||
return cost;
|
||||
}
|
||||
|
||||
/* Determine if a given CONST RTX is a valid memory displacement
|
||||
in PIC mode. */
|
||||
|
||||
|
|
|
@ -2040,11 +2040,7 @@ while (0)
|
|||
lifetimes. */
|
||||
|
||||
#define ADDRESS_COST(RTX) \
|
||||
((CONSTANT_P (RTX) \
|
||||
|| (GET_CODE (RTX) == PLUS && CONSTANT_P (XEXP (RTX, 1)) \
|
||||
&& REG_P (XEXP (RTX, 0)))) ? 0 \
|
||||
: REG_P (RTX) ? 1 \
|
||||
: 2)
|
||||
ix86_address_cost (x)
|
||||
|
||||
/* A C expression for the cost of moving data from a register in class FROM to
|
||||
one in class TO. The classes are expressed using the enumeration values
|
||||
|
|
82
gcc/cse.c
82
gcc/cse.c
|
@ -537,16 +537,6 @@ struct table_elt
|
|||
|
||||
#define REGNO_QTY_VALID_P(N) (REG_QTY (N) != (int) (N))
|
||||
|
||||
#ifdef ADDRESS_COST
|
||||
/* The ADDRESS_COST macro does not deal with ADDRESSOF nodes. But,
|
||||
during CSE, such nodes are present. Using an ADDRESSOF node which
|
||||
refers to the address of a REG is a good thing because we can then
|
||||
turn (MEM (ADDRESSSOF (REG))) into just plain REG. */
|
||||
#define CSE_ADDRESS_COST(RTX) \
|
||||
((GET_CODE (RTX) == ADDRESSOF && REG_P (XEXP ((RTX), 0))) \
|
||||
? -1 : ADDRESS_COST(RTX))
|
||||
#endif
|
||||
|
||||
static struct table_elt *table[HASH_SIZE];
|
||||
|
||||
/* Chain of `struct table_elt's made so far for this function
|
||||
|
@ -683,7 +673,7 @@ static unsigned canon_hash PARAMS ((rtx, enum machine_mode));
|
|||
static unsigned safe_hash PARAMS ((rtx, enum machine_mode));
|
||||
static int exp_equiv_p PARAMS ((rtx, rtx, int, int));
|
||||
static rtx canon_reg PARAMS ((rtx, rtx));
|
||||
static void find_best_addr PARAMS ((rtx, rtx *));
|
||||
static void find_best_addr PARAMS ((rtx, rtx *, enum machine_mode));
|
||||
static enum rtx_code find_comparison_args PARAMS ((enum rtx_code, rtx *, rtx *,
|
||||
enum machine_mode *,
|
||||
enum machine_mode *));
|
||||
|
@ -849,6 +839,34 @@ rtx_cost (x, outer_code)
|
|||
return total;
|
||||
}
|
||||
|
||||
/* Return cost of address expression X. Expect that X is propertly formed address
|
||||
reference. */
|
||||
int
|
||||
address_cost (x, mode)
|
||||
rtx x;
|
||||
enum machine_mode mode;
|
||||
{
|
||||
/* The ADDRESS_COST macro does not deal with ADDRESSOF nodes. But,
|
||||
during CSE, such nodes are present. Using an ADDRESSOF node which
|
||||
refers to the address of a REG is a good thing because we can then
|
||||
turn (MEM (ADDRESSSOF (REG))) into just plain REG. */
|
||||
|
||||
if (GET_CODE (x) == ADDRESSOF && REG_P (XEXP ((x), 0)))
|
||||
return -1;
|
||||
|
||||
/* We may be asked for cost of various unusual addresses, such as operands
|
||||
of push instruction. It is not worthwhile to complicate writting
|
||||
of ADDRESS_COST macro by such cases. */
|
||||
|
||||
if (!memory_address_p (mode, x))
|
||||
return 1000;
|
||||
#ifdef ADDRESS_COST
|
||||
return ADDRESS_COST (x);
|
||||
#else
|
||||
return rtx_cost (x, MEM);
|
||||
#endif
|
||||
}
|
||||
|
||||
static struct cse_reg_info *
|
||||
get_cse_reg_info (regno)
|
||||
unsigned int regno;
|
||||
|
@ -2681,9 +2699,10 @@ canon_reg (x, insn)
|
|||
*/
|
||||
|
||||
static void
|
||||
find_best_addr (insn, loc)
|
||||
find_best_addr (insn, loc, mode)
|
||||
rtx insn;
|
||||
rtx *loc;
|
||||
enum machine_mode mode;
|
||||
{
|
||||
struct table_elt *elt;
|
||||
rtx addr = *loc;
|
||||
|
@ -2695,6 +2714,7 @@ find_best_addr (insn, loc)
|
|||
int save_hash_arg_in_memory = hash_arg_in_memory;
|
||||
int addr_volatile;
|
||||
int regno;
|
||||
int folded_cost, addr_cost;
|
||||
unsigned hash;
|
||||
|
||||
/* Do not try to replace constant addresses or addresses of local and
|
||||
|
@ -2728,14 +2748,13 @@ find_best_addr (insn, loc)
|
|||
{
|
||||
rtx folded = fold_rtx (copy_rtx (addr), NULL_RTX);
|
||||
|
||||
if (1
|
||||
#ifdef ADDRESS_COST
|
||||
&& (CSE_ADDRESS_COST (folded) < CSE_ADDRESS_COST (addr)
|
||||
|| (CSE_ADDRESS_COST (folded) == CSE_ADDRESS_COST (addr)
|
||||
&& rtx_cost (folded, MEM) > rtx_cost (addr, MEM)))
|
||||
#else
|
||||
folded_cost = address_cost (folded, mode);
|
||||
addr_cost = address_cost (addr, mode);
|
||||
|
||||
if ((folded_cost < addr_cost
|
||||
|| (folded_cost == addr_cost
|
||||
&& rtx_cost (folded, MEM) > rtx_cost (addr, MEM)))
|
||||
&& rtx_cost (folded, MEM) < rtx_cost (addr, MEM)
|
||||
#endif
|
||||
&& validate_change (insn, loc, folded, 0))
|
||||
addr = folded;
|
||||
}
|
||||
|
@ -2782,8 +2801,9 @@ find_best_addr (insn, loc)
|
|||
|
||||
while (found_better)
|
||||
{
|
||||
int best_addr_cost = CSE_ADDRESS_COST (*loc);
|
||||
int best_addr_cost = address_cost (*loc, mode);
|
||||
int best_rtx_cost = (elt->cost + 1) >> 1;
|
||||
int exp_cost;
|
||||
struct table_elt *best_elt = elt;
|
||||
|
||||
found_better = 0;
|
||||
|
@ -2792,12 +2812,12 @@ find_best_addr (insn, loc)
|
|||
{
|
||||
if ((GET_CODE (p->exp) == REG
|
||||
|| exp_equiv_p (p->exp, p->exp, 1, 0))
|
||||
&& (CSE_ADDRESS_COST (p->exp) < best_addr_cost
|
||||
|| (CSE_ADDRESS_COST (p->exp) == best_addr_cost
|
||||
&& (p->cost + 1) >> 1 > best_rtx_cost)))
|
||||
&& ((exp_cost = address_cost (p->exp, mode)) < best_addr_cost
|
||||
|| (exp_cost == best_addr_cost
|
||||
&& (p->cost + 1) >> 1 < best_rtx_cost)))
|
||||
{
|
||||
found_better = 1;
|
||||
best_addr_cost = CSE_ADDRESS_COST (p->exp);
|
||||
best_addr_cost = exp_cost;
|
||||
best_rtx_cost = (p->cost + 1) >> 1;
|
||||
best_elt = p;
|
||||
}
|
||||
|
@ -2851,7 +2871,7 @@ find_best_addr (insn, loc)
|
|||
|
||||
while (found_better)
|
||||
{
|
||||
int best_addr_cost = CSE_ADDRESS_COST (*loc);
|
||||
int best_addr_cost = address_cost (*loc, mode);
|
||||
int best_rtx_cost = (COST (*loc) + 1) >> 1;
|
||||
struct table_elt *best_elt = elt;
|
||||
rtx best_rtx = *loc;
|
||||
|
@ -2873,13 +2893,15 @@ find_best_addr (insn, loc)
|
|||
{
|
||||
rtx new = simplify_gen_binary (GET_CODE (*loc), Pmode,
|
||||
p->exp, c);
|
||||
int new_cost;
|
||||
new_cost = address_cost (new, mode);
|
||||
|
||||
if ((CSE_ADDRESS_COST (new) < best_addr_cost
|
||||
|| (CSE_ADDRESS_COST (new) == best_addr_cost
|
||||
&& (COST (new) + 1) >> 1 > best_rtx_cost)))
|
||||
if (new_cost < best_addr_cost
|
||||
|| (new_cost == best_addr_cost
|
||||
&& (COST (new) + 1) >> 1 > best_rtx_cost))
|
||||
{
|
||||
found_better = 1;
|
||||
best_addr_cost = CSE_ADDRESS_COST (new);
|
||||
best_addr_cost = new_cost;
|
||||
best_rtx_cost = (COST (new) + 1) >> 1;
|
||||
best_elt = p;
|
||||
best_rtx = new;
|
||||
|
@ -3350,7 +3372,7 @@ fold_rtx (x, insn)
|
|||
best address. Not only don't we care, but we could modify the
|
||||
MEM in an invalid way since we have no insn to validate against. */
|
||||
if (insn != 0)
|
||||
find_best_addr (insn, &XEXP (x, 0));
|
||||
find_best_addr (insn, &XEXP (x, 0), GET_MODE (x));
|
||||
|
||||
{
|
||||
/* Even if we don't fold in the insn itself,
|
||||
|
|
31
gcc/loop.c
31
gcc/loop.c
|
@ -278,7 +278,7 @@ static int basic_induction_var PARAMS ((const struct loop *, rtx,
|
|||
rtx *, rtx *, rtx **, int *));
|
||||
static rtx simplify_giv_expr PARAMS ((const struct loop *, rtx, int *));
|
||||
static int general_induction_var PARAMS ((const struct loop *loop, rtx, rtx *,
|
||||
rtx *, rtx *, int, int *));
|
||||
rtx *, rtx *, int, int *, enum machine_mode));
|
||||
static int consec_sets_giv PARAMS ((const struct loop *, int, rtx,
|
||||
rtx, rtx, rtx *, rtx *, rtx *));
|
||||
static int check_dbra_loop PARAMS ((struct loop *, int));
|
||||
|
@ -367,11 +367,7 @@ init_loop ()
|
|||
|
||||
add_cost = rtx_cost (gen_rtx_PLUS (word_mode, reg, reg), SET);
|
||||
|
||||
#ifdef ADDRESS_COST
|
||||
reg_address_cost = ADDRESS_COST (reg);
|
||||
#else
|
||||
reg_address_cost = rtx_cost (reg, MEM);
|
||||
#endif
|
||||
reg_address_cost = address_cost (reg, SImode);
|
||||
|
||||
/* We multiply by 2 to reconcile the difference in scale between
|
||||
these two ways of computing costs. Otherwise the cost of a copy
|
||||
|
@ -5133,12 +5129,12 @@ check_insn_for_givs (loop, p, not_every_iteration, maybe_multiple)
|
|||
|
||||
if (/* SET_SRC is a giv. */
|
||||
(general_induction_var (loop, SET_SRC (set), &src_reg, &add_val,
|
||||
&mult_val, 0, &benefit)
|
||||
&mult_val, 0, &benefit, VOIDmode)
|
||||
/* Equivalent expression is a giv. */
|
||||
|| ((regnote = find_reg_note (p, REG_EQUAL, NULL_RTX))
|
||||
&& general_induction_var (loop, XEXP (regnote, 0), &src_reg,
|
||||
&add_val, &mult_val, 0,
|
||||
&benefit)))
|
||||
&benefit, VOIDmode)))
|
||||
/* Don't try to handle any regs made by loop optimization.
|
||||
We have nothing on them in regno_first_uid, etc. */
|
||||
&& REGNO (dest_reg) < max_reg_before_loop
|
||||
|
@ -5276,7 +5272,7 @@ find_mem_givs (loop, x, insn, not_every_iteration, maybe_multiple)
|
|||
this one would not be seen. */
|
||||
|
||||
if (general_induction_var (loop, XEXP (x, 0), &src_reg, &add_val,
|
||||
&mult_val, 1, &benefit))
|
||||
&mult_val, 1, &benefit, GET_MODE (x)))
|
||||
{
|
||||
/* Found one; record it. */
|
||||
struct induction *v
|
||||
|
@ -6126,7 +6122,8 @@ basic_induction_var (loop, x, mode, dest_reg, p, inc_val, mult_val,
|
|||
such that the value of X is biv * mult + add; */
|
||||
|
||||
static int
|
||||
general_induction_var (loop, x, src_reg, add_val, mult_val, is_addr, pbenefit)
|
||||
general_induction_var (loop, x, src_reg, add_val, mult_val, is_addr,
|
||||
pbenefit, addr_mode)
|
||||
const struct loop *loop;
|
||||
rtx x;
|
||||
rtx *src_reg;
|
||||
|
@ -6134,6 +6131,7 @@ general_induction_var (loop, x, src_reg, add_val, mult_val, is_addr, pbenefit)
|
|||
rtx *mult_val;
|
||||
int is_addr;
|
||||
int *pbenefit;
|
||||
enum machine_mode addr_mode;
|
||||
{
|
||||
rtx orig_x = x;
|
||||
char *storage;
|
||||
|
@ -6207,13 +6205,7 @@ general_induction_var (loop, x, src_reg, add_val, mult_val, is_addr, pbenefit)
|
|||
*mult_val = XEXP (*mult_val, 0);
|
||||
|
||||
if (is_addr)
|
||||
{
|
||||
#ifdef ADDRESS_COST
|
||||
*pbenefit += ADDRESS_COST (orig_x) - reg_address_cost;
|
||||
#else
|
||||
*pbenefit += rtx_cost (orig_x, MEM) - reg_address_cost;
|
||||
#endif
|
||||
}
|
||||
*pbenefit += address_cost (orig_x, addr_mode) - reg_address_cost;
|
||||
else
|
||||
*pbenefit += rtx_cost (orig_x, SET);
|
||||
|
||||
|
@ -6745,11 +6737,12 @@ consec_sets_giv (loop, first_benefit, p, src_reg, dest_reg,
|
|||
&& GET_CODE (SET_DEST (set)) == REG
|
||||
&& SET_DEST (set) == dest_reg
|
||||
&& (general_induction_var (loop, SET_SRC (set), &src_reg,
|
||||
add_val, mult_val, 0, &benefit)
|
||||
add_val, mult_val, 0, &benefit, VOIDmode)
|
||||
/* Giv created by equivalent expression. */
|
||||
|| ((temp = find_reg_note (p, REG_EQUAL, NULL_RTX))
|
||||
&& general_induction_var (loop, XEXP (temp, 0), &src_reg,
|
||||
add_val, mult_val, 0, &benefit)))
|
||||
add_val, mult_val, 0, &benefit,
|
||||
VOIDmode)))
|
||||
&& src_reg == v->src_reg)
|
||||
{
|
||||
if (find_reg_note (p, REG_RETVAL, NULL_RTX))
|
||||
|
|
|
@ -1486,6 +1486,7 @@ extern void push_obstacks PARAMS ((struct obstack *,
|
|||
/* In cse.c */
|
||||
struct cse_basic_block_data;
|
||||
extern int rtx_cost PARAMS ((rtx, enum rtx_code));
|
||||
extern int address_cost PARAMS ((rtx, enum machine_mode));
|
||||
extern void delete_trivially_dead_insns PARAMS ((rtx, int));
|
||||
#ifdef BUFSIZ
|
||||
extern int cse_main PARAMS ((rtx, int, int, FILE *));
|
||||
|
|
Loading…
Add table
Reference in a new issue