diff mbox

patch to fix PR56148

Message ID 511A7DA2.1050504@redhat.com
State New
Headers show

Commit Message

Vladimir Makarov Feb. 12, 2013, 5:36 p.m. UTC
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  <vmakarov@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  <vmakarov@redhat.com>

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

Patch

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));
+}