Patchwork patch to fix PR56148

login
register
mail settings
Submitter Vladimir Makarov
Date Feb. 12, 2013, 5:36 p.m.
Message ID <511A7DA2.1050504@redhat.com>
Download mbox | patch
Permalink /patch/219925/
State New
Headers show

Comments

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

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