Patchwork Recording predicate information in all rtl gen* programs

login
register
mail settings
Submitter Richard Sandiford
Date April 12, 2011, 12:28 p.m.
Message ID <g439lnhcvq.fsf@linaro.org>
Download mbox | patch
Permalink /patch/90774/
State New
Headers show

Comments

Richard Sandiford - April 12, 2011, 12:28 p.m.
This patch is a prerequisite for:

    http://gcc.gnu.org/ml/gcc-patches/2011-03/msg02168.html    

(approved but not yet applied, because I'd forgotten about this).

At the moment, gen* programs that want predicate information need
to process the DEFINE*_PREDICATE directives themselves.  They can then
use routines in gensupport.c to record and retrieve the processed data.

This patch moves the directive processing into gensupport.c too, so that
all gen* programs have access to it.

Tested on x86_64-linux-gnu and arm-linux-gnueabi.  OK to install?

Richard


gcc/
	* genpreds.c (process_define_predicate): Move most processing
	to gensupport.c.  Continue to validate the expression.
	* genrecog.c (did_you_mean_codes, compute_predicate_codes)
	(process_define_predicate): Move processing to gensupport.c.
	(main): Remove DEFINE_PREDICATE and DEFINE_SPECIAL_PREDICATE cases.
	* gensupport.c (did_you_mean_codes): Moved from genrecog.c.
	(compute_predicate_codes): Moved from genrecog.c.  Add lineno
	argument.
	(valid_predicate_name_p): New function, split out from old
	genpreds.c:process_define_predicate.
	(process_define_predicate): New function, combining code from
	old genpreds.c and genrecog.c functions.
	(process_rtx): Call it for DEFINE_PREDICATE and
	DEFINE_SPECIAL_PREDICATE.
Bernd Schmidt - April 12, 2011, 12:44 p.m.
On 04/12/2011 02:28 PM, Richard Sandiford wrote:
> This patch is a prerequisite for:
> 
>     http://gcc.gnu.org/ml/gcc-patches/2011-03/msg02168.html    
> 
> (approved but not yet applied, because I'd forgotten about this).
> 
> At the moment, gen* programs that want predicate information need
> to process the DEFINE*_PREDICATE directives themselves.  They can then
> use routines in gensupport.c to record and retrieve the processed data.
> 
> This patch moves the directive processing into gensupport.c too, so that
> all gen* programs have access to it.

Ok.


Bernd
H.J. Lu - April 12, 2011, 2:07 p.m.
On Tue, Apr 12, 2011 at 5:28 AM, Richard Sandiford
<richard.sandiford@linaro.org> wrote:
> This patch is a prerequisite for:
>
>    http://gcc.gnu.org/ml/gcc-patches/2011-03/msg02168.html
>
> (approved but not yet applied, because I'd forgotten about this).
>
> At the moment, gen* programs that want predicate information need
> to process the DEFINE*_PREDICATE directives themselves.  They can then
> use routines in gensupport.c to record and retrieve the processed data.
>
> This patch moves the directive processing into gensupport.c too, so that
> all gen* programs have access to it.
>
> Tested on x86_64-linux-gnu and arm-linux-gnueabi.  OK to install?
>
> Richard
>
>
> gcc/
>        * genpreds.c (process_define_predicate): Move most processing
>        to gensupport.c.  Continue to validate the expression.
>        * genrecog.c (did_you_mean_codes, compute_predicate_codes)
>        (process_define_predicate): Move processing to gensupport.c.
>        (main): Remove DEFINE_PREDICATE and DEFINE_SPECIAL_PREDICATE cases.
>        * gensupport.c (did_you_mean_codes): Moved from genrecog.c.
>        (compute_predicate_codes): Moved from genrecog.c.  Add lineno
>        argument.
>        (valid_predicate_name_p): New function, split out from old
>        genpreds.c:process_define_predicate.
>        (process_define_predicate): New function, combining code from
>        old genpreds.c and genrecog.c functions.
>        (process_rtx): Call it for DEFINE_PREDICATE and
>        DEFINE_SPECIAL_PREDICATE.
>
>

I think your patch caused:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48573
Richard Sandiford - April 12, 2011, 3 p.m.
"H.J. Lu" <hjl.tools@gmail.com> writes:
> I think your patch caused:
>
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48573

Sorry, this didn't show up on pure x86_64.  It was caused by the
optabs.c patch rather than this one.  I've reverted it for now.

One fix would be:

  /* If the operand is a memory, try forcing the address into a register.  */
  if (MEM_P (op->value)
      && GET_RTX_CLASS (GET_CODE (XEXP (op->value, 0))) != RTX_AUTOINC
      && insn_data[(int) icode].operand[opno].allows_mem)

I think all other addresses really can be forced into registers.

Richard

Patch

Index: gcc/genpreds.c
===================================================================
--- gcc/genpreds.c	2011-04-12 12:16:48.000000000 +0100
+++ gcc/genpreds.c	2011-04-12 12:16:49.000000000 +0100
@@ -93,34 +93,7 @@  validate_exp (rtx exp, const char *name,
 static void
 process_define_predicate (rtx defn, int lineno)
 {
-  struct pred_data *pred;
-  const char *p;
-
-  if (!ISALPHA (XSTR (defn, 0)[0]) && XSTR (defn, 0)[0] != '_')
-    goto bad_name;
-  for (p = XSTR (defn, 0) + 1; *p; p++)
-    if (!ISALNUM (*p) && *p != '_')
-      goto bad_name;
-
-  if (validate_exp (XEXP (defn, 1), XSTR (defn, 0), lineno))
-    return;
-
-  pred = XCNEW (struct pred_data);
-  pred->name = XSTR (defn, 0);
-  pred->exp = XEXP (defn, 1);
-  pred->c_block = XSTR (defn, 2);
-
-  if (GET_CODE (defn) == DEFINE_SPECIAL_PREDICATE)
-    pred->special = true;
-
-  add_predicate (pred);
-  return;
-
- bad_name:
-  error_with_line (lineno,
-		   "%s: predicate name must be a valid C function name",
-		   XSTR (defn, 0));
-  return;
+  validate_exp (XEXP (defn, 1), XSTR (defn, 0), lineno);
 }
 
 /* Given a predicate, if it has an embedded C block, write the block
Index: gcc/genrecog.c
===================================================================
--- gcc/genrecog.c	2011-04-12 12:16:48.000000000 +0100
+++ gcc/genrecog.c	2011-04-12 12:16:49.000000000 +0100
@@ -171,219 +171,6 @@  #define IS_SPLIT(X) ((X) != RECOG)
 /* The line number of the start of the pattern currently being processed.  */
 static int pattern_lineno;
 
-/* Predicate handling.
-
-   We construct from the machine description a table mapping each
-   predicate to a list of the rtl codes it can possibly match.  The
-   function 'maybe_both_true' uses it to deduce that there are no
-   expressions that can be matches by certain pairs of tree nodes.
-   Also, if a predicate can match only one code, we can hardwire that
-   code into the node testing the predicate.
-
-   Some predicates are flagged as special.  validate_pattern will not
-   warn about modeless match_operand expressions if they have a
-   special predicate.  Predicates that allow only constants are also
-   treated as special, for this purpose.
-
-   validate_pattern will warn about predicates that allow non-lvalues
-   when they appear in destination operands.
-
-   Calculating the set of rtx codes that can possibly be accepted by a
-   predicate expression EXP requires a three-state logic: any given
-   subexpression may definitively accept a code C (Y), definitively
-   reject a code C (N), or may have an indeterminate effect (I).  N
-   and I is N; Y or I is Y; Y and I, N or I are both I.  Here are full
-   truth tables.
-
-     a b  a&b  a|b
-     Y Y   Y    Y
-     N Y   N    Y
-     N N   N    N
-     I Y   I    Y
-     I N   N    I
-     I I   I    I
-
-   We represent Y with 1, N with 0, I with 2.  If any code is left in
-   an I state by the complete expression, we must assume that that
-   code can be accepted.  */
-
-#define N 0
-#define Y 1
-#define I 2
-
-#define TRISTATE_AND(a,b)			\
-  ((a) == I ? ((b) == N ? N : I) :		\
-   (b) == I ? ((a) == N ? N : I) :		\
-   (a) && (b))
-
-#define TRISTATE_OR(a,b)			\
-  ((a) == I ? ((b) == Y ? Y : I) :		\
-   (b) == I ? ((a) == Y ? Y : I) :		\
-   (a) || (b))
-
-#define TRISTATE_NOT(a)				\
-  ((a) == I ? I : !(a))
-
-/* 0 means no warning about that code yet, 1 means warned.  */
-static char did_you_mean_codes[NUM_RTX_CODE];
-
-/* Recursively calculate the set of rtx codes accepted by the
-   predicate expression EXP, writing the result to CODES.  */
-static void
-compute_predicate_codes (rtx exp, char codes[NUM_RTX_CODE])
-{
-  char op0_codes[NUM_RTX_CODE];
-  char op1_codes[NUM_RTX_CODE];
-  char op2_codes[NUM_RTX_CODE];
-  int i;
-
-  switch (GET_CODE (exp))
-    {
-    case AND:
-      compute_predicate_codes (XEXP (exp, 0), op0_codes);
-      compute_predicate_codes (XEXP (exp, 1), op1_codes);
-      for (i = 0; i < NUM_RTX_CODE; i++)
-	codes[i] = TRISTATE_AND (op0_codes[i], op1_codes[i]);
-      break;
-
-    case IOR:
-      compute_predicate_codes (XEXP (exp, 0), op0_codes);
-      compute_predicate_codes (XEXP (exp, 1), op1_codes);
-      for (i = 0; i < NUM_RTX_CODE; i++)
-	codes[i] = TRISTATE_OR (op0_codes[i], op1_codes[i]);
-      break;
-    case NOT:
-      compute_predicate_codes (XEXP (exp, 0), op0_codes);
-      for (i = 0; i < NUM_RTX_CODE; i++)
-	codes[i] = TRISTATE_NOT (op0_codes[i]);
-      break;
-
-    case IF_THEN_ELSE:
-      /* a ? b : c  accepts the same codes as (a & b) | (!a & c).  */
-      compute_predicate_codes (XEXP (exp, 0), op0_codes);
-      compute_predicate_codes (XEXP (exp, 1), op1_codes);
-      compute_predicate_codes (XEXP (exp, 2), op2_codes);
-      for (i = 0; i < NUM_RTX_CODE; i++)
-	codes[i] = TRISTATE_OR (TRISTATE_AND (op0_codes[i], op1_codes[i]),
-				TRISTATE_AND (TRISTATE_NOT (op0_codes[i]),
-					      op2_codes[i]));
-      break;
-
-    case MATCH_CODE:
-      /* MATCH_CODE allows a specified list of codes.  However, if it
-	 does not apply to the top level of the expression, it does not
-	 constrain the set of codes for the top level.  */
-      if (XSTR (exp, 1)[0] != '\0')
-	{
-	  memset (codes, Y, NUM_RTX_CODE);
-	  break;
-	}
-
-      memset (codes, N, NUM_RTX_CODE);
-      {
-	const char *next_code = XSTR (exp, 0);
-	const char *code;
-
-	if (*next_code == '\0')
-	  {
-	    error_with_line (pattern_lineno, "empty match_code expression");
-	    break;
-	  }
-
-	while ((code = scan_comma_elt (&next_code)) != 0)
-	  {
-	    size_t n = next_code - code;
-	    int found_it = 0;
-
-	    for (i = 0; i < NUM_RTX_CODE; i++)
-	      if (!strncmp (code, GET_RTX_NAME (i), n)
-		  && GET_RTX_NAME (i)[n] == '\0')
-		{
-		  codes[i] = Y;
-		  found_it = 1;
-		  break;
-		}
-	    if (!found_it)
-	      {
-		error_with_line (pattern_lineno,
-				 "match_code \"%.*s\" matches nothing",
-				 (int) n, code);
-		for (i = 0; i < NUM_RTX_CODE; i++)
-		  if (!strncasecmp (code, GET_RTX_NAME (i), n)
-		      && GET_RTX_NAME (i)[n] == '\0'
-		      && !did_you_mean_codes[i])
-		    {
-		      did_you_mean_codes[i] = 1;
-		      message_with_line (pattern_lineno, "(did you mean \"%s\"?)", GET_RTX_NAME (i));
-		    }
-	      }
-
-	  }
-      }
-      break;
-
-    case MATCH_OPERAND:
-      /* MATCH_OPERAND disallows the set of codes that the named predicate
-	 disallows, and is indeterminate for the codes that it does allow.  */
-      {
-	struct pred_data *p = lookup_predicate (XSTR (exp, 1));
-	if (!p)
-	  {
-	    error_with_line (pattern_lineno,
-			     "reference to unknown predicate '%s'",
-			     XSTR (exp, 1));
-	    break;
-	  }
-	for (i = 0; i < NUM_RTX_CODE; i++)
-	  codes[i] = p->codes[i] ? I : N;
-      }
-      break;
-
-
-    case MATCH_TEST:
-      /* (match_test WHATEVER) is completely indeterminate.  */
-      memset (codes, I, NUM_RTX_CODE);
-      break;
-
-    default:
-      error_with_line (pattern_lineno,
-		       "'%s' cannot be used in a define_predicate expression",
-		       GET_RTX_NAME (GET_CODE (exp)));
-      memset (codes, I, NUM_RTX_CODE);
-      break;
-    }
-}
-
-#undef TRISTATE_OR
-#undef TRISTATE_AND
-#undef TRISTATE_NOT
-
-/* Process a define_predicate expression: compute the set of predicates
-   that can be matched, and record this as a known predicate.  */
-static void
-process_define_predicate (rtx desc)
-{
-  struct pred_data *pred = XCNEW (struct pred_data);
-  char codes[NUM_RTX_CODE];
-  int i;
-
-  pred->name = XSTR (desc, 0);
-  if (GET_CODE (desc) == DEFINE_SPECIAL_PREDICATE)
-    pred->special = 1;
-
-  compute_predicate_codes (XEXP (desc, 1), codes);
-
-  for (i = 0; i < NUM_RTX_CODE; i++)
-    if (codes[i] != N)
-      add_predicate_code (pred, (enum rtx_code) i);
-
-  add_predicate (pred);
-}
-#undef I
-#undef N
-#undef Y
-
-
 static struct decision *new_decision
   (const char *, struct decision_head *);
 static struct decision_test *new_decision_test
@@ -2716,11 +2503,6 @@  main (int argc, char **argv)
 
       switch (GET_CODE (desc))
 	{
-	case DEFINE_PREDICATE:
-	case DEFINE_SPECIAL_PREDICATE:
-	  process_define_predicate (desc);
-	  break;
-
 	case DEFINE_INSN:
 	  h = make_insn_sequence (desc, RECOG);
 	  merge_trees (&recog_tree, &h);
Index: gcc/gensupport.c
===================================================================
--- gcc/gensupport.c	2011-04-12 12:16:48.000000000 +0100
+++ gcc/gensupport.c	2011-04-12 12:20:09.000000000 +0100
@@ -109,6 +109,247 @@  gen_rtx_CONST_INT (enum machine_mode ARG
   return rt;
 }
 
+/* Predicate handling.
+
+   We construct from the machine description a table mapping each
+   predicate to a list of the rtl codes it can possibly match.  The
+   function 'maybe_both_true' uses it to deduce that there are no
+   expressions that can be matches by certain pairs of tree nodes.
+   Also, if a predicate can match only one code, we can hardwire that
+   code into the node testing the predicate.
+
+   Some predicates are flagged as special.  validate_pattern will not
+   warn about modeless match_operand expressions if they have a
+   special predicate.  Predicates that allow only constants are also
+   treated as special, for this purpose.
+
+   validate_pattern will warn about predicates that allow non-lvalues
+   when they appear in destination operands.
+
+   Calculating the set of rtx codes that can possibly be accepted by a
+   predicate expression EXP requires a three-state logic: any given
+   subexpression may definitively accept a code C (Y), definitively
+   reject a code C (N), or may have an indeterminate effect (I).  N
+   and I is N; Y or I is Y; Y and I, N or I are both I.  Here are full
+   truth tables.
+
+     a b  a&b  a|b
+     Y Y   Y    Y
+     N Y   N    Y
+     N N   N    N
+     I Y   I    Y
+     I N   N    I
+     I I   I    I
+
+   We represent Y with 1, N with 0, I with 2.  If any code is left in
+   an I state by the complete expression, we must assume that that
+   code can be accepted.  */
+
+#define N 0
+#define Y 1
+#define I 2
+
+#define TRISTATE_AND(a,b)			\
+  ((a) == I ? ((b) == N ? N : I) :		\
+   (b) == I ? ((a) == N ? N : I) :		\
+   (a) && (b))
+
+#define TRISTATE_OR(a,b)			\
+  ((a) == I ? ((b) == Y ? Y : I) :		\
+   (b) == I ? ((a) == Y ? Y : I) :		\
+   (a) || (b))
+
+#define TRISTATE_NOT(a)				\
+  ((a) == I ? I : !(a))
+
+/* 0 means no warning about that code yet, 1 means warned.  */
+static char did_you_mean_codes[NUM_RTX_CODE];
+
+/* Recursively calculate the set of rtx codes accepted by the
+   predicate expression EXP, writing the result to CODES.  LINENO is
+   the line number on which the directive containing EXP appeared.  */
+
+static void
+compute_predicate_codes (rtx exp, int lineno, char codes[NUM_RTX_CODE])
+{
+  char op0_codes[NUM_RTX_CODE];
+  char op1_codes[NUM_RTX_CODE];
+  char op2_codes[NUM_RTX_CODE];
+  int i;
+
+  switch (GET_CODE (exp))
+    {
+    case AND:
+      compute_predicate_codes (XEXP (exp, 0), lineno, op0_codes);
+      compute_predicate_codes (XEXP (exp, 1), lineno, op1_codes);
+      for (i = 0; i < NUM_RTX_CODE; i++)
+	codes[i] = TRISTATE_AND (op0_codes[i], op1_codes[i]);
+      break;
+
+    case IOR:
+      compute_predicate_codes (XEXP (exp, 0), lineno, op0_codes);
+      compute_predicate_codes (XEXP (exp, 1), lineno, op1_codes);
+      for (i = 0; i < NUM_RTX_CODE; i++)
+	codes[i] = TRISTATE_OR (op0_codes[i], op1_codes[i]);
+      break;
+    case NOT:
+      compute_predicate_codes (XEXP (exp, 0), lineno, op0_codes);
+      for (i = 0; i < NUM_RTX_CODE; i++)
+	codes[i] = TRISTATE_NOT (op0_codes[i]);
+      break;
+
+    case IF_THEN_ELSE:
+      /* a ? b : c  accepts the same codes as (a & b) | (!a & c).  */
+      compute_predicate_codes (XEXP (exp, 0), lineno, op0_codes);
+      compute_predicate_codes (XEXP (exp, 1), lineno, op1_codes);
+      compute_predicate_codes (XEXP (exp, 2), lineno, op2_codes);
+      for (i = 0; i < NUM_RTX_CODE; i++)
+	codes[i] = TRISTATE_OR (TRISTATE_AND (op0_codes[i], op1_codes[i]),
+				TRISTATE_AND (TRISTATE_NOT (op0_codes[i]),
+					      op2_codes[i]));
+      break;
+
+    case MATCH_CODE:
+      /* MATCH_CODE allows a specified list of codes.  However, if it
+	 does not apply to the top level of the expression, it does not
+	 constrain the set of codes for the top level.  */
+      if (XSTR (exp, 1)[0] != '\0')
+	{
+	  memset (codes, Y, NUM_RTX_CODE);
+	  break;
+	}
+
+      memset (codes, N, NUM_RTX_CODE);
+      {
+	const char *next_code = XSTR (exp, 0);
+	const char *code;
+
+	if (*next_code == '\0')
+	  {
+	    error_with_line (lineno, "empty match_code expression");
+	    break;
+	  }
+
+	while ((code = scan_comma_elt (&next_code)) != 0)
+	  {
+	    size_t n = next_code - code;
+	    int found_it = 0;
+
+	    for (i = 0; i < NUM_RTX_CODE; i++)
+	      if (!strncmp (code, GET_RTX_NAME (i), n)
+		  && GET_RTX_NAME (i)[n] == '\0')
+		{
+		  codes[i] = Y;
+		  found_it = 1;
+		  break;
+		}
+	    if (!found_it)
+	      {
+		error_with_line (lineno,
+				 "match_code \"%.*s\" matches nothing",
+				 (int) n, code);
+		for (i = 0; i < NUM_RTX_CODE; i++)
+		  if (!strncasecmp (code, GET_RTX_NAME (i), n)
+		      && GET_RTX_NAME (i)[n] == '\0'
+		      && !did_you_mean_codes[i])
+		    {
+		      did_you_mean_codes[i] = 1;
+		      message_with_line (lineno, "(did you mean \"%s\"?)",
+					 GET_RTX_NAME (i));
+		    }
+	      }
+	  }
+      }
+      break;
+
+    case MATCH_OPERAND:
+      /* MATCH_OPERAND disallows the set of codes that the named predicate
+	 disallows, and is indeterminate for the codes that it does allow.  */
+      {
+	struct pred_data *p = lookup_predicate (XSTR (exp, 1));
+	if (!p)
+	  {
+	    error_with_line (lineno, "reference to unknown predicate '%s'",
+			     XSTR (exp, 1));
+	    break;
+	  }
+	for (i = 0; i < NUM_RTX_CODE; i++)
+	  codes[i] = p->codes[i] ? I : N;
+      }
+      break;
+
+
+    case MATCH_TEST:
+      /* (match_test WHATEVER) is completely indeterminate.  */
+      memset (codes, I, NUM_RTX_CODE);
+      break;
+
+    default:
+      error_with_line (lineno,
+		       "'%s' cannot be used in a define_predicate expression",
+		       GET_RTX_NAME (GET_CODE (exp)));
+      memset (codes, I, NUM_RTX_CODE);
+      break;
+    }
+}
+
+#undef TRISTATE_OR
+#undef TRISTATE_AND
+#undef TRISTATE_NOT
+
+/* Return true if NAME is a valid predicate name.  */
+
+static bool
+valid_predicate_name_p (const char *name)
+{
+  const char *p;
+
+  if (!ISALPHA (name[0]) && name[0] != '_')
+    return false;
+  for (p = name + 1; *p; p++)
+    if (!ISALNUM (*p) && *p != '_')
+      return false;
+  return true;
+}
+
+/* Process define_predicate directive DESC, which appears on line number
+   LINENO.  Compute the set of codes that can be matched, and record this
+   as a known predicate.  */
+
+static void
+process_define_predicate (rtx desc, int lineno)
+{
+  struct pred_data *pred;
+  char codes[NUM_RTX_CODE];
+  int i;
+
+  if (!valid_predicate_name_p (XSTR (desc, 0)))
+    {
+      error_with_line (lineno,
+		       "%s: predicate name must be a valid C function name",
+		       XSTR (desc, 0));
+      return;
+    }
+
+  pred = XCNEW (struct pred_data);
+  pred->name = XSTR (desc, 0);
+  pred->exp = XEXP (desc, 1);
+  pred->c_block = XSTR (desc, 2);
+  if (GET_CODE (desc) == DEFINE_SPECIAL_PREDICATE)
+    pred->special = true;
+
+  compute_predicate_codes (XEXP (desc, 1), lineno, codes);
+
+  for (i = 0; i < NUM_RTX_CODE; i++)
+    if (codes[i] != N)
+      add_predicate_code (pred, (enum rtx_code) i);
+
+  add_predicate (pred);
+}
+#undef I
+#undef N
+#undef Y
+
 /* Queue PATTERN on LIST_TAIL.  Return the address of the new queue
    element.  */
 
@@ -182,6 +423,9 @@  process_rtx (rtx desc, int lineno)
 
     case DEFINE_PREDICATE:
     case DEFINE_SPECIAL_PREDICATE:
+      process_define_predicate (desc, lineno);
+      /* Fall through.  */
+
     case DEFINE_CONSTRAINT:
     case DEFINE_REGISTER_CONSTRAINT:
     case DEFINE_MEMORY_CONSTRAINT: