[v4] match: Fix A || B not optimized to true when !B implies A [PR114326]
Checks
Context |
Check |
Description |
linaro-tcwg-bot/tcwg_gcc_build--master-arm |
success
|
Build passed
|
linaro-tcwg-bot/tcwg_gcc_check--master-arm |
success
|
Test passed
|
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 |
success
|
Build passed
|
linaro-tcwg-bot/tcwg_gcc_check--master-aarch64 |
success
|
Test passed
|
Commit Message
From: kelefth <konstantinos.eleftheriou@vrull.eu>
In expressions like (a != b || ((a ^ b) & c) == d) and
(a != b || (a ^ b) == c), (a ^ b) is folded to false.
In the equivalent expressions (((a ^ b) & c) == d || a != b) and
((a ^ b) == c || a != b) this is not happening.
This patch adds the following simplifications in match.pd:
((a ^ b) & c) cmp d || a != b --> 0 cmp d || a != b
(a ^ b) cmp c || a != b --> 0 cmp c || a != b
PR tree-optimization/114326
gcc/ChangeLog:
* match.pd: Add two patterns to fold a ^ b to 0, when a == b.
gcc/testsuite/ChangeLog:
* gcc.dg/tree-ssa/fold-xor-and-or.c: New test.
* gcc.dg/tree-ssa/fold-xor-or.c: New test.
Tested-by: Christoph Müllner <christoph.muellner@vrull.eu>
Signed-off-by: Philipp Tomsich <philipp.tomsich@vrull.eu>
Signed-off-by: Konstantinos Eleftheriou <konstantinos.eleftheriou@vrull.eu>
---
gcc/match.pd | 32 ++++++++++-
.../gcc.dg/tree-ssa/fold-xor-and-or.c | 55 +++++++++++++++++++
gcc/testsuite/gcc.dg/tree-ssa/fold-xor-or.c | 55 +++++++++++++++++++
3 files changed, 141 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/fold-xor-and-or.c
create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/fold-xor-or.c
Comments
On Thu, Sep 19, 2024 at 2:18 PM Konstantinos Eleftheriou
<konstantinos.eleftheriou@vrull.eu> wrote:
>
> From: kelefth <konstantinos.eleftheriou@vrull.eu>
>
> In expressions like (a != b || ((a ^ b) & c) == d) and
> (a != b || (a ^ b) == c), (a ^ b) is folded to false.
> In the equivalent expressions (((a ^ b) & c) == d || a != b) and
> ((a ^ b) == c || a != b) this is not happening.
>
> This patch adds the following simplifications in match.pd:
> ((a ^ b) & c) cmp d || a != b --> 0 cmp d || a != b
> (a ^ b) cmp c || a != b --> 0 cmp c || a != b
OK.
Thanks,
Richard.
> PR tree-optimization/114326
>
> gcc/ChangeLog:
>
> * match.pd: Add two patterns to fold a ^ b to 0, when a == b.
>
> gcc/testsuite/ChangeLog:
>
> * gcc.dg/tree-ssa/fold-xor-and-or.c: New test.
> * gcc.dg/tree-ssa/fold-xor-or.c: New test.
>
> Tested-by: Christoph Müllner <christoph.muellner@vrull.eu>
> Signed-off-by: Philipp Tomsich <philipp.tomsich@vrull.eu>
> Signed-off-by: Konstantinos Eleftheriou <konstantinos.eleftheriou@vrull.eu>
> ---
> gcc/match.pd | 32 ++++++++++-
> .../gcc.dg/tree-ssa/fold-xor-and-or.c | 55 +++++++++++++++++++
> gcc/testsuite/gcc.dg/tree-ssa/fold-xor-or.c | 55 +++++++++++++++++++
> 3 files changed, 141 insertions(+), 1 deletion(-)
> create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/fold-xor-and-or.c
> create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/fold-xor-or.c
>
> diff --git a/gcc/match.pd b/gcc/match.pd
> index 4aa610e2270..3c4f9b5f774 100644
> --- a/gcc/match.pd
> +++ b/gcc/match.pd
> @@ -3761,6 +3761,36 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> (if (types_match (type, TREE_TYPE (@0)))
> (bit_xor @0 { build_one_cst (type); } ))))))
>
> +/* ((a ^ b) & c) cmp d || a != b --> (0 cmp d || a != b). */
> +(for cmp (simple_comparison)
> + (simplify
> + (bit_ior
> + (cmp:c
> + (bit_and:c
> + (bit_xor:c @0 @1)
> + tree_expr_nonzero_p@2)
> + @3)
> + (ne:c@4 @0 @1))
> + (bit_ior
> + (cmp
> + { build_zero_cst (TREE_TYPE (@0)); }
> + @3)
> + @4)))
> +
> +/* (a ^ b) cmp c || a != b --> (0 cmp c || a != b). */
> +(for cmp (simple_comparison)
> + (simplify
> + (bit_ior
> + (cmp:c
> + (bit_xor:c @0 @1)
> + @2)
> + (ne:c@3 @0 @1))
> + (bit_ior
> + (cmp
> + { build_zero_cst (TREE_TYPE (@0)); }
> + @2)
> + @3)))
> +
> /* We can't reassociate at all for saturating types. */
> (if (!TYPE_SATURATING (type))
>
> @@ -10763,4 +10793,4 @@ and,
> }
> }
> (if (full_perm_p)
> - (vec_perm (op@3 @0 @1) @3 @2))))))
> + (vec_perm (op@3 @0 @1) @3 @2))))))
Spurious whitespace change?
> \ No newline at end of file
> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/fold-xor-and-or.c b/gcc/testsuite/gcc.dg/tree-ssa/fold-xor-and-or.c
> new file mode 100644
> index 00000000000..e5dc98e7541
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/fold-xor-and-or.c
> @@ -0,0 +1,55 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -fdump-tree-optimized" } */
> +
> +typedef unsigned long int uint64_t;
> +
> +int cmp1(int d1, int d2) {
> + if (((d1 ^ d2) & 0xabcd) == 0 || d1 != d2)
> + return 0;
> + return 1;
> +}
> +
> +int cmp2(int d1, int d2) {
> + if (d1 != d2 || ((d1 ^ d2) & 0xabcd) == 0)
> + return 0;
> + return 1;
> +}
> +
> +int cmp3(int d1, int d2) {
> + if (10 > (0xabcd & (d2 ^ d1)) || d2 != d1)
> + return 0;
> + return 1;
> +}
> +
> +int cmp4(int d1, int d2) {
> + if (d2 != d1 || 10 > (0xabcd & (d2 ^ d1)))
> + return 0;
> + return 1;
> +}
> +
> +int cmp1_64(uint64_t d1, uint64_t d2) {
> + if (((d1 ^ d2) & 0xabcd) == 0 || d1 != d2)
> + return 0;
> + return 1;
> +}
> +
> +int cmp2_64(uint64_t d1, uint64_t d2) {
> + if (d1 != d2 || ((d1 ^ d2) & 0xabcd) == 0)
> + return 0;
> + return 1;
> +}
> +
> +int cmp3_64(uint64_t d1, uint64_t d2) {
> + if (10 > (0xabcd & (d2 ^ d1)) || d2 != d1)
> + return 0;
> + return 1;
> +}
> +
> +int cmp4_64(uint64_t d1, uint64_t d2) {
> + if (d2 != d1 || 10 > (0xabcd & (d2 ^ d1)))
> + return 0;
> + return 1;
> +}
> +
> +/* The if should be removed, so the condition should not exist */
> +/* { dg-final { scan-tree-dump-not "d1_\[0-9\]+.D. \\^ d2_\[0-9\]+.D." "optimized" } } */
> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/fold-xor-or.c b/gcc/testsuite/gcc.dg/tree-ssa/fold-xor-or.c
> new file mode 100644
> index 00000000000..c55cfbcc84c
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/fold-xor-or.c
> @@ -0,0 +1,55 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -fdump-tree-optimized" } */
> +
> +typedef unsigned long int uint64_t;
> +
> +int cmp1(int d1, int d2) {
> + if ((d1 ^ d2) == 0xabcd || d1 != d2)
> + return 0;
> + return 1;
> +}
> +
> +int cmp2(int d1, int d2) {
> + if (d1 != d2 || (d1 ^ d2) == 0xabcd)
> + return 0;
> + return 1;
> +}
> +
> +int cmp3(int d1, int d2) {
> + if (0xabcd > (d2 ^ d1) || d2 != d1)
> + return 0;
> + return 1;
> +}
> +
> +int cmp4(int d1, int d2) {
> + if (d2 != d1 || 0xabcd > (d2 ^ d1))
> + return 0;
> + return 1;
> +}
> +
> +int cmp1_64(uint64_t d1, uint64_t d2) {
> + if ((d1 ^ d2) == 0xabcd || d1 != d2)
> + return 0;
> + return 1;
> +}
> +
> +int cmp2_64(uint64_t d1, uint64_t d2) {
> + if (d1 != d2 || (d1 ^ d2) == 0xabcd)
> + return 0;
> + return 1;
> +}
> +
> +int cmp3_64(uint64_t d1, uint64_t d2) {
> + if (0xabcd > (d2 ^ d1) || d2 != d1)
> + return 0;
> + return 1;
> +}
> +
> +int cmp4_64(uint64_t d1, uint64_t d2) {
> + if (d2 != d1 || 0xabcd > (d2 ^ d1))
> + return 0;
> + return 1;
> +}
> +
> +/* The if should be removed, so the condition should not exist */
> +/* { dg-final { scan-tree-dump-not "d1_\[0-9\]+.D. \\^ d2_\[0-9\]+.D." "optimized" } } */
> --
> 2.46.0
>
Applied to master with a fixup for the spurious
whitespace-change/removal of newline (at the end of the file), thanks!
--Philipp.
On Wed, 25 Sept 2024 at 15:02, Richard Biener
<richard.guenther@gmail.com> wrote:
>
> On Thu, Sep 19, 2024 at 2:18 PM Konstantinos Eleftheriou
> <konstantinos.eleftheriou@vrull.eu> wrote:
> >
> > From: kelefth <konstantinos.eleftheriou@vrull.eu>
> >
> > In expressions like (a != b || ((a ^ b) & c) == d) and
> > (a != b || (a ^ b) == c), (a ^ b) is folded to false.
> > In the equivalent expressions (((a ^ b) & c) == d || a != b) and
> > ((a ^ b) == c || a != b) this is not happening.
> >
> > This patch adds the following simplifications in match.pd:
> > ((a ^ b) & c) cmp d || a != b --> 0 cmp d || a != b
> > (a ^ b) cmp c || a != b --> 0 cmp c || a != b
>
> OK.
>
> Thanks,
> Richard.
>
> > PR tree-optimization/114326
> >
> > gcc/ChangeLog:
> >
> > * match.pd: Add two patterns to fold a ^ b to 0, when a == b.
> >
> > gcc/testsuite/ChangeLog:
> >
> > * gcc.dg/tree-ssa/fold-xor-and-or.c: New test.
> > * gcc.dg/tree-ssa/fold-xor-or.c: New test.
> >
> > Tested-by: Christoph Müllner <christoph.muellner@vrull.eu>
> > Signed-off-by: Philipp Tomsich <philipp.tomsich@vrull.eu>
> > Signed-off-by: Konstantinos Eleftheriou <konstantinos.eleftheriou@vrull.eu>
> > ---
> > gcc/match.pd | 32 ++++++++++-
> > .../gcc.dg/tree-ssa/fold-xor-and-or.c | 55 +++++++++++++++++++
> > gcc/testsuite/gcc.dg/tree-ssa/fold-xor-or.c | 55 +++++++++++++++++++
> > 3 files changed, 141 insertions(+), 1 deletion(-)
> > create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/fold-xor-and-or.c
> > create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/fold-xor-or.c
> >
> > diff --git a/gcc/match.pd b/gcc/match.pd
> > index 4aa610e2270..3c4f9b5f774 100644
> > --- a/gcc/match.pd
> > +++ b/gcc/match.pd
> > @@ -3761,6 +3761,36 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
> > (if (types_match (type, TREE_TYPE (@0)))
> > (bit_xor @0 { build_one_cst (type); } ))))))
> >
> > +/* ((a ^ b) & c) cmp d || a != b --> (0 cmp d || a != b). */
> > +(for cmp (simple_comparison)
> > + (simplify
> > + (bit_ior
> > + (cmp:c
> > + (bit_and:c
> > + (bit_xor:c @0 @1)
> > + tree_expr_nonzero_p@2)
> > + @3)
> > + (ne:c@4 @0 @1))
> > + (bit_ior
> > + (cmp
> > + { build_zero_cst (TREE_TYPE (@0)); }
> > + @3)
> > + @4)))
> > +
> > +/* (a ^ b) cmp c || a != b --> (0 cmp c || a != b). */
> > +(for cmp (simple_comparison)
> > + (simplify
> > + (bit_ior
> > + (cmp:c
> > + (bit_xor:c @0 @1)
> > + @2)
> > + (ne:c@3 @0 @1))
> > + (bit_ior
> > + (cmp
> > + { build_zero_cst (TREE_TYPE (@0)); }
> > + @2)
> > + @3)))
> > +
> > /* We can't reassociate at all for saturating types. */
> > (if (!TYPE_SATURATING (type))
> >
> > @@ -10763,4 +10793,4 @@ and,
> > }
> > }
> > (if (full_perm_p)
> > - (vec_perm (op@3 @0 @1) @3 @2))))))
> > + (vec_perm (op@3 @0 @1) @3 @2))))))
>
> Spurious whitespace change?
>
> > \ No newline at end of file
> > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/fold-xor-and-or.c b/gcc/testsuite/gcc.dg/tree-ssa/fold-xor-and-or.c
> > new file mode 100644
> > index 00000000000..e5dc98e7541
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/tree-ssa/fold-xor-and-or.c
> > @@ -0,0 +1,55 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -fdump-tree-optimized" } */
> > +
> > +typedef unsigned long int uint64_t;
> > +
> > +int cmp1(int d1, int d2) {
> > + if (((d1 ^ d2) & 0xabcd) == 0 || d1 != d2)
> > + return 0;
> > + return 1;
> > +}
> > +
> > +int cmp2(int d1, int d2) {
> > + if (d1 != d2 || ((d1 ^ d2) & 0xabcd) == 0)
> > + return 0;
> > + return 1;
> > +}
> > +
> > +int cmp3(int d1, int d2) {
> > + if (10 > (0xabcd & (d2 ^ d1)) || d2 != d1)
> > + return 0;
> > + return 1;
> > +}
> > +
> > +int cmp4(int d1, int d2) {
> > + if (d2 != d1 || 10 > (0xabcd & (d2 ^ d1)))
> > + return 0;
> > + return 1;
> > +}
> > +
> > +int cmp1_64(uint64_t d1, uint64_t d2) {
> > + if (((d1 ^ d2) & 0xabcd) == 0 || d1 != d2)
> > + return 0;
> > + return 1;
> > +}
> > +
> > +int cmp2_64(uint64_t d1, uint64_t d2) {
> > + if (d1 != d2 || ((d1 ^ d2) & 0xabcd) == 0)
> > + return 0;
> > + return 1;
> > +}
> > +
> > +int cmp3_64(uint64_t d1, uint64_t d2) {
> > + if (10 > (0xabcd & (d2 ^ d1)) || d2 != d1)
> > + return 0;
> > + return 1;
> > +}
> > +
> > +int cmp4_64(uint64_t d1, uint64_t d2) {
> > + if (d2 != d1 || 10 > (0xabcd & (d2 ^ d1)))
> > + return 0;
> > + return 1;
> > +}
> > +
> > +/* The if should be removed, so the condition should not exist */
> > +/* { dg-final { scan-tree-dump-not "d1_\[0-9\]+.D. \\^ d2_\[0-9\]+.D." "optimized" } } */
> > diff --git a/gcc/testsuite/gcc.dg/tree-ssa/fold-xor-or.c b/gcc/testsuite/gcc.dg/tree-ssa/fold-xor-or.c
> > new file mode 100644
> > index 00000000000..c55cfbcc84c
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/tree-ssa/fold-xor-or.c
> > @@ -0,0 +1,55 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-O3 -fdump-tree-optimized" } */
> > +
> > +typedef unsigned long int uint64_t;
> > +
> > +int cmp1(int d1, int d2) {
> > + if ((d1 ^ d2) == 0xabcd || d1 != d2)
> > + return 0;
> > + return 1;
> > +}
> > +
> > +int cmp2(int d1, int d2) {
> > + if (d1 != d2 || (d1 ^ d2) == 0xabcd)
> > + return 0;
> > + return 1;
> > +}
> > +
> > +int cmp3(int d1, int d2) {
> > + if (0xabcd > (d2 ^ d1) || d2 != d1)
> > + return 0;
> > + return 1;
> > +}
> > +
> > +int cmp4(int d1, int d2) {
> > + if (d2 != d1 || 0xabcd > (d2 ^ d1))
> > + return 0;
> > + return 1;
> > +}
> > +
> > +int cmp1_64(uint64_t d1, uint64_t d2) {
> > + if ((d1 ^ d2) == 0xabcd || d1 != d2)
> > + return 0;
> > + return 1;
> > +}
> > +
> > +int cmp2_64(uint64_t d1, uint64_t d2) {
> > + if (d1 != d2 || (d1 ^ d2) == 0xabcd)
> > + return 0;
> > + return 1;
> > +}
> > +
> > +int cmp3_64(uint64_t d1, uint64_t d2) {
> > + if (0xabcd > (d2 ^ d1) || d2 != d1)
> > + return 0;
> > + return 1;
> > +}
> > +
> > +int cmp4_64(uint64_t d1, uint64_t d2) {
> > + if (d2 != d1 || 0xabcd > (d2 ^ d1))
> > + return 0;
> > + return 1;
> > +}
> > +
> > +/* The if should be removed, so the condition should not exist */
> > +/* { dg-final { scan-tree-dump-not "d1_\[0-9\]+.D. \\^ d2_\[0-9\]+.D." "optimized" } } */
> > --
> > 2.46.0
> >
@@ -3761,6 +3761,36 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(if (types_match (type, TREE_TYPE (@0)))
(bit_xor @0 { build_one_cst (type); } ))))))
+/* ((a ^ b) & c) cmp d || a != b --> (0 cmp d || a != b). */
+(for cmp (simple_comparison)
+ (simplify
+ (bit_ior
+ (cmp:c
+ (bit_and:c
+ (bit_xor:c @0 @1)
+ tree_expr_nonzero_p@2)
+ @3)
+ (ne:c@4 @0 @1))
+ (bit_ior
+ (cmp
+ { build_zero_cst (TREE_TYPE (@0)); }
+ @3)
+ @4)))
+
+/* (a ^ b) cmp c || a != b --> (0 cmp c || a != b). */
+(for cmp (simple_comparison)
+ (simplify
+ (bit_ior
+ (cmp:c
+ (bit_xor:c @0 @1)
+ @2)
+ (ne:c@3 @0 @1))
+ (bit_ior
+ (cmp
+ { build_zero_cst (TREE_TYPE (@0)); }
+ @2)
+ @3)))
+
/* We can't reassociate at all for saturating types. */
(if (!TYPE_SATURATING (type))
@@ -10763,4 +10793,4 @@ and,
}
}
(if (full_perm_p)
- (vec_perm (op@3 @0 @1) @3 @2))))))
+ (vec_perm (op@3 @0 @1) @3 @2))))))
\ No newline at end of file
new file mode 100644
@@ -0,0 +1,55 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fdump-tree-optimized" } */
+
+typedef unsigned long int uint64_t;
+
+int cmp1(int d1, int d2) {
+ if (((d1 ^ d2) & 0xabcd) == 0 || d1 != d2)
+ return 0;
+ return 1;
+}
+
+int cmp2(int d1, int d2) {
+ if (d1 != d2 || ((d1 ^ d2) & 0xabcd) == 0)
+ return 0;
+ return 1;
+}
+
+int cmp3(int d1, int d2) {
+ if (10 > (0xabcd & (d2 ^ d1)) || d2 != d1)
+ return 0;
+ return 1;
+}
+
+int cmp4(int d1, int d2) {
+ if (d2 != d1 || 10 > (0xabcd & (d2 ^ d1)))
+ return 0;
+ return 1;
+}
+
+int cmp1_64(uint64_t d1, uint64_t d2) {
+ if (((d1 ^ d2) & 0xabcd) == 0 || d1 != d2)
+ return 0;
+ return 1;
+}
+
+int cmp2_64(uint64_t d1, uint64_t d2) {
+ if (d1 != d2 || ((d1 ^ d2) & 0xabcd) == 0)
+ return 0;
+ return 1;
+}
+
+int cmp3_64(uint64_t d1, uint64_t d2) {
+ if (10 > (0xabcd & (d2 ^ d1)) || d2 != d1)
+ return 0;
+ return 1;
+}
+
+int cmp4_64(uint64_t d1, uint64_t d2) {
+ if (d2 != d1 || 10 > (0xabcd & (d2 ^ d1)))
+ return 0;
+ return 1;
+}
+
+/* The if should be removed, so the condition should not exist */
+/* { dg-final { scan-tree-dump-not "d1_\[0-9\]+.D. \\^ d2_\[0-9\]+.D." "optimized" } } */
new file mode 100644
@@ -0,0 +1,55 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fdump-tree-optimized" } */
+
+typedef unsigned long int uint64_t;
+
+int cmp1(int d1, int d2) {
+ if ((d1 ^ d2) == 0xabcd || d1 != d2)
+ return 0;
+ return 1;
+}
+
+int cmp2(int d1, int d2) {
+ if (d1 != d2 || (d1 ^ d2) == 0xabcd)
+ return 0;
+ return 1;
+}
+
+int cmp3(int d1, int d2) {
+ if (0xabcd > (d2 ^ d1) || d2 != d1)
+ return 0;
+ return 1;
+}
+
+int cmp4(int d1, int d2) {
+ if (d2 != d1 || 0xabcd > (d2 ^ d1))
+ return 0;
+ return 1;
+}
+
+int cmp1_64(uint64_t d1, uint64_t d2) {
+ if ((d1 ^ d2) == 0xabcd || d1 != d2)
+ return 0;
+ return 1;
+}
+
+int cmp2_64(uint64_t d1, uint64_t d2) {
+ if (d1 != d2 || (d1 ^ d2) == 0xabcd)
+ return 0;
+ return 1;
+}
+
+int cmp3_64(uint64_t d1, uint64_t d2) {
+ if (0xabcd > (d2 ^ d1) || d2 != d1)
+ return 0;
+ return 1;
+}
+
+int cmp4_64(uint64_t d1, uint64_t d2) {
+ if (d2 != d1 || 0xabcd > (d2 ^ d1))
+ return 0;
+ return 1;
+}
+
+/* The if should be removed, so the condition should not exist */
+/* { dg-final { scan-tree-dump-not "d1_\[0-9\]+.D. \\^ d2_\[0-9\]+.D." "optimized" } } */