aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2024-10-24 17:06:29 +0200
committerRichard Biener <rguenth@gcc.gnu.org>2024-10-25 11:14:42 +0200
commit967939055cee4a34729f795042977d99535e061a (patch)
tree156e2b05e9c88bcaf25a181576704bb72324eb6a /gcc
parent482d5a7b1a4abdd95f42033ad3b8d1276b8fb20a (diff)
downloadgcc-967939055cee4a34729f795042977d99535e061a.zip
gcc-967939055cee4a34729f795042977d99535e061a.tar.gz
gcc-967939055cee4a34729f795042977d99535e061a.tar.bz2
Restrict :c to commutative ops as intended
genmatch was supposed to restrict :c to verifiable commutative operations while leaving :C to the "I know what I'm doing" case. The following enforces this, cleaning up parsing and amending the commutative_op helper. There's one pattern that needs adjustment, the pattern optimizing fmax (x, NaN) or fmax (NaN, x) to x since fmax isn't commutative. * genmatch.cc (commutative_op): Add paramter to indicate whether all compares should be considered commutative. Handle hypot, add_overflow and mul_overflow. (parser::parse_expr): Simplify 'c' handling by using commutative_op and error out when the operation is not. * match.pd ((minmax:c @0 NaN@1) -> @0): Use :C, we know what we are doing.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/genmatch.cc40
-rw-r--r--gcc/match.pd2
2 files changed, 16 insertions, 26 deletions
diff --git a/gcc/genmatch.cc b/gcc/genmatch.cc
index 1682206..1acd921 100644
--- a/gcc/genmatch.cc
+++ b/gcc/genmatch.cc
@@ -1107,12 +1107,13 @@ is_a_helper <user_id *>::test (id_base *id)
index of the first, otherwise return -1. */
static int
-commutative_op (id_base *id)
+commutative_op (id_base *id, bool compares_are_commutative = false)
{
if (operator_id *code = dyn_cast <operator_id *> (id))
{
if (commutative_tree_code (code->code)
- || commutative_ternary_tree_code (code->code))
+ || commutative_ternary_tree_code (code->code)
+ || (compares_are_commutative && comparison_code_p (code->code)))
return 0;
return -1;
}
@@ -1120,9 +1121,12 @@ commutative_op (id_base *id)
switch (fn->fn)
{
CASE_CFN_FMA:
+ CASE_CFN_HYPOT:
case CFN_FMS:
case CFN_FNMA:
case CFN_FNMS:
+ case CFN_ADD_OVERFLOW:
+ case CFN_MUL_OVERFLOW:
return 0;
case CFN_COND_ADD:
@@ -1158,11 +1162,13 @@ commutative_op (id_base *id)
}
if (user_id *uid = dyn_cast<user_id *> (id))
{
- int res = commutative_op (uid->substitutes[0]);
+ int res = commutative_op (uid->substitutes[0],
+ compares_are_commutative);
if (res < 0)
return -1;
for (unsigned i = 1; i < uid->substitutes.length (); ++i)
- if (res != commutative_op (uid->substitutes[i]))
+ if (res != commutative_op (uid->substitutes[i],
+ compares_are_commutative))
return -1;
return res;
}
@@ -5214,27 +5220,11 @@ parser::parse_expr ()
{
if (*sp == 'c')
{
- if (operator_id *o
- = dyn_cast<operator_id *> (e->operation))
- {
- if (!commutative_tree_code (o->code)
- && !comparison_code_p (o->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;
+ if (commutative_op (e->operation, true) != -1)
+ is_commutative = true;
+ else
+ fatal_at (token, "operation %s is not known "
+ "commutative", e->operation->id);
}
else if (*sp == 'C')
is_commutative = true;
diff --git a/gcc/match.pd b/gcc/match.pd
index 148d0bc..93536a3 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -4672,7 +4672,7 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
/* If either argument is NaN and other one is not sNaN, return the other
one. Avoid the transformation if we get (and honor) a signalling NaN. */
(simplify
- (minmax:c @0 REAL_CST@1)
+ (minmax:C @0 REAL_CST@1)
(if (real_isnan (TREE_REAL_CST_PTR (@1))
&& (!HONOR_SNANS (@1) || !TREE_REAL_CST (@1).signalling)
&& !tree_expr_maybe_signaling_nan_p (@0))