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]

Don't delete REG_UNUSED


The REG_UNUSED notes must be preserved even after reload.  It is
impossible in general to accurately recompute them because reload can
reorder insns in a way that makes it impossible to correctly identify
register stores that should be ignored.  Consider the following insn:

(insn 222 220 369 (parallel [
            (set (mem/s:SI (plus:SI (reg:SI 77)
                        (reg:SI 70)) 2)
                (udiv:SI (reg/v:SI 41)
                    (reg:SI 102)))
            (set (reg:SI 82)
                (umod:SI (reg/v:SI 41)
                    (reg:SI 102)))
        ]) 213 {udivmodsi4} (insn_list 209 (nil))
    (expr_list:REG_UNUSED (reg:SI 82)
        (expr_list:REG_DEAD (reg:SI 102)
            (expr_list:REG_DEAD (reg:SI 70)
                (nil)))))

Here pseudo 82 is marked with REG_UNUSED, thus it is treated as if never
being set.  After the pseudos have been allocated to hard registers the
insn looks like this:

(insn 222 220 369 (parallel [
            (set (mem/s:SI (plus:SI (reg:SI 8 %a0)
                        (reg:SI 0 %d0)) 2)
                (udiv:SI (reg/v:SI 1 %d1)
                    (reg:SI 3 %d3)))
            (set (reg:SI 0 %d0)
                (umod:SI (reg/v:SI 1 %d1)
                    (reg:SI 3 %d3)))
        ]) 213 {udivmodsi4} (insn_list 209 (nil))
    (expr_list:REG_UNUSED (reg:SI 0 %d0)
        (expr_list:REG_DEAD (reg:SI 3 %d3)
            (expr_list:REG_DEAD (reg:SI 0 %d0)
                (nil)))))

Note that both pseudos 70 and 82 have been allocated to the same register,
which is ok, since the destination of the second set is not marked as
earlyclobber in the constraints for udivmodsi4.  But the destination of
the first set must be reloaded, which effectively extends the lifetime of
pseudo 79 in %d0 until after the insn.  Again, this is ok, since the store
to pseudo 82 in %d0 can be ignored.  But that also means that register %d0
looks like being set by the insn if the REG_UNUSED note is deleted, when
in fact it isn't actually.

Here is the source that triggers the bug, to be compiled with -O2 for
m68k-linux.

----------------------------------------------------------------------
int
div_and_round_double (uns,
		      lnum_orig, hnum_orig, lden_orig, hden_orig,
		      lquo, hquo, lrem, hrem)
     int uns;
     long lnum_orig, hnum_orig;
     long lden_orig, hden_orig;
     long *lquo, *hquo, *lrem, *hrem;
{
  int quo_neg = 0;
  long num[4 + 1];
  long den[4], quo[4];
  register int i, j;
  unsigned long work;
  register unsigned long carry = 0;
  long lnum = lnum_orig;
  long hnum = hnum_orig;
  long lden = lden_orig;
  long hden = hden_orig;
  int overflow = 0;

  if ((hden == 0) && (lden == 0))
    overflow = 1, lden = 1;

  if (!uns) 
    {
      if (hnum < 0)
	{
	  quo_neg = ~ quo_neg;
	  if (neg_double (lnum, hnum, &lnum, &hnum) && (lden & hden) == -1)
	    overflow = 1;
	}
      if (hden < 0) 
	{
	  quo_neg = ~ quo_neg;
	  neg_double (lden, hden, &lden, &hden);
	}
    }

  encode (num, lnum, hnum); 
  encode (den, lden, hden);

  if (hden == 0 && lden < (long) (1 << 16))
    {
      for (i = 4 - 1; i >= 0; i--)
	{
	  work = num[i] + carry * (1 << 16);
	  quo[i] = work / (unsigned long) lden;
	  carry = work % (unsigned long) lden;
	}
    }
  else
    full_div_and_round (num, den, quo);

  decode (quo, lquo, hquo);

  if (quo_neg)
    neg_double (*lquo, *hquo, lquo, hquo);

  mul_double (*lquo, *hquo, lden_orig, hden_orig, lrem, hrem);
  neg_double (*lrem, *hrem, lrem, hrem);
  add_double (lnum_orig, hnum_orig, *lrem, *hrem, lrem, hrem);
  return overflow;
}
----------------------------------------------------------------------


1998-11-01  Andreas Schwab  <schwab@issan.cs.uni-dortmund.de>

	* reload1.c (reload): Don't remove REG_UNUSED notes here, it is
	impossible in general to recompute them accurately afterwards.

--- egcs-2.92/gcc/reload1.c.~2~	Sat Oct 31 18:43:45 1998
+++ egcs-2.92/gcc/reload1.c	Sun Nov  1 14:21:46 1998
@@ -1217,8 +1217,8 @@
     }
 
   /* Make a pass over all the insns and delete all USEs which we inserted
-     only to tag a REG_EQUAL note on them.  Also remove all REG_DEAD and
-     REG_UNUSED notes.  */
+     only to tag a REG_EQUAL note on them.  Also remove all REG_DEAD
+     notes.  */
 
   for (insn = first; insn; insn = NEXT_INSN (insn))
     if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
@@ -1237,8 +1237,7 @@
 	pnote = &REG_NOTES (insn);
 	while (*pnote != 0)
 	  {
-	    if (REG_NOTE_KIND (*pnote) == REG_DEAD
-		|| REG_NOTE_KIND (*pnote) == REG_UNUSED)
+	    if (REG_NOTE_KIND (*pnote) == REG_DEAD)
 	      *pnote = XEXP (*pnote, 1);
 	    else
 	      pnote = &XEXP (*pnote, 1);


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