/* 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.
#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. */
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. */
/* 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
{
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. */
/* 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;
\f
-/* 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 *);
+\f
+/* 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];
- 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, i);
-
- 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
-\f
-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 *);
-\f
/* 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. */
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:
&& 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));
}
}
/* 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. */
&& 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");
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:
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;
+ if (pos->depth > max_depth)
+ max_depth = pos->depth;
- subpos = xmalloc (depth + 2);
- strcpy (subpos, position);
- subpos[depth + 1] = 0;
-
- 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);
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;
}
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;
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;
}
/* 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;
}
default:
gcc_unreachable ();
}
+ subpos_ptr = &subpos->next;
}
fini:
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;
}
\f
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])
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);
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;
}
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++;
}
}
}
/* 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)
{
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;
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;
}
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);
}
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;
}
}
\f
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;
if (data->codes[c])
{
fputs (" case ", stdout);
- print_code (c);
+ print_code ((enum rtx_code) c);
fputs (":\n", stdout);
codemap[c] = 1;
}
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);
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;
}
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)
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");
#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\
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;
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, j);
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);
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)
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)
place = &test->next;
if (test->type == DT_accept_op)
{
- last = new_decision ("", &last->success);
+ last = new_decision (&root_pos, &last->success);
place = &last->tests;
}
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;
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);
}
}
- if (error_count || have_error)
+ if (have_error)
return FATAL_EXIT_CODE;
puts ("\n\n");
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)