re PR rtl-optimization/63620 (RELOAD lost SET_GOT dependency on Darwin)
authorVladimir Makarov <vmakarov@redhat.com>
Sun, 9 Nov 2014 16:45:15 +0000 (16:45 +0000)
committerVladimir Makarov <vmakarov@gcc.gnu.org>
Sun, 9 Nov 2014 16:45:15 +0000 (16:45 +0000)
2014-11-09  Vladimir Makarov  <vmakarov@redhat.com>

PR rtl-optimization/63620
* lra-constraints.c (substitute_pseudo): Add prefix lra_ to the
name.  Move to lra.c.  Make it external.
(substitute_pseudo_within_insn): Ditto.
(inherit_reload_reg, split_reg, remove_inheritance_pseudos): Use
the new names.
(undo_optional_reloads): Ditto.
* lra-int.h (lra_dump_bitmap_with_title, lra_substitute_pseudo):
New prototypes.
(lra_substitute_pseudo_within_insn): Ditto.
* lra-lives.c (bb_killed_pseudos, bb_gen_pseudos): New.
(mark_regno_live): Add parameter.  Update bb_gen_pseudos.
(mark_regno_dead): Add parameter.  Update bb_gen_pseudos and
bb_killed_pseudos.
(struct bb_data, bb_data_t, bb_data): New.
(get_bb_data, get_bb_data_by_index): Ditto.
(all_hard_regs_bitmap): New.
(live_trans_fun, live_con_fun_0, live_con_fun_n, all_blocks): New.
(initiate_live_solver, finish_live_solver): New.
(process_bb_lives): Change return type.  Add code updating local
live data and removing dead insns.  Pass new argument to
mark_regno_live and mark_regno_dead.  Check changing bb pseudo
life info.  Return the result.
(lra_create_live_ranges): Add code to do global pseudo live
analysis.
(lra_live_ranges_init): Call initiate_live_solver.
(lra_live_ranges_finish): Call finish_live_solver.
* lra.c (lra_dump_bitmap_with_title): New.
(lra_substitute_pseudo, lra_substitute_pseudo_within_insn): Move
from lra-constraints.c.

From-SVN: r217265

gcc/ChangeLog
gcc/lra-constraints.c
gcc/lra-int.h
gcc/lra-lives.c
gcc/lra.c

index 5f7edb2f69f2e79b4305dd6d675919970e8cfdbd..c2e61a56351a2cd107da498bdc02ef9f960e0351 100644 (file)
@@ -1,3 +1,36 @@
+2014-11-09  Vladimir Makarov  <vmakarov@redhat.com>
+
+       PR rtl-optimization/63620
+       * lra-constraints.c (substitute_pseudo): Add prefix lra_ to the
+       name.  Move to lra.c.  Make it external.
+       (substitute_pseudo_within_insn): Ditto.
+       (inherit_reload_reg, split_reg, remove_inheritance_pseudos): Use
+       the new names.
+       (undo_optional_reloads): Ditto.
+       * lra-int.h (lra_dump_bitmap_with_title, lra_substitute_pseudo):
+       New prototypes.
+       (lra_substitute_pseudo_within_insn): Ditto.
+       * lra-lives.c (bb_killed_pseudos, bb_gen_pseudos): New.
+       (mark_regno_live): Add parameter.  Update bb_gen_pseudos.
+       (mark_regno_dead): Add parameter.  Update bb_gen_pseudos and
+       bb_killed_pseudos.
+       (struct bb_data, bb_data_t, bb_data): New.
+       (get_bb_data, get_bb_data_by_index): Ditto.
+       (all_hard_regs_bitmap): New.
+       (live_trans_fun, live_con_fun_0, live_con_fun_n, all_blocks): New.
+       (initiate_live_solver, finish_live_solver): New.
+       (process_bb_lives): Change return type.  Add code updating local
+       live data and removing dead insns.  Pass new argument to
+       mark_regno_live and mark_regno_dead.  Check changing bb pseudo
+       life info.  Return the result.
+       (lra_create_live_ranges): Add code to do global pseudo live
+       analysis.
+       (lra_live_ranges_init): Call initiate_live_solver.
+       (lra_live_ranges_finish): Call finish_live_solver.
+       * lra.c (lra_dump_bitmap_with_title): New.
+       (lra_substitute_pseudo, lra_substitute_pseudo_within_insn): Move
+       from lra-constraints.c.
+
 2014-11-09  Richard Biener  <rguenther@suse.de>
 
        * match.pd: Add patterns convering two conversions in a row
index 36405d253929b69e11f7b22b687126b9850477a6..73533547942f44ad59d44a21686fabfd6a8dbe46 100644 (file)
@@ -4366,67 +4366,6 @@ add_next_usage_insn (int regno, rtx insn, int reloads_num)
     usage_insns[regno].check = 0;
 }
 
-/* Replace all references to register OLD_REGNO in *LOC with pseudo
-   register NEW_REG.  Return true if any change was made.  */
-static bool
-substitute_pseudo (rtx *loc, int old_regno, rtx new_reg)
-{
-  rtx x = *loc;
-  bool result = false;
-  enum rtx_code code;
-  const char *fmt;
-  int i, j;
-
-  if (x == NULL_RTX)
-    return false;
-
-  code = GET_CODE (x);
-  if (code == REG && (int) REGNO (x) == old_regno)
-    {
-      machine_mode mode = GET_MODE (*loc);
-      machine_mode inner_mode = GET_MODE (new_reg);
-
-      if (mode != inner_mode)
-       {
-         if (GET_MODE_SIZE (mode) >= GET_MODE_SIZE (inner_mode)
-             || ! SCALAR_INT_MODE_P (inner_mode))
-           new_reg = gen_rtx_SUBREG (mode, new_reg, 0);
-         else
-           new_reg = gen_lowpart_SUBREG (mode, new_reg);
-       }
-      *loc = new_reg;
-      return true;
-    }
-
-  /* Scan all the operand sub-expressions.  */
-  fmt = GET_RTX_FORMAT (code);
-  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
-    {
-      if (fmt[i] == 'e')
-       {
-         if (substitute_pseudo (&XEXP (x, i), old_regno, new_reg))
-           result = true;
-       }
-      else if (fmt[i] == 'E')
-       {
-         for (j = XVECLEN (x, i) - 1; j >= 0; j--)
-           if (substitute_pseudo (&XVECEXP (x, i, j), old_regno, new_reg))
-             result = true;
-       }
-    }
-  return result;
-}
-
-/* Call substitute_pseudo within an insn.  This won't update the insn ptr,
-   just the contents of the insn.  */
-
-static bool
-substitute_pseudo_within_insn (rtx_insn *insn, int old_regno, rtx new_reg)
-{
-  rtx loc = insn;
-  return substitute_pseudo (&loc, old_regno, new_reg);
-}
-
 /* Return first non-debug insn in list USAGE_INSNS.  */
 static rtx_insn *
 skip_usage_debug_insns (rtx usage_insns)
@@ -4588,7 +4527,7 @@ inherit_reload_reg (bool def_p, int original_regno,
        }
       return false;
     }
-  substitute_pseudo_within_insn (insn, original_regno, new_reg);
+  lra_substitute_pseudo_within_insn (insn, original_regno, new_reg);
   lra_update_insn_regno_info (insn);
   if (! def_p)
     /* We now have a new usage insn for original regno.  */
@@ -4620,7 +4559,7 @@ inherit_reload_reg (bool def_p, int original_regno,
          lra_assert (DEBUG_INSN_P (usage_insn));
          next_usage_insns = XEXP (next_usage_insns, 1);
        }
-      substitute_pseudo (&usage_insn, original_regno, new_reg);
+      lra_substitute_pseudo (&usage_insn, original_regno, new_reg);
       lra_update_insn_regno_info (as_a <rtx_insn *> (usage_insn));
       if (lra_dump_file != NULL)
        {
@@ -4884,7 +4823,7 @@ split_reg (bool before_p, int original_regno, rtx_insn *insn,
       usage_insn = XEXP (next_usage_insns, 0);
       lra_assert (DEBUG_INSN_P (usage_insn));
       next_usage_insns = XEXP (next_usage_insns, 1);
-      substitute_pseudo (&usage_insn, original_regno, new_reg);
+      lra_substitute_pseudo (&usage_insn, original_regno, new_reg);
       lra_update_insn_regno_info (as_a <rtx_insn *> (usage_insn));
       if (lra_dump_file != NULL)
        {
@@ -5803,7 +5742,7 @@ remove_inheritance_pseudos (bitmap remove_pseudos)
                    {
                      if (change_p && bitmap_bit_p (remove_pseudos, regno))
                        {
-                         substitute_pseudo_within_insn (
+                         lra_substitute_pseudo_within_insn (
                            curr_insn, regno, regno_reg_rtx[restore_regno]);
                          restored_regs_p = true;
                        }
@@ -5927,7 +5866,7 @@ undo_optional_reloads (void)
                 we remove the inheritance pseudo and the optional
                 reload.  */
            }
-         substitute_pseudo_within_insn (
+         lra_substitute_pseudo_within_insn (
            insn, regno,
            regno_reg_rtx[lra_reg_info[regno].restore_regno]);
          lra_update_insn_regno_info (insn);
index ae4164f21678b7205ada8e8311f00c2f26ccb4c1..5355ebfa4ec9bf3ecea57d52cdd9fbfa8b2a7b85 100644 (file)
@@ -284,6 +284,7 @@ extern lra_insn_recog_data_t *lra_insn_recog_data;
 
 extern int lra_curr_reload_num;
 
+extern void lra_dump_bitmap_with_title (const char *, bitmap, int);
 extern void lra_push_insn (rtx_insn *);
 extern void lra_push_insn_by_uid (unsigned int);
 extern void lra_push_insn_and_update_insn_regno_info (rtx_insn *);
@@ -303,6 +304,9 @@ extern void lra_update_dups (lra_insn_recog_data_t, signed char *);
 extern void lra_process_new_insns (rtx_insn *, rtx_insn *, rtx_insn *,
                                   const char *);
 
+extern bool lra_substitute_pseudo (rtx *, int, rtx);
+extern bool lra_substitute_pseudo_within_insn (rtx_insn *, int, rtx);
+
 extern lra_insn_recog_data_t lra_set_insn_recog_data (rtx_insn *);
 extern lra_insn_recog_data_t lra_update_insn_recog_data (rtx_insn *);
 extern void lra_set_used_insn_alternative (rtx_insn *, int);
index 6a494032e6503ffe05a1f2fa3c7d40b22742dd5d..0e97cd814299df160ad7d1ba31ffd6b2e5440cce 100644 (file)
@@ -316,12 +316,15 @@ mark_pseudo_dead (int regno, int point)
     }
 }
 
-/* Mark register REGNO (pseudo or hard register) in MODE as live
-   at program point POINT.
-   Return TRUE if the liveness tracking sets were modified,
-   or FALSE if nothing changed.  */
+/* The corresponding bitmaps of BB currently being processed.  */
+static bitmap bb_killed_pseudos, bb_gen_pseudos;
+
+/* Mark register REGNO (pseudo or hard register) in MODE as live at
+   program point POINT.  Update BB_GEN_PSEUDOS if LOCAL_SETS_P.
+   Return TRUE if the liveness tracking sets were modified, or FALSE
+   if nothing changed.  */
 static bool
-mark_regno_live (int regno, machine_mode mode, int point)
+mark_regno_live (int regno, machine_mode mode, int point, bool local_sets_p)
 {
   int last;
   bool changed = false;
@@ -333,20 +336,26 @@ mark_regno_live (int regno, machine_mode mode, int point)
           regno++)
        make_hard_regno_born (regno);
     }
-  else if (! sparseset_bit_p (pseudos_live, regno))
+  else
     {
-      mark_pseudo_live (regno, point);
-      changed = true;
+      if (! sparseset_bit_p (pseudos_live, regno))
+       {
+         mark_pseudo_live (regno, point);
+         changed = true;
+       }
+      if (local_sets_p)
+       bitmap_set_bit (bb_gen_pseudos, regno);
     }
   return changed;
 }
 
 
-/* Mark register REGNO in MODE as dead at program point POINT.
-   Return TRUE if the liveness tracking sets were modified,
-   or FALSE if nothing changed.  */
+/* Mark register REGNO in MODE as dead at program point POINT.  Update
+   BB_GEN_PSEUDOS and BB_KILLED_PSEUDOS if LOCAL_SETS_P.  Return TRUE
+   if the liveness tracking sets were modified, or FALSE if nothing
+   changed.  */
 static bool
-mark_regno_dead (int regno, machine_mode mode, int point)
+mark_regno_dead (int regno, machine_mode mode, int point, bool local_sets_p)
 {
   int last;
   bool changed = false;
@@ -358,14 +367,154 @@ mark_regno_dead (int regno, machine_mode mode, int point)
           regno++)
        make_hard_regno_dead (regno);
     }
-  else if (sparseset_bit_p (pseudos_live, regno))
+  else
     {
-      mark_pseudo_dead (regno, point);
-      changed = true;
+      if (sparseset_bit_p (pseudos_live, regno))
+       {
+         mark_pseudo_dead (regno, point);
+         changed = true;
+       }
+      if (local_sets_p)
+       {
+         bitmap_clear_bit (bb_gen_pseudos, regno);
+         bitmap_set_bit (bb_killed_pseudos, regno);
+       }
     }
   return changed;
 }
 
+\f
+
+/* This page contains code for making global live analysis of pseudos.
+   The code works only when pseudo live info is changed on a BB
+   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.  */
+struct bb_data
+{
+  /* 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 struct bb_data *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)
+{
+  return &bb_data[(bb)->index];
+}
+
+static inline bb_data_t
+get_bb_data_by_index (int index)
+{
+  return &bb_data[index];
+}
+
+/* Bitmap with all hard regs.  */
+static bitmap_head all_hard_regs_bitmap;
+
+/* Bitmap used for holding intermediate bitmap operation results.  */
+static bitmap_head temp_bitmap;
+
+/* The transfer function used by the DF equation solver to propagate
+   live info through block with BB_INDEX according to the following
+   equation:
+
+     bb.livein = (bb.liveout - bb.kill) OR bb.gen
+*/
+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);
+}
+
+/* The confluence function used by the DF equation solver to set up
+   live info for a block BB without predecessor.  */
+static void
+live_con_fun_0 (basic_block bb)
+{
+  bitmap_and_into (df_get_live_out (bb), &all_hard_regs_bitmap);
+}
+
+/* The confluence function used by the DF equation solver to propagate
+   live info from successor to predecessor on edge E according to the
+   following equation:
+
+      bb.liveout = 0 for entry block | OR (livein of successors)
+ */
+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);
+  
+  return bitmap_ior_and_compl_into (bb_liveout,
+                                   dest_livein, &all_hard_regs_bitmap);
+}
+
+/* Indexes of all function blocks.  */
+static bitmap_head all_blocks;
+
+/* Allocate and initialize data needed for global pseudo live
+   analysis.  */
+static void
+initiate_live_solver (void)
+{
+  bitmap_initialize (&temp_bitmap, &reg_obstack);
+  bitmap_initialize (&all_hard_regs_bitmap, &reg_obstack);
+  bitmap_set_range (&all_hard_regs_bitmap, 0, FIRST_PSEUDO_REGISTER);
+  bb_data = XNEWVEC (struct bb_data, last_basic_block_for_fn (cfun));
+  bitmap_initialize (&all_blocks, &reg_obstack);
+
+  basic_block bb;
+  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_set_bit (&all_blocks, bb->index);
+    }
+}
+
+/* Free all data needed for global pseudo live analysis.  */
+static void
+finish_live_solver (void)
+{
+  basic_block bb;
+
+  bitmap_clear (&all_blocks);
+  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);
+    }
+  free (bb_data);
+  bitmap_clear (&all_hard_regs_bitmap);
+  bitmap_clear (&temp_bitmap);
+}
+
+\f
+
 /* Insn currently scanned.  */
 static rtx_insn *curr_insn;
 /* The insn data.  */
@@ -492,8 +641,10 @@ check_pseudos_live_through_calls (int regno)
    pseudo hard register conflicts, and insn notes.  We do it on
    backward scan of BB insns.  CURR_POINT is the program point where
    BB ends.  The function updates this counter and returns in
-   CURR_POINT the program point where BB starts.  */
-static void
+   CURR_POINT the program point where BB starts.  The function also
+   can delete the dead insns.  It returns true if pseudo live info was
+   changed at the BB start.  */
+static bool
 process_bb_lives (basic_block bb, int &curr_point)
 {
   int i, regno, freq;
@@ -501,6 +652,7 @@ process_bb_lives (basic_block bb, int &curr_point)
   bitmap_iterator bi;
   bitmap reg_live_out;
   unsigned int px;
+  rtx_insn *next;
   rtx link, *link_loc;
   bool need_curr_point_incr;
 
@@ -514,6 +666,11 @@ process_bb_lives (basic_block bb, int &curr_point)
   EXECUTE_IF_SET_IN_BITMAP (reg_live_out, FIRST_PSEUDO_REGISTER, j, bi)
     mark_pseudo_live (j, curr_point);
 
+  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);
+
   freq = REG_FREQ_FROM_BB (bb);
 
   if (lra_dump_file != NULL)
@@ -528,7 +685,7 @@ process_bb_lives (basic_block bb, int &curr_point)
      FOO will remain live until the beginning of the block.  Likewise
      if FOO is not set at all. This is unnecessarily pessimistic, but
      it probably doesn't matter much in practice.  */
-  FOR_BB_INSNS_REVERSE (bb, curr_insn)
+  FOR_BB_INSNS_REVERSE_SAFE (bb, curr_insn, next)
     {
       bool call_p;
       int dst_regno, src_regno;
@@ -544,6 +701,51 @@ process_bb_lives (basic_block bb, int &curr_point)
        fprintf (lra_dump_file, "   Insn %u: point = %d\n",
                 INSN_UID (curr_insn), curr_point);
 
+      set = single_set (curr_insn);
+
+      if (set != NULL_RTX
+         && REG_P (SET_DEST (set)) && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER)
+       {
+         bool dead_insn_p = true;
+
+         for (reg = curr_id->regs; reg != NULL; reg = reg->next)
+           if (reg->type != OP_IN && sparseset_bit_p (pseudos_live, reg->regno))
+             {
+               dead_insn_p = false;
+               break;
+             }
+         for (reg = curr_static_id->hard_regs; reg != NULL; reg = reg->next)
+           if (reg->type != OP_IN)
+             {
+               dead_insn_p = false;
+               break;
+             }
+         if (dead_insn_p && ! volatile_refs_p (PATTERN (curr_insn)))
+           {
+             dst_regno = REGNO (SET_DEST (set));
+             if (lra_dump_file != NULL)
+               fprintf (lra_dump_file, "   Deleting dead insn %u\n",
+                        INSN_UID (curr_insn));
+             lra_set_insn_deleted (curr_insn);
+             if (lra_reg_info[dst_regno].nrefs == 0)
+               {
+                 /* There might be some debug insns with the pseudo.  */
+                 unsigned int uid;
+                 rtx_insn *insn;
+
+                 EXECUTE_IF_SET_IN_BITMAP
+                   (&lra_reg_info[dst_regno].insn_bitmap, 0, uid, bi)
+                   {
+                     insn = lra_insn_recog_data[uid]->insn;
+                     lra_substitute_pseudo_within_insn (insn, dst_regno,
+                                                        SET_SRC (set));
+                     lra_update_insn_regno_info (insn);
+                   }
+               }
+             continue;
+           }
+       }
+
       /* Update max ref width and hard reg usage.  */
       for (reg = curr_id->regs; reg != NULL; reg = reg->next)
        if (reg->regno >= FIRST_PSEUDO_REGISTER
@@ -555,7 +757,7 @@ process_bb_lives (basic_block bb, int &curr_point)
 
       call_p = CALL_P (curr_insn);
       if (complete_info_p
-         && (set = single_set (curr_insn)) != NULL_RTX
+         && set != NULL_RTX
          && REG_P (SET_DEST (set)) && REG_P (SET_SRC (set))
          /* Check that source regno does not conflict with
             destination regno to exclude most impossible
@@ -612,7 +814,7 @@ process_bb_lives (basic_block bb, int &curr_point)
          {
            need_curr_point_incr |= mark_regno_live (reg->regno,
                                                     reg->biggest_mode,
-                                                    curr_point);
+                                                    curr_point, true);
            check_pseudos_live_through_calls (reg->regno);
          }
 
@@ -629,7 +831,7 @@ process_bb_lives (basic_block bb, int &curr_point)
        if (reg->type == OP_OUT && ! reg->early_clobber && ! reg->subreg_p)
          need_curr_point_incr |= mark_regno_dead (reg->regno,
                                                   reg->biggest_mode,
-                                                  curr_point);
+                                                  curr_point, true);
 
       for (reg = curr_static_id->hard_regs; reg != NULL; reg = reg->next)
        if (reg->type == OP_OUT && ! reg->early_clobber && ! reg->subreg_p)
@@ -671,7 +873,7 @@ process_bb_lives (basic_block bb, int &curr_point)
          {
            need_curr_point_incr |= mark_regno_live (reg->regno,
                                                     reg->biggest_mode,
-                                                    curr_point);
+                                                    curr_point, true);
            check_pseudos_live_through_calls (reg->regno);
          }
 
@@ -691,7 +893,7 @@ process_bb_lives (basic_block bb, int &curr_point)
        if (reg->type == OP_OUT && reg->early_clobber && ! reg->subreg_p)
          need_curr_point_incr |= mark_regno_dead (reg->regno,
                                                   reg->biggest_mode,
-                                                  curr_point);
+                                                  curr_point, true);
 
       for (reg = curr_static_id->hard_regs; reg != NULL; reg = reg->next)
        if (reg->type == OP_OUT && reg->early_clobber && ! reg->subreg_p)
@@ -764,6 +966,20 @@ process_bb_lives (basic_block bb, int &curr_point)
            make_hard_regno_born (px);
     }
 
+  /* Check if bb border live info was changed.  */
+  unsigned int live_pseudos_num = 0;
+  bool live_change_p = false;
+  EXECUTE_IF_SET_IN_BITMAP (df_get_live_in (bb), FIRST_PSEUDO_REGISTER, j, bi)
+    {
+      live_pseudos_num++;
+      if (! sparseset_bit_p (pseudos_live, j))
+       {
+         live_change_p = TRUE;
+         break;
+       }
+    }
+  live_change_p = live_change_p || sparseset_cardinality (pseudos_live) != live_pseudos_num;
+
   /* 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,
      to make sure the finish points are set up correctly.  */
@@ -779,9 +995,11 @@ process_bb_lives (basic_block bb, int &curr_point)
       if (sparseset_bit_p (pseudos_live_through_calls, j))
        check_pseudos_live_through_calls (j);
     }
-
+  
   if (need_curr_point_incr)
     next_program_point (curr_point, freq);
+
+  return live_change_p;
 }
 
 /* Compress pseudo live ranges by removing program points where
@@ -947,19 +1165,22 @@ compress_live_ranges (void)
     }
 }
 
+\f
+
 /* The number of the current live range pass.  */
 int lra_live_range_iter;
 
 /* The main entry function creates live ranges only for memory pseudos
-   (or for all ones if ALL_P), set up CONFLICT_HARD_REGS for
-   the pseudos.         */
+   (or for all ones if ALL_P), set up CONFLICT_HARD_REGS for the
+   pseudos.  It also does global live analysis only for pseudos and
+   only if the pseudo live info was changed on a BB border.  */
 void
 lra_create_live_ranges (bool all_p)
 {
   basic_block bb;
   int i, hard_regno, max_regno = max_reg_num ();
   int curr_point;
-  bool have_referenced_pseudos = false;
+  bool bb_live_change_p, have_referenced_pseudos = false;
 
   timevar_push (TV_LRA_CREATE_LIVE_RANGES);
 
@@ -1023,17 +1244,55 @@ lra_create_live_ranges (bool all_p)
   int *post_order_rev_cfg = XNEWVEC (int, last_basic_block_for_fn (cfun));
   int n_blocks_inverted = inverted_post_order_compute (post_order_rev_cfg);
   lra_assert (n_blocks_inverted == n_basic_blocks_for_fn (cfun));
+  bb_live_change_p = false;
   for (i = n_blocks_inverted - 1; i >= 0; --i)
     {
       bb = BASIC_BLOCK_FOR_FN (cfun, post_order_rev_cfg[i]);
       if (bb == EXIT_BLOCK_PTR_FOR_FN (cfun) || bb
          == ENTRY_BLOCK_PTR_FOR_FN (cfun))
        continue;
-      process_bb_lives (bb, curr_point);
+      if (process_bb_lives (bb, curr_point))
+       bb_live_change_p = true;
+    }
+  if (bb_live_change_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)
+       {
+         bitmap_clear_range (df_get_live_in (bb), FIRST_PSEUDO_REGISTER,
+                             max_regno - FIRST_PSEUDO_REGISTER);
+         bitmap_clear_range (df_get_live_out (bb), FIRST_PSEUDO_REGISTER,
+                             max_regno - FIRST_PSEUDO_REGISTER);
+       }
+      /* As we did not change CFG since LRA start we can use
+        DF-infrastructure solver to solve live data flow problem.  */
+      df_simple_dataflow
+       (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 (lra_dump_file != NULL)
+       {
+         fprintf (lra_dump_file, "Global pseudo live data have be updated:\n");
+         basic_block bb;
+         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);
+           }
+       }
     }
   free (post_order_rev_cfg);
   lra_live_max_point = curr_point;
