Commit e04d2a35 by Richard Biener Committed by Richard Biener

genmatch.c (comparison_code_p): New predicate.

2016-06-01  Richard Biener  <rguenther@suse.de>

	* genmatch.c (comparison_code_p): New predicate.
	(swap_tree_comparison): New function.
	(commutate): Add for_vec parameter to append new for entries.
	Support commutating relational operators by swapping it alongside
	operands.
	(lower_commutative): Adjust.
	(dt_simplify::gen): Do not pass artificial operators to gen
	functions.
	(decision_tree::gen): Do not add artificial operators as parameters.
	(parser::parse_expr): Verify operator commutativity when :c is
	applied.  Allow :C to override this.
	* match.pd: Adjust patterns to use :C instead of :c where required.

From-SVN: r236977
parent e4b631a5
2016-06-01 Richard Biener <rguenther@suse.de>
* genmatch.c (comparison_code_p): New predicate.
(swap_tree_comparison): New function.
(commutate): Add for_vec parameter to append new for entries.
Support commutating relational operators by swapping it alongside
operands.
(lower_commutative): Adjust.
(dt_simplify::gen): Do not pass artificial operators to gen
functions.
(decision_tree::gen): Do not add artificial operators as parameters.
(parser::parse_expr): Verify operator commutativity when :c is
applied. Allow :C to override this.
* match.pd: Adjust patterns to use :C instead of :c where required.
2016-06-01 Patrick Palka <ppalka@gcc.gnu.org>
PR tree-optimization/71077
......
......@@ -291,6 +291,35 @@ commutative_ternary_tree_code (enum tree_code code)
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. */
......@@ -528,6 +557,42 @@ get_operator (const char *id, bool allow_null = false)
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;
......@@ -816,7 +881,7 @@ cartesian_product (const vec< vec<operand *> >& ops_vector,
/* 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;
......@@ -827,7 +892,7 @@ commutate (operand *op)
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]);
......@@ -845,7 +910,7 @@ commutate (operand *op)
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 ());
......@@ -868,6 +933,50 @@ commutate (operand *op)
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)
......@@ -884,7 +993,7 @@ commutate (operand *op)
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,
......@@ -3248,7 +3357,8 @@ dt_simplify::gen (FILE *f, int indent, bool gimple)
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");
}
......@@ -3260,7 +3370,10 @@ dt_simplify::gen (FILE *f, int indent, bool gimple)
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");
}
......@@ -3269,6 +3382,8 @@ dt_simplify::gen (FILE *f, int indent, bool gimple)
{
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,
......@@ -3425,6 +3540,8 @@ decision_tree::gen (FILE *f, bool gimple)
}
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);
......@@ -3885,6 +4002,30 @@ parser::parse_expr ()
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')
{
......
......@@ -189,7 +189,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
/* Optimize -A / A to -1.0 if we don't care about
NaNs or Infinities. */
(simplify
(rdiv:c @0 (negate @0))
(rdiv:C @0 (negate @0))
(if (FLOAT_TYPE_P (type)
&& ! HONOR_NANS (type)
&& ! HONOR_INFINITIES (type))
......@@ -2830,7 +2830,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
/* cabs(x+0i) or cabs(0+xi) -> abs(x). */
(simplify
(CABS (complex:c @0 real_zerop@1))
(CABS (complex:C @0 real_zerop@1))
(abs @0))
/* trunc(trunc(x)) -> trunc(x), etc. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment