diff options
author | Konstantinos Eleftheriou <konstantinos.eleftheriou@vrull.eu> | 2024-08-07 17:54:30 +0200 |
---|---|---|
committer | Philipp Tomsich <philipp.tomsich@vrull.eu> | 2024-09-25 16:25:26 +0200 |
commit | a88d6c6d777ad7c9235e2e620318f26e5347e50a (patch) | |
tree | 8c606b0cce462459c9095d0c768a89ab5ee16d76 /gcc | |
parent | 0e095df4b4c61bc57413cf3cbca56ff1a038de40 (diff) | |
download | gcc-a88d6c6d777ad7c9235e2e620318f26e5347e50a.zip gcc-a88d6c6d777ad7c9235e2e620318f26e5347e50a.tar.gz gcc-a88d6c6d777ad7c9235e2e620318f26e5347e50a.tar.bz2 |
match: Fix A || B not optimized to true when !B implies A [PR114326]
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>
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/match.pd | 30 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/fold-xor-and-or.c | 55 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/fold-xor-or.c | 55 |
3 files changed, 140 insertions, 0 deletions
diff --git a/gcc/match.pd b/gcc/match.pd index 7150b8e..d10ac7d 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -3787,6 +3787,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)) 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 0000000..e5dc98e --- /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 0000000..c55cfbc --- /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" } } */ |