mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-19 18:20:56 +08:00
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
This commit is contained in:
parent
e4b631a5a8
commit
e04d2a35c8
@ -1,3 +1,18 @@
|
||||
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
|
||||
|
153
gcc/genmatch.c
153
gcc/genmatch.c
@ -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. */
|
||||
|
Loading…
x
Reference in New Issue
Block a user