Patchwork [lra] patch to fix a bug

login
register
mail settings
Submitter Vladimir Makarov
Date Oct. 6, 2012, 2:52 a.m.
Message ID <506F9CE9.4090108@redhat.com>
Download mbox | patch
Permalink /patch/189661/
State New
Headers show

Comments

Vladimir Makarov - Oct. 6, 2012, 2:52 a.m.
The following patch fixes a bug found on x86-64 in a big program with 
some options combination.

   The patch was successfully bootstrapped on x86/x86-64. The patch 
changes the code for about 30% of SPEC2000 tests.  But these changes are 
quite small (in code size and performance point of view).

   The patch is committed as rev. 192153.

2012-10-05  Vladimir Makarov  <vmakarov@redhat.com>

         * lra-constraints.c (multi_block_pseudo_p, dead_pseudo_p): New
         functions.
         (insn_rhs_dead_pseudo_p, init_insn_rhs_dead_pseudo_p): Ditto.
         (lra_constraints): Use them.

Patch

Index: lra-constraints.c
===================================================================
--- lra-constraints.c	(revision 192048)
+++ lra-constraints.c	(working copy)
@@ -3590,6 +3590,83 @@  int lra_constraint_iter_after_spill;
    pseudo.  */
 bool lra_risky_transformations_p;
 
+/* Return true if REGNO is referenced in more than one block.  */
+static bool
+multi_block_pseudo_p (int regno)
+{
+  basic_block bb = NULL;
+  unsigned int uid;
+  bitmap_iterator bi;
+  
+  if (regno < FIRST_PSEUDO_REGISTER)
+    return false;
+  
+    EXECUTE_IF_SET_IN_BITMAP (&lra_reg_info[regno].insn_bitmap, 0, uid, bi)
+      if (bb == NULL)
+	bb = BLOCK_FOR_INSN (lra_insn_recog_data[uid]->insn);
+      else if (BLOCK_FOR_INSN (lra_insn_recog_data[uid]->insn) != bb)
+	return true;
+    return false;
+}
+
+/* Return true if X contains a pseudo dying in INSN.  */
+static bool
+dead_pseudo_p (rtx x, rtx insn)
+{
+  int i, j;
+  const char *fmt;
+  enum rtx_code code;
+
+  if (REG_P (x))
+    return (insn != NULL_RTX
+	    && find_regno_note (insn, REG_DEAD, REGNO (x)) != NULL_RTX);
+  code = GET_CODE (x);
+  fmt = GET_RTX_FORMAT (code);
+  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+    {
+      if (fmt[i] == 'e')
+	{
+	  if (dead_pseudo_p (XEXP (x, i), insn))
+	    return true;
+	}
+      else if (fmt[i] == 'E')
+	{
+	  for (j = XVECLEN (x, i) - 1; j >= 0; j--)
+	    if (dead_pseudo_p (XVECEXP (x, i, j), insn))
+	      return true;
+	}
+    }
+  return false;
+}
+
+/* Return true if INSN contains a dying pseudo in INSN right hand
+   side.  */
+static bool
+insn_rhs_dead_pseudo_p (rtx insn)
+{
+  rtx set = single_set (insn);
+
+  gcc_assert (set != NULL);
+  return dead_pseudo_p (SET_SRC (set), insn);
+}
+
+/* Return true if any init insn of REGNO contains a dying pseudo in
+   insn right hand side.  */
+static bool
+init_insn_rhs_dead_pseudo_p (int regno)
+{
+  rtx insns = ira_reg_equiv[regno].init_insns;
+
+  if (insns == NULL)
+    return false;
+  if (INSN_P (insns))
+    return insn_rhs_dead_pseudo_p (insns);
+  for (; insns != NULL_RTX; insns = XEXP (insns, 1))
+    if (insn_rhs_dead_pseudo_p (XEXP (insns, 0)))
+      return true;
+  return false;
+}
+
 /* Entry function of LRA constraint pass.  Return true if the
    constraint pass did change the code.	 */
 bool
@@ -3628,7 +3705,22 @@  lra_constraints (bool first_p)
 	  }
 	else if ((x = get_equiv_substitution (regno_reg_rtx[i])) != NULL_RTX)
 	  {
-	    if (! first_p && contains_reg_p (x, false, false))
+	    bool pseudo_p = contains_reg_p (x, false, false);
+
+	    /* We don't use DF for compilation speed sake.  So it is
+	       problematic to update live info when we use an
+	       equivalence containing pseudos in more than one BB.  */
+	    if ((pseudo_p && multi_block_pseudo_p (i))
+		/* We check that a pseudo in rhs of the init insn is
+		   not dying in the insn.  Otherwise, the live info
+		   at the beginning of the corresponding BB might be
+		   wrong after we removed the insn.  When the equiv can
+		   be a constant, the right hand side of the init insn
+		   can be a pseudo.  */
+		|| (ira_reg_equiv[i].memory == NULL_RTX
+		    && init_insn_rhs_dead_pseudo_p (i)))
+	      ira_reg_equiv[i].defined_p = false;
+	    else if (! first_p && pseudo_p)
 	      /* After RTL transformation, we can not guarantee that
 		 pseudo in the substitution was not reloaded which
 		 might make equivalence invalid.  For example, in