diff options
-rw-r--r-- | gcc/ChangeLog | 16 | ||||
-rw-r--r-- | gcc/config/i386/predicates.md | 21 | ||||
-rw-r--r-- | gcc/doc/md.texi | 29 | ||||
-rw-r--r-- | gcc/genpreds.c | 60 | ||||
-rw-r--r-- | gcc/genrecog.c | 10 | ||||
-rw-r--r-- | gcc/read-rtl.c | 45 | ||||
-rw-r--r-- | gcc/rtl.def | 9 |
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 |