frame_pointer_needed = true;
CLEAR_HARD_REG_SET (set);
add_to_hard_reg_set (&set, Pmode, HARD_FRAME_POINTER_REGNUM);
+ /* If !lra_reg_spill_p, we likely have incomplete range information
+ for pseudos assigned to the frame pointer that will have to be
+ spilled, and so we may end up incorrectly sharing them unless we
+ get live range information for them. */
+ if (lra_complete_live_ranges ())
+ /* If lives ranges changed, update the aggregate live ranges in
+ slots as well before spilling any further pseudos. */
+ lra_recompute_slots_live_ranges ();
n = spill_pseudos (set, spilled_pseudos);
if (!ep)
for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++)
extern int lra_hard_reg_usage[FIRST_PSEUDO_REGISTER];
extern int lra_live_range_iter;
+extern void lra_reset_live_range_list (lra_live_range_t &);
extern void lra_create_live_ranges (bool, bool);
+extern bool lra_complete_live_ranges (void);
extern lra_live_range_t lra_copy_live_range_list (lra_live_range_t);
extern lra_live_range_t lra_merge_live_ranges (lra_live_range_t,
lra_live_range_t);
extern bool lra_need_for_spills_p (void);
extern void lra_spill (void);
extern void lra_final_code_change (void);
+extern void lra_recompute_slots_live_ranges (void);
/* lra-remat.cc: */
}
}
+/* Reset and release live range list LR. */
+void
+lra_reset_live_range_list (lra_live_range_t &lr)
+{
+ lra_live_range_t first = lr;
+ lr = NULL;
+ free_live_range_list (first);
+}
+
/* Create and return pseudo live range with given attributes. */
static lra_live_range_t
create_live_range (int regno, int start, int finish, lra_live_range_t next)
lra_assert (! res);
}
+/* Run lra_create_live_ranges if !complete_info_p. Return FALSE iff
+ live ranges are known to have remained unchanged. */
+
+bool
+lra_complete_live_ranges (void)
+{
+ if (complete_info_p)
+ return false;
+
+ lra_create_live_ranges (true, true);
+ return true;
+}
+
/* Finish all live ranges. */
void
lra_clear_live_ranges (void)
for (res = i = 0; i < n; i++)
{
regno = pseudo_regnos[i];
+ gcc_assert (lra_reg_info[regno].live_ranges);
rclass = lra_get_allocno_class (regno);
if (bitmap_bit_p (setjump_crosses, regno)
|| (spill_class
first = pseudo_slots[regno].first = &pseudo_slots[slots[slot_num].regno];
pseudo_slots[regno].next = first->next;
first->next = &pseudo_slots[regno];
+ lra_assert (slots[slot_num].live_ranges);
}
pseudo_slots[regno].mem = NULL_RTX;
pseudo_slots[regno].slot_num = slot_num;
+
+ /* Pseudos with empty ranges shouldn't need to be spilled; if we get
+ an empty range added to a slot, something fishy is going on, such
+ as missing live range information, and without that information
+ we may generate wrong code. We can probably relax this to an
+ lra_assert at some point. Likewise the analogous one in
+ assign_spill_hard_regs. */
+ gcc_assert (lra_reg_info[regno].live_ranges);
+
slots[slot_num].live_ranges
= lra_merge_live_ranges (slots[slot_num].live_ranges,
lra_copy_live_range_list
(lra_reg_info[regno].live_ranges));
}
+/* Recompute the combined live ranges of pseudos assigned to stack
+ slots. This brings the live ranges of slots back in sync with
+ those of pseudos, after recomputing live ranges for pseudos. */
+void
+lra_recompute_slots_live_ranges (void)
+{
+ for (int i = 0; i < slots_num; i++)
+ {
+ if (slots[i].regno < 0)
+ continue;
+ lra_reset_live_range_list (slots[i].live_ranges);
+ for (struct pseudo_slot *next = pseudo_slots[slots[i].regno].first;
+ next; next = next->next)
+ {
+ int regno = next - pseudo_slots;
+ lra_assert (!(lra_intersected_live_ranges_p
+ (lra_reg_info[regno].live_ranges,
+ slots[i].live_ranges)));
+ slots[i].live_ranges
+ = lra_merge_live_ranges (slots[i].live_ranges,
+ lra_copy_live_range_list
+ (lra_reg_info[regno].live_ranges));
+ }
+ }
+}
+
/* Assign stack slot numbers to pseudos in array PSEUDO_REGNOS of
length N. Sort pseudos in PSEUDO_REGNOS for subsequent assigning
memory stack slots. */