@@ -186,19 +186,28 @@ static bitmap_head used_pseudos_bitmap;
/* Set up USED_PSEUDOS_BITMAP, and update LR_BITMAP (a BB live info
bitmap). */
static void
-update_live_info (bitmap lr_bitmap)
+update_live_info (bitmap all, bitmap full, bitmap partial)
{
unsigned int j;
bitmap_iterator bi;
bitmap_clear (&used_pseudos_bitmap);
- EXECUTE_IF_AND_IN_BITMAP (&coalesced_pseudos_bitmap, lr_bitmap,
+ EXECUTE_IF_AND_IN_BITMAP (&coalesced_pseudos_bitmap, all,
FIRST_PSEUDO_REGISTER, j, bi)
bitmap_set_bit (&used_pseudos_bitmap, first_coalesced_pseudo[j]);
- if (! bitmap_empty_p (&used_pseudos_bitmap))
+ if (!bitmap_empty_p (&used_pseudos_bitmap))
{
- bitmap_and_compl_into (lr_bitmap, &coalesced_pseudos_bitmap);
- bitmap_ior_into (lr_bitmap, &used_pseudos_bitmap);
+ bitmap_and_compl_into (all, &coalesced_pseudos_bitmap);
+ bitmap_ior_into (all, &used_pseudos_bitmap);
+
+ if (flag_track_subreg_liveness)
+ {
+ bitmap_and_compl_into (full, &coalesced_pseudos_bitmap);
+ bitmap_ior_and_compl_into (full, &used_pseudos_bitmap, partial);
+
+ bitmap_and_compl_into (partial, &coalesced_pseudos_bitmap);
+ bitmap_ior_and_compl_into (partial, &used_pseudos_bitmap, full);
+ }
}
}
@@ -301,8 +310,12 @@ lra_coalesce (void)
bitmap_initialize (&used_pseudos_bitmap, ®_obstack);
FOR_EACH_BB_FN (bb, cfun)
{
- update_live_info (df_get_live_in (bb));
- update_live_info (df_get_live_out (bb));
+ update_live_info (df_get_subreg_live_in (bb),
+ df_get_subreg_live_full_in (bb),
+ df_get_subreg_live_partial_in (bb));
+ update_live_info (df_get_subreg_live_out (bb),
+ df_get_subreg_live_full_out (bb),
+ df_get_subreg_live_partial_out (bb));
FOR_BB_INSNS_SAFE (bb, insn, next)
if (INSN_P (insn)
&& bitmap_bit_p (&involved_insns_bitmap, INSN_UID (insn)))
@@ -6554,34 +6554,86 @@ update_ebb_live_info (rtx_insn *head, rtx_insn *tail)
{
if (prev_bb != NULL)
{
- /* Update df_get_live_in (prev_bb): */
+ /* Update subreg live (prev_bb): */
+ bitmap subreg_all_in = df_get_subreg_live_in (prev_bb);
+ bitmap subreg_full_in = df_get_subreg_live_full_in (prev_bb);
+ bitmap subreg_partial_in = df_get_subreg_live_partial_in (prev_bb);
+ subregs_live *range_in = df_get_subreg_live_range_in (prev_bb);
EXECUTE_IF_SET_IN_BITMAP (&check_only_regs, 0, j, bi)
if (bitmap_bit_p (&live_regs, j))
- bitmap_set_bit (df_get_live_in (prev_bb), j);
- else
- bitmap_clear_bit (df_get_live_in (prev_bb), j);
+ {
+ bitmap_set_bit (subreg_all_in, j);
+ if (flag_track_subreg_liveness)
+ {
+ bitmap_set_bit (subreg_full_in, j);
+ if (bitmap_bit_p (subreg_partial_in, j))
+ {
+ bitmap_clear_bit (subreg_partial_in, j);
+ range_in->remove_range (j);
+ }
+ }
+ }
+ else if (bitmap_bit_p (subreg_all_in, j))
+ {
+ bitmap_clear_bit (subreg_all_in, j);
+ if (flag_track_subreg_liveness)
+ {
+ bitmap_clear_bit (subreg_full_in, j);
+ if (bitmap_bit_p (subreg_partial_in, j))
+ {
+ bitmap_clear_bit (subreg_partial_in, j);
+ range_in->remove_range (j);
+ }
+ }
+ }
}
+ bitmap subreg_all_out = df_get_subreg_live_out (curr_bb);
if (curr_bb != last_bb)
{
- /* Update df_get_live_out (curr_bb): */
+ /* Update subreg live (curr_bb): */
+ bitmap subreg_full_out = df_get_subreg_live_full_out (curr_bb);
+ bitmap subreg_partial_out = df_get_subreg_live_partial_out (curr_bb);
+ subregs_live *range_out = df_get_subreg_live_range_out (curr_bb);
EXECUTE_IF_SET_IN_BITMAP (&check_only_regs, 0, j, bi)
{
live_p = bitmap_bit_p (&live_regs, j);
if (! live_p)
FOR_EACH_EDGE (e, ei, curr_bb->succs)
- if (bitmap_bit_p (df_get_live_in (e->dest), j))
+ if (bitmap_bit_p (df_get_subreg_live_in (e->dest), j))
{
live_p = true;
break;
}
if (live_p)
- bitmap_set_bit (df_get_live_out (curr_bb), j);
- else
- bitmap_clear_bit (df_get_live_out (curr_bb), j);
+ {
+ bitmap_set_bit (subreg_all_out, j);
+ if (flag_track_subreg_liveness)
+ {
+ bitmap_set_bit (subreg_full_out, j);
+ if (bitmap_bit_p (subreg_partial_out, j))
+ {
+ bitmap_clear_bit (subreg_partial_out, j);
+ range_out->remove_range (j);
+ }
+ }
+ }
+ else if (bitmap_bit_p (subreg_all_out, j))
+ {
+ bitmap_clear_bit (subreg_all_out, j);
+ if (flag_track_subreg_liveness)
+ {
+ bitmap_clear_bit (subreg_full_out, j);
+ if (bitmap_bit_p (subreg_partial_out, j))
+ {
+ bitmap_clear_bit (subreg_partial_out, j);
+ range_out->remove_range (j);
+ }
+ }
+ }
}
}
prev_bb = curr_bb;
- bitmap_and (&live_regs, &check_only_regs, df_get_live_out (curr_bb));
+ bitmap_and (&live_regs, &check_only_regs, subreg_all_out);
}
if (! NONDEBUG_INSN_P (curr_insn))
continue;
@@ -6698,7 +6750,7 @@ get_live_on_other_edges (basic_block from, basic_block to, bitmap res)
bitmap_clear (res);
FOR_EACH_EDGE (e, ei, from->succs)
if (e->dest != to)
- bitmap_ior_into (res, df_get_live_in (e->dest));
+ bitmap_ior_into (res, df_get_subreg_live_in (e->dest));
last = get_last_insertion_point (from);
if (! JUMP_P (last))
return;
@@ -6770,7 +6822,7 @@ inherit_in_ebb (rtx_insn *head, rtx_insn *tail)
{
/* We are at the end of BB. Add qualified living
pseudos for potential splitting. */
- to_process = df_get_live_out (curr_bb);
+ to_process = df_get_subreg_live_out (curr_bb);
if (last_processed_bb != NULL)
{
/* We are somewhere in the middle of EBB. */
@@ -7142,7 +7194,7 @@ inherit_in_ebb (rtx_insn *head, rtx_insn *tail)
{
/* We reached the beginning of the current block -- do
rest of spliting in the current BB. */
- to_process = df_get_live_in (curr_bb);
+ to_process = df_get_subreg_live_in (curr_bb);
if (BLOCK_FOR_INSN (head) != curr_bb)
{
/* We are somewhere in the middle of EBB. */
@@ -7219,7 +7271,7 @@ lra_inheritance (void)
fprintf (lra_dump_file, "EBB");
/* Form a EBB starting with BB. */
bitmap_clear (&ebb_global_regs);
- bitmap_ior_into (&ebb_global_regs, df_get_live_in (bb));
+ bitmap_ior_into (&ebb_global_regs, df_get_subreg_live_in (bb));
for (;;)
{
if (lra_dump_file != NULL)
@@ -7235,7 +7287,7 @@ lra_inheritance (void)
break;
bb = bb->next_bb;
}
- bitmap_ior_into (&ebb_global_regs, df_get_live_out (bb));
+ bitmap_ior_into (&ebb_global_regs, df_get_subreg_live_out (bb));
if (lra_dump_file != NULL)
fprintf (lra_dump_file, "\n");
if (inherit_in_ebb (BB_HEAD (start_bb), BB_END (bb)))
@@ -7264,15 +7316,26 @@ int lra_undo_inheritance_iter;
/* Fix BB live info LIVE after removing pseudos created on pass doing
inheritance/split which are REMOVED_PSEUDOS. */
static void
-fix_bb_live_info (bitmap live, bitmap removed_pseudos)
+fix_bb_live_info (bitmap all, bitmap full, bitmap partial,
+ bitmap removed_pseudos)
{
unsigned int regno;
bitmap_iterator bi;
EXECUTE_IF_SET_IN_BITMAP (removed_pseudos, 0, regno, bi)
- if (bitmap_clear_bit (live, regno)
- && REG_P (lra_reg_info[regno].restore_rtx))
- bitmap_set_bit (live, REGNO (lra_reg_info[regno].restore_rtx));
+ {
+ if (bitmap_clear_bit (all, regno)
+ && REG_P (lra_reg_info[regno].restore_rtx))
+ {
+ bitmap_set_bit (all, REGNO (lra_reg_info[regno].restore_rtx));
+ if (flag_track_subreg_liveness)
+ {
+ bitmap_clear_bit (full, regno);
+ bitmap_set_bit (full, REGNO (lra_reg_info[regno].restore_rtx));
+ gcc_assert (!bitmap_bit_p (partial, regno));
+ }
+ }
+ }
}
/* Return regno of the (subreg of) REG. Otherwise, return a negative
@@ -7338,8 +7401,12 @@ remove_inheritance_pseudos (bitmap remove_pseudos)
constraint pass. */
FOR_EACH_BB_FN (bb, cfun)
{
- fix_bb_live_info (df_get_live_in (bb), remove_pseudos);
- fix_bb_live_info (df_get_live_out (bb), remove_pseudos);
+ fix_bb_live_info (df_get_subreg_live_in (bb),
+ df_get_subreg_live_full_in (bb),
+ df_get_subreg_live_partial_in (bb), remove_pseudos);
+ fix_bb_live_info (df_get_subreg_live_out (bb),
+ df_get_subreg_live_full_out (bb),
+ df_get_subreg_live_partial_out (bb), remove_pseudos);
FOR_BB_INSNS_REVERSE (bb, curr_insn)
{
if (! INSN_P (curr_insn))
@@ -21,6 +21,8 @@ along with GCC; see the file COPYING3. If not see
#ifndef GCC_LRA_INT_H
#define GCC_LRA_INT_H
+#include "subreg-live-range.h"
+
#define lra_assert(c) gcc_checking_assert (c)
/* The parameter used to prevent infinite reloading for an insn. Each
@@ -161,6 +163,8 @@ struct lra_insn_reg
int regno;
/* Next reg info of the same insn. */
struct lra_insn_reg *next;
+ /* The corresponding reg or subreg RTX. */
+ rtx op;
};
/* Static part (common info for insns with the same ICODE) of LRA
@@ -272,8 +272,34 @@ update_pseudo_point (int regno, int point, enum point_type type)
}
}
-/* The corresponding bitmaps of BB currently being processed. */
-static bitmap bb_killed_pseudos, bb_gen_pseudos;
+/* Structure describing local BB data used for pseudo
+ live-analysis. */
+class bb_data_pseudos : public df_live_subreg_local_bb_info
+{
+public:
+ /* Basic block about which the below data are. */
+ basic_block bb;
+};
+
+/* Array for all BB data. Indexed by the corresponding BB index. */
+typedef class bb_data_pseudos *bb_data_t;
+
+/* All basic block data are referred through the following array. */
+static bb_data_t bb_data;
+
+/* The corresponding df local data of BB currently being processed. */
+static bb_data_t curr_bb_info;
+
+/* The regs which need to be tracked it's subreg liveness. */
+static bitmap_head tracked_regs;
+
+/* Return true if the REGNO need be track with subreg liveness. */
+
+static bool
+need_track_subreg_p (unsigned regno)
+{
+ return bitmap_bit_p (&tracked_regs, regno);
+}
/* Record hard register REGNO as now being live. It updates
living hard regs and START_LIVING. */
@@ -287,7 +313,7 @@ make_hard_regno_live (int regno)
SET_HARD_REG_BIT (hard_regs_live, regno);
sparseset_set_bit (start_living, regno);
if (fixed_regs[regno] || TEST_HARD_REG_BIT (hard_regs_spilled_into, regno))
- bitmap_set_bit (bb_gen_pseudos, regno);
+ bitmap_set_bit (&curr_bb_info->full_use, regno);
}
/* Process the definition of hard register REGNO. This updates
@@ -310,8 +336,8 @@ make_hard_regno_dead (int regno)
sparseset_set_bit (start_dying, regno);
if (fixed_regs[regno] || TEST_HARD_REG_BIT (hard_regs_spilled_into, regno))
{
- bitmap_clear_bit (bb_gen_pseudos, regno);
- bitmap_set_bit (bb_killed_pseudos, regno);
+ bitmap_clear_bit (&curr_bb_info->full_use, regno);
+ bitmap_set_bit (&curr_bb_info->full_def, regno);
}
}
@@ -343,7 +369,7 @@ mark_pseudo_dead (int regno)
/* Mark register REGNO (pseudo or hard register) in MODE as being live
and update BB_GEN_PSEUDOS. */
static void
-mark_regno_live (int regno, machine_mode mode)
+mark_regno_live (int regno, machine_mode mode, struct lra_insn_reg *reg)
{
int last;
@@ -355,15 +381,23 @@ mark_regno_live (int regno, machine_mode mode)
else
{
mark_pseudo_live (regno);
- bitmap_set_bit (bb_gen_pseudos, regno);
+ if (!need_track_subreg_p (regno))
+ bitmap_set_bit (&curr_bb_info->full_use, regno);
+ else
+ {
+ machine_mode reg_mode
+ = GET_MODE (SUBREG_P (reg->op) ? SUBREG_REG (reg->op) : reg->op);
+ auto_sbitmap range (get_nblocks (reg_mode));
+ init_range (reg->op, range);
+ add_subreg_range_to_use (curr_bb_info, regno, range);
+ }
}
}
-
/* Mark register REGNO (pseudo or hard register) in MODE as being dead
and update BB_GEN_PSEUDOS and BB_KILLED_PSEUDOS. */
static void
-mark_regno_dead (int regno, machine_mode mode)
+mark_regno_dead (int regno, machine_mode mode, struct lra_insn_reg *reg)
{
int last;
@@ -375,8 +409,20 @@ mark_regno_dead (int regno, machine_mode mode)
else
{
mark_pseudo_dead (regno);
- bitmap_clear_bit (bb_gen_pseudos, regno);
- bitmap_set_bit (bb_killed_pseudos, regno);
+ if (!need_track_subreg_p (regno))
+ {
+ bitmap_clear_bit (&curr_bb_info->full_use, regno);
+ bitmap_set_bit (&curr_bb_info->full_def, regno);
+ }
+ else
+ {
+ machine_mode reg_mode
+ = GET_MODE (SUBREG_P (reg->op) ? SUBREG_REG (reg->op) : reg->op);
+ auto_sbitmap range (get_nblocks (reg_mode));
+ init_range (reg->op, range);
+ remove_subreg_range (curr_bb_info, regno, range);
+ add_subreg_range_to_def (curr_bb_info, regno, range);
+ }
}
}
@@ -387,23 +433,6 @@ mark_regno_dead (int regno, machine_mode mode)
border. That might be a consequence of some global transformations
in LRA, e.g. PIC pseudo reuse or rematerialization. */
-/* Structure describing local BB data used for pseudo
- live-analysis. */
-class bb_data_pseudos
-{
-public:
- /* Basic block about which the below data are. */
- basic_block bb;
- bitmap_head killed_pseudos; /* pseudos killed in the BB. */
- bitmap_head gen_pseudos; /* pseudos generated in the BB. */
-};
-
-/* Array for all BB data. Indexed by the corresponding BB index. */
-typedef class bb_data_pseudos *bb_data_t;
-
-/* All basic block data are referred through the following array. */
-static bb_data_t bb_data;
-
/* Two small functions for access to the bb data. */
static inline bb_data_t
get_bb_data (basic_block bb)
@@ -429,14 +458,73 @@ static bitmap_head all_hard_regs_bitmap;
static bool
live_trans_fun (int bb_index)
{
- basic_block bb = get_bb_data_by_index (bb_index)->bb;
- bitmap bb_liveout = df_get_live_out (bb);
- bitmap bb_livein = df_get_live_in (bb);
- bb_data_t bb_info = get_bb_data (bb);
-
- bitmap_and_compl (&temp_bitmap, bb_liveout, &all_hard_regs_bitmap);
- return bitmap_ior_and_compl (bb_livein, &bb_info->gen_pseudos,
- &temp_bitmap, &bb_info->killed_pseudos);
+ bb_data_t local_bb_info = get_bb_data_by_index (bb_index);
+ bitmap full_in = df_get_subreg_live_full_in (local_bb_info->bb);
+ bitmap full_out = df_get_subreg_live_full_out (local_bb_info->bb);
+
+ bitmap_and_compl (&temp_bitmap, full_out, &all_hard_regs_bitmap);
+ bool changed = bitmap_ior_and_compl (full_in, &local_bb_info->full_use,
+ &temp_bitmap, &local_bb_info->full_def);
+
+ /* Handle partial live case. */
+ if (flag_track_subreg_liveness)
+ {
+ bitmap partial_in = df_get_subreg_live_partial_in (local_bb_info->bb);
+ bitmap partial_out = df_get_subreg_live_partial_out (local_bb_info->bb);
+ subregs_live *range_in = df_get_subreg_live_range_in (local_bb_info->bb);
+ subregs_live *range_out
+ = df_get_subreg_live_range_out (local_bb_info->bb);
+
+ if (!bitmap_empty_p (partial_out)
+ || !bitmap_empty_p (&local_bb_info->partial_use))
+ {
+ unsigned int regno;
+ bitmap_iterator bi;
+ bitmap_head temp_partial_out;
+ subregs_live temp_range_out;
+
+ /* TEMP = (OUT & ~DEF) */
+ bitmap_initialize (&temp_partial_out, &bitmap_default_obstack);
+ EXECUTE_IF_SET_IN_BITMAP (partial_out, FIRST_PSEUDO_REGISTER, regno,
+ bi)
+ {
+ sbitmap out_range = range_out->get_range (regno);
+ temp_range_out.add_range (regno, out_range);
+ if (bitmap_bit_p (&local_bb_info->partial_def, regno))
+ {
+ sbitmap def_range
+ = local_bb_info->range_def->get_range (regno);
+ temp_range_out.remove_range (regno, def_range);
+ if (!temp_range_out.empty_p (regno))
+ bitmap_set_bit (&temp_partial_out, regno);
+ }
+ else
+ bitmap_set_bit (&temp_partial_out, regno);
+ }
+
+ /* TEMP = USE | TEMP */
+ EXECUTE_IF_SET_IN_BITMAP (&local_bb_info->partial_use,
+ FIRST_PSEUDO_REGISTER, regno, bi)
+ {
+ sbitmap use_range = local_bb_info->range_use->get_range (regno);
+ temp_range_out.add_range (regno, use_range);
+ }
+ bitmap_ior_into (&temp_partial_out, &local_bb_info->partial_use);
+
+ /* IN = TEMP */
+ changed |= range_in->copy_lives (temp_range_out);
+ bitmap_copy (partial_in, &temp_partial_out);
+ df_live_subreg_check_result (full_in, partial_in, range_in);
+ }
+ else if (!bitmap_empty_p (partial_in))
+ {
+ changed = true;
+ bitmap_clear (partial_in);
+ range_in->clear ();
+ }
+ }
+
+ return changed;
}
/* The confluence function used by the DF equation solver to set up
@@ -444,7 +532,9 @@ live_trans_fun (int bb_index)
static void
live_con_fun_0 (basic_block bb)
{
- bitmap_and_into (df_get_live_out (bb), &all_hard_regs_bitmap);
+ bitmap_and_into (df_get_subreg_live_out (bb), &all_hard_regs_bitmap);
+ if (flag_track_subreg_liveness)
+ bitmap_and_into (df_get_subreg_live_full_out (bb), &all_hard_regs_bitmap);
}
/* The confluence function used by the DF equation solver to propagate
@@ -456,13 +546,37 @@ live_con_fun_0 (basic_block bb)
static bool
live_con_fun_n (edge e)
{
- basic_block bb = e->src;
- basic_block dest = e->dest;
- bitmap bb_liveout = df_get_live_out (bb);
- bitmap dest_livein = df_get_live_in (dest);
+ bitmap src_full_out = df_get_subreg_live_full_out (e->src);
+ bitmap dest_full_in = df_get_subreg_live_full_in (e->dest);
+
+ bool changed = bitmap_ior_and_compl_into (src_full_out, dest_full_in,
+ &all_hard_regs_bitmap);
+ /* Handle partial live case. */
+ if (flag_track_subreg_liveness)
+ {
+ bitmap src_partial_out = df_get_subreg_live_partial_out (e->src);
+ subregs_live *src_range_out = df_get_subreg_live_range_out (e->src);
+ bitmap dest_partial_in = df_get_subreg_live_partial_in (e->dest);
+ subregs_live *dest_range_in = df_get_subreg_live_range_in (e->dest);
+
+ if (bitmap_empty_p (dest_partial_in))
+ return changed;
+
+ unsigned int regno;
+ bitmap_iterator bi;
+ EXECUTE_IF_SET_IN_BITMAP (dest_partial_in, FIRST_PSEUDO_REGISTER, regno,
+ bi)
+ {
+ sbitmap dest_range = dest_range_in->get_range (regno);
+ changed |= src_range_out->add_range (regno, dest_range);
+ }
+ changed |= bitmap_ior_into (src_partial_out, dest_partial_in);
- return bitmap_ior_and_compl_into (bb_liveout,
- dest_livein, &all_hard_regs_bitmap);
+ df_live_subreg_check_result (src_full_out, src_partial_out,
+ src_range_out);
+ }
+
+ return changed;
}
/* Indexes of all function blocks. */
@@ -479,12 +593,47 @@ initiate_live_solver (void)
bitmap_initialize (&all_blocks, ®_obstack);
basic_block bb;
+ if (flag_track_subreg_liveness)
+ {
+ bitmap_initialize (&tracked_regs, ®_obstack);
+ FOR_ALL_BB_FN (bb, cfun)
+ {
+ rtx_insn *insn;
+ df_ref use;
+ FOR_BB_INSNS (bb, insn)
+ {
+ if (!NONDEBUG_INSN_P (insn))
+ continue;
+
+ df_insn_info *insn_info = DF_INSN_INFO_GET (insn);
+
+ FOR_EACH_INSN_INFO_USE (use, insn_info)
+ {
+ unsigned int regno = DF_REF_REGNO (use);
+ /* A multireg which is used via subreg pattern. */
+ if (multireg_p (regno)
+ && DF_REF_FLAGS (use) & (DF_REF_SUBREG))
+ bitmap_set_bit (&tracked_regs, regno);
+ }
+ }
+ }
+ }
+
+
FOR_ALL_BB_FN (bb, cfun)
{
bb_data_t bb_info = get_bb_data (bb);
bb_info->bb = bb;
- bitmap_initialize (&bb_info->killed_pseudos, ®_obstack);
- bitmap_initialize (&bb_info->gen_pseudos, ®_obstack);
+ bitmap_initialize (&bb_info->full_def, ®_obstack);
+ bitmap_initialize (&bb_info->full_use, ®_obstack);
+ if (flag_track_subreg_liveness)
+ {
+ bitmap_initialize (&bb_info->partial_def, ®_obstack);
+ bitmap_initialize (&bb_info->partial_use, ®_obstack);
+ size_t num_regs = bitmap_count_bits (&tracked_regs);
+ bb_info->range_def = new subregs_live (num_regs);
+ bb_info->range_use = new subregs_live (num_regs);
+ }
bitmap_set_bit (&all_blocks, bb->index);
}
}
@@ -496,11 +645,19 @@ finish_live_solver (void)
basic_block bb;
bitmap_clear (&all_blocks);
+ bitmap_clear (&tracked_regs);
FOR_ALL_BB_FN (bb, cfun)
{
bb_data_t bb_info = get_bb_data (bb);
- bitmap_clear (&bb_info->killed_pseudos);
- bitmap_clear (&bb_info->gen_pseudos);
+ bitmap_clear (&bb_info->full_def);
+ bitmap_clear (&bb_info->full_use);
+ if (flag_track_subreg_liveness)
+ {
+ bitmap_clear (&bb_info->partial_def);
+ bitmap_clear (&bb_info->partial_use);
+ delete bb_info->range_def;
+ delete bb_info->range_use;
+ }
}
free (bb_data);
bitmap_clear (&all_hard_regs_bitmap);
@@ -663,7 +820,7 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
/* Only has a meaningful value once we've seen a call. */
function_abi last_call_abi = default_function_abi;
- reg_live_out = df_get_live_out (bb);
+ reg_live_out = df_get_subreg_live_out (bb);
sparseset_clear (pseudos_live);
sparseset_clear (pseudos_live_through_calls);
sparseset_clear (pseudos_live_through_setjumps);
@@ -675,10 +832,16 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
mark_pseudo_live (j);
}
- bb_gen_pseudos = &get_bb_data (bb)->gen_pseudos;
- bb_killed_pseudos = &get_bb_data (bb)->killed_pseudos;
- bitmap_clear (bb_gen_pseudos);
- bitmap_clear (bb_killed_pseudos);
+ curr_bb_info = get_bb_data (bb);
+ bitmap_clear (&curr_bb_info->full_use);
+ bitmap_clear (&curr_bb_info->full_def);
+ if (flag_track_subreg_liveness)
+ {
+ bitmap_clear (&curr_bb_info->partial_use);
+ bitmap_clear (&curr_bb_info->partial_def);
+ curr_bb_info->range_use->clear ();
+ curr_bb_info->range_def->clear ();
+ }
freq = REG_FREQ_FROM_BB (bb);
if (lra_dump_file != NULL)
@@ -860,7 +1023,7 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
if (reg->type != OP_IN)
{
update_pseudo_point (reg->regno, curr_point, USE_POINT);
- mark_regno_live (reg->regno, reg->biggest_mode);
+ mark_regno_live (reg->regno, reg->biggest_mode, reg);
/* ??? Should be a no-op for unused registers. */
check_pseudos_live_through_calls (reg->regno, last_call_abi);
}
@@ -886,7 +1049,7 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
{
if (reg->type == OP_OUT)
update_pseudo_point (reg->regno, curr_point, DEF_POINT);
- mark_regno_dead (reg->regno, reg->biggest_mode);
+ mark_regno_dead (reg->regno, reg->biggest_mode, reg);
}
for (reg = curr_static_id->hard_regs; reg != NULL; reg = reg->next)
@@ -945,8 +1108,12 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
{
if (reg->type == OP_IN)
update_pseudo_point (reg->regno, curr_point, USE_POINT);
- mark_regno_live (reg->regno, reg->biggest_mode);
check_pseudos_live_through_calls (reg->regno, last_call_abi);
+ /* Ignore the use of subreg which is used as dest operand. */
+ if (need_track_subreg_p (reg->regno) && reg->subreg_p
+ && reg->type == OP_INOUT)
+ continue;
+ mark_regno_live (reg->regno, reg->biggest_mode, reg);
}
for (reg = curr_static_id->hard_regs; reg != NULL; reg = reg->next)
@@ -970,12 +1137,12 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
{
if (reg->type == OP_OUT)
update_pseudo_point (reg->regno, curr_point, DEF_POINT);
- mark_regno_dead (reg->regno, reg->biggest_mode);
+ mark_regno_dead (reg->regno, reg->biggest_mode, reg);
/* We're done processing inputs, so make sure early clobber
operands that are both inputs and outputs are still live. */
if (reg->type == OP_INOUT)
- mark_regno_live (reg->regno, reg->biggest_mode);
+ mark_regno_live (reg->regno, reg->biggest_mode, reg);
}
for (reg = curr_static_id->hard_regs; reg != NULL; reg = reg->next)
@@ -1099,8 +1266,8 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
bool live_change_p = false;
/* Check if bb border live info was changed. */
unsigned int live_pseudos_num = 0;
- EXECUTE_IF_SET_IN_BITMAP (df_get_live_in (bb),
- FIRST_PSEUDO_REGISTER, j, bi)
+ EXECUTE_IF_SET_IN_BITMAP (df_get_subreg_live_in (bb), FIRST_PSEUDO_REGISTER,
+ j, bi)
{
live_pseudos_num++;
if (! sparseset_bit_p (pseudos_live, j))
@@ -1118,7 +1285,7 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
live_change_p = true;
if (lra_dump_file != NULL)
EXECUTE_IF_SET_IN_SPARSESET (pseudos_live, j)
- if (! bitmap_bit_p (df_get_live_in (bb), j))
+ if (! bitmap_bit_p (df_get_subreg_live_in (bb), j))
fprintf (lra_dump_file,
" r%d is added to live at bb%d start\n", j, bb->index);
}
@@ -1133,7 +1300,8 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
mark_pseudo_dead (i);
}
- EXECUTE_IF_SET_IN_BITMAP (df_get_live_in (bb), FIRST_PSEUDO_REGISTER, j, bi)
+ EXECUTE_IF_SET_IN_BITMAP (df_get_subreg_live_in (bb), FIRST_PSEUDO_REGISTER,
+ j, bi)
{
if (sparseset_cardinality (pseudos_live_through_calls) == 0)
break;
@@ -1149,7 +1317,7 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
if (!TEST_HARD_REG_BIT (hard_regs_spilled_into, i))
continue;
- if (bitmap_bit_p (df_get_live_in (bb), i))
+ if (bitmap_bit_p (df_get_subreg_live_in (bb), i))
continue;
live_change_p = true;
@@ -1157,7 +1325,9 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
fprintf (lra_dump_file,
" hard reg r%d is added to live at bb%d start\n", i,
bb->index);
- bitmap_set_bit (df_get_live_in (bb), i);
+ bitmap_set_bit (df_get_subreg_live_in (bb), i);
+ if (flag_track_subreg_liveness)
+ bitmap_set_bit (df_get_subreg_live_full_in (bb), i);
}
if (need_curr_point_incr)
@@ -1421,12 +1591,30 @@ lra_create_live_ranges_1 (bool all_p, bool dead_insn_p)
{
/* We need to clear pseudo live info as some pseudos can
disappear, e.g. pseudos with used equivalences. */
- FOR_EACH_BB_FN (bb, cfun)
+ FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR_FOR_FN (cfun),
+ EXIT_BLOCK_PTR_FOR_FN (cfun), next_bb)
{
- bitmap_clear_range (df_get_live_in (bb), FIRST_PSEUDO_REGISTER,
+ bitmap_clear_range (df_get_subreg_live_in (bb), FIRST_PSEUDO_REGISTER,
max_regno - FIRST_PSEUDO_REGISTER);
- bitmap_clear_range (df_get_live_out (bb), FIRST_PSEUDO_REGISTER,
+ bitmap_clear_range (df_get_subreg_live_out (bb), FIRST_PSEUDO_REGISTER,
max_regno - FIRST_PSEUDO_REGISTER);
+ if (flag_track_subreg_liveness)
+ {
+ bitmap_clear_range (df_get_subreg_live_full_in (bb),
+ FIRST_PSEUDO_REGISTER,
+ max_regno - FIRST_PSEUDO_REGISTER);
+ bitmap_clear_range (df_get_subreg_live_partial_in (bb),
+ FIRST_PSEUDO_REGISTER,
+ max_regno - FIRST_PSEUDO_REGISTER);
+ bitmap_clear_range (df_get_subreg_live_full_out (bb),
+ FIRST_PSEUDO_REGISTER,
+ max_regno - FIRST_PSEUDO_REGISTER);
+ bitmap_clear_range (df_get_subreg_live_partial_out (bb),
+ FIRST_PSEUDO_REGISTER,
+ max_regno - FIRST_PSEUDO_REGISTER);
+ df_get_subreg_live_range_in (bb)->clear ();
+ df_get_subreg_live_range_out (bb)->clear ();
+ }
}
/* As we did not change CFG since LRA start we can use
DF-infrastructure solver to solve live data flow problem. */
@@ -1439,6 +1627,10 @@ lra_create_live_ranges_1 (bool all_p, bool dead_insn_p)
(DF_BACKWARD, NULL, live_con_fun_0, live_con_fun_n,
live_trans_fun, &all_blocks,
df_get_postorder (DF_BACKWARD), df_get_n_blocks (DF_BACKWARD));
+
+ if (flag_track_subreg_liveness)
+ df_live_subreg_finalize (&all_blocks);
+
if (lra_dump_file != NULL)
{
fprintf (lra_dump_file,
@@ -1447,16 +1639,33 @@ lra_create_live_ranges_1 (bool all_p, bool dead_insn_p)
FOR_EACH_BB_FN (bb, cfun)
{
bb_data_t bb_info = get_bb_data (bb);
- bitmap bb_livein = df_get_live_in (bb);
- bitmap bb_liveout = df_get_live_out (bb);
fprintf (lra_dump_file, "\nBB %d:\n", bb->index);
- lra_dump_bitmap_with_title (" gen:",
- &bb_info->gen_pseudos, bb->index);
- lra_dump_bitmap_with_title (" killed:",
- &bb_info->killed_pseudos, bb->index);
- lra_dump_bitmap_with_title (" livein:", bb_livein, bb->index);
- lra_dump_bitmap_with_title (" liveout:", bb_liveout, bb->index);
+ lra_dump_bitmap_with_title (" full use", &bb_info->full_use,
+ bb->index);
+ lra_dump_bitmap_with_title (" full def", &bb_info->full_def,
+ bb->index);
+ lra_dump_bitmap_with_title (" live in full",
+ df_get_subreg_live_full_in (bb),
+ bb->index);
+ lra_dump_bitmap_with_title (" live out full",
+ df_get_subreg_live_full_out (bb),
+ bb->index);
+ if (flag_track_subreg_liveness)
+ {
+ lra_dump_bitmap_with_title (" partial use",
+ &bb_info->partial_use, bb->index);
+ lra_dump_bitmap_with_title (" partial def",
+ &bb_info->partial_def, bb->index);
+ lra_dump_bitmap_with_title (" live in partial",
+ df_get_subreg_live_partial_in (
+ bb),
+ bb->index);
+ lra_dump_bitmap_with_title (" live out partial",
+ df_get_subreg_live_partial_out (
+ bb),
+ bb->index);
+ }
}
}
}
@@ -556,11 +556,11 @@ dump_candidates_and_remat_bb_data (void)
fprintf (lra_dump_file, "\nBB %d:\n", bb->index);
/* Livein */
fprintf (lra_dump_file, " register live in:");
- dump_regset (df_get_live_in (bb), lra_dump_file);
+ dump_regset (df_get_subreg_live_in (bb), lra_dump_file);
putc ('\n', lra_dump_file);
/* Liveout */
fprintf (lra_dump_file, " register live out:");
- dump_regset (df_get_live_out (bb), lra_dump_file);
+ dump_regset (df_get_subreg_live_out (bb), lra_dump_file);
putc ('\n', lra_dump_file);
/* Changed/dead regs: */
fprintf (lra_dump_file, " changed regs:");
@@ -727,7 +727,7 @@ calculate_livein_cands (void)
FOR_EACH_BB_FN (bb, cfun)
{
- bitmap livein_regs = df_get_live_in (bb);
+ bitmap livein_regs = df_get_subreg_live_in (bb);
bitmap livein_cands = &get_remat_bb_data (bb)->livein_cands;
for (unsigned int i = 0; i < cands_num; i++)
{
@@ -1064,7 +1064,7 @@ do_remat (void)
FOR_EACH_BB_FN (bb, cfun)
{
CLEAR_HARD_REG_SET (live_hard_regs);
- EXECUTE_IF_SET_IN_BITMAP (df_get_live_in (bb), 0, regno, bi)
+ EXECUTE_IF_SET_IN_BITMAP (df_get_subreg_live_in (bb), 0, regno, bi)
{
int hard_regno = regno < FIRST_PSEUDO_REGISTER
? regno
@@ -566,8 +566,31 @@ spill_pseudos (void)
"Debug insn #%u is reset because it referenced "
"removed pseudo\n", INSN_UID (insn));
}
- bitmap_and_compl_into (df_get_live_in (bb), spilled_pseudos);
- bitmap_and_compl_into (df_get_live_out (bb), spilled_pseudos);
+ bitmap_and_compl_into (df_get_subreg_live_in (bb), spilled_pseudos);
+ bitmap_and_compl_into (df_get_subreg_live_out (bb), spilled_pseudos);
+
+ if (flag_track_subreg_liveness)
+ {
+ bitmap_and_compl_into (df_get_subreg_live_full_in (bb),
+ spilled_pseudos);
+ bitmap partial_in = df_get_subreg_live_partial_in (bb);
+ subregs_live *range_in = df_get_subreg_live_range_in (bb);
+ unsigned int regno;
+ bitmap_iterator bi;
+ EXECUTE_IF_AND_IN_BITMAP (partial_in, spilled_pseudos,
+ FIRST_PSEUDO_REGISTER, regno, bi)
+ range_in->remove_range (regno);
+ bitmap_and_compl_into (partial_in, spilled_pseudos);
+
+ bitmap_and_compl_into (df_get_subreg_live_full_out (bb),
+ spilled_pseudos);
+ bitmap partial_out = df_get_subreg_live_partial_out (bb);
+ subregs_live *range_out = df_get_subreg_live_range_out (bb);
+ EXECUTE_IF_AND_IN_BITMAP (partial_out, spilled_pseudos,
+ FIRST_PSEUDO_REGISTER, regno, bi)
+ range_out->remove_range (regno);
+ bitmap_and_compl_into (partial_out, spilled_pseudos);
+ }
}
}
}
@@ -574,7 +574,7 @@ object_allocator<lra_insn_reg> lra_insn_reg_pool ("insn regs");
EARLY_CLOBBER_ALTS. */
static struct lra_insn_reg *
new_insn_reg (rtx_insn *insn, int regno, enum op_type type,
- machine_mode mode, bool subreg_p,
+ machine_mode mode, bool subreg_p, rtx op,
alternative_mask early_clobber_alts,
struct lra_insn_reg *next)
{
@@ -586,6 +586,7 @@ new_insn_reg (rtx_insn *insn, int regno, enum op_type type,
ir->subreg_p = subreg_p;
ir->early_clobber_alts = early_clobber_alts;
ir->regno = regno;
+ ir->op = op;
ir->next = next;
return ir;
}
@@ -926,7 +927,7 @@ collect_non_operand_hard_regs (rtx_insn *insn, rtx *x,
&& ! (FIRST_STACK_REG <= regno
&& regno <= LAST_STACK_REG));
#endif
- list = new_insn_reg (data->insn, regno, type, mode, subreg_p,
+ list = new_insn_reg (data->insn, regno, type, mode, subreg_p, *x,
early_clobber ? ALL_ALTERNATIVES : 0, list);
}
}
@@ -1484,6 +1485,7 @@ add_regs_to_insn_regno_info (lra_insn_recog_data_t data, rtx x,
code = GET_CODE (x);
mode = GET_MODE (x);
subreg_p = false;
+ rtx op = x;
if (GET_CODE (x) == SUBREG)
{
mode = wider_subreg_mode (x);
@@ -1501,7 +1503,7 @@ add_regs_to_insn_regno_info (lra_insn_recog_data_t data, rtx x,
if (bitmap_set_bit (&lra_reg_info[regno].insn_bitmap, INSN_UID (insn)))
{
data->regs = new_insn_reg (data->insn, regno, type, mode, subreg_p,
- early_clobber_alts, data->regs);
+ op, early_clobber_alts, data->regs);
return;
}
else
@@ -1513,7 +1515,7 @@ add_regs_to_insn_regno_info (lra_insn_recog_data_t data, rtx x,
/* The info cannot be integrated into the found
structure. */
data->regs = new_insn_reg (data->insn, regno, type, mode,
- subreg_p, early_clobber_alts,
+ subreg_p, op, early_clobber_alts,
data->regs);
else
{