This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] Superscalar tweaks to synth_mult


On Mon, 30 Aug 2004, Richard Henderson wrote:
> Some more commentary would be nice.

No problem.  How about the following?  I also noticed that the
"enum alg_code" enumeration contains some unused/undocumented
values that have been there since CVS revision 1.1.  I took the
liberty of removing them at the top of this patch.

Just to be safe, I've rebootstrapped and regression tested this
patch (even though the most significant changes are additional
commentary :) on i686-pc-linux-gnu against yesterday's mainline.
Once again, there are no new failures with a top-level "make -k
check" built with all default languages, and the I've reconfirmed
by hand the code improvements documented in my original posting.



2004-08-31  Roger Sayle  <roger@eyesopen.com>

	* expmed.c (enum alg_code): Remove long unused enumeration values.
        (struct mult_cost): New structure to hold the "score" of a synthetic
	multiply sequence, including both a rtx_cost and a latency field.
	(MULT_COST_LESS): New macro to compare mult_cost to a constant.
	(CHEAPER_MULT_COST): New macro to compare two mult_costs.
	(struct algorithm): Change type of cost field to be mult_cost.
	(synth_mult): Change type of cost_limit argument to be a
	pointer to a mult_cost.  Update all cost comparisons to use the
	new mult_cost infrastructure.  For alg_add_factor and
	alg_sub_factor operations, latency is lower than the rtx_cost.
	(choose_mult_variant):  Update calls to synth_mult.  Perform
	cost comparisons using the new mult_cost infrastructure.
	(expand_mult_highpart): Use alg.cost.cost instead of alg.cost
	to optain the total rtx_cost of a synth_mult "algorithm".


