[V3,6/7] lra: Switch to live_subreg data flow

Message ID 20231112120817.2635864-7-lehua.ding@rivai.ai
State Unresolved
Headers
Series ira/lra: Support subreg coalesce |

Checks

Context Check Description
snail/gcc-patch-check warning Git am fail log

Commit Message

Lehua Ding Nov. 12, 2023, 12:08 p.m. UTC
  This patch switches the live_reg data in lra to live_subreg data,
and the situation will be more complicated than in ira because
this part of the data is modified in lra also and the live_subreg
data will be recalculated.

gcc/ChangeLog:

	* lra-coalesce.cc (update_live_info):
	Adjust to new live subreg data.
	(lra_coalesce): Ditto.
	* lra-constraints.cc (update_ebb_live_info): Ditto.
	(get_live_on_other_edges): Ditto.
	(inherit_in_ebb): Ditto.
	(lra_inheritance): Ditto.
	(fix_bb_live_info): Ditto.
	(remove_inheritance_pseudos): Ditto.
	* lra-int.h (GCC_LRA_INT_H): Ditto.
	* lra-lives.cc (class bb_data_pseudos): Ditto.
	(make_hard_regno_live): Ditto.
	(make_hard_regno_dead): Ditto.
	(mark_regno_live): Ditto.
	(mark_regno_dead): Ditto.
	(live_trans_fun): Ditto.
	(live_con_fun_0): Ditto.
	(live_con_fun_n): Ditto.
	(initiate_live_solver): Ditto.
	(finish_live_solver): Ditto.
	(process_bb_lives): Ditto.
	(lra_create_live_ranges_1): Ditto.
	* lra-remat.cc (dump_candidates_and_remat_bb_data): Ditto.
	(calculate_livein_cands): Ditto.
	(do_remat): Ditto.
	* lra-spills.cc (spill_pseudos): Ditto.

---
 gcc/lra-coalesce.cc    |  20 ++-
 gcc/lra-constraints.cc |  93 +++++++++---
 gcc/lra-int.h          |   2 +
 gcc/lra-lives.cc       | 328 ++++++++++++++++++++++++++++++++---------
 gcc/lra-remat.cc       |  13 +-
 gcc/lra-spills.cc      |  22 ++-
 6 files changed, 374 insertions(+), 104 deletions(-)
  

Patch

diff --git a/gcc/lra-coalesce.cc b/gcc/lra-coalesce.cc
index 04a5bbd714b..abfc54f1cc2 100644
--- a/gcc/lra-coalesce.cc
+++ b/gcc/lra-coalesce.cc
@@ -188,19 +188,25 @@  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))
     {
-      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);
+
+      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);
     }
 }
 
@@ -303,8 +309,10 @@  lra_coalesce (void)
   bitmap_initialize (&used_pseudos_bitmap, &reg_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_LIVE_SUBREG_IN (bb), DF_LIVE_SUBREG_FULL_IN (bb),
+			DF_LIVE_SUBREG_PARTIAL_IN (bb));
+      update_live_info (DF_LIVE_SUBREG_OUT (bb), DF_LIVE_SUBREG_FULL_OUT (bb),
+			DF_LIVE_SUBREG_PARTIAL_OUT (bb));
       FOR_BB_INSNS_SAFE (bb, insn, next)
 	if (INSN_P (insn)
 	    && bitmap_bit_p (&involved_insns_bitmap, INSN_UID (insn)))
diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc
index 0607c8be7cb..c3ad846b97b 100644
--- a/gcc/lra-constraints.cc
+++ b/gcc/lra-constraints.cc
@@ -6571,34 +6571,75 @@  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_LIVE_SUBREG_IN (prev_bb);
+	      bitmap subreg_full_in = DF_LIVE_SUBREG_FULL_IN (prev_bb);
+	      bitmap subreg_partial_in = DF_LIVE_SUBREG_PARTIAL_IN (prev_bb);
+	      subregs_live *range_in = DF_LIVE_SUBREG_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);
+		    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_live (j);
+		      }
+		  }
+		else if (bitmap_bit_p (subreg_all_in, j))
+		  {
+		    bitmap_clear_bit (subreg_all_in, j);
+		    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_live (j);
+		      }
+		  }
 	    }
