---
 gcc/lra-coalesce.cc    |  27 +++-
 gcc/lra-constraints.cc | 109 ++++++++++---
 gcc/lra-int.h          |   4 +
 gcc/lra-lives.cc       | 357 ++++++++++++++++++++++++++++++++---------
 gcc/lra-remat.cc       |   8 +-
 gcc/lra-spills.cc      |  27 +++-
 gcc/lra.cc             |  10 +-
 7 files changed, 430 insertions(+), 112 deletions(-)

diff --git a/gcc/lra-coalesce.cc b/gcc/lra-coalesce.cc
index a9b5b51cb3f..9416775a009 100644
--- a/gcc/lra-coalesce.cc
+++ b/gcc/lra-coalesce.cc
@@ -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, &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_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)))
diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc
index e945a4da451..c9246e6be58 100644
--- a/gcc/lra-constraints.cc
+++ b/gcc/lra-constraints.cc
@@ -6565,34 +6565,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;
@@ -6709,7 +6761,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;
@@ -6781,7 +6833,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.  */
@@ -7153,7 +7205,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.  */
@@ -7230,7 +7282,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)
@@ -7246,7 +7298,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)))
@@ -7275,15 +7327,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
@@ -7349,8 +7412,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))
diff --git a/gcc/lra-int.h b/gcc/lra-int.h
index 5f605c3ae41..d73ff4e31b5 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
@@ -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
diff --git a/gcc/lra-lives.cc b/gcc/lra-lives.cc
index 66c6577e5d6..27897fdd3e1 100644
--- a/gcc/lra-lives.cc
+++ b/gcc/lra-lives.cc
@@ -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, &reg_obstack);
 
   basic_block bb;
+  if (flag_track_subreg_liveness)
+    {
+      bitmap_initialize (&tracked_regs, &reg_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, &reg_obstack);
-      bitmap_initialize (&bb_info->gen_pseudos, &reg_obstack);
+      bitmap_initialize (&bb_info->full_def, &reg_obstack);
+      bitmap_initialize (&bb_info->full_use, &reg_obstack);
+      if (flag_track_subreg_liveness)
+       {
+         bitmap_initialize (&bb_info->partial_def, &reg_obstack);
+         bitmap_initialize (&bb_info->partial_use, &reg_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);
+               }
            }
        }
     }
diff --git a/gcc/lra-remat.cc b/gcc/lra-remat.cc
index c84bf3c9938..ef0157513b0 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_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
diff --git a/gcc/lra-spills.cc b/gcc/lra-spills.cc
index 8b1a945d632..08ec247bc00 100644
--- a/gcc/lra-spills.cc
+++ b/gcc/lra-spills.cc
@@ -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);
+           }
        }
     }
 }
diff --git a/gcc/lra.cc b/gcc/lra.cc
index fb32e134004..a6fabe7d118 100644
--- a/gcc/lra.cc
+++ b/gcc/lra.cc
@@ -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
                  {
-- 
2.36.3


Reply via email to