The following patch fixes

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56148

The patch was successfully bootstrapped and tested on x86/x86-64.

Committed as rev.195998.

2013-02-12  Vladimir Makarov  <vmaka...@redhat.com>

        PR inline-asm/56148
        * lra-constraints.c (process_alt_operands): Match early clobber
        operand with itself.  Check conflicts with earlyclobber only if
        the operand is not reloaded.  Prefer to reload conflicting operand
        if earlyclobber and matching operands are the same.

2013-02-12  Vladimir Makarov  <vmaka...@redhat.com>

        PR inline-asm/56148
        * gcc.target/i386/pr56148.c: New test.

Index: lra-constraints.c
===================================================================
--- lra-constraints.c	(revision 195902)
+++ lra-constraints.c	(working copy)
@@ -1533,8 +1533,8 @@ process_alt_operands (int only_alternati
 			if (! curr_static_id->operand[m].early_clobber
 			    || operand_reg[nop] == NULL_RTX
 			    || (find_regno_note (curr_insn, REG_DEAD,
-						 REGNO (operand_reg[nop]))
-						 != NULL_RTX))
+						 REGNO (op))
+				|| REGNO (op) == REGNO (operand_reg[m])))
 			  match_p = true;
 		      }
 		    if (match_p)
@@ -2059,6 +2059,7 @@ process_alt_operands (int only_alternati
 	  if ((! curr_alt_win[i] && ! curr_alt_match_win[i])
 	      || hard_regno[i] < 0)
 	    continue;
+	  lra_assert (operand_reg[i] != NULL_RTX);
 	  clobbered_hard_regno = hard_regno[i];
 	  CLEAR_HARD_REG_SET (temp_set);
 	  add_to_hard_reg_set (&temp_set, biggest_mode[i], clobbered_hard_regno);
@@ -2073,30 +2074,49 @@ process_alt_operands (int only_alternati
 	    else if ((curr_alt_matches[j] == i && curr_alt_match_win[j])
 		     || (curr_alt_matches[i] == j && curr_alt_match_win[i]))
 	      continue;
-	    else if (uses_hard_regs_p (*curr_id->operand_loc[j], temp_set))
+	    /* If we don't reload j-th operand, check conflicts.  */
+	    else if ((curr_alt_win[j] || curr_alt_match_win[j])
+		     && uses_hard_regs_p (*curr_id->operand_loc[j], temp_set))
 	      break;
 	  if (j >= n_operands)
 	    continue;
-	  /* We need to reload early clobbered register.  */
-	  for (j = 0; j < n_operands; j++)
-	    if (curr_alt_matches[j] == i)
-	      {
-		curr_alt_match_win[j] = false;
-		losers++;
-		overall += LRA_LOSER_COST_FACTOR;
-	      }
-	  if (! curr_alt_match_win[i])
-	    curr_alt_dont_inherit_ops[curr_alt_dont_inherit_ops_num++] = i;
+	  /* If earlyclobber operand conflicts with another
+	     non-matching operand which is actually the same register
+	     as the earlyclobber operand, it is better to reload the
+	     another operand as an operand matching the earlyclobber
+	     operand can be also the same.  */
+	  if (operand_reg[j] != NULL_RTX && ! curr_alt_match_win[j]
+	      && REGNO (operand_reg[i]) == REGNO (operand_reg[j]))
+	    {
+	      curr_alt_win[j] = false;
+	      curr_alt_dont_inherit_ops[curr_alt_dont_inherit_ops_num++] = j;
+	      losers++;
+	      overall += LRA_LOSER_COST_FACTOR;
+	    }
 	  else
 	    {
-	      /* Remember pseudos used for match reloads are never
-		 inherited.  */
-	      lra_assert (curr_alt_matches[i] >= 0);
-	      curr_alt_win[curr_alt_matches[i]] = false;
+	      /* We need to reload early clobbered register and the
+		 matched registers.  */
+	      for (j = 0; j < n_operands; j++)
+		if (curr_alt_matches[j] == i)
+		  {
+		    curr_alt_match_win[j] = false;
+		    losers++;
+		    overall += LRA_LOSER_COST_FACTOR;
+		  }
+	      if (! curr_alt_match_win[i])
+		curr_alt_dont_inherit_ops[curr_alt_dont_inherit_ops_num++] = i;
+	      else
+		{
+		  /* Remember pseudos used for match reloads are never
+		     inherited.  */
+		  lra_assert (curr_alt_matches[i] >= 0);
+		  curr_alt_win[curr_alt_matches[i]] = false;
+		}
+	      curr_alt_win[i] = curr_alt_match_win[i] = false;
+	      losers++;
+	      overall += LRA_LOSER_COST_FACTOR;
 	    }
-	  curr_alt_win[i] = curr_alt_match_win[i] = false;
-	  losers++;
-	  overall += LRA_LOSER_COST_FACTOR;
 	}
       small_class_operands_num = 0;
       for (nop = 0; nop < n_operands; nop++)
Index: testsuite/gcc.target/i386/pr56148.c
===================================================================
--- testsuite/gcc.target/i386/pr56148.c	(revision 0)
+++ testsuite/gcc.target/i386/pr56148.c	(working copy)
@@ -0,0 +1,12 @@
+/* PR inline-asm/56148 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+void
+foo (void)
+{
+  unsigned char e[16];
+  unsigned long a, b, c, d;
+  __asm__ __volatile__ ("" : "=d" (a), "=&c" (c), "=&D" (d), "=&a" (b)
+               : "0" (-1U), "mr" (e), "1" (128 >> 5), "2" (e), "3" (-1U));
+}

Reply via email to