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]

Re: scan_one_insn() doesn't keep REG_N_REFS accurate


On May  3, 2001, Alexandre Oliva <aoliva@redhat.com> wrote:

> scan_one_insn() will optimize two-address insns that require operand1
> to match operand0 by introducing a copy insn from operand1 to operand0
> before the two-address insn.  However, even though it increments
> REG_N_SETS, it doesn't increment REG_N_REFS (that should be REG_N_SETS
> + number of uses).

> This causes local-alloc to abort() if a pseudo was set once and used
> once, before the transformation.  update_equiv_regs() would note that
> REG_N_REFS was 2 and that the first set of the register was movable,
> so it would set the replace flag for the pseudo.  However, when it got
> to the second set, it would call no_equiv(), clearing init_insns and
> replacement, but not the replace flag.  Then, when it got to the use
> of the pseudo, it would abort() because init_insns was (const_int 0)
> when processing the REG_DEATH note, or crash because equiv_insns would
> be set to NULL.

Sorry about the horribly broken ChangeLog entry.  I had failed to save
the cleaned-up patch file :-(

Here's the patch I had meant to post:

Index: gcc/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* regclass.c (scan_one_insn): Update REG_N_REFS when optimizing
	handling of two-address insns.

Index: gcc/regclass.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/regclass.c,v
retrieving revision 1.118
diff -u -p -r1.118 regclass.c
--- gcc/regclass.c 2001/04/13 16:34:41 1.118
+++ gcc/regclass.c 2001/05/03 09:01:24
@@ -1058,11 +1058,16 @@ scan_one_insn (insn, pass)
 
       /* This makes one more setting of new insns's dest.  */
       REG_N_SETS (REGNO (recog_data.operand[0]))++;
+      REG_N_REFS (REGNO (recog_data.operand[0]))++;
 
       *recog_data.operand_loc[1] = recog_data.operand[0];
+      REG_N_REFS (REGNO (recog_data.operand[0]))++;
       for (i = recog_data.n_dups - 1; i >= 0; i--)
 	if (recog_data.dup_num[i] == 1)
-	  *recog_data.dup_loc[i] = recog_data.operand[0];
+	  {
+	    *recog_data.dup_loc[i] = recog_data.operand[0];
+	    REG_N_REFS (REGNO (recog_data.operand[0]))++;
+	  }
 
       return PREV_INSN (newinsn);
     }

-- 
Alexandre Oliva   Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer                  aoliva@{cygnus.com, redhat.com}
CS PhD student at IC-Unicamp        oliva@{lsd.ic.unicamp.br, gnu.org}
Free Software Evangelist    *Please* write to mailing lists, not to me

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