X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fgenrecog.c;h=7c9298dfc60900ed02829aeeb4a26a5b15cabed6;hb=467fa2ada0cbc1b7b81db7567540e8e46dbca920;hp=8564b5cc1f13675e3575d24ddd35b73889ec4316;hpb=8c4c00c181e6df4f0a9afc76e4c9edbbc1c2fd41;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/genrecog.c b/gcc/genrecog.c index 8564b5cc1f1..7c9298dfc60 100644 --- a/gcc/genrecog.c +++ b/gcc/genrecog.c @@ -1,6 +1,6 @@ /* Generate code from machine description to recognize rtl as insns. Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007 + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GCC. @@ -56,11 +56,55 @@ #include "tm.h" #include "rtl.h" #include "errors.h" +#include "read-md.h" #include "gensupport.h" #define OUTPUT_LABEL(INDENT_STRING, LABEL_NUMBER) \ printf("%sL%d: ATTRIBUTE_UNUSED_LABEL\n", (INDENT_STRING), (LABEL_NUMBER)) +/* Ways of obtaining an rtx to be tested. */ +enum position_type { + /* PATTERN (peep2_next_insn (ARG)). */ + POS_PEEP2_INSN, + + /* XEXP (BASE, ARG). */ + POS_XEXP, + + /* XVECEXP (BASE, 0, ARG). */ + POS_XVECEXP0 +}; + +/* The position of an rtx relative to X0. Each useful position is + represented by exactly one instance of this structure. */ +struct position +{ + /* The parent rtx. This is the root position for POS_PEEP2_INSNs. */ + struct position *base; + + /* A position with the same BASE and TYPE, but with the next value + of ARG. */ + struct position *next; + + /* A list of all POS_XEXP positions that use this one as their base, + chained by NEXT fields. The first entry represents XEXP (this, 0), + the second represents XEXP (this, 1), and so on. */ + struct position *xexps; + + /* A list of POS_XVECEXP0 positions that use this one as their base, + chained by NEXT fields. The first entry represents XVECEXP (this, 0, 0), + the second represents XVECEXP (this, 0, 1), and so on. */ + struct position *xvecexp0s; + + /* The type of position. */ + enum position_type type; + + /* The argument to TYPE (shown as ARG in the position_type comments). */ + int arg; + + /* The depth of this position, with 0 as the root. */ + int depth; +}; + /* A listhead of decision trees. The alternatives to a node are kept in a doubly-linked list so we can easily add nodes to the proper place when merging. */ @@ -71,6 +115,17 @@ struct decision_head struct decision *last; }; +/* These types are roughly in the order in which we'd like to test them. */ +enum decision_type +{ + DT_num_insns, + DT_mode, DT_code, DT_veclen, + DT_elt_zero_int, DT_elt_one_int, DT_elt_zero_wide, DT_elt_zero_wide_safe, + DT_const_int, + DT_veclen_ge, DT_dup, DT_pred, DT_c_test, + DT_accept_op, DT_accept_insn +}; + /* A single test. The two accept types aren't tests per-se, but their equality (or lack thereof) does affect tree merging so it is convenient to keep them here. */ @@ -80,16 +135,7 @@ struct decision_test /* A linked list through the tests attached to a node. */ struct decision_test *next; - /* These types are roughly in the order in which we'd like to test them. */ - enum decision_type - { - DT_num_insns, - DT_mode, DT_code, DT_veclen, - DT_elt_zero_int, DT_elt_one_int, DT_elt_zero_wide, DT_elt_zero_wide_safe, - DT_const_int, - DT_veclen_ge, DT_dup, DT_pred, DT_c_test, - DT_accept_op, DT_accept_insn - } type; + enum decision_type type; union { @@ -129,7 +175,7 @@ struct decision struct decision *afterward; /* Node to test on success, but failure of successor nodes. */ - const char *position; /* String denoting position in pattern. */ + struct position *position; /* Position in pattern. */ struct decision_test *tests; /* The tests for this node. */ @@ -168,339 +214,82 @@ static int max_depth; /* The line number of the start of the pattern currently being processed. */ static int pattern_lineno; -/* Count of errors. */ -static int error_count; +/* The root position (x0). */ +static struct position root_pos; + +/* A list of all POS_PEEP2_INSNs. The entry for insn 0 is the root position, + since we are given that instruction's pattern as x0. */ +static struct position *peep2_insn_pos_list = &root_pos; -/* 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]) +extern void debug_decision + (struct decision *); +extern void debug_decision_list + (struct decision *); + +/* Return a position with the given BASE, TYPE and ARG. NEXT_PTR + points to where the unique object that represents the position + should be stored. Create the object if it doesn't already exist, + otherwise reuse the object that is already there. */ + +static struct position * +next_position (struct position **next_ptr, struct position *base, + enum position_type type, int arg) { - char op0_codes[NUM_RTX_CODE]; - char op1_codes[NUM_RTX_CODE]; - char op2_codes[NUM_RTX_CODE]; - int i; + struct position *pos; - switch (GET_CODE (exp)) + pos = *next_ptr; + if (!pos) { - 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') - { - message_with_line (pattern_lineno, "empty match_code expression"); - error_count++; - 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) - { - message_with_line (pattern_lineno, "match_code \"%.*s\" matches nothing", - (int) n, code); - error_count ++; - 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) - { - message_with_line (pattern_lineno, - "reference to unknown predicate '%s'", - XSTR (exp, 1)); - error_count++; - 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: - message_with_line (pattern_lineno, - "'%s' cannot be used in a define_predicate expression", - GET_RTX_NAME (GET_CODE (exp))); - error_count++; - memset (codes, I, NUM_RTX_CODE); - break; + pos = XCNEW (struct position); + pos->base = base; + pos->type = type; + pos->arg = arg; + pos->depth = base->depth + 1; + *next_ptr = pos; } + return pos; } -#undef TRISTATE_OR -#undef TRISTATE_AND -#undef TRISTATE_NOT +/* Compare positions POS1 and POS2 lexicographically. */ -/* 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) +static int +compare_positions (struct position *pos1, struct position *pos2) { - struct pred_data *pred = xcalloc (sizeof (struct pred_data), 1); - char codes[NUM_RTX_CODE]; - bool seen_one = false; - 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) - { - pred->codes[i] = true; - if (GET_RTX_CLASS (i) != RTX_CONST_OBJ) - pred->allows_non_const = true; - if (i != REG - && i != SUBREG - && i != MEM - && i != CONCAT - && i != PARALLEL - && i != STRICT_LOW_PART) - pred->allows_non_lvalue = true; - - if (seen_one) - pred->singleton = UNKNOWN; - else - { - pred->singleton = i; - seen_one = true; - } - } - add_predicate (pred); + int diff; + + diff = pos1->depth - pos2->depth; + if (diff < 0) + do + pos2 = pos2->base; + while (pos1->depth != pos2->depth); + else if (diff > 0) + do + pos1 = pos1->base; + while (pos1->depth != pos2->depth); + while (pos1 != pos2) + { + diff = (int) pos1->type - (int) pos2->type; + if (diff == 0) + diff = pos1->arg - pos2->arg; + pos1 = pos1->base; + pos2 = pos2->base; + } + return diff; } -#undef I -#undef N -#undef Y - -static struct decision *new_decision - (const char *, struct decision_head *); -static struct decision_test *new_decision_test - (enum decision_type, struct decision_test ***); -static rtx find_operand - (rtx, int, rtx); -static rtx find_matching_operand - (rtx, int); -static void validate_pattern - (rtx, rtx, rtx, int); -static struct decision *add_to_sequence - (rtx, struct decision_head *, const char *, enum routine_type, int); - -static int maybe_both_true_2 - (struct decision_test *, struct decision_test *); -static int maybe_both_true_1 - (struct decision_test *, struct decision_test *); -static int maybe_both_true - (struct decision *, struct decision *, int); - -static int nodes_identical_1 - (struct decision_test *, struct decision_test *); -static int nodes_identical - (struct decision *, struct decision *); -static void merge_accept_insn - (struct decision *, struct decision *); -static void merge_trees - (struct decision_head *, struct decision_head *); - -static void factor_tests - (struct decision_head *); -static void simplify_tests - (struct decision_head *); -static int break_out_subroutines - (struct decision_head *, int); -static void find_afterward - (struct decision_head *, struct decision *); - -static void change_state - (const char *, const char *, const char *); -static void print_code - (enum rtx_code); -static void write_afterward - (struct decision *, struct decision *, const char *); -static struct decision *write_switch - (struct decision *, int); -static void write_cond - (struct decision_test *, int, enum routine_type); -static void write_action - (struct decision *, struct decision_test *, int, int, - struct decision *, enum routine_type); -static int is_unconditional - (struct decision_test *, enum routine_type); -static int write_node - (struct decision *, int, enum routine_type); -static void write_tree_1 - (struct decision_head *, int, enum routine_type); -static void write_tree - (struct decision_head *, const char *, enum routine_type, int); -static void write_subroutine - (struct decision_head *, enum routine_type); -static void write_subroutines - (struct decision_head *, enum routine_type); -static void write_header - (void); - -static struct decision_head make_insn_sequence - (rtx, enum routine_type); -static void process_tree - (struct decision_head *, enum routine_type); - -static void debug_decision_0 - (struct decision *, int, int); -static void debug_decision_1 - (struct decision *, int); -static void debug_decision_2 - (struct decision_test *); -extern void debug_decision - (struct decision *); -extern void debug_decision_list - (struct decision *); - /* Create a new node in sequence after LAST. */ static struct decision * -new_decision (const char *position, struct decision_head *last) +new_decision (struct position *pos, struct decision_head *last) { - struct decision *new = xcalloc (1, sizeof (struct decision)); + struct decision *new_decision = XCNEW (struct decision); - new->success = *last; - new->position = xstrdup (position); - new->number = next_number++; + new_decision->success = *last; + new_decision->position = pos; + new_decision->number = next_number++; - last->first = last->last = new; - return new; + last->first = last->last = new_decision; + return new_decision; } /* Create a new test and link it in at PLACE. */ @@ -650,12 +439,9 @@ validate_pattern (rtx pattern, rtx insn, rtx set, int set_code) case MATCH_OP_DUP: case MATCH_PAR_DUP: if (find_operand (insn, XINT (pattern, 0), pattern) == pattern) - { - message_with_line (pattern_lineno, - "operand %i duplicated before defined", - XINT (pattern, 0)); - error_count++; - } + error_with_line (pattern_lineno, + "operand %i duplicated before defined", + XINT (pattern, 0)); break; case MATCH_OPERAND: case MATCH_OPERATOR: @@ -711,20 +497,14 @@ validate_pattern (rtx pattern, rtx insn, rtx set, int set_code) && find_matching_operand (insn, XINT (pattern, 0))) ; else - { - message_with_line (pattern_lineno, - "operand %d missing in-out reload", - XINT (pattern, 0)); - error_count++; - } - } - else if (constraints0 != '=' && constraints0 != '+') - { - message_with_line (pattern_lineno, - "operand %d missing output reload", + error_with_line (pattern_lineno, + "operand %d missing in-out reload", XINT (pattern, 0)); - error_count++; } + else if (constraints0 != '=' && constraints0 != '+') + error_with_line (pattern_lineno, + "operand %d missing output reload", + XINT (pattern, 0)); } } @@ -798,12 +578,9 @@ validate_pattern (rtx pattern, rtx insn, rtx set, int set_code) /* The operands of a SET must have the same mode unless one is VOIDmode. */ else if (dmode != VOIDmode && smode != VOIDmode && dmode != smode) - { - message_with_line (pattern_lineno, - "mode mismatch in set: %smode vs %smode", - GET_MODE_NAME (dmode), GET_MODE_NAME (smode)); - error_count++; - } + error_with_line (pattern_lineno, + "mode mismatch in set: %smode vs %smode", + GET_MODE_NAME (dmode), GET_MODE_NAME (smode)); /* If only one of the operands is VOIDmode, and PC or CC0 is not involved, it's probably a mistake. */ @@ -812,7 +589,8 @@ validate_pattern (rtx pattern, rtx insn, rtx set, int set_code) && GET_CODE (dest) != CC0 && GET_CODE (src) != PC && GET_CODE (src) != CC0 - && GET_CODE (src) != CONST_INT) + && !CONST_INT_P (src) + && GET_CODE (src) != CALL) { const char *which; which = (dmode == VOIDmode ? "destination" : "source"); @@ -843,12 +621,9 @@ validate_pattern (rtx pattern, rtx insn, rtx set, int set_code) case LABEL_REF: if (GET_MODE (XEXP (pattern, 0)) != VOIDmode) - { - message_with_line (pattern_lineno, - "operand to label_ref %smode not VOIDmode", - GET_MODE_NAME (GET_MODE (XEXP (pattern, 0)))); - error_count++; - } + error_with_line (pattern_lineno, + "operand to label_ref %smode not VOIDmode", + GET_MODE_NAME (GET_MODE (XEXP (pattern, 0)))); break; default: @@ -885,36 +660,32 @@ validate_pattern (rtx pattern, rtx insn, rtx set, int set_code) LAST is a pointer to the listhead in the previous node in the chain (or in the calling function, for the first node). - POSITION is the string representing the current position in the insn. + POSITION is the current position in the insn. INSN_TYPE is the type of insn for which we are emitting code. A pointer to the final node in the chain is returned. */ static struct decision * -add_to_sequence (rtx pattern, struct decision_head *last, const char *position, - enum routine_type insn_type, int top) +add_to_sequence (rtx pattern, struct decision_head *last, + struct position *pos, enum routine_type insn_type, int top) { RTX_CODE code; - struct decision *this, *sub; + struct decision *this_decision, *sub; struct decision_test *test; struct decision_test **place; - char *subpos; + struct position *subpos, **subpos_ptr; size_t i; const char *fmt; - int depth = strlen (position); int len; enum machine_mode mode; + enum position_type pos_type; - if (depth > max_depth) - max_depth = depth; - - subpos = xmalloc (depth + 2); - strcpy (subpos, position); - subpos[depth + 1] = 0; + if (pos->depth > max_depth) + max_depth = pos->depth; - sub = this = new_decision (position, last); - place = &this->tests; + sub = this_decision = new_decision (pos, last); + place = &this_decision->tests; restart: mode = GET_MODE (pattern); @@ -943,15 +714,15 @@ add_to_sequence (rtx pattern, struct decision_head *last, const char *position, last->first = last->last = NULL; } + subpos_ptr = &peep2_insn_pos_list; for (i = 0; i < (size_t) XVECLEN (pattern, 0); i++) { - /* Which insn we're looking at is represented by A-Z. We don't - ever use 'A', however; it is always implied. */ - - subpos[depth] = (i > 0 ? 'A' + i : 0); + subpos = next_position (subpos_ptr, &root_pos, + POS_PEEP2_INSN, i); sub = add_to_sequence (XVECEXP (pattern, 0, i), last, subpos, insn_type, 0); last = &sub->success; + subpos_ptr = &subpos->next; } goto ret; } @@ -1035,12 +806,22 @@ add_to_sequence (rtx pattern, struct decision_head *last, const char *position, if (was_code == MATCH_OPERATOR || was_code == MATCH_PARALLEL) { - char base = (was_code == MATCH_OPERATOR ? '0' : 'a'); + if (was_code == MATCH_OPERATOR) + { + pos_type = POS_XEXP; + subpos_ptr = &pos->xexps; + } + else + { + pos_type = POS_XVECEXP0; + subpos_ptr = &pos->xvecexp0s; + } for (i = 0; i < (size_t) XVECLEN (pattern, 2); i++) { - subpos[depth] = i + base; + subpos = next_position (subpos_ptr, pos, pos_type, i); sub = add_to_sequence (XVECEXP (pattern, 2, i), &sub->success, subpos, insn_type, 0); + subpos_ptr = &subpos->next; } } goto fini; @@ -1055,11 +836,13 @@ add_to_sequence (rtx pattern, struct decision_head *last, const char *position, test = new_decision_test (DT_accept_op, &place); test->u.opno = XINT (pattern, 0); + subpos_ptr = &pos->xexps; for (i = 0; i < (size_t) XVECLEN (pattern, 1); i++) { - subpos[depth] = i + '0'; + subpos = next_position (subpos_ptr, pos, POS_XEXP, i); sub = add_to_sequence (XVECEXP (pattern, 1, i), &sub->success, subpos, insn_type, 0); + subpos_ptr = &subpos->next; } goto fini; @@ -1123,24 +906,29 @@ add_to_sequence (rtx pattern, struct decision_head *last, const char *position, } /* Now test our sub-patterns. */ + subpos_ptr = &pos->xexps; for (i = 0; i < (size_t) len; i++) { + subpos = next_position (subpos_ptr, pos, POS_XEXP, i); switch (fmt[i]) { case 'e': case 'u': - subpos[depth] = '0' + i; sub = add_to_sequence (XEXP (pattern, i), &sub->success, subpos, insn_type, 0); break; case 'E': { + struct position *subpos2, **subpos2_ptr; int j; + + subpos2_ptr = &pos->xvecexp0s; for (j = 0; j < XVECLEN (pattern, i); j++) { - subpos[depth] = 'a' + j; + subpos2 = next_position (subpos2_ptr, pos, POS_XVECEXP0, j); sub = add_to_sequence (XVECEXP (pattern, i, j), - &sub->success, subpos, insn_type, 0); + &sub->success, subpos2, insn_type, 0); + subpos2_ptr = &subpos2->next; } break; } @@ -1154,6 +942,7 @@ add_to_sequence (rtx pattern, struct decision_head *last, const char *position, default: gcc_unreachable (); } + subpos_ptr = &subpos->next; } fini: @@ -1161,23 +950,22 @@ add_to_sequence (rtx pattern, struct decision_head *last, const char *position, before any of the nodes we may have added above. */ if (code != UNKNOWN) { - place = &this->tests; + place = &this_decision->tests; test = new_decision_test (DT_code, &place); test->u.code = code; } if (mode != VOIDmode) { - place = &this->tests; + place = &this_decision->tests; test = new_decision_test (DT_mode, &place); test->u.mode = mode; } /* If we didn't insert any tests or accept nodes, hork. */ - gcc_assert (this->tests); + gcc_assert (this_decision->tests); ret: - free (subpos); return sub; } @@ -1262,7 +1050,7 @@ maybe_both_true_2 (struct decision_test *d1, struct decision_test *d2) else if (d2->type == DT_pred && d2->u.pred.data) { bool common = false; - enum rtx_code c; + int c; for (c = 0; c < NUM_RTX_CODE; c++) if (d1->u.pred.data->codes[c] && d2->u.pred.data->codes[c]) @@ -1343,12 +1131,12 @@ maybe_both_true (struct decision *d1, struct decision *d2, of a node's success nodes (from the loop at the end of this function). Skip forward until we come to a position that matches. - Due to the way position strings are constructed, we know that iterating - forward from the lexically lower position (e.g. "00") will run into - the lexically higher position (e.g. "1") and not the other way around. - This saves a bit of effort. */ + Due to the way positions are constructed, we know that iterating + forward from the lexically lower position will run into the lexically + higher position and not the other way around. This saves a bit + of effort. */ - cmp = strcmp (d1->position, d2->position); + cmp = compare_positions (d1->position, d2->position); if (cmp != 0) { gcc_assert (!toplevel); @@ -1463,7 +1251,7 @@ nodes_identical (struct decision *d1, struct decision *d2) invoked. */ if (d1->success.first && d2->success.first - && strcmp (d1->success.first->position, d2->success.first->position)) + && d1->success.first->position != d2->success.first->position) return 0; return 1; @@ -1509,12 +1297,11 @@ merge_accept_insn (struct decision *oldd, struct decision *addd) } else { - message_with_line (add->u.insn.lineno, "`%s' matches `%s'", - get_insn_name (add->u.insn.code_number), - get_insn_name (old->u.insn.code_number)); + error_with_line (add->u.insn.lineno, "`%s' matches `%s'", + get_insn_name (add->u.insn.code_number), + get_insn_name (old->u.insn.code_number)); message_with_line (old->u.insn.lineno, "previous definition of `%s'", get_insn_name (old->u.insn.code_number)); - error_count++; } } @@ -1534,7 +1321,7 @@ merge_trees (struct decision_head *oldh, struct decision_head *addh) } /* Trying to merge bits at different positions isn't possible. */ - gcc_assert (!strcmp (oldh->first->position, addh->first->position)); + gcc_assert (oldh->first->position == addh->first->position); for (add = addh->first; add ; add = next) { @@ -1611,7 +1398,7 @@ factor_tests (struct decision_head *head) for (first = head->first; first && first->next; first = next) { enum decision_type type; - struct decision *new, *old_last; + struct decision *new_dec, *old_last; type = first->tests->type; next = first->next; @@ -1634,8 +1421,8 @@ factor_tests (struct decision_head *head) below our first test. */ if (first->tests->next != NULL) { - new = new_decision (first->position, &first->success); - new->tests = first->tests->next; + new_dec = new_decision (first->position, &first->success); + new_dec->tests = first->tests->next; first->tests->next = NULL; } @@ -1652,14 +1439,14 @@ factor_tests (struct decision_head *head) if (next->tests->next != NULL) { - new = new_decision (next->position, &next->success); - new->tests = next->tests->next; + new_dec = new_decision (next->position, &next->success); + new_dec->tests = next->tests->next; next->tests->next = NULL; } - new = next; + new_dec = next; next = next->next; - new->next = NULL; - h.first = h.last = new; + new_dec->next = NULL; + h.first = h.last = new_dec; merge_trees (head, &h); } @@ -1793,42 +1580,31 @@ find_afterward (struct decision_head *head, struct decision *real_afterward) match multiple insns and we try to step past the end of the stream. */ static void -change_state (const char *oldpos, const char *newpos, const char *indent) +change_state (struct position *oldpos, struct position *newpos, + const char *indent) { - int odepth = strlen (oldpos); - int ndepth = strlen (newpos); - int depth; - int old_has_insn, new_has_insn; + while (oldpos->depth > newpos->depth) + oldpos = oldpos->base; - /* Pop up as many levels as necessary. */ - for (depth = odepth; strncmp (oldpos, newpos, depth) != 0; --depth) - continue; + if (oldpos != newpos) + switch (newpos->type) + { + case POS_PEEP2_INSN: + printf ("%stem = peep2_next_insn (%d);\n", indent, newpos->arg); + printf ("%sx%d = PATTERN (tem);\n", indent, newpos->depth); + break; - /* Hunt for the last [A-Z] in both strings. */ - for (old_has_insn = odepth - 1; old_has_insn >= 0; --old_has_insn) - if (ISUPPER (oldpos[old_has_insn])) - break; - for (new_has_insn = ndepth - 1; new_has_insn >= 0; --new_has_insn) - if (ISUPPER (newpos[new_has_insn])) - break; + case POS_XEXP: + change_state (oldpos, newpos->base, indent); + printf ("%sx%d = XEXP (x%d, %d);\n", + indent, newpos->depth, newpos->depth - 1, newpos->arg); + break; - /* Go down to desired level. */ - while (depth < ndepth) - { - /* It's a different insn from the first one. */ - if (ISUPPER (newpos[depth])) - { - printf ("%stem = peep2_next_insn (%d);\n", - indent, newpos[depth] - 'A'); - printf ("%sx%d = PATTERN (tem);\n", indent, depth + 1); - } - else if (ISLOWER (newpos[depth])) + case POS_XVECEXP0: + change_state (oldpos, newpos->base, indent); printf ("%sx%d = XVECEXP (x%d, 0, %d);\n", - indent, depth + 1, depth, newpos[depth] - 'a'); - else - printf ("%sx%d = XEXP (x%d, %c);\n", - indent, depth + 1, depth, newpos[depth]); - ++depth; + indent, newpos->depth, newpos->depth - 1, newpos->arg); + break; } } @@ -1940,7 +1716,8 @@ write_switch (struct decision *start, int depth) while (p && p->tests->type == DT_pred && p->tests->u.pred.data) { const struct pred_data *data = p->tests->u.pred.data; - RTX_CODE c; + int c; + for (c = 0; c < NUM_RTX_CODE; c++) if (codemap[c] && data->codes[c]) goto pred_done; @@ -1949,7 +1726,7 @@ write_switch (struct decision *start, int depth) if (data->codes[c]) { fputs (" case ", stdout); - print_code (c); + print_code ((enum rtx_code) c); fputs (":\n", stdout); codemap[c] = 1; } @@ -2200,12 +1977,13 @@ write_action (struct decision *p, struct decision_test *test, case PEEPHOLE2: { - int match_len = 0, i; + int match_len = 0; + struct position *pos; - for (i = strlen (p->position) - 1; i >= 0; --i) - if (ISUPPER (p->position[i])) + for (pos = p->position; pos; pos = pos->base) + if (pos->type == POS_PEEP2_INSN) { - match_len = p->position[i] - 'A'; + match_len = pos->arg; break; } printf ("%s*_pmatch_len = %d;\n", indent, match_len); @@ -2347,7 +2125,7 @@ write_tree_1 (struct decision_head *head, int depth, position at the node that branched to this node. */ static void -write_tree (struct decision_head *head, const char *prevpos, +write_tree (struct decision_head *head, struct position *prevpos, enum routine_type type, int initial) { struct decision *p = head->first; @@ -2389,10 +2167,8 @@ write_tree (struct decision_head *head, const char *prevpos, } else { - int depth = strlen (p->position); - change_state (prevpos, p->position, " "); - write_tree_1 (head, depth, type); + write_tree_1 (head, p->position->depth, type); for (p = head->first; p; p = p->next) if (p->success.first) @@ -2448,7 +2224,7 @@ peephole2%s (rtx x0 ATTRIBUTE_UNUSED,\n\trtx insn ATTRIBUTE_UNUSED,\n\tint *_pma printf (" recog_data.insn = NULL_RTX;\n"); if (head->first) - write_tree (head, "", type, 1); + write_tree (head, &root_pos, type, 1); else printf (" goto ret0;\n"); @@ -2489,12 +2265,11 @@ write_header (void) #include \"function.h\"\n\ #include \"insn-config.h\"\n\ #include \"recog.h\"\n\ -#include \"real.h\"\n\ #include \"output.h\"\n\ #include \"flags.h\"\n\ #include \"hard-reg-set.h\"\n\ #include \"resource.h\"\n\ -#include \"toplev.h\"\n\ +#include \"diagnostic-core.h\"\n\ #include \"reload.h\"\n\ #include \"regs.h\"\n\ #include \"tm-constrs.h\"\n\ @@ -2546,12 +2321,12 @@ make_insn_sequence (rtx insn, enum routine_type type) struct decision *last; struct decision_test *test, **place; struct decision_head head; - char c_test_pos[2]; + struct position *c_test_pos, **pos_ptr; /* We should never see an insn whose C test is false at compile time. */ gcc_assert (truth); - c_test_pos[0] = '\0'; + c_test_pos = &root_pos; if (type == PEEPHOLE2) { int i, j; @@ -2563,19 +2338,20 @@ make_insn_sequence (rtx insn, enum routine_type type) x = rtx_alloc (PARALLEL); PUT_MODE (x, VOIDmode); XVEC (x, 0) = rtvec_alloc (XVECLEN (insn, 0)); + pos_ptr = &peep2_insn_pos_list; for (i = j = 0; i < XVECLEN (insn, 0); i++) { rtx tmp = XVECEXP (insn, 0, i); if (GET_CODE (tmp) != MATCH_SCRATCH && GET_CODE (tmp) != MATCH_DUP) { + c_test_pos = next_position (pos_ptr, &root_pos, + POS_PEEP2_INSN, i); XVECEXP (x, 0, j) = tmp; j++; + pos_ptr = &c_test_pos->next; } } XVECLEN (x, 0) = j; - - c_test_pos[0] = 'A' + j - 1; - c_test_pos[1] = '\0'; } else if (XVECLEN (insn, type == RECOG) == 1) x = XVECEXP (insn, type == RECOG, 0); @@ -2589,7 +2365,7 @@ make_insn_sequence (rtx insn, enum routine_type type) validate_pattern (x, insn, NULL_RTX, 0); memset(&head, 0, sizeof(head)); - last = add_to_sequence (x, &head, "", type, 1); + last = add_to_sequence (x, &head, &root_pos, type, 1); /* Find the end of the test chain on the last node. */ for (test = last->tests; test->next; test = test->next) @@ -2637,25 +2413,26 @@ make_insn_sequence (rtx insn, enum routine_type type) if (i != XVECLEN (x, 0)) { - rtx new; + rtx new_rtx; struct decision_head clobber_head; /* Build a similar insn without the clobbers. */ if (i == 1) - new = XVECEXP (x, 0, 0); + new_rtx = XVECEXP (x, 0, 0); else { int j; - new = rtx_alloc (PARALLEL); - XVEC (new, 0) = rtvec_alloc (i); + new_rtx = rtx_alloc (PARALLEL); + XVEC (new_rtx, 0) = rtvec_alloc (i); for (j = i - 1; j >= 0; j--) - XVECEXP (new, 0, j) = XVECEXP (x, 0, j); + XVECEXP (new_rtx, 0, j) = XVECEXP (x, 0, j); } /* Recognize it. */ memset (&clobber_head, 0, sizeof(clobber_head)); - last = add_to_sequence (new, &clobber_head, "", type, 1); + last = add_to_sequence (new_rtx, &clobber_head, &root_pos, + type, 1); /* Find the end of the test chain on the last node. */ for (test = last->tests; test->next; test = test->next) @@ -2666,7 +2443,7 @@ make_insn_sequence (rtx insn, enum routine_type type) place = &test->next; if (test->type == DT_accept_op) { - last = new_decision ("", &last->success); + last = new_decision (&root_pos, &last->success); place = &last->tests; } @@ -2745,7 +2522,7 @@ main (int argc, char **argv) memset (&split_tree, 0, sizeof split_tree); memset (&peephole2_tree, 0, sizeof peephole2_tree); - if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE) + if (!init_rtx_reader_args (argc, argv)) return (FATAL_EXIT_CODE); next_insn_code = 0; @@ -2762,11 +2539,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); @@ -2786,7 +2558,7 @@ main (int argc, char **argv) } } - if (error_count || have_error) + if (have_error) return FATAL_EXIT_CODE; puts ("\n\n"); @@ -2913,13 +2685,13 @@ debug_decision_0 (struct decision *d, int indent, int maxdepth) debug_decision_0 (n, indent + 2, maxdepth - 1); } -void +DEBUG_FUNCTION void debug_decision (struct decision *d) { debug_decision_0 (d, 0, 1000000); } -void +DEBUG_FUNCTION void debug_decision_list (struct decision *d) { while (d)