]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR middle-end/87899 (r264897 cause mis-compiled native arm-linux-gnueabihf toolchain)
authorPeter Bergner <bergner@linux.ibm.com>
Tue, 13 Nov 2018 22:14:11 +0000 (22:14 +0000)
committerPeter Bergner <bergner@gcc.gnu.org>
Tue, 13 Nov 2018 22:14:11 +0000 (16:14 -0600)
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.

From-SVN: r266086

gcc/ChangeLog
gcc/lra-lives.c

index 9f474bb00750c356ba0b4ea122b937ab96540340..da5a5382f5677d3a016af8a8c8d6f48a383dbf98 100644 (file)
@@ -1,3 +1,30 @@
+2018-11-13  Peter Bergner  <bergner@linux.ibm.com>
+
+       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.
+
 2018-11-13  David Malcolm  <dmalcolm@redhat.com>
 
        * builtins.c: Replace "source_location" with "location_t".
index 0bf8cd06a302c8a6fcb914b94f953cdaa86597a2..da47692c9041601c03eedbcd93a1881b7e51b0af 100644 (file)
@@ -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_range_t r1, lra_live_range_t r2)
   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_pseudos;
 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;
 }
 
 \f
@@ -607,7 +589,7 @@ check_pseudos_live_through_calls (int regno,
   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 &curr_point, bool dead_insn_p)
   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 &curr_point, bool dead_insn_p)
   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 &curr_point, bool dead_insn_p)
       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 &curr_point, bool dead_insn_p)
          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 &curr_point, bool dead_insn_p)
        }
 
       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 &curr_point, bool dead_insn_p)
          /* 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 &curr_point, bool dead_insn_p)
            }
          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 &curr_point, bool dead_insn_p)
 
       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 &curr_point, bool dead_insn_p)
        {
          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 &curr_point, bool dead_insn_p)
 
       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 &curr_point, bool dead_insn_p)
 
       /* 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 &curr_point, bool dead_insn_p)
        }
 
       /* 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 &curr_point, bool dead_insn_p)
              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 &curr_point, bool dead_insn_p)
       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 &curr_point, bool dead_insn_p)
         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 &curr_point, bool dead_insn_p)
                 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 &curr_point, bool dead_insn_p)
   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 &curr_point, bool dead_insn_p)
        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, bool dead_insn_p)
         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, bool dead_insn_p)
        }
       /* 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);