diff mbox series

[committed] IRA: Process digital constraints containing more one digit

Message ID 04fb3dd3-6326-b0de-857c-7ace281a0034@redhat.com
State New
Headers show
Series [committed] IRA: Process digital constraints containing more one digit | expand

Commit Message

Vladimir Makarov March 9, 2021, 10:30 p.m. UTC
While working on PR99454 I found that IR incorrectly processes 
constraints starting with '0'..'9' and containing more one digit. It is 
probably a rare event and it does not result in wrong code generation.  
Simply, the generated code will be more efficient.

In any case the following patch fixes this pitfall.  The patch was 
successfully bootstrapped and tested on x86-64.
commit 63d74fed4566f1de583c368ecb9e2fc423fb1c87 (HEAD -> master)
Author: Vladimir N. Makarov <vmakarov@redhat.com>
Date:   Tue Mar 9 17:18:58 2021 -0500

    IRA: Process digital constraints containing more one digit
    
    gcc/ChangeLog:
    
            * ira.c (ira_setup_alts, ira_get_dup_out_num): Process digital
            constraints > 9.
            * ira-lives.c (single_reg_class): Ditto.
diff mbox series

Patch

diff --git a/gcc/ira-lives.c b/gcc/ira-lives.c
index f63da79a78e..f3341313bd1 100644
--- a/gcc/ira-lives.c
+++ b/gcc/ira-lives.c
@@ -855,53 +855,61 @@  single_reg_class (const char *constraints, rtx op, rtx equiv_const)
 
   cl = NO_REGS;
   alternative_mask preferred = preferred_alternatives;
-  for (; (c = *constraints); constraints += CONSTRAINT_LEN (c, constraints))
-    if (c == '#')
-      preferred &= ~ALTERNATIVE_BIT (0);
-    else if (c == ',')
-      preferred >>= 1;
-    else if (preferred & 1)
-      switch (c)
-	{
-	case 'g':
-	  return NO_REGS;
-
-	default:
-	  /* ??? Is this the best way to handle memory constraints?  */
-	  cn = lookup_constraint (constraints);
-	  if (insn_extra_memory_constraint (cn)
-	      || insn_extra_special_memory_constraint (cn)
-	      || insn_extra_address_constraint (cn))
-	    return NO_REGS;
-	  if (constraint_satisfied_p (op, cn)
-	      || (equiv_const != NULL_RTX
-		  && CONSTANT_P (equiv_const)
-		  && constraint_satisfied_p (equiv_const, cn)))
+  while ((c = *constraints))
+    {
+      if (c == '#')
+	preferred &= ~ALTERNATIVE_BIT (0);
+      else if (c == ',')
+	preferred >>= 1;
+      else if (preferred & 1)
+	switch (c)
+	  {
+	  case 'g':
 	    return NO_REGS;
-	  next_cl = reg_class_for_constraint (cn);
-	  if (next_cl == NO_REGS)
+	    
+	  default:
+	    /* ??? Is this the best way to handle memory constraints?  */
+	    cn = lookup_constraint (constraints);
+	    if (insn_extra_memory_constraint (cn)
+		|| insn_extra_special_memory_constraint (cn)
+		|| insn_extra_address_constraint (cn))
+	      return NO_REGS;
+	    if (constraint_satisfied_p (op, cn)
+		|| (equiv_const != NULL_RTX
+		    && CONSTANT_P (equiv_const)
+		    && constraint_satisfied_p (equiv_const, cn)))
+	      return NO_REGS;
+	    next_cl = reg_class_for_constraint (cn);
+	    if (next_cl == NO_REGS)
+	      break;
+	    if (cl == NO_REGS
+		? ira_class_singleton[next_cl][GET_MODE (op)] < 0
+		: (ira_class_singleton[cl][GET_MODE (op)]
+		   != ira_class_singleton[next_cl][GET_MODE (op)]))
+	      return NO_REGS;
+	    cl = next_cl;
 	    break;
-	  if (cl == NO_REGS
-	      ? ira_class_singleton[next_cl][GET_MODE (op)] < 0
-	      : (ira_class_singleton[cl][GET_MODE (op)]
-		 != ira_class_singleton[next_cl][GET_MODE (op)]))
-	    return NO_REGS;
-	  cl = next_cl;
-	  break;
-
-	case '0': case '1': case '2': case '3': case '4':
-	case '5': case '6': case '7': case '8': case '9':
-	  next_cl
-	    = single_reg_class (recog_data.constraints[c - '0'],
-				recog_data.operand[c - '0'], NULL_RTX);
-	  if (cl == NO_REGS
-	      ? ira_class_singleton[next_cl][GET_MODE (op)] < 0
-	      : (ira_class_singleton[cl][GET_MODE (op)]
-		 != ira_class_singleton[next_cl][GET_MODE (op)]))
-	    return NO_REGS;
-	  cl = next_cl;
-	  break;
-	}
+	    
+	  case '0': case '1': case '2': case '3': case '4':
+	  case '5': case '6': case '7': case '8': case '9':
+	    {
+	      char *end;
+	      unsigned long dup = strtoul (constraints, &end, 10);
+	      constraints = end;
+	      next_cl
+		= single_reg_class (recog_data.constraints[dup],
+				    recog_data.operand[dup], NULL_RTX);
+	      if (cl == NO_REGS
+		  ? ira_class_singleton[next_cl][GET_MODE (op)] < 0
+		  : (ira_class_singleton[cl][GET_MODE (op)]
+		     != ira_class_singleton[next_cl][GET_MODE (op)]))
+		return NO_REGS;
+	      cl = next_cl;
+	      continue;
+	    }
+	  }
+      constraints += CONSTRAINT_LEN (c, constraints);
+   }
   return cl;
 }
 
