process. It is done in each region on top-down traverse of the
region tree (file ira-color.c). There are following subpasses:
- * Optional aggressive coalescing of allocnos in the region.
-
* Putting allocnos onto the coloring stack. IRA uses Briggs
optimistic coloring which is a major improvement over
Chaitin's coloring. Therefore IRA does not spill allocnos at
CLEAR_HARD_REG_SET (processed_hard_reg_set);
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
{
- ira_non_ordered_class_hard_regs[cl][0] = -1;
- ira_class_hard_reg_index[cl][0] = -1;
+ ira_non_ordered_class_hard_regs[cl][i] = -1;
+ ira_class_hard_reg_index[cl][i] = -1;
}
for (n = 0, i = 0; i < FIRST_PSEUDO_REGISTER; i++)
{
test_reg1 = gen_rtx_REG (VOIDmode, 0);
test_reg2 = gen_rtx_REG (VOIDmode, 0);
move_pat = gen_rtx_SET (VOIDmode, test_reg1, test_reg2);
- move_insn = gen_rtx_INSN (VOIDmode, 0, 0, 0, 0, 0, move_pat, -1, 0);
+ move_insn = gen_rtx_INSN (VOIDmode, 0, 0, 0, 0, move_pat, 0, -1, 0);
for (i = 0; i < NUM_MACHINE_MODES; i++)
{
SET_HARD_REG_SET (ira_prohibited_mode_move_regs[i]);
{
if (! HARD_REGNO_MODE_OK (j, (enum machine_mode) i))
continue;
- SET_REGNO (test_reg1, j);
+ SET_REGNO_RAW (test_reg1, j);
PUT_MODE (test_reg1, (enum machine_mode) i);
- SET_REGNO (test_reg2, j);
+ SET_REGNO_RAW (test_reg2, j);
PUT_MODE (test_reg2, (enum machine_mode) i);
INSN_CODE (move_insn) = -1;
recog_memoized (move_insn);
static bool
ira_bad_reload_regno_1 (int regno, rtx x)
{
- int x_regno;
+ int x_regno, n, i;
ira_allocno_t a;
enum reg_class pref;
/* If the pseudo conflicts with REGNO, then we consider REGNO a
poor choice for a reload regno. */
a = ira_regno_allocno_map[x_regno];
- if (TEST_HARD_REG_BIT (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a), regno))
- return true;
-
+ n = ALLOCNO_NUM_OBJECTS (a);
+ for (i = 0; i < n; i++)
+ {
+ ira_object_t obj = ALLOCNO_OBJECT (a, i);
+ if (TEST_HARD_REG_BIT (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj), regno))
+ return true;
+ }
return false;
}
else
df_set_regs_ever_live (eliminables[i].from, true);
}
-#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
+#if !HARD_FRAME_POINTER_IS_FRAME_POINTER
if (!TEST_HARD_REG_BIT (crtl->asm_clobbers, HARD_FRAME_POINTER_REGNUM))
{
SET_HARD_REG_BIT (eliminable_regset, HARD_FRAME_POINTER_REGNUM);
static void
check_allocation (void)
{
- ira_allocno_t a, conflict_a;
- int hard_regno, conflict_hard_regno, nregs, conflict_nregs;
- ira_allocno_conflict_iterator aci;
+ ira_allocno_t a;
+ int hard_regno, nregs, conflict_nregs;
ira_allocno_iterator ai;
FOR_EACH_ALLOCNO (a, ai)
{
+ int n = ALLOCNO_NUM_OBJECTS (a);
+ int i;
+
if (ALLOCNO_CAP_MEMBER (a) != NULL
|| (hard_regno = ALLOCNO_HARD_REGNO (a)) < 0)
continue;
nregs = hard_regno_nregs[hard_regno][ALLOCNO_MODE (a)];
- FOR_EACH_ALLOCNO_CONFLICT (a, conflict_a, aci)
- if ((conflict_hard_regno = ALLOCNO_HARD_REGNO (conflict_a)) >= 0)
- {
- conflict_nregs
- = (hard_regno_nregs
- [conflict_hard_regno][ALLOCNO_MODE (conflict_a)]);
- if ((conflict_hard_regno <= hard_regno
- && hard_regno < conflict_hard_regno + conflict_nregs)
- || (hard_regno <= conflict_hard_regno
- && conflict_hard_regno < hard_regno + nregs))
- {
- fprintf (stderr, "bad allocation for %d and %d\n",
- ALLOCNO_REGNO (a), ALLOCNO_REGNO (conflict_a));
- gcc_unreachable ();
- }
- }
+ if (nregs == 1)
+ /* We allocated a single hard register. */
+ n = 1;
+ else if (n > 1)
+ /* We allocated multiple hard registers, and we will test
+ conflicts in a granularity of single hard regs. */
+ nregs = 1;
+
+ for (i = 0; i < n; i++)
+ {
+ ira_object_t obj = ALLOCNO_OBJECT (a, i);
+ ira_object_t conflict_obj;
+ ira_object_conflict_iterator oci;
+ int this_regno = hard_regno;
+ if (n > 1)
+ {
+ if (WORDS_BIG_ENDIAN)
+ this_regno += n - i - 1;
+ else
+ this_regno += i;
+ }
+ FOR_EACH_OBJECT_CONFLICT (obj, conflict_obj, oci)
+ {
+ ira_allocno_t conflict_a = OBJECT_ALLOCNO (conflict_obj);
+ int conflict_hard_regno = ALLOCNO_HARD_REGNO (conflict_a);
+ if (conflict_hard_regno < 0)
+ continue;
+
+ conflict_nregs
+ = (hard_regno_nregs
+ [conflict_hard_regno][ALLOCNO_MODE (conflict_a)]);
+
+ if (ALLOCNO_NUM_OBJECTS (conflict_a) > 1
+ && conflict_nregs == ALLOCNO_NUM_OBJECTS (conflict_a))
+ {
+ if (WORDS_BIG_ENDIAN)
+ conflict_hard_regno += (ALLOCNO_NUM_OBJECTS (conflict_a)
+ - OBJECT_SUBWORD (conflict_obj) - 1);
+ else
+ conflict_hard_regno += OBJECT_SUBWORD (conflict_obj);
+ conflict_nregs = 1;
+ }
+
+ if ((conflict_hard_regno <= this_regno
+ && this_regno < conflict_hard_regno + conflict_nregs)
+ || (this_regno <= conflict_hard_regno
+ && conflict_hard_regno < this_regno + nregs))
+ {
+ fprintf (stderr, "bad allocation for %d and %d\n",
+ ALLOCNO_REGNO (a), ALLOCNO_REGNO (conflict_a));
+ gcc_unreachable ();
+ }
+ }
+ }
}
}
#endif
if (find_reg_note (insn, REG_DEAD, reg))
return 1;
- if (CALL_P (insn) && ! MEM_READONLY_P (memref)
- && ! RTL_CONST_OR_PURE_CALL_P (insn))
+ /* This used to ignore readonly memory and const/pure calls. The problem
+ is the equivalent form may reference a pseudo which gets assigned a
+ call clobbered hard reg. When we later replace REG with its
+ equivalent form, the value in the call-clobbered reg has been
+ changed and all hell breaks loose. */
+ if (CALL_P (insn))
return 0;
note_stores (PATTERN (insn), validate_equiv_mem_from_store, NULL);
if (!REG_P (dest)
|| (regno = REGNO (dest)) < FIRST_PSEUDO_REGISTER
|| reg_equiv[regno].init_insns == const0_rtx
- || (CLASS_LIKELY_SPILLED_P (reg_preferred_class (regno))
+ || (targetm.class_likely_spilled_p (reg_preferred_class (regno))
&& MEM_P (src) && ! reg_equiv[regno].is_arg_equivalence))
{
/* This might be setting a SUBREG of a pseudo, a pseudo that is
rtx equiv_insn;
if (! reg_equiv[regno].replace
- || reg_equiv[regno].loop_depth < loop_depth)
+ || reg_equiv[regno].loop_depth < loop_depth
+ /* There is no sense to move insns if we did
+ register pressure-sensitive scheduling was
+ done because it will not improve allocation
+ but worsen insn schedule with a big
+ probability. */
+ || (flag_sched_pressure && flag_schedule_insns))
continue;
/* reg_equiv[REGNO].replace gets set only when
{
/* Consider spilled pseudos too for IRA because they still have a
chance to get hard-registers in the reload when IRA is used. */
- return (reg_renumber[regno] >= 0
- || (ira_conflicts_p && flag_ira_share_spill_slots));
+ return (reg_renumber[regno] >= 0 || ira_conflicts_p);
}
/* Init LIVE_SUBREGS[ALLOCNUM] and LIVE_SUBREGS_USED[ALLOCNUM] using
ira_assert (ira_conflicts_p || !loops_p);
saved_flag_ira_share_spill_slots = flag_ira_share_spill_slots;
- if (too_high_register_pressure_p ())
+ if (too_high_register_pressure_p () || cfun->calls_setjmp)
/* It is just wasting compiler's time to pack spilled pseudos into
- stack slots in this case -- prohibit it. */
+ stack slots in this case -- prohibit it. We also do this if
+ there is setjmp call because a variable not modified between
+ setjmp and longjmp the compiler is required to preserve its
+ value and sharing slots does not guarantee it. */
flag_ira_share_spill_slots = FALSE;
ira_color ();
reload_completed = !reload (get_insns (), ira_conflicts_p);
- finish_subregs_of_mode ();
-
timevar_pop (TV_RELOAD);
timevar_push (TV_IRA);