This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: alpha himode reload problem


On Wed, Oct 22, 1997 at 07:01:01PM -0700, Jim Wilson wrote:
> Another way to fix this is to modify expand_asm_operands to fix the MEM
> during RTL generation.  This seems more elegant.

Comments on the following?  The recog.c changes were necesary to 
get combine not to undo our hard work in stmt.c.


r~
Sun Oct 26 15:51:49 1997  Richard Henderson  <rth@cygnus.com>

	* recog.c (check_asm_operands): Don't allow combinations that reload
	will simply have to undo later.
	* stmt.c (study_asm_constraint): New function.
	(expand_asm_operands): Use it.  Force mem operand to reg if constraint
	doesn't allow memory.
	* tree.h: Prototype expand_asm_operands and study_asm_constraint.


Index: recog.c
===================================================================
RCS file: /cvs/cvsfiles/egcs/gcc/recog.c,v
retrieving revision 1.1.1.1
diff -u -p -r1.1.1.1 recog.c
--- recog.c	1997/08/11 15:57:12	1.1.1.1
+++ recog.c	1997/10/26 23:44:52
@@ -31,6 +31,7 @@ Boston, MA 02111-1307, USA.  */
 #include "hard-reg-set.h"
 #include "flags.h"
 #include "real.h"
+#include "tree.h"
 
 #ifndef STACK_PUSH_CODE
 #ifdef STACK_GROWS_DOWNWARD
@@ -110,6 +111,7 @@ check_asm_operands (x)
 {
   int noperands = asm_noperands (x);
   rtx *operands;
+  char **constraints;
   int i;
 
   if (noperands < 0)
@@ -118,11 +120,40 @@ check_asm_operands (x)
     return 1;
 
   operands = (rtx *) alloca (noperands * sizeof (rtx));
-  decode_asm_operands (x, operands, NULL_PTR, NULL_PTR, NULL_PTR);
+  constraints = (char **) alloca (noperands * sizeof (char *));
+  decode_asm_operands (x, operands, NULL_PTR, constraints, NULL_PTR);
 
   for (i = 0; i < noperands; i++)
     if (!general_operand (operands[i], VOIDmode))
       return 0;
+
+  /* Prevent problems for reload by making sure mem and reg inputs stay
+     mem or reg inputs.  */
+  for (i = noperands - ASM_OPERANDS_INPUT_LENGTH (x); i < noperands; ++i)
+    {
+      struct asm_constraint_summary sum;
+      study_asm_constraint (&sum, constraints[i]);
+      switch (GET_CODE (operands[i]))
+	{
+	case MEM:
+	  if (! sum.allow_mem)
+	    return 0;
+	  break;
+	case REG:
+	case SUBREG:
+	  if (! sum.allow_reg)
+	    return 0;
+	  break;
+	case CONST_INT:
+	case CONST_DOUBLE:
+	  if (! sum.allow_const)
+	    return 0;
+	  break;
+
+	default:
+	  break;  /* ??? or return 0 */
+	}
+    }
 
   return 1;
 }
Index: stmt.c
===================================================================
RCS file: /cvs/cvsfiles/egcs/gcc/stmt.c,v
retrieving revision 1.2
diff -u -p -r1.2 stmt.c
--- stmt.c	1997/08/20 19:30:36	1.2
+++ stmt.c	1997/10/26 23:45:24
@@ -1371,6 +1371,63 @@ expand_asm (body)
   last_expr_type = 0;
 }
 
+/* Examine an asm constraint string and summarize important aspects.  */
+
+void
+study_asm_constraint (sum, str)
+    struct asm_constraint_summary *sum;
+    const char *str;
+{
+  bzero(sum, sizeof(*sum));
+  while (*str)
+    switch (*str++)
+      {
+      case '+':
+	sum->found_plus = 1;
+	break;
+      case '=':
+	sum->found_equal = 1;
+	break;
+
+      case '0':  case '1':  case '2':  case '3':  case '4':
+      case '5':  case '6':  case '7':  case '8':  case '9':
+	{
+	  int match = str[-1] - '0' + 1;
+	  if (match > sum->found_match)
+	    sum->found_match = match;
+	}
+	break;
+
+      case 'm':  case 'o':  case 'V':  case '<':  case '>':
+	sum->allow_mem = 1;
+	break;
+
+      case 'i':  case 'n':  case 's':
+      case 'I':  case 'J':  case 'K':  case 'L':  case 'M':
+      case 'N':  case 'O':  case 'P':  case 'E':  case 'F':
+      case 'G':  case 'H':
+	sum->allow_const = 1;
+	break;
+
+      case 'r':  case 'p':
+      default:
+        sum->allow_reg = 1;
+        break;
+
+      case 'g':  case 'X':
+        sum->allow_reg = 1;
+        sum->allow_mem = 1;
+        sum->allow_const = 1;
+	break;
+
+      case '?':  case '!':  case '*':  case '%':  case '&':  case ',':
+#ifdef EXTRA_CONSTRAINT
+      case 'Q':  case 'R':  case 'S':  case 'T':  case 'U':
+#endif
+        break;
+      }
+}
+
 /* Generate RTL for an asm statement with arguments.
    STRING is the instruction template.
    OUTPUTS is a list of output arguments (lvalues); INPUTS a list of inputs.
@@ -1441,67 +1498,47 @@ expand_asm_operands (string, outputs, in
       tree val = TREE_VALUE (tail);
       tree type = TREE_TYPE (val);
       tree val1;
-      int j;
-      int found_equal = 0;
-      int found_plus = 0;
-      int allows_reg = 0;
+      struct asm_constraint_summary sum;
 
       /* If there's an erroneous arg, emit no insn.  */
       if (TREE_TYPE (val) == error_mark_node)
 	return;
 
+      study_asm_constraint (&sum, TREE_STRING_POINTER (TREE_PURPOSE (tail)));
+
       /* Make sure constraint has `=' and does not have `+'.  Also, see
 	 if it allows any register.  Be liberal on the latter test, since
 	 the worst that happens if we get it wrong is we issue an error
 	 message.  */
 
-      for (j = 0; j < TREE_STRING_LENGTH (TREE_PURPOSE (tail)) - 1; j++)
-	switch (TREE_STRING_POINTER (TREE_PURPOSE (tail))[j])
-	  {
-	  case '+':
-	    /* Make sure we can specify the matching operand.  */
-	    if (i > 9)
-	      {
-		error ("output operand constraint %d contains `+'", i);
-		return;
-	      }
-
-	    /* Replace '+' with '='.  */
-	    TREE_STRING_POINTER (TREE_PURPOSE (tail))[j] = '=';
-	    found_plus = 1;
-	    break;
-
-	  case '=':
-	    found_equal = 1;
-	    break;
-
-	  case '?':  case '!':  case '*':  case '%':  case '&':
-	  case 'V':  case 'm':  case 'o':  case '<':  case '>':
-	  case 'E':  case 'F':  case 'G':  case 'H':  case 'X':
-	  case 's':  case 'i':  case 'n':
-	  case 'I':  case 'J':  case 'K':  case 'L':  case 'M':
-	  case 'N':  case 'O':  case 'P':  case ',':
-#ifdef EXTRA_CONSTRAINT
-	  case 'Q':  case 'R':  case 'S':  case 'T':  case 'U':
-#endif
-	    break;
-
-	  case '0':  case '1':  case '2':  case '3':  case '4':
-	  case '5':  case '6':  case '7':  case '8':  case '9':
-	    error ("matching constraint not valid in output operand");
-	    break;
-
-	  case 'p':  case 'g':  case 'r':
-	  default:
-	    allows_reg = 1;
-	    break;
-	  }
+      if (sum.found_plus)
+	{
+	  char *p;
 
-      if (! found_equal && ! found_plus)
+	  /* Make sure we can specify the matching operand.  */
+	  if (i > 9)
+	    {
+	      error ("output operand constraint %d contains `+'", i);
+	      return;
+	    }
+
+	  /* Replace '+' with '='.  */
+	  p = strchr (TREE_STRING_POINTER (TREE_PURPOSE (tail)), '+');
+	  do {
+	    *p = '=';
+	    p = strchr (p, '=');
+	  } while (p);
+	}
+      if (! sum.found_equal && ! sum.found_plus)
 	{
 	  error ("output operand constraint lacks `='");
 	  return;
 	}
+      if (sum.found_match)
+        {
+	  error ("matching constraint not valid in output operand");
+	  return;
+	}
 
       /* If an output operand is not a decl or indirect ref and our constraint
 	 allows a register, make a temporary to act as an intermediate.
@@ -1512,17 +1549,17 @@ expand_asm_operands (string, outputs, in
 	  || (TREE_CODE_CLASS (TREE_CODE (val)) == 'd'
 	      && ! (GET_CODE (DECL_RTL (val)) == REG
 		    && GET_MODE (DECL_RTL (val)) != TYPE_MODE (type)))
-	  || ! allows_reg
-	  || found_plus)
+	  || ! sum.allow_reg
+	  || sum.found_plus)
 	{
-	  if (! allows_reg)
+	  if (! sum.allow_reg)
 	    mark_addressable (TREE_VALUE (tail));
 
 	  output_rtx[i]
 	    = expand_expr (TREE_VALUE (tail), NULL_RTX, VOIDmode,
 			   EXPAND_MEMORY_USE_WO);
 
-	  if (! allows_reg && GET_CODE (output_rtx[i]) != MEM)
+	  if (! sum.allow_reg && GET_CODE (output_rtx[i]) != MEM)
 	    error ("output number %d not directly addressable", i);
 	}
       else
@@ -1531,7 +1568,7 @@ expand_asm_operands (string, outputs, in
 	  TREE_VALUE (tail) = make_tree (type, output_rtx[i]);
 	}
 
-      if (found_plus)
+      if (sum.found_plus)
 	{
 	  inout_mode[ninout] = TYPE_MODE (TREE_TYPE (TREE_VALUE (tail)));
 	  inout_opnum[ninout++] = i;
@@ -1561,8 +1598,7 @@ expand_asm_operands (string, outputs, in
   i = 0;
   for (tail = inputs; tail; tail = TREE_CHAIN (tail))
     {
-      int j;
-      int allows_reg = 0;
+      struct asm_constraint_summary sum;
 
       /* If there's an erroneous arg, emit no insn,
 	 because the ASM_INPUT would get VOIDmode
@@ -1576,47 +1612,31 @@ expand_asm_operands (string, outputs, in
 	  return;
 	}
 
-      /* Make sure constraint has neither `=' nor `+'.  */
+      study_asm_constraint (&sum, TREE_STRING_POINTER (TREE_PURPOSE (tail)));
 
-      for (j = 0; j < TREE_STRING_LENGTH (TREE_PURPOSE (tail)) - 1; j++)
-	switch (TREE_STRING_POINTER (TREE_PURPOSE (tail))[j])
-	  {
-	  case '+':   case '=':
-	    error ("input operand constraint contains `%c'",
-		   TREE_STRING_POINTER (TREE_PURPOSE (tail))[j]);
-	    return;
-
-	  case '?':  case '!':  case '*':  case '%':  case '&':
-	  case 'V':  case 'm':  case 'o':  case '<':  case '>':
-	  case 'E':  case 'F':  case 'G':  case 'H':  case 'X':
-	  case 's':  case 'i':  case 'n':
-	  case 'I':  case 'J':  case 'K':  case 'L':  case 'M':
-	  case 'N':  case 'O':  case 'P':  case ',':
-#ifdef EXTRA_CONSTRAINT
-	  case 'Q':  case 'R':  case 'S':  case 'T':  case 'U':
-#endif
-	    break;
+      /* Make sure constraint has neither `=' nor `+'.  */
+      if (sum.found_plus || sum.found_equal)
+	{
+	  error ("input operand constraint contains `%c'",
+		 sum.found_plus ? '+' : '=');
+	  return;
+	}
 
-	    /* Whether or not a numeric constraint allows a register is
-	       decided by the matching constraint, and so there is no need
-	       to do anything special with them.  We must handle them in
-	       the default case, so that we don't unnecessarily force
-	       operands to memory.  */
-	  case '0':  case '1':  case '2':  case '3':  case '4':
-	  case '5':  case '6':  case '7':  case '8':  case '9':
-	    if (TREE_STRING_POINTER (TREE_PURPOSE (tail))[j]
-		>= '0' + noutputs)
-	      error ("matching constraint references invalid operand number");
-
-	    /* ... fall through ... */
-
-	  case 'p':  case 'g':  case 'r':
-	  default:
-	    allows_reg = 1;
-	    break;
-	  }
+      /* Whether or not a numeric constraint allows a register is
+	 decided by the matching constraint, and so there is no need
+	 to do anything special with them.  We must handle them in
+	 the default case, so that we don't unnecessarily force
+	 operands to memory.  */
+      if (sum.found_match)
+	{
+	  if (sum.found_match - 1 >= noutputs)
+	    error ("matching constraint references invalid operand number");
+	  /* ??? This is what the old code did.  Shall we merge with the 
+	     real output constraint?  */
+	  sum.allow_reg = 1;
+	}
 
