aboutsummaryrefslogtreecommitdiff
path: root/gcc/expmed.c
diff options
context:
space:
mode:
authorKazu Hirata <kazu@codesourcery.com>2009-05-03 23:31:18 +0000
committerKazu Hirata <kazu@gcc.gnu.org>2009-05-03 23:31:18 +0000
commitddc2690ac0b80de267c5046b524638a40a24d572 (patch)
tree5f5db59d20cd73e728d53fddc169aa78116c6f00 /gcc/expmed.c
parentef268d34b78bed8d3e253fa00143b16817f68816 (diff)
downloadgcc-ddc2690ac0b80de267c5046b524638a40a24d572.zip
gcc-ddc2690ac0b80de267c5046b524638a40a24d572.tar.gz
gcc-ddc2690ac0b80de267c5046b524638a40a24d572.tar.bz2
expmed.c (synth_mult): When trying out a shift, pass the result of a signed shift.
* expmed.c (synth_mult): When trying out a shift, pass the result of a signed shift. From-SVN: r147087
Diffstat (limited to 'gcc/expmed.c')
-rw-r--r--gcc/expmed.c32
1 files changed, 32 insertions, 0 deletions
diff --git a/gcc/expmed.c b/gcc/expmed.c
index 7ffb693..d0c1621 100644
--- a/gcc/expmed.c
+++ b/gcc/expmed.c
@@ -2551,6 +2551,38 @@ synth_mult (struct algorithm *alg_out, unsigned HOST_WIDE_INT t,
best_alg->log[best_alg->ops] = m;
best_alg->op[best_alg->ops] = alg_shift;
}
+
+ /* See if treating ORIG_T as a signed number yields a better
+ sequence. Try this sequence only for a negative ORIG_T
+ as it would be useless for a non-negative ORIG_T. */
+ if ((HOST_WIDE_INT) orig_t < 0)
+ {
+ /* Shift ORIG_T as follows because a right shift of a
+ negative-valued signed type is implementation
+ defined. */
+ q = ~(~orig_t >> 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[speed][mode],
+ shift_cost[speed][mode][m]). */
+ op_cost = m * add_cost[speed][mode];
+ if (shift_cost[speed][mode][m] < op_cost)
+ op_cost = shift_cost[speed][mode][m];
+ new_limit.cost = best_cost.cost - op_cost;
+ new_limit.latency = best_cost.latency - op_cost;
+ synth_mult (alg_in, q, &new_limit, mode);
+
+ alg_in->cost.cost += op_cost;
+ alg_in->cost.latency += op_cost;
+ if (CHEAPER_MULT_COST (&alg_in->cost, &best_cost))
+ {
+ struct algorithm *x;
+ best_cost = alg_in->cost;
+ x = alg_in, alg_in = best_alg, best_alg = x;
+ best_alg->log[best_alg->ops] = m;
+ best_alg->op[best_alg->ops] = alg_shift;
+ }
+ }
}
if (cache_hit)
goto done;