return false;
}
+/* Return true if CODE is a comparison. */
+
+bool
+comparison_code_p (enum tree_code code)
+{
+ switch (code)
+ {
+ case EQ_EXPR:
+ case NE_EXPR:
+ case ORDERED_EXPR:
+ case UNORDERED_EXPR:
+ case LTGT_EXPR:
+ case UNEQ_EXPR:
+ case GT_EXPR:
+ case GE_EXPR:
+ case LT_EXPR:
+ case LE_EXPR:
+ case UNGT_EXPR:
+ case UNGE_EXPR:
+ case UNLT_EXPR:
+ case UNLE_EXPR:
+ return true;
+
+ default:
+ break;
+ }
+ return false;
+}
+
/* Base class for all identifiers the parser knows. */
return operators->find_with_hash (&tem, tem.hashval);
}
+/* Return the comparison operators that results if the operands are
+ swapped. This is safe for floating-point. */
+
+id_base *
+swap_tree_comparison (operator_id *p)
+{
+ switch (p->code)
+ {
+ case EQ_EXPR:
+ case NE_EXPR:
+ case ORDERED_EXPR:
+ case UNORDERED_EXPR:
+ case LTGT_EXPR:
+ case UNEQ_EXPR:
+ return p;
+ case GT_EXPR:
+ return get_operator ("LT_EXPR");
+ case GE_EXPR:
+ return get_operator ("LE_EXPR");
+ case LT_EXPR:
+ return get_operator ("GT_EXPR");
+ case LE_EXPR:
+ return get_operator ("GE_EXPR");
+ case UNGT_EXPR:
+ return get_operator ("UNLT_EXPR");
+ case UNGE_EXPR:
+ return get_operator ("UNLE_EXPR");
+ case UNLT_EXPR:
+ return get_operator ("UNGT_EXPR");
+ case UNLE_EXPR:
+ return get_operator ("UNGE_EXPR");
+ default:
+ gcc_unreachable ();
+ }
+}
+
typedef hash_map<nofree_string_hash, unsigned> cid_map_t;
/* Lower OP to two operands in case it is marked as commutative. */
static vec<operand *>
-commutate (operand *op)
+commutate (operand *op, vec<vec<user_id *> > &for_vec)
{
vec<operand *> ret = vNULL;
ret.safe_push (op);
return ret;
}
- vec<operand *> v = commutate (c->what);
+ vec<operand *> v = commutate (c->what, for_vec);
for (unsigned i = 0; i < v.length (); ++i)
{
capture *nc = new capture (c->location, c->where, v[i]);
vec< vec<operand *> > ops_vector = vNULL;
for (unsigned i = 0; i < e->ops.length (); ++i)
- ops_vector.safe_push (commutate (e->ops[i]));
+ ops_vector.safe_push (commutate (e->ops[i], for_vec));
auto_vec< vec<operand *> > result;
auto_vec<operand *> v (e->ops.length ());
for (unsigned i = 0; i < result.length (); ++i)
{
expr *ne = new expr (e);
+ if (operator_id *p = dyn_cast <operator_id *> (ne->operation))
+ {
+ if (comparison_code_p (p->code))
+ ne->operation = swap_tree_comparison (p);
+ }
+ else if (user_id *p = dyn_cast <user_id *> (ne->operation))
+ {
+ bool found_compare = false;
+ for (unsigned j = 0; j < p->substitutes.length (); ++j)
+ if (operator_id *q = dyn_cast <operator_id *> (p->substitutes[j]))
+ {
+ if (comparison_code_p (q->code)
+ && swap_tree_comparison (q) != q)
+ {
+ found_compare = true;
+ break;
+ }
+ }
+ if (found_compare)
+ {
+ user_id *newop = new user_id ("<internal>");
+ for (unsigned j = 0; j < p->substitutes.length (); ++j)
+ {
+ id_base *subst = p->substitutes[j];
+ if (operator_id *q = dyn_cast <operator_id *> (subst))
+ {
+ if (comparison_code_p (q->code))
+ subst = swap_tree_comparison (q);
+ }
+ newop->substitutes.safe_push (subst);
+ }
+ ne->operation = newop;
+ /* Search for 'p' inside the for vector and push 'newop'
+ to the same level. */
+ for (unsigned j = 0; newop && j < for_vec.length (); ++j)
+ for (unsigned k = 0; k < for_vec[j].length (); ++k)
+ if (for_vec[j][k] == p)
+ {
+ for_vec[j].safe_push (newop);
+ newop = NULL;
+ break;
+ }
+ }
+ }
ne->is_commutative = false;
// result[i].length () is 2 since e->operation is binary
for (unsigned j = result[i].length (); j; --j)
static void
lower_commutative (simplify *s, vec<simplify *>& simplifiers)
{
- vec<operand *> matchers = commutate (s->match);
+ vec<operand *> matchers = commutate (s->match, s->for_vec);
for (unsigned i = 0; i < matchers.length (); ++i)
{
simplify *ns = new simplify (s->kind, matchers[i], s->result,
fprintf_indent (f, indent, "if (%s (res_code, res_ops, seq, "
"valueize, type, captures", info->fname);
for (unsigned i = 0; i < s->for_subst_vec.length (); ++i)
- fprintf (f, ", %s", s->for_subst_vec[i].second->id);
+ if (s->for_subst_vec[i].first->used)
+ fprintf (f, ", %s", s->for_subst_vec[i].second->id);
fprintf (f, "))\n");
fprintf_indent (f, indent, " return true;\n");
}
fprintf (f, ", op%d", i);
fprintf (f, ", captures");
for (unsigned i = 0; i < s->for_subst_vec.length (); ++i)
- fprintf (f, ", %s", s->for_subst_vec[i].second->id);
+ {
+ if (s->for_subst_vec[i].first->used)
+ fprintf (f, ", %s", s->for_subst_vec[i].second->id);
+ }
fprintf (f, ");\n");
fprintf_indent (f, indent, "if (res) return res;\n");
}
{
for (unsigned i = 0; i < s->for_subst_vec.length (); ++i)
{
+ if (! s->for_subst_vec[i].first->used)
+ continue;
if (is_a <operator_id *> (s->for_subst_vec[i].second))
fprintf_indent (f, indent, "enum tree_code %s = %s;\n",
s->for_subst_vec[i].first->id,
}
for (unsigned i = 0; i < s->s->s->for_subst_vec.length (); ++i)
{
+ if (! s->s->s->for_subst_vec[i].first->used)
+ continue;
if (is_a <operator_id *> (s->s->s->for_subst_vec[i].second))
fprintf (f, ", enum tree_code ARG_UNUSED (%s)",
s->s->s->for_subst_vec[i].first->id);
while (*sp)
{
if (*sp == 'c')
+ {
+ if (operator_id *p
+ = dyn_cast<operator_id *> (e->operation))
+ {
+ if (!commutative_tree_code (p->code)
+ && !comparison_code_p (p->code))
+ fatal_at (token, "operation is not commutative");
+ }
+ else if (user_id *p = dyn_cast<user_id *> (e->operation))
+ for (unsigned i = 0;
+ i < p->substitutes.length (); ++i)
+ {
+ if (operator_id *q
+ = dyn_cast<operator_id *> (p->substitutes[i]))
+ {
+ if (!commutative_tree_code (q->code)
+ && !comparison_code_p (q->code))
+ fatal_at (token, "operation %s is not "
+ "commutative", q->id);
+ }
+ }
+ is_commutative = true;
+ }
+ else if (*sp == 'C')
is_commutative = true;
else if (*sp == 's')
{