This is the mail archive of the gcc@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]

array bounds violation in caller-save.c : duplicate hard regs check added


If I apply this patch, which checks for duplicate hard registers within
-fira-share-save-slots, the following *-elf targets fail due to the assert:

	bfin cris m32c rl78 rx sh sh64 v850

The following succeed:

	frv h8300 i386 ia64 m32r mep mipsisa32 mipsisa64 mn10300 powerpc tx39

Without this patch, the failing targets eventually overflow the
call_saved_regs[] array (size FIRST_PSEUDO_REGISTER) and corrupt other
memory and data structures.  I originally had an assert for that
bounds check too, but this one caught all the cases sooner.

Can someone who knows more about IRA and this optimization explain if
and/or why duplicate hard regs are allowed at that point, and what if
any changes should be made to avoid the array overflow?

Thanks,
DJ


Index: caller-save.c
===================================================================
--- caller-save.c	(revision 187842)
+++ caller-save.c	(working copy)
@@ -504,12 +504,13 @@ setup_save_areas (void)
       struct saved_hard_reg *saved_reg2, *saved_reg3;
       int call_saved_regs_num;
       struct saved_hard_reg *call_saved_regs[FIRST_PSEUDO_REGISTER];
       int best_slot_num;
       int prev_save_slots_num;
       rtx prev_save_slots[FIRST_PSEUDO_REGISTER];
+      rtx dj_saw[FIRST_PSEUDO_REGISTER];
 
       /* Find saved hard register conflicts.  */
       saved_reg_conflicts = (char *) xmalloc (saved_regs_num * saved_regs_num);
       memset (saved_reg_conflicts, 0, saved_regs_num * saved_regs_num);
       for (chain = reload_insn_chain; chain != 0; chain = next)
 	{
@@ -518,12 +519,14 @@ setup_save_areas (void)
 	  insn = chain->insn;
 	  next = chain->next;
 	  if (!CALL_P (insn)
 	      || find_reg_note (insn, REG_NORETURN, NULL))
 	    continue;
 
+	  memset(dj_saw, 0, sizeof(dj_saw));
+
 	  cheap = find_reg_note (insn, REG_RETURNED, NULL);
 	  if (cheap)
 	    cheap = XEXP (cheap, 0);
 
 	  REG_SET_TO_HARD_REG_SET (hard_regs_to_save,
 				   &chain->live_throughout);
@@ -560,13 +563,21 @@ setup_save_areas (void)
 	      if (r < 0 || regno_reg_rtx[regno] == cheap)
 		continue;
 
 	      bound = r + hard_regno_nregs[r][PSEUDO_REGNO_MODE (regno)];
 	      for (; r < bound; r++)
 		if (TEST_HARD_REG_BIT (used_regs, r))
-		  call_saved_regs[call_saved_regs_num++] = hard_reg_map[r];
+		  {
+		    call_saved_regs[call_saved_regs_num++] = hard_reg_map[r];
+		    if (dj_saw[r])
+		      {
+			fprintf(stderr, "\033[31mDJERR: DUPLICATE HARD REG %d\033[0m\n", r);
+			gcc_assert (!dj_saw [r]);
+		      }
+		    dj_saw [r] = 1;
+		  }
 	    }
 	  for (i = 0; i < call_saved_regs_num; i++)
 	    {
 	      saved_reg = call_saved_regs[i];
 	      for (j = 0; j < call_saved_regs_num; j++)
 		if (i != j)


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