aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog18
-rw-r--r--gcc/config/i386/i386-protos.h1
-rw-r--r--gcc/config/i386/i386.c58
-rw-r--r--gcc/config/i386/i386.h6
-rw-r--r--gcc/cse.c82
-rw-r--r--gcc/loop.c31
-rw-r--r--gcc/rtl.h1
7 files changed, 143 insertions, 54 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c563b21..b485d4f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index 420435f..3bd06b1 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -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));
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index b2e81a4..0d96728 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -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. */
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 8ae7be8..9f5a28d 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -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
diff --git a/gcc/cse.c b/gcc/cse.c
index 3e872e2..fe5e4a6 100644
--- a/gcc/cse.c
+++ b/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,
diff --git a/gcc/loop.c b/gcc/loop.c
index 02ac5d7..0969678 100644
--- a/gcc/loop.c
+++ b/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))
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 172691e..7a4d493 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -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 *));