diff --git a/gcc/ira.c b/gcc/ira.c
index c32ecf814fd..fc77131491d 100644
--- a/gcc/ira.c
+++ b/gcc/ira.c
@@ -1829,7 +1829,10 @@  ira_setup_alts (rtx_insn *insn)
 		  case '0':  case '1':  case '2':  case '3':  case '4':
 		  case '5':  case '6':  case '7':  case '8':  case '9':
 		    {
-		      rtx other = recog_data.operand[c - '0'];
+		      char *end;
+		      unsigned long dup = strtoul (p, &end, 10);
+		      rtx other = recog_data.operand[dup];
+		      len = end - p;
 		      if (MEM_P (other)
 			  ? rtx_equal_p (other, op)
 			  : REG_P (op) || SUBREG_P (op))
@@ -1922,7 +1925,7 @@  ira_setup_alts (rtx_insn *insn)
 int
 ira_get_dup_out_num (int op_num, alternative_mask alts)
 {
-  int curr_alt, c, original, dup;
+  int curr_alt, c, original;
   bool ignore_p, use_commut_op_p;
   const char *str;
 
@@ -1969,18 +1972,22 @@  ira_get_dup_out_num (int op_num, alternative_mask alts)
 		
 	      case '0': case '1': case '2': case '3': case '4':
 	      case '5': case '6': case '7': case '8': case '9':
-		if (original != -1 && original != c)
-		  goto fail;
-		original = c;
-		break;
+		{
+		  char *end;
+		  int n = (int) strtoul (str, &end, 10);
+		  str = end;
+		  if (original != -1 && original != n)
+		    goto fail;
+		  original = n;
+		  continue;
+		}
 	      }
 	  str += CONSTRAINT_LEN (c, str);
 	}
       if (original == -1)
 	goto fail;
-      dup = original - '0';
-      if (recog_data.operand_type[dup] == OP_OUT)
-	return dup;
+      if (recog_data.operand_type[original] == OP_OUT)
+	return original;
     fail:
       if (use_commut_op_p)
 	break;