/* Generate code from machine description to recognize rtl as insns.
- Copyright (C) 1987-1991 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1988, 1992 Free Software Foundation, Inc.
This file is part of GNU CC.
#define obstack_chunk_free free
extern void free ();
+extern rtx read_rtx ();
/* Data structure for a listhead of decision trees. The alternatives
to a node are kept in a doublely-linked list so we can easily add nodes
int test_elt_zero_int; /* Nonzero if should test XINT (rtl, 0) */
int elt_zero_int; /* Required value for XINT (rtl, 0) */
int test_elt_one_int; /* Nonzero if should test XINT (rtl, 1) */
- int elt_one_int; /* Required value for XINT (rtl, 2) */
+ int elt_one_int; /* Required value for XINT (rtl, 1) */
+ int test_elt_zero_wide; /* Nonzero if should test XWINT (rtl, 0) */
+ HOST_WIDE_INT elt_zero_wide; /* Required value for XWINT (rtl, 0) */
char *tests; /* If nonzero predicate to call */
int pred; /* `preds' index of predicate or -1 */
char *c_test; /* Additional test to perform */
new->veclen = 0;
new->test_elt_zero_int = 0;
new->test_elt_one_int = 0;
+ new->test_elt_zero_wide = 0;
new->elt_zero_int = 0;
new->elt_one_int = 0;
+ new->elt_zero_wide = 0;
new->tests = 0;
new->pred = -1;
new->c_test = 0;
new = add_to_sequence (XVECEXP (pattern, 2, i),
&new->success, newpos);
}
-
- this->success.first->enforce_mode = 0;
}
return new;
new = add_to_sequence (XVECEXP (pattern, 1, i),
&new->success, newpos);
}
- this->success.first->enforce_mode = 0;
return new;
case MATCH_DUP:
+ case MATCH_PAR_DUP:
new->dupno = XINT (pattern, 0);
new->code = UNKNOWN;
new->enforce_mode = 0;
this->test_elt_one_int = 1;
this->elt_one_int = XINT (pattern, i);
}
+ else if (fmt[i] == 'w' && i == 0)
+ {
+ this->test_elt_zero_wide = 1;
+ this->elt_zero_wide = XWINT (pattern, i);
+ }
else if (fmt[i] == 'E')
{
register int j;
&& d1->elt_zero_int != d2->elt_zero_int)
|| (d1->test_elt_one_int && d2->test_elt_one_int
&& d1->elt_one_int != d2->elt_one_int)
+ || (d1->test_elt_zero_wide && d2->test_elt_zero_wide
+ && d1->elt_zero_wide != d2->elt_zero_wide)
|| (d1->veclen && d2->veclen && d1->veclen != d2->veclen))
return 1;
for D1's predicate. */
if (d2->code != UNKNOWN)
{
- for (i = 0; i < NUM_RTX_CODE && preds[d1->pred].codes[i]; i++)
+ for (i = 0; i < NUM_RTX_CODE && preds[d1->pred].codes[i] != 0; i++)
if (preds[d1->pred].codes[i] == d2->code)
break;
else if (d2->pred >= 0)
{
- for (i = 0; i < NUM_RTX_CODE && preds[d1->pred].codes[i]; i++)
+ for (i = 0; i < NUM_RTX_CODE && preds[d1->pred].codes[i] != 0; i++)
{
for (j = 0; j < NUM_RTX_CODE; j++)
if (preds[d2->pred].codes[j] == 0
We would like to list nodes testing for specific codes before those
that test predicates to avoid unnecessary function calls. Similarly,
- tests for specific modes should preceed nodes that allow any mode.
+ tests for specific modes should precede nodes that allow any mode.
This function returns the merit (with 0 being the best) of inserting
a test involving the specified MODE and CODE after node P. If P is
would cause an infinite recursion. */
if (old->tests == 0 && old->test_elt_zero_int == 0
&& old->test_elt_one_int == 0 && old->veclen == 0
+ && old->test_elt_zero_wide == 0
&& old->dupno == -1 && old->mode == VOIDmode
&& old->code == UNKNOWN
&& (old->c_test != 0 || add->c_test != 0))
|| (old->pred >= 0 && old->pred == add->pred)
|| (old->tests && add->tests
&& !strcmp (old->tests, add->tests)))
- && old->test_elt_zero_int == add->test_elt_zero_int
- && old->elt_zero_int == add->elt_zero_int
- && old->test_elt_one_int == add->test_elt_one_int
- && old->elt_one_int == add->elt_one_int
- && old->veclen == add->veclen
- && old->dupno == add->dupno
- && old->opno == add->opno
- && old->code == add->code
- && old->enforce_mode == add->enforce_mode
- && old->mode == add->mode)
+ && old->test_elt_zero_int == add->test_elt_zero_int
+ && old->elt_zero_int == add->elt_zero_int
+ && old->test_elt_one_int == add->test_elt_one_int
+ && old->elt_one_int == add->elt_one_int
+ && old->test_elt_zero_wide == add->test_elt_zero_wide
+ && old->elt_zero_wide == add->elt_zero_wide
+ && old->veclen == add->veclen
+ && old->dupno == add->dupno
+ && old->opno == add->opno
+ && old->code == add->code
+ && old->enforce_mode == add->enforce_mode
+ && old->mode == add->mode)
{
/* If the additional test is not the same, split both nodes
into nodes that just contain all things tested before the
split->veclen = 0;
split->test_elt_zero_int = 0;
split->test_elt_one_int = 0;
+ split->test_elt_zero_wide = 0;
split->tests = 0;
split->pred = -1;
+ split->dupno = -1;
}
if (add->insn_code_number >= 0 || add->opno >= 0)
split->veclen = 0;
split->test_elt_zero_int = 0;
split->test_elt_one_int = 0;
+ split->test_elt_zero_wide = 0;
split->tests = 0;
split->pred = -1;
+ split->dupno = -1;
}
}
- old->success = merge_trees (old->success, add->success);
if (old->insn_code_number >= 0 && add->insn_code_number >= 0)
- fatal ("Two actions at one point in tree");
+ {
+ /* If one node is for a normal insn and the second is
+ for the base insn with clobbers stripped off, the
+ second node should be ignored. */
+
+ if (old->num_clobbers_to_add == 0
+ && add->num_clobbers_to_add > 0)
+ /* Nothing to do here. */
+ ;
+ else if (old->num_clobbers_to_add > 0
+ && add->num_clobbers_to_add == 0)
+ {
+ /* In this case, replace OLD with ADD. */
+ old->insn_code_number = add->insn_code_number;
+ old->num_clobbers_to_add = 0;
+ }
+ else
+ fatal ("Two actions at one point in tree");
+ }
+
if (old->insn_code_number == -1)
old->insn_code_number = add->insn_code_number;
+ old->success = merge_trees (old->success, add->success);
add = 0;
break;
}
if (best_position == 0)
abort ();
- if (old == 0 && position_merit (0, add_mode, add->code) < best_merit)
+ if (old == 0
+ && position_merit (NULL_PTR, add_mode, add->code) < best_merit)
{
add->prev = 0;
add->next = oldh.first;
printf ("x%d;\n", max_depth);
printf (" %s tem;\n", type == SPLIT ? "rtx" : "int");
- write_tree (tree, "", 0, 1, type);
+ write_tree (tree, "", NULL_PTR, 1, type);
printf (" ret0: return %d;\n}\n\n", type == SPLIT ? 0 : -1);
}
\f
of the same mode, we also group tests with the same code, followed by a
group that does not test a code.
- Occasionally, we cannot arbitarily reorder the tests so that multiple
+ Occasionally, we cannot arbitrarily reorder the tests so that multiple
sequence of groups as described above are present.
We generate two nested switch statements, the outer statement for
if (p->pred >= 0)
{
- for (i = 0; i < NUM_RTX_CODE && preds[p->pred].codes[i]; i++)
+ for (i = 0; i < NUM_RTX_CODE && preds[p->pred].codes[i] != 0; i++)
if (codemap[(int) preds[p->pred].codes[i]])
break;
if (code == MATCH_OPERAND)
{
- for (i = 0; i < NUM_RTX_CODE && preds[p->pred].codes[i]; i++)
+ for (i = 0; i < NUM_RTX_CODE && preds[p->pred].codes[i] != 0; i++)
{
printf ("%scase ", indents[indent - 2]);
print_code (preds[p->pred].codes[i]);
if ((mode != switch_mode && ! p->ignore_mode)
|| (p->code != switch_code && p->code != UNKNOWN && ! p->ignore_code)
- || p->test_elt_zero_int || p->test_elt_one_int || p->veclen
+ || p->test_elt_zero_int || p->test_elt_one_int
+ || p->test_elt_zero_wide || p->veclen
|| p->dupno >= 0 || p->tests || p->num_clobbers_to_add)
{
printf ("%sif (", indents[indent]);
printf ("XINT (x%d, 0) == %d && ", depth, p->elt_zero_int);
if (p->test_elt_one_int)
printf ("XINT (x%d, 1) == %d && ", depth, p->elt_one_int);
+ if (p->test_elt_zero_wide)
+ printf (
+#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
+ "XWINT (x%d, 0) == %d && ",
+#else
+ "XWINT (x%d, 0) == %ld && ",
+#endif
+ depth, p->elt_zero_wide);
if (p->veclen)
printf ("XVECLEN (x%d, 0) == %d && ", depth, p->veclen);
if (p->dupno >= 0)
fprintf (stderr, "genrecog: ");
fprintf (stderr, s, a1, a2);
fprintf (stderr, "\n");
- fprintf (stderr, "after %d instruction definitions\n", next_index);
+ fprintf (stderr, "after %d definitions\n", next_index);
exit (FATAL_EXIT_CODE);
}
struct decision_head recog_tree;
struct decision_head split_tree;
FILE *infile;
- extern rtx read_rtx ();
register int c;
obstack_init (rtl_obstack);