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)