+	  bitmap subreg_all_out = DF_LIVE_SUBREG_OUT (curr_bb);
 	  if (curr_bb != last_bb)
 	    {
-	      /* Update df_get_live_out (curr_bb):  */
+	      /* Update subreg live (curr_bb):  */
+	      bitmap subreg_all_out = DF_LIVE_SUBREG_OUT (curr_bb);
+	      bitmap subreg_full_out = DF_LIVE_SUBREG_FULL_OUT (curr_bb);
+	      bitmap subreg_partial_out = DF_LIVE_SUBREG_PARTIAL_OUT (curr_bb);
+	      subregs_live *range_out = DF_LIVE_SUBREG_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_LIVE_SUBREG_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);
+		      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_live (j);
+			}
+		    }
+		  else if (bitmap_bit_p (subreg_all_out, j))
+		    {
+		      bitmap_clear_bit (subreg_all_out, j);
+		      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_live (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;
@@ -6715,7 +6756,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_LIVE_SUBREG_IN (e->dest));
   last = get_last_insertion_point (from);
   if (! JUMP_P (last))
     return;
@@ -6787,7 +6828,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_LIVE_SUBREG_OUT (curr_bb);
 	  if (last_processed_bb != NULL)
 	    {
 	      /* We are somewhere in the middle of EBB.	 */
@@ -7159,7 +7200,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_LIVE_SUBREG_IN (curr_bb);
 	  if (BLOCK_FOR_INSN (head) != curr_bb)
 	    {
 	      /* We are somewhere in the middle of EBB.	 */
@@ -7236,7 +7277,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_LIVE_SUBREG_IN (bb));
       for (;;)
 	{
 	  if (lra_dump_file != NULL)
@@ -7252,7 +7293,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_LIVE_SUBREG_OUT (bb));
       if (lra_dump_file != NULL)
 	fprintf (lra_dump_file, "\n");
       if (inherit_in_ebb (BB_HEAD (start_bb), BB_END (bb)))
@@ -7281,15 +7322,23 @@  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));
+	  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
@@ -7355,8 +7404,10 @@  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_LIVE_SUBREG_IN (bb), DF_LIVE_SUBREG_FULL_IN (bb),
+			DF_LIVE_SUBREG_PARTIAL_IN (bb), remove_pseudos);
+      fix_bb_live_info (DF_LIVE_SUBREG_OUT (bb), DF_LIVE_SUBREG_FULL_OUT (bb),
+			DF_LIVE_SUBREG_PARTIAL_OUT (bb), remove_pseudos);
       FOR_BB_INSNS_REVERSE (bb, curr_insn)
 	{
 	  if (! INSN_P (curr_insn))
diff --git a/gcc/lra-int.h b/gcc/lra-int.h
index d0752c2ae50..678377d9ec6 100644
--- a/gcc/lra-int.h
+++ b/gcc/lra-int.h
@@ -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
diff --git a/gcc/lra-lives.cc b/gcc/lra-lives.cc
index f60e564da82..d93921ad302 100644
--- a/gcc/lra-lives.cc
+++ b/gcc/lra-lives.cc
@@ -272,8 +272,26 @@  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 basic_block_subreg_live_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 basic block info of BB currently being processed.  */
+static bb_data_t curr_bb_info;
+
+/* Flag mean curr function has subreg ref need be tracked.  */
+static bool has_subreg_live_p;
 
 /* Record hard register REGNO as now being live.  It updates
    living hard regs and START_LIVING.  */
@@ -287,7 +305,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 +328,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);
     }
 }
 
@@ -355,7 +373,9 @@  mark_regno_live (int regno, machine_mode mode)
   else
     {
       mark_pseudo_live (regno);
-      bitmap_set_bit (bb_gen_pseudos, regno);
+      bitmap_set_bit (&curr_bb_info->full_use, regno);
+      gcc_assert (!bitmap_bit_p (&curr_bb_info->partial_use, regno));
+      gcc_assert (!bitmap_bit_p (&curr_bb_info->partial_def, regno));
     }
 }
 
@@ -375,8 +395,10 @@  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);
+      bitmap_clear_bit (&curr_bb_info->full_use, regno);
+      bitmap_set_bit (&curr_bb_info->full_def, regno);
+      gcc_assert (!bitmap_bit_p (&curr_bb_info->partial_use, regno));
+      gcc_assert (!bitmap_bit_p (&curr_bb_info->partial_def, regno));
     }
 }
 
