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)

Reply via email to