summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog16
-rw-r--r--gcc/config/i386/predicates.md21
-rw-r--r--gcc/doc/md.texi29
-rw-r--r--gcc/genpreds.c60
-rw-r--r--gcc/genrecog.c10
-rw-r--r--gcc/read-rtl.c45
-rw-r--r--gcc/rtl.def9
7 files changed, 159 insertions, 31 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 291dd5135e1..eaaf2d87fe0 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,21 @@
2006-01-22 Zack Weinberg <zackw@panix.com>
+ * rtl.def (match_code): Add second argument.
+ * genpreds.c (write_extract_subexp): New function.
+ (write_match_code): Add path argument. Use write_extract_subexp.
+ (write_predicate_expr): Pass path to write_match_code.
+ (mark_mode_tests): MATCH_CODE applied to a subexpression does
+ not perform a mode test.
+ * genrecog.c (compute_predicate_codes): MATCH_CODE applied to
+ a subexpression does not constrain the top-level code set.
+ * read-rtl.c (read_rtx_variadic): New function.
+ (read_rtx_1): Use it; allow AND and IOR to be variadic.
+ * doc/md.texi: Document new notation.
+ * config/i386/predicates.md (cmpsi_operand_1): Fold into ...
+ (cmpsi_operand): ... here, using new notation.
+
+2006-01-22 Zack Weinberg <zackw@panix.com>
+
* varray.c: Remove GENERATOR_FILE #ifdefs.
2006-01-22 Zack Weinberg <zackw@panix.com>
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index 2d423d4053a..acc01eeb537 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -931,21 +931,16 @@
;; ??? It seems likely that this will only work because cmpsi is an
;; expander, and no actual insns use this.
-(define_predicate "cmpsi_operand_1"
- (match_code "and")
-{
- return (GET_MODE (op) == SImode
- && GET_CODE (XEXP (op, 0)) == ZERO_EXTRACT
- && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT
- && GET_CODE (XEXP (XEXP (op, 0), 2)) == CONST_INT
- && INTVAL (XEXP (XEXP (op, 0), 1)) == 8
- && INTVAL (XEXP (XEXP (op, 0), 2)) == 8
- && GET_CODE (XEXP (op, 1)) == CONST_INT);
-})
-
(define_predicate "cmpsi_operand"
(ior (match_operand 0 "nonimmediate_operand")
- (match_operand 0 "cmpsi_operand_1")))
+ (and (match_code "and")
+ (match_code "zero_extract" "0")
+ (match_code "const_int" "1")
+ (match_code "const_int" "01")
+ (match_code "const_int" "02")
+ (match_test "INTVAL (XEXP (XEXP (op, 0), 1)) == 8")
+ (match_test "INTVAL (XEXP (XEXP (op, 0), 2)) == 8")
+ )))
(define_predicate "compare_operator"
(match_code "compare"))
diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
index b6dd8382f8e..df16e9370c3 100644
--- a/gcc/doc/md.texi
+++ b/gcc/doc/md.texi
@@ -898,9 +898,27 @@ limitations in @command{genrecog}, you can only refer to generic
predicates and predicates that have already been defined.
@item MATCH_CODE
-This expression has one operand, a string constant containing a
-comma-separated list of RTX code names (in lower case). It evaluates
-to true if @var{op} has any of the listed codes.
+This expression evaluates to true if @var{op} or a specified
+subexpression of @var{op} has one of a given list of RTX codes.
+
+The first operand of this expression is a string constant containing a
+comma-separated list of RTX code names (in lower case). These are the
+codes for which the @code{MATCH_CODE} will be true.
+
+The second operand is a string constant which indicates what
+subexpression of @var{op} to examine. If it is absent or the empty
+string, @var{op} itself is examined. Otherwise, the string constant
+must be a sequence of digits and/or lowercase letters. Each character
+indicates a subexpression to extract from the current expression; for
+the first character this is @var{op}, for the second and subsequent
+characters it is the result of the previous character. A digit
+@var{n} extracts @samp{@w{XEXP (@var{e}, @var{n})}}; a letter @var{l}
+extracts @samp{@w{XVECEXP (@var{e}, 0, @var{n})}} where @var{n} is the
+alphabetic ordinal of @var{l} (0 for `a', 1 for 'b', and so on). The
+@code{MATCH_CODE} then examines the RTX code of the subexpression
+extracted by the complete string. It is not possible to extract
+components of an @code{rtvec} that is not at position 0 within its RTX
+object.
@item MATCH_TEST
This expression has one operand, a string constant containing a C
@@ -915,7 +933,10 @@ evaluates to true if the C expression evaluates to a nonzero value.
@itemx IF_THEN_ELSE
The basic @samp{MATCH_} expressions can be combined using these
logical operators, which have the semantics of the C operators
-@samp{&&}, @samp{||}, @samp{!}, and @samp{@w{? :}} respectively.
+@samp{&&}, @samp{||}, @samp{!}, and @samp{@w{? :}} respectively. As
+in Common Lisp, you may give an @code{AND} or @code{IOR} expression an
+arbitrary number of arguments; this has exactly the same effect as
+writing a chain of two-argument @code{AND} or @code{IOR} expressions.
@end table
@item
diff --git a/gcc/genpreds.c b/gcc/genpreds.c
index 6dbe7d4b920..bfd681cc7b8 100644
--- a/gcc/genpreds.c
+++ b/gcc/genpreds.c
@@ -148,11 +148,11 @@ write_predicate_subfunction (struct pred_data *p)
/* Given an RTL expression EXP, find all subexpressions which we may
assume to perform mode tests. Normal MATCH_OPERAND does;
- MATCH_CODE does if and only if it accepts CONST_INT or
- CONST_DOUBLE; and we have to assume that MATCH_TEST does not.
- These combine in almost-boolean fashion - the only exception is
- that (not X) must be assumed not to perform a mode test, whether or
- not X does.
+ MATCH_CODE does if it applies to the whole expression and accepts
+ CONST_INT or CONST_DOUBLE; and we have to assume that MATCH_TEST
+ does not. These combine in almost-boolean fashion - the only
+ exception is that (not X) must be assumed not to perform a mode
+ test, whether or not X does.
The mark is the RTL /v flag, which is true for subexpressions which
do *not* perform mode tests.
@@ -174,8 +174,9 @@ mark_mode_tests (rtx exp)
break;
case MATCH_CODE:
- if (!strstr (XSTR (exp, 0), "const_int")
- && !strstr (XSTR (exp, 0), "const_double"))
+ if (XSTR (exp, 1)[0] != '\0'
+ || (!strstr (XSTR (exp, 0), "const_int")
+ && !strstr (XSTR (exp, 0), "const_double")))
NO_MODE_TEST (exp) = 1;
break;
@@ -305,17 +306,56 @@ add_mode_tests (struct pred_data *p)
*pos = and_exp;
}
+/* PATH is a string describing a path from the root of an RTL
+ expression to an inner subexpression to be tested. Output
+ code which computes the subexpression from the variable
+ holding the root of the expression. */
+static void
+write_extract_subexp (const char *path)
+{
+ int len = strlen (path);
+ int i;
+
+ /* We first write out the operations (XEXP or XVECEXP) in reverse
+ order, then write "op", then the indices in forward order. */
+ for (i = len - 1; i >= 0; i--)
+ {
+ if (ISLOWER (path[i]))
+ fputs ("XVECEXP (", stdout);
+ else if (ISDIGIT (path[i]))
+ fputs ("XEXP (", stdout);
+ else
+ {
+ error ("bad character in path string '%s'", path);
+ return;
+ }
+ }
+
+ fputs ("op", stdout);
+
+ for (i = 0; i < len; i++)
+ {
+ if (ISLOWER (path[i]))
+ printf (", 0, %d)", path[i] - 'a');
+ else if (ISDIGIT (path[i]))
+ printf (", %d)", path[i] - '0');
+ else
+ gcc_unreachable ();
+ }
+}
/* CODES is a list of RTX codes. Write out an expression which
determines whether the operand has one of those codes. */
static void
-write_match_code (const char *codes)
+write_match_code (const char *path, const char *codes)
{
const char *code;
while ((code = scan_comma_elt (&codes)) != 0)
{
- fputs ("GET_CODE (op) == ", stdout);
+ fputs ("GET_CODE (", stdout);
+ write_extract_subexp (path);
+ fputs (") == ", stdout);
while (code < codes)
{
putchar (TOUPPER (*code));
@@ -374,7 +414,7 @@ write_predicate_expr (const char *name, rtx exp)
break;
case MATCH_CODE:
- write_match_code (XSTR (exp, 0));
+ write_match_code (XSTR (exp, 1), XSTR (exp, 0));
break;
case MATCH_TEST:
diff --git a/gcc/genrecog.c b/gcc/genrecog.c
index cb86849e936..56d65985d25 100644
--- a/gcc/genrecog.c
+++ b/gcc/genrecog.c
@@ -270,7 +270,15 @@ compute_predicate_codes (rtx exp, char codes[NUM_RTX_CODE])
break;
case MATCH_CODE:
- /* MATCH_CODE allows a specified list of codes. */
+ /* 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);
diff --git a/gcc/read-rtl.c b/gcc/read-rtl.c
index b4b105108eb..5eb642ee0a2 100644
--- a/gcc/read-rtl.c
+++ b/gcc/read-rtl.c
@@ -145,6 +145,7 @@ static int find_macro (struct macro_group *, const char *, FILE *);
static struct mapping *read_mapping (struct macro_group *, htab_t, FILE *);
static void check_code_macro (struct mapping *, FILE *);
static rtx read_rtx_1 (FILE *, struct map_value **);
+static rtx read_rtx_variadic (FILE *, struct map_value **, rtx);
/* The mode and code macro structures. */
static struct macro_group modes, codes;
@@ -1696,7 +1697,49 @@ read_rtx_1 (FILE *infile, struct map_value **mode_maps)
c = read_skip_spaces (infile);
if (c != ')')
- fatal_expected_char (infile, ')', c);
+ {
+ /* Syntactic sugar for AND and IOR, allowing Lisp-like
+ arbitrary number of arguments for them. */
+ if (c == '(' && (GET_CODE (return_rtx) == AND
+ || GET_CODE (return_rtx) == IOR))
+ return read_rtx_variadic (infile, mode_maps, return_rtx);
+ else
+ fatal_expected_char (infile, ')', c);
+ }
return return_rtx;
}
+
+/* Mutually recursive subroutine of read_rtx which reads
+ (thing x1 x2 x3 ...) and produces RTL as if
+ (thing x1 (thing x2 (thing x3 ...))) had been written.
+ When called, FORM is (thing x1 x2), and the file position
+ is just past the leading parenthesis of x3. Only works
+ for THINGs which are dyadic expressions, e.g. AND, IOR. */
+static rtx
+read_rtx_variadic (FILE *infile, struct map_value **mode_maps, rtx form)
+{
+ char c = '(';
+ rtx p = form, q;
+
+ do
+ {
+ ungetc (c, infile);
+
+ q = rtx_alloc (GET_CODE (p));
+ PUT_MODE (q, GET_MODE (p));
+
+ XEXP (q, 0) = XEXP (p, 1);
+ XEXP (q, 1) = read_rtx_1 (infile, mode_maps);
+
+ XEXP (p, 1) = q;
+ p = q;
+ c = read_skip_spaces (infile);
+ }
+ while (c == '(');
+
+ if (c != ')')
+ fatal_expected_char (infile, ')', c);
+
+ return form;
+}
diff --git a/gcc/rtl.def b/gcc/rtl.def
index f9dd11e4b0f..8710f54890f 100644
--- a/gcc/rtl.def
+++ b/gcc/rtl.def
@@ -727,8 +727,13 @@ DEF_RTL_EXPR(MATCH_PAR_DUP, "match_par_dup", "iE", RTX_MATCH)
/* Appears only in define_predicate/define_special_predicate
expressions. Evaluates true only if the operand has an RTX code
- from the set given by the argument (a comma-separated list). */
-DEF_RTL_EXPR(MATCH_CODE, "match_code", "s", RTX_MATCH)
+ from the set given by the argument (a comma-separated list). If the
+ second argument is present and nonempty, it is a sequence of digits
+ and/or letters which indicates the subexpression to test, using the
+ same syntax as genextract/genrecog's location strings: 0-9 for
+ XEXP (op, n), a-z for XVECEXP (op, 0, n); each character applies to
+ the result of the one before it. */
+DEF_RTL_EXPR(MATCH_CODE, "match_code", "ss", RTX_MATCH)
/* Appears only in define_predicate/define_special_predicate
expressions. The argument is a C expression to be injected at this