[patch] for PR 20249

Zdenek Dvorak rakdver@atrey.karlin.mff.cuni.cz
Mon Mar 7 10:28:00 GMT 2005


Hello,

my patch to safe_insert_insn_on_edge exposed a latent bug in cse.  The
rtl looks as follows (saving and restoring of reg:si 5 to reg:si 124 is
due to the patch):

(set (reg:si 124) (reg:si 5))
...
(set (reg:si 5) (reg:si 124))
...
(set (reg:di 119) (reg:di 5))   (*)
...
(set (reg:di 3) (reg:di 119))

CSE copy propagates all over, creating invalid insn

(set (reg:di 3) (reg:si 5))

The reason is that at the insn (*), reg 119 is recorded to be equivalent
to register 5.  However the record for reg 5 is in SImode, which causes
the problem.

This patch fixes the problem by preventing the recording of equivalence
with a register in a different mode.

Bootstrapped & regtested on i686 and ia64 with -fprofile-arcs.  I have
also tried bootstrapping on ppc, this is successful except for a
bootstrap misscompare (which is a progress, since without the patch
the bootstrap fails with an ICE similar to the one of the PR).  I need
to check whether the misscompare problem is related to the PR or not.

Zdenek

	PR middle-end/20249
	* cse.c (insert_regs): Do not record equivalence of registers in
	different modes.

Index: cse.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cse.c,v
retrieving revision 1.348
diff -c -3 -p -r1.348 cse.c
*** cse.c	6 Mar 2005 20:05:58 -0000	1.348
--- cse.c	6 Mar 2005 23:20:50 -0000
*************** insert_regs (rtx x, struct table_elt *cl
*** 1234,1240 ****
  	      if (REG_P (classp->exp)
  		  && GET_MODE (classp->exp) == GET_MODE (x))
  		{
! 		  make_regs_eqv (regno, REGNO (classp->exp));
  		  return 1;
  		}
  
--- 1234,1257 ----
  	      if (REG_P (classp->exp)
  		  && GET_MODE (classp->exp) == GET_MODE (x))
  		{
! 		  unsigned c_regno = REGNO (classp->exp);
! 
! 		  gcc_assert (REGNO_QTY_VALID_P (c_regno));
! 
! 		  /* Suppose that 5 is hard reg and 100 and 101 are
! 		     pseudos.  Consider
! 
! 		     (set (reg:si 100) (reg:si 5))
! 		     (set (reg:si 5) (reg:si 100))
! 		     (set (reg:di 101) (reg:di 5))
! 
! 		     We would now set REG_QTY (101) = REG_QTY (5), but the
! 		     entry for 5 is in SImode.  When we use this later in
! 		     copy propagation, we get the register in wrong mode.  */
! 		  if (qty_table[REG_QTY (c_regno)].mode != GET_MODE (x))
! 		    continue;
! 
! 		  make_regs_eqv (regno, c_regno);
  		  return 1;
  		}
  



More information about the Gcc-patches mailing list