From ddc2690ac0b80de267c5046b524638a40a24d572 Mon Sep 17 00:00:00 2001 From: Kazu Hirata Date: Sun, 3 May 2009 23:31:18 +0000 Subject: [PATCH] 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 --- gcc/ChangeLog | 5 +++++ gcc/expmed.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b67be5b78e0..dcc0070b232 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2009-05-04 Kazu Hirata + + * expmed.c (synth_mult): When trying out a shift, pass the result + of a signed shift. + 2009-05-04 Kazu Hirata * expmed.c (shiftsub_cost): Rename to shiftsub0_cost. diff --git a/gcc/expmed.c b/gcc/expmed.c index 7ffb693dcdd..d0c1621cc5e 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;