diff options
-rw-r--r-- | gcc/ChangeLog | 18 | ||||
-rw-r--r-- | gcc/config/i386/i386-protos.h | 1 | ||||
-rw-r--r-- | gcc/config/i386/i386.c | 58 | ||||
-rw-r--r-- | gcc/config/i386/i386.h | 6 | ||||
-rw-r--r-- | gcc/cse.c | 82 | ||||
-rw-r--r-- | gcc/loop.c | 31 | ||||
-rw-r--r-- | gcc/rtl.h | 1 |
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 @@ -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, @@ -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 *)); |