@@ -387,23 +409,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)
@@ -430,13 +435,93 @@  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);
+  bitmap full_out = DF_LIVE_SUBREG_FULL_OUT (bb);
+  bitmap full_in = DF_LIVE_SUBREG_FULL_IN (bb);
+  bitmap partial_out = DF_LIVE_SUBREG_PARTIAL_OUT (bb);
+  bitmap partial_in = DF_LIVE_SUBREG_PARTIAL_IN (bb);
+  subregs_live *range_out = DF_LIVE_SUBREG_RANGE_OUT (bb);
+  subregs_live *range_in = DF_LIVE_SUBREG_RANGE_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);
+  if (!has_subreg_live_p)
+    {
+      bitmap_and_compl (&temp_bitmap, full_out, &all_hard_regs_bitmap);
+      return bitmap_ior_and_compl (full_in, &bb_info->full_use, &temp_bitmap,
+				   &bb_info->full_def);
+    }
+
+  /* If there has subreg live need be tracked.  */
+  unsigned int regno;
+  bitmap_iterator bi;
+  bool changed = false;
+  bitmap_head temp_full_out;
+  bitmap_head temp_partial_out;
+  bitmap_head temp_partial_be_full_out;
+  bitmap_head all_def;
+  subregs_live temp_range_out;
+  bitmap_initialize (&temp_full_out, &reg_obstack);
+  bitmap_initialize (&temp_partial_out, &reg_obstack);
+  bitmap_initialize (&temp_partial_be_full_out, &reg_obstack);
+  bitmap_initialize (&all_def, &reg_obstack);
+
+  bitmap_and_compl (&temp_full_out, full_out, &all_hard_regs_bitmap);
+
+  bitmap_ior (&all_def, &bb_info->full_def, &bb_info->partial_def);
+
+  bitmap_and (&temp_partial_out, &temp_full_out, &bb_info->partial_def);
+  EXECUTE_IF_SET_IN_BITMAP (&temp_partial_out, FIRST_PSEUDO_REGISTER, regno, bi)
+    {
+      subreg_ranges temp (bb_info->range_def->lives.at (regno).max);
+      temp.make_full ();
+      temp.remove_ranges (bb_info->range_def->lives.at (regno));
+      temp_range_out.add_ranges (regno, temp);
+    }
+  bitmap_ior_and_compl_into (&temp_partial_out, partial_out, &all_def);
+  EXECUTE_IF_AND_COMPL_IN_BITMAP (partial_out, &all_def, FIRST_PSEUDO_REGISTER,
+				  regno, bi)
+    {
+      temp_range_out.add_ranges (regno, range_out->lives.at (regno));
+    }
+  EXECUTE_IF_AND_IN_BITMAP (partial_out, &bb_info->partial_def, 0, regno, bi)
+    {
+      subreg_ranges temp = range_out->lives.at (regno);
+      temp.remove_ranges (bb_info->range_def->lives.at (regno));
+      if (!temp.empty_p ())
+	{
+	  bitmap_set_bit (&temp_partial_out, regno);
+	  temp_range_out.add_ranges (regno, temp);
+	}
+    }
+
+  temp_range_out.add_lives (*bb_info->range_use);
+  EXECUTE_IF_AND_IN_BITMAP (&temp_partial_out, &bb_info->partial_use, 0, regno,
+			    bi)
+    {
+      subreg_ranges temp = temp_range_out.lives.at (regno);
+      temp.add_ranges (bb_info->range_use->lives.at (regno));
+      if (temp.full_p ())
+	{
+	  bitmap_set_bit (&temp_partial_be_full_out, regno);
+	  temp_range_out.remove_live (regno);
+	}
+    }
+
+  bitmap_ior_and_compl_into (&temp_partial_be_full_out, &temp_full_out,
+			     &all_def);
+  changed
+    |= bitmap_ior (full_in, &temp_partial_be_full_out, &bb_info->full_use);
+
+  bitmap_ior_into (&temp_partial_out, &bb_info->partial_use);
+  changed |= bitmap_and_compl (partial_in, &temp_partial_out,
+			       &temp_partial_be_full_out);
+  changed |= range_in->copy_lives (temp_range_out);
+
+  bitmap_clear (&temp_full_out);
+  bitmap_clear (&temp_partial_out);
+  bitmap_clear (&temp_partial_be_full_out);
+  bitmap_clear (&all_def);
+
+  return changed;
 }
 
 /* The confluence function used by the DF equation solver to set up
@@ -444,7 +529,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_LIVE_SUBREG_OUT (bb), &all_hard_regs_bitmap);
+  bitmap_and_into (DF_LIVE_SUBREG_FULL_OUT (bb), &all_hard_regs_bitmap);
+  bitmap_and_into (DF_LIVE_SUBREG_PARTIAL_OUT (bb), &all_hard_regs_bitmap);
 }
 
 /* The confluence function used by the DF equation solver to propagate
@@ -456,13 +543,77 @@  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);
+  class df_live_subreg_bb_info *src_bb_info
+    = df_live_subreg_get_bb_info (e->src->index);
+  class df_live_subreg_bb_info *dest_bb_info
+    = df_live_subreg_get_bb_info (e->dest->index);
+
+  if (!has_subreg_live_p)
+    {
+      return bitmap_ior_and_compl_into (&src_bb_info->full_out,
+					&dest_bb_info->full_in,
+					&all_hard_regs_bitmap);
+    }
+
+  /* If there has subreg live need be tracked. Calculation formula:
+       temp_full mean:
+	 1. partial in out/in, full in other in/out
+	 2. partial in out and in, and mrege range is full
+       temp_range mean:
+	 the range of regno which partial live
+       src_bb_info->partial_out = (src_bb_info->partial_out |
+     dest_bb_info->partial_in) & ~temp_full src_bb_info->range_out = copy
+     (temp_range) src_bb_info->full_out |= dest_bb_info->full_in | temp_full
+       */
+  subregs_live temp_range;
+  temp_range.add_lives (*src_bb_info->range_out);
+  temp_range.add_lives (*dest_bb_info->range_in);
+
+  bitmap_head temp_partial_all;
+  bitmap_initialize (&temp_partial_all, &bitmap_default_obstack);
+  bitmap_ior (&temp_partial_all, &src_bb_info->partial_out,
+	      &dest_bb_info->partial_in);
+
+  bitmap_head temp_full;
+  bitmap_initialize (&temp_full, &bitmap_default_obstack);
+
+  /* Collect regno that become full after merge src_bb_info->partial_out
+     and dest_bb_info->partial_in.  */
+  unsigned int regno;
+  bitmap_iterator bi;
+  EXECUTE_IF_SET_IN_BITMAP (&temp_partial_all, FIRST_PSEUDO_REGISTER, regno, bi)
+    {
+      if (bitmap_bit_p (&src_bb_info->full_out, regno)
+	  || bitmap_bit_p (&dest_bb_info->full_in, regno))
+	{
+	  bitmap_set_bit (&temp_full, regno);
+	  temp_range.remove_live (regno);
+	  continue;
+	}
+      else if (!bitmap_bit_p (&src_bb_info->partial_out, regno)
+	       || !bitmap_bit_p (&dest_bb_info->partial_in, regno))
+	continue;
+
+      subreg_ranges temp = src_bb_info->range_out->lives.at (regno);
+      temp.add_ranges (dest_bb_info->range_in->lives.at (regno));
+      if (temp.full_p ())
+	{
+	  bitmap_set_bit (&temp_full, regno);
+	  temp_range.remove_live (regno);
+	}
+    }
+
+  /* Calculating src_bb_info->partial_out and src_bb_info->range_out.  */
+  bool changed = bitmap_and_compl (&src_bb_info->partial_out, &temp_partial_all,
+				   &temp_full);
+  changed |= src_bb_info->range_out->copy_lives (temp_range);
 
