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)