public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH][LRA] Fix PR87899: r264897 cause mis-compiled native arm-linux-gnueabihf toolchain
@ 2018-11-12  4:34 Peter Bergner
  2018-11-12 12:26 ` Renlin Li
  0 siblings, 1 reply; 10+ messages in thread
From: Peter Bergner @ 2018-11-12  4:34 UTC (permalink / raw)
  To: Renlin Li, Jeff Law, Vladimir N Makarov
  Cc: GCC Patches, Christophe Lyon, Ramana Radhakrishnan,
	Kyrylo Tkachov, Wilco Dijkstra

Renlin, Jeff and Vlad: requests and questions for you below...

PR87899 shows another latent LRA bug exposed by my r264897 commit.
In the bugzilla report, we have the following rtl in LRA:

  (insn 1 (set (reg:SI 1 r1) (reg/f:SI 2040)))
...
  (insn 2 (set (mem/f/c:SI (pre_modify:SI (reg:SI 1 r1)
                                          (plus:SI (reg:SI 1 r1)
                                                   (const_int 12))))
               (reg:SI 1048))
          (expr_list:REG_INC (reg:SI 1 r1)))
...
  <another use of pseudo 2040>

My earlier patch now sees the reg copy in insn "1" and correctly skips
adding a conflict between r1 and r2040 due to the copy.  However, insn "2"
updates r1 and r2040 is live across that update and so we should create
a conflict between them, but we currently do not and that leads to us
assigning r1 to one of r2040's reload pseudos which gets clobbered by
the r1 update in insn "2".

The reason a conflict was never added between r1 and r2040 is that LRA
skips INOUT operands when computing conflicts and so misses the definition
of r1 in insn "2" and so never adds conflicts for it.  The reason the code
skips the INOUT operands is that LRA doesn't want to create new program
points for INOUT operands, since unnecessary program points can slow down
remove_some_program_points_and_update_live_ranges.  This was all fine
before when we had conservative conflict info, but now we cannot ignore
INOUT operands.

The heart of the problem is that the {make,mark}_*_{live,dead} routines
update the liveness, conflict and program point information for operands.
My solution to the problem was to pull out the updating of the program point
info from {make,mark}_*_{live,dead} and have them only update liveness and
conflict information.  I then created a separate function that is used for
updating an operand's program points.  This allowed me to modify the insn
operand scanning to handle all operand types (IN, OUT and INOUT) and always
call the {make,mark}_*_{live,dead} functions for all operand types, while
only calling the new program point update function for IN and OUT operands.

This change then allowed me to remove the hacky handling of conflicts for
reg copies and instead use the more common method of removing the src reg
of a copy from the live set before handling the copy's definition, thereby
skipping the unwanted conflict.  Bonus! :-)

This passes bootstrap and regtesting on powerpc64le-linux with no regressions.

Renlin, can you please verify that this patch fixes the issue you ran into?

Jeff, could you please throw this on your test builders to see whether
it exposes any problems with the patch I didn't see?

Otherwise, Vlad and Jeff, what do you think of this solution?

I'll note that I have compiled quite a few largish test cases and so far
I am seeing the same exact program points being used in the LRA rtl dump
before and after my patch.  I'm continuing to do that with more tests
to make sure I have everything working correctly.

I'll also note I took the opportunity to convert lra-lives.c over to using
the HARD_REGISTER_P and HARD_REGISTER_NUM_P convenience macros.

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;
 }
 
 \f
@@ -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,63 @@ 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);
 
-      need_curr_point_incr = false;
-
       /* 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);
 
+      /* If we removed the source reg from a simple register copy from the
+	 live set, then it will appear to be dead, but it really isn't.  */
+      if (ignore_reg != NULL_RTX)
+	sparseset_clear_bit (dead_set, REGNO (ignore_reg));
+
+      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 +997,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 +1031,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 +1060,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 +1070,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 +1108,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 +1121,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 +1348,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 +1410,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);

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2018-11-14  8:27 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-11-12  4:34 [PATCH][LRA] Fix PR87899: r264897 cause mis-compiled native arm-linux-gnueabihf toolchain Peter Bergner
2018-11-12 12:26 ` Renlin Li
2018-11-12 15:33   ` Peter Bergner
2018-11-12 16:26     ` Renlin Li
2018-11-12 20:25   ` Peter Bergner
2018-11-13 15:01     ` Renlin Li
2018-11-13 15:53       ` Peter Bergner
2018-11-13 22:09         ` Vladimir Makarov
2018-11-13 22:18           ` Peter Bergner
2018-11-14  8:27             ` Christophe Lyon

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).