struct id_base : nofree_ptr_hash<id_base>
{
- enum id_kind { CODE, FN, PREDICATE, USER } kind;
+ enum id_kind { CODE, FN, PREDICATE, USER, NULL_ID } kind;
id_base (id_kind, const char *, int = -1);
&& strcmp (op1->id, op2->id) == 0);
}
+/* The special id "null", which matches nothing. */
+static id_base *null_id;
+
/* Hashtable of known pattern operators. This is pre-seeded from
all known tree codes and all known builtin function ids. */
static hash_table<id_base> *operators;
return false;
}
-/* Lookup the identifier ID. */
+/* Lookup the identifier ID. Allow "null" if ALLOW_NULL. */
id_base *
-get_operator (const char *id)
+get_operator (const char *id, bool allow_null = false)
{
+ if (allow_null && strcmp (id, "null") == 0)
+ return null_id;
+
id_base tem (id_base::CODE, id);
id_base *op = operators->find_with_hash (&tem, tem.hashval);
}
}
+/* Return true if O refers to ID. */
+
+bool
+contains_id (operand *o, user_id *id)
+{
+ if (capture *c = dyn_cast<capture *> (o))
+ return c->what && contains_id (c->what, id);
+
+ if (expr *e = dyn_cast<expr *> (o))
+ {
+ if (e->operation == id)
+ return true;
+ for (unsigned i = 0; i < e->ops.length (); ++i)
+ if (contains_id (e->ops[i], id))
+ return true;
+ return false;
+ }
+
+ if (with_expr *w = dyn_cast <with_expr *> (o))
+ return (contains_id (w->with, id)
+ || contains_id (w->subexpr, id));
+
+ if (if_expr *ife = dyn_cast <if_expr *> (o))
+ return (contains_id (ife->cond, id)
+ || contains_id (ife->trueexpr, id)
+ || (ife->falseexpr && contains_id (ife->falseexpr, id)));
+
+ if (c_expr *ce = dyn_cast<c_expr *> (o))
+ return ce->capture_ids && ce->capture_ids->get (id->id);
+
+ return false;
+}
+
+
/* In AST operand O replace operator ID with operator WITH. */
operand *
operand *result_op = s->result;
vec<std::pair<user_id *, id_base *> > subst;
subst.create (n_ids);
+ bool skip = false;
for (unsigned i = 0; i < n_ids; ++i)
{
user_id *id = ids[i];
id_base *oper = id->substitutes[j % id->substitutes.length ()];
+ if (oper == null_id
+ && (contains_id (match_op, id)
+ || contains_id (result_op, id)))
+ {
+ skip = true;
+ break;
+ }
subst.quick_push (std::make_pair (id, oper));
match_op = replace_id (match_op, id, oper);
if (result_op
&& !can_delay_subst)
result_op = replace_id (result_op, id, oper);
}
+ if (skip)
+ {
+ subst.release ();
+ continue;
+ }
simplify *ns = new simplify (s->kind, match_op, result_op,
vNULL, s->capture_ids);
ns->for_subst_vec.safe_splice (s->for_subst_vec);
/* Insert the user defined operators into the operator hash. */
const char *id = get_ident ();
- if (get_operator (id) != NULL)
+ if (get_operator (id, true) != NULL)
fatal_at (token, "operator already defined");
user_id *op = new user_id (id);
id_base **slot = operators->find_slot_with_hash (op, op->hashval, INSERT);
while ((token = peek_ident ()) != 0)
{
const char *oper = get_ident ();
- id_base *idb = get_operator (oper);
+ id_base *idb = get_operator (oper, true);
if (idb == NULL)
fatal_at (token, "no such operator '%s'", oper);
if (*idb == CONVERT0 || *idb == CONVERT1 || *idb == CONVERT2
const cpp_token *token = peek ();
const char *id = get_ident ();
- if (get_operator (id) != 0)
+ if (get_operator (id, true) != 0)
fatal_at (token, "operator %s already defined", id);
user_id *op = new user_id (id, true);
{
token = peek ();
const char *oper = get_ident ();
- id_base *idb = get_operator (oper);
+ id_base *idb = get_operator (oper, true);
if (idb == 0)
fatal_at (token, "no such operator '%s'", oper);
cpp_define (r, gimple ? "GIMPLE=1": "GENERIC=1");
cpp_define (r, gimple ? "GENERIC=0": "GIMPLE=0");
+ null_id = new id_base (id_base::NULL_ID, "null");
+
/* Pre-seed operators. */
operators = new hash_table<id_base> (1024);
#define DEFTREECODE(SYM, STRING, TYPE, NARGS) \