-  return bitmap_ior_and_compl_into (bb_liveout,
-				    dest_livein, &all_hard_regs_bitmap);
+  /* Calculating src_bb_info->full_out.  */
+  bitmap_ior_and_compl_into (&temp_full, &dest_bb_info->full_in,
+			     &all_hard_regs_bitmap);
+  changed |= bitmap_ior_into (&src_bb_info->full_out, &temp_full);
+
+  return changed;
 }
 
 /* Indexes of all function blocks.  */
@@ -483,8 +634,12 @@  initiate_live_solver (void)
     {
       bb_data_t bb_info = get_bb_data (bb);
       bb_info->bb = bb;
-      bitmap_initialize (&bb_info->killed_pseudos, &reg_obstack);
-      bitmap_initialize (&bb_info->gen_pseudos, &reg_obstack);
+      bitmap_initialize (&bb_info->full_def, &reg_obstack);
+      bitmap_initialize (&bb_info->partial_def, &reg_obstack);
+      bitmap_initialize (&bb_info->full_use, &reg_obstack);
+      bitmap_initialize (&bb_info->partial_use, &reg_obstack);
+      bb_info->range_def = new subregs_live ();
+      bb_info->range_use = new subregs_live ();
       bitmap_set_bit (&all_blocks, bb->index);
     }
 }
