/* Generate code from machine description to recognize rtl as insns.
- Copyright (C) 1987, 88, 92-95, 97-98, 1999 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1997, 1998,
+ 1999, 2000 Free Software Foundation, Inc.
This file is part of GNU CC.
{"address_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
LABEL_REF, SUBREG, REG, MEM, PLUS, MINUS, MULT}},
{"register_operand", {SUBREG, REG}},
+ {"pmode_register_operand", {SUBREG, REG}},
{"scratch_operand", {SCRATCH, REG}},
{"immediate_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
LABEL_REF}},
#define NUM_KNOWN_PREDS (sizeof preds / sizeof preds[0])
+static const char * special_mode_pred_table[] = {
+#ifdef SPECIAL_MODE_PREDICATES
+ SPECIAL_MODE_PREDICATES
+#endif
+ "pmode_register_operand"
+};
+
+#define NUM_SPECIAL_MODE_PREDS \
+ (sizeof (special_mode_pred_table) / sizeof (special_mode_pred_table[0]))
+
+static void message_with_line
+ PARAMS ((int, const char *, ...)) ATTRIBUTE_PRINTF_2;
+
static struct decision *new_decision
- PROTO((const char *, struct decision_head *));
+ PARAMS ((const char *, struct decision_head *));
static struct decision_test *new_decision_test
- PROTO((enum decision_type, struct decision_test ***));
+ PARAMS ((enum decision_type, struct decision_test ***));
+static rtx find_operand
+ PARAMS ((rtx, int));
static void validate_pattern
- PROTO((rtx, int));
+ PARAMS ((rtx, rtx, rtx));
static struct decision *add_to_sequence
- PROTO((rtx, struct decision_head *, const char *, enum routine_type, int));
+ PARAMS ((rtx, struct decision_head *, const char *, enum routine_type, int));
static int maybe_both_true_2
- PROTO((struct decision_test *, struct decision_test *));
+ PARAMS ((struct decision_test *, struct decision_test *));
static int maybe_both_true_1
- PROTO((struct decision_test *, struct decision_test *));
+ PARAMS ((struct decision_test *, struct decision_test *));
static int maybe_both_true
- PROTO((struct decision *, struct decision *, int));
+ PARAMS ((struct decision *, struct decision *, int));
static int nodes_identical_1
- PROTO((struct decision_test *, struct decision_test *));
+ PARAMS ((struct decision_test *, struct decision_test *));
static int nodes_identical
- PROTO((struct decision *, struct decision *));
+ PARAMS ((struct decision *, struct decision *));
static void merge_accept_insn
- PROTO((struct decision *, struct decision *));
+ PARAMS ((struct decision *, struct decision *));
static void merge_trees
- PROTO((struct decision_head *, struct decision_head *));
+ PARAMS ((struct decision_head *, struct decision_head *));
static void factor_tests
- PROTO((struct decision_head *));
+ PARAMS ((struct decision_head *));
static void simplify_tests
- PROTO((struct decision_head *));
+ PARAMS ((struct decision_head *));
static int break_out_subroutines
- PROTO((struct decision_head *, int));
+ PARAMS ((struct decision_head *, int));
static void find_afterward
- PROTO((struct decision_head *, struct decision *));
+ PARAMS ((struct decision_head *, struct decision *));
static void change_state
- PROTO((const char *, const char *, struct decision *, const char *));
+ PARAMS ((const char *, const char *, struct decision *, const char *));
static void print_code
- PROTO((enum rtx_code));
+ PARAMS ((enum rtx_code));
static void write_afterward
- PROTO((struct decision *, struct decision *, const char *));
+ PARAMS ((struct decision *, struct decision *, const char *));
static struct decision *write_switch
- PROTO((struct decision *, int));
+ PARAMS ((struct decision *, int));
static void write_cond
- PROTO((struct decision_test *, int, enum routine_type));
+ PARAMS ((struct decision_test *, int, enum routine_type));
static void write_action
- PROTO((struct decision_test *, int, int, struct decision *,
+ PARAMS ((struct decision_test *, int, int, struct decision *,
enum routine_type));
static int is_unconditional
- PROTO((struct decision_test *, enum routine_type));
+ PARAMS ((struct decision_test *, enum routine_type));
static int write_node
- PROTO((struct decision *, int, enum routine_type));
+ PARAMS ((struct decision *, int, enum routine_type));
static void write_tree_1
- PROTO((struct decision_head *, int, enum routine_type));
+ PARAMS ((struct decision_head *, int, enum routine_type));
static void write_tree
- PROTO((struct decision_head *, const char *, enum routine_type, int));
+ PARAMS ((struct decision_head *, const char *, enum routine_type, int));
static void write_subroutine
- PROTO((struct decision_head *, enum routine_type));
+ PARAMS ((struct decision_head *, enum routine_type));
static void write_subroutines
- PROTO((struct decision_head *, enum routine_type));
+ PARAMS ((struct decision_head *, enum routine_type));
static void write_header
- PROTO((void));
+ PARAMS ((void));
static struct decision_head make_insn_sequence
- PROTO((rtx, enum routine_type));
+ PARAMS ((rtx, enum routine_type));
static void process_tree
- PROTO((struct decision_head *, enum routine_type));
+ PARAMS ((struct decision_head *, enum routine_type));
static void record_insn_name
- PROTO((int, const char *));
+ PARAMS ((int, const char *));
+static void debug_decision_0
+ PARAMS ((struct decision *, int, int));
static void debug_decision_1
- PROTO((struct decision *, int));
+ PARAMS ((struct decision *, int));
static void debug_decision_2
- PROTO((struct decision_test *));
+ PARAMS ((struct decision_test *));
extern void debug_decision
- PROTO((struct decision *));
+ PARAMS ((struct decision *));
+extern void debug_decision_list
+ PARAMS ((struct decision *));
\f
static void
-message_with_line VPROTO ((int lineno, const char *msg, ...))
+message_with_line VPARAMS ((int lineno, const char *msg, ...))
{
#ifndef ANSI_PROTOTYPES
int lineno;
return test;
}
-/* Check for various errors in patterns. */
+/* Search for and return operand N. */
-static void
-validate_pattern (pattern, set_dest)
+static rtx
+find_operand (pattern, n)
rtx pattern;
- int set_dest;
+ int n;
{
const char *fmt;
RTX_CODE code;
int i, j, len;
+ rtx r;
+
+ code = GET_CODE (pattern);
+ if ((code == MATCH_SCRATCH
+ || code == MATCH_INSN
+ || code == MATCH_OPERAND
+ || code == MATCH_OPERATOR
+ || code == MATCH_PARALLEL)
+ && XINT (pattern, 0) == n)
+ return pattern;
+
+ fmt = GET_RTX_FORMAT (code);
+ len = GET_RTX_LENGTH (code);
+ for (i = 0; i < len; i++)
+ {
+ switch (fmt[i])
+ {
+ case 'e': case 'u':
+ if ((r = find_operand (XEXP (pattern, i), n)) != NULL_RTX)
+ return r;
+ break;
+
+ case 'E':
+ for (j = 0; j < XVECLEN (pattern, i); j++)
+ if ((r = find_operand (XVECEXP (pattern, i, j), n)) != NULL_RTX)
+ return r;
+ break;
+
+ case 'i': case 'w': case '0': case 's':
+ break;
+
+ default:
+ abort ();
+ }
+ }
+
+ return NULL;
+}
+
+/* Check for various errors in patterns. SET is nonnull for a destination,
+ and is the complete set pattern. */
+
+static void
+validate_pattern (pattern, insn, set)
+ rtx pattern;
+ rtx insn;
+ rtx set;
+{
+ const char *fmt;
+ RTX_CODE code;
+ size_t i, len;
+ int j;
code = GET_CODE (pattern);
switch (code)
{
case MATCH_SCRATCH:
- case MATCH_INSN:
return;
+ case MATCH_INSN:
case MATCH_OPERAND:
+ case MATCH_OPERATOR:
{
const char *pred_name = XSTR (pattern, 1);
+ int allows_non_lvalue = 1, allows_non_const = 1;
+ int special_mode_pred = 0;
+ const char *c_test;
+
+ if (GET_CODE (insn) == DEFINE_INSN)
+ c_test = XSTR (insn, 2);
+ else
+ c_test = XSTR (insn, 1);
if (pred_name[0] != 0)
{
- /* See if we know about this predicate and save its number. If
- we do, and it only accepts one code, note that fact. The
- predicate `const_int_operand' only tests for a CONST_INT, so
- if we do so we can avoid calling it at all.
-
- Finally, if we know that the predicate does not allow
- CONST_INT, we know that the only way the predicate can match
- is if the modes match (here we use the kludge of relying on
- the fact that "address_operand" accepts CONST_INT; otherwise,
- it would have to be a special case), so we can test the mode
- (but we need not). This fact should considerably simplify the
- generated code. */
-
- for (i = 0; i < (int) NUM_KNOWN_PREDS; i++)
+ for (i = 0; i < NUM_KNOWN_PREDS; i++)
if (! strcmp (preds[i].name, pred_name))
break;
- if (i < (int) NUM_KNOWN_PREDS)
+ if (i < NUM_KNOWN_PREDS)
{
- int j, allows_const_int;
+ int j;
- allows_const_int = 0;
+ allows_non_lvalue = allows_non_const = 0;
for (j = 0; preds[i].codes[j] != 0; j++)
- if (preds[i].codes[j] == CONST_INT)
- {
- allows_const_int = 1;
- break;
- }
-
- if (allows_const_int && set_dest)
{
- message_with_line (pattern_lineno,
- "warning: `%s' accepts const_int,",
- pred_name);
- message_with_line (pattern_lineno,
- " and used as destination of a set");
+ RTX_CODE c = preds[i].codes[j];
+ if (c != LABEL_REF
+ && c != SYMBOL_REF
+ && c != CONST_INT
+ && c != CONST_DOUBLE
+ && c != CONST
+ && c != HIGH
+ && c != CONSTANT_P_RTX)
+ allows_non_const = 1;
+
+ if (c != REG
+ && c != SUBREG
+ && c != MEM
+ && c != CONCAT
+ && c != PARALLEL
+ && c != STRICT_LOW_PART)
+ allows_non_lvalue = 1;
}
}
else
#ifdef PREDICATE_CODES
/* If the port has a list of the predicates it uses but
omits one, warn. */
- message_with_line (pattern_lineno, "warning: `%s' not in PREDICATE_CODES", pred_name);
+ message_with_line (pattern_lineno,
+ "warning: `%s' not in PREDICATE_CODES",
+ pred_name);
#endif
}
+
+ for (i = 0; i < NUM_SPECIAL_MODE_PREDS; ++i)
+ if (strcmp (pred_name, special_mode_pred_table[i]) == 0)
+ {
+ special_mode_pred = 1;
+ break;
+ }
+ }
+
+ /* A MATCH_OPERAND that is a SET should have an output reload. */
+ if (set
+ && code == MATCH_OPERAND
+ && XSTR (pattern, 2)[0] != '\0'
+ && XSTR (pattern, 2)[0] != '='
+ && XSTR (pattern, 2)[0] != '+')
+ {
+ message_with_line (pattern_lineno,
+ "operand %d missing output reload",
+ XINT (pattern, 0));
+ error_count++;
+ }
+
+ /* Allowing non-lvalues in destinations -- particularly CONST_INT --
+ while not likely to occur at runtime, results in less efficient
+ code from insn-recog.c. */
+ if (set
+ && pred_name[0] != '\0'
+ && allows_non_lvalue)
+ {
+ message_with_line (pattern_lineno,
+ "warning: destination operand %d allows non-lvalue",
+ XINT (pattern, 0));
}
+ /* A modeless MATCH_OPERAND can be handy when we can
+ check for multiple modes in the c_test. In most other cases,
+ it is a mistake. Only DEFINE_INSN is eligible, since SPLIT
+ and PEEP2 can FAIL within the output pattern. Exclude
+ address_operand, since its mode is related to the mode of
+ the memory not the operand. Exclude the SET_DEST of a call
+ instruction, as that is a common idiom. */
+
+ if (GET_MODE (pattern) == VOIDmode
+ && code == MATCH_OPERAND
+ && GET_CODE (insn) == DEFINE_INSN
+ && allows_non_const
+ && ! special_mode_pred
+ && pred_name[0] != '\0'
+ && strcmp (pred_name, "address_operand") != 0
+ && strstr (c_test, "operands") == NULL
+ && ! (set
+ && GET_CODE (set) == SET
+ && GET_CODE (SET_SRC (set)) == CALL))
+ {
+ message_with_line (pattern_lineno,
+ "warning: operand %d missing mode?",
+ XINT (pattern, 0));
+ }
return;
}
case SET:
- /* The operands of a SET must have the same mode unless one
- is VOIDmode. */
- if (GET_MODE (SET_SRC (pattern)) != VOIDmode
- && GET_MODE (SET_DEST (pattern)) != VOIDmode
- && GET_MODE (SET_SRC (pattern)) != GET_MODE (SET_DEST (pattern))
- /* The mode of an ADDRESS_OPERAND is the mode of the memory
- reference, not the mode of the address. */
- && ! (GET_CODE (SET_SRC (pattern)) == MATCH_OPERAND
- && ! strcmp (XSTR (SET_SRC (pattern), 1), "address_operand")))
- {
- message_with_line (pattern_lineno,
- "mode mismatch in set: %smode vs %smode",
- GET_MODE_NAME (GET_MODE (SET_DEST (pattern))),
- GET_MODE_NAME (GET_MODE (SET_SRC (pattern))));
- error_count++;
- }
+ {
+ enum machine_mode dmode, smode;
+ rtx dest, src;
+
+ dest = SET_DEST (pattern);
+ src = SET_SRC (pattern);
+
+ /* Find the referant for a DUP. */
+
+ if (GET_CODE (dest) == MATCH_DUP
+ || GET_CODE (dest) == MATCH_OP_DUP
+ || GET_CODE (dest) == MATCH_PAR_DUP)
+ dest = find_operand (insn, XINT (dest, 0));
+
+ if (GET_CODE (src) == MATCH_DUP
+ || GET_CODE (src) == MATCH_OP_DUP
+ || GET_CODE (src) == MATCH_PAR_DUP)
+ src = find_operand (insn, XINT (src, 0));
+
+ /* STRICT_LOW_PART is a wrapper. Its argument is the real
+ destination, and it's mode should match the source. */
+ if (GET_CODE (dest) == STRICT_LOW_PART)
+ dest = XEXP (dest, 0);
+
+ dmode = GET_MODE (dest);
+ smode = GET_MODE (src);
- validate_pattern (SET_DEST (pattern), 1);
- validate_pattern (SET_SRC (pattern), 0);
+ /* The mode of an ADDRESS_OPERAND is the mode of the memory
+ reference, not the mode of the address. */
+ if (GET_CODE (src) == MATCH_OPERAND
+ && ! strcmp (XSTR (src, 1), "address_operand"))
+ ;
+
+ /* 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++;
+ }
+
+ /* If only one of the operands is VOIDmode, and PC or CC0 is
+ not involved, it's probably a mistake. */
+ else if (dmode != smode
+ && GET_CODE (dest) != PC
+ && GET_CODE (dest) != CC0
+ && GET_CODE (src) != PC
+ && GET_CODE (src) != CC0
+ && GET_CODE (src) != CONST_INT)
+ {
+ const char *which;
+ which = (dmode == VOIDmode ? "destination" : "source");
+ message_with_line (pattern_lineno,
+ "warning: %s missing a mode?", which);
+ }
+
+ if (dest != SET_DEST (pattern))
+ validate_pattern (dest, insn, pattern);
+ validate_pattern (SET_DEST (pattern), insn, pattern);
+ validate_pattern (SET_SRC (pattern), insn, NULL_RTX);
+ return;
+ }
+
+ case CLOBBER:
+ validate_pattern (SET_DEST (pattern), insn, pattern);
return;
-
+
case LABEL_REF:
if (GET_MODE (XEXP (pattern, 0)) != VOIDmode)
{
switch (fmt[i])
{
case 'e': case 'u':
- validate_pattern (XEXP (pattern, i), 0);
+ validate_pattern (XEXP (pattern, i), insn, NULL_RTX);
break;
case 'E':
for (j = 0; j < XVECLEN (pattern, i); j++)
- validate_pattern (XVECEXP (pattern, i, j), 0);
+ validate_pattern (XVECEXP (pattern, i, j), insn, NULL_RTX);
break;
case 'i': case 'w': case '0': case 's':
abort ();
}
}
-
}
/* Create a chain of nodes to verify that an rtl expression matches
{
if (d2->type == DT_mode)
{
- if (d1->u.pred.mode != d2->u.mode)
- return 0;
- }
- else if (d2->type == DT_pred)
- {
- if (d2->u.pred.mode != VOIDmode
- && d1->u.pred.mode != d2->u.pred.mode)
+ if (d1->u.pred.mode != d2->u.mode
+ /* The mode of an address_operand predicate is the
+ mode of the memory, not the operand. It can only
+ be used for testing the predicate, so we must
+ ignore it here. */
+ && strcmp (d1->u.pred.name, "address_operand") != 0)
return 0;
}
+ /* Don't check two predicate modes here, because if both predicates
+ accept CONST_INT, then both can still be true even if the modes
+ are different. If they don't accept CONST_INT, there will be a
+ separate DT_mode that will make maybe_both_true_1 return 0. */
}
if (d1->u.pred.index >= 0)
}
/* For success, they should now both be null. */
- return t1 == t2;
+ if (t1 != t2)
+ return 0;
+
+ /* Check that their subnodes are at the same position, as any one set
+ of sibling decisions must be at the same position. */
+ if (d1->success.first
+ && d2->success.first
+ && strcmp (d1->success.first->position, d2->success.first->position))
+ return 0;
+
+ return 1;
}
/* A subroutine of merge_trees; given two nodes that have been declared
for (old_has_insn = odepth - 1; old_has_insn >= 0; --old_has_insn)
if (oldpos[old_has_insn] >= 'A' && oldpos[old_has_insn] <= 'Z')
break;
- for (new_has_insn = odepth - 1; new_has_insn >= 0; --new_has_insn)
+ for (new_has_insn = ndepth - 1; new_has_insn >= 0; --new_has_insn)
if (newpos[new_has_insn] >= 'A' && newpos[new_has_insn] <= 'Z')
break;
- /* Make sure to reset the _last_insn pointer when popping back up. */
+ /* Make sure to reset the last_insn pointer when popping back up. */
if (old_has_insn >= 0 && new_has_insn < 0)
- printf ("%s_last_insn = insn;\n", indent);
+ printf ("%slast_insn = insn;\n", indent);
/* Go down to desired level. */
while (depth < ndepth)
/* We can only fail if we're moving down the tree. */
if (old_has_insn >= 0 && oldpos[old_has_insn] >= newpos[depth])
{
- printf ("%s_last_insn = recog_next_insn (insn, %d);\n",
+ printf ("%slast_insn = recog_next_insn (insn, %d);\n",
indent, newpos[depth] - 'A');
}
else
printf ("%s goto L%d;\n", indent, afterward->number);
else
printf ("%s goto ret0;\n", indent);
- printf ("%s_last_insn = tem;\n", indent);
+ printf ("%slast_insn = tem;\n", indent);
}
- printf ("%sx%d = PATTERN (_last_insn);\n", indent, depth + 1);
+ printf ("%sx%d = PATTERN (last_insn);\n", indent, depth + 1);
}
else if (newpos[depth] >= 'a' && newpos[depth] <= 'z')
printf ("%sx%d = XVECEXP (x%d, 0, %d);\n",
{
char codemap[NUM_RTX_CODE];
struct decision *ret;
+ RTX_CODE code;
memset (codemap, 0, sizeof(codemap));
printf (" switch (GET_CODE (x%d))\n {\n", depth);
+ code = p->tests->u.code;
do
{
- RTX_CODE code = p->tests->u.code;
printf (" case ");
print_code (code);
printf (":\n goto L%d;\n", p->success.first->number);
codemap[code] = 1;
p = p->next;
}
- while (p && p->tests->type == DT_code && !p->tests->next);
+ while (p
+ && ! p->tests->next
+ && p->tests->type == DT_code
+ && ! codemap[code = p->tests->u.code]);
/* If P is testing a predicate that we know about and we haven't
seen any of the codes that are valid for the predicate, we can
|| type == DT_elt_one_int
|| type == DT_elt_zero_wide)
{
- const char *str;
-
printf (" switch (");
switch (type)
{
case DT_mode:
- str = "GET_MODE (x%d)";
+ printf ("GET_MODE (x%d)", depth);
break;
case DT_veclen:
- str = "XVECLEN (x%d, 0)";
+ printf ("XVECLEN (x%d, 0)", depth);
break;
case DT_elt_zero_int:
- str = "XINT (x%d, 0)";
+ printf ("XINT (x%d, 0)", depth);
break;
case DT_elt_one_int:
- str = "XINT (x%d, 1)";
+ printf ("XINT (x%d, 1)", depth);
break;
case DT_elt_zero_wide:
- str = "XWINT (x%d, 0)";
+ /* Convert result of XWINT to int for portability since some C
+ compilers won't do it and some will. */
+ printf ("(int) XWINT (x%d, 0)", depth);
break;
default:
abort ();
}
- printf (str, depth);
printf (")\n {\n");
do
struct decision_head *head;
enum routine_type type;
{
- static const char * const proto_pattern[] = {
- "%sint recog%s PROTO ((rtx, rtx, int *));\n",
- "%srtx split%s PROTO ((rtx, rtx));\n",
- "%srtx peephole2%s PROTO ((rtx, rtx, rtx *));\n"
- };
-
- static const char * const decl_pattern[] = {
-"%sint\n\
-recog%s (x0, insn, pnum_clobbers)\n\
- register rtx x0;\n\
- rtx insn ATTRIBUTE_UNUSED;\n\
- int *pnum_clobbers ATTRIBUTE_UNUSED;\n",
-
-"%srtx\n\
-split%s (x0, insn)\n\
- register rtx x0;\n\
- rtx insn ATTRIBUTE_UNUSED;\n",
-
-"%srtx\n\
-peephole2%s (x0, insn, _plast_insn)\n\
- register rtx x0;\n\
- rtx insn ATTRIBUTE_UNUSED;\n\
- rtx *_plast_insn ATTRIBUTE_UNUSED;\n"
- };
-
int subfunction = head->first ? head->first->subroutine_number : 0;
const char *s_or_e;
char extension[32];
else
strcpy (extension, "_insns");
- printf (proto_pattern[type], s_or_e, extension);
- printf (decl_pattern[type], s_or_e, extension);
+ switch (type)
+ {
+ case RECOG:
+ printf ("%sint recog%s PARAMS ((rtx, rtx, int *));\n", s_or_e, extension);
+ printf ("%sint\n\
+recog%s (x0, insn, pnum_clobbers)\n\
+ register rtx x0;\n\
+ rtx insn ATTRIBUTE_UNUSED;\n\
+ int *pnum_clobbers ATTRIBUTE_UNUSED;\n", s_or_e, extension);
+ break;
+ case SPLIT:
+ printf ("%srtx split%s PARAMS ((rtx, rtx));\n", s_or_e, extension);
+ printf ("%srtx\n\
+split%s (x0, insn)\n\
+ register rtx x0;\n\
+ rtx insn ATTRIBUTE_UNUSED;\n", s_or_e, extension);
+ break;
+ case PEEPHOLE2:
+ printf ("%srtx peephole2%s PARAMS ((rtx, rtx, rtx *));\n", s_or_e, extension);
+ printf ("%srtx\n\
+peephole2%s (x0, insn, _plast_insn)\n\
+ register rtx x0;\n\
+ rtx insn ATTRIBUTE_UNUSED;\n\
+ rtx *_plast_insn ATTRIBUTE_UNUSED;\n", s_or_e, extension);
+ break;
+ }
- printf ("{\n register rtx * const operands = &recog_data.operand[0];\n");
+ printf ("{\n register rtx * const operands ATTRIBUTE_UNUSED = &recog_data.operand[0];\n");
for (i = 1; i <= max_depth; i++)
printf (" register rtx x%d ATTRIBUTE_UNUSED;\n", i);
if (type == PEEPHOLE2)
- printf (" register rtx _last_insn = insn;\n");
+ printf (" register rtx last_insn = insn;\n");
printf (" %s tem ATTRIBUTE_UNUSED;\n", IS_SPLIT (type) ? "rtx" : "int");
if (head->first)
printf (" goto ret0;\n");
if (type == PEEPHOLE2)
- printf (" ret1:\n *_plast_insn = _last_insn;\n return tem;\n");
+ printf (" ret1:\n *_plast_insn = last_insn;\n return tem;\n");
printf (" ret0:\n return %d;\n}\n\n", IS_SPLIT (type) ? 0 : -1);
}
struct decision *last;
struct decision_test *test, **place;
struct decision_head head;
+ char *c_test_pos = "";
record_insn_name (next_insn_code, (type == RECOG ? XSTR (insn, 0) : NULL));
}
}
XVECLEN (x, 0) = j;
+
+ c_test_pos = alloca (2);
+ 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);
PUT_MODE (x, VOIDmode);
}
- validate_pattern (x, 0);
+ validate_pattern (x, insn, NULL_RTX);
memset(&head, 0, sizeof(head));
last = add_to_sequence (x, &head, "", type, 1);
/* Need a new node if we have another test to add. */
if (test->type == DT_accept_op)
{
- last = new_decision ("", &last->success);
+ last = new_decision (c_test_pos, &last->success);
place = &last->tests;
}
test = new_decision_test (DT_c_test, &place);
case SPLIT:
/* Define the subroutine we will call below and emit in genemit. */
- printf ("extern rtx gen_split_%d PROTO ((rtx *));\n", next_insn_code);
+ printf ("extern rtx gen_split_%d PARAMS ((rtx *));\n", next_insn_code);
break;
case PEEPHOLE2:
/* Define the subroutine we will call below and emit in genemit. */
- printf ("extern rtx gen_peephole2_%d PROTO ((rtx, rtx *));\n",
+ printf ("extern rtx gen_peephole2_%d PARAMS ((rtx, rtx *));\n",
next_insn_code);
break;
}
struct decision_head *head;
enum routine_type subroutine_type;
{
- if (head->first != NULL)
+ if (head->first == NULL)
+ {
+ /* We can elide peephole2_insns, but not recog or split_insns. */
+ if (subroutine_type == PEEPHOLE2)
+ return;
+ }
+ else
{
factor_tests (head);
- simplify_tests (head);
next_subroutine_number = 0;
break_out_subroutines (head, 1);
find_afterward (head, NULL);
+ /* We run this after find_afterward, because find_afterward needs
+ the redundant DT_mode tests on predicates to determine whether
+ two tests can both be true or not. */
+ simplify_tests(head);
+
write_subroutines (head, subroutine_type);
}
+
write_subroutine (head, subroutine_type);
}
\f
+extern int main PARAMS ((int, char **));
+
int
main (argc, argv)
int argc;
debug_decision_2 (test);
}
}
- fprintf (stderr, "} %d\n", d->number);
+ fprintf (stderr, "} %d n %d a %d\n", d->number,
+ (d->next ? d->next->number : -1),
+ (d->afterward ? d->afterward->number : -1));
}
static void