-      if (! allows_reg)
+      if (! sum.allow_reg)
 	mark_addressable (TREE_VALUE (tail));
 
       XVECEXP (body, 3, i)      /* argvec */
@@ -1625,7 +1645,7 @@ expand_asm_operands (string, outputs, in
 	  && ! general_operand (XVECEXP (body, 3, i),
 				TYPE_MODE (TREE_TYPE (TREE_VALUE (tail)))))
 	{
-	  if (allows_reg)
+	  if (sum.allow_reg)
 	    XVECEXP (body, 3, i)
 	      = force_reg (TYPE_MODE (TREE_TYPE (TREE_VALUE (tail))),
 			   XVECEXP (body, 3, i));
@@ -1635,7 +1655,7 @@ expand_asm_operands (string, outputs, in
 				 XVECEXP (body, 3, i));
 	}
 
-      if (! allows_reg
+      if (! sum.allow_reg
 	  && (GET_CODE (XVECEXP (body, 3, i)) == REG
 	      || GET_CODE (XVECEXP (body, 3, i)) == SUBREG
 	      || GET_CODE (XVECEXP (body, 3, i)) == CONCAT))
@@ -1645,6 +1665,14 @@ expand_asm_operands (string, outputs, in
 
 	  emit_move_insn (memloc, XVECEXP (body, 3, i));
 	  XVECEXP (body, 3, i) = memloc;
+	}
+
+      if (! sum.allow_mem && sum.allow_reg
+	  && GET_CODE (XVECEXP (body, 3, i)) == MEM)
+	{
+	  XVECEXP (body, 3, i)
+	    = force_reg (TYPE_MODE (TREE_TYPE (TREE_VALUE (tail))),
+			 XVECEXP (body, 3, i));
 	}
 	  
       XVECEXP (body, 4, i)      /* constraints */
Index: tree.h
===================================================================
RCS file: /cvs/cvsfiles/egcs/gcc/tree.h,v
retrieving revision 1.8
diff -u -p -r1.8 tree.h
--- tree.h	1997/10/15 17:19:40	1.8
+++ tree.h	1997/10/26 23:45:36
@@ -1724,6 +1724,22 @@ extern int pushcase				PROTO((tree,
 extern int pushcase_range			PROTO((tree, tree,
 						       tree (*) (tree, tree),
 						       tree, tree *));
+extern void expand_asm_operands			PROTO((tree, tree, tree, tree,
+						       int, char *, int));
+
+struct asm_constraint_summary
+{
+  unsigned found_plus  : 1;
+  unsigned found_equal : 1;
+  unsigned found_match : 4;
+  unsigned allow_reg   : 1;
+  unsigned allow_mem   : 1;
+  unsigned allow_const : 1;
+};
+
+extern void study_asm_constraint	PROTO((struct asm_constraint_summary *,
+					       const char *));
+
 
 /* In fold-const.c */
 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]