@@ -499,8 +654,12 @@  finish_live_solver (void)
   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->partial_def);
+      bitmap_clear (&bb_info->full_use);
+      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 +822,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_LIVE_SUBREG_OUT (bb);
   sparseset_clear (pseudos_live);
   sparseset_clear (pseudos_live_through_calls);
   sparseset_clear (pseudos_live_through_setjumps);
@@ -675,10 +834,13 @@  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->partial_use);
+  bitmap_clear (&curr_bb_info->full_def);
+  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)
@@ -1101,16 +1263,16 @@  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_LIVE_SUBREG_IN (bb), FIRST_PSEUDO_REGISTER, j,
+			    bi)
     {
       live_pseudos_num++;
-      if (! sparseset_bit_p (pseudos_live, j))
+      if (!sparseset_bit_p (pseudos_live, j))
 	{
 	  live_change_p = true;
 	  if (lra_dump_file != NULL)
-	    fprintf (lra_dump_file,
-		     "  r%d is removed as live at bb%d start\n", j, bb->index);
+	    fprintf (lra_dump_file, "  r%d is removed as live at bb%d start\n",
+		     j, bb->index);
 	  break;
 	}
     }
@@ -1120,9 +1282,9 @@  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))
-	    fprintf (lra_dump_file,
-		     "  r%d is added to live at bb%d start\n", j, bb->index);
+      if (!bitmap_bit_p (DF_LIVE_SUBREG_IN (bb), j))
+	fprintf (lra_dump_file, "  r%d is added to live at bb%d start\n", j,
+		 bb->index);
     }
   /* See if we'll need an increment at the end of this basic block.
      An increment is needed if the PSEUDOS_LIVE set is not empty,
@@ -1135,8 +1297,9 @@  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_LIVE_SUBREG_IN (bb), FIRST_PSEUDO_REGISTER, j,
+			      bi)
+      {
       if (sparseset_cardinality (pseudos_live_through_calls) == 0)
 	break;
       if (sparseset_bit_p (pseudos_live_through_calls, j))
@@ -1151,7 +1314,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_LIVE_SUBREG_IN (bb), i))
 	continue;
 
       live_change_p = true;
@@ -1159,7 +1322,8 @@  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_LIVE_SUBREG_IN (bb), i);
+      bitmap_set_bit (DF_LIVE_SUBREG_FULL_IN (bb), i);
     }
 
   if (need_curr_point_incr)
@@ -1425,10 +1589,24 @@  lra_create_live_ranges_1 (bool all_p, bool dead_insn_p)
 	 disappear, e.g. pseudos with used equivalences.  */
       FOR_EACH_BB_FN (bb, cfun)
 	{
-	  bitmap_clear_range (df_get_live_in (bb), FIRST_PSEUDO_REGISTER,
+	  bitmap_clear_range (DF_LIVE_SUBREG_IN (bb), FIRST_PSEUDO_REGISTER,
+			      max_regno - FIRST_PSEUDO_REGISTER);
+	  bitmap_clear_range (DF_LIVE_SUBREG_FULL_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_LIVE_SUBREG_PARTIAL_IN (bb),
+			      FIRST_PSEUDO_REGISTER,
 			      max_regno - FIRST_PSEUDO_REGISTER);
+	  bitmap_clear_range (DF_LIVE_SUBREG_OUT (bb), FIRST_PSEUDO_REGISTER,
+			      max_regno - FIRST_PSEUDO_REGISTER);
+	  bitmap_clear_range (DF_LIVE_SUBREG_FULL_OUT (bb),
+			      FIRST_PSEUDO_REGISTER,
+			      max_regno - FIRST_PSEUDO_REGISTER);
+	  bitmap_clear_range (DF_LIVE_SUBREG_PARTIAL_OUT (bb),
+			      FIRST_PSEUDO_REGISTER,
+			      max_regno - FIRST_PSEUDO_REGISTER);
+	  DF_LIVE_SUBREG_RANGE_IN (bb)->clear ();
+	  DF_LIVE_SUBREG_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.  */
@@ -1441,6 +1619,8 @@  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));
+      df_live_subreg_finalize (&all_blocks);
+
       if (lra_dump_file != NULL)
 	{
 	  fprintf (lra_dump_file,
@@ -1449,16 +1629,28 @@  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 ("  partial use",
+					  &bb_info->partial_use, bb->index);
+	      lra_dump_bitmap_with_title ("  full def", &bb_info->full_def,
+					  bb->index);
+	      lra_dump_bitmap_with_title ("  partial def",
+					  &bb_info->partial_def, bb->index);
+	      lra_dump_bitmap_with_title ("  live in full",
+					  DF_LIVE_SUBREG_FULL_IN (bb),
+					  bb->index);
+	      lra_dump_bitmap_with_title ("  live in partial",
+					  DF_LIVE_SUBREG_PARTIAL_IN (bb),
+					  bb->index);
+	      lra_dump_bitmap_with_title ("  live out full",
+					  DF_LIVE_SUBREG_FULL_OUT (bb),
+					  bb->index);
+	      lra_dump_bitmap_with_title ("  live out partial",
+					  DF_LIVE_SUBREG_PARTIAL_OUT (bb),
+					  bb->index);
 	    }
 	}
     }
