+/* Helper functions for insn elision. */
+
+/* Compute a hash function of a c_test structure, which is keyed
+ by its ->expr field. */
+hashval_t
+hash_c_test (const void *x)
+{
+ const struct c_test *a = (const struct c_test *) x;
+ const unsigned char *base, *s = (const unsigned char *) a->expr;
+ hashval_t hash;
+ unsigned char c;
+ unsigned int len;
+
+ base = s;
+ hash = 0;
+
+ while ((c = *s++) != '\0')
+ {
+ hash += c + (c << 17);
+ hash ^= hash >> 2;
+ }
+
+ len = s - base;
+ hash += len + (len << 17);
+ hash ^= hash >> 2;
+
+ return hash;
+}
+
+/* Compare two c_test expression structures. */
+int
+cmp_c_test (const void *x, const void *y)
+{
+ const struct c_test *a = (const struct c_test *) x;
+ const struct c_test *b = (const struct c_test *) y;
+
+ return !strcmp (a->expr, b->expr);
+}
+
+/* Given a string representing a C test expression, look it up in the
+ condition_table and report whether or not its value is known
+ at compile time. Returns a tristate: 1 for known true, 0 for
+ known false, -1 for unknown. */
+int
+maybe_eval_c_test (const char *expr)
+{
+ const struct c_test *test;
+ struct c_test dummy;
+
+ if (expr[0] == 0)
+ return 1;
+
+ dummy.expr = expr;
+ test = (const struct c_test *)htab_find (condition_table, &dummy);
+ if (!test)
+ return -1;
+ return test->value;
+}
+
+/* Record the C test expression EXPR in the condition_table, with
+ value VAL. Duplicates clobber previous entries. */
+
+void
+add_c_test (const char *expr, int value)
+{
+ struct c_test *test;
+
+ if (expr[0] == 0)
+ return;
+
+ test = XNEW (struct c_test);
+ test->expr = expr;
+ test->value = value;
+
+ *(htab_find_slot (condition_table, test, INSERT)) = test;
+}
+
+/* For every C test, call CALLBACK with two arguments: a pointer to
+ the condition structure and INFO. Stops when CALLBACK returns zero. */
+void
+traverse_c_tests (htab_trav callback, void *info)
+{
+ if (condition_table)
+ htab_traverse (condition_table, callback, info);
+}
+
+
+/* Given a string, return the number of comma-separated elements in it.
+ Return 0 for the null string. */
+int
+n_comma_elts (const char *s)
+{
+ int n;
+
+ if (*s == '\0')
+ return 0;
+
+ for (n = 1; *s; s++)
+ if (*s == ',')
+ n++;
+
+ return n;
+}
+
+/* Given a pointer to a (char *), return a pointer to the beginning of the
+ next comma-separated element in the string. Advance the pointer given
+ to the end of that element. Return NULL if at end of string. Caller
+ is responsible for copying the string if necessary. White space between
+ a comma and an element is ignored. */
+
+const char *
+scan_comma_elt (const char **pstr)
+{
+ const char *start;
+ const char *p = *pstr;
+
+ if (*p == ',')
+ p++;
+ while (ISSPACE(*p))
+ p++;
+
+ if (*p == '\0')
+ return NULL;
+
+ start = p;
+
+ while (*p != ',' && *p != '\0')
+ p++;
+
+ *pstr = p;
+ return start;
+}
+
+/* Helper functions for define_predicate and define_special_predicate
+ processing. Shared between genrecog.c and genpreds.c. */
+
+static htab_t predicate_table;
+struct pred_data *first_predicate;
+static struct pred_data **last_predicate = &first_predicate;
+
+static hashval_t
+hash_struct_pred_data (const void *ptr)
+{
+ return htab_hash_string (((const struct pred_data *)ptr)->name);
+}
+
+static int
+eq_struct_pred_data (const void *a, const void *b)
+{
+ return !strcmp (((const struct pred_data *)a)->name,
+ ((const struct pred_data *)b)->name);
+}
+
+struct pred_data *
+lookup_predicate (const char *name)