aboutsummaryrefslogtreecommitdiff
path: root/gcc/match.pd
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2021-01-22 11:50:18 +0100
committerJakub Jelinek <jakub@redhat.com>2021-01-22 11:51:22 +0100
commit36fe1cdc9534c36c02803ce97557130354d2b2a0 (patch)
treef1b9475408940c2922bb3d9252e236181e7fb495 /gcc/match.pd
parente287a2a11d7958e5d9f7c6172e59cc83495e393a (diff)
downloadgcc-36fe1cdc9534c36c02803ce97557130354d2b2a0.zip
gcc-36fe1cdc9534c36c02803ce97557130354d2b2a0.tar.gz
gcc-36fe1cdc9534c36c02803ce97557130354d2b2a0.tar.bz2
match.pd: Replace incorrect simplifications into copysign [PR90248]
In the PR Andrew said he has implemented a simplification that has been added to LLVM, but that actually is not true, what is in there are X * (X cmp 0.0 ? +-1.0 : -+1.0) simplifications into +-abs(X) but what has been added into GCC are (X cmp 0.0 ? +-1.0 : -+1.0) simplifications into copysign(1, +-X) and then X * copysign (1, +-X) into +-abs (X). The problem is with the (X cmp 0.0 ? +-1.0 : -+1.0) simplifications, they don't work correctly when X is zero. E.g. (X > 0.0 ? 1.0 : -1.0) is -1.0 when X is either -0.0 or 0.0, but copysign will make it return 1.0 for 0.0 and -1.0 only for -0.0. (X >= 0.0 ? 1.0 : -1.0) is 1.0 when X is either -0.0 or 0.0, but copysign will make it return still 1.0 for 0.0 and -1.0 for -0.0. The simplifications were guarded on !HONOR_SIGNED_ZEROS, but as discussed in the PR, that option doesn't mean that -0.0 will not ever appear as operand of some operation, it is hard to guarantee that without compiler adding canonicalizations of -0.0 to 0.0 after most of the operations and thus making it very slow, but that the user asserts that he doesn't care if the result of operations will be 0.0 or -0.0. Not to mention that some of the transformations are incorrect even for positive 0.0. So, instead of those simplifications this patch recognizes patterns where those ?: expressions are multiplied by X, directly into +-abs. That works fine even for 0.0 and -0.0 (as long as we don't care about whether the result is exactly 0.0 or -0.0 in those cases), because whether the result of copysign is -1.0 or 1.0 doesn't matter when it is multiplied by 0.0 or -0.0. As a follow-up, maybe we should add the simplification mentioned in the PR, in particular doing copysign by hand through VIEW_CONVERT_EXPR <int, float_X> < 0 ? -float_constant : float_constant into copysign (float_constant, float_X). But I think that would need to be done in phiopt. 2021-01-22 Jakub Jelinek <jakub@redhat.com> PR tree-optimization/90248 * match.pd (X cmp 0.0 ? 1.0 : -1.0 -> copysign(1, +-X), X cmp 0.0 ? -1.0 : +1.0 -> copysign(1, -+X)): Remove simplifications. (X * (X cmp 0.0 ? 1.0 : -1.0) -> +-abs(X), X * (X cmp 0.0 ? -1.0 : 1.0) -> +-abs(X)): New simplifications. * gcc.dg/tree-ssa/copy-sign-1.c: Don't expect any copysign builtins. * gcc.dg/pr90248.c: New test.
Diffstat (limited to 'gcc/match.pd')
-rw-r--r--gcc/match.pd46
1 files changed, 16 insertions, 30 deletions
diff --git a/gcc/match.pd b/gcc/match.pd
index 05e7ba9..17c35ee4 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -253,36 +253,22 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(for cmp (gt ge lt le)
outp (convert convert negate negate)
outn (negate negate convert convert)
- /* Transform (X > 0.0 ? 1.0 : -1.0) into copysign(1, X). */
- /* Transform (X >= 0.0 ? 1.0 : -1.0) into copysign(1, X). */
- /* Transform (X < 0.0 ? 1.0 : -1.0) into copysign(1,-X). */
- /* Transform (X <= 0.0 ? 1.0 : -1.0) into copysign(1,-X). */
- (simplify
- (cond (cmp @0 real_zerop) real_onep@1 real_minus_onep)
- (if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type)
- && types_match (type, TREE_TYPE (@0)))
- (switch
- (if (types_match (type, float_type_node))
- (BUILT_IN_COPYSIGNF @1 (outp @0)))
- (if (types_match (type, double_type_node))
- (BUILT_IN_COPYSIGN @1 (outp @0)))
- (if (types_match (type, long_double_type_node))
- (BUILT_IN_COPYSIGNL @1 (outp @0))))))
- /* Transform (X > 0.0 ? -1.0 : 1.0) into copysign(1,-X). */
- /* Transform (X >= 0.0 ? -1.0 : 1.0) into copysign(1,-X). */
- /* Transform (X < 0.0 ? -1.0 : 1.0) into copysign(1,X). */
- /* Transform (X <= 0.0 ? -1.0 : 1.0) into copysign(1,X). */
- (simplify
- (cond (cmp @0 real_zerop) real_minus_onep real_onep@1)
- (if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type)
- && types_match (type, TREE_TYPE (@0)))
- (switch
- (if (types_match (type, float_type_node))
- (BUILT_IN_COPYSIGNF @1 (outn @0)))
- (if (types_match (type, double_type_node))
- (BUILT_IN_COPYSIGN @1 (outn @0)))
- (if (types_match (type, long_double_type_node))
- (BUILT_IN_COPYSIGNL @1 (outn @0)))))))
+ /* Transform X * (X > 0.0 ? 1.0 : -1.0) into abs(X). */
+ /* Transform X * (X >= 0.0 ? 1.0 : -1.0) into abs(X). */
+ /* Transform X * (X < 0.0 ? 1.0 : -1.0) into -abs(X). */
+ /* Transform X * (X <= 0.0 ? 1.0 : -1.0) into -abs(X). */
+ (simplify
+ (mult:c @0 (cond (cmp @0 real_zerop) real_onep@1 real_minus_onep))
+ (if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type))
+ (outp (abs @0))))
+ /* Transform X * (X > 0.0 ? -1.0 : 1.0) into -abs(X). */
+ /* Transform X * (X >= 0.0 ? -1.0 : 1.0) into -abs(X). */
+ /* Transform X * (X < 0.0 ? -1.0 : 1.0) into abs(X). */
+ /* Transform X * (X <= 0.0 ? -1.0 : 1.0) into abs(X). */
+ (simplify
+ (mult:c @0 (cond (cmp @0 real_zerop) real_minus_onep real_onep@1))
+ (if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type))
+ (outn (abs @0)))))
/* Transform X * copysign (1.0, X) into abs(X). */
(simplify