diff options
author | Richard Biener <rguenther@suse.de> | 2016-06-01 09:00:57 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2016-06-01 09:00:57 +0000 |
commit | e04d2a35c884f075ebe12cd6f871e35f6d0362a4 (patch) | |
tree | 638943efbfc2fd09c79e79434b1bfd8ad43999e1 /gcc/genmatch.c | |
parent | e4b631a5a80b0fe254b3e9a747df697780748c12 (diff) | |
download | gcc-e04d2a35c884f075ebe12cd6f871e35f6d0362a4.zip gcc-e04d2a35c884f075ebe12cd6f871e35f6d0362a4.tar.gz gcc-e04d2a35c884f075ebe12cd6f871e35f6d0362a4.tar.bz2 |
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
Diffstat (limited to 'gcc/genmatch.c')
-rw-r--r-- | gcc/genmatch.c | 153 |
1 files changed, 147 insertions, 6 deletions
diff --git a/gcc/genmatch.c b/gcc/genmatch.c index 2b666dd..9bb1279 100644 --- a/gcc/genmatch.c +++ b/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') { |