Skip to content
Snippets Groups Projects
Commit a88d6c6d authored by Konstantinos Eleftheriou's avatar Konstantinos Eleftheriou Committed by Philipp Tomsich
Browse files

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: default avatarChristoph Müllner <christoph.muellner@vrull.eu>
Signed-off-by: default avatarPhilipp Tomsich <philipp.tomsich@vrull.eu>
Signed-off-by: default avatarKonstantinos Eleftheriou <konstantinos.eleftheriou@vrull.eu>
parent 0e095df4
No related branches found
No related tags found
No related merge requests found
......@@ -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))
......
/* { 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" } } */
/* { 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" } } */
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment