aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/expmed.c25
2 files changed, 31 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 46f3360..92a4d69 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2004-06-30 Roger Sayle <roger@eyesopen.com>
+
+ * expmed.c (expand_shift): Consider expanding LSHIFT_EXPR by a
+ constant as a sequence of additions depending upon the rtx_costs.
+ (synth_mult): Update the "observed" cost of a shift, based upon
+ the above optimization.
+
2004-06-28 Geoffrey Keating <geoffk@apple.com>
Andreas Tobler <a.tobler@schweiz.ch>
diff --git a/gcc/expmed.c b/gcc/expmed.c
index a2278b9..e95a626 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -2017,6 +2017,24 @@ expand_shift (enum tree_code code, enum machine_mode mode, rtx shifted,
if (op1 == const0_rtx)
return shifted;
+ /* Check whether its cheaper to implement a left shift by a constant
+ bit count by a sequence of additions. */
+ if (code == LSHIFT_EXPR
+ && GET_CODE (op1) == CONST_INT
+ && INTVAL (op1) > 0
+ && INTVAL (op1) < GET_MODE_BITSIZE (mode)
+ && shift_cost[mode][INTVAL (op1)] > INTVAL (op1) * add_cost[mode])
+ {
+ int i;
+ for (i = 0; i < INTVAL (op1); i++)
+ {
+ temp = force_reg (mode, shifted);
+ shifted = expand_binop (mode, add_optab, temp, temp, NULL_RTX,
+ unsignedp, OPTAB_LIB_WIDEN);
+ }
+ return shifted;
+ }
+
for (try = 0; temp == 0 && try < 3; try++)
{
enum optab_methods methods;
@@ -2242,7 +2260,12 @@ synth_mult (struct algorithm *alg_out, unsigned HOST_WIDE_INT t,
if (m < maxm)
{
q = t >> m;
- cost = shift_cost[mode][m];
+ /* The function expand_shift will choose between a shift and
+ a sequence of additions, so the observed cost is given as
+ MIN (m * add_cost[mode], shift_cost[mode][m]). */
+ cost = m * add_cost[mode];
+ if (shift_cost[mode][m] < cost)
+ cost = shift_cost[mode][m];
synth_mult (alg_in, q, cost_limit - cost, mode);
cost += alg_in->cost;