Index: expmed.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expmed.c,v
retrieving revision 1.193
diff -c -3 -p -r1.193 expmed.c
*** expmed.c	25 Aug 2004 09:51:22 -0000	1.193
--- expmed.c	31 Aug 2004 16:01:13 -0000
*************** expand_shift (enum tree_code code, enum
*** 2153,2160 ****
  enum alg_code { alg_zero, alg_m, alg_shift,
  		  alg_add_t_m2, alg_sub_t_m2,
  		  alg_add_factor, alg_sub_factor,
! 		  alg_add_t2_m, alg_sub_t2_m,
! 		  alg_add, alg_subtract, alg_factor, alg_shiftop };

  /* This structure records a sequence of operations.
     `ops' is the number of operations recorded.
--- 2153,2189 ----
  enum alg_code { alg_zero, alg_m, alg_shift,
  		  alg_add_t_m2, alg_sub_t_m2,
  		  alg_add_factor, alg_sub_factor,
! 		  alg_add_t2_m, alg_sub_t2_m };
!
! /* This structure holds the "cost" of a multiply sequence.  The
!    "cost" field holds the total rtx_cost of every operator in the
!    synthetic multiplication sequence, hence cost(a op b) is defined
!    as rtx_cost(op) + cost(a) + cost(b), where cost(leaf) is zero.
!    The "latency" field holds the minimum possible latency of the
!    synthetic multiply, on a hypothetical infinitely parallel CPU.
!    This is the critical path, or the maximum height, of the expression
!    tree which is the sum of rtx_costs on the most expensive path from
!    any leaf to the root.  Hence latency(a op b) is defined as zero for
!    leaves and rtx_cost(op) + max(latency(a), latency(b)) otherwise. */
!
! struct mult_cost {
!   short cost;     /* Total rtx_cost of the multiplication sequence.  */
!   short latency;  /* The latency of the multiplication sequence.  */
! };
!
! /* This macro is used to compare a pointer to a mult_cost against an
!    single integer "rtx_cost" value.  This is equivalent to the macro
!    CHEAPER_MULT_COST(X,Z) where Z = {Y,Y}.  */
! #define MULT_COST_LESS(X,Y) ((X)->cost < (Y)	\
! 			     || ((X)->cost == (Y) && (X)->latency < (Y)))
!
! /* This macro is used to compare two pointers to mult_costs against
!    each other.  The macro returns true if X is cheaper than Y.
!    Currently, the cheaper of two mult_costs is the one with the
!    lower "cost".  If "cost"s are tied, the lower latency is cheaper.  */
! #define CHEAPER_MULT_COST(X,Y)  ((X)->cost < (Y)->cost		\
! 				 || ((X)->cost == (Y)->cost	\
! 				     && (X)->latency < (Y)->latency))

  /* This structure records a sequence of operations.
     `ops' is the number of operations recorded.
*************** enum alg_code { alg_zero, alg_m, alg_shi
*** 2177,2183 ****

  struct algorithm
  {
!   short cost;
    short ops;
    /* The size of the OP and LOG fields are not directly related to the
       word size, but the worst-case algorithms will be if we have few
--- 2206,2212 ----

  struct algorithm
  {
!   struct mult_cost cost;
    short ops;
    /* The size of the OP and LOG fields are not directly related to the
       word size, but the worst-case algorithms will be if we have few
*************** struct algorithm
*** 2195,2201 ****
  enum mult_variant {basic_variant, negate_variant, add_variant};

  static void synth_mult (struct algorithm *, unsigned HOST_WIDE_INT,
! 			int, enum machine_mode mode);
  static bool choose_mult_variant (enum machine_mode, HOST_WIDE_INT,
  				 struct algorithm *, enum mult_variant *, int);
  static rtx expand_mult_const (enum machine_mode, rtx, HOST_WIDE_INT, rtx,
--- 2224,2230 ----
  enum mult_variant {basic_variant, negate_variant, add_variant};

  static void synth_mult (struct algorithm *, unsigned HOST_WIDE_INT,
! 			const struct mult_cost *, enum machine_mode mode);
  static bool choose_mult_variant (enum machine_mode, HOST_WIDE_INT,
  				 struct algorithm *, enum mult_variant *, int);
  static rtx expand_mult_const (enum machine_mode, rtx, HOST_WIDE_INT, rtx,
*************** static rtx expand_mult_highpart_optab (e
*** 2215,2233 ****

  static void
  synth_mult (struct algorithm *alg_out, unsigned HOST_WIDE_INT t,
! 	    int cost_limit, enum machine_mode mode)
  {
    int m;
    struct algorithm *alg_in, *best_alg;
!   int cost;
    unsigned HOST_WIDE_INT q;
    int maxm = MIN (BITS_PER_WORD, GET_MODE_BITSIZE (mode));

    /* Indicate that no algorithm is yet found.  If no algorithm
       is found, this value will be returned and indicate failure.  */
!   alg_out->cost = cost_limit;

!   if (cost_limit <= 0)
      return;

    /* Restrict the bits of "t" to the multiplication's mode.  */
--- 2244,2265 ----

  static void
  synth_mult (struct algorithm *alg_out, unsigned HOST_WIDE_INT t,
! 	    const struct mult_cost *cost_limit, enum machine_mode mode)
  {
    int m;
    struct algorithm *alg_in, *best_alg;
!   struct mult_cost best_cost;
!   struct mult_cost new_limit;
!   int op_cost, op_latency;
    unsigned HOST_WIDE_INT q;
    int maxm = MIN (BITS_PER_WORD, GET_MODE_BITSIZE (mode));

    /* Indicate that no algorithm is yet found.  If no algorithm
       is found, this value will be returned and indicate failure.  */
!   alg_out->cost.cost = cost_limit->cost + 1;

!   if (cost_limit->cost < 0
!       || (cost_limit->cost == 0 && cost_limit->latency <= 0))
      return;

    /* Restrict the bits of "t" to the multiplication's mode.  */
*************** synth_mult (struct algorithm *alg_out, u
*** 2237,2243 ****
    if (t == 1)
      {
        alg_out->ops = 1;
!       alg_out->cost = 0;
        alg_out->op[0] = alg_m;
        return;
      }
--- 2269,2276 ----
    if (t == 1)
      {
        alg_out->ops = 1;
!       alg_out->cost.cost = 0;
!       alg_out->cost.latency = 0;
        alg_out->op[0] = alg_m;
        return;
      }
*************** synth_mult (struct algorithm *alg_out, u
*** 2246,2257 ****
       fail now.  */
    if (t == 0)
      {
!       if (zero_cost >= cost_limit)
  	return;
        else
  	{
  	  alg_out->ops = 1;
! 	  alg_out->cost = zero_cost;
  	  alg_out->op[0] = alg_zero;
  	  return;
  	}
--- 2279,2291 ----
       fail now.  */
    if (t == 0)
      {
!       if (MULT_COST_LESS (cost_limit, zero_cost))
  	return;
        else
  	{
  	  alg_out->ops = 1;
! 	  alg_out->cost.cost = zero_cost;
! 	  alg_out->cost.latency = zero_cost;
  	  alg_out->op[0] = alg_zero;
  	  return;
  	}
*************** synth_mult (struct algorithm *alg_out, u
*** 2261,2266 ****
--- 2295,2301 ----

    alg_in = alloca (sizeof (struct algorithm));
    best_alg = alloca (sizeof (struct algorithm));
+   best_cost = *cost_limit;

    /* If we have a group of zero bits at the low-order part of T, try
       multiplying by the remaining bits and then doing a shift.  */
*************** synth_mult (struct algorithm *alg_out, u
*** 2274,2292 ****
  	  /* 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;
! 	  if (cost < cost_limit)
  	    {
  	      struct algorithm *x;
  	      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;
- 	      cost_limit = cost;
  	    }
  	}
      }
--- 2309,2330 ----
  	  /* 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]).  */
! 	  op_cost = m * add_cost[mode];
! 	  if (shift_cost[mode][m] < op_cost)
! 	    op_cost = shift_cost[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;
  	    }
  	}
      }
*************** synth_mult (struct algorithm *alg_out, u
*** 2311,2344 ****
  	{
  	  /* T ends with ...111.  Multiply by (T + 1) and subtract 1.  */

! 	  cost = add_cost[mode];
! 	  synth_mult (alg_in, t + 1, cost_limit - cost, mode);
!
! 	  cost += alg_in->cost;
! 	  if (cost < cost_limit)
  	    {
  	      struct algorithm *x;
  	      x = alg_in, alg_in = best_alg, best_alg = x;
  	      best_alg->log[best_alg->ops] = 0;
  	      best_alg->op[best_alg->ops] = alg_sub_t_m2;
- 	      cost_limit = cost;
  	    }
  	}
        else
  	{
  	  /* T ends with ...01 or ...011.  Multiply by (T - 1) and add 1.  */

! 	  cost = add_cost[mode];
! 	  synth_mult (alg_in, t - 1, cost_limit - cost, mode);
!
! 	  cost += alg_in->cost;
! 	  if (cost < cost_limit)
  	    {
  	      struct algorithm *x;
  	      x = alg_in, alg_in = best_alg, best_alg = x;
  	      best_alg->log[best_alg->ops] = 0;
  	      best_alg->op[best_alg->ops] = alg_add_t_m2;
- 	      cost_limit = cost;
  	    }
  	}
      }
--- 2349,2388 ----
  	{
  	  /* T ends with ...111.  Multiply by (T + 1) and subtract 1.  */

! 	  op_cost = add_cost[mode];
! 	  new_limit.cost = best_cost.cost - op_cost;
! 	  new_limit.latency = best_cost.latency - op_cost;
! 	  synth_mult (alg_in, t + 1, &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] = 0;
  	      best_alg->op[best_alg->ops] = alg_sub_t_m2;
  	    }
  	}
        else
  	{
  	  /* T ends with ...01 or ...011.  Multiply by (T - 1) and add 1.  */

! 	  op_cost = add_cost[mode];
! 	  new_limit.cost = best_cost.cost - op_cost;
! 	  new_limit.latency = best_cost.latency - op_cost;
! 	  synth_mult (alg_in, t - 1, &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] = 0;
  	      best_alg->op[best_alg->ops] = alg_add_t_m2;
  	    }
  	}
      }
*************** synth_mult (struct algorithm *alg_out, u
*** 2360,2378 ****
        d = ((unsigned HOST_WIDE_INT) 1 << m) + 1;
        if (t % d == 0 && t > d && m < maxm)
  	{
! 	  cost = add_cost[mode] + shift_cost[mode][m];
! 	  if (shiftadd_cost[mode][m] < cost)
! 	    cost = shiftadd_cost[mode][m];
! 	  synth_mult (alg_in, t / d, cost_limit - cost, mode);

! 	  cost += alg_in->cost;
! 	  if (cost < cost_limit)
  	    {
  	      struct algorithm *x;
  	      x = alg_in, alg_in = best_alg, best_alg = x;
  	      best_alg->log[best_alg->ops] = m;
  	      best_alg->op[best_alg->ops] = alg_add_factor;
- 	      cost_limit = cost;
  	    }
  	  /* Other factors will have been taken care of in the recursion.  */
  	  break;
--- 2404,2439 ----
        d = ((unsigned HOST_WIDE_INT) 1 << m) + 1;
        if (t % d == 0 && t > d && m < maxm)
  	{
! 	  /* If the target has a cheap shift-and-add instruction use
! 	     that in preference to a shift insn followed by an add insn.
! 	     Assume that the shift-and-add is "atomic" with a latency
! 	     equal to it's cost, otherwise assume that on superscalar
! 	     hardware the shift may be executed concurrently with the
! 	     earlier steps in the algorithm.  */
! 	  op_cost = add_cost[mode] + shift_cost[mode][m];
! 	  if (shiftadd_cost[mode][m] < op_cost)
! 	    {
! 	      op_cost = shiftadd_cost[mode][m];
! 	      op_latency = op_cost;
! 	    }
! 	  else
! 	    op_latency = add_cost[mode];

! 	  new_limit.cost = best_cost.cost - op_cost;
! 	  new_limit.latency = best_cost.latency - op_latency;
! 	  synth_mult (alg_in, t / d, &new_limit, mode);
!
! 	  alg_in->cost.cost += op_cost;
! 	  alg_in->cost.latency += op_latency;
! 	  if (alg_in->cost.latency < 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_add_factor;
  	    }
  	  /* Other factors will have been taken care of in the recursion.  */
  	  break;
*************** synth_mult (struct algorithm *alg_out, u
*** 2381,2399 ****
        d = ((unsigned HOST_WIDE_INT) 1 << m) - 1;
        if (t % d == 0 && t > d && m < maxm)
  	{
! 	  cost = add_cost[mode] + shift_cost[mode][m];
! 	  if (shiftsub_cost[mode][m] < cost)
! 	    cost = shiftsub_cost[mode][m];
! 	  synth_mult (alg_in, t / d, cost_limit - cost, mode);

! 	  cost += alg_in->cost;
! 	  if (cost < cost_limit)
  	    {
  	      struct algorithm *x;
  	      x = alg_in, alg_in = best_alg, best_alg = x;
  	      best_alg->log[best_alg->ops] = m;
  	      best_alg->op[best_alg->ops] = alg_sub_factor;
- 	      cost_limit = cost;
  	    }
  	  break;
  	}
--- 2442,2477 ----
        d = ((unsigned HOST_WIDE_INT) 1 << m) - 1;
        if (t % d == 0 && t > d && m < maxm)
  	{
! 	  /* If the target has a cheap shift-and-subtract insn use
! 	     that in preference to a shift insn followed by a sub insn.
! 	     Assume that the shift-and-sub is "atomic" with a latency
! 	     equal to it's cost, otherwise assume that on superscalar
! 	     hardware the shift may be executed concurrently with the
! 	     earlier steps in the algorithm.  */
! 	  op_cost = add_cost[mode] + shift_cost[mode][m];
! 	  if (shiftsub_cost[mode][m] < op_cost)
! 	    {
! 	      op_cost = shiftsub_cost[mode][m];
! 	      op_latency = op_cost;
! 	    }
! 	  else
! 	    op_latency = add_cost[mode];

! 	  new_limit.cost = best_cost.cost - op_cost;
! 	  new_limit.cost = best_cost.cost - op_latency;
! 	  synth_mult (alg_in, t / d, &new_limit, mode);
!
! 	  alg_in->cost.cost += op_cost;
! 	  alg_in->cost.latency += op_latency;
! 	  if (alg_in->cost.latency < 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_sub_factor;
  	    }
  	  break;
  	}
*************** synth_mult (struct algorithm *alg_out, u
*** 2408,2424 ****
        m = exact_log2 (q);
        if (m >= 0 && m < maxm)
  	{
! 	  cost = shiftadd_cost[mode][m];
! 	  synth_mult (alg_in, (t - 1) >> m, cost_limit - cost, mode);
!
! 	  cost += alg_in->cost;
! 	  if (cost < cost_limit)
  	    {
  	      struct algorithm *x;
  	      x = alg_in, alg_in = best_alg, best_alg = x;
  	      best_alg->log[best_alg->ops] = m;
  	      best_alg->op[best_alg->ops] = alg_add_t2_m;
- 	      cost_limit = cost;
  	    }
  	}

--- 2486,2505 ----
        m = exact_log2 (q);
        if (m >= 0 && m < maxm)
  	{
! 	  op_cost = shiftadd_cost[mode][m];
! 	  new_limit.cost = best_cost.cost - op_cost;
! 	  new_limit.latency = best_cost.latency - op_cost;
! 	  synth_mult (alg_in, (t - 1) >> m, &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_add_t2_m;
  	    }
  	}

*************** synth_mult (struct algorithm *alg_out, u
*** 2427,2462 ****
        m = exact_log2 (q);
        if (m >= 0 && m < maxm)
  	{
! 	  cost = shiftsub_cost[mode][m];
! 	  synth_mult (alg_in, (t + 1) >> m, cost_limit - cost, mode);
!
! 	  cost += alg_in->cost;
! 	  if (cost < cost_limit)
  	    {
  	      struct algorithm *x;
  	      x = alg_in, alg_in = best_alg, best_alg = x;
  	      best_alg->log[best_alg->ops] = m;
  	      best_alg->op[best_alg->ops] = alg_sub_t2_m;
- 	      cost_limit = cost;
  	    }
  	}
      }

-   /* If cost_limit has not decreased since we stored it in alg_out->cost,
-      we have not found any algorithm.  */
-   if (cost_limit == alg_out->cost)
-     return;
-
    /* If we are getting a too long sequence for `struct algorithm'
       to record, make this search fail.  */
    if (best_alg->ops == MAX_BITS_PER_WORD)
      return;

    /* Copy the algorithm from temporary space to the space at alg_out.
       We avoid using structure assignment because the majority of
       best_alg is normally undefined, and this is a critical function.  */
    alg_out->ops = best_alg->ops + 1;
!   alg_out->cost = cost_limit;
    memcpy (alg_out->op, best_alg->op,
  	  alg_out->ops * sizeof *alg_out->op);
    memcpy (alg_out->log, best_alg->log,
--- 2508,2545 ----
        m = exact_log2 (q);
        if (m >= 0 && m < maxm)
  	{
! 	  op_cost = shiftsub_cost[mode][m];
! 	  new_limit.cost = best_cost.cost - op_cost;
! 	  new_limit.latency = best_cost.latency - op_cost;
! 	  synth_mult (alg_in, (t + 1) >> m, &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_sub_t2_m;
  	    }
  	}
      }

    /* If we are getting a too long sequence for `struct algorithm'
       to record, make this search fail.  */
    if (best_alg->ops == MAX_BITS_PER_WORD)
      return;

+   /* If best_cost has not decreased, we have not found any algorithm.  */
+   if (!CHEAPER_MULT_COST (&best_cost, cost_limit))
+     return;
+
    /* Copy the algorithm from temporary space to the space at alg_out.
       We avoid using structure assignment because the majority of
       best_alg is normally undefined, and this is a critical function.  */
    alg_out->ops = best_alg->ops + 1;
!   alg_out->cost = best_cost;
    memcpy (alg_out->op, best_alg->op,
  	  alg_out->ops * sizeof *alg_out->op);
    memcpy (alg_out->log, best_alg->log,
*************** choose_mult_variant (enum machine_mode m
*** 2479,2507 ****
  		     int mult_cost)
  {
    struct algorithm alg2;

    *variant = basic_variant;
!   synth_mult (alg, val, mult_cost, mode);

    /* This works only if the inverted value actually fits in an
       `unsigned int' */
    if (HOST_BITS_PER_INT >= GET_MODE_BITSIZE (mode))
      {
!       synth_mult (&alg2, -val, MIN (alg->cost, mult_cost) - neg_cost[mode],
! 		  mode);
!       alg2.cost += neg_cost[mode];
!       if (alg2.cost < alg->cost)
  	*alg = alg2, *variant = negate_variant;
      }

    /* This proves very useful for division-by-constant.  */
!   synth_mult (&alg2, val - 1, MIN (alg->cost, mult_cost) - add_cost[mode],
! 	      mode);
!   alg2.cost += add_cost[mode];
!   if (alg2.cost < alg->cost)
      *alg = alg2, *variant = add_variant;

!   return alg->cost < mult_cost;
  }

  /* A subroutine of expand_mult, used for constant multiplications.
--- 2562,2618 ----
  		     int mult_cost)
  {
    struct algorithm alg2;
+   struct mult_cost limit;
+   int op_cost;

    *variant = basic_variant;
!   limit.cost = mult_cost;
!   limit.latency = mult_cost;
!   synth_mult (alg, val, &limit, mode);

    /* This works only if the inverted value actually fits in an
       `unsigned int' */
    if (HOST_BITS_PER_INT >= GET_MODE_BITSIZE (mode))
      {
!       op_cost = neg_cost[mode];
!       if (MULT_COST_LESS (&alg->cost, mult_cost))
! 	{
! 	  limit.cost = alg->cost.cost - op_cost;
! 	  limit.latency = alg->cost.latency - op_cost;
! 	}
!       else
! 	{
! 	  limit.cost = mult_cost - op_cost;
! 	  limit.latency = mult_cost - op_cost;
! 	}
!
!       synth_mult (&alg2, -val, &limit, mode);
!       alg2.cost.cost += op_cost;
!       alg2.cost.latency += op_cost;
!       if (CHEAPER_MULT_COST (&alg2.cost, &alg->cost))
  	*alg = alg2, *variant = negate_variant;
      }

    /* This proves very useful for division-by-constant.  */
!   op_cost = add_cost[mode];
!   if (MULT_COST_LESS (&alg->cost, mult_cost))
!     {
!       limit.cost = alg->cost.cost - op_cost;
!       limit.latency = alg->cost.latency - op_cost;
!     }
!   else
!     {
!       limit.cost = mult_cost - op_cost;
!       limit.latency = mult_cost - op_cost;
!     }
!
!   synth_mult (&alg2, val - 1, &limit, mode);
!   alg2.cost.cost += op_cost;
!   alg2.cost.latency += op_cost;
!   if (CHEAPER_MULT_COST (&alg2.cost, &alg->cost))
      *alg = alg2, *variant = add_variant;

!   return MULT_COST_LESS (&alg->cost, mult_cost);
  }

  /* A subroutine of expand_mult, used for constant multiplications.
*************** expand_mult_highpart (enum machine_mode
*** 3074,3081 ****
      {
        /* See whether the specialized multiplication optabs are
  	 cheaper than the shift/add version.  */
!       tem = expand_mult_highpart_optab (mode, op0, op1, target,
! 					unsignedp, alg.cost + extra_cost);
        if (tem)
  	return tem;

--- 3185,3192 ----
      {
        /* See whether the specialized multiplication optabs are
  	 cheaper than the shift/add version.  */
!       tem = expand_mult_highpart_optab (mode, op0, op1, target, unsignedp,
! 					alg.cost.cost + extra_cost);
        if (tem)
  	return tem;


Roger
--
Roger Sayle,                         E-mail: roger@eyesopen.com
OpenEye Scientific Software,         WWW: http://www.eyesopen.com/
Suite 1107, 3600 Cerrillos Road,     Tel: (+1) 505-473-7385
Santa Fe, New Mexico, 87507.         Fax: (+1) 505-473-0833


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]