From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2153) id E4DB338618FF; Tue, 20 Apr 2021 23:31:18 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org E4DB338618FF MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Jakub Jelinek To: gcc-cvs@gcc.gnu.org Subject: [gcc r9-9407] match.pd: Replace incorrect simplifications into copysign [PR90248] X-Act-Checkin: gcc X-Git-Author: Jakub Jelinek X-Git-Refname: refs/heads/releases/gcc-9 X-Git-Oldrev: 2fe1131465af7352be9e03773c30a3f6059af993 X-Git-Newrev: 45a6eae129c6fee387a3bb7075181d8509fa6e2a Message-Id: <20210420233118.E4DB338618FF@sourceware.org> Date: Tue, 20 Apr 2021 23:31:18 +0000 (GMT) X-BeenThere: gcc-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 20 Apr 2021 23:31:19 -0000 https://gcc.gnu.org/g:45a6eae129c6fee387a3bb7075181d8509fa6e2a commit r9-9407-g45a6eae129c6fee387a3bb7075181d8509fa6e2a Author: Jakub Jelinek Date: Fri Jan 22 11:50:18 2021 +0100 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 < 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 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. (cherry picked from commit dd92986ea6d2d363146e1726817a84910453fdc8) Diff: --- gcc/match.pd | 46 +++++++----------- gcc/testsuite/gcc.dg/pr90248.c | 73 +++++++++++++++++++++++++++++ gcc/testsuite/gcc.dg/tree-ssa/copy-sign-1.c | 2 +- 3 files changed, 90 insertions(+), 31 deletions(-) diff --git a/gcc/match.pd b/gcc/match.pd index f7e192d9b73..88a91b16239 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -214,36 +214,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 diff --git a/gcc/testsuite/gcc.dg/pr90248.c b/gcc/testsuite/gcc.dg/pr90248.c new file mode 100644 index 00000000000..2c89e1e4a4b --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr90248.c @@ -0,0 +1,73 @@ +/* PR tree-optimization/90248 */ +/* { dg-do run } */ +/* { dg-options "-Ofast" } */ + +volatile float b1 = -1.f; +volatile float b2 = 0.f; + +__attribute__((noipa)) float +f1 (float x) +{ + return x > 0 ? 1.f : -1.f; +} + +__attribute__((noipa)) float +f2 (float x) +{ + return x >= 0 ? 1.f : -1.f; +} + +__attribute__((noipa)) float +f3 (float x) +{ + return x < 0 ? 1.f : -1.f; +} + +__attribute__((noipa)) float +f4 (float x) +{ + return x <= 0 ? 1.f : -1.f; +} + +__attribute__((noipa)) float +f5 (float x) +{ + return x > 0 ? -1.f : 1.f; +} + +__attribute__((noipa)) float +f6 (float x) +{ + return x >= 0 ? -1.f : 1.f; +} + +__attribute__((noipa)) float +f7 (float x) +{ + return x < 0 ? -1.f : 1.f; +} + +__attribute__((noipa)) float +f8 (float x) +{ + return x <= 0 ? -1.f : 1.f; +} + +int +main () +{ + float a = 0.f; + float b = b1 * b2; + float c = 2.f; + float d = -2.f; + if (f1 (a) != -1.f || f1 (b) != -1.f || f1 (c) != 1.f || f1 (d) != -1.f + || f2 (a) != 1.f || f2 (b) != 1.f || f2 (c) != 1.f || f2 (d) != -1.f + || f3 (a) != -1.f || f3 (b) != -1.f || f3 (c) != -1.f || f3 (d) != 1.f + || f4 (a) != 1.f || f4 (b) != 1.f || f4 (c) != -1.f || f4 (d) != 1.f + || f5 (a) != 1.f || f5 (b) != 1.f || f5 (c) != -1.f || f5 (d) != 1.f + || f6 (a) != -1.f || f6 (b) != -1.f || f6 (c) != -1.f || f6 (d) != 1.f + || f7 (a) != 1.f || f7 (b) != 1.f || f7 (c) != 1.f || f7 (d) != -1.f + || f8 (a) != -1.f || f8 (b) != -1.f || f8 (c) != 1.f || f8 (d) != -1.f) + __builtin_abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/copy-sign-1.c b/gcc/testsuite/gcc.dg/tree-ssa/copy-sign-1.c index de3e7b242ce..8e7fe3890b2 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/copy-sign-1.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/copy-sign-1.c @@ -34,4 +34,4 @@ float i1(float x) { return (x <= 0.f ? 1.f : -1.f); } -/* { dg-final { scan-tree-dump-times "copysign" 8 "gimple"} } */ +/* { dg-final { scan-tree-dump-not "copysign" "gimple"} } */