On Thu, Aug 29, 2024 at 9:03 AM <[email protected]> wrote:
>
> From: kelefth <[email protected]>
>
> 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) == d || a != b --> 0 == d || a != b
> (a ^ b) == c || a != b --> 0 == 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.
>
> Reviewed-by: Christoph Müllner <[email protected]>
> Signed-off-by: Philipp Tomsich <[email protected]>
> Signed-off-by: Konstantinos Eleftheriou <[email protected]>
> ---
> gcc/match.pd | 30 ++++++++++++++++++
> .../gcc.dg/tree-ssa/fold-xor-and-or.c | 31 +++++++++++++++++++
> gcc/testsuite/gcc.dg/tree-ssa/fold-xor-or.c | 31 +++++++++++++++++++
> 3 files changed, 92 insertions(+)
> 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 be211535a49..6bab3cfbde1 100644
> --- a/gcc/match.pd
> +++ b/gcc/match.pd
> @@ -10727,3 +10727,33 @@ and,
> }
> (if (full_perm_p)
> (vec_perm (op@3 @0 @1) @3 @2))))))
Can you please place those patterns next to related ones? I suggest
after (type)([0,1]@a != 0) -> (type)a and before
/* We can't reassociate at all for saturating types. */
> +/* ((a ^ b) & c) == d || a != b --> (0 == d || a != b). */
The comment indicates == d but you also test for other
comparison ops. As far as I can see your testcases also
only cover ==.
> +(for cmp (simple_comparison)
> + (simplify
> + (bit_ior
> + (cmp
> + (bit_and
This needs :c
> + (bit_xor @0 @1)
Likewise.
I think you also need :c on the comparison to match
d == (...).
> + tree_expr_nonzero_p@2)
> + @3)
> + (ne@4 @0 @1))
> + (bit_ior
> + (cmp
> + { build_zero_cst (TREE_TYPE (@0)); }
> + @3)
> + @4)))
> +
> +/* (a ^ b) == c || a != b --> (0 == c || a != b). */
> +(for cmp (simple_comparison)
> + (simplify
> + (bit_ior
> + (cmp
> + (bit_xor @0 @1)
similar, :c here and also on the comparison. Same
question with regard to == c.
> + @2)
> + (ne@3 @0 @1))
> + (bit_ior
> + (cmp
> + { build_zero_cst (TREE_TYPE (@0)); }
> + @2)
> + @3)))
> \ 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..ec327e62f6e
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/fold-xor-and-or.c
> @@ -0,0 +1,31 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -fdump-tree-optimized" } */
> +
> +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;
> +}
> +
> +typedef unsigned long int uint64_t;
> +
> +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;
> +}
> +
> +/* 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..f5fce847394
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/fold-xor-or.c
> @@ -0,0 +1,31 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O3 -fdump-tree-optimized" } */
> +
> +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;
> +}
> +
> +typedef unsigned long int uint64_t;
> +
> +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;
> +}
> +
> +/* 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
>