fix c/5290: Miscompilation of GDB on i386

Richard Henderson rth@redhat.com
Thu Jan 10 19:24:00 GMT 2002


The ugliness here stems from emitting one output reload insn, deleting it,
emitting a second reload insn, then deleting the first reload insn a second
time.  The duplicate deletion scrogs the insn chain and we lose stuff.

Bootstrapped and checked on alphaev6 and i686 linux.


r~


        * cfgrtl.c (delete_insn): Assert insn hasn't been deleted yet.
        * reload1.c (delete_output_reload): Zap spill_reg_store.  Take
        care not to delete instructions twice.

Index: cfgrtl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cfgrtl.c,v
retrieving revision 1.25
diff -c -p -d -r1.25 cfgrtl.c
*** cfgrtl.c	2002/01/10 20:37:42	1.25
--- cfgrtl.c	2002/01/11 02:43:15
*************** delete_insn (insn)
*** 135,140 ****
--- 135,143 ----
  
    if (really_delete)
      {
+       /* If this insn has already been deleted, something is very wrong.  */
+       if (INSN_DELETED_P (insn))
+ 	abort ();
        remove_insn (insn);
        INSN_DELETED_P (insn) = 1;
      }
Index: reload1.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/reload1.c,v
retrieving revision 1.319
diff -c -p -d -r1.319 reload1.c
*** reload1.c	2002/01/10 00:56:54	1.319
--- reload1.c	2002/01/11 02:43:15
*************** gen_reload (out, in, opnum, type)
*** 7537,7545 ****
    return last ? NEXT_INSN (last) : get_insns ();
  }
  
! /* Delete a previously made output-reload
!    whose result we now believe is not needed.
!    First we double-check.
  
     INSN is the insn now being processed.
     LAST_RELOAD_REG is the hard register number for which we want to delete
--- 7537,7544 ----
    return last ? NEXT_INSN (last) : get_insns ();
  }
  
! /* Delete a previously made output-reload whose result we now believe
!    is not needed.  First we double-check.
  
     INSN is the insn now being processed.
     LAST_RELOAD_REG is the hard register number for which we want to delete
*************** delete_output_reload (insn, j, last_relo
*** 7633,7647 ****
  	}
      }
  
    /* The caller has already checked that REG dies or is set in INSN.
!      It has also checked that we are optimizing, and thus some inaccurancies
!      in the debugging information are acceptable.
!      So we could just delete output_reload_insn.
!      But in some cases we can improve the debugging information without
!      sacrificing optimization - maybe even improving the code:
!      See if the pseudo reg has been completely replaced
!      with reload regs.  If so, delete the store insn
!      and forget we had a stack slot for the pseudo.  */
    if (rld[j].out != rld[j].in
        && REG_N_DEATHS (REGNO (reg)) == 1
        && REG_N_SETS (REGNO (reg)) == 1
--- 7632,7652 ----
  	}
      }
  
+   /* We will be deleting the insn.  Remove the spill reg information.  */
+   for (k = HARD_REGNO_NREGS (last_reload_reg, GET_MODE (reg)); k-- > 0; )
+     {
+       spill_reg_store[last_reload_reg + k] = 0;
+       spill_reg_stored_to[last_reload_reg + k] = 0;
+     }
+ 
    /* The caller has already checked that REG dies or is set in INSN.
!      It has also checked that we are optimizing, and thus some
!      inaccurancies in the debugging information are acceptable.
!      So we could just delete output_reload_insn.  But in some cases
!      we can improve the debugging information without sacrificing
!      optimization - maybe even improving the code: See if the pseudo
!      reg has been completely replaced with reload regs.  If so, delete
!      the store insn and forget we had a stack slot for the pseudo.  */
    if (rld[j].out != rld[j].in
        && REG_N_DEATHS (REGNO (reg)) == 1
        && REG_N_SETS (REGNO (reg)) == 1
*************** delete_output_reload (insn, j, last_relo
*** 7650,7660 ****
      {
        rtx i2;
  
!       /* We know that it was used only between here
! 	 and the beginning of the current basic block.
! 	 (We also know that the last use before INSN was
! 	 the output reload we are thinking of deleting, but never mind that.)
! 	 Search that range; see if any ref remains.  */
        for (i2 = PREV_INSN (insn); i2; i2 = PREV_INSN (i2))
  	{
  	  rtx set = single_set (i2);
--- 7655,7664 ----
      {
        rtx i2;
  
!       /* We know that it was used only between here and the beginning of
! 	 the current basic block.  (We also know that the last use before
! 	 INSN was the output reload we are thinking of deleting, but never
! 	 mind that.)  Search that range; see if any ref remains.  */
        for (i2 = PREV_INSN (insn); i2; i2 = PREV_INSN (i2))
  	{
  	  rtx set = single_set (i2);
*************** delete_output_reload (insn, j, last_relo
*** 7677,7683 ****
  	    }
  	}
  
!       /* Delete the now-dead stores into this pseudo.  */
        for (i2 = PREV_INSN (insn); i2; i2 = PREV_INSN (i2))
  	{
  	  rtx set = single_set (i2);
--- 7681,7688 ----
  	    }
  	}
  
!       /* Delete the now-dead stores into this pseudo.  Note that this
! 	 loop also takes care of deleting output_reload_insn.  */
        for (i2 = PREV_INSN (insn); i2; i2 = PREV_INSN (i2))
  	{
  	  rtx set = single_set (i2);
*************** delete_output_reload (insn, j, last_relo
*** 7685,7692 ****
  	  if (set != 0 && SET_DEST (set) == reg)
  	    {
  	      delete_address_reloads (i2, insn);
- 	      /* This might be a basic block head,
- 		 thus don't use delete_insn.  */
  	      delete_insn (i2);
  	    }
  	  if (GET_CODE (i2) == CODE_LABEL
--- 7690,7695 ----
*************** delete_output_reload (insn, j, last_relo
*** 7694,7707 ****
  	    break;
  	}
  
!       /* For the debugging info,
! 	 say the pseudo lives in this reload reg.  */
        reg_renumber[REGNO (reg)] = REGNO (rld[j].reg_rtx);
        alter_reg (REGNO (reg), -1);
      }
!   delete_address_reloads (output_reload_insn, insn);
!   delete_insn (output_reload_insn);
! 
  }
  
  /* We are going to delete DEAD_INSN.  Recursively delete loads of
--- 7697,7711 ----
  	    break;
  	}
  
!       /* For the debugging info, say the pseudo lives in this reload reg.  */
        reg_renumber[REGNO (reg)] = REGNO (rld[j].reg_rtx);
        alter_reg (REGNO (reg), -1);
      }
!   else
!     {
!       delete_address_reloads (output_reload_insn, insn);
!       delete_insn (output_reload_insn);
!     }
  }
  
  /* We are going to delete DEAD_INSN.  Recursively delete loads of



More information about the Gcc-patches mailing list