On 11/13/18 9:01 AM, Renlin Li wrote:
> I could verify that, your patch fixes all the ICEs I saw with 
> arm-linux-gnueabihf toolchain!
> There are some differences on the test results, because I compare the latest 
> results with something which is old.
> 
> I haven't test it on bare-metal toolchain yet. But will do to ensure all 
> related issues are fixed.

Hi Renlin,

That's excellent news!  My guess on the testsuite results changes is that
they're probably caused by the combine changes/fixes that went in around
the same time as my patches.

If you want to disable the special copy handling, which should only help
things since it gives RA more freedom, you can apply the patch I mentioned
here:

  https://gcc.gnu.org/ml/gcc-patches/2018-11/msg00379.html

which allows you to turn on and off the optimization with an option.


Jeff and Vlad,

I think with the above results, I think the patch is ready for review.
I'm attaching the latest updated patch below.

Again, this passed bootstrap and regtesting on powerpc64le-linux with
no regressions.  Ok for mainline?

Peter


gcc/
        PR rtl-optimization/87899
        * lra-lives.c (start_living): Update white space in comment.
        (enum point_type): New.
        (sparseset_contains_pseudos_p): New function.
        (update_pseudo_point): Likewise.
        (make_hard_regno_live): Use HARD_REGISTER_NUM_P macro.
        (make_hard_regno_dead): Likewise.  Remove ignore_reg_for_conflicts
        handling.  Move early exit after adding conflicts.
        (mark_pseudo_live): Use HARD_REGISTER_NUM_P macro.  Add early exit
        if regno is already live.  Remove all handling of program points.
        (mark_pseudo_dead): Use HARD_REGISTER_NUM_P macro.  Add early exit
        after adding conflicts.  Remove all handling of program points and
        ignore_reg_for_conflicts.
        (mark_regno_live): Use HARD_REGISTER_NUM_P macro.  Remove return value
        and do not guard call to mark_pseudo_live.
        (mark_regno_dead): Use HARD_REGISTER_NUM_P macro.  Remove return value
        and do not guard call to mark_pseudo_dead.
        (check_pseudos_live_through_calls): Use HARD_REGISTER_NUM_P macro.
        (process_bb_lives): Use HARD_REGISTER_NUM_P and HARD_REGISTER_P macros.
        Use new function update_pseudo_point.  Handle register copies by
        removing the source register from the live set.  Handle INOUT operands.
        Update to the next program point using the unused_set, dead_set and
        start_dying sets.
        (lra_create_live_ranges_1): Use HARD_REGISTER_NUM_P macro.

Index: gcc/lra-lives.c
===================================================================
--- gcc/lra-lives.c     (revision 265971)
+++ gcc/lra-lives.c     (working copy)
@@ -83,7 +83,7 @@ static HARD_REG_SET hard_regs_live;
 
 /* Set of pseudos and hard registers start living/dying in the current
    insn.  These sets are used to update REG_DEAD and REG_UNUSED notes
-   in the insn.         */
+   in the insn.  */
 static sparseset start_living, start_dying;
 
 /* Set of pseudos and hard regs dead and unused in the current
@@ -96,10 +96,6 @@ static bitmap_head temp_bitmap;
 /* Pool for pseudo live ranges.         */
 static object_allocator<lra_live_range> lra_live_range_pool ("live ranges");
 
-/* If non-NULL, the source operand of a register to register copy for which
-   we should not add a conflict with the copy's destination operand.  */
-static rtx ignore_reg_for_conflicts;
-
 /* Free live range list LR.  */
 static void
 free_live_range_list (lra_live_range_t lr)
@@ -224,6 +220,57 @@ lra_intersected_live_ranges_p (lra_live_
   return false;
 }
 
