(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)
+/* ((a ^ b) & c) cmp d && a == b --> (0 cmp d && a == b). */
+(for bitop (bit_ior bit_and)
+ neeq (ne eq)
+ (for cmp (simple_comparison)
(simplify
- (bit_ior
+ (bitop:c
(cmp:c
(bit_and:c
- (bit_xor:c @0 @1)
+ (bit_xor @0 @1)
tree_expr_nonzero_p@2)
@3)
- (ne@4 @0 @1))
- (bit_ior
+ (neeq@4 @0 @1))
+ (bitop
(cmp
{ build_zero_cst (TREE_TYPE (@0)); }
@3)
- @4)))
-
+ @4))
/* (a ^ b) cmp c || a != b --> (0 cmp c || a != b). */
-(for cmp (simple_comparison)
+/* (a ^ b) cmp c && a == b --> (0 cmp c || a == b). */
(simplify
- (bit_ior
+ (bitop:c
(cmp:c
- (bit_xor:c @0 @1)
+ (bit_xor @0 @1)
@2)
- (ne@3 @0 @1))
- (bit_ior
+ (neeq@3 @0 @1))
+ (bitop
(cmp
- { build_zero_cst (TREE_TYPE (@0)); }
- @2)
- @3)))
+ { build_zero_cst (TREE_TYPE (@0)); } @2)
+ @3))))
/* We can't reassociate at all for saturating types. */
(if (!TYPE_SATURATING (type))
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O3 -fdump-tree-optimized --param logical-op-non-short-circuit=0" } */
+
+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" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O3 -fdump-tree-optimized --param logical-op-non-short-circuit=0" } */
+
+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" } } */
/* { dg-do compile } */
-/* { dg-options "-O3 -fdump-tree-pre --param logical-op-non-short-circuit=1" } */
+/* { dg-options "-O3 -fdump-tree-pre -fdump-tree-optimized --param logical-op-non-short-circuit=1" } */
typedef __UINT64_TYPE__ uint64_t;
return 0;
}
-/* Check for condition assignments for noccmp0 and noccmp1. */
-/* { dg-final { scan-tree-dump-times {_\d+ = d\d+_\d+ != d\d+_\d+;\n _\d+ = bar_\d+ == 0;} 2 "pre" } } */
+/* Check for condition assignments for noccmp1 and noccmp0. */
+/* { dg-final { scan-tree-dump-times {_\d+ = d\d+_\d+ != d\d+_\d+;\n _\d+ = bar_\d+ == 0;} 1 "pre" } } */
+/* { dg-final { scan-tree-dump-times "optimizing two comparisons " 2 "pre" } } */
+/* The conditional in noccmp1 should be optimized in pre */
+/* { dg-final { scan-tree-dump-times " if " 1 "pre" } } */
+/* { dg-final { scan-tree-dump-times " if " 1 "optimized" } } */