expmed.c (synth_mult): When trying out a shift, pass the result of a signed shift.
authorKazu Hirata <kazu@codesourcery.com>
Sun, 3 May 2009 23:31:18 +0000 (23:31 +0000)
committerKazu Hirata <kazu@gcc.gnu.org>
Sun, 3 May 2009 23:31:18 +0000 (23:31 +0000)
* expmed.c (synth_mult): When trying out a shift, pass the result
of a signed shift.

From-SVN: r147087

gcc/ChangeLog
gcc/expmed.c

index b67be5b78e0dfa8f97d9a511027c18a8ac0ba26c..dcc0070b23207f5d28d0f068d8b6d25da04d938c 100644 (file)
@@ -1,3 +1,8 @@
+2009-05-04  Kazu Hirata  <kazu@codesourcery.com>
+
+       * expmed.c (synth_mult): When trying out a shift, pass the result
+       of a signed shift.
+
 2009-05-04  Kazu Hirata  <kazu@codesourcery.com>
 
        * expmed.c (shiftsub_cost): Rename to shiftsub0_cost.
index 7ffb693dcdd4db18fca0d01733251b9beca79e4b..d0c1621cc5e2655813f7d3e1972267cc69b9690a 100644 (file)
@@ -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;