+enum point_type {
+  DEF_POINT,
+  USE_POINT
+};
+
+/* Return TRUE if set A contains a pseudo register, otherwise, return FALSE.  
*/
+static bool
+sparseset_contains_pseudos_p (sparseset a)
+{
+  int regno;
+  EXECUTE_IF_SET_IN_SPARSESET (a, regno)
+    if (!HARD_REGISTER_NUM_P (regno))
+      return true;
+  return false;
+}
+
+/* Mark pseudo REGNO as living or dying at program point POINT, depending on
+   whether TYPE is a definition or a use.  If this is the first reference to
+   REGNO that we've encountered, then create a new live range for it.  */
+
+static void
+update_pseudo_point (int regno, int point, enum point_type type)
+{
+  lra_live_range_t p;
+
+  /* Don't compute points for hard registers.  */
+  if (HARD_REGISTER_NUM_P (regno))
+    return;
+
+  if (complete_info_p || lra_get_regno_hard_regno (regno) < 0)
+    {
+      if (type == DEF_POINT)
+       {
+         if (sparseset_bit_p (pseudos_live, regno))
+           {
+             p = lra_reg_info[regno].live_ranges;
+             lra_assert (p != NULL);
+             p->finish = point;
+           }
+       }
+      else /* USE_POINT */
+       {
+         if (!sparseset_bit_p (pseudos_live, regno)
+             && ((p = lra_reg_info[regno].live_ranges) == NULL
+                 || (p->finish != point && p->finish + 1 != point)))
+           lra_reg_info[regno].live_ranges
+             = create_live_range (regno, point, -1, p);
+       }
+    }
+}
+
 /* The corresponding bitmaps of BB currently being processed.  */
 static bitmap bb_killed_pseudos, bb_gen_pseudos;
 
@@ -232,7 +279,7 @@ static bitmap bb_killed_pseudos, bb_gen_
 static void
 make_hard_regno_live (int regno)
 {
-  lra_assert (regno < FIRST_PSEUDO_REGISTER);
+  lra_assert (HARD_REGISTER_NUM_P (regno));
   if (TEST_HARD_REG_BIT (hard_regs_live, regno))
     return;
   SET_HARD_REG_BIT (hard_regs_live, regno);
@@ -247,19 +294,15 @@ make_hard_regno_live (int regno)
 static void
 make_hard_regno_dead (int regno)
 {
-  lra_assert (regno < FIRST_PSEUDO_REGISTER);
-  if (! TEST_HARD_REG_BIT (hard_regs_live, regno))
-    return;
-  sparseset_set_bit (start_dying, regno);
+  lra_assert (HARD_REGISTER_NUM_P (regno));
   unsigned int i;
   EXECUTE_IF_SET_IN_SPARSESET (pseudos_live, i)
-    {
-      if (ignore_reg_for_conflicts != NULL_RTX
-         && REGNO (ignore_reg_for_conflicts) == i)
-       continue;
-      SET_HARD_REG_BIT (lra_reg_info[i].conflict_hard_regs, regno);
-    }
+    SET_HARD_REG_BIT (lra_reg_info[i].conflict_hard_regs, regno);
+
+  if (! TEST_HARD_REG_BIT (hard_regs_live, regno))
+    return;
   CLEAR_HARD_REG_BIT (hard_regs_live, 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);
@@ -267,130 +310,69 @@ make_hard_regno_dead (int regno)
     }
 }
 
-/* Mark pseudo REGNO as living at program point POINT, update START_LIVING
-   and start a new live range for the pseudo corresponding to REGNO if it
-   is necessary.  */
+/* Mark pseudo REGNO as now being live and update START_LIVING.  */
 static void
-mark_pseudo_live (int regno, int point)
+mark_pseudo_live (int regno)
 {
-  lra_live_range_t p;
+  lra_assert (!HARD_REGISTER_NUM_P (regno));
+  if (sparseset_bit_p (pseudos_live, regno))
+    return;
 
-  lra_assert (regno >= FIRST_PSEUDO_REGISTER);
-  lra_assert (! sparseset_bit_p (pseudos_live, regno));
   sparseset_set_bit (pseudos_live, regno);
-
-  if ((complete_info_p || lra_get_regno_hard_regno (regno) < 0)
-      && ((p = lra_reg_info[regno].live_ranges) == NULL
-         || (p->finish != point && p->finish + 1 != point)))
-     lra_reg_info[regno].live_ranges
-       = create_live_range (regno, point, -1, p);
   sparseset_set_bit (start_living, regno);
 }
 
