From 66dea8899df6475d5cb289491dbbff307c16c1a7 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 10 Dec 2020 11:46:08 +0100 Subject: [PATCH] dojump: Optimize a == a or a != a [PR98169] If the backend doesn't have floating point EQ or NE comparison, dojump.c splits it into ORDERED && UNEQ or UNORDERED || LTGT. If both comparison operands are the same, we know the result of the second comparison though, a == b is equivalent to a ord b and a != b is equivalent to a unord b, and thus can just use ORDERED or UNORDERED. On the testcase, this changes f1: - ucomiss %xmm0, %xmm0 - movl $1, %eax - jp .L3 - jne .L3 - ret - .p2align 4,,10 - .p2align 3 -.L3: xorl %eax, %eax + ucomiss %xmm0, %xmm0 + setnp %al and f3: - ucomisd %xmm0, %xmm0 - movl $1, %eax - jp .L8 - jne .L8 - ret - .p2align 4,,10 - .p2align 3 -.L8: xorl %eax, %eax + ucomisd %xmm0, %xmm0 + setnp %al while keeping the same code for f2 and f4. 2020-12-10 Jakub Jelinek PR tree-optimization/98169 * dojump.c (do_compare_rtx_and_jump): Don't split self-EQ/NE comparisons, just use ORDERED or UNORDERED. * gcc.target/i386/pr98169.c: New test. --- gcc/dojump.c | 8 +++++++- gcc/testsuite/gcc.target/i386/pr98169.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr98169.c diff --git a/gcc/dojump.c b/gcc/dojump.c index 28b47b7..4c7fafe 100644 --- a/gcc/dojump.c +++ b/gcc/dojump.c @@ -1114,7 +1114,7 @@ do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp, /* ... or if there is no libcall for it. */ || code_to_optab (code) == unknown_optab)) { - enum rtx_code first_code; + enum rtx_code first_code, orig_code = code; bool and_them = split_comparison (code, mode, &first_code, &code); /* If there are no NaNs, the first comparison should always fall @@ -1122,6 +1122,12 @@ do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp, if (!HONOR_NANS (mode)) gcc_assert (first_code == (and_them ? ORDERED : UNORDERED)); + else if ((orig_code == EQ || orig_code == NE) + && rtx_equal_p (op0, op1)) + /* Self-comparisons x == x or x != x can be optimized into + just x ord x or x nord x. */ + code = orig_code == EQ ? ORDERED : UNORDERED; + else { profile_probability cprob diff --git a/gcc/testsuite/gcc.target/i386/pr98169.c b/gcc/testsuite/gcc.target/i386/pr98169.c new file mode 100644 index 0000000..b192731 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr98169.c @@ -0,0 +1,29 @@ +/* PR tree-optimization/98169 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-finite-math-only" } */ +/* { dg-final { scan-assembler-times "\tsetn\?p\t" 4 } } */ +/* { dg-final { scan-assembler-not "\tjn\?\[ep]\t" } } */ + +int +f1 (float a) +{ + return a == a; +} + +int +f2 (float a) +{ + return !__builtin_isnanf (a); +} + +int +f3 (double a) +{ + return a == a; +} + +int +f4 (double a) +{ + return !__builtin_isnan (a); +} -- 2.7.4