Commit 630c79be by Bernd Schmidt Committed by Bernd Schmidt

Changes in cse.c/loop.c cost calculations

From-SVN: r36192
parent 39a10a29
2000-09-06 Bernd Schmidt <bernds@redhat.co.uk>
* Makefile.in (cse.o): Depend on $(BASIC_BLOCK_H).
* cse.c: Include "basic-block.h".
(struct table_elt): New field REGCOST.
(CHEAP_REG): Delete macro.
(COST): Return 0 for REGs.
(approx_reg_cost_1, approx_reg_cost, preferrable): New functions.
(notreg_cost): Return 0 for appropriate SUBREGs.
(COSTS_N_INSNS): Return N * 2.
(rtx_cost): Return 0 for REGs, and use cost of nested rtx for cheap
SUBREGs.
(CHEAPER): Use new function preferrable.
(insert): Initialize REGCOST member.
(find_best_addr): Use approx_reg_cost for estimation of register
usage.
(cse_insn): Likewise.
* loop.c (iv_add_mult_cost): New function.
(add_cost, shift_cost, mult_cost): Delete variables.
(init_loop): Don't initialize add_cost; reduce copy_cost by half.
(strength_reduce): Use iv_add_mult_cost instead of fixed add_cost.
Make code that detects autoinc opportunities slightly less optimistic.
(simplify_giv_expr): If expression contains other reg that is also a
giv, only increment benefit if this is the only use of that reg.
(consec_sets_giv): Take that change into account.
(combine_givs): Slightly more verbose output.
* i386.h (RTX_COSTS): For MULT, return true cost of multiplication,
not the cost of an equivalent shift.
* sh-protos.h (addsubcosts): Declare.
* sh.c (addsubcosts): New function.
* sh.h (CONST_COSTS): If CONST_OK_FOR_I, then return 0.
(RTX_COSTS): Tweak. Use addsubcosts.
(ADDRESS_COST): Return higher cost for reg+reg addressing.
2000-09-06 Geoff Keating <geoffk@cygnus.com> 2000-09-06 Geoff Keating <geoffk@cygnus.com>
* config/rs6000/rs6000.c (validate_condition_mode): New function. * config/rs6000/rs6000.c (validate_condition_mode): New function.
......
...@@ -1322,7 +1322,8 @@ simplify-rtx.o : simplify-rtx.c $(CONFIG_H) system.h $(RTL_H) $(REGS_H) \ ...@@ -1322,7 +1322,8 @@ simplify-rtx.o : simplify-rtx.c $(CONFIG_H) system.h $(RTL_H) $(REGS_H) \
hard-reg-set.h flags.h real.h insn-config.h $(RECOG_H) $(EXPR_H) toplev.h \ hard-reg-set.h flags.h real.h insn-config.h $(RECOG_H) $(EXPR_H) toplev.h \
output.h function.h cselib.h ggc.h $(OBSTACK_H) output.h function.h cselib.h ggc.h $(OBSTACK_H)
cse.o : cse.c $(CONFIG_H) system.h $(RTL_H) $(REGS_H) hard-reg-set.h flags.h \ cse.o : cse.c $(CONFIG_H) system.h $(RTL_H) $(REGS_H) hard-reg-set.h flags.h \
real.h insn-config.h $(RECOG_H) $(EXPR_H) toplev.h output.h function.h $(GGC_H) real.h insn-config.h $(RECOG_H) $(EXPR_H) toplev.h output.h function.h \
$(BASIC_BLOCK_H) $(GGC_H)
gcse.o : gcse.c $(CONFIG_H) system.h $(RTL_H) $(REGS_H) hard-reg-set.h \ gcse.o : gcse.c $(CONFIG_H) system.h $(RTL_H) $(REGS_H) hard-reg-set.h \
flags.h real.h insn-config.h $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) \ flags.h real.h insn-config.h $(RECOG_H) $(EXPR_H) $(BASIC_BLOCK_H) \
function.h output.h toplev.h function.h output.h toplev.h
......
...@@ -1978,22 +1978,14 @@ while (0) ...@@ -1978,22 +1978,14 @@ while (0)
unsigned HOST_WIDE_INT value = INTVAL (XEXP (X, 1)); \ unsigned HOST_WIDE_INT value = INTVAL (XEXP (X, 1)); \
int nbits = 0; \ int nbits = 0; \
\ \
if (value == 2) \
TOPLEVEL_COSTS_N_INSNS (ix86_cost->add); \
if (value == 4 || value == 8) \
TOPLEVEL_COSTS_N_INSNS (ix86_cost->lea); \
\
while (value != 0) \ while (value != 0) \
{ \ { \
nbits++; \ nbits++; \
value >>= 1; \ value >>= 1; \
} \ } \
\ \
if (nbits == 1) \ TOPLEVEL_COSTS_N_INSNS (ix86_cost->mult_init \
TOPLEVEL_COSTS_N_INSNS (ix86_cost->shift_const); \ + nbits * ix86_cost->mult_bit); \
else \
TOPLEVEL_COSTS_N_INSNS (ix86_cost->mult_init \
+ nbits * ix86_cost->mult_bit); \
} \ } \
else /* This is arbitrary */ \ else /* This is arbitrary */ \
TOPLEVEL_COSTS_N_INSNS (ix86_cost->mult_init \ TOPLEVEL_COSTS_N_INSNS (ix86_cost->mult_init \
......
...@@ -54,6 +54,7 @@ extern int prepare_move_operands PARAMS ((rtx[], enum machine_mode mode)); ...@@ -54,6 +54,7 @@ extern int prepare_move_operands PARAMS ((rtx[], enum machine_mode mode));
extern void from_compare PARAMS ((rtx *, int)); extern void from_compare PARAMS ((rtx *, int));
extern int shift_insns_rtx PARAMS ((rtx)); extern int shift_insns_rtx PARAMS ((rtx));
extern int shiftcosts PARAMS ((rtx)); extern int shiftcosts PARAMS ((rtx));
extern int addsubcosts PARAMS ((rtx));
extern int andcosts PARAMS ((rtx)); extern int andcosts PARAMS ((rtx));
extern int multcosts PARAMS ((rtx)); extern int multcosts PARAMS ((rtx));
extern void gen_ashift PARAMS ((int, int, rtx)); extern void gen_ashift PARAMS ((int, int, rtx));
......
...@@ -1012,6 +1012,25 @@ andcosts (x) ...@@ -1012,6 +1012,25 @@ andcosts (x)
return 3; return 3;
} }
/* Return the cost of an addition or a subtraction. */
int
addsubcosts (x)
rtx x;
{
/* Adding a register is a single cycle insn. */
if (GET_CODE (XEXP (x, 1)) != CONST_INT)
return 1;
/* Likewise for small constants. */
if (CONST_OK_FOR_I (INTVAL (XEXP (x, 1))))
return 1;
/* Any other constant requires a 2 cycle pc-relative load plus an
addition. */
return 3;
}
/* Return the cost of a multiply. */ /* Return the cost of a multiply. */
int int
multcosts (x) multcosts (x)
......
...@@ -1651,15 +1651,12 @@ extern int current_function_anonymous_args; ...@@ -1651,15 +1651,12 @@ extern int current_function_anonymous_args;
#define Pmode SImode #define Pmode SImode
#define FUNCTION_MODE Pmode #define FUNCTION_MODE Pmode
/* The relative costs of various types of constants. Note that cse.c defines /* The relative costs of various types of constants. */
REG = 1, SUBREG = 2, any node = (2 + sum of subnodes). */
#define CONST_COSTS(RTX, CODE, OUTER_CODE) \ #define CONST_COSTS(RTX, CODE, OUTER_CODE) \
case CONST_INT: \ case CONST_INT: \
if (INTVAL (RTX) == 0) \ if (CONST_OK_FOR_I (INTVAL (RTX))) \
return 0; \ return 0; \
else if (CONST_OK_FOR_I (INTVAL (RTX))) \
return 1; \
else if (((OUTER_CODE) == AND || (OUTER_CODE) == IOR || (OUTER_CODE) == XOR) \ else if (((OUTER_CODE) == AND || (OUTER_CODE) == IOR || (OUTER_CODE) == XOR) \
&& CONST_OK_FOR_L (INTVAL (RTX))) \ && CONST_OK_FOR_L (INTVAL (RTX))) \
return 1; \ return 1; \
...@@ -1674,10 +1671,7 @@ extern int current_function_anonymous_args; ...@@ -1674,10 +1671,7 @@ extern int current_function_anonymous_args;
#define RTX_COSTS(X, CODE, OUTER_CODE) \ #define RTX_COSTS(X, CODE, OUTER_CODE) \
case PLUS: \ case PLUS: \
return (COSTS_N_INSNS (1) \ return COSTS_N_INSNS (addsubcosts (X)); \
+ rtx_cost (XEXP ((X), 0), PLUS) \
+ (rtx_equal_p (XEXP ((X), 0), XEXP ((X), 1))\
? 0 : rtx_cost (XEXP ((X), 1), PLUS)));\
case AND: \ case AND: \
return COSTS_N_INSNS (andcosts (X)); \ return COSTS_N_INSNS (andcosts (X)); \
case MULT: \ case MULT: \
...@@ -1685,13 +1679,7 @@ extern int current_function_anonymous_args; ...@@ -1685,13 +1679,7 @@ extern int current_function_anonymous_args;
case ASHIFT: \ case ASHIFT: \
case ASHIFTRT: \ case ASHIFTRT: \
case LSHIFTRT: \ case LSHIFTRT: \
/* Add one extra unit for the matching constraint. \ return COSTS_N_INSNS (shiftcosts (X)); \
Otherwise loop strength reduction would think that\
a shift with different sourc and destination is \
as cheap as adding a constant to a register. */ \
return (COSTS_N_INSNS (shiftcosts (X)) \
+ rtx_cost (XEXP ((X), 0), (CODE)) \
+ 1); \
case DIV: \ case DIV: \
case UDIV: \ case UDIV: \
case MOD: \ case MOD: \
...@@ -1768,11 +1756,11 @@ while (0) ...@@ -1768,11 +1756,11 @@ while (0)
&& nonpic_symbol_mentioned_p (X)) && nonpic_symbol_mentioned_p (X))
/* Compute the cost of an address. For the SH, all valid addresses are /* Compute the cost of an address. For the SH, all valid addresses are
the same cost. */ the same cost. Use a slightly higher cost for reg + reg addressing,
/* ??? Perhaps we should make reg+reg addresses have higher cost because since it increases pressure on r0. */
they add to register pressure on r0. */
#define ADDRESS_COST(RTX) 1 #define ADDRESS_COST(X) (GET_CODE (X) == PLUS && ! CONSTANT_P (XEXP (X, 1)) \
? 1 : 0)
/* Compute extra cost of moving data between one register class /* Compute extra cost of moving data between one register class
and another. */ and another. */
......
...@@ -312,6 +312,7 @@ static void try_swap_copy_prop PARAMS ((const struct loop *, rtx, ...@@ -312,6 +312,7 @@ static void try_swap_copy_prop PARAMS ((const struct loop *, rtx,
static int replace_label PARAMS ((rtx *, void *)); static int replace_label PARAMS ((rtx *, void *));
static rtx check_insn_for_givs PARAMS((struct loop *, rtx, int, int)); static rtx check_insn_for_givs PARAMS((struct loop *, rtx, int, int));
static rtx check_insn_for_bivs PARAMS((struct loop *, rtx, int, int)); static rtx check_insn_for_bivs PARAMS((struct loop *, rtx, int, int));
static int iv_add_mult_cost PARAMS ((rtx, rtx, rtx, rtx));
static void loop_dump_aux PARAMS ((const struct loop *, FILE *, int)); static void loop_dump_aux PARAMS ((const struct loop *, FILE *, int));
void debug_loop PARAMS ((const struct loop *)); void debug_loop PARAMS ((const struct loop *));
...@@ -341,13 +342,6 @@ static int compute_luids PARAMS ((rtx, rtx, int)); ...@@ -341,13 +342,6 @@ static int compute_luids PARAMS ((rtx, rtx, int));
static int biv_elimination_giv_has_0_offset PARAMS ((struct induction *, static int biv_elimination_giv_has_0_offset PARAMS ((struct induction *,
struct induction *, rtx)); struct induction *, rtx));
/* Relative gain of eliminating various kinds of operations. */
static int add_cost;
#if 0
static int shift_cost;
static int mult_cost;
#endif
/* Benefit penalty, if a giv is not replaceable, i.e. must emit an insn to /* Benefit penalty, if a giv is not replaceable, i.e. must emit an insn to
copy the value of the strength reduced giv to its original register. */ copy the value of the strength reduced giv to its original register. */
static int copy_cost; static int copy_cost;
...@@ -361,15 +355,9 @@ init_loop () ...@@ -361,15 +355,9 @@ init_loop ()
char *free_point = (char *) oballoc (1); char *free_point = (char *) oballoc (1);
rtx reg = gen_rtx_REG (word_mode, LAST_VIRTUAL_REGISTER + 1); rtx reg = gen_rtx_REG (word_mode, LAST_VIRTUAL_REGISTER + 1);
add_cost = rtx_cost (gen_rtx_PLUS (word_mode, reg, reg), SET);
reg_address_cost = address_cost (reg, SImode); reg_address_cost = address_cost (reg, SImode);
/* We multiply by 2 to reconcile the difference in scale between copy_cost = 2;
these two ways of computing costs. Otherwise the cost of a copy
will be far less than the cost of an add. */
copy_cost = 2 * 2;
/* Free the objects we just allocated. */ /* Free the objects we just allocated. */
obfree (free_point); obfree (free_point);
...@@ -3825,6 +3813,7 @@ strength_reduce (loop, insn_count, flags) ...@@ -3825,6 +3813,7 @@ strength_reduce (loop, insn_count, flags)
rtx loop_start = loop->start; rtx loop_start = loop->start;
rtx loop_end = loop->end; rtx loop_end = loop->end;
rtx loop_scan_start = loop->scan_start; rtx loop_scan_start = loop->scan_start;
rtx test_reg = gen_rtx_REG (word_mode, LAST_VIRTUAL_REGISTER + 1);
VARRAY_INT_INIT (reg_iv_type, max_reg_before_loop, "reg_iv_type"); VARRAY_INT_INIT (reg_iv_type, max_reg_before_loop, "reg_iv_type");
VARRAY_GENERIC_PTR_INIT (reg_iv_info, max_reg_before_loop, "reg_iv_info"); VARRAY_GENERIC_PTR_INIT (reg_iv_info, max_reg_before_loop, "reg_iv_info");
...@@ -4436,11 +4425,15 @@ strength_reduce (loop, insn_count, flags) ...@@ -4436,11 +4425,15 @@ strength_reduce (loop, insn_count, flags)
for (v = bl->giv; v; v = v->next_iv) for (v = bl->giv; v; v = v->next_iv)
{ {
struct induction *tv; struct induction *tv;
int add_cost;
if (v->ignore || v->same) if (v->ignore || v->same)
continue; continue;
benefit = v->benefit; benefit = v->benefit;
PUT_MODE (test_reg, v->mode);
add_cost = iv_add_mult_cost (bl->biv->add_val, v->mult_val,
test_reg, test_reg);
/* Reduce benefit if not replaceable, since we will insert /* Reduce benefit if not replaceable, since we will insert
a move-insn to replace the insn that calculates this giv. a move-insn to replace the insn that calculates this giv.
...@@ -4457,7 +4450,14 @@ strength_reduce (loop, insn_count, flags) ...@@ -4457,7 +4450,14 @@ strength_reduce (loop, insn_count, flags)
benefit -= copy_cost; benefit -= copy_cost;
/* Decrease the benefit to count the add-insns that we will /* Decrease the benefit to count the add-insns that we will
insert to increment the reduced reg for the giv. */ insert to increment the reduced reg for the giv.
??? This can overestimate the run-time cost of the additional
insns, e.g. if there are multiple basic blocks that increment
the biv, but only one of these blocks is executed during each
iteration. There is no good way to detect cases like this with
the current structure of the loop optimizer.
This code is more accurate for determining code size than
run-time benefits. */
benefit -= add_cost * bl->biv_count; benefit -= add_cost * bl->biv_count;
/* Decide whether to strength-reduce this giv or to leave the code /* Decide whether to strength-reduce this giv or to leave the code
...@@ -4469,6 +4469,10 @@ strength_reduce (loop, insn_count, flags) ...@@ -4469,6 +4469,10 @@ strength_reduce (loop, insn_count, flags)
new add insns; if so, increase BENEFIT (undo the subtraction of new add insns; if so, increase BENEFIT (undo the subtraction of
add_cost that was done above). */ add_cost that was done above). */
if (v->giv_type == DEST_ADDR if (v->giv_type == DEST_ADDR
/* Increasing the benefit is risky, since this is only a guess.
Avoid increasing register pressure in cases where there would
be no other benefit from reducing this giv. */
&& benefit > 0
&& GET_CODE (v->mult_val) == CONST_INT) && GET_CODE (v->mult_val) == CONST_INT)
{ {
if (HAVE_POST_INCREMENT if (HAVE_POST_INCREMENT
...@@ -6439,7 +6443,20 @@ simplify_giv_expr (loop, x, benefit) ...@@ -6439,7 +6443,20 @@ simplify_giv_expr (loop, x, benefit)
/* Form expression from giv and add benefit. Ensure this giv /* Form expression from giv and add benefit. Ensure this giv
can derive another and subtract any needed adjustment if so. */ can derive another and subtract any needed adjustment if so. */
*benefit += v->benefit;
/* Increasing the benefit here is risky. The only case in which it
is arguably correct is if this is the only use of V. In other
cases, this will artificially inflate the benefit of the current
giv, and lead to suboptimal code. Thus, it is disabled, since
potentially not reducing an only marginally beneficial giv is
less harmful than reducing many givs that are not really
beneficial. */
{
rtx single_use = VARRAY_RTX (reg_single_usage, REGNO (x));
if (single_use && single_use != const0_rtx)
*benefit += v->benefit;
}
if (v->cant_derive) if (v->cant_derive)
return 0; return 0;
...@@ -6683,7 +6700,7 @@ consec_sets_giv (loop, first_benefit, p, src_reg, dest_reg, ...@@ -6683,7 +6700,7 @@ consec_sets_giv (loop, first_benefit, p, src_reg, dest_reg,
count--; count--;
v->mult_val = *mult_val; v->mult_val = *mult_val;
v->add_val = *add_val; v->add_val = *add_val;
v->benefit = benefit; v->benefit += benefit;
} }
else if (code != NOTE) else if (code != NOTE)
{ {
...@@ -7098,8 +7115,9 @@ restart: ...@@ -7098,8 +7115,9 @@ restart:
if (loop_dump_stream) if (loop_dump_stream)
fprintf (loop_dump_stream, fprintf (loop_dump_stream,
"giv at %d combined with giv at %d\n", "giv at %d combined with giv at %d; new benefit %d + %d, lifetime %d\n",
INSN_UID (g2->insn), INSN_UID (g1->insn)); INSN_UID (g2->insn), INSN_UID (g1->insn),
g1->benefit, g1_add_benefit, g1->lifetime);
} }
} }
...@@ -7613,6 +7631,34 @@ emit_iv_add_mult (b, m, a, reg, insert_before) ...@@ -7613,6 +7631,34 @@ emit_iv_add_mult (b, m, a, reg, insert_before)
&& GET_CODE (SET_DEST (seq)) == REG) && GET_CODE (SET_DEST (seq)) == REG)
record_base_value (REGNO (SET_DEST (seq)), SET_SRC (seq), 0); record_base_value (REGNO (SET_DEST (seq)), SET_SRC (seq), 0);
} }
/* Similar to emit_iv_add_mult, but compute cost rather than emitting
insns. */
static int
iv_add_mult_cost (b, m, a, reg)
rtx b; /* initial value of basic induction variable */
rtx m; /* multiplicative constant */
rtx a; /* additive constant */
rtx reg; /* destination register */
{
int cost = 0;
rtx last, result;
start_sequence ();
result = expand_mult_add (b, reg, m, a, GET_MODE (reg), 0);
if (reg != result)
emit_move_insn (reg, result);
last = get_last_insn ();
while (last)
{
rtx t = single_set (last);
if (t)
cost += rtx_cost (SET_SRC (t), SET);
last = PREV_INSN (last);
}
end_sequence ();
return cost;
}
/* Test whether A * B can be computed without /* Test whether A * B can be computed without
an actual multiply insn. Value is 1 if so. */ an actual multiply insn. Value is 1 if so. */
......
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