-  gcc_checking_assert (lra_live_max_point > 0);
   if (lra_dump_file != NULL)
     print_live_ranges (lra_dump_file);
   /* Clean up. */
@@ -1065,11 +1324,13 @@ lra_live_ranges_init (void)
 {
   live_range_pool = create_alloc_pool ("live ranges",
                                       sizeof (struct lra_live_range), 100);
+  initiate_live_solver ();
 }
 
 /* Finish live ranges data once per function.  */
 void
 lra_live_ranges_finish (void)
 {
+  finish_live_solver ();
   free_alloc_pool (live_range_pool);
 }
index ee390db0b06eacd21fb1c6eb9710d48faf9395ac..3ae47e86ba641fe68245ded4b5dbb5fdcf56787e 100644 (file)
--- a/gcc/lra.c
+++ b/gcc/lra.c
@@ -129,6 +129,33 @@ along with GCC; see the file COPYING3.     If not see
 #include "lra-int.h"
 #include "df.h"
 
+/* Dump bitmap SET with TITLE and BB INDEX.  */
+void
+lra_dump_bitmap_with_title (const char *title, bitmap set, int index)
+{
+  unsigned int i;
+  int count;
+  bitmap_iterator bi;
+  static const int max_nums_on_line = 10;
+
+  if (bitmap_empty_p (set))
+    return;
+  fprintf (lra_dump_file, "  %s %d:", title, index);
+  fprintf (lra_dump_file, "\n");
+  count = max_nums_on_line + 1;
+  EXECUTE_IF_SET_IN_BITMAP (set, 0, i, bi)
+    {
+      if (count > max_nums_on_line)
+       {
+         fprintf (lra_dump_file, "\n    ");
+         count = 0;
+       }
+      fprintf (lra_dump_file, " %4u", i);
+      count++;
+    }
+  fprintf (lra_dump_file, "\n");
+}
+
 /* Hard registers currently not available for allocation.  It can
    changed after some hard  registers become not eliminable.  */
 HARD_REG_SET lra_no_alloc_regs;
@@ -1753,6 +1780,68 @@ lra_process_new_insns (rtx_insn *insn, rtx_insn *before, rtx_insn *after,
 
 \f
 
+/* Replace all references to register OLD_REGNO in *LOC with pseudo
+   register NEW_REG.  Return true if any change was made.  */
+bool
+lra_substitute_pseudo (rtx *loc, int old_regno, rtx new_reg)
+{
+  rtx x = *loc;
+  bool result = false;
+  enum rtx_code code;
+  const char *fmt;
+  int i, j;
+
+  if (x == NULL_RTX)
+    return false;
+
+  code = GET_CODE (x);
+  if (code == REG && (int) REGNO (x) == old_regno)
+    {
+      machine_mode mode = GET_MODE (*loc);
+      machine_mode inner_mode = GET_MODE (new_reg);
+
+      if (mode != inner_mode)
+       {
+         if (GET_MODE_SIZE (mode) >= GET_MODE_SIZE (inner_mode)
+             || ! SCALAR_INT_MODE_P (inner_mode))
+           new_reg = gen_rtx_SUBREG (mode, new_reg, 0);
+         else
+           new_reg = gen_lowpart_SUBREG (mode, new_reg);
+       }
+      *loc = new_reg;
+      return true;
+    }
+
+  /* Scan all the operand sub-expressions.  */
+  fmt = GET_RTX_FORMAT (code);
+  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+    {
+      if (fmt[i] == 'e')
+       {
+         if (lra_substitute_pseudo (&XEXP (x, i), old_regno, new_reg))
+           result = true;
+       }
+      else if (fmt[i] == 'E')
+       {
+         for (j = XVECLEN (x, i) - 1; j >= 0; j--)
+           if (lra_substitute_pseudo (&XVECEXP (x, i, j), old_regno, new_reg))
+             result = true;
+       }
+    }
+  return result;
+}
+
+/* Call lra_substitute_pseudo within an insn.  This won't update the insn ptr,
+   just the contents of the insn.  */
+bool
+lra_substitute_pseudo_within_insn (rtx_insn *insn, int old_regno, rtx new_reg)
+{
+  rtx loc = insn;
+  return lra_substitute_pseudo (&loc, old_regno, new_reg);
+}
+
+\f
+
 /* This page contains code dealing with scratches (changing them onto
    pseudos and restoring them from the pseudos).