diff --git a/gcc/lra-remat.cc b/gcc/lra-remat.cc
index 681dcf36331..26d3da07b00 100644
--- a/gcc/lra-remat.cc
+++ b/gcc/lra-remat.cc
@@ -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_LIVE_SUBREG_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_LIVE_SUBREG_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_LIVE_SUBREG_IN (bb);
       bitmap livein_cands = &get_remat_bb_data (bb)->livein_cands;
       for (unsigned int i = 0; i < cands_num; i++)
 	{
@@ -1064,11 +1064,10 @@  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_LIVE_SUBREG_IN (bb), 0, regno, bi)
 	{
-	  int hard_regno = regno < FIRST_PSEUDO_REGISTER
-			   ? regno
-			   : reg_renumber[regno];
+	  int hard_regno
+	    = regno < FIRST_PSEUDO_REGISTER ? regno : reg_renumber[regno];
 	  if (hard_regno >= 0)
 	    SET_HARD_REG_BIT (live_hard_regs, hard_regno);
 	}
diff --git a/gcc/lra-spills.cc b/gcc/lra-spills.cc
index a663a1931e3..d38a2ffe2a7 100644
--- a/gcc/lra-spills.cc
+++ b/gcc/lra-spills.cc
@@ -566,8 +566,26 @@  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);
+	  unsigned int regno;
+	  bitmap_iterator bi;
+
+	  bitmap_and_compl_into (DF_LIVE_SUBREG_IN (bb), spilled_pseudos);
+	  bitmap_and_compl_into (DF_LIVE_SUBREG_FULL_IN (bb), spilled_pseudos);
+	  bitmap partial_in = DF_LIVE_SUBREG_PARTIAL_IN (bb);
+	  subregs_live *range_in = DF_LIVE_SUBREG_RANGE_IN (bb);
+	  EXECUTE_IF_AND_IN_BITMAP (partial_in, spilled_pseudos,
+				    FIRST_PSEUDO_REGISTER, regno, bi)
+	    range_in->remove_live (regno);
+	  bitmap_and_compl_into (partial_in, spilled_pseudos);
+
+	  bitmap_and_compl_into (DF_LIVE_SUBREG_OUT (bb), spilled_pseudos);
+	  bitmap_and_compl_into (DF_LIVE_SUBREG_FULL_OUT (bb), spilled_pseudos);
+	  bitmap partial_out = DF_LIVE_SUBREG_PARTIAL_OUT (bb);
+	  subregs_live *range_out = DF_LIVE_SUBREG_RANGE_OUT (bb);
+	  EXECUTE_IF_AND_IN_BITMAP (partial_out, spilled_pseudos,
+				    FIRST_PSEUDO_REGISTER, regno, bi)
+	    range_out->remove_live (regno);
+	  bitmap_and_compl_into (partial_out, spilled_pseudos);
 	}
     }
 }