public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Richard Biener <richard.guenther@gmail.com>
To: Andrew Pinski <apinski@marvell.com>
Cc: gcc-patches@gcc.gnu.org
Subject: Re: [PATCH] MATCH: Simplify (a CMP1 b) ^ (a CMP2 b)
Date: Tue, 12 Sep 2023 12:35:19 +0200	[thread overview]
Message-ID: <CAFiYyc1mfK4Ky_zRRrX7XHHCbzwYrjLvi_eYs=Xu-1BRwuC7sw@mail.gmail.com> (raw)
In-Reply-To: <20230912042152.1412606-1-apinski@marvell.com>

On Tue, Sep 12, 2023 at 6:22 AM Andrew Pinski via Gcc-patches
<gcc-patches@gcc.gnu.org> wrote:
>
> This adds the missing optimizations here.
> Note we don't need to match where CMP1 and CMP2 are complements of each
> other as that is already handled elsewhere.
>
> I added a new executable testcase to make sure we optimize it correctly
> as I had originally messed up one of the entries for the resulting
> comparison to make sure they were 100% correct.
>
> OK? Bootstrapped and tested on x86_64-linux-gnu with no regressions.

OK.

>         PR tree-optimization/107881
>
> gcc/ChangeLog:
>
>         * match.pd (`(a CMP1 b) ^ (a CMP2 b)`): New pattern.
>         (`(a CMP1 b) == (a CMP2 b)`): New pattern.
>
> gcc/testsuite/ChangeLog:
>
>         * gcc.c-torture/execute/pr107881-1.c: New test.
>         * gcc.dg/tree-ssa/cmpeq-4.c: New test.
>         * gcc.dg/tree-ssa/cmpxor-1.c: New test.
> ---
>  gcc/match.pd                                  |  20 +++
>  .../gcc.c-torture/execute/pr107881-1.c        | 115 ++++++++++++++++++
>  gcc/testsuite/gcc.dg/tree-ssa/cmpeq-4.c       |  51 ++++++++
>  gcc/testsuite/gcc.dg/tree-ssa/cmpxor-1.c      |  51 ++++++++
>  4 files changed, 237 insertions(+)
>  create mode 100644 gcc/testsuite/gcc.c-torture/execute/pr107881-1.c
>  create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/cmpeq-4.c
>  create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/cmpxor-1.c
>
> diff --git a/gcc/match.pd b/gcc/match.pd
> index e96e385c6fa..39c7ea1088f 100644
> --- a/gcc/match.pd
> +++ b/gcc/match.pd
> @@ -3154,6 +3154,26 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
>        { constant_boolean_node (true, type); })
>       ))))))
>
> +/* Optimize (a CMP b) ^ (a CMP b)  */
> +/* Optimize (a CMP b) != (a CMP b)  */
> +(for op (bit_xor ne)
> + (for cmp1 (lt lt lt le le le)
> +      cmp2 (gt eq ne ge eq ne)
> +      rcmp (ne le gt ne lt ge)
> +  (simplify
> +   (op:c (cmp1:c @0 @1) (cmp2:c @0 @1))
> +   (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) || POINTER_TYPE_P (TREE_TYPE (@0)))
> +    (rcmp @0 @1)))))
> +
> +/* Optimize (a CMP b) == (a CMP b)  */
> +(for cmp1 (lt lt lt le le le)
> +     cmp2 (gt eq ne ge eq ne)
> +     rcmp (eq gt le eq ge lt)
> + (simplify
> +  (eq:c (cmp1:c @0 @1) (cmp2:c @0 @1))
> +  (if (INTEGRAL_TYPE_P (TREE_TYPE (@0)) || POINTER_TYPE_P (TREE_TYPE (@0)))
> +    (rcmp @0 @1))))
> +
>  /* We can't reassociate at all for saturating types.  */
>  (if (!TYPE_SATURATING (type))
>
> diff --git a/gcc/testsuite/gcc.c-torture/execute/pr107881-1.c b/gcc/testsuite/gcc.c-torture/execute/pr107881-1.c
> new file mode 100644
> index 00000000000..063ec4c2797
> --- /dev/null
> +++ b/gcc/testsuite/gcc.c-torture/execute/pr107881-1.c
> @@ -0,0 +1,115 @@
> +#define func(vol, op1, op2, op3)       \
> +_Bool op1##_##op2##_##op3##_##vol (int a, int b)       \
> +{                                      \
> + vol _Bool x = op_##op1(a, b);         \
> + vol _Bool y = op_##op2(a, b);         \
> + return op_##op3(x, y);                        \
> +}
> +
> +#define op_lt(a, b) ((a) < (b))
> +#define op_le(a, b) ((a) <= (b))
> +#define op_eq(a, b) ((a) == (b))
> +#define op_ne(a, b) ((a) != (b))
> +#define op_gt(a, b) ((a) > (b))
> +#define op_ge(a, b) ((a) >= (b))
> +#define op_xor(a, b) ((a) ^ (b))
> +
> +
> +#define funcs(a) \
> + a(lt,lt,ne) \
> + a(lt,lt,eq) \
> + a(lt,lt,xor) \
> + a(lt,le,ne) \
> + a(lt,le,eq) \
> + a(lt,le,xor) \
> + a(lt,gt,ne) \
> + a(lt,gt,eq) \
> + a(lt,gt,xor) \
> + a(lt,ge,ne) \
> + a(lt,ge,eq) \
> + a(lt,ge,xor) \
> + a(lt,eq,ne) \
> + a(lt,eq,eq) \
> + a(lt,eq,xor) \
> + a(lt,ne,ne) \
> + a(lt,ne,eq) \
> + a(lt,ne,xor) \
> +  \
> + a(le,lt,ne) \
> + a(le,lt,eq) \
> + a(le,lt,xor) \
> + a(le,le,ne) \
> + a(le,le,eq) \
> + a(le,le,xor) \
> + a(le,gt,ne) \
> + a(le,gt,eq) \
> + a(le,gt,xor) \
> + a(le,ge,ne) \
> + a(le,ge,eq) \
> + a(le,ge,xor) \
> + a(le,eq,ne) \
> + a(le,eq,eq) \
> + a(le,eq,xor) \
> + a(le,ne,ne) \
> + a(le,ne,eq) \
> + a(le,ne,xor)  \
> + \
> + a(gt,lt,ne) \
> + a(gt,lt,eq) \
> + a(gt,lt,xor) \
> + a(gt,le,ne) \
> + a(gt,le,eq) \
> + a(gt,le,xor) \
> + a(gt,gt,ne) \
> + a(gt,gt,eq) \
> + a(gt,gt,xor) \
> + a(gt,ge,ne) \
> + a(gt,ge,eq) \
> + a(gt,ge,xor) \
> + a(gt,eq,ne) \
> + a(gt,eq,eq) \
> + a(gt,eq,xor) \
> + a(gt,ne,ne) \
> + a(gt,ne,eq) \
> + a(gt,ne,xor) \
> +  \
> + a(ge,lt,ne) \
> + a(ge,lt,eq) \
> + a(ge,lt,xor) \
> + a(ge,le,ne) \
> + a(ge,le,eq) \
> + a(ge,le,xor) \
> + a(ge,gt,ne) \
> + a(ge,gt,eq) \
> + a(ge,gt,xor) \
> + a(ge,ge,ne) \
> + a(ge,ge,eq) \
> + a(ge,ge,xor) \
> + a(ge,eq,ne) \
> + a(ge,eq,eq) \
> + a(ge,eq,xor) \
> + a(ge,ne,ne) \
> + a(ge,ne,eq) \
> + a(ge,ne,xor)
> +
> +#define funcs1(a,b,c) \
> +func(,a,b,c) \
> +func(volatile,a,b,c)
> +
> +funcs(funcs1)
> +
> +#define test(op1,op2,op3)                      \
> +do {                                           \
> +  if (op1##_##op2##_##op3##_(x,y)              \
> +      != op1##_##op2##_##op3##_volatile(x,y))  \
> +    __builtin_abort();                         \
> +} while(0);
> +
> +int main()
> +{
> +  for(int x = -10; x < 10; x++)
> +    for(int y = -10; y < 10; y++)
> +    {
> +        funcs(test)
> +    }
> +}
> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/cmpeq-4.c b/gcc/testsuite/gcc.dg/tree-ssa/cmpeq-4.c
> new file mode 100644
> index 00000000000..868d80fdcca
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/cmpeq-4.c
> @@ -0,0 +1,51 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fdump-tree-optimized -fdump-tree-original" } */
> +/* PR tree-optimization/107881 */
> +
> +_Bool ltgt_eq(int a, int b)
> +{
> +  _Bool c = a < b;
> +  _Bool d = a > b;
> +  return c == d; // a == b
> +}
> +/* { dg-final { scan-tree-dump "a_\[0-9\]+.D. == b_\[0-9\]+.D.|b_\[0-9\]+.D. == a_\[0-9\]+.D." "optimized" } } */
> +
> +_Bool lteq_eq(int x, int y)
> +{
> +  _Bool c = x < y;
> +  _Bool d = x == y;
> +  return c == d; // x > y
> +}
> +/* { dg-final { scan-tree-dump "x_\[0-9\]+.D. > y_\[0-9\]+.D.|y_\[0-9\]+.D. < x_\[0-9\]+.D." "optimized" } } */
> +
> +_Bool ltne_eq(int z, int w)
> +{
> +  _Bool c = z < w;
> +  _Bool d = z != w;
> +  return c == d; // z <= w
> +}
> +/* { dg-final { scan-tree-dump "z_\[0-9\]+.D. <= w_\[0-9\]+.D.|w_\[0-9\]+.D. >= y_\[0-9\]+.D." "optimized" } } */
> +
> +_Bool lege_eq(int i, int j)
> +{
> +  _Bool c = i <= j;
> +  _Bool d = i >= j;
> +  return c == d; // i == j
> +}
> +/* { dg-final { scan-tree-dump "i_\[0-9\]+.D. == j_\[0-9\]+.D.|j_\[0-9\]+.D. == i_\[0-9\]+.D." "optimized" } } */
> +
> +_Bool leeq_eq(int k, int l)
> +{
> +  _Bool c = k <= l;
> +  _Bool d = k == l;
> +  return c == d; // k >= l
> +}
> +/* { dg-final { scan-tree-dump "k_\[0-9\]+.D. >= l_\[0-9\]+.D.|l_\[0-9\]+.D. <= k_\[0-9\]+.D." "optimized" } } */
> +
> +_Bool lene_eq(int m, int n)
> +{
> +  _Bool c = m <= n;
> +  _Bool d = m != n;
> +  return c == d; // m < n
> +}
> +/* { dg-final { scan-tree-dump "m_\[0-9\]+.D. < n_\[0-9\]+.D.|n_\[0-9\]+.D. > m_\[0-9\]+.D." "optimized" } } */
> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/cmpxor-1.c b/gcc/testsuite/gcc.dg/tree-ssa/cmpxor-1.c
> new file mode 100644
> index 00000000000..8de2d9d2244
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/cmpxor-1.c
> @@ -0,0 +1,51 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fdump-tree-optimized" } */
> +/* PR tree-optimization/107881 */
> +
> +_Bool ltgtxor(int a, int b)
> +{
> +  _Bool c = a < b;
> +  _Bool d = a > b;
> +  return c ^ d; // a != b
> +}
> +/* { dg-final { scan-tree-dump "a_\[0-9\]+.D. != b_\[0-9\]+.D.|b_\[0-9\]+.D. != a_\[0-9\]+.D." "optimized" } } */
> +
> +_Bool lteqxor(int x, int y)
> +{
> +  _Bool c = x < y;
> +  _Bool d = x == y;
> +  return c ^ d; // x <= y (basically | here)
> +}
> +/* { dg-final { scan-tree-dump "x_\[0-9\]+.D. <= y_\[0-9\]+.D.|y_\[0-9\]+.D. >= x_\[0-9\]+.D." "optimized" } } */
> +
> +_Bool ltnexor(int z, int w)
> +{
> +  _Bool c = z < w;
> +  _Bool d = z != w;
> +  return c ^ d; // z > w
> +}
> +/* { dg-final { scan-tree-dump "z_\[0-9\]+.D. > w_\[0-9\]+.D.|w_\[0-9\]+.D. < y_\[0-9\]+.D." "optimized" } } */
> +
> +_Bool legexor(int i, int j)
> +{
> +  _Bool c = i <= j;
> +  _Bool d = i >= j;
> +  return c ^ d; // i != j
> +}
> +/* { dg-final { scan-tree-dump "i_\[0-9\]+.D. != j_\[0-9\]+.D.|j_\[0-9\]+.D. != i_\[0-9\]+.D." "optimized" } } */
> +
> +_Bool leeqxor(int k, int l)
> +{
> +  _Bool c = k <= l;
> +  _Bool d = k == l;
> +  return c ^ d; // k < l
> +}
> +/* { dg-final { scan-tree-dump "k_\[0-9\]+.D. < l_\[0-9\]+.D.|l_\[0-9\]+.D. > k_\[0-9\]+.D." "optimized" } } */
> +
> +_Bool lenexor(int m, int n)
> +{
> +  _Bool c = m <= n;
> +  _Bool d = m != n;
> +  return c ^ d; // m >= n
> +}
> +/* { dg-final { scan-tree-dump "m_\[0-9\]+.D. >= n_\[0-9\]+.D.|n_\[0-9\]+.D. <= m_\[0-9\]+.D." "optimized" } } */
> --
> 2.31.1
>

      reply	other threads:[~2023-09-12 10:37 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-09-12  4:21 Andrew Pinski
2023-09-12 10:35 ` Richard Biener [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAFiYyc1mfK4Ky_zRRrX7XHHCbzwYrjLvi_eYs=Xu-1BRwuC7sw@mail.gmail.com' \
    --to=richard.guenther@gmail.com \
    --cc=apinski@marvell.com \
    --cc=gcc-patches@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).