-/* Mark pseudo REGNO as not living at program point POINT and update
-   START_DYING.
-   This finishes the current live range for the pseudo corresponding
-   to REGNO.  */
+/* Mark pseudo REGNO as now being dead and update START_DYING.  */
 static void
-mark_pseudo_dead (int regno, int point)
+mark_pseudo_dead (int regno)
 {
-  lra_live_range_t p;
-  int ignore_regno = -1;
-  int end_regno = -1;
+  lra_assert (!HARD_REGISTER_NUM_P (regno));
+  IOR_HARD_REG_SET (lra_reg_info[regno].conflict_hard_regs, hard_regs_live);
+  if (!sparseset_bit_p (pseudos_live, regno))
+    return;
 
-  lra_assert (regno >= FIRST_PSEUDO_REGISTER);
-  lra_assert (sparseset_bit_p (pseudos_live, regno));
   sparseset_clear_bit (pseudos_live, regno);
   sparseset_set_bit (start_dying, regno);
-
-  /* Check whether any part of IGNORE_REG_FOR_CONFLICTS already conflicts
-     with REGNO.  */
-  if (ignore_reg_for_conflicts != NULL_RTX
-      && REGNO (ignore_reg_for_conflicts) < FIRST_PSEUDO_REGISTER)
-    {
-      end_regno = END_REGNO (ignore_reg_for_conflicts);
-      int src_regno = ignore_regno = REGNO (ignore_reg_for_conflicts);
-
-      while (src_regno < end_regno)
-       {
-         if (TEST_HARD_REG_BIT (lra_reg_info[regno].conflict_hard_regs,
-                                src_regno))
-           {
-             ignore_regno = end_regno = -1;
-             break;
-           }
-         src_regno++;
-       }
-    }
-
-  IOR_HARD_REG_SET (lra_reg_info[regno].conflict_hard_regs, hard_regs_live);
-
-  /* If IGNORE_REG_FOR_CONFLICTS did not already conflict with REGNO, make
-     sure it still doesn't.  */
-  for (; ignore_regno < end_regno; ignore_regno++)
-    CLEAR_HARD_REG_BIT (lra_reg_info[regno].conflict_hard_regs, ignore_regno);
-
-  if (complete_info_p || lra_get_regno_hard_regno (regno) < 0)
-    {
-      p = lra_reg_info[regno].live_ranges;
-      lra_assert (p != NULL);
-      p->finish = point;
-    }
 }
 
-/* Mark register REGNO (pseudo or hard register) in MODE as live at
-   program point POINT.  Update BB_GEN_PSEUDOS.
-   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 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)
 {
   int last;
-  bool changed = false;
 
-  if (regno < FIRST_PSEUDO_REGISTER)
+  if (HARD_REGISTER_NUM_P (regno))
     {
       for (last = end_hard_regno (mode, regno); regno < last; regno++)
        make_hard_regno_live (regno);
     }
   else
     {
-      if (! sparseset_bit_p (pseudos_live, regno))
-       {
-         mark_pseudo_live (regno, point);
-         changed = true;
-       }
+      mark_pseudo_live (regno);
       bitmap_set_bit (bb_gen_pseudos, regno);
     }
-  return changed;
 }
 
 
-/* Mark register REGNO in MODE as dead at program point POINT.  Update
-   BB_GEN_PSEUDOS and BB_KILLED_PSEUDOS.  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 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)
 {
   int last;
-  bool changed = false;
 
-  if (regno < FIRST_PSEUDO_REGISTER)
+  if (HARD_REGISTER_NUM_P (regno))
     {
       for (last = end_hard_regno (mode, regno); regno < last; regno++)
        make_hard_regno_dead (regno);
     }
   else
     {
-      if (sparseset_bit_p (pseudos_live, regno))
-       {
-         mark_pseudo_dead (regno, point);
-         changed = true;
-       }
+      mark_pseudo_dead (regno);
       bitmap_clear_bit (bb_gen_pseudos, regno);
       bitmap_set_bit (bb_killed_pseudos, regno);
     }
-  return changed;
 }
 
 
@@ -607,7 +589,7 @@ check_pseudos_live_through_calls (int re
   IOR_HARD_REG_SET (lra_reg_info[regno].conflict_hard_regs,
                    last_call_used_reg_set);
 
-  for (hr = 0; hr < FIRST_PSEUDO_REGISTER; hr++)
+  for (hr = 0; HARD_REGISTER_NUM_P (hr); hr++)
     if (targetm.hard_regno_call_part_clobbered (hr,
                                                PSEUDO_REGNO_MODE (regno)))
       add_to_hard_reg_set (&lra_reg_info[regno].conflict_hard_regs,
@@ -653,7 +635,7 @@ process_bb_lives (basic_block bb, int &c
   rtx link, *link_loc;
   bool need_curr_point_incr;
   HARD_REG_SET last_call_used_reg_set;
-  
+
   reg_live_out = df_get_live_out (bb);
   sparseset_clear (pseudos_live);
   sparseset_clear (pseudos_live_through_calls);
@@ -662,7 +644,10 @@ process_bb_lives (basic_block bb, int &c
   REG_SET_TO_HARD_REG_SET (hard_regs_live, reg_live_out);
   AND_COMPL_HARD_REG_SET (hard_regs_live, eliminable_regset);
   EXECUTE_IF_SET_IN_BITMAP (reg_live_out, FIRST_PSEUDO_REGISTER, j, bi)
-    mark_pseudo_live (j, curr_point);
+    {
+      update_pseudo_point (j, curr_point, USE_POINT);
+      mark_pseudo_live (j);
+    }
 
   bb_gen_pseudos = &get_bb_data (bb)->gen_pseudos;
   bb_killed_pseudos = &get_bb_data (bb)->killed_pseudos;
@@ -702,7 +687,7 @@ process_bb_lives (basic_block bb, int &c
       set = single_set (curr_insn);
 
       if (dead_insn_p && set != NULL_RTX
-         && REG_P (SET_DEST (set)) && REGNO (SET_DEST (set)) >= 
FIRST_PSEUDO_REGISTER
+         && REG_P (SET_DEST (set)) && !HARD_REGISTER_P (SET_DEST (set))
          && find_reg_note (curr_insn, REG_EH_REGION, NULL_RTX) == NULL_RTX
          && ! may_trap_p (PATTERN (curr_insn))
          /* Don't do premature remove of pic offset pseudo as we can
@@ -759,7 +744,7 @@ process_bb_lives (basic_block bb, int &c
          if (partial_subreg_p (lra_reg_info[regno].biggest_mode,
                                reg->biggest_mode))
            lra_reg_info[regno].biggest_mode = reg->biggest_mode;
-         if (regno < FIRST_PSEUDO_REGISTER)
+         if (HARD_REGISTER_NUM_P (regno))
            {
              lra_hard_reg_usage[regno] += freq;
              /* A hard register explicitly can be used in small mode,
@@ -775,7 +760,26 @@ process_bb_lives (basic_block bb, int &c
        }
 
       call_p = CALL_P (curr_insn);
-      ignore_reg_for_conflicts = non_conflicting_reg_copy_p (curr_insn);
+
+      /* If we have a simple register copy and the source reg is live after
+        this instruction, then remove the source reg from the live set so
+        that it will not conflict with the destination reg.  */
+      rtx ignore_reg = non_conflicting_reg_copy_p (curr_insn);
+      if (ignore_reg != NULL_RTX)
+       {
+         int ignore_regno = REGNO (ignore_reg);
+         if (HARD_REGISTER_NUM_P (ignore_regno)
+             && TEST_HARD_REG_BIT (hard_regs_live, ignore_regno))
+           CLEAR_HARD_REG_BIT (hard_regs_live, ignore_regno);
+         else if (!HARD_REGISTER_NUM_P (ignore_regno)
+                  && sparseset_bit_p (pseudos_live, ignore_regno))
+           sparseset_clear_bit (pseudos_live, ignore_regno);
+         else
+           /* We don't need any special handling of the source reg if
+              it is dead after this instruction.  */
+           ignore_reg = NULL_RTX;
+       }
+
       src_regno = (set != NULL_RTX && REG_P (SET_SRC (set))
                   ? REGNO (SET_SRC (set)) : -1);
       dst_regno = (set != NULL_RTX && REG_P (SET_DEST (set))
@@ -785,13 +789,13 @@ process_bb_lives (basic_block bb, int &c
          /* Check that source regno does not conflict with
             destination regno to exclude most impossible
             preferences.  */
-         && (((src_regno >= FIRST_PSEUDO_REGISTER
+         && (((!HARD_REGISTER_NUM_P (src_regno)
                && (! sparseset_bit_p (pseudos_live, src_regno)
-                   || (dst_regno >= FIRST_PSEUDO_REGISTER
+                   || (!HARD_REGISTER_NUM_P (dst_regno)
                        && lra_reg_val_equal_p (src_regno,
                                                lra_reg_info[dst_regno].val,
                                                
lra_reg_info[dst_regno].offset))))
-              || (src_regno < FIRST_PSEUDO_REGISTER
+              || (HARD_REGISTER_NUM_P (src_regno)
                   && ! TEST_HARD_REG_BIT (hard_regs_live, src_regno)))
              /* It might be 'inheritance pseudo <- reload pseudo'.  */
              || (src_regno >= lra_constraint_new_regno_start
@@ -816,13 +820,13 @@ process_bb_lives (basic_block bb, int &c
            }
          else if (dst_regno >= lra_constraint_new_regno_start)
            {
-             if ((hard_regno = src_regno) >= FIRST_PSEUDO_REGISTER)
+             if (!HARD_REGISTER_NUM_P (hard_regno = src_regno))
                hard_regno = reg_renumber[src_regno];
              regno = dst_regno;
            }
          else if (src_regno >= lra_constraint_new_regno_start)
            {
-             if ((hard_regno = dst_regno) >= FIRST_PSEUDO_REGISTER)
+             if (!HARD_REGISTER_NUM_P (hard_regno = dst_regno))
                hard_regno = reg_renumber[dst_regno];
              regno = src_regno;
            }
@@ -833,12 +837,6 @@ process_bb_lives (basic_block bb, int &c
 
       sparseset_clear (start_living);
 
-      /* Try to avoid unnecessary program point increments, this saves
-        a lot of time in remove_some_program_points_and_update_live_ranges.
-        We only need an increment if something becomes live or dies at this
-        program point.  */
-      need_curr_point_incr = false;
-
       /* Mark each defined value as live.  We need to do this for
         unused values because they still conflict with quantities
         that are live at the time of the definition.  */
@@ -846,14 +844,13 @@ process_bb_lives (basic_block bb, int &c
        {
          if (reg->type != OP_IN)
            {
-             need_curr_point_incr
-               |= mark_regno_live (reg->regno, reg->biggest_mode,
-                                   curr_point);
+             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_used_reg_set);
            }
 
-         if (reg->regno >= FIRST_PSEUDO_REGISTER)
+         if (!HARD_REGISTER_NUM_P (reg->regno))
            for (hr = curr_static_id->hard_regs; hr != NULL; hr = hr->next)
              if (hr->clobber_high
                  && maybe_gt (GET_MODE_SIZE (PSEUDO_REGNO_MODE (reg->regno)),
@@ -868,7 +865,7 @@ process_bb_lives (basic_block bb, int &c
 
       if (curr_id->arg_hard_regs != NULL)
        for (i = 0; (regno = curr_id->arg_hard_regs[i]) >= 0; i++)
-         if (regno >= FIRST_PSEUDO_REGISTER)
+         if (!HARD_REGISTER_NUM_P (regno))
            /* It is a clobber.  */
            make_hard_regno_live (regno - FIRST_PSEUDO_REGISTER);
 
@@ -878,20 +875,22 @@ process_bb_lives (basic_block bb, int &c
 
       /* See which defined values die here.  */
       for (reg = curr_id->regs; reg != NULL; reg = reg->next)
-       if (reg->type == OP_OUT
+       if (reg->type != OP_IN
            && ! reg_early_clobber_p (reg, n_alt) && ! reg->subreg_p)
-         need_curr_point_incr
-           |= mark_regno_dead (reg->regno, reg->biggest_mode,
-                               curr_point);
+         {
+           if (reg->type == OP_OUT)
+             update_pseudo_point (reg->regno, curr_point, DEF_POINT);
+           mark_regno_dead (reg->regno, reg->biggest_mode);
+         }
 
       for (reg = curr_static_id->hard_regs; reg != NULL; reg = reg->next)
-       if (reg->type == OP_OUT
+       if (reg->type != OP_IN
            && ! reg_early_clobber_p (reg, n_alt) && ! reg->subreg_p)
          make_hard_regno_dead (reg->regno);
 
       if (curr_id->arg_hard_regs != NULL)
        for (i = 0; (regno = curr_id->arg_hard_regs[i]) >= 0; i++)
-         if (regno >= FIRST_PSEUDO_REGISTER)
+         if (!HARD_REGISTER_NUM_P (regno))
            /* It is a clobber.  */
            make_hard_regno_dead (regno - FIRST_PSEUDO_REGISTER);
 
@@ -931,50 +930,70 @@ process_bb_lives (basic_block bb, int &c
        }
 
       /* Increment the current program point if we must.  */
-      if (need_curr_point_incr)
+      if (sparseset_contains_pseudos_p (unused_set)
+         || sparseset_contains_pseudos_p (start_dying))
        next_program_point (curr_point, freq);
 
-      sparseset_clear (start_living);
+      /* If we removed the source reg from a simple register copy from the
+        live set above, then add it back now so we don't accidentally add
+        it to the start_living set below.  */
+      if (ignore_reg != NULL_RTX)
+       {
+         int ignore_regno = REGNO (ignore_reg);
+         if (HARD_REGISTER_NUM_P (ignore_regno))
+           SET_HARD_REG_BIT (hard_regs_live, ignore_regno);
+         else
+           sparseset_set_bit (pseudos_live, ignore_regno);
+       }
 
-      need_curr_point_incr = false;
+      sparseset_clear (start_living);
 
       /* Mark each used value as live. */
       for (reg = curr_id->regs; reg != NULL; reg = reg->next)
-       if (reg->type == OP_IN)
+       if (reg->type != OP_OUT)
          {
-           need_curr_point_incr
-             |= mark_regno_live (reg->regno, reg->biggest_mode,
-                                 curr_point);
+           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_used_reg_set);
          }
 
       for (reg = curr_static_id->hard_regs; reg != NULL; reg = reg->next)
-       if (reg->type == OP_IN)
+       if (reg->type != OP_OUT)
          make_hard_regno_live (reg->regno);
 
       if (curr_id->arg_hard_regs != NULL)
        /* Make argument hard registers live.  */
        for (i = 0; (regno = curr_id->arg_hard_regs[i]) >= 0; i++)
-         if (regno < FIRST_PSEUDO_REGISTER)
+         if (HARD_REGISTER_NUM_P (regno))
            make_hard_regno_live (regno);
 
       sparseset_and_compl (dead_set, start_living, start_dying);
 
+      sparseset_clear (start_dying);
+
       /* Mark early clobber outputs dead.  */
       for (reg = curr_id->regs; reg != NULL; reg = reg->next)
-       if (reg->type == OP_OUT
+       if (reg->type != OP_IN
            && reg_early_clobber_p (reg, n_alt) && ! reg->subreg_p)
-         need_curr_point_incr
-           |= mark_regno_dead (reg->regno, reg->biggest_mode,
-                               curr_point);
+         {
+           if (reg->type == OP_OUT)
+             update_pseudo_point (reg->regno, curr_point, DEF_POINT);
+           mark_regno_dead (reg->regno, reg->biggest_mode);
+
+           /* 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);
+         }
 
       for (reg = curr_static_id->hard_regs; reg != NULL; reg = reg->next)
-       if (reg->type == OP_OUT
+       if (reg->type != OP_IN
            && reg_early_clobber_p (reg, n_alt) && ! reg->subreg_p)
          {
            struct lra_insn_reg *reg2;
-           
+
            /* We can have early clobbered non-operand hard reg and
               the same hard reg as an insn input.  Don't make hard
               reg dead before the insns.  */
@@ -985,7 +1004,9 @@ process_bb_lives (basic_block bb, int &c
              make_hard_regno_dead (reg->regno);
          }
 
-      if (need_curr_point_incr)
+      /* Increment the current program point if we must.  */
+      if (sparseset_contains_pseudos_p (dead_set)
+         || sparseset_contains_pseudos_p (start_dying))
        next_program_point (curr_point, freq);
 
       /* Update notes. */
@@ -1017,7 +1038,6 @@ process_bb_lives (basic_block bb, int &c
       EXECUTE_IF_SET_IN_SPARSESET (unused_set, j)
        add_reg_note (curr_insn, REG_UNUSED, regno_reg_rtx[j]);
     }
-  ignore_reg_for_conflicts = NULL_RTX;
 
   if (bb_has_eh_pred (bb))
     for (j = 0; ; ++j)
@@ -1047,7 +1067,7 @@ process_bb_lives (basic_block bb, int &c
         allocate such regs in this case.  */
       if (!cfun->has_nonlocal_label
          && has_abnormal_call_or_eh_pred_edge_p (bb))
-       for (px = 0; px < FIRST_PSEUDO_REGISTER; px++)
+       for (px = 0; HARD_REGISTER_NUM_P (px); px++)
          if (call_used_regs[px]
 #ifdef REAL_PIC_OFFSET_TABLE_REGNUM
              /* We should create a conflict of PIC pseudo with PIC
@@ -1057,7 +1077,7 @@ process_bb_lives (basic_block bb, int &c
                 pseudo will also have a wrong value.  */
              || (px == REAL_PIC_OFFSET_TABLE_REGNUM
                  && pic_offset_table_rtx != NULL_RTX
-                 && REGNO (pic_offset_table_rtx) >= FIRST_PSEUDO_REGISTER)
+                 && !HARD_REGISTER_P (pic_offset_table_rtx))
 #endif
              )
            make_hard_regno_live (px);
@@ -1095,7 +1115,10 @@ process_bb_lives (basic_block bb, int &c
   need_curr_point_incr = (sparseset_cardinality (pseudos_live) > 0);
 
   EXECUTE_IF_SET_IN_SPARSESET (pseudos_live, i)
-    mark_pseudo_dead (i, curr_point);
+    {
+      update_pseudo_point (i, curr_point, DEF_POINT);
+      mark_pseudo_dead (i);
+    }
 
   EXECUTE_IF_SET_IN_BITMAP (df_get_live_in (bb), FIRST_PSEUDO_REGISTER, j, bi)
     {
@@ -1105,7 +1128,7 @@ process_bb_lives (basic_block bb, int &c
        check_pseudos_live_through_calls (j, last_call_used_reg_set);
     }
 
-  for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
+  for (i = 0; HARD_REGISTER_NUM_P (i); ++i)
     {
       if (!TEST_HARD_REG_BIT (hard_regs_live, i))
        continue;
@@ -1332,12 +1355,12 @@ lra_create_live_ranges_1 (bool all_p, bo
         conservative because of recent transformation.  Here in this
         file we recalculate it again as it costs practically
         nothing.  */
-      if (i >= FIRST_PSEUDO_REGISTER && regno_reg_rtx[i] != NULL_RTX)
+      if (!HARD_REGISTER_NUM_P (i) && regno_reg_rtx[i] != NULL_RTX)
        lra_reg_info[i].biggest_mode = GET_MODE (regno_reg_rtx[i]);
       else
        lra_reg_info[i].biggest_mode = VOIDmode;
       lra_reg_info[i].call_p = false;
-      if (i >= FIRST_PSEUDO_REGISTER
+      if (!HARD_REGISTER_NUM_P (i)
          && lra_reg_info[i].nrefs != 0)
        {
          if ((hard_regno = reg_renumber[i]) >= 0)
@@ -1394,7 +1417,7 @@ lra_create_live_ranges_1 (bool all_p, bo
        }
       /* As we did not change CFG since LRA start we can use
         DF-infrastructure solver to solve live data flow problem.  */
-      for (int i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
+      for (int i = 0; HARD_REGISTER_NUM_P (i); ++i)
        {
          if (TEST_HARD_REG_BIT (hard_regs_spilled_into, i))
            bitmap_clear_bit (&all_hard_regs_bitmap, i);

Reply via email to