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]

[PATCH] Fix sparc64 bootstrap failure in synth_mult



The following patch should address the current bootstrap failure
on sparc64 caused by my recent patch to index shift_cost by the
multiplication's machine mode.

In my opinion, the underlying problem is a signedness issue with
synth_mult's multiplier co-efficient, that has been harmlessly(?)
latent for a long time.  This function's "t" argument is an unsigned
HOST_WIDE_INT, whose bits represent the value the multiplicand.
On many platforms, multiplications are typically performed in
word_mode, which matches the width of HOST_WIDE_INT, so there's
no distintion between passing signed vs. unsigned multipliers
to synth_mult.

However, on sparc64 and other platforms where the host's HOST_WIDE_INT
is wider than the mode of an operation, the sign extension of negative
multipliers produces extra one-bits with confuse the synth_mult algorithm.
For years on these platforms, synth_mult has been relying on the
backend's rtx_cost to return "reasonable" values for invalid RTL such as
(ASHIFT:SI (REG:SI x) (const_int 40)), [where the shift is by a value
wider than the presumed 32-bit SImode].


With the recent transition to look-up tables, that sensibly avoid
determining shift_cost[SImode][40], this latent problem has been
exposed, and trigger's a miscompilation on sparc64.


The fix below is two fold.  The main "obvious" fix is at the start of
synth_mult function to mask the multiplier to width of the machine
mode, using GET_MODE_MASK.  Hence for QImode multiplications by -1,
we consider the multiplier to have 8 bits set, not 32 or 64.  This
also improves termination conditions on the algorithm.  The second part
of the fix, just to be doubly safe, is to tweak the sanity checks in
synth_mult such that we never access shift_cost[mode][m] for invalid
m, i.e. m must be < GET_MODE_BITSIZE (mode).


The following patch has been tested on i686-pc-linux-gnu with a full
"make bootstrap", all default languages, and regression tested with a
top-level "make -k check" with no new failures.  From Eric Botcazou's
analysis and description of the sparc64 bootstrap failure, either of
these changes in the patch should (in theory) resolve the issue.


Ok for mainline?



2004-06-13  Roger Sayle  <roger@eyesopen.com>

	* expmed.c (synth_mult): Mask bits of the multiplier to the
	machine mode of the multiplication.  Don't consider shifts
	by more than (or equal two) the width of the operation's mode.


Index: expmed.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/expmed.c,v
retrieving revision 1.165
diff -c -3 -p -r1.165 expmed.c
*** expmed.c	13 Jun 2004 02:46:08 -0000	1.165
--- expmed.c	13 Jun 2004 21:04:36 -0000
*************** synth_mult (struct algorithm *alg_out, u
*** 2191,2196 ****
--- 2191,2197 ----
    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.  */
*************** synth_mult (struct algorithm *alg_out, u
*** 2199,2204 ****
--- 2200,2208 ----
    if (cost_limit <= 0)
      return;

+   /* Restrict the bits of "t" to the multiplication's mode.  */
+   t &= GET_MODE_MASK (mode);
+
    /* t == 1 can be done in zero cost.  */
    if (t == 1)
      {
*************** synth_mult (struct algorithm *alg_out, u
*** 2234,2240 ****
    if ((t & 1) == 0)
      {
        m = floor_log2 (t & -t);	/* m = number of low zero bits */
!       if (m < BITS_PER_WORD)
  	{
  	  q = t >> m;
  	  cost = shift_cost[mode][m];
--- 2238,2244 ----
    if ((t & 1) == 0)
      {
        m = floor_log2 (t & -t);	/* m = number of low zero bits */
!       if (m < maxm)
  	{
  	  q = t >> m;
  	  cost = shift_cost[mode][m];
*************** synth_mult (struct algorithm *alg_out, u
*** 2319,2325 ****
        unsigned HOST_WIDE_INT d;

        d = ((unsigned HOST_WIDE_INT) 1 << m) + 1;
!       if (t % d == 0 && t > d && m < BITS_PER_WORD)
  	{
  	  cost = add_cost[mode] + shift_cost[mode][m];
  	  if (shiftadd_cost[mode][m] < cost)
--- 2323,2329 ----
        unsigned HOST_WIDE_INT d;

        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)
*************** synth_mult (struct algorithm *alg_out, u
*** 2340,2346 ****
  	}

        d = ((unsigned HOST_WIDE_INT) 1 << m) - 1;
!       if (t % d == 0 && t > d && m < BITS_PER_WORD)
  	{
  	  cost = add_cost[mode] + shift_cost[mode][m];
  	  if (shiftsub_cost[mode][m] < cost)
--- 2344,2350 ----
  	}

        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)
*************** synth_mult (struct algorithm *alg_out, u
*** 2367,2373 ****
        q = t - 1;
        q = q & -q;
        m = exact_log2 (q);
!       if (m >= 0 && m < BITS_PER_WORD)
  	{
  	  cost = shiftadd_cost[mode][m];
  	  synth_mult (alg_in, (t - 1) >> m, cost_limit - cost, mode);
--- 2371,2377 ----
        q = t - 1;
        q = q & -q;
        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);
*************** synth_mult (struct algorithm *alg_out, u
*** 2386,2392 ****
        q = t + 1;
        q = q & -q;
        m = exact_log2 (q);
!       if (m >= 0 && m < BITS_PER_WORD)
  	{
  	  cost = shiftsub_cost[mode][m];
  	  synth_mult (alg_in, (t + 1) >> m, cost_limit - cost, mode);
--- 2390,2396 ----
        q = t + 1;
        q = q